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 + +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 #include #include -#include #include #include #include @@ -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 and linux-wireless list + 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 #include #include -#include +#include #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 + * Original Authors: Daniel Drake + * Duane Griffin + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 "); +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 /* 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); +static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo *arg); +static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg); +static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file); +static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, void *file); +static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg, void *file); +static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *file); +static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file); +static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file); +static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file); +static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd, void *file); -extern void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s); -static int do_cancel(comedi_device *dev, comedi_subdevice *s); +extern void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s); +static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static int comedi_fasync(int fd, struct file *file, int on); -static int is_device_busy(comedi_device *dev); +static int is_device_busy(struct comedi_device *dev); #ifdef HAVE_UNLOCKED_IOCTL static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, @@ -98,9 +104,13 @@ static int comedi_ioctl(struct inode *inode, struct file *file, const unsigned minor = iminor(file->f_dentry->d_inode); struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(minor); - comedi_device *dev = dev_file_info->device; + struct comedi_device *dev; int rc; + if (dev_file_info == NULL || dev_file_info->device == NULL) + return -ENODEV; + dev = dev_file_info->device; + mutex_lock(&dev->mutex); /* Device config is special, because it must work on @@ -182,9 +192,9 @@ 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 #include #include #include @@ -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 #include -#include #include #include #include @@ -36,7 +35,6 @@ #include #include #include -#include #include "interrupt.h" #include #include @@ -55,9 +53,9 @@ #define COMEDI_INITCLEANUP_NOMODULE(x) \ static int __init x ## _init_module(void) \ - {return comedi_driver_register(&(x));} \ + {return comedi_driver_register(&(x)); } \ static void __exit x ## _cleanup_module(void) \ - {comedi_driver_unregister(&(x));} \ + {comedi_driver_unregister(&(x)); } \ module_init(x ## _init_module); \ module_exit(x ## _cleanup_module); \ @@ -120,23 +118,14 @@ #define PCI_VENDOR_ID_MEILHAUS 0x1402 #define COMEDI_NUM_MINORS 0x100 -#define COMEDI_NUM_LEGACY_MINORS 0x10 #define COMEDI_NUM_BOARD_MINORS 0x30 #define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS -typedef struct comedi_device_struct comedi_device; -typedef struct comedi_subdevice_struct comedi_subdevice; -typedef struct comedi_async_struct comedi_async; -typedef struct comedi_driver_struct comedi_driver; -typedef struct comedi_lrange_struct comedi_lrange; - -typedef struct device device_create_result_type; - #define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \ device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt) -struct comedi_subdevice_struct { - comedi_device *device; +struct comedi_subdevice { + struct comedi_device *device; int type; int n_chan; volatile int subdev_flags; @@ -144,7 +133,7 @@ struct comedi_subdevice_struct { void *private; - comedi_async *async; + struct comedi_async *async; void *lock; void *busy; @@ -153,46 +142,46 @@ struct comedi_subdevice_struct { int io_bits; - lsampl_t maxdata; /* if maxdata==0, use list */ - const lsampl_t *maxdata_list; /* list is channel specific */ + unsigned int maxdata; /* if maxdata==0, use list */ + const unsigned int *maxdata_list; /* list is channel specific */ unsigned int flags; const unsigned int *flaglist; unsigned int settling_time_0; - const comedi_lrange *range_table; - const comedi_lrange *const *range_table_list; + const struct comedi_lrange *range_table; + const struct comedi_lrange *const *range_table_list; unsigned int *chanlist; /* driver-owned chanlist (not used) */ - int (*insn_read) (comedi_device *, comedi_subdevice *, comedi_insn *, - lsampl_t *); - int (*insn_write) (comedi_device *, comedi_subdevice *, comedi_insn *, - lsampl_t *); - int (*insn_bits) (comedi_device *, comedi_subdevice *, comedi_insn *, - lsampl_t *); - int (*insn_config) (comedi_device *, comedi_subdevice *, comedi_insn *, - lsampl_t *); + int (*insn_read) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + int (*insn_write) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + int (*insn_bits) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + int (*insn_config) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); - int (*do_cmd) (comedi_device *, comedi_subdevice *); - int (*do_cmdtest) (comedi_device *, comedi_subdevice *, comedi_cmd *); - int (*poll) (comedi_device *, comedi_subdevice *); - int (*cancel) (comedi_device *, comedi_subdevice *); - /* int (*do_lock)(comedi_device *,comedi_subdevice *); */ - /* int (*do_unlock)(comedi_device *,comedi_subdevice *); */ + int (*do_cmd) (struct comedi_device *, struct comedi_subdevice *); + int (*do_cmdtest) (struct comedi_device *, struct comedi_subdevice *, struct comedi_cmd *); + int (*poll) (struct comedi_device *, struct comedi_subdevice *); + int (*cancel) (struct comedi_device *, struct comedi_subdevice *); + /* int (*do_lock)(struct comedi_device *,struct comedi_subdevice *); */ + /* int (*do_unlock)(struct comedi_device *,struct comedi_subdevice *); */ /* called when the buffer changes */ - int (*buf_change) (comedi_device *dev, comedi_subdevice *s, + int (*buf_change) (struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); - void (*munge) (comedi_device *dev, comedi_subdevice *s, void *data, + void (*munge) (struct comedi_device *dev, struct comedi_subdevice *s, void *data, unsigned int num_bytes, unsigned int start_chan_index); enum dma_data_direction async_dma_dir; unsigned int state; - device_create_result_type *class_dev; + struct device *class_dev; int minor; }; @@ -201,8 +190,8 @@ struct comedi_buf_page { dma_addr_t dma_addr; }; -struct comedi_async_struct { - comedi_subdevice *subdevice; +struct comedi_async { + struct comedi_subdevice *subdevice; void *prealloc_buf; /* pre-allocated buffer */ unsigned int prealloc_bufsz; /* buffer size, in bytes */ @@ -232,7 +221,7 @@ struct comedi_async_struct { unsigned int events; /* events that have occurred */ - comedi_cmd cmd; + struct comedi_cmd cmd; wait_queue_head_t wait_head; @@ -241,17 +230,17 @@ struct comedi_async_struct { int (*cb_func) (unsigned int flags, void *); void *cb_arg; - int (*inttrig) (comedi_device *dev, comedi_subdevice *s, + int (*inttrig) (struct comedi_device *dev, struct comedi_subdevice *s, unsigned int x); }; -struct comedi_driver_struct { - struct comedi_driver_struct *next; +struct comedi_driver { + struct comedi_driver *next; const char *driver_name; struct module *module; - int (*attach) (comedi_device *, comedi_devconfig *); - int (*detach) (comedi_device *); + int (*attach) (struct comedi_device *, struct comedi_devconfig *); + int (*detach) (struct comedi_device *); /* number of elements in board_name and board_id arrays */ unsigned int num_names; @@ -260,12 +249,12 @@ struct comedi_driver_struct { int offset; }; -struct comedi_device_struct { +struct comedi_device { int use_count; - comedi_driver *driver; + struct comedi_driver *driver; void *private; - device_create_result_type *class_dev; + struct device *class_dev; int minor; /* hw_dev is passed to dma_alloc_coherent when allocating async buffers * for subdevices that have async_dma_dir set to something other than @@ -281,25 +270,25 @@ struct comedi_device_struct { int in_request_module; int n_subdevices; - comedi_subdevice *subdevices; + struct comedi_subdevice *subdevices; /* dumb */ unsigned long iobase; unsigned int irq; - comedi_subdevice *read_subdev; - comedi_subdevice *write_subdev; + struct comedi_subdevice *read_subdev; + struct comedi_subdevice *write_subdev; struct fasync_struct *async_queue; - void (*open) (comedi_device *dev); - void (*close) (comedi_device *dev); + void (*open) (struct comedi_device *dev); + void (*close) (struct comedi_device *dev); }; struct comedi_device_file_info { - comedi_device *device; - comedi_subdevice *read_subdevice; - comedi_subdevice *write_subdevice; + struct comedi_device *device; + struct comedi_subdevice *read_subdevice; + struct comedi_subdevice *write_subdevice; }; #ifdef CONFIG_COMEDI_DEBUG @@ -312,8 +301,8 @@ static const int comedi_debug; * function prototypes */ -void comedi_event(comedi_device *dev, comedi_subdevice *s); -void comedi_error(const comedi_device *dev, const char *s); +void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); +void comedi_error(const struct comedi_device *dev, const char *s); /* we can expand the number of bits used to encode devices/subdevices into the minor number soon, after more distros support > 8 bit minor numbers @@ -327,7 +316,7 @@ static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor); -static inline comedi_subdevice *comedi_get_read_subdevice( +static inline struct comedi_subdevice *comedi_get_read_subdevice( const struct comedi_device_file_info *info) { if (info->read_subdevice) @@ -337,7 +326,7 @@ static inline comedi_subdevice *comedi_get_read_subdevice( return info->device->read_subdev; } -static inline comedi_subdevice *comedi_get_write_subdevice( +static inline struct comedi_subdevice *comedi_get_write_subdevice( const struct comedi_device_file_info *info) { if (info->write_subdevice) @@ -347,17 +336,17 @@ static inline comedi_subdevice *comedi_get_write_subdevice( return info->device->write_subdev; } -void comedi_device_detach(comedi_device *dev); -int comedi_device_attach(comedi_device *dev, comedi_devconfig *it); -int comedi_driver_register(comedi_driver *); -int comedi_driver_unregister(comedi_driver *); +void comedi_device_detach(struct comedi_device *dev); +int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it); +int comedi_driver_register(struct comedi_driver *); +int comedi_driver_unregister(struct comedi_driver *); void init_polling(void); void cleanup_polling(void); -void start_polling(comedi_device *); -void stop_polling(comedi_device *); +void start_polling(struct comedi_device *); +void stop_polling(struct comedi_device *); -int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s, unsigned long +int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); #ifdef CONFIG_PROC_FS @@ -386,13 +375,13 @@ enum subdevice_runflags { various internal comedi functions */ -int do_rangeinfo_ioctl(comedi_device *dev, comedi_rangeinfo *arg); -int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist); -void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask, +int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg); +int check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist); +void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask, unsigned bits); -unsigned comedi_get_subdevice_runflags(comedi_subdevice *s); -int insn_inval(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data); +unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s); +int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); /* range stuff */ @@ -403,12 +392,12 @@ int insn_inval(comedi_device *dev, comedi_subdevice *s, #define BIP_RANGE(a) {-(a)*1e6, (a)*1e6, 0} #define UNI_RANGE(a) {0, (a)*1e6, 0} -extern const comedi_lrange range_bipolar10; -extern const comedi_lrange range_bipolar5; -extern const comedi_lrange range_bipolar2_5; -extern const comedi_lrange range_unipolar10; -extern const comedi_lrange range_unipolar5; -extern const comedi_lrange range_unknown; +extern const struct comedi_lrange range_bipolar10; +extern const struct comedi_lrange range_bipolar5; +extern const struct comedi_lrange range_bipolar2_5; +extern const struct comedi_lrange range_unipolar10; +extern const struct comedi_lrange range_unipolar5; +extern const struct comedi_lrange range_unknown; #define range_digital range_unipolar5 @@ -418,21 +407,21 @@ extern const comedi_lrange range_unknown; #define GCC_ZERO_LENGTH_ARRAY 0 #endif -struct comedi_lrange_struct { +struct comedi_lrange { int length; - comedi_krange range[GCC_ZERO_LENGTH_ARRAY]; + struct comedi_krange range[GCC_ZERO_LENGTH_ARRAY]; }; /* some silly little inline functions */ -static inline int alloc_subdevices(comedi_device *dev, +static inline int alloc_subdevices(struct comedi_device *dev, unsigned int num_subdevices) { unsigned i; dev->n_subdevices = num_subdevices; dev->subdevices = - kcalloc(num_subdevices, sizeof(comedi_subdevice), GFP_KERNEL); + kcalloc(num_subdevices, sizeof(struct comedi_subdevice), GFP_KERNEL); if (!dev->subdevices) return -ENOMEM; for (i = 0; i < num_subdevices; ++i) { @@ -444,7 +433,7 @@ static inline int alloc_subdevices(comedi_device *dev, return 0; } -static inline int alloc_private(comedi_device *dev, int size) +static inline int alloc_private(struct comedi_device *dev, int size) { dev->private = kzalloc(size, GFP_KERNEL); if (!dev->private) @@ -452,17 +441,17 @@ static inline int alloc_private(comedi_device *dev, int size) return 0; } -static inline unsigned int bytes_per_sample(const comedi_subdevice *subd) +static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd) { if (subd->subdev_flags & SDF_LSAMPL) - return sizeof(lsampl_t); + return sizeof(unsigned int); else - return sizeof(sampl_t); + return sizeof(short); } /* must be used in attach to set dev->hw_dev if you wish to dma directly into comedi's buffer */ -static inline void comedi_set_hw_dev(comedi_device *dev, struct device *hw_dev) +static inline void comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev) { if (dev->hw_dev) put_device(dev->hw_dev); @@ -474,31 +463,31 @@ static inline void comedi_set_hw_dev(comedi_device *dev, struct device *hw_dev) } } -int comedi_buf_put(comedi_async *async, sampl_t x); -int comedi_buf_get(comedi_async *async, sampl_t *x); +int comedi_buf_put(struct comedi_async *async, short x); +int comedi_buf_get(struct comedi_async *async, short *x); -unsigned int comedi_buf_write_n_available(comedi_async *async); -unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes); -unsigned int comedi_buf_write_alloc_strict(comedi_async *async, +unsigned int comedi_buf_write_n_available(struct comedi_async *async); +unsigned int comedi_buf_write_alloc(struct comedi_async *async, unsigned int nbytes); +unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async, unsigned int nbytes); -unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes); -unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes); -unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes); -unsigned int comedi_buf_read_n_available(comedi_async *async); -void comedi_buf_memcpy_to(comedi_async *async, unsigned int offset, +unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes); +unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes); +unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes); +unsigned int comedi_buf_read_n_available(struct comedi_async *async); +void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, const void *source, unsigned int num_bytes); -void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset, +void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, void *destination, unsigned int num_bytes); -static inline unsigned comedi_buf_write_n_allocated(comedi_async *async) +static inline unsigned comedi_buf_write_n_allocated(struct comedi_async *async) { return async->buf_write_alloc_count - async->buf_write_count; } -static inline unsigned comedi_buf_read_n_allocated(comedi_async *async) +static inline unsigned comedi_buf_read_n_allocated(struct comedi_async *async) { return async->buf_read_alloc_count - async->buf_read_count; } -void comedi_reset_async_buf(comedi_async *async); +void comedi_reset_async_buf(struct comedi_async *async); static inline void *comedi_aux_data(int options[], int n) { @@ -527,10 +516,13 @@ static inline void *comedi_aux_data(int options[], int n) int comedi_alloc_board_minor(struct device *hardware_device); void comedi_free_board_minor(unsigned minor); -int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s); -void comedi_free_subdevice_minor(comedi_subdevice *s); +int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdevice *s); +void comedi_free_subdevice_minor(struct comedi_subdevice *s); int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name); void comedi_pci_auto_unconfig(struct pci_dev *pcidev); +struct usb_device; /* forward declaration */ +int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name); +void comedi_usb_auto_unconfig(struct usb_device *usbdev); #include "comedi_rt.h" 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 #include #include +#include #include #include #include @@ -46,26 +47,26 @@ #include #include -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 + + 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 + + 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 + +#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 + + 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 + +#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) | + (b_SecondCounterModus & 0xA) | + (b_SecondCounterOption & 0x40); + + /***********************/ + /* Test if direct mode */ + /***********************/ + + if (b_FirstCounterModus == APCI1710_DIRECT_MODE) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 | + APCI1710_DIRECT_MODE; + } + } + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_CounterInit = 1; + } + } else { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_CounterAutoTest | +| (BYTE_ b_BoardHandle, | +| PBYTE_ pb_TestStatus) | ++----------------------------------------------------------------------------+ +| Task : A test mode is intended for testing the component and | +| the connected periphery. All the 8-bit counter chains | +| are operated internally as down counters. | +| Independently from the external signals, | +| all the four 8-bit counter chains are decremented in | +| parallel by each negative clock pulse edge of CLKX. | +| | +| Counter auto test conclusion | +| ---------------------------- | +| +-----------------+-----------------------------+ | +| | pb_TestStatus | Error description | | +| | mask | | | +| |-----------------+-----------------------------| | +| | 0000 | No error detected | | +| |-----------------|-----------------------------| | +| | 0001 | Error detected of counter 0 | | +| |-----------------|-----------------------------| | +| | 0010 | Error detected of counter 1 | | +| |-----------------|-----------------------------| | +| | 0100 | Error detected of counter 2 | | +| |-----------------|-----------------------------| | +| | 1000 | Error detected of counter 3 | | +| +-----------------+-----------------------------+ | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TestStatus : Auto test conclusion. See table| ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_CounterAutoTest(struct comedi_device * dev, PBYTE pb_TestStatus) +{ + BYTE b_ModulCpt = 0; + INT i_ReturnValue = 0; + DWORD dw_LathchValue; + + *pb_TestStatus = 0; + + /********************************/ + /* Test if counter module found */ + /********************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[0] & 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER + || (devpriv->s_BoardInfos. + dw_MolduleConfiguration[1] & 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER + || (devpriv->s_BoardInfos. + dw_MolduleConfiguration[2] & 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER + || (devpriv->s_BoardInfos. + dw_MolduleConfiguration[3] & 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER) { + for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) { + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulCpt] & + 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER) { + /******************/ + /* Start the test */ + /******************/ + + outl(3, devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulCpt)); + + /*********************/ + /* Tatch the counter */ + /*********************/ + + outl(1, devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulCpt)); + + /************************/ + /* Read the latch value */ + /************************/ + + dw_LathchValue = inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulCpt)); + + if ((dw_LathchValue & 0xFF) != + ((dw_LathchValue >> 8) & 0xFF) + && (dw_LathchValue & 0xFF) != + ((dw_LathchValue >> 16) & 0xFF) + && (dw_LathchValue & 0xFF) != + ((dw_LathchValue >> 24) & 0xFF)) { + *pb_TestStatus = + *pb_TestStatus | (1 << + b_ModulCpt); + } + + /*****************/ + /* Stop the test */ + /*****************/ + + outl(0, devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulCpt)); + } + } + } else { + /***************************/ + /* No counter module found */ + /***************************/ + + DPRINTK("No counter module found\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitIndex (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_ReferenceAction, | +| BYTE_ b_IndexOperation, | +| BYTE_ b_AutoMode, | +| BYTE_ b_InterruptEnable) | ++----------------------------------------------------------------------------+ +| Task : Initialise the index corresponding to the selected | +| module (b_ModulNbr). If a INDEX flag occur, you have | +| the possibility to clear the 32-Bit counter or to latch| +| the current 32-Bit value in to the first latch | +| register. The b_IndexOperation parameter give the | +| possibility to choice the INDEX action. | +| If you have enabled the automatic mode, each INDEX | +| action is cleared automatically, else you must read | +| the index status ("i_APCI1710_ReadIndexStatus") | +| after each INDEX action. | +| | +| | +| Index action | +| ------------ | +| | +| +------------------------+------------------------------------+ | +| | b_IndexOperation | Operation | | +| |------------------------+------------------------------------| | +| |APCI1710_LATCH_COUNTER | After a index signal, the counter | | +| | | value (32-Bit) is latched in to | | +| | | the first latch register | | +| |------------------------|------------------------------------| | +| |APCI1710_CLEAR_COUNTER | After a index signal, the counter | | +| | | value is cleared (32-Bit) | | +| +------------------------+------------------------------------+ | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_ReferenceAction : Determine if the reference | +| must set or no for the | +| acceptance from index | +| APCI1710_ENABLE : | +| Reference must be set for | +| accepted the index | +| APCI1710_DISABLE : | +| Reference have not | +| importance | +| BYTE_ b_IndexOperation : Index operating mode. | +| See table. | +| BYTE_ b_AutoMode : Enable or disable the | +| automatic index reset. | +| APCI1710_ENABLE : | +| Enable the automatic mode | +| APCI1710_DISABLE : | +| Disable the automatic mode | +| BYTE_ b_InterruptEnable : Enable or disable the | +| interrupt. | +| APCI1710_ENABLE : | +| Enable the interrupt | +| APCI1710_DISABLE : | +| Disable the interrupt | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4 The reference action parameter is wrong | +| -5: The index operating mode parameter is wrong | +| -6: The auto mode parameter is wrong | +| -7: Interrupt parameter is wrong | +| -8: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitIndex(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_ReferenceAction, + BYTE b_IndexOperation, BYTE b_AutoMode, BYTE b_InterruptEnable) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /********************************/ + /* Test the reference parameter */ + /********************************/ + + if (b_ReferenceAction == APCI1710_ENABLE || + b_ReferenceAction == APCI1710_DISABLE) { + /****************************/ + /* Test the index parameter */ + /****************************/ + + if (b_IndexOperation == + APCI1710_HIGH_EDGE_LATCH_COUNTER + || b_IndexOperation == + APCI1710_LOW_EDGE_LATCH_COUNTER + || b_IndexOperation == + APCI1710_HIGH_EDGE_CLEAR_COUNTER + || b_IndexOperation == + APCI1710_LOW_EDGE_CLEAR_COUNTER + || b_IndexOperation == + APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER + || b_IndexOperation == + APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + { + /********************************/ + /* Test the auto mode parameter */ + /********************************/ + + if (b_AutoMode == APCI1710_ENABLE || + b_AutoMode == APCI1710_DISABLE) + { + /***************************/ + /* Test the interrupt mode */ + /***************************/ + + if (b_InterruptEnable == + APCI1710_ENABLE + || b_InterruptEnable == + APCI1710_DISABLE) { + + /************************************/ + /* Makte the configuration commando */ + /************************************/ + + if (b_ReferenceAction == + APCI1710_ENABLE) + { + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + | + APCI1710_ENABLE_INDEX_ACTION; + } else { + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + & + APCI1710_DISABLE_INDEX_ACTION; + } + + /****************************************/ + /* Test if low level latch or/and clear */ + /****************************************/ + + if (b_IndexOperation == + APCI1710_LOW_EDGE_LATCH_COUNTER + || + b_IndexOperation + == + APCI1710_LOW_EDGE_CLEAR_COUNTER + || + b_IndexOperation + == + APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + { + /*************************************/ + /* Set the index level to low (DQ26) */ + /*************************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + | + APCI1710_SET_LOW_INDEX_LEVEL; + } else { + /**************************************/ + /* Set the index level to high (DQ26) */ + /**************************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + & + APCI1710_SET_HIGH_INDEX_LEVEL; + } + + /***********************************/ + /* Test if latch and clear counter */ + /***********************************/ + + if (b_IndexOperation == + APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER + || + b_IndexOperation + == + APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + { + /***************************************/ + /* Set the latch and clear flag (DQ27) */ + /***************************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + | + APCI1710_ENABLE_LATCH_AND_CLEAR; + } // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + else { + /*****************************************/ + /* Clear the latch and clear flag (DQ27) */ + /*****************************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + & + APCI1710_DISABLE_LATCH_AND_CLEAR; + + /*************************/ + /* Test if latch counter */ + /*************************/ + + if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER) { + /*********************************/ + /* Enable the latch from counter */ + /*********************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + | + APCI1710_INDEX_LATCH_COUNTER; + } else { + /*********************************/ + /* Enable the clear from counter */ + /*********************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + & + (~APCI1710_INDEX_LATCH_COUNTER); + } + } // // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) + + if (b_AutoMode == + APCI1710_DISABLE) + { + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + | + APCI1710_INDEX_AUTO_MODE; + } else { + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 + & + (~APCI1710_INDEX_AUTO_MODE); + } + + if (b_InterruptEnable == + APCI1710_ENABLE) + { + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 + | + APCI1710_ENABLE_INDEX_INT; + } else { + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 + & + APCI1710_DISABLE_INDEX_INT; + } + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_IndexInit = 1; + + } else { + /********************************/ + /* Interrupt parameter is wrong */ + /********************************/ + DPRINTK("Interrupt parameter is wrong\n"); + i_ReturnValue = -7; + } + } else { + /************************************/ + /* The auto mode parameter is wrong */ + /************************************/ + + DPRINTK("The auto mode parameter is wrong\n"); + i_ReturnValue = -6; + } + } else { + /***********************************************/ + /* The index operating mode parameter is wrong */ + /***********************************************/ + + DPRINTK("The index operating mode parameter is wrong\n"); + i_ReturnValue = -5; + } + } else { + /*******************************************/ + /* The reference action parameter is wrong */ + /*******************************************/ + + DPRINTK("The reference action parameter is wrong\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitReference | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_ReferenceLevel) | ++----------------------------------------------------------------------------+ +| Task : Initialise the reference corresponding to the selected | +| module (b_ModulNbr). | +| | +| Reference level | +| --------------- | +| +--------------------+-------------------------+ | +| | b_ReferenceLevel | Operation | | +| +--------------------+-------------------------+ | +| | APCI1710_LOW | Reference occur if "0" | | +| |--------------------|-------------------------| | +| | APCI1710_HIGH | Reference occur if "1" | | +| +--------------------+-------------------------+ | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_ReferenceLevel : Reference level. | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number parameter is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Reference level parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitReference(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_ReferenceLevel) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /**************************************/ + /* Test the reference level parameter */ + /**************************************/ + + if (b_ReferenceLevel == 0 || b_ReferenceLevel == 1) { + if (b_ReferenceLevel == 1) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 | + APCI1710_REFERENCE_HIGH; + } else { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & + APCI1710_REFERENCE_LOW; + } + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos.ui_Address + 20 + + (64 * b_ModulNbr)); + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_ReferenceInit = 1; + } else { + /**************************************/ + /* Reference level parameter is wrong */ + /**************************************/ + + DPRINTK("Reference level parameter is wrong\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitExternalStrobe | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_ExternalStrobe, | +| BYTE_ b_ExternalStrobeLevel) | ++----------------------------------------------------------------------------+ +| Task : Initialises the external strobe level corresponding to | +| the selected module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_ExternalStrobe : External strobe selection | +| 0 : External strobe A | +| 1 : External strobe B | +| BYTE_ b_ExternalStrobeLevel : External strobe level | +| APCI1710_LOW : | +| External latch occurs if "0" | +| APCI1710_HIGH : | +| External latch occurs if "1" | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised. | +| See function "i_APCI1710_InitCounter" | +| -4: External strobe selection is wrong | +| -5: External strobe level parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitExternalStrobe(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_ExternalStrobe, BYTE b_ExternalStrobeLevel) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /**************************************/ + /* Test the external strobe selection */ + /**************************************/ + + if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) { + /******************/ + /* Test the level */ + /******************/ + + if ((b_ExternalStrobeLevel == APCI1710_HIGH) || + ((b_ExternalStrobeLevel == APCI1710_LOW + && (devpriv-> + s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & + 0xFFFF) >= + 0x3135))) { + /*****************/ + /* Set the level */ + /*****************/ + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 & (0xFF - + (0x10 << b_ExternalStrobe))) | ((b_ExternalStrobeLevel ^ 1) << (4 + b_ExternalStrobe)); + } else { + /********************************************/ + /* External strobe level parameter is wrong */ + /********************************************/ + + DPRINTK("External strobe level parameter is wrong\n"); + i_ReturnValue = -5; + } + } // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) + else { + /**************************************/ + /* External strobe selection is wrong */ + /**************************************/ + + DPRINTK("External strobe selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + + /* + +----------------------------------------------------------------------------+ + | Function Name : _INT_ i_APCI1710_InitCompareLogic | + | (BYTE_ b_BoardHandle, | + | BYTE_ b_ModulNbr, | + | UINT_ ui_CompareValue) | + +----------------------------------------------------------------------------+ + | Task : Set the 32-Bit compare value. At that moment that the | + | incremental counter arrive to the compare value | + | (ui_CompareValue) a interrupt is generated. | + +----------------------------------------------------------------------------+ + | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | + | BYTE_ b_ModulNbr : Module number to configure | + | (0 to 3) | + | UINT_ ui_CompareValue : 32-Bit compare value | + +----------------------------------------------------------------------------+ + | Output Parameters : - + +----------------------------------------------------------------------------+ + | Return Value : 0: No error | + | -1: The handle parameter of the board is wrong | + | -2: No counter module found | + | -3: Counter not initialised see function | + | "i_APCI1710_InitCounter" | + +----------------------------------------------------------------------------+ + */ + +INT i_APCI1710_InitCompareLogic(struct comedi_device * dev, + BYTE b_ModulNbr, UINT ui_CompareValue) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + + outl(ui_CompareValue, devpriv->s_BoardInfos. + ui_Address + 28 + (64 * b_ModulNbr)); + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_CompareLogicInit = 1; + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitFrequencyMeasurement | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PCIInputClock, | +| BYTE_ b_TimingUnity, | +| ULONG_ ul_TimingInterval, | +| PULONG_ pul_RealTimingInterval) | ++----------------------------------------------------------------------------+ +| Task : Sets the time for the frequency measurement. | +| Configures the selected TOR incremental counter of the | +| selected module (b_ModulNbr). The ul_TimingInterval and| +| ul_TimingUnity determine the time base for the | +| measurement. The pul_RealTimingInterval returns the | +| real time value. You must call up this function before | +| you call up any other function which gives access to | +| the frequency measurement. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | +| BYTE_ b_PCIInputClock : Selection of the PCI bus | +| clock | +| - APCI1710_30MHZ : | +| The PC has a PCI bus clock | +| of 30 MHz | +| - APCI1710_33MHZ : | +| The PC has a PCI bus clock | +| of 33 MHz | +| BYTE_ b_TimingUnity : Base time unit (0 to 2) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| ULONG_ ul_TimingInterval: Base time value. | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_RealTimingInterval : Real base time value. | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected PCI input clock is wrong | +| -5: Timing unity selection is wrong | +| -6: Base timing selection is wrong | +| -7: 40MHz quartz not on board | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_PCIInputClock, + BYTE b_TimingUnity, + ULONG ul_TimingInterval, PULONG pul_RealTimingInterval) +{ + INT i_ReturnValue = 0; + ULONG ul_TimerValue = 0; + double d_RealTimingInterval; + DWORD dw_Status = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /**************************/ + /* Test the PCI bus clock */ + /**************************/ + + if ((b_PCIInputClock == APCI1710_30MHZ) || + (b_PCIInputClock == APCI1710_33MHZ) || + (b_PCIInputClock == APCI1710_40MHZ)) { + /************************/ + /* Test the timing unit */ + /************************/ + + if (b_TimingUnity <= 2) { + /**********************************/ + /* Test the base timing selection */ + /**********************************/ + + if (((b_PCIInputClock == APCI1710_30MHZ) + && (b_TimingUnity == 0) + && (ul_TimingInterval >= + 266) + && (ul_TimingInterval <= + 8738133UL)) + || ((b_PCIInputClock == + APCI1710_30MHZ) + && (b_TimingUnity == 1) + && (ul_TimingInterval >= + 1) + && (ul_TimingInterval <= + 8738UL)) + || ((b_PCIInputClock == + APCI1710_30MHZ) + && (b_TimingUnity == 2) + && (ul_TimingInterval >= + 1) + && (ul_TimingInterval <= + 8UL)) + || ((b_PCIInputClock == + APCI1710_33MHZ) + && (b_TimingUnity == 0) + && (ul_TimingInterval >= + 242) + && (ul_TimingInterval <= + 7943757UL)) + || ((b_PCIInputClock == + APCI1710_33MHZ) + && (b_TimingUnity == 1) + && (ul_TimingInterval >= + 1) + && (ul_TimingInterval <= + 7943UL)) + || ((b_PCIInputClock == + APCI1710_33MHZ) + && (b_TimingUnity == 2) + && (ul_TimingInterval >= + 1) + && (ul_TimingInterval <= + 7UL)) + || ((b_PCIInputClock == + APCI1710_40MHZ) + && (b_TimingUnity == 0) + && (ul_TimingInterval >= + 200) + && (ul_TimingInterval <= + 6553500UL)) + || ((b_PCIInputClock == + APCI1710_40MHZ) + && (b_TimingUnity == 1) + && (ul_TimingInterval >= + 1) + && (ul_TimingInterval <= + 6553UL)) + || ((b_PCIInputClock == + APCI1710_40MHZ) + && (b_TimingUnity == 2) + && (ul_TimingInterval >= + 1) + && (ul_TimingInterval <= + 6UL))) { + /**********************/ + /* Test if 40MHz used */ + /**********************/ + + if (b_PCIInputClock == + APCI1710_40MHZ) { + /******************************/ + /* Test if firmware >= Rev1.5 */ + /******************************/ + + if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3135) { + /*********************************/ + /* Test if 40MHz quartz on board */ + /*********************************/ + + /*INPDW (ps_APCI1710Variable-> + s_Board [b_BoardHandle]. + s_BoardInfos. + ui_Address + 36 + (64 * b_ModulNbr), &dw_Status); */ + dw_Status = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + 36 + + (64 * b_ModulNbr)); + + /******************************/ + /* Test the quartz flag (DQ0) */ + /******************************/ + + if ((dw_Status & 1) != 1) { + /*****************************/ + /* 40MHz quartz not on board */ + /*****************************/ + + DPRINTK("40MHz quartz not on board\n"); + i_ReturnValue + = + -7; + } + } else { + /*****************************/ + /* 40MHz quartz not on board */ + /*****************************/ + DPRINTK("40MHz quartz not on board\n"); + i_ReturnValue = + -7; + } + } // if (b_PCIInputClock == APCI1710_40MHZ) + + /***************************/ + /* Test if not error occur */ + /***************************/ + + if (i_ReturnValue == 0) { + /****************************/ + /* Test the INC_CPT version */ + /****************************/ + + if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131) { + + /**********************/ + /* Test if 40MHz used */ + /**********************/ + + if (b_PCIInputClock == APCI1710_40MHZ) { + /*********************************/ + /* Enable the 40MHz quarz (DQ30) */ + /*********************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + | + APCI1710_ENABLE_40MHZ_FREQUENCY; + } // if (b_PCIInputClock == APCI1710_40MHZ) + else { + /**********************************/ + /* Disable the 40MHz quarz (DQ30) */ + /**********************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + & + APCI1710_DISABLE_40MHZ_FREQUENCY; + + } // if (b_PCIInputClock == APCI1710_40MHZ) + + /********************************/ + /* Calculate the division fator */ + /********************************/ + + fpu_begin(); + switch (b_TimingUnity) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + (ul_TimingInterval + * + (0.00025 * b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (0.00025 * (double)b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + (0.00025 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (0.00025 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) { + *pul_RealTimingInterval + = + *pul_RealTimingInterval + + + 1; + } + + ul_TimingInterval + = + ul_TimingInterval + - + 1; + ul_TimerValue + = + ul_TimerValue + - + 2; + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + (ul_TimingInterval + * + (0.25 * b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (0.25 * (double)b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + ( + (double) + 0.25 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (0.25 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) { + *pul_RealTimingInterval + = + *pul_RealTimingInterval + + + 1; + } + + ul_TimingInterval + = + ul_TimingInterval + - + 1; + ul_TimerValue + = + ul_TimerValue + - + 2; + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + ul_TimingInterval + * + (250.0 + * + b_PCIInputClock); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (250.0 * (double)b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + (250.0 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (250.0 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) { + *pul_RealTimingInterval + = + *pul_RealTimingInterval + + + 1; + } + + ul_TimingInterval + = + ul_TimingInterval + - + 1; + ul_TimerValue + = + ul_TimerValue + - + 2; + + break; + } + + fpu_end(); + /*************************/ + /* Write the timer value */ + /*************************/ + + outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 32 + (64 * b_ModulNbr)); + + /*******************************/ + /* Set the initialisation flag */ + /*******************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementInit + = 1; + } else { + /***************************/ + /* Counter not initialised */ + /***************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = + -3; + } + } // if (i_ReturnValue == 0) + } else { + /**********************************/ + /* Base timing selection is wrong */ + /**********************************/ + + DPRINTK("Base timing selection is wrong\n"); + i_ReturnValue = -6; + } + } else { + /***********************************/ + /* Timing unity selection is wrong */ + /***********************************/ + + DPRINTK("Timing unity selection is wrong\n"); + i_ReturnValue = -5; + } + } else { + /*****************************************/ + /* The selected PCI input clock is wrong */ + /*****************************************/ + + DPRINTK("The selected PCI input clock is wrong\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/*########################################################################### */ + + //INSN BITS +/*########################################################################### */ + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev,struct comedi_subdevice *s, +struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Set & Clear Functions for INC_CPT | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnBitsINCCPT(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_BitsType; + INT i_ReturnValue = 0; + ui_BitsType = CR_CHAN(insn->chanspec); + devpriv->tsk_Current = current; // Save the current process task structure + + switch (ui_BitsType) { + case APCI1710_INCCPT_CLEARCOUNTERVALUE: + i_ReturnValue = i_APCI1710_ClearCounterValue(dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_CLEARALLCOUNTERVALUE: + i_ReturnValue = i_APCI1710_ClearAllCounterValue(dev); + break; + + case APCI1710_INCCPT_SETINPUTFILTER: + i_ReturnValue = i_APCI1710_SetInputFilter(dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], (BYTE) data[1]); + break; + + case APCI1710_INCCPT_LATCHCOUNTER: + i_ReturnValue = i_APCI1710_LatchCounter(dev, + (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]); + break; + + case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE: + i_ReturnValue = i_APCI1710_SetIndexAndReferenceSource(dev, + (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]); + break; + + case APCI1710_INCCPT_SETDIGITALCHLON: + i_ReturnValue = i_APCI1710_SetDigitalChlOn(dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_SETDIGITALCHLOFF: + i_ReturnValue = i_APCI1710_SetDigitalChlOff(dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + default: + printk("Bits Config Parameter Wrong\n"); + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ClearCounterValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Clear the counter value from selected module | +| (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number parameter is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ClearCounterValue(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*********************/ + /* Clear the counter */ + /*********************/ + + outl(1, devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ClearAllCounterValue | +| (BYTE_ b_BoardHandle) | ++----------------------------------------------------------------------------+ +| Task : Clear all counter value. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ClearAllCounterValue(struct comedi_device * dev) +{ + BYTE b_ModulCpt = 0; + INT i_ReturnValue = 0; + + /********************************/ + /* Test if counter module found */ + /********************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[0] & 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER + || (devpriv->s_BoardInfos. + dw_MolduleConfiguration[1] & 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER + || (devpriv->s_BoardInfos. + dw_MolduleConfiguration[2] & 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER + || (devpriv->s_BoardInfos. + dw_MolduleConfiguration[3] & 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER) { + for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) { + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulCpt] & + 0xFFFF0000UL) == + APCI1710_INCREMENTAL_COUNTER) { + /*********************/ + /* Clear the counter */ + /*********************/ + + outl(1, devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulCpt)); + } + } + } else { + /***************************/ + /* No counter module found */ + /***************************/ + + DPRINTK("No counter module found\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetInputFilter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_Module, | +| BYTE_ b_PCIInputClock, | +| BYTE_ b_Filter) | ++----------------------------------------------------------------------------+ +| Task : Disable or enable the software filter from selected | +| module (b_ModulNbr). b_Filter determine the filter time| ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | +| BYTE_ b_PCIInputClock : Selection of the PCI bus | +| clock | +| - APCI1710_30MHZ : | +| The PC has a PCI bus clock | +| of 30 MHz | +| - APCI1710_33MHZ : | +| The PC has a PCI bus clock | +| of 33 MHz | +| - APCI1710_40MHZ : | +| The APCI1710 has a 40MHz | +| quartz | +| BYTE_ b_Filter : Filter selection | +| | +| 30 MHz | +| ------ | +| 0: Software filter not used | +| 1: Filter from 266ns (3.750000MHz) | +| 2: Filter from 400ns (2.500000MHz) | +| 3: Filter from 533ns (1.876170MHz) | +| 4: Filter from 666ns (1.501501MHz) | +| 5: Filter from 800ns (1.250000MHz) | +| 6: Filter from 933ns (1.071800MHz) | +| 7: Filter from 1066ns (0.938080MHz) | +| 8: Filter from 1200ns (0.833333MHz) | +| 9: Filter from 1333ns (0.750000MHz) | +| 10: Filter from 1466ns (0.682100MHz) | +| 11: Filter from 1600ns (0.625000MHz) | +| 12: Filter from 1733ns (0.577777MHz) | +| 13: Filter from 1866ns (0.535900MHz) | +| 14: Filter from 2000ns (0.500000MHz) | +| 15: Filter from 2133ns (0.468800MHz) | +| | +| 33 MHz | +| ------ | +| 0: Software filter not used | +| 1: Filter from 242ns (4.125000MHz) | +| 2: Filter from 363ns (2.754820MHz) | +| 3: Filter from 484ns (2.066115MHz) | +| 4: Filter from 605ns (1.652892MHz) | +| 5: Filter from 726ns (1.357741MHz) | +| 6: Filter from 847ns (1.180637MHz) | +| 7: Filter from 968ns (1.033055MHz) | +| 8: Filter from 1089ns (0.918273MHz) | +| 9: Filter from 1210ns (0.826446MHz) | +| 10: Filter from 1331ns (0.751314MHz) | +| 11: Filter from 1452ns (0.688705MHz) | +| 12: Filter from 1573ns (0.635727MHz) | +| 13: Filter from 1694ns (0.590318MHz) | +| 14: Filter from 1815ns (0.550964MHz) | +| 15: Filter from 1936ns (0.516528MHz) | +| | +| 40 MHz | +| ------ | +| 0: Software filter not used | +| 1: Filter from 200ns (5.000000MHz) | +| 2: Filter from 300ns (3.333333MHz) | +| 3: Filter from 400ns (2.500000MHz) | +| 4: Filter from 500ns (2.000000MHz) | +| 5: Filter from 600ns (1.666666MHz) | +| 6: Filter from 700ns (1.428500MHz) | +| 7: Filter from 800ns (1.250000MHz) | +| 8: Filter from 900ns (1.111111MHz) | +| 9: Filter from 1000ns (1.000000MHz) | +| 10: Filter from 1100ns (0.909090MHz) | +| 11: Filter from 1200ns (0.833333MHz) | +| 12: Filter from 1300ns (0.769200MHz) | +| 13: Filter from 1400ns (0.714200MHz) | +| 14: Filter from 1500ns (0.666666MHz) | +| 15: Filter from 1600ns (0.625000MHz) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: The module is not a counter module | +| -4: The selected PCI input clock is wrong | +| -5: The selected filter value is wrong | +| -6: 40MHz quartz not on board | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetInputFilter(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_PCIInputClock, BYTE b_Filter) +{ + INT i_ReturnValue = 0; + DWORD dw_Status = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) { + /******************************/ + /* Test if firmware >= Rev1.5 */ + /******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF) >= 0x3135) { + /**************************/ + /* Test the PCI bus clock */ + /**************************/ + + if ((b_PCIInputClock == APCI1710_30MHZ) || + (b_PCIInputClock == APCI1710_33MHZ) || + (b_PCIInputClock == APCI1710_40MHZ)) { + /*************************/ + /* Test the filter value */ + /*************************/ + + if (b_Filter < 16) { + /**********************/ + /* Test if 40MHz used */ + /**********************/ + + if (b_PCIInputClock == + APCI1710_40MHZ) { + /*********************************/ + /* Test if 40MHz quartz on board */ + /*********************************/ + + dw_Status = + inl(devpriv-> + s_BoardInfos. + ui_Address + + 36 + + (64 * b_ModulNbr)); + + /******************************/ + /* Test the quartz flag (DQ0) */ + /******************************/ + + if ((dw_Status & 1) != + 1) { + /*****************************/ + /* 40MHz quartz not on board */ + /*****************************/ + + DPRINTK("40MHz quartz not on board\n"); + i_ReturnValue = + -6; + } + } // if (b_PCIInputClock == APCI1710_40MHZ) + + /***************************/ + /* Test if error not occur */ + /***************************/ + + if (i_ReturnValue == 0) { + /**********************/ + /* Test if 40MHz used */ + /**********************/ + + if (b_PCIInputClock == + APCI1710_40MHZ) + { + /*********************************/ + /* Enable the 40MHz quarz (DQ31) */ + /*********************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + | + APCI1710_ENABLE_40MHZ_FILTER; + + } // if (b_PCIInputClock == APCI1710_40MHZ) + else { + /**********************************/ + /* Disable the 40MHz quarz (DQ31) */ + /**********************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + & + APCI1710_DISABLE_40MHZ_FILTER; + + } // if (b_PCIInputClock == APCI1710_40MHZ) + + /************************/ + /* Set the filter value */ + /************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 + = + (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 + & 0x1F) | + ((b_Filter & + 0x7) << + 5); + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + = + (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 + & 0xFE) | + ((b_Filter & + 0x8) >> + 3); + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv-> + s_BoardInfos. + ui_Address + + 20 + + (64 * b_ModulNbr)); + } // if (i_ReturnValue == 0) + } // if (b_Filter < 16) + else { + /**************************************/ + /* The selected filter value is wrong */ + /**************************************/ + + DPRINTK("The selected filter value is wrong\n"); + i_ReturnValue = -5; + } // if (b_Filter < 16) + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) + else { + /*****************************************/ + /* The selected PCI input clock is wrong */ + /*****************************************/ + + DPRINTK("The selected PCI input clock is wrong\n"); + i_ReturnValue = 4; + } // if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) + } else { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -3; + } + } else { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_LatchCounter (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_LatchReg) | ++----------------------------------------------------------------------------+ +| Task : Latch the courant value from selected module | +| (b_ModulNbr) in to the selected latch register | +| (b_LatchReg). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_LatchReg : Selected latch register | +| 0 : for the first latch register | +| 1 : for the second latch register | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected latch register parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_LatchCounter(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_LatchReg) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*************************************/ + /* Test the latch register parameter */ + /*************************************/ + + if (b_LatchReg < 2) { + /*********************/ + /* Tatch the counter */ + /*********************/ + + outl(1 << (b_LatchReg * 4), + devpriv->s_BoardInfos.ui_Address + + (64 * b_ModulNbr)); + } else { + /**************************************************/ + /* The selected latch register parameter is wrong */ + /**************************************************/ + + DPRINTK("The selected latch register parameter is wrong\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetIndexAndReferenceSource | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SourceSelection) | ++----------------------------------------------------------------------------+ +| Task : Determine the hardware source for the index and the | +| reference logic. Per default the index logic is | +| connected to the difference input C and the reference | +| logic is connected to the 24V input E | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_SourceSelection : APCI1710_SOURCE_0 : | +| The index logic is connected | +| to the difference input C and| +| the reference logic is | +| connected to the 24V input E.| +| This is the default | +| configuration. | +| APCI1710_SOURCE_1 : | +| The reference logic is | +| connected to the difference | +| input C and the index logic | +| is connected to the 24V | +| input E | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: The module is not a counter module. | +| -4: The source selection is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_SourceSelection) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if incremental counter */ + /*******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) { + /******************************/ + /* Test if firmware >= Rev1.5 */ + /******************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF) >= 0x3135) { + /*****************************/ + /* Test the source selection */ + /*****************************/ + + if (b_SourceSelection == APCI1710_SOURCE_0 || + b_SourceSelection == APCI1710_SOURCE_1) + { + /******************************************/ + /* Test if invert the index and reference */ + /******************************************/ + + if (b_SourceSelection == + APCI1710_SOURCE_1) { + /********************************************/ + /* Invert index and reference source (DQ25) */ + /********************************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 | + APCI1710_INVERT_INDEX_RFERENCE; + } else { + /****************************************/ + /* Set the default configuration (DQ25) */ + /****************************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister4 & + APCI1710_DEFAULT_INDEX_RFERENCE; + } + } // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) + else { + /*********************************/ + /* The source selection is wrong */ + /*********************************/ + + DPRINTK("The source selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) + } else { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -3; + } + } else { + /**************************************/ + /* The module is not a counter module */ + /**************************************/ + + DPRINTK("The module is not a counter module\n"); + i_ReturnValue = -3; + } + } else { + /***************************************/ + /* The selected module number is wrong */ + /***************************************/ + + DPRINTK("The selected module number is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetDigitalChlOn | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Sets the digital output H Setting an output means | +| setting an ouput high. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetDigitalChlOn(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister.b_ModeRegister3 | 0x10; + + /*********************/ + /* Set the output On */ + /*********************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_SetDigitalChlOff | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Resets the digital output H. Resetting an output means | +| setting an ouput low. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Number of the module to be | +| configured (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The selected module number is wrong | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetDigitalChlOff(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister.b_ModeRegister3 & 0xEF; + + /**********************/ + /* Set the output Off */ + /**********************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/*########################################################################### */ + + // INSN WRITE +/*########################################################################### */ + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s, +struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Enable Disable functions for INC_CPT | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1710_InsnWriteINCCPT(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_WriteType; + INT i_ReturnValue = 0; + + ui_WriteType = CR_CHAN(insn->chanspec); + devpriv->tsk_Current = current; // Save the current process task structure + + switch (ui_WriteType) { + case APCI1710_INCCPT_ENABLELATCHINTERRUPT: + i_ReturnValue = i_APCI1710_EnableLatchInterrupt(dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_DISABLELATCHINTERRUPT: + i_ReturnValue = i_APCI1710_DisableLatchInterrupt(dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE: + i_ReturnValue = i_APCI1710_Write16BitCounterValue(dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], (UINT) data[1]); + break; + + case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE: + i_ReturnValue = i_APCI1710_Write32BitCounterValue(dev, + (BYTE) CR_AREF(insn->chanspec), (ULONG) data[0]); + + break; + + case APCI1710_INCCPT_ENABLEINDEX: + i_APCI1710_EnableIndex(dev, (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_DISABLEINDEX: + i_ReturnValue = i_APCI1710_DisableIndex(dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_ENABLECOMPARELOGIC: + i_ReturnValue = i_APCI1710_EnableCompareLogic(dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_DISABLECOMPARELOGIC: + i_ReturnValue = i_APCI1710_DisableCompareLogic(dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT: + i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement(dev, + (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]); + break; + + case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT: + i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement(dev, + (BYTE) CR_AREF(insn->chanspec)); + break; + + default: + printk("Write Config Parameter Wrong\n"); + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableLatchInterrupt | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Enable the latch interrupt from selected module | +| (b_ModulNbr). Each software or hardware latch occur a | +| interrupt. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Interrupt routine not installed see function | +| "i_APCI1710_SetBoardIntRoutine" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + + /********************/ + /* Enable interrupt */ + /********************/ + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 | APCI1710_ENABLE_LATCH_INT; + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModulNbr)); + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisableLatchInterrupt | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Disable the latch interrupt from selected module | +| (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Interrupt routine not installed see function | +| "i_APCI1710_SetBoardIntRoutine" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisableLatchInterrupt(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4 & + ((APCI1710_DISABLE_LATCH_INT << 8) | 0xFF), + devpriv->s_BoardInfos.ui_Address + 20 + + (64 * b_ModulNbr)); + + mdelay(1000); + + /*********************/ + /* Disable interrupt */ + /*********************/ + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & APCI1710_DISABLE_LATCH_INT; + + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Write16BitCounterValue | +| (BYTE_ b_BoardHandle | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SelectedCounter, | +| UINT_ ui_WriteValue) | ++----------------------------------------------------------------------------+ +| Task : Write a 16-Bit value (ui_WriteValue) in to the selected| +| 16-Bit counter (b_SelectedCounter) from selected module| +| (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_SelectedCounter : Selected 16-Bit counter | +| (0 or 1) | +| UINT_ ui_WriteValue : 16-Bit write value | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected 16-Bit counter parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Write16BitCounterValue(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_SelectedCounter, UINT ui_WriteValue) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /******************************/ + /* Test the counter selection */ + /******************************/ + + if (b_SelectedCounter < 2) { + /*******************/ + /* Write the value */ + /*******************/ + + outl((ULONG) ((ULONG) (ui_WriteValue) << (16 * + b_SelectedCounter)), + devpriv->s_BoardInfos.ui_Address + 8 + + (b_SelectedCounter * 4) + + (64 * b_ModulNbr)); + } else { + /**************************************************/ + /* The selected 16-Bit counter parameter is wrong */ + /**************************************************/ + + DPRINTK("The selected 16-Bit counter parameter is wrong\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Write32BitCounterValue | +| (BYTE_ b_BoardHandle | +| BYTE_ b_ModulNbr, | +| ULONG_ ul_WriteValue) | ++----------------------------------------------------------------------------+ +| Task : Write a 32-Bit value (ui_WriteValue) in to the selected| +| module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| ULONG_ ul_WriteValue : 32-Bit write value | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Write32BitCounterValue(struct comedi_device * dev, + BYTE b_ModulNbr, ULONG ul_WriteValue) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*******************/ + /* Write the value */ + /*******************/ + + outl(ul_WriteValue, devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulNbr)); + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableIndex (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Enable the INDEX actions | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Index not initialised see function | +| "i_APCI1710_InitIndex" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnableIndex(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + ULONG ul_InterruptLatchReg; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*****************************/ + /* Test if index initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_IndexInit) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 | APCI1710_ENABLE_INDEX; + + ul_InterruptLatchReg = + inl(devpriv->s_BoardInfos.ui_Address + + 24 + (64 * b_ModulNbr)); + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos.ui_Address + 20 + + (64 * b_ModulNbr)); + } else { + /*************************************************************/ + /* Index not initialised see function "i_APCI1710_InitIndex" */ + /*************************************************************/ + + DPRINTK("Index not initialised \n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisableIndex (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Disable the INDEX actions | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Index not initialised see function | +| "i_APCI1710_InitIndex" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisableIndex(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*****************************/ + /* Test if index initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_IndexInit) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & + APCI1710_DISABLE_INDEX; + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos.ui_Address + 20 + + (64 * b_ModulNbr)); + } else { + /*************************************************************/ + /* Index not initialised see function "i_APCI1710_InitIndex" */ + /*************************************************************/ + + DPRINTK("Index not initialised \n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableCompareLogic | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Enable the 32-Bit compare logic. At that moment that | +| the incremental counter arrive to the compare value a | +| interrupt is generated. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Compare logic not initialised. | +| See function "i_APCI1710_InitCompareLogic" | +| -5: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*************************************/ + /* Test if compare logic initialised */ + /*************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_CompareLogicInit == 1) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 | + APCI1710_ENABLE_COMPARE_INT; + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos.ui_Address + 20 + + (64 * b_ModulNbr)); + } else { + /*********************************/ + /* Compare logic not initialised */ + /*********************************/ + + DPRINTK("Compare logic not initialised\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisableCompareLogic | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Task : Disable the 32-Bit compare logic. ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : - ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Compare logic not initialised. | +| See function "i_APCI1710_InitCompareLogic" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisableCompareLogic(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*************************************/ + /* Test if compare logic initialised */ + /*************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_CompareLogicInit == 1) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & + APCI1710_DISABLE_COMPARE_INT; + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos.ui_Address + 20 + + (64 * b_ModulNbr)); + } else { + /*********************************/ + /* Compare logic not initialised */ + /*********************************/ + + DPRINTK("Compare logic not initialised\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + + /* + +----------------------------------------------------------------------------+ + | Function Name : _INT_ i_APCI1710_EnableFrequencyMeasurement | + | (BYTE_ b_BoardHandle, | + | BYTE_ b_ModulNbr, | + | BYTE_ b_InterruptEnable) | + +----------------------------------------------------------------------------+ + | Task : Enables the frequency measurement function | + +----------------------------------------------------------------------------+ + | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | + | BYTE_ b_ModulNbr : Number of the module to be | + | configured (0 to 3) | + | BYTE_ b_InterruptEnable: Enable or disable the | + | interrupt. | + | APCI1710_ENABLE: | + | Enable the interrupt | + | APCI1710_DISABLE: | + | Disable the interrupt | + +----------------------------------------------------------------------------+ + | Output Parameters : - | + +----------------------------------------------------------------------------+ + | Return Value : 0: No error | + | -1: The handle parameter of the board is wrong | + | -2: The selected module number is wrong | + | -3: Counter not initialised see function | + | "i_APCI1710_InitCounter" | + | -4: Frequency measurement logic not initialised. | + | See function "i_APCI1710_InitFrequencyMeasurement" | + | -5: Interrupt parameter is wrong | + | -6: Interrupt function not initialised. | + +----------------------------------------------------------------------------+ + */ + +INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_InterruptEnable) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /********************************************/ + /* Test if frequency mesurement initialised */ + /********************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_FrequencyMeasurementInit == 1) { + /***************************/ + /* Test the interrupt mode */ + /***************************/ + + if ((b_InterruptEnable == APCI1710_DISABLE) || + (b_InterruptEnable == APCI1710_ENABLE)) + { + + /************************************/ + /* Enable the frequency measurement */ + /************************************/ + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 | + APCI1710_ENABLE_FREQUENCY; + + /*********************************************/ + /* Disable or enable the frequency interrupt */ + /*********************************************/ + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & + APCI1710_DISABLE_FREQUENCY_INT) + | (b_InterruptEnable << 3); + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos. + ui_Address + 20 + + (64 * b_ModulNbr)); + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementEnable = + 1; + } else { + /********************************/ + /* Interrupt parameter is wrong */ + /********************************/ + + DPRINTK("Interrupt parameter is wrong\n"); + i_ReturnValue = -5; + } + } else { + /***********************************************/ + /* Frequency measurement logic not initialised */ + /***********************************************/ + + DPRINTK("Frequency measurement logic not initialised\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + + /* + +----------------------------------------------------------------------------+ + | Function Name : _INT_ i_APCI1710_DisableFrequencyMeasurement | + | (BYTE_ b_BoardHandle, | + | BYTE_ b_ModulNbr) | + +----------------------------------------------------------------------------+ + | Task : Disables the frequency measurement function | + +----------------------------------------------------------------------------+ + | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | + | BYTE_ b_ModulNbr : Number of the module to be | + | configured (0 to 3) | + +----------------------------------------------------------------------------+ + | Output Parameters : - | + +----------------------------------------------------------------------------+ + | Return Value : 0: No error | + | -1: The handle parameter of the board is wrong | + | -2: The selected module number is wrong | + | -3: Counter not initialised see function | + | "i_APCI1710_InitCounter" | + | -4: Frequency measurement logic not initialised. | + | See function "i_APCI1710_InitFrequencyMeasurement" | + +----------------------------------------------------------------------------+ + */ + +INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device * dev, BYTE b_ModulNbr) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /********************************************/ + /* Test if frequency mesurement initialised */ + /********************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_FrequencyMeasurementInit == 1) { + /*************************************/ + /* Disable the frequency measurement */ + /*************************************/ + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & + APCI1710_DISABLE_FREQUENCY + // Begin CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared + & APCI1710_DISABLE_FREQUENCY_INT; + // End CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared + + /***************************/ + /* Write the configuration */ + /***************************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos.ui_Address + 20 + + (64 * b_ModulNbr)); + + /*************************************/ + /* Disable the frequency measurement */ + /*************************************/ + + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementEnable = 0; + } else { + /***********************************************/ + /* Frequency measurement logic not initialised */ + /***********************************************/ + + DPRINTK("Frequency measurement logic not initialised\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/*########################################################################### */ + + // INSN READ + +/*########################################################################### */ + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev,struct comedi_subdevice *s, +struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read and Get functions for INC_CPT | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1710_InsnReadINCCPT(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_ReadType; + INT i_ReturnValue = 0; + + ui_ReadType = CR_CHAN(insn->chanspec); + + devpriv->tsk_Current = current; // Save the current process task structure + switch (ui_ReadType) { + case APCI1710_INCCPT_READLATCHREGISTERSTATUS: + i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_RANGE(insn->chanspec), (PBYTE) & data[0]); + break; + + case APCI1710_INCCPT_READLATCHREGISTERVALUE: + i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_RANGE(insn->chanspec), (PULONG) & data[0]); + printk("Latch Register Value %d\n", data[0]); + break; + + case APCI1710_INCCPT_READ16BITCOUNTERVALUE: + i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) CR_RANGE(insn->chanspec), (PUINT) & data[0]); + break; + + case APCI1710_INCCPT_READ32BITCOUNTERVALUE: + i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev, + (BYTE) CR_AREF(insn->chanspec), (PULONG) & data[0]); + break; + + case APCI1710_INCCPT_GETINDEXSTATUS: + i_ReturnValue = i_APCI1710_GetIndexStatus(dev, + (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]); + break; + + case APCI1710_INCCPT_GETREFERENCESTATUS: + i_ReturnValue = i_APCI1710_GetReferenceStatus(dev, + (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]); + break; + + case APCI1710_INCCPT_GETUASSTATUS: + i_ReturnValue = i_APCI1710_GetUASStatus(dev, + (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]); + break; + + case APCI1710_INCCPT_GETCBSTATUS: + i_ReturnValue = i_APCI1710_GetCBStatus(dev, + (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]); + break; + + case APCI1710_INCCPT_GET16BITCBSTATUS: + i_ReturnValue = i_APCI1710_Get16BitCBStatus(dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) & data[0], (PBYTE) & data[1]); + break; + + case APCI1710_INCCPT_GETUDSTATUS: + i_ReturnValue = i_APCI1710_GetUDStatus(dev, + (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]); + + break; + + case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS: + i_ReturnValue = i_APCI1710_GetInterruptUDLatchedStatus(dev, + (BYTE) CR_AREF(insn->chanspec), (PBYTE) & data[0]); + break; + + case APCI1710_INCCPT_READFREQUENCYMEASUREMENT: + i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev, + (BYTE) CR_AREF(insn->chanspec), + (PBYTE) & data[0], + (PBYTE) & data[1], (PULONG) & data[2]); + break; + + case APCI1710_INCCPT_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; + + default: + printk("ReadType Parameter wrong\n"); + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); + +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadLatchRegisterStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_LatchReg, | +| PBYTE_ pb_LatchStatus) | ++----------------------------------------------------------------------------+ +| Task : Read the latch register status from selected module | +| (b_ModulNbr) and selected latch register (b_LatchReg). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_LatchReg : Selected latch register | +| 0 : for the first latch register | +| 1 : for the second latch register | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_LatchStatus : Latch register status. | +| 0 : No latch occur | +| 1 : A software latch occur | +| 2 : A hardware latch occur | +| 3 : A software and hardware | +| latch occur | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected latch register parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_LatchReg, PBYTE pb_LatchStatus) +{ + INT i_ReturnValue = 0; + DWORD dw_LatchReg; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*************************************/ + /* Test the latch register parameter */ + /*************************************/ + + if (b_LatchReg < 2) { + dw_LatchReg = inl(devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + + *pb_LatchStatus = + (BYTE) ((dw_LatchReg >> (b_LatchReg * + 4)) & 0x3); + } else { + /**************************************************/ + /* The selected latch register parameter is wrong */ + /**************************************************/ + + DPRINTK("The selected latch register parameter is wrong\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadLatchRegisterValue | +| (BYTE_ b_BoardHandle,| +| BYTE_ b_ModulNbr, | +| BYTE_ b_LatchReg, | +| PULONG_ pul_LatchValue) | ++----------------------------------------------------------------------------+ +| Task : Read the latch register value from selected module | +| (b_ModulNbr) and selected latch register (b_LatchReg). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_LatchReg : Selected latch register | +| 0 : for the first latch register | +| 1 : for the second latch register | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_LatchValue : Latch register value | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected latch register parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_LatchReg, PULONG pul_LatchValue) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*************************************/ + /* Test the latch register parameter */ + /*************************************/ + + if (b_LatchReg < 2) { + *pul_LatchValue = inl(devpriv->s_BoardInfos. + ui_Address + ((b_LatchReg + 1) * 4) + + (64 * b_ModulNbr)); + + } else { + /**************************************************/ + /* The selected latch register parameter is wrong */ + /**************************************************/ + + DPRINTK("The selected latch register parameter is wrong\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Read16BitCounterValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SelectedCounter, | +| PUINT_ pui_CounterValue) | ++----------------------------------------------------------------------------+ +| Task : Latch the selected 16-Bit counter (b_SelectedCounter) | +| from selected module (b_ModulNbr) in to the first | +| latch register and return the latched value. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| BYTE_ b_SelectedCounter : Selected 16-Bit counter | +| (0 or 1) | ++----------------------------------------------------------------------------+ +| Output Parameters : PUINT_ pui_CounterValue : 16-Bit counter value | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: The selected 16-Bit counter parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Read16BitCounterValue(struct comedi_device * dev, + BYTE b_ModulNbr, BYTE b_SelectedCounter, PUINT pui_CounterValue) +{ + INT i_ReturnValue = 0; + DWORD dw_LathchValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /******************************/ + /* Test the counter selection */ + /******************************/ + + if (b_SelectedCounter < 2) { + /*********************/ + /* Latch the counter */ + /*********************/ + + outl(1, devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + + /************************/ + /* Read the latch value */ + /************************/ + + dw_LathchValue = inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulNbr)); + + *pui_CounterValue = + (UINT) ((dw_LathchValue >> (16 * + b_SelectedCounter)) & + 0xFFFFU); + } else { + /**************************************************/ + /* The selected 16-Bit counter parameter is wrong */ + /**************************************************/ + + DPRINTK("The selected 16-Bit counter parameter is wrong\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Read32BitCounterValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PULONG_ pul_CounterValue) | ++----------------------------------------------------------------------------+ +| Task : Latch the 32-Bit counter from selected module | +| (b_ModulNbr) in to the first latch register and return | +| the latched value. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_CounterValue : 32-Bit counter value | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Read32BitCounterValue(struct comedi_device * dev, + BYTE b_ModulNbr, PULONG pul_CounterValue) +{ + INT i_ReturnValue = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*********************/ + /* Tatch the counter */ + /*********************/ + + outl(1, devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + + /************************/ + /* Read the latch value */ + /************************/ + + *pul_CounterValue = inl(devpriv->s_BoardInfos. + ui_Address + 4 + (64 * b_ModulNbr)); + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetIndexStatus (BYTE_ b_BoardHandle,| +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_IndexStatus)| ++----------------------------------------------------------------------------+ +| Task : Return the index status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_IndexStatus : 0 : No INDEX occur | +| 1 : A INDEX occur | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Index not initialised see function | +| "i_APCI1710_InitIndex" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetIndexStatus(struct comedi_device * dev, + BYTE b_ModulNbr, PBYTE pb_IndexStatus) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*****************************/ + /* Test if index initialised */ + /*****************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_IndexInit) { + dw_StatusReg = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModulNbr)); + + *pb_IndexStatus = (BYTE) (dw_StatusReg & 1); + } else { + /*************************************************************/ + /* Index not initialised see function "i_APCI1710_InitIndex" */ + /*************************************************************/ + + DPRINTK("Index not initialised\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetReferenceStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_ReferenceStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the reference status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_ReferenceStatus : 0 : No REFERENCE occur | +| 1 : A REFERENCE occur | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Reference not initialised see function | +| "i_APCI1710_InitReference" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetReferenceStatus(struct comedi_device * dev, + BYTE b_ModulNbr, PBYTE pb_ReferenceStatus) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*********************************/ + /* Test if reference initialised */ + /*********************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_ReferenceInit) { + dw_StatusReg = inl(devpriv->s_BoardInfos. + ui_Address + 24 + (64 * b_ModulNbr)); + + *pb_ReferenceStatus = + (BYTE) (~dw_StatusReg & 1); + } else { + /*********************************************************************/ + /* Reference not initialised see function "i_APCI1710_InitReference" */ + /*********************************************************************/ + + DPRINTK("Reference not initialised\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetUASStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_UASStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the error signal (UAS) status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_UASStatus : 0 : UAS is low "0" | +| 1 : UAS is high "1" | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetUASStatus(struct comedi_device * dev, + BYTE b_ModulNbr, PBYTE pb_UASStatus) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + dw_StatusReg = inl(devpriv->s_BoardInfos. + ui_Address + 24 + (64 * b_ModulNbr)); + + *pb_UASStatus = (BYTE) ((dw_StatusReg >> 1) & 1); + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetCBStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_CBStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the counter overflow status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_CBStatus : 0 : Counter no overflow | +| 1 : Counter overflow | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetCBStatus(struct comedi_device * dev, + BYTE b_ModulNbr, PBYTE pb_CBStatus) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + dw_StatusReg = inl(devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModulNbr)); + + *pb_CBStatus = (BYTE) (dw_StatusReg & 1); + + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Get16BitCBStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_CBStatusCounter0, | +| PBYTE_ pb_CBStatusCounter1) | ++----------------------------------------------------------------------------+ +| Task : Returns the counter overflow (counter initialised to | +| 2*16-bit) status from selected incremental counter | +| module | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_CBStatusCounter0 : 0 : No overflow occur for | +| the first 16-bit | +| counter | +| 1 : Overflow occur for the| +| first 16-bit counter | +| PBYTE_ pb_CBStatusCounter1 : 0 : No overflow occur for | +| the second 16-bit | +| counter | +| 1 : Overflow occur for the| +| second 16-bit counter | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Counter not initialised to 2*16-bit mode. | +| See function "i_APCI1710_InitCounter" | +| -5: Firmware revision error | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_Get16BitCBStatus(struct comedi_device * dev, + BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0, PBYTE pb_CBStatusCounter1) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*************************/ + /* Test if 2*16-Bit mode */ + /*************************/ + + if ((devpriv->s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 & 0x10) == 0x10) { + /*****************************/ + /* Test the Firmware version */ + /*****************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & 0xFFFF) >= + 0x3136) { + dw_StatusReg = + inl(devpriv->s_BoardInfos. + ui_Address + 16 + + (64 * b_ModulNbr)); + + *pb_CBStatusCounter1 = + (BYTE) ((dw_StatusReg >> 0) & + 1); + *pb_CBStatusCounter0 = + (BYTE) ((dw_StatusReg >> 1) & + 1); + } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) + else { + /****************************/ + /* Firmware revision error */ + /****************************/ + + i_ReturnValue = -5; + } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) + } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) + else { + /********************************************/ + /* Counter not initialised to 2*16-bit mode */ + /* "i_APCI1710_InitCounter" */ + /********************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -4; + } // if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) + } // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) + else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } // if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) + } // if (b_ModulNbr < 4) + else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } // if (b_ModulNbr < 4) + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetUDStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_UDStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the counter progress status | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_UDStatus : 0 : Counter progress in the | +| selected mode down | +| 1 : Counter progress in the | +| selected mode up | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetUDStatus(struct comedi_device * dev, + BYTE b_ModulNbr, PBYTE pb_UDStatus) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + dw_StatusReg = inl(devpriv->s_BoardInfos. + ui_Address + 24 + (64 * b_ModulNbr)); + + *pb_UDStatus = (BYTE) ((dw_StatusReg >> 2) & 1); + + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_GetInterruptUDLatchedStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| PBYTE_ pb_UDStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the counter progress latched status after a | +| index interrupt occur. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_UDStatus : 0 : Counter progress in the | +| selected mode down | +| 1 : Counter progress in the | +| selected mode up | +| 2 : No index interrupt occur | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: No counter module found | +| -3: Counter not initialised see function | +| "i_APCI1710_InitCounter" | +| -4: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device * dev, + BYTE b_ModulNbr, PBYTE pb_UDStatus) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /*********************************/ + /* Test if index interrupt occur */ + /*********************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_IndexInterruptOccur == 1) { + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_IndexInterruptOccur = 0; + + dw_StatusReg = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModulNbr)); + + *pb_UDStatus = (BYTE) ((dw_StatusReg >> 1) & 1); + } else { + /****************************/ + /* No index interrupt occur */ + /****************************/ + + *pb_UDStatus = 2; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + + /* + +----------------------------------------------------------------------------+ + | Function Name : _INT_ i_APCI1710_ReadFrequencyMeasurement | + | (BYTE_ b_BoardHandle, | + | BYTE_ b_ModulNbr, | + | PBYTE_ pb_Status, | + | PULONG_ pul_ReadValue) | + +----------------------------------------------------------------------------+ + | Task : Returns the status (pb_Status) and the number of | + | increments in the set time. | + | See function " i_APCI1710_InitFrequencyMeasurement " | + +----------------------------------------------------------------------------+ + | Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | + | BYTE_ b_ModulNbr : Number of the module to be | + | configured (0 to 3) | + +----------------------------------------------------------------------------+ + | Output Parameters : PBYTE_ pb_Status : Returns the frequency | + | measurement status | + | 0 : Counting cycle not | + | started. | + | 1 : Counting cycle started. | + | 2 : Counting cycle stopped. | + | The measurement cycle is | + | completed. | + | PBYTE_ pb_UDStatus : 0 : Counter progress in the | + | selected mode down | + | 1 : Counter progress in the | + | selected mode up | + | PULONG_ pul_ReadValue : Return the number of | + | increments in the defined | + | time base. | + +----------------------------------------------------------------------------+ + | Return Value : 0: No error | + | -1: The handle parameter of the board is wrong | + | -2: The selected module number is wrong | + | -3: Counter not initialised see function | + | "i_APCI1710_InitCounter" | + | -4: Frequency measurement logic not initialised. | + | See function "i_APCI1710_InitFrequencyMeasurement" | + +----------------------------------------------------------------------------+ + */ + +INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device * dev, + BYTE b_ModulNbr, + PBYTE pb_Status, PBYTE pb_UDStatus, PULONG pul_ReadValue) +{ + INT i_ReturnValue = 0; + UINT ui_16BitValue; + DWORD dw_StatusReg; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { + /********************************************/ + /* Test if frequency mesurement initialised */ + /********************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag.b_FrequencyMeasurementInit == 1) { + /******************/ + /* Test if enable */ + /******************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SiemensCounterInfo. + s_InitFlag. + b_FrequencyMeasurementEnable == 1) { + /*******************/ + /* Read the status */ + /*******************/ + + dw_StatusReg = + inl(devpriv->s_BoardInfos. + ui_Address + 32 + + (64 * b_ModulNbr)); + + /**************************/ + /* Test if frequency stop */ + /**************************/ + + if (dw_StatusReg & 1) { + *pb_Status = 2; + *pb_UDStatus = + (BYTE) ((dw_StatusReg >> + 1) & 3); + + /******************/ + /* Read the value */ + /******************/ + + *pul_ReadValue = + inl(devpriv-> + s_BoardInfos. + ui_Address + 28 + + (64 * b_ModulNbr)); + + if (*pb_UDStatus == 0) { + /*************************/ + /* Test the counter mode */ + /*************************/ + + if ((devpriv->s_ModuleInfo[b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & APCI1710_16BIT_COUNTER) == APCI1710_16BIT_COUNTER) { + /****************************************/ + /* Test if 16-bit counter 1 pulse occur */ + /****************************************/ + + if ((*pul_ReadValue & 0xFFFFU) != 0) { + ui_16BitValue + = + (UINT) + * + pul_ReadValue + & + 0xFFFFU; + *pul_ReadValue + = + (*pul_ReadValue + & + 0xFFFF0000UL) + | + (0xFFFFU + - + ui_16BitValue); + } + + /****************************************/ + /* Test if 16-bit counter 2 pulse occur */ + /****************************************/ + + if ((*pul_ReadValue & 0xFFFF0000UL) != 0) { + ui_16BitValue + = + (UINT) + ( + (*pul_ReadValue + >> + 16) + & + 0xFFFFU); + *pul_ReadValue + = + (*pul_ReadValue + & + 0xFFFFUL) + | + ( + (0xFFFFU - ui_16BitValue) << 16); + } + } else { + if (*pul_ReadValue != 0) { + *pul_ReadValue + = + 0xFFFFFFFFUL + - + *pul_ReadValue; + } + } + } else { + if (*pb_UDStatus == 1) { + /****************************************/ + /* Test if 16-bit counter 2 pulse occur */ + /****************************************/ + + if ((*pul_ReadValue & 0xFFFF0000UL) != 0) { + ui_16BitValue + = + (UINT) + ( + (*pul_ReadValue + >> + 16) + & + 0xFFFFU); + *pul_ReadValue + = + (*pul_ReadValue + & + 0xFFFFUL) + | + ( + (0xFFFFU - ui_16BitValue) << 16); + } + } else { + if (*pb_UDStatus + == 2) { + /****************************************/ + /* Test if 16-bit counter 1 pulse occur */ + /****************************************/ + + if ((*pul_ReadValue & 0xFFFFU) != 0) { + ui_16BitValue + = + (UINT) + * + pul_ReadValue + & + 0xFFFFU; + *pul_ReadValue + = + (*pul_ReadValue + & + 0xFFFF0000UL) + | + (0xFFFFU + - + ui_16BitValue); + } + } + } + } + } else { + *pb_Status = 1; + *pb_UDStatus = 0; + } + } else { + *pb_Status = 0; + *pb_UDStatus = 0; + } + } else { + /***********************************************/ + /* Frequency measurement logic not initialised */ + /***********************************************/ + + DPRINTK("Frequency measurement logic not initialised\n"); + i_ReturnValue = -4; + } + } else { + /****************************************/ + /* Counter not initialised see function */ + /* "i_APCI1710_InitCounter" */ + /****************************************/ + + DPRINTK("Counter not initialised\n"); + i_ReturnValue = -3; + } + } else { + /*************************************************/ + /* The selected module number parameter is wrong */ + /*************************************************/ + + DPRINTK("The selected module number parameter is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h new file mode 100644 index 000000000000..5153cf686658 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.h @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#define APCI1710_16BIT_COUNTER 0x10 +#define APCI1710_32BIT_COUNTER 0x0 +#define APCI1710_QUADRUPLE_MODE 0x0 +#define APCI1710_DOUBLE_MODE 0x3 +#define APCI1710_SIMPLE_MODE 0xF +#define APCI1710_DIRECT_MODE 0x80 +#define APCI1710_HYSTERESIS_ON 0x60 +#define APCI1710_HYSTERESIS_OFF 0x0 +#define APCI1710_INCREMENT 0x60 +#define APCI1710_DECREMENT 0x0 +#define APCI1710_LATCH_COUNTER 0x1 +#define APCI1710_CLEAR_COUNTER 0x0 +#define APCI1710_LOW 0x0 +#define APCI1710_HIGH 0x1 + +/*********************/ +/* Version 0600-0229 */ +/*********************/ +#define APCI1710_HIGH_EDGE_CLEAR_COUNTER 0x0 +#define APCI1710_HIGH_EDGE_LATCH_COUNTER 0x1 +#define APCI1710_LOW_EDGE_CLEAR_COUNTER 0x2 +#define APCI1710_LOW_EDGE_LATCH_COUNTER 0x3 +#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER 0x4 +#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER 0x5 +#define APCI1710_SOURCE_0 0x0 +#define APCI1710_SOURCE_1 0x1 + +#define APCI1710_30MHZ 30 +#define APCI1710_33MHZ 33 +#define APCI1710_40MHZ 40 + +#define APCI1710_ENABLE_LATCH_INT 0x80 +#define APCI1710_DISABLE_LATCH_INT (~APCI1710_ENABLE_LATCH_INT) + +#define APCI1710_INDEX_LATCH_COUNTER 0x10 +#define APCI1710_INDEX_AUTO_MODE 0x8 +#define APCI1710_ENABLE_INDEX 0x4 +#define APCI1710_DISABLE_INDEX (~APCI1710_ENABLE_INDEX) +#define APCI1710_ENABLE_LATCH_AND_CLEAR 0x8 +#define APCI1710_DISABLE_LATCH_AND_CLEAR (~APCI1710_ENABLE_LATCH_AND_CLEAR) +#define APCI1710_SET_LOW_INDEX_LEVEL 0x4 +#define APCI1710_SET_HIGH_INDEX_LEVEL (~APCI1710_SET_LOW_INDEX_LEVEL) +#define APCI1710_INVERT_INDEX_RFERENCE 0x2 +#define APCI1710_DEFAULT_INDEX_RFERENCE (~APCI1710_INVERT_INDEX_RFERENCE) + +#define APCI1710_ENABLE_INDEX_INT 0x1 +#define APCI1710_DISABLE_INDEX_INT (~APCI1710_ENABLE_INDEX_INT) + +#define APCI1710_ENABLE_FREQUENCY 0x4 +#define APCI1710_DISABLE_FREQUENCY (~APCI1710_ENABLE_FREQUENCY) + +#define APCI1710_ENABLE_FREQUENCY_INT 0x8 +#define APCI1710_DISABLE_FREQUENCY_INT (~APCI1710_ENABLE_FREQUENCY_INT) + +#define APCI1710_ENABLE_40MHZ_FREQUENCY 0x40 +#define APCI1710_DISABLE_40MHZ_FREQUENCY (~APCI1710_ENABLE_40MHZ_FREQUENCY) + +#define APCI1710_ENABLE_40MHZ_FILTER 0x80 +#define APCI1710_DISABLE_40MHZ_FILTER (~APCI1710_ENABLE_40MHZ_FILTER) + +#define APCI1710_ENABLE_COMPARE_INT 0x2 +#define APCI1710_DISABLE_COMPARE_INT (~APCI1710_ENABLE_COMPARE_INT) + +#define APCI1710_ENABLE_INDEX_ACTION 0x20 +#define APCI1710_DISABLE_INDEX_ACTION (~APCI1710_ENABLE_INDEX_ACTION) +#define APCI1710_REFERENCE_HIGH 0x40 +#define APCI1710_REFERENCE_LOW (~APCI1710_REFERENCE_HIGH) + +#define APCI1710_TOR_GATE_LOW 0x40 +#define APCI1710_TOR_GATE_HIGH (~APCI1710_TOR_GATE_LOW) + +/* INSN CONFIG */ +#define APCI1710_INCCPT_INITCOUNTER 100 +#define APCI1710_INCCPT_COUNTERAUTOTEST 101 +#define APCI1710_INCCPT_INITINDEX 102 +#define APCI1710_INCCPT_INITREFERENCE 103 +#define APCI1710_INCCPT_INITEXTERNALSTROBE 104 +#define APCI1710_INCCPT_INITCOMPARELOGIC 105 +#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT 106 + +/* INSN READ */ +#define APCI1710_INCCPT_READLATCHREGISTERSTATUS 200 +#define APCI1710_INCCPT_READLATCHREGISTERVALUE 201 +#define APCI1710_INCCPT_READ16BITCOUNTERVALUE 202 +#define APCI1710_INCCPT_READ32BITCOUNTERVALUE 203 +#define APCI1710_INCCPT_GETINDEXSTATUS 204 +#define APCI1710_INCCPT_GETREFERENCESTATUS 205 +#define APCI1710_INCCPT_GETUASSTATUS 206 +#define APCI1710_INCCPT_GETCBSTATUS 207 +#define APCI1710_INCCPT_GET16BITCBSTATUS 208 +#define APCI1710_INCCPT_GETUDSTATUS 209 +#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS 210 +#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT 211 +#define APCI1710_INCCPT_READINTERRUPT 212 + +/* INSN BITS */ +#define APCI1710_INCCPT_CLEARCOUNTERVALUE 300 +#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE 301 +#define APCI1710_INCCPT_SETINPUTFILTER 302 +#define APCI1710_INCCPT_LATCHCOUNTER 303 +#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE 304 +#define APCI1710_INCCPT_SETDIGITALCHLON 305 +#define APCI1710_INCCPT_SETDIGITALCHLOFF 306 + +/* INSN WRITE */ +#define APCI1710_INCCPT_ENABLELATCHINTERRUPT 400 +#define APCI1710_INCCPT_DISABLELATCHINTERRUPT 401 +#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE 402 +#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE 403 +#define APCI1710_INCCPT_ENABLEINDEX 404 +#define APCI1710_INCCPT_DISABLEINDEX 405 +#define APCI1710_INCCPT_ENABLECOMPARELOGIC 406 +#define APCI1710_INCCPT_DISABLECOMPARELOGIC 407 +#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT 408 +#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT 409 + +/************ Main Functions *************/ +INT i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int * data); + +INT i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, struct comedi_subdevice * s, + struct comedi_insn *insn, unsigned int * data); + +INT i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, struct comedi_subdevice * s, + struct comedi_insn *insn, unsigned int * data); + +INT i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, struct comedi_subdevice * s, + struct comedi_insn *insn, unsigned int * data); + +/*********** Supplementary Functions********/ + +/* INSN CONFIG */ +INT i_APCI1710_InitCounter(struct comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_CounterRange, + BYTE b_FirstCounterModus, + BYTE b_FirstCounterOption, + BYTE b_SecondCounterModus, + BYTE b_SecondCounterOption); + +INT i_APCI1710_CounterAutoTest(struct comedi_device *dev, PBYTE pb_TestStatus); + +INT i_APCI1710_InitIndex(struct comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_ReferenceAction, + BYTE b_IndexOperation, BYTE b_AutoMode, + BYTE b_InterruptEnable); + +INT i_APCI1710_InitReference(struct comedi_device *dev, + BYTE b_ModulNbr, BYTE b_ReferenceLevel); + +INT i_APCI1710_InitExternalStrobe(struct comedi_device *dev, + BYTE b_ModulNbr, BYTE b_ExternalStrobe, + BYTE b_ExternalStrobeLevel); + +INT i_APCI1710_InitCompareLogic(struct comedi_device *dev, + BYTE b_ModulNbr, UINT ui_CompareValue); + +INT i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PCIInputClock, + BYTE b_TimingUnity, + ULONG ul_TimingInterval, + PULONG pul_RealTimingInterval); + +/* INSN BITS */ +INT i_APCI1710_ClearCounterValue(struct comedi_device *dev, BYTE b_ModulNbr); + +INT i_APCI1710_ClearAllCounterValue(struct comedi_device *dev); + +INT i_APCI1710_SetInputFilter(struct comedi_device *dev, + BYTE b_ModulNbr, BYTE b_PCIInputClock, + BYTE b_Filter); + +INT i_APCI1710_LatchCounter(struct comedi_device *dev, + BYTE b_ModulNbr, BYTE b_LatchReg); + +INT i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_SourceSelection); + +INT i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, BYTE b_ModulNbr); + +INT i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, BYTE b_ModulNbr); + +/* INSN WRITE */ +INT i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr); + +INT i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, BYTE b_ModulNbr); + +INT i_APCI1710_Write16BitCounterValue(struct comedi_device *dev, + BYTE b_ModulNbr, BYTE b_SelectedCounter, + UINT ui_WriteValue); + +INT i_APCI1710_Write32BitCounterValue(struct comedi_device *dev, + BYTE b_ModulNbr, ULONG ul_WriteValue); + +INT i_APCI1710_EnableIndex(struct comedi_device *dev, BYTE b_ModulNbr); + +INT i_APCI1710_DisableIndex(struct comedi_device *dev, BYTE b_ModulNbr); + +INT i_APCI1710_EnableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr); + +INT i_APCI1710_DisableCompareLogic(struct comedi_device *dev, BYTE b_ModulNbr); + +INT i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_InterruptEnable); + +INT i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev, + BYTE b_ModulNbr); + +/* INSN READ */ +INT i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev, + BYTE b_ModulNbr, BYTE b_LatchReg, + PBYTE pb_LatchStatus); + +INT i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev, + BYTE b_ModulNbr, BYTE b_LatchReg, + PULONG pul_LatchValue); + +INT i_APCI1710_Read16BitCounterValue(struct comedi_device *dev, + BYTE b_ModulNbr, BYTE b_SelectedCounter, + PUINT pui_CounterValue); + +INT i_APCI1710_Read32BitCounterValue(struct comedi_device *dev, + BYTE b_ModulNbr, PULONG pul_CounterValue); + +INT i_APCI1710_GetIndexStatus(struct comedi_device *dev, + BYTE b_ModulNbr, PBYTE pb_IndexStatus); + +INT i_APCI1710_GetReferenceStatus(struct comedi_device *dev, + BYTE b_ModulNbr, PBYTE pb_ReferenceStatus); + +INT i_APCI1710_GetUASStatus(struct comedi_device *dev, + BYTE b_ModulNbr, PBYTE pb_UASStatus); + +INT i_APCI1710_GetCBStatus(struct comedi_device *dev, + BYTE b_ModulNbr, PBYTE pb_CBStatus); + +INT i_APCI1710_Get16BitCBStatus(struct comedi_device *dev, + BYTE b_ModulNbr, PBYTE pb_CBStatusCounter0, + PBYTE pb_CBStatusCounter1); + +INT i_APCI1710_GetUDStatus(struct comedi_device *dev, + BYTE b_ModulNbr, PBYTE pb_UDStatus); + +INT i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev, + BYTE b_ModulNbr, PBYTE pb_UDStatus); + +INT i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev, + BYTE b_ModulNbr, + PBYTE pb_Status, PBYTE pb_UDStatus, + PULONG pul_ReadValue); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c new file mode 100644 index 000000000000..3ac6a264ef54 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c @@ -0,0 +1,861 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : API APCI1710 | Compiler : gcc | + | Module name : Inp_CPT.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 pulse encoder module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "APCI1710_Inp_cpt.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitPulseEncoder | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PulseEncoderNbr, | +| BYTE_ b_InputLevelSelection, | +| BYTE_ b_TriggerOutputAction, | +| ULONG_ ul_StartValue) | ++----------------------------------------------------------------------------+ +| Task : Configure the pulse encoder operating mode selected via| +| b_ModulNbr and b_PulseEncoderNbr. The pulse encoder | +| after each pulse decrement the counter value from 1. | +| | +| You must calling this function be for you call any | +| other function witch access of pulse encoders. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_PulseEncoderNbr : Pulse encoder selection | +| (0 to 3) | +| BYTE_ b_InputLevelSelection : Input level selection | +| (0 or 1) | +| 0 : Set pulse encoder| +| count the the low| +| level pulse. | +| 1 : Set pulse encoder| +| count the the | +| high level pulse.| +| BYTE_ b_TriggerOutputAction : Digital TRIGGER output | +| action | +| 0 : No action | +| 1 : Set the trigger | +| output to "1" | +| (high) after the | +| passage from 1 to| +| 0 from pulse | +| encoder. | +| 2 : Set the trigger | +| output to "0" | +| (low) after the | +| passage from 1 to| +| 0 from pulse | +| encoder | +| ULONG_ ul_StartValue : Pulse encoder start value| +| (1 to 4294967295) + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_PulseEncoderNbr =(BYTE) data[0]; + b_InputLevelSelection =(BYTE) data[1]; + b_TriggerOutputAction =(BYTE) data[2]; + ul_StartValue =(ULONG) data[3]; + | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module is not a pulse encoder module | +| -3: Pulse encoder selection is wrong | +| -4: Input level selection is wrong | +| -5: Digital TRIGGER output action selection is wrong | +| -6: Pulse encoder start value is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_IntRegister; + + BYTE b_ModulNbr; + BYTE b_PulseEncoderNbr; + BYTE b_InputLevelSelection; + BYTE b_TriggerOutputAction; + ULONG ul_StartValue; + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_PulseEncoderNbr = (BYTE) data[0]; + b_InputLevelSelection = (BYTE) data[1]; + b_TriggerOutputAction = (BYTE) data[2]; + ul_StartValue = (ULONG) data[3]; + + i_ReturnValue = insn->n; + + /***********************************/ + /* Test the selected module number */ + /***********************************/ + + if (b_ModulNbr <= 3) { + /*************************/ + /* Test if pulse encoder */ + /*************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + APCI1710_PULSE_ENCODER) == + APCI1710_PULSE_ENCODER) { + /******************************************/ + /* Test the selected pulse encoder number */ + /******************************************/ + + if (b_PulseEncoderNbr <= 3) { + /************************/ + /* Test the input level */ + /************************/ + + if ((b_InputLevelSelection == 0) + || (b_InputLevelSelection == 1)) { + /*******************************************/ + /* Test the ouput TRIGGER action selection */ + /*******************************************/ + + if ((b_TriggerOutputAction <= 2) + || (b_PulseEncoderNbr > 0)) { + if (ul_StartValue > 1) { + + dw_IntRegister = + inl(devpriv-> + s_BoardInfos. + ui_Address + + 20 + + (64 * b_ModulNbr)); + + /***********************/ + /* Set the start value */ + /***********************/ + + outl(ul_StartValue, + devpriv-> + s_BoardInfos. + ui_Address + + (b_PulseEncoderNbr + * 4) + + (64 * b_ModulNbr)); + + /***********************/ + /* Set the input level */ + /***********************/ + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister = + (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister & + (0xFFFFFFFFUL - + (1UL << (8 + b_PulseEncoderNbr)))) | ((1UL & (~b_InputLevelSelection)) << (8 + b_PulseEncoderNbr)); + + /*******************************/ + /* Test if output trigger used */ + /*******************************/ + + if ((b_TriggerOutputAction > 0) && (b_PulseEncoderNbr > 1)) { + /****************************/ + /* Enable the output action */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + | (1UL + << (4 + b_PulseEncoderNbr)); + + /*********************************/ + /* Set the output TRIGGER action */ + /*********************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + = + (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + & + (0xFFFFFFFFUL + - + (1UL << (12 + b_PulseEncoderNbr)))) | ((1UL & (b_TriggerOutputAction - 1)) << (12 + b_PulseEncoderNbr)); + } else { + /*****************************/ + /* Disable the output action */ + /*****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + & + (0xFFFFFFFFUL + - + (1UL << (4 + b_PulseEncoderNbr))); + } + + /*************************/ + /* Set the configuration */ + /*************************/ + + outl(devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister, + devpriv-> + s_BoardInfos. + ui_Address + + 20 + + (64 * b_ModulNbr)); + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + s_PulseEncoderInfo + [b_PulseEncoderNbr]. + b_PulseEncoderInit + = 1; + } else { + /**************************************/ + /* Pulse encoder start value is wrong */ + /**************************************/ + + DPRINTK("Pulse encoder start value is wrong\n"); + i_ReturnValue = -6; + } + } else { + /****************************************************/ + /* Digital TRIGGER output action selection is wrong */ + /****************************************************/ + + DPRINTK("Digital TRIGGER output action selection is wrong\n"); + i_ReturnValue = -5; + } + } else { + /**********************************/ + /* Input level selection is wrong */ + /**********************************/ + + DPRINTK("Input level selection is wrong\n"); + i_ReturnValue = -4; + } + } else { + /************************************/ + /* Pulse encoder selection is wrong */ + /************************************/ + + DPRINTK("Pulse encoder selection is wrong\n"); + i_ReturnValue = -3; + } + } else { + /********************************************/ + /* The module is not a pulse encoder module */ + /********************************************/ + + DPRINTK("The module is not a pulse encoder module\n"); + i_ReturnValue = -2; + } + } else { + /********************************************/ + /* The module is not a pulse encoder module */ + /********************************************/ + + DPRINTK("The module is not a pulse encoder module\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnablePulseEncoder | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PulseEncoderNbr, | +| BYTE_ b_CycleSelection, | +| BYTE_ b_InterruptHandling) | ++----------------------------------------------------------------------------+ +| Task : Enableor disable the selected pulse encoder (b_PulseEncoderNbr) | +| from selected module (b_ModulNbr). Each input pulse | +| decrement the pulse encoder counter value from 1. | +| If you enabled the interrupt (b_InterruptHandling), a | +| interrupt is generated when the pulse encoder has run | +| down. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_PulseEncoderNbr : Pulse encoder selection | +| (0 to 3) | +| BYTE_ b_CycleSelection : APCI1710_CONTINUOUS: | +| Each time the | +| counting value is set| +| on "0", the pulse | +| encoder load the | +| start value after | +| the next pulse. | +| APCI1710_SINGLE: | +| If the counter is set| +| on "0", the pulse | +| encoder is stopped. | +| BYTE_ b_InterruptHandling : Interrupts can be | +| generated, when the pulse| +| encoder has run down. | +| With this parameter the | +| user decides if | +| interrupts are used or | +| not. | +| APCI1710_ENABLE: | +| Interrupts are enabled | +| APCI1710_DISABLE: | +| Interrupts are disabled + + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_Action =(BYTE) data[0]; + b_PulseEncoderNbr =(BYTE) data[1]; + b_CycleSelection =(BYTE) data[2]; + b_InterruptHandling =(BYTE) data[3];| ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection is wrong | +| -3: Pulse encoder selection is wrong | +| -4: Pulse encoder not initialised. | +| See function "i_APCI1710_InitPulseEncoder" | +| -5: Cycle selection mode is wrong | +| -6: Interrupt handling mode is wrong | +| -7: Interrupt routine not installed. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + BYTE b_ModulNbr; + BYTE b_PulseEncoderNbr; + BYTE b_CycleSelection; + BYTE b_InterruptHandling; + BYTE b_Action; + + i_ReturnValue = insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_Action = (BYTE) data[0]; + b_PulseEncoderNbr = (BYTE) data[1]; + b_CycleSelection = (BYTE) data[2]; + b_InterruptHandling = (BYTE) data[3]; + + /***********************************/ + /* Test the selected module number */ + /***********************************/ + + if (b_ModulNbr <= 3) { + /******************************************/ + /* Test the selected pulse encoder number */ + /******************************************/ + + if (b_PulseEncoderNbr <= 3) { + /*************************************/ + /* Test if pulse encoder initialised */ + /*************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + s_PulseEncoderInfo[b_PulseEncoderNbr]. + b_PulseEncoderInit == 1) { + switch (b_Action) { + + case APCI1710_ENABLE: + /****************************/ + /* Test the cycle selection */ + /****************************/ + + if (b_CycleSelection == + APCI1710_CONTINUOUS + || b_CycleSelection == + APCI1710_SINGLE) { + /*******************************/ + /* Test the interrupt handling */ + /*******************************/ + + if (b_InterruptHandling == + APCI1710_ENABLE + || b_InterruptHandling + == APCI1710_DISABLE) { + /******************************/ + /* Test if interrupt not used */ + /******************************/ + + if (b_InterruptHandling + == + APCI1710_DISABLE) + { + /*************************/ + /* Disable the interrupt */ + /*************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + & + (0xFFFFFFFFUL + - + (1UL << b_PulseEncoderNbr)); + } else { + + /************************/ + /* Enable the interrupt */ + /************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister + | (1UL + << + b_PulseEncoderNbr); + devpriv->tsk_Current = current; // Save the current process task structure + + } + + if (i_ReturnValue >= 0) { + /***********************************/ + /* Enable or disable the interrupt */ + /***********************************/ + + outl(devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_SetRegister, + devpriv-> + s_BoardInfos. + ui_Address + + 20 + + (64 * b_ModulNbr)); + + /****************************/ + /* Enable the pulse encoder */ + /****************************/ + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister + = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister + | (1UL + << + b_PulseEncoderNbr); + + /**********************/ + /* Set the cycle mode */ + /**********************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister + = + (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister + & + (0xFFFFFFFFUL + - + (1 << (b_PulseEncoderNbr + 4)))) | ((b_CycleSelection & 1UL) << (4 + b_PulseEncoderNbr)); + + /****************************/ + /* Enable the pulse encoder */ + /****************************/ + + outl(devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister, + devpriv-> + s_BoardInfos. + ui_Address + + 16 + + (64 * b_ModulNbr)); + } + } else { + /************************************/ + /* Interrupt handling mode is wrong */ + /************************************/ + + DPRINTK("Interrupt handling mode is wrong\n"); + i_ReturnValue = -6; + } + } else { + /*********************************/ + /* Cycle selection mode is wrong */ + /*********************************/ + + DPRINTK("Cycle selection mode is wrong\n"); + i_ReturnValue = -5; + } + break; + + case APCI1710_DISABLE: + devpriv->s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister = + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister & + (0xFFFFFFFFUL - + (1UL << b_PulseEncoderNbr)); + + /*****************************/ + /* Disable the pulse encoder */ + /*****************************/ + + outl(devpriv->s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_ControlRegister, + devpriv->s_BoardInfos. + ui_Address + 16 + + (64 * b_ModulNbr)); + + break; + } // switch End + + } else { + /*********************************/ + /* Pulse encoder not initialised */ + /*********************************/ + + DPRINTK("Pulse encoder not initialised\n"); + i_ReturnValue = -4; + } + } else { + /************************************/ + /* Pulse encoder selection is wrong */ + /************************************/ + + DPRINTK("Pulse encoder selection is wrong\n"); + i_ReturnValue = -3; + } + } else { + /*****************************/ + /* Module selection is wrong */ + /*****************************/ + + DPRINTK("Module selection is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadPulseEncoderStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PulseEncoderNbr, | +| PBYTE_ pb_Status) | ++----------------------------------------------------------------------------+ +| Task APCI1710_PULSEENCODER_READ : Reads the pulse encoder status + and valuefrom selected pulse | +| encoder (b_PulseEncoderNbr) from selected module | +| (b_ModulNbr). | ++----------------------------------------------------------------------------+ + BYTE b_Type; data[0] + APCI1710_PULSEENCODER_WRITE + Writes a 32-bit value (ul_WriteValue) into the selected| +| pulse encoder (b_PulseEncoderNbr) from selected module | +| (b_ModulNbr). This operation set the new start pulse | +| encoder value. + APCI1710_PULSEENCODER_READ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| CRAREF() BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| data[1] BYTE_ b_PulseEncoderNbr : Pulse encoder selection | +| (0 to 3) + APCI1710_PULSEENCODER_WRITE + data[2] ULONG_ ul_WriteValue : 32-bit value to be | +| written | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_Status : Pulse encoder status. | +| 0 : No overflow occur| +| 1 : Overflow occur + PULONG_ pul_ReadValue : Pulse encoder value | | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection is wrong | +| -3: Pulse encoder selection is wrong | +| -4: Pulse encoder not initialised. | +| See function "i_APCI1710_InitPulseEncoder" | ++----------------------------------------------------------------------------+ +*/ + +/*_INT_ i_APCI1710_ReadPulseEncoderStatus (BYTE_ b_BoardHandle, + BYTE_ b_ModulNbr, + BYTE_ b_PulseEncoderNbr, + + PBYTE_ pb_Status) + */ +INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusRegister; + BYTE b_ModulNbr; + BYTE b_PulseEncoderNbr; + PBYTE pb_Status; + BYTE b_Type; + PULONG pul_ReadValue; + ULONG ul_WriteValue; + + i_ReturnValue = insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_Type = (BYTE) data[0]; + b_PulseEncoderNbr = (BYTE) data[1]; + pb_Status = (PBYTE) & data[0]; + pul_ReadValue = (PULONG) & data[1]; + + /***********************************/ + /* Test the selected module number */ + /***********************************/ + + if (b_ModulNbr <= 3) { + /******************************************/ + /* Test the selected pulse encoder number */ + /******************************************/ + + if (b_PulseEncoderNbr <= 3) { + /*************************************/ + /* Test if pulse encoder initialised */ + /*************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + s_PulseEncoderInfo[b_PulseEncoderNbr]. + b_PulseEncoderInit == 1) { + + switch (b_Type) { + case APCI1710_PULSEENCODER_READ: + /****************************/ + /* Read the status register */ + /****************************/ + + dw_StatusRegister = + inl(devpriv->s_BoardInfos. + ui_Address + 16 + + (64 * b_ModulNbr)); + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister | + dw_StatusRegister; + + *pb_Status = + (BYTE) (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister >> (1 + + b_PulseEncoderNbr)) & 1; + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister = + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_PulseEncoderModuleInfo. + dw_StatusRegister & + (0xFFFFFFFFUL - (1 << (1 + + b_PulseEncoderNbr))); + + /******************/ + /* Read the value */ + /******************/ + + *pul_ReadValue = + inl(devpriv->s_BoardInfos. + ui_Address + + (4 * b_PulseEncoderNbr) + + (64 * b_ModulNbr)); + break; + + case APCI1710_PULSEENCODER_WRITE: + ul_WriteValue = (ULONG) data[2]; + /*******************/ + /* Write the value */ + /*******************/ + + outl(ul_WriteValue, + devpriv->s_BoardInfos. + ui_Address + + (4 * b_PulseEncoderNbr) + + (64 * b_ModulNbr)); + + } //end of switch + } else { + /*********************************/ + /* Pulse encoder not initialised */ + /*********************************/ + + DPRINTK("Pulse encoder not initialised\n"); + i_ReturnValue = -4; + } + } else { + /************************************/ + /* Pulse encoder selection is wrong */ + /************************************/ + + DPRINTK("Pulse encoder selection is wrong\n"); + i_ReturnValue = -3; + } + } else { + /*****************************/ + /* Module selection is wrong */ + /*****************************/ + + DPRINTK("Module selection is wrong\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + + data[0] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters.ui_Read].b_OldModuleMask; + data[1] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters.ui_Read].ul_OldInterruptMask; + data[2] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; + + /***************************/ + /* Increment the read FIFO */ + /***************************/ + + devpriv->s_InterruptParameters. + ui_Read = (devpriv-> + s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT; + + return insn->n; + +} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h new file mode 100644 index 000000000000..28252873e862 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#define APCI1710_SINGLE 0 +#define APCI1710_CONTINUOUS 1 + +#define APCI1710_PULSEENCODER_READ 0 +#define APCI1710_PULSEENCODER_WRITE 1 + +INT i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +INT i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + +/* + * READ PULSE ENCODER FUNCTIONS + */ +INT i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + +/* + * WRITE PULSE ENCODER FUNCTIONS + */ +INT i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c new file mode 100644 index 000000000000..5ddd092a656a --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c @@ -0,0 +1,3588 @@ +/** +@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 : PWM.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 Wulse wide modulation module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +-----------------------------------------------------------------------+ + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "APCI1710_Pwm.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name :INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, +struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Pwm Init and Get Pwm Initialisation | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigPWM(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_ConfigType; + INT i_ReturnValue = 0; + b_ConfigType = CR_CHAN(insn->chanspec); + + switch (b_ConfigType) { + case APCI1710_PWM_INIT: + i_ReturnValue = i_APCI1710_InitPWM(dev, (BYTE) CR_AREF(insn->chanspec), // b_ModulNbr + (BYTE) data[0], //b_PWM + (BYTE) data[1], // b_ClockSelection + (BYTE) data[2], // b_TimingUnit + (ULONG) data[3], //ul_LowTiming + (ULONG) data[4], //ul_HighTiming + (PULONG) & data[0], //pul_RealLowTiming + (PULONG) & data[1] //pul_RealHighTiming + ); + break; + + case APCI1710_PWM_GETINITDATA: + i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (BYTE) CR_AREF(insn->chanspec), // b_ModulNbr + (BYTE) data[0], //b_PWM + (PBYTE) & data[0], //pb_TimingUnit + (PULONG) & data[1], //pul_LowTiming + (PULONG) & data[2], //pul_HighTiming + (PBYTE) & data[3], // pb_StartLevel + (PBYTE) & data[4], // pb_StopMode + (PBYTE) & data[5], // pb_StopLevel + (PBYTE) & data[6], // pb_ExternGate + (PBYTE) & data[7], // pb_InterruptEnable + (PBYTE) & data[8] // pb_Enable + ); + break; + + default: + printk(" Config Parameter Wrong\n"); + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitPWM | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| BYTE_ b_ClockSelection, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_LowTiming, | +| ULONG_ ul_HighTiming, | +| PULONG_ pul_RealLowTiming, | +| PULONG_ pul_RealHighTiming) | ++----------------------------------------------------------------------------+ +| Task : Configure the selected PWM (b_PWM) from selected module| +| (b_ModulNbr). The ul_LowTiming, ul_HighTiming and | +| ul_TimingUnit determine the low/high timing base for | +| the period. pul_RealLowTiming, pul_RealHighTiming | +| return the real timing value. | +| You must calling this function be for you call any | +| other function witch access of the PWM. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure| +| (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1). | +| BYTE_ b_ClockSelection : Selection from PCI bus | +| clock | +| - APCI1710_30MHZ : | +| The PC have a 30 MHz | +| PCI bus clock | +| - APCI1710_33MHZ : | +| The PC have a 33 MHz | +| PCI bus clock | +| - APCI1710_40MHZ | +| The APCI-1710 have a | +| integrated 40Mhz | +| quartz. | +| BYTE_ b_TimingUnit : Base timing Unit (0 to 4) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| ULONG_ ul_LowTiming : Low base timing value. | +| ULONG_ ul_HighTiming : High base timing value. | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_RealLowTiming : Real low base timing | +| value. | +| PULONG_ pul_RealHighTiming : Real high base 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 PWM module | +| -4: PWM selection is wrong | +| -5: The selected input clock is wrong | +| -6: Timing Unit selection is wrong | +| -7: Low base timing selection is wrong | +| -8: High base timing selection is wrong | +| -9: You can not used the 40MHz clock selection with | +| this board | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InitPWM(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_ClockSelection, + BYTE b_TimingUnit, + ULONG ul_LowTiming, + ULONG ul_HighTiming, + PULONG pul_RealLowTiming, PULONG pul_RealHighTiming) +{ + INT i_ReturnValue = 0; + ULONG ul_LowTimerValue = 0; + ULONG ul_HighTimerValue = 0; + DWORD dw_Command; + double d_RealLowTiming = 0; + double d_RealHighTiming = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /******************/ + /* Test the clock */ + /******************/ + + if ((b_ClockSelection == APCI1710_30MHZ) || + (b_ClockSelection == APCI1710_33MHZ) || + (b_ClockSelection == APCI1710_40MHZ)) { + /************************/ + /* Test the timing unit */ + /************************/ + + if (b_TimingUnit <= 4) { + /*********************************/ + /* Test the low timing selection */ + /*********************************/ + + if (((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 266) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571230650UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571230UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= 9UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 242) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 519691043UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 519691UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 520UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= 8UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 200) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429496729UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429496UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 7UL))) { + /**********************************/ + /* Test the High timing selection */ + /**********************************/ + + if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) { + /**************************/ + /* Test the board version */ + /**************************/ + + if (((b_ClockSelection == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_ClockSelection != APCI1710_40MHZ)) { + + /************************************/ + /* Calculate the low division fator */ + /************************************/ + + fpu_begin + (); + + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (0.00025 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (0.00025 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (0.25 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + ( + (double) + 0.25 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + ul_LowTiming + * + (250.0 + * + b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250.0 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (250.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + ( + (ul_LowTiming + * + 60) + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60; + d_RealLowTiming + = + ( + (double) + ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60.0; + + if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealLowTiming + 0.5)) { + *pul_RealLowTiming + = + *pul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + } + + /*************************************/ + /* Calculate the high division fator */ + /*************************************/ + + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (0.00025 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (0.00025 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (0.25 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + ( + (double) + 0.25 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + ul_HighTiming + * + (250.0 + * + b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250.0 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (250.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + ( + (ul_HighTiming + * + 60) + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + *pul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60; + d_RealHighTiming + = + ( + (double) + ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60.0; + + if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealHighTiming + 0.5)) { + *pul_RealHighTiming + = + *pul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + } + + fpu_end(); + /****************************/ + /* Save the clock selection */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + b_ClockSelection + = + b_ClockSelection; + + /************************/ + /* Save the timing unit */ + /************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + b_TimingUnit + = + b_TimingUnit; + + /****************************/ + /* Save the low base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + d_LowTiming + = + d_RealLowTiming; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + ul_RealLowTiming + = + *pul_RealLowTiming; + + /****************************/ + /* Save the high base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + d_HighTiming + = + d_RealHighTiming; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + ul_RealHighTiming + = + *pul_RealHighTiming; + + /************************/ + /* Write the low timing */ + /************************/ + + outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /*************************/ + /* Write the high timing */ + /*************************/ + + outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /***************************/ + /* Set the clock selection */ + /***************************/ + + dw_Command + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 8 + + + (20 * b_PWM) + (64 * b_ModulNbr)); + + dw_Command + = + dw_Command + & + 0x7F; + + if (b_ClockSelection == APCI1710_40MHZ) { + dw_Command + = + dw_Command + | + 0x80; + } + + /***************************/ + /* Set the clock selection */ + /***************************/ + + outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /*************/ + /* PWM init. */ + /*************/ + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + b_PWMInit + = + 1; + } else { + /***************************************************/ + /* You can not used the 40MHz clock selection with */ + /* this board */ + /***************************************************/ + DPRINTK("You can not used the 40MHz clock selection with this board\n"); + i_ReturnValue + = + -9; + } + } else { + /***************************************/ + /* High base timing selection is wrong */ + /***************************************/ + DPRINTK("High base timing selection is wrong\n"); + i_ReturnValue = + -8; + } + } else { + /**************************************/ + /* Low base timing selection is wrong */ + /**************************************/ + DPRINTK("Low base timing selection is wrong\n"); + i_ReturnValue = -7; + } + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + else { + /**********************************/ + /* Timing unit selection is wrong */ + /**********************************/ + DPRINTK("Timing unit selection is wrong\n"); + i_ReturnValue = -6; + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + } // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) + else { + /*******************************/ + /* The selected clock is wrong */ + /*******************************/ + DPRINTK("The selected clock is wrong\n"); + i_ReturnValue = -5; + } // if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM 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_GetPWMInitialisation | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| PBYTE_ pb_TimingUnit, | +| PULONG_ pul_LowTiming, | +| PULONG_ pul_HighTiming, | +| PBYTE_ pb_StartLevel, | +| PBYTE_ pb_StopMode, | +| PBYTE_ pb_StopLevel, | +| PBYTE_ pb_ExternGate, | +| PBYTE_ pb_InterruptEnable, | +| PBYTE_ pb_Enable) | ++----------------------------------------------------------------------------+ +| Task : Return the PWM (b_PWM) initialisation from selected | +| module (b_ModulNbr). You must calling the | +| "i_APCI1710_InitPWM" function be for you call this | +| function. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TimingUnit : Base timing Unit (0 to 4) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| PULONG_ pul_LowTiming : Low base timing value. | +| PULONG_ pul_HighTiming : High base timing value. | +| PBYTE_ pb_StartLevel : Start period level | +| selection | +| 0 : The period start | +| with a low level | +| 1 : The period start | +| with a high level| +| PBYTE_ pb_StopMode : Stop mode selection | +| 0 : The PWM is stopped | +| directly after the | +| "i_APCI1710_DisablePWM"| +| function and break the| +| last period | +| 1 : After the | +| "i_APCI1710_DisablePWM"| +| function the PWM is | +| stopped at the end | +| from last period cycle| +| PBYTE_ pb_StopLevel : Stop PWM level selection | +| 0 : The output signal | +| keep the level after| +| the | +| "i_APCI1710_DisablePWM"| +| function | +| 1 : The output signal is| +| set to low after the| +| "i_APCI1710_DisablePWM"| +| function | +| 2 : The output signal is| +| set to high after | +| the | +| "i_APCI1710_DisablePWM"| +| function | +| PBYTE_ pb_ExternGate : Extern gate action | +| selection | +| 0 : Extern gate signal | +| not used. | +| 1 : Extern gate signal | +| used. | +| PBYTE_ pb_InterruptEnable : Enable or disable the PWM | +| interrupt. | +| - APCI1710_ENABLE : | +| Enable the PWM interrupt| +| A interrupt occur after | +| each period | +| - APCI1710_DISABLE : | +| Disable the PWM | +| interrupt | +| PBYTE_ pb_Enable : Indicate if the PWM is | +| enabled or no | +| 0 : PWM not enabled | +| 1 : PWM enabled | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_GetPWMInitialisation(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_PWM, + PBYTE pb_TimingUnit, + PULONG pul_LowTiming, + PULONG pul_HighTiming, + PBYTE pb_StartLevel, + PBYTE pb_StopMode, + PBYTE pb_StopLevel, + PBYTE pb_ExternGate, PBYTE pb_InterruptEnable, PBYTE pb_Enable) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_Command; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + /***********************/ + /* Read the low timing */ + /***********************/ + + *pul_LowTiming = + inl(devpriv->s_BoardInfos. + ui_Address + 0 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + /************************/ + /* Read the high timing */ + /************************/ + + *pul_HighTiming = + inl(devpriv->s_BoardInfos. + ui_Address + 4 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + /********************/ + /* Read the command */ + /********************/ + + dw_Command = inl(devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + *pb_StartLevel = + (BYTE) ((dw_Command >> 5) & 1); + *pb_StopMode = + (BYTE) ((dw_Command >> 0) & 1); + *pb_StopLevel = + (BYTE) ((dw_Command >> 1) & 1); + *pb_ExternGate = + (BYTE) ((dw_Command >> 4) & 1); + *pb_InterruptEnable = + (BYTE) ((dw_Command >> 3) & 1); + + if (*pb_StopLevel) { + *pb_StopLevel = + *pb_StopLevel + + (BYTE) ((dw_Command >> + 2) & 1); + } + + /********************/ + /* Read the command */ + /********************/ + + dw_Command = inl(devpriv->s_BoardInfos. + ui_Address + 8 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + *pb_Enable = + (BYTE) ((dw_Command >> 0) & 1); + + *pb_TimingUnit = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo[b_PWM].b_TimingUnit; + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM 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_InsnWritePWM(struct comedi_device *dev, +struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Pwm Enable Disable and Set New Timing | ++----------------------------------------------------------------------------+ +| Input Parameters : ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWritePWM(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_WriteType; + INT i_ReturnValue = 0; + b_WriteType = CR_CHAN(insn->chanspec); + + switch (b_WriteType) { + case APCI1710_PWM_ENABLE: + i_ReturnValue = i_APCI1710_EnablePWM(dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], + (BYTE) data[2], + (BYTE) data[3], (BYTE) data[4], (BYTE) data[5]); + break; + + case APCI1710_PWM_DISABLE: + i_ReturnValue = i_APCI1710_DisablePWM(dev, + (BYTE) CR_AREF(insn->chanspec), (BYTE) data[0]); + break; + + case APCI1710_PWM_NEWTIMING: + i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev, + (BYTE) CR_AREF(insn->chanspec), + (BYTE) data[0], + (BYTE) data[1], (ULONG) data[2], (ULONG) data[3]); + break; + + default: + printk("Write Config Parameter Wrong\n"); + } + + if (i_ReturnValue >= 0) + i_ReturnValue = insn->n; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnablePWM | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| BYTE_ b_StartLevel, | +| BYTE_ b_StopMode, | +| BYTE_ b_StopLevel, | +| BYTE_ b_ExternGate, | +| BYTE_ b_InterruptEnable) | ++----------------------------------------------------------------------------+ +| Task : Enable the selected PWM (b_PWM) from selected module | +| (b_ModulNbr). You must calling the "i_APCI1710_InitPWM"| +| function be for you call this function. | +| If you enable the PWM interrupt, the PWM generate a | +| interrupt after each period. | +| See function "i_APCI1710_SetBoardIntRoutineX" and the | +| Interrupt mask description chapter. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number | +| (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1) | +| BYTE_ b_StartLevel : Start period level selection | +| 0 : The period start with a | +| low level | +| 1 : The period start with a | +| high level | +| BYTE_ b_StopMode : Stop mode selection | +| 0 : The PWM is stopped | +| directly after the | +| "i_APCI1710_DisablePWM" | +| function and break the | +| last period | +| 1 : After the | +| "i_APCI1710_DisablePWM" | +| function the PWM is | +| stopped at the end from| +| last period cycle. | +| BYTE_ b_StopLevel : Stop PWM level selection | +| 0 : The output signal keep | +| the level after the | +| "i_APCI1710_DisablePWM" | +| function | +| 1 : The output signal is set| +| to low after the | +| "i_APCI1710_DisablePWM" | +| function | +| 2 : The output signal is set| +| to high after the | +| "i_APCI1710_DisablePWM" | +| function | +| BYTE_ b_ExternGate : Extern gate action selection | +| 0 : Extern gate signal not | +| used. | +| 1 : Extern gate signal used.| +| BYTE_ b_InterruptEnable : Enable or disable the PWM | +| interrupt. | +| - APCI1710_ENABLE : | +| Enable the PWM interrupt | +| A interrupt occur after | +| each period | +| - APCI1710_DISABLE : | +| Disable the PWM 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 PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | +| -6: PWM start level selection is wrong | +| -7: PWM stop mode selection is wrong | +| -8: PWM stop level selection is wrong | +| -9: Extern gate signal selection is wrong | +| -10: Interrupt parameter is wrong | +| -11: Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_EnablePWM(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_StartLevel, + BYTE b_StopMode, + BYTE b_StopLevel, BYTE b_ExternGate, BYTE b_InterruptEnable) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_Command; + + devpriv->tsk_Current = current; // Save the current process task structure + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + /**********************************/ + /* Test the start level selection */ + /**********************************/ + + if (b_StartLevel <= 1) { + /**********************/ + /* Test the stop mode */ + /**********************/ + + if (b_StopMode <= 1) { + /***********************/ + /* Test the stop level */ + /***********************/ + + if (b_StopLevel <= 2) { + /*****************************/ + /* Test the extern gate mode */ + /*****************************/ + + if (b_ExternGate + <= 1) { + /*****************************/ + /* Test the interrupt action */ + /*****************************/ + + if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) { + /******************************************/ + /* Test if interrupt function initialised */ + /******************************************/ + + /********************/ + /* Read the command */ + /********************/ + + dw_Command + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 8 + + + (20 * b_PWM) + (64 * b_ModulNbr)); + + dw_Command + = + dw_Command + & + 0x80; + + /********************/ + /* Make the command */ + /********************/ + + dw_Command + = + dw_Command + | + b_StopMode + | + (b_InterruptEnable + << + 3) + | + (b_ExternGate + << + 4) + | + (b_StartLevel + << + 5); + + if (b_StopLevel & 3) { + dw_Command + = + dw_Command + | + 2; + + if (b_StopLevel & 2) { + dw_Command + = + dw_Command + | + 4; + } + } + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + b_InterruptEnable + = + b_InterruptEnable; + + /*******************/ + /* Set the command */ + /*******************/ + + outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /******************/ + /* Enable the PWM */ + /******************/ + outl(1, devpriv->s_BoardInfos.ui_Address + 12 + (20 * b_PWM) + (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 + = + -10; + } // if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) + } // if (b_ExternGate >= 0 && b_ExternGate <= 1) + else { + /*****************************************/ + /* Extern gate signal selection is wrong */ + /*****************************************/ + DPRINTK("Extern gate signal selection is wrong\n"); + i_ReturnValue + = + -9; + } // if (b_ExternGate >= 0 && b_ExternGate <= 1) + } // if (b_StopLevel >= 0 && b_StopLevel <= 2) + else { + /*************************************/ + /* PWM stop level selection is wrong */ + /*************************************/ + DPRINTK("PWM stop level selection is wrong\n"); + i_ReturnValue = + -8; + } // if (b_StopLevel >= 0 && b_StopLevel <= 2) + } // if (b_StopMode >= 0 && b_StopMode <= 1) + else { + /************************************/ + /* PWM stop mode selection is wrong */ + /************************************/ + DPRINTK("PWM stop mode selection is wrong\n"); + i_ReturnValue = -7; + } // if (b_StopMode >= 0 && b_StopMode <= 1) + } // if (b_StartLevel >= 0 && b_StartLevel <= 1) + else { + /**************************************/ + /* PWM start level selection is wrong */ + /**************************************/ + DPRINTK("PWM start level selection is wrong\n"); + i_ReturnValue = -6; + } // if (b_StartLevel >= 0 && b_StartLevel <= 1) + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM 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_DisablePWM (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM) | ++----------------------------------------------------------------------------+ +| Task : Disable the selected PWM (b_PWM) from selected module | +| (b_ModulNbr). The output signal level depend of the | +| initialisation by the "i_APCI1710_EnablePWM". | +| See the b_StartLevel, b_StopMode and b_StopLevel | +| parameters from this function. | ++----------------------------------------------------------------------------+ +| Input Parameters :BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1) | ++----------------------------------------------------------------------------+ +| 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 PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | +| -6: PWM not enabled see function | +| "i_APCI1710_EnablePWM" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_DisablePWM(struct comedi_device * dev, BYTE b_ModulNbr, BYTE b_PWM) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + /***********************/ + /* Test if PWM enabled */ + /***********************/ + + if (dw_Status & 0x1) { + /*******************/ + /* Disable the PWM */ + /*******************/ + outl(0, devpriv->s_BoardInfos. + ui_Address + 12 + + (20 * b_PWM) + + (64 * b_ModulNbr)); + } // if (dw_Status & 0x1) + else { + /*******************/ + /* PWM not enabled */ + /*******************/ + DPRINTK("PWM not enabled\n"); + i_ReturnValue = -6; + } // if (dw_Status & 0x1) + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK(" PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM 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_SetNewPWMTiming | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| BYTE_ b_ClockSelection, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_LowTiming, | +| ULONG_ ul_HighTiming) | ++----------------------------------------------------------------------------+ +| Task : Set a new timing. The ul_LowTiming, ul_HighTiming and | +| ul_TimingUnit determine the low/high timing base for | +| the period. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Module number to configure| +| (0 to 3) | +| BYTE_ b_PWM : Selected PWM (0 or 1). | +| BYTE_ b_TimingUnit : Base timing Unit (0 to 4) | +| 0 : ns | +| 1 : æs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| ULONG_ ul_LowTiming : Low base timing value. | +| ULONG_ ul_HighTiming : High base timing value. | ++----------------------------------------------------------------------------+ +| 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 PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised | +| -6: Timing Unit selection is wrong | +| -7: Low base timing selection is wrong | +| -8: High base timing selection is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_SetNewPWMTiming(struct comedi_device * dev, + BYTE b_ModulNbr, + BYTE b_PWM, BYTE b_TimingUnit, ULONG ul_LowTiming, ULONG ul_HighTiming) +{ + BYTE b_ClockSelection; + INT i_ReturnValue = 0; + ULONG ul_LowTimerValue = 0; + ULONG ul_HighTimerValue = 0; + ULONG ul_RealLowTiming = 0; + ULONG ul_RealHighTiming = 0; + DWORD dw_Status; + DWORD dw_Command; + double d_RealLowTiming = 0; + double d_RealHighTiming = 0; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + b_ClockSelection = devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_PWMModuleInfo. + b_ClockSelection; + + /************************/ + /* Test the timing unit */ + /************************/ + + if (b_TimingUnit <= 4) { + /*********************************/ + /* Test the low timing selection */ + /*********************************/ + + if (((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 266) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571230650UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571230UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 571UL)) + || ((b_ClockSelection == + APCI1710_30MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= 9UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 242) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 519691043UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 519691UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 520UL)) + || ((b_ClockSelection == + APCI1710_33MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= 8UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 0) + && (ul_LowTiming + >= 200) + && (ul_LowTiming + <= + 0xFFFFFFFFUL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 1) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429496729UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 2) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429496UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 3) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 429UL)) + || ((b_ClockSelection == + APCI1710_40MHZ) + && (b_TimingUnit + == 4) + && (ul_LowTiming + >= 1) + && (ul_LowTiming + <= + 7UL))) { + /**********************************/ + /* Test the High timing selection */ + /**********************************/ + + if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) { + /************************************/ + /* Calculate the low division fator */ + /************************************/ + + fpu_begin(); + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (0.00025 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (0.00025 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (0.25 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + ( + (double) + 0.25 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + ul_LowTiming + * + (250.0 + * + b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250.0 * (double)b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (250.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + (ul_LowTiming + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)); + d_RealLowTiming + = + (double) + ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_LowTimerValue + = + (ULONG) + ( + (ul_LowTiming + * + 60) + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { + ul_LowTimerValue + = + ul_LowTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealLowTiming + = + (ULONG) + (ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60; + d_RealLowTiming + = + ( + (double) + ul_LowTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60.0; + + if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealLowTiming + 0.5)) { + ul_RealLowTiming + = + ul_RealLowTiming + + + 1; + } + + ul_LowTiming + = + ul_LowTiming + - + 1; + ul_LowTimerValue + = + ul_LowTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_LowTimerValue + = + (ULONG) + ( + (double) + (ul_LowTimerValue) + * + 1.007752288); + } + + break; + } + + /*************************************/ + /* Calculate the high division fator */ + /*************************************/ + + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (0.00025 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (0.00025 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (0.00025 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (0.25 * b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (0.25 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + ( + (double) + 0.25 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + ul_HighTiming + * + (250.0 + * + b_ClockSelection); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250.0 * (double)b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (250.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + (ul_HighTiming + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)); + d_RealHighTiming + = + (double) + ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection); + + if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_HighTimerValue + = + (ULONG) + ( + (ul_HighTiming + * + 60) + * + (250000.0 + * + b_ClockSelection)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { + ul_HighTimerValue + = + ul_HighTimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealHighTiming + = + (ULONG) + (ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60; + d_RealHighTiming + = + ( + (double) + ul_HighTimerValue + / + (250000.0 + * + (double) + b_ClockSelection)) + / + 60.0; + + if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealHighTiming + 0.5)) { + ul_RealHighTiming + = + ul_RealHighTiming + + + 1; + } + + ul_HighTiming + = + ul_HighTiming + - + 1; + ul_HighTimerValue + = + ul_HighTimerValue + - + 2; + + if (b_ClockSelection != APCI1710_40MHZ) { + ul_HighTimerValue + = + (ULONG) + ( + (double) + (ul_HighTimerValue) + * + 1.007752288); + } + + break; + } + + fpu_end(); + + /************************/ + /* Save the timing unit */ + /************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + b_TimingUnit + = + b_TimingUnit; + + /****************************/ + /* Save the low base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + d_LowTiming + = + d_RealLowTiming; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + ul_RealLowTiming + = + ul_RealLowTiming; + + /****************************/ + /* Save the high base timing */ + /****************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + d_HighTiming + = + d_RealHighTiming; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_PWMModuleInfo. + s_PWMInfo + [b_PWM]. + ul_RealHighTiming + = + ul_RealHighTiming; + + /************************/ + /* Write the low timing */ + /************************/ + + outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /*************************/ + /* Write the high timing */ + /*************************/ + + outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr)); + + /***************************/ + /* Set the clock selection */ + /***************************/ + + dw_Command = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + 8 + + (20 * b_PWM) + (64 * b_ModulNbr)); + + dw_Command = + dw_Command + & 0x7F; + + if (b_ClockSelection == APCI1710_40MHZ) { + dw_Command + = + dw_Command + | + 0x80; + } + + /***************************/ + /* Set the clock selection */ + /***************************/ + + outl(dw_Command, + devpriv-> + s_BoardInfos. + ui_Address + + 8 + + (20 * b_PWM) + (64 * b_ModulNbr)); + } else { + /***************************************/ + /* High base timing selection is wrong */ + /***************************************/ + DPRINTK("High base timing selection is wrong\n"); + i_ReturnValue = + -8; + } + } else { + /**************************************/ + /* Low base timing selection is wrong */ + /**************************************/ + DPRINTK("Low base timing selection is wrong\n"); + i_ReturnValue = -7; + } + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + else { + /**********************************/ + /* Timing unit selection is wrong */ + /**********************************/ + DPRINTK("Timing unit selection is wrong\n"); + i_ReturnValue = -6; + } // if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + DPRINTK("The module is not a PWM 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_GetPWMStatus | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PWM, | +| PBYTE_ pb_PWMOutputStatus, | +| PBYTE_ pb_ExternGateStatus) | ++----------------------------------------------------------------------------+ +| Task : Return the status from selected PWM (b_PWM) from | +| selected module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_PWM : Selected PWM (0 or 1) | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) + b_ModulNbr =(BYTE) CR_AREF(insn->chanspec); + b_PWM =(BYTE) data[0]; + + | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_PWMOutputStatus : Return the PWM output | +| level status. | +| 0 : The PWM output level| +| is low. | +| 1 : The PWM output level| +| is high. | +| PBYTE_ pb_ExternGateStatus : Return the extern gate | +| level status. | +| 0 : The extern gate is | +| low. | +| 1 : The extern gate is | +| high. + pb_PWMOutputStatus =(PBYTE) data[0]; + pb_ExternGateStatus =(PBYTE) data[1]; | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a PWM module | +| -4: PWM selection is wrong | +| -5: PWM not initialised see function | +| "i_APCI1710_InitPWM" | +| -6: PWM not enabled see function "i_APCI1710_EnablePWM"| ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + + BYTE b_ModulNbr; + BYTE b_PWM; + PBYTE pb_PWMOutputStatus; + PBYTE pb_ExternGateStatus; + + i_ReturnValue = insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_PWM = (BYTE) CR_CHAN(insn->chanspec); + pb_PWMOutputStatus = (PBYTE) & data[0]; + pb_ExternGateStatus = (PBYTE) & data[1]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***************/ + /* Test if PWM */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_PWM) { + /**************************/ + /* Test the PWM selection */ + /**************************/ + + if (b_PWM <= 1) { + /***************************/ + /* Test if PWM initialised */ + /***************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (20 * b_PWM) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + /***********************/ + /* Test if PWM enabled */ + /***********************/ + + if (dw_Status & 0x1) { + *pb_PWMOutputStatus = + (BYTE) ((dw_Status >> 7) + & 1); + *pb_ExternGateStatus = + (BYTE) ((dw_Status >> 6) + & 1); + } // if (dw_Status & 0x1) + else { + /*******************/ + /* PWM not enabled */ + /*******************/ + + DPRINTK("PWM not enabled \n"); + i_ReturnValue = -6; + } // if (dw_Status & 0x1) + } // if (dw_Status & 0x10) + else { + /***********************/ + /* PWM not initialised */ + /***********************/ + + DPRINTK("PWM not initialised\n"); + i_ReturnValue = -5; + } // if (dw_Status & 0x10) + } // if (b_PWM >= 0 && b_PWM <= 1) + else { + /******************************/ + /* Tor PWM selection is wrong */ + /******************************/ + + DPRINTK("Tor PWM selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_PWM >= 0 && b_PWM <= 1) + } else { + /**********************************/ + /* The module is not a PWM module */ + /**********************************/ + + DPRINTK("The module is not a PWM module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters.ui_Read].b_OldModuleMask; + data[1] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters.ui_Read].ul_OldInterruptMask; + data[2] = devpriv->s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; + + /**************************/ + /* Increment the read FIFO */ + /***************************/ + + devpriv-> + s_InterruptParameters. + ui_Read = (devpriv-> + s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT; + + return insn->n; + +} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h new file mode 100644 index 000000000000..c1b7f4ca47c3 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#define APCI1710_30MHZ 30 +#define APCI1710_33MHZ 33 +#define APCI1710_40MHZ 40 + +#define APCI1710_PWM_INIT 0 +#define APCI1710_PWM_GETINITDATA 1 + +#define APCI1710_PWM_DISABLE 0 +#define APCI1710_PWM_ENABLE 1 +#define APCI1710_PWM_NEWTIMING 2 + +INT i_APCI1710_InsnConfigPWM(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +INT i_APCI1710_InitPWM(struct comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_ClockSelection, + BYTE b_TimingUnit, + ULONG ul_LowTiming, + ULONG ul_HighTiming, + PULONG pul_RealLowTiming, PULONG pul_RealHighTiming); + +INT i_APCI1710_GetPWMInitialisation(struct comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + PBYTE pb_TimingUnit, + PULONG pul_LowTiming, + PULONG pul_HighTiming, + PBYTE pb_StartLevel, + PBYTE pb_StopMode, + PBYTE pb_StopLevel, + PBYTE pb_ExternGate, + PBYTE pb_InterruptEnable, PBYTE pb_Enable); + +INT i_APCI1710_InsnWritePWM(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +INT i_APCI1710_EnablePWM(struct comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, + BYTE b_StartLevel, + BYTE b_StopMode, + BYTE b_StopLevel, BYTE b_ExternGate, + BYTE b_InterruptEnable); + +INT i_APCI1710_SetNewPWMTiming(struct comedi_device *dev, + BYTE b_ModulNbr, + BYTE b_PWM, BYTE b_TimingUnit, + ULONG ul_LowTiming, ULONG ul_HighTiming); + +INT i_APCI1710_DisablePWM(struct comedi_device *dev, BYTE b_ModulNbr, BYTE b_PWM); + +INT i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +INT i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c new file mode 100644 index 000000000000..bb6e1622e379 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c @@ -0,0 +1,848 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : API APCI1710 | Compiler : gcc | + | Module name : SSI.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 SSI counter module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 13/05/98 | S. Weber | SSI digital input / output implementation | + |----------|-----------|------------------------------------------------| + | 22/03/00 | C.Guinot | 0100/0226 -> 0200/0227 | + | | | Änderung in InitSSI Funktion | + | | | b_SSIProfile >= 2 anstatt b_SSIProfile > 2 | + | | | | + +-----------------------------------------------------------------------+ + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "APCI1710_Ssi.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitSSI | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SSIProfile, | +| BYTE_ b_PositionTurnLength, | +| BYTE_ b_TurnCptLength, | +| BYTE_ b_PCIInputClock, | +| ULONG_ ul_SSIOutputClock, | +| BYTE_ b_SSICountingMode) | ++----------------------------------------------------------------------------+ +| Task : Configure the SSI operating mode from selected module | +| (b_ModulNbr). You must calling this function be for you| +| call any other function witch access of SSI. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_SSIProfile : Selection from SSI | +| profile length (2 to 32).| +| BYTE_ b_PositionTurnLength : Selection from SSI | +| position data length | +| (1 to 31). | +| BYTE_ b_TurnCptLength : Selection from SSI turn | +| counter data length | +| (1 to 31). | +| BYTE b_PCIInputClock : Selection from PCI bus | +| clock | +| - APCI1710_30MHZ : | +| The PC have a PCI bus | +| clock from 30 MHz | +| - APCI1710_33MHZ : | +| The PC have a PCI bus | +| clock from 33 MHz | +| ULONG_ ul_SSIOutputClock : Selection from SSI output| +| clock. | +| From 229 to 5 000 000 Hz| +| for 30 MHz selection. | +| From 252 to 5 000 000 Hz| +| for 33 MHz selection. | +| BYTE b_SSICountingMode : SSI counting mode | +| selection | +| - APCI1710_BINARY_MODE : | +| Binary counting mode. | +| - APCI1710_GRAY_MODE : | +| Gray counting mode. + + b_ModulNbr = CR_AREF(insn->chanspec); + b_SSIProfile = (BYTE) data[0]; + b_PositionTurnLength= (BYTE) data[1]; + b_TurnCptLength = (BYTE) data[2]; + b_PCIInputClock = (BYTE) data[3]; + ul_SSIOutputClock = (ULONG) data[4]; + b_SSICountingMode = (BYTE) data[5]; | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a SSI module | +| -4: The selected SSI profile length is wrong | +| -5: The selected SSI position data length is wrong | +| -6: The selected SSI turn counter data length is wrong | +| -7: The selected PCI input clock is wrong | +| -8: The selected SSI output clock is wrong | +| -9: The selected SSI counting mode parameter is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigInitSSI(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + UINT ui_TimerValue; + BYTE b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength, + b_PCIInputClock, b_SSICountingMode; + ULONG ul_SSIOutputClock; + + b_ModulNbr = CR_AREF(insn->chanspec); + b_SSIProfile = (BYTE) data[0]; + b_PositionTurnLength = (BYTE) data[1]; + b_TurnCptLength = (BYTE) data[2]; + b_PCIInputClock = (BYTE) data[3]; + ul_SSIOutputClock = (ULONG) data[4]; + b_SSICountingMode = (BYTE) data[5]; + + i_ReturnValue = insn->n; + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if SSI counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { + /*******************************/ + /* Test the SSI profile length */ + /*******************************/ + + // CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 + if (b_SSIProfile >= 2 && b_SSIProfile < 33) { + /*************************************/ + /* Test the SSI position data length */ + /*************************************/ + + if (b_PositionTurnLength > 0 + && b_PositionTurnLength < 32) { + /*****************************************/ + /* Test the SSI turn counter data length */ + /*****************************************/ + + if (b_TurnCptLength > 0 + && b_TurnCptLength < 32) { + /***************************/ + /* Test the profile length */ + /***************************/ + + if ((b_TurnCptLength + + b_PositionTurnLength) + <= b_SSIProfile) { + /****************************/ + /* Test the PCI input clock */ + /****************************/ + + if (b_PCIInputClock == + APCI1710_30MHZ + || + b_PCIInputClock + == + APCI1710_33MHZ) + { + /*************************/ + /* Test the output clock */ + /*************************/ + + if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) { + if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) { + /**********************/ + /* Save configuration */ + /**********************/ + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_SSIProfile + = + b_SSIProfile; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength + = + b_PositionTurnLength; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_TurnCptLength + = + b_TurnCptLength; + + /*********************************/ + /* Initialise the profile length */ + /*********************************/ + + if (b_SSICountingMode == APCI1710_BINARY_MODE) { + + outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); + } else { + + outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); + } + + /******************************/ + /* Calculate the output clock */ + /******************************/ + + ui_TimerValue + = + (UINT) + ( + ((ULONG) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock); + + /************************/ + /* Initialise the timer */ + /************************/ + + outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); + + /********************************/ + /* Initialise the counting mode */ + /********************************/ + + outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_SSIInit + = + 1; + } else { + /*****************************************************/ + /* The selected SSI counting mode parameter is wrong */ + /*****************************************************/ + + DPRINTK("The selected SSI counting mode parameter is wrong\n"); + i_ReturnValue + = + -9; + } + } else { + /******************************************/ + /* The selected SSI output clock is wrong */ + /******************************************/ + + DPRINTK("The selected SSI output clock is wrong\n"); + i_ReturnValue + = + -8; + } + } else { + /*****************************************/ + /* The selected PCI input clock is wrong */ + /*****************************************/ + + DPRINTK("The selected PCI input clock is wrong\n"); + i_ReturnValue = + -7; + } + } else { + /********************************************/ + /* The selected SSI profile length is wrong */ + /********************************************/ + + DPRINTK("The selected SSI profile length is wrong\n"); + i_ReturnValue = -4; + } + } else { + /******************************************************/ + /* The selected SSI turn counter data length is wrong */ + /******************************************************/ + + DPRINTK("The selected SSI turn counter data length is wrong\n"); + i_ReturnValue = -6; + } + } else { + /**************************************************/ + /* The selected SSI position data length is wrong */ + /**************************************************/ + + DPRINTK("The selected SSI position data length is wrong\n"); + i_ReturnValue = -5; + } + } else { + /********************************************/ + /* The selected SSI profile length is wrong */ + /********************************************/ + + DPRINTK("The selected SSI profile length is wrong\n"); + i_ReturnValue = -4; + } + } else { + /**********************************/ + /* The module is not a SSI module */ + /**********************************/ + + DPRINTK("The module is not a SSI module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_Read1SSIValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SelectedSSI, | +| PULONG_ pul_Position, | +| PULONG_ pul_TurnCpt) + INT i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : + + + Read the selected SSI counter (b_SelectedSSI) from | +| selected module (b_ModulNbr). + or Read all SSI counter (b_SelectedSSI) from | +| selected module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | +| BYTE_ b_SelectedSSI : Selection from SSI | +| counter (0 to 2) + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec); (in case of single ssi) + b_ReadType = (BYTE) CR_RANGE(insn->chanspec); +| ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_Position : SSI position in the turn | +| PULONG_ pul_TurnCpt : Number of turns + +pul_Position = (PULONG) &data[0]; + pul_TurnCpt = (PULONG) &data[1]; | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a SSI module | +| -4: SSI not initialised see function | +| "i_APCI1710_InitSSI" | +| -5: The selected SSI is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadSSIValue(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + BYTE b_Cpt; + BYTE b_Length; + BYTE b_Schift; + BYTE b_SSICpt; + DWORD dw_And; + DWORD dw_And1; + DWORD dw_And2; + DWORD dw_StatusReg; + DWORD dw_CounterValue; + BYTE b_ModulNbr; + BYTE b_SelectedSSI; + BYTE b_ReadType; + PULONG pul_Position; + PULONG pul_TurnCpt; + PULONG pul_Position1; + PULONG pul_TurnCpt1; + + i_ReturnValue = insn->n; + pul_Position1 = (PULONG) & data[0]; +// For Read1 + pul_TurnCpt1 = (PULONG) & data[1]; +// For Read all + pul_Position = (PULONG) & data[0]; //0-2 + pul_TurnCpt = (PULONG) & data[3]; //3-5 + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_SelectedSSI = (BYTE) CR_CHAN(insn->chanspec); + b_ReadType = (BYTE) CR_RANGE(insn->chanspec); + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if SSI counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { + /***************************/ + /* Test if SSI initialised */ + /***************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_SSICounterInfo.b_SSIInit == 1) { + + switch (b_ReadType) { + + case APCI1710_SSI_READ1VALUE: + /****************************************/ + /* Test the selected SSI counter number */ + /****************************************/ + + if (b_SelectedSSI < 3) { + /************************/ + /* Start the conversion */ + /************************/ + + outl(0, devpriv->s_BoardInfos. + ui_Address + 8 + + (64 * b_ModulNbr)); + + do { + /*******************/ + /* Read the status */ + /*******************/ + + dw_StatusReg = + inl(devpriv-> + s_BoardInfos. + ui_Address + + (64 * b_ModulNbr)); + } + while ((dw_StatusReg & 0x1) != + 0); + + /******************************/ + /* Read the SSI counter value */ + /******************************/ + + dw_CounterValue = + inl(devpriv-> + s_BoardInfos. + ui_Address + 4 + + (b_SelectedSSI * 4) + + (64 * b_ModulNbr)); + + b_Length = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_SSIProfile / 2; + + if ((b_Length * 2) != + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_SSIProfile) { + b_Length++; + } + + b_Schift = + b_Length - + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength; + + *pul_Position1 = + dw_CounterValue >> + b_Schift; + + dw_And = 1; + + for (b_Cpt = 0; + b_Cpt < + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength; + b_Cpt++) { + dw_And = dw_And * 2; + } + + *pul_Position1 = + *pul_Position1 & + ((dw_And) - 1); + + *pul_TurnCpt1 = + dw_CounterValue >> + b_Length; + + dw_And = 1; + + for (b_Cpt = 0; + b_Cpt < + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_TurnCptLength; + b_Cpt++) { + dw_And = dw_And * 2; + } + + *pul_TurnCpt1 = + *pul_TurnCpt1 & + ((dw_And) - 1); + } else { + /*****************************/ + /* The selected SSI is wrong */ + /*****************************/ + + DPRINTK("The selected SSI is wrong\n"); + i_ReturnValue = -5; + } + break; + + case APCI1710_SSI_READALLVALUE: + dw_And1 = 1; + + for (b_Cpt = 0; + b_Cpt < + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength; b_Cpt++) { + dw_And1 = dw_And1 * 2; + } + + dw_And2 = 1; + + for (b_Cpt = 0; + b_Cpt < + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_SSICounterInfo. + b_TurnCptLength; b_Cpt++) { + dw_And2 = dw_And2 * 2; + } + + /************************/ + /* Start the conversion */ + /************************/ + + outl(0, devpriv->s_BoardInfos. + ui_Address + 8 + + (64 * b_ModulNbr)); + + do { + /*******************/ + /* Read the status */ + /*******************/ + + dw_StatusReg = + inl(devpriv-> + s_BoardInfos. + ui_Address + + (64 * b_ModulNbr)); + } + while ((dw_StatusReg & 0x1) != 0); + + for (b_SSICpt = 0; b_SSICpt < 3; + b_SSICpt++) { + /******************************/ + /* Read the SSI counter value */ + /******************************/ + + dw_CounterValue = + inl(devpriv-> + s_BoardInfos. + ui_Address + 4 + + (b_SSICpt * 4) + + (64 * b_ModulNbr)); + + b_Length = + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_SSIProfile / 2; + + if ((b_Length * 2) != + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_SSIProfile) { + b_Length++; + } + + b_Schift = + b_Length - + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_SSICounterInfo. + b_PositionTurnLength; + + pul_Position[b_SSICpt] = + dw_CounterValue >> + b_Schift; + pul_Position[b_SSICpt] = + pul_Position[b_SSICpt] & + ((dw_And1) - 1); + + pul_TurnCpt[b_SSICpt] = + dw_CounterValue >> + b_Length; + pul_TurnCpt[b_SSICpt] = + pul_TurnCpt[b_SSICpt] & + ((dw_And2) - 1); + } + break; + + default: + printk("Read Type Inputs Wrong\n"); + + } // switch ending + + } else { + /***********************/ + /* SSI not initialised */ + /***********************/ + + DPRINTK("SSI not initialised\n"); + i_ReturnValue = -4; + } + } else { + /**********************************/ + /* The module is not a SSI module */ + /**********************************/ + + DPRINTK("The module is not a SSI module\n"); + i_ReturnValue = -3; + + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_InputChannel, | +| PBYTE_ pb_ChannelStatus) | ++----------------------------------------------------------------------------+ +| Task : + (0) Set the digital output from selected SSI moule | +| (b_ModuleNbr) ON + (1) Set the digital output from selected SSI moule | +| (b_ModuleNbr) OFF + (2)Read the status from selected SSI digital input | +| (b_InputChannel) + (3)Read the status from all SSI digital inputs from | +| selected SSI module (b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr CR_AREF : Module number to | +| configure (0 to 3) | +| BYTE_ b_InputChannel CR_CHAN : Selection from digital | +| data[0] which IOTYPE input ( 0 to 2) | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_ChannelStatus : Digital input channel | +| data[0] status | +| 0 : Channle is not active| +| 1 : Channle is active | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: The module parameter is wrong | +| -3: The module is not a SSI module | +| -4: The selected SSI digital input is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg; + BYTE b_ModulNbr; + BYTE b_InputChannel; + PBYTE pb_ChannelStatus; + PBYTE pb_InputStatus; + BYTE b_IOType; + i_ReturnValue = insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_IOType = (BYTE) data[0]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if SSI counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { + switch (b_IOType) { + case APCI1710_SSI_SET_CHANNELON: + /*****************************/ + /* Set the digital output ON */ + /*****************************/ + + outl(1, devpriv->s_BoardInfos.ui_Address + 16 + + (64 * b_ModulNbr)); + break; + + case APCI1710_SSI_SET_CHANNELOFF: + /******************************/ + /* Set the digital output OFF */ + /******************************/ + + outl(0, devpriv->s_BoardInfos.ui_Address + 16 + + (64 * b_ModulNbr)); + break; + + case APCI1710_SSI_READ_1CHANNEL: + /******************************************/ + /* Test the digital imnput channel number */ + /******************************************/ + + b_InputChannel = (BYTE) CR_CHAN(insn->chanspec); + pb_ChannelStatus = (PBYTE) & data[0]; + + if (b_InputChannel <= 2) { + /**************************/ + /* Read all digital input */ + /**************************/ + + dw_StatusReg = + inl(devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + *pb_ChannelStatus = + (BYTE) (((~dw_StatusReg) >> (4 + + b_InputChannel)) + & 1); + } else { + /********************************/ + /* Selected digital input error */ + /********************************/ + + DPRINTK("Selected digital input error\n"); + i_ReturnValue = -4; + } + break; + + case APCI1710_SSI_READ_ALLCHANNEL: + /**************************/ + /* Read all digital input */ + /**************************/ + pb_InputStatus = (PBYTE) & data[0]; + + dw_StatusReg = + inl(devpriv->s_BoardInfos.ui_Address + + (64 * b_ModulNbr)); + *pb_InputStatus = + (BYTE) (((~dw_StatusReg) >> 4) & 7); + break; + + default: + printk("IO type wrong\n"); + + } //switch end + } else { + /**********************************/ + /* The module is not a SSI module */ + /**********************************/ + + DPRINTK("The module is not a SSI module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h new file mode 100644 index 000000000000..88daad1a3912 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#define APCI1710_30MHZ 30 +#define APCI1710_33MHZ 33 +#define APCI1710_40MHZ 40 + +#define APCI1710_BINARY_MODE 0x1 +#define APCI1710_GRAY_MODE 0x0 + +#define APCI1710_SSI_READ1VALUE 1 +#define APCI1710_SSI_READALLVALUE 2 + +#define APCI1710_SSI_SET_CHANNELON 0 +#define APCI1710_SSI_SET_CHANNELOFF 1 +#define APCI1710_SSI_READ_1CHANNEL 2 +#define APCI1710_SSI_READ_ALLCHANNEL 3 + +/* + * SSI INISIALISATION FUNCTION + */ +INT i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +INT i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +INT i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c new file mode 100644 index 000000000000..90316e10a3bd --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c @@ -0,0 +1,2049 @@ +/** +@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 : TOR.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 tor counter module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 27/01/99 | S. Weber | 40 MHz implementation | + +-----------------------------------------------------------------------+ + | 28/04/00 | S. Weber | Simple,double and quadruple mode implementation| + | | | Extern clock implementation | + +-----------------------------------------------------------------------+ + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "APCI1710_Tor.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitTorCounter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter, | +| BYTE_ b_PCIInputClock, | +| BYTE_ b_TimingUnit, | +| ULONG_ ul_TimingInterval, | +| PULONG_ pul_RealTimingInterval) | ++----------------------------------------------------------------------------+ +| Task : Configure the selected tor counter (b_TorCounter) | +| 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 tor counter. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : | +| + CR_AREF BYTE_ b_ModulNbr : Module number to configure | +| (0 to 3) | +| data[0] BYTE_ b_TorCounter : Tor counter selection | +| (0 or 1). | +| data[1] BYTE_ b_PCIInputClock : Selection from PCI bus clock| +| - APCI1710_30MHZ : | +| The PC have a PCI bus | +| clock from 30 MHz | +| - APCI1710_33MHZ : | +| The PC have a PCI bus | +| clock from 33 MHz | +| - APCI1710_40MHZ | +| The APCI-1710 have a | +| integrated 40Mhz | +| quartz. | +| - APCI1710_GATE_INPUT | +| Used the gate input for | +| the base clock. If you | +| have selected this option,| +| than it is not possibl to | +| used the gate input for | +| enabled the acquisition | +| data[2] BYTE_ b_TimingUnit : Base timing unit (0 to 4) | +| 0 : ns | +| 1 : µs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| data[3] ULONG_ ul_TimingInterval : Base timing value. | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_RealTimingInterval : Real base timing | +| data[0] 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 tor counter module | +| -4: Tor counter selection is wrong | +| -5: The selected PCI input clock is wrong | +| -6: Timing unit 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 TOR version | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + ULONG ul_TimerValue = 0; + DWORD dw_Command; + double d_RealTimingInterval = 0; + BYTE b_ModulNbr; + BYTE b_TorCounter; + BYTE b_PCIInputClock; + BYTE b_TimingUnit; + ULONG ul_TimingInterval; + ULONG ul_RealTimingInterval = 0; + + i_ReturnValue = insn->n; + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + + b_TorCounter = (BYTE) data[0]; + b_PCIInputClock = (BYTE) data[1]; + b_TimingUnit = (BYTE) data[2]; + ul_TimingInterval = (ULONG) data[3]; + printk("INPUT clock %d\n", b_PCIInputClock); + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if tor counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { + /**********************************/ + /* Test the tor counter selection */ + /**********************************/ + + if (b_TorCounter <= 1) { + /**************************/ + /* Test the PCI bus clock */ + /**************************/ + + if ((b_PCIInputClock == APCI1710_30MHZ) || + (b_PCIInputClock == APCI1710_33MHZ) || + (b_PCIInputClock == APCI1710_40MHZ) || + (b_PCIInputClock == + APCI1710_GATE_INPUT)) { + /************************/ + /* Test the timing unit */ + /************************/ + + if ((b_TimingUnit <= 4) + || (b_PCIInputClock == + APCI1710_GATE_INPUT)) { + /**********************************/ + /* Test the base timing selection */ + /**********************************/ + + if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 133) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230650UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 9UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 121) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691043UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 520UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 8UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 100) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496729UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 7UL)) || ((b_PCIInputClock == APCI1710_GATE_INPUT) && (ul_TimingInterval >= 2))) { + /**************************/ + /* 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_GATE_INPUT) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3132)) || (b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) { + /*********************************/ + /* Test if not extern clock used */ + /*********************************/ + + if (b_PCIInputClock != APCI1710_GATE_INPUT) { + fpu_begin + (); + /****************************************/ + /* Calculate the timer 0 division fator */ + /****************************************/ + + switch (b_TimingUnit) { + /******/ + /* ns */ + /******/ + + case 0: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + (ul_TimingInterval + * + (0.00025 * b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (0.00025 * (double)b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + (0.00025 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (0.00025 * (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) + * + 1.007752288); + } + + break; + + /******/ + /* æs */ + /******/ + + case 1: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + (ul_TimingInterval + * + (0.25 * b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (0.25 * (double)b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + ( + (double) + 0.25 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (0.25 * (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) + * + 1.007752288); + } + + break; + + /******/ + /* ms */ + /******/ + + case 2: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + ul_TimingInterval + * + (250.0 + * + b_PCIInputClock); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (250.0 * (double)b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + (250.0 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (250.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) + * + 1.007752288); + } + + break; + + /*****/ + /* s */ + /*****/ + + case 3: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + (ul_TimingInterval + * + (250000.0 + * + b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)ul_TimingInterval * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (250000.0 + * + (double) + b_PCIInputClock)); + d_RealTimingInterval + = + (double) + ul_TimerValue + / + (250000.0 + * + (double) + b_PCIInputClock); + + if ((double)((double)ul_TimerValue / (250000.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) + * + 1.007752288); + } + + break; + + /******/ + /* mn */ + /******/ + + case 4: + + /******************/ + /* Timer 0 factor */ + /******************/ + + ul_TimerValue + = + (ULONG) + ( + (ul_TimingInterval + * + 60) + * + (250000.0 + * + b_PCIInputClock)); + + /*******************/ + /* Round the value */ + /*******************/ + + if ((double)((double)(ul_TimingInterval * 60.0) * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { + ul_TimerValue + = + ul_TimerValue + + + 1; + } + + /*****************************/ + /* Calculate the real timing */ + /*****************************/ + + ul_RealTimingInterval + = + (ULONG) + (ul_TimerValue + / + (250000.0 + * + (double) + b_PCIInputClock)) + / + 60; + d_RealTimingInterval + = + ( + (double) + ul_TimerValue + / + (250000.0 + * + (double) + b_PCIInputClock)) + / + 60.0; + + if ((double)(((double)ul_TimerValue / (250000.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) + * + 1.007752288); + } + + break; + } + + fpu_end(); + } // if (b_PCIInputClock != APCI1710_GATE_INPUT) + else { + /*************************************************************/ + /* 2 Clock used for the overflow and the reload from counter */ + /*************************************************************/ + + ul_TimerValue + = + ul_TimingInterval + - + 2; + } // if (b_PCIInputClock != APCI1710_GATE_INPUT) + + /****************************/ + /* Save the PCI input clock */ + /****************************/ + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TorCounterModuleInfo. + b_PCIInputClock + = + b_PCIInputClock; + + /************************/ + /* Save the timing unit */ + /************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo + [b_TorCounter]. + b_TimingUnit + = + b_TimingUnit; + + /************************/ + /* Save the base timing */ + /************************/ + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo + [b_TorCounter]. + d_TimingInterval + = + d_RealTimingInterval; + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo + [b_TorCounter]. + ul_RealTimingInterval + = + ul_RealTimingInterval; + + /*******************/ + /* Get the command */ + /*******************/ + + dw_Command + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 4 + + + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + dw_Command + = + (dw_Command + >> + 4) + & + 0xF; + + /******************/ + /* Test if 40 MHz */ + /******************/ + + if (b_PCIInputClock == APCI1710_40MHZ) { + /****************************/ + /* Set the 40 MHz selection */ + /****************************/ + + dw_Command + = + dw_Command + | + 0x10; + } + + /*****************************/ + /* Test if extern clock used */ + /*****************************/ + + if (b_PCIInputClock == APCI1710_GATE_INPUT) { + /****************************/ + /* Set the 40 MHz selection */ + /****************************/ + + dw_Command + = + dw_Command + | + 0x20; + } + + /*************************/ + /* Write the new command */ + /*************************/ + + outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + /*******************/ + /* Disable the tor */ + /*******************/ + + outl(0, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr)); + /*************************/ + /* Set the timer 1 value */ + /*************************/ + + outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + /*********************/ + /* Tor counter init. */ + /*********************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo + [b_TorCounter]. + b_TorCounterInit + = + 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 unit selection is wrong */ + /**********************************/ + + DPRINTK("Timing unit 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_TorCounterMode >= 0 && b_TorCounterMode <= 7) + else { + /**********************************/ + /* Tor Counter selection is wrong */ + /**********************************/ + + DPRINTK("Tor Counter selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7) + } else { + /******************************************/ + /* The module is not a tor counter module */ + /******************************************/ + + DPRINTK("The module is not a tor counter module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + data[0] = (UINT) ul_RealTimingInterval; + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_EnableTorCounter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter, | +| BYTE_ b_InputMode, | +| BYTE_ b_ExternGate, | +| BYTE_ b_CycleMode, | +| BYTE_ b_InterruptEnable) | ++----------------------------------------------------------------------------+ +| Task : Enable the tor counter (b_TorCounter) from selected | +| module (b_ModulNbr). You must calling the | +| "i_APCI1710_InitTorCounter" function be for you call | +| this function. | +| If you enable the tor counter interrupt, the | +| tor counter generate a interrupt after the timing cycle| +| 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. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_TorCounter : Tor counter selection (0 or 1). | +| BYTE_ b_InputMode : Input signal level selection | +| 0 : Tor count each low level | +| 1 : Tor count each high level| +| BYTE_ b_ExternGate : Extern gate action selection | +| 0 : Extern gate signal not | +| used | +| 1 : Extern gate signal used. | +| If you selected the | +| single mode, each high | +| level signal start the | +| counter. | +| If you selected the | +| continuous mode, the | +| first high level signal | +| start the tor counter | +| | +| APCI1710_TOR_QUADRUPLE _MODE : | +| In the quadruple mode, the edge| +| analysis circuit generates a | +| counting pulse from each edge | +| of 2 signals which are phase | +| shifted in relation to each | +| other. | +| The gate input is used for the | +| signal B | +| | +| APCI1710_TOR_DOUBLE_MODE: | +| Functions in the same way as | +| the quadruple mode, except that| +| only two of the four edges are | +| analysed per period. | +| The gate input is used for the | +| signal B | +| | +| APCI1710_TOR_SIMPLE_MODE: | +| Functions in the same way as | +| the quadruple mode, except that| +| only one of the four edges is | +| analysed per period. | +| The gate input is used for the | +| signal B | +| | +| BYTE_ b_CycleMode : Selected the tor counter | +| acquisition mode | +| BYTE_ b_InterruptEnable : Enable or disable the | +| tor counter interrupt. | +| APCI1710_ENABLE: | +| Enable the tor counter | +| interrupt | +| APCI1710_DISABLE: | +| Disable the tor counter | +| 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 tor counter module | +| -4: Tor counter selection is wrong | +| -5: Tor counter not initialised see function | +| "i_APCI1710_InitTorCounter" | +| -6: Tor input signal selection is wrong | +| -7: Extern gate signal mode is wrong | +| -8: Tor counter acquisition mode cycle is wrong | +| -9: Interrupt parameter is wrong | +| -10:Interrupt function not initialised. | +| See function "i_APCI1710_SetBoardIntRoutineX" | ++----------------------------------------------------------------------------+ +*/ +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_DisableTorCounter | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter) | ++----------------------------------------------------------------------------+ +| Task : Disable the tor counter (b_TorCounter) from selected | +| module (b_ModulNbr). If you disable the tor counter | +| after a start cycle occur and you restart the tor | +| counter witch the " i_APCI1710_EnableTorCounter" | +| function, the status register is cleared | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_TorCounter : Tor counter selection (0 or 1). | ++----------------------------------------------------------------------------+ +| 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 tor counter module | +| -4: Tor counter selection is wrong | +| -5: Tor counter not initialised see function | +| "i_APCI1710_InitTorCounter" | +| -6: Tor counter not enabled see function | +| "i_APCI1710_EnableTorCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_DummyRead; + DWORD dw_ConfigReg; + BYTE b_ModulNbr, b_Action; + BYTE b_TorCounter; + BYTE b_InputMode; + BYTE b_ExternGate; + BYTE b_CycleMode; + BYTE b_InterruptEnable; + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_Action = (BYTE) data[0]; // enable or disable + b_TorCounter = (BYTE) data[1]; + b_InputMode = (BYTE) data[2]; + b_ExternGate = (BYTE) data[3]; + b_CycleMode = (BYTE) data[4]; + b_InterruptEnable = (BYTE) data[5]; + i_ReturnValue = insn->n;; + devpriv->tsk_Current = current; // Save the current process task structure + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if tor counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { + /**********************************/ + /* Test the tor counter selection */ + /**********************************/ + + if (b_TorCounter <= 1) { + switch (b_Action) // Enable or Disable + { + case APCI1710_ENABLE: + /***********************************/ + /* Test if tor counter initialised */ + /***********************************/ + + dw_Status = + inl(devpriv->s_BoardInfos. + ui_Address + 8 + + (16 * b_TorCounter) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + /******************************/ + /* Test the input signal mode */ + /******************************/ + + if (b_InputMode == 0 || + b_InputMode == 1 || + b_InputMode == + APCI1710_TOR_SIMPLE_MODE + || b_InputMode == + APCI1710_TOR_DOUBLE_MODE + || b_InputMode == + APCI1710_TOR_QUADRUPLE_MODE) + { + /************************************/ + /* Test the extern gate signal mode */ + /************************************/ + + if (b_ExternGate == 0 + || b_ExternGate + == 1 + || b_InputMode > + 1) { + /*********************************/ + /* 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 mode */ + /***************************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo + [b_TorCounter]. + b_InterruptEnable + = + b_InterruptEnable; + + /*******************/ + /* Get the command */ + /*******************/ + + dw_ConfigReg + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 4 + + + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + dw_ConfigReg + = + (dw_ConfigReg + >> + 4) + & + 0x30; + + /********************************/ + /* Test if not direct mode used */ + /********************************/ + + if (b_InputMode > 1) { + /*******************************/ + /* Extern gate can not be used */ + /*******************************/ + + b_ExternGate + = + 0; + + /*******************************************/ + /* Enable the extern gate for the Signal B */ + /*******************************************/ + + dw_ConfigReg + = + dw_ConfigReg + | + 0x40; + + /***********************/ + /* Test if simple mode */ + /***********************/ + + if (b_InputMode == APCI1710_TOR_SIMPLE_MODE) { + /**************************/ + /* Enable the sinple mode */ + /**************************/ + + dw_ConfigReg + = + dw_ConfigReg + | + 0x780; + + } // if (b_InputMode == APCI1710_TOR_SIMPLE_MODE) + + /***********************/ + /* Test if double mode */ + /***********************/ + + if (b_InputMode == APCI1710_TOR_DOUBLE_MODE) { + /**************************/ + /* Enable the double mode */ + /**************************/ + + dw_ConfigReg + = + dw_ConfigReg + | + 0x180; + + } // if (b_InputMode == APCI1710_TOR_DOUBLE_MODE) + + b_InputMode + = + 0; + } // if (b_InputMode > 1) + + /*******************/ + /* Set the command */ + /*******************/ + + dw_ConfigReg + = + dw_ConfigReg + | + b_CycleMode + | + (b_InterruptEnable + * + 2) + | + (b_InputMode + * + 4) + | + (b_ExternGate + * + 8); + + /*****************************/ + /* Clear the status register */ + /*****************************/ + + dw_DummyRead + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 0 + + + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + /***************************************/ + /* Clear the interrupt status register */ + /***************************************/ + + dw_DummyRead + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 12 + + + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + /********************/ + /* Set the commando */ + /********************/ + + outl(dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + /****************/ + /* Set the gate */ + /****************/ + + outl(1, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (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 + = + -9; + } // if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) + } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) + else { + /***********************************************/ + /* Tor counter acquisition mode cycle is wrong */ + /***********************************************/ + + DPRINTK("Tor counter acquisition mode cycle is wrong\n"); + i_ReturnValue + = + -8; + } // if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) + } // if (b_ExternGate >= 0 && b_ExternGate <= 1) + else { + /***********************************/ + /* Extern gate input mode is wrong */ + /***********************************/ + + DPRINTK("Extern gate input mode is wrong\n"); + i_ReturnValue = + -7; + } // if (b_ExternGate >= 0 && b_ExternGate <= 1) + } // if (b_InputMode >= 0 && b_InputMode <= 1) + else { + /***************************************/ + /* Tor input signal selection is wrong */ + /***************************************/ + + DPRINTK("Tor input signal selection is wrong\n"); + i_ReturnValue = -6; + } + } else { + /*******************************/ + /* Tor counter not initialised */ + /*******************************/ + + DPRINTK("Tor counter not initialised\n"); + i_ReturnValue = -5; + } + break; + + case APCI1710_DISABLE: + /***********************************/ + /* Test if tor counter initialised */ + /***********************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 8 + + (16 * b_TorCounter) + + (64 * b_ModulNbr)); + + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (dw_Status & 0x10) { + /***************************/ + /* Test if counter enabled */ + /***************************/ + + if (dw_Status & 0x1) { + /****************************/ + /* Clear the interrupt mode */ + /****************************/ + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo + [b_TorCounter]. + b_InterruptEnable + = + APCI1710_DISABLE; + + /******************/ + /* Clear the gate */ + /******************/ + + outl(0, devpriv-> + s_BoardInfos. + ui_Address + 8 + + (16 * b_TorCounter) + (64 * b_ModulNbr)); + } // if (dw_Status & 0x1) + else { + /***************************/ + /* Tor counter not enabled */ + /***************************/ + + DPRINTK("Tor counter not enabled \n"); + i_ReturnValue = -6; + } // if (dw_Status & 0x1) + } // if (dw_Status & 0x10) + else { + /*******************************/ + /* Tor counter not initialised */ + /*******************************/ + + DPRINTK("Tor counter not initialised\n"); + i_ReturnValue = -5; + } // // if (dw_Status & 0x10) + + } // switch + } // if (b_TorCounter <= 1) + else { + /**********************************/ + /* Tor counter selection is wrong */ + /**********************************/ + + DPRINTK("Tor counter selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_TorCounter <= 1) + } else { + /******************************************/ + /* The module is not a tor counter module */ + /******************************************/ + + DPRINTK("The module is not a tor counter 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_GetTorCounterInitialisation | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter, | +| PBYTE_ pb_TimingUnit, | +| PULONG_ pul_TimingInterval, | +| PBYTE_ pb_InputMode, | +| PBYTE_ pb_ExternGate, | +| PBYTE_ pb_CycleMode, | +| PBYTE_ pb_Enable, | +| PBYTE_ pb_InterruptEnable)| ++----------------------------------------------------------------------------+ +| Task : Enable the tor counter (b_TorCounter) from selected | +| module (b_ModulNbr). You must calling the | +| "i_APCI1710_InitTorCounter" function be for you call | +| this function. | +| If you enable the tor counter interrupt, the | +| tor counter generate a interrupt after the timing cycle| +| 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. | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_TorCounter : Tor counter selection (0 or 1) + + b_ModulNbr = CR_AREF(insn->chanspec); + b_TorCounter = CR_CHAN(insn->chanspec); +. | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TimingUnit : Base timing unit (0 to 4) | +| 0 : ns | +| 1 : µs | +| 2 : ms | +| 3 : s | +| 4 : mn | +| PULONG_ pul_TimingInterval : Base timing value. | +| PBYTE_ pb_InputMode : Input signal level | +| selection | +| 0 : Tor count each low level | +| 1 : Tor count each high level| +| PBYTE_ pb_ExternGate : Extern gate action | +| selection | +| 0 : Extern gate signal not | +| used | +| 1 : Extern gate signal used| +| PBYTE_ pb_CycleMode : Tor counter acquisition | +| mode | +| PBYTE_ pb_Enable : Indicate if the tor counter| +| is enabled or no | +| 0 : Tor counter disabled | +| 1 : Tor counter enabled | +| PBYTE_ pb_InterruptEnable : Enable or disable the | +| tor counter interrupt. | +| APCI1710_ENABLE: | +| Enable the tor counter | +| interrupt | +| APCI1710_DISABLE: | +| Disable the tor counter | +| interrupt + pb_TimingUnit = (PBYTE) &data[0]; + pul_TimingInterval = (PULONG) &data[1]; + pb_InputMode = (PBYTE) &data[2]; + pb_ExternGate = (PBYTE) &data[3]; + pb_CycleMode = (PBYTE) &data[4]; + pb_Enable = (PBYTE) &data[5]; + pb_InterruptEnable = (PBYTE) &data[6]; + | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a tor counter module | +| -4: Tor counter selection is wrong | +| -5: Tor counter not initialised see function | +| "i_APCI1710_InitTorCounter" | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + BYTE b_ModulNbr; + BYTE b_TorCounter; + PBYTE pb_TimingUnit; + PULONG pul_TimingInterval; + PBYTE pb_InputMode; + PBYTE pb_ExternGate; + PBYTE pb_CycleMode; + PBYTE pb_Enable; + PBYTE pb_InterruptEnable; + + i_ReturnValue = insn->n; + b_ModulNbr = CR_AREF(insn->chanspec); + b_TorCounter = CR_CHAN(insn->chanspec); + + pb_TimingUnit = (PBYTE) & data[0]; + pul_TimingInterval = (PULONG) & data[1]; + pb_InputMode = (PBYTE) & data[2]; + pb_ExternGate = (PBYTE) & data[3]; + pb_CycleMode = (PBYTE) & data[4]; + pb_Enable = (PBYTE) & data[5]; + pb_InterruptEnable = (PBYTE) & data[6]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if tor counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { + /**********************************/ + /* Test the tor counter selection */ + /**********************************/ + + if (b_TorCounter <= 1) { + + /***********************************/ + /* Test if tor counter initialised */ + /***********************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 8 + (16 * b_TorCounter) + + (64 * b_ModulNbr)); + + if (dw_Status & 0x10) { + *pb_Enable = dw_Status & 1; + + /********************/ + /* Get the commando */ + /********************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 4 + + (16 * b_TorCounter) + + (64 * b_ModulNbr)); + + *pb_CycleMode = + (BYTE) ((dw_Status >> 4) & 1); + *pb_InterruptEnable = + (BYTE) ((dw_Status >> 5) & 1); + + /******************************************************/ + /* Test if extern gate used for clock or for signal B */ + /******************************************************/ + + if (dw_Status & 0x600) { + /*****************************************/ + /* Test if extern gate used for signal B */ + /*****************************************/ + + if (dw_Status & 0x400) { + /***********************/ + /* Test if simple mode */ + /***********************/ + + if ((dw_Status & 0x7800) + == 0x7800) { + *pb_InputMode = + APCI1710_TOR_SIMPLE_MODE; + } + + /***********************/ + /* Test if double mode */ + /***********************/ + + if ((dw_Status & 0x7800) + == 0x1800) { + *pb_InputMode = + APCI1710_TOR_DOUBLE_MODE; + } + + /**************************/ + /* Test if quadruple mode */ + /**************************/ + + if ((dw_Status & 0x7800) + == 0x0000) { + *pb_InputMode = + APCI1710_TOR_QUADRUPLE_MODE; + } + } // if (dw_Status & 0x400) + else { + *pb_InputMode = 1; + } // // if (dw_Status & 0x400) + + /************************/ + /* Extern gate not used */ + /************************/ + + *pb_ExternGate = 0; + } // if (dw_Status & 0x600) + else { + *pb_InputMode = + (BYTE) ((dw_Status >> 6) + & 1); + *pb_ExternGate = + (BYTE) ((dw_Status >> 7) + & 1); + } // if (dw_Status & 0x600) + + *pb_TimingUnit = + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo[b_TorCounter]. + b_TimingUnit; + + *pul_TimingInterval = + devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_TorCounterModuleInfo. + s_TorCounterInfo[b_TorCounter]. + ul_RealTimingInterval; + } else { + /*******************************/ + /* Tor counter not initialised */ + /*******************************/ + + DPRINTK("Tor counter not initialised\n"); + i_ReturnValue = -5; + } + + } // if (b_TorCounter <= 1) + else { + /**********************************/ + /* Tor counter selection is wrong */ + /**********************************/ + + DPRINTK("Tor counter selection is wrong \n"); + i_ReturnValue = -4; + } // if (b_TorCounter <= 1) + } else { + /******************************************/ + /* The module is not a tor counter module */ + /******************************************/ + + DPRINTK("The module is not a tor counter 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_ReadTorCounterValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_TorCounter, | +| UINT_ ui_TimeOut, | +| PBYTE_ pb_TorCounterStatus, | +| PULONG_ pul_TorCounterValue) | ++----------------------------------------------------------------------------+ +| Task case APCI1710_TOR_GETPROGRESSSTATUS: Return the tor counter +(b_TorCounter) status (pb_TorCounterStatus) from selected tor counter | +| module (b_ModulNbr). + + case APCI1710_TOR_GETCOUNTERVALUE : + Return the tor counter (b_TorCounter) status | +| (pb_TorCounterStatus) and the timing value | +| (pul_TorCounterValue) after a conting cycle stop | +| from selected tor counter module (b_ModulNbr). | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710 | +| BYTE_ b_ModulNbr : Selected module number (0 to 3) | +| BYTE_ b_TorCounter : Tor counter selection (0 or 1). + b_ModulNbr = CR_AREF(insn->chanspec); + b_ReadType = (BYTE) data[0]; + b_TorCounter = (BYTE) data[1]; + ui_TimeOut = (UINT) data[2]; | ++----------------------------------------------------------------------------+ +| Output Parameters : PBYTE_ pb_TorCounterStatus : Return the tor counter | +| status. | +| 0 : Conting cycle not started| +| Software gate not set. | +| 1 : Conting cycle started. | +| Software gate set. | +| 2 : Conting cycle stopped. | +| The conting cycle is | +| terminate. | +| 3 : A overflow occur. You | +| must change the base | +| timing witch the | +| function | +| "i_APCI1710_InitTorCounter"| +| 4 : Timeeout occur | +| PULONG pul_TorCounterValue : Tor counter value. + pb_TorCounterStatus=(PBYTE) &data[0]; + pul_TorCounterValue=(PULONG) &data[1]; | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -1: The handle parameter of the board is wrong | +| -2: Module selection wrong | +| -3: The module is not a tor counter module | +| -4: Tor counter selection is wrong | +| -5: Tor counter not initialised see function | +| "i_APCI1710_InitTorCounter" | +| -6: Tor counter not enabled see function | +| "i_APCI1710_EnableTorCounter" | +| -7: Timeout parameter is wrong (0 to 65535) | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_Status; + DWORD dw_TimeOut = 0; + + BYTE b_ModulNbr; + BYTE b_TorCounter; + BYTE b_ReadType; + UINT ui_TimeOut; + PBYTE pb_TorCounterStatus; + PULONG pul_TorCounterValue; + + i_ReturnValue = insn->n; + b_ModulNbr = CR_AREF(insn->chanspec); + b_ReadType = (BYTE) data[0]; + b_TorCounter = (BYTE) data[1]; + ui_TimeOut = (UINT) data[2]; + pb_TorCounterStatus = (PBYTE) & data[0]; + pul_TorCounterValue = (PULONG) & data[1]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ReadType == APCI1710_TOR_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; + + return insn->n; + } + + if (b_ModulNbr < 4) { + /***********************/ + /* Test if tor counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { + /**********************************/ + /* Test the tor counter selection */ + /**********************************/ + + if (b_TorCounter <= 1) { + /***********************************/ + /* Test if tor counter initialised */ + /***********************************/ + + dw_Status = inl(devpriv->s_BoardInfos. + ui_Address + 8 + (16 * b_TorCounter) + + (64 * b_ModulNbr)); + + /*******************************/ + /* Test if counter initialised */ + /*******************************/ + + if (dw_Status & 0x10) { + /***************************/ + /* Test if counter enabled */ + /***************************/ + + if (dw_Status & 0x1) { + + switch (b_ReadType) { + + case APCI1710_TOR_GETPROGRESSSTATUS: + /*******************/ + /* Read the status */ + /*******************/ + + dw_Status = + inl(devpriv-> + s_BoardInfos. + ui_Address + 4 + + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + dw_Status = + dw_Status & 0xF; + + /*****************/ + /* Test if start */ + /*****************/ + + if (dw_Status & 1) { + if (dw_Status & + 2) { + if (dw_Status & 4) { + /************************/ + /* Tor counter owerflow */ + /************************/ + + *pb_TorCounterStatus + = + 3; + } else { + /***********************/ + /* Tor counter started */ + /***********************/ + + *pb_TorCounterStatus + = + 2; + } + } else { + /***********************/ + /* Tor counter started */ + /***********************/ + + *pb_TorCounterStatus + = + 1; + } + } else { + /***************************/ + /* Tor counter not started */ + /***************************/ + + *pb_TorCounterStatus + = 0; + } + break; + + case APCI1710_TOR_GETCOUNTERVALUE: + + /*****************************/ + /* Test the timout parameter */ + /*****************************/ + + if ((ui_TimeOut >= 0) + && (ui_TimeOut + <= + 65535UL)) + { + for (;;) { + /*******************/ + /* Read the status */ + /*******************/ + + dw_Status + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 4 + + + (16 * b_TorCounter) + (64 * b_ModulNbr)); + /********************/ + /* Test if overflow */ + /********************/ + + if ((dw_Status & 4) == 4) { + /******************/ + /* Overflow occur */ + /******************/ + + *pb_TorCounterStatus + = + 3; + + /******************/ + /* Read the value */ + /******************/ + + *pul_TorCounterValue + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 0 + + + (16 * b_TorCounter) + (64 * b_ModulNbr)); + break; + } // if ((dw_Status & 4) == 4) + else { + /*******************************/ + /* Test if measurement stopped */ + /*******************************/ + + if ((dw_Status & 2) == 2) { + /***********************/ + /* A stop signal occur */ + /***********************/ + + *pb_TorCounterStatus + = + 2; + + /******************/ + /* Read the value */ + /******************/ + + *pul_TorCounterValue + = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + 0 + + + (16 * b_TorCounter) + (64 * b_ModulNbr)); + + break; + } // if ((dw_Status & 2) == 2) + else { + /*******************************/ + /* Test if measurement started */ + /*******************************/ + + if ((dw_Status & 1) == 1) { + /************************/ + /* A start signal occur */ + /************************/ + + *pb_TorCounterStatus + = + 1; + } // if ((dw_Status & 1) == 1) + else { + /***************************/ + /* Measurement not started */ + /***************************/ + + *pb_TorCounterStatus + = + 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 timeout occur */ + /*************************/ + + if ((*pb_TorCounterStatus != 3) && (dw_TimeOut == ui_TimeOut) && (ui_TimeOut != 0)) { + /*****************/ + /* Timeout occur */ + /*****************/ + + *pb_TorCounterStatus + = + 4; + } + } else { + /******************************/ + /* Timeout parameter is wrong */ + /******************************/ + + DPRINTK("Timeout parameter is wrong\n"); + i_ReturnValue = + -7; + } + break; + + default: + printk("Inputs wrong\n"); + } // switch end + } // if (dw_Status & 0x1) + else { + /***************************/ + /* Tor counter not enabled */ + /***************************/ + + DPRINTK("Tor counter not enabled\n"); + i_ReturnValue = -6; + } // if (dw_Status & 0x1) + } else { + /*******************************/ + /* Tor counter not initialised */ + /*******************************/ + + DPRINTK("Tor counter not initialised\n"); + i_ReturnValue = -5; + } + } // if (b_TorCounter <= 1) + else { + /**********************************/ + /* Tor counter selection is wrong */ + /**********************************/ + + DPRINTK("Tor counter selection is wrong\n"); + i_ReturnValue = -4; + } // if (b_TorCounter <= 1) + } else { + /******************************************/ + /* The module is not a tor counter module */ + /******************************************/ + + DPRINTK("The module is not a tor counter 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_Tor.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h new file mode 100644 index 000000000000..c245d16207b8 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#define APCI1710_30MHZ 30 +#define APCI1710_33MHZ 33 +#define APCI1710_40MHZ 40 + +#define APCI1710_GATE_INPUT 10 + +#define APCI1710_TOR_SIMPLE_MODE 2 +#define APCI1710_TOR_DOUBLE_MODE 3 +#define APCI1710_TOR_QUADRUPLE_MODE 4 + +#define APCI1710_SINGLE 0 +#define APCI1710_CONTINUOUS 1 + +#define APCI1710_TOR_GETPROGRESSSTATUS 0 +#define APCI1710_TOR_GETCOUNTERVALUE 1 +#define APCI1710_TOR_READINTERRUPT 2 + +/* + * TOR_COUNTER INISIALISATION FUNCTION + */ +INT i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +INT i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + +INT i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); +/* + * TOR_COUNTER READ FUNCTION + */ +INT i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c new file mode 100644 index 000000000000..68b1d26bae13 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c @@ -0,0 +1,1038 @@ +/** +@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 : TTL.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : APCI-1710 TTL I/O module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 13/05/98 | S. Weber | TTL digital input / output implementation | + |----------|-----------|------------------------------------------------| + | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | + | | | available | + +-----------------------------------------------------------------------+ + | | | | + | | | | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "APCI1710_Ttl.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_InitTTLIODirection | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_PortAMode, | +| BYTE_ b_PortBMode, | +| BYTE_ b_PortCMode, | +| BYTE_ b_PortDMode) | ++----------------------------------------------------------------------------+ +| Task APCI1710_TTL_INIT (using defaults) : Configure the TTL I/O operating mode from selected | +| module (b_ModulNbr). You must calling this function be| +| for you call any other function witch access of TTL. | + APCI1710_TTL_INITDIRECTION(user inputs for direction) + ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_InitType = (BYTE) data[0]; + b_PortAMode = (BYTE) data[1]; + b_PortBMode = (BYTE) data[2]; + b_PortCMode = (BYTE) data[3]; + b_PortDMode = (BYTE) data[4];| ++----------------------------------------------------------------------------+ +| 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 TTL module | +| -4: Function not available for this version | +| -5: Port A mode selection is wrong | +| -6: Port B mode selection is wrong | +| -7: Port C mode selection is wrong | +| -8: Port D mode selection is wrong | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + BYTE b_ModulNbr; + BYTE b_InitType; + BYTE b_PortAMode; + BYTE b_PortBMode; + BYTE b_PortCMode; + BYTE b_PortDMode; + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + b_InitType = (BYTE) data[0]; + i_ReturnValue = insn->n; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /**************************/ + /* Test if TTL I/O module */ + /**************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_TTL_IO) { + switch (b_InitType) { + case APCI1710_TTL_INIT: + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo.b_TTLInit = 1; + + /***************************/ + /* Set TTL port A to input */ + /***************************/ + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo.b_PortConfiguration[0] = 0; + + /***************************/ + /* Set TTL port B to input */ + /***************************/ + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo.b_PortConfiguration[1] = 0; + + /***************************/ + /* Set TTL port C to input */ + /***************************/ + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo.b_PortConfiguration[2] = 0; + + /****************************/ + /* Set TTL port D to output */ + /****************************/ + + devpriv->s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo.b_PortConfiguration[3] = 1; + + /*************************/ + /* Set the configuration */ + /*************************/ + + outl(0x8, + devpriv->s_BoardInfos.ui_Address + 20 + + (64 * b_ModulNbr)); + break; + + case APCI1710_TTL_INITDIRECTION: + + b_PortAMode = (BYTE) data[1]; + b_PortBMode = (BYTE) data[2]; + b_PortCMode = (BYTE) data[3]; + b_PortDMode = (BYTE) data[4]; + + /********************/ + /* Test the version */ + /********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & 0xFFFF) >= + 0x3230) { + /************************/ + /* Test the port A mode */ + /************************/ + + if ((b_PortAMode == 0) + || (b_PortAMode == 1)) { + /************************/ + /* Test the port B mode */ + /************************/ + + if ((b_PortBMode == 0) + || (b_PortBMode == 1)) { + /************************/ + /* Test the port C mode */ + /************************/ + + if ((b_PortCMode == 0) + || (b_PortCMode + == 1)) { + /************************/ + /* Test the port D mode */ + /************************/ + + if ((b_PortDMode == 0) || (b_PortDMode == 1)) { + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo. + b_TTLInit + = + 1; + + /***********************/ + /* Set TTL port A mode */ + /***********************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration + [0] + = + b_PortAMode; + + /***********************/ + /* Set TTL port B mode */ + /***********************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration + [1] + = + b_PortBMode; + + /***********************/ + /* Set TTL port C mode */ + /***********************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration + [2] + = + b_PortCMode; + + /***********************/ + /* Set TTL port D mode */ + /***********************/ + + devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration + [3] + = + b_PortDMode; + + /*************************/ + /* Set the configuration */ + /*************************/ + + outl((b_PortAMode << 0) | (b_PortBMode << 1) | (b_PortCMode << 2) | (b_PortDMode << 3), devpriv->s_BoardInfos.ui_Address + 20 + (64 * b_ModulNbr)); + } else { + /**********************************/ + /* Port D mode selection is wrong */ + /**********************************/ + + DPRINTK("Port D mode selection is wrong\n"); + i_ReturnValue + = + -8; + } + } else { + /**********************************/ + /* Port C mode selection is wrong */ + /**********************************/ + + DPRINTK("Port C mode selection is wrong\n"); + i_ReturnValue = + -7; + } + } else { + /**********************************/ + /* Port B mode selection is wrong */ + /**********************************/ + + DPRINTK("Port B mode selection is wrong\n"); + i_ReturnValue = -6; + } + } else { + /**********************************/ + /* Port A mode selection is wrong */ + /**********************************/ + + DPRINTK("Port A mode selection is wrong\n"); + i_ReturnValue = -5; + } + } else { + /*******************************************/ + /* Function not available for this version */ + /*******************************************/ + + DPRINTK("Function not available for this version\n"); + i_ReturnValue = -4; + } + break; + + DPRINTK("\n"); + default: + printk("Bad Config Type\n"); + } // switch end + } else { + /**********************************/ + /* The module is not a TTL module */ + /**********************************/ + + DPRINTK("The module is not a TTL module\n"); + i_ReturnValue = -3; + } + } else { + /***********************/ + /* Module number error */ + /***********************/ + + DPRINTK("Module number error\n"); + i_ReturnValue = -2; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| INPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : _INT_ i_APCI1710_ReadTTLIOChannelValue | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_SelectedPort, | +| BYTE_ b_InputChannel, | +| PBYTE_ pb_ChannelStatus) | ++----------------------------------------------------------------------------+ +| Task : Read the status from selected TTL digital input | +| (b_InputChannel) ++----------------------------------------------------------------------------+ +| Task : Read the status from digital input port | +| (b_SelectedPort) from selected TTL module (b_ModulNbr) | ++----------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 7) | +| BYTE_ b_SelectedPort, : Selection from TTL I/O | +| port (0 to 2) | +| 0 : Port A selection | +| 1 : Port B selection | +| 2 : Port C selection | +| 3 : Port D selection | +| BYTE_ b_InputChannel : Selection from digital | +| input ( 0 to 2) +APCI1710_TTL_READCHANNEL + b_ModulNbr = CR_AREF(insn->chanspec); + b_SelectedPort= CR_RANGE(insn->chanspec); + b_InputChannel= CR_CHAN(insn->chanspec); + b_ReadType = (BYTE) data[0]; + + APCI1710_TTL_READPORT| + b_ModulNbr = CR_AREF(insn->chanspec); + b_SelectedPort= CR_RANGE(insn->chanspec); + b_ReadType = (BYTE) data[0]; + ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] + + PBYTE_ pb_ChannelStatus : 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 TTL module | +| -4: The selected TTL input port is wrong | +| -5: The selected TTL digital input is wrong | +| -6: TTL I/O not initialised | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg; + BYTE b_ModulNbr; + BYTE b_SelectedPort; + BYTE b_InputChannel; + BYTE b_ReadType; + PBYTE pb_ChannelStatus; + PBYTE pb_PortValue; + + i_ReturnValue = insn->n; + b_ReadType = (BYTE) data[0]; + b_ModulNbr = CR_AREF(insn->chanspec); + b_SelectedPort = CR_RANGE(insn->chanspec); + b_InputChannel = CR_CHAN(insn->chanspec); + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /**************************/ + /* Test if TTL I/O module */ + /**************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_TTL_IO) { + switch (b_ReadType) { + + case APCI1710_TTL_READCHANNEL: + pb_ChannelStatus = (PBYTE) & data[0]; + /********************************/ + /* Test the TTL I/O port number */ + /********************************/ + + if (((b_SelectedPort <= 2) + && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & + 0xFFFF) == + 0x3130)) + || ((b_SelectedPort <= 3) + && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & + 0xFFFF) >= + 0x3230))) { + /******************************************/ + /* Test the digital imnput channel number */ + /******************************************/ + + if (((b_InputChannel <= 7) + && (b_SelectedPort < 3)) + || ((b_InputChannel <= 1) + && (b_SelectedPort == + 3))) { + /******************************************/ + /* Test if the TTL I/O module initialised */ + /******************************************/ + + if (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo.b_TTLInit == + 1) { + /***********************************/ + /* Test if TTL port used for input */ + /***********************************/ + + if (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) == 0x3130) || (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) { + /**************************/ + /* Read all digital input */ + /**************************/ + + dw_StatusReg = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + (64 * b_ModulNbr)); + + *pb_ChannelStatus + = + (BYTE) ( + (dw_StatusReg + >> + (8 * b_SelectedPort)) >> b_InputChannel) & 1; + } else { + /*******************************/ + /* Selected TTL I/O port error */ + /*******************************/ + + DPRINTK("Selected TTL I/O port error\n"); + i_ReturnValue = + -4; + } + } else { + /***************************/ + /* TTL I/O not initialised */ + /***************************/ + + DPRINTK("TTL I/O not initialised\n"); + i_ReturnValue = -6; + } + } else { + /********************************/ + /* Selected digital input error */ + /********************************/ + + DPRINTK("Selected digital input error\n"); + i_ReturnValue = -5; + } + } else { + /*******************************/ + /* Selected TTL I/O port error */ + /*******************************/ + + DPRINTK("Selected TTL I/O port error\n"); + i_ReturnValue = -4; + } + break; + + case APCI1710_TTL_READPORT: + pb_PortValue = (PBYTE) & data[0]; + /********************************/ + /* Test the TTL I/O port number */ + /********************************/ + + if (((b_SelectedPort <= 2) + && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & + 0xFFFF) == + 0x3130)) + || ((b_SelectedPort <= 3) + && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & + 0xFFFF) >= + 0x3230))) { + /******************************************/ + /* Test if the TTL I/O module initialised */ + /******************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo.b_TTLInit == 1) { + /***********************************/ + /* Test if TTL port used for input */ + /***********************************/ + + if (((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] + & + 0xFFFF) + == 0x3130) + || (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) { + /**************************/ + /* Read all digital input */ + /**************************/ + + dw_StatusReg = + inl(devpriv-> + s_BoardInfos. + ui_Address + + (64 * b_ModulNbr)); + + *pb_PortValue = + (BYTE) ( + (dw_StatusReg >> + (8 * b_SelectedPort)) & 0xFF); + } else { + /*******************************/ + /* Selected TTL I/O port error */ + /*******************************/ + + DPRINTK("Selected TTL I/O port error\n"); + i_ReturnValue = -4; + } + } else { + /***************************/ + /* TTL I/O not initialised */ + /***************************/ + + DPRINTK("TTL I/O not initialised\n"); + i_ReturnValue = -5; + } + } else { + /*******************************/ + /* Selected TTL I/O port error */ + /*******************************/ + + DPRINTK("Selected TTL I/O port error\n"); + i_ReturnValue = -4; + } + break; + + default: + printk("Bad ReadType\n"); + + } //End Switch + } else { + /**********************************/ + /* The module is not a TTL module */ + /**********************************/ + + DPRINTK("The module is not a TTL 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_InsnReadTTLIOAllPortValue(comedi_device +*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read the status from all digital input ports | +| (port A, port B and port C) from selected TTL | +| module (b_ModulNbr) | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE_ b_BoardHandle : Handle of board APCI-1710| +| BYTE_ b_ModulNbr : Module number to | +| configure (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : PULONG_ pul_PortValue : Digital TTL inputs port | +| status | ++----------------------------------------------------------------------------+ +| 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 TTL module | +| -4: TTL I/O not initialised | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnReadTTLIOAllPortValue(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; + PULONG pul_PortValue; + + b_ModulNbr = (BYTE) CR_AREF(insn->chanspec); + i_ReturnValue = insn->n; + pul_PortValue = (PULONG) & data[0]; + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /**************************/ + /* Test if TTL I/O module */ + /**************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_TTL_IO) { + /******************************************/ + /* Test if the TTL I/O module initialised */ + /******************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo.b_TTLInit == 1) { + /**************************/ + /* Read all digital input */ + /**************************/ + + dw_StatusReg = inl(devpriv->s_BoardInfos. + ui_Address + (64 * b_ModulNbr)); + + /**********************/ + /* Test if TTL Rev1.0 */ + /**********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & 0xFFFF) == + 0x3130) { + *pul_PortValue = + dw_StatusReg & 0xFFFFFFUL; + } else { + /**************************************/ + /* Test if port A not used for output */ + /**************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration[0] == 1) { + *pul_PortValue = + dw_StatusReg & + 0x3FFFF00UL; + } + + /**************************************/ + /* Test if port B not used for output */ + /**************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration[1] == 1) { + *pul_PortValue = + dw_StatusReg & + 0x3FF00FFUL; + } + + /**************************************/ + /* Test if port C not used for output */ + /**************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration[2] == 1) { + *pul_PortValue = + dw_StatusReg & + 0x300FFFFUL; + } + + /**************************************/ + /* Test if port D not used for output */ + /**************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration[3] == 1) { + *pul_PortValue = + dw_StatusReg & + 0xFFFFFFUL; + } + } + } else { + /***************************/ + /* TTL I/O not initialised */ + /***************************/ + DPRINTK("TTL I/O not initialised\n"); + i_ReturnValue = -5; + } + } else { + /**********************************/ + /* The module is not a TTL module */ + /**********************************/ + DPRINTK("The module is not a TTL 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_SetTTLIOChlOn | +| (BYTE_ b_BoardHandle, | +| BYTE_ b_ModulNbr, | +| BYTE_ b_OutputChannel) +INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct 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 : Selected module number (0 to 3)| +| BYTE_ b_OutputChannel : Selection from digital output | +| channel (0 or 1) | +| 0 : PD0 | +| 1 : PD1 | +| 2 to 9 : PA | +| 10 to 17: PB | +| 18 to 25: PC | + + b_ModulNbr = CR_AREF(insn->chanspec); + b_OutputChannel= CR_CHAN(insn->chanspec); + ui_State = data[0]; // ON or OFF ++----------------------------------------------------------------------------+ +| 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 TTL I/O module | +| -4: The selected digital output is wrong | +| -5: TTL I/O not initialised see function | +| " i_APCI1710_InitTTLIO" ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = 0; + DWORD dw_StatusReg = 0; + BYTE b_ModulNbr; + BYTE b_OutputChannel; + UINT ui_State; + + i_ReturnValue = insn->n; + b_ModulNbr = CR_AREF(insn->chanspec); + b_OutputChannel = CR_CHAN(insn->chanspec); + ui_State = data[0]; // ON or OFF + + /**************************/ + /* Test the module number */ + /**************************/ + + if (b_ModulNbr < 4) { + /**************************/ + /* Test if TTL I/O module */ + /**************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModulNbr] & + 0xFFFF0000UL) == APCI1710_TTL_IO) { + /******************************************/ + /* Test if the TTL I/O module initialised */ + /******************************************/ + + if (devpriv->s_ModuleInfo[b_ModulNbr]. + s_TTLIOInfo.b_TTLInit == 1) { + /***********************************/ + /* Test the TTL I/O channel number */ + /***********************************/ + + if (((b_OutputChannel <= 1) + && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & + 0xFFFF) == + 0x3130)) + || ((b_OutputChannel <= 25) + && ((devpriv->s_BoardInfos. + dw_MolduleConfiguration + [b_ModulNbr] & + 0xFFFF) >= + 0x3230))) { + /****************************************************/ + /* Test if the selected channel is a output channel */ + /****************************************************/ + + if (((b_OutputChannel <= 1) + && (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration + [3] == 1)) + || ((b_OutputChannel >= 2) + && (b_OutputChannel <= + 9) + && (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration + [0] == 1)) + || ((b_OutputChannel >= 10) + && (b_OutputChannel <= + 17) + && (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration + [1] == 1)) + || ((b_OutputChannel >= 18) + && (b_OutputChannel <= + 25) + && (devpriv-> + s_ModuleInfo + [b_ModulNbr]. + s_TTLIOInfo. + b_PortConfiguration + [2] == 1))) { + /************************/ + /* Test if PD0 selected */ + /************************/ + + if (b_OutputChannel == 0) { + + outl(ui_State, + devpriv-> + s_BoardInfos. + ui_Address + + (64 * b_ModulNbr)); + } else { + /************************/ + /* Test if PD1 selected */ + /************************/ + + if (b_OutputChannel == + 1) { + + outl(ui_State, + devpriv-> + s_BoardInfos. + ui_Address + + 4 + + (64 * b_ModulNbr)); + } else { + b_OutputChannel + = + b_OutputChannel + - 2; + + /********************/ + /* Read all channel */ + /********************/ + + dw_StatusReg = + inl + (devpriv-> + s_BoardInfos. + ui_Address + + + (64 * b_ModulNbr)); + if (ui_State) // ON + { + dw_StatusReg + = + (dw_StatusReg + >> + ((b_OutputChannel / 8) * 8)) & 0xFF; + dw_StatusReg + = + dw_StatusReg + | + (1 + << + (b_OutputChannel + % + 8)); + } else // Off + { + dw_StatusReg + = + (dw_StatusReg + >> + ((b_OutputChannel / 8) * 8)) & 0xFF; + dw_StatusReg + = + dw_StatusReg + & + (0xFF + - + (1 << (b_OutputChannel % 8))); + + } + + /****************************/ + /* Set the new output value */ + /****************************/ + + outl(dw_StatusReg, devpriv->s_BoardInfos.ui_Address + 8 + ((b_OutputChannel / 8) * 4) + (64 * b_ModulNbr)); + } + } + } else { + /************************************/ + /* The selected TTL output is wrong */ + /************************************/ + + DPRINTK(" The selected TTL output is wrong\n"); + i_ReturnValue = -4; + } + } else { + /************************************/ + /* The selected TTL output is wrong */ + /************************************/ + + DPRINTK("The selected TTL output is wrong\n"); + i_ReturnValue = -4; + } + } else { + /***************************/ + /* TTL I/O not initialised */ + /***************************/ + + DPRINTK("TTL I/O not initialised\n"); + i_ReturnValue = -5; + } + } else { + /**************************************/ + /* The module is not a TTL I/O module */ + /**************************************/ + + DPRINTK("The module is not a TTL I/O 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_Ttl.h b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h new file mode 100644 index 000000000000..00915ddf9218 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#define APCI1710_TTL_INIT 0 +#define APCI1710_TTL_INITDIRECTION 1 + +#define APCI1710_TTL_READCHANNEL 0 +#define APCI1710_TTL_READPORT 1 + +/* + * TTL INISIALISATION FUNCTION + */ +INT i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +/* + * TTL INPUT FUNCTION + */ +INT i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +/* + * TTL OUTPUT FUNCTIONS + */ +INT i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c new file mode 100644 index 000000000000..b0907ec14667 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c @@ -0,0 +1,203 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : ADDI HEADER READ WRITER | Compiler : Visual C++ | + | Module name : S5920.cpp | Version : 6.0 | + +-------------------------------+---------------------------------------+ + | Author : E. LIBS Date : 02/05/2002 | + +-----------------------------------------------------------------------+ + | Description : DLL with the S5920 PCI Controller functions | + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 28/08/02 | LIBS Eric | Add return codes each time a function of the | + | | | Addi Library is called | + +-----------------------------------------------------------------------+ + | 31/07/03 | KRAUTH J. | Changes for the MSX-Box | + +-----------------------------------------------------------------------+ +*/ + +#include "addi_amcc_S5920.h" + +/*+----------------------------------------------------------------------------+*/ +/*| Function Name : INT i_AddiHeaderRW_ReadEeprom |*/ +/*| (INT i_NbOfWordsToRead, |*/ +/*| DWORD dw_PCIBoardEepromAddress, |*/ +/*| WORD w_EepromStartAddress, |*/ +/*| PWORD pw_DataRead) |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Task : Read word from the 5920 eeprom. |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Input Parameters : INT i_NbOfWordsToRead : Nbr. of word to read |*/ +/*| DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/ +/*| WORD w_EepromStartAddress : Eeprom strat address |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Output Parameters : PWORD pw_DataRead : Read data |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Return Value : - |*/ +/*+----------------------------------------------------------------------------+*/ + +INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead, + DWORD dw_PCIBoardEepromAddress, + WORD w_EepromStartAddress, PWORD pw_DataRead) +{ + DWORD dw_eeprom_busy = 0; + INT i_Counter = 0; + INT i_WordCounter; + INT i; + BYTE pb_ReadByte[1]; + BYTE b_ReadLowByte = 0; + BYTE b_ReadHighByte = 0; + BYTE b_SelectedAddressLow = 0; + BYTE b_SelectedAddressHigh = 0; + WORD w_ReadWord = 0; + + for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead; + i_WordCounter++) { + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + for (i_Counter = 0; i_Counter < 2; i_Counter++) { + b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256; //Read the low 8 bit part + b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256; //Read the high 8 bit part + + //Select the load low address mode + outb(NVCMD_LOAD_LOW, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 3); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Load the low address + outb(b_SelectedAddressLow, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 2); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Select the load high address mode + outb(NVCMD_LOAD_HIGH, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 3); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Load the high address + outb(b_SelectedAddressHigh, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 2); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Select the READ mode + outb(NVCMD_BEGIN_READ, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 3); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Read data into the EEPROM + *pb_ReadByte = + inb(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR + 2); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Select the upper address part + if (i_Counter == 0) { + b_ReadLowByte = pb_ReadByte[0]; + } else { + b_ReadHighByte = pb_ReadByte[0]; + } + + //Sleep + for (i = 0; i < 10000; i++) ; + + } + w_ReadWord = + (b_ReadLowByte | (((unsigned short)b_ReadHighByte) * + 256)); + + pw_DataRead[i_WordCounter] = w_ReadWord; + + w_EepromStartAddress += 2; // to read the next word + + } // for (...) i_NbOfWordsToRead + return (0); +} diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h new file mode 100644 index 000000000000..9ae56bc3adad --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#define AMCC_OP_REG_MCSR 0x3c +#define EEPROM_BUSY 0x80000000 +#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */ +#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */ +#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */ +#define NVCMD_BEGIN_WRITE (0x6 << 5) /* EEPROM begin write command */ + +INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead, + DWORD dw_PCIBoardEepromAddress, + WORD w_EepromStartAddress, PWORD pw_DataRead); diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h new file mode 100644 index 000000000000..b50774cdcf77 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_s5933.h @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/* Header file for AMCC s 5933 */ + +#ifndef _AMCC_S5933_H_ +#define _AMCC_S5933_H_ + +#include "../../comedidev.h" + +#include "../comedi_pci.h" + +#ifdef PCI_SUPPORT_VER1 +#error No support for 2.1.55 and older +#endif + +/* written on base0 */ +#define FIFO_ADVANCE_ON_BYTE_2 0x20000000 + +/* added for step 6 dma written on base2 */ +#define AMWEN_ENABLE 0x02 + +#define A2P_FIFO_WRITE_ENABLE 0x01 + +/* for transfer count enable bit */ +#define AGCSTS_TC_ENABLE 0x10000000 + +/* + * ADDON RELATED ADDITIONS + */ +/* Constant */ +#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00 +#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200 +#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L +#define APCI3120_AMWEN_ENABLE 0x02 +#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01 +#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L +#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L +#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L +#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0 +#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0 +#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0 + +/* ADD_ON ::: this needed since apci supports 16 bit interface to add on */ +#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C +#define APCI3120_ADD_ON_AGCSTS_HIGH (APCI3120_ADD_ON_AGCSTS_LOW + 2) +#define APCI3120_ADD_ON_MWAR_LOW 0x24 +#define APCI3120_ADD_ON_MWAR_HIGH (APCI3120_ADD_ON_MWAR_LOW + 2) +#define APCI3120_ADD_ON_MWTC_LOW 0x058 +#define APCI3120_ADD_ON_MWTC_HIGH (APCI3120_ADD_ON_MWTC_LOW + 2) + +/* AMCC */ +#define APCI3120_AMCC_OP_MCSR 0x3C +#define APCI3120_AMCC_OP_REG_INTCSR 0x38 + +/* + * AMCC Operation Register Offsets - PCI + */ +#define AMCC_OP_REG_OMB1 0x00 +#define AMCC_OP_REG_OMB2 0x04 +#define AMCC_OP_REG_OMB3 0x08 +#define AMCC_OP_REG_OMB4 0x0c +#define AMCC_OP_REG_IMB1 0x10 +#define AMCC_OP_REG_IMB2 0x14 +#define AMCC_OP_REG_IMB3 0x18 +#define AMCC_OP_REG_IMB4 0x1c +#define AMCC_OP_REG_FIFO 0x20 +#define AMCC_OP_REG_MWAR 0x24 +#define AMCC_OP_REG_MWTC 0x28 +#define AMCC_OP_REG_MRAR 0x2c +#define AMCC_OP_REG_MRTC 0x30 +#define AMCC_OP_REG_MBEF 0x34 +#define AMCC_OP_REG_INTCSR 0x38 +/* INT source */ +#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) +/* FIFO ctrl */ +#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) +#define AMCC_OP_REG_MCSR 0x3c +/* Data in byte 2 */ +#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) +/* Command in byte 3 */ +#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) + +#define AMCC_FIFO_DEPTH_DWORD 8 +#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof(u32)) + +/* + * AMCC Operation Registers Size - PCI + */ +#define AMCC_OP_REG_SIZE 64 /* in bytes */ + +/* + * AMCC Operation Register Offsets - Add-on + */ +#define AMCC_OP_REG_AIMB1 0x00 +#define AMCC_OP_REG_AIMB2 0x04 +#define AMCC_OP_REG_AIMB3 0x08 +#define AMCC_OP_REG_AIMB4 0x0c +#define AMCC_OP_REG_AOMB1 0x10 +#define AMCC_OP_REG_AOMB2 0x14 +#define AMCC_OP_REG_AOMB3 0x18 +#define AMCC_OP_REG_AOMB4 0x1c +#define AMCC_OP_REG_AFIFO 0x20 +#define AMCC_OP_REG_AMWAR 0x24 +#define AMCC_OP_REG_APTA 0x28 +#define AMCC_OP_REG_APTD 0x2c +#define AMCC_OP_REG_AMRAR 0x30 +#define AMCC_OP_REG_AMBEF 0x34 +#define AMCC_OP_REG_AINT 0x38 +#define AMCC_OP_REG_AGCSTS 0x3c +#define AMCC_OP_REG_AMWTC 0x58 +#define AMCC_OP_REG_AMRTC 0x5c + +/* + * AMCC - Add-on General Control/Status Register + */ +#define AGCSTS_CONTROL_MASK 0xfffff000 +#define AGCSTS_NV_ACC_MASK 0xe0000000 +#define AGCSTS_RESET_MASK 0x0e000000 +#define AGCSTS_NV_DA_MASK 0x00ff0000 +#define AGCSTS_BIST_MASK 0x0000f000 +#define AGCSTS_STATUS_MASK 0x000000ff +#define AGCSTS_TCZERO_MASK 0x000000c0 +#define AGCSTS_FIFO_ST_MASK 0x0000003f + +#define AGCSTS_RESET_MBFLAGS 0x08000000 +#define AGCSTS_RESET_P2A_FIFO 0x04000000 +#define AGCSTS_RESET_A2P_FIFO 0x02000000 +#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO) + +#define AGCSTS_A2P_TCOUNT 0x00000080 +#define AGCSTS_P2A_TCOUNT 0x00000040 + +#define AGCSTS_FS_P2A_EMPTY 0x00000020 +#define AGCSTS_FS_P2A_HALF 0x00000010 +#define AGCSTS_FS_P2A_FULL 0x00000008 + +#define AGCSTS_FS_A2P_EMPTY 0x00000004 +#define AGCSTS_FS_A2P_HALF 0x00000002 +#define AGCSTS_FS_A2P_FULL 0x00000001 + +/* + * AMCC - Add-on Interrupt Control/Status Register + */ +#define AINT_INT_MASK 0x00ff0000 +#define AINT_SEL_MASK 0x0000ffff +#define AINT_IS_ENSEL_MASK 0x00001f1f + +#define AINT_INT_ASSERTED 0x00800000 +#define AINT_BM_ERROR 0x00200000 +#define AINT_BIST_INT 0x00100000 + +#define AINT_RT_COMPLETE 0x00080000 +#define AINT_WT_COMPLETE 0x00040000 + +#define AINT_OUT_MB_INT 0x00020000 +#define AINT_IN_MB_INT 0x00010000 + +#define AINT_READ_COMPL 0x00008000 +#define AINT_WRITE_COMPL 0x00004000 + +#define AINT_OMB_ENABLE 0x00001000 +#define AINT_OMB_SELECT 0x00000c00 +#define AINT_OMB_BYTE 0x00000300 + +#define AINT_IMB_ENABLE 0x00000010 +#define AINT_IMB_SELECT 0x0000000c +#define AINT_IMB_BYTE 0x00000003 + +/* Enable Bus Mastering */ +#define EN_A2P_TRANSFERS 0x00000400 +/* FIFO Flag Reset */ +#define RESET_A2P_FLAGS 0x04000000L +/* FIFO Relative Priority */ +#define A2P_HI_PRIORITY 0x00000100L +/* Identify Interrupt Sources */ +#define ANY_S593X_INT 0x00800000L +#define READ_TC_INT 0x00080000L +#define WRITE_TC_INT 0x00040000L +#define IN_MB_INT 0x00020000L +#define MASTER_ABORT_INT 0x00100000L +#define TARGET_ABORT_INT 0x00200000L +#define BUS_MASTER_INT 0x00200000L + +/****************************************************************************/ + +struct pcilst_struct { + struct pcilst_struct *next; + int used; + struct pci_dev *pcidev; + unsigned short vendor; + unsigned short device; + unsigned char pci_bus; + unsigned char pci_slot; + unsigned char pci_func; + resource_size_t io_addr[5]; + unsigned int irq; +}; + +/* ptr to root list of all amcc devices */ +struct pcilst_struct *amcc_devices; + +static const int i_ADDIDATADeviceID[] = { 0x15B8, 0x10E8 }; + +/****************************************************************************/ + +void v_pci_card_list_init(unsigned short pci_vendor, char display); +void v_pci_card_list_cleanup(unsigned short pci_vendor); +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, + unsigned short + device_id); +int i_find_free_pci_card_by_position(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + struct pcilst_struct **card); +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + int i_Master); + +int pci_card_alloc(struct pcilst_struct *amcc, int master); +int i_pci_card_free(struct pcilst_struct *amcc); +void v_pci_card_list_display(void); +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, + unsigned char *pci_func, resource_size_t * io_addr, + unsigned int *irq); + +/****************************************************************************/ + +/* build list of amcc cards in this system */ +void v_pci_card_list_init(unsigned short pci_vendor, char display) +{ + struct pci_dev *pcidev; + struct pcilst_struct *amcc, *last; + int i; + int i_Count = 0; + amcc_devices = NULL; + last = NULL; + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + for (i_Count = 0; i_Count < 2; i_Count++) { + pci_vendor = i_ADDIDATADeviceID[i_Count]; + if (pcidev->vendor == pci_vendor) { + amcc = kmalloc(sizeof(*amcc), GFP_KERNEL); + memset(amcc, 0, sizeof(*amcc)); + + amcc->pcidev = pcidev; + if (last) + last->next = amcc; + else + amcc_devices = amcc; + last = amcc; + + amcc->vendor = pcidev->vendor; + amcc->device = pcidev->device; + amcc->pci_bus = pcidev->bus->number; + amcc->pci_slot = PCI_SLOT(pcidev->devfn); + amcc->pci_func = PCI_FUNC(pcidev->devfn); + /* Note: resources may be invalid if PCI device + * not enabled, but they are corrected in + * pci_card_alloc. */ + for (i = 0; i < 5; i++) + amcc->io_addr[i] = + pci_resource_start(pcidev, i); + amcc->irq = pcidev->irq; + + } + } + } + + if (display) + v_pci_card_list_display(); +} + +/****************************************************************************/ +/* free up list of amcc cards in this system */ +void v_pci_card_list_cleanup(unsigned short pci_vendor) +{ + struct pcilst_struct *amcc, *next; + + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + kfree(amcc); + } + + amcc_devices = NULL; +} + +/****************************************************************************/ +/* find first unused card with this device_id */ +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, + unsigned short device_id) +{ + struct pcilst_struct *amcc, *next; + + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + if ((!amcc->used) && (amcc->device == device_id) + && (amcc->vendor == vendor_id)) + return amcc; + + } + + return NULL; +} + +/****************************************************************************/ +/* find card on requested position */ +int i_find_free_pci_card_by_position(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + struct pcilst_struct **card) +{ + struct pcilst_struct *amcc, *next; + + *card = NULL; + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + if ((amcc->vendor == vendor_id) && (amcc->device == device_id) + && (amcc->pci_bus == pci_bus) + && (amcc->pci_slot == pci_slot)) { + if (!(amcc->used)) { + *card = amcc; + return 0; /* ok, card is found */ + } else { + rt_printk(" - \nCard on requested position is used b:s %d:%d!\n", + pci_bus, pci_slot); + return 2; /* card exist but is used */ + } + } + } + + /* no card found */ + return 1; +} + +/****************************************************************************/ +/* mark card as used */ +int pci_card_alloc(struct pcilst_struct *amcc, int master) +{ + int i; + + if (!amcc) + return -1; + + if (amcc->used) + return 1; + if (comedi_pci_enable(amcc->pcidev, "addi_amcc_s5933")) + return -1; + /* Resources will be accurate now. */ + for (i = 0; i < 5; i++) + amcc->io_addr[i] = pci_resource_start(amcc->pcidev, i); + if (master) + pci_set_master(amcc->pcidev); + amcc->used = 1; + + return 0; +} + +/****************************************************************************/ +/* mark card as free */ +int i_pci_card_free(struct pcilst_struct *amcc) +{ + if (!amcc) + return -1; + + if (!amcc->used) + return 1; + amcc->used = 0; + comedi_pci_disable(amcc->pcidev); + return 0; +} + +/****************************************************************************/ +/* display list of found cards */ +void v_pci_card_list_display(void) +{ + struct pcilst_struct *amcc, *next; + + printk(KERN_DEBUG "List of pci cards\n"); + printk(KERN_DEBUG "bus:slot:func vendor device io_amcc io_daq irq used\n"); + + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + printk + ("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n", + amcc->pci_bus, amcc->pci_slot, amcc->pci_func, + amcc->vendor, amcc->device, + (unsigned long long)amcc->io_addr[0], + (unsigned long long)amcc->io_addr[2], amcc->irq, + amcc->used); + + } +} + +/****************************************************************************/ +/* return all card information for driver */ +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, + unsigned char *pci_func, resource_size_t * io_addr, + unsigned int *irq) +{ + int i; + + if (!amcc) + return -1; + *pci_bus = amcc->pci_bus; + *pci_slot = amcc->pci_slot; + *pci_func = amcc->pci_func; + for (i = 0; i < 5; i++) + io_addr[i] = amcc->io_addr[i]; + *irq = amcc->irq; + return 0; +} + +/****************************************************************************/ +/* select and alloc card */ +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + int i_Master) +{ + struct pcilst_struct *card; + + if ((pci_bus < 1) & (pci_slot < 1)) { + /* use autodetection */ + card = ptr_find_free_pci_card_by_device(vendor_id, device_id); + if (card == NULL) { + rt_printk(" - Unused card not found in system!\n"); + return NULL; + } + } else { + switch (i_find_free_pci_card_by_position(vendor_id, device_id, + pci_bus, pci_slot, + &card)) { + case 1: + rt_printk(" - Card not found on requested position b:s %d:%d!\n", + pci_bus, pci_slot); + return NULL; + case 2: + rt_printk(" - Card on requested position is used b:s %d:%d!\n", + pci_bus, pci_slot); + return NULL; + } + } + + if (pci_card_alloc(card, i_Master) != 0) { + rt_printk(" - Can't allocate card!\n"); + return NULL; + + } + + return card; +} +#endif diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c new file mode 100644 index 000000000000..618c69b6838d --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -0,0 +1,3062 @@ +/** +@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 Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : ADDI DATA | Compiler : GCC | + | Modulname : addi_common.c | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Author : | Date : | + +-----------------------------------------------------------------------+ + | Description : ADDI COMMON Main Module | + +-----------------------------------------------------------------------+ + | CONFIG OPTIONS | + | option[0] - PCI bus number - if bus number and slot number are 0, | + | then driver search for first unused card | + | option[1] - PCI slot number | + | | + | option[2] = 0 - DMA ENABLE | + | = 1 - DMA DISABLE | + +----------+-----------+------------------------------------------------+ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../comedidev.h" +#include +#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300) +#include +#endif +#include "../comedi_fc.h" + +#include "addi_common.h" +#include "addi_amcc_s5933.h" + +//Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH "); +//Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); +//Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); + +#define devpriv ((addi_private *)dev->private) +#define this_board ((boardtype *)dev->board_ptr) + +#if defined(CONFIG_APCI_1710) || defined(CONFIG_APCI_3200) || defined(CONFIG_APCI_3300) +//BYTE b_SaveFPUReg [94]; + +void fpu_begin(void) +{ + //asm ("fstenv b_SaveFPUReg"); + kernel_fpu_begin(); +} + +void fpu_end(void) +{ + // asm ("frstor b_SaveFPUReg"); + kernel_fpu_end(); +} +#endif + +#include "addi_eeprom.c" +#if (defined (CONFIG_APCI_3120) || defined (CONFIG_APCI_3001)) +#include "hwdrv_apci3120.c" +#endif +#ifdef CONFIG_APCI_1032 +#include "hwdrv_apci1032.c" +#endif +#ifdef CONFIG_APCI_1516 +#include "hwdrv_apci1516.c" +#endif +#ifdef CONFIG_APCI_2016 +#include "hwdrv_apci2016.c" +#endif +#ifdef CONFIG_APCI_2032 +#include "hwdrv_apci2032.c" +#endif +#ifdef CONFIG_APCI_2200 +#include "hwdrv_apci2200.c" +#endif +#ifdef CONFIG_APCI_1564 +#include "hwdrv_apci1564.c" +#endif +#ifdef CONFIG_APCI_1500 +#include "hwdrv_apci1500.c" +#endif +#ifdef CONFIG_APCI_3501 +#include "hwdrv_apci3501.c" +#endif +#ifdef CONFIG_APCI_035 +#include "hwdrv_apci035.c" +#endif +#if (defined (CONFIG_APCI_3200) || defined (CONFIG_APCI_3300)) +#include "hwdrv_apci3200.c" +#endif +#ifdef CONFIG_APCI_1710 +#include "hwdrv_APCI1710.c" +#endif +#ifdef CONFIG_APCI_16XX +#include "hwdrv_apci16xx.c" +#endif +#ifdef CONFIG_APCI_3XXX +#include "hwdrv_apci3xxx.c" +#endif + +#ifndef COMEDI_SUBD_TTLIO +#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */ +#endif + +static DEFINE_PCI_DEVICE_TABLE(addi_apci_tbl) = { +#ifdef CONFIG_APCI_3120 + {APCI3120_BOARD_VENDOR_ID, 0x818D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_1032 + {APCI1032_BOARD_VENDOR_ID, 0x1003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_1516 + {APCI1516_BOARD_VENDOR_ID, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_2016 + {APCI2016_BOARD_VENDOR_ID, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_2032 + {APCI2032_BOARD_VENDOR_ID, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_2200 + {APCI2200_BOARD_VENDOR_ID, 0x1005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_1564 + {APCI1564_BOARD_VENDOR_ID, 0x1006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_1500 + {APCI1500_BOARD_VENDOR_ID, 0x80fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_3001 + {APCI3120_BOARD_VENDOR_ID, 0x828D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_3501 + {APCI3501_BOARD_VENDOR_ID, 0x3001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_035 + {APCI035_BOARD_VENDOR_ID, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_3200 + {APCI3200_BOARD_VENDOR_ID, 0x3000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_3300 + {APCI3200_BOARD_VENDOR_ID, 0x3007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_1710 + {APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_16XX + {0x15B8, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x100A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif +#ifdef CONFIG_APCI_3XXX + {0x15B8, 0x3010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x300F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x300E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x301A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x301B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x301C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x301D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x301E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x301F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x300B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x15B8, 0x3024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +#endif + {0} +}; + +MODULE_DEVICE_TABLE(pci, addi_apci_tbl); + +static const boardtype boardtypes[] = { +#ifdef CONFIG_APCI_3120 + {"apci3120", + APCI3120_BOARD_VENDOR_ID, + 0x818D, + AMCC_OP_REG_SIZE, + APCI3120_ADDRESS_RANGE, + 8, + 0, + ADDIDATA_NO_EEPROM, + NULL, + 16, + 8, + 16, + 8, + 0xffff, + 0x3fff, + &range_apci3120_ai, + &range_apci3120_ao, + 4, + 4, + 0x0f, + 0, + NULL, + 1, + 1, + 1, + 10000, + 100000, + v_APCI3120_Interrupt, + i_APCI3120_Reset, + i_APCI3120_InsnConfigAnalogInput, + i_APCI3120_InsnReadAnalogInput, + NULL, + NULL, + i_APCI3120_CommandTestAnalogInput, + i_APCI3120_CommandAnalogInput, + i_APCI3120_StopCyclicAcquisition, + NULL, + i_APCI3120_InsnWriteAnalogOutput, + NULL, + NULL, + i_APCI3120_InsnReadDigitalInput, + NULL, + i_APCI3120_InsnBitsDigitalInput, + i_APCI3120_InsnConfigDigitalOutput, + i_APCI3120_InsnWriteDigitalOutput, + i_APCI3120_InsnBitsDigitalOutput, + NULL, + i_APCI3120_InsnConfigTimer, + i_APCI3120_InsnWriteTimer, + i_APCI3120_InsnReadTimer, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_1032 + {"apci1032", + APCI1032_BOARD_VENDOR_ID, + 0x1003, + 4, + APCI1032_ADDRESS_RANGE, + 0, + 0, + ADDIDATA_EEPROM, + ADDIDATA_93C76, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 32, + 0, + 0, + 0, + NULL, + 0, + 0, + 0, + 0, + 0, + v_APCI1032_Interrupt, + i_APCI1032_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI1032_ConfigDigitalInput, + i_APCI1032_Read1DigitalInput, + NULL, + i_APCI1032_ReadMoreDigitalInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_1516 + {"apci1516", + APCI1516_BOARD_VENDOR_ID, + 0x1001, + 128, + APCI1516_ADDRESS_RANGE, + 32, + 0, + ADDIDATA_EEPROM, + ADDIDATA_S5920, + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, + 8, + 8, + 0, + 0, + NULL, + 0, + 1, + 0, + 0, + 0, + NULL, + i_APCI1516_Reset, + NULL, NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI1516_Read1DigitalInput, + NULL, + i_APCI1516_ReadMoreDigitalInput, + i_APCI1516_ConfigDigitalOutput, + i_APCI1516_WriteDigitalOutput, + i_APCI1516_ReadDigitalOutput, + NULL, + i_APCI1516_ConfigWatchdog, + i_APCI1516_StartStopWriteWatchdog, + i_APCI1516_ReadWatchdog, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_2016 + {"apci2016", + APCI2016_BOARD_VENDOR_ID, + 0x1002, + 128, + APCI2016_ADDRESS_RANGE, + 32, + 0, + ADDIDATA_EEPROM, + ADDIDATA_S5920, + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, + 0, + 16, + 0, + 0, + NULL, + 0, + 1, + 0, + 0, + 0, + NULL, + i_APCI2016_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI2016_ConfigDigitalOutput, + i_APCI2016_WriteDigitalOutput, + i_APCI2016_BitsDigitalOutput, + NULL, + i_APCI2016_ConfigWatchdog, + i_APCI2016_StartStopWriteWatchdog, + i_APCI2016_ReadWatchdog, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_2032 + {"apci2032", + APCI2032_BOARD_VENDOR_ID, + 0x1004, + 4, + APCI2032_ADDRESS_RANGE, + 0, + 0, + ADDIDATA_EEPROM, + ADDIDATA_93C76, + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, + 0, + 32, + 0xffffffff, + 0, + NULL, + 0, + 1, + 0, + 0, + 0, + v_APCI2032_Interrupt, + i_APCI2032_Reset, + NULL, NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI2032_ConfigDigitalOutput, + i_APCI2032_WriteDigitalOutput, + i_APCI2032_ReadDigitalOutput, + i_APCI2032_ReadInterruptStatus, + i_APCI2032_ConfigWatchdog, + i_APCI2032_StartStopWriteWatchdog, + i_APCI2032_ReadWatchdog, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_2200 + {"apci2200", + APCI2200_BOARD_VENDOR_ID, + 0x1005, + 4, + APCI2200_ADDRESS_RANGE, + 0, + 0, + ADDIDATA_EEPROM, + ADDIDATA_93C76, + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, + 8, + 16, + 0, + 0, + NULL, + 0, + 1, + 0, + 0, + 0, + NULL, + i_APCI2200_Reset, + NULL, NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI2200_Read1DigitalInput, + NULL, + i_APCI2200_ReadMoreDigitalInput, + i_APCI2200_ConfigDigitalOutput, + i_APCI2200_WriteDigitalOutput, + i_APCI2200_ReadDigitalOutput, + NULL, + i_APCI2200_ConfigWatchdog, + i_APCI2200_StartStopWriteWatchdog, + i_APCI2200_ReadWatchdog, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_1564 + {"apci1564", + APCI1564_BOARD_VENDOR_ID, + 0x1006, + 128, + APCI1564_ADDRESS_RANGE, + 0, + 0, + ADDIDATA_EEPROM, + ADDIDATA_93C76, + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, + 32, + 32, + 0xffffffff, + 0, + NULL, + 0, + 1, + 0, + 0, + 0, + v_APCI1564_Interrupt, + i_APCI1564_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI1564_ConfigDigitalInput, + i_APCI1564_Read1DigitalInput, + NULL, + i_APCI1564_ReadMoreDigitalInput, + i_APCI1564_ConfigDigitalOutput, + i_APCI1564_WriteDigitalOutput, + i_APCI1564_ReadDigitalOutput, + i_APCI1564_ReadInterruptStatus, + i_APCI1564_ConfigTimerCounterWatchdog, + i_APCI1564_StartStopWriteTimerCounterWatchdog, + i_APCI1564_ReadTimerCounterWatchdog, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_1500 + {"apci1500", + APCI1500_BOARD_VENDOR_ID, + 0x80fc, + 128, + APCI1500_ADDRESS_RANGE, + 4, + 0, + ADDIDATA_NO_EEPROM, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, + 16, + 16, + 0xffff, + 0, + NULL, + 0, + 1, + 0, + 0, + 0, + v_APCI1500_Interrupt, + i_APCI1500_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI1500_ConfigDigitalInputEvent, + i_APCI1500_Initialisation, + i_APCI1500_StartStopInputEvent, + i_APCI1500_ReadMoreDigitalInput, + i_APCI1500_ConfigDigitalOutputErrorInterrupt, + i_APCI1500_WriteDigitalOutput, + i_APCI1500_ConfigureInterrupt, + NULL, + i_APCI1500_ConfigCounterTimerWatchdog, + i_APCI1500_StartStopTriggerTimerCounterWatchdog, + i_APCI1500_ReadInterruptMask, + i_APCI1500_ReadCounterTimerWatchdog, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_3001 + {"apci3001", + APCI3120_BOARD_VENDOR_ID, + 0x828D, + AMCC_OP_REG_SIZE, + APCI3120_ADDRESS_RANGE, + 8, + 0, + ADDIDATA_NO_EEPROM, + NULL, + 16, + 8, + 16, + 0, + 0xfff, + 0, + &range_apci3120_ai, + NULL, + 4, + 4, + 0x0f, + 0, + NULL, + 1, + 1, + 1, + 10000, + 100000, + v_APCI3120_Interrupt, + i_APCI3120_Reset, + i_APCI3120_InsnConfigAnalogInput, + i_APCI3120_InsnReadAnalogInput, + NULL, + NULL, + i_APCI3120_CommandTestAnalogInput, + i_APCI3120_CommandAnalogInput, + i_APCI3120_StopCyclicAcquisition, + NULL, + NULL, + NULL, + NULL, + i_APCI3120_InsnReadDigitalInput, + NULL, + i_APCI3120_InsnBitsDigitalInput, + i_APCI3120_InsnConfigDigitalOutput, + i_APCI3120_InsnWriteDigitalOutput, + i_APCI3120_InsnBitsDigitalOutput, + NULL, + i_APCI3120_InsnConfigTimer, + i_APCI3120_InsnWriteTimer, + i_APCI3120_InsnReadTimer, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_3501 + {"apci3501", + APCI3501_BOARD_VENDOR_ID, + 0x3001, + 64, + APCI3501_ADDRESS_RANGE, + 0, + 0, + ADDIDATA_EEPROM, + ADDIDATA_S5933, + 0, + 0, + 0, + 8, + 0, + 16383, + NULL, + &range_apci3501_ao, + 2, + 2, + 0x3, + 0, + NULL, + 0, + 1, + 0, + 0, + 0, + v_APCI3501_Interrupt, + i_APCI3501_Reset, + NULL, NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3501_ConfigAnalogOutput, + i_APCI3501_WriteAnalogOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3501_ReadDigitalInput, + i_APCI3501_ConfigDigitalOutput, + i_APCI3501_WriteDigitalOutput, + i_APCI3501_ReadDigitalOutput, + NULL, + i_APCI3501_ConfigTimerCounterWatchdog, + i_APCI3501_StartStopWriteTimerCounterWatchdog, + i_APCI3501_ReadTimerCounterWatchdog, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_035 + {"apci035", + APCI035_BOARD_VENDOR_ID, + 0x0300, + 127, + APCI035_ADDRESS_RANGE, + 0, + 0, + 1, + ADDIDATA_S5920, + 16, + 8, + 16, + 0, + 0xff, + 0, + &range_apci035_ai, + NULL, + 0, + 0, + 0, + 0, + NULL, + 0, + 1, + 0, + 10000, + 100000, + v_APCI035_Interrupt, + i_APCI035_Reset, + i_APCI035_ConfigAnalogInput, + i_APCI035_ReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI035_ConfigTimerWatchdog, + i_APCI035_StartStopWriteTimerWatchdog, + i_APCI035_ReadTimerWatchdog, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_3200 + {"apci3200", + APCI3200_BOARD_VENDOR_ID, + 0x3000, + 128, + 256, + 4, + 4, + ADDIDATA_EEPROM, + ADDIDATA_S5920, + 16, + 8, + 16, + 0, + 0x3ffff, + 0, + &range_apci3200_ai, + NULL, + 4, + 4, + 0, + 0, + NULL, + 0, + 0, + 0, + 10000, + 100000, + v_APCI3200_Interrupt, + i_APCI3200_Reset, + i_APCI3200_ConfigAnalogInput, + i_APCI3200_ReadAnalogInput, + i_APCI3200_InsnWriteReleaseAnalogInput, + i_APCI3200_InsnBits_AnalogInput_Test, + i_APCI3200_CommandTestAnalogInput, + i_APCI3200_CommandAnalogInput, + i_APCI3200_StopCyclicAcquisition, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3200_ReadDigitalInput, + i_APCI3200_ConfigDigitalOutput, + i_APCI3200_WriteDigitalOutput, + i_APCI3200_ReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_3300 + //Begin JK 20.10.2004: APCI-3300 integration + {"apci3300", + APCI3200_BOARD_VENDOR_ID, + 0x3007, + 128, + 256, + 4, + 4, + ADDIDATA_EEPROM, + ADDIDATA_S5920, + 0, + 8, + 8, + 0, + 0x3ffff, + 0, + &range_apci3300_ai, + NULL, + 4, + 4, + 0, + 0, + NULL, + 0, + 0, + 0, + 10000, + 100000, + v_APCI3200_Interrupt, + i_APCI3200_Reset, + i_APCI3200_ConfigAnalogInput, + i_APCI3200_ReadAnalogInput, + i_APCI3200_InsnWriteReleaseAnalogInput, + i_APCI3200_InsnBits_AnalogInput_Test, + i_APCI3200_CommandTestAnalogInput, + i_APCI3200_CommandAnalogInput, + i_APCI3200_StopCyclicAcquisition, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3200_ReadDigitalInput, + i_APCI3200_ConfigDigitalOutput, + i_APCI3200_WriteDigitalOutput, + i_APCI3200_ReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_1710 + {"apci1710", APCI1710_BOARD_VENDOR_ID, APCI1710_BOARD_DEVICE_ID, + 128, + 8, + 256, + 0, + ADDIDATA_NO_EEPROM, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, + 0, + 0, + 0, + 0, + NULL, + 0, + 0, + 0, + 0, + 0, + v_APCI1710_Interrupt, + i_APCI1710_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, +#endif +#ifdef CONFIG_APCI_16XX + {"apci1648", + 0x15B8, + 0x1009, + 128, + 0, + 0, + 0, + ADDIDATA_NO_EEPROM, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, + 0, + 0, + 0, + 48, + &range_apci16xx_ttl, + 0, + 0, + 0, + 0, + 0, + NULL, + i_APCI16XX_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI16XX_InsnConfigInitTTLIO, + i_APCI16XX_InsnBitsReadTTLIO, + i_APCI16XX_InsnReadTTLIOAllPortValue, + i_APCI16XX_InsnBitsWriteTTLIO}, + + {"apci1696", + 0x15B8, + 0x100A, + 128, + 0, + 0, + 0, + ADDIDATA_NO_EEPROM, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + NULL, + NULL, + 0, + 0, + 0, + 96, + &range_apci16xx_ttl, + 0, + 0, + 0, + 0, + 0, + NULL, + i_APCI16XX_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI16XX_InsnConfigInitTTLIO, + i_APCI16XX_InsnBitsReadTTLIO, + i_APCI16XX_InsnReadTTLIOAllPortValue, + i_APCI16XX_InsnBitsWriteTTLIO}, +#endif +#ifdef CONFIG_APCI_3XXX + {"apci3000-16", + 0x15B8, + 0x3010, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 16, + 8, + 16, + 0, + 4095, + 0, + &range_apci3XXX_ai, + NULL, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3000-8", + 0x15B8, + 0x300F, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 8, + 4, + 8, + 0, + 4095, + 0, + &range_apci3XXX_ai, + NULL, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3000-4", + 0x15B8, + 0x300E, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 4, + 2, + 4, + 0, + 4095, + 0, + &range_apci3XXX_ai, + NULL, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3006-16", + 0x15B8, + 0x3013, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 16, + 8, + 16, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3006-8", + 0x15B8, + 0x3014, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 8, + 4, + 8, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3006-4", + 0x15B8, + 0x3015, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 4, + 2, + 4, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3010-16", + 0x15B8, + 0x3016, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 16, + 8, + 16, + 0, + 4095, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3010-8", + 0x15B8, + 0x3017, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 8, + 4, + 8, + 0, + 4095, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3010-4", + 0x15B8, + 0x3018, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 4, + 2, + 4, + 0, + 4095, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3016-16", + 0x15B8, + 0x3019, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 16, + 8, + 16, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3016-8", + 0x15B8, + 0x301A, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 8, + 4, + 8, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3016-4", + 0x15B8, + 0x301B, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 4, + 2, + 4, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3100-16-4", + 0x15B8, + 0x301C, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 16, + 8, + 16, + 4, + 4095, + 4095, + &range_apci3XXX_ai, + &range_apci3XXX_ao, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnWriteAnalogOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3100-8-4", + 0x15B8, + 0x301D, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 8, + 4, + 8, + 4, + 4095, + 4095, + &range_apci3XXX_ai, + &range_apci3XXX_ao, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnWriteAnalogOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3106-16-4", + 0x15B8, + 0x301E, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 16, + 8, + 16, + 4, + 65535, + 4095, + &range_apci3XXX_ai, + &range_apci3XXX_ao, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnWriteAnalogOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3106-8-4", + 0x15B8, + 0x301F, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 8, + 4, + 8, + 4, + 65535, + 4095, + &range_apci3XXX_ai, + &range_apci3XXX_ao, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 10000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnWriteAnalogOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3110-16-4", + 0x15B8, + 0x3020, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 16, + 8, + 16, + 4, + 4095, + 4095, + &range_apci3XXX_ai, + &range_apci3XXX_ao, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnWriteAnalogOutput, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3110-8-4", + 0x15B8, + 0x3021, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 8, + 4, + 8, + 4, + 4095, + 4095, + &range_apci3XXX_ai, + &range_apci3XXX_ao, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnWriteAnalogOutput, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3116-16-4", + 0x15B8, + 0x3022, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 16, + 8, + 16, + 4, + 65535, + 4095, + &range_apci3XXX_ai, + &range_apci3XXX_ao, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnWriteAnalogOutput, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3116-8-4", + 0x15B8, + 0x3023, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 8, + 4, + 8, + 4, + 65535, + 4095, + &range_apci3XXX_ai, + &range_apci3XXX_ao, + 4, + 4, + 1, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnWriteAnalogOutput, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, + + {"apci3003", + 0x15B8, + 0x300B, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 0, + 4, + 4, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 0, + NULL, + 0, + 0, + 7, + 2500, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, + + {"apci3002-16", + 0x15B8, + 0x3002, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 0, + 16, + 16, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 0, + NULL, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, + + {"apci3002-8", + 0x15B8, + 0x3003, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 0, + 8, + 8, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 0, + NULL, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, + + {"apci3002-4", + 0x15B8, + 0x3004, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 0, + 4, + 4, + 0, + 65535, + 0, + &range_apci3XXX_ai, + NULL, + 4, + 4, + 1, + 0, + NULL, + 0, + 0, + 6, + 5000, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + i_APCI3XXX_InsnConfigAnalogInput, + i_APCI3XXX_InsnReadAnalogInput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnReadDigitalInput, + NULL, + i_APCI3XXX_InsnBitsDigitalInput, + NULL, + i_APCI3XXX_InsnWriteDigitalOutput, + i_APCI3XXX_InsnBitsDigitalOutput, + i_APCI3XXX_InsnReadDigitalOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL}, + + {"apci3500", + 0x15B8, + 0x3024, + 256, + 256, + 256, + 256, + ADDIDATA_NO_EEPROM, + ADDIDATA_9054, + 0, + 0, + 0, + 4, + 0, + 4095, + NULL, + &range_apci3XXX_ao, + 0, + 0, + 0, + 24, + &range_apci3XXX_ttl, + 0, + 0, + 0, + 0, + 0, + v_APCI3XXX_Interrupt, + i_APCI3XXX_Reset, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnWriteAnalogOutput, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + i_APCI3XXX_InsnConfigInitTTLIO, + i_APCI3XXX_InsnBitsTTLIO, + i_APCI3XXX_InsnReadTTLIO, + i_APCI3XXX_InsnWriteTTLIO}, +#endif +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype)) + +struct comedi_driver driver_addi = { + driver_name:"addi_common", + module:THIS_MODULE, + attach:i_ADDI_Attach, + detach:i_ADDI_Detach, + num_names:n_boardtypes, + board_name:&boardtypes[0].pc_DriverName, + offset:sizeof(boardtype), +}; + +COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl); + +/* ++----------------------------------------------------------------------------+ +| Function name :static int i_ADDI_Attach(struct comedi_device *dev, | +| struct comedi_devconfig *it) | +| | ++----------------------------------------------------------------------------+ +| Task :Detects the card. | +| Configure the driver for a particular board. | +| This function does all the initializations and memory | +| allocation of data structures for the driver. | ++----------------------------------------------------------------------------+ +| Input Parameters :struct comedi_device *dev | +| struct comedi_devconfig *it | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +static int i_ADDI_Attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret, pages, i, n_subdevices; + DWORD dw_Dummy; + resource_size_t io_addr[5]; + unsigned int irq; + resource_size_t iobase_a, iobase_main, iobase_addon, iobase_reserved; + struct pcilst_struct *card = NULL; + unsigned char pci_bus, pci_slot, pci_func; + int i_Dma = 0; + static char c_Identifier[150]; + + sprintf(c_Identifier, "Addi-Data GmbH Comedi %s", + this_board->pc_DriverName); + + if ((ret = alloc_private(dev, sizeof(addi_private))) < 0) { + return -ENOMEM; + } + + if (!pci_list_builded) { + v_pci_card_list_init(this_board->i_VendorId, 1); //1 for displaying the list.. + pci_list_builded = 1; + } + //rt_printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName); + + if ((this_board->i_Dma) && (it->options[2] == 0)) { + i_Dma = 1; + } + + if ((card = ptr_select_and_alloc_pci_card(this_board->i_VendorId, + this_board->i_DeviceId, + it->options[0], + it->options[1], i_Dma)) == NULL) { + return -EIO; + } + devpriv->allocated = 1; + + if ((i_pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0], + &irq)) < 0) { + i_pci_card_free(card); + printk(" - Can't get AMCC data!\n"); + return -EIO; + } + + iobase_a = io_addr[0]; + iobase_main = io_addr[1]; + iobase_addon = io_addr[2]; + iobase_reserved = io_addr[3]; + printk("\nBus %d: Slot %d: Funct%d\nBase0: 0x%8llx\nBase1: 0x%8llx\nBase2: 0x%8llx\nBase3: 0x%8llx\n", pci_bus, pci_slot, pci_func, (unsigned long long)io_addr[0], (unsigned long long)io_addr[1], (unsigned long long)io_addr[2], (unsigned long long)io_addr[3]); + + if ((this_board->pc_EepromChip == NULL) + || (strcmp(this_board->pc_EepromChip, ADDIDATA_9054) != 0)) { + /************************************/ + /* Test if more that 1 address used */ + /************************************/ + + if (this_board->i_IorangeBase1 != 0) { + dev->iobase = (unsigned long)iobase_main; // DAQ base address... + } else { + dev->iobase = (unsigned long)iobase_a; // DAQ base address... + } + + dev->board_name = this_board->pc_DriverName; + devpriv->amcc = card; + devpriv->iobase = (INT) dev->iobase; + devpriv->i_IobaseAmcc = (INT) iobase_a; //AMCC base address... + devpriv->i_IobaseAddon = (INT) iobase_addon; //ADD ON base address.... + devpriv->i_IobaseReserved = (INT) iobase_reserved; + devpriv->ps_BoardInfo = this_board; + } else { + dev->board_name = this_board->pc_DriverName; + dev->iobase = (unsigned long)io_addr[2]; + devpriv->amcc = card; + devpriv->iobase = (INT) io_addr[2]; + devpriv->ps_BoardInfo = this_board; + devpriv->i_IobaseReserved = (INT) io_addr[3]; + printk("\nioremap begin"); + devpriv->dw_AiBase = + (ULONG_PTR) ioremap(io_addr[3], + this_board->i_IorangeBase3); + printk("\nioremap end"); + } + + //## + + if (irq > 0) { + if (comedi_request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED, + c_Identifier, dev) < 0) { + printk(", unable to allocate IRQ %u, DISABLING IT", + irq); + irq = 0; /* Can't use IRQ */ + } else { + rt_printk("\nirq=%u", irq); + } + } else { + rt_printk(", IRQ disabled"); + } + + printk("\nOption %d %d %d\n", it->options[0], it->options[1], + it->options[2]); + dev->irq = irq; + + // Read eepeom and fill boardtype Structure + + if (this_board->i_PCIEeprom) { + printk("\nPCI Eeprom used"); + if (!(strcmp(this_board->pc_EepromChip, "S5920"))) { + // Set 3 wait stait + if (!(strcmp(this_board->pc_DriverName, "apci035"))) { + outl(0x80808082, devpriv->i_IobaseAmcc + 0x60); + } else { + outl(0x83838383, devpriv->i_IobaseAmcc + 0x60); + } + // Enable the interrupt for the controler + dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38); + outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38); + printk("\nEnable the interrupt for the controler"); + } + printk("\nRead Eeprom"); + i_EepromReadMainHeader(io_addr[0], this_board->pc_EepromChip, + dev); + } else { + printk("\nPCI Eeprom unused"); + } + + if (it->options[2] > 0) { + devpriv->us_UseDma = ADDI_DISABLE; + } else { + devpriv->us_UseDma = ADDI_ENABLE; + } + + if (this_board->i_Dma) { + printk("\nDMA used"); + if (devpriv->us_UseDma == ADDI_ENABLE) { + // alloc DMA buffers + devpriv->b_DmaDoubleBuffer = 0; + for (i = 0; i < 2; i++) { + for (pages = 4; pages >= 0; pages--) { + if ((devpriv->ul_DmaBufferVirtual[i] = + (void *) + __get_free_pages + (GFP_KERNEL, pages))) { + break; + } + } + if (devpriv->ul_DmaBufferVirtual[i]) { + devpriv->ui_DmaBufferPages[i] = pages; + devpriv->ui_DmaBufferSize[i] = + PAGE_SIZE * pages; + devpriv->ui_DmaBufferSamples[i] = + devpriv-> + ui_DmaBufferSize[i] >> 1; + devpriv->ul_DmaBufferHw[i] = + virt_to_bus((void *)devpriv-> + ul_DmaBufferVirtual[i]); + } + } + if (!devpriv->ul_DmaBufferVirtual[0]) { + rt_printk + (", Can't allocate DMA buffer, DMA disabled!"); + devpriv->us_UseDma = ADDI_DISABLE; + } + + if (devpriv->ul_DmaBufferVirtual[1]) { + devpriv->b_DmaDoubleBuffer = 1; + } + } + + if ((devpriv->us_UseDma == ADDI_ENABLE)) { + rt_printk("\nDMA ENABLED\n"); + } else { + printk("\nDMA DISABLED\n"); + } + } + + if (!strcmp(this_board->pc_DriverName, "apci1710")) { +#ifdef CONFIG_APCI_1710 + i_ADDI_AttachPCI1710(dev); + + // save base address + devpriv->s_BoardInfos.ui_Address = io_addr[2]; +#endif + } else { + //Update-0.7.57->0.7.68dev->n_subdevices = 7; + n_subdevices = 7; + if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) + return ret; + + // Allocate and Initialise AI Subdevice Structures + s = dev->subdevices + 0; + if ((this_board->i_NbrAiChannel) + || (this_board->i_NbrAiChannelDiff)) { + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = + SDF_READABLE | SDF_RT | SDF_COMMON | SDF_GROUND + | SDF_DIFF; + if (this_board->i_NbrAiChannel) { + s->n_chan = this_board->i_NbrAiChannel; + devpriv->b_SingelDiff = 0; + } else { + s->n_chan = this_board->i_NbrAiChannelDiff; + devpriv->b_SingelDiff = 1; + } + s->maxdata = this_board->i_AiMaxdata; + s->len_chanlist = this_board->i_AiChannelList; + s->range_table = this_board->pr_AiRangelist; + + /* Set the initialisation flag */ + devpriv->b_AiInitialisation = 1; + + s->insn_config = + this_board->i_hwdrv_InsnConfigAnalogInput; + s->insn_read = this_board->i_hwdrv_InsnReadAnalogInput; + s->insn_write = + this_board->i_hwdrv_InsnWriteAnalogInput; + s->insn_bits = this_board->i_hwdrv_InsnBitsAnalogInput; + s->do_cmdtest = + this_board->i_hwdrv_CommandTestAnalogInput; + s->do_cmd = this_board->i_hwdrv_CommandAnalogInput; + s->cancel = this_board->i_hwdrv_CancelAnalogInput; + + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + // Allocate and Initialise AO Subdevice Structures + s = dev->subdevices + 1; + if (this_board->i_NbrAoChannel) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = + SDF_WRITEABLE | SDF_GROUND | SDF_COMMON | + SDF_RT; + s->n_chan = this_board->i_NbrAoChannel; + s->maxdata = this_board->i_AoMaxdata; + s->len_chanlist = this_board->i_NbrAoChannel; + s->range_table = this_board->pr_AoRangelist; + s->insn_config = + this_board->i_hwdrv_InsnConfigAnalogOutput; + s->insn_write = + this_board->i_hwdrv_InsnWriteAnalogOutput; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + // Allocate and Initialise DI Subdevice Structures + s = dev->subdevices + 2; + if (this_board->i_NbrDiChannel) { + s->type = COMEDI_SUBD_DI; + s->subdev_flags = + SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->i_NbrDiChannel; + s->maxdata = 1; + s->len_chanlist = this_board->i_NbrDiChannel; + s->range_table = &range_digital; + s->io_bits = 0; /* all bits input */ + s->insn_config = + this_board->i_hwdrv_InsnConfigDigitalInput; + s->insn_read = this_board->i_hwdrv_InsnReadDigitalInput; + s->insn_write = + this_board->i_hwdrv_InsnWriteDigitalInput; + s->insn_bits = this_board->i_hwdrv_InsnBitsDigitalInput; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + // Allocate and Initialise DO Subdevice Structures + s = dev->subdevices + 3; + if (this_board->i_NbrDoChannel) { + s->type = COMEDI_SUBD_DO; + s->subdev_flags = + SDF_READABLE | SDF_WRITEABLE | SDF_RT | + SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->i_NbrDoChannel; + s->maxdata = this_board->i_DoMaxdata; + s->len_chanlist = this_board->i_NbrDoChannel; + s->range_table = &range_digital; + s->io_bits = 0xf; /* all bits output */ + + s->insn_config = this_board->i_hwdrv_InsnConfigDigitalOutput; //for digital output memory.. + s->insn_write = + this_board->i_hwdrv_InsnWriteDigitalOutput; + s->insn_bits = + this_board->i_hwdrv_InsnBitsDigitalOutput; + s->insn_read = + this_board->i_hwdrv_InsnReadDigitalOutput; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + // Allocate and Initialise Timer Subdevice Structures + s = dev->subdevices + 4; + if (this_board->i_Timer) { + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = + SDF_WRITEABLE | SDF_RT | SDF_GROUND | + SDF_COMMON; + s->n_chan = 1; + s->maxdata = 0; + s->len_chanlist = 1; + s->range_table = &range_digital; + + s->insn_write = this_board->i_hwdrv_InsnWriteTimer; + s->insn_read = this_board->i_hwdrv_InsnReadTimer; + s->insn_config = this_board->i_hwdrv_InsnConfigTimer; + s->insn_bits = this_board->i_hwdrv_InsnBitsTimer; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + // Allocate and Initialise TTL + s = dev->subdevices + 5; + if (this_board->i_NbrTTLChannel) { + s->type = COMEDI_SUBD_TTLIO; + s->subdev_flags = + SDF_WRITEABLE | SDF_READABLE | SDF_RT | + SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->i_NbrTTLChannel; + s->maxdata = 1; + s->io_bits = 0; /* all bits input */ + s->len_chanlist = this_board->i_NbrTTLChannel; + s->range_table = &range_digital; + s->insn_config = this_board->i_hwdr_ConfigInitTTLIO; + s->insn_bits = this_board->i_hwdr_ReadTTLIOBits; + s->insn_read = this_board->i_hwdr_ReadTTLIOAllPortValue; + s->insn_write = this_board->i_hwdr_WriteTTLIOChlOnOff; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* EEPROM */ + s = dev->subdevices + 6; + if (this_board->i_PCIEeprom) { + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE | SDF_INTERNAL; + s->n_chan = 256; + s->maxdata = 0xffff; + s->insn_read = i_ADDIDATA_InsnReadEeprom; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + } + + printk("\ni_ADDI_Attach end\n"); + i_ADDI_Reset(dev); + devpriv->b_ValidDriver = 1; + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : static int i_ADDI_Detach(struct comedi_device *dev) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : Deallocates resources of the addi_common driver | +| Free the DMA buffers, unregister irq. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +static int i_ADDI_Detach(struct comedi_device * dev) +{ + + if (dev->private) { + if (devpriv->b_ValidDriver) { + i_ADDI_Reset(dev); + } + + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + + if ((devpriv->ps_BoardInfo->pc_EepromChip == NULL) + || (strcmp(devpriv->ps_BoardInfo->pc_EepromChip, + ADDIDATA_9054) != 0)) { + if (devpriv->allocated) { + i_pci_card_free(devpriv->amcc); + } + + if (devpriv->ul_DmaBufferVirtual[0]) { + free_pages((unsigned long)devpriv-> + ul_DmaBufferVirtual[0], + devpriv->ui_DmaBufferPages[0]); + } + + if (devpriv->ul_DmaBufferVirtual[1]) { + free_pages((unsigned long)devpriv-> + ul_DmaBufferVirtual[1], + devpriv->ui_DmaBufferPages[1]); + } + } else { + iounmap((void *)devpriv->dw_AiBase); + + if (devpriv->allocated) { + i_pci_card_free(devpriv->amcc); + } + } + + if (pci_list_builded) { + //v_pci_card_list_cleanup(PCI_VENDOR_ID_AMCC); + v_pci_card_list_cleanup(this_board->i_VendorId); + pci_list_builded = 0; + } + } + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : static int i_ADDI_Reset(struct comedi_device *dev) | +| | ++----------------------------------------------------------------------------+ +| Task : Disables all interrupts, Resets digital output to low, | +| Set all analog output to low | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +static int i_ADDI_Reset(struct comedi_device * dev) +{ + + this_board->i_hwdrv_Reset(dev); + return 0; +} + +// Interrupt function +/* ++----------------------------------------------------------------------------+ +| Function name : | +|static void v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG) | +| | ++----------------------------------------------------------------------------+ +| Task : Registerd interrupt routine | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + this_board->v_hwdrv_Interrupt(irq, d); + return IRQ_RETVAL(1); +} + +// EEPROM Read Function +/* ++----------------------------------------------------------------------------+ +| Function name : | +|INT i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data) +| | ++----------------------------------------------------------------------------+ +| Task : Read 256 words from EEPROM | +| | ++----------------------------------------------------------------------------+ +| Input Parameters :(struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data) | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +static int i_ADDIDATA_InsnReadEeprom(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + WORD w_Data; + WORD w_Address; + w_Address = CR_CHAN(insn->chanspec); // address to be read as 0,1,2,3...255 + + w_Data = w_EepromReadWord(devpriv->i_IobaseAmcc, + this_board->pc_EepromChip, 0x100 + (2 * w_Address)); + data[0] = w_Data; + //multiplied by 2 bcozinput will be like 0,1,2...255 + return insn->n; + +} diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h new file mode 100644 index 000000000000..19df5c1444a4 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../comedidev.h" +#include "addi_amcc_s5933.h" + +#define ERROR -1 +#define SUCCESS 1 + +/* variable type definition */ +typedef unsigned char BYTE, *PBYTE; +typedef short SHORT, *PSHORT; +typedef unsigned short USHORT, *PUSHORT; +typedef unsigned short WORD, *PWORD; +typedef int INT, *PINT;; +typedef unsigned int UINT, *PUINT; +typedef int LONG, *PLONG; /* 32-bit */ +typedef unsigned int ULONG, *PULONG; /* 32-bit */ +typedef unsigned int DWORD, *PDWORD; /* 32-bit */ +typedef unsigned long ULONG_PTR; + +typedef const struct comedi_lrange *PCRANGE; + +#define LOBYTE(W) (BYTE)((W) & 0xFF) +#define HIBYTE(W) (BYTE)(((W) >> 8) & 0xFF) +#define MAKEWORD(H, L) (USHORT)((L) | ((H) << 8)) +#define LOWORD(W) (USHORT)((W) & 0xFFFF) +#define HIWORD(W) (USHORT)(((W) >> 16) & 0xFFFF) +#define MAKEDWORD(H, L) (UINT)((L) | ((H) << 16)) + +#define ADDI_ENABLE 1 +#define ADDI_DISABLE 0 +#define APCI1710_SAVE_INTERRUPT 1 + +#define ADDIDATA_EEPROM 1 +#define ADDIDATA_NO_EEPROM 0 +#define ADDIDATA_93C76 "93C76" +#define ADDIDATA_S5920 "S5920" +#define ADDIDATA_S5933 "S5933" +#define ADDIDATA_9054 "9054" + +/* ADDIDATA Enable Disable */ +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +/* Structures */ + +/* structure for the boardtype */ +typedef struct { + const char *pc_DriverName; // driver name + INT i_VendorId; //PCI vendor a device ID of card + INT i_DeviceId; + INT i_IorangeBase0; + INT i_IorangeBase1; + INT i_IorangeBase2; // base 2 range + INT i_IorangeBase3; // base 3 range + INT i_PCIEeprom; // eeprom present or not + char *pc_EepromChip; // type of chip + INT i_NbrAiChannel; // num of A/D chans + INT i_NbrAiChannelDiff; // num of A/D chans in diff mode + INT i_AiChannelList; // len of chanlist + INT i_NbrAoChannel; // num of D/A chans + INT i_AiMaxdata; // resolution of A/D + INT i_AoMaxdata; // resolution of D/A + PCRANGE pr_AiRangelist; // rangelist for A/D + PCRANGE pr_AoRangelist; // rangelist for D/A + + INT i_NbrDiChannel; // Number of DI channels + INT i_NbrDoChannel; // Number of DO channels + INT i_DoMaxdata; // data to set all chanels high + + INT i_NbrTTLChannel; // Number of TTL channels + PCRANGE pr_TTLRangelist; // rangelist for TTL + + INT i_Dma; // dma present or not + INT i_Timer; // timer subdevice present or not + BYTE b_AvailableConvertUnit; + UINT ui_MinAcquisitiontimeNs; // Minimum Acquisition in Nano secs + UINT ui_MinDelaytimeNs; // Minimum Delay in Nano secs + + /* interrupt and reset */ + void (*v_hwdrv_Interrupt)(int irq, void *d); + int (*i_hwdrv_Reset)(struct comedi_device *dev); + + /* Subdevice functions */ + + /* ANALOG INPUT */ + int (*i_hwdrv_InsnConfigAnalogInput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnReadAnalogInput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnWriteAnalogInput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnBitsAnalogInput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd); + int (*i_hwdrv_CommandAnalogInput)(struct comedi_device *dev, + struct comedi_subdevice *s); + int (*i_hwdrv_CancelAnalogInput)(struct comedi_device *dev, + struct comedi_subdevice *s); + + /* Analog Output */ + int (*i_hwdrv_InsnConfigAnalogOutput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnWriteAnalogOutput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnBitsAnalogOutput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + + /* Digital Input */ + int (*i_hwdrv_InsnConfigDigitalInput) (struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnReadDigitalInput) (struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnWriteDigitalInput) (struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnBitsDigitalInput) (struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + + /* Digital Output */ + int (*i_hwdrv_InsnConfigDigitalOutput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnWriteDigitalOutput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnBitsDigitalOutput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnReadDigitalOutput)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + + /* TIMER */ + int (*i_hwdrv_InsnConfigTimer)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + int (*i_hwdrv_InsnWriteTimer)(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + + /* TTL IO */ + int (*i_hwdr_ConfigInitTTLIO)(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + int (*i_hwdr_ReadTTLIOAllPortValue)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +} boardtype; + +//MODULE INFO STRUCTURE + +typedef union { + /* Incremental counter infos */ + struct { + union { + struct { + BYTE b_ModeRegister1; + BYTE b_ModeRegister2; + BYTE b_ModeRegister3; + BYTE b_ModeRegister4; + } s_ByteModeRegister; + DWORD dw_ModeRegister1_2_3_4; + } s_ModeRegister; + + struct { + unsigned int b_IndexInit:1; + unsigned int b_CounterInit:1; + unsigned int b_ReferenceInit:1; + unsigned int b_IndexInterruptOccur:1; + unsigned int b_CompareLogicInit:1; + unsigned int b_FrequencyMeasurementInit:1; + unsigned int b_FrequencyMeasurementEnable:1; + } s_InitFlag; + + } s_SiemensCounterInfo; + + /* SSI infos */ + struct { + BYTE b_SSIProfile; + BYTE b_PositionTurnLength; + BYTE b_TurnCptLength; + BYTE b_SSIInit; + } s_SSICounterInfo; + + /* TTL I/O infos */ + struct { + BYTE b_TTLInit; + BYTE b_PortConfiguration[4]; + } s_TTLIOInfo; + + /* Digital I/O infos */ + struct { + BYTE b_DigitalInit; + BYTE b_ChannelAMode; + BYTE b_ChannelBMode; + BYTE b_OutputMemoryEnabled; + DWORD dw_OutputMemory; + } s_DigitalIOInfo; + + /*********************/ + /* 82X54 timer infos */ + /*********************/ + + struct { + struct { + BYTE b_82X54Init; + BYTE b_InputClockSelection; + BYTE b_InputClockLevel; + BYTE b_OutputLevel; + BYTE b_HardwareGateLevel; + DWORD dw_ConfigurationWord; + } s_82X54TimerInfo[3]; + BYTE b_InterruptMask; + } s_82X54ModuleInfo; + + /*********************/ + /* Chronometer infos */ + /*********************/ + + struct { + BYTE b_ChronoInit; + BYTE b_InterruptMask; + BYTE b_PCIInputClock; + BYTE b_TimingUnit; + BYTE b_CycleMode; + double d_TimingInterval; + DWORD dw_ConfigReg; + } s_ChronoModuleInfo; + + /***********************/ + /* Pulse encoder infos */ + /***********************/ + + struct { + struct { + BYTE b_PulseEncoderInit; + } s_PulseEncoderInfo[4]; + DWORD dw_SetRegister; + DWORD dw_ControlRegister; + DWORD dw_StatusRegister; + } s_PulseEncoderModuleInfo; + + /* Tor conter infos */ + struct { + struct { + BYTE b_TorCounterInit; + BYTE b_TimingUnit; + BYTE b_InterruptEnable; + double d_TimingInterval; + ULONG ul_RealTimingInterval; + } s_TorCounterInfo[2]; + BYTE b_PCIInputClock; + } s_TorCounterModuleInfo; + + /* PWM infos */ + struct { + struct { + BYTE b_PWMInit; + BYTE b_TimingUnit; + BYTE b_InterruptEnable; + double d_LowTiming; + double d_HighTiming; + ULONG ul_RealLowTiming; + ULONG ul_RealHighTiming; + } s_PWMInfo[2]; + BYTE b_ClockSelection; + } s_PWMModuleInfo; + + /* ETM infos */ + struct { + struct { + BYTE b_ETMEnable; + BYTE b_ETMInterrupt; + } s_ETMInfo[2]; + BYTE b_ETMInit; + BYTE b_TimingUnit; + BYTE b_ClockSelection; + double d_TimingInterval; + ULONG ul_Timing; + } s_ETMModuleInfo; + + /* CDA infos */ + struct { + BYTE b_CDAEnable; + BYTE b_CDAInterrupt; + BYTE b_CDAInit; + BYTE b_FctSelection; + BYTE b_CDAReadFIFOOverflow; + } s_CDAModuleInfo; + +} str_ModuleInfo; + +/* Private structure for the addi_apci3120 driver */ +typedef struct { + + INT iobase; + INT i_IobaseAmcc; // base+size for AMCC chip + INT i_IobaseAddon; //addon base address + INT i_IobaseReserved; + ULONG_PTR dw_AiBase; + struct pcilst_struct *amcc; // ptr too AMCC data + BYTE allocated; // we have blocked card + BYTE b_ValidDriver; // driver is ok + BYTE b_AiContinuous; // we do unlimited AI + BYTE b_AiInitialisation; + UINT ui_AiActualScan; //how many scans we finished + UINT ui_AiBufferPtr; // data buffer ptr in samples + UINT ui_AiNbrofChannels; // how many channels is measured + UINT ui_AiScanLength; // Length of actual scanlist + UINT ui_AiActualScanPosition; // position in actual scan + PUINT pui_AiChannelList; // actual chanlist + UINT ui_AiChannelList[32]; // actual chanlist + BYTE b_AiChannelConfiguration[32]; // actual chanlist + UINT ui_AiReadData[32]; + DWORD dw_AiInitialised; + UINT ui_AiTimer0; //Timer Constant for Timer0 + UINT ui_AiTimer1; //Timer constant for Timer1 + UINT ui_AiFlags; + UINT ui_AiDataLength; + short *AiData; // Pointer to sample data + UINT ui_AiNbrofScans; // number of scans to do + USHORT us_UseDma; // To use Dma or not + BYTE b_DmaDoubleBuffer; // we can use double buffering + UINT ui_DmaActualBuffer; // which buffer is used now + //*UPDATE-0.7.57->0.7.68 + //ULONG ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer + short *ul_DmaBufferVirtual[2]; // pointers to begin of DMA buffer + ULONG ul_DmaBufferHw[2]; // hw address of DMA buff + UINT ui_DmaBufferSize[2]; // size of dma buffer in bytes + UINT ui_DmaBufferUsesize[2]; // which size we may now used for transfer + UINT ui_DmaBufferSamples[2]; // size in samples + UINT ui_DmaBufferPages[2]; // number of pages in buffer + BYTE b_DigitalOutputRegister; // Digital Output Register + BYTE b_OutputMemoryStatus; + BYTE b_AnalogInputChannelNbr; // Analog input channel Nbr + BYTE b_AnalogOutputChannelNbr; // Analog input Output Nbr + BYTE b_TimerSelectMode; // Contain data written at iobase + 0C + BYTE b_ModeSelectRegister; // Contain data written at iobase + 0E + USHORT us_OutputRegister; // Contain data written at iobase + 0 + BYTE b_InterruptState; + BYTE b_TimerInit; // Specify if InitTimerWatchdog was load + BYTE b_TimerStarted; // Specify if timer 2 is running or not + BYTE b_Timer2Mode; // Specify the timer 2 mode + BYTE b_Timer2Interrupt; //Timer2 interrupt enable or disable + BYTE b_AiCyclicAcquisition; // indicate cyclic acquisition + BYTE b_InterruptMode; // eoc eos or dma + BYTE b_EocEosInterrupt; // Enable disable eoc eos interrupt + UINT ui_EocEosConversionTime; + BYTE b_EocEosConversionTimeBase; + BYTE b_SingelDiff; + BYTE b_ExttrigEnable; /* To enable or disable external trigger */ + + /* Pointer to the current process */ + struct task_struct *tsk_Current; + boardtype *ps_BoardInfo; + + /* Hardware board infos for 1710 */ + struct { + UINT ui_Address; /* Board address */ + UINT ui_FlashAddress; + BYTE b_InterruptNbr; /* Board interrupt number */ + BYTE b_SlotNumber; /* PCI slot number */ + BYTE b_BoardVersion; + DWORD dw_MolduleConfiguration[4]; /* Module config */ + } s_BoardInfos; + + /* Interrupt infos */ + struct { + ULONG ul_InterruptOccur; /* 0 : No interrupt occur */ + /* > 0 : Interrupt occur */ + UINT ui_Read; /* Read FIFO */ + UINT ui_Write; /* Write FIFO */ + struct { + BYTE b_OldModuleMask; + ULONG ul_OldInterruptMask; /* Interrupt mask */ + ULONG ul_OldCounterLatchValue; /* Interrupt counter value */ + } s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT]; + } s_InterruptParameters; + + str_ModuleInfo s_ModuleInfo[4]; + ULONG ul_TTLPortConfiguration[10]; + +} addi_private; + +static unsigned short pci_list_builded; /* set to 1 when list of card is known */ + +/* Function declarations */ +static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int i_ADDI_Detach(struct comedi_device *dev); +static int i_ADDI_Reset(struct comedi_device *dev); + +static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG); +static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c new file mode 100644 index 000000000000..a8a1bb2e8fa5 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c @@ -0,0 +1,1158 @@ +/** +@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 Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : ADDI DATA | Compiler : GCC | + | Modulname : addi_eeprom.c | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description : ADDI EEPROM Module | + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +#define NVCMD_BEGIN_READ (0x7 << 5 ) // nvRam begin read command +#define NVCMD_LOAD_LOW (0x4 << 5 ) // nvRam load low command +#define NVCMD_LOAD_HIGH (0x5 << 5 ) // nvRam load high command +#define EE76_CMD_LEN 13 // bits in instructions +#define EE_READ 0x0180 // 01 1000 0000 read instruction + +#define WORD unsigned short +#define PWORD unsigned short * +#define PDWORD unsigned int * + +#ifndef DWORD +#define DWORD unsigned int +#endif + +#define EEPROM_DIGITALINPUT 0 +#define EEPROM_DIGITALOUTPUT 1 +#define EEPROM_ANALOGINPUT 2 +#define EEPROM_ANALOGOUTPUT 3 +#define EEPROM_TIMER 4 +#define EEPROM_WATCHDOG 5 +#define EEPROM_TIMER_WATCHDOG_COUNTER 10 + +struct str_Functionality { + BYTE b_Type; + WORD w_Address; +}; + +typedef struct { + WORD w_HeaderSize; + BYTE b_Nfunctions; + struct str_Functionality s_Functions[7]; +} str_MainHeader; + +typedef struct { + WORD w_Nchannel; + BYTE b_Interruptible; + WORD w_NinterruptLogic; +} str_DigitalInputHeader; + +typedef struct { + WORD w_Nchannel; +} str_DigitalOutputHeader; + +// used for timer as well as watchdog + +typedef struct { + WORD w_HeaderSize; + BYTE b_Resolution; + BYTE b_Mode; // in case of Watchdog it is functionality + WORD w_MinTiming; + BYTE b_TimeBase; +} str_TimerDetails; +typedef struct { + + WORD w_Ntimer; + str_TimerDetails s_TimerDetails[4]; // supports 4 timers +} str_TimerMainHeader; + +typedef struct { + WORD w_Nchannel; + BYTE b_Resolution; +} str_AnalogOutputHeader; + +typedef struct { + WORD w_Nchannel; + WORD w_MinConvertTiming; + WORD w_MinDelayTiming; + BYTE b_HasDma; + BYTE b_Resolution; +} str_AnalogInputHeader; + + /*****************************************/ + /* Read Header Functions */ + /*****************************************/ + +INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, struct comedi_device *dev); + +INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_DigitalInputHeader * s_Header); + +INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_DigitalOutputHeader * s_Header); + +INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_TimerMainHeader * s_Header); + +INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_AnalogOutputHeader * s_Header); + +INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_AnalogInputHeader * s_Header); + + /******************************************/ + /* Eeprom Specific Functions */ + /******************************************/ +WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation, + WORD w_EepromStartAddress); +void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress); +void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue); +void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress); +void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand, + BYTE b_DataLengthInBits); +void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value); + +/* ++----------------------------------------------------------------------------+ +| Function Name : WORD w_EepromReadWord | +| (WORD w_PCIBoardEepromAddress, | +| char * pc_PCIChipInformation, | +| WORD w_EepromStartAddress) | ++----------------------------------------------------------------------------+ +| Task : Read from eepromn a word | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| char *pc_PCIChipInformation : PCI Chip Type. | +| | +| WORD w_EepromStartAddress : Selected eeprom address | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : Read word value from eeprom | ++----------------------------------------------------------------------------+ +*/ + +WORD w_EepromReadWord(WORD w_PCIBoardEepromAddress, char *pc_PCIChipInformation, + WORD w_EepromStartAddress) +{ + + BYTE b_Counter = 0; + + BYTE b_ReadByte = 0; + + BYTE b_ReadLowByte = 0; + + BYTE b_ReadHighByte = 0; + + BYTE b_SelectedAddressLow = 0; + + BYTE b_SelectedAddressHigh = 0; + + WORD w_ReadWord = 0; + + /**************************/ + + /* Test the PCI chip type */ + + /**************************/ + + if ((!strcmp(pc_PCIChipInformation, "S5920")) || + (!strcmp(pc_PCIChipInformation, "S5933"))) + { + + for (b_Counter = 0; b_Counter < 2; b_Counter++) + { + + b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256; //Read the low 8 bit part + + b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256; //Read the high 8 bit part + + /************************************/ + + /* Select the load low address mode */ + + /************************************/ + + outb(NVCMD_LOAD_LOW, w_PCIBoardEepromAddress + 0x3F); + + /****************/ + + /* Wait on busy */ + + /****************/ + + v_EepromWaitBusy(w_PCIBoardEepromAddress); + + /************************/ + + /* Load the low address */ + + /************************/ + + outb(b_SelectedAddressLow, + w_PCIBoardEepromAddress + 0x3E); + + /****************/ + + /* Wait on busy */ + + /****************/ + + v_EepromWaitBusy(w_PCIBoardEepromAddress); + + /*************************************/ + + /* Select the load high address mode */ + + /*************************************/ + + outb(NVCMD_LOAD_HIGH, w_PCIBoardEepromAddress + 0x3F); + + /****************/ + + /* Wait on busy */ + + /****************/ + + v_EepromWaitBusy(w_PCIBoardEepromAddress); + + /*************************/ + + /* Load the high address */ + + /*************************/ + + outb(b_SelectedAddressHigh, + w_PCIBoardEepromAddress + 0x3E); + + /****************/ + + /* Wait on busy */ + + /****************/ + + v_EepromWaitBusy(w_PCIBoardEepromAddress); + + /************************/ + + /* Select the READ mode */ + + /************************/ + + outb(NVCMD_BEGIN_READ, w_PCIBoardEepromAddress + 0x3F); + + /****************/ + + /* Wait on busy */ + + /****************/ + + v_EepromWaitBusy(w_PCIBoardEepromAddress); + + /*****************************/ + + /* Read data into the EEPROM */ + + /*****************************/ + + b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E); + + /****************/ + + /* Wait on busy */ + + /****************/ + + v_EepromWaitBusy(w_PCIBoardEepromAddress); + + /*********************************/ + + /* Select the upper address part */ + + /*********************************/ + + if (b_Counter == 0) + { + + b_ReadLowByte = b_ReadByte; + + } // if(b_Counter==0) + + else + { + + b_ReadHighByte = b_ReadByte; + + } // if(b_Counter==0) + + } // for (b_Counter=0; b_Counter<2; b_Counter++) + + w_ReadWord = (b_ReadLowByte | (((WORD) b_ReadHighByte) * 256)); + + } // end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933"))) + + if (!strcmp(pc_PCIChipInformation, "93C76")) + { + + /*************************************/ + + /* Read 16 bit from the EEPROM 93C76 */ + + /*************************************/ + + v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress, + &w_ReadWord); + + } + + return (w_ReadWord); + +} + +/* + ++----------------------------------------------------------------------------+ + +| Function Name : void v_EepromWaitBusy | + +| (WORD w_PCIBoardEepromAddress) | + ++----------------------------------------------------------------------------+ + +| Task : Wait the busy flag from PCI controller | + ++----------------------------------------------------------------------------+ + +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom base address | + ++----------------------------------------------------------------------------+ + +| Output Parameters : - | + ++----------------------------------------------------------------------------+ + +| Return Value : - | + ++----------------------------------------------------------------------------+ + +*/ + +void v_EepromWaitBusy(WORD w_PCIBoardEepromAddress) +{ + + BYTE b_EepromBusy = 0; + + do + { + + /*************/ + + /* IMPORTANT */ + + /*************/ + + /************************************************************************/ + + /* An error has been written in the AMCC 5933 book at the page B-13 */ + + /* Ex: if you read a byte and look for the busy statusEEPROM=0x80 and */ + + /* the operator register is AMCC_OP_REG_MCSR+3 */ + + /* WORD read EEPROM=0x8000 andAMCC_OP_REG_MCSR+2 */ + + /* DWORD read EEPROM=0x80000000 and AMCC_OP_REG_MCSR */ + + /************************************************************************/ + + b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F); + b_EepromBusy = b_EepromBusy & 0x80; + + } + while (b_EepromBusy == 0x80); + +} + +/* + ++---------------------------------------------------------------------------------+ + +| Function Name : void v_EepromClock76(DWORD dw_Address, | + +| DWORD dw_RegisterValue) | + ++---------------------------------------------------------------------------------+ + +| Task : This function sends the clocking sequence to the EEPROM. | + ++---------------------------------------------------------------------------------+ + +| Input Parameters : DWORD dw_Address : PCI eeprom base address | + +| DWORD dw_RegisterValue : PCI eeprom register value to write.| + ++---------------------------------------------------------------------------------+ + +| Output Parameters : - | + ++---------------------------------------------------------------------------------+ + +| Return Value : - | + ++---------------------------------------------------------------------------------+ + +*/ + +void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue) +{ + + /************************/ + + /* Set EEPROM clock Low */ + + /************************/ + + outl(dw_RegisterValue & 0x6, dw_Address); + + /***************/ + + /* Wait 0.1 ms */ + + /***************/ + + udelay(100); + + /*************************/ + + /* Set EEPROM clock High */ + + /*************************/ + + outl(dw_RegisterValue | 0x1, dw_Address); + + /***************/ + + /* Wait 0.1 ms */ + + /***************/ + + udelay(100); + +} + +/* + ++---------------------------------------------------------------------------------+ + +| Function Name : void v_EepromSendCommand76(DWORD dw_Address, | + +| DWORD dw_EepromCommand, | + +| BYTE b_DataLengthInBits) | + ++---------------------------------------------------------------------------------+ + +| Task : This function sends a Command to the EEPROM 93C76. | + ++---------------------------------------------------------------------------------+ + +| Input Parameters : DWORD dw_Address : PCI eeprom base address | + +| DWORD dw_EepromCommand : PCI eeprom command to write. | + +| BYTE b_DataLengthInBits : PCI eeprom command data length. | + ++---------------------------------------------------------------------------------+ + +| Output Parameters : - | + ++---------------------------------------------------------------------------------+ + +| Return Value : - | + ++---------------------------------------------------------------------------------+ + +*/ + +void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand, + BYTE b_DataLengthInBits) +{ + + char c_BitPos = 0; + + DWORD dw_RegisterValue = 0; + + /*****************************/ + + /* Enable EEPROM Chip Select */ + + /*****************************/ + + dw_RegisterValue = 0x2; + + /********************************************************************/ + + /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */ + + /********************************************************************/ + + outl(dw_RegisterValue, dw_Address); + + /***************/ + + /* Wait 0.1 ms */ + + /***************/ + + udelay(100); + + /*******************************************/ + + /* Send EEPROM command - one bit at a time */ + + /*******************************************/ + + for (c_BitPos = (b_DataLengthInBits - 1); c_BitPos >= 0; c_BitPos--) + { + + /**********************************/ + + /* Check if current bit is 0 or 1 */ + + /**********************************/ + + if (dw_EepromCommand & (1 << c_BitPos)) + { + + /***********/ + + /* Write 1 */ + + /***********/ + + dw_RegisterValue = dw_RegisterValue | 0x4; + + } + + else + { + + /***********/ + + /* Write 0 */ + + /***********/ + + dw_RegisterValue = dw_RegisterValue & 0x3; + + } + + /*********************/ + + /* Write the command */ + + /*********************/ + + outl(dw_RegisterValue, dw_Address); + + /***************/ + + /* Wait 0.1 ms */ + + /***************/ + + udelay(100); + + /****************************/ + + /* Trigger the EEPROM clock */ + + /****************************/ + + v_EepromClock76(dw_Address, dw_RegisterValue); + + } + +} + +/* + ++---------------------------------------------------------------------------------+ + +| Function Name : void v_EepromCs76Read(DWORD dw_Address, | + +| WORD w_offset, | + +| PWORD pw_Value) | + ++---------------------------------------------------------------------------------+ + +| Task : This function read a value from the EEPROM 93C76. | + ++---------------------------------------------------------------------------------+ + +| Input Parameters : DWORD dw_Address : PCI eeprom base address | + +| WORD w_offset : Offset of the adress to read | + +| PWORD pw_Value : PCI eeprom 16 bit read value. | + ++---------------------------------------------------------------------------------+ + +| Output Parameters : - | + ++---------------------------------------------------------------------------------+ + +| Return Value : - | + ++---------------------------------------------------------------------------------+ + +*/ + +void v_EepromCs76Read(DWORD dw_Address, WORD w_offset, PWORD pw_Value) +{ + + char c_BitPos = 0; + + DWORD dw_RegisterValue = 0; + + DWORD dw_RegisterValueRead = 0; + + /*************************************************/ + + /* Send EEPROM read command and offset to EEPROM */ + + /*************************************************/ + + v_EepromSendCommand76(dw_Address, (EE_READ << 4) | (w_offset / 2), + EE76_CMD_LEN); + + /*******************************/ + + /* Get the last register value */ + + /*******************************/ + + dw_RegisterValue = (((w_offset / 2) & 0x1) << 2) | 0x2; + + /*****************************/ + + /* Set the 16-bit value of 0 */ + + /*****************************/ + + *pw_Value = 0; + + /************************/ + + /* Get the 16-bit value */ + + /************************/ + + for (c_BitPos = 0; c_BitPos < 16; c_BitPos++) + { + + /****************************/ + + /* Trigger the EEPROM clock */ + + /****************************/ + + v_EepromClock76(dw_Address, dw_RegisterValue); + + /**********************/ + + /* Get the result bit */ + + /**********************/ + + dw_RegisterValueRead = inl(dw_Address); + + /***************/ + + /* Wait 0.1 ms */ + + /***************/ + + udelay(100); + + /***************************************/ + + /* Get bit value and shift into result */ + + /***************************************/ + + if (dw_RegisterValueRead & 0x8) + { + + /**********/ + + /* Read 1 */ + + /**********/ + + *pw_Value = (*pw_Value << 1) | 0x1; + + } + + else + { + + /**********/ + + /* Read 0 */ + + /**********/ + + *pw_Value = (*pw_Value << 1); + + } + + } + + /*************************/ + + /* Clear all EEPROM bits */ + + /*************************/ + + dw_RegisterValue = 0x0; + + /********************************************************************/ + + /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */ + + /********************************************************************/ + + outl(dw_RegisterValue, dw_Address); + + /***************/ + + /* Wait 0.1 ms */ + + /***************/ + + udelay(100); + +} + + /******************************************/ + /* EEPROM HEADER READ FUNCTIONS */ + /******************************************/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress, | +| char * pc_PCIChipInformation,struct comedi_device *dev) | ++----------------------------------------------------------------------------+ +| Task : Read from eeprom Main Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| char *pc_PCIChipInformation : PCI Chip Type. | +| | +| struct comedi_device *dev : comedi device structure | +| pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ + +INT i_EepromReadMainHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, struct comedi_device *dev) +{ + WORD w_Temp, i, w_Count = 0; + UINT ui_Temp; + str_MainHeader s_MainHeader; + str_DigitalInputHeader s_DigitalInputHeader; + str_DigitalOutputHeader s_DigitalOutputHeader; + //str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader; + str_AnalogOutputHeader s_AnalogOutputHeader; + str_AnalogInputHeader s_AnalogInputHeader; + + // Read size + s_MainHeader.w_HeaderSize = + w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, + 0x100 + 8); + + // Read nbr of functionality + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, 0x100 + 10); + s_MainHeader.b_Nfunctions = (BYTE) w_Temp & 0x00FF; + + // Read functionality details + for (i = 0; i < s_MainHeader.b_Nfunctions; i++) { + // Read Type + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, 0x100 + 12 + w_Count); + s_MainHeader.s_Functions[i].b_Type = (BYTE) w_Temp & 0x3F; + w_Count = w_Count + 2; + //Read Address + s_MainHeader.s_Functions[i].w_Address = + w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, 0x100 + 12 + w_Count); + w_Count = w_Count + 2; + } + + // Display main header info + for (i = 0; i < s_MainHeader.b_Nfunctions; i++) { + + switch (s_MainHeader.s_Functions[i].b_Type) { + case EEPROM_DIGITALINPUT: + i_EepromReadDigitalInputHeader(w_PCIBoardEepromAddress, + pc_PCIChipInformation, + s_MainHeader.s_Functions[i].w_Address, + &s_DigitalInputHeader); + this_board->i_NbrDiChannel = + s_DigitalInputHeader.w_Nchannel; + break; + + case EEPROM_DIGITALOUTPUT: + i_EepromReadDigitalOutputHeader(w_PCIBoardEepromAddress, + pc_PCIChipInformation, + s_MainHeader.s_Functions[i].w_Address, + &s_DigitalOutputHeader); + this_board->i_NbrDoChannel = + s_DigitalOutputHeader.w_Nchannel; + ui_Temp = 0xffffffff; + this_board->i_DoMaxdata = + ui_Temp >> (32 - this_board->i_NbrDoChannel); + break; + + case EEPROM_ANALOGINPUT: + i_EepromReadAnlogInputHeader(w_PCIBoardEepromAddress, + pc_PCIChipInformation, + s_MainHeader.s_Functions[i].w_Address, + &s_AnalogInputHeader); + if (!(strcmp(this_board->pc_DriverName, "apci3200"))) + this_board->i_NbrAiChannel = + s_AnalogInputHeader.w_Nchannel * 4; + else + this_board->i_NbrAiChannel = + s_AnalogInputHeader.w_Nchannel; + this_board->i_Dma = s_AnalogInputHeader.b_HasDma; + this_board->ui_MinAcquisitiontimeNs = + (UINT) s_AnalogInputHeader.w_MinConvertTiming * + 1000; + this_board->ui_MinDelaytimeNs = + (UINT) s_AnalogInputHeader.w_MinDelayTiming * + 1000; + ui_Temp = 0xffff; + this_board->i_AiMaxdata = + ui_Temp >> (16 - + s_AnalogInputHeader.b_Resolution); + break; + + case EEPROM_ANALOGOUTPUT: + i_EepromReadAnlogOutputHeader(w_PCIBoardEepromAddress, + pc_PCIChipInformation, + s_MainHeader.s_Functions[i].w_Address, + &s_AnalogOutputHeader); + this_board->i_NbrAoChannel = + s_AnalogOutputHeader.w_Nchannel; + ui_Temp = 0xffff; + this_board->i_AoMaxdata = + ui_Temp >> (16 - + s_AnalogOutputHeader.b_Resolution); + break; + + case EEPROM_TIMER: + this_board->i_Timer = 1; //Timer subdevice present + break; + + case EEPROM_WATCHDOG: + this_board->i_Timer = 1; //Timer subdevice present + break; + + case EEPROM_TIMER_WATCHDOG_COUNTER: + this_board->i_Timer = 1; //Timer subdevice present + } + } + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadDigitalInputHeader(WORD | +| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, | +| WORD w_Address,str_DigitalInputHeader *s_Header) | +| | ++----------------------------------------------------------------------------+ +| Task : Read Digital Input Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| char *pc_PCIChipInformation : PCI Chip Type. | +| | +| str_DigitalInputHeader *s_Header: Digita Input Header | +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ +INT i_EepromReadDigitalInputHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_DigitalInputHeader * s_Header) +{ + WORD w_Temp; + + // read nbr of channels + s_Header->w_Nchannel = + w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, + 0x100 + w_Address + 6); + + // interruptible or not + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, 0x100 + w_Address + 8); + s_Header->b_Interruptible = (BYTE) (w_Temp >> 7) & 0x01; + +// How many interruptible logic + s_Header->w_NinterruptLogic = + w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, + 0x100 + w_Address + 10); + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadDigitalOutputHeader(WORD | +| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, | +| WORD w_Address,str_DigitalOutputHeader *s_Header) | +| | ++----------------------------------------------------------------------------+ +| Task : Read Digital Output Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| char *pc_PCIChipInformation : PCI Chip Type. | +| | +| str_DigitalOutputHeader *s_Header: Digital Output Header| +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ +INT i_EepromReadDigitalOutputHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_DigitalOutputHeader * s_Header) +{ +// Read Nbr channels + s_Header->w_Nchannel = + w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, + 0x100 + w_Address + 6); + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress, | +| char *pc_PCIChipInformation,WORD w_Address, | +| str_TimerMainHeader *s_Header) | ++----------------------------------------------------------------------------+ +| Task : Read Timer or Watchdog Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| char *pc_PCIChipInformation : PCI Chip Type. | +| | +| str_TimerMainHeader *s_Header: Timer Header | +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ +INT i_EepromReadTimerHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_TimerMainHeader * s_Header) +{ + + WORD i, w_Size = 0, w_Temp; + +//Read No of Timer + s_Header->w_Ntimer = + w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, + 0x100 + w_Address + 6); +//Read header size + + for (i = 0; i < s_Header->w_Ntimer; i++) { + s_Header->s_TimerDetails[i].w_HeaderSize = + w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, + 0x100 + w_Address + 8 + w_Size + 0); + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, + 0x100 + w_Address + 8 + w_Size + 2); + + //Read Resolution + s_Header->s_TimerDetails[i].b_Resolution = + (BYTE) (w_Temp >> 10) & 0x3F; + + //Read Mode + s_Header->s_TimerDetails[i].b_Mode = + (BYTE) (w_Temp >> 4) & 0x3F; + + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, + 0x100 + w_Address + 8 + w_Size + 4); + + //Read MinTiming + s_Header->s_TimerDetails[i].w_MinTiming = (w_Temp >> 6) & 0x3FF; + + //Read Timebase + s_Header->s_TimerDetails[i].b_TimeBase = (BYTE) (w_Temp) & 0x3F; + w_Size += s_Header->s_TimerDetails[i].w_HeaderSize; + } + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadAnlogOutputHeader(WORD | +| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, | +| WORD w_Address,str_AnalogOutputHeader *s_Header) | ++----------------------------------------------------------------------------+ +| Task : Read Nalog Output Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| char *pc_PCIChipInformation : PCI Chip Type. | +| | +| str_AnalogOutputHeader *s_Header:Anlog Output Header | +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ + +INT i_EepromReadAnlogOutputHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_AnalogOutputHeader * s_Header) +{ + WORD w_Temp; + // No of channels for 1st hard component + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, 0x100 + w_Address + 10); + s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF; + // Resolution for 1st hard component + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, 0x100 + w_Address + 16); + s_Header->b_Resolution = (BYTE) (w_Temp >> 8) & 0xFF; + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_EepromReadAnlogInputHeader(WORD | +| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, | +| WORD w_Address,str_AnalogInputHeader *s_Header) | ++----------------------------------------------------------------------------+ +| Task : Read Nalog Output Header | ++----------------------------------------------------------------------------+ +| Input Parameters : WORD w_PCIBoardEepromAddress : PCI eeprom address | +| | +| char *pc_PCIChipInformation : PCI Chip Type. | +| | +| str_AnalogInputHeader *s_Header:Anlog Input Header | +| Pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 | ++----------------------------------------------------------------------------+ +*/ + +// Reads only for ONE hardware component +INT i_EepromReadAnlogInputHeader(WORD w_PCIBoardEepromAddress, + char *pc_PCIChipInformation, WORD w_Address, + str_AnalogInputHeader * s_Header) +{ + WORD w_Temp, w_Offset; + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, 0x100 + w_Address + 10); + s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF; + s_Header->w_MinConvertTiming = + w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, + 0x100 + w_Address + 16); + s_Header->w_MinDelayTiming = + w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, + 0x100 + w_Address + 30); + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, 0x100 + w_Address + 20); + s_Header->b_HasDma = (w_Temp >> 13) & 0x01; // whether dma present or not + + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, 0x100 + w_Address + 72); // reading Y + w_Temp = w_Temp & 0x00FF; + if (w_Temp) //Y>0 + { + w_Offset = 74 + (2 * w_Temp) + (10 * (1 + (w_Temp / 16))); // offset of first analog input single header + w_Offset = w_Offset + 2; // resolution + } else //Y=0 + { + w_Offset = 74; + w_Offset = w_Offset + 2; // resolution + } + +// read Resolution + w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, + pc_PCIChipInformation, 0x100 + w_Address + w_Offset); + s_Header->b_Resolution = w_Temp & 0x001F; // last 5 bits + + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h new file mode 100644 index 000000000000..617dc087dcbf --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h @@ -0,0 +1,457 @@ +/* + Modified by umesh on 16th may 2001 + Modified by sarath on 22nd may 2001 +*/ + +/* + comedi/drivers/amcc_s5933_v_58.h + + Stuff for AMCC S5933 PCI Controller + + Author: Michal Dobes + + Inspirated from general-purpose AMCC S5933 PCI Matchmaker driver + made by Andrea Cisternino + and as result of espionage from MITE code made by David A. Schleef. + Thanks to AMCC for their on-line documentation and bus master DMA + example. +*/ + +#ifndef _AMCC_S5933_H_ +#define _AMCC_S5933_H_ + +#include +#include "../../comedidev.h" + +#ifdef PCI_SUPPORT_VER1 +#error Sorry, no support for 2.1.55 and older! :-(((( +#endif + +/***********Added by sarath for compatibility with APCI3120 + +*************************/ + +#define FIFO_ADVANCE_ON_BYTE_2 0x20000000 // written on base0 + +#define AMWEN_ENABLE 0x02 // added for step 6 dma written on base2 +#define A2P_FIFO_WRITE_ENABLE 0x01 + +#define AGCSTS_TC_ENABLE 0x10000000 // Added for transfer count enable bit + +// ADDON RELATED ADDITIONS +// Constant +#define APCI3120_ENABLE_TRANSFER_ADD_ON_LOW 0x00 +#define APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH 0x1200 +#define APCI3120_A2P_FIFO_MANAGEMENT 0x04000400L +#define APCI3120_AMWEN_ENABLE 0x02 +#define APCI3120_A2P_FIFO_WRITE_ENABLE 0x01 +#define APCI3120_FIFO_ADVANCE_ON_BYTE_2 0x20000000L +#define APCI3120_ENABLE_WRITE_TC_INT 0x00004000L +#define APCI3120_CLEAR_WRITE_TC_INT 0x00040000L +#define APCI3120_DISABLE_AMWEN_AND_A2P_FIFO_WRITE 0x0 +#define APCI3120_DISABLE_BUS_MASTER_ADD_ON 0x0 +#define APCI3120_DISABLE_BUS_MASTER_PCI 0x0 + + // ADD_ON ::: this needed since apci supports 16 bit interface to add on +#define APCI3120_ADD_ON_AGCSTS_LOW 0x3C +#define APCI3120_ADD_ON_AGCSTS_HIGH APCI3120_ADD_ON_AGCSTS_LOW + 2 +#define APCI3120_ADD_ON_MWAR_LOW 0x24 +#define APCI3120_ADD_ON_MWAR_HIGH APCI3120_ADD_ON_MWAR_LOW + 2 +#define APCI3120_ADD_ON_MWTC_LOW 0x058 +#define APCI3120_ADD_ON_MWTC_HIGH APCI3120_ADD_ON_MWTC_LOW + 2 + +// AMCC +#define APCI3120_AMCC_OP_MCSR 0x3C +#define APCI3120_AMCC_OP_REG_INTCSR 0x38 + +/*******from here all upward definitions are added by sarath */ + +/****************************************************************************/ +/* AMCC Operation Register Offsets - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_OMB1 0x00 +#define AMCC_OP_REG_OMB2 0x04 +#define AMCC_OP_REG_OMB3 0x08 +#define AMCC_OP_REG_OMB4 0x0c +#define AMCC_OP_REG_IMB1 0x10 +#define AMCC_OP_REG_IMB2 0x14 +#define AMCC_OP_REG_IMB3 0x18 +#define AMCC_OP_REG_IMB4 0x1c +#define AMCC_OP_REG_FIFO 0x20 +#define AMCC_OP_REG_MWAR 0x24 +#define AMCC_OP_REG_MWTC 0x28 +#define AMCC_OP_REG_MRAR 0x2c +#define AMCC_OP_REG_MRTC 0x30 +#define AMCC_OP_REG_MBEF 0x34 +#define AMCC_OP_REG_INTCSR 0x38 +#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) /* INT source */ +#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) /* FIFO ctrl */ +#define AMCC_OP_REG_MCSR 0x3c +#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) /* Data in byte 2 */ +#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) /* Command in byte 3 */ + +#define AMCC_FIFO_DEPTH_DWORD 8 +#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof (u32)) + +/****************************************************************************/ +/* AMCC Operation Registers Size - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_SIZE 64 /* in bytes */ + +/****************************************************************************/ +/* AMCC Operation Register Offsets - Add-on */ +/****************************************************************************/ + +#define AMCC_OP_REG_AIMB1 0x00 +#define AMCC_OP_REG_AIMB2 0x04 +#define AMCC_OP_REG_AIMB3 0x08 +#define AMCC_OP_REG_AIMB4 0x0c +#define AMCC_OP_REG_AOMB1 0x10 +#define AMCC_OP_REG_AOMB2 0x14 +#define AMCC_OP_REG_AOMB3 0x18 +#define AMCC_OP_REG_AOMB4 0x1c +#define AMCC_OP_REG_AFIFO 0x20 +#define AMCC_OP_REG_AMWAR 0x24 +#define AMCC_OP_REG_APTA 0x28 +#define AMCC_OP_REG_APTD 0x2c +#define AMCC_OP_REG_AMRAR 0x30 +#define AMCC_OP_REG_AMBEF 0x34 +#define AMCC_OP_REG_AINT 0x38 +#define AMCC_OP_REG_AGCSTS 0x3c +#define AMCC_OP_REG_AMWTC 0x58 +#define AMCC_OP_REG_AMRTC 0x5c + +/****************************************************************************/ +/* AMCC - Add-on General Control/Status Register */ +/****************************************************************************/ + +#define AGCSTS_CONTROL_MASK 0xfffff000 +#define AGCSTS_NV_ACC_MASK 0xe0000000 +#define AGCSTS_RESET_MASK 0x0e000000 +#define AGCSTS_NV_DA_MASK 0x00ff0000 +#define AGCSTS_BIST_MASK 0x0000f000 +#define AGCSTS_STATUS_MASK 0x000000ff +#define AGCSTS_TCZERO_MASK 0x000000c0 +#define AGCSTS_FIFO_ST_MASK 0x0000003f + +#define AGCSTS_RESET_MBFLAGS 0x08000000 +#define AGCSTS_RESET_P2A_FIFO 0x04000000 +#define AGCSTS_RESET_A2P_FIFO 0x02000000 +#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO) + +#define AGCSTS_A2P_TCOUNT 0x00000080 +#define AGCSTS_P2A_TCOUNT 0x00000040 + +#define AGCSTS_FS_P2A_EMPTY 0x00000020 +#define AGCSTS_FS_P2A_HALF 0x00000010 +#define AGCSTS_FS_P2A_FULL 0x00000008 + +#define AGCSTS_FS_A2P_EMPTY 0x00000004 +#define AGCSTS_FS_A2P_HALF 0x00000002 +#define AGCSTS_FS_A2P_FULL 0x00000001 + +/****************************************************************************/ +/* AMCC - Add-on Interrupt Control/Status Register */ +/****************************************************************************/ + +#define AINT_INT_MASK 0x00ff0000 +#define AINT_SEL_MASK 0x0000ffff +#define AINT_IS_ENSEL_MASK 0x00001f1f + +#define AINT_INT_ASSERTED 0x00800000 +#define AINT_BM_ERROR 0x00200000 +#define AINT_BIST_INT 0x00100000 + +#define AINT_RT_COMPLETE 0x00080000 +#define AINT_WT_COMPLETE 0x00040000 + +#define AINT_OUT_MB_INT 0x00020000 +#define AINT_IN_MB_INT 0x00010000 + +#define AINT_READ_COMPL 0x00008000 +#define AINT_WRITE_COMPL 0x00004000 + +#define AINT_OMB_ENABLE 0x00001000 +#define AINT_OMB_SELECT 0x00000c00 +#define AINT_OMB_BYTE 0x00000300 + +#define AINT_IMB_ENABLE 0x00000010 +#define AINT_IMB_SELECT 0x0000000c +#define AINT_IMB_BYTE 0x00000003 + +/* Enable Bus Mastering */ +#define EN_A2P_TRANSFERS 0x00000400 +/* FIFO Flag Reset */ +#define RESET_A2P_FLAGS 0x04000000L +/* FIFO Relative Priority */ +#define A2P_HI_PRIORITY 0x00000100L +/* Identify Interrupt Sources */ +#define ANY_S593X_INT 0x00800000L +#define READ_TC_INT 0x00080000L +#define WRITE_TC_INT 0x00040000L +#define IN_MB_INT 0x00020000L +#define MASTER_ABORT_INT 0x00100000L +#define TARGET_ABORT_INT 0x00200000L +#define BUS_MASTER_INT 0x00200000L + +/****************************************************************************/ + +struct pcilst_struct { + struct pcilst_struct *next; + int used; + struct pci_dev *pcidev; + unsigned short vendor; + unsigned short device; + unsigned int master; + unsigned char pci_bus; + unsigned char pci_slot; + unsigned char pci_func; + unsigned int io_addr[5]; + unsigned int irq; +}; + +struct pcilst_struct *amcc_devices; // ptr to root list of all amcc devices + +/****************************************************************************/ + +void v_pci_card_list_init(unsigned short pci_vendor, char display); +void v_pci_card_list_cleanup(unsigned short pci_vendor); +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, + unsigned short + device_id); +int i_find_free_pci_card_by_position(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + struct pcilst_struct **card); +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot); + +int i_pci_card_alloc(struct pcilst_struct *amcc); +int i_pci_card_free(struct pcilst_struct *amcc); +void v_pci_card_list_display(void); +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, + unsigned char *pci_func, unsigned short *io_addr, + unsigned short *irq, unsigned short *master); + +/****************************************************************************/ + +/* build list of amcc cards in this system */ +void v_pci_card_list_init(unsigned short pci_vendor, char display) +{ + struct pci_dev *pcidev; + struct pcilst_struct *amcc, *last; + int i; + + amcc_devices = NULL; + last = NULL; + + pci_for_each_dev(pcidev) { + if (pcidev->vendor == pci_vendor) { + amcc = kmalloc(sizeof(*amcc), GFP_KERNEL); + memset(amcc, 0, sizeof(*amcc)); + + amcc->pcidev = pcidev; + if (last) { + last->next = amcc; + } else { + amcc_devices = amcc; + } + last = amcc; + + amcc->vendor = pcidev->vendor; + amcc->device = pcidev->device; +#if 0 + amcc->master = pcidev->master; // how get this information under 2.4 kernels? +#endif + amcc->pci_bus = pcidev->bus->number; + amcc->pci_slot = PCI_SLOT(pcidev->devfn); + amcc->pci_func = PCI_FUNC(pcidev->devfn); + for (i = 0; i < 5; i++) + amcc->io_addr[i] = + pcidev->resource[i].start & ~3UL; + amcc->irq = pcidev->irq; + } + } + + if (display) + v_pci_card_list_display(); +} + +/****************************************************************************/ +/* free up list of amcc cards in this system */ +void v_pci_card_list_cleanup(unsigned short pci_vendor) +{ + struct pcilst_struct *amcc, *next; + + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + kfree(amcc); + } + + amcc_devices = NULL; +} + +/****************************************************************************/ +/* find first unused card with this device_id */ +struct pcilst_struct *ptr_find_free_pci_card_by_device(unsigned short vendor_id, + unsigned short device_id) +{ + struct pcilst_struct *amcc, *next; + + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + if ((!amcc->used) && (amcc->device == device_id) + && (amcc->vendor == vendor_id)) + return amcc; + + } + + return NULL; +} + +/****************************************************************************/ +/* find card on requested position */ +int i_find_free_pci_card_by_position(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot, + struct pcilst_struct **card) +{ + struct pcilst_struct *amcc, *next; + + *card = NULL; + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + if ((amcc->vendor == vendor_id) && (amcc->device == device_id) + && (amcc->pci_bus == pci_bus) + && (amcc->pci_slot == pci_slot)) { + if (!(amcc->used)) { + *card = amcc; + return 0; // ok, card is found + } else { + rt_printk + (" - \nCard on requested position is used b:s %d:%d!\n", + pci_bus, pci_slot); + return 2; // card exist but is used + } + } + } + + return 1; // no card found +} + +/****************************************************************************/ +/* mark card as used */ +int i_pci_card_alloc(struct pcilst_struct *amcc) +{ + if (!amcc) + return -1; + + if (amcc->used) + return 1; + amcc->used = 1; + return 0; +} + +/****************************************************************************/ +/* mark card as free */ +int i_pci_card_free(struct pcilst_struct *amcc) +{ + if (!amcc) + return -1; + + if (!amcc->used) + return 1; + amcc->used = 0; + return 0; +} + +/****************************************************************************/ +/* display list of found cards */ +void v_pci_card_list_display(void) +{ + struct pcilst_struct *amcc, *next; + + printk("List of pci cards\n"); + printk("bus:slot:func vendor device master io_amcc io_daq irq used\n"); + + for (amcc = amcc_devices; amcc; amcc = next) { + next = amcc->next; + printk + ("%2d %2d %2d 0x%4x 0x%4x %3s 0x%4x 0x%4x %2d %2d\n", + amcc->pci_bus, amcc->pci_slot, amcc->pci_func, + amcc->vendor, amcc->device, amcc->master ? "yes" : "no", + amcc->io_addr[0], amcc->io_addr[2], amcc->irq, amcc->used); + + } +} + +/****************************************************************************/ +/* return all card information for driver */ +int i_pci_card_data(struct pcilst_struct *amcc, + unsigned char *pci_bus, unsigned char *pci_slot, + unsigned char *pci_func, unsigned short *io_addr, + unsigned short *irq, unsigned short *master) +{ + int i; + + if (!amcc) + return -1; + *pci_bus = amcc->pci_bus; + *pci_slot = amcc->pci_slot; + *pci_func = amcc->pci_func; + for (i = 0; i < 5; i++) + io_addr[i] = amcc->io_addr[i]; + *irq = amcc->irq; + *master = amcc->master; + return 0; +} + +/****************************************************************************/ +/* select and alloc card */ +struct pcilst_struct *ptr_select_and_alloc_pci_card(unsigned short vendor_id, + unsigned short device_id, + unsigned short pci_bus, + unsigned short pci_slot) +{ + struct pcilst_struct *card; + + if ((pci_bus < 1) & (pci_slot < 1)) { // use autodetection + if ((card = ptr_find_free_pci_card_by_device(vendor_id, + device_id)) == + NULL) { + rt_printk(" - Unused card not found in system!\n"); + return NULL; + } + } else { + switch (i_find_free_pci_card_by_position(vendor_id, device_id, + pci_bus, pci_slot, + &card)) { + case 1: + rt_printk + (" - Card not found on requested position b:s %d:%d!\n", + pci_bus, pci_slot); + return NULL; + case 2: + rt_printk + (" - Card on requested position is used b:s %d:%d!\n", + pci_bus, pci_slot); + return NULL; + } + } + + if (i_pci_card_alloc(card) != 0) { + rt_printk(" - Can't allocate card!\n"); + return NULL; + } + + return card; +} + +#endif diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c new file mode 100644 index 000000000000..3f8929c09070 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c @@ -0,0 +1,1265 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-1710 | Compiler : GCC | + | Module name : hwdrv_apci1710.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-1710 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ +#include "hwdrv_APCI1710.h" +#include "APCI1710_Inp_cpt.c" + +#include "APCI1710_Ssi.c" +#include "APCI1710_Tor.c" +#include "APCI1710_Ttl.c" +#include "APCI1710_Dig_io.c" +#include "APCI1710_82x54.c" +#include "APCI1710_Chrono.c" +#include "APCI1710_Pwm.c" +#include "APCI1710_INCCPT.c" + +void i_ADDI_AttachPCI1710(struct comedi_device * dev) +{ + struct comedi_subdevice *s; + int ret = 0; + int n_subdevices = 9; + + //Update-0.7.57->0.7.68dev->n_subdevices = 9; + if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) + return; + + // Allocate and Initialise Timer Subdevice Structures + s = dev->subdevices + 0; + + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = SDF_WRITEABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = 3; + s->maxdata = 0; + s->len_chanlist = 3; + s->range_table = &range_digital; + s->insn_write = i_APCI1710_InsnWriteEnableDisableTimer; + s->insn_read = i_APCI1710_InsnReadAllTimerValue; + s->insn_config = i_APCI1710_InsnConfigInitTimer; + s->insn_bits = i_APCI1710_InsnBitsTimer; + + // Allocate and Initialise DIO Subdevice Structures + s = dev->subdevices + 1; + + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = + SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = 7; + s->maxdata = 1; + s->len_chanlist = 7; + s->range_table = &range_digital; + s->insn_config = i_APCI1710_InsnConfigDigitalIO; + s->insn_read = i_APCI1710_InsnReadDigitalIOChlValue; + s->insn_bits = i_APCI1710_InsnBitsDigitalIOPortOnOff; + s->insn_write = i_APCI1710_InsnWriteDigitalIOChlOnOff; + + // Allocate and Initialise Chrono Subdevice Structures + s = dev->subdevices + 2; + + s->type = COMEDI_SUBD_CHRONO; + s->subdev_flags = SDF_WRITEABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = 4; + s->maxdata = 0; + s->len_chanlist = 4; + s->range_table = &range_digital; + s->insn_write = i_APCI1710_InsnWriteEnableDisableChrono; + s->insn_read = i_APCI1710_InsnReadChrono; + s->insn_config = i_APCI1710_InsnConfigInitChrono; + s->insn_bits = i_APCI1710_InsnBitsChronoDigitalIO; + + // Allocate and Initialise PWM Subdevice Structures + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_PWM; + s->subdev_flags = + SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = 3; + s->maxdata = 1; + s->len_chanlist = 3; + s->range_table = &range_digital; + s->io_bits = 0; //all bits input + s->insn_config = i_APCI1710_InsnConfigPWM; + s->insn_read = i_APCI1710_InsnReadGetPWMStatus; + s->insn_write = i_APCI1710_InsnWritePWM; + s->insn_bits = i_APCI1710_InsnBitsReadPWMInterrupt; + + // Allocate and Initialise TTLIO Subdevice Structures + s = dev->subdevices + 4; + s->type = COMEDI_SUBD_TTLIO; + s->subdev_flags = + SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = 8; + s->maxdata = 1; + s->len_chanlist = 8; + s->range_table = &range_apci1710_ttl; // to pass arguments in range + s->insn_config = i_APCI1710_InsnConfigInitTTLIO; + s->insn_bits = i_APCI1710_InsnBitsReadTTLIO; + s->insn_write = i_APCI1710_InsnWriteSetTTLIOChlOnOff; + s->insn_read = i_APCI1710_InsnReadTTLIOAllPortValue; + + // Allocate and Initialise TOR Subdevice Structures + s = dev->subdevices + 5; + s->type = COMEDI_SUBD_TOR; + s->subdev_flags = + SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = 8; + s->maxdata = 1; + s->len_chanlist = 8; + s->range_table = &range_digital; + s->io_bits = 0; //all bits input + s->insn_config = i_APCI1710_InsnConfigInitTorCounter; + s->insn_read = i_APCI1710_InsnReadGetTorCounterInitialisation; + s->insn_write = i_APCI1710_InsnWriteEnableDisableTorCounter; + s->insn_bits = i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue; + + // Allocate and Initialise SSI Subdevice Structures + s = dev->subdevices + 6; + s->type = COMEDI_SUBD_SSI; + s->subdev_flags = + SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = 4; + s->maxdata = 1; + s->len_chanlist = 4; + s->range_table = &range_apci1710_ssi; + s->insn_config = i_APCI1710_InsnConfigInitSSI; + s->insn_read = i_APCI1710_InsnReadSSIValue; + s->insn_bits = i_APCI1710_InsnBitsSSIDigitalIO; + + // Allocate and Initialise PULSEENCODER Subdevice Structures + s = dev->subdevices + 7; + s->type = COMEDI_SUBD_PULSEENCODER; + s->subdev_flags = + SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = 4; + s->maxdata = 1; + s->len_chanlist = 4; + s->range_table = &range_digital; + s->insn_config = i_APCI1710_InsnConfigInitPulseEncoder; + s->insn_write = i_APCI1710_InsnWriteEnableDisablePulseEncoder; + s->insn_bits = i_APCI1710_InsnBitsReadWritePulseEncoder; + s->insn_read = i_APCI1710_InsnReadInterruptPulseEncoder; + + // Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures + s = dev->subdevices + 8; + s->type = COMEDI_SUBD_INCREMENTALCOUNTER; + s->subdev_flags = + SDF_WRITEABLE | SDF_READABLE | SDF_RT | SDF_GROUND | SDF_COMMON; + s->n_chan = 500; + s->maxdata = 1; + s->len_chanlist = 500; + s->range_table = &range_apci1710_inccpt; + s->insn_config = i_APCI1710_InsnConfigINCCPT; + s->insn_write = i_APCI1710_InsnWriteINCCPT; + s->insn_read = i_APCI1710_InsnReadINCCPT; + s->insn_bits = i_APCI1710_InsnBitsINCCPT; +} + +int i_APCI1710_Reset(struct comedi_device * dev); +void v_APCI1710_Interrupt(int irq, void *d); +//for 1710 + +int i_APCI1710_Reset(struct comedi_device * dev) +{ + int ret; + DWORD dw_Dummy; + + /*********************************/ + /* Read all module configuration */ + /*********************************/ + ret = inl(devpriv->s_BoardInfos.ui_Address + 60); + devpriv->s_BoardInfos.dw_MolduleConfiguration[0] = ret; + + ret = inl(devpriv->s_BoardInfos.ui_Address + 124); + devpriv->s_BoardInfos.dw_MolduleConfiguration[1] = ret; + + ret = inl(devpriv->s_BoardInfos.ui_Address + 188); + devpriv->s_BoardInfos.dw_MolduleConfiguration[2] = ret; + + ret = inl(devpriv->s_BoardInfos.ui_Address + 252); + devpriv->s_BoardInfos.dw_MolduleConfiguration[3] = ret; + + // outl(0x80808082,devpriv->s_BoardInfos.ui_Address+0x60); + outl(0x83838383, devpriv->s_BoardInfos.ui_Address + 0x60); + + devpriv->s_BoardInfos.b_BoardVersion = 1; + + // Enable the interrupt for the controler + dw_Dummy = inl(devpriv->s_BoardInfos.ui_Address + 0x38); + outl(dw_Dummy | 0x2000, devpriv->s_BoardInfos.ui_Address + 0x38); + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function's Name : __void__ v_APCI1710_InterruptFunction | +| (BYTE b_Interrupt, __CPPARGS) | ++----------------------------------------------------------------------------+ +| Task : APCI-1710 interrupt function | ++----------------------------------------------------------------------------+ +| Input Parameters : BYTE b_Interrupt : Interrupt number | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 : OK | +| -1 : Error | ++----------------------------------------------------------------------------+ +*/ + +void v_APCI1710_Interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + BYTE b_ModuleCpt = 0; + BYTE b_InterruptFlag = 0; + BYTE b_PWMCpt = 0; + BYTE b_TorCounterCpt = 0; + BYTE b_PulseIncoderCpt = 0; + UINT ui_16BitValue; + ULONG ul_InterruptLatchReg = 0; + ULONG ul_LatchRegisterValue = 0; + ULONG ul_82X54InterruptStatus; + ULONG ul_StatusRegister; + + str_ModuleInfo *ps_ModuleInfo; + + printk("APCI1710 Interrupt\n"); + for (b_ModuleCpt = 0; b_ModuleCpt < 4; b_ModuleCpt++, ps_ModuleInfo++) { + + /**************************/ + /* 1199/0225 to 0100/0226 */ + /**************************/ + ps_ModuleInfo = &devpriv->s_ModuleInfo[b_ModuleCpt]; + + /***********************/ + /* Test if 82X54 timer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModuleCpt] & + 0xFFFF0000UL) == APCI1710_82X54_TIMER) { + + //printk("TIMER Interrupt Occurred\n"); + ul_82X54InterruptStatus = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if ((ul_82X54InterruptStatus & ps_ModuleInfo-> + s_82X54ModuleInfo. + b_InterruptMask) != 0) { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = + (ul_82X54InterruptStatus & + ps_ModuleInfo->s_82X54ModuleInfo. + b_InterruptMask) << 4; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters. + ui_Write].ul_OldCounterLatchValue = 0; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + + } // if ((ul_82X54InterruptStatus & 0x7) != 0) + } // 82X54 timer + + /***************************/ + /* Test if increm. counter */ + /***************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModuleCpt] & + 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) { + + ul_InterruptLatchReg = inl(devpriv->s_BoardInfos. + ui_Address + (64 * b_ModuleCpt)); + + /*********************/ + /* Test if interrupt */ + /*********************/ + + if ((ul_InterruptLatchReg & 0x22) && (ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & 0x80)) { + /************************************/ + /* Test if strobe latch I interrupt */ + /************************************/ + + if (ul_InterruptLatchReg & 2) { + ul_LatchRegisterValue = + inl(devpriv->s_BoardInfos. + ui_Address + 4 + + (64 * b_ModuleCpt)); + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].ul_OldInterruptMask = + 1UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].b_OldModuleMask = + 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = + ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, + 0); + + } + + /*************************************/ + /* Test if strobe latch II interrupt */ + /*************************************/ + + if (ul_InterruptLatchReg & 0x20) { + + ul_LatchRegisterValue = + inl(devpriv->s_BoardInfos. + ui_Address + 8 + + (64 * b_ModuleCpt)); + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].ul_OldInterruptMask = + 2UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].b_OldModuleMask = + 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = + ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, + 0); + + } + } + + ul_InterruptLatchReg = inl(devpriv->s_BoardInfos. + ui_Address + 24 + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if index interrupt */ + /***************************/ + + if (ul_InterruptLatchReg & 0x8) { + ps_ModuleInfo-> + s_SiemensCounterInfo. + s_InitFlag.b_IndexInterruptOccur = 1; + + if (ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister2 & + APCI1710_INDEX_AUTO_MODE) { + + outl(ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + dw_ModeRegister1_2_3_4, + devpriv->s_BoardInfos. + ui_Address + 20 + + (64 * b_ModuleCpt)); + } + + /*****************************/ + /* Test if interrupt enabled */ + /*****************************/ + + if ((ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & + APCI1710_ENABLE_INDEX_INT) == + APCI1710_ENABLE_INDEX_INT) { + devpriv->s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].ul_OldInterruptMask = + 4UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].b_OldModuleMask = + 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = + ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, + 0); + + } + } + + /*****************************/ + /* Test if compare interrupt */ + /*****************************/ + + if (ul_InterruptLatchReg & 0x10) { + /*****************************/ + /* Test if interrupt enabled */ + /*****************************/ + + if ((ps_ModuleInfo-> + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister3 & + APCI1710_ENABLE_COMPARE_INT) == + APCI1710_ENABLE_COMPARE_INT) { + devpriv->s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].ul_OldInterruptMask = + 8UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].b_OldModuleMask = + 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = + ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, + 0); + + } + } + + /*******************************************/ + /* Test if frequency measurement interrupt */ + /*******************************************/ + + if (ul_InterruptLatchReg & 0x20) { + /*******************/ + /* Read the status */ + /*******************/ + + ul_StatusRegister = inl(devpriv->s_BoardInfos. + ui_Address + 32 + (64 * b_ModuleCpt)); + + /******************/ + /* Read the value */ + /******************/ + + ul_LatchRegisterValue = + inl(devpriv->s_BoardInfos.ui_Address + + 28 + (64 * b_ModuleCpt)); + + switch ((ul_StatusRegister >> 1) & 3) { + case 0: + /*************************/ + /* Test the counter mode */ + /*************************/ + + if ((devpriv->s_ModuleInfo[b_ModuleCpt]. + s_SiemensCounterInfo. + s_ModeRegister. + s_ByteModeRegister. + b_ModeRegister1 & + APCI1710_16BIT_COUNTER) + == APCI1710_16BIT_COUNTER) { + /****************************************/ + /* Test if 16-bit counter 1 pulse occur */ + /****************************************/ + + if ((ul_LatchRegisterValue & + 0xFFFFU) != 0) { + ui_16BitValue = + (UINT) + ul_LatchRegisterValue + & 0xFFFFU; + ul_LatchRegisterValue = + (ul_LatchRegisterValue + & 0xFFFF0000UL) + | (0xFFFFU - + ui_16BitValue); + } + + /****************************************/ + /* Test if 16-bit counter 2 pulse occur */ + /****************************************/ + + if ((ul_LatchRegisterValue & + 0xFFFF0000UL) != + 0) { + ui_16BitValue = + (UINT) ( + (ul_LatchRegisterValue + >> 16) & + 0xFFFFU); + ul_LatchRegisterValue = + (ul_LatchRegisterValue + & 0xFFFFUL) | + ((0xFFFFU - + ui_16BitValue) + << 16); + } + } else { + if (ul_LatchRegisterValue != 0) { + ul_LatchRegisterValue = + 0xFFFFFFFFUL - + ul_LatchRegisterValue; + } + } + break; + + case 1: + /****************************************/ + /* Test if 16-bit counter 2 pulse occur */ + /****************************************/ + + if ((ul_LatchRegisterValue & + 0xFFFF0000UL) != 0) { + ui_16BitValue = + (UINT) ( + (ul_LatchRegisterValue + >> 16) & + 0xFFFFU); + ul_LatchRegisterValue = + (ul_LatchRegisterValue & + 0xFFFFUL) | ((0xFFFFU - + ui_16BitValue) + << 16); + } + break; + + case 2: + /****************************************/ + /* Test if 16-bit counter 1 pulse occur */ + /****************************************/ + + if ((ul_LatchRegisterValue & 0xFFFFU) != + 0) { + ui_16BitValue = + (UINT) + ul_LatchRegisterValue & + 0xFFFFU; + ul_LatchRegisterValue = + (ul_LatchRegisterValue & + 0xFFFF0000UL) | (0xFFFFU + - ui_16BitValue); + } + break; + } + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = 0x10000UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters[devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = + ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + + } + } // Incremental counter + + /***************/ + /* Test if CDA */ + /***************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModuleCpt] & + 0xFFFF0000UL) == APCI1710_CDA) { + /******************************************/ + /* Test if CDA enable and functionality 0 */ + /******************************************/ + + if ((devpriv->s_ModuleInfo[b_ModuleCpt]. + s_CDAModuleInfo. + b_CDAEnable == APCI1710_ENABLE) + && (devpriv->s_ModuleInfo[b_ModuleCpt]. + s_CDAModuleInfo.b_FctSelection == 0)) { + /****************************/ + /* Get the interrupt status */ + /****************************/ + + ul_StatusRegister = inl(devpriv->s_BoardInfos. + ui_Address + 16 + (64 * b_ModuleCpt)); + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if (ul_StatusRegister & 1) { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].ul_OldInterruptMask = + 0x80000UL; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].b_OldModuleMask = + 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = 0; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, + 0); + + } // if (ul_StatusRegister & 1) + + } + } // CDA + + /***********************/ + /* Test if PWM counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModuleCpt] & + 0xFFFF0000UL) == APCI1710_PWM) { + for (b_PWMCpt = 0; b_PWMCpt < 2; b_PWMCpt++) { + /*************************************/ + /* Test if PWM interrupt initialised */ + /*************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModuleCpt]. + s_PWMModuleInfo. + s_PWMInfo[b_PWMCpt]. + b_InterruptEnable == APCI1710_ENABLE) { + /*****************************/ + /* Read the interrupt status */ + /*****************************/ + + ul_StatusRegister = + inl(devpriv->s_BoardInfos. + ui_Address + 16 + + (20 * b_PWMCpt) + + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if (ul_StatusRegister & 0x1) { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = + 0x4000UL << b_PWMCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = + 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + + 1) % + APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO, + devpriv->tsk_Current, + 0); + + } // if (ul_StatusRegister & 0x1) + } // if (APCI1710_ENABLE) + } // for (b_PWMCpt == 0; b_PWMCpt < 0; b_PWMCpt ++) + } // PWM counter + + /***********************/ + /* Test if tor counter */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModuleCpt] & + 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { + for (b_TorCounterCpt = 0; b_TorCounterCpt < 2; + b_TorCounterCpt++) { + /*************************************/ + /* Test if tor interrupt initialised */ + /*************************************/ + + if (devpriv-> + s_ModuleInfo[b_ModuleCpt]. + s_TorCounterModuleInfo. + s_TorCounterInfo[b_TorCounterCpt]. + b_InterruptEnable == APCI1710_ENABLE) { + /*****************************/ + /* Read the interrupt status */ + /*****************************/ + + ul_StatusRegister = + inl(devpriv->s_BoardInfos. + ui_Address + 12 + + (16 * b_TorCounterCpt) + + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if (ul_StatusRegister & 0x1) { + /******************************/ + /* Read the tor counter value */ + /******************************/ + + ul_LatchRegisterValue = + inl(devpriv-> + s_BoardInfos. + ui_Address + 0 + + (16 * b_TorCounterCpt) + + (64 * b_ModuleCpt)); + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = + 0x1000UL << + b_TorCounterCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = + 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue + = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + + 1) % + APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + + //Send a signal to from kernel to user space + send_sig(SIGIO, + devpriv->tsk_Current, + 0); + } // if (ul_StatusRegister & 0x1) + } // if (APCI1710_ENABLE) + } // for (b_TorCounterCpt == 0; b_TorCounterCpt < 0; b_TorCounterCpt ++) + } // Tor counter + + /***********************/ + /* Test if chronometer */ + /***********************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModuleCpt] & + 0xFFFF0000UL) == APCI1710_CHRONOMETER) { + + //printk("APCI1710 Chrono Interrupt\n"); + /*****************************/ + /* Read the interrupt status */ + /*****************************/ + + ul_InterruptLatchReg = inl(devpriv->s_BoardInfos. + ui_Address + 12 + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if ((ul_InterruptLatchReg & 0x8) == 0x8) { + /****************************/ + /* Clear the interrupt flag */ + /****************************/ + + outl(0, devpriv->s_BoardInfos. + ui_Address + 32 + (64 * b_ModuleCpt)); + + /***************************/ + /* Test if continuous mode */ + /***************************/ + + if (ps_ModuleInfo-> + s_ChronoModuleInfo. + b_CycleMode == APCI1710_ENABLE) { + /********************/ + /* Clear the status */ + /********************/ + + outl(0, devpriv->s_BoardInfos. + ui_Address + 36 + + (64 * b_ModuleCpt)); + } + + /*************************/ + /* Read the timing value */ + /*************************/ + + ul_LatchRegisterValue = + inl(devpriv->s_BoardInfos.ui_Address + + 4 + (64 * b_ModuleCpt)); + + /*****************************/ + /* Test if interrupt enabled */ + /*****************************/ + + if (ps_ModuleInfo-> + s_ChronoModuleInfo.b_InterruptMask) { + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].ul_OldInterruptMask = + 0x80; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write].b_OldModuleMask = + 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv->s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue = + ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + + 1) % APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, + 0); + + } + } + } // Chronometer + + /*************************/ + /* Test if pulse encoder */ + /*************************/ + + if ((devpriv->s_BoardInfos. + dw_MolduleConfiguration[b_ModuleCpt] & + 0xFFFF0000UL) == APCI1710_PULSE_ENCODER) { + /****************************/ + /* Read the status register */ + /****************************/ + + ul_StatusRegister = inl(devpriv->s_BoardInfos. + ui_Address + 20 + (64 * b_ModuleCpt)); + + if (ul_StatusRegister & 0xF) { + for (b_PulseIncoderCpt = 0; + b_PulseIncoderCpt < 4; + b_PulseIncoderCpt++) { + /*************************************/ + /* Test if pulse encoder initialised */ + /*************************************/ + + if ((ps_ModuleInfo-> + s_PulseEncoderModuleInfo. + s_PulseEncoderInfo + [b_PulseIncoderCpt]. + b_PulseEncoderInit == 1) + && (((ps_ModuleInfo->s_PulseEncoderModuleInfo.dw_SetRegister >> b_PulseIncoderCpt) & 1) == 1) && (((ul_StatusRegister >> (b_PulseIncoderCpt)) & 1) == 1)) { + devpriv->s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldInterruptMask = + 0x100UL << + b_PulseIncoderCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv-> + s_InterruptParameters. + ui_Write]. + b_OldModuleMask = + 1 << b_ModuleCpt; + + devpriv-> + s_InterruptParameters. + s_FIFOInterruptParameters + [devpriv-> + s_InterruptParameters. + ui_Write]. + ul_OldCounterLatchValue + = ul_LatchRegisterValue; + + devpriv-> + s_InterruptParameters. + ul_InterruptOccur++; + + /****************************/ + /* 0899/0224 to 1199/0225 */ + /****************************/ + /* Increment the write FIFO */ + /****************************/ + + devpriv-> + s_InterruptParameters. + ui_Write = (devpriv-> + s_InterruptParameters. + ui_Write + + 1) % + APCI1710_SAVE_INTERRUPT; + + b_InterruptFlag = 1; + + /**********************/ + /* Call user function */ + /**********************/ + //Send a signal to from kernel to user space + send_sig(SIGIO, + devpriv->tsk_Current, + 0); + + } + } + } + } //pulse encoder + + } + return; + +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h new file mode 100644 index 000000000000..998cbba8afeb --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */ +#define COMEDI_SUBD_PWM 12 /* Pulse width Measurement */ +#define COMEDI_SUBD_SSI 13 /* Synchronous serial interface */ +#define COMEDI_SUBD_TOR 14 /* Tor counter */ +#define COMEDI_SUBD_CHRONO 15 /* Chrono meter */ +#define COMEDI_SUBD_PULSEENCODER 16 /* Pulse Encoder INP CPT */ +#define COMEDI_SUBD_INCREMENTALCOUNTER 17 /* Incremental Counter */ + +#define APCI1710_BOARD_NAME "apci1710" +#define APCI1710_BOARD_VENDOR_ID 0x10E8 +#define APCI1710_BOARD_DEVICE_ID 0x818F +#define APCI1710_ADDRESS_RANGE 256 +#define APCI1710_CONFIG_ADDRESS_RANGE 8 +#define APCI1710_INCREMENTAL_COUNTER 0x53430000UL +#define APCI1710_SSI_COUNTER 0x53490000UL +#define APCI1710_TTL_IO 0x544C0000UL +#define APCI1710_DIGITAL_IO 0x44490000UL +#define APCI1710_82X54_TIMER 0x49430000UL +#define APCI1710_CHRONOMETER 0x43480000UL +#define APCI1710_PULSE_ENCODER 0x495A0000UL +#define APCI1710_TOR_COUNTER 0x544F0000UL +#define APCI1710_PWM 0x50570000UL +#define APCI1710_ETM 0x45540000UL +#define APCI1710_CDA 0x43440000UL +#define APCI1710_DISABLE 0 +#define APCI1710_ENABLE 1 +#define APCI1710_SYNCHRONOUS_MODE 1 +#define APCI1710_ASYNCHRONOUS_MODE 0 + +//MODULE INFO STRUCTURE + +static const struct comedi_lrange range_apci1710_ttl = { 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1) + } +}; + +static const struct comedi_lrange range_apci1710_ssi = { 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1) + } +}; + +static const struct comedi_lrange range_apci1710_inccpt = { 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1) + } +}; diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c new file mode 100644 index 000000000000..e4527926c2df --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c @@ -0,0 +1,600 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-035 | Compiler : GCC | + | Module name : hwdrv_apci035.c | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-035 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci035.h" +INT i_WatchdogNbr = 0; +INT i_Temp = 0; +INT i_Flag = 1; +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_ConfigTimerWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Configure As Timer | +| 1 Configure As Watchdog | + data[1] : Watchdog number +| data[2] : Time base Unit | +| data[3] : Reload Value | + data[4] : External Trigger | + 1:Enable + 0:Disable + data[5] :External Trigger Level + 00 Trigger Disabled + 01 Trigger Enabled (Low level) + 10 Trigger Enabled (High Level) + 11 Trigger Enabled (High/Low level) + data[6] : External Gate | + 1:Enable + 0:Disable + data[7] : External Gate level + 00 Gate Disabled + 01 Gate Enabled (Low level) + 10 Gate Enabled (High Level) + data[8] :Warning Relay + 1: ENABLE + 0: DISABLE + data[9] :Warning Delay available + data[10] :Warning Relay Time unit + data[11] :Warning Relay Time Reload value + data[12] :Reset Relay + 1 : ENABLE + 0 : DISABLE + data[13] :Interrupt + 1 : ENABLE + 0 : DISABLE + +| ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_ConfigTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Status = 0; + UINT ui_Command = 0; + UINT ui_Mode = 0; + i_Temp = 0; + devpriv->tsk_Current = current; + devpriv->b_TimerSelectMode = data[0]; + i_WatchdogNbr = data[1]; + if (data[0] == 0) { + ui_Mode = 2; + } else { + ui_Mode = 0; + } +//ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + ui_Command = 0; +//ui_Command = ui_Command & 0xFFFFF9FEUL; + outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + ui_Command = 0; + ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); +/************************/ +/* Set the reload value */ +/************************/ + outl(data[3], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 4); +/*********************/ +/* Set the time unit */ +/*********************/ + outl(data[2], devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 8); + if (data[0] == ADDIDATA_TIMER) { + + /******************************/ + /* Set the mode : */ + /* - Disable the hardware */ + /* - Disable the counter mode */ + /* - Disable the warning */ + /* - Disable the reset */ + /* - Enable the timer mode */ + /* - Set the timer mode */ + /******************************/ + + ui_Command = + (ui_Command & 0xFFF719E2UL) | ui_Mode << 13UL | 0x10UL; + + } //if (data[0] == ADDIDATA_TIMER) + else { + if (data[0] == ADDIDATA_WATCHDOG) { + + /******************************/ + /* Set the mode : */ + /* - Disable the hardware */ + /* - Disable the counter mode */ + /* - Disable the warning */ + /* - Disable the reset */ + /* - Disable the timer mode */ + /******************************/ + + ui_Command = ui_Command & 0xFFF819E2UL; + + } else { + printk("\n The parameter for Timer/watchdog selection is in error\n"); + return -EINVAL; + } + } + outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + ui_Command = 0; + ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); +/********************************/ +/* Disable the hardware trigger */ +/********************************/ + ui_Command = ui_Command & 0xFFFFF89FUL; + if (data[4] == ADDIDATA_ENABLE) { + /**********************************/ + /* Set the hardware trigger level */ + /**********************************/ + ui_Command = ui_Command | (data[5] << 5); + } + outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + ui_Command = 0; + ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); +/*****************************/ +/* Disable the hardware gate */ +/*****************************/ + ui_Command = ui_Command & 0xFFFFF87FUL; + if (data[6] == ADDIDATA_ENABLE) { +/*******************************/ +/* Set the hardware gate level */ +/*******************************/ + ui_Command = ui_Command | (data[7] << 7); + } + outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + ui_Command = 0; + ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); +/*******************************/ +/* Disable the hardware output */ +/*******************************/ + ui_Command = ui_Command & 0xFFFFF9FBUL; +/*********************************/ +/* Set the hardware output level */ +/*********************************/ + ui_Command = ui_Command | (data[8] << 2); + outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + if (data[9] == ADDIDATA_ENABLE) { + /************************/ + /* Set the reload value */ + /************************/ + outl(data[11], + devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 24); + /**********************/ + /* Set the time unite */ + /**********************/ + outl(data[10], + devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 28); + } + + ui_Command = 0; + ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + /*******************************/ + /* Disable the hardware output */ + /*******************************/ + ui_Command = ui_Command & 0xFFFFF9F7UL; + /*********************************/ + /* Set the hardware output level */ + /*********************************/ + ui_Command = ui_Command | (data[12] << 3); + outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + /*************************************/ + /** Enable the watchdog interrupt **/ + /*************************************/ + ui_Command = 0; + ui_Command = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); +/*******************************/ +/* Set the interrupt selection */ +/*******************************/ + ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16); + + ui_Command = (ui_Command & 0xFFFFF9FDUL) | (data[13] << 1); + outl(ui_Command, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_StartStopWriteTimerWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Selected Timer , or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 - Stop Selected Timer/Watchdog | +| 1 - Start Selected Timer/Watchdog | +| 2 - Trigger Selected Timer/Watchdog | +| 3 - Stop All Timer/Watchdog | +| 4 - Start All Timer/Watchdog | +| 5 - Trigger All Timer/Watchdog | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Command = 0; + INT i_Count = 0; + if (data[0] == 1) { + ui_Command = + inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + /**********************/ + /* Start the hardware */ + /**********************/ + ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x1UL; + outl(ui_Command, + devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + } // if (data[0]==1) + if (data[0] == 2) { + ui_Command = + inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + /***************************/ + /* Set the trigger command */ + /***************************/ + ui_Command = (ui_Command & 0xFFFFF9FFUL) | 0x200UL; + outl(ui_Command, + devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + } + + if (data[0] == 0) //Stop The Watchdog + { + //Stop The Watchdog + ui_Command = 0; + //ui_Command = inl(devpriv->iobase+((i_WatchdogNbr-1)*32)+12); + //ui_Command = ui_Command & 0xFFFFF9FEUL; + outl(ui_Command, + devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 12); + } // if (data[1]==0) + if (data[0] == 3) //stop all Watchdogs + { + ui_Command = 0; + for (i_Count = 1; i_Count <= 4; i_Count++) { + if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { + ui_Command = 0x2UL; + } else { + ui_Command = 0x10UL; + } + i_WatchdogNbr = i_Count; + outl(ui_Command, + devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + + 0); + } + + } + if (data[0] == 4) //start all Watchdogs + { + ui_Command = 0; + for (i_Count = 1; i_Count <= 4; i_Count++) { + if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { + ui_Command = 0x1UL; + } else { + ui_Command = 0x8UL; + } + i_WatchdogNbr = i_Count; + outl(ui_Command, + devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + + 0); + } + } + if (data[0] == 5) //trigger all Watchdogs + { + ui_Command = 0; + for (i_Count = 1; i_Count <= 4; i_Count++) { + if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { + ui_Command = 0x4UL; + } else { + ui_Command = 0x20UL; + } + + i_WatchdogNbr = i_Count; + outl(ui_Command, + devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + + 0); + } + i_Temp = 1; + } + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_ReadTimerWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] : software trigger status + data[1] : hardware trigger status +| data[2] : Software clear status + data[3] : Overflow status + data[4] : Timer actual value + + ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_ReadTimerWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Status = 0; // Status register + i_WatchdogNbr = insn->unused[0]; + /******************/ + /* Get the status */ + /******************/ + ui_Status = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 16); + /***********************************/ + /* Get the software trigger status */ + /***********************************/ + data[0] = ((ui_Status >> 1) & 1); + /***********************************/ + /* Get the hardware trigger status */ + /***********************************/ + data[1] = ((ui_Status >> 2) & 1); + /*********************************/ + /* Get the software clear status */ + /*********************************/ + data[2] = ((ui_Status >> 3) & 1); + /***************************/ + /* Get the overflow status */ + /***************************/ + data[3] = ((ui_Status >> 0) & 1); + if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { + data[4] = inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0); + + } // if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI035_ConfigAnalogInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Analog Input Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s : Subdevice Pointer | +| struct comedi_insn *insn : Insn Structure Pointer | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| data[0] : Warning delay value +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + devpriv->tsk_Current = current; + outl(0x200 | 0, devpriv->iobase + 128 + 0x4); + outl(0, devpriv->iobase + 128 + 0); +/********************************/ +/* Initialise the warning value */ +/********************************/ + outl(0x300 | 0, devpriv->iobase + 128 + 0x4); + outl((data[0] << 8), devpriv->iobase + 128 + 0); + outl(0x200000UL, devpriv->iobase + 128 + 12); + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_ReadAnalogInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | +| data[0] : Digital Value Of Input | +| | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_CommandRegister = 0; +/******************/ +/* Set the start */ +/******************/ + ui_CommandRegister = 0x80000; + /******************************/ + /* Write the command register */ + /******************************/ + outl(ui_CommandRegister, devpriv->iobase + 128 + 8); + +/***************************************/ +/* Read the digital value of the input */ +/***************************************/ + data[0] = inl(devpriv->iobase + 128 + 28); + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI035_Reset(struct comedi_device *dev) | +| | ++----------------------------------------------------------------------------+ +| Task :Resets the registers of the card | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI035_Reset(struct comedi_device * dev) +{ + INT i_Count = 0; + for (i_Count = 1; i_Count <= 4; i_Count++) { + i_WatchdogNbr = i_Count; + outl(0x0, devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 0); //stop all timers + } + outl(0x0, devpriv->iobase + 128 + 12); //Disable the warning delay + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI035_Interrupt | +| (int irq , void *d) | ++----------------------------------------------------------------------------+ +| Task : Interrupt processing Routine | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +static void v_APCI035_Interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + UINT ui_StatusRegister1 = 0; + UINT ui_StatusRegister2 = 0; + UINT ui_ReadCommand = 0; + UINT ui_ChannelNumber = 0; + UINT ui_DigitalTemperature = 0; + if (i_Temp == 1) { + i_WatchdogNbr = i_Flag; + i_Flag = i_Flag + 1; + } + /**************************************/ + /* Read the interrupt status register of temperature Warning */ + /**************************************/ + ui_StatusRegister1 = inl(devpriv->iobase + 128 + 16); + /**************************************/ + /* Read the interrupt status register for Watchdog/timer */ + /**************************************/ + + ui_StatusRegister2 = + inl(devpriv->iobase + ((i_WatchdogNbr - 1) * 32) + 20); + + if ((((ui_StatusRegister1) & 0x8) == 0x8)) //Test if warning relay interrupt + { + /**********************************/ + /* Disable the temperature warning */ + /**********************************/ + ui_ReadCommand = inl(devpriv->iobase + 128 + 12); + ui_ReadCommand = ui_ReadCommand & 0xFFDF0000UL; + outl(ui_ReadCommand, devpriv->iobase + 128 + 12); + /***************************/ + /* Read the channel number */ + /***************************/ + ui_ChannelNumber = inl(devpriv->iobase + 128 + 60); + /**************************************/ + /* Read the digital temperature value */ + /**************************************/ + ui_DigitalTemperature = inl(devpriv->iobase + 128 + 60); + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + } //if (((ui_StatusRegister1 & 0x8) == 0x8)) + + else { + if ((ui_StatusRegister2 & 0x1) == 0x1) { + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + } + } //else if (((ui_StatusRegister1 & 0x8) == 0x8)) + + return; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h new file mode 100644 index 000000000000..80d7c0d39aab --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/* Card Specific information */ +#define APCI035_BOARD_VENDOR_ID 0x15B8 +#define APCI035_ADDRESS_RANGE 255 + +INT i_TW_Number; +struct { + INT i_Gain; + INT i_Polarity; + INT i_OffsetRange; + INT i_Coupling; + INT i_SingleDiff; + INT i_AutoCalibration; + UINT ui_ReloadValue; + UINT ui_TimeUnitReloadVal; + INT i_Interrupt; + INT i_ModuleSelection; +} Config_Parameters_Main; + +/* ANALOG INPUT RANGE */ +struct comedi_lrange range_apci035_ai = { 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1) + } +}; + +/* Timer / Watchdog Related Defines */ +#define APCI035_TCW_SYNC_ENABLEDISABLE 0 +#define APCI035_TCW_RELOAD_VALUE 4 +#define APCI035_TCW_TIMEBASE 8 +#define APCI035_TCW_PROG 12 +#define APCI035_TCW_TRIG_STATUS 16 +#define APCI035_TCW_IRQ 20 +#define APCI035_TCW_WARN_TIMEVAL 24 +#define APCI035_TCW_WARN_TIMEBASE 28 + +#define ADDIDATA_TIMER 0 +/* #define ADDIDATA_WATCHDOG 1 */ + +#define APCI035_TW1 0 +#define APCI035_TW2 32 +#define APCI035_TW3 64 +#define APCI035_TW4 96 + +#define APCI035_AI_OFFSET 0 +#define APCI035_TEMP 128 +#define APCI035_ALR_SEQ 4 +#define APCI035_START_STOP_INDEX 8 +#define APCI035_ALR_START_STOP 12 +#define APCI035_ALR_IRQ 16 +#define APCI035_EOS 20 +#define APCI035_CHAN_NO 24 +#define APCI035_CHAN_VAL 28 +#define APCI035_CONV_TIME_TIME_BASE 36 +#define APCI035_RELOAD_CONV_TIME_VAL 32 +#define APCI035_DELAY_TIME_TIME_BASE 44 +#define APCI035_RELOAD_DELAY_TIME_VAL 40 +#define ENABLE_EXT_TRIG 1 +#define ENABLE_EXT_GATE 2 +#define ENABLE_EXT_TRIG_GATE 3 + +#define ANALOG_INPUT 0 +#define TEMPERATURE 1 +#define RESISTANCE 2 + +#define ADDIDATA_GREATER_THAN_TEST 0 +#define ADDIDATA_LESS_THAN_TEST 1 + +#define APCI035_MAXVOLT 2.5 + +#define ADDIDATA_UNIPOLAR 1 +#define ADDIDATA_BIPOLAR 2 + +/* ADDIDATA Enable Disable */ +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +/* Hardware Layer functions for Apci035 */ + +/* TIMER */ +/* timer value is passed as u seconds */ +INT i_APCI035_ConfigTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI035_StartStopWriteTimerWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI035_ReadTimerWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +/* Temperature Related Defines (Analog Input Subdevice) */ + +INT i_APCI035_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI035_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +/* Interrupt */ +static void v_APCI035_Interrupt(int irq, void *d); + +/* Reset functions */ +INT i_APCI035_Reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c new file mode 100644 index 000000000000..32796ceb946e --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c @@ -0,0 +1,285 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-1032 | Compiler : GCC | + | Module name : hwdrv_apci1032.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-1032 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci1032.h" +#include +//Global variables +UINT ui_InterruptStatus = 0; + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1032_ConfigDigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures the digital input Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 1 Enable Digital Input Interrupt | +| 0 Disable Digital Input Interrupt | +| data[1] : 0 ADDIDATA Interrupt OR LOGIC | +| : 1 ADDIDATA Interrupt AND LOGIC | +| data[2] : Interrupt mask for the mode 1 | +| data[3] : Interrupt mask for the mode 2 | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1032_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_TmpValue; + + ULONG ul_Command1 = 0; + ULONG ul_Command2 = 0; + devpriv->tsk_Current = current; + + /*******************************/ + /* Set the digital input logic */ + /*******************************/ + if (data[0] == ADDIDATA_ENABLE) { + ul_Command1 = ul_Command1 | data[2]; + ul_Command2 = ul_Command2 | data[3]; + outl(ul_Command1, + devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1); + outl(ul_Command2, + devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2); + if (data[1] == ADDIDATA_OR) { + outl(0x4, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); + ui_TmpValue = + inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); + } //if (data[1] == ADDIDATA_OR) + else { + outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); + } //else if(data[1] == ADDIDATA_OR) + } // if( data[0] == ADDIDATA_ENABLE) + else { + ul_Command1 = ul_Command1 & 0xFFFF0000; + ul_Command2 = ul_Command2 & 0xFFFF0000; + outl(ul_Command1, + devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1); + outl(ul_Command2, + devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2); + outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); + } //else if ( data[0] == ADDIDATA_ENABLE) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1032_Read1DigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_Channel : Channel number to read | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1032_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_TmpValue = 0; + UINT ui_Channel; + ui_Channel = CR_CHAN(insn->chanspec); + if (ui_Channel >= 0 && ui_Channel <= 31) { + ui_TmpValue = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP); + // since only 1 channel reqd to bring it to last bit it is rotated + // 8 +(chan - 1) times then ANDed with 1 for last bit. + *data = (ui_TmpValue >> ui_Channel) & 0x1; + } //if(ui_Channel >= 0 && ui_Channel <=31) + else { + //comedi_error(dev," \n chan spec wrong\n"); + return -EINVAL; // "sorry channel spec wrong " + } //else if(ui_Channel >= 0 && ui_Channel <=31) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1032_ReadMoreDigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To be Read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_PortValue = data[0]; + UINT ui_Mask = 0; + UINT ui_NoOfChannels; + + ui_NoOfChannels = CR_CHAN(insn->chanspec); + if (data[1] == 0) { + *data = (UINT) inl(devpriv->iobase + APCI1032_DIGITAL_IP); + switch (ui_NoOfChannels) { + case 2: + ui_Mask = 3; + *data = (*data >> (2 * ui_PortValue)) & ui_Mask; + break; + case 4: + ui_Mask = 15; + *data = (*data >> (4 * ui_PortValue)) & ui_Mask; + break; + case 8: + ui_Mask = 255; + *data = (*data >> (8 * ui_PortValue)) & ui_Mask; + break; + case 16: + ui_Mask = 65535; + *data = (*data >> (16 * ui_PortValue)) & ui_Mask; + break; + case 31: + break; + default: + //comedi_error(dev," \nchan spec wrong\n"); + return -EINVAL; // "sorry channel spec wrong " + break; + } //switch(ui_NoOfChannels) + } //if(data[1]==0) + else { + if (data[1] == 1) { + *data = ui_InterruptStatus; + } //if(data[1]==1) + } //else if(data[1]==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI1032_Interrupt | +| (int irq , void *d) | ++----------------------------------------------------------------------------+ +| Task : Interrupt handler for the interruptible digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +static void v_APCI1032_Interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + + UINT ui_Temp; + //disable the interrupt + ui_Temp = inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); + outl(ui_Temp & APCI1032_DIGITAL_IP_INTERRUPT_DISABLE, + devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); + ui_InterruptStatus = + inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS); + ui_InterruptStatus = ui_InterruptStatus & 0X0000FFFF; + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + outl(ui_Temp, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); //enable the interrupt + return; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1032_Reset(struct comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1032_Reset(struct comedi_device * dev) +{ + outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ); //disable the interrupts + inl(devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_STATUS); //Reset the interrupt status register + outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE1); //Disable the and/or interrupt + outl(0x0, devpriv->iobase + APCI1032_DIGITAL_IP_INTERRUPT_MODE2); + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h new file mode 100644 index 000000000000..659ef85088cd --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/********* Definitions for APCI-1032 card *****/ + +#define APCI1032_BOARD_VENDOR_ID 0x15B8 +#define APCI1032_ADDRESS_RANGE 20 +//DIGITAL INPUT DEFINE + +#define APCI1032_DIGITAL_IP 0 +#define APCI1032_DIGITAL_IP_INTERRUPT_MODE1 4 +#define APCI1032_DIGITAL_IP_INTERRUPT_MODE2 8 +#define APCI1032_DIGITAL_IP_IRQ 16 + +//Digital Input IRQ Function Selection +#define ADDIDATA_OR 0 +#define ADDIDATA_AND 1 + +//Digital Input Interrupt Status +#define APCI1032_DIGITAL_IP_INTERRUPT_STATUS 12 + +//Digital Input Interrupt Enable Disable. +#define APCI1032_DIGITAL_IP_INTERRUPT_ENABLE 0x4 +#define APCI1032_DIGITAL_IP_INTERRUPT_DISABLE 0xFFFFFFFB + +//ADDIDATA Enable Disable + +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +// Hardware Layer functions for Apci1032 + +//DI +// for di read + +INT i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +INT i_APCI1032_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +INT i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// Interrupt functions..... + +static void v_APCI1032_Interrupt(int irq, void *d); +//Reset +INT i_APCI1032_Reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c new file mode 100644 index 000000000000..2d6adcff41e3 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -0,0 +1,3045 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-1500 | Compiler : GCC | + | Module name : hwdrv_apci1500.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-1500 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ +#include "hwdrv_apci1500.h" + +int i_TimerCounter1Init = 0; +int i_TimerCounter2Init = 0; +int i_WatchdogCounter3Init = 0; +int i_Event1Status = 0, i_Event2Status = 0; +int i_TimerCounterWatchdogInterrupt = 0; +int i_Logic = 0, i_CounterLogic = 0; +int i_InterruptMask = 0; +int i_InputChannel = 0; +int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled = + 0, i_WatchdogCounter3Enabled = 0; + +/* + +----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ConfigDigitalInputEvent | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : An event can be generated for each port. | +| The first event is related to the first 8 channels | +| (port 1) and the second to the following 6 channels | +| (port 2). An interrupt is generated when one or both | +| events have occurred | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] :Number of the input port on | +| which the event will take place | +| (1 or 2) + data[1] : The event logic for port 1 has | +| three possibilities | +| :0 APCI1500_AND :This logic | +| links | +| the inputs | +| with an AND | +| logic. | +| 1 APCI1500_OR :This logic | +| links | +| the inputs | +| with a | +| OR logic. | +| 2 APCI1500_OR_PRIORITY | +| :This logic | +| links | +| the inputs | +| with a | +| priority | +| OR logic. | +| Input 1 | +| has the | +| highest | +| priority | +| level and | +| input 8 | +| the smallest| +| For the second port the user has| +| 1 possibility: | +| APCI1500_OR :This logic | +| links | +| the inputs | +| with a | +| polarity | +| OR logic | +| data[2] : These 8-character word for port1| +| and 6-character word for port 2 | +| give the mask of the event. | +| Each place gives the state | +| of the input channels and can | +| have one of these six characters| +| | +| 0 : This input must be on 0 | +| 1 : This input must be on 1 | +| 2 : This input reacts to | +| a falling edge | +| 3 : This input reacts to a | +| rising edge | +| 4 : This input reacts to both edges | +| +| 5 : This input is not | +| used for event | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1500_ConfigDigitalInputEvent(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0; + int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0; + int i_PatternTransitionCount = 0, i_RegValue; + int i; + + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Disables the main interrupt on the board */ + /**********************************************/ + outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + if (data[0] == 1) { + i_MaxChannel = 8; + } // if (data[0] == 1) + else { + if (data[0] == 2) { + i_MaxChannel = 6; + } // if(data[0]==2) + else { + printk("\nThe specified port event does not exist\n"); + return -EINVAL; + } //else if(data[0]==2) + } //else if (data[0] == 1) + switch (data[1]) { + case 0: + data[1] = APCI1500_AND; + break; + case 1: + data[1] = APCI1500_OR; + break; + case 2: + data[1] = APCI1500_OR_PRIORITY; + break; + default: + printk("\nThe specified interrupt logic does not exist\n"); + return -EINVAL; + } //switch(data[1]); + + i_Logic = data[1]; + for (i_Count = i_MaxChannel, i = 0; i_Count > 0; i_Count--, i++) { + i_EventMask = data[2 + i]; + switch (i_EventMask) { + case 0: + i_PatternMask = + i_PatternMask | (1 << (i_MaxChannel - i_Count)); + break; + case 1: + i_PatternMask = + i_PatternMask | (1 << (i_MaxChannel - i_Count)); + i_PatternPolarity = + i_PatternPolarity | (1 << (i_MaxChannel - + i_Count)); + break; + case 2: + i_PatternMask = + i_PatternMask | (1 << (i_MaxChannel - i_Count)); + i_PatternTransition = + i_PatternTransition | (1 << (i_MaxChannel - + i_Count)); + break; + case 3: + i_PatternMask = + i_PatternMask | (1 << (i_MaxChannel - i_Count)); + i_PatternPolarity = + i_PatternPolarity | (1 << (i_MaxChannel - + i_Count)); + i_PatternTransition = + i_PatternTransition | (1 << (i_MaxChannel - + i_Count)); + break; + case 4: + i_PatternTransition = + i_PatternTransition | (1 << (i_MaxChannel - + i_Count)); + break; + case 5: + break; + default: + printk("\nThe option indicated in the event mask does not exist\n"); + return -EINVAL; + } // switch(i_EventMask) + } //for (i_Count = i_MaxChannel; i_Count >0;i_Count --) + + if (data[0] == 1) { + /****************************/ + /* Test the interrupt logic */ + /****************************/ + + if (data[1] == APCI1500_AND || + data[1] == APCI1500_OR || + data[1] == APCI1500_OR_PRIORITY) { + /**************************************/ + /* Tests if a transition was declared */ + /* for a OR PRIORITY logic */ + /**************************************/ + + if (data[1] == APCI1500_OR_PRIORITY + && i_PatternTransition != 0) { + /********************************************/ + /* Transition error on an OR PRIORITY logic */ + /********************************************/ + printk("\nTransition error on an OR PRIORITY logic\n"); + return -EINVAL; + } // if (data[1]== APCI1500_OR_PRIORITY && i_PatternTransition != 0) + + /*************************************/ + /* Tests if more than one transition */ + /* was declared for an AND logic */ + /*************************************/ + + if (data[1] == APCI1500_AND) { + for (i_Count = 0; i_Count < 8; i_Count++) { + i_PatternTransitionCount = + i_PatternTransitionCount + + ((i_PatternTransition >> + i_Count) & 0x1); + + } //for (i_Count = 0; i_Count < 8; i_Count++) + + if (i_PatternTransitionCount > 1) { + /****************************************/ + /* Transition error on an AND logic */ + /****************************************/ + printk("\n Transition error on an AND logic\n"); + return -EINVAL; + } // if (i_PatternTransitionCount > 1) + } // if (data[1]== APCI1500_AND) + + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port A */ + /******************/ + outb(0xF0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Selects the polarity register of port 1 */ + /**********************************************/ + outb(APCI1500_RW_PORT_A_PATTERN_POLARITY, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternPolarity, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /*********************************************/ + /* Selects the pattern mask register of */ + /* port 1 */ + /*********************************************/ + outb(APCI1500_RW_PORT_A_PATTERN_MASK, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternMask, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /********************************************/ + /* Selects the pattern transition register */ + /* of port 1 */ + /********************************************/ + outb(APCI1500_RW_PORT_A_PATTERN_TRANSITION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternTransition, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /******************************************/ + /* Selects the mode specification mask */ + /* register of port 1 */ + /******************************************/ + outb(APCI1500_RW_PORT_A_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /******************************************/ + /* Selects the mode specification mask */ + /* register of port 1 */ + /******************************************/ + outb(APCI1500_RW_PORT_A_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /**********************/ + /* Port A new mode */ + /**********************/ + + i_RegValue = (i_RegValue & 0xF9) | data[1] | 0x9; + outb(i_RegValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + i_Event1Status = 1; + + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port A */ + /*****************/ + outb(0xF4, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + } // if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY) + else { + printk("\nThe choice for interrupt logic does not exist\n"); + return -EINVAL; + } // else }// if(data[1]==APCI1500_AND||data[1]==APCI1500_OR||data[1]==APCI1500_OR_PRIORITY) + } // if (data[0]== 1) + + /************************************/ + /* Test if event setting for port 2 */ + /************************************/ + + if (data[0] == 2) { + /************************/ + /* Test the event logic */ + /************************/ + + if (data[1] == APCI1500_OR) { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port B */ + /******************/ + outb(0x74, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the mode specification mask */ + /* register of port B */ + /****************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /******************************************/ + /* Selects the mode specification mask */ + /* register of port B */ + /******************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = i_RegValue & 0xF9; + outb(i_RegValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /**********************************/ + /* Selects error channels 1 and 2 */ + /**********************************/ + + i_PatternMask = (i_PatternMask | 0xC0); + i_PatternPolarity = (i_PatternPolarity | 0xC0); + i_PatternTransition = (i_PatternTransition | 0xC0); + + /**********************************************/ + /* Selects the polarity register of port 2 */ + /**********************************************/ + outb(APCI1500_RW_PORT_B_PATTERN_POLARITY, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternPolarity, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Selects the pattern transition register */ + /* of port 2 */ + /**********************************************/ + outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternTransition, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Selects the pattern Mask register */ + /* of port 2 */ + /**********************************************/ + + outb(APCI1500_RW_PORT_B_PATTERN_MASK, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_PatternMask, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /******************************************/ + /* Selects the mode specification mask */ + /* register of port 2 */ + /******************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /******************************************/ + /* Selects the mode specification mask */ + /* register of port 2 */ + /******************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = (i_RegValue & 0xF9) | 4; + outb(i_RegValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + i_Event2Status = 1; + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port B */ + /*****************/ + + outb(0xF4, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } // if (data[1] == APCI1500_OR) + else { + printk("\nThe choice for interrupt logic does not exist\n"); + return -EINVAL; + } //elseif (data[1] == APCI1500_OR) + } //if(data[0]==2) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_StartStopInputEvent | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Allows or disallows a port event | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_Channel : Channel number to read | +| unsigned int *data : Data Pointer to read status | + data[0] :0 Start input event + 1 Stop input event + data[1] :No of port (1 or 2) ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_StartStopInputEvent(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i_Event1InterruptStatus = 0, i_Event2InterruptStatus = + 0, i_RegValue; + switch (data[0]) { + case START: + /*************************/ + /* Tests the port number */ + /*************************/ + + if (data[1] == 1 || data[1] == 2) { + /***************************/ + /* Test if port 1 selected */ + /***************************/ + + if (data[1] == 1) { + /*****************************/ + /* Test if event initialised */ + /*****************************/ + if (i_Event1Status == 1) { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port A */ + /******************/ + outb(0xF0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the command and status register of */ + /* port 1 */ + /***************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*************************************/ + /* Allows the pattern interrupt */ + /*************************************/ + outb(0xC0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port A */ + /*****************/ + outb(0xF4, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_Event1InterruptStatus = 1; + outb(APCI1500_RW_PORT_A_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Authorizes the main interrupt on the board */ + /**********************************************/ + outb(0xD0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + } // if(i_Event1Status==1) + else { + printk("\nEvent 1 not initialised\n"); + return -EINVAL; + } //else if(i_Event1Status==1) + } //if (data[1]==1) + if (data[1] == 2) { + + if (i_Event2Status == 1) { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port B */ + /******************/ + outb(0x74, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the command and status register of */ + /* port 2 */ + /***************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*************************************/ + /* Allows the pattern interrupt */ + /*************************************/ + outb(0xC0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port B */ + /*****************/ + outb(0xF4, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Authorizes the main interrupt on the board */ + /**********************************************/ + outb(0xD0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_Event2InterruptStatus = 1; + } // if(i_Event2Status==1) + else { + printk("\nEvent 2 not initialised\n"); + return -EINVAL; + } //else if(i_Event2Status==1) + } // if(data[1]==2) + } // if (data[1] == 1 || data[0] == 2) + else { + printk("\nThe port parameter is in error\n"); + return -EINVAL; + } //else if (data[1] == 1 || data[0] == 2) + + break; + + case STOP: + /*************************/ + /* Tests the port number */ + /*************************/ + + if (data[1] == 1 || data[1] == 2) { + /***************************/ + /* Test if port 1 selected */ + /***************************/ + + if (data[1] == 1) { + /*****************************/ + /* Test if event initialised */ + /*****************************/ + if (i_Event1Status == 1) { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port A */ + /******************/ + outb(0xF0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the command and status register of */ + /* port 1 */ + /***************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*************************************/ + /* Inhibits the pattern interrupt */ + /*************************************/ + outb(0xE0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port A */ + /*****************/ + outb(0xF4, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_Event1InterruptStatus = 0; + } // if(i_Event1Status==1) + else { + printk("\nEvent 1 not initialised\n"); + return -EINVAL; + } //else if(i_Event1Status==1) + } //if (data[1]==1) + if (data[1] == 2) { + /*****************************/ + /* Test if event initialised */ + /*****************************/ + if (i_Event2Status == 1) { + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************/ + /* Disable Port B */ + /******************/ + outb(0x74, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the command and status register of */ + /* port 2 */ + /***************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*************************************/ + /* Inhibits the pattern interrupt */ + /*************************************/ + outb(0xE0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************************/ + /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ + /*****************************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*****************/ + /* Enable Port B */ + /*****************/ + outb(0xF4, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_Event2InterruptStatus = 0; + } // if(i_Event2Status==1) + else { + printk("\nEvent 2 not initialised\n"); + return -EINVAL; + } //else if(i_Event2Status==1) + } //if(data[1]==2) + + } // if (data[1] == 1 || data[1] == 2) + else { + printk("\nThe port parameter is in error\n"); + return -EINVAL; + } //else if (data[1] == 1 || data[1] == 2) + break; + default: + printk("\nThe option of START/STOP logic does not exist\n"); + return -EINVAL; + } //switch(data[0]) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_Initialisation | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_Channel : Channel number to read | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1500_Initialisation(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i_DummyRead = 0; + /******************/ + /* Software reset */ + /******************/ + i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the master configuration control register */ + /*****************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the mode specification register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the data path polarity register of port A */ + outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* High level of port A means 1 */ + outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the data direction register of port A */ + outb(APCI1500_RW_PORT_A_DATA_DIRECTION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs */ + outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port A */ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port A */ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of port A: */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the handshake specification register of port A */ + outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes the register */ + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the mode specification register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data path polarity register of port B */ + outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* A high level of port B means 1 */ + outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data direction register of port B */ + outb(APCI1500_RW_PORT_B_DATA_DIRECTION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs */ + outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port B */ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port B */ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of port B: */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the handshake specification register of port B */ + outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes the register */ + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the data path polarity register of port C */ + /*****************************************************/ + outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* High level of port C means 1 */ + outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data direction register of port C */ + outb(APCI1500_RW_PORT_C_DATA_DIRECTION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs except channel 1 */ + outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the special IO register of port C */ + outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes it */ + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 1 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of timer 1 */ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of timer 1 */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 2 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of timer 2 */ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates Timer 2 interrupt management: */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 3 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of Timer 3 */ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates interrupt management of timer 3: */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes all interrupts */ + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ReadMoreDigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To be Read | +| UINT *data : Data Pointer + data[0] : 0 Read a single channel + 1 read a port value + data[1] : port value ++----------------------------------------------------------------------------+ +| Output Parameters : -- data[0] :The read status value ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1500_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_PortValue = data[1]; + UINT ui_Mask = 0; + UINT ui_Channel; + UINT ui_TmpValue = 0; + ui_Channel = CR_CHAN(insn->chanspec); + + switch (data[0]) { + case 0: + if (ui_Channel >= 0 && ui_Channel <= 15) { + ui_TmpValue = + (UINT) inw(devpriv->i_IobaseAddon + + APCI1500_DIGITAL_IP); + *data = (ui_TmpValue >> ui_Channel) & 0x1; + } //if(ui_Channel >= 0 && ui_Channel <=15) + else { + printk("\nThe channel specification are in error\n"); + return -EINVAL; // "sorry channel spec wrong " + } //else if(ui_Channel >= 0 && ui_Channel <=15) + break; + case 1: + + *data = (UINT) inw(devpriv->i_IobaseAddon + + APCI1500_DIGITAL_IP); + switch (ui_Channel) { + case 2: + ui_Mask = 3; + *data = (*data >> (2 * ui_PortValue)) & ui_Mask; + break; + case 4: + ui_Mask = 15; + *data = (*data >> (4 * ui_PortValue)) & ui_Mask; + break; + case 8: + ui_Mask = 255; + *data = (*data >> (8 * ui_PortValue)) & ui_Mask; + break; + case 15: + break; + + default: + printk("\nSpecified channel cannot be read \n"); + return -EINVAL; // "sorry channel spec wrong " + break; + } //switch(ui_Channel) + break; + default: + printk("\nThe specified functionality does not exist\n"); + return -EINVAL; + } //switch(data[0]) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ConfigDigitalOutputErrorInterrupt + (struct comedi_device *dev,struct comedi_subdevice *s struct comedi_insn + *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures the digital output memory and the digital + output error interrupt | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| data[0] :1:Memory on | +| 0:Memory off | + data[1] :1 Enable the voltage error interrupt +| :0 Disable the voltage error interrupt | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + devpriv->b_OutputMemoryStatus = data[0]; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_WriteDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To Write | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1500_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + static UINT ui_Temp = 0; + UINT ui_Temp1; + + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + + if (!devpriv->b_OutputMemoryStatus) { + ui_Temp = 0; + + } //if(!devpriv->b_OutputMemoryStatus ) + if (data[3] == 0) { + if (data[1] == 0) { + data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; + outw(data[0], + devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP); + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = + (data[0] << (2 * + data[2])) | ui_Temp; + break; + + case 4: + data[0] = + (data[0] << (4 * + data[2])) | ui_Temp; + break; + + case 8: + data[0] = + (data[0] << (8 * + data[2])) | ui_Temp; + break; + + case 15: + data[0] = data[0] | ui_Temp; + break; + + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + + outw(data[0], + devpriv->i_IobaseAddon + + APCI1500_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==0) + else { + if (data[3] == 1) { + if (data[1] == 0) { + data[0] = ~data[0] & 0x1; + ui_Temp1 = 1; + ui_Temp1 = ui_Temp1 << ui_NoOfChannel; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + (data[0] << ui_NoOfChannel) ^ + 0xffffffff; + data[0] = data[0] & ui_Temp; + outw(data[0], + devpriv->i_IobaseAddon + + APCI1500_DIGITAL_OP); + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = ~data[0] & 0x3; + ui_Temp1 = 3; + ui_Temp1 = + ui_Temp1 << 2 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (2 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + + case 4: + data[0] = ~data[0] & 0xf; + ui_Temp1 = 15; + ui_Temp1 = + ui_Temp1 << 4 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (4 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + + case 8: + data[0] = ~data[0] & 0xff; + ui_Temp1 = 255; + ui_Temp1 = + ui_Temp1 << 8 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (8 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + + case 15: + break; + + default: + comedi_error(dev, + " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + + outw(data[0], + devpriv->i_IobaseAddon + + APCI1500_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==1); + else { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } //if else data[3]==1) + } //if else data[3]==0) + ui_Temp = data[0]; + return (insn->n);; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ConfigCounterTimerWatchdog(comedi_device + *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)| +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status data[0] : 2 APCI1500_1_8_KHZ +| 1 APCI1500_3_6_KHZ | +| 0 APCI1500_115_KHZ + data[1] : 0 Counter1/Timer1 + 1 Counter2/Timer2 + 2 Counter3/Watchdog + data[2] : 0 Counter + 1 Timer/Watchdog + data[3] : This parameter has | +| two meanings. | +| - If the counter/timer | +| is used as a counter | +| the limit value of | +| the counter is given | +| | +| - If the counter/timer | +| is used as a timer, | +| the divider factor | +| for the output is | +| given. + data[4] : 0 APCI1500_CONTINUOUS + 1 APCI1500_SINGLE + data[5] : 0 Software Trigger + 1 Hardware Trigger + + data[6] :0 Software gate + 1 Hardware gate + data[7] :0 Interrupt Disable + 1 Interrupt Enable ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int i_TimerCounterMode, i_MasterConfiguration; + + devpriv->tsk_Current = current; + +//Selection of the input clock + if (data[0] == 0 || data[0] == 1 || data[0] == 2) { + outw(data[0], devpriv->i_IobaseAddon + APCI1500_CLK_SELECT); + } // if(data[0]==0||data[0]==1||data[0]==2) + else { + if (data[0] != 3) { + printk("\nThe option for input clock selection does not exist\n"); + return -EINVAL; + } // if(data[0]!=3) + } //elseif(data[0]==0||data[0]==1||data[0]==2) + //Select the counter/timer + switch (data[1]) { + case COUNTER1: + //selecting counter or timer + switch (data[2]) { + case 0: + data[2] = APCI1500_COUNTER; + break; + case 1: + data[2] = APCI1500_TIMER; + break; + default: + printk("\nThis choice is not a timer nor a counter\n"); + return -EINVAL; + } // switch(data[2]) + + //Selecting single or continuous mode + switch (data[4]) { + case 0: + data[4] = APCI1500_CONTINUOUS; + break; + case 1: + data[4] = APCI1500_SINGLE; + break; + default: + printk("\nThis option for single/continuous mode does not exist\n"); + return -EINVAL; + } // switch(data[4]) + + i_TimerCounterMode = data[2] | data[4] | 7; + /*************************/ + /* Test the reload value */ + /*************************/ + + if ((data[3] >= 0) && (data[3] <= 65535)) { + if (data[7] == APCI1500_ENABLE + || data[7] == APCI1500_DISABLE) { + + /************************************************/ + /* Selects the mode register of timer/counter 1 */ + /************************************************/ + outb(APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***********************/ + /* Writes the new mode */ + /***********************/ + outb(i_TimerCounterMode, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of timer/counter 1 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR1_TIME_CST_LOW, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /*************************/ + /* Writes the low value */ + /*************************/ + + outb(data[3], + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of timer/counter 1 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR1_TIME_CST_HIGH, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /**************************/ + /* Writes the high value */ + /**************************/ + + data[3] = data[3] >> 8; + outb(data[3], + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /**********************/ + /* Reads the register */ + /**********************/ + + i_MasterConfiguration = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /********************************************************/ + /* Enables timer/counter 1 and triggers timer/counter 1 */ + /********************************************************/ + + i_MasterConfiguration = + i_MasterConfiguration | 0x40; + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /********************************/ + /* Writes the new configuration */ + /********************************/ + outb(i_MasterConfiguration, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the commands register of */ + /* timer/counter 1 */ + /****************************************/ + + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /***************************/ + /* Disable timer/counter 1 */ + /***************************/ + + outb(0x0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the commands register of */ + /* timer/counter 1 */ + /****************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /***************************/ + /* Trigger timer/counter 1 */ + /***************************/ + outb(0x2, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + else { + printk("\nError in selection of interrupt enable or disable\n"); + return -EINVAL; + } //elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + } // if ((data[3]>= 0) && (data[3] <= 65535)) + else { + printk("\nError in selection of reload value\n"); + return -EINVAL; + } //else if ((data[3]>= 0) && (data[3] <= 65535)) + i_TimerCounterWatchdogInterrupt = data[7]; + i_TimerCounter1Init = 1; + break; + + case COUNTER2: //selecting counter or timer + switch (data[2]) { + case 0: + data[2] = APCI1500_COUNTER; + break; + case 1: + data[2] = APCI1500_TIMER; + break; + default: + printk("\nThis choice is not a timer nor a counter\n"); + return -EINVAL; + } // switch(data[2]) + + //Selecting single or continuous mode + switch (data[4]) { + case 0: + data[4] = APCI1500_CONTINUOUS; + break; + case 1: + data[4] = APCI1500_SINGLE; + break; + default: + printk("\nThis option for single/continuous mode does not exist\n"); + return -EINVAL; + } // switch(data[4]) + + //Selecting software or hardware trigger + switch (data[5]) { + case 0: + data[5] = APCI1500_SOFTWARE_TRIGGER; + break; + case 1: + data[5] = APCI1500_HARDWARE_TRIGGER; + break; + default: + printk("\nThis choice for software or hardware trigger does not exist\n"); + return -EINVAL; + } // switch(data[5]) + + //Selecting software or hardware gate + switch (data[6]) { + case 0: + data[6] = APCI1500_SOFTWARE_GATE; + break; + case 1: + data[6] = APCI1500_HARDWARE_GATE; + break; + default: + printk("\nThis choice for software or hardware gate does not exist\n"); + return -EINVAL; + } // switch(data[6]) + + i_TimerCounterMode = data[2] | data[4] | data[5] | data[6] | 7; + + /*************************/ + /* Test the reload value */ + /*************************/ + + if ((data[3] >= 0) && (data[3] <= 65535)) { + if (data[7] == APCI1500_ENABLE + || data[7] == APCI1500_DISABLE) { + + /************************************************/ + /* Selects the mode register of timer/counter 2 */ + /************************************************/ + outb(APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***********************/ + /* Writes the new mode */ + /***********************/ + outb(i_TimerCounterMode, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of timer/counter 2 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR2_TIME_CST_LOW, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /*************************/ + /* Writes the low value */ + /*************************/ + + outb(data[3], + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of timer/counter 2 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR2_TIME_CST_HIGH, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /**************************/ + /* Writes the high value */ + /**************************/ + + data[3] = data[3] >> 8; + outb(data[3], + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /**********************/ + /* Reads the register */ + /**********************/ + + i_MasterConfiguration = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /********************************************************/ + /* Enables timer/counter 2 and triggers timer/counter 2 */ + /********************************************************/ + + i_MasterConfiguration = + i_MasterConfiguration | 0x20; + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /********************************/ + /* Writes the new configuration */ + /********************************/ + outb(i_MasterConfiguration, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the commands register of */ + /* timer/counter 2 */ + /****************************************/ + + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /***************************/ + /* Disable timer/counter 2 */ + /***************************/ + + outb(0x0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /****************************************/ + /* Selects the commands register of */ + /* timer/counter 2 */ + /****************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /***************************/ + /* Trigger timer/counter 1 */ + /***************************/ + outb(0x2, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + else { + printk("\nError in selection of interrupt enable or disable\n"); + return -EINVAL; + } //elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + } // if ((data[3]>= 0) && (data[3] <= 65535)) + else { + printk("\nError in selection of reload value\n"); + return -EINVAL; + } //else if ((data[3]>= 0) && (data[3] <= 65535)) + i_TimerCounterWatchdogInterrupt = data[7]; + i_TimerCounter2Init = 1; + break; + + case COUNTER3: //selecting counter or watchdog + switch (data[2]) { + case 0: + data[2] = APCI1500_COUNTER; + break; + case 1: + data[2] = APCI1500_WATCHDOG; + break; + default: + printk("\nThis choice is not a watchdog nor a counter\n"); + return -EINVAL; + } // switch(data[2]) + + //Selecting single or continuous mode + switch (data[4]) { + case 0: + data[4] = APCI1500_CONTINUOUS; + break; + case 1: + data[4] = APCI1500_SINGLE; + break; + default: + printk("\nThis option for single/continuous mode does not exist\n"); + return -EINVAL; + } // switch(data[4]) + + //Selecting software or hardware gate + switch (data[6]) { + case 0: + data[6] = APCI1500_SOFTWARE_GATE; + break; + case 1: + data[6] = APCI1500_HARDWARE_GATE; + break; + default: + printk("\nThis choice for software or hardware gate does not exist\n"); + return -EINVAL; + } // switch(data[6]) + + /*****************************/ + /* Test if used for watchdog */ + /*****************************/ + + if (data[2] == APCI1500_WATCHDOG) { + /*****************************/ + /* - Enables the output line */ + /* - Enables retrigger */ + /* - Pulses output */ + /*****************************/ + i_TimerCounterMode = data[2] | data[4] | 0x54; + } //if (data[2] == APCI1500_WATCHDOG) + else { + i_TimerCounterMode = data[2] | data[4] | data[6] | 7; + } //elseif (data[2] == APCI1500_WATCHDOG) + /*************************/ + /* Test the reload value */ + /*************************/ + + if ((data[3] >= 0) && (data[3] <= 65535)) { + if (data[7] == APCI1500_ENABLE + || data[7] == APCI1500_DISABLE) { + + /************************************************/ + /* Selects the mode register of watchdog/counter 3 */ + /************************************************/ + outb(APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***********************/ + /* Writes the new mode */ + /***********************/ + outb(i_TimerCounterMode, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of watchdog/counter 3 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR3_TIME_CST_LOW, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /*************************/ + /* Writes the low value */ + /*************************/ + + outb(data[3], + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /****************************************************/ + /* Selects the constant register of watchdog/counter 3 */ + /****************************************************/ + + outb(APCI1500_RW_CPT_TMR3_TIME_CST_HIGH, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /**************************/ + /* Writes the high value */ + /**************************/ + + data[3] = data[3] >> 8; + outb(data[3], + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /**********************/ + /* Reads the register */ + /**********************/ + + i_MasterConfiguration = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /********************************************************/ + /* Enables watchdog/counter 3 and triggers watchdog/counter 3 */ + /********************************************************/ + + i_MasterConfiguration = + i_MasterConfiguration | 0x10; + + /*********************************************/ + /* Selects the master configuration register */ + /*********************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /********************************/ + /* Writes the new configuration */ + /********************************/ + outb(i_MasterConfiguration, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /********************/ + /* Test if COUNTER */ + /********************/ + if (data[2] == APCI1500_COUNTER) { + + /*************************************/ + /* Selects the command register of */ + /* watchdog/counter 3 */ + /*************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /*************************************************/ + /* Disable the watchdog/counter 3 and starts it */ + /*************************************************/ + outb(0x0, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /*************************************/ + /* Selects the command register of */ + /* watchdog/counter 3 */ + /*************************************/ + + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /*************************************************/ + /* Trigger the watchdog/counter 3 and starts it */ + /*************************************************/ + outb(0x2, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + } //elseif(data[2]==APCI1500_COUNTER) + + } //if(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + else { + printk("\nError in selection of interrupt enable or disable\n"); + return -EINVAL; + } //elseif(data[7]== APCI1500_ENABLE ||data[7]== APCI1500_DISABLE) + } // if ((data[3]>= 0) && (data[3] <= 65535)) + else { + printk("\nError in selection of reload value\n"); + return -EINVAL; + } //else if ((data[3]>= 0) && (data[3] <= 65535)) + i_TimerCounterWatchdogInterrupt = data[7]; + i_WatchdogCounter3Init = 1; + break; + + default: + printk("\nThe specified counter\timer option does not exist\n"); + } //switch(data[1]) + i_CounterLogic = data[2]; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_StartStopTriggerTimerCounterWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data); | ++----------------------------------------------------------------------------+ +| Task : Start / Stop or trigger the timer counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | + data[0] : 0 Counter1/Timer1 + 1 Counter2/Timer2 + 2 Counter3/Watchdog + data[1] : 0 start + 1 stop + 2 Trigger + data[2] : 0 Counter + 1 Timer/Watchdog ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int i_CommandAndStatusValue; + + switch (data[0]) { + case COUNTER1: + switch (data[1]) { + case START: + if (i_TimerCounter1Init == 1) { + if (i_TimerCounterWatchdogInterrupt == 1) { + i_CommandAndStatusValue = 0xC4; //Enable the interrupt + } // if(i_TimerCounterWatchdogInterrupt==1) + else { + i_CommandAndStatusValue = 0xE4; //disable the interrupt + } //elseif(i_TimerCounterWatchdogInterrupt==1) + /**************************/ + /* Starts timer/counter 1 */ + /**************************/ + i_TimerCounter1Enabled = 1; + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if( i_TimerCounter1Init==1) + else { + printk("\nCounter/Timer1 not configured\n"); + return -EINVAL; + } + break; + + case STOP: + + /**************************/ + /* Stop timer/counter 1 */ + /**************************/ + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(0x00, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_TimerCounter1Enabled = 0; + break; + + case TRIGGER: + if (i_TimerCounter1Init == 1) { + if (i_TimerCounter1Enabled == 1) { + /************************/ + /* Set Trigger and gate */ + /************************/ + + i_CommandAndStatusValue = 0x6; + } //if( i_TimerCounter1Enabled==1) + else { + /***************/ + /* Set Trigger */ + /***************/ + + i_CommandAndStatusValue = 0x2; + } //elseif(i_TimerCounter1Enabled==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if( i_TimerCounter1Init==1) + else { + printk("\nCounter/Timer1 not configured\n"); + return -EINVAL; + } + break; + + default: + printk("\nThe specified option for start/stop/trigger does not exist\n"); + return -EINVAL; + } //switch(data[1]) + break; + + case COUNTER2: + switch (data[1]) { + case START: + if (i_TimerCounter2Init == 1) { + if (i_TimerCounterWatchdogInterrupt == 1) { + i_CommandAndStatusValue = 0xC4; //Enable the interrupt + } // if(i_TimerCounterWatchdogInterrupt==1) + else { + i_CommandAndStatusValue = 0xE4; //disable the interrupt + } //elseif(i_TimerCounterWatchdogInterrupt==1) + /**************************/ + /* Starts timer/counter 2 */ + /**************************/ + i_TimerCounter2Enabled = 1; + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if( i_TimerCounter2Init==1) + else { + printk("\nCounter/Timer2 not configured\n"); + return -EINVAL; + } + break; + + case STOP: + + /**************************/ + /* Stop timer/counter 2 */ + /**************************/ + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(0x00, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_TimerCounter2Enabled = 0; + break; + case TRIGGER: + if (i_TimerCounter2Init == 1) { + if (i_TimerCounter2Enabled == 1) { + /************************/ + /* Set Trigger and gate */ + /************************/ + + i_CommandAndStatusValue = 0x6; + } //if( i_TimerCounter2Enabled==1) + else { + /***************/ + /* Set Trigger */ + /***************/ + + i_CommandAndStatusValue = 0x2; + } //elseif(i_TimerCounter2Enabled==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if( i_TimerCounter2Init==1) + else { + printk("\nCounter/Timer2 not configured\n"); + return -EINVAL; + } + break; + default: + printk("\nThe specified option for start/stop/trigger does not exist\n"); + return -EINVAL; + } //switch(data[1]) + break; + case COUNTER3: + switch (data[1]) { + case START: + if (i_WatchdogCounter3Init == 1) { + + if (i_TimerCounterWatchdogInterrupt == 1) { + i_CommandAndStatusValue = 0xC4; //Enable the interrupt + } // if(i_TimerCounterWatchdogInterrupt==1) + else { + i_CommandAndStatusValue = 0xE4; //disable the interrupt + } //elseif(i_TimerCounterWatchdogInterrupt==1) + /**************************/ + /* Starts Watchdog/counter 3 */ + /**************************/ + i_WatchdogCounter3Enabled = 1; + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + } // if( i_WatchdogCounter3init==1) + else { + printk("\nWatchdog/Counter3 not configured\n"); + return -EINVAL; + } + break; + + case STOP: + + /**************************/ + /* Stop Watchdog/counter 3 */ + /**************************/ + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(0x00, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_WatchdogCounter3Enabled = 0; + break; + + case TRIGGER: + switch (data[2]) { + case 0: //triggering counter 3 + if (i_WatchdogCounter3Init == 1) { + if (i_WatchdogCounter3Enabled == 1) { + /************************/ + /* Set Trigger and gate */ + /************************/ + + i_CommandAndStatusValue = 0x6; + } //if( i_WatchdogCounter3Enabled==1) + else { + /***************/ + /* Set Trigger */ + /***************/ + + i_CommandAndStatusValue = 0x2; + } //elseif(i_WatchdogCounter3Enabled==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if( i_WatchdogCounter3Init==1) + else { + printk("\nCounter3 not configured\n"); + return -EINVAL; + } + break; + case 1: + //triggering Watchdog 3 + if (i_WatchdogCounter3Init == 1) { + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(0x6, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if( i_WatchdogCounter3Init==1) + else { + printk("\nWatchdog 3 not configured\n"); + return -EINVAL; + } + break; + default: + printk("\nWrong choice of watchdog/counter3\n"); + return -EINVAL; + } //switch(data[2]) + break; + default: + printk("\nThe specified option for start/stop/trigger does not exist\n"); + return -EINVAL; + } //switch(data[1]) + break; + default: + printk("\nThe specified choice for counter/watchdog/timer does not exist\n"); + return -EINVAL; + } //switch(data[0]) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ReadCounterTimerWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data); | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | + data[0] : 0 Counter1/Timer1 + 1 Counter2/Timer2 + 2 Counter3/Watchdog + ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int i_CommandAndStatusValue; + switch (data[0]) { + case COUNTER1: + //Read counter/timer1 + if (i_TimerCounter1Init == 1) { + if (i_TimerCounter1Enabled == 1) { + /************************/ + /* Set RCC and gate */ + /************************/ + + i_CommandAndStatusValue = 0xC; + } //if( i_TimerCounter1Init==1) + else { + /***************/ + /* Set RCC */ + /***************/ + + i_CommandAndStatusValue = 0x8; + } //elseif(i_TimerCounter1Init==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /***************************************/ + /* Selects the counter register (high) */ + /***************************************/ + outb(APCI1500_R_CPT_TMR1_VALUE_HIGH, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + data[0] = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + data[0] = data[0] << 8; + data[0] = data[0] & 0xff00; + outb(APCI1500_R_CPT_TMR1_VALUE_LOW, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + data[0] = + data[0] | inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if( i_TimerCounter1Init==1) + else { + printk("\nTimer/Counter1 not configured\n"); + return -EINVAL; + } //elseif( i_TimerCounter1Init==1) + break; + case COUNTER2: + //Read counter/timer2 + if (i_TimerCounter2Init == 1) { + if (i_TimerCounter2Enabled == 1) { + /************************/ + /* Set RCC and gate */ + /************************/ + + i_CommandAndStatusValue = 0xC; + } //if( i_TimerCounter2Init==1) + else { + /***************/ + /* Set RCC */ + /***************/ + + i_CommandAndStatusValue = 0x8; + } //elseif(i_TimerCounter2Init==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /***************************************/ + /* Selects the counter register (high) */ + /***************************************/ + outb(APCI1500_R_CPT_TMR2_VALUE_HIGH, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + data[0] = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + data[0] = data[0] << 8; + data[0] = data[0] & 0xff00; + outb(APCI1500_R_CPT_TMR2_VALUE_LOW, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + data[0] = + data[0] | inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if( i_TimerCounter2Init==1) + else { + printk("\nTimer/Counter2 not configured\n"); + return -EINVAL; + } //elseif( i_TimerCounter2Init==1) + break; + case COUNTER3: + //Read counter/watchdog2 + if (i_WatchdogCounter3Init == 1) { + if (i_WatchdogCounter3Enabled == 1) { + /************************/ + /* Set RCC and gate */ + /************************/ + + i_CommandAndStatusValue = 0xC; + } //if( i_TimerCounter2Init==1) + else { + /***************/ + /* Set RCC */ + /***************/ + + i_CommandAndStatusValue = 0x8; + } //elseif(i_WatchdogCounter3Init==1) + + /********************************************/ + /* Selects the commands and status register */ + /********************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_CommandAndStatusValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /***************************************/ + /* Selects the counter register (high) */ + /***************************************/ + outb(APCI1500_R_CPT_TMR3_VALUE_HIGH, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + data[0] = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + data[0] = data[0] << 8; + data[0] = data[0] & 0xff00; + outb(APCI1500_R_CPT_TMR3_VALUE_LOW, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + data[0] = + data[0] | inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + } //if( i_WatchdogCounter3Init==1) + else { + printk("\nWatchdogCounter3 not configured\n"); + return -EINVAL; + } //elseif( i_WatchdogCounter3Init==1) + break; + default: + printk("\nThe choice of timer/counter/watchdog does not exist\n"); + return -EINVAL; + } //switch(data[0]) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ReadInterruptMask | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data); | ++----------------------------------------------------------------------------+ +| Task : Read the interrupt mask | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | + + ++----------------------------------------------------------------------------+ +| Output Parameters : -- data[0]:The interrupt mask value data[1]:Channel no ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_ReadInterruptMask(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = i_InterruptMask; + data[1] = i_InputChannel; + i_InterruptMask = 0; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_ConfigureInterrupt | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data); | ++----------------------------------------------------------------------------+ +| Task : Configures the interrupt registers | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer | + + ++----------------------------------------------------------------------------+ +| Output Parameters : -- ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1500_ConfigureInterrupt(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Status; + int i_RegValue; + int i_Constant; + devpriv->tsk_Current = current; + outl(0x0, devpriv->i_IobaseAmcc + 0x38); + if (data[0] == 1) { + i_Constant = 0xC0; + } //if(data[0]==1) + else { + if (data[0] == 0) { + i_Constant = 0x00; + } //if{data[0]==0) + else { + printk("\nThe parameter passed to driver is in error for enabling the voltage interrupt\n"); + return -EINVAL; + } //else if(data[0]==0) + } //elseif(data[0]==1) + + /*****************************************************/ + /* Selects the mode specification register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_PORT_B_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*********************************************/ + /* Writes the new configuration (APCI1500_OR) */ + /*********************************************/ + i_RegValue = (i_RegValue & 0xF9) | APCI1500_OR; + + outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************/ + /* Authorises the interrupt on the board */ + /*****************************************/ + outb(0xC0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /***************************************************/ + /* Selects the pattern polarity register of port B */ + /***************************************************/ + outb(APCI1500_RW_PORT_B_PATTERN_POLARITY, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************/ + /* Selects the pattern transition register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************************/ + /* Selects the pattern mask register of port B */ + /***********************************************/ + outb(APCI1500_RW_PORT_B_PATTERN_MASK, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the command and status register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of port A */ + /***********************************/ + + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of port B */ + /***********************************/ + + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the command and status register of timer 1 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 1 */ + /***********************************/ + + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the command and status register of timer 2 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 2 */ + /***********************************/ + + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the command and status register of timer 3 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 3 */ + /***********************************/ + + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Authorizes the main interrupt on the board */ + /**********************************************/ + outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /***************************/ + /* Enables the PCI interrupt */ + /*****************************/ + outl(0x3000, devpriv->i_IobaseAmcc + 0x38); + ui_Status = inl(devpriv->i_IobaseAmcc + 0x10); + ui_Status = inl(devpriv->i_IobaseAmcc + 0x38); + outl(0x23000, devpriv->i_IobaseAmcc + 0x38); + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI1500_Interrupt | +| (int irq , void *d) | ++----------------------------------------------------------------------------+ +| Task : Interrupt handler | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +static void v_APCI1500_Interrupt(int irq, void *d) +{ + + struct comedi_device *dev = d; + UINT ui_InterruptStatus = 0; + int i_RegValue = 0; + i_InterruptMask = 0; + + /***********************************/ + /* Read the board interrupt status */ + /***********************************/ + ui_InterruptStatus = inl(devpriv->i_IobaseAmcc + 0x38); + + /***************************************/ + /* Test if board generated a interrupt */ + /***************************************/ + if ((ui_InterruptStatus & 0x800000) == 0x800000) { + /************************/ + /* Disable all Interrupt */ + /************************/ + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + //outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Disables the main interrupt on the board */ + /**********************************************/ + //outb(0x00,devpriv->iobase+APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the command and status register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) { + /*****************************************************/ + /* Selects the command and status register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of port A */ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_InterruptMask = i_InterruptMask | 1; + if (i_Logic == APCI1500_OR_PRIORITY) { + outb(APCI1500_RW_PORT_A_SPECIFICATION, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + /***************************************************/ + /* Selects the interrupt vector register of port A */ + /***************************************************/ + outb(APCI1500_RW_PORT_A_INTERRUPT_CONTROL, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + + i_InputChannel = 1 + (i_RegValue >> 1); + + } // if(i_Logic==APCI1500_OR_PRIORITY) + else { + i_InputChannel = 0; + } //elseif(i_Logic==APCI1500_OR_PRIORITY) + } // if ((i_RegValue & 0x60) == 0x60) + + /*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) { + /*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of port B */ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + printk("\n\n\n"); + /****************/ + /* Reads port B */ + /****************/ + i_RegValue = + inb((UINT) devpriv->iobase + + APCI1500_Z8536_PORT_B); + + i_RegValue = i_RegValue & 0xC0; + /**************************************/ + /* Tests if this is an external error */ + /**************************************/ + + if (i_RegValue) { + //Disable the interrupt + /*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outl(0x0, devpriv->i_IobaseAmcc + 0x38); + + if (i_RegValue & 0x80) { + i_InterruptMask = + i_InterruptMask | 0x40; + } //if (i_RegValue & 0x80) + + if (i_RegValue & 0x40) { + i_InterruptMask = + i_InterruptMask | 0x80; + } //if (i_RegValue & 0x40) + } // if (i_RegValue) + else { + i_InterruptMask = i_InterruptMask | 2; + } // if (i_RegValue) + } //if ((i_RegValue & 0x60) == 0x60) + + /*****************************************************/ + /* Selects the command and status register of timer 1 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) { + /*****************************************************/ + /* Selects the command and status register of timer 1 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 1 */ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_InterruptMask = i_InterruptMask | 4; + } // if ((i_RegValue & 0x60) == 0x60) + /*****************************************************/ + /* Selects the command and status register of timer 2 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) { + /*****************************************************/ + /* Selects the command and status register of timer 2 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 2 */ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + i_InterruptMask = i_InterruptMask | 8; + } // if ((i_RegValue & 0x60) == 0x60) + + /*****************************************************/ + /* Selects the command and status register of timer 3 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = + inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + if ((i_RegValue & 0x60) == 0x60) { + /*****************************************************/ + /* Selects the command and status register of timer 3 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + /***********************************/ + /* Deletes the interrupt of timer 3 */ + /***********************************/ + i_RegValue = (i_RegValue & 0x0F) | 0x20; + outb(i_RegValue, + devpriv->iobase + + APCI1500_Z8536_CONTROL_REGISTER); + if (i_CounterLogic == APCI1500_COUNTER) { + i_InterruptMask = i_InterruptMask | 0x10; + } //if(i_CounterLogic==APCI1500_COUNTER) + else { + i_InterruptMask = i_InterruptMask | 0x20; + } + } // if ((i_RegValue & 0x60) == 0x60) + + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + /***********************/ + /* Enable all Interrupts */ + /***********************/ + + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /**********************************************/ + /* Authorizes the main interrupt on the board */ + /**********************************************/ + outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + } // if ((ui_InterruptStatus & 0x800000) == 0x800000) + else { + printk("\nInterrupt from unknown source\n"); + + } //else if ((ui_InterruptStatus & 0x800000) == 0x800000) + return; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1500_Reset(struct comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1500_Reset(struct comedi_device * dev) +{ + int i_DummyRead = 0; + i_TimerCounter1Init = 0; + i_TimerCounter2Init = 0; + i_WatchdogCounter3Init = 0; + i_Event1Status = 0; + i_Event2Status = 0; + i_TimerCounterWatchdogInterrupt = 0; + i_Logic = 0; + i_CounterLogic = 0; + i_InterruptMask = 0; + i_InputChannel = 0;; + i_TimerCounter1Enabled = 0; + i_TimerCounter2Enabled = 0; + i_WatchdogCounter3Enabled = 0; + + /******************/ + /* Software reset */ + /******************/ + i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the master configuration control register */ + /*****************************************************/ + outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the mode specification register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the data path polarity register of port A */ + outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* High level of port A means 1 */ + outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /* Selects the data direction register of port A */ + outb(APCI1500_RW_PORT_A_DATA_DIRECTION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs */ + outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port A */ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port A */ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of port A: */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the handshake specification register of port A */ + outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes the register */ + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the mode specification register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data path polarity register of port B */ + outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* A high level of port B means 1 */ + outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data direction register of port B */ + outb(APCI1500_RW_PORT_B_DATA_DIRECTION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs */ + outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port B */ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of port B */ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of port B: */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the handshake specification register of port B */ + outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes the register */ + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + /*****************************************************/ + /* Selects the data path polarity register of port C */ + /*****************************************************/ + outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* High level of port C means 1 */ + outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the data direction register of port C */ + outb(APCI1500_RW_PORT_C_DATA_DIRECTION, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* All bits used as inputs except channel 1 */ + outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the special IO register of port C */ + outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes it */ + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 1 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of timer 1 */ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates the interrupt management of timer 1 */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 2 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of timer 2 */ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates Timer 2 interrupt management: */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /******************************************************/ + /* Selects the command and status register of timer 3 */ + /******************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes IP and IUS */ + outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Selects the command and status register of Timer 3 */ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates interrupt management of timer 3: */ + outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deletes all interrupts */ + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + //reset all the digital outputs + outw(0x0, devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP); +/*******************************/ +/* Disable the board interrupt */ +/*******************************/ + /*************************************************/ + /* Selects the master interrupt control register */ + /*************************************************/ + outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /*****************************************************/ + /* Selects the command and status register of port A */ + /*****************************************************/ + outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ + outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/*****************************************************/ + /* Selects the command and status register of port B */ + /*****************************************************/ + outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ + outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/*****************************************************/ + /* Selects the command and status register of timer 1 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ + outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/*****************************************************/ + /* Selects the command and status register of timer 2 */ + /*****************************************************/ + outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ + outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/*****************************************************/ +/* Selects the command and status register of timer 3*/ +/*****************************************************/ + outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, + devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); +/****************************/ +/* Deactivates all interrupts */ +/******************************/ + outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h new file mode 100644 index 000000000000..5d960b40a6a8 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/********* Definitions for APCI-1500 card *****/ + +// Card Specific information +#define APCI1500_BOARD_VENDOR_ID 0x10e8 +#define APCI1500_ADDRESS_RANGE 4 + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI1500_DIGITAL_OP 2 +#define APCI1500_DIGITAL_IP 0 +#define APCI1500_AND 2 +#define APCI1500_OR 4 +#define APCI1500_OR_PRIORITY 6 +#define APCI1500_CLK_SELECT 0 +#define COUNTER1 0 +#define COUNTER2 1 +#define COUNTER3 2 +#define APCI1500_COUNTER 0x20 +#define APCI1500_TIMER 0 +#define APCI1500_WATCHDOG 0 +#define APCI1500_SINGLE 0 +#define APCI1500_CONTINUOUS 0x80 +#define APCI1500_DISABLE 0 +#define APCI1500_ENABLE 1 +#define APCI1500_SOFTWARE_TRIGGER 0x4 +#define APCI1500_HARDWARE_TRIGGER 0x10 +#define APCI1500_SOFTWARE_GATE 0 +#define APCI1500_HARDWARE_GATE 0x8 +#define START 0 +#define STOP 1 +#define TRIGGER 2 + +/* + * Zillog I/O enumeration + */ +enum { + APCI1500_Z8536_PORT_C, + APCI1500_Z8536_PORT_B, + APCI1500_Z8536_PORT_A, + APCI1500_Z8536_CONTROL_REGISTER +}; + +/* + * Z8536 CIO Internal Address + */ +enum { + APCI1500_RW_MASTER_INTERRUPT_CONTROL, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL, + APCI1500_RW_PORT_A_INTERRUPT_CONTROL, + APCI1500_RW_PORT_B_INTERRUPT_CONTROL, + APCI1500_RW_TIMER_COUNTER_INTERRUPT_VECTOR, + APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, + APCI1500_RW_PORT_C_DATA_DIRECTION, + APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, + + APCI1500_RW_PORT_A_COMMAND_AND_STATUS, + APCI1500_RW_PORT_B_COMMAND_AND_STATUS, + APCI1500_RW_CPT_TMR1_CMD_STATUS, + APCI1500_RW_CPT_TMR2_CMD_STATUS, + APCI1500_RW_CPT_TMR3_CMD_STATUS, + APCI1500_RW_PORT_A_DATA, + APCI1500_RW_PORT_B_DATA, + APCI1500_RW_PORT_C_DATA, + + APCI1500_R_CPT_TMR1_VALUE_HIGH, + APCI1500_R_CPT_TMR1_VALUE_LOW, + APCI1500_R_CPT_TMR2_VALUE_HIGH, + APCI1500_R_CPT_TMR2_VALUE_LOW, + APCI1500_R_CPT_TMR3_VALUE_HIGH, + APCI1500_R_CPT_TMR3_VALUE_LOW, + APCI1500_RW_CPT_TMR1_TIME_CST_HIGH, + APCI1500_RW_CPT_TMR1_TIME_CST_LOW, + APCI1500_RW_CPT_TMR2_TIME_CST_HIGH, + APCI1500_RW_CPT_TMR2_TIME_CST_LOW, + APCI1500_RW_CPT_TMR3_TIME_CST_HIGH, + APCI1500_RW_CPT_TMR3_TIME_CST_LOW, + APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION, + APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION, + APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION, + APCI1500_R_CURRENT_VECTOR, + + APCI1500_RW_PORT_A_SPECIFICATION, + APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, + APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, + APCI1500_RW_PORT_A_DATA_DIRECTION, + APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL, + APCI1500_RW_PORT_A_PATTERN_POLARITY, + APCI1500_RW_PORT_A_PATTERN_TRANSITION, + APCI1500_RW_PORT_A_PATTERN_MASK, + + APCI1500_RW_PORT_B_SPECIFICATION, + APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, + APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, + APCI1500_RW_PORT_B_DATA_DIRECTION, + APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL, + APCI1500_RW_PORT_B_PATTERN_POLARITY, + APCI1500_RW_PORT_B_PATTERN_TRANSITION, + APCI1500_RW_PORT_B_PATTERN_MASK +}; + + /*----------DIGITAL INPUT----------------*/ +static int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); + +static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +/*---------- DIGITAL OUTPUT------------*/ +static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); +static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +/*----------TIMER----------------*/ +static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); +static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); +static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); +static int i_APCI1500_ReadInterruptMask(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +/*----------INTERRUPT HANDLER------*/ +static void v_APCI1500_Interrupt(int irq, void *d); +static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +/*----------RESET---------------*/ +static int i_APCI1500_Reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c new file mode 100644 index 000000000000..5ae9a93844e7 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c @@ -0,0 +1,542 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-1516 | Compiler : GCC | + | Module name : hwdrv_apci1516.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-1516 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci1516.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_Read1DigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1516_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_TmpValue = 0; + UINT ui_Channel; + ui_Channel = CR_CHAN(insn->chanspec); + if (ui_Channel >= 0 && ui_Channel <= 7) { + ui_TmpValue = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP); + // since only 1 channel reqd to bring it to last bit it is rotated + // 8 +(chan - 1) times then ANDed with 1 for last bit. + *data = (ui_TmpValue >> ui_Channel) & 0x1; + } //if(ui_Channel >= 0 && ui_Channel <=7) + else { + //comedi_error(dev," \n chan spec wrong\n"); + return -EINVAL; // "sorry channel spec wrong " + } //else if(ui_Channel >= 0 && ui_Channel <=7) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ReadMoreDigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + UINT ui_PortValue = data[0]; + UINT ui_Mask = 0; + UINT ui_NoOfChannels; + + ui_NoOfChannels = CR_CHAN(insn->chanspec); + + *data = (UINT) inw(devpriv->iobase + APCI1516_DIGITAL_IP); + switch (ui_NoOfChannels) { + case 2: + ui_Mask = 3; + *data = (*data >> (2 * ui_PortValue)) & ui_Mask; + break; + case 4: + ui_Mask = 15; + *data = (*data >> (4 * ui_PortValue)) & ui_Mask; + break; + case 7: + break; + + default: + printk("\nWrong parameters\n"); + return -EINVAL; // "sorry channel spec wrong " + break; + } //switch(ui_NoOfChannels) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ConfigDigitalOutput (struct comedi_device *dev, + struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| data[0] :1:Memory on | +| 0:Memory off | +| | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI1516_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + devpriv->b_OutputMemoryStatus = data[0]; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_WriteDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1516_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp, ui_Temp1; + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + + printk("EL311003 : @=%x\n", devpriv->iobase + APCI1516_DIGITAL_OP); + + if (devpriv->b_OutputMemoryStatus) { + ui_Temp = inw(devpriv->iobase + APCI1516_DIGITAL_OP); + + } //if(devpriv->b_OutputMemoryStatus ) + else { + ui_Temp = 0; + } //if(devpriv->b_OutputMemoryStatus ) + if (data[3] == 0) { + if (data[1] == 0) { + data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; + outw(data[0], devpriv->iobase + APCI1516_DIGITAL_OP); + + printk("EL311003 : d=%d @=%x\n", data[0], + devpriv->iobase + APCI1516_DIGITAL_OP); + + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = + (data[0] << (2 * + data[2])) | ui_Temp; + break; + + case 4: + data[0] = + (data[0] << (4 * + data[2])) | ui_Temp; + break; + + case 7: + data[0] = data[0] | ui_Temp; + break; + + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + + outw(data[0], + devpriv->iobase + APCI1516_DIGITAL_OP); + + printk("EL311003 : d=%d @=%x\n", data[0], + devpriv->iobase + APCI1516_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==0) + else { + if (data[3] == 1) { + if (data[1] == 0) { + data[0] = ~data[0] & 0x1; + ui_Temp1 = 1; + ui_Temp1 = ui_Temp1 << ui_NoOfChannel; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = (data[0] << ui_NoOfChannel) ^ 0xff; + data[0] = data[0] & ui_Temp; + outw(data[0], + devpriv->iobase + APCI1516_DIGITAL_OP); + + printk("EL311003 : d=%d @=%x\n", data[0], + devpriv->iobase + APCI1516_DIGITAL_OP); + + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = ~data[0] & 0x3; + ui_Temp1 = 3; + ui_Temp1 = + ui_Temp1 << 2 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (2 * + data + [2])) ^ + 0xff) & ui_Temp; + break; + + case 4: + data[0] = ~data[0] & 0xf; + ui_Temp1 = 15; + ui_Temp1 = + ui_Temp1 << 4 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (4 * + data + [2])) ^ + 0xff) & ui_Temp; + break; + + case 7: + break; + + default: + comedi_error(dev, + " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + + outw(data[0], + devpriv->iobase + + APCI1516_DIGITAL_OP); + + printk("EL311003 : d=%d @=%x\n", + data[0], + devpriv->iobase + + APCI1516_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==1); + else { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } //if else data[3]==1) + } //if else data[3]==0) + return (insn->n);; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ReadDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1516_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + UINT ui_Temp; + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + ui_Temp = data[0]; + *data = inw(devpriv->iobase + APCI1516_DIGITAL_OP_RW); + if (ui_Temp == 0) { + *data = (*data >> ui_NoOfChannel) & 0x1; + } //if(ui_Temp==0) + else { + if (ui_Temp == 1) { + switch (ui_NoOfChannel) { + + case 2: + *data = (*data >> (2 * data[1])) & 3; + break; + + case 4: + *data = (*data >> (4 * data[1])) & 15; + break; + + case 7: + break; + + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + } //if(ui_Temp==1) + else { + printk("\nSpecified channel not supported \n"); + } //elseif(ui_Temp==1) + } //elseif(ui_Temp==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1516_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (data[0] == 0) { + //Disable the watchdog + outw(0x0, + devpriv->i_IobaseAddon + + APCI1516_WATCHDOG_ENABLEDISABLE); + //Loading the Reload value + outw(data[1], + devpriv->i_IobaseAddon + + APCI1516_WATCHDOG_RELOAD_VALUE); + data[1] = data[1] >> 16; + outw(data[1], + devpriv->i_IobaseAddon + + APCI1516_WATCHDOG_RELOAD_VALUE + 2); + } //if(data[0]==0) + else { + printk("\nThe input parameters are wrong\n"); + return -EINVAL; + } //elseif(data[0]==0) + + return insn->n; +} + + /* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI1516_StartStopWriteWatchdog | + | (struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data); | + +----------------------------------------------------------------------------+ + | Task : Start / Stop The Watchdog | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | + | unsigned int *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ + */ + +int i_APCI1516_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + switch (data[0]) { + case 0: //stop the watchdog + outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE); //disable the watchdog + break; + case 1: //start the watchdog + outw(0x0001, + devpriv->i_IobaseAddon + + APCI1516_WATCHDOG_ENABLEDISABLE); + break; + case 2: //Software trigger + outw(0x0201, + devpriv->i_IobaseAddon + + APCI1516_WATCHDOG_ENABLEDISABLE); + break; + default: + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } // switch(data[0]) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_ReadWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data); | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1516_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = inw(devpriv->i_IobaseAddon + APCI1516_WATCHDOG_STATUS) & 0x1; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1516_Reset(struct comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1516_Reset(struct comedi_device * dev) +{ + outw(0x0, devpriv->iobase + APCI1516_DIGITAL_OP); //RESETS THE DIGITAL OUTPUTS + outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_ENABLEDISABLE); + outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE); + outw(0x0, devpriv->i_IobaseAddon + APCI1516_WATCHDOG_RELOAD_VALUE + 2); + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h new file mode 100644 index 000000000000..398baa04a163 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/********* Definitions for APCI-1516 card *****/ + +// Card Specific information +#define APCI1516_BOARD_VENDOR_ID 0x15B8 +#define APCI1516_ADDRESS_RANGE 8 + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI1516_DIGITAL_OP 4 +#define APCI1516_DIGITAL_OP_RW 4 +#define APCI1516_DIGITAL_IP 0 + +// TIMER COUNTER WATCHDOG DEFINES + +#define ADDIDATA_WATCHDOG 2 +#define APCI1516_DIGITAL_OP_WATCHDOG 0 +#define APCI1516_WATCHDOG_ENABLEDISABLE 12 +#define APCI1516_WATCHDOG_RELOAD_VALUE 4 +#define APCI1516_WATCHDOG_STATUS 16 + +// Hardware Layer functions for Apci1516 + +//Digital Input +INT i_APCI1516_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI1516_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//Digital Output +int i_APCI1516_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI1516_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI1516_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// TIMER +// timer value is passed as u seconds +int i_APCI1516_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI1516_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI1516_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//reset +INT i_APCI1516_Reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c new file mode 100644 index 000000000000..a6b504c3d391 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c @@ -0,0 +1,1105 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-1564 | Compiler : GCC | + | Module name : hwdrv_apci1564.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-1564 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include +#include "hwdrv_apci1564.h" + +//Global variables +UINT ui_InterruptStatus_1564 = 0; +UINT ui_InterruptData, ui_Type; + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ConfigDigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures the digital input Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 1 Enable Digital Input Interrupt | +| 0 Disable Digital Input Interrupt | +| data[1] : 0 ADDIDATA Interrupt OR LOGIC | +| : 1 ADDIDATA Interrupt AND LOGIC | +| data[2] : Interrupt mask for the mode 1 | +| data[3] : Interrupt mask for the mode 2 | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ConfigDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + devpriv->tsk_Current = current; + /*******************************/ + /* Set the digital input logic */ + /*******************************/ + if (data[0] == ADDIDATA_ENABLE) { + data[2] = data[2] << 4; + data[3] = data[3] << 4; + outl(data[2], + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); + outl(data[3], + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_INTERRUPT_MODE2); + if (data[1] == ADDIDATA_OR) { + outl(0x4, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_IRQ); + } // if (data[1] == ADDIDATA_OR) + else { + outl(0x6, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_IRQ); + } // else if (data[1] == ADDIDATA_OR) + } // if (data[0] == ADDIDATA_ENABLE) + else { + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_INTERRUPT_MODE2); + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_IRQ); + } // else if (data[0] == ADDIDATA_ENABLE) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_Read1DigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_Channel : Channel number to read | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_TmpValue = 0; + UINT ui_Channel; + + ui_Channel = CR_CHAN(insn->chanspec); + if (ui_Channel >= 0 && ui_Channel <= 31) { + ui_TmpValue = + (UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP); + // since only 1 channel reqd to bring it to last bit it is rotated + // 8 +(chan - 1) times then ANDed with 1 for last bit. + *data = (ui_TmpValue >> ui_Channel) & 0x1; + } // if (ui_Channel >= 0 && ui_Channel <=31) + else { + comedi_error(dev, "Not a valid channel number !!! \n"); + return -EINVAL; // "sorry channel spec wrong " + } //else if (ui_Channel >= 0 && ui_Channel <=31) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ReadMoreDigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To be Read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_PortValue = data[0]; + UINT ui_Mask = 0; + UINT ui_NoOfChannels; + + ui_NoOfChannels = CR_CHAN(insn->chanspec); + if (data[1] == 0) { + *data = (UINT) inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP); + switch (ui_NoOfChannels) { + case 2: + ui_Mask = 3; + *data = (*data >> (2 * ui_PortValue)) & ui_Mask; + break; + case 4: + ui_Mask = 15; + *data = (*data >> (4 * ui_PortValue)) & ui_Mask; + break; + case 8: + ui_Mask = 255; + *data = (*data >> (8 * ui_PortValue)) & ui_Mask; + break; + case 16: + ui_Mask = 65535; + *data = (*data >> (16 * ui_PortValue)) & ui_Mask; + break; + case 31: + break; + default: + comedi_error(dev, "Not a valid Channel number !!!\n"); + return -EINVAL; // "sorry channel spec wrong " + break; + } // switch (ui_NoOfChannels) + } // if (data[1]==0) + else { + if (data[1] == 1) { + *data = ui_InterruptStatus_1564; + } // if (data[1]==1) + } // else if (data[1]==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ConfigDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[1] : 1 Enable VCC Interrupt | +| 0 Disable VCC Interrupt | +| data[2] : 1 Enable CC Interrupt | +| 0 Disable CC Interrupt | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + ULONG ul_Command = 0; + + if ((data[0] != 0) && (data[0] != 1)) { + comedi_error(dev, + "Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } // if ((data[0]!=0) && (data[0]!=1)) + if (data[0]) { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; + } // if (data[0]) + else { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + } // else if (data[0]) + if (data[1] == ADDIDATA_ENABLE) { + ul_Command = ul_Command | 0x1; + } // if (data[1] == ADDIDATA_ENABLE) + else { + ul_Command = ul_Command & 0xFFFFFFFE; + } // else if (data[1] == ADDIDATA_ENABLE) + if (data[2] == ADDIDATA_ENABLE) { + ul_Command = ul_Command | 0x2; + } // if (data[2] == ADDIDATA_ENABLE) + else { + ul_Command = ul_Command & 0xFFFFFFFD; + } // else if (data[2] == ADDIDATA_ENABLE) + outl(ul_Command, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_INTERRUPT); + ui_InterruptData = + inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_INTERRUPT); + devpriv->tsk_Current = current; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_WriteDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To Write | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp, ui_Temp1; + UINT ui_NoOfChannel; + + ui_NoOfChannel = CR_CHAN(insn->chanspec); + if (devpriv->b_OutputMemoryStatus) { + ui_Temp = + inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_RW); + } // if (devpriv->b_OutputMemoryStatus ) + else { + ui_Temp = 0; + } // else if (devpriv->b_OutputMemoryStatus ) + if (data[3] == 0) { + if (data[1] == 0) { + data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; + outl(data[0], + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_RW); + } // if (data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + case 2: + data[0] = + (data[0] << (2 * + data[2])) | ui_Temp; + break; + case 4: + data[0] = + (data[0] << (4 * + data[2])) | ui_Temp; + break; + case 8: + data[0] = + (data[0] << (8 * + data[2])) | ui_Temp; + break; + case 16: + data[0] = + (data[0] << (16 * + data[2])) | ui_Temp; + break; + case 31: + data[0] = data[0] | ui_Temp; + break; + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + } // switch (ui_NoOfChannels) + outl(data[0], + devpriv->i_IobaseAmcc + + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_RW); + } // if (data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } // else if (data[1]==1) + } // else if (data[1]==0) + } //if(data[3]==0) + else { + if (data[3] == 1) { + if (data[1] == 0) { + data[0] = ~data[0] & 0x1; + ui_Temp1 = 1; + ui_Temp1 = ui_Temp1 << ui_NoOfChannel; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + (data[0] << ui_NoOfChannel) ^ + 0xffffffff; + data[0] = data[0] & ui_Temp; + outl(data[0], + devpriv->i_IobaseAmcc + + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_RW); + } // if (data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + case 2: + data[0] = ~data[0] & 0x3; + ui_Temp1 = 3; + ui_Temp1 = + ui_Temp1 << 2 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (2 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + case 4: + data[0] = ~data[0] & 0xf; + ui_Temp1 = 15; + ui_Temp1 = + ui_Temp1 << 4 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (4 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + case 8: + data[0] = ~data[0] & 0xff; + ui_Temp1 = 255; + ui_Temp1 = + ui_Temp1 << 8 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (8 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + case 16: + data[0] = ~data[0] & 0xffff; + ui_Temp1 = 65535; + ui_Temp1 = + ui_Temp1 << 16 * + data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (16 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + case 31: + break; + default: + comedi_error(dev, + " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + } //switch(ui_NoOfChannels) + outl(data[0], + devpriv->i_IobaseAmcc + + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_RW); + } // if (data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } // else if (data[1]==1) + } // else if (data[1]==0) + } // if (data[3]==1); + else { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } // else if (data[3]==1) + } // else if (data[3]==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ReadDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + + ui_NoOfChannel = CR_CHAN(insn->chanspec); + ui_Temp = data[0]; + *data = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_RW); + if (ui_Temp == 0) { + *data = (*data >> ui_NoOfChannel) & 0x1; + } // if (ui_Temp==0) + else { + if (ui_Temp == 1) { + switch (ui_NoOfChannel) { + case 2: + *data = (*data >> (2 * data[1])) & 3; + break; + + case 4: + *data = (*data >> (4 * data[1])) & 15; + break; + + case 8: + *data = (*data >> (8 * data[1])) & 255; + break; + + case 16: + *data = (*data >> (16 * data[1])) & 65535; + break; + + case 31: + break; + + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + break; + } // switch(ui_NoOfChannels) + } // if (ui_Temp==1) + else { + printk("\nSpecified channel not supported \n"); + } // else if (ui_Temp==1) + } // else if (ui_Temp==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ConfigTimerCounterWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Configure As Timer | +| 1 Configure As Counter | +| 2 Configure As Watchdog | +| data[1] : 1 Enable Interrupt | +| 0 Disable Interrupt | +| data[2] : Time Unit | +| data[3] : Reload Value | +| data[4] : Timer Mode | +| data[5] : Timer Counter Watchdog Number| + data[6] : Counter Direction ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + ULONG ul_Command1 = 0; + devpriv->tsk_Current = current; + if (data[0] == ADDIDATA_WATCHDOG) { + devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG; + + //Disable the watchdog + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + + APCI1564_TCW_PROG); + //Loading the Reload value + outl(data[3], + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + + APCI1564_TCW_RELOAD_VALUE); + } // if (data[0]==ADDIDATA_WATCHDOG) + else if (data[0] == ADDIDATA_TIMER) { + //First Stop The Timer + ul_Command1 = + inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_PROG); + ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //Stop The Timer + + devpriv->b_TimerSelectMode = ADDIDATA_TIMER; + if (data[1] == 1) { + outl(0x02, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_IRQ); + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_IRQ); + outl(0x0, + devpriv->i_IobaseAmcc + + APCI1564_DIGITAL_OP_WATCHDOG + + APCI1564_TCW_IRQ); + outl(0x0, + devpriv->iobase + APCI1564_COUNTER1 + + APCI1564_TCW_IRQ); + outl(0x0, + devpriv->iobase + APCI1564_COUNTER2 + + APCI1564_TCW_IRQ); + outl(0x0, + devpriv->iobase + APCI1564_COUNTER3 + + APCI1564_TCW_IRQ); + outl(0x0, + devpriv->iobase + APCI1564_COUNTER4 + + APCI1564_TCW_IRQ); + } // if (data[1]==1) + else { + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //disable Timer interrupt + } // else if (data[1]==1) + + // Loading Timebase + + outl(data[2], + devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_TIMEBASE); + + //Loading the Reload value + outl(data[3], + devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_RELOAD_VALUE); + + ul_Command1 = + inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_PROG); + ul_Command1 = + (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL; + outl(ul_Command1, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); //mode 2 + } // else if (data[0]==ADDIDATA_TIMER) + else if (data[0] == ADDIDATA_COUNTER) { + devpriv->b_TimerSelectMode = ADDIDATA_COUNTER; + devpriv->b_ModeSelectRegister = data[5]; + + //First Stop The Counter + ul_Command1 = + inl(devpriv->iobase + ((data[5] - 1) * 0x20) + + APCI1564_TCW_PROG); + ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1, devpriv->iobase + ((data[5] - 1) * 0x20) + APCI1564_TCW_PROG); //Stop The Timer + + /************************/ + /* Set the reload value */ + /************************/ + outl(data[3], + devpriv->iobase + ((data[5] - 1) * 0x20) + + APCI1564_TCW_RELOAD_VALUE); + + /******************************/ + /* Set the mode : */ + /* - Disable the hardware */ + /* - Disable the counter mode */ + /* - Disable the warning */ + /* - Disable the reset */ + /* - Disable the timer mode */ + /* - Enable the counter mode */ + /******************************/ + ul_Command1 = + (ul_Command1 & 0xFFFC19E2UL) | 0x80000UL | + (ULONG) ((ULONG) data[4] << 16UL); + outl(ul_Command1, + devpriv->iobase + ((data[5] - 1) * 0x20) + + APCI1564_TCW_PROG); + + // Enable or Disable Interrupt + ul_Command1 = (ul_Command1 & 0xFFFFF9FD) | (data[1] << 1); + outl(ul_Command1, + devpriv->iobase + ((data[5] - 1) * 0x20) + + APCI1564_TCW_PROG); + + /*****************************/ + /* Set the Up/Down selection */ + /*****************************/ + ul_Command1 = (ul_Command1 & 0xFFFBF9FFUL) | (data[6] << 18); + outl(ul_Command1, + devpriv->iobase + ((data[5] - 1) * 0x20) + + APCI1564_TCW_PROG); + } // else if (data[0]==ADDIDATA_COUNTER) + else { + printk(" Invalid subdevice."); + } // else if (data[0]==ADDIDATA_WATCHDOG) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_StartStopWriteTimerCounterWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Timer | +| 1 Counter | +| 2 Watchdog | | data[1] : 1 Start | +| 0 Stop | +| 2 Trigger | +| Clear (Only Counter) | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + ULONG ul_Command1 = 0; + if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { + switch (data[1]) { + case 0: //stop the watchdog + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + APCI1564_TCW_PROG); //disable the watchdog + break; + case 1: //start the watchdog + outl(0x0001, + devpriv->i_IobaseAmcc + + APCI1564_DIGITAL_OP_WATCHDOG + + APCI1564_TCW_PROG); + break; + case 2: //Software trigger + outl(0x0201, + devpriv->i_IobaseAmcc + + APCI1564_DIGITAL_OP_WATCHDOG + + APCI1564_TCW_PROG); + break; + default: + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } // switch (data[1]) + } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { + if (data[1] == 1) { + ul_Command1 = + inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_PROG); + ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; + + //Enable the Timer + outl(ul_Command1, + devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_PROG); + } // if (data[1]==1) + else if (data[1] == 0) { + //Stop The Timer + + ul_Command1 = + inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_PROG); + ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1, + devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_PROG); + } // else if(data[1]==0) + } // if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { + ul_Command1 = + inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister - + 1) * 0x20) + APCI1564_TCW_PROG); + if (data[1] == 1) { + //Start the Counter subdevice + ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; + } // if (data[1] == 1) + else if (data[1] == 0) { + // Stops the Counter subdevice + ul_Command1 = 0; + + } // else if (data[1] == 0) + else if (data[1] == 2) { + // Clears the Counter subdevice + ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x400; + } // else if (data[1] == 3) + outl(ul_Command1, + devpriv->iobase + ((devpriv->b_ModeSelectRegister - + 1) * 0x20) + APCI1564_TCW_PROG); + } // if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ReadTimerCounterWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | + ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + ULONG ul_Command1 = 0; + + if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { + // Stores the status of the Watchdog + data[0] = + inl(devpriv->i_IobaseAmcc + + APCI1564_DIGITAL_OP_WATCHDOG + + APCI1564_TCW_TRIG_STATUS) & 0x1; + data[1] = + inl(devpriv->i_IobaseAmcc + + APCI1564_DIGITAL_OP_WATCHDOG); + } // if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { + // Stores the status of the Timer + data[0] = + inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_TRIG_STATUS) & 0x1; + + // Stores the Actual value of the Timer + data[1] = inl(devpriv->i_IobaseAmcc + APCI1564_TIMER); + } // else if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + else if (devpriv->b_TimerSelectMode == ADDIDATA_COUNTER) { + // Read the Counter Actual Value. + data[0] = + inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister - + 1) * 0x20) + + APCI1564_TCW_SYNC_ENABLEDISABLE); + ul_Command1 = + inl(devpriv->iobase + ((devpriv->b_ModeSelectRegister - + 1) * 0x20) + APCI1564_TCW_TRIG_STATUS); + + /***********************************/ + /* Get the software trigger status */ + /***********************************/ + data[1] = (BYTE) ((ul_Command1 >> 1) & 1); + + /***********************************/ + /* Get the hardware trigger status */ + /***********************************/ + data[2] = (BYTE) ((ul_Command1 >> 2) & 1); + + /*********************************/ + /* Get the software clear status */ + /*********************************/ + data[3] = (BYTE) ((ul_Command1 >> 3) & 1); + + /***************************/ + /* Get the overflow status */ + /***************************/ + data[4] = (BYTE) ((ul_Command1 >> 0) & 1); + } // else if (devpriv->b_TimerSelectMode==ADDIDATA_COUNTER) + else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER) + && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG) + && (devpriv->b_TimerSelectMode != ADDIDATA_COUNTER)) { + printk("\n Invalid Subdevice !!!\n"); + } // else if ((devpriv->b_TimerSelectMode!=ADDIDATA_TIMER) && (devpriv->b_TimerSelectMode!=ADDIDATA_WATCHDOG)&& (devpriv->b_TimerSelectMode!=ADDIDATA_COUNTER)) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_ReadInterruptStatus | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task :Reads the interrupt status register | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI1564_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + *data = ui_Type; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI1564_Interrupt | +| (int irq , void *d) | ++----------------------------------------------------------------------------+ +| Task : Interrupt handler for the interruptible digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +static void v_APCI1564_Interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + UINT ui_DO, ui_DI; + UINT ui_Timer; + UINT ui_C1, ui_C2, ui_C3, ui_C4; + ULONG ul_Command2 = 0; + ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_IRQ) & 0x01; + ui_DO = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_IRQ) & 0x01; + ui_Timer = + inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_IRQ) & 0x01; + ui_C1 = inl(devpriv->iobase + APCI1564_COUNTER1 + + APCI1564_TCW_IRQ) & 0x1; + ui_C2 = inl(devpriv->iobase + APCI1564_COUNTER2 + + APCI1564_TCW_IRQ) & 0x1; + ui_C3 = inl(devpriv->iobase + APCI1564_COUNTER3 + + APCI1564_TCW_IRQ) & 0x1; + ui_C4 = inl(devpriv->iobase + APCI1564_COUNTER4 + + APCI1564_TCW_IRQ) & 0x1; + if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0 + && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) { + printk("\nInterrupt from unknown source\n"); + } // if(ui_DI==0 && ui_DO==0 && ui_Timer==0 && ui_C1==0 && ui_C2==0 && ui_C3==0 && ui_C4==0) + + if (ui_DI == 1) { + ui_DI = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_IRQ); + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_IRQ); + ui_InterruptStatus_1564 = + inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + + APCI1564_DIGITAL_IP_INTERRUPT_STATUS); + ui_InterruptStatus_1564 = ui_InterruptStatus_1564 & 0X000FFFF0; + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + outl(ui_DI, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP + APCI1564_DIGITAL_IP_IRQ); //enable the interrupt + return; + } + + if (ui_DO == 1) { + // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. + ui_Type = + inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_INTERRUPT_STATUS) & 0x3; + //Disable the Interrupt + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + + APCI1564_DIGITAL_OP_INTERRUPT); + + //Sends signal to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + + } // if (ui_DO) + + if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_TIMER)) { + // Disable Timer Interrupt + ul_Command2 = + inl(devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_PROG); + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + + // Enable Timer Interrupt + + outl(ul_Command2, + devpriv->i_IobaseAmcc + APCI1564_TIMER + + APCI1564_TCW_PROG); + } // if ((ui_Timer == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_TIMER)) + + if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) { + // Disable Counter Interrupt + ul_Command2 = + inl(devpriv->iobase + APCI1564_COUNTER1 + + APCI1564_TCW_PROG); + outl(0x0, + devpriv->iobase + APCI1564_COUNTER1 + + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + + // Enable Counter Interrupt + outl(ul_Command2, + devpriv->iobase + APCI1564_COUNTER1 + + APCI1564_TCW_PROG); + } // if ((ui_C1 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) + + if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) { + // Disable Counter Interrupt + ul_Command2 = + inl(devpriv->iobase + APCI1564_COUNTER2 + + APCI1564_TCW_PROG); + outl(0x0, + devpriv->iobase + APCI1564_COUNTER2 + + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + + // Enable Counter Interrupt + outl(ul_Command2, + devpriv->iobase + APCI1564_COUNTER2 + + APCI1564_TCW_PROG); + } // if ((ui_C2 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) + + if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) { + // Disable Counter Interrupt + ul_Command2 = + inl(devpriv->iobase + APCI1564_COUNTER3 + + APCI1564_TCW_PROG); + outl(0x0, + devpriv->iobase + APCI1564_COUNTER3 + + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + + // Enable Counter Interrupt + outl(ul_Command2, + devpriv->iobase + APCI1564_COUNTER3 + + APCI1564_TCW_PROG); + } // if ((ui_C3 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) + + if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode = ADDIDATA_COUNTER)) { + // Disable Counter Interrupt + ul_Command2 = + inl(devpriv->iobase + APCI1564_COUNTER4 + + APCI1564_TCW_PROG); + outl(0x0, + devpriv->iobase + APCI1564_COUNTER4 + + APCI1564_TCW_PROG); + + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + + // Enable Counter Interrupt + outl(ul_Command2, + devpriv->iobase + APCI1564_COUNTER4 + + APCI1564_TCW_PROG); + } // if ((ui_C4 == 1) && (devpriv->b_TimerSelectMode =ADDIDATA_COUNTER)) + return; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI1564_Reset(struct comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI1564_Reset(struct comedi_device * dev) +{ + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_IRQ); //disable the interrupts + inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_STATUS); //Reset the interrupt status register + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE1); //Disable the and/or interrupt + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_IP_INTERRUPT_MODE2); + devpriv->b_DigitalOutputRegister = 0; + ui_Type = 0; + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP); //Resets the output channels + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_INTERRUPT); //Disables the interrupt. + outl(0x0, + devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP_WATCHDOG + + APCI1564_TCW_RELOAD_VALUE); + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER); + outl(0x0, devpriv->i_IobaseAmcc + APCI1564_TIMER + APCI1564_TCW_PROG); + + outl(0x0, devpriv->iobase + APCI1564_COUNTER1 + APCI1564_TCW_PROG); + outl(0x0, devpriv->iobase + APCI1564_COUNTER2 + APCI1564_TCW_PROG); + outl(0x0, devpriv->iobase + APCI1564_COUNTER3 + APCI1564_TCW_PROG); + outl(0x0, devpriv->iobase + APCI1564_COUNTER4 + APCI1564_TCW_PROG); + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h new file mode 100644 index 000000000000..f0c461ca5396 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/********* Definitions for APCI-1564 card *****/ + +#define APCI1564_BOARD_VENDOR_ID 0x15B8 +#define APCI1564_ADDRESS_RANGE 128 + +//DIGITAL INPUT-OUTPUT DEFINE +// Input defines +#define APCI1564_DIGITAL_IP 0x04 +#define APCI1564_DIGITAL_IP_INTERRUPT_MODE1 4 +#define APCI1564_DIGITAL_IP_INTERRUPT_MODE2 8 +#define APCI1564_DIGITAL_IP_IRQ 16 + +// Output defines +#define APCI1564_DIGITAL_OP 0x18 +#define APCI1564_DIGITAL_OP_RW 0 +#define APCI1564_DIGITAL_OP_INTERRUPT 4 +#define APCI1564_DIGITAL_OP_IRQ 12 + +//Digital Input IRQ Function Selection +#define ADDIDATA_OR 0 +#define ADDIDATA_AND 1 + +//Digital Input Interrupt Status +#define APCI1564_DIGITAL_IP_INTERRUPT_STATUS 12 + +//Digital Output Interrupt Status +#define APCI1564_DIGITAL_OP_INTERRUPT_STATUS 8 + +//Digital Input Interrupt Enable Disable. +#define APCI1564_DIGITAL_IP_INTERRUPT_ENABLE 0x4 +#define APCI1564_DIGITAL_IP_INTERRUPT_DISABLE 0xFFFFFFFB + +//Digital Output Interrupt Enable Disable. +#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1 +#define APCI1564_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xFFFFFFFE +#define APCI1564_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2 +#define APCI1564_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xFFFFFFFD + +//ADDIDATA Enable Disable + +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +// TIMER COUNTER WATCHDOG DEFINES + +#define ADDIDATA_TIMER 0 +#define ADDIDATA_COUNTER 1 +#define ADDIDATA_WATCHDOG 2 +#define APCI1564_DIGITAL_OP_WATCHDOG 0x28 +#define APCI1564_TIMER 0x48 +#define APCI1564_COUNTER1 0x0 +#define APCI1564_COUNTER2 0x20 +#define APCI1564_COUNTER3 0x40 +#define APCI1564_COUNTER4 0x60 +#define APCI1564_TCW_SYNC_ENABLEDISABLE 0 +#define APCI1564_TCW_RELOAD_VALUE 4 +#define APCI1564_TCW_TIMEBASE 8 +#define APCI1564_TCW_PROG 12 +#define APCI1564_TCW_TRIG_STATUS 16 +#define APCI1564_TCW_IRQ 20 +#define APCI1564_TCW_WARN_TIMEVAL 24 +#define APCI1564_TCW_WARN_TIMEBASE 28 + +// Hardware Layer functions for Apci1564 + +//DI +// for di read +INT i_APCI1564_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI1564_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI1564_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//DO +int i_APCI1564_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI1564_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI1564_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI1564_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// TIMER +// timer value is passed as u seconds +INT i_APCI1564_ConfigTimerCounterWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI1564_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); +int i_APCI1564_ReadTimerCounterWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// INTERRUPT +static void v_APCI1564_Interrupt(int irq, void *d); + +// RESET +INT i_APCI1564_Reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c new file mode 100644 index 000000000000..906d635da6b2 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c @@ -0,0 +1,780 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : API APCI1648 | Compiler : gcc | + | Module name : TTL.C | Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: S. Weber | Date : 25/05/2005 | + +-----------------------------------------------------------------------+ + | Description : APCI-16XX TTL I/O module | + | | + | | + +-----------------------------------------------------------------------+ + | UPDATES | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + |25.05.2005| S.Weber | Creation | + | | | | + +-----------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "hwdrv_apci16xx.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI16XX_InsnConfigInitTTLIO | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task APCI16XX_TTL_INIT (using defaults) : | +| Configure the TTL I/O operating mode from all ports | +| You must calling this function be | +| for you call any other function witch access of TTL. | +| APCI16XX_TTL_INITDIRECTION(user inputs for direction) | ++----------------------------------------------------------------------------+ +| Input Parameters : b_InitType = (BYTE) data[0]; | +| b_Port0Mode = (BYTE) data[1]; | +| b_Port1Mode = (BYTE) data[2]; | +| b_Port2Mode = (BYTE) data[3]; | +| b_Port3Mode = (BYTE) data[4]; | +| ........ | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value :>0: No error | +| -1: Port 0 mode selection is wrong | +| -2: Port 1 mode selection is wrong | +| -3: Port 2 mode selection is wrong | +| -4: Port 3 mode selection is wrong | +| -X: Port X-1 mode selection is wrong | +| .... | +| -100 : Config command error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_Command = 0; + BYTE b_Cpt = 0; + BYTE b_NumberOfPort = + (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8); + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + /*******************/ + /* Get the command */ + /* **************** */ + + b_Command = (BYTE) data[0]; + + /********************/ + /* Test the command */ + /********************/ + + if ((b_Command == APCI16XX_TTL_INIT) || + (b_Command == APCI16XX_TTL_INITDIRECTION) || + (b_Command == APCI16XX_TTL_OUTPUTMEMORY)) { + /***************************************/ + /* Test the initialisation buffer size */ + /***************************************/ + + if ((b_Command == APCI16XX_TTL_INITDIRECTION) + && ((BYTE) (insn->n - 1) != b_NumberOfPort)) { + /*******************/ + /* Data size error */ + /*******************/ + + printk("\nBuffer size error"); + i_ReturnValue = -101; + } + + if ((b_Command == APCI16XX_TTL_OUTPUTMEMORY) + && ((BYTE) (insn->n) != 2)) { + /*******************/ + /* Data size error */ + /*******************/ + + printk("\nBuffer size error"); + i_ReturnValue = -101; + } + } else { + /************************/ + /* Config command error */ + /************************/ + + printk("\nCommand selection error"); + i_ReturnValue = -100; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("\nBuffer size error"); + i_ReturnValue = -101; + } + + /**************************************************************************/ + /* Test if no error occur and APCI16XX_TTL_INITDIRECTION command selected */ + /**************************************************************************/ + + if ((i_ReturnValue >= 0) && (b_Command == APCI16XX_TTL_INITDIRECTION)) { + memset(devpriv->ul_TTLPortConfiguration, 0, + sizeof(devpriv->ul_TTLPortConfiguration)); + + /*************************************/ + /* Test the port direction selection */ + /*************************************/ + + for (b_Cpt = 1; + (b_Cpt <= b_NumberOfPort) && (i_ReturnValue >= 0); + b_Cpt++) { + /**********************/ + /* Test the direction */ + /**********************/ + + if ((data[b_Cpt] != 0) && (data[b_Cpt] != 0xFF)) { + /************************/ + /* Port direction error */ + /************************/ + + printk("\nPort %d direction selection error", + (INT) b_Cpt); + i_ReturnValue = -(INT) b_Cpt; + } + + /**************************/ + /* Save the configuration */ + /**************************/ + + devpriv->ul_TTLPortConfiguration[(b_Cpt - 1) / 4] = + devpriv->ul_TTLPortConfiguration[(b_Cpt - + 1) / 4] | (data[b_Cpt] << (8 * ((b_Cpt - + 1) % 4))); + } + } + + /**************************/ + /* Test if no error occur */ + /**************************/ + + if (i_ReturnValue >= 0) { + /***********************************/ + /* Test if TTL port initilaisation */ + /***********************************/ + + if ((b_Command == APCI16XX_TTL_INIT) + || (b_Command == APCI16XX_TTL_INITDIRECTION)) { + /******************************/ + /* Set all port configuration */ + /******************************/ + + for (b_Cpt = 0; b_Cpt <= b_NumberOfPort; b_Cpt++) { + if ((b_Cpt % 4) == 0) { + /*************************/ + /* Set the configuration */ + /*************************/ + + outl(devpriv-> + ul_TTLPortConfiguration[b_Cpt / + 4], + devpriv->iobase + 32 + b_Cpt); + } + } + } + } + + /************************************************/ + /* Test if output memory initialisation command */ + /************************************************/ + + if (b_Command == APCI16XX_TTL_OUTPUTMEMORY) { + if (data[1]) { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; + } else { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + } + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| INPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI16XX_InsnBitsReadTTLIO | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read the status from selected TTL digital input | +| (b_InputChannel) | ++----------------------------------------------------------------------------+ +| Task : Read the status from digital input port | +| (b_SelectedPort) | ++----------------------------------------------------------------------------+ +| Input Parameters : | +| APCI16XX_TTL_READCHANNEL | +| b_SelectedPort= CR_RANGE(insn->chanspec); | +| b_InputChannel= CR_CHAN(insn->chanspec); | +| b_ReadType = (BYTE) data[0]; | +| | +| APCI16XX_TTL_READPORT | +| b_SelectedPort= CR_RANGE(insn->chanspec); | +| b_ReadType = (BYTE) data[0]; | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] 0 : Channle is not active | +| 1 : Channle is active | ++----------------------------------------------------------------------------+ +| Return Value : >0 : No error | +| -100 : Config command error | +| -101 : Data size error | +| -102 : The selected TTL input port is wrong | +| -103 : The selected TTL digital input is wrong | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_Command = 0; + BYTE b_NumberOfPort = + (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8); + BYTE b_SelectedPort = CR_RANGE(insn->chanspec); + BYTE b_InputChannel = CR_CHAN(insn->chanspec); + BYTE *pb_Status; + DWORD dw_Status; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + /*******************/ + /* Get the command */ + /* **************** */ + + b_Command = (BYTE) data[0]; + + /********************/ + /* Test the command */ + /********************/ + + if ((b_Command == APCI16XX_TTL_READCHANNEL) + || (b_Command == APCI16XX_TTL_READPORT)) { + /**************************/ + /* Test the selected port */ + /**************************/ + + if (b_SelectedPort < b_NumberOfPort) { + /**********************/ + /* Test if input port */ + /**********************/ + + if (((devpriv->ul_TTLPortConfiguration + [b_SelectedPort / + 4] >> (8 * + (b_SelectedPort + % + 4))) & + 0xFF) == 0) { + /***************************/ + /* Test the channel number */ + /***************************/ + + if ((b_Command == + APCI16XX_TTL_READCHANNEL) + && (b_InputChannel > 7)) { + /*******************************************/ + /* The selected TTL digital input is wrong */ + /*******************************************/ + + printk("\nChannel selection error"); + i_ReturnValue = -103; + } + } else { + /****************************************/ + /* The selected TTL input port is wrong */ + /****************************************/ + + printk("\nPort selection error"); + i_ReturnValue = -102; + } + } else { + /****************************************/ + /* The selected TTL input port is wrong */ + /****************************************/ + + printk("\nPort selection error"); + i_ReturnValue = -102; + } + } else { + /************************/ + /* Config command error */ + /************************/ + + printk("\nCommand selection error"); + i_ReturnValue = -100; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("\nBuffer size error"); + i_ReturnValue = -101; + } + + /**************************/ + /* Test if no error occur */ + /**************************/ + + if (i_ReturnValue >= 0) { + pb_Status = (PBYTE) & data[0]; + + /*******************************/ + /* Get the digital inpu status */ + /*******************************/ + + dw_Status = + inl(devpriv->iobase + 8 + ((b_SelectedPort / 4) * 4)); + dw_Status = (dw_Status >> (8 * (b_SelectedPort % 4))) & 0xFF; + + /***********************/ + /* Save the port value */ + /***********************/ + + *pb_Status = (BYTE) dw_Status; + + /***************************************/ + /* Test if read channel status command */ + /***************************************/ + + if (b_Command == APCI16XX_TTL_READCHANNEL) { + *pb_Status = (*pb_Status >> b_InputChannel) & 1; + } + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI16XX_InsnReadTTLIOAllPortValue | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read the status from all digital input ports | ++----------------------------------------------------------------------------+ +| Input Parameters : - | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] : Port 0 to 3 data | +| data[1] : Port 4 to 7 data | +| .... | ++----------------------------------------------------------------------------+ +| Return Value : 0: No error | +| -100 : Read command error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_Command = (BYTE) CR_AREF(insn->chanspec); + INT i_ReturnValue = insn->n; + BYTE b_Cpt = 0; + BYTE b_NumberOfPort = 0; + unsigned int *pls_ReadData = data; + + /********************/ + /* Test the command */ + /********************/ + + if ((b_Command == APCI16XX_TTL_READ_ALL_INPUTS) + || (b_Command == APCI16XX_TTL_READ_ALL_OUTPUTS)) { + /**********************************/ + /* Get the number of 32-Bit ports */ + /**********************************/ + + b_NumberOfPort = + (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 32); + if ((b_NumberOfPort * 32) < + devpriv->ps_BoardInfo->i_NbrTTLChannel) { + b_NumberOfPort = b_NumberOfPort + 1; + } + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= b_NumberOfPort) { + if (b_Command == APCI16XX_TTL_READ_ALL_INPUTS) { + /**************************/ + /* Read all digital input */ + /**************************/ + + for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) { + /************************/ + /* Read the 32-Bit port */ + /************************/ + + pls_ReadData[b_Cpt] = + inl(devpriv->iobase + 8 + + (b_Cpt * 4)); + + /**************************************/ + /* Mask all channels used als outputs */ + /**************************************/ + + pls_ReadData[b_Cpt] = + pls_ReadData[b_Cpt] & + (~devpriv-> + ul_TTLPortConfiguration[b_Cpt]); + } + } else { + /****************************/ + /* Read all digital outputs */ + /****************************/ + + for (b_Cpt = 0; b_Cpt < b_NumberOfPort; b_Cpt++) { + /************************/ + /* Read the 32-Bit port */ + /************************/ + + pls_ReadData[b_Cpt] = + inl(devpriv->iobase + 20 + + (b_Cpt * 4)); + + /**************************************/ + /* Mask all channels used als outputs */ + /**************************************/ + + pls_ReadData[b_Cpt] = + pls_ReadData[b_Cpt] & devpriv-> + ul_TTLPortConfiguration[b_Cpt]; + } + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("\nBuffer size error"); + i_ReturnValue = -101; + } + } else { + /*****************/ + /* Command error */ + /*****************/ + + printk("\nCommand selection error"); + i_ReturnValue = -100; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| OUTPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI16XX_InsnBitsWriteTTLIO | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Set the state from selected TTL digital output | +| (b_OutputChannel) | ++----------------------------------------------------------------------------+ +| Task : Set the state from digital output port | +| (b_SelectedPort) | ++----------------------------------------------------------------------------+ +| Input Parameters : | +| APCI16XX_TTL_WRITECHANNEL_ON | APCI16XX_TTL_WRITECHANNEL_OFF | +| b_SelectedPort = CR_RANGE(insn->chanspec); | +| b_OutputChannel= CR_CHAN(insn->chanspec); | +| b_Command = (BYTE) data[0]; | +| | +| APCI16XX_TTL_WRITEPORT_ON | APCI16XX_TTL_WRITEPORT_OFF | +| b_SelectedPort = CR_RANGE(insn->chanspec); | +| b_Command = (BYTE) data[0]; | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] : TTL output port 0 to 3 data | +| data[1] : TTL output port 4 to 7 data | +| .... | ++----------------------------------------------------------------------------+ +| Return Value : >0 : No error | +| -100 : Command error | +| -101 : Data size error | +| -102 : The selected TTL output port is wrong | +| -103 : The selected TTL digital output is wrong | +| -104 : Output memory disabled | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_Command = 0; + BYTE b_NumberOfPort = + (BYTE) (devpriv->ps_BoardInfo->i_NbrTTLChannel / 8); + BYTE b_SelectedPort = CR_RANGE(insn->chanspec); + BYTE b_OutputChannel = CR_CHAN(insn->chanspec); + DWORD dw_Status = 0; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + /*******************/ + /* Get the command */ + /* **************** */ + + b_Command = (BYTE) data[0]; + + /********************/ + /* Test the command */ + /********************/ + + if ((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) || + (b_Command == APCI16XX_TTL_WRITEPORT_ON) || + (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) || + (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) { + /**************************/ + /* Test the selected port */ + /**************************/ + + if (b_SelectedPort < b_NumberOfPort) { + /***********************/ + /* Test if output port */ + /***********************/ + + if (((devpriv->ul_TTLPortConfiguration + [b_SelectedPort / + 4] >> (8 * + (b_SelectedPort + % + 4))) & + 0xFF) == 0xFF) { + /***************************/ + /* Test the channel number */ + /***************************/ + + if (((b_Command == APCI16XX_TTL_WRITECHANNEL_ON) || (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF)) && (b_OutputChannel > 7)) { + /********************************************/ + /* The selected TTL digital output is wrong */ + /********************************************/ + + printk("\nChannel selection error"); + i_ReturnValue = -103; + } + + if (((b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE)) { + /********************************************/ + /* The selected TTL digital output is wrong */ + /********************************************/ + + printk("\nOutput memory disabled"); + i_ReturnValue = -104; + } + + /************************/ + /* Test the buffer size */ + /************************/ + + if (((b_Command == APCI16XX_TTL_WRITEPORT_ON) || (b_Command == APCI16XX_TTL_WRITEPORT_OFF)) && (insn->n < 2)) { + /*******************/ + /* Data size error */ + /*******************/ + + printk("\nBuffer size error"); + i_ReturnValue = -101; + } + } else { + /*****************************************/ + /* The selected TTL output port is wrong */ + /*****************************************/ + + printk("\nPort selection error %lX", + (unsigned long)devpriv-> + ul_TTLPortConfiguration[0]); + i_ReturnValue = -102; + } + } else { + /****************************************/ + /* The selected TTL output port is wrong */ + /****************************************/ + + printk("\nPort selection error %d %d", + b_SelectedPort, b_NumberOfPort); + i_ReturnValue = -102; + } + } else { + /************************/ + /* Config command error */ + /************************/ + + printk("\nCommand selection error"); + i_ReturnValue = -100; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("\nBuffer size error"); + i_ReturnValue = -101; + } + + /**************************/ + /* Test if no error occur */ + /**************************/ + + if (i_ReturnValue >= 0) { + /********************************/ + /* Get the digital output state */ + /********************************/ + + dw_Status = + inl(devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4)); + + /**********************************/ + /* Test if output memory not used */ + /**********************************/ + + if (devpriv->b_OutputMemoryStatus == ADDIDATA_DISABLE) { + /*********************************/ + /* Clear the selected port value */ + /*********************************/ + + dw_Status = + dw_Status & (0xFFFFFFFFUL - + (0xFFUL << (8 * (b_SelectedPort % 4)))); + } + + /******************************/ + /* Test if setting channel ON */ + /******************************/ + + if (b_Command == APCI16XX_TTL_WRITECHANNEL_ON) { + dw_Status = + dw_Status | (1UL << ((8 * (b_SelectedPort % + 4)) + b_OutputChannel)); + } + + /***************************/ + /* Test if setting port ON */ + /***************************/ + + if (b_Command == APCI16XX_TTL_WRITEPORT_ON) { + dw_Status = + dw_Status | ((data[1] & 0xFF) << (8 * + (b_SelectedPort % 4))); + } + + /*******************************/ + /* Test if setting channel OFF */ + /*******************************/ + + if (b_Command == APCI16XX_TTL_WRITECHANNEL_OFF) { + dw_Status = + dw_Status & (0xFFFFFFFFUL - + (1UL << ((8 * (b_SelectedPort % 4)) + + b_OutputChannel))); + } + + /****************************/ + /* Test if setting port OFF */ + /****************************/ + + if (b_Command == APCI16XX_TTL_WRITEPORT_OFF) { + dw_Status = + dw_Status & (0xFFFFFFFFUL - + ((data[1] & 0xFF) << (8 * (b_SelectedPort % + 4)))); + } + + outl(dw_Status, + devpriv->iobase + 20 + ((b_SelectedPort / 4) * 4)); + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : - | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI16XX_Reset(struct comedi_device * dev) +{ + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h new file mode 100644 index 000000000000..5bf91e13a035 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#ifndef COMEDI_SUBD_TTLIO +#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */ +#endif + +#ifndef ADDIDATA_ENABLE +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 +#endif + +#define APCI16XX_TTL_INIT 0 +#define APCI16XX_TTL_INITDIRECTION 1 +#define APCI16XX_TTL_OUTPUTMEMORY 2 + +#define APCI16XX_TTL_READCHANNEL 0 +#define APCI16XX_TTL_READPORT 1 + +#define APCI16XX_TTL_WRITECHANNEL_ON 0 +#define APCI16XX_TTL_WRITECHANNEL_OFF 1 +#define APCI16XX_TTL_WRITEPORT_ON 2 +#define APCI16XX_TTL_WRITEPORT_OFF 3 + +#define APCI16XX_TTL_READ_ALL_INPUTS 0 +#define APCI16XX_TTL_READ_ALL_OUTPUTS 1 + +#ifdef __KERNEL__ + +static const struct comedi_lrange range_apci16xx_ttl = { 12, + {BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1)} +}; + +/* ++----------------------------------------------------------------------------+ +| TTL INISIALISATION FUNCTION | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI16XX_InsnConfigInitTTLIO(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data); + +/* ++----------------------------------------------------------------------------+ +| TTL INPUT FUNCTION | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI16XX_InsnBitsReadTTLIO(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data); + +int i_APCI16XX_InsnReadTTLIOAllPortValue(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +/* ++----------------------------------------------------------------------------+ +| TTL OUTPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI16XX_InsnBitsWriteTTLIO(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data); + +int i_APCI16XX_Reset(struct comedi_device *dev); +#endif diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c new file mode 100644 index 000000000000..31f55da39ea8 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c @@ -0,0 +1,460 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-2016 | Compiler : GCC | + | Module name : hwdrv_apci2016.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-2016 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci2016.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_ConfigDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 1 Digital Memory On | +| 0 Digital Memory Off | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if ((data[0] != 0) && (data[0] != 1)) { + comedi_error(dev, + "Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } // if ((data[0]!=0) && (data[0]!=1)) + if (data[0]) { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; + } // if (data[0] + else { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + } // else if (data[0] + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_WriteDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To Write | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_NoOfChannel; + UINT ui_Temp, ui_Temp1; + ui_NoOfChannel = CR_CHAN(insn->chanspec); + if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) { + comedi_error(dev, + "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); + return -EINVAL; + } // if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) + if (devpriv->b_OutputMemoryStatus) { + ui_Temp = inw(devpriv->iobase + APCI2016_DIGITAL_OP); + } // if (devpriv->b_OutputMemoryStatus ) + else { + ui_Temp = 0; + } // else if (devpriv->b_OutputMemoryStatus ) + if ((data[1] != 0) && (data[1] != 1)) { + comedi_error(dev, + "Invalid Data[1] value !!!, Data[1] should be 0 or 1\n"); + return -EINVAL; + } // if ((data[1]!=0) && (data[1]!=1)) + + if (data[3] == 0) { + if (data[1] == 0) { + data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; + outw(data[0], devpriv->iobase + APCI2016_DIGITAL_OP); + } // if (data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + case 2: + data[0] = + (data[0] << (2 * + data[2])) | ui_Temp; + break; + case 4: + data[0] = + (data[0] << (4 * + data[2])) | ui_Temp; + break; + case 8: + data[0] = + (data[0] << (8 * + data[2])) | ui_Temp; + break; + case 15: + data[0] = data[0] | ui_Temp; + break; + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + } //switch(ui_NoOfChannels) + outw(data[0], + devpriv->iobase + APCI2016_DIGITAL_OP); + } // if (data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } // else if (data[1]==1) + } // else if (data[1]==0) + } // if (data[3]==0) + else { + if (data[3] == 1) { + if (data[1] == 0) { + data[0] = ~data[0] & 0x1; + ui_Temp1 = 1; + ui_Temp1 = ui_Temp1 << ui_NoOfChannel; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff; + data[0] = data[0] & ui_Temp; + outw(data[0], + devpriv->iobase + APCI2016_DIGITAL_OP); + } // if (data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + case 2: + data[0] = ~data[0] & 0x3; + ui_Temp1 = 3; + ui_Temp1 = + ui_Temp1 << 2 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (2 * + data + [2])) ^ + 0xffff) & ui_Temp; + break; + case 4: + data[0] = ~data[0] & 0xf; + ui_Temp1 = 15; + ui_Temp1 = + ui_Temp1 << 4 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (4 * + data + [2])) ^ + 0xffff) & ui_Temp; + break; + case 8: + data[0] = ~data[0] & 0xff; + ui_Temp1 = 255; + ui_Temp1 = + ui_Temp1 << 8 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (8 * + data + [2])) ^ + 0xffff) & ui_Temp; + break; + case 15: + break; + default: + comedi_error(dev, + " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + } //switch(ui_NoOfChannels) + outw(data[0], + devpriv->iobase + + APCI2016_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==1); + else { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } //if else data[3]==1) + } //if else data[3]==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_BitsDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_BitsDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + ui_NoOfChannel = CR_CHAN(insn->chanspec); + if ((ui_NoOfChannel < 0) || (ui_NoOfChannel > 15)) { + comedi_error(dev, + "Invalid Channel Numbers !!!, Channel Numbers must be between 0 and 15\n"); + return -EINVAL; + } // if ((ui_NoOfChannel<0) || (ui_NoOfChannel>15)) + if ((data[0] != 0) && (data[0] != 1)) { + comedi_error(dev, + "Invalid Data[0] value !!!, Data[0] should be 0 or 1\n"); + return -EINVAL; + } // if ((data[0]!=0) && (data[0]!=1)) + ui_Temp = data[0]; + *data = inw(devpriv->iobase + APCI2016_DIGITAL_OP_RW); + if (ui_Temp == 0) { + *data = (*data >> ui_NoOfChannel) & 0x1; + } // if (ui_Temp==0) + else { + if (ui_Temp == 1) { + switch (ui_NoOfChannel) { + case 2: + *data = (*data >> (2 * data[1])) & 3; + break; + + case 4: + *data = (*data >> (4 * data[1])) & 15; + break; + + case 8: + *data = (*data >> (8 * data[1])) & 255; + break; + + case 15: + break; + + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + } //switch(ui_NoOfChannel) + } // if (ui_Temp==1) + else { + printk("\nSpecified channel not supported \n"); + } // else if (ui_Temp==1) + } // if (ui_Temp==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_ConfigWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure | +| struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + if (data[0] == 0) { + //Disable the watchdog + outw(0x0, + devpriv->i_IobaseAddon + + APCI2016_WATCHDOG_ENABLEDISABLE); + //Loading the Reload value + outw(data[1], + devpriv->i_IobaseAddon + + APCI2016_WATCHDOG_RELOAD_VALUE); + data[1] = data[1] >> 16; + outw(data[1], + devpriv->i_IobaseAddon + + APCI2016_WATCHDOG_RELOAD_VALUE + 2); + } else { + printk("\nThe input parameters are wrong\n"); + } + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_StartStopWriteWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure | +| struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2016_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + switch (data[0]) { + case 0: //stop the watchdog + outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE); //disable the watchdog + break; + case 1: //start the watchdog + outw(0x0001, + devpriv->i_IobaseAddon + + APCI2016_WATCHDOG_ENABLEDISABLE); + break; + case 2: //Software trigger + outw(0x0201, + devpriv->i_IobaseAddon + + APCI2016_WATCHDOG_ENABLEDISABLE); + break; + default: + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } // switch(data[0]) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_ReadWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure | +| struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2016_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + udelay(5); + data[0] = inw(devpriv->i_IobaseAddon + APCI2016_WATCHDOG_STATUS) & 0x1; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2016_Reset(struct comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2016_Reset(struct comedi_device * dev) +{ + outw(0x0, devpriv->iobase + APCI2016_DIGITAL_OP); // Resets the digital output channels + outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_ENABLEDISABLE); + outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE); + outw(0x0, devpriv->i_IobaseAddon + APCI2016_WATCHDOG_RELOAD_VALUE + 2); + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h new file mode 100644 index 000000000000..9261aacd25f1 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ +/********* Definitions for APCI-2016 card *****/ + +#define APCI2016_BOARD_VENDOR_ID 0x15B8 +#define APCI2016_ADDRESS_RANGE 8 + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI2016_DIGITAL_OP 0x04 +#define APCI2016_DIGITAL_OP_RW 4 + +//ADDIDATA Enable Disable + +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +// TIMER COUNTER WATCHDOG DEFINES + +#define ADDIDATA_WATCHDOG 2 +#define APCI2016_DIGITAL_OP_WATCHDOG 0 +#define APCI2016_WATCHDOG_ENABLEDISABLE 12 +#define APCI2016_WATCHDOG_RELOAD_VALUE 4 +#define APCI2016_WATCHDOG_STATUS 16 + +// Hardware Layer functions for Apci2016 + +//DO +int i_APCI2016_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +int i_APCI2016_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +int i_APCI2016_BitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// TIMER +// timer value is passed as u seconds + +int i_APCI2016_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +int i_APCI2016_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +int i_APCI2016_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// Interrupt functions..... + +// void v_APCI2016_Interrupt(int irq, void *d) ; + + //void v_APCI2016_Interrupt(int irq, void *d); +// RESET +INT i_APCI2016_Reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c new file mode 100644 index 000000000000..1347bc388f3e --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c @@ -0,0 +1,579 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-2032 | Compiler : GCC | + | Module name : hwdrv_apci2032.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-2032 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ + +#include "hwdrv_apci2032.h" +UINT ui_InterruptData, ui_Type; +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_ConfigDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[1] : 1 Enable VCC Interrupt | +| 0 Disable VCC Interrupt | +| data[2] : 1 Enable CC Interrupt | +| 0 Disable CC Interrupt | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2032_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + ULONG ul_Command = 0; + devpriv->tsk_Current = current; + + if ((data[0] != 0) && (data[0] != 1)) { + comedi_error(dev, + "Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } //if ( (data[0]!=0) && (data[0]!=1) ) + if (data[0]) { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; + } // if (data[0]) + else { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + } //else if (data[0]) + + if (data[1] == ADDIDATA_ENABLE) { + ul_Command = ul_Command | 0x1; + } //if (data[1] == ADDIDATA_ENABLE) + else { + ul_Command = ul_Command & 0xFFFFFFFE; + } //elseif (data[1] == ADDIDATA_ENABLE) + if (data[2] == ADDIDATA_ENABLE) { + ul_Command = ul_Command | 0x2; + } //if (data[2] == ADDIDATA_ENABLE) + else { + ul_Command = ul_Command & 0xFFFFFFFD; + } //elseif (data[2] == ADDIDATA_ENABLE) + outl(ul_Command, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT); + ui_InterruptData = inl(devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT); + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_WriteDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To Write | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2032_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp, ui_Temp1; + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + if (devpriv->b_OutputMemoryStatus) { + ui_Temp = inl(devpriv->iobase + APCI2032_DIGITAL_OP); + + } //if(devpriv->b_OutputMemoryStatus ) + else { + ui_Temp = 0; + } //if(devpriv->b_OutputMemoryStatus ) + if (data[3] == 0) { + if (data[1] == 0) { + data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; + outl(data[0], devpriv->iobase + APCI2032_DIGITAL_OP); + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = + (data[0] << (2 * + data[2])) | ui_Temp; + break; + + case 4: + data[0] = + (data[0] << (4 * + data[2])) | ui_Temp; + break; + + case 8: + data[0] = + (data[0] << (8 * + data[2])) | ui_Temp; + break; + + case 16: + data[0] = + (data[0] << (16 * + data[2])) | ui_Temp; + break; + case 31: + data[0] = data[0] | ui_Temp; + break; + + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + + outl(data[0], + devpriv->iobase + APCI2032_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==0) + else { + if (data[3] == 1) { + if (data[1] == 0) { + data[0] = ~data[0] & 0x1; + ui_Temp1 = 1; + ui_Temp1 = ui_Temp1 << ui_NoOfChannel; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + (data[0] << ui_NoOfChannel) ^ + 0xffffffff; + data[0] = data[0] & ui_Temp; + outl(data[0], + devpriv->iobase + APCI2032_DIGITAL_OP); + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = ~data[0] & 0x3; + ui_Temp1 = 3; + ui_Temp1 = + ui_Temp1 << 2 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (2 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + + case 4: + data[0] = ~data[0] & 0xf; + ui_Temp1 = 15; + ui_Temp1 = + ui_Temp1 << 4 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (4 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + + case 8: + data[0] = ~data[0] & 0xff; + ui_Temp1 = 255; + ui_Temp1 = + ui_Temp1 << 8 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (8 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + + case 16: + data[0] = ~data[0] & 0xffff; + ui_Temp1 = 65535; + ui_Temp1 = + ui_Temp1 << 16 * + data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (16 * + data + [2])) ^ + 0xffffffff) & ui_Temp; + break; + + case 31: + break; + default: + comedi_error(dev, + " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + + outl(data[0], + devpriv->iobase + + APCI2032_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==1); + else { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } //if else data[3]==1) + } //if else data[3]==0) + return (insn->n);; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_ReadDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2032_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + ui_NoOfChannel = CR_CHAN(insn->chanspec); + ui_Temp = data[0]; + *data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW); + if (ui_Temp == 0) { + *data = (*data >> ui_NoOfChannel) & 0x1; + } //if (ui_Temp==0) + else { + if (ui_Temp == 1) { + switch (ui_NoOfChannel) { + + case 2: + *data = (*data >> (2 * data[1])) & 3; + break; + + case 4: + *data = (*data >> (4 * data[1])) & 15; + break; + + case 8: + *data = (*data >> (8 * data[1])) & 255; + break; + + case 16: + *data = (*data >> (16 * data[1])) & 65535; + break; + + case 31: + break; + + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + } //if (ui_Temp==1) + else { + printk("\nSpecified channel not supported \n"); + } //elseif (ui_Temp==1) + } + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI2032_ConfigWatchdog(comedi_device + *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)| +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI2032_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (data[0] == 0) { + //Disable the watchdog + outl(0x0, + devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + + APCI2032_TCW_PROG); + //Loading the Reload value + outl(data[1], + devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + + APCI2032_TCW_RELOAD_VALUE); + } else { + printk("\nThe input parameters are wrong\n"); + return -EINVAL; + } + + return insn->n; +} + + /* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI2032_StartStopWriteWatchdog | + | (struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data); | + +----------------------------------------------------------------------------+ + | Task : Start / Stop The Watchdog | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | + | unsigned int *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ + */ + +int i_APCI2032_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + switch (data[0]) { + case 0: //stop the watchdog + outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); //disable the watchdog + break; + case 1: //start the watchdog + outl(0x0001, + devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + + APCI2032_TCW_PROG); + break; + case 2: //Software trigger + outl(0x0201, + devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + + APCI2032_TCW_PROG); + break; + default: + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_ReadWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data); | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2032_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + data[0] = + inl(devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + + APCI2032_TCW_TRIG_STATUS) & 0x1; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : void v_APCI2032_Interrupt | +| (int irq , void *d) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +void v_APCI2032_Interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + unsigned int ui_DO; + + ui_DO = inl(devpriv->iobase + APCI2032_DIGITAL_OP_IRQ) & 0x1; //Check if VCC OR CC interrupt has occured. + + if (ui_DO == 0) { + printk("\nInterrupt from unKnown source\n"); + } // if(ui_DO==0) + if (ui_DO) { + // Check for Digital Output interrupt Type - 1: Vcc interrupt 2: CC interrupt. + ui_Type = + inl(devpriv->iobase + + APCI2032_DIGITAL_OP_INTERRUPT_STATUS) & 0x3; + outl(0x0, + devpriv->iobase + APCI2032_DIGITAL_OP + + APCI2032_DIGITAL_OP_INTERRUPT); + if (ui_Type == 1) { + //Sends signal to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + } // if (ui_Type==1) + else { + if (ui_Type == 2) { + // Sends signal to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + } //if (ui_Type==2) + } //else if (ui_Type==1) + } //if(ui_DO) + + return; + +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_ReadInterruptStatus | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task :Reads the interrupt status register | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2032_ReadInterruptStatus(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + *data = ui_Type; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2032_Reset(struct comedi_device *dev) | +| | ++----------------------------------------------------------------------------+ +| Task :Resets the registers of the card | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2032_Reset(struct comedi_device * dev) +{ + devpriv->b_DigitalOutputRegister = 0; + ui_Type = 0; + outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP); //Resets the output channels + outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_INTERRUPT); //Disables the interrupt. + outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_PROG); //disable the watchdog + outl(0x0, devpriv->iobase + APCI2032_DIGITAL_OP_WATCHDOG + APCI2032_TCW_RELOAD_VALUE); //reload=0 + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h new file mode 100644 index 000000000000..55002e0288b5 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/********* Definitions for APCI-2032 card *****/ + +// Card Specific information +#define APCI2032_BOARD_VENDOR_ID 0x15B8 +#define APCI2032_ADDRESS_RANGE 63 + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI2032_DIGITAL_OP 0 +#define APCI2032_DIGITAL_OP_RW 0 +#define APCI2032_DIGITAL_OP_INTERRUPT 4 +#define APCI2032_DIGITAL_OP_IRQ 12 + +//Digital Output Interrupt Status +#define APCI2032_DIGITAL_OP_INTERRUPT_STATUS 8 + +//Digital Output Interrupt Enable Disable. +#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_ENABLE 0x1 +#define APCI2032_DIGITAL_OP_VCC_INTERRUPT_DISABLE 0xFFFFFFFE +#define APCI2032_DIGITAL_OP_CC_INTERRUPT_ENABLE 0x2 +#define APCI2032_DIGITAL_OP_CC_INTERRUPT_DISABLE 0xFFFFFFFD + +//ADDIDATA Enable Disable + +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 + +// TIMER COUNTER WATCHDOG DEFINES + +#define ADDIDATA_WATCHDOG 2 +#define APCI2032_DIGITAL_OP_WATCHDOG 16 +#define APCI2032_TCW_RELOAD_VALUE 4 +#define APCI2032_TCW_TIMEBASE 8 +#define APCI2032_TCW_PROG 12 +#define APCI2032_TCW_TRIG_STATUS 16 +#define APCI2032_TCW_IRQ 20 + +// Hardware Layer functions for Apci2032 + +//DO +int i_APCI2032_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI2032_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI2032_ReadInterruptStatus(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// TIMER +// timer value is passed as u seconds +INT i_APCI2032_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI2032_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI2032_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// Interrupt functions..... + +void v_APCI2032_Interrupt(int irq, void *d); + +//Reset functions +int i_APCI2032_Reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c new file mode 100644 index 000000000000..947e18ef3ab3 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c @@ -0,0 +1,549 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-2200 | Compiler : GCC | + | Module name : hwdrv_apci2200.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-2200 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci2200.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_Read1DigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the digital input | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI2200_Read1DigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_TmpValue = 0; + UINT ui_Channel; + ui_Channel = CR_CHAN(insn->chanspec); + if (ui_Channel >= 0 && ui_Channel <= 7) { + ui_TmpValue = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP); + *data = (ui_TmpValue >> ui_Channel) & 0x1; + } //if(ui_Channel >= 0 && ui_Channel <=7) + else { + printk("\nThe specified channel does not exist\n"); + return -EINVAL; // "sorry channel spec wrong " + } //else if(ui_Channel >= 0 && ui_Channel <=7) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ReadMoreDigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Return the status of the Requested digital inputs | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + UINT ui_PortValue = data[0]; + UINT ui_Mask = 0; + UINT ui_NoOfChannels; + + ui_NoOfChannels = CR_CHAN(insn->chanspec); + + *data = (UINT) inw(devpriv->iobase + APCI2200_DIGITAL_IP); + switch (ui_NoOfChannels) { + case 2: + ui_Mask = 3; + *data = (*data >> (2 * ui_PortValue)) & ui_Mask; + break; + case 4: + ui_Mask = 15; + *data = (*data >> (4 * ui_PortValue)) & ui_Mask; + break; + case 7: + break; + + default: + printk("\nWrong parameters\n"); + return -EINVAL; // "sorry channel spec wrong " + break; + } //switch(ui_NoOfChannels) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ConfigDigitalOutput (struct comedi_device *dev, + struct comedi_subdevice *s struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| data[0] :1:Memory on | +| 0:Memory off | +| | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI2200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + devpriv->b_OutputMemoryStatus = data[0]; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_WriteDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Writes port value To the selected port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp, ui_Temp1; + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + if (devpriv->b_OutputMemoryStatus) { + ui_Temp = inw(devpriv->iobase + APCI2200_DIGITAL_OP); + + } //if(devpriv->b_OutputMemoryStatus ) + else { + ui_Temp = 0; + } //if(devpriv->b_OutputMemoryStatus ) + if (data[3] == 0) { + if (data[1] == 0) { + data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; + outw(data[0], devpriv->iobase + APCI2200_DIGITAL_OP); + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = + (data[0] << (2 * + data[2])) | ui_Temp; + break; + + case 4: + data[0] = + (data[0] << (4 * + data[2])) | ui_Temp; + break; + + case 8: + data[0] = + (data[0] << (8 * + data[2])) | ui_Temp; + break; + case 15: + data[0] = data[0] | ui_Temp; + break; + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + + outw(data[0], + devpriv->iobase + APCI2200_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==0) + else { + if (data[3] == 1) { + if (data[1] == 0) { + data[0] = ~data[0] & 0x1; + ui_Temp1 = 1; + ui_Temp1 = ui_Temp1 << ui_NoOfChannel; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = (data[0] << ui_NoOfChannel) ^ 0xffff; + data[0] = data[0] & ui_Temp; + outw(data[0], + devpriv->iobase + APCI2200_DIGITAL_OP); + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = ~data[0] & 0x3; + ui_Temp1 = 3; + ui_Temp1 = + ui_Temp1 << 2 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (2 * + data + [2])) ^ + 0xffff) & ui_Temp; + break; + + case 4: + data[0] = ~data[0] & 0xf; + ui_Temp1 = 15; + ui_Temp1 = + ui_Temp1 << 4 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (4 * + data + [2])) ^ + 0xffff) & ui_Temp; + break; + + case 8: + data[0] = ~data[0] & 0xff; + ui_Temp1 = 255; + ui_Temp1 = + ui_Temp1 << 8 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (8 * + data + [2])) ^ + 0xffff) & ui_Temp; + break; + case 15: + break; + + default: + comedi_error(dev, + " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + + outw(data[0], + devpriv->iobase + + APCI2200_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==1); + else { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } //if else data[3]==1) + } //if else data[3]==0) + return (insn->n);; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ReadDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + UINT ui_Temp; + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + ui_Temp = data[0]; + *data = inw(devpriv->iobase + APCI2200_DIGITAL_OP); + if (ui_Temp == 0) { + *data = (*data >> ui_NoOfChannel) & 0x1; + } //if(ui_Temp==0) + else { + if (ui_Temp == 1) { + switch (ui_NoOfChannel) { + + case 2: + *data = (*data >> (2 * data[1])) & 3; + break; + + case 4: + *data = (*data >> (4 * data[1])) & 15; + break; + + case 8: + *data = (*data >> (8 * data[1])) & 255; + break; + + case 15: + break; + + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + } //if(ui_Temp==1) + else { + printk("\nSpecified channel not supported \n"); + } //elseif(ui_Temp==1) + } //elseif(ui_Temp==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Configures The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2200_ConfigWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (data[0] == 0) { + //Disable the watchdog + outw(0x0, + devpriv->iobase + APCI2200_WATCHDOG + + APCI2200_WATCHDOG_ENABLEDISABLE); + //Loading the Reload value + outw(data[1], + devpriv->iobase + APCI2200_WATCHDOG + + APCI2200_WATCHDOG_RELOAD_VALUE); + data[1] = data[1] >> 16; + outw(data[1], + devpriv->iobase + APCI2200_WATCHDOG + + APCI2200_WATCHDOG_RELOAD_VALUE + 2); + } //if(data[0]==0) + else { + printk("\nThe input parameters are wrong\n"); + return -EINVAL; + } //elseif(data[0]==0) + + return insn->n; +} + + /* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI2200_StartStopWriteWatchdog | + | (struct comedi_device *dev,struct comedi_subdevice *s, + struct comedi_insn *insn,unsigned int *data); | + +----------------------------------------------------------------------------+ + | Task : Start / Stop The Watchdog | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | + | unsigned int *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ + */ + +int i_APCI2200_StartStopWriteWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + switch (data[0]) { + case 0: //stop the watchdog + outw(0x0, devpriv->iobase + APCI2200_WATCHDOG + APCI2200_WATCHDOG_ENABLEDISABLE); //disable the watchdog + break; + case 1: //start the watchdog + outw(0x0001, + devpriv->iobase + APCI2200_WATCHDOG + + APCI2200_WATCHDOG_ENABLEDISABLE); + break; + case 2: //Software trigger + outw(0x0201, + devpriv->iobase + APCI2200_WATCHDOG + + APCI2200_WATCHDOG_ENABLEDISABLE); + break; + default: + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } // switch(data[0]) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_ReadWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn, + unsigned int *data); | ++----------------------------------------------------------------------------+ +| Task : Read The Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s, :pointer to subdevice structure + struct comedi_insn *insn :pointer to insn structure | +| unsigned int *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI2200_ReadWatchdog(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = + inw(devpriv->iobase + APCI2200_WATCHDOG + + APCI2200_WATCHDOG_STATUS) & 0x1; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI2200_Reset(struct comedi_device *dev) | | ++----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI2200_Reset(struct comedi_device * dev) +{ + outw(0x0, devpriv->iobase + APCI2200_DIGITAL_OP); //RESETS THE DIGITAL OUTPUTS + outw(0x0, + devpriv->iobase + APCI2200_WATCHDOG + + APCI2200_WATCHDOG_ENABLEDISABLE); + outw(0x0, + devpriv->iobase + APCI2200_WATCHDOG + + APCI2200_WATCHDOG_RELOAD_VALUE); + outw(0x0, + devpriv->iobase + APCI2200_WATCHDOG + + APCI2200_WATCHDOG_RELOAD_VALUE + 2); + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h new file mode 100644 index 000000000000..0a115b4c44c9 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/********* Definitions for APCI-2200 card *****/ + +// Card Specific information +#define APCI2200_BOARD_VENDOR_ID 0x15b8 +#define APCI2200_ADDRESS_RANGE 64 + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI2200_DIGITAL_OP 4 +#define APCI2200_DIGITAL_IP 0 + +// TIMER COUNTER WATCHDOG DEFINES + +#define APCI2200_WATCHDOG 0x08 +#define APCI2200_WATCHDOG_ENABLEDISABLE 12 +#define APCI2200_WATCHDOG_RELOAD_VALUE 4 +#define APCI2200_WATCHDOG_STATUS 16 + +// Hardware Layer functions for Apci2200 + +//Digital Input +INT i_APCI2200_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI2200_Read1DigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//Digital Output +int i_APCI2200_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI2200_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI2200_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// TIMER +int i_APCI2200_ConfigWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI2200_StartStopWriteWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI2200_ReadWatchdog(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//reset +INT i_APCI2200_Reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c new file mode 100644 index 000000000000..68eb8dfd5139 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -0,0 +1,2697 @@ +/** +@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 Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : APCI-3120 | Compiler : GCC | + | Module name : hwdrv_apci3120.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-----------------------------------------------------------------------+ + | Description :APCI3120 Module. Hardware abstraction Layer for APCI3120| + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +#include "hwdrv_apci3120.h" +static UINT ui_Temp = 0; + +// FUNCTION DEFINITIONS + +/* ++----------------------------------------------------------------------------+ +| ANALOG INPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev,| +| struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Calls card specific function | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT i; + + if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE)) + return -1; + + // Check for Conversion time to be added ?? + devpriv->ui_EocEosConversionTime = data[2]; + + if (data[0] == APCI3120_EOS_MODE) { + + //Test the number of the channel + for (i = 0; i < data[3]; i++) { + + if (CR_CHAN(data[4 + i]) >= this_board->i_NbrAiChannel) { + printk("bad channel list\n"); + return -2; + } + } + + devpriv->b_InterruptMode = APCI3120_EOS_MODE; + + if (data[1]) { + devpriv->b_EocEosInterrupt = APCI3120_ENABLE; + } else + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; + // Copy channel list and Range List to devpriv + + devpriv->ui_AiNbrofChannels = data[3]; + for (i = 0; i < devpriv->ui_AiNbrofChannels; i++) { + devpriv->ui_AiChannelList[i] = data[4 + i]; + } + + } else // EOC + { + devpriv->b_InterruptMode = APCI3120_EOC_MODE; + if (data[1]) { + devpriv->b_EocEosInterrupt = APCI3120_ENABLE; + } else { + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; + } + } + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, | +| struct comedi_subdevice *s,struct comedi_insn *insn, unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : card specific function | +| Reads analog input in synchronous mode | +| EOC and EOS is selected as per configured | +| if no conversion time is set uses default conversion | +| time 10 microsec. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + USHORT us_ConvertTiming, us_TmpValue, i; + BYTE b_Tmp; + + // fix convertion time to 10 us + if (!devpriv->ui_EocEosConversionTime) { + printk("No timer0 Value using 10 us\n"); + us_ConvertTiming = 10; + } else + us_ConvertTiming = (USHORT) (devpriv->ui_EocEosConversionTime / 1000); // nano to useconds + + // this_board->i_hwdrv_InsnReadAnalogInput(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]); + + // Clear software registers + devpriv->b_TimerSelectMode = 0; + devpriv->b_ModeSelectRegister = 0; + devpriv->us_OutputRegister = 0; +// devpriv->b_DigitalOutputRegister=0; + + if (insn->unused[0] == 222) // second insn read + { + + for (i = 0; i < insn->n; i++) { + data[i] = devpriv->ui_AiReadData[i]; + } + + } else { + devpriv->tsk_Current = current; // Save the current process task structure + //Testing if board have the new Quartz and calculate the time value + //to set in the timer + + us_TmpValue = + (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS); + + //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 + if ((us_TmpValue & 0x00B0) == 0x00B0 + || !strcmp(this_board->pc_DriverName, "apci3001")) { + us_ConvertTiming = (us_ConvertTiming * 2) - 2; + } else { + us_ConvertTiming = + ((us_ConvertTiming * 12926) / 10000) - 1; + } + + us_TmpValue = (USHORT) devpriv->b_InterruptMode; + + switch (us_TmpValue) { + + case APCI3120_EOC_MODE: + + // Testing the interrupt flag and set the EOC bit + // Clears the FIFO + inw(devpriv->iobase + APCI3120_RESET_FIFO); + + // Initialize the sequence array + + //if (!i_APCI3120_SetupChannelList(dev,s,1,chanlist,0)) return -EINVAL; + + if (!i_APCI3120_SetupChannelList(dev, s, 1, + &insn->chanspec, 0)) + return -EINVAL; + + //Initialize Timer 0 mode 4 + devpriv->b_TimerSelectMode = + (devpriv-> + b_TimerSelectMode & 0xFC) | + APCI3120_TIMER_0_MODE_4; + outb(devpriv->b_TimerSelectMode, + devpriv->iobase + APCI3120_TIMER_CRT1); + + // Reset the scan bit and Disables the EOS, DMA, EOC interrupt + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & APCI3120_DISABLE_SCAN; + + if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { + + //Disables the EOS,DMA and enables the EOC interrupt + devpriv->b_ModeSelectRegister = + (devpriv-> + b_ModeSelectRegister & + APCI3120_DISABLE_EOS_INT) | + APCI3120_ENABLE_EOC_INT; + inw(devpriv->iobase); + + } else { + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & + APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER; + } + + outb(devpriv->b_ModeSelectRegister, + devpriv->iobase + APCI3120_WRITE_MODE_SELECT); + + // Sets gate 0 + devpriv->us_OutputRegister = + (devpriv-> + us_OutputRegister & APCI3120_CLEAR_PA_PR) | + APCI3120_ENABLE_TIMER0; + outw(devpriv->us_OutputRegister, + devpriv->iobase + APCI3120_WR_ADDRESS); + + // Select Timer 0 + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_0_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + + //Set the convertion time + outw(us_ConvertTiming, + devpriv->iobase + APCI3120_TIMER_VALUE); + + us_TmpValue = + (USHORT) inw(dev->iobase + APCI3120_RD_STATUS); + + if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) { + + do { + // Waiting for the end of conversion + us_TmpValue = + inw(devpriv->iobase + + APCI3120_RD_STATUS); + } while ((us_TmpValue & APCI3120_EOC) == + APCI3120_EOC); + + //Read the result in FIFO and put it in insn data pointer + us_TmpValue = inw(devpriv->iobase + 0); + *data = us_TmpValue; + + inw(devpriv->iobase + APCI3120_RESET_FIFO); + } + + break; + + case APCI3120_EOS_MODE: + + inw(devpriv->iobase); + // Clears the FIFO + inw(devpriv->iobase + APCI3120_RESET_FIFO); + // clear PA PR and disable timer 0 + + devpriv->us_OutputRegister = + (devpriv-> + us_OutputRegister & APCI3120_CLEAR_PA_PR) | + APCI3120_DISABLE_TIMER0; + + outw(devpriv->us_OutputRegister, + devpriv->iobase + APCI3120_WR_ADDRESS); + + if (!i_APCI3120_SetupChannelList(dev, s, + devpriv->ui_AiNbrofChannels, + devpriv->ui_AiChannelList, 0)) + return -EINVAL; + + //Initialize Timer 0 mode 2 + devpriv->b_TimerSelectMode = + (devpriv-> + b_TimerSelectMode & 0xFC) | + APCI3120_TIMER_0_MODE_2; + outb(devpriv->b_TimerSelectMode, + devpriv->iobase + APCI3120_TIMER_CRT1); + + //Select Timer 0 + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_0_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + + //Set the convertion time + outw(us_ConvertTiming, + devpriv->iobase + APCI3120_TIMER_VALUE); + + //Set the scan bit + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister | APCI3120_ENABLE_SCAN; + outb(devpriv->b_ModeSelectRegister, + devpriv->iobase + APCI3120_WRITE_MODE_SELECT); + + //If Interrupt function is loaded + if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { + //Disables the EOC,DMA and enables the EOS interrupt + devpriv->b_ModeSelectRegister = + (devpriv-> + b_ModeSelectRegister & + APCI3120_DISABLE_EOC_INT) | + APCI3120_ENABLE_EOS_INT; + inw(devpriv->iobase); + + } else + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & + APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER; + + outb(devpriv->b_ModeSelectRegister, + devpriv->iobase + APCI3120_WRITE_MODE_SELECT); + + inw(devpriv->iobase + APCI3120_RD_STATUS); + + //Sets gate 0 + + devpriv->us_OutputRegister = + devpriv-> + us_OutputRegister | APCI3120_ENABLE_TIMER0; + outw(devpriv->us_OutputRegister, + devpriv->iobase + APCI3120_WR_ADDRESS); + + //Start conversion + outw(0, devpriv->iobase + APCI3120_START_CONVERSION); + + //Waiting of end of convertion if interrupt is not installed + if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) { + //Waiting the end of convertion + do { + us_TmpValue = + inw(devpriv->iobase + + APCI3120_RD_STATUS); + } + while ((us_TmpValue & APCI3120_EOS) != + APCI3120_EOS); + + for (i = 0; i < devpriv->ui_AiNbrofChannels; + i++) { + //Read the result in FIFO and write them in shared memory + us_TmpValue = inw(devpriv->iobase); + data[i] = (UINT) us_TmpValue; + } + + devpriv->b_InterruptMode = APCI3120_EOC_MODE; // Restore defaults. + } + break; + + default: + printk("inputs wrong\n"); + + } + devpriv->ui_EocEosConversionTime = 0; // re initializing the variable; + } + + return insn->n; + +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev,| +| struct comedi_subdevice *s)| +| | ++----------------------------------------------------------------------------+ +| Task : Stops Cyclic acquisition | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| | ++----------------------------------------------------------------------------+ +| Return Value :0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s) +{ + // Disable A2P Fifo write and AMWEN signal + outw(0, devpriv->i_IobaseAddon + 4); + + //Disable Bus Master ADD ON + outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0); + outw(0, devpriv->i_IobaseAddon + 2); + outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0); + outw(0, devpriv->i_IobaseAddon + 2); + + //Disable BUS Master PCI + outl(0, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR); + + //outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR)&(~AINT_WRITE_COMPL), devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); // stop amcc irqs + //outl(inl(devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR)&(~EN_A2P_TRANSFERS), devpriv->i_IobaseAmcc+AMCC_OP_REG_MCSR); // stop DMA + + //Disable ext trigger + i_APCI3120_ExttrigDisable(dev); + + devpriv->us_OutputRegister = 0; + //stop counters + outw(devpriv-> + us_OutputRegister & APCI3120_DISABLE_TIMER0 & + APCI3120_DISABLE_TIMER1, dev->iobase + APCI3120_WR_ADDRESS); + + outw(APCI3120_DISABLE_ALL_TIMER, dev->iobase + APCI3120_WR_ADDRESS); + + //DISABLE_ALL_INTERRUPT + outb(APCI3120_DISABLE_ALL_INTERRUPT, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + //Flush FIFO + inb(dev->iobase + APCI3120_RESET_FIFO); + inw(dev->iobase + APCI3120_RD_STATUS); + devpriv->ui_AiActualScan = 0; + devpriv->ui_AiActualScanPosition = 0; + s->async->cur_chan = 0; + devpriv->ui_AiBufferPtr = 0; + devpriv->b_AiContinuous = 0; + devpriv->ui_DmaActualBuffer = 0; + + devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; + devpriv->b_InterruptMode = APCI3120_EOC_MODE; + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; + i_APCI3120_Reset(dev); + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev| +| ,struct comedi_subdevice *s,struct comedi_cmd *cmd) | +| | ++----------------------------------------------------------------------------+ +| Task : Test validity for a command for cyclic anlog input | +| acquisition | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_cmd *cmd | ++----------------------------------------------------------------------------+ +| Return Value :0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; // divisor1,divisor2; + + // step 1: make sure trigger sources are trivially valid + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + //step 2: make sure trigger sources are unique and mutually compatible + + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) { + err++; + } + + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + + if (cmd->convert_src != TRIG_TIMER) + err++; + + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; + + if (err) + return 2; + + // step 3: make sure arguments are trivially compatible + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + if (cmd->scan_begin_src == TRIG_TIMER) // Test Delay timing + { + if (cmd->scan_begin_arg < this_board->ui_MinDelaytimeNs) { + cmd->scan_begin_arg = this_board->ui_MinDelaytimeNs; + err++; + } + } + + if (cmd->convert_src == TRIG_TIMER) // Test Acquisition timing + { + if (cmd->scan_begin_src == TRIG_TIMER) { + if ((cmd->convert_arg) + && (cmd->convert_arg < + this_board->ui_MinAcquisitiontimeNs)) { + cmd->convert_arg = + this_board->ui_MinAcquisitiontimeNs; + err++; + } + } else { + if (cmd->convert_arg < + this_board->ui_MinAcquisitiontimeNs) { + cmd->convert_arg = + this_board->ui_MinAcquisitiontimeNs; + err++; + + } + } + } + + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->chanlist_len > this_board->i_AiChannelList) { + cmd->chanlist_len = this_board->i_AiChannelList; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + } else { // TRIG_NONE + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + // step 4: fix up any arguments + + if (cmd->convert_src == TRIG_TIMER) { + + if (cmd->scan_begin_src == TRIG_TIMER && + cmd->scan_begin_arg < + cmd->convert_arg * cmd->scan_end_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->scan_end_arg; + err++; + } + } + + if (err) + return 4; + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, | +| struct comedi_subdevice *s) | +| | ++----------------------------------------------------------------------------+ +| Task : Does asynchronous acquisition | +| Determines the mode 1 or 2. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + + //loading private structure with cmd structure inputs + devpriv->ui_AiFlags = cmd->flags; + devpriv->ui_AiNbrofChannels = cmd->chanlist_len; + devpriv->ui_AiScanLength = cmd->scan_end_arg; + devpriv->pui_AiChannelList = cmd->chanlist; + + //UPDATE-0.7.57->0.7.68devpriv->AiData=s->async->data; + devpriv->AiData = s->async->prealloc_buf; + //UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len; + devpriv->ui_AiDataLength = s->async->prealloc_bufsz; + + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ui_AiNbrofScans = cmd->stop_arg; + } else { + devpriv->ui_AiNbrofScans = 0; + } + + devpriv->ui_AiTimer0 = 0; // variables changed to timer0,timer1 + devpriv->ui_AiTimer1 = 0; + if ((devpriv->ui_AiNbrofScans == 0) || (devpriv->ui_AiNbrofScans == -1)) + devpriv->b_AiContinuous = 1; // user want neverending analog acquisition + // stopped using cancel + + if (cmd->start_src == TRIG_EXT) + devpriv->b_ExttrigEnable = APCI3120_ENABLE; + else + devpriv->b_ExttrigEnable = APCI3120_DISABLE; + + if (cmd->scan_begin_src == TRIG_FOLLOW) { + // mode 1 or 3 + if (cmd->convert_src == TRIG_TIMER) { + // mode 1 + + devpriv->ui_AiTimer0 = cmd->convert_arg; // timer constant in nano seconds + //return this_board->i_hwdrv_CommandAnalogInput(1,dev,s); + return i_APCI3120_CyclicAnalogInput(1, dev, s); + } + + } + if ((cmd->scan_begin_src == TRIG_TIMER) + && (cmd->convert_src == TRIG_TIMER)) { + // mode 2 + devpriv->ui_AiTimer1 = cmd->scan_begin_arg; + devpriv->ui_AiTimer0 = cmd->convert_arg; // variable changed timer2 to timer0 + //return this_board->i_hwdrv_CommandAnalogInput(2,dev,s); + return i_APCI3120_CyclicAnalogInput(2, dev, s); + } + return -1; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_CyclicAnalogInput(int mode, | +| struct comedi_device * dev,struct comedi_subdevice * s) | ++----------------------------------------------------------------------------+ +| Task : This is used for analog input cyclic acquisition | +| Performs the command operations. | +| If DMA is configured does DMA initialization | +| otherwise does the acquisition with EOS interrupt. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device * dev, + struct comedi_subdevice * s) +{ + BYTE b_Tmp; + UINT ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 = + 0, dmalen1 = 0, ui_TimerValue2 = + 0, ui_TimerValue0, ui_ConvertTiming; + USHORT us_TmpValue; + + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + //devpriv->b_AiCyclicAcquisition=APCI3120_ENABLE; + //END JK 07.05.04: Comparison between WIN32 and Linux driver + + /*******************/ + /* Resets the FIFO */ + /*******************/ + inb(dev->iobase + APCI3120_RESET_FIFO); + + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + //inw(dev->iobase+APCI3120_RD_STATUS); + //END JK 07.05.04: Comparison between WIN32 and Linux driver + + /***************************/ + /* Acquisition initialized */ + /***************************/ + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + devpriv->b_AiCyclicAcquisition = APCI3120_ENABLE; + //END JK 07.05.04: Comparison between WIN32 and Linux driver + + // clear software registers + devpriv->b_TimerSelectMode = 0; + devpriv->us_OutputRegister = 0; + devpriv->b_ModeSelectRegister = 0; + //devpriv->b_DigitalOutputRegister=0; + + //COMMENT JK 07.05.04: Followings calls are in i_APCI3120_StartAnalogInputAcquisition + + /****************************/ + /* Clear Timer Write TC INT */ + /****************************/ + outl(APCI3120_CLEAR_WRITE_TC_INT, + devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_REG_INTCSR); + + /************************************/ + /* Clears the timer status register */ + /************************************/ + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + //inw(dev->iobase+APCI3120_TIMER_STATUS_REGISTER); + inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER); + //END JK 07.05.04: Comparison between WIN32 and Linux driver + + /**************************/ + /* Disables All Timer */ + /* Sets PR and PA to 0 */ + /**************************/ + devpriv->us_OutputRegister = devpriv->us_OutputRegister & + APCI3120_DISABLE_TIMER0 & + APCI3120_DISABLE_TIMER1 & APCI3120_CLEAR_PA_PR; + + outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); + + /*******************/ + /* Resets the FIFO */ + /*******************/ + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + inb(devpriv->iobase + APCI3120_RESET_FIFO); + //END JK 07.05.04: Comparison between WIN32 and Linux driver + + devpriv->ui_AiActualScan = 0; + devpriv->ui_AiActualScanPosition = 0; + s->async->cur_chan = 0; + devpriv->ui_AiBufferPtr = 0; + devpriv->ui_DmaActualBuffer = 0; + + // value for timer2 minus -2 has to be done .....dunno y?? + ui_TimerValue2 = devpriv->ui_AiNbrofScans - 2; + ui_ConvertTiming = devpriv->ui_AiTimer0; + + if (mode == 2) + ui_DelayTiming = devpriv->ui_AiTimer1; + + /**********************************/ + /* Initializes the sequence array */ + /**********************************/ + if (!i_APCI3120_SetupChannelList(dev, s, devpriv->ui_AiNbrofChannels, + devpriv->pui_AiChannelList, 0)) + return -EINVAL; + + us_TmpValue = (USHORT) inw(dev->iobase + APCI3120_RD_STATUS); +/*** EL241003 : add this section in comment because floats must not be used + if((us_TmpValue & 0x00B0)==0x00B0) + { + f_ConvertValue=(((float)ui_ConvertTiming * 0.002) - 2); + ui_TimerValue0=(UINT)f_ConvertValue; + if (mode==2) + { + f_DelayValue = (((float)ui_DelayTiming * 0.00002) - 2); + ui_TimerValue1 = (UINT) f_DelayValue; + } + } + else + { + f_ConvertValue=(((float)ui_ConvertTiming * 0.0012926) - 1); + ui_TimerValue0=(UINT)f_ConvertValue; + if (mode == 2) + { + f_DelayValue = (((float)ui_DelayTiming * 0.000012926) - 1); + ui_TimerValue1 = (UINT) f_DelayValue; + } + } +***********************************************************************************************/ +/*** EL241003 Begin : add this section to replace floats calculation by integer calculations **/ + //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 + if ((us_TmpValue & 0x00B0) == 0x00B0 + || !strcmp(this_board->pc_DriverName, "apci3001")) { + ui_TimerValue0 = ui_ConvertTiming * 2 - 2000; + ui_TimerValue0 = ui_TimerValue0 / 1000; + + if (mode == 2) { + ui_DelayTiming = ui_DelayTiming / 1000; + ui_TimerValue1 = ui_DelayTiming * 2 - 200; + ui_TimerValue1 = ui_TimerValue1 / 100; + } + } else { + ui_ConvertTiming = ui_ConvertTiming / 1000; + ui_TimerValue0 = ui_ConvertTiming * 12926 - 10000; + ui_TimerValue0 = ui_TimerValue0 / 10000; + + if (mode == 2) { + ui_DelayTiming = ui_DelayTiming / 1000; + ui_TimerValue1 = ui_DelayTiming * 12926 - 1; + ui_TimerValue1 = ui_TimerValue1 / 1000000; + } + } +/*** EL241003 End ******************************************************************************/ + + if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) { + i_APCI3120_ExttrigEnable(dev); // activate EXT trigger + } + switch (mode) { + case 1: + // init timer0 in mode 2 + devpriv->b_TimerSelectMode = + (devpriv-> + b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2; + outb(devpriv->b_TimerSelectMode, + dev->iobase + APCI3120_TIMER_CRT1); + + //Select Timer 0 + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_0_WORD; + outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); + //Set the convertion time + outw(((USHORT) ui_TimerValue0), + dev->iobase + APCI3120_TIMER_VALUE); + break; + + case 2: + // init timer1 in mode 2 + devpriv->b_TimerSelectMode = + (devpriv-> + b_TimerSelectMode & 0xF3) | APCI3120_TIMER_1_MODE_2; + outb(devpriv->b_TimerSelectMode, + dev->iobase + APCI3120_TIMER_CRT1); + + //Select Timer 1 + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_1_WORD; + outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); + //Set the convertion time + outw(((USHORT) ui_TimerValue1), + dev->iobase + APCI3120_TIMER_VALUE); + + // init timer0 in mode 2 + devpriv->b_TimerSelectMode = + (devpriv-> + b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2; + outb(devpriv->b_TimerSelectMode, + dev->iobase + APCI3120_TIMER_CRT1); + + //Select Timer 0 + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_0_WORD; + outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); + + //Set the convertion time + outw(((USHORT) ui_TimerValue0), + dev->iobase + APCI3120_TIMER_VALUE); + break; + + } + // ##########common for all modes################# + + /***********************/ + /* Clears the SCAN bit */ + /***********************/ + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + //devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister | APCI3120_DISABLE_SCAN; + devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & + APCI3120_DISABLE_SCAN; + //END JK 07.05.04: Comparison between WIN32 and Linux driver + outb(devpriv->b_ModeSelectRegister, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + + // If DMA is disabled + if (devpriv->us_UseDma == APCI3120_DISABLE) { + // disable EOC and enable EOS + devpriv->b_InterruptMode = APCI3120_EOS_MODE; + devpriv->b_EocEosInterrupt = APCI3120_ENABLE; + + devpriv->b_ModeSelectRegister = + (devpriv-> + b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT) | + APCI3120_ENABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + + if (!devpriv->b_AiContinuous) { + // configure Timer2 For counting EOS + //Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0) + devpriv->us_OutputRegister = + devpriv-> + us_OutputRegister & APCI3120_DISABLE_TIMER2; + outw(devpriv->us_OutputRegister, + dev->iobase + APCI3120_WR_ADDRESS); + + // DISABLE TIMER INTERRUPT + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & + APCI3120_DISABLE_TIMER_INT & 0xEF; + outb(devpriv->b_ModeSelectRegister, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + + //(1) Init timer 2 in mode 0 and write timer value + devpriv->b_TimerSelectMode = + (devpriv-> + b_TimerSelectMode & 0x0F) | + APCI3120_TIMER_2_MODE_0; + outb(devpriv->b_TimerSelectMode, + dev->iobase + APCI3120_TIMER_CRT1); + + //Writing LOW WORD + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); + outw(LOWORD(ui_TimerValue2), + dev->iobase + APCI3120_TIMER_VALUE); + + //Writing HIGH WORD + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0); + outw(HIWORD(ui_TimerValue2), + dev->iobase + APCI3120_TIMER_VALUE); + + //(2) Reset FC_TIMER BIT Clearing timer status register + inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER); + // enable timer counter and disable watch dog + devpriv->b_ModeSelectRegister = + (devpriv-> + b_ModeSelectRegister | + APCI3120_ENABLE_TIMER_COUNTER) & + APCI3120_DISABLE_WATCHDOG; + // select EOS clock input for timer 2 + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister | + APCI3120_TIMER2_SELECT_EOS; + // Enable timer2 interrupt + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister | + APCI3120_ENABLE_TIMER_INT; + outb(devpriv->b_ModeSelectRegister, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + devpriv->b_Timer2Mode = APCI3120_COUNTER; + devpriv->b_Timer2Interrupt = APCI3120_ENABLE; + } + } else { + // If DMA Enabled + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + //inw(dev->iobase+0);// reset EOC bit + //END JK 07.05.04: Comparison between WIN32 and Linux driver + devpriv->b_InterruptMode = APCI3120_DMA_MODE; + + /************************************/ + /* Disables the EOC, EOS interrupt */ + /************************************/ + devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister & + APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT; + + outb(devpriv->b_ModeSelectRegister, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + + dmalen0 = devpriv->ui_DmaBufferSize[0]; + dmalen1 = devpriv->ui_DmaBufferSize[1]; + + if (!devpriv->b_AiContinuous) { + + if (dmalen0 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2)) { // must we fill full first buffer? + dmalen0 = + devpriv->ui_AiNbrofScans * + devpriv->ui_AiScanLength * 2; + } else if (dmalen1 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2 - dmalen0)) // and must we fill full second buffer when first is once filled? + dmalen1 = + devpriv->ui_AiNbrofScans * + devpriv->ui_AiScanLength * 2 - dmalen0; + } + + if (devpriv->ui_AiFlags & TRIG_WAKE_EOS) { + // don't we want wake up every scan? + if (dmalen0 > (devpriv->ui_AiScanLength * 2)) { + dmalen0 = devpriv->ui_AiScanLength * 2; + if (devpriv->ui_AiScanLength & 1) + dmalen0 += 2; + } + if (dmalen1 > (devpriv->ui_AiScanLength * 2)) { + dmalen1 = devpriv->ui_AiScanLength * 2; + if (devpriv->ui_AiScanLength & 1) + dmalen1 -= 2; + if (dmalen1 < 4) + dmalen1 = 4; + } + } else { // isn't output buff smaller that our DMA buff? + if (dmalen0 > (devpriv->ui_AiDataLength)) { + dmalen0 = devpriv->ui_AiDataLength; + } + if (dmalen1 > (devpriv->ui_AiDataLength)) { + dmalen1 = devpriv->ui_AiDataLength; + } + } + devpriv->ui_DmaBufferUsesize[0] = dmalen0; + devpriv->ui_DmaBufferUsesize[1] = dmalen1; + + //Initialize DMA + + // Set Transfer count enable bit and A2P_fifo reset bit in AGCSTS register + //1 + ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO; + outl(ui_Tmp, devpriv->i_IobaseAmcc + AMCC_OP_REG_AGCSTS); + + // changed since 16 bit interface for add on + /*********************/ + /* ENABLE BUS MASTER */ + /*********************/ + outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW, + devpriv->i_IobaseAddon + 2); + + outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, + devpriv->i_IobaseAddon + 2); + + // TO VERIFIED + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + outw(0x1000, devpriv->i_IobaseAddon + 2); + //END JK 07.05.04: Comparison between WIN32 and Linux driver + + //2 No change + // A2P FIFO MANAGEMENT + // A2P fifo reset & transfer control enable + /***********************/ + /* A2P FIFO MANAGEMENT */ + /***********************/ + outl(APCI3120_A2P_FIFO_MANAGEMENT, devpriv->i_IobaseAmcc + + APCI3120_AMCC_OP_MCSR); + + //3 + //beginning address of dma buf + //The 32 bit address of dma buffer is converted into two 16 bit addresses + // Can done by using _attach and put into into an array + // array used may be for differnet pages + + // DMA Start Adress Low + outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0); + outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF), + devpriv->i_IobaseAddon + 2); + + /*************************/ + /* DMA Start Adress High */ + /*************************/ + outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0); + outw((devpriv->ul_DmaBufferHw[0] / 65536), + devpriv->i_IobaseAddon + 2); + + //4 + // amount of bytes to be transfered set transfer count + // used ADDON MWTC register + //commented testing outl(devpriv->ui_DmaBufferUsesize[0], devpriv->i_IobaseAddon+AMCC_OP_REG_AMWTC); + + /**************************/ + /* Nbr of acquisition LOW */ + /**************************/ + outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0); + outw((devpriv->ui_DmaBufferUsesize[0] & 0xFFFF), + devpriv->i_IobaseAddon + 2); + + /***************************/ + /* Nbr of acquisition HIGH */ + /***************************/ + outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0); + outw((devpriv->ui_DmaBufferUsesize[0] / 65536), + devpriv->i_IobaseAddon + 2); + + //5 + // To configure A2P FIFO + // testing outl( FIFO_ADVANCE_ON_BYTE_2,devpriv->i_IobaseAmcc+AMCC_OP_REG_INTCSR); + + /******************/ + /* A2P FIFO RESET */ + /******************/ + // TO VERIFY + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + outl(0x04000000UL, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR); + //END JK 07.05.04: Comparison between WIN32 and Linux driver + + //6 + //ENABLE A2P FIFO WRITE AND ENABLE AMWEN + // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + //outw(3,devpriv->i_IobaseAddon + 4); + //END JK 07.05.04: Comparison between WIN32 and Linux driver + + //7 + //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) + /***************************************************/ + /* A2P FIFO CONFIGURATE, END OF DMA INTERRUPT INIT */ + /***************************************************/ + outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 | + APCI3120_ENABLE_WRITE_TC_INT), + devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); + + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + /******************************************/ + /* ENABLE A2P FIFO WRITE AND ENABLE AMWEN */ + /******************************************/ + outw(3, devpriv->i_IobaseAddon + 4); + //END JK 07.05.04: Comparison between WIN32 and Linux driver + + /******************/ + /* A2P FIFO RESET */ + /******************/ + //BEGIN JK 07.05.04: Comparison between WIN32 and Linux driver + outl(0x04000000UL, + devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_MCSR); + //END JK 07.05.04: Comparison between WIN32 and Linux driver + } + + if ((devpriv->us_UseDma == APCI3120_DISABLE) + && !devpriv->b_AiContinuous) { + // set gate 2 to start conversion + devpriv->us_OutputRegister = + devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER2; + outw(devpriv->us_OutputRegister, + dev->iobase + APCI3120_WR_ADDRESS); + } + + switch (mode) { + case 1: + // set gate 0 to start conversion + devpriv->us_OutputRegister = + devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0; + outw(devpriv->us_OutputRegister, + dev->iobase + APCI3120_WR_ADDRESS); + break; + case 2: + // set gate 0 and gate 1 + devpriv->us_OutputRegister = + devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER1; + devpriv->us_OutputRegister = + devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0; + outw(devpriv->us_OutputRegister, + dev->iobase + APCI3120_WR_ADDRESS); + break; + + } + + return 0; + +} + +/* ++----------------------------------------------------------------------------+ +| INTERNAL FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_Reset(struct comedi_device *dev) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : Hardware reset function | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_Reset(struct comedi_device * dev) +{ + unsigned int i; + unsigned short us_TmpValue; + + devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; + devpriv->b_InterruptMode = APCI3120_EOC_MODE; + devpriv->ui_EocEosConversionTime = 0; // set eoc eos conv time to 0 + devpriv->b_OutputMemoryStatus = 0; + + // variables used in timer subdevice + devpriv->b_Timer2Mode = 0; + devpriv->b_Timer2Interrupt = 0; + devpriv->b_ExttrigEnable = 0; // Disable ext trigger + + /* Disable all interrupts, watchdog for the anolog output */ + devpriv->b_ModeSelectRegister = 0; + outb(devpriv->b_ModeSelectRegister, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + + // Disables all counters, ext trigger and clears PA, PR + devpriv->us_OutputRegister = 0; + outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); + + //Code to set the all anolog o/p channel to 0v + //8191 is decimal value for zero(0 v)volt in bipolar mode(default) + outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1); //channel 1 + outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1); //channel 2 + outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1); //channel 3 + outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1); //channel 4 + + outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2); //channel 5 + outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2); //channel 6 + outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2); //channel 7 + outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2); //channel 8 + + // Reset digital output to L0W + +//ES05 outb(0x0,dev->iobase+APCI3120_DIGITAL_OUTPUT); + udelay(10); + + inw(dev->iobase + 0); //make a dummy read + inb(dev->iobase + APCI3120_RESET_FIFO); // flush FIFO + inw(dev->iobase + APCI3120_RD_STATUS); // flush A/D status register + + //code to reset the RAM sequence + for (i = 0; i < 16; i++) { + us_TmpValue = i << 8; //select the location + outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS); + } + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_SetupChannelList(struct comedi_device * dev, | +| struct comedi_subdevice * s, int n_chan,unsigned int *chanlist| +| ,char check) | +| | ++----------------------------------------------------------------------------+ +| Task :This function will first check channel list is ok or not| +|and then initialize the sequence RAM with the polarity, Gain,Channel number | +|If the last argument of function "check"is 1 then it only checks the channel| +|list is ok or not. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device * dev | +| struct comedi_subdevice * s | +| int n_chan | + unsigned int *chanlist + char check ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_SetupChannelList(struct comedi_device * dev, struct comedi_subdevice * s, + int n_chan, unsigned int *chanlist, char check) +{ + unsigned int i; //, differencial=0, bipolar=0; + unsigned int gain; + unsigned short us_TmpValue; + + /* correct channel and range number check itself comedi/range.c */ + if (n_chan < 1) { + if (!check) + comedi_error(dev, "range/channel list is empty!"); + return 0; + } + // All is ok, so we can setup channel/range list + if (check) + return 1; + + //Code to set the PA and PR...Here it set PA to 0.. + devpriv->us_OutputRegister = + devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR; + devpriv->us_OutputRegister = ((n_chan - 1) & 0xf) << 8; + outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); + + for (i = 0; i < n_chan; i++) { + // store range list to card + us_TmpValue = CR_CHAN(chanlist[i]); // get channel number; + + if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES) { + us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff); // set bipolar + } else { + us_TmpValue |= APCI3120_UNIPOLAR; // enable unipolar...... + } + + gain = CR_RANGE(chanlist[i]); // get gain number + us_TmpValue |= ((gain & 0x03) << 4); //<<4 for G0 and G1 bit in RAM + us_TmpValue |= i << 8; //To select the RAM LOCATION.... + outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS); + + printk("\n Gain = %i", + (((unsigned char)CR_RANGE(chanlist[i]) & 0x03) << 2)); + printk("\n Channel = %i", CR_CHAN(chanlist[i])); + printk("\n Polarity = %i", us_TmpValue & APCI3120_UNIPOLAR); + } + return 1; // we can serve this with scan logic +} + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_ExttrigEnable(struct comedi_device * dev) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : Enable the external trigger | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device * dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_ExttrigEnable(struct comedi_device * dev) +{ + + devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER; + outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_ExttrigDisable(struct comedi_device * dev) | +| | ++----------------------------------------------------------------------------+ +| Task : Disables the external trigger | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device * dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_ExttrigDisable(struct comedi_device * dev) +{ + devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER; + outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS); + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| INTERRUPT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function name : void v_APCI3120_Interrupt(int irq, void *d) | +| | +| | ++----------------------------------------------------------------------------+ +| Task :Interrupt handler for APCI3120 | +| When interrupt occurs this gets called. | +| First it finds which interrupt has been generated and | +| handles corresponding interrupt | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq | +| void *d | +| | ++----------------------------------------------------------------------------+ +| Return Value : void | +| | ++----------------------------------------------------------------------------+ +*/ + +void v_APCI3120_Interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + USHORT int_daq; + + unsigned int int_amcc, ui_Check, i; + USHORT us_TmpValue; + BYTE b_DummyRead; + + struct comedi_subdevice *s = dev->subdevices + 0; + ui_Check = 1; + + int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000; // get IRQ reasons + int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); // get AMCC INT register + + if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) { + comedi_error(dev, "IRQ from unknow source"); + return; + } + + outl(int_amcc | 0x00ff0000, devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); // shutdown IRQ reasons in AMCC + + int_daq = (int_daq >> 12) & 0xF; + + if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) { + //Disable ext trigger + i_APCI3120_ExttrigDisable(dev); + devpriv->b_ExttrigEnable = APCI3120_DISABLE; + } + //clear the timer 2 interrupt + inb(devpriv->i_IobaseAmcc + APCI3120_TIMER_STATUS_REGISTER); + + if (int_amcc & MASTER_ABORT_INT) + comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!"); + if (int_amcc & TARGET_ABORT_INT) + comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!"); + + // Ckeck if EOC interrupt + if (((int_daq & 0x8) == 0) + && (devpriv->b_InterruptMode == APCI3120_EOC_MODE)) { + if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { + + // Read the AI Value + + devpriv->ui_AiReadData[0] = + (UINT) inw(devpriv->iobase + 0); + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + } else { + //Disable EOC Interrupt + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT; + outb(devpriv->b_ModeSelectRegister, + devpriv->iobase + APCI3120_WRITE_MODE_SELECT); + + } + } + + // Check If EOS interrupt + if ((int_daq & 0x2) && (devpriv->b_InterruptMode == APCI3120_EOS_MODE)) { + + if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) // enable this in without DMA ??? + { + + if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) { + ui_Check = 0; + i_APCI3120_InterruptHandleEos(dev); + devpriv->ui_AiActualScan++; + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister | + APCI3120_ENABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister, + dev->iobase + + APCI3120_WRITE_MODE_SELECT); + } else { + ui_Check = 0; + for (i = 0; i < devpriv->ui_AiNbrofChannels; + i++) { + us_TmpValue = inw(devpriv->iobase + 0); + devpriv->ui_AiReadData[i] = + (UINT) us_TmpValue; + } + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; + devpriv->b_InterruptMode = APCI3120_EOC_MODE; + + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + + } + + } else { + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + devpriv->b_EocEosInterrupt = APCI3120_DISABLE; //Default settings + devpriv->b_InterruptMode = APCI3120_EOC_MODE; + } + + } + //Timer2 interrupt + if (int_daq & 0x1) { + + switch (devpriv->b_Timer2Mode) { + case APCI3120_COUNTER: + + devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + + // stop timer 2 + devpriv->us_OutputRegister = + devpriv-> + us_OutputRegister & APCI3120_DISABLE_ALL_TIMER; + outw(devpriv->us_OutputRegister, + dev->iobase + APCI3120_WR_ADDRESS); + + //stop timer 0 and timer 1 + i_APCI3120_StopCyclicAcquisition(dev, s); + devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; + + //UPDATE-0.7.57->0.7.68comedi_done(dev,s); + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + + break; + + case APCI3120_TIMER: + + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + break; + + case APCI3120_WATCHDOG: + + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + break; + + default: + + // disable Timer Interrupt + + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & + APCI3120_DISABLE_TIMER_INT; + + outb(devpriv->b_ModeSelectRegister, + dev->iobase + APCI3120_WRITE_MODE_SELECT); + + } + + b_DummyRead = inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER); + + } + + if ((int_daq & 0x4) && (devpriv->b_InterruptMode == APCI3120_DMA_MODE)) { + if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) { + + /****************************/ + /* Clear Timer Write TC INT */ + /****************************/ + + outl(APCI3120_CLEAR_WRITE_TC_INT, + devpriv->i_IobaseAmcc + + APCI3120_AMCC_OP_REG_INTCSR); + + /************************************/ + /* Clears the timer status register */ + /************************************/ + inw(dev->iobase + APCI3120_TIMER_STATUS_REGISTER); + v_APCI3120_InterruptDma(irq, d); // do some data transfer + } else { + /* Stops the Timer */ + outw(devpriv-> + us_OutputRegister & APCI3120_DISABLE_TIMER0 & + APCI3120_DISABLE_TIMER1, + dev->iobase + APCI3120_WR_ADDRESS); + } + + } + + return; +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InterruptHandleEos(struct comedi_device *dev) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : This function handles EOS interrupt. | +| This function copies the acquired data(from FIFO) | +| to Comedi buffer. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| | +| | ++----------------------------------------------------------------------------+ +| Return Value : 0 | +| | ++----------------------------------------------------------------------------+ +*/ + +/* + * int i_APCI3120_InterruptHandleEos(struct comedi_device *dev) +{ + int n_chan,i; + short *data; + struct comedi_subdevice *s=dev->subdevices+0; + struct comedi_async *async = s->async; + data=async->data+async->buf_int_ptr; + n_chan=devpriv->ui_AiNbrofChannels; + + for(i=0;iiobase+0); + } + async->buf_int_count+=n_chan*sizeof(short); + async->buf_int_ptr+=n_chan*sizeof(short); + comedi_eos(dev,s); + if (s->async->buf_int_ptr>=s->async->data_len) // for buffer rool over + { +*//* buffer rollover */ +/* s->async->buf_int_ptr=0; + comedi_eobuf(dev,s); + } + return 0; +}*/ +int i_APCI3120_InterruptHandleEos(struct comedi_device * dev) +{ + int n_chan, i; + struct comedi_subdevice *s = dev->subdevices + 0; + int err = 1; + + n_chan = devpriv->ui_AiNbrofChannels; + + s->async->events = 0; + + for (i = 0; i < n_chan; i++) + err &= comedi_buf_put(s->async, inw(dev->iobase + 0)); + + s->async->events |= COMEDI_CB_EOS; + + if (err == 0) + s->async->events |= COMEDI_CB_OVERFLOW; + + comedi_event(dev, s); + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : void v_APCI3120_InterruptDma(int irq, void *d) | +| | ++----------------------------------------------------------------------------+ +| Task : This is a handler for the DMA interrupt | +| This function copies the data to Comedi Buffer. | +| For continuous DMA it reinitializes the DMA operation. | +| For single mode DMA it stop the acquisition. | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq, void *d | +| | ++----------------------------------------------------------------------------+ +| Return Value : void | +| | ++----------------------------------------------------------------------------+ +*/ + +void v_APCI3120_InterruptDma(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + unsigned int next_dma_buf, samplesinbuf; + unsigned long low_word, high_word, var; + + UINT ui_Tmp; + samplesinbuf = + devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] - + inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC); + + if (samplesinbuf < + devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) { + comedi_error(dev, "Interrupted DMA transfer!"); + } + if (samplesinbuf & 1) { + comedi_error(dev, "Odd count of bytes in DMA ring!"); + i_APCI3120_StopCyclicAcquisition(dev, s); + devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; + + return; + } + samplesinbuf = samplesinbuf >> 1; // number of received samples + if (devpriv->b_DmaDoubleBuffer) { + // switch DMA buffers if is used double buffering + next_dma_buf = 1 - devpriv->ui_DmaActualBuffer; + + ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO; + outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS); + + // changed since 16 bit interface for add on + outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW, + devpriv->i_IobaseAddon + 2); + outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2); // 0x1000 is out putted in windows driver + + var = devpriv->ul_DmaBufferHw[next_dma_buf]; + low_word = var & 0xffff; + var = devpriv->ul_DmaBufferHw[next_dma_buf]; + high_word = var / 65536; + + /* DMA Start Adress Low */ + outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0); + outw(low_word, devpriv->i_IobaseAddon + 2); + + /* DMA Start Adress High */ + outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0); + outw(high_word, devpriv->i_IobaseAddon + 2); + + var = devpriv->ui_DmaBufferUsesize[next_dma_buf]; + low_word = var & 0xffff; + var = devpriv->ui_DmaBufferUsesize[next_dma_buf]; + high_word = var / 65536; + + /* Nbr of acquisition LOW */ + outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0); + outw(low_word, devpriv->i_IobaseAddon + 2); + + /* Nbr of acquisition HIGH */ + outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0); + outw(high_word, devpriv->i_IobaseAddon + 2); + + // To configure A2P FIFO + // ENABLE A2P FIFO WRITE AND ENABLE AMWEN + // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 + outw(3, devpriv->i_IobaseAddon + 4); + //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) + outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 | + APCI3120_ENABLE_WRITE_TC_INT), + devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); + + } +/*UPDATE-0.7.57->0.7.68 + ptr=(short *)devpriv->ul_DmaBufferVirtual[devpriv->ui_DmaActualBuffer]; + + + // if there is not enough space left in the buffer to copy all data contained in the DMABufferVirtual + if(s->async->buf_int_ptr+samplesinbuf*sizeof(short)>=devpriv->ui_AiDataLength) + { + m=(devpriv->ui_AiDataLength-s->async->buf_int_ptr)/sizeof(short); + v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,m); + s->async->buf_int_count+=m*sizeof(short); + ptr+=m*sizeof(short); + samplesinbuf-=m; + s->async->buf_int_ptr=0; + comedi_eobuf(dev,s); + } + + if (samplesinbuf) + { + v_APCI3120_InterruptDmaMoveBlock16bit(dev,s,(void *)ptr,((void *)(devpriv->AiData))+s->async->buf_int_ptr,samplesinbuf); + + s->async->buf_int_count+=samplesinbuf*sizeof(short); + s->async->buf_int_ptr+=samplesinbuf*sizeof(short); + if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS)) + { + comedi_bufcheck(dev,s); + } + } + if (!devpriv->b_AiContinuous) + if ( devpriv->ui_AiActualScan>=devpriv->ui_AiNbrofScans ) + { + // all data sampled + i_APCI3120_StopCyclicAcquisition(dev,s); + devpriv->b_AiCyclicAcquisition=APCI3120_DISABLE; + //DPRINTK("\n Single DMA completed..\n"); + comedi_done(dev,s); + return; + } +*/ + if (samplesinbuf) { + v_APCI3120_InterruptDmaMoveBlock16bit(dev, s, + devpriv->ul_DmaBufferVirtual[devpriv-> + ui_DmaActualBuffer], samplesinbuf); + + if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS)) { + s->async->events |= COMEDI_CB_EOS; + comedi_event(dev, s); + } + } + if (!devpriv->b_AiContinuous) + if (devpriv->ui_AiActualScan >= devpriv->ui_AiNbrofScans) { + // all data sampled + i_APCI3120_StopCyclicAcquisition(dev, s); + devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE; + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + return; + } + + if (devpriv->b_DmaDoubleBuffer) { // switch dma buffers + devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer; + } else { + // restart DMA if is not used double buffering + //ADDED REINITIALISE THE DMA + ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO; + outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS); + + // changed since 16 bit interface for add on + outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW, + devpriv->i_IobaseAddon + 2); + outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0); + outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2); // + // A2P FIFO MANAGEMENT + // A2P fifo reset & transfer control enable + outl(APCI3120_A2P_FIFO_MANAGEMENT, + devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR); + + var = devpriv->ul_DmaBufferHw[0]; + low_word = var & 0xffff; + var = devpriv->ul_DmaBufferHw[0]; + high_word = var / 65536; + outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0); + outw(low_word, devpriv->i_IobaseAddon + 2); + outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0); + outw(high_word, devpriv->i_IobaseAddon + 2); + + var = devpriv->ui_DmaBufferUsesize[0]; + low_word = var & 0xffff; //changed + var = devpriv->ui_DmaBufferUsesize[0]; + high_word = var / 65536; + outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0); + outw(low_word, devpriv->i_IobaseAddon + 2); + outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0); + outw(high_word, devpriv->i_IobaseAddon + 2); + + // To configure A2P FIFO + //ENABLE A2P FIFO WRITE AND ENABLE AMWEN + // AMWEN_ENABLE | A2P_FIFO_WRITE_ENABLE (0x01|0x02)=0x03 + outw(3, devpriv->i_IobaseAddon + 4); + //initialise end of dma interrupt AINT_WRITE_COMPL = ENABLE_WRITE_TC_INT(ADDI) + outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 | + APCI3120_ENABLE_WRITE_TC_INT), + devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR); + } +} + +/* ++----------------------------------------------------------------------------+ +| Function name :void v_APCI3120_InterruptDmaMoveBlock16bit(comedi_device| +|*dev,struct comedi_subdevice *s,short *dma,short *data,int n) | +| | ++----------------------------------------------------------------------------+ +| Task : This function copies the data from DMA buffer to the | +| Comedi buffer | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| short *dma | +| short *data,int n | ++----------------------------------------------------------------------------+ +| Return Value : void | +| | ++----------------------------------------------------------------------------+ +*/ + +/*void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n) +{ + int i,j,m; + + j=s->async->cur_chan; + m=devpriv->ui_AiActualScanPosition; + for(i=0;i=devpriv->ui_AiNbrofChannels) + { + m+=j; + j=0; + if(m>=devpriv->ui_AiScanLength) + { + m=0; + devpriv->ui_AiActualScan++; + if (devpriv->ui_AiFlags & TRIG_WAKE_EOS) +;//UPDATE-0.7.57->0.7.68 comedi_eos(dev,s); + } + } + } + devpriv->ui_AiActualScanPosition=m; + s->async->cur_chan=j; + +} +*/ +void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device * dev, + struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples) +{ + devpriv->ui_AiActualScan += + (s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength; + s->async->cur_chan += num_samples; + s->async->cur_chan %= devpriv->ui_AiScanLength; + + cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short)); +} + +/* ++----------------------------------------------------------------------------+ +| TIMER SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, | +| struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task :Configure Timer 2 | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | +| | +| data[0]= TIMER configure as timer | +| = WATCHDOG configure as watchdog | +| data[1] = Timer constant | +| data[2] = Timer2 interrupt (1)enable or(0) disable | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnConfigTimer(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + UINT ui_Timervalue2; + USHORT us_TmpValue; + BYTE b_Tmp; + + if (!data[1]) + comedi_error(dev, "config:No timer constant !"); + + devpriv->b_Timer2Interrupt = (BYTE) data[2]; // save info whether to enable or disable interrupt + + ui_Timervalue2 = data[1] / 1000; // convert nano seconds to u seconds + + //this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(BYTE)data[0]); + us_TmpValue = (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS); + + //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 + // and calculate the time value to set in the timer + if ((us_TmpValue & 0x00B0) == 0x00B0 + || !strcmp(this_board->pc_DriverName, "apci3001")) { + //Calculate the time value to set in the timer + ui_Timervalue2 = ui_Timervalue2 / 50; + } else { + //Calculate the time value to set in the timer + ui_Timervalue2 = ui_Timervalue2 / 70; + } + + //Reset gate 2 of Timer 2 to disable it (Set Bit D14 to 0) + devpriv->us_OutputRegister = + devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2; + outw(devpriv->us_OutputRegister, devpriv->iobase + APCI3120_WR_ADDRESS); + + // Disable TIMER Interrupt + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF; + + // Disable Eoc and Eos Interrupts + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT & + APCI3120_DISABLE_EOS_INT; + outb(devpriv->b_ModeSelectRegister, + devpriv->iobase + APCI3120_WRITE_MODE_SELECT); + if (data[0] == APCI3120_TIMER) //initialize timer + { + + //devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister| APCI3120_ENABLE_TIMER_INT ; + //outb(devpriv->b_ModeSelectRegister,devpriv->iobase+APCI3120_WRITE_MODE_SELECT); + + //Set the Timer 2 in mode 2(Timer) + devpriv->b_TimerSelectMode = + (devpriv-> + b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_2; + outb(devpriv->b_TimerSelectMode, + devpriv->iobase + APCI3120_TIMER_CRT1); + + //Configure the timer 2 for writing the LOW WORD of timer is Delay value + //You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0 + //you can set the digital output and configure the timer 2,and if you don't make this, digital output + //are erase (Set to 0) + + //Writing LOW WORD + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + outw(LOWORD(ui_Timervalue2), + devpriv->iobase + APCI3120_TIMER_VALUE); + + //Writing HIGH WORD + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + outw(HIWORD(ui_Timervalue2), + devpriv->iobase + APCI3120_TIMER_VALUE); + // timer2 in Timer mode enabled + devpriv->b_Timer2Mode = APCI3120_TIMER; + + } else // Initialize Watch dog + { + + //Set the Timer 2 in mode 5(Watchdog) + + devpriv->b_TimerSelectMode = + (devpriv-> + b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_5; + outb(devpriv->b_TimerSelectMode, + devpriv->iobase + APCI3120_TIMER_CRT1); + + //Configure the timer 2 for writing the LOW WORD of timer is Delay value + //You must make a b_tmp variable with DigitalOutPutRegister because at Address_1+APCI3120_TIMER_CRT0 + //you can set the digital output and configure the timer 2,and if you don't make this, digital output + //are erase (Set to 0) + + //Writing LOW WORD + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + outw(LOWORD(ui_Timervalue2), + devpriv->iobase + APCI3120_TIMER_VALUE); + + //Writing HIGH WORD + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + + outw(HIWORD(ui_Timervalue2), + devpriv->iobase + APCI3120_TIMER_VALUE); + //watchdog enabled + devpriv->b_Timer2Mode = APCI3120_WATCHDOG; + + } + + return insn->n; + +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, | +| struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : To start and stop the timer | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | +| | +| data[0] = 1 (start) | +| data[0] = 0 (stop ) | +| data[0] = 2 (write new value) | +| data[1]= new value | +| | +| devpriv->b_Timer2Mode = 0 DISABLE | +| 1 Timer | +| 2 Watch dog | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnWriteTimer(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + UINT ui_Timervalue2 = 0; + USHORT us_TmpValue; + BYTE b_Tmp; + + if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG) + && (devpriv->b_Timer2Mode != APCI3120_TIMER)) { + comedi_error(dev, "\nwrite:timer2 not configured "); + return -EINVAL; + } + + if (data[0] == 2) // write new value + { + if (devpriv->b_Timer2Mode != APCI3120_TIMER) { + comedi_error(dev, + "write :timer2 not configured in TIMER MODE"); + return -EINVAL; + } + + if (data[1]) + ui_Timervalue2 = data[1]; + else + ui_Timervalue2 = 0; + } + + //this_board->i_hwdrv_InsnWriteTimer(dev,data[0],ui_Timervalue2); + + switch (data[0]) { + case APCI3120_START: + + // Reset FC_TIMER BIT + inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER); + if (devpriv->b_Timer2Mode == APCI3120_TIMER) //start timer + { + //Enable Timer + devpriv->b_ModeSelectRegister = + devpriv->b_ModeSelectRegister & 0x0B; + } else //start watch dog + { + //Enable WatchDog + devpriv->b_ModeSelectRegister = + (devpriv-> + b_ModeSelectRegister & 0x0B) | + APCI3120_ENABLE_WATCHDOG; + } + + //enable disable interrupt + if ((devpriv->b_Timer2Interrupt) == APCI3120_ENABLE) { + + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister | + APCI3120_ENABLE_TIMER_INT; + // save the task structure to pass info to user + devpriv->tsk_Current = current; + } else { + + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & + APCI3120_DISABLE_TIMER_INT; + } + outb(devpriv->b_ModeSelectRegister, + devpriv->iobase + APCI3120_WRITE_MODE_SELECT); + + if (devpriv->b_Timer2Mode == APCI3120_TIMER) //start timer + { + //For Timer mode is Gate2 must be activated **timer started + devpriv->us_OutputRegister = + devpriv-> + us_OutputRegister | APCI3120_ENABLE_TIMER2; + outw(devpriv->us_OutputRegister, + devpriv->iobase + APCI3120_WR_ADDRESS); + } + + break; + + case APCI3120_STOP: + if (devpriv->b_Timer2Mode == APCI3120_TIMER) { + //Disable timer + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & + APCI3120_DISABLE_TIMER_COUNTER; + } else { + //Disable WatchDog + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & + APCI3120_DISABLE_WATCHDOG; + } + // Disable timer interrupt + devpriv->b_ModeSelectRegister = + devpriv-> + b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT; + + // Write above states to register + outb(devpriv->b_ModeSelectRegister, + devpriv->iobase + APCI3120_WRITE_MODE_SELECT); + + // Reset Gate 2 + devpriv->us_OutputRegister = + devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER_INT; + outw(devpriv->us_OutputRegister, + devpriv->iobase + APCI3120_WR_ADDRESS); + + // Reset FC_TIMER BIT + inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER); + + // Disable timer + //devpriv->b_Timer2Mode=APCI3120_DISABLE; + + break; + + case 2: //write new value to Timer + if (devpriv->b_Timer2Mode != APCI3120_TIMER) { + comedi_error(dev, + "write :timer2 not configured in TIMER MODE"); + return -EINVAL; + } + // ui_Timervalue2=data[1]; // passed as argument + us_TmpValue = + (USHORT) inw(devpriv->iobase + APCI3120_RD_STATUS); + + //EL250804: Testing if board APCI3120 have the new Quartz or if it is an APCI3001 + // and calculate the time value to set in the timer + if ((us_TmpValue & 0x00B0) == 0x00B0 + || !strcmp(this_board->pc_DriverName, "apci3001")) { + //Calculate the time value to set in the timer + ui_Timervalue2 = ui_Timervalue2 / 50; + } else { + //Calculate the time value to set in the timer + ui_Timervalue2 = ui_Timervalue2 / 70; + } + //Writing LOW WORD + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + + outw(LOWORD(ui_Timervalue2), + devpriv->iobase + APCI3120_TIMER_VALUE); + + //Writing HIGH WORD + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + + outw(HIWORD(ui_Timervalue2), + devpriv->iobase + APCI3120_TIMER_VALUE); + + break; + default: + return -EINVAL; // Not a valid input + } + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function name : int i_APCI3120_InsnReadTimer(struct comedi_device *dev, | +| struct comedi_subdevice *s,struct comedi_insn *insn, unsigned int *data) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : read the Timer value | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | +| | ++----------------------------------------------------------------------------+ +| Return Value : | +| for Timer: data[0]= Timer constant | +| | +| for watchdog: data[0]=0 (still running) | +| data[0]=1 (run down) | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3120_InsnReadTimer(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_Tmp; + USHORT us_TmpValue, us_TmpValue_2, us_StatusValue; + + if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG) + && (devpriv->b_Timer2Mode != APCI3120_TIMER)) { + comedi_error(dev, "\nread:timer2 not configured "); + } + + //this_board->i_hwdrv_InsnReadTimer(dev,data); + if (devpriv->b_Timer2Mode == APCI3120_TIMER) { + + //Read the LOW WORD of Timer 2 register + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_LOW_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + + us_TmpValue = inw(devpriv->iobase + APCI3120_TIMER_VALUE); + + //Read the HIGH WORD of Timer 2 register + b_Tmp = ((devpriv-> + b_DigitalOutputRegister) & 0xF0) | + APCI3120_SELECT_TIMER_2_HIGH_WORD; + outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0); + + us_TmpValue_2 = inw(devpriv->iobase + APCI3120_TIMER_VALUE); + + // combining both words + data[0] = (UINT) ((us_TmpValue) | ((us_TmpValue_2) << 16)); + + } else // Read watch dog status + { + + us_StatusValue = inw(devpriv->iobase + APCI3120_RD_STATUS); + us_StatusValue = + ((us_StatusValue & APCI3120_FC_TIMER) >> 12) & 1; + if (us_StatusValue == 1) { + // RESET FC_TIMER BIT + inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER); + } + data[0] = us_StatusValue; // when data[0] = 1 then the watch dog has rundown + } + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| DIGITAL INPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, | +| struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) | +| | +| | ++----------------------------------------------------------------------------+ +| Task : Reads the value of the specified Digital input channel| +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + UINT ui_Chan, ui_TmpValue; + + ui_Chan = CR_CHAN(insn->chanspec); // channel specified + + //this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data); + if (ui_Chan >= 0 && ui_Chan <= 3) { + ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS); + + // since only 1 channel reqd to bring it to last bit it is rotated + // 8 +(chan - 1) times then ANDed with 1 for last bit. + *data = (ui_TmpValue >> (ui_Chan + 8)) & 1; + //return 0; + } else { + // comedi_error(dev," chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + } + return insn->n; + +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, | +|struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Reads the value of the Digital input Port i.e.4channels| +| value is returned in data[0] | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3120_InsnBitsDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_TmpValue; + ui_TmpValue = (UINT) inw(devpriv->iobase + APCI3120_RD_STATUS); + /***** state of 4 channels in the 11, 10, 9, 8 bits of status reg + rotated right 8 times to bring them to last four bits + ANDed with oxf for value. + *****/ + + *data = (ui_TmpValue >> 8) & 0xf; + //this_board->i_hwdrv_InsnBitsDigitalInput(dev,data); + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| DIGITAL OUTPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device | +| *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task :Configure the output memory ON or OFF | +| | ++----------------------------------------------------------------------------+ +| Input Parameters :struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + + if ((data[0] != 0) && (data[0] != 1)) { + comedi_error(dev, + "Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } + if (data[0]) { + devpriv->b_OutputMemoryStatus = APCI3120_ENABLE; + + } else { + devpriv->b_OutputMemoryStatus = APCI3120_DISABLE; + devpriv->b_DigitalOutputRegister = 0; + } + if (!devpriv->b_OutputMemoryStatus) { + ui_Temp = 0; + + } //if(!devpriv->b_OutputMemoryStatus ) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, | +| struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : write diatal output port | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | + data[0] Value to be written + data[1] :1 Set digital o/p ON + data[1] 2 Set digital o/p OFF with memory ON ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device * dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) { + + comedi_error(dev, "Data is not valid !!! \n"); + return -EINVAL; + } + + switch (data[1]) { + case 1: + data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister; + break; + + case 2: + data[0] = data[0]; + break; + default: + printk("\nThe parameter passed is in error \n"); + return -EINVAL; + } // switch(data[1]) + outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT); + + devpriv->b_DigitalOutputRegister = data[0] & 0xF0; + + return insn->n; + +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,| +|struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Write digiatl output | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | + data[0] Value to be written + data[1] :1 Set digital o/p ON + data[1] 2 Set digital o/p OFF with memory ON ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + + UINT ui_Temp1; + + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + + if ((data[0] != 0) && (data[0] != 1)) { + comedi_error(dev, + "Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } + if ((ui_NoOfChannel > (this_board->i_NbrDoChannel - 1)) + || (ui_NoOfChannel < 0)) { + comedi_error(dev, + "This board doesn't have specified channel !!! \n"); + return -EINVAL; + } + + switch (data[1]) { + case 1: + data[0] = (data[0] << ui_NoOfChannel); +//ES05 data[0]=(data[0]<<4)|ui_Temp; + data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister; + break; + + case 2: + data[0] = ~data[0] & 0x1; + ui_Temp1 = 1; + ui_Temp1 = ui_Temp1 << ui_NoOfChannel; + ui_Temp1 = ui_Temp1 << 4; +//ES05 ui_Temp=ui_Temp|ui_Temp1; + devpriv->b_DigitalOutputRegister = + devpriv->b_DigitalOutputRegister | ui_Temp1; + + data[0] = (data[0] << ui_NoOfChannel) ^ 0xf; + data[0] = data[0] << 4; +//ES05 data[0]=data[0]& ui_Temp; + data[0] = data[0] & devpriv->b_DigitalOutputRegister; + break; + default: + printk("\nThe parameter passed is in error \n"); + return -EINVAL; + } // switch(data[1]) + outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT); + +//ES05 ui_Temp=data[0] & 0xf0; + devpriv->b_DigitalOutputRegister = data[0] & 0xf0; + return (insn->n); + +} + +/* ++----------------------------------------------------------------------------+ +| ANALOG OUTPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,| +|struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) | +| | ++----------------------------------------------------------------------------+ +| Task : Write analog output | +| | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | +| struct comedi_subdevice *s | +| struct comedi_insn *insn | +| unsigned int *data | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + UINT ui_Range, ui_Channel; + USHORT us_TmpValue; + + ui_Range = CR_RANGE(insn->chanspec); + ui_Channel = CR_CHAN(insn->chanspec); + + //this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]); + if (ui_Range) // if 1 then unipolar + { + + if (data[0] != 0) + data[0] = + ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 << + 13) | (data[0] + 8191)); + else + data[0] = + ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 << + 13) | 8192); + + } else // if 0 then bipolar + { + data[0] = + ((((ui_Channel & 0x03) << 14) & 0xC000) | (0 << 13) | + data[0]); + + } + + //out put n values at the given channel. + // rt_printk("\nwaiting for DA_READY BIT"); + do //Waiting of DA_READY BIT + { + us_TmpValue = + ((USHORT) inw(devpriv->iobase + + APCI3120_RD_STATUS)) & 0x0001; + } while (us_TmpValue != 0x0001); + + if (ui_Channel <= 3) + // for channel 0-3 out at the register 1 (wrDac1-8) + // data[i] typecasted to ushort since word write is to be done + outw((USHORT) data[0], + devpriv->iobase + APCI3120_ANALOG_OUTPUT_1); + else + // for channel 4-7 out at the register 2 (wrDac5-8) + //data[i] typecasted to ushort since word write is to be done + outw((USHORT) data[0], + devpriv->iobase + APCI3120_ANALOG_OUTPUT_2); + + return insn->n; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h new file mode 100644 index 000000000000..59d5d87a845b --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.h @@ -0,0 +1,241 @@ + +// hwdrv_apci3120.h + +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +// comedi related defines + +//ANALOG INPUT RANGE +static const struct comedi_lrange range_apci3120_ai = { 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1) + } +}; + +// ANALOG OUTPUT RANGE +static const struct comedi_lrange range_apci3120_ao = { 2, { + BIP_RANGE(10), + UNI_RANGE(10) + } +}; + +#define APCI3120_BIPOLAR_RANGES 4 // used for test on mixture of BIP/UNI ranges + +#define APCI3120_BOARD_VENDOR_ID 0x10E8 +#define APCI3120_ADDRESS_RANGE 16 + +#define APCI3120_DISABLE 0 +#define APCI3120_ENABLE 1 + +#define APCI3120_START 1 +#define APCI3120_STOP 0 + +#define APCI3120_EOC_MODE 1 +#define APCI3120_EOS_MODE 2 +#define APCI3120_DMA_MODE 3 + +//DIGITAL INPUT-OUTPUT DEFINE + +#define APCI3120_DIGITAL_OUTPUT 0x0D +#define APCI3120_RD_STATUS 0x02 +#define APCI3120_RD_FIFO 0x00 + +// digital output insn_write ON /OFF selection +#define APCI3120_SET4DIGITALOUTPUTON 1 +#define APCI3120_SET4DIGITALOUTPUTOFF 0 + +// analog output SELECT BIT +#define APCI3120_ANALOG_OP_CHANNEL_1 0x0000 +#define APCI3120_ANALOG_OP_CHANNEL_2 0x4000 +#define APCI3120_ANALOG_OP_CHANNEL_3 0x8000 +#define APCI3120_ANALOG_OP_CHANNEL_4 0xC000 +#define APCI3120_ANALOG_OP_CHANNEL_5 0x0000 +#define APCI3120_ANALOG_OP_CHANNEL_6 0x4000 +#define APCI3120_ANALOG_OP_CHANNEL_7 0x8000 +#define APCI3120_ANALOG_OP_CHANNEL_8 0xC000 + +// Enable external trigger bit in nWrAddress +#define APCI3120_ENABLE_EXT_TRIGGER 0x8000 + +//ANALOG OUTPUT AND INPUT DEFINE +#define APCI3120_UNIPOLAR 0x80 //$$ RAM sequence polarity BIT +#define APCI3120_BIPOLAR 0x00 //$$ RAM sequence polarity BIT +#define APCI3120_ANALOG_OUTPUT_1 0x08 // (ADDRESS ) +#define APCI3120_ANALOG_OUTPUT_2 0x0A // (ADDRESS ) +#define APCI3120_1_GAIN 0x00 //$$ RAM sequence Gain Bits for gain 1 +#define APCI3120_2_GAIN 0x10 //$$ RAM sequence Gain Bits for gain 2 +#define APCI3120_5_GAIN 0x20 //$$ RAM sequence Gain Bits for gain 5 +#define APCI3120_10_GAIN 0x30 //$$ RAM sequence Gain Bits for gain 10 +#define APCI3120_SEQ_RAM_ADDRESS 0x06 //$$ EARLIER NAMED APCI3120_FIFO_ADDRESS +#define APCI3120_RESET_FIFO 0x0C //(ADDRESS) +#define APCI3120_TIMER_0_MODE_2 0x01 //$$ Bits for timer mode +#define APCI3120_TIMER_0_MODE_4 0x2 +#define APCI3120_SELECT_TIMER_0_WORD 0x00 +#define APCI3120_ENABLE_TIMER0 0x1000 //$$Gatebit 0 in nWrAddress +#define APCI3120_CLEAR_PR 0xF0FF +#define APCI3120_CLEAR_PA 0xFFF0 +#define APCI3120_CLEAR_PA_PR (APCI3120_CLEAR_PR & APCI3120_CLEAR_PA) + +// nWrMode_Select +#define APCI3120_ENABLE_SCAN 0x8 //$$ bit in nWrMode_Select +#define APCI3120_DISABLE_SCAN (~APCI3120_ENABLE_SCAN) +#define APCI3120_ENABLE_EOS_INT 0x2 //$$ bit in nWrMode_Select + +#define APCI3120_DISABLE_EOS_INT (~APCI3120_ENABLE_EOS_INT) +#define APCI3120_ENABLE_EOC_INT 0x1 +#define APCI3120_DISABLE_EOC_INT (~APCI3120_ENABLE_EOC_INT) +#define APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER (APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT) +#define APCI3120_DISABLE_ALL_INTERRUPT (APCI3120_DISABLE_TIMER_INT & APCI3120_DISABLE_EOS_INT & APCI3120_DISABLE_EOC_INT) + +//status register bits +#define APCI3120_EOC 0x8000 +#define APCI3120_EOS 0x2000 + +// software trigger dummy register +#define APCI3120_START_CONVERSION 0x02 //(ADDRESS) + +//TIMER DEFINE +#define APCI3120_QUARTZ_A 70 +#define APCI3120_QUARTZ_B 50 +#define APCI3120_TIMER 1 +#define APCI3120_WATCHDOG 2 +#define APCI3120_TIMER_DISABLE 0 +#define APCI3120_TIMER_ENABLE 1 +#define APCI3120_ENABLE_TIMER2 0x4000 //$$ gatebit 2 in nWrAddress +#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2) +#define APCI3120_ENABLE_TIMER_INT 0x04 //$$ ENAIRQ_FC_Bit in nWrModeSelect +#define APCI3120_DISABLE_TIMER_INT (~APCI3120_ENABLE_TIMER_INT) +#define APCI3120_WRITE_MODE_SELECT 0x0E // (ADDRESS) +#define APCI3120_SELECT_TIMER_0_WORD 0x00 +#define APCI3120_SELECT_TIMER_1_WORD 0x01 +#define APCI3120_TIMER_1_MODE_2 0x4 + +//$$ BIT FOR MODE IN nCsTimerCtr1 +#define APCI3120_TIMER_2_MODE_0 0x0 +#define APCI3120_TIMER_2_MODE_2 0x10 +#define APCI3120_TIMER_2_MODE_5 0x30 + +//$$ BIT FOR MODE IN nCsTimerCtr0 +#define APCI3120_SELECT_TIMER_2_LOW_WORD 0x02 +#define APCI3120_SELECT_TIMER_2_HIGH_WORD 0x03 + +#define APCI3120_TIMER_CRT0 0x0D //(ADDRESS for cCsTimerCtr0) +#define APCI3120_TIMER_CRT1 0x0C //(ADDRESS for cCsTimerCtr1) + +#define APCI3120_TIMER_VALUE 0x04 //ADDRESS for nCsTimerWert +#define APCI3120_TIMER_STATUS_REGISTER 0x0D //ADDRESS for delete timer 2 interrupt +#define APCI3120_RD_STATUS 0x02 //ADDRESS +#define APCI3120_WR_ADDRESS 0x00 //ADDRESS +#define APCI3120_ENABLE_WATCHDOG 0x20 //$$BIT in nWrMode_Select +#define APCI3120_DISABLE_WATCHDOG (~APCI3120_ENABLE_WATCHDOG) +#define APCI3120_ENABLE_TIMER_COUNTER 0x10 //$$BIT in nWrMode_Select +#define APCI3120_DISABLE_TIMER_COUNTER (~APCI3120_ENABLE_TIMER_COUNTER) +#define APCI3120_FC_TIMER 0x1000 //bit in status register +#define APCI3120_ENABLE_TIMER0 0x1000 +#define APCI3120_ENABLE_TIMER1 0x2000 +#define APCI3120_ENABLE_TIMER2 0x4000 +#define APCI3120_DISABLE_TIMER0 (~APCI3120_ENABLE_TIMER0) +#define APCI3120_DISABLE_TIMER1 (~APCI3120_ENABLE_TIMER1) +#define APCI3120_DISABLE_TIMER2 (~APCI3120_ENABLE_TIMER2) + +#define APCI3120_TIMER2_SELECT_EOS 0xC0 // ADDED on 20-6 +#define APCI3120_COUNTER 3 // on 20-6 +#define APCI3120_DISABLE_ALL_TIMER ( APCI3120_DISABLE_TIMER0 & APCI3120_DISABLE_TIMER1 & APCI3120_DISABLE_TIMER2 ) // on 20-6 + +#define MAX_ANALOGINPUT_CHANNELS 32 + +typedef struct { + BYTE b_Type; /* EOC or EOS */ + BYTE b_InterruptFlag; /* Interrupt use or not */ + UINT ui_ConvertTiming; /* Selection of the convertion time */ + BYTE b_NbrOfChannel; /* Number of channel to read */ + UINT ui_ChannelList[MAX_ANALOGINPUT_CHANNELS]; /* Number of the channel to be read */ + UINT ui_RangeList[MAX_ANALOGINPUT_CHANNELS]; /* Gain of each channel */ + +} str_AnalogReadInformation; + +// Function Declaration For APCI-3120 + +// Internal functions +int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s, + int n_chan, unsigned int *chanlist, char check); +int i_APCI3120_ExttrigEnable(struct comedi_device *dev); +int i_APCI3120_ExttrigDisable(struct comedi_device *dev); +int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s); +int i_APCI3120_Reset(struct comedi_device *dev); +int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev, + struct comedi_subdevice *s); +// Interrupt functions +void v_APCI3120_Interrupt(int irq, void *d); +//UPDATE-0.7.57->0.7.68 void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,struct comedi_subdevice *s,short *dma,short *data,int n); +void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev, + struct comedi_subdevice *s, + short *dma_buffer, + unsigned int num_samples); +int i_APCI3120_InterruptHandleEos(struct comedi_device *dev); +void v_APCI3120_InterruptDma(int irq, void *d); + +// TIMER + +int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//DI +// for di read + +int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//DO +//int i_APCI3120_WriteDigitalOutput(struct comedi_device *dev, BYTE data); +int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data); +int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//AO +//int i_APCI3120_Write1AnalogValue(struct comedi_device *dev,UINT ui_Range,UINT ui_Channel,UINT data ); +int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//AI HArdware layer + +int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd); +int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s); +//int i_APCI3120_CancelAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s); +int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c new file mode 100644 index 000000000000..1ff66bee548d --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -0,0 +1,3642 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/* + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-3200 | Compiler : GCC | + | Module name : hwdrv_apci3200.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-3200 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | 02.07.04 | J. Krauth | Modification from the driver in order to | + | | | correct some errors when using several boards. | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ + | 26.10.04 | J. Krauth | - Update for COMEDI 0.7.68 | + | | | - Read eeprom value | + | | | - Append APCI-3300 | + +----------+-----------+------------------------------------------------+ +*/ + +/* + +----------------------------------------------------------------------------+ + | Included files | + +----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci3200.h" +//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values +#include "addi_amcc_S5920.h" +//#define PRINT_INFO + +//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + +//BEGIN JK 06.07.04: Management of sevrals boards +/* + INT i_CJCAvailable=1; + INT i_CJCPolarity=0; + INT i_CJCGain=2;//changed from 0 to 2 + INT i_InterruptFlag=0; + INT i_ADDIDATAPolarity; + INT i_ADDIDATAGain; + INT i_AutoCalibration=0; //: auto calibration + INT i_ADDIDATAConversionTime; + INT i_ADDIDATAConversionTimeUnit; + INT i_ADDIDATAType; + INT i_ChannelNo; + INT i_ChannelCount=0; + INT i_ScanType; + INT i_FirstChannel; + INT i_LastChannel; + INT i_Sum=0; + INT i_Offset; + UINT ui_Channel_num=0; + static int i_Count=0; + INT i_Initialised=0; + UINT ui_InterruptChannelValue[96]; //Buffer +*/ +str_BoardInfos s_BoardInfos[100]; // 100 will be the max number of boards to be used +//END JK 06.07.04: Management of sevrals boards + +//Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + +/*+----------------------------------------------------------------------------+*/ +/*| Function Name : INT i_AddiHeaderRW_ReadEeprom |*/ +/*| (INT i_NbOfWordsToRead, |*/ +/*| DWORD dw_PCIBoardEepromAddress, |*/ +/*| WORD w_EepromStartAddress, |*/ +/*| PWORD pw_DataRead) |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Task : Read word from the 5920 eeprom. |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Input Parameters : INT i_NbOfWordsToRead : Nbr. of word to read |*/ +/*| DWORD dw_PCIBoardEepromAddress : Address of the eeprom |*/ +/*| WORD w_EepromStartAddress : Eeprom strat address |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Output Parameters : PWORD pw_DataRead : Read data |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Return Value : - |*/ +/*+----------------------------------------------------------------------------+*/ + +INT i_AddiHeaderRW_ReadEeprom(INT i_NbOfWordsToRead, + DWORD dw_PCIBoardEepromAddress, + WORD w_EepromStartAddress, PWORD pw_DataRead) +{ + DWORD dw_eeprom_busy = 0; + INT i_Counter = 0; + INT i_WordCounter; + INT i; + BYTE pb_ReadByte[1]; + BYTE b_ReadLowByte = 0; + BYTE b_ReadHighByte = 0; + BYTE b_SelectedAddressLow = 0; + BYTE b_SelectedAddressHigh = 0; + WORD w_ReadWord = 0; + + for (i_WordCounter = 0; i_WordCounter < i_NbOfWordsToRead; + i_WordCounter++) { + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + for (i_Counter = 0; i_Counter < 2; i_Counter++) { + b_SelectedAddressLow = (w_EepromStartAddress + i_Counter) % 256; //Read the low 8 bit part + b_SelectedAddressHigh = (w_EepromStartAddress + i_Counter) / 256; //Read the high 8 bit part + + //Select the load low address mode + outb(NVCMD_LOAD_LOW, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 3); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Load the low address + outb(b_SelectedAddressLow, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 2); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Select the load high address mode + outb(NVCMD_LOAD_HIGH, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 3); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Load the high address + outb(b_SelectedAddressHigh, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 2); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Select the READ mode + outb(NVCMD_BEGIN_READ, + dw_PCIBoardEepromAddress + AMCC_OP_REG_MCSR + + 3); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Read data into the EEPROM + *pb_ReadByte = + inb(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR + 2); + + //Wait on busy + do { + dw_eeprom_busy = + inl(dw_PCIBoardEepromAddress + + AMCC_OP_REG_MCSR); + dw_eeprom_busy = dw_eeprom_busy & EEPROM_BUSY; + } + while (dw_eeprom_busy == EEPROM_BUSY); + + //Select the upper address part + if (i_Counter == 0) { + b_ReadLowByte = pb_ReadByte[0]; + } else { + b_ReadHighByte = pb_ReadByte[0]; + } + + //Sleep + for (i = 0; i < 10000; i++) ; + + } + w_ReadWord = + (b_ReadLowByte | (((unsigned short)b_ReadHighByte) * + 256)); + + pw_DataRead[i_WordCounter] = w_ReadWord; + + w_EepromStartAddress += 2; // to read the next word + + } // for (...) i_NbOfWordsToRead + return (0); +} + +/*+----------------------------------------------------------------------------+*/ +/*| Function Name : void v_GetAPCI3200EepromCalibrationValue (void) |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Task : Read calibration value from the APCI-3200 eeprom. |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Input Parameters : - |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Output Parameters : - |*/ +/*+----------------------------------------------------------------------------+*/ +/*| Return Value : - |*/ +/*+----------------------------------------------------------------------------+*/ + +void v_GetAPCI3200EepromCalibrationValue(DWORD dw_PCIBoardEepromAddress, + str_BoardInfos * BoardInformations) +{ + WORD w_AnalogInputMainHeaderAddress; + WORD w_AnalogInputComponentAddress; + WORD w_NumberOfModuls = 0; + WORD w_CurrentSources[2]; + WORD w_ModulCounter = 0; + WORD w_FirstHeaderSize = 0; + WORD w_NumberOfInputs = 0; + WORD w_CJCFlag = 0; + WORD w_NumberOfGainValue = 0; + WORD w_SingleHeaderAddress = 0; + WORD w_SingleHeaderSize = 0; + WORD w_Input = 0; + WORD w_GainFactorAddress = 0; + WORD w_GainFactorValue[2]; + WORD w_GainIndex = 0; + WORD w_GainValue = 0; + + /*****************************************/ + /** Get the Analog input header address **/ + /*****************************************/ + i_AddiHeaderRW_ReadEeprom(1, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, 0x116, //w_EepromStartAddress: Analog input header address + &w_AnalogInputMainHeaderAddress); + + /*******************************************/ + /** Compute the real analog input address **/ + /*******************************************/ + w_AnalogInputMainHeaderAddress = w_AnalogInputMainHeaderAddress + 0x100; + + /******************************/ + /** Get the number of moduls **/ + /******************************/ + i_AddiHeaderRW_ReadEeprom(1, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, w_AnalogInputMainHeaderAddress + 0x02, //w_EepromStartAddress: Number of conponment + &w_NumberOfModuls); + + for (w_ModulCounter = 0; w_ModulCounter < w_NumberOfModuls; + w_ModulCounter++) { + /***********************************/ + /** Compute the component address **/ + /***********************************/ + w_AnalogInputComponentAddress = + w_AnalogInputMainHeaderAddress + + (w_FirstHeaderSize * w_ModulCounter) + 0x04; + + /****************************/ + /** Read first header size **/ + /****************************/ + i_AddiHeaderRW_ReadEeprom(1, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress, // Address of the first header + &w_FirstHeaderSize); + + w_FirstHeaderSize = w_FirstHeaderSize >> 4; + + /***************************/ + /** Read number of inputs **/ + /***************************/ + i_AddiHeaderRW_ReadEeprom(1, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x06, // Number of inputs for the first modul + &w_NumberOfInputs); + + w_NumberOfInputs = w_NumberOfInputs >> 4; + + /***********************/ + /** Read the CJC flag **/ + /***********************/ + i_AddiHeaderRW_ReadEeprom(1, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x08, // CJC flag + &w_CJCFlag); + + w_CJCFlag = (w_CJCFlag >> 3) & 0x1; // Get only the CJC flag + + /*******************************/ + /** Read number of gain value **/ + /*******************************/ + i_AddiHeaderRW_ReadEeprom(1, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 0x44, // Number of gain value + &w_NumberOfGainValue); + + w_NumberOfGainValue = w_NumberOfGainValue & 0xFF; + + /***********************************/ + /** Compute single header address **/ + /***********************************/ + w_SingleHeaderAddress = + w_AnalogInputComponentAddress + 0x46 + + (((w_NumberOfGainValue / 16) + 1) * 2) + + (6 * w_NumberOfGainValue) + + (4 * (((w_NumberOfGainValue / 16) + 1) * 2)); + + /********************************************/ + /** Read current sources value for input 1 **/ + /********************************************/ + i_AddiHeaderRW_ReadEeprom(1, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, w_SingleHeaderAddress, //w_EepromStartAddress: Single header address + &w_SingleHeaderSize); + + w_SingleHeaderSize = w_SingleHeaderSize >> 4; + + /*************************************/ + /** Read gain factor for the module **/ + /*************************************/ + w_GainFactorAddress = w_AnalogInputComponentAddress; + + for (w_GainIndex = 0; w_GainIndex < w_NumberOfGainValue; + w_GainIndex++) { + /************************************/ + /** Read gain value for the module **/ + /************************************/ + i_AddiHeaderRW_ReadEeprom(1, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + (2 * (1 + (w_NumberOfGainValue / 16))) + (0x02 * w_GainIndex), // Gain value + &w_GainValue); + + BoardInformations->s_Module[w_ModulCounter]. + w_GainValue[w_GainIndex] = w_GainValue; + +# ifdef PRINT_INFO + printk("\n Gain value = %d", + BoardInformations->s_Module[w_ModulCounter]. + w_GainValue[w_GainIndex]); +# endif + + /*************************************/ + /** Read gain factor for the module **/ + /*************************************/ + i_AddiHeaderRW_ReadEeprom(2, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, w_AnalogInputComponentAddress + 70 + ((2 * w_NumberOfGainValue) + (2 * (1 + (w_NumberOfGainValue / 16)))) + (0x04 * w_GainIndex), // Gain factor + w_GainFactorValue); + + BoardInformations->s_Module[w_ModulCounter]. + ul_GainFactor[w_GainIndex] = + (w_GainFactorValue[1] << 16) + + w_GainFactorValue[0]; + +# ifdef PRINT_INFO + printk("\n w_GainFactorValue [%d] = %lu", w_GainIndex, + BoardInformations->s_Module[w_ModulCounter]. + ul_GainFactor[w_GainIndex]); +# endif + } + + /***************************************************************/ + /** Read current source value for each channels of the module **/ + /***************************************************************/ + for (w_Input = 0; w_Input < w_NumberOfInputs; w_Input++) { + /********************************************/ + /** Read current sources value for input 1 **/ + /********************************************/ + i_AddiHeaderRW_ReadEeprom(2, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, + (w_Input * w_SingleHeaderSize) + + w_SingleHeaderAddress + 0x0C, w_CurrentSources); + + /************************************/ + /** Save the current sources value **/ + /************************************/ + BoardInformations->s_Module[w_ModulCounter]. + ul_CurrentSource[w_Input] = + (w_CurrentSources[0] + + ((w_CurrentSources[1] & 0xFFF) << 16)); + +# ifdef PRINT_INFO + printk("\n Current sources [%d] = %lu", w_Input, + BoardInformations->s_Module[w_ModulCounter]. + ul_CurrentSource[w_Input]); +# endif + } + + /***************************************/ + /** Read the CJC current source value **/ + /***************************************/ + i_AddiHeaderRW_ReadEeprom(2, //i_NbOfWordsToRead + dw_PCIBoardEepromAddress, + (w_Input * w_SingleHeaderSize) + w_SingleHeaderAddress + + 0x0C, w_CurrentSources); + + /************************************/ + /** Save the current sources value **/ + /************************************/ + BoardInformations->s_Module[w_ModulCounter]. + ul_CurrentSourceCJC = + (w_CurrentSources[0] + + ((w_CurrentSources[1] & 0xFFF) << 16)); + +# ifdef PRINT_INFO + printk("\n Current sources CJC = %lu", + BoardInformations->s_Module[w_ModulCounter]. + ul_CurrentSourceCJC); +# endif + } +} + +INT i_APCI3200_GetChannelCalibrationValue(struct comedi_device * dev, + unsigned int ui_Channel_num, unsigned int * CJCCurrentSource, + unsigned int * ChannelCurrentSource, unsigned int * ChannelGainFactor) +{ + int i_DiffChannel = 0; + int i_Module = 0; + +#ifdef PRINT_INFO + printk("\n Channel = %u", ui_Channel_num); +#endif + + //Test if single or differential mode + if (s_BoardInfos[dev->minor].i_ConnectionType == 1) { + //if diff + + if ((ui_Channel_num >= 0) && (ui_Channel_num <= 1)) + i_DiffChannel = ui_Channel_num, i_Module = 0; + else if ((ui_Channel_num >= 2) && (ui_Channel_num <= 3)) + i_DiffChannel = ui_Channel_num - 2, i_Module = 1; + else if ((ui_Channel_num >= 4) && (ui_Channel_num <= 5)) + i_DiffChannel = ui_Channel_num - 4, i_Module = 2; + else if ((ui_Channel_num >= 6) && (ui_Channel_num <= 7)) + i_DiffChannel = ui_Channel_num - 6, i_Module = 3; + + } else { + // if single + if ((ui_Channel_num == 0) || (ui_Channel_num == 1)) + i_DiffChannel = 0, i_Module = 0; + else if ((ui_Channel_num == 2) || (ui_Channel_num == 3)) + i_DiffChannel = 1, i_Module = 0; + else if ((ui_Channel_num == 4) || (ui_Channel_num == 5)) + i_DiffChannel = 0, i_Module = 1; + else if ((ui_Channel_num == 6) || (ui_Channel_num == 7)) + i_DiffChannel = 1, i_Module = 1; + else if ((ui_Channel_num == 8) || (ui_Channel_num == 9)) + i_DiffChannel = 0, i_Module = 2; + else if ((ui_Channel_num == 10) || (ui_Channel_num == 11)) + i_DiffChannel = 1, i_Module = 2; + else if ((ui_Channel_num == 12) || (ui_Channel_num == 13)) + i_DiffChannel = 0, i_Module = 3; + else if ((ui_Channel_num == 14) || (ui_Channel_num == 15)) + i_DiffChannel = 1, i_Module = 3; + } + + //Test if thermocouple or RTD mode + *CJCCurrentSource = + s_BoardInfos[dev->minor].s_Module[i_Module].ul_CurrentSourceCJC; +#ifdef PRINT_INFO + printk("\n CJCCurrentSource = %lu", *CJCCurrentSource); +#endif + + *ChannelCurrentSource = + s_BoardInfos[dev->minor].s_Module[i_Module]. + ul_CurrentSource[i_DiffChannel]; +#ifdef PRINT_INFO + printk("\n ChannelCurrentSource = %lu", *ChannelCurrentSource); +#endif + // } + // } + + //Channle gain factor + *ChannelGainFactor = + s_BoardInfos[dev->minor].s_Module[i_Module]. + ul_GainFactor[s_BoardInfos[dev->minor].i_ADDIDATAGain]; +#ifdef PRINT_INFO + printk("\n ChannelGainFactor = %lu", *ChannelGainFactor); +#endif + //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + + return (0); +} + +//End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_ReadDigitalInput | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Read value of the selected channel or port | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | UINT ui_NoOfChannels : No Of Channels To read for Port + Channel Numberfor single channel + | UINT data[0] : 0: Read single channel + 1: Read port value + data[1] Port number + +----------------------------------------------------------------------------+ + | Output Parameters : -- data[0] :Read status value + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ + +INT i_APCI3200_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp = 0; + UINT ui_NoOfChannel = 0; + ui_NoOfChannel = CR_CHAN(insn->chanspec); + ui_Temp = data[0]; + *data = inl(devpriv->i_IobaseReserved); + + if (ui_Temp == 0) { + *data = (*data >> ui_NoOfChannel) & 0x1; + } //if (ui_Temp==0) + else { + if (ui_Temp == 1) { + if (data[1] < 0 || data[1] > 1) { + printk("\nThe port number is in error\n"); + return -EINVAL; + } //if(data[1] < 0 || data[1] >1) + switch (ui_NoOfChannel) { + + case 2: + *data = (*data >> (2 * data[1])) & 0x3; + break; + case 3: + *data = (*data & 15); + break; + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + + } //switch(ui_NoOfChannels) + } //if (ui_Temp==1) + else { + printk("\nSpecified channel not supported \n"); + } //elseif (ui_Temp==1) + } + return insn->n; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_ConfigDigitalOutput | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Configures The Digital Output Subdevice. | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | data[0] :1 Memory enable + 0 Memory Disable + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + if ((data[0] != 0) && (data[0] != 1)) { + comedi_error(dev, + "Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } //if ( (data[0]!=0) && (data[0]!=1) ) + if (data[0]) { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; + } // if (data[0]) + else { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + } //else if (data[0]) + return insn->n; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_WriteDigitalOutput | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : writes To the digital Output Subdevice | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | struct comedi_subdevice *s : Subdevice Pointer | + | struct comedi_insn *insn : Insn Structure Pointer | + | unsigned int *data : Data Pointer contains | + | configuration parameters as below | + | data[0] :Value to output + data[1] : 0 o/p single channel + 1 o/p port + data[2] : port no + data[3] :0 set the digital o/p on + 1 set the digital o/p off + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp = 0, ui_Temp1 = 0; + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + if (devpriv->b_OutputMemoryStatus) { + ui_Temp = inl(devpriv->i_IobaseAddon); + + } //if(devpriv->b_OutputMemoryStatus ) + else { + ui_Temp = 0; + } //if(devpriv->b_OutputMemoryStatus ) + if (data[3] == 0) { + if (data[1] == 0) { + data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; + outl(data[0], devpriv->i_IobaseAddon); + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = + (data[0] << (2 * + data[2])) | ui_Temp; + break; + case 3: + data[0] = (data[0] | ui_Temp); + break; + } //switch(ui_NoOfChannels) + + outl(data[0], devpriv->i_IobaseAddon); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==0) + else { + if (data[3] == 1) { + if (data[1] == 0) { + data[0] = ~data[0] & 0x1; + ui_Temp1 = 1; + ui_Temp1 = ui_Temp1 << ui_NoOfChannel; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = (data[0] << ui_NoOfChannel) ^ 0xf; + data[0] = data[0] & ui_Temp; + outl(data[0], devpriv->i_IobaseAddon); + } //if(data[1]==0) + else { + if (data[1] == 1) { + switch (ui_NoOfChannel) { + + case 2: + data[0] = ~data[0] & 0x3; + ui_Temp1 = 3; + ui_Temp1 = + ui_Temp1 << 2 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (2 * + data + [2])) ^ + 0xf) & ui_Temp; + + break; + case 3: + break; + + default: + comedi_error(dev, + " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + } //switch(ui_NoOfChannels) + + outl(data[0], devpriv->i_IobaseAddon); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==1); + else { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } //if else data[3]==1) + } //if else data[3]==0) + return insn->n; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_ReadDigitalOutput | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Read value of the selected channel or port | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | UINT ui_NoOfChannels : No Of Channels To read | + | UINT *data : Data Pointer to read status | + data[0] :0 read single channel + 1 read port value + data[1] port no + + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + ui_NoOfChannel = CR_CHAN(insn->chanspec); + ui_Temp = data[0]; + *data = inl(devpriv->i_IobaseAddon); + if (ui_Temp == 0) { + *data = (*data >> ui_NoOfChannel) & 0x1; + } // if (ui_Temp==0) + else { + if (ui_Temp == 1) { + if (data[1] < 0 || data[1] > 1) { + printk("\nThe port selection is in error\n"); + return -EINVAL; + } //if(data[1] <0 ||data[1] >1) + switch (ui_NoOfChannel) { + case 2: + *data = (*data >> (2 * data[1])) & 3; + break; + + case 3: + break; + + default: + comedi_error(dev, " chan spec wrong"); + return -EINVAL; // "sorry channel spec wrong " + break; + } // switch(ui_NoOfChannels) + } // if (ui_Temp==1) + else { + printk("\nSpecified channel not supported \n"); + } // else if (ui_Temp==1) + } // else if (ui_Temp==0) + return insn->n; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : INT i_APCI3200_ConfigAnalogInput | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Configures The Analog Input Subdevice | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | struct comedi_subdevice *s : Subdevice Pointer | + | struct comedi_insn *insn : Insn Structure Pointer | + | unsigned int *data : Data Pointer contains | + | configuration parameters as below | + | | + | data[0] + | 0:Normal AI | + | 1:RTD | + | 2:THERMOCOUPLE | + | data[1] : Gain To Use | + | | + | data[2] : Polarity + | 0:Bipolar | + | 1:Unipolar | + | | + | data[3] : Offset Range + | | + | data[4] : Coupling + | 0:DC Coupling | + | 1:AC Coupling | + | | + | data[5] :Differential/Single + | 0:Single | + | 1:Differential | + | | + | data[6] :TimerReloadValue + | | + | data[7] :ConvertingTimeUnit + | | + | data[8] :0 Analog voltage measurement + 1 Resistance measurement + 2 Temperature measurement + | data[9] :Interrupt + | 0:Disable + | 1:Enable + data[10] :Type of Thermocouple + | data[11] : 0: single channel + Module Number + | + | data[12] + | 0:Single Read + | 1:Read more channel + 2:Single scan + | 3:Continous Scan + data[13] :Number of channels to read + | data[14] :RTD connection type + :0:RTD not used + 1:RTD 2 wire connection + 2:RTD 3 wire connection + 3:RTD 4 wire connection + | | + | | + | | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_ConfigAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + UINT ul_Config = 0, ul_Temp = 0; + UINT ui_ChannelNo = 0; + UINT ui_Dummy = 0; + INT i_err = 0; + + //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + +#ifdef PRINT_INFO + INT i = 0, i2 = 0; +#endif + //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + + //BEGIN JK 06.07.04: Management of sevrals boards + // Initialize the structure + if (s_BoardInfos[dev->minor].b_StructInitialized != 1) { + s_BoardInfos[dev->minor].i_CJCAvailable = 1; + s_BoardInfos[dev->minor].i_CJCPolarity = 0; + s_BoardInfos[dev->minor].i_CJCGain = 2; //changed from 0 to 2 + s_BoardInfos[dev->minor].i_InterruptFlag = 0; + s_BoardInfos[dev->minor].i_AutoCalibration = 0; //: auto calibration + s_BoardInfos[dev->minor].i_ChannelCount = 0; + s_BoardInfos[dev->minor].i_Sum = 0; + s_BoardInfos[dev->minor].ui_Channel_num = 0; + s_BoardInfos[dev->minor].i_Count = 0; + s_BoardInfos[dev->minor].i_Initialised = 0; + s_BoardInfos[dev->minor].b_StructInitialized = 1; + + //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + s_BoardInfos[dev->minor].i_ConnectionType = 0; + //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + + //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + memset(s_BoardInfos[dev->minor].s_Module, 0, + sizeof(s_BoardInfos[dev->minor].s_Module[MAX_MODULE])); + + v_GetAPCI3200EepromCalibrationValue(devpriv->i_IobaseAmcc, + &s_BoardInfos[dev->minor]); + +#ifdef PRINT_INFO + for (i = 0; i < MAX_MODULE; i++) { + printk("\n s_Module[%i].ul_CurrentSourceCJC = %lu", i, + s_BoardInfos[dev->minor].s_Module[i]. + ul_CurrentSourceCJC); + + for (i2 = 0; i2 < 5; i2++) { + printk("\n s_Module[%i].ul_CurrentSource [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_CurrentSource[i2]); + } + + for (i2 = 0; i2 < 8; i2++) { + printk("\n s_Module[%i].ul_GainFactor [%i] = %lu", i, i2, s_BoardInfos[dev->minor].s_Module[i].ul_GainFactor[i2]); + } + + for (i2 = 0; i2 < 8; i2++) { + printk("\n s_Module[%i].w_GainValue [%i] = %u", + i, i2, + s_BoardInfos[dev->minor].s_Module[i]. + w_GainValue[i2]); + } + } +#endif + //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + } + + if (data[0] != 0 && data[0] != 1 && data[0] != 2) { + printk("\nThe selection of acquisition type is in error\n"); + i_err++; + } //if(data[0]!=0 && data[0]!=1 && data[0]!=2) + if (data[0] == 1) { + if (data[14] != 0 && data[14] != 1 && data[14] != 2 + && data[14] != 4) { + printk("\n Error in selection of RTD connection type\n"); + i_err++; + } //if(data[14]!=0 && data[14]!=1 && data[14]!=2 && data[14]!=4) + } //if(data[0]==1 ) + if (data[1] < 0 || data[1] > 7) { + printk("\nThe selection of gain is in error\n"); + i_err++; + } // if(data[1]<0 || data[1]>7) + if (data[2] != 0 && data[2] != 1) { + printk("\nThe selection of polarity is in error\n"); + i_err++; + } //if(data[2]!=0 && data[2]!=1) + if (data[3] != 0) { + printk("\nThe selection of offset range is in error\n"); + i_err++; + } // if(data[3]!=0) + if (data[4] != 0 && data[4] != 1) { + printk("\nThe selection of coupling is in error\n"); + i_err++; + } //if(data[4]!=0 && data[4]!=1) + if (data[5] != 0 && data[5] != 1) { + printk("\nThe selection of single/differential mode is in error\n"); + i_err++; + } //if(data[5]!=0 && data[5]!=1) + if (data[8] != 0 && data[8] != 1 && data[2] != 2) { + printk("\nError in selection of functionality\n"); + } //if(data[8]!=0 && data[8]!=1 && data[2]!=2) + if (data[12] == 0 || data[12] == 1) { + if (data[6] != 20 && data[6] != 40 && data[6] != 80 + && data[6] != 160) { + printk("\nThe selection of conversion time reload value is in error\n"); + i_err++; + } // if (data[6]!=20 && data[6]!=40 && data[6]!=80 && data[6]!=160 ) + if (data[7] != 2) { + printk("\nThe selection of conversion time unit is in error\n"); + i_err++; + } // if(data[7]!=2) + } + if (data[9] != 0 && data[9] != 1) { + printk("\nThe selection of interrupt enable is in error\n"); + i_err++; + } //if(data[9]!=0 && data[9]!=1) + if (data[11] < 0 || data[11] > 4) { + printk("\nThe selection of module is in error\n"); + i_err++; + } //if(data[11] <0 || data[11]>1) + if (data[12] < 0 || data[12] > 3) { + printk("\nThe selection of singlechannel/scan selection is in error\n"); + i_err++; + } //if(data[12] < 0 || data[12]> 3) + if (data[13] < 0 || data[13] > 16) { + printk("\nThe selection of number of channels is in error\n"); + i_err++; + } // if(data[13] <0 ||data[13] >15) + + //BEGIN JK 06.07.04: Management of sevrals boards + /* + i_ChannelCount=data[13]; + i_ScanType=data[12]; + i_ADDIDATAPolarity = data[2]; + i_ADDIDATAGain=data[1]; + i_ADDIDATAConversionTime=data[6]; + i_ADDIDATAConversionTimeUnit=data[7]; + i_ADDIDATAType=data[0]; + */ + + // Save acquisition configuration for the actual board + s_BoardInfos[dev->minor].i_ChannelCount = data[13]; + s_BoardInfos[dev->minor].i_ScanType = data[12]; + s_BoardInfos[dev->minor].i_ADDIDATAPolarity = data[2]; + s_BoardInfos[dev->minor].i_ADDIDATAGain = data[1]; + s_BoardInfos[dev->minor].i_ADDIDATAConversionTime = data[6]; + s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit = data[7]; + s_BoardInfos[dev->minor].i_ADDIDATAType = data[0]; + //Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + s_BoardInfos[dev->minor].i_ConnectionType = data[5]; + //End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + //END JK 06.07.04: Management of sevrals boards + + //Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + memset(s_BoardInfos[dev->minor].ui_ScanValueArray, 0, (7 + 12) * sizeof(unsigned int)); // 7 is the maximal number of channels + //End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + + //BEGIN JK 02.07.04 : This while can't be do, it block the process when using severals boards + //while(i_InterruptFlag==1) + while (s_BoardInfos[dev->minor].i_InterruptFlag == 1) { +#ifndef MSXBOX + udelay(1); +#else + // In the case where the driver is compiled for the MSX-Box + // we used a printk to have a little delay because udelay + // seems to be broken under the MSX-Box. + // This solution hat to be studied. + printk(""); +#endif + } + //END JK 02.07.04 : This while can't be do, it block the process when using severals boards + + ui_ChannelNo = CR_CHAN(insn->chanspec); // get the channel + //BEGIN JK 06.07.04: Management of sevrals boards + //i_ChannelNo=ui_ChannelNo; + //ui_Channel_num =ui_ChannelNo; + + s_BoardInfos[dev->minor].i_ChannelNo = ui_ChannelNo; + s_BoardInfos[dev->minor].ui_Channel_num = ui_ChannelNo; + + //END JK 06.07.04: Management of sevrals boards + + if (data[5] == 0) { + if (ui_ChannelNo < 0 || ui_ChannelNo > 15) { + printk("\nThe Selection of the channel is in error\n"); + i_err++; + } // if(ui_ChannelNo<0 || ui_ChannelNo>15) + } //if(data[5]==0) + else { + if (data[14] == 2) { + if (ui_ChannelNo < 0 || ui_ChannelNo > 3) { + printk("\nThe Selection of the channel is in error\n"); + i_err++; + } // if(ui_ChannelNo<0 || ui_ChannelNo>3) + } //if(data[14]==2) + else { + if (ui_ChannelNo < 0 || ui_ChannelNo > 7) { + printk("\nThe Selection of the channel is in error\n"); + i_err++; + } // if(ui_ChannelNo<0 || ui_ChannelNo>7) + } //elseif(data[14]==2) + } //elseif(data[5]==0) + if (data[12] == 0 || data[12] == 1) { + switch (data[5]) { + case 0: + if (ui_ChannelNo >= 0 && ui_ChannelNo <= 3) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=0; + s_BoardInfos[dev->minor].i_Offset = 0; + //END JK 06.07.04: Management of sevrals boards + } //if(ui_ChannelNo >=0 && ui_ChannelNo <=3) + if (ui_ChannelNo >= 4 && ui_ChannelNo <= 7) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=64; + s_BoardInfos[dev->minor].i_Offset = 64; + //END JK 06.07.04: Management of sevrals boards + } //if(ui_ChannelNo >=4 && ui_ChannelNo <=7) + if (ui_ChannelNo >= 8 && ui_ChannelNo <= 11) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=128; + s_BoardInfos[dev->minor].i_Offset = 128; + //END JK 06.07.04: Management of sevrals boards + } //if(ui_ChannelNo >=8 && ui_ChannelNo <=11) + if (ui_ChannelNo >= 12 && ui_ChannelNo <= 15) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=192; + s_BoardInfos[dev->minor].i_Offset = 192; + //END JK 06.07.04: Management of sevrals boards + } //if(ui_ChannelNo >=12 && ui_ChannelNo <=15) + break; + case 1: + if (data[14] == 2) { + if (ui_ChannelNo == 0) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=0; + s_BoardInfos[dev->minor].i_Offset = 0; + //END JK 06.07.04: Management of sevrals boards + } //if(ui_ChannelNo ==0 ) + if (ui_ChannelNo == 1) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=0; + s_BoardInfos[dev->minor].i_Offset = 64; + //END JK 06.07.04: Management of sevrals boards + } // if(ui_ChannelNo ==1) + if (ui_ChannelNo == 2) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=128; + s_BoardInfos[dev->minor].i_Offset = 128; + //END JK 06.07.04: Management of sevrals boards + } //if(ui_ChannelNo ==2 ) + if (ui_ChannelNo == 3) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=192; + s_BoardInfos[dev->minor].i_Offset = 192; + //END JK 06.07.04: Management of sevrals boards + } //if(ui_ChannelNo ==3) + + //BEGIN JK 06.07.04: Management of sevrals boards + //i_ChannelNo=0; + s_BoardInfos[dev->minor].i_ChannelNo = 0; + //END JK 06.07.04: Management of sevrals boards + ui_ChannelNo = 0; + break; + } //if(data[14]==2) + if (ui_ChannelNo >= 0 && ui_ChannelNo <= 1) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=0; + s_BoardInfos[dev->minor].i_Offset = 0; + //END JK 06.07.04: Management of sevrals boards + } //if(ui_ChannelNo >=0 && ui_ChannelNo <=1) + if (ui_ChannelNo >= 2 && ui_ChannelNo <= 3) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_ChannelNo=i_ChannelNo-2; + //i_Offset=64; + s_BoardInfos[dev->minor].i_ChannelNo = + s_BoardInfos[dev->minor].i_ChannelNo - + 2; + s_BoardInfos[dev->minor].i_Offset = 64; + //END JK 06.07.04: Management of sevrals boards + ui_ChannelNo = ui_ChannelNo - 2; + } //if(ui_ChannelNo >=2 && ui_ChannelNo <=3) + if (ui_ChannelNo >= 4 && ui_ChannelNo <= 5) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_ChannelNo=i_ChannelNo-4; + //i_Offset=128; + s_BoardInfos[dev->minor].i_ChannelNo = + s_BoardInfos[dev->minor].i_ChannelNo - + 4; + s_BoardInfos[dev->minor].i_Offset = 128; + //END JK 06.07.04: Management of sevrals boards + ui_ChannelNo = ui_ChannelNo - 4; + } //if(ui_ChannelNo >=4 && ui_ChannelNo <=5) + if (ui_ChannelNo >= 6 && ui_ChannelNo <= 7) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_ChannelNo=i_ChannelNo-6; + //i_Offset=192; + s_BoardInfos[dev->minor].i_ChannelNo = + s_BoardInfos[dev->minor].i_ChannelNo - + 6; + s_BoardInfos[dev->minor].i_Offset = 192; + //END JK 06.07.04: Management of sevrals boards + ui_ChannelNo = ui_ChannelNo - 6; + } //if(ui_ChannelNo >=6 && ui_ChannelNo <=7) + break; + + default: + printk("\n This selection of polarity does not exist\n"); + i_err++; + } //switch(data[2]) + } //if(data[12]==0 || data[12]==1) + else { + switch (data[11]) { + case 1: + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=0; + s_BoardInfos[dev->minor].i_Offset = 0; + //END JK 06.07.04: Management of sevrals boards + break; + case 2: + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=64; + s_BoardInfos[dev->minor].i_Offset = 64; + //END JK 06.07.04: Management of sevrals boards + break; + case 3: + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=128; + s_BoardInfos[dev->minor].i_Offset = 128; + //END JK 06.07.04: Management of sevrals boards + break; + case 4: + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Offset=192; + s_BoardInfos[dev->minor].i_Offset = 192; + //END JK 06.07.04: Management of sevrals boards + break; + default: + printk("\nError in module selection\n"); + i_err++; + } // switch(data[11]) + } // elseif(data[12]==0 || data[12]==1) + if (i_err) { + i_APCI3200_Reset(dev); + return -EINVAL; + } + //if(i_ScanType!=1) + if (s_BoardInfos[dev->minor].i_ScanType != 1) { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Count=0; + //i_Sum=0; + s_BoardInfos[dev->minor].i_Count = 0; + s_BoardInfos[dev->minor].i_Sum = 0; + //END JK 06.07.04: Management of sevrals boards + } //if(i_ScanType!=1) + + ul_Config = + data[1] | (data[2] << 6) | (data[5] << 7) | (data[3] << 8) | + (data[4] << 9); + //BEGIN JK 06.07.04: Management of sevrals boards + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //END JK 06.07.04: Management of sevrals boards + /*********************************/ + /* Write the channel to configure */ + /*********************************/ + //BEGIN JK 06.07.04: Management of sevrals boards + //outl(0 | ui_ChannelNo , devpriv->iobase+i_Offset + 0x4); + outl(0 | ui_ChannelNo, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4); + //END JK 06.07.04: Management of sevrals boards + + //BEGIN JK 06.07.04: Management of sevrals boards + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //END JK 06.07.04: Management of sevrals boards + /**************************/ + /* Reset the configuration */ + /**************************/ + //BEGIN JK 06.07.04: Management of sevrals boards + //outl(0 , devpriv->iobase+i_Offset + 0x0); + outl(0, devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0); + //END JK 06.07.04: Management of sevrals boards + + //BEGIN JK 06.07.04: Management of sevrals boards + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //END JK 06.07.04: Management of sevrals boards + + /***************************/ + /* Write the configuration */ + /***************************/ + //BEGIN JK 06.07.04: Management of sevrals boards + //outl(ul_Config , devpriv->iobase+i_Offset + 0x0); + outl(ul_Config, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x0); + //END JK 06.07.04: Management of sevrals boards + + /***************************/ + /*Reset the calibration bit */ + /***************************/ + //BEGIN JK 06.07.04: Management of sevrals boards + //ul_Temp = inl(devpriv->iobase+i_Offset + 12); + ul_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); + //END JK 06.07.04: Management of sevrals boards + + //BEGIN JK 06.07.04: Management of sevrals boards + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //END JK 06.07.04: Management of sevrals boards + + //BEGIN JK 06.07.04: Management of sevrals boards + //outl((ul_Temp & 0xFFF9FFFF) , devpriv->iobase+.i_Offset + 12); + outl((ul_Temp & 0xFFF9FFFF), + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); + //END JK 06.07.04: Management of sevrals boards + + if (data[9] == 1) { + devpriv->tsk_Current = current; + //BEGIN JK 06.07.04: Management of sevrals boards + //i_InterruptFlag=1; + s_BoardInfos[dev->minor].i_InterruptFlag = 1; + //END JK 06.07.04: Management of sevrals boards + } // if(data[9]==1) + else { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_InterruptFlag=0; + s_BoardInfos[dev->minor].i_InterruptFlag = 0; + //END JK 06.07.04: Management of sevrals boards + } //else if(data[9]==1) + + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Initialised=1; + s_BoardInfos[dev->minor].i_Initialised = 1; + //END JK 06.07.04: Management of sevrals boards + + //BEGIN JK 06.07.04: Management of sevrals boards + //if(i_ScanType==1) + if (s_BoardInfos[dev->minor].i_ScanType == 1) + //END JK 06.07.04: Management of sevrals boards + { + //BEGIN JK 06.07.04: Management of sevrals boards + //i_Sum=i_Sum+1; + s_BoardInfos[dev->minor].i_Sum = + s_BoardInfos[dev->minor].i_Sum + 1; + //END JK 06.07.04: Management of sevrals boards + + insn->unused[0] = 0; + i_APCI3200_ReadAnalogInput(dev, s, insn, &ui_Dummy); + } + + return insn->n; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_ReadAnalogInput | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Read value of the selected channel | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | UINT ui_NoOfChannels : No Of Channels To read | + | UINT *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + | data[0] : Digital Value Of Input | + | data[1] : Calibration Offset Value | + | data[2] : Calibration Gain Value + | data[3] : CJC value + | data[4] : CJC offset value + | data[5] : CJC gain value + | Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + | data[6] : CJC current source from eeprom + | data[7] : Channel current source from eeprom + | data[8] : Channle gain factor from eeprom + | End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_ReadAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_DummyValue = 0; + int i_ConvertCJCCalibration; + int i = 0; + + //BEGIN JK 06.07.04: Management of sevrals boards + //if(i_Initialised==0) + if (s_BoardInfos[dev->minor].i_Initialised == 0) + //END JK 06.07.04: Management of sevrals boards + { + i_APCI3200_Reset(dev); + return -EINVAL; + } //if(i_Initialised==0); + +#ifdef PRINT_INFO + printk("\n insn->unused[0] = %i", insn->unused[0]); +#endif + + switch (insn->unused[0]) { + case 0: + + i_APCI3200_Read1AnalogInputChannel(dev, s, insn, + &ui_DummyValue); + //BEGIN JK 06.07.04: Management of sevrals boards + //ui_InterruptChannelValue[i_Count+0]=ui_DummyValue; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos[dev->minor]. + i_Count + 0] = ui_DummyValue; + //END JK 06.07.04: Management of sevrals boards + + //Begin JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + i_APCI3200_GetChannelCalibrationValue(dev, + s_BoardInfos[dev->minor].ui_Channel_num, + &s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos[dev->minor]. + i_Count + 6], + &s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos[dev->minor]. + i_Count + 7], + &s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos[dev->minor]. + i_Count + 8]); + +#ifdef PRINT_INFO + printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+6] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 6]); + + printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+7] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 7]); + + printk("\n s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count+8] = %lu", s_BoardInfos[dev->minor].ui_InterruptChannelValue[s_BoardInfos[dev->minor].i_Count + 8]); +#endif + + //End JK 25.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + + //BEGIN JK 06.07.04: Management of sevrals boards + //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) + if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2) + && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE) + && (s_BoardInfos[dev->minor].i_CJCAvailable == 1)) + //END JK 06.07.04: Management of sevrals boards + { + i_APCI3200_ReadCJCValue(dev, &ui_DummyValue); + //BEGIN JK 06.07.04: Management of sevrals boards + //ui_InterruptChannelValue[i_Count + 3]=ui_DummyValue; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos[dev-> + minor].i_Count + 3] = ui_DummyValue; + //END JK 06.07.04: Management of sevrals boards + } //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) + else { + //BEGIN JK 06.07.04: Management of sevrals boards + //ui_InterruptChannelValue[i_Count + 3]=0; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos[dev-> + minor].i_Count + 3] = 0; + //END JK 06.07.04: Management of sevrals boards + } //elseif((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE) && (i_CJCAvailable==1)) + + //BEGIN JK 06.07.04: Management of sevrals boards + //if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) + if ((s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) + && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE)) + //END JK 06.07.04: Management of sevrals boards + { + i_APCI3200_ReadCalibrationOffsetValue(dev, + &ui_DummyValue); + //BEGIN JK 06.07.04: Management of sevrals boards + //ui_InterruptChannelValue[i_Count + 1]=ui_DummyValue; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos[dev-> + minor].i_Count + 1] = ui_DummyValue; + //END JK 06.07.04: Management of sevrals boards + i_APCI3200_ReadCalibrationGainValue(dev, + &ui_DummyValue); + //BEGIN JK 06.07.04: Management of sevrals boards + //ui_InterruptChannelValue[i_Count + 2]=ui_DummyValue; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos[dev-> + minor].i_Count + 2] = ui_DummyValue; + //END JK 06.07.04: Management of sevrals boards + } //if (( i_AutoCalibration == FALSE) && (i_InterruptFlag == FALSE)) + + //BEGIN JK 06.07.04: Management of sevrals boards + //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)&& (i_CJCAvailable==1)) + if ((s_BoardInfos[dev->minor].i_ADDIDATAType == 2) + && (s_BoardInfos[dev->minor].i_InterruptFlag == FALSE) + && (s_BoardInfos[dev->minor].i_CJCAvailable == 1)) + //END JK 06.07.04: Management of sevrals boards + { + /**********************************************************/ + /*Test if the Calibration channel must be read for the CJC */ + /**********************************************************/ + /**********************************/ + /*Test if the polarity is the same */ + /**********************************/ + //BEGIN JK 06.07.04: Management of sevrals boards + //if(i_CJCPolarity!=i_ADDIDATAPolarity) + if (s_BoardInfos[dev->minor].i_CJCPolarity != + s_BoardInfos[dev->minor].i_ADDIDATAPolarity) + //END JK 06.07.04: Management of sevrals boards + { + i_ConvertCJCCalibration = 1; + } //if(i_CJCPolarity!=i_ADDIDATAPolarity) + else { + //BEGIN JK 06.07.04: Management of sevrals boards + //if(i_CJCGain==i_ADDIDATAGain) + if (s_BoardInfos[dev->minor].i_CJCGain == + s_BoardInfos[dev->minor].i_ADDIDATAGain) + //END JK 06.07.04: Management of sevrals boards + { + i_ConvertCJCCalibration = 0; + } //if(i_CJCGain==i_ADDIDATAGain) + else { + i_ConvertCJCCalibration = 1; + } //elseif(i_CJCGain==i_ADDIDATAGain) + } //elseif(i_CJCPolarity!=i_ADDIDATAPolarity) + if (i_ConvertCJCCalibration == 1) { + i_APCI3200_ReadCJCCalOffset(dev, + &ui_DummyValue); + //BEGIN JK 06.07.04: Management of sevrals boards + //ui_InterruptChannelValue[i_Count+4]=ui_DummyValue; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos + [dev->minor].i_Count + 4] = + ui_DummyValue; + //END JK 06.07.04: Management of sevrals boards + + i_APCI3200_ReadCJCCalGain(dev, &ui_DummyValue); + + //BEGIN JK 06.07.04: Management of sevrals boards + //ui_InterruptChannelValue[i_Count+5]=ui_DummyValue; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos + [dev->minor].i_Count + 5] = + ui_DummyValue; + //END JK 06.07.04: Management of sevrals boards + } //if(i_ConvertCJCCalibration==1) + else { + //BEGIN JK 06.07.04: Management of sevrals boards + //ui_InterruptChannelValue[i_Count+4]=0; + //ui_InterruptChannelValue[i_Count+5]=0; + + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos + [dev->minor].i_Count + 4] = 0; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[s_BoardInfos + [dev->minor].i_Count + 5] = 0; + //END JK 06.07.04: Management of sevrals boards + } //elseif(i_ConvertCJCCalibration==1) + } //if((i_ADDIDATAType==2) && (i_InterruptFlag == FALSE)) + + //BEGIN JK 06.07.04: Management of sevrals boards + //if(i_ScanType!=1) + if (s_BoardInfos[dev->minor].i_ScanType != 1) { + //i_Count=0; + s_BoardInfos[dev->minor].i_Count = 0; + } //if(i_ScanType!=1) + else { + //i_Count=i_Count +6; + //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count +6; + s_BoardInfos[dev->minor].i_Count = + s_BoardInfos[dev->minor].i_Count + 9; + //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + } //else if(i_ScanType!=1) + + //if((i_ScanType==1) &&(i_InterruptFlag==1)) + if ((s_BoardInfos[dev->minor].i_ScanType == 1) + && (s_BoardInfos[dev->minor].i_InterruptFlag == 1)) { + //i_Count=i_Count-6; + //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count-6; + s_BoardInfos[dev->minor].i_Count = + s_BoardInfos[dev->minor].i_Count - 9; + //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + } + //if(i_ScanType==0) + if (s_BoardInfos[dev->minor].i_ScanType == 0) { + /* + data[0]= ui_InterruptChannelValue[0]; + data[1]= ui_InterruptChannelValue[1]; + data[2]= ui_InterruptChannelValue[2]; + data[3]= ui_InterruptChannelValue[3]; + data[4]= ui_InterruptChannelValue[4]; + data[5]= ui_InterruptChannelValue[5]; + */ +#ifdef PRINT_INFO + printk("\n data[0]= s_BoardInfos [dev->minor].ui_InterruptChannelValue[0];"); +#endif + data[0] = + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[0]; + data[1] = + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[1]; + data[2] = + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[2]; + data[3] = + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[3]; + data[4] = + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[4]; + data[5] = + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[5]; + + //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + //printk("\n 0 - i_APCI3200_GetChannelCalibrationValue data [6] = %lu, data [7] = %lu, data [8] = %lu", data [6], data [7], data [8]); + i_APCI3200_GetChannelCalibrationValue(dev, + s_BoardInfos[dev->minor].ui_Channel_num, + &data[6], &data[7], &data[8]); + //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + } + break; + case 1: + + for (i = 0; i < insn->n; i++) { + //data[i]=ui_InterruptChannelValue[i]; + data[i] = + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue[i]; + } + + //i_Count=0; + //i_Sum=0; + //if(i_ScanType==1) + s_BoardInfos[dev->minor].i_Count = 0; + s_BoardInfos[dev->minor].i_Sum = 0; + if (s_BoardInfos[dev->minor].i_ScanType == 1) { + //i_Initialised=0; + //i_InterruptFlag=0; + s_BoardInfos[dev->minor].i_Initialised = 0; + s_BoardInfos[dev->minor].i_InterruptFlag = 0; + //END JK 06.07.04: Management of sevrals boards + } + break; + default: + printk("\nThe parameters passed are in error\n"); + i_APCI3200_Reset(dev); + return -EINVAL; + } //switch(insn->unused[0]) + + return insn->n; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_Read1AnalogInputChannel | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Read value of the selected channel | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | UINT ui_NoOfChannel : Channel No to read | + | UINT *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + | data[0] : Digital Value read | + | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +INT i_APCI3200_Read1AnalogInputChannel(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_EOC = 0; + UINT ui_ChannelNo = 0; + UINT ui_CommandRegister = 0; + + //BEGIN JK 06.07.04: Management of sevrals boards + //ui_ChannelNo=i_ChannelNo; + ui_ChannelNo = s_BoardInfos[dev->minor].i_ChannelNo; + + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + /*********************************/ + /* Write the channel to configure */ + /*********************************/ + //Begin JK 20.10.2004: Bad channel value is used when using differential mode + //outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); + //outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); + outl(0 | s_BoardInfos[dev->minor].i_ChannelNo, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x4); + //End JK 20.10.2004: Bad channel value is used when using differential mode + + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + + //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36); + + /**************************/ + /* Set the convert timing */ + /**************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + + //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32); + + /**************************************************************************/ + /* Set the start end stop index to the selected channel and set the start */ + /**************************************************************************/ + + ui_CommandRegister = ui_ChannelNo | (ui_ChannelNo << 8) | 0x80000; + + /*********************************/ + /*Test if the interrupt is enable */ + /*********************************/ + + //if (i_InterruptFlag == ADDIDATA_ENABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { + /************************/ + /* Enable the interrupt */ + /************************/ + ui_CommandRegister = ui_CommandRegister | 0x00100000; + } //if (i_InterruptFlag == ADDIDATA_ENABLE) + + /******************************/ + /* Write the command register */ + /******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + + //outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); + outl(ui_CommandRegister, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + + /*****************************/ + /*Test if interrupt is enable */ + /*****************************/ + //if (i_InterruptFlag == ADDIDATA_DISABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + do { + /*************************/ + /*Read the EOC Status bit */ + /*************************/ + + //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + ui_EOC = inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 20) & 1; + + } while (ui_EOC != 1); + + /***************************************/ + /* Read the digital value of the input */ + /***************************************/ + + //data[0] = inl (devpriv->iobase+i_Offset + 28); + data[0] = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 28); + //END JK 06.07.04: Management of sevrals boards + + } // if (i_InterruptFlag == ADDIDATA_DISABLE) + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_ReadCalibrationOffsetValue | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Read calibration offset value of the selected channel| + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | UINT *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + | data[0] : Calibration offset Value | + | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device * dev, UINT * data) +{ + UINT ui_Temp = 0, ui_EOC = 0; + UINT ui_CommandRegister = 0; + + //BEGIN JK 06.07.04: Management of sevrals boards + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + /*********************************/ + /* Write the channel to configure */ + /*********************************/ + //Begin JK 20.10.2004: This seems not necessary ! + //outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); + //outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); + //End JK 20.10.2004: This seems not necessary ! + + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32); + /*****************************/ + /*Read the calibration offset */ + /*****************************/ + //ui_Temp = inl(devpriv->iobase+i_Offset + 12); + ui_Temp = inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); + + /*********************************/ + /*Configure the Offset Conversion */ + /*********************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl((ui_Temp | 0x00020000), devpriv->iobase+i_Offset + 12); + outl((ui_Temp | 0x00020000), + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); + /*******************************/ + /*Initialise ui_CommandRegister */ + /*******************************/ + + ui_CommandRegister = 0; + + /*********************************/ + /*Test if the interrupt is enable */ + /*********************************/ + + //if (i_InterruptFlag == ADDIDATA_ENABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { + + /**********************/ + /*Enable the interrupt */ + /**********************/ + + ui_CommandRegister = ui_CommandRegister | 0x00100000; + + } //if (i_InterruptFlag == ADDIDATA_ENABLE) + + /**********************/ + /*Start the conversion */ + /**********************/ + ui_CommandRegister = ui_CommandRegister | 0x00080000; + + /***************************/ + /*Write the command regiter */ + /***************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(ui_CommandRegister, devpriv->iobase+i_Offset + 8); + outl(ui_CommandRegister, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + + /*****************************/ + /*Test if interrupt is enable */ + /*****************************/ + + //if (i_InterruptFlag == ADDIDATA_DISABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + + do { + /*******************/ + /*Read the EOC flag */ + /*******************/ + + //ui_EOC = inl (devpriv->iobase+i_Offset + 20) & 1; + ui_EOC = inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 20) & 1; + + } while (ui_EOC != 1); + + /**************************************************/ + /*Read the digital value of the calibration Offset */ + /**************************************************/ + + //data[0] = inl(devpriv->iobase+i_Offset+ 28); + data[0] = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 28); + } //if (i_InterruptFlag == ADDIDATA_DISABLE) + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_ReadCalibrationGainValue | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Read calibration gain value of the selected channel | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | UINT *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + | data[0] : Calibration gain Value Of Input | + | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ReadCalibrationGainValue(struct comedi_device * dev, UINT * data) +{ + UINT ui_EOC = 0; + INT ui_CommandRegister = 0; + + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + /*********************************/ + /* Write the channel to configure */ + /*********************************/ + //Begin JK 20.10.2004: This seems not necessary ! + //outl(0 | ui_Channel_num , devpriv->iobase+i_Offset + 0x4); + //outl(0 | s_BoardInfos [dev->minor].ui_Channel_num , devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 0x4); + //End JK 20.10.2004: This seems not necessary ! + + /***************************/ + /*Read the calibration gain */ + /***************************/ + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32); + /*******************************/ + /*Configure the Gain Conversion */ + /*******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(0x00040000 , devpriv->iobase+i_Offset + 12); + outl(0x00040000, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); + + /*******************************/ + /*Initialise ui_CommandRegister */ + /*******************************/ + + ui_CommandRegister = 0; + + /*********************************/ + /*Test if the interrupt is enable */ + /*********************************/ + + //if (i_InterruptFlag == ADDIDATA_ENABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { + + /**********************/ + /*Enable the interrupt */ + /**********************/ + + ui_CommandRegister = ui_CommandRegister | 0x00100000; + + } //if (i_InterruptFlag == ADDIDATA_ENABLE) + + /**********************/ + /*Start the conversion */ + /**********************/ + + ui_CommandRegister = ui_CommandRegister | 0x00080000; + /***************************/ + /*Write the command regiter */ + /***************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); + outl(ui_CommandRegister, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + + /*****************************/ + /*Test if interrupt is enable */ + /*****************************/ + + //if (i_InterruptFlag == ADDIDATA_DISABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + + do { + + /*******************/ + /*Read the EOC flag */ + /*******************/ + + //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + ui_EOC = inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 20) & 1; + + } while (ui_EOC != 1); + + /************************************************/ + /*Read the digital value of the calibration Gain */ + /************************************************/ + + //data[0] = inl(devpriv->iobase+i_Offset + 28); + data[0] = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 28); + + } //if (i_InterruptFlag == ADDIDATA_DISABLE) + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_ReadCJCValue | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Read CJC value of the selected channel | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | UINT *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + | data[0] : CJC Value | + | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ + +int i_APCI3200_ReadCJCValue(struct comedi_device * dev, unsigned int * data) +{ + UINT ui_EOC = 0; + INT ui_CommandRegister = 0; + + /******************************/ + /*Set the converting time unit */ + /******************************/ + + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + + //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + + //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32); + + /******************************/ + /*Configure the CJC Conversion */ + /******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + + //outl( 0x00000400 , devpriv->iobase+i_Offset + 4); + outl(0x00000400, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4); + /*******************************/ + /*Initialise dw_CommandRegister */ + /*******************************/ + ui_CommandRegister = 0; + /*********************************/ + /*Test if the interrupt is enable */ + /*********************************/ + //if (i_InterruptFlag == ADDIDATA_ENABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { + /**********************/ + /*Enable the interrupt */ + /**********************/ + ui_CommandRegister = ui_CommandRegister | 0x00100000; + } + + /**********************/ + /*Start the conversion */ + /**********************/ + + ui_CommandRegister = ui_CommandRegister | 0x00080000; + + /***************************/ + /*Write the command regiter */ + /***************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(ui_CommandRegister , devpriv->iobase+i_Offset + 8); + outl(ui_CommandRegister, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + + /*****************************/ + /*Test if interrupt is enable */ + /*****************************/ + + //if (i_InterruptFlag == ADDIDATA_DISABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + do { + + /*******************/ + /*Read the EOC flag */ + /*******************/ + + //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + ui_EOC = inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 20) & 1; + + } while (ui_EOC != 1); + + /***********************************/ + /*Read the digital value of the CJC */ + /***********************************/ + + //data[0] = inl(devpriv->iobase+i_Offset + 28); + data[0] = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 28); + + } //if (i_InterruptFlag == ADDIDATA_DISABLE) + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_ReadCJCCalOffset | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Read CJC calibration offset value of the selected channel + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | UINT *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + | data[0] : CJC calibration offset Value + | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ReadCJCCalOffset(struct comedi_device * dev, unsigned int * data) +{ + UINT ui_EOC = 0; + INT ui_CommandRegister = 0; + /*******************************************/ + /*Read calibration offset value for the CJC */ + /*******************************************/ + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32); + /******************************/ + /*Configure the CJC Conversion */ + /******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(0x00000400 , devpriv->iobase+i_Offset + 4); + outl(0x00000400, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4); + /*********************************/ + /*Configure the Offset Conversion */ + /*********************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(0x00020000, devpriv->iobase+i_Offset + 12); + outl(0x00020000, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); + /*******************************/ + /*Initialise ui_CommandRegister */ + /*******************************/ + ui_CommandRegister = 0; + /*********************************/ + /*Test if the interrupt is enable */ + /*********************************/ + + //if (i_InterruptFlag == ADDIDATA_ENABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { + /**********************/ + /*Enable the interrupt */ + /**********************/ + ui_CommandRegister = ui_CommandRegister | 0x00100000; + + } + + /**********************/ + /*Start the conversion */ + /**********************/ + ui_CommandRegister = ui_CommandRegister | 0x00080000; + /***************************/ + /*Write the command regiter */ + /***************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(ui_CommandRegister,devpriv->iobase+i_Offset + 8); + outl(ui_CommandRegister, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + //if (i_InterruptFlag == ADDIDATA_DISABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + do { + /*******************/ + /*Read the EOC flag */ + /*******************/ + //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + ui_EOC = inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 20) & 1; + } while (ui_EOC != 1); + + /**************************************************/ + /*Read the digital value of the calibration Offset */ + /**************************************************/ + //data[0] = inl(devpriv->iobase+i_Offset + 28); + data[0] = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 28); + } //if (i_InterruptFlag == ADDIDATA_DISABLE) + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_ReadCJCGainValue | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Read CJC calibration gain value + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | UINT ui_NoOfChannels : No Of Channels To read | + | UINT *data : Data Pointer to read status | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + | data[0] : CJC calibration gain value + | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +int i_APCI3200_ReadCJCCalGain(struct comedi_device * dev, unsigned int * data) +{ + UINT ui_EOC = 0; + INT ui_CommandRegister = 0; + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(i_ADDIDATAConversionTimeUnit , devpriv->iobase+i_Offset + 36); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTimeUnit, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36); + /**************************/ + /* Set the convert timing */ + /**************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(i_ADDIDATAConversionTime , devpriv->iobase+i_Offset + 32); + outl(s_BoardInfos[dev->minor].i_ADDIDATAConversionTime, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32); + /******************************/ + /*Configure the CJC Conversion */ + /******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(0x00000400,devpriv->iobase+i_Offset + 4); + outl(0x00000400, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4); + /*******************************/ + /*Configure the Gain Conversion */ + /*******************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(0x00040000,devpriv->iobase+i_Offset + 12); + outl(0x00040000, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); + + /*******************************/ + /*Initialise dw_CommandRegister */ + /*******************************/ + ui_CommandRegister = 0; + /*********************************/ + /*Test if the interrupt is enable */ + /*********************************/ + //if (i_InterruptFlag == ADDIDATA_ENABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_ENABLE) { + /**********************/ + /*Enable the interrupt */ + /**********************/ + ui_CommandRegister = ui_CommandRegister | 0x00100000; + } + /**********************/ + /*Start the conversion */ + /**********************/ + ui_CommandRegister = ui_CommandRegister | 0x00080000; + /***************************/ + /*Write the command regiter */ + /***************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(ui_CommandRegister ,devpriv->iobase+i_Offset + 8); + outl(ui_CommandRegister, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + //if (i_InterruptFlag == ADDIDATA_DISABLE) + if (s_BoardInfos[dev->minor].i_InterruptFlag == ADDIDATA_DISABLE) { + do { + /*******************/ + /*Read the EOC flag */ + /*******************/ + //ui_EOC = inl(devpriv->iobase+i_Offset + 20) & 1; + ui_EOC = inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 20) & 1; + } while (ui_EOC != 1); + /************************************************/ + /*Read the digital value of the calibration Gain */ + /************************************************/ + //data[0] = inl (devpriv->iobase+i_Offset + 28); + data[0] = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 28); + } //if (i_InterruptFlag == ADDIDATA_DISABLE) + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_InsnBits_AnalogInput_Test | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Tests the Selected Anlog Input Channel | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | struct comedi_subdevice *s : Subdevice Pointer | + | struct comedi_insn *insn : Insn Structure Pointer | + | unsigned int *data : Data Pointer contains | + | configuration parameters as below | + | + | + | data[0] : 0 TestAnalogInputShortCircuit + | 1 TestAnalogInputConnection | + + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + | data[0] : Digital value obtained | + | data[1] : calibration offset | + | data[2] : calibration gain | + | | + | | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ + +INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Configuration = 0; + INT i_Temp; //,i_TimeUnit; + //if(i_Initialised==0) + + if (s_BoardInfos[dev->minor].i_Initialised == 0) { + i_APCI3200_Reset(dev); + return -EINVAL; + } //if(i_Initialised==0); + if (data[0] != 0 && data[0] != 1) { + printk("\nError in selection of functionality\n"); + i_APCI3200_Reset(dev); + return -EINVAL; + } //if(data[0]!=0 && data[0]!=1) + + if (data[0] == 1) //Perform Short Circuit TEST + { + /**************************/ + /*Set the short-cicuit bit */ + /**************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor]. + i_Offset + 12) >> 19) & 1) != + 1) ; + //outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4); + outl((0x00001000 | s_BoardInfos[dev->minor].i_ChannelNo), + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 4); + /*************************/ + /*Set the time unit to ns */ + /*************************/ + /* i_TimeUnit= i_ADDIDATAConversionTimeUnit; + i_ADDIDATAConversionTimeUnit= 1; */ + //i_Temp= i_InterruptFlag ; + i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag; + //i_InterruptFlag = ADDIDATA_DISABLE; + s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE; + i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data); + //if(i_AutoCalibration == FALSE) + if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) { + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor]. + i_Offset + + 12) >> 19) & 1) != 1) ; + + //outl((0x00001000 |i_ChannelNo) , devpriv->iobase+i_Offset + 4); + outl((0x00001000 | s_BoardInfos[dev->minor]. + i_ChannelNo), + devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 4); + data++; + i_APCI3200_ReadCalibrationOffsetValue(dev, data); + data++; + i_APCI3200_ReadCalibrationGainValue(dev, data); + } + } else { + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor]. + i_Offset + 12) >> 19) & 1) != + 1) ; + //outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4); + outl((0x00000800 | s_BoardInfos[dev->minor].i_ChannelNo), + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 4); + //ui_Configuration = inl(devpriv->iobase+i_Offset + 0); + ui_Configuration = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 0); + /*************************/ + /*Set the time unit to ns */ + /*************************/ + /* i_TimeUnit= i_ADDIDATAConversionTimeUnit; + i_ADDIDATAConversionTimeUnit= 1; */ + //i_Temp= i_InterruptFlag ; + i_Temp = s_BoardInfos[dev->minor].i_InterruptFlag; + //i_InterruptFlag = ADDIDATA_DISABLE; + s_BoardInfos[dev->minor].i_InterruptFlag = ADDIDATA_DISABLE; + i_APCI3200_Read1AnalogInputChannel(dev, s, insn, data); + //if(i_AutoCalibration == FALSE) + if (s_BoardInfos[dev->minor].i_AutoCalibration == FALSE) { + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor]. + i_Offset + + 12) >> 19) & 1) != 1) ; + //outl((0x00000800|i_ChannelNo) , devpriv->iobase+i_Offset + 4); + outl((0x00000800 | s_BoardInfos[dev->minor]. + i_ChannelNo), + devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 4); + data++; + i_APCI3200_ReadCalibrationOffsetValue(dev, data); + data++; + i_APCI3200_ReadCalibrationGainValue(dev, data); + } + } + //i_InterruptFlag=i_Temp ; + s_BoardInfos[dev->minor].i_InterruptFlag = i_Temp; + //printk("\ni_InterruptFlag=%d\n",i_InterruptFlag); + return insn->n; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_InsnWriteReleaseAnalogInput | + | (struct comedi_device *dev,struct comedi_subdevice *s, | + | struct comedi_insn *insn,unsigned int *data) | + +----------------------------------------------------------------------------+ + | Task : Resets the channels | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev : Driver handle | + | struct comedi_subdevice *s : Subdevice Pointer | + | struct comedi_insn *insn : Insn Structure Pointer | + | unsigned int *data : Data Pointer + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ + +INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + i_APCI3200_Reset(dev); + return insn->n; +} + +/* + +----------------------------------------------------------------------------+ + | Function name :int i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev| + | ,struct comedi_subdevice *s,struct comedi_cmd *cmd) | + | | + +----------------------------------------------------------------------------+ + | Task : Test validity for a command for cyclic anlog input | + | acquisition | + | | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev | + | struct comedi_subdevice *s | + | struct comedi_cmd *cmd | + | | + | + | | + | | + | | + +----------------------------------------------------------------------------+ + | Return Value :0 | + | | + +----------------------------------------------------------------------------+ +*/ + +int i_APCI3200_CommandTestAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + + int err = 0; + int tmp; // divisor1,divisor2; + UINT ui_ConvertTime = 0; + UINT ui_ConvertTimeBase = 0; + UINT ui_DelayTime = 0; + UINT ui_DelayTimeBase = 0; + INT i_Triggermode = 0; + INT i_TriggerEdge = 0; + INT i_NbrOfChannel = 0; + INT i_Cpt = 0; + double d_ConversionTimeForAllChannels = 0.0; + double d_SCANTimeNewUnit = 0.0; + // step 1: make sure trigger sources are trivially valid + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + //if(i_InterruptFlag==0) + if (s_BoardInfos[dev->minor].i_InterruptFlag == 0) { + err++; + // printk("\nThe interrupt should be enabled\n"); + } + if (err) { + i_APCI3200_Reset(dev); + return 1; + } + + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) { + err++; + } + if (cmd->start_src == TRIG_EXT) { + i_TriggerEdge = cmd->start_arg & 0xFFFF; + i_Triggermode = cmd->start_arg >> 16; + if (i_TriggerEdge < 1 || i_TriggerEdge > 3) { + err++; + printk("\nThe trigger edge selection is in error\n"); + } + if (i_Triggermode != 2) { + err++; + printk("\nThe trigger mode selection is in error\n"); + } + } + + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + + if (cmd->convert_src != TRIG_TIMER) + err++; + + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; + + if (err) { + i_APCI3200_Reset(dev); + return 2; + } + //i_FirstChannel=cmd->chanlist[0]; + s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0]; + //i_LastChannel=cmd->chanlist[1]; + s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1]; + + if (cmd->convert_src == TRIG_TIMER) { + ui_ConvertTime = cmd->convert_arg & 0xFFFF; + ui_ConvertTimeBase = cmd->convert_arg >> 16; + if (ui_ConvertTime != 20 && ui_ConvertTime != 40 + && ui_ConvertTime != 80 && ui_ConvertTime != 160) + { + printk("\nThe selection of conversion time reload value is in error\n"); + err++; + } // if (ui_ConvertTime!=20 && ui_ConvertTime!=40 && ui_ConvertTime!=80 && ui_ConvertTime!=160 ) + if (ui_ConvertTimeBase != 2) { + printk("\nThe selection of conversion time unit is in error\n"); + err++; + } //if(ui_ConvertTimeBase!=2) + } else { + ui_ConvertTime = 0; + ui_ConvertTimeBase = 0; + } + if (cmd->scan_begin_src == TRIG_FOLLOW) { + ui_DelayTime = 0; + ui_DelayTimeBase = 0; + } //if(cmd->scan_begin_src==TRIG_FOLLOW) + else { + ui_DelayTime = cmd->scan_begin_arg & 0xFFFF; + ui_DelayTimeBase = cmd->scan_begin_arg >> 16; + if (ui_DelayTimeBase != 2 && ui_DelayTimeBase != 3) { + err++; + printk("\nThe Delay time base selection is in error\n"); + } + if (ui_DelayTime < 1 && ui_DelayTime > 1023) { + err++; + printk("\nThe Delay time value is in error\n"); + } + if (err) { + i_APCI3200_Reset(dev); + return 3; + } + fpu_begin(); + d_SCANTimeNewUnit = (double)ui_DelayTime; + //i_NbrOfChannel= i_LastChannel-i_FirstChannel + 4; + i_NbrOfChannel = + s_BoardInfos[dev->minor].i_LastChannel - + s_BoardInfos[dev->minor].i_FirstChannel + 4; + /**********************************************************/ + /*calculate the total conversion time for all the channels */ + /**********************************************************/ + d_ConversionTimeForAllChannels = + (double)((double)ui_ConvertTime / + (double)i_NbrOfChannel); + + /*******************************/ + /*Convert the frequence in time */ + /*******************************/ + d_ConversionTimeForAllChannels = + (double)1.0 / d_ConversionTimeForAllChannels; + ui_ConvertTimeBase = 3; + /***********************************/ + /*Test if the time unit is the same */ + /***********************************/ + + if (ui_DelayTimeBase <= ui_ConvertTimeBase) { + + for (i_Cpt = 0; + i_Cpt < (ui_ConvertTimeBase - ui_DelayTimeBase); + i_Cpt++) { + + d_ConversionTimeForAllChannels = + d_ConversionTimeForAllChannels * 1000; + d_ConversionTimeForAllChannels = + d_ConversionTimeForAllChannels + 1; + } + } else { + for (i_Cpt = 0; + i_Cpt < (ui_DelayTimeBase - ui_ConvertTimeBase); + i_Cpt++) { + d_SCANTimeNewUnit = d_SCANTimeNewUnit * 1000; + + } + } + + if (d_ConversionTimeForAllChannels >= d_SCANTimeNewUnit) { + + printk("\nSCAN Delay value cannot be used\n"); + /*********************************/ + /*SCAN Delay value cannot be used */ + /*********************************/ + err++; + } + fpu_end(); + } //else if(cmd->scan_begin_src==TRIG_FOLLOW) + + if (err) { + i_APCI3200_Reset(dev); + return 4; + } + + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function name :int i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev,| + | struct comedi_subdevice *s)| + | | + +----------------------------------------------------------------------------+ + | Task : Stop the acquisition | + | | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev | + | struct comedi_subdevice *s | + | | + +----------------------------------------------------------------------------+ + | Return Value :0 | + | | + +----------------------------------------------------------------------------+ +*/ + +int i_APCI3200_StopCyclicAcquisition(struct comedi_device * dev, struct comedi_subdevice * s) +{ + UINT ui_Configuration = 0; + //i_InterruptFlag=0; + //i_Initialised=0; + //i_Count=0; + //i_Sum=0; + s_BoardInfos[dev->minor].i_InterruptFlag = 0; + s_BoardInfos[dev->minor].i_Initialised = 0; + s_BoardInfos[dev->minor].i_Count = 0; + s_BoardInfos[dev->minor].i_Sum = 0; + + /*******************/ + /*Read the register */ + /*******************/ + //ui_Configuration = inl(devpriv->iobase+i_Offset + 8); + ui_Configuration = + inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + /*****************************/ + /*Reset the START and IRQ bit */ + /*****************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl((ui_Configuration & 0xFFE7FFFF),devpriv->iobase+i_Offset + 8); + outl((ui_Configuration & 0xFFE7FFFF), + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function name : int i_APCI3200_CommandAnalogInput(struct comedi_device *dev, | + | struct comedi_subdevice *s) | + | | + +----------------------------------------------------------------------------+ + | Task : Does asynchronous acquisition | + | Determines the mode 1 or 2. | + | | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev | + | struct comedi_subdevice *s | + | | + | | + +----------------------------------------------------------------------------+ + | Return Value : | + | | + +----------------------------------------------------------------------------+ +*/ + +int i_APCI3200_CommandAnalogInput(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + UINT ui_Configuration = 0; + //INT i_CurrentSource = 0; + UINT ui_Trigger = 0; + UINT ui_TriggerEdge = 0; + UINT ui_Triggermode = 0; + UINT ui_ScanMode = 0; + UINT ui_ConvertTime = 0; + UINT ui_ConvertTimeBase = 0; + UINT ui_DelayTime = 0; + UINT ui_DelayTimeBase = 0; + UINT ui_DelayMode = 0; + //i_FirstChannel=cmd->chanlist[0]; + //i_LastChannel=cmd->chanlist[1]; + s_BoardInfos[dev->minor].i_FirstChannel = cmd->chanlist[0]; + s_BoardInfos[dev->minor].i_LastChannel = cmd->chanlist[1]; + if (cmd->start_src == TRIG_EXT) { + ui_Trigger = 1; + ui_TriggerEdge = cmd->start_arg & 0xFFFF; + ui_Triggermode = cmd->start_arg >> 16; + } //if(cmd->start_src==TRIG_EXT) + else { + ui_Trigger = 0; + } //elseif(cmd->start_src==TRIG_EXT) + + if (cmd->stop_src == TRIG_COUNT) { + ui_ScanMode = 0; + } // if (cmd->stop_src==TRIG_COUNT) + else { + ui_ScanMode = 2; + } //else if (cmd->stop_src==TRIG_COUNT) + + if (cmd->scan_begin_src == TRIG_FOLLOW) { + ui_DelayTime = 0; + ui_DelayTimeBase = 0; + ui_DelayMode = 0; + } //if(cmd->scan_begin_src==TRIG_FOLLOW) + else { + ui_DelayTime = cmd->scan_begin_arg & 0xFFFF; + ui_DelayTimeBase = cmd->scan_begin_arg >> 16; + ui_DelayMode = 1; + } //else if(cmd->scan_begin_src==TRIG_FOLLOW) + // printk("\nui_DelayTime=%u\n",ui_DelayTime); + // printk("\nui_DelayTimeBase=%u\n",ui_DelayTimeBase); + if (cmd->convert_src == TRIG_TIMER) { + ui_ConvertTime = cmd->convert_arg & 0xFFFF; + ui_ConvertTimeBase = cmd->convert_arg >> 16; + } else { + ui_ConvertTime = 0; + ui_ConvertTimeBase = 0; + } + + // if(i_ADDIDATAType ==1 || ((i_ADDIDATAType==2))) + // { + /**************************************************/ + /*Read the old configuration of the current source */ + /**************************************************/ + //ui_Configuration = inl(devpriv->iobase+i_Offset + 12); + ui_Configuration = + inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); + /***********************************************/ + /*Write the configuration of the current source */ + /***********************************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl((ui_Configuration & 0xFFC00000 ), devpriv->iobase+i_Offset +12); + outl((ui_Configuration & 0xFFC00000), + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 12); + // } + ui_Configuration = 0; + // printk("\nfirstchannel=%u\n",i_FirstChannel); + // printk("\nlastchannel=%u\n",i_LastChannel); + // printk("\nui_Trigger=%u\n",ui_Trigger); + // printk("\nui_TriggerEdge=%u\n",ui_TriggerEdge); + // printk("\nui_Triggermode=%u\n",ui_Triggermode); + // printk("\nui_DelayMode=%u\n",ui_DelayMode); + // printk("\nui_ScanMode=%u\n",ui_ScanMode); + + //ui_Configuration = i_FirstChannel |(i_LastChannel << 8)| 0x00100000 | + ui_Configuration = + s_BoardInfos[dev->minor].i_FirstChannel | (s_BoardInfos[dev-> + minor]. + i_LastChannel << 8) | 0x00100000 | (ui_Trigger << 24) | + (ui_TriggerEdge << 25) | (ui_Triggermode << 27) | (ui_DelayMode + << 18) | (ui_ScanMode << 16); + + /*************************/ + /*Write the Configuration */ + /*************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl( ui_Configuration, devpriv->iobase+i_Offset + 0x8); + outl(ui_Configuration, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 0x8); + /***********************/ + /*Write the Delay Value */ + /***********************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(ui_DelayTime,devpriv->iobase+i_Offset + 40); + outl(ui_DelayTime, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 40); + /***************************/ + /*Write the Delay time base */ + /***************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(ui_DelayTimeBase,devpriv->iobase+i_Offset + 44); + outl(ui_DelayTimeBase, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 44); + /*********************************/ + /*Write the conversion time value */ + /*********************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(ui_ConvertTime,devpriv->iobase+i_Offset + 32); + outl(ui_ConvertTime, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 32); + + /********************************/ + /*Write the conversion time base */ + /********************************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl(ui_ConvertTimeBase,devpriv->iobase+i_Offset + 36); + outl(ui_ConvertTimeBase, + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 36); + /*******************/ + /*Read the register */ + /*******************/ + //ui_Configuration = inl(devpriv->iobase+i_Offset + 4); + ui_Configuration = + inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4); + /******************/ + /*Set the SCAN bit */ + /******************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + + //outl(((ui_Configuration & 0x1E0FF) | 0x00002000),devpriv->iobase+i_Offset + 4); + outl(((ui_Configuration & 0x1E0FF) | 0x00002000), + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 4); + /*******************/ + /*Read the register */ + /*******************/ + ui_Configuration = 0; + //ui_Configuration = inl(devpriv->iobase+i_Offset + 8); + ui_Configuration = + inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + + /*******************/ + /*Set the START bit */ + /*******************/ + //while (((inl(devpriv->iobase+i_Offset+12)>>19) & 1) != 1); + while (((inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + + 12) >> 19) & 1) != 1) ; + //outl((ui_Configuration | 0x00080000),devpriv->iobase+i_Offset + 8); + outl((ui_Configuration | 0x00080000), + devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 8); + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : int i_APCI3200_Reset(struct comedi_device *dev) | + | | + +----------------------------------------------------------------------------+ + | Task :Resets the registers of the card | + +----------------------------------------------------------------------------+ + | Input Parameters : | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + +----------------------------------------------------------------------------+ + | Return Value : | + | | + +----------------------------------------------------------------------------+ +*/ + +int i_APCI3200_Reset(struct comedi_device * dev) +{ + INT i_Temp; + DWORD dw_Dummy; + //i_InterruptFlag=0; + //i_Initialised==0; + //i_Count=0; + //i_Sum=0; + + s_BoardInfos[dev->minor].i_InterruptFlag = 0; + s_BoardInfos[dev->minor].i_Initialised = 0; + s_BoardInfos[dev->minor].i_Count = 0; + s_BoardInfos[dev->minor].i_Sum = 0; + s_BoardInfos[dev->minor].b_StructInitialized = 0; + + outl(0x83838383, devpriv->i_IobaseAmcc + 0x60); + + // Enable the interrupt for the controler + dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38); + outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38); + outl(0, devpriv->i_IobaseAddon); //Resets the output + /***************/ + /*Empty the buffer */ + /**************/ + for (i_Temp = 0; i_Temp <= 95; i_Temp++) { + //ui_InterruptChannelValue[i_Temp]=0; + s_BoardInfos[dev->minor].ui_InterruptChannelValue[i_Temp] = 0; + } //for(i_Temp=0;i_Temp<=95;i_Temp++) + /*****************************/ + /*Reset the START and IRQ bit */ + /*****************************/ + for (i_Temp = 0; i_Temp <= 192;) { + while (((inl(devpriv->iobase + i_Temp + 12) >> 19) & 1) != 1) ; + outl(0, devpriv->iobase + i_Temp + 8); + i_Temp = i_Temp + 64; + } //for(i_Temp=0;i_Temp<=192;i_Temp+64) + return 0; +} + +/* + +----------------------------------------------------------------------------+ + | Function Name : static void v_APCI3200_Interrupt | + | (int irq , void *d) | + +----------------------------------------------------------------------------+ + | Task : Interrupt processing Routine | + +----------------------------------------------------------------------------+ + | Input Parameters : int irq : irq number | + | void *d : void pointer | + +----------------------------------------------------------------------------+ + | Output Parameters : -- | + +----------------------------------------------------------------------------+ + | Return Value : TRUE : No error occur | + | : FALSE : Error occur. Return the error | + | | + +----------------------------------------------------------------------------+ +*/ +void v_APCI3200_Interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + UINT ui_StatusRegister = 0; + UINT ui_ChannelNumber = 0; + INT i_CalibrationFlag = 0; + INT i_CJCFlag = 0; + UINT ui_DummyValue = 0; + UINT ui_DigitalTemperature = 0; + UINT ui_DigitalInput = 0; + int i_ConvertCJCCalibration; + + //BEGIN JK TEST + int i_ReturnValue = 0; + //END JK TEST + + //printk ("\n i_ScanType = %i i_ADDIDATAType = %i", s_BoardInfos [dev->minor].i_ScanType, s_BoardInfos [dev->minor].i_ADDIDATAType); + + //switch(i_ScanType) + switch (s_BoardInfos[dev->minor].i_ScanType) { + case 0: + case 1: + //switch(i_ADDIDATAType) + switch (s_BoardInfos[dev->minor].i_ADDIDATAType) { + case 0: + case 1: + + /************************************/ + /*Read the interrupt status register */ + /************************************/ + //ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); + ui_StatusRegister = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 16); + if ((ui_StatusRegister & 0x2) == 0x2) { + //i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17); + i_CalibrationFlag = + ((inl(devpriv->iobase + + s_BoardInfos[dev-> + minor]. + i_Offset + + 12) & 0x00060000) >> + 17); + /*************************/ + /*Read the channel number */ + /*************************/ + //ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); + + /*************************************/ + /*Read the digital analog input value */ + /*************************************/ + //ui_DigitalInput = inl(devpriv->iobase+i_Offset + 28); + ui_DigitalInput = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 28); + + /***********************************************/ + /* Test if the value read is the channel value */ + /***********************************************/ + if (i_CalibrationFlag == 0) { + //ui_InterruptChannelValue[i_Count + 0] = ui_DigitalInput; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev->minor]. + i_Count + 0] = ui_DigitalInput; + + //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + /* + printk("\n 1 - i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos %i", ui_ChannelNumber); + i_APCI3200_GetChannelCalibrationValue (dev, s_BoardInfos [dev->minor].ui_Channel_num, + &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 6], + &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 7], + &s_BoardInfos [dev->minor].ui_InterruptChannelValue[s_BoardInfos [dev->minor].i_Count + 8]); + */ + //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + + /******************************************************/ + /*Start the conversion of the calibration offset value */ + /******************************************************/ + i_APCI3200_ReadCalibrationOffsetValue + (dev, &ui_DummyValue); + } //if (i_CalibrationFlag == 0) + /**********************************************************/ + /* Test if the value read is the calibration offset value */ + /**********************************************************/ + + if (i_CalibrationFlag == 1) { + + /******************/ + /* Save the value */ + /******************/ + + //ui_InterruptChannelValue[i_Count + 1] = ui_DigitalInput; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev->minor]. + i_Count + 1] = ui_DigitalInput; + + /******************************************************/ + /* Start the conversion of the calibration gain value */ + /******************************************************/ + i_APCI3200_ReadCalibrationGainValue(dev, + &ui_DummyValue); + } //if (i_CalibrationFlag == 1) + /******************************************************/ + /*Test if the value read is the calibration gain value */ + /******************************************************/ + + if (i_CalibrationFlag == 2) { + + /****************/ + /*Save the value */ + /****************/ + //ui_InterruptChannelValue[i_Count + 2] = ui_DigitalInput; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev->minor]. + i_Count + 2] = ui_DigitalInput; + //if(i_ScanType==1) + if (s_BoardInfos[dev->minor]. + i_ScanType == 1) { + + //i_InterruptFlag=0; + s_BoardInfos[dev->minor]. + i_InterruptFlag = 0; + //i_Count=i_Count + 6; + //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6; + s_BoardInfos[dev->minor]. + i_Count = + s_BoardInfos[dev-> + minor].i_Count + 9; + //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + } //if(i_ScanType==1) + else { + //i_Count=0; + s_BoardInfos[dev->minor]. + i_Count = 0; + } //elseif(i_ScanType==1) + //if(i_ScanType!=1) + if (s_BoardInfos[dev->minor]. + i_ScanType != 1) { + i_ReturnValue = send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + } //if(i_ScanType!=1) + else { + //if(i_ChannelCount==i_Sum) + if (s_BoardInfos[dev->minor]. + i_ChannelCount == + s_BoardInfos[dev-> + minor].i_Sum) { + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + } + } //if(i_ScanType!=1) + } //if (i_CalibrationFlag == 2) + } // if ((ui_StatusRegister & 0x2) == 0x2) + + break; + + case 2: + /************************************/ + /*Read the interrupt status register */ + /************************************/ + + //ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); + ui_StatusRegister = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 16); + /*************************/ + /*Test if interrupt occur */ + /*************************/ + + if ((ui_StatusRegister & 0x2) == 0x2) { + + //i_CJCFlag = ((inl(devpriv->iobase+i_Offset + 4) & 0x00000400) >> 10); + i_CJCFlag = + ((inl(devpriv->iobase + + s_BoardInfos[dev-> + minor]. + i_Offset + + 4) & 0x00000400) >> 10); + + //i_CalibrationFlag = ((inl(devpriv->iobase+i_Offset + 12) & 0x00060000) >> 17); + i_CalibrationFlag = + ((inl(devpriv->iobase + + s_BoardInfos[dev-> + minor]. + i_Offset + + 12) & 0x00060000) >> + 17); + + /*************************/ + /*Read the channel number */ + /*************************/ + + //ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); + ui_ChannelNumber = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 24); + //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + s_BoardInfos[dev->minor].ui_Channel_num = + ui_ChannelNumber; + //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + + /************************************/ + /*Read the digital temperature value */ + /************************************/ + //ui_DigitalTemperature = inl(devpriv->iobase+i_Offset + 28); + ui_DigitalTemperature = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 28); + + /*********************************************/ + /*Test if the value read is the channel value */ + /*********************************************/ + + if ((i_CalibrationFlag == 0) + && (i_CJCFlag == 0)) { + //ui_InterruptChannelValue[i_Count + 0]=ui_DigitalTemperature; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev->minor]. + i_Count + 0] = + ui_DigitalTemperature; + + /*********************************/ + /*Start the conversion of the CJC */ + /*********************************/ + i_APCI3200_ReadCJCValue(dev, + &ui_DummyValue); + + } //if ((i_CalibrationFlag == 0) && (i_CJCFlag == 0)) + + /*****************************************/ + /*Test if the value read is the CJC value */ + /*****************************************/ + + if ((i_CJCFlag == 1) + && (i_CalibrationFlag == 0)) { + //ui_InterruptChannelValue[i_Count + 3]=ui_DigitalTemperature; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev->minor]. + i_Count + 3] = + ui_DigitalTemperature; + + /******************************************************/ + /*Start the conversion of the calibration offset value */ + /******************************************************/ + i_APCI3200_ReadCalibrationOffsetValue + (dev, &ui_DummyValue); + } // if ((i_CJCFlag == 1) && (i_CalibrationFlag == 0)) + + /********************************************************/ + /*Test if the value read is the calibration offset value */ + /********************************************************/ + + if ((i_CalibrationFlag == 1) + && (i_CJCFlag == 0)) { + //ui_InterruptChannelValue[i_Count + 1]=ui_DigitalTemperature; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev->minor]. + i_Count + 1] = + ui_DigitalTemperature; + + /****************************************************/ + /*Start the conversion of the calibration gain value */ + /****************************************************/ + i_APCI3200_ReadCalibrationGainValue(dev, + &ui_DummyValue); + + } //if ((i_CalibrationFlag == 1) && (i_CJCFlag == 0)) + + /******************************************************/ + /*Test if the value read is the calibration gain value */ + /******************************************************/ + + if ((i_CalibrationFlag == 2) + && (i_CJCFlag == 0)) { + //ui_InterruptChannelValue[i_Count + 2]=ui_DigitalTemperature; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev->minor]. + i_Count + 2] = + ui_DigitalTemperature; + + /**********************************************************/ + /*Test if the Calibration channel must be read for the CJC */ + /**********************************************************/ + + /*Test if the polarity is the same */ + /**********************************/ + //if(i_CJCPolarity!=i_ADDIDATAPolarity) + if (s_BoardInfos[dev->minor]. + i_CJCPolarity != + s_BoardInfos[dev->minor]. + i_ADDIDATAPolarity) { + i_ConvertCJCCalibration = 1; + } //if(i_CJCPolarity!=i_ADDIDATAPolarity) + else { + //if(i_CJCGain==i_ADDIDATAGain) + if (s_BoardInfos[dev->minor]. + i_CJCGain == + s_BoardInfos[dev-> + minor]. + i_ADDIDATAGain) { + i_ConvertCJCCalibration + = 0; + } //if(i_CJCGain==i_ADDIDATAGain) + else { + i_ConvertCJCCalibration + = 1; + } //elseif(i_CJCGain==i_ADDIDATAGain) + } //elseif(i_CJCPolarity!=i_ADDIDATAPolarity) + if (i_ConvertCJCCalibration == 1) { + /****************************************************************/ + /*Start the conversion of the calibration gain value for the CJC */ + /****************************************************************/ + i_APCI3200_ReadCJCCalOffset(dev, + &ui_DummyValue); + + } //if(i_ConvertCJCCalibration==1) + else { + //ui_InterruptChannelValue[i_Count + 4]=0; + //ui_InterruptChannelValue[i_Count + 5]=0; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev-> + minor].i_Count + + 4] = 0; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev-> + minor].i_Count + + 5] = 0; + } //elseif(i_ConvertCJCCalibration==1) + } //else if ((i_CalibrationFlag == 2) && (i_CJCFlag == 0)) + + /********************************************************************/ + /*Test if the value read is the calibration offset value for the CJC */ + /********************************************************************/ + + if ((i_CalibrationFlag == 1) + && (i_CJCFlag == 1)) { + //ui_InterruptChannelValue[i_Count + 4]=ui_DigitalTemperature; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev->minor]. + i_Count + 4] = + ui_DigitalTemperature; + + /****************************************************************/ + /*Start the conversion of the calibration gain value for the CJC */ + /****************************************************************/ + i_APCI3200_ReadCJCCalGain(dev, + &ui_DummyValue); + + } //if ((i_CalibrationFlag == 1) && (i_CJCFlag == 1)) + + /******************************************************************/ + /*Test if the value read is the calibration gain value for the CJC */ + /******************************************************************/ + + if ((i_CalibrationFlag == 2) + && (i_CJCFlag == 1)) { + //ui_InterruptChannelValue[i_Count + 5]=ui_DigitalTemperature; + s_BoardInfos[dev->minor]. + ui_InterruptChannelValue + [s_BoardInfos[dev->minor]. + i_Count + 5] = + ui_DigitalTemperature; + + //if(i_ScanType==1) + if (s_BoardInfos[dev->minor]. + i_ScanType == 1) { + + //i_InterruptFlag=0; + s_BoardInfos[dev->minor]. + i_InterruptFlag = 0; + //i_Count=i_Count + 6; + //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + //s_BoardInfos [dev->minor].i_Count=s_BoardInfos [dev->minor].i_Count + 6; + s_BoardInfos[dev->minor]. + i_Count = + s_BoardInfos[dev-> + minor].i_Count + 9; + //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + } //if(i_ScanType==1) + else { + //i_Count=0; + s_BoardInfos[dev->minor]. + i_Count = 0; + } //elseif(i_ScanType==1) + + //if(i_ScanType!=1) + if (s_BoardInfos[dev->minor]. + i_ScanType != 1) { + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + } //if(i_ScanType!=1) + else { + //if(i_ChannelCount==i_Sum) + if (s_BoardInfos[dev->minor]. + i_ChannelCount == + s_BoardInfos[dev-> + minor].i_Sum) { + send_sig(SIGIO, devpriv->tsk_Current, 0); // send signal to the sample + + } //if(i_ChannelCount==i_Sum) + } //else if(i_ScanType!=1) + } //if ((i_CalibrationFlag == 2) && (i_CJCFlag == 1)) + + } //else if ((ui_StatusRegister & 0x2) == 0x2) + break; + } //switch(i_ADDIDATAType) + break; + case 2: + case 3: + i_APCI3200_InterruptHandleEos(dev); + break; + } //switch(i_ScanType) + return; +} + +/* + +----------------------------------------------------------------------------+ + | Function name :int i_APCI3200_InterruptHandleEos(struct comedi_device *dev) | + | | + | | + +----------------------------------------------------------------------------+ + | Task : . | + | This function copies the acquired data(from FIFO) | + | to Comedi buffer. | + | | + +----------------------------------------------------------------------------+ + | Input Parameters : struct comedi_device *dev | + | | + | | + +----------------------------------------------------------------------------+ + | Return Value : 0 | + | | + +----------------------------------------------------------------------------+ +*/ +int i_APCI3200_InterruptHandleEos(struct comedi_device * dev) +{ + UINT ui_StatusRegister = 0; + struct comedi_subdevice *s = dev->subdevices + 0; + + //BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + //comedi_async *async = s->async; + //UINT *data; + //data=async->data+async->buf_int_ptr;//new samples added from here onwards + int n = 0, i = 0; + //END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + + /************************************/ + /*Read the interrupt status register */ + /************************************/ + //ui_StatusRegister = inl(devpriv->iobase+i_Offset + 16); + ui_StatusRegister = + inl(devpriv->iobase + s_BoardInfos[dev->minor].i_Offset + 16); + + /*************************/ + /*Test if interrupt occur */ + /*************************/ + + if ((ui_StatusRegister & 0x2) == 0x2) { + /*************************/ + /*Read the channel number */ + /*************************/ + //ui_ChannelNumber = inl(devpriv->iobase+i_Offset + 24); + //BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + //This value is not used + //ui_ChannelNumber = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 24); + s->async->events = 0; + //END JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + + /*************************************/ + /*Read the digital Analog Input value */ + /*************************************/ + + //data[i_Count] = inl(devpriv->iobase+i_Offset + 28); + //Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + //data[s_BoardInfos [dev->minor].i_Count] = inl(devpriv->iobase+s_BoardInfos [dev->minor].i_Offset + 28); + s_BoardInfos[dev->minor].ui_ScanValueArray[s_BoardInfos[dev-> + minor].i_Count] = + inl(devpriv->iobase + + s_BoardInfos[dev->minor].i_Offset + 28); + //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + + //if((i_Count == (i_LastChannel-i_FirstChannel+3))) + if ((s_BoardInfos[dev->minor].i_Count == + (s_BoardInfos[dev->minor].i_LastChannel - + s_BoardInfos[dev->minor]. + i_FirstChannel + 3))) { + + //Begin JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + s_BoardInfos[dev->minor].i_Count++; + + for (i = s_BoardInfos[dev->minor].i_FirstChannel; + i <= s_BoardInfos[dev->minor].i_LastChannel; + i++) { + i_APCI3200_GetChannelCalibrationValue(dev, i, + &s_BoardInfos[dev->minor]. + ui_ScanValueArray[s_BoardInfos[dev-> + minor].i_Count + ((i - + s_BoardInfos + [dev->minor]. + i_FirstChannel) + * 3)], + &s_BoardInfos[dev->minor]. + ui_ScanValueArray[s_BoardInfos[dev-> + minor].i_Count + ((i - + s_BoardInfos + [dev->minor]. + i_FirstChannel) + * 3) + 1], + &s_BoardInfos[dev->minor]. + ui_ScanValueArray[s_BoardInfos[dev-> + minor].i_Count + ((i - + s_BoardInfos + [dev->minor]. + i_FirstChannel) + * 3) + 2]); + } + + //End JK 22.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + + //i_Count=-1; + + s_BoardInfos[dev->minor].i_Count = -1; + + //async->buf_int_count+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT); + //Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + //async->buf_int_count+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(UINT); + //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + //async->buf_int_ptr+=(i_LastChannel-i_FirstChannel+4)*sizeof(UINT); + //Begin JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + //async->buf_int_ptr+=(s_BoardInfos [dev->minor].i_LastChannel-s_BoardInfos [dev->minor].i_FirstChannel+4)*sizeof(UINT); + //comedi_eos(dev,s); + + // Set the event type (Comedi Buffer End Of Scan) + s->async->events |= COMEDI_CB_EOS; + + // Test if enougth memory is available and allocate it for 7 values + //n = comedi_buf_write_alloc(s->async, 7*sizeof(unsigned int)); + n = comedi_buf_write_alloc(s->async, + (7 + 12) * sizeof(unsigned int)); + + // If not enougth memory available, event is set to Comedi Buffer Errror + if (n > ((7 + 12) * sizeof(unsigned int))) { + printk("\ncomedi_buf_write_alloc n = %i", n); + s->async->events |= COMEDI_CB_ERROR; + } + // Write all 7 scan values in the comedi buffer + comedi_buf_memcpy_to(s->async, 0, + (unsigned int *) s_BoardInfos[dev->minor]. + ui_ScanValueArray, (7 + 12) * sizeof(unsigned int)); + + // Update comedi buffer pinters indexes + comedi_buf_write_free(s->async, + (7 + 12) * sizeof(unsigned int)); + + // Send events + comedi_event(dev, s); + //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + + //BEGIN JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + // + //if (s->async->buf_int_ptr>=s->async->data_len) // for buffer rool over + // { + // /* buffer rollover */ + // s->async->buf_int_ptr=0; + // comedi_eobuf(dev,s); + // } + //End JK 18.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + } + //i_Count++; + s_BoardInfos[dev->minor].i_Count++; + } + //i_InterruptFlag=0; + s_BoardInfos[dev->minor].i_InterruptFlag = 0; + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h new file mode 100644 index 000000000000..a6f57f55e79c --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +// Card Specific information +#define APCI3200_BOARD_VENDOR_ID 0x15B8 +//#define APCI3200_ADDRESS_RANGE 264 + +int MODULE_NO; +struct { + INT i_Gain; + INT i_Polarity; + INT i_OffsetRange; + INT i_Coupling; + INT i_SingleDiff; + INT i_AutoCalibration; + UINT ui_ReloadValue; + UINT ui_TimeUnitReloadVal; + INT i_Interrupt; + INT i_ModuleSelection; +} Config_Parameters_Module1, Config_Parameters_Module2, + Config_Parameters_Module3, Config_Parameters_Module4; + +//ANALOG INPUT RANGE +static const struct comedi_lrange range_apci3200_ai = { 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1) + } +}; + +static const struct comedi_lrange range_apci3300_ai = { 4, { + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1) + } +}; + +//Analog Input related Defines +#define APCI3200_AI_OFFSET_GAIN 0 +#define APCI3200_AI_SC_TEST 4 +#define APCI3200_AI_IRQ 8 +#define APCI3200_AI_AUTOCAL 12 +#define APCI3200_RELOAD_CONV_TIME_VAL 32 +#define APCI3200_CONV_TIME_TIME_BASE 36 +#define APCI3200_RELOAD_DELAY_TIME_VAL 40 +#define APCI3200_DELAY_TIME_TIME_BASE 44 +#define APCI3200_AI_MODULE1 0 +#define APCI3200_AI_MODULE2 64 +#define APCI3200_AI_MODULE3 128 +#define APCI3200_AI_MODULE4 192 +#define TRUE 1 +#define FALSE 0 +#define APCI3200_AI_EOSIRQ 16 +#define APCI3200_AI_EOS 20 +#define APCI3200_AI_CHAN_ID 24 +#define APCI3200_AI_CHAN_VAL 28 +#define ANALOG_INPUT 0 +#define TEMPERATURE 1 +#define RESISTANCE 2 + +#define ENABLE_EXT_TRIG 1 +#define ENABLE_EXT_GATE 2 +#define ENABLE_EXT_TRIG_GATE 3 + +#define APCI3200_MAXVOLT 2.5 +#define ADDIDATA_GREATER_THAN_TEST 0 +#define ADDIDATA_LESS_THAN_TEST 1 + +#define ADDIDATA_UNIPOLAR 1 +#define ADDIDATA_BIPOLAR 2 + +//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values +#define MAX_MODULE 4 +//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + +typedef struct { + ULONG ul_NumberOfValue; + ULONG *pul_ResistanceValue; + ULONG *pul_TemperatureValue; +} str_ADDIDATA_RTDStruct, *pstr_ADDIDATA_RTDStruct; + +//BEGIN JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values +typedef struct { + // Begin JK 05/08/2003 change for Linux + unsigned long ul_CurrentSourceCJC; + unsigned long ul_CurrentSource[5]; + // End JK 05/08/2003 change for Linux + + // Begin CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1 + unsigned long ul_GainFactor[8]; // Gain Factor + unsigned int w_GainValue[10]; + // End CG 15/02/02 Rev 1.0 -> Rev 1.1 : Add Header Type 1 +} str_Module; +//END JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + +//BEGIN JK 06.07.04: Management of sevrals boards +typedef struct { + INT i_CJCAvailable; + INT i_CJCPolarity; + INT i_CJCGain; + INT i_InterruptFlag; + INT i_ADDIDATAPolarity; + INT i_ADDIDATAGain; + INT i_AutoCalibration; + INT i_ADDIDATAConversionTime; + INT i_ADDIDATAConversionTimeUnit; + INT i_ADDIDATAType; + INT i_ChannelNo; + INT i_ChannelCount; + INT i_ScanType; + INT i_FirstChannel; + INT i_LastChannel; + INT i_Sum; + INT i_Offset; + UINT ui_Channel_num; + INT i_Count; + INT i_Initialised; + //UINT ui_InterruptChannelValue[96]; //Buffer + UINT ui_InterruptChannelValue[144]; //Buffer + BYTE b_StructInitialized; + //Begin JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + unsigned int ui_ScanValueArray[7 + 12]; // 7 is the maximal number of channels + //End JK 19.10.2004: APCI-3200 Driver update 0.7.57 -> 0.7.68 + + //Begin JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values + INT i_ConnectionType; + INT i_NbrOfModule; + str_Module s_Module[MAX_MODULE]; + //End JK 21.10.2004: APCI-3200 / APCI-3300 Reading of EEPROM values +} str_BoardInfos; +//END JK 06.07.04: Management of sevrals boards + +// Hardware Layer functions for Apci3200 + +//AI + +INT i_APCI3200_ConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI3200_ReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI3200_InsnWriteReleaseAnalogInput(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI3200_InsnBits_AnalogInput_Test(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI3200_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s); +INT i_APCI3200_InterruptHandleEos(struct comedi_device *dev); +INT i_APCI3200_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd); +INT i_APCI3200_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s); +INT i_APCI3200_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +//Interrupt +void v_APCI3200_Interrupt(int irq, void *d); +int i_APCI3200_InterruptHandleEos(struct comedi_device *dev); +//Reset functions +INT i_APCI3200_Reset(struct comedi_device *dev); + +int i_APCI3200_ReadCJCCalOffset(struct comedi_device *dev, unsigned int *data); +int i_APCI3200_ReadCJCValue(struct comedi_device *dev, unsigned int *data); +int i_APCI3200_ReadCalibrationGainValue(struct comedi_device *dev, UINT *data); +int i_APCI3200_ReadCalibrationOffsetValue(struct comedi_device *dev, UINT *data); +int i_APCI3200_Read1AnalogInputChannel(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, + unsigned int *data); +int i_APCI3200_ReadCJCCalGain(struct comedi_device *dev, unsigned int *data); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c new file mode 100644 index 000000000000..20391a91da03 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c @@ -0,0 +1,742 @@ +/** +@verbatim + +Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + + ADDI-DATA GmbH + Dieselstrasse 3 + D-77833 Ottersweier + Tel: +19(0)7223/9493-0 + Fax: +49(0)7223/9493-92 + http://www.addi-data-com + info@addi-data.com + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You shoud also find the complete GPL in the COPYING file accompanying this source code. + +@endverbatim +*/ +/*. + + +-----------------------------------------------------------------------+ + | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-------------------------------+---------------------------------------+ + | Project : APCI-3501 | Compiler : GCC | + | Module name : hwdrv_apci3501.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: Eric Stolz | Date : 02/12/2002 | + +-------------------------------+---------------------------------------+ + | Description : Hardware Layer Acces For APCI-3501 | + +-----------------------------------------------------------------------+ + | UPDATES | + +----------+-----------+------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Included files | ++----------------------------------------------------------------------------+ +*/ +#include "hwdrv_apci3501.h" + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ReadDigitalInput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +INT i_APCI3501_ReadDigitalInput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + ui_NoOfChannel = CR_CHAN(insn->chanspec); + ui_Temp = data[0]; + *data = inl(devpriv->iobase + APCI3501_DIGITAL_IP); + if (ui_Temp == 0) { + *data = (*data >> ui_NoOfChannel) & 0x1; + } //if (ui_Temp==0) + else { + if (ui_Temp == 1) { + + *data = *data & 0x3; + } //if (ui_Temp==1) + else { + printk("\nSpecified channel not supported \n"); + } //elseif (ui_Temp==1) + } //elseif (ui_Temp==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ConfigDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Digital Output Subdevice. | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[1] : 1 Enable VCC Interrupt | +| 0 Disable VCC Interrupt | +| data[2] : 1 Enable CC Interrupt | +| 0 Disable CC Interrupt | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3501_ConfigDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + if ((data[0] != 0) && (data[0] != 1)) { + comedi_error(dev, + "Not a valid Data !!! ,Data should be 1 or 0\n"); + return -EINVAL; + } //if ( (data[0]!=0) && (data[0]!=1) ) + if (data[0]) { + devpriv->b_OutputMemoryStatus = ADDIDATA_ENABLE; + } // if (data[0]) + else { + devpriv->b_OutputMemoryStatus = ADDIDATA_DISABLE; + } //else if (data[0]) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_WriteDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : writes To the digital Output Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s : Subdevice Pointer | +| struct comedi_insn *insn : Insn Structure Pointer | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_WriteDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp, ui_Temp1; + UINT ui_NoOfChannel = CR_CHAN(insn->chanspec); // get the channel + if (devpriv->b_OutputMemoryStatus) { + ui_Temp = inl(devpriv->iobase + APCI3501_DIGITAL_OP); + } //if(devpriv->b_OutputMemoryStatus ) + else { + ui_Temp = 0; + } //if(devpriv->b_OutputMemoryStatus ) + if (data[3] == 0) { + if (data[1] == 0) { + data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; + outl(data[0], devpriv->iobase + APCI3501_DIGITAL_OP); + } //if(data[1]==0) + else { + if (data[1] == 1) { + data[0] = (data[0] << (2 * data[2])) | ui_Temp; + outl(data[0], + devpriv->iobase + APCI3501_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==0) + else { + if (data[3] == 1) { + if (data[1] == 0) { + data[0] = ~data[0] & 0x1; + ui_Temp1 = 1; + ui_Temp1 = ui_Temp1 << ui_NoOfChannel; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + (data[0] << ui_NoOfChannel) ^ + 0xffffffff; + data[0] = data[0] & ui_Temp; + outl(data[0], + devpriv->iobase + APCI3501_DIGITAL_OP); + } //if(data[1]==0) + else { + if (data[1] == 1) { + data[0] = ~data[0] & 0x3; + ui_Temp1 = 3; + ui_Temp1 = ui_Temp1 << 2 * data[2]; + ui_Temp = ui_Temp | ui_Temp1; + data[0] = + ((data[0] << (2 * + data[2])) ^ + 0xffffffff) & ui_Temp; + outl(data[0], + devpriv->iobase + + APCI3501_DIGITAL_OP); + } // if(data[1]==1) + else { + printk("\nSpecified channel not supported\n"); + } //else if(data[1]==1) + } //elseif(data[1]==0) + } //if(data[3]==1); + else { + printk("\nSpecified functionality does not exist\n"); + return -EINVAL; + } //if else data[3]==1) + } //if else data[3]==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ReadDigitalOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read value of the selected channel or port | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT ui_NoOfChannels : No Of Channels To read | +| UINT *data : Data Pointer to read status | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_ReadDigitalOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + UINT ui_Temp; + UINT ui_NoOfChannel; + + ui_NoOfChannel = CR_CHAN(insn->chanspec); + ui_Temp = data[0]; + *data = inl(devpriv->iobase + APCI3501_DIGITAL_OP); + if (ui_Temp == 0) { + *data = (*data >> ui_NoOfChannel) & 0x1; + } // if (ui_Temp==0) + else { + if (ui_Temp == 1) { + *data = *data & 0x3; + + } // if (ui_Temp==1) + else { + printk("\nSpecified channel not supported \n"); + } // else if (ui_Temp==1) + } // else if (ui_Temp==0) + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ConfigAnalogOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Analog Output Subdevice | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s : Subdevice Pointer | +| struct comedi_insn *insn : Insn Structure Pointer | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : Voltage Mode | +| 0:Mode 0 | +| 1:Mode 1 | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_ConfigAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + outl(data[0], + devpriv->iobase + APCI3501_ANALOG_OUTPUT + + APCI3501_AO_VOLT_MODE); + + if (data[0]) { + devpriv->b_InterruptMode = MODE1; + } else { + devpriv->b_InterruptMode = MODE0; + } + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_WriteAnalogOutput | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Writes To the Selected Anlog Output Channel | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| struct comedi_subdevice *s : Subdevice Pointer | +| struct comedi_insn *insn : Insn Structure Pointer | +| unsigned int *data : Data Pointer contains | +| configuration parameters as below | +| | +| | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_WriteAnalogOutput(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + ULONG ul_Command1 = 0, ul_Channel_no, ul_Polarity, ul_DAC_Ready = 0;; + + ul_Channel_no = CR_CHAN(insn->chanspec); + + if (devpriv->b_InterruptMode == MODE1) { + ul_Polarity = 0x80000000; + if ((*data < 0) || (*data > 16384)) { + printk("\nIn WriteAnalogOutput :: Not Valid Data\n"); + } + + } // end if(devpriv->b_InterruptMode==MODE1) + else { + ul_Polarity = 0; + if ((*data < 0) || (*data > 8192)) { + printk("\nIn WriteAnalogOutput :: Not Valid Data\n"); + } + + } // end else + + if ((ul_Channel_no < 0) || (ul_Channel_no > 7)) { + printk("\nIn WriteAnalogOutput :: Not Valid Channel\n"); + } // end if((ul_Channel_no<0)||(ul_Channel_no>7)) + + ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT); + + while (ul_DAC_Ready == 0) { + ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT); + ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1; + } + + if (ul_DAC_Ready) { +// Output the Value on the output channels. + ul_Command1 = + (ULONG) ((ULONG) (ul_Channel_no & 0xFF) | + (ULONG) ((*data << 0x8) & 0x7FFFFF00L) | + (ULONG) (ul_Polarity)); + outl(ul_Command1, + devpriv->iobase + APCI3501_ANALOG_OUTPUT + + APCI3501_AO_PROG); + } + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ConfigTimerCounterWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Configures The Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Configure As Timer | +| 1 Configure As Counter | +| 2 Configure As Watchdog | +| data[1] : 1 Enable Interrupt | +| 0 Disable Interrupt | +| data[2] : Time Unit | +| data[3] : Reload Value | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + ULONG ul_Command1 = 0; + devpriv->tsk_Current = current; + if (data[0] == ADDIDATA_WATCHDOG) { + + devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG; + //Disable the watchdog + outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //disable Wa + + if (data[1] == 1) { + //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES + outl(0x02, + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + } else { + outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //disable Timer interrupt + } + + //Loading the Timebase value + outl(data[2], + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_TIMEBASE); + + //Loading the Reload value + outl(data[3], + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_RELOAD_VALUE); + //Set the mode + ul_Command1 = inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG) | 0xFFF819E0UL; //e2->e0 + outl(ul_Command1, + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + } //end if(data[0]==ADDIDATA_WATCHDOG) + + else if (data[0] == ADDIDATA_TIMER) { + //First Stop The Timer + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //Stop The Timer + devpriv->b_TimerSelectMode = ADDIDATA_TIMER; + if (data[1] == 1) { + //Enable TIMER int & DISABLE ALL THE OTHER int SOURCES + outl(0x02, + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + } else { + outl(0x0, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //disable Timer interrupt + } + + // Loading Timebase + outl(data[2], + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_TIMEBASE); + + //Loading the Reload value + outl(data[3], + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_RELOAD_VALUE); + + // printk ("\nTimer Address :: %x\n", (devpriv->iobase+APCI3501_WATCHDOG)); + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + ul_Command1 = + (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL; + outl(ul_Command1, devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); //mode 2 + + } //end if(data[0]==ADDIDATA_TIMER) + + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_StartStopWriteTimerCounterWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Start / Stop The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Timer | +| 1 Counter | +| 2 Watchdog | | data[1] : 1 Start | +| 0 Stop | 2 Trigger | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + ULONG ul_Command1 = 0; + int i_Temp; + if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { + + if (data[1] == 1) { + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; + //Enable the Watchdog + outl(ul_Command1, + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + } + + else if (data[1] == 0) //Stop The Watchdog + { + //Stop The Watchdog + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; + outl(0x0, + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + } else if (data[1] == 2) { + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL; + outl(ul_Command1, + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + } //if(data[1]==2) + } // end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + + if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { + if (data[1] == 1) { + + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL; + //Enable the Timer + outl(ul_Command1, + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + } else if (data[1] == 0) { + //Stop The Timer + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + ul_Command1 = ul_Command1 & 0xFFFFF9FEUL; + outl(ul_Command1, + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + } + + else if (data[1] == 2) { + //Trigger the Timer + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL; + outl(ul_Command1, + devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_PROG); + } + + } // end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + i_Temp = inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_TRIG_STATUS) & 0x1; + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_ReadTimerCounterWatchdog | +| (struct comedi_device *dev,struct comedi_subdevice *s, | +| struct comedi_insn *insn,unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read The Selected Timer , Counter or Watchdog | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev : Driver handle | +| UINT *data : Data Pointer contains | +| configuration parameters as below | +| | +| data[0] : 0 Timer | +| 1 Counter | +| 2 Watchdog | | data[1] : Timer Counter Watchdog Number | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + + if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { + data[0] = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_TRIG_STATUS) & 0x1; + data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG); + } // end if (devpriv->b_TimerSelectMode==ADDIDATA_WATCHDOG) + + else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) { + data[0] = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_TRIG_STATUS) & 0x1; + data[1] = inl(devpriv->iobase + APCI3501_WATCHDOG); + } // end if (devpriv->b_TimerSelectMode==ADDIDATA_TIMER) + + else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER) + && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) { + printk("\nIn ReadTimerCounterWatchdog :: Invalid Subdevice \n"); + } + return insn->n; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3501_Reset(struct comedi_device *dev) | +| | ++----------------------------------------------------------------------------+ +| Task :Resets the registers of the card | ++----------------------------------------------------------------------------+ +| Input Parameters : | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : | +| | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3501_Reset(struct comedi_device * dev) +{ + int i_Count = 0, i_temp = 0; + ULONG ul_Command1 = 0, ul_Polarity, ul_DAC_Ready = 0; + outl(0x0, devpriv->iobase + APCI3501_DIGITAL_OP); + outl(1, devpriv->iobase + APCI3501_ANALOG_OUTPUT + + APCI3501_AO_VOLT_MODE); + + ul_Polarity = 0x80000000; + + for (i_Count = 0; i_Count <= 7; i_Count++) { + ul_DAC_Ready = inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT); + + while (ul_DAC_Ready == 0) { + ul_DAC_Ready = + inl(devpriv->iobase + APCI3501_ANALOG_OUTPUT); + ul_DAC_Ready = (ul_DAC_Ready >> 8) & 1; + } + + if (ul_DAC_Ready) { + // Output the Value on the output channels. + ul_Command1 = + (ULONG) ((ULONG) (i_Count & 0xFF) | + (ULONG) ((i_temp << 0x8) & 0x7FFFFF00L) | + (ULONG) (ul_Polarity)); + outl(ul_Command1, + devpriv->iobase + APCI3501_ANALOG_OUTPUT + + APCI3501_AO_PROG); + } + } + + return 0; +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : static void v_APCI3501_Interrupt | +| (int irq , void *d) | ++----------------------------------------------------------------------------+ +| Task : Interrupt processing Routine | ++----------------------------------------------------------------------------+ +| Input Parameters : int irq : irq number | +| void *d : void pointer | ++----------------------------------------------------------------------------+ +| Output Parameters : -- | ++----------------------------------------------------------------------------+ +| Return Value : TRUE : No error occur | +| : FALSE : Error occur. Return the error | +| | ++----------------------------------------------------------------------------+ +*/ +void v_APCI3501_Interrupt(int irq, void *d) +{ + int i_temp; + struct comedi_device *dev = d; + unsigned int ui_Timer_AOWatchdog; + unsigned long ul_Command1; + // Disable Interrupt + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); + + ul_Command1 = (ul_Command1 & 0xFFFFF9FDul); + outl(ul_Command1, + devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); + + ui_Timer_AOWatchdog = + inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_IRQ) & 0x1; + + if ((!ui_Timer_AOWatchdog)) { + comedi_error(dev, "IRQ from unknow source"); + return; + } + + // Enable Interrupt + //Send a signal to from kernel to user space + send_sig(SIGIO, devpriv->tsk_Current, 0); + ul_Command1 = + inl(devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); + ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1); + outl(ul_Command1, + devpriv->iobase + APCI3501_WATCHDOG + APCI3501_TCW_PROG); + i_temp = inl(devpriv->iobase + APCI3501_WATCHDOG + + APCI3501_TCW_TRIG_STATUS) & 0x1; + return; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h new file mode 100644 index 000000000000..51e7b66544ac --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +// Card Specific information +#define APCI3501_BOARD_VENDOR_ID 0x15B8 +#define APCI3501_ADDRESS_RANGE 255 + +#define APCI3501_DIGITAL_IP 0x50 +#define APCI3501_DIGITAL_OP 0x40 +#define APCI3501_ANALOG_OUTPUT 0x00 + +//Analog Output related Defines +#define APCI3501_AO_VOLT_MODE 0 +#define APCI3501_AO_PROG 4 +#define APCI3501_AO_TRIG_SCS 8 +#define UNIPOLAR 0 +#define BIPOLAR 1 +#define MODE0 0 +#define MODE1 1 +// ANALOG OUTPUT RANGE +struct comedi_lrange range_apci3501_ao = { 2, { + BIP_RANGE(10), + UNI_RANGE(10) + } +}; + +//Watchdog Related Defines + +#define APCI3501_WATCHDOG 0x20 +#define APCI3501_TCW_SYNC_ENABLEDISABLE 0 +#define APCI3501_TCW_RELOAD_VALUE 4 +#define APCI3501_TCW_TIMEBASE 8 +#define APCI3501_TCW_PROG 12 +#define APCI3501_TCW_TRIG_STATUS 16 +#define APCI3501_TCW_IRQ 20 +#define APCI3501_TCW_WARN_TIMEVAL 24 +#define APCI3501_TCW_WARN_TIMEBASE 28 +#define ADDIDATA_TIMER 0 +#define ADDIDATA_WATCHDOG 2 + +// Hardware Layer functions for Apci3501 + +//AO +INT i_APCI3501_ConfigAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI3501_WriteAnalogOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//DI +// for di read +//INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); + +INT i_APCI3501_ReadDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +//DO +int i_APCI3501_ConfigDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI3501_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +INT i_APCI3501_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); + +// TIMER +// timer value is passed as u seconds +INT i_APCI3501_ConfigTimerCounterWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +int i_APCI3501_StartStopWriteTimerCounterWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data); +int i_APCI3501_ReadTimerCounterWatchdog(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +//Interrupt +void v_APCI3501_Interrupt(int irq, void *d); + +//Reset functions +int i_APCI3501_Reset(struct comedi_device *dev); diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c new file mode 100644 index 000000000000..b7268e4da64e --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c @@ -0,0 +1,1691 @@ +/** +@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 Dieselstrasse 3 D-77833 Ottersweier | + +-----------------------------------------------------------------------+ + | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | + | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | + +-----------------------------------------------------------------------+ + | Project : APCI-3XXX | Compiler : GCC | + | Module name : hwdrv_apci3xxx.c| Version : 2.96 | + +-------------------------------+---------------------------------------+ + | Project manager: S. Weber | Date : 15/09/2005 | + +-----------------------------------------------------------------------+ + | Description :APCI3XXX Module. Hardware abstraction Layer for APCI3XXX| + +-----------------------------------------------------------------------+ + | UPDATE'S | + +-----------------------------------------------------------------------+ + | Date | Author | Description of updates | + +----------+-----------+------------------------------------------------+ + | | | | + | | | | + +----------+-----------+------------------------------------------------+ +*/ + +#include "hwdrv_apci3xxx.h" + +/* ++----------------------------------------------------------------------------+ +| ANALOG INPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3XXX_TestConversionStarted | +| (struct comedi_device *dev) | ++----------------------------------------------------------------------------+ +| Task Test if any conversion started | ++----------------------------------------------------------------------------+ +| Input Parameters : - | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 : Conversion not started | +| 1 : Conversion started | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_TestConversionStarted(struct comedi_device * dev) +{ + if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL) { + return (1); + } else { + return (0); + } +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3XXX_AnalogInputConfigOperatingMode | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task Converting mode and convert time selection | ++----------------------------------------------------------------------------+ +| Input Parameters : b_SingleDiff = (BYTE) data[1]; | +| b_TimeBase = (BYTE) data[2]; (0: ns, 1:micros 2:ms)| +| dw_ReloadValue = (DWORD) data[3]; | +| ........ | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value :>0 : No error | +| -1 : Single/Diff selection error | +| -2 : Convert time base unity selection error | +| -3 : Convert time value selection error | +| -10: Any conversion started | +| .... | +| -100 : Config command error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_TimeBase = 0; + BYTE b_SingleDiff = 0; + DWORD dw_ReloadValue = 0; + DWORD dw_TestReloadValue = 0; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n == 4) { + /****************************/ + /* Get the Singel/Diff flag */ + /****************************/ + + b_SingleDiff = (BYTE) data[1]; + + /****************************/ + /* Get the time base unitiy */ + /****************************/ + + b_TimeBase = (BYTE) data[2]; + + /*************************************/ + /* Get the convert time reload value */ + /*************************************/ + + dw_ReloadValue = (DWORD) data[3]; + + /**********************/ + /* Test the time base */ + /**********************/ + + if ((devpriv->ps_BoardInfo-> + b_AvailableConvertUnit & (1 << b_TimeBase)) != + 0) { + /*******************************/ + /* Test the convert time value */ + /*******************************/ + + if ((dw_ReloadValue >= 0) && (dw_ReloadValue <= 65535)) { + dw_TestReloadValue = dw_ReloadValue; + + if (b_TimeBase == 1) { + dw_TestReloadValue = + dw_TestReloadValue * 1000UL; + } + if (b_TimeBase == 2) { + dw_TestReloadValue = + dw_TestReloadValue * 1000000UL; + } + + /*******************************/ + /* Test the convert time value */ + /*******************************/ + + if (dw_TestReloadValue >= + devpriv->ps_BoardInfo-> + ui_MinAcquisitiontimeNs) { + if ((b_SingleDiff == APCI3XXX_SINGLE) + || (b_SingleDiff == + APCI3XXX_DIFF)) { + if (((b_SingleDiff == APCI3XXX_SINGLE) && (devpriv->ps_BoardInfo->i_NbrAiChannel == 0)) || ((b_SingleDiff == APCI3XXX_DIFF) && (devpriv->ps_BoardInfo->i_NbrAiChannelDiff == 0))) { + /*******************************/ + /* Single/Diff selection error */ + /*******************************/ + + printk("Single/Diff selection error\n"); + i_ReturnValue = -1; + } else { + /**********************************/ + /* Test if conversion not started */ + /**********************************/ + + if (i_APCI3XXX_TestConversionStarted(dev) == 0) { + devpriv-> + ui_EocEosConversionTime + = + (UINT) + dw_ReloadValue; + devpriv-> + b_EocEosConversionTimeBase + = + b_TimeBase; + devpriv-> + b_SingelDiff + = + b_SingleDiff; + devpriv-> + b_AiInitialisation + = 1; + + /*******************************/ + /* Set the convert timing unit */ + /*******************************/ + + writel((DWORD) + b_TimeBase, + (void *) + (devpriv-> + dw_AiBase + + + 36)); + + /**************************/ + /* Set the convert timing */ + /*************************/ + + writel(dw_ReloadValue, (void *)(devpriv->dw_AiBase + 32)); + } else { + /**************************/ + /* Any conversion started */ + /**************************/ + + printk("Any conversion started\n"); + i_ReturnValue = + -10; + } + } + } else { + /*******************************/ + /* Single/Diff selection error */ + /*******************************/ + + printk("Single/Diff selection error\n"); + i_ReturnValue = -1; + } + } else { + /************************/ + /* Time selection error */ + /************************/ + + printk("Convert time value selection error\n"); + i_ReturnValue = -3; + } + } else { + /************************/ + /* Time selection error */ + /************************/ + + printk("Convert time value selection error\n"); + i_ReturnValue = -3; + } + } else { + /*****************************/ + /* Time base selection error */ + /*****************************/ + + printk("Convert time base unity selection error\n"); + i_ReturnValue = -2; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3XXX_InsnConfigAnalogInput | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task Converting mode and convert time selection | ++----------------------------------------------------------------------------+ +| Input Parameters : b_ConvertMode = (BYTE) data[0]; | +| b_TimeBase = (BYTE) data[1]; (0: ns, 1:micros 2:ms)| +| dw_ReloadValue = (DWORD) data[2]; | +| ........ | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value :>0: No error | +| .... | +| -100 : Config command error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + switch ((BYTE) data[0]) { + case APCI3XXX_CONFIGURATION: + i_ReturnValue = + i_APCI3XXX_AnalogInputConfigOperatingMode(dev, + s, insn, data); + break; + + default: + i_ReturnValue = -100; + printk("Config command error %d\n", data[0]); + break; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3XXX_InsnReadAnalogInput | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task Read 1 analog input | ++----------------------------------------------------------------------------+ +| Input Parameters : b_Range = CR_RANGE(insn->chanspec); | +| b_Channel = CR_CHAN(insn->chanspec); | +| dw_NbrOfAcquisition = insn->n; | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value :>0: No error | +| -3 : Channel selection error | +| -4 : Configuration selelection error | +| -10: Any conversion started | +| .... | +| -100 : Config command error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_Configuration = (BYTE) CR_RANGE(insn->chanspec); + BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); + DWORD dw_Temp = 0; + DWORD dw_Configuration = 0; + DWORD dw_AcquisitionCpt = 0; + BYTE b_Interrupt = 0; + + /*************************************/ + /* Test if operating mode configured */ + /*************************************/ + + if (devpriv->b_AiInitialisation) { + /***************************/ + /* Test the channel number */ + /***************************/ + + if (((b_Channel < devpriv->ps_BoardInfo->i_NbrAiChannel) + && (devpriv->b_SingelDiff == APCI3XXX_SINGLE)) + || ((b_Channel < devpriv->ps_BoardInfo-> + i_NbrAiChannelDiff) + && (devpriv->b_SingelDiff == APCI3XXX_DIFF))) { + /**********************************/ + /* Test the channel configuration */ + /**********************************/ + + if (b_Configuration > 7) { + /***************************/ + /* Channel not initialised */ + /***************************/ + + i_ReturnValue = -4; + printk("Channel %d range %d selection error\n", + b_Channel, b_Configuration); + } + } else { + /***************************/ + /* Channel selection error */ + /***************************/ + + i_ReturnValue = -3; + printk("Channel %d selection error\n", b_Channel); + } + + /**************************/ + /* Test if no error occur */ + /**************************/ + + if (i_ReturnValue >= 0) { + /************************/ + /* Test the buffer size */ + /************************/ + + if ((b_Interrupt != 0) || ((b_Interrupt == 0) + && (insn->n >= 1))) { + /**********************************/ + /* Test if conversion not started */ + /**********************************/ + + if (i_APCI3XXX_TestConversionStarted(dev) == 0) { + /******************/ + /* Clear the FIFO */ + /******************/ + + writel(0x10000UL, + (void *)(devpriv->dw_AiBase + + 12)); + + /*******************************/ + /* Get and save the delay mode */ + /*******************************/ + + dw_Temp = + readl((void *)(devpriv-> + dw_AiBase + 4)); + dw_Temp = dw_Temp & 0xFFFFFEF0UL; + + /***********************************/ + /* Channel configuration selection */ + /***********************************/ + + writel(dw_Temp, + (void *)(devpriv->dw_AiBase + + 4)); + + /**************************/ + /* Make the configuration */ + /**************************/ + + dw_Configuration = + (b_Configuration & 3) | + ((DWORD) (b_Configuration >> 2) + << 6) | ((DWORD) devpriv-> + b_SingelDiff << 7); + + /***************************/ + /* Write the configuration */ + /***************************/ + + writel(dw_Configuration, + (void *)(devpriv->dw_AiBase + + 0)); + + /*********************/ + /* Channel selection */ + /*********************/ + + writel(dw_Temp | 0x100UL, + (void *)(devpriv->dw_AiBase + + 4)); + writel((DWORD) b_Channel, + (void *)(devpriv->dw_AiBase + + 0)); + + /***********************/ + /* Restaure delay mode */ + /***********************/ + + writel(dw_Temp, + (void *)(devpriv->dw_AiBase + + 4)); + + /***********************************/ + /* Set the number of sequence to 1 */ + /***********************************/ + + writel(1, + (void *)(devpriv->dw_AiBase + + 48)); + + /***************************/ + /* Save the interrupt flag */ + /***************************/ + + devpriv->b_EocEosInterrupt = + b_Interrupt; + + /*******************************/ + /* Save the number of channels */ + /*******************************/ + + devpriv->ui_AiNbrofChannels = 1; + + /******************************/ + /* Test if interrupt not used */ + /******************************/ + + if (b_Interrupt == 0) { + for (dw_AcquisitionCpt = 0; + dw_AcquisitionCpt < + insn->n; + dw_AcquisitionCpt++) { + /************************/ + /* Start the conversion */ + /************************/ + + writel(0x80000UL, + (void *) + (devpriv-> + dw_AiBase + + 8)); + + /****************/ + /* Wait the EOS */ + /****************/ + + do { + dw_Temp = + readl( + (void *) + (devpriv-> + dw_AiBase + + + 20)); + dw_Temp = + dw_Temp + & 1; + } + while (dw_Temp != 1); + + /*************************/ + /* Read the analog value */ + /*************************/ + + data[dw_AcquisitionCpt] + = + (unsigned int) + readl((void + *) + (devpriv-> + dw_AiBase + + 28)); + } + } else { + /************************/ + /* Start the conversion */ + /************************/ + + writel(0x180000UL, + (void *)(devpriv-> + dw_AiBase + 8)); + } + } else { + /**************************/ + /* Any conversion started */ + /**************************/ + + printk("Any conversion started\n"); + i_ReturnValue = -10; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + } + } else { + /***************************/ + /* Channel selection error */ + /***************************/ + + printk("Operating mode not configured\n"); + i_ReturnValue = -1; + } + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function name : void v_APCI3XXX_Interrupt (int irq, | +| void *d) | ++----------------------------------------------------------------------------+ +| Task :Interrupt handler for APCI3XXX | +| When interrupt occurs this gets called. | +| First it finds which interrupt has been generated and | +| handles corresponding interrupt | ++----------------------------------------------------------------------------+ +| Input Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : - | ++----------------------------------------------------------------------------+ +*/ + +void v_APCI3XXX_Interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + BYTE b_CopyCpt = 0; + DWORD dw_Status = 0; + + /***************************/ + /* Test if interrupt occur */ + /***************************/ + + if (((dw_Status = readl((void *)(devpriv->dw_AiBase + 16))) & 0x2UL) == + 0x2UL) { + /***********************/ + /* Reset the interrupt */ + /***********************/ + + writel(dw_Status, (void *)(devpriv->dw_AiBase + 16)); + + /*****************************/ + /* Test if interrupt enabled */ + /*****************************/ + + if (devpriv->b_EocEosInterrupt == 1) { + /********************************/ + /* Read all analog inputs value */ + /********************************/ + + for (b_CopyCpt = 0; + b_CopyCpt < devpriv->ui_AiNbrofChannels; + b_CopyCpt++) { + devpriv->ui_AiReadData[b_CopyCpt] = + (UINT) readl((void *)(devpriv-> + dw_AiBase + 28)); + } + + /**************************/ + /* Set the interrupt flag */ + /**************************/ + + devpriv->b_EocEosInterrupt = 2; + + /**********************************************/ + /* Send a signal to from kernel to user space */ + /**********************************************/ + + send_sig(SIGIO, devpriv->tsk_Current, 0); + } + } +} + +/* ++----------------------------------------------------------------------------+ +| ANALOG OUTPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3XXX_InsnWriteAnalogOutput | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task Read 1 analog input | ++----------------------------------------------------------------------------+ +| Input Parameters : b_Range = CR_RANGE(insn->chanspec); | +| b_Channel = CR_CHAN(insn->chanspec); | +| data[0] = analog value; | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value :>0: No error | +| -3 : Channel selection error | +| -4 : Configuration selelection error | +| .... | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_Range = (BYTE) CR_RANGE(insn->chanspec); + BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); + DWORD dw_Status = 0; + INT i_ReturnValue = insn->n; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + /***************************/ + /* Test the channel number */ + /***************************/ + + if (b_Channel < devpriv->ps_BoardInfo->i_NbrAoChannel) { + /**********************************/ + /* Test the channel configuration */ + /**********************************/ + + if (b_Range < 2) { + /***************************/ + /* Set the range selection */ + /***************************/ + + writel(b_Range, + (void *)(devpriv->dw_AiBase + 96)); + + /**************************************************/ + /* Write the analog value to the selected channel */ + /**************************************************/ + + writel((data[0] << 8) | b_Channel, + (void *)(devpriv->dw_AiBase + 100)); + + /****************************/ + /* Wait the end of transfer */ + /****************************/ + + do { + dw_Status = + readl((void *)(devpriv-> + dw_AiBase + 96)); + } + while ((dw_Status & 0x100) != 0x100); + } else { + /***************************/ + /* Channel not initialised */ + /***************************/ + + i_ReturnValue = -4; + printk("Channel %d range %d selection error\n", + b_Channel, b_Range); + } + } else { + /***************************/ + /* Channel selection error */ + /***************************/ + + i_ReturnValue = -3; + printk("Channel %d selection error\n", b_Channel); + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| TTL FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3XXX_InsnConfigInitTTLIO | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task You must calling this function be | +| for you call any other function witch access of TTL. | +| APCI3XXX_TTL_INIT_DIRECTION_PORT2(user inputs for direction)| ++----------------------------------------------------------------------------+ +| Input Parameters : b_InitType = (BYTE) data[0]; | +| b_Port2Mode = (BYTE) data[1]; | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value :>0: No error | +| -1: Port 2 mode selection is wrong | +| .... | +| -100 : Config command error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_Command = 0; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + /*******************/ + /* Get the command */ + /* **************** */ + + b_Command = (BYTE) data[0]; + + /********************/ + /* Test the command */ + /********************/ + + if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) { + /***************************************/ + /* Test the initialisation buffer size */ + /***************************************/ + + if ((b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) + && (insn->n != 2)) { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + } else { + /************************/ + /* Config command error */ + /************************/ + + printk("Command selection error\n"); + i_ReturnValue = -100; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + /*********************************************************************************/ + /* Test if no error occur and APCI3XXX_TTL_INIT_DIRECTION_PORT2 command selected */ + /*********************************************************************************/ + + if ((i_ReturnValue >= 0) + && (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2)) { + /**********************/ + /* Test the direction */ + /**********************/ + + if ((data[1] == 0) || (data[1] == 0xFF)) { + /**************************/ + /* Save the configuration */ + /**************************/ + + devpriv->ul_TTLPortConfiguration[0] = + devpriv->ul_TTLPortConfiguration[0] | data[1]; + } else { + /************************/ + /* Port direction error */ + /************************/ + + printk("Port 2 direction selection error\n"); + i_ReturnValue = -1; + } + } + + /**************************/ + /* Test if no error occur */ + /**************************/ + + if (i_ReturnValue >= 0) { + /***********************************/ + /* Test if TTL port initilaisation */ + /***********************************/ + + if (b_Command == APCI3XXX_TTL_INIT_DIRECTION_PORT2) { + /*************************/ + /* Set the configuration */ + /*************************/ + + outl(data[1], devpriv->iobase + 224); + } + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| TTL INPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3XXX_InsnBitsTTLIO | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Write the selected output mask and read the status from| +| all TTL channles | ++----------------------------------------------------------------------------+ +| Input Parameters : dw_ChannelMask = data [0]; | +| dw_BitMask = data [1]; | ++----------------------------------------------------------------------------+ +| Output Parameters : data[1] : All TTL channles states | ++----------------------------------------------------------------------------+ +| Return Value : >0 : No error | +| -4 : Channel mask error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_ChannelCpt = 0; + DWORD dw_ChannelMask = 0; + DWORD dw_BitMask = 0; + DWORD dw_Status = 0; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 2) { + /*******************************/ + /* Get the channe and bit mask */ + /*******************************/ + + dw_ChannelMask = data[0]; + dw_BitMask = data[1]; + + /*************************/ + /* Test the channel mask */ + /*************************/ + + if (((dw_ChannelMask & 0XFF00FF00) == 0) && + (((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0xFF) + || (((devpriv->ul_TTLPortConfiguration[0] & + 0xFF) == 0) + && ((dw_ChannelMask & 0XFF0000) == + 0)))) { + /*********************************/ + /* Test if set/reset any channel */ + /*********************************/ + + if (dw_ChannelMask) { + /****************************************/ + /* Test if set/rest any port 0 channels */ + /****************************************/ + + if (dw_ChannelMask & 0xFF) { + /*******************************************/ + /* Read port 0 (first digital output port) */ + /*******************************************/ + + dw_Status = inl(devpriv->iobase + 80); + + for (b_ChannelCpt = 0; b_ChannelCpt < 8; + b_ChannelCpt++) { + if ((dw_ChannelMask >> + b_ChannelCpt) & + 1) { + dw_Status = + (dw_Status & + (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt)); + } + } + + outl(dw_Status, devpriv->iobase + 80); + } + + /****************************************/ + /* Test if set/rest any port 2 channels */ + /****************************************/ + + if (dw_ChannelMask & 0xFF0000) { + dw_BitMask = dw_BitMask >> 16; + dw_ChannelMask = dw_ChannelMask >> 16; + + /********************************************/ + /* Read port 2 (second digital output port) */ + /********************************************/ + + dw_Status = inl(devpriv->iobase + 112); + + for (b_ChannelCpt = 0; b_ChannelCpt < 8; + b_ChannelCpt++) { + if ((dw_ChannelMask >> + b_ChannelCpt) & + 1) { + dw_Status = + (dw_Status & + (0xFF - (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt)); + } + } + + outl(dw_Status, devpriv->iobase + 112); + } + } + + /*******************************************/ + /* Read port 0 (first digital output port) */ + /*******************************************/ + + data[1] = inl(devpriv->iobase + 80); + + /******************************************/ + /* Read port 1 (first digital input port) */ + /******************************************/ + + data[1] = data[1] | (inl(devpriv->iobase + 64) << 8); + + /************************/ + /* Test if port 2 input */ + /************************/ + + if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) == 0) { + data[1] = + data[1] | (inl(devpriv->iobase + + 96) << 16); + } else { + data[1] = + data[1] | (inl(devpriv->iobase + + 112) << 16); + } + } else { + /************************/ + /* Config command error */ + /************************/ + + printk("Channel mask error\n"); + i_ReturnValue = -4; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3XXX_InsnReadTTLIO | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read the status from selected channel | ++----------------------------------------------------------------------------+ +| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] : Selected TTL channel state | ++----------------------------------------------------------------------------+ +| Return Value : 0 : No error | +| -3 : Channel selection error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnReadTTLIO(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); + INT i_ReturnValue = insn->n; + unsigned int *pls_ReadData = data; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + /***********************/ + /* Test if read port 0 */ + /***********************/ + + if (b_Channel < 8) { + /*******************************************/ + /* Read port 0 (first digital output port) */ + /*******************************************/ + + pls_ReadData[0] = inl(devpriv->iobase + 80); + pls_ReadData[0] = (pls_ReadData[0] >> b_Channel) & 1; + } else { + /***********************/ + /* Test if read port 1 */ + /***********************/ + + if ((b_Channel > 7) && (b_Channel < 16)) { + /******************************************/ + /* Read port 1 (first digital input port) */ + /******************************************/ + + pls_ReadData[0] = inl(devpriv->iobase + 64); + pls_ReadData[0] = + (pls_ReadData[0] >> (b_Channel - + 8)) & 1; + } else { + /***********************/ + /* Test if read port 2 */ + /***********************/ + + if ((b_Channel > 15) && (b_Channel < 24)) { + /************************/ + /* Test if port 2 input */ + /************************/ + + if ((devpriv->ul_TTLPortConfiguration[0] + & 0xFF) == 0) { + pls_ReadData[0] = + inl(devpriv->iobase + + 96); + pls_ReadData[0] = + (pls_ReadData[0] >> + (b_Channel - 16)) & 1; + } else { + pls_ReadData[0] = + inl(devpriv->iobase + + 112); + pls_ReadData[0] = + (pls_ReadData[0] >> + (b_Channel - 16)) & 1; + } + } else { + /***************************/ + /* Channel selection error */ + /***************************/ + + i_ReturnValue = -3; + printk("Channel %d selection error\n", + b_Channel); + } + } + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| TTL OUTPUT FUNCTIONS | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function Name : INT i_APCI3XXX_InsnWriteTTLIO | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Set the state from TTL output channel | ++----------------------------------------------------------------------------+ +| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) | +| b_State = data [0] | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : 0 : No error | +| -3 : Channel selection error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); + BYTE b_State = 0; + DWORD dw_Status = 0; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + b_State = (BYTE) data[0]; + + /***********************/ + /* Test if read port 0 */ + /***********************/ + + if (b_Channel < 8) { + /*****************************************************************************/ + /* Read port 0 (first digital output port) and set/reset the selcted channel */ + /*****************************************************************************/ + + dw_Status = inl(devpriv->iobase + 80); + dw_Status = + (dw_Status & (0xFF - + (1 << b_Channel))) | ((b_State & 1) << + b_Channel); + outl(dw_Status, devpriv->iobase + 80); + } else { + /***********************/ + /* Test if read port 2 */ + /***********************/ + + if ((b_Channel > 15) && (b_Channel < 24)) { + /*************************/ + /* Test if port 2 output */ + /*************************/ + + if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF) + == 0xFF) { + /*****************************************************************************/ + /* Read port 2 (first digital output port) and set/reset the selcted channel */ + /*****************************************************************************/ + + dw_Status = inl(devpriv->iobase + 112); + dw_Status = + (dw_Status & (0xFF - + (1 << (b_Channel - + 16)))) | + ((b_State & 1) << (b_Channel - + 16)); + outl(dw_Status, devpriv->iobase + 112); + } else { + /***************************/ + /* Channel selection error */ + /***************************/ + + i_ReturnValue = -3; + printk("Channel %d selection error\n", + b_Channel); + } + } else { + /***************************/ + /* Channel selection error */ + /***************************/ + + i_ReturnValue = -3; + printk("Channel %d selection error\n", + b_Channel); + } + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| DIGITAL INPUT SUBDEVICE | ++----------------------------------------------------------------------------+ +*/ + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3XXX_InsnReadDigitalInput | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Reads the value of the specified Digital input channel | ++----------------------------------------------------------------------------+ +| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) (0 to 3) | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] : Channel value | ++----------------------------------------------------------------------------+ +| Return Value : 0 : No error | +| -3 : Channel selection error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_Channel = (BYTE) CR_CHAN(insn->chanspec); + DWORD dw_Temp = 0; + + /***************************/ + /* Test the channel number */ + /***************************/ + + if (b_Channel <= devpriv->ps_BoardInfo->i_NbrDiChannel) { + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + dw_Temp = inl(devpriv->iobase + 32); + *data = (dw_Temp >> b_Channel) & 1; + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + } else { + /***************************/ + /* Channel selection error */ + /***************************/ + + printk("Channel selection error\n"); + i_ReturnValue = -3; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3XXX_InsnBitsDigitalInput | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Reads the value of the Digital input Port i.e.4channels| ++----------------------------------------------------------------------------+ +| Input Parameters : - | ++----------------------------------------------------------------------------+ +| Output Parameters : data[0] : Port value | ++----------------------------------------------------------------------------+ +| Return Value :>0: No error | +| .... | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + DWORD dw_Temp = 0; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + dw_Temp = inl(devpriv->iobase + 32); + *data = dw_Temp & 0xf; + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| DIGITAL OUTPUT SUBDEVICE | ++----------------------------------------------------------------------------+ + +*/ + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3XXX_InsnBitsDigitalOutput | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Write the selected output mask and read the status from| +| all digital output channles | ++----------------------------------------------------------------------------+ +| Input Parameters : dw_ChannelMask = data [0]; | +| dw_BitMask = data [1]; | ++----------------------------------------------------------------------------+ +| Output Parameters : data[1] : All digital output channles states | ++----------------------------------------------------------------------------+ +| Return Value : >0 : No error | +| -4 : Channel mask error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ +int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_ChannelCpt = 0; + DWORD dw_ChannelMask = 0; + DWORD dw_BitMask = 0; + DWORD dw_Status = 0; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 2) { + /*******************************/ + /* Get the channe and bit mask */ + /*******************************/ + + dw_ChannelMask = data[0]; + dw_BitMask = data[1]; + + /*************************/ + /* Test the channel mask */ + /*************************/ + + if ((dw_ChannelMask & 0XFFFFFFF0) == 0) { + /*********************************/ + /* Test if set/reset any channel */ + /*********************************/ + + if (dw_ChannelMask & 0xF) { + /********************************/ + /* Read the digital output port */ + /********************************/ + + dw_Status = inl(devpriv->iobase + 48); + + for (b_ChannelCpt = 0; b_ChannelCpt < 4; + b_ChannelCpt++) { + if ((dw_ChannelMask >> b_ChannelCpt) & + 1) { + dw_Status = + (dw_Status & (0xF - + (1 << b_ChannelCpt))) | (dw_BitMask & (1 << b_ChannelCpt)); + } + } + + outl(dw_Status, devpriv->iobase + 48); + } + + /********************************/ + /* Read the digital output port */ + /********************************/ + + data[1] = inl(devpriv->iobase + 48); + } else { + /************************/ + /* Config command error */ + /************************/ + + printk("Channel mask error\n"); + i_ReturnValue = -4; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3XXX_InsnWriteDigitalOutput | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Set the state from digital output channel | ++----------------------------------------------------------------------------+ +| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) | +| b_State = data [0] | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : >0 : No error | +| -3 : Channel selection error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_Channel = CR_CHAN(insn->chanspec); + BYTE b_State = 0; + DWORD dw_Status = 0; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + /***************************/ + /* Test the channel number */ + /***************************/ + + if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) { + /*******************/ + /* Get the command */ + /*******************/ + + b_State = (BYTE) data[0]; + + /********************************/ + /* Read the digital output port */ + /********************************/ + + dw_Status = inl(devpriv->iobase + 48); + + dw_Status = + (dw_Status & (0xF - + (1 << b_Channel))) | ((b_State & 1) << + b_Channel); + outl(dw_Status, devpriv->iobase + 48); + } else { + /***************************/ + /* Channel selection error */ + /***************************/ + + printk("Channel selection error\n"); + i_ReturnValue = -3; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function name :int i_APCI3XXX_InsnReadDigitalOutput | +| (struct comedi_device *dev, | +| struct comedi_subdevice *s, | +| struct comedi_insn *insn, | +| unsigned int *data) | ++----------------------------------------------------------------------------+ +| Task : Read the state from digital output channel | ++----------------------------------------------------------------------------+ +| Input Parameters : b_Channel = CR_CHAN(insn->chanspec) | ++----------------------------------------------------------------------------+ +| Output Parameters : b_State = data [0] | ++----------------------------------------------------------------------------+ +| Return Value : >0 : No error | +| -3 : Channel selection error | +| -101 : Data size error | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + INT i_ReturnValue = insn->n; + BYTE b_Channel = CR_CHAN(insn->chanspec); + DWORD dw_Status = 0; + + /************************/ + /* Test the buffer size */ + /************************/ + + if (insn->n >= 1) { + /***************************/ + /* Test the channel number */ + /***************************/ + + if (b_Channel < devpriv->ps_BoardInfo->i_NbrDoChannel) { + /********************************/ + /* Read the digital output port */ + /********************************/ + + dw_Status = inl(devpriv->iobase + 48); + + dw_Status = (dw_Status >> b_Channel) & 1; + *data = dw_Status; + } else { + /***************************/ + /* Channel selection error */ + /***************************/ + + printk("Channel selection error\n"); + i_ReturnValue = -3; + } + } else { + /*******************/ + /* Data size error */ + /*******************/ + + printk("Buffer size error\n"); + i_ReturnValue = -101; + } + + return (i_ReturnValue); +} + +/* ++----------------------------------------------------------------------------+ +| Function Name : int i_APCI3XXX_Reset(struct comedi_device *dev) | +----------------------------------------------------------------------------+ +| Task :resets all the registers | ++----------------------------------------------------------------------------+ +| Input Parameters : struct comedi_device *dev | ++----------------------------------------------------------------------------+ +| Output Parameters : - | ++----------------------------------------------------------------------------+ +| Return Value : - | ++----------------------------------------------------------------------------+ +*/ + +int i_APCI3XXX_Reset(struct comedi_device * dev) +{ + unsigned char b_Cpt = 0; + + /*************************/ + /* Disable the interrupt */ + /*************************/ + + disable_irq(dev->irq); + + /****************************/ + /* Reset the interrupt flag */ + /****************************/ + + devpriv->b_EocEosInterrupt = 0; + + /***************************/ + /* Clear the start command */ + /***************************/ + + writel(0, (void *)(devpriv->dw_AiBase + 8)); + + /*****************************/ + /* Reset the interrupt flags */ + /*****************************/ + + writel(readl((void *)(devpriv->dw_AiBase + 16)), + (void *)(devpriv->dw_AiBase + 16)); + + /*****************/ + /* clear the EOS */ + /*****************/ + + readl((void *)(devpriv->dw_AiBase + 20)); + + /******************/ + /* Clear the FIFO */ + /******************/ + + for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) { + readl((void *)(devpriv->dw_AiBase + 28)); + } + + /************************/ + /* Enable the interrupt */ + /************************/ + + enable_irq(dev->irq); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h new file mode 100644 index 000000000000..788d7c1cf5c1 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data-com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#ifndef COMEDI_SUBD_TTLIO +#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */ +#endif + +#ifndef ADDIDATA_ENABLE +#define ADDIDATA_ENABLE 1 +#define ADDIDATA_DISABLE 0 +#endif + +#define APCI3XXX_SINGLE 0 +#define APCI3XXX_DIFF 1 +#define APCI3XXX_CONFIGURATION 0 + +#define APCI3XXX_TTL_INIT_DIRECTION_PORT2 0 + +#ifdef __KERNEL__ + +static const struct comedi_lrange range_apci3XXX_ai = { 8, {BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1)} +}; + +static const struct comedi_lrange range_apci3XXX_ttl = { 12, {BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1), + BIP_RANGE(1)} +}; + +static const struct comedi_lrange range_apci3XXX_ao = { 2, {BIP_RANGE(10), + UNI_RANGE(10)} +}; +#endif diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c new file mode 100644 index 000000000000..bac018202fe8 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_035.c @@ -0,0 +1,5 @@ +#define CONFIG_APCI_035 1 + +#define ADDIDATA_WATCHDOG 2 // Or shold it be something else + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c new file mode 100644 index 000000000000..fa2056e8aa0e --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_1032 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c new file mode 100644 index 000000000000..7a5cae599ef8 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_1500 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c new file mode 100644 index 000000000000..8d414844009f --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_1516 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c new file mode 100644 index 000000000000..0351cdde1026 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_1564 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c new file mode 100644 index 000000000000..506799041294 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_16XX 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c new file mode 100644 index 000000000000..c433445913dd --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_1710.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_1710 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_2016.c b/drivers/staging/comedi/drivers/addi_apci_2016.c new file mode 100644 index 000000000000..271c47c8cad3 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_2016.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_2016 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c new file mode 100644 index 000000000000..5108ea2a3924 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_2032 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c new file mode 100644 index 000000000000..e439f835cf4f --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_2200 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3001.c b/drivers/staging/comedi/drivers/addi_apci_3001.c new file mode 100644 index 000000000000..df97c305828b --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_3001.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_3001 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c new file mode 100644 index 000000000000..9183125ddde4 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_3120 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c new file mode 100644 index 000000000000..f25a70b3290b --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_3200.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_3200 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3300.c b/drivers/staging/comedi/drivers/addi_apci_3300.c new file mode 100644 index 000000000000..1ee4778ad45b --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_3300.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_3300 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c new file mode 100644 index 000000000000..1049e20237e8 --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_3501 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c new file mode 100644 index 000000000000..fb9deb7083bd --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -0,0 +1,3 @@ +#define CONFIG_APCI_3XXX 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_all.c b/drivers/staging/comedi/drivers/addi_apci_all.c new file mode 100644 index 000000000000..aeb1b2688f3d --- /dev/null +++ b/drivers/staging/comedi/drivers/addi_apci_all.c @@ -0,0 +1,18 @@ +#define CONFIG_APCI_035 1 +#define CONFIG_APCI_1032 1 +#define CONFIG_APCI_1500 1 +#define CONFIG_APCI_1516 1 +#define CONFIG_APCI_1564 1 +#define CONFIG_APCI_16XX 1 +#define CONFIG_APCI_1710 1 +#define CONFIG_APCI_2016 1 +#define CONFIG_APCI_2032 1 +#define CONFIG_APCI_2200 1 +#define CONFIG_APCI_3001 1 +#define CONFIG_APCI_3120 1 +#define CONFIG_APCI_3200 1 +#define CONFIG_APCI_3300 1 +#define CONFIG_APCI_3501 1 +#define CONFIG_APCI_3XXX 1 + +#include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c new file mode 100644 index 000000000000..f710f551820d --- /dev/null +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -0,0 +1,391 @@ +/* + comedi/drivers/adl_pci6208.c + + Hardware driver for ADLink 6208 series cards: + card | voltage output | current output + -------------+-------------------+--------------- + PCI-6208V | 8 channels | - + PCI-6216V | 16 channels | - + PCI-6208A | 8 channels | 8 channels + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: adl_pci6208 +Description: ADLink PCI-6208A +Devices: [ADLink] PCI-6208A (adl_pci6208) +Author: nsyeow +Updated: Fri, 30 Jan 2004 14:44:27 +0800 +Status: untested + +Configuration Options: + none + +References: + - ni_660x.c + - adl_pci9111.c copied the entire pci setup section + - adl_pci9118.c +*/ +/* + * These headers should be followed by a blank line, and any comments + * you wish to say about the driver. The comment area is the place + * to put any known bugs, limitations, unsupported features, supported + * command triggers, whether or not commands are supported on particular + * subdevices, etc. + * + * Somewhere in the comment should be information about configuration + * options that are used with comedi_config. + */ +#include "../comedidev.h" +#include "comedi_pci.h" + +#define PCI6208_DRIVER_NAME "adl_pci6208" + +/* Board descriptions */ +struct pci6208_board { + const char *name; + unsigned short dev_id; /* `lspci` will show you this */ + int ao_chans; + //int ao_bits; +}; + +static const struct pci6208_board pci6208_boards[] = { + /*{ + name : "pci6208v", + dev_id : 0x6208, //not sure + ao_chans: 8 + //, ao_bits : 16 + }, + { + name : "pci6216v", + dev_id : 0x6208, //not sure + ao_chans: 16 + //, ao_bits : 16 + }, */ + { + name: "pci6208a", + dev_id: 0x6208, + ao_chans:8 + //, ao_bits : 16 + } +}; + +/* This is used by modprobe to translate PCI IDs to drivers. Should + * only be used for PCI and ISA-PnP devices */ +static DEFINE_PCI_DEVICE_TABLE(pci6208_pci_table) = { + //{ PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + //{ PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + {PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pci6208_pci_table); + +/* Will be initialized in pci6208_find device(). */ +#define thisboard ((const struct pci6208_board *)dev->board_ptr) + +struct pci6208_private { + int data; + struct pci_dev *pci_dev; /* for a PCI device */ + unsigned int ao_readback[2]; /* Used for AO readback */ +}; + +#define devpriv ((struct pci6208_private *)dev->private) + +static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pci6208_detach(struct comedi_device * dev); + +#define pci6208_board_nbr \ + (sizeof(pci6208_boards) / sizeof(struct pci6208_board)) + +static struct comedi_driver driver_pci6208 = { + driver_name:PCI6208_DRIVER_NAME, + module:THIS_MODULE, + attach:pci6208_attach, + detach:pci6208_detach, +}; + +COMEDI_PCI_INITCLEANUP(driver_pci6208, pci6208_pci_table); + +static int pci6208_find_device(struct comedi_device * dev, int bus, int slot); +static int +pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr, + int dev_minor); + +/*read/write functions*/ +static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +//static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, +// struct comedi_insn *insn,unsigned int *data); +//static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s, +// struct comedi_insn *insn,unsigned int *data); + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int retval; + unsigned long io_base; + + printk("comedi%d: pci6208: ", dev->minor); + + retval = alloc_private(dev, sizeof(struct pci6208_private)); + if (retval < 0) + return retval; + + retval = pci6208_find_device(dev, it->options[0], it->options[1]); + if (retval < 0) + return retval; + + retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor); + if (retval < 0) + return retval; + + dev->iobase = io_base; + dev->board_name = thisboard->name; + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_subdevices(dev, 2) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; //anything else to add here?? + s->n_chan = thisboard->ao_chans; + s->maxdata = 0xffff; //16-bit DAC + s->range_table = &range_bipolar10; //this needs to be checked. + s->insn_write = pci6208_ao_winsn; + s->insn_read = pci6208_ao_rinsn; + + //s=dev->subdevices+1; + /* digital i/o subdevice */ + //s->type=COMEDI_SUBD_DIO; + //s->subdev_flags=SDF_READABLE|SDF_WRITABLE; + //s->n_chan=16; + //s->maxdata=1; + //s->range_table=&range_digital; + //s->insn_bits = pci6208_dio_insn_bits; + //s->insn_config = pci6208_dio_insn_config; + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pci6208_detach(struct comedi_device * dev) +{ + printk("comedi%d: pci6208: remove\n", dev->minor); + + if (devpriv && devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + + return 0; +} + +static int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i = 0, Data_Read; + unsigned short chan = CR_CHAN(insn->chanspec); + unsigned long invert = 1 << (16 - 1); + unsigned long out_value; + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { + out_value = data[i] ^ invert; + /* a typical programming sequence */ + do { + Data_Read = (inw(dev->iobase) & 1); + } while (Data_Read); + outw(out_value, dev->iobase + (0x02 * chan)); + devpriv->ao_readback[chan] = out_value; + } + + /* return the number of samples read/written */ + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. */ +static int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +/* DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write */ +//static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, +// struct comedi_insn *insn,unsigned int *data) +//{ +// if(insn->n!=2)return -EINVAL; + + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ +// if(data[0]){ +// s->state &= ~data[0]; +// s->state |= data[0]&data[1]; + /* Write out the new digital output lines */ + //outw(s->state,dev->iobase + SKEL_DIO); +// } + + /* on return, data[1] contains the value of the digital + * input and output lines. */ + //data[1]=inw(dev->iobase + SKEL_DIO); + /* or we could just return the software copy of the output values if + * it was a purely digital output subdevice */ + //data[1]=s->state; + +// return 2; +//} + +//static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s, +// struct comedi_insn *insn,unsigned int *data) +//{ +// int chan=CR_CHAN(insn->chanspec); + + /* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ + +// if(data[0]==COMEDI_OUTPUT){ +// s->io_bits |= 1<io_bits &= ~(1<io_bits,dev->iobase + SKEL_DIO_CONFIG); + +// return 1; +//} + +static int pci6208_find_device(struct comedi_device * dev, int bus, int slot) +{ + struct pci_dev *pci_dev; + int i; + + for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pci_dev != NULL; + pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) { + if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) { + for (i = 0; i < pci6208_board_nbr; i++) { + if (pci6208_boards[i].dev_id == pci_dev->device) { + // was a particular bus/slot requested? + if ((bus != 0) || (slot != 0)) { + // are we on the wrong bus/slot? + if (pci_dev->bus->number + != bus || + PCI_SLOT(pci_dev->devfn) + != slot) { + continue; + } + } + dev->board_ptr = pci6208_boards + i; + goto found; + } + } + } + } + + printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return -EIO; + + found: + printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n", + dev->minor, + pci6208_boards[i].name, + pci_dev->bus->number, + PCI_SLOT(pci_dev->devfn), + PCI_FUNC(pci_dev->devfn), pci_dev->irq); + + // TODO: Warn about non-tested boards. + //switch(board->device_id) + //{ + //}; + + devpriv->pci_dev = pci_dev; + + return 0; +} + +static int +pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr, + int dev_minor) +{ + unsigned long io_base, io_range, lcr_io_base, lcr_io_range; + + // Enable PCI device and request regions + if (comedi_pci_enable(pci_dev, PCI6208_DRIVER_NAME) < 0) { + printk("comedi%d: Failed to enable PCI device and request regions\n", dev_minor); + return -EIO; + } + // Read local configuration register base address [PCI_BASE_ADDRESS #1]. + lcr_io_base = pci_resource_start(pci_dev, 1); + lcr_io_range = pci_resource_len(pci_dev, 1); + + printk("comedi%d: local config registers at address 0x%4lx [0x%4lx]\n", + dev_minor, lcr_io_base, lcr_io_range); + + // Read PCI6208 register base address [PCI_BASE_ADDRESS #2]. + io_base = pci_resource_start(pci_dev, 2); + io_range = pci_resource_end(pci_dev, 2) - io_base + 1; + + printk("comedi%d: 6208 registers at address 0x%4lx [0x%4lx]\n", + dev_minor, io_base, io_range); + + *io_base_ptr = io_base; + //devpriv->io_range = io_range; + //devpriv->is_valid=0; + //devpriv->lcr_io_base=lcr_io_base; + //devpriv->lcr_io_range=lcr_io_range; + + return 0; +} diff --git a/drivers/staging/comedi/drivers/adl_pci7296.c b/drivers/staging/comedi/drivers/adl_pci7296.c new file mode 100644 index 000000000000..bd0f9ab226ef --- /dev/null +++ b/drivers/staging/comedi/drivers/adl_pci7296.c @@ -0,0 +1,174 @@ +/* + comedi/drivers/adl_pci7296.c + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: adl_pci7296 +Description: Driver for the Adlink PCI-7296 96 ch. digital io board +Devices: [ADLink] PCI-7296 (adl_pci7296) +Author: Jon Grierson +Updated: Mon, 14 Apr 2008 15:05:56 +0100 +Status: testing + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. +*/ + +#include "../comedidev.h" +#include + +#include "comedi_pci.h" +#include "8255.h" +// #include "8253.h" + +#define PORT1A 0 +#define PORT2A 4 +#define PORT3A 8 +#define PORT4A 12 + +#define PCI_DEVICE_ID_PCI7296 0x7296 + +static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = { + {PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296, PCI_ANY_ID, PCI_ANY_ID, 0, + 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table); + +struct adl_pci7296_private { + int data; + struct pci_dev *pci_dev; +}; + + +#define devpriv ((struct adl_pci7296_private *)dev->private) + +static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int adl_pci7296_detach(struct comedi_device * dev); +static struct comedi_driver driver_adl_pci7296 = { + driver_name:"adl_pci7296", + module:THIS_MODULE, + attach:adl_pci7296_attach, + detach:adl_pci7296_detach, +}; + +static int adl_pci7296_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct pci_dev *pcidev; + struct comedi_subdevice *s; + int bus, slot; + int ret; + + printk("comedi: attempt to attach...\n"); + printk("comedi%d: adl_pci7432\n", dev->minor); + + dev->board_name = "pci7432"; + bus = it->options[0]; + slot = it->options[1]; + + if (alloc_private(dev, sizeof(struct adl_pci7296_private)) < 0) + return -ENOMEM; + + if (alloc_subdevices(dev, 4) < 0) + return -ENOMEM; + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + + if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && + pcidev->device == PCI_DEVICE_ID_PCI7296) { + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus + || PCI_SLOT(pcidev->devfn) != slot) { + continue; + } + } + devpriv->pci_dev = pcidev; + if (comedi_pci_enable(pcidev, "adl_pci7296") < 0) { + printk("comedi%d: Failed to enable PCI device and request regions\n", dev->minor); + return -EIO; + } + + dev->iobase = pci_resource_start(pcidev, 2); + printk("comedi: base addr %4lx\n", dev->iobase); + + // four 8255 digital io subdevices + s = dev->subdevices + 0; + subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase)); + + s = dev->subdevices + 1; + ret = subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase + PORT2A)); + if (ret < 0) + return ret; + + s = dev->subdevices + 2; + ret = subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase + PORT3A)); + if (ret < 0) + return ret; + + s = dev->subdevices + 3; + ret = subdev_8255_init(dev, s, NULL, + (unsigned long)(dev->iobase + PORT4A)); + if (ret < 0) + return ret; + + printk("attached\n"); + + return 1; + } + } + + printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return -EIO; +} + +static int adl_pci7296_detach(struct comedi_device * dev) +{ + printk("comedi%d: pci7432: remove\n", dev->minor); + + if (devpriv && devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + // detach four 8255 digital io subdevices + if (dev->subdevices) { + subdev_8255_cleanup(dev, dev->subdevices + 0); + subdev_8255_cleanup(dev, dev->subdevices + 1); + subdev_8255_cleanup(dev, dev->subdevices + 2); + subdev_8255_cleanup(dev, dev->subdevices + 3); + + } + + return 0; +} + +COMEDI_PCI_INITCLEANUP(driver_adl_pci7296, adl_pci7296_pci_table); diff --git a/drivers/staging/comedi/drivers/adl_pci7432.c b/drivers/staging/comedi/drivers/adl_pci7432.c new file mode 100644 index 000000000000..a8f1715608d1 --- /dev/null +++ b/drivers/staging/comedi/drivers/adl_pci7432.c @@ -0,0 +1,202 @@ +/* + comedi/drivers/adl_pci7432.c + + Hardware comedi driver fot PCI7432 Adlink card + Copyright (C) 2004 Michel Lachine + + 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: adl_pci7432 +Description: Driver for the Adlink PCI-7432 64 ch. isolated digital io board +Devices: [ADLink] PCI-7432 (adl_pci7432) +Author: Michel Lachaine +Status: experimental +Updated: Mon, 14 Apr 2008 15:08:14 +0100 + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. +*/ + +#include "../comedidev.h" +#include +#include "comedi_pci.h" + +#define PCI7432_DI 0x00 +#define PCI7432_DO 0x00 + +#define PCI_DEVICE_ID_PCI7432 0x7432 + +static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = { + {PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432, PCI_ANY_ID, PCI_ANY_ID, 0, + 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table); + +struct adl_pci7432_private { + int data; + struct pci_dev *pci_dev; +}; + +#define devpriv ((struct adl_pci7432_private *)dev->private) + +static int adl_pci7432_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int adl_pci7432_detach(struct comedi_device * dev); +static struct comedi_driver driver_adl_pci7432 = { + driver_name:"adl_pci7432", + module:THIS_MODULE, + attach:adl_pci7432_attach, + detach:adl_pci7432_detach, +}; + +/* Digital IO */ + +static int adl_pci7432_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +/* */ + +static int adl_pci7432_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct pci_dev *pcidev; + struct comedi_subdevice *s; + int bus, slot; + + printk("comedi: attempt to attach...\n"); + printk("comedi%d: adl_pci7432\n", dev->minor); + + dev->board_name = "pci7432"; + bus = it->options[0]; + slot = it->options[1]; + + if (alloc_private(dev, sizeof(struct adl_pci7432_private)) < 0) + return -ENOMEM; + + if (alloc_subdevices(dev, 2) < 0) + return -ENOMEM; + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + + if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && + pcidev->device == PCI_DEVICE_ID_PCI7432) { + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus + || PCI_SLOT(pcidev->devfn) != slot) { + continue; + } + } + devpriv->pci_dev = pcidev; + if (comedi_pci_enable(pcidev, "adl_pci7432") < 0) { + printk("comedi%d: Failed to enable PCI device and request regions\n", dev->minor); + return -EIO; + } + dev->iobase = pci_resource_start(pcidev, 2); + printk("comedi: base addr %4lx\n", dev->iobase); + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = + SDF_READABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 32; + s->maxdata = 1; + s->len_chanlist = 32; + s->io_bits = 0x00000000; + s->range_table = &range_digital; + s->insn_bits = adl_pci7432_di_insn_bits; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = + SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 32; + s->maxdata = 1; + s->len_chanlist = 32; + s->io_bits = 0xffffffff; + s->range_table = &range_digital; + s->insn_bits = adl_pci7432_do_insn_bits; + + printk("comedi: attached\n"); + + return 1; + } + } + + printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return -EIO; +} + +static int adl_pci7432_detach(struct comedi_device * dev) +{ + printk("comedi%d: pci7432: remove\n", dev->minor); + + if (devpriv && devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + + return 0; +} + +static int adl_pci7432_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + printk("comedi: pci7432_do_insn_bits called\n"); + printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]); + + if (insn->n != 2) + return -EINVAL; + + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + + printk("comedi: out: %8x on iobase %4lx\n", s->state, + dev->iobase + PCI7432_DO); + outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO); + } + return 2; +} + +static int adl_pci7432_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + printk("comedi: pci7432_di_insn_bits called\n"); + printk("comedi: data0: %8x data1: %8x\n", data[0], data[1]); + + if (insn->n != 2) + return -EINVAL; + + data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff; + printk("comedi: data1 %8x\n", data[1]); + + return 2; +} + +COMEDI_PCI_INITCLEANUP(driver_adl_pci7432, adl_pci7432_pci_table); diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c new file mode 100644 index 000000000000..adf90be79983 --- /dev/null +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -0,0 +1,512 @@ +/* + comedi/drivers/adl_pci8164.c + + Hardware comedi driver fot PCI-8164 Adlink card + Copyright (C) 2004 Michel Lachine + + 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: adl_pci8164 +Description: Driver for the Adlink PCI-8164 4 Axes Motion Control board +Devices: [ADLink] PCI-8164 (adl_pci8164) +Author: Michel Lachaine +Status: experimental +Updated: Mon, 14 Apr 2008 15:10:32 +0100 + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. +*/ + +#include "../comedidev.h" +#include +#include "comedi_fc.h" +#include "comedi_pci.h" +#include "8253.h" + +#define PCI8164_AXIS_X 0x00 +#define PCI8164_AXIS_Y 0x08 +#define PCI8164_AXIS_Z 0x10 +#define PCI8164_AXIS_U 0x18 + +#define PCI8164_MSTS 0x00 +#define PCI8164_SSTS 0x02 +#define PCI8164_BUF0 0x04 +#define PCI8164_BUF1 0x06 + +#define PCI8164_CMD 0x00 +#define PCI8164_OTP 0x02 + +#define PCI_DEVICE_ID_PCI8164 0x8164 + +static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = { + {PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164, PCI_ANY_ID, PCI_ANY_ID, 0, + 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table); + +struct adl_pci8164_private { + int data; + struct pci_dev *pci_dev; +}; + +#define devpriv ((struct adl_pci8164_private *)dev->private) + +static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int adl_pci8164_detach(struct comedi_device * dev); +static struct comedi_driver driver_adl_pci8164 = { + driver_name:"adl_pci8164", + module:THIS_MODULE, + attach:adl_pci8164_attach, + detach:adl_pci8164_detach, +}; + +static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int adl_pci8164_insn_write_buf0(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +static int adl_pci8164_insn_write_buf1(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +static int adl_pci8164_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct pci_dev *pcidev; + struct comedi_subdevice *s; + int bus, slot; + + printk("comedi: attempt to attach...\n"); + printk("comedi%d: adl_pci8164\n", dev->minor); + + dev->board_name = "pci8164"; + bus = it->options[0]; + slot = it->options[1]; + + if (alloc_private(dev, sizeof(struct adl_pci8164_private)) < 0) + return -ENOMEM; + + if (alloc_subdevices(dev, 4) < 0) + return -ENOMEM; + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + + if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && + pcidev->device == PCI_DEVICE_ID_PCI8164) { + if (bus || slot) { + /* requested particular bus/slot */ + if (pcidev->bus->number != bus + || PCI_SLOT(pcidev->devfn) != slot) { + continue; + } + } + devpriv->pci_dev = pcidev; + if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) { + printk("comedi%d: Failed to enable PCI device and request regions\n", dev->minor); + return -EIO; + } + dev->iobase = pci_resource_start(pcidev, 2); + printk("comedi: base addr %4lx\n", dev->iobase); + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + //s->range_table = &range_axis; + s->insn_read = adl_pci8164_insn_read_msts; + s->insn_write = adl_pci8164_insn_write_cmd; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + //s->range_table = &range_axis; + s->insn_read = adl_pci8164_insn_read_ssts; + s->insn_write = adl_pci8164_insn_write_otp; + + s = dev->subdevices + 2; + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + //s->range_table = &range_axis; + s->insn_read = adl_pci8164_insn_read_buf0; + s->insn_write = adl_pci8164_insn_write_buf0; + + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_PROC; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->len_chanlist = 4; + //s->range_table = &range_axis; + s->insn_read = adl_pci8164_insn_read_buf1; + s->insn_write = adl_pci8164_insn_write_buf1; + + printk("comedi: attached\n"); + + return 1; + } + } + + printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, bus, slot); + return -EIO; +} + +static int adl_pci8164_detach(struct comedi_device * dev) +{ + printk("comedi%d: pci8164: remove\n", dev->minor); + + if (devpriv && devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + + return 0; +} + +static int adl_pci8164_insn_read_msts(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int axis, axis_reg; + char *axisname; + + axis = CR_CHAN(insn->chanspec); + + switch (axis) { + case 0: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + break; + case 1: + axis_reg = PCI8164_AXIS_Y; + axisname = "Y"; + break; + case 2: + axis_reg = PCI8164_AXIS_Z; + axisname = "Z"; + break; + case 3: + axis_reg = PCI8164_AXIS_U; + axisname = "U"; + break; + default: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + } + + data[0] = inw(dev->iobase + axis_reg + PCI8164_MSTS); + printk("comedi: pci8164 MSTS read -> %04X:%04X on axis %s\n", data[0], + data[1], axisname); + + return 2; +} + +static int adl_pci8164_insn_read_ssts(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int axis, axis_reg; + char *axisname; + + axis = CR_CHAN(insn->chanspec); + + switch (axis) { + case 0: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + break; + case 1: + axis_reg = PCI8164_AXIS_Y; + axisname = "Y"; + break; + case 2: + axis_reg = PCI8164_AXIS_Z; + axisname = "Z"; + break; + case 3: + axis_reg = PCI8164_AXIS_U; + axisname = "U"; + break; + default: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + } + + data[0] = inw(dev->iobase + axis_reg + PCI8164_SSTS); + printk("comedi: pci8164 SSTS read -> %04X:%04X on axis %s\n", data[0], + data[1], axisname); + + return 2; +} + +static int adl_pci8164_insn_read_buf0(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int axis, axis_reg; + char *axisname; + + axis = CR_CHAN(insn->chanspec); + + switch (axis) { + case 0: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + break; + case 1: + axis_reg = PCI8164_AXIS_Y; + axisname = "Y"; + break; + case 2: + axis_reg = PCI8164_AXIS_Z; + axisname = "Z"; + break; + case 3: + axis_reg = PCI8164_AXIS_U; + axisname = "U"; + break; + default: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + } + + data[0] = inw(dev->iobase + axis_reg + PCI8164_BUF0); + printk("comedi: pci8164 BUF0 read -> %04X:%04X on axis %s\n", data[0], + data[1], axisname); + + return 2; +} + +static int adl_pci8164_insn_read_buf1(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int axis, axis_reg; + + char *axisname; + + axis = CR_CHAN(insn->chanspec); + + switch (axis) { + case 0: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + break; + case 1: + axis_reg = PCI8164_AXIS_Y; + axisname = "Y"; + break; + case 2: + axis_reg = PCI8164_AXIS_Z; + axisname = "Z"; + break; + case 3: + axis_reg = PCI8164_AXIS_U; + axisname = "U"; + break; + default: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + } + + data[0] = inw(dev->iobase + axis_reg + PCI8164_BUF1); + printk("comedi: pci8164 BUF1 read -> %04X:%04X on axis %s\n", data[0], + data[1], axisname); + + return 2; +} + +static int adl_pci8164_insn_write_cmd(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int axis, axis_reg; + + char *axisname; + + axis = CR_CHAN(insn->chanspec); + + switch (axis) { + case 0: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + break; + case 1: + axis_reg = PCI8164_AXIS_Y; + axisname = "Y"; + break; + case 2: + axis_reg = PCI8164_AXIS_Z; + axisname = "Z"; + break; + case 3: + axis_reg = PCI8164_AXIS_U; + axisname = "U"; + break; + default: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + } + + outw(data[0], dev->iobase + axis_reg + PCI8164_CMD); + printk("comedi: pci8164 CMD write -> %04X:%04X on axis %s\n", data[0], + data[1], axisname); + + return 2; +} + +static int adl_pci8164_insn_write_otp(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int axis, axis_reg; + + char *axisname; + + axis = CR_CHAN(insn->chanspec); + + switch (axis) { + case 0: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + break; + case 1: + axis_reg = PCI8164_AXIS_Y; + axisname = "Y"; + break; + case 2: + axis_reg = PCI8164_AXIS_Z; + axisname = "Z"; + break; + case 3: + axis_reg = PCI8164_AXIS_U; + axisname = "U"; + break; + default: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + } + + outw(data[0], dev->iobase + axis_reg + PCI8164_OTP); + printk("comedi: pci8164 OTP write -> %04X:%04X on axis %s\n", data[0], + data[1], axisname); + + return 2; +} + +static int adl_pci8164_insn_write_buf0(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int axis, axis_reg; + + char *axisname; + + axis = CR_CHAN(insn->chanspec); + + switch (axis) { + case 0: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + break; + case 1: + axis_reg = PCI8164_AXIS_Y; + axisname = "Y"; + break; + case 2: + axis_reg = PCI8164_AXIS_Z; + axisname = "Z"; + break; + case 3: + axis_reg = PCI8164_AXIS_U; + axisname = "U"; + break; + default: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + } + + outw(data[0], dev->iobase + axis_reg + PCI8164_BUF0); + printk("comedi: pci8164 BUF0 write -> %04X:%04X on axis %s\n", data[0], + data[1], axisname); + + return 2; +} + +static int adl_pci8164_insn_write_buf1(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int axis, axis_reg; + + char *axisname; + + axis = CR_CHAN(insn->chanspec); + + switch (axis) { + case 0: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + break; + case 1: + axis_reg = PCI8164_AXIS_Y; + axisname = "Y"; + break; + case 2: + axis_reg = PCI8164_AXIS_Z; + axisname = "Z"; + break; + case 3: + axis_reg = PCI8164_AXIS_U; + axisname = "U"; + break; + default: + axis_reg = PCI8164_AXIS_X; + axisname = "X"; + } + + outw(data[0], dev->iobase + axis_reg + PCI8164_BUF1); + printk("comedi: pci8164 BUF1 write -> %04X:%04X on axis %s\n", data[0], + data[1], axisname); + + return 2; +} + +COMEDI_PCI_INITCLEANUP(driver_adl_pci8164, adl_pci8164_pci_table); diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c new file mode 100644 index 000000000000..b4a61c560c5b --- /dev/null +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -0,0 +1,1391 @@ +/* + + comedi/drivers/adl_pci9111.c + + Hardware driver for PCI9111 ADLink cards: + + PCI-9111HR + + Copyright (C) 2002-2005 Emmanuel Pacaud + + 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: adl_pci9111 +Description: Adlink PCI-9111HR +Author: Emmanuel Pacaud +Devices: [ADLink] PCI-9111HR (adl_pci9111) +Status: experimental + +Supports: + + - ai_insn read + - ao_insn read/write + - di_insn read + - do_insn read/write + - ai_do_cmd mode with the following sources: + + - start_src TRIG_NOW + - scan_begin_src TRIG_FOLLOW TRIG_TIMER TRIG_EXT + - convert_src TRIG_TIMER TRIG_EXT + - scan_end_src TRIG_COUNT + - stop_src TRIG_COUNT TRIG_NONE + + The scanned channels must be consecutive and start from 0. They must + all have the same range and aref. + +Configuration options: + + [0] - PCI bus number (optional) + [1] - PCI slot number (optional) + + If bus/slot is not specified, the first available PCI + device will be used. + +*/ + +/* +CHANGELOG: + + 2005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be + a multiple of chanlist_len*convert_arg. + 2002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data. + 2002/02/18 Added external trigger support for analog input. + +TODO: + + - Really test implemented functionality. + - Add support for the PCI-9111DG with a probe routine to identify the card type + (perhaps with the help of the channel number readback of the A/D Data register). + - Add external multiplexer support. + +*/ + +#include "../comedidev.h" + +#include + +#include "8253.h" +#include "comedi_pci.h" +#include "comedi_fc.h" + +#define PCI9111_DRIVER_NAME "adl_pci9111" +#define PCI9111_HR_DEVICE_ID 0x9111 + +/* TODO: Add other pci9111 board id */ + +#define PCI9111_IO_RANGE 0x0100 + +#define PCI9111_FIFO_HALF_SIZE 512 + +#define PCI9111_AI_CHANNEL_NBR 16 + +#define PCI9111_AI_RESOLUTION 12 +#define PCI9111_AI_RESOLUTION_MASK 0x0FFF +#define PCI9111_AI_RESOLUTION_2_CMP_BIT 0x0800 + +#define PCI9111_HR_AI_RESOLUTION 16 +#define PCI9111_HR_AI_RESOLUTION_MASK 0xFFFF +#define PCI9111_HR_AI_RESOLUTION_2_CMP_BIT 0x8000 + +#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS 10000 +#define PCI9111_AO_CHANNEL_NBR 1 +#define PCI9111_AO_RESOLUTION 12 +#define PCI9111_AO_RESOLUTION_MASK 0x0FFF +#define PCI9111_DI_CHANNEL_NBR 16 +#define PCI9111_DO_CHANNEL_NBR 16 +#define PCI9111_DO_MASK 0xFFFF + +#define PCI9111_RANGE_SETTING_DELAY 10 +#define PCI9111_AI_INSTANT_READ_UDELAY_US 2 +#define PCI9111_AI_INSTANT_READ_TIMEOUT 100 + +#define PCI9111_8254_CLOCK_PERIOD_NS 500 + +#define PCI9111_8254_COUNTER_0 0x00 +#define PCI9111_8254_COUNTER_1 0x40 +#define PCI9111_8254_COUNTER_2 0x80 +#define PCI9111_8254_COUNTER_LATCH 0x00 +#define PCI9111_8254_READ_LOAD_LSB_ONLY 0x10 +#define PCI9111_8254_READ_LOAD_MSB_ONLY 0x20 +#define PCI9111_8254_READ_LOAD_LSB_MSB 0x30 +#define PCI9111_8254_MODE_0 0x00 +#define PCI9111_8254_MODE_1 0x02 +#define PCI9111_8254_MODE_2 0x04 +#define PCI9111_8254_MODE_3 0x06 +#define PCI9111_8254_MODE_4 0x08 +#define PCI9111_8254_MODE_5 0x0A +#define PCI9111_8254_BINARY_COUNTER 0x00 +#define PCI9111_8254_BCD_COUNTER 0x01 + +/* IO address map */ + +#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored in FIFO */ +#define PCI9111_REGISTER_DA_OUTPUT 0x00 +#define PCI9111_REGISTER_DIGITAL_IO 0x02 +#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04 +#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel selection */ +#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06 +#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08 +#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08 +#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 0x0A +#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 0x0A +#define PCI9111_REGISTER_SOFTWARE_TRIGGER 0x0E +#define PCI9111_REGISTER_INTERRUPT_CONTROL 0x0C +#define PCI9111_REGISTER_8254_COUNTER_0 0x40 +#define PCI9111_REGISTER_8254_COUNTER_1 0x42 +#define PCI9111_REGISTER_8254_COUNTER_2 0X44 +#define PCI9111_REGISTER_8254_CONTROL 0x46 +#define PCI9111_REGISTER_INTERRUPT_CLEAR 0x48 + +#define PCI9111_TRIGGER_MASK 0x0F +#define PCI9111_PTRG_OFF (0 << 3) +#define PCI9111_PTRG_ON (1 << 3) +#define PCI9111_EITS_EXTERNAL (1 << 2) +#define PCI9111_EITS_INTERNAL (0 << 2) +#define PCI9111_TPST_SOFTWARE_TRIGGER (0 << 1) +#define PCI9111_TPST_TIMER_PACER (1 << 1) +#define PCI9111_ASCAN_ON (1 << 0) +#define PCI9111_ASCAN_OFF (0 << 0) + +#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0) +#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL (1 << 0) +#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK (0 << 1) +#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG (1 << 1) +#define PCI9111_FFEN_SET_FIFO_ENABLE (0 << 2) +#define PCI9111_FFEN_SET_FIFO_DISABLE (1 << 2) + +#define PCI9111_CHANNEL_MASK 0x0F + +#define PCI9111_RANGE_MASK 0x07 +#define PCI9111_FIFO_EMPTY_MASK 0x10 +#define PCI9111_FIFO_HALF_FULL_MASK 0x20 +#define PCI9111_FIFO_FULL_MASK 0x40 +#define PCI9111_AD_BUSY_MASK 0x80 + +#define PCI9111_IO_BASE dev->iobase + +/* + * Define inlined function + */ + +#define pci9111_trigger_and_autoscan_get() \ + (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F) + +#define pci9111_trigger_and_autoscan_set(flags) \ + outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL) + +#define pci9111_interrupt_and_fifo_get() \ + ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) &0x03) + +#define pci9111_interrupt_and_fifo_set(flags) \ + outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL) + +#define pci9111_interrupt_clear() \ + outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR) + +#define pci9111_software_trigger() \ + outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER) + +#define pci9111_fifo_reset() \ + outb(PCI9111_FFEN_SET_FIFO_ENABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ + outb(PCI9111_FFEN_SET_FIFO_DISABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ + outb(PCI9111_FFEN_SET_FIFO_ENABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL) + +#define pci9111_is_fifo_full() \ + ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ + PCI9111_FIFO_FULL_MASK)==0) + +#define pci9111_is_fifo_half_full() \ + ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ + PCI9111_FIFO_HALF_FULL_MASK)==0) + +#define pci9111_is_fifo_empty() \ + ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ + PCI9111_FIFO_EMPTY_MASK)==0) + +#define pci9111_ai_channel_set(channel) \ + outb((channel)&PCI9111_CHANNEL_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL) + +#define pci9111_ai_channel_get() \ + inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)&PCI9111_CHANNEL_MASK + +#define pci9111_ai_range_set(range) \ + outb((range)&PCI9111_RANGE_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE) + +#define pci9111_ai_range_get() \ + inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)&PCI9111_RANGE_MASK + +#define pci9111_ai_get_data() \ + ((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4)&PCI9111_AI_RESOLUTION_MASK) \ + ^ PCI9111_AI_RESOLUTION_2_CMP_BIT + +#define pci9111_hr_ai_get_data() \ + (inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) & PCI9111_HR_AI_RESOLUTION_MASK) \ + ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT + +#define pci9111_ao_set_data(data) \ + outw(data&PCI9111_AO_RESOLUTION_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT) + +#define pci9111_di_get_bits() \ + inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO) + +#define pci9111_do_set_bits(bits) \ + outw(bits,PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO) + +#define pci9111_8254_control_set(flags) \ + outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL) + +#define pci9111_8254_counter_0_set(data) \ + outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \ + outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0) + +#define pci9111_8254_counter_1_set(data) \ + outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \ + outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1) + +#define pci9111_8254_counter_2_set(data) \ + outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \ + outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2) + +/* Function prototypes */ + +static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pci9111_detach(struct comedi_device * dev); +static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s, + void *data, unsigned int num_bytes, unsigned int start_chan_index); + +static const struct comedi_lrange pci9111_hr_ai_range = { + 5, + { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625) + } +}; + +static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = { + {PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, + 0, 0}, + /* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */ + {0} +}; + +MODULE_DEVICE_TABLE(pci, pci9111_pci_table); + +/* */ +/* Board specification structure */ +/* */ + +struct pci9111_board { + const char *name; /* driver name */ + int device_id; + int ai_channel_nbr; /* num of A/D chans */ + int ao_channel_nbr; /* num of D/A chans */ + int ai_resolution; /* resolution of A/D */ + int ai_resolution_mask; + int ao_resolution; /* resolution of D/A */ + int ao_resolution_mask; + const struct comedi_lrange *ai_range_list; /* rangelist for A/D */ + const struct comedi_lrange *ao_range_list; /* rangelist for D/A */ + unsigned int ai_acquisition_period_min_ns; +}; + +static const struct pci9111_board pci9111_boards[] = { + { + name: "pci9111_hr", + device_id:PCI9111_HR_DEVICE_ID, + ai_channel_nbr:PCI9111_AI_CHANNEL_NBR, + ao_channel_nbr:PCI9111_AO_CHANNEL_NBR, + ai_resolution:PCI9111_HR_AI_RESOLUTION, + ai_resolution_mask:PCI9111_HR_AI_RESOLUTION_MASK, + ao_resolution:PCI9111_AO_RESOLUTION, + ao_resolution_mask:PCI9111_AO_RESOLUTION_MASK, + ai_range_list:&pci9111_hr_ai_range, + ao_range_list:&range_bipolar10, + ai_acquisition_period_min_ns:PCI9111_AI_ACQUISITION_PERIOD_MIN_NS} +}; + +#define pci9111_board_nbr \ + (sizeof(pci9111_boards)/sizeof(struct pci9111_board)) + +static struct comedi_driver pci9111_driver = { + driver_name:PCI9111_DRIVER_NAME, + module:THIS_MODULE, + attach:pci9111_attach, + detach:pci9111_detach, +}; + +COMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table); + +/* Private data structure */ + +struct pci9111_private_data { + struct pci_dev *pci_device; + unsigned long io_range; /* PCI6503 io range */ + + unsigned long lcr_io_base; /* Local configuration register base address */ + unsigned long lcr_io_range; + + int stop_counter; + int stop_is_none; + + unsigned int scan_delay; + unsigned int chanlist_len; + unsigned int chunk_counter; + unsigned int chunk_num_samples; + + int ao_readback; /* Last written analog output data */ + + int timer_divisor_1; /* Divisor values for the 8254 timer pacer */ + int timer_divisor_2; + + int is_valid; /* Is device valid */ + + short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; +}; + +#define dev_private ((struct pci9111_private_data *)dev->private) + +/* ------------------------------------------------------------------ */ +/* PLX9050 SECTION */ +/* ------------------------------------------------------------------ */ + +#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c + +#define PLX9050_LINTI1_ENABLE (1 << 0) +#define PLX9050_LINTI1_ACTIVE_HIGH (1 << 1) +#define PLX9050_LINTI1_STATUS (1 << 2) +#define PLX9050_LINTI2_ENABLE (1 << 3) +#define PLX9050_LINTI2_ACTIVE_HIGH (1 << 4) +#define PLX9050_LINTI2_STATUS (1 << 5) +#define PLX9050_PCI_INTERRUPT_ENABLE (1 << 6) +#define PLX9050_SOFTWARE_INTERRUPT (1 << 7) + +static void plx9050_interrupt_control(unsigned long io_base, + bool LINTi1_enable, + bool LINTi1_active_high, + bool LINTi2_enable, bool LINTi2_active_high, bool interrupt_enable) +{ + int flags = 0; + + if (LINTi1_enable) + flags |= PLX9050_LINTI1_ENABLE; + if (LINTi1_active_high) + flags |= PLX9050_LINTI1_ACTIVE_HIGH; + if (LINTi2_enable) + flags |= PLX9050_LINTI2_ENABLE; + if (LINTi2_active_high) + flags |= PLX9050_LINTI2_ACTIVE_HIGH; + + if (interrupt_enable) + flags |= PLX9050_PCI_INTERRUPT_ENABLE; + + outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL); +} + +/* ------------------------------------------------------------------ */ +/* MISCELLANEOUS SECTION */ +/* ------------------------------------------------------------------ */ + +/* 8254 timer */ + +static void pci9111_timer_set(struct comedi_device * dev) +{ + pci9111_8254_control_set(PCI9111_8254_COUNTER_0 | + PCI9111_8254_READ_LOAD_LSB_MSB | + PCI9111_8254_MODE_0 | PCI9111_8254_BINARY_COUNTER); + + pci9111_8254_control_set(PCI9111_8254_COUNTER_1 | + PCI9111_8254_READ_LOAD_LSB_MSB | + PCI9111_8254_MODE_2 | PCI9111_8254_BINARY_COUNTER); + + pci9111_8254_control_set(PCI9111_8254_COUNTER_2 | + PCI9111_8254_READ_LOAD_LSB_MSB | + PCI9111_8254_MODE_2 | PCI9111_8254_BINARY_COUNTER); + + comedi_udelay(1); + + pci9111_8254_counter_2_set(dev_private->timer_divisor_2); + pci9111_8254_counter_1_set(dev_private->timer_divisor_1); +} + +enum pci9111_trigger_sources { + software, + timer_pacer, + external +}; + +static void pci9111_trigger_source_set(struct comedi_device * dev, + enum pci9111_trigger_sources source) +{ + int flags; + + flags = pci9111_trigger_and_autoscan_get() & 0x09; + + switch (source) { + case software: + flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER; + break; + + case timer_pacer: + flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER; + break; + + case external: + flags |= PCI9111_EITS_EXTERNAL; + break; + } + + pci9111_trigger_and_autoscan_set(flags); +} + +static void pci9111_pretrigger_set(struct comedi_device * dev, bool pretrigger) +{ + int flags; + + flags = pci9111_trigger_and_autoscan_get() & 0x07; + + if (pretrigger) + flags |= PCI9111_PTRG_ON; + + pci9111_trigger_and_autoscan_set(flags); +} + +static void pci9111_autoscan_set(struct comedi_device * dev, bool autoscan) +{ + int flags; + + flags = pci9111_trigger_and_autoscan_get() & 0x0e; + + if (autoscan) + flags |= PCI9111_ASCAN_ON; + + pci9111_trigger_and_autoscan_set(flags); +} + +enum pci9111_ISC0_sources { + irq_on_eoc, + irq_on_fifo_half_full +}; + +enum pci9111_ISC1_sources { + irq_on_timer_tick, + irq_on_external_trigger +}; + +static void pci9111_interrupt_source_set(struct comedi_device * dev, + enum pci9111_ISC0_sources irq_0_source, enum pci9111_ISC1_sources irq_1_source) +{ + int flags; + + flags = pci9111_interrupt_and_fifo_get() & 0x04; + + if (irq_0_source == irq_on_fifo_half_full) + flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL; + + if (irq_1_source == irq_on_external_trigger) + flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG; + + pci9111_interrupt_and_fifo_set(flags); +} + +/* ------------------------------------------------------------------ */ +/* HARDWARE TRIGGERED ANALOG INPUT SECTION */ +/* ------------------------------------------------------------------ */ + +/* Cancel analog input autoscan */ + +#undef AI_DO_CMD_DEBUG + +static int pci9111_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + /* Disable interrupts */ + + plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, + true, false); + + pci9111_trigger_source_set(dev, software); + + pci9111_autoscan_set(dev, false); + + pci9111_fifo_reset(); + +#ifdef AI_DO_CMD_DEBUG + printk(PCI9111_DRIVER_NAME ": ai_cancel\n"); +#endif + + return 0; +} + +/* Test analog input command */ + +#define pci9111_check_trigger_src(src,flags) \ + tmp = src; \ + src &= flags; \ + if (!src || tmp != src) error++ + +static int +pci9111_ai_do_cmd_test(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_cmd * cmd) +{ + int tmp; + int error = 0; + int range, reference; + int i; + struct pci9111_board *board = (struct pci9111_board *) dev->board_ptr; + + /* Step 1 : check if trigger are trivialy valid */ + + pci9111_check_trigger_src(cmd->start_src, TRIG_NOW); + pci9111_check_trigger_src(cmd->scan_begin_src, + TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT); + pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT); + pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT); + pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE); + + if (error) + return 1; + + /* step 2 : make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW) + error++; + + if ((cmd->scan_begin_src != TRIG_TIMER) && + (cmd->scan_begin_src != TRIG_FOLLOW) && + (cmd->scan_begin_src != TRIG_EXT)) + error++; + + if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT)) { + error++; + } + if ((cmd->convert_src == TRIG_TIMER) && + !((cmd->scan_begin_src == TRIG_TIMER) || + (cmd->scan_begin_src == TRIG_FOLLOW))) { + error++; + } + if ((cmd->convert_src == TRIG_EXT) && + !((cmd->scan_begin_src == TRIG_EXT) || + (cmd->scan_begin_src == TRIG_FOLLOW))) { + error++; + } + + if (cmd->scan_end_src != TRIG_COUNT) + error++; + if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE)) + error++; + + if (error) + return 2; + + /* Step 3 : make sure arguments are trivialy compatible */ + + if (cmd->chanlist_len < 1) { + cmd->chanlist_len = 1; + error++; + } + + if (cmd->chanlist_len > board->ai_channel_nbr) { + cmd->chanlist_len = board->ai_channel_nbr; + error++; + } + + if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) { + cmd->start_arg = 0; + error++; + } + + if ((cmd->convert_src == TRIG_TIMER) && + (cmd->convert_arg < board->ai_acquisition_period_min_ns)) { + cmd->convert_arg = board->ai_acquisition_period_min_ns; + error++; + } + if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) { + cmd->convert_arg = 0; + error++; + } + + if ((cmd->scan_begin_src == TRIG_TIMER) && + (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) { + cmd->scan_begin_arg = board->ai_acquisition_period_min_ns; + error++; + } + if ((cmd->scan_begin_src == TRIG_FOLLOW) && (cmd->scan_begin_arg != 0)) { + cmd->scan_begin_arg = 0; + error++; + } + if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) { + cmd->scan_begin_arg = 0; + error++; + } + + if ((cmd->scan_end_src == TRIG_COUNT) && + (cmd->scan_end_arg != cmd->chanlist_len)) { + cmd->scan_end_arg = cmd->chanlist_len; + error++; + } + + if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) { + cmd->stop_arg = 1; + error++; + } + if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) { + cmd->stop_arg = 0; + error++; + } + + if (error) + return 3; + + /* Step 4 : fix up any arguments */ + + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, + &(dev_private->timer_divisor_1), + &(dev_private->timer_divisor_2), + &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + error++; + } + /* There's only one timer on this card, so the scan_begin timer must */ + /* be a multiple of chanlist_len*convert_arg */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + + unsigned int scan_begin_min; + unsigned int scan_begin_arg; + unsigned int scan_factor; + + scan_begin_min = cmd->chanlist_len * cmd->convert_arg; + + if (cmd->scan_begin_arg != scan_begin_min) { + if (scan_begin_min < cmd->scan_begin_arg) { + scan_factor = + cmd->scan_begin_arg / scan_begin_min; + scan_begin_arg = scan_factor * scan_begin_min; + if (cmd->scan_begin_arg != scan_begin_arg) { + cmd->scan_begin_arg = scan_begin_arg; + error++; + } + } else { + cmd->scan_begin_arg = scan_begin_min; + error++; + } + } + } + + if (error) + return 4; + + /* Step 5 : check channel list */ + + if (cmd->chanlist) { + + range = CR_RANGE(cmd->chanlist[0]); + reference = CR_AREF(cmd->chanlist[0]); + + if (cmd->chanlist_len > 1) { + for (i = 0; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != i) { + comedi_error(dev, + "entries in chanlist must be consecutive " + "channels,counting upwards from 0\n"); + error++; + } + if (CR_RANGE(cmd->chanlist[i]) != range) { + comedi_error(dev, + "entries in chanlist must all have the same gain\n"); + error++; + } + if (CR_AREF(cmd->chanlist[i]) != reference) { + comedi_error(dev, + "entries in chanlist must all have the same reference\n"); + error++; + } + } + } else { + if ((CR_CHAN(cmd->chanlist[0]) > + (board->ai_channel_nbr - 1)) + || (CR_CHAN(cmd->chanlist[0]) < 0)) { + comedi_error(dev, + "channel number is out of limits\n"); + error++; + } + } + } + + if (error) + return 5; + + return 0; + +} + +/* Analog input command */ + +static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * subdevice) +{ + struct comedi_cmd *async_cmd = &subdevice->async->cmd; + + if (!dev->irq) { + comedi_error(dev, + "no irq assigned for PCI9111, cannot do hardware conversion"); + return -1; + } + /* Set channel scan limit */ + /* PCI9111 allows only scanning from channel 0 to channel n */ + /* TODO: handle the case of an external multiplexer */ + + if (async_cmd->chanlist_len > 1) { + pci9111_ai_channel_set((async_cmd->chanlist_len) - 1); + pci9111_autoscan_set(dev, true); + } else { + pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0])); + pci9111_autoscan_set(dev, false); + } + + /* Set gain */ + /* This is the same gain on every channel */ + + pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0])); + + /* Set counter */ + + switch (async_cmd->stop_src) { + case TRIG_COUNT: + dev_private->stop_counter = + async_cmd->stop_arg * async_cmd->chanlist_len; + dev_private->stop_is_none = 0; + break; + + case TRIG_NONE: + dev_private->stop_counter = 0; + dev_private->stop_is_none = 1; + break; + + default: + comedi_error(dev, "Invalid stop trigger"); + return -1; + } + + /* Set timer pacer */ + + dev_private->scan_delay = 0; + switch (async_cmd->convert_src) { + case TRIG_TIMER: + i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, + &(dev_private->timer_divisor_1), + &(dev_private->timer_divisor_2), + &(async_cmd->convert_arg), + async_cmd->flags & TRIG_ROUND_MASK); +#ifdef AI_DO_CMD_DEBUG + printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n", + dev_private->timer_divisor_1, + dev_private->timer_divisor_2); +#endif + + pci9111_trigger_source_set(dev, software); + pci9111_timer_set(dev); + pci9111_fifo_reset(); + pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, + irq_on_timer_tick); + pci9111_trigger_source_set(dev, timer_pacer); + plx9050_interrupt_control(dev_private->lcr_io_base, true, true, + false, true, true); + + dev_private->scan_delay = + (async_cmd->scan_begin_arg / (async_cmd->convert_arg * + async_cmd->chanlist_len)) - 1; + + break; + + case TRIG_EXT: + + pci9111_trigger_source_set(dev, external); + pci9111_fifo_reset(); + pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, + irq_on_timer_tick); + plx9050_interrupt_control(dev_private->lcr_io_base, true, true, + false, true, true); + + break; + + default: + comedi_error(dev, "Invalid convert trigger"); + return -1; + } + + dev_private->stop_counter *= (1 + dev_private->scan_delay); + dev_private->chanlist_len = async_cmd->chanlist_len; + dev_private->chunk_counter = 0; + dev_private->chunk_num_samples = + dev_private->chanlist_len * (1 + dev_private->scan_delay); + +#ifdef AI_DO_CMD_DEBUG + printk(PCI9111_DRIVER_NAME ": start interruptions!\n"); + printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n", + pci9111_trigger_and_autoscan_get()); + printk(PCI9111_DRIVER_NAME ": irq source = %2x\n", + pci9111_interrupt_and_fifo_get()); + printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n"); + printk(PCI9111_DRIVER_NAME ": stop counter = %d\n", + dev_private->stop_counter); + printk(PCI9111_DRIVER_NAME ": scan delay = %d\n", + dev_private->scan_delay); + printk(PCI9111_DRIVER_NAME ": chanlist_len = %d\n", + dev_private->chanlist_len); + printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n", + dev_private->chunk_num_samples); +#endif + + return 0; +} + +static void pci9111_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s, + void *data, unsigned int num_bytes, unsigned int start_chan_index) +{ + unsigned int i, num_samples = num_bytes / sizeof(short); + short *array = data; + int resolution = + ((struct pci9111_board *) dev->board_ptr)->ai_resolution; + + for (i = 0; i < num_samples; i++) { + if (resolution == PCI9111_HR_AI_RESOLUTION) + array[i] = + (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^ + PCI9111_HR_AI_RESOLUTION_2_CMP_BIT; + else + array[i] = + ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^ + PCI9111_AI_RESOLUTION_2_CMP_BIT; + } +} + +/* ------------------------------------------------------------------ */ +/* INTERRUPT SECTION */ +/* ------------------------------------------------------------------ */ + +#undef INTERRUPT_DEBUG + +static irqreturn_t pci9111_interrupt(int irq, void *p_device PT_REGS_ARG) +{ + struct comedi_device *dev = p_device; + struct comedi_subdevice *subdevice = dev->read_subdev; + struct comedi_async *async; + unsigned long irq_flags; + unsigned char intcsr; + + if (!dev->attached) { + /* Ignore interrupt before device fully attached. */ + /* Might not even have allocated subdevices yet! */ + return IRQ_NONE; + } + + async = subdevice->async; + + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + + /* Check if we are source of interrupt */ + intcsr = inb(dev_private->lcr_io_base + + PLX9050_REGISTER_INTERRUPT_CONTROL); + if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0) + && (((intcsr & (PLX9050_LINTI1_ENABLE | + PLX9050_LINTI1_STATUS)) + == + (PLX9050_LINTI1_ENABLE | + PLX9050_LINTI1_STATUS)) + || ((intcsr & (PLX9050_LINTI2_ENABLE | + PLX9050_LINTI2_STATUS)) + == + (PLX9050_LINTI2_ENABLE | + PLX9050_LINTI2_STATUS))))) { + /* Not the source of the interrupt. */ + /* (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */ + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + return IRQ_NONE; + } + + if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) == + (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) { + /* Interrupt comes from fifo_half-full signal */ + + if (pci9111_is_fifo_full()) { + comedi_spin_unlock_irqrestore(&dev->spinlock, + irq_flags); + comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow"); + pci9111_interrupt_clear(); + pci9111_ai_cancel(dev, subdevice); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + comedi_event(dev, subdevice); + + return IRQ_HANDLED; + } + + if (pci9111_is_fifo_half_full()) { + unsigned int num_samples; + unsigned int bytes_written = 0; + +#ifdef INTERRUPT_DEBUG + printk(PCI9111_DRIVER_NAME ": fifo is half full\n"); +#endif + + num_samples = + PCI9111_FIFO_HALF_SIZE > + dev_private->stop_counter + && !dev_private->stop_is_none ? dev_private-> + stop_counter : PCI9111_FIFO_HALF_SIZE; + insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE, + dev_private->ai_bounce_buffer, num_samples); + + if (dev_private->scan_delay < 1) { + bytes_written = + cfc_write_array_to_buffer(subdevice, + dev_private->ai_bounce_buffer, + num_samples * sizeof(short)); + } else { + int position = 0; + int to_read; + + while (position < num_samples) { + if (dev_private->chunk_counter < + dev_private->chanlist_len) { + to_read = + dev_private-> + chanlist_len - + dev_private-> + chunk_counter; + + if (to_read > + num_samples - position) + to_read = + num_samples - + position; + + bytes_written += + cfc_write_array_to_buffer + (subdevice, + dev_private-> + ai_bounce_buffer + + position, + to_read * + sizeof(short)); + } else { + to_read = + dev_private-> + chunk_num_samples - + dev_private-> + chunk_counter; + if (to_read > + num_samples - position) + to_read = + num_samples - + position; + + bytes_written += + sizeof(short) * + to_read; + } + + position += to_read; + dev_private->chunk_counter += to_read; + + if (dev_private->chunk_counter >= + dev_private->chunk_num_samples) + dev_private->chunk_counter = 0; + } + } + + dev_private->stop_counter -= + bytes_written / sizeof(short); + } + } + + if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) { + async->events |= COMEDI_CB_EOA; + pci9111_ai_cancel(dev, subdevice); + } + + /* Very important, otherwise another interrupt request will be inserted + * and will cause driver hangs on processing interrupt event. */ + + pci9111_interrupt_clear(); + + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + comedi_event(dev, subdevice); + + return IRQ_HANDLED; +} + +/* ------------------------------------------------------------------ */ +/* INSTANT ANALOG INPUT OUTPUT SECTION */ +/* ------------------------------------------------------------------ */ + +/* analog instant input */ + +#undef AI_INSN_DEBUG + +static int pci9111_ai_insn_read(struct comedi_device * dev, + struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data) +{ + int resolution = + ((struct pci9111_board *) dev->board_ptr)->ai_resolution; + + int timeout, i; + +#ifdef AI_INSN_DEBUG + printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n", + CR_CHAN((&insn->chanspec)[0]), + CR_RANGE((&insn->chanspec)[0]), insn->n); +#endif + + pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0])); + + if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0])) { + pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0])); + } + + pci9111_fifo_reset(); + + for (i = 0; i < insn->n; i++) { + pci9111_software_trigger(); + + timeout = PCI9111_AI_INSTANT_READ_TIMEOUT; + + while (timeout--) { + if (!pci9111_is_fifo_empty()) + goto conversion_done; + } + + comedi_error(dev, "A/D read timeout"); + data[i] = 0; + pci9111_fifo_reset(); + return -ETIME; + + conversion_done: + + if (resolution == PCI9111_HR_AI_RESOLUTION) { + data[i] = pci9111_hr_ai_get_data(); + } else { + data[i] = pci9111_ai_get_data(); + } + } + +#ifdef AI_INSN_DEBUG + printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n", + pci9111_ai_channel_get(), + pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get()); +#endif + + return i; +} + +/* Analog instant output */ + +static int +pci9111_ao_insn_write(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int i; + + for (i = 0; i < insn->n; i++) { + pci9111_ao_set_data(data[i]); + dev_private->ao_readback = data[i]; + } + + return i; +} + +/* Analog output readback */ + +static int pci9111_ao_insn_read(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int i; + + for (i = 0; i < insn->n; i++) { + data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK; + } + + return i; +} + +/* ------------------------------------------------------------------ */ +/* DIGITAL INPUT OUTPUT SECTION */ +/* ------------------------------------------------------------------ */ + +/* Digital inputs */ + +static int pci9111_di_insn_bits(struct comedi_device * dev, + struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data) +{ + unsigned int bits; + + bits = pci9111_di_get_bits(); + data[1] = bits; + + return 2; +} + +/* Digital outputs */ + +static int pci9111_do_insn_bits(struct comedi_device * dev, + struct comedi_subdevice * subdevice, struct comedi_insn * insn, unsigned int * data) +{ + unsigned int bits; + + /* Only set bits that have been masked */ + /* data[0] = mask */ + /* data[1] = bit state */ + + data[0] &= PCI9111_DO_MASK; + + bits = subdevice->state; + bits &= ~data[0]; + bits |= data[0] & data[1]; + subdevice->state = bits; + + pci9111_do_set_bits(bits); + + data[1] = bits; + + return 2; +} + +/* ------------------------------------------------------------------ */ +/* INITIALISATION SECTION */ +/* ------------------------------------------------------------------ */ + +/* Reset device */ + +static int pci9111_reset(struct comedi_device * dev) +{ + /* Set trigger source to software */ + + plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, + true, false); + + pci9111_trigger_source_set(dev, software); + pci9111_pretrigger_set(dev, false); + pci9111_autoscan_set(dev, false); + + /* Reset 8254 chip */ + + dev_private->timer_divisor_1 = 0; + dev_private->timer_divisor_2 = 0; + + pci9111_timer_set(dev); + + return 0; +} + +/* Attach */ +/* - Register PCI device */ +/* - Declare device driver capability */ + +static int pci9111_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *subdevice; + unsigned long io_base, io_range, lcr_io_base, lcr_io_range; + struct pci_dev *pci_device; + int error, i; + const struct pci9111_board *board; + + if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0) { + return -ENOMEM; + } + /* Probe the device to determine what device in the series it is. */ + + printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor); + + for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pci_device != NULL; + pci_device = + pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) { + if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) { + for (i = 0; i < pci9111_board_nbr; i++) { + if (pci9111_boards[i].device_id == + pci_device->device) { + /* was a particular bus/slot requested? */ + if ((it->options[0] != 0) + || (it->options[1] != 0)) { + /* are we on the wrong bus/slot? */ + if (pci_device->bus->number != + it->options[0] + || PCI_SLOT(pci_device-> + devfn) != + it->options[1]) { + continue; + } + } + + dev->board_ptr = pci9111_boards + i; + board = (struct pci9111_board *) dev-> + board_ptr; + dev_private->pci_device = pci_device; + goto found; + } + } + } + } + + printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", + dev->minor, it->options[0], it->options[1]); + return -EIO; + + found: + + printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n", + dev->minor, + pci9111_boards[i].name, + pci_device->bus->number, + PCI_SLOT(pci_device->devfn), + PCI_FUNC(pci_device->devfn), pci_device->irq); + + /* TODO: Warn about non-tested boards. */ + + switch (board->device_id) { + }; + + /* Read local configuration register base address [PCI_BASE_ADDRESS #1]. */ + + lcr_io_base = pci_resource_start(pci_device, 1); + lcr_io_range = pci_resource_len(pci_device, 1); + + printk("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n", dev->minor, lcr_io_base, lcr_io_range); + + /* Enable PCI device and request regions */ + if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) { + printk("comedi%d: Failed to enable PCI device and request regions\n", dev->minor); + return -EIO; + } + /* Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */ + + io_base = pci_resource_start(pci_device, 2); + io_range = pci_resource_len(pci_device, 2); + + printk("comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n", + dev->minor, io_base, io_range); + + dev->iobase = io_base; + dev->board_name = board->name; + dev_private->io_range = io_range; + dev_private->is_valid = 0; + dev_private->lcr_io_base = lcr_io_base; + dev_private->lcr_io_range = lcr_io_range; + + pci9111_reset(dev); + + /* Irq setup */ + + dev->irq = 0; + if (pci_device->irq > 0) { + if (comedi_request_irq(pci_device->irq, + pci9111_interrupt, + IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) { + printk("comedi%d: unable to allocate irq %u\n", + dev->minor, pci_device->irq); + return -EINVAL; + } + } + dev->irq = pci_device->irq; + + /* TODO: Add external multiplexer setup (according to option[2]). */ + + if ((error = alloc_subdevices(dev, 4)) < 0) + return error; + + subdevice = dev->subdevices + 0; + dev->read_subdev = subdevice; + + subdevice->type = COMEDI_SUBD_AI; + subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; + + /* TODO: Add external multiplexer data */ + /* if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */ + /* else { subdevice->n_chan = this_board->n_aichan; } */ + + subdevice->n_chan = board->ai_channel_nbr; + subdevice->maxdata = board->ai_resolution_mask; + subdevice->len_chanlist = board->ai_channel_nbr; + subdevice->range_table = board->ai_range_list; + subdevice->cancel = pci9111_ai_cancel; + subdevice->insn_read = pci9111_ai_insn_read; + subdevice->do_cmdtest = pci9111_ai_do_cmd_test; + subdevice->do_cmd = pci9111_ai_do_cmd; + subdevice->munge = pci9111_ai_munge; + + subdevice = dev->subdevices + 1; + subdevice->type = COMEDI_SUBD_AO; + subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON; + subdevice->n_chan = board->ao_channel_nbr; + subdevice->maxdata = board->ao_resolution_mask; + subdevice->len_chanlist = board->ao_channel_nbr; + subdevice->range_table = board->ao_range_list; + subdevice->insn_write = pci9111_ao_insn_write; + subdevice->insn_read = pci9111_ao_insn_read; + + subdevice = dev->subdevices + 2; + subdevice->type = COMEDI_SUBD_DI; + subdevice->subdev_flags = SDF_READABLE; + subdevice->n_chan = PCI9111_DI_CHANNEL_NBR; + subdevice->maxdata = 1; + subdevice->range_table = &range_digital; + subdevice->insn_bits = pci9111_di_insn_bits; + + subdevice = dev->subdevices + 3; + subdevice->type = COMEDI_SUBD_DO; + subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE; + subdevice->n_chan = PCI9111_DO_CHANNEL_NBR; + subdevice->maxdata = 1; + subdevice->range_table = &range_digital; + subdevice->insn_bits = pci9111_do_insn_bits; + + dev_private->is_valid = 1; + + return 0; +} + +/* Detach */ + +static int pci9111_detach(struct comedi_device * dev) +{ + /* Reset device */ + + if (dev->private != 0) { + if (dev_private->is_valid) + pci9111_reset(dev); + + } + /* Release previously allocated irq */ + + if (dev->irq != 0) { + comedi_free_irq(dev->irq, dev); + } + + if (dev_private != 0 && dev_private->pci_device != 0) { + if (dev->iobase) { + comedi_pci_disable(dev_private->pci_device); + } + pci_dev_put(dev_private->pci_device); + } + + return 0; +} diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c new file mode 100644 index 000000000000..278cf30cc4a3 --- /dev/null +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -0,0 +1,2100 @@ +/* + * comedi/drivers/adl_pci9118.c + * + * hardware driver for ADLink cards: + * card: PCI-9118DG, PCI-9118HG, PCI-9118HR + * driver: pci9118dg, pci9118hg, pci9118hr + * + * Author: Michal Dobes + * +*/ +/* +Driver: adl_pci9118 +Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR +Author: Michal Dobes +Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg), + PCI-9118HR (pci9118hr) +Status: works + +This driver supports AI, AO, DI and DO subdevices. +AI subdevice supports cmd and insn interface, +other subdevices support only insn interface. +For AI: +- If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46). +- If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44). +- If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46). +- It is not neccessary to have cmd.scan_end_arg=cmd.chanlist_len but + cmd.scan_end_arg modulo cmd.chanlist_len must by 0. +- If return value of cmdtest is 5 then you've bad channel list + (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar + ranges). + +There are some hardware limitations: +a) You cann't use mixture of unipolar/bipoar ranges or differencial/single + ended inputs. +b) DMA transfers must have the length aligned to two samples (32 bit), + so there is some problems if cmd->chanlist_len is odd. This driver tries + bypass this with adding one sample to the end of the every scan and discard + it on output but this cann't be used if cmd->scan_begin_src=TRIG_FOLLOW + and is used flag TRIG_WAKE_EOS, then driver switch to interrupt driven mode + with interrupt after every sample. +c) If isn't used DMA then you can use only mode where + cmd->scan_begin_src=TRIG_FOLLOW. + +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, then first available PCI + card will be used. + [2] - 0= standard 8 DIFF/16 SE channels configuration + n= external multiplexer connected, 1<=n<=256 + [3] - 0=autoselect DMA or EOC interrupts operation + 1=disable DMA mode + 3=disable DMA and INT, only insn interface will work + [4] - sample&hold signal - card can generate signal for external S&H board + 0=use SSHO (pin 45) signal is generated in onboard hardware S&H logic + 0!=use ADCHN7 (pin 23) signal is generated from driver, number + say how long delay is requested in ns and sign polarity of the hold + (in this case external multiplexor can serve only 128 channels) + [5] - 0=stop measure on all hardware errors + 2|=ignore ADOR - A/D Overrun status + 8|=ignore Bover - A/D Burst Mode Overrun status + 256|=ignore nFull - A/D FIFO Full status + +*/ +#include "../comedidev.h" +#include "../pci_ids.h" + +#include + +#include "amcc_s5933.h" +#include "8253.h" +#include "comedi_pci.h" +#include "comedi_fc.h" + +/* paranoid checks are broken */ +#undef PCI9118_PARANOIDCHECK /* if defined, then is used code which control correct channel number on every 12 bit sample */ + +#undef PCI9118_EXTDEBUG /* if defined then driver prints a lot of messages */ + +#undef DPRINTK +#ifdef PCI9118_EXTDEBUG +#define DPRINTK(fmt, args...) rt_printk(fmt, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#define IORANGE_9118 64 /* I hope */ +#define PCI9118_CHANLEN 255 /* len of chanlist, some source say 256, but reality looks like 255 :-( */ + +#define PCI9118_CNT0 0x00 /* R/W: 8254 couter 0 */ +#define PCI9118_CNT1 0x04 /* R/W: 8254 couter 0 */ +#define PCI9118_CNT2 0x08 /* R/W: 8254 couter 0 */ +#define PCI9118_CNTCTRL 0x0c /* W: 8254 counter control */ +#define PCI9118_AD_DATA 0x10 /* R: A/D data */ +#define PCI9118_DA1 0x10 /* W: D/A registers */ +#define PCI9118_DA2 0x14 +#define PCI9118_ADSTAT 0x18 /* R: A/D status register */ +#define PCI9118_ADCNTRL 0x18 /* W: A/D control register */ +#define PCI9118_DI 0x1c /* R: digi input register */ +#define PCI9118_DO 0x1c /* W: digi output register */ +#define PCI9118_SOFTTRG 0x20 /* W: soft trigger for A/D */ +#define PCI9118_GAIN 0x24 /* W: A/D gain/channel register */ +#define PCI9118_BURST 0x28 /* W: A/D burst number register */ +#define PCI9118_SCANMOD 0x2c /* W: A/D auto scan mode */ +#define PCI9118_ADFUNC 0x30 /* W: A/D function register */ +#define PCI9118_DELFIFO 0x34 /* W: A/D data FIFO reset */ +#define PCI9118_INTSRC 0x38 /* R: interrupt reason register */ +#define PCI9118_INTCTRL 0x38 /* W: interrupt control register */ + +// bits from A/D control register (PCI9118_ADCNTRL) +#define AdControl_UniP 0x80 /* 1=bipolar, 0=unipolar */ +#define AdControl_Diff 0x40 /* 1=differential, 0= single end inputs */ +#define AdControl_SoftG 0x20 /* 1=8254 counter works, 0=counter stops */ +#define AdControl_ExtG 0x10 /* 1=8254 countrol controlled by TGIN(pin 46), 0=controled by SoftG */ +#define AdControl_ExtM 0x08 /* 1=external hardware trigger (pin 44), 0=internal trigger */ +#define AdControl_TmrTr 0x04 /* 1=8254 is iternal trigger source, 0=software trigger is source (register PCI9118_SOFTTRG) */ +#define AdControl_Int 0x02 /* 1=enable INT, 0=disable */ +#define AdControl_Dma 0x01 /* 1=enable DMA, 0=disable */ + +// bits from A/D function register (PCI9118_ADFUNC) +#define AdFunction_PDTrg 0x80 /* 1=positive, 0=negative digital trigger (only positive is correct) */ +#define AdFunction_PETrg 0x40 /* 1=positive, 0=negative external trigger (only positive is correct) */ +#define AdFunction_BSSH 0x20 /* 1=with sample&hold, 0=without */ +#define AdFunction_BM 0x10 /* 1=burst mode, 0=normal mode */ +#define AdFunction_BS 0x08 /* 1=burst mode start, 0=burst mode stop */ +#define AdFunction_PM 0x04 /* 1=post trigger mode, 0=not post trigger */ +#define AdFunction_AM 0x02 /* 1=about trigger mode, 0=not about trigger */ +#define AdFunction_Start 0x01 /* 1=trigger start, 0=trigger stop */ + +// bits from A/D status register (PCI9118_ADSTAT) +#define AdStatus_nFull 0x100 /* 0=FIFO full (fatal), 1=not full */ +#define AdStatus_nHfull 0x080 /* 0=FIFO half full, 1=FIFO not half full */ +#define AdStatus_nEpty 0x040 /* 0=FIFO empty, 1=FIFO not empty */ +#define AdStatus_Acmp 0x020 /* */ +#define AdStatus_DTH 0x010 /* 1=external digital trigger */ +#define AdStatus_Bover 0x008 /* 1=burst mode overrun (fatal) */ +#define AdStatus_ADOS 0x004 /* 1=A/D over speed (warning) */ +#define AdStatus_ADOR 0x002 /* 1=A/D overrun (fatal) */ +#define AdStatus_ADrdy 0x001 /* 1=A/D already ready, 0=not ready */ + +// bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) +// 1=interrupt occur, enable source, 0=interrupt not occur, disable source +#define Int_Timer 0x08 /* timer interrupt */ +#define Int_About 0x04 /* about trigger complete */ +#define Int_Hfull 0x02 /* A/D FIFO hlaf full */ +#define Int_DTrg 0x01 /* external digital trigger */ + +#define START_AI_EXT 0x01 /* start measure on external trigger */ +#define STOP_AI_EXT 0x02 /* stop measure on external trigger */ +#define START_AI_INT 0x04 /* start measure on internal trigger */ +#define STOP_AI_INT 0x08 /* stop measure on internal trigger */ + +#define EXTTRG_AI 0 /* ext trg is used by AI */ + +static const struct comedi_lrange range_pci9118dg_hr = { 8, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; + +static const struct comedi_lrange range_pci9118hg = { 8, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.005), + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01) + } +}; + +#define PCI9118_BIPOLAR_RANGES 4 /* used for test on mixture of BIP/UNI ranges */ + +static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pci9118_detach(struct comedi_device * dev); + +struct boardtype { + const char *name; // board name + int vendor_id; // PCI vendor a device ID of card + int device_id; + int iorange_amcc; // iorange for own S5933 region + int iorange_9118; // pass thru card region size + int n_aichan; // num of A/D chans + int n_aichand; // num of A/D chans in diff mode + int mux_aichan; // num of A/D chans with external multiplexor + int n_aichanlist; // len of chanlist + int n_aochan; // num of D/A chans + int ai_maxdata; // resolution of A/D + int ao_maxdata; // resolution of D/A + const struct comedi_lrange *rangelist_ai; // rangelist for A/D + const struct comedi_lrange *rangelist_ao; // rangelist for D/A + unsigned int ai_ns_min; // max sample speed of card v ns + unsigned int ai_pacer_min; // minimal pacer value (c1*c2 or c1 in burst) + int half_fifo_size; // size of FIFO/2 + +}; + +static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = { + {PCI_VENDOR_ID_AMCC, 0x80d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pci9118_pci_table); + +static const struct boardtype boardtypes[] = { + {"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9, + AMCC_OP_REG_SIZE, IORANGE_9118, + 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff, + &range_pci9118dg_hr, &range_bipolar10, + 3000, 12, 512}, + {"pci9118hg", PCI_VENDOR_ID_AMCC, 0x80d9, + AMCC_OP_REG_SIZE, IORANGE_9118, + 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff, + &range_pci9118hg, &range_bipolar10, + 3000, 12, 512}, + {"pci9118hr", PCI_VENDOR_ID_AMCC, 0x80d9, + AMCC_OP_REG_SIZE, IORANGE_9118, + 16, 8, 256, PCI9118_CHANLEN, 2, 0xffff, 0x0fff, + &range_pci9118dg_hr, &range_bipolar10, + 10000, 40, 512}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype)) + +static struct comedi_driver driver_pci9118 = { + driver_name:"adl_pci9118", + module:THIS_MODULE, + attach:pci9118_attach, + detach:pci9118_detach, + num_names:n_boardtypes, + board_name:&boardtypes[0].name, + offset:sizeof(struct boardtype), +}; + +COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table); + +struct pci9118_private { + unsigned long iobase_a; // base+size for AMCC chip + unsigned int master; // master capable + struct pci_dev *pcidev; // ptr to actual pcidev + unsigned int usemux; // we want to use external multiplexor! +#ifdef PCI9118_PARANOIDCHECK + unsigned short chanlist[PCI9118_CHANLEN + 1]; // list of scaned channel + unsigned char chanlistlen; // number of scanlist +#endif + unsigned char AdControlReg; // A/D control register + unsigned char IntControlReg; // Interrupt control register + unsigned char AdFunctionReg; // A/D function register + char valid; // driver is ok + char ai_neverending; // we do unlimited AI + unsigned int i8254_osc_base; // frequence of onboard oscilator + unsigned int ai_do; // what do AI? 0=nothing, 1 to 4 mode + unsigned int ai_act_scan; // how many scans we finished + unsigned int ai_buf_ptr; // data buffer ptr in samples + unsigned int ai_n_chan; // how many channels is measured + unsigned int ai_n_scanlen; // len of actual scanlist + unsigned int ai_n_realscanlen; // what we must transfer for one outgoing scan include front/back adds + unsigned int ai_act_dmapos; // position in actual real stream + unsigned int ai_add_front; // how many channels we must add before scan to satisfy S&H? + unsigned int ai_add_back; // how many channels we must add before scan to satisfy DMA? + unsigned int *ai_chanlist; // actaul chanlist + unsigned int ai_timer1; + unsigned int ai_timer2; + unsigned int ai_flags; + char ai12_startstop; // measure can start/stop on external trigger + unsigned int ai_divisor1, ai_divisor2; // divisors for start of measure on external start + unsigned int ai_data_len; + short *ai_data; + short ao_data[2]; // data output buffer + unsigned int ai_scans; // number of scans to do + char dma_doublebuf; // we can use double buffring + unsigned int dma_actbuf; // which buffer is used now + short *dmabuf_virt[2]; // pointers to begin of DMA buffer + unsigned long dmabuf_hw[2]; // hw address of DMA buff + unsigned int dmabuf_size[2]; // size of dma buffer in bytes + unsigned int dmabuf_use_size[2]; // which size we may now used for transfer + unsigned int dmabuf_used_size[2]; // which size was trully used + unsigned int dmabuf_panic_size[2]; + unsigned int dmabuf_samples[2]; // size in samples + int dmabuf_pages[2]; // number of pages in buffer + unsigned char cnt0_users; // bit field of 8254 CNT0 users (0-unused, 1-AO, 2-DI, 3-DO) + unsigned char exttrg_users; // bit field of external trigger users (0-AI, 1-AO, 2-DI, 3-DO) + unsigned int cnt0_divisor; // actual CNT0 divisor + void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *, unsigned short, unsigned int, unsigned short); // ptr to actual interrupt AI function + unsigned char ai16bits; // =1 16 bit card + unsigned char usedma; // =1 use DMA transfer and not INT + unsigned char useeoshandle; // =1 change WAKE_EOS DMA transfer to fit on every second + unsigned char usessh; // =1 turn on S&H support + int softsshdelay; // >0 use software S&H, numer is requested delay in ns + unsigned char softsshsample; // polarity of S&H signal in sample state + unsigned char softsshhold; // polarity of S&H signal in hold state + unsigned int ai_maskerr; // which warning was printed + unsigned int ai_maskharderr; // on which error bits stops + unsigned int ai_inttrig_start; // TRIG_INT for start +}; + +#define devpriv ((struct pci9118_private *)dev->private) +#define this_board ((struct boardtype *)dev->board_ptr) + +/* +============================================================================== +*/ + +static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + int n_chan, unsigned int *chanlist, int frontadd, int backadd); +static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd, + int usedma, char eoshandle); +static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2); +static int pci9118_reset(struct comedi_device * dev); +static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source); +static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source); +static int pci9118_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void pci9118_calc_divisors(char mode, struct comedi_device * dev, + struct comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2, + unsigned int flags, int chans, unsigned int *div1, unsigned int *div2, + char usessh, unsigned int chnsshfront); + +/* +============================================================================== +*/ +static int pci9118_insn_read_ai(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + int n, timeout; + + devpriv->AdControlReg = AdControl_Int & 0xff; + devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); // positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop + + if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0)) + return -EINVAL; + + outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO + + for (n = 0; n < insn->n; n++) { + outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */ + comedi_udelay(2); + timeout = 100; + while (timeout--) { + if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy) + goto conv_finish; + comedi_udelay(1); + } + + comedi_error(dev, "A/D insn timeout"); + data[n] = 0; + outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO + return -ETIME; + + conv_finish: + if (devpriv->ai16bits) { + data[n] = + (inl(dev->iobase + + PCI9118_AD_DATA) & 0xffff) ^ 0x8000; + } else { + data[n] = + (inw(dev->iobase + + PCI9118_AD_DATA) >> 4) & 0xfff; + } + } + + outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO + return n; + +} + +/* +============================================================================== +*/ +static int pci9118_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, chanreg, ch; + + ch = CR_CHAN(insn->chanspec); + if (ch) { + chanreg = PCI9118_DA2; + } else { + chanreg = PCI9118_DA1; + } + + for (n = 0; n < insn->n; n++) { + outl(data[n], dev->iobase + chanreg); + devpriv->ao_data[ch] = data[n]; + } + + return n; +} + +/* +============================================================================== +*/ +static int pci9118_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, chan; + + chan = CR_CHAN(insn->chanspec); + for (n = 0; n < insn->n; n++) + data[n] = devpriv->ao_data[chan]; + + return n; +} + +/* +============================================================================== +*/ +static int pci9118_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[1] = inl(dev->iobase + PCI9118_DI) & 0xf; + + return 2; +} + +/* +============================================================================== +*/ +static int pci9118_insn_bits_do(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]); + outl(s->state & 0x0f, dev->iobase + PCI9118_DO); + } + data[1] = s->state; + + return 2; +} + +/* +============================================================================== +*/ +static void interrupt_pci9118_ai_mode4_switch(struct comedi_device * dev) +{ + devpriv->AdFunctionReg = + AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM; + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); + outl(0x30, dev->iobase + PCI9118_CNTCTRL); + outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff, + dev->iobase + PCI9118_CNT0); + outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff, + dev->iobase + PCI9118_CNT0); + devpriv->AdFunctionReg |= AdFunction_Start; + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); +} + +static unsigned int defragment_dma_buffer(struct comedi_device * dev, + struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples) +{ + unsigned int i = 0, j = 0; + unsigned int start_pos = devpriv->ai_add_front, + stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan; + unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan + + devpriv->ai_add_back; + + for (i = 0; i < num_samples; i++) { + if (devpriv->ai_act_dmapos >= start_pos && + devpriv->ai_act_dmapos < stop_pos) { + dma_buffer[j++] = dma_buffer[i]; + } + devpriv->ai_act_dmapos++; + devpriv->ai_act_dmapos %= raw_scanlen; + } + + return j; +} + +/* +============================================================================== +*/ +static unsigned int move_block_from_dma(struct comedi_device * dev, + struct comedi_subdevice * s, short * dma_buffer, unsigned int num_samples) +{ + unsigned int num_bytes; + + num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples); + devpriv->ai_act_scan += + (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen; + s->async->cur_chan += num_samples; + s->async->cur_chan %= devpriv->ai_n_scanlen; + num_bytes = + cfc_write_array_to_buffer(s, dma_buffer, + num_samples * sizeof(short)); + if (num_bytes < num_samples * sizeof(short)) + return -1; + return 0; +} + +/* +============================================================================== +*/ +static char pci9118_decode_error_status(struct comedi_device * dev, + struct comedi_subdevice * s, unsigned char m) +{ + if (m & 0x100) { + comedi_error(dev, "A/D FIFO Full status (Fatal Error!)"); + devpriv->ai_maskerr &= ~0x100L; + } + if (m & 0x008) { + comedi_error(dev, + "A/D Burst Mode Overrun Status (Fatal Error!)"); + devpriv->ai_maskerr &= ~0x008L; + } + if (m & 0x004) { + comedi_error(dev, "A/D Over Speed Status (Warning!)"); + devpriv->ai_maskerr &= ~0x004L; + } + if (m & 0x002) { + comedi_error(dev, "A/D Overrun Status (Fatal Error!)"); + devpriv->ai_maskerr &= ~0x002L; + } + if (m & devpriv->ai_maskharderr) { + s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + pci9118_ai_cancel(dev, s); + comedi_event(dev, s); + return 1; + } + + return 0; +} + +static void pci9118_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s, + void *data, unsigned int num_bytes, unsigned int start_chan_index) +{ + unsigned int i, num_samples = num_bytes / sizeof(short); + short *array = data; + + for (i = 0; i < num_samples; i++) { + if (devpriv->usedma) + array[i] = be16_to_cpu(array[i]); + if (devpriv->ai16bits) { + array[i] ^= 0x8000; + } else { + array[i] = (array[i] >> 4) & 0x0fff; + } + } +} + +/* +============================================================================== +*/ +static void interrupt_pci9118_ai_onesample(struct comedi_device * dev, + struct comedi_subdevice * s, unsigned short int_adstat, unsigned int int_amcc, + unsigned short int_daq) +{ + register short sampl; + + s->async->events = 0; + + if (int_adstat & devpriv->ai_maskerr) + if (pci9118_decode_error_status(dev, s, int_adstat)) + return; + + sampl = inw(dev->iobase + PCI9118_AD_DATA); + +#ifdef PCI9118_PARANOIDCHECK + if (devpriv->ai16bits == 0) { + if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) { // data dropout! + rt_printk + ("comedi: A/D SAMPL - data dropout: received channel %d, expected %d!\n", + sampl & 0x000f, + devpriv->chanlist[s->async->cur_chan]); + s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + pci9118_ai_cancel(dev, s); + comedi_event(dev, s); + return; + } + } +#endif + cfc_write_to_buffer(s, sampl); + s->async->cur_chan++; + if (s->async->cur_chan >= devpriv->ai_n_scanlen) { /* one scan done */ + s->async->cur_chan %= devpriv->ai_n_scanlen; + devpriv->ai_act_scan++; + if (!(devpriv->ai_neverending)) + if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + pci9118_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + } + } + + if (s->async->events) + comedi_event(dev, s); +} + +/* +============================================================================== +*/ +static void interrupt_pci9118_ai_dma(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned short int_adstat, unsigned int int_amcc, + unsigned short int_daq) +{ + unsigned int next_dma_buf, samplesinbuf, sampls, m; + + if (int_amcc & MASTER_ABORT_INT) { + comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!"); + s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + pci9118_ai_cancel(dev, s); + comedi_event(dev, s); + return; + } + + if (int_amcc & TARGET_ABORT_INT) { + comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!"); + s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + pci9118_ai_cancel(dev, s); + comedi_event(dev, s); + return; + } + + if (int_adstat & devpriv->ai_maskerr) +// if (int_adstat & 0x106) + if (pci9118_decode_error_status(dev, s, int_adstat)) + return; + + samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1; // number of received real samples +// DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); + + if (devpriv->dma_doublebuf) { // switch DMA buffers if is used double buffering + next_dma_buf = 1 - devpriv->dma_actbuf; + outl(devpriv->dmabuf_hw[next_dma_buf], + devpriv->iobase_a + AMCC_OP_REG_MWAR); + outl(devpriv->dmabuf_use_size[next_dma_buf], + devpriv->iobase_a + AMCC_OP_REG_MWTC); + devpriv->dmabuf_used_size[next_dma_buf] = + devpriv->dmabuf_use_size[next_dma_buf]; + if (devpriv->ai_do == 4) + interrupt_pci9118_ai_mode4_switch(dev); + } + + if (samplesinbuf) { + m = devpriv->ai_data_len >> 1; // how many samples is to end of buffer +// DPRINTK("samps=%d m=%d %d %d\n",samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr); + sampls = m; + move_block_from_dma(dev, s, + devpriv->dmabuf_virt[devpriv->dma_actbuf], + samplesinbuf); + m = m - sampls; // m= how many samples was transfered + } +// DPRINTK("YYY\n"); + + if (!devpriv->ai_neverending) + if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + pci9118_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + } + + if (devpriv->dma_doublebuf) { // switch dma buffers + devpriv->dma_actbuf = 1 - devpriv->dma_actbuf; + } else { // restart DMA if is not used double buffering + outl(devpriv->dmabuf_hw[0], + devpriv->iobase_a + AMCC_OP_REG_MWAR); + outl(devpriv->dmabuf_use_size[0], + devpriv->iobase_a + AMCC_OP_REG_MWTC); + if (devpriv->ai_do == 4) + interrupt_pci9118_ai_mode4_switch(dev); + } + + comedi_event(dev, s); +} + +/* +============================================================================== +*/ +static irqreturn_t interrupt_pci9118(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + unsigned int int_daq = 0, int_amcc, int_adstat; + + if (!dev->attached) + return IRQ_NONE; // not fully initialized + + int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf; // get IRQ reasons from card + int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR); // get INT register from AMCC chip + +// DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n", int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR), inl(devpriv->iobase_a+AMCC_OP_REG_MWTC), inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do); + + if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) + return IRQ_NONE; // interrupt from other source + + outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR); // shutdown IRQ reasons in AMCC + + int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff; // get STATUS register + + if (devpriv->ai_do) { + if (devpriv->ai12_startstop) + if ((int_adstat & AdStatus_DTH) && (int_daq & Int_DTrg)) { // start stop of measure + if (devpriv->ai12_startstop & START_AI_EXT) { + devpriv->ai12_startstop &= + ~START_AI_EXT; + if (!(devpriv->ai12_startstop & + STOP_AI_EXT)) + pci9118_exttrg_del(dev, EXTTRG_AI); // deactivate EXT trigger + start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, devpriv->ai_divisor2); // start pacer + outl(devpriv->AdControlReg, + dev->iobase + PCI9118_ADCNTRL); + } else { + if (devpriv-> + ai12_startstop & STOP_AI_EXT) { + devpriv->ai12_startstop &= + ~STOP_AI_EXT; + pci9118_exttrg_del(dev, EXTTRG_AI); // deactivate EXT trigger + devpriv->ai_neverending = 0; //well, on next interrupt from DMA/EOC measure will stop + } + } + } + + (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat, + int_amcc, int_daq); + + } + return IRQ_HANDLED; +} + +/* +============================================================================== +*/ +static int pci9118_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ + if (trignum != devpriv->ai_inttrig_start) + return -EINVAL; + + devpriv->ai12_startstop &= ~START_AI_INT; + s->async->inttrig = NULL; + + outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); + if (devpriv->ai_do != 3) { + start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, + devpriv->ai_divisor2); + devpriv->AdControlReg |= AdControl_SoftG; + } + outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); + + return 1; +} + +/* +============================================================================== +*/ +static int pci9118_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp, divisor1, divisor2; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + if (devpriv->master) { + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW; + } else { + cmd->scan_begin_src &= TRIG_FOLLOW; + } + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + if (devpriv->master) { + cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW; + } else { + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + } + 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_COUNT | TRIG_NONE | TRIG_EXT; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW && + cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) { + cmd->start_src = TRIG_NOW; + err++; + } + + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_INT && + cmd->scan_begin_src != TRIG_FOLLOW) { + cmd->scan_begin_src = TRIG_FOLLOW; + err++; + } + + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) { + cmd->convert_src = TRIG_TIMER; + err++; + } + + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && + cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) { + cmd->stop_src = TRIG_COUNT; + err++; + } + + if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) { + cmd->start_src = TRIG_NOW; + err++; + } + + if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) { + cmd->start_src = TRIG_NOW; + err++; + } + + if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) && + (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) { + cmd->convert_src = TRIG_TIMER; + err++; + } + + if ((cmd->scan_begin_src == TRIG_FOLLOW) && + (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) { + cmd->convert_src = TRIG_TIMER; + err++; + } + + if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) { + cmd->stop_src = TRIG_COUNT; + err++; + } + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_src & (TRIG_NOW | TRIG_EXT)) + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT)) + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + + if ((cmd->scan_begin_src == TRIG_TIMER) && + (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) { + cmd->scan_begin_src = TRIG_FOLLOW; + cmd->convert_arg = cmd->scan_begin_arg; + cmd->scan_begin_arg = 0; + } + + if (cmd->scan_begin_src == TRIG_TIMER) + if (cmd->scan_begin_arg < this_board->ai_ns_min) { + cmd->scan_begin_arg = this_board->ai_ns_min; + err++; + } + + if (cmd->scan_begin_src == TRIG_EXT) + if (cmd->scan_begin_arg) { + cmd->scan_begin_arg = 0; + err++; + if (cmd->scan_end_arg > 65535) { + cmd->scan_end_arg = 65535; + err++; + } + } + + if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) + if (cmd->convert_arg < this_board->ai_ns_min) { + cmd->convert_arg = this_board->ai_ns_min; + err++; + } + + if (cmd->convert_src == TRIG_EXT) + if (cmd->convert_arg) { + cmd->convert_arg = 0; + err++; + } + + if (cmd->stop_src == TRIG_COUNT) { + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + } else { /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + + if (cmd->chanlist_len > this_board->n_aichanlist) { + cmd->chanlist_len = this_board->n_aichanlist; + err++; + } + + if (cmd->scan_end_arg < cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + if ((cmd->scan_end_arg % cmd->chanlist_len)) { + cmd->scan_end_arg = + cmd->chanlist_len * (cmd->scan_end_arg / + cmd->chanlist_len); + err++; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; +// rt_printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, + &divisor2, &cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); +// rt_printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); + if (cmd->scan_begin_arg < this_board->ai_ns_min) + cmd->scan_begin_arg = this_board->ai_ns_min; + if (tmp != cmd->scan_begin_arg) + err++; + } + + if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) { + tmp = cmd->convert_arg; + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, + &divisor2, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); +// rt_printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); + if (cmd->convert_arg < this_board->ai_ns_min) + cmd->convert_arg = this_board->ai_ns_min; + if (tmp != cmd->convert_arg) + err++; + if (cmd->scan_begin_src == TRIG_TIMER + && cmd->convert_src == TRIG_NOW) { + if (cmd->convert_arg == 0) { + if (cmd->scan_begin_arg < + this_board->ai_ns_min * + (cmd->scan_end_arg + 2)) { + cmd->scan_begin_arg = + this_board->ai_ns_min * + (cmd->scan_end_arg + 2); +// rt_printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); + err++; + } + } else { + if (cmd->scan_begin_arg < + cmd->convert_arg * cmd->chanlist_len) { + cmd->scan_begin_arg = + cmd->convert_arg * + cmd->chanlist_len; +// rt_printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); + err++; + } + } + } + } + + if (err) + return 4; + + if (cmd->chanlist) + if (!check_channel_list(dev, s, cmd->chanlist_len, + cmd->chanlist, 0, 0)) + return 5; // incorrect channels list + + return 0; +} + +/* +============================================================================== +*/ +static int Compute_and_setup_dma(struct comedi_device * dev) +{ + unsigned int dmalen0, dmalen1, i; + + DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n"); + dmalen0 = devpriv->dmabuf_size[0]; + dmalen1 = devpriv->dmabuf_size[1]; + DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1, + devpriv->ai_data_len); + // isn't output buff smaller that our DMA buff? + if (dmalen0 > (devpriv->ai_data_len)) { + dmalen0 = devpriv->ai_data_len & ~3L; // allign to 32bit down + } + if (dmalen1 > (devpriv->ai_data_len)) { + dmalen1 = devpriv->ai_data_len & ~3L; // allign to 32bit down + } + DPRINTK("2 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); + + // we want wake up every scan? + if (devpriv->ai_flags & TRIG_WAKE_EOS) { + if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) { + // uff, too short DMA buffer, disable EOS support! + devpriv->ai_flags &= (~TRIG_WAKE_EOS); + rt_printk + ("comedi%d: WAR: DMA0 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n", + dev->minor, dmalen0, + devpriv->ai_n_realscanlen << 1); + } else { + // short first DMA buffer to one scan + dmalen0 = devpriv->ai_n_realscanlen << 1; + DPRINTK("21 dmalen0=%d ai_n_realscanlen=%d useeoshandle=%d\n", dmalen0, devpriv->ai_n_realscanlen, devpriv->useeoshandle); + if (devpriv->useeoshandle) + dmalen0 += 2; + if (dmalen0 < 4) { + rt_printk + ("comedi%d: ERR: DMA0 buf len bug? (%d<4)\n", + dev->minor, dmalen0); + dmalen0 = 4; + } + } + } + if (devpriv->ai_flags & TRIG_WAKE_EOS) { + if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) { + // uff, too short DMA buffer, disable EOS support! + devpriv->ai_flags &= (~TRIG_WAKE_EOS); + rt_printk + ("comedi%d: WAR: DMA1 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n", + dev->minor, dmalen1, + devpriv->ai_n_realscanlen << 1); + } else { + // short second DMA buffer to one scan + dmalen1 = devpriv->ai_n_realscanlen << 1; + DPRINTK("22 dmalen1=%d ai_n_realscanlen=%d useeoshandle=%d\n", dmalen1, devpriv->ai_n_realscanlen, devpriv->useeoshandle); + if (devpriv->useeoshandle) + dmalen1 -= 2; + if (dmalen1 < 4) { + rt_printk + ("comedi%d: ERR: DMA1 buf len bug? (%d<4)\n", + dev->minor, dmalen1); + dmalen1 = 4; + } + } + } + + DPRINTK("3 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); + // transfer without TRIG_WAKE_EOS + if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) { + // if it's possible then allign DMA buffers to length of scan + i = dmalen0; + dmalen0 = + (dmalen0 / (devpriv->ai_n_realscanlen << 1)) * + (devpriv->ai_n_realscanlen << 1); + dmalen0 &= ~3L; + if (!dmalen0) + dmalen0 = i; // uff. very long scan? + i = dmalen1; + dmalen1 = + (dmalen1 / (devpriv->ai_n_realscanlen << 1)) * + (devpriv->ai_n_realscanlen << 1); + dmalen1 &= ~3L; + if (!dmalen1) + dmalen1 = i; // uff. very long scan? + // if measure isn't neverending then test, if it whole fits into one or two DMA buffers + if (!devpriv->ai_neverending) { + // fits whole measure into one DMA buffer? + if (dmalen0 > + ((devpriv->ai_n_realscanlen << 1) * + devpriv->ai_scans)) { + DPRINTK("3.0 ai_n_realscanlen=%d ai_scans=%d \n", devpriv->ai_n_realscanlen, devpriv->ai_scans); + dmalen0 = + (devpriv->ai_n_realscanlen << 1) * + devpriv->ai_scans; + DPRINTK("3.1 dmalen0=%d dmalen1=%d \n", dmalen0, + dmalen1); + dmalen0 &= ~3L; + } else { // fits whole measure into two DMA buffer? + if (dmalen1 > + ((devpriv->ai_n_realscanlen << 1) * + devpriv->ai_scans - dmalen0)) + dmalen1 = + (devpriv-> + ai_n_realscanlen << 1) * + devpriv->ai_scans - dmalen0; + DPRINTK("3.2 dmalen0=%d dmalen1=%d \n", dmalen0, + dmalen1); + dmalen1 &= ~3L; + } + } + } + + DPRINTK("4 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); + + // these DMA buffer size we'll be used + devpriv->dma_actbuf = 0; + devpriv->dmabuf_use_size[0] = dmalen0; + devpriv->dmabuf_use_size[1] = dmalen1; + + DPRINTK("5 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1); +#if 0 + if (devpriv->ai_n_scanlen < this_board->half_fifo_size) { + devpriv->dmabuf_panic_size[0] = + (this_board->half_fifo_size / devpriv->ai_n_scanlen + + 1) * devpriv->ai_n_scanlen * sizeof(short); + devpriv->dmabuf_panic_size[1] = + (this_board->half_fifo_size / devpriv->ai_n_scanlen + + 1) * devpriv->ai_n_scanlen * sizeof(short); + } else { + devpriv->dmabuf_panic_size[0] = + (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0]; + devpriv->dmabuf_panic_size[1] = + (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1]; + } +#endif + + outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR); // stop DMA + outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR); + outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC); + // init DMA transfer + outl(0x00000000 | AINT_WRITE_COMPL, + devpriv->iobase_a + AMCC_OP_REG_INTCSR); +// outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); + + outl(inl(devpriv->iobase_a + + AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY | + EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR); + outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_INTCSR); // allow bus mastering + + DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n"); + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_ai_docmd_sampl(struct comedi_device * dev, struct comedi_subdevice * s) +{ + DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n", + dev->minor, devpriv->ai_do); + switch (devpriv->ai_do) { + case 1: + devpriv->AdControlReg |= AdControl_TmrTr; + break; + case 2: + comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n"); + return -EIO; + case 3: + devpriv->AdControlReg |= AdControl_ExtM; + break; + case 4: + comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n"); + return -EIO; + default: + comedi_error(dev, + "pci9118_ai_docmd_sampl() mode number bug!\n"); + return -EIO; + }; + + devpriv->int_ai_func = interrupt_pci9118_ai_onesample; //transfer function + + if (devpriv->ai12_startstop) + pci9118_exttrg_add(dev, EXTTRG_AI); // activate EXT trigger + + if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2)) + devpriv->IntControlReg |= Int_Timer; + + devpriv->AdControlReg |= AdControl_Int; + + outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR); // allow INT in AMCC + + if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) { + outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); + if (devpriv->ai_do != 3) { + start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, + devpriv->ai_divisor2); + devpriv->AdControlReg |= AdControl_SoftG; + } + outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); + } + + DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n"); + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_ai_docmd_dma(struct comedi_device * dev, struct comedi_subdevice * s) +{ + DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n", + dev->minor, devpriv->ai_do, devpriv->usedma); + Compute_and_setup_dma(dev); + + switch (devpriv->ai_do) { + case 1: + devpriv->AdControlReg |= + ((AdControl_TmrTr | AdControl_Dma) & 0xff); + break; + case 2: + devpriv->AdControlReg |= + ((AdControl_TmrTr | AdControl_Dma) & 0xff); + devpriv->AdFunctionReg = + AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM | + AdFunction_BS; + if (devpriv->usessh && (!devpriv->softsshdelay)) + devpriv->AdFunctionReg |= AdFunction_BSSH; + outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST); + break; + case 3: + devpriv->AdControlReg |= + ((AdControl_ExtM | AdControl_Dma) & 0xff); + devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; + break; + case 4: + devpriv->AdControlReg |= + ((AdControl_TmrTr | AdControl_Dma) & 0xff); + devpriv->AdFunctionReg = + AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM; + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); + outl(0x30, dev->iobase + PCI9118_CNTCTRL); + outl((devpriv->dmabuf_hw[0] >> 1) & 0xff, + dev->iobase + PCI9118_CNT0); + outl((devpriv->dmabuf_hw[0] >> 9) & 0xff, + dev->iobase + PCI9118_CNT0); + devpriv->AdFunctionReg |= AdFunction_Start; + break; + default: + comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n"); + return -EIO; + }; + + if (devpriv->ai12_startstop) { + pci9118_exttrg_add(dev, EXTTRG_AI); // activate EXT trigger + } + + devpriv->int_ai_func = interrupt_pci9118_ai_dma; //transfer function + + outl(0x02000000 | AINT_WRITE_COMPL, + devpriv->iobase_a + AMCC_OP_REG_INTCSR); + + if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) { + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); + outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); + if (devpriv->ai_do != 3) { + start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, + devpriv->ai_divisor2); + devpriv->AdControlReg |= AdControl_SoftG; + } + outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); + } + + DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n"); + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int addchans = 0; + int ret = 0; + + DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n", dev->minor); + devpriv->ai12_startstop = 0; + devpriv->ai_flags = cmd->flags; + devpriv->ai_n_chan = cmd->chanlist_len; + devpriv->ai_n_scanlen = cmd->scan_end_arg; + devpriv->ai_chanlist = cmd->chanlist; + devpriv->ai_data = s->async->prealloc_buf; + devpriv->ai_data_len = s->async->prealloc_bufsz; + devpriv->ai_timer1 = 0; + devpriv->ai_timer2 = 0; + devpriv->ai_add_front = 0; + devpriv->ai_add_back = 0; + devpriv->ai_maskerr = 0x10e; + + // prepare for start/stop conditions + if (cmd->start_src == TRIG_EXT) + devpriv->ai12_startstop |= START_AI_EXT; + if (cmd->stop_src == TRIG_EXT) { + devpriv->ai_neverending = 1; + devpriv->ai12_startstop |= STOP_AI_EXT; + } + if (cmd->start_src == TRIG_INT) { + devpriv->ai12_startstop |= START_AI_INT; + devpriv->ai_inttrig_start = cmd->start_arg; + s->async->inttrig = pci9118_ai_inttrig; + } +#if 0 + if (cmd->stop_src == TRIG_INT) { + devpriv->ai_neverending = 1; + devpriv->ai12_startstop |= STOP_AI_INT; + } +#endif + if (cmd->stop_src == TRIG_NONE) + devpriv->ai_neverending = 1; + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ai_scans = cmd->stop_arg; + devpriv->ai_neverending = 0; + } else { + devpriv->ai_scans = 0; + } + + // use sample&hold signal? + if (cmd->convert_src == TRIG_NOW) { + devpriv->usessh = 1; + } // yes + else { + devpriv->usessh = 0; + } // no + + DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n", + devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh, + devpriv->ai12_startstop); + + // use additional sample at end of every scan to satisty DMA 32 bit transfer? + devpriv->ai_add_front = 0; + devpriv->ai_add_back = 0; + devpriv->useeoshandle = 0; + if (devpriv->master) { + devpriv->usedma = 1; + if ((cmd->flags & TRIG_WAKE_EOS) && + (devpriv->ai_n_scanlen == 1)) { + if (cmd->convert_src == TRIG_NOW) { + devpriv->ai_add_back = 1; + } + if (cmd->convert_src == TRIG_TIMER) { + devpriv->usedma = 0; // use INT transfer if scanlist have only one channel + } + } + if ((cmd->flags & TRIG_WAKE_EOS) && + (devpriv->ai_n_scanlen & 1) && + (devpriv->ai_n_scanlen > 1)) { + if (cmd->scan_begin_src == TRIG_FOLLOW) { + //vpriv->useeoshandle=1; // change DMA transfer block to fit EOS on every second call + devpriv->usedma = 0; // XXX maybe can be corrected to use 16 bit DMA + } else { // well, we must insert one sample to end of EOS to meet 32 bit transfer + devpriv->ai_add_back = 1; + } + } + } else { // interrupt transfer don't need any correction + devpriv->usedma = 0; + } + + // we need software S&H signal? It add two samples before every scan as minimum + if (devpriv->usessh && devpriv->softsshdelay) { + devpriv->ai_add_front = 2; + if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) { // move it to front + devpriv->ai_add_front++; + devpriv->ai_add_back = 0; + } + if (cmd->convert_arg < this_board->ai_ns_min) + cmd->convert_arg = this_board->ai_ns_min; + addchans = devpriv->softsshdelay / cmd->convert_arg; + if (devpriv->softsshdelay % cmd->convert_arg) + addchans++; + if (addchans > (devpriv->ai_add_front - 1)) { // uff, still short :-( + devpriv->ai_add_front = addchans + 1; + if (devpriv->usedma == 1) + if ((devpriv->ai_add_front + + devpriv->ai_n_chan + + devpriv->ai_add_back) & 1) + devpriv->ai_add_front++; // round up to 32 bit + } + } // well, we now know what must be all added + + devpriv->ai_n_realscanlen = // what we must take from card in real to have ai_n_scanlen on output? + (devpriv->ai_add_front + devpriv->ai_n_chan + + devpriv->ai_add_back) * (devpriv->ai_n_scanlen / + devpriv->ai_n_chan); + + DPRINTK("2 usedma=%d realscan=%d af=%u n_chan=%d ab=%d n_scanlen=%d\n", + devpriv->usedma, + devpriv->ai_n_realscanlen, devpriv->ai_add_front, + devpriv->ai_n_chan, devpriv->ai_add_back, + devpriv->ai_n_scanlen); + + // check and setup channel list + if (!check_channel_list(dev, s, devpriv->ai_n_chan, + devpriv->ai_chanlist, devpriv->ai_add_front, + devpriv->ai_add_back)) + return -EINVAL; + if (!setup_channel_list(dev, s, devpriv->ai_n_chan, + devpriv->ai_chanlist, 0, devpriv->ai_add_front, + devpriv->ai_add_back, devpriv->usedma, + devpriv->useeoshandle)) + return -EINVAL; + + // compute timers settings + // simplest way, fr=4Mhz/(tim1*tim2), channel manipulation without timers effect + if (((cmd->scan_begin_src == TRIG_FOLLOW) || (cmd->scan_begin_src == TRIG_EXT) || (cmd->scan_begin_src == TRIG_INT)) && (cmd->convert_src == TRIG_TIMER)) { // both timer is used for one time + if (cmd->scan_begin_src == TRIG_EXT) { + devpriv->ai_do = 4; + } else { + devpriv->ai_do = 1; + } + pci9118_calc_divisors(devpriv->ai_do, dev, s, + &cmd->scan_begin_arg, &cmd->convert_arg, + devpriv->ai_flags, devpriv->ai_n_realscanlen, + &devpriv->ai_divisor1, &devpriv->ai_divisor2, + devpriv->usessh, devpriv->ai_add_front); + devpriv->ai_timer2 = cmd->convert_arg; + } + + if ((cmd->scan_begin_src == TRIG_TIMER) && ((cmd->convert_src == TRIG_TIMER) || (cmd->convert_src == TRIG_NOW))) { // double timed action + if (!devpriv->usedma) { + comedi_error(dev, + "cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!"); + return -EIO; + } + + devpriv->ai_do = 2; + pci9118_calc_divisors(devpriv->ai_do, dev, s, + &cmd->scan_begin_arg, &cmd->convert_arg, + devpriv->ai_flags, devpriv->ai_n_realscanlen, + &devpriv->ai_divisor1, &devpriv->ai_divisor2, + devpriv->usessh, devpriv->ai_add_front); + devpriv->ai_timer1 = cmd->scan_begin_arg; + devpriv->ai_timer2 = cmd->convert_arg; + } + + if ((cmd->scan_begin_src == TRIG_FOLLOW) + && (cmd->convert_src == TRIG_EXT)) { + devpriv->ai_do = 3; + } + + start_pacer(dev, -1, 0, 0); // stop pacer + + devpriv->AdControlReg = 0; // bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable DMA + outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); + devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; // positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); + comedi_udelay(1); + outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO + inl(dev->iobase + PCI9118_ADSTAT); // flush A/D and INT status register + inl(dev->iobase + PCI9118_INTSRC); + + devpriv->ai_act_scan = 0; + devpriv->ai_act_dmapos = 0; + s->async->cur_chan = 0; + devpriv->ai_buf_ptr = 0; + + if (devpriv->usedma) { + ret = pci9118_ai_docmd_dma(dev, s); + } else { + ret = pci9118_ai_docmd_sampl(dev, s); + } + + DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n"); + return ret; +} + +/* +============================================================================== +*/ +static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + int n_chan, unsigned int *chanlist, int frontadd, int backadd) +{ + unsigned int i, differencial = 0, bipolar = 0; + + /* correct channel and range number check itself comedi/range.c */ + if (n_chan < 1) { + comedi_error(dev, "range/channel list is empty!"); + return 0; + } + if ((frontadd + n_chan + backadd) > s->len_chanlist) { + rt_printk + ("comedi%d: range/channel list is too long for actual configuration (%d>%d)!", + dev->minor, n_chan, + s->len_chanlist - frontadd - backadd); + return 0; + } + + if (CR_AREF(chanlist[0]) == AREF_DIFF) + differencial = 1; // all input must be diff + if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES) + bipolar = 1; // all input must be bipolar + if (n_chan > 1) + for (i = 1; i < n_chan; i++) { // check S.E/diff + if ((CR_AREF(chanlist[i]) == AREF_DIFF) != + (differencial)) { + comedi_error(dev, + "Differencial and single ended inputs cann't be mixtured!"); + return 0; + } + if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) != + (bipolar)) { + comedi_error(dev, + "Bipolar and unipolar ranges cann't be mixtured!"); + return 0; + } + if ((!devpriv->usemux) & (differencial) & + (CR_CHAN(chanlist[i]) >= + this_board->n_aichand)) { + comedi_error(dev, + "If AREF_DIFF is used then is available only first 8 channels!"); + return 0; + } + } + + return 1; +} + +/* +============================================================================== +*/ +static int setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd, + int usedma, char useeos) +{ + unsigned int i, differencial = 0, bipolar = 0; + unsigned int scanquad, gain, ssh = 0x00; + + DPRINTK("adl_pci9118 EDBG: BGN: setup_channel_list(%d,.,%d,.,%d,%d,%d,%d)\n", dev->minor, n_chan, rot, frontadd, backadd, usedma); + + if (usedma == 1) { + rot = 8; + usedma = 0; + } + + if (CR_AREF(chanlist[0]) == AREF_DIFF) + differencial = 1; // all input must be diff + if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES) + bipolar = 1; // all input must be bipolar + + // All is ok, so we can setup channel/range list + + if (!bipolar) { + devpriv->AdControlReg |= AdControl_UniP; // set unibipolar + } else { + devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff); // enable bipolar + } + + if (differencial) { + devpriv->AdControlReg |= AdControl_Diff; // enable diff inputs + } else { + devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff); // set single ended inputs + } + + outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); // setup mode + + outl(2, dev->iobase + PCI9118_SCANMOD); // gods know why this sequence! + outl(0, dev->iobase + PCI9118_SCANMOD); + outl(1, dev->iobase + PCI9118_SCANMOD); + +#ifdef PCI9118_PARANOIDCHECK + devpriv->chanlistlen = n_chan; + for (i = 0; i < (PCI9118_CHANLEN + 1); i++) + devpriv->chanlist[i] = 0x55aa; +#endif + + if (frontadd) { // insert channels for S&H + ssh = devpriv->softsshsample; + DPRINTK("FA: %04x: ", ssh); + for (i = 0; i < frontadd; i++) { // store range list to card + scanquad = CR_CHAN(chanlist[0]); // get channel number; + gain = CR_RANGE(chanlist[0]); // get gain number + scanquad |= ((gain & 0x03) << 8); + outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); + DPRINTK("%02x ", scanquad | ssh); + ssh = devpriv->softsshhold; + } + DPRINTK("\n "); + } + + DPRINTK("SL: ", ssh); + for (i = 0; i < n_chan; i++) { // store range list to card + scanquad = CR_CHAN(chanlist[i]); // get channel number; +#ifdef PCI9118_PARANOIDCHECK + devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot; +#endif + gain = CR_RANGE(chanlist[i]); // get gain number + scanquad |= ((gain & 0x03) << 8); + outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); + DPRINTK("%02x ", scanquad | ssh); + } + DPRINTK("\n "); + + if (backadd) { // insert channels for fit onto 32bit DMA + DPRINTK("BA: %04x: ", ssh); + for (i = 0; i < backadd; i++) { // store range list to card + scanquad = CR_CHAN(chanlist[0]); // get channel number; + gain = CR_RANGE(chanlist[0]); // get gain number + scanquad |= ((gain & 0x03) << 8); + outl(scanquad | ssh, dev->iobase + PCI9118_GAIN); + DPRINTK("%02x ", scanquad | ssh); + } + DPRINTK("\n "); + } +#ifdef PCI9118_PARANOIDCHECK + devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma]; // for 32bit oerations + if (useeos) { + for (i = 1; i < n_chan; i++) { // store range list to card + devpriv->chanlist[(n_chan + i) ^ usedma] = + (CR_CHAN(chanlist[i]) & 0xf) << rot; + } + devpriv->chanlist[(2 * n_chan) ^ usedma] = devpriv->chanlist[0 ^ usedma]; // for 32bit oerations + useeos = 2; + } else { + useeos = 1; + } +#ifdef PCI9118_EXTDEBUG + DPRINTK("CHL: "); + for (i = 0; i <= (useeos * n_chan); i++) { + DPRINTK("%04x ", devpriv->chanlist[i]); + } + DPRINTK("\n "); +#endif +#endif + outl(0, dev->iobase + PCI9118_SCANMOD); // close scan queue +// comedi_udelay(100); // important delay, or first sample will be cripled + + DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n"); + return 1; // we can serve this with scan logic +} + +/* +============================================================================== + calculate 8254 divisors if they are used for dual timing +*/ +static void pci9118_calc_divisors(char mode, struct comedi_device * dev, + struct comedi_subdevice * s, unsigned int *tim1, unsigned int *tim2, + unsigned int flags, int chans, unsigned int *div1, unsigned int *div2, + char usessh, unsigned int chnsshfront) +{ + DPRINTK("adl_pci9118 EDBG: BGN: pci9118_calc_divisors(%d,%d,.,%u,%u,%u,%d,.,.,,%u,%u)\n", mode, dev->minor, *tim1, *tim2, flags, chans, usessh, chnsshfront); + switch (mode) { + case 1: + case 4: + if (*tim2 < this_board->ai_ns_min) + *tim2 = this_board->ai_ns_min; + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2, + tim2, flags & TRIG_ROUND_NEAREST); + DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u\n", + devpriv->i8254_osc_base, *div1, *div2, *tim1); + break; + case 2: + if (*tim2 < this_board->ai_ns_min) + *tim2 = this_board->ai_ns_min; + DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + *div1 = *tim2 / devpriv->i8254_osc_base; // convert timer (burst) + DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + if (*div1 < this_board->ai_pacer_min) + *div1 = this_board->ai_pacer_min; + DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + *div2 = *tim1 / devpriv->i8254_osc_base; // scan timer + DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + *div2 = *div2 / *div1; // major timer is c1*c2 + DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + if (*div2 < chans) + *div2 = chans; + DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + + *tim2 = *div1 * devpriv->i8254_osc_base; // real convert timer + + if (usessh & (chnsshfront == 0)) // use BSSH signal + if (*div2 < (chans + 2)) + *div2 = chans + 2; + + DPRINTK("7 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2, + *tim1, *tim2); + *tim1 = *div1 * *div2 * devpriv->i8254_osc_base; + DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u timer2=%u\n", + devpriv->i8254_osc_base, *div1, *div2, *tim1, *tim2); + break; + } + DPRINTK("adl_pci9118 EDBG: END: pci9118_calc_divisors(%u,%u)\n", + *div1, *div2); +} + +/* +============================================================================== +*/ +static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2) +{ + outl(0x74, dev->iobase + PCI9118_CNTCTRL); + outl(0xb4, dev->iobase + PCI9118_CNTCTRL); +// outl(0x30, dev->iobase + PCI9118_CNTCTRL); + comedi_udelay(1); + + if ((mode == 1) || (mode == 2) || (mode == 4)) { + outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2); + outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2); + outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1); + outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1); + } +} + +/* +============================================================================== +*/ +static int pci9118_exttrg_add(struct comedi_device * dev, unsigned char source) +{ + if (source > 3) + return -1; // incorrect source + devpriv->exttrg_users |= (1 << source); + devpriv->IntControlReg |= Int_DTrg; + outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); + outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR); // allow INT in AMCC + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_exttrg_del(struct comedi_device * dev, unsigned char source) +{ + if (source > 3) + return -1; // incorrect source + devpriv->exttrg_users &= ~(1 << source); + if (!devpriv->exttrg_users) { // shutdown ext trg intterrupts + devpriv->IntControlReg &= ~Int_DTrg; + if (!devpriv->IntControlReg) // all IRQ disabled + outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) & (~0x00001f00), devpriv->iobase_a + AMCC_OP_REG_INTCSR); // disable int in AMCC + outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); + } + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + if (devpriv->usedma) + outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR); // stop DMA + pci9118_exttrg_del(dev, EXTTRG_AI); + start_pacer(dev, 0, 0, 0); // stop 8254 counters + devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); // positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop + devpriv->AdControlReg = 0x00; + outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); // bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA + outl(0, dev->iobase + PCI9118_BURST); + outl(1, dev->iobase + PCI9118_SCANMOD); + outl(2, dev->iobase + PCI9118_SCANMOD); // reset scan queue + outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO + + devpriv->ai_do = 0; + devpriv->usedma = 0; + + devpriv->ai_act_scan = 0; + devpriv->ai_act_dmapos = 0; + s->async->cur_chan = 0; + s->async->inttrig = NULL; + devpriv->ai_buf_ptr = 0; + devpriv->ai_neverending = 0; + devpriv->dma_actbuf = 0; + + if (!devpriv->IntControlReg) + outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR); // allow INT in AMCC + + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_reset(struct comedi_device * dev) +{ + devpriv->IntControlReg = 0; + devpriv->exttrg_users = 0; + inl(dev->iobase + PCI9118_INTCTRL); + outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); // disable interrupts source + outl(0x30, dev->iobase + PCI9118_CNTCTRL); +// outl(0xb4, dev->iobase + PCI9118_CNTCTRL); + start_pacer(dev, 0, 0, 0); // stop 8254 counters + devpriv->AdControlReg = 0; + outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); // bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA + outl(0, dev->iobase + PCI9118_BURST); + outl(1, dev->iobase + PCI9118_SCANMOD); + outl(2, dev->iobase + PCI9118_SCANMOD); // reset scan queue + devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; + outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); // positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop + + devpriv->ao_data[0] = 2047; + devpriv->ao_data[1] = 2047; + outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1); // reset A/D outs to 0V + outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2); + outl(0, dev->iobase + PCI9118_DO); // reset digi outs to L + comedi_udelay(10); + inl(dev->iobase + PCI9118_AD_DATA); + outl(0, dev->iobase + PCI9118_DELFIFO); // flush FIFO + outl(0, dev->iobase + PCI9118_INTSRC); // remove INT requests + inl(dev->iobase + PCI9118_ADSTAT); // flush A/D status register + inl(dev->iobase + PCI9118_INTSRC); // flush INT requests + devpriv->AdControlReg = 0; + outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); // bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA + + devpriv->cnt0_users = 0; + devpriv->exttrg_users = 0; + + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret, pages, i; + unsigned short master; + unsigned int irq; + unsigned long iobase_a, iobase_9; + struct pci_dev *pcidev; + int opt_bus, opt_slot; + const char *errstr; + unsigned char pci_bus, pci_slot, pci_func; + u16 u16w; + + rt_printk("comedi%d: adl_pci9118: board=%s", dev->minor, + this_board->name); + + opt_bus = it->options[0]; + opt_slot = it->options[1]; + if (it->options[3] & 1) { + master = 0; // user don't want use bus master + } else { + master = 1; + } + + if ((ret = alloc_private(dev, sizeof(struct pci9118_private))) < 0) { + rt_printk(" - Allocation failed!\n"); + return -ENOMEM; + } + + /* Look for matching PCI device */ + errstr = "not found!"; + pcidev = NULL; + while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_AMCC, + this_board->device_id, pcidev))) { + /* Found matching vendor/device. */ + if (opt_bus || opt_slot) { + /* Check bus/slot. */ + if (opt_bus != pcidev->bus->number + || opt_slot != PCI_SLOT(pcidev->devfn)) + continue; /* no match */ + } + /* + * Look for device that isn't in use. + * Enable PCI device and request regions. + */ + if (comedi_pci_enable(pcidev, "adl_pci9118")) { + errstr = "failed to enable PCI device and request regions!"; + continue; + } + break; + } + + if (!pcidev) { + if (opt_bus || opt_slot) { + rt_printk(" - Card at b:s %d:%d %s\n", + opt_bus, opt_slot, errstr); + } else { + rt_printk(" - Card %s\n", errstr); + } + return -EIO; + } + + if (master) { + pci_set_master(pcidev); + } + + pci_bus = pcidev->bus->number; + pci_slot = PCI_SLOT(pcidev->devfn); + pci_func = PCI_FUNC(pcidev->devfn); + irq = pcidev->irq; + iobase_a = pci_resource_start(pcidev, 0); + iobase_9 = pci_resource_start(pcidev, 2); + + rt_printk(", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx", pci_bus, pci_slot, + pci_func, iobase_9, iobase_a); + + dev->iobase = iobase_9; + dev->board_name = this_board->name; + + devpriv->pcidev = pcidev; + devpriv->iobase_a = iobase_a; + + pci9118_reset(dev); + + if (it->options[3] & 2) + irq = 0; // user don't want use IRQ + if (irq > 0) { + if (comedi_request_irq(irq, interrupt_pci9118, IRQF_SHARED, + "ADLink PCI-9118", dev)) { + rt_printk(", unable to allocate IRQ %d, DISABLING IT", + irq); + irq = 0; /* Can't use IRQ */ + } else { + rt_printk(", irq=%u", irq); + } + } else { + rt_printk(", IRQ disabled"); + } + + dev->irq = irq; + + if (master) { // alloc DMA buffers + devpriv->dma_doublebuf = 0; + for (i = 0; i < 2; i++) { + for (pages = 4; pages >= 0; pages--) + if ((devpriv->dmabuf_virt[i] = (short *) + __get_free_pages(GFP_KERNEL, + pages))) + break; + if (devpriv->dmabuf_virt[i]) { + devpriv->dmabuf_pages[i] = pages; + devpriv->dmabuf_size[i] = PAGE_SIZE * pages; + devpriv->dmabuf_samples[i] = + devpriv->dmabuf_size[i] >> 1; + devpriv->dmabuf_hw[i] = + virt_to_bus((void *)devpriv-> + dmabuf_virt[i]); + } + } + if (!devpriv->dmabuf_virt[0]) { + rt_printk(", Can't allocate DMA buffer, DMA disabled!"); + master = 0; + } + + if (devpriv->dmabuf_virt[1]) + devpriv->dma_doublebuf = 1; + + } + + if ((devpriv->master = master)) { + rt_printk(", bus master"); + } else { + rt_printk(", no bus master"); + } + + devpriv->usemux = 0; + if (it->options[2] > 0) { + devpriv->usemux = it->options[2]; + if (devpriv->usemux > 256) + devpriv->usemux = 256; // max 256 channels! + if (it->options[4] > 0) + if (devpriv->usemux > 128) { + devpriv->usemux = 128; // max 128 channels with softare S&H! + } + rt_printk(", ext. mux %d channels", devpriv->usemux); + } + + devpriv->softsshdelay = it->options[4]; + if (devpriv->softsshdelay < 0) { // select sample&hold signal polarity + devpriv->softsshdelay = -devpriv->softsshdelay; + devpriv->softsshsample = 0x80; + devpriv->softsshhold = 0x00; + } else { + devpriv->softsshsample = 0x00; + devpriv->softsshhold = 0x80; + } + + rt_printk(".\n"); + + pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w); + pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64); // Enable parity check for parity error + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + + s = dev->subdevices + 0; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; + if (devpriv->usemux) { + s->n_chan = devpriv->usemux; + } else { + s->n_chan = this_board->n_aichan; + } + s->maxdata = this_board->ai_maxdata; + s->len_chanlist = this_board->n_aichanlist; + s->range_table = this_board->rangelist_ai; + s->cancel = pci9118_ai_cancel; + s->insn_read = pci9118_insn_read_ai; + if (dev->irq) { + s->subdev_flags |= SDF_CMD_READ; + s->do_cmdtest = pci9118_ai_cmdtest; + s->do_cmd = pci9118_ai_cmd; + s->munge = pci9118_ai_munge; + } + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_aochan; + s->maxdata = this_board->ao_maxdata; + s->len_chanlist = this_board->n_aochan; + s->range_table = this_board->rangelist_ao; + s->insn_write = pci9118_insn_write_ao; + s->insn_read = pci9118_insn_read_ao; + + s = dev->subdevices + 2; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 4; + s->maxdata = 1; + s->len_chanlist = 4; + s->range_table = &range_digital; + s->io_bits = 0; /* all bits input */ + s->insn_bits = pci9118_insn_bits_di; + + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 4; + s->maxdata = 1; + s->len_chanlist = 4; + s->range_table = &range_digital; + s->io_bits = 0xf; /* all bits output */ + s->insn_bits = pci9118_insn_bits_do; + + devpriv->valid = 1; + devpriv->i8254_osc_base = 250; // 250ns=4MHz + devpriv->ai_maskharderr = 0x10a; // default measure crash condition + if (it->options[5]) // disable some requested + devpriv->ai_maskharderr &= ~it->options[5]; + + switch (this_board->ai_maxdata) { + case 0xffff: + devpriv->ai16bits = 1; + break; + default: + devpriv->ai16bits = 0; + break; + } + return 0; +} + +/* +============================================================================== +*/ +static int pci9118_detach(struct comedi_device * dev) +{ + if (dev->private) { + if (devpriv->valid) + pci9118_reset(dev); + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (devpriv->pcidev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pcidev); + } + pci_dev_put(devpriv->pcidev); + } + if (devpriv->dmabuf_virt[0]) + free_pages((unsigned long)devpriv->dmabuf_virt[0], + devpriv->dmabuf_pages[0]); + if (devpriv->dmabuf_virt[1]) + free_pages((unsigned long)devpriv->dmabuf_virt[1], + devpriv->dmabuf_pages[1]); + } + + return 0; +} + +/* +============================================================================== +*/ diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c new file mode 100644 index 000000000000..92f62854d6dc --- /dev/null +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -0,0 +1,394 @@ +/* + comedi/drivers/adq12b.c + driver for MicroAxial ADQ12-B data acquisition and control card + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: adq12b +Description: driver for MicroAxial ADQ12-B data acquisition and control card +Devices: [MicroAxial] ADQ12-B (adq12b) +Author: jeremy theler +Updated: Thu, 21 Feb 2008 02:56:27 -0300 +Status: works + +Driver for the acquisition card ADQ12-B (without any add-on). + + - Analog input is subdevice 0 (16 channels single-ended or 8 differential) + - Digital input is subdevice 1 (5 channels) + - Digital output is subdevice 1 (8 channels) + - The PACER is not supported in this version + +If you do not specify any options, they will default to + + # comedi_config /dev/comedi0 adq12b 0x300,0,0 + + option 1: I/O base address. The following table is provided as a help + of the hardware jumpers. + + address jumper JADR + 0x300 1 (factory default) + 0x320 2 + 0x340 3 + 0x360 4 + 0x380 5 + 0x3A0 6 + + option 2: unipolar/bipolar ADC selection: 0 -> bipolar, 1 -> unipolar + + selection comedi_config option JUB + bipolar 0 2-3 (factory default) + unipolar 1 1-2 + + option 3: single-ended/differential AI selection: 0 -> SE, 1 -> differential + + selection comedi_config option JCHA JCHB + single-ended 0 1-2 1-2 (factory default) + differential 1 2-3 2-3 + + + written by jeremy theler + + instituto balseiro + comision nacional de energia atomica + universidad nacional de cuyo + argentina + + 21-feb-2008 + + changed supported devices string (missused the [] and ()) + + 13-oct-2007 + + first try + + +*/ + +#include "../comedidev.h" + +// address scheme (page 2.17 of the manual) +#define ADQ12B_SIZE 16 + +#define ADQ12B_CTREG 0x00 +#define ADQ12B_STINR 0x00 +#define ADQ12B_OUTBR 0x04 +#define ADQ12B_ADLOW 0x08 +#define ADQ12B_ADHIG 0x09 +#define ADQ12B_CONT0 0x0c +#define ADQ12B_CONT1 0x0d +#define ADQ12B_CONT2 0x0e +#define ADQ12B_COWORD 0x0f + +// mask of the bit at STINR to check end of conversion +#define ADQ12B_EOC 0x20 + +#define TIMEOUT 20 + +// available ranges through the PGA gains +static const struct comedi_lrange range_adq12b_ai_bipolar = { 4, { + BIP_RANGE( 5 ), + BIP_RANGE( 2 ), + BIP_RANGE( 1 ), + BIP_RANGE( 0.5 ) +}}; + +static const struct comedi_lrange range_adq12b_ai_unipolar = { 4, { + UNI_RANGE( 5 ), + UNI_RANGE( 2 ), + UNI_RANGE( 1 ), + UNI_RANGE( 0.5 ) +}}; + + + +struct adq12b_board { + const char *name; + int ai_se_chans; + int ai_diff_chans; + int ai_bits; + int di_chans; + int do_chans; +}; + +static const struct adq12b_board adq12b_boards[] = { + { + name: "adq12b", + ai_se_chans: 16, + ai_diff_chans: 8, + ai_bits: 12, + di_chans: 5, + do_chans: 8 + } +// potentially, more adq-based deviced will be added +/*, + name: "adq12b", + ai_chans: 16, // this is just for reference, hardcoded again later + ai_bits: 12, + di_chans: 8, + do_chans: 5 + }*/ +}; + +#define thisboard ((const struct adq12b_board *)dev->board_ptr) + +struct adq12b_private { + int unipolar; /* option 2 of comedi_config (1 is iobase) */ + int differential; /* option 3 of comedi_config */ + int last_channel; + int last_range; + unsigned int digital_state; +}; + +#define devpriv ((struct adq12b_private *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int adq12b_attach(struct comedi_device *dev,struct comedi_devconfig *it); +static int adq12b_detach(struct comedi_device *dev); +static struct comedi_driver driver_adq12b={ + driver_name: "adq12b", + module: THIS_MODULE, + attach: adq12b_attach, + detach: adq12b_detach, + board_name: &adq12b_boards[0].name, + offset: sizeof(struct adq12b_board), + num_names: sizeof(adq12b_boards) / sizeof(struct adq12b_board), +}; + +static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); +static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data); +static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data); + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int adq12b_attach(struct comedi_device *dev,struct comedi_devconfig *it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + int unipolar, differential; + + iobase = it->options[0]; + unipolar = it->options[1]; + differential = it->options[2]; + + printk("comedi%d: adq12b called with options base=0x%03lx, %s and %s\n",dev->minor, iobase, (unipolar==1)?"unipolar":"bipolar", (differential==1)?"differential":"single-ended"); + + /* if no address was specified, try the default 0x300 */ + if (iobase == 0) { + printk("comedi%d: adq12b warning: I/O base address not specified. Trying the default 0x300.\n", dev->minor); + iobase = 0x300; + } + + printk("comedi%d: adq12b: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, ADQ12B_SIZE, "adq12b")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if(alloc_private(dev, sizeof(struct adq12b_private)) < 0) + return -ENOMEM; + +/* fill in devpriv structure */ + devpriv->unipolar = unipolar; + devpriv->differential = differential; + devpriv->digital_state = 0; +/* initialize channel and range to -1 so we make sure we always write + at least once to the CTREG in the instruction */ + devpriv->last_channel = -1; + devpriv->last_range = -1; + + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if(alloc_subdevices(dev, 3)<0) + return -ENOMEM; + + s = dev->subdevices+0; + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + if (differential) { + s->subdev_flags = SDF_READABLE|SDF_GROUND|SDF_DIFF; + s->n_chan = thisboard->ai_diff_chans; + } else { + s->subdev_flags = SDF_READABLE|SDF_GROUND; + s->n_chan = thisboard->ai_se_chans; + } + + if (unipolar) { + s->range_table = &range_adq12b_ai_unipolar; + } else { + s->range_table = &range_adq12b_ai_bipolar; + } + + s->maxdata = (1 << thisboard->ai_bits)-1; + + + s->len_chanlist = 4; /* This is the maximum chanlist length that + the board can handle */ + s->insn_read = adq12b_ai_rinsn; + + + s = dev->subdevices+1; + /* digital input subdevice */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan=thisboard->di_chans; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = adq12b_di_insn_bits; + + s = dev->subdevices+2; + /* digital output subdevice */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->do_chans; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = adq12b_do_insn_bits; + + + printk("attached\n"); + + return 0; +} + + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int adq12b_detach(struct comedi_device *dev) +{ + if (dev->iobase) + release_region(dev->iobase, ADQ12B_SIZE); + + kfree(devpriv); + + printk("comedi%d: adq12b: removed\n",dev->minor); + + return 0; +} + +/* + * "instructions" read/write data in "one-shot" or "software-triggered" + * mode. + */ + +static int adq12b_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) +{ + int n, i; + int range, channel; + unsigned char hi, lo, status; + + /* change channel and range only if it is different from the previous */ + range = CR_RANGE(insn->chanspec); + channel = CR_CHAN(insn->chanspec); + if (channel != devpriv->last_channel || range != devpriv->last_range) { + outb((range << 4) | channel, dev->iobase + ADQ12B_CTREG); + comedi_udelay(50); /* wait for the mux to settle */ + } + + /* trigger conversion */ + status = inb(dev->iobase + ADQ12B_ADLOW); + + /* convert n samples */ + for(n=0; n < insn->n; n++){ + + /* wait for end of convertion */ + i = 0; + do { +// comedi_udelay(1); + status = inb(dev->iobase + ADQ12B_STINR); + status = status & ADQ12B_EOC; + } while (status == 0 && ++i < TIMEOUT); +// } while (++i < 10); + + /* read data */ + hi = inb(dev->iobase + ADQ12B_ADHIG); + lo = inb(dev->iobase + ADQ12B_ADLOW); + + //rt_printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n", channel, range, status, hi, lo); + data[n] = (hi << 8) | lo; + + } + + /* return the number of samples read/written */ + return n; +} + + +static int adq12b_di_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) +{ + + /* only bits 0-4 have information about digital inputs */ + data[1] = (inb(dev->iobase+ADQ12B_STINR) & (0x1f)); + + return 2; +} + + +static int adq12b_do_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_insn *insn,unsigned int *data) +{ + int channel; + + for (channel = 0; channel < 8; channel++) + if (((data[0]>>channel) & 0x01) != 0) + outb((((data[1]>>channel)&0x01)<<3) | channel, dev->iobase + ADQ12B_OUTBR); + + /* store information to retrieve when asked for reading */ + if (data[0]) { + devpriv->digital_state &= ~data[0]; + devpriv->digital_state |= (data[0]&data[1]); + } + + data[1] = devpriv->digital_state; + + return 2; +} + + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver_adq12b); diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c new file mode 100644 index 000000000000..29eac743c8e0 --- /dev/null +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -0,0 +1,1568 @@ +/* + * comedi/drivers/adv_pci1710.c + * + * Author: Michal Dobes + * + * Thanks to ZhenGang Shang + * for testing and informations. + * + * hardware driver for Advantech cards: + * card: PCI-1710, PCI-1710HG, PCI-1711, PCI-1713, PCI-1720, PCI-1731 + * driver: pci1710, pci1710hg, pci1711, pci1713, pci1720, pci1731 + * + * Options: + * [0] - PCI bus number - if bus number and slot number are 0, + * then driver search for first unused card + * [1] - PCI slot number + * +*/ +/* +Driver: adv_pci1710 +Description: Advantech PCI-1710, PCI-1710HG, PCI-1711, PCI-1713, + Advantech PCI-1720, PCI-1731 +Author: Michal Dobes +Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG (pci1710hg), + PCI-1711 (adv_pci1710), PCI-1713, PCI-1720, + PCI-1731 +Status: works + +This driver supports AI, AO, DI and DO subdevices. +AI subdevice supports cmd and insn interface, +other subdevices support only insn interface. + +The PCI-1710 and PCI-1710HG have the same PCI device ID, so the +driver cannot distinguish between them, as would be normal for a +PCI driver. + +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first available PCI + device will be used. +*/ + +#include "../comedidev.h" + +#include "comedi_pci.h" + +#include "8253.h" +#include "amcc_s5933.h" + +#define PCI171x_PARANOIDCHECK /* if defined, then is used code which control correct channel number on every 12 bit sample */ + +#undef PCI171X_EXTDEBUG + +#define DRV_NAME "adv_pci1710" + +#undef DPRINTK +#ifdef PCI171X_EXTDEBUG +#define DPRINTK(fmt, args...) rt_printk(fmt, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +// hardware types of the cards +#define TYPE_PCI171X 0 +#define TYPE_PCI1713 2 +#define TYPE_PCI1720 3 + +#define IORANGE_171x 32 +#define IORANGE_1720 16 + +#define PCI171x_AD_DATA 0 /* R: A/D data */ +#define PCI171x_SOFTTRG 0 /* W: soft trigger for A/D */ +#define PCI171x_RANGE 2 /* W: A/D gain/range register */ +#define PCI171x_MUX 4 /* W: A/D multiplexor control */ +#define PCI171x_STATUS 6 /* R: status register */ +#define PCI171x_CONTROL 6 /* W: control register */ +#define PCI171x_CLRINT 8 /* W: clear interrupts request */ +#define PCI171x_CLRFIFO 9 /* W: clear FIFO */ +#define PCI171x_DA1 10 /* W: D/A register */ +#define PCI171x_DA2 12 /* W: D/A register */ +#define PCI171x_DAREF 14 /* W: D/A reference control */ +#define PCI171x_DI 16 /* R: digi inputs */ +#define PCI171x_DO 16 /* R: digi inputs */ +#define PCI171x_CNT0 24 /* R/W: 8254 couter 0 */ +#define PCI171x_CNT1 26 /* R/W: 8254 couter 1 */ +#define PCI171x_CNT2 28 /* R/W: 8254 couter 2 */ +#define PCI171x_CNTCTRL 30 /* W: 8254 counter control */ + +// upper bits from status register (PCI171x_STATUS) (lower is same woth control reg) +#define Status_FE 0x0100 /* 1=FIFO is empty */ +#define Status_FH 0x0200 /* 1=FIFO is half full */ +#define Status_FF 0x0400 /* 1=FIFO is full, fatal error */ +#define Status_IRQ 0x0800 /* 1=IRQ occured */ +// bits from control register (PCI171x_CONTROL) +#define Control_CNT0 0x0040 /* 1=CNT0 have external source, 0=have internal 100kHz source */ +#define Control_ONEFH 0x0020 /* 1=IRQ on FIFO is half full, 0=every sample */ +#define Control_IRQEN 0x0010 /* 1=enable IRQ */ +#define Control_GATE 0x0008 /* 1=enable external trigger GATE (8254?) */ +#define Control_EXT 0x0004 /* 1=external trigger source */ +#define Control_PACER 0x0002 /* 1=enable internal 8254 trigger source */ +#define Control_SW 0x0001 /* 1=enable software trigger source */ +// bits from counter control register (PCI171x_CNTCTRL) +#define Counter_BCD 0x0001 /* 0 = binary counter, 1 = BCD counter */ +#define Counter_M0 0x0002 /* M0-M2 select modes 0-5 */ +#define Counter_M1 0x0004 /* 000 = mode 0, 010 = mode 2 ... */ +#define Counter_M2 0x0008 +#define Counter_RW0 0x0010 /* RW0/RW1 select read/write mode */ +#define Counter_RW1 0x0020 +#define Counter_SC0 0x0040 /* Select Counter. Only 00 or 11 may */ +#define Counter_SC1 0x0080 /* be used, 00 for CNT0, 11 for read-back command */ + +#define PCI1720_DA0 0 /* W: D/A register 0 */ +#define PCI1720_DA1 2 /* W: D/A register 1 */ +#define PCI1720_DA2 4 /* W: D/A register 2 */ +#define PCI1720_DA3 6 /* W: D/A register 3 */ +#define PCI1720_RANGE 8 /* R/W: D/A range register */ +#define PCI1720_SYNCOUT 9 /* W: D/A synchronized output register */ +#define PCI1720_SYNCONT 15 /* R/W: D/A synchronized control */ + +// D/A synchronized control (PCI1720_SYNCONT) +#define Syncont_SC0 1 /* set synchronous output mode */ + +static const struct comedi_lrange range_pci1710_3 = { 9, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + BIP_RANGE(10), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; + +static const char range_codes_pci1710_3[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x10, 0x11, 0x12, 0x13 }; + +static const struct comedi_lrange range_pci1710hg = { 12, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.005), + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.01), + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01) + } +}; + +static const char range_codes_pci1710hg[] = + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, + 0x13 }; + +static const struct comedi_lrange range_pci17x1 = { 5, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625) + } +}; + +static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; + +static const struct comedi_lrange range_pci1720 = { 4, { + UNI_RANGE(5), + UNI_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(10) + } +}; + +static const struct comedi_lrange range_pci171x_da = { 2, { + UNI_RANGE(5), + UNI_RANGE(10), + } +}; + +static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pci1710_detach(struct comedi_device * dev); + +struct boardtype { + const char *name; // board name + int device_id; + int iorange; // I/O range len + char have_irq; // 1=card support IRQ + char cardtype; // 0=1710& co. 2=1713, ... + int n_aichan; // num of A/D chans + int n_aichand; // num of A/D chans in diff mode + int n_aochan; // num of D/A chans + int n_dichan; // num of DI chans + int n_dochan; // num of DO chans + int n_counter; // num of counters + int ai_maxdata; // resolution of A/D + int ao_maxdata; // resolution of D/A + const struct comedi_lrange *rangelist_ai; // rangelist for A/D + const char *rangecode_ai; // range codes for programming + const struct comedi_lrange *rangelist_ao; // rangelist for D/A + unsigned int ai_ns_min; // max sample speed of card v ns + unsigned int fifo_half_size; // size of FIFO/2 +}; + +static DEFINE_PCI_DEVICE_TABLE(pci1710_pci_table) = { + {PCI_VENDOR_ID_ADVANTECH, 0x1710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1713, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1731, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pci1710_pci_table); + +static const struct boardtype boardtypes[] = { + {"pci1710", 0x1710, + IORANGE_171x, 1, TYPE_PCI171X, + 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff, + &range_pci1710_3, range_codes_pci1710_3, + &range_pci171x_da, + 10000, 2048}, + {"pci1710hg", 0x1710, + IORANGE_171x, 1, TYPE_PCI171X, + 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff, + &range_pci1710hg, range_codes_pci1710hg, + &range_pci171x_da, + 10000, 2048}, + {"pci1711", 0x1711, + IORANGE_171x, 1, TYPE_PCI171X, + 16, 0, 2, 16, 16, 1, 0x0fff, 0x0fff, + &range_pci17x1, range_codes_pci17x1, &range_pci171x_da, + 10000, 512}, + {"pci1713", 0x1713, + IORANGE_171x, 1, TYPE_PCI1713, + 32, 16, 0, 0, 0, 0, 0x0fff, 0x0000, + &range_pci1710_3, range_codes_pci1710_3, NULL, + 10000, 2048}, + {"pci1720", 0x1720, + IORANGE_1720, 0, TYPE_PCI1720, + 0, 0, 4, 0, 0, 0, 0x0000, 0x0fff, + NULL, NULL, &range_pci1720, + 0, 0}, + {"pci1731", 0x1731, + IORANGE_171x, 1, TYPE_PCI171X, + 16, 0, 0, 16, 16, 0, 0x0fff, 0x0000, + &range_pci17x1, range_codes_pci17x1, NULL, + 10000, 512}, + // dummy entry corresponding to driver name + {.name = DRV_NAME}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype)) + +static struct comedi_driver driver_pci1710 = { + .driver_name = DRV_NAME, + .module = THIS_MODULE, + .attach = pci1710_attach, + .detach = pci1710_detach, + .num_names = n_boardtypes, + .board_name = &boardtypes[0].name, + .offset = sizeof(struct boardtype), +}; + +struct pci1710_private { + struct pci_dev *pcidev; // ptr to PCI device + char valid; // card is usable + char neverending_ai; // we do unlimited AI + unsigned int CntrlReg; // Control register + unsigned int i8254_osc_base; // frequence of onboard oscilator + unsigned int ai_do; // what do AI? 0=nothing, 1 to 4 mode + unsigned int ai_act_scan; // how many scans we finished + unsigned int ai_act_chan; // actual position in actual scan + unsigned int ai_buf_ptr; // data buffer ptr in samples + unsigned char ai_eos; // 1=EOS wake up + unsigned char ai_et; + unsigned int ai_et_CntrlReg; + unsigned int ai_et_MuxVal; + unsigned int ai_et_div1, ai_et_div2; + unsigned int act_chanlist[32]; // list of scaned channel + unsigned char act_chanlist_len; // len of scanlist + unsigned char act_chanlist_pos; // actual position in MUX list + unsigned char da_ranges; // copy of D/A outpit range register + unsigned int ai_scans; // len of scanlist + unsigned int ai_n_chan; // how many channels is measured + unsigned int *ai_chanlist; // actaul chanlist + unsigned int ai_flags; // flaglist + unsigned int ai_data_len; // len of data buffer + short *ai_data; // data buffer + unsigned int ai_timer1; // timers + unsigned int ai_timer2; + short ao_data[4]; // data output buffer + unsigned int cnt0_write_wait; // after a write, wait for update of the internal state +}; + +#define devpriv ((struct pci1710_private *)dev->private) +#define this_board ((const struct boardtype *)dev->board_ptr) + +/* +============================================================================== +*/ + +static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int *chanlist, unsigned int n_chan); +static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int *chanlist, unsigned int n_chan, unsigned int seglen); +static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2); +static int pci1710_reset(struct comedi_device * dev); +static int pci171x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); + +static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, // used for gain list programming + 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, + 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717, + 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f +}; + +/* +============================================================================== +*/ +static int pci171x_insn_read_ai(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, timeout; +#ifdef PCI171x_PARANOIDCHECK + unsigned int idata; +#endif + + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_insn_read_ai(...)\n"); + devpriv->CntrlReg &= Control_CNT0; + devpriv->CntrlReg |= Control_SW; // set software trigger + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); + + setup_channel_list(dev, s, &insn->chanspec, 1, 1); + + DPRINTK("adv_pci1710 A ST=%4x IO=%x\n", + inw(dev->iobase + PCI171x_STATUS), + dev->iobase + PCI171x_STATUS); + for (n = 0; n < insn->n; n++) { + outw(0, dev->iobase + PCI171x_SOFTTRG); /* start conversion */ + DPRINTK("adv_pci1710 B n=%d ST=%4x\n", n, + inw(dev->iobase + PCI171x_STATUS)); + //comedi_udelay(1); + DPRINTK("adv_pci1710 C n=%d ST=%4x\n", n, + inw(dev->iobase + PCI171x_STATUS)); + timeout = 100; + while (timeout--) { + if (!(inw(dev->iobase + PCI171x_STATUS) & Status_FE)) + goto conv_finish; + if (!(timeout % 10)) + DPRINTK("adv_pci1710 D n=%d tm=%d ST=%4x\n", n, + timeout, + inw(dev->iobase + PCI171x_STATUS)); + } + comedi_error(dev, "A/D insn timeout"); + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); + data[n] = 0; + DPRINTK("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", n); + return -ETIME; + + conv_finish: +#ifdef PCI171x_PARANOIDCHECK + idata = inw(dev->iobase + PCI171x_AD_DATA); + if (this_board->cardtype != TYPE_PCI1713) + if ((idata & 0xf000) != devpriv->act_chanlist[0]) { + comedi_error(dev, "A/D insn data droput!"); + return -ETIME; + } + data[n] = idata & 0x0fff; +#else + data[n] = inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff; +#endif + + } + + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); + + DPRINTK("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", n); + return n; +} + +/* +============================================================================== +*/ +static int pci171x_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, chan, range, ofs; + + chan = CR_CHAN(insn->chanspec); + range = CR_RANGE(insn->chanspec); + if (chan) { + devpriv->da_ranges &= 0xfb; + devpriv->da_ranges |= (range << 2); + outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); + ofs = PCI171x_DA2; + } else { + devpriv->da_ranges &= 0xfe; + devpriv->da_ranges |= range; + outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); + ofs = PCI171x_DA1; + } + + for (n = 0; n < insn->n; n++) + outw(data[n], dev->iobase + ofs); + + devpriv->ao_data[chan] = data[n]; + + return n; + +} + +/* +============================================================================== +*/ +static int pci171x_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, chan; + + chan = CR_CHAN(insn->chanspec); + for (n = 0; n < insn->n; n++) + data[n] = devpriv->ao_data[chan]; + + return n; +} + +/* +============================================================================== +*/ +static int pci171x_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[1] = inw(dev->iobase + PCI171x_DI); + + return 2; +} + +/* +============================================================================== +*/ +static int pci171x_insn_bits_do(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]); + outw(s->state, dev->iobase + PCI171x_DO); + } + data[1] = s->state; + + return 2; +} + +/* +============================================================================== +*/ +static int pci171x_insn_counter_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int msb, lsb, ccntrl; + int i; + + ccntrl = 0xD2; /* count only */ + for (i = 0; i < insn->n; i++) { + outw(ccntrl, dev->iobase + PCI171x_CNTCTRL); + + lsb = inw(dev->iobase + PCI171x_CNT0) & 0xFF; + msb = inw(dev->iobase + PCI171x_CNT0) & 0xFF; + + data[0] = lsb | (msb << 8); + } + + return insn->n; +} + +/* +============================================================================== +*/ +static int pci171x_insn_counter_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + uint msb, lsb, ccntrl, status; + + lsb = data[0] & 0x00FF; + msb = (data[0] & 0xFF00) >> 8; + + /* write lsb, then msb */ + outw(lsb, dev->iobase + PCI171x_CNT0); + outw(msb, dev->iobase + PCI171x_CNT0); + + if (devpriv->cnt0_write_wait) { + /* wait for the new count to be loaded */ + ccntrl = 0xE2; + do { + outw(ccntrl, dev->iobase + PCI171x_CNTCTRL); + status = inw(dev->iobase + PCI171x_CNT0) & 0xFF; + } while (status & 0x40); + } + + return insn->n; +} + +/* +============================================================================== +*/ +static int pci171x_insn_counter_config(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ +#ifdef unused + /* This doesn't work like a normal Comedi counter config */ + uint ccntrl = 0; + + devpriv->cnt0_write_wait = data[0] & 0x20; + + /* internal or external clock? */ + if (!(data[0] & 0x10)) { /* internal */ + devpriv->CntrlReg &= ~Control_CNT0; + } else { + devpriv->CntrlReg |= Control_CNT0; + } + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + + if (data[0] & 0x01) + ccntrl |= Counter_M0; + if (data[0] & 0x02) + ccntrl |= Counter_M1; + if (data[0] & 0x04) + ccntrl |= Counter_M2; + if (data[0] & 0x08) + ccntrl |= Counter_BCD; + ccntrl |= Counter_RW0; /* set read/write mode */ + ccntrl |= Counter_RW1; + outw(ccntrl, dev->iobase + PCI171x_CNTCTRL); +#endif + + return 1; +} + +/* +============================================================================== +*/ +static int pci1720_insn_write_ao(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, rangereg, chan; + + chan = CR_CHAN(insn->chanspec); + rangereg = devpriv->da_ranges & (~(0x03 << (chan << 1))); + rangereg |= (CR_RANGE(insn->chanspec) << (chan << 1)); + if (rangereg != devpriv->da_ranges) { + outb(rangereg, dev->iobase + PCI1720_RANGE); + devpriv->da_ranges = rangereg; + } + + for (n = 0; n < insn->n; n++) { + outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1)); + outb(0, dev->iobase + PCI1720_SYNCOUT); // update outputs + } + + devpriv->ao_data[chan] = data[n]; + + return n; +} + +/* +============================================================================== +*/ +static void interrupt_pci1710_every_sample(void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + int m; +#ifdef PCI171x_PARANOIDCHECK + short sampl; +#endif + + DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_every_sample(...)\n"); + m = inw(dev->iobase + PCI171x_STATUS); + if (m & Status_FE) { + rt_printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m); + pci171x_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return; + } + if (m & Status_FF) { + rt_printk + ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n", + dev->minor, m); + pci171x_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return; + } + + outb(0, dev->iobase + PCI171x_CLRINT); // clear our INT request + + DPRINTK("FOR "); + for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) { +#ifdef PCI171x_PARANOIDCHECK + sampl = inw(dev->iobase + PCI171x_AD_DATA); + DPRINTK("%04x:", sampl); + if (this_board->cardtype != TYPE_PCI1713) + if ((sampl & 0xf000) != + devpriv->act_chanlist[s->async->cur_chan]) { + rt_printk + ("comedi: A/D data dropout: received data from channel %d, expected %d!\n", + (sampl & 0xf000) >> 12, + (devpriv->act_chanlist[s->async-> + cur_chan] & 0xf000) >> + 12); + pci171x_ai_cancel(dev, s); + s->async->events |= + COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return; + } + DPRINTK("%8d %2d %8d~", s->async->buf_int_ptr, + s->async->cur_chan, s->async->buf_int_count); + comedi_buf_put(s->async, sampl & 0x0fff); +#else + comedi_buf_put(s->async, + inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff); +#endif + ++s->async->cur_chan; + + if (s->async->cur_chan >= devpriv->ai_n_chan) { + s->async->cur_chan = 0; + } + + if (s->async->cur_chan == 0) { // one scan done + devpriv->ai_act_scan++; + DPRINTK("adv_pci1710 EDBG: EOS1 bic %d bip %d buc %d bup %d\n", s->async->buf_int_count, s->async->buf_int_ptr, s->async->buf_user_count, s->async->buf_user_ptr); + DPRINTK("adv_pci1710 EDBG: EOS2\n"); + if ((!devpriv->neverending_ai) && (devpriv->ai_act_scan >= devpriv->ai_scans)) { // all data sampled + pci171x_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + return; + } + } + } + + outb(0, dev->iobase + PCI171x_CLRINT); // clear our INT request + DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_every_sample(...)\n"); + + comedi_event(dev, s); +} + +/* +============================================================================== +*/ +static int move_block_from_fifo(struct comedi_device * dev, struct comedi_subdevice * s, + int n, int turn) +{ + int i, j; +#ifdef PCI171x_PARANOIDCHECK + int sampl; +#endif + DPRINTK("adv_pci1710 EDBG: BGN: move_block_from_fifo(...,%d,%d)\n", n, + turn); + j = s->async->cur_chan; + for (i = 0; i < n; i++) { +#ifdef PCI171x_PARANOIDCHECK + sampl = inw(dev->iobase + PCI171x_AD_DATA); + if (this_board->cardtype != TYPE_PCI1713) + if ((sampl & 0xf000) != devpriv->act_chanlist[j]) { + rt_printk + ("comedi%d: A/D FIFO data dropout: received data from channel %d, expected %d! (%d/%d/%d/%d/%d/%4x)\n", + dev->minor, (sampl & 0xf000) >> 12, + (devpriv-> + act_chanlist[j] & 0xf000) >> 12, + i, j, devpriv->ai_act_scan, n, turn, + sampl); + pci171x_ai_cancel(dev, s); + s->async->events |= + COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return 1; + } + comedi_buf_put(s->async, sampl & 0x0fff); +#else + comedi_buf_put(s->async, + inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff); +#endif + j++; + if (j >= devpriv->ai_n_chan) { + j = 0; + devpriv->ai_act_scan++; + } + } + DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n"); + return 0; +} + +/* +============================================================================== +*/ +static void interrupt_pci1710_half_fifo(void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + int m, samplesinbuf; + + DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_half_fifo(...)\n"); + m = inw(dev->iobase + PCI171x_STATUS); + if (!(m & Status_FH)) { + rt_printk("comedi%d: A/D FIFO not half full! (%4x)\n", + dev->minor, m); + pci171x_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return; + } + if (m & Status_FF) { + rt_printk + ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n", + dev->minor, m); + pci171x_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return; + } + + samplesinbuf = this_board->fifo_half_size; + if (samplesinbuf * sizeof(short) >= devpriv->ai_data_len) { + m = devpriv->ai_data_len / sizeof(short); + if (move_block_from_fifo(dev, s, m, 0)) + return; + samplesinbuf -= m; + } + + if (samplesinbuf) { + if (move_block_from_fifo(dev, s, samplesinbuf, 1)) + return; + } + + if (!devpriv->neverending_ai) + if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + pci171x_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + return; + } + outb(0, dev->iobase + PCI171x_CLRINT); // clear our INT request + DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_half_fifo(...)\n"); + + comedi_event(dev, s); +} + +/* +============================================================================== +*/ +static irqreturn_t interrupt_service_pci1710(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + + DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n", + irq); + if (!dev->attached) // is device attached? + return IRQ_NONE; // no, exit + + if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ)) // is this interrupt from our board? + return IRQ_NONE; // no, exit + + DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n", + inw(dev->iobase + PCI171x_STATUS)); + + if (devpriv->ai_et) { // Switch from initial TRIG_EXT to TRIG_xxx. + devpriv->ai_et = 0; + devpriv->CntrlReg &= Control_CNT0; + devpriv->CntrlReg |= Control_SW; // set software trigger + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + devpriv->CntrlReg = devpriv->ai_et_CntrlReg; + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); + outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + // start pacer + start_pacer(dev, 1, devpriv->ai_et_div1, devpriv->ai_et_div2); + return IRQ_HANDLED; + } + if (devpriv->ai_eos) { // We use FIFO half full INT or not? + interrupt_pci1710_every_sample(d); + } else { + interrupt_pci1710_half_fifo(d); + } + DPRINTK("adv_pci1710 EDBG: END: interrupt_service_pci1710(...)\n"); + return IRQ_HANDLED; +} + +/* +============================================================================== +*/ +static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device * dev, + struct comedi_subdevice * s) +{ + unsigned int divisor1, divisor2; + unsigned int seglen; + + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n", + mode); + start_pacer(dev, -1, 0, 0); // stop pacer + + seglen = check_channel_list(dev, s, devpriv->ai_chanlist, + devpriv->ai_n_chan); + if (seglen < 1) + return -EINVAL; + setup_channel_list(dev, s, devpriv->ai_chanlist, + devpriv->ai_n_chan, seglen); + + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); + + devpriv->ai_do = mode; + + devpriv->ai_act_scan = 0; + s->async->cur_chan = 0; + devpriv->ai_buf_ptr = 0; + devpriv->neverending_ai = 0; + + devpriv->CntrlReg &= Control_CNT0; + if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { // don't we want wake up every scan? devpriv->ai_eos=1; + devpriv->ai_eos = 1; + } else { + devpriv->CntrlReg |= Control_ONEFH; + devpriv->ai_eos = 0; + } + + if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1)) { + devpriv->neverending_ai = 1; + } //well, user want neverending + else { + devpriv->neverending_ai = 0; + } + switch (mode) { + case 1: + case 2: + if (devpriv->ai_timer1 < this_board->ai_ns_min) + devpriv->ai_timer1 = this_board->ai_ns_min; + devpriv->CntrlReg |= Control_PACER | Control_IRQEN; + if (mode == 2) { + devpriv->ai_et_CntrlReg = devpriv->CntrlReg; + devpriv->CntrlReg &= + ~(Control_PACER | Control_ONEFH | Control_GATE); + devpriv->CntrlReg |= Control_EXT; + devpriv->ai_et = 1; + } else { + devpriv->ai_et = 0; + } + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, + &divisor2, &devpriv->ai_timer1, + devpriv->ai_flags & TRIG_ROUND_MASK); + DPRINTK("adv_pci1710 EDBG: OSC base=%u div1=%u div2=%u timer=%u\n", devpriv->i8254_osc_base, divisor1, divisor2, devpriv->ai_timer1); + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + if (mode != 2) { + // start pacer + start_pacer(dev, mode, divisor1, divisor2); + } else { + devpriv->ai_et_div1 = divisor1; + devpriv->ai_et_div2 = divisor2; + } + break; + case 3: + devpriv->CntrlReg |= Control_EXT | Control_IRQEN; + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + break; + } + + DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_docmd_and_mode(...)\n"); + return 0; +} + +#ifdef PCI171X_EXTDEBUG +/* +============================================================================== +*/ +static void pci171x_cmdtest_out(int e, struct comedi_cmd * cmd) +{ + rt_printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, + cmd->start_src, cmd->scan_begin_src, cmd->convert_src); + rt_printk("adv_pci1710 e=%d startarg=%d scanarg=%d convarg=%d\n", e, + cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); + rt_printk("adv_pci1710 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src, + cmd->scan_end_src); + rt_printk("adv_pci1710 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", + e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); +} +#endif + +/* +============================================================================== +*/ +static int pci171x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp, divisor1, divisor2; + + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n"); +#ifdef PCI171X_EXTDEBUG + pci171x_cmdtest_out(-1, cmd); +#endif + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) { +#ifdef PCI171X_EXTDEBUG + pci171x_cmdtest_out(1, cmd); +#endif + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n", err); + return 1; + } + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) { + cmd->start_src = TRIG_NOW; + err++; + } + + if (cmd->scan_begin_src != TRIG_FOLLOW) { + cmd->scan_begin_src = TRIG_FOLLOW; + err++; + } + + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; + + if (err) { +#ifdef PCI171X_EXTDEBUG + pci171x_cmdtest_out(2, cmd); +#endif + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n", err); + return 2; + } + + /* step 3: make sure arguments are trivially compatible */ + + 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_src == TRIG_TIMER) { + if (cmd->convert_arg < this_board->ai_ns_min) { + cmd->convert_arg = this_board->ai_ns_min; + err++; + } + } else { /* TRIG_FOLLOW */ + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + } + + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->chanlist_len > this_board->n_aichan) { + cmd->chanlist_len = this_board->n_aichan; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + } else { /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) { +#ifdef PCI171X_EXTDEBUG + pci171x_cmdtest_out(3, cmd); +#endif + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n", err); + return 3; + } + + /* step 4: fix up any arguments */ + + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, + &divisor2, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (cmd->convert_arg < this_board->ai_ns_min) + cmd->convert_arg = this_board->ai_ns_min; + if (tmp != cmd->convert_arg) + err++; + } + + if (err) { + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=4\n", err); + return 4; + } + + /* step 5: complain about special chanlist considerations */ + + if (cmd->chanlist) { + if (!check_channel_list(dev, s, cmd->chanlist, + cmd->chanlist_len)) + return 5; // incorrect channels list + } + + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) ret=0\n"); + return 0; +} + +/* +============================================================================== +*/ +static int pci171x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmd(...)\n"); + devpriv->ai_n_chan = cmd->chanlist_len; + devpriv->ai_chanlist = cmd->chanlist; + devpriv->ai_flags = cmd->flags; + devpriv->ai_data_len = s->async->prealloc_bufsz; + devpriv->ai_data = s->async->prealloc_buf; + devpriv->ai_timer1 = 0; + devpriv->ai_timer2 = 0; + + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ai_scans = cmd->stop_arg; + } else { + devpriv->ai_scans = 0; + } + + if (cmd->scan_begin_src == TRIG_FOLLOW) { // mode 1, 2, 3 + if (cmd->convert_src == TRIG_TIMER) { // mode 1 and 2 + devpriv->ai_timer1 = cmd->convert_arg; + return pci171x_ai_docmd_and_mode(cmd->start_src == + TRIG_EXT ? 2 : 1, dev, s); + } + if (cmd->convert_src == TRIG_EXT) { // mode 3 + return pci171x_ai_docmd_and_mode(3, dev, s); + } + } + + return -1; +} + +/* +============================================================================== + Check if channel list from user is builded correctly + If it's ok, then program scan/gain logic. + This works for all cards. +*/ +static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int *chanlist, unsigned int n_chan) +{ + unsigned int chansegment[32]; + unsigned int i, nowmustbechan, seglen, segpos; + + DPRINTK("adv_pci1710 EDBG: check_channel_list(...,%d)\n", n_chan); + /* correct channel and range number check itself comedi/range.c */ + if (n_chan < 1) { + comedi_error(dev, "range/channel list is empty!"); + return 0; + } + + if (n_chan > 1) { + chansegment[0] = chanlist[0]; // first channel is everytime ok + for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { // build part of chanlist + // rt_printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); + if (chanlist[0] == chanlist[i]) + break; // we detect loop, this must by finish + if (CR_CHAN(chanlist[i]) & 1) // odd channel cann't by differencial + if (CR_AREF(chanlist[i]) == AREF_DIFF) { + comedi_error(dev, + "Odd channel can't be differential input!\n"); + return 0; + } + nowmustbechan = + (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; + if (CR_AREF(chansegment[i - 1]) == AREF_DIFF) + nowmustbechan = (nowmustbechan + 1) % s->n_chan; + if (nowmustbechan != CR_CHAN(chanlist[i])) { // channel list isn't continous :-( + rt_printk + ("channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n", + i, CR_CHAN(chanlist[i]), nowmustbechan, + CR_CHAN(chanlist[0])); + return 0; + } + chansegment[i] = chanlist[i]; // well, this is next correct channel in list + } + + for (i = 0, segpos = 0; i < n_chan; i++) { // check whole chanlist + //rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); + if (chanlist[i] != chansegment[i % seglen]) { + rt_printk + ("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", + i, CR_CHAN(chansegment[i]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(chanlist[i % seglen]), + CR_RANGE(chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); + return 0; // chan/gain list is strange + } + } + } else { + seglen = 1; + } + return seglen; +} + +static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int *chanlist, unsigned int n_chan, unsigned int seglen) +{ + unsigned int i, range, chanprog; + + DPRINTK("adv_pci1710 EDBG: setup_channel_list(...,%d,%d)\n", n_chan, + seglen); + devpriv->act_chanlist_len = seglen; + devpriv->act_chanlist_pos = 0; + + DPRINTK("SegLen: %d\n", seglen); + for (i = 0; i < seglen; i++) { // store range list to card + chanprog = muxonechan[CR_CHAN(chanlist[i])]; + outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ + range = this_board->rangecode_ai[CR_RANGE(chanlist[i])]; + if (CR_AREF(chanlist[i]) == AREF_DIFF) + range |= 0x0020; + outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ +#ifdef PCI171x_PARANOIDCHECK + devpriv->act_chanlist[i] = + (CR_CHAN(chanlist[i]) << 12) & 0xf000; +#endif + DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range, + devpriv->act_chanlist[i]); + } + + devpriv->ai_et_MuxVal = + CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); + outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); /* select channel interval to scan */ + DPRINTK("MUX: %4x L%4x.H%4x\n", + CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8), + CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen - 1])); +} + +/* +============================================================================== +*/ +static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2) +{ + DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, + divisor1, divisor2); + outw(0xb4, dev->iobase + PCI171x_CNTCTRL); + outw(0x74, dev->iobase + PCI171x_CNTCTRL); + + if (mode == 1) { + outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2); + outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2); + outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1); + outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1); + } + DPRINTK("adv_pci1710 EDBG: END: start_pacer(...)\n"); +} + +/* +============================================================================== +*/ +static int pci171x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n"); + + switch (this_board->cardtype) { + default: + devpriv->CntrlReg &= Control_CNT0; + devpriv->CntrlReg |= Control_SW; + + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); // reset any operations + start_pacer(dev, -1, 0, 0); + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); + break; + } + + devpriv->ai_do = 0; + devpriv->ai_act_scan = 0; + s->async->cur_chan = 0; + devpriv->ai_buf_ptr = 0; + devpriv->neverending_ai = 0; + + DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_cancel(...)\n"); + return 0; +} + +/* +============================================================================== +*/ +static int pci171x_reset(struct comedi_device * dev) +{ + DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n"); + outw(0x30, dev->iobase + PCI171x_CNTCTRL); + devpriv->CntrlReg = Control_SW | Control_CNT0; // Software trigger, CNT0=external + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); // reset any operations + outb(0, dev->iobase + PCI171x_CLRFIFO); // clear FIFO + outb(0, dev->iobase + PCI171x_CLRINT); // clear INT request + start_pacer(dev, -1, 0, 0); // stop 8254 + devpriv->da_ranges = 0; + if (this_board->n_aochan) { + outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); // set DACs to 0..5V + outw(0, dev->iobase + PCI171x_DA1); // set DA outputs to 0V + devpriv->ao_data[0] = 0x0000; + if (this_board->n_aochan > 1) { + outw(0, dev->iobase + PCI171x_DA2); + devpriv->ao_data[1] = 0x0000; + } + } + outw(0, dev->iobase + PCI171x_DO); // digital outputs to 0 + outb(0, dev->iobase + PCI171x_CLRFIFO); // clear FIFO + outb(0, dev->iobase + PCI171x_CLRINT); // clear INT request + + DPRINTK("adv_pci1710 EDBG: END: pci171x_reset(...)\n"); + return 0; +} + +/* +============================================================================== +*/ +static int pci1720_reset(struct comedi_device * dev) +{ + DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n"); + outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); // set synchronous output mode + devpriv->da_ranges = 0xAA; + outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); // set all ranges to +/-5V + outw(0x0800, dev->iobase + PCI1720_DA0); // set outputs to 0V + outw(0x0800, dev->iobase + PCI1720_DA1); + outw(0x0800, dev->iobase + PCI1720_DA2); + outw(0x0800, dev->iobase + PCI1720_DA3); + outb(0, dev->iobase + PCI1720_SYNCOUT); // update outputs + devpriv->ao_data[0] = 0x0800; + devpriv->ao_data[1] = 0x0800; + devpriv->ao_data[2] = 0x0800; + devpriv->ao_data[3] = 0x0800; + DPRINTK("adv_pci1710 EDBG: END: pci1720_reset(...)\n"); + return 0; +} + +/* +============================================================================== +*/ +static int pci1710_reset(struct comedi_device * dev) +{ + DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n"); + switch (this_board->cardtype) { + case TYPE_PCI1720: + return pci1720_reset(dev); + default: + return pci171x_reset(dev); + } + DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n"); +} + +/* +============================================================================== +*/ +static int pci1710_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret, subdev, n_subdevices; + unsigned int irq; + unsigned long iobase; + struct pci_dev *pcidev; + int opt_bus, opt_slot; + const char *errstr; + unsigned char pci_bus, pci_slot, pci_func; + int i; + int board_index; + + rt_printk("comedi%d: adv_pci1710: ", dev->minor); + + opt_bus = it->options[0]; + opt_slot = it->options[1]; + + if ((ret = alloc_private(dev, sizeof(struct pci1710_private))) < 0) { + rt_printk(" - Allocation failed!\n"); + return -ENOMEM; + } + + /* Look for matching PCI device */ + errstr = "not found!"; + pcidev = NULL; + board_index = this_board - boardtypes; + while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_ADVANTECH, + PCI_ANY_ID, pcidev))) { + if(strcmp(this_board->name, DRV_NAME) == 0) + { + for(i = 0; i < n_boardtypes; ++i) + { + if(pcidev->device == boardtypes[i].device_id) + { + board_index = i; + break; + } + } + if(i == n_boardtypes) continue; + }else + { + if(pcidev->device != boardtypes[board_index].device_id) continue; + } + + /* Found matching vendor/device. */ + if (opt_bus || opt_slot) { + /* Check bus/slot. */ + if (opt_bus != pcidev->bus->number + || opt_slot != PCI_SLOT(pcidev->devfn)) + continue; /* no match */ + } + /* + * Look for device that isn't in use. + * Enable PCI device and request regions. + */ + if (comedi_pci_enable(pcidev, DRV_NAME)) { + errstr = "failed to enable PCI device and request regions!"; + continue; + } + // fixup board_ptr in case we were using the dummy entry with the driver name + dev->board_ptr = &boardtypes[board_index]; + break; + } + + if (!pcidev) { + if (opt_bus || opt_slot) { + rt_printk(" - Card at b:s %d:%d %s\n", + opt_bus, opt_slot, errstr); + } else { + rt_printk(" - Card %s\n", errstr); + } + return -EIO; + } + + pci_bus = pcidev->bus->number; + pci_slot = PCI_SLOT(pcidev->devfn); + pci_func = PCI_FUNC(pcidev->devfn); + irq = pcidev->irq; + iobase = pci_resource_start(pcidev, 2); + + rt_printk(", b:s:f=%d:%d:%d, io=0x%4lx", pci_bus, pci_slot, pci_func, + iobase); + + dev->iobase = iobase; + + dev->board_name = this_board->name; + devpriv->pcidev = pcidev; + + n_subdevices = 0; + if (this_board->n_aichan) + n_subdevices++; + if (this_board->n_aochan) + n_subdevices++; + if (this_board->n_dichan) + n_subdevices++; + if (this_board->n_dochan) + n_subdevices++; + if (this_board->n_counter) + n_subdevices++; + + if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) { + rt_printk(" - Allocation failed!\n"); + return ret; + } + + pci1710_reset(dev); + + if (this_board->have_irq) { + if (irq) { + if (comedi_request_irq(irq, interrupt_service_pci1710, + IRQF_SHARED, "Advantech PCI-1710", + dev)) { + rt_printk + (", unable to allocate IRQ %d, DISABLING IT", + irq); + irq = 0; /* Can't use IRQ */ + } else { + rt_printk(", irq=%u", irq); + } + } else { + rt_printk(", IRQ disabled"); + } + } else { + irq = 0; + } + + dev->irq = irq; + + printk(".\n"); + + subdev = 0; + + if (this_board->n_aichan) { + s = dev->subdevices + subdev; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; + if (this_board->n_aichand) + s->subdev_flags |= SDF_DIFF; + s->n_chan = this_board->n_aichan; + s->maxdata = this_board->ai_maxdata; + s->len_chanlist = this_board->n_aichan; + s->range_table = this_board->rangelist_ai; + s->cancel = pci171x_ai_cancel; + s->insn_read = pci171x_insn_read_ai; + if (irq) { + s->subdev_flags |= SDF_CMD_READ; + s->do_cmdtest = pci171x_ai_cmdtest; + s->do_cmd = pci171x_ai_cmd; + } + devpriv->i8254_osc_base = 100; // 100ns=10MHz + subdev++; + } + + if (this_board->n_aochan) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_aochan; + s->maxdata = this_board->ao_maxdata; + s->len_chanlist = this_board->n_aochan; + s->range_table = this_board->rangelist_ao; + switch (this_board->cardtype) { + case TYPE_PCI1720: + s->insn_write = pci1720_insn_write_ao; + break; + default: + s->insn_write = pci171x_insn_write_ao; + break; + } + s->insn_read = pci171x_insn_read_ao; + subdev++; + } + + if (this_board->n_dichan) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_dichan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dichan; + s->range_table = &range_digital; + s->io_bits = 0; /* all bits input */ + s->insn_bits = pci171x_insn_bits_di; + subdev++; + } + + if (this_board->n_dochan) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_dochan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dochan; + s->range_table = &range_digital; + s->io_bits = (1 << this_board->n_dochan) - 1; /* all bits output */ + s->state = 0; + s->insn_bits = pci171x_insn_bits_do; + subdev++; + } + + if (this_board->n_counter) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = this_board->n_counter; + s->len_chanlist = this_board->n_counter; + s->maxdata = 0xffff; + s->range_table = &range_unknown; + s->insn_read = pci171x_insn_counter_read; + s->insn_write = pci171x_insn_counter_write; + s->insn_config = pci171x_insn_counter_config; + subdev++; + } + + devpriv->valid = 1; + + return 0; +} + +/* +============================================================================== +*/ +static int pci1710_detach(struct comedi_device * dev) +{ + + if (dev->private) { + if (devpriv->valid) + pci1710_reset(dev); + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (devpriv->pcidev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pcidev); + } + pci_dev_put(devpriv->pcidev); + } + } + + return 0; +} + +/* +============================================================================== +*/ +COMEDI_PCI_INITCLEANUP(driver_pci1710, pci1710_pci_table); +/* +============================================================================== +*/ diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c new file mode 100644 index 000000000000..81f7ee18c150 --- /dev/null +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -0,0 +1,465 @@ +/******************************************************************************* + comedi/drivers/pci1723.c + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: adv_pci1723 +Description: Advantech PCI-1723 +Author: yonggang , Ian Abbott +Devices: [Advantech] PCI-1723 (adv_pci1723) +Updated: Mon, 14 Apr 2008 15:12:56 +0100 +Status: works + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + + If bus/slot is not specified, the first supported + PCI device found will be used. + +Subdevice 0 is 8-channel AO, 16-bit, range +/- 10 V. + +Subdevice 1 is 16-channel DIO. The channels are configurable as input or +output in 2 groups (0 to 7, 8 to 15). Configuring any channel implicitly +configures all channels in the same group. + +TODO: + +1. Add the two milliamp ranges to the AO subdevice (0 to 20 mA, 4 to 20 mA). +2. Read the initial ranges and values of the AO subdevice at start-up instead + of reinitializing them. +3. Implement calibration. +*/ + +#include "../comedidev.h" + +#include "comedi_pci.h" + +#define ADVANTECH_VENDOR 0x13fe /* Advantech PCI vendor ID */ + +// hardware types of the cards +#define TYPE_PCI1723 0 + +#define IORANGE_1723 0x2A + +/* all the registers for the pci1723 board */ +#define PCI1723_DA(N) ((N)<<1) /* W: D/A register N (0 to 7) */ + +#define PCI1723_SYN_SET 0x12 /*synchronized set register */ +#define PCI1723_ALL_CHNNELE_SYN_STROBE 0x12 /*synchronized status register */ + +#define PCI1723_RANGE_CALIBRATION_MODE 0x14 /* range and calibration mode */ +#define PCI1723_RANGE_CALIBRATION_STATUS 0x14 /* range and calibration status */ + +#define PCI1723_CONTROL_CMD_CALIBRATION_FUN 0x16 /* SADC control command for calibration function */ +#define PCI1723_STATUS_CMD_CALIBRATION_FUN 0x16 /* SADC control status for calibration function */ + +#define PCI1723_CALIBRATION_PARA_STROBE 0x18 /* Calibration parameter strobe */ + +#define PCI1723_DIGITAL_IO_PORT_SET 0x1A /* Digital I/O port setting */ +#define PCI1723_DIGITAL_IO_PORT_MODE 0x1A /* Digital I/O port mode */ + +#define PCI1723_WRITE_DIGITAL_OUTPUT_CMD 0x1C /* Write digital output command */ +#define PCI1723_READ_DIGITAL_INPUT_DATA 0x1C /* Read digital input data */ + +#define PCI1723_WRITE_CAL_CMD 0x1E /* Write calibration command */ +#define PCI1723_READ_CAL_STATUS 0x1E /* Read calibration status */ + +#define PCI1723_SYN_STROBE 0x20 /* Synchronized strobe */ + +#define PCI1723_RESET_ALL_CHN_STROBE 0x22 /* Reset all D/A channels strobe */ + +#define PCI1723_RESET_CAL_CONTROL_STROBE 0x24 /* Reset the calibration controller strobe */ + +#define PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE 0x26 /* Change D/A channels output type strobe */ + +#define PCI1723_SELECT_CALIBRATION 0x28 /* Select the calibration Ref_V */ + +//static unsigned short pci_list_builded=0; /*=1 list of card is know */ + +static const struct comedi_lrange range_pci1723 = { 1, { + BIP_RANGE(10) + } +}; + +/* + * Board descriptions for pci1723 boards. + */ +struct pci1723_board { + const char *name; + int vendor_id; // PCI vendor a device ID of card + int device_id; + int iorange; + char cardtype; + int n_aochan; // num of D/A chans + int n_diochan; // num of DIO chans + int ao_maxdata; // resolution of D/A + const struct comedi_lrange *rangelist_ao; // rangelist for D/A +}; + +static const struct pci1723_board boardtypes[] = { + { + name: "pci1723", + vendor_id:ADVANTECH_VENDOR, + device_id:0x1723, + iorange: IORANGE_1723, + cardtype:TYPE_PCI1723, + n_aochan:8, + n_diochan:16, + ao_maxdata:0xffff, + rangelist_ao:&range_pci1723, + }, +}; + +/* This is used by modprobe to translate PCI IDs to drivers. Should + * only be used for PCI and ISA-PnP devices */ +static DEFINE_PCI_DEVICE_TABLE(pci1723_pci_table) = { + {PCI_VENDOR_ID_ADVANTECH, 0x1723, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pci1723_pci_table); + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pci1723_detach(struct comedi_device * dev); + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pci1723_board)) + +static struct comedi_driver driver_pci1723 = { + driver_name:"adv_pci1723", + module:THIS_MODULE, + attach:pci1723_attach, + detach:pci1723_detach, +}; + +/* this structure is for data unique to this hardware driver. */ +struct pci1723_private { + int valid; //card is usable; + + struct pci_dev *pcidev; + unsigned char da_range[8]; // D/A output range for each channel + + short ao_data[8]; // data output buffer +}; + +/*the following macro to make it easy to +* access the private structure. +*/ +#define devpriv ((struct pci1723_private *)dev->private) + +#define this_board boardtypes + +/* + * the pci1723 card reset; + */ +static int pci1723_reset(struct comedi_device * dev) +{ + int i; + DPRINTK("adv_pci1723 EDBG: BGN: pci1723_reset(...)\n"); + + outw(0x01, dev->iobase + PCI1723_SYN_SET); // set synchronous output mode + + for (i = 0; i < 8; i++) { + // set all outputs to 0V + devpriv->ao_data[i] = 0x8000; + outw(devpriv->ao_data[i], dev->iobase + PCI1723_DA(i)); + // set all ranges to +/- 10V + devpriv->da_range[i] = 0; + outw(((devpriv->da_range[i] << 4) | i), + PCI1723_RANGE_CALIBRATION_MODE); + } + + outw(0, dev->iobase + PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE); // update ranges + outw(0, dev->iobase + PCI1723_SYN_STROBE); // update outputs + + // set asynchronous output mode + outw(0, dev->iobase + PCI1723_SYN_SET); + + DPRINTK("adv_pci1723 EDBG: END: pci1723_reset(...)\n"); + return 0; +} + +static int pci1723_insn_read_ao(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, chan; + + chan = CR_CHAN(insn->chanspec); + DPRINTK(" adv_PCI1723 DEBUG: pci1723_insn_read_ao() ----- \n"); + for (n = 0; n < insn->n; n++) + data[n] = devpriv->ao_data[chan]; + + return n; +} + +/* + analog data output; +*/ +static int pci1723_ao_write_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, chan; + chan = CR_CHAN(insn->chanspec); + + DPRINTK("PCI1723: the pci1723_ao_write_winsn() ------\n"); + + for (n = 0; n < insn->n; n++) { + + devpriv->ao_data[chan] = data[n]; + outw(data[n], dev->iobase + PCI1723_DA(chan)); + } + + return n; +} + +/* + digital i/o config/query +*/ +static int pci1723_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int mask; + unsigned int bits; + unsigned short dio_mode; + + mask = 1 << CR_CHAN(insn->chanspec); + if (mask & 0x00FF) { + bits = 0x00FF; + } else { + bits = 0xFF00; + } + 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; + default: + return -EINVAL; + } + + // update hardware DIO mode + dio_mode = 0x0000; // low byte output, high byte output + if ((s->io_bits & 0x00FF) == 0) + dio_mode |= 0x0001; // low byte input + if ((s->io_bits & 0xFF00) == 0) + dio_mode |= 0x0002; // high byte input + outw(dio_mode, dev->iobase + PCI1723_DIGITAL_IO_PORT_SET); + return 1; +} + +/* + digital i/o bits read/write +*/ +static int pci1723_dio_insn_bits(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]); + outw(s->state, dev->iobase + PCI1723_WRITE_DIGITAL_OUTPUT_CMD); + } + data[1] = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA); + return 2; +} + +/* + * Attach is called by the Comedi core to configure the driver + * for a pci1723 board. + */ +static int pci1723_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret, subdev, n_subdevices; + struct pci_dev *pcidev; + unsigned int iobase; + unsigned char pci_bus, pci_slot, pci_func; + int opt_bus, opt_slot; + const char *errstr; + + rt_printk("comedi%d: adv_pci1723: board=%s", dev->minor, + this_board->name); + + opt_bus = it->options[0]; + opt_slot = it->options[1]; + + if ((ret = alloc_private(dev, sizeof(struct pci1723_private))) < 0) { + rt_printk(" - Allocation failed!\n"); + return -ENOMEM; + } + + /* Look for matching PCI device */ + errstr = "not found!"; + pcidev = NULL; + while (NULL != (pcidev = + pci_get_device(PCI_VENDOR_ID_ADVANTECH, + this_board->device_id, pcidev))) { + /* Found matching vendor/device. */ + if (opt_bus || opt_slot) { + /* Check bus/slot. */ + if (opt_bus != pcidev->bus->number + || opt_slot != PCI_SLOT(pcidev->devfn)) + continue; /* no match */ + } + /* + * Look for device that isn't in use. + * Enable PCI device and request regions. + */ + if (comedi_pci_enable(pcidev, "adv_pci1723")) { + errstr = "failed to enable PCI device and request regions!"; + continue; + } + break; + } + + if (!pcidev) { + if (opt_bus || opt_slot) { + rt_printk(" - Card at b:s %d:%d %s\n", + opt_bus, opt_slot, errstr); + } else { + rt_printk(" - Card %s\n", errstr); + } + return -EIO; + } + + pci_bus = pcidev->bus->number; + pci_slot = PCI_SLOT(pcidev->devfn); + pci_func = PCI_FUNC(pcidev->devfn); + iobase = pci_resource_start(pcidev, 2); + + rt_printk(", b:s:f=%d:%d:%d, io=0x%4x", pci_bus, pci_slot, pci_func, + iobase); + + dev->iobase = iobase; + + dev->board_name = this_board->name; + devpriv->pcidev = pcidev; + + n_subdevices = 0; + + if (this_board->n_aochan) + n_subdevices++; + if (this_board->n_diochan) + n_subdevices++; + + if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) { + rt_printk(" - Allocation failed!\n"); + return ret; + } + + pci1723_reset(dev); + subdev = 0; + if (this_board->n_aochan) { + s = dev->subdevices + subdev; + dev->write_subdev = s; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_aochan; + s->maxdata = this_board->ao_maxdata; + s->len_chanlist = this_board->n_aochan; + s->range_table = this_board->rangelist_ao; + + s->insn_write = pci1723_ao_write_winsn; + s->insn_read = pci1723_insn_read_ao; + + // read DIO config + switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE) & 0x03) { + case 0x00: // low byte output, high byte output + s->io_bits = 0xFFFF; + break; + case 0x01: // low byte input, high byte output + s->io_bits = 0xFF00; + break; + case 0x02: // low byte output, high byte input + s->io_bits = 0x00FF; + break; + case 0x03: // low byte input, high byte input + s->io_bits = 0x0000; + break; + } + // read DIO port state + s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA); + + subdev++; + } + + if (this_board->n_diochan) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = + SDF_READABLE | SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = this_board->n_diochan; + s->maxdata = 1; + s->len_chanlist = this_board->n_diochan; + s->range_table = &range_digital; + s->insn_config = pci1723_dio_insn_config; + s->insn_bits = pci1723_dio_insn_bits; + subdev++; + } + + devpriv->valid = 1; + + pci1723_reset(dev); + + return 0; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pci1723_detach(struct comedi_device * dev) +{ + printk("comedi%d: pci1723: remove\n", dev->minor); + + if (dev->private) { + if (devpriv->valid) + pci1723_reset(dev); + + if (devpriv->pcidev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pcidev); + } + pci_dev_put(devpriv->pcidev); + } + } + + return 0; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_PCI_INITCLEANUP(driver_pci1723, pci1723_pci_table); diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c new file mode 100644 index 000000000000..2604425c3a0f --- /dev/null +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -0,0 +1,1077 @@ +/* + * comedi/drivers/adv_pci_dio.c + * + * Author: Michal Dobes + * + * Hardware driver for Advantech PCI DIO cards. +*/ +/* +Driver: adv_pci_dio +Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1736UP, + PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754, + PCI-1756, PCI-1762 +Author: Michal Dobes +Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733, + PCI-1734, PCI-1736UP, PCI-1750, + PCI-1751, PCI-1752, PCI-1753, + PCI-1753+PCI-1753E, PCI-1754, PCI-1756, + PCI-1760, PCI-1762 +Status: untested +Updated: Mon, 14 Apr 2008 10:43:08 +0100 + +This driver supports now only insn interface for DI/DO/DIO. + +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first available PCI + device will be used. + +*/ + +#include "../comedidev.h" + +#include + +#include "comedi_pci.h" +#include "8255.h" + +#undef PCI_DIO_EXTDEBUG /* if defined, enable extensive debug logging */ + +#undef DPRINTK +#ifdef PCI_DIO_EXTDEBUG +#define DPRINTK(fmt, args...) rt_printk(fmt, ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +/* hardware types of the cards */ +enum hw_cards_id { + TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736, + TYPE_PCI1750, + TYPE_PCI1751, + TYPE_PCI1752, + TYPE_PCI1753, TYPE_PCI1753E, + TYPE_PCI1754, TYPE_PCI1756, + TYPE_PCI1760, + TYPE_PCI1762 +}; + +/* which I/O instructions to use */ +enum hw_io_access { + IO_8b, IO_16b +}; + +#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */ +#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */ +#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per card */ + +#define SIZE_8255 4 /* 8255 IO space length */ + +#define PCIDIO_MAINREG 2 /* main I/O region for all Advantech cards? */ + +/* Register offset definitions */ +/* Advantech PCI-1730/3/4 */ +#define PCI1730_IDI 0 /* R: Isolated digital input 0-15 */ +#define PCI1730_IDO 0 /* W: Isolated digital output 0-15 */ +#define PCI1730_DI 2 /* R: Digital input 0-15 */ +#define PCI1730_DO 2 /* W: Digital output 0-15 */ +#define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */ +#define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */ +#define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for interrupts */ +#define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */ +#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */ +#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */ + +/* Advantech PCI-1736UP */ +#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */ +#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */ +#define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */ +#define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for interrupts */ +#define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */ +#define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */ +#define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */ + +/* Advantech PCI-1750 */ +#define PCI1750_IDI 0 /* R: Isolated digital input 0-15 */ +#define PCI1750_IDO 0 /* W: Isolated digital output 0-15 */ +#define PCI1750_ICR 32 /* W: Interrupt control register */ +#define PCI1750_ISR 32 /* R: Interrupt status register */ + +/* Advantech PCI-1751/3/3E */ +#define PCI1751_DIO 0 /* R/W: begin of 8255 registers block */ +#define PCI1751_ICR 32 /* W: Interrupt control register */ +#define PCI1751_ISR 32 /* R: Interrupt status register */ +#define PCI1753_DIO 0 /* R/W: begin of 8255 registers block */ +#define PCI1753_ICR0 16 /* R/W: Interrupt control register group 0 */ +#define PCI1753_ICR1 17 /* R/W: Interrupt control register group 1 */ +#define PCI1753_ICR2 18 /* R/W: Interrupt control register group 2 */ +#define PCI1753_ICR3 19 /* R/W: Interrupt control register group 3 */ +#define PCI1753E_DIO 32 /* R/W: begin of 8255 registers block */ +#define PCI1753E_ICR0 48 /* R/W: Interrupt control register group 0 */ +#define PCI1753E_ICR1 49 /* R/W: Interrupt control register group 1 */ +#define PCI1753E_ICR2 50 /* R/W: Interrupt control register group 2 */ +#define PCI1753E_ICR3 51 /* R/W: Interrupt control register group 3 */ + +/* Advantech PCI-1752/4/6 */ +#define PCI1752_IDO 0 /* R/W: Digital output 0-31 */ +#define PCI1752_IDO2 4 /* R/W: Digital output 32-63 */ +#define PCI1754_IDI 0 /* R: Digital input 0-31 */ +#define PCI1754_IDI2 4 /* R: Digital input 32-64 */ +#define PCI1756_IDI 0 /* R: Digital input 0-31 */ +#define PCI1756_IDO 4 /* R/W: Digital output 0-31 */ +#define PCI1754_6_ICR0 0x08 /* R/W: Interrupt control register group 0 */ +#define PCI1754_6_ICR1 0x0a /* R/W: Interrupt control register group 1 */ +#define PCI1754_ICR2 0x0c /* R/W: Interrupt control register group 2 */ +#define PCI1754_ICR3 0x0e /* R/W: Interrupt control register group 3 */ +#define PCI1752_6_CFC 0x12 /* R/W: set/read channel freeze function */ +#define PCI175x_BOARDID 0x10 /* R: Board I/D switch for 1752/4/6 */ + +/* Advantech PCI-1762 registers */ +#define PCI1762_RO 0 /* R/W: Relays status/output */ +#define PCI1762_IDI 2 /* R: Isolated input status */ +#define PCI1762_BOARDID 4 /* R: Board I/D switch */ +#define PCI1762_ICR 6 /* W: Interrupt control register */ +#define PCI1762_ISR 6 /* R: Interrupt status register */ + +/* Advantech PCI-1760 registers */ +#define OMB0 0x0c /* W: Mailbox outgoing registers */ +#define OMB1 0x0d +#define OMB2 0x0e +#define OMB3 0x0f +#define IMB0 0x1c /* R: Mailbox incoming registers */ +#define IMB1 0x1d +#define IMB2 0x1e +#define IMB3 0x1f +#define INTCSR0 0x38 /* R/W: Interrupt control registers */ +#define INTCSR1 0x39 +#define INTCSR2 0x3a +#define INTCSR3 0x3b + +/* PCI-1760 mailbox commands */ +#define CMD_ClearIMB2 0x00 /* Clear IMB2 status and return actaul DI status in IMB3 */ +#define CMD_SetRelaysOutput 0x01 /* Set relay output from OMB0 */ +#define CMD_GetRelaysStatus 0x02 /* Get relay status to IMB0 */ +#define CMD_ReadCurrentStatus 0x07 /* Read the current status of the register in OMB0, result in IMB0 */ +#define CMD_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in IMB1.IMB0 */ +#define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in IMB1.IMB0 */ +#define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in OMB0 */ +#define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on bits in OMB0 */ +#define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on bits in OMB0 */ +#define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in OMB0 */ +#define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in OMB0 to its reset values */ +#define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow interrupts based on bits in OMB0 */ +#define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value interrupts based on bits in OMB0 */ +#define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0 - rising, =1 - falling) */ +#define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current value */ +#define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value 256*OMB1+OMB0 */ +#define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value 256*OMB1+OMB0 */ +#define CMD_SetIDI2CntResetValue 0x42 /* Set IDI2 Counter Reset Value 256*OMB1+OMB0 */ +#define CMD_SetIDI3CntResetValue 0x43 /* Set IDI3 Counter Reset Value 256*OMB1+OMB0 */ +#define CMD_SetIDI4CntResetValue 0x44 /* Set IDI4 Counter Reset Value 256*OMB1+OMB0 */ +#define CMD_SetIDI5CntResetValue 0x45 /* Set IDI5 Counter Reset Value 256*OMB1+OMB0 */ +#define CMD_SetIDI6CntResetValue 0x46 /* Set IDI6 Counter Reset Value 256*OMB1+OMB0 */ +#define CMD_SetIDI7CntResetValue 0x47 /* Set IDI7 Counter Reset Value 256*OMB1+OMB0 */ +#define CMD_SetIDI0CntMatchValue 0x48 /* Set IDI0 Counter Match Value 256*OMB1+OMB0 */ +#define CMD_SetIDI1CntMatchValue 0x49 /* Set IDI1 Counter Match Value 256*OMB1+OMB0 */ +#define CMD_SetIDI2CntMatchValue 0x4a /* Set IDI2 Counter Match Value 256*OMB1+OMB0 */ +#define CMD_SetIDI3CntMatchValue 0x4b /* Set IDI3 Counter Match Value 256*OMB1+OMB0 */ +#define CMD_SetIDI4CntMatchValue 0x4c /* Set IDI4 Counter Match Value 256*OMB1+OMB0 */ +#define CMD_SetIDI5CntMatchValue 0x4d /* Set IDI5 Counter Match Value 256*OMB1+OMB0 */ +#define CMD_SetIDI6CntMatchValue 0x4e /* Set IDI6 Counter Match Value 256*OMB1+OMB0 */ +#define CMD_SetIDI7CntMatchValue 0x4f /* Set IDI7 Counter Match Value 256*OMB1+OMB0 */ + +#define OMBCMD_RETRY 0x03 /* 3 times try request before error */ + +static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pci_dio_detach(struct comedi_device * dev); + +struct diosubd_data { + int chans; /* num of chans */ + int addr; /* PCI address ofset */ + int regs; /* number of registers to read or 8255 subdevices */ + unsigned int specflags; /* addon subdevice flags */ +}; + +struct dio_boardtype { + const char *name; /* board name */ + int vendor_id; /* vendor/device PCI ID */ + int device_id; + int main_pci_region; /* main I/O PCI region */ + enum hw_cards_id cardtype; + struct diosubd_data sdi[MAX_DI_SUBDEVS]; /* DI chans */ + struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */ + struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */ + struct diosubd_data boardid; /* card supports board ID switch */ + enum hw_io_access io_access; +}; + +static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = { + {PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1733, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1734, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1752, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1753, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1754, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1756, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1760, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ADVANTECH, 0x1762, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pci_dio_pci_table); + +static const struct dio_boardtype boardtypes[] = { + {"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG, + TYPE_PCI1730, + {{16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0}}, + {{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, + IO_8b, + }, + {"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG, + TYPE_PCI1733, + {{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, + IO_8b}, + {"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG, + TYPE_PCI1734, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, + IO_8b}, + {"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG, + TYPE_PCI1736, + {{0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0}}, + {{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}}, + {{ 0, 0, 0, 0}, { 0, 0, 0, 0}}, + { 4, PCI1736_BOARDID, 1, SDF_INTERNAL}, + IO_8b, + }, + {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG, + TYPE_PCI1750, + {{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}}, + {{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {0, 0, 0, 0}, + IO_8b}, + {"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG, + TYPE_PCI1751, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}}, + {0, 0, 0, 0}, + IO_8b}, + {"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG, + TYPE_PCI1752, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, + IO_16b}, + {"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, + TYPE_PCI1753, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}}, + {0, 0, 0, 0}, + IO_8b}, + {"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, + TYPE_PCI1753E, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}}, + {0, 0, 0, 0}, + IO_8b}, + {"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG, + TYPE_PCI1754, + {{32, PCI1754_IDI, 2, 0}, {32, PCI1754_IDI2, 2, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, + IO_16b}, + {"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG, + TYPE_PCI1756, + {{0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0}}, + {{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, + IO_16b}, + {"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0, + TYPE_PCI1760, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, /* This card have own setup work */ + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {0, 0, 0, 0}, + IO_8b}, + {"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG, + TYPE_PCI1762, + {{0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0}}, + {{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + {4, PCI1762_BOARDID, 1, SDF_INTERNAL}, + IO_16b} +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct dio_boardtype)) + +static struct comedi_driver driver_pci_dio = { + driver_name:"adv_pci_dio", + module:THIS_MODULE, + attach:pci_dio_attach, + detach:pci_dio_detach +}; + +struct pci_dio_private { + struct pci_dio_private *prev; /* previous private struct */ + struct pci_dio_private *next; /* next private struct */ + struct pci_dev *pcidev; /* pointer to board's pci_dev */ + char valid; /* card is usable */ + char GlobalIrqEnabled; /* 1= any IRQ source is enabled */ + /* PCI-1760 specific data */ + unsigned char IDICntEnable; /* counter's counting enable status */ + unsigned char IDICntOverEnable; /* counter's overflow interrupts enable status */ + unsigned char IDICntMatchEnable; /* counter's match interrupts enable status */ + unsigned char IDICntEdge; /* counter's count edge value (bit=0 - rising, =1 - falling) */ + unsigned short CntResValue[8]; /* counters' reset value */ + unsigned short CntMatchValue[8]; /* counters' match interrupt value */ + unsigned char IDIFiltersEn; /* IDI's digital filters enable status */ + unsigned char IDIPatMatchEn; /* IDI's pattern match enable status */ + unsigned char IDIPatMatchValue; /* IDI's pattern match value */ + unsigned short IDIFiltrLow[8]; /* IDI's filter value low signal */ + unsigned short IDIFiltrHigh[8]; /* IDI's filter value high signal */ +}; + +static struct pci_dio_private *pci_priv = NULL; /* list of allocated cards */ + +#define devpriv ((struct pci_dio_private *)dev->private) +#define this_board ((const struct dio_boardtype *)dev->board_ptr) + +/* +============================================================================== +*/ +static int pci_dio_insn_bits_di_b(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + const struct diosubd_data *d = (const struct diosubd_data *)s->private; + int i; + + data[1] = 0; + for (i = 0; i < d->regs; i++) { + data[1] |= inb(dev->iobase + d->addr + i) << (8 * i); + } + + return 2; +} + +/* +============================================================================== +*/ +static int pci_dio_insn_bits_di_w(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + const struct diosubd_data *d = (const struct diosubd_data *)s->private; + int i; + + data[1] = 0; + for (i = 0; i < d->regs; i++) + data[1] |= inw(dev->iobase + d->addr + 2 * i) << (16 * i); + + return 2; +} + +/* +============================================================================== +*/ +static int pci_dio_insn_bits_do_b(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + const struct diosubd_data *d = (const struct diosubd_data *)s->private; + int i; + + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + for (i = 0; i < d->regs; i++) + outb((s->state >> (8 * i)) & 0xff, + dev->iobase + d->addr + i); + } + data[1] = s->state; + + return 2; +} + +/* +============================================================================== +*/ +static int pci_dio_insn_bits_do_w(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + const struct diosubd_data *d = (const struct diosubd_data *)s->private; + int i; + + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + for (i = 0; i < d->regs; i++) + outw((s->state >> (16 * i)) & 0xffff, + dev->iobase + d->addr + 2 * i); + } + data[1] = s->state; + + return 2; +} + +/* +============================================================================== +*/ +static int pci1760_unchecked_mbxrequest(struct comedi_device * dev, + unsigned char *omb, unsigned char *imb, int repeats) +{ + int cnt, tout, ok = 0; + + for (cnt = 0; cnt < repeats; cnt++) { + outb(omb[0], dev->iobase + OMB0); + outb(omb[1], dev->iobase + OMB1); + outb(omb[2], dev->iobase + OMB2); + outb(omb[3], dev->iobase + OMB3); + for (tout = 0; tout < 251; tout++) { + if ((imb[2] = inb(dev->iobase + IMB2)) == omb[2]) { + imb[0] = inb(dev->iobase + IMB0); + imb[1] = inb(dev->iobase + IMB1); + imb[3] = inb(dev->iobase + IMB3); + ok = 1; + break; + } + comedi_udelay(1); + } + if (ok) + return 0; + } + + comedi_error(dev, "PCI-1760 mailbox request timeout!"); + return -ETIME; +} + +static int pci1760_clear_imb2(struct comedi_device * dev) +{ + unsigned char omb[4] = { 0x0, 0x0, CMD_ClearIMB2, 0x0 }; + unsigned char imb[4]; + /* check if imb2 is already clear */ + if (inb(dev->iobase + IMB2) == CMD_ClearIMB2) + return 0; + return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY); +} + +static int pci1760_mbxrequest(struct comedi_device * dev, + unsigned char *omb, unsigned char *imb) +{ + if (omb[2] == CMD_ClearIMB2) { + comedi_error(dev, + "bug! this function should not be used for CMD_ClearIMB2 command"); + return -EINVAL; + } + if (inb(dev->iobase + IMB2) == omb[2]) { + int retval; + retval = pci1760_clear_imb2(dev); + if (retval < 0) + return retval; + } + return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY); +} + +/* +============================================================================== +*/ +static int pci1760_insn_bits_di(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[1] = inb(dev->iobase + IMB3); + + return 2; +} + +/* +============================================================================== +*/ +static int pci1760_insn_bits_do(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int ret; + unsigned char omb[4] = { + 0x00, + 0x00, + CMD_SetRelaysOutput, + 0x00 + }; + unsigned char imb[4]; + + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + omb[0] = s->state; + if (!(ret = pci1760_mbxrequest(dev, omb, imb))) + return ret; + } + data[1] = s->state; + + return 2; +} + +/* +============================================================================== +*/ +static int pci1760_insn_cnt_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int ret, n; + unsigned char omb[4] = { + CR_CHAN(insn->chanspec) & 0x07, + 0x00, + CMD_GetIDICntCurValue, + 0x00 + }; + unsigned char imb[4]; + + for (n = 0; n < insn->n; n++) { + if (!(ret = pci1760_mbxrequest(dev, omb, imb))) + return ret; + data[n] = (imb[1] << 8) + imb[0]; + } + + return n; +} + +/* +============================================================================== +*/ +static int pci1760_insn_cnt_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int ret; + unsigned char chan = CR_CHAN(insn->chanspec) & 0x07; + unsigned char bitmask = 1 << chan; + unsigned char omb[4] = { + data[0] & 0xff, + (data[0] >> 8) & 0xff, + CMD_SetIDI0CntResetValue + chan, + 0x00 + }; + unsigned char imb[4]; + + if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) { /* Set reset value if different */ + if (!(ret = pci1760_mbxrequest(dev, omb, imb))) + return ret; + devpriv->CntResValue[chan] = data[0] & 0xffff; + } + + omb[0] = bitmask; /* reset counter to it reset value */ + omb[2] = CMD_ResetIDICounters; + if (!(ret = pci1760_mbxrequest(dev, omb, imb))) + return ret; + + if (!(bitmask & devpriv->IDICntEnable)) { /* start counter if it don't run */ + omb[0] = bitmask; + omb[2] = CMD_EnableIDICounters; + if (!(ret = pci1760_mbxrequest(dev, omb, imb))) + return ret; + devpriv->IDICntEnable |= bitmask; + } + return 1; +} + +/* +============================================================================== +*/ +static int pci1760_reset(struct comedi_device * dev) +{ + int i; + unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 }; + unsigned char imb[4]; + + outb(0, dev->iobase + INTCSR0); /* disable IRQ */ + outb(0, dev->iobase + INTCSR1); + outb(0, dev->iobase + INTCSR2); + outb(0, dev->iobase + INTCSR3); + devpriv->GlobalIrqEnabled = 0; + + omb[0] = 0x00; + omb[2] = CMD_SetRelaysOutput; /* reset relay outputs */ + pci1760_mbxrequest(dev, omb, imb); + + omb[0] = 0x00; + omb[2] = CMD_EnableIDICounters; /* disable IDI up counters */ + pci1760_mbxrequest(dev, omb, imb); + devpriv->IDICntEnable = 0; + + omb[0] = 0x00; + omb[2] = CMD_OverflowIDICounters; /* disable counters overflow interrupts */ + pci1760_mbxrequest(dev, omb, imb); + devpriv->IDICntOverEnable = 0; + + omb[0] = 0x00; + omb[2] = CMD_MatchIntIDICounters; /* disable counters match value interrupts */ + pci1760_mbxrequest(dev, omb, imb); + devpriv->IDICntMatchEnable = 0; + + omb[0] = 0x00; + omb[1] = 0x80; + for (i = 0; i < 8; i++) { /* set IDI up counters match value */ + omb[2] = CMD_SetIDI0CntMatchValue + i; + pci1760_mbxrequest(dev, omb, imb); + devpriv->CntMatchValue[i] = 0x8000; + } + + omb[0] = 0x00; + omb[1] = 0x00; + for (i = 0; i < 8; i++) { /* set IDI up counters reset value */ + omb[2] = CMD_SetIDI0CntResetValue + i; + pci1760_mbxrequest(dev, omb, imb); + devpriv->CntResValue[i] = 0x0000; + } + + omb[0] = 0xff; + omb[2] = CMD_ResetIDICounters; /* reset IDI up counters to reset values */ + pci1760_mbxrequest(dev, omb, imb); + + omb[0] = 0x00; + omb[2] = CMD_EdgeIDICounters; /* set IDI up counters count edge */ + pci1760_mbxrequest(dev, omb, imb); + devpriv->IDICntEdge = 0x00; + + omb[0] = 0x00; + omb[2] = CMD_EnableIDIFilters; /* disable all digital in filters */ + pci1760_mbxrequest(dev, omb, imb); + devpriv->IDIFiltersEn = 0x00; + + omb[0] = 0x00; + omb[2] = CMD_EnableIDIPatternMatch; /* disable pattern matching */ + pci1760_mbxrequest(dev, omb, imb); + devpriv->IDIPatMatchEn = 0x00; + + omb[0] = 0x00; + omb[2] = CMD_SetIDIPatternMatch; /* set pattern match value */ + pci1760_mbxrequest(dev, omb, imb); + devpriv->IDIPatMatchValue = 0x00; + + return 0; +} + +/* +============================================================================== +*/ +static int pci_dio_reset(struct comedi_device * dev) +{ + DPRINTK("adv_pci_dio EDBG: BGN: pci171x_reset(...)\n"); + + switch (this_board->cardtype) { + case TYPE_PCI1730: + outb(0, dev->iobase + PCI1730_DO); /* clear outputs */ + outb(0, dev->iobase + PCI1730_DO + 1); + outb(0, dev->iobase + PCI1730_IDO); + outb(0, dev->iobase + PCI1730_IDO + 1); + /* NO break there! */ + case TYPE_PCI1733: + outb(0, dev->iobase + PCI1730_3_INT_EN); /* disable interrupts */ + outb(0x0f, dev->iobase + PCI1730_3_INT_CLR); /* clear interrupts */ + outb(0, dev->iobase + PCI1730_3_INT_RF); /* set rising edge trigger */ + break; + case TYPE_PCI1734: + outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */ + outb(0, dev->iobase + PCI1734_IDO + 1); + outb(0, dev->iobase + PCI1734_IDO + 2); + outb(0, dev->iobase + PCI1734_IDO + 3); + break; + + case TYPE_PCI1736: + outb(0, dev->iobase+PCI1736_IDO); + outb(0, dev->iobase+PCI1736_IDO+1); + outb(0, dev->iobase+PCI1736_3_INT_EN); /* disable interrupts */ + outb(0x0f, dev->iobase+PCI1736_3_INT_CLR);/* clear interrupts */ + outb(0, dev->iobase+PCI1736_3_INT_RF); /* set rising edge trigger */ + break; + + case TYPE_PCI1750: + case TYPE_PCI1751: + outb(0x88, dev->iobase + PCI1750_ICR); /* disable & clear interrupts */ + break; + case TYPE_PCI1752: + outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze function */ + outw(0, dev->iobase + PCI1752_IDO); /* clear outputs */ + outw(0, dev->iobase + PCI1752_IDO + 2); + outw(0, dev->iobase + PCI1752_IDO2); + outw(0, dev->iobase + PCI1752_IDO2 + 2); + break; + case TYPE_PCI1753E: + outb(0x88, dev->iobase + PCI1753E_ICR0); /* disable & clear interrupts */ + outb(0x80, dev->iobase + PCI1753E_ICR1); + outb(0x80, dev->iobase + PCI1753E_ICR2); + outb(0x80, dev->iobase + PCI1753E_ICR3); + /* NO break there! */ + case TYPE_PCI1753: + outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear interrupts */ + outb(0x80, dev->iobase + PCI1753_ICR1); + outb(0x80, dev->iobase + PCI1753_ICR2); + outb(0x80, dev->iobase + PCI1753_ICR3); + break; + case TYPE_PCI1754: + outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear interrupts */ + outw(0x08, dev->iobase + PCI1754_6_ICR1); + outw(0x08, dev->iobase + PCI1754_ICR2); + outw(0x08, dev->iobase + PCI1754_ICR3); + break; + case TYPE_PCI1756: + outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze function */ + outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear interrupts */ + outw(0x08, dev->iobase + PCI1754_6_ICR1); + outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */ + outw(0, dev->iobase + PCI1756_IDO + 2); + break; + case TYPE_PCI1760: + pci1760_reset(dev); + break; + case TYPE_PCI1762: + outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear interrupts */ + break; + } + + DPRINTK("adv_pci_dio EDBG: END: pci171x_reset(...)\n"); + + return 0; +} + +/* +============================================================================== +*/ +static int pci1760_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int subdev = 0; + + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 8; + s->maxdata = 1; + s->len_chanlist = 8; + s->range_table = &range_digital; + s->insn_bits = pci1760_insn_bits_di; + subdev++; + + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->n_chan = 8; + s->maxdata = 1; + s->len_chanlist = 8; + s->range_table = &range_digital; + s->state = 0; + s->insn_bits = pci1760_insn_bits_do; + subdev++; + + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = SDF_WRITABLE | SDF_LSAMPL; + s->n_chan = 2; + s->maxdata = 0xffffffff; + s->len_chanlist = 2; +/* s->insn_config=pci1760_insn_pwm_cfg; */ + subdev++; + + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 0xffff; + s->len_chanlist = 8; + s->insn_read = pci1760_insn_cnt_read; + s->insn_write = pci1760_insn_cnt_write; +/* s->insn_config=pci1760_insn_cnt_cfg; */ + subdev++; + + return 0; +} + +/* +============================================================================== +*/ +static int pci_dio_add_di(struct comedi_device * dev, struct comedi_subdevice * s, + const struct diosubd_data * d, int subdev) +{ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | d->specflags; + if (d->chans > 16) + s->subdev_flags |= SDF_LSAMPL; + s->n_chan = d->chans; + s->maxdata = 1; + s->len_chanlist = d->chans; + s->range_table = &range_digital; + switch (this_board->io_access) { + case IO_8b: + s->insn_bits = pci_dio_insn_bits_di_b; + break; + case IO_16b: + s->insn_bits = pci_dio_insn_bits_di_w; + break; + } + s->private = (void *)d; + + return 0; +} + +/* +============================================================================== +*/ +static int pci_dio_add_do(struct comedi_device * dev, struct comedi_subdevice * s, + const struct diosubd_data * d, int subdev) +{ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + if (d->chans > 16) + s->subdev_flags |= SDF_LSAMPL; + s->n_chan = d->chans; + s->maxdata = 1; + s->len_chanlist = d->chans; + s->range_table = &range_digital; + s->state = 0; + switch (this_board->io_access) { + case IO_8b: + s->insn_bits = pci_dio_insn_bits_do_b; + break; + case IO_16b: + s->insn_bits = pci_dio_insn_bits_do_w; + break; + } + s->private = (void *)d; + + return 0; +} + +/* +============================================================================== +*/ +static int CheckAndAllocCard(struct comedi_device * dev, struct comedi_devconfig * it, + struct pci_dev *pcidev) +{ + struct pci_dio_private *pr, *prev; + + for (pr = pci_priv, prev = NULL; pr != NULL; prev = pr, pr = pr->next) { + if (pr->pcidev == pcidev) { + return 0; /* this card is used, look for another */ + } + } + + if (prev) { + devpriv->prev = prev; + prev->next = devpriv; + } else { + pci_priv = devpriv; + } + + devpriv->pcidev = pcidev; + + return 1; +} + +/* +============================================================================== +*/ +static int pci_dio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret, subdev, n_subdevices, i, j; + unsigned long iobase; + struct pci_dev *pcidev; + + rt_printk("comedi%d: adv_pci_dio: ", dev->minor); + + if ((ret = alloc_private(dev, sizeof(struct pci_dio_private))) < 0) { + rt_printk(", Error: Cann't allocate private memory!\n"); + return -ENOMEM; + } + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + /* loop through cards supported by this driver */ + for (i = 0; i < n_boardtypes; ++i) { + if (boardtypes[i].vendor_id != pcidev->vendor) + continue; + if (boardtypes[i].device_id != pcidev->device) + continue; + /* was a particular bus/slot requested? */ + if (it->options[0] || it->options[1]) { + /* are we on the wrong bus/slot? */ + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != + it->options[1]) { + continue; + } + } + ret = CheckAndAllocCard(dev, it, pcidev); + if (ret != 1) continue; + dev->board_ptr = boardtypes + i; + break; + } + if (dev->board_ptr) + break; + } + + if (!dev->board_ptr) { + rt_printk + (", Error: Requested type of the card was not found!\n"); + return -EIO; + } + + if (comedi_pci_enable(pcidev, driver_pci_dio.driver_name)) { + rt_printk + (", Error: Can't enable PCI device and request regions!\n"); + return -EIO; + } + iobase = pci_resource_start(pcidev, this_board->main_pci_region); + rt_printk(", b:s:f=%d:%d:%d, io=0x%4lx", + pcidev->bus->number, PCI_SLOT(pcidev->devfn), + PCI_FUNC(pcidev->devfn), iobase); + + dev->iobase = iobase; + dev->board_name = this_board->name; + + if (this_board->cardtype == TYPE_PCI1760) { + n_subdevices = 4; /* 8 IDI, 8 IDO, 2 PWM, 8 CNT */ + } else { + n_subdevices = 0; + for (i = 0; i < MAX_DI_SUBDEVS; i++) + if (this_board->sdi[i].chans) + n_subdevices++; + for (i = 0; i < MAX_DO_SUBDEVS; i++) + if (this_board->sdo[i].chans) + n_subdevices++; + for (i = 0; i < MAX_DIO_SUBDEVG; i++) + n_subdevices += this_board->sdio[i].regs; + if (this_board->boardid.chans) + n_subdevices++; + } + + if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) { + rt_printk(", Error: Cann't allocate subdevice memory!\n"); + return ret; + } + + rt_printk(".\n"); + + subdev = 0; + + for (i = 0; i < MAX_DI_SUBDEVS; i++) + if (this_board->sdi[i].chans) { + s = dev->subdevices + subdev; + pci_dio_add_di(dev, s, &this_board->sdi[i], subdev); + subdev++; + } + + for (i = 0; i < MAX_DO_SUBDEVS; i++) + if (this_board->sdo[i].chans) { + s = dev->subdevices + subdev; + pci_dio_add_do(dev, s, &this_board->sdo[i], subdev); + subdev++; + } + + for (i = 0; i < MAX_DIO_SUBDEVG; i++) + for (j = 0; j < this_board->sdio[i].regs; j++) { + s = dev->subdevices + subdev; + subdev_8255_init(dev, s, NULL, + dev->iobase + this_board->sdio[i].addr + + SIZE_8255 * j); + subdev++; + } + + if (this_board->boardid.chans) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DI; + pci_dio_add_di(dev, s, &this_board->boardid, subdev); + subdev++; + } + + if (this_board->cardtype == TYPE_PCI1760) + pci1760_attach(dev, it); + + devpriv->valid = 1; + + pci_dio_reset(dev); + + return 0; +} + +/* +============================================================================== +*/ +static int pci_dio_detach(struct comedi_device * dev) +{ + int i, j; + struct comedi_subdevice *s; + int subdev; + + if (dev->private) { + if (devpriv->valid) { + pci_dio_reset(dev); + } + + /* This shows the silliness of using this kind of + * scheme for numbering subdevices. Don't do it. --ds */ + subdev = 0; + for (i = 0; i < MAX_DI_SUBDEVS; i++) { + if (this_board->sdi[i].chans) { + subdev++; + } + } + for (i = 0; i < MAX_DO_SUBDEVS; i++) { + if (this_board->sdo[i].chans) { + subdev++; + } + } + for (i = 0; i < MAX_DIO_SUBDEVG; i++) { + for (j = 0; j < this_board->sdio[i].regs; j++) { + s = dev->subdevices + subdev; + subdev_8255_cleanup(dev, s); + subdev++; + } + } + + for (i = 0; i < dev->n_subdevices; i++) { + s = dev->subdevices + i; + s->private = NULL; + } + + if (devpriv->pcidev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pcidev); + } + pci_dev_put(devpriv->pcidev); + } + + if (devpriv->prev) { + devpriv->prev->next = devpriv->next; + } else { + pci_priv = devpriv->next; + } + if (devpriv->next) { + devpriv->next->prev = devpriv->prev; + } + } + + return 0; +} + +/* +============================================================================== +*/ +COMEDI_PCI_INITCLEANUP(driver_pci_dio, pci_dio_pci_table); +/* +============================================================================== +*/ diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c new file mode 100644 index 000000000000..b97b4d82611b --- /dev/null +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -0,0 +1,226 @@ +/* + + comedi/drivers/aio_aio12_8.c + + Driver for Acces I/O Products PC-104 AIO12-8 Analog I/O Board + Copyright (C) 2006 C&C Technologies, Inc. + + 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: aio_aio12_8 +Description: Acces I/O Products PC-104 AIO12-8 Analog I/O Board +Author: Pablo Mejia +Devices: + [Acces I/O] PC-104 AIO12-8 +Status: experimental + +Configuration Options: + [0] - I/O port base address + +Notes: + + Only synchronous operations are supported. + +*/ + +#include "../comedidev.h" +#include +#include "8255.h" + +#define AIO12_8_STATUS 0x00 +#define AIO12_8_INTERRUPT 0x01 +#define AIO12_8_ADC 0x02 +#define AIO12_8_DAC_0 0x04 +#define AIO12_8_DAC_1 0x06 +#define AIO12_8_DAC_2 0x08 +#define AIO12_8_DAC_3 0x0A +#define AIO12_8_COUNTER_0 0x0C +#define AIO12_8_COUNTER_1 0x0D +#define AIO12_8_COUNTER_2 0x0E +#define AIO12_8_COUNTER_CONTROL 0x0F +#define AIO12_8_DIO_0 0x10 +#define AIO12_8_DIO_1 0x11 +#define AIO12_8_DIO_2 0x12 +#define AIO12_8_DIO_STATUS 0x13 +#define AIO12_8_DIO_CONTROL 0x14 +#define AIO12_8_ADC_TRIGGER_CONTROL 0x15 +#define AIO12_8_TRIGGER 0x16 +#define AIO12_8_POWER 0x17 + +#define STATUS_ADC_EOC 0x80 + +#define ADC_MODE_NORMAL 0x00 +#define ADC_MODE_INTERNAL_CLOCK 0x40 +#define ADC_MODE_STANDBY 0x80 +#define ADC_MODE_POWERDOWN 0xC0 + +#define DAC_ENABLE 0x18 + +struct aio12_8_boardtype { + const char *name; +}; + +static const struct aio12_8_boardtype board_types[] = { + { + name: "aio_aio12_8"}, +}; + +#define thisboard ((const struct aio12_8_boardtype *) dev->board_ptr) + +struct aio12_8_private { + unsigned int ao_readback[4]; +}; + +#define devpriv ((struct aio12_8_private *) dev->private) + +static int aio_aio12_8_ai_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + unsigned char control = + ADC_MODE_NORMAL | + (CR_RANGE(insn->chanspec) << 3) | CR_CHAN(insn->chanspec); + + //read status to clear EOC latch + inb(dev->iobase + AIO12_8_STATUS); + + for (n = 0; n < insn->n; n++) { + int timeout = 5; + + // Setup and start conversion + outb(control, dev->iobase + AIO12_8_ADC); + + // Wait for conversion to complete + while (timeout && + !(inb(dev->iobase + AIO12_8_STATUS) & STATUS_ADC_EOC)) { + timeout--; + printk("timeout %d\n", timeout); + comedi_udelay(1); + } + if (timeout == 0) { + comedi_error(dev, "ADC timeout"); + return -EIO; + } + + data[n] = inw(dev->iobase + AIO12_8_ADC) & 0x0FFF; + } + return n; +} + +static int aio_aio12_8_ao_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int val = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; + + for (i = 0; i < insn->n; i++) + data[i] = val; + return insn->n; +} + +static int aio_aio12_8_ao_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + unsigned long port = dev->iobase + AIO12_8_DAC_0 + (2 * chan); + + //enable DACs + outb(0x01, dev->iobase + DAC_ENABLE); + + for (i = 0; i < insn->n; i++) { + outb(data[i] & 0xFF, port); // LSB + outb((data[i] >> 8) & 0x0F, port + 1); // MSB + devpriv->ao_readback[chan] = data[i]; + } + return insn->n; +} + +static const struct comedi_lrange range_aio_aio12_8 = { + 4, + { + UNI_RANGE(5), + BIP_RANGE(5), + UNI_RANGE(10), + BIP_RANGE(10), + } +}; + +static int aio_aio12_8_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int iobase; + struct comedi_subdevice *s; + + iobase = it->options[0]; + if (!request_region(iobase, 24, "aio_aio12_8")) { + printk("I/O port conflict"); + return -EIO; + } + + dev->board_name = thisboard->name; + + dev->iobase = iobase; + + if (alloc_private(dev, sizeof(struct aio12_8_private)) < 0) + return -ENOMEM; + + if (alloc_subdevices(dev, 3) < 0) + return -ENOMEM; + + s = &dev->subdevices[0]; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; + s->n_chan = 8; + s->maxdata = (1 << 12) - 1; + s->range_table = &range_aio_aio12_8; + s->insn_read = aio_aio12_8_ai_read; + + s = &dev->subdevices[1]; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_DIFF; + s->n_chan = 4; + s->maxdata = (1 << 12) - 1; + s->range_table = &range_aio_aio12_8; + s->insn_read = aio_aio12_8_ao_read; + s->insn_write = aio_aio12_8_ao_write; + + s = &dev->subdevices[2]; + subdev_8255_init(dev, s, NULL, dev->iobase + AIO12_8_DIO_0); + + return 0; +} + +static int aio_aio12_8_detach(struct comedi_device * dev) +{ + subdev_8255_cleanup(dev, &dev->subdevices[2]); + if (dev->iobase) + release_region(dev->iobase, 24); + return 0; +} + +static struct comedi_driver driver_aio_aio12_8 = { + driver_name:"aio_aio12_8", + module:THIS_MODULE, + attach:aio_aio12_8_attach, + detach:aio_aio12_8_detach, + board_name:&board_types[0].name, + num_names:1, + offset:sizeof(struct aio12_8_boardtype), +}; + +COMEDI_INITCLEANUP(driver_aio_aio12_8); diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c new file mode 100644 index 000000000000..9160fdf0ca37 --- /dev/null +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -0,0 +1,177 @@ +/* + + comedi/drivers/aio_iiro_16.c + + Driver for Acces I/O Products PC-104 AIO-IIRO-16 Digital I/O board + Copyright (C) 2006 C&C Technologies, Inc. + + 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: aio_iiro_16 +Description: Acces I/O Products PC-104 IIRO16 Relay And Isolated Input Board +Author: Zachary Ware +Devices: + [Acces I/O] PC-104 AIO12-8 +Status: experimental + +Configuration Options: + [0] - I/O port base address + +*/ + +#include "../comedidev.h" +#include + +#define AIO_IIRO_16_SIZE 0x08 +#define AIO_IIRO_16_RELAY_0_7 0x00 +#define AIO_IIRO_16_INPUT_0_7 0x01 +#define AIO_IIRO_16_IRQ 0x02 +#define AIO_IIRO_16_RELAY_8_15 0x04 +#define AIO_IIRO_16_INPUT_8_15 0x05 + +struct aio_iiro_16_board { + const char *name; + int do_; + int di; +}; + +static const struct aio_iiro_16_board aio_iiro_16_boards[] = { + { + name: "aio_iiro_16", + di: 16, + do_: 16}, +}; + +#define thisboard ((const struct aio_iiro_16_board *) dev->board_ptr) + +struct aio_iiro_16_private { + int data; + struct pci_dev *pci_dev; + unsigned int ao_readback[2]; +}; + +#define devpriv ((struct aio_iiro_16_private *) dev->private) + +static int aio_iiro_16_attach(struct comedi_device * dev, struct comedi_devconfig * it); + +static int aio_iiro_16_detach(struct comedi_device * dev); + +static struct comedi_driver driver_aio_iiro_16 = { + driver_name:"aio_iiro_16", + module:THIS_MODULE, + attach:aio_iiro_16_attach, + detach:aio_iiro_16_detach, + board_name:&aio_iiro_16_boards[0].name, + offset:sizeof(struct aio_iiro_16_board), + num_names:sizeof(aio_iiro_16_boards) / sizeof(struct aio_iiro_16_board), +}; + +static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +static int aio_iiro_16_dio_insn_bits_write(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +static int aio_iiro_16_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int iobase; + struct comedi_subdevice *s; + + printk("comedi%d: aio_iiro_16: ", dev->minor); + + dev->board_name = thisboard->name; + + iobase = it->options[0]; + + if (!request_region(iobase, AIO_IIRO_16_SIZE, dev->board_name)) { + printk("I/O port conflict"); + return -EIO; + } + + dev->iobase = iobase; + + if (alloc_private(dev, sizeof(struct aio_iiro_16_private)) < 0) + return -ENOMEM; + + if (alloc_subdevices(dev, 2) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = aio_iiro_16_dio_insn_bits_write; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = aio_iiro_16_dio_insn_bits_read; + + printk("attached\n"); + + return 1; +} + +static int aio_iiro_16_detach(struct comedi_device * dev) +{ + printk("comedi%d: aio_iiro_16: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, AIO_IIRO_16_SIZE); + + return 0; +} + +static int aio_iiro_16_dio_insn_bits_write(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]; + outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7); + outb((s->state >> 8) & 0xff, + dev->iobase + AIO_IIRO_16_RELAY_8_15); + } + + data[1] = s->state; + + return 2; +} + +static int aio_iiro_16_dio_insn_bits_read(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + data[1] = 0; + data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7); + data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8; + + return 2; +} + +COMEDI_INITCLEANUP(driver_aio_iiro_16); diff --git a/drivers/staging/comedi/drivers/am9513.h b/drivers/staging/comedi/drivers/am9513.h new file mode 100644 index 000000000000..f533cf1658cf --- /dev/null +++ b/drivers/staging/comedi/drivers/am9513.h @@ -0,0 +1,79 @@ +/* + module/am9513.h + value added preprocessor definitions for Am9513 timer chip + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998 David A. Schleef + + 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 _AM9513_H_ +#define _AM9513_H_ + +#if 0 + +/* + * Before including this file, the following need to be defined: + */ +#define Am9513_8BITBUS xxx +/* or */ +#define Am9513_16BITBUS xxx + +#define Am9513_output_control(a) xxx +#define Am9513_input_status() xxx +#define Am9513_output_data(a) xxx +#define Am9513_input_data() xxx + +#endif + +/* + * + */ + +#ifdef Am9513_8BITBUS + +#define Am9513_write_register(reg,val) \ + do{ \ + Am9513_output_control(reg); \ + Am9513_output_data(val>>8); \ + Am9513_output_data(val&0xff); \ + }while(0) + +#define Am9513_read_register(reg,val) \ + do{ \ + Am9513_output_control(reg); \ + val=Am9513_input_data()<<8; \ + val|=Am9513_input_data(); \ + }while(0) + +#else /* Am9513_16BITBUS */ + +#define Am9513_write_register(reg,val) \ + do{ \ + Am9513_output_control(reg); \ + Am9513_output_data(val); \ + }while(0) + +#define Am9513_read_register(reg,val) \ + do{ \ + Am9513_output_control(reg); \ + val=Am9513_input_data(); \ + }while(0) + +#endif + +#endif diff --git a/drivers/staging/comedi/drivers/amcc_s5933.h b/drivers/staging/comedi/drivers/amcc_s5933.h new file mode 100644 index 000000000000..aceffce7ef3f --- /dev/null +++ b/drivers/staging/comedi/drivers/amcc_s5933.h @@ -0,0 +1,172 @@ +/* + comedi/drivers/amcc_s5933.h + + Stuff for AMCC S5933 PCI Controller + + Author: Michal Dobes + + Inspirated from general-purpose AMCC S5933 PCI Matchmaker driver + made by Andrea Cisternino + and as result of espionage from MITE code made by David A. Schleef. + Thanks to AMCC for their on-line documentation and bus master DMA + example. +*/ + +#ifndef _AMCC_S5933_H_ +#define _AMCC_S5933_H_ + +/****************************************************************************/ +/* AMCC Operation Register Offsets - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_OMB1 0x00 +#define AMCC_OP_REG_OMB2 0x04 +#define AMCC_OP_REG_OMB3 0x08 +#define AMCC_OP_REG_OMB4 0x0c +#define AMCC_OP_REG_IMB1 0x10 +#define AMCC_OP_REG_IMB2 0x14 +#define AMCC_OP_REG_IMB3 0x18 +#define AMCC_OP_REG_IMB4 0x1c +#define AMCC_OP_REG_FIFO 0x20 +#define AMCC_OP_REG_MWAR 0x24 +#define AMCC_OP_REG_MWTC 0x28 +#define AMCC_OP_REG_MRAR 0x2c +#define AMCC_OP_REG_MRTC 0x30 +#define AMCC_OP_REG_MBEF 0x34 +#define AMCC_OP_REG_INTCSR 0x38 +#define AMCC_OP_REG_INTCSR_SRC (AMCC_OP_REG_INTCSR + 2) /* INT source */ +#define AMCC_OP_REG_INTCSR_FEC (AMCC_OP_REG_INTCSR + 3) /* FIFO ctrl */ +#define AMCC_OP_REG_MCSR 0x3c +#define AMCC_OP_REG_MCSR_NVDATA (AMCC_OP_REG_MCSR + 2) /* Data in byte 2 */ +#define AMCC_OP_REG_MCSR_NVCMD (AMCC_OP_REG_MCSR + 3) /* Command in byte 3 */ + +#define AMCC_FIFO_DEPTH_DWORD 8 +#define AMCC_FIFO_DEPTH_BYTES (8 * sizeof (u32)) + +/****************************************************************************/ +/* AMCC - PCI Interrupt Control/Status Register */ +/****************************************************************************/ +#define INTCSR_OUTBOX_BYTE(x) ((x) & 0x3) +#define INTCSR_OUTBOX_SELECT(x) (((x) & 0x3) << 2) +#define INTCSR_OUTBOX_EMPTY_INT 0x10 // enable outbox empty interrupt +#define INTCSR_INBOX_BYTE(x) (((x) & 0x3) << 8) +#define INTCSR_INBOX_SELECT(x) (((x) & 0x3) << 10) +#define INTCSR_INBOX_FULL_INT 0x1000 // enable inbox full interrupt +#define INTCSR_INBOX_INTR_STATUS 0x20000 // read, or write clear inbox full interrupt +#define INTCSR_INTR_ASSERTED 0x800000 // read only, interrupt asserted + +/****************************************************************************/ +/* AMCC - PCI non-volatile ram command register (byte 3 of master control/status register) */ +/****************************************************************************/ +#define MCSR_NV_LOAD_LOW_ADDR 0x0 +#define MCSR_NV_LOAD_HIGH_ADDR 0x20 +#define MCSR_NV_WRITE 0x40 +#define MCSR_NV_READ 0x60 +#define MCSR_NV_MASK 0x60 +#define MCSR_NV_ENABLE 0x80 +#define MCSR_NV_BUSY MCSR_NV_ENABLE + +/****************************************************************************/ +/* AMCC Operation Registers Size - PCI */ +/****************************************************************************/ + +#define AMCC_OP_REG_SIZE 64 /* in bytes */ + +/****************************************************************************/ +/* AMCC Operation Register Offsets - Add-on */ +/****************************************************************************/ + +#define AMCC_OP_REG_AIMB1 0x00 +#define AMCC_OP_REG_AIMB2 0x04 +#define AMCC_OP_REG_AIMB3 0x08 +#define AMCC_OP_REG_AIMB4 0x0c +#define AMCC_OP_REG_AOMB1 0x10 +#define AMCC_OP_REG_AOMB2 0x14 +#define AMCC_OP_REG_AOMB3 0x18 +#define AMCC_OP_REG_AOMB4 0x1c +#define AMCC_OP_REG_AFIFO 0x20 +#define AMCC_OP_REG_AMWAR 0x24 +#define AMCC_OP_REG_APTA 0x28 +#define AMCC_OP_REG_APTD 0x2c +#define AMCC_OP_REG_AMRAR 0x30 +#define AMCC_OP_REG_AMBEF 0x34 +#define AMCC_OP_REG_AINT 0x38 +#define AMCC_OP_REG_AGCSTS 0x3c +#define AMCC_OP_REG_AMWTC 0x58 +#define AMCC_OP_REG_AMRTC 0x5c + +/****************************************************************************/ +/* AMCC - Add-on General Control/Status Register */ +/****************************************************************************/ + +#define AGCSTS_CONTROL_MASK 0xfffff000 +#define AGCSTS_NV_ACC_MASK 0xe0000000 +#define AGCSTS_RESET_MASK 0x0e000000 +#define AGCSTS_NV_DA_MASK 0x00ff0000 +#define AGCSTS_BIST_MASK 0x0000f000 +#define AGCSTS_STATUS_MASK 0x000000ff +#define AGCSTS_TCZERO_MASK 0x000000c0 +#define AGCSTS_FIFO_ST_MASK 0x0000003f + +#define AGCSTS_RESET_MBFLAGS 0x08000000 +#define AGCSTS_RESET_P2A_FIFO 0x04000000 +#define AGCSTS_RESET_A2P_FIFO 0x02000000 +#define AGCSTS_RESET_FIFOS (AGCSTS_RESET_A2P_FIFO | AGCSTS_RESET_P2A_FIFO) + +#define AGCSTS_A2P_TCOUNT 0x00000080 +#define AGCSTS_P2A_TCOUNT 0x00000040 + +#define AGCSTS_FS_P2A_EMPTY 0x00000020 +#define AGCSTS_FS_P2A_HALF 0x00000010 +#define AGCSTS_FS_P2A_FULL 0x00000008 + +#define AGCSTS_FS_A2P_EMPTY 0x00000004 +#define AGCSTS_FS_A2P_HALF 0x00000002 +#define AGCSTS_FS_A2P_FULL 0x00000001 + +/****************************************************************************/ +/* AMCC - Add-on Interrupt Control/Status Register */ +/****************************************************************************/ + +#define AINT_INT_MASK 0x00ff0000 +#define AINT_SEL_MASK 0x0000ffff +#define AINT_IS_ENSEL_MASK 0x00001f1f + +#define AINT_INT_ASSERTED 0x00800000 +#define AINT_BM_ERROR 0x00200000 +#define AINT_BIST_INT 0x00100000 + +#define AINT_RT_COMPLETE 0x00080000 +#define AINT_WT_COMPLETE 0x00040000 + +#define AINT_OUT_MB_INT 0x00020000 +#define AINT_IN_MB_INT 0x00010000 + +#define AINT_READ_COMPL 0x00008000 +#define AINT_WRITE_COMPL 0x00004000 + +#define AINT_OMB_ENABLE 0x00001000 +#define AINT_OMB_SELECT 0x00000c00 +#define AINT_OMB_BYTE 0x00000300 + +#define AINT_IMB_ENABLE 0x00000010 +#define AINT_IMB_SELECT 0x0000000c +#define AINT_IMB_BYTE 0x00000003 + +// these are bits from various different registers, needs cleanup XXX +/* Enable Bus Mastering */ +#define EN_A2P_TRANSFERS 0x00000400 +/* FIFO Flag Reset */ +#define RESET_A2P_FLAGS 0x04000000L +/* FIFO Relative Priority */ +#define A2P_HI_PRIORITY 0x00000100L +/* Identify Interrupt Sources */ +#define ANY_S593X_INT 0x00800000L +#define READ_TC_INT 0x00080000L +#define WRITE_TC_INT 0x00040000L +#define IN_MB_INT 0x00020000L +#define MASTER_ABORT_INT 0x00100000L +#define TARGET_ABORT_INT 0x00200000L +#define BUS_MASTER_INT 0x00200000L + +#endif diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c new file mode 100644 index 000000000000..8555e272a861 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -0,0 +1,1483 @@ +/* + comedi/drivers/amplc_dio200.c + Driver for Amplicon PC272E and PCI272 DIO boards. + (Support for other boards in Amplicon 200 series may be added at + a later date, e.g. PCI215.) + + Copyright (C) 2005 MEV Ltd. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998,2000 David A. Schleef + + 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: amplc_dio200 +Description: Amplicon 200 Series Digital I/O +Author: Ian Abbott +Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e), + PCI215 (pci215 or amplc_dio200), PC218E (pc218e), PC272E (pc272e), + PCI272 (pci272 or amplc_dio200) +Updated: Wed, 22 Oct 2008 13:36:02 +0100 +Status: works + +Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E: + [0] - I/O port base address + [1] - IRQ (optional, but commands won't work without it) + +Configuration options - PCI215, PCI272: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first available PCI device will + be used. + +Passing a zero for an option is the same as leaving it unspecified. + +SUBDEVICES + + PC218E PC212E PC215E/PCI215 + ------------- ------------- ------------- + Subdevices 7 6 5 + 0 CTR-X1 PPI-X PPI-X + 1 CTR-X2 CTR-Y1 PPI-Y + 2 CTR-Y1 CTR-Y2 CTR-Z1 + 3 CTR-Y2 CTR-Z1 CTR-Z2 + 4 CTR-Z1 CTR-Z2 INTERRUPT + 5 CTR-Z2 INTERRUPT + 6 INTERRUPT + + PC214E PC272E/PCI272 + ------------- ------------- + Subdevices 4 4 + 0 PPI-X PPI-X + 1 PPI-Y PPI-Y + 2 CTR-Z1* PPI-Z + 3 INTERRUPT* INTERRUPT + +Each PPI is a 8255 chip providing 24 DIO channels. The DIO channels +are configurable as inputs or outputs in four groups: + + Port A - channels 0 to 7 + Port B - channels 8 to 15 + Port CL - channels 16 to 19 + Port CH - channels 20 to 23 + +Only mode 0 of the 8255 chips is supported. + +Each CTR is a 8254 chip providing 3 16-bit counter channels. Each +channel is configured individually with INSN_CONFIG instructions. The +specific type of configuration instruction is specified in data[0]. +Some configuration instructions expect an additional parameter in +data[1]; others return a value in data[1]. The following configuration +instructions are supported: + + INSN_CONFIG_SET_COUNTER_MODE. Sets the counter channel's mode and + BCD/binary setting specified in data[1]. + + INSN_CONFIG_8254_READ_STATUS. Reads the status register value for the + counter channel into data[1]. + + INSN_CONFIG_SET_CLOCK_SRC. Sets the counter channel's clock source as + specified in data[1] (this is a hardware-specific value). Not + supported on PC214E. For the other boards, valid clock sources are + 0 to 7 as follows: + + 0. CLK n, the counter channel's dedicated CLK input from the SK1 + connector. (N.B. for other values, the counter channel's CLKn + pin on the SK1 connector is an output!) + 1. Internal 10 MHz clock. + 2. Internal 1 MHz clock. + 3. Internal 100 kHz clock. + 4. Internal 10 kHz clock. + 5. Internal 1 kHz clock. + 6. OUT n-1, the output of counter channel n-1 (see note 1 below). + 7. Ext Clock, the counter chip's dedicated Ext Clock input from + the SK1 connector. This pin is shared by all three counter + channels on the chip. + + INSN_CONFIG_GET_CLOCK_SRC. Returns the counter channel's current + clock source in data[1]. For internal clock sources, data[2] is set + to the period in ns. + + INSN_CONFIG_SET_GATE_SRC. Sets the counter channel's gate source as + specified in data[2] (this is a hardware-specific value). Not + supported on PC214E. For the other boards, valid gate sources are 0 + to 7 as follows: + + 0. VCC (internal +5V d.c.), i.e. gate permanently enabled. + 1. GND (internal 0V d.c.), i.e. gate permanently disabled. + 2. GAT n, the counter channel's dedicated GAT input from the SK1 + connector. (N.B. for other values, the counter channel's GATn + pin on the SK1 connector is an output!) + 3. /OUT n-2, the inverted output of counter channel n-2 (see note + 2 below). + 4. Reserved. + 5. Reserved. + 6. Reserved. + 7. Reserved. + + INSN_CONFIG_GET_GATE_SRC. Returns the counter channel's current gate + source in data[2]. + +Clock and gate interconnection notes: + + 1. Clock source OUT n-1 is the output of the preceding channel on the + same counter subdevice if n > 0, or the output of channel 2 on the + preceding counter subdevice (see note 3) if n = 0. + + 2. Gate source /OUT n-2 is the inverted output of channel 0 on the + same counter subdevice if n = 2, or the inverted output of channel n+1 + on the preceding counter subdevice (see note 3) if n < 2. + + 3. The counter subdevices are connected in a ring, so the highest + counter subdevice precedes the lowest. + +The 'INTERRUPT' subdevice pretends to be a digital input subdevice. The +digital inputs come from the interrupt status register. The number of +channels matches the number of interrupt sources. The PC214E does not +have an interrupt status register; see notes on 'INTERRUPT SOURCES' +below. + +INTERRUPT SOURCES + + PC218E PC212E PC215E/PCI215 + ------------- ------------- ------------- + Sources 6 6 6 + 0 CTR-X1-OUT PPI-X-C0 PPI-X-C0 + 1 CTR-X2-OUT PPI-X-C3 PPI-X-C3 + 2 CTR-Y1-OUT CTR-Y1-OUT PPI-Y-C0 + 3 CTR-Y2-OUT CTR-Y2-OUT PPI-Y-C3 + 4 CTR-Z1-OUT CTR-Z1-OUT CTR-Z1-OUT + 5 CTR-Z2-OUT CTR-Z2-OUT CTR-Z2-OUT + + PC214E PC272E/PCI272 + ------------- ------------- + Sources 1 6 + 0 JUMPER-J5 PPI-X-C0 + 1 PPI-X-C3 + 2 PPI-Y-C0 + 3 PPI-Y-C3 + 4 PPI-Z-C0 + 5 PPI-Z-C3 + +When an interrupt source is enabled in the interrupt source enable +register, a rising edge on the source signal latches the corresponding +bit to 1 in the interrupt status register. + +When the interrupt status register value as a whole (actually, just the +6 least significant bits) goes from zero to non-zero, the board will +generate an interrupt. For level-triggered hardware interrupts (PCI +card), the interrupt will remain asserted until the interrupt status +register is cleared to zero. For edge-triggered hardware interrupts +(ISA card), no further interrupts will occur until the interrupt status +register is cleared to zero. To clear a bit to zero in the interrupt +status register, the corresponding interrupt source must be disabled +in the interrupt source enable register (there is no separate interrupt +clear register). + +The PC214E does not have an interrupt source enable register or an +interrupt status register; its 'INTERRUPT' subdevice has a single +channel and its interrupt source is selected by the position of jumper +J5. + +COMMANDS + +The driver supports a read streaming acquisition command on the +'INTERRUPT' subdevice. The channel list selects the interrupt sources +to be enabled. All channels will be sampled together (convert_src == +TRIG_NOW). The scan begins a short time after the hardware interrupt +occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT, +scan_begin_arg == 0). The value read from the interrupt status register +is packed into a short value, one bit per requested channel, in the +order they appear in the channel list. +*/ + +#include "../comedidev.h" + +#include "comedi_pci.h" + +#include "8255.h" +#include "8253.h" + +#define DIO200_DRIVER_NAME "amplc_dio200" + +/* PCI IDs */ +/* #define PCI_VENDOR_ID_AMPLICON 0x14dc */ +#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a +#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b +#define PCI_DEVICE_ID_INVALID 0xffff + +/* 200 series registers */ +#define DIO200_IO_SIZE 0x20 +#define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */ +#define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */ +#define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */ +#define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */ +#define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */ +#define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */ +#define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */ + +/* + * Macros for constructing value for DIO_200_?CLK_SCE and + * DIO_200_?GAT_SCE registers: + * + * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2. + * 'chan' is the channel: 0, 1 or 2. + * 'source' is the signal source: 0 to 7. + */ +#define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source)) +#define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source)) + +/* + * Periods of the internal clock sources in nanoseconds. + */ +static const unsigned clock_period[8] = { + 0, /* dedicated clock input/output pin */ + 100, /* 10 MHz */ + 1000, /* 1 MHz */ + 10000, /* 100 kHz */ + 100000, /* 10 kHz */ + 1000000, /* 1 kHz */ + 0, /* OUT N-1 */ + 0 /* group clock input pin */ +}; + +/* + * Board descriptions. + */ + +enum dio200_bustype { isa_bustype, pci_bustype }; + +enum dio200_model { + pc212e_model, + pc214e_model, + pc215e_model, pci215_model, + pc218e_model, + pc272e_model, pci272_model, + anypci_model +}; + +enum dio200_layout { + pc212_layout, + pc214_layout, + pc215_layout, + pc218_layout, + pc272_layout +}; + +struct dio200_board { + const char *name; + unsigned short devid; + enum dio200_bustype bustype; + enum dio200_model model; + enum dio200_layout layout; +}; + +static const struct dio200_board dio200_boards[] = { + { + name: "pc212e", + bustype: isa_bustype, + model: pc212e_model, + layout: pc212_layout, + }, + { + name: "pc214e", + bustype: isa_bustype, + model: pc214e_model, + layout: pc214_layout, + }, + { + name: "pc215e", + bustype: isa_bustype, + model: pc215e_model, + layout: pc215_layout, + }, +#ifdef CONFIG_COMEDI_PCI + { + name: "pci215", + devid: PCI_DEVICE_ID_AMPLICON_PCI215, + bustype: pci_bustype, + model: pci215_model, + layout: pc215_layout, + }, +#endif + { + name: "pc218e", + bustype: isa_bustype, + model: pc218e_model, + layout: pc218_layout, + }, + { + name: "pc272e", + bustype: isa_bustype, + model: pc272e_model, + layout: pc272_layout, + }, +#ifdef CONFIG_COMEDI_PCI + { + name: "pci272", + devid: PCI_DEVICE_ID_AMPLICON_PCI272, + bustype: pci_bustype, + model: pci272_model, + layout: pc272_layout, + }, +#endif +#ifdef CONFIG_COMEDI_PCI + { + name: DIO200_DRIVER_NAME, + devid: PCI_DEVICE_ID_INVALID, + bustype: pci_bustype, + model: anypci_model, /* wildcard */ + }, +#endif +}; + +/* + * Layout descriptions - some ISA and PCI board descriptions share the same + * layout. + */ + +enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 }; + +#define DIO200_MAX_SUBDEVS 7 +#define DIO200_MAX_ISNS 6 + +struct dio200_layout_struct { + unsigned short n_subdevs; /* number of subdevices */ + unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */ + unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */ + char has_int_sce; /* has interrupt enable/status register */ + char has_clk_gat_sce; /* has clock/gate selection registers */ +}; + +static const struct dio200_layout_struct dio200_layouts[] = { + [pc212_layout] = { + n_subdevs:6, + sdtype: {sd_8255, sd_8254, sd_8254, sd_8254, + sd_8254, + sd_intr}, + sdinfo: {0x00, 0x08, 0x0C, 0x10, 0x14, + 0x3F}, + has_int_sce:1, + has_clk_gat_sce:1, + }, + [pc214_layout] = { + n_subdevs:4, + sdtype: {sd_8255, sd_8255, sd_8254, + sd_intr}, + sdinfo: {0x00, 0x08, 0x10, 0x01}, + has_int_sce:0, + has_clk_gat_sce:0, + }, + [pc215_layout] = { + n_subdevs:5, + sdtype: {sd_8255, sd_8255, sd_8254, + sd_8254, + sd_intr}, + sdinfo: {0x00, 0x08, 0x10, 0x14, 0x3F}, + has_int_sce:1, + has_clk_gat_sce:1, + }, + [pc218_layout] = { + n_subdevs:7, + sdtype: {sd_8254, sd_8254, sd_8255, sd_8254, + sd_8254, + sd_intr}, + sdinfo: {0x00, 0x04, 0x08, 0x0C, 0x10, + 0x14, + 0x3F}, + has_int_sce:1, + has_clk_gat_sce:1, + }, + [pc272_layout] = { + n_subdevs:4, + sdtype: {sd_8255, sd_8255, sd_8255, + sd_intr}, + sdinfo: {0x00, 0x08, 0x10, 0x3F}, + has_int_sce:1, + has_clk_gat_sce:0, + }, +}; + +/* + * PCI driver table. + */ + +#ifdef CONFIG_COMEDI_PCI +static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = { + {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, dio200_pci_table); +#endif /* CONFIG_COMEDI_PCI */ + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct dio200_board *)dev->board_ptr) +#define thislayout (&dio200_layouts[((struct dio200_board *)dev->board_ptr)->layout]) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct dio200_private { +#ifdef CONFIG_COMEDI_PCI + struct pci_dev *pci_dev; /* PCI device */ +#endif + int intr_sd; +}; + +#define devpriv ((struct dio200_private *)dev->private) + +struct dio200_subdev_8254 { + unsigned long iobase; /* Counter base address */ + unsigned long clk_sce_iobase; /* CLK_SCE base address */ + unsigned long gat_sce_iobase; /* GAT_SCE base address */ + int which; /* Bit 5 of CLK_SCE or GAT_SCE */ + int has_clk_gat_sce; + unsigned clock_src[3]; /* Current clock sources */ + unsigned gate_src[3]; /* Current gate sources */ +}; + +struct dio200_subdev_intr { + unsigned long iobase; + spinlock_t spinlock; + int active; + int has_int_sce; + unsigned int valid_isns; + unsigned int enabled_isns; + unsigned int stopcount; + int continuous; +}; + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dio200_detach(struct comedi_device * dev); +static struct comedi_driver driver_amplc_dio200 = { + driver_name:DIO200_DRIVER_NAME, + module:THIS_MODULE, + attach:dio200_attach, + detach:dio200_detach, + board_name:&dio200_boards[0].name, + offset:sizeof(struct dio200_board), + num_names:sizeof(dio200_boards) / sizeof(struct dio200_board), +}; + +#ifdef CONFIG_COMEDI_PCI +COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table); +#else +COMEDI_INITCLEANUP(driver_amplc_dio200); +#endif + +/* + * This function looks for a PCI device matching the requested board name, + * bus and slot. + */ +#ifdef CONFIG_COMEDI_PCI +static int +dio200_find_pci(struct comedi_device * dev, int bus, int slot, + struct pci_dev **pci_dev_p) +{ + struct pci_dev *pci_dev = NULL; + + *pci_dev_p = NULL; + + /* Look for matching PCI device. */ + for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL); + pci_dev != NULL; + pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, + PCI_ANY_ID, pci_dev)) { + /* If bus/slot specified, check them. */ + if (bus || slot) { + if (bus != pci_dev->bus->number + || slot != PCI_SLOT(pci_dev->devfn)) + continue; + } + if (thisboard->model == anypci_model) { + /* Match any supported model. */ + int i; + + for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) { + if (dio200_boards[i].bustype != pci_bustype) + continue; + if (pci_dev->device == dio200_boards[i].devid) { + /* Change board_ptr to matched board. */ + dev->board_ptr = &dio200_boards[i]; + break; + } + } + if (i == ARRAY_SIZE(dio200_boards)) + continue; + } else { + /* Match specific model name. */ + if (pci_dev->device != thisboard->devid) + continue; + } + + /* Found a match. */ + *pci_dev_p = pci_dev; + return 0; + } + /* No match found. */ + if (bus || slot) { + printk(KERN_ERR + "comedi%d: error! no %s found at pci %02x:%02x!\n", + dev->minor, thisboard->name, bus, slot); + } else { + printk(KERN_ERR "comedi%d: error! no %s found!\n", + dev->minor, thisboard->name); + } + return -EIO; +} +#endif + +/* + * This function checks and requests an I/O region, reporting an error + * if there is a conflict. + */ +static int +dio200_request_region(unsigned minor, unsigned long from, unsigned long extent) +{ + if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) { + printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", + minor, from, extent); + return -EIO; + } + return 0; +} + +/* + * 'insn_bits' function for an 'INTERRUPT' subdevice. + */ +static int +dio200_subdev_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct dio200_subdev_intr *subpriv = s->private; + + if (subpriv->has_int_sce) { + /* Just read the interrupt status register. */ + data[1] = inb(subpriv->iobase) & subpriv->valid_isns; + } else { + /* No interrupt status register. */ + data[0] = 0; + } + + return 2; +} + +/* + * Called to stop acquisition for an 'INTERRUPT' subdevice. + */ +static void dio200_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct dio200_subdev_intr *subpriv = s->private; + + subpriv->active = 0; + subpriv->enabled_isns = 0; + if (subpriv->has_int_sce) { + outb(0, subpriv->iobase); + } +} + +/* + * Called to start acquisition for an 'INTERRUPT' subdevice. + */ +static int dio200_start_intr(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned int n; + unsigned isn_bits; + struct dio200_subdev_intr *subpriv = s->private; + struct comedi_cmd *cmd = &s->async->cmd; + int retval = 0; + + if (!subpriv->continuous && subpriv->stopcount == 0) { + /* An empty acquisition! */ + s->async->events |= COMEDI_CB_EOA; + subpriv->active = 0; + retval = 1; + } else { + /* Determine interrupt sources to enable. */ + isn_bits = 0; + if (cmd->chanlist) { + for (n = 0; n < cmd->chanlist_len; n++) { + isn_bits |= (1U << CR_CHAN(cmd->chanlist[n])); + } + } + isn_bits &= subpriv->valid_isns; + /* Enable interrupt sources. */ + subpriv->enabled_isns = isn_bits; + if (subpriv->has_int_sce) { + outb(isn_bits, subpriv->iobase); + } + } + + return retval; +} + +/* + * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. + */ +static int +dio200_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ + struct dio200_subdev_intr *subpriv; + unsigned long flags; + int event = 0; + + if (trignum != 0) + return -EINVAL; + + subpriv = s->private; + + comedi_spin_lock_irqsave(&subpriv->spinlock, flags); + s->async->inttrig = 0; + if (subpriv->active) { + event = dio200_start_intr(dev, s); + } + comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags); + + if (event) { + comedi_event(dev, s); + } + + return 1; +} + +/* + * This is called from the interrupt service routine to handle a read + * scan on an 'INTERRUPT' subdevice. + */ +static int dio200_handle_read_intr(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct dio200_subdev_intr *subpriv = s->private; + unsigned triggered; + unsigned intstat; + unsigned cur_enabled; + unsigned int oldevents; + unsigned long flags; + + triggered = 0; + + comedi_spin_lock_irqsave(&subpriv->spinlock, flags); + oldevents = s->async->events; + if (subpriv->has_int_sce) { + /* + * Collect interrupt sources that have triggered and disable + * them temporarily. Loop around until no extra interrupt + * sources have triggered, at which point, the valid part of + * the interrupt status register will read zero, clearing the + * cause of the interrupt. + * + * Mask off interrupt sources already seen to avoid infinite + * loop in case of misconfiguration. + */ + cur_enabled = subpriv->enabled_isns; + while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns + & ~triggered)) != 0) { + triggered |= intstat; + cur_enabled &= ~triggered; + outb(cur_enabled, subpriv->iobase); + } + } else { + /* + * No interrupt status register. Assume the single interrupt + * source has triggered. + */ + triggered = subpriv->enabled_isns; + } + + if (triggered) { + /* + * Some interrupt sources have triggered and have been + * temporarily disabled to clear the cause of the interrupt. + * + * Reenable them NOW to minimize the time they are disabled. + */ + cur_enabled = subpriv->enabled_isns; + if (subpriv->has_int_sce) { + outb(cur_enabled, subpriv->iobase); + } + + if (subpriv->active) { + /* + * The command is still active. + * + * Ignore interrupt sources that the command isn't + * interested in (just in case there's a race + * condition). + */ + if (triggered & subpriv->enabled_isns) { + /* Collect scan data. */ + short val; + unsigned int n, ch, len; + + val = 0; + len = s->async->cmd.chanlist_len; + for (n = 0; n < len; n++) { + ch = CR_CHAN(s->async->cmd.chanlist[n]); + if (triggered & (1U << ch)) { + val |= (1U << n); + } + } + /* Write the scan to the buffer. */ + if (comedi_buf_put(s->async, val)) { + s->async->events |= (COMEDI_CB_BLOCK | + COMEDI_CB_EOS); + } else { + /* Error! Stop acquisition. */ + dio200_stop_intr(dev, s); + s->async->events |= COMEDI_CB_ERROR + | COMEDI_CB_OVERFLOW; + comedi_error(dev, "buffer overflow"); + } + + /* Check for end of acquisition. */ + if (!subpriv->continuous) { + /* stop_src == TRIG_COUNT */ + if (subpriv->stopcount > 0) { + subpriv->stopcount--; + if (subpriv->stopcount == 0) { + s->async->events |= + COMEDI_CB_EOA; + dio200_stop_intr(dev, + s); + } + } + } + } + } + } + comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags); + + if (oldevents != s->async->events) { + comedi_event(dev, s); + } + + return (triggered != 0); +} + +/* + * 'cancel' function for an 'INTERRUPT' subdevice. + */ +static int dio200_subdev_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct dio200_subdev_intr *subpriv = s->private; + unsigned long flags; + + comedi_spin_lock_irqsave(&subpriv->spinlock, flags); + if (subpriv->active) { + dio200_stop_intr(dev, s); + } + comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags); + + return 0; +} + +/* + * 'do_cmdtest' function for an 'INTERRUPT' subdevice. + */ +static int +dio200_subdev_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + unsigned int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= (TRIG_NOW | TRIG_INT); + 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_NOW; + 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_COUNT | TRIG_NONE); + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */ + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + /* cmd->scan_begin_src == TRIG_EXT */ + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + + /* cmd->convert_src == TRIG_NOW */ + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + + /* cmd->scan_end_src == TRIG_COUNT */ + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + switch (cmd->stop_src) { + case TRIG_COUNT: + /* any count allowed */ + break; + case TRIG_NONE: + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + break; + default: + break; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + /* if (err) return 4; */ + + return 0; +} + +/* + * 'do_cmd' function for an 'INTERRUPT' subdevice. + */ +static int dio200_subdev_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + struct dio200_subdev_intr *subpriv = s->private; + unsigned long flags; + int event = 0; + + comedi_spin_lock_irqsave(&subpriv->spinlock, flags); + subpriv->active = 1; + + /* Set up end of acquisition. */ + switch (cmd->stop_src) { + case TRIG_COUNT: + subpriv->continuous = 0; + subpriv->stopcount = cmd->stop_arg; + break; + default: + /* TRIG_NONE */ + subpriv->continuous = 1; + subpriv->stopcount = 0; + break; + } + + /* Set up start of acquisition. */ + switch (cmd->start_src) { + case TRIG_INT: + s->async->inttrig = dio200_inttrig_start_intr; + break; + default: + /* TRIG_NOW */ + event = dio200_start_intr(dev, s); + break; + } + comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags); + + if (event) { + comedi_event(dev, s); + } + + return 0; +} + +/* + * This function initializes an 'INTERRUPT' subdevice. + */ +static int +dio200_subdev_intr_init(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long iobase, unsigned valid_isns, int has_int_sce) +{ + struct dio200_subdev_intr *subpriv; + + subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); + if (!subpriv) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return -ENOMEM; + } + subpriv->iobase = iobase; + subpriv->has_int_sce = has_int_sce; + subpriv->valid_isns = valid_isns; + spin_lock_init(&subpriv->spinlock); + + if (has_int_sce) { + outb(0, subpriv->iobase); /* Disable interrupt sources. */ + } + + s->private = subpriv; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + if (has_int_sce) { + s->n_chan = DIO200_MAX_ISNS; + s->len_chanlist = DIO200_MAX_ISNS; + } else { + /* No interrupt source register. Support single channel. */ + s->n_chan = 1; + s->len_chanlist = 1; + } + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_bits = dio200_subdev_intr_insn_bits; + s->do_cmdtest = dio200_subdev_intr_cmdtest; + s->do_cmd = dio200_subdev_intr_cmd; + s->cancel = dio200_subdev_intr_cancel; + + return 0; +} + +/* + * This function cleans up an 'INTERRUPT' subdevice. + */ +static void +dio200_subdev_intr_cleanup(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct dio200_subdev_intr *subpriv = s->private; + + if (subpriv) { + kfree(subpriv); + } +} + +/* + * Interrupt service routine. + */ +static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + int handled; + + if (!dev->attached) { + return IRQ_NONE; + } + + if (devpriv->intr_sd >= 0) { + handled = dio200_handle_read_intr(dev, + dev->subdevices + devpriv->intr_sd); + } else { + handled = 0; + } + + return IRQ_RETVAL(handled); +} + +/* + * Handle 'insn_read' for an '8254' counter subdevice. + */ +static int +dio200_subdev_8254_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct dio200_subdev_8254 *subpriv = s->private; + int chan = CR_CHAN(insn->chanspec); + + data[0] = i8254_read(subpriv->iobase, 0, chan); + + return 1; +} + +/* + * Handle 'insn_write' for an '8254' counter subdevice. + */ +static int +dio200_subdev_8254_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct dio200_subdev_8254 *subpriv = s->private; + int chan = CR_CHAN(insn->chanspec); + + i8254_write(subpriv->iobase, 0, chan, data[0]); + + return 1; +} + +/* + * Set gate source for an '8254' counter subdevice channel. + */ +static int +dio200_set_gate_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number, + unsigned int gate_src) +{ + unsigned char byte; + + if (!subpriv->has_clk_gat_sce) + return -1; + if (counter_number > 2) + return -1; + if (gate_src > 7) + return -1; + + subpriv->gate_src[counter_number] = gate_src; + byte = GAT_SCE(subpriv->which, counter_number, gate_src); + outb(byte, subpriv->gat_sce_iobase); + + return 0; +} + +/* + * Get gate source for an '8254' counter subdevice channel. + */ +static int +dio200_get_gate_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number) +{ + if (!subpriv->has_clk_gat_sce) + return -1; + if (counter_number > 2) + return -1; + + return subpriv->gate_src[counter_number]; +} + +/* + * Set clock source for an '8254' counter subdevice channel. + */ +static int +dio200_set_clock_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number, + unsigned int clock_src) +{ + unsigned char byte; + + if (!subpriv->has_clk_gat_sce) + return -1; + if (counter_number > 2) + return -1; + if (clock_src > 7) + return -1; + + subpriv->clock_src[counter_number] = clock_src; + byte = CLK_SCE(subpriv->which, counter_number, clock_src); + outb(byte, subpriv->clk_sce_iobase); + + return 0; +} + +/* + * Get clock source for an '8254' counter subdevice channel. + */ +static int +dio200_get_clock_src(struct dio200_subdev_8254 * subpriv, unsigned int counter_number, + unsigned int * period_ns) +{ + unsigned clock_src; + + if (!subpriv->has_clk_gat_sce) + return -1; + if (counter_number > 2) + return -1; + + clock_src = subpriv->clock_src[counter_number]; + *period_ns = clock_period[clock_src]; + return clock_src; +} + +/* + * Handle 'insn_config' for an '8254' counter subdevice. + */ +static int +dio200_subdev_8254_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct dio200_subdev_8254 *subpriv = s->private; + int ret; + int chan = CR_CHAN(insn->chanspec); + + switch (data[0]) { + case INSN_CONFIG_SET_COUNTER_MODE: + ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]); + if (ret < 0) + return -EINVAL; + break; + case INSN_CONFIG_8254_READ_STATUS: + data[1] = i8254_status(subpriv->iobase, 0, chan); + break; + case INSN_CONFIG_SET_GATE_SRC: + ret = dio200_set_gate_src(subpriv, chan, data[2]); + if (ret < 0) + return -EINVAL; + break; + case INSN_CONFIG_GET_GATE_SRC: + ret = dio200_get_gate_src(subpriv, chan); + if (ret < 0) + return -EINVAL; + data[2] = ret; + break; + case INSN_CONFIG_SET_CLOCK_SRC: + ret = dio200_set_clock_src(subpriv, chan, data[1]); + if (ret < 0) + return -EINVAL; + break; + case INSN_CONFIG_GET_CLOCK_SRC: + ret = dio200_get_clock_src(subpriv, chan, &data[2]); + if (ret < 0) + return -EINVAL; + data[1] = ret; + break; + default: + return -EINVAL; + break; + } + return insn->n; +} + +/* + * This function initializes an '8254' counter subdevice. + * + * Note: iobase is the base address of the board, not the subdevice; + * offset is the offset to the 8254 chip. + */ +static int +dio200_subdev_8254_init(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long iobase, unsigned offset, int has_clk_gat_sce) +{ + struct dio200_subdev_8254 *subpriv; + unsigned int chan; + + subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); + if (!subpriv) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return -ENOMEM; + } + + s->private = subpriv; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 3; + s->maxdata = 0xFFFF; + s->insn_read = dio200_subdev_8254_read; + s->insn_write = dio200_subdev_8254_write; + s->insn_config = dio200_subdev_8254_config; + + subpriv->iobase = offset + iobase; + subpriv->has_clk_gat_sce = has_clk_gat_sce; + if (has_clk_gat_sce) { + /* Derive CLK_SCE and GAT_SCE register offsets from + * 8254 offset. */ + subpriv->clk_sce_iobase = + DIO200_XCLK_SCE + (offset >> 3) + iobase; + subpriv->gat_sce_iobase = + DIO200_XGAT_SCE + (offset >> 3) + iobase; + subpriv->which = (offset >> 2) & 1; + } + + /* Initialize channels. */ + for (chan = 0; chan < 3; chan++) { + i8254_set_mode(subpriv->iobase, 0, chan, + I8254_MODE0 | I8254_BINARY); + if (subpriv->has_clk_gat_sce) { + /* Gate source 0 is VCC (logic 1). */ + dio200_set_gate_src(subpriv, chan, 0); + /* Clock source 0 is the dedicated clock input. */ + dio200_set_clock_src(subpriv, chan, 0); + } + } + + return 0; +} + +/* + * This function cleans up an '8254' counter subdevice. + */ +static void +dio200_subdev_8254_cleanup(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct dio200_subdev_intr *subpriv = s->private; + + if (subpriv) { + kfree(subpriv); + } +} + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int dio200_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase = 0; + unsigned int irq = 0; +#ifdef CONFIG_COMEDI_PCI + struct pci_dev *pci_dev = NULL; + int bus = 0, slot = 0; +#endif + const struct dio200_layout_struct *layout; + int share_irq = 0; + int sdx; + unsigned n; + int ret; + + printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, + DIO200_DRIVER_NAME); + + if ((ret = alloc_private(dev, sizeof(struct dio200_private))) < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + + /* Process options. */ + switch (thisboard->bustype) { + case isa_bustype: + iobase = it->options[0]; + irq = it->options[1]; + share_irq = 0; + break; +#ifdef CONFIG_COMEDI_PCI + case pci_bustype: + bus = it->options[0]; + slot = it->options[1]; + share_irq = 1; + + if ((ret = dio200_find_pci(dev, bus, slot, &pci_dev)) < 0) + return ret; + devpriv->pci_dev = pci_dev; + break; +#endif + default: + printk(KERN_ERR + "comedi%d: %s: BUG! cannot determine board type!\n", + dev->minor, DIO200_DRIVER_NAME); + return -EINVAL; + break; + } + + devpriv->intr_sd = -1; + + /* Enable device and reserve I/O spaces. */ +#ifdef CONFIG_COMEDI_PCI + if (pci_dev) { + ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME); + if (ret < 0) { + printk(KERN_ERR + "comedi%d: error! cannot enable PCI device and request regions!\n", + dev->minor); + return ret; + } + iobase = pci_resource_start(pci_dev, 2); + irq = pci_dev->irq; + } else +#endif + { + ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE); + if (ret < 0) { + return ret; + } + } + dev->iobase = iobase; + + layout = thislayout; + if ((ret = alloc_subdevices(dev, layout->n_subdevs)) < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + + for (n = 0; n < dev->n_subdevices; n++) { + s = &dev->subdevices[n]; + switch (layout->sdtype[n]) { + case sd_8254: + /* counter subdevice (8254) */ + ret = dio200_subdev_8254_init(dev, s, iobase, + layout->sdinfo[n], layout->has_clk_gat_sce); + if (ret < 0) { + return ret; + } + break; + case sd_8255: + /* digital i/o subdevice (8255) */ + ret = subdev_8255_init(dev, s, 0, + iobase + layout->sdinfo[n]); + if (ret < 0) { + return ret; + } + break; + case sd_intr: + /* 'INTERRUPT' subdevice */ + if (irq) { + ret = dio200_subdev_intr_init(dev, s, + iobase + DIO200_INT_SCE, + layout->sdinfo[n], layout->has_int_sce); + if (ret < 0) { + return ret; + } + devpriv->intr_sd = n; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + break; + default: + s->type = COMEDI_SUBD_UNUSED; + break; + } + } + + sdx = devpriv->intr_sd; + if (sdx >= 0 && sdx < dev->n_subdevices) { + dev->read_subdev = &dev->subdevices[sdx]; + } + + dev->board_name = thisboard->name; + + if (irq) { + unsigned long flags = share_irq ? IRQF_SHARED : 0; + + if (comedi_request_irq(irq, dio200_interrupt, flags, + DIO200_DRIVER_NAME, dev) >= 0) { + dev->irq = irq; + } else { + printk(KERN_WARNING + "comedi%d: warning! irq %u unavailable!\n", + dev->minor, irq); + } + } + + printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); + if (thisboard->bustype == isa_bustype) { + printk("(base %#lx) ", iobase); + } else { +#ifdef CONFIG_COMEDI_PCI + printk("(pci %s) ", pci_name(pci_dev)); +#endif + } + if (irq) { + printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); + } else { + printk("(no irq) "); + } + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int dio200_detach(struct comedi_device * dev) +{ + const struct dio200_layout_struct *layout; + unsigned n; + + printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, + DIO200_DRIVER_NAME); + + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + if (dev->subdevices) { + layout = thislayout; + for (n = 0; n < dev->n_subdevices; n++) { + struct comedi_subdevice *s = &dev->subdevices[n]; + switch (layout->sdtype[n]) { + case sd_8254: + dio200_subdev_8254_cleanup(dev, s); + break; + case sd_8255: + subdev_8255_cleanup(dev, s); + break; + case sd_intr: + dio200_subdev_intr_cleanup(dev, s); + break; + default: + break; + } + } + } + if (devpriv) { +#ifdef CONFIG_COMEDI_PCI + if (devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } else +#endif + { + if (dev->iobase) { + release_region(dev->iobase, DIO200_IO_SIZE); + } + } + } + if (dev->board_name) { + printk(KERN_INFO "comedi%d: %s removed\n", + dev->minor, dev->board_name); + } + + return 0; +} diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c new file mode 100644 index 000000000000..2027c75feaca --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -0,0 +1,654 @@ +/* + comedi/drivers/amplc_pc236.c + Driver for Amplicon PC36AT and PCI236 DIO boards. + + Copyright (C) 2002 MEV Ltd. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: amplc_pc236 +Description: Amplicon PC36AT, PCI236 +Author: Ian Abbott +Devices: [Amplicon] PC36AT (pc36at), PCI236 (pci236 or amplc_pc236) +Updated: Wed, 22 Oct 2008 13:40:03 +0100 +Status: works + +Configuration options - PC36AT: + [0] - I/O port base address + [1] - IRQ (optional) + +Configuration options - PCI236: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first available PCI device will be + used. + +The PC36AT ISA board and PCI236 PCI board have a single 8255 appearing +as subdevice 0. + +Subdevice 1 pretends to be a digital input device, but it always returns +0 when read. However, if you run a command with scan_begin_src=TRIG_EXT, +a rising edge on port C bit 7 acts as an external trigger, which can be +used to wake up tasks. This is like the comedi_parport device, but the +only way to physically disable the interrupt on the PC36AT is to remove +the IRQ jumper. If no interrupt is connected, then subdevice 1 is +unused. +*/ + +#include "../comedidev.h" + +#include "comedi_pci.h" + +#include "8255.h" +#include "plx9052.h" + +#define PC236_DRIVER_NAME "amplc_pc236" + +/* PCI236 PCI configuration register information */ +#define PCI_VENDOR_ID_AMPLICON 0x14dc +#define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009 +#define PCI_DEVICE_ID_INVALID 0xffff + +/* PC36AT / PCI236 registers */ + +#define PC236_IO_SIZE 4 +#define PC236_LCR_IO_SIZE 128 + +/* + * INTCSR values for PCI236. + */ +/* Disable interrupt, also clear any interrupt there */ +#define PCI236_INTR_DISABLE ( PLX9052_INTCSR_LI1ENAB_DISABLED \ + | PLX9052_INTCSR_LI1POL_HIGH \ + | PLX9052_INTCSR_LI2POL_HIGH \ + | PLX9052_INTCSR_PCIENAB_DISABLED \ + | PLX9052_INTCSR_LI1SEL_EDGE \ + | PLX9052_INTCSR_LI1CLRINT_ASSERTED ) +/* Enable interrupt, also clear any interrupt there. */ +#define PCI236_INTR_ENABLE ( PLX9052_INTCSR_LI1ENAB_ENABLED \ + | PLX9052_INTCSR_LI1POL_HIGH \ + | PLX9052_INTCSR_LI2POL_HIGH \ + | PLX9052_INTCSR_PCIENAB_ENABLED \ + | PLX9052_INTCSR_LI1SEL_EDGE \ + | PLX9052_INTCSR_LI1CLRINT_ASSERTED ) + +/* + * Board descriptions for Amplicon PC36AT and PCI236. + */ + +enum pc236_bustype { isa_bustype, pci_bustype }; +enum pc236_model { pc36at_model, pci236_model, anypci_model }; + +struct pc236_board { + const char *name; + const char *fancy_name; + unsigned short devid; + enum pc236_bustype bustype; + enum pc236_model model; +}; +static const struct pc236_board pc236_boards[] = { + { + name: "pc36at", + fancy_name:"PC36AT", + bustype: isa_bustype, + model: pc36at_model, + }, +#ifdef CONFIG_COMEDI_PCI + { + name: "pci236", + fancy_name:"PCI236", + devid: PCI_DEVICE_ID_AMPLICON_PCI236, + bustype: pci_bustype, + model: pci236_model, + }, +#endif +#ifdef CONFIG_COMEDI_PCI + { + name: PC236_DRIVER_NAME, + fancy_name:PC236_DRIVER_NAME, + devid: PCI_DEVICE_ID_INVALID, + bustype: pci_bustype, + model: anypci_model, /* wildcard */ + }, +#endif +}; + +#ifdef CONFIG_COMEDI_PCI +static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = { + {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pc236_pci_table); +#endif /* CONFIG_COMEDI_PCI */ + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct pc236_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct pc236_private { +#ifdef CONFIG_COMEDI_PCI + /* PCI device */ + struct pci_dev *pci_dev; + unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */ +#endif + int enable_irq; +}; + +#define devpriv ((struct pc236_private *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int pc236_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pc236_detach(struct comedi_device * dev); +static struct comedi_driver driver_amplc_pc236 = { + driver_name:PC236_DRIVER_NAME, + module:THIS_MODULE, + attach:pc236_attach, + detach:pc236_detach, + board_name:&pc236_boards[0].name, + offset:sizeof(struct pc236_board), + num_names:sizeof(pc236_boards) / sizeof(struct pc236_board), +}; + +#ifdef CONFIG_COMEDI_PCI +COMEDI_PCI_INITCLEANUP(driver_amplc_pc236, pc236_pci_table); +#else +COMEDI_INITCLEANUP(driver_amplc_pc236); +#endif + +static int pc236_request_region(unsigned minor, unsigned long from, + unsigned long extent); +static void pc236_intr_disable(struct comedi_device * dev); +static void pc236_intr_enable(struct comedi_device * dev); +static int pc236_intr_check(struct comedi_device * dev); +static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int pc236_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int pc236_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static irqreturn_t pc236_interrupt(int irq, void *d PT_REGS_ARG); + +/* + * This function looks for a PCI device matching the requested board name, + * bus and slot. + */ +#ifdef CONFIG_COMEDI_PCI +static int +pc236_find_pci(struct comedi_device * dev, int bus, int slot, + struct pci_dev **pci_dev_p) +{ + struct pci_dev *pci_dev = NULL; + + *pci_dev_p = NULL; + + /* Look for matching PCI device. */ + for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL); + pci_dev != NULL; + pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, + PCI_ANY_ID, pci_dev)) { + /* If bus/slot specified, check them. */ + if (bus || slot) { + if (bus != pci_dev->bus->number + || slot != PCI_SLOT(pci_dev->devfn)) + continue; + } + if (thisboard->model == anypci_model) { + /* Match any supported model. */ + int i; + + for (i = 0; i < ARRAY_SIZE(pc236_boards); i++) { + if (pc236_boards[i].bustype != pci_bustype) + continue; + if (pci_dev->device == pc236_boards[i].devid) { + /* Change board_ptr to matched board. */ + dev->board_ptr = &pc236_boards[i]; + break; + } + } + if (i == ARRAY_SIZE(pc236_boards)) + continue; + } else { + /* Match specific model name. */ + if (pci_dev->device != thisboard->devid) + continue; + } + + /* Found a match. */ + *pci_dev_p = pci_dev; + return 0; + } + /* No match found. */ + if (bus || slot) { + printk(KERN_ERR + "comedi%d: error! no %s found at pci %02x:%02x!\n", + dev->minor, thisboard->name, bus, slot); + } else { + printk(KERN_ERR "comedi%d: error! no %s found!\n", + dev->minor, thisboard->name); + } + return -EIO; +} +#endif + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pc236_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase = 0; + unsigned int irq = 0; +#ifdef CONFIG_COMEDI_PCI + struct pci_dev *pci_dev = NULL; + int bus = 0, slot = 0; +#endif + int share_irq = 0; + int ret; + + printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, + PC236_DRIVER_NAME); +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if ((ret = alloc_private(dev, sizeof(struct pc236_private))) < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + /* Process options. */ + switch (thisboard->bustype) { + case isa_bustype: + iobase = it->options[0]; + irq = it->options[1]; + share_irq = 0; + break; +#ifdef CONFIG_COMEDI_PCI + case pci_bustype: + bus = it->options[0]; + slot = it->options[1]; + share_irq = 1; + + if ((ret = pc236_find_pci(dev, bus, slot, &pci_dev)) < 0) + return ret; + devpriv->pci_dev = pci_dev; + break; +#endif /* CONFIG_COMEDI_PCI */ + default: + printk(KERN_ERR + "comedi%d: %s: BUG! cannot determine board type!\n", + dev->minor, PC236_DRIVER_NAME); + return -EINVAL; + break; + } + +/* + * Initialize dev->board_name. + */ + dev->board_name = thisboard->name; + + /* Enable device and reserve I/O spaces. */ +#ifdef CONFIG_COMEDI_PCI + if (pci_dev) { + if ((ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME)) < 0) { + printk(KERN_ERR + "comedi%d: error! cannot enable PCI device and request regions!\n", + dev->minor); + return ret; + } + devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); + iobase = pci_resource_start(pci_dev, 2); + irq = pci_dev->irq; + } else +#endif + { + ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE); + if (ret < 0) { + return ret; + } + } + dev->iobase = iobase; + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if ((ret = alloc_subdevices(dev, 2)) < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + + s = dev->subdevices + 0; + /* digital i/o subdevice (8255) */ + if ((ret = subdev_8255_init(dev, s, NULL, iobase)) < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + s = dev->subdevices + 1; + dev->read_subdev = s; + s->type = COMEDI_SUBD_UNUSED; + pc236_intr_disable(dev); + if (irq) { + unsigned long flags = share_irq ? IRQF_SHARED : 0; + + if (comedi_request_irq(irq, pc236_interrupt, flags, + PC236_DRIVER_NAME, dev) >= 0) { + dev->irq = irq; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 1; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pc236_intr_insn; + s->do_cmdtest = pc236_intr_cmdtest; + s->do_cmd = pc236_intr_cmd; + s->cancel = pc236_intr_cancel; + } + } + printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); + if (thisboard->bustype == isa_bustype) { + printk("(base %#lx) ", iobase); + } else { +#ifdef CONFIG_COMEDI_PCI + printk("(pci %s) ", pci_name(pci_dev)); +#endif + } + if (irq) { + printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); + } else { + printk("(no irq) "); + } + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pc236_detach(struct comedi_device * dev) +{ + printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, + PC236_DRIVER_NAME); + if (devpriv) { + pc236_intr_disable(dev); + } + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (dev->subdevices) { + subdev_8255_cleanup(dev, dev->subdevices + 0); + } + if (devpriv) { +#ifdef CONFIG_COMEDI_PCI + if (devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } else +#endif + { + if (dev->iobase) { + release_region(dev->iobase, PC236_IO_SIZE); + } + } + } + if (dev->board_name) { + printk(KERN_INFO "comedi%d: %s removed\n", + dev->minor, dev->board_name); + } + return 0; +} + +/* + * This function checks and requests an I/O region, reporting an error + * if there is a conflict. + */ +static int pc236_request_region(unsigned minor, unsigned long from, + unsigned long extent) +{ + if (!from || !request_region(from, extent, PC236_DRIVER_NAME)) { + printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", + minor, from, extent); + return -EIO; + } + return 0; +} + +/* + * This function is called to mark the interrupt as disabled (no command + * configured on subdevice 1) and to physically disable the interrupt + * (not possible on the PC36AT, except by removing the IRQ jumper!). + */ +static void pc236_intr_disable(struct comedi_device * dev) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->enable_irq = 0; +#ifdef CONFIG_COMEDI_PCI + if (devpriv->lcr_iobase) + outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR); +#endif + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); +} + +/* + * This function is called to mark the interrupt as enabled (a command + * configured on subdevice 1) and to physically enable the interrupt + * (not possible on the PC36AT, except by (re)connecting the IRQ jumper!). + */ +static void pc236_intr_enable(struct comedi_device * dev) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->enable_irq = 1; +#ifdef CONFIG_COMEDI_PCI + if (devpriv->lcr_iobase) + outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR); +#endif + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); +} + +/* + * This function is called when an interrupt occurs to check whether + * the interrupt has been marked as enabled and was generated by the + * board. If so, the function prepares the hardware for the next + * interrupt. + * Returns 0 if the interrupt should be ignored. + */ +static int pc236_intr_check(struct comedi_device * dev) +{ + int retval = 0; + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + if (devpriv->enable_irq) { + retval = 1; +#ifdef CONFIG_COMEDI_PCI + if (devpriv->lcr_iobase) { + if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR) + & PLX9052_INTCSR_LI1STAT_MASK) + == PLX9052_INTCSR_LI1STAT_INACTIVE) { + retval = 0; + } else { + /* Clear interrupt and keep it enabled. */ + outl(PCI236_INTR_ENABLE, + devpriv->lcr_iobase + PLX9052_INTCSR); + } + } +#endif + } + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + return retval; +} + +/* + * Input from subdevice 1. + * Copied from the comedi_parport driver. + */ +static int pc236_intr_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[1] = 0; + return 2; +} + +/* + * Subdevice 1 command test. + * Copied from the comedi_parport driver. + */ +static int pc236_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + 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: ignored */ + + 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: ignored */ + + if (err) + return 4; + + return 0; +} + +/* + * Subdevice 1 command. + */ +static int pc236_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + pc236_intr_enable(dev); + + return 0; +} + +/* + * Subdevice 1 cancel command. + */ +static int pc236_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + pc236_intr_disable(dev); + + return 0; +} + +/* + * Interrupt service routine. + * Based on the comedi_parport driver. + */ +static irqreturn_t pc236_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 1; + int handled; + + handled = pc236_intr_check(dev); + if (dev->attached && handled) { + comedi_buf_put(s->async, 0); + s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; + comedi_event(dev, s); + } + return IRQ_RETVAL(handled); +} diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c new file mode 100644 index 000000000000..97ac4157adaf --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -0,0 +1,431 @@ +/* + comedi/drivers/amplc_pc263.c + Driver for Amplicon PC263 and PCI263 relay boards. + + Copyright (C) 2002 MEV Ltd. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: amplc_pc263 +Description: Amplicon PC263, PCI263 +Author: Ian Abbott +Devices: [Amplicon] PC263 (pc263), PCI263 (pci263 or amplc_pc263) +Updated: Wed, 22 Oct 2008 14:10:53 +0100 +Status: works + +Configuration options - PC263: + [0] - I/O port base address + +Configuration options - PCI263: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first available PCI device will be + used. + +Each board appears as one subdevice, with 16 digital outputs, each +connected to a reed-relay. Relay contacts are closed when output is 1. +The state of the outputs can be read. +*/ + +#include "../comedidev.h" + +#include "comedi_pci.h" + +#define PC263_DRIVER_NAME "amplc_pc263" + +/* PCI263 PCI configuration register information */ +#define PCI_VENDOR_ID_AMPLICON 0x14dc +#define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c +#define PCI_DEVICE_ID_INVALID 0xffff + +/* PC263 / PCI263 registers */ +#define PC263_IO_SIZE 2 + +/* + * Board descriptions for Amplicon PC263 / PCI263. + */ + +enum pc263_bustype { isa_bustype, pci_bustype }; +enum pc263_model { pc263_model, pci263_model, anypci_model }; + +struct pc263_board { + const char *name; + const char *fancy_name; + unsigned short devid; + enum pc263_bustype bustype; + enum pc263_model model; +}; +static const struct pc263_board pc263_boards[] = { + { + name: "pc263", + fancy_name:"PC263", + bustype: isa_bustype, + model: pc263_model, + }, +#ifdef CONFIG_COMEDI_PCI + { + name: "pci263", + fancy_name:"PCI263", + devid: PCI_DEVICE_ID_AMPLICON_PCI263, + bustype: pci_bustype, + model: pci263_model, + }, +#endif +#ifdef CONFIG_COMEDI_PCI + { + name: PC263_DRIVER_NAME, + fancy_name:PC263_DRIVER_NAME, + devid: PCI_DEVICE_ID_INVALID, + bustype: pci_bustype, + model: anypci_model, /* wildcard */ + }, +#endif +}; + +#ifdef CONFIG_COMEDI_PCI +static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = { + {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pc263_pci_table); +#endif /* CONFIG_COMEDI_PCI */ + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct pc263_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +#ifdef CONFIG_COMEDI_PCI +struct pc263_private { + /* PCI device. */ + struct pci_dev *pci_dev; +}; + +#define devpriv ((struct pc263_private *)dev->private) +#endif /* CONFIG_COMEDI_PCI */ + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int pc263_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pc263_detach(struct comedi_device * dev); +static struct comedi_driver driver_amplc_pc263 = { + driver_name:PC263_DRIVER_NAME, + module:THIS_MODULE, + attach:pc263_attach, + detach:pc263_detach, + board_name:&pc263_boards[0].name, + offset:sizeof(struct pc263_board), + num_names:sizeof(pc263_boards) / sizeof(struct pc263_board), +}; + +static int pc263_request_region(unsigned minor, unsigned long from, + unsigned long extent); +static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pc263_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +/* + * This function looks for a PCI device matching the requested board name, + * bus and slot. + */ +#ifdef CONFIG_COMEDI_PCI +static int +pc263_find_pci(struct comedi_device * dev, int bus, int slot, + struct pci_dev **pci_dev_p) +{ + struct pci_dev *pci_dev = NULL; + + *pci_dev_p = NULL; + + /* Look for matching PCI device. */ + for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL); + pci_dev != NULL; + pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, + PCI_ANY_ID, pci_dev)) { + /* If bus/slot specified, check them. */ + if (bus || slot) { + if (bus != pci_dev->bus->number + || slot != PCI_SLOT(pci_dev->devfn)) + continue; + } + if (thisboard->model == anypci_model) { + /* Match any supported model. */ + int i; + + for (i = 0; i < ARRAY_SIZE(pc263_boards); i++) { + if (pc263_boards[i].bustype != pci_bustype) + continue; + if (pci_dev->device == pc263_boards[i].devid) { + /* Change board_ptr to matched board. */ + dev->board_ptr = &pc263_boards[i]; + break; + } + } + if (i == ARRAY_SIZE(pc263_boards)) + continue; + } else { + /* Match specific model name. */ + if (pci_dev->device != thisboard->devid) + continue; + } + + /* Found a match. */ + *pci_dev_p = pci_dev; + return 0; + } + /* No match found. */ + if (bus || slot) { + printk(KERN_ERR + "comedi%d: error! no %s found at pci %02x:%02x!\n", + dev->minor, thisboard->name, bus, slot); + } else { + printk(KERN_ERR "comedi%d: error! no %s found!\n", + dev->minor, thisboard->name); + } + return -EIO; +} +#endif + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pc263_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase = 0; +#ifdef CONFIG_COMEDI_PCI + struct pci_dev *pci_dev = NULL; + int bus = 0, slot = 0; +#endif + int ret; + + printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, + PC263_DRIVER_NAME); +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ +#ifdef CONFIG_COMEDI_PCI + if ((ret = alloc_private(dev, sizeof(struct pc263_private))) < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } +#endif + /* Process options. */ + switch (thisboard->bustype) { + case isa_bustype: + iobase = it->options[0]; + break; +#ifdef CONFIG_COMEDI_PCI + case pci_bustype: + bus = it->options[0]; + slot = it->options[1]; + + if ((ret = pc263_find_pci(dev, bus, slot, &pci_dev)) < 0) + return ret; + devpriv->pci_dev = pci_dev; + break; +#endif /* CONFIG_COMEDI_PCI */ + default: + printk(KERN_ERR + "comedi%d: %s: BUG! cannot determine board type!\n", + dev->minor, PC263_DRIVER_NAME); + return -EINVAL; + break; + } + +/* + * Initialize dev->board_name. + */ + dev->board_name = thisboard->name; + + /* Enable device and reserve I/O spaces. */ +#ifdef CONFIG_COMEDI_PCI + if (pci_dev) { + if ((ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME)) < 0) { + printk(KERN_ERR + "comedi%d: error! cannot enable PCI device and request regions!\n", + dev->minor); + return ret; + } + iobase = pci_resource_start(pci_dev, 2); + } else +#endif + { + ret = pc263_request_region(dev->minor, iobase, PC263_IO_SIZE); + if (ret < 0) { + return ret; + } + } + dev->iobase = iobase; + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if ((ret = alloc_subdevices(dev, 1)) < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + + s = dev->subdevices + 0; + /* digital i/o subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_RT; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pc263_dio_insn_bits; + s->insn_config = pc263_dio_insn_config; + /* all outputs */ + s->io_bits = 0xffff; + /* read initial relay state */ + s->state = inb(dev->iobase); + s->state = s->state | (inb(dev->iobase) << 8); + + printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); + if (thisboard->bustype == isa_bustype) { + printk("(base %#lx) ", iobase); + } else { +#ifdef CONFIG_COMEDI_PCI + printk("(pci %s) ", pci_name(pci_dev)); +#endif + } + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pc263_detach(struct comedi_device * dev) +{ + printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, + PC263_DRIVER_NAME); + +#ifdef CONFIG_COMEDI_PCI + if (devpriv) +#endif + { +#ifdef CONFIG_COMEDI_PCI + if (devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } else +#endif + { + if (dev->iobase) { + release_region(dev->iobase, PC263_IO_SIZE); + } + } + } + if (dev->board_name) { + printk(KERN_INFO "comedi%d: %s removed\n", + dev->minor, dev->board_name); + } + return 0; +} + +/* + * This function checks and requests an I/O region, reporting an error + * if there is a conflict. + */ +static int pc263_request_region(unsigned minor, unsigned long from, + unsigned long extent) +{ + if (!from || !request_region(from, extent, PC263_DRIVER_NAME)) { + printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", + minor, from, extent); + return -EIO; + } + return 0; +} + +/* DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write */ +static int pc263_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + /* Write out the new digital output lines */ + outb(s->state & 0xFF, dev->iobase); + outb(s->state >> 8, dev->iobase + 1); + } + + /* on return, data[1] contains the value of the digital + * input and output lines. */ + /* or we could just return the software copy of the output values if + * it was a purely digital output subdevice */ + data[1] = s->state; + + return 2; +} + +static int pc263_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 1) + return -EINVAL; + return 1; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +#ifdef CONFIG_COMEDI_PCI +COMEDI_PCI_INITCLEANUP(driver_amplc_pc263, pc263_pci_table); +#else +COMEDI_INITCLEANUP(driver_amplc_pc263); +#endif diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c new file mode 100644 index 000000000000..770b96648932 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -0,0 +1,1545 @@ +/* + comedi/drivers/amplc_pci224.c + Driver for Amplicon PCI224 and PCI234 AO boards. + + Copyright (C) 2005 MEV Ltd. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998,2000 David A. Schleef + + 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: amplc_pci224 +Description: Amplicon PCI224, PCI234 +Author: Ian Abbott +Devices: [Amplicon] PCI224 (amplc_pci224 or pci224), + PCI234 (amplc_pci224 or pci234) +Updated: Wed, 22 Oct 2008 12:25:08 +0100 +Status: works, but see caveats + +Supports: + + - ao_insn read/write + - ao_do_cmd mode with the following sources: + + - start_src TRIG_INT TRIG_EXT + - scan_begin_src TRIG_TIMER TRIG_EXT + - convert_src TRIG_NOW + - scan_end_src TRIG_COUNT + - stop_src TRIG_COUNT TRIG_EXT TRIG_NONE + + The channel list must contain at least one channel with no repeated + channels. The scan end count must equal the number of channels in + the channel list. + + There is only one external trigger source so only one of start_src, + scan_begin_src or stop_src may use TRIG_EXT. + +Configuration options - PCI224: + [0] - PCI bus of device (optional). + [1] - PCI slot of device (optional). + If bus/slot is not specified, the first available PCI device + will be used. + [2] - Select available ranges according to jumper LK1. All channels + are set to the same range: + 0=Jumper position 1-2 (factory default), 4 software-selectable + internal voltage references, giving 4 bipolar and 4 unipolar + ranges: + [-10V,+10V], [-5V,+5V], [-2.5V,+2.5V], [-1.25V,+1.25V], + [0,+10V], [0,+5V], [0,+2.5V], [0,1.25V]. + 1=Jumper position 2-3, 1 external voltage reference, giving + 1 bipolar and 1 unipolar range: + [-Vext,+Vext], [0,+Vext]. + +Configuration options - PCI234: + [0] - PCI bus of device (optional). + [1] - PCI slot of device (optional). + If bus/slot is not specified, the first available PCI device + will be used. + [2] - Select internal or external voltage reference according to + jumper LK1. This affects all channels: + 0=Jumper position 1-2 (factory default), Vref=5V internal. + 1=Jumper position 2-3, Vref=Vext external. + [3] - Select channel 0 range according to jumper LK2: + 0=Jumper position 2-3 (factory default), range [-2*Vref,+2*Vref] + (10V bipolar when options[2]=0). + 1=Jumper position 1-2, range [-Vref,+Vref] + (5V bipolar when options[2]=0). + [4] - Select channel 1 range according to jumper LK3: cf. options[3]. + [5] - Select channel 2 range according to jumper LK4: cf. options[3]. + [6] - Select channel 3 range according to jumper LK5: cf. options[3]. + +Passing a zero for an option is the same as leaving it unspecified. + +Caveats: + + 1) All channels on the PCI224 share the same range. Any change to the + range as a result of insn_write or a streaming command will affect + the output voltages of all channels, including those not specified + by the instruction or command. + + 2) For the analog output command, the first scan may be triggered + falsely at the start of acquisition. This occurs when the DAC scan + trigger source is switched from 'none' to 'timer' (scan_begin_src = + TRIG_TIMER) or 'external' (scan_begin_src == TRIG_EXT) at the start + of acquisition and the trigger source is at logic level 1 at the + time of the switch. This is very likely for TRIG_TIMER. For + TRIG_EXT, it depends on the state of the external line and whether + the CR_INVERT flag has been set. The remaining scans are triggered + correctly. +*/ + +#include "../comedidev.h" + +#include "comedi_pci.h" + +#include "comedi_fc.h" +#include "8253.h" + +#define DRIVER_NAME "amplc_pci224" + +/* + * PCI IDs. + */ +/* #define PCI_VENDOR_ID_AMPLICON 0x14dc */ +#define PCI_DEVICE_ID_AMPLICON_PCI224 0x0007 +#define PCI_DEVICE_ID_AMPLICON_PCI234 0x0008 +#define PCI_DEVICE_ID_INVALID 0xffff + +/* + * PCI224/234 i/o space 1 (PCIBAR2) registers. + */ +#define PCI224_IO1_SIZE 0x20 /* Size of i/o space 1 (8-bit registers) */ +#define PCI224_Z2_CT0 0x14 /* 82C54 counter/timer 0 */ +#define PCI224_Z2_CT1 0x15 /* 82C54 counter/timer 1 */ +#define PCI224_Z2_CT2 0x16 /* 82C54 counter/timer 2 */ +#define PCI224_Z2_CTC 0x17 /* 82C54 counter/timer control word */ +#define PCI224_ZCLK_SCE 0x1A /* Group Z Clock Configuration Register */ +#define PCI224_ZGAT_SCE 0x1D /* Group Z Gate Configuration Register */ +#define PCI224_INT_SCE 0x1E /* ISR Interrupt source mask register */ + /* /Interrupt status */ + +/* + * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers. + */ +#define PCI224_IO2_SIZE 0x10 /* Size of i/o space 2 (16-bit registers). */ +#define PCI224_DACDATA 0x00 /* (w-o) DAC FIFO data. */ +#define PCI224_SOFTTRIG 0x00 /* (r-o) DAC software scan trigger. */ +#define PCI224_DACCON 0x02 /* (r/w) DAC status/configuration. */ +#define PCI224_FIFOSIZ 0x04 /* (w-o) FIFO size for wraparound mode. */ +#define PCI224_DACCEN 0x06 /* (w-o) DAC channel enable register. */ + +/* + * DACCON values. + */ +/* (r/w) Scan trigger. */ +#define PCI224_DACCON_TRIG_MASK (7 << 0) +#define PCI224_DACCON_TRIG_NONE (0 << 0) /* none */ +#define PCI224_DACCON_TRIG_SW (1 << 0) /* software trig */ +#define PCI224_DACCON_TRIG_EXTP (2 << 0) /* ext +ve edge */ +#define PCI224_DACCON_TRIG_EXTN (3 << 0) /* ext -ve edge */ +#define PCI224_DACCON_TRIG_Z2CT0 (4 << 0) /* Z2 CT0 out */ +#define PCI224_DACCON_TRIG_Z2CT1 (5 << 0) /* Z2 CT1 out */ +#define PCI224_DACCON_TRIG_Z2CT2 (6 << 0) /* Z2 CT2 out */ +/* (r/w) Polarity (PCI224 only, PCI234 always bipolar!). */ +#define PCI224_DACCON_POLAR_MASK (1 << 3) +#define PCI224_DACCON_POLAR_UNI (0 << 3) /* range [0,Vref] */ +#define PCI224_DACCON_POLAR_BI (1 << 3) /* range [-Vref,Vref] */ +/* (r/w) Internal Vref (PCI224 only, when LK1 in position 1-2). */ +#define PCI224_DACCON_VREF_MASK (3 << 4) +#define PCI224_DACCON_VREF_1_25 (0 << 4) /* Vref = 1.25V */ +#define PCI224_DACCON_VREF_2_5 (1 << 4) /* Vref = 2.5V */ +#define PCI224_DACCON_VREF_5 (2 << 4) /* Vref = 5V */ +#define PCI224_DACCON_VREF_10 (3 << 4) /* Vref = 10V */ +/* (r/w) Wraparound mode enable (to play back stored waveform). */ +#define PCI224_DACCON_FIFOWRAP (1 << 7) +/* (r/w) FIFO enable. It MUST be set! */ +#define PCI224_DACCON_FIFOENAB (1 << 8) +/* (r/w) FIFO interrupt trigger level (most values are not very useful). */ +#define PCI224_DACCON_FIFOINTR_MASK (7 << 9) +#define PCI224_DACCON_FIFOINTR_EMPTY (0 << 9) /* when empty */ +#define PCI224_DACCON_FIFOINTR_NEMPTY (1 << 9) /* when not empty */ +#define PCI224_DACCON_FIFOINTR_NHALF (2 << 9) /* when not half full */ +#define PCI224_DACCON_FIFOINTR_HALF (3 << 9) /* when half full */ +#define PCI224_DACCON_FIFOINTR_NFULL (4 << 9) /* when not full */ +#define PCI224_DACCON_FIFOINTR_FULL (5 << 9) /* when full */ +/* (r-o) FIFO fill level. */ +#define PCI224_DACCON_FIFOFL_MASK (7 << 12) +#define PCI224_DACCON_FIFOFL_EMPTY (1 << 12) /* 0 */ +#define PCI224_DACCON_FIFOFL_ONETOHALF (0 << 12) /* [1,2048] */ +#define PCI224_DACCON_FIFOFL_HALFTOFULL (4 << 12) /* [2049,4095] */ +#define PCI224_DACCON_FIFOFL_FULL (6 << 12) /* 4096 */ +/* (r-o) DAC busy flag. */ +#define PCI224_DACCON_BUSY (1 << 15) +/* (w-o) FIFO reset. */ +#define PCI224_DACCON_FIFORESET (1 << 12) +/* (w-o) Global reset (not sure what it does). */ +#define PCI224_DACCON_GLOBALRESET (1 << 13) + +/* + * DAC FIFO size. + */ +#define PCI224_FIFO_SIZE 4096 + +/* + * DAC FIFO guaranteed minimum room available, depending on reported fill level. + * The maximum room available depends on the reported fill level and how much + * has been written! + */ +#define PCI224_FIFO_ROOM_EMPTY PCI224_FIFO_SIZE +#define PCI224_FIFO_ROOM_ONETOHALF (PCI224_FIFO_SIZE / 2) +#define PCI224_FIFO_ROOM_HALFTOFULL 1 +#define PCI224_FIFO_ROOM_FULL 0 + +/* + * Counter/timer clock input configuration sources. + */ +#define CLK_CLK 0 /* reserved (channel-specific clock) */ +#define CLK_10MHZ 1 /* internal 10 MHz clock */ +#define CLK_1MHZ 2 /* internal 1 MHz clock */ +#define CLK_100KHZ 3 /* internal 100 kHz clock */ +#define CLK_10KHZ 4 /* internal 10 kHz clock */ +#define CLK_1KHZ 5 /* internal 1 kHz clock */ +#define CLK_OUTNM1 6 /* output of channel-1 modulo total */ +#define CLK_EXT 7 /* external clock */ +/* Macro to construct clock input configuration register value. */ +#define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7)) +/* Timebases in ns. */ +#define TIMEBASE_10MHZ 100 +#define TIMEBASE_1MHZ 1000 +#define TIMEBASE_100KHZ 10000 +#define TIMEBASE_10KHZ 100000 +#define TIMEBASE_1KHZ 1000000 + +/* + * Counter/timer gate input configuration sources. + */ +#define GAT_VCC 0 /* VCC (i.e. enabled) */ +#define GAT_GND 1 /* GND (i.e. disabled) */ +#define GAT_EXT 2 /* reserved (external gate input) */ +#define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */ +/* Macro to construct gate input configuration register value. */ +#define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7)) + +/* + * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI224 and PCI234: + * + * Channel's Channel's + * clock input gate input + * Channel CLK_OUTNM1 GAT_NOUTNM2 + * ------- ---------- ----------- + * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT + * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT + * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT + */ + +/* + * Interrupt enable/status bits + */ +#define PCI224_INTR_EXT 0x01 /* rising edge on external input */ +#define PCI224_INTR_DAC 0x04 /* DAC (FIFO) interrupt */ +#define PCI224_INTR_Z2CT1 0x20 /* rising edge on Z2-CT1 output */ + +#define PCI224_INTR_EDGE_BITS (PCI224_INTR_EXT | PCI224_INTR_Z2CT1) +#define PCI224_INTR_LEVEL_BITS PCI224_INTR_DACFIFO + +/* + * Handy macros. + */ + +/* Combine old and new bits. */ +#define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask))) + +/* A generic null function pointer value. */ +#define NULLFUNC 0 + +/* Current CPU. XXX should this be hard_smp_processor_id()? */ +#define THISCPU smp_processor_id() + +/* State bits for use with atomic bit operations. */ +#define AO_CMD_STARTED 0 + +/* + * Range tables. + */ + +/* The software selectable internal ranges for PCI224 (option[2] == 0). */ +static const struct comedi_lrange range_pci224_internal = { + 8, + { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + } +}; + +static const unsigned short hwrange_pci224_internal[8] = { + PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_10, + PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_5, + PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_2_5, + PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_1_25, + PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_10, + PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_5, + PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_2_5, + PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_1_25, +}; + +/* The software selectable external ranges for PCI224 (option[2] == 1). */ +static const struct comedi_lrange range_pci224_external = { + 2, + { + RANGE_ext(-1, 1), /* bipolar [-Vref,+Vref] */ + RANGE_ext(0, 1), /* unipolar [0,+Vref] */ + } +}; + +static const unsigned short hwrange_pci224_external[2] = { + PCI224_DACCON_POLAR_BI, + PCI224_DACCON_POLAR_UNI, +}; + +/* The hardware selectable Vref*2 external range for PCI234 + * (option[2] == 1, option[3+n] == 0). */ +static const struct comedi_lrange range_pci234_ext2 = { + 1, + { + RANGE_ext(-2, 2), + } +}; + +/* The hardware selectable Vref external range for PCI234 + * (option[2] == 1, option[3+n] == 1). */ +static const struct comedi_lrange range_pci234_ext = { + 1, + { + RANGE_ext(-1, 1), + } +}; + +/* This serves for all the PCI234 ranges. */ +static const unsigned short hwrange_pci234[1] = { + PCI224_DACCON_POLAR_BI, /* bipolar - hardware ignores it! */ +}; + +/* + * Board descriptions. + */ + +enum pci224_model { any_model, pci224_model, pci234_model }; + +struct pci224_board { + const char *name; + unsigned short devid; + enum pci224_model model; + unsigned int ao_chans; + unsigned int ao_bits; +}; + +static const struct pci224_board pci224_boards[] = { + { + name: "pci224", + devid: PCI_DEVICE_ID_AMPLICON_PCI224, + model: pci224_model, + ao_chans:16, + ao_bits: 12, + }, + { + name: "pci234", + devid: PCI_DEVICE_ID_AMPLICON_PCI234, + model: pci234_model, + ao_chans:4, + ao_bits: 16, + }, + { + name: DRIVER_NAME, + devid: PCI_DEVICE_ID_INVALID, + model: any_model, /* wildcard */ + }, +}; + +/* + * PCI driver table. + */ + +static DEFINE_PCI_DEVICE_TABLE(pci224_pci_table) = { + {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pci224_pci_table); + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((struct pci224_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct pci224_private { + struct pci_dev *pci_dev; /* PCI device */ + const unsigned short *hwrange; + unsigned long iobase1; + unsigned long state; + spinlock_t ao_spinlock; + unsigned int *ao_readback; + short *ao_scan_vals; + unsigned char *ao_scan_order; + int intr_cpuid; + short intr_running; + unsigned short daccon; + unsigned int cached_div1; + unsigned int cached_div2; + unsigned int ao_stop_count; + short ao_stop_continuous; + unsigned short ao_enab; /* max 16 channels so 'short' will do */ + unsigned char intsce; +}; + +#define devpriv ((struct pci224_private *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int pci224_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pci224_detach(struct comedi_device * dev); +static struct comedi_driver driver_amplc_pci224 = { + driver_name:DRIVER_NAME, + module:THIS_MODULE, + attach:pci224_attach, + detach:pci224_detach, + board_name:&pci224_boards[0].name, + offset:sizeof(struct pci224_board), + num_names:sizeof(pci224_boards) / sizeof(struct pci224_board), +}; + +COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table); + +/* + * Called from the 'insn_write' function to perform a single write. + */ +static void +pci224_ao_set_data(struct comedi_device * dev, int chan, int range, unsigned int data) +{ + unsigned short mangled; + + /* Store unmangled data for readback. */ + devpriv->ao_readback[chan] = data; + /* Enable the channel. */ + outw(1 << chan, dev->iobase + PCI224_DACCEN); + /* Set range and reset FIFO. */ + devpriv->daccon = COMBINE(devpriv->daccon, devpriv->hwrange[range], + (PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK)); + outw(devpriv->daccon | PCI224_DACCON_FIFORESET, + dev->iobase + PCI224_DACCON); + /* + * Mangle the data. The hardware expects: + * - bipolar: 16-bit 2's complement + * - unipolar: 16-bit unsigned + */ + mangled = (unsigned short)data << (16 - thisboard->ao_bits); + if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) == + PCI224_DACCON_POLAR_BI) { + mangled ^= 0x8000; + } + /* Write mangled data to the FIFO. */ + outw(mangled, dev->iobase + PCI224_DACDATA); + /* Trigger the conversion. */ + inw(dev->iobase + PCI224_SOFTTRIG); +} + +/* + * 'insn_write' function for AO subdevice. + */ +static int +pci224_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan, range; + + /* Unpack channel and range. */ + chan = CR_CHAN(insn->chanspec); + range = CR_RANGE(insn->chanspec); + + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { + pci224_ao_set_data(dev, chan, range, data[i]); + } + return i; +} + +/* + * 'insn_read' function for AO subdevice. + * + * N.B. The value read will not be valid if the DAC channel has + * never been written successfully since the device was attached + * or since the channel has been used by an AO streaming write + * command. + */ +static int +pci224_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan; + + chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +/* + * Just a wrapper for the inline function 'i8253_cascade_ns_to_timer'. + */ +static void +pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2, + unsigned int *nanosec, int round_mode) +{ + i8253_cascade_ns_to_timer(osc_base, d1, d2, nanosec, round_mode); +} + +/* + * Kills a command running on the AO subdevice. + */ +static void pci224_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + + if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state)) { + return; + } + + comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags); + /* Kill the interrupts. */ + devpriv->intsce = 0; + outb(0, devpriv->iobase1 + PCI224_INT_SCE); + /* + * Interrupt routine may or may not be running. We may or may not + * have been called from the interrupt routine (directly or + * indirectly via a comedi_events() callback routine). It's highly + * unlikely that we've been called from some other interrupt routine + * but who knows what strange things coders get up to! + * + * If the interrupt routine is currently running, wait for it to + * finish, unless we appear to have been called via the interrupt + * routine. + */ + while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { + comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); + comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags); + } + comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); + /* Reconfigure DAC for insn_write usage. */ + outw(0, dev->iobase + PCI224_DACCEN); /* Disable channels. */ + devpriv->daccon = COMBINE(devpriv->daccon, + PCI224_DACCON_TRIG_SW | PCI224_DACCON_FIFOINTR_EMPTY, + PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK); + outw(devpriv->daccon | PCI224_DACCON_FIFORESET, + dev->iobase + PCI224_DACCON); +} + +/* + * Handles start of acquisition for the AO subdevice. + */ +static void pci224_ao_start(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + unsigned long flags; + + set_bit(AO_CMD_STARTED, &devpriv->state); + if (!devpriv->ao_stop_continuous && devpriv->ao_stop_count == 0) { + /* An empty acquisition! */ + pci224_ao_stop(dev, s); + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + } else { + /* Enable interrupts. */ + comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags); + if (cmd->stop_src == TRIG_EXT) { + devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC; + } else { + devpriv->intsce = PCI224_INTR_DAC; + } + outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE); + comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); + } +} + +/* + * Handles interrupts from the DAC FIFO. + */ +static void pci224_ao_handle_fifo(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int num_scans; + unsigned int room; + unsigned short dacstat; + unsigned int i, n; + unsigned int bytes_per_scan; + + if (cmd->chanlist_len) { + bytes_per_scan = cmd->chanlist_len * sizeof(short); + } else { + /* Shouldn't get here! */ + bytes_per_scan = sizeof(short); + } + /* Determine number of scans available in buffer. */ + num_scans = comedi_buf_read_n_available(s->async) / bytes_per_scan; + if (!devpriv->ao_stop_continuous) { + /* Fixed number of scans. */ + if (num_scans > devpriv->ao_stop_count) { + num_scans = devpriv->ao_stop_count; + } + } + + /* Determine how much room is in the FIFO (in samples). */ + dacstat = inw(dev->iobase + PCI224_DACCON); + switch (dacstat & PCI224_DACCON_FIFOFL_MASK) { + case PCI224_DACCON_FIFOFL_EMPTY: + room = PCI224_FIFO_ROOM_EMPTY; + if (!devpriv->ao_stop_continuous + && devpriv->ao_stop_count == 0) { + /* FIFO empty at end of counted acquisition. */ + pci224_ao_stop(dev, s); + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + return; + } + break; + case PCI224_DACCON_FIFOFL_ONETOHALF: + room = PCI224_FIFO_ROOM_ONETOHALF; + break; + case PCI224_DACCON_FIFOFL_HALFTOFULL: + room = PCI224_FIFO_ROOM_HALFTOFULL; + break; + default: + room = PCI224_FIFO_ROOM_FULL; + break; + } + if (room >= PCI224_FIFO_ROOM_ONETOHALF) { + /* FIFO is less than half-full. */ + if (num_scans == 0) { + /* Nothing left to put in the FIFO. */ + pci224_ao_stop(dev, s); + s->async->events |= COMEDI_CB_OVERFLOW; + rt_printk(KERN_ERR "comedi%d: " + "AO buffer underrun\n", dev->minor); + } + } + /* Determine how many new scans can be put in the FIFO. */ + if (cmd->chanlist_len) { + room /= cmd->chanlist_len; + } + /* Determine how many scans to process. */ + if (num_scans > room) { + num_scans = room; + } + /* Process scans. */ + for (n = 0; n < num_scans; n++) { + cfc_read_array_from_buffer(s, &devpriv->ao_scan_vals[0], + bytes_per_scan); + for (i = 0; i < cmd->chanlist_len; i++) { + outw(devpriv->ao_scan_vals[devpriv-> + ao_scan_order[i]], + dev->iobase + PCI224_DACDATA); + } + } + if (!devpriv->ao_stop_continuous) { + devpriv->ao_stop_count -= num_scans; + if (devpriv->ao_stop_count == 0) { + /* + * Change FIFO interrupt trigger level to wait + * until FIFO is empty. + */ + devpriv->daccon = COMBINE(devpriv->daccon, + PCI224_DACCON_FIFOINTR_EMPTY, + PCI224_DACCON_FIFOINTR_MASK); + outw(devpriv->daccon, + dev->iobase + PCI224_DACCON); + } + } + if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) == + PCI224_DACCON_TRIG_NONE) { + unsigned short trig; + + /* + * This is the initial DAC FIFO interrupt at the + * start of the acquisition. The DAC's scan trigger + * has been set to 'none' up until now. + * + * Now that data has been written to the FIFO, the + * DAC's scan trigger source can be set to the + * correct value. + * + * BUG: The first scan will be triggered immediately + * if the scan trigger source is at logic level 1. + */ + if (cmd->scan_begin_src == TRIG_TIMER) { + trig = PCI224_DACCON_TRIG_Z2CT0; + } else { + /* cmd->scan_begin_src == TRIG_EXT */ + if (cmd->scan_begin_arg & CR_INVERT) { + trig = PCI224_DACCON_TRIG_EXTN; + } else { + trig = PCI224_DACCON_TRIG_EXTP; + } + } + devpriv->daccon = COMBINE(devpriv->daccon, trig, + PCI224_DACCON_TRIG_MASK); + outw(devpriv->daccon, dev->iobase + PCI224_DACCON); + } + if (s->async->events) { + comedi_event(dev, s); + } +} + +/* + * Internal trigger function to start acquisition on AO subdevice. + */ +static int +pci224_ao_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ + if (trignum != 0) + return -EINVAL; + + s->async->inttrig = NULLFUNC; + pci224_ao_start(dev, s); + + return 1; +} + +#define MAX_SCAN_PERIOD 0xFFFFFFFFU +#define MIN_SCAN_PERIOD 2500 +#define CONVERT_PERIOD 625 + +/* + * 'do_cmdtest' function for AO subdevice. + */ +static int +pci224_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd) +{ + int err = 0; + unsigned int tmp; + + /* Step 1: make sure trigger sources are trivially valid. */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_EXT | TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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_COUNT | TRIG_EXT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* Step 2: make sure trigger sources are unique and mutually + * compatible. */ + + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; + + /* There's only one external trigger signal (which makes these + * tests easier). Only one thing can use it. */ + tmp = 0; + if (cmd->start_src & TRIG_EXT) + tmp++; + if (cmd->scan_begin_src & TRIG_EXT) + tmp++; + if (cmd->stop_src & TRIG_EXT) + tmp++; + if (tmp > 1) + err++; + + if (err) + return 2; + + /* Step 3: make sure arguments are trivially compatible. */ + + switch (cmd->start_src) { + case TRIG_INT: + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + break; + case TRIG_EXT: + /* Force to external trigger 0. */ + if ((cmd->start_arg & ~CR_FLAGS_MASK) != 0) { + cmd->start_arg = COMBINE(cmd->start_arg, 0, + ~CR_FLAGS_MASK); + err++; + } + /* The only flag allowed is CR_EDGE, which is ignored. */ + if ((cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) { + cmd->start_arg = COMBINE(cmd->start_arg, 0, + CR_FLAGS_MASK & ~CR_EDGE); + err++; + } + break; + } + + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + if (cmd->scan_begin_arg > MAX_SCAN_PERIOD) { + cmd->scan_begin_arg = MAX_SCAN_PERIOD; + err++; + } + tmp = cmd->chanlist_len * CONVERT_PERIOD; + if (tmp < MIN_SCAN_PERIOD) { + tmp = MIN_SCAN_PERIOD; + } + if (cmd->scan_begin_arg < tmp) { + cmd->scan_begin_arg = tmp; + err++; + } + break; + case TRIG_EXT: + /* Force to external trigger 0. */ + if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) { + cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, + ~CR_FLAGS_MASK); + err++; + } + /* Only allow flags CR_EDGE and CR_INVERT. Ignore CR_EDGE. */ + if ((cmd->scan_begin_arg & CR_FLAGS_MASK & + ~(CR_EDGE | CR_INVERT)) != 0) { + cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, + CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT)); + err++; + } + break; + } + + /* cmd->convert_src == TRIG_NOW */ + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + + /* cmd->scan_end_arg == TRIG_COUNT */ + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + switch (cmd->stop_src) { + case TRIG_COUNT: + /* Any count allowed. */ + break; + case TRIG_EXT: + /* Force to external trigger 0. */ + if ((cmd->stop_arg & ~CR_FLAGS_MASK) != 0) { + cmd->stop_arg = COMBINE(cmd->stop_arg, 0, + ~CR_FLAGS_MASK); + err++; + } + /* The only flag allowed is CR_EDGE, which is ignored. */ + if ((cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) { + cmd->stop_arg = COMBINE(cmd->stop_arg, 0, + CR_FLAGS_MASK & ~CR_EDGE); + } + break; + case TRIG_NONE: + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + break; + } + + if (err) + return 3; + + /* Step 4: fix up any arguments. */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + unsigned int div1, div2, round; + int round_mode = cmd->flags & TRIG_ROUND_MASK; + + tmp = cmd->scan_begin_arg; + /* Check whether to use a single timer. */ + switch (round_mode) { + case TRIG_ROUND_NEAREST: + default: + round = TIMEBASE_10MHZ / 2; + break; + case TRIG_ROUND_DOWN: + round = 0; + break; + case TRIG_ROUND_UP: + round = TIMEBASE_10MHZ - 1; + break; + } + /* Be careful to avoid overflow! */ + div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ; + div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) / + TIMEBASE_10MHZ; + if (div2 <= 0x10000) { + /* A single timer will suffice. */ + if (div2 < 2) + div2 = 2; + cmd->scan_begin_arg = div2 * TIMEBASE_10MHZ; + if (cmd->scan_begin_arg < div2 || + cmd->scan_begin_arg < TIMEBASE_10MHZ) { + /* Overflow! */ + cmd->scan_begin_arg = MAX_SCAN_PERIOD; + } + } else { + /* Use two timers. */ + div1 = devpriv->cached_div1; + div2 = devpriv->cached_div2; + pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2, + &cmd->scan_begin_arg, round_mode); + devpriv->cached_div1 = div1; + devpriv->cached_div2 = div2; + } + if (tmp != cmd->scan_begin_arg) { + err++; + } + } + + if (err) + return 4; + + /* Step 5: check channel list. */ + + if (cmd->chanlist && (cmd->chanlist_len > 0)) { + unsigned int range; + enum { range_err = 1, dupchan_err = 2, }; + unsigned errors; + unsigned int n; + unsigned int ch; + + /* + * Check all channels have the same range index. Don't care + * about analogue reference, as we can't configure it. + * + * Check the list has no duplicate channels. + */ + range = CR_RANGE(cmd->chanlist[0]); + errors = 0; + tmp = 0; + for (n = 0; n < cmd->chanlist_len; n++) { + ch = CR_CHAN(cmd->chanlist[n]); + if (tmp & (1U << ch)) { + errors |= dupchan_err; + } + tmp |= (1U << ch); + if (CR_RANGE(cmd->chanlist[n]) != range) { + errors |= range_err; + } + } + if (errors) { + if (errors & dupchan_err) { + DPRINTK("comedi%d: " DRIVER_NAME + ": ao_cmdtest: " + "entries in chanlist must contain no " + "duplicate channels\n", dev->minor); + } + if (errors & range_err) { + DPRINTK("comedi%d: " DRIVER_NAME + ": ao_cmdtest: " + "entries in chanlist must all have " + "the same range index\n", dev->minor); + } + err++; + } + } + + if (err) + return 5; + + return 0; +} + +/* + * 'do_cmd' function for AO subdevice. + */ +static int pci224_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + int range; + unsigned int i, j; + unsigned int ch; + unsigned int rank; + unsigned long flags; + + /* Cannot handle null/empty chanlist. */ + if (cmd->chanlist == NULL || cmd->chanlist_len == 0) { + return -EINVAL; + } + + /* Determine which channels are enabled and their load order. */ + devpriv->ao_enab = 0; + + for (i = 0; i < cmd->chanlist_len; i++) { + ch = CR_CHAN(cmd->chanlist[i]); + devpriv->ao_enab |= 1U << ch; + rank = 0; + for (j = 0; j < cmd->chanlist_len; j++) { + if (CR_CHAN(cmd->chanlist[j]) < ch) { + rank++; + } + } + devpriv->ao_scan_order[rank] = i; + } + + /* Set enabled channels. */ + outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN); + + /* Determine range and polarity. All channels the same. */ + range = CR_RANGE(cmd->chanlist[0]); + + /* + * Set DAC range and polarity. + * Set DAC scan trigger source to 'none'. + * Set DAC FIFO interrupt trigger level to 'not half full'. + * Reset DAC FIFO. + * + * N.B. DAC FIFO interrupts are currently disabled. + */ + devpriv->daccon = COMBINE(devpriv->daccon, + (devpriv->hwrange[range] | PCI224_DACCON_TRIG_NONE | + PCI224_DACCON_FIFOINTR_NHALF), + (PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK | + PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK)); + outw(devpriv->daccon | PCI224_DACCON_FIFORESET, + dev->iobase + PCI224_DACCON); + + if (cmd->scan_begin_src == TRIG_TIMER) { + unsigned int div1, div2, round; + unsigned int ns = cmd->scan_begin_arg; + int round_mode = cmd->flags & TRIG_ROUND_MASK; + + /* Check whether to use a single timer. */ + switch (round_mode) { + case TRIG_ROUND_NEAREST: + default: + round = TIMEBASE_10MHZ / 2; + break; + case TRIG_ROUND_DOWN: + round = 0; + break; + case TRIG_ROUND_UP: + round = TIMEBASE_10MHZ - 1; + break; + } + /* Be careful to avoid overflow! */ + div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ; + div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) / + TIMEBASE_10MHZ; + if (div2 <= 0x10000) { + /* A single timer will suffice. */ + if (div2 < 2) + div2 = 2; + div2 &= 0xffff; + div1 = 1; /* Flag that single timer to be used. */ + } else { + /* Use two timers. */ + div1 = devpriv->cached_div1; + div2 = devpriv->cached_div2; + pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2, + &ns, round_mode); + } + + /* + * The output of timer Z2-0 will be used as the scan trigger + * source. + */ + /* Make sure Z2-0 is gated on. */ + outb(GAT_CONFIG(0, GAT_VCC), + devpriv->iobase1 + PCI224_ZGAT_SCE); + if (div1 == 1) { + /* Not cascading. Z2-0 needs 10 MHz clock. */ + outb(CLK_CONFIG(0, CLK_10MHZ), + devpriv->iobase1 + PCI224_ZCLK_SCE); + } else { + /* Cascading with Z2-2. */ + /* Make sure Z2-2 is gated on. */ + outb(GAT_CONFIG(2, GAT_VCC), + devpriv->iobase1 + PCI224_ZGAT_SCE); + /* Z2-2 needs 10 MHz clock. */ + outb(CLK_CONFIG(2, CLK_10MHZ), + devpriv->iobase1 + PCI224_ZCLK_SCE); + /* Load Z2-2 mode (2) and counter (div1). */ + i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0, + 2, div1, 2); + /* Z2-0 is clocked from Z2-2's output. */ + outb(CLK_CONFIG(0, CLK_OUTNM1), + devpriv->iobase1 + PCI224_ZCLK_SCE); + } + /* Load Z2-0 mode (2) and counter (div2). */ + i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0, 0, div2, 2); + } + + /* + * Sort out end of acquisition. + */ + switch (cmd->stop_src) { + case TRIG_COUNT: + /* Fixed number of scans. */ + devpriv->ao_stop_continuous = 0; + devpriv->ao_stop_count = cmd->stop_arg; + break; + default: + /* Continuous scans. */ + devpriv->ao_stop_continuous = 1; + devpriv->ao_stop_count = 0; + break; + } + + /* + * Sort out start of acquisition. + */ + switch (cmd->start_src) { + case TRIG_INT: + comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags); + s->async->inttrig = &pci224_ao_inttrig_start; + comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); + break; + case TRIG_EXT: + /* Enable external interrupt trigger to start acquisition. */ + comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags); + devpriv->intsce |= PCI224_INTR_EXT; + outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE); + comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); + break; + } + + return 0; +} + +/* + * 'cancel' function for AO subdevice. + */ +static int pci224_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + pci224_ao_stop(dev, s); + return 0; +} + +/* + * 'munge' data for AO command. + */ +static void +pci224_ao_munge(struct comedi_device * dev, struct comedi_subdevice * s, void *data, + unsigned int num_bytes, unsigned int chan_index) +{ + struct comedi_async *async = s->async; + short *array = data; + unsigned int length = num_bytes / sizeof(*array); + unsigned int offset; + unsigned int shift; + unsigned int i; + + /* The hardware expects 16-bit numbers. */ + shift = 16 - thisboard->ao_bits; + /* Channels will be all bipolar or all unipolar. */ + if ((devpriv->hwrange[CR_RANGE(async->cmd.chanlist[0])] & + PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) { + /* Unipolar */ + offset = 0; + } else { + /* Bipolar */ + offset = 32768; + } + /* Munge the data. */ + for (i = 0; i < length; i++) { + array[i] = (array[i] << shift) - offset; + } +} + +/* + * Interrupt handler. + */ +static irqreturn_t pci224_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_cmd *cmd; + unsigned char intstat, valid_intstat; + unsigned char curenab; + int retval = 0; + unsigned long flags; + + intstat = inb(devpriv->iobase1 + PCI224_INT_SCE) & 0x3F; + if (intstat) { + retval = 1; + comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags); + valid_intstat = devpriv->intsce & intstat; + /* Temporarily disable interrupt sources. */ + curenab = devpriv->intsce & ~intstat; + outb(curenab, devpriv->iobase1 + PCI224_INT_SCE); + devpriv->intr_running = 1; + devpriv->intr_cpuid = THISCPU; + comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); + if (valid_intstat != 0) { + cmd = &s->async->cmd; + if (valid_intstat & PCI224_INTR_EXT) { + devpriv->intsce &= ~PCI224_INTR_EXT; + if (cmd->start_src == TRIG_EXT) { + pci224_ao_start(dev, s); + } else if (cmd->stop_src == TRIG_EXT) { + pci224_ao_stop(dev, s); + } + } + if (valid_intstat & PCI224_INTR_DAC) { + pci224_ao_handle_fifo(dev, s); + } + } + /* Reenable interrupt sources. */ + comedi_spin_lock_irqsave(&devpriv->ao_spinlock, flags); + if (curenab != devpriv->intsce) { + outb(devpriv->intsce, + devpriv->iobase1 + PCI224_INT_SCE); + } + devpriv->intr_running = 0; + comedi_spin_unlock_irqrestore(&devpriv->ao_spinlock, flags); + } + return IRQ_RETVAL(retval); +} + +/* + * This function looks for a PCI device matching the requested board name, + * bus and slot. + */ +static int +pci224_find_pci(struct comedi_device * dev, int bus, int slot, + struct pci_dev **pci_dev_p) +{ + struct pci_dev *pci_dev = NULL; + + *pci_dev_p = NULL; + + /* Look for matching PCI device. */ + for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL); + pci_dev != NULL; + pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, + pci_dev)) { + /* If bus/slot specified, check them. */ + if (bus || slot) { + if (bus != pci_dev->bus->number + || slot != PCI_SLOT(pci_dev->devfn)) + continue; + } + if (thisboard->model == any_model) { + /* Match any supported model. */ + int i; + + for (i = 0; i < ARRAY_SIZE(pci224_boards); i++) { + if (pci_dev->device == pci224_boards[i].devid) { + /* Change board_ptr to matched board. */ + dev->board_ptr = &pci224_boards[i]; + break; + } + } + if (i == ARRAY_SIZE(pci224_boards)) + continue; + } else { + /* Match specific model name. */ + if (thisboard->devid != pci_dev->device) + continue; + } + + /* Found a match. */ + *pci_dev_p = pci_dev; + return 0; + } + /* No match found. */ + if (bus || slot) { + printk(KERN_ERR "comedi%d: error! " + "no %s found at pci %02x:%02x!\n", + dev->minor, thisboard->name, bus, slot); + } else { + printk(KERN_ERR "comedi%d: error! no %s found!\n", + dev->minor, thisboard->name); + } + return -EIO; +} + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pci224_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + struct pci_dev *pci_dev; + unsigned int irq; + int bus = 0, slot = 0; + unsigned n; + int ret; + + printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, DRIVER_NAME); + + bus = it->options[0]; + slot = it->options[1]; + if ((ret = alloc_private(dev, sizeof(struct pci224_private))) < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + if ((ret = pci224_find_pci(dev, bus, slot, &pci_dev)) < 0) + return ret; + devpriv->pci_dev = pci_dev; + + if ((ret = comedi_pci_enable(pci_dev, DRIVER_NAME)) < 0) { + printk(KERN_ERR + "comedi%d: error! cannot enable PCI device " + "and request regions!\n", dev->minor); + return ret; + } + spin_lock_init(&devpriv->ao_spinlock); + + devpriv->iobase1 = pci_resource_start(pci_dev, 2); + dev->iobase = pci_resource_start(pci_dev, 3); + irq = pci_dev->irq; + + /* Allocate readback buffer for AO channels. */ + devpriv->ao_readback = kmalloc(sizeof(devpriv->ao_readback[0]) * + thisboard->ao_chans, GFP_KERNEL); + if (!devpriv->ao_readback) { + return -ENOMEM; + } + + /* Allocate buffer to hold values for AO channel scan. */ + devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) * + thisboard->ao_chans, GFP_KERNEL); + if (!devpriv->ao_scan_vals) { + return -ENOMEM; + } + + /* Allocate buffer to hold AO channel scan order. */ + devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) * + thisboard->ao_chans, GFP_KERNEL); + if (!devpriv->ao_scan_order) { + return -ENOMEM; + } + + /* Disable interrupt sources. */ + devpriv->intsce = 0; + outb(0, devpriv->iobase1 + PCI224_INT_SCE); + + /* Initialize the DAC hardware. */ + outw(PCI224_DACCON_GLOBALRESET, dev->iobase + PCI224_DACCON); + outw(0, dev->iobase + PCI224_DACCEN); + outw(0, dev->iobase + PCI224_FIFOSIZ); + devpriv->daccon = (PCI224_DACCON_TRIG_SW | PCI224_DACCON_POLAR_BI | + PCI224_DACCON_FIFOENAB | PCI224_DACCON_FIFOINTR_EMPTY); + outw(devpriv->daccon | PCI224_DACCON_FIFORESET, + dev->iobase + PCI224_DACCON); + + /* Allocate subdevices. There is only one! */ + if ((ret = alloc_subdevices(dev, 1)) < 0) { + printk(KERN_ERR "comedi%d: error! out of memory!\n", + dev->minor); + return ret; + } + + s = dev->subdevices + 0; + /* Analog output subdevice. */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; + s->n_chan = thisboard->ao_chans; + s->maxdata = (1 << thisboard->ao_bits) - 1; + s->insn_write = &pci224_ao_insn_write; + s->insn_read = &pci224_ao_insn_read; + s->len_chanlist = s->n_chan; + + dev->write_subdev = s; + s->do_cmd = &pci224_ao_cmd; + s->do_cmdtest = &pci224_ao_cmdtest; + s->cancel = &pci224_ao_cancel; + s->munge = &pci224_ao_munge; + + /* Sort out channel range options. */ + if (thisboard->model == pci234_model) { + /* PCI234 range options. */ + const struct comedi_lrange **range_table_list; + + s->range_table_list = range_table_list = + kmalloc(sizeof(struct comedi_lrange *) * s->n_chan, + GFP_KERNEL); + if (!s->range_table_list) { + return -ENOMEM; + } + for (n = 2; n < 3 + s->n_chan; n++) { + if (it->options[n] < 0 || it->options[n] > 1) { + printk(KERN_WARNING "comedi%d: %s: warning! " + "bad options[%u]=%d\n", + dev->minor, DRIVER_NAME, n, + it->options[n]); + } + } + for (n = 0; n < s->n_chan; n++) { + if (n < COMEDI_NDEVCONFOPTS - 3 && + it->options[3 + n] == 1) { + if (it->options[2] == 1) { + range_table_list[n] = &range_pci234_ext; + } else { + range_table_list[n] = &range_bipolar5; + } + } else { + if (it->options[2] == 1) { + range_table_list[n] = + &range_pci234_ext2; + } else { + range_table_list[n] = &range_bipolar10; + } + } + } + devpriv->hwrange = hwrange_pci234; + } else { + /* PCI224 range options. */ + if (it->options[2] == 1) { + s->range_table = &range_pci224_external; + devpriv->hwrange = hwrange_pci224_external; + } else { + if (it->options[2] != 0) { + printk(KERN_WARNING "comedi%d: %s: warning! " + "bad options[2]=%d\n", + dev->minor, DRIVER_NAME, + it->options[2]); + } + s->range_table = &range_pci224_internal; + devpriv->hwrange = hwrange_pci224_internal; + } + } + + dev->board_name = thisboard->name; + + if (irq) { + ret = comedi_request_irq(irq, pci224_interrupt, IRQF_SHARED, + DRIVER_NAME, dev); + if (ret < 0) { + printk(KERN_ERR "comedi%d: error! " + "unable to allocate irq %u\n", dev->minor, irq); + return ret; + } else { + dev->irq = irq; + } + } + + printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); + printk("(pci %s) ", pci_name(pci_dev)); + if (irq) { + printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); + } else { + printk("(no irq) "); + } + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pci224_detach(struct comedi_device * dev) +{ + printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, DRIVER_NAME); + + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + if (dev->subdevices) { + struct comedi_subdevice *s; + + s = dev->subdevices + 0; + /* AO subdevice */ + if (s->range_table_list) { + kfree(s->range_table_list); + } + } + if (devpriv) { + if (devpriv->ao_readback) { + kfree(devpriv->ao_readback); + } + if (devpriv->ao_scan_vals) { + kfree(devpriv->ao_scan_vals); + } + if (devpriv->ao_scan_order) { + kfree(devpriv->ao_scan_order); + } + if (devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + } + if (dev->board_name) { + printk(KERN_INFO "comedi%d: %s removed\n", + dev->minor, dev->board_name); + } + + return 0; +} diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c new file mode 100644 index 000000000000..0c9e5737e100 --- /dev/null +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -0,0 +1,2977 @@ + /* + comedi/drivers/amplc_pci230.c + Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards. + + Copyright (C) 2001 Allan Willcox + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: amplc_pci230 +Description: Amplicon PCI230, PCI260 Multifunction I/O boards +Author: Allan Willcox , + Steve D Sharples , + Ian Abbott +Updated: Wed, 22 Oct 2008 12:34:49 +0100 +Devices: [Amplicon] PCI230 (pci230 or amplc_pci230), + PCI230+ (pci230+ or amplc_pci230), + PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230) +Status: works + +Configuration options: + [0] - PCI bus of device (optional). + [1] - PCI slot of device (optional). + If bus/slot is not specified, the first available PCI device + will be used. + +Configuring a "amplc_pci230" will match any supported card and it will +choose the best match, picking the "+" models if possible. Configuring +a "pci230" will match a PCI230 or PCI230+ card and it will be treated as +a PCI230. Configuring a "pci260" will match a PCI260 or PCI260+ card +and it will be treated as a PCI260. Configuring a "pci230+" will match +a PCI230+ card. Configuring a "pci260+" will match a PCI260+ card. + +Subdevices: + + PCI230(+) PCI260(+) + --------- --------- + Subdevices 3 1 + 0 AI AI + 1 AO + 2 DIO + +AI Subdevice: + + The AI subdevice has 16 single-ended channels or 8 differential + channels. + + The PCI230 and PCI260 cards have 12-bit resolution. The PCI230+ and + PCI260+ cards have 16-bit resolution. + + For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use + inputs 14 and 15 for channel 7). If the card is physically a PCI230 + or PCI260 then it actually uses a "pseudo-differential" mode where the + inputs are sampled a few microseconds apart. The PCI230+ and PCI260+ + use true differential sampling. Another difference is that if the + card is physically a PCI230 or PCI260, the inverting input is 2N, + whereas for a PCI230+ or PCI260+ the inverting input is 2N+1. So if a + PCI230 is physically replaced by a PCI230+ (or a PCI260 with a + PCI260+) and differential mode is used, the differential inputs need + to be physically swapped on the connector. + + The following input ranges are supported: + + 0 => [-10, +10] V + 1 => [-5, +5] V + 2 => [-2.5, +2.5] V + 3 => [-1.25, +1.25] V + 4 => [0, 10] V + 5 => [0, 5] V + 6 => [0, 2.5] V + +AI Commands: + + +=========+==============+===========+============+==========+ + |start_src|scan_begin_src|convert_src|scan_end_src| stop_src | + +=========+==============+===========+============+==========+ + |TRIG_NOW | TRIG_FOLLOW |TRIG_TIMER | TRIG_COUNT |TRIG_NONE | + |TRIG_INT | |TRIG_EXT(3)| |TRIG_COUNT| + | | |TRIG_INT | | | + | |--------------|-----------| | | + | | TRIG_TIMER(1)|TRIG_TIMER | | | + | | TRIG_EXT(2) | | | | + | | TRIG_INT | | | | + +---------+--------------+-----------+------------+----------+ + + Note 1: If AI command and AO command are used simultaneously, only + one may have scan_begin_src == TRIG_TIMER. + + Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses + DIO channel 16 (pin 49) which will need to be configured as + a digital input. For PCI260+, the EXTTRIG/EXTCONVCLK input + (pin 17) is used instead. For PCI230, scan_begin_src == + TRIG_EXT is not supported. The trigger is a rising edge + on the input. + + Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input + (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used. The + convert_arg value is interpreted as follows: + + convert_arg == (CR_EDGE | 0) => rising edge + convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge + convert_arg == 0 => falling edge (backwards compatibility) + convert_arg == 1 => rising edge (backwards compatibility) + + All entries in the channel list must use the same analogue reference. + If the analogue reference is not AREF_DIFF (not differential) each + pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same + input range. The input ranges used in the sequence must be all + bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6). The channel + sequence must consist of 1 or more identical subsequences. Within the + subsequence, channels must be in ascending order with no repeated + channels. For example, the following sequences are valid: 0 1 2 3 + (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid + subsequence), 1 1 1 1 (repeated valid subsequence). The following + sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3 + (incompletely repeated subsequence). Some versions of the PCI230+ and + PCI260+ have a bug that requires a subsequence longer than one entry + long to include channel 0. + +AO Subdevice: + + The AO subdevice has 2 channels with 12-bit resolution. + + The following output ranges are supported: + + 0 => [0, 10] V + 1 => [-10, +10] V + +AO Commands: + + +=========+==============+===========+============+==========+ + |start_src|scan_begin_src|convert_src|scan_end_src| stop_src | + +=========+==============+===========+============+==========+ + |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW | TRIG_COUNT |TRIG_NONE | + | | TRIG_EXT(2) | | |TRIG_COUNT| + | | TRIG_INT | | | | + +---------+--------------+-----------+------------+----------+ + + Note 1: If AI command and AO command are used simultaneously, only + one may have scan_begin_src == TRIG_TIMER. + + Note 2: scan_begin_src == TRIG_EXT is only supported if the card is + configured as a PCI230+ and is only supported on later + versions of the card. As a card configured as a PCI230+ is + not guaranteed to support external triggering, please consider + this support to be a bonus. It uses the EXTTRIG/ EXTCONVCLK + input (PCI230+ pin 25). Triggering will be on the rising edge + unless the CR_INVERT flag is set in scan_begin_arg. + + The channels in the channel sequence must be in ascending order with + no repeats. All entries in the channel sequence must use the same + output range. + +DIO Subdevice: + + The DIO subdevice is a 8255 chip providing 24 DIO channels. The DIO + channels are configurable as inputs or outputs in four groups: + + Port A - channels 0 to 7 + Port B - channels 8 to 15 + Port CL - channels 16 to 19 + Port CH - channels 20 to 23 + + Only mode 0 of the 8255 chip is supported. + + Bit 0 of port C (DIO channel 16) is also used as an external scan + trigger input for AI commands on PCI230 and PCI230+, so would need to + be configured as an input to use it for that purpose. +*/ +/* +Extra triggered scan functionality, interrupt bug-fix added by Steve Sharples. +Support for PCI230+/260+, more triggered scan functionality, and workarounds +for (or detection of) various hardware problems added by Ian Abbott. +*/ +#include "../comedidev.h" + +#include + +#include "comedi_pci.h" +#include "8253.h" +#include "8255.h" + +/* PCI230 PCI configuration register information */ +#define PCI_VENDOR_ID_AMPLICON 0x14dc +#define PCI_DEVICE_ID_PCI230 0x0000 +#define PCI_DEVICE_ID_PCI260 0x0006 +#define PCI_DEVICE_ID_INVALID 0xffff + +#define PCI230_IO1_SIZE 32 /* Size of I/O space 1 */ +#define PCI230_IO2_SIZE 16 /* Size of I/O space 2 */ + +/* PCI230 i/o space 1 registers. */ +#define PCI230_PPI_X_BASE 0x00 /* User PPI (82C55) base */ +#define PCI230_PPI_X_A 0x00 /* User PPI (82C55) port A */ +#define PCI230_PPI_X_B 0x01 /* User PPI (82C55) port B */ +#define PCI230_PPI_X_C 0x02 /* User PPI (82C55) port C */ +#define PCI230_PPI_X_CMD 0x03 /* User PPI (82C55) control word */ +#define PCI230_Z2_CT_BASE 0x14 /* 82C54 counter/timer base */ +#define PCI230_Z2_CT0 0x14 /* 82C54 counter/timer 0 */ +#define PCI230_Z2_CT1 0x15 /* 82C54 counter/timer 1 */ +#define PCI230_Z2_CT2 0x16 /* 82C54 counter/timer 2 */ +#define PCI230_Z2_CTC 0x17 /* 82C54 counter/timer control word */ +#define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration */ +#define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration */ +#define PCI230_INT_SCE 0x1E /* Interrupt source mask (w) */ +#define PCI230_INT_STAT 0x1E /* Interrupt status (r) */ + +/* PCI230 i/o space 2 registers. */ +#define PCI230_DACCON 0x00 /* DAC control */ +#define PCI230_DACOUT1 0x02 /* DAC channel 0 (w) */ +#define PCI230_DACOUT2 0x04 /* DAC channel 1 (w) (not FIFO mode) */ +#define PCI230_ADCDATA 0x08 /* ADC data (r) */ +#define PCI230_ADCSWTRIG 0x08 /* ADC software trigger (w) */ +#define PCI230_ADCCON 0x0A /* ADC control */ +#define PCI230_ADCEN 0x0C /* ADC channel enable bits */ +#define PCI230_ADCG 0x0E /* ADC gain control bits */ +/* PCI230+ i/o space 2 additional registers. */ +#define PCI230P_ADCTRIG 0x10 /* ADC start acquisition trigger */ +#define PCI230P_ADCTH 0x12 /* ADC analog trigger threshold */ +#define PCI230P_ADCFFTH 0x14 /* ADC FIFO interrupt threshold */ +#define PCI230P_ADCFFLEV 0x16 /* ADC FIFO level (r) */ +#define PCI230P_ADCPTSC 0x18 /* ADC pre-trigger sample count (r) */ +#define PCI230P_ADCHYST 0x1A /* ADC analog trigger hysteresys */ +#define PCI230P_EXTFUNC 0x1C /* Extended functions */ +#define PCI230P_HWVER 0x1E /* Hardware version (r) */ +/* PCI230+ hardware version 2 onwards. */ +#define PCI230P2_DACDATA 0x02 /* DAC data (FIFO mode) (w) */ +#define PCI230P2_DACSWTRIG 0x02 /* DAC soft trigger (FIFO mode) (r) */ +#define PCI230P2_DACEN 0x06 /* DAC channel enable (FIFO mode) */ + +/* Convertor related constants. */ +#define PCI230_DAC_SETTLE 5 /* Analogue output settling time in µs */ + /* (DAC itself is 1µs nominally). */ +#define PCI230_ADC_SETTLE 1 /* Analogue input settling time in µs */ + /* (ADC itself is 1.6µs nominally but we poll + * anyway). */ +#define PCI230_MUX_SETTLE 10 /* ADC MUX settling time in µS */ + /* - 10µs for se, 20µs de. */ + +/* DACCON read-write values. */ +#define PCI230_DAC_OR_UNI (0<<0) /* Output range unipolar */ +#define PCI230_DAC_OR_BIP (1<<0) /* Output range bipolar */ +#define PCI230_DAC_OR_MASK (1<<0) +/* The following applies only if DAC FIFO support is enabled in the EXTFUNC + * register (and only for PCI230+ hardware version 2 onwards). */ +#define PCI230P2_DAC_FIFO_EN (1<<8) /* FIFO enable */ +/* The following apply only if the DAC FIFO is enabled (and only for PCI230+ + * hardware version 2 onwards). */ +#define PCI230P2_DAC_TRIG_NONE (0<<2) /* No trigger */ +#define PCI230P2_DAC_TRIG_SW (1<<2) /* Software trigger trigger */ +#define PCI230P2_DAC_TRIG_EXTP (2<<2) /* EXTTRIG +ve edge trigger */ +#define PCI230P2_DAC_TRIG_EXTN (3<<2) /* EXTTRIG -ve edge trigger */ +#define PCI230P2_DAC_TRIG_Z2CT0 (4<<2) /* CT0-OUT +ve edge trigger */ +#define PCI230P2_DAC_TRIG_Z2CT1 (5<<2) /* CT1-OUT +ve edge trigger */ +#define PCI230P2_DAC_TRIG_Z2CT2 (6<<2) /* CT2-OUT +ve edge trigger */ +#define PCI230P2_DAC_TRIG_MASK (7<<2) +#define PCI230P2_DAC_FIFO_WRAP (1<<7) /* FIFO wraparound mode */ +#define PCI230P2_DAC_INT_FIFO_EMPTY (0<<9) /* FIFO interrupt empty */ +#define PCI230P2_DAC_INT_FIFO_NEMPTY (1<<9) +#define PCI230P2_DAC_INT_FIFO_NHALF (2<<9) /* FIFO intr not half full */ +#define PCI230P2_DAC_INT_FIFO_HALF (3<<9) +#define PCI230P2_DAC_INT_FIFO_NFULL (4<<9) /* FIFO interrupt not full */ +#define PCI230P2_DAC_INT_FIFO_FULL (5<<9) +#define PCI230P2_DAC_INT_FIFO_MASK (7<<9) + +/* DACCON read-only values. */ +#define PCI230_DAC_BUSY (1<<1) /* DAC busy. */ +/* The following apply only if the DAC FIFO is enabled (and only for PCI230+ + * hardware version 2 onwards). */ +#define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED (1<<5) /* Underrun error */ +#define PCI230P2_DAC_FIFO_EMPTY (1<<13) /* FIFO empty */ +#define PCI230P2_DAC_FIFO_FULL (1<<14) /* FIFO full */ +#define PCI230P2_DAC_FIFO_HALF (1<<15) /* FIFO half full */ + +/* DACCON write-only, transient values. */ +/* The following apply only if the DAC FIFO is enabled (and only for PCI230+ + * hardware version 2 onwards). */ +#define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR (1<<5) /* Clear underrun */ +#define PCI230P2_DAC_FIFO_RESET (1<<12) /* FIFO reset */ + +/* PCI230+ hardware version 2 DAC FIFO levels. */ +#define PCI230P2_DAC_FIFOLEVEL_HALF 512 +#define PCI230P2_DAC_FIFOLEVEL_FULL 1024 +/* Free space in DAC FIFO. */ +#define PCI230P2_DAC_FIFOROOM_EMPTY PCI230P2_DAC_FIFOLEVEL_FULL +#define PCI230P2_DAC_FIFOROOM_ONETOHALF \ + (PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF) +#define PCI230P2_DAC_FIFOROOM_HALFTOFULL 1 +#define PCI230P2_DAC_FIFOROOM_FULL 0 + +/* ADCCON read/write values. */ +#define PCI230_ADC_TRIG_NONE (0<<0) /* No trigger */ +#define PCI230_ADC_TRIG_SW (1<<0) /* Software trigger trigger */ +#define PCI230_ADC_TRIG_EXTP (2<<0) /* EXTTRIG +ve edge trigger */ +#define PCI230_ADC_TRIG_EXTN (3<<0) /* EXTTRIG -ve edge trigger */ +#define PCI230_ADC_TRIG_Z2CT0 (4<<0) /* CT0-OUT +ve edge trigger */ +#define PCI230_ADC_TRIG_Z2CT1 (5<<0) /* CT1-OUT +ve edge trigger */ +#define PCI230_ADC_TRIG_Z2CT2 (6<<0) /* CT2-OUT +ve edge trigger */ +#define PCI230_ADC_TRIG_MASK (7<<0) +#define PCI230_ADC_IR_UNI (0<<3) /* Input range unipolar */ +#define PCI230_ADC_IR_BIP (1<<3) /* Input range bipolar */ +#define PCI230_ADC_IR_MASK (1<<3) +#define PCI230_ADC_IM_SE (0<<4) /* Input mode single ended */ +#define PCI230_ADC_IM_DIF (1<<4) /* Input mode differential */ +#define PCI230_ADC_IM_MASK (1<<4) +#define PCI230_ADC_FIFO_EN (1<<8) /* FIFO enable */ +#define PCI230_ADC_INT_FIFO_EMPTY (0<<9) +#define PCI230_ADC_INT_FIFO_NEMPTY (1<<9) /* FIFO interrupt not empty */ +#define PCI230_ADC_INT_FIFO_NHALF (2<<9) +#define PCI230_ADC_INT_FIFO_HALF (3<<9) /* FIFO interrupt half full */ +#define PCI230_ADC_INT_FIFO_NFULL (4<<9) +#define PCI230_ADC_INT_FIFO_FULL (5<<9) /* FIFO interrupt full */ +#define PCI230P_ADC_INT_FIFO_THRESH (7<<9) /* FIFO interrupt threshold */ +#define PCI230_ADC_INT_FIFO_MASK (7<<9) + +/* ADCCON write-only, transient values. */ +#define PCI230_ADC_FIFO_RESET (1<<12) /* FIFO reset */ +#define PCI230_ADC_GLOB_RESET (1<<13) /* Global reset */ + +/* ADCCON read-only values. */ +#define PCI230_ADC_BUSY (1<<15) /* ADC busy */ +#define PCI230_ADC_FIFO_EMPTY (1<<12) /* FIFO empty */ +#define PCI230_ADC_FIFO_FULL (1<<13) /* FIFO full */ +#define PCI230_ADC_FIFO_HALF (1<<14) /* FIFO half full */ +#define PCI230_ADC_FIFO_FULL_LATCHED (1<<5) /* Indicates overrun occurred */ + +/* PCI230 ADC FIFO levels. */ +#define PCI230_ADC_FIFOLEVEL_HALFFULL 2049 /* Value for FIFO half full */ +#define PCI230_ADC_FIFOLEVEL_FULL 4096 /* FIFO size */ + +/* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger + * mode. Can be anything. */ +#define PCI230_ADC_CONV 0xffff + +/* PCI230+ EXTFUNC values. */ +#define PCI230P_EXTFUNC_GAT_EXTTRIG (1<<0) + /* Route EXTTRIG pin to external gate inputs. */ +/* PCI230+ hardware version 2 values. */ +#define PCI230P2_EXTFUNC_DACFIFO (1<<1) + /* Allow DAC FIFO to be enabled. */ + +/* + * Counter/timer clock input configuration sources. + */ +#define CLK_CLK 0 /* reserved (channel-specific clock) */ +#define CLK_10MHZ 1 /* internal 10 MHz clock */ +#define CLK_1MHZ 2 /* internal 1 MHz clock */ +#define CLK_100KHZ 3 /* internal 100 kHz clock */ +#define CLK_10KHZ 4 /* internal 10 kHz clock */ +#define CLK_1KHZ 5 /* internal 1 kHz clock */ +#define CLK_OUTNM1 6 /* output of channel-1 modulo total */ +#define CLK_EXT 7 /* external clock */ +/* Macro to construct clock input configuration register value. */ +#define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7)) +/* Timebases in ns. */ +#define TIMEBASE_10MHZ 100 +#define TIMEBASE_1MHZ 1000 +#define TIMEBASE_100KHZ 10000 +#define TIMEBASE_10KHZ 100000 +#define TIMEBASE_1KHZ 1000000 + +/* + * Counter/timer gate input configuration sources. + */ +#define GAT_VCC 0 /* VCC (i.e. enabled) */ +#define GAT_GND 1 /* GND (i.e. disabled) */ +#define GAT_EXT 2 /* external gate input (PPCn on PCI230) */ +#define GAT_NOUTNM2 3 /* inverted output of channel-2 modulo total */ +/* Macro to construct gate input configuration register value. */ +#define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7)) + +/* + * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260: + * + * Channel's Channel's + * clock input gate input + * Channel CLK_OUTNM1 GAT_NOUTNM2 + * ------- ---------- ----------- + * Z2-CT0 Z2-CT2-OUT /Z2-CT1-OUT + * Z2-CT1 Z2-CT0-OUT /Z2-CT2-OUT + * Z2-CT2 Z2-CT1-OUT /Z2-CT0-OUT + */ + +/* Interrupt enables/status register values. */ +#define PCI230_INT_DISABLE 0 +#define PCI230_INT_PPI_C0 (1<<0) +#define PCI230_INT_PPI_C3 (1<<1) +#define PCI230_INT_ADC (1<<2) +#define PCI230_INT_ZCLK_CT1 (1<<5) +/* For PCI230+ hardware version 2 when DAC FIFO enabled. */ +#define PCI230P2_INT_DAC (1<<4) + +#define PCI230_TEST_BIT(val, n) ((val>>n)&1) + /* Assumes bits numbered with zero offset, ie. 0-15 */ + +/* (Potentially) shared resources and their owners */ +enum { + RES_Z2CT0, /* Z2-CT0 */ + RES_Z2CT1, /* Z2-CT1 */ + RES_Z2CT2, /* Z2-CT2 */ + NUM_RESOURCES /* Number of (potentially) shared resources. */ +}; + +enum { + OWNER_NONE, /* Not owned */ + OWNER_AICMD, /* Owned by AI command */ + OWNER_AOCMD /* Owned by AO command */ +}; + +/* + * Handy macros. + */ + +/* Combine old and new bits. */ +#define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask))) + +/* A generic null function pointer value. */ +#define NULLFUNC 0 + +/* Current CPU. XXX should this be hard_smp_processor_id()? */ +#define THISCPU smp_processor_id() + +/* State flags for atomic bit operations */ +#define AI_CMD_STARTED 0 +#define AO_CMD_STARTED 1 + +/* + * Board descriptions for the two boards supported. + */ + +struct pci230_board { + const char *name; + unsigned short id; + int ai_chans; + int ai_bits; + int ao_chans; + int ao_bits; + int have_dio; + unsigned int min_hwver; /* Minimum hardware version supported. */ +}; +static const struct pci230_board pci230_boards[] = { + { + name: "pci230+", + id: PCI_DEVICE_ID_PCI230, + ai_chans:16, + ai_bits: 16, + ao_chans:2, + ao_bits: 12, + have_dio:1, + min_hwver:1, + }, + { + name: "pci260+", + id: PCI_DEVICE_ID_PCI260, + ai_chans:16, + ai_bits: 16, + ao_chans:0, + ao_bits: 0, + have_dio:0, + min_hwver:1, + }, + { + name: "pci230", + id: PCI_DEVICE_ID_PCI230, + ai_chans:16, + ai_bits: 12, + ao_chans:2, + ao_bits: 12, + have_dio:1, + }, + { + name: "pci260", + id: PCI_DEVICE_ID_PCI260, + ai_chans:16, + ai_bits: 12, + ao_chans:0, + ao_bits: 0, + have_dio:0, + }, + { + name: "amplc_pci230", /* Wildcard matches any above */ + id: PCI_DEVICE_ID_INVALID, + }, +}; + +static DEFINE_PCI_DEVICE_TABLE(pci230_pci_table) = { + {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0}, + {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pci230_pci_table); +/* + * Useful for shorthand access to the particular board structure + */ +#define n_pci230_boards (sizeof(pci230_boards)/sizeof(pci230_boards[0])) +#define thisboard ((const struct pci230_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct pci230_private { + struct pci_dev *pci_dev; + spinlock_t isr_spinlock; /* Interrupt spin lock */ + spinlock_t res_spinlock; /* Shared resources spin lock */ + spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */ + spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */ + unsigned long state; /* State flags */ + unsigned long iobase1; /* PCI230's I/O space 1 */ + unsigned int ao_readback[2]; /* Used for AO readback */ + unsigned int ai_scan_count; /* Number of analogue input scans + * remaining. */ + unsigned int ai_scan_pos; /* Current position within analogue + * input scan */ + unsigned int ao_scan_count; /* Number of analogue output scans + * remaining. */ + int intr_cpuid; /* ID of CPU running interrupt routine. */ + unsigned short hwver; /* Hardware version (for '+' models). */ + unsigned short adccon; /* ADCCON register value. */ + unsigned short daccon; /* DACCON register value. */ + unsigned short adcfifothresh; /* ADC FIFO programmable interrupt + * level threshold (PCI230+/260+). */ + unsigned short adcg; /* ADCG register value. */ + unsigned char int_en; /* Interrupt enables bits. */ + unsigned char ai_continuous; /* Flag set when cmd->stop_src == + * TRIG_NONE - user chooses to stop + * continuous conversion by + * cancelation. */ + unsigned char ao_continuous; /* Flag set when cmd->stop_src == + * TRIG_NONE - user chooses to stop + * continuous conversion by + * cancelation. */ + unsigned char ai_bipolar; /* Set if bipolar input range so we + * know to mangle it. */ + unsigned char ao_bipolar; /* Set if bipolar output range so we + * know to mangle it. */ + unsigned char ier; /* Copy of interrupt enables/status register. */ + unsigned char intr_running; /* Flag set in interrupt routine. */ + unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners. */ +}; + +#define devpriv ((struct pci230_private *)dev->private) + +/* PCI230 clock source periods in ns */ +static const unsigned int pci230_timebase[8] = { + [CLK_10MHZ] = TIMEBASE_10MHZ, + [CLK_1MHZ] = TIMEBASE_1MHZ, + [CLK_100KHZ] = TIMEBASE_100KHZ, + [CLK_10KHZ] = TIMEBASE_10KHZ, + [CLK_1KHZ] = TIMEBASE_1KHZ, +}; + +/* PCI230 analogue input range table */ +static const struct comedi_lrange pci230_ai_range = { 7, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5) + } +}; + +/* PCI230 analogue gain bits for each input range. */ +static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 }; + +/* PCI230 adccon bipolar flag for each analogue input range. */ +static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 }; + +/* PCI230 analogue output range table */ +static const struct comedi_lrange pci230_ao_range = { 2, { + UNI_RANGE(10), + BIP_RANGE(10) + } +}; + +/* PCI230 daccon bipolar flag for each analogue output range. */ +static const unsigned char pci230_ao_bipolar[2] = { 0, 1 }; + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int pci230_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pci230_detach(struct comedi_device * dev); +static struct comedi_driver driver_amplc_pci230 = { + driver_name:"amplc_pci230", + module:THIS_MODULE, + attach:pci230_attach, + detach:pci230_detach, + board_name:&pci230_boards[0].name, + offset:sizeof(pci230_boards[0]), + num_names:sizeof(pci230_boards) / sizeof(pci230_boards[0]), +}; + +COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table); + +static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static void pci230_ct_setup_ns_mode(struct comedi_device * dev, unsigned int ct, + unsigned int mode, uint64_t ns, unsigned int round); +static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round); +static void pci230_cancel_ct(struct comedi_device * dev, unsigned int ct); +static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG); +static int pci230_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int pci230_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void pci230_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s); +static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_subdevice * s); +static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subdevice * s); +static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int pci230_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int pci230_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void pci230_ai_stop(struct comedi_device * dev, struct comedi_subdevice * s); +static void pci230_handle_ai(struct comedi_device * dev, struct comedi_subdevice * s); + +static short pci230_ai_read(struct comedi_device * dev) +{ + /* Read sample. */ + short data = (short) inw(dev->iobase + PCI230_ADCDATA); + + /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower + * four bits reserved for expansion). */ + /* PCI230+ is 16 bit AI. */ + data = data >> (16 - thisboard->ai_bits); + + /* If a bipolar range was specified, mangle it (twos + * complement->straight binary). */ + if (devpriv->ai_bipolar) { + data ^= 1 << (thisboard->ai_bits - 1); + } + return data; +} + +static inline unsigned short pci230_ao_mangle_datum(struct comedi_device * dev, + short datum) +{ + /* If a bipolar range was specified, mangle it (straight binary->twos + * complement). */ + if (devpriv->ao_bipolar) { + datum ^= 1 << (thisboard->ao_bits - 1); + } + + /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower + * four bits reserved for expansion). */ + /* PCI230+ is also 12 bit AO. */ + datum <<= (16 - thisboard->ao_bits); + return (unsigned short)datum; +} + +static inline void pci230_ao_write_nofifo(struct comedi_device * dev, short datum, + unsigned int chan) +{ + /* Store unmangled datum to be read back later. */ + devpriv->ao_readback[chan] = datum; + + /* Write mangled datum to appropriate DACOUT register. */ + outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0) + ? PCI230_DACOUT1 : PCI230_DACOUT2)); +} + +static inline void pci230_ao_write_fifo(struct comedi_device * dev, short datum, + unsigned int chan) +{ + /* Store unmangled datum to be read back later. */ + devpriv->ao_readback[chan] = datum; + + /* Write mangled datum to appropriate DACDATA register. */ + outw(pci230_ao_mangle_datum(dev, datum), + dev->iobase + PCI230P2_DACDATA); +} + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pci230_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase1, iobase2; + /* PCI230's I/O spaces 1 and 2 respectively. */ + struct pci_dev *pci_dev; + int i = 0, irq_hdl, rc; + + printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor, + thisboard->name, it->options[0], it->options[1]); + + /* Allocate the private structure area using alloc_private(). + * Macro defined in comedidev.h - memsets struct fields to 0. */ + if ((alloc_private(dev, sizeof(struct pci230_private))) < 0) { + return -ENOMEM; + } + spin_lock_init(&devpriv->isr_spinlock); + spin_lock_init(&devpriv->res_spinlock); + spin_lock_init(&devpriv->ai_stop_spinlock); + spin_lock_init(&devpriv->ao_stop_spinlock); + /* Find card */ + for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pci_dev != NULL; + pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) { + if (it->options[0] || it->options[1]) { + /* Match against bus/slot options. */ + if (it->options[0] != pci_dev->bus->number || + it->options[1] != PCI_SLOT(pci_dev->devfn)) + continue; + } + if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON) + continue; + if (thisboard->id == PCI_DEVICE_ID_INVALID) { + /* The name was specified as "amplc_pci230" which is + * used to match any supported device. Replace the + * current dev->board_ptr with one that matches the + * PCI device ID. */ + for (i = 0; i < n_pci230_boards; i++) { + if (pci_dev->device == pci230_boards[i].id) { + if (pci230_boards[i].min_hwver > 0) { + /* Check for a '+' model. + * First check length of + * registers. */ + if (pci_resource_len(pci_dev, 3) + < 32) { + /* Not a '+' model. */ + continue; + } + /* TODO: temporarily enable the + * PCI device and read the + * hardware version register. + * For now assume it's okay. */ + } + /* Change board_ptr to matched board */ + dev->board_ptr = &pci230_boards[i]; + break; + } + } + if (i < n_pci230_boards) + break; + } else { + /* The name was specified as a specific device name. + * The current dev->board_ptr is correct. Check + * whether it matches the PCI device ID. */ + if (thisboard->id == pci_dev->device) { + /* Check minimum hardware version. */ + if (thisboard->min_hwver > 0) { + /* Looking for a '+' model. First + * check length of registers. */ + if (pci_resource_len(pci_dev, 3) < 32) { + /* Not a '+' model. */ + continue; + } + /* TODO: temporarily enable the PCI + * device and read the hardware version + * register. For now, assume it's + * okay. */ + break; + } else { + break; + } + } + } + } + if (!pci_dev) { + printk("comedi%d: No %s card found\n", dev->minor, + thisboard->name); + return -EIO; + } + devpriv->pci_dev = pci_dev; + + /* + * Initialize dev->board_name. + */ + dev->board_name = thisboard->name; + + /* Enable PCI device and reserve I/O spaces. */ + if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) { + printk("comedi%d: failed to enable PCI device " + "and request regions\n", dev->minor); + return -EIO; + } + + /* Read base addresses of the PCI230's two I/O regions from PCI + * configuration register. */ + iobase1 = pci_resource_start(pci_dev, 2); + iobase2 = pci_resource_start(pci_dev, 3); + + printk("comedi%d: %s I/O region 1 0x%04lx I/O region 2 0x%04lx\n", + dev->minor, dev->board_name, iobase1, iobase2); + + devpriv->iobase1 = iobase1; + dev->iobase = iobase2; + + /* Read bits of DACCON register - only the output range. */ + devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK; + + /* Read hardware version register and set extended function register + * if they exist. */ + if (pci_resource_len(pci_dev, 3) >= 32) { + unsigned short extfunc = 0; + + devpriv->hwver = inw(dev->iobase + PCI230P_HWVER); + if (devpriv->hwver < thisboard->min_hwver) { + printk("comedi%d: %s - bad hardware version " + "- got %u, need %u\n", dev->minor, + dev->board_name, devpriv->hwver, + thisboard->min_hwver); + return -EIO; + } + if (devpriv->hwver > 0) { + if (!thisboard->have_dio) { + /* No DIO ports. Route counters' external gates + * to the EXTTRIG signal (PCI260+ pin 17). + * (Otherwise, they would be routed to DIO + * inputs PC0, PC1 and PC2 which don't exist + * on PCI260[+].) */ + extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG; + } + if ((thisboard->ao_chans > 0) + && (devpriv->hwver >= 2)) { + /* Enable DAC FIFO functionality. */ + extfunc |= PCI230P2_EXTFUNC_DACFIFO; + } + } + outw(extfunc, dev->iobase + PCI230P_EXTFUNC); + if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) { + /* Temporarily enable DAC FIFO, reset it and disable + * FIFO wraparound. */ + outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN + | PCI230P2_DAC_FIFO_RESET, + dev->iobase + PCI230_DACCON); + /* Clear DAC FIFO channel enable register. */ + outw(0, dev->iobase + PCI230P2_DACEN); + /* Disable DAC FIFO. */ + outw(devpriv->daccon, dev->iobase + PCI230_DACCON); + } + } + + /* Disable board's interrupts. */ + outb(0, devpriv->iobase1 + PCI230_INT_SCE); + + /* Set ADC to a reasonable state. */ + devpriv->adcg = 0; + devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE + | PCI230_ADC_IR_BIP; + outw(1 << 0, dev->iobase + PCI230_ADCEN); + outw(devpriv->adcg, dev->iobase + PCI230_ADCG); + outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, + dev->iobase + PCI230_ADCCON); + + /* Register the interrupt handler. */ + irq_hdl = comedi_request_irq(devpriv->pci_dev->irq, pci230_interrupt, + IRQF_SHARED, "amplc_pci230", dev); + if (irq_hdl < 0) { + printk("comedi%d: unable to register irq, " + "commands will not be available %d\n", dev->minor, + devpriv->pci_dev->irq); + } else { + dev->irq = devpriv->pci_dev->irq; + printk("comedi%d: registered irq %u\n", dev->minor, + devpriv->pci_dev->irq); + } + + /* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_subdevices(dev, 3) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; + s->n_chan = thisboard->ai_chans; + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = &pci230_ai_range; + s->insn_read = &pci230_ai_rinsn; + s->len_chanlist = 256; /* but there are restrictions. */ + /* Only register commands if the interrupt handler is installed. */ + if (irq_hdl == 0) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->do_cmd = &pci230_ai_cmd; + s->do_cmdtest = &pci230_ai_cmdtest; + s->cancel = pci230_ai_cancel; + } + + s = dev->subdevices + 1; + /* analog output subdevice */ + if (thisboard->ao_chans > 0) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = thisboard->ao_chans;; + s->maxdata = (1 << thisboard->ao_bits) - 1; + s->range_table = &pci230_ao_range; + s->insn_write = &pci230_ao_winsn; + s->insn_read = &pci230_ao_rinsn; + s->len_chanlist = thisboard->ao_chans; + /* Only register commands if the interrupt handler is + * installed. */ + if (irq_hdl == 0) { + dev->write_subdev = s; + s->subdev_flags |= SDF_CMD_WRITE; + s->do_cmd = &pci230_ao_cmd; + s->do_cmdtest = &pci230_ao_cmdtest; + s->cancel = pci230_ao_cancel; + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 2; + /* digital i/o subdevice */ + if (thisboard->have_dio) { + rc = subdev_8255_init(dev, s, NULL, + (devpriv->iobase1 + PCI230_PPI_X_BASE)); + if (rc < 0) + return rc; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + printk("comedi%d: attached\n", dev->minor); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pci230_detach(struct comedi_device * dev) +{ + printk("comedi%d: amplc_pci230: remove\n", dev->minor); + + if (dev->subdevices && thisboard->have_dio) + /* Clean up dio subdevice. */ + subdev_8255_cleanup(dev, dev->subdevices + 2); + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + if (devpriv) { + if (devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + } + + return 0; +} + +static int get_resources(struct comedi_device * dev, unsigned int res_mask, + unsigned char owner) +{ + int ok; + unsigned int i; + unsigned int b; + unsigned int claimed; + unsigned long irqflags; + + ok = 1; + claimed = 0; + comedi_spin_lock_irqsave(&devpriv->res_spinlock, irqflags); + for (b = 1, i = 0; (i < NUM_RESOURCES) + && (res_mask != 0); b <<= 1, i++) { + if ((res_mask & b) != 0) { + res_mask &= ~b; + if (devpriv->res_owner[i] == OWNER_NONE) { + devpriv->res_owner[i] = owner; + claimed |= b; + } else if (devpriv->res_owner[i] != owner) { + for (b = 1, i = 0; claimed != 0; b <<= 1, i++) { + if ((claimed & b) != 0) { + devpriv->res_owner[i] + = OWNER_NONE; + claimed &= ~b; + } + } + ok = 0; + break; + } + } + } + comedi_spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags); + return ok; +} + +static inline int get_one_resource(struct comedi_device * dev, unsigned int resource, + unsigned char owner) +{ + return get_resources(dev, (1U << resource), owner); +} + +static void put_resources(struct comedi_device * dev, unsigned int res_mask, + unsigned char owner) +{ + unsigned int i; + unsigned int b; + unsigned long irqflags; + + comedi_spin_lock_irqsave(&devpriv->res_spinlock, irqflags); + for (b = 1, i = 0; (i < NUM_RESOURCES) + && (res_mask != 0); b <<= 1, i++) { + if ((res_mask & b) != 0) { + res_mask &= ~b; + if (devpriv->res_owner[i] == owner) { + devpriv->res_owner[i] = OWNER_NONE; + } + } + } + comedi_spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags); +} + +static inline void put_one_resource(struct comedi_device * dev, unsigned int resource, + unsigned char owner) +{ + put_resources(dev, (1U << resource), owner); +} + +static inline void put_all_resources(struct comedi_device * dev, unsigned char owner) +{ + put_resources(dev, (1U << NUM_RESOURCES) - 1, owner); +} + +/* + * COMEDI_SUBD_AI instruction; + */ +static int pci230_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int n, i; + unsigned int chan, range, aref; + unsigned int gainshift; + unsigned int status; + unsigned short adccon, adcen; + + /* Unpack channel and range. */ + chan = CR_CHAN(insn->chanspec); + range = CR_RANGE(insn->chanspec); + aref = CR_AREF(insn->chanspec); + if (aref == AREF_DIFF) { + /* Differential. */ + if (chan >= s->n_chan / 2) { + DPRINTK("comedi%d: amplc_pci230: ai_rinsn: " + "differential channel number out of range " + "0 to %u\n", dev->minor, (s->n_chan / 2) - 1); + return -EINVAL; + } + } + + /* Use Z2-CT2 as a conversion trigger instead of the built-in + * software trigger, as otherwise triggering of differential channels + * doesn't work properly for some versions of PCI230/260. Also set + * FIFO mode because the ADC busy bit only works for software triggers. + */ + adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN; + /* Set Z2-CT2 output low to avoid any false triggers. */ + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0); + devpriv->ai_bipolar = pci230_ai_bipolar[range]; + if (aref == AREF_DIFF) { + /* Differential. */ + gainshift = chan * 2; + if (devpriv->hwver == 0) { + /* Original PCI230/260 expects both inputs of the + * differential channel to be enabled. */ + adcen = 3 << gainshift; + } else { + /* PCI230+/260+ expects only one input of the + * differential channel to be enabled. */ + adcen = 1 << gainshift; + } + adccon |= PCI230_ADC_IM_DIF; + } else { + /* Single ended. */ + adcen = 1 << chan; + gainshift = chan & ~1; + adccon |= PCI230_ADC_IM_SE; + } + devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) + | (pci230_ai_gain[range] << gainshift); + if (devpriv->ai_bipolar) { + adccon |= PCI230_ADC_IR_BIP; + } else { + adccon |= PCI230_ADC_IR_UNI; + } + + /* Enable only this channel in the scan list - otherwise by default + * we'll get one sample from each channel. */ + outw(adcen, dev->iobase + PCI230_ADCEN); + + /* Set gain for channel. */ + outw(devpriv->adcg, dev->iobase + PCI230_ADCG); + + /* Specify uni/bip, se/diff, conversion source, and reset FIFO. */ + devpriv->adccon = adccon; + outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON); + + /* Convert n samples */ + for (n = 0; n < insn->n; n++) { + /* Trigger conversion by toggling Z2-CT2 output (finish with + * output high). */ + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, + I8254_MODE0); + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, + I8254_MODE1); + +#define TIMEOUT 100 + /* wait for conversion to end */ + for (i = 0; i < TIMEOUT; i++) { + status = inw(dev->iobase + PCI230_ADCCON); + if (!(status & PCI230_ADC_FIFO_EMPTY)) + break; + comedi_udelay(1); + } + if (i == TIMEOUT) { + /* rt_printk() should be used instead of printk() + * whenever the code can be called from real-time. */ + rt_printk("timeout\n"); + return -ETIMEDOUT; + } + + /* read data */ + data[n] = pci230_ai_read(dev); + } + + /* return the number of samples read/written */ + return n; +} + +/* + * COMEDI_SUBD_AO instructions; + */ +static int pci230_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan, range; + + /* Unpack channel and range. */ + chan = CR_CHAN(insn->chanspec); + range = CR_RANGE(insn->chanspec); + + /* Set range - see analogue output range table; 0 => unipolar 10V, + * 1 => bipolar +/-10V range scale */ + devpriv->ao_bipolar = pci230_ao_bipolar[range]; + outw(range, dev->iobase + PCI230_DACCON); + + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { + /* Write value to DAC and store it. */ + pci230_ao_write_nofifo(dev, data[i], chan); + } + + /* return the number of samples read/written */ + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. */ +static int pci230_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +static int pci230_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + unsigned int tmp; + + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* Step 1: make sure trigger sources are trivially valid. + * "invalid source" returned by comedilib to user mode process + * if this fails. */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) { + /* + * For PCI230+ hardware version 2 onwards, allow external + * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25). + * + * FIXME: The permitted scan_begin_src values shouldn't depend + * on devpriv->hwver (the detected card's actual hardware + * version). They should only depend on thisboard->min_hwver + * (the static capabilities of the configured card). To fix + * it, a new card model, e.g. "pci230+2" would have to be + * defined with min_hwver set to 2. It doesn't seem worth it + * for this alone. At the moment, please consider + * scan_begin_src==TRIG_EXT support to be a bonus rather than a + * guarantee! + */ + cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT; + } else { + cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT; + } + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* Step 2: make sure trigger sources are unique and mutually compatible + * "source conflict" returned by comedilib to user mode process + * if this fails. */ + + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; + + if (err) + return 2; + + /* Step 3: make sure arguments are trivially compatible. + * "invalid argument" returned by comedilib to user mode process + * if this fails. */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } +#define MAX_SPEED_AO 8000 /* 8000 ns => 125 kHz */ +#define MIN_SPEED_AO 4294967295u /* 4294967295ns = 4.29s */ + /*- Comedi limit due to unsigned int cmd. Driver limit + * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard + * clock) = 65.536s */ + + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + if (cmd->scan_begin_arg < MAX_SPEED_AO) { + cmd->scan_begin_arg = MAX_SPEED_AO; + err++; + } + if (cmd->scan_begin_arg > MIN_SPEED_AO) { + cmd->scan_begin_arg = MIN_SPEED_AO; + err++; + } + break; + case TRIG_EXT: + /* External trigger - for PCI230+ hardware version 2 onwards. */ + /* Trigger number must be 0. */ + if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) { + cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, + ~CR_FLAGS_MASK); + err++; + } + /* The only flags allowed are CR_EDGE and CR_INVERT. The + * CR_EDGE flag is ignored. */ + if ((cmd->scan_begin_arg + & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != + 0) { + cmd->scan_begin_arg = + COMBINE(cmd->scan_begin_arg, 0, + CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT)); + err++; + } + break; + default: + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + break; + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_NONE) { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* Step 4: fix up any arguments. + * "argument conflict" returned by comedilib to user mode process + * if this fails. */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + pci230_ns_to_single_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + + if (err) + return 4; + + /* Step 5: check channel list if it exists. */ + + if (cmd->chanlist && cmd->chanlist_len > 0) { + enum { + seq_err = (1 << 0), + range_err = (1 << 1) + }; + unsigned int errors; + unsigned int n; + unsigned int chan, prev_chan; + unsigned int range, first_range; + + prev_chan = CR_CHAN(cmd->chanlist[0]); + first_range = CR_RANGE(cmd->chanlist[0]); + errors = 0; + for (n = 1; n < cmd->chanlist_len; n++) { + chan = CR_CHAN(cmd->chanlist[n]); + range = CR_RANGE(cmd->chanlist[n]); + /* Channel numbers must strictly increase. */ + if (chan < prev_chan) { + errors |= seq_err; + } + /* Ranges must be the same. */ + if (range != first_range) { + errors |= range_err; + } + prev_chan = chan; + } + if (errors != 0) { + err++; + if ((errors & seq_err) != 0) { + DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: " + "channel numbers must increase\n", + dev->minor); + } + if ((errors & range_err) != 0) { + DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: " + "channels must have the same range\n", + dev->minor); + } + } + } + + if (err) + return 5; + + return 0; +} + +static int pci230_ao_inttrig_scan_begin(struct comedi_device * dev, + struct comedi_subdevice * s, unsigned int trig_num) +{ + unsigned long irqflags; + + if (trig_num != 0) + return -EINVAL; + + comedi_spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags); + if (test_bit(AO_CMD_STARTED, &devpriv->state)) { + /* Perform scan. */ + if (devpriv->hwver < 2) { + /* Not using DAC FIFO. */ + comedi_spin_unlock_irqrestore(&devpriv-> + ao_stop_spinlock, irqflags); + pci230_handle_ao_nofifo(dev, s); + comedi_event(dev, s); + } else { + /* Using DAC FIFO. */ + /* Read DACSWTRIG register to trigger conversion. */ + inw(dev->iobase + PCI230P2_DACSWTRIG); + comedi_spin_unlock_irqrestore(&devpriv-> + ao_stop_spinlock, irqflags); + } + /* Delay. Should driver be responsible for this? */ + /* XXX TODO: See if DAC busy bit can be used. */ + comedi_udelay(8); + } + + return 1; +} + +static void pci230_ao_start(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned long irqflags; + + set_bit(AO_CMD_STARTED, &devpriv->state); + if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) { + /* An empty acquisition! */ + async->events |= COMEDI_CB_EOA; + pci230_ao_stop(dev, s); + comedi_event(dev, s); + } else { + if (devpriv->hwver >= 2) { + /* Using DAC FIFO. */ + unsigned short scantrig; + int run; + + /* Preload FIFO data. */ + run = pci230_handle_ao_fifo(dev, s); + comedi_event(dev, s); + if (!run) { + /* Stopped. */ + return; + } + /* Set scan trigger source. */ + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + scantrig = PCI230P2_DAC_TRIG_Z2CT1; + break; + case TRIG_EXT: + /* Trigger on EXTTRIG/EXTCONVCLK pin. */ + if ((cmd->scan_begin_arg & CR_INVERT) == 0) { + /* +ve edge */ + scantrig = PCI230P2_DAC_TRIG_EXTP; + } else { + /* -ve edge */ + scantrig = PCI230P2_DAC_TRIG_EXTN; + } + break; + case TRIG_INT: + scantrig = PCI230P2_DAC_TRIG_SW; + break; + default: + /* Shouldn't get here. */ + scantrig = PCI230P2_DAC_TRIG_NONE; + break; + } + devpriv->daccon = (devpriv->daccon + & ~PCI230P2_DAC_TRIG_MASK) | scantrig; + outw(devpriv->daccon, dev->iobase + PCI230_DACCON); + + } + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + if (devpriv->hwver < 2) { + /* Not using DAC FIFO. */ + /* Enable CT1 timer interrupt. */ + comedi_spin_lock_irqsave(&devpriv->isr_spinlock, + irqflags); + devpriv->int_en |= PCI230_INT_ZCLK_CT1; + devpriv->ier |= PCI230_INT_ZCLK_CT1; + outb(devpriv->ier, + devpriv->iobase1 + PCI230_INT_SCE); + comedi_spin_unlock_irqrestore(&devpriv-> + isr_spinlock, irqflags); + } + /* Set CT1 gate high to start counting. */ + outb(GAT_CONFIG(1, GAT_VCC), + devpriv->iobase1 + PCI230_ZGAT_SCE); + break; + case TRIG_INT: + async->inttrig = pci230_ao_inttrig_scan_begin; + break; + } + if (devpriv->hwver >= 2) { + /* Using DAC FIFO. Enable DAC FIFO interrupt. */ + comedi_spin_lock_irqsave(&devpriv->isr_spinlock, + irqflags); + devpriv->int_en |= PCI230P2_INT_DAC; + devpriv->ier |= PCI230P2_INT_DAC; + outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); + comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, + irqflags); + } + } +} + +static int pci230_ao_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trig_num) +{ + if (trig_num != 0) + return -EINVAL; + + s->async->inttrig = NULLFUNC; + pci230_ao_start(dev, s); + + return 1; +} + +static int pci230_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned short daccon; + unsigned int range; + + /* Get the command. */ + struct comedi_cmd *cmd = &s->async->cmd; + + if (cmd->scan_begin_src == TRIG_TIMER) { + /* Claim Z2-CT1. */ + if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD)) { + return -EBUSY; + } + } + + /* Get number of scans required. */ + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ao_scan_count = cmd->stop_arg; + devpriv->ao_continuous = 0; + } else { + /* TRIG_NONE, user calls cancel. */ + devpriv->ao_scan_count = 0; + devpriv->ao_continuous = 1; + } + + /* Set range - see analogue output range table; 0 => unipolar 10V, + * 1 => bipolar +/-10V range scale */ + range = CR_RANGE(cmd->chanlist[0]); + devpriv->ao_bipolar = pci230_ao_bipolar[range]; + daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI; + /* Use DAC FIFO for hardware version 2 onwards. */ + if (devpriv->hwver >= 2) { + unsigned short dacen; + unsigned int i; + + dacen = 0; + for (i = 0; i < cmd->chanlist_len; i++) { + dacen |= 1 << CR_CHAN(cmd->chanlist[i]); + } + /* Set channel scan list. */ + outw(dacen, dev->iobase + PCI230P2_DACEN); + /* + * Enable DAC FIFO. + * Set DAC scan source to 'none'. + * Set DAC FIFO interrupt trigger level to 'not half full'. + * Reset DAC FIFO and clear underrun. + * + * N.B. DAC FIFO interrupts are currently disabled. + */ + daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET + | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR + | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF; + } + + /* Set DACCON. */ + outw(daccon, dev->iobase + PCI230_DACCON); + /* Preserve most of DACCON apart from write-only, transient bits. */ + devpriv->daccon = daccon + & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR); + + if (cmd->scan_begin_src == TRIG_TIMER) { + /* Set the counter timer 1 to the specified scan frequency. */ + /* cmd->scan_begin_arg is sampling period in ns */ + /* gate it off for now. */ + outb(GAT_CONFIG(1, GAT_GND), + devpriv->iobase1 + PCI230_ZGAT_SCE); + pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3, + cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); + } + + /* N.B. cmd->start_src == TRIG_INT */ + s->async->inttrig = pci230_ao_inttrig_start; + + return 0; +} + +static int pci230_ai_check_scan_period(struct comedi_cmd * cmd) +{ + unsigned int min_scan_period, chanlist_len; + int err = 0; + + chanlist_len = cmd->chanlist_len; + if (cmd->chanlist_len == 0) { + chanlist_len = 1; + } + min_scan_period = chanlist_len * cmd->convert_arg; + if ((min_scan_period < chanlist_len) + || (min_scan_period < cmd->convert_arg)) { + /* Arithmetic overflow. */ + min_scan_period = UINT_MAX; + err++; + } + if (cmd->scan_begin_arg < min_scan_period) { + cmd->scan_begin_arg = min_scan_period; + err++; + } + + return !err; +} + +static int pci230_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + unsigned int tmp; + + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4,5 or 0, depending on which tests + * the command passes. */ + + /* Step 1: make sure trigger sources are trivially valid. + * "invalid source" returned by comedilib to user mode process + * if this fails. */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + /* Unfortunately, we cannot trigger a scan off an external source + * on the PCI260 board, since it uses the PPIC0 (DIO) input, which + * isn't present on the PCI260. For PCI260+ we can use the + * EXTTRIG/EXTCONVCLK input on pin 17 instead. */ + if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) { + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT + | TRIG_EXT; + } else { + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT; + } + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* Step 2: make sure trigger sources are unique and mutually compatible + * "source conflict" returned by comedilib to user mode process + * if this fails. */ + + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; + + /* If scan_begin_src is not TRIG_FOLLOW, then a monostable will be + * set up to generate a fixed number of timed conversion pulses. */ + if ((cmd->scan_begin_src != TRIG_FOLLOW) + && (cmd->convert_src != TRIG_TIMER)) + err++; + + if (err) + return 2; + + /* Step 3: make sure arguments are trivially compatible. + * "invalid argument" returned by comedilib to user mode process + * if this fails. */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } +#define MAX_SPEED_AI_SE 3200 /* PCI230 SE: 3200 ns => 312.5 kHz */ +#define MAX_SPEED_AI_DIFF 8000 /* PCI230 DIFF: 8000 ns => 125 kHz */ +#define MAX_SPEED_AI_PLUS 4000 /* PCI230+: 4000 ns => 250 kHz */ +#define MIN_SPEED_AI 4294967295u /* 4294967295ns = 4.29s */ + /*- Comedi limit due to unsigned int cmd. Driver limit + * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard + * clock) = 65.536s */ + + if (cmd->convert_src == TRIG_TIMER) { + unsigned int max_speed_ai; + + if (devpriv->hwver == 0) { + /* PCI230 or PCI260. Max speed depends whether + * single-ended or pseudo-differential. */ + if (cmd->chanlist && (cmd->chanlist_len > 0)) { + /* Peek analogue reference of first channel. */ + if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) { + max_speed_ai = MAX_SPEED_AI_DIFF; + } else { + max_speed_ai = MAX_SPEED_AI_SE; + } + } else { + /* No channel list. Assume single-ended. */ + max_speed_ai = MAX_SPEED_AI_SE; + } + } else { + /* PCI230+ or PCI260+. */ + max_speed_ai = MAX_SPEED_AI_PLUS; + } + + if (cmd->convert_arg < max_speed_ai) { + cmd->convert_arg = max_speed_ai; + err++; + } + if (cmd->convert_arg > MIN_SPEED_AI) { + cmd->convert_arg = MIN_SPEED_AI; + err++; + } + } else if (cmd->convert_src == TRIG_EXT) { + /* + * external trigger + * + * convert_arg == (CR_EDGE | 0) + * => trigger on +ve edge. + * convert_arg == (CR_EDGE | CR_INVERT | 0) + * => trigger on -ve edge. + */ + if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) { + /* Trigger number must be 0. */ + if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) { + cmd->convert_arg = COMBINE(cmd->convert_arg, 0, + ~CR_FLAGS_MASK); + err++; + } + /* The only flags allowed are CR_INVERT and CR_EDGE. + * CR_EDGE is required. */ + if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT)) + != CR_EDGE) { + /* Set CR_EDGE, preserve CR_INVERT. */ + cmd->convert_arg = + COMBINE(cmd->start_arg, (CR_EDGE | 0), + CR_FLAGS_MASK & ~CR_INVERT); + err++; + } + } else { + /* Backwards compatibility with previous versions. */ + /* convert_arg == 0 => trigger on -ve edge. */ + /* convert_arg == 1 => trigger on +ve edge. */ + if (cmd->convert_arg > 1) { + /* Default to trigger on +ve edge. */ + cmd->convert_arg = 1; + err++; + } + } + } else { + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + if (cmd->stop_src == TRIG_NONE) { + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (cmd->scan_begin_src == TRIG_EXT) { + /* external "trigger" to begin each scan + * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate + * of CT2 (sample convert trigger is CT2) */ + if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) { + cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, + ~CR_FLAGS_MASK); + err++; + } + /* The only flag allowed is CR_EDGE, which is ignored. */ + if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) { + cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0, + CR_FLAGS_MASK & ~CR_EDGE); + err++; + } + } else if (cmd->scan_begin_src == TRIG_TIMER) { + /* N.B. cmd->convert_arg is also TRIG_TIMER */ + if (!pci230_ai_check_scan_period(cmd)) { + err++; + } + } else { + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* Step 4: fix up any arguments. + * "argument conflict" returned by comedilib to user mode process + * if this fails. */ + + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + pci230_ns_to_single_timer(&cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + } + + if (cmd->scan_begin_src == TRIG_TIMER) { + /* N.B. cmd->convert_arg is also TRIG_TIMER */ + tmp = cmd->scan_begin_arg; + pci230_ns_to_single_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + if (!pci230_ai_check_scan_period(cmd)) { + /* Was below minimum required. Round up. */ + pci230_ns_to_single_timer(&cmd->scan_begin_arg, + TRIG_ROUND_UP); + pci230_ai_check_scan_period(cmd); + } + if (tmp != cmd->scan_begin_arg) + err++; + } + + if (err) + return 4; + + /* Step 5: check channel list if it exists. */ + + if (cmd->chanlist && cmd->chanlist_len > 0) { + enum { + seq_err = 1 << 0, + rangepair_err = 1 << 1, + polarity_err = 1 << 2, + aref_err = 1 << 3, + diffchan_err = 1 << 4, + buggy_chan0_err = 1 << 5 + }; + unsigned int errors; + unsigned int chan, prev_chan; + unsigned int range, prev_range; + unsigned int polarity, prev_polarity; + unsigned int aref, prev_aref; + unsigned int subseq_len; + unsigned int n; + + subseq_len = 0; + errors = 0; + prev_chan = prev_aref = prev_range = prev_polarity = 0; + for (n = 0; n < cmd->chanlist_len; n++) { + chan = CR_CHAN(cmd->chanlist[n]); + range = CR_RANGE(cmd->chanlist[n]); + aref = CR_AREF(cmd->chanlist[n]); + polarity = pci230_ai_bipolar[range]; + /* Only the first half of the channels are available if + * differential. (These are remapped in software. In + * hardware, only the even channels are available.) */ + if ((aref == AREF_DIFF) + && (chan >= (s->n_chan / 2))) { + errors |= diffchan_err; + } + if (n > 0) { + /* Channel numbers must strictly increase or + * subsequence must repeat exactly. */ + if ((chan <= prev_chan) + && (subseq_len == 0)) { + subseq_len = n; + } + if ((subseq_len > 0) + && (cmd->chanlist[n] != + cmd->chanlist[n % + subseq_len])) { + errors |= seq_err; + } + /* Channels must have same AREF. */ + if (aref != prev_aref) { + errors |= aref_err; + } + /* Channel ranges must have same polarity. */ + if (polarity != prev_polarity) { + errors |= polarity_err; + } + /* Single-ended channel pairs must have same + * range. */ + if ((aref != AREF_DIFF) + && (((chan ^ prev_chan) & ~1) == 0) + && (range != prev_range)) { + errors |= rangepair_err; + } + } + prev_chan = chan; + prev_range = range; + prev_aref = aref; + prev_polarity = polarity; + } + if (subseq_len == 0) { + /* Subsequence is whole sequence. */ + subseq_len = n; + } + /* If channel list is a repeating subsequence, need a whole + * number of repeats. */ + if ((n % subseq_len) != 0) { + errors |= seq_err; + } + if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) { + /* + * Buggy PCI230+ or PCI260+ requires channel 0 to be + * (first) in the sequence if the sequence contains + * more than one channel. Hardware versions 1 and 2 + * have the bug. There is no hardware version 3. + * + * Actually, there are two firmwares that report + * themselves as hardware version 1 (the boards + * have different ADC chips with slightly different + * timing requirements, which was supposed to be + * invisible to software). The first one doesn't + * seem to have the bug, but the second one + * does, and we can't tell them apart! + */ + if ((subseq_len > 1) + && (CR_CHAN(cmd->chanlist[0]) != 0)) { + errors |= buggy_chan0_err; + } + } + if (errors != 0) { + err++; + if ((errors & seq_err) != 0) { + DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " + "channel numbers must increase or " + "sequence must repeat exactly\n", + dev->minor); + } + if ((errors & rangepair_err) != 0) { + DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " + "single-ended channel pairs must " + "have the same range\n", dev->minor); + } + if ((errors & polarity_err) != 0) { + DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " + "channel sequence ranges must be all " + "bipolar or all unipolar\n", + dev->minor); + } + if ((errors & aref_err) != 0) { + DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " + "channel sequence analogue references " + "must be all the same (single-ended " + "or differential)\n", dev->minor); + } + if ((errors & diffchan_err) != 0) { + DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: " + "differential channel number out of " + "range 0 to %u\n", dev->minor, + (s->n_chan / 2) - 1); + } + if ((errors & buggy_chan0_err) != 0) { + /* Use printk instead of DPRINTK here. */ + printk("comedi: comedi%d: amplc_pci230: " + "ai_cmdtest: Buggy PCI230+/260+ " + "h/w version %u requires first channel " + "of multi-channel sequence to be 0 " + "(corrected in h/w version 4)\n", + dev->minor, devpriv->hwver); + } + } + } + + if (err) + return 5; + + return 0; +} + +static void pci230_ai_update_fifo_trigger_level(struct comedi_device * dev, + struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int scanlen = cmd->scan_end_arg; + unsigned int wake; + unsigned short triglev; + unsigned short adccon; + + if ((cmd->flags & TRIG_WAKE_EOS) != 0) { + /* Wake at end of scan. */ + wake = scanlen - devpriv->ai_scan_pos; + } else { + if (devpriv->ai_continuous + || (devpriv->ai_scan_count + >= PCI230_ADC_FIFOLEVEL_HALFFULL) + || (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) { + wake = PCI230_ADC_FIFOLEVEL_HALFFULL; + } else { + wake = (devpriv->ai_scan_count * scanlen) + - devpriv->ai_scan_pos; + } + } + if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) { + triglev = PCI230_ADC_INT_FIFO_HALF; + } else { + if ((wake > 1) && (devpriv->hwver > 0)) { + /* PCI230+/260+ programmable FIFO interrupt level. */ + if (devpriv->adcfifothresh != wake) { + devpriv->adcfifothresh = wake; + outw(wake, dev->iobase + PCI230P_ADCFFTH); + } + triglev = PCI230P_ADC_INT_FIFO_THRESH; + } else { + triglev = PCI230_ADC_INT_FIFO_NEMPTY; + } + } + adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev; + if (adccon != devpriv->adccon) { + devpriv->adccon = adccon; + outw(adccon, dev->iobase + PCI230_ADCCON); + } +} + +static int pci230_ai_inttrig_convert(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trig_num) +{ + unsigned long irqflags; + + if (trig_num != 0) + return -EINVAL; + + comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); + if (test_bit(AI_CMD_STARTED, &devpriv->state)) { + unsigned int delayus; + + /* Trigger conversion by toggling Z2-CT2 output. Finish + * with output high. */ + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, + I8254_MODE0); + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, + I8254_MODE1); + /* Delay. Should driver be responsible for this? An + * alternative would be to wait until conversion is complete, + * but we can't tell when it's complete because the ADC busy + * bit has a different meaning when FIFO enabled (and when + * FIFO not enabled, it only works for software triggers). */ + if (((devpriv->adccon & PCI230_ADC_IM_MASK) + == PCI230_ADC_IM_DIF) + && (devpriv->hwver == 0)) { + /* PCI230/260 in differential mode */ + delayus = 8; + } else { + /* single-ended or PCI230+/260+ */ + delayus = 4; + } + comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, + irqflags); + comedi_udelay(delayus); + } else { + comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, + irqflags); + } + + return 1; +} + +static int pci230_ai_inttrig_scan_begin(struct comedi_device * dev, + struct comedi_subdevice * s, unsigned int trig_num) +{ + unsigned long irqflags; + unsigned char zgat; + + if (trig_num != 0) + return -EINVAL; + + comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); + if (test_bit(AI_CMD_STARTED, &devpriv->state)) { + /* Trigger scan by waggling CT0 gate source. */ + zgat = GAT_CONFIG(0, GAT_GND); + outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); + zgat = GAT_CONFIG(0, GAT_VCC); + outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); + } + comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags); + + return 1; +} + +static void pci230_ai_start(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long irqflags; + unsigned short conv; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + + set_bit(AI_CMD_STARTED, &devpriv->state); + if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) { + /* An empty acquisition! */ + async->events |= COMEDI_CB_EOA; + pci230_ai_stop(dev, s); + comedi_event(dev, s); + } else { + /* Enable ADC FIFO trigger level interrupt. */ + comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + devpriv->int_en |= PCI230_INT_ADC; + devpriv->ier |= PCI230_INT_ADC; + outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); + comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + + /* Update conversion trigger source which is currently set + * to CT2 output, which is currently stuck high. */ + switch (cmd->convert_src) { + default: + conv = PCI230_ADC_TRIG_NONE; + break; + case TRIG_TIMER: + /* Using CT2 output. */ + conv = PCI230_ADC_TRIG_Z2CT2; + break; + case TRIG_EXT: + if ((cmd->convert_arg & CR_EDGE) != 0) { + if ((cmd->convert_arg & CR_INVERT) == 0) { + /* Trigger on +ve edge. */ + conv = PCI230_ADC_TRIG_EXTP; + } else { + /* Trigger on -ve edge. */ + conv = PCI230_ADC_TRIG_EXTN; + } + } else { + /* Backwards compatibility. */ + if (cmd->convert_arg != 0) { + /* Trigger on +ve edge. */ + conv = PCI230_ADC_TRIG_EXTP; + } else { + /* Trigger on -ve edge. */ + conv = PCI230_ADC_TRIG_EXTN; + } + } + break; + case TRIG_INT: + /* Use CT2 output for software trigger due to problems + * in differential mode on PCI230/260. */ + conv = PCI230_ADC_TRIG_Z2CT2; + break; + } + devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK) + | conv; + outw(devpriv->adccon, dev->iobase + PCI230_ADCCON); + if (cmd->convert_src == TRIG_INT) { + async->inttrig = pci230_ai_inttrig_convert; + } + /* Update FIFO interrupt trigger level, which is currently + * set to "full". */ + pci230_ai_update_fifo_trigger_level(dev, s); + if (cmd->convert_src == TRIG_TIMER) { + /* Update timer gates. */ + unsigned char zgat; + + if (cmd->scan_begin_src != TRIG_FOLLOW) { + /* Conversion timer CT2 needs to be gated by + * inverted output of monostable CT2. */ + zgat = GAT_CONFIG(2, GAT_NOUTNM2); + } else { + /* Conversion timer CT2 needs to be gated on + * continuously. */ + zgat = GAT_CONFIG(2, GAT_VCC); + } + outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); + if (cmd->scan_begin_src != TRIG_FOLLOW) { + /* Set monostable CT0 trigger source. */ + switch (cmd->scan_begin_src) { + default: + zgat = GAT_CONFIG(0, GAT_VCC); + break; + case TRIG_EXT: + /* + * For CT0 on PCI230, the external + * trigger (gate) signal comes from + * PPC0, which is channel 16 of the DIO + * subdevice. The application needs to + * configure this as an input in order + * to use it as an external scan + * trigger. + */ + zgat = GAT_CONFIG(0, GAT_EXT); + break; + case TRIG_TIMER: + /* + * Monostable CT0 triggered by rising + * edge on inverted output of CT1 + * (falling edge on CT1). + */ + zgat = GAT_CONFIG(0, GAT_NOUTNM2); + break; + case TRIG_INT: + /* + * Monostable CT0 is triggered by + * inttrig function waggling the CT0 + * gate source. + */ + zgat = GAT_CONFIG(0, GAT_VCC); + break; + } + outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + /* Scan period timer CT1 needs to be + * gated on to start counting. */ + zgat = GAT_CONFIG(1, GAT_VCC); + outb(zgat, devpriv->iobase1 + + PCI230_ZGAT_SCE); + break; + case TRIG_INT: + async->inttrig = + pci230_ai_inttrig_scan_begin; + break; + } + } + } else if (cmd->convert_src != TRIG_INT) { + /* No longer need Z2-CT2. */ + put_one_resource(dev, RES_Z2CT2, OWNER_AICMD); + } + } +} + +static int pci230_ai_inttrig_start(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trig_num) +{ + if (trig_num != 0) + return -EINVAL; + + s->async->inttrig = NULLFUNC; + pci230_ai_start(dev, s); + + return 1; +} + +static int pci230_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned int i, chan, range, diff; + unsigned int res_mask; + unsigned short adccon, adcen; + unsigned char zgat; + + /* Get the command. */ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + + /* + * Determine which shared resources are needed. + */ + res_mask = 0; + /* Need Z2-CT2 to supply a conversion trigger source at a high + * logic level, even if not doing timed conversions. */ + res_mask |= (1U << RES_Z2CT2); + if (cmd->scan_begin_src != TRIG_FOLLOW) { + /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */ + res_mask |= (1U << RES_Z2CT0); + if (cmd->scan_begin_src == TRIG_TIMER) { + /* Using Z2-CT1 for scan frequency */ + res_mask |= (1U << RES_Z2CT1); + } + } + /* Claim resources. */ + if (!get_resources(dev, res_mask, OWNER_AICMD)) { + return -EBUSY; + } + + /* Get number of scans required. */ + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ai_scan_count = cmd->stop_arg; + devpriv->ai_continuous = 0; + } else { + /* TRIG_NONE, user calls cancel. */ + devpriv->ai_scan_count = 0; + devpriv->ai_continuous = 1; + } + devpriv->ai_scan_pos = 0; /* Position within scan. */ + + /* Steps; + * - Set channel scan list. + * - Set channel gains. + * - Enable and reset FIFO, specify uni/bip, se/diff, and set + * start conversion source to point to something at a high logic + * level (we use the output of counter/timer 2 for this purpose. + * - PAUSE to allow things to settle down. + * - Reset the FIFO again because it needs resetting twice and there + * may have been a false conversion trigger on some versions of + * PCI230/260 due to the start conversion source being set to a + * high logic level. + * - Enable ADC FIFO level interrupt. + * - Set actual conversion trigger source and FIFO interrupt trigger + * level. + * - If convert_src is TRIG_TIMER, set up the timers. + */ + + adccon = PCI230_ADC_FIFO_EN; + adcen = 0; + + if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) { + /* Differential - all channels must be differential. */ + diff = 1; + adccon |= PCI230_ADC_IM_DIF; + } else { + /* Single ended - all channels must be single-ended. */ + diff = 0; + adccon |= PCI230_ADC_IM_SE; + } + + range = CR_RANGE(cmd->chanlist[0]); + devpriv->ai_bipolar = pci230_ai_bipolar[range]; + if (devpriv->ai_bipolar) { + adccon |= PCI230_ADC_IR_BIP; + } else { + adccon |= PCI230_ADC_IR_UNI; + } + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int gainshift; + + chan = CR_CHAN(cmd->chanlist[i]); + range = CR_RANGE(cmd->chanlist[i]); + if (diff) { + gainshift = 2 * chan; + if (devpriv->hwver == 0) { + /* Original PCI230/260 expects both inputs of + * the differential channel to be enabled. */ + adcen |= 3 << gainshift; + } else { + /* PCI230+/260+ expects only one input of the + * differential channel to be enabled. */ + adcen |= 1 << gainshift; + } + } else { + gainshift = (chan & ~1); + adcen |= 1 << chan; + } + devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) + | (pci230_ai_gain[range] << gainshift); + } + + /* Set channel scan list. */ + outw(adcen, dev->iobase + PCI230_ADCEN); + + /* Set channel gains. */ + outw(devpriv->adcg, dev->iobase + PCI230_ADCG); + + /* Set counter/timer 2 output high for use as the initial start + * conversion source. */ + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1); + + /* Temporarily use CT2 output as conversion trigger source and + * temporarily set FIFO interrupt trigger level to 'full'. */ + adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2; + + /* Enable and reset FIFO, specify FIFO trigger level full, specify + * uni/bip, se/diff, and temporarily set the start conversion source + * to CT2 output. Note that CT2 output is currently high, and this + * will produce a false conversion trigger on some versions of the + * PCI230/260, but that will be dealt with later. */ + devpriv->adccon = adccon; + outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON); + + /* Delay */ + /* Failure to include this will result in the first few channels'-worth + * of data being corrupt, normally manifesting itself by large negative + * voltages. It seems the board needs time to settle between the first + * FIFO reset (above) and the second FIFO reset (below). Setting the + * channel gains and scan list _before_ the first FIFO reset also + * helps, though only slightly. */ + comedi_udelay(25); + + /* Reset FIFO again. */ + outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON); + + if (cmd->convert_src == TRIG_TIMER) { + /* Set up CT2 as conversion timer, but gate it off for now. + * Note, counter/timer output 2 can be monitored on the + * connector: PCI230 pin 21, PCI260 pin 18. */ + zgat = GAT_CONFIG(2, GAT_GND); + outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); + /* Set counter/timer 2 to the specified conversion period. */ + pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (cmd->scan_begin_src != TRIG_FOLLOW) { + /* + * Set up monostable on CT0 output for scan timing. A + * rising edge on the trigger (gate) input of CT0 will + * trigger the monostable, causing its output to go low + * for the configured period. The period depends on + * the conversion period and the number of conversions + * in the scan. + * + * Set the trigger high before setting up the + * monostable to stop it triggering. The trigger + * source will be changed later. + */ + zgat = GAT_CONFIG(0, GAT_VCC); + outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); + pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1, + ((uint64_t) cmd->convert_arg + * cmd->scan_end_arg), TRIG_ROUND_UP); + if (cmd->scan_begin_src == TRIG_TIMER) { + /* + * Monostable on CT0 will be triggered by + * output of CT1 at configured scan frequency. + * + * Set up CT1 but gate it off for now. + */ + zgat = GAT_CONFIG(1, GAT_GND); + outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE); + pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3, + cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + } + } + } + + if (cmd->start_src == TRIG_INT) { + s->async->inttrig = pci230_ai_inttrig_start; + } else { + /* TRIG_NOW */ + pci230_ai_start(dev, s); + } + + return 0; +} + +static unsigned int divide_ns(uint64_t ns, unsigned int timebase, + unsigned int round_mode) +{ + uint64_t div; + unsigned int rem; + + div = ns; + rem = do_div(div, timebase); + round_mode &= TRIG_ROUND_MASK; + switch (round_mode) { + default: + case TRIG_ROUND_NEAREST: + div += (rem + (timebase / 2)) / timebase; + break; + case TRIG_ROUND_DOWN: + break; + case TRIG_ROUND_UP: + div += (rem + timebase - 1) / timebase; + break; + } + return div > UINT_MAX ? UINT_MAX : (unsigned int)div; +} + +/* Given desired period in ns, returns the required internal clock source + * and gets the initial count. */ +static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count, + unsigned int round_mode) +{ + unsigned int clk_src, cnt; + + for (clk_src = CLK_10MHZ;; clk_src++) { + cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode); + if ((cnt <= 65536) || (clk_src == CLK_1KHZ)) { + break; + } + } + *count = cnt; + return clk_src; +} + +static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round) +{ + unsigned int count; + unsigned int clk_src; + + clk_src = pci230_choose_clk_count(*ns, &count, round); + *ns = count * pci230_timebase[clk_src]; + return; +} + +static void pci230_ct_setup_ns_mode(struct comedi_device * dev, unsigned int ct, + unsigned int mode, uint64_t ns, unsigned int round) +{ + unsigned int clk_src; + unsigned int count; + + /* Set mode. */ + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode); + /* Determine clock source and count. */ + clk_src = pci230_choose_clk_count(ns, &count, round); + /* Program clock source. */ + outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE); + /* Set initial count. */ + if (count >= 65536) { + count = 0; + } + i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count); +} + +static void pci230_cancel_ct(struct comedi_device * dev, unsigned int ct) +{ + i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, + I8254_MODE1); + /* Counter ct, 8254 mode 1, initial count not written. */ +} + +/* Interrupt handler */ +static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG) +{ + unsigned char status_int, valid_status_int; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; + unsigned long irqflags; + + /* Read interrupt status/enable register. */ + status_int = inb(devpriv->iobase1 + PCI230_INT_STAT); + + if (status_int == PCI230_INT_DISABLE) { + return IRQ_NONE; + } + + comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + valid_status_int = devpriv->int_en & status_int; + /* Disable triggered interrupts. + * (Only those interrupts that need re-enabling, are, later in the + * handler). */ + devpriv->ier = devpriv->int_en & ~status_int; + outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); + devpriv->intr_running = 1; + devpriv->intr_cpuid = THISCPU; + comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + + /* + * Check the source of interrupt and handle it. + * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3 + * interrupts. However, at present (Comedi-0.7.60) does not allow + * concurrent execution of commands, instructions or a mixture of the + * two. + */ + + if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) { + s = dev->write_subdev; + pci230_handle_ao_nofifo(dev, s); + comedi_event(dev, s); + } + + if ((valid_status_int & PCI230P2_INT_DAC) != 0) { + s = dev->write_subdev; + pci230_handle_ao_fifo(dev, s); + comedi_event(dev, s); + } + + if ((valid_status_int & PCI230_INT_ADC) != 0) { + s = dev->read_subdev; + pci230_handle_ai(dev, s); + comedi_event(dev, s); + } + + /* Reenable interrupts. */ + comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + if (devpriv->ier != devpriv->int_en) { + devpriv->ier = devpriv->int_en; + outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); + } + devpriv->intr_running = 0; + comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + + return IRQ_HANDLED; +} + +static void pci230_handle_ao_nofifo(struct comedi_device * dev, struct comedi_subdevice * s) +{ + short data; + int i, ret; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + + if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) { + return; + } + + for (i = 0; i < cmd->chanlist_len; i++) { + /* Read sample from Comedi's circular buffer. */ + ret = comedi_buf_get(s->async, &data); + if (ret == 0) { + s->async->events |= COMEDI_CB_OVERFLOW; + pci230_ao_stop(dev, s); + comedi_error(dev, "AO buffer underrun"); + return; + } + /* Write value to DAC. */ + pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i])); + } + + async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; + if (!devpriv->ao_continuous) { + devpriv->ao_scan_count--; + if (devpriv->ao_scan_count == 0) { + /* End of acquisition. */ + async->events |= COMEDI_CB_EOA; + pci230_ao_stop(dev, s); + } + } +} + +/* Loads DAC FIFO (if using it) from buffer. */ +/* Returns 0 if AO finished due to completion or error, 1 if still going. */ +static int pci230_handle_ao_fifo(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int num_scans; + unsigned int room; + unsigned short dacstat; + unsigned int i, n; + unsigned int bytes_per_scan; + unsigned int events = 0; + int running; + + /* Get DAC FIFO status. */ + dacstat = inw(dev->iobase + PCI230_DACCON); + + /* Determine number of scans available in buffer. */ + bytes_per_scan = cmd->chanlist_len * sizeof(short); + num_scans = comedi_buf_read_n_available(async) / bytes_per_scan; + if (!devpriv->ao_continuous) { + /* Fixed number of scans. */ + if (num_scans > devpriv->ao_scan_count) { + num_scans = devpriv->ao_scan_count; + } + if (devpriv->ao_scan_count == 0) { + /* End of acquisition. */ + events |= COMEDI_CB_EOA; + } + } + if (events == 0) { + /* Check for FIFO underrun. */ + if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) { + comedi_error(dev, "AO FIFO underrun"); + events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; + } + /* Check for buffer underrun if FIFO less than half full + * (otherwise there will be loads of "DAC FIFO not half full" + * interrupts). */ + if ((num_scans == 0) + && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) { + comedi_error(dev, "AO buffer underrun"); + events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; + } + } + if (events == 0) { + /* Determine how much room is in the FIFO (in samples). */ + if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0) { + room = PCI230P2_DAC_FIFOROOM_FULL; + } else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0) { + room = PCI230P2_DAC_FIFOROOM_HALFTOFULL; + } else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0) { + room = PCI230P2_DAC_FIFOROOM_EMPTY; + } else { + room = PCI230P2_DAC_FIFOROOM_ONETOHALF; + } + /* Convert room to number of scans that can be added. */ + room /= cmd->chanlist_len; + /* Determine number of scans to process. */ + if (num_scans > room) { + num_scans = room; + } + /* Process scans. */ + for (n = 0; n < num_scans; n++) { + for (i = 0; i < cmd->chanlist_len; i++) { + short datum; + + comedi_buf_get(async, &datum); + pci230_ao_write_fifo(dev, datum, + CR_CHAN(cmd->chanlist[i])); + } + } + events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK; + if (!devpriv->ao_continuous) { + devpriv->ao_scan_count -= num_scans; + if (devpriv->ao_scan_count == 0) { + /* All data for the command has been written + * to FIFO. Set FIFO interrupt trigger level + * to 'empty'. */ + devpriv->daccon = (devpriv->daccon + & ~PCI230P2_DAC_INT_FIFO_MASK) + | PCI230P2_DAC_INT_FIFO_EMPTY; + outw(devpriv->daccon, + dev->iobase + PCI230_DACCON); + } + } + /* Check if FIFO underrun occurred while writing to FIFO. */ + dacstat = inw(dev->iobase + PCI230_DACCON); + if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) { + comedi_error(dev, "AO FIFO underrun"); + events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; + } + } + if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) + != 0) { + /* Stopping AO due to completion or error. */ + pci230_ao_stop(dev, s); + running = 0; + } else { + running = 1; + } + async->events |= events; + return running; +} + +static void pci230_handle_ai(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned int events = 0; + unsigned int status_fifo; + unsigned int i; + unsigned int todo; + unsigned int fifoamount; + struct comedi_async *async = s->async; + unsigned int scanlen = async->cmd.scan_end_arg; + + /* Determine number of samples to read. */ + if (devpriv->ai_continuous) { + todo = PCI230_ADC_FIFOLEVEL_HALFFULL; + } else if (devpriv->ai_scan_count == 0) { + todo = 0; + } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL) + || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) { + todo = PCI230_ADC_FIFOLEVEL_HALFFULL; + } else { + todo = (devpriv->ai_scan_count * scanlen) + - devpriv->ai_scan_pos; + if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL) { + todo = PCI230_ADC_FIFOLEVEL_HALFFULL; + } + } + + if (todo == 0) { + return; + } + + fifoamount = 0; + for (i = 0; i < todo; i++) { + if (fifoamount == 0) { + /* Read FIFO state. */ + status_fifo = inw(dev->iobase + PCI230_ADCCON); + + if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) { + /* Report error otherwise FIFO overruns will go + * unnoticed by the caller. */ + comedi_error(dev, "AI FIFO overrun"); + events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; + break; + } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) { + /* FIFO empty. */ + break; + } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) { + /* FIFO half full. */ + fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL; + } else { + /* FIFO not empty. */ + if (devpriv->hwver > 0) { + /* Read PCI230+/260+ ADC FIFO level. */ + fifoamount = inw(dev->iobase + + PCI230P_ADCFFLEV); + if (fifoamount == 0) { + /* Shouldn't happen. */ + break; + } + } else { + fifoamount = 1; + } + } + } + + /* Read sample and store in Comedi's circular buffer. */ + if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) { + events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW; + comedi_error(dev, "AI buffer overflow"); + break; + } + fifoamount--; + devpriv->ai_scan_pos++; + if (devpriv->ai_scan_pos == scanlen) { + /* End of scan. */ + devpriv->ai_scan_pos = 0; + devpriv->ai_scan_count--; + async->events |= COMEDI_CB_EOS; + } + } + + if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) { + /* End of acquisition. */ + events |= COMEDI_CB_EOA; + } else { + /* More samples required, tell Comedi to block. */ + events |= COMEDI_CB_BLOCK; + } + async->events |= events; + + if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | + COMEDI_CB_OVERFLOW)) != 0) { + /* disable hardware conversions */ + pci230_ai_stop(dev, s); + } else { + /* update FIFO interrupt trigger level */ + pci230_ai_update_fifo_trigger_level(dev, s); + } +} + +static void pci230_ao_stop(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long irqflags; + unsigned char intsrc; + int started; + struct comedi_cmd *cmd; + + comedi_spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags); + started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state); + comedi_spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags); + if (!started) { + return; + } + + cmd = &s->async->cmd; + if (cmd->scan_begin_src == TRIG_TIMER) { + /* Stop scan rate generator. */ + pci230_cancel_ct(dev, 1); + } + + /* Determine interrupt source. */ + if (devpriv->hwver < 2) { + /* Not using DAC FIFO. Using CT1 interrupt. */ + intsrc = PCI230_INT_ZCLK_CT1; + } else { + /* Using DAC FIFO interrupt. */ + intsrc = PCI230P2_INT_DAC; + } + /* Disable interrupt and wait for interrupt routine to finish running + * unless we are called from the interrupt routine. */ + comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + devpriv->int_en &= ~intsrc; + while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { + comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + } + if (devpriv->ier != devpriv->int_en) { + devpriv->ier = devpriv->int_en; + outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); + } + comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + + if (devpriv->hwver >= 2) { + /* Using DAC FIFO. Reset FIFO, clear underrun error, + * disable FIFO. */ + devpriv->daccon &= PCI230_DAC_OR_MASK; + outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET + | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR, + dev->iobase + PCI230_DACCON); + } + + /* Release resources. */ + put_all_resources(dev, OWNER_AOCMD); +} + +static int pci230_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + pci230_ao_stop(dev, s); + return 0; +} + +static void pci230_ai_stop(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long irqflags; + struct comedi_cmd *cmd; + int started; + + comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags); + started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state); + comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags); + if (!started) { + return; + } + + cmd = &s->async->cmd; + if (cmd->convert_src == TRIG_TIMER) { + /* Stop conversion rate generator. */ + pci230_cancel_ct(dev, 2); + } + if (cmd->scan_begin_src != TRIG_FOLLOW) { + /* Stop scan period monostable. */ + pci230_cancel_ct(dev, 0); + } + + comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + /* Disable ADC interrupt and wait for interrupt routine to finish + * running unless we are called from the interrupt routine. */ + devpriv->int_en &= ~PCI230_INT_ADC; + while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) { + comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags); + } + if (devpriv->ier != devpriv->int_en) { + devpriv->ier = devpriv->int_en; + outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE); + } + comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); + + /* Reset FIFO, disable FIFO and set start conversion source to none. + * Keep se/diff and bip/uni settings */ + devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK + | PCI230_ADC_IM_MASK)) | PCI230_ADC_TRIG_NONE; + outw(devpriv->adccon | PCI230_ADC_FIFO_RESET, + dev->iobase + PCI230_ADCCON); + + /* Release resources. */ + put_all_resources(dev, OWNER_AICMD); +} + +static int pci230_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + pci230_ai_stop(dev, s); + return 0; +} diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c new file mode 100644 index 000000000000..2efffb14610d --- /dev/null +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -0,0 +1,517 @@ +/* + comedi/drivers/c6xdigio.c + + Hardware driver for Mechatronic Systems Inc. C6x_DIGIO DSP daughter card. + (http://robot0.ge.uiuc.edu/~spong/mecha/) + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999 Dan Block + + 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: c6xdigio +Description: Mechatronic Systems Inc. C6x_DIGIO DSP daughter card +Author: Dan Block +Status: unknown +Devices: [Mechatronic Systems Inc.] C6x_DIGIO DSP daughter card (c6xdigio) +Updated: Sun Nov 20 20:18:34 EST 2005 + +This driver will not work with a 2.4 kernel. +http://robot0.ge.uiuc.edu/~spong/mecha/ + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../comedidev.h" + +static u8 ReadByteFromHwPort(unsigned long addr) +{ + u8 result = inb(addr); + return result; +} + +static void WriteByteToHwPort(unsigned long addr, u8 val) +{ + outb_p(val, addr); +} + +#define C6XDIGIO_SIZE 3 + +/* + * port offsets + */ +#define C6XDIGIO_PARALLEL_DATA 0 +#define C6XDIGIO_PARALLEL_STATUS 1 +#define C6XDIGIO_PARALLEL_CONTROL 2 +struct pwmbitstype { + unsigned sb0:2; + unsigned sb1:2; + unsigned sb2:2; + unsigned sb3:2; + unsigned sb4:2; +}; +union pwmcmdtype { + unsigned cmd; // assuming here that int is 32bit + struct pwmbitstype bits; +}; +struct encbitstype { + unsigned sb0:3; + unsigned sb1:3; + unsigned sb2:3; + unsigned sb3:3; + unsigned sb4:3; + unsigned sb5:3; + unsigned sb6:3; + unsigned sb7:3; +}; +union encvaluetype { + unsigned value; + struct encbitstype bits; +}; + +#define C6XDIGIO_TIME_OUT 20 + +static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int c6xdigio_detach(struct comedi_device * dev); +struct comedi_driver driver_c6xdigio = { + driver_name:"c6xdigio", + module:THIS_MODULE, + attach:c6xdigio_attach, + detach:c6xdigio_detach, +}; + +static void C6X_pwmInit(unsigned long baseAddr) +{ + int timeout = 0; + +//printk("Inside C6X_pwmInit\n"); + + WriteByteToHwPort(baseAddr, 0x70); + while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0) + && (timeout < C6XDIGIO_TIME_OUT)) { + timeout++; + } + + WriteByteToHwPort(baseAddr, 0x74); + timeout = 0; + while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80) + && (timeout < C6XDIGIO_TIME_OUT)) { + timeout++; + } + + WriteByteToHwPort(baseAddr, 0x70); + timeout = 0; + while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x0) + && (timeout < C6XDIGIO_TIME_OUT)) { + timeout++; + } + + WriteByteToHwPort(baseAddr, 0x0); + timeout = 0; + while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80) + && (timeout < C6XDIGIO_TIME_OUT)) { + timeout++; + } + +} + +static void C6X_pwmOutput(unsigned long baseAddr, unsigned channel, int value) +{ + unsigned ppcmd; + union pwmcmdtype pwm; + int timeout = 0; + unsigned tmp; + + //printk("Inside C6X_pwmOutput\n"); + + pwm.cmd = value; + if (pwm.cmd > 498) + pwm.cmd = 498; + if (pwm.cmd < 2) + pwm.cmd = 2; + + if (channel == 0) { + ppcmd = 0x28; + } else { // if channel == 1 + ppcmd = 0x30; + } /* endif */ + + WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb0); + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + + WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb1 + 0x4); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + + WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb2); + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + + WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb3 + 0x4); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + + WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb4); + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + + WriteByteToHwPort(baseAddr, 0x0); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + +} + +static int C6X_encInput(unsigned long baseAddr, unsigned channel) +{ + unsigned ppcmd; + union encvaluetype enc; + int timeout = 0; + int tmp; + + //printk("Inside C6X_encInput\n"); + + enc.value = 0; + if (channel == 0) { + ppcmd = 0x48; + } else { + ppcmd = 0x50; + } + WriteByteToHwPort(baseAddr, ppcmd); + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + + enc.bits.sb0 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); + WriteByteToHwPort(baseAddr, ppcmd + 0x4); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + enc.bits.sb1 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); + WriteByteToHwPort(baseAddr, ppcmd); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + enc.bits.sb2 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); + WriteByteToHwPort(baseAddr, ppcmd + 0x4); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + enc.bits.sb3 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); + WriteByteToHwPort(baseAddr, ppcmd); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + enc.bits.sb4 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); + WriteByteToHwPort(baseAddr, ppcmd + 0x4); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + enc.bits.sb5 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); + WriteByteToHwPort(baseAddr, ppcmd); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x0) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + enc.bits.sb6 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); + WriteByteToHwPort(baseAddr, ppcmd + 0x4); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + enc.bits.sb7 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7); + WriteByteToHwPort(baseAddr, ppcmd); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x0) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + + WriteByteToHwPort(baseAddr, 0x0); + timeout = 0; + tmp = ReadByteFromHwPort(baseAddr + 1); + while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) { + tmp = ReadByteFromHwPort(baseAddr + 1); + timeout++; + } + + return (enc.value ^ 0x800000); +} + +static void C6X_encResetAll(unsigned long baseAddr) +{ + unsigned timeout = 0; + +//printk("Inside C6X_encResetAll\n"); + + WriteByteToHwPort(baseAddr, 0x68); + while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0) + && (timeout < C6XDIGIO_TIME_OUT)) { + timeout++; + } + WriteByteToHwPort(baseAddr, 0x6C); + timeout = 0; + while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80) + && (timeout < C6XDIGIO_TIME_OUT)) { + timeout++; + } + WriteByteToHwPort(baseAddr, 0x68); + timeout = 0; + while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x0) + && (timeout < C6XDIGIO_TIME_OUT)) { + timeout++; + } + WriteByteToHwPort(baseAddr, 0x0); + timeout = 0; + while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80) + && (timeout < C6XDIGIO_TIME_OUT)) { + timeout++; + } +} + +static int c6xdigio_pwmo_insn_read(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + printk("c6xdigio_pwmo_insn_read %x\n", insn->n); + return insn->n; +} + +static int c6xdigio_pwmo_insn_write(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + // printk("c6xdigio_pwmo_insn_write %x\n", insn->n); + for (i = 0; i < insn->n; i++) { + C6X_pwmOutput(dev->iobase, chan, data[i]); + /* devpriv->ao_readback[chan] = data[i]; */ + } + return i; +} + +//static int c6xdigio_ei_init_insn_read(struct comedi_device *dev, +// struct comedi_subdevice *s, +// struct comedi_insn *insn, +// unsigned int *data) +//{ +// printk("c6xdigio_ei_init_insn_read %x\n", insn->n); +// return insn->n; +//} + +//static int c6xdigio_ei_init_insn_write(struct comedi_device *dev, +// struct comedi_subdevice *s, +// struct comedi_insn *insn, +// unsigned int *data) +//{ +// int i; +// int chan = CR_CHAN(insn->chanspec); +// +// C6X_encResetAll( dev->iobase ); +// +// return insn->n; +//} + +static int c6xdigio_ei_insn_read(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + // printk("c6xdigio_ei__insn_read %x\n", insn->n); + int n; + int chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { + data[n] = (C6X_encInput(dev->iobase, chan) & 0xffffff); + } + + return n; +} + +static void board_init(struct comedi_device * dev) +{ + + //printk("Inside board_init\n"); + + C6X_pwmInit(dev->iobase); + C6X_encResetAll(dev->iobase); + +} + +//static void board_halt(struct comedi_device *dev) { +// C6X_pwmInit(dev->iobase); +//} + +/* + options[0] - I/O port + options[1] - irq + options[2] - number of encoder chips installed + */ + +static const struct pnp_device_id c6xdigio_pnp_tbl[] = { + /* Standard LPT Printer Port */ + {.id = "PNP0400",.driver_data = 0}, + /* ECP Printer Port */ + {.id = "PNP0401",.driver_data = 0}, + {} +}; + +static struct pnp_driver c6xdigio_pnp_driver = { + .name = "c6xdigio", + .id_table = c6xdigio_pnp_tbl, +}; + +static int c6xdigio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int result = 0; + unsigned long iobase; + unsigned int irq; + struct comedi_subdevice *s; + + iobase = it->options[0]; + printk("comedi%d: c6xdigio: 0x%04lx\n", dev->minor, iobase); + if (!request_region(iobase, C6XDIGIO_SIZE, "c6xdigio")) { + printk("comedi%d: I/O port conflict\n", dev->minor); + return -EIO; + } + dev->iobase = iobase; + dev->board_name = "c6xdigio"; + + result = alloc_subdevices(dev, 2); // 3 with encoder_init write + if (result < 0) + return result; + + // Make sure that PnP ports gets activated + pnp_register_driver(&c6xdigio_pnp_driver); + + irq = it->options[1]; + if (irq > 0) { + printk("comedi%d: irq = %u ignored\n", dev->minor, irq); + } else if (irq == 0) { + printk("comedi%d: no irq\n", dev->minor); + } + + s = dev->subdevices + 0; + /* pwm output subdevice */ + s->type = COMEDI_SUBD_AO; // Not sure what to put here + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 2; + /* s->trig[0] = c6xdigio_pwmo; */ + s->insn_read = c6xdigio_pwmo_insn_read; + s->insn_write = c6xdigio_pwmo_insn_write; + s->maxdata = 500; + s->range_table = &range_bipolar10; // A suitable lie + + s = dev->subdevices + 1; + /* encoder (counter) subdevice */ + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_LSAMPL; + s->n_chan = 2; + /* s->trig[0] = c6xdigio_ei; */ + s->insn_read = c6xdigio_ei_insn_read; + s->maxdata = 0xffffff; + s->range_table = &range_unknown; + + // s = dev->subdevices + 2; + // /* pwm output subdevice */ + // s->type = COMEDI_SUBD_COUNTER; // Not sure what to put here + // s->subdev_flags = SDF_WRITEABLE; + // s->n_chan = 1; + // /* s->trig[0] = c6xdigio_ei_init; */ + // s->insn_read = c6xdigio_ei_init_insn_read; + // s->insn_write = c6xdigio_ei_init_insn_write; + // s->maxdata = 0xFFFF; // Really just a don't care + // s->range_table = &range_unknown; // Not sure what to put here + + // I will call this init anyway but more than likely the DSP board will not be connect + // when device driver is loaded. + board_init(dev); + + return 0; +} + +static int c6xdigio_detach(struct comedi_device * dev) +{ +// board_halt(dev); // may not need this + + printk("comedi%d: c6xdigio: remove\n", dev->minor); + + if (dev->iobase) { + release_region(dev->iobase, C6XDIGIO_SIZE); + } + if (dev->irq) { + free_irq(dev->irq, dev); + } // Not using IRQ so I am not sure if I need this + pnp_unregister_driver(&c6xdigio_pnp_driver); + + return 0; +} + +COMEDI_INITCLEANUP(driver_c6xdigio); diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c new file mode 100644 index 000000000000..0bfe4c954eb5 --- /dev/null +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -0,0 +1,976 @@ +/* + comedi/drivers/das16cs.c + Driver for Computer Boards PC-CARD DAS16/16. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000, 2001, 2002 David A. Schleef + + 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: cb_das16_cs +Description: Computer Boards PC-CARD DAS16/16 +Devices: [ComputerBoards] PC-CARD DAS16/16 (cb_das16_cs), PC-CARD DAS16/16-AO +Author: ds +Updated: Mon, 04 Nov 2002 20:04:21 -0800 +Status: experimental + + +*/ + +#include "../comedidev.h" +#include +#include + +#include +#include +#include +#include + +#include "8253.h" + +#define DAS16CS_SIZE 18 + +#define DAS16CS_ADC_DATA 0 +#define DAS16CS_DIO_MUX 2 +#define DAS16CS_MISC1 4 +#define DAS16CS_MISC2 6 +#define DAS16CS_CTR0 8 +#define DAS16CS_CTR1 10 +#define DAS16CS_CTR2 12 +#define DAS16CS_CTR_CONTROL 14 +#define DAS16CS_DIO 16 + +struct das16cs_board { + const char *name; + int device_id; + int n_ao_chans; +}; +static const struct das16cs_board das16cs_boards[] = { + { + device_id:0x0000,/* unknown */ + name: "PC-CARD DAS16/16", + n_ao_chans:0, + }, + { + device_id:0x0039, + name: "PC-CARD DAS16/16-AO", + n_ao_chans:2, + }, + { + device_id:0x4009, + name: "PCM-DAS16s/16", + n_ao_chans:0, + }, +}; + +#define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0])) +#define thisboard ((const struct das16cs_board *)dev->board_ptr) + +struct das16cs_private { + struct pcmcia_device *link; + + unsigned int ao_readback[2]; + unsigned short status1; + unsigned short status2; +}; +#define devpriv ((struct das16cs_private *)dev->private) + +static int das16cs_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int das16cs_detach(struct comedi_device * dev); +static struct comedi_driver driver_das16cs = { + driver_name:"cb_das16_cs", + module:THIS_MODULE, + attach:das16cs_attach, + detach:das16cs_detach, +}; + +static struct pcmcia_device *cur_dev = NULL; + +static const struct comedi_lrange das16cs_ai_range = { 4, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2.5, 2.5), + RANGE(-1.25, 1.25), + } +}; + +static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG); +static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16cs_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link) +{ + tuple_t tuple; + u_short buf[128]; + int prodid = 0; + + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.DesiredTuple = CISTPL_MANFID; + tuple.Attributes = TUPLE_RETURN_COMMON; + if ((pcmcia_get_first_tuple(link, &tuple) == 0) && + (pcmcia_get_tuple_data(link, &tuple) == 0)) { + prodid = le16_to_cpu(buf[1]); + } + + return prodid; +} + +static const struct das16cs_board *das16cs_probe(struct comedi_device * dev, + struct pcmcia_device *link) +{ + int id; + int i; + + id = get_prodid(dev, link); + + for (i = 0; i < n_boards; i++) { + if (das16cs_boards[i].device_id == id) { + return das16cs_boards + i; + } + } + + printk("unknown board!\n"); + + return NULL; +} + +static int das16cs_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct pcmcia_device *link; + struct comedi_subdevice *s; + int ret; + int i; + + printk("comedi%d: cb_das16_cs: ", dev->minor); + + link = cur_dev; /* XXX hack */ + if (!link) + return -EIO; + + dev->iobase = link->io.BasePort1; + printk("I/O base=0x%04lx ", dev->iobase); + + printk("fingerprint:\n"); + for (i = 0; i < 48; i += 2) { + printk("%04x ", inw(dev->iobase + i)); + } + printk("\n"); + + ret = comedi_request_irq(link->irq.AssignedIRQ, das16cs_interrupt, + IRQF_SHARED, "cb_das16_cs", dev); + if (ret < 0) { + return ret; + } + dev->irq = link->irq.AssignedIRQ; + printk("irq=%u ", dev->irq); + + dev->board_ptr = das16cs_probe(dev, link); + if (!dev->board_ptr) + return -EIO; + + dev->board_name = thisboard->name; + + if (alloc_private(dev, sizeof(struct das16cs_private)) < 0) + return -ENOMEM; + + if (alloc_subdevices(dev, 4) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + dev->read_subdev = s; + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + s->n_chan = 16; + s->maxdata = 0xffff; + s->range_table = &das16cs_ai_range; + s->len_chanlist = 16; + s->insn_read = das16cs_ai_rinsn; + s->do_cmd = das16cs_ai_cmd; + s->do_cmdtest = das16cs_ai_cmdtest; + + s = dev->subdevices + 1; + /* analog output subdevice */ + if (thisboard->n_ao_chans) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->n_ao_chans; + s->maxdata = 0xffff; + s->range_table = &range_bipolar10; + s->insn_write = &das16cs_ao_winsn; + s->insn_read = &das16cs_ao_rinsn; + } + + s = dev->subdevices + 2; + /* digital i/o subdevice */ + if (1) { + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das16cs_dio_insn_bits; + s->insn_config = das16cs_dio_insn_config; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 3; + /* timer subdevice */ + if (0) { + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 1; + s->maxdata = 0xff; + s->range_table = &range_unknown; + s->insn_read = das16cs_timer_insn_read; + s->insn_config = das16cs_timer_insn_config; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + printk("attached\n"); + + return 1; +} + +static int das16cs_detach(struct comedi_device * dev) +{ + printk("comedi%d: das16cs: remove\n", dev->minor); + + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + + return 0; +} + +static irqreturn_t das16cs_interrupt(int irq, void *d PT_REGS_ARG) +{ + //struct comedi_device *dev = d; + return IRQ_HANDLED; +} + +/* + * "instructions" read/write data in "one-shot" or "software-triggered" + * mode. + */ +static int das16cs_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int to; + int aref; + int range; + int chan; + static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 }; + + chan = CR_CHAN(insn->chanspec); + aref = CR_AREF(insn->chanspec); + range = CR_RANGE(insn->chanspec); + + outw(chan, dev->iobase + 2); + + devpriv->status1 &= ~0xf320; + devpriv->status1 |= (aref == AREF_DIFF) ? 0 : 0x0020; + outw(devpriv->status1, dev->iobase + 4); + + devpriv->status2 &= ~0xff00; + devpriv->status2 |= range_bits[range]; + outw(devpriv->status2, dev->iobase + 6); + + for (i = 0; i < insn->n; i++) { + outw(0, dev->iobase); + +#define TIMEOUT 1000 + for (to = 0; to < TIMEOUT; to++) { + if (inw(dev->iobase + 4) & 0x0080) + break; + } + if (to == TIMEOUT) { + printk("cb_das16_cs: ai timeout\n"); + return -ETIME; + } + data[i] = (unsigned short)inw(dev->iobase + 0); + } + + return i; +} + +static int das16cs_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + return -EINVAL; +} + +static int das16cs_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ + + 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_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } +#define MAX_SPEED 10000 /* in nanoseconds */ +#define MIN_SPEED 1000000000 /* in nanoseconds */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < MAX_SPEED) { + cmd->scan_begin_arg = MAX_SPEED; + err++; + } + if (cmd->scan_begin_arg > MIN_SPEED) { + cmd->scan_begin_arg = MIN_SPEED; + err++; + } + } else { + /* external trigger */ + /* should be level/edge, hi/lo specification here */ + /* should specify multiple external triggers */ + if (cmd->scan_begin_arg > 9) { + cmd->scan_begin_arg = 9; + err++; + } + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < MAX_SPEED) { + cmd->convert_arg = MAX_SPEED; + err++; + } + if (cmd->convert_arg > MIN_SPEED) { + cmd->convert_arg = MIN_SPEED; + err++; + } + } else { + /* external trigger */ + /* see above */ + if (cmd->convert_arg > 9) { + cmd->convert_arg = 9; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_arg > 0x00ffffff) { + cmd->stop_arg = 0x00ffffff; + err++; + } + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + unsigned int div1, div2; + + tmp = cmd->scan_begin_arg; + i8253_cascade_ns_to_timer(100, &div1, &div2, + &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + if (cmd->convert_src == TRIG_TIMER) { + unsigned int div1, div2; + + tmp = cmd->convert_arg; + i8253_cascade_ns_to_timer(100, &div1, &div2, + &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + if (cmd->scan_begin_src == TRIG_TIMER && + cmd->scan_begin_arg < + cmd->convert_arg * cmd->scan_end_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->scan_end_arg; + err++; + } + } + + if (err) + return 4; + + return 0; +} + +static int das16cs_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + unsigned short status1; + unsigned short d; + int bit; + + for (i = 0; i < insn->n; i++) { + devpriv->ao_readback[chan] = data[i]; + d = data[i]; + + outw(devpriv->status1, dev->iobase + 4); + comedi_udelay(1); + + status1 = devpriv->status1 & ~0xf; + if (chan) + status1 |= 0x0001; + else + status1 |= 0x0008; + +/* printk("0x%04x\n",status1);*/ + outw(status1, dev->iobase + 4); + comedi_udelay(1); + + for (bit = 15; bit >= 0; bit--) { + int b = (d >> bit) & 0x1; + b <<= 1; +/* printk("0x%04x\n",status1 | b | 0x0000);*/ + outw(status1 | b | 0x0000, dev->iobase + 4); + comedi_udelay(1); +/* printk("0x%04x\n",status1 | b | 0x0004);*/ + outw(status1 | b | 0x0004, dev->iobase + 4); + comedi_udelay(1); + } +/* make high both DAC0CS and DAC1CS to load + new data and update analog output*/ + outw(status1 | 0x9, dev->iobase + 4); + } + + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. */ +static int das16cs_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +/* DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write */ +static int das16cs_dio_insn_bits(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]; + + outw(s->state, dev->iobase + 16); + } + + /* on return, data[1] contains the value of the digital + * input and output lines. */ + data[1] = inw(dev->iobase + 16); + + return 2; +} + +static int das16cs_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + int bits; + + if (chan < 4) + bits = 0x0f; + else + bits = 0xf0; + + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= bits; + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= bits; + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s-> + io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + break; + } + + devpriv->status2 &= ~0x00c0; + devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0; + devpriv->status2 |= (s->io_bits & 0x0f) ? 0x0040 : 0; + + outw(devpriv->status2, dev->iobase + 6); + + return insn->n; +} + +static int das16cs_timer_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + return -EINVAL; +} + +static int das16cs_timer_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + return -EINVAL; +} + +/* PCMCIA stuff */ + +/*====================================================================== + + The following pcmcia code for the pcm-das08 is adapted from the + dummy_cs.c driver of the Linux PCMCIA Card Services package. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + +======================================================================*/ + +/* + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + you do not define PCMCIA_DEBUG at all, all the debug code will be + left out. If you compile with PCMCIA_DEBUG=0, the debug code will + be present but disabled -- but it can then be enabled for specific + modules at load time with a 'pc_debug=#' option to insmod. +*/ +#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +module_param(pc_debug, int, 0644); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = + "cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +static void das16cs_pcmcia_config(struct pcmcia_device *link); +static void das16cs_pcmcia_release(struct pcmcia_device *link); +static int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev); +static int das16cs_pcmcia_resume(struct pcmcia_device *p_dev); + +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static int das16cs_pcmcia_attach(struct pcmcia_device *); +static void das16cs_pcmcia_detach(struct pcmcia_device *); + +/* + You'll also need to prototype all the functions that will actually + be used to talk to your device. See 'memory_cs' for a good example + of a fully self-sufficient driver; the other drivers rely more or + less on other parts of the kernel. +*/ + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static dev_info_t dev_info = "cb_das16_cs"; + +struct local_info_t { + struct pcmcia_device *link; + dev_node_t node; + int stop; + struct bus_operations *bus; +}; + +/*====================================================================== + + das16cs_pcmcia_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + +======================================================================*/ + +static int das16cs_pcmcia_attach(struct pcmcia_device *link) +{ + struct local_info_t *local; + + DEBUG(0, "das16cs_pcmcia_attach()\n"); + + /* Allocate space for private device-specific data */ + local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); + if (!local) + return -ENOMEM; + local->link = link; + link->priv = local; + + /* Initialize the pcmcia_device structure */ + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->irq.Handler = NULL; + + link->conf.Attributes = 0; + link->conf.IntType = INT_MEMORY_AND_IO; + + cur_dev = link; + + das16cs_pcmcia_config(link); + + return 0; +} /* das16cs_pcmcia_attach */ + +static void das16cs_pcmcia_detach(struct pcmcia_device *link) +{ + DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link); + + if (link->dev_node) { + ((struct local_info_t *) link->priv)->stop = 1; + das16cs_pcmcia_release(link); + } + /* This points to the parent struct local_info_t struct */ + if (link->priv) + kfree(link->priv); +} /* das16cs_pcmcia_detach */ + +static void das16cs_pcmcia_config(struct pcmcia_device *link) +{ + struct local_info_t *dev = link->priv; + tuple_t tuple; + cisparse_t parse; + int last_fn, last_ret; + u_char buf[64]; + cistpl_cftable_entry_t dflt = { 0 }; + + DEBUG(0, "das16cs_pcmcia_config(0x%p)\n", link); + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + last_fn = GetFirstTuple; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) + goto cs_failed; + last_fn = GetTupleData; + if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) + goto cs_failed; + last_fn = ParseTuple; + if ((last_ret = pcmcia_parse_tuple(link, &tuple, &parse)) != 0) + goto cs_failed; + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* + In this loop, we scan the CIS for configuration table entries, + each of which describes a valid card configuration, including + voltage, IO window, memory window, and interrupt settings. + + We make no assumptions about the card to be configured: we use + just the information available in the CIS. In an ideal world, + this would work for any PCMCIA card, but it requires a complete + and accurate CIS. In practice, a driver usually "knows" most of + these things without consulting the CIS, and most client drivers + will only use the CIS to fill in implementation-defined details. + */ + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + last_fn = GetFirstTuple; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) + goto cs_failed; + while (1) { + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + if (pcmcia_get_tuple_data(link, &tuple)) + goto next_entry; + if (pcmcia_parse_tuple(link, &tuple, &parse)) + goto next_entry; + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + if (cfg->index == 0) + goto next_entry; + link->conf.ConfigIndex = cfg->index; + + /* Does this card need audio output? */ +/* if (cfg->flags & CISTPL_CFTABLE_AUDIO) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } +*/ + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + /* This reserves IO space but doesn't actually enable it */ + if (pcmcia_request_io(link, &link->io)) + goto next_entry; + } + + /* If we got this far, we're cool! */ + break; + + next_entry: + last_fn = GetNextTuple; + if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0) + goto cs_failed; + } + + /* + Allocate an interrupt line. Note that this does not assign a + handler to the interrupt, unless the 'Handler' member of the + irq structure is initialized. + */ + if (link->conf.Attributes & CONF_ENABLE_IRQ) { + last_fn = RequestIRQ; + if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0) + goto cs_failed; + } + /* + This actually configures the PCMCIA socket -- setting up + the I/O windows and the interrupt mapping, and putting the + card and host interface into "Memory and IO" mode. + */ + last_fn = RequestConfiguration; + if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0) + goto cs_failed; + + /* + At this point, the dev_node_t structure(s) need to be + initialized and arranged in a linked list at link->dev. + */ + sprintf(dev->node.dev_name, "cb_das16_cs"); + dev->node.major = dev->node.minor = 0; + link->dev_node = &dev->node; + + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %u", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1 + link->io.NumPorts1 - 1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2 + link->io.NumPorts2 - 1); + printk("\n"); + + return; + + cs_failed: + cs_error(link, last_fn, last_ret); + das16cs_pcmcia_release(link); +} /* das16cs_pcmcia_config */ + +static void das16cs_pcmcia_release(struct pcmcia_device *link) +{ + DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link); + pcmcia_disable_device(link); +} /* das16cs_pcmcia_release */ + +static int das16cs_pcmcia_suspend(struct pcmcia_device *link) +{ + struct local_info_t *local = link->priv; + + /* Mark the device as stopped, to block IO until later */ + local->stop = 1; + + return 0; +} /* das16cs_pcmcia_suspend */ + +static int das16cs_pcmcia_resume(struct pcmcia_device *link) +{ + struct local_info_t *local = link->priv; + + local->stop = 0; + return 0; +} /* das16cs_pcmcia_resume */ + +/*====================================================================*/ + +static struct pcmcia_device_id das16cs_id_table[] = { + PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0039), + PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4009), + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table); + +struct pcmcia_driver das16cs_driver = { + .probe = das16cs_pcmcia_attach, + .remove = das16cs_pcmcia_detach, + .suspend = das16cs_pcmcia_suspend, + .resume = das16cs_pcmcia_resume, + .id_table = das16cs_id_table, + .owner = THIS_MODULE, + .drv = { + .name = dev_info, + }, +}; + +static int __init init_das16cs_pcmcia_cs(void) +{ + DEBUG(0, "%s\n", version); + pcmcia_register_driver(&das16cs_driver); + return 0; +} + +static void __exit exit_das16cs_pcmcia_cs(void) +{ + DEBUG(0, "das16cs_pcmcia_cs: unloading\n"); + pcmcia_unregister_driver(&das16cs_driver); +} + +int __init init_module(void) +{ + int ret; + + ret = init_das16cs_pcmcia_cs(); + if (ret < 0) + return ret; + + return comedi_driver_register(&driver_das16cs); +} + +void __exit cleanup_module(void) +{ + exit_das16cs_pcmcia_cs(); + comedi_driver_unregister(&driver_das16cs); +} + +#else +COMEDI_INITCLEANUP(driver_das16cs); +#endif //CONFIG_PCMCIA diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c new file mode 100644 index 000000000000..fcc551651367 --- /dev/null +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -0,0 +1,1831 @@ +/* + comedi/drivers/cb_pcidas.c + + Developed by Ivan Martinez and Frank Mori Hess, with valuable help from + David Schleef and the rest of the Comedi developers comunity. + + Copyright (C) 2001-2003 Ivan Martinez + Copyright (C) 2001,2002 Frank Mori Hess + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-8 David A. Schleef + + 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: cb_pcidas +Description: MeasurementComputing PCI-DAS series with the AMCC S5933 PCI controller +Author: Ivan Martinez , + Frank Mori Hess +Updated: 2003-3-11 +Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas), + PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr, + PCI-DAS1000, PCI-DAS1001, PCI_DAS1002 + +Status: + There are many reports of the driver being used with most of the + supported cards. Despite no detailed log is maintained, it can + be said that the driver is quite tested and stable. + + The boards may be autocalibrated using the comedi_calibrate + utility. + +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. + +For commands, the scanned channels must be consecutive +(i.e. 4-5-6-7, 2-3-4,...), and must all have the same +range and aref. +*/ +/* + +TODO: + +analog triggering on 1602 series +*/ + +#include "../comedidev.h" +#include + +#include "8253.h" +#include "8255.h" +#include "amcc_s5933.h" +#include "comedi_pci.h" +#include "comedi_fc.h" + +#undef CB_PCIDAS_DEBUG // disable debugging code +//#define CB_PCIDAS_DEBUG // enable debugging code + +// PCI vendor number of ComputerBoards/MeasurementComputing +#define PCI_VENDOR_ID_CB 0x1307 +#define TIMER_BASE 100 // 10MHz master clock +#define AI_BUFFER_SIZE 1024 // maximum fifo size of any supported board +#define AO_BUFFER_SIZE 1024 // maximum fifo size of any supported board +#define NUM_CHANNELS_8800 8 +#define NUM_CHANNELS_7376 1 +#define NUM_CHANNELS_8402 2 +#define NUM_CHANNELS_DAC08 1 + +/* PCI-DAS base addresses */ + +// indices of base address regions +#define S5933_BADRINDEX 0 +#define CONT_STAT_BADRINDEX 1 +#define ADC_FIFO_BADRINDEX 2 +#define PACER_BADRINDEX 3 +#define AO_BADRINDEX 4 +// sizes of io regions +#define CONT_STAT_SIZE 10 +#define ADC_FIFO_SIZE 4 +#define PACER_SIZE 12 +#define AO_SIZE 4 + +/* Control/Status registers */ +#define INT_ADCFIFO 0 // INTERRUPT / ADC FIFO register +#define INT_EOS 0x1 // interrupt end of scan +#define INT_FHF 0x2 // interrupt fifo half full +#define INT_FNE 0x3 // interrupt fifo not empty +#define INT_MASK 0x3 // mask of interrupt select bits +#define INTE 0x4 // interrupt enable +#define DAHFIE 0x8 // dac half full interrupt enable +#define EOAIE 0x10 // end of aquisition interrupt enable +#define DAHFI 0x20 // dac half full read status / write interrupt clear +#define EOAI 0x40 // read end of acq. interrupt status / write clear +#define INT 0x80 // read interrupt status / write clear +#define EOBI 0x200 // read end of burst interrupt status +#define ADHFI 0x400 // read half-full interrupt status +#define ADNEI 0x800 // read fifo not empty interrupt latch status +#define ADNE 0x1000 // read, fifo not empty (realtime, not latched) status +#define DAEMIE 0x1000 // write, dac empty interrupt enable +#define LADFUL 0x2000 // read fifo overflow / write clear +#define DAEMI 0x4000 // dac fifo empty interrupt status / write clear + +#define ADCMUX_CONT 2 // ADC CHANNEL MUX AND CONTROL register +#define BEGIN_SCAN(x) ((x) & 0xf) +#define END_SCAN(x) (((x) & 0xf) << 4) +#define GAIN_BITS(x) (((x) & 0x3) << 8) +#define UNIP 0x800 // Analog front-end unipolar for range +#define SE 0x400 // Inputs in single-ended mode +#define PACER_MASK 0x3000 // pacer source bits +#define PACER_INT 0x1000 // internal pacer +#define PACER_EXT_FALL 0x2000 // external falling edge +#define PACER_EXT_RISE 0x3000 // external rising edge +#define EOC 0x4000 // adc not busy + +#define TRIG_CONTSTAT 4 // TRIGGER CONTROL/STATUS register +#define SW_TRIGGER 0x1 // software start trigger +#define EXT_TRIGGER 0x2 // external start trigger +#define ANALOG_TRIGGER 0x3 // external analog trigger +#define TRIGGER_MASK 0x3 // mask of bits that determine start trigger +#define TGEN 0x10 // enable external start trigger +#define BURSTE 0x20 // burst mode enable +#define XTRCL 0x80 // clear external trigger + +#define CALIBRATION_REG 6 // CALIBRATION register +#define SELECT_8800_BIT 0x100 // select 8800 caldac +#define SELECT_TRIMPOT_BIT 0x200 // select ad7376 trim pot +#define SELECT_DAC08_BIT 0x400 // select dac08 caldac +#define CAL_SRC_BITS(x) (((x) & 0x7) << 11) +#define CAL_EN_BIT 0x4000 // read calibration source instead of analog input channel 0 +#define SERIAL_DATA_IN_BIT 0x8000 // serial data stream going to 8800 and 7376 + +#define DAC_CSR 0x8 // dac control and status register +enum dac_csr_bits { + DACEN = 0x2, // dac enable + DAC_MODE_UPDATE_BOTH = 0x80, // update both dacs when dac0 is written +}; +static inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range) +{ + return (range & 0x3) << (8 + 2 * (channel & 0x1)); +} +static inline unsigned int DAC_RANGE_MASK(unsigned int channel) +{ + return 0x3 << (8 + 2 * (channel & 0x1)); +}; + +// bits for 1602 series only +enum dac_csr_bits_1602 { + DAC_EMPTY = 0x1, // dac fifo empty, read, write clear + DAC_START = 0x4, // start/arm dac fifo operations + DAC_PACER_MASK = 0x18, // bits that set dac pacer source + DAC_PACER_INT = 0x8, // dac internal pacing + DAC_PACER_EXT_FALL = 0x10, // dac external pacing, falling edge + DAC_PACER_EXT_RISE = 0x18, // dac external pacing, rising edge +}; +static inline unsigned int DAC_CHAN_EN(unsigned int channel) +{ + return 1 << (5 + (channel & 0x1)); // enable channel 0 or 1 +}; + +/* analog input fifo */ +#define ADCDATA 0 // ADC DATA register +#define ADCFIFOCLR 2 // ADC FIFO CLEAR + +// pacer, counter, dio registers +#define ADC8254 0 +#define DIO_8255 4 +#define DAC8254 8 + +// analog output registers for 100x, 1200 series +static inline unsigned int DAC_DATA_REG(unsigned int channel) +{ + return 2 * (channel & 0x1); +} + +/* analog output registers for 1602 series*/ +#define DACDATA 0 // DAC DATA register +#define DACFIFOCLR 2 // DAC FIFO CLEAR + +// bit in hexadecimal representation of range index that indicates unipolar input range +#define IS_UNIPOLAR 0x4 +// analog input ranges for most boards +static const struct comedi_lrange cb_pcidas_ranges = { + 8, + { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; + +// pci-das1001 input ranges +static const struct comedi_lrange cb_pcidas_alt_ranges = { + 8, + { + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.01), + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01) + } +}; + +// analog output ranges +static const struct comedi_lrange cb_pcidas_ao_ranges = { + 4, + { + BIP_RANGE(5), + BIP_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(10), + } +}; + +enum trimpot_model { + AD7376, + AD8402, +}; + +struct cb_pcidas_board { + const char *name; + unsigned short device_id; + int ai_se_chans; // Inputs in single-ended mode + int ai_diff_chans; // Inputs in differential mode + int ai_bits; // analog input resolution + int ai_speed; // fastest conversion period in ns + int ao_nchan; // number of analog out channels + int has_ao_fifo; // analog output has fifo + int ao_scan_speed; // analog output speed for 1602 series (for a scan, not conversion) + int fifo_size; // number of samples fifo can hold + const struct comedi_lrange *ranges; + enum trimpot_model trimpot; + unsigned has_dac08:1; +}; + +static const struct cb_pcidas_board cb_pcidas_boards[] = { + { + name: "pci-das1602/16", + device_id:0x1, + ai_se_chans:16, + ai_diff_chans:8, + ai_bits: 16, + ai_speed:5000, + ao_nchan:2, + has_ao_fifo:1, + ao_scan_speed:10000, + fifo_size:512, + ranges: &cb_pcidas_ranges, + trimpot: AD8402, + has_dac08:1, + }, + { + name: "pci-das1200", + device_id:0xF, + ai_se_chans:16, + ai_diff_chans:8, + ai_bits: 12, + ai_speed:3200, + ao_nchan:2, + has_ao_fifo:0, + fifo_size:1024, + ranges: &cb_pcidas_ranges, + trimpot: AD7376, + has_dac08:0, + }, + { + name: "pci-das1602/12", + device_id:0x10, + ai_se_chans:16, + ai_diff_chans:8, + ai_bits: 12, + ai_speed:3200, + ao_nchan:2, + has_ao_fifo:1, + ao_scan_speed:4000, + fifo_size:1024, + ranges: &cb_pcidas_ranges, + trimpot: AD7376, + has_dac08:0, + }, + { + name: "pci-das1200/jr", + device_id:0x19, + ai_se_chans:16, + ai_diff_chans:8, + ai_bits: 12, + ai_speed:3200, + ao_nchan:0, + has_ao_fifo:0, + fifo_size:1024, + ranges: &cb_pcidas_ranges, + trimpot: AD7376, + has_dac08:0, + }, + { + name: "pci-das1602/16/jr", + device_id:0x1C, + ai_se_chans:16, + ai_diff_chans:8, + ai_bits: 16, + ai_speed:5000, + ao_nchan:0, + has_ao_fifo:0, + fifo_size:512, + ranges: &cb_pcidas_ranges, + trimpot: AD8402, + has_dac08:1, + }, + { + name: "pci-das1000", + device_id:0x4C, + ai_se_chans:16, + ai_diff_chans:8, + ai_bits: 12, + ai_speed:4000, + ao_nchan:0, + has_ao_fifo:0, + fifo_size:1024, + ranges: &cb_pcidas_ranges, + trimpot: AD7376, + has_dac08:0, + }, + { + name: "pci-das1001", + device_id:0x1a, + ai_se_chans:16, + ai_diff_chans:8, + ai_bits: 12, + ai_speed:6800, + ao_nchan:2, + has_ao_fifo:0, + fifo_size:1024, + ranges: &cb_pcidas_alt_ranges, + trimpot: AD7376, + has_dac08:0, + }, + { + name: "pci-das1002", + device_id:0x1b, + ai_se_chans:16, + ai_diff_chans:8, + ai_bits: 12, + ai_speed:6800, + ao_nchan:2, + has_ao_fifo:0, + fifo_size:1024, + ranges: &cb_pcidas_ranges, + trimpot: AD7376, + has_dac08:0, + }, +}; + +// Number of boards in cb_pcidas_boards +#define N_BOARDS (sizeof(cb_pcidas_boards) / sizeof(struct cb_pcidas_board)) + +static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = { + {PCI_VENDOR_ID_CB, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x000f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x0010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x001c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x004c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x001a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x001b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table); + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct cb_pcidas_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct cb_pcidas_private { + /* would be useful for a PCI device */ + struct pci_dev *pci_dev; + // base addresses + unsigned long s5933_config; + unsigned long control_status; + unsigned long adc_fifo; + unsigned long pacer_counter_dio; + unsigned long ao_registers; + // divisors of master clock for analog input pacing + unsigned int divisor1; + unsigned int divisor2; + volatile unsigned int count; // number of analog input samples remaining + volatile unsigned int adc_fifo_bits; // bits to write to interupt/adcfifo register + volatile unsigned int s5933_intcsr_bits; // bits to write to amcc s5933 interrupt control/status register + volatile unsigned int ao_control_bits; // bits to write to ao control and status register + short ai_buffer[AI_BUFFER_SIZE]; + short ao_buffer[AO_BUFFER_SIZE]; + // divisors of master clock for analog output pacing + unsigned int ao_divisor1; + unsigned int ao_divisor2; + volatile unsigned int ao_count; // number of analog output samples remaining + int ao_value[2]; // remember what the analog outputs are set to, to allow readback + unsigned int caldac_value[NUM_CHANNELS_8800]; // for readback of caldac + unsigned int trimpot_value[NUM_CHANNELS_8402]; // for readback of trimpot + unsigned int dac08_value; + unsigned int calibration_source; +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct cb_pcidas_private *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int cb_pcidas_detach(struct comedi_device * dev); +static struct comedi_driver driver_cb_pcidas = { + driver_name:"cb_pcidas", + module:THIS_MODULE, + attach:cb_pcidas_attach, + detach:cb_pcidas_detach, +}; + +static int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int cb_pcidas_ao_inttrig(struct comedi_device *dev, + struct comedi_subdevice *subdev, + unsigned int trig_num); +static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG); +static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status); +static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static int cb_pcidas_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns, + int round_flags); +static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int cb_pcidas_trimpot_write(struct comedi_device * dev, unsigned int channel, + unsigned int value); +static int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dac08_write(struct comedi_device * dev, unsigned int value); +static int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int caldac_8800_write(struct comedi_device * dev, unsigned int address, + uint8_t value); +static int trimpot_7376_write(struct comedi_device * dev, uint8_t value); +static int trimpot_8402_write(struct comedi_device * dev, unsigned int channel, + uint8_t value); +static int nvram_read(struct comedi_device * dev, unsigned int address, + uint8_t * data); + +static inline unsigned int cal_enable_bits(struct comedi_device * dev) +{ + return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source); +} + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. + */ +static int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + struct pci_dev *pcidev; + int index; + int i; + + printk("comedi%d: cb_pcidas: ", dev->minor); + +/* + * Allocate the private structure area. + */ + if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0) + return -ENOMEM; + +/* + * Probe the device to determine what device in the series it is. + */ + printk("\n"); + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + // is it not a computer boards card? + if (pcidev->vendor != PCI_VENDOR_ID_CB) + continue; + // loop through cards supported by this driver + for (index = 0; index < N_BOARDS; index++) { + if (cb_pcidas_boards[index].device_id != pcidev->device) + continue; + // was a particular bus/slot requested? + if (it->options[0] || it->options[1]) { + // are we on the wrong bus/slot? + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != + it->options[1]) { + continue; + } + } + devpriv->pci_dev = pcidev; + dev->board_ptr = cb_pcidas_boards + index; + goto found; + } + } + + printk("No supported ComputerBoards/MeasurementComputing card found on " + "requested position\n"); + return -EIO; + + found: + + printk("Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name, + pcidev->bus->number, PCI_SLOT(pcidev->devfn)); + + /* + * Enable PCI device and reserve I/O ports. + */ + if (comedi_pci_enable(pcidev, "cb_pcidas")) { + printk(" Failed to enable PCI device and request regions\n"); + return -EIO; + } + /* + * Initialize devpriv->control_status and devpriv->adc_fifo to point to + * their base address. + */ + devpriv->s5933_config = + pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX); + devpriv->control_status = + pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX); + devpriv->adc_fifo = + pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX); + devpriv->pacer_counter_dio = + pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX); + if (thisboard->ao_nchan) { + devpriv->ao_registers = + pci_resource_start(devpriv->pci_dev, AO_BADRINDEX); + } + // disable and clear interrupts on amcc s5933 + outl(INTCSR_INBOX_INTR_STATUS, + devpriv->s5933_config + AMCC_OP_REG_INTCSR); + + // get irq + if (comedi_request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt, + IRQF_SHARED, "cb_pcidas", dev)) { + printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq); + return -EINVAL; + } + dev->irq = devpriv->pci_dev->irq; + + //Initialize dev->board_name + dev->board_name = thisboard->name; + +/* + * Allocate the subdevice structures. + */ + if (alloc_subdevices(dev, 7) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* analog input subdevice */ + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + /* WARNING: Number of inputs in differential mode is ignored */ + s->n_chan = thisboard->ai_se_chans; + s->len_chanlist = thisboard->ai_se_chans; + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = thisboard->ranges; + s->insn_read = cb_pcidas_ai_rinsn; + s->insn_config = ai_config_insn; + s->do_cmd = cb_pcidas_ai_cmd; + s->do_cmdtest = cb_pcidas_ai_cmdtest; + s->cancel = cb_pcidas_cancel; + + /* analog output subdevice */ + s = dev->subdevices + 1; + if (thisboard->ao_nchan) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; + s->n_chan = thisboard->ao_nchan; + // analog out resolution is the same as analog input resolution, so use ai_bits + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = &cb_pcidas_ao_ranges; + s->insn_read = cb_pcidas_ao_readback_insn; + if (thisboard->has_ao_fifo) { + dev->write_subdev = s; + s->subdev_flags |= SDF_CMD_WRITE; + s->insn_write = cb_pcidas_ao_fifo_winsn; + s->do_cmdtest = cb_pcidas_ao_cmdtest; + s->do_cmd = cb_pcidas_ao_cmd; + s->cancel = cb_pcidas_ao_cancel; + } else { + s->insn_write = cb_pcidas_ao_nofifo_winsn; + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* 8255 */ + s = dev->subdevices + 2; + subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255); + + // serial EEPROM, + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE | SDF_INTERNAL; + s->n_chan = 256; + s->maxdata = 0xff; + s->insn_read = eeprom_read_insn; + + // 8800 caldac + s = dev->subdevices + 4; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = NUM_CHANNELS_8800; + s->maxdata = 0xff; + s->insn_read = caldac_read_insn; + s->insn_write = caldac_write_insn; + for (i = 0; i < s->n_chan; i++) + caldac_8800_write(dev, i, s->maxdata / 2); + + // trim potentiometer + s = dev->subdevices + 5; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + if (thisboard->trimpot == AD7376) { + s->n_chan = NUM_CHANNELS_7376; + s->maxdata = 0x7f; + } else { + s->n_chan = NUM_CHANNELS_8402; + s->maxdata = 0xff; + } + s->insn_read = trimpot_read_insn; + s->insn_write = trimpot_write_insn; + for (i = 0; i < s->n_chan; i++) + cb_pcidas_trimpot_write(dev, i, s->maxdata / 2); + + // dac08 caldac + s = dev->subdevices + 6; + if (thisboard->has_dac08) { + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = NUM_CHANNELS_DAC08; + s->insn_read = dac08_read_insn; + s->insn_write = dac08_write_insn; + s->maxdata = 0xff; + dac08_write(dev, s->maxdata / 2); + } else + s->type = COMEDI_SUBD_UNUSED; + + // make sure mailbox 4 is empty + inl(devpriv->s5933_config + AMCC_OP_REG_IMB4); + /* Set bits to enable incoming mailbox interrupts on amcc s5933. */ + devpriv->s5933_intcsr_bits = + INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) | + INTCSR_INBOX_FULL_INT; + // clear and enable interrupt on amcc s5933 + outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS, + devpriv->s5933_config + AMCC_OP_REG_INTCSR); + + return 1; +} + +/* + * cb_pcidas_detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int cb_pcidas_detach(struct comedi_device * dev) +{ + printk("comedi%d: cb_pcidas: remove\n", dev->minor); + + if (devpriv) { + if (devpriv->s5933_config) { + // disable and clear interrupts on amcc s5933 + outl(INTCSR_INBOX_INTR_STATUS, + devpriv->s5933_config + AMCC_OP_REG_INTCSR); +#ifdef CB_PCIDAS_DEBUG + rt_printk("detaching, incsr is 0x%x\n", + inl(devpriv->s5933_config + + AMCC_OP_REG_INTCSR)); +#endif + } + } + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 2); + if (devpriv && devpriv->pci_dev) { + if (devpriv->s5933_config) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + + return 0; +} + +/* + * "instructions" read/write data in "one-shot" or "software-triggered" + * mode. + */ +static int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, i; + unsigned int bits; + static const int timeout = 10000; + int channel; + // enable calibration input if appropriate + if (insn->chanspec & CR_ALT_SOURCE) { + outw(cal_enable_bits(dev), + devpriv->control_status + CALIBRATION_REG); + channel = 0; + } else { + outw(0, devpriv->control_status + CALIBRATION_REG); + channel = CR_CHAN(insn->chanspec); + } + // set mux limits and gain + bits = BEGIN_SCAN(channel) | + END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec)); + // set unipolar/bipolar + if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR) + bits |= UNIP; + // set singleended/differential + if (CR_AREF(insn->chanspec) != AREF_DIFF) + bits |= SE; + outw(bits, devpriv->control_status + ADCMUX_CONT); + + /* clear fifo */ + outw(0, devpriv->adc_fifo + ADCFIFOCLR); + + /* convert n samples */ + for (n = 0; n < insn->n; n++) { + /* trigger conversion */ + outw(0, devpriv->adc_fifo + ADCDATA); + + /* wait for conversion to end */ + /* return -ETIMEDOUT if there is a timeout */ + for (i = 0; i < timeout; i++) { + if (inw(devpriv->control_status + ADCMUX_CONT) & EOC) + break; + } + if (i == timeout) + return -ETIMEDOUT; + + /* read data */ + data[n] = inw(devpriv->adc_fifo + ADCDATA); + } + + /* return the number of samples read/written */ + return n; +} + +static int ai_config_calibration_source(struct comedi_device * dev, unsigned int * data) +{ + static const int num_calibration_sources = 8; + unsigned int source = data[1]; + + if (source >= num_calibration_sources) { + printk("invalid calibration source: %i\n", source); + return -EINVAL; + } + + devpriv->calibration_source = source; + + return 2; +} + +static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int id = data[0]; + + switch (id) { + case INSN_CONFIG_ALT_SOURCE: + return ai_config_calibration_source(dev, data); + break; + default: + return -EINVAL; + break; + } + return -EINVAL; +} + +// analog output insn for pcidas-1000 and 1200 series +static int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int channel; + unsigned long flags; + + // set channel and range + channel = CR_CHAN(insn->chanspec); + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->ao_control_bits &= + ~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel); + devpriv->ao_control_bits |= + DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec)); + outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // remember value for readback + devpriv->ao_value[channel] = data[0]; + // send data + outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel)); + + return 1; +} + +// analog output insn for pcidas-1602 series +static int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int channel; + unsigned long flags; + + // clear dac fifo + outw(0, devpriv->ao_registers + DACFIFOCLR); + + // set channel and range + channel = CR_CHAN(insn->chanspec); + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->ao_control_bits &= + ~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) & + ~DAC_PACER_MASK; + devpriv->ao_control_bits |= + DACEN | DAC_RANGE(channel, + CR_RANGE(insn->chanspec)) | DAC_CHAN_EN(channel) | DAC_START; + outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // remember value for readback + devpriv->ao_value[channel] = data[0]; + // send data + outw(data[0], devpriv->ao_registers + DACDATA); + + return 1; +} + +// analog output readback insn +// XXX loses track of analog output value back after an analog ouput command is executed +static int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + uint8_t nvram_data; + int retval; + + retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data); + if (retval < 0) + return retval; + + data[0] = nvram_data; + + return 1; +} + +static int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + const unsigned int channel = CR_CHAN(insn->chanspec); + + return caldac_8800_write(dev, channel, data[0]); +} + +static int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)]; + + return 1; +} + +/* 1602/16 pregain offset */ +static int dac08_write(struct comedi_device * dev, unsigned int value) +{ + if (devpriv->dac08_value == value) + return 1; + + devpriv->dac08_value = value; + + outw(cal_enable_bits(dev) | (value & 0xff), + devpriv->control_status + CALIBRATION_REG); + comedi_udelay(1); + outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff), + devpriv->control_status + CALIBRATION_REG); + comedi_udelay(1); + outw(cal_enable_bits(dev) | (value & 0xff), + devpriv->control_status + CALIBRATION_REG); + comedi_udelay(1); + + return 1; +} + +static int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + return dac08_write(dev, data[0]); +} + +static int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->dac08_value; + + return 1; +} + +static int cb_pcidas_trimpot_write(struct comedi_device * dev, + unsigned int channel, unsigned int value) +{ + if (devpriv->trimpot_value[channel] == value) + return 1; + + devpriv->trimpot_value[channel] = value; + switch (thisboard->trimpot) { + case AD7376: + trimpot_7376_write(dev, value); + break; + case AD8402: + trimpot_8402_write(dev, channel, value); + break; + default: + comedi_error(dev, "driver bug?"); + return -1; + break; + } + + return 1; +} + +static int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int channel = CR_CHAN(insn->chanspec); + + return cb_pcidas_trimpot_write(dev, channel, data[0]); +} + +static int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int channel = CR_CHAN(insn->chanspec); + + data[0] = devpriv->trimpot_value[channel]; + + return 1; +} + +static int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + int i, gain, start_chan; + + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + // make sure trigger sources are compatible with each other + if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) + err++; + if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->start_src == TRIG_EXT && + (cmd->convert_src == TRIG_EXT + || cmd->scan_begin_src == TRIG_EXT)) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < + thisboard->ai_speed * cmd->chanlist_len) { + cmd->scan_begin_arg = + thisboard->ai_speed * cmd->chanlist_len; + err++; + } + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < thisboard->ai_speed) { + cmd->convert_arg = thisboard->ai_speed; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_NONE) { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + i8253_cascade_ns_to_timer_2div(TIMER_BASE, + &(devpriv->divisor1), &(devpriv->divisor2), + &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + i8253_cascade_ns_to_timer_2div(TIMER_BASE, + &(devpriv->divisor1), &(devpriv->divisor2), + &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + } + + if (err) + return 4; + + // check channel/gain list against card's limitations + if (cmd->chanlist) { + gain = CR_RANGE(cmd->chanlist[0]); + start_chan = CR_CHAN(cmd->chanlist[0]); + for (i = 1; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != + (start_chan + i) % s->n_chan) { + comedi_error(dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); + err++; + } + if (CR_RANGE(cmd->chanlist[i]) != gain) { + comedi_error(dev, + "entries in chanlist must all have the same gain\n"); + err++; + } + } + } + + if (err) + return 5; + + return 0; +} + +static int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int bits; + unsigned long flags; + + // make sure CAL_EN_BIT is disabled + outw(0, devpriv->control_status + CALIBRATION_REG); + // initialize before settings pacer source and count values + outw(0, devpriv->control_status + TRIG_CONTSTAT); + // clear fifo + outw(0, devpriv->adc_fifo + ADCFIFOCLR); + + // set mux limits, gain and pacer source + bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) | + END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) | + GAIN_BITS(CR_RANGE(cmd->chanlist[0])); + // set unipolar/bipolar + if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR) + bits |= UNIP; + // set singleended/differential + if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF) + bits |= SE; + // set pacer source + if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT) + bits |= PACER_EXT_RISE; + else + bits |= PACER_INT; + outw(bits, devpriv->control_status + ADCMUX_CONT); + +#ifdef CB_PCIDAS_DEBUG + rt_printk("comedi: sent 0x%x to adcmux control\n", bits); +#endif + + // load counters + if (cmd->convert_src == TRIG_TIMER) + cb_pcidas_load_counters(dev, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + else if (cmd->scan_begin_src == TRIG_TIMER) + cb_pcidas_load_counters(dev, &cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + + // set number of conversions + if (cmd->stop_src == TRIG_COUNT) { + devpriv->count = cmd->chanlist_len * cmd->stop_arg; + } + // enable interrupts + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->adc_fifo_bits |= INTE; + devpriv->adc_fifo_bits &= ~INT_MASK; + if (cmd->flags & TRIG_WAKE_EOS) { + if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) + devpriv->adc_fifo_bits |= INT_EOS; // interrupt end of burst + else + devpriv->adc_fifo_bits |= INT_FNE; // interrupt fifo not empty + } else { + devpriv->adc_fifo_bits |= INT_FHF; //interrupt fifo half full + } +#ifdef CB_PCIDAS_DEBUG + rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits); +#endif + // enable (and clear) interrupts + outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL, + devpriv->control_status + INT_ADCFIFO); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // set start trigger and burst mode + bits = 0; + if (cmd->start_src == TRIG_NOW) + bits |= SW_TRIGGER; + else if (cmd->start_src == TRIG_EXT) + bits |= EXT_TRIGGER | TGEN | XTRCL; + else { + comedi_error(dev, "bug!"); + return -1; + } + if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) + bits |= BURSTE; + outw(bits, devpriv->control_status + TRIG_CONTSTAT); +#ifdef CB_PCIDAS_DEBUG + rt_printk("comedi: sent 0x%x to trig control\n", bits); +#endif + + return 0; +} + +static int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < thisboard->ao_scan_speed) { + cmd->scan_begin_arg = thisboard->ao_scan_speed; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_NONE) { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + i8253_cascade_ns_to_timer_2div(TIMER_BASE, + &(devpriv->ao_divisor1), &(devpriv->ao_divisor2), + &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + + if (err) + return 4; + + // check channel/gain list against card's limitations + if (cmd->chanlist && cmd->chanlist_len > 1) { + if (CR_CHAN(cmd->chanlist[0]) != 0 || + CR_CHAN(cmd->chanlist[1]) != 1) { + comedi_error(dev, + "channels must be ordered channel 0, channel 1 in chanlist\n"); + err++; + } + } + + if (err) + return 5; + + return 0; +} + +static int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int i; + unsigned long flags; + + // set channel limits, gain + comedi_spin_lock_irqsave(&dev->spinlock, flags); + for (i = 0; i < cmd->chanlist_len; i++) { + // enable channel + devpriv->ao_control_bits |= + DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i])); + // set range + devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]), + CR_RANGE(cmd->chanlist[i])); + } + + // disable analog out before settings pacer source and count values + outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // clear fifo + outw(0, devpriv->ao_registers + DACFIFOCLR); + + // load counters + if (cmd->scan_begin_src == TRIG_TIMER) { + i8253_cascade_ns_to_timer_2div(TIMER_BASE, + &(devpriv->ao_divisor1), &(devpriv->ao_divisor2), + &(cmd->scan_begin_arg), cmd->flags); + + /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ + i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1, + devpriv->ao_divisor1, 2); + i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2, + devpriv->ao_divisor2, 2); + } + // set number of conversions + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg; + } + // set pacer source + comedi_spin_lock_irqsave(&dev->spinlock, flags); + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + devpriv->ao_control_bits |= DAC_PACER_INT; + break; + case TRIG_EXT: + devpriv->ao_control_bits |= DAC_PACER_EXT_RISE; + break; + default: + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + comedi_error(dev, "error setting dac pacer source"); + return -1; + break; + } + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + async->inttrig = cb_pcidas_ao_inttrig; + + return 0; +} + +static int cb_pcidas_ao_inttrig(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) +{ + unsigned int num_bytes, num_points = thisboard->fifo_size; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &s->async->cmd; + unsigned long flags; + + if (trig_num != 0) + return -EINVAL; + + // load up fifo + if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points) + num_points = devpriv->ao_count; + + num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer, + num_points * sizeof(short)); + num_points = num_bytes / sizeof(short); + + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ao_count -= num_points; + } + // write data to board's fifo + outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes); + + // enable dac half-full and empty interrupts + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->adc_fifo_bits |= DAEMIE | DAHFIE; +#ifdef CB_PCIDAS_DEBUG + rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits); +#endif + // enable and clear interrupts + outw(devpriv->adc_fifo_bits | DAEMI | DAHFI, + devpriv->control_status + INT_ADCFIFO); + + // start dac + devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY; + outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); +#ifdef CB_PCIDAS_DEBUG + rt_printk("comedi: sent 0x%x to dac control\n", + devpriv->ao_control_bits); +#endif + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + async->inttrig = NULL; + + return 0; +} + +static irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async; + int status, s5933_status; + int half_fifo = thisboard->fifo_size / 2; + unsigned int num_samples, i; + static const int timeout = 10000; + unsigned long flags; + + if (dev->attached == 0) { + return IRQ_NONE; + } + + async = s->async; + async->events = 0; + + s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR); +#ifdef CB_PCIDAS_DEBUG + rt_printk("intcsr 0x%x\n", s5933_status); + rt_printk("mbef 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_MBEF)); +#endif + + if ((INTCSR_INTR_ASSERTED & s5933_status) == 0) + return IRQ_NONE; + + // make sure mailbox 4 is empty + inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4); + // clear interrupt on amcc s5933 + outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS, + devpriv->s5933_config + AMCC_OP_REG_INTCSR); + + status = inw(devpriv->control_status + INT_ADCFIFO); +#ifdef CB_PCIDAS_DEBUG + if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0) { + comedi_error(dev, "spurious interrupt"); + } +#endif + + // check for analog output interrupt + if (status & (DAHFI | DAEMI)) { + handle_ao_interrupt(dev, status); + } + // check for analog input interrupts + // if fifo half-full + if (status & ADHFI) { + // read data + num_samples = half_fifo; + if (async->cmd.stop_src == TRIG_COUNT && + num_samples > devpriv->count) { + num_samples = devpriv->count; + } + insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer, + num_samples); + cfc_write_array_to_buffer(s, devpriv->ai_buffer, + num_samples * sizeof(short)); + devpriv->count -= num_samples; + if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) { + async->events |= COMEDI_CB_EOA; + cb_pcidas_cancel(dev, s); + } + // clear half-full interrupt latch + comedi_spin_lock_irqsave(&dev->spinlock, flags); + outw(devpriv->adc_fifo_bits | INT, + devpriv->control_status + INT_ADCFIFO); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + // else if fifo not empty + } else if (status & (ADNEI | EOBI)) { + for (i = 0; i < timeout; i++) { + // break if fifo is empty + if ((ADNE & inw(devpriv->control_status + + INT_ADCFIFO)) == 0) + break; + cfc_write_to_buffer(s, inw(devpriv->adc_fifo)); + if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) { /* end of acquisition */ + cb_pcidas_cancel(dev, s); + async->events |= COMEDI_CB_EOA; + break; + } + } + // clear not-empty interrupt latch + comedi_spin_lock_irqsave(&dev->spinlock, flags); + outw(devpriv->adc_fifo_bits | INT, + devpriv->control_status + INT_ADCFIFO); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + } else if (status & EOAI) { + comedi_error(dev, + "bug! encountered end of aquisition interrupt?"); + // clear EOA interrupt latch + comedi_spin_lock_irqsave(&dev->spinlock, flags); + outw(devpriv->adc_fifo_bits | EOAI, + devpriv->control_status + INT_ADCFIFO); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + } + //check for fifo overflow + if (status & LADFUL) { + comedi_error(dev, "fifo overflow"); + // clear overflow interrupt latch + comedi_spin_lock_irqsave(&dev->spinlock, flags); + outw(devpriv->adc_fifo_bits | LADFUL, + devpriv->control_status + INT_ADCFIFO); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + cb_pcidas_cancel(dev, s); + async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + } + + comedi_event(dev, s); + + return IRQ_HANDLED; +} + +static void handle_ao_interrupt(struct comedi_device * dev, unsigned int status) +{ + struct comedi_subdevice *s = dev->write_subdev; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int half_fifo = thisboard->fifo_size / 2; + unsigned int num_points; + unsigned int flags; + + async->events = 0; + + if (status & DAEMI) { + // clear dac empty interrupt latch + comedi_spin_lock_irqsave(&dev->spinlock, flags); + outw(devpriv->adc_fifo_bits | DAEMI, + devpriv->control_status + INT_ADCFIFO); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) { + if (cmd->stop_src == TRIG_NONE || + (cmd->stop_src == TRIG_COUNT + && devpriv->ao_count)) { + comedi_error(dev, "dac fifo underflow"); + cb_pcidas_ao_cancel(dev, s); + async->events |= COMEDI_CB_ERROR; + } + async->events |= COMEDI_CB_EOA; + } + } else if (status & DAHFI) { + unsigned int num_bytes; + + // figure out how many points we are writing to fifo + num_points = half_fifo; + if (cmd->stop_src == TRIG_COUNT && + devpriv->ao_count < num_points) + num_points = devpriv->ao_count; + num_bytes = + cfc_read_array_from_buffer(s, devpriv->ao_buffer, + num_points * sizeof(short)); + num_points = num_bytes / sizeof(short); + + if (async->cmd.stop_src == TRIG_COUNT) { + devpriv->ao_count -= num_points; + } + // write data to board's fifo + outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, + num_points); + // clear half-full interrupt latch + comedi_spin_lock_irqsave(&dev->spinlock, flags); + outw(devpriv->adc_fifo_bits | DAHFI, + devpriv->control_status + INT_ADCFIFO); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + } + + comedi_event(dev, s); +} + +/* cancel analog input command */ +static int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + // disable interrupts + devpriv->adc_fifo_bits &= ~INTE & ~EOAIE; + outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // disable start trigger source and burst mode + outw(0, devpriv->control_status + TRIG_CONTSTAT); + // software pacer source + outw(0, devpriv->control_status + ADCMUX_CONT); + + return 0; +} + +/* cancel analog output command */ +static int cb_pcidas_ao_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + // disable interrupts + devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE; + outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO); + + // disable output + devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK; + outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + return 0; +} + +static void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns, + int rounding_flags) +{ + i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), + &(devpriv->divisor2), ns, rounding_flags & TRIG_ROUND_MASK); + + /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ + i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1, + devpriv->divisor1, 2); + i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2, + devpriv->divisor2, 2); +} + +static void write_calibration_bitstream(struct comedi_device * dev, + unsigned int register_bits, unsigned int bitstream, + unsigned int bitstream_length) +{ + static const int write_delay = 1; + unsigned int bit; + + for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { + if (bitstream & bit) + register_bits |= SERIAL_DATA_IN_BIT; + else + register_bits &= ~SERIAL_DATA_IN_BIT; + comedi_udelay(write_delay); + outw(register_bits, devpriv->control_status + CALIBRATION_REG); + } +} + +static int caldac_8800_write(struct comedi_device * dev, unsigned int address, + uint8_t value) +{ + static const int num_caldac_channels = 8; + static const int bitstream_length = 11; + unsigned int bitstream = ((address & 0x7) << 8) | value; + static const int caldac_8800_comedi_udelay = 1; + + if (address >= num_caldac_channels) { + comedi_error(dev, "illegal caldac channel"); + return -1; + } + + if (value == devpriv->caldac_value[address]) + return 1; + + devpriv->caldac_value[address] = value; + + write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream, + bitstream_length); + + comedi_udelay(caldac_8800_comedi_udelay); + outw(cal_enable_bits(dev) | SELECT_8800_BIT, + devpriv->control_status + CALIBRATION_REG); + comedi_udelay(caldac_8800_comedi_udelay); + outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); + + return 1; +} + +static int trimpot_7376_write(struct comedi_device * dev, uint8_t value) +{ + static const int bitstream_length = 7; + unsigned int bitstream = value & 0x7f; + unsigned int register_bits; + static const int ad7376_comedi_udelay = 1; + + register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; + comedi_udelay(ad7376_comedi_udelay); + outw(register_bits, devpriv->control_status + CALIBRATION_REG); + + write_calibration_bitstream(dev, register_bits, bitstream, + bitstream_length); + + comedi_udelay(ad7376_comedi_udelay); + outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); + + return 0; +} + +/* For 1602/16 only + * ch 0 : adc gain + * ch 1 : adc postgain offset */ +static int trimpot_8402_write(struct comedi_device * dev, unsigned int channel, + uint8_t value) +{ + static const int bitstream_length = 10; + unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff); + unsigned int register_bits; + static const int ad8402_comedi_udelay = 1; + + register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT; + comedi_udelay(ad8402_comedi_udelay); + outw(register_bits, devpriv->control_status + CALIBRATION_REG); + + write_calibration_bitstream(dev, register_bits, bitstream, + bitstream_length); + + comedi_udelay(ad8402_comedi_udelay); + outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); + + return 0; +} + +static int wait_for_nvram_ready(unsigned long s5933_base_addr) +{ + static const int timeout = 1000; + unsigned int i; + + for (i = 0; i < timeout; i++) { + if ((inb(s5933_base_addr + + AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY) + == 0) + return 0; + comedi_udelay(1); + } + return -1; +} + +static int nvram_read(struct comedi_device * dev, unsigned int address, uint8_t * data) +{ + unsigned long iobase = devpriv->s5933_config; + + if (wait_for_nvram_ready(iobase) < 0) + return -ETIMEDOUT; + + outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR, + iobase + AMCC_OP_REG_MCSR_NVCMD); + outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); + outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR, + iobase + AMCC_OP_REG_MCSR_NVCMD); + outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); + outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD); + + if (wait_for_nvram_ready(iobase) < 0) + return -ETIMEDOUT; + + *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA); + + return 0; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, cb_pcidas_pci_table); diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c new file mode 100644 index 000000000000..1a580bd2247a --- /dev/null +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -0,0 +1,4222 @@ +/* + comedi/drivers/cb_pcidas64.c + This is a driver for the ComputerBoards/MeasurementComputing PCI-DAS + 64xx, 60xx, and 4020 cards. + + Author: Frank Mori Hess + Copyright (C) 2001, 2002 Frank Mori Hess + + Thanks also go to the following people: + + Steve Rosenbluth, for providing the source code for + his pci-das6402 driver, and source code for working QNX pci-6402 + drivers by Greg Laird and Mariusz Bogacz. None of the code was + used directly here, but it was useful as an additional source of + documentation on how to program the boards. + + John Sims, for much testing and feedback on pcidas-4020 support. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-8 David A. Schleef + + 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: cb_pcidas64 +Description: MeasurementComputing PCI-DAS64xx, 60XX, and 4020 series with the PLX 9080 PCI controller +Author: Frank Mori Hess +Status: works +Updated: 2002-10-09 +Devices: [Measurement Computing] PCI-DAS6402/16 (cb_pcidas64), + PCI-DAS6402/12, PCI-DAS64/M1/16, PCI-DAS64/M2/16, + PCI-DAS64/M3/16, PCI-DAS6402/16/JR, PCI-DAS64/M1/16/JR, + PCI-DAS64/M2/16/JR, PCI-DAS64/M3/16/JR, PCI-DAS64/M1/14, + PCI-DAS64/M2/14, PCI-DAS64/M3/14, PCI-DAS6013, PCI-DAS6014, + PCI-DAS6023, PCI-DAS6025, PCI-DAS6030, + PCI-DAS6031, PCI-DAS6032, PCI-DAS6033, PCI-DAS6034, + PCI-DAS6035, PCI-DAS6036, PCI-DAS6040, PCI-DAS6052, + PCI-DAS6070, PCI-DAS6071, PCI-DAS4020/12 + +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + +These boards may be autocalibrated with the comedi_calibrate utility. + +To select the bnc trigger input on the 4020 (instead of the dio input), +specify a nonzero channel in the chanspec. If you wish to use an external +master clock on the 4020, you may do so by setting the scan_begin_src +to TRIG_OTHER, and using an INSN_CONFIG_TIMER_1 configuration insn +to configure the divisor to use for the external clock. + +Some devices are not identified because the PCI device IDs are not yet +known. If you have such a board, please file a bug report at +https://bugs.comedi.org. + +*/ + +/* + +TODO: + make it return error if user attempts an ai command that uses the + external queue, and an ao command simultaneously + user counter subdevice + there are a number of boards this driver will support when they are + fully released, but does not yet since the pci device id numbers + are not yet available. + support prescaled 100khz clock for slow pacing (not available on 6000 series?) + make ao fifo size adjustable like ai fifo +*/ + +#include "../comedidev.h" +#include +#include + +#include "comedi_pci.h" +#include "8253.h" +#include "8255.h" +#include "plx9080.h" +#include "comedi_fc.h" + +#undef PCIDAS64_DEBUG // disable debugging code +//#define PCIDAS64_DEBUG // enable debugging code + +#ifdef PCIDAS64_DEBUG +#define DEBUG_PRINT(format, args...) rt_printk(format , ## args ) +#else +#define DEBUG_PRINT(format, args...) +#endif + +#define TIMER_BASE 25 // 40MHz master clock +#define PRESCALED_TIMER_BASE 10000 // 100kHz 'prescaled' clock for slow aquisition, maybe I'll support this someday +#define DMA_BUFFER_SIZE 0x1000 + +/* maximum value that can be loaded into board's 24-bit counters*/ +static const int max_counter_value = 0xffffff; + +/* PCI-DAS64xxx base addresses */ + +// indices of base address regions +enum base_address_regions { + PLX9080_BADDRINDEX = 0, + MAIN_BADDRINDEX = 2, + DIO_COUNTER_BADDRINDEX = 3, +}; + +// priv(dev)->main_iobase registers +enum write_only_registers { + INTR_ENABLE_REG = 0x0, // interrupt enable register + HW_CONFIG_REG = 0x2, // hardware config register + DAQ_SYNC_REG = 0xc, + DAQ_ATRIG_LOW_4020_REG = 0xc, + ADC_CONTROL0_REG = 0x10, // adc control register 0 + ADC_CONTROL1_REG = 0x12, // adc control register 1 + CALIBRATION_REG = 0x14, + ADC_SAMPLE_INTERVAL_LOWER_REG = 0x16, // lower 16 bits of adc sample interval counter + ADC_SAMPLE_INTERVAL_UPPER_REG = 0x18, // upper 8 bits of adc sample interval counter + ADC_DELAY_INTERVAL_LOWER_REG = 0x1a, // lower 16 bits of delay interval counter + ADC_DELAY_INTERVAL_UPPER_REG = 0x1c, // upper 8 bits of delay interval counter + ADC_COUNT_LOWER_REG = 0x1e, // lower 16 bits of hardware conversion/scan counter + ADC_COUNT_UPPER_REG = 0x20, // upper 8 bits of hardware conversion/scan counter + ADC_START_REG = 0x22, // software trigger to start aquisition + ADC_CONVERT_REG = 0x24, // initiates single conversion + ADC_QUEUE_CLEAR_REG = 0x26, // clears adc queue + ADC_QUEUE_LOAD_REG = 0x28, // loads adc queue + ADC_BUFFER_CLEAR_REG = 0x2a, + ADC_QUEUE_HIGH_REG = 0x2c, // high channel for internal queue, use adc_chan_bits() inline above + DAC_CONTROL0_REG = 0x50, // dac control register 0 + DAC_CONTROL1_REG = 0x52, // dac control register 0 + DAC_SAMPLE_INTERVAL_LOWER_REG = 0x54, // lower 16 bits of dac sample interval counter + DAC_SAMPLE_INTERVAL_UPPER_REG = 0x56, // upper 8 bits of dac sample interval counter + DAC_SELECT_REG = 0x60, + DAC_START_REG = 0x64, + DAC_BUFFER_CLEAR_REG = 0x66, // clear dac buffer +}; +static inline unsigned int dac_convert_reg(unsigned int channel) +{ + return 0x70 + (2 * (channel & 0x1)); +} +static inline unsigned int dac_lsb_4020_reg(unsigned int channel) +{ + return 0x70 + (4 * (channel & 0x1)); +} +static inline unsigned int dac_msb_4020_reg(unsigned int channel) +{ + return 0x72 + (4 * (channel & 0x1)); +} + +enum read_only_registers { + HW_STATUS_REG = 0x0, // hardware status register, reading this apparently clears pending interrupts as well + PIPE1_READ_REG = 0x4, + ADC_READ_PNTR_REG = 0x8, + LOWER_XFER_REG = 0x10, + ADC_WRITE_PNTR_REG = 0xc, + PREPOST_REG = 0x14, +}; + +enum read_write_registers { + I8255_4020_REG = 0x48, // 8255 offset, for 4020 only + ADC_QUEUE_FIFO_REG = 0x100, // external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG + ADC_FIFO_REG = 0x200, /* adc data fifo */ + DAC_FIFO_REG = 0x300, /* dac data fifo, has weird interactions with external channel queue */ +}; + +// priv(dev)->dio_counter_iobase registers +enum dio_counter_registers { + DIO_8255_OFFSET = 0x0, + DO_REG = 0x20, + DI_REG = 0x28, + DIO_DIRECTION_60XX_REG = 0x40, + DIO_DATA_60XX_REG = 0x48, +}; + +// bit definitions for write-only registers + +enum intr_enable_contents { + ADC_INTR_SRC_MASK = 0x3, // bits that set adc interrupt source + ADC_INTR_QFULL_BITS = 0x0, // interrupt fifo quater full + ADC_INTR_EOC_BITS = 0x1, // interrupt end of conversion + ADC_INTR_EOSCAN_BITS = 0x2, // interrupt end of scan + ADC_INTR_EOSEQ_BITS = 0x3, // interrupt end of sequence (probably wont use this it's pretty fancy) + EN_ADC_INTR_SRC_BIT = 0x4, // enable adc interrupt source + EN_ADC_DONE_INTR_BIT = 0x8, // enable adc aquisition done interrupt + DAC_INTR_SRC_MASK = 0x30, + DAC_INTR_QEMPTY_BITS = 0x0, + DAC_INTR_HIGH_CHAN_BITS = 0x10, + EN_DAC_INTR_SRC_BIT = 0x40, // enable dac interrupt source + EN_DAC_DONE_INTR_BIT = 0x80, + EN_ADC_ACTIVE_INTR_BIT = 0x200, // enable adc active interrupt + EN_ADC_STOP_INTR_BIT = 0x400, // enable adc stop trigger interrupt + EN_DAC_ACTIVE_INTR_BIT = 0x800, // enable dac active interrupt + EN_DAC_UNDERRUN_BIT = 0x4000, // enable dac underrun status bit + EN_ADC_OVERRUN_BIT = 0x8000, // enable adc overrun status bit +}; + +enum hw_config_contents { + MASTER_CLOCK_4020_MASK = 0x3, // bits that specify master clock source for 4020 + INTERNAL_CLOCK_4020_BITS = 0x1, // use 40 MHz internal master clock for 4020 + BNC_CLOCK_4020_BITS = 0x2, // use BNC input for master clock + EXT_CLOCK_4020_BITS = 0x3, // use dio input for master clock + EXT_QUEUE_BIT = 0x200, // use external channel/gain queue (more versatile than internal queue) + SLOW_DAC_BIT = 0x400, // use 225 nanosec strobe when loading dac instead of 50 nanosec + HW_CONFIG_DUMMY_BITS = 0x2000, // bit with unknown function yet given as default value in pci-das64 manual + DMA_CH_SELECT_BIT = 0x8000, // bit selects channels 1/0 for analog input/output, otherwise 0/1 + FIFO_SIZE_REG = 0x4, // allows adjustment of fifo sizes + DAC_FIFO_SIZE_MASK = 0xff00, // bits that set dac fifo size + DAC_FIFO_BITS = 0xf800, /* 8k sample ao fifo */ +}; +#define DAC_FIFO_SIZE 0x2000 + +enum daq_atrig_low_4020_contents { + EXT_AGATE_BNC_BIT = 0x8000, // use trig/ext clk bnc input for analog gate signal + EXT_STOP_TRIG_BNC_BIT = 0x4000, // use trig/ext clk bnc input for external stop trigger signal + EXT_START_TRIG_BNC_BIT = 0x2000, // use trig/ext clk bnc input for external start trigger signal +}; +static inline uint16_t analog_trig_low_threshold_bits(uint16_t threshold) +{ + return threshold & 0xfff; +} + +enum adc_control0_contents { + ADC_GATE_SRC_MASK = 0x3, // bits that select gate + ADC_SOFT_GATE_BITS = 0x1, // software gate + ADC_EXT_GATE_BITS = 0x2, // external digital gate + ADC_ANALOG_GATE_BITS = 0x3, // analog level gate + ADC_GATE_LEVEL_BIT = 0x4, // level-sensitive gate (for digital) + ADC_GATE_POLARITY_BIT = 0x8, // gate active low + ADC_START_TRIG_SOFT_BITS = 0x10, + ADC_START_TRIG_EXT_BITS = 0x20, + ADC_START_TRIG_ANALOG_BITS = 0x30, + ADC_START_TRIG_MASK = 0x30, + ADC_START_TRIG_FALLING_BIT = 0x40, // trig 1 uses falling edge + ADC_EXT_CONV_FALLING_BIT = 0x800, // external pacing uses falling edge + ADC_SAMPLE_COUNTER_EN_BIT = 0x1000, // enable hardware scan counter + ADC_DMA_DISABLE_BIT = 0x4000, // disables dma + ADC_ENABLE_BIT = 0x8000, // master adc enable +}; + +enum adc_control1_contents { + ADC_QUEUE_CONFIG_BIT = 0x1, // should be set for boards with > 16 channels + CONVERT_POLARITY_BIT = 0x10, + EOC_POLARITY_BIT = 0x20, + ADC_SW_GATE_BIT = 0x40, // software gate of adc + ADC_DITHER_BIT = 0x200, // turn on extra noise for dithering + RETRIGGER_BIT = 0x800, + ADC_LO_CHANNEL_4020_MASK = 0x300, + ADC_HI_CHANNEL_4020_MASK = 0xc00, + TWO_CHANNEL_4020_BITS = 0x1000, // two channel mode for 4020 + FOUR_CHANNEL_4020_BITS = 0x2000, // four channel mode for 4020 + CHANNEL_MODE_4020_MASK = 0x3000, + ADC_MODE_MASK = 0xf000, +}; +static inline uint16_t adc_lo_chan_4020_bits(unsigned int channel) +{ + return (channel & 0x3) << 8; +}; +static inline uint16_t adc_hi_chan_4020_bits(unsigned int channel) +{ + return (channel & 0x3) << 10; +}; +static inline uint16_t adc_mode_bits(unsigned int mode) +{ + return (mode & 0xf) << 12; +}; + +enum calibration_contents { + SELECT_8800_BIT = 0x1, + SELECT_8402_64XX_BIT = 0x2, + SELECT_1590_60XX_BIT = 0x2, + CAL_EN_64XX_BIT = 0x40, // calibration enable for 64xx series + SERIAL_DATA_IN_BIT = 0x80, + SERIAL_CLOCK_BIT = 0x100, + CAL_EN_60XX_BIT = 0x200, // calibration enable for 60xx series + CAL_GAIN_BIT = 0x800, +}; +/* calibration sources for 6025 are: + * 0 : ground + * 1 : 10V + * 2 : 5V + * 3 : 0.5V + * 4 : 0.05V + * 5 : ground + * 6 : dac channel 0 + * 7 : dac channel 1 + */ +static inline uint16_t adc_src_bits(unsigned int source) +{ + return (source & 0xf) << 3; +}; + +static inline uint16_t adc_convert_chan_4020_bits(unsigned int channel) +{ + return (channel & 0x3) << 8; +}; + +enum adc_queue_load_contents { + UNIP_BIT = 0x800, // unipolar/bipolar bit + ADC_SE_DIFF_BIT = 0x1000, // single-ended/ differential bit + ADC_COMMON_BIT = 0x2000, // non-referenced single-ended (common-mode input) + QUEUE_EOSEQ_BIT = 0x4000, // queue end of sequence + QUEUE_EOSCAN_BIT = 0x8000, // queue end of scan +}; +static inline uint16_t adc_chan_bits(unsigned int channel) +{ + return channel & 0x3f; +}; + +enum dac_control0_contents { + DAC_ENABLE_BIT = 0x8000, // dac controller enable bit + DAC_CYCLIC_STOP_BIT = 0x4000, + DAC_WAVEFORM_MODE_BIT = 0x100, + DAC_EXT_UPDATE_FALLING_BIT = 0x80, + DAC_EXT_UPDATE_ENABLE_BIT = 0x40, + WAVEFORM_TRIG_MASK = 0x30, + WAVEFORM_TRIG_DISABLED_BITS = 0x0, + WAVEFORM_TRIG_SOFT_BITS = 0x10, + WAVEFORM_TRIG_EXT_BITS = 0x20, + WAVEFORM_TRIG_ADC1_BITS = 0x30, + WAVEFORM_TRIG_FALLING_BIT = 0x8, + WAVEFORM_GATE_LEVEL_BIT = 0x4, + WAVEFORM_GATE_ENABLE_BIT = 0x2, + WAVEFORM_GATE_SELECT_BIT = 0x1, +}; + +enum dac_control1_contents { + DAC_WRITE_POLARITY_BIT = 0x800, /* board-dependent setting */ + DAC1_EXT_REF_BIT = 0x200, + DAC0_EXT_REF_BIT = 0x100, + DAC_OUTPUT_ENABLE_BIT = 0x80, // dac output enable bit + DAC_UPDATE_POLARITY_BIT = 0x40, /* board-dependent setting */ + DAC_SW_GATE_BIT = 0x20, + DAC1_UNIPOLAR_BIT = 0x8, + DAC0_UNIPOLAR_BIT = 0x2, +}; + +// bit definitions for read-only registers +enum hw_status_contents { + DAC_UNDERRUN_BIT = 0x1, + ADC_OVERRUN_BIT = 0x2, + DAC_ACTIVE_BIT = 0x4, + ADC_ACTIVE_BIT = 0x8, + DAC_INTR_PENDING_BIT = 0x10, + ADC_INTR_PENDING_BIT = 0x20, + DAC_DONE_BIT = 0x40, + ADC_DONE_BIT = 0x80, + EXT_INTR_PENDING_BIT = 0x100, + ADC_STOP_BIT = 0x200, +}; +static inline uint16_t pipe_full_bits(uint16_t hw_status_bits) +{ + return (hw_status_bits >> 10) & 0x3; +}; + +static inline unsigned int dma_chain_flag_bits(uint16_t prepost_bits) +{ + return (prepost_bits >> 6) & 0x3; +} +static inline unsigned int adc_upper_read_ptr_code(uint16_t prepost_bits) +{ + return (prepost_bits >> 12) & 0x3; +} +static inline unsigned int adc_upper_write_ptr_code(uint16_t prepost_bits) +{ + return (prepost_bits >> 14) & 0x3; +} + +// I2C addresses for 4020 +enum i2c_addresses { + RANGE_CAL_I2C_ADDR = 0x20, + CALDAC0_I2C_ADDR = 0xc, + CALDAC1_I2C_ADDR = 0xd, +}; + +enum range_cal_i2c_contents { + ADC_SRC_4020_MASK = 0x70, // bits that set what source the adc converter measures + BNC_TRIG_THRESHOLD_0V_BIT = 0x80, // make bnc trig/ext clock threshold 0V instead of 2.5V +}; +static inline uint8_t adc_src_4020_bits(unsigned int source) +{ + return (source << 4) & ADC_SRC_4020_MASK; +}; +static inline uint8_t attenuate_bit(unsigned int channel) +{ + // attenuate channel (+-5V input range) + return 1 << (channel & 0x3); +}; + +// analog input ranges for 64xx boards +static const struct comedi_lrange ai_ranges_64xx = { + 8, + { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; + +/* analog input ranges for 60xx boards */ +static const struct comedi_lrange ai_ranges_60xx = { + 4, + { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + } +}; + +/* analog input ranges for 6030, etc boards */ +static const struct comedi_lrange ai_ranges_6030 = { + 14, + { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1), + BIP_RANGE(0.5), + BIP_RANGE(0.2), + BIP_RANGE(0.1), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1), + UNI_RANGE(0.5), + UNI_RANGE(0.2), + UNI_RANGE(0.1), + } +}; + +/* analog input ranges for 6052, etc boards */ +static const struct comedi_lrange ai_ranges_6052 = { + 15, + { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1), + BIP_RANGE(0.5), + BIP_RANGE(0.25), + BIP_RANGE(0.1), + BIP_RANGE(0.05), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1), + UNI_RANGE(0.5), + UNI_RANGE(0.2), + UNI_RANGE(0.1), + } +}; + +// analog input ranges for 4020 board +static const struct comedi_lrange ai_ranges_4020 = { + 2, + { + BIP_RANGE(5), + BIP_RANGE(1), + } +}; + +// analog output ranges +static const struct comedi_lrange ao_ranges_64xx = { + 4, + { + BIP_RANGE(5), + BIP_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(10), + } +}; +static const int ao_range_code_64xx[] = { + 0x0, + 0x1, + 0x2, + 0x3, +}; + +static const struct comedi_lrange ao_ranges_60xx = { + 1, + { + BIP_RANGE(10), + } +}; +static const int ao_range_code_60xx[] = { + 0x0, +}; + +static const struct comedi_lrange ao_ranges_6030 = { + 2, + { + BIP_RANGE(10), + UNI_RANGE(10), + } +}; +static const int ao_range_code_6030[] = { + 0x0, + 0x2, +}; + +static const struct comedi_lrange ao_ranges_4020 = { + 2, + { + BIP_RANGE(5), + BIP_RANGE(10), + } +}; +static const int ao_range_code_4020[] = { + 0x1, + 0x0, +}; + +enum register_layout { + LAYOUT_60XX, + LAYOUT_64XX, + LAYOUT_4020, +}; + +struct hw_fifo_info { + unsigned int num_segments; + unsigned int max_segment_length; + unsigned int sample_packing_ratio; + uint16_t fifo_size_reg_mask; +}; + +struct pcidas64_board { + const char *name; + int device_id; // pci device id + int ai_se_chans; // number of ai inputs in single-ended mode + int ai_bits; // analog input resolution + int ai_speed; // fastest conversion period in ns + const struct comedi_lrange *ai_range_table; + int ao_nchan; // number of analog out channels + int ao_bits; // analog output resolution + int ao_scan_speed; // analog output speed (for a scan, not conversion) + const struct comedi_lrange *ao_range_table; + const int *ao_range_code; + const struct hw_fifo_info *const ai_fifo; + enum register_layout layout; // different board families have slightly different registers + unsigned has_8255:1; +}; + +static const struct hw_fifo_info ai_fifo_4020 = { + num_segments:2, + max_segment_length:0x8000, + sample_packing_ratio:2, + fifo_size_reg_mask:0x7f, +}; + +static const struct hw_fifo_info ai_fifo_64xx = { + num_segments:4, + max_segment_length:0x800, + sample_packing_ratio:1, + fifo_size_reg_mask:0x3f, +}; + +static const struct hw_fifo_info ai_fifo_60xx = { + num_segments:4, + max_segment_length:0x800, + sample_packing_ratio:1, + fifo_size_reg_mask:0x7f, +}; + +/* maximum number of dma transfers we will chain together into a ring + * (and the maximum number of dma buffers we maintain) */ +#define MAX_AI_DMA_RING_COUNT (0x80000 / DMA_BUFFER_SIZE) +#define MIN_AI_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) +#define AO_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) +static inline unsigned int ai_dma_ring_count(struct pcidas64_board * board) +{ + if (board->layout == LAYOUT_4020) + return MAX_AI_DMA_RING_COUNT; + else + return MIN_AI_DMA_RING_COUNT; +} + +static const int bytes_in_sample = 2; + +static const struct pcidas64_board pcidas64_boards[] = { + { + name: "pci-das6402/16", + device_id:0x1d, + ai_se_chans:64, + ai_bits: 16, + ai_speed:5000, + ao_nchan:2, + ao_bits: 16, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ao_range_table:&ao_ranges_64xx, + ao_range_code:ao_range_code_64xx, + ai_fifo: &ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das6402/12", // XXX check + device_id:0x1e, + ai_se_chans:64, + ai_bits: 12, + ai_speed:5000, + ao_nchan:2, + ao_bits: 12, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ao_range_table:&ao_ranges_64xx, + ao_range_code:ao_range_code_64xx, + ai_fifo: &ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das64/m1/16", + device_id:0x35, + ai_se_chans:64, + ai_bits: 16, + ai_speed:1000, + ao_nchan:2, + ao_bits: 16, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ao_range_table:&ao_ranges_64xx, + ao_range_code:ao_range_code_64xx, + ai_fifo: &ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das64/m2/16", + device_id:0x36, + ai_se_chans:64, + ai_bits: 16, + ai_speed:500, + ao_nchan:2, + ao_bits: 16, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ao_range_table:&ao_ranges_64xx, + ao_range_code:ao_range_code_64xx, + ai_fifo: &ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das64/m3/16", + device_id:0x37, + ai_se_chans:64, + ai_bits: 16, + ai_speed:333, + ao_nchan:2, + ao_bits: 16, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ao_range_table:&ao_ranges_64xx, + ao_range_code:ao_range_code_64xx, + ai_fifo: &ai_fifo_64xx, + has_8255:1, + }, + { + .name = "pci-das6013", + .device_id = 0x78, + .ai_se_chans = 16, + .ai_bits = 16, + .ai_speed = 5000, + .ao_nchan = 0, + .ao_bits = 16, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, + .ao_range_table = &ao_ranges_60xx, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, + { + name: "pci-das6014", + device_id:0x79, + ai_se_chans:16, + ai_bits: 16, + ai_speed:5000, + ao_nchan:2, + ao_bits: 16, + ao_scan_speed:100000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_60xx, + ao_range_table:&ao_ranges_60xx, + ao_range_code:ao_range_code_60xx, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6023", + device_id:0x5d, + ai_se_chans:16, + ai_bits: 12, + ai_speed:5000, + ao_nchan:0, + ao_scan_speed:100000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_60xx, + ao_range_table:&ao_ranges_60xx, + ao_range_code:ao_range_code_60xx, + ai_fifo: &ai_fifo_60xx, + has_8255:1, + }, + { + name: "pci-das6025", + device_id:0x5e, + ai_se_chans:16, + ai_bits: 12, + ai_speed:5000, + ao_nchan:2, + ao_bits: 12, + ao_scan_speed:100000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_60xx, + ao_range_table:&ao_ranges_60xx, + ao_range_code:ao_range_code_60xx, + ai_fifo: &ai_fifo_60xx, + has_8255:1, + }, + { + name: "pci-das6030", + device_id:0x5f, + ai_se_chans:16, + ai_bits: 16, + ai_speed:10000, + ao_nchan:2, + ao_bits: 16, + ao_scan_speed:10000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_6030, + ao_range_table:&ao_ranges_6030, + ao_range_code:ao_range_code_6030, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6031", + device_id:0x60, + ai_se_chans:64, + ai_bits: 16, + ai_speed:10000, + ao_nchan:2, + ao_bits: 16, + ao_scan_speed:10000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_6030, + ao_range_table:&ao_ranges_6030, + ao_range_code:ao_range_code_6030, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6032", + device_id:0x61, + ai_se_chans:16, + ai_bits: 16, + ai_speed:10000, + ao_nchan:0, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_6030, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6033", + device_id:0x62, + ai_se_chans:64, + ai_bits: 16, + ai_speed:10000, + ao_nchan:0, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_6030, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6034", + device_id:0x63, + ai_se_chans:16, + ai_bits: 16, + ai_speed:5000, + ao_nchan:0, + ao_scan_speed:0, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_60xx, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6035", + device_id:0x64, + ai_se_chans:16, + ai_bits: 16, + ai_speed:5000, + ao_nchan:2, + ao_bits: 12, + ao_scan_speed:100000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_60xx, + ao_range_table:&ao_ranges_60xx, + ao_range_code:ao_range_code_60xx, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6036", + device_id:0x6f, + ai_se_chans:16, + ai_bits: 16, + ai_speed:5000, + ao_nchan:2, + ao_bits: 16, + ao_scan_speed:100000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_60xx, + ao_range_table:&ao_ranges_60xx, + ao_range_code:ao_range_code_60xx, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6040", + device_id:0x65, + ai_se_chans:16, + ai_bits: 12, + ai_speed:2000, + ao_nchan:2, + ao_bits: 12, + ao_scan_speed:1000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_6052, + ao_range_table:&ao_ranges_6030, + ao_range_code:ao_range_code_6030, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6052", + device_id:0x66, + ai_se_chans:16, + ai_bits: 16, + ai_speed:3333, + ao_nchan:2, + ao_bits: 16, + ao_scan_speed:3333, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_6052, + ao_range_table:&ao_ranges_6030, + ao_range_code:ao_range_code_6030, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6070", + device_id:0x67, + ai_se_chans:16, + ai_bits: 12, + ai_speed:800, + ao_nchan:2, + ao_bits: 12, + ao_scan_speed:1000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_6052, + ao_range_table:&ao_ranges_6030, + ao_range_code:ao_range_code_6030, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das6071", + device_id:0x68, + ai_se_chans:64, + ai_bits: 12, + ai_speed:800, + ao_nchan:2, + ao_bits: 12, + ao_scan_speed:1000, + layout: LAYOUT_60XX, + ai_range_table:&ai_ranges_6052, + ao_range_table:&ao_ranges_6030, + ao_range_code:ao_range_code_6030, + ai_fifo: &ai_fifo_60xx, + has_8255:0, + }, + { + name: "pci-das4020/12", + device_id:0x52, + ai_se_chans:4, + ai_bits: 12, + ai_speed:50, + ao_bits: 12, + ao_nchan:2, + ao_scan_speed:0, // no hardware pacing on ao + layout: LAYOUT_4020, + ai_range_table:&ai_ranges_4020, + ao_range_table:&ao_ranges_4020, + ao_range_code:ao_range_code_4020, + ai_fifo: &ai_fifo_4020, + has_8255:1, + }, +#if 0 + { + name: "pci-das6402/16/jr", + device_id:0 // XXX, + ai_se_chans:64, + ai_bits: 16, + ai_speed:5000, + ao_nchan:0, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ai_fifo: ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das64/m1/16/jr", + device_id:0 // XXX, + ai_se_chans:64, + ai_bits: 16, + ai_speed:1000, + ao_nchan:0, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ai_fifo: ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das64/m2/16/jr", + device_id:0 // XXX, + ai_se_chans:64, + ai_bits: 16, + ai_speed:500, + ao_nchan:0, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ai_fifo: ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das64/m3/16/jr", + device_id:0 // XXX, + ai_se_chans:64, + ai_bits: 16, + ai_speed:333, + ao_nchan:0, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ai_fifo: ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das64/m1/14", + device_id:0, // XXX + ai_se_chans:64, + ai_bits: 14, + ai_speed:1000, + ao_nchan:2, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ai_fifo: ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das64/m2/14", + device_id:0, // XXX + ai_se_chans:64, + ai_bits: 14, + ai_speed:500, + ao_nchan:2, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ai_fifo: ai_fifo_64xx, + has_8255:1, + }, + { + name: "pci-das64/m3/14", + device_id:0, // XXX + ai_se_chans:64, + ai_bits: 14, + ai_speed:333, + ao_nchan:2, + ao_scan_speed:10000, + layout: LAYOUT_64XX, + ai_range_table:&ai_ranges_64xx, + ai_fifo: ai_fifo_64xx, + has_8255:1, + }, +#endif +}; + +// Number of boards in cb_pcidas_boards +static inline unsigned int num_boards(void) +{ + return sizeof(pcidas64_boards) / sizeof(struct pcidas64_board); +} + +static DEFINE_PCI_DEVICE_TABLE(pcidas64_pci_table) = { + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x001d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x001e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0035, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0036, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0037, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x005d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x005e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x005f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0061, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0062, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0063, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0066, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0067, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x006f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0078, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0079, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pcidas64_pci_table); + +static inline struct pcidas64_board *board(const struct comedi_device * dev) +{ + return (struct pcidas64_board *) dev->board_ptr; +} + +static inline unsigned short se_diff_bit_6xxx(struct comedi_device * dev, + int use_differential) +{ + if ((board(dev)->layout == LAYOUT_64XX && !use_differential) || + (board(dev)->layout == LAYOUT_60XX && use_differential)) + return ADC_SE_DIFF_BIT; + else + return 0; +}; + +struct ext_clock_info { + unsigned int divisor; // master clock divisor to use for scans with external master clock + unsigned int chanspec; // chanspec for master clock input when used as scan begin src +}; + +/* this structure is for data unique to this hardware driver. */ +struct pcidas64_private { + + struct pci_dev *hw_dev; // pointer to board's pci_dev struct + // base addresses (physical) + resource_size_t plx9080_phys_iobase; + resource_size_t main_phys_iobase; + resource_size_t dio_counter_phys_iobase; + // base addresses (ioremapped) + void *plx9080_iobase; + void *main_iobase; + void *dio_counter_iobase; + // local address (used by dma controller) + uint32_t local0_iobase; + uint32_t local1_iobase; + volatile unsigned int ai_count; // number of analog input samples remaining + uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT]; // dma buffers for analog input + dma_addr_t ai_buffer_bus_addr[MAX_AI_DMA_RING_COUNT]; // physical addresses of ai dma buffers + struct plx_dma_desc *ai_dma_desc; // array of ai dma descriptors read by plx9080, allocated to get proper alignment + dma_addr_t ai_dma_desc_bus_addr; // physical address of ai dma descriptor array + volatile unsigned int ai_dma_index; // index of the ai dma descriptor/buffer that is currently being used + uint16_t *ao_buffer[AO_DMA_RING_COUNT]; // dma buffers for analog output + dma_addr_t ao_buffer_bus_addr[AO_DMA_RING_COUNT]; // physical addresses of ao dma buffers + struct plx_dma_desc *ao_dma_desc; + dma_addr_t ao_dma_desc_bus_addr; + volatile unsigned int ao_dma_index; // keeps track of buffer where the next ao sample should go + volatile unsigned long ao_count; // number of analog output samples remaining + volatile unsigned int ao_value[2]; // remember what the analog outputs are set to, to allow readback + unsigned int hw_revision; // stc chip hardware revision number + volatile unsigned int intr_enable_bits; // last bits sent to INTR_ENABLE_REG register + volatile uint16_t adc_control1_bits; // last bits sent to ADC_CONTROL1_REG register + volatile uint16_t fifo_size_bits; // last bits sent to FIFO_SIZE_REG register + volatile uint16_t hw_config_bits; // last bits sent to HW_CONFIG_REG register + volatile uint16_t dac_control1_bits; + volatile uint32_t plx_control_bits; // last bits written to plx9080 control register + volatile uint32_t plx_intcsr_bits; // last bits written to plx interrupt control and status register + volatile int calibration_source; // index of calibration source readable through ai ch0 + volatile uint8_t i2c_cal_range_bits; // bits written to i2c calibration/range register + volatile unsigned int ext_trig_falling; // configure digital triggers to trigger on falling edge + // states of various devices stored to enable read-back + unsigned int ad8402_state[2]; + unsigned int caldac_state[8]; + volatile short ai_cmd_running; + unsigned int ai_fifo_segment_length; + struct ext_clock_info ext_clock; + short ao_bounce_buffer[DAC_FIFO_SIZE]; +}; + + +/* inline function that makes it easier to + * access the private structure. + */ +static inline struct pcidas64_private *priv(struct comedi_device * dev) +{ + return dev->private; +} + +/* + * The comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int detach(struct comedi_device * dev); +static struct comedi_driver driver_cb_pcidas = { + driver_name:"cb_pcidas64", + module:THIS_MODULE, + attach:attach, + detach:detach, +}; + +static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * subdev, + unsigned int trig_num); +static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG); +static int ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static int ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static int dio_callback(int dir, int port, int data, unsigned long arg); +static int dio_callback_4020(int dir, int port, int data, unsigned long arg); +static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dio_60xx_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ad8402_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static void ad8402_write(struct comedi_device * dev, unsigned int channel, + unsigned int value); +static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static void check_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd); +static unsigned int get_divisor(unsigned int ns, unsigned int flags); +static void i2c_write(struct comedi_device * dev, unsigned int address, + const uint8_t * data, unsigned int length); +static void caldac_write(struct comedi_device * dev, unsigned int channel, + unsigned int value); +static int caldac_8800_write(struct comedi_device * dev, unsigned int address, + uint8_t value); +//static int dac_1590_write(struct comedi_device *dev, unsigned int dac_a, unsigned int dac_b); +static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_channel, + unsigned int value); +static void abort_dma(struct comedi_device * dev, unsigned int channel); +static void disable_plx_interrupts(struct comedi_device * dev); +static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples); +static unsigned int ai_fifo_size(struct comedi_device * dev); +static int set_ai_fifo_segment_length(struct comedi_device * dev, + unsigned int num_entries); +static void disable_ai_pacing(struct comedi_device * dev); +static void disable_ai_interrupts(struct comedi_device * dev); +static void enable_ai_interrupts(struct comedi_device * dev, const struct comedi_cmd * cmd); +static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags); +static void load_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd); + +COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, pcidas64_pci_table); + +static unsigned int ai_range_bits_6xxx(const struct comedi_device * dev, + unsigned int range_index) +{ + const struct comedi_krange *range = + &board(dev)->ai_range_table->range[range_index]; + unsigned int bits = 0; + + switch (range->max) { + case 10000000: + bits = 0x000; + break; + case 5000000: + bits = 0x100; + break; + case 2000000: + case 2500000: + bits = 0x200; + break; + case 1000000: + case 1250000: + bits = 0x300; + break; + case 500000: + bits = 0x400; + break; + case 200000: + case 250000: + bits = 0x500; + break; + case 100000: + bits = 0x600; + break; + case 50000: + bits = 0x700; + break; + default: + comedi_error(dev, "bug! in ai_range_bits_6xxx"); + break; + } + if (range->min == 0) + bits += 0x900; + return bits; +} + +static unsigned int hw_revision(const struct comedi_device * dev, + uint16_t hw_status_bits) +{ + if (board(dev)->layout == LAYOUT_4020) + return (hw_status_bits >> 13) & 0x7; + + return (hw_status_bits >> 12) & 0xf; +} + +static void set_dac_range_bits(struct comedi_device * dev, volatile uint16_t * bits, + unsigned int channel, unsigned int range) +{ + unsigned int code = board(dev)->ao_range_code[range]; + + if (channel > 1) + comedi_error(dev, "bug! bad channel?"); + if (code & ~0x3) + comedi_error(dev, "bug! bad range code?"); + + *bits &= ~(0x3 << (2 * channel)); + *bits |= code << (2 * channel); +}; + +static inline int ao_cmd_is_supported(const struct pcidas64_board * board) +{ + return board->ao_nchan && board->layout != LAYOUT_4020; +} + +// initialize plx9080 chip +static void init_plx9080(struct comedi_device * dev) +{ + uint32_t bits; + void *plx_iobase = priv(dev)->plx9080_iobase; + + priv(dev)->plx_control_bits = + readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG); + + // plx9080 dump + DEBUG_PRINT(" plx interrupt status 0x%x\n", + readl(plx_iobase + PLX_INTRCS_REG)); + DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG)); + DEBUG_PRINT(" plx control reg 0x%x\n", priv(dev)->plx_control_bits); + DEBUG_PRINT(" plx mode/arbitration reg 0x%x\n", + readl(plx_iobase + PLX_MARB_REG)); + DEBUG_PRINT(" plx region0 reg 0x%x\n", + readl(plx_iobase + PLX_REGION0_REG)); + DEBUG_PRINT(" plx region1 reg 0x%x\n", + readl(plx_iobase + PLX_REGION1_REG)); + + DEBUG_PRINT(" plx revision 0x%x\n", + readl(plx_iobase + PLX_REVISION_REG)); + DEBUG_PRINT(" plx dma channel 0 mode 0x%x\n", + readl(plx_iobase + PLX_DMA0_MODE_REG)); + DEBUG_PRINT(" plx dma channel 1 mode 0x%x\n", + readl(plx_iobase + PLX_DMA1_MODE_REG)); + DEBUG_PRINT(" plx dma channel 0 pci address 0x%x\n", + readl(plx_iobase + PLX_DMA0_PCI_ADDRESS_REG)); + DEBUG_PRINT(" plx dma channel 0 local address 0x%x\n", + readl(plx_iobase + PLX_DMA0_LOCAL_ADDRESS_REG)); + DEBUG_PRINT(" plx dma channel 0 transfer size 0x%x\n", + readl(plx_iobase + PLX_DMA0_TRANSFER_SIZE_REG)); + DEBUG_PRINT(" plx dma channel 0 descriptor 0x%x\n", + readl(plx_iobase + PLX_DMA0_DESCRIPTOR_REG)); + DEBUG_PRINT(" plx dma channel 0 command status 0x%x\n", + readb(plx_iobase + PLX_DMA0_CS_REG)); + DEBUG_PRINT(" plx dma channel 0 threshold 0x%x\n", + readl(plx_iobase + PLX_DMA0_THRESHOLD_REG)); + DEBUG_PRINT(" plx bigend 0x%x\n", readl(plx_iobase + PLX_BIGEND_REG)); + +#ifdef __BIG_ENDIAN + bits = BIGEND_DMA0 | BIGEND_DMA1; +#else + bits = 0; +#endif + writel(bits, priv(dev)->plx9080_iobase + PLX_BIGEND_REG); + + disable_plx_interrupts(dev); + + abort_dma(dev, 0); + abort_dma(dev, 1); + + // configure dma0 mode + bits = 0; + // enable ready input, not sure if this is necessary + bits |= PLX_DMA_EN_READYIN_BIT; + // enable bterm, not sure if this is necessary + bits |= PLX_EN_BTERM_BIT; + // enable dma chaining + bits |= PLX_EN_CHAIN_BIT; + // enable interrupt on dma done (probably don't need this, since chain never finishes) + bits |= PLX_EN_DMA_DONE_INTR_BIT; + // don't increment local address during transfers (we are transferring from a fixed fifo register) + bits |= PLX_LOCAL_ADDR_CONST_BIT; + // route dma interrupt to pci bus + bits |= PLX_DMA_INTR_PCI_BIT; + // enable demand mode + bits |= PLX_DEMAND_MODE_BIT; + // enable local burst mode + bits |= PLX_DMA_LOCAL_BURST_EN_BIT; + // 4020 uses 32 bit dma + if (board(dev)->layout == LAYOUT_4020) { + bits |= PLX_LOCAL_BUS_32_WIDE_BITS; + } else { // localspace0 bus is 16 bits wide + bits |= PLX_LOCAL_BUS_16_WIDE_BITS; + } + writel(bits, plx_iobase + PLX_DMA1_MODE_REG); + if (ao_cmd_is_supported(board(dev))) + writel(bits, plx_iobase + PLX_DMA0_MODE_REG); + + // enable interrupts on plx 9080 + priv(dev)->plx_intcsr_bits |= + ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE | + ICS_DMA0_E | ICS_DMA1_E; + writel(priv(dev)->plx_intcsr_bits, + priv(dev)->plx9080_iobase + PLX_INTRCS_REG); +} + +/* Allocate and initialize the subdevice structures. + */ +static int setup_subdevices(struct comedi_device * dev) +{ + struct comedi_subdevice *s; + void *dio_8255_iobase; + int i; + + if (alloc_subdevices(dev, 10) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* analog input subdevice */ + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DITHER | SDF_CMD_READ; + if (board(dev)->layout == LAYOUT_60XX) + s->subdev_flags |= SDF_COMMON | SDF_DIFF; + else if (board(dev)->layout == LAYOUT_64XX) + s->subdev_flags |= SDF_DIFF; + /* XXX Number of inputs in differential mode is ignored */ + s->n_chan = board(dev)->ai_se_chans; + s->len_chanlist = 0x2000; + s->maxdata = (1 << board(dev)->ai_bits) - 1; + s->range_table = board(dev)->ai_range_table; + s->insn_read = ai_rinsn; + s->insn_config = ai_config_insn; + s->do_cmd = ai_cmd; + s->do_cmdtest = ai_cmdtest; + s->cancel = ai_cancel; + if (board(dev)->layout == LAYOUT_4020) { + unsigned int i; + uint8_t data; + // set adc to read from inputs (not internal calibration sources) + priv(dev)->i2c_cal_range_bits = adc_src_4020_bits(4); + // set channels to +-5 volt input ranges + for (i = 0; i < s->n_chan; i++) + priv(dev)->i2c_cal_range_bits |= attenuate_bit(i); + data = priv(dev)->i2c_cal_range_bits; + i2c_write(dev, RANGE_CAL_I2C_ADDR, &data, sizeof(data)); + } + + /* analog output subdevice */ + s = dev->subdevices + 1; + if (board(dev)->ao_nchan) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = + SDF_READABLE | SDF_WRITABLE | SDF_GROUND | + SDF_CMD_WRITE; + s->n_chan = board(dev)->ao_nchan; + s->maxdata = (1 << board(dev)->ao_bits) - 1; + s->range_table = board(dev)->ao_range_table; + s->insn_read = ao_readback_insn; + s->insn_write = ao_winsn; + if (ao_cmd_is_supported(board(dev))) { + dev->write_subdev = s; + s->do_cmdtest = ao_cmdtest; + s->do_cmd = ao_cmd; + s->len_chanlist = board(dev)->ao_nchan; + s->cancel = ao_cancel; + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + // digital input + s = dev->subdevices + 2; + if (board(dev)->layout == LAYOUT_64XX) { + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = di_rbits; + } else + s->type = COMEDI_SUBD_UNUSED; + + // digital output + if (board(dev)->layout == LAYOUT_64XX) { + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = do_wbits; + } else + s->type = COMEDI_SUBD_UNUSED; + + /* 8255 */ + s = dev->subdevices + 4; + if (board(dev)->has_8255) { + if (board(dev)->layout == LAYOUT_4020) { + dio_8255_iobase = + priv(dev)->main_iobase + I8255_4020_REG; + subdev_8255_init(dev, s, dio_callback_4020, + (unsigned long)dio_8255_iobase); + } else { + dio_8255_iobase = + priv(dev)->dio_counter_iobase + DIO_8255_OFFSET; + subdev_8255_init(dev, s, dio_callback, + (unsigned long)dio_8255_iobase); + } + } else + s->type = COMEDI_SUBD_UNUSED; + + // 8 channel dio for 60xx + s = dev->subdevices + 5; + if (board(dev)->layout == LAYOUT_60XX) { + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_config = dio_60xx_config_insn; + s->insn_bits = dio_60xx_wbits; + } else + s->type = COMEDI_SUBD_UNUSED; + + // caldac + s = dev->subdevices + 6; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 8; + if (board(dev)->layout == LAYOUT_4020) + s->maxdata = 0xfff; + else + s->maxdata = 0xff; + s->insn_read = calib_read_insn; + s->insn_write = calib_write_insn; + for (i = 0; i < s->n_chan; i++) + caldac_write(dev, i, s->maxdata / 2); + + // 2 channel ad8402 potentiometer + s = dev->subdevices + 7; + if (board(dev)->layout == LAYOUT_64XX) { + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 2; + s->insn_read = ad8402_read_insn; + s->insn_write = ad8402_write_insn; + s->maxdata = 0xff; + for (i = 0; i < s->n_chan; i++) + ad8402_write(dev, i, s->maxdata / 2); + } else + s->type = COMEDI_SUBD_UNUSED; + + //serial EEPROM, if present + s = dev->subdevices + 8; + if (readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG) & CTL_EECHK) { + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE | SDF_INTERNAL; + s->n_chan = 128; + s->maxdata = 0xffff; + s->insn_read = eeprom_read_insn; + } else + s->type = COMEDI_SUBD_UNUSED; + + // user counter subd XXX + s = dev->subdevices + 9; + s->type = COMEDI_SUBD_UNUSED; + + return 0; +} + +static void disable_plx_interrupts(struct comedi_device * dev) +{ + priv(dev)->plx_intcsr_bits = 0; + writel(priv(dev)->plx_intcsr_bits, + priv(dev)->plx9080_iobase + PLX_INTRCS_REG); +} + +static void init_stc_registers(struct comedi_device * dev) +{ + uint16_t bits; + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + + // bit should be set for 6025, although docs say boards with <= 16 chans should be cleared XXX + if (1) + priv(dev)->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT; + writew(priv(dev)->adc_control1_bits, + priv(dev)->main_iobase + ADC_CONTROL1_REG); + + // 6402/16 manual says this register must be initialized to 0xff? + writew(0xff, priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); + + bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT; + if (board(dev)->layout == LAYOUT_4020) + bits |= INTERNAL_CLOCK_4020_BITS; + priv(dev)->hw_config_bits |= bits; + writew(priv(dev)->hw_config_bits, + priv(dev)->main_iobase + HW_CONFIG_REG); + + writew(0, priv(dev)->main_iobase + DAQ_SYNC_REG); + writew(0, priv(dev)->main_iobase + CALIBRATION_REG); + + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // set fifos to maximum size + priv(dev)->fifo_size_bits |= DAC_FIFO_BITS; + set_ai_fifo_segment_length(dev, + board(dev)->ai_fifo->max_segment_length); + + priv(dev)->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT; + priv(dev)->intr_enable_bits = /* EN_DAC_INTR_SRC_BIT | DAC_INTR_QEMPTY_BITS | */ + EN_DAC_DONE_INTR_BIT | EN_DAC_UNDERRUN_BIT; + writew(priv(dev)->intr_enable_bits, + priv(dev)->main_iobase + INTR_ENABLE_REG); + + disable_ai_pacing(dev); +}; + +int alloc_and_init_dma_members(struct comedi_device * dev) +{ + int i; + + // alocate pci dma buffers + for (i = 0; i < ai_dma_ring_count(board(dev)); i++) { + priv(dev)->ai_buffer[i] = + pci_alloc_consistent(priv(dev)->hw_dev, DMA_BUFFER_SIZE, + &priv(dev)->ai_buffer_bus_addr[i]); + if (priv(dev)->ai_buffer[i] == NULL) { + return -ENOMEM; + } + } + for (i = 0; i < AO_DMA_RING_COUNT; i++) { + if (ao_cmd_is_supported(board(dev))) { + priv(dev)->ao_buffer[i] = + pci_alloc_consistent(priv(dev)->hw_dev, + DMA_BUFFER_SIZE, + &priv(dev)->ao_buffer_bus_addr[i]); + if (priv(dev)->ao_buffer[i] == NULL) { + return -ENOMEM; + } + } + } + // allocate dma descriptors + priv(dev)->ai_dma_desc = + pci_alloc_consistent(priv(dev)->hw_dev, + sizeof(struct plx_dma_desc) * ai_dma_ring_count(board(dev)), + &priv(dev)->ai_dma_desc_bus_addr); + if (priv(dev)->ai_dma_desc == NULL) { + return -ENOMEM; + } + DEBUG_PRINT("ai dma descriptors start at bus addr 0x%x\n", + priv(dev)->ai_dma_desc_bus_addr); + if (ao_cmd_is_supported(board(dev))) { + priv(dev)->ao_dma_desc = + pci_alloc_consistent(priv(dev)->hw_dev, + sizeof(struct plx_dma_desc) * AO_DMA_RING_COUNT, + &priv(dev)->ao_dma_desc_bus_addr); + if (priv(dev)->ao_dma_desc == NULL) { + return -ENOMEM; + } + DEBUG_PRINT("ao dma descriptors start at bus addr 0x%x\n", + priv(dev)->ao_dma_desc_bus_addr); + } + // initialize dma descriptors + for (i = 0; i < ai_dma_ring_count(board(dev)); i++) { + priv(dev)->ai_dma_desc[i].pci_start_addr = + cpu_to_le32(priv(dev)->ai_buffer_bus_addr[i]); + if (board(dev)->layout == LAYOUT_4020) + priv(dev)->ai_dma_desc[i].local_start_addr = + cpu_to_le32(priv(dev)->local1_iobase + + ADC_FIFO_REG); + else + priv(dev)->ai_dma_desc[i].local_start_addr = + cpu_to_le32(priv(dev)->local0_iobase + + ADC_FIFO_REG); + priv(dev)->ai_dma_desc[i].transfer_size = cpu_to_le32(0); + priv(dev)->ai_dma_desc[i].next = + cpu_to_le32((priv(dev)->ai_dma_desc_bus_addr + ((i + + 1) % + ai_dma_ring_count(board(dev))) * + sizeof(priv(dev)-> + ai_dma_desc[0])) | PLX_DESC_IN_PCI_BIT | + PLX_INTR_TERM_COUNT | PLX_XFER_LOCAL_TO_PCI); + } + if (ao_cmd_is_supported(board(dev))) { + for (i = 0; i < AO_DMA_RING_COUNT; i++) { + priv(dev)->ao_dma_desc[i].pci_start_addr = + cpu_to_le32(priv(dev)->ao_buffer_bus_addr[i]); + priv(dev)->ao_dma_desc[i].local_start_addr = + cpu_to_le32(priv(dev)->local0_iobase + + DAC_FIFO_REG); + priv(dev)->ao_dma_desc[i].transfer_size = + cpu_to_le32(0); + priv(dev)->ao_dma_desc[i].next = + cpu_to_le32((priv(dev)->ao_dma_desc_bus_addr + + ((i + 1) % (AO_DMA_RING_COUNT)) * + sizeof(priv(dev)-> + ao_dma_desc[0])) | + PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT); + } + } + return 0; +} + +static inline void warn_external_queue(struct comedi_device * dev) +{ + comedi_error(dev, + "AO command and AI external channel queue cannot be used simultaneously."); + comedi_error(dev, + "Use internal AI channel queue (channels must be consecutive and use same range/aref)"); +} + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. + */ +static int attach(struct comedi_device *dev, struct comedi_devconfig *it) +{ + struct pci_dev *pcidev; + int index; + uint32_t local_range, local_decode; + int retval; + + printk("comedi%d: cb_pcidas64\n", dev->minor); + +/* + * Allocate the private structure area. + */ + if (alloc_private(dev, sizeof(struct pcidas64_private)) < 0) + return -ENOMEM; + +/* + * Probe the device to determine what device in the series it is. + */ + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + // is it not a computer boards card? + if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) + continue; + // loop through cards supported by this driver + for (index = 0; index < num_boards(); index++) { + if (pcidas64_boards[index].device_id != pcidev->device) + continue; + // was a particular bus/slot requested? + if (it->options[0] || it->options[1]) { + // are we on the wrong bus/slot? + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != + it->options[1]) { + continue; + } + } + priv(dev)->hw_dev = pcidev; + dev->board_ptr = pcidas64_boards + index; + break; + } + if (dev->board_ptr) + break; + } + + if (dev->board_ptr == NULL) { + printk("No supported ComputerBoards/MeasurementComputing card found\n"); + return -EIO; + } + + printk("Found %s on bus %i, slot %i\n", board(dev)->name, + pcidev->bus->number, PCI_SLOT(pcidev->devfn)); + + if (comedi_pci_enable(pcidev, driver_cb_pcidas.driver_name)) { + printk(KERN_WARNING + " failed to enable PCI device and request regions\n"); + return -EIO; + } + pci_set_master(pcidev); + + //Initialize dev->board_name + dev->board_name = board(dev)->name; + + priv(dev)->plx9080_phys_iobase = + pci_resource_start(pcidev, PLX9080_BADDRINDEX); + priv(dev)->main_phys_iobase = + pci_resource_start(pcidev, MAIN_BADDRINDEX); + priv(dev)->dio_counter_phys_iobase = + pci_resource_start(pcidev, DIO_COUNTER_BADDRINDEX); + + // remap, won't work with 2.0 kernels but who cares + priv(dev)->plx9080_iobase = ioremap(priv(dev)->plx9080_phys_iobase, + pci_resource_len(pcidev, PLX9080_BADDRINDEX)); + priv(dev)->main_iobase = ioremap(priv(dev)->main_phys_iobase, + pci_resource_len(pcidev, MAIN_BADDRINDEX)); + priv(dev)->dio_counter_iobase = + ioremap(priv(dev)->dio_counter_phys_iobase, + pci_resource_len(pcidev, DIO_COUNTER_BADDRINDEX)); + + if (!priv(dev)->plx9080_iobase || !priv(dev)->main_iobase + || !priv(dev)->dio_counter_iobase) { + printk(" failed to remap io memory\n"); + return -ENOMEM; + } + + DEBUG_PRINT(" plx9080 remapped to 0x%p\n", priv(dev)->plx9080_iobase); + DEBUG_PRINT(" main remapped to 0x%p\n", priv(dev)->main_iobase); + DEBUG_PRINT(" diocounter remapped to 0x%p\n", + priv(dev)->dio_counter_iobase); + + // figure out what local addresses are + local_range = + readl(priv(dev)->plx9080_iobase + + PLX_LAS0RNG_REG) & LRNG_MEM_MASK; + local_decode = + readl(priv(dev)->plx9080_iobase + + PLX_LAS0MAP_REG) & local_range & LMAP_MEM_MASK; + priv(dev)->local0_iobase = + ((uint32_t) priv(dev)-> + main_phys_iobase & ~local_range) | local_decode; + local_range = + readl(priv(dev)->plx9080_iobase + + PLX_LAS1RNG_REG) & LRNG_MEM_MASK; + local_decode = + readl(priv(dev)->plx9080_iobase + + PLX_LAS1MAP_REG) & local_range & LMAP_MEM_MASK; + priv(dev)->local1_iobase = + ((uint32_t) priv(dev)-> + dio_counter_phys_iobase & ~local_range) | local_decode; + + DEBUG_PRINT(" local 0 io addr 0x%x\n", priv(dev)->local0_iobase); + DEBUG_PRINT(" local 1 io addr 0x%x\n", priv(dev)->local1_iobase); + + retval = alloc_and_init_dma_members(dev); + if (retval < 0) + return retval; + + priv(dev)->hw_revision = + hw_revision(dev, readw(priv(dev)->main_iobase + HW_STATUS_REG)); + printk(" stc hardware revision %i\n", priv(dev)->hw_revision); + init_plx9080(dev); + init_stc_registers(dev); + // get irq + if (comedi_request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, + "cb_pcidas64", dev)) { + printk(" unable to allocate irq %u\n", pcidev->irq); + return -EINVAL; + } + dev->irq = pcidev->irq; + printk(" irq %u\n", dev->irq); + + retval = setup_subdevices(dev); + if (retval < 0) { + return retval; + } + + return 0; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int detach(struct comedi_device * dev) +{ + unsigned int i; + + printk("comedi%d: cb_pcidas: remove\n", dev->minor); + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (priv(dev)) { + if (priv(dev)->hw_dev) { + if (priv(dev)->plx9080_iobase) { + disable_plx_interrupts(dev); + iounmap((void *)priv(dev)->plx9080_iobase); + } + if (priv(dev)->main_iobase) + iounmap((void *)priv(dev)->main_iobase); + if (priv(dev)->dio_counter_iobase) + iounmap((void *)priv(dev)->dio_counter_iobase); + // free pci dma buffers + for (i = 0; i < ai_dma_ring_count(board(dev)); i++) { + if (priv(dev)->ai_buffer[i]) + pci_free_consistent(priv(dev)->hw_dev, + DMA_BUFFER_SIZE, + priv(dev)->ai_buffer[i], + priv(dev)-> + ai_buffer_bus_addr[i]); + } + for (i = 0; i < AO_DMA_RING_COUNT; i++) { + if (priv(dev)->ao_buffer[i]) + pci_free_consistent(priv(dev)->hw_dev, + DMA_BUFFER_SIZE, + priv(dev)->ao_buffer[i], + priv(dev)-> + ao_buffer_bus_addr[i]); + } + // free dma descriptors + if (priv(dev)->ai_dma_desc) + pci_free_consistent(priv(dev)->hw_dev, + sizeof(struct plx_dma_desc) * + ai_dma_ring_count(board(dev)), + priv(dev)->ai_dma_desc, + priv(dev)->ai_dma_desc_bus_addr); + if (priv(dev)->ao_dma_desc) + pci_free_consistent(priv(dev)->hw_dev, + sizeof(struct plx_dma_desc) * + AO_DMA_RING_COUNT, + priv(dev)->ao_dma_desc, + priv(dev)->ao_dma_desc_bus_addr); + if (priv(dev)->main_phys_iobase) { + comedi_pci_disable(priv(dev)->hw_dev); + } + pci_dev_put(priv(dev)->hw_dev); + } + } + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 4); + + return 0; +} + +static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int bits = 0, n, i; + unsigned int channel, range, aref; + unsigned long flags; + static const int timeout = 100; + + DEBUG_PRINT("chanspec 0x%x\n", insn->chanspec); + channel = CR_CHAN(insn->chanspec); + range = CR_RANGE(insn->chanspec); + aref = CR_AREF(insn->chanspec); + + // disable card's analog input interrupt sources and pacing + // 4020 generates dac done interrupts even though they are disabled + disable_ai_pacing(dev); + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + if (insn->chanspec & CR_ALT_FILTER) + priv(dev)->adc_control1_bits |= ADC_DITHER_BIT; + else + priv(dev)->adc_control1_bits &= ~ADC_DITHER_BIT; + writew(priv(dev)->adc_control1_bits, + priv(dev)->main_iobase + ADC_CONTROL1_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + if (board(dev)->layout != LAYOUT_4020) { + // use internal queue + priv(dev)->hw_config_bits &= ~EXT_QUEUE_BIT; + writew(priv(dev)->hw_config_bits, + priv(dev)->main_iobase + HW_CONFIG_REG); + + // ALT_SOURCE is internal calibration reference + if (insn->chanspec & CR_ALT_SOURCE) { + unsigned int cal_en_bit; + + DEBUG_PRINT("reading calibration source\n"); + if (board(dev)->layout == LAYOUT_60XX) + cal_en_bit = CAL_EN_60XX_BIT; + else + cal_en_bit = CAL_EN_64XX_BIT; + // select internal reference source to connect to channel 0 + writew(cal_en_bit | adc_src_bits(priv(dev)-> + calibration_source), + priv(dev)->main_iobase + CALIBRATION_REG); + } else { + // make sure internal calibration source is turned off + writew(0, priv(dev)->main_iobase + CALIBRATION_REG); + } + // load internal queue + bits = 0; + // set gain + bits |= ai_range_bits_6xxx(dev, CR_RANGE(insn->chanspec)); + // set single-ended / differential + bits |= se_diff_bit_6xxx(dev, aref == AREF_DIFF); + if (aref == AREF_COMMON) + bits |= ADC_COMMON_BIT; + bits |= adc_chan_bits(channel); + // set stop channel + writew(adc_chan_bits(channel), + priv(dev)->main_iobase + ADC_QUEUE_HIGH_REG); + // set start channel, and rest of settings + writew(bits, priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG); + } else { + uint8_t old_cal_range_bits = priv(dev)->i2c_cal_range_bits; + + priv(dev)->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK; + if (insn->chanspec & CR_ALT_SOURCE) { + DEBUG_PRINT("reading calibration source\n"); + priv(dev)->i2c_cal_range_bits |= + adc_src_4020_bits(priv(dev)-> + calibration_source); + } else { //select BNC inputs + priv(dev)->i2c_cal_range_bits |= adc_src_4020_bits(4); + } + // select range + if (range == 0) + priv(dev)->i2c_cal_range_bits |= attenuate_bit(channel); + else + priv(dev)->i2c_cal_range_bits &= + ~attenuate_bit(channel); + // update calibration/range i2c register only if necessary, as it is very slow + if (old_cal_range_bits != priv(dev)->i2c_cal_range_bits) { + uint8_t i2c_data = priv(dev)->i2c_cal_range_bits; + i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data, + sizeof(i2c_data)); + } + + /* 4020 manual asks that sample interval register to be set before writing to convert register. + * Using somewhat arbitrary setting of 4 master clock ticks = 0.1 usec */ + writew(0, + priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); + writew(2, + priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); + } + + for (n = 0; n < insn->n; n++) { + + // clear adc buffer (inside loop for 4020 sake) + writew(0, priv(dev)->main_iobase + ADC_BUFFER_CLEAR_REG); + + /* trigger conversion, bits sent only matter for 4020 */ + writew(adc_convert_chan_4020_bits(CR_CHAN(insn->chanspec)), + priv(dev)->main_iobase + ADC_CONVERT_REG); + + // wait for data + for (i = 0; i < timeout; i++) { + bits = readw(priv(dev)->main_iobase + HW_STATUS_REG); + DEBUG_PRINT(" pipe bits 0x%x\n", pipe_full_bits(bits)); + if (board(dev)->layout == LAYOUT_4020) { + if (readw(priv(dev)->main_iobase + + ADC_WRITE_PNTR_REG)) + break; + } else { + if (pipe_full_bits(bits)) + break; + } + comedi_udelay(1); + } + DEBUG_PRINT(" looped %i times waiting for data\n", i); + if (i == timeout) { + comedi_error(dev, " analog input read insn timed out"); + rt_printk(" status 0x%x\n", bits); + return -ETIME; + } + if (board(dev)->layout == LAYOUT_4020) + data[n] = + readl(priv(dev)->dio_counter_iobase + + ADC_FIFO_REG) & 0xffff; + else + data[n] = + readw(priv(dev)->main_iobase + PIPE1_READ_REG); + } + + return n; +} + +static int ai_config_calibration_source(struct comedi_device * dev, unsigned int * data) +{ + unsigned int source = data[1]; + int num_calibration_sources; + + if (board(dev)->layout == LAYOUT_60XX) + num_calibration_sources = 16; + else + num_calibration_sources = 8; + if (source >= num_calibration_sources) { + printk("invalid calibration source: %i\n", source); + return -EINVAL; + } + + DEBUG_PRINT("setting calibration source to %i\n", source); + priv(dev)->calibration_source = source; + + return 2; +} + +static int ai_config_block_size(struct comedi_device * dev, unsigned int * data) +{ + int fifo_size; + const struct hw_fifo_info *const fifo = board(dev)->ai_fifo; + unsigned int block_size, requested_block_size; + int retval; + + requested_block_size = data[1]; + + if (requested_block_size) { + fifo_size = + requested_block_size * fifo->num_segments / + bytes_in_sample; + + retval = set_ai_fifo_size(dev, fifo_size); + if (retval < 0) + return retval; + + } + + block_size = ai_fifo_size(dev) / fifo->num_segments * bytes_in_sample; + + data[1] = block_size; + + return 2; +} + +static int ai_config_master_clock_4020(struct comedi_device * dev, unsigned int * data) +{ + unsigned int divisor = data[4]; + int retval = 0; + + if (divisor < 2) { + divisor = 2; + retval = -EAGAIN; + } + + switch (data[1]) { + case COMEDI_EV_SCAN_BEGIN: + priv(dev)->ext_clock.divisor = divisor; + priv(dev)->ext_clock.chanspec = data[2]; + break; + default: + return -EINVAL; + break; + } + + data[4] = divisor; + + return retval ? retval : 5; +} + +// XXX could add support for 60xx series +static int ai_config_master_clock(struct comedi_device * dev, unsigned int * data) +{ + + switch (board(dev)->layout) { + case LAYOUT_4020: + return ai_config_master_clock_4020(dev, data); + break; + default: + return -EINVAL; + break; + } + + return -EINVAL; +} + +static int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int id = data[0]; + + switch (id) { + case INSN_CONFIG_ALT_SOURCE: + return ai_config_calibration_source(dev, data); + break; + case INSN_CONFIG_BLOCK_SIZE: + return ai_config_block_size(dev, data); + break; + case INSN_CONFIG_TIMER_1: + return ai_config_master_clock(dev, data); + break; + default: + return -EINVAL; + break; + } + return -EINVAL; +} + +static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + unsigned int tmp_arg, tmp_arg2; + int i; + int aref; + unsigned int triggers; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + triggers = TRIG_TIMER; + if (board(dev)->layout == LAYOUT_4020) + triggers |= TRIG_OTHER; + else + triggers |= TRIG_FOLLOW; + cmd->scan_begin_src &= triggers; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + triggers = TRIG_TIMER; + if (board(dev)->layout == LAYOUT_4020) + triggers |= TRIG_NOW; + else + triggers |= TRIG_EXT; + cmd->convert_src &= triggers; + 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_COUNT | TRIG_EXT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + // uniqueness check + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_OTHER && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) + err++; + + // compatibility check + if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER) + err++; + if (cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->convert_src == TRIG_TIMER) { + if (board(dev)->layout == LAYOUT_4020) { + if (cmd->convert_arg) { + cmd->convert_arg = 0; + err++; + } + } else { + if (cmd->convert_arg < board(dev)->ai_speed) { + cmd->convert_arg = board(dev)->ai_speed; + err++; + } + if (cmd->scan_begin_src == TRIG_TIMER) { + // if scans are timed faster than conversion rate allows + if (cmd->convert_arg * cmd->chanlist_len > + cmd->scan_begin_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * + cmd->chanlist_len; + err++; + } + } + } + } + + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + switch (cmd->stop_src) { + case TRIG_EXT: + break; + case TRIG_COUNT: + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + break; + case TRIG_NONE: + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + break; + default: + break; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->convert_src == TRIG_TIMER) { + tmp_arg = cmd->convert_arg; + tmp_arg2 = cmd->scan_begin_arg; + check_adc_timing(dev, cmd); + if (tmp_arg != cmd->convert_arg) + err++; + if (tmp_arg2 != cmd->scan_begin_arg) + err++; + } + + if (err) + return 4; + + // make sure user is doesn't change analog reference mid chanlist + if (cmd->chanlist) { + aref = CR_AREF(cmd->chanlist[0]); + for (i = 1; i < cmd->chanlist_len; i++) { + if (aref != CR_AREF(cmd->chanlist[i])) { + comedi_error(dev, + "all elements in chanlist must use the same analog reference"); + err++; + break; + } + } + // check 4020 chanlist + if (board(dev)->layout == LAYOUT_4020) { + unsigned int first_channel = CR_CHAN(cmd->chanlist[0]); + for (i = 1; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != + first_channel + i) { + comedi_error(dev, + "chanlist must use consecutive channels"); + err++; + break; + } + } + if (cmd->chanlist_len == 3) { + comedi_error(dev, + "chanlist cannot be 3 channels long, use 1, 2, or 4 channels"); + err++; + } + } + } + + if (err) + return 5; + + return 0; +} + +static int use_hw_sample_counter(struct comedi_cmd * cmd) +{ +// disable for now until I work out a race + return 0; + + if (cmd->stop_src == TRIG_COUNT && cmd->stop_arg <= max_counter_value) + return 1; + else + return 0; +} + +static void setup_sample_counters(struct comedi_device * dev, struct comedi_cmd * cmd) +{ + if (cmd->stop_src == TRIG_COUNT) { + // set software count + priv(dev)->ai_count = cmd->stop_arg * cmd->chanlist_len; + } + // load hardware conversion counter + if (use_hw_sample_counter(cmd)) { + writew(cmd->stop_arg & 0xffff, + priv(dev)->main_iobase + ADC_COUNT_LOWER_REG); + writew((cmd->stop_arg >> 16) & 0xff, + priv(dev)->main_iobase + ADC_COUNT_UPPER_REG); + } else { + writew(1, priv(dev)->main_iobase + ADC_COUNT_LOWER_REG); + } +} + +static inline unsigned int dma_transfer_size(struct comedi_device * dev) +{ + unsigned int num_samples; + + num_samples = + priv(dev)->ai_fifo_segment_length * + board(dev)->ai_fifo->sample_packing_ratio; + if (num_samples > DMA_BUFFER_SIZE / sizeof(uint16_t)) + num_samples = DMA_BUFFER_SIZE / sizeof(uint16_t); + + return num_samples; +} + +static void disable_ai_pacing(struct comedi_device * dev) +{ + unsigned long flags; + + disable_ai_interrupts(dev); + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + priv(dev)->adc_control1_bits &= ~ADC_SW_GATE_BIT; + writew(priv(dev)->adc_control1_bits, + priv(dev)->main_iobase + ADC_CONTROL1_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + /* disable pacing, triggering, etc */ + writew(ADC_DMA_DISABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT, + priv(dev)->main_iobase + ADC_CONTROL0_REG); +} + +static void disable_ai_interrupts(struct comedi_device * dev) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + priv(dev)->intr_enable_bits &= + ~EN_ADC_INTR_SRC_BIT & ~EN_ADC_DONE_INTR_BIT & + ~EN_ADC_ACTIVE_INTR_BIT & ~EN_ADC_STOP_INTR_BIT & + ~EN_ADC_OVERRUN_BIT & ~ADC_INTR_SRC_MASK; + writew(priv(dev)->intr_enable_bits, + priv(dev)->main_iobase + INTR_ENABLE_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + DEBUG_PRINT("intr enable bits 0x%x\n", priv(dev)->intr_enable_bits); +} + +static void enable_ai_interrupts(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + uint32_t bits; + unsigned long flags; + + bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT | + EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT; + // Use pio transfer and interrupt on end of conversion if TRIG_WAKE_EOS flag is set. + if (cmd->flags & TRIG_WAKE_EOS) { + // 4020 doesn't support pio transfers except for fifo dregs + if (board(dev)->layout != LAYOUT_4020) + bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT; + } + comedi_spin_lock_irqsave(&dev->spinlock, flags); + priv(dev)->intr_enable_bits |= bits; + writew(priv(dev)->intr_enable_bits, + priv(dev)->main_iobase + INTR_ENABLE_REG); + DEBUG_PRINT("intr enable bits 0x%x\n", priv(dev)->intr_enable_bits); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); +} + +static uint32_t ai_convert_counter_6xxx(const struct comedi_device * dev, + const struct comedi_cmd * cmd) +{ + // supposed to load counter with desired divisor minus 3 + return cmd->convert_arg / TIMER_BASE - 3; +} + +static uint32_t ai_scan_counter_6xxx(struct comedi_device * dev, struct comedi_cmd * cmd) +{ + uint32_t count; + // figure out how long we need to delay at end of scan + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + count = (cmd->scan_begin_arg - + (cmd->convert_arg * (cmd->chanlist_len - 1))) + / TIMER_BASE; + break; + case TRIG_FOLLOW: + count = cmd->convert_arg / TIMER_BASE; + break; + default: + return 0; + break; + } + return count - 3; +} + +static uint32_t ai_convert_counter_4020(struct comedi_device * dev, struct comedi_cmd * cmd) +{ + unsigned int divisor; + + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + divisor = cmd->scan_begin_arg / TIMER_BASE; + break; + case TRIG_OTHER: + divisor = priv(dev)->ext_clock.divisor; + break; + default: // should never happen + comedi_error(dev, "bug! failed to set ai pacing!"); + divisor = 1000; + break; + } + + // supposed to load counter with desired divisor minus 2 for 4020 + return divisor - 2; +} + +static void select_master_clock_4020(struct comedi_device * dev, + const struct comedi_cmd * cmd) +{ + // select internal/external master clock + priv(dev)->hw_config_bits &= ~MASTER_CLOCK_4020_MASK; + if (cmd->scan_begin_src == TRIG_OTHER) { + int chanspec = priv(dev)->ext_clock.chanspec; + + if (CR_CHAN(chanspec)) + priv(dev)->hw_config_bits |= BNC_CLOCK_4020_BITS; + else + priv(dev)->hw_config_bits |= EXT_CLOCK_4020_BITS; + } else { + priv(dev)->hw_config_bits |= INTERNAL_CLOCK_4020_BITS; + } + writew(priv(dev)->hw_config_bits, + priv(dev)->main_iobase + HW_CONFIG_REG); +} + +static void select_master_clock(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + switch (board(dev)->layout) { + case LAYOUT_4020: + select_master_clock_4020(dev, cmd); + break; + default: + break; + } +} + +static inline void dma_start_sync(struct comedi_device * dev, unsigned int channel) +{ + unsigned long flags; + + // spinlock for plx dma control/status reg + comedi_spin_lock_irqsave(&dev->spinlock, flags); + if (channel) + writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT | + PLX_CLEAR_DMA_INTR_BIT, + priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG); + else + writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT | + PLX_CLEAR_DMA_INTR_BIT, + priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); +} + +static void set_ai_pacing(struct comedi_device * dev, struct comedi_cmd * cmd) +{ + uint32_t convert_counter = 0, scan_counter = 0; + + check_adc_timing(dev, cmd); + + select_master_clock(dev, cmd); + + if (board(dev)->layout == LAYOUT_4020) { + convert_counter = ai_convert_counter_4020(dev, cmd); + } else { + convert_counter = ai_convert_counter_6xxx(dev, cmd); + scan_counter = ai_scan_counter_6xxx(dev, cmd); + } + + // load lower 16 bits of convert interval + writew(convert_counter & 0xffff, + priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); + DEBUG_PRINT("convert counter 0x%x\n", convert_counter); + // load upper 8 bits of convert interval + writew((convert_counter >> 16) & 0xff, + priv(dev)->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); + // load lower 16 bits of scan delay + writew(scan_counter & 0xffff, + priv(dev)->main_iobase + ADC_DELAY_INTERVAL_LOWER_REG); + // load upper 8 bits of scan delay + writew((scan_counter >> 16) & 0xff, + priv(dev)->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG); + DEBUG_PRINT("scan counter 0x%x\n", scan_counter); +} + +static int use_internal_queue_6xxx(const struct comedi_cmd * cmd) +{ + int i; + for (i = 0; i + 1 < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i + 1]) != + CR_CHAN(cmd->chanlist[i]) + 1) + return 0; + if (CR_RANGE(cmd->chanlist[i + 1]) != + CR_RANGE(cmd->chanlist[i])) + return 0; + if (CR_AREF(cmd->chanlist[i + 1]) != CR_AREF(cmd->chanlist[i])) + return 0; + } + return 1; +} + +static int setup_channel_queue(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + unsigned short bits; + int i; + + if (board(dev)->layout != LAYOUT_4020) { + if (use_internal_queue_6xxx(cmd)) { + priv(dev)->hw_config_bits &= ~EXT_QUEUE_BIT; + writew(priv(dev)->hw_config_bits, + priv(dev)->main_iobase + HW_CONFIG_REG); + bits = 0; + // set channel + bits |= adc_chan_bits(CR_CHAN(cmd->chanlist[0])); + // set gain + bits |= ai_range_bits_6xxx(dev, + CR_RANGE(cmd->chanlist[0])); + // set single-ended / differential + bits |= se_diff_bit_6xxx(dev, + CR_AREF(cmd->chanlist[0]) == AREF_DIFF); + if (CR_AREF(cmd->chanlist[0]) == AREF_COMMON) + bits |= ADC_COMMON_BIT; + // set stop channel + writew(adc_chan_bits(CR_CHAN(cmd->chanlist[cmd-> + chanlist_len - 1])), + priv(dev)->main_iobase + ADC_QUEUE_HIGH_REG); + // set start channel, and rest of settings + writew(bits, + priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG); + } else { + // use external queue + if (dev->write_subdev && dev->write_subdev->busy) { + warn_external_queue(dev); + return -EBUSY; + } + priv(dev)->hw_config_bits |= EXT_QUEUE_BIT; + writew(priv(dev)->hw_config_bits, + priv(dev)->main_iobase + HW_CONFIG_REG); + // clear DAC buffer to prevent weird interactions + writew(0, + priv(dev)->main_iobase + DAC_BUFFER_CLEAR_REG); + // clear queue pointer + writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG); + // load external queue + for (i = 0; i < cmd->chanlist_len; i++) { + bits = 0; + // set channel + bits |= adc_chan_bits(CR_CHAN(cmd-> + chanlist[i])); + // set gain + bits |= ai_range_bits_6xxx(dev, + CR_RANGE(cmd->chanlist[i])); + // set single-ended / differential + bits |= se_diff_bit_6xxx(dev, + CR_AREF(cmd->chanlist[i]) == AREF_DIFF); + if (CR_AREF(cmd->chanlist[i]) == AREF_COMMON) + bits |= ADC_COMMON_BIT; + // mark end of queue + if (i == cmd->chanlist_len - 1) + bits |= QUEUE_EOSCAN_BIT | + QUEUE_EOSEQ_BIT; + writew(bits, + priv(dev)->main_iobase + + ADC_QUEUE_FIFO_REG); + DEBUG_PRINT + ("wrote 0x%x to external channel queue\n", + bits); + } + /* doing a queue clear is not specified in board docs, + * but required for reliable operation */ + writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG); + // prime queue holding register + writew(0, priv(dev)->main_iobase + ADC_QUEUE_LOAD_REG); + } + } else { + unsigned short old_cal_range_bits = + priv(dev)->i2c_cal_range_bits; + + priv(dev)->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK; + //select BNC inputs + priv(dev)->i2c_cal_range_bits |= adc_src_4020_bits(4); + // select ranges + for (i = 0; i < cmd->chanlist_len; i++) { + unsigned int channel = CR_CHAN(cmd->chanlist[i]); + unsigned int range = CR_RANGE(cmd->chanlist[i]); + + if (range == 0) + priv(dev)->i2c_cal_range_bits |= + attenuate_bit(channel); + else + priv(dev)->i2c_cal_range_bits &= + ~attenuate_bit(channel); + } + // update calibration/range i2c register only if necessary, as it is very slow + if (old_cal_range_bits != priv(dev)->i2c_cal_range_bits) { + uint8_t i2c_data = priv(dev)->i2c_cal_range_bits; + i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data, + sizeof(i2c_data)); + } + } + return 0; +} + +static inline void load_first_dma_descriptor(struct comedi_device * dev, + unsigned int dma_channel, unsigned int descriptor_bits) +{ + /* The transfer size, pci address, and local address registers + * are supposedly unused during chained dma, + * but I have found that left over values from last operation + * occasionally cause problems with transfer of first dma + * block. Initializing them to zero seems to fix the problem. */ + if (dma_channel) { + writel(0, + priv(dev)->plx9080_iobase + PLX_DMA1_TRANSFER_SIZE_REG); + writel(0, priv(dev)->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG); + writel(0, + priv(dev)->plx9080_iobase + PLX_DMA1_LOCAL_ADDRESS_REG); + writel(descriptor_bits, + priv(dev)->plx9080_iobase + PLX_DMA1_DESCRIPTOR_REG); + } else { + writel(0, + priv(dev)->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG); + writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG); + writel(0, + priv(dev)->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG); + writel(descriptor_bits, + priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG); + } +} + +static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + uint32_t bits; + unsigned int i; + unsigned long flags; + int retval; + + disable_ai_pacing(dev); + abort_dma(dev, 1); + + retval = setup_channel_queue(dev, cmd); + if (retval < 0) + return retval; + + // make sure internal calibration source is turned off + writew(0, priv(dev)->main_iobase + CALIBRATION_REG); + + set_ai_pacing(dev, cmd); + + setup_sample_counters(dev, cmd); + + enable_ai_interrupts(dev, cmd); + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + /* set mode, allow conversions through software gate */ + priv(dev)->adc_control1_bits |= ADC_SW_GATE_BIT; + priv(dev)->adc_control1_bits &= ~ADC_DITHER_BIT; + if (board(dev)->layout != LAYOUT_4020) { + priv(dev)->adc_control1_bits &= ~ADC_MODE_MASK; + if (cmd->convert_src == TRIG_EXT) + priv(dev)->adc_control1_bits |= adc_mode_bits(13); // good old mode 13 + else + priv(dev)->adc_control1_bits |= adc_mode_bits(8); // mode 8. What else could you need? + } else { + priv(dev)->adc_control1_bits &= ~CHANNEL_MODE_4020_MASK; + if (cmd->chanlist_len == 4) + priv(dev)->adc_control1_bits |= FOUR_CHANNEL_4020_BITS; + else if (cmd->chanlist_len == 2) + priv(dev)->adc_control1_bits |= TWO_CHANNEL_4020_BITS; + priv(dev)->adc_control1_bits &= ~ADC_LO_CHANNEL_4020_MASK; + priv(dev)->adc_control1_bits |= + adc_lo_chan_4020_bits(CR_CHAN(cmd->chanlist[0])); + priv(dev)->adc_control1_bits &= ~ADC_HI_CHANNEL_4020_MASK; + priv(dev)->adc_control1_bits |= + adc_hi_chan_4020_bits(CR_CHAN(cmd->chanlist[cmd-> + chanlist_len - 1])); + } + writew(priv(dev)->adc_control1_bits, + priv(dev)->main_iobase + ADC_CONTROL1_REG); + DEBUG_PRINT("control1 bits 0x%x\n", priv(dev)->adc_control1_bits); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // clear adc buffer + writew(0, priv(dev)->main_iobase + ADC_BUFFER_CLEAR_REG); + + if ((cmd->flags & TRIG_WAKE_EOS) == 0 || + board(dev)->layout == LAYOUT_4020) { + priv(dev)->ai_dma_index = 0; + + // set dma transfer size + for (i = 0; i < ai_dma_ring_count(board(dev)); i++) + priv(dev)->ai_dma_desc[i].transfer_size = + cpu_to_le32(dma_transfer_size(dev) * + sizeof(uint16_t)); + + // give location of first dma descriptor + load_first_dma_descriptor(dev, 1, + priv(dev)-> + ai_dma_desc_bus_addr | PLX_DESC_IN_PCI_BIT | + PLX_INTR_TERM_COUNT | PLX_XFER_LOCAL_TO_PCI); + + dma_start_sync(dev, 1); + } + + if (board(dev)->layout == LAYOUT_4020) { + /* set source for external triggers */ + bits = 0; + if (cmd->start_src == TRIG_EXT && CR_CHAN(cmd->start_arg)) + bits |= EXT_START_TRIG_BNC_BIT; + if (cmd->stop_src == TRIG_EXT && CR_CHAN(cmd->stop_arg)) + bits |= EXT_STOP_TRIG_BNC_BIT; + writew(bits, priv(dev)->main_iobase + DAQ_ATRIG_LOW_4020_REG); + } + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + + /* enable pacing, triggering, etc */ + bits = ADC_ENABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT; + if (cmd->flags & TRIG_WAKE_EOS) + bits |= ADC_DMA_DISABLE_BIT; + // set start trigger + if (cmd->start_src == TRIG_EXT) { + bits |= ADC_START_TRIG_EXT_BITS; + if (cmd->start_arg & CR_INVERT) + bits |= ADC_START_TRIG_FALLING_BIT; + } else if (cmd->start_src == TRIG_NOW) + bits |= ADC_START_TRIG_SOFT_BITS; + if (use_hw_sample_counter(cmd)) + bits |= ADC_SAMPLE_COUNTER_EN_BIT; + writew(bits, priv(dev)->main_iobase + ADC_CONTROL0_REG); + DEBUG_PRINT("control0 bits 0x%x\n", bits); + + priv(dev)->ai_cmd_running = 1; + + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // start aquisition + if (cmd->start_src == TRIG_NOW) { + writew(0, priv(dev)->main_iobase + ADC_START_REG); + DEBUG_PRINT("soft trig\n"); + } + + return 0; +} + +// read num_samples from 16 bit wide ai fifo +static void pio_drain_ai_fifo_16(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int i; + uint16_t prepost_bits; + int read_segment, read_index, write_segment, write_index; + int num_samples; + + do { + // get least significant 15 bits + read_index = + readw(priv(dev)->main_iobase + + ADC_READ_PNTR_REG) & 0x7fff; + write_index = + readw(priv(dev)->main_iobase + + ADC_WRITE_PNTR_REG) & 0x7fff; + /* Get most significant bits (grey code). Different boards use different code + * so use a scheme that doesn't depend on encoding. This read must + * occur after reading least significant 15 bits to avoid race + * with fifo switching to next segment. */ + prepost_bits = readw(priv(dev)->main_iobase + PREPOST_REG); + + /* if read and write pointers are not on the same fifo segment, read to the + * end of the read segment */ + read_segment = adc_upper_read_ptr_code(prepost_bits); + write_segment = adc_upper_write_ptr_code(prepost_bits); + + DEBUG_PRINT(" rd seg %i, wrt seg %i, rd idx %i, wrt idx %i\n", + read_segment, write_segment, read_index, write_index); + + if (read_segment != write_segment) + num_samples = + priv(dev)->ai_fifo_segment_length - read_index; + else + num_samples = write_index - read_index; + + if (cmd->stop_src == TRIG_COUNT) { + if (priv(dev)->ai_count == 0) + break; + if (num_samples > priv(dev)->ai_count) { + num_samples = priv(dev)->ai_count; + } + priv(dev)->ai_count -= num_samples; + } + + if (num_samples < 0) { + rt_printk(" cb_pcidas64: bug! num_samples < 0\n"); + break; + } + + DEBUG_PRINT(" read %i samples from fifo\n", num_samples); + + for (i = 0; i < num_samples; i++) { + cfc_write_to_buffer(s, + readw(priv(dev)->main_iobase + ADC_FIFO_REG)); + } + + } while (read_segment != write_segment); +} + +/* Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of pointers. + * The pci-4020 hardware only supports + * dma transfers (it only supports the use of pio for draining the last remaining + * points from the fifo when a data aquisition operation has completed). + */ +static void pio_drain_ai_fifo_32(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int i; + unsigned int max_transfer = 100000; + uint32_t fifo_data; + int write_code = + readw(priv(dev)->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff; + int read_code = + readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff; + + if (cmd->stop_src == TRIG_COUNT) { + if (max_transfer > priv(dev)->ai_count) { + max_transfer = priv(dev)->ai_count; + } + } + for (i = 0; read_code != write_code && i < max_transfer;) { + fifo_data = readl(priv(dev)->dio_counter_iobase + ADC_FIFO_REG); + cfc_write_to_buffer(s, fifo_data & 0xffff); + i++; + if (i < max_transfer) { + cfc_write_to_buffer(s, (fifo_data >> 16) & 0xffff); + i++; + } + read_code = + readw(priv(dev)->main_iobase + + ADC_READ_PNTR_REG) & 0x7fff; + } + priv(dev)->ai_count -= i; +} + +// empty fifo +static void pio_drain_ai_fifo(struct comedi_device * dev) +{ + if (board(dev)->layout == LAYOUT_4020) { + pio_drain_ai_fifo_32(dev); + } else + pio_drain_ai_fifo_16(dev); +} + +static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel) +{ + struct comedi_async *async = dev->read_subdev->async; + uint32_t next_transfer_addr; + int j; + int num_samples = 0; + void *pci_addr_reg; + + if (channel) + pci_addr_reg = + priv(dev)->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG; + else + pci_addr_reg = + priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG; + + // loop until we have read all the full buffers + for (j = 0, next_transfer_addr = readl(pci_addr_reg); + (next_transfer_addr < + priv(dev)->ai_buffer_bus_addr[priv(dev)->ai_dma_index] + || next_transfer_addr >= + priv(dev)->ai_buffer_bus_addr[priv(dev)->ai_dma_index] + + DMA_BUFFER_SIZE) && j < ai_dma_ring_count(board(dev)); + j++) { + // transfer data from dma buffer to comedi buffer + num_samples = dma_transfer_size(dev); + if (async->cmd.stop_src == TRIG_COUNT) { + if (num_samples > priv(dev)->ai_count) + num_samples = priv(dev)->ai_count; + priv(dev)->ai_count -= num_samples; + } + cfc_write_array_to_buffer(dev->read_subdev, + priv(dev)->ai_buffer[priv(dev)->ai_dma_index], + num_samples * sizeof(uint16_t)); + priv(dev)->ai_dma_index = + (priv(dev)->ai_dma_index + + 1) % ai_dma_ring_count(board(dev)); + + DEBUG_PRINT("next buffer addr 0x%lx\n", + (unsigned long)priv(dev)->ai_buffer_bus_addr[priv(dev)-> + ai_dma_index]); + DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr); + } + /* XXX check for dma ring buffer overrun (use end-of-chain bit to mark last + * unused buffer) */ +} + +void handle_ai_interrupt(struct comedi_device * dev, unsigned short status, + unsigned int plx_status) +{ + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + uint8_t dma1_status; + unsigned long flags; + + // check for fifo overrun + if (status & ADC_OVERRUN_BIT) { + comedi_error(dev, "fifo overrun"); + async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + } + // spin lock makes sure noone else changes plx dma control reg + comedi_spin_lock_irqsave(&dev->spinlock, flags); + dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG); + if (plx_status & ICS_DMA1_A) { // dma chan 1 interrupt + writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, + priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG); + DEBUG_PRINT("dma1 status 0x%x\n", dma1_status); + + if (dma1_status & PLX_DMA_EN_BIT) { + drain_dma_buffers(dev, 1); + } + DEBUG_PRINT(" cleared dma ch1 interrupt\n"); + } + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + if (status & ADC_DONE_BIT) + DEBUG_PRINT("adc done interrupt\n"); + + // drain fifo with pio + if ((status & ADC_DONE_BIT) || + ((cmd->flags & TRIG_WAKE_EOS) && + (status & ADC_INTR_PENDING_BIT) && + (board(dev)->layout != LAYOUT_4020))) { + DEBUG_PRINT("pio fifo drain\n"); + comedi_spin_lock_irqsave(&dev->spinlock, flags); + if (priv(dev)->ai_cmd_running) { + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + pio_drain_ai_fifo(dev); + } else + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + } + // if we are have all the data, then quit + if ((cmd->stop_src == TRIG_COUNT && priv(dev)->ai_count <= 0) || + (cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT))) { + async->events |= COMEDI_CB_EOA; + } + + cfc_handle_events(dev, s); +} + +static inline unsigned int prev_ao_dma_index(struct comedi_device * dev) +{ + unsigned int buffer_index; + + if (priv(dev)->ao_dma_index == 0) + buffer_index = AO_DMA_RING_COUNT - 1; + else + buffer_index = priv(dev)->ao_dma_index - 1; + return buffer_index; +} + +static int last_ao_dma_load_completed(struct comedi_device * dev) +{ + unsigned int buffer_index; + unsigned int transfer_address; + unsigned short dma_status; + + buffer_index = prev_ao_dma_index(dev); + dma_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); + if ((dma_status & PLX_DMA_DONE_BIT) == 0) + return 0; + + transfer_address = + readl(priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG); + if (transfer_address != priv(dev)->ao_buffer_bus_addr[buffer_index]) + return 0; + + return 1; +} + +static int ao_stopped_by_error(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + if (cmd->stop_src == TRIG_NONE) + return 1; + if (cmd->stop_src == TRIG_COUNT) { + if (priv(dev)->ao_count) + return 1; + if (last_ao_dma_load_completed(dev) == 0) + return 1; + } + return 0; +} + +static inline int ao_dma_needs_restart(struct comedi_device * dev, + unsigned short dma_status) +{ + if ((dma_status & PLX_DMA_DONE_BIT) == 0 || + (dma_status & PLX_DMA_EN_BIT) == 0) + return 0; + if (last_ao_dma_load_completed(dev)) + return 0; + + return 1; +} + +static void restart_ao_dma(struct comedi_device * dev) +{ + unsigned int dma_desc_bits; + + dma_desc_bits = + readl(priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG); + dma_desc_bits &= ~PLX_END_OF_CHAIN_BIT; + DEBUG_PRINT("restarting ao dma, descriptor reg 0x%x\n", dma_desc_bits); + load_first_dma_descriptor(dev, 0, dma_desc_bits); + + dma_start_sync(dev, 0); +} + +static void handle_ao_interrupt(struct comedi_device * dev, unsigned short status, + unsigned int plx_status) +{ + struct comedi_subdevice *s = dev->write_subdev; + struct comedi_async *async; + struct comedi_cmd *cmd; + uint8_t dma0_status; + unsigned long flags; + + /* board might not support ao, in which case write_subdev is NULL */ + if (s == NULL) + return; + async = s->async; + cmd = &async->cmd; + + // spin lock makes sure noone else changes plx dma control reg + comedi_spin_lock_irqsave(&dev->spinlock, flags); + dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); + if (plx_status & ICS_DMA0_A) { // dma chan 0 interrupt + if ((dma0_status & PLX_DMA_EN_BIT) + && !(dma0_status & PLX_DMA_DONE_BIT)) + writeb(PLX_DMA_EN_BIT | PLX_CLEAR_DMA_INTR_BIT, + priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); + else + writeb(PLX_CLEAR_DMA_INTR_BIT, + priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + DEBUG_PRINT("dma0 status 0x%x\n", dma0_status); + if (dma0_status & PLX_DMA_EN_BIT) { + load_ao_dma(dev, cmd); + /* try to recover from dma end-of-chain event */ + if (ao_dma_needs_restart(dev, dma0_status)) + restart_ao_dma(dev); + } + DEBUG_PRINT(" cleared dma ch0 interrupt\n"); + } else + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + if ((status & DAC_DONE_BIT)) { + async->events |= COMEDI_CB_EOA; + if (ao_stopped_by_error(dev, cmd)) + async->events |= COMEDI_CB_ERROR; + DEBUG_PRINT("plx dma0 desc reg 0x%x\n", + readl(priv(dev)->plx9080_iobase + + PLX_DMA0_DESCRIPTOR_REG)); + DEBUG_PRINT("plx dma0 address reg 0x%x\n", + readl(priv(dev)->plx9080_iobase + + PLX_DMA0_PCI_ADDRESS_REG)); + } + cfc_handle_events(dev, s); +} + +static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + unsigned short status; + uint32_t plx_status; + uint32_t plx_bits; + + plx_status = readl(priv(dev)->plx9080_iobase + PLX_INTRCS_REG); + status = readw(priv(dev)->main_iobase + HW_STATUS_REG); + + DEBUG_PRINT("cb_pcidas64: hw status 0x%x ", status); + DEBUG_PRINT("plx status 0x%x\n", plx_status); + + /* an interrupt before all the postconfig stuff gets done could + * cause a NULL dereference if we continue through the + * interrupt handler */ + if (dev->attached == 0) { + DEBUG_PRINT("cb_pcidas64: premature interrupt, ignoring", + status); + return IRQ_HANDLED; + } + handle_ai_interrupt(dev, status, plx_status); + handle_ao_interrupt(dev, status, plx_status); + + // clear possible plx9080 interrupt sources + if (plx_status & ICS_LDIA) { // clear local doorbell interrupt + plx_bits = readl(priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG); + writel(plx_bits, priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG); + DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits); + } + + DEBUG_PRINT("exiting handler\n"); + + return IRQ_HANDLED; +} + +void abort_dma(struct comedi_device * dev, unsigned int channel) +{ + unsigned long flags; + + // spinlock for plx dma control/status reg + comedi_spin_lock_irqsave(&dev->spinlock, flags); + + plx9080_abort_dma(priv(dev)->plx9080_iobase, channel); + + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); +} + +static int ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + if (priv(dev)->ai_cmd_running == 0) { + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + return 0; + } + priv(dev)->ai_cmd_running = 0; + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + disable_ai_pacing(dev); + + abort_dma(dev, 1); + + DEBUG_PRINT("ai canceled\n"); + return 0; +} + +static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + int range = CR_RANGE(insn->chanspec); + + // do some initializing + writew(0, priv(dev)->main_iobase + DAC_CONTROL0_REG); + + // set range + set_dac_range_bits(dev, &priv(dev)->dac_control1_bits, chan, range); + writew(priv(dev)->dac_control1_bits, + priv(dev)->main_iobase + DAC_CONTROL1_REG); + + // write to channel + if (board(dev)->layout == LAYOUT_4020) { + writew(data[0] & 0xff, + priv(dev)->main_iobase + dac_lsb_4020_reg(chan)); + writew((data[0] >> 8) & 0xf, + priv(dev)->main_iobase + dac_msb_4020_reg(chan)); + } else { + writew(data[0], priv(dev)->main_iobase + dac_convert_reg(chan)); + } + + // remember output value + priv(dev)->ao_value[chan] = data[0]; + + return 1; +} + +static int ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = priv(dev)->ao_value[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static void set_dac_control0_reg(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + unsigned int bits = DAC_ENABLE_BIT | WAVEFORM_GATE_LEVEL_BIT | + WAVEFORM_GATE_ENABLE_BIT | WAVEFORM_GATE_SELECT_BIT; + + if (cmd->start_src == TRIG_EXT) { + bits |= WAVEFORM_TRIG_EXT_BITS; + if (cmd->start_arg & CR_INVERT) + bits |= WAVEFORM_TRIG_FALLING_BIT; + } else { + bits |= WAVEFORM_TRIG_SOFT_BITS; + } + if (cmd->scan_begin_src == TRIG_EXT) { + bits |= DAC_EXT_UPDATE_ENABLE_BIT; + if (cmd->scan_begin_arg & CR_INVERT) + bits |= DAC_EXT_UPDATE_FALLING_BIT; + } + writew(bits, priv(dev)->main_iobase + DAC_CONTROL0_REG); +} + +static void set_dac_control1_reg(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + int i; + + for (i = 0; i < cmd->chanlist_len; i++) { + int channel, range; + + channel = CR_CHAN(cmd->chanlist[i]); + range = CR_RANGE(cmd->chanlist[i]); + set_dac_range_bits(dev, &priv(dev)->dac_control1_bits, channel, + range); + } + priv(dev)->dac_control1_bits |= DAC_SW_GATE_BIT; + writew(priv(dev)->dac_control1_bits, + priv(dev)->main_iobase + DAC_CONTROL1_REG); +} + +static void set_dac_select_reg(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + uint16_t bits; + unsigned int first_channel, last_channel; + + first_channel = CR_CHAN(cmd->chanlist[0]); + last_channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); + if (last_channel < first_channel) + comedi_error(dev, "bug! last ao channel < first ao channel"); + + bits = (first_channel & 0x7) | (last_channel & 0x7) << 3; + + writew(bits, priv(dev)->main_iobase + DAC_SELECT_REG); +} + +static void set_dac_interval_regs(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + unsigned int divisor; + + if (cmd->scan_begin_src != TRIG_TIMER) + return; + + divisor = get_ao_divisor(cmd->scan_begin_arg, cmd->flags); + if (divisor > max_counter_value) { + comedi_error(dev, "bug! ao divisor too big"); + divisor = max_counter_value; + } + writew(divisor & 0xffff, + priv(dev)->main_iobase + DAC_SAMPLE_INTERVAL_LOWER_REG); + writew((divisor >> 16) & 0xff, + priv(dev)->main_iobase + DAC_SAMPLE_INTERVAL_UPPER_REG); +} + +static unsigned int load_ao_dma_buffer(struct comedi_device * dev, + const struct comedi_cmd * cmd) +{ + unsigned int num_bytes, buffer_index, prev_buffer_index; + unsigned int next_bits; + + buffer_index = priv(dev)->ao_dma_index; + prev_buffer_index = prev_ao_dma_index(dev); + + DEBUG_PRINT("attempting to load ao buffer %i (0x%x)\n", buffer_index, + priv(dev)->ao_buffer_bus_addr[buffer_index]); + + num_bytes = comedi_buf_read_n_available(dev->write_subdev->async); + if (num_bytes > DMA_BUFFER_SIZE) + num_bytes = DMA_BUFFER_SIZE; + if (cmd->stop_src == TRIG_COUNT && num_bytes > priv(dev)->ao_count) + num_bytes = priv(dev)->ao_count; + num_bytes -= num_bytes % bytes_in_sample; + + if (num_bytes == 0) + return 0; + + DEBUG_PRINT("loading %i bytes\n", num_bytes); + + num_bytes = cfc_read_array_from_buffer(dev->write_subdev, + priv(dev)->ao_buffer[buffer_index], num_bytes); + priv(dev)->ao_dma_desc[buffer_index].transfer_size = + cpu_to_le32(num_bytes); + /* set end of chain bit so we catch underruns */ + next_bits = le32_to_cpu(priv(dev)->ao_dma_desc[buffer_index].next); + next_bits |= PLX_END_OF_CHAIN_BIT; + priv(dev)->ao_dma_desc[buffer_index].next = cpu_to_le32(next_bits); + /* clear end of chain bit on previous buffer now that we have set it + * for the last buffer */ + next_bits = le32_to_cpu(priv(dev)->ao_dma_desc[prev_buffer_index].next); + next_bits &= ~PLX_END_OF_CHAIN_BIT; + priv(dev)->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits); + + priv(dev)->ao_dma_index = (buffer_index + 1) % AO_DMA_RING_COUNT; + priv(dev)->ao_count -= num_bytes; + + return num_bytes; +} + +static void load_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + unsigned int num_bytes; + unsigned int next_transfer_addr; + void *pci_addr_reg = + priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG; + unsigned int buffer_index; + + do { + buffer_index = priv(dev)->ao_dma_index; + /* don't overwrite data that hasn't been transferred yet */ + next_transfer_addr = readl(pci_addr_reg); + if (next_transfer_addr >= + priv(dev)->ao_buffer_bus_addr[buffer_index] + && next_transfer_addr < + priv(dev)->ao_buffer_bus_addr[buffer_index] + + DMA_BUFFER_SIZE) + return; + num_bytes = load_ao_dma_buffer(dev, cmd); + } while (num_bytes >= DMA_BUFFER_SIZE); +} + +static int prep_ao_dma(struct comedi_device * dev, const struct comedi_cmd * cmd) +{ + unsigned int num_bytes; + int i; + + /* clear queue pointer too, since external queue has + * weird interactions with ao fifo */ + writew(0, priv(dev)->main_iobase + ADC_QUEUE_CLEAR_REG); + writew(0, priv(dev)->main_iobase + DAC_BUFFER_CLEAR_REG); + + num_bytes = (DAC_FIFO_SIZE / 2) * bytes_in_sample; + if (cmd->stop_src == TRIG_COUNT && + num_bytes / bytes_in_sample > priv(dev)->ao_count) + num_bytes = priv(dev)->ao_count * bytes_in_sample; + num_bytes = cfc_read_array_from_buffer(dev->write_subdev, + priv(dev)->ao_bounce_buffer, num_bytes); + for (i = 0; i < num_bytes / bytes_in_sample; i++) { + writew(priv(dev)->ao_bounce_buffer[i], + priv(dev)->main_iobase + DAC_FIFO_REG); + } + priv(dev)->ao_count -= num_bytes / bytes_in_sample; + if (cmd->stop_src == TRIG_COUNT && priv(dev)->ao_count == 0) + return 0; + num_bytes = load_ao_dma_buffer(dev, cmd); + if (num_bytes == 0) + return -1; + if (num_bytes >= DMA_BUFFER_SIZE) ; + load_ao_dma(dev, cmd); + + dma_start_sync(dev, 0); + + return 0; +} + +static inline int external_ai_queue_in_use(struct comedi_device * dev) +{ + if (dev->read_subdev->busy) + return 0; + if (board(dev)->layout == LAYOUT_4020) + return 0; + else if (use_internal_queue_6xxx(&dev->read_subdev->async->cmd)) + return 0; + return 1; +} + +static int ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + + if (external_ai_queue_in_use(dev)) { + warn_external_queue(dev); + return -EBUSY; + } + /* disable analog output system during setup */ + writew(0x0, priv(dev)->main_iobase + DAC_CONTROL0_REG); + + priv(dev)->ao_dma_index = 0; + priv(dev)->ao_count = cmd->stop_arg * cmd->chanlist_len; + + set_dac_select_reg(dev, cmd); + set_dac_interval_regs(dev, cmd); + load_first_dma_descriptor(dev, 0, priv(dev)->ao_dma_desc_bus_addr | + PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT); + + set_dac_control1_reg(dev, cmd); + s->async->inttrig = ao_inttrig; + + return 0; +} + +static int ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trig_num) +{ + struct comedi_cmd *cmd = &s->async->cmd; + int retval; + + if (trig_num != 0) + return -EINVAL; + + retval = prep_ao_dma(dev, cmd); + if (retval < 0) + return -EPIPE; + + set_dac_control0_reg(dev, cmd); + + if (cmd->start_src == TRIG_INT) + writew(0, priv(dev)->main_iobase + DAC_START_REG); + + s->async->inttrig = NULL; + + return 0; +} + +static int ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + unsigned int tmp_arg; + int i; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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: make sure trigger sources are unique and mutually compatible */ + + // uniqueness check + if (cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + + // compatibility check + if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER) + err++; + if (cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < board(dev)->ao_scan_speed) { + cmd->scan_begin_arg = board(dev)->ao_scan_speed; + err++; + } + if (get_ao_divisor(cmd->scan_begin_arg, + cmd->flags) > max_counter_value) { + cmd->scan_begin_arg = + (max_counter_value + 2) * TIMER_BASE; + err++; + } + } + + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp_arg = cmd->scan_begin_arg; + cmd->scan_begin_arg = + get_divisor(cmd->scan_begin_arg, + cmd->flags) * TIMER_BASE; + if (tmp_arg != cmd->scan_begin_arg) + err++; + } + + if (err) + return 4; + + if (cmd->chanlist) { + unsigned int first_channel = CR_CHAN(cmd->chanlist[0]); + for (i = 1; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != first_channel + i) { + comedi_error(dev, + "chanlist must use consecutive channels"); + err++; + break; + } + } + } + + if (err) + return 5; + + return 0; +} + +static int ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + writew(0x0, priv(dev)->main_iobase + DAC_CONTROL0_REG); + abort_dma(dev, 0); + return 0; +} + +static int dio_callback(int dir, int port, int data, unsigned long iobase) +{ + if (dir) { + writeb(data, (void *)(iobase + port)); + DEBUG_PRINT("wrote 0x%x to port %i\n", data, port); + return 0; + } else { + return readb((void *)(iobase + port)); + } +} + +static int dio_callback_4020(int dir, int port, int data, unsigned long iobase) +{ + if (dir) { + writew(data, (void *)(iobase + 2 * port)); + return 0; + } else { + return readw((void *)(iobase + 2 * port)); + } +} + +static int di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int bits; + + bits = readb(priv(dev)->dio_counter_iobase + DI_REG); + bits &= 0xf; + data[1] = bits; + data[0] = 0; + + return 2; +} + +static int do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] &= 0xf; + // zero bits we are going to change + s->state &= ~data[0]; + // set new bits + s->state |= data[0] & data[1]; + + writeb(s->state, priv(dev)->dio_counter_iobase + DO_REG); + + data[1] = s->state; + + return 2; +} + +static int dio_60xx_config_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int mask; + + mask = 1 << CR_CHAN(insn->chanspec); + + switch (data[0]) { + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~mask; + break; + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= mask; + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; + return 2; + default: + return -EINVAL; + } + + writeb(s->io_bits, + priv(dev)->dio_counter_iobase + DIO_DIRECTION_60XX_REG); + + return 1; +} + +static int dio_60xx_wbits(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]); + writeb(s->state, + priv(dev)->dio_counter_iobase + DIO_DATA_60XX_REG); + } + + data[1] = readb(priv(dev)->dio_counter_iobase + DIO_DATA_60XX_REG); + + return 2; +} + +static void caldac_write(struct comedi_device * dev, unsigned int channel, + unsigned int value) +{ + priv(dev)->caldac_state[channel] = value; + + switch (board(dev)->layout) { + case LAYOUT_60XX: + case LAYOUT_64XX: + caldac_8800_write(dev, channel, value); + break; + case LAYOUT_4020: + caldac_i2c_write(dev, channel, value); + break; + default: + break; + } +} + +static int calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int channel = CR_CHAN(insn->chanspec); + + /* return immediately if setting hasn't changed, since + * programming these things is slow */ + if (priv(dev)->caldac_state[channel] == data[0]) + return 1; + + caldac_write(dev, channel, data[0]); + + return 1; +} + +static int calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int channel = CR_CHAN(insn->chanspec); + + data[0] = priv(dev)->caldac_state[channel]; + + return 1; +} + +static void ad8402_write(struct comedi_device * dev, unsigned int channel, + unsigned int value) +{ + static const int bitstream_length = 10; + unsigned int bit, register_bits; + unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff); + static const int ad8402_comedi_udelay = 1; + + priv(dev)->ad8402_state[channel] = value; + + register_bits = SELECT_8402_64XX_BIT; + comedi_udelay(ad8402_comedi_udelay); + writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG); + + for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { + if (bitstream & bit) + register_bits |= SERIAL_DATA_IN_BIT; + else + register_bits &= ~SERIAL_DATA_IN_BIT; + comedi_udelay(ad8402_comedi_udelay); + writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG); + comedi_udelay(ad8402_comedi_udelay); + writew(register_bits | SERIAL_CLOCK_BIT, + priv(dev)->main_iobase + CALIBRATION_REG); + } + + comedi_udelay(ad8402_comedi_udelay); + writew(0, priv(dev)->main_iobase + CALIBRATION_REG); +} + +/* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */ +static int ad8402_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int channel = CR_CHAN(insn->chanspec); + + /* return immediately if setting hasn't changed, since + * programming these things is slow */ + if (priv(dev)->ad8402_state[channel] == data[0]) + return 1; + + priv(dev)->ad8402_state[channel] = data[0]; + + ad8402_write(dev, channel, data[0]); + + return 1; +} + +static int ad8402_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int channel = CR_CHAN(insn->chanspec); + + data[0] = priv(dev)->ad8402_state[channel]; + + return 1; +} + +static uint16_t read_eeprom(struct comedi_device * dev, uint8_t address) +{ + static const int bitstream_length = 11; + static const int read_command = 0x6; + unsigned int bitstream = (read_command << 8) | address; + unsigned int bit; + void *const plx_control_addr = + priv(dev)->plx9080_iobase + PLX_CONTROL_REG; + uint16_t value; + static const int value_length = 16; + static const int eeprom_comedi_udelay = 1; + + comedi_udelay(eeprom_comedi_udelay); + priv(dev)->plx_control_bits &= ~CTL_EE_CLK & ~CTL_EE_CS; + // make sure we don't send anything to the i2c bus on 4020 + priv(dev)->plx_control_bits |= CTL_USERO; + writel(priv(dev)->plx_control_bits, plx_control_addr); + // activate serial eeprom + comedi_udelay(eeprom_comedi_udelay); + priv(dev)->plx_control_bits |= CTL_EE_CS; + writel(priv(dev)->plx_control_bits, plx_control_addr); + + // write read command and desired memory address + for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { + // set bit to be written + comedi_udelay(eeprom_comedi_udelay); + if (bitstream & bit) + priv(dev)->plx_control_bits |= CTL_EE_W; + else + priv(dev)->plx_control_bits &= ~CTL_EE_W; + writel(priv(dev)->plx_control_bits, plx_control_addr); + // clock in bit + comedi_udelay(eeprom_comedi_udelay); + priv(dev)->plx_control_bits |= CTL_EE_CLK; + writel(priv(dev)->plx_control_bits, plx_control_addr); + comedi_udelay(eeprom_comedi_udelay); + priv(dev)->plx_control_bits &= ~CTL_EE_CLK; + writel(priv(dev)->plx_control_bits, plx_control_addr); + } + // read back value from eeprom memory location + value = 0; + for (bit = 1 << (value_length - 1); bit; bit >>= 1) { + // clock out bit + comedi_udelay(eeprom_comedi_udelay); + priv(dev)->plx_control_bits |= CTL_EE_CLK; + writel(priv(dev)->plx_control_bits, plx_control_addr); + comedi_udelay(eeprom_comedi_udelay); + priv(dev)->plx_control_bits &= ~CTL_EE_CLK; + writel(priv(dev)->plx_control_bits, plx_control_addr); + comedi_udelay(eeprom_comedi_udelay); + if (readl(plx_control_addr) & CTL_EE_R) + value |= bit; + } + + // deactivate eeprom serial input + comedi_udelay(eeprom_comedi_udelay); + priv(dev)->plx_control_bits &= ~CTL_EE_CS; + writel(priv(dev)->plx_control_bits, plx_control_addr); + + return value; +} + +static int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = read_eeprom(dev, CR_CHAN(insn->chanspec)); + + return 1; +} + +/* utility function that rounds desired timing to an achievable time, and + * sets cmd members appropriately. + * adc paces conversions from master clock by dividing by (x + 3) where x is 24 bit number + */ +static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) +{ + unsigned int convert_divisor = 0, scan_divisor; + static const int min_convert_divisor = 3; + static const int max_convert_divisor = + max_counter_value + min_convert_divisor; + static const int min_scan_divisor_4020 = 2; + unsigned long long max_scan_divisor, min_scan_divisor; + + if (cmd->convert_src == TRIG_TIMER) { + if (board(dev)->layout == LAYOUT_4020) { + cmd->convert_arg = 0; + } else { + convert_divisor = + get_divisor(cmd->convert_arg, cmd->flags); + if (convert_divisor > max_convert_divisor) + convert_divisor = max_convert_divisor; + if (convert_divisor < min_convert_divisor) + convert_divisor = min_convert_divisor; + cmd->convert_arg = convert_divisor * TIMER_BASE; + } + } else if (cmd->convert_src == TRIG_NOW) + cmd->convert_arg = 0; + + if (cmd->scan_begin_src == TRIG_TIMER) { + scan_divisor = get_divisor(cmd->scan_begin_arg, cmd->flags); + if (cmd->convert_src == TRIG_TIMER) { + // XXX check for integer overflows + min_scan_divisor = convert_divisor * cmd->chanlist_len; + max_scan_divisor = + (convert_divisor * cmd->chanlist_len - 1) + + max_counter_value; + } else { + min_scan_divisor = min_scan_divisor_4020; + max_scan_divisor = max_counter_value + min_scan_divisor; + } + if (scan_divisor > max_scan_divisor) + scan_divisor = max_scan_divisor; + if (scan_divisor < min_scan_divisor) + scan_divisor = min_scan_divisor; + cmd->scan_begin_arg = scan_divisor * TIMER_BASE; + } + + return; +} + +/* Gets nearest achievable timing given master clock speed, does not + * take into account possible minimum/maximum divisor values. Used + * by other timing checking functions. */ +static unsigned int get_divisor(unsigned int ns, unsigned int flags) +{ + unsigned int divisor; + + switch (flags & TRIG_ROUND_MASK) { + case TRIG_ROUND_UP: + divisor = (ns + TIMER_BASE - 1) / TIMER_BASE; + break; + case TRIG_ROUND_DOWN: + divisor = ns / TIMER_BASE; + break; + case TRIG_ROUND_NEAREST: + default: + divisor = (ns + TIMER_BASE / 2) / TIMER_BASE; + break; + } + return divisor; +} + +static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags) +{ + return get_divisor(ns, flags) - 2; +} + +// adjusts the size of hardware fifo (which determines block size for dma xfers) +static int set_ai_fifo_size(struct comedi_device * dev, unsigned int num_samples) +{ + unsigned int num_fifo_entries; + int retval; + const struct hw_fifo_info *const fifo = board(dev)->ai_fifo; + + num_fifo_entries = num_samples / fifo->sample_packing_ratio; + + retval = set_ai_fifo_segment_length(dev, + num_fifo_entries / fifo->num_segments); + if (retval < 0) + return retval; + + num_samples = retval * fifo->num_segments * fifo->sample_packing_ratio; + + DEBUG_PRINT("set hardware fifo size to %i\n", num_samples); + + return num_samples; +} + +// query length of fifo +static unsigned int ai_fifo_size(struct comedi_device * dev) +{ + return priv(dev)->ai_fifo_segment_length * + board(dev)->ai_fifo->num_segments * + board(dev)->ai_fifo->sample_packing_ratio; +} + +static int set_ai_fifo_segment_length(struct comedi_device * dev, + unsigned int num_entries) +{ + static const int increment_size = 0x100; + const struct hw_fifo_info *const fifo = board(dev)->ai_fifo; + unsigned int num_increments; + uint16_t bits; + + if (num_entries < increment_size) + num_entries = increment_size; + if (num_entries > fifo->max_segment_length) + num_entries = fifo->max_segment_length; + + // 1 == 256 entries, 2 == 512 entries, etc + num_increments = (num_entries + increment_size / 2) / increment_size; + + bits = (~(num_increments - 1)) & fifo->fifo_size_reg_mask; + priv(dev)->fifo_size_bits &= ~fifo->fifo_size_reg_mask; + priv(dev)->fifo_size_bits |= bits; + writew(priv(dev)->fifo_size_bits, + priv(dev)->main_iobase + FIFO_SIZE_REG); + + priv(dev)->ai_fifo_segment_length = num_increments * increment_size; + + DEBUG_PRINT("set hardware fifo segment length to %i\n", + priv(dev)->ai_fifo_segment_length); + + return priv(dev)->ai_fifo_segment_length; +} + +/* pci-6025 8800 caldac: + * address 0 == dac channel 0 offset + * address 1 == dac channel 0 gain + * address 2 == dac channel 1 offset + * address 3 == dac channel 1 gain + * address 4 == fine adc offset + * address 5 == coarse adc offset + * address 6 == coarse adc gain + * address 7 == fine adc gain + */ +/* pci-6402/16 uses all 8 channels for dac: + * address 0 == dac channel 0 fine gain + * address 1 == dac channel 0 coarse gain + * address 2 == dac channel 0 coarse offset + * address 3 == dac channel 1 coarse offset + * address 4 == dac channel 1 fine gain + * address 5 == dac channel 1 coarse gain + * address 6 == dac channel 0 fine offset + * address 7 == dac channel 1 fine offset +*/ + +static int caldac_8800_write(struct comedi_device * dev, unsigned int address, + uint8_t value) +{ + static const int num_caldac_channels = 8; + static const int bitstream_length = 11; + unsigned int bitstream = ((address & 0x7) << 8) | value; + unsigned int bit, register_bits; + static const int caldac_8800_udelay = 1; + + if (address >= num_caldac_channels) { + comedi_error(dev, "illegal caldac channel"); + return -1; + } + for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { + register_bits = 0; + if (bitstream & bit) + register_bits |= SERIAL_DATA_IN_BIT; + comedi_udelay(caldac_8800_udelay); + writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG); + register_bits |= SERIAL_CLOCK_BIT; + comedi_udelay(caldac_8800_udelay); + writew(register_bits, priv(dev)->main_iobase + CALIBRATION_REG); + } + comedi_udelay(caldac_8800_udelay); + writew(SELECT_8800_BIT, priv(dev)->main_iobase + CALIBRATION_REG); + comedi_udelay(caldac_8800_udelay); + writew(0, priv(dev)->main_iobase + CALIBRATION_REG); + comedi_udelay(caldac_8800_udelay); + return 0; +} + +// 4020 caldacs +static int caldac_i2c_write(struct comedi_device * dev, unsigned int caldac_channel, + unsigned int value) +{ + uint8_t serial_bytes[3]; + uint8_t i2c_addr; + enum pointer_bits { + // manual has gain and offset bits switched + OFFSET_0_2 = 0x1, + GAIN_0_2 = 0x2, + OFFSET_1_3 = 0x4, + GAIN_1_3 = 0x8, + }; + enum data_bits { + NOT_CLEAR_REGISTERS = 0x20, + }; + + switch (caldac_channel) { + case 0: // chan 0 offset + i2c_addr = CALDAC0_I2C_ADDR; + serial_bytes[0] = OFFSET_0_2; + break; + case 1: // chan 1 offset + i2c_addr = CALDAC0_I2C_ADDR; + serial_bytes[0] = OFFSET_1_3; + break; + case 2: // chan 2 offset + i2c_addr = CALDAC1_I2C_ADDR; + serial_bytes[0] = OFFSET_0_2; + break; + case 3: // chan 3 offset + i2c_addr = CALDAC1_I2C_ADDR; + serial_bytes[0] = OFFSET_1_3; + break; + case 4: // chan 0 gain + i2c_addr = CALDAC0_I2C_ADDR; + serial_bytes[0] = GAIN_0_2; + break; + case 5: // chan 1 gain + i2c_addr = CALDAC0_I2C_ADDR; + serial_bytes[0] = GAIN_1_3; + break; + case 6: // chan 2 gain + i2c_addr = CALDAC1_I2C_ADDR; + serial_bytes[0] = GAIN_0_2; + break; + case 7: // chan 3 gain + i2c_addr = CALDAC1_I2C_ADDR; + serial_bytes[0] = GAIN_1_3; + break; + default: + comedi_error(dev, "invalid caldac channel\n"); + return -1; + break; + } + serial_bytes[1] = NOT_CLEAR_REGISTERS | ((value >> 8) & 0xf); + serial_bytes[2] = value & 0xff; + i2c_write(dev, i2c_addr, serial_bytes, 3); + return 0; +} + +// Their i2c requires a huge delay on setting clock or data high for some reason +static const int i2c_high_comedi_udelay = 1000; +static const int i2c_low_comedi_udelay = 10; + +// set i2c data line high or low +static void i2c_set_sda(struct comedi_device * dev, int state) +{ + static const int data_bit = CTL_EE_W; + void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG; + + if (state) { + // set data line high + priv(dev)->plx_control_bits &= ~data_bit; + writel(priv(dev)->plx_control_bits, plx_control_addr); + comedi_udelay(i2c_high_comedi_udelay); + } else // set data line low + { + priv(dev)->plx_control_bits |= data_bit; + writel(priv(dev)->plx_control_bits, plx_control_addr); + comedi_udelay(i2c_low_comedi_udelay); + } +} + +// set i2c clock line high or low +static void i2c_set_scl(struct comedi_device * dev, int state) +{ + static const int clock_bit = CTL_USERO; + void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG; + + if (state) { + // set clock line high + priv(dev)->plx_control_bits &= ~clock_bit; + writel(priv(dev)->plx_control_bits, plx_control_addr); + comedi_udelay(i2c_high_comedi_udelay); + } else // set clock line low + { + priv(dev)->plx_control_bits |= clock_bit; + writel(priv(dev)->plx_control_bits, plx_control_addr); + comedi_udelay(i2c_low_comedi_udelay); + } +} + +static void i2c_write_byte(struct comedi_device * dev, uint8_t byte) +{ + uint8_t bit; + unsigned int num_bits = 8; + + DEBUG_PRINT("writing to i2c byte 0x%x\n", byte); + + for (bit = 1 << (num_bits - 1); bit; bit >>= 1) { + i2c_set_scl(dev, 0); + if ((byte & bit)) + i2c_set_sda(dev, 1); + else + i2c_set_sda(dev, 0); + i2c_set_scl(dev, 1); + } +} + +// we can't really read the lines, so fake it +static int i2c_read_ack(struct comedi_device * dev) +{ + i2c_set_scl(dev, 0); + i2c_set_sda(dev, 1); + i2c_set_scl(dev, 1); + + return 0; // return fake acknowledge bit +} + +// send start bit +static void i2c_start(struct comedi_device * dev) +{ + i2c_set_scl(dev, 1); + i2c_set_sda(dev, 1); + i2c_set_sda(dev, 0); +} + +// send stop bit +static void i2c_stop(struct comedi_device * dev) +{ + i2c_set_scl(dev, 0); + i2c_set_sda(dev, 0); + i2c_set_scl(dev, 1); + i2c_set_sda(dev, 1); +} + +static void i2c_write(struct comedi_device * dev, unsigned int address, + const uint8_t * data, unsigned int length) +{ + unsigned int i; + uint8_t bitstream; + static const int read_bit = 0x1; + +//XXX need mutex to prevent simultaneous attempts to access eeprom and i2c bus + + // make sure we dont send anything to eeprom + priv(dev)->plx_control_bits &= ~CTL_EE_CS; + + i2c_stop(dev); + i2c_start(dev); + + // send address and write bit + bitstream = (address << 1) & ~read_bit; + i2c_write_byte(dev, bitstream); + + // get acknowledge + if (i2c_read_ack(dev) != 0) { + comedi_error(dev, "i2c write failed: no acknowledge"); + i2c_stop(dev); + return; + } + // write data bytes + for (i = 0; i < length; i++) { + i2c_write_byte(dev, data[i]); + if (i2c_read_ack(dev) != 0) { + comedi_error(dev, "i2c write failed: no acknowledge"); + i2c_stop(dev); + return; + } + } + i2c_stop(dev); +} diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c new file mode 100644 index 000000000000..ed0a5eb3dd91 --- /dev/null +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -0,0 +1,841 @@ +/* + comedi/drivers/cb_pcidda.c + This intends to be a driver for the ComputerBoards / MeasurementComputing + PCI-DDA series. + + Copyright (C) 2001 Ivan Martinez + Copyright (C) 2001 Frank Mori Hess + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-8 David A. Schleef + + 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: cb_pcidda +Description: MeasurementComputing PCI-DDA series +Author: Ivan Martinez , Frank Mori Hess +Status: Supports 08/16, 04/16, 02/16, 08/12, 04/12, and 02/12 +Devices: [Measurement Computing] PCI-DDA08/12 (cb_pcidda), PCI-DDA04/12, + PCI-DDA02/12, PCI-DDA08/16, PCI-DDA04/16, PCI-DDA02/16 + +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first available PCI + device will be used. + +Only simple analog output writing is supported. + +So far it has only been tested with: + - PCI-DDA08/12 +Please report success/failure with other different cards to +. +*/ + +#include "../comedidev.h" + +#include "comedi_pci.h" +#include "8255.h" + +#define PCI_VENDOR_ID_CB 0x1307 // PCI vendor number of ComputerBoards +#define N_BOARDS 10 // Number of boards in cb_pcidda_boards +#define EEPROM_SIZE 128 // number of entries in eeprom +#define MAX_AO_CHANNELS 8 // maximum number of ao channels for supported boards + +/* PCI-DDA base addresses */ +#define DIGITALIO_BADRINDEX 2 + // DIGITAL I/O is pci_dev->resource[2] +#define DIGITALIO_SIZE 8 + // DIGITAL I/O uses 8 I/O port addresses +#define DAC_BADRINDEX 3 + // DAC is pci_dev->resource[3] + +/* Digital I/O registers */ +#define PORT1A 0 // PORT 1A DATA + +#define PORT1B 1 // PORT 1B DATA + +#define PORT1C 2 // PORT 1C DATA + +#define CONTROL1 3 // CONTROL REGISTER 1 + +#define PORT2A 4 // PORT 2A DATA + +#define PORT2B 5 // PORT 2B DATA + +#define PORT2C 6 // PORT 2C DATA + +#define CONTROL2 7 // CONTROL REGISTER 2 + +/* DAC registers */ +#define DACONTROL 0 // D/A CONTROL REGISTER +#define SU 0000001 // Simultaneous update enabled +#define NOSU 0000000 // Simultaneous update disabled +#define ENABLEDAC 0000002 // Enable specified DAC +#define DISABLEDAC 0000000 // Disable specified DAC +#define RANGE2V5 0000000 // 2.5V +#define RANGE5V 0000200 // 5V +#define RANGE10V 0000300 // 10V +#define UNIP 0000400 // Unipolar outputs +#define BIP 0000000 // Bipolar outputs + +#define DACALIBRATION1 4 // D/A CALIBRATION REGISTER 1 +//write bits +#define SERIAL_IN_BIT 0x1 // serial data input for eeprom, caldacs, reference dac +#define CAL_CHANNEL_MASK (0x7 << 1) +#define CAL_CHANNEL_BITS(channel) (((channel) << 1) & CAL_CHANNEL_MASK) +//read bits +#define CAL_COUNTER_MASK 0x1f +#define CAL_COUNTER_OVERFLOW_BIT 0x20 // calibration counter overflow status bit +#define AO_BELOW_REF_BIT 0x40 // analog output is less than reference dac voltage +#define SERIAL_OUT_BIT 0x80 // serial data out, for reading from eeprom + +#define DACALIBRATION2 6 // D/A CALIBRATION REGISTER 2 +#define SELECT_EEPROM_BIT 0x1 // send serial data in to eeprom +#define DESELECT_REF_DAC_BIT 0x2 // don't send serial data to MAX542 reference dac +#define DESELECT_CALDAC_BIT(n) (0x4 << (n)) // don't send serial data to caldac n +#define DUMMY_BIT 0x40 // manual says to set this bit with no explanation + +#define DADATA 8 // FIRST D/A DATA REGISTER (0) + +static const struct comedi_lrange cb_pcidda_ranges = { + 6, + { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + } +}; + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct cb_pcidda_board { + const char *name; + char status; // Driver status: + // 0 - tested + // 1 - manual read, not tested + // 2 - manual not read + unsigned short device_id; + int ao_chans; + int ao_bits; + const struct comedi_lrange *ranges; +}; +static const struct cb_pcidda_board cb_pcidda_boards[] = { + { + name: "pci-dda02/12", + status: 1, + device_id:0x20, + ao_chans:2, + ao_bits: 12, + ranges: &cb_pcidda_ranges, + }, + { + name: "pci-dda04/12", + status: 1, + device_id:0x21, + ao_chans:4, + ao_bits: 12, + ranges: &cb_pcidda_ranges, + }, + { + name: "pci-dda08/12", + status: 0, + device_id:0x22, + ao_chans:8, + ao_bits: 12, + ranges: &cb_pcidda_ranges, + }, + { + name: "pci-dda02/16", + status: 2, + device_id:0x23, + ao_chans:2, + ao_bits: 16, + ranges: &cb_pcidda_ranges, + }, + { + name: "pci-dda04/16", + status: 2, + device_id:0x24, + ao_chans:4, + ao_bits: 16, + ranges: &cb_pcidda_ranges, + }, + { + name: "pci-dda08/16", + status: 0, + device_id:0x25, + ao_chans:8, + ao_bits: 16, + ranges: &cb_pcidda_ranges, + }, +}; + +static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = { + {PCI_VENDOR_ID_CB, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x0021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x0023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x0024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x0025, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table); + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct cb_pcidda_private { + int data; + + /* would be useful for a PCI device */ + struct pci_dev *pci_dev; + + unsigned long digitalio; + unsigned long dac; + //unsigned long control_status; + //unsigned long adc_fifo; + unsigned int dac_cal1_bits; // bits last written to da calibration register 1 + unsigned int ao_range[MAX_AO_CHANNELS]; // current range settings for output channels + u16 eeprom_data[EEPROM_SIZE]; // software copy of board's eeprom +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct cb_pcidda_private *)dev->private) + +static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int cb_pcidda_detach(struct comedi_device * dev); +//static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); +static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +//static int cb_pcidda_ai_cmd(struct comedi_device *dev,struct comedi_subdevice *s); +//static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,struct comedi_subdevice *s, struct comedi_cmd *cmd); +//static int cb_pcidda_ns_to_timer(unsigned int *ns,int round); +static unsigned int cb_pcidda_serial_in(struct comedi_device * dev); +static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value, + unsigned int num_bits); +static unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev, + unsigned int address); +static void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel, + unsigned int range); + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static struct comedi_driver driver_cb_pcidda = { + driver_name:"cb_pcidda", + module:THIS_MODULE, + attach:cb_pcidda_attach, + detach:cb_pcidda_detach, +}; + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. + */ +static int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + struct pci_dev *pcidev; + int index; + + printk("comedi%d: cb_pcidda: ", dev->minor); + +/* + * Allocate the private structure area. + */ + if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0) + return -ENOMEM; + +/* + * Probe the device to determine what device in the series it is. + */ + printk("\n"); + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + if (pcidev->vendor == PCI_VENDOR_ID_CB) { + if (it->options[0] || it->options[1]) { + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != + it->options[1]) { + continue; + } + } + for (index = 0; index < N_BOARDS; index++) { + if (cb_pcidda_boards[index].device_id == + pcidev->device) { + goto found; + } + } + } + } + if (!pcidev) { + printk("Not a ComputerBoards/MeasurementComputing card on requested position\n"); + return -EIO; + } + found: + devpriv->pci_dev = pcidev; + dev->board_ptr = cb_pcidda_boards + index; + // "thisboard" macro can be used from here. + printk("Found %s at requested position\n", thisboard->name); + + /* + * Enable PCI device and request regions. + */ + if (comedi_pci_enable(pcidev, thisboard->name)) { + printk("cb_pcidda: failed to enable PCI device and request regions\n"); + return -EIO; + } + +/* + * Allocate the I/O ports. + */ + devpriv->digitalio = + pci_resource_start(devpriv->pci_dev, DIGITALIO_BADRINDEX); + devpriv->dac = pci_resource_start(devpriv->pci_dev, DAC_BADRINDEX); + +/* + * Warn about the status of the driver. + */ + if (thisboard->status == 2) + printk("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. " "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. " "PLEASE REPORT USAGE TO .\n"); + +/* + * Initialize dev->board_name. + */ + dev->board_name = thisboard->name; + +/* + * Allocate the subdevice structures. + */ + if (alloc_subdevices(dev, 3) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_chans; + s->maxdata = (1 << thisboard->ao_bits) - 1; + s->range_table = thisboard->ranges; + s->insn_write = cb_pcidda_ao_winsn; +// s->subdev_flags |= SDF_CMD_READ; +// s->do_cmd = cb_pcidda_ai_cmd; +// s->do_cmdtest = cb_pcidda_ai_cmdtest; + + // two 8255 digital io subdevices + s = dev->subdevices + 1; + subdev_8255_init(dev, s, NULL, devpriv->digitalio); + s = dev->subdevices + 2; + subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A); + + printk(" eeprom:"); + for (index = 0; index < EEPROM_SIZE; index++) { + devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index); + printk(" %i:0x%x ", index, devpriv->eeprom_data[index]); + } + printk("\n"); + + // set calibrations dacs + for (index = 0; index < thisboard->ao_chans; index++) + cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int cb_pcidda_detach(struct comedi_device * dev) +{ +/* + * Deallocate the I/O ports. + */ + if (devpriv) { + if (devpriv->pci_dev) { + if (devpriv->dac) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + } + // cleanup 8255 + if (dev->subdevices) { + subdev_8255_cleanup(dev, dev->subdevices + 1); + subdev_8255_cleanup(dev, dev->subdevices + 2); + } + + printk("comedi%d: cb_pcidda: remove\n", dev->minor); + + return 0; +} + +/* + * I will program this later... ;-) + */ +#if 0 +static int cb_pcidda_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + printk("cb_pcidda_ai_cmd\n"); + printk("subdev: %d\n", cmd->subdev); + printk("flags: %d\n", cmd->flags); + printk("start_src: %d\n", cmd->start_src); + printk("start_arg: %d\n", cmd->start_arg); + printk("scan_begin_src: %d\n", cmd->scan_begin_src); + printk("convert_src: %d\n", cmd->convert_src); + printk("convert_arg: %d\n", cmd->convert_arg); + printk("scan_end_src: %d\n", cmd->scan_end_src); + printk("scan_end_arg: %d\n", cmd->scan_end_arg); + printk("stop_src: %d\n", cmd->stop_src); + printk("stop_arg: %d\n", cmd->stop_arg); + printk("chanlist_len: %d\n", cmd->chanlist_len); +} +#endif + +#if 0 +static int cb_pcidda_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ + + 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_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER + && cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } +#define MAX_SPEED 10000 /* in nanoseconds */ +#define MIN_SPEED 1000000000 /* in nanoseconds */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < MAX_SPEED) { + cmd->scan_begin_arg = MAX_SPEED; + err++; + } + if (cmd->scan_begin_arg > MIN_SPEED) { + cmd->scan_begin_arg = MIN_SPEED; + err++; + } + } else { + /* external trigger */ + /* should be level/edge, hi/lo specification here */ + /* should specify multiple external triggers */ + if (cmd->scan_begin_arg > 9) { + cmd->scan_begin_arg = 9; + err++; + } + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < MAX_SPEED) { + cmd->convert_arg = MAX_SPEED; + err++; + } + if (cmd->convert_arg > MIN_SPEED) { + cmd->convert_arg = MIN_SPEED; + err++; + } + } else { + /* external trigger */ + /* see above */ + if (cmd->convert_arg > 9) { + cmd->convert_arg = 9; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_arg > 0x00ffffff) { + cmd->stop_arg = 0x00ffffff; + err++; + } + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + cb_pcidda_ns_to_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + cb_pcidda_ns_to_timer(&cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + if (cmd->scan_begin_src == TRIG_TIMER && + cmd->scan_begin_arg < + cmd->convert_arg * cmd->scan_end_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->scan_end_arg; + err++; + } + } + + if (err) + return 4; + + return 0; +} +#endif + +/* This function doesn't require a particular form, this is just + * what happens to be used in some of the drivers. It should + * convert ns nanoseconds to a counter value suitable for programming + * the device. Also, it should adjust ns so that it cooresponds to + * the actual time that the device will use. */ +#if 0 +static int cb_pcidda_ns_to_timer(unsigned int *ns, int round) +{ + /* trivial timer */ + return *ns; +} +#endif + +static int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int command; + unsigned int channel, range; + + channel = CR_CHAN(insn->chanspec); + range = CR_RANGE(insn->chanspec); + + // adjust calibration dacs if range has changed + if (range != devpriv->ao_range[channel]) + cb_pcidda_calibrate(dev, channel, range); + + /* output channel configuration */ + command = NOSU | ENABLEDAC; + + /* output channel range */ + switch (range) { + case 0: + command |= BIP | RANGE10V; + break; + case 1: + command |= BIP | RANGE5V; + break; + case 2: + command |= BIP | RANGE2V5; + break; + case 3: + command |= UNIP | RANGE10V; + break; + case 4: + command |= UNIP | RANGE5V; + break; + case 5: + command |= UNIP | RANGE2V5; + break; + }; + + /* output channel specification */ + command |= channel << 2; + outw(command, devpriv->dac + DACONTROL); + + /* write data */ + outw(data[0], devpriv->dac + DADATA + channel * 2); + + /* return the number of samples read/written */ + return 1; +} + +// lowlevel read from eeprom +static unsigned int cb_pcidda_serial_in(struct comedi_device * dev) +{ + unsigned int value = 0; + int i; + const int value_width = 16; // number of bits wide values are + + for (i = 1; i <= value_width; i++) { + // read bits most significant bit first + if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT) { + value |= 1 << (value_width - i); + } + } + + return value; +} + +// lowlevel write to eeprom/dac +static void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value, + unsigned int num_bits) +{ + int i; + + for (i = 1; i <= num_bits; i++) { + // send bits most significant bit first + if (value & (1 << (num_bits - i))) + devpriv->dac_cal1_bits |= SERIAL_IN_BIT; + else + devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT; + outw_p(devpriv->dac_cal1_bits, devpriv->dac + DACALIBRATION1); + } +} + +// reads a 16 bit value from board's eeprom +static unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev, + unsigned int address) +{ + unsigned int i; + unsigned int cal2_bits; + unsigned int value; + const int max_num_caldacs = 4; // one caldac for every two dac channels + const int read_instruction = 0x6; // bits to send to tell eeprom we want to read + const int instruction_length = 3; + const int address_length = 8; + + // send serial output stream to eeprom + cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT; + // deactivate caldacs (one caldac for every two channels) + for (i = 0; i < max_num_caldacs; i++) { + cal2_bits |= DESELECT_CALDAC_BIT(i); + } + outw_p(cal2_bits, devpriv->dac + DACALIBRATION2); + + // tell eeprom we want to read + cb_pcidda_serial_out(dev, read_instruction, instruction_length); + // send address we want to read from + cb_pcidda_serial_out(dev, address, address_length); + + value = cb_pcidda_serial_in(dev); + + // deactivate eeprom + cal2_bits &= ~SELECT_EEPROM_BIT; + outw_p(cal2_bits, devpriv->dac + DACALIBRATION2); + + return value; +} + +// writes to 8 bit calibration dacs +static void cb_pcidda_write_caldac(struct comedi_device * dev, unsigned int caldac, + unsigned int channel, unsigned int value) +{ + unsigned int cal2_bits; + unsigned int i; + const int num_channel_bits = 3; // caldacs use 3 bit channel specification + const int num_caldac_bits = 8; // 8 bit calibration dacs + const int max_num_caldacs = 4; // one caldac for every two dac channels + + /* write 3 bit channel */ + cb_pcidda_serial_out(dev, channel, num_channel_bits); + // write 8 bit caldac value + cb_pcidda_serial_out(dev, value, num_caldac_bits); + + // latch stream into appropriate caldac + // deselect reference dac + cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT; + // deactivate caldacs (one caldac for every two channels) + for (i = 0; i < max_num_caldacs; i++) { + cal2_bits |= DESELECT_CALDAC_BIT(i); + } + // activate the caldac we want + cal2_bits &= ~DESELECT_CALDAC_BIT(caldac); + outw_p(cal2_bits, devpriv->dac + DACALIBRATION2); + // deactivate caldac + cal2_bits |= DESELECT_CALDAC_BIT(caldac); + outw_p(cal2_bits, devpriv->dac + DACALIBRATION2); +} + +// returns caldac that calibrates given analog out channel +static unsigned int caldac_number(unsigned int channel) +{ + return channel / 2; +} + +// returns caldac channel that provides fine gain for given ao channel +static unsigned int fine_gain_channel(unsigned int ao_channel) +{ + return 4 * (ao_channel % 2); +} + +// returns caldac channel that provides coarse gain for given ao channel +static unsigned int coarse_gain_channel(unsigned int ao_channel) +{ + return 1 + 4 * (ao_channel % 2); +} + +// returns caldac channel that provides coarse offset for given ao channel +static unsigned int coarse_offset_channel(unsigned int ao_channel) +{ + return 2 + 4 * (ao_channel % 2); +} + +// returns caldac channel that provides fine offset for given ao channel +static unsigned int fine_offset_channel(unsigned int ao_channel) +{ + return 3 + 4 * (ao_channel % 2); +} + +// returns eeprom address that provides offset for given ao channel and range +static unsigned int offset_eeprom_address(unsigned int ao_channel, + unsigned int range) +{ + return 0x7 + 2 * range + 12 * ao_channel; +} + +// returns eeprom address that provides gain calibration for given ao channel and range +static unsigned int gain_eeprom_address(unsigned int ao_channel, + unsigned int range) +{ + return 0x8 + 2 * range + 12 * ao_channel; +} + +// returns upper byte of eeprom entry, which gives the coarse adjustment values +static unsigned int eeprom_coarse_byte(unsigned int word) +{ + return (word >> 8) & 0xff; +} + +// returns lower byte of eeprom entry, which gives the fine adjustment values +static unsigned int eeprom_fine_byte(unsigned int word) +{ + return word & 0xff; +} + +// set caldacs to eeprom values for given channel and range +static void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel, + unsigned int range) +{ + unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain; + + // remember range so we can tell when we need to readjust calibration + devpriv->ao_range[channel] = range; + + // get values from eeprom data + coarse_offset = + eeprom_coarse_byte(devpriv-> + eeprom_data[offset_eeprom_address(channel, range)]); + fine_offset = + eeprom_fine_byte(devpriv-> + eeprom_data[offset_eeprom_address(channel, range)]); + coarse_gain = + eeprom_coarse_byte(devpriv-> + eeprom_data[gain_eeprom_address(channel, range)]); + fine_gain = + eeprom_fine_byte(devpriv-> + eeprom_data[gain_eeprom_address(channel, range)]); + + // set caldacs + cb_pcidda_write_caldac(dev, caldac_number(channel), + coarse_offset_channel(channel), coarse_offset); + cb_pcidda_write_caldac(dev, caldac_number(channel), + fine_offset_channel(channel), fine_offset); + cb_pcidda_write_caldac(dev, caldac_number(channel), + coarse_gain_channel(channel), coarse_gain); + cb_pcidda_write_caldac(dev, caldac_number(channel), + fine_gain_channel(channel), fine_gain); +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_PCI_INITCLEANUP(driver_cb_pcidda, cb_pcidda_pci_table); diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c new file mode 100644 index 000000000000..71a4b1482e36 --- /dev/null +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -0,0 +1,294 @@ +/* + comedi/drivers/cb_pcidio.c + A Comedi driver for PCI-DIO24H & PCI-DIO48H of ComputerBoards (currently MeasurementComputing) + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: cb_pcidio +Description: ComputerBoards' DIO boards with PCI interface +Devices: [Measurement Computing] PCI-DIO24 (cb_pcidio), PCI-DIO24H, PCI-DIO48H +Author: Yoshiya Matsuzaka +Updated: Mon, 29 Oct 2007 15:40:47 +0000 +Status: experimental + +This driver has been modified from skel.c of comedi-0.7.70. + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first available PCI device will + be used. + +Passing a zero for an option is the same as leaving it unspecified. +*/ + +/*------------------------------ HEADER FILES ---------------------------------*/ +#include "../comedidev.h" +#include "comedi_pci.h" +#include "8255.h" + +/*-------------------------- MACROS and DATATYPES -----------------------------*/ +#define PCI_VENDOR_ID_CB 0x1307 + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct pcidio_board { + const char *name; // anme of the board + int n_8255; // number of 8255 chips on board + + // indices of base address regions + int pcicontroler_badrindex; + int dioregs_badrindex; +}; + +static const struct pcidio_board pcidio_boards[] = { + { + name: "pci-dio24", + n_8255: 1, + pcicontroler_badrindex:1, + dioregs_badrindex:2, + }, + { + name: "pci-dio24h", + n_8255: 1, + pcicontroler_badrindex:1, + dioregs_badrindex:2, + }, + { + name: "pci-dio48h", + n_8255: 2, + pcicontroler_badrindex:0, + dioregs_badrindex:1, + }, +}; + +/* This is used by modprobe to translate PCI IDs to drivers. Should + * only be used for PCI and ISA-PnP devices */ +/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded + * upstream. */ +static DEFINE_PCI_DEVICE_TABLE(pcidio_pci_table) = { + {PCI_VENDOR_ID_CB, 0x0028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x0014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_CB, 0x000b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pcidio_pci_table); + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct pcidio_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct pcidio_private { + int data; // curently unused + + /* would be useful for a PCI device */ + struct pci_dev *pci_dev; + + /* used for DO readback, curently unused */ + unsigned int do_readback[4]; /* up to 4 unsigned int suffice to hold 96 bits for PCI-DIO96 */ + + unsigned long dio_reg_base; // address of port A of the first 8255 chip on board +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct pcidio_private *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcidio_detach(struct comedi_device * dev); +static struct comedi_driver driver_cb_pcidio = { + driver_name:"cb_pcidio", + module:THIS_MODULE, + attach:pcidio_attach, + detach:pcidio_detach, +/* It is not necessary to implement the following members if you are + * writing a driver for a ISA PnP or PCI card */ + /* Most drivers will support multiple types of boards by + * having an array of board structures. These were defined + * in pcidio_boards[] above. Note that the element 'name' + * was first in the structure -- Comedi uses this fact to + * extract the name of the board without knowing any details + * about the structure except for its length. + * When a device is attached (by comedi_config), the name + * of the device is given to Comedi, and Comedi tries to + * match it by going through the list of board names. If + * there is a match, the address of the pointer is put + * into dev->board_ptr and driver->attach() is called. + * + * Note that these are not necessary if you can determine + * the type of board in software. ISA PnP, PCI, and PCMCIA + * devices are such boards. + */ +// The following fields should NOT be initialized if you are dealing with PCI devices +// board_name: pcidio_boards, +// offset: sizeof(struct pcidio_board), +// num_names: sizeof(pcidio_boards) / sizeof(struct pcidio_board), +}; + +/*------------------------------- FUNCTIONS -----------------------------------*/ + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pcidio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct pci_dev *pcidev = NULL; + int index; + int i; + + printk("comedi%d: cb_pcidio: \n", dev->minor); + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct pcidio_private)) < 0) + return -ENOMEM; +/* + * If you can probe the device to determine what device in a series + * it is, this is the place to do it. Otherwise, dev->board_ptr + * should already be initialized. + */ +/* + * Probe the device to determine what device in the series it is. + */ + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + // is it not a computer boards card? + if (pcidev->vendor != PCI_VENDOR_ID_CB) + continue; + // loop through cards supported by this driver + for (index = 0; + index < sizeof pcidio_boards / sizeof(struct pcidio_board); + index++) { + if (pcidio_pci_table[index].device != pcidev->device) + continue; + + // was a particular bus/slot requested? + if (it->options[0] || it->options[1]) { + // are we on the wrong bus/slot? + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != + it->options[1]) { + continue; + } + } + dev->board_ptr = pcidio_boards + index; + goto found; + } + } + + printk("No supported ComputerBoards/MeasurementComputing card found on " + "requested position\n"); + return -EIO; + + found: + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + + devpriv->pci_dev = pcidev; + printk("Found %s on bus %i, slot %i\n", thisboard->name, + devpriv->pci_dev->bus->number, + PCI_SLOT(devpriv->pci_dev->devfn)); + if (comedi_pci_enable(pcidev, thisboard->name)) { + printk("cb_pcidio: failed to enable PCI device and request regions\n"); + return -EIO; + } + devpriv->dio_reg_base + = + pci_resource_start(devpriv->pci_dev, + pcidio_boards[index].dioregs_badrindex); + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_subdevices(dev, thisboard->n_8255) < 0) + return -ENOMEM; + + for (i = 0; i < thisboard->n_8255; i++) { + subdev_8255_init(dev, dev->subdevices + i, + NULL, devpriv->dio_reg_base + i * 4); + printk(" subdev %d: base = 0x%lx\n", i, + devpriv->dio_reg_base + i * 4); + } + + printk("attached\n"); + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pcidio_detach(struct comedi_device * dev) +{ + printk("comedi%d: cb_pcidio: remove\n", dev->minor); + if (devpriv) { + if (devpriv->pci_dev) { + if (devpriv->dio_reg_base) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + } + if (dev->subdevices) { + int i; + for (i = 0; i < thisboard->n_8255; i++) { + subdev_8255_cleanup(dev, dev->subdevices + i); + } + } + return 0; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_PCI_INITCLEANUP(driver_cb_pcidio, pcidio_pci_table); diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c new file mode 100644 index 000000000000..af705fa092c0 --- /dev/null +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -0,0 +1,484 @@ +/* + comedi/drivers/cb_pcimdas.c + Comedi driver for Computer Boards PCIM-DAS1602/16 + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: cb_pcimdas +Description: Measurement Computing PCI Migration series boards +Devices: [ComputerBoards] PCIM-DAS1602/16 (cb_pcimdas) +Author: Richard Bytheway +Updated: Wed, 13 Nov 2002 12:34:56 +0000 +Status: experimental + +Written to support the PCIM-DAS1602/16 on a 2.4 series kernel. + +Configuration Options: + [0] - PCI bus number + [1] - PCI slot number + +Developed from cb_pcidas and skel by Richard Bytheway (mocelet@sucs.org). +Only supports DIO, AO and simple AI in it's present form. +No interrupts, multi channel or FIFO AI, although the card looks like it could support this. +See http://www.measurementcomputing.com/PDFManuals/pcim-das1602_16.pdf for more details. +*/ + +#include "../comedidev.h" + +#include + +#include "comedi_pci.h" +#include "plx9052.h" +#include "8255.h" + +//#define CBPCIMDAS_DEBUG +#undef CBPCIMDAS_DEBUG + +/* Registers for the PCIM-DAS1602/16 */ + +// sizes of io regions (bytes) +#define BADR0_SIZE 2 //?? +#define BADR1_SIZE 4 +#define BADR2_SIZE 6 +#define BADR3_SIZE 16 +#define BADR4_SIZE 4 + +//DAC Offsets +#define ADC_TRIG 0 +#define DAC0_OFFSET 2 +#define DAC1_OFFSET 4 + +//AI and Counter Constants +#define MUX_LIMITS 0 +#define MAIN_CONN_DIO 1 +#define ADC_STAT 2 +#define ADC_CONV_STAT 3 +#define ADC_INT 4 +#define ADC_PACER 5 +#define BURST_MODE 6 +#define PROG_GAIN 7 +#define CLK8254_1_DATA 8 +#define CLK8254_2_DATA 9 +#define CLK8254_3_DATA 10 +#define CLK8254_CONTROL 11 +#define USER_COUNTER 12 +#define RESID_COUNT_H 13 +#define RESID_COUNT_L 14 + +/* Board description */ +struct cb_pcimdas_board { + const char *name; + unsigned short device_id; + int ai_se_chans; // Inputs in single-ended mode + int ai_diff_chans; // Inputs in differential mode + int ai_bits; // analog input resolution + int ai_speed; // fastest conversion period in ns + int ao_nchan; // number of analog out channels + int ao_bits; // analogue output resolution + int has_ao_fifo; // analog output has fifo + int ao_scan_speed; // analog output speed for 1602 series (for a scan, not conversion) + int fifo_size; // number of samples fifo can hold + int dio_bits; // number of dio bits + int has_dio; // has DIO + const struct comedi_lrange *ranges; +}; + +static const struct cb_pcimdas_board cb_pcimdas_boards[] = { + { + name: "PCIM-DAS1602/16", + device_id:0x56, + ai_se_chans:16, + ai_diff_chans:8, + ai_bits: 16, + ai_speed:10000, //?? + ao_nchan:2, + ao_bits: 12, + has_ao_fifo:0, //?? + ao_scan_speed:10000, + //?? + fifo_size:1024, + dio_bits:24, + has_dio: 1, +// ranges: &cb_pcimdas_ranges, + }, +}; + +/* This is used by modprobe to translate PCI IDs to drivers. Should + * only be used for PCI and ISA-PnP devices */ +static DEFINE_PCI_DEVICE_TABLE(cb_pcimdas_pci_table) = { + {PCI_VENDOR_ID_COMPUTERBOARDS, 0x0056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, cb_pcimdas_pci_table); + +#define N_BOARDS 1 // Max number of boards supported + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct cb_pcimdas_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct cb_pcimdas_private { + int data; + + // would be useful for a PCI device + struct pci_dev *pci_dev; + + //base addresses + unsigned long BADR0; + unsigned long BADR1; + unsigned long BADR2; + unsigned long BADR3; + unsigned long BADR4; + + /* Used for AO readback */ + unsigned int ao_readback[2]; + + // Used for DIO + unsigned short int port_a; // copy of BADR4+0 + unsigned short int port_b; // copy of BADR4+1 + unsigned short int port_c; // copy of BADR4+2 + unsigned short int dio_mode; // copy of BADR4+3 + +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct cb_pcimdas_private *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int cb_pcimdas_detach(struct comedi_device * dev); +static struct comedi_driver driver_cb_pcimdas = { + driver_name:"cb_pcimdas", + module:THIS_MODULE, + attach:cb_pcimdas_attach, + detach:cb_pcimdas_detach, +}; + +static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int cb_pcimdas_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + struct pci_dev *pcidev; + int index; + //int i; + + printk("comedi%d: cb_pcimdas: ", dev->minor); + +/* + * Allocate the private structure area. + */ + if (alloc_private(dev, sizeof(struct cb_pcimdas_private)) < 0) + return -ENOMEM; + +/* + * Probe the device to determine what device in the series it is. + */ + printk("\n"); + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + // is it not a computer boards card? + if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) + continue; + // loop through cards supported by this driver + for (index = 0; index < N_BOARDS; index++) { + if (cb_pcimdas_boards[index].device_id != + pcidev->device) + continue; + // was a particular bus/slot requested? + if (it->options[0] || it->options[1]) { + // are we on the wrong bus/slot? + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != + it->options[1]) { + continue; + } + } + devpriv->pci_dev = pcidev; + dev->board_ptr = cb_pcimdas_boards + index; + goto found; + } + } + + printk("No supported ComputerBoards/MeasurementComputing card found on " + "requested position\n"); + return -EIO; + + found: + + printk("Found %s on bus %i, slot %i\n", cb_pcimdas_boards[index].name, + pcidev->bus->number, PCI_SLOT(pcidev->devfn)); + + // Warn about non-tested features + switch (thisboard->device_id) { + case 0x56: + break; + default: + printk("THIS CARD IS UNSUPPORTED.\n" + "PLEASE REPORT USAGE TO \n"); + }; + + if (comedi_pci_enable(pcidev, "cb_pcimdas")) { + printk(" Failed to enable PCI device and request regions\n"); + return -EIO; + } + + devpriv->BADR0 = pci_resource_start(devpriv->pci_dev, 0); + devpriv->BADR1 = pci_resource_start(devpriv->pci_dev, 1); + devpriv->BADR2 = pci_resource_start(devpriv->pci_dev, 2); + devpriv->BADR3 = pci_resource_start(devpriv->pci_dev, 3); + devpriv->BADR4 = pci_resource_start(devpriv->pci_dev, 4); + +#ifdef CBPCIMDAS_DEBUG + printk("devpriv->BADR0 = 0x%lx\n", devpriv->BADR0); + printk("devpriv->BADR1 = 0x%lx\n", devpriv->BADR1); + printk("devpriv->BADR2 = 0x%lx\n", devpriv->BADR2); + printk("devpriv->BADR3 = 0x%lx\n", devpriv->BADR3); + printk("devpriv->BADR4 = 0x%lx\n", devpriv->BADR4); +#endif + +// Dont support IRQ yet +// // get irq +// if(comedi_request_irq(devpriv->pci_dev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) +// { +// printk(" unable to allocate irq %u\n", devpriv->pci_dev->irq); +// return -EINVAL; +// } +// dev->irq = devpriv->pci_dev->irq; + + //Initialize dev->board_name + dev->board_name = thisboard->name; + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_subdevices(dev, 3) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + //dev->read_subdev=s; + // analog input subdevice + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = thisboard->ai_se_chans; + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = &range_unknown; + s->len_chanlist = 1; // This is the maximum chanlist length that + // the board can handle + s->insn_read = cb_pcimdas_ai_rinsn; + + s = dev->subdevices + 1; + // analog output subdevice + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_nchan; + s->maxdata = 1 << thisboard->ao_bits; + s->range_table = &range_unknown; //ranges are hardware settable, but not software readable. + s->insn_write = &cb_pcimdas_ao_winsn; + s->insn_read = &cb_pcimdas_ao_rinsn; + + s = dev->subdevices + 2; + /* digital i/o subdevice */ + if (thisboard->has_dio) { + subdev_8255_init(dev, s, NULL, devpriv->BADR4); + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int cb_pcimdas_detach(struct comedi_device * dev) +{ +#ifdef CBPCIMDAS_DEBUG + if (devpriv) { + printk("devpriv->BADR0 = 0x%lx\n", devpriv->BADR0); + printk("devpriv->BADR1 = 0x%lx\n", devpriv->BADR1); + printk("devpriv->BADR2 = 0x%lx\n", devpriv->BADR2); + printk("devpriv->BADR3 = 0x%lx\n", devpriv->BADR3); + printk("devpriv->BADR4 = 0x%lx\n", devpriv->BADR4); + } +#endif + printk("comedi%d: cb_pcimdas: remove\n", dev->minor); + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (devpriv) { + if (devpriv->pci_dev) { + if (devpriv->BADR0) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + } + + return 0; +} + +/* + * "instructions" read/write data in "one-shot" or "software-triggered" + * mode. + */ +static int cb_pcimdas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, i; + unsigned int d; + unsigned int busy; + int chan = CR_CHAN(insn->chanspec); + unsigned short chanlims; + int maxchans; + + // only support sw initiated reads from a single channel + + //check channel number + if ((inb(devpriv->BADR3 + 2) & 0x20) == 0) //differential mode + maxchans = thisboard->ai_diff_chans; + else + maxchans = thisboard->ai_se_chans; + + if (chan > (maxchans - 1)) + return -ETIMEDOUT; //*** Wrong error code. Fixme. + + //configure for sw initiated read + d = inb(devpriv->BADR3 + 5); + if ((d & 0x03) > 0) { //only reset if needed. + d = d & 0xfd; + outb(d, devpriv->BADR3 + 5); + } + outb(0x01, devpriv->BADR3 + 6); //set bursting off, conversions on + outb(0x00, devpriv->BADR3 + 7); //set range to 10V. UP/BP is controlled by a switch on the board + + // write channel limits to multiplexer, set Low (bits 0-3) and High (bits 4-7) channels to chan. + chanlims = chan | (chan << 4); + outb(chanlims, devpriv->BADR3 + 0); + + /* convert n samples */ + for (n = 0; n < insn->n; n++) { + /* trigger conversion */ + outw(0, devpriv->BADR2 + 0); + +#define TIMEOUT 1000 //typically takes 5 loops on a lightly loaded Pentium 100MHz, + //this is likely to be 100 loops on a 2GHz machine, so set 1000 as the limit. + + /* wait for conversion to end */ + for (i = 0; i < TIMEOUT; i++) { + busy = inb(devpriv->BADR3 + 2) & 0x80; + if (!busy) + break; + } + if (i == TIMEOUT) { + printk("timeout\n"); + return -ETIMEDOUT; + } + /* read data */ + d = inw(devpriv->BADR2 + 0); + + /* mangle the data as necessary */ + //d ^= 1<<(thisboard->ai_bits-1); // 16 bit data from ADC, so no mangle needed. + + data[n] = d; + } + + /* return the number of samples read/written */ + return n; +} + +static int cb_pcimdas_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { + switch (chan) { + case 0: + outw(data[i] & 0x0FFF, devpriv->BADR2 + DAC0_OFFSET); + break; + case 1: + outw(data[i] & 0x0FFF, devpriv->BADR2 + DAC1_OFFSET); + break; + default: + return -1; + } + devpriv->ao_readback[chan] = data[i]; + } + + /* return the number of samples read/written */ + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. */ +static int cb_pcimdas_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_PCI_INITCLEANUP(driver_cb_pcimdas, cb_pcimdas_pci_table); diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c new file mode 100644 index 000000000000..e4c5b460fbd5 --- /dev/null +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -0,0 +1,474 @@ +/* + comedi/drivers/cb_pcimdda.c + Computer Boards PCIM-DDA06-16 Comedi driver + Author: Calin Culianu + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: cb_pcimdda +Description: Measurement Computing PCIM-DDA06-16 +Devices: [Measurement Computing] PCIM-DDA06-16 (cb_pcimdda) +Author: Calin Culianu +Updated: Mon, 14 Apr 2008 15:15:51 +0100 +Status: works + +All features of the PCIM-DDA06-16 board are supported. This board +has 6 16-bit AO channels, and the usual 8255 DIO setup. (24 channels, +configurable in banks of 8 and 4, etc.). This board does not support commands. + +The board has a peculiar way of specifying AO gain/range settings -- You have +1 jumper bank on the card, which either makes all 6 AO channels either +5 Volt unipolar, 5V bipolar, 10 Volt unipolar or 10V bipolar. + +Since there is absolutely _no_ way to tell in software how this jumper is set +(well, at least according to the rather thin spec. from Measurement Computing + that comes with the board), the driver assumes the jumper is at its factory +default setting of +/-5V. + +Also of note is the fact that this board features another jumper, whose +state is also completely invisible to software. It toggles two possible AO +output modes on the board: + + - Update Mode: Writing to an AO channel instantaneously updates the actual + signal output by the DAC on the board (this is the factory default). + - Simultaneous XFER Mode: Writing to an AO channel has no effect until + you read from any one of the AO channels. This is useful for loading + all 6 AO values, and then reading from any one of the AO channels on the + device to instantly update all 6 AO values in unison. Useful for some + control apps, I would assume? If your jumper is in this setting, then you + need to issue your comedi_data_write()s to load all the values you want, + then issue one comedi_data_read() on any channel on the AO subdevice + to initiate the simultaneous XFER. + +Configuration Options: + [0] PCI bus (optional) + [1] PCI slot (optional) + [2] analog output range jumper setting + 0 == +/- 5 V + 1 == +/- 10 V +*/ + +/* + This is a driver for the Computer Boards PCIM-DDA06-16 Analog Output + card. This board has a unique register layout and as such probably + deserves its own driver file. + + It is theoretically possible to integrate this board into the cb_pcidda + file, but since that isn't my code, I didn't want to significantly + modify that file to support this board (I thought it impolite to do so). + + At any rate, if you feel ambitious, please feel free to take + the code out of this file and combine it with a more unified driver + file. + + I would like to thank Timothy Curry + for lending me a board so that I could write this driver. + + -Calin Culianu + */ + +#include "../comedidev.h" + +#include "comedi_pci.h" + +#include "8255.h" + +/* device ids of the cards we support -- currently only 1 card supported */ +#define PCI_ID_PCIM_DDA06_16 0x0053 + +/* + * This is straight from skel.c -- I did this in case this source file + * will someday support more than 1 board... + */ +struct board_struct { + const char *name; + unsigned short device_id; + int ao_chans; + int ao_bits; + int dio_chans; + int dio_method; + int dio_offset; /* how many bytes into the BADR are the DIO ports */ + int regs_badrindex; /* IO Region for the control, analog output, + and DIO registers */ + int reg_sz; /* number of bytes of registers in io region */ +}; + +enum DIO_METHODS { + DIO_NONE = 0, + DIO_8255, + DIO_INTERNAL /* unimplemented */ +}; + +static const struct board_struct boards[] = { + { + name: "cb_pcimdda06-16", + device_id:PCI_ID_PCIM_DDA06_16, + ao_chans:6, + ao_bits: 16, + dio_chans:24, + dio_method:DIO_8255, + dio_offset:12, + regs_badrindex:3, + reg_sz: 16, + } +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct board_struct *)dev->board_ptr) + +/* Number of boards in boards[] */ +#define N_BOARDS (sizeof(boards) / sizeof(struct board_struct)) +#define REG_SZ (thisboard->reg_sz) +#define REGS_BADRINDEX (thisboard->regs_badrindex) + +/* This is used by modprobe to translate PCI IDs to drivers. Should + * only be used for PCI and ISA-PnP devices */ +/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded + * upstream. */ +static DEFINE_PCI_DEVICE_TABLE(pci_table) = { + {PCI_VENDOR_ID_COMPUTERBOARDS, PCI_ID_PCIM_DDA06_16, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, pci_table); + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct board_private_struct { + unsigned long registers; /* set by probe */ + unsigned long dio_registers; + char attached_to_8255; /* boolean */ + char attached_successfully; /* boolean */ + /* would be useful for a PCI device */ + struct pci_dev *pci_dev; + +#define MAX_AO_READBACK_CHANNELS 6 + /* Used for AO readback */ + unsigned int ao_readback[MAX_AO_READBACK_CHANNELS]; + +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct board_private_struct *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int detach(struct comedi_device * dev); +static struct comedi_driver cb_pcimdda_driver = { + driver_name:"cb_pcimdda", + module:THIS_MODULE, + attach:attach, + detach:detach, +}; + +MODULE_AUTHOR("Calin A. Culianu "); +MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA " + "series. Currently only supports PCIM-DDA06-16 (which " + "also happens to be the only board in this series. :) ) "); +MODULE_LICENSE("GPL"); +COMEDI_PCI_INITCLEANUP_NOMODULE(cb_pcimdda_driver, pci_table); + +static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +/*--------------------------------------------------------------------------- + HELPER FUNCTION DECLARATIONS +-----------------------------------------------------------------------------*/ + +/* returns a maxdata value for a given n_bits */ +static inline unsigned int figure_out_maxdata(int bits) +{ + return (((unsigned int) 1 << bits) - 1); +} + +/* + * Probes for a supported device. + * + * Prerequisite: private be allocated already inside dev + * + * If the device is found, it returns 0 and has the following side effects: + * + * o assigns a struct pci_dev * to dev->private->pci_dev + * o assigns a struct board * to dev->board_ptr + * o sets dev->private->registers + * o sets dev->private->dio_registers + * + * Otherwise, returns a -errno on error + */ +static int probe(struct comedi_device * dev, const struct comedi_devconfig * it); + +/*--------------------------------------------------------------------------- + FUNCTION DEFINITIONS +-----------------------------------------------------------------------------*/ + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int err; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + * if this function fails (returns negative) then the private area is + * kfree'd by comedi + */ + if (alloc_private(dev, sizeof(struct board_private_struct)) < 0) + return -ENOMEM; + +/* + * If you can probe the device to determine what device in a series + * it is, this is the place to do it. Otherwise, dev->board_ptr + * should already be initialized. + */ + if ((err = probe(dev, it))) + return err; + +/* Output some info */ + printk("comedi%d: %s: ", dev->minor, thisboard->name); + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_subdevices(dev, 2) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = thisboard->ao_chans; + s->maxdata = figure_out_maxdata(thisboard->ao_bits); + /* this is hard-coded here */ + if (it->options[2]) { + s->range_table = &range_bipolar10; + } else { + s->range_table = &range_bipolar5; + } + s->insn_write = &ao_winsn; + s->insn_read = &ao_rinsn; + + s = dev->subdevices + 1; + /* digital i/o subdevice */ + if (thisboard->dio_chans) { + switch (thisboard->dio_method) { + case DIO_8255: + /* this is a straight 8255, so register us with the 8255 driver */ + subdev_8255_init(dev, s, NULL, devpriv->dio_registers); + devpriv->attached_to_8255 = 1; + break; + case DIO_INTERNAL: + default: + printk("DIO_INTERNAL not implemented yet!\n"); + return -ENXIO; + break; + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + devpriv->attached_successfully = 1; + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int detach(struct comedi_device * dev) +{ + if (devpriv) { + + if (dev->subdevices && devpriv->attached_to_8255) { + /* de-register us from the 8255 driver */ + subdev_8255_cleanup(dev, dev->subdevices + 2); + devpriv->attached_to_8255 = 0; + } + + if (devpriv->pci_dev) { + if (devpriv->registers) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + + if (devpriv->attached_successfully && thisboard) + printk("comedi%d: %s: detached\n", dev->minor, + thisboard->name); + + } + + return 0; +} + +static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + unsigned long offset = devpriv->registers + chan * 2; + + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { + /* first, load the low byte */ + outb((char)(data[i] & 0x00ff), offset); + /* next, write the high byte -- only after this is written is + the channel voltage updated in the DAC, unless + we're in simultaneous xfer mode (jumper on card) + then a rinsn is necessary to actually update the DAC -- + see ao_rinsn() below... */ + outb((char)(data[i] >> 8 & 0x00ff), offset + 1); + + /* for testing only.. the actual rinsn SHOULD do an inw! + (see the stuff about simultaneous XFER mode on this board) */ + devpriv->ao_readback[chan] = data[i]; + } + + /* return the number of samples read/written */ + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + + Usually this means copying a value stored in devpriv->ao_readback. + However, since this board has this jumper setting called "Simultaneous + Xfer mode" (off by default), we will support it. Simultaneaous xfer + mode is accomplished by loading ALL the values you want for AO in all the + channels, then READing off one of the AO registers to initiate the + instantaneous simultaneous update of all DAC outputs, which makes + all AO channels update simultaneously. This is useful for some control + applications, I would imagine. +*/ +static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + inw(devpriv->registers + chan * 2); + /* should I set data[i] to the result of the actual read on the register + or the cached unsigned int in devpriv->ao_readback[]? */ + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +/*--------------------------------------------------------------------------- + HELPER FUNCTION DEFINITIONS +-----------------------------------------------------------------------------*/ + +/* + * Probes for a supported device. + * + * Prerequisite: private be allocated already inside dev + * + * If the device is found, it returns 0 and has the following side effects: + * + * o assigns a struct pci_dev * to dev->private->pci_dev + * o assigns a struct board * to dev->board_ptr + * o sets dev->private->registers + * o sets dev->private->dio_registers + * + * Otherwise, returns a -errno on error + */ +static int probe(struct comedi_device * dev, const struct comedi_devconfig * it) +{ + struct pci_dev *pcidev; + int index; + unsigned long registers; + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + // is it not a computer boards card? + if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) + continue; + // loop through cards supported by this driver + for (index = 0; index < N_BOARDS; index++) { + if (boards[index].device_id != pcidev->device) + continue; + // was a particular bus/slot requested? + if (it->options[0] || it->options[1]) { + // are we on the wrong bus/slot? + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != + it->options[1]) { + continue; + } + } + /* found ! */ + + devpriv->pci_dev = pcidev; + dev->board_ptr = boards + index; + if (comedi_pci_enable(pcidev, thisboard->name)) { + printk("cb_pcimdda: Failed to enable PCI device and request regions\n"); + return -EIO; + } + registers = + pci_resource_start(devpriv->pci_dev, + REGS_BADRINDEX); + devpriv->registers = registers; + devpriv->dio_registers + = devpriv->registers + thisboard->dio_offset; + return 0; + } + } + + printk("cb_pcimdda: No supported ComputerBoards/MeasurementComputing " + "card found at the requested position\n"); + return -ENODEV; +} diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 9e5496f4f1ae..1ee489864d3b 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -59,7 +59,7 @@ Configuration Options: * Devices: a full list of the boards that attempt to be supported by * the driver. Format is "(manufacturer) board name [comedi name]", * where comedi_name is the name that is used to configure the board. - * See the comment near board_name: in the comedi_driver structure + * See the comment near board_name: in the struct comedi_driver structure * below. If (manufacturer) or [comedi name] is missing, the previous * value is used. * Author: you @@ -142,7 +142,7 @@ static const struct BondingBoard bondingBoards[] = { #define thisboard ((const struct BondingBoard *)dev->board_ptr) struct BondedDevice { - comedi_t *dev; + void *dev; unsigned minor; unsigned subdev; unsigned subdev_type; @@ -154,7 +154,7 @@ struct BondedDevice { /* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, - feel free to suggest moving the variable to the comedi_device struct. */ + feel free to suggest moving the variable to the struct comedi_device struct. */ struct Private { # define MAX_BOARD_NAME 256 char name[MAX_BOARD_NAME]; @@ -171,21 +171,21 @@ struct Private { #define devpriv ((struct Private *)dev->private) /* - * The comedi_driver structure tells the Comedi core module + * The struct comedi_driver structure tells the Comedi core module * which functions to call to configure/deconfigure (attach/detach) * the board, and also about the kernel module that contains * the device code. */ -static int bonding_attach(comedi_device *dev, comedi_devconfig *it); -static int bonding_detach(comedi_device *dev); +static int bonding_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int bonding_detach(struct comedi_device *dev); /** Build Private array of all devices.. */ -static int doDevConfig(comedi_device *dev, comedi_devconfig *it); -static void doDevUnconfig(comedi_device *dev); +static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it); +static void doDevUnconfig(struct comedi_device *dev); /* Ugly implementation of realloc that always copies memory around -- I'm lazy, * what can I say? I like to do wasteful memcopies.. :) */ static void *Realloc(const void *ptr, size_t len, size_t old_len); -static comedi_driver driver_bonding = { +static struct comedi_driver driver_bonding = { .driver_name = MODULE_NAME, .module = THIS_MODULE, .attach = bonding_attach, @@ -213,10 +213,10 @@ static comedi_driver driver_bonding = { .num_names = sizeof(bondingBoards) / sizeof(struct BondingBoard), }; -static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data); -static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data); +static int bonding_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int bonding_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); /* * Attach is called by the Comedi core to configure the driver @@ -224,9 +224,9 @@ static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s, * in the driver structure, dev->board_ptr contains that * address. */ -static int bonding_attach(comedi_device *dev, comedi_devconfig *it) +static int bonding_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - comedi_subdevice *s; + struct comedi_subdevice *s; LOG_MSG("comedi%d\n", dev->minor); @@ -281,7 +281,7 @@ static int bonding_attach(comedi_device *dev, comedi_devconfig *it) * allocated by _attach(). dev->private and dev->subdevices are * deallocated automatically by the core. */ -static int bonding_detach(comedi_device *dev) +static int bonding_detach(struct comedi_device *dev) { LOG_MSG("comedi%d: remove\n", dev->minor); doDevUnconfig(dev); @@ -293,10 +293,10 @@ static int bonding_detach(comedi_device *dev) * useful to applications if you implement the insn_bits interface. * This allows packed reading/writing of the DIO channels. The * comedi core can convert between insn_bits and insn_read/write */ -static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int bonding_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { -#define LSAMPL_BITS (sizeof(lsampl_t)*8) +#define LSAMPL_BITS (sizeof(unsigned int)*8) unsigned nchans = LSAMPL_BITS, num_done = 0, i; if (insn->n != 2) return -EINVAL; @@ -312,12 +312,12 @@ static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s, to this subdevice.. need to shift them to zero position of course. */ /* Bits corresponding to this subdev. */ - lsampl_t subdevMask = ((1 << bdev->nchans) - 1); - lsampl_t writeMask, dataBits; + unsigned int subdevMask = ((1 << bdev->nchans) - 1); + unsigned int writeMask, dataBits; /* Argh, we have >= LSAMPL_BITS chans.. take all bits */ if (bdev->nchans >= LSAMPL_BITS) - subdevMask = (lsampl_t) (-1); + subdevMask = (unsigned int) (-1); writeMask = (data[0] >> num_done) & subdevMask; dataBits = (data[1] >> num_done) & subdevMask; @@ -340,8 +340,8 @@ static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s, return insn->n; } -static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int bonding_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits; unsigned int io; @@ -394,10 +394,10 @@ static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen) return newmem; } -static int doDevConfig(comedi_device *dev, comedi_devconfig *it) +static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it) { int i; - comedi_t *devs_opened[COMEDI_NUM_BOARD_MINORS]; + void *devs_opened[COMEDI_NUM_BOARD_MINORS]; memset(devs_opened, 0, sizeof(devs_opened)); devpriv->name[0] = 0;; @@ -406,7 +406,7 @@ static int doDevConfig(comedi_device *dev, comedi_devconfig *it) for (i = 0; i < COMEDI_NDEVCONFOPTS && (!i || it->options[i]); ++i) { char file[] = "/dev/comediXXXXXX"; int minor = it->options[i]; - comedi_t *d; + void *d; int sdev = -1, nchans, tmp; struct BondedDevice *bdev = NULL; @@ -497,7 +497,7 @@ static int doDevConfig(comedi_device *dev, comedi_devconfig *it) return 1; } -static void doDevUnconfig(comedi_device *dev) +static void doDevUnconfig(struct comedi_device *dev) { unsigned long devs_closed = 0; diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c index cd74dbe5417d..9fa4cdc84d44 100644 --- a/drivers/staging/comedi/drivers/comedi_fc.c +++ b/drivers/staging/comedi/drivers/comedi_fc.c @@ -28,10 +28,10 @@ #include "comedi_fc.h" -static void increment_scan_progress(comedi_subdevice *subd, +static void increment_scan_progress(struct comedi_subdevice *subd, unsigned int num_bytes) { - comedi_async *async = subd->async; + struct comedi_async *async = subd->async; unsigned int scan_length = cfc_bytes_per_scan(subd); async->scan_progress += num_bytes; @@ -42,10 +42,10 @@ static void increment_scan_progress(comedi_subdevice *subd, } /* Writes an array of data points to comedi's buffer */ -unsigned int cfc_write_array_to_buffer(comedi_subdevice *subd, void *data, +unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd, void *data, unsigned int num_bytes) { - comedi_async *async = subd->async; + struct comedi_async *async = subd->async; unsigned int retval; if (num_bytes == 0) @@ -67,10 +67,10 @@ unsigned int cfc_write_array_to_buffer(comedi_subdevice *subd, void *data, } EXPORT_SYMBOL(cfc_write_array_to_buffer); -unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd, void *data, +unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd, void *data, unsigned int num_bytes) { - comedi_async *async = subd->async; + struct comedi_async *async = subd->async; if (num_bytes == 0) return 0; @@ -85,7 +85,7 @@ unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd, void *data, } EXPORT_SYMBOL(cfc_read_array_from_buffer); -unsigned int cfc_handle_events(comedi_device *dev, comedi_subdevice *subd) +unsigned int cfc_handle_events(struct comedi_device *dev, struct comedi_subdevice *subd) { unsigned int events = subd->async->events; diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h index 6952fe20f273..494ae3f2aff6 100644 --- a/drivers/staging/comedi/drivers/comedi_fc.h +++ b/drivers/staging/comedi/drivers/comedi_fc.h @@ -30,30 +30,30 @@ #include "../comedidev.h" /* Writes an array of data points to comedi's buffer */ -extern unsigned int cfc_write_array_to_buffer(comedi_subdevice *subd, +extern unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd, void *data, unsigned int num_bytes); -static inline unsigned int cfc_write_to_buffer(comedi_subdevice *subd, - sampl_t data) +static inline unsigned int cfc_write_to_buffer(struct comedi_subdevice *subd, + short data) { return cfc_write_array_to_buffer(subd, &data, sizeof(data)); }; -static inline unsigned int cfc_write_long_to_buffer(comedi_subdevice *subd, - lsampl_t data) +static inline unsigned int cfc_write_long_to_buffer(struct comedi_subdevice *subd, + unsigned int data) { return cfc_write_array_to_buffer(subd, &data, sizeof(data)); }; -extern unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd, +extern unsigned int cfc_read_array_from_buffer(struct comedi_subdevice *subd, void *data, unsigned int num_bytes); -extern unsigned int cfc_handle_events(comedi_device *dev, - comedi_subdevice *subd); +extern unsigned int cfc_handle_events(struct comedi_device *dev, + struct comedi_subdevice *subd); -static inline unsigned int cfc_bytes_per_scan(comedi_subdevice *subd) +static inline unsigned int cfc_bytes_per_scan(struct comedi_subdevice *subd) { int num_samples; int bits_per_sample; diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index ba838fffa29e..a23339155ffc 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -90,9 +90,9 @@ pin, which can be used to wake up tasks. #define PARPORT_B 1 #define PARPORT_C 2 -static int parport_attach(comedi_device *dev, comedi_devconfig *it); -static int parport_detach(comedi_device *dev); -static comedi_driver driver_parport = { +static int parport_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int parport_detach(struct comedi_device *dev); +static struct comedi_driver driver_parport = { .driver_name = "comedi_parport", .module = THIS_MODULE, .attach = parport_attach, @@ -108,8 +108,8 @@ struct parport_private { }; #define devpriv ((struct parport_private *)(dev->private)) -static int parport_insn_a(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { if (data[0]) { devpriv->a_data &= ~data[0]; @@ -123,8 +123,8 @@ static int parport_insn_a(comedi_device *dev, comedi_subdevice *s, return 2; } -static int parport_insn_config_a(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int parport_insn_config_a(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { if (data[0]) { s->io_bits = 0xff; @@ -138,8 +138,8 @@ static int parport_insn_config_a(comedi_device *dev, comedi_subdevice *s, return 1; } -static int parport_insn_b(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { if (data[0]) { /* should writes be ignored? */ @@ -151,8 +151,8 @@ static int parport_insn_b(comedi_device *dev, comedi_subdevice *s, return 2; } -static int parport_insn_c(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { data[0] &= 0x0f; if (data[0]) { @@ -167,8 +167,8 @@ static int parport_insn_c(comedi_device *dev, comedi_subdevice *s, return 2; } -static int parport_intr_insn(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int parport_intr_insn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { if (insn->n < 1) return -EINVAL; @@ -177,8 +177,8 @@ static int parport_intr_insn(comedi_device *dev, comedi_subdevice *s, return 2; } -static int parport_intr_cmdtest(comedi_device *dev, comedi_subdevice *s, - comedi_cmd *cmd) +static int parport_intr_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd) { int err = 0; int tmp; @@ -252,7 +252,7 @@ static int parport_intr_cmdtest(comedi_device *dev, comedi_subdevice *s, return 0; } -static int parport_intr_cmd(comedi_device *dev, comedi_subdevice *s) +static int parport_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { devpriv->c_data |= 0x10; outb(devpriv->c_data, dev->iobase + PARPORT_C); @@ -262,7 +262,7 @@ static int parport_intr_cmd(comedi_device *dev, comedi_subdevice *s) return 0; } -static int parport_intr_cancel(comedi_device *dev, comedi_subdevice *s) +static int parport_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { printk(KERN_DEBUG "parport_intr_cancel()\n"); @@ -276,8 +276,8 @@ static int parport_intr_cancel(comedi_device *dev, comedi_subdevice *s) static irqreturn_t parport_interrupt(int irq, void *d PT_REGS_ARG) { - comedi_device *dev = d; - comedi_subdevice *s = dev->subdevices + 3; + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 3; if (!devpriv->enable_irq) { printk(KERN_ERR "comedi_parport: bogus irq, ignored\n"); @@ -291,12 +291,12 @@ static irqreturn_t parport_interrupt(int irq, void *d PT_REGS_ARG) return IRQ_HANDLED; } -static int parport_attach(comedi_device *dev, comedi_devconfig *it) +static int parport_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int ret; unsigned int irq; unsigned long iobase; - comedi_subdevice *s; + struct comedi_subdevice *s; iobase = it->options[0]; printk(KERN_INFO "comedi%d: parport: 0x%04lx ", dev->minor, iobase); @@ -376,7 +376,7 @@ static int parport_attach(comedi_device *dev, comedi_devconfig *it) return 1; } -static int parport_detach(comedi_device *dev) +static int parport_detach(struct comedi_device *dev) { printk("comedi%d: parport: remove\n", dev->minor); diff --git a/drivers/staging/comedi/drivers/comedi_rt_timer.c b/drivers/staging/comedi/drivers/comedi_rt_timer.c new file mode 100644 index 000000000000..f40c8cffd4bb --- /dev/null +++ b/drivers/staging/comedi/drivers/comedi_rt_timer.c @@ -0,0 +1,728 @@ +/* + comedi/drivers/comedi_rt_timer.c + virtual driver for using RTL timing sources + + Authors: David A. Schleef, Frank M. Hess + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999,2001 David A. Schleef + + 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: comedi_rt_timer +Description: Command emulator using real-time tasks +Author: ds, fmhess +Devices: +Status: works + +This driver requires RTAI or RTLinux to work correctly. It doesn't +actually drive hardware directly, but calls other drivers and uses +a real-time task to emulate commands for drivers and devices that +are incapable of native commands. Thus, you can get accurately +timed I/O on any device. + +Since the timing is all done in software, sampling jitter is much +higher than with a device that has an on-board timer, and maximum +sample rate is much lower. + +Configuration options: + [0] - minor number of device you wish to emulate commands for + [1] - subdevice number you wish to emulate commands for +*/ +/* +TODO: + Support for digital io commands could be added, except I can't see why + anyone would want to use them + What happens if device we are emulating for is de-configured? +*/ + +#include "../comedidev.h" +#include "../comedilib.h" + +#include "comedi_fc.h" + +#ifdef CONFIG_COMEDI_RTL_V1 +#include +#include +#endif +#ifdef CONFIG_COMEDI_RTL +#include +#include +#include +#include + +#ifndef RTLINUX_VERSION_CODE +#define RTLINUX_VERSION_CODE 0 +#endif +#ifndef RTLINUX_VERSION +#define RTLINUX_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +// begin hack to workaround broken HRT_TO_8254() function on rtlinux +#if RTLINUX_VERSION_CODE <= RTLINUX_VERSION(3,0,100) +// this function sole purpose is to divide a long long by 838 +static inline RTIME nano2count(long long ns) +{ + do_div(ns, 838); + return ns; +} + +#ifdef rt_get_time() +#undef rt_get_time() +#endif +#define rt_get_time() nano2count(gethrtime()) + +#else + +#define nano2count(x) HRT_TO_8254(x) +#endif +// end hack + +// rtl-rtai compatibility +#define rt_task_wait_period() rt_task_wait() +#define rt_pend_linux_srq(irq) rtl_global_pend_irq(irq) +#define rt_free_srq(irq) rtl_free_soft_irq(irq) +#define rt_request_srq(x,y,z) rtl_get_soft_irq(y,"timer") +#define rt_task_init(a,b,c,d,e,f,g) rt_task_init(a,b,c,d,(e)+1) +#define rt_task_resume(x) rt_task_wakeup(x) +#define rt_set_oneshot_mode() +#define start_rt_timer(x) +#define stop_rt_timer() + +#endif +#ifdef CONFIG_COMEDI_RTAI +#include +#include + +#if RTAI_VERSION_CODE < RTAI_MANGLE_VERSION(3,3,0) +#define comedi_rt_task_context_t int +#else +#define comedi_rt_task_context_t long +#endif + +#endif + +/* This defines the fastest speed we will emulate. Note that + * without a watchdog (like in RTAI), we could easily overrun our + * task period because analog input tends to be slow. */ +#define SPEED_LIMIT 100000 /* in nanoseconds */ + +static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int timer_detach(struct comedi_device * dev); +static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trig_num); +static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice * s); + +static struct comedi_driver driver_timer = { + module:THIS_MODULE, + driver_name:"comedi_rt_timer", + attach:timer_attach, + detach:timer_detach, +// open: timer_open, +}; + +COMEDI_INITCLEANUP(driver_timer); + +struct timer_private { + comedi_t *device; // device we are emulating commands for + int subd; // subdevice we are emulating commands for + RT_TASK *rt_task; // rt task that starts scans + RT_TASK *scan_task; // rt task that controls conversion timing in a scan + /* io_function can point to either an input or output function + * depending on what kind of subdevice we are emulating for */ + int (*io_function) (struct comedi_device * dev, struct comedi_cmd * cmd, + unsigned int index); + // RTIME has units of 1 = 838 nanoseconds + // time at which first scan started, used to check scan timing + RTIME start; + // time between scans + RTIME scan_period; + // time between conversions in a scan + RTIME convert_period; + // flags + volatile int stop; // indicates we should stop + volatile int rt_task_active; // indicates rt_task is servicing a struct comedi_cmd + volatile int scan_task_active; // indicates scan_task is servicing a struct comedi_cmd + unsigned timer_running:1; +}; +#define devpriv ((struct timer_private *)dev->private) + +static int timer_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + devpriv->stop = 1; + + return 0; +} + +// checks for scan timing error +inline static int check_scan_timing(struct comedi_device * dev, + unsigned long long scan) +{ + RTIME now, timing_error; + + now = rt_get_time(); + timing_error = now - (devpriv->start + scan * devpriv->scan_period); + if (timing_error > devpriv->scan_period) { + comedi_error(dev, "timing error"); + rt_printk("scan started %i ns late\n", timing_error * 838); + return -1; + } + + return 0; +} + +// checks for conversion timing error +inline static int check_conversion_timing(struct comedi_device * dev, + RTIME scan_start, unsigned int conversion) +{ + RTIME now, timing_error; + + now = rt_get_time(); + timing_error = + now - (scan_start + conversion * devpriv->convert_period); + if (timing_error > devpriv->convert_period) { + comedi_error(dev, "timing error"); + rt_printk("conversion started %i ns late\n", + timing_error * 838); + return -1; + } + + return 0; +} + +// devpriv->io_function for an input subdevice +static int timer_data_read(struct comedi_device * dev, struct comedi_cmd * cmd, + unsigned int index) +{ + struct comedi_subdevice *s = dev->read_subdev; + int ret; + unsigned int data; + + ret = comedi_data_read(devpriv->device, devpriv->subd, + CR_CHAN(cmd->chanlist[index]), + CR_RANGE(cmd->chanlist[index]), + CR_AREF(cmd->chanlist[index]), &data); + if (ret < 0) { + comedi_error(dev, "read error"); + return -EIO; + } + if (s->flags & SDF_LSAMPL) { + cfc_write_long_to_buffer(s, data); + } else { + comedi_buf_put(s->async, data); + } + + return 0; +} + +// devpriv->io_function for an output subdevice +static int timer_data_write(struct comedi_device * dev, struct comedi_cmd * cmd, + unsigned int index) +{ + struct comedi_subdevice *s = dev->write_subdev; + unsigned int num_bytes; + short data; + unsigned int long_data; + int ret; + + if (s->flags & SDF_LSAMPL) { + num_bytes = + cfc_read_array_from_buffer(s, &long_data, + sizeof(long_data)); + } else { + num_bytes = cfc_read_array_from_buffer(s, &data, sizeof(data)); + long_data = data; + } + + if (num_bytes == 0) { + comedi_error(dev, "buffer underrun"); + return -EAGAIN; + } + ret = comedi_data_write(devpriv->device, devpriv->subd, + CR_CHAN(cmd->chanlist[index]), + CR_RANGE(cmd->chanlist[index]), + CR_AREF(cmd->chanlist[index]), long_data); + if (ret < 0) { + comedi_error(dev, "write error"); + return -EIO; + } + + return 0; +} + +// devpriv->io_function for DIO subdevices +static int timer_dio_read(struct comedi_device * dev, struct comedi_cmd * cmd, + unsigned int index) +{ + struct comedi_subdevice *s = dev->read_subdev; + int ret; + unsigned int data; + + ret = comedi_dio_bitfield(devpriv->device, devpriv->subd, 0, &data); + if (ret < 0) { + comedi_error(dev, "read error"); + return -EIO; + } + + if (s->flags & SDF_LSAMPL) + cfc_write_long_to_buffer(s, data); + else + cfc_write_to_buffer(s, data); + + return 0; +} + +// performs scans +static void scan_task_func(comedi_rt_task_context_t d) +{ + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + 0; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + int i, ret; + unsigned long long n; + RTIME scan_start; + + // every struct comedi_cmd causes one execution of while loop + while (1) { + devpriv->scan_task_active = 1; + // each for loop completes one scan + for (n = 0; n < cmd->stop_arg || cmd->stop_src == TRIG_NONE; + n++) { + if (n) { + // suspend task until next scan + ret = rt_task_suspend(devpriv->scan_task); + if (ret < 0) { + comedi_error(dev, + "error suspending scan task"); + async->events |= COMEDI_CB_ERROR; + goto cleanup; + } + } + // check if stop flag was set (by timer_cancel()) + if (devpriv->stop) + goto cleanup; + ret = check_scan_timing(dev, n); + if (ret < 0) { + async->events |= COMEDI_CB_ERROR; + goto cleanup; + } + scan_start = rt_get_time(); + for (i = 0; i < cmd->scan_end_arg; i++) { + // conversion timing + if (cmd->convert_src == TRIG_TIMER && i) { + rt_task_wait_period(); + ret = check_conversion_timing(dev, + scan_start, i); + if (ret < 0) { + async->events |= + COMEDI_CB_ERROR; + goto cleanup; + } + } + ret = devpriv->io_function(dev, cmd, i); + if (ret < 0) { + async->events |= COMEDI_CB_ERROR; + goto cleanup; + } + } + s->async->events |= COMEDI_CB_BLOCK; + comedi_event(dev, s); + s->async->events = 0; + } + + cleanup: + + comedi_unlock(devpriv->device, devpriv->subd); + async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + async->events = 0; + devpriv->scan_task_active = 0; + // suspend task until next struct comedi_cmd + rt_task_suspend(devpriv->scan_task); + } +} + +static void timer_task_func(comedi_rt_task_context_t d) +{ + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + 0; + struct comedi_cmd *cmd = &s->async->cmd; + int ret; + unsigned long long n; + + // every struct comedi_cmd causes one execution of while loop + while (1) { + devpriv->rt_task_active = 1; + devpriv->scan_task_active = 1; + devpriv->start = rt_get_time(); + + for (n = 0; n < cmd->stop_arg || cmd->stop_src == TRIG_NONE; + n++) { + // scan timing + if (n) + rt_task_wait_period(); + if (devpriv->scan_task_active == 0) { + goto cleanup; + } + ret = rt_task_make_periodic(devpriv->scan_task, + devpriv->start + devpriv->scan_period * n, + devpriv->convert_period); + if (ret < 0) { + comedi_error(dev, "bug!"); + } + } + + cleanup: + + devpriv->rt_task_active = 0; + // suspend until next struct comedi_cmd + rt_task_suspend(devpriv->rt_task); + } +} + +static int timer_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct comedi_insn xinsn = *insn; + + xinsn.data = data; + xinsn.subdev = devpriv->subd; + + return comedi_do_insn(devpriv->device, &xinsn); +} + +static int cmdtest_helper(struct comedi_cmd * cmd, + unsigned int start_src, + unsigned int scan_begin_src, + unsigned int convert_src, + unsigned int scan_end_src, unsigned int stop_src) +{ + int err = 0; + int tmp; + + tmp = cmd->start_src; + cmd->start_src &= start_src; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= scan_begin_src; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= convert_src; + if (!cmd->convert_src || tmp != cmd->convert_src) + err++; + + tmp = cmd->scan_end_src; + cmd->scan_end_src &= scan_end_src; + if (!cmd->scan_end_src || tmp != cmd->scan_end_src) + err++; + + tmp = cmd->stop_src; + cmd->stop_src &= stop_src; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + return err; +} + +static int timer_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + unsigned int start_src = 0; + + if (s->type == COMEDI_SUBD_AO) + start_src = TRIG_INT; + else + start_src = TRIG_NOW; + + err = cmdtest_helper(cmd, start_src, /* start_src */ + TRIG_TIMER | TRIG_FOLLOW, /* scan_begin_src */ + TRIG_NOW | TRIG_TIMER, /* convert_src */ + TRIG_COUNT, /* scan_end_src */ + TRIG_COUNT | TRIG_NONE); /* stop_src */ + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually + * compatible */ + + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + if (cmd->scan_begin_src == TRIG_FOLLOW + && cmd->convert_src != TRIG_TIMER) + err++; + if (cmd->convert_src == TRIG_NOW && cmd->scan_begin_src != TRIG_TIMER) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + // limit frequency, this is fairly arbitrary + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < SPEED_LIMIT) { + cmd->scan_begin_arg = SPEED_LIMIT; + err++; + } + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < SPEED_LIMIT) { + cmd->convert_arg = SPEED_LIMIT; + err++; + } + } + // make sure conversion and scan frequencies are compatible + if (cmd->convert_src == TRIG_TIMER && cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->convert_arg * cmd->scan_end_arg > cmd->scan_begin_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->scan_end_arg; + err++; + } + } + if (err) + return 3; + + /* step 4: fix up and arguments */ + if (err) + return 4; + + return 0; +} + +static int timer_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int ret; + struct comedi_cmd *cmd = &s->async->cmd; + + /* hack attack: drivers are not supposed to do this: */ + dev->rt = 1; + + // make sure tasks have finished cleanup of last struct comedi_cmd + if (devpriv->rt_task_active || devpriv->scan_task_active) + return -EBUSY; + + ret = comedi_lock(devpriv->device, devpriv->subd); + if (ret < 0) { + comedi_error(dev, "failed to obtain lock"); + return ret; + } + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + devpriv->scan_period = nano2count(cmd->scan_begin_arg); + break; + case TRIG_FOLLOW: + devpriv->scan_period = + nano2count(cmd->convert_arg * cmd->scan_end_arg); + break; + default: + comedi_error(dev, "bug setting scan period!"); + return -1; + break; + } + switch (cmd->convert_src) { + case TRIG_TIMER: + devpriv->convert_period = nano2count(cmd->convert_arg); + break; + case TRIG_NOW: + devpriv->convert_period = 1; + break; + default: + comedi_error(dev, "bug setting conversion period!"); + return -1; + break; + } + + if (cmd->start_src == TRIG_NOW) + return timer_start_cmd(dev, s); + + s->async->inttrig = timer_inttrig; + + return 0; +} + +static int timer_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trig_num) +{ + if (trig_num != 0) + return -EINVAL; + + s->async->inttrig = NULL; + + return timer_start_cmd(dev, s); +} + +static int timer_start_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + RTIME now, delay, period; + int ret; + + devpriv->stop = 0; + s->async->events = 0; + + if (cmd->start_src == TRIG_NOW) + delay = nano2count(cmd->start_arg); + else + delay = 0; + + now = rt_get_time(); + /* Using 'period' this way gets around some weird bug in gcc-2.95.2 + * that generates the compile error 'internal error--unrecognizable insn' + * when rt_task_make_period() is called (observed with rtlinux-3.1, linux-2.2.19). + * - fmhess */ + period = devpriv->scan_period; + ret = rt_task_make_periodic(devpriv->rt_task, now + delay, period); + if (ret < 0) { + comedi_error(dev, "error starting rt_task"); + return ret; + } + return 0; +} + +static int timer_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + struct comedi_subdevice *s, *emul_s; + struct comedi_device *emul_dev; + /* These should probably be devconfig options[] */ + const int timer_priority = 4; + const int scan_priority = timer_priority + 1; + char path[20]; + + printk("comedi%d: timer: ", dev->minor); + + dev->board_name = "timer"; + + if ((ret = alloc_subdevices(dev, 1)) < 0) + return ret; + if ((ret = alloc_private(dev, sizeof(struct timer_private))) < 0) + return ret; + + sprintf(path, "/dev/comedi%d", it->options[0]); + devpriv->device = comedi_open(path); + devpriv->subd = it->options[1]; + + printk("emulating commands for minor %i, subdevice %d\n", + it->options[0], devpriv->subd); + + emul_dev = devpriv->device; + emul_s = emul_dev->subdevices + devpriv->subd; + + // input or output subdevice + s = dev->subdevices + 0; + s->type = emul_s->type; + s->subdev_flags = emul_s->subdev_flags; /* SDF_GROUND (to fool check_driver) */ + s->n_chan = emul_s->n_chan; + s->len_chanlist = 1024; + s->do_cmd = timer_cmd; + s->do_cmdtest = timer_cmdtest; + s->cancel = timer_cancel; + s->maxdata = emul_s->maxdata; + s->range_table = emul_s->range_table; + s->range_table_list = emul_s->range_table_list; + switch (emul_s->type) { + case COMEDI_SUBD_AI: + s->insn_read = timer_insn; + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + devpriv->io_function = timer_data_read; + break; + case COMEDI_SUBD_AO: + s->insn_write = timer_insn; + s->insn_read = timer_insn; + dev->write_subdev = s; + s->subdev_flags |= SDF_CMD_WRITE; + devpriv->io_function = timer_data_write; + break; + case COMEDI_SUBD_DIO: + s->insn_write = timer_insn; + s->insn_read = timer_insn; + s->insn_bits = timer_insn; + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + devpriv->io_function = timer_dio_read; + break; + default: + comedi_error(dev, "failed to determine subdevice type!"); + return -EINVAL; + } + + rt_set_oneshot_mode(); + start_rt_timer(1); + devpriv->timer_running = 1; + + devpriv->rt_task = kzalloc(sizeof(RT_TASK), GFP_KERNEL); + + // initialize real-time tasks + ret = rt_task_init(devpriv->rt_task, timer_task_func, + (comedi_rt_task_context_t) dev, 3000, timer_priority, 0, 0); + if (ret < 0) { + comedi_error(dev, "error initalizing rt_task"); + kfree(devpriv->rt_task); + devpriv->rt_task = 0; + return ret; + } + + devpriv->scan_task = kzalloc(sizeof(RT_TASK), GFP_KERNEL); + + ret = rt_task_init(devpriv->scan_task, scan_task_func, + (comedi_rt_task_context_t) dev, 3000, scan_priority, 0, 0); + if (ret < 0) { + comedi_error(dev, "error initalizing scan_task"); + kfree(devpriv->scan_task); + devpriv->scan_task = 0; + return ret; + } + + return 1; +} + +// free allocated resources +static int timer_detach(struct comedi_device * dev) +{ + printk("comedi%d: timer: remove\n", dev->minor); + + if (devpriv) { + if (devpriv->rt_task) { + rt_task_delete(devpriv->rt_task); + kfree(devpriv->rt_task); + } + if (devpriv->scan_task) { + rt_task_delete(devpriv->scan_task); + kfree(devpriv->scan_task); + } + if (devpriv->timer_running) + stop_rt_timer(); + if (devpriv->device) + comedi_close(devpriv->device); + } + return 0; +} diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index 4b4c37d07482..e679328a4f8f 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -89,13 +89,13 @@ struct waveform_private { unsigned int scan_period; /* scan period in usec */ unsigned int convert_period; /* conversion period in usec */ unsigned timer_running:1; - lsampl_t ao_loopbacks[N_CHANS]; + unsigned int ao_loopbacks[N_CHANS]; }; #define devpriv ((struct waveform_private *)dev->private) -static int waveform_attach(comedi_device *dev, comedi_devconfig *it); -static int waveform_detach(comedi_device *dev); -static comedi_driver driver_waveform = { +static int waveform_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int waveform_detach(struct comedi_device *dev); +static struct comedi_driver driver_waveform = { .driver_name = "comedi_test", .module = THIS_MODULE, .attach = waveform_attach, @@ -107,28 +107,28 @@ static comedi_driver driver_waveform = { COMEDI_INITCLEANUP(driver_waveform); -static int waveform_ai_cmdtest(comedi_device *dev, comedi_subdevice *s, - comedi_cmd *cmd); -static int waveform_ai_cmd(comedi_device *dev, comedi_subdevice *s); -static int waveform_ai_cancel(comedi_device *dev, comedi_subdevice *s); -static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data); -static int waveform_ao_insn_write(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data); -static sampl_t fake_sawtooth(comedi_device *dev, unsigned int range, +static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd); +static int waveform_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s); +static int waveform_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s); +static int waveform_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int waveform_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static short fake_sawtooth(struct comedi_device *dev, unsigned int range, unsigned long current_time); -static sampl_t fake_squarewave(comedi_device *dev, unsigned int range, +static short fake_squarewave(struct comedi_device *dev, unsigned int range, unsigned long current_time); -static sampl_t fake_flatline(comedi_device *dev, unsigned int range, +static short fake_flatline(struct comedi_device *dev, unsigned int range, unsigned long current_time); -static sampl_t fake_waveform(comedi_device *dev, unsigned int channel, +static short fake_waveform(struct comedi_device *dev, unsigned int channel, unsigned int range, unsigned long current_time); /* 1000 nanosec in a microsec */ static const int nano_per_micro = 1000; /* fake analog input ranges */ -static const comedi_lrange waveform_ai_ranges = { +static const struct comedi_lrange waveform_ai_ranges = { 2, { BIP_RANGE(10), @@ -143,9 +143,9 @@ static const comedi_lrange waveform_ai_ranges = { */ static void waveform_ai_interrupt(unsigned long arg) { - comedi_device *dev = (comedi_device *) arg; - comedi_async *async = dev->read_subdev->async; - comedi_cmd *cmd = &async->cmd; + struct comedi_device *dev = (struct comedi_device *) arg; + struct comedi_async *async = dev->read_subdev->async; + struct comedi_cmd *cmd = &async->cmd; unsigned int i, j; /* all times in microsec */ unsigned long elapsed_time; @@ -192,9 +192,9 @@ static void waveform_ai_interrupt(unsigned long arg) comedi_event(dev, dev->read_subdev); } -static int waveform_attach(comedi_device *dev, comedi_devconfig *it) +static int waveform_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - comedi_subdevice *s; + struct comedi_subdevice *s; int amplitude = it->options[0]; int period = it->options[1]; int i; @@ -259,7 +259,7 @@ static int waveform_attach(comedi_device *dev, comedi_devconfig *it) return 1; } -static int waveform_detach(comedi_device *dev) +static int waveform_detach(struct comedi_device *dev) { printk("comedi%d: comedi_test: remove\n", dev->minor); @@ -269,8 +269,8 @@ static int waveform_detach(comedi_device *dev) return 0; } -static int waveform_ai_cmdtest(comedi_device *dev, comedi_subdevice *s, - comedi_cmd *cmd) +static int waveform_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd) { int err = 0; int tmp; @@ -397,9 +397,9 @@ static int waveform_ai_cmdtest(comedi_device *dev, comedi_subdevice *s, return 0; } -static int waveform_ai_cmd(comedi_device *dev, comedi_subdevice *s) +static int waveform_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - comedi_cmd *cmd = &s->async->cmd; + struct comedi_cmd *cmd = &s->async->cmd; if (cmd->flags & TRIG_RT) { comedi_error(dev, @@ -429,20 +429,20 @@ static int waveform_ai_cmd(comedi_device *dev, comedi_subdevice *s) return 0; } -static int waveform_ai_cancel(comedi_device *dev, comedi_subdevice *s) +static int waveform_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { devpriv->timer_running = 0; del_timer(&devpriv->timer); return 0; } -static sampl_t fake_sawtooth(comedi_device *dev, unsigned int range_index, +static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index, unsigned long current_time) { - comedi_subdevice *s = dev->read_subdev; + struct comedi_subdevice *s = dev->read_subdev; unsigned int offset = s->maxdata / 2; u64 value; - const comedi_krange *krange = &s->range_table->range[range_index]; + const struct comedi_krange *krange = &s->range_table->range[range_index]; u64 binary_amplitude; binary_amplitude = s->maxdata; @@ -457,13 +457,13 @@ static sampl_t fake_sawtooth(comedi_device *dev, unsigned int range_index, return offset + value; } -static sampl_t fake_squarewave(comedi_device *dev, unsigned int range_index, +static short fake_squarewave(struct comedi_device *dev, unsigned int range_index, unsigned long current_time) { - comedi_subdevice *s = dev->read_subdev; + struct comedi_subdevice *s = dev->read_subdev; unsigned int offset = s->maxdata / 2; u64 value; - const comedi_krange *krange = &s->range_table->range[range_index]; + const struct comedi_krange *krange = &s->range_table->range[range_index]; current_time %= devpriv->usec_period; value = s->maxdata; @@ -476,14 +476,14 @@ static sampl_t fake_squarewave(comedi_device *dev, unsigned int range_index, return offset + value; } -static sampl_t fake_flatline(comedi_device *dev, unsigned int range_index, +static short fake_flatline(struct comedi_device *dev, unsigned int range_index, unsigned long current_time) { return dev->read_subdev->maxdata / 2; } /* generates a different waveform depending on what channel is read */ -static sampl_t fake_waveform(comedi_device *dev, unsigned int channel, +static short fake_waveform(struct comedi_device *dev, unsigned int channel, unsigned int range, unsigned long current_time) { enum { @@ -504,8 +504,8 @@ static sampl_t fake_waveform(comedi_device *dev, unsigned int channel, return fake_flatline(dev, range, current_time); } -static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int waveform_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int i, chan = CR_CHAN(insn->chanspec); @@ -515,8 +515,8 @@ static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s, return insn->n; } -static int waveform_ao_insn_write(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int waveform_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int i, chan = CR_CHAN(insn->chanspec); diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c new file mode 100644 index 000000000000..1f194a0a45d6 --- /dev/null +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -0,0 +1,230 @@ +/* + comedi/drivers/contec_pci_dio.c + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: contec_pci_dio +Description: Contec PIO1616L digital I/O board +Devices: [Contec] PIO1616L (contec_pci_dio) +Author: Stefano Rivoir +Updated: Wed, 27 Jun 2007 13:00:06 +0100 +Status: works + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. +*/ + +#include "../comedidev.h" + +#include "comedi_pci.h" + +enum contec_model { + PIO1616L = 0, +}; + +struct contec_board { + const char *name; + int model; + int in_ports; + int out_ports; + int in_offs; + int out_offs; + int out_boffs; +}; +static const struct contec_board contec_boards[] = { + {"PIO1616L", PIO1616L, 16, 16, 0, 2, 10}, +}; + +#define PCI_DEVICE_ID_PIO1616L 0x8172 +static DEFINE_PCI_DEVICE_TABLE(contec_pci_table) = { + {PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, PIO1616L}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, contec_pci_table); + +#define thisboard ((const struct contec_board *)dev->board_ptr) + +struct contec_private { + int data; + + struct pci_dev *pci_dev; + +}; + +#define devpriv ((struct contec_private *)dev->private) + +static int contec_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int contec_detach(struct comedi_device * dev); +static struct comedi_driver driver_contec = { + driver_name:"contec_pci_dio", + module:THIS_MODULE, + attach:contec_attach, + detach:contec_detach, +}; + +/* Classic digital IO */ +static int contec_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +#if 0 +static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); + +static int contec_ns_to_timer(unsigned int *ns, int round); +#endif + +static int contec_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct pci_dev *pcidev; + struct comedi_subdevice *s; + + printk("comedi%d: contec: ", dev->minor); + + dev->board_name = thisboard->name; + + if (alloc_private(dev, sizeof(struct contec_private)) < 0) + return -ENOMEM; + + if (alloc_subdevices(dev, 2) < 0) + return -ENOMEM; + + for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pcidev != NULL; + pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { + + if (pcidev->vendor == PCI_VENDOR_ID_CONTEC && + pcidev->device == PCI_DEVICE_ID_PIO1616L) { + if (it->options[0] || it->options[1]) { + /* Check bus and slot. */ + if (it->options[0] != pcidev->bus->number || + it->options[1] != + PCI_SLOT(pcidev->devfn)) { + continue; + } + } + devpriv->pci_dev = pcidev; + if (comedi_pci_enable(pcidev, "contec_pci_dio")) { + printk("error enabling PCI device and request regions!\n"); + return -EIO; + } + dev->iobase = pci_resource_start(pcidev, 0); + printk(" base addr %lx ", dev->iobase); + + dev->board_ptr = contec_boards + 0; + + s = dev->subdevices + 0; + + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = contec_di_insn_bits; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = contec_do_insn_bits; + + printk("attached\n"); + + return 1; + } + } + + printk("card not present!\n"); + + return -EIO; +} + +static int contec_detach(struct comedi_device * dev) +{ + printk("comedi%d: contec: remove\n", dev->minor); + + if (devpriv && devpriv->pci_dev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + + return 0; +} + +#if 0 +static int contec_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + printk("contec_cmdtest called\n"); + return 0; +} + +static int contec_ns_to_timer(unsigned int *ns, int round) +{ + return *ns; +} +#endif + +static int contec_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + printk("contec_do_insn_bits called\n"); + printk(" data: %d %d\n", data[0], data[1]); + + if (insn->n != 2) + return -EINVAL; + + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + rt_printk(" out: %d on %lx\n", s->state, + dev->iobase + thisboard->out_offs); + outw(s->state, dev->iobase + thisboard->out_offs); + } + return 2; +} + +static int contec_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + rt_printk("contec_di_insn_bits called\n"); + rt_printk(" data: %d %d\n", data[0], data[1]); + + if (insn->n != 2) + return -EINVAL; + + data[1] = inw(dev->iobase + thisboard->in_offs); + + return 2; +} + +COMEDI_PCI_INITCLEANUP(driver_contec, contec_pci_table); diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c new file mode 100644 index 000000000000..3b8444f09f28 --- /dev/null +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -0,0 +1,877 @@ +/* + comedi/drivers/daqboard2000.c + hardware driver for IOtech DAQboard/2000 + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999 Anders Blomdell + + 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: daqboard2000 +Description: IOTech DAQBoard/2000 +Author: Anders Blomdell +Status: works +Updated: Mon, 14 Apr 2008 15:28:52 +0100 +Devices: [IOTech] DAQBoard/2000 (daqboard2000) + +Much of the functionality of this driver was determined from reading +the source code for the Windows driver. + +The FPGA on the board requires initialization code, which can +be loaded by comedi_config using the -i +option. The initialization code is available from http://www.comedi.org +in the comedi_nonfree_firmware tarball. + +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. +*/ +/* + This card was obviously never intended to leave the Windows world, + since it lacked all kind of hardware documentation (except for cable + pinouts, plug and pray has something to catch up with yet). + + With some help from our swedish distributor, we got the Windows sourcecode + for the card, and here are the findings so far. + + 1. A good document that describes the PCI interface chip is found at: + http://plx.plxtech.com/download/9080/databook/9080db-106.pdf + + 2. The initialization done so far is: + a. program the FPGA (windows code sans a lot of error messages) + b. + + 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled, + you have to output values to all enabled DAC's until result appears, I + guess that it has something to do with pacer clocks, but the source + gives me no clues. I'll keep it simple so far. + + 4. Analog in. + Each channel in the scanlist seems to be controlled by four + control words: + + Word0: + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! | | | ! | | | ! | | | ! | | | ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Word1: + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! | | | ! | | | ! | | | ! | | | ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | | | | | | + +------+------+ | | | | +-- Digital input (??) + | | | | +---- 10 us settling time + | | | +------ Suspend acquisition (last to scan) + | | +-------- Simultaneous sample and hold + | +---------- Signed data format + +------------------------- Correction offset low + + Word2: + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! | | | ! | | | ! | | | ! | | | ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | | | | | | | | | + +-----+ +--+--+ +++ +++ +--+--+ + | | | | +----- Expansion channel + | | | +----------- Expansion gain + | | +--------------- Channel (low) + | +--------------------- Correction offset high + +----------------------------- Correction gain low + Word3: + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! | | | ! | | | ! | | | ! | | | ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | | | | | | | | + +------+------+ | | +-+-+ | | +-- Low bank enable + | | | | | +---- High bank enable + | | | | +------ Hi/low select + | | | +---------- Gain (1,?,2,4,8,16,32,64) + | | +-------------- differential/single ended + | +---------------- Unipolar + +------------------------- Correction gain high + + + + 999. The card seems to have an incredible amount of capabilities, but + trying to reverse engineer them from the Windows source is beyond my + patience. + + + */ + +#include "../comedidev.h" + +#include + +#include "comedi_pci.h" +#include "8255.h" + +#define DAQBOARD2000_SUBSYSTEM_IDS2 0x00021616 /* Daqboard/2000 - 2 Dacs */ +#define DAQBOARD2000_SUBSYSTEM_IDS4 0x00041616 /* Daqboard/2000 - 4 Dacs */ + +#define DAQBOARD2000_DAQ_SIZE 0x1002 +#define DAQBOARD2000_PLX_SIZE 0x100 + +// Initialization bits for the Serial EEPROM Control Register +#define DAQBOARD2000_SECRProgPinHi 0x8001767e +#define DAQBOARD2000_SECRProgPinLo 0x8000767e +#define DAQBOARD2000_SECRLocalBusHi 0xc000767e +#define DAQBOARD2000_SECRLocalBusLo 0x8000767e +#define DAQBOARD2000_SECRReloadHi 0xa000767e +#define DAQBOARD2000_SECRReloadLo 0x8000767e + +// SECR status bits +#define DAQBOARD2000_EEPROM_PRESENT 0x10000000 + +// CPLD status bits +#define DAQBOARD2000_CPLD_INIT 0x0002 +#define DAQBOARD2000_CPLD_DONE 0x0004 + +// Available ranges +static const struct comedi_lrange range_daqboard2000_ai = { 13, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2.5, 2.5), + RANGE(-1.25, 1.25), + RANGE(-0.625, 0.625), + RANGE(-0.3125, 0.3125), + RANGE(-0.156, 0.156), + RANGE(0, 10), + RANGE(0, 5), + RANGE(0, 2.5), + RANGE(0, 1.25), + RANGE(0, 0.625), + RANGE(0, 0.3125) + } +}; + +static const struct comedi_lrange range_daqboard2000_ao = { 1, { + RANGE(-10, 10) + } +}; + +struct daqboard2000_hw { + volatile u16 acqControl; // 0x00 + volatile u16 acqScanListFIFO; // 0x02 + volatile u32 acqPacerClockDivLow; // 0x04 + + volatile u16 acqScanCounter; // 0x08 + volatile u16 acqPacerClockDivHigh; // 0x0a + volatile u16 acqTriggerCount; // 0x0c + volatile u16 fill2; // 0x0e + volatile u16 acqResultsFIFO; // 0x10 + volatile u16 fill3; // 0x12 + volatile u16 acqResultsShadow; // 0x14 + volatile u16 fill4; // 0x16 + volatile u16 acqAdcResult; // 0x18 + volatile u16 fill5; // 0x1a + volatile u16 dacScanCounter; // 0x1c + volatile u16 fill6; // 0x1e + + volatile u16 dacControl; // 0x20 + volatile u16 fill7; // 0x22 + volatile s16 dacFIFO; // 0x24 + volatile u16 fill8[2]; // 0x26 + volatile u16 dacPacerClockDiv; // 0x2a + volatile u16 refDacs; // 0x2c + volatile u16 fill9; // 0x2e + + volatile u16 dioControl; // 0x30 + volatile s16 dioP3hsioData; // 0x32 + volatile u16 dioP3Control; // 0x34 + volatile u16 calEepromControl; // 0x36 + volatile s16 dacSetting[4]; // 0x38 + volatile s16 dioP2ExpansionIO8Bit[32]; // 0x40 + + volatile u16 ctrTmrControl; // 0x80 + volatile u16 fill10[3]; // 0x82 + volatile s16 ctrInput[4]; // 0x88 + volatile u16 fill11[8]; // 0x90 + volatile u16 timerDivisor[2]; // 0xa0 + volatile u16 fill12[6]; // 0xa4 + + volatile u16 dmaControl; // 0xb0 + volatile u16 trigControl; // 0xb2 + volatile u16 fill13[2]; // 0xb4 + volatile u16 calEeprom; // 0xb8 + volatile u16 acqDigitalMark; // 0xba + volatile u16 trigDacs; // 0xbc + volatile u16 fill14; // 0xbe + volatile s16 dioP2ExpansionIO16Bit[32]; // 0xc0 +}; + +/* Scan Sequencer programming */ +#define DAQBOARD2000_SeqStartScanList 0x0011 +#define DAQBOARD2000_SeqStopScanList 0x0010 + +// Prepare for acquisition +#define DAQBOARD2000_AcqResetScanListFifo 0x0004 +#define DAQBOARD2000_AcqResetResultsFifo 0x0002 +#define DAQBOARD2000_AcqResetConfigPipe 0x0001 + +// Acqusition status bits +#define DAQBOARD2000_AcqResultsFIFOMore1Sample 0x0001 +#define DAQBOARD2000_AcqResultsFIFOHasValidData 0x0002 +#define DAQBOARD2000_AcqResultsFIFOOverrun 0x0004 +#define DAQBOARD2000_AcqLogicScanning 0x0008 +#define DAQBOARD2000_AcqConfigPipeFull 0x0010 +#define DAQBOARD2000_AcqScanListFIFOEmpty 0x0020 +#define DAQBOARD2000_AcqAdcNotReady 0x0040 +#define DAQBOARD2000_ArbitrationFailure 0x0080 +#define DAQBOARD2000_AcqPacerOverrun 0x0100 +#define DAQBOARD2000_DacPacerOverrun 0x0200 +#define DAQBOARD2000_AcqHardwareError 0x01c0 + +// Scan Sequencer programming +#define DAQBOARD2000_SeqStartScanList 0x0011 +#define DAQBOARD2000_SeqStopScanList 0x0010 + +/* Pacer Clock Control */ +#define DAQBOARD2000_AdcPacerInternal 0x0030 +#define DAQBOARD2000_AdcPacerExternal 0x0032 +#define DAQBOARD2000_AdcPacerEnable 0x0031 +#define DAQBOARD2000_AdcPacerEnableDacPacer 0x0034 +#define DAQBOARD2000_AdcPacerDisable 0x0030 +#define DAQBOARD2000_AdcPacerNormalMode 0x0060 +#define DAQBOARD2000_AdcPacerCompatibilityMode 0x0061 +#define DAQBOARD2000_AdcPacerInternalOutEnable 0x0008 +#define DAQBOARD2000_AdcPacerExternalRising 0x0100 + +// DAC status +#define DAQBOARD2000_DacFull 0x0001 +#define DAQBOARD2000_RefBusy 0x0002 +#define DAQBOARD2000_TrgBusy 0x0004 +#define DAQBOARD2000_CalBusy 0x0008 +#define DAQBOARD2000_Dac0Busy 0x0010 +#define DAQBOARD2000_Dac1Busy 0x0020 +#define DAQBOARD2000_Dac2Busy 0x0040 +#define DAQBOARD2000_Dac3Busy 0x0080 + +// DAC control +#define DAQBOARD2000_Dac0Enable 0x0021 +#define DAQBOARD2000_Dac1Enable 0x0031 +#define DAQBOARD2000_Dac2Enable 0x0041 +#define DAQBOARD2000_Dac3Enable 0x0051 +#define DAQBOARD2000_DacEnableBit 0x0001 +#define DAQBOARD2000_Dac0Disable 0x0020 +#define DAQBOARD2000_Dac1Disable 0x0030 +#define DAQBOARD2000_Dac2Disable 0x0040 +#define DAQBOARD2000_Dac3Disable 0x0050 +#define DAQBOARD2000_DacResetFifo 0x0004 +#define DAQBOARD2000_DacPatternDisable 0x0060 +#define DAQBOARD2000_DacPatternEnable 0x0061 +#define DAQBOARD2000_DacSelectSignedData 0x0002 +#define DAQBOARD2000_DacSelectUnsignedData 0x0000 + +/* Trigger Control */ +#define DAQBOARD2000_TrigAnalog 0x0000 +#define DAQBOARD2000_TrigTTL 0x0010 +#define DAQBOARD2000_TrigTransHiLo 0x0004 +#define DAQBOARD2000_TrigTransLoHi 0x0000 +#define DAQBOARD2000_TrigAbove 0x0000 +#define DAQBOARD2000_TrigBelow 0x0004 +#define DAQBOARD2000_TrigLevelSense 0x0002 +#define DAQBOARD2000_TrigEdgeSense 0x0000 +#define DAQBOARD2000_TrigEnable 0x0001 +#define DAQBOARD2000_TrigDisable 0x0000 + +// Reference Dac Selection +#define DAQBOARD2000_PosRefDacSelect 0x0100 +#define DAQBOARD2000_NegRefDacSelect 0x0000 + +static int daqboard2000_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int daqboard2000_detach(struct comedi_device * dev); + +static struct comedi_driver driver_daqboard2000 = { + driver_name:"daqboard2000", + module:THIS_MODULE, + attach:daqboard2000_attach, + detach:daqboard2000_detach, +}; + +struct daq200_boardtype { + const char *name; + int id; +}; +static const struct daq200_boardtype boardtypes[] = { + {"ids2", DAQBOARD2000_SUBSYSTEM_IDS2}, + {"ids4", DAQBOARD2000_SUBSYSTEM_IDS4}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct daq200_boardtype)) +#define this_board ((const struct daq200_boardtype *)dev->board_ptr) + +static DEFINE_PCI_DEVICE_TABLE(daqboard2000_pci_table) = { + {0x1616, 0x0409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, daqboard2000_pci_table); + +struct daqboard2000_private { + enum { + card_daqboard_2000 + } card; + struct pci_dev *pci_dev; + void *daq; + void *plx; + int got_regions; + unsigned int ao_readback[2]; +}; + +#define devpriv ((struct daqboard2000_private *)dev->private) + +static void writeAcqScanListEntry(struct comedi_device * dev, u16 entry) +{ + struct daqboard2000_hw *fpga = devpriv->daq; + +// comedi_udelay(4); + fpga->acqScanListFIFO = entry & 0x00ff; +// comedi_udelay(4); + fpga->acqScanListFIFO = (entry >> 8) & 0x00ff; +} + +static void setup_sampling(struct comedi_device * dev, int chan, int gain) +{ + u16 word0, word1, word2, word3; + + /* Channel 0-7 diff, channel 8-23 single ended */ + word0 = 0; + word1 = 0x0004; /* Last scan */ + word2 = (chan << 6) & 0x00c0; + switch (chan / 4) { + case 0: + word3 = 0x0001; + break; + case 1: + word3 = 0x0002; + break; + case 2: + word3 = 0x0005; + break; + case 3: + word3 = 0x0006; + break; + case 4: + word3 = 0x0041; + break; + case 5: + word3 = 0x0042; + break; + default: + word3 = 0; + break; + } +/* + dev->eeprom.correctionDACSE[i][j][k].offset = 0x800; + dev->eeprom.correctionDACSE[i][j][k].gain = 0xc00; +*/ + /* These should be read from EEPROM */ + word2 |= 0x0800; + word3 |= 0xc000; +/* printk("%d %4.4x %4.4x %4.4x %4.4x\n", chan, word0, word1, word2, word3);*/ + writeAcqScanListEntry(dev, word0); + writeAcqScanListEntry(dev, word1); + writeAcqScanListEntry(dev, word2); + writeAcqScanListEntry(dev, word3); +} + +static int daqboard2000_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + struct daqboard2000_hw *fpga = devpriv->daq; + int gain, chan, timeout; + + fpga->acqControl = + DAQBOARD2000_AcqResetScanListFifo | + DAQBOARD2000_AcqResetResultsFifo | + DAQBOARD2000_AcqResetConfigPipe; + + /* If pacer clock is not set to some high value (> 10 us), we + risk multiple samples to be put into the result FIFO. */ + fpga->acqPacerClockDivLow = 1000000; /* 1 second, should be long enough */ + fpga->acqPacerClockDivHigh = 0; + + gain = CR_RANGE(insn->chanspec); + chan = CR_CHAN(insn->chanspec); + + /* This doesn't look efficient. I decided to take the conservative + * approach when I did the insn conversion. Perhaps it would be + * better to have broken it completely, then someone would have been + * forced to fix it. --ds */ + for (i = 0; i < insn->n; i++) { + setup_sampling(dev, chan, gain); + /* Enable reading from the scanlist FIFO */ + fpga->acqControl = DAQBOARD2000_SeqStartScanList; + for (timeout = 0; timeout < 20; timeout++) { + if (fpga->acqControl & DAQBOARD2000_AcqConfigPipeFull) { + break; + } + //comedi_udelay(2); + } + fpga->acqControl = DAQBOARD2000_AdcPacerEnable; + for (timeout = 0; timeout < 20; timeout++) { + if (fpga->acqControl & DAQBOARD2000_AcqLogicScanning) { + break; + } + //comedi_udelay(2); + } + for (timeout = 0; timeout < 20; timeout++) { + if (fpga-> + acqControl & + DAQBOARD2000_AcqResultsFIFOHasValidData) { + break; + } + //comedi_udelay(2); + } + data[i] = fpga->acqResultsFIFO; + fpga->acqControl = DAQBOARD2000_AdcPacerDisable; + fpga->acqControl = DAQBOARD2000_SeqStopScanList; + } + + return i; +} + +static int daqboard2000_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +static int daqboard2000_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + struct daqboard2000_hw *fpga = devpriv->daq; + int timeout; + + for (i = 0; i < insn->n; i++) { + /* + * OK, since it works OK without enabling the DAC's, let's keep + * it as simple as possible... + */ + //fpga->dacControl = (chan + 2) * 0x0010 | 0x0001; comedi_udelay(1000); + fpga->dacSetting[chan] = data[i]; + for (timeout = 0; timeout < 20; timeout++) { + if ((fpga->dacControl & ((chan + 1) * 0x0010)) == 0) { + break; + } + //comedi_udelay(2); + } + devpriv->ao_readback[chan] = data[i]; + /* + * Since we never enabled the DAC's, we don't need to disable it... + * fpga->dacControl = (chan + 2) * 0x0010 | 0x0000; comedi_udelay(1000); + */ + } + + return i; +} + +static void daqboard2000_resetLocalBus(struct comedi_device * dev) +{ + printk("daqboard2000_resetLocalBus\n"); + writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c); + comedi_udelay(10000); + writel(DAQBOARD2000_SECRLocalBusLo, devpriv->plx + 0x6c); + comedi_udelay(10000); +} + +static void daqboard2000_reloadPLX(struct comedi_device * dev) +{ + printk("daqboard2000_reloadPLX\n"); + writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); + comedi_udelay(10000); + writel(DAQBOARD2000_SECRReloadHi, devpriv->plx + 0x6c); + comedi_udelay(10000); + writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); + comedi_udelay(10000); +} + +static void daqboard2000_pulseProgPin(struct comedi_device * dev) +{ + printk("daqboard2000_pulseProgPin 1\n"); + writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c); + comedi_udelay(10000); + writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c); + comedi_udelay(10000); /* Not in the original code, but I like symmetry... */ +} + +static int daqboard2000_pollCPLD(struct comedi_device * dev, int mask) +{ + int result = 0; + int i; + int cpld; + + /* timeout after 50 tries -> 5ms */ + for (i = 0; i < 50; i++) { + cpld = readw(devpriv->daq + 0x1000); + if ((cpld & mask) == mask) { + result = 1; + break; + } + comedi_udelay(100); + } + comedi_udelay(5); + return result; +} + +static int daqboard2000_writeCPLD(struct comedi_device * dev, int data) +{ + int result = 0; + + comedi_udelay(10); + writew(data, devpriv->daq + 0x1000); + if ((readw(devpriv->daq + 0x1000) & DAQBOARD2000_CPLD_INIT) == + DAQBOARD2000_CPLD_INIT) { + result = 1; + } + return result; +} + +static int initialize_daqboard2000(struct comedi_device * dev, + unsigned char *cpld_array, int len) +{ + int result = -EIO; + /* Read the serial EEPROM control register */ + int secr; + int retry; + int i; + + /* Check to make sure the serial eeprom is present on the board */ + secr = readl(devpriv->plx + 0x6c); + if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) { +#ifdef DEBUG_EEPROM + printk("no serial eeprom\n"); +#endif + return -EIO; + } + + for (retry = 0; retry < 3; retry++) { +#ifdef DEBUG_EEPROM + printk("Programming EEPROM try %x\n", retry); +#endif + + daqboard2000_resetLocalBus(dev); + daqboard2000_reloadPLX(dev); + daqboard2000_pulseProgPin(dev); + if (daqboard2000_pollCPLD(dev, DAQBOARD2000_CPLD_INIT)) { + for (i = 0; i < len; i++) { + if (cpld_array[i] == 0xff + && cpld_array[i + 1] == 0x20) { +#ifdef DEBUG_EEPROM + printk("Preamble found at %d\n", i); +#endif + break; + } + } + for (; i < len; i += 2) { + int data = + (cpld_array[i] << 8) + cpld_array[i + + 1]; + if (!daqboard2000_writeCPLD(dev, data)) { + break; + } + } + if (i >= len) { +#ifdef DEBUG_EEPROM + printk("Programmed\n"); +#endif + daqboard2000_resetLocalBus(dev); + daqboard2000_reloadPLX(dev); + result = 0; + break; + } + } + } + return result; +} + +static void daqboard2000_adcStopDmaTransfer(struct comedi_device * dev) +{ +/* printk("Implement: daqboard2000_adcStopDmaTransfer\n");*/ +} + +static void daqboard2000_adcDisarm(struct comedi_device * dev) +{ + struct daqboard2000_hw *fpga = devpriv->daq; + + /* Disable hardware triggers */ + comedi_udelay(2); + fpga->trigControl = DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable; + comedi_udelay(2); + fpga->trigControl = DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable; + + /* Stop the scan list FIFO from loading the configuration pipe */ + comedi_udelay(2); + fpga->acqControl = DAQBOARD2000_SeqStopScanList; + + /* Stop the pacer clock */ + comedi_udelay(2); + fpga->acqControl = DAQBOARD2000_AdcPacerDisable; + + /* Stop the input dma (abort channel 1) */ + daqboard2000_adcStopDmaTransfer(dev); +} + +static void daqboard2000_activateReferenceDacs(struct comedi_device * dev) +{ + struct daqboard2000_hw *fpga = devpriv->daq; + int timeout; + + // Set the + reference dac value in the FPGA + fpga->refDacs = 0x80 | DAQBOARD2000_PosRefDacSelect; + for (timeout = 0; timeout < 20; timeout++) { + if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) { + break; + } + comedi_udelay(2); + } +/* printk("DAQBOARD2000_PosRefDacSelect %d\n", timeout);*/ + + // Set the - reference dac value in the FPGA + fpga->refDacs = 0x80 | DAQBOARD2000_NegRefDacSelect; + for (timeout = 0; timeout < 20; timeout++) { + if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) { + break; + } + comedi_udelay(2); + } +/* printk("DAQBOARD2000_NegRefDacSelect %d\n", timeout);*/ +} + +static void daqboard2000_initializeCtrs(struct comedi_device * dev) +{ +/* printk("Implement: daqboard2000_initializeCtrs\n");*/ +} + +static void daqboard2000_initializeTmrs(struct comedi_device * dev) +{ +/* printk("Implement: daqboard2000_initializeTmrs\n");*/ +} + +static void daqboard2000_dacDisarm(struct comedi_device * dev) +{ +/* printk("Implement: daqboard2000_dacDisarm\n");*/ +} + +static void daqboard2000_initializeAdc(struct comedi_device * dev) +{ + daqboard2000_adcDisarm(dev); + daqboard2000_activateReferenceDacs(dev); + daqboard2000_initializeCtrs(dev); + daqboard2000_initializeTmrs(dev); +} + +static void daqboard2000_initializeDac(struct comedi_device * dev) +{ + daqboard2000_dacDisarm(dev); +} + +/* +The test command, REMOVE!!: + +rmmod daqboard2000 ; rmmod comedi; make install ; modprobe daqboard2000; /usr/sbin/comedi_config /dev/comedi0 daqboard/2000 ; tail -40 /var/log/messages +*/ + +static int daqboard2000_8255_cb(int dir, int port, int data, + unsigned long ioaddr) +{ + int result = 0; + if (dir) { + writew(data, ((void *)ioaddr) + port * 2); + result = 0; + } else { + result = readw(((void *)ioaddr) + port * 2); + } +/* + printk("daqboard2000_8255_cb %x %d %d %2.2x -> %2.2x\n", + arg, dir, port, data, result); +*/ + return result; +} + +static int daqboard2000_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int result = 0; + struct comedi_subdevice *s; + struct pci_dev *card = NULL; + void *aux_data; + unsigned int aux_len; + int bus, slot; + + printk("comedi%d: daqboard2000:", dev->minor); + + bus = it->options[0]; + slot = it->options[1]; + + result = alloc_private(dev, sizeof(struct daqboard2000_private)); + if (result < 0) { + return -ENOMEM; + } + for (card = pci_get_device(0x1616, 0x0409, NULL); + card != NULL; + card = pci_get_device(0x1616, 0x0409, card)) { + if (bus || slot) { + /* requested particular bus/slot */ + if (card->bus->number != bus || + PCI_SLOT(card->devfn) != slot) { + continue; + } + } + break; /* found one */ + } + if (!card) { + if (bus || slot) + printk(" no daqboard2000 found at bus/slot: %d/%d\n", + bus, slot); + else + printk(" no daqboard2000 found\n"); + return -EIO; + } else { + u32 id; + int i; + devpriv->pci_dev = card; + id = ((u32) card->subsystem_device << 16) | card-> + subsystem_vendor; + for (i = 0; i < n_boardtypes; i++) { + if (boardtypes[i].id == id) { + printk(" %s", boardtypes[i].name); + dev->board_ptr = boardtypes + i; + } + } + if (!dev->board_ptr) { + printk(" unknown subsystem id %08x (pretend it is an ids2)", id); + dev->board_ptr = boardtypes; + } + } + + if ((result = comedi_pci_enable(card, "daqboard2000")) < 0) { + printk(" failed to enable PCI device and request regions\n"); + return -EIO; + } + devpriv->got_regions = 1; + devpriv->plx = + ioremap(pci_resource_start(card, 0), DAQBOARD2000_PLX_SIZE); + devpriv->daq = + ioremap(pci_resource_start(card, 2), DAQBOARD2000_DAQ_SIZE); + if (!devpriv->plx || !devpriv->daq) { + return -ENOMEM; + } + + result = alloc_subdevices(dev, 3); + if (result < 0) + goto out; + + readl(devpriv->plx + 0x6c); + + /* + u8 interrupt; + Windows code does restore interrupts, but since we don't use them... + pci_read_config_byte(card, PCI_INTERRUPT_LINE, &interrupt); + printk("Interrupt before is: %x\n", interrupt); + */ + + aux_data = comedi_aux_data(it->options, 0); + aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; + + if (aux_data && aux_len) { + result = initialize_daqboard2000(dev, aux_data, aux_len); + } else { + printk("no FPGA initialization code, aborting\n"); + result = -EIO; + } + if (result < 0) + goto out; + daqboard2000_initializeAdc(dev); + daqboard2000_initializeDac(dev); + /* + Windows code does restore interrupts, but since we don't use them... + pci_read_config_byte(card, PCI_INTERRUPT_LINE, &interrupt); + printk("Interrupt after is: %x\n", interrupt); + */ + + dev->iobase = (unsigned long)devpriv->daq; + + dev->board_name = this_board->name; + + s = dev->subdevices + 0; + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 24; + s->maxdata = 0xffff; + s->insn_read = daqboard2000_ai_insn_read; + s->range_table = &range_daqboard2000_ai; + + s = dev->subdevices + 1; + /* ao subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->maxdata = 0xffff; + s->insn_read = daqboard2000_ao_insn_read; + s->insn_write = daqboard2000_ao_insn_write; + s->range_table = &range_daqboard2000_ao; + + s = dev->subdevices + 2; + result = subdev_8255_init(dev, s, daqboard2000_8255_cb, + (unsigned long)(dev->iobase + 0x40)); + + printk("\n"); + out: + return result; +} + +static int daqboard2000_detach(struct comedi_device * dev) +{ + printk("comedi%d: daqboard2000: remove\n", dev->minor); + + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 2); + + if (dev->irq) { + free_irq(dev->irq, dev); + } + if (devpriv) { + if (devpriv->daq) + iounmap(devpriv->daq); + if (devpriv->plx) + iounmap(devpriv->plx); + if (devpriv->pci_dev) { + if (devpriv->got_regions) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + } + return 0; +} + +COMEDI_PCI_INITCLEANUP(driver_daqboard2000, daqboard2000_pci_table); diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c new file mode 100644 index 000000000000..e4563331e963 --- /dev/null +++ b/drivers/staging/comedi/drivers/das08.c @@ -0,0 +1,1068 @@ +/* + comedi/drivers/das08.c + DAS08 driver + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + Copyright (C) 2001,2002,2003 Frank Mori Hess + Copyright (C) 2004 Salvador E. Tropea + + 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: das08 +Description: DAS-08 compatible boards +Author: Warren Jasper, ds, Frank Hess +Devices: [Keithley Metrabyte] DAS08 (isa-das08), [ComputerBoards] DAS08 (isa-das08), + DAS08-PGM (das08-pgm), + DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh), + DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao), + DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (das08), + PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16) +Status: works + +This is a rewrite of the das08 and das08jr drivers. + +Options (for ISA cards): + [0] - base io address + +Options (for pci-das08): + [0] - bus (optional) + [1] = slot (optional) + +The das08 driver doesn't support asynchronous commands, since +the cheap das08 hardware doesn't really support them. The +comedi_rt_timer driver can be used to emulate commands for this +driver. +*/ + +#include "../comedidev.h" + +#include + +#include "comedi_pci.h" +#include "8255.h" +#include "das08.h" + +#define DRV_NAME "das08" + +#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307 +#define PCI_DEVICE_ID_PCIDAS08 0x29 +#define PCIDAS08_SIZE 0x54 + +// pci configuration registers +#define INTCSR 0x4c +#define INTR1_ENABLE 0x1 +#define INTR1_HIGH_POLARITY 0x2 +#define PCI_INTR_ENABLE 0x40 +#define INTR1_EDGE_TRIG 0x100 // requires high polarity +#define CNTRL 0x50 +#define CNTRL_DIR 0x2 +#define CNTRL_INTR 0x4 + +/* + cio-das08.pdf + + "isa-das08" + + 0 a/d bits 0-3 start 8 bit + 1 a/d bits 4-11 start 12 bit + 2 eoc, ip1-3, irq, mux op1-4, inte, mux + 3 unused unused + 4567 8254 + 89ab 8255 + + requires hard-wiring for async ai + +*/ + +#define DAS08_LSB 0 +#define DAS08_MSB 1 +#define DAS08_TRIG_12BIT 1 +#define DAS08_STATUS 2 +#define DAS08_EOC (1<<7) +#define DAS08_IRQ (1<<3) +#define DAS08_IP(x) (((x)>>4)&0x7) +#define DAS08_CONTROL 2 +#define DAS08_MUX_MASK 0x7 +#define DAS08_MUX(x) ((x) & DAS08_MUX_MASK) +#define DAS08_INTE (1<<3) +#define DAS08_DO_MASK 0xf0 +#define DAS08_OP(x) (((x) << 4) & DAS08_DO_MASK) + +/* + cio-das08jr.pdf + + "das08/jr-ao" + + 0 a/d bits 0-3 unused + 1 a/d bits 4-11 start 12 bit + 2 eoc, mux mux + 3 di do + 4 unused ao0_lsb + 5 unused ao0_msb + 6 unused ao1_lsb + 7 unused ao1_msb + +*/ + +#define DAS08JR_DIO 3 +#define DAS08JR_AO_LSB(x) ((x)?6:4) +#define DAS08JR_AO_MSB(x) ((x)?7:5) + +/* + cio-das08_aox.pdf + + "das08-aoh" + "das08-aol" + "das08-aom" + + 0 a/d bits 0-3 start 8 bit + 1 a/d bits 4-11 start 12 bit + 2 eoc, ip1-3, irq, mux op1-4, inte, mux + 3 mux, gain status gain control + 4567 8254 + 8 unused ao0_lsb + 9 unused ao0_msb + a unused ao1_lsb + b unused ao1_msb + 89ab + cdef 8255 +*/ + +#define DAS08AO_GAIN_CONTROL 3 +#define DAS08AO_GAIN_STATUS 3 + +#define DAS08AO_AO_LSB(x) ((x)?0xa:8) +#define DAS08AO_AO_MSB(x) ((x)?0xb:9) +#define DAS08AO_AO_UPDATE 8 + +/* gainlist same as _pgx_ below */ + +static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das08ao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static void i8254_set_mode_low(unsigned int base, int channel, + unsigned int mode); + +static const struct comedi_lrange range_das08_pgl = { 9, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; +static const struct comedi_lrange range_das08_pgh = { 12, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(1), + BIP_RANGE(0.5), + BIP_RANGE(0.1), + BIP_RANGE(0.05), + BIP_RANGE(0.01), + BIP_RANGE(0.005), + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01), + } +}; +static const struct comedi_lrange range_das08_pgm = { 9, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.01), + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01) + } +}; /* + cio-das08jr.pdf + + "das08/jr-ao" + + 0 a/d bits 0-3 unused + 1 a/d bits 4-11 start 12 bit + 2 eoc, mux mux + 3 di do + 4 unused ao0_lsb + 5 unused ao0_msb + 6 unused ao1_lsb + 7 unused ao1_msb + + */ + +static const struct comedi_lrange *const das08_ai_lranges[] = { + &range_unknown, + &range_bipolar5, + &range_das08_pgh, + &range_das08_pgl, + &range_das08_pgm, +}; + +static const int das08_pgh_gainlist[] = + { 8, 0, 10, 2, 12, 4, 14, 6, 1, 3, 5, 7 }; +static const int das08_pgl_gainlist[] = { 8, 0, 2, 4, 6, 1, 3, 5, 7 }; +static const int das08_pgm_gainlist[] = { 8, 0, 10, 12, 14, 9, 11, 13, 15 }; + +static const int *const das08_gainlists[] = { + NULL, + NULL, + das08_pgh_gainlist, + das08_pgl_gainlist, + das08_pgm_gainlist, +}; + +static const struct das08_board_struct das08_boards[] = { + { + name: "isa-das08", // cio-das08.pdf + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_pg_none, + ai_encoding:das08_encode12, + ao: NULL, + ao_nbits:12, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:4, + i8255_offset:8, + i8254_offset:4, + iosize: 16, // unchecked + }, + { + name: "das08-pgm", // cio-das08pgx.pdf + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_pgm, + ai_encoding:das08_encode12, + ao: NULL, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:4, + i8255_offset:0, + i8254_offset:0x04, + iosize: 16, // unchecked + }, + { + name: "das08-pgh", // cio-das08pgx.pdf + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_pgh, + ai_encoding:das08_encode12, + ao: NULL, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:4, + i8255_offset:0, + i8254_offset:0x04, + iosize: 16, // unchecked + }, + { + name: "das08-pgl", // cio-das08pgx.pdf + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_pgl, + ai_encoding:das08_encode12, + ao: NULL, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:4, + i8255_offset:0, + i8254_offset:0x04, + iosize: 16, // unchecked + }, + { + name: "das08-aoh", // cio-das08_aox.pdf + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_pgh, + ai_encoding:das08_encode12, + ao: das08ao_ao_winsn, // 8 + ao_nbits:12, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:4, + i8255_offset:0x0c, + i8254_offset:0x04, + iosize: 16, // unchecked + }, + { + name: "das08-aol", // cio-das08_aox.pdf + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_pgl, + ai_encoding:das08_encode12, + ao: das08ao_ao_winsn, // 8 + ao_nbits:12, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:4, + i8255_offset:0x0c, + i8254_offset:0x04, + iosize: 16, // unchecked + }, + { + name: "das08-aom", // cio-das08_aox.pdf + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_pgm, + ai_encoding:das08_encode12, + ao: das08ao_ao_winsn, // 8 + ao_nbits:12, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:4, + i8255_offset:0x0c, + i8254_offset:0x04, + iosize: 16, // unchecked + }, + { + name: "das08/jr-ao", // cio-das08-jr-ao.pdf + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_pg_none, + ai_encoding:das08_encode12, + ao: das08jr_ao_winsn, + ao_nbits:12, + di: das08jr_di_rbits, + do_: das08jr_do_wbits, + do_nchan:8, + i8255_offset:0, + i8254_offset:0, + iosize: 16, // unchecked + }, + { + name: "das08jr-16-ao", // cio-das08jr-16-ao.pdf + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:16, + ai_pg: das08_pg_none, + ai_encoding:das08_encode12, + ao: das08jr_ao_winsn, + ao_nbits:16, + di: das08jr_di_rbits, + do_: das08jr_do_wbits, + do_nchan:8, + i8255_offset:0, + i8254_offset:0x04, + iosize: 16, // unchecked + }, +#ifdef CONFIG_COMEDI_PCI + { + name: "das08", // pci-das08 + id: PCI_DEVICE_ID_PCIDAS08, + bustype: pci, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_bipolar5, + ai_encoding:das08_encode12, + ao: NULL, + ao_nbits:0, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:4, + i8255_offset:0, + i8254_offset:4, + iosize: 8, + }, +#endif + { + name: "pc104-das08", + bustype: pc104, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_pg_none, + ai_encoding:das08_encode12, + ao: NULL, + ao_nbits:0, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:4, + i8255_offset:0, + i8254_offset:4, + iosize: 16, // unchecked + }, +#if 0 + { + name: "das08/f", + }, + { + name: "das08jr", + }, +#endif + { + name: "das08jr/16", + bustype: isa, + ai: das08_ai_rinsn, + ai_nbits:16, + ai_pg: das08_pg_none, + ai_encoding:das08_encode16, + ao: NULL, + ao_nbits:0, + di: das08jr_di_rbits, + do_: das08jr_do_wbits, + do_nchan:8, + i8255_offset:0, + i8254_offset:0, + iosize: 16, // unchecked + }, +#if 0 + { + name: "das48-pga", // cio-das48-pga.pdf + }, + { + name: "das08-pga-g2", // a KM board + }, +#endif +}; + +#ifdef CONFIG_COMEDI_PCMCIA +struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS] = { + { + name: "pcm-das08", + id: 0x0, // XXX + bustype: pcmcia, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_bipolar5, + ai_encoding:das08_pcm_encode12, + ao: NULL, + ao_nbits:0, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:3, + i8255_offset:0, + i8254_offset:0, + iosize: 16, + }, + // duplicate so driver name can be used also + { + name: "das08_cs", + id: 0x0, // XXX + bustype: pcmcia, + ai: das08_ai_rinsn, + ai_nbits:12, + ai_pg: das08_bipolar5, + ai_encoding:das08_pcm_encode12, + ao: NULL, + ao_nbits:0, + di: das08_di_rbits, + do_: das08_do_wbits, + do_nchan:3, + i8255_offset:0, + i8254_offset:0, + iosize: 16, + }, +}; +#endif + +#ifdef CONFIG_COMEDI_PCI +static DEFINE_PCI_DEVICE_TABLE(das08_pci_table) = { + {PCI_VENDOR_ID_COMPUTERBOARDS, PCI_DEVICE_ID_PCIDAS08, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, das08_pci_table); +#endif + +#define devpriv ((struct das08_private_struct *)dev->private) +#define thisboard ((const struct das08_board_struct *)dev->board_ptr) + +#define TIMEOUT 100000 + +static int das08_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, n; + int chan; + int range; + int lsb, msb; + + chan = CR_CHAN(insn->chanspec); + range = CR_RANGE(insn->chanspec); + + /* clear crap */ + inb(dev->iobase + DAS08_LSB); + inb(dev->iobase + DAS08_MSB); + + /* set multiplexer */ + spin_lock(&dev->spinlock); // lock to prevent race with digital output + devpriv->do_mux_bits &= ~DAS08_MUX_MASK; + devpriv->do_mux_bits |= DAS08_MUX(chan); + outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); + spin_unlock(&dev->spinlock); + + if (s->range_table->length > 1) { + /* set gain/range */ + range = CR_RANGE(insn->chanspec); + outb(devpriv->pg_gainlist[range], + dev->iobase + DAS08AO_GAIN_CONTROL); + } + + for (n = 0; n < insn->n; n++) { + /* clear over-range bits for 16-bit boards */ + if (thisboard->ai_nbits == 16) + if (inb(dev->iobase + DAS08_MSB) & 0x80) + rt_printk("das08: over-range\n"); + + /* trigger conversion */ + outb_p(0, dev->iobase + DAS08_TRIG_12BIT); + + for (i = 0; i < TIMEOUT; i++) { + if (!(inb(dev->iobase + DAS08_STATUS) & DAS08_EOC)) + break; + } + if (i == TIMEOUT) { + rt_printk("das08: timeout\n"); + return -ETIME; + } + msb = inb(dev->iobase + DAS08_MSB); + lsb = inb(dev->iobase + DAS08_LSB); + if (thisboard->ai_encoding == das08_encode12) { + data[n] = (lsb >> 4) | (msb << 4); + } else if (thisboard->ai_encoding == das08_pcm_encode12) { + data[n] = (msb << 8) + lsb; + } else if (thisboard->ai_encoding == das08_encode16) { + /* FPOS 16-bit boards are sign-magnitude */ + if (msb & 0x80) + data[n] = (1 << 15) | lsb | ((msb & 0x7f) << 8); + else + data[n] = (1 << 15) - (lsb | (msb & 0x7f) << 8); + } else { + comedi_error(dev, "bug! unknown ai encoding"); + return -1; + } + } + + return n; +} + +static int das08_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = 0; + data[1] = DAS08_IP(inb(dev->iobase + DAS08_STATUS)); + + return 2; +} + +static int das08_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int wbits; + + // get current settings of digital output lines + wbits = (devpriv->do_mux_bits >> 4) & 0xf; + // null bits we are going to set + wbits &= ~data[0]; + // set new bit values + wbits |= data[0] & data[1]; + // remember digital output bits + spin_lock(&dev->spinlock); // prevent race with setting of analog input mux + devpriv->do_mux_bits &= ~DAS08_DO_MASK; + devpriv->do_mux_bits |= DAS08_OP(wbits); + outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); + spin_unlock(&dev->spinlock); + + data[1] = wbits; + + return 2; +} + +static int das08jr_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = 0; + data[1] = inb(dev->iobase + DAS08JR_DIO); + + return 2; +} + +static int das08jr_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + // null bits we are going to set + devpriv->do_bits &= ~data[0]; + // set new bit values + devpriv->do_bits |= data[0] & data[1]; + outb(devpriv->do_bits, dev->iobase + DAS08JR_DIO); + + data[1] = devpriv->do_bits; + + return 2; +} + +static int das08jr_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int lsb, msb; + int chan; + + lsb = data[0] & 0xff; + msb = (data[0] >> 8) & 0xf; + + chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { +#if 0 + outb(lsb, dev->iobase + devpriv->ao_offset_lsb[chan]); + outb(msb, dev->iobase + devpriv->ao_offset_msb[chan]); +#else + outb(lsb, dev->iobase + DAS08JR_AO_LSB(chan)); + outb(msb, dev->iobase + DAS08JR_AO_MSB(chan)); +#endif + + /* load DACs */ + inb(dev->iobase + DAS08JR_DIO); + } + + return n; +} + +/* + * + * The -aox boards have the DACs at a different offset and use + * a different method to force an update. + * + */ +static int das08ao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int lsb, msb; + int chan; + + lsb = data[0] & 0xff; + msb = (data[0] >> 8) & 0xf; + + chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { +#if 0 + outb(lsb, dev->iobase + devpriv->ao_offset_lsb[chan]); + outb(msb, dev->iobase + devpriv->ao_offset_msb[chan]); +#else + outb(lsb, dev->iobase + DAS08AO_AO_LSB(chan)); + outb(msb, dev->iobase + DAS08AO_AO_MSB(chan)); +#endif + + /* load DACs */ + inb(dev->iobase + DAS08AO_AO_UPDATE); + } + + return n; +} + +static unsigned int i8254_read_channel_low(unsigned int base, int chan) +{ + unsigned int msb, lsb; + + /* The following instructions must be in order. + We must avoid other process reading the counter's value in the + middle. + The spin_lock isn't needed since ioctl calls grab the big kernel + lock automatically */ + /*spin_lock(sp); */ + outb(chan << 6, base + I8254_CTRL); + base += chan; + lsb = inb(base); + msb = inb(base); + /*spin_unlock(sp); */ + + return lsb | (msb << 8); +} + +static void i8254_write_channel_low(unsigned int base, int chan, + unsigned int value) +{ + unsigned int msb, lsb; + + lsb = value & 0xFF; + msb = value >> 8; + + /* write lsb, then msb */ + base += chan; + /* See comments in i8254_read_channel_low */ + /*spin_lock(sp); */ + outb(lsb, base); + outb(msb, base); + /*spin_unlock(sp); */ +} + +static unsigned int i8254_read_channel(struct i8254_struct *st, int channel) +{ + int chan = st->logic2phys[channel]; + + return i8254_read_channel_low(st->iobase, chan); +} + +static void i8254_write_channel(struct i8254_struct *st, int channel, + unsigned int value) +{ + int chan = st->logic2phys[channel]; + + i8254_write_channel_low(st->iobase, chan, value); +} + +static void i8254_initialize(struct i8254_struct *st) +{ + int i; + for (i = 0; i < 3; ++i) + i8254_set_mode_low(st->iobase, i, st->mode[i]); +} + +static void i8254_set_mode_low(unsigned int base, int channel, + unsigned int mode) +{ + outb((channel << 6) | 0x30 | (mode & 0x0F), base + I8254_CTRL); +} + +static void i8254_set_mode(struct i8254_struct *st, int channel, + unsigned int mode) +{ + int chan = st->logic2phys[channel]; + + st->mode[chan] = mode; + return i8254_set_mode_low(st->iobase, chan, mode); +} + +static unsigned int i8254_read_status_low(unsigned int base, int channel) +{ + outb(0xE0 | (2 << channel), base + I8254_CTRL); + return inb(base + channel); +} + +static unsigned int i8254_read_status(struct i8254_struct *st, int channel) +{ + int chan = st->logic2phys[channel]; + + return i8254_read_status_low(st->iobase, chan); +} + +static int das08_counter_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = insn->chanspec; + + //printk("Reading counter channel %d ",chan); + data[0] = i8254_read_channel(&devpriv->i8254, chan); + //printk("=> 0x%08X\n",data[0]); + + return 1; +} + +static int das08_counter_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = insn->chanspec; + + //printk("Writing counter channel %d with 0x%04X\n",chan,data[0]); + i8254_write_channel(&devpriv->i8254, chan, data[0]); + + return 1; +} + +static int das08_counter_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = insn->chanspec; + + if (insn->n != 2) + return -EINVAL; + + switch (data[0]) { + case INSN_CONFIG_SET_COUNTER_MODE: + i8254_set_mode(&devpriv->i8254, chan, data[1]); + break; + case INSN_CONFIG_8254_READ_STATUS: + data[1] = i8254_read_status(&devpriv->i8254, chan); + break; + default: + return -EINVAL; + break; + } + return 2; +} + +static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it); + +static struct comedi_driver driver_das08 = { + driver_name: DRV_NAME, + module:THIS_MODULE, + attach:das08_attach, + detach:das08_common_detach, + board_name:&das08_boards[0].name, + num_names:sizeof(das08_boards) / + sizeof(struct das08_board_struct), + offset:sizeof(struct das08_board_struct), +}; + +int das08_common_attach(struct comedi_device * dev, unsigned long iobase) +{ + struct comedi_subdevice *s; + int ret; + + // allocate ioports for non-pcmcia, non-pci boards + if ((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) { + printk(" iobase 0x%lx\n", iobase); + if (!request_region(iobase, thisboard->iosize, DRV_NAME)) { + printk(" I/O port conflict\n"); + return -EIO; + } + } + dev->iobase = iobase; + + dev->board_name = thisboard->name; + + if ((ret = alloc_subdevices(dev, 6)) < 0) + return ret; + + s = dev->subdevices + 0; + /* ai */ + if (thisboard->ai) { + s->type = COMEDI_SUBD_AI; + /* XXX some boards actually have differential inputs instead of single ended. + * The driver does nothing with arefs though, so it's no big deal. */ + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 8; + s->maxdata = (1 << thisboard->ai_nbits) - 1; + s->range_table = das08_ai_lranges[thisboard->ai_pg]; + s->insn_read = thisboard->ai; + devpriv->pg_gainlist = das08_gainlists[thisboard->ai_pg]; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 1; + /* ao */ + if (thisboard->ao) { + s->type = COMEDI_SUBD_AO; +// XXX lacks read-back insn + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->maxdata = (1 << thisboard->ao_nbits) - 1; + s->range_table = &range_bipolar5; + s->insn_write = thisboard->ao; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 2; + /* di */ + if (thisboard->di) { + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = (thisboard->di == das08_di_rbits) ? 3 : 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = thisboard->di; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 3; + /* do */ + if (thisboard->do_) { + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = thisboard->do_nchan; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = thisboard->do_; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 4; + /* 8255 */ + if (thisboard->i8255_offset != 0) { + subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase + + thisboard->i8255_offset)); + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 5; + /* 8254 */ + if (thisboard->i8254_offset != 0) { + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 3; + s->maxdata = 0xFFFF; + s->insn_read = das08_counter_read; + s->insn_write = das08_counter_write; + s->insn_config = das08_counter_config; + /* Set-up the 8254 structure */ + devpriv->i8254.channels = 3; + devpriv->i8254.logic2phys[0] = 0; + devpriv->i8254.logic2phys[1] = 1; + devpriv->i8254.logic2phys[2] = 2; + devpriv->i8254.iobase = iobase + thisboard->i8254_offset; + devpriv->i8254.mode[0] = + devpriv->i8254.mode[1] = + devpriv->i8254.mode[2] = I8254_MODE0 | I8254_BINARY; + i8254_initialize(&devpriv->i8254); + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + return 0; +} + +static int das08_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + unsigned long iobase; +#ifdef CONFIG_COMEDI_PCI + unsigned long pci_iobase = 0; + struct pci_dev *pdev; +#endif + + if ((ret = alloc_private(dev, sizeof(struct das08_private_struct))) < 0) + return ret; + + printk("comedi%d: das08: ", dev->minor); + // deal with a pci board + if (thisboard->bustype == pci) { +#ifdef CONFIG_COMEDI_PCI + if (it->options[0] || it->options[1]) { + printk("bus %i slot %i ", + it->options[0], it->options[1]); + } + printk("\n"); + // find card + for (pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pdev != NULL; + pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) { + if (pdev->vendor == PCI_VENDOR_ID_COMPUTERBOARDS + && pdev->device == PCI_DEVICE_ID_PCIDAS08) { + if (it->options[0] || it->options[1]) { + if (pdev->bus->number == it->options[0] + && PCI_SLOT(pdev->devfn) == + it->options[1]) { + break; + } + } else { + break; + } + } + } + if (!pdev) { + printk("No pci das08 cards found\n"); + return -EIO; + } + devpriv->pdev = pdev; + // enable PCI device and reserve I/O spaces + if (comedi_pci_enable(pdev, DRV_NAME)) { + printk(" Error enabling PCI device and requesting regions\n"); + return -EIO; + } + // read base addresses + pci_iobase = pci_resource_start(pdev, 1); + iobase = pci_resource_start(pdev, 2); + printk("pcibase 0x%lx iobase 0x%lx\n", pci_iobase, iobase); + devpriv->pci_iobase = pci_iobase; +#if 0 +/* We could enable to pci-das08's interrupt here to make it possible + * to do timed input in this driver, but there is little point since + * conversions would have to be started by the interrupt handler + * so you might as well use comedi_rt_timer to emulate commands + */ + /* set source of interrupt trigger to counter2 output */ + outb(CNTRL_INTR | CNTRL_DIR, pci_iobase + CNTRL); + /* Enable local interrupt 1 and pci interrupt */ + outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR); +#endif +#else /* CONFIG_COMEDI_PCI */ + printk("this driver has not been built with PCI support.\n"); + return -EINVAL; +#endif /* CONFIG_COMEDI_PCI */ + } else { + iobase = it->options[0]; + } + printk("\n"); + + return das08_common_attach(dev, iobase); +} + +int das08_common_detach(struct comedi_device * dev) +{ + printk(KERN_INFO "comedi%d: das08: remove\n", dev->minor); + + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 4); + + // deallocate ioports for non-pcmcia, non-pci boards + if ((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) { + if (dev->iobase) + release_region(dev->iobase, thisboard->iosize); + } + +#ifdef CONFIG_COMEDI_PCI + if (devpriv) { + if (devpriv->pdev) { + if (devpriv->pci_iobase) { + comedi_pci_disable(devpriv->pdev); + } + pci_dev_put(devpriv->pdev); + } + } +#endif + + return 0; +} + +#ifdef CONFIG_COMEDI_PCI +COMEDI_PCI_INITCLEANUP(driver_das08, das08_pci_table); +#else +COMEDI_INITCLEANUP(driver_das08); +#endif + +EXPORT_SYMBOL_GPL(das08_common_attach); +EXPORT_SYMBOL_GPL(das08_common_detach); +#ifdef CONFIG_COMEDI_PCMCIA +EXPORT_SYMBOL_GPL(das08_cs_boards); +#endif diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h new file mode 100644 index 000000000000..69089ce690f2 --- /dev/null +++ b/drivers/staging/comedi/drivers/das08.h @@ -0,0 +1,78 @@ +/* + das08.h + + Header for das08.c and das08_cs.c + + Copyright (C) 2003 Frank Mori Hess + + 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 _DAS08_H +#define _DAS08_H + +enum das08_bustype { isa, pci, pcmcia, pc104 }; +// different ways ai data is encoded in first two registers +enum das08_ai_encoding { das08_encode12, das08_encode16, das08_pcm_encode12 }; +enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl, + das08_pgm }; + +struct das08_board_struct { + const char *name; + unsigned int id; // id for pci/pcmcia boards + enum das08_bustype bustype; + void *ai; + unsigned int ai_nbits; + enum das08_lrange ai_pg; + enum das08_ai_encoding ai_encoding; + void *ao; + unsigned int ao_nbits; + void *di; + void *do_; + unsigned int do_nchan; + unsigned int i8255_offset; + unsigned int i8254_offset; + unsigned int iosize; // number of ioports used +}; + +struct i8254_struct { + int channels; // available channels. Some could be used internally. + int logic2phys[3]; // to know which physical channel is. + int mode[3]; // the index is the real counter. + unsigned int iobase; +}; + +#define I8254_CNT0 0 +#define I8254_CNT1 1 +#define I8254_CNT2 2 +#define I8254_CTRL 3 + +struct das08_private_struct { + unsigned int do_mux_bits; // bits for do/mux register on boards without seperate do register + unsigned int do_bits; // bits for do register on boards with register dedicated to digital out only + const unsigned int *pg_gainlist; + struct pci_dev *pdev; // struct for pci-das08 + unsigned int pci_iobase; // additional base address for pci-das08 + struct i8254_struct i8254; +}; + +#define NUM_DAS08_CS_BOARDS 2 +extern struct das08_board_struct das08_cs_boards[NUM_DAS08_CS_BOARDS]; + +int das08_common_attach(struct comedi_device * dev, unsigned long iobase); +int das08_common_detach(struct comedi_device * dev); + +#endif /* _DAS08_H */ diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c new file mode 100644 index 000000000000..be6c88788c4b --- /dev/null +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -0,0 +1,488 @@ +/* + comedi/drivers/das08_cs.c + DAS08 driver + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + Copyright (C) 2001,2002,2003 Frank Mori Hess + + 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: das08_cs +Description: DAS-08 PCMCIA boards +Author: Warren Jasper, ds, Frank Hess +Devices: [ComputerBoards] PCM-DAS08 (pcm-das08) +Status: works + +This is the PCMCIA-specific support split off from the +das08 driver. + +Options (for pcm-das08): + NONE + +Command support does not exist, but could be added for this board. +*/ + +#include "../comedidev.h" + +#include +#include + +#include "das08.h" + +// pcmcia includes +#include +#include +#include +#include + +static struct pcmcia_device *cur_dev = NULL; + +#define thisboard ((const struct das08_board_struct *)dev->board_ptr) + +static int das08_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it); + +static struct comedi_driver driver_das08_cs = { + driver_name:"das08_cs", + module:THIS_MODULE, + attach:das08_cs_attach, + detach:das08_common_detach, + board_name:&das08_cs_boards[0].name, + num_names:sizeof(das08_cs_boards) / + sizeof(struct das08_board_struct), + offset:sizeof(struct das08_board_struct), +}; + +static int das08_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + unsigned long iobase; + struct pcmcia_device *link = cur_dev; // XXX hack + + if ((ret = alloc_private(dev, sizeof(struct das08_private_struct))) < 0) + return ret; + + printk("comedi%d: das08_cs: ", dev->minor); + // deal with a pci board + + if (thisboard->bustype == pcmcia) { + if (link == NULL) { + printk(" no pcmcia cards found\n"); + return -EIO; + } + iobase = link->io.BasePort1; + } else { + printk(" bug! board does not have PCMCIA bustype\n"); + return -EINVAL; + } + + printk("\n"); + + return das08_common_attach(dev, iobase); +} + +/*====================================================================== + + The following pcmcia code for the pcm-das08 is adapted from the + dummy_cs.c driver of the Linux PCMCIA Card Services package. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + +======================================================================*/ + +/* + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + you do not define PCMCIA_DEBUG at all, all the debug code will be + left out. If you compile with PCMCIA_DEBUG=0, the debug code will + be present but disabled -- but it can then be enabled for specific + modules at load time with a 'pc_debug=#' option to insmod. +*/ + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +module_param(pc_debug, int, 0644); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static const char *version = + "das08.c pcmcia code (Frank Hess), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ +static void das08_pcmcia_config(struct pcmcia_device *link); +static void das08_pcmcia_release(struct pcmcia_device *link); +static int das08_pcmcia_suspend(struct pcmcia_device *p_dev); +static int das08_pcmcia_resume(struct pcmcia_device *p_dev); + +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static int das08_pcmcia_attach(struct pcmcia_device *); +static void das08_pcmcia_detach(struct pcmcia_device *); + +/* + You'll also need to prototype all the functions that will actually + be used to talk to your device. See 'memory_cs' for a good example + of a fully self-sufficient driver; the other drivers rely more or + less on other parts of the kernel. +*/ + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static const dev_info_t dev_info = "pcm-das08"; + +struct local_info_t { + struct pcmcia_device *link; + dev_node_t node; + int stop; + struct bus_operations *bus; +}; + +/*====================================================================== + + das08_pcmcia_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + +======================================================================*/ + +static int das08_pcmcia_attach(struct pcmcia_device *link) +{ + struct local_info_t *local; + + DEBUG(0, "das08_pcmcia_attach()\n"); + + /* Allocate space for private device-specific data */ + local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); + if (!local) + return -ENOMEM; + local->link = link; + link->priv = local; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->irq.Handler = NULL; + + /* + General socket configuration defaults can go here. In this + client, we assume very little, and rely on the CIS for almost + everything. In most clients, many details (i.e., number, sizes, + and attributes of IO windows) are fixed by the nature of the + device, and can be hard-wired here. + */ + link->conf.Attributes = 0; + link->conf.IntType = INT_MEMORY_AND_IO; + + cur_dev = link; + + das08_pcmcia_config(link); + + return 0; +} /* das08_pcmcia_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void das08_pcmcia_detach(struct pcmcia_device *link) +{ + + DEBUG(0, "das08_pcmcia_detach(0x%p)\n", link); + + if (link->dev_node) { + ((struct local_info_t *) link->priv)->stop = 1; + das08_pcmcia_release(link); + } + + /* This points to the parent struct local_info_t struct */ + if (link->priv) + kfree(link->priv); + +} /* das08_pcmcia_detach */ + +/*====================================================================== + + das08_pcmcia_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + device available to the system. + +======================================================================*/ + +static void das08_pcmcia_config(struct pcmcia_device *link) +{ + struct local_info_t *dev = link->priv; + tuple_t tuple; + cisparse_t parse; + int last_fn, last_ret; + u_char buf[64]; + cistpl_cftable_entry_t dflt = { 0 }; + + DEBUG(0, "das08_pcmcia_config(0x%p)\n", link); + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + last_fn = GetFirstTuple; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) + goto cs_failed; + last_fn = GetTupleData; + if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) + goto cs_failed; + last_fn = ParseTuple; + if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) + goto cs_failed; + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* + In this loop, we scan the CIS for configuration table entries, + each of which describes a valid card configuration, including + voltage, IO window, memory window, and interrupt settings. + + We make no assumptions about the card to be configured: we use + just the information available in the CIS. In an ideal world, + this would work for any PCMCIA card, but it requires a complete + and accurate CIS. In practice, a driver usually "knows" most of + these things without consulting the CIS, and most client drivers + will only use the CIS to fill in implementation-defined details. + */ + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + last_fn = GetFirstTuple; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) + goto cs_failed; + while (1) { + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) + goto next_entry; + if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) + goto next_entry; + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + if (cfg->index == 0) + goto next_entry; + link->conf.ConfigIndex = cfg->index; + + /* Does this card need audio output? */ +/* if (cfg->flags & CISTPL_CFTABLE_AUDIO) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } +*/ + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + /* This reserves IO space but doesn't actually enable it */ + if (pcmcia_request_io(link, &link->io) != 0) + goto next_entry; + } + + /* If we got this far, we're cool! */ + break; + + next_entry: + last_fn = GetNextTuple; + if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0) + goto cs_failed; + } + + if (link->conf.Attributes & CONF_ENABLE_IRQ) { + last_fn = RequestIRQ; + if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0) + goto cs_failed; + } + + /* + This actually configures the PCMCIA socket -- setting up + the I/O windows and the interrupt mapping, and putting the + card and host interface into "Memory and IO" mode. + */ + last_fn = RequestConfiguration; + if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0) + goto cs_failed; + + /* + At this point, the dev_node_t structure(s) need to be + initialized and arranged in a linked list at link->dev. + */ + sprintf(dev->node.dev_name, "pcm-das08"); + dev->node.major = dev->node.minor = 0; + link->dev_node = &dev->node; + + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %u", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1 + link->io.NumPorts1 - 1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2 + link->io.NumPorts2 - 1); + printk("\n"); + + return; + + cs_failed: + cs_error(link, last_fn, last_ret); + das08_pcmcia_release(link); + +} /* das08_pcmcia_config */ + +/*====================================================================== + + After a card is removed, das08_pcmcia_release() will unregister the + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + +======================================================================*/ + +static void das08_pcmcia_release(struct pcmcia_device *link) +{ + DEBUG(0, "das08_pcmcia_release(0x%p)\n", link); + pcmcia_disable_device(link); +} /* das08_pcmcia_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. + + When a CARD_REMOVAL event is received, we immediately set a + private flag to block future accesses to this device. All the + functions that actually access the device should check this flag + to make sure the card is still present. + +======================================================================*/ + +static int das08_pcmcia_suspend(struct pcmcia_device *link) +{ + struct local_info_t *local = link->priv; + /* Mark the device as stopped, to block IO until later */ + local->stop = 1; + + return 0; +} /* das08_pcmcia_suspend */ + +static int das08_pcmcia_resume(struct pcmcia_device *link) +{ + struct local_info_t *local = link->priv; + + local->stop = 0; + return 0; +} /* das08_pcmcia_resume */ + +/*====================================================================*/ + +static struct pcmcia_device_id das08_cs_id_table[] = { + PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4001), + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table); + +struct pcmcia_driver das08_cs_driver = { + .probe = das08_pcmcia_attach, + .remove = das08_pcmcia_detach, + .suspend = das08_pcmcia_suspend, + .resume = das08_pcmcia_resume, + .id_table = das08_cs_id_table, + .owner = THIS_MODULE, + .drv = { + .name = dev_info, + }, +}; + +static int __init init_das08_pcmcia_cs(void) +{ + DEBUG(0, "%s\n", version); + pcmcia_register_driver(&das08_cs_driver); + return 0; +} + +static void __exit exit_das08_pcmcia_cs(void) +{ + DEBUG(0, "das08_pcmcia_cs: unloading\n"); + pcmcia_unregister_driver(&das08_cs_driver); +} + +static int __init das08_cs_init_module(void) +{ + int ret; + + ret = init_das08_pcmcia_cs(); + if (ret < 0) + return ret; + + return comedi_driver_register(&driver_das08_cs); +} + +static void __exit das08_cs_exit_module(void) +{ + exit_das08_pcmcia_cs(); + comedi_driver_unregister(&driver_das08_cs); +} + +MODULE_LICENSE("GPL"); +module_init(das08_cs_init_module); +module_exit(das08_cs_exit_module); diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c new file mode 100644 index 000000000000..6b6b042099de --- /dev/null +++ b/drivers/staging/comedi/drivers/das16.c @@ -0,0 +1,1730 @@ +/* + comedi/drivers/das16.c + DAS16 driver + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + Copyright (C) 2000 Chris R. Baugher + Copyright (C) 2001,2002 Frank Mori Hess + + 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: das16 +Description: DAS16 compatible boards +Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze +Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g), + DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202), + DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601), + DAS-1602 (das-1602), + [ComputerBoards] PC104-DAS16/JR (pc104-das16jr), + PC104-DAS16JR/16 (pc104-das16jr/16), + CIO-DAS16JR/16 (cio-das16jr/16), + CIO-DAS16/JR (cio-das16/jr), CIO-DAS1401/12 (cio-das1401/12), + CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16), + CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12), + CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330) +Status: works +Updated: 2003-10-12 + +A rewrite of the das16 and das1600 drivers. +Options: + [0] - base io address + [1] - irq (does nothing, irq is not used anymore) + [2] - dma (optional, required for comedi_command support) + [3] - master clock speed in MHz (optional, 1 or 10, ignored if + board can probe clock, defaults to 1) + [4] - analog input range lowest voltage in microvolts (optional, + only useful if your board does not have software + programmable gain) + [5] - analog input range highest voltage in microvolts (optional, + only useful if board does not have software programmable + gain) + [6] - analog output range lowest voltage in microvolts (optional) + [7] - analog output range highest voltage in microvolts (optional) + [8] - use timer mode for DMA. Timer mode is needed e.g. for + buggy DMA controllers in NS CS5530A (Geode Companion), and for + 'jr' cards that lack a hardware fifo. This option is no + longer needed, since timer mode is _always_ used. + +Passing a zero for an option is the same as leaving it unspecified. + +*/ +/* + +Testing and debugging help provided by Daniel Koch. + +Keithley Manuals: + 2309.PDF (das16) + 4919.PDF (das1400, 1600) + 4922.PDF (das-1400) + 4923.PDF (das1200, 1400, 1600) + +Computer boards manuals also available from their website www.measurementcomputing.com + +*/ + +#include +#include +#include "../comedidev.h" + +#include "8253.h" +#include "8255.h" +#include "comedi_fc.h" + +#undef DEBUG +//#define DEBUG + +#ifdef DEBUG +#define DEBUG_PRINT(format, args...) rt_printk("das16: " format, ## args) +#else +#define DEBUG_PRINT(format, args...) +#endif + +#define DAS16_SIZE 20 // number of ioports +#define DAS16_DMA_SIZE 0xff00 // size in bytes of allocated dma buffer + +/* + cio-das16.pdf + + "das16" + "das16/f" + + 0 a/d bits 0-3 start 12 bit + 1 a/d bits 4-11 unused + 2 mux read mux set + 3 di 4 bit do 4 bit + 4 unused ao0_lsb + 5 unused ao0_msb + 6 unused ao1_lsb + 7 unused ao1_msb + 8 status eoc uni/bip interrupt reset + 9 dma, int, trig ctrl set dma, int + a pacer control unused + b reserved reserved + cdef 8254 + 0123 8255 + +*/ + +/* + cio-das16jr.pdf + + "das16jr" + + 0 a/d bits 0-3 start 12 bit + 1 a/d bits 4-11 unused + 2 mux read mux set + 3 di 4 bit do 4 bit + 4567 unused unused + 8 status eoc uni/bip interrupt reset + 9 dma, int, trig ctrl set dma, int + a pacer control unused + b gain status gain control + cdef 8254 + +*/ + +/* + cio-das16jr_16.pdf + + "das16jr_16" + + 0 a/d bits 0-7 start 16 bit + 1 a/d bits 8-15 unused + 2 mux read mux set + 3 di 4 bit do 4 bit + 4567 unused unused + 8 status eoc uni/bip interrupt reset + 9 dma, int, trig ctrl set dma, int + a pacer control unused + b gain status gain control + cdef 8254 + +*/ +/* + cio-das160x-1x.pdf + + "das1601/12" + "das1602/12" + "das1602/16" + + 0 a/d bits 0-3 start 12 bit + 1 a/d bits 4-11 unused + 2 mux read mux set + 3 di 4 bit do 4 bit + 4 unused ao0_lsb + 5 unused ao0_msb + 6 unused ao1_lsb + 7 unused ao1_msb + 8 status eoc uni/bip interrupt reset + 9 dma, int, trig ctrl set dma, int + a pacer control unused + b gain status gain control + cdef 8254 + 400 8255 + 404 unused conversion enable + 405 unused burst enable + 406 unused das1600 enable + 407 status + +*/ + +static const int sample_size = 2; // size in bytes of a sample from board + +#define DAS16_TRIG 0 +#define DAS16_AI_LSB 0 +#define DAS16_AI_MSB 1 +#define DAS16_MUX 2 +#define DAS16_DIO 3 +#define DAS16_AO_LSB(x) ((x)?6:4) +#define DAS16_AO_MSB(x) ((x)?7:5) +#define DAS16_STATUS 8 +#define BUSY (1<<7) +#define UNIPOLAR (1<<6) +#define DAS16_MUXBIT (1<<5) +#define DAS16_INT (1<<4) +#define DAS16_CONTROL 9 +#define DAS16_INTE (1<<7) +#define DAS16_IRQ(x) (((x) & 0x7) << 4) +#define DMA_ENABLE (1<<2) +#define PACING_MASK 0x3 +#define INT_PACER 0x03 +#define EXT_PACER 0x02 +#define DAS16_SOFT 0x00 +#define DAS16_PACER 0x0A +#define DAS16_CTR0 (1<<1) +#define DAS16_TRIG0 (1<<0) +#define BURST_LEN_BITS(x) (((x) & 0xf) << 4) +#define DAS16_GAIN 0x0B +#define DAS16_CNTR0_DATA 0x0C +#define DAS16_CNTR1_DATA 0x0D +#define DAS16_CNTR2_DATA 0x0E +#define DAS16_CNTR_CONTROL 0x0F +#define DAS16_TERM_CNT 0x00 +#define DAS16_ONE_SHOT 0x02 +#define DAS16_RATE_GEN 0x04 +#define DAS16_CNTR_LSB_MSB 0x30 +#define DAS16_CNTR0 0x00 +#define DAS16_CNTR1 0x40 +#define DAS16_CNTR2 0x80 + +#define DAS1600_CONV 0x404 +#define DAS1600_CONV_DISABLE 0x40 +#define DAS1600_BURST 0x405 +#define DAS1600_BURST_VAL 0x40 +#define DAS1600_ENABLE 0x406 +#define DAS1600_ENABLE_VAL 0x40 +#define DAS1600_STATUS_B 0x407 +#define DAS1600_BME 0x40 +#define DAS1600_ME 0x20 +#define DAS1600_CD 0x10 +#define DAS1600_WS 0x02 +#define DAS1600_CLK_10MHZ 0x01 + +static const struct comedi_lrange range_das1x01_bip = { 4, { + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.01), + } +}; +static const struct comedi_lrange range_das1x01_unip = { 4, { + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01), + } +}; +static const struct comedi_lrange range_das1x02_bip = { 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + } +}; +static const struct comedi_lrange range_das1x02_unip = { 4, { + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + } +}; +static const struct comedi_lrange range_das16jr = { 9, { + // also used by 16/330 + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + } +}; +static const struct comedi_lrange range_das16jr_16 = { 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + } +}; + +static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 }; +static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static const int das1600_gainlist[] = { 0, 1, 2, 3 }; +enum { + das16_pg_none = 0, + das16_pg_16jr, + das16_pg_16jr_16, + das16_pg_1601, + das16_pg_1602, +}; +static const int *const das16_gainlists[] = { + NULL, + das16jr_gainlist, + das16jr_16_gainlist, + das1600_gainlist, + das1600_gainlist, +}; +static const struct comedi_lrange *const das16_ai_uni_lranges[] = { + &range_unknown, + &range_das16jr, + &range_das16jr_16, + &range_das1x01_unip, + &range_das1x02_unip, +}; +static const struct comedi_lrange *const das16_ai_bip_lranges[] = { + &range_unknown, + &range_das16jr, + &range_das16jr_16, + &range_das1x01_bip, + &range_das1x02_bip, +}; + +struct munge_info { + uint8_t byte; + unsigned have_byte:1; +}; + +static int das16_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s); +static int das16_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void das16_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s, + void *array, unsigned int num_bytes, unsigned int start_chan_index); + +static void das16_reset(struct comedi_device * dev); +static irqreturn_t das16_dma_interrupt(int irq, void *d PT_REGS_ARG); +static void das16_timer_interrupt(unsigned long arg); +static void das16_interrupt(struct comedi_device * dev); + +static unsigned int das16_set_pacer(struct comedi_device * dev, unsigned int ns, + int flags); +static int das1600_mode_detect(struct comedi_device * dev); +static unsigned int das16_suggest_transfer_size(struct comedi_device * dev, + struct comedi_cmd cmd); + +static void reg_dump(struct comedi_device * dev); + +struct das16_board { + const char *name; + void *ai; + unsigned int ai_nbits; + unsigned int ai_speed; // max conversion speed in nanosec + unsigned int ai_pg; + void *ao; + unsigned int ao_nbits; + void *di; + void *do_; + + unsigned int i8255_offset; + unsigned int i8254_offset; + + unsigned int size; + unsigned int id; +}; + +static const struct das16_board das16_boards[] = { + { + name: "das-16", + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:15000, + ai_pg: das16_pg_none, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x10, + i8254_offset:0x0c, + size: 0x14, + id: 0x00, + }, + { + name: "das-16g", + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:15000, + ai_pg: das16_pg_none, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x10, + i8254_offset:0x0c, + size: 0x14, + id: 0x00, + }, + { + name: "das-16f", + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:8500, + ai_pg: das16_pg_none, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x10, + i8254_offset:0x0c, + size: 0x14, + id: 0x00, + }, + { + name: "cio-das16", // cio-das16.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:20000, + ai_pg: das16_pg_none, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x10, + i8254_offset:0x0c, + size: 0x14, + id: 0x80, + }, + { + name: "cio-das16/f", // das16.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:10000, + ai_pg: das16_pg_none, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x10, + i8254_offset:0x0c, + size: 0x14, + id: 0x80, + }, + { + name: "cio-das16/jr", // cio-das16jr.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:7692, + ai_pg: das16_pg_16jr, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0, + i8254_offset:0x0c, + size: 0x10, + id: 0x00, + }, + { + name: "pc104-das16jr", // pc104-das16jr_xx.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:3300, + ai_pg: das16_pg_16jr, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0, + i8254_offset:0x0c, + size: 0x10, + id: 0x00, + }, + { + name: "cio-das16jr/16", // cio-das16jr_16.pdf + ai: das16_ai_rinsn, + ai_nbits:16, + ai_speed:10000, + ai_pg: das16_pg_16jr_16, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0, + i8254_offset:0x0c, + size: 0x10, + id: 0x00, + }, + { + name: "pc104-das16jr/16", // pc104-das16jr_xx.pdf + ai: das16_ai_rinsn, + ai_nbits:16, + ai_speed:10000, + ai_pg: das16_pg_16jr_16, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0, + i8254_offset:0x0c, + size: 0x10, + id: 0x00, + }, + { + name: "das-1201", // 4924.pdf (keithley user's manual) + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:20000, + ai_pg: das16_pg_none, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x400, + i8254_offset:0x0c, + size: 0x408, + id: 0x20, + }, + { + name: "das-1202", // 4924.pdf (keithley user's manual) + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:10000, + ai_pg: das16_pg_none, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x400, + i8254_offset:0x0c, + size: 0x408, + id: 0x20, + }, + { + name: "das-1401", // 4919.pdf and 4922.pdf (keithley user's manual) + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:10000, + ai_pg: das16_pg_1601, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x0, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0 // 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 + }, + { + name: "das-1402", // 4919.pdf and 4922.pdf (keithley user's manual) + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:10000, + ai_pg: das16_pg_1602, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x0, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0 // 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 + }, + { + name: "das-1601", // 4919.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:10000, + ai_pg: das16_pg_1601, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x400, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0}, + { + name: "das-1602", // 4919.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:10000, + ai_pg: das16_pg_1602, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x400, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0}, + { + name: "cio-das1401/12", // cio-das1400_series.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:6250, + ai_pg: das16_pg_1601, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0}, + { + name: "cio-das1402/12", // cio-das1400_series.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:6250, + ai_pg: das16_pg_1602, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0}, + { + name: "cio-das1402/16", // cio-das1400_series.pdf + ai: das16_ai_rinsn, + ai_nbits:16, + ai_speed:10000, + ai_pg: das16_pg_1602, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0}, + { + name: "cio-das1601/12", // cio-das160x-1x.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:6250, + ai_pg: das16_pg_1601, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x400, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0}, + { + name: "cio-das1602/12", // cio-das160x-1x.pdf + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:10000, + ai_pg: das16_pg_1602, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x400, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0}, + { + name: "cio-das1602/16", // cio-das160x-1x.pdf + ai: das16_ai_rinsn, + ai_nbits:16, + ai_speed:10000, + ai_pg: das16_pg_1602, + ao: das16_ao_winsn, + ao_nbits:12, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0x400, + i8254_offset:0x0c, + size: 0x408, + id: 0xc0}, + { + name: "cio-das16/330", // ? + ai: das16_ai_rinsn, + ai_nbits:12, + ai_speed:3030, + ai_pg: das16_pg_16jr, + ao: NULL, + di: das16_di_rbits, + do_: das16_do_wbits, + i8255_offset:0, + i8254_offset:0x0c, + size: 0x14, + id: 0xf0}, +#if 0 + { + name: "das16/330i", // ? + }, + { + name: "das16/jr/ctr5", // ? + }, + { + name: "cio-das16/m1/16", // cio-das16_m1_16.pdf, this board is a bit quirky, no dma + }, +#endif +}; + +#define n_das16_boards ((sizeof(das16_boards))/(sizeof(struct das16_board))) + +static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int das16_detach(struct comedi_device * dev); +static struct comedi_driver driver_das16 = { + driver_name:"das16", + module:THIS_MODULE, + attach:das16_attach, + detach:das16_detach, + board_name:&das16_boards[0].name, + num_names:n_das16_boards, + offset:sizeof(das16_boards[0]), +}; + +#define DAS16_TIMEOUT 1000 + +/* Period for timer interrupt in jiffies. It's a function + * to deal with possibility of dynamic HZ patches */ +static inline int timer_period(void) +{ + return HZ / 20; +} +struct das16_private_struct { + unsigned int ai_unipolar; // unipolar flag + unsigned int ai_singleended; // single ended flag + unsigned int clockbase; // master clock speed in ns + volatile unsigned int control_state; // dma, interrupt and trigger control bits + volatile unsigned long adc_byte_count; // number of bytes remaining + unsigned int divisor1; // divisor dividing master clock to get conversion frequency + unsigned int divisor2; // divisor dividing master clock to get conversion frequency + unsigned int dma_chan; // dma channel + uint16_t *dma_buffer[2]; + dma_addr_t dma_buffer_addr[2]; + unsigned int current_buffer; + volatile unsigned int dma_transfer_size; // target number of bytes to transfer per dma shot + // user-defined analog input and output ranges defined from config options + struct comedi_lrange *user_ai_range_table; + struct comedi_lrange *user_ao_range_table; + + struct timer_list timer; // for timed interrupt + volatile short timer_running; + volatile short timer_mode; // true if using timer mode +}; +#define devpriv ((struct das16_private_struct *)(dev->private)) +#define thisboard ((struct das16_board *)(dev->board_ptr)) + +static int das16_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0, tmp; + int gain, start_chan, i; + int mask; + + /* make sure triggers are valid */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + mask = TRIG_FOLLOW; + // if board supports burst mode + if (thisboard->size > 0x400) + mask |= TRIG_TIMER | TRIG_EXT; + cmd->scan_begin_src &= mask; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + mask = TRIG_TIMER | TRIG_EXT; + // if board supports burst mode + if (thisboard->size > 0x400) + mask |= TRIG_NOW; + cmd->convert_src &= mask; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; + + // make sure scan_begin_src and convert_src dont conflict + if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) + err++; + if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + if (cmd->scan_begin_src == TRIG_FOLLOW) { + /* internal trigger */ + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + // check against maximum frequency + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < + thisboard->ai_speed * cmd->chanlist_len) { + cmd->scan_begin_arg = + thisboard->ai_speed * cmd->chanlist_len; + err++; + } + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < thisboard->ai_speed) { + cmd->convert_arg = thisboard->ai_speed; + err++; + } + } + + if (cmd->stop_src == TRIG_NONE) { + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + if (err) + return 3; + + // step 4: fix up arguments + if (cmd->scan_begin_src == TRIG_TIMER) { + unsigned int tmp = cmd->scan_begin_arg; + // set divisors, correct timing arguments + i8253_cascade_ns_to_timer_2div(devpriv->clockbase, + &(devpriv->divisor1), &(devpriv->divisor2), + &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK); + err += (tmp != cmd->scan_begin_arg); + } + if (cmd->convert_src == TRIG_TIMER) { + unsigned int tmp = cmd->convert_arg; + // set divisors, correct timing arguments + i8253_cascade_ns_to_timer_2div(devpriv->clockbase, + &(devpriv->divisor1), &(devpriv->divisor2), + &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK); + err += (tmp != cmd->convert_arg); + } + if (err) + return 4; + + // check channel/gain list against card's limitations + if (cmd->chanlist) { + gain = CR_RANGE(cmd->chanlist[0]); + start_chan = CR_CHAN(cmd->chanlist[0]); + for (i = 1; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != + (start_chan + i) % s->n_chan) { + comedi_error(dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); + err++; + } + if (CR_RANGE(cmd->chanlist[i]) != gain) { + comedi_error(dev, + "entries in chanlist must all have the same gain\n"); + err++; + } + } + } + if (err) + return 5; + + return 0; +} + +static int das16_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int byte; + unsigned long flags; + int range; + + if (devpriv->dma_chan == 0 || (dev->irq == 0 + && devpriv->timer_mode == 0)) { + comedi_error(dev, + "irq (or use of 'timer mode') dma required to execute comedi_cmd"); + return -1; + } + if (cmd->flags & TRIG_RT) { + comedi_error(dev, + "isa dma transfers cannot be performed with TRIG_RT, aborting"); + return -1; + } + + devpriv->adc_byte_count = + cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t); + + // disable conversions for das1600 mode + if (thisboard->size > 0x400) { + outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV); + } + // set scan limits + byte = CR_CHAN(cmd->chanlist[0]); + byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4; + outb(byte, dev->iobase + DAS16_MUX); + + /* set gain (this is also burst rate register but according to + * computer boards manual, burst rate does nothing, even on keithley cards) */ + if (thisboard->ai_pg != das16_pg_none) { + range = CR_RANGE(cmd->chanlist[0]); + outb((das16_gainlists[thisboard->ai_pg])[range], + dev->iobase + DAS16_GAIN); + } + + /* set counter mode and counts */ + cmd->convert_arg = + das16_set_pacer(dev, cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg); + + /* enable counters */ + byte = 0; + /* Enable burst mode if appropriate. */ + if (thisboard->size > 0x400) { + if (cmd->convert_src == TRIG_NOW) { + outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST); + // set burst length + byte |= BURST_LEN_BITS(cmd->chanlist_len - 1); + } else { + outb(0, dev->iobase + DAS1600_BURST); + } + } + outb(byte, dev->iobase + DAS16_PACER); + + // set up dma transfer + flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + /* clear flip-flop to make sure 2-byte registers for + * count and address get set correctly */ + clear_dma_ff(devpriv->dma_chan); + devpriv->current_buffer = 0; + set_dma_addr(devpriv->dma_chan, + devpriv->dma_buffer_addr[devpriv->current_buffer]); + // set appropriate size of transfer + devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, *cmd); + set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); + enable_dma(devpriv->dma_chan); + release_dma_lock(flags); + + // set up interrupt + if (devpriv->timer_mode) { + devpriv->timer_running = 1; + devpriv->timer.expires = jiffies + timer_period(); + add_timer(&devpriv->timer); + devpriv->control_state &= ~DAS16_INTE; + } else { + /* clear interrupt bit */ + outb(0x00, dev->iobase + DAS16_STATUS); + /* enable interrupts */ + devpriv->control_state |= DAS16_INTE; + } + devpriv->control_state |= DMA_ENABLE; + devpriv->control_state &= ~PACING_MASK; + if (cmd->convert_src == TRIG_EXT) + devpriv->control_state |= EXT_PACER; + else + devpriv->control_state |= INT_PACER; + outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); + + /* Enable conversions if using das1600 mode */ + if (thisboard->size > 0x400) { + outb(0, dev->iobase + DAS1600_CONV); + } + + return 0; +} + +static int das16_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + /* disable interrupts, dma and pacer clocked conversions */ + devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE; + outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); + if (devpriv->dma_chan) + disable_dma(devpriv->dma_chan); + + // disable SW timer + if (devpriv->timer_mode && devpriv->timer_running) { + devpriv->timer_running = 0; + del_timer(&devpriv->timer); + } + + /* disable burst mode */ + if (thisboard->size > 0x400) { + outb(0, dev->iobase + DAS1600_BURST); + } + + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + return 0; +} + +static void das16_reset(struct comedi_device * dev) +{ + outb(0, dev->iobase + DAS16_STATUS); + outb(0, dev->iobase + DAS16_CONTROL); + outb(0, dev->iobase + DAS16_PACER); + outb(0, dev->iobase + DAS16_CNTR_CONTROL); +} + +static int das16_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, n; + int range; + int chan; + int msb, lsb; + + // disable interrupts and pacing + devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK; + outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); + + /* set multiplexer */ + chan = CR_CHAN(insn->chanspec); + chan |= CR_CHAN(insn->chanspec) << 4; + outb(chan, dev->iobase + DAS16_MUX); + + /* set gain */ + if (thisboard->ai_pg != das16_pg_none) { + range = CR_RANGE(insn->chanspec); + outb((das16_gainlists[thisboard->ai_pg])[range], + dev->iobase + DAS16_GAIN); + } + + for (n = 0; n < insn->n; n++) { + /* trigger conversion */ + outb_p(0, dev->iobase + DAS16_TRIG); + + for (i = 0; i < DAS16_TIMEOUT; i++) { + if (!(inb(dev->iobase + DAS16_STATUS) & BUSY)) + break; + } + if (i == DAS16_TIMEOUT) { + rt_printk("das16: timeout\n"); + return -ETIME; + } + msb = inb(dev->iobase + DAS16_AI_MSB); + lsb = inb(dev->iobase + DAS16_AI_LSB); + if (thisboard->ai_nbits == 12) { + data[n] = ((lsb >> 4) & 0xf) | (msb << 4); + } else { + data[n] = lsb | (msb << 8); + } + } + + return n; +} + +static int das16_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int bits; + + bits = inb(dev->iobase + DAS16_DIO) & 0xf; + data[1] = bits; + data[0] = 0; + + return 2; +} + +static int das16_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int wbits; + + // only set bits that have been masked + data[0] &= 0xf; + wbits = s->state; + // zero bits that have been masked + wbits &= ~data[0]; + // set masked bits + wbits |= data[0] & data[1]; + s->state = wbits; + data[1] = wbits; + + outb(s->state, dev->iobase + DAS16_DIO); + + return 2; +} + +static int das16_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int lsb, msb; + int chan; + + chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + if (thisboard->ao_nbits == 12) { + lsb = (data[i] << 4) & 0xff; + msb = (data[i] >> 4) & 0xff; + } else { + lsb = data[i] & 0xff; + msb = (data[i] >> 8) & 0xff; + } + outb(lsb, dev->iobase + DAS16_AO_LSB(chan)); + outb(msb, dev->iobase + DAS16_AO_MSB(chan)); + } + + return i; +} + +static irqreturn_t das16_dma_interrupt(int irq, void *d PT_REGS_ARG) +{ + int status; + struct comedi_device *dev = d; + + status = inb(dev->iobase + DAS16_STATUS); + + if ((status & DAS16_INT) == 0) { + DEBUG_PRINT("spurious interrupt\n"); + return IRQ_NONE; + } + + /* clear interrupt */ + outb(0x00, dev->iobase + DAS16_STATUS); + das16_interrupt(dev); + return IRQ_HANDLED; +} + +static void das16_timer_interrupt(unsigned long arg) +{ + struct comedi_device *dev = (struct comedi_device *) arg; + + das16_interrupt(dev); + + if (devpriv->timer_running) + mod_timer(&devpriv->timer, jiffies + timer_period()); +} + +/* the pc104-das16jr (at least) has problems if the dma + transfer is interrupted in the middle of transferring + a 16 bit sample, so this function takes care to get + an even transfer count after disabling dma + channel. +*/ +static int disable_dma_on_even(struct comedi_device * dev) +{ + int residue; + int i; + static const int disable_limit = 100; + static const int enable_timeout = 100; + disable_dma(devpriv->dma_chan); + residue = get_dma_residue(devpriv->dma_chan); + for (i = 0; i < disable_limit && (residue % 2); ++i) { + int j; + enable_dma(devpriv->dma_chan); + for (j = 0; j < enable_timeout; ++j) { + int new_residue; + comedi_udelay(2); + new_residue = get_dma_residue(devpriv->dma_chan); + if (new_residue != residue) + break; + } + disable_dma(devpriv->dma_chan); + residue = get_dma_residue(devpriv->dma_chan); + } + if (i == disable_limit) { + comedi_error(dev, + "failed to get an even dma transfer, could be trouble."); + } + return residue; +} + +static void das16_interrupt(struct comedi_device * dev) +{ + unsigned long dma_flags, spin_flags; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async; + struct comedi_cmd *cmd; + int num_bytes, residue; + int buffer_index; + + if (dev->attached == 0) { + comedi_error(dev, "premature interrupt"); + return; + } + // initialize async here to make sure it is not NULL + async = s->async; + cmd = &async->cmd; + + if (devpriv->dma_chan == 0) { + comedi_error(dev, "interrupt with no dma channel?"); + return; + } + + comedi_spin_lock_irqsave(&dev->spinlock, spin_flags); + if ((devpriv->control_state & DMA_ENABLE) == 0) { + comedi_spin_unlock_irqrestore(&dev->spinlock, spin_flags); + DEBUG_PRINT("interrupt while dma disabled?\n"); + return; + } + + dma_flags = claim_dma_lock(); + clear_dma_ff(devpriv->dma_chan); + residue = disable_dma_on_even(dev); + + // figure out how many points to read + if (residue > devpriv->dma_transfer_size) { + comedi_error(dev, "residue > transfer size!\n"); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + num_bytes = 0; + } else + num_bytes = devpriv->dma_transfer_size - residue; + + if (cmd->stop_src == TRIG_COUNT && num_bytes >= devpriv->adc_byte_count) { + num_bytes = devpriv->adc_byte_count; + async->events |= COMEDI_CB_EOA; + } + + buffer_index = devpriv->current_buffer; + devpriv->current_buffer = (devpriv->current_buffer + 1) % 2; + devpriv->adc_byte_count -= num_bytes; + + // figure out how many bytes for next transfer + if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 && + devpriv->dma_transfer_size > devpriv->adc_byte_count) + devpriv->dma_transfer_size = devpriv->adc_byte_count; + + // re-enable dma + if ((async->events & COMEDI_CB_EOA) == 0) { + set_dma_addr(devpriv->dma_chan, + devpriv->dma_buffer_addr[devpriv->current_buffer]); + set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); + enable_dma(devpriv->dma_chan); + /* reenable conversions for das1600 mode, (stupid hardware) */ + if (thisboard->size > 0x400 && devpriv->timer_mode == 0) { + outb(0x00, dev->iobase + DAS1600_CONV); + } + } + release_dma_lock(dma_flags); + + comedi_spin_unlock_irqrestore(&dev->spinlock, spin_flags); + + cfc_write_array_to_buffer(s, + devpriv->dma_buffer[buffer_index], num_bytes); + + cfc_handle_events(dev, s); +} + +static unsigned int das16_set_pacer(struct comedi_device * dev, unsigned int ns, + int rounding_flags) +{ + i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1), + &(devpriv->divisor2), &ns, rounding_flags & TRIG_ROUND_MASK); + + /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ + i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2); + i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2); + + return ns; +} + +static void reg_dump(struct comedi_device * dev) +{ + DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n"); + DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX)); + DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO)); + DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS)); + DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL)); + DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER)); + DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN)); + DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n", + inb(dev->iobase + DAS16_CNTR_CONTROL)); + DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV)); + DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST)); + DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE)); + DEBUG_PRINT("DAS1600_STATUS_B: %x\n", + inb(dev->iobase + DAS1600_STATUS_B)); +} + +static int das16_probe(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int status; + int diobits; + + /* status is available on all boards */ + + status = inb(dev->iobase + DAS16_STATUS); + + if ((status & UNIPOLAR)) { + devpriv->ai_unipolar = 1; + } else { + devpriv->ai_unipolar = 0; + } + + if ((status & DAS16_MUXBIT)) { + devpriv->ai_singleended = 1; + } else { + devpriv->ai_singleended = 0; + } + + /* diobits indicates boards */ + + diobits = inb(dev->iobase + DAS16_DIO) & 0xf0; + + printk(" id bits are 0x%02x\n", diobits); + if (thisboard->id != diobits) { + printk(" requested board's id bits are 0x%x (ignore)\n", + thisboard->id); + } + + return 0; +} + +static int das1600_mode_detect(struct comedi_device * dev) +{ + int status = 0; + + status = inb(dev->iobase + DAS1600_STATUS_B); + + if (status & DAS1600_CLK_10MHZ) { + devpriv->clockbase = 100; + printk(" 10MHz pacer clock\n"); + } else { + devpriv->clockbase = 1000; + printk(" 1MHz pacer clock\n"); + } + + reg_dump(dev); + + return 0; +} + +/* + * + * Options list: + * 0 I/O base + * 1 IRQ + * 2 DMA + * 3 Clock speed (in MHz) + */ + +static int das16_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret; + unsigned int irq; + unsigned long iobase; + unsigned int dma_chan; + int timer_mode; + unsigned long flags; + struct comedi_krange *user_ai_range, *user_ao_range; + + iobase = it->options[0]; +#if 0 + irq = it->options[1]; + timer_mode = it->options[8]; +#endif + /* always use time_mode since using irq can drop samples while + * waiting for dma done interrupt (due to hardware limitations) */ + irq = 0; + timer_mode = 1; + if (timer_mode) + irq = 0; + + printk("comedi%d: das16:", dev->minor); + + // check that clock setting is valid + if (it->options[3]) { + if (it->options[3] != 0 && + it->options[3] != 1 && it->options[3] != 10) { + printk("\n Invalid option. Master clock must be set to 1 or 10 (MHz)\n"); + return -EINVAL; + } + } + + if ((ret = alloc_private(dev, sizeof(struct das16_private_struct))) < 0) + return ret; + + if (thisboard->size < 0x400) { + printk(" 0x%04lx-0x%04lx\n", iobase, iobase + thisboard->size); + if (!request_region(iobase, thisboard->size, "das16")) { + printk(" I/O port conflict\n"); + return -EIO; + } + } else { + printk(" 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n", + iobase, iobase + 0x0f, + iobase + 0x400, + iobase + 0x400 + (thisboard->size & 0x3ff)); + if (!request_region(iobase, 0x10, "das16")) { + printk(" I/O port conflict: 0x%04lx-0x%04lx\n", + iobase, iobase + 0x0f); + return -EIO; + } + if (!request_region(iobase + 0x400, thisboard->size & 0x3ff, + "das16")) { + release_region(iobase, 0x10); + printk(" I/O port conflict: 0x%04lx-0x%04lx\n", + iobase + 0x400, + iobase + 0x400 + (thisboard->size & 0x3ff)); + return -EIO; + } + } + + dev->iobase = iobase; + + // probe id bits to make sure they are consistent + if (das16_probe(dev, it)) { + printk(" id bits do not match selected board, aborting\n"); + return -EINVAL; + } + dev->board_name = thisboard->name; + + // get master clock speed + if (thisboard->size < 0x400) { + if (it->options[3]) + devpriv->clockbase = 1000 / it->options[3]; + else + devpriv->clockbase = 1000; // 1 MHz default + } else { + das1600_mode_detect(dev); + } + + /* now for the irq */ + if (irq > 1 && irq < 8) { + if ((ret = comedi_request_irq(irq, das16_dma_interrupt, 0, + "das16", dev)) < 0) + return ret; + dev->irq = irq; + printk(" ( irq = %u )", irq); + } else if (irq == 0) { + printk(" ( no irq )"); + } else { + printk(" invalid irq\n"); + return -EINVAL; + } + + // initialize dma + dma_chan = it->options[2]; + if (dma_chan == 1 || dma_chan == 3) { + // allocate dma buffers + int i; + for (i = 0; i < 2; i++) { + devpriv->dma_buffer[i] = pci_alloc_consistent(NULL, + DAS16_DMA_SIZE, &devpriv->dma_buffer_addr[i]); + if (devpriv->dma_buffer[i] == NULL) + return -ENOMEM; + } + if (request_dma(dma_chan, "das16")) { + printk(" failed to allocate dma channel %i\n", + dma_chan); + return -EINVAL; + } + devpriv->dma_chan = dma_chan; + flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); + release_dma_lock(flags); + printk(" ( dma = %u)\n", dma_chan); + } else if (dma_chan == 0) { + printk(" ( no dma )\n"); + } else { + printk(" invalid dma channel\n"); + return -EINVAL; + } + + // get any user-defined input range + if (thisboard->ai_pg == das16_pg_none && + (it->options[4] || it->options[5])) { + // allocate single-range range table + devpriv->user_ai_range_table = + kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange), + GFP_KERNEL); + // initialize ai range + devpriv->user_ai_range_table->length = 1; + user_ai_range = devpriv->user_ai_range_table->range; + user_ai_range->min = it->options[4]; + user_ai_range->max = it->options[5]; + user_ai_range->flags = UNIT_volt; + } + // get any user-defined output range + if (it->options[6] || it->options[7]) { + // allocate single-range range table + devpriv->user_ao_range_table = + kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange), + GFP_KERNEL); + // initialize ao range + devpriv->user_ao_range_table->length = 1; + user_ao_range = devpriv->user_ao_range_table->range; + user_ao_range->min = it->options[6]; + user_ao_range->max = it->options[7]; + user_ao_range->flags = UNIT_volt; + } + + if (timer_mode) { + init_timer(&(devpriv->timer)); + devpriv->timer.function = das16_timer_interrupt; + devpriv->timer.data = (unsigned long)dev; + } + devpriv->timer_mode = timer_mode ? 1 : 0; + + if ((ret = alloc_subdevices(dev, 5)) < 0) + return ret; + + s = dev->subdevices + 0; + dev->read_subdev = s; + /* ai */ + if (thisboard->ai) { + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + if (devpriv->ai_singleended) { + s->n_chan = 16; + s->len_chanlist = 16; + s->subdev_flags |= SDF_GROUND; + } else { + s->n_chan = 8; + s->len_chanlist = 8; + s->subdev_flags |= SDF_DIFF; + } + s->maxdata = (1 << thisboard->ai_nbits) - 1; + if (devpriv->user_ai_range_table) { // user defined ai range + s->range_table = devpriv->user_ai_range_table; + } else if (devpriv->ai_unipolar) { + s->range_table = das16_ai_uni_lranges[thisboard->ai_pg]; + } else { + s->range_table = das16_ai_bip_lranges[thisboard->ai_pg]; + } + s->insn_read = thisboard->ai; + s->do_cmdtest = das16_cmd_test; + s->do_cmd = das16_cmd_exec; + s->cancel = das16_cancel; + s->munge = das16_ai_munge; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 1; + /* ao */ + if (thisboard->ao) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->maxdata = (1 << thisboard->ao_nbits) - 1; + if (devpriv->user_ao_range_table) { // user defined ao range + s->range_table = devpriv->user_ao_range_table; + } else { + s->range_table = &range_unknown; + } + s->insn_write = thisboard->ao; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 2; + /* di */ + if (thisboard->di) { + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = thisboard->di; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 3; + /* do */ + if (thisboard->do_) { + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = thisboard->do_; + // initialize digital output lines + outb(s->state, dev->iobase + DAS16_DIO); + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 4; + /* 8255 */ + if (thisboard->i8255_offset != 0) { + subdev_8255_init(dev, s, NULL, (dev->iobase + + thisboard->i8255_offset)); + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + das16_reset(dev); + /* set the interrupt level */ + devpriv->control_state = DAS16_IRQ(dev->irq); + outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); + + // turn on das1600 mode if available + if (thisboard->size > 0x400) { + outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE); + outb(0, dev->iobase + DAS1600_CONV); + outb(0, dev->iobase + DAS1600_BURST); + } + + return 0; +} + +static int das16_detach(struct comedi_device * dev) +{ + printk("comedi%d: das16: remove\n", dev->minor); + + das16_reset(dev); + + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 4); + + if (devpriv) { + int i; + for (i = 0; i < 2; i++) { + if (devpriv->dma_buffer[i]) + pci_free_consistent(NULL, DAS16_DMA_SIZE, + devpriv->dma_buffer[i], + devpriv->dma_buffer_addr[i]); + } + if (devpriv->dma_chan) + free_dma(devpriv->dma_chan); + if (devpriv->user_ai_range_table) + kfree(devpriv->user_ai_range_table); + if (devpriv->user_ao_range_table) + kfree(devpriv->user_ao_range_table); + } + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + if (dev->iobase) { + if (thisboard->size < 0x400) { + release_region(dev->iobase, thisboard->size); + } else { + release_region(dev->iobase, 0x10); + release_region(dev->iobase + 0x400, + thisboard->size & 0x3ff); + } + } + + return 0; +} + +COMEDI_INITCLEANUP(driver_das16); + +// utility function that suggests a dma transfer size in bytes +static unsigned int das16_suggest_transfer_size(struct comedi_device * dev, + struct comedi_cmd cmd) +{ + unsigned int size; + unsigned int freq; + + /* if we are using timer interrupt, we don't care how long it + * will take to complete transfer since it will be interrupted + * by timer interrupt */ + if (devpriv->timer_mode) + return DAS16_DMA_SIZE; + + /* otherwise, we are relying on dma terminal count interrupt, + * so pick a reasonable size */ + if (cmd.convert_src == TRIG_TIMER) + freq = 1000000000 / cmd.convert_arg; + else if (cmd.scan_begin_src == TRIG_TIMER) + freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len; + // return some default value + else + freq = 0xffffffff; + + if (cmd.flags & TRIG_WAKE_EOS) { + size = sample_size * cmd.chanlist_len; + } else { + // make buffer fill in no more than 1/3 second + size = (freq / 3) * sample_size; + } + + // set a minimum and maximum size allowed + if (size > DAS16_DMA_SIZE) + size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size; + else if (size < sample_size) + size = sample_size; + + if (cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count) + size = devpriv->adc_byte_count; + + return size; +} + +static void das16_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s, + void *array, unsigned int num_bytes, unsigned int start_chan_index) +{ + unsigned int i, num_samples = num_bytes / sizeof(short); + short *data = array; + + for (i = 0; i < num_samples; i++) { + data[i] = le16_to_cpu(data[i]); + if (thisboard->ai_nbits == 12) { + data[i] = (data[i] >> 4) & 0xfff; + } + } +} diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c new file mode 100644 index 000000000000..0e423e199ed6 --- /dev/null +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -0,0 +1,765 @@ +/* + comedi/drivers/das16m1.c + CIO-DAS16/M1 driver + Author: Frank Mori Hess, based on code from the das16 + driver. + Copyright (C) 2001 Frank Mori Hess + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: das16m1 +Description: CIO-DAS16/M1 +Author: Frank Mori Hess +Devices: [Measurement Computing] CIO-DAS16/M1 (cio-das16/m1) +Status: works + +This driver supports a single board - the CIO-DAS16/M1. +As far as I know, there are no other boards that have +the same register layout. Even the CIO-DAS16/M1/16 is +significantly different. + +I was _barely_ able to reach the full 1 MHz capability +of this board, using a hard real-time interrupt +(set the TRIG_RT flag in your struct comedi_cmd and use +rtlinux or RTAI). The board can't do dma, so the bottleneck is +pulling the data across the ISA bus. I timed the interrupt +handler, and it took my computer ~470 microseconds to pull 512 +samples from the board. So at 1 Mhz sampling rate, +expect your CPU to be spending almost all of its +time in the interrupt handler. + +This board has some unusual restrictions for its channel/gain list. If the +list has 2 or more channels in it, then two conditions must be satisfied: +(1) - even/odd channels must appear at even/odd indices in the list +(2) - the list must have an even number of entries. + +Options: + [0] - base io address + [1] - irq (optional, but you probably want it) + +irq can be omitted, although the cmd interface will not work without it. +*/ + +#include +#include "../comedidev.h" + +#include "8255.h" +#include "8253.h" +#include "comedi_fc.h" + +#define DAS16M1_SIZE 16 +#define DAS16M1_SIZE2 8 + +#define DAS16M1_XTAL 100 //10 MHz master clock + +#define FIFO_SIZE 1024 // 1024 sample fifo + +/* + CIO-DAS16_M1.pdf + + "cio-das16/m1" + + 0 a/d bits 0-3, mux start 12 bit + 1 a/d bits 4-11 unused + 2 status control + 3 di 4 bit do 4 bit + 4 unused clear interrupt + 5 interrupt, pacer + 6 channel/gain queue address + 7 channel/gain queue data + 89ab 8254 + cdef 8254 + 400 8255 + 404-407 8254 + +*/ + +#define DAS16M1_AI 0 // 16-bit wide register +#define AI_CHAN(x) ((x) & 0xf) +#define DAS16M1_CS 2 +#define EXT_TRIG_BIT 0x1 +#define OVRUN 0x20 +#define IRQDATA 0x80 +#define DAS16M1_DIO 3 +#define DAS16M1_CLEAR_INTR 4 +#define DAS16M1_INTR_CONTROL 5 +#define EXT_PACER 0x2 +#define INT_PACER 0x3 +#define PACER_MASK 0x3 +#define INTE 0x80 +#define DAS16M1_QUEUE_ADDR 6 +#define DAS16M1_QUEUE_DATA 7 +#define Q_CHAN(x) ((x) & 0x7) +#define Q_RANGE(x) (((x) & 0xf) << 4) +#define UNIPOLAR 0x40 +#define DAS16M1_8254_FIRST 0x8 +#define DAS16M1_8254_FIRST_CNTRL 0xb +#define TOTAL_CLEAR 0x30 +#define DAS16M1_8254_SECOND 0xc +#define DAS16M1_82C55 0x400 +#define DAS16M1_8254_THIRD 0x404 + +static const struct comedi_lrange range_das16m1 = { 9, + { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + BIP_RANGE(10), + } +}; + +static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s); +static int das16m1_cancel(struct comedi_device * dev, struct comedi_subdevice * s); + +static int das16m1_poll(struct comedi_device * dev, struct comedi_subdevice * s); +static irqreturn_t das16m1_interrupt(int irq, void *d PT_REGS_ARG); +static void das16m1_handler(struct comedi_device * dev, unsigned int status); + +static unsigned int das16m1_set_pacer(struct comedi_device * dev, unsigned int ns, + int round_flag); + +static int das16m1_irq_bits(unsigned int irq); + +struct das16m1_board { + const char *name; + unsigned int ai_speed; +}; + +static const struct das16m1_board das16m1_boards[] = { + { + name: "cio-das16/m1", // CIO-DAS16_M1.pdf + ai_speed:1000, // 1MHz max speed + }, +}; + +#define das16m1_num_boards ((sizeof(das16m1_boards)) / (sizeof(das16m1_boards[0]))) + +static int das16m1_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int das16m1_detach(struct comedi_device * dev); +static struct comedi_driver driver_das16m1 = { + driver_name:"das16m1", + module:THIS_MODULE, + attach:das16m1_attach, + detach:das16m1_detach, + board_name:&das16m1_boards[0].name, + num_names:das16m1_num_boards, + offset:sizeof(das16m1_boards[0]), +}; + +struct das16m1_private_struct { + unsigned int control_state; + volatile unsigned int adc_count; // number of samples completed + /* initial value in lower half of hardware conversion counter, + * needed to keep track of whether new count has been loaded into + * counter yet (loaded by first sample conversion) */ + u16 initial_hw_count; + short ai_buffer[FIFO_SIZE]; + unsigned int do_bits; // saves status of digital output bits + unsigned int divisor1; // divides master clock to obtain conversion speed + unsigned int divisor2; // divides master clock to obtain conversion speed +}; +#define devpriv ((struct das16m1_private_struct *)(dev->private)) +#define thisboard ((const struct das16m1_board *)(dev->board_ptr)) + +COMEDI_INITCLEANUP(driver_das16m1); + +static inline short munge_sample(short data) +{ + return (data >> 4) & 0xfff; +} + +static int das16m1_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + unsigned int err = 0, tmp, i; + + /* make sure triggers are valid */ + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + if (cmd->scan_begin_src == TRIG_FOLLOW) { + /* internal trigger */ + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + } + + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < thisboard->ai_speed) { + cmd->convert_arg = thisboard->ai_speed; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + if (cmd->stop_src == TRIG_COUNT) { + /* any count is allowed */ + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up arguments */ + + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + /* calculate counter values that give desired timing */ + i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, + &(devpriv->divisor1), &(devpriv->divisor2), + &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + } + + if (err) + return 4; + + // check chanlist against board's peculiarities + if (cmd->chanlist && cmd->chanlist_len > 1) { + for (i = 0; i < cmd->chanlist_len; i++) { + // even/odd channels must go into even/odd queue addresses + if ((i % 2) != (CR_CHAN(cmd->chanlist[i]) % 2)) { + comedi_error(dev, "bad chanlist:\n" + " even/odd channels must go have even/odd chanlist indices"); + err++; + } + } + if ((cmd->chanlist_len % 2) != 0) { + comedi_error(dev, + "chanlist must be of even length or length 1"); + err++; + } + } + + if (err) + return 5; + + return 0; +} + +static int das16m1_cmd_exec(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int byte, i; + + if (dev->irq == 0) { + comedi_error(dev, "irq required to execute comedi_cmd"); + return -1; + } + + /* disable interrupts and internal pacer */ + devpriv->control_state &= ~INTE & ~PACER_MASK; + outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); + + // set software count + devpriv->adc_count = 0; + /* Initialize lower half of hardware counter, used to determine how + * many samples are in fifo. Value doesn't actually load into counter + * until counter's next clock (the next a/d conversion) */ + i8254_load(dev->iobase + DAS16M1_8254_FIRST, 0, 1, 0, 2); + /* remember current reading of counter so we know when counter has + * actually been loaded */ + devpriv->initial_hw_count = + i8254_read(dev->iobase + DAS16M1_8254_FIRST, 0, 1); + /* setup channel/gain queue */ + for (i = 0; i < cmd->chanlist_len; i++) { + outb(i, dev->iobase + DAS16M1_QUEUE_ADDR); + byte = Q_CHAN(CR_CHAN(cmd-> + chanlist[i])) | Q_RANGE(CR_RANGE(cmd-> + chanlist[i])); + outb(byte, dev->iobase + DAS16M1_QUEUE_DATA); + } + + /* set counter mode and counts */ + cmd->convert_arg = + das16m1_set_pacer(dev, cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + + // set control & status register + byte = 0; + /* if we are using external start trigger (also board dislikes having + * both start and conversion triggers external simultaneously) */ + if (cmd->start_src == TRIG_EXT && cmd->convert_src != TRIG_EXT) { + byte |= EXT_TRIG_BIT; + } + outb(byte, dev->iobase + DAS16M1_CS); + /* clear interrupt bit */ + outb(0, dev->iobase + DAS16M1_CLEAR_INTR); + + /* enable interrupts and internal pacer */ + devpriv->control_state &= ~PACER_MASK; + if (cmd->convert_src == TRIG_TIMER) { + devpriv->control_state |= INT_PACER; + } else { + devpriv->control_state |= EXT_PACER; + } + devpriv->control_state |= INTE; + outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); + + return 0; +} + +static int das16m1_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + devpriv->control_state &= ~INTE & ~PACER_MASK; + outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); + + return 0; +} + +static int das16m1_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, n; + int byte; + const int timeout = 1000; + + /* disable interrupts and internal pacer */ + devpriv->control_state &= ~INTE & ~PACER_MASK; + outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); + + /* setup channel/gain queue */ + outb(0, dev->iobase + DAS16M1_QUEUE_ADDR); + byte = Q_CHAN(CR_CHAN(insn->chanspec)) | Q_RANGE(CR_RANGE(insn-> + chanspec)); + outb(byte, dev->iobase + DAS16M1_QUEUE_DATA); + + for (n = 0; n < insn->n; n++) { + /* clear IRQDATA bit */ + outb(0, dev->iobase + DAS16M1_CLEAR_INTR); + /* trigger conversion */ + outb(0, dev->iobase); + + for (i = 0; i < timeout; i++) { + if (inb(dev->iobase + DAS16M1_CS) & IRQDATA) + break; + } + if (i == timeout) { + comedi_error(dev, "timeout"); + return -ETIME; + } + data[n] = munge_sample(inw(dev->iobase)); + } + + return n; +} + +static int das16m1_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int bits; + + bits = inb(dev->iobase + DAS16M1_DIO) & 0xf; + data[1] = bits; + data[0] = 0; + + return 2; +} + +static int das16m1_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int wbits; + + // only set bits that have been masked + data[0] &= 0xf; + wbits = devpriv->do_bits; + // zero bits that have been masked + wbits &= ~data[0]; + // set masked bits + wbits |= data[0] & data[1]; + devpriv->do_bits = wbits; + data[1] = wbits; + + outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO); + + return 2; +} + +static int das16m1_poll(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + unsigned int status; + + // prevent race with interrupt handler + comedi_spin_lock_irqsave(&dev->spinlock, flags); + status = inb(dev->iobase + DAS16M1_CS); + das16m1_handler(dev, status); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + return s->async->buf_write_count - s->async->buf_read_count; +} + +static irqreturn_t das16m1_interrupt(int irq, void *d PT_REGS_ARG) +{ + int status; + struct comedi_device *dev = d; + + if (dev->attached == 0) { + comedi_error(dev, "premature interrupt"); + return IRQ_HANDLED; + } + // prevent race with comedi_poll() + spin_lock(&dev->spinlock); + + status = inb(dev->iobase + DAS16M1_CS); + + if ((status & (IRQDATA | OVRUN)) == 0) { + comedi_error(dev, "spurious interrupt"); + spin_unlock(&dev->spinlock); + return IRQ_NONE; + } + + das16m1_handler(dev, status); + + /* clear interrupt */ + outb(0, dev->iobase + DAS16M1_CLEAR_INTR); + + spin_unlock(&dev->spinlock); + return IRQ_HANDLED; +} + +static void munge_sample_array(short * array, unsigned int num_elements) +{ + unsigned int i; + + for (i = 0; i < num_elements; i++) { + array[i] = munge_sample(array[i]); + } +} + +static void das16m1_handler(struct comedi_device * dev, unsigned int status) +{ + struct comedi_subdevice *s; + struct comedi_async *async; + struct comedi_cmd *cmd; + u16 num_samples; + u16 hw_counter; + + s = dev->read_subdev; + async = s->async; + async->events = 0; + cmd = &async->cmd; + + // figure out how many samples are in fifo + hw_counter = i8254_read(dev->iobase + DAS16M1_8254_FIRST, 0, 1); + /* make sure hardware counter reading is not bogus due to initial value + * not having been loaded yet */ + if (devpriv->adc_count == 0 && hw_counter == devpriv->initial_hw_count) { + num_samples = 0; + } else { + /* The calculation of num_samples looks odd, but it uses the following facts. + * 16 bit hardware counter is initialized with value of zero (which really + * means 0x1000). The counter decrements by one on each conversion + * (when the counter decrements from zero it goes to 0xffff). num_samples + * is a 16 bit variable, so it will roll over in a similar fashion to the + * hardware counter. Work it out, and this is what you get. */ + num_samples = -hw_counter - devpriv->adc_count; + } + // check if we only need some of the points + if (cmd->stop_src == TRIG_COUNT) { + if (num_samples > cmd->stop_arg * cmd->chanlist_len) + num_samples = cmd->stop_arg * cmd->chanlist_len; + } + // make sure we dont try to get too many points if fifo has overrun + if (num_samples > FIFO_SIZE) + num_samples = FIFO_SIZE; + insw(dev->iobase, devpriv->ai_buffer, num_samples); + munge_sample_array(devpriv->ai_buffer, num_samples); + cfc_write_array_to_buffer(s, devpriv->ai_buffer, + num_samples * sizeof(short)); + devpriv->adc_count += num_samples; + + if (cmd->stop_src == TRIG_COUNT) { + if (devpriv->adc_count >= cmd->stop_arg * cmd->chanlist_len) { /* end of acquisition */ + das16m1_cancel(dev, s); + async->events |= COMEDI_CB_EOA; + } + } + + /* this probably won't catch overruns since the card doesn't generate + * overrun interrupts, but we might as well try */ + if (status & OVRUN) { + das16m1_cancel(dev, s); + async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_error(dev, "fifo overflow"); + } + + comedi_event(dev, s); + +} + +/* This function takes a time in nanoseconds and sets the * + * 2 pacer clocks to the closest frequency possible. It also * + * returns the actual sampling period. */ +static unsigned int das16m1_set_pacer(struct comedi_device * dev, unsigned int ns, + int rounding_flags) +{ + i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1), + &(devpriv->divisor2), &ns, rounding_flags & TRIG_ROUND_MASK); + + /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ + i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 1, devpriv->divisor1, + 2); + i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 2, devpriv->divisor2, + 2); + + return ns; +} + +static int das16m1_irq_bits(unsigned int irq) +{ + int ret; + + switch (irq) { + case 10: + ret = 0x0; + break; + case 11: + ret = 0x1; + break; + case 12: + ret = 0x2; + break; + case 15: + ret = 0x3; + break; + case 2: + ret = 0x4; + break; + case 3: + ret = 0x5; + break; + case 5: + ret = 0x6; + break; + case 7: + ret = 0x7; + break; + default: + return -1; + break; + } + return (ret << 4); +} + +/* + * Options list: + * 0 I/O base + * 1 IRQ + */ + +static int das16m1_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret; + unsigned int irq; + unsigned long iobase; + + iobase = it->options[0]; + + printk("comedi%d: das16m1:", dev->minor); + + if ((ret = alloc_private(dev, + sizeof(struct das16m1_private_struct))) < 0) + return ret; + + dev->board_name = thisboard->name; + + printk(" io 0x%lx-0x%lx 0x%lx-0x%lx", + iobase, iobase + DAS16M1_SIZE, + iobase + DAS16M1_82C55, iobase + DAS16M1_82C55 + DAS16M1_SIZE2); + if (!request_region(iobase, DAS16M1_SIZE, driver_das16m1.driver_name)) { + printk(" I/O port conflict\n"); + return -EIO; + } + if (!request_region(iobase + DAS16M1_82C55, DAS16M1_SIZE2, + driver_das16m1.driver_name)) { + release_region(iobase, DAS16M1_SIZE); + printk(" I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + /* now for the irq */ + irq = it->options[1]; + // make sure it is valid + if (das16m1_irq_bits(irq) >= 0) { + ret = comedi_request_irq(irq, das16m1_interrupt, 0, + driver_das16m1.driver_name, dev); + if (ret < 0) { + printk(", irq unavailable\n"); + return ret; + } + dev->irq = irq; + printk(", irq %u\n", irq); + } else if (irq == 0) { + printk(", no irq\n"); + } else { + printk(", invalid irq\n" + " valid irqs are 2, 3, 5, 7, 10, 11, 12, or 15\n"); + return -EINVAL; + } + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + + s = dev->subdevices + 0; + dev->read_subdev = s; + /* ai */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 8; + s->subdev_flags = SDF_DIFF; + s->len_chanlist = 256; + s->maxdata = (1 << 12) - 1; + s->range_table = &range_das16m1; + s->insn_read = das16m1_ai_rinsn; + s->do_cmdtest = das16m1_cmd_test; + s->do_cmd = das16m1_cmd_exec; + s->cancel = das16m1_cancel; + s->poll = das16m1_poll; + + s = dev->subdevices + 1; + /* di */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das16m1_di_rbits; + + s = dev->subdevices + 2; + /* do */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das16m1_do_wbits; + + s = dev->subdevices + 3; + /* 8255 */ + subdev_8255_init(dev, s, NULL, dev->iobase + DAS16M1_82C55); + + // disable upper half of hardware conversion counter so it doesn't mess with us + outb(TOTAL_CLEAR, dev->iobase + DAS16M1_8254_FIRST_CNTRL); + + // initialize digital output lines + outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO); + + /* set the interrupt level */ + if (dev->irq) + devpriv->control_state = das16m1_irq_bits(dev->irq); + else + devpriv->control_state = 0; + outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); + + return 0; +} + +static int das16m1_detach(struct comedi_device * dev) +{ + printk("comedi%d: das16m1: remove\n", dev->minor); + +// das16m1_reset(dev); + + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 3); + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + if (dev->iobase) { + release_region(dev->iobase, DAS16M1_SIZE); + release_region(dev->iobase + DAS16M1_82C55, DAS16M1_SIZE2); + } + + return 0; +} diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c new file mode 100644 index 000000000000..cd4cd4e6a79b --- /dev/null +++ b/drivers/staging/comedi/drivers/das1800.c @@ -0,0 +1,1758 @@ +/* + comedi/drivers/das1800.c + Driver for Keitley das1700/das1800 series boards + Copyright (C) 2000 Frank Mori Hess + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: das1800 +Description: Keithley Metrabyte DAS1800 (& compatibles) +Author: Frank Mori Hess +Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st), + DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao), + DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da), + DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da), + DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st), + DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc), + DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st), + DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr), + DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc), + DAS-1802AO (das-1802ao) +Status: works + +The waveform analog output on the 'ao' cards is not supported. +If you need it, send me (Frank Hess) an email. + +Configuration options: + [0] - I/O port base address + [1] - IRQ (optional, required for timed or externally triggered conversions) + [2] - DMA0 (optional, requires irq) + [3] - DMA1 (optional, requires irq and dma0) +*/ +/* + +This driver supports the following Keithley boards: + +das-1701st +das-1701st-da +das-1701ao +das-1702st +das-1702st-da +das-1702hr +das-1702hr-da +das-1702ao +das-1801st +das-1801st-da +das-1801hc +das-1801ao +das-1802st +das-1802st-da +das-1802hr +das-1802hr-da +das-1802hc +das-1802ao + +Options: + [0] - base io address + [1] - irq (optional, required for timed or externally triggered conversions) + [2] - dma0 (optional, requires irq) + [3] - dma1 (optional, requires irq and dma0) + +irq can be omitted, although the cmd interface will not work without it. + +analog input cmd triggers supported: + start_src: TRIG_NOW | TRIG_EXT + scan_begin_src: TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT + scan_end_src: TRIG_COUNT + convert_src: TRIG_TIMER | TRIG_EXT (TRIG_EXT requires scan_begin_src == TRIG_FOLLOW) + stop_src: TRIG_COUNT | TRIG_EXT | TRIG_NONE + +scan_begin_src triggers TRIG_TIMER and TRIG_EXT use the card's +'burst mode' which limits the valid conversion time to 64 microseconds +(convert_arg <= 64000). This limitation does not apply if scan_begin_src +is TRIG_FOLLOW. + +NOTES: +Only the DAS-1801ST has been tested by me. +Unipolar and bipolar ranges cannot be mixed in the channel/gain list. + +TODO: + Make it automatically allocate irq and dma channels if they are not specified + Add support for analog out on 'ao' cards + read insn for analog out +*/ + +#include "../comedidev.h" + +#include +#include + +#include "8253.h" +#include "comedi_fc.h" + +// misc. defines +#define DAS1800_SIZE 16 //uses 16 io addresses +#define FIFO_SIZE 1024 // 1024 sample fifo +#define TIMER_BASE 200 // 5 Mhz master clock +#define UNIPOLAR 0x4 // bit that determines whether input range is uni/bipolar +#define DMA_BUF_SIZE 0x1ff00 // size in bytes of dma buffers + +/* Registers for the das1800 */ +#define DAS1800_FIFO 0x0 +#define DAS1800_QRAM 0x0 +#define DAS1800_DAC 0x0 +#define DAS1800_SELECT 0x2 +#define ADC 0x0 +#define QRAM 0x1 +#define DAC(a) (0x2 + a) +#define DAS1800_DIGITAL 0x3 +#define DAS1800_CONTROL_A 0x4 +#define FFEN 0x1 +#define CGEN 0x4 +#define CGSL 0x8 +#define TGEN 0x10 +#define TGSL 0x20 +#define ATEN 0x80 +#define DAS1800_CONTROL_B 0x5 +#define DMA_CH5 0x1 +#define DMA_CH6 0x2 +#define DMA_CH7 0x3 +#define DMA_CH5_CH6 0x5 +#define DMA_CH6_CH7 0x6 +#define DMA_CH7_CH5 0x7 +#define DMA_ENABLED 0x3 //mask used to determine if dma is enabled +#define DMA_DUAL 0x4 +#define IRQ3 0x8 +#define IRQ5 0x10 +#define IRQ7 0x18 +#define IRQ10 0x28 +#define IRQ11 0x30 +#define IRQ15 0x38 +#define FIMD 0x40 +#define DAS1800_CONTROL_C 0X6 +#define IPCLK 0x1 +#define XPCLK 0x3 +#define BMDE 0x4 +#define CMEN 0x8 +#define UQEN 0x10 +#define SD 0x40 +#define UB 0x80 +#define DAS1800_STATUS 0x7 +// bits that prevent interrupt status bits (and CVEN) from being cleared on write +#define CLEAR_INTR_MASK (CVEN_MASK | 0x1f) +#define INT 0x1 +#define DMATC 0x2 +#define CT0TC 0x8 +#define OVF 0x10 +#define FHF 0x20 +#define FNE 0x40 +#define CVEN_MASK 0x40 // masks CVEN on write +#define CVEN 0x80 +#define DAS1800_BURST_LENGTH 0x8 +#define DAS1800_BURST_RATE 0x9 +#define DAS1800_QRAM_ADDRESS 0xa +#define DAS1800_COUNTER 0xc + +#define IOBASE2 0x400 //offset of additional ioports used on 'ao' cards + +enum { + das1701st, das1701st_da, das1702st, das1702st_da, das1702hr, + das1702hr_da, + das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da, + das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao +}; + +static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int das1800_detach(struct comedi_device * dev); +static int das1800_probe(struct comedi_device * dev); +static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG); +static int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s); +static void das1800_ai_handler(struct comedi_device * dev); +static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int status); +static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s); +static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int channel, uint16_t * buffer); +static void das1800_handle_fifo_half_full(struct comedi_device * dev, + struct comedi_subdevice * s); +static void das1800_handle_fifo_not_empty(struct comedi_device * dev, + struct comedi_subdevice * s); +static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int das1800_set_frequency(struct comedi_device * dev); +static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode); +static unsigned int suggest_transfer_size(struct comedi_cmd * cmd); + +// analog input ranges +static const struct comedi_lrange range_ai_das1801 = { + 8, + { + RANGE(-5, 5), + RANGE(-1, 1), + RANGE(-0.1, 0.1), + RANGE(-0.02, 0.02), + RANGE(0, 5), + RANGE(0, 1), + RANGE(0, 0.1), + RANGE(0, 0.02), + } +}; + +static const struct comedi_lrange range_ai_das1802 = { + 8, + { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2.5, 2.5), + RANGE(-1.25, 1.25), + RANGE(0, 10), + RANGE(0, 5), + RANGE(0, 2.5), + RANGE(0, 1.25), + } +}; + +struct das1800_board { + const char *name; + int ai_speed; /* max conversion period in nanoseconds */ + int resolution; /* bits of ai resolution */ + int qram_len; /* length of card's channel / gain queue */ + int common; /* supports AREF_COMMON flag */ + int do_n_chan; /* number of digital output channels */ + int ao_ability; /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */ + int ao_n_chan; /* number of analog out channels */ + const struct comedi_lrange *range_ai; /* available input ranges */ +}; + +/* Warning: the maximum conversion speeds listed below are + * not always achievable depending on board setup (see + * user manual.) + */ +static const struct das1800_board das1800_boards[] = { + { + name: "das-1701st", + ai_speed:6250, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:0, + ao_n_chan:0, + range_ai:&range_ai_das1801, + }, + { + name: "das-1701st-da", + ai_speed:6250, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:1, + ao_n_chan:4, + range_ai:&range_ai_das1801, + }, + { + name: "das-1702st", + ai_speed:6250, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:0, + ao_n_chan:0, + range_ai:&range_ai_das1802, + }, + { + name: "das-1702st-da", + ai_speed:6250, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:1, + ao_n_chan:4, + range_ai:&range_ai_das1802, + }, + { + name: "das-1702hr", + ai_speed:20000, + resolution:16, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:0, + ao_n_chan:0, + range_ai:&range_ai_das1802, + }, + { + name: "das-1702hr-da", + ai_speed:20000, + resolution:16, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:1, + ao_n_chan:2, + range_ai:&range_ai_das1802, + }, + { + name: "das-1701ao", + ai_speed:6250, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:2, + ao_n_chan:2, + range_ai:&range_ai_das1801, + }, + { + name: "das-1702ao", + ai_speed:6250, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:2, + ao_n_chan:2, + range_ai:&range_ai_das1802, + }, + { + name: "das-1801st", + ai_speed:3000, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:0, + ao_n_chan:0, + range_ai:&range_ai_das1801, + }, + { + name: "das-1801st-da", + ai_speed:3000, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:0, + ao_n_chan:4, + range_ai:&range_ai_das1801, + }, + { + name: "das-1802st", + ai_speed:3000, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:0, + ao_n_chan:0, + range_ai:&range_ai_das1802, + }, + { + name: "das-1802st-da", + ai_speed:3000, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:1, + ao_n_chan:4, + range_ai:&range_ai_das1802, + }, + { + name: "das-1802hr", + ai_speed:10000, + resolution:16, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:0, + ao_n_chan:0, + range_ai:&range_ai_das1802, + }, + { + name: "das-1802hr-da", + ai_speed:10000, + resolution:16, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:1, + ao_n_chan:2, + range_ai:&range_ai_das1802, + }, + { + name: "das-1801hc", + ai_speed:3000, + resolution:12, + qram_len:64, + common: 0, + do_n_chan:8, + ao_ability:1, + ao_n_chan:2, + range_ai:&range_ai_das1801, + }, + { + name: "das-1802hc", + ai_speed:3000, + resolution:12, + qram_len:64, + common: 0, + do_n_chan:8, + ao_ability:1, + ao_n_chan:2, + range_ai:&range_ai_das1802, + }, + { + name: "das-1801ao", + ai_speed:3000, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:2, + ao_n_chan:2, + range_ai:&range_ai_das1801, + }, + { + name: "das-1802ao", + ai_speed:3000, + resolution:12, + qram_len:256, + common: 1, + do_n_chan:4, + ao_ability:2, + ao_n_chan:2, + range_ai:&range_ai_das1802, + }, +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct das1800_board *)dev->board_ptr) + +struct das1800_private { + volatile unsigned int count; /* number of data points left to be taken */ + unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */ + unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */ + int do_bits; /* digital output bits */ + int irq_dma_bits; /* bits for control register b */ + /* dma bits for control register b, stored so that dma can be + * turned on and off */ + int dma_bits; + unsigned int dma0; /* dma channels used */ + unsigned int dma1; + volatile unsigned int dma_current; /* dma channel currently in use */ + uint16_t *ai_buf0; /* pointers to dma buffers */ + uint16_t *ai_buf1; + uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */ + unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */ + unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */ + short ao_update_bits; /* remembers the last write to the 'update' dac */ +}; + +#define devpriv ((struct das1800_private *)dev->private) + +// analog out range for boards with basic analog out +static const struct comedi_lrange range_ao_1 = { + 1, + { + RANGE(-10, 10), + } +}; + +// analog out range for 'ao' boards +/* +static const struct comedi_lrange range_ao_2 = { + 2, + { + RANGE(-10, 10), + RANGE(-5, 5), + } +}; +*/ + +static struct comedi_driver driver_das1800 = { + driver_name:"das1800", + module:THIS_MODULE, + attach:das1800_attach, + detach:das1800_detach, + num_names:sizeof(das1800_boards) / sizeof(struct das1800_board), + board_name:&das1800_boards[0].name, + offset:sizeof(struct das1800_board), +}; + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver_das1800); + +static int das1800_init_dma(struct comedi_device * dev, unsigned int dma0, + unsigned int dma1) +{ + unsigned long flags; + + // need an irq to do dma + if (dev->irq && dma0) { + //encode dma0 and dma1 into 2 digit hexadecimal for switch + switch ((dma0 & 0x7) | (dma1 << 4)) { + case 0x5: // dma0 == 5 + devpriv->dma_bits |= DMA_CH5; + break; + case 0x6: // dma0 == 6 + devpriv->dma_bits |= DMA_CH6; + break; + case 0x7: // dma0 == 7 + devpriv->dma_bits |= DMA_CH7; + break; + case 0x65: // dma0 == 5, dma1 == 6 + devpriv->dma_bits |= DMA_CH5_CH6; + break; + case 0x76: // dma0 == 6, dma1 == 7 + devpriv->dma_bits |= DMA_CH6_CH7; + break; + case 0x57: // dma0 == 7, dma1 == 5 + devpriv->dma_bits |= DMA_CH7_CH5; + break; + default: + printk(" only supports dma channels 5 through 7\n" + " Dual dma only allows the following combinations:\n" + " dma 5,6 / 6,7 / or 7,5\n"); + return -EINVAL; + break; + } + if (request_dma(dma0, driver_das1800.driver_name)) { + printk(" failed to allocate dma channel %i\n", dma0); + return -EINVAL; + } + devpriv->dma0 = dma0; + devpriv->dma_current = dma0; + if (dma1) { + if (request_dma(dma1, driver_das1800.driver_name)) { + printk(" failed to allocate dma channel %i\n", + dma1); + return -EINVAL; + } + devpriv->dma1 = dma1; + } + devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (devpriv->ai_buf0 == NULL) + return -ENOMEM; + devpriv->dma_current_buf = devpriv->ai_buf0; + if (dma1) { + devpriv->ai_buf1 = + kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (devpriv->ai_buf1 == NULL) + return -ENOMEM; + } + flags = claim_dma_lock(); + disable_dma(devpriv->dma0); + set_dma_mode(devpriv->dma0, DMA_MODE_READ); + if (dma1) { + disable_dma(devpriv->dma1); + set_dma_mode(devpriv->dma1, DMA_MODE_READ); + } + release_dma_lock(flags); + } + return 0; +} + +static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase = it->options[0]; + unsigned int irq = it->options[1]; + unsigned int dma0 = it->options[2]; + unsigned int dma1 = it->options[3]; + unsigned long iobase2; + int board; + int retval; + + /* allocate and initialize dev->private */ + if (alloc_private(dev, sizeof(struct das1800_private)) < 0) + return -ENOMEM; + + printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name, + iobase); + if (irq) { + printk(", irq %u", irq); + if (dma0) { + printk(", dma %u", dma0); + if (dma1) + printk(" and %u", dma1); + } + } + printk("\n"); + + if (iobase == 0) { + printk(" io base address required\n"); + return -EINVAL; + } + + /* check if io addresses are available */ + if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) { + printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase, iobase + DAS1800_SIZE - 1); + return -EIO; + } + dev->iobase = iobase; + + board = das1800_probe(dev); + if (board < 0) { + printk(" unable to determine board type\n"); + return -ENODEV; + } + + dev->board_ptr = das1800_boards + board; + dev->board_name = thisboard->name; + + // if it is an 'ao' board with fancy analog out then we need extra io ports + if (thisboard->ao_ability == 2) { + iobase2 = iobase + IOBASE2; + if (!request_region(iobase2, DAS1800_SIZE, + driver_das1800.driver_name)) { + printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase2, iobase2 + DAS1800_SIZE - 1); + return -EIO; + } + devpriv->iobase2 = iobase2; + } + + /* grab our IRQ */ + if (irq) { + if (comedi_request_irq(irq, das1800_interrupt, 0, + driver_das1800.driver_name, dev)) { + printk(" unable to allocate irq %u\n", irq); + return -EINVAL; + } + } + dev->irq = irq; + + // set bits that tell card which irq to use + switch (irq) { + case 0: + break; + case 3: + devpriv->irq_dma_bits |= 0x8; + break; + case 5: + devpriv->irq_dma_bits |= 0x10; + break; + case 7: + devpriv->irq_dma_bits |= 0x18; + break; + case 10: + devpriv->irq_dma_bits |= 0x28; + break; + case 11: + devpriv->irq_dma_bits |= 0x30; + break; + case 15: + devpriv->irq_dma_bits |= 0x38; + break; + default: + printk(" irq out of range\n"); + return -EINVAL; + break; + } + + retval = das1800_init_dma(dev, dma0, dma1); + if (retval < 0) + return retval; + + if (devpriv->ai_buf0 == NULL) { + devpriv->ai_buf0 = + kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL); + if (devpriv->ai_buf0 == NULL) + return -ENOMEM; + } + + if (alloc_subdevices(dev, 4) < 0) + return -ENOMEM; + + /* analog input subdevice */ + s = dev->subdevices + 0; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ; + if (thisboard->common) + s->subdev_flags |= SDF_COMMON; + s->n_chan = thisboard->qram_len; + s->len_chanlist = thisboard->qram_len; + s->maxdata = (1 << thisboard->resolution) - 1; + s->range_table = thisboard->range_ai; + s->do_cmd = das1800_ai_do_cmd; + s->do_cmdtest = das1800_ai_do_cmdtest; + s->insn_read = das1800_ai_rinsn; + s->poll = das1800_ai_poll; + s->cancel = das1800_cancel; + + /* analog out */ + s = dev->subdevices + 1; + if (thisboard->ao_ability == 1) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_n_chan; + s->maxdata = (1 << thisboard->resolution) - 1; + s->range_table = &range_ao_1; + s->insn_write = das1800_ao_winsn; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* di */ + s = dev->subdevices + 2; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das1800_di_rbits; + + /* do */ + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = thisboard->do_n_chan; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das1800_do_wbits; + + das1800_cancel(dev, dev->read_subdev); + + // initialize digital out channels + outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL); + + // initialize analog out channels + if (thisboard->ao_ability == 1) { + // select 'update' dac channel for baseAddress + 0x0 + outb(DAC(thisboard->ao_n_chan - 1), + dev->iobase + DAS1800_SELECT); + outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC); + } + + return 0; +}; + +static int das1800_detach(struct comedi_device * dev) +{ + /* only free stuff if it has been allocated by _attach */ + if (dev->iobase) + release_region(dev->iobase, DAS1800_SIZE); + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (dev->private) { + if (devpriv->iobase2) + release_region(devpriv->iobase2, DAS1800_SIZE); + if (devpriv->dma0) + free_dma(devpriv->dma0); + if (devpriv->dma1) + free_dma(devpriv->dma1); + if (devpriv->ai_buf0) + kfree(devpriv->ai_buf0); + if (devpriv->ai_buf1) + kfree(devpriv->ai_buf1); + } + + printk("comedi%d: %s: remove\n", dev->minor, + driver_das1800.driver_name); + + return 0; +}; + +/* probes and checks das-1800 series board type + */ +static int das1800_probe(struct comedi_device * dev) +{ + int id; + int board; + + id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; /* get id bits */ + board = ((struct das1800_board *) dev->board_ptr) - das1800_boards; + + switch (id) { + case 0x3: + if (board == das1801st_da || board == das1802st_da || + board == das1701st_da || board == das1702st_da) { + printk(" Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk(" Board model (probed, not recommended): das-1800st-da series\n"); + return das1801st; + break; + case 0x4: + if (board == das1802hr_da || board == das1702hr_da) { + printk(" Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk(" Board model (probed, not recommended): das-1802hr-da\n"); + return das1802hr; + break; + case 0x5: + if (board == das1801ao || board == das1802ao || + board == das1701ao || board == das1702ao) { + printk(" Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk(" Board model (probed, not recommended): das-1800ao series\n"); + return das1801ao; + break; + case 0x6: + if (board == das1802hr || board == das1702hr) { + printk(" Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk(" Board model (probed, not recommended): das-1802hr\n"); + return das1802hr; + break; + case 0x7: + if (board == das1801st || board == das1802st || + board == das1701st || board == das1702st) { + printk(" Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk(" Board model (probed, not recommended): das-1800st series\n"); + return das1801st; + break; + case 0x8: + if (board == das1801hc || board == das1802hc) { + printk(" Board model: %s\n", + das1800_boards[board].name); + return board; + } + printk(" Board model (probed, not recommended): das-1800hc series\n"); + return das1801hc; + break; + default: + printk(" Board model: probe returned 0x%x (unknown, please report)\n", id); + return board; + break; + } + return -1; +} + +static int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + + // prevent race with interrupt handler + comedi_spin_lock_irqsave(&dev->spinlock, flags); + das1800_ai_handler(dev); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + return s->async->buf_write_count - s->async->buf_read_count; +} + +static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + unsigned int status; + + if (dev->attached == 0) { + comedi_error(dev, "premature interrupt"); + return IRQ_HANDLED; + } + + /* Prevent race with das1800_ai_poll() on multi processor systems. + * Also protects indirect addressing in das1800_ai_handler */ + spin_lock(&dev->spinlock); + status = inb(dev->iobase + DAS1800_STATUS); + + /* if interrupt was not caused by das-1800 */ + if (!(status & INT)) { + spin_unlock(&dev->spinlock); + return IRQ_NONE; + } + /* clear the interrupt status bit INT */ + outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS); + // handle interrupt + das1800_ai_handler(dev); + + spin_unlock(&dev->spinlock); + return IRQ_HANDLED; +} + +// the guts of the interrupt handler, that is shared with das1800_ai_poll +static void das1800_ai_handler(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->subdevices + 0; /* analog input subdevice */ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int status = inb(dev->iobase + DAS1800_STATUS); + + async->events = 0; + // select adc for base address + 0 + outb(ADC, dev->iobase + DAS1800_SELECT); + // dma buffer full + if (devpriv->irq_dma_bits & DMA_ENABLED) { + // look for data from dma transfer even if dma terminal count hasn't happened yet + das1800_handle_dma(dev, s, status); + } else if (status & FHF) { // if fifo half full + das1800_handle_fifo_half_full(dev, s); + } else if (status & FNE) { // if fifo not empty + das1800_handle_fifo_not_empty(dev, s); + } + + async->events |= COMEDI_CB_BLOCK; + /* if the card's fifo has overflowed */ + if (status & OVF) { + // clear OVF interrupt bit + outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS); + comedi_error(dev, "DAS1800 FIFO overflow"); + das1800_cancel(dev, s); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + comedi_event(dev, s); + return; + } + // stop taking data if appropriate + /* stop_src TRIG_EXT */ + if (status & CT0TC) { + // clear CT0TC interrupt bit + outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS); + // make sure we get all remaining data from board before quitting + if (devpriv->irq_dma_bits & DMA_ENABLED) + das1800_flush_dma(dev, s); + else + das1800_handle_fifo_not_empty(dev, s); + das1800_cancel(dev, s); /* disable hardware conversions */ + async->events |= COMEDI_CB_EOA; + } else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) { // stop_src TRIG_COUNT + das1800_cancel(dev, s); /* disable hardware conversions */ + async->events |= COMEDI_CB_EOA; + } + + comedi_event(dev, s); + + return; +} + +static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int status) +{ + unsigned long flags; + const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; + + flags = claim_dma_lock(); + das1800_flush_dma_channel(dev, s, devpriv->dma_current, + devpriv->dma_current_buf); + // re-enable dma channel + set_dma_addr(devpriv->dma_current, + virt_to_bus(devpriv->dma_current_buf)); + set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size); + enable_dma(devpriv->dma_current); + release_dma_lock(flags); + + if (status & DMATC) { + // clear DMATC interrupt bit + outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS); + // switch dma channels for next time, if appropriate + if (dual_dma) { + // read data from the other channel next time + if (devpriv->dma_current == devpriv->dma0) { + devpriv->dma_current = devpriv->dma1; + devpriv->dma_current_buf = devpriv->ai_buf1; + } else { + devpriv->dma_current = devpriv->dma0; + devpriv->dma_current_buf = devpriv->ai_buf0; + } + } + } + + return; +} + +static inline uint16_t munge_bipolar_sample(const struct comedi_device * dev, + uint16_t sample) +{ + sample += 1 << (thisboard->resolution - 1); + return sample; +} + +static void munge_data(struct comedi_device * dev, uint16_t * array, + unsigned int num_elements) +{ + unsigned int i; + int unipolar; + + /* see if card is using a unipolar or bipolar range so we can munge data correctly */ + unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; + + /* convert to unsigned type if we are in a bipolar mode */ + if (!unipolar) { + for (i = 0; i < num_elements; i++) { + array[i] = munge_bipolar_sample(dev, array[i]); + } + } +} + +/* Utility function used by das1800_flush_dma() and das1800_handle_dma(). + * Assumes dma lock is held */ +static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int channel, uint16_t * buffer) +{ + unsigned int num_bytes, num_samples; + struct comedi_cmd *cmd = &s->async->cmd; + + disable_dma(channel); + + /* clear flip-flop to make sure 2-byte registers + * get set correctly */ + clear_dma_ff(channel); + + // figure out how many points to read + num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel); + num_samples = num_bytes / sizeof(short); + + /* if we only need some of the points */ + if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples) + num_samples = devpriv->count; + + munge_data(dev, buffer, num_samples); + cfc_write_array_to_buffer(s, buffer, num_bytes); + if (s->async->cmd.stop_src == TRIG_COUNT) + devpriv->count -= num_samples; + + return; +} + +/* flushes remaining data from board when external trigger has stopped aquisition + * and we are using dma transfers */ +static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; + + flags = claim_dma_lock(); + das1800_flush_dma_channel(dev, s, devpriv->dma_current, + devpriv->dma_current_buf); + + if (dual_dma) { + // switch to other channel and flush it + if (devpriv->dma_current == devpriv->dma0) { + devpriv->dma_current = devpriv->dma1; + devpriv->dma_current_buf = devpriv->ai_buf1; + } else { + devpriv->dma_current = devpriv->dma0; + devpriv->dma_current_buf = devpriv->ai_buf0; + } + das1800_flush_dma_channel(dev, s, devpriv->dma_current, + devpriv->dma_current_buf); + } + + release_dma_lock(flags); + + // get any remaining samples in fifo + das1800_handle_fifo_not_empty(dev, s); + + return; +} + +static void das1800_handle_fifo_half_full(struct comedi_device * dev, + struct comedi_subdevice * s) +{ + int numPoints = 0; /* number of points to read */ + struct comedi_cmd *cmd = &s->async->cmd; + + numPoints = FIFO_SIZE / 2; + /* if we only need some of the points */ + if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints) + numPoints = devpriv->count; + insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints); + munge_data(dev, devpriv->ai_buf0, numPoints); + cfc_write_array_to_buffer(s, devpriv->ai_buf0, + numPoints * sizeof(devpriv->ai_buf0[0])); + if (cmd->stop_src == TRIG_COUNT) + devpriv->count -= numPoints; + return; +} + +static void das1800_handle_fifo_not_empty(struct comedi_device * dev, + struct comedi_subdevice * s) +{ + short dpnt; + int unipolar; + struct comedi_cmd *cmd = &s->async->cmd; + + unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; + + while (inb(dev->iobase + DAS1800_STATUS) & FNE) { + if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) + break; + dpnt = inw(dev->iobase + DAS1800_FIFO); + /* convert to unsigned type if we are in a bipolar mode */ + if (!unipolar) ; + dpnt = munge_bipolar_sample(dev, dpnt); + cfc_write_to_buffer(s, dpnt); + if (cmd->stop_src == TRIG_COUNT) + devpriv->count--; + } + + return; +} + +static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */ + outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */ + outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */ + if (devpriv->dma0) + disable_dma(devpriv->dma0); + if (devpriv->dma1) + disable_dma(devpriv->dma1); + return 0; +} + +/* test analog input cmd */ +static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + unsigned int tmp_arg; + int i; + int unipolar; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + 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_COUNT | TRIG_EXT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + // uniqueness check + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) + err++; + //compatibility check + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->convert_src != TRIG_TIMER) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < thisboard->ai_speed) { + cmd->convert_arg = thisboard->ai_speed; + err++; + } + } + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + switch (cmd->stop_src) { + case TRIG_COUNT: + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + break; + case TRIG_NONE: + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + break; + default: + break; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->convert_src == TRIG_TIMER) { + // if we are not in burst mode + if (cmd->scan_begin_src == TRIG_FOLLOW) { + tmp_arg = cmd->convert_arg; + /* calculate counter values that give desired timing */ + i8253_cascade_ns_to_timer_2div(TIMER_BASE, + &(devpriv->divisor1), &(devpriv->divisor2), + &(cmd->convert_arg), + cmd->flags & TRIG_ROUND_MASK); + if (tmp_arg != cmd->convert_arg) + err++; + } + // if we are in burst mode + else { + // check that convert_arg is compatible + tmp_arg = cmd->convert_arg; + cmd->convert_arg = + burst_convert_arg(cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp_arg != cmd->convert_arg) + err++; + + if (cmd->scan_begin_src == TRIG_TIMER) { + // if scans are timed faster than conversion rate allows + if (cmd->convert_arg * cmd->chanlist_len > + cmd->scan_begin_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * + cmd->chanlist_len; + err++; + } + tmp_arg = cmd->scan_begin_arg; + /* calculate counter values that give desired timing */ + i8253_cascade_ns_to_timer_2div(TIMER_BASE, + &(devpriv->divisor1), + &(devpriv->divisor2), + &(cmd->scan_begin_arg), + cmd->flags & TRIG_ROUND_MASK); + if (tmp_arg != cmd->scan_begin_arg) + err++; + } + } + } + + if (err) + return 4; + + // make sure user is not trying to mix unipolar and bipolar ranges + if (cmd->chanlist) { + unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR; + for (i = 1; i < cmd->chanlist_len; i++) { + if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) { + comedi_error(dev, + "unipolar and bipolar ranges cannot be mixed in the chanlist"); + err++; + break; + } + } + } + + if (err) + return 5; + + return 0; +} + +/* analog input cmd interface */ + +// first, some utility functions used in the main ai_do_cmd() + +// returns appropriate bits for control register a, depending on command +static int control_a_bits(struct comedi_cmd cmd) +{ + int control_a; + + control_a = FFEN; //enable fifo + if (cmd.stop_src == TRIG_EXT) { + control_a |= ATEN; + } + switch (cmd.start_src) { + case TRIG_EXT: + control_a |= TGEN | CGSL; + break; + case TRIG_NOW: + control_a |= CGEN; + break; + default: + break; + } + + return control_a; +} + +// returns appropriate bits for control register c, depending on command +static int control_c_bits(struct comedi_cmd cmd) +{ + int control_c; + int aref; + + /* set clock source to internal or external, select analog reference, + * select unipolar / bipolar + */ + aref = CR_AREF(cmd.chanlist[0]); + control_c = UQEN; //enable upper qram addresses + if (aref != AREF_DIFF) + control_c |= SD; + if (aref == AREF_COMMON) + control_c |= CMEN; + /* if a unipolar range was selected */ + if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR) + control_c |= UB; + switch (cmd.scan_begin_src) { + case TRIG_FOLLOW: // not in burst mode + switch (cmd.convert_src) { + case TRIG_TIMER: + /* trig on cascaded counters */ + control_c |= IPCLK; + break; + case TRIG_EXT: + /* trig on falling edge of external trigger */ + control_c |= XPCLK; + break; + default: + break; + } + break; + case TRIG_TIMER: + // burst mode with internal pacer clock + control_c |= BMDE | IPCLK; + break; + case TRIG_EXT: + // burst mode with external trigger + control_c |= BMDE | XPCLK; + break; + default: + break; + } + + return control_c; +} + +// sets up counters +static int setup_counters(struct comedi_device * dev, struct comedi_cmd cmd) +{ + // setup cascaded counters for conversion/scan frequency + switch (cmd.scan_begin_src) { + case TRIG_FOLLOW: // not in burst mode + if (cmd.convert_src == TRIG_TIMER) { + /* set conversion frequency */ + i8253_cascade_ns_to_timer_2div(TIMER_BASE, + &(devpriv->divisor1), &(devpriv->divisor2), + &(cmd.convert_arg), + cmd.flags & TRIG_ROUND_MASK); + if (das1800_set_frequency(dev) < 0) { + return -1; + } + } + break; + case TRIG_TIMER: // in burst mode + /* set scan frequency */ + i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), + &(devpriv->divisor2), &(cmd.scan_begin_arg), + cmd.flags & TRIG_ROUND_MASK); + if (das1800_set_frequency(dev) < 0) { + return -1; + } + break; + default: + break; + } + + // setup counter 0 for 'about triggering' + if (cmd.stop_src == TRIG_EXT) { + // load counter 0 in mode 0 + i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0); + } + + return 0; +} + +// sets up dma +static void setup_dma(struct comedi_device * dev, struct comedi_cmd cmd) +{ + unsigned long lock_flags; + const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; + + if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0) + return; + + /* determine a reasonable dma transfer size */ + devpriv->dma_transfer_size = suggest_transfer_size(&cmd); + lock_flags = claim_dma_lock(); + disable_dma(devpriv->dma0); + /* clear flip-flop to make sure 2-byte registers for + * count and address get set correctly */ + clear_dma_ff(devpriv->dma0); + set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0)); + // set appropriate size of transfer + set_dma_count(devpriv->dma0, devpriv->dma_transfer_size); + devpriv->dma_current = devpriv->dma0; + devpriv->dma_current_buf = devpriv->ai_buf0; + enable_dma(devpriv->dma0); + // set up dual dma if appropriate + if (dual_dma) { + disable_dma(devpriv->dma1); + /* clear flip-flop to make sure 2-byte registers for + * count and address get set correctly */ + clear_dma_ff(devpriv->dma1); + set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1)); + // set appropriate size of transfer + set_dma_count(devpriv->dma1, devpriv->dma_transfer_size); + enable_dma(devpriv->dma1); + } + release_dma_lock(lock_flags); + + return; +} + +// programs channel/gain list into card +static void program_chanlist(struct comedi_device * dev, struct comedi_cmd cmd) +{ + int i, n, chan_range; + unsigned long irq_flags; + const int range_mask = 0x3; //masks unipolar/bipolar bit off range + const int range_bitshift = 8; + + n = cmd.chanlist_len; + // spinlock protects indirect addressing + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */ + outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*set QRAM address start */ + /* make channel / gain list */ + for (i = 0; i < n; i++) { + chan_range = + CR_CHAN(cmd.chanlist[i]) | ((CR_RANGE(cmd. + chanlist[i]) & range_mask) << + range_bitshift); + outw(chan_range, dev->iobase + DAS1800_QRAM); + } + outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */ + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + return; +} + +// analog input do_cmd +static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int ret; + int control_a, control_c; + struct comedi_async *async = s->async; + struct comedi_cmd cmd = async->cmd; + + if (!dev->irq) { + comedi_error(dev, + "no irq assigned for das-1800, cannot do hardware conversions"); + return -1; + } + + /* disable dma on TRIG_WAKE_EOS, or TRIG_RT + * (because dma in handler is unsafe at hard real-time priority) */ + if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) { + devpriv->irq_dma_bits &= ~DMA_ENABLED; + } else { + devpriv->irq_dma_bits |= devpriv->dma_bits; + } + // interrupt on end of conversion for TRIG_WAKE_EOS + if (cmd.flags & TRIG_WAKE_EOS) { + // interrupt fifo not empty + devpriv->irq_dma_bits &= ~FIMD; + } else { + // interrupt fifo half full + devpriv->irq_dma_bits |= FIMD; + } + // determine how many conversions we need + if (cmd.stop_src == TRIG_COUNT) { + devpriv->count = cmd.stop_arg * cmd.chanlist_len; + } + + das1800_cancel(dev, s); + + // determine proper bits for control registers + control_a = control_a_bits(cmd); + control_c = control_c_bits(cmd); + + /* setup card and start */ + program_chanlist(dev, cmd); + ret = setup_counters(dev, cmd); + if (ret < 0) { + comedi_error(dev, "Error setting up counters"); + return ret; + } + setup_dma(dev, cmd); + outb(control_c, dev->iobase + DAS1800_CONTROL_C); + // set conversion rate and length for burst mode + if (control_c & BMDE) { + // program conversion period with number of microseconds minus 1 + outb(cmd.convert_arg / 1000 - 1, + dev->iobase + DAS1800_BURST_RATE); + outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH); + } + outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); // enable irq/dma + outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */ + outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */ + + return 0; +} + +/* read analog input */ +static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, n; + int chan, range, aref, chan_range; + int timeout = 1000; + short dpnt; + int conv_flags = 0; + unsigned long irq_flags; + + /* set up analog reference and unipolar / bipolar mode */ + aref = CR_AREF(insn->chanspec); + conv_flags |= UQEN; + if (aref != AREF_DIFF) + conv_flags |= SD; + if (aref == AREF_COMMON) + conv_flags |= CMEN; + /* if a unipolar range was selected */ + if (CR_RANGE(insn->chanspec) & UNIPOLAR) + conv_flags |= UB; + + outb(conv_flags, dev->iobase + DAS1800_CONTROL_C); /* software conversion enabled */ + outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */ + outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */ + outb(FFEN, dev->iobase + DAS1800_CONTROL_A); + + chan = CR_CHAN(insn->chanspec); + /* mask of unipolar/bipolar bit from range */ + range = CR_RANGE(insn->chanspec) & 0x3; + chan_range = chan | (range << 8); + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */ + outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /* set QRAM address start */ + outw(chan_range, dev->iobase + DAS1800_QRAM); + outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */ + outb(ADC, dev->iobase + DAS1800_SELECT); /* select ADC for baseAddress + 0x0 */ + + for (n = 0; n < insn->n; n++) { + /* trigger conversion */ + outb(0, dev->iobase + DAS1800_FIFO); + for (i = 0; i < timeout; i++) { + if (inb(dev->iobase + DAS1800_STATUS) & FNE) + break; + } + if (i == timeout) { + comedi_error(dev, "timeout"); + return -ETIME; + } + dpnt = inw(dev->iobase + DAS1800_FIFO); + /* shift data to offset binary for bipolar ranges */ + if ((conv_flags & UB) == 0) + dpnt += 1 << (thisboard->resolution - 1); + data[n] = dpnt; + } + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + return n; +} + +/* writes to an analog output channel */ +static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); +// int range = CR_RANGE(insn->chanspec); + int update_chan = thisboard->ao_n_chan - 1; + short output; + unsigned long irq_flags; + + // card expects two's complement data + output = data[0] - (1 << (thisboard->resolution - 1)); + // if the write is to the 'update' channel, we need to remember its value + if (chan == update_chan) + devpriv->ao_update_bits = output; + // write to channel + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(DAC(chan), dev->iobase + DAS1800_SELECT); /* select dac channel for baseAddress + 0x0 */ + outw(output, dev->iobase + DAS1800_DAC); + // now we need to write to 'update' channel to update all dac channels + if (chan != update_chan) { + outb(DAC(update_chan), dev->iobase + DAS1800_SELECT); /* select 'update' channel for baseAddress + 0x0 */ + outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC); + } + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + return 1; +} + +/* reads from digital input channels */ +static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf; + data[0] = 0; + + return 2; +} + +/* writes to digital output channels */ +static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int wbits; + + // only set bits that have been masked + data[0] &= (1 << s->n_chan) - 1; + wbits = devpriv->do_bits; + wbits &= ~data[0]; + wbits |= data[0] & data[1]; + devpriv->do_bits = wbits; + + outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL); + + data[1] = devpriv->do_bits; + + return 2; +} + +/* loads counters with divisor1, divisor2 from private structure */ +static int das1800_set_frequency(struct comedi_device * dev) +{ + int err = 0; + + // counter 1, mode 2 + if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1, + 2)) + err++; + // counter 2, mode 2 + if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2, + 2)) + err++; + if (err) + return -1; + + return 0; +} + +/* converts requested conversion timing to timing compatible with + * hardware, used only when card is in 'burst mode' + */ +static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode) +{ + unsigned int micro_sec; + + // in burst mode, the maximum conversion time is 64 microseconds + if (convert_arg > 64000) + convert_arg = 64000; + + // the conversion time must be an integral number of microseconds + switch (round_mode) { + case TRIG_ROUND_NEAREST: + default: + micro_sec = (convert_arg + 500) / 1000; + break; + case TRIG_ROUND_DOWN: + micro_sec = convert_arg / 1000; + break; + case TRIG_ROUND_UP: + micro_sec = (convert_arg - 1) / 1000 + 1; + break; + } + + // return number of nanoseconds + return micro_sec * 1000; +} + +// utility function that suggests a dma transfer size based on the conversion period 'ns' +static unsigned int suggest_transfer_size(struct comedi_cmd * cmd) +{ + unsigned int size = DMA_BUF_SIZE; + static const int sample_size = 2; // size in bytes of one sample from board + unsigned int fill_time = 300000000; // target time in nanoseconds for filling dma buffer + unsigned int max_size; // maximum size we will allow for a transfer + + // make dma buffer fill in 0.3 seconds for timed modes + switch (cmd->scan_begin_src) { + case TRIG_FOLLOW: // not in burst mode + if (cmd->convert_src == TRIG_TIMER) + size = (fill_time / cmd->convert_arg) * sample_size; + break; + case TRIG_TIMER: + size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) * + sample_size; + break; + default: + size = DMA_BUF_SIZE; + break; + } + + // set a minimum and maximum size allowed + max_size = DMA_BUF_SIZE; + // if we are taking limited number of conversions, limit transfer size to that + if (cmd->stop_src == TRIG_COUNT && + cmd->stop_arg * cmd->chanlist_len * sample_size < max_size) + max_size = cmd->stop_arg * cmd->chanlist_len * sample_size; + + if (size > max_size) + size = max_size; + if (size < sample_size) + size = sample_size; + + return size; +} diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c new file mode 100644 index 000000000000..2a8ca0525104 --- /dev/null +++ b/drivers/staging/comedi/drivers/das6402.c @@ -0,0 +1,354 @@ +/* + Some comments on the code.. + + - it shouldn't be necessary to use outb_p(). + + - ignoreirq creates a race condition. It needs to be fixed. + + */ + +/* + comedi/drivers/das6402.c + An experimental driver for Computerboards' DAS6402 I/O card + + Copyright (C) 1999 Oystein Svendsen + + 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: das6402 +Description: Keithley Metrabyte DAS6402 (& compatibles) +Author: Oystein Svendsen +Status: bitrotten +Devices: [Keithley Metrabyte] DAS6402 (das6402) + +This driver has suffered bitrot. +*/ + +#include "../comedidev.h" + +#include + +#define DAS6402_SIZE 16 + +#define N_WORDS 3000*64 + +#define STOP 0 +#define START 1 + +#define SCANL 0x3f00 +#define BYTE unsigned char +#define WORD unsigned short + +/*----- register 8 ----*/ +#define CLRINT 0x01 +#define CLRXTR 0x02 +#define CLRXIN 0x04 +#define EXTEND 0x10 +#define ARMED 0x20 /* enable conting of post sample conv */ +#define POSTMODE 0x40 +#define MHZ 0x80 /* 10 MHz clock */ +/*---------------------*/ + +/*----- register 9 ----*/ +#define IRQ (0x04 << 4) /* these two are */ +#define IRQV 10 /* dependent on each other */ + +#define CONVSRC 0x03 /* trig src is Intarnal pacer */ +#define BURSTEN 0x04 /* enable burst */ +#define XINTE 0x08 /* use external int. trig */ +#define INTE 0x80 /* enable analog interrupts */ +/*---------------------*/ + +/*----- register 10 ---*/ +#define TGEN 0x01 /* Use pin DI1 for externl trigging? */ +#define TGSEL 0x02 /* Use edge triggering */ +#define TGPOL 0x04 /* active edge is falling */ +#define PRETRIG 0x08 /* pretrig */ +/*---------------------*/ + +/*----- register 11 ---*/ +#define EOB 0x0c +#define FIFOHFULL 0x08 +#define GAIN 0x01 +#define FIFONEPTY 0x04 +#define MODE 0x10 +#define SEM 0x20 +#define BIP 0x40 +/*---------------------*/ + +#define M0 0x00 +#define M2 0x04 + +#define C0 0x00 +#define C1 0x40 +#define C2 0x80 +#define RWLH 0x30 + +static int das6402_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int das6402_detach(struct comedi_device * dev); +static struct comedi_driver driver_das6402 = { + driver_name:"das6402", + module:THIS_MODULE, + attach:das6402_attach, + detach:das6402_detach, +}; + +COMEDI_INITCLEANUP(driver_das6402); + +struct das6402_private { + int ai_bytes_to_read; + + int das6402_ignoreirq; +}; +#define devpriv ((struct das6402_private *)dev->private) + +static void das6402_ai_fifo_dregs(struct comedi_device * dev, struct comedi_subdevice * s); + +static void das6402_setcounter(struct comedi_device * dev) +{ + BYTE p; + unsigned short ctrlwrd; + + /* set up counter0 first, mode 0 */ + p = M0 | C0 | RWLH; + outb_p(p, dev->iobase + 15); + ctrlwrd = 2000; + p = (BYTE) (0xff & ctrlwrd); + outb_p(p, dev->iobase + 12); + p = (BYTE) (0xff & (ctrlwrd >> 8)); + outb_p(p, dev->iobase + 12); + + /* set up counter1, mode 2 */ + p = M2 | C1 | RWLH; + outb_p(p, dev->iobase + 15); + ctrlwrd = 10; + p = (BYTE) (0xff & ctrlwrd); + outb_p(p, dev->iobase + 13); + p = (BYTE) (0xff & (ctrlwrd >> 8)); + outb_p(p, dev->iobase + 13); + + /* set up counter1, mode 2 */ + p = M2 | C2 | RWLH; + outb_p(p, dev->iobase + 15); + ctrlwrd = 1000; + p = (BYTE) (0xff & ctrlwrd); + outb_p(p, dev->iobase + 14); + p = (BYTE) (0xff & (ctrlwrd >> 8)); + outb_p(p, dev->iobase + 14); +} + +static irqreturn_t intr_handler(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices; + + if (!dev->attached || devpriv->das6402_ignoreirq) { + printk("das6402: BUG: spurious interrupt\n"); + return IRQ_HANDLED; + } +#ifdef DEBUG + printk("das6402: interrupt! das6402_irqcount=%i\n", + devpriv->das6402_irqcount); + printk("das6402: iobase+2=%i\n", inw_p(dev->iobase + 2)); +#endif + + das6402_ai_fifo_dregs(dev, s); + + if (s->async->buf_write_count >= devpriv->ai_bytes_to_read) { + outw_p(SCANL, dev->iobase + 2); /* clears the fifo */ + outb(0x07, dev->iobase + 8); /* clears all flip-flops */ +#ifdef DEBUG + printk("das6402: Got %i samples\n\n", + devpriv->das6402_wordsread - diff); +#endif + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + } + + outb(0x01, dev->iobase + 8); /* clear only the interrupt flip-flop */ + + comedi_event(dev, s); + return IRQ_HANDLED; +} + +#if 0 +static void das6402_ai_fifo_read(struct comedi_device * dev, short * data, int n) +{ + int i; + + for (i = 0; i < n; i++) + data[i] = inw(dev->iobase); +} +#endif + +static void das6402_ai_fifo_dregs(struct comedi_device * dev, struct comedi_subdevice * s) +{ + while (1) { + if (!(inb(dev->iobase + 8) & 0x01)) + return; + comedi_buf_put(s->async, inw(dev->iobase)); + } +} + +static int das6402_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + /* + * This function should reset the board from whatever condition it + * is in (i.e., acquiring data), to a non-active state. + */ + + devpriv->das6402_ignoreirq = 1; +#ifdef DEBUG + printk("das6402: Stopping acquisition\n"); +#endif + devpriv->das6402_ignoreirq = 1; + outb_p(0x02, dev->iobase + 10); /* disable external trigging */ + outw_p(SCANL, dev->iobase + 2); /* resets the card fifo */ + outb_p(0, dev->iobase + 9); /* disables interrupts */ + + outw_p(SCANL, dev->iobase + 2); + + return 0; +} + +#ifdef unused +static int das6402_ai_mode2(struct comedi_device * dev, struct comedi_subdevice * s, + comedi_trig * it) +{ + devpriv->das6402_ignoreirq = 1; + +#ifdef DEBUG + printk("das6402: Starting acquisition\n"); +#endif + outb_p(0x03, dev->iobase + 10); /* enable external trigging */ + outw_p(SCANL, dev->iobase + 2); /* resets the card fifo */ + outb_p(IRQ | CONVSRC | BURSTEN | INTE, dev->iobase + 9); + + devpriv->ai_bytes_to_read = it->n * sizeof(short); + + /* um... ignoreirq is a nasty race condition */ + devpriv->das6402_ignoreirq = 0; + + outw_p(SCANL, dev->iobase + 2); + + return 0; +} +#endif + +static int board_init(struct comedi_device * dev) +{ + BYTE b; + + devpriv->das6402_ignoreirq = 1; + + outb(0x07, dev->iobase + 8); + + /* register 11 */ + outb_p(MODE, dev->iobase + 11); + b = BIP | SEM | MODE | GAIN | FIFOHFULL; + outb_p(b, dev->iobase + 11); + + /* register 8 */ + outb_p(EXTEND, dev->iobase + 8); + b = EXTEND | MHZ; + outb_p(b, dev->iobase + 8); + b = MHZ | CLRINT | CLRXTR | CLRXIN; + outb_p(b, dev->iobase + 8); + + /* register 9 */ + b = IRQ | CONVSRC | BURSTEN | INTE; + outb_p(b, dev->iobase + 9); + + /* register 10 */ + b = TGSEL | TGEN; + outb_p(b, dev->iobase + 10); + + b = 0x07; + outb_p(b, dev->iobase + 8); + + das6402_setcounter(dev); + + outw_p(SCANL, dev->iobase + 2); /* reset card fifo */ + + devpriv->das6402_ignoreirq = 0; + + return 0; +} + +static int das6402_detach(struct comedi_device * dev) +{ + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (dev->iobase) + release_region(dev->iobase, DAS6402_SIZE); + + return 0; +} + +static int das6402_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + unsigned int irq; + unsigned long iobase; + int ret; + struct comedi_subdevice *s; + + dev->board_name = "das6402"; + + iobase = it->options[0]; + if (iobase == 0) + iobase = 0x300; + + printk("comedi%d: das6402: 0x%04lx", dev->minor, iobase); + + if (!request_region(iobase, DAS6402_SIZE, "das6402")) { + printk(" I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + /* should do a probe here */ + + irq = it->options[0]; + printk(" ( irq = %u )", irq); + ret = comedi_request_irq(irq, intr_handler, 0, "das6402", dev); + if (ret < 0) { + printk("irq conflict\n"); + return ret; + } + dev->irq = irq; + + if ((ret = alloc_private(dev, sizeof(struct das6402_private))) < 0) + return ret; + + if ((ret = alloc_subdevices(dev, 1)) < 0) + return ret; + + /* ai subdevice */ + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 8; + //s->trig[2]=das6402_ai_mode2; + s->cancel = das6402_ai_cancel; + s->maxdata = (1 << 12) - 1; + s->len_chanlist = 16; /* ? */ + s->range_table = &range_unknown; + + board_init(dev); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c new file mode 100644 index 000000000000..7a6656bf809c --- /dev/null +++ b/drivers/staging/comedi/drivers/das800.c @@ -0,0 +1,894 @@ +/* + comedi/drivers/das800.c + Driver for Keitley das800 series boards and compatibles + Copyright (C) 2000 Frank Mori Hess + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: das800 +Description: Keithley Metrabyte DAS800 (& compatibles) +Author: Frank Mori Hess +Devices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801), + DAS-802 (das-802), + [Measurement Computing] CIO-DAS800 (cio-das800), + CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802), + CIO-DAS802/16 (cio-das802/16) +Status: works, cio-das802/16 untested - email me if you have tested it + +Configuration options: + [0] - I/O port base address + [1] - IRQ (optional, required for timed or externally triggered conversions) + +Notes: + IRQ can be omitted, although the cmd interface will not work without it. + + All entries in the channel/gain list must use the same gain and be + consecutive channels counting upwards in channel number (these are + hardware limitations.) + + I've never tested the gain setting stuff since I only have a + DAS-800 board with fixed gain. + + The cio-das802/16 does not have a fifo-empty status bit! Therefore + only fifo-half-full transfers are possible with this card. +*/ +/* + +cmd triggers supported: + start_src: TRIG_NOW | TRIG_EXT + scan_begin_src: TRIG_FOLLOW + scan_end_src: TRIG_COUNT + convert_src: TRIG_TIMER | TRIG_EXT + stop_src: TRIG_NONE | TRIG_COUNT + + +*/ + +#include "../comedidev.h" + +#include +#include + +#include "8253.h" +#include "comedi_fc.h" + +#define DAS800_SIZE 8 +#define TIMER_BASE 1000 +#define N_CHAN_AI 8 // number of analog input channels + +/* Registers for the das800 */ + +#define DAS800_LSB 0 +#define FIFO_EMPTY 0x1 +#define FIFO_OVF 0x2 +#define DAS800_MSB 1 +#define DAS800_CONTROL1 2 +#define CONTROL1_INTE 0x8 +#define DAS800_CONV_CONTROL 2 +#define ITE 0x1 +#define CASC 0x2 +#define DTEN 0x4 +#define IEOC 0x8 +#define EACS 0x10 +#define CONV_HCEN 0x80 +#define DAS800_SCAN_LIMITS 2 +#define DAS800_STATUS 2 +#define IRQ 0x8 +#define BUSY 0x80 +#define DAS800_GAIN 3 +#define CIO_FFOV 0x8 // fifo overflow for cio-das802/16 +#define CIO_ENHF 0x90 // interrupt fifo half full for cio-das802/16 +#define CONTROL1 0x80 +#define CONV_CONTROL 0xa0 +#define SCAN_LIMITS 0xc0 +#define ID 0xe0 +#define DAS800_8254 4 +#define DAS800_STATUS2 7 +#define STATUS2_HCEN 0x80 +#define STATUS2_INTE 0X20 +#define DAS800_ID 7 + +struct das800_board { + const char *name; + int ai_speed; + const struct comedi_lrange *ai_range; + int resolution; +}; + +//analog input ranges +static const struct comedi_lrange range_das800_ai = { + 1, + { + RANGE(-5, 5), + } +}; + +static const struct comedi_lrange range_das801_ai = { + 9, + { + RANGE(-5, 5), + RANGE(-10, 10), + RANGE(0, 10), + RANGE(-0.5, 0.5), + RANGE(0, 1), + RANGE(-0.05, 0.05), + RANGE(0, 0.1), + RANGE(-0.01, 0.01), + RANGE(0, 0.02), + } +}; + +static const struct comedi_lrange range_cio_das801_ai = { + 9, + { + RANGE(-5, 5), + RANGE(-10, 10), + RANGE(0, 10), + RANGE(-0.5, 0.5), + RANGE(0, 1), + RANGE(-0.05, 0.05), + RANGE(0, 0.1), + RANGE(-0.005, 0.005), + RANGE(0, 0.01), + } +}; + +static const struct comedi_lrange range_das802_ai = { + 9, + { + RANGE(-5, 5), + RANGE(-10, 10), + RANGE(0, 10), + RANGE(-2.5, 2.5), + RANGE(0, 5), + RANGE(-1.25, 1.25), + RANGE(0, 2.5), + RANGE(-0.625, 0.625), + RANGE(0, 1.25), + } +}; + +static const struct comedi_lrange range_das80216_ai = { + 8, + { + RANGE(-10, 10), + RANGE(0, 10), + RANGE(-5, 5), + RANGE(0, 5), + RANGE(-2.5, 2.5), + RANGE(0, 2.5), + RANGE(-1.25, 1.25), + RANGE(0, 1.25), + } +}; + +enum { das800, ciodas800, das801, ciodas801, das802, ciodas802, ciodas80216 }; + +static const struct das800_board das800_boards[] = { + { + name: "das-800", + ai_speed:25000, + ai_range:&range_das800_ai, + resolution:12, + }, + { + name: "cio-das800", + ai_speed:20000, + ai_range:&range_das800_ai, + resolution:12, + }, + { + name: "das-801", + ai_speed:25000, + ai_range:&range_das801_ai, + resolution:12, + }, + { + name: "cio-das801", + ai_speed:20000, + ai_range:&range_cio_das801_ai, + resolution:12, + }, + { + name: "das-802", + ai_speed:25000, + ai_range:&range_das802_ai, + resolution:12, + }, + { + name: "cio-das802", + ai_speed:20000, + ai_range:&range_das802_ai, + resolution:12, + }, + { + name: "cio-das802/16", + ai_speed:10000, + ai_range:&range_das80216_ai, + resolution:16, + }, +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct das800_board *)dev->board_ptr) + +struct das800_private { + volatile unsigned int count; /* number of data points left to be taken */ + volatile int forever; /* flag indicating whether we should take data forever */ + unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */ + unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */ + volatile int do_bits; /* digital output bits */ +}; + +#define devpriv ((struct das800_private *)dev->private) + +static int das800_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int das800_detach(struct comedi_device * dev); +static int das800_cancel(struct comedi_device * dev, struct comedi_subdevice * s); + +static struct comedi_driver driver_das800 = { + driver_name:"das800", + module:THIS_MODULE, + attach:das800_attach, + detach:das800_detach, + num_names:sizeof(das800_boards) / sizeof(struct das800_board), + board_name:&das800_boards[0].name, + offset:sizeof(struct das800_board), +}; + +static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG); +static void enable_das800(struct comedi_device * dev); +static void disable_das800(struct comedi_device * dev); +static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int das800_probe(struct comedi_device * dev); +static int das800_set_frequency(struct comedi_device * dev); + +/* checks and probes das-800 series board type */ +static int das800_probe(struct comedi_device * dev) +{ + int id_bits; + unsigned long irq_flags; + int board; + + // 'comedi spin lock irqsave' disables even rt interrupts, we use them to protect indirect addressing + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(ID, dev->iobase + DAS800_GAIN); /* select base address + 7 to be ID register */ + id_bits = inb(dev->iobase + DAS800_ID) & 0x3; /* get id bits */ + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + board = thisboard - das800_boards; + + switch (id_bits) { + case 0x0: + if (board == das800) { + printk(" Board model: DAS-800\n"); + return board; + } + if (board == ciodas800) { + printk(" Board model: CIO-DAS800\n"); + return board; + } + printk(" Board model (probed): DAS-800\n"); + return das800; + break; + case 0x2: + if (board == das801) { + printk(" Board model: DAS-801\n"); + return board; + } + if (board == ciodas801) { + printk(" Board model: CIO-DAS801\n"); + return board; + } + printk(" Board model (probed): DAS-801\n"); + return das801; + break; + case 0x3: + if (board == das802) { + printk(" Board model: DAS-802\n"); + return board; + } + if (board == ciodas802) { + printk(" Board model: CIO-DAS802\n"); + return board; + } + if (board == ciodas80216) { + printk(" Board model: CIO-DAS802/16\n"); + return board; + } + printk(" Board model (probed): DAS-802\n"); + return das802; + break; + default: + printk(" Board model: probe returned 0x%x (unknown)\n", + id_bits); + return board; + break; + } + return -1; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver_das800); + +/* interrupt service routine */ +static irqreturn_t das800_interrupt(int irq, void *d PT_REGS_ARG) +{ + short i; /* loop index */ + short dataPoint = 0; + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->read_subdev; /* analog input subdevice */ + struct comedi_async *async; + int status; + unsigned long irq_flags; + static const int max_loops = 128; // half-fifo size for cio-das802/16 + // flags + int fifo_empty = 0; + int fifo_overflow = 0; + + status = inb(dev->iobase + DAS800_STATUS); + /* if interrupt was not generated by board or driver not attached, quit */ + if (!(status & IRQ)) + return IRQ_NONE; + if (!(dev->attached)) + return IRQ_HANDLED; + + /* wait until here to initialize async, since we will get null dereference + * if interrupt occurs before driver is fully attached! + */ + async = s->async; + + // if hardware conversions are not enabled, then quit + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select base address + 7 to be STATUS2 register */ + status = inb(dev->iobase + DAS800_STATUS2) & STATUS2_HCEN; + /* don't release spinlock yet since we want to make sure noone else disables hardware conversions */ + if (status == 0) { + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + return IRQ_HANDLED; + } + + /* loop while card's fifo is not empty (and limit to half fifo for cio-das802/16) */ + for (i = 0; i < max_loops; i++) { + /* read 16 bits from dev->iobase and dev->iobase + 1 */ + dataPoint = inb(dev->iobase + DAS800_LSB); + dataPoint += inb(dev->iobase + DAS800_MSB) << 8; + if (thisboard->resolution == 12) { + fifo_empty = dataPoint & FIFO_EMPTY; + fifo_overflow = dataPoint & FIFO_OVF; + if (fifo_overflow) + break; + } else { + fifo_empty = 0; // cio-das802/16 has no fifo empty status bit + } + if (fifo_empty) { + break; + } + /* strip off extraneous bits for 12 bit cards */ + if (thisboard->resolution == 12) + dataPoint = (dataPoint >> 4) & 0xfff; + /* if there are more data points to collect */ + if (devpriv->count > 0 || devpriv->forever == 1) { + /* write data point to buffer */ + cfc_write_to_buffer(s, dataPoint); + if (devpriv->count > 0) + devpriv->count--; + } + } + async->events |= COMEDI_CB_BLOCK; + /* check for fifo overflow */ + if (thisboard->resolution == 12) { + fifo_overflow = dataPoint & FIFO_OVF; + // else cio-das802/16 + } else { + fifo_overflow = inb(dev->iobase + DAS800_GAIN) & CIO_FFOV; + } + if (fifo_overflow) { + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + comedi_error(dev, "DAS800 FIFO overflow"); + das800_cancel(dev, dev->subdevices + 0); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + comedi_event(dev, s); + async->events = 0; + return IRQ_HANDLED; + } + if (devpriv->count > 0 || devpriv->forever == 1) { + /* Re-enable card's interrupt. + * We already have spinlock, so indirect addressing is safe */ + outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ + outb(CONTROL1_INTE | devpriv->do_bits, + dev->iobase + DAS800_CONTROL1); + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + /* otherwise, stop taking data */ + } else { + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + disable_das800(dev); /* diable hardware triggered conversions */ + async->events |= COMEDI_CB_EOA; + } + comedi_event(dev, s); + async->events = 0; + return IRQ_HANDLED; +} + +static int das800_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase = it->options[0]; + unsigned int irq = it->options[1]; + unsigned long irq_flags; + int board; + + printk("comedi%d: das800: io 0x%lx", dev->minor, iobase); + if (irq) { + printk(", irq %u", irq); + } + printk("\n"); + + /* allocate and initialize dev->private */ + if (alloc_private(dev, sizeof(struct das800_private)) < 0) + return -ENOMEM; + + if (iobase == 0) { + printk("io base address required for das800\n"); + return -EINVAL; + } + + /* check if io addresses are available */ + if (!request_region(iobase, DAS800_SIZE, "das800")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + board = das800_probe(dev); + if (board < 0) { + printk("unable to determine board type\n"); + return -ENODEV; + } + dev->board_ptr = das800_boards + board; + + /* grab our IRQ */ + if (irq == 1 || irq > 7) { + printk("irq out of range\n"); + return -EINVAL; + } + if (irq) { + if (comedi_request_irq(irq, das800_interrupt, 0, "das800", dev)) { + printk("unable to allocate irq %u\n", irq); + return -EINVAL; + } + } + dev->irq = irq; + + dev->board_name = thisboard->name; + + if (alloc_subdevices(dev, 3) < 0) + return -ENOMEM; + + /* analog input subdevice */ + s = dev->subdevices + 0; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; + s->n_chan = 8; + s->len_chanlist = 8; + s->maxdata = (1 << thisboard->resolution) - 1; + s->range_table = thisboard->ai_range; + s->do_cmd = das800_ai_do_cmd; + s->do_cmdtest = das800_ai_do_cmdtest; + s->insn_read = das800_ai_rinsn; + s->cancel = das800_cancel; + + /* di */ + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 3; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das800_di_rbits; + + /* do */ + s = dev->subdevices + 2; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das800_do_wbits; + + disable_das800(dev); + + /* initialize digital out channels */ + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ + outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1); + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + return 0; +}; + +static int das800_detach(struct comedi_device * dev) +{ + printk("comedi%d: das800: remove\n", dev->minor); + + /* only free stuff if it has been allocated by _attach */ + if (dev->iobase) + release_region(dev->iobase, DAS800_SIZE); + if (dev->irq) + comedi_free_irq(dev->irq, dev); + return 0; +}; + +static int das800_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + devpriv->forever = 0; + devpriv->count = 0; + disable_das800(dev); + return 0; +} + +/* enable_das800 makes the card start taking hardware triggered conversions */ +static void enable_das800(struct comedi_device * dev) +{ + unsigned long irq_flags; + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + // enable fifo-half full interrupts for cio-das802/16 + if (thisboard->resolution == 16) + outb(CIO_ENHF, dev->iobase + DAS800_GAIN); + outb(CONV_CONTROL, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be conversion control register */ + outb(CONV_HCEN, dev->iobase + DAS800_CONV_CONTROL); /* enable hardware triggering */ + outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ + outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1); /* enable card's interrupt */ + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); +} + +/* disable_das800 stops hardware triggered conversions */ +static void disable_das800(struct comedi_device * dev) +{ + unsigned long irq_flags; + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(CONV_CONTROL, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be conversion control register */ + outb(0x0, dev->iobase + DAS800_CONV_CONTROL); /* disable hardware triggering of conversions */ + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); +} + +static int das800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + int gain, startChan; + int i; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < thisboard->ai_speed) { + cmd->convert_arg = thisboard->ai_speed; + err++; + } + } + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + } else { /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + /* calculate counter values that give desired timing */ + i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), + &(devpriv->divisor2), &(cmd->convert_arg), + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + } + + if (err) + return 4; + + // check channel/gain list against card's limitations + if (cmd->chanlist) { + gain = CR_RANGE(cmd->chanlist[0]); + startChan = CR_CHAN(cmd->chanlist[0]); + for (i = 1; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != + (startChan + i) % N_CHAN_AI) { + comedi_error(dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); + err++; + } + if (CR_RANGE(cmd->chanlist[i]) != gain) { + comedi_error(dev, + "entries in chanlist must all have the same gain\n"); + err++; + } + } + } + + if (err) + return 5; + + return 0; +} + +static int das800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int startChan, endChan, scan, gain; + int conv_bits; + unsigned long irq_flags; + struct comedi_async *async = s->async; + + if (!dev->irq) { + comedi_error(dev, + "no irq assigned for das-800, cannot do hardware conversions"); + return -1; + } + + disable_das800(dev); + + /* set channel scan limits */ + startChan = CR_CHAN(async->cmd.chanlist[0]); + endChan = (startChan + async->cmd.chanlist_len - 1) % 8; + scan = (endChan << 3) | startChan; + + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(SCAN_LIMITS, dev->iobase + DAS800_GAIN); /* select base address + 2 to be scan limits register */ + outb(scan, dev->iobase + DAS800_SCAN_LIMITS); /* set scan limits */ + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + /* set gain */ + gain = CR_RANGE(async->cmd.chanlist[0]); + if (thisboard->resolution == 12 && gain > 0) + gain += 0x7; + gain &= 0xf; + outb(gain, dev->iobase + DAS800_GAIN); + + switch (async->cmd.stop_src) { + case TRIG_COUNT: + devpriv->count = async->cmd.stop_arg * async->cmd.chanlist_len; + devpriv->forever = 0; + break; + case TRIG_NONE: + devpriv->forever = 1; + devpriv->count = 0; + break; + default: + break; + } + + /* enable auto channel scan, send interrupts on end of conversion + * and set clock source to internal or external + */ + conv_bits = 0; + conv_bits |= EACS | IEOC; + if (async->cmd.start_src == TRIG_EXT) + conv_bits |= DTEN; + switch (async->cmd.convert_src) { + case TRIG_TIMER: + conv_bits |= CASC | ITE; + /* set conversion frequency */ + i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), + &(devpriv->divisor2), &(async->cmd.convert_arg), + async->cmd.flags & TRIG_ROUND_MASK); + if (das800_set_frequency(dev) < 0) { + comedi_error(dev, "Error setting up counters"); + return -1; + } + break; + case TRIG_EXT: + break; + default: + break; + } + + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(CONV_CONTROL, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be conversion control register */ + outb(conv_bits, dev->iobase + DAS800_CONV_CONTROL); + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + async->events = 0; + enable_das800(dev); + return 0; +} + +static int das800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, n; + int chan; + int range; + int lsb, msb; + int timeout = 1000; + unsigned long irq_flags; + + disable_das800(dev); /* disable hardware conversions (enables software conversions) */ + + /* set multiplexer */ + chan = CR_CHAN(insn->chanspec); + + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ + outb(chan | devpriv->do_bits, dev->iobase + DAS800_CONTROL1); + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + /* set gain / range */ + range = CR_RANGE(insn->chanspec); + if (thisboard->resolution == 12 && range) + range += 0x7; + range &= 0xf; + outb(range, dev->iobase + DAS800_GAIN); + + comedi_udelay(5); + + for (n = 0; n < insn->n; n++) { + /* trigger conversion */ + outb_p(0, dev->iobase + DAS800_MSB); + + for (i = 0; i < timeout; i++) { + if (!(inb(dev->iobase + DAS800_STATUS) & BUSY)) + break; + } + if (i == timeout) { + comedi_error(dev, "timeout"); + return -ETIME; + } + lsb = inb(dev->iobase + DAS800_LSB); + msb = inb(dev->iobase + DAS800_MSB); + if (thisboard->resolution == 12) { + data[n] = (lsb >> 4) & 0xff; + data[n] |= (msb << 4); + } else { + data[n] = (msb << 8) | lsb; + } + } + + return n; +} + +static int das800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int bits; + + bits = inb(dev->iobase + DAS800_STATUS) >> 4; + bits &= 0x7; + data[1] = bits; + data[0] = 0; + + return 2; +} + +static int das800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int wbits; + unsigned long irq_flags; + + // only set bits that have been masked + data[0] &= 0xf; + wbits = devpriv->do_bits >> 4; + wbits &= ~data[0]; + wbits |= data[0] & data[1]; + devpriv->do_bits = wbits << 4; + + comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ + outb(devpriv->do_bits | CONTROL1_INTE, dev->iobase + DAS800_CONTROL1); + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); + + data[1] = wbits; + + return 2; +} + +/* loads counters with divisor1, divisor2 from private structure */ +static int das800_set_frequency(struct comedi_device * dev) +{ + int err = 0; + + if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2)) + err++; + if (i8254_load(dev->iobase + DAS800_8254, 0, 2, devpriv->divisor2, 2)) + err++; + if (err) + return -1; + + return 0; +} diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c new file mode 100644 index 000000000000..829083651edc --- /dev/null +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -0,0 +1,1081 @@ +/* + comedi/drivers/dmm32at.c + Diamond Systems mm32at code for a Comedi driver + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: dmm32at +Description: Diamond Systems mm32at driver. +Devices: +Author: Perry J. Piplani +Updated: Fri Jun 4 09:13:24 CDT 2004 +Status: experimental + +This driver is for the Diamond Systems MM-32-AT board +http://www.diamondsystems.com/products/diamondmm32at It is being used +on serveral projects inside NASA, without problems so far. For analog +input commands, TRIG_EXT is not yet supported at all.. + +Configuration Options: + comedi_config /dev/comedi0 dmm32at baseaddr,irq +*/ + +/* + * The previous block comment is used to automatically generate + * documentation in Comedi and Comedilib. The fields: + * + * Driver: the name of the driver + * Description: a short phrase describing the driver. Don't list boards. + * Devices: a full list of the boards that attempt to be supported by + * the driver. Format is "(manufacturer) board name [comedi name]", + * where comedi_name is the name that is used to configure the board. + * See the comment near board_name: in the struct comedi_driver structure + * below. If (manufacturer) or [comedi name] is missing, the previous + * value is used. + * Author: you + * Updated: date when the _documentation_ was last updated. Use 'date -R' + * to get a value for this. + * Status: a one-word description of the status. Valid values are: + * works - driver works correctly on most boards supported, and + * passes comedi_test. + * unknown - unknown. Usually put there by ds. + * experimental - may not work in any particular release. Author + * probably wants assistance testing it. + * bitrotten - driver has not been update in a long time, probably + * doesn't work, and probably is missing support for significant + * Comedi interface features. + * untested - author probably wrote it "blind", and is believed to + * work, but no confirmation. + * + * These headers should be followed by a blank line, and any comments + * you wish to say about the driver. The comment area is the place + * to put any known bugs, limitations, unsupported features, supported + * command triggers, whether or not commands are supported on particular + * subdevices, etc. + * + * Somewhere in the comment should be information about configuration + * options that are used with comedi_config. + */ + +#include "../comedidev.h" +#include + +/* Board register addresses */ + +#define DMM32AT_MEMSIZE 0x10 + +#define DMM32AT_CONV 0x00 +#define DMM32AT_AILSB 0x00 +#define DMM32AT_AUXDOUT 0x01 +#define DMM32AT_AIMSB 0x01 +#define DMM32AT_AILOW 0x02 +#define DMM32AT_AIHIGH 0x03 + +#define DMM32AT_DACLSB 0x04 +#define DMM32AT_DACSTAT 0x04 +#define DMM32AT_DACMSB 0x05 + +#define DMM32AT_FIFOCNTRL 0x07 +#define DMM32AT_FIFOSTAT 0x07 + +#define DMM32AT_CNTRL 0x08 +#define DMM32AT_AISTAT 0x08 + +#define DMM32AT_INTCLOCK 0x09 + +#define DMM32AT_CNTRDIO 0x0a + +#define DMM32AT_AICONF 0x0b +#define DMM32AT_AIRBACK 0x0b + +#define DMM32AT_CLK1 0x0d +#define DMM32AT_CLK2 0x0e +#define DMM32AT_CLKCT 0x0f + +#define DMM32AT_DIOA 0x0c +#define DMM32AT_DIOB 0x0d +#define DMM32AT_DIOC 0x0e +#define DMM32AT_DIOCONF 0x0f + +#define dmm_inb(cdev,reg) inb((cdev->iobase)+reg) +#define dmm_outb(cdev,reg,valu) outb(valu,(cdev->iobase)+reg) + +/* Board register values. */ + +/* DMM32AT_DACSTAT 0x04 */ +#define DMM32AT_DACBUSY 0x80 + +/* DMM32AT_FIFOCNTRL 0x07 */ +#define DMM32AT_FIFORESET 0x02 +#define DMM32AT_SCANENABLE 0x04 + +/* DMM32AT_CNTRL 0x08 */ +#define DMM32AT_RESET 0x20 +#define DMM32AT_INTRESET 0x08 +#define DMM32AT_CLKACC 0x00 +#define DMM32AT_DIOACC 0x01 + +/* DMM32AT_AISTAT 0x08 */ +#define DMM32AT_STATUS 0x80 + +/* DMM32AT_INTCLOCK 0x09 */ +#define DMM32AT_ADINT 0x80 +#define DMM32AT_CLKSEL 0x03 + +/* DMM32AT_CNTRDIO 0x0a */ +#define DMM32AT_FREQ12 0x80 + +/* DMM32AT_AICONF 0x0b */ +#define DMM32AT_RANGE_U10 0x0c +#define DMM32AT_RANGE_U5 0x0d +#define DMM32AT_RANGE_B10 0x08 +#define DMM32AT_RANGE_B5 0x00 +#define DMM32AT_SCINT_20 0x00 +#define DMM32AT_SCINT_15 0x10 +#define DMM32AT_SCINT_10 0x20 +#define DMM32AT_SCINT_5 0x30 + +/* DMM32AT_CLKCT 0x0f */ +#define DMM32AT_CLKCT1 0x56 /* mode3 counter 1 - write low byte only */ +#define DMM32AT_CLKCT2 0xb6 /* mode3 counter 2 - write high and low byte */ + +/* DMM32AT_DIOCONF 0x0f */ +#define DMM32AT_DIENABLE 0x80 +#define DMM32AT_DIRA 0x10 +#define DMM32AT_DIRB 0x02 +#define DMM32AT_DIRCL 0x01 +#define DMM32AT_DIRCH 0x08 + +/* board AI ranges in comedi structure */ +static const struct comedi_lrange dmm32at_airanges = { + 4, + { + UNI_RANGE(10), + UNI_RANGE(5), + BIP_RANGE(10), + BIP_RANGE(5), + } +}; + +/* register values for above ranges */ +static const unsigned char dmm32at_rangebits[] = { + DMM32AT_RANGE_U10, + DMM32AT_RANGE_U5, + DMM32AT_RANGE_B10, + DMM32AT_RANGE_B5, +}; + +/* only one of these ranges is valid, as set by a jumper on the + * board. The application should only use the range set by the jumper + */ +static const struct comedi_lrange dmm32at_aoranges = { + 4, + { + UNI_RANGE(10), + UNI_RANGE(5), + BIP_RANGE(10), + BIP_RANGE(5), + } +}; + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct dmm32at_board { + const char *name; + int ai_chans; + int ai_bits; + const struct comedi_lrange *ai_ranges; + int ao_chans; + int ao_bits; + const struct comedi_lrange *ao_ranges; + int have_dio; + int dio_chans; +}; +static const struct dmm32at_board dmm32at_boards[] = { + { + name: "dmm32at", + ai_chans:32, + ai_bits: 16, + ai_ranges:&dmm32at_airanges, + ao_chans:4, + ao_bits: 12, + ao_ranges:&dmm32at_aoranges, + have_dio:1, + dio_chans:24, + }, +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct dmm32at_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + * several hardware drivers keep similar information in this structure, + * feel free to suggest moving the variable to the struct comedi_device struct. + */ +struct dmm32at_private { + + int data; + int ai_inuse; + unsigned int ai_scans_left; + + /* Used for AO readback */ + unsigned int ao_readback[4]; + unsigned char dio_config; + +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct dmm32at_private *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int dmm32at_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dmm32at_detach(struct comedi_device * dev); +static struct comedi_driver driver_dmm32at = { + driver_name:"dmm32at", + module:THIS_MODULE, + attach:dmm32at_attach, + detach:dmm32at_detach, +/* It is not necessary to implement the following members if you are + * writing a driver for a ISA PnP or PCI card */ +/* Most drivers will support multiple types of boards by + * having an array of board structures. These were defined + * in dmm32at_boards[] above. Note that the element 'name' + * was first in the structure -- Comedi uses this fact to + * extract the name of the board without knowing any details + * about the structure except for its length. + * When a device is attached (by comedi_config), the name + * of the device is given to Comedi, and Comedi tries to + * match it by going through the list of board names. If + * there is a match, the address of the pointer is put + * into dev->board_ptr and driver->attach() is called. + * + * Note that these are not necessary if you can determine + * the type of board in software. ISA PnP, PCI, and PCMCIA + * devices are such boards. + */ + board_name:&dmm32at_boards[0].name, + offset:sizeof(struct dmm32at_board), + num_names:sizeof(dmm32at_boards) / sizeof(struct dmm32at_board), +}; + +/* prototypes for driver functions below */ +static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int dmm32at_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static int dmm32at_ns_to_timer(unsigned int *ns, int round); +static irqreturn_t dmm32at_isr(int irq, void *d PT_REGS_ARG); +void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec); + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int dmm32at_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + struct comedi_subdevice *s; + unsigned char aihi, ailo, fifostat, aistat, intstat, airback; + unsigned long iobase; + unsigned int irq; + + iobase = it->options[0]; + irq = it->options[1]; + + printk("comedi%d: dmm32at: attaching\n", dev->minor); + printk("dmm32at: probing at address 0x%04lx, irq %u\n", iobase, irq); + + /* register address space */ + if (!request_region(iobase, DMM32AT_MEMSIZE, thisboard->name)) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + /* the following just makes sure the board is there and gets + it to a known state */ + + /* reset the board */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_RESET); + + /* allow a millisecond to reset */ + udelay(1000); + + /* zero scan and fifo control */ + dmm_outb(dev, DMM32AT_FIFOCNTRL, 0x0); + + /* zero interrupt and clock control */ + dmm_outb(dev, DMM32AT_INTCLOCK, 0x0); + + /* write a test channel range, the high 3 bits should drop */ + dmm_outb(dev, DMM32AT_AILOW, 0x80); + dmm_outb(dev, DMM32AT_AIHIGH, 0xff); + + /* set the range at 10v unipolar */ + dmm_outb(dev, DMM32AT_AICONF, DMM32AT_RANGE_U10); + + /* should take 10 us to settle, here's a hundred */ + udelay(100); + + /* read back the values */ + ailo = dmm_inb(dev, DMM32AT_AILOW); + aihi = dmm_inb(dev, DMM32AT_AIHIGH); + fifostat = dmm_inb(dev, DMM32AT_FIFOSTAT); + aistat = dmm_inb(dev, DMM32AT_AISTAT); + intstat = dmm_inb(dev, DMM32AT_INTCLOCK); + airback = dmm_inb(dev, DMM32AT_AIRBACK); + + printk("dmm32at: lo=0x%02x hi=0x%02x fifostat=0x%02x\n", + ailo, aihi, fifostat); + printk("dmm32at: aistat=0x%02x intstat=0x%02x airback=0x%02x\n", + aistat, intstat, airback); + + if ((ailo != 0x00) || (aihi != 0x1f) || (fifostat != 0x80) || + (aistat != 0x60 || (intstat != 0x00) || airback != 0x0c)) { + printk("dmmat32: board detection failed\n"); + return -EIO; + } + + /* board is there, register interrupt */ + if (irq) { + ret = comedi_request_irq(irq, dmm32at_isr, 0, thisboard->name, + dev); + if (ret < 0) { + printk("irq conflict\n"); + return ret; + } + dev->irq = irq; + } + +/* + * If you can probe the device to determine what device in a series + * it is, this is the place to do it. Otherwise, dev->board_ptr + * should already be initialized. + */ + //dev->board_ptr = dmm32at_probe(dev); + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct dmm32at_private)) < 0) + return -ENOMEM; + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_subdevices(dev, 3) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + dev->read_subdev = s; + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + /* we support single-ended (ground) and differential */ + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + s->n_chan = thisboard->ai_chans; + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = thisboard->ai_ranges; + s->len_chanlist = 32; /* This is the maximum chanlist length that + the board can handle */ + s->insn_read = dmm32at_ai_rinsn; + s->do_cmd = dmm32at_ai_cmd; + s->do_cmdtest = dmm32at_ai_cmdtest; + s->cancel = dmm32at_ai_cancel; + + s = dev->subdevices + 1; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_chans; + s->maxdata = (1 << thisboard->ao_bits) - 1; + s->range_table = thisboard->ao_ranges; + s->insn_write = dmm32at_ao_winsn; + s->insn_read = dmm32at_ao_rinsn; + + s = dev->subdevices + 2; + /* digital i/o subdevice */ + if (thisboard->have_dio) { + + /* get access to the DIO regs */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC); + /* set the DIO's to the defualt input setting */ + devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB | + DMM32AT_DIRCL | DMM32AT_DIRCH | DMM32AT_DIENABLE; + dmm_outb(dev, DMM32AT_DIOCONF, devpriv->dio_config); + + /* set up the subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = thisboard->dio_chans; + s->maxdata = 1; + s->state = 0; + s->range_table = &range_digital; + s->insn_bits = dmm32at_dio_insn_bits; + s->insn_config = dmm32at_dio_insn_config; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* success */ + printk("comedi%d: dmm32at: attached\n", dev->minor); + + return 1; + +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int dmm32at_detach(struct comedi_device * dev) +{ + printk("comedi%d: dmm32at: remove\n", dev->minor); + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (dev->iobase) + release_region(dev->iobase, DMM32AT_MEMSIZE); + + return 0; +} + +/* + * "instructions" read/write data in "one-shot" or "software-triggered" + * mode. + */ + +static int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, i; + unsigned int d; + unsigned char status; + unsigned short msb, lsb; + unsigned char chan; + int range; + + /* get the channel and range number */ + + chan = CR_CHAN(insn->chanspec) & (s->n_chan - 1); + range = CR_RANGE(insn->chanspec); + + //printk("channel=0x%02x, range=%d\n",chan,range); + + /* zero scan and fifo control and reset fifo */ + dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_FIFORESET); + + /* write the ai channel range regs */ + dmm_outb(dev, DMM32AT_AILOW, chan); + dmm_outb(dev, DMM32AT_AIHIGH, chan); + /* set the range bits */ + dmm_outb(dev, DMM32AT_AICONF, dmm32at_rangebits[range]); + + /* wait for circuit to settle */ + for (i = 0; i < 40000; i++) { + status = dmm_inb(dev, DMM32AT_AIRBACK); + if ((status & DMM32AT_STATUS) == 0) + break; + } + if (i == 40000) { + printk("timeout\n"); + return -ETIMEDOUT; + } + + /* convert n samples */ + for (n = 0; n < insn->n; n++) { + /* trigger conversion */ + dmm_outb(dev, DMM32AT_CONV, 0xff); + /* wait for conversion to end */ + for (i = 0; i < 40000; i++) { + status = dmm_inb(dev, DMM32AT_AISTAT); + if ((status & DMM32AT_STATUS) == 0) + break; + } + if (i == 40000) { + printk("timeout\n"); + return -ETIMEDOUT; + } + + /* read data */ + lsb = dmm_inb(dev, DMM32AT_AILSB); + msb = dmm_inb(dev, DMM32AT_AIMSB); + + /* invert sign bit to make range unsigned, this is an + idiosyncracy of the diamond board, it return + conversions as a signed value, i.e. -32768 to + 32767, flipping the bit and interpreting it as + signed gives you a range of 0 to 65535 which is + used by comedi */ + d = ((msb ^ 0x0080) << 8) + lsb; + + data[n] = d; + } + + /* return the number of samples read/written */ + return n; +} + +static int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + int start_chan, gain, i; + + //printk("dmmat32 in command test\n"); + + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ + + 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_TIMER /*| TRIG_EXT */ ; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER /*| TRIG_EXT */ ; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } +#define MAX_SCAN_SPEED 1000000 /* in nanoseconds */ +#define MIN_SCAN_SPEED 1000000000 /* in nanoseconds */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < MAX_SCAN_SPEED) { + cmd->scan_begin_arg = MAX_SCAN_SPEED; + err++; + } + if (cmd->scan_begin_arg > MIN_SCAN_SPEED) { + cmd->scan_begin_arg = MIN_SCAN_SPEED; + err++; + } + } else { + /* external trigger */ + /* should be level/edge, hi/lo specification here */ + /* should specify multiple external triggers */ + if (cmd->scan_begin_arg > 9) { + cmd->scan_begin_arg = 9; + err++; + } + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg >= 17500) + cmd->convert_arg = 20000; + else if (cmd->convert_arg >= 12500) + cmd->convert_arg = 15000; + else if (cmd->convert_arg >= 7500) + cmd->convert_arg = 10000; + else + cmd->convert_arg = 5000; + + } else { + /* external trigger */ + /* see above */ + if (cmd->convert_arg > 9) { + cmd->convert_arg = 9; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_arg > 0xfffffff0) { + cmd->stop_arg = 0xfffffff0; + err++; + } + if (cmd->stop_arg == 0) { + cmd->stop_arg = 1; + err++; + } + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + dmm32at_ns_to_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + dmm32at_ns_to_timer(&cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + if (cmd->scan_begin_src == TRIG_TIMER && + cmd->scan_begin_arg < + cmd->convert_arg * cmd->scan_end_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->scan_end_arg; + err++; + } + } + + if (err) + return 4; + + /* step 5 check the channel list, the channel list for this + board must be consecutive and gains must be the same */ + + if (cmd->chanlist) { + gain = CR_RANGE(cmd->chanlist[0]); + start_chan = CR_CHAN(cmd->chanlist[0]); + for (i = 1; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != + (start_chan + i) % s->n_chan) { + comedi_error(dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); + err++; + } + if (CR_RANGE(cmd->chanlist[i]) != gain) { + comedi_error(dev, + "entries in chanlist must all have the same gain\n"); + err++; + } + } + } + + if (err) + return 5; + + return 0; +} + +static int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + int i, range; + unsigned char chanlo, chanhi, status; + + if (!cmd->chanlist) + return -EINVAL; + + /* get the channel list and range */ + chanlo = CR_CHAN(cmd->chanlist[0]) & (s->n_chan - 1); + chanhi = chanlo + cmd->chanlist_len - 1; + if (chanhi >= s->n_chan) + return -EINVAL; + range = CR_RANGE(cmd->chanlist[0]); + + /* reset fifo */ + dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_FIFORESET); + + /* set scan enable */ + dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_SCANENABLE); + + /* write the ai channel range regs */ + dmm_outb(dev, DMM32AT_AILOW, chanlo); + dmm_outb(dev, DMM32AT_AIHIGH, chanhi); + + /* set the range bits */ + dmm_outb(dev, DMM32AT_AICONF, dmm32at_rangebits[range]); + + /* reset the interrupt just in case */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_INTRESET); + + if (cmd->stop_src == TRIG_COUNT) + devpriv->ai_scans_left = cmd->stop_arg; + else { /* TRIG_NONE */ + devpriv->ai_scans_left = 0xffffffff; /* indicates TRIG_NONE to isr */ + } + + /* wait for circuit to settle */ + for (i = 0; i < 40000; i++) { + status = dmm_inb(dev, DMM32AT_AIRBACK); + if ((status & DMM32AT_STATUS) == 0) + break; + } + if (i == 40000) { + printk("timeout\n"); + return -ETIMEDOUT; + } + + if (devpriv->ai_scans_left > 1) { + /* start the clock and enable the interrupts */ + dmm32at_setaitimer(dev, cmd->scan_begin_arg); + } else { + /* start the interrups and initiate a single scan */ + dmm_outb(dev, DMM32AT_INTCLOCK, DMM32AT_ADINT); + dmm_outb(dev, DMM32AT_CONV, 0xff); + } + +/* printk("dmmat32 in command\n"); */ + +/* for(i=0;ichanlist_len;i++) */ +/* comedi_buf_put(s->async,i*100); */ + +/* s->async->events |= COMEDI_CB_EOA; */ +/* comedi_event(dev, s); */ + + return 0; + +} + +static int dmm32at_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + devpriv->ai_scans_left = 1; + return 0; +} + +static irqreturn_t dmm32at_isr(int irq, void *d PT_REGS_ARG) +{ + unsigned char intstat; + unsigned int samp; + unsigned short msb, lsb; + int i; + struct comedi_device *dev = d; + + if (!dev->attached) { + comedi_error(dev, "spurious interrupt"); + return IRQ_HANDLED; + } + + intstat = dmm_inb(dev, DMM32AT_INTCLOCK); + + if (intstat & DMM32AT_ADINT) { + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_cmd *cmd = &s->async->cmd; + + for (i = 0; i < cmd->chanlist_len; i++) { + /* read data */ + lsb = dmm_inb(dev, DMM32AT_AILSB); + msb = dmm_inb(dev, DMM32AT_AIMSB); + + /* invert sign bit to make range unsigned */ + samp = ((msb ^ 0x0080) << 8) + lsb; + comedi_buf_put(s->async, samp); + } + + if (devpriv->ai_scans_left != 0xffffffff) { /* TRIG_COUNT */ + devpriv->ai_scans_left--; + if (devpriv->ai_scans_left == 0) { + /* disable further interrupts and clocks */ + dmm_outb(dev, DMM32AT_INTCLOCK, 0x0); + /* set the buffer to be flushed with an EOF */ + s->async->events |= COMEDI_CB_EOA; + } + + } + /* flush the buffer */ + comedi_event(dev, s); + } + + /* reset the interrupt */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_INTRESET); + return IRQ_HANDLED; +} + +/* This function doesn't require a particular form, this is just + * what happens to be used in some of the drivers. It should + * convert ns nanoseconds to a counter value suitable for programming + * the device. Also, it should adjust ns so that it cooresponds to + * the actual time that the device will use. */ +static int dmm32at_ns_to_timer(unsigned int *ns, int round) +{ + /* trivial timer */ + /* if your timing is done through two cascaded timers, the + * i8253_cascade_ns_to_timer() function in 8253.h can be + * very helpful. There are also i8254_load() and i8254_mm_load() + * which can be used to load values into the ubiquitous 8254 counters + */ + + return *ns; +} + +static int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + unsigned char hi, lo, status; + + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { + + devpriv->ao_readback[chan] = data[i]; + + /* get the low byte */ + lo = data[i] & 0x00ff; + /* high byte also contains channel number */ + hi = (data[i] >> 8) + chan * (1 << 6); + //printk("writing 0x%02x 0x%02x\n",hi,lo); + /* write the low and high values to the board */ + dmm_outb(dev, DMM32AT_DACLSB, lo); + dmm_outb(dev, DMM32AT_DACMSB, hi); + + /* wait for circuit to settle */ + for (i = 0; i < 40000; i++) { + status = dmm_inb(dev, DMM32AT_DACSTAT); + if ((status & DMM32AT_DACBUSY) == 0) + break; + } + if (i == 40000) { + printk("timeout\n"); + return -ETIMEDOUT; + } + /* dummy read to update trigger the output */ + status = dmm_inb(dev, DMM32AT_DACMSB); + + } + + /* return the number of samples read/written */ + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. */ +static int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +/* DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write */ +static int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned char diobits; + + if (insn->n != 2) + return -EINVAL; + + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + /* Write out the new digital output lines */ + //outw(s->state,dev->iobase + DMM32AT_DIO); + } + + /* get access to the DIO regs */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC); + + /* if either part of dio is set for output */ + if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) || + ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) { + diobits = (s->state & 0x00ff0000) >> 16; + dmm_outb(dev, DMM32AT_DIOC, diobits); + } + if ((devpriv->dio_config & DMM32AT_DIRB) == 0) { + diobits = (s->state & 0x0000ff00) >> 8; + dmm_outb(dev, DMM32AT_DIOB, diobits); + } + if ((devpriv->dio_config & DMM32AT_DIRA) == 0) { + diobits = (s->state & 0x000000ff); + dmm_outb(dev, DMM32AT_DIOA, diobits); + } + + /* now read the state back in */ + s->state = dmm_inb(dev, DMM32AT_DIOC); + s->state <<= 8; + s->state |= dmm_inb(dev, DMM32AT_DIOB); + s->state <<= 8; + s->state |= dmm_inb(dev, DMM32AT_DIOA); + data[1] = s->state; + + /* on return, data[1] contains the value of the digital + * input and output lines. */ + //data[1]=inw(dev->iobase + DMM32AT_DIO); + /* or we could just return the software copy of the output values if + * it was a purely digital output subdevice */ + //data[1]=s->state; + + return 2; +} + +static int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned char chanbit; + int chan = CR_CHAN(insn->chanspec); + + if (insn->n != 1) + return -EINVAL; + + if (chan < 8) + chanbit = DMM32AT_DIRA; + else if (chan < 16) + chanbit = DMM32AT_DIRB; + else if (chan < 20) + chanbit = DMM32AT_DIRCL; + else + chanbit = DMM32AT_DIRCH; + + /* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ + + /* if output clear the bit, otherwise set it */ + if (data[0] == COMEDI_OUTPUT) { + devpriv->dio_config &= ~chanbit; + } else { + devpriv->dio_config |= chanbit; + } + /* get access to the DIO regs */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC); + /* set the DIO's to the new configuration setting */ + dmm_outb(dev, DMM32AT_DIOCONF, devpriv->dio_config); + + return 1; +} + +void dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec) +{ + unsigned char lo1, lo2, hi2; + unsigned short both2; + + /* based on 10mhz clock */ + lo1 = 200; + both2 = nansec / 20000; + hi2 = (both2 & 0xff00) >> 8; + lo2 = both2 & 0x00ff; + + /* set the counter frequency to 10mhz */ + dmm_outb(dev, DMM32AT_CNTRDIO, 0); + + /* get access to the clock regs */ + dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_CLKACC); + + /* write the counter 1 control word and low byte to counter */ + dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT1); + dmm_outb(dev, DMM32AT_CLK1, lo1); + + /* write the counter 2 control word and low byte then to counter */ + dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT2); + dmm_outb(dev, DMM32AT_CLK2, lo2); + dmm_outb(dev, DMM32AT_CLK2, hi2); + + /* enable the ai conversion interrupt and the clock to start scans */ + dmm_outb(dev, DMM32AT_INTCLOCK, DMM32AT_ADINT | DMM32AT_CLKSEL); + +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver_dmm32at); diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c new file mode 100644 index 000000000000..5e0eed835d1a --- /dev/null +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -0,0 +1,697 @@ +/* + * comedi/drivers/dt2801.c + * Device Driver for DataTranslation DT2801 + * + */ +/* +Driver: dt2801 +Description: Data Translation DT2801 series and DT01-EZ +Author: ds +Status: works +Devices: [Data Translation] DT2801 (dt2801), DT2801-A, DT2801/5716A, + DT2805, DT2805/5716A, DT2808, DT2818, DT2809, DT01-EZ + +This driver can autoprobe the type of board. + +Configuration options: + [0] - I/O port base address + [1] - unused + [2] - A/D reference 0=differential, 1=single-ended + [3] - A/D range + 0 = [-10,10] + 1 = [0,10] + [4] - D/A 0 range + 0 = [-10,10] + 1 = [-5,5] + 2 = [-2.5,2.5] + 3 = [0,10] + 4 = [0,5] + [5] - D/A 1 range (same choices) +*/ + +#include "../comedidev.h" +#include +#include + +#define DT2801_TIMEOUT 1000 + +/* Hardware Configuration */ +/* ====================== */ + +#define DT2801_MAX_DMA_SIZE (64 * 1024) + +/* Ports */ +#define DT2801_IOSIZE 2 + +/* define's */ +/* ====================== */ + +/* Commands */ +#define DT_C_RESET 0x0 +#define DT_C_CLEAR_ERR 0x1 +#define DT_C_READ_ERRREG 0x2 +#define DT_C_SET_CLOCK 0x3 + +#define DT_C_TEST 0xb +#define DT_C_STOP 0xf + +#define DT_C_SET_DIGIN 0x4 +#define DT_C_SET_DIGOUT 0x5 +#define DT_C_READ_DIG 0x6 +#define DT_C_WRITE_DIG 0x7 + +#define DT_C_WRITE_DAIM 0x8 +#define DT_C_SET_DA 0x9 +#define DT_C_WRITE_DA 0xa + +#define DT_C_READ_ADIM 0xc +#define DT_C_SET_AD 0xd +#define DT_C_READ_AD 0xe + +/* Command modifiers (only used with read/write), EXTTRIG can be + used with some other commands. +*/ +#define DT_MOD_DMA (1<<4) +#define DT_MOD_CONT (1<<5) +#define DT_MOD_EXTCLK (1<<6) +#define DT_MOD_EXTTRIG (1<<7) + +/* Bits in status register */ +#define DT_S_DATA_OUT_READY (1<<0) +#define DT_S_DATA_IN_FULL (1<<1) +#define DT_S_READY (1<<2) +#define DT_S_COMMAND (1<<3) +#define DT_S_COMPOSITE_ERROR (1<<7) + +/* registers */ +#define DT2801_DATA 0 +#define DT2801_STATUS 1 +#define DT2801_CMD 1 + +static int dt2801_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dt2801_detach(struct comedi_device * dev); +static struct comedi_driver driver_dt2801 = { + driver_name:"dt2801", + module:THIS_MODULE, + attach:dt2801_attach, + detach:dt2801_detach, +}; + +COMEDI_INITCLEANUP(driver_dt2801); + +#if 0 +// ignore 'defined but not used' warning +static const struct comedi_lrange range_dt2801_ai_pgh_bipolar = { 4, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2.5, 2.5), + RANGE(-1.25, 1.25), + } +}; +#endif +static const struct comedi_lrange range_dt2801_ai_pgl_bipolar = { 4, { + RANGE(-10, 10), + RANGE(-1, 1), + RANGE(-0.1, 0.1), + RANGE(-0.02, 0.02), + } +}; + +#if 0 +// ignore 'defined but not used' warning +static const struct comedi_lrange range_dt2801_ai_pgh_unipolar = { 4, { + RANGE(0, 10), + RANGE(0, 5), + RANGE(0, 2.5), + RANGE(0, 1.25), + } +}; +#endif +static const struct comedi_lrange range_dt2801_ai_pgl_unipolar = { 4, { + RANGE(0, 10), + RANGE(0, 1), + RANGE(0, 0.1), + RANGE(0, 0.02), + } +}; + +struct dt2801_board { + + const char *name; + int boardcode; + int ad_diff; + int ad_chan; + int adbits; + int adrangetype; + int dabits; +}; + + +/* Typeid's for the different boards of the DT2801-series + (taken from the test-software, that comes with the board) + */ +static const struct dt2801_board boardtypes[] = { + { + name: "dt2801", + boardcode:0x09, + ad_diff: 2, + ad_chan: 16, + adbits: 12, + adrangetype:0, + dabits: 12}, + { + name: "dt2801-a", + boardcode:0x52, + ad_diff: 2, + ad_chan: 16, + adbits: 12, + adrangetype:0, + dabits: 12}, + { + name: "dt2801/5716a", + boardcode:0x82, + ad_diff: 1, + ad_chan: 16, + adbits: 16, + adrangetype:1, + dabits: 12}, + { + name: "dt2805", + boardcode:0x12, + ad_diff: 1, + ad_chan: 16, + adbits: 12, + adrangetype:0, + dabits: 12}, + { + name: "dt2805/5716a", + boardcode:0x92, + ad_diff: 1, + ad_chan: 16, + adbits: 16, + adrangetype:1, + dabits: 12}, + { + name: "dt2808", + boardcode:0x20, + ad_diff: 0, + ad_chan: 16, + adbits: 12, + adrangetype:2, + dabits: 8}, + { + name: "dt2818", + boardcode:0xa2, + ad_diff: 0, + ad_chan: 4, + adbits: 12, + adrangetype:0, + dabits: 12}, + { + name: "dt2809", + boardcode:0xb0, + ad_diff: 0, + ad_chan: 8, + adbits: 12, + adrangetype:1, + dabits: 12}, +}; + +#define n_boardtypes ((sizeof(boardtypes))/(sizeof(boardtypes[0]))) +#define boardtype (*(const struct dt2801_board *)dev->board_ptr) + +struct dt2801_private { + + const struct comedi_lrange *dac_range_types[2]; + unsigned int ao_readback[2]; +}; + +#define devpriv ((struct dt2801_private *)dev->private) + +static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dt2801_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dt2801_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +/* These are the low-level routines: + writecommand: write a command to the board + writedata: write data byte + readdata: read data byte + */ + +/* Only checks DataOutReady-flag, not the Ready-flag as it is done + in the examples of the manual. I don't see why this should be + necessary. */ +static int dt2801_readdata(struct comedi_device * dev, int *data) +{ + int stat = 0; + int timeout = DT2801_TIMEOUT; + + do { + stat = inb_p(dev->iobase + DT2801_STATUS); + if (stat & (DT_S_COMPOSITE_ERROR | DT_S_READY)) { + return stat; + } + if (stat & DT_S_DATA_OUT_READY) { + *data = inb_p(dev->iobase + DT2801_DATA); + return 0; + } + } while (--timeout > 0); + + return -ETIME; +} + +static int dt2801_readdata2(struct comedi_device * dev, int *data) +{ + int lb, hb; + int ret; + + ret = dt2801_readdata(dev, &lb); + if (ret) + return ret; + ret = dt2801_readdata(dev, &hb); + if (ret) + return ret; + + *data = (hb << 8) + lb; + return 0; +} + +static int dt2801_writedata(struct comedi_device * dev, unsigned int data) +{ + int stat = 0; + int timeout = DT2801_TIMEOUT; + + do { + stat = inb_p(dev->iobase + DT2801_STATUS); + + if (stat & DT_S_COMPOSITE_ERROR) { + return stat; + } + if (!(stat & DT_S_DATA_IN_FULL)) { + outb_p(data & 0xff, dev->iobase + DT2801_DATA); + return 0; + } +#if 0 + if (stat & DT_S_READY) { + printk("dt2801: ready flag set (bad!) in dt2801_writedata()\n"); + return -EIO; + } +#endif + } while (--timeout > 0); + + return -ETIME; +} + +static int dt2801_writedata2(struct comedi_device * dev, unsigned int data) +{ + int ret; + + ret = dt2801_writedata(dev, data & 0xff); + if (ret < 0) + return ret; + ret = dt2801_writedata(dev, (data >> 8)); + if (ret < 0) + return ret; + + return 0; +} + +static int dt2801_wait_for_ready(struct comedi_device * dev) +{ + int timeout = DT2801_TIMEOUT; + int stat; + + stat = inb_p(dev->iobase + DT2801_STATUS); + if (stat & DT_S_READY) { + return 0; + } + do { + stat = inb_p(dev->iobase + DT2801_STATUS); + + if (stat & DT_S_COMPOSITE_ERROR) { + return stat; + } + if (stat & DT_S_READY) { + return 0; + } + } while (--timeout > 0); + + return -ETIME; +} + +static int dt2801_writecmd(struct comedi_device * dev, int command) +{ + int stat; + + dt2801_wait_for_ready(dev); + + stat = inb_p(dev->iobase + DT2801_STATUS); + if (stat & DT_S_COMPOSITE_ERROR) { + printk("dt2801: composite-error in dt2801_writecmd(), ignoring\n"); + } + if (!(stat & DT_S_READY)) { + printk("dt2801: !ready in dt2801_writecmd(), ignoring\n"); + } + outb_p(command, dev->iobase + DT2801_CMD); + + return 0; +} + +static int dt2801_reset(struct comedi_device * dev) +{ + int board_code = 0; + unsigned int stat; + int timeout; + + DPRINTK("dt2801: resetting board...\n"); + DPRINTK("fingerprint: 0x%02x 0x%02x\n", inb_p(dev->iobase), + inb_p(dev->iobase + 1)); + + /* pull random data from data port */ + inb_p(dev->iobase + DT2801_DATA); + inb_p(dev->iobase + DT2801_DATA); + inb_p(dev->iobase + DT2801_DATA); + inb_p(dev->iobase + DT2801_DATA); + + DPRINTK("dt2801: stop\n"); + //dt2801_writecmd(dev,DT_C_STOP); + outb_p(DT_C_STOP, dev->iobase + DT2801_CMD); + + //dt2801_wait_for_ready(dev); + comedi_udelay(100); + timeout = 10000; + do { + stat = inb_p(dev->iobase + DT2801_STATUS); + if (stat & DT_S_READY) + break; + } while (timeout--); + if (!timeout) { + printk("dt2801: timeout 1 status=0x%02x\n", stat); + } + //printk("dt2801: reading dummy\n"); + //dt2801_readdata(dev,&board_code); + + DPRINTK("dt2801: reset\n"); + outb_p(DT_C_RESET, dev->iobase + DT2801_CMD); + //dt2801_writecmd(dev,DT_C_RESET); + + comedi_udelay(100); + timeout = 10000; + do { + stat = inb_p(dev->iobase + DT2801_STATUS); + if (stat & DT_S_READY) + break; + } while (timeout--); + if (!timeout) { + printk("dt2801: timeout 2 status=0x%02x\n", stat); + } + + DPRINTK("dt2801: reading code\n"); + dt2801_readdata(dev, &board_code); + + DPRINTK("dt2801: ok. code=0x%02x\n", board_code); + + return board_code; +} + +static int probe_number_of_ai_chans(struct comedi_device * dev) +{ + int n_chans; + int stat; + int data; + + for (n_chans = 0; n_chans < 16; n_chans++) { + stat = dt2801_writecmd(dev, DT_C_READ_ADIM); + dt2801_writedata(dev, 0); + dt2801_writedata(dev, n_chans); + stat = dt2801_readdata2(dev, &data); + + if (stat) + break; + } + + dt2801_reset(dev); + dt2801_reset(dev); + + return n_chans; +} + +static const struct comedi_lrange *dac_range_table[] = { + &range_bipolar10, + &range_bipolar5, + &range_bipolar2_5, + &range_unipolar10, + &range_unipolar5 +}; + +static const struct comedi_lrange *dac_range_lkup(int opt) +{ + if (opt < 0 || opt > 5) + return &range_unknown; + return dac_range_table[opt]; +} + +static const struct comedi_lrange *ai_range_lkup(int type, int opt) +{ + switch (type) { + case 0: + return (opt) ? + &range_dt2801_ai_pgl_unipolar : + &range_dt2801_ai_pgl_bipolar; + case 1: + return (opt) ? &range_unipolar10 : &range_bipolar10; + case 2: + return &range_unipolar5; + } + return &range_unknown; +} + +/* + options: + [0] - i/o base + [1] - unused + [2] - a/d 0=differential, 1=single-ended + [3] - a/d range 0=[-10,10], 1=[0,10] + [4] - dac0 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5] + [5] - dac1 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5] +*/ +static int dt2801_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + int board_code, type; + int ret = 0; + int n_ai_chans; + + iobase = it->options[0]; + if (!request_region(iobase, DT2801_IOSIZE, "dt2801")) { + comedi_error(dev, "I/O port conflict"); + return -EIO; + } + dev->iobase = iobase; + + /* do some checking */ + + board_code = dt2801_reset(dev); + + /* heh. if it didn't work, try it again. */ + if (!board_code) + board_code = dt2801_reset(dev); + + for (type = 0; type < n_boardtypes; type++) { + if (boardtypes[type].boardcode == board_code) + goto havetype; + } + printk("dt2801: unrecognized board code=0x%02x, contact author\n", + board_code); + type = 0; + + havetype: + dev->board_ptr = boardtypes + type; + printk("dt2801: %s at port 0x%lx", boardtype.name, iobase); + + n_ai_chans = probe_number_of_ai_chans(dev); + printk(" (ai channels = %d)", n_ai_chans); + + if ((ret = alloc_subdevices(dev, 4)) < 0) + goto out; + + if ((ret = alloc_private(dev, sizeof(struct dt2801_private))) < 0) + goto out; + + dev->board_name = boardtype.name; + + s = dev->subdevices + 0; + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; +#if 1 + s->n_chan = n_ai_chans; +#else + if (it->options[2]) + s->n_chan = boardtype.ad_chan; + else + s->n_chan = boardtype.ad_chan / 2; +#endif + s->maxdata = (1 << boardtype.adbits) - 1; + s->range_table = ai_range_lkup(boardtype.adrangetype, it->options[3]); + s->insn_read = dt2801_ai_insn_read; + + s++; + /* ao subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->maxdata = (1 << boardtype.dabits) - 1; + s->range_table_list = devpriv->dac_range_types; + devpriv->dac_range_types[0] = dac_range_lkup(it->options[4]); + devpriv->dac_range_types[1] = dac_range_lkup(it->options[5]); + s->insn_read = dt2801_ao_insn_read; + s->insn_write = dt2801_ao_insn_write; + + s++; + /* 1st digital subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = dt2801_dio_insn_bits; + s->insn_config = dt2801_dio_insn_config; + + s++; + /* 2nd digital subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = dt2801_dio_insn_bits; + s->insn_config = dt2801_dio_insn_config; + + ret = 0; + out: + printk("\n"); + + return ret; +} + +static int dt2801_detach(struct comedi_device * dev) +{ + if (dev->iobase) + release_region(dev->iobase, DT2801_IOSIZE); + + return 0; +} + +static int dt2801_error(struct comedi_device * dev, int stat) +{ + if (stat < 0) { + if (stat == -ETIME) { + printk("dt2801: timeout\n"); + } else { + printk("dt2801: error %d\n", stat); + } + return stat; + } + printk("dt2801: error status 0x%02x, resetting...\n", stat); + + dt2801_reset(dev); + dt2801_reset(dev); + + return -EIO; +} + +static int dt2801_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int d; + int stat; + int i; + + for (i = 0; i < insn->n; i++) { + stat = dt2801_writecmd(dev, DT_C_READ_ADIM); + dt2801_writedata(dev, CR_RANGE(insn->chanspec)); + dt2801_writedata(dev, CR_CHAN(insn->chanspec)); + stat = dt2801_readdata2(dev, &d); + + if (stat != 0) + return dt2801_error(dev, stat); + + data[i] = d; + } + + return i; +} + +static int dt2801_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int dt2801_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + dt2801_writecmd(dev, DT_C_WRITE_DAIM); + dt2801_writedata(dev, CR_CHAN(insn->chanspec)); + dt2801_writedata2(dev, data[0]); + + devpriv->ao_readback[CR_CHAN(insn->chanspec)] = data[0]; + + return 1; +} + +static int dt2801_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int which = 0; + + if (s == dev->subdevices + 4) + which = 1; + + if (insn->n != 2) + return -EINVAL; + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + dt2801_writecmd(dev, DT_C_WRITE_DIG); + dt2801_writedata(dev, which); + dt2801_writedata(dev, s->state); + } + dt2801_writecmd(dev, DT_C_READ_DIG); + dt2801_writedata(dev, which); + dt2801_readdata(dev, data + 1); + + return 2; +} + +static int dt2801_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int which = 0; + + if (s == dev->subdevices + 4) + which = 1; + + /* configure */ + if (data[0]) { + s->io_bits = 0xff; + dt2801_writecmd(dev, DT_C_SET_DIGOUT); + } else { + s->io_bits = 0; + dt2801_writecmd(dev, DT_C_SET_DIGIN); + } + dt2801_writedata(dev, which); + + return 1; +} diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c new file mode 100644 index 000000000000..795932ec67d3 --- /dev/null +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -0,0 +1,604 @@ +/* + comedi/drivers/dt2811.c + Hardware driver for Data Translation DT2811 + + COMEDI - Linux Control and Measurement Device Interface + History: + Base Version - David A. Schleef + December 1998 - Updated to work. David does not have a DT2811 + board any longer so this was suffering from bitrot. + Updated performed by ... + + 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: dt2811 +Description: Data Translation DT2811 +Author: ds +Devices: [Data Translation] DT2811-PGL (dt2811-pgl), DT2811-PGH (dt2811-pgh) +Status: works + +Configuration options: + [0] - I/O port base address + [1] - IRQ, although this is currently unused + [2] - A/D reference + 0 = signle-ended + 1 = differential + 2 = pseudo-differential (common reference) + [3] - A/D range + 0 = [-5,5] + 1 = [-2.5,2.5] + 2 = [0,5] + [4] - D/A 0 range (same choices) + [4] - D/A 1 range (same choices) +*/ + +#include "../comedidev.h" + +#include + +static const char *driver_name = "dt2811"; + +static const struct comedi_lrange range_dt2811_pgh_ai_5_unipolar = { 4, { + RANGE(0, 5), + RANGE(0, 2.5), + RANGE(0, 1.25), + RANGE(0, 0.625) + } +}; +static const struct comedi_lrange range_dt2811_pgh_ai_2_5_bipolar = { 4, { + RANGE(-2.5, 2.5), + RANGE(-1.25, 1.25), + RANGE(-0.625, 0.625), + RANGE(-0.3125, 0.3125) + } +}; +static const struct comedi_lrange range_dt2811_pgh_ai_5_bipolar = { 4, { + RANGE(-5, 5), + RANGE(-2.5, 2.5), + RANGE(-1.25, 1.25), + RANGE(-0.625, 0.625) + } +}; +static const struct comedi_lrange range_dt2811_pgl_ai_5_unipolar = { 4, { + RANGE(0, 5), + RANGE(0, 0.5), + RANGE(0, 0.05), + RANGE(0, 0.01) + } +}; +static const struct comedi_lrange range_dt2811_pgl_ai_2_5_bipolar = { 4, { + RANGE(-2.5, 2.5), + RANGE(-0.25, 0.25), + RANGE(-0.025, 0.025), + RANGE(-0.005, 0.005) + } +}; +static const struct comedi_lrange range_dt2811_pgl_ai_5_bipolar = { 4, { + RANGE(-5, 5), + RANGE(-0.5, 0.5), + RANGE(-0.05, 0.05), + RANGE(-0.01, 0.01) + } +}; + +/* + + 0x00 ADCSR R/W A/D Control/Status Register + bit 7 - (R) 1 indicates A/D conversion done + reading ADDAT clears bit + (W) ignored + bit 6 - (R) 1 indicates A/D error + (W) ignored + bit 5 - (R) 1 indicates A/D busy, cleared at end + of conversion + (W) ignored + bit 4 - (R) 0 + (W) + bit 3 - (R) 0 + bit 2 - (R/W) 1 indicates interrupts enabled + bits 1,0 - (R/W) mode bits + 00 single conversion on ADGCR load + 01 continuous conversion, internal clock, + (clock enabled on ADGCR load) + 10 continuous conversion, internal clock, + external trigger + 11 continuous conversion, external clock, + external trigger + + 0x01 ADGCR R/W A/D Gain/Channel Register + bit 6,7 - (R/W) gain select + 00 gain=1, both PGH, PGL models + 01 gain=2 PGH, 10 PGL + 10 gain=4 PGH, 100 PGL + 11 gain=8 PGH, 500 PGL + bit 4,5 - reserved + bit 3-0 - (R/W) channel select + channel number from 0-15 + + 0x02,0x03 (R) ADDAT A/D Data Register + (W) DADAT0 D/A Data Register 0 + 0x02 low byte + 0x03 high byte + + 0x04,0x05 (W) DADAT0 D/A Data Register 1 + + 0x06 (R) DIO0 Digital Input Port 0 + (W) DIO1 Digital Output Port 1 + + 0x07 TMRCTR (R/W) Timer/Counter Register + bits 6,7 - reserved + bits 5-3 - Timer frequency control (mantissa) + 543 divisor freqency (kHz) + 000 1 600 + 001 10 60 + 010 2 300 + 011 3 200 + 100 4 150 + 101 5 120 + 110 6 100 + 111 12 50 + bits 2-0 - Timer frequency control (exponent) + 210 multiply divisor/divide frequency by + 000 1 + 001 10 + 010 100 + 011 1000 + 100 10000 + 101 100000 + 110 1000000 + 111 10000000 + + */ + +#define TIMEOUT 10000 + +#define DT2811_SIZE 8 + +#define DT2811_ADCSR 0 +#define DT2811_ADGCR 1 +#define DT2811_ADDATLO 2 +#define DT2811_ADDATHI 3 +#define DT2811_DADAT0LO 2 +#define DT2811_DADAT0HI 3 +#define DT2811_DADAT1LO 4 +#define DT2811_DADAT1HI 5 +#define DT2811_DIO 6 +#define DT2811_TMRCTR 7 + +/* + * flags + */ + +/* ADCSR */ + +#define DT2811_ADDONE 0x80 +#define DT2811_ADERROR 0x40 +#define DT2811_ADBUSY 0x20 +#define DT2811_CLRERROR 0x10 +#define DT2811_INTENB 0x04 +#define DT2811_ADMODE 0x03 + +struct dt2811_board { + + const char *name; + const struct comedi_lrange *bip_5; + const struct comedi_lrange *bip_2_5; + const struct comedi_lrange *unip_5; +}; + +static const struct dt2811_board boardtypes[] = { + {"dt2811-pgh", + &range_dt2811_pgh_ai_5_bipolar, + &range_dt2811_pgh_ai_2_5_bipolar, + &range_dt2811_pgh_ai_5_unipolar, + }, + {"dt2811-pgl", + &range_dt2811_pgl_ai_5_bipolar, + &range_dt2811_pgl_ai_2_5_bipolar, + &range_dt2811_pgl_ai_5_unipolar, + }, +}; + +#define this_board ((const struct dt2811_board *)dev->board_ptr) + +static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dt2811_detach(struct comedi_device * dev); +static struct comedi_driver driver_dt2811 = { + driver_name:"dt2811", + module:THIS_MODULE, + attach:dt2811_attach, + detach:dt2811_detach, + board_name:&boardtypes[0].name, + num_names:sizeof(boardtypes) / sizeof(struct dt2811_board), + offset:sizeof(struct dt2811_board), +}; + +COMEDI_INITCLEANUP(driver_dt2811); + +static int dt2811_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dt2811_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int dt2811_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +enum { card_2811_pgh, card_2811_pgl }; + +struct dt2811_private { + int ntrig; + int curadchan; + enum { + adc_singleended, adc_diff, adc_pseudo_diff + } adc_mux; + enum { + dac_bipolar_5, dac_bipolar_2_5, dac_unipolar_5 + } dac_range[2]; + const struct comedi_lrange *range_type_list[2]; + unsigned int ao_readback[2]; +}; + +#define devpriv ((struct dt2811_private *)dev->private) + +static const struct comedi_lrange *dac_range_types[] = { + &range_bipolar5, + &range_bipolar2_5, + &range_unipolar5 +}; + +#define DT2811_TIMEOUT 5 + +#if 0 +static irqreturn_t dt2811_interrupt(int irq, void *d PT_REGS_ARG) +{ + int lo, hi; + int data; + struct comedi_device *dev = d; + + if (!dev->attached) { + comedi_error(dev, "spurious interrupt"); + return IRQ_HANDLED; + } + + lo = inb(dev->iobase + DT2811_ADDATLO); + hi = inb(dev->iobase + DT2811_ADDATHI); + + data = lo + (hi << 8); + + if (!(--devpriv->ntrig)) { + /* how to turn off acquisition */ + s->async->events |= COMEDI_SB_EOA; + } + comedi_event(dev, s); + return IRQ_HANDLED; +} +#endif + +/* + options[0] Board base address + options[1] IRQ + options[2] Input configuration + 0 == single-ended + 1 == differential + 2 == pseudo-differential + options[3] Analog input range configuration + 0 == bipolar 5 (-5V -- +5V) + 1 == bipolar 2.5V (-2.5V -- +2.5V) + 2 == unipolar 5V (0V -- +5V) + options[4] Analog output 0 range configuration + 0 == bipolar 5 (-5V -- +5V) + 1 == bipolar 2.5V (-2.5V -- +2.5V) + 2 == unipolar 5V (0V -- +5V) + options[5] Analog output 1 range configuration + 0 == bipolar 5 (-5V -- +5V) + 1 == bipolar 2.5V (-2.5V -- +2.5V) + 2 == unipolar 5V (0V -- +5V) +*/ + +static int dt2811_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + //int i, irq; + //unsigned long irqs; + //long flags; + int ret; + struct comedi_subdevice *s; + unsigned long iobase; + + iobase = it->options[0]; + + printk("comedi%d: dt2811: base=0x%04lx\n", dev->minor, iobase); + + if (!request_region(iobase, DT2811_SIZE, driver_name)) { + printk("I/O port conflict\n"); + return -EIO; + } + + dev->iobase = iobase; + dev->board_name = this_board->name; + +#if 0 + outb(0, dev->iobase + DT2811_ADCSR); + comedi_udelay(100); + i = inb(dev->iobase + DT2811_ADDATLO); + i = inb(dev->iobase + DT2811_ADDATHI); +#endif + +#if 0 + irq = it->options[1]; + if (irq < 0) { + save_flags(flags); + sti(); + irqs = probe_irq_on(); + + outb(DT2811_CLRERROR | DT2811_INTENB, + dev->iobase + DT2811_ADCSR); + outb(0, dev->iobase + DT2811_ADGCR); + + comedi_udelay(100); + + irq = probe_irq_off(irqs); + restore_flags(flags); + + /*outb(DT2811_CLRERROR|DT2811_INTENB,dev->iobase+DT2811_ADCSR); */ + + if (inb(dev->iobase + DT2811_ADCSR) & DT2811_ADERROR) { + printk("error probing irq (bad) \n"); + } + dev->irq = 0; + if (irq > 0) { + i = inb(dev->iobase + DT2811_ADDATLO); + i = inb(dev->iobase + DT2811_ADDATHI); + printk("(irq = %d)\n", irq); + ret = comedi_request_irq(irq, dt2811_interrupt, 0, + driver_name, dev); + if (ret < 0) + return -EIO; + dev->irq = irq; + } else if (irq == 0) { + printk("(no irq)\n"); + } else { + printk("( multiple irq's -- this is bad! )\n"); + } + } +#endif + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + if ((ret = alloc_private(dev, sizeof(struct dt2811_private))) < 0) + return ret; + switch (it->options[2]) { + case 0: + devpriv->adc_mux = adc_singleended; + break; + case 1: + devpriv->adc_mux = adc_diff; + break; + case 2: + devpriv->adc_mux = adc_pseudo_diff; + break; + default: + devpriv->adc_mux = adc_singleended; + break; + } + switch (it->options[4]) { + case 0: + devpriv->dac_range[0] = dac_bipolar_5; + break; + case 1: + devpriv->dac_range[0] = dac_bipolar_2_5; + break; + case 2: + devpriv->dac_range[0] = dac_unipolar_5; + break; + default: + devpriv->dac_range[0] = dac_bipolar_5; + break; + } + switch (it->options[5]) { + case 0: + devpriv->dac_range[1] = dac_bipolar_5; + break; + case 1: + devpriv->dac_range[1] = dac_bipolar_2_5; + break; + case 2: + devpriv->dac_range[1] = dac_unipolar_5; + break; + default: + devpriv->dac_range[1] = dac_bipolar_5; + break; + } + + s = dev->subdevices + 0; + /* initialize the ADC subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = devpriv->adc_mux == adc_diff ? 8 : 16; + s->insn_read = dt2811_ai_insn; + s->maxdata = 0xfff; + switch (it->options[3]) { + case 0: + default: + s->range_table = this_board->bip_5; + break; + case 1: + s->range_table = this_board->bip_2_5; + break; + case 2: + s->range_table = this_board->unip_5; + break; + } + + s = dev->subdevices + 1; + /* ao subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->insn_write = dt2811_ao_insn; + s->insn_read = dt2811_ao_insn_read; + s->maxdata = 0xfff; + s->range_table_list = devpriv->range_type_list; + devpriv->range_type_list[0] = dac_range_types[devpriv->dac_range[0]]; + devpriv->range_type_list[1] = dac_range_types[devpriv->dac_range[1]]; + + s = dev->subdevices + 2; + /* di subdevice */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 8; + s->insn_bits = dt2811_di_insn_bits; + s->maxdata = 1; + s->range_table = &range_digital; + + s = dev->subdevices + 3; + /* do subdevice */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 8; + s->insn_bits = dt2811_do_insn_bits; + s->maxdata = 1; + s->state = 0; + s->range_table = &range_digital; + + return 0; +} + +static int dt2811_detach(struct comedi_device * dev) +{ + printk("comedi%d: dt2811: remove\n", dev->minor); + + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + if (dev->iobase) { + release_region(dev->iobase, DT2811_SIZE); + } + + return 0; +} + +static int dt2811_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + int timeout = DT2811_TIMEOUT; + int i; + + for (i = 0; i < insn->n; i++) { + outb(chan, dev->iobase + DT2811_ADGCR); + + while (timeout + && inb(dev->iobase + DT2811_ADCSR) & DT2811_ADBUSY) + timeout--; + if (!timeout) + return -ETIME; + + data[i] = inb(dev->iobase + DT2811_ADDATLO); + data[i] |= inb(dev->iobase + DT2811_ADDATHI) << 8; + data[i] &= 0xfff; + } + + return i; +} + +#if 0 +/* Wow. This is code from the Comedi stone age. But it hasn't been + * replaced, so I'll let it stay. */ +int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig) +{ + struct comedi_device *dev = comedi_devices + minor; + + if (adtrig->n < 1) + return 0; + dev->curadchan = adtrig->chan; + switch (dev->i_admode) { + case COMEDI_MDEMAND: + dev->ntrig = adtrig->n - 1; + /*printk("dt2811: AD soft trigger\n"); */ + /*outb(DT2811_CLRERROR|DT2811_INTENB,dev->iobase+DT2811_ADCSR); *//* not neccessary */ + outb(dev->curadchan, dev->iobase + DT2811_ADGCR); + do_gettimeofday(&trigtime); + break; + case COMEDI_MCONTS: + dev->ntrig = adtrig->n; + break; + } + + return 0; +} +#endif + +static int dt2811_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan; + + chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + outb(data[i] & 0xff, dev->iobase + DT2811_DADAT0LO + 2 * chan); + outb((data[i] >> 8) & 0xff, + dev->iobase + DT2811_DADAT0HI + 2 * chan); + devpriv->ao_readback[chan] = data[i]; + } + + return i; +} + +static int dt2811_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan; + + chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +static int dt2811_di_insn_bits(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 + DT2811_DIO); + + return 2; +} + +static int dt2811_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + outb(s->state, dev->iobase + DT2811_DIO); + + data[1] = s->state; + + return 2; +} diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c new file mode 100644 index 000000000000..8320139160a4 --- /dev/null +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -0,0 +1,383 @@ +/* + comedi/drivers/dt2814.c + Hardware driver for Data Translation DT2814 + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998 David A. Schleef + + 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: dt2814 +Description: Data Translation DT2814 +Author: ds +Status: complete +Devices: [Data Translation] DT2814 (dt2814) + +Configuration options: + [0] - I/O port base address + [1] - IRQ + +This card has 16 analog inputs multiplexed onto a 12 bit ADC. There +is a minimally useful onboard clock. The base frequency for the +clock is selected by jumpers, and the clock divider can be selected +via programmed I/O. Unfortunately, the clock divider can only be +a power of 10, from 1 to 10^7, of which only 3 or 4 are useful. In +addition, the clock does not seem to be very accurate. +*/ + +#include "../comedidev.h" + +#include +#include + +#define DT2814_SIZE 2 + +#define DT2814_CSR 0 +#define DT2814_DATA 1 + +/* + * flags + */ + +#define DT2814_FINISH 0x80 +#define DT2814_ERR 0x40 +#define DT2814_BUSY 0x20 +#define DT2814_ENB 0x10 +#define DT2814_CHANMASK 0x0f + +static int dt2814_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dt2814_detach(struct comedi_device * dev); +static struct comedi_driver driver_dt2814 = { + driver_name:"dt2814", + module:THIS_MODULE, + attach:dt2814_attach, + detach:dt2814_detach, +}; + +COMEDI_INITCLEANUP(driver_dt2814); + +static irqreturn_t dt2814_interrupt(int irq, void *dev PT_REGS_ARG); + +struct dt2814_private { + + int ntrig; + int curadchan; +}; + +#define devpriv ((struct dt2814_private *)dev->private) + +#define DT2814_TIMEOUT 10 +#define DT2814_MAX_SPEED 100000 /* Arbitrary 10 khz limit */ + +static int dt2814_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, i, hi, lo; + int chan; + int status = 0; + + for (n = 0; n < insn->n; n++) { + chan = CR_CHAN(insn->chanspec); + + outb(chan, dev->iobase + DT2814_CSR); + for (i = 0; i < DT2814_TIMEOUT; i++) { + status = inb(dev->iobase + DT2814_CSR); + printk("dt2814: status: %02x\n", status); + comedi_udelay(10); + if (status & DT2814_FINISH) + break; + } + if (i >= DT2814_TIMEOUT) { + printk("dt2814: status: %02x\n", status); + return -ETIMEDOUT; + } + + hi = inb(dev->iobase + DT2814_DATA); + lo = inb(dev->iobase + DT2814_DATA); + + data[n] = (hi << 4) | (lo >> 4); + } + + return n; +} + +static int dt2814_ns_to_timer(unsigned int *ns, unsigned int flags) +{ + int i; + unsigned int f; + + /* XXX ignores flags */ + + f = 10000; /* ns */ + for (i = 0; i < 8; i++) { + if ((2 * (*ns)) < (f * 11)) + break; + f *= 10; + } + + *ns = f; + + return i; +} + +static int dt2814_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + 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_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + if (cmd->scan_begin_arg > 1000000000) { + cmd->scan_begin_arg = 1000000000; + err++; + } + if (cmd->scan_begin_arg < DT2814_MAX_SPEED) { + cmd->scan_begin_arg = DT2814_MAX_SPEED; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_arg < 2) { + cmd->stop_arg = 2; + err++; + } + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + tmp = cmd->scan_begin_arg; + dt2814_ns_to_timer(&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + + if (err) + return 4; + + return 0; +} + +static int dt2814_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + int chan; + int trigvar; + + trigvar = + dt2814_ns_to_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + + chan = CR_CHAN(cmd->chanlist[0]); + + devpriv->ntrig = cmd->stop_arg; + outb(chan | DT2814_ENB | (trigvar << 5), dev->iobase + DT2814_CSR); + + return 0; + +} + +static int dt2814_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int i, irq; + int ret; + struct comedi_subdevice *s; + unsigned long iobase; + + iobase = it->options[0]; + printk("comedi%d: dt2814: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, DT2814_SIZE, "dt2814")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + dev->board_name = "dt2814"; + + outb(0, dev->iobase + DT2814_CSR); + comedi_udelay(100); + if (inb(dev->iobase + DT2814_CSR) & DT2814_ERR) { + printk("reset error (fatal)\n"); + return -EIO; + } + i = inb(dev->iobase + DT2814_DATA); + i = inb(dev->iobase + DT2814_DATA); + + irq = it->options[1]; +#if 0 + if (irq < 0) { + save_flags(flags); + sti(); + irqs = probe_irq_on(); + + outb(0, dev->iobase + DT2814_CSR); + + comedi_udelay(100); + + irq = probe_irq_off(irqs); + restore_flags(flags); + if (inb(dev->iobase + DT2814_CSR) & DT2814_ERR) { + printk("error probing irq (bad) \n"); + } + + i = inb(dev->iobase + DT2814_DATA); + i = inb(dev->iobase + DT2814_DATA); + } +#endif + dev->irq = 0; + if (irq > 0) { + if (comedi_request_irq(irq, dt2814_interrupt, 0, "dt2814", dev)) { + printk("(irq %d unavailable)\n", irq); + } else { + printk("( irq = %d )\n", irq); + dev->irq = irq; + } + } else if (irq == 0) { + printk("(no irq)\n"); + } else { +#if 0 + printk("(probe returned multiple irqs--bad)\n"); +#else + printk("(irq probe not implemented)\n"); +#endif + } + + if ((ret = alloc_subdevices(dev, 1)) < 0) + return ret; + if ((ret = alloc_private(dev, sizeof(struct dt2814_private))) < 0) + return ret; + + s = dev->subdevices + 0; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; + s->n_chan = 16; /* XXX */ + s->len_chanlist = 1; + s->insn_read = dt2814_ai_insn_read; + s->do_cmd = dt2814_ai_cmd; + s->do_cmdtest = dt2814_ai_cmdtest; + s->maxdata = 0xfff; + s->range_table = &range_unknown; /* XXX */ + + return 0; +} + +static int dt2814_detach(struct comedi_device * dev) +{ + printk("comedi%d: dt2814: remove\n", dev->minor); + + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + if (dev->iobase) { + release_region(dev->iobase, DT2814_SIZE); + } + + return 0; +} + +static irqreturn_t dt2814_interrupt(int irq, void *d PT_REGS_ARG) +{ + int lo, hi; + struct comedi_device *dev = d; + struct comedi_subdevice *s; + int data; + + if (!dev->attached) { + comedi_error(dev, "spurious interrupt"); + return IRQ_HANDLED; + } + + s = dev->subdevices + 0; + + hi = inb(dev->iobase + DT2814_DATA); + lo = inb(dev->iobase + DT2814_DATA); + + data = (hi << 4) | (lo >> 4); + + if (!(--devpriv->ntrig)) { + int i; + + outb(0, dev->iobase + DT2814_CSR); + /* note: turning off timed mode triggers another + sample. */ + + for (i = 0; i < DT2814_TIMEOUT; i++) { + if (inb(dev->iobase + DT2814_CSR) & DT2814_FINISH) + break; + } + inb(dev->iobase + DT2814_DATA); + inb(dev->iobase + DT2814_DATA); + + s->async->events |= COMEDI_CB_EOA; + } + comedi_event(dev, s); + return IRQ_HANDLED; +} diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c new file mode 100644 index 000000000000..fccec8a77d50 --- /dev/null +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -0,0 +1,264 @@ +/* + comedi/drivers/dt2815.c + Hardware driver for Data Translation DT2815 + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999 Anders Blomdell + + 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: dt2815 +Description: Data Translation DT2815 +Author: ds +Status: mostly complete, untested +Devices: [Data Translation] DT2815 (dt2815) + +I'm not sure anyone has ever tested this board. If you have information +contrary, please update. + +Configuration options: + [0] - I/O port base base address + [1] - IRQ (unused) + [2] - Voltage unipolar/bipolar configuration + 0 == unipolar 5V (0V -- +5V) + 1 == bipolar 5V (-5V -- +5V) + [3] - Current offset configuration + 0 == disabled (0mA -- +32mAV) + 1 == enabled (+4mA -- +20mAV) + [4] - Firmware program configuration + 0 == program 1 (see manual table 5-4) + 1 == program 2 (see manual table 5-4) + 2 == program 3 (see manual table 5-4) + 3 == program 4 (see manual table 5-4) + [5] - Analog output 0 range configuration + 0 == voltage + 1 == current + [6] - Analog output 1 range configuration (same options) + [7] - Analog output 2 range configuration (same options) + [8] - Analog output 3 range configuration (same options) + [9] - Analog output 4 range configuration (same options) + [10] - Analog output 5 range configuration (same options) + [11] - Analog output 6 range configuration (same options) + [12] - Analog output 7 range configuration (same options) +*/ + +#include "../comedidev.h" + +#include +#include + +static const struct comedi_lrange range_dt2815_ao_32_current = { 1, { + RANGE_mA(0, 32) + } +}; +static const struct comedi_lrange range_dt2815_ao_20_current = { 1, { + RANGE_mA(4, 20) + } +}; + +#define DT2815_SIZE 2 + +#define DT2815_DATA 0 +#define DT2815_STATUS 1 + +static int dt2815_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dt2815_detach(struct comedi_device * dev); +static struct comedi_driver driver_dt2815 = { + driver_name:"dt2815", + module:THIS_MODULE, + attach:dt2815_attach, + detach:dt2815_detach, +}; + +COMEDI_INITCLEANUP(driver_dt2815); + +static void dt2815_free_resources(struct comedi_device * dev); + +struct dt2815_private { + + const struct comedi_lrange *range_type_list[8]; + unsigned int ao_readback[8]; +}; + + +#define devpriv ((struct dt2815_private *)dev->private) + +static int dt2815_wait_for_status(struct comedi_device * dev, int status) +{ + int i; + + for (i = 0; i < 100; i++) { + if (inb(dev->iobase + DT2815_STATUS) == status) + break; + } + return status; +} + +static int dt2815_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +static int dt2815_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + unsigned int status; + unsigned int lo, hi; + + for (i = 0; i < insn->n; i++) { + lo = ((data[i] & 0x0f) << 4) | (chan << 1) | 0x01; + hi = (data[i] & 0xff0) >> 4; + + status = dt2815_wait_for_status(dev, 0x00); + if (status != 0) { + rt_printk + ("dt2815: failed to write low byte on %d reason %x\n", + chan, status); + return -EBUSY; + } + + outb(lo, dev->iobase + DT2815_DATA); + + status = dt2815_wait_for_status(dev, 0x10); + if (status != 0x10) { + rt_printk + ("dt2815: failed to write high byte on %d reason %x\n", + chan, status); + return -EBUSY; + } + devpriv->ao_readback[chan] = data[i]; + } + return i; +} + +/* + options[0] Board base address + options[1] IRQ (not applicable) + options[2] Voltage unipolar/bipolar configuration + 0 == unipolar 5V (0V -- +5V) + 1 == bipolar 5V (-5V -- +5V) + options[3] Current offset configuration + 0 == disabled (0mA -- +32mAV) + 1 == enabled (+4mA -- +20mAV) + options[4] Firmware program configuration + 0 == program 1 (see manual table 5-4) + 1 == program 2 (see manual table 5-4) + 2 == program 3 (see manual table 5-4) + 3 == program 4 (see manual table 5-4) + options[5] Analog output 0 range configuration + 0 == voltage + 1 == current + options[6] Analog output 1 range configuration + ... + options[12] Analog output 7 range configuration + 0 == voltage + 1 == current + */ + +static int dt2815_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int i; + const struct comedi_lrange *current_range_type, *voltage_range_type; + unsigned long iobase; + + iobase = it->options[0]; + printk("comedi%d: dt2815: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, DT2815_SIZE, "dt2815")) { + printk("I/O port conflict\n"); + return -EIO; + } + + dev->iobase = iobase; + dev->board_name = "dt2815"; + + if (alloc_subdevices(dev, 1) < 0) + return -ENOMEM; + if (alloc_private(dev, sizeof(struct dt2815_private)) < 0) + return -ENOMEM; + + s = dev->subdevices; + /* ao subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 0xfff; + s->n_chan = 8; + s->insn_write = dt2815_ao_insn; + s->insn_read = dt2815_ao_insn_read; + s->range_table_list = devpriv->range_type_list; + + current_range_type = (it->options[3]) + ? &range_dt2815_ao_20_current : &range_dt2815_ao_32_current; + voltage_range_type = (it->options[2]) + ? &range_bipolar5 : &range_unipolar5; + for (i = 0; i < 8; i++) { + devpriv->range_type_list[i] = (it->options[5 + i]) + ? current_range_type : voltage_range_type; + } + + /* Init the 2815 */ + outb(0x00, dev->iobase + DT2815_STATUS); + for (i = 0; i < 100; i++) { + /* This is incredibly slow (approx 20 ms) */ + unsigned int status; + + comedi_udelay(1000); + status = inb(dev->iobase + DT2815_STATUS); + if (status == 4) { + unsigned int program; + program = (it->options[4] & 0x3) << 3 | 0x7; + outb(program, dev->iobase + DT2815_DATA); + printk(", program: 0x%x (@t=%d)\n", program, i); + break; + } else if (status != 0x00) { + printk("dt2815: unexpected status 0x%x (@t=%d)\n", + status, i); + if (status & 0x60) { + outb(0x00, dev->iobase + DT2815_STATUS); + } + } + } + + printk("\n"); + + return 0; +} + +static void dt2815_free_resources(struct comedi_device * dev) +{ + if (dev->iobase) + release_region(dev->iobase, DT2815_SIZE); +} + +static int dt2815_detach(struct comedi_device * dev) +{ + printk("comedi%d: dt2815: remove\n", dev->minor); + + dt2815_free_resources(dev); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c new file mode 100644 index 000000000000..2dc396a44e6f --- /dev/null +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -0,0 +1,178 @@ +/* + comedi/drivers/dt2817.c + Hardware driver for Data Translation DT2817 + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998 David A. Schleef + + 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: dt2817 +Description: Data Translation DT2817 +Author: ds +Status: complete +Devices: [Data Translation] DT2817 (dt2817) + +A very simple digital I/O card. Four banks of 8 lines, each bank +is configurable for input or output. One wonders why it takes a +50 page manual to describe this thing. + +The driver (which, btw, is much less than 50 pages) has 1 subdevice +with 32 channels, configurable in groups of 8. + +Configuration options: + [0] - I/O port base base address +*/ + +#include "../comedidev.h" + +#include + +#define DT2817_SIZE 5 + +#define DT2817_CR 0 +#define DT2817_DATA 1 + +static int dt2817_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dt2817_detach(struct comedi_device * dev); +static struct comedi_driver driver_dt2817 = { + driver_name:"dt2817", + module:THIS_MODULE, + attach:dt2817_attach, + detach:dt2817_detach, +}; + +COMEDI_INITCLEANUP(driver_dt2817); + +static int dt2817_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int mask; + int chan; + int oe = 0; + + if (insn->n != 1) + return -EINVAL; + + chan = CR_CHAN(insn->chanspec); + if (chan < 8) { + mask = 0xff; + } else if (chan < 16) { + mask = 0xff00; + } else if (chan < 24) { + mask = 0xff0000; + } else + mask = 0xff000000; + if (data[0]) + s->io_bits |= mask; + else + s->io_bits &= ~mask; + + if (s->io_bits & 0x000000ff) + oe |= 0x1; + if (s->io_bits & 0x0000ff00) + oe |= 0x2; + if (s->io_bits & 0x00ff0000) + oe |= 0x4; + if (s->io_bits & 0xff000000) + oe |= 0x8; + + outb(oe, dev->iobase + DT2817_CR); + + return 1; +} + +static int dt2817_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int changed; + + /* It's questionable whether it is more important in + * a driver like this to be deterministic or fast. + * We choose fast. */ + + if (data[0]) { + changed = s->state; + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + changed ^= s->state; + changed &= s->io_bits; + if (changed & 0x000000ff) + outb(s->state & 0xff, dev->iobase + DT2817_DATA + 0); + if (changed & 0x0000ff00) + outb((s->state >> 8) & 0xff, + dev->iobase + DT2817_DATA + 1); + if (changed & 0x00ff0000) + outb((s->state >> 16) & 0xff, + dev->iobase + DT2817_DATA + 2); + if (changed & 0xff000000) + outb((s->state >> 24) & 0xff, + dev->iobase + DT2817_DATA + 3); + } + data[1] = inb(dev->iobase + DT2817_DATA + 0); + data[1] |= (inb(dev->iobase + DT2817_DATA + 1) << 8); + data[1] |= (inb(dev->iobase + DT2817_DATA + 2) << 16); + data[1] |= (inb(dev->iobase + DT2817_DATA + 3) << 24); + + return 2; +} + +static int dt2817_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + struct comedi_subdevice *s; + unsigned long iobase; + + iobase = it->options[0]; + printk("comedi%d: dt2817: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, DT2817_SIZE, "dt2817")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + dev->board_name = "dt2817"; + + if ((ret = alloc_subdevices(dev, 1)) < 0) + return ret; + + s = dev->subdevices + 0; + + s->n_chan = 32; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_bits = dt2817_dio_insn_bits; + s->insn_config = dt2817_dio_insn_config; + + s->state = 0; + outb(0, dev->iobase + DT2817_CR); + + printk("\n"); + + return 0; +} + +static int dt2817_detach(struct comedi_device * dev) +{ + printk("comedi%d: dt2817: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, DT2817_SIZE); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c new file mode 100644 index 000000000000..4882c3e679cc --- /dev/null +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -0,0 +1,1471 @@ +/* + comedi/drivers/dt282x.c + Hardware driver for Data Translation DT2821 series + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-8 David A. Schleef + + 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: dt282x +Description: Data Translation DT2821 series (including DT-EZ) +Author: ds +Devices: [Data Translation] DT2821 (dt2821), + DT2821-F-16SE (dt2821-f), DT2821-F-8DI (dt2821-f), + DT2821-G-16SE (dt2821-f), DT2821-G-8DI (dt2821-g), + DT2823 (dt2823), + DT2824-PGH (dt2824-pgh), DT2824-PGL (dt2824-pgl), DT2825 (dt2825), + DT2827 (dt2827), DT2828 (dt2828), DT21-EZ (dt21-ez), DT23-EZ (dt23-ez), + DT24-EZ (dt24-ez), DT24-EZ-PGL (dt24-ez-pgl) +Status: complete +Updated: Wed, 22 Aug 2001 17:11:34 -0700 + +Configuration options: + [0] - I/O port base address + [1] - IRQ + [2] - DMA 1 + [3] - DMA 2 + [4] - AI jumpered for 0=single ended, 1=differential + [5] - AI jumpered for 0=straight binary, 1=2's complement + [6] - AO 0 jumpered for 0=straight binary, 1=2's complement + [7] - AO 1 jumpered for 0=straight binary, 1=2's complement + [8] - AI jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5] + [9] - AO 0 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5], + 4=[-2.5,2.5] + [10]- A0 1 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5], + 4=[-2.5,2.5] + +Notes: + - AO commands might be broken. + - If you try to run a command on both the AI and AO subdevices + simultaneously, bad things will happen. The driver needs to + be fixed to check for this situation and return an error. +*/ + +#include "../comedidev.h" + +#include +#include +#include +#include "comedi_fc.h" + +#define DEBUG + +#define DT2821_TIMEOUT 100 /* 500 us */ +#define DT2821_SIZE 0x10 + +/* + * Registers in the DT282x + */ + +#define DT2821_ADCSR 0x00 /* A/D Control/Status */ +#define DT2821_CHANCSR 0x02 /* Channel Control/Status */ +#define DT2821_ADDAT 0x04 /* A/D data */ +#define DT2821_DACSR 0x06 /* D/A Control/Status */ +#define DT2821_DADAT 0x08 /* D/A data */ +#define DT2821_DIODAT 0x0a /* digital data */ +#define DT2821_SUPCSR 0x0c /* Supervisor Control/Status */ +#define DT2821_TMRCTR 0x0e /* Timer/Counter */ + +/* + * At power up, some registers are in a well-known state. The + * masks and values are as follows: + */ + +#define DT2821_ADCSR_MASK 0xfff0 +#define DT2821_ADCSR_VAL 0x7c00 + +#define DT2821_CHANCSR_MASK 0xf0f0 +#define DT2821_CHANCSR_VAL 0x70f0 + +#define DT2821_DACSR_MASK 0x7c93 +#define DT2821_DACSR_VAL 0x7c90 + +#define DT2821_SUPCSR_MASK 0xf8ff +#define DT2821_SUPCSR_VAL 0x0000 + +#define DT2821_TMRCTR_MASK 0xff00 +#define DT2821_TMRCTR_VAL 0xf000 + +/* + * Bit fields of each register + */ + +/* ADCSR */ + +#define DT2821_ADERR 0x8000 /* (R) 1 for A/D error */ +#define DT2821_ADCLK 0x0200 /* (R/W) A/D clock enable */ + /* 0x7c00 read as 1's */ +#define DT2821_MUXBUSY 0x0100 /* (R) multiplexer busy */ +#define DT2821_ADDONE 0x0080 /* (R) A/D done */ +#define DT2821_IADDONE 0x0040 /* (R/W) interrupt on A/D done */ + /* 0x0030 gain select */ + /* 0x000f channel select */ + +/* CHANCSR */ + +#define DT2821_LLE 0x8000 /* (R/W) Load List Enable */ + /* 0x7000 read as 1's */ + /* 0x0f00 (R) present address */ + /* 0x00f0 read as 1's */ + /* 0x000f (R) number of entries - 1 */ + +/* DACSR */ + +#define DT2821_DAERR 0x8000 /* (R) D/A error */ +#define DT2821_YSEL 0x0200 /* (R/W) DAC 1 select */ +#define DT2821_SSEL 0x0100 /* (R/W) single channel select */ +#define DT2821_DACRDY 0x0080 /* (R) DAC ready */ +#define DT2821_IDARDY 0x0040 /* (R/W) interrupt on DAC ready */ +#define DT2821_DACLK 0x0020 /* (R/W) D/A clock enable */ +#define DT2821_HBOE 0x0002 /* (R/W) DIO high byte output enable */ +#define DT2821_LBOE 0x0001 /* (R/W) DIO low byte output enable */ + +/* SUPCSR */ + +#define DT2821_DMAD 0x8000 /* (R) DMA done */ +#define DT2821_ERRINTEN 0x4000 /* (R/W) interrupt on error */ +#define DT2821_CLRDMADNE 0x2000 /* (W) clear DMA done */ +#define DT2821_DDMA 0x1000 /* (R/W) dual DMA */ +#define DT2821_DS1 0x0800 /* (R/W) DMA select 1 */ +#define DT2821_DS0 0x0400 /* (R/W) DMA select 0 */ +#define DT2821_BUFFB 0x0200 /* (R/W) buffer B selected */ +#define DT2821_SCDN 0x0100 /* (R) scan done */ +#define DT2821_DACON 0x0080 /* (W) DAC single conversion */ +#define DT2821_ADCINIT 0x0040 /* (W) A/D initialize */ +#define DT2821_DACINIT 0x0020 /* (W) D/A initialize */ +#define DT2821_PRLD 0x0010 /* (W) preload multiplexer */ +#define DT2821_STRIG 0x0008 /* (W) software trigger */ +#define DT2821_XTRIG 0x0004 /* (R/W) external trigger enable */ +#define DT2821_XCLK 0x0002 /* (R/W) external clock enable */ +#define DT2821_BDINIT 0x0001 /* (W) initialize board */ + +static const struct comedi_lrange range_dt282x_ai_lo_bipolar = { 4, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2.5, 2.5), + RANGE(-1.25, 1.25) + } +}; +static const struct comedi_lrange range_dt282x_ai_lo_unipolar = { 4, { + RANGE(0, 10), + RANGE(0, 5), + RANGE(0, 2.5), + RANGE(0, 1.25) + } +}; +static const struct comedi_lrange range_dt282x_ai_5_bipolar = { 4, { + RANGE(-5, 5), + RANGE(-2.5, 2.5), + RANGE(-1.25, 1.25), + RANGE(-0.625, 0.625), + } +}; +static const struct comedi_lrange range_dt282x_ai_5_unipolar = { 4, { + RANGE(0, 5), + RANGE(0, 2.5), + RANGE(0, 1.25), + RANGE(0, 0.625), + } +}; +static const struct comedi_lrange range_dt282x_ai_hi_bipolar = { 4, { + RANGE(-10, 10), + RANGE(-1, 1), + RANGE(-0.1, 0.1), + RANGE(-0.02, 0.02) + } +}; +static const struct comedi_lrange range_dt282x_ai_hi_unipolar = { 4, { + RANGE(0, 10), + RANGE(0, 1), + RANGE(0, 0.1), + RANGE(0, 0.02) + } +}; + +struct dt282x_board { + const char *name; + int adbits; + int adchan_se; + int adchan_di; + int ai_speed; + int ispgl; + int dachan; + int dabits; +}; + +static const struct dt282x_board boardtypes[] = { + {name:"dt2821", + adbits: 12, + adchan_se:16, + adchan_di:8, + ai_speed:20000, + ispgl: 0, + dachan: 2, + dabits: 12, + }, + {name:"dt2821-f", + adbits: 12, + adchan_se:16, + adchan_di:8, + ai_speed:6500, + ispgl: 0, + dachan: 2, + dabits: 12, + }, + {name:"dt2821-g", + adbits: 12, + adchan_se:16, + adchan_di:8, + ai_speed:4000, + ispgl: 0, + dachan: 2, + dabits: 12, + }, + {name:"dt2823", + adbits: 16, + adchan_se:0, + adchan_di:4, + ai_speed:10000, + ispgl: 0, + dachan: 2, + dabits: 16, + }, + {name:"dt2824-pgh", + adbits: 12, + adchan_se:16, + adchan_di:8, + ai_speed:20000, + ispgl: 0, + dachan: 0, + dabits: 0, + }, + {name:"dt2824-pgl", + adbits: 12, + adchan_se:16, + adchan_di:8, + ai_speed:20000, + ispgl: 1, + dachan: 0, + dabits: 0, + }, + {name:"dt2825", + adbits: 12, + adchan_se:16, + adchan_di:8, + ai_speed:20000, + ispgl: 1, + dachan: 2, + dabits: 12, + }, + {name:"dt2827", + adbits: 16, + adchan_se:0, + adchan_di:4, + ai_speed:10000, + ispgl: 0, + dachan: 2, + dabits: 12, + }, + {name:"dt2828", + adbits: 12, + adchan_se:4, + adchan_di:0, + ai_speed:10000, + ispgl: 0, + dachan: 2, + dabits: 12, + }, + {name:"dt2829", + adbits: 16, + adchan_se:8, + adchan_di:0, + ai_speed:33250, + ispgl: 0, + dachan: 2, + dabits: 16, + }, + {name:"dt21-ez", + adbits: 12, + adchan_se:16, + adchan_di:8, + ai_speed:10000, + ispgl: 0, + dachan: 2, + dabits: 12, + }, + {name:"dt23-ez", + adbits: 16, + adchan_se:16, + adchan_di:8, + ai_speed:10000, + ispgl: 0, + dachan: 0, + dabits: 0, + }, + {name:"dt24-ez", + adbits: 12, + adchan_se:16, + adchan_di:8, + ai_speed:10000, + ispgl: 0, + dachan: 0, + dabits: 0, + }, + {name:"dt24-ez-pgl", + adbits: 12, + adchan_se:16, + adchan_di:8, + ai_speed:10000, + ispgl: 1, + dachan: 0, + dabits: 0, + }, +}; + +#define n_boardtypes sizeof(boardtypes)/sizeof(struct dt282x_board) +#define this_board ((const struct dt282x_board *)dev->board_ptr) + +struct dt282x_private { + int ad_2scomp; /* we have 2's comp jumper set */ + int da0_2scomp; /* same, for DAC0 */ + int da1_2scomp; /* same, for DAC1 */ + + const struct comedi_lrange *darangelist[2]; + + short ao[2]; + + volatile int dacsr; /* software copies of registers */ + volatile int adcsr; + volatile int supcsr; + + volatile int ntrig; + volatile int nread; + + struct { + int chan; + short *buf; /* DMA buffer */ + volatile int size; /* size of current transfer */ + } dma[2]; + int dma_maxsize; /* max size of DMA transfer (in bytes) */ + int usedma; /* driver uses DMA */ + volatile int current_dma_index; + int dma_dir; +}; + +#define devpriv ((struct dt282x_private *)dev->private) +#define boardtype (*(const struct dt282x_board *)dev->board_ptr) + +/* + * Some useless abstractions + */ +#define chan_to_DAC(a) ((a)&1) +#define update_dacsr(a) outw(devpriv->dacsr|(a),dev->iobase+DT2821_DACSR) +#define update_adcsr(a) outw(devpriv->adcsr|(a),dev->iobase+DT2821_ADCSR) +#define mux_busy() (inw(dev->iobase+DT2821_ADCSR)&DT2821_MUXBUSY) +#define ad_done() (inw(dev->iobase+DT2821_ADCSR)&DT2821_ADDONE) +#define update_supcsr(a) outw(devpriv->supcsr|(a),dev->iobase+DT2821_SUPCSR) + +/* + * danger! macro abuse... a is the expression to wait on, and b is + * the statement(s) to execute if it doesn't happen. + */ +#define wait_for(a,b) \ + do{ \ + int _i; \ + for(_i=0;_iad_2scomp) { + sign = 1 << (boardtype.adbits - 1); + } else { + sign = 0; + } + + if (nbytes % 2) + comedi_error(dev, "bug! odd number of bytes from dma xfer"); + n = nbytes / 2; + for (i = 0; i < n; i++) { + buf[i] = (buf[i] & mask) ^ sign; + } +} + +static void dt282x_ao_dma_interrupt(struct comedi_device * dev) +{ + void *ptr; + int size; + int i; + struct comedi_subdevice *s = dev->subdevices + 1; + + update_supcsr(DT2821_CLRDMADNE); + + if (!s->async->prealloc_buf) { + printk("async->data disappeared. dang!\n"); + return; + } + + i = devpriv->current_dma_index; + ptr = devpriv->dma[i].buf; + + disable_dma(devpriv->dma[i].chan); + + devpriv->current_dma_index = 1 - i; + + size = cfc_read_array_from_buffer(s, ptr, devpriv->dma_maxsize); + if (size == 0) { + rt_printk("dt282x: AO underrun\n"); + dt282x_ao_cancel(dev, s); + s->async->events |= COMEDI_CB_OVERFLOW; + return; + } + prep_ao_dma(dev, i, size); + return; +} + +static void dt282x_ai_dma_interrupt(struct comedi_device * dev) +{ + void *ptr; + int size; + int i; + int ret; + struct comedi_subdevice *s = dev->subdevices; + + update_supcsr(DT2821_CLRDMADNE); + + if (!s->async->prealloc_buf) { + printk("async->data disappeared. dang!\n"); + return; + } + + i = devpriv->current_dma_index; + ptr = devpriv->dma[i].buf; + size = devpriv->dma[i].size; + + disable_dma(devpriv->dma[i].chan); + + devpriv->current_dma_index = 1 - i; + + dt282x_munge(dev, ptr, size); + ret = cfc_write_array_to_buffer(s, ptr, size); + if (ret != size) { + dt282x_ai_cancel(dev, s); + return; + } + devpriv->nread -= size / 2; + + if (devpriv->nread < 0) { + printk("dt282x: off by one\n"); + devpriv->nread = 0; + } + if (!devpriv->nread) { + dt282x_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + return; + } +#if 0 + /* clear the dual dma flag, making this the last dma segment */ + /* XXX probably wrong */ + if (!devpriv->ntrig) { + devpriv->supcsr &= ~(DT2821_DDMA); + update_supcsr(0); + } +#endif + /* restart the channel */ + prep_ai_dma(dev, i, 0); +} + +static int prep_ai_dma(struct comedi_device * dev, int dma_index, int n) +{ + int dma_chan; + unsigned long dma_ptr; + unsigned long flags; + + if (!devpriv->ntrig) + return 0; + + if (n == 0) + n = devpriv->dma_maxsize; + if (n > devpriv->ntrig * 2) + n = devpriv->ntrig * 2; + devpriv->ntrig -= n / 2; + + devpriv->dma[dma_index].size = n; + dma_chan = devpriv->dma[dma_index].chan; + dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); + + set_dma_mode(dma_chan, DMA_MODE_READ); + flags = claim_dma_lock(); + clear_dma_ff(dma_chan); + set_dma_addr(dma_chan, dma_ptr); + set_dma_count(dma_chan, n); + release_dma_lock(flags); + + enable_dma(dma_chan); + + return n; +} + +static int prep_ao_dma(struct comedi_device * dev, int dma_index, int n) +{ + int dma_chan; + unsigned long dma_ptr; + unsigned long flags; + + devpriv->dma[dma_index].size = n; + dma_chan = devpriv->dma[dma_index].chan; + dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); + + set_dma_mode(dma_chan, DMA_MODE_WRITE); + flags = claim_dma_lock(); + clear_dma_ff(dma_chan); + set_dma_addr(dma_chan, dma_ptr); + set_dma_count(dma_chan, n); + release_dma_lock(flags); + + enable_dma(dma_chan); + + return n; +} + +static irqreturn_t dt282x_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s; + struct comedi_subdevice *s_ao; + unsigned int supcsr, adcsr, dacsr; + int handled = 0; + + if (!dev->attached) { + comedi_error(dev, "spurious interrupt"); + return IRQ_HANDLED; + } + + s = dev->subdevices + 0; + s_ao = dev->subdevices + 1; + adcsr = inw(dev->iobase + DT2821_ADCSR); + dacsr = inw(dev->iobase + DT2821_DACSR); + supcsr = inw(dev->iobase + DT2821_SUPCSR); + if (supcsr & DT2821_DMAD) { + if (devpriv->dma_dir == DMA_MODE_READ) + dt282x_ai_dma_interrupt(dev); + else + dt282x_ao_dma_interrupt(dev); + handled = 1; + } + if (adcsr & DT2821_ADERR) { + if (devpriv->nread != 0) { + comedi_error(dev, "A/D error"); + dt282x_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_ERROR; + } + handled = 1; + } + if (dacsr & DT2821_DAERR) { +#if 0 + static int warn = 5; + if (--warn <= 0) { + disable_irq(dev->irq); + printk("disabling irq\n"); + } +#endif + comedi_error(dev, "D/A error"); + dt282x_ao_cancel(dev, s_ao); + s->async->events |= COMEDI_CB_ERROR; + handled = 1; + } +#if 0 + if (adcsr & DT2821_ADDONE) { + int ret; + short data; + + data = (short) inw(dev->iobase + DT2821_ADDAT); + data &= (1 << boardtype.adbits) - 1; + if (devpriv->ad_2scomp) { + data ^= 1 << (boardtype.adbits - 1); + } + ret = comedi_buf_put(s->async, data); + if (ret == 0) { + s->async->events |= COMEDI_CB_OVERFLOW; + } + + devpriv->nread--; + if (!devpriv->nread) { + s->async->events |= COMEDI_CB_EOA; + } else { + if (supcsr & DT2821_SCDN) + update_supcsr(DT2821_STRIG); + } + handled = 1; + } +#endif + comedi_event(dev, s); + /* printk("adcsr=0x%02x dacsr-0x%02x supcsr=0x%02x\n", adcsr, dacsr, supcsr); */ + return IRQ_RETVAL(handled); +} + +static void dt282x_load_changain(struct comedi_device * dev, int n, + unsigned int *chanlist) +{ + unsigned int i; + unsigned int chan, range; + + outw(DT2821_LLE | (n - 1), dev->iobase + DT2821_CHANCSR); + for (i = 0; i < n; i++) { + chan = CR_CHAN(chanlist[i]); + range = CR_RANGE(chanlist[i]); + update_adcsr((range << 4) | (chan)); + } + outw(n - 1, dev->iobase + DT2821_CHANCSR); +} + +/* + * Performs a single A/D conversion. + * - Put channel/gain into channel-gain list + * - preload multiplexer + * - trigger conversion and wait for it to finish + */ +static int dt282x_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + + /* XXX should we really be enabling the ad clock here? */ + devpriv->adcsr = DT2821_ADCLK; + update_adcsr(0); + + dt282x_load_changain(dev, 1, &insn->chanspec); + + update_supcsr(DT2821_PRLD); + wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); + return -ETIME; + ); + + for (i = 0; i < insn->n; i++) { + update_supcsr(DT2821_STRIG); + wait_for(ad_done(), comedi_error(dev, "timeout\n"); + return -ETIME; + ); + + data[i] = + inw(dev->iobase + + DT2821_ADDAT) & ((1 << boardtype.adbits) - 1); + if (devpriv->ad_2scomp) + data[i] ^= (1 << (boardtype.adbits - 1)); + } + + return i; +} + +static int dt282x_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + 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_FOLLOW | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + if (cmd->scan_begin_src == TRIG_FOLLOW) { + /* internal trigger */ + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + } else { + /* external trigger */ + /* should be level/edge, hi/lo specification here */ + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + } + if (cmd->convert_arg < 4000) { + /* XXX board dependent */ + cmd->convert_arg = 4000; + err++; + } +#define SLOWEST_TIMER (250*(1<<15)*255) + if (cmd->convert_arg > SLOWEST_TIMER) { + cmd->convert_arg = SLOWEST_TIMER; + err++; + } + if (cmd->convert_arg < this_board->ai_speed) { + cmd->convert_arg = this_board->ai_speed; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + /* any count is allowed */ + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + tmp = cmd->convert_arg; + dt282x_ns_to_timer(&cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + + if (err) + return 4; + + return 0; +} + +static int dt282x_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + int timer; + + if (devpriv->usedma == 0) { + comedi_error(dev, + "driver requires 2 dma channels to execute command"); + return -EIO; + } + + dt282x_disable_dma(dev); + + if (cmd->convert_arg < this_board->ai_speed) + cmd->convert_arg = this_board->ai_speed; + timer = dt282x_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_NEAREST); + outw(timer, dev->iobase + DT2821_TMRCTR); + + if (cmd->scan_begin_src == TRIG_FOLLOW) { + /* internal trigger */ + devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0; + } else { + /* external trigger */ + devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0 | DT2821_DS1; + } + update_supcsr(DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_ADCINIT); + + devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg; + devpriv->nread = devpriv->ntrig; + + devpriv->dma_dir = DMA_MODE_READ; + devpriv->current_dma_index = 0; + prep_ai_dma(dev, 0, 0); + if (devpriv->ntrig) { + prep_ai_dma(dev, 1, 0); + devpriv->supcsr |= DT2821_DDMA; + update_supcsr(0); + } + + devpriv->adcsr = 0; + + dt282x_load_changain(dev, cmd->chanlist_len, cmd->chanlist); + + devpriv->adcsr = DT2821_ADCLK | DT2821_IADDONE; + update_adcsr(0); + + update_supcsr(DT2821_PRLD); + wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); + return -ETIME; + ); + + if (cmd->scan_begin_src == TRIG_FOLLOW) { + update_supcsr(DT2821_STRIG); + } else { + devpriv->supcsr |= DT2821_XTRIG; + update_supcsr(0); + } + + return 0; +} + +static void dt282x_disable_dma(struct comedi_device * dev) +{ + if (devpriv->usedma) { + disable_dma(devpriv->dma[0].chan); + disable_dma(devpriv->dma[1].chan); + } +} + +static int dt282x_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + dt282x_disable_dma(dev); + + devpriv->adcsr = 0; + update_adcsr(0); + + devpriv->supcsr = 0; + update_supcsr(DT2821_ADCINIT); + + return 0; +} + +static int dt282x_ns_to_timer(int *nanosec, int round_mode) +{ + int prescale, base, divider; + + for (prescale = 0; prescale < 16; prescale++) { + if (prescale == 1) + continue; + base = 250 * (1 << prescale); + switch (round_mode) { + case TRIG_ROUND_NEAREST: + default: + divider = (*nanosec + base / 2) / base; + break; + case TRIG_ROUND_DOWN: + divider = (*nanosec) / base; + break; + case TRIG_ROUND_UP: + divider = (*nanosec + base - 1) / base; + break; + } + if (divider < 256) { + *nanosec = divider * base; + return (prescale << 8) | (255 - divider); + } + } + base = 250 * (1 << 15); + divider = 255; + *nanosec = divider * base; + return (15 << 8) | (255 - divider); +} + +/* + * Analog output routine. Selects single channel conversion, + * selects correct channel, converts from 2's compliment to + * offset binary if necessary, loads the data into the DAC + * data register, and performs the conversion. + */ +static int dt282x_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->ao[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int dt282x_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + short d; + unsigned int chan; + + chan = CR_CHAN(insn->chanspec); + d = data[0]; + d &= (1 << boardtype.dabits) - 1; + devpriv->ao[chan] = d; + + devpriv->dacsr |= DT2821_SSEL; + + if (chan) { + /* select channel */ + devpriv->dacsr |= DT2821_YSEL; + if (devpriv->da0_2scomp) + d ^= (1 << (boardtype.dabits - 1)); + } else { + devpriv->dacsr &= ~DT2821_YSEL; + if (devpriv->da1_2scomp) + d ^= (1 << (boardtype.dabits - 1)); + } + + update_dacsr(0); + + outw(d, dev->iobase + DT2821_DADAT); + + update_supcsr(DT2821_DACON); + + return 1; +} + +static int dt282x_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + if (cmd->scan_begin_arg < 5000 /* XXX unknown */ ) { + cmd->scan_begin_arg = 5000; + err++; + } + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + if (cmd->scan_end_arg > 2) { + /* XXX chanlist stuff? */ + cmd->scan_end_arg = 2; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + /* any count is allowed */ + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + tmp = cmd->scan_begin_arg; + dt282x_ns_to_timer(&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + + if (err) + return 4; + + return 0; + +} + +static int dt282x_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int x) +{ + int size; + + if (x != 0) + return -EINVAL; + + size = cfc_read_array_from_buffer(s, devpriv->dma[0].buf, + devpriv->dma_maxsize); + if (size == 0) { + rt_printk("dt282x: AO underrun\n"); + return -EPIPE; + } + prep_ao_dma(dev, 0, size); + + size = cfc_read_array_from_buffer(s, devpriv->dma[1].buf, + devpriv->dma_maxsize); + if (size == 0) { + rt_printk("dt282x: AO underrun\n"); + return -EPIPE; + } + prep_ao_dma(dev, 1, size); + + update_supcsr(DT2821_STRIG); + s->async->inttrig = NULL; + + return 1; +} + +static int dt282x_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int timer; + struct comedi_cmd *cmd = &s->async->cmd; + + if (devpriv->usedma == 0) { + comedi_error(dev, + "driver requires 2 dma channels to execute command"); + return -EIO; + } + + dt282x_disable_dma(dev); + + devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS1 | DT2821_DDMA; + update_supcsr(DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_DACINIT); + + devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len; + devpriv->nread = devpriv->ntrig; + + devpriv->dma_dir = DMA_MODE_WRITE; + devpriv->current_dma_index = 0; + + timer = dt282x_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_NEAREST); + outw(timer, dev->iobase + DT2821_TMRCTR); + + devpriv->dacsr = DT2821_SSEL | DT2821_DACLK | DT2821_IDARDY; + update_dacsr(0); + + s->async->inttrig = dt282x_ao_inttrig; + + return 0; +} + +static int dt282x_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + dt282x_disable_dma(dev); + + devpriv->dacsr = 0; + update_dacsr(0); + + devpriv->supcsr = 0; + update_supcsr(DT2821_DACINIT); + + return 0; +} + +static int dt282x_dio_insn_bits(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]); + + outw(s->state, dev->iobase + DT2821_DIODAT); + } + data[1] = inw(dev->iobase + DT2821_DIODAT); + + return 2; +} + +static int dt282x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int mask; + + mask = (CR_CHAN(insn->chanspec) < 8) ? 0x00ff : 0xff00; + if (data[0]) + s->io_bits |= mask; + else + s->io_bits &= ~mask; + + if (s->io_bits & 0x00ff) + devpriv->dacsr |= DT2821_LBOE; + else + devpriv->dacsr &= ~DT2821_LBOE; + if (s->io_bits & 0xff00) + devpriv->dacsr |= DT2821_HBOE; + else + devpriv->dacsr &= ~DT2821_HBOE; + + outw(devpriv->dacsr, dev->iobase + DT2821_DACSR); + + return 1; +} + +static const struct comedi_lrange *const ai_range_table[] = { + &range_dt282x_ai_lo_bipolar, + &range_dt282x_ai_lo_unipolar, + &range_dt282x_ai_5_bipolar, + &range_dt282x_ai_5_unipolar +}; +static const struct comedi_lrange *const ai_range_pgl_table[] = { + &range_dt282x_ai_hi_bipolar, + &range_dt282x_ai_hi_unipolar +}; +static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x) +{ + if (ispgl) { + if (x < 0 || x >= 2) + x = 0; + return ai_range_pgl_table[x]; + } else { + if (x < 0 || x >= 4) + x = 0; + return ai_range_table[x]; + } +} +static const struct comedi_lrange *const ao_range_table[] = { + &range_bipolar10, + &range_unipolar10, + &range_bipolar5, + &range_unipolar5, + &range_bipolar2_5 +}; +static const struct comedi_lrange *opt_ao_range_lkup(int x) +{ + if (x < 0 || x >= 5) + x = 0; + return ao_range_table[x]; +} + +enum { opt_iobase = 0, opt_irq, opt_dma1, opt_dma2, /* i/o base, irq, dma channels */ + opt_diff, /* differential */ + opt_ai_twos, opt_ao0_twos, opt_ao1_twos, /* twos comp */ + opt_ai_range, opt_ao0_range, opt_ao1_range, /* range */ +}; + +/* + options: + 0 i/o base + 1 irq + 2 dma1 + 3 dma2 + 4 0=single ended, 1=differential + 5 ai 0=straight binary, 1=2's comp + 6 ao0 0=straight binary, 1=2's comp + 7 ao1 0=straight binary, 1=2's comp + 8 ai 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V + 9 ao0 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V + 10 ao1 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V + */ +static int dt282x_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int i, irq; + int ret; + struct comedi_subdevice *s; + unsigned long iobase; + + dev->board_name = this_board->name; + + iobase = it->options[opt_iobase]; + if (!iobase) + iobase = 0x240; + + printk("comedi%d: dt282x: 0x%04lx", dev->minor, iobase); + if (!request_region(iobase, DT2821_SIZE, "dt282x")) { + printk(" I/O port conflict\n"); + return -EBUSY; + } + dev->iobase = iobase; + + outw(DT2821_BDINIT, dev->iobase + DT2821_SUPCSR); + i = inw(dev->iobase + DT2821_ADCSR); +#ifdef DEBUG + printk(" fingerprint=%x,%x,%x,%x,%x", + inw(dev->iobase + DT2821_ADCSR), + inw(dev->iobase + DT2821_CHANCSR), + inw(dev->iobase + DT2821_DACSR), + inw(dev->iobase + DT2821_SUPCSR), + inw(dev->iobase + DT2821_TMRCTR)); +#endif + + if (((inw(dev->iobase + DT2821_ADCSR) & DT2821_ADCSR_MASK) + != DT2821_ADCSR_VAL) || + ((inw(dev->iobase + DT2821_CHANCSR) & DT2821_CHANCSR_MASK) + != DT2821_CHANCSR_VAL) || + ((inw(dev->iobase + DT2821_DACSR) & DT2821_DACSR_MASK) + != DT2821_DACSR_VAL) || + ((inw(dev->iobase + DT2821_SUPCSR) & DT2821_SUPCSR_MASK) + != DT2821_SUPCSR_VAL) || + ((inw(dev->iobase + DT2821_TMRCTR) & DT2821_TMRCTR_MASK) + != DT2821_TMRCTR_VAL)) { + printk(" board not found"); + return -EIO; + } + /* should do board test */ + + irq = it->options[opt_irq]; +#if 0 + if (irq < 0) { + unsigned long flags; + int irqs; + + save_flags(flags); + sti(); + irqs = probe_irq_on(); + + /* trigger interrupt */ + + comedi_udelay(100); + + irq = probe_irq_off(irqs); + restore_flags(flags); + if (0 /* error */ ) { + printk(" error probing irq (bad)"); + } + } +#endif + if (irq > 0) { + printk(" ( irq = %d )", irq); + ret = comedi_request_irq(irq, dt282x_interrupt, 0, "dt282x", + dev); + if (ret < 0) { + printk(" failed to get irq\n"); + return -EIO; + } + dev->irq = irq; + } else if (irq == 0) { + printk(" (no irq)"); + } else { +#if 0 + printk(" (probe returned multiple irqs--bad)"); +#else + printk(" (irq probe not implemented)"); +#endif + } + + if ((ret = alloc_private(dev, sizeof(struct dt282x_private))) < 0) + return ret; + + ret = dt282x_grab_dma(dev, it->options[opt_dma1], + it->options[opt_dma2]); + if (ret < 0) + return ret; + + if ((ret = alloc_subdevices(dev, 3)) < 0) + return ret; + + s = dev->subdevices + 0; + + dev->read_subdev = s; + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ | + ((it->options[opt_diff]) ? SDF_DIFF : SDF_COMMON); + s->n_chan = + (it->options[opt_diff]) ? boardtype.adchan_di : boardtype. + adchan_se; + s->insn_read = dt282x_ai_insn_read; + s->do_cmdtest = dt282x_ai_cmdtest; + s->do_cmd = dt282x_ai_cmd; + s->cancel = dt282x_ai_cancel; + s->maxdata = (1 << boardtype.adbits) - 1; + s->len_chanlist = 16; + s->range_table = + opt_ai_range_lkup(boardtype.ispgl, it->options[opt_ai_range]); + devpriv->ad_2scomp = it->options[opt_ai_twos]; + + s++; + if ((s->n_chan = boardtype.dachan)) { + /* ao subsystem */ + s->type = COMEDI_SUBD_AO; + dev->write_subdev = s; + s->subdev_flags = SDF_WRITABLE | SDF_CMD_WRITE; + s->insn_read = dt282x_ao_insn_read; + s->insn_write = dt282x_ao_insn_write; + s->do_cmdtest = dt282x_ao_cmdtest; + s->do_cmd = dt282x_ao_cmd; + s->cancel = dt282x_ao_cancel; + s->maxdata = (1 << boardtype.dabits) - 1; + s->len_chanlist = 2; + s->range_table_list = devpriv->darangelist; + devpriv->darangelist[0] = + opt_ao_range_lkup(it->options[opt_ao0_range]); + devpriv->darangelist[1] = + opt_ao_range_lkup(it->options[opt_ao1_range]); + devpriv->da0_2scomp = it->options[opt_ao0_twos]; + devpriv->da1_2scomp = it->options[opt_ao1_twos]; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s++; + /* dio subsystem */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 16; + s->insn_bits = dt282x_dio_insn_bits; + s->insn_config = dt282x_dio_insn_config; + s->maxdata = 1; + s->range_table = &range_digital; + + printk("\n"); + + return 0; +} + +static void free_resources(struct comedi_device * dev) +{ + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + if (dev->iobase) + release_region(dev->iobase, DT2821_SIZE); + if (dev->private) { + if (devpriv->dma[0].chan) + free_dma(devpriv->dma[0].chan); + if (devpriv->dma[1].chan) + free_dma(devpriv->dma[1].chan); + if (devpriv->dma[0].buf) + free_page((unsigned long)devpriv->dma[0].buf); + if (devpriv->dma[1].buf) + free_page((unsigned long)devpriv->dma[1].buf); + } +} + +static int dt282x_detach(struct comedi_device * dev) +{ + printk("comedi%d: dt282x: remove\n", dev->minor); + + free_resources(dev); + + return 0; +} + +static int dt282x_grab_dma(struct comedi_device * dev, int dma1, int dma2) +{ + int ret; + + devpriv->usedma = 0; + + if (!dma1 && !dma2) { + printk(" (no dma)"); + return 0; + } + + if (dma1 == dma2 || dma1 < 5 || dma2 < 5 || dma1 > 7 || dma2 > 7) + return -EINVAL; + + if (dma2 < dma1) { + int i; + i = dma1; + dma1 = dma2; + dma2 = i; + } + + ret = request_dma(dma1, "dt282x A"); + if (ret) + return -EBUSY; + devpriv->dma[0].chan = dma1; + + ret = request_dma(dma2, "dt282x B"); + if (ret) + return -EBUSY; + devpriv->dma[1].chan = dma2; + + devpriv->dma_maxsize = PAGE_SIZE; + devpriv->dma[0].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); + devpriv->dma[1].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); + if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) { + printk(" can't get DMA memory"); + return -ENOMEM; + } + + printk(" (dma=%d,%d)", dma1, dma2); + + devpriv->usedma = 1; + + return 0; +} diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c new file mode 100644 index 000000000000..d9467984706e --- /dev/null +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -0,0 +1,983 @@ +/* + comedi/drivers/dt3000.c + Data Translation DT3000 series driver + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999 David A. Schleef + + 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: dt3000 +Description: Data Translation DT3000 series +Author: ds +Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003, + DT3003-PGL, DT3004, DT3005, DT3004-200 +Updated: Mon, 14 Apr 2008 15:41:24 +0100 +Status: works + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. + +There is code to support AI commands, but it may not work. + +AO commands are not supported. +*/ + +/* + The DT3000 series is Data Translation's attempt to make a PCI + data acquisition board. The design of this series is very nice, + since each board has an on-board DSP (Texas Instruments TMS320C52). + However, a few details are a little annoying. The boards lack + bus-mastering DMA, which eliminates them from serious work. + They also are not capable of autocalibration, which is a common + feature in modern hardware. The default firmware is pretty bad, + making it nearly impossible to write an RT compatible driver. + It would make an interesting project to write a decent firmware + for these boards. + + Data Translation originally wanted an NDA for the documentation + for the 3k series. However, if you ask nicely, they might send + you the docs without one, also. +*/ + +#define DEBUG 1 + +#include "../comedidev.h" +#include + +#include "comedi_pci.h" + +#define PCI_VENDOR_ID_DT 0x1116 + +static const struct comedi_lrange range_dt3000_ai = { 4, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2.5, 2.5), + RANGE(-1.25, 1.25) + } +}; +static const struct comedi_lrange range_dt3000_ai_pgl = { 4, { + RANGE(-10, 10), + RANGE(-1, 1), + RANGE(-0.1, 0.1), + RANGE(-0.02, 0.02) + } +}; + +struct dt3k_boardtype { + + const char *name; + unsigned int device_id; + int adchan; + int adbits; + int ai_speed; + const struct comedi_lrange *adrange; + int dachan; + int dabits; +}; + + +static const struct dt3k_boardtype dt3k_boardtypes[] = { + {name:"dt3001", + device_id:0x22, + adchan: 16, + adbits: 12, + adrange: &range_dt3000_ai, + ai_speed:3000, + dachan: 2, + dabits: 12, + }, + {name:"dt3001-pgl", + device_id:0x27, + adchan: 16, + adbits: 12, + adrange: &range_dt3000_ai_pgl, + ai_speed:3000, + dachan: 2, + dabits: 12, + }, + {name:"dt3002", + device_id:0x23, + adchan: 32, + adbits: 12, + adrange: &range_dt3000_ai, + ai_speed:3000, + dachan: 0, + dabits: 0, + }, + {name:"dt3003", + device_id:0x24, + adchan: 64, + adbits: 12, + adrange: &range_dt3000_ai, + ai_speed:3000, + dachan: 2, + dabits: 12, + }, + {name:"dt3003-pgl", + device_id:0x28, + adchan: 64, + adbits: 12, + adrange: &range_dt3000_ai_pgl, + ai_speed:3000, + dachan: 2, + dabits: 12, + }, + {name:"dt3004", + device_id:0x25, + adchan: 16, + adbits: 16, + adrange: &range_dt3000_ai, + ai_speed:10000, + dachan: 2, + dabits: 12, + }, + {name:"dt3005", /* a.k.a. 3004-200 */ + device_id:0x26, + adchan: 16, + adbits: 16, + adrange: &range_dt3000_ai, + ai_speed:5000, + dachan: 2, + dabits: 12, + }, +}; + +#define n_dt3k_boards sizeof(dt3k_boardtypes)/sizeof(struct dt3k_boardtype) +#define this_board ((const struct dt3k_boardtype *)dev->board_ptr) + +static DEFINE_PCI_DEVICE_TABLE(dt3k_pci_table) = { + {PCI_VENDOR_ID_DT, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_DT, 0x0027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_DT, 0x0023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_DT, 0x0024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_DT, 0x0028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_DT, 0x0025, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_DT, 0x0026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, dt3k_pci_table); + +#define DT3000_SIZE (4*0x1000) + +/* dual-ported RAM location definitions */ + +#define DPR_DAC_buffer (4*0x000) +#define DPR_ADC_buffer (4*0x800) +#define DPR_Command (4*0xfd3) +#define DPR_SubSys (4*0xfd3) +#define DPR_Encode (4*0xfd4) +#define DPR_Params(a) (4*(0xfd5+(a))) +#define DPR_Tick_Reg_Lo (4*0xff5) +#define DPR_Tick_Reg_Hi (4*0xff6) +#define DPR_DA_Buf_Front (4*0xff7) +#define DPR_DA_Buf_Rear (4*0xff8) +#define DPR_AD_Buf_Front (4*0xff9) +#define DPR_AD_Buf_Rear (4*0xffa) +#define DPR_Int_Mask (4*0xffb) +#define DPR_Intr_Flag (4*0xffc) +#define DPR_Response_Mbx (4*0xffe) +#define DPR_Command_Mbx (4*0xfff) + +#define AI_FIFO_DEPTH 2003 +#define AO_FIFO_DEPTH 2048 + +/* command list */ + +#define CMD_GETBRDINFO 0 +#define CMD_CONFIG 1 +#define CMD_GETCONFIG 2 +#define CMD_START 3 +#define CMD_STOP 4 +#define CMD_READSINGLE 5 +#define CMD_WRITESINGLE 6 +#define CMD_CALCCLOCK 7 +#define CMD_READEVENTS 8 +#define CMD_WRITECTCTRL 16 +#define CMD_READCTCTRL 17 +#define CMD_WRITECT 18 +#define CMD_READCT 19 +#define CMD_WRITEDATA 32 +#define CMD_READDATA 33 +#define CMD_WRITEIO 34 +#define CMD_READIO 35 +#define CMD_WRITECODE 36 +#define CMD_READCODE 37 +#define CMD_EXECUTE 38 +#define CMD_HALT 48 + +#define SUBS_AI 0 +#define SUBS_AO 1 +#define SUBS_DIN 2 +#define SUBS_DOUT 3 +#define SUBS_MEM 4 +#define SUBS_CT 5 + +/* interrupt flags */ +#define DT3000_CMDONE 0x80 +#define DT3000_CTDONE 0x40 +#define DT3000_DAHWERR 0x20 +#define DT3000_DASWERR 0x10 +#define DT3000_DAEMPTY 0x08 +#define DT3000_ADHWERR 0x04 +#define DT3000_ADSWERR 0x02 +#define DT3000_ADFULL 0x01 + +#define DT3000_COMPLETION_MASK 0xff00 +#define DT3000_COMMAND_MASK 0x00ff +#define DT3000_NOTPROCESSED 0x0000 +#define DT3000_NOERROR 0x5500 +#define DT3000_ERROR 0xaa00 +#define DT3000_NOTSUPPORTED 0xff00 + +#define DT3000_EXTERNAL_CLOCK 1 +#define DT3000_RISING_EDGE 2 + +#define TMODE_MASK 0x1c + +#define DT3000_AD_TRIG_INTERNAL (0<<2) +#define DT3000_AD_TRIG_EXTERNAL (1<<2) +#define DT3000_AD_RETRIG_INTERNAL (2<<2) +#define DT3000_AD_RETRIG_EXTERNAL (3<<2) +#define DT3000_AD_EXTRETRIG (4<<2) + +#define DT3000_CHANNEL_MODE_SE 0 +#define DT3000_CHANNEL_MODE_DI 1 + +struct dt3k_private { + + struct pci_dev *pci_dev; + resource_size_t phys_addr; + void *io_addr; + unsigned int lock; + unsigned int ao_readback[2]; + unsigned int ai_front; + unsigned int ai_rear; +}; + +#define devpriv ((struct dt3k_private *)dev->private) + +static int dt3000_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dt3000_detach(struct comedi_device * dev); +static struct comedi_driver driver_dt3000 = { + driver_name:"dt3000", + module:THIS_MODULE, + attach:dt3000_attach, + detach:dt3000_detach, +}; + +COMEDI_PCI_INITCLEANUP(driver_dt3000, dt3k_pci_table); + +static void dt3k_ai_empty_fifo(struct comedi_device * dev, struct comedi_subdevice * s); +static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg, + unsigned int round_mode); +static int dt3k_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +#ifdef DEBUG +static void debug_intr_flags(unsigned int flags); +#endif + +#define TIMEOUT 100 + +static int dt3k_send_cmd(struct comedi_device * dev, unsigned int cmd) +{ + int i; + unsigned int status = 0; + + writew(cmd, devpriv->io_addr + DPR_Command_Mbx); + + for (i = 0; i < TIMEOUT; i++) { + status = readw(devpriv->io_addr + DPR_Command_Mbx); + if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED) + break; + comedi_udelay(1); + } + if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR) { + return 0; + } + + printk("dt3k_send_cmd() timeout/error status=0x%04x\n", status); + + return -ETIME; +} + +static unsigned int dt3k_readsingle(struct comedi_device * dev, unsigned int subsys, + unsigned int chan, unsigned int gain) +{ + writew(subsys, devpriv->io_addr + DPR_SubSys); + + writew(chan, devpriv->io_addr + DPR_Params(0)); + writew(gain, devpriv->io_addr + DPR_Params(1)); + + dt3k_send_cmd(dev, CMD_READSINGLE); + + return readw(devpriv->io_addr + DPR_Params(2)); +} + +static void dt3k_writesingle(struct comedi_device * dev, unsigned int subsys, + unsigned int chan, unsigned int data) +{ + writew(subsys, devpriv->io_addr + DPR_SubSys); + + writew(chan, devpriv->io_addr + DPR_Params(0)); + writew(0, devpriv->io_addr + DPR_Params(1)); + writew(data, devpriv->io_addr + DPR_Params(2)); + + dt3k_send_cmd(dev, CMD_WRITESINGLE); +} + +static int debug_n_ints = 0; + +// FIXME! Assumes shared interrupt is for this card. +// What's this debug_n_ints stuff? Obviously needs some work... +static irqreturn_t dt3k_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s; + unsigned int status; + + if (!dev->attached) { + return IRQ_NONE; + } + + s = dev->subdevices + 0; + status = readw(devpriv->io_addr + DPR_Intr_Flag); +#ifdef DEBUG + debug_intr_flags(status); +#endif + + if (status & DT3000_ADFULL) { + dt3k_ai_empty_fifo(dev, s); + s->async->events |= COMEDI_CB_BLOCK; + } + + if (status & (DT3000_ADSWERR | DT3000_ADHWERR)) { + s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + } + + debug_n_ints++; + if (debug_n_ints >= 10) { + dt3k_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + } + + comedi_event(dev, s); + return IRQ_HANDLED; +} + +#ifdef DEBUG +static char *intr_flags[] = { + "AdFull", "AdSwError", "AdHwError", "DaEmpty", + "DaSwError", "DaHwError", "CtDone", "CmDone", +}; +static void debug_intr_flags(unsigned int flags) +{ + int i; + printk("dt3k: intr_flags:"); + for (i = 0; i < 8; i++) { + if (flags & (1 << i)) { + printk(" %s", intr_flags[i]); + } + } + printk("\n"); +} +#endif + +static void dt3k_ai_empty_fifo(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int front; + int rear; + int count; + int i; + short data; + + front = readw(devpriv->io_addr + DPR_AD_Buf_Front); + count = front - devpriv->ai_front; + if (count < 0) + count += AI_FIFO_DEPTH; + + printk("reading %d samples\n", count); + + rear = devpriv->ai_rear; + + for (i = 0; i < count; i++) { + data = readw(devpriv->io_addr + DPR_ADC_buffer + rear); + comedi_buf_put(s->async, data); + rear++; + if (rear >= AI_FIFO_DEPTH) + rear = 0; + } + + devpriv->ai_rear = rear; + writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear); +} + +static int dt3k_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + 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_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + 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_COUNT; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < this_board->ai_speed) { + cmd->scan_begin_arg = this_board->ai_speed; + err++; + } + if (cmd->scan_begin_arg > 100 * 16 * 65535) { + cmd->scan_begin_arg = 100 * 16 * 65535; + err++; + } + } else { + /* not supported */ + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < this_board->ai_speed) { + cmd->convert_arg = this_board->ai_speed; + err++; + } + if (cmd->convert_arg > 50 * 16 * 65535) { + cmd->convert_arg = 50 * 16 * 65535; + err++; + } + } else { + /* not supported */ + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_arg > 0x00ffffff) { + cmd->stop_arg = 0x00ffffff; + err++; + } + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + dt3k_ns_to_timer(100, &cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } else { + /* not supported */ + } + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + dt3k_ns_to_timer(50, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + if (cmd->scan_begin_src == TRIG_TIMER && + cmd->scan_begin_arg < + cmd->convert_arg * cmd->scan_end_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->scan_end_arg; + err++; + } + } else { + /* not supported */ + } + + if (err) + return 4; + + return 0; +} + +static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec, + unsigned int round_mode) +{ + int divider, base, prescale; + + /* This function needs improvment */ + /* Don't know if divider==0 works. */ + + for (prescale = 0; prescale < 16; prescale++) { + base = timer_base * (prescale + 1); + switch (round_mode) { + case TRIG_ROUND_NEAREST: + default: + divider = (*nanosec + base / 2) / base; + break; + case TRIG_ROUND_DOWN: + divider = (*nanosec) / base; + break; + case TRIG_ROUND_UP: + divider = (*nanosec) / base; + break; + } + if (divider < 65536) { + *nanosec = divider * base; + return (prescale << 16) | (divider); + } + } + + prescale = 15; + base = timer_base * (1 << prescale); + divider = 65535; + *nanosec = divider * base; + return (prescale << 16) | (divider); +} + +static int dt3k_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + int i; + unsigned int chan, range, aref; + unsigned int divider; + unsigned int tscandiv; + int ret; + unsigned int mode; + + printk("dt3k_ai_cmd:\n"); + for (i = 0; i < cmd->chanlist_len; i++) { + chan = CR_CHAN(cmd->chanlist[i]); + range = CR_RANGE(cmd->chanlist[i]); + + writew((range << 6) | chan, + devpriv->io_addr + DPR_ADC_buffer + i); + } + aref = CR_AREF(cmd->chanlist[0]); + + writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0)); + printk("param[0]=0x%04x\n", cmd->scan_end_arg); + + if (cmd->convert_src == TRIG_TIMER) { + divider = dt3k_ns_to_timer(50, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + writew((divider >> 16), devpriv->io_addr + DPR_Params(1)); + printk("param[1]=0x%04x\n", divider >> 16); + writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2)); + printk("param[2]=0x%04x\n", divider & 0xffff); + } else { + /* not supported */ + } + + if (cmd->scan_begin_src == TRIG_TIMER) { + tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3)); + printk("param[3]=0x%04x\n", tscandiv >> 16); + writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4)); + printk("param[4]=0x%04x\n", tscandiv & 0xffff); + } else { + /* not supported */ + } + + mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0; + writew(mode, devpriv->io_addr + DPR_Params(5)); + printk("param[5]=0x%04x\n", mode); + writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6)); + printk("param[6]=0x%04x\n", aref == AREF_DIFF); + + writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7)); + printk("param[7]=0x%04x\n", AI_FIFO_DEPTH / 2); + + writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); + ret = dt3k_send_cmd(dev, CMD_CONFIG); + + writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR, + devpriv->io_addr + DPR_Int_Mask); + + debug_n_ints = 0; + + writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); + ret = dt3k_send_cmd(dev, CMD_START); + + return 0; +} + +static int dt3k_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int ret; + + writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); + ret = dt3k_send_cmd(dev, CMD_STOP); + + writew(0, devpriv->io_addr + DPR_Int_Mask); + + return 0; +} + +static int dt3k_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + unsigned int chan, gain, aref; + + chan = CR_CHAN(insn->chanspec); + gain = CR_RANGE(insn->chanspec); + /* XXX docs don't explain how to select aref */ + aref = CR_AREF(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain); + } + + return i; +} + +static int dt3k_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + unsigned int chan; + + chan = CR_CHAN(insn->chanspec); + for (i = 0; i < insn->n; i++) { + dt3k_writesingle(dev, SUBS_AO, chan, data[i]); + devpriv->ao_readback[chan] = data[i]; + } + + return i; +} + +static int dt3k_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + unsigned int chan; + + chan = CR_CHAN(insn->chanspec); + for (i = 0; i < insn->n; i++) { + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +static void dt3k_dio_config(struct comedi_device * dev, int bits) +{ + /* XXX */ + writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys); + + writew(bits, devpriv->io_addr + DPR_Params(0)); +#if 0 + /* don't know */ + writew(0, devpriv->io_addr + DPR_Params(1)); + writew(0, devpriv->io_addr + DPR_Params(2)); +#endif + + dt3k_send_cmd(dev, CMD_CONFIG); +} + +static int dt3k_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int mask; + + mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0; + + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= mask; + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~mask; + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s->io_bits & (1 << CR_CHAN(insn-> + chanspec))) ? COMEDI_OUTPUT : + COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + break; + } + mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3); + dt3k_dio_config(dev, mask); + + return insn->n; +} + +static int dt3k_dio_insn_bits(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[1] & data[0]; + dt3k_writesingle(dev, SUBS_DOUT, 0, s->state); + } + data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0); + + return 2; +} + +static int dt3k_mem_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int addr = CR_CHAN(insn->chanspec); + int i; + + for (i = 0; i < insn->n; i++) { + writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys); + writew(addr, devpriv->io_addr + DPR_Params(0)); + writew(1, devpriv->io_addr + DPR_Params(1)); + + dt3k_send_cmd(dev, CMD_READCODE); + + data[i] = readw(devpriv->io_addr + DPR_Params(2)); + } + + return i; +} + +static int dt_pci_probe(struct comedi_device * dev, int bus, int slot); + +static int dt3000_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int bus, slot; + int ret = 0; + + printk("dt3000:"); + bus = it->options[0]; + slot = it->options[1]; + + if ((ret = alloc_private(dev, sizeof(struct dt3k_private))) < 0) + return ret; + + ret = dt_pci_probe(dev, bus, slot); + if (ret < 0) + return ret; + if (ret == 0) { + printk(" no DT board found\n"); + return -ENODEV; + } + + dev->board_name = this_board->name; + + if (comedi_request_irq(devpriv->pci_dev->irq, dt3k_interrupt, + IRQF_SHARED, "dt3000", dev)) { + printk(" unable to allocate IRQ %u\n", devpriv->pci_dev->irq); + return -EINVAL; + } + dev->irq = devpriv->pci_dev->irq; + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + + s = dev->subdevices; + dev->read_subdev = s; + + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + s->n_chan = this_board->adchan; + s->insn_read = dt3k_ai_insn; + s->maxdata = (1 << this_board->adbits) - 1; + s->len_chanlist = 512; + s->range_table = &range_dt3000_ai; /* XXX */ + s->do_cmd = dt3k_ai_cmd; + s->do_cmdtest = dt3k_ai_cmdtest; + s->cancel = dt3k_ai_cancel; + + s++; + /* ao subsystem */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->insn_read = dt3k_ao_insn_read; + s->insn_write = dt3k_ao_insn; + s->maxdata = (1 << this_board->dabits) - 1; + s->len_chanlist = 1; + s->range_table = &range_bipolar10; + + s++; + /* dio subsystem */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->insn_config = dt3k_dio_insn_config; + s->insn_bits = dt3k_dio_insn_bits; + s->maxdata = 1; + s->len_chanlist = 8; + s->range_table = &range_digital; + + s++; + /* mem subsystem */ + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE; + s->n_chan = 0x1000; + s->insn_read = dt3k_mem_insn_read; + s->maxdata = 0xff; + s->len_chanlist = 1; + s->range_table = &range_unknown; + +#if 0 + s++; + /* proc subsystem */ + s->type = COMEDI_SUBD_PROC; +#endif + + return 0; +} + +static int dt3000_detach(struct comedi_device * dev) +{ + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + if (devpriv) { + if (devpriv->pci_dev) { + if (devpriv->phys_addr) { + comedi_pci_disable(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + if (devpriv->io_addr) + iounmap(devpriv->io_addr); + } + /* XXX */ + + return 0; +} + +static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board); +static int setup_pci(struct comedi_device * dev); + +static int dt_pci_probe(struct comedi_device * dev, int bus, int slot) +{ + int board; + int ret; + struct pci_dev *pcidev; + + pcidev = NULL; + while ((pcidev = dt_pci_find_device(pcidev, &board)) != NULL) { + if ((bus == 0 && slot == 0) || + (pcidev->bus->number == bus && + PCI_SLOT(pcidev->devfn) == slot)) { + break; + } + } + devpriv->pci_dev = pcidev; + + if (board >= 0) + dev->board_ptr = dt3k_boardtypes + board; + + if (!devpriv->pci_dev) + return 0; + + if ((ret = setup_pci(dev)) < 0) + return ret; + + return 1; +} + +static int setup_pci(struct comedi_device * dev) +{ + resource_size_t addr; + int ret; + + ret = comedi_pci_enable(devpriv->pci_dev, "dt3000"); + if (ret < 0) + return ret; + + addr = pci_resource_start(devpriv->pci_dev, 0); + devpriv->phys_addr = addr; + devpriv->io_addr = ioremap(devpriv->phys_addr, DT3000_SIZE); + if (!devpriv->io_addr) + return -ENOMEM; +#if DEBUG + printk("0x%08llx mapped to %p, ", + (unsigned long long)devpriv->phys_addr, devpriv->io_addr); +#endif + + return 0; +} + +static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board) +{ + int i; + + for (from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from); + from != NULL; + from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from)) { + for (i = 0; i < n_dt3k_boards; i++) { + if (from->device == dt3k_boardtypes[i].device_id) { + *board = i; + return from; + } + } + printk("unknown Data Translation PCI device found with device_id=0x%04x\n", from->device); + } + *board = -1; + return from; +} diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index f2d2173d7219..cc4c04630086 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -300,22 +300,22 @@ struct slot_dt9812 { struct comedi_dt9812 *comedi; }; -static const comedi_lrange dt9812_10_ain_range = { 1, { +static const struct comedi_lrange dt9812_10_ain_range = { 1, { BIP_RANGE(10), } }; -static const comedi_lrange dt9812_2pt5_ain_range = { 1, { +static const struct comedi_lrange dt9812_2pt5_ain_range = { 1, { UNI_RANGE(2.5), } }; -static const comedi_lrange dt9812_10_aout_range = { 1, { +static const struct comedi_lrange dt9812_10_aout_range = { 1, { BIP_RANGE(10), } }; -static const comedi_lrange dt9812_2pt5_aout_range = { 1, { +static const struct comedi_lrange dt9812_2pt5_aout_range = { 1, { UNI_RANGE(2.5), } }; @@ -892,12 +892,12 @@ static struct usb_driver dt9812_usb_driver = { * Comedi functions */ -static void dt9812_comedi_open(comedi_device *dev) +static void dt9812_comedi_open(struct comedi_device *dev) { down(&devpriv->slot->mutex); if (devpriv->slot->usb) { /* We have an attached device, fill in current range info */ - comedi_subdevice *s; + struct comedi_subdevice *s; s = &dev->subdevices[0]; s->n_chan = 8; @@ -940,8 +940,8 @@ static void dt9812_comedi_open(comedi_device *dev) up(&devpriv->slot->mutex); } -static int dt9812_di_rinsn(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int dt9812_di_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; u8 bits = 0; @@ -952,8 +952,8 @@ static int dt9812_di_rinsn(comedi_device *dev, comedi_subdevice *s, return n; } -static int dt9812_do_winsn(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int dt9812_do_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; u8 bits = 0; @@ -970,8 +970,8 @@ static int dt9812_do_winsn(comedi_device *dev, comedi_subdevice *s, return n; } -static int dt9812_ai_rinsn(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int dt9812_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; @@ -985,8 +985,8 @@ static int dt9812_ai_rinsn(comedi_device *dev, comedi_subdevice *s, return n; } -static int dt9812_ao_rinsn(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int dt9812_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; u16 value; @@ -999,8 +999,8 @@ static int dt9812_ao_rinsn(comedi_device *dev, comedi_subdevice *s, return n; } -static int dt9812_ao_winsn(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int dt9812_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; @@ -1009,10 +1009,10 @@ static int dt9812_ao_winsn(comedi_device *dev, comedi_subdevice *s, return n; } -static int dt9812_attach(comedi_device *dev, comedi_devconfig *it) +static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int i; - comedi_subdevice *s; + struct comedi_subdevice *s; dev->board_name = "dt9812"; @@ -1103,12 +1103,12 @@ static int dt9812_attach(comedi_device *dev, comedi_devconfig *it) return 0; } -static int dt9812_detach(comedi_device *dev) +static int dt9812_detach(struct comedi_device *dev) { return 0; } -static comedi_driver dt9812_comedi_driver = { +static struct comedi_driver dt9812_comedi_driver = { .module = THIS_MODULE, .driver_name = "dt9812", .attach = dt9812_attach, diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c new file mode 100644 index 000000000000..6d7bb37d2b1c --- /dev/null +++ b/drivers/staging/comedi/drivers/fl512.c @@ -0,0 +1,186 @@ +/* + comedi/drivers/fl512.c + Anders Gnistrup +*/ + +/* +Driver: fl512 +Description: unknown +Author: Anders Gnistrup +Devices: [unknown] FL512 (fl512) +Status: unknown + +Digital I/O is not supported. + +Configuration options: + [0] - I/O port base address +*/ + +#define DEBUG 0 + +#include "../comedidev.h" + +#include +#include + +#define FL512_SIZE 16 /* the size of the used memory */ +struct fl512_private { + + short ao_readback[2]; +}; + +#define devpriv ((struct fl512_private *) dev->private) + +static const struct comedi_lrange range_fl512 = { 4, { + BIP_RANGE(0.5), + BIP_RANGE(1), + BIP_RANGE(5), + BIP_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(5), + UNI_RANGE(10), + } +}; + +static int fl512_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int fl512_detach(struct comedi_device * dev); + +static struct comedi_driver driver_fl512 = { + driver_name:"fl512", + module:THIS_MODULE, + attach:fl512_attach, + detach:fl512_detach, +}; + +COMEDI_INITCLEANUP(driver_fl512); + +static int fl512_ai_insn(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); +static int fl512_ao_insn(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); +static int fl512_ao_insn_readback(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +/* + * fl512_ai_insn : this is the analog input function + */ +static int fl512_ai_insn(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int n; + unsigned int lo_byte, hi_byte; + char chan = CR_CHAN(insn->chanspec); + unsigned long iobase = dev->iobase; + + for (n = 0; n < insn->n; n++) { /* sample n times on selected channel */ + /* XXX probably can move next step out of for() loop -- will make + * AI a little bit faster. */ + outb(chan, iobase + 2); /* select chan */ + outb(0, iobase + 3); /* start conversion */ + /* XXX should test "done" flag instead of delay */ + comedi_udelay(30); /* sleep 30 usec */ + lo_byte = inb(iobase + 2); /* low 8 byte */ + hi_byte = inb(iobase + 3) & 0xf; /* high 4 bit and mask */ + data[n] = lo_byte + (hi_byte << 8); + } + return n; +} + +/* + * fl512_ao_insn : used to write to a DA port n times + */ +static int fl512_ao_insn(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan = CR_CHAN(insn->chanspec); /* get chan to write */ + unsigned long iobase = dev->iobase; /* get base address */ + + for (n = 0; n < insn->n; n++) { /* write n data set */ + outb(data[n] & 0x0ff, iobase + 4 + 2 * chan); /* write low byte */ + outb((data[n] & 0xf00) >> 8, iobase + 4 + 2 * chan); /* write high byte */ + inb(iobase + 4 + 2 * chan); /* trig */ + + devpriv->ao_readback[chan] = data[n]; + } + return n; +} + +/* + * fl512_ao_insn_readback : used to read previous values written to + * DA port + */ +static int fl512_ao_insn_readback(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { + data[n] = devpriv->ao_readback[chan]; + } + + return n; +} + +/* + * start attach + */ +static int fl512_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + unsigned long iobase; + struct comedi_subdevice *s; /* pointer to the subdevice: + Analog in, Analog out, ( not made ->and Digital IO) */ + + iobase = it->options[0]; + printk("comedi:%d fl512: 0x%04lx", dev->minor, iobase); + if (!request_region(iobase, FL512_SIZE, "fl512")) { + printk(" I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + dev->board_name = "fl512"; + if (alloc_private(dev, sizeof(struct fl512_private)) < 0) + return -ENOMEM; + +#if DEBUG + printk("malloc ok\n"); +#endif + + if (alloc_subdevices(dev, 2) < 0) + return -ENOMEM; + + /* + * this if the definitions of the supdevices, 2 have been defined + */ + /* Analog indput */ + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_AI; /* define subdevice as Analog In */ + s->subdev_flags = SDF_READABLE | SDF_GROUND; /* you can read it from userspace */ + s->n_chan = 16; /* Number of Analog input channels */ + s->maxdata = 0x0fff; /* accept only 12 bits of data */ + s->range_table = &range_fl512; /* device use one of the ranges */ + s->insn_read = fl512_ai_insn; /* function to call when read AD */ + printk("comedi: fl512: subdevice 0 initialized\n"); + + /* Analog output */ + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_AO; /* define subdevice as Analog OUT */ + s->subdev_flags = SDF_WRITABLE; /* you can write it from userspace */ + s->n_chan = 2; /* Number of Analog output channels */ + s->maxdata = 0x0fff; /* accept only 12 bits of data */ + s->range_table = &range_fl512; /* device use one of the ranges */ + s->insn_write = fl512_ao_insn; /* function to call when write DA */ + s->insn_read = fl512_ao_insn_readback; /* function to call when reading DA */ + printk("comedi: fl512: subdevice 1 initialized\n"); + + return 1; +} + +static int fl512_detach(struct comedi_device * dev) +{ + if (dev->iobase) + release_region(dev->iobase, FL512_SIZE); + printk("comedi%d: fl512: dummy i detach\n", dev->minor); + return 0; +} diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c new file mode 100644 index 000000000000..49e5c86c2dd8 --- /dev/null +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -0,0 +1,1060 @@ +/* + comedi/drivers/gsc_hpdi.c + This is a driver for the General Standards Corporation High + Speed Parallel Digital Interface rs485 boards. + + Author: Frank Mori Hess + Copyright (C) 2003 Coherent Imaging Systems + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-8 David A. Schleef + + 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: gsc_hpdi +Description: General Standards Corporation High + Speed Parallel Digital Interface rs485 boards +Author: Frank Mori Hess +Status: only receive mode works, transmit not supported +Updated: 2003-02-20 +Devices: [General Standards Corporation] PCI-HPDI32 (gsc_hpdi), + PMC-HPDI32 + +Configuration options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + +There are some additional hpdi models available from GSC for which +support could be added to this driver. + +*/ + +#include "../comedidev.h" +#include + +#include "comedi_pci.h" +#include "plx9080.h" +#include "comedi_fc.h" + +static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int hpdi_detach(struct comedi_device * dev); +void abort_dma(struct comedi_device * dev, unsigned int channel); +static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int hpdi_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int hpdi_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG); +static int dio_config_block_size(struct comedi_device * dev, unsigned int * data); + +#undef HPDI_DEBUG // disable debugging messages +//#define HPDI_DEBUG // enable debugging code + +#ifdef HPDI_DEBUG +#define DEBUG_PRINT(format, args...) rt_printk(format , ## args ) +#else +#define DEBUG_PRINT(format, args...) +#endif + +#define TIMER_BASE 50 // 20MHz master clock +#define DMA_BUFFER_SIZE 0x10000 +#define NUM_DMA_BUFFERS 4 +#define NUM_DMA_DESCRIPTORS 256 + +// indices of base address regions +enum base_address_regions { + PLX9080_BADDRINDEX = 0, + HPDI_BADDRINDEX = 2, +}; + +enum hpdi_registers { + FIRMWARE_REV_REG = 0x0, + BOARD_CONTROL_REG = 0x4, + BOARD_STATUS_REG = 0x8, + TX_PROG_ALMOST_REG = 0xc, + RX_PROG_ALMOST_REG = 0x10, + FEATURES_REG = 0x14, + FIFO_REG = 0x18, + TX_STATUS_COUNT_REG = 0x1c, + TX_LINE_VALID_COUNT_REG = 0x20, + TX_LINE_INVALID_COUNT_REG = 0x24, + RX_STATUS_COUNT_REG = 0x28, + RX_LINE_COUNT_REG = 0x2c, + INTERRUPT_CONTROL_REG = 0x30, + INTERRUPT_STATUS_REG = 0x34, + TX_CLOCK_DIVIDER_REG = 0x38, + TX_FIFO_SIZE_REG = 0x40, + RX_FIFO_SIZE_REG = 0x44, + TX_FIFO_WORDS_REG = 0x48, + RX_FIFO_WORDS_REG = 0x4c, + INTERRUPT_EDGE_LEVEL_REG = 0x50, + INTERRUPT_POLARITY_REG = 0x54, +}; + +int command_channel_valid(unsigned int channel) +{ + if (channel == 0 || channel > 6) { + rt_printk("gsc_hpdi: bug! invalid cable command channel\n"); + return 0; + } + return 1; +} + +// bit definitions + +enum firmware_revision_bits { + FEATURES_REG_PRESENT_BIT = 0x8000, +}; +int firmware_revision(uint32_t fwr_bits) +{ + return fwr_bits & 0xff; +} + +int pcb_revision(uint32_t fwr_bits) +{ + return (fwr_bits >> 8) & 0xff; +} + +int hpdi_subid(uint32_t fwr_bits) +{ + return (fwr_bits >> 16) & 0xff; +} + +enum board_control_bits { + BOARD_RESET_BIT = 0x1, /* wait 10usec before accessing fifos */ + TX_FIFO_RESET_BIT = 0x2, + RX_FIFO_RESET_BIT = 0x4, + TX_ENABLE_BIT = 0x10, + RX_ENABLE_BIT = 0x20, + DEMAND_DMA_DIRECTION_TX_BIT = 0x40, /* for channel 0, channel 1 can only transmit (when present) */ + LINE_VALID_ON_STATUS_VALID_BIT = 0x80, + START_TX_BIT = 0x10, + CABLE_THROTTLE_ENABLE_BIT = 0x20, + TEST_MODE_ENABLE_BIT = 0x80000000, +}; +uint32_t command_discrete_output_bits(unsigned int channel, int output, + int output_value) +{ + uint32_t bits = 0; + + if (command_channel_valid(channel) == 0) + return 0; + if (output) { + bits |= 0x1 << (16 + channel); + if (output_value) + bits |= 0x1 << (24 + channel); + } else + bits |= 0x1 << (24 + channel); + + return bits; +} + +enum board_status_bits { + COMMAND_LINE_STATUS_MASK = 0x7f, + TX_IN_PROGRESS_BIT = 0x80, + TX_NOT_EMPTY_BIT = 0x100, + TX_NOT_ALMOST_EMPTY_BIT = 0x200, + TX_NOT_ALMOST_FULL_BIT = 0x400, + TX_NOT_FULL_BIT = 0x800, + RX_NOT_EMPTY_BIT = 0x1000, + RX_NOT_ALMOST_EMPTY_BIT = 0x2000, + RX_NOT_ALMOST_FULL_BIT = 0x4000, + RX_NOT_FULL_BIT = 0x8000, + BOARD_JUMPER0_INSTALLED_BIT = 0x10000, + BOARD_JUMPER1_INSTALLED_BIT = 0x20000, + TX_OVERRUN_BIT = 0x200000, + RX_UNDERRUN_BIT = 0x400000, + RX_OVERRUN_BIT = 0x800000, +}; + +uint32_t almost_full_bits(unsigned int num_words) +{ +// XXX need to add or subtract one? + return (num_words << 16) & 0xff0000; +} + +uint32_t almost_empty_bits(unsigned int num_words) +{ + return num_words & 0xffff; +} +unsigned int almost_full_num_words(uint32_t bits) +{ +// XXX need to add or subtract one? + return (bits >> 16) & 0xffff; +} +unsigned int almost_empty_num_words(uint32_t bits) +{ + return bits & 0xffff; +} + +enum features_bits { + FIFO_SIZE_PRESENT_BIT = 0x1, + FIFO_WORDS_PRESENT_BIT = 0x2, + LEVEL_EDGE_INTERRUPTS_PRESENT_BIT = 0x4, + GPIO_SUPPORTED_BIT = 0x8, + PLX_DMA_CH1_SUPPORTED_BIT = 0x10, + OVERRUN_UNDERRUN_SUPPORTED_BIT = 0x20, +}; + +enum interrupt_sources { + FRAME_VALID_START_INTR = 0, + FRAME_VALID_END_INTR = 1, + TX_FIFO_EMPTY_INTR = 8, + TX_FIFO_ALMOST_EMPTY_INTR = 9, + TX_FIFO_ALMOST_FULL_INTR = 10, + TX_FIFO_FULL_INTR = 11, + RX_EMPTY_INTR = 12, + RX_ALMOST_EMPTY_INTR = 13, + RX_ALMOST_FULL_INTR = 14, + RX_FULL_INTR = 15, +}; +int command_intr_source(unsigned int channel) +{ + if (command_channel_valid(channel) == 0) + channel = 1; + return channel + 1; +} + +uint32_t intr_bit(int interrupt_source) +{ + return 0x1 << interrupt_source; +} + +uint32_t tx_clock_divisor_bits(unsigned int divisor) +{ + return divisor & 0xff; +} + +unsigned int fifo_size(uint32_t fifo_size_bits) +{ + return fifo_size_bits & 0xfffff; +} + +unsigned int fifo_words(uint32_t fifo_words_bits) +{ + return fifo_words_bits & 0xfffff; +} + +uint32_t intr_edge_bit(int interrupt_source) +{ + return 0x1 << interrupt_source; +} + +uint32_t intr_active_high_bit(int interrupt_source) +{ + return 0x1 << interrupt_source; +} + +struct hpdi_board { + + char *name; + int device_id; // pci device id + int subdevice_id; // pci subdevice id +}; + + +static const struct hpdi_board hpdi_boards[] = { + { + name: "pci-hpdi32", + device_id:PCI_DEVICE_ID_PLX_9080, + subdevice_id:0x2400, + }, +#if 0 + { + name: "pxi-hpdi32", + device_id:0x9656, + subdevice_id:0x2705, + }, +#endif +}; + +static inline unsigned int num_boards(void) +{ + return sizeof(hpdi_boards) / sizeof(struct hpdi_board); +} + +static DEFINE_PCI_DEVICE_TABLE(hpdi_pci_table) = { + {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, PCI_VENDOR_ID_PLX, 0x2400, + 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, hpdi_pci_table); + +static inline struct hpdi_board *board(const struct comedi_device * dev) +{ + return (struct hpdi_board *) dev->board_ptr; +} + +struct hpdi_private { + + struct pci_dev *hw_dev; // pointer to board's pci_dev struct + // base addresses (physical) + resource_size_t plx9080_phys_iobase; + resource_size_t hpdi_phys_iobase; + // base addresses (ioremapped) + void *plx9080_iobase; + void *hpdi_iobase; + uint32_t *dio_buffer[NUM_DMA_BUFFERS]; // dma buffers + dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS]; // physical addresses of dma buffers + struct plx_dma_desc *dma_desc; // array of dma descriptors read by plx9080, allocated to get proper alignment + dma_addr_t dma_desc_phys_addr; // physical address of dma descriptor array + unsigned int num_dma_descriptors; + uint32_t *desc_dio_buffer[NUM_DMA_DESCRIPTORS]; // pointer to start of buffers indexed by descriptor + volatile unsigned int dma_desc_index; // index of the dma descriptor that is currently being used + unsigned int tx_fifo_size; + unsigned int rx_fifo_size; + volatile unsigned long dio_count; + volatile uint32_t bits[24]; // software copies of values written to hpdi registers + volatile unsigned int block_size; // number of bytes at which to generate COMEDI_CB_BLOCK events + unsigned dio_config_output:1; +}; + + +static inline struct hpdi_private *priv(struct comedi_device * dev) +{ + return dev->private; +} + +static struct comedi_driver driver_hpdi = { + driver_name:"gsc_hpdi", + module:THIS_MODULE, + attach:hpdi_attach, + detach:hpdi_detach, +}; + +COMEDI_PCI_INITCLEANUP(driver_hpdi, hpdi_pci_table); + +static int dio_config_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + priv(dev)->dio_config_output = 1; + return insn->n; + break; + case INSN_CONFIG_DIO_INPUT: + priv(dev)->dio_config_output = 0; + return insn->n; + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + priv(dev)-> + dio_config_output ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + case INSN_CONFIG_BLOCK_SIZE: + return dio_config_block_size(dev, data); + break; + default: + break; + } + + return -EINVAL; +} + +static void disable_plx_interrupts(struct comedi_device * dev) +{ + writel(0, priv(dev)->plx9080_iobase + PLX_INTRCS_REG); +} + +// initialize plx9080 chip +static void init_plx9080(struct comedi_device * dev) +{ + uint32_t bits; + void *plx_iobase = priv(dev)->plx9080_iobase; + + // plx9080 dump + DEBUG_PRINT(" plx interrupt status 0x%x\n", + readl(plx_iobase + PLX_INTRCS_REG)); + DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG)); + DEBUG_PRINT(" plx control reg 0x%x\n", + readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG)); + + DEBUG_PRINT(" plx revision 0x%x\n", + readl(plx_iobase + PLX_REVISION_REG)); + DEBUG_PRINT(" plx dma channel 0 mode 0x%x\n", + readl(plx_iobase + PLX_DMA0_MODE_REG)); + DEBUG_PRINT(" plx dma channel 1 mode 0x%x\n", + readl(plx_iobase + PLX_DMA1_MODE_REG)); + DEBUG_PRINT(" plx dma channel 0 pci address 0x%x\n", + readl(plx_iobase + PLX_DMA0_PCI_ADDRESS_REG)); + DEBUG_PRINT(" plx dma channel 0 local address 0x%x\n", + readl(plx_iobase + PLX_DMA0_LOCAL_ADDRESS_REG)); + DEBUG_PRINT(" plx dma channel 0 transfer size 0x%x\n", + readl(plx_iobase + PLX_DMA0_TRANSFER_SIZE_REG)); + DEBUG_PRINT(" plx dma channel 0 descriptor 0x%x\n", + readl(plx_iobase + PLX_DMA0_DESCRIPTOR_REG)); + DEBUG_PRINT(" plx dma channel 0 command status 0x%x\n", + readb(plx_iobase + PLX_DMA0_CS_REG)); + DEBUG_PRINT(" plx dma channel 0 threshold 0x%x\n", + readl(plx_iobase + PLX_DMA0_THRESHOLD_REG)); + DEBUG_PRINT(" plx bigend 0x%x\n", readl(plx_iobase + PLX_BIGEND_REG)); +#ifdef __BIG_ENDIAN + bits = BIGEND_DMA0 | BIGEND_DMA1; +#else + bits = 0; +#endif + writel(bits, priv(dev)->plx9080_iobase + PLX_BIGEND_REG); + + disable_plx_interrupts(dev); + + abort_dma(dev, 0); + abort_dma(dev, 1); + + // configure dma0 mode + bits = 0; + // enable ready input + bits |= PLX_DMA_EN_READYIN_BIT; + // enable dma chaining + bits |= PLX_EN_CHAIN_BIT; + // enable interrupt on dma done (probably don't need this, since chain never finishes) + bits |= PLX_EN_DMA_DONE_INTR_BIT; + // don't increment local address during transfers (we are transferring from a fixed fifo register) + bits |= PLX_LOCAL_ADDR_CONST_BIT; + // route dma interrupt to pci bus + bits |= PLX_DMA_INTR_PCI_BIT; + // enable demand mode + bits |= PLX_DEMAND_MODE_BIT; + // enable local burst mode + bits |= PLX_DMA_LOCAL_BURST_EN_BIT; + bits |= PLX_LOCAL_BUS_32_WIDE_BITS; + writel(bits, plx_iobase + PLX_DMA0_MODE_REG); +} + +/* Allocate and initialize the subdevice structures. + */ +static int setup_subdevices(struct comedi_device * dev) +{ + struct comedi_subdevice *s; + + if (alloc_subdevices(dev, 1) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* analog input subdevice */ + dev->read_subdev = s; +/* dev->write_subdev = s; */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = + SDF_READABLE | SDF_WRITEABLE | SDF_LSAMPL | SDF_CMD_READ; + s->n_chan = 32; + s->len_chanlist = 32; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_config = dio_config_insn; + s->do_cmd = hpdi_cmd; + s->do_cmdtest = hpdi_cmd_test; + s->cancel = hpdi_cancel; + + return 0; +} + +static int init_hpdi(struct comedi_device * dev) +{ + uint32_t plx_intcsr_bits; + + writel(BOARD_RESET_BIT, priv(dev)->hpdi_iobase + BOARD_CONTROL_REG); + comedi_udelay(10); + + writel(almost_empty_bits(32) | almost_full_bits(32), + priv(dev)->hpdi_iobase + RX_PROG_ALMOST_REG); + writel(almost_empty_bits(32) | almost_full_bits(32), + priv(dev)->hpdi_iobase + TX_PROG_ALMOST_REG); + + priv(dev)->tx_fifo_size = fifo_size(readl(priv(dev)->hpdi_iobase + + TX_FIFO_SIZE_REG)); + priv(dev)->rx_fifo_size = fifo_size(readl(priv(dev)->hpdi_iobase + + RX_FIFO_SIZE_REG)); + + writel(0, priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG); + + // enable interrupts + plx_intcsr_bits = + ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE | + ICS_DMA0_E; + writel(plx_intcsr_bits, priv(dev)->plx9080_iobase + PLX_INTRCS_REG); + + return 0; +} + +// setup dma descriptors so a link completes every 'transfer_size' bytes +static int setup_dma_descriptors(struct comedi_device * dev, + unsigned int transfer_size) +{ + unsigned int buffer_index, buffer_offset; + uint32_t next_bits = PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | + PLX_XFER_LOCAL_TO_PCI; + unsigned int i; + + if (transfer_size > DMA_BUFFER_SIZE) + transfer_size = DMA_BUFFER_SIZE; + transfer_size -= transfer_size % sizeof(uint32_t); + if (transfer_size == 0) + return -1; + + DEBUG_PRINT(" transfer_size %i\n", transfer_size); + DEBUG_PRINT(" descriptors at 0x%lx\n", + (unsigned long)priv(dev)->dma_desc_phys_addr); + + buffer_offset = 0; + buffer_index = 0; + for (i = 0; i < NUM_DMA_DESCRIPTORS && + buffer_index < NUM_DMA_BUFFERS; i++) { + priv(dev)->dma_desc[i].pci_start_addr = + cpu_to_le32(priv(dev)-> + dio_buffer_phys_addr[buffer_index] + buffer_offset); + priv(dev)->dma_desc[i].local_start_addr = cpu_to_le32(FIFO_REG); + priv(dev)->dma_desc[i].transfer_size = + cpu_to_le32(transfer_size); + priv(dev)->dma_desc[i].next = + cpu_to_le32((priv(dev)->dma_desc_phys_addr + (i + + 1) * + sizeof(priv(dev)->dma_desc[0])) | next_bits); + + priv(dev)->desc_dio_buffer[i] = + priv(dev)->dio_buffer[buffer_index] + + (buffer_offset / sizeof(uint32_t)); + + buffer_offset += transfer_size; + if (transfer_size + buffer_offset > DMA_BUFFER_SIZE) { + buffer_offset = 0; + buffer_index++; + } + + DEBUG_PRINT(" desc %i\n", i); + DEBUG_PRINT(" start addr virt 0x%p, phys 0x%lx\n", + priv(dev)->desc_dio_buffer[i], + (unsigned long)priv(dev)->dma_desc[i].pci_start_addr); + DEBUG_PRINT(" next 0x%lx\n", + (unsigned long)priv(dev)->dma_desc[i].next); + } + priv(dev)->num_dma_descriptors = i; + // fix last descriptor to point back to first + priv(dev)->dma_desc[i - 1].next = + cpu_to_le32(priv(dev)->dma_desc_phys_addr | next_bits); + DEBUG_PRINT(" desc %i next fixup 0x%lx\n", i - 1, + (unsigned long)priv(dev)->dma_desc[i - 1].next); + + priv(dev)->block_size = transfer_size; + + return transfer_size; +} + +static int hpdi_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct pci_dev *pcidev; + int i; + int retval; + + printk("comedi%d: gsc_hpdi\n", dev->minor); + + if (alloc_private(dev, sizeof(struct hpdi_private)) < 0) + return -ENOMEM; + + pcidev = NULL; + for (i = 0; i < num_boards() && dev->board_ptr == NULL; i++) { + do { + pcidev = pci_get_subsys(PCI_VENDOR_ID_PLX, + hpdi_boards[i].device_id, PCI_VENDOR_ID_PLX, + hpdi_boards[i].subdevice_id, pcidev); + // was a particular bus/slot requested? + if (it->options[0] || it->options[1]) { + // are we on the wrong bus/slot? + if (pcidev->bus->number != it->options[0] || + PCI_SLOT(pcidev->devfn) != + it->options[1]) + continue; + } + if (pcidev) { + priv(dev)->hw_dev = pcidev; + dev->board_ptr = hpdi_boards + i; + break; + } + } while (pcidev != NULL); + } + if (dev->board_ptr == NULL) { + printk("gsc_hpdi: no hpdi card found\n"); + return -EIO; + } + + printk("gsc_hpdi: found %s on bus %i, slot %i\n", board(dev)->name, + pcidev->bus->number, PCI_SLOT(pcidev->devfn)); + + if (comedi_pci_enable(pcidev, driver_hpdi.driver_name)) { + printk(KERN_WARNING + " failed enable PCI device and request regions\n"); + return -EIO; + } + pci_set_master(pcidev); + + //Initialize dev->board_name + dev->board_name = board(dev)->name; + + priv(dev)->plx9080_phys_iobase = + pci_resource_start(pcidev, PLX9080_BADDRINDEX); + priv(dev)->hpdi_phys_iobase = + pci_resource_start(pcidev, HPDI_BADDRINDEX); + + // remap, won't work with 2.0 kernels but who cares + priv(dev)->plx9080_iobase = ioremap(priv(dev)->plx9080_phys_iobase, + pci_resource_len(pcidev, PLX9080_BADDRINDEX)); + priv(dev)->hpdi_iobase = ioremap(priv(dev)->hpdi_phys_iobase, + pci_resource_len(pcidev, HPDI_BADDRINDEX)); + if (!priv(dev)->plx9080_iobase || !priv(dev)->hpdi_iobase) { + printk(" failed to remap io memory\n"); + return -ENOMEM; + } + + DEBUG_PRINT(" plx9080 remapped to 0x%p\n", priv(dev)->plx9080_iobase); + DEBUG_PRINT(" hpdi remapped to 0x%p\n", priv(dev)->hpdi_iobase); + + init_plx9080(dev); + + // get irq + if (comedi_request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, + driver_hpdi.driver_name, dev)) { + printk(" unable to allocate irq %u\n", pcidev->irq); + return -EINVAL; + } + dev->irq = pcidev->irq; + + printk(" irq %u\n", dev->irq); + + // alocate pci dma buffers + for (i = 0; i < NUM_DMA_BUFFERS; i++) { + priv(dev)->dio_buffer[i] = + pci_alloc_consistent(priv(dev)->hw_dev, DMA_BUFFER_SIZE, + &priv(dev)->dio_buffer_phys_addr[i]); + DEBUG_PRINT("dio_buffer at virt 0x%p, phys 0x%lx\n", + priv(dev)->dio_buffer[i], + (unsigned long)priv(dev)->dio_buffer_phys_addr[i]); + } + // allocate dma descriptors + priv(dev)->dma_desc = pci_alloc_consistent(priv(dev)->hw_dev, + sizeof(struct plx_dma_desc) * NUM_DMA_DESCRIPTORS, + &priv(dev)->dma_desc_phys_addr); + if (priv(dev)->dma_desc_phys_addr & 0xf) { + printk(" dma descriptors not quad-word aligned (bug)\n"); + return -EIO; + } + + retval = setup_dma_descriptors(dev, 0x1000); + if (retval < 0) + return retval; + + retval = setup_subdevices(dev); + if (retval < 0) + return retval; + + return init_hpdi(dev); +} + +static int hpdi_detach(struct comedi_device * dev) +{ + unsigned int i; + + printk("comedi%d: gsc_hpdi: remove\n", dev->minor); + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (priv(dev)) { + if (priv(dev)->hw_dev) { + if (priv(dev)->plx9080_iobase) { + disable_plx_interrupts(dev); + iounmap((void *)priv(dev)->plx9080_iobase); + } + if (priv(dev)->hpdi_iobase) + iounmap((void *)priv(dev)->hpdi_iobase); + // free pci dma buffers + for (i = 0; i < NUM_DMA_BUFFERS; i++) { + if (priv(dev)->dio_buffer[i]) + pci_free_consistent(priv(dev)->hw_dev, + DMA_BUFFER_SIZE, + priv(dev)->dio_buffer[i], + priv(dev)-> + dio_buffer_phys_addr[i]); + } + // free dma descriptors + if (priv(dev)->dma_desc) + pci_free_consistent(priv(dev)->hw_dev, + sizeof(struct plx_dma_desc) * + NUM_DMA_DESCRIPTORS, + priv(dev)->dma_desc, + priv(dev)->dma_desc_phys_addr); + if (priv(dev)->hpdi_phys_iobase) { + comedi_pci_disable(priv(dev)->hw_dev); + } + pci_dev_put(priv(dev)->hw_dev); + } + } + return 0; +} + +static int dio_config_block_size(struct comedi_device * dev, unsigned int * data) +{ + unsigned int requested_block_size; + int retval; + + requested_block_size = data[1]; + + retval = setup_dma_descriptors(dev, requested_block_size); + if (retval < 0) + return retval; + + data[1] = retval; + + return 2; +} + +static int di_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + int i; + + /* step 1: make sure trigger sources are trivially valid */ + + 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_NOW; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + // uniqueness check + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (!cmd->chanlist_len) { + cmd->chanlist_len = 32; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + switch (cmd->stop_src) { + case TRIG_COUNT: + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + break; + case TRIG_NONE: + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + break; + default: + break; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (err) + return 4; + + if (cmd->chanlist) { + for (i = 1; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != i) { + // XXX could support 8 channels or 16 channels + comedi_error(dev, + "chanlist must be channels 0 to 31 in order"); + err++; + break; + } + } + } + + if (err) + return 5; + + return 0; +} + +static int hpdi_cmd_test(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + if (priv(dev)->dio_config_output) { + return -EINVAL; + } else + return di_cmd_test(dev, s, cmd); +} + +static inline void hpdi_writel(struct comedi_device * dev, uint32_t bits, + unsigned int offset) +{ + writel(bits | priv(dev)->bits[offset / sizeof(uint32_t)], + priv(dev)->hpdi_iobase + offset); +} + +static int di_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + uint32_t bits; + unsigned long flags; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + + hpdi_writel(dev, RX_FIFO_RESET_BIT, BOARD_CONTROL_REG); + + DEBUG_PRINT("hpdi: in di_cmd\n"); + + abort_dma(dev, 0); + + priv(dev)->dma_desc_index = 0; + + /* These register are supposedly unused during chained dma, + * but I have found that left over values from last operation + * occasionally cause problems with transfer of first dma + * block. Initializing them to zero seems to fix the problem. */ + writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_TRANSFER_SIZE_REG); + writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG); + writel(0, priv(dev)->plx9080_iobase + PLX_DMA0_LOCAL_ADDRESS_REG); + // give location of first dma descriptor + bits = priv(dev)-> + dma_desc_phys_addr | PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | + PLX_XFER_LOCAL_TO_PCI; + writel(bits, priv(dev)->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG); + + // spinlock for plx dma control/status reg + comedi_spin_lock_irqsave(&dev->spinlock, flags); + // enable dma transfer + writeb(PLX_DMA_EN_BIT | PLX_DMA_START_BIT | PLX_CLEAR_DMA_INTR_BIT, + priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + if (cmd->stop_src == TRIG_COUNT) + priv(dev)->dio_count = cmd->stop_arg; + else + priv(dev)->dio_count = 1; + + // clear over/under run status flags + writel(RX_UNDERRUN_BIT | RX_OVERRUN_BIT, + priv(dev)->hpdi_iobase + BOARD_STATUS_REG); + // enable interrupts + writel(intr_bit(RX_FULL_INTR), + priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG); + + DEBUG_PRINT("hpdi: starting rx\n"); + hpdi_writel(dev, RX_ENABLE_BIT, BOARD_CONTROL_REG); + + return 0; +} + +static int hpdi_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + if (priv(dev)->dio_config_output) { + return -EINVAL; + } else + return di_cmd(dev, s); +} + +static void drain_dma_buffers(struct comedi_device * dev, unsigned int channel) +{ + struct comedi_async *async = dev->read_subdev->async; + uint32_t next_transfer_addr; + int j; + int num_samples = 0; + void *pci_addr_reg; + + if (channel) + pci_addr_reg = + priv(dev)->plx9080_iobase + PLX_DMA1_PCI_ADDRESS_REG; + else + pci_addr_reg = + priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG; + + // loop until we have read all the full buffers + j = 0; + for (next_transfer_addr = readl(pci_addr_reg); + (next_transfer_addr < + le32_to_cpu(priv(dev)->dma_desc[priv(dev)-> + dma_desc_index].pci_start_addr) + || next_transfer_addr >= + le32_to_cpu(priv(dev)->dma_desc[priv(dev)-> + dma_desc_index].pci_start_addr) + + priv(dev)->block_size) + && j < priv(dev)->num_dma_descriptors; j++) { + // transfer data from dma buffer to comedi buffer + num_samples = priv(dev)->block_size / sizeof(uint32_t); + if (async->cmd.stop_src == TRIG_COUNT) { + if (num_samples > priv(dev)->dio_count) + num_samples = priv(dev)->dio_count; + priv(dev)->dio_count -= num_samples; + } + cfc_write_array_to_buffer(dev->read_subdev, + priv(dev)->desc_dio_buffer[priv(dev)->dma_desc_index], + num_samples * sizeof(uint32_t)); + priv(dev)->dma_desc_index++; + priv(dev)->dma_desc_index %= priv(dev)->num_dma_descriptors; + + DEBUG_PRINT("next desc addr 0x%lx\n", (unsigned long) + priv(dev)->dma_desc[priv(dev)->dma_desc_index].next); + DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr); + } + // XXX check for buffer overrun somehow +} + +static irqreturn_t handle_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async = s->async; + uint32_t hpdi_intr_status, hpdi_board_status; + uint32_t plx_status; + uint32_t plx_bits; + uint8_t dma0_status, dma1_status; + unsigned long flags; + + if (!dev->attached) { + return IRQ_NONE; + } + + plx_status = readl(priv(dev)->plx9080_iobase + PLX_INTRCS_REG); + if ((plx_status & (ICS_DMA0_A | ICS_DMA1_A | ICS_LIA)) == 0) { + return IRQ_NONE; + } + + hpdi_intr_status = readl(priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG); + hpdi_board_status = readl(priv(dev)->hpdi_iobase + BOARD_STATUS_REG); + + async->events = 0; + + if (hpdi_intr_status) { + DEBUG_PRINT("hpdi: intr status 0x%x, ", hpdi_intr_status); + writel(hpdi_intr_status, + priv(dev)->hpdi_iobase + INTERRUPT_STATUS_REG); + } + // spin lock makes sure noone else changes plx dma control reg + comedi_spin_lock_irqsave(&dev->spinlock, flags); + dma0_status = readb(priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); + if (plx_status & ICS_DMA0_A) { // dma chan 0 interrupt + writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, + priv(dev)->plx9080_iobase + PLX_DMA0_CS_REG); + + DEBUG_PRINT("dma0 status 0x%x\n", dma0_status); + if (dma0_status & PLX_DMA_EN_BIT) { + drain_dma_buffers(dev, 0); + } + DEBUG_PRINT(" cleared dma ch0 interrupt\n"); + } + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // spin lock makes sure noone else changes plx dma control reg + comedi_spin_lock_irqsave(&dev->spinlock, flags); + dma1_status = readb(priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG); + if (plx_status & ICS_DMA1_A) // XXX + { // dma chan 1 interrupt + writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, + priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG); + DEBUG_PRINT("dma1 status 0x%x\n", dma1_status); + + DEBUG_PRINT(" cleared dma ch1 interrupt\n"); + } + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // clear possible plx9080 interrupt sources + if (plx_status & ICS_LDIA) { // clear local doorbell interrupt + plx_bits = readl(priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG); + writel(plx_bits, priv(dev)->plx9080_iobase + PLX_DBR_OUT_REG); + DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits); + } + + if (hpdi_board_status & RX_OVERRUN_BIT) { + comedi_error(dev, "rx fifo overrun"); + async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + DEBUG_PRINT("dma0_status 0x%x\n", + (int)readb(priv(dev)->plx9080_iobase + + PLX_DMA0_CS_REG)); + } + + if (hpdi_board_status & RX_UNDERRUN_BIT) { + comedi_error(dev, "rx fifo underrun"); + async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + } + + if (priv(dev)->dio_count == 0) + async->events |= COMEDI_CB_EOA; + + DEBUG_PRINT("board status 0x%x, ", hpdi_board_status); + DEBUG_PRINT("plx status 0x%x\n", plx_status); + if (async->events) + DEBUG_PRINT(" events 0x%x\n", async->events); + + cfc_handle_events(dev, s); + + return IRQ_HANDLED; +} + +void abort_dma(struct comedi_device * dev, unsigned int channel) +{ + unsigned long flags; + + // spinlock for plx dma control/status reg + comedi_spin_lock_irqsave(&dev->spinlock, flags); + + plx9080_abort_dma(priv(dev)->plx9080_iobase, channel); + + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); +} + +static int hpdi_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + hpdi_writel(dev, 0, BOARD_CONTROL_REG); + + writel(0, priv(dev)->hpdi_iobase + INTERRUPT_CONTROL_REG); + + abort_dma(dev, 0); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 59144d7cb0bc..15fce0190b2f 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -61,7 +61,7 @@ Options: #define ICP_MULTI_EXTDEBUG -// Hardware types of the cards +/* Hardware types of the cards */ #define TYPE_ICP_MULTI 0 #define IORANGE_ICP_MULTI 32 @@ -81,20 +81,20 @@ Options: #define ICP_MULTI_SIZE 0x20 /* 32 bytes */ -// Define bits from ADC command/status register +/* Define bits from ADC command/status register */ #define ADC_ST 0x0001 /* Start ADC */ #define ADC_BSY 0x0001 /* ADC busy */ #define ADC_BI 0x0010 /* Bipolar input range 1 = bipolar */ #define ADC_RA 0x0020 /* Input range 0 = 5V, 1 = 10V */ #define ADC_DI 0x0040 /* Differential input mode 1 = differential */ -// Define bits from DAC command/status register +/* Define bits from DAC command/status register */ #define DAC_ST 0x0001 /* Start DAC */ #define DAC_BSY 0x0001 /* DAC busy */ #define DAC_BI 0x0010 /* Bipolar input range 1 = bipolar */ #define DAC_RA 0x0020 /* Input range 0 = 5V, 1 = 10V */ -// Define bits from interrupt enable/status registers +/* Define bits from interrupt enable/status registers */ #define ADC_READY 0x0001 /* A/d conversion ready interrupt */ #define DAC_READY 0x0002 /* D/a conversion ready interrupt */ #define DOUT_ERROR 0x0004 /* Digital output error interrupt */ @@ -104,11 +104,11 @@ Options: #define CIE2 0x0040 /* Counter 2 overrun interrupt */ #define CIE3 0x0080 /* Counter 3 overrun interrupt */ -// Useful definitions -#define Status_IRQ 0x00ff // All interrupts +/* Useful definitions */ +#define Status_IRQ 0x00ff /* All interrupts */ -// Define analogue range -static const comedi_lrange range_analog = { 4, { +/* Define analogue range */ +static const struct comedi_lrange range_analog = { 4, { UNI_RANGE(5), UNI_RANGE(10), BIP_RANGE(5), @@ -123,8 +123,8 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 }; Forward declarations ============================================================================== */ -static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it); -static int icp_multi_detach(comedi_device * dev); +static int icp_multi_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int icp_multi_detach(struct comedi_device *dev); /* ============================================================================== @@ -133,79 +133,79 @@ static int icp_multi_detach(comedi_device * dev); */ static unsigned short pci_list_builded = 0; /*>0 list of card is known */ -typedef struct { - const char *name; // driver name +struct boardtype { + const char *name; /* driver name */ int device_id; - int iorange; // I/O range len - char have_irq; // 1=card support IRQ - char cardtype; // 0=ICP Multi - int n_aichan; // num of A/D chans - int n_aichand; // num of A/D chans in diff mode - int n_aochan; // num of D/A chans - int n_dichan; // num of DI chans - int n_dochan; // num of DO chans - int n_ctrs; // num of counters - int ai_maxdata; // resolution of A/D - int ao_maxdata; // resolution of D/A - const comedi_lrange *rangelist_ai; // rangelist for A/D - const char *rangecode; // range codes for programming - const comedi_lrange *rangelist_ao; // rangelist for D/A -} boardtype; - -static const boardtype boardtypes[] = { - {"icp_multi", // Driver name - DEVICE_ID, // PCI device ID - IORANGE_ICP_MULTI, // I/O range length - 1, // 1=Card supports interrupts - TYPE_ICP_MULTI, // Card type = ICP MULTI - 16, // Num of A/D channels - 8, // Num of A/D channels in diff mode - 4, // Num of D/A channels - 16, // Num of digital inputs - 8, // Num of digital outputs - 4, // Num of counters - 0x0fff, // Resolution of A/D - 0x0fff, // Resolution of D/A - &range_analog, // Rangelist for A/D - range_codes_analog, // Range codes for programming - &range_analog}, // Rangelist for D/A + int iorange; /* I/O range len */ + char have_irq; /* 1=card support IRQ */ + char cardtype; /* 0=ICP Multi */ + int n_aichan; /* num of A/D chans */ + int n_aichand; /* num of A/D chans in diff mode */ + int n_aochan; /* num of D/A chans */ + int n_dichan; /* num of DI chans */ + int n_dochan; /* num of DO chans */ + int n_ctrs; /* num of counters */ + int ai_maxdata; /* resolution of A/D */ + int ao_maxdata; /* resolution of D/A */ + const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ + const char *rangecode; /* range codes for programming */ + const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ }; -#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype)) +static const struct boardtype boardtypes[] = { + {"icp_multi", /* Driver name */ + DEVICE_ID, /* PCI device ID */ + IORANGE_ICP_MULTI, /* I/O range length */ + 1, /* 1=Card supports interrupts */ + TYPE_ICP_MULTI, /* Card type = ICP MULTI */ + 16, /* Num of A/D channels */ + 8, /* Num of A/D channels in diff mode */ + 4, /* Num of D/A channels */ + 16, /* Num of digital inputs */ + 8, /* Num of digital outputs */ + 4, /* Num of counters */ + 0x0fff, /* Resolution of A/D */ + 0x0fff, /* Resolution of D/A */ + &range_analog, /* Rangelist for A/D */ + range_codes_analog, /* Range codes for programming */ + &range_analog}, /* Rangelist for D/A */ +}; -static comedi_driver driver_icp_multi = { +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype)) + +static struct comedi_driver driver_icp_multi = { driver_name:"icp_multi", - module:THIS_MODULE, - attach:icp_multi_attach, - detach:icp_multi_detach, - num_names:n_boardtypes, - board_name:&boardtypes[0].name, - offset:sizeof(boardtype), + module : THIS_MODULE, + attach : icp_multi_attach, + detach : icp_multi_detach, + num_names : n_boardtypes, + board_name : &boardtypes[0].name, + offset : sizeof(struct boardtype), }; COMEDI_INITCLEANUP(driver_icp_multi); -typedef struct { - struct pcilst_struct *card; // pointer to card - char valid; // card is usable - void *io_addr; // Pointer to mapped io address - resource_size_t phys_iobase; // Physical io address - unsigned int AdcCmdStatus; // ADC Command/Status register - unsigned int DacCmdStatus; // DAC Command/Status register - unsigned int IntEnable; // Interrupt Enable register - unsigned int IntStatus; // Interrupt Status register - unsigned int act_chanlist[32]; // list of scaned channel - unsigned char act_chanlist_len; // len of scanlist - unsigned char act_chanlist_pos; // actual position in MUX list - unsigned int *ai_chanlist; // actaul chanlist - sampl_t *ai_data; // data buffer - sampl_t ao_data[4]; // data output buffer - sampl_t di_data; // Digital input data - unsigned int do_data; // Remember digital output data -} icp_multi_private; +struct icp_multi_private { + struct pcilst_struct *card; /* pointer to card */ + char valid; /* card is usable */ + void *io_addr; /* Pointer to mapped io address */ + resource_size_t phys_iobase; /* Physical io address */ + unsigned int AdcCmdStatus; /* ADC Command/Status register */ + unsigned int DacCmdStatus; /* DAC Command/Status register */ + unsigned int IntEnable; /* Interrupt Enable register */ + unsigned int IntStatus; /* Interrupt Status register */ + unsigned int act_chanlist[32]; /* list of scaned channel */ + unsigned char act_chanlist_len; /* len of scanlist */ + unsigned char act_chanlist_pos; /* actual position in MUX list */ + unsigned int *ai_chanlist; /* actaul chanlist */ + short *ai_data; /* data buffer */ + short ao_data[4]; /* data output buffer */ + short di_data; /* Digital input data */ + unsigned int do_data; /* Remember digital output data */ +}; -#define devpriv ((icp_multi_private *)dev->private) -#define this_board ((const boardtype *)dev->board_ptr) +#define devpriv ((struct icp_multi_private *)dev->private) +#define this_board ((const struct boardtype *)dev->board_ptr) /* ============================================================================== @@ -214,12 +214,12 @@ typedef struct { */ #if 0 -static int check_channel_list(comedi_device * dev, comedi_subdevice * s, +static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int *chanlist, unsigned int n_chan); #endif -static void setup_channel_list(comedi_device * dev, comedi_subdevice * s, +static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int *chanlist, unsigned int n_chan); -static int icp_multi_reset(comedi_device * dev); +static int icp_multi_reset(struct comedi_device *dev); /* ============================================================================== @@ -236,32 +236,32 @@ static int icp_multi_reset(comedi_device * dev); This function reads a single analogue input. Parameters: - comedi_device *dev Pointer to current device structure - comedi_subdevice *s Pointer to current subdevice structure - comedi_insn *insn Pointer to current comedi instruction - lsampl_t *data Pointer to analogue input data + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue input data Returns:int Nmuber of instructions executed ============================================================================== */ -static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int icp_multi_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n, timeout; #ifdef ICP_MULTI_EXTDEBUG printk("icp multi EDBG: BGN: icp_multi_insn_read_ai(...)\n"); #endif - // Disable A/D conversion ready interrupt + /* Disable A/D conversion ready interrupt */ devpriv->IntEnable &= ~ADC_READY; writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); - // Clear interrupt status + /* Clear interrupt status */ devpriv->IntStatus |= ADC_READY; writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); - // Set up appropriate channel, mode and range data, for specified channel + /* Set up appropriate channel, mode and range data, for specified channel */ setup_channel_list(dev, s, &insn->chanspec, 1); #ifdef ICP_MULTI_EXTDEBUG @@ -271,7 +271,7 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s, #endif for (n = 0; n < insn->n; n++) { - // Set start ADC bit + /* Set start ADC bit */ devpriv->AdcCmdStatus |= ADC_ST; writew(devpriv->AdcCmdStatus, devpriv->io_addr + ICP_MULTI_ADC_CSR); @@ -289,7 +289,7 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s, readw(devpriv->io_addr + ICP_MULTI_ADC_CSR)); #endif - // Wait for conversion to complete, or get fed up waiting + /* Wait for conversion to complete, or get fed up waiting */ timeout = 100; while (timeout--) { if (!(readw(devpriv->io_addr + @@ -307,19 +307,19 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s, comedi_udelay(1); } - // If we reach here, a timeout has occurred + /* If we reach here, a timeout has occurred */ comedi_error(dev, "A/D insn timeout"); - // Disable interrupt + /* Disable interrupt */ devpriv->IntEnable &= ~ADC_READY; writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); - // Clear interrupt status + /* Clear interrupt status */ devpriv->IntStatus |= ADC_READY; writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); - // Clear data received + /* Clear data received */ data[n] = 0; #ifdef ICP_MULTI_EXTDEBUG @@ -332,11 +332,11 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s, (readw(devpriv->io_addr + ICP_MULTI_AI) >> 4) & 0x0fff; } - // Disable interrupt + /* Disable interrupt */ devpriv->IntEnable &= ~ADC_READY; writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); - // Clear interrupt status + /* Clear interrupt status */ devpriv->IntStatus |= ADC_READY; writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); @@ -355,40 +355,40 @@ static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s, This function writes a single analogue output. Parameters: - comedi_device *dev Pointer to current device structure - comedi_subdevice *s Pointer to current subdevice structure - comedi_insn *insn Pointer to current comedi instruction - lsampl_t *data Pointer to analogue output data + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data Returns:int Nmuber of instructions executed ============================================================================== */ -static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int icp_multi_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n, chan, range, timeout; #ifdef ICP_MULTI_EXTDEBUG printk("icp multi EDBG: BGN: icp_multi_insn_write_ao(...)\n"); #endif - // Disable D/A conversion ready interrupt + /* Disable D/A conversion ready interrupt */ devpriv->IntEnable &= ~DAC_READY; writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); - // Clear interrupt status + /* Clear interrupt status */ devpriv->IntStatus |= DAC_READY; writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); - // Get channel number and range + /* Get channel number and range */ chan = CR_CHAN(insn->chanspec); range = CR_RANGE(insn->chanspec); - // Set up range and channel data - // Bit 4 = 1 : Bipolar - // Bit 5 = 0 : 5V - // Bit 5 = 1 : 10V - // Bits 8-9 : Channel number + /* Set up range and channel data */ + /* Bit 4 = 1 : Bipolar */ + /* Bit 5 = 0 : 5V */ + /* Bit 5 = 1 : 10V */ + /* Bits 8-9 : Channel number */ devpriv->DacCmdStatus &= 0xfccf; devpriv->DacCmdStatus |= this_board->rangecode[range]; devpriv->DacCmdStatus |= (chan << 8); @@ -396,7 +396,7 @@ static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s, writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR); for (n = 0; n < insn->n; n++) { - // Wait for analogue output data register to be ready for new data, or get fed up waiting + /* Wait for analogue output data register to be ready for new data, or get fed up waiting */ timeout = 100; while (timeout--) { if (!(readw(devpriv->io_addr + @@ -414,19 +414,19 @@ static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s, comedi_udelay(1); } - // If we reach here, a timeout has occurred + /* If we reach here, a timeout has occurred */ comedi_error(dev, "D/A insn timeout"); - // Disable interrupt + /* Disable interrupt */ devpriv->IntEnable &= ~DAC_READY; writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN); - // Clear interrupt status + /* Clear interrupt status */ devpriv->IntStatus |= DAC_READY; writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT); - // Clear data received + /* Clear data received */ devpriv->ao_data[chan] = 0; #ifdef ICP_MULTI_EXTDEBUG @@ -435,16 +435,16 @@ static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s, return -ETIME; dac_ready: - // Write data to analogue output data register + /* Write data to analogue output data register */ writew(data[n], devpriv->io_addr + ICP_MULTI_AO); - // Set DAC_ST bit to write the data to selected channel + /* Set DAC_ST bit to write the data to selected channel */ devpriv->DacCmdStatus |= DAC_ST; writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR); devpriv->DacCmdStatus &= ~DAC_ST; - // Save analogue output data + /* Save analogue output data */ devpriv->ao_data[chan] = data[n]; } @@ -463,24 +463,24 @@ static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s, This function reads a single analogue output. Parameters: - comedi_device *dev Pointer to current device structure - comedi_subdevice *s Pointer to current subdevice structure - comedi_insn *insn Pointer to current comedi instruction - lsampl_t *data Pointer to analogue output data + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data Returns:int Nmuber of instructions executed ============================================================================== */ -static int icp_multi_insn_read_ao(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int icp_multi_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n, chan; - // Get channel number + /* Get channel number */ chan = CR_CHAN(insn->chanspec); - // Read analogue outputs + /* Read analogue outputs */ for (n = 0; n < insn->n; n++) data[n] = devpriv->ao_data[chan]; @@ -496,17 +496,17 @@ static int icp_multi_insn_read_ao(comedi_device * dev, comedi_subdevice * s, This function reads the digital inputs. Parameters: - comedi_device *dev Pointer to current device structure - comedi_subdevice *s Pointer to current subdevice structure - comedi_insn *insn Pointer to current comedi instruction - lsampl_t *data Pointer to analogue output data + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data Returns:int Nmuber of instructions executed ============================================================================== */ -static int icp_multi_insn_bits_di(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int icp_multi_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { data[1] = readw(devpriv->io_addr + ICP_MULTI_DI); @@ -522,17 +522,17 @@ static int icp_multi_insn_bits_di(comedi_device * dev, comedi_subdevice * s, This function writes the appropriate digital outputs. Parameters: - comedi_device *dev Pointer to current device structure - comedi_subdevice *s Pointer to current subdevice structure - comedi_insn *insn Pointer to current comedi instruction - lsampl_t *data Pointer to analogue output data + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to analogue output data Returns:int Nmuber of instructions executed ============================================================================== */ -static int icp_multi_insn_bits_do(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int icp_multi_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { #ifdef ICP_MULTI_EXTDEBUG printk("icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n"); @@ -564,17 +564,17 @@ static int icp_multi_insn_bits_do(comedi_device * dev, comedi_subdevice * s, This function reads the specified counter. Parameters: - comedi_device *dev Pointer to current device structure - comedi_subdevice *s Pointer to current subdevice structure - comedi_insn *insn Pointer to current comedi instruction - lsampl_t *data Pointer to counter data + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to counter data Returns:int Nmuber of instructions executed ============================================================================== */ -static int icp_multi_insn_read_ctr(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int icp_multi_insn_read_ctr(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { return 0; } @@ -588,17 +588,17 @@ static int icp_multi_insn_read_ctr(comedi_device * dev, comedi_subdevice * s, This function write to the specified counter. Parameters: - comedi_device *dev Pointer to current device structure - comedi_subdevice *s Pointer to current subdevice structure - comedi_insn *insn Pointer to current comedi instruction - lsampl_t *data Pointer to counter data + struct comedi_device *dev Pointer to current device structure + struct comedi_subdevice *s Pointer to current subdevice structure + struct comedi_insn *insn Pointer to current comedi instruction + unsigned int *data Pointer to counter data Returns:int Nmuber of instructions executed ============================================================================== */ -static int icp_multi_insn_write_ctr(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int icp_multi_insn_write_ctr(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { return 0; } @@ -620,7 +620,7 @@ static int icp_multi_insn_write_ctr(comedi_device * dev, comedi_subdevice * s, */ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG) { - comedi_device *dev = d; + struct comedi_device *dev = d; int int_no; #ifdef ICP_MULTI_EXTDEBUG @@ -628,10 +628,10 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG) irq); #endif - // Is this interrupt from our board? + /* Is this interrupt from our board? */ int_no = readw(devpriv->io_addr + ICP_MULTI_INT_STAT) & Status_IRQ; if (!int_no) - // No, exit + /* No, exit */ return IRQ_NONE; #ifdef ICP_MULTI_EXTDEBUG @@ -639,7 +639,7 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG) readw(devpriv->io_addr + ICP_MULTI_INT_STAT)); #endif - // Determine which interrupt is active & handle it + /* Determine which interrupt is active & handle it */ switch (int_no) { case ADC_READY: break; @@ -679,8 +679,8 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG) is built correctly Parameters: - comedi_device *dev Pointer to current sevice structure - comedi_subdevice *s Pointer to current subdevice structure + struct comedi_device *dev Pointer to current sevice structure + struct comedi_subdevice *s Pointer to current subdevice structure unsigned int *chanlist Pointer to packed channel list unsigned int n_chan Number of channels to scan @@ -689,7 +689,7 @@ static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG) ============================================================================== */ -static int check_channel_list(comedi_device * dev, comedi_subdevice * s, +static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int *chanlist, unsigned int n_chan) { unsigned int i; @@ -697,14 +697,14 @@ static int check_channel_list(comedi_device * dev, comedi_subdevice * s, #ifdef ICP_MULTI_EXTDEBUG printk("icp multi EDBG: check_channel_list(...,%d)\n", n_chan); #endif - // Check that we at least have one channel to check + /* Check that we at least have one channel to check */ if (n_chan < 1) { comedi_error(dev, "range/channel list is empty!"); return 0; } - // Check all channels + /* Check all channels */ for (i = 0; i < n_chan; i++) { - // Check that channel number is < maximum + /* Check that channel number is < maximum */ if (CR_AREF(chanlist[i]) == AREF_DIFF) { if (CR_CHAN(chanlist[i]) > this_board->n_aichand) { comedi_error(dev, @@ -734,8 +734,8 @@ static int check_channel_list(comedi_device * dev, comedi_subdevice * s, Status register. Parameters: - comedi_device *dev Pointer to current sevice structure - comedi_subdevice *s Pointer to current subdevice structure + struct comedi_device *dev Pointer to current sevice structure + struct comedi_subdevice *s Pointer to current subdevice structure unsigned int *chanlist Pointer to packed channel list unsigned int n_chan Number of channels to scan @@ -743,7 +743,7 @@ static int check_channel_list(comedi_device * dev, comedi_subdevice * s, ============================================================================== */ -static void setup_channel_list(comedi_device * dev, comedi_subdevice * s, +static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int *chanlist, unsigned int n_chan) { unsigned int i, range, chanprog; @@ -756,10 +756,10 @@ static void setup_channel_list(comedi_device * dev, comedi_subdevice * s, devpriv->act_chanlist_pos = 0; for (i = 0; i < n_chan; i++) { - // Get channel + /* Get channel */ chanprog = CR_CHAN(chanlist[i]); - // Determine if it is a differential channel (Bit 15 = 1) + /* Determine if it is a differential channel (Bit 15 = 1) */ if (CR_AREF(chanlist[i]) == AREF_DIFF) { diff = 1; chanprog &= 0x0007; @@ -768,21 +768,21 @@ static void setup_channel_list(comedi_device * dev, comedi_subdevice * s, chanprog &= 0x000f; } - // Clear channel, range and input mode bits in A/D command/status register + /* Clear channel, range and input mode bits in A/D command/status register */ devpriv->AdcCmdStatus &= 0xf00f; - // Set channel number and differential mode status bit + /* Set channel number and differential mode status bit */ if (diff) { - // Set channel number, bits 9-11 & mode, bit 6 + /* Set channel number, bits 9-11 & mode, bit 6 */ devpriv->AdcCmdStatus |= (chanprog << 9); devpriv->AdcCmdStatus |= ADC_DI; } else - // Set channel number, bits 8-11 + /* Set channel number, bits 8-11 */ devpriv->AdcCmdStatus |= (chanprog << 8); - // Get range for current channel + /* Get range for current channel */ range = this_board->rangecode[CR_RANGE(chanlist[i])]; - // Set range. bits 4-5 + /* Set range. bits 4-5 */ devpriv->AdcCmdStatus |= range; /* Output channel, range, mode to ICP Multi */ @@ -806,45 +806,45 @@ static void setup_channel_list(comedi_device * dev, comedi_subdevice * s, This function resets the icp multi device to a 'safe' state Parameters: - comedi_device *dev Pointer to current sevice structure + struct comedi_device *dev Pointer to current sevice structure Returns:int 0 = success ============================================================================== */ -static int icp_multi_reset(comedi_device * dev) +static int icp_multi_reset(struct comedi_device *dev) { unsigned int i; #ifdef ICP_MULTI_EXTDEBUG printk("icp_multi EDBG: BGN: icp_multi_reset(...)\n"); #endif - // Clear INT enables and requests + /* Clear INT enables and requests */ writew(0, devpriv->io_addr + ICP_MULTI_INT_EN); writew(0x00ff, devpriv->io_addr + ICP_MULTI_INT_STAT); if (this_board->n_aochan) - // Set DACs to 0..5V range and 0V output + /* Set DACs to 0..5V range and 0V output */ for (i = 0; i < this_board->n_aochan; i++) { devpriv->DacCmdStatus &= 0xfcce; - // Set channel number + /* Set channel number */ devpriv->DacCmdStatus |= (i << 8); - // Output 0V + /* Output 0V */ writew(0, devpriv->io_addr + ICP_MULTI_AO); - // Set start conversion bit + /* Set start conversion bit */ devpriv->DacCmdStatus |= DAC_ST; - // Output to command / status register + /* Output to command / status register */ writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR); - // Delay to allow DAC time to recover + /* Delay to allow DAC time to recover */ comedi_udelay(1); } - // Digital outputs to 0 + /* Digital outputs to 0 */ writew(0, devpriv->io_addr + ICP_MULTI_DO); #ifdef ICP_MULTI_EXTDEBUG @@ -863,16 +863,16 @@ static int icp_multi_reset(comedi_device * dev) device. Parameters: - comedi_device *dev Pointer to current device structure - comedi_devconfig *it Pointer to current device configuration + struct comedi_device *dev Pointer to current device structure + struct comedi_devconfig *it Pointer to current device configuration Returns:int 0 = success ============================================================================== */ -static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it) +static int icp_multi_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - comedi_subdevice *s; + struct comedi_subdevice *s; int ret, subdev, n_subdevices; unsigned int irq; struct pcilst_struct *card = NULL; @@ -881,11 +881,12 @@ static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it) printk("icp_multi EDBG: BGN: icp_multi_attach(...)\n"); - // Alocate private data storage space - if ((ret = alloc_private(dev, sizeof(icp_multi_private))) < 0) + /* Alocate private data storage space */ + ret = alloc_private(dev, sizeof(struct icp_multi_private)); + if (ret < 0) return ret; - // Initialise list of PCI cards in system, if not already done so + /* Initialise list of PCI cards in system, if not already done so */ if (pci_list_builded++ == 0) { pci_card_list_init(PCI_VENDOR_ID_ICP, #ifdef ICP_MULTI_EXTDEBUG @@ -899,9 +900,11 @@ static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it) printk("Anne's comedi%d: icp_multi: board=%s", dev->minor, this_board->name); - if ((card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP, - this_board->device_id, it->options[0], - it->options[1])) == NULL) + card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP, + this_board->device_id, it->options[0], + it->options[1]); + + if (card == NULL) return -EIO; devpriv->card = card; @@ -943,9 +946,9 @@ static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it) if (this_board->n_ctrs) n_subdevices++; - if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) { + ret = alloc_subdevices(dev, n_subdevices); + if (ret < 0) return ret; - } icp_multi_reset(dev); @@ -1055,13 +1058,13 @@ static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it) device. Parameters: - comedi_device *dev Pointer to current device structure + struct comedi_device *dev Pointer to current device structure Returns:int 0 = success ============================================================================== */ -static int icp_multi_detach(comedi_device * dev) +static int icp_multi_detach(struct comedi_device *dev) { if (dev->private) @@ -1077,9 +1080,8 @@ static int icp_multi_detach(comedi_device * dev) if (dev->private && devpriv->card) pci_card_free(devpriv->card); - if (--pci_list_builded == 0) { + if (--pci_list_builded == 0) pci_card_list_cleanup(PCI_VENDOR_ID_ICP); - } return 0; } diff --git a/drivers/staging/comedi/drivers/icp_multi.h b/drivers/staging/comedi/drivers/icp_multi.h index 6df4a8d15ff2..21d84766fea8 100644 --- a/drivers/staging/comedi/drivers/icp_multi.h +++ b/drivers/staging/comedi/drivers/icp_multi.h @@ -28,7 +28,8 @@ struct pcilst_struct { unsigned int irq; }; -struct pcilst_struct *inova_devices; // ptr to root list of all Inova devices +struct pcilst_struct *inova_devices; +/* ptr to root list of all Inova devices */ /****************************************************************************/ @@ -150,14 +151,14 @@ static int find_free_pci_card_by_position(unsigned short vendor_id, && (inova->pci_slot == pci_slot)) { if (!(inova->used)) { *card = inova; - return 0; // ok, card is found + return 0; /* ok, card is found */ } else { - return 2; // card exist but is used + return 2; /* card exist but is used */ } } } - return 1; // no card found + return 1; /* no card found */ } /****************************************************************************/ @@ -243,9 +244,10 @@ static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, struct pcilst_struct *card; int err; - if ((pci_bus < 1) & (pci_slot < 1)) { // use autodetection - if ((card = find_free_pci_card_by_device(vendor_id, - device_id)) == NULL) { + if ((pci_bus < 1) & (pci_slot < 1)) { /* use autodetection */ + + card = find_free_pci_card_by_device(vendor_id, device_id); + if (card == NULL) { rt_printk(" - Unused card not found in system!\n"); return NULL; } @@ -265,7 +267,8 @@ static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, } } - if ((err = pci_card_alloc(card)) != 0) { + err = pci_card_alloc(card); + if (err != 0) { if (err > 0) rt_printk(" - Can't allocate card!\n"); /* else: error already printed. */ diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c new file mode 100644 index 000000000000..80825ba25418 --- /dev/null +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -0,0 +1,612 @@ +/* + * comedi/drivers/ii_pci20kc.c + * Driver for Intelligent Instruments PCI-20001C carrier board + * and modules. + * + * Copyright (C) 2000 Markus Kempf + * with suggestions from David Schleef + * 16.06.2000 + * + * Linux device driver for COMEDI + * Intelligent Instrumentation + * PCI-20001 C-2A Carrier Board + * PCI-20341 M-1A 16-Bit analog input module + * - differential + * - range (-5V - +5V) + * - 16 bit + * PCI-20006 M-2 16-Bit analog output module + * - ranges (-10V - +10V) (0V - +10V) (-5V - +5V) + * - 16 bit + * + * only ONE PCI-20341 module possible + * only ONE PCI-20006 module possible + * no extern trigger implemented + * + * NOT WORKING (but soon) only 4 on-board differential channels supported + * NOT WORKING (but soon) only ONE di-port and ONE do-port supported instead of 4 digital ports + * di-port == Port 0 + * do-port == Port 1 + * + * The state of this driver is only a starting point for a complete + * COMEDI-driver. The final driver should support all features of the + * carrier board and modules. + * + * The test configuration: + * + * kernel 2.2.14 with RTAI v1.2 and patch-2.2.14rthal2 + * COMEDI 0.7.45 + * COMEDILIB 0.7.9 + * + */ +/* +Driver: ii_pci20kc +Description: Intelligent Instruments PCI-20001C carrier board +Author: Markus Kempf +Devices: [Intelligent Instrumentation] PCI-20001C (ii_pci20kc) +Status: works + +Supports the PCI-20001 C-2a Carrier board, and could probably support +the other carrier boards with small modifications. Modules supported +are: + PCI-20006 M-2 16-bit analog output module + PCI-20341 M-1A 16-bit analog input module + +Options: + 0 Board base address + 1 IRQ + 2 first option for module 1 + 3 second option for module 1 + 4 first option for module 2 + 5 second option for module 2 + 6 first option for module 3 + 7 second option for module 3 + +options for PCI-20006M: + first: Analog output channel 0 range configuration + 0 bipolar 10 (-10V -- +10V) + 1 unipolar 10 (0V -- +10V) + 2 bipolar 5 (-5V -- 5V) + second: Analog output channel 1 range configuration + +options for PCI-20341M: + first: Analog input gain configuration + 0 1 + 1 10 + 2 100 + 3 200 +*/ + +/* XXX needs to use ioremap() for compatibility with 2.4 kernels. Should also + * check_mem_region() etc. - fmhess */ + +#include "../comedidev.h" + +#define PCI20000_ID 0x1d +#define PCI20341_ID 0x77 +#define PCI20006_ID 0xe3 +#define PCI20xxx_EMPTY_ID 0xff + +#define PCI20000_OFFSET 0x100 +#define PCI20000_MODULES 3 + +#define PCI20000_DIO_0 0x80 +#define PCI20000_DIO_1 0x81 +#define PCI20000_DIO_2 0xc0 +#define PCI20000_DIO_3 0xc1 +#define PCI20000_DIO_CONTROL_01 0x83 /* port 0, 1 control */ +#define PCI20000_DIO_CONTROL_23 0xc3 /* port 2, 3 control */ +#define PCI20000_DIO_BUFFER 0x82 /* buffer direction and enable */ +#define PCI20000_DIO_EOC 0xef /* even port, control output */ +#define PCI20000_DIO_OOC 0xfd /* odd port, control output */ +#define PCI20000_DIO_EIC 0x90 /* even port, control input */ +#define PCI20000_DIO_OIC 0x82 /* odd port, control input */ +#define DIO_CAND 0x12 /* and bit 1, bit 4 of control */ +#define DIO_BE 0x01 /* buffer: port enable */ +#define DIO_BO 0x04 /* buffer: output */ +#define DIO_BI 0x05 /* buffer: input */ +#define DIO_PS_0 0x00 /* buffer: port shift 0 */ +#define DIO_PS_1 0x01 /* buffer: port shift 1 */ +#define DIO_PS_2 0x04 /* buffer: port shift 2 */ +#define DIO_PS_3 0x05 /* buffer: port shift 3 */ + +#define PCI20006_LCHAN0 0x0d +#define PCI20006_STROBE0 0x0b +#define PCI20006_LCHAN1 0x15 +#define PCI20006_STROBE1 0x13 + +#define PCI20341_INIT 0x04 +#define PCI20341_REPMODE 0x00 /* single shot mode */ +#define PCI20341_PACER 0x00 /* Hardware Pacer disabled */ +#define PCI20341_CHAN_NR 0x04 /* number of input channels */ +#define PCI20341_CONFIG_REG 0x10 +#define PCI20341_MOD_STATUS 0x01 +#define PCI20341_OPT_REG 0x11 +#define PCI20341_SET_TIME_REG 0x15 +#define PCI20341_LCHAN_ADDR_REG 0x13 +#define PCI20341_CHAN_LIST 0x80 +#define PCI20341_CC_RESET 0x1b +#define PCI20341_CHAN_RESET 0x19 +#define PCI20341_SOFT_PACER 0x04 +#define PCI20341_STATUS_REG 0x12 +#define PCI20341_LDATA 0x02 +#define PCI20341_DAISY_CHAIN 0x20 /* On-board inputs only */ +#define PCI20341_MUX 0x04 /* Enable on-board MUX */ +#define PCI20341_SCANLIST 0x80 /* Channel/Gain Scan List */ + +union pci20xxx_subdev_private { + void *iobase; + struct { + void *iobase; + const struct comedi_lrange *ao_range_list[2]; /* range of channels of ao module */ + unsigned int last_data[2]; + } pci20006; + struct { + void *iobase; + int timebase; + int settling_time; + int ai_gain; + } pci20341; +}; + +struct pci20xxx_private { + + void *ioaddr; + union pci20xxx_subdev_private subdev_private[PCI20000_MODULES]; +}; + + +#define devpriv ((struct pci20xxx_private *)dev->private) +#define CHAN (CR_CHAN(it->chanlist[0])) + +static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pci20xxx_detach(struct comedi_device * dev); + +static struct comedi_driver driver_pci20xxx = { + driver_name:"ii_pci20kc", + module:THIS_MODULE, + attach:pci20xxx_attach, + detach:pci20xxx_detach, +}; + +static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s, + int opt0, int opt1); +static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s, + int opt0, int opt1); +static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice * s); + +/* + options[0] Board base address + options[1] IRQ + options[2] first option for module 1 + options[3] second option for module 1 + options[4] first option for module 2 + options[5] second option for module 2 + options[6] first option for module 3 + options[7] second option for module 3 + + options for PCI-20341M: + first Analog input gain configuration + 0 == 1 + 1 == 10 + 2 == 100 + 3 == 200 + + options for PCI-20006M: + first Analog output channel 0 range configuration + 0 == bipolar 10 (-10V -- +10V) + 1 == unipolar 10V (0V -- +10V) + 2 == bipolar 5V (-5V -- +5V) + second Analog output channel 1 range configuration + 0 == bipolar 10 (-10V -- +10V) + 1 == unipolar 10V (0V -- +10V) + 2 == bipolar 5V (-5V -- +5V) +*/ +static int pci20xxx_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + unsigned char i; + int ret; + int id; + struct comedi_subdevice *s; + union pci20xxx_subdev_private *sdp; + + if ((ret = alloc_subdevices(dev, 1 + PCI20000_MODULES)) < 0) + return ret; + if ((ret = alloc_private(dev, sizeof(struct pci20xxx_private))) < 0) + return ret; + + devpriv->ioaddr = (void *)(unsigned long)it->options[0]; + dev->board_name = "pci20kc"; + + /* Check PCI-20001 C-2A Carrier Board ID */ + if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) { + printk("comedi%d: ii_pci20kc", dev->minor); + printk(" PCI-20001 C-2A Carrier Board at base=0x%p not found !\n", devpriv->ioaddr); + return -EINVAL; + } + printk("comedi%d:\n", dev->minor); + printk("ii_pci20kc: PCI-20001 C-2A at base=0x%p\n", devpriv->ioaddr); + + for (i = 0; i < PCI20000_MODULES; i++) { + s = dev->subdevices + i; + id = readb(devpriv->ioaddr + (i + 1) * PCI20000_OFFSET); + s->private = devpriv->subdev_private + i; + sdp = s->private; + switch (id) { + case PCI20006_ID: + sdp->pci20006.iobase = + devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; + pci20006_init(dev, s, it->options[2 * i + 2], + it->options[2 * i + 3]); + printk("comedi%d: ii_pci20kc", dev->minor); + printk(" PCI-20006 module in slot %d \n", i + 1); + break; + case PCI20341_ID: + sdp->pci20341.iobase = + devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; + pci20341_init(dev, s, it->options[2 * i + 2], + it->options[2 * i + 3]); + printk("comedi%d: ii_pci20kc", dev->minor); + printk(" PCI-20341 module in slot %d \n", i + 1); + break; + default: + printk("ii_pci20kc: unknown module code 0x%02x in slot %d: module disabled\n", id, i); + /* fall through */ + case PCI20xxx_EMPTY_ID: + s->type = COMEDI_SUBD_UNUSED; + break; + } + } + + /* initialize struct pci20xxx_private */ + pci20xxx_dio_init(dev, dev->subdevices + PCI20000_MODULES); + + return 1; +} + +static int pci20xxx_detach(struct comedi_device * dev) +{ + printk("comedi%d: pci20xxx: remove\n", dev->minor); + + return 0; +} + +/* pci20006m */ + +static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static const struct comedi_lrange *pci20006_range_list[] = { + &range_bipolar10, + &range_unipolar10, + &range_bipolar5, +}; + +static int pci20006_init(struct comedi_device * dev, struct comedi_subdevice * s, + int opt0, int opt1) +{ + union pci20xxx_subdev_private *sdp = s->private; + + if (opt0 < 0 || opt0 > 2) + opt0 = 0; + if (opt1 < 0 || opt1 > 2) + opt1 = 0; + + sdp->pci20006.ao_range_list[0] = pci20006_range_list[opt0]; + sdp->pci20006.ao_range_list[1] = pci20006_range_list[opt1]; + + /* ao subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->len_chanlist = 2; + s->insn_read = pci20006_insn_read; + s->insn_write = pci20006_insn_write; + s->maxdata = 0xffff; + s->range_table_list = sdp->pci20006.ao_range_list; + return 0; +} + +static int pci20006_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + union pci20xxx_subdev_private *sdp = s->private; + + data[0] = sdp->pci20006.last_data[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int pci20006_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + union pci20xxx_subdev_private *sdp = s->private; + int hi, lo; + unsigned int boarddata; + + sdp->pci20006.last_data[CR_CHAN(insn->chanspec)] = data[0]; + boarddata = (((unsigned int)data[0] + 0x8000) & 0xffff); /* comedi-data -> board-data */ + lo = (boarddata & 0xff); + hi = ((boarddata >> 8) & 0xff); + + switch (CR_CHAN(insn->chanspec)) { + case 0: + writeb(lo, sdp->iobase + PCI20006_LCHAN0); + writeb(hi, sdp->iobase + PCI20006_LCHAN0 + 1); + writeb(0x00, sdp->iobase + PCI20006_STROBE0); + break; + case 1: + writeb(lo, sdp->iobase + PCI20006_LCHAN1); + writeb(hi, sdp->iobase + PCI20006_LCHAN1 + 1); + writeb(0x00, sdp->iobase + PCI20006_STROBE1); + break; + default: + printk(" comedi%d: pci20xxx: ao channel Error!\n", dev->minor); + return -EINVAL; + } + + return 1; +} + +/* PCI20341M */ + +static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 }; +static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; + +static const struct comedi_lrange range_bipolar0_5 = { 1, {BIP_RANGE(0.5)} }; +static const struct comedi_lrange range_bipolar0_05 = { 1, {BIP_RANGE(0.05)} }; +static const struct comedi_lrange range_bipolar0_025 = { 1, {BIP_RANGE(0.025)} }; + +static const struct comedi_lrange *const pci20341_ranges[] = { + &range_bipolar5, + &range_bipolar0_5, + &range_bipolar0_05, + &range_bipolar0_025, +}; + +static int pci20341_init(struct comedi_device * dev, struct comedi_subdevice * s, + int opt0, int opt1) +{ + union pci20xxx_subdev_private *sdp = s->private; + int option; + + /* options handling */ + if (opt0 < 0 || opt0 > 3) + opt0 = 0; + sdp->pci20341.timebase = pci20341_timebase[opt0]; + sdp->pci20341.settling_time = pci20341_settling_time[opt0]; + + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE; + s->n_chan = PCI20341_CHAN_NR; + s->len_chanlist = PCI20341_SCANLIST; + s->insn_read = pci20341_insn_read; + s->maxdata = 0xffff; + s->range_table = pci20341_ranges[opt0]; + + option = sdp->pci20341.timebase | PCI20341_REPMODE; /* depends on gain, trigger, repetition mode */ + + writeb(PCI20341_INIT, sdp->iobase + PCI20341_CONFIG_REG); /* initialize Module */ + writeb(PCI20341_PACER, sdp->iobase + PCI20341_MOD_STATUS); /* set Pacer */ + writeb(option, sdp->iobase + PCI20341_OPT_REG); /* option register */ + writeb(sdp->pci20341.settling_time, sdp->iobase + PCI20341_SET_TIME_REG); /* settling time counter */ + /* trigger not implemented */ + return 0; +} + +static int pci20341_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + union pci20xxx_subdev_private *sdp = s->private; + unsigned int i = 0, j = 0; + int lo, hi; + unsigned char eoc; /* end of conversion */ + unsigned int clb; /* channel list byte */ + unsigned int boarddata; + + writeb(1, sdp->iobase + PCI20341_LCHAN_ADDR_REG); /* write number of input channels */ + clb = PCI20341_DAISY_CHAIN | PCI20341_MUX | (sdp->pci20341.ai_gain << 3) + | CR_CHAN(insn->chanspec); + writeb(clb, sdp->iobase + PCI20341_CHAN_LIST); + writeb(0x00, sdp->iobase + PCI20341_CC_RESET); /* reset settling time counter and trigger delay counter */ + writeb(0x00, sdp->iobase + PCI20341_CHAN_RESET); + + /* generate Pacer */ + + for (i = 0; i < insn->n; i++) { + /* data polling isn't the niciest way to get the data, I know, + * but there are only 6 cycles (mean) and it is easier than + * the whole interrupt stuff + */ + j = 0; + readb(sdp->iobase + PCI20341_SOFT_PACER); /* generate Pacer */ + eoc = readb(sdp->iobase + PCI20341_STATUS_REG); + while ((eoc < 0x80) && j < 100) { /* poll Interrupt Flag */ + j++; + eoc = readb(sdp->iobase + PCI20341_STATUS_REG); + } + if (j >= 100) { + printk("comedi%d: pci20xxx: AI interrupt channel %i polling exit !\n", dev->minor, i); + return -EINVAL; + } + lo = readb(sdp->iobase + PCI20341_LDATA); + hi = readb(sdp->iobase + PCI20341_LDATA + 1); + boarddata = lo + 0x100 * hi; + data[i] = (short) ((boarddata + 0x8000) & 0xffff); /* board-data -> comedi-data */ + } + + return i; +} + +/* native DIO */ + +static void pci20xxx_dio_config(struct comedi_device * dev, struct comedi_subdevice * s); +static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +/* initialize struct pci20xxx_private */ +static int pci20xxx_dio_init(struct comedi_device * dev, struct comedi_subdevice * s) +{ + + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 32; + s->insn_bits = pci20xxx_dio_insn_bits; + s->insn_config = pci20xxx_dio_insn_config; + s->maxdata = 1; + s->len_chanlist = 32; + s->range_table = &range_digital; + s->io_bits = 0; + + /* digital I/O lines default to input on board reset. */ + pci20xxx_dio_config(dev, s); + + return 0; +} + +static int pci20xxx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int mask, bits; + + mask = 1 << CR_CHAN(insn->chanspec); + if (mask & 0x000000ff) { + bits = 0x000000ff; + } else if (mask & 0x0000ff00) { + bits = 0x0000ff00; + } else if (mask & 0x00ff0000) { + bits = 0x00ff0000; + } else { + bits = 0xff000000; + } + if (data[0]) { + s->io_bits |= bits; + } else { + s->io_bits &= ~bits; + } + pci20xxx_dio_config(dev, s); + + return 1; +} + +static int pci20xxx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int mask = data[0]; + + s->state &= ~mask; + s->state |= (mask & data[1]); + + mask &= s->io_bits; + if (mask & 0x000000ff) + writeb((s->state >> 0) & 0xff, + devpriv->ioaddr + PCI20000_DIO_0); + if (mask & 0x0000ff00) + writeb((s->state >> 8) & 0xff, + devpriv->ioaddr + PCI20000_DIO_1); + if (mask & 0x00ff0000) + writeb((s->state >> 16) & 0xff, + devpriv->ioaddr + PCI20000_DIO_2); + if (mask & 0xff000000) + writeb((s->state >> 24) & 0xff, + devpriv->ioaddr + PCI20000_DIO_3); + + data[1] = readb(devpriv->ioaddr + PCI20000_DIO_0); + data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8; + data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16; + data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_3) << 24; + + return 2; +} + +static void pci20xxx_dio_config(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned char control_01; + unsigned char control_23; + unsigned char buffer; + + control_01 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_01); + control_23 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_23); + buffer = readb(devpriv->ioaddr + PCI20000_DIO_BUFFER); + + if (s->io_bits & 0x000000ff) { + /* output port 0 */ + control_01 &= PCI20000_DIO_EOC; + buffer = (buffer & (~(DIO_BE << DIO_PS_0))) | (DIO_BO << + DIO_PS_0); + } else { + /* input port 0 */ + control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_EIC; + buffer = (buffer & (~(DIO_BI << DIO_PS_0))); + } + if (s->io_bits & 0x0000ff00) { + /* output port 1 */ + control_01 &= PCI20000_DIO_OOC; + buffer = (buffer & (~(DIO_BE << DIO_PS_1))) | (DIO_BO << + DIO_PS_1); + } else { + /* input port 1 */ + control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_OIC; + buffer = (buffer & (~(DIO_BI << DIO_PS_1))); + } + if (s->io_bits & 0x00ff0000) { + /* output port 2 */ + control_23 &= PCI20000_DIO_EOC; + buffer = (buffer & (~(DIO_BE << DIO_PS_2))) | (DIO_BO << + DIO_PS_2); + } else { + /* input port 2 */ + control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_EIC; + buffer = (buffer & (~(DIO_BI << DIO_PS_2))); + } + if (s->io_bits & 0xff000000) { + /* output port 3 */ + control_23 &= PCI20000_DIO_OOC; + buffer = (buffer & (~(DIO_BE << DIO_PS_3))) | (DIO_BO << + DIO_PS_3); + } else { + /* input port 3 */ + control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_OIC; + buffer = (buffer & (~(DIO_BI << DIO_PS_3))); + } + writeb(control_01, devpriv->ioaddr + PCI20000_DIO_CONTROL_01); + writeb(control_23, devpriv->ioaddr + PCI20000_DIO_CONTROL_23); + writeb(buffer, devpriv->ioaddr + PCI20000_DIO_BUFFER); +} + +#if 0 +static void pci20xxx_do(struct comedi_device * dev, struct comedi_subdevice * s) +{ + /* XXX if the channel is configured for input, does this + do bad things? */ + /* XXX it would be a good idea to only update the registers + that _need_ to be updated. This requires changes to + comedi, however. */ + writeb((s->state >> 0) & 0xff, devpriv->ioaddr + PCI20000_DIO_0); + writeb((s->state >> 8) & 0xff, devpriv->ioaddr + PCI20000_DIO_1); + writeb((s->state >> 16) & 0xff, devpriv->ioaddr + PCI20000_DIO_2); + writeb((s->state >> 24) & 0xff, devpriv->ioaddr + PCI20000_DIO_3); +} + +static unsigned int pci20xxx_di(struct comedi_device * dev, struct comedi_subdevice * s) +{ + /* XXX same note as above */ + unsigned int bits; + + bits = readb(devpriv->ioaddr + PCI20000_DIO_0); + bits |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8; + bits |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16; + bits |= readb(devpriv->ioaddr + PCI20000_DIO_3) << 24; + + return bits; +} +#endif + +COMEDI_INITCLEANUP(driver_pci20xxx); diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c new file mode 100644 index 000000000000..a3c887f3b2c6 --- /dev/null +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -0,0 +1,976 @@ +/* + comedi/drivers/jr3_pci.c + hardware driver for JR3/PCI force sensor board + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2007 Anders Blomdell + + 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: jr3_pci +Description: JR3/PCI force sensor board +Author: Anders Blomdell +Status: works +Devices: [JR3] PCI force sensor board (jr3_pci) + + The DSP on the board requires initialization code, which can + be loaded by placing it in /lib/firmware/comedi. + The initialization code should be somewhere on the media you got + with your card. One version is available from http://www.comedi.org + in the comedi_nonfree_firmware tarball. + + Configuration options: + [0] - PCI bus number - if bus number and slot number are 0, + then driver search for first unused card + [1] - PCI slot number + +*/ + +#include "../comedidev.h" + +#include +#include +#include +#include "comedi_pci.h" +#include "jr3_pci.h" + +/* Hotplug firmware loading stuff */ + +static void comedi_fw_release(struct device *dev) +{ + printk(KERN_DEBUG "firmware_sample_driver: ghost_release\n"); +} + +static struct device comedi_fw_device = { + .init_name = "comedi", + .release = comedi_fw_release +}; + +typedef int comedi_firmware_callback(struct comedi_device * dev, + const u8 * data, size_t size); + +static int comedi_load_firmware(struct comedi_device * dev, + char *name, comedi_firmware_callback cb) +{ + int result = 0; + const struct firmware *fw; + char *firmware_path; + static const char *prefix = "comedi/"; + + firmware_path = kmalloc(strlen(prefix) + strlen(name) + 1, GFP_KERNEL); + if (!firmware_path) { + result = -ENOMEM; + } else { + firmware_path[0] = '\0'; + strcat(firmware_path, prefix); + strcat(firmware_path, name); + result = device_register(&comedi_fw_device); + if (result == 0) { + result = request_firmware(&fw, firmware_path, + &comedi_fw_device); + if (result == 0) { + if (!cb) { + result = -EINVAL; + } else { + result = cb(dev, fw->data, fw->size); + } + release_firmware(fw); + } + device_unregister(&comedi_fw_device); + } + kfree(firmware_path); + } + return result; +} + +#define PCI_VENDOR_ID_JR3 0x1762 +#define PCI_DEVICE_ID_JR3_1_CHANNEL 0x3111 +#define PCI_DEVICE_ID_JR3_2_CHANNEL 0x3112 +#define PCI_DEVICE_ID_JR3_3_CHANNEL 0x3113 +#define PCI_DEVICE_ID_JR3_4_CHANNEL 0x3114 + +static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int jr3_pci_detach(struct comedi_device * dev); + +static struct comedi_driver driver_jr3_pci = { + driver_name:"jr3_pci", + module:THIS_MODULE, + attach:jr3_pci_attach, + detach:jr3_pci_detach, +}; + +static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = { + {PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_2_CHANNEL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_3_CHANNEL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_4_CHANNEL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, jr3_pci_pci_table); + +struct jr3_pci_dev_private { + + struct pci_dev *pci_dev; + int pci_enabled; + volatile struct jr3_t *iobase; + int n_channels; + struct timer_list timer; +}; + + +struct poll_delay_t { + + int min; + int max; +}; + + +struct jr3_pci_subdev_private { + volatile struct jr3_channel *channel; + unsigned long next_time_min; + unsigned long next_time_max; + enum { state_jr3_poll, + state_jr3_init_wait_for_offset, + state_jr3_init_transform_complete, + state_jr3_init_set_full_scale_complete, + state_jr3_init_use_offset_complete, + state_jr3_done + } state; + int channel_no; + int serial_no; + int model_no; + struct { + int length; + struct comedi_krange range; + } range[9]; + const struct comedi_lrange *range_table_list[8 * 7 + 2]; + unsigned int maxdata_list[8 * 7 + 2]; + u16 errors; + int retries; +}; + +static struct poll_delay_t poll_delay_min_max(int min, int max) +{ + struct poll_delay_t result; + + result.min = min; + result.max = max; + return result; +} + +static int is_complete(volatile struct jr3_channel *channel) +{ + return get_s16(&channel->command_word0) == 0; +} + +struct transform_t { + struct { + u16 link_type; + s16 link_amount; + } link[8]; +}; + +static void set_transforms(volatile struct jr3_channel *channel, + struct transform_t transf, short num) +{ + int i; + + num &= 0x000f; // Make sure that 0 <= num <= 15 + for (i = 0; i < 8; i++) { + + set_u16(&channel->transforms[num].link[i].link_type, + transf.link[i].link_type); + comedi_udelay(1); + set_s16(&channel->transforms[num].link[i].link_amount, + transf.link[i].link_amount); + comedi_udelay(1); + if (transf.link[i].link_type == end_x_form) { + break; + } + } +} + +static void use_transform(volatile struct jr3_channel *channel, short transf_num) +{ + set_s16(&channel->command_word0, 0x0500 + (transf_num & 0x000f)); +} + +static void use_offset(volatile struct jr3_channel *channel, short offset_num) +{ + set_s16(&channel->command_word0, 0x0600 + (offset_num & 0x000f)); +} + +static void set_offset(volatile struct jr3_channel *channel) +{ + set_s16(&channel->command_word0, 0x0700); +} + +struct six_axis_t { + s16 fx; + s16 fy; + s16 fz; + s16 mx; + s16 my; + s16 mz; +}; + +static void set_full_scales(volatile struct jr3_channel *channel, + struct six_axis_t full_scale) +{ + printk("%d %d %d %d %d %d\n", + full_scale.fx, + full_scale.fy, + full_scale.fz, full_scale.mx, full_scale.my, full_scale.mz); + set_s16(&channel->full_scale.fx, full_scale.fx); + set_s16(&channel->full_scale.fy, full_scale.fy); + set_s16(&channel->full_scale.fz, full_scale.fz); + set_s16(&channel->full_scale.mx, full_scale.mx); + set_s16(&channel->full_scale.my, full_scale.my); + set_s16(&channel->full_scale.mz, full_scale.mz); + set_s16(&channel->command_word0, 0x0a00); +} + +static struct six_axis_t get_min_full_scales(volatile struct jr3_channel *channel) +{ + struct six_axis_t result; + result.fx = get_s16(&channel->min_full_scale.fx); + result.fy = get_s16(&channel->min_full_scale.fy); + result.fz = get_s16(&channel->min_full_scale.fz); + result.mx = get_s16(&channel->min_full_scale.mx); + result.my = get_s16(&channel->min_full_scale.my); + result.mz = get_s16(&channel->min_full_scale.mz); + return result; +} + +static struct six_axis_t get_max_full_scales(volatile struct jr3_channel *channel) +{ + struct six_axis_t result; + result.fx = get_s16(&channel->max_full_scale.fx); + result.fy = get_s16(&channel->max_full_scale.fy); + result.fz = get_s16(&channel->max_full_scale.fz); + result.mx = get_s16(&channel->max_full_scale.mx); + result.my = get_s16(&channel->max_full_scale.my); + result.mz = get_s16(&channel->max_full_scale.mz); + return result; +} + +static int jr3_pci_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int result; + struct jr3_pci_subdev_private *p; + int channel; + + p = s->private; + channel = CR_CHAN(insn->chanspec); + if (p == NULL || channel > 57) { + result = -EINVAL; + } else { + int i; + + result = insn->n; + if (p->state != state_jr3_done || + (get_u16(&p->channel-> + errors) & (watch_dog | watch_dog2 | + sensor_change))) { + /* No sensor or sensor changed */ + if (p->state == state_jr3_done) { + /* Restart polling */ + p->state = state_jr3_poll; + } + result = -EAGAIN; + } + for (i = 0; i < insn->n; i++) { + if (channel < 56) { + int axis, filter; + + axis = channel % 8; + filter = channel / 8; + if (p->state != state_jr3_done) { + data[i] = 0; + } else { + int F = 0; + switch (axis) { + case 0:{ + F = get_s16(&p-> + channel-> + filter[filter]. + fx); + } + break; + case 1:{ + F = get_s16(&p-> + channel-> + filter[filter]. + fy); + } + break; + case 2:{ + F = get_s16(&p-> + channel-> + filter[filter]. + fz); + } + break; + case 3:{ + F = get_s16(&p-> + channel-> + filter[filter]. + mx); + } + break; + case 4:{ + F = get_s16(&p-> + channel-> + filter[filter]. + my); + } + break; + case 5:{ + F = get_s16(&p-> + channel-> + filter[filter]. + mz); + } + break; + case 6:{ + F = get_s16(&p-> + channel-> + filter[filter]. + v1); + } + break; + case 7:{ + F = get_s16(&p-> + channel-> + filter[filter]. + v2); + } + break; + } + data[i] = F + 0x4000; + } + } else if (channel == 56) { + if (p->state != state_jr3_done) { + data[i] = 0; + } else { + data[i] = + get_u16(&p->channel->model_no); + } + } else if (channel == 57) { + if (p->state != state_jr3_done) { + data[i] = 0; + } else { + data[i] = + get_u16(&p->channel->serial_no); + } + } + } + } + return result; +} + +static void jr3_pci_open(struct comedi_device * dev) +{ + int i; + struct jr3_pci_dev_private *devpriv = dev->private; + + printk("jr3_pci_open\n"); + for (i = 0; i < devpriv->n_channels; i++) { + struct jr3_pci_subdev_private *p; + + p = dev->subdevices[i].private; + if (p) { + printk("serial: %p %d (%d)\n", p, p->serial_no, + p->channel_no); + } + } +} + +int read_idm_word(const u8 * data, size_t size, int *pos, unsigned int *val) +{ + int result = 0; + if (pos != 0 && val != 0) { + // Skip over non hex + for (; *pos < size && !isxdigit(data[*pos]); (*pos)++) { + } + // Collect value + *val = 0; + for (; *pos < size && isxdigit(data[*pos]); (*pos)++) { + char ch = tolower(data[*pos]); + result = 1; + if ('0' <= ch && ch <= '9') { + *val = (*val << 4) + (ch - '0'); + } else if ('a' <= ch && ch <= 'f') { + *val = (*val << 4) + (ch - 'a' + 10); + } + } + } + return result; +} + +static int jr3_download_firmware(struct comedi_device * dev, const u8 * data, + size_t size) +{ + /* + * IDM file format is: + * { count, address, data } * + * ffff + */ + int result, more, pos, OK; + + result = 0; + more = 1; + pos = 0; + OK = 0; + while (more) { + unsigned int count, addr; + + more = more && read_idm_word(data, size, &pos, &count); + if (more && count == 0xffff) { + OK = 1; + break; + } + more = more && read_idm_word(data, size, &pos, &addr); + while (more && count > 0) { + unsigned int dummy; + more = more && read_idm_word(data, size, &pos, &dummy); + count--; + } + } + + if (!OK) { + result = -ENODATA; + } else { + int i; + struct jr3_pci_dev_private *p = dev->private; + + for (i = 0; i < p->n_channels; i++) { + struct jr3_pci_subdev_private *sp; + + sp = dev->subdevices[i].private; + more = 1; + pos = 0; + while (more) { + unsigned int count, addr; + more = more + && read_idm_word(data, size, &pos, + &count); + if (more && count == 0xffff) { + break; + } + more = more + && read_idm_word(data, size, &pos, + &addr); + printk("Loading#%d %4.4x bytes at %4.4x\n", i, + count, addr); + while (more && count > 0) { + if (addr & 0x4000) { + // 16 bit data, never seen in real life!! + unsigned int data1; + + more = more + && read_idm_word(data, + size, &pos, &data1); + count--; + // printk("jr3_data, not tested\n"); + // jr3[addr + 0x20000 * pnum] = data1; + } else { + // Download 24 bit program + unsigned int data1, data2; + + more = more + && read_idm_word(data, + size, &pos, &data1); + more = more + && read_idm_word(data, + size, &pos, &data2); + count -= 2; + if (more) { + set_u16(&p->iobase-> + channel[i]. + program_low + [addr], data1); + comedi_udelay(1); + set_u16(&p->iobase-> + channel[i]. + program_high + [addr], data2); + comedi_udelay(1); + + } + } + addr++; + } + } + } + } + return result; +} + +static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice * s) +{ + struct poll_delay_t result = poll_delay_min_max(1000, 2000); + struct jr3_pci_subdev_private *p = s->private; + + if (p) { + volatile struct jr3_channel *channel = p->channel; + int errors = get_u16(&channel->errors); + + if (errors != p->errors) { + printk("Errors: %x -> %x\n", p->errors, errors); + p->errors = errors; + } + if (errors & (watch_dog | watch_dog2 | sensor_change)) { + // Sensor communication lost, force poll mode + p->state = state_jr3_poll; + + } + switch (p->state) { + case state_jr3_poll:{ + u16 model_no = get_u16(&channel->model_no); + u16 serial_no = get_u16(&channel->serial_no); + if ((errors & (watch_dog | watch_dog2)) || + model_no == 0 || serial_no == 0) { + // Still no sensor, keep on polling. Since it takes up to + // 10 seconds for offsets to stabilize, polling each + // second should suffice. + result = poll_delay_min_max(1000, 2000); + } else { + p->retries = 0; + p->state = + state_jr3_init_wait_for_offset; + result = poll_delay_min_max(1000, 2000); + } + } + break; + case state_jr3_init_wait_for_offset:{ + p->retries++; + if (p->retries < 10) { + // Wait for offeset to stabilize (< 10 s according to manual) + result = poll_delay_min_max(1000, 2000); + } else { + struct transform_t transf; + + p->model_no = + get_u16(&channel->model_no); + p->serial_no = + get_u16(&channel->serial_no); + + printk("Setting transform for channel %d\n", p->channel_no); + printk("Sensor Model = %i\n", + p->model_no); + printk("Sensor Serial = %i\n", + p->serial_no); + + // Transformation all zeros + transf.link[0].link_type = + (enum link_types)0; + transf.link[0].link_amount = 0; + transf.link[1].link_type = + (enum link_types)0; + transf.link[1].link_amount = 0; + transf.link[2].link_type = + (enum link_types)0; + transf.link[2].link_amount = 0; + transf.link[3].link_type = + (enum link_types)0; + transf.link[3].link_amount = 0; + + set_transforms(channel, transf, 0); + use_transform(channel, 0); + p->state = + state_jr3_init_transform_complete; + result = poll_delay_min_max(20, 100); // Allow 20 ms for completion + } + } break; + case state_jr3_init_transform_complete:{ + if (!is_complete(channel)) { + printk("state_jr3_init_transform_complete complete = %d\n", is_complete(channel)); + result = poll_delay_min_max(20, 100); + } else { + // Set full scale + struct six_axis_t min_full_scale; + struct six_axis_t max_full_scale; + + min_full_scale = + get_min_full_scales(channel); + printk("Obtained Min. Full Scales:\n"); + printk("%i ", (min_full_scale).fx); + printk("%i ", (min_full_scale).fy); + printk("%i ", (min_full_scale).fz); + printk("%i ", (min_full_scale).mx); + printk("%i ", (min_full_scale).my); + printk("%i ", (min_full_scale).mz); + printk("\n"); + + max_full_scale = + get_max_full_scales(channel); + printk("Obtained Max. Full Scales:\n"); + printk("%i ", (max_full_scale).fx); + printk("%i ", (max_full_scale).fy); + printk("%i ", (max_full_scale).fz); + printk("%i ", (max_full_scale).mx); + printk("%i ", (max_full_scale).my); + printk("%i ", (max_full_scale).mz); + printk("\n"); + + set_full_scales(channel, + max_full_scale); + + p->state = + state_jr3_init_set_full_scale_complete; + result = poll_delay_min_max(20, 100); // Allow 20 ms for completion + } + } + break; + case state_jr3_init_set_full_scale_complete:{ + if (!is_complete(channel)) { + printk("state_jr3_init_set_full_scale_complete complete = %d\n", is_complete(channel)); + result = poll_delay_min_max(20, 100); + } else { + volatile struct force_array *full_scale; + + // Use ranges in kN or we will overflow arount 2000N! + full_scale = &channel->full_scale; + p->range[0].range.min = + -get_s16(&full_scale->fx) * + 1000; + p->range[0].range.max = + get_s16(&full_scale->fx) * 1000; + p->range[1].range.min = + -get_s16(&full_scale->fy) * + 1000; + p->range[1].range.max = + get_s16(&full_scale->fy) * 1000; + p->range[2].range.min = + -get_s16(&full_scale->fz) * + 1000; + p->range[2].range.max = + get_s16(&full_scale->fz) * 1000; + p->range[3].range.min = + -get_s16(&full_scale->mx) * 100; + p->range[3].range.max = + get_s16(&full_scale->mx) * 100; + p->range[4].range.min = + -get_s16(&full_scale->my) * 100; + p->range[4].range.max = + get_s16(&full_scale->my) * 100; + p->range[5].range.min = + -get_s16(&full_scale->mz) * 100; + p->range[5].range.max = + get_s16(&full_scale->mz) * 100; + p->range[6].range.min = -get_s16(&full_scale->v1) * 100; // ?? + p->range[6].range.max = get_s16(&full_scale->v1) * 100; // ?? + p->range[7].range.min = -get_s16(&full_scale->v2) * 100; // ?? + p->range[7].range.max = get_s16(&full_scale->v2) * 100; // ?? + p->range[8].range.min = 0; + p->range[8].range.max = 65535; + + { + int i; + for (i = 0; i < 9; i++) { + printk("%d %d - %d\n", + i, + p->range[i]. + range.min, + p->range[i]. + range.max); + } + } + + use_offset(channel, 0); + p->state = + state_jr3_init_use_offset_complete; + result = poll_delay_min_max(40, 100); // Allow 40 ms for completion + } + } + break; + case state_jr3_init_use_offset_complete:{ + if (!is_complete(channel)) { + printk("state_jr3_init_use_offset_complete complete = %d\n", is_complete(channel)); + result = poll_delay_min_max(20, 100); + } else { + printk("Default offsets %d %d %d %d %d %d\n", get_s16(&channel->offsets.fx), get_s16(&channel->offsets.fy), get_s16(&channel->offsets.fz), get_s16(&channel->offsets.mx), get_s16(&channel->offsets.my), get_s16(&channel->offsets.mz)); + + set_s16(&channel->offsets.fx, 0); + set_s16(&channel->offsets.fy, 0); + set_s16(&channel->offsets.fz, 0); + set_s16(&channel->offsets.mx, 0); + set_s16(&channel->offsets.my, 0); + set_s16(&channel->offsets.mz, 0); + + set_offset(channel); + + p->state = state_jr3_done; + } + } + break; + case state_jr3_done:{ + poll_delay_min_max(10000, 20000); + } + break; + default:{ + poll_delay_min_max(1000, 2000); + } + break; + } + } + return result; +} + +static void jr3_pci_poll_dev(unsigned long data) +{ + unsigned long flags; + struct comedi_device *dev = (struct comedi_device *) data; + struct jr3_pci_dev_private *devpriv = dev->private; + unsigned long now; + int delay; + int i; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + delay = 1000; + now = jiffies; + // Poll all channels that are ready to be polled + for (i = 0; i < devpriv->n_channels; i++) { + struct jr3_pci_subdev_private *subdevpriv = dev->subdevices[i].private; + if (now > subdevpriv->next_time_min) { + struct poll_delay_t sub_delay; + + sub_delay = jr3_pci_poll_subdevice(&dev->subdevices[i]); + subdevpriv->next_time_min = + jiffies + msecs_to_jiffies(sub_delay.min); + subdevpriv->next_time_max = + jiffies + msecs_to_jiffies(sub_delay.max); + if (sub_delay.max && sub_delay.max < delay) { + // Wake up as late as possible -> poll as many channels as + // possible at once + delay = sub_delay.max; + } + } + } + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + devpriv->timer.expires = jiffies + msecs_to_jiffies(delay); + add_timer(&devpriv->timer); +} + +static int jr3_pci_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int result = 0; + struct pci_dev *card = NULL; + int opt_bus, opt_slot, i; + struct jr3_pci_dev_private *devpriv; + + printk("comedi%d: jr3_pci\n", dev->minor); + + opt_bus = it->options[0]; + opt_slot = it->options[1]; + + if (sizeof(struct jr3_channel) != 0xc00) { + printk("sizeof(struct jr3_channel) = %x [expected %x]\n", + (unsigned)sizeof(struct jr3_channel), 0xc00); + return -EINVAL; + } + + result = alloc_private(dev, sizeof(struct jr3_pci_dev_private)); + if (result < 0) { + return -ENOMEM; + } + card = NULL; + devpriv = dev->private; + init_timer(&devpriv->timer); + while (1) { + card = pci_get_device(PCI_VENDOR_ID_JR3, PCI_ANY_ID, card); + if (card == NULL) { + /* No card found */ + break; + } else { + switch (card->device) { + case PCI_DEVICE_ID_JR3_1_CHANNEL:{ + devpriv->n_channels = 1; + } + break; + case PCI_DEVICE_ID_JR3_2_CHANNEL:{ + devpriv->n_channels = 2; + } + break; + case PCI_DEVICE_ID_JR3_3_CHANNEL:{ + devpriv->n_channels = 3; + } + break; + case PCI_DEVICE_ID_JR3_4_CHANNEL:{ + devpriv->n_channels = 4; + } + break; + default:{ + devpriv->n_channels = 0; + } + } + if (devpriv->n_channels >= 1) { + if (opt_bus == 0 && opt_slot == 0) { + /* Take first available card */ + break; + } else if (opt_bus == card->bus->number && + opt_slot == PCI_SLOT(card->devfn)) { + /* Take requested card */ + break; + } + } + } + } + if (!card) { + printk(" no jr3_pci found\n"); + return -EIO; + } else { + devpriv->pci_dev = card; + dev->board_name = "jr3_pci"; + } + if ((result = comedi_pci_enable(card, "jr3_pci")) < 0) { + return -EIO; + } + devpriv->pci_enabled = 1; + devpriv->iobase = ioremap(pci_resource_start(card, 0), sizeof(struct jr3_t)); + result = alloc_subdevices(dev, devpriv->n_channels); + if (result < 0) + goto out; + + dev->open = jr3_pci_open; + for (i = 0; i < devpriv->n_channels; i++) { + dev->subdevices[i].type = COMEDI_SUBD_AI; + dev->subdevices[i].subdev_flags = SDF_READABLE | SDF_GROUND; + dev->subdevices[i].n_chan = 8 * 7 + 2; + dev->subdevices[i].insn_read = jr3_pci_ai_insn_read; + dev->subdevices[i].private = + kzalloc(sizeof(struct jr3_pci_subdev_private), GFP_KERNEL); + if (dev->subdevices[i].private) { + struct jr3_pci_subdev_private *p; + int j; + + p = dev->subdevices[i].private; + p->channel = &devpriv->iobase->channel[i].data; + printk("p->channel %p %p (%tx)\n", + p->channel, devpriv->iobase, + ((char *)(p->channel) - + (char *)(devpriv->iobase))); + p->channel_no = i; + for (j = 0; j < 8; j++) { + int k; + + p->range[j].length = 1; + p->range[j].range.min = -1000000; + p->range[j].range.max = 1000000; + for (k = 0; k < 7; k++) { + p->range_table_list[j + k * 8] = + (struct comedi_lrange *) & p->range[j]; + p->maxdata_list[j + k * 8] = 0x7fff; + } + } + p->range[8].length = 1; + p->range[8].range.min = 0; + p->range[8].range.max = 65536; + + p->range_table_list[56] = + (struct comedi_lrange *) & p->range[8]; + p->range_table_list[57] = + (struct comedi_lrange *) & p->range[8]; + p->maxdata_list[56] = 0xffff; + p->maxdata_list[57] = 0xffff; + // Channel specific range and maxdata + dev->subdevices[i].range_table = 0; + dev->subdevices[i].range_table_list = + p->range_table_list; + dev->subdevices[i].maxdata = 0; + dev->subdevices[i].maxdata_list = p->maxdata_list; + } + } + + // Reset DSP card + devpriv->iobase->channel[0].reset = 0; + + result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware); + printk("Firmare load %d\n", result); + + if (result < 0) { + goto out; + } + // TODO: use firmware to load preferred offset tables. Suggested format: + // model serial Fx Fy Fz Mx My Mz\n + // + // comedi_load_firmware(dev, "jr3_offsets_table", jr3_download_firmware); + + // It takes a few milliseconds for software to settle + // as much as we can read firmware version + msleep_interruptible(25); + for (i = 0; i < 0x18; i++) { + printk("%c", + get_u16(&devpriv->iobase->channel[0].data. + copyright[i]) >> 8); + } + + // Start card timer + for (i = 0; i < devpriv->n_channels; i++) { + struct jr3_pci_subdev_private *p = dev->subdevices[i].private; + + p->next_time_min = jiffies + msecs_to_jiffies(500); + p->next_time_max = jiffies + msecs_to_jiffies(2000); + } + + devpriv->timer.data = (unsigned long)dev; + devpriv->timer.function = jr3_pci_poll_dev; + devpriv->timer.expires = jiffies + msecs_to_jiffies(1000); + add_timer(&devpriv->timer); + + out: + return result; +} + +static int jr3_pci_detach(struct comedi_device * dev) +{ + int i; + struct jr3_pci_dev_private *devpriv = dev->private; + + printk("comedi%d: jr3_pci: remove\n", dev->minor); + if (devpriv) { + del_timer_sync(&devpriv->timer); + + if (dev->subdevices) { + for (i = 0; i < devpriv->n_channels; i++) { + kfree(dev->subdevices[i].private); + } + } + + if (devpriv->iobase) { + iounmap((void *)devpriv->iobase); + } + if (devpriv->pci_enabled) { + comedi_pci_disable(devpriv->pci_dev); + } + + if (devpriv->pci_dev) { + pci_dev_put(devpriv->pci_dev); + } + } + return 0; +} + +COMEDI_PCI_INITCLEANUP(driver_jr3_pci, jr3_pci_pci_table); diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h new file mode 100644 index 000000000000..3585f2941bca --- /dev/null +++ b/drivers/staging/comedi/drivers/jr3_pci.h @@ -0,0 +1,681 @@ +/* Helper types to take care of the fact that the DSP card memory + * is 16 bits, but aligned on a 32 bit PCI boundary + */ + +static inline u16 get_u16(volatile const u32 * p) +{ + return (u16) readl(p); +} + +static inline void set_u16(volatile u32 * p, u16 val) +{ + writel(val, p); +} + +static inline s16 get_s16(volatile const s32 * p) +{ + return (s16) readl(p); +} + +static inline void set_s16(volatile s32 * p, s16 val) +{ + writel(val, p); +} + +/* The raw data is stored in a format which facilitates rapid + * processing by the JR3 DSP chip. The raw_channel structure shows the + * format for a single channel of data. Each channel takes four, + * two-byte words. + * + * Raw_time is an unsigned integer which shows the value of the JR3 + * DSP's internal clock at the time the sample was received. The clock + * runs at 1/10 the JR3 DSP cycle time. JR3's slowest DSP runs at 10 + * Mhz. At 10 Mhz raw_time would therefore clock at 1 Mhz. + * + * Raw_data is the raw data received directly from the sensor. The + * sensor data stream is capable of representing 16 different + * channels. Channel 0 shows the excitation voltage at the sensor. It + * is used to regulate the voltage over various cable lengths. + * Channels 1-6 contain the coupled force data Fx through Mz. Channel + * 7 contains the sensor's calibration data. The use of channels 8-15 + * varies with different sensors. + */ + +struct raw_channel { + u32 raw_time; + s32 raw_data; + s32 reserved[2]; +}; + +/* The force_array structure shows the layout for the decoupled and + * filtered force data. + */ +struct force_array { + s32 fx; + s32 fy; + s32 fz; + s32 mx; + s32 my; + s32 mz; + s32 v1; + s32 v2; +}; + +/* The six_axis_array structure shows the layout for the offsets and + * the full scales. + */ +struct six_axis_array { + s32 fx; + s32 fy; + s32 fz; + s32 mx; + s32 my; + s32 mz; +}; + +/* VECT_BITS */ +/* The vect_bits structure shows the layout for indicating + * which axes to use in computing the vectors. Each bit signifies + * selection of a single axis. The V1x axis bit corresponds to a hex + * value of 0x0001 and the V2z bit corresponds to a hex value of + * 0x0020. Example: to specify the axes V1x, V1y, V2x, and V2z the + * pattern would be 0x002b. Vector 1 defaults to a force vector and + * vector 2 defaults to a moment vector. It is possible to change one + * or the other so that two force vectors or two moment vectors are + * calculated. Setting the changeV1 bit or the changeV2 bit will + * change that vector to be the opposite of its default. Therefore to + * have two force vectors, set changeV1 to 1. + */ + +/* vect_bits appears to be unused at this time */ +enum { + fx = 0x0001, + fy = 0x0002, + fz = 0x0004, + mx = 0x0008, + my = 0x0010, + mz = 0x0020, + changeV2 = 0x0040, + changeV1 = 0x0080 +} vect_bits_t; + +/* WARNING_BITS */ +/* The warning_bits structure shows the bit pattern for the warning + * word. The bit fields are shown from bit 0 (lsb) to bit 15 (msb). + */ + +/* XX_NEAR_SET */ +/* The xx_near_sat bits signify that the indicated axis has reached or + * exceeded the near saturation value. + */ + +enum { + fx_near_sat = 0x0001, + fy_near_sat = 0x0002, + fz_near_sat = 0x0004, + mx_near_sat = 0x0008, + my_near_sat = 0x0010, + mz_near_sat = 0x0020 +} warning_bits_t; + +/* ERROR_BITS */ +/* XX_SAT */ +/* MEMORY_ERROR */ +/* SENSOR_CHANGE */ + +/* The error_bits structure shows the bit pattern for the error word. + * The bit fields are shown from bit 0 (lsb) to bit 15 (msb). The + * xx_sat bits signify that the indicated axis has reached or exceeded + * the saturation value. The memory_error bit indicates that a problem + * was detected in the on-board RAM during the power-up + * initialization. The sensor_change bit indicates that a sensor other + * than the one originally plugged in has passed its CRC check. This + * bit latches, and must be reset by the user. + * + */ + +/* SYSTEM_BUSY */ + +/* The system_busy bit indicates that the JR3 DSP is currently busy + * and is not calculating force data. This occurs when a new + * coordinate transformation, or new sensor full scale is set by the + * user. A very fast system using the force data for feedback might + * become unstable during the approximately 4 ms needed to accomplish + * these calculations. This bit will also become active when a new + * sensor is plugged in and the system needs to recalculate the + * calibration CRC. + */ + +/* CAL_CRC_BAD */ + +/* The cal_crc_bad bit indicates that the calibration CRC has not + * calculated to zero. CRC is short for cyclic redundancy code. It is + * a method for determining the integrity of messages in data + * communication. The calibration data stored inside the sensor is + * transmitted to the JR3 DSP along with the sensor data. The + * calibration data has a CRC attached to the end of it, to assist in + * determining the completeness and integrity of the calibration data + * received from the sensor. There are two reasons the CRC may not + * have calculated to zero. The first is that all the calibration data + * has not yet been received, the second is that the calibration data + * has been corrupted. A typical sensor transmits the entire contents + * of its calibration matrix over 30 times a second. Therefore, if + * this bit is not zero within a couple of seconds after the sensor + * has been plugged in, there is a problem with the sensor's + * calibration data. + */ + +/* WATCH_DOG */ +/* WATCH_DOG2 */ + +/* The watch_dog and watch_dog2 bits are sensor, not processor, watch + * dog bits. Watch_dog indicates that the sensor data line seems to be + * acting correctly, while watch_dog2 indicates that sensor data and + * clock are being received. It is possible for watch_dog2 to go off + * while watch_dog does not. This would indicate an improper clock + * signal, while data is acting correctly. If either watch dog barks, + * the sensor data is not being received correctly. + */ + +enum error_bits_t { + fx_sat = 0x0001, + fy_sat = 0x0002, + fz_sat = 0x0004, + mx_sat = 0x0008, + my_sat = 0x0010, + mz_sat = 0x0020, + memory_error = 0x0400, + sensor_change = 0x0800, + system_busy = 0x1000, + cal_crc_bad = 0x2000, + watch_dog2 = 0x4000, + watch_dog = 0x8000 +}; + +/* THRESH_STRUCT */ + +/* This structure shows the layout for a single threshold packet inside of a + * load envelope. Each load envelope can contain several threshold structures. + * 1. data_address contains the address of the data for that threshold. This + * includes filtered, unfiltered, raw, rate, counters, error and warning data + * 2. threshold is the is the value at which, if data is above or below, the + * bits will be set ... (pag.24). + * 3. bit_pattern contains the bits that will be set if the threshold value is + * met or exceeded. + */ + +struct thresh_struct { + s32 data_address; + s32 threshold; + s32 bit_pattern; +}; + +/* LE_STRUCT */ + +/* Layout of a load enveloped packet. Four thresholds are showed ... for more + * see manual (pag.25) + * 1. latch_bits is a bit pattern that show which bits the user wants to latch. + * The latched bits will not be reset once the threshold which set them is + * no longer true. In that case the user must reset them using the reset_bit + * command. + * 2. number_of_xx_thresholds specify how many GE/LE threshold there are. + */ +struct le_struct { + s32 latch_bits; + s32 number_of_ge_thresholds; + s32 number_of_le_thresholds; + struct thresh_struct thresholds[4]; + s32 reserved; +}; + +/* LINK_TYPES */ +/* Link types is an enumerated value showing the different possible transform + * link types. + * 0 - end transform packet + * 1 - translate along X axis (TX) + * 2 - translate along Y axis (TY) + * 3 - translate along Z axis (TZ) + * 4 - rotate about X axis (RX) + * 5 - rotate about Y axis (RY) + * 6 - rotate about Z axis (RZ) + * 7 - negate all axes (NEG) + */ + +enum link_types { + end_x_form, + tx, + ty, + tz, + rx, + ry, + rz, + neg +}; + +/* TRANSFORM */ +/* Structure used to describe a transform. */ +struct intern_transform { + struct { + u32 link_type; + s32 link_amount; + } link[8]; +}; + +/* JR3 force/torque sensor data definition. For more information see sensor and */ +/* hardware manuals. */ + +struct jr3_channel { + /* Raw_channels is the area used to store the raw data coming from */ + /* the sensor. */ + + struct raw_channel raw_channels[16]; /* offset 0x0000 */ + + /* Copyright is a null terminated ASCII string containing the JR3 */ + /* copyright notice. */ + + u32 copyright[0x0018]; /* offset 0x0040 */ + s32 reserved1[0x0008]; /* offset 0x0058 */ + + /* Shunts contains the sensor shunt readings. Some JR3 sensors have + * the ability to have their gains adjusted. This allows the + * hardware full scales to be adjusted to potentially allow + * better resolution or dynamic range. For sensors that have + * this ability, the gain of each sensor channel is measured at + * the time of calibration using a shunt resistor. The shunt + * resistor is placed across one arm of the resistor bridge, and + * the resulting change in the output of that channel is + * measured. This measurement is called the shunt reading, and + * is recorded here. If the user has changed the gain of the // + * sensor, and made new shunt measurements, those shunt + * measurements can be placed here. The JR3 DSP will then scale + * the calibration matrix such so that the gains are again + * proper for the indicated shunt readings. If shunts is 0, then + * the sensor cannot have its gain changed. For details on + * changing the sensor gain, and making shunts readings, please + * see the sensor manual. To make these values take effect the + * user must call either command (5) use transform # (pg. 33) or + * command (10) set new full scales (pg. 38). + */ + + struct six_axis_array shunts; /* offset 0x0060 */ + s32 reserved2[2]; /* offset 0x0066 */ + + /* Default_FS contains the full scale that is used if the user does */ + /* not set a full scale. */ + + struct six_axis_array default_FS; /* offset 0x0068 */ + s32 reserved3; /* offset 0x006e */ + + /* Load_envelope_num is the load envelope number that is currently + * in use. This value is set by the user after one of the load + * envelopes has been initialized. + */ + + s32 load_envelope_num; /* offset 0x006f */ + + /* Min_full_scale is the recommend minimum full scale. */ + + /* These values in conjunction with max_full_scale (pg. 9) helps + * determine the appropriate value for setting the full scales. The + * software allows the user to set the sensor full scale to an + * arbitrary value. But setting the full scales has some hazards. If + * the full scale is set too low, the data will saturate + * prematurely, and dynamic range will be lost. If the full scale is + * set too high, then resolution is lost as the data is shifted to + * the right and the least significant bits are lost. Therefore the + * maximum full scale is the maximum value at which no resolution is + * lost, and the minimum full scale is the value at which the data + * will not saturate prematurely. These values are calculated + * whenever a new coordinate transformation is calculated. It is + * possible for the recommended maximum to be less than the + * recommended minimum. This comes about primarily when using + * coordinate translations. If this is the case, it means that any + * full scale selection will be a compromise between dynamic range + * and resolution. It is usually recommended to compromise in favor + * of resolution which means that the recommend maximum full scale + * should be chosen. + * + * WARNING: Be sure that the full scale is no less than 0.4% of the + * recommended minimum full scale. Full scales below this value will + * cause erroneous results. + */ + + struct six_axis_array min_full_scale; /* offset 0x0070 */ + s32 reserved4; /* offset 0x0076 */ + + /* Transform_num is the transform number that is currently in use. + * This value is set by the JR3 DSP after the user has used command + * (5) use transform # (pg. 33). + */ + + s32 transform_num; /* offset 0x0077 */ + + /* Max_full_scale is the recommended maximum full scale. See */ + /* min_full_scale (pg. 9) for more details. */ + + struct six_axis_array max_full_scale; /* offset 0x0078 */ + s32 reserved5; /* offset 0x007e */ + + /* Peak_address is the address of the data which will be monitored + * by the peak routine. This value is set by the user. The peak + * routine will monitor any 8 contiguous addresses for peak values. + * (ex. to watch filter3 data for peaks, set this value to 0x00a8). + */ + + s32 peak_address; /* offset 0x007f */ + + /* Full_scale is the sensor full scales which are currently in use. + * Decoupled and filtered data is scaled so that +/- 16384 is equal + * to the full scales. The engineering units used are indicated by + * the units value discussed on page 16. The full scales for Fx, Fy, + * Fz, Mx, My and Mz can be written by the user prior to calling + * command (10) set new full scales (pg. 38). The full scales for V1 + * and V2 are set whenever the full scales are changed or when the + * axes used to calculate the vectors are changed. The full scale of + * V1 and V2 will always be equal to the largest full scale of the + * axes used for each vector respectively. + */ + + struct force_array full_scale; /* offset 0x0080 */ + + /* Offsets contains the sensor offsets. These values are subtracted from + * the sensor data to obtain the decoupled data. The offsets are set a + * few seconds (< 10) after the calibration data has been received. + * They are set so that the output data will be zero. These values + * can be written as well as read. The JR3 DSP will use the values + * written here within 2 ms of being written. To set future + * decoupled data to zero, add these values to the current decoupled + * data values and place the sum here. The JR3 DSP will change these + * values when a new transform is applied. So if the offsets are + * such that FX is 5 and all other values are zero, after rotating + * about Z by 90 degrees, FY would be 5 and all others would be zero. + */ + + struct six_axis_array offsets; /* offset 0x0088 */ + + /* Offset_num is the number of the offset currently in use. This + * value is set by the JR3 DSP after the user has executed the use + * offset # command (pg. 34). It can vary between 0 and 15. + */ + + s32 offset_num; /* offset 0x008e */ + + /* Vect_axes is a bit map showing which of the axes are being used + * in the vector calculations. This value is set by the JR3 DSP + * after the user has executed the set vector axes command (pg. 37). + */ + + u32 vect_axes; /* offset 0x008f */ + + /* Filter0 is the decoupled, unfiltered data from the JR3 sensor. + * This data has had the offsets removed. + * + * These force_arrays hold the filtered data. The decoupled data is + * passed through cascaded low pass filters. Each succeeding filter + * has a cutoff frequency of 1/4 of the preceding filter. The cutoff + * frequency of filter1 is 1/16 of the sample rate from the sensor. + * For a typical sensor with a sample rate of 8 kHz, the cutoff + * frequency of filter1 would be 500 Hz. The following filters would + * cutoff at 125 Hz, 31.25 Hz, 7.813 Hz, 1.953 Hz and 0.4883 Hz. + */ + + struct force_array filter[7]; /* offset 0x0090, + offset 0x0098, + offset 0x00a0, + offset 0x00a8, + offset 0x00b0, + offset 0x00b8 , + offset 0x00c0 */ + + /* Rate_data is the calculated rate data. It is a first derivative + * calculation. It is calculated at a frequency specified by the + * variable rate_divisor (pg. 12). The data on which the rate is + * calculated is specified by the variable rate_address (pg. 12). + */ + + struct force_array rate_data; /* offset 0x00c8 */ + + /* Minimum_data & maximum_data are the minimum and maximum (peak) + * data values. The JR3 DSP can monitor any 8 contiguous data items + * for minimums and maximums at full sensor bandwidth. This area is + * only updated at user request. This is done so that the user does + * not miss any peaks. To read the data, use either the read peaks + * command (pg. 40), or the read and reset peaks command (pg. 39). + * The address of the data to watch for peaks is stored in the + * variable peak_address (pg. 10). Peak data is lost when executing + * a coordinate transformation or a full scale change. Peak data is + * also lost when plugging in a new sensor. + */ + + struct force_array minimum_data; /* offset 0x00d0 */ + struct force_array maximum_data; /* offset 0x00d8 */ + + /* Near_sat_value & sat_value contain the value used to determine if + * the raw sensor is saturated. Because of decoupling and offset + * removal, it is difficult to tell from the processed data if the + * sensor is saturated. These values, in conjunction with the error + * and warning words (pg. 14), provide this critical information. + * These two values may be set by the host processor. These values + * are positive signed values, since the saturation logic uses the + * absolute values of the raw data. The near_sat_value defaults to + * approximately 80% of the ADC's full scale, which is 26214, while + * sat_value defaults to the ADC's full scale: + * + * sat_value = 32768 - 2^(16 - ADC bits) + */ + + s32 near_sat_value; /* offset 0x00e0 */ + s32 sat_value; /* offset 0x00e1 */ + + /* Rate_address, rate_divisor & rate_count contain the data used to + * control the calculations of the rates. Rate_address is the + * address of the data used for the rate calculation. The JR3 DSP + * will calculate rates for any 8 contiguous values (ex. to + * calculate rates for filter3 data set rate_address to 0x00a8). + * Rate_divisor is how often the rate is calculated. If rate_divisor + * is 1, the rates are calculated at full sensor bandwidth. If + * rate_divisor is 200, rates are calculated every 200 samples. + * Rate_divisor can be any value between 1 and 65536. Set + * rate_divisor to 0 to calculate rates every 65536 samples. + * Rate_count starts at zero and counts until it equals + * rate_divisor, at which point the rates are calculated, and + * rate_count is reset to 0. When setting a new rate divisor, it is + * a good idea to set rate_count to one less than rate divisor. This + * will minimize the time necessary to start the rate calculations. + */ + + s32 rate_address; /* offset 0x00e2 */ + u32 rate_divisor; /* offset 0x00e3 */ + u32 rate_count; /* offset 0x00e4 */ + + /* Command_word2 through command_word0 are the locations used to + * send commands to the JR3 DSP. Their usage varies with the command + * and is detailed later in the Command Definitions section (pg. + * 29). In general the user places values into various memory + * locations, and then places the command word into command_word0. + * The JR3 DSP will process the command and place a 0 into + * command_word0 to indicate successful completion. Alternatively + * the JR3 DSP will place a negative number into command_word0 to + * indicate an error condition. Please note the command locations + * are numbered backwards. (I.E. command_word2 comes before + * command_word1). + */ + + s32 command_word2; /* offset 0x00e5 */ + s32 command_word1; /* offset 0x00e6 */ + s32 command_word0; /* offset 0x00e7 */ + + /* Count1 through count6 are unsigned counters which are incremented + * every time the matching filters are calculated. Filter1 is + * calculated at the sensor data bandwidth. So this counter would + * increment at 8 kHz for a typical sensor. The rest of the counters + * are incremented at 1/4 the interval of the counter immediately + * preceding it, so they would count at 2 kHz, 500 Hz, 125 Hz etc. + * These counters can be used to wait for data. Each time the + * counter changes, the corresponding data set can be sampled, and + * this will insure that the user gets each sample, once, and only + * once. + */ + + u32 count1; /* offset 0x00e8 */ + u32 count2; /* offset 0x00e9 */ + u32 count3; /* offset 0x00ea */ + u32 count4; /* offset 0x00eb */ + u32 count5; /* offset 0x00ec */ + u32 count6; /* offset 0x00ed */ + + /* Error_count is a running count of data reception errors. If this + * counter is changing rapidly, it probably indicates a bad sensor + * cable connection or other hardware problem. In most installations + * error_count should not change at all. But it is possible in an + * extremely noisy environment to experience occasional errors even + * without a hardware problem. If the sensor is well grounded, this + * is probably unavoidable in these environments. On the occasions + * where this counter counts a bad sample, that sample is ignored. + */ + + u32 error_count; /* offset 0x00ee */ + + /* Count_x is a counter which is incremented every time the JR3 DSP + * searches its job queues and finds nothing to do. It indicates the + * amount of idle time the JR3 DSP has available. It can also be + * used to determine if the JR3 DSP is alive. See the Performance + * Issues section on pg. 49 for more details. + */ + + u32 count_x; /* offset 0x00ef */ + + /* Warnings & errors contain the warning and error bits + * respectively. The format of these two words is discussed on page + * 21 under the headings warnings_bits and error_bits. + */ + + u32 warnings; /* offset 0x00f0 */ + u32 errors; /* offset 0x00f1 */ + + /* Threshold_bits is a word containing the bits that are set by the + * load envelopes. See load_envelopes (pg. 17) and thresh_struct + * (pg. 23) for more details. + */ + + s32 threshold_bits; /* offset 0x00f2 */ + + /* Last_crc is the value that shows the actual calculated CRC. CRC + * is short for cyclic redundancy code. It should be zero. See the + * description for cal_crc_bad (pg. 21) for more information. + */ + + s32 last_CRC; /* offset 0x00f3 */ + + /* EEProm_ver_no contains the version number of the sensor EEProm. + * EEProm version numbers can vary between 0 and 255. + * Software_ver_no contains the software version number. Version + * 3.02 would be stored as 302. + */ + + s32 eeprom_ver_no; /* offset 0x00f4 */ + s32 software_ver_no; /* offset 0x00f5 */ + + /* Software_day & software_year are the release date of the software + * the JR3 DSP is currently running. Day is the day of the year, + * with January 1 being 1, and December 31, being 365 for non leap + * years. + */ + + s32 software_day; /* offset 0x00f6 */ + s32 software_year; /* offset 0x00f7 */ + + /* Serial_no & model_no are the two values which uniquely identify a + * sensor. This model number does not directly correspond to the JR3 + * model number, but it will provide a unique identifier for + * different sensor configurations. + */ + + u32 serial_no; /* offset 0x00f8 */ + u32 model_no; /* offset 0x00f9 */ + + /* Cal_day & cal_year are the sensor calibration date. Day is the + * day of the year, with January 1 being 1, and December 31, being + * 366 for leap years. + */ + + s32 cal_day; /* offset 0x00fa */ + s32 cal_year; /* offset 0x00fb */ + + /* Units is an enumerated read only value defining the engineering + * units used in the sensor full scale. The meanings of particular + * values are discussed in the section detailing the force_units + * structure on page 22. The engineering units are setto customer + * specifications during sensor manufacture and cannot be changed by + * writing to Units. + * + * Bits contains the number of bits of resolution of the ADC + * currently in use. + * + * Channels is a bit field showing which channels the current sensor + * is capable of sending. If bit 0 is active, this sensor can send + * channel 0, if bit 13 is active, this sensor can send channel 13, + * etc. This bit can be active, even if the sensor is not currently + * sending this channel. Some sensors are configurable as to which + * channels to send, and this field only contains information on the + * channels available to send, not on the current configuration. To + * find which channels are currently being sent, monitor the + * Raw_time fields (pg. 19) in the raw_channels array (pg. 7). If + * the time is changing periodically, then that channel is being + * received. + */ + + u32 units; /* offset 0x00fc */ + s32 bits; /* offset 0x00fd */ + s32 channels; /* offset 0x00fe */ + + /* Thickness specifies the overall thickness of the sensor from + * flange to flange. The engineering units for this value are + * contained in units (pg. 16). The sensor calibration is relative + * to the center of the sensor. This value allows easy coordinate + * transformation from the center of the sensor to either flange. + */ + + s32 thickness; /* offset 0x00ff */ + + /* Load_envelopes is a table containing the load envelope + * descriptions. There are 16 possible load envelope slots in the + * table. The slots are on 16 word boundaries and are numbered 0-15. + * Each load envelope needs to start at the beginning of a slot but + * need not be fully contained in that slot. That is to say that a + * single load envelope can be larger than a single slot. The + * software has been tested and ran satisfactorily with 50 + * thresholds active. A single load envelope this large would take + * up 5 of the 16 slots. The load envelope data is laid out in an + * order that is most efficient for the JR3 DSP. The structure is + * detailed later in the section showing the definition of the + * le_struct structure (pg. 23). + */ + + struct le_struct load_envelopes[0x10]; /* offset 0x0100 */ + + /* Transforms is a table containing the transform descriptions. + * There are 16 possible transform slots in the table. The slots are + * on 16 word boundaries and are numbered 0-15. Each transform needs + * to start at the beginning of a slot but need not be fully + * contained in that slot. That is to say that a single transform + * can be larger than a single slot. A transform is 2 * no of links + * + 1 words in length. So a single slot can contain a transform + * with 7 links. Two slots can contain a transform that is 15 links. + * The layout is detailed later in the section showing the + * definition of the transform structure (pg. 26). + */ + + struct intern_transform transforms[0x10]; /* offset 0x0200 */ +}; + +struct jr3_t { + struct { + u32 program_low[0x4000]; /* 0x00000 - 0x10000 */ + struct jr3_channel data; /* 0x10000 - 0x10c00 */ + char pad2[0x30000 - 0x00c00]; /* 0x10c00 - 0x40000 */ + u32 program_high[0x8000]; /* 0x40000 - 0x60000 */ + u32 reset; /* 0x60000 - 0x60004 */ + char pad3[0x20000 - 0x00004]; /* 0x60004 - 0x80000 */ + } channel[4]; +}; diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c new file mode 100644 index 000000000000..79f6fe5646c5 --- /dev/null +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -0,0 +1,254 @@ +/* + comedi/drivers/ke_counter.c + Comedi driver for Kolter-Electronic PCI Counter 1 Card + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: ke_counter +Description: Driver for Kolter Electronic Counter Card +Devices: [Kolter Electronic] PCI Counter Card (ke_counter) +Author: Michael Hillmann +Updated: Mon, 14 Apr 2008 15:42:42 +0100 +Status: tested + +Configuration Options: + [0] - PCI bus of device (optional) + [1] - PCI slot of device (optional) + If bus/slot is not specified, the first supported + PCI device found will be used. + +This driver is a simple driver to read the counter values from +Kolter Electronic PCI Counter Card. +*/ + +#include "../comedidev.h" + +#include "comedi_pci.h" + +#define CNT_DRIVER_NAME "ke_counter" +#define PCI_VENDOR_ID_KOLTER 0x1001 +#define CNT_CARD_DEVICE_ID 0x0014 + +/*-- function prototypes ----------------------------------------------------*/ + +static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int cnt_detach(struct comedi_device * dev); + +static DEFINE_PCI_DEVICE_TABLE(cnt_pci_table) = { + {PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, cnt_pci_table); + +/*-- board specification structure ------------------------------------------*/ + +struct cnt_board_struct { + + const char *name; + int device_id; + int cnt_channel_nbr; + int cnt_bits; +}; + + +static const struct cnt_board_struct cnt_boards[] = { + { + name: CNT_DRIVER_NAME, + device_id:CNT_CARD_DEVICE_ID, + cnt_channel_nbr:3, + cnt_bits:24} +}; + +#define cnt_board_nbr (sizeof(cnt_boards)/sizeof(struct cnt_board_struct)) + +/*-- device private structure -----------------------------------------------*/ + +struct cnt_device_private { + + struct pci_dev *pcidev; +}; + + +#define devpriv ((struct cnt_device_private *)dev->private) + +static struct comedi_driver cnt_driver = { + driver_name:CNT_DRIVER_NAME, + module:THIS_MODULE, + attach:cnt_attach, + detach:cnt_detach, +}; + +COMEDI_PCI_INITCLEANUP(cnt_driver, cnt_pci_table); + +/*-- counter write ----------------------------------------------------------*/ + +/* This should be used only for resetting the counters; maybe it is better + to make a special command 'reset'. */ +static int cnt_winsn(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + + outb((unsigned char)((data[0] >> 24) & 0xff), + dev->iobase + chan * 0x20 + 0x10); + outb((unsigned char)((data[0] >> 16) & 0xff), + dev->iobase + chan * 0x20 + 0x0c); + outb((unsigned char)((data[0] >> 8) & 0xff), + dev->iobase + chan * 0x20 + 0x08); + outb((unsigned char)((data[0] >> 0) & 0xff), + dev->iobase + chan * 0x20 + 0x04); + + /* return the number of samples written */ + return 1; +} + +/*-- counter read -----------------------------------------------------------*/ + +static int cnt_rinsn(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + unsigned char a0, a1, a2, a3, a4; + int chan = CR_CHAN(insn->chanspec); + int result; + + a0 = inb(dev->iobase + chan * 0x20); + a1 = inb(dev->iobase + chan * 0x20 + 0x04); + a2 = inb(dev->iobase + chan * 0x20 + 0x08); + a3 = inb(dev->iobase + chan * 0x20 + 0x0c); + a4 = inb(dev->iobase + chan * 0x20 + 0x10); + + result = (a1 + (a2 * 256) + (a3 * 65536)); + if (a4 > 0) + result = result - s->maxdata; + + *data = (unsigned int) result; + + /* return the number of samples read */ + return 1; +} + +/*-- attach -----------------------------------------------------------------*/ + +static int cnt_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *subdevice; + struct pci_dev *pci_device; + struct cnt_board_struct *board; + unsigned long io_base; + int error, i; + + /* allocate device private structure */ + if ((error = alloc_private(dev, sizeof(struct cnt_device_private))) < 0) { + return error; + } + + /* Probe the device to determine what device in the series it is. */ + for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); + pci_device != NULL; + pci_device = + pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) { + if (pci_device->vendor == PCI_VENDOR_ID_KOLTER) { + for (i = 0; i < cnt_board_nbr; i++) { + if (cnt_boards[i].device_id == + pci_device->device) { + /* was a particular bus/slot requested? */ + if ((it->options[0] != 0) + || (it->options[1] != 0)) { + /* are we on the wrong bus/slot? */ + if (pci_device->bus->number != + it->options[0] + || PCI_SLOT(pci_device-> + devfn) != + it->options[1]) { + continue; + } + } + + dev->board_ptr = cnt_boards + i; + board = (struct cnt_board_struct *) dev-> + board_ptr; + goto found; + } + } + } + } + printk("comedi%d: no supported board found! (req. bus/slot: %d/%d)\n", + dev->minor, it->options[0], it->options[1]); + return -EIO; + + found: + printk("comedi%d: found %s at PCI bus %d, slot %d\n", dev->minor, + board->name, pci_device->bus->number, + PCI_SLOT(pci_device->devfn)); + devpriv->pcidev = pci_device; + dev->board_name = board->name; + + /* enable PCI device and request regions */ + if ((error = comedi_pci_enable(pci_device, CNT_DRIVER_NAME)) < 0) { + printk("comedi%d: failed to enable PCI device and request regions!\n", dev->minor); + return error; + } + + /* read register base address [PCI_BASE_ADDRESS #0] */ + io_base = pci_resource_start(pci_device, 0); + dev->iobase = io_base; + + /* allocate the subdevice structures */ + if ((error = alloc_subdevices(dev, 1)) < 0) { + return error; + } + + subdevice = dev->subdevices + 0; + dev->read_subdev = subdevice; + + subdevice->type = COMEDI_SUBD_COUNTER; + subdevice->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ; + subdevice->n_chan = board->cnt_channel_nbr; + subdevice->maxdata = (1 << board->cnt_bits) - 1; + subdevice->insn_read = cnt_rinsn; + subdevice->insn_write = cnt_winsn; + + // select 20MHz clock + outb(3, dev->iobase + 248); + + // reset all counters + outb(0, dev->iobase); + outb(0, dev->iobase + 0x20); + outb(0, dev->iobase + 0x40); + + printk("comedi%d: " CNT_DRIVER_NAME " attached.\n", dev->minor); + return 0; +} + +/*-- detach -----------------------------------------------------------------*/ + +static int cnt_detach(struct comedi_device * dev) +{ + if (devpriv && devpriv->pcidev) { + if (dev->iobase) { + comedi_pci_disable(devpriv->pcidev); + } + pci_dev_put(devpriv->pcidev); + } + printk("comedi%d: " CNT_DRIVER_NAME " remove\n", dev->minor); + return 0; +} diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index b432aa7d7644..12481a032b9f 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -92,7 +92,7 @@ static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = { MODULE_DEVICE_TABLE(pci, me4000_pci_table); -static const me4000_board_t me4000_boards[] = { +static const struct me4000_board me4000_boards[] = { {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0}}, {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3}}, @@ -113,108 +113,108 @@ static const me4000_board_t me4000_boards[] = { {0}, }; -#define ME4000_BOARD_VERSIONS (sizeof(me4000_boards) / sizeof(me4000_board_t) - 1) +#define ME4000_BOARD_VERSIONS (sizeof(me4000_boards) / sizeof(struct me4000_board) - 1) /*----------------------------------------------------------------------------- Comedi function prototypes ---------------------------------------------------------------------------*/ -static int me4000_attach(comedi_device * dev, comedi_devconfig * it); -static int me4000_detach(comedi_device * dev); -static comedi_driver driver_me4000 = { +static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int me4000_detach(struct comedi_device *dev); +static struct comedi_driver driver_me4000 = { driver_name:"me4000", - module:THIS_MODULE, - attach:me4000_attach, - detach:me4000_detach, + module : THIS_MODULE, + attach : me4000_attach, + detach : me4000_detach, }; /*----------------------------------------------------------------------------- Meilhaus function prototypes ---------------------------------------------------------------------------*/ -static int me4000_probe(comedi_device * dev, comedi_devconfig * it); -static int get_registers(comedi_device * dev, struct pci_dev *pci_dev_p); -static int init_board_info(comedi_device * dev, struct pci_dev *pci_dev_p); -static int init_ao_context(comedi_device * dev); -static int init_ai_context(comedi_device * dev); -static int init_dio_context(comedi_device * dev); -static int init_cnt_context(comedi_device * dev); -static int xilinx_download(comedi_device * dev); -static int reset_board(comedi_device * dev); +static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it); +static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p); +static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p); +static int init_ao_context(struct comedi_device *dev); +static int init_ai_context(struct comedi_device *dev); +static int init_dio_context(struct comedi_device *dev); +static int init_cnt_context(struct comedi_device *dev); +static int xilinx_download(struct comedi_device *dev); +static int reset_board(struct comedi_device *dev); -static int me4000_dio_insn_bits(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data); +static int me4000_dio_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -static int me4000_dio_insn_config(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data); +static int me4000_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -static int cnt_reset(comedi_device * dev, unsigned int channel); +static int cnt_reset(struct comedi_device *dev, unsigned int channel); -static int cnt_config(comedi_device * dev, +static int cnt_config(struct comedi_device *dev, unsigned int channel, unsigned int mode); -static int me4000_cnt_insn_config(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data); +static int me4000_cnt_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -static int me4000_cnt_insn_write(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data); +static int me4000_cnt_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -static int me4000_cnt_insn_read(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data); +static int me4000_cnt_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -static int me4000_ai_insn_read(comedi_device * dev, - comedi_subdevice * subdevice, comedi_insn * insn, lsampl_t * data); +static int me4000_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data); -static int me4000_ai_cancel(comedi_device * dev, comedi_subdevice * s); +static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s); -static int ai_check_chanlist(comedi_device * dev, - comedi_subdevice * s, comedi_cmd * cmd); +static int ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd); -static int ai_round_cmd_args(comedi_device * dev, - comedi_subdevice * s, - comedi_cmd * cmd, +static int ai_round_cmd_args(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd, unsigned int *init_ticks, unsigned int *scan_ticks, unsigned int *chan_ticks); -static int ai_prepare(comedi_device * dev, - comedi_subdevice * s, - comedi_cmd * cmd, +static int ai_prepare(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd, unsigned int init_ticks, unsigned int scan_ticks, unsigned int chan_ticks); -static int ai_write_chanlist(comedi_device * dev, - comedi_subdevice * s, comedi_cmd * cmd); +static int ai_write_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd); static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG); -static int me4000_ai_do_cmd_test(comedi_device * dev, - comedi_subdevice * s, comedi_cmd * cmd); +static int me4000_ai_do_cmd_test(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd); -static int me4000_ai_do_cmd(comedi_device * dev, comedi_subdevice * s); +static int me4000_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s); -static int me4000_ao_insn_write(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data); +static int me4000_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); -static int me4000_ao_insn_read(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data); +static int me4000_ao_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); /*----------------------------------------------------------------------------- Meilhaus inline functions ---------------------------------------------------------------------------*/ -static inline void me4000_outb(comedi_device * dev, unsigned char value, +static inline void me4000_outb(struct comedi_device *dev, unsigned char value, unsigned long port) { PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port); outb(value, port); } -static inline void me4000_outl(comedi_device * dev, unsigned long value, +static inline void me4000_outl(struct comedi_device *dev, unsigned long value, unsigned long port) { PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port); outl(value, port); } -static inline unsigned long me4000_inl(comedi_device * dev, unsigned long port) +static inline unsigned long me4000_inl(struct comedi_device *dev, unsigned long port) { unsigned long value; value = inl(port); @@ -222,7 +222,7 @@ static inline unsigned long me4000_inl(comedi_device * dev, unsigned long port) return value; } -static inline unsigned char me4000_inb(comedi_device * dev, unsigned long port) +static inline unsigned char me4000_inb(struct comedi_device *dev, unsigned long port) { unsigned char value; value = inb(port); @@ -230,7 +230,7 @@ static inline unsigned char me4000_inb(comedi_device * dev, unsigned long port) return value; } -static const comedi_lrange me4000_ai_range = { +static const struct comedi_lrange me4000_ai_range = { 4, { UNI_RANGE(2.5), @@ -240,16 +240,16 @@ static const comedi_lrange me4000_ai_range = { } }; -static const comedi_lrange me4000_ao_range = { +static const struct comedi_lrange me4000_ao_range = { 1, { BIP_RANGE(10), } }; -static int me4000_attach(comedi_device * dev, comedi_devconfig * it) +static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - comedi_subdevice *s; + struct comedi_subdevice *s; int result; CALL_PDEBUG("In me4000_attach()\n"); @@ -277,7 +277,7 @@ static int me4000_attach(comedi_device * dev, comedi_devconfig * it) s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; s->n_chan = thisboard->ai.count; - s->maxdata = 0xFFFF; // 16 bit ADC + s->maxdata = 0xFFFF; /* 16 bit ADC */ s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT; s->range_table = &me4000_ai_range; s->insn_read = me4000_ai_insn_read; @@ -312,7 +312,7 @@ static int me4000_attach(comedi_device * dev, comedi_devconfig * it) s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND; s->n_chan = thisboard->ao.count; - s->maxdata = 0xFFFF; // 16 bit DAC + s->maxdata = 0xFFFF; /* 16 bit DAC */ s->range_table = &me4000_ao_range; s->insn_write = me4000_ao_insn_write; s->insn_read = me4000_ao_insn_read; @@ -358,7 +358,7 @@ static int me4000_attach(comedi_device * dev, comedi_devconfig * it) s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = thisboard->cnt.count; - s->maxdata = 0xFFFF; // 16 bit counters + s->maxdata = 0xFFFF; /* 16 bit counters */ s->insn_read = me4000_cnt_insn_read; s->insn_write = me4000_cnt_insn_write; s->insn_config = me4000_cnt_insn_config; @@ -369,18 +369,18 @@ static int me4000_attach(comedi_device * dev, comedi_devconfig * it) return 0; } -static int me4000_probe(comedi_device * dev, comedi_devconfig * it) +static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it) { struct pci_dev *pci_device; int result, i; - me4000_board_t *board; + struct me4000_board *board; CALL_PDEBUG("In me4000_probe()\n"); /* Allocate private memory */ - if (alloc_private(dev, sizeof(me4000_info_t)) < 0) { + if (alloc_private(dev, sizeof(struct me4000_info)) < 0) return -ENOMEM; - } + /* * Probe the device to determine what device in the series it is. */ @@ -405,7 +405,7 @@ static int me4000_probe(comedi_device * dev, comedi_devconfig * it) } } dev->board_ptr = me4000_boards + i; - board = (me4000_board_t *) dev-> + board = (struct me4000_board *) dev-> board_ptr; info->pci_dev_p = pci_device; goto found; @@ -512,7 +512,7 @@ static int me4000_probe(comedi_device * dev, comedi_devconfig * it) return 0; } -static int get_registers(comedi_device * dev, struct pci_dev *pci_dev_p) +static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p) { CALL_PDEBUG("In get_registers()\n"); @@ -564,27 +564,25 @@ static int get_registers(comedi_device * dev, struct pci_dev *pci_dev_p) return 0; } -static int init_board_info(comedi_device * dev, struct pci_dev *pci_dev_p) +static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p) { int result; CALL_PDEBUG("In init_board_info()\n"); /* Init spin locks */ - //spin_lock_init(&info->preload_lock); - //spin_lock_init(&info->ai_ctrl_lock); + /* spin_lock_init(&info->preload_lock); */ + /* spin_lock_init(&info->ai_ctrl_lock); */ /* Get the serial number */ result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no); - if (result != PCIBIOS_SUCCESSFUL) { + if (result != PCIBIOS_SUCCESSFUL) return result; - } /* Get the hardware revision */ result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision); - if (result != PCIBIOS_SUCCESSFUL) { + if (result != PCIBIOS_SUCCESSFUL) return result; - } /* Get the vendor id */ info->vendor_id = pci_dev_p->vendor; @@ -598,14 +596,14 @@ static int init_board_info(comedi_device * dev, struct pci_dev *pci_dev_p) return 0; } -static int init_ao_context(comedi_device * dev) +static int init_ao_context(struct comedi_device *dev) { int i; CALL_PDEBUG("In init_ao_context()\n"); for (i = 0; i < thisboard->ao.count; i++) { - //spin_lock_init(&info->ao_context[i].use_lock); + /* spin_lock_init(&info->ao_context[i].use_lock); */ info->ao_context[i].irq = info->irq; switch (i) { @@ -681,7 +679,7 @@ static int init_ao_context(comedi_device * dev) return 0; } -static int init_ai_context(comedi_device * dev) +static int init_ai_context(struct comedi_device *dev) { CALL_PDEBUG("In init_ai_context()\n"); @@ -715,7 +713,7 @@ static int init_ai_context(comedi_device * dev) return 0; } -static int init_dio_context(comedi_device * dev) +static int init_dio_context(struct comedi_device *dev) { CALL_PDEBUG("In init_dio_context()\n"); @@ -734,7 +732,7 @@ static int init_dio_context(comedi_device * dev) return 0; } -static int init_cnt_context(comedi_device * dev) +static int init_cnt_context(struct comedi_device *dev) { CALL_PDEBUG("In init_cnt_context()\n"); @@ -755,7 +753,7 @@ static int init_cnt_context(comedi_device * dev) extern unsigned char *xilinx_firm; #endif -static int xilinx_download(comedi_device * dev) +static int xilinx_download(struct comedi_device *dev) { u32 value = 0; wait_queue_head_t queue; @@ -782,7 +780,7 @@ static int xilinx_download(comedi_device * dev) /* Wait until /INIT pin is set */ udelay(20); - if (!inl(info->plx_regbase + PLX_INTCSR) & 0x20) { + if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) { printk(KERN_ERR "comedi%d: me4000: xilinx_download(): Can't init Xilinx\n", dev->minor); @@ -837,7 +835,7 @@ static int xilinx_download(comedi_device * dev) return 0; } -static int reset_board(comedi_device * dev) +static int reset_board(struct comedi_device *dev) { unsigned long icr; @@ -895,16 +893,15 @@ static int reset_board(comedi_device * dev) return 0; } -static int me4000_detach(comedi_device * dev) +static int me4000_detach(struct comedi_device *dev) { CALL_PDEBUG("In me4000_detach()\n"); if (info) { if (info->pci_dev_p) { reset_board(dev); - if (info->plx_regbase) { + if (info->plx_regbase) comedi_pci_disable(info->pci_dev_p); - } pci_dev_put(info->pci_dev_p); } } @@ -916,8 +913,8 @@ static int me4000_detach(comedi_device * dev) Analog input section ===========================================================================*/ -static int me4000_ai_insn_read(comedi_device * dev, - comedi_subdevice * subdevice, comedi_insn * insn, lsampl_t * data) +static int me4000_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data) { int chan = CR_CHAN(insn->chanspec); @@ -1040,7 +1037,7 @@ static int me4000_ai_insn_read(comedi_device * dev, return 1; } -static int me4000_ai_cancel(comedi_device * dev, comedi_subdevice * s) +static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { unsigned long tmp; @@ -1057,8 +1054,8 @@ static int me4000_ai_cancel(comedi_device * dev, comedi_subdevice * s) return 0; } -static int ai_check_chanlist(comedi_device * dev, - comedi_subdevice * s, comedi_cmd * cmd) +static int ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd) { int aref; int i; @@ -1138,9 +1135,9 @@ static int ai_check_chanlist(comedi_device * dev, return 0; } -static int ai_round_cmd_args(comedi_device * dev, - comedi_subdevice * s, - comedi_cmd * cmd, +static int ai_round_cmd_args(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd, unsigned int *init_ticks, unsigned int *scan_ticks, unsigned int *chan_ticks) { @@ -1163,9 +1160,8 @@ static int ai_round_cmd_args(comedi_device * dev, rest = (cmd->start_arg * 33) % 1000; if (cmd->flags & TRIG_ROUND_NEAREST) { - if (rest > 33) { + if (rest > 33) (*init_ticks)++; - } } else if (cmd->flags & TRIG_ROUND_UP) { if (rest) (*init_ticks)++; @@ -1177,9 +1173,8 @@ static int ai_round_cmd_args(comedi_device * dev, rest = (cmd->scan_begin_arg * 33) % 1000; if (cmd->flags & TRIG_ROUND_NEAREST) { - if (rest > 33) { + if (rest > 33) (*scan_ticks)++; - } } else if (cmd->flags & TRIG_ROUND_UP) { if (rest) (*scan_ticks)++; @@ -1191,9 +1186,8 @@ static int ai_round_cmd_args(comedi_device * dev, rest = (cmd->convert_arg * 33) % 1000; if (cmd->flags & TRIG_ROUND_NEAREST) { - if (rest > 33) { + if (rest > 33) (*chan_ticks)++; - } } else if (cmd->flags & TRIG_ROUND_UP) { if (rest) (*chan_ticks)++; @@ -1207,7 +1201,7 @@ static int ai_round_cmd_args(comedi_device * dev, return 0; } -static void ai_write_timer(comedi_device * dev, +static void ai_write_timer(struct comedi_device *dev, unsigned int init_ticks, unsigned int scan_ticks, unsigned int chan_ticks) { @@ -1228,9 +1222,9 @@ static void ai_write_timer(comedi_device * dev, me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_timer_reg); } -static int ai_prepare(comedi_device * dev, - comedi_subdevice * s, - comedi_cmd * cmd, +static int ai_prepare(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd, unsigned int init_ticks, unsigned int scan_ticks, unsigned int chan_ticks) { @@ -1297,8 +1291,8 @@ static int ai_prepare(comedi_device * dev, return 0; } -static int ai_write_chanlist(comedi_device * dev, - comedi_subdevice * s, comedi_cmd * cmd) +static int ai_write_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd) { unsigned int entry; unsigned int chan; @@ -1337,13 +1331,13 @@ static int ai_write_chanlist(comedi_device * dev, return 0; } -static int me4000_ai_do_cmd(comedi_device * dev, comedi_subdevice * s) +static int me4000_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { int err; unsigned int init_ticks = 0; unsigned int scan_ticks = 0; unsigned int chan_ticks = 0; - comedi_cmd *cmd = &s->async->cmd; + struct comedi_cmd *cmd = &s->async->cmd; CALL_PDEBUG("In me4000_ai_do_cmd()\n"); @@ -1381,8 +1375,8 @@ static int me4000_ai_do_cmd(comedi_device * dev, comedi_subdevice * s) * - invalid chanlist * So I tried to adopt this scheme. */ -static int me4000_ai_do_cmd_test(comedi_device * dev, - comedi_subdevice * s, comedi_cmd * cmd) +static int me4000_ai_do_cmd_test(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd) { unsigned int init_ticks; @@ -1503,9 +1497,8 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, cmd->stop_src = TRIG_NONE; err++; } - if (err) { + if (err) return 1; - } /* * Stage 2. Check for trigger source conflicts. @@ -1553,9 +1546,8 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, cmd->scan_end_src = TRIG_NONE; err++; } - if (err) { + if (err) return 2; - } /* * Stage 3. Check if arguments are generally valid. @@ -1588,9 +1580,9 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, cmd->convert_arg = 2000; err++; } - if (err) { + + if (err) return 3; - } /* * Stage 4. Check for argument conflicts. @@ -1604,21 +1596,21 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", dev->minor); - cmd->start_arg = 2000; // 66 ticks at least + cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", dev->minor); - cmd->convert_arg = 2000; // 66 ticks at least + cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } if (scan_ticks <= cmd->chanlist_len * chan_ticks) { printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n", dev->minor); - cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; // At least one tick more + cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; /* At least one tick more */ err++; } } else if (cmd->start_src == TRIG_NOW && @@ -1630,14 +1622,14 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", dev->minor); - cmd->start_arg = 2000; // 66 ticks at least + cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", dev->minor); - cmd->convert_arg = 2000; // 66 ticks at least + cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } } else if (cmd->start_src == TRIG_EXT && @@ -1649,21 +1641,21 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", dev->minor); - cmd->start_arg = 2000; // 66 ticks at least + cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", dev->minor); - cmd->convert_arg = 2000; // 66 ticks at least + cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } if (scan_ticks <= cmd->chanlist_len * chan_ticks) { printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n", dev->minor); - cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; // At least one tick more + cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; /* At least one tick more */ err++; } } else if (cmd->start_src == TRIG_EXT && @@ -1675,14 +1667,14 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", dev->minor); - cmd->start_arg = 2000; // 66 ticks at least + cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", dev->minor); - cmd->convert_arg = 2000; // 66 ticks at least + cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } } else if (cmd->start_src == TRIG_EXT && @@ -1694,14 +1686,14 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", dev->minor); - cmd->start_arg = 2000; // 66 ticks at least + cmd->start_arg = 2000; /* 66 ticks at least */ err++; } if (chan_ticks < ME4000_AI_MIN_TICKS) { printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n", dev->minor); - cmd->convert_arg = 2000; // 66 ticks at least + cmd->convert_arg = 2000; /* 66 ticks at least */ err++; } } else if (cmd->start_src == TRIG_EXT && @@ -1713,7 +1705,7 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, printk(KERN_ERR "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n", dev->minor); - cmd->start_arg = 2000; // 66 ticks at least + cmd->start_arg = 2000; /* 66 ticks at least */ err++; } } @@ -1735,9 +1727,9 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, err++; } } - if (err) { + + if (err) return 4; - } /* * Stage 5. Check the channel list. @@ -1751,9 +1743,9 @@ static int me4000_ai_do_cmd_test(comedi_device * dev, static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG) { unsigned int tmp; - comedi_device *dev = dev_id; - comedi_subdevice *s = dev->subdevices; - me4000_ai_context_t *ai_context = &info->ai_context; + struct comedi_device *dev = dev_id; + struct comedi_subdevice *s = dev->subdevices; + struct me4000_ai_context *ai_context = &info->ai_context; int i; int c = 0; long lval; @@ -1911,8 +1903,8 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG) Analog output section ===========================================================================*/ -static int me4000_ao_insn_write(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int me4000_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int chan = CR_CHAN(insn->chanspec); @@ -1969,8 +1961,8 @@ static int me4000_ao_insn_write(comedi_device * dev, return 1; } -static int me4000_ao_insn_read(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int me4000_ao_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int chan = CR_CHAN(insn->chanspec); @@ -1990,16 +1982,16 @@ static int me4000_ao_insn_read(comedi_device * dev, Digital I/O section ===========================================================================*/ -static int me4000_dio_insn_bits(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int me4000_dio_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { CALL_PDEBUG("In me4000_dio_insn_bits()\n"); /* Length of data must be 2 (mask and new data, see below) */ - if (insn->n == 0) { + if (insn->n == 0) return 0; - } + if (insn->n != 2) { printk("comedi%d: me4000: me4000_dio_insn_bits(): Invalid instruction length\n", dev->minor); return -EINVAL; @@ -2041,8 +2033,8 @@ static int me4000_dio_insn_bits(comedi_device * dev, return 2; } -static int me4000_dio_insn_config(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int me4000_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned long tmp; int chan = CR_CHAN(insn->chanspec); @@ -2135,7 +2127,7 @@ static int me4000_dio_insn_config(comedi_device * dev, Counter section ===========================================================================*/ -static int cnt_reset(comedi_device * dev, unsigned int channel) +static int cnt_reset(struct comedi_device *dev, unsigned int channel) { CALL_PDEBUG("In cnt_reset()\n"); @@ -2166,7 +2158,7 @@ static int cnt_reset(comedi_device * dev, unsigned int channel) return 0; } -static int cnt_config(comedi_device * dev, unsigned int channel, +static int cnt_config(struct comedi_device *dev, unsigned int channel, unsigned int mode) { int tmp = 0; @@ -2223,8 +2215,8 @@ static int cnt_config(comedi_device * dev, unsigned int channel, return 0; } -static int me4000_cnt_insn_config(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int me4000_cnt_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int err; @@ -2266,17 +2258,17 @@ static int me4000_cnt_insn_config(comedi_device * dev, return 2; } -static int me4000_cnt_insn_read(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int me4000_cnt_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned short tmp; CALL_PDEBUG("In me4000_cnt_insn_read()\n"); - if (insn->n == 0) { + if (insn->n == 0) return 0; - } + if (insn->n > 1) { printk(KERN_ERR "comedi%d: me4000: me4000_cnt_insn_read(): Invalid instruction length %d\n", @@ -2313,8 +2305,8 @@ static int me4000_cnt_insn_read(comedi_device * dev, return 1; } -static int me4000_cnt_insn_write(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int me4000_cnt_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned short tmp; diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h index f12b8873ec3c..733b19243c75 100644 --- a/drivers/staging/comedi/drivers/me4000.h +++ b/drivers/staging/comedi/drivers/me4000.h @@ -28,37 +28,37 @@ Debug section ===========================================================================*/ -#undef ME4000_CALL_DEBUG // Debug function entry and exit -#undef ME4000_PORT_DEBUG // Debug port access -#undef ME4000_ISR_DEBUG // Debug the interrupt service routine -#undef ME4000_DEBUG // General purpose debug masseges +#undef ME4000_CALL_DEBUG /* Debug function entry and exit */ +#undef ME4000_PORT_DEBUG /* Debug port access */ +#undef ME4000_ISR_DEBUG /* Debug the interrupt service routine */ +#undef ME4000_DEBUG /* General purpose debug masseges */ #ifdef ME4000_CALL_DEBUG #undef CALL_PDEBUG #define CALL_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) #else -# define CALL_PDEBUG(fmt, args...) // no debugging, do nothing +# define CALL_PDEBUG(fmt, args...) /* no debugging, do nothing */ #endif #ifdef ME4000_PORT_DEBUG #undef PORT_PDEBUG #define PORT_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) #else -#define PORT_PDEBUG(fmt, args...) // no debugging, do nothing +#define PORT_PDEBUG(fmt, args...) /* no debugging, do nothing */ #endif #ifdef ME4000_ISR_DEBUG #undef ISR_PDEBUG #define ISR_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) #else -#define ISR_PDEBUG(fmt, args...) // no debugging, do nothing +#define ISR_PDEBUG(fmt, args...) /* no debugging, do nothing */ #endif #ifdef ME4000_DEBUG #undef PDEBUG #define PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args) #else -#define PDEBUG(fmt, args...) // no debugging, do nothing +#define PDEBUG(fmt, args...) /* no debugging, do nothing */ #endif /*============================================================================= @@ -67,78 +67,78 @@ #define PCI_VENDOR_ID_MEILHAUS 0x1402 -#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 // Low Cost version +#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 /* Low Cost version */ -#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 // Standard version -#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 // Isolated version -#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 // Standard version with Sample and Hold -#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 // Isolated version with Sample and Hold +#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 /* Standard version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 /* Isolated version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 /* Standard version with Sample and Hold */ +#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 /* Isolated version with Sample and Hold */ -#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 // Standard version -#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 // Isolated version -#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 // Standard version with Sample and Hold -#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 // Isolated version with Sample and Hold +#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 /* Standard version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 /* Isolated version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 /* Standard version with Sample and Hold */ +#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 /* Isolated version with Sample and Hold */ -#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 // Standard version -#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 // Isolated version -#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 // Standard version with Sample and Hold -#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 // Isolated version with Sample and Hold +#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 /* Standard version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 /* Isolated version */ +#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 /* Standard version with Sample and Hold */ +#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 /* Isolated version with Sample and Hold */ /*============================================================================= ME-4000 base register offsets ===========================================================================*/ -#define ME4000_AO_00_CTRL_REG 0x00 // R/W -#define ME4000_AO_00_STATUS_REG 0x04 // R/_ -#define ME4000_AO_00_FIFO_REG 0x08 // _/W -#define ME4000_AO_00_SINGLE_REG 0x0C // R/W -#define ME4000_AO_00_TIMER_REG 0x10 // _/W +#define ME4000_AO_00_CTRL_REG 0x00 /* R/W */ +#define ME4000_AO_00_STATUS_REG 0x04 /* R/_ */ +#define ME4000_AO_00_FIFO_REG 0x08 /* _/W */ +#define ME4000_AO_00_SINGLE_REG 0x0C /* R/W */ +#define ME4000_AO_00_TIMER_REG 0x10 /* _/W */ -#define ME4000_AO_01_CTRL_REG 0x18 // R/W -#define ME4000_AO_01_STATUS_REG 0x1C // R/_ -#define ME4000_AO_01_FIFO_REG 0x20 // _/W -#define ME4000_AO_01_SINGLE_REG 0x24 // R/W -#define ME4000_AO_01_TIMER_REG 0x28 // _/W +#define ME4000_AO_01_CTRL_REG 0x18 /* R/W */ +#define ME4000_AO_01_STATUS_REG 0x1C /* R/_ */ +#define ME4000_AO_01_FIFO_REG 0x20 /* _/W */ +#define ME4000_AO_01_SINGLE_REG 0x24 /* R/W */ +#define ME4000_AO_01_TIMER_REG 0x28 /* _/W */ -#define ME4000_AO_02_CTRL_REG 0x30 // R/W -#define ME4000_AO_02_STATUS_REG 0x34 // R/_ -#define ME4000_AO_02_FIFO_REG 0x38 // _/W -#define ME4000_AO_02_SINGLE_REG 0x3C // R/W -#define ME4000_AO_02_TIMER_REG 0x40 // _/W +#define ME4000_AO_02_CTRL_REG 0x30 /* R/W */ +#define ME4000_AO_02_STATUS_REG 0x34 /* R/_ */ +#define ME4000_AO_02_FIFO_REG 0x38 /* _/W */ +#define ME4000_AO_02_SINGLE_REG 0x3C /* R/W */ +#define ME4000_AO_02_TIMER_REG 0x40 /* _/W */ -#define ME4000_AO_03_CTRL_REG 0x48 // R/W -#define ME4000_AO_03_STATUS_REG 0x4C // R/_ -#define ME4000_AO_03_FIFO_REG 0x50 // _/W -#define ME4000_AO_03_SINGLE_REG 0x54 // R/W -#define ME4000_AO_03_TIMER_REG 0x58 // _/W +#define ME4000_AO_03_CTRL_REG 0x48 /* R/W */ +#define ME4000_AO_03_STATUS_REG 0x4C /* R/_ */ +#define ME4000_AO_03_FIFO_REG 0x50 /* _/W */ +#define ME4000_AO_03_SINGLE_REG 0x54 /* R/W */ +#define ME4000_AO_03_TIMER_REG 0x58 /* _/W */ -#define ME4000_AI_CTRL_REG 0x74 // _/W -#define ME4000_AI_STATUS_REG 0x74 // R/_ -#define ME4000_AI_CHANNEL_LIST_REG 0x78 // _/W -#define ME4000_AI_DATA_REG 0x7C // R/_ -#define ME4000_AI_CHAN_TIMER_REG 0x80 // _/W -#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84 // _/W -#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88 // _/W -#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8C // _/W -#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90 // _/W -#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 // _/W -#define ME4000_AI_START_REG 0x98 // R/_ +#define ME4000_AI_CTRL_REG 0x74 /* _/W */ +#define ME4000_AI_STATUS_REG 0x74 /* R/_ */ +#define ME4000_AI_CHANNEL_LIST_REG 0x78 /* _/W */ +#define ME4000_AI_DATA_REG 0x7C /* R/_ */ +#define ME4000_AI_CHAN_TIMER_REG 0x80 /* _/W */ +#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84 /* _/W */ +#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88 /* _/W */ +#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8C /* _/W */ +#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90 /* _/W */ +#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 /* _/W */ +#define ME4000_AI_START_REG 0x98 /* R/_ */ -#define ME4000_IRQ_STATUS_REG 0x9C // R/_ +#define ME4000_IRQ_STATUS_REG 0x9C /* R/_ */ -#define ME4000_DIO_PORT_0_REG 0xA0 // R/W -#define ME4000_DIO_PORT_1_REG 0xA4 // R/W -#define ME4000_DIO_PORT_2_REG 0xA8 // R/W -#define ME4000_DIO_PORT_3_REG 0xAC // R/W -#define ME4000_DIO_DIR_REG 0xB0 // R/W +#define ME4000_DIO_PORT_0_REG 0xA0 /* R/W */ +#define ME4000_DIO_PORT_1_REG 0xA4 /* R/W */ +#define ME4000_DIO_PORT_2_REG 0xA8 /* R/W */ +#define ME4000_DIO_PORT_3_REG 0xAC /* R/W */ +#define ME4000_DIO_DIR_REG 0xB0 /* R/W */ -#define ME4000_AO_LOADSETREG_XX 0xB4 // R/W +#define ME4000_AO_LOADSETREG_XX 0xB4 /* R/W */ -#define ME4000_DIO_CTRL_REG 0xB8 // R/W +#define ME4000_DIO_CTRL_REG 0xB8 /* R/W */ -#define ME4000_AO_DEMUX_ADJUST_REG 0xBC // -/W +#define ME4000_AO_DEMUX_ADJUST_REG 0xBC /* -/W */ -#define ME4000_AI_SAMPLE_COUNTER_REG 0xC0 // _/W +#define ME4000_AI_SAMPLE_COUNTER_REG 0xC0 /* _/W */ /*============================================================================= Value to adjust Demux @@ -159,21 +159,21 @@ PLX base register offsets ===========================================================================*/ -#define PLX_INTCSR 0x4C // Interrupt control and status register -#define PLX_ICR 0x50 // Initialization control register +#define PLX_INTCSR 0x4C /* Interrupt control and status register */ +#define PLX_ICR 0x50 /* Initialization control register */ /*============================================================================= Bits for the PLX_ICSR register ===========================================================================*/ -#define PLX_INTCSR_LOCAL_INT1_EN 0x01 // If set, local interrupt 1 is enabled (r/w) -#define PLX_INTCSR_LOCAL_INT1_POL 0x02 // If set, local interrupt 1 polarity is active high (r/w) -#define PLX_INTCSR_LOCAL_INT1_STATE 0x04 // If set, local interrupt 1 is active (r/_) -#define PLX_INTCSR_LOCAL_INT2_EN 0x08 // If set, local interrupt 2 is enabled (r/w) -#define PLX_INTCSR_LOCAL_INT2_POL 0x10 // If set, local interrupt 2 polarity is active high (r/w) -#define PLX_INTCSR_LOCAL_INT2_STATE 0x20 // If set, local interrupt 2 is active (r/_) -#define PLX_INTCSR_PCI_INT_EN 0x40 // If set, PCI interrupt is enabled (r/w) -#define PLX_INTCSR_SOFT_INT 0x80 // If set, a software interrupt is generated (r/w) +#define PLX_INTCSR_LOCAL_INT1_EN 0x01 /* If set, local interrupt 1 is enabled (r/w) */ +#define PLX_INTCSR_LOCAL_INT1_POL 0x02 /* If set, local interrupt 1 polarity is active high (r/w) */ +#define PLX_INTCSR_LOCAL_INT1_STATE 0x04 /* If set, local interrupt 1 is active (r/_) */ +#define PLX_INTCSR_LOCAL_INT2_EN 0x08 /* If set, local interrupt 2 is enabled (r/w) */ +#define PLX_INTCSR_LOCAL_INT2_POL 0x10 /* If set, local interrupt 2 polarity is active high (r/w) */ +#define PLX_INTCSR_LOCAL_INT2_STATE 0x20 /* If set, local interrupt 2 is active (r/_) */ +#define PLX_INTCSR_PCI_INT_EN 0x40 /* If set, PCI interrupt is enabled (r/w) */ +#define PLX_INTCSR_SOFT_INT 0x80 /* If set, a software interrupt is generated (r/w) */ /*============================================================================= Bits for the PLX_ICR register @@ -293,45 +293,45 @@ Information about the hardware capabilities ===========================================================================*/ -typedef struct me4000_ao_info { +struct me4000_ao_info { int count; int fifo_count; -} me4000_ao_info_t; +}; -typedef struct me4000_ai_info { +struct me4000_ai_info { int count; int sh_count; int diff_count; int ex_trig_analog; -} me4000_ai_info_t; +}; -typedef struct me4000_dio_info { +struct me4000_dio_info { int count; -} me4000_dio_info_t; +}; -typedef struct me4000_cnt_info { +struct me4000_cnt_info { int count; -} me4000_cnt_info_t; +}; -typedef struct me4000_board { +struct me4000_board { const char *name; unsigned short device_id; - me4000_ao_info_t ao; - me4000_ai_info_t ai; - me4000_dio_info_t dio; - me4000_cnt_info_t cnt; -} me4000_board_t; + struct me4000_ao_info ao; + struct me4000_ai_info ai; + struct me4000_dio_info dio; + struct me4000_cnt_info cnt; +}; -#define thisboard ((const me4000_board_t *)dev->board_ptr) +#define thisboard ((const struct me4000_board *)dev->board_ptr) /*============================================================================= Global board and subdevice information structures ===========================================================================*/ -typedef struct me4000_ao_context { +struct me4000_ao_context { int irq; - unsigned long mirror; // Store the last written value + unsigned long mirror; /* Store the last written value */ unsigned long ctrl_reg; unsigned long status_reg; @@ -340,9 +340,9 @@ typedef struct me4000_ao_context { unsigned long timer_reg; unsigned long irq_status_reg; unsigned long preload_reg; -} me4000_ao_context_t; +}; -typedef struct me4000_ai_context { +struct me4000_ai_context { int irq; unsigned long ctrl_reg; @@ -358,51 +358,51 @@ typedef struct me4000_ai_context { unsigned long start_reg; unsigned long irq_status_reg; unsigned long sample_counter_reg; -} me4000_ai_context_t; +}; -typedef struct me4000_dio_context { +struct me4000_dio_context { unsigned long dir_reg; unsigned long ctrl_reg; unsigned long port_0_reg; unsigned long port_1_reg; unsigned long port_2_reg; unsigned long port_3_reg; -} me4000_dio_context_t; +}; -typedef struct me4000_cnt_context { +struct me4000_cnt_context { unsigned long ctrl_reg; unsigned long counter_0_reg; unsigned long counter_1_reg; unsigned long counter_2_reg; -} me4000_cnt_context_t; +}; -typedef struct me4000_info { - unsigned long plx_regbase; // PLX configuration space base address - unsigned long me4000_regbase; // Base address of the ME4000 - unsigned long timer_regbase; // Base address of the timer circuit - unsigned long program_regbase; // Base address to set the program pin for the xilinx +struct me4000_info { + unsigned long plx_regbase; /* PLX configuration space base address */ + unsigned long me4000_regbase; /* Base address of the ME4000 */ + unsigned long timer_regbase; /* Base address of the timer circuit */ + unsigned long program_regbase; /* Base address to set the program pin for the xilinx */ - unsigned long plx_regbase_size; // PLX register set space - unsigned long me4000_regbase_size; // ME4000 register set space - unsigned long timer_regbase_size; // Timer circuit register set space - unsigned long program_regbase_size; // Size of program base address of the ME4000 + unsigned long plx_regbase_size; /* PLX register set space */ + unsigned long me4000_regbase_size; /* ME4000 register set space */ + unsigned long timer_regbase_size; /* Timer circuit register set space */ + unsigned long program_regbase_size; /* Size of program base address of the ME4000 */ - unsigned int serial_no; // Serial number of the board - unsigned char hw_revision; // Hardware revision of the board - unsigned short vendor_id; // Meilhaus vendor id - unsigned short device_id; // Device id + unsigned int serial_no; /* Serial number of the board */ + unsigned char hw_revision; /* Hardware revision of the board */ + unsigned short vendor_id; /* Meilhaus vendor id */ + unsigned short device_id; /* Device id */ - struct pci_dev *pci_dev_p; // General PCI information + struct pci_dev *pci_dev_p; /* General PCI information */ - unsigned int irq; // IRQ assigned from the PCI BIOS + unsigned int irq; /* IRQ assigned from the PCI BIOS */ - struct me4000_ai_context ai_context; // Analog input specific context - struct me4000_ao_context ao_context[4]; // Vector with analog output specific context - struct me4000_dio_context dio_context; // Digital I/O specific context - struct me4000_cnt_context cnt_context; // Counter specific context -} me4000_info_t; + struct me4000_ai_context ai_context; /* Analog input specific context */ + struct me4000_ao_context ao_context[4]; /* Vector with analog output specific context */ + struct me4000_dio_context dio_context; /* Digital I/O specific context */ + struct me4000_cnt_context cnt_context; /* Counter specific context */ +}; -#define info ((me4000_info_t *)dev->private) +#define info ((struct me4000_info *)dev->private) /*----------------------------------------------------------------------------- Defines for analog input @@ -412,7 +412,7 @@ typedef struct me4000_info { #define ME4000_AI_FIFO_COUNT 2048 #define ME4000_AI_MIN_TICKS 66 -#define ME4000_AI_MIN_SAMPLE_TIME 2000 // Minimum sample time [ns] +#define ME4000_AI_MIN_SAMPLE_TIME 2000 /* Minimum sample time [ns] */ #define ME4000_AI_BASE_FREQUENCY (unsigned int) 33E6 /* Channel list defines and masks */ @@ -436,11 +436,11 @@ typedef struct me4000_info { #define ME4000_CNT_COUNTER_1 0x40 #define ME4000_CNT_COUNTER_2 0x80 -#define ME4000_CNT_MODE_0 0x00 // Change state if zero crossing -#define ME4000_CNT_MODE_1 0x02 // Retriggerable One-Shot -#define ME4000_CNT_MODE_2 0x04 // Asymmetrical divider -#define ME4000_CNT_MODE_3 0x06 // Symmetrical divider -#define ME4000_CNT_MODE_4 0x08 // Counter start by software trigger -#define ME4000_CNT_MODE_5 0x0A // Counter start by hardware trigger +#define ME4000_CNT_MODE_0 0x00 /* Change state if zero crossing */ +#define ME4000_CNT_MODE_1 0x02 /* Retriggerable One-Shot */ +#define ME4000_CNT_MODE_2 0x04 /* Asymmetrical divider */ +#define ME4000_CNT_MODE_3 0x06 /* Symmetrical divider */ +#define ME4000_CNT_MODE_4 0x08 /* Counter start by software trigger */ +#define ME4000_CNT_MODE_5 0x0A /* Counter start by hardware trigger */ #endif diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index 6accec20a0f9..0f023d009e61 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -144,10 +144,10 @@ from http://www.comedi.org #define ME_COUNTER_VALUE_B 0x0022 /* R | - */ /* Function prototypes */ -static int me_attach(comedi_device *dev, comedi_devconfig *it); -static int me_detach(comedi_device *dev); +static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int me_detach(struct comedi_device *dev); -static const comedi_lrange me2000_ai_range = { +static const struct comedi_lrange me2000_ai_range = { 8, { BIP_RANGE(10), @@ -161,7 +161,7 @@ static const comedi_lrange me2000_ai_range = { } }; -static const comedi_lrange me2600_ai_range = { +static const struct comedi_lrange me2600_ai_range = { 8, { BIP_RANGE(10), @@ -175,7 +175,7 @@ static const comedi_lrange me2600_ai_range = { } }; -static const comedi_lrange me2600_ao_range = { +static const struct comedi_lrange me2600_ao_range = { 3, { BIP_RANGE(10), @@ -201,11 +201,11 @@ struct me_board { int ao_channel_nbr; /* DA config */ int ao_resolution; int ao_resolution_mask; - const comedi_lrange *ao_range_list; + const struct comedi_lrange *ao_range_list; int ai_channel_nbr; /* AD config */ int ai_resolution; int ai_resolution_mask; - const comedi_lrange *ai_range_list; + const struct comedi_lrange *ai_range_list; int dio_channel_nbr; /* DIO config */ }; @@ -246,7 +246,8 @@ static const struct me_board me_boards[] = { #define me_board_nbr (sizeof(me_boards)/sizeof(struct me_board)) -static comedi_driver me_driver = { + +static struct comedi_driver me_driver = { .driver_name = ME_DRIVER_NAME, .module = THIS_MODULE, .attach = me_attach, @@ -290,8 +291,8 @@ static inline void sleep(unsigned sec) * * ------------------------------------------------------------------ */ -static int me_dio_insn_config(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int me_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int bits; int mask = 1 << CR_CHAN(insn->chanspec); @@ -326,8 +327,8 @@ static int me_dio_insn_config(comedi_device *dev, comedi_subdevice *s, } /* Digital instant input/outputs */ -static int me_dio_insn_bits(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int me_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { unsigned int mask = data[0]; s->state &= ~mask; @@ -362,8 +363,8 @@ static int me_dio_insn_bits(comedi_device *dev, comedi_subdevice *s, */ /* Analog instant input */ -static int me_ai_insn_read(comedi_device *dev, comedi_subdevice *subdevice, - comedi_insn *insn, lsampl_t *data) +static int me_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *subdevice, + struct comedi_insn *insn, unsigned int *data) { unsigned short value; int chan = CR_CHAN((&insn->chanspec)[0]); @@ -436,7 +437,7 @@ static int me_ai_insn_read(comedi_device *dev, comedi_subdevice *subdevice, */ /* Cancel analog input autoscan */ -static int me_ai_cancel(comedi_device *dev, comedi_subdevice *s) +static int me_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { /* disable interrupts */ @@ -448,14 +449,14 @@ static int me_ai_cancel(comedi_device *dev, comedi_subdevice *s) } /* Test analog input command */ -static int me_ai_do_cmd_test(comedi_device *dev, comedi_subdevice *s, - comedi_cmd *cmd) +static int me_ai_do_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd) { return 0; } /* Analog input command */ -static int me_ai_do_cmd(comedi_device *dev, comedi_subdevice *subdevice) +static int me_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *subdevice) { return 0; } @@ -469,8 +470,8 @@ static int me_ai_do_cmd(comedi_device *dev, comedi_subdevice *subdevice) */ /* Analog instant output */ -static int me_ao_insn_write(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int me_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int chan; int rang; @@ -519,8 +520,8 @@ static int me_ao_insn_write(comedi_device *dev, comedi_subdevice *s, } /* Analog output readback */ -static int me_ao_insn_read(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int me_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int i; @@ -541,7 +542,7 @@ static int me_ao_insn_read(comedi_device *dev, comedi_subdevice *s, */ /* Xilinx firmware download for card: ME-2600i */ -static int me2600_xilinx_download(comedi_device *dev, +static int me2600_xilinx_download(struct comedi_device *dev, unsigned char *me2600_firmware, unsigned int length) { @@ -609,7 +610,7 @@ static int me2600_xilinx_download(comedi_device *dev, } /* Reset device */ -static int me_reset(comedi_device *dev) +static int me_reset(struct comedi_device *dev) { /* Reset board */ writew(0x00, dev_private->me_regbase + ME_CONTROL_1); @@ -631,10 +632,10 @@ static int me_reset(comedi_device *dev) * - Register PCI device * - Declare device driver capability */ -static int me_attach(comedi_device *dev, comedi_devconfig *it) +static int me_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct pci_dev *pci_device; - comedi_subdevice *subdevice; + struct comedi_subdevice *subdevice; struct me_board *board; resource_size_t plx_regbase_tmp; unsigned long plx_regbase_size_tmp; @@ -825,7 +826,7 @@ found: } /* Detach */ -static int me_detach(comedi_device *dev) +static int me_detach(struct comedi_device *dev) { if (dev_private) { if (dev_private->me_regbase) { diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 9cc527424d04..ae9017744537 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -47,7 +47,7 @@ */ -//#define USE_KMALLOC +/* #define USE_KMALLOC */ #include "mite.h" @@ -63,7 +63,7 @@ MODULE_LICENSE("GPL"); -struct mite_struct *mite_devices = NULL; +struct mite_struct *mite_devices; #define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK))) @@ -103,7 +103,7 @@ static void dump_chip_signature(u32 csigr_bits) printk("mite: num channels = %i, write post fifo depth = %i, wins = %i, iowins = %i\n", mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits), mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits)); } -unsigned mite_fifo_size(struct mite_struct * mite, unsigned channel) +unsigned mite_fifo_size(struct mite_struct *mite, unsigned channel) { unsigned fcr_bits = readl(mite->mite_io_addr + MITE_FCR(channel)); @@ -139,7 +139,7 @@ int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1) addr = pci_resource_start(mite->pcidev, 1); mite->daq_phys_addr = addr; length = pci_resource_len(mite->pcidev, 1); - // In case of a 660x board, DAQ size is 8k instead of 4k (see as shown by lspci output) + /* In case of a 660x board, DAQ size is 8k instead of 4k (see as shown by lspci output) */ mite->daq_io_addr = ioremap(mite->daq_phys_addr, length); if (!mite->daq_io_addr) { printk("failed to remap daq io memory address\n"); @@ -212,7 +212,7 @@ void mite_cleanup(void) void mite_unsetup(struct mite_struct *mite) { - //unsigned long offset, start, length; + /* unsigned long offset, start, length; */ if (!mite) return; @@ -257,7 +257,7 @@ struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, unsigned long flags; struct mite_channel *channel = NULL; - // spin lock so mite_release_channel can be called safely from interrupts + /* spin lock so mite_release_channel can be called safely from interrupts */ comedi_spin_lock_irqsave(&mite->lock, flags); for (i = min_channel; i <= max_channel; ++i) { if (mite->channel_allocated[i] == 0) { @@ -276,7 +276,7 @@ void mite_release_channel(struct mite_channel *mite_chan) struct mite_struct *mite = mite_chan->mite; unsigned long flags; - // spin lock to prevent races with mite_request_channel + /* spin lock to prevent races with mite_request_channel */ comedi_spin_lock_irqsave(&mite->lock, flags); if (mite->channel_allocated[mite_chan->channel]) { mite_dma_disarm(mite_chan); @@ -312,12 +312,12 @@ void mite_dma_arm(struct mite_channel *mite_chan) writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel)); mmiowb(); comedi_spin_unlock_irqrestore(&mite->lock, flags); -// mite_dma_tcr(mite, channel); +/* mite_dma_tcr(mite, channel); */ } /**************************************/ -int mite_buf_change(struct mite_dma_descriptor_ring *ring, comedi_async * async) +int mite_buf_change(struct mite_dma_descriptor_ring *ring, struct comedi_async * async) { unsigned int n_links; int i; @@ -331,9 +331,9 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, comedi_async * async) ring->descriptors_dma_addr = 0; ring->n_links = 0; - if (async->prealloc_bufsz == 0) { + if (async->prealloc_bufsz == 0) return 0; - } + n_links = async->prealloc_bufsz >> PAGE_SHIFT; MDPRINTK("ring->hw_dev=%p, n_links=0x%04x\n", ring->hw_dev, n_links); @@ -395,9 +395,9 @@ void mite_prep_dma(struct mite_channel *mite_chan, on e-series boards. */ chcr |= CHCR_BYTE_SWAP_DEVICE | CHCR_BYTE_SWAP_MEMORY; } - if (mite_chan->dir == COMEDI_INPUT) { + if (mite_chan->dir == COMEDI_INPUT) chcr |= CHCR_DEV_TO_MEM; - } + writel(chcr, mite->mite_io_addr + MITE_CHCR(mite_chan->channel)); /* to/from memory */ @@ -459,15 +459,15 @@ u32 mite_device_bytes_transferred(struct mite_channel *mite_chan) return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel)); } -u32 mite_bytes_in_transit(struct mite_channel * mite_chan) +u32 mite_bytes_in_transit(struct mite_channel *mite_chan) { struct mite_struct *mite = mite_chan->mite; return readl(mite->mite_io_addr + MITE_FCR(mite_chan->channel)) & 0x000000FF; } -// returns lower bound for number of bytes transferred from device to memory -u32 mite_bytes_written_to_memory_lb(struct mite_channel * mite_chan) +/* returns lower bound for number of bytes transferred from device to memory */ +u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan) { u32 device_byte_count; @@ -475,8 +475,8 @@ u32 mite_bytes_written_to_memory_lb(struct mite_channel * mite_chan) return device_byte_count - mite_bytes_in_transit(mite_chan); } -// returns upper bound for number of bytes transferred from device to memory -u32 mite_bytes_written_to_memory_ub(struct mite_channel * mite_chan) +/* returns upper bound for number of bytes transferred from device to memory */ +u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan) { u32 in_transit_count; @@ -484,8 +484,8 @@ u32 mite_bytes_written_to_memory_ub(struct mite_channel * mite_chan) return mite_device_bytes_transferred(mite_chan) - in_transit_count; } -// returns lower bound for number of bytes read from memory for transfer to device -u32 mite_bytes_read_from_memory_lb(struct mite_channel * mite_chan) +/* returns lower bound for number of bytes read from memory for transfer to device */ +u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan) { u32 device_byte_count; @@ -493,8 +493,8 @@ u32 mite_bytes_read_from_memory_lb(struct mite_channel * mite_chan) return device_byte_count + mite_bytes_in_transit(mite_chan); } -// returns upper bound for number of bytes read from memory for transfer to device -u32 mite_bytes_read_from_memory_ub(struct mite_channel * mite_chan) +/* returns upper bound for number of bytes read from memory for transfer to device */ +u32 mite_bytes_read_from_memory_ub(struct mite_channel *mite_chan) { u32 in_transit_count; @@ -526,14 +526,14 @@ void mite_dma_disarm(struct mite_channel *mite_chan) writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel)); } -int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async) +int mite_sync_input_dma(struct mite_channel *mite_chan, struct comedi_async * async) { int count; unsigned int nbytes, old_alloc_count; const unsigned bytes_per_scan = cfc_bytes_per_scan(async->subdevice); old_alloc_count = async->buf_write_alloc_count; - // write alloc as much as we can + /* write alloc as much as we can */ comedi_buf_write_alloc(async, async->prealloc_bufsz); nbytes = mite_bytes_written_to_memory_lb(mite_chan); @@ -547,9 +547,9 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async) count = nbytes - async->buf_write_count; /* it's possible count will be negative due to * conservative value returned by mite_bytes_written_to_memory_lb */ - if (count <= 0) { + if (count <= 0) return 0; - } + comedi_buf_write_free(async, count); async->scan_progress += count; @@ -561,7 +561,7 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async) return 0; } -int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async) +int mite_sync_output_dma(struct mite_channel *mite_chan, struct comedi_async * async) { int count; u32 nbytes_ub, nbytes_lb; @@ -570,7 +570,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async) async->cmd.stop_arg * cfc_bytes_per_scan(async->subdevice); old_alloc_count = async->buf_read_alloc_count; - // read alloc as much as we can + /* read alloc as much as we can */ comedi_buf_read_alloc(async, async->prealloc_bufsz); nbytes_lb = mite_bytes_read_from_memory_lb(mite_chan); if (async->cmd.stop_src == TRIG_COUNT && @@ -586,9 +586,9 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async) return -1; } count = nbytes_lb - async->buf_read_count; - if (count <= 0) { + if (count <= 0) return 0; - } + if (count) { comedi_buf_read_free(async, count); async->events |= COMEDI_CB_BLOCK; @@ -753,9 +753,8 @@ static void mite_decode(char **bit_str, unsigned int bits) int i; for (i = 31; i >= 0; i--) { - if (bits & (1 << i)) { + if (bits & (1 << i)) printk(" %s", bit_str[i]); - } } printk("\n"); } diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index b84eafa6ff2b..cdaf8a31688a 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -29,13 +29,13 @@ #define PCI_VENDOR_ID_NATINST 0x1093 -// #define DEBUG_MITE +/* #define DEBUG_MITE */ #define PCIMIO_COMPAT #ifdef DEBUG_MITE -#define MDPRINTK(format,args...) printk(format , ## args ) +#define MDPRINTK(format, args...) printk(format , ## args) #else -#define MDPRINTK(format,args...) +#define MDPRINTK(format, args...) #endif #define MAX_MITE_DMA_CHANNELS 8 @@ -142,8 +142,8 @@ void mite_release_channel(struct mite_channel *mite_chan); unsigned mite_dma_tcr(struct mite_channel *mite_chan); void mite_dma_arm(struct mite_channel *mite_chan); void mite_dma_disarm(struct mite_channel *mite_chan); -int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async); -int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async); +int mite_sync_input_dma(struct mite_channel *mite_chan, struct comedi_async * async); +int mite_sync_output_dma(struct mite_channel *mite_chan, struct comedi_async * async); u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan); u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan); u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan); @@ -153,7 +153,7 @@ unsigned mite_get_status(struct mite_channel *mite_chan); int mite_done(struct mite_channel *mite_chan); #if 0 -unsigned long mite_ll_from_kvmem(struct mite_struct *mite, comedi_async * async, +unsigned long mite_ll_from_kvmem(struct mite_struct *mite, struct comedi_async * async, int len); void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan, int dir); @@ -162,7 +162,7 @@ void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan, void mite_prep_dma(struct mite_channel *mite_chan, unsigned int num_device_bits, unsigned int num_memory_bits); int mite_buf_change(struct mite_dma_descriptor_ring *ring, - comedi_async * async); + struct comedi_async *async); #ifdef DEBUG_MITE void mite_print_chsr(unsigned int chsr); @@ -179,83 +179,83 @@ enum mite_registers { written and read back. The bits 0x1f always read as 1. The rest always read as zero. */ MITE_UNKNOWN_DMA_BURST_REG = 0x28, - MITE_IODWBSR = 0xc0, //IO Device Window Base Size Register - MITE_IODWBSR_1 = 0xc4, // IO Device Window Base Size Register 1 + MITE_IODWBSR = 0xc0, /* IO Device Window Base Size Register */ + MITE_IODWBSR_1 = 0xc4, /* IO Device Window Base Size Register 1 */ MITE_IODWCR_1 = 0xf4, MITE_PCI_CONFIG_OFFSET = 0x300, - MITE_CSIGR = 0x460 //chip signature + MITE_CSIGR = 0x460 /* chip signature */ }; -static inline int MITE_CHOR(int channel) // channel operation +static inline int MITE_CHOR(int channel) /* channel operation */ { return CHAN_OFFSET(channel) + 0x0; }; -static inline int MITE_CHCR(int channel) // channel control +static inline int MITE_CHCR(int channel) /* channel control */ { return CHAN_OFFSET(channel) + 0x4; }; -static inline int MITE_TCR(int channel) // transfer count +static inline int MITE_TCR(int channel) /* transfer count */ { return CHAN_OFFSET(channel) + 0x8; }; -static inline int MITE_MCR(int channel) // memory configuration +static inline int MITE_MCR(int channel) /* memory configuration */ { return CHAN_OFFSET(channel) + 0xc; }; -static inline int MITE_MAR(int channel) // memory address +static inline int MITE_MAR(int channel) /* memory address */ { return CHAN_OFFSET(channel) + 0x10; }; -static inline int MITE_DCR(int channel) // device configuration +static inline int MITE_DCR(int channel) /* device configuration */ { return CHAN_OFFSET(channel) + 0x14; }; -static inline int MITE_DAR(int channel) // device address +static inline int MITE_DAR(int channel) /* device address */ { return CHAN_OFFSET(channel) + 0x18; }; -static inline int MITE_LKCR(int channel) // link configuration +static inline int MITE_LKCR(int channel) /* link configuration */ { return CHAN_OFFSET(channel) + 0x1c; }; -static inline int MITE_LKAR(int channel) // link address +static inline int MITE_LKAR(int channel) /* link address */ { return CHAN_OFFSET(channel) + 0x20; }; -static inline int MITE_LLKAR(int channel) // see mite section of tnt5002 manual +static inline int MITE_LLKAR(int channel) /* see mite section of tnt5002 manual */ { return CHAN_OFFSET(channel) + 0x24; }; -static inline int MITE_BAR(int channel) // base address +static inline int MITE_BAR(int channel) /* base address */ { return CHAN_OFFSET(channel) + 0x28; }; -static inline int MITE_BCR(int channel) // base count +static inline int MITE_BCR(int channel) /* base count */ { return CHAN_OFFSET(channel) + 0x2c; }; -static inline int MITE_SAR(int channel) // ? address +static inline int MITE_SAR(int channel) /* ? address */ { return CHAN_OFFSET(channel) + 0x30; }; -static inline int MITE_WSCR(int channel) // ? +static inline int MITE_WSCR(int channel) /* ? */ { return CHAN_OFFSET(channel) + 0x34; }; -static inline int MITE_WSER(int channel) // ? +static inline int MITE_WSER(int channel) /* ? */ { return CHAN_OFFSET(channel) + 0x38; }; -static inline int MITE_CHSR(int channel) // channel status +static inline int MITE_CHSR(int channel) /* channel status */ { return CHAN_OFFSET(channel) + 0x3c; }; -static inline int MITE_FCR(int channel) // fifo count +static inline int MITE_FCR(int channel) /* fifo count */ { return CHAN_OFFSET(channel) + 0x40; }; enum MITE_IODWBSR_bits { - WENAB = 0x80, // window enable + WENAB = 0x80, /* window enable */ }; static inline unsigned MITE_IODWBSR_1_WSIZE_bits(unsigned size) @@ -276,23 +276,23 @@ static inline int mite_csigr_version(u32 csigr_bits) return csigr_bits & 0xf; }; static inline int mite_csigr_type(u32 csigr_bits) -{ // original mite = 0, minimite = 1 +{ /* original mite = 0, minimite = 1 */ return (csigr_bits >> 4) & 0xf; }; static inline int mite_csigr_mmode(u32 csigr_bits) -{ // mite mode, minimite = 1 +{ /* mite mode, minimite = 1 */ return (csigr_bits >> 8) & 0x3; }; static inline int mite_csigr_imode(u32 csigr_bits) -{ // cpu port interface mode, pci = 0x3 +{ /* cpu port interface mode, pci = 0x3 */ return (csigr_bits >> 12) & 0x3; }; static inline int mite_csigr_dmac(u32 csigr_bits) -{ // number of dma channels +{ /* number of dma channels */ return (csigr_bits >> 16) & 0xf; }; static inline int mite_csigr_wpdep(u32 csigr_bits) -{ // write post fifo depth +{ /* write post fifo depth */ unsigned int wpdep_bits = (csigr_bits >> 20) & 0x7; if (wpdep_bits == 0) return 0; @@ -304,7 +304,7 @@ static inline int mite_csigr_wins(u32 csigr_bits) return (csigr_bits >> 24) & 0x1f; }; static inline int mite_csigr_iowins(u32 csigr_bits) -{ // number of io windows +{ /* number of io windows */ return (csigr_bits >> 29) & 0x7; }; diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c new file mode 100644 index 000000000000..a151602929d9 --- /dev/null +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -0,0 +1,386 @@ +/* + comedi/drivers/mpc624.c + Hardware driver for a Micro/sys inc. MPC-624 PC/104 board + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: mpc624 +Description: Micro/sys MPC-624 PC/104 board +Devices: [Micro/sys] MPC-624 (mpc624) +Author: Stanislaw Raczynski +Updated: Thu, 15 Sep 2005 12:01:18 +0200 +Status: working + + The Micro/sys MPC-624 board is based on the LTC2440 24-bit sigma-delta + ADC chip. + + Subdevices supported by the driver: + - Analog In: supported + - Digital I/O: not supported + - LEDs: not supported + - EEPROM: not supported + +Configuration Options: + [0] - I/O base address + [1] - convertion rate + Convertion rate RMS noise Effective Number Of Bits + 0 3.52kHz 23uV 17 + 1 1.76kHz 3.5uV 20 + 2 880Hz 2uV 21.3 + 3 440Hz 1.4uV 21.8 + 4 220Hz 1uV 22.4 + 5 110Hz 750uV 22.9 + 6 55Hz 510nV 23.4 + 7 27.5Hz 375nV 24 + 8 13.75Hz 250nV 24.4 + 9 6.875Hz 200nV 24.6 + [2] - voltage range + 0 -1.01V .. +1.01V + 1 -10.1V .. +10.1V +*/ + +#include "../comedidev.h" + +#include +#include + +// Consecutive I/O port addresses +#define MPC624_SIZE 16 + +// Offsets of different ports +#define MPC624_MASTER_CONTROL 0 // not used +#define MPC624_GNMUXCH 1 // Gain, Mux, Channel of ADC +#define MPC624_ADC 2 // read/write to/from ADC +#define MPC624_EE 3 // read/write to/from serial EEPROM via I2C +#define MPC624_LEDS 4 // write to LEDs +#define MPC624_DIO 5 // read/write to/from digital I/O ports +#define MPC624_IRQ_MASK 6 // IRQ masking enable/disable + +// Register bits' names +#define MPC624_ADBUSY (1<<5) +#define MPC624_ADSDO (1<<4) +#define MPC624_ADFO (1<<3) +#define MPC624_ADCS (1<<2) +#define MPC624_ADSCK (1<<1) +#define MPC624_ADSDI (1<<0) + +// SDI Speed/Resolution Programming bits +#define MPC624_OSR4 (1<<31) +#define MPC624_OSR3 (1<<30) +#define MPC624_OSR2 (1<<29) +#define MPC624_OSR1 (1<<28) +#define MPC624_OSR0 (1<<27) + +// 32-bit output value bits' names +#define MPC624_EOC_BIT (1<<31) +#define MPC624_DMY_BIT (1<<30) +#define MPC624_SGN_BIT (1<<29) + +// Convertion speeds +/* OSR4 OSR3 OSR2 OSR1 OSR0 Convertion rate RMS noise ENOB^ + * X 0 0 0 1 3.52kHz 23uV 17 + * X 0 0 1 0 1.76kHz 3.5uV 20 + * X 0 0 1 1 880Hz 2uV 21.3 + * X 0 1 0 0 440Hz 1.4uV 21.8 + * X 0 1 0 1 220Hz 1uV 22.4 + * X 0 1 1 0 110Hz 750uV 22.9 + * X 0 1 1 1 55Hz 510nV 23.4 + * X 1 0 0 0 27.5Hz 375nV 24 + * X 1 0 0 1 13.75Hz 250nV 24.4 + * X 1 1 1 1 6.875Hz 200nV 24.6 + * + * ^ - Effective Number Of Bits + */ + +#define MPC624_SPEED_3_52_kHz (MPC624_OSR4 | MPC624_OSR0) +#define MPC624_SPEED_1_76_kHz (MPC624_OSR4 | MPC624_OSR1 ) +#define MPC624_SPEED_880_Hz (MPC624_OSR4 | MPC624_OSR1 | MPC624_OSR0) +#define MPC624_SPEED_440_Hz (MPC624_OSR4 | MPC624_OSR2 ) +#define MPC624_SPEED_220_Hz (MPC624_OSR4 | MPC624_OSR2 | MPC624_OSR0) +#define MPC624_SPEED_110_Hz (MPC624_OSR4 | MPC624_OSR2 | MPC624_OSR1 ) +#define MPC624_SPEED_55_Hz (MPC624_OSR4 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0) +#define MPC624_SPEED_27_5_Hz (MPC624_OSR4 | MPC624_OSR3 ) +#define MPC624_SPEED_13_75_Hz (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR0) +#define MPC624_SPEED_6_875_Hz (MPC624_OSR4 | MPC624_OSR3 | MPC624_OSR2 | MPC624_OSR1 | MPC624_OSR0) +//---------------------------------------------------------------------------- +struct skel_private { + + unsigned long int ulConvertionRate; // set by mpc624_attach() from driver's parameters +}; + + +#define devpriv ((struct skel_private *)dev->private) +//---------------------------------------------------------------------------- +static const struct comedi_lrange range_mpc624_bipolar1 = { + 1, + { +// BIP_RANGE(1.01) // this is correct, + // but my MPC-624 actually seems to have a range of 2.02 + BIP_RANGE(2.02) + } +}; +static const struct comedi_lrange range_mpc624_bipolar10 = { + 1, + { +// BIP_RANGE(10.1) // this is correct, + // but my MPC-624 actually seems to have a range of 20.2 + BIP_RANGE(20.2) + } +}; + +//---------------------------------------------------------------------------- +static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int mpc624_detach(struct comedi_device * dev); +//---------------------------------------------------------------------------- +static struct comedi_driver driver_mpc624 = { + driver_name:"mpc624", + module:THIS_MODULE, + attach:mpc624_attach, + detach:mpc624_detach +}; + +//---------------------------------------------------------------------------- +static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +//---------------------------------------------------------------------------- +static int mpc624_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + + iobase = it->options[0]; + rt_printk("comedi%d: mpc624 [0x%04lx, ", dev->minor, iobase); + if (request_region(iobase, MPC624_SIZE, "mpc624") == NULL) { + rt_printk("I/O port(s) in use\n"); + return -EIO; + } + + dev->iobase = iobase; + dev->board_name = "mpc624"; + + // Private structure initialization + if (alloc_private(dev, sizeof(struct skel_private)) < 0) + return -ENOMEM; + + switch (it->options[1]) { + case 0: + devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; + rt_printk("3.52 kHz, "); + break; + case 1: + devpriv->ulConvertionRate = MPC624_SPEED_1_76_kHz; + rt_printk("1.76 kHz, "); + break; + case 2: + devpriv->ulConvertionRate = MPC624_SPEED_880_Hz; + rt_printk("880 Hz, "); + break; + case 3: + devpriv->ulConvertionRate = MPC624_SPEED_440_Hz; + rt_printk("440 Hz, "); + break; + case 4: + devpriv->ulConvertionRate = MPC624_SPEED_220_Hz; + rt_printk("220 Hz, "); + break; + case 5: + devpriv->ulConvertionRate = MPC624_SPEED_110_Hz; + rt_printk("110 Hz, "); + break; + case 6: + devpriv->ulConvertionRate = MPC624_SPEED_55_Hz; + rt_printk("55 Hz, "); + break; + case 7: + devpriv->ulConvertionRate = MPC624_SPEED_27_5_Hz; + rt_printk("27.5 Hz, "); + break; + case 8: + devpriv->ulConvertionRate = MPC624_SPEED_13_75_Hz; + rt_printk("13.75 Hz, "); + break; + case 9: + devpriv->ulConvertionRate = MPC624_SPEED_6_875_Hz; + rt_printk("6.875 Hz, "); + break; + default: + rt_printk + ("illegal convertion rate setting! Valid numbers are 0..9. Using 9 => 6.875 Hz, "); + devpriv->ulConvertionRate = MPC624_SPEED_3_52_kHz; + } + + // Subdevices structures + if (alloc_subdevices(dev, 1) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF; + s->n_chan = 8; + switch (it->options[1]) { + default: + s->maxdata = 0x3FFFFFFF; + rt_printk("30 bit, "); + } + + switch (it->options[1]) { + case 0: + s->range_table = &range_mpc624_bipolar1; + rt_printk("1.01V]: "); + break; + default: + s->range_table = &range_mpc624_bipolar10; + rt_printk("10.1V]: "); + } + s->len_chanlist = 1; + s->insn_read = mpc624_ai_rinsn; + + rt_printk("attached\n"); + + return 1; +} + +static int mpc624_detach(struct comedi_device * dev) +{ + rt_printk("comedi%d: mpc624: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, MPC624_SIZE); + + return 0; +} + +// Timeout 200ms +#define TIMEOUT 200 + +static int mpc624_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, i; + unsigned long int data_in, data_out; + unsigned char ucPort; + + // WARNING: We always write 0 to GNSWA bit, so the channel range is +-/10.1Vdc + outb(insn->chanspec, dev->iobase + MPC624_GNMUXCH); +// rt_printk("Channel %d: \n", insn->chanspec); + if (!insn->n) { + rt_printk("MPC624: Warning, no data to aquire\n"); + return 0; + } + + for (n = 0; n < insn->n; n++) { + // Trigger the convertion + outb(MPC624_ADSCK, dev->iobase + MPC624_ADC); + comedi_udelay(1); + outb(MPC624_ADCS | MPC624_ADSCK, dev->iobase + MPC624_ADC); + comedi_udelay(1); + outb(0, dev->iobase + MPC624_ADC); + comedi_udelay(1); + + // Wait for the convertion to end + for (i = 0; i < TIMEOUT; i++) { + ucPort = inb(dev->iobase + MPC624_ADC); + if (ucPort & MPC624_ADBUSY) + comedi_udelay(1000); + else + break; + } + if (i == TIMEOUT) { + rt_printk("MPC624: timeout (%dms)\n", TIMEOUT); + data[n] = 0; + return -ETIMEDOUT; + } + // Start reading data + data_in = 0; + data_out = devpriv->ulConvertionRate; + comedi_udelay(1); + for (i = 0; i < 32; i++) { + // Set the clock low + outb(0, dev->iobase + MPC624_ADC); + comedi_udelay(1); + + if (data_out & (1 << 31)) // the next bit is a 1 + { + // Set the ADSDI line (send to MPC624) + outb(MPC624_ADSDI, dev->iobase + MPC624_ADC); + comedi_udelay(1); + // Set the clock high + outb(MPC624_ADSCK | MPC624_ADSDI, + dev->iobase + MPC624_ADC); + } else // the next bit is a 0 + { + // Set the ADSDI line (send to MPC624) + outb(0, dev->iobase + MPC624_ADC); + comedi_udelay(1); + // Set the clock high + outb(MPC624_ADSCK, dev->iobase + MPC624_ADC); + } + // Read ADSDO on high clock (receive from MPC624) + comedi_udelay(1); + data_in <<= 1; + data_in |= + (inb(dev->iobase + + MPC624_ADC) & MPC624_ADSDO) >> 4; + comedi_udelay(1); + + data_out <<= 1; + } + + // Received 32-bit long value consist of: + // 31: EOC (End Of Transmission) bit - should be 0 + // 30: DMY (Dummy) bit - should be 0 + // 29: SIG (Sign) bit - 1 if the voltage is positive, 0 if negative + // 28: MSB (Most Significant Bit) - the first bit of convertion result + // .... + // 05: LSB (Least Significant Bit) - the last bit of convertion result + // 04: sub-LSB - sub-LSBs are basically noise, but when + // 03: sub-LSB averaged properly, they can increase convertion + // 02: sub-LSB precision up to 29 bits; they can be discarded + // 01: sub-LSB without loss of resolution. + // 00: sub-LSB + + if (data_in & MPC624_EOC_BIT) + rt_printk("MPC624: EOC bit is set (data_in=%lu)!", + data_in); + if (data_in & MPC624_DMY_BIT) + rt_printk("MPC624: DMY bit is set (data_in=%lu)!", + data_in); + if (data_in & MPC624_SGN_BIT) // check the sign bit + { // The voltage is positive + data_in &= 0x3FFFFFFF; // EOC and DMY should be 0, but we will mask them out just to be sure + data[n] = data_in; // comedi operates on unsigned numbers, so we don't clear the SGN bit + // SGN bit is still set! It's correct, since we're converting to unsigned. + } else { // The voltage is negative + // data_in contains a number in 30-bit two's complement code and we must deal with it + data_in |= MPC624_SGN_BIT; + data_in = ~data_in; + data_in += 1; + data_in &= ~(MPC624_EOC_BIT | MPC624_DMY_BIT); + // clear EOC and DMY bits + data_in = 0x20000000 - data_in; + data[n] = data_in; + } + } + + // Return the number of samples read/written + return n; +} + +COMEDI_INITCLEANUP(driver_mpc624); diff --git a/drivers/staging/comedi/drivers/mpc8260cpm.c b/drivers/staging/comedi/drivers/mpc8260cpm.c new file mode 100644 index 000000000000..bac0a7bb9cbd --- /dev/null +++ b/drivers/staging/comedi/drivers/mpc8260cpm.c @@ -0,0 +1,169 @@ +/* + comedi/drivers/mpc8260.c + driver for digital I/O pins on the MPC 8260 CPM module + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000,2001 David A. Schleef + + 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: mpc8260cpm +Description: MPC8260 CPM module generic digital I/O lines +Devices: [Motorola] MPC8260 CPM (mpc8260cpm) +Author: ds +Status: experimental +Updated: Sat, 16 Mar 2002 17:34:48 -0800 + +This driver is specific to the Motorola MPC8260 processor, allowing +you to access the processor's generic digital I/O lines. + +It is apparently missing some code. +*/ + +#include "../comedidev.h" + +extern unsigned long mpc8260_dio_reserved[4]; + +struct mpc8260cpm_private { + + int data; + +}; + +#define devpriv ((struct mpc8260cpm_private *)dev->private) + +static int mpc8260cpm_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int mpc8260cpm_detach(struct comedi_device * dev); +static struct comedi_driver driver_mpc8260cpm = { + driver_name:"mpc8260cpm", + module:THIS_MODULE, + attach:mpc8260cpm_attach, + detach:mpc8260cpm_detach, +}; + +COMEDI_INITCLEANUP(driver_mpc8260cpm); + +static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int mpc8260cpm_dio_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int mpc8260cpm_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int i; + + printk("comedi%d: mpc8260cpm: ", dev->minor); + + dev->board_ptr = mpc8260cpm_boards + dev->board; + + dev->board_name = thisboard->name; + + if (alloc_private(dev, sizeof(struct mpc8260cpm_private)) < 0) + return -ENOMEM; + + if (alloc_subdevices(dev, 4) < 0) + return -ENOMEM; + + for (i = 0; i < 4; i++) { + s = dev->subdevices + i; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 32; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_config = mpc8260cpm_dio_config; + s->insn_bits = mpc8260cpm_dio_bits; + } + + return 1; +} + +static int mpc8260cpm_detach(struct comedi_device * dev) +{ + printk("comedi%d: mpc8260cpm: remove\n", dev->minor); + + return 0; +} + +static unsigned long *cpm_pdat(int port) +{ + switch (port) { + case 0: + return &io->iop_pdata; + case 1: + return &io->iop_pdatb; + case 2: + return &io->iop_pdatc; + case 3: + return &io->iop_pdatd; + } +} + +static int mpc8260cpm_dio_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + unsigned int d; + unsigned int mask; + int port; + + port = (int)s->private; + mask = 1 << CR_CHAN(insn->chanspec); + if (mask & cpm_reserved_bits[port]) { + return -EINVAL; + } + + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= mask; + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~mask; + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + } + + switch (port) { + case 0: + return &io->iop_pdira; + case 1: + return &io->iop_pdirb; + case 2: + return &io->iop_pdirc; + case 3: + return &io->iop_pdird; + } + + return 1; +} + +static int mpc8260cpm_dio_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int port; + unsigned long *p; + + p = cpm_pdat((int)s->private); + + return 2; +} diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c new file mode 100644 index 000000000000..9e47574171de --- /dev/null +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -0,0 +1,333 @@ +/* + comedi/drivers/multiq3.c + Hardware driver for Quanser Consulting MultiQ-3 board + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999 Anders Blomdell + + 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: multiq3 +Description: Quanser Consulting MultiQ-3 +Author: Anders Blomdell +Status: works +Devices: [Quanser Consulting] MultiQ-3 (multiq3) + +*/ + +#include "../comedidev.h" + +#include + +#define MULTIQ3_SIZE 16 + +/* + * MULTIQ-3 port offsets + */ +#define MULTIQ3_DIGIN_PORT 0 +#define MULTIQ3_DIGOUT_PORT 0 +#define MULTIQ3_DAC_DATA 2 +#define MULTIQ3_AD_DATA 4 +#define MULTIQ3_AD_CS 4 +#define MULTIQ3_STATUS 6 +#define MULTIQ3_CONTROL 6 +#define MULTIQ3_CLK_DATA 8 +#define MULTIQ3_ENC_DATA 12 +#define MULTIQ3_ENC_CONTROL 14 + +/* + * flags for CONTROL register + */ +#define MULTIQ3_AD_MUX_EN 0x0040 +#define MULTIQ3_AD_AUTOZ 0x0080 +#define MULTIQ3_AD_AUTOCAL 0x0100 +#define MULTIQ3_AD_SH 0x0200 +#define MULTIQ3_AD_CLOCK_4M 0x0400 +#define MULTIQ3_DA_LOAD 0x1800 + +#define MULTIQ3_CONTROL_MUST 0x0600 + +/* + * flags for STATUS register + */ +#define MULTIQ3_STATUS_EOC 0x008 +#define MULTIQ3_STATUS_EOC_I 0x010 + +/* + * flags for encoder control + */ +#define MULTIQ3_CLOCK_DATA 0x00 +#define MULTIQ3_CLOCK_SETUP 0x18 +#define MULTIQ3_INPUT_SETUP 0x41 +#define MULTIQ3_QUAD_X4 0x38 +#define MULTIQ3_BP_RESET 0x01 +#define MULTIQ3_CNTR_RESET 0x02 +#define MULTIQ3_TRSFRPR_CTR 0x08 +#define MULTIQ3_TRSFRCNTR_OL 0x10 +#define MULTIQ3_EFLAG_RESET 0x06 + +#define MULTIQ3_TIMEOUT 30 + +static int multiq3_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int multiq3_detach(struct comedi_device * dev); +static struct comedi_driver driver_multiq3 = { + driver_name:"multiq3", + module:THIS_MODULE, + attach:multiq3_attach, + detach:multiq3_detach, +}; + +COMEDI_INITCLEANUP(driver_multiq3); + +struct multiq3_private { + unsigned int ao_readback[2]; +}; +#define devpriv ((struct multiq3_private *)dev->private) + +static int multiq3_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, n; + int chan; + unsigned int hi, lo; + + chan = CR_CHAN(insn->chanspec); + outw(MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3), + dev->iobase + MULTIQ3_CONTROL); + + for (i = 0; i < MULTIQ3_TIMEOUT; i++) { + if (inw(dev->iobase + MULTIQ3_STATUS) & MULTIQ3_STATUS_EOC) + break; + } + if (i == MULTIQ3_TIMEOUT) + return -ETIMEDOUT; + + for (n = 0; n < insn->n; n++) { + outw(0, dev->iobase + MULTIQ3_AD_CS); + for (i = 0; i < MULTIQ3_TIMEOUT; i++) { + if (inw(dev->iobase + + MULTIQ3_STATUS) & MULTIQ3_STATUS_EOC_I) + break; + } + if (i == MULTIQ3_TIMEOUT) + return -ETIMEDOUT; + + hi = inb(dev->iobase + MULTIQ3_AD_CS); + lo = inb(dev->iobase + MULTIQ3_AD_CS); + data[n] = (((hi << 8) | lo) + 0x1000) & 0x1fff; + } + + return n; +} + +static int multiq3_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +static int multiq3_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + outw(MULTIQ3_CONTROL_MUST | MULTIQ3_DA_LOAD | chan, + dev->iobase + MULTIQ3_CONTROL); + outw(data[i], dev->iobase + MULTIQ3_DAC_DATA); + outw(MULTIQ3_CONTROL_MUST, dev->iobase + MULTIQ3_CONTROL); + + devpriv->ao_readback[chan] = data[i]; + } + + return i; +} + +static int multiq3_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + data[1] = inw(dev->iobase + MULTIQ3_DIGIN_PORT); + + return 2; +} + +static int multiq3_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + outw(s->state, dev->iobase + MULTIQ3_DIGOUT_PORT); + + data[1] = s->state; + + return 2; +} + +static int multiq3_encoder_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan = CR_CHAN(insn->chanspec); + int control = MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3); + + for (n = 0; n < insn->n; n++) { + int value; + outw(control, dev->iobase + MULTIQ3_CONTROL); + outb(MULTIQ3_BP_RESET, dev->iobase + MULTIQ3_ENC_CONTROL); + outb(MULTIQ3_TRSFRCNTR_OL, dev->iobase + MULTIQ3_ENC_CONTROL); + value = inb(dev->iobase + MULTIQ3_ENC_DATA); + value |= (inb(dev->iobase + MULTIQ3_ENC_DATA) << 8); + value |= (inb(dev->iobase + MULTIQ3_ENC_DATA) << 16); + data[n] = (value + 0x800000) & 0xffffff; + } + + return n; +} + +static void encoder_reset(struct comedi_device * dev) +{ + int chan; + for (chan = 0; chan < dev->subdevices[4].n_chan; chan++) { + int control = + MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3); + outw(control, dev->iobase + MULTIQ3_CONTROL); + outb(MULTIQ3_EFLAG_RESET, dev->iobase + MULTIQ3_ENC_CONTROL); + outb(MULTIQ3_BP_RESET, dev->iobase + MULTIQ3_ENC_CONTROL); + outb(MULTIQ3_CLOCK_DATA, dev->iobase + MULTIQ3_ENC_DATA); + outb(MULTIQ3_CLOCK_SETUP, dev->iobase + MULTIQ3_ENC_CONTROL); + outb(MULTIQ3_INPUT_SETUP, dev->iobase + MULTIQ3_ENC_CONTROL); + outb(MULTIQ3_QUAD_X4, dev->iobase + MULTIQ3_ENC_CONTROL); + outb(MULTIQ3_CNTR_RESET, dev->iobase + MULTIQ3_ENC_CONTROL); + } +} + +/* + options[0] - I/O port + options[1] - irq + options[2] - number of encoder chips installed + */ + +static int multiq3_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int result = 0; + unsigned long iobase; + unsigned int irq; + struct comedi_subdevice *s; + + iobase = it->options[0]; + printk("comedi%d: multiq3: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, MULTIQ3_SIZE, "multiq3")) { + printk("comedi%d: I/O port conflict\n", dev->minor); + return -EIO; + } + + dev->iobase = iobase; + + irq = it->options[1]; + if (irq) { + printk("comedi%d: irq = %u ignored\n", dev->minor, irq); + } else { + printk("comedi%d: no irq\n", dev->minor); + } + dev->board_name = "multiq3"; + result = alloc_subdevices(dev, 5); + if (result < 0) + return result; + + result = alloc_private(dev, sizeof(struct multiq3_private)); + if (result < 0) + return result; + + s = dev->subdevices + 0; + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 8; + s->insn_read = multiq3_ai_insn_read; + s->maxdata = 0x1fff; + s->range_table = &range_bipolar5; + + s = dev->subdevices + 1; + /* ao subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 8; + s->insn_read = multiq3_ao_insn_read; + s->insn_write = multiq3_ao_insn_write; + s->maxdata = 0xfff; + s->range_table = &range_bipolar5; + + s = dev->subdevices + 2; + /* di subdevice */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->insn_bits = multiq3_di_insn_bits; + s->maxdata = 1; + s->range_table = &range_digital; + + s = dev->subdevices + 3; + /* do subdevice */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->insn_bits = multiq3_do_insn_bits; + s->maxdata = 1; + s->range_table = &range_digital; + s->state = 0; + + s = dev->subdevices + 4; + /* encoder (counter) subdevice */ + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_LSAMPL; + s->n_chan = it->options[2] * 2; + s->insn_read = multiq3_encoder_insn_read; + s->maxdata = 0xffffff; + s->range_table = &range_unknown; + + encoder_reset(dev); + + return 0; +} + +static int multiq3_detach(struct comedi_device * dev) +{ + printk("comedi%d: multiq3: remove\n", dev->minor); + + if (dev->iobase) { + release_region(dev->iobase, MULTIQ3_SIZE); + } + if (dev->irq) { + free_irq(dev->irq, dev); + } + + return 0; +} diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c new file mode 100644 index 000000000000..e01ecb6760f9 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -0,0 +1,489 @@ +/* + comedi/drivers/ni_6527.c + driver for National Instruments PCI-6527 + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999,2002,2003 David A. Schleef + + 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: ni_6527 +Description: National Instruments 6527 +Author: ds +Status: works +Devices: [National Instruments] PCI-6527 (ni6527), PXI-6527 +Updated: Sat, 25 Jan 2003 13:24:40 -0800 + + +*/ + +/* + Manuals (available from ftp://ftp.natinst.com/support/manuals) + + 370106b.pdf 6527 Register Level Programmer Manual + + */ + +#define DEBUG 1 +#define DEBUG_FLAGS + +#include "../comedidev.h" + +#include "mite.h" + +#define NI6527_DIO_SIZE 4096 +#define NI6527_MITE_SIZE 4096 + +#define Port_Register(x) (0x00+(x)) +#define ID_Register 0x06 + +#define Clear_Register 0x07 +#define ClrEdge 0x08 +#define ClrOverflow 0x04 +#define ClrFilter 0x02 +#define ClrInterval 0x01 + +#define Filter_Interval(x) (0x08+(x)) +#define Filter_Enable(x) (0x0c+(x)) + +#define Change_Status 0x14 +#define MasterInterruptStatus 0x04 +#define Overflow 0x02 +#define EdgeStatus 0x01 + +#define Master_Interrupt_Control 0x15 +#define FallingEdgeIntEnable 0x10 +#define RisingEdgeIntEnable 0x08 +#define MasterInterruptEnable 0x04 +#define OverflowIntEnable 0x02 +#define EdgeIntEnable 0x01 + +#define Rising_Edge_Detection_Enable(x) (0x018+(x)) +#define Falling_Edge_Detection_Enable(x) (0x020+(x)) + +static int ni6527_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int ni6527_detach(struct comedi_device * dev); +static struct comedi_driver driver_ni6527 = { + driver_name:"ni6527", + module:THIS_MODULE, + attach:ni6527_attach, + detach:ni6527_detach, +}; + +struct ni6527_board { + + int dev_id; + const char *name; +}; + +static const struct ni6527_board ni6527_boards[] = { + { + dev_id: 0x2b20, + name: "pci-6527", + }, + { + dev_id: 0x2b10, + name: "pxi-6527", + }, +}; + +#define n_ni6527_boards (sizeof(ni6527_boards)/sizeof(ni6527_boards[0])) +#define this_board ((const struct ni6527_board *)dev->board_ptr) + +static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = { + {PCI_VENDOR_ID_NATINST, 0x2b10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, ni6527_pci_table); + +struct ni6527_private { + struct mite_struct *mite; + unsigned int filter_interval; + unsigned int filter_enable; +}; + +#define devpriv ((struct ni6527_private *)dev->private) + +static int ni6527_find_device(struct comedi_device * dev, int bus, int slot); + +static int ni6527_di_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + unsigned int interval; + + if (insn->n != 2) + return -EINVAL; + + if (data[0] != INSN_CONFIG_FILTER) + return -EINVAL; + + if (data[1]) { + interval = (data[1] + 100) / 200; + data[1] = interval * 200; + + if (interval != devpriv->filter_interval) { + writeb(interval & 0xff, + devpriv->mite->daq_io_addr + + Filter_Interval(0)); + writeb((interval >> 8) & 0xff, + devpriv->mite->daq_io_addr + + Filter_Interval(1)); + writeb((interval >> 16) & 0x0f, + devpriv->mite->daq_io_addr + + Filter_Interval(2)); + + writeb(ClrInterval, + devpriv->mite->daq_io_addr + Clear_Register); + + devpriv->filter_interval = interval; + } + + devpriv->filter_enable |= 1 << chan; + } else { + devpriv->filter_enable &= ~(1 << chan); + } + + writeb(devpriv->filter_enable, + devpriv->mite->daq_io_addr + Filter_Enable(0)); + writeb(devpriv->filter_enable >> 8, + devpriv->mite->daq_io_addr + Filter_Enable(1)); + writeb(devpriv->filter_enable >> 16, + devpriv->mite->daq_io_addr + Filter_Enable(2)); + + return 2; +} + +static int ni6527_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + data[1] = readb(devpriv->mite->daq_io_addr + Port_Register(0)); + data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(1)) << 8; + data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(2)) << 16; + + return 2; +} + +static int ni6527_do_insn_bits(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]); + + /* The open relay state on the board cooresponds to 1, + * but in Comedi, it is represented by 0. */ + if (data[0] & 0x0000ff) { + writeb((s->state ^ 0xff), + devpriv->mite->daq_io_addr + Port_Register(3)); + } + if (data[0] & 0x00ff00) { + writeb((s->state >> 8) ^ 0xff, + devpriv->mite->daq_io_addr + Port_Register(4)); + } + if (data[0] & 0xff0000) { + writeb((s->state >> 16) ^ 0xff, + devpriv->mite->daq_io_addr + Port_Register(5)); + } + } + data[1] = s->state; + + return 2; +} + +static irqreturn_t ni6527_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 2; + unsigned int status; + + status = readb(devpriv->mite->daq_io_addr + Change_Status); + if ((status & MasterInterruptStatus) == 0) + return IRQ_NONE; + if ((status & EdgeStatus) == 0) + return IRQ_NONE; + + writeb(ClrEdge | ClrOverflow, + devpriv->mite->daq_io_addr + Clear_Register); + + comedi_buf_put(s->async, 0); + s->async->events |= COMEDI_CB_EOS; + comedi_event(dev, s); + return IRQ_HANDLED; +} + +static int ni6527_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + 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_OTHER; + 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_COUNT; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + 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: fix up any arguments */ + + if (err) + return 4; + + return 0; +} + +static int ni6527_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + //struct comedi_cmd *cmd = &s->async->cmd; + + writeb(ClrEdge | ClrOverflow, + devpriv->mite->daq_io_addr + Clear_Register); + writeb(FallingEdgeIntEnable | RisingEdgeIntEnable | + MasterInterruptEnable | EdgeIntEnable, + devpriv->mite->daq_io_addr + Master_Interrupt_Control); + + return 0; +} + +static int ni6527_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control); + + return 0; +} + +static int ni6527_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n < 1) + return -EINVAL; + + data[1] = 0; + return 2; +} + +static int ni6527_intr_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n < 1) + return -EINVAL; + if (data[0] != INSN_CONFIG_CHANGE_NOTIFY) + return -EINVAL; + + writeb(data[1], + devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(0)); + writeb(data[1] >> 8, + devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(1)); + writeb(data[1] >> 16, + devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(2)); + + writeb(data[2], + devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(0)); + writeb(data[2] >> 8, + devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(1)); + writeb(data[2] >> 16, + devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(2)); + + return 2; +} + +static int ni6527_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret; + + printk("comedi%d: ni6527:", dev->minor); + + if ((ret = alloc_private(dev, sizeof(struct ni6527_private))) < 0) + return ret; + + ret = ni6527_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; + + ret = mite_setup(devpriv->mite); + if (ret < 0) { + printk("error setting up mite\n"); + return ret; + } + + dev->board_name = this_board->name; + printk(" %s", dev->board_name); + + printk(" ID=0x%02x", readb(devpriv->mite->daq_io_addr + ID_Register)); + + if ((ret = alloc_subdevices(dev, 3)) < 0) + return ret; + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 24; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_config = ni6527_di_insn_config; + s->insn_bits = ni6527_di_insn_bits; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 24; + s->range_table = &range_unknown; /* FIXME: actually conductance */ + s->maxdata = 1; + s->insn_bits = ni6527_do_insn_bits; + + s = dev->subdevices + 2; + dev->read_subdev = s; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 1; + s->range_table = &range_unknown; + s->maxdata = 1; + s->do_cmdtest = ni6527_intr_cmdtest; + s->do_cmd = ni6527_intr_cmd; + s->cancel = ni6527_intr_cancel; + s->insn_bits = ni6527_intr_insn_bits; + s->insn_config = ni6527_intr_insn_config; + + writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(0)); + writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(1)); + writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(2)); + + writeb(ClrEdge | ClrOverflow | ClrFilter | ClrInterval, + devpriv->mite->daq_io_addr + Clear_Register); + writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control); + + ret = comedi_request_irq(mite_irq(devpriv->mite), ni6527_interrupt, + IRQF_SHARED, "ni6527", dev); + if (ret < 0) { + printk(" irq not available"); + } else + dev->irq = mite_irq(devpriv->mite); + + printk("\n"); + + return 0; +} + +static int ni6527_detach(struct comedi_device * dev) +{ + if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) { + writeb(0x00, + devpriv->mite->daq_io_addr + Master_Interrupt_Control); + } + + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + + if (devpriv && devpriv->mite) { + mite_unsetup(devpriv->mite); + } + + return 0; +} + +static int ni6527_find_device(struct comedi_device * dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + for (i = 0; i < n_ni6527_boards; i++) { + if (mite_device_id(mite) == ni6527_boards[i].dev_id) { + dev->board_ptr = ni6527_boards + i; + devpriv->mite = mite; + return 0; + } + } + } + printk("no device found\n"); + mite_list_devices(); + return -EIO; +} + +COMEDI_PCI_INITCLEANUP(driver_ni6527, ni6527_pci_table); diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c new file mode 100644 index 000000000000..6e85da16a241 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -0,0 +1,809 @@ +/* + comedi/drivers/ni_6514.c + driver for National Instruments PCI-6514 + + Copyright (C) 2006 Jon Grierson + Copyright (C) 2006 Frank Mori Hess + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999,2002,2003 David A. Schleef + + 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: ni_65xx +Description: National Instruments 65xx static dio boards +Author: Jon Grierson , Frank Mori Hess +Status: testing +Devices: [National Instruments] PCI-6509 (ni_65xx), PXI-6509, PCI-6510, PCI-6511, + PXI-6511, PCI-6512, PXI-6512, PCI-6513, PXI-6513, PCI-6514, PXI-6514, PCI-6515, + PXI-6515, PCI-6516, PCI-6517, PCI-6518, PCI-6519, PCI-6520, PCI-6521, PXI-6521, + PCI-6528, PXI-6528 +Updated: Wed Oct 18 08:59:11 EDT 2006 + +Based on the PCI-6527 driver by ds. +The interrupt subdevice (subdevice 3) is probably broken for all boards +except maybe the 6514. + +*/ + +/* + Manuals (available from ftp://ftp.natinst.com/support/manuals) + + 370106b.pdf 6514 Register Level Programmer Manual + + */ + +#define _GNU_SOURCE +#define DEBUG 1 +#define DEBUG_FLAGS +#include "../comedidev.h" + +#include "mite.h" + +#define NI6514_DIO_SIZE 4096 +#define NI6514_MITE_SIZE 4096 + +#define NI_65XX_MAX_NUM_PORTS 12 +static const unsigned ni_65xx_channels_per_port = 8; +static const unsigned ni_65xx_port_offset = 0x10; + +static inline unsigned Port_Data(unsigned port) +{ + return 0x40 + port * ni_65xx_port_offset; +} +static inline unsigned Port_Select(unsigned port) +{ + return 0x41 + port * ni_65xx_port_offset; +} +static inline unsigned Rising_Edge_Detection_Enable(unsigned port) +{ + return 0x42 + port * ni_65xx_port_offset; +} +static inline unsigned Falling_Edge_Detection_Enable(unsigned port) +{ + return 0x43 + port * ni_65xx_port_offset; +} +static inline unsigned Filter_Enable(unsigned port) +{ + return 0x44 + port * ni_65xx_port_offset; +} + +#define ID_Register 0x00 + +#define Clear_Register 0x01 +#define ClrEdge 0x08 +#define ClrOverflow 0x04 + +#define Filter_Interval 0x08 + +#define Change_Status 0x02 +#define MasterInterruptStatus 0x04 +#define Overflow 0x02 +#define EdgeStatus 0x01 + +#define Master_Interrupt_Control 0x03 +#define FallingEdgeIntEnable 0x10 +#define RisingEdgeIntEnable 0x08 +#define MasterInterruptEnable 0x04 +#define OverflowIntEnable 0x02 +#define EdgeIntEnable 0x01 + +static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int ni_65xx_detach(struct comedi_device * dev); +static struct comedi_driver driver_ni_65xx = { + driver_name:"ni_65xx", + module:THIS_MODULE, + attach:ni_65xx_attach, + detach:ni_65xx_detach, +}; + +struct ni_65xx_board { + + int dev_id; + const char *name; + unsigned num_dio_ports; + unsigned num_di_ports; + unsigned num_do_ports; + unsigned invert_outputs:1; +}; + +static const struct ni_65xx_board ni_65xx_boards[] = { + { + dev_id: 0x7085, + name: "pci-6509", + num_dio_ports:12, + invert_outputs:0}, + { + dev_id: 0x1710, + name: "pxi-6509", + num_dio_ports:12, + invert_outputs:0}, + { + dev_id: 0x7124, + name: "pci-6510", + num_di_ports:4}, + { + dev_id: 0x70c3, + name: "pci-6511", + num_di_ports:8}, + { + dev_id: 0x70d3, + name: "pxi-6511", + num_di_ports:8}, + { + dev_id: 0x70cc, + name: "pci-6512", + num_do_ports:8}, + { + dev_id: 0x70d2, + name: "pxi-6512", + num_do_ports:8}, + { + dev_id: 0x70c8, + name: "pci-6513", + num_do_ports:8, + invert_outputs:1}, + { + dev_id: 0x70d1, + name: "pxi-6513", + num_do_ports:8, + invert_outputs:1}, + { + dev_id: 0x7088, + name: "pci-6514", + num_di_ports:4, + num_do_ports:4, + invert_outputs:1}, + { + dev_id: 0x70CD, + name: "pxi-6514", + num_di_ports:4, + num_do_ports:4, + invert_outputs:1}, + { + dev_id: 0x7087, + name: "pci-6515", + num_di_ports:4, + num_do_ports:4, + invert_outputs:1}, + { + dev_id: 0x70c9, + name: "pxi-6515", + num_di_ports:4, + num_do_ports:4, + invert_outputs:1}, + { + dev_id: 0x7125, + name: "pci-6516", + num_do_ports:4, + invert_outputs:1}, + { + dev_id: 0x7126, + name: "pci-6517", + num_do_ports:4, + invert_outputs:1}, + { + dev_id: 0x7127, + name: "pci-6518", + num_di_ports:2, + num_do_ports:2, + invert_outputs:1}, + { + dev_id: 0x7128, + name: "pci-6519", + num_di_ports:2, + num_do_ports:2, + invert_outputs:1}, + { + dev_id: 0x71c5, + name: "pci-6520", + num_di_ports:1, + num_do_ports:1, + }, + { + dev_id: 0x718b, + name: "pci-6521", + num_di_ports:1, + num_do_ports:1, + }, + { + dev_id: 0x718c, + name: "pxi-6521", + num_di_ports:1, + num_do_ports:1, + }, + { + dev_id: 0x70a9, + name: "pci-6528", + num_di_ports:3, + num_do_ports:3, + }, + { + dev_id: 0x7086, + name: "pxi-6528", + num_di_ports:3, + num_do_ports:3, + }, +}; + +#define n_ni_65xx_boards (sizeof(ni_65xx_boards)/sizeof(ni_65xx_boards[0])) +static inline const struct ni_65xx_board *board(struct comedi_device * dev) +{ + return dev->board_ptr; +} +static inline unsigned ni_65xx_port_by_channel(unsigned channel) +{ + return channel / ni_65xx_channels_per_port; +} +static inline unsigned ni_65xx_total_num_ports(const struct ni_65xx_board * board) +{ + return board->num_dio_ports + board->num_di_ports + board->num_do_ports; +} + +static DEFINE_PCI_DEVICE_TABLE(ni_65xx_pci_table) = { + {PCI_VENDOR_ID_NATINST, 0x1710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x7085, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x7086, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x7087, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x7088, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70a9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70c8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70c9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70d2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70d3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x7124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x7125, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x7126, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x7127, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x7128, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x718b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x718c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x71c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, ni_65xx_pci_table); + +struct ni_65xx_private { + struct mite_struct *mite; + unsigned int filter_interval; + unsigned short filter_enable[NI_65XX_MAX_NUM_PORTS]; + unsigned short output_bits[NI_65XX_MAX_NUM_PORTS]; + unsigned short dio_direction[NI_65XX_MAX_NUM_PORTS]; +}; + +static inline struct ni_65xx_private *private(struct comedi_device * dev) +{ + return dev->private; +} + +struct ni_65xx_subdevice_private { + unsigned base_port; +}; + +static inline struct ni_65xx_subdevice_private *sprivate(struct comedi_subdevice * subdev) +{ + return subdev->private; +} +static struct ni_65xx_subdevice_private *ni_65xx_alloc_subdevice_private(void) +{ + struct ni_65xx_subdevice_private *subdev_private = + kzalloc(sizeof(struct ni_65xx_subdevice_private), GFP_KERNEL); + if (subdev_private == NULL) + return NULL; + return subdev_private; +} + +static int ni_65xx_find_device(struct comedi_device * dev, int bus, int slot); + +static int ni_65xx_config_filter(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + const unsigned chan = CR_CHAN(insn->chanspec); + const unsigned port = + sprivate(s)->base_port + ni_65xx_port_by_channel(chan); + + if (data[0] != INSN_CONFIG_FILTER) + return -EINVAL; + if (data[1]) { + static const unsigned filter_resolution_ns = 200; + static const unsigned max_filter_interval = 0xfffff; + unsigned interval = + (data[1] + + (filter_resolution_ns / 2)) / filter_resolution_ns; + if (interval > max_filter_interval) + interval = max_filter_interval; + data[1] = interval * filter_resolution_ns; + + if (interval != private(dev)->filter_interval) { + writeb(interval, + private(dev)->mite->daq_io_addr + + Filter_Interval); + private(dev)->filter_interval = interval; + } + + private(dev)->filter_enable[port] |= + 1 << (chan % ni_65xx_channels_per_port); + } else { + private(dev)->filter_enable[port] &= + ~(1 << (chan % ni_65xx_channels_per_port)); + } + + writeb(private(dev)->filter_enable[port], + private(dev)->mite->daq_io_addr + Filter_Enable(port)); + + return 2; +} + +static int ni_65xx_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned port; + + if (insn->n < 1) + return -EINVAL; + port = sprivate(s)->base_port + + ni_65xx_port_by_channel(CR_CHAN(insn->chanspec)); + switch (data[0]) { + case INSN_CONFIG_FILTER: + return ni_65xx_config_filter(dev, s, insn, data); + break; + case INSN_CONFIG_DIO_OUTPUT: + if (s->type != COMEDI_SUBD_DIO) + return -EINVAL; + private(dev)->dio_direction[port] = COMEDI_OUTPUT; + writeb(0, private(dev)->mite->daq_io_addr + Port_Select(port)); + return 1; + break; + case INSN_CONFIG_DIO_INPUT: + if (s->type != COMEDI_SUBD_DIO) + return -EINVAL; + private(dev)->dio_direction[port] = COMEDI_INPUT; + writeb(1, private(dev)->mite->daq_io_addr + Port_Select(port)); + return 1; + break; + case INSN_CONFIG_DIO_QUERY: + if (s->type != COMEDI_SUBD_DIO) + return -EINVAL; + data[1] = private(dev)->dio_direction[port]; + return insn->n; + break; + default: + break; + } + return -EINVAL; +} + +static int ni_65xx_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned base_bitfield_channel; + const unsigned max_ports_per_bitfield = 5; + unsigned read_bits = 0; + unsigned j; + if (insn->n != 2) + return -EINVAL; + base_bitfield_channel = CR_CHAN(insn->chanspec); + for (j = 0; j < max_ports_per_bitfield; ++j) { + const unsigned port = + sprivate(s)->base_port + + ni_65xx_port_by_channel(base_bitfield_channel) + j; + unsigned base_port_channel; + unsigned port_mask, port_data, port_read_bits; + int bitshift; + if (port >= ni_65xx_total_num_ports(board(dev))) + break; + base_port_channel = port * ni_65xx_channels_per_port; + port_mask = data[0]; + port_data = data[1]; + bitshift = base_port_channel - base_bitfield_channel; + if (bitshift >= 32 || bitshift <= -32) + break; + if (bitshift > 0) { + port_mask >>= bitshift; + port_data >>= bitshift; + } else { + port_mask <<= -bitshift; + port_data <<= -bitshift; + } + port_mask &= 0xff; + port_data &= 0xff; + if (port_mask) { + unsigned bits; + private(dev)->output_bits[port] &= ~port_mask; + private(dev)->output_bits[port] |= + port_data & port_mask; + bits = private(dev)->output_bits[port]; + if (board(dev)->invert_outputs) + bits = ~bits; + writeb(bits, + private(dev)->mite->daq_io_addr + + Port_Data(port)); +// rt_printk("wrote 0x%x to port %i\n", bits, port); + } + port_read_bits = + readb(private(dev)->mite->daq_io_addr + + Port_Data(port)); +// rt_printk("read 0x%x from port %i\n", port_read_bits, port); + if (bitshift > 0) { + port_read_bits <<= bitshift; + } else { + port_read_bits >>= -bitshift; + } + read_bits |= port_read_bits; + } + data[1] = read_bits; + return insn->n; +} + +static irqreturn_t ni_65xx_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 2; + unsigned int status; + + status = readb(private(dev)->mite->daq_io_addr + Change_Status); + if ((status & MasterInterruptStatus) == 0) + return IRQ_NONE; + if ((status & EdgeStatus) == 0) + return IRQ_NONE; + + writeb(ClrEdge | ClrOverflow, + private(dev)->mite->daq_io_addr + Clear_Register); + + comedi_buf_put(s->async, 0); + s->async->events |= COMEDI_CB_EOS; + comedi_event(dev, s); + return IRQ_HANDLED; +} + +static int ni_65xx_intr_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + 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_OTHER; + 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_COUNT; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + 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: fix up any arguments */ + + if (err) + return 4; + + return 0; +} + +static int ni_65xx_intr_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + //struct comedi_cmd *cmd = &s->async->cmd; + + writeb(ClrEdge | ClrOverflow, + private(dev)->mite->daq_io_addr + Clear_Register); + writeb(FallingEdgeIntEnable | RisingEdgeIntEnable | + MasterInterruptEnable | EdgeIntEnable, + private(dev)->mite->daq_io_addr + Master_Interrupt_Control); + + return 0; +} + +static int ni_65xx_intr_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + writeb(0x00, + private(dev)->mite->daq_io_addr + Master_Interrupt_Control); + + return 0; +} + +static int ni_65xx_intr_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n < 1) + return -EINVAL; + + data[1] = 0; + return 2; +} + +static int ni_65xx_intr_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n < 1) + return -EINVAL; + if (data[0] != INSN_CONFIG_CHANGE_NOTIFY) + return -EINVAL; + + writeb(data[1], + private(dev)->mite->daq_io_addr + + Rising_Edge_Detection_Enable(0)); + writeb(data[1] >> 8, + private(dev)->mite->daq_io_addr + + Rising_Edge_Detection_Enable(0x10)); + writeb(data[1] >> 16, + private(dev)->mite->daq_io_addr + + Rising_Edge_Detection_Enable(0x20)); + writeb(data[1] >> 24, + private(dev)->mite->daq_io_addr + + Rising_Edge_Detection_Enable(0x30)); + + writeb(data[2], + private(dev)->mite->daq_io_addr + + Falling_Edge_Detection_Enable(0)); + writeb(data[2] >> 8, + private(dev)->mite->daq_io_addr + + Falling_Edge_Detection_Enable(0x10)); + writeb(data[2] >> 16, + private(dev)->mite->daq_io_addr + + Falling_Edge_Detection_Enable(0x20)); + writeb(data[2] >> 24, + private(dev)->mite->daq_io_addr + + Falling_Edge_Detection_Enable(0x30)); + + return 2; +} + +static int ni_65xx_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned i; + int ret; + + printk("comedi%d: ni_65xx:", dev->minor); + + if ((ret = alloc_private(dev, sizeof(struct ni_65xx_private))) < 0) + return ret; + + ret = ni_65xx_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; + + ret = mite_setup(private(dev)->mite); + if (ret < 0) { + printk("error setting up mite\n"); + return ret; + } + + dev->board_name = board(dev)->name; + dev->irq = mite_irq(private(dev)->mite); + printk(" %s", dev->board_name); + + printk(" ID=0x%02x", + readb(private(dev)->mite->daq_io_addr + ID_Register)); + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + + s = dev->subdevices + 0; + if (board(dev)->num_di_ports) { + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = + board(dev)->num_di_ports * ni_65xx_channels_per_port; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_config = ni_65xx_dio_insn_config; + s->insn_bits = ni_65xx_dio_insn_bits; + s->private = ni_65xx_alloc_subdevice_private(); + if (s->private == NULL) + return -ENOMEM; + sprivate(s)->base_port = 0; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 1; + if (board(dev)->num_do_ports) { + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = + board(dev)->num_do_ports * ni_65xx_channels_per_port; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_bits = ni_65xx_dio_insn_bits; + s->private = ni_65xx_alloc_subdevice_private(); + if (s->private == NULL) + return -ENOMEM; + sprivate(s)->base_port = board(dev)->num_di_ports; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 2; + if (board(dev)->num_dio_ports) { + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = + board(dev)->num_dio_ports * ni_65xx_channels_per_port; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_config = ni_65xx_dio_insn_config; + s->insn_bits = ni_65xx_dio_insn_bits; + s->private = ni_65xx_alloc_subdevice_private(); + if (s->private == NULL) + return -ENOMEM; + sprivate(s)->base_port = 0; + for (i = 0; i < board(dev)->num_dio_ports; ++i) { + // configure all ports for input + writeb(0x1, + private(dev)->mite->daq_io_addr + + Port_Select(i)); + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s = dev->subdevices + 3; + dev->read_subdev = s; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 1; + s->range_table = &range_unknown; + s->maxdata = 1; + s->do_cmdtest = ni_65xx_intr_cmdtest; + s->do_cmd = ni_65xx_intr_cmd; + s->cancel = ni_65xx_intr_cancel; + s->insn_bits = ni_65xx_intr_insn_bits; + s->insn_config = ni_65xx_intr_insn_config; + + for (i = 0; i < ni_65xx_total_num_ports(board(dev)); ++i) { + writeb(0x00, + private(dev)->mite->daq_io_addr + Filter_Enable(i)); + if (board(dev)->invert_outputs) + writeb(0x01, + private(dev)->mite->daq_io_addr + Port_Data(i)); + else + writeb(0x00, + private(dev)->mite->daq_io_addr + Port_Data(i)); + } + writeb(ClrEdge | ClrOverflow, + private(dev)->mite->daq_io_addr + Clear_Register); + writeb(0x00, + private(dev)->mite->daq_io_addr + Master_Interrupt_Control); + + /* Set filter interval to 0 (32bit reg) */ + writeb(0x00000000, private(dev)->mite->daq_io_addr + Filter_Interval); + + ret = comedi_request_irq(dev->irq, ni_65xx_interrupt, IRQF_SHARED, + "ni_65xx", dev); + if (ret < 0) { + dev->irq = 0; + printk(" irq not available"); + } + + printk("\n"); + + return 0; +} + +static int ni_65xx_detach(struct comedi_device * dev) +{ + if (private(dev) && private(dev)->mite + && private(dev)->mite->daq_io_addr) { + writeb(0x00, + private(dev)->mite->daq_io_addr + + Master_Interrupt_Control); + } + + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + + if (private(dev)) { + unsigned i; + for (i = 0; i < dev->n_subdevices; ++i) { + if (dev->subdevices[i].private) { + kfree(dev->subdevices[i].private); + dev->subdevices[i].private = NULL; + } + } + if (private(dev)->mite) { + mite_unsetup(private(dev)->mite); + } + } + return 0; +} + +static int ni_65xx_find_device(struct comedi_device * dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + for (i = 0; i < n_ni_65xx_boards; i++) { + if (mite_device_id(mite) == ni_65xx_boards[i].dev_id) { + dev->board_ptr = ni_65xx_boards + i; + private(dev)->mite = mite; + return 0; + } + } + } + printk("no device found\n"); + mite_list_devices(); + return -EIO; +} + +COMEDI_PCI_INITCLEANUP(driver_ni_65xx, ni_65xx_pci_table); diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c new file mode 100644 index 000000000000..14e35ba721e9 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -0,0 +1,1324 @@ +/* + comedi/drivers/ni_660x.c + Hardware driver for NI 660x devices + + 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: ni_660x +Description: National Instruments 660x counter/timer boards +Devices: +[National Instruments] PCI-6601 (ni_660x), PCI-6602, PXI-6602, + PXI-6608 +Author: J.P. Mellor , + Herman.Bruyninckx@mech.kuleuven.ac.be, + Wim.Meeussen@mech.kuleuven.ac.be, + Klaas.Gadeyne@mech.kuleuven.ac.be, + Frank Mori Hess +Updated: Thu Oct 18 12:56:06 EDT 2007 +Status: experimental + +Encoders work. PulseGeneration (both single pulse and pulse train) +works. Buffered commands work for input but not output. + +References: +DAQ 660x Register-Level Programmer Manual (NI 370505A-01) +DAQ 6601/6602 User Manual (NI 322137B-01) + +*/ + +#include "../comedidev.h" +#include "mite.h" +#include "ni_tio.h" + +enum ni_660x_constants { + min_counter_pfi_chan = 8, + max_dio_pfi_chan = 31, + counters_per_chip = 4 +}; + +#define NUM_PFI_CHANNELS 40 +// really there are only up to 3 dma channels, but the register layout allows for 4 +#define MAX_DMA_CHANNEL 4 + +/* See Register-Level Programmer Manual page 3.1 */ +enum NI_660x_Register { + G0InterruptAcknowledge, + G0StatusRegister, + G1InterruptAcknowledge, + G1StatusRegister, + G01StatusRegister, + G0CommandRegister, + STCDIOParallelInput, + G1CommandRegister, + G0HWSaveRegister, + G1HWSaveRegister, + STCDIOOutput, + STCDIOControl, + G0SWSaveRegister, + G1SWSaveRegister, + G0ModeRegister, + G01JointStatus1Register, + G1ModeRegister, + STCDIOSerialInput, + G0LoadARegister, + G01JointStatus2Register, + G0LoadBRegister, + G1LoadARegister, + G1LoadBRegister, + G0InputSelectRegister, + G1InputSelectRegister, + G0AutoincrementRegister, + G1AutoincrementRegister, + G01JointResetRegister, + G0InterruptEnable, + G1InterruptEnable, + G0CountingModeRegister, + G1CountingModeRegister, + G0SecondGateRegister, + G1SecondGateRegister, + G0DMAConfigRegister, + G0DMAStatusRegister, + G1DMAConfigRegister, + G1DMAStatusRegister, + G2InterruptAcknowledge, + G2StatusRegister, + G3InterruptAcknowledge, + G3StatusRegister, + G23StatusRegister, + G2CommandRegister, + G3CommandRegister, + G2HWSaveRegister, + G3HWSaveRegister, + G2SWSaveRegister, + G3SWSaveRegister, + G2ModeRegister, + G23JointStatus1Register, + G3ModeRegister, + G2LoadARegister, + G23JointStatus2Register, + G2LoadBRegister, + G3LoadARegister, + G3LoadBRegister, + G2InputSelectRegister, + G3InputSelectRegister, + G2AutoincrementRegister, + G3AutoincrementRegister, + G23JointResetRegister, + G2InterruptEnable, + G3InterruptEnable, + G2CountingModeRegister, + G3CountingModeRegister, + G3SecondGateRegister, + G2SecondGateRegister, + G2DMAConfigRegister, + G2DMAStatusRegister, + G3DMAConfigRegister, + G3DMAStatusRegister, + DIO32Input, + DIO32Output, + ClockConfigRegister, + GlobalInterruptStatusRegister, + DMAConfigRegister, + GlobalInterruptConfigRegister, + IOConfigReg0_1, + IOConfigReg2_3, + IOConfigReg4_5, + IOConfigReg6_7, + IOConfigReg8_9, + IOConfigReg10_11, + IOConfigReg12_13, + IOConfigReg14_15, + IOConfigReg16_17, + IOConfigReg18_19, + IOConfigReg20_21, + IOConfigReg22_23, + IOConfigReg24_25, + IOConfigReg26_27, + IOConfigReg28_29, + IOConfigReg30_31, + IOConfigReg32_33, + IOConfigReg34_35, + IOConfigReg36_37, + IOConfigReg38_39, + NumRegisters, +}; + +static inline unsigned IOConfigReg(unsigned pfi_channel) +{ + unsigned reg = IOConfigReg0_1 + pfi_channel / 2; + BUG_ON(reg > IOConfigReg38_39); + return reg; +} + +enum ni_660x_register_width { + DATA_1B, + DATA_2B, + DATA_4B +}; + +enum ni_660x_register_direction { + NI_660x_READ, + NI_660x_WRITE, + NI_660x_READ_WRITE +}; + +enum ni_660x_pfi_output_select { + pfi_output_select_high_Z = 0, + pfi_output_select_counter = 1, + pfi_output_select_do = 2, + num_pfi_output_selects +}; + +enum ni_660x_subdevices { + NI_660X_DIO_SUBDEV = 1, + NI_660X_GPCT_SUBDEV_0 = 2 +}; +static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index) +{ + return NI_660X_GPCT_SUBDEV_0 + index; +} + +struct NI_660xRegisterData { + + const char *name; // Register Name + int offset; // Offset from base address from GPCT chip + enum ni_660x_register_direction direction; + enum ni_660x_register_width size; // 1 byte, 2 bytes, or 4 bytes +}; + + +static const struct NI_660xRegisterData registerData[NumRegisters] = { + {"G0 Interrupt Acknowledge", 0x004, NI_660x_WRITE, DATA_2B}, + {"G0 Status Register", 0x004, NI_660x_READ, DATA_2B}, + {"G1 Interrupt Acknowledge", 0x006, NI_660x_WRITE, DATA_2B}, + {"G1 Status Register", 0x006, NI_660x_READ, DATA_2B}, + {"G01 Status Register ", 0x008, NI_660x_READ, DATA_2B}, + {"G0 Command Register", 0x00C, NI_660x_WRITE, DATA_2B}, + {"STC DIO Parallel Input", 0x00E, NI_660x_READ, DATA_2B}, + {"G1 Command Register", 0x00E, NI_660x_WRITE, DATA_2B}, + {"G0 HW Save Register", 0x010, NI_660x_READ, DATA_4B}, + {"G1 HW Save Register", 0x014, NI_660x_READ, DATA_4B}, + {"STC DIO Output", 0x014, NI_660x_WRITE, DATA_2B}, + {"STC DIO Control", 0x016, NI_660x_WRITE, DATA_2B}, + {"G0 SW Save Register", 0x018, NI_660x_READ, DATA_4B}, + {"G1 SW Save Register", 0x01C, NI_660x_READ, DATA_4B}, + {"G0 Mode Register", 0x034, NI_660x_WRITE, DATA_2B}, + {"G01 Joint Status 1 Register", 0x036, NI_660x_READ, DATA_2B}, + {"G1 Mode Register", 0x036, NI_660x_WRITE, DATA_2B}, + {"STC DIO Serial Input", 0x038, NI_660x_READ, DATA_2B}, + {"G0 Load A Register", 0x038, NI_660x_WRITE, DATA_4B}, + {"G01 Joint Status 2 Register", 0x03A, NI_660x_READ, DATA_2B}, + {"G0 Load B Register", 0x03C, NI_660x_WRITE, DATA_4B}, + {"G1 Load A Register", 0x040, NI_660x_WRITE, DATA_4B}, + {"G1 Load B Register", 0x044, NI_660x_WRITE, DATA_4B}, + {"G0 Input Select Register", 0x048, NI_660x_WRITE, DATA_2B}, + {"G1 Input Select Register", 0x04A, NI_660x_WRITE, DATA_2B}, + {"G0 Autoincrement Register", 0x088, NI_660x_WRITE, DATA_2B}, + {"G1 Autoincrement Register", 0x08A, NI_660x_WRITE, DATA_2B}, + {"G01 Joint Reset Register", 0x090, NI_660x_WRITE, DATA_2B}, + {"G0 Interrupt Enable", 0x092, NI_660x_WRITE, DATA_2B}, + {"G1 Interrupt Enable", 0x096, NI_660x_WRITE, DATA_2B}, + {"G0 Counting Mode Register", 0x0B0, NI_660x_WRITE, DATA_2B}, + {"G1 Counting Mode Register", 0x0B2, NI_660x_WRITE, DATA_2B}, + {"G0 Second Gate Register", 0x0B4, NI_660x_WRITE, DATA_2B}, + {"G1 Second Gate Register", 0x0B6, NI_660x_WRITE, DATA_2B}, + {"G0 DMA Config Register", 0x0B8, NI_660x_WRITE, DATA_2B}, + {"G0 DMA Status Register", 0x0B8, NI_660x_READ, DATA_2B}, + {"G1 DMA Config Register", 0x0BA, NI_660x_WRITE, DATA_2B}, + {"G1 DMA Status Register", 0x0BA, NI_660x_READ, DATA_2B}, + {"G2 Interrupt Acknowledge", 0x104, NI_660x_WRITE, DATA_2B}, + {"G2 Status Register", 0x104, NI_660x_READ, DATA_2B}, + {"G3 Interrupt Acknowledge", 0x106, NI_660x_WRITE, DATA_2B}, + {"G3 Status Register", 0x106, NI_660x_READ, DATA_2B}, + {"G23 Status Register", 0x108, NI_660x_READ, DATA_2B}, + {"G2 Command Register", 0x10C, NI_660x_WRITE, DATA_2B}, + {"G3 Command Register", 0x10E, NI_660x_WRITE, DATA_2B}, + {"G2 HW Save Register", 0x110, NI_660x_READ, DATA_4B}, + {"G3 HW Save Register", 0x114, NI_660x_READ, DATA_4B}, + {"G2 SW Save Register", 0x118, NI_660x_READ, DATA_4B}, + {"G3 SW Save Register", 0x11C, NI_660x_READ, DATA_4B}, + {"G2 Mode Register", 0x134, NI_660x_WRITE, DATA_2B}, + {"G23 Joint Status 1 Register", 0x136, NI_660x_READ, DATA_2B}, + {"G3 Mode Register", 0x136, NI_660x_WRITE, DATA_2B}, + {"G2 Load A Register", 0x138, NI_660x_WRITE, DATA_4B}, + {"G23 Joint Status 2 Register", 0x13A, NI_660x_READ, DATA_2B}, + {"G2 Load B Register", 0x13C, NI_660x_WRITE, DATA_4B}, + {"G3 Load A Register", 0x140, NI_660x_WRITE, DATA_4B}, + {"G3 Load B Register", 0x144, NI_660x_WRITE, DATA_4B}, + {"G2 Input Select Register", 0x148, NI_660x_WRITE, DATA_2B}, + {"G3 Input Select Register", 0x14A, NI_660x_WRITE, DATA_2B}, + {"G2 Autoincrement Register", 0x188, NI_660x_WRITE, DATA_2B}, + {"G3 Autoincrement Register", 0x18A, NI_660x_WRITE, DATA_2B}, + {"G23 Joint Reset Register", 0x190, NI_660x_WRITE, DATA_2B}, + {"G2 Interrupt Enable", 0x192, NI_660x_WRITE, DATA_2B}, + {"G3 Interrupt Enable", 0x196, NI_660x_WRITE, DATA_2B}, + {"G2 Counting Mode Register", 0x1B0, NI_660x_WRITE, DATA_2B}, + {"G3 Counting Mode Register", 0x1B2, NI_660x_WRITE, DATA_2B}, + {"G3 Second Gate Register", 0x1B6, NI_660x_WRITE, DATA_2B}, + {"G2 Second Gate Register", 0x1B4, NI_660x_WRITE, DATA_2B}, + {"G2 DMA Config Register", 0x1B8, NI_660x_WRITE, DATA_2B}, + {"G2 DMA Status Register", 0x1B8, NI_660x_READ, DATA_2B}, + {"G3 DMA Config Register", 0x1BA, NI_660x_WRITE, DATA_2B}, + {"G3 DMA Status Register", 0x1BA, NI_660x_READ, DATA_2B}, + {"32 bit Digital Input", 0x414, NI_660x_READ, DATA_4B}, + {"32 bit Digital Output", 0x510, NI_660x_WRITE, DATA_4B}, + {"Clock Config Register", 0x73C, NI_660x_WRITE, DATA_4B}, + {"Global Interrupt Status Register", 0x754, NI_660x_READ, DATA_4B}, + {"DMA Configuration Register", 0x76C, NI_660x_WRITE, DATA_4B}, + {"Global Interrupt Config Register", 0x770, NI_660x_WRITE, DATA_4B}, + {"IO Config Register 0-1", 0x77C, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 2-3", 0x77E, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 4-5", 0x780, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 6-7", 0x782, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 8-9", 0x784, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 10-11", 0x786, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 12-13", 0x788, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 14-15", 0x78A, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 16-17", 0x78C, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 18-19", 0x78E, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 20-21", 0x790, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 22-23", 0x792, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 24-25", 0x794, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 26-27", 0x796, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 28-29", 0x798, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 30-31", 0x79A, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 32-33", 0x79C, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 34-35", 0x79E, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 36-37", 0x7A0, NI_660x_READ_WRITE, DATA_2B}, + {"IO Config Register 38-39", 0x7A2, NI_660x_READ_WRITE, DATA_2B} +}; + +// kind of ENABLE for the second counter +enum clock_config_register_bits { + CounterSwap = 0x1 << 21 +}; + +// ioconfigreg +static inline unsigned ioconfig_bitshift(unsigned pfi_channel) +{ + if (pfi_channel % 2) + return 0; + else + return 8; +} +static inline unsigned pfi_output_select_mask(unsigned pfi_channel) +{ + return 0x3 << ioconfig_bitshift(pfi_channel); +} +static inline unsigned pfi_output_select_bits(unsigned pfi_channel, + unsigned output_select) +{ + return (output_select & 0x3) << ioconfig_bitshift(pfi_channel); +} +static inline unsigned pfi_input_select_mask(unsigned pfi_channel) +{ + return 0x7 << (4 + ioconfig_bitshift(pfi_channel)); +} +static inline unsigned pfi_input_select_bits(unsigned pfi_channel, + unsigned input_select) +{ + return (input_select & 0x7) << (4 + ioconfig_bitshift(pfi_channel)); +} + +// dma configuration register bits +static inline unsigned dma_select_mask(unsigned dma_channel) +{ + BUG_ON(dma_channel >= MAX_DMA_CHANNEL); + return 0x1f << (8 * dma_channel); +} +enum dma_selection { + dma_selection_none = 0x1f, +}; +static inline unsigned dma_selection_counter(unsigned counter_index) +{ + BUG_ON(counter_index >= counters_per_chip); + return counter_index; +} +static inline unsigned dma_select_bits(unsigned dma_channel, unsigned selection) +{ + BUG_ON(dma_channel >= MAX_DMA_CHANNEL); + return (selection << (8 * dma_channel)) & dma_select_mask(dma_channel); +} +static inline unsigned dma_reset_bit(unsigned dma_channel) +{ + BUG_ON(dma_channel >= MAX_DMA_CHANNEL); + return 0x80 << (8 * dma_channel); +} + +enum global_interrupt_status_register_bits { + Counter_0_Int_Bit = 0x100, + Counter_1_Int_Bit = 0x200, + Counter_2_Int_Bit = 0x400, + Counter_3_Int_Bit = 0x800, + Cascade_Int_Bit = 0x20000000, + Global_Int_Bit = 0x80000000 +}; + +enum global_interrupt_config_register_bits { + Cascade_Int_Enable_Bit = 0x20000000, + Global_Int_Polarity_Bit = 0x40000000, + Global_Int_Enable_Bit = 0x80000000 +}; + +// Offset of the GPCT chips from the base-adress of the card +static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 }; /* First chip is at base-address + + 0x00, etc. */ + +/* Board description*/ +struct ni_660x_board { + unsigned short dev_id; /* `lspci` will show you this */ + const char *name; + unsigned n_chips; /* total number of TIO chips */ +}; + +static const struct ni_660x_board ni_660x_boards[] = { + { + dev_id: 0x2c60, + name: "PCI-6601", + n_chips: 1, + }, + { + dev_id: 0x1310, + name: "PCI-6602", + n_chips: 2, + }, + { + dev_id: 0x1360, + name: "PXI-6602", + n_chips: 2, + }, + { + dev_id: 0x2cc0, + name: "PXI-6608", + n_chips: 2, + }, +}; + +#define NI_660X_MAX_NUM_CHIPS 2 +#define NI_660X_MAX_NUM_COUNTERS (NI_660X_MAX_NUM_CHIPS * counters_per_chip) + +static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = { + {PCI_VENDOR_ID_NATINST, 0x2c60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2cc0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, ni_660x_pci_table); + +struct ni_660x_private { + struct mite_struct *mite; + struct ni_gpct_device *counter_dev; + uint64_t pfi_direction_bits; + struct mite_dma_descriptor_ring + *mite_rings[NI_660X_MAX_NUM_CHIPS][counters_per_chip]; + spinlock_t mite_channel_lock; + unsigned dma_configuration_soft_copies[NI_660X_MAX_NUM_CHIPS]; + spinlock_t soft_reg_copy_lock; + unsigned short pfi_output_selects[NUM_PFI_CHANNELS]; +}; + +static inline struct ni_660x_private *private(struct comedi_device * dev) +{ + return dev->private; +} + +/* initialized in ni_660x_find_device() */ +static inline const struct ni_660x_board *board(struct comedi_device * dev) +{ + return dev->board_ptr; +} + +#define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0])) + +static int ni_660x_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int ni_660x_detach(struct comedi_device * dev); +static void init_tio_chip(struct comedi_device * dev, int chipset); +static void ni_660x_select_pfi_output(struct comedi_device * dev, unsigned pfi_channel, + unsigned output_select); + +static struct comedi_driver driver_ni_660x = { + driver_name:"ni_660x", + module:THIS_MODULE, + attach:ni_660x_attach, + detach:ni_660x_detach, +}; + +COMEDI_PCI_INITCLEANUP(driver_ni_660x, ni_660x_pci_table); + +static int ni_660x_find_device(struct comedi_device * dev, int bus, int slot); +static int ni_660x_set_pfi_routing(struct comedi_device * dev, unsigned chan, + unsigned source); + +/* Possible instructions for a GPCT */ +static int ni_660x_GPCT_rinsn(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); +static int ni_660x_GPCT_insn_config(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); +static int ni_660x_GPCT_winsn(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +/* Possible instructions for Digital IO */ +static int ni_660x_dio_insn_config(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); +static int ni_660x_dio_insn_bits(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +static inline unsigned ni_660x_num_counters(struct comedi_device * dev) +{ + return board(dev)->n_chips * counters_per_chip; +} + +static enum NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg) +{ + enum NI_660x_Register ni_660x_register; + switch (reg) { + case NITIO_G0_Autoincrement_Reg: + ni_660x_register = G0AutoincrementRegister; + break; + case NITIO_G1_Autoincrement_Reg: + ni_660x_register = G1AutoincrementRegister; + break; + case NITIO_G2_Autoincrement_Reg: + ni_660x_register = G2AutoincrementRegister; + break; + case NITIO_G3_Autoincrement_Reg: + ni_660x_register = G3AutoincrementRegister; + break; + case NITIO_G0_Command_Reg: + ni_660x_register = G0CommandRegister; + break; + case NITIO_G1_Command_Reg: + ni_660x_register = G1CommandRegister; + break; + case NITIO_G2_Command_Reg: + ni_660x_register = G2CommandRegister; + break; + case NITIO_G3_Command_Reg: + ni_660x_register = G3CommandRegister; + break; + case NITIO_G0_HW_Save_Reg: + ni_660x_register = G0HWSaveRegister; + break; + case NITIO_G1_HW_Save_Reg: + ni_660x_register = G1HWSaveRegister; + break; + case NITIO_G2_HW_Save_Reg: + ni_660x_register = G2HWSaveRegister; + break; + case NITIO_G3_HW_Save_Reg: + ni_660x_register = G3HWSaveRegister; + break; + case NITIO_G0_SW_Save_Reg: + ni_660x_register = G0SWSaveRegister; + break; + case NITIO_G1_SW_Save_Reg: + ni_660x_register = G1SWSaveRegister; + break; + case NITIO_G2_SW_Save_Reg: + ni_660x_register = G2SWSaveRegister; + break; + case NITIO_G3_SW_Save_Reg: + ni_660x_register = G3SWSaveRegister; + break; + case NITIO_G0_Mode_Reg: + ni_660x_register = G0ModeRegister; + break; + case NITIO_G1_Mode_Reg: + ni_660x_register = G1ModeRegister; + break; + case NITIO_G2_Mode_Reg: + ni_660x_register = G2ModeRegister; + break; + case NITIO_G3_Mode_Reg: + ni_660x_register = G3ModeRegister; + break; + case NITIO_G0_LoadA_Reg: + ni_660x_register = G0LoadARegister; + break; + case NITIO_G1_LoadA_Reg: + ni_660x_register = G1LoadARegister; + break; + case NITIO_G2_LoadA_Reg: + ni_660x_register = G2LoadARegister; + break; + case NITIO_G3_LoadA_Reg: + ni_660x_register = G3LoadARegister; + break; + case NITIO_G0_LoadB_Reg: + ni_660x_register = G0LoadBRegister; + break; + case NITIO_G1_LoadB_Reg: + ni_660x_register = G1LoadBRegister; + break; + case NITIO_G2_LoadB_Reg: + ni_660x_register = G2LoadBRegister; + break; + case NITIO_G3_LoadB_Reg: + ni_660x_register = G3LoadBRegister; + break; + case NITIO_G0_Input_Select_Reg: + ni_660x_register = G0InputSelectRegister; + break; + case NITIO_G1_Input_Select_Reg: + ni_660x_register = G1InputSelectRegister; + break; + case NITIO_G2_Input_Select_Reg: + ni_660x_register = G2InputSelectRegister; + break; + case NITIO_G3_Input_Select_Reg: + ni_660x_register = G3InputSelectRegister; + break; + case NITIO_G01_Status_Reg: + ni_660x_register = G01StatusRegister; + break; + case NITIO_G23_Status_Reg: + ni_660x_register = G23StatusRegister; + break; + case NITIO_G01_Joint_Reset_Reg: + ni_660x_register = G01JointResetRegister; + break; + case NITIO_G23_Joint_Reset_Reg: + ni_660x_register = G23JointResetRegister; + break; + case NITIO_G01_Joint_Status1_Reg: + ni_660x_register = G01JointStatus1Register; + break; + case NITIO_G23_Joint_Status1_Reg: + ni_660x_register = G23JointStatus1Register; + break; + case NITIO_G01_Joint_Status2_Reg: + ni_660x_register = G01JointStatus2Register; + break; + case NITIO_G23_Joint_Status2_Reg: + ni_660x_register = G23JointStatus2Register; + break; + case NITIO_G0_Counting_Mode_Reg: + ni_660x_register = G0CountingModeRegister; + break; + case NITIO_G1_Counting_Mode_Reg: + ni_660x_register = G1CountingModeRegister; + break; + case NITIO_G2_Counting_Mode_Reg: + ni_660x_register = G2CountingModeRegister; + break; + case NITIO_G3_Counting_Mode_Reg: + ni_660x_register = G3CountingModeRegister; + break; + case NITIO_G0_Second_Gate_Reg: + ni_660x_register = G0SecondGateRegister; + break; + case NITIO_G1_Second_Gate_Reg: + ni_660x_register = G1SecondGateRegister; + break; + case NITIO_G2_Second_Gate_Reg: + ni_660x_register = G2SecondGateRegister; + break; + case NITIO_G3_Second_Gate_Reg: + ni_660x_register = G3SecondGateRegister; + break; + case NITIO_G0_DMA_Config_Reg: + ni_660x_register = G0DMAConfigRegister; + break; + case NITIO_G0_DMA_Status_Reg: + ni_660x_register = G0DMAStatusRegister; + break; + case NITIO_G1_DMA_Config_Reg: + ni_660x_register = G1DMAConfigRegister; + break; + case NITIO_G1_DMA_Status_Reg: + ni_660x_register = G1DMAStatusRegister; + break; + case NITIO_G2_DMA_Config_Reg: + ni_660x_register = G2DMAConfigRegister; + break; + case NITIO_G2_DMA_Status_Reg: + ni_660x_register = G2DMAStatusRegister; + break; + case NITIO_G3_DMA_Config_Reg: + ni_660x_register = G3DMAConfigRegister; + break; + case NITIO_G3_DMA_Status_Reg: + ni_660x_register = G3DMAStatusRegister; + break; + case NITIO_G0_Interrupt_Acknowledge_Reg: + ni_660x_register = G0InterruptAcknowledge; + break; + case NITIO_G1_Interrupt_Acknowledge_Reg: + ni_660x_register = G1InterruptAcknowledge; + break; + case NITIO_G2_Interrupt_Acknowledge_Reg: + ni_660x_register = G2InterruptAcknowledge; + break; + case NITIO_G3_Interrupt_Acknowledge_Reg: + ni_660x_register = G3InterruptAcknowledge; + break; + case NITIO_G0_Status_Reg: + ni_660x_register = G0StatusRegister; + break; + case NITIO_G1_Status_Reg: + ni_660x_register = G0StatusRegister; + break; + case NITIO_G2_Status_Reg: + ni_660x_register = G0StatusRegister; + break; + case NITIO_G3_Status_Reg: + ni_660x_register = G0StatusRegister; + break; + case NITIO_G0_Interrupt_Enable_Reg: + ni_660x_register = G0InterruptEnable; + break; + case NITIO_G1_Interrupt_Enable_Reg: + ni_660x_register = G1InterruptEnable; + break; + case NITIO_G2_Interrupt_Enable_Reg: + ni_660x_register = G2InterruptEnable; + break; + case NITIO_G3_Interrupt_Enable_Reg: + ni_660x_register = G3InterruptEnable; + break; + default: + rt_printk("%s: unhandled register 0x%x in switch.\n", + __FUNCTION__, reg); + BUG(); + return 0; + break; + } + return ni_660x_register; +} + +static inline void ni_660x_write_register(struct comedi_device * dev, + unsigned chip_index, unsigned bits, enum NI_660x_Register reg) +{ + void *const write_address = + private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] + + registerData[reg].offset; + + switch (registerData[reg].size) { + case DATA_2B: + writew(bits, write_address); + break; + case DATA_4B: + writel(bits, write_address); + break; + default: + rt_printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n", + __FILE__, __FUNCTION__, reg); + BUG(); + break; + } +} + +static inline unsigned ni_660x_read_register(struct comedi_device * dev, + unsigned chip_index, enum NI_660x_Register reg) +{ + void *const read_address = + private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] + + registerData[reg].offset; + + switch (registerData[reg].size) { + case DATA_2B: + return readw(read_address); + break; + case DATA_4B: + return readl(read_address); + break; + default: + rt_printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n", + __FILE__, __FUNCTION__, reg); + BUG(); + break; + } + return 0; +} + +static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, + enum ni_gpct_register reg) +{ + struct comedi_device *dev = counter->counter_dev->dev; + enum NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg); + ni_660x_write_register(dev, counter->chip_index, bits, + ni_660x_register); +} + +static unsigned ni_gpct_read_register(struct ni_gpct *counter, + enum ni_gpct_register reg) +{ + struct comedi_device *dev = counter->counter_dev->dev; + enum NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg); + return ni_660x_read_register(dev, counter->chip_index, + ni_660x_register); +} + +static inline struct mite_dma_descriptor_ring *mite_ring(struct ni_660x_private * priv, + struct ni_gpct *counter) +{ + return priv->mite_rings[counter->chip_index][counter->counter_index]; +} + +static inline void ni_660x_set_dma_channel(struct comedi_device * dev, + unsigned mite_channel, struct ni_gpct *counter) +{ + unsigned long flags; + comedi_spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags); + private(dev)->dma_configuration_soft_copies[counter->chip_index] &= + ~dma_select_mask(mite_channel); + private(dev)->dma_configuration_soft_copies[counter->chip_index] |= + dma_select_bits(mite_channel, + dma_selection_counter(counter->counter_index)); + ni_660x_write_register(dev, counter->chip_index, + private(dev)->dma_configuration_soft_copies[counter-> + chip_index] | dma_reset_bit(mite_channel), + DMAConfigRegister); + mmiowb(); + comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags); +} + +static inline void ni_660x_unset_dma_channel(struct comedi_device * dev, + unsigned mite_channel, struct ni_gpct *counter) +{ + unsigned long flags; + comedi_spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags); + private(dev)->dma_configuration_soft_copies[counter->chip_index] &= + ~dma_select_mask(mite_channel); + private(dev)->dma_configuration_soft_copies[counter->chip_index] |= + dma_select_bits(mite_channel, dma_selection_none); + ni_660x_write_register(dev, counter->chip_index, + private(dev)->dma_configuration_soft_copies[counter-> + chip_index], DMAConfigRegister); + mmiowb(); + comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags); +} + +static int ni_660x_request_mite_channel(struct comedi_device * dev, + struct ni_gpct *counter, enum comedi_io_direction direction) +{ + unsigned long flags; + struct mite_channel *mite_chan; + + comedi_spin_lock_irqsave(&private(dev)->mite_channel_lock, flags); + BUG_ON(counter->mite_chan); + mite_chan = + mite_request_channel(private(dev)->mite, mite_ring(private(dev), + counter)); + if (mite_chan == NULL) { + comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, + flags); + comedi_error(dev, + "failed to reserve mite dma channel for counter."); + return -EBUSY; + } + mite_chan->dir = direction; + ni_tio_set_mite_channel(counter, mite_chan); + ni_660x_set_dma_channel(dev, mite_chan->channel, counter); + comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags); + return 0; +} + +void ni_660x_release_mite_channel(struct comedi_device * dev, struct ni_gpct *counter) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&private(dev)->mite_channel_lock, flags); + if (counter->mite_chan) { + struct mite_channel *mite_chan = counter->mite_chan; + + ni_660x_unset_dma_channel(dev, mite_chan->channel, counter); + ni_tio_set_mite_channel(counter, NULL); + mite_release_channel(mite_chan); + } + comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags); +} + +static int ni_660x_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int retval; + + struct ni_gpct *counter = subdev_to_counter(s); +// const struct comedi_cmd *cmd = &s->async->cmd; + + retval = ni_660x_request_mite_channel(dev, counter, COMEDI_INPUT); + if (retval) { + comedi_error(dev, + "no dma channel available for use by counter"); + return retval; + } + ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL); + retval = ni_tio_cmd(counter, s->async); + + return retval; +} + +static int ni_660x_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + struct ni_gpct *counter = subdev_to_counter(s); + + return ni_tio_cmdtest(counter, cmd); +} + +static int ni_660x_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct ni_gpct *counter = subdev_to_counter(s); + int retval; + + retval = ni_tio_cancel(counter); + ni_660x_release_mite_channel(dev, counter); + return retval; +} + +static void set_tio_counterswap(struct comedi_device * dev, int chipset) +{ + /* See P. 3.5 of the Register-Level Programming manual. The + CounterSwap bit has to be set on the second chip, otherwise + it will try to use the same pins as the first chip. + */ + if (chipset) + ni_660x_write_register(dev, chipset, CounterSwap, + ClockConfigRegister); + else + ni_660x_write_register(dev, chipset, 0, ClockConfigRegister); +} + +static void ni_660x_handle_gpct_interrupt(struct comedi_device * dev, + struct comedi_subdevice * s) +{ + ni_tio_handle_interrupt(subdev_to_counter(s), s); + if (s->async->events) { + if (s->async-> + events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | + COMEDI_CB_OVERFLOW)) { + ni_660x_cancel(dev, s); + } + comedi_event(dev, s); + } +} + +static irqreturn_t ni_660x_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s; + unsigned i; + + if (dev->attached == 0) + return IRQ_NONE; + smp_mb(); + for (i = 0; i < ni_660x_num_counters(dev); ++i) { + s = dev->subdevices + NI_660X_GPCT_SUBDEV(i); + ni_660x_handle_gpct_interrupt(dev, s); + } + return IRQ_HANDLED; +} + +static int ni_660x_buf_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size) +{ + int ret; + + ret = mite_buf_change(mite_ring(private(dev), subdev_to_counter(s)), + s->async); + if (ret < 0) + return ret; + + return 0; +} + +static int ni_660x_allocate_private(struct comedi_device * dev) +{ + int retval; + unsigned i; + + if ((retval = alloc_private(dev, sizeof(struct ni_660x_private))) < 0) + return retval; + spin_lock_init(&private(dev)->mite_channel_lock); + spin_lock_init(&private(dev)->soft_reg_copy_lock); + for (i = 0; i < NUM_PFI_CHANNELS; ++i) { + private(dev)->pfi_output_selects[i] = pfi_output_select_counter; + } + return 0; +} + +static int ni_660x_alloc_mite_rings(struct comedi_device * dev) +{ + unsigned i; + unsigned j; + + for (i = 0; i < board(dev)->n_chips; ++i) { + for (j = 0; j < counters_per_chip; ++j) { + private(dev)->mite_rings[i][j] = + mite_alloc_ring(private(dev)->mite); + if (private(dev)->mite_rings[i][j] == NULL) { + return -ENOMEM; + } + } + } + return 0; +} + +static void ni_660x_free_mite_rings(struct comedi_device * dev) +{ + unsigned i; + unsigned j; + + for (i = 0; i < board(dev)->n_chips; ++i) { + for (j = 0; j < counters_per_chip; ++j) { + mite_free_ring(private(dev)->mite_rings[i][j]); + } + } +} + +static int ni_660x_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret; + unsigned i; + unsigned global_interrupt_config_bits; + + printk("comedi%d: ni_660x: ", dev->minor); + + ret = ni_660x_allocate_private(dev); + if (ret < 0) + return ret; + ret = ni_660x_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; + + dev->board_name = board(dev)->name; + + ret = mite_setup2(private(dev)->mite, 1); + if (ret < 0) { + printk("error setting up mite\n"); + return ret; + } + comedi_set_hw_dev(dev, &private(dev)->mite->pcidev->dev); + ret = ni_660x_alloc_mite_rings(dev); + if (ret < 0) + return ret; + + printk(" %s ", dev->board_name); + + dev->n_subdevices = 2 + NI_660X_MAX_NUM_COUNTERS; + + if (alloc_subdevices(dev, dev->n_subdevices) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */ + s->type = COMEDI_SUBD_UNUSED; + + s = dev->subdevices + NI_660X_DIO_SUBDEV; + /* DIGITAL I/O SUBDEVICE */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = NUM_PFI_CHANNELS; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ni_660x_dio_insn_bits; + s->insn_config = ni_660x_dio_insn_config; + s->io_bits = 0; /* all bits default to input */ + // we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg + ni_660x_write_register(dev, 0, 0, STCDIOControl); + + private(dev)->counter_dev = ni_gpct_device_construct(dev, + &ni_gpct_write_register, &ni_gpct_read_register, + ni_gpct_variant_660x, ni_660x_num_counters(dev)); + if (private(dev)->counter_dev == NULL) + return -ENOMEM; + for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) { + s = dev->subdevices + NI_660X_GPCT_SUBDEV(i); + if (i < ni_660x_num_counters(dev)) { + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = + SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | + SDF_CMD_READ /* | SDF_CMD_WRITE */ ; + s->n_chan = 3; + s->maxdata = 0xffffffff; + s->insn_read = ni_660x_GPCT_rinsn; + s->insn_write = ni_660x_GPCT_winsn; + s->insn_config = ni_660x_GPCT_insn_config; + s->do_cmd = &ni_660x_cmd; + s->len_chanlist = 1; + s->do_cmdtest = &ni_660x_cmdtest; + s->cancel = &ni_660x_cancel; + s->async_dma_dir = DMA_BIDIRECTIONAL; + s->buf_change = &ni_660x_buf_change; + s->private = &private(dev)->counter_dev->counters[i]; + + private(dev)->counter_dev->counters[i].chip_index = + i / counters_per_chip; + private(dev)->counter_dev->counters[i].counter_index = + i % counters_per_chip; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + } + for (i = 0; i < board(dev)->n_chips; ++i) { + init_tio_chip(dev, i); + } + for (i = 0; i < ni_660x_num_counters(dev); ++i) { + ni_tio_init_counter(&private(dev)->counter_dev->counters[i]); + } + for (i = 0; i < NUM_PFI_CHANNELS; ++i) { + if (i < min_counter_pfi_chan) + ni_660x_set_pfi_routing(dev, i, pfi_output_select_do); + else + ni_660x_set_pfi_routing(dev, i, + pfi_output_select_counter); + ni_660x_select_pfi_output(dev, i, pfi_output_select_high_Z); + } + /* to be safe, set counterswap bits on tio chips after all the counter + outputs have been set to high impedance mode */ + for (i = 0; i < board(dev)->n_chips; ++i) { + set_tio_counterswap(dev, i); + } + if ((ret = comedi_request_irq(mite_irq(private(dev)->mite), + &ni_660x_interrupt, IRQF_SHARED, "ni_660x", + dev)) < 0) { + printk(" irq not available\n"); + return ret; + } + dev->irq = mite_irq(private(dev)->mite); + global_interrupt_config_bits = Global_Int_Enable_Bit; + if (board(dev)->n_chips > 1) + global_interrupt_config_bits |= Cascade_Int_Enable_Bit; + ni_660x_write_register(dev, 0, global_interrupt_config_bits, + GlobalInterruptConfigRegister); + printk("attached\n"); + return 0; +} + +static int ni_660x_detach(struct comedi_device * dev) +{ + printk("comedi%d: ni_660x: remove\n", dev->minor); + + /* Free irq */ + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + if (dev->private) { + if (private(dev)->counter_dev) + ni_gpct_device_destroy(private(dev)->counter_dev); + if (private(dev)->mite) { + ni_660x_free_mite_rings(dev); + mite_unsetup(private(dev)->mite); + } + } + return 0; +} + +static int +ni_660x_GPCT_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + return ni_tio_rinsn(subdev_to_counter(s), insn, data); +} + +static void init_tio_chip(struct comedi_device * dev, int chipset) +{ + unsigned i; + + // init dma configuration register + private(dev)->dma_configuration_soft_copies[chipset] = 0; + for (i = 0; i < MAX_DMA_CHANNEL; ++i) { + private(dev)->dma_configuration_soft_copies[chipset] |= + dma_select_bits(i, + dma_selection_none) & dma_select_mask(i); + } + ni_660x_write_register(dev, chipset, + private(dev)->dma_configuration_soft_copies[chipset], + DMAConfigRegister); + for(i = 0; i < NUM_PFI_CHANNELS; ++i) + { + ni_660x_write_register(dev, chipset, 0, IOConfigReg(i)); + } +} + +static int +ni_660x_GPCT_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + return ni_tio_insn_config(subdev_to_counter(s), insn, data); +} + +static int ni_660x_GPCT_winsn(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + return ni_tio_winsn(subdev_to_counter(s), insn, data); +} + +static int ni_660x_find_device(struct comedi_device * dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + + for (i = 0; i < n_ni_660x_boards; i++) { + if (mite_device_id(mite) == ni_660x_boards[i].dev_id) { + dev->board_ptr = ni_660x_boards + i; + private(dev)->mite = mite; + return 0; + } + } + } + printk("no device found\n"); + mite_list_devices(); + return -EIO; +} + +static int ni_660x_dio_insn_bits(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + unsigned base_bitfield_channel = CR_CHAN(insn->chanspec); + + // Check if we have to write some bits + if (data[0]) { + s->state &= ~(data[0] << base_bitfield_channel); + s->state |= (data[0] & data[1]) << base_bitfield_channel; + /* Write out the new digital output lines */ + ni_660x_write_register(dev, 0, s->state, DIO32Output); + } + /* on return, data[1] contains the value of the digital + * input and output lines. */ + data[1] = + (ni_660x_read_register(dev, 0, + DIO32Input) >> base_bitfield_channel); + return 2; +} + +static void ni_660x_select_pfi_output(struct comedi_device * dev, unsigned pfi_channel, + unsigned output_select) +{ + static const unsigned counter_4_7_first_pfi = 8; + static const unsigned counter_4_7_last_pfi = 23; + unsigned active_chipset = 0; + unsigned idle_chipset = 0; + unsigned active_bits; + unsigned idle_bits; + + if(board(dev)->n_chips > 1) { + if(output_select == pfi_output_select_counter && + pfi_channel >= counter_4_7_first_pfi && + pfi_channel <= counter_4_7_last_pfi) { + active_chipset = 1; + idle_chipset = 0; + }else { + active_chipset = 0; + idle_chipset = 1; + } + } + + if(idle_chipset != active_chipset) { + idle_bits = ni_660x_read_register(dev, idle_chipset, IOConfigReg(pfi_channel)); + idle_bits &= ~pfi_output_select_mask(pfi_channel); + idle_bits |= pfi_output_select_bits(pfi_channel, pfi_output_select_high_Z); + ni_660x_write_register(dev, idle_chipset, idle_bits, IOConfigReg(pfi_channel)); + } + + active_bits = ni_660x_read_register(dev, active_chipset, IOConfigReg(pfi_channel)); + active_bits &= ~pfi_output_select_mask(pfi_channel); + active_bits |= pfi_output_select_bits(pfi_channel, output_select); + ni_660x_write_register(dev, active_chipset, active_bits, IOConfigReg(pfi_channel)); +} + +static int ni_660x_set_pfi_routing(struct comedi_device * dev, unsigned chan, + unsigned source) +{ + if (source > num_pfi_output_selects) + return -EINVAL; + if (source == pfi_output_select_high_Z) + return -EINVAL; + if (chan < min_counter_pfi_chan) { + if (source == pfi_output_select_counter) + return -EINVAL; + } else if (chan > max_dio_pfi_chan) { + if (source == pfi_output_select_do) + return -EINVAL; + } + BUG_ON(chan >= NUM_PFI_CHANNELS); + + private(dev)->pfi_output_selects[chan] = source; + if (private(dev)->pfi_direction_bits & (((uint64_t) 1) << chan)) + ni_660x_select_pfi_output(dev, chan, + private(dev)->pfi_output_selects[chan]); + return 0; +} + +static unsigned ni_660x_get_pfi_routing(struct comedi_device * dev, unsigned chan) +{ + BUG_ON(chan >= NUM_PFI_CHANNELS); + return private(dev)->pfi_output_selects[chan]; +} + +static void ni660x_config_filter(struct comedi_device * dev, unsigned pfi_channel, + enum ni_gpct_filter_select filter) +{ + unsigned bits = ni_660x_read_register(dev, 0, IOConfigReg(pfi_channel)); + bits &= ~pfi_input_select_mask(pfi_channel); + bits |= pfi_input_select_bits(pfi_channel, filter); + ni_660x_write_register(dev, 0, bits, IOConfigReg(pfi_channel)); +} + +static int ni_660x_dio_insn_config(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + + /* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ + + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + private(dev)->pfi_direction_bits |= ((uint64_t) 1) << chan; + ni_660x_select_pfi_output(dev, chan, + private(dev)->pfi_output_selects[chan]); + break; + case INSN_CONFIG_DIO_INPUT: + private(dev)->pfi_direction_bits &= ~(((uint64_t) 1) << chan); + ni_660x_select_pfi_output(dev, chan, pfi_output_select_high_Z); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (private(dev)-> + pfi_direction_bits & (((uint64_t) 1) << chan)) ? + COMEDI_OUTPUT : COMEDI_INPUT; + return 0; + case INSN_CONFIG_SET_ROUTING: + return ni_660x_set_pfi_routing(dev, chan, data[1]); + break; + case INSN_CONFIG_GET_ROUTING: + data[1] = ni_660x_get_pfi_routing(dev, chan); + break; + case INSN_CONFIG_FILTER: + ni660x_config_filter(dev, chan, data[1]); + break; + default: + return -EINVAL; + break; + }; + return 0; +} diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c new file mode 100644 index 000000000000..d1312e073a65 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -0,0 +1,337 @@ +/* + comedi/drivers/ni_670x.c + Hardware driver for NI 670x devices + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-2001 David A. Schleef + + 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: ni_670x +Description: National Instruments 670x +Author: Bart Joris +Updated: Wed, 11 Dec 2002 18:25:35 -0800 +Devices: [National Instruments] PCI-6703 (ni_670x), PCI-6704 +Status: unknown + +Commands are not supported. +*/ + +/* + Bart Joris Last updated on 20/08/2001 + + Manuals: + + 322110a.pdf PCI/PXI-6704 User Manual + 322110b.pdf PCI/PXI-6703/6704 User Manual + +*/ + +#include "../comedidev.h" + +#include "mite.h" + +#define PCI_VENDOR_ID_NATINST 0x1093 + +#define AO_VALUE_OFFSET 0x00 +#define AO_CHAN_OFFSET 0x0c +#define AO_STATUS_OFFSET 0x10 +#define AO_CONTROL_OFFSET 0x10 +#define DIO_PORT0_DIR_OFFSET 0x20 +#define DIO_PORT0_DATA_OFFSET 0x24 +#define DIO_PORT1_DIR_OFFSET 0x28 +#define DIO_PORT1_DATA_OFFSET 0x2c +#define MISC_STATUS_OFFSET 0x14 +#define MISC_CONTROL_OFFSET 0x14 + +/* Board description*/ + +struct ni_670x_board { + unsigned short dev_id; + const char *name; + unsigned short ao_chans; + unsigned short ao_bits; +}; + +static const struct ni_670x_board ni_670x_boards[] = { + { + dev_id: 0x2c90, + name: "PCI-6703", + ao_chans:16, + ao_bits: 16, + }, + { + dev_id: 0x1920, + name: "PXI-6704", + ao_chans:32, + ao_bits: 16, + }, + { + dev_id: 0x1290, + name: "PCI-6704", + ao_chans:32, + ao_bits: 16, + }, +}; + +static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = { + {PCI_VENDOR_ID_NATINST, 0x2c90, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + //{ PCI_VENDOR_ID_NATINST, 0x0000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + {0} +}; + +MODULE_DEVICE_TABLE(pci, ni_670x_pci_table); + +#define thisboard ((struct ni_670x_board *)dev->board_ptr) + +struct ni_670x_private { + + struct mite_struct *mite; + int boardtype; + int dio; + unsigned int ao_readback[32]; +}; + + +#define devpriv ((struct ni_670x_private *)dev->private) +#define n_ni_670x_boards (sizeof(ni_670x_boards)/sizeof(ni_670x_boards[0])) + +static int ni_670x_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int ni_670x_detach(struct comedi_device * dev); + +static struct comedi_driver driver_ni_670x = { + driver_name:"ni_670x", + module:THIS_MODULE, + attach:ni_670x_attach, + detach:ni_670x_detach, +}; + +COMEDI_PCI_INITCLEANUP(driver_ni_670x, ni_670x_pci_table); + +static struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; + +static int ni_670x_find_device(struct comedi_device * dev, int bus, int slot); + +static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int ni_670x_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int ret; + int i; + + printk("comedi%d: ni_670x: ", dev->minor); + + if ((ret = alloc_private(dev, sizeof(struct ni_670x_private))) < 0) + return ret; + + ret = ni_670x_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; + + ret = mite_setup(devpriv->mite); + if (ret < 0) { + printk("error setting up mite\n"); + return ret; + } + dev->board_name = thisboard->name; + dev->irq = mite_irq(devpriv->mite); + printk(" %s", dev->board_name); + + if (alloc_subdevices(dev, 2) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->ao_chans; + s->maxdata = 0xffff; + if (s->n_chan == 32) { + const struct comedi_lrange **range_table_list; + + range_table_list = kmalloc(sizeof(struct comedi_lrange *) * 32, + GFP_KERNEL); + if (!range_table_list) + return -ENOMEM; + s->range_table_list = range_table_list; + for (i = 0; i < 16; i++) { + range_table_list[i] = &range_bipolar10; + range_table_list[16 + i] = &range_0_20mA; + } + } else { + s->range_table = &range_bipolar10; + } + s->insn_write = &ni_670x_ao_winsn; + s->insn_read = &ni_670x_ao_rinsn; + + s = dev->subdevices + 1; + /* digital i/o subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ni_670x_dio_insn_bits; + s->insn_config = ni_670x_dio_insn_config; + + writel(0x10, devpriv->mite->daq_io_addr + MISC_CONTROL_OFFSET); /* Config of misc registers */ + writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET); /* Config of ao registers */ + + printk("attached\n"); + + return 1; +} + +static int ni_670x_detach(struct comedi_device * dev) +{ + printk("comedi%d: ni_670x: remove\n", dev->minor); + + if (dev->subdevices[0].range_table_list) { + kfree(dev->subdevices[0].range_table_list); + } + if (dev->private && devpriv->mite) + mite_unsetup(devpriv->mite); + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + return 0; +} + +static int ni_670x_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + /* Channel number mapping : + + NI 6703/ NI 6704 | NI 6704 Only + ---------------------------------------------------- + vch(0) : 0 | ich(16) : 1 + vch(1) : 2 | ich(17) : 3 + . : . | . . + . : . | . . + . : . | . . + vch(15) : 30 | ich(31) : 31 */ + + for (i = 0; i < insn->n; i++) { + writel(((chan & 15) << 1) | ((chan & 16) >> 4), devpriv->mite->daq_io_addr + AO_CHAN_OFFSET); /* First write in channel register which channel to use */ + writel(data[i], devpriv->mite->daq_io_addr + AO_VALUE_OFFSET); /* write channel value */ + devpriv->ao_readback[chan] = data[i]; + } + + return i; +} + +static int ni_670x_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +static int ni_670x_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + writel(s->state, + devpriv->mite->daq_io_addr + DIO_PORT0_DATA_OFFSET); + } + + /* on return, data[1] contains the value of the digital + * input lines. */ + data[1] = readl(devpriv->mite->daq_io_addr + DIO_PORT0_DATA_OFFSET); + + return 2; +} + +static int ni_670x_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= 1 << chan; + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~(1 << chan); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s-> + io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + break; + } + writel(s->io_bits, devpriv->mite->daq_io_addr + DIO_PORT0_DIR_OFFSET); + + return insn->n; +} + +static int ni_670x_find_device(struct comedi_device * dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number + || slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + + for (i = 0; i < n_ni_670x_boards; i++) { + if (mite_device_id(mite) == ni_670x_boards[i].dev_id) { + dev->board_ptr = ni_670x_boards + i; + devpriv->mite = mite; + + return 0; + } + } + } + printk("no device found\n"); + mite_list_devices(); + return -EIO; +} diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c new file mode 100644 index 000000000000..5d45bf24a5ef --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -0,0 +1,909 @@ +/* + comedi/drivers/ni_at_a2150.c + Driver for National Instruments AT-A2150 boards + Copyright (C) 2001, 2002 Frank Mori Hess + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: ni_at_a2150 +Description: National Instruments AT-A2150 +Author: Frank Mori Hess +Status: works +Devices: [National Instruments] AT-A2150C (at_a2150c), AT-2150S (at_a2150s) + +If you want to ac couple the board's inputs, use AREF_OTHER. + +Configuration options: + [0] - I/O port base address + [1] - IRQ (optional, required for timed conversions) + [2] - DMA (optional, required for timed conversions) + +*/ +/* +Yet another driver for obsolete hardware brought to you by Frank Hess. +Testing and debugging help provided by Dave Andruczyk. + +This driver supports the boards: + +AT-A2150C +AT-A2150S + +The only difference is their master clock frequencies. + +Options: + [0] - base io address + [1] - irq + [2] - dma channel + +References (from ftp://ftp.natinst.com/support/manuals): + + 320360.pdf AT-A2150 User Manual + +TODO: + +analog level triggering +TRIG_WAKE_EOS + +*/ + +#include "../comedidev.h" + +#include +#include + +#include "8253.h" +#include "comedi_fc.h" + +#define A2150_SIZE 28 +#define A2150_DMA_BUFFER_SIZE 0xff00 // size in bytes of dma buffer + +//#define A2150_DEBUG // enable debugging code +#undef A2150_DEBUG // disable debugging code + +/* Registers and bits */ +#define CONFIG_REG 0x0 +#define CHANNEL_BITS(x) ((x) & 0x7) +#define CHANNEL_MASK 0x7 +#define CLOCK_SELECT_BITS(x) (((x) & 0x3) << 3) +#define CLOCK_DIVISOR_BITS(x) (((x) & 0x3) << 5) +#define CLOCK_MASK (0xf << 3) +#define ENABLE0_BIT 0x80 // enable (don't internally ground) channels 0 and 1 +#define ENABLE1_BIT 0x100 // enable (don't internally ground) channels 2 and 3 +#define AC0_BIT 0x200 // ac couple channels 0,1 +#define AC1_BIT 0x400 // ac couple channels 2,3 +#define APD_BIT 0x800 // analog power down +#define DPD_BIT 0x1000 // digital power down +#define TRIGGER_REG 0x2 // trigger config register +#define POST_TRIGGER_BITS 0x2 +#define DELAY_TRIGGER_BITS 0x3 +#define HW_TRIG_EN 0x10 // enable hardware trigger +#define FIFO_START_REG 0x6 // software start aquistion trigger +#define FIFO_RESET_REG 0x8 // clears fifo + fifo flags +#define FIFO_DATA_REG 0xa // read data +#define DMA_TC_CLEAR_REG 0xe // clear dma terminal count interrupt +#define STATUS_REG 0x12 // read only +#define FNE_BIT 0x1 // fifo not empty +#define OVFL_BIT 0x8 // fifo overflow +#define EDAQ_BIT 0x10 // end of aquisition interrupt +#define DCAL_BIT 0x20 // offset calibration in progress +#define INTR_BIT 0x40 // interrupt has occured +#define DMA_TC_BIT 0x80 // dma terminal count interrupt has occured +#define ID_BITS(x) (((x) >> 8) & 0x3) +#define IRQ_DMA_CNTRL_REG 0x12 // write only +#define DMA_CHAN_BITS(x) ((x) & 0x7) // sets dma channel +#define DMA_EN_BIT 0x8 // enables dma +#define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) // sets irq level +#define FIFO_INTR_EN_BIT 0x100 // enable fifo interrupts +#define FIFO_INTR_FHF_BIT 0x200 // interrupt fifo half full +#define DMA_INTR_EN_BIT 0x800 // enable interrupt on dma terminal count +#define DMA_DEM_EN_BIT 0x1000 // enables demand mode dma +#define I8253_BASE_REG 0x14 +#define I8253_MODE_REG 0x17 +#define HW_COUNT_DISABLE 0x30 // disable hardware counting of conversions + +struct a2150_board { + const char *name; + int clock[4]; // master clock periods, in nanoseconds + int num_clocks; // number of available master clock speeds + int ai_speed; // maximum conversion rate in nanoseconds +}; + +//analog input range +static const struct comedi_lrange range_a2150 = { + 1, + { + RANGE(-2.828, 2.828), + } +}; + +// enum must match board indices +enum { a2150_c, a2150_s }; +static const struct a2150_board a2150_boards[] = { + { + name: "at-a2150c", + clock: {31250, 22676, 20833, 19531}, + num_clocks:4, + ai_speed:19531, + }, + { + name: "at-a2150s", + clock: {62500, 50000, 41667, 0}, + num_clocks:3, + ai_speed:41667, + }, +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct a2150_board *)dev->board_ptr) + +struct a2150_private { + + volatile unsigned int count; /* number of data points left to be taken */ + unsigned int dma; // dma channel + s16 *dma_buffer; // dma buffer + unsigned int dma_transfer_size; // size in bytes of dma transfers + int irq_dma_bits; // irq/dma register bits + int config_bits; // config register bits +}; + + +#define devpriv ((struct a2150_private *)dev->private) + +static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int a2150_detach(struct comedi_device * dev); +static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s); + +static struct comedi_driver driver_a2150 = { + driver_name:"ni_at_a2150", + module:THIS_MODULE, + attach:a2150_attach, + detach:a2150_detach, +}; + +static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG); +static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int a2150_get_timing(struct comedi_device * dev, unsigned int *period, + int flags); +static int a2150_probe(struct comedi_device * dev); +static int a2150_set_chanlist(struct comedi_device * dev, unsigned int start_channel, + unsigned int num_channels); +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver_a2150); + +#ifdef A2150_DEBUG + +static void ni_dump_regs(struct comedi_device * dev) +{ + rt_printk("config bits 0x%x\n", devpriv->config_bits); + rt_printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits); + rt_printk("status bits 0x%x\n", inw(dev->iobase + STATUS_REG)); +} + +#endif + +/* interrupt service routine */ +static irqreturn_t a2150_interrupt(int irq, void *d PT_REGS_ARG) +{ + int i; + int status; + unsigned long flags; + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async; + struct comedi_cmd *cmd; + unsigned int max_points, num_points, residue, leftover; + short dpnt; + static const int sample_size = sizeof(devpriv->dma_buffer[0]); + + if (dev->attached == 0) { + comedi_error(dev, "premature interrupt"); + return IRQ_HANDLED; + } + // initialize async here to make sure s is not NULL + async = s->async; + async->events = 0; + cmd = &async->cmd; + + status = inw(dev->iobase + STATUS_REG); + + if ((status & INTR_BIT) == 0) { + comedi_error(dev, "spurious interrupt"); + return IRQ_NONE; + } + + if (status & OVFL_BIT) { + comedi_error(dev, "fifo overflow"); + a2150_cancel(dev, s); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + } + + if ((status & DMA_TC_BIT) == 0) { + comedi_error(dev, "caught non-dma interrupt? Aborting."); + a2150_cancel(dev, s); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + comedi_event(dev, s); + return IRQ_HANDLED; + } + + flags = claim_dma_lock(); + disable_dma(devpriv->dma); + /* clear flip-flop to make sure 2-byte registers for + * count and address get set correctly */ + clear_dma_ff(devpriv->dma); + + // figure out how many points to read + max_points = devpriv->dma_transfer_size / sample_size; + /* residue is the number of points left to be done on the dma + * transfer. It should always be zero at this point unless + * the stop_src is set to external triggering. + */ + residue = get_dma_residue(devpriv->dma) / sample_size; + num_points = max_points - residue; + if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT) + num_points = devpriv->count; + + // figure out how many points will be stored next time + leftover = 0; + if (cmd->stop_src == TRIG_NONE) { + leftover = devpriv->dma_transfer_size / sample_size; + } else if (devpriv->count > max_points) { + leftover = devpriv->count - max_points; + if (leftover > max_points) + leftover = max_points; + } + /* there should only be a residue if collection was stopped by having + * the stop_src set to an external trigger, in which case there + * will be no more data + */ + if (residue) + leftover = 0; + + for (i = 0; i < num_points; i++) { + /* write data point to comedi buffer */ + dpnt = devpriv->dma_buffer[i]; + // convert from 2's complement to unsigned coding + dpnt ^= 0x8000; + cfc_write_to_buffer(s, dpnt); + if (cmd->stop_src == TRIG_COUNT) { + if (--devpriv->count == 0) { /* end of acquisition */ + a2150_cancel(dev, s); + async->events |= COMEDI_CB_EOA; + break; + } + } + } + // re-enable dma + if (leftover) { + set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer)); + set_dma_count(devpriv->dma, leftover * sample_size); + enable_dma(devpriv->dma); + } + release_dma_lock(flags); + + async->events |= COMEDI_CB_BLOCK; + + comedi_event(dev, s); + + /* clear interrupt */ + outw(0x00, dev->iobase + DMA_TC_CLEAR_REG); + + return IRQ_HANDLED; +} + +// probes board type, returns offset +static int a2150_probe(struct comedi_device * dev) +{ + int status = inw(dev->iobase + STATUS_REG); + return ID_BITS(status); +} + +static int a2150_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase = it->options[0]; + unsigned int irq = it->options[1]; + unsigned int dma = it->options[2]; + static const int timeout = 2000; + int i; + + printk("comedi%d: %s: io 0x%lx", dev->minor, driver_a2150.driver_name, + iobase); + if (irq) { + printk(", irq %u", irq); + } else { + printk(", no irq"); + } + if (dma) { + printk(", dma %u", dma); + } else { + printk(", no dma"); + } + printk("\n"); + + /* allocate and initialize dev->private */ + if (alloc_private(dev, sizeof(struct a2150_private)) < 0) + return -ENOMEM; + + if (iobase == 0) { + printk(" io base address required\n"); + return -EINVAL; + } + + /* check if io addresses are available */ + if (!request_region(iobase, A2150_SIZE, driver_a2150.driver_name)) { + printk(" I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + /* grab our IRQ */ + if (irq) { + // check that irq is supported + if (irq < 3 || irq == 8 || irq == 13 || irq > 15) { + printk(" invalid irq line %u\n", irq); + return -EINVAL; + } + if (comedi_request_irq(irq, a2150_interrupt, 0, + driver_a2150.driver_name, dev)) { + printk("unable to allocate irq %u\n", irq); + return -EINVAL; + } + devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq); + dev->irq = irq; + } + // initialize dma + if (dma) { + if (dma == 4 || dma > 7) { + printk(" invalid dma channel %u\n", dma); + return -EINVAL; + } + if (request_dma(dma, driver_a2150.driver_name)) { + printk(" failed to allocate dma channel %u\n", dma); + return -EINVAL; + } + devpriv->dma = dma; + devpriv->dma_buffer = + kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA); + if (devpriv->dma_buffer == NULL) + return -ENOMEM; + + disable_dma(dma); + set_dma_mode(dma, DMA_MODE_READ); + + devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma); + } + + dev->board_ptr = a2150_boards + a2150_probe(dev); + dev->board_name = thisboard->name; + + if (alloc_subdevices(dev, 1) < 0) + return -ENOMEM; + + /* analog input subdevice */ + s = dev->subdevices + 0; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ; + s->n_chan = 4; + s->len_chanlist = 4; + s->maxdata = 0xffff; + s->range_table = &range_a2150; + s->do_cmd = a2150_ai_cmd; + s->do_cmdtest = a2150_ai_cmdtest; + s->insn_read = a2150_ai_rinsn; + s->cancel = a2150_cancel; + + /* need to do this for software counting of completed conversions, to + * prevent hardware count from stopping aquisition */ + outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG); + + // set card's irq and dma levels + outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); + + // reset and sync adc clock circuitry + outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG); + outw_p(DPD_BIT, dev->iobase + CONFIG_REG); + // initialize configuration register + devpriv->config_bits = 0; + outw(devpriv->config_bits, dev->iobase + CONFIG_REG); + // wait until offset calibration is done, then enable analog inputs + for (i = 0; i < timeout; i++) { + if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0) + break; + comedi_udelay(1000); + } + if (i == timeout) { + printk(" timed out waiting for offset calibration to complete\n"); + return -ETIME; + } + devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT; + outw(devpriv->config_bits, dev->iobase + CONFIG_REG); + + return 0; +}; + +static int a2150_detach(struct comedi_device * dev) +{ + printk("comedi%d: %s: remove\n", dev->minor, driver_a2150.driver_name); + + /* only free stuff if it has been allocated by _attach */ + if (dev->iobase) { + // put board in power-down mode + outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG); + release_region(dev->iobase, A2150_SIZE); + } + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (devpriv) { + if (devpriv->dma) + free_dma(devpriv->dma); + if (devpriv->dma_buffer) + kfree(devpriv->dma_buffer); + } + + return 0; +}; + +static int a2150_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + // disable dma on card + devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT; + outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); + + // disable computer's dma + disable_dma(devpriv->dma); + + // clear fifo and reset triggering circuitry + outw(0, dev->iobase + FIFO_RESET_REG); + + return 0; +} + +static int a2150_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + int startChan; + int i; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < thisboard->ai_speed) { + cmd->convert_arg = thisboard->ai_speed; + err++; + } + } + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + } else { /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags); + if (tmp != cmd->scan_begin_arg) + err++; + } + + if (err) + return 4; + + // check channel/gain list against card's limitations + if (cmd->chanlist) { + startChan = CR_CHAN(cmd->chanlist[0]); + for (i = 1; i < cmd->chanlist_len; i++) { + if (CR_CHAN(cmd->chanlist[i]) != (startChan + i)) { + comedi_error(dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); + err++; + } + } + if (cmd->chanlist_len == 2 && CR_CHAN(cmd->chanlist[0]) == 1) { + comedi_error(dev, + "length 2 chanlist must be channels 0,1 or channels 2,3"); + err++; + } + if (cmd->chanlist_len == 3) { + comedi_error(dev, + "chanlist must have 1,2 or 4 channels"); + err++; + } + if (CR_AREF(cmd->chanlist[0]) != CR_AREF(cmd->chanlist[1]) || + CR_AREF(cmd->chanlist[2]) != CR_AREF(cmd->chanlist[3])) + { + comedi_error(dev, + "channels 0/1 and 2/3 must have the same analog reference"); + err++; + } + } + + if (err) + return 5; + + return 0; +} + +static int a2150_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned long lock_flags; + unsigned int old_config_bits = devpriv->config_bits; + unsigned int trigger_bits; + + if (!dev->irq || !devpriv->dma) { + comedi_error(dev, + " irq and dma required, cannot do hardware conversions"); + return -1; + } + if (cmd->flags & TRIG_RT) { + comedi_error(dev, + " dma incompatible with hard real-time interrupt (TRIG_RT), aborting"); + return -1; + } + // clear fifo and reset triggering circuitry + outw(0, dev->iobase + FIFO_RESET_REG); + + /* setup chanlist */ + if (a2150_set_chanlist(dev, CR_CHAN(cmd->chanlist[0]), + cmd->chanlist_len) < 0) + return -1; + + // setup ac/dc coupling + if (CR_AREF(cmd->chanlist[0]) == AREF_OTHER) + devpriv->config_bits |= AC0_BIT; + else + devpriv->config_bits &= ~AC0_BIT; + if (CR_AREF(cmd->chanlist[2]) == AREF_OTHER) + devpriv->config_bits |= AC1_BIT; + else + devpriv->config_bits &= ~AC1_BIT; + + // setup timing + a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags); + + // send timing, channel, config bits + outw(devpriv->config_bits, dev->iobase + CONFIG_REG); + + // initialize number of samples remaining + devpriv->count = cmd->stop_arg * cmd->chanlist_len; + + // enable computer's dma + lock_flags = claim_dma_lock(); + disable_dma(devpriv->dma); + /* clear flip-flop to make sure 2-byte registers for + * count and address get set correctly */ + clear_dma_ff(devpriv->dma); + set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer)); + // set size of transfer to fill in 1/3 second +#define ONE_THIRD_SECOND 333333333 + devpriv->dma_transfer_size = + sizeof(devpriv->dma_buffer[0]) * cmd->chanlist_len * + ONE_THIRD_SECOND / cmd->scan_begin_arg; + if (devpriv->dma_transfer_size > A2150_DMA_BUFFER_SIZE) + devpriv->dma_transfer_size = A2150_DMA_BUFFER_SIZE; + if (devpriv->dma_transfer_size < sizeof(devpriv->dma_buffer[0])) + devpriv->dma_transfer_size = sizeof(devpriv->dma_buffer[0]); + devpriv->dma_transfer_size -= + devpriv->dma_transfer_size % sizeof(devpriv->dma_buffer[0]); + set_dma_count(devpriv->dma, devpriv->dma_transfer_size); + enable_dma(devpriv->dma); + release_dma_lock(lock_flags); + + /* clear dma interrupt before enabling it, to try and get rid of that + * one spurious interrupt that has been happening */ + outw(0x00, dev->iobase + DMA_TC_CLEAR_REG); + + // enable dma on card + devpriv->irq_dma_bits |= DMA_INTR_EN_BIT | DMA_EN_BIT; + outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); + + // may need to wait 72 sampling periods if timing was changed + i8254_load(dev->iobase + I8253_BASE_REG, 0, 2, 72, 0); + + // setup start triggering + trigger_bits = 0; + // decide if we need to wait 72 periods for valid data + if (cmd->start_src == TRIG_NOW && + (old_config_bits & CLOCK_MASK) != + (devpriv->config_bits & CLOCK_MASK)) { + // set trigger source to delay trigger + trigger_bits |= DELAY_TRIGGER_BITS; + } else { + // otherwise no delay + trigger_bits |= POST_TRIGGER_BITS; + } + // enable external hardware trigger + if (cmd->start_src == TRIG_EXT) { + trigger_bits |= HW_TRIG_EN; + } else if (cmd->start_src == TRIG_OTHER) { + // XXX add support for level/slope start trigger using TRIG_OTHER + comedi_error(dev, "you shouldn't see this?"); + } + // send trigger config bits + outw(trigger_bits, dev->iobase + TRIGGER_REG); + + // start aquisition for soft trigger + if (cmd->start_src == TRIG_NOW) { + outw(0, dev->iobase + FIFO_START_REG); + } +#ifdef A2150_DEBUG + ni_dump_regs(dev); +#endif + + return 0; +} + +static int a2150_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int i, n; + static const int timeout = 100000; + static const int filter_delay = 36; + + // clear fifo and reset triggering circuitry + outw(0, dev->iobase + FIFO_RESET_REG); + + /* setup chanlist */ + if (a2150_set_chanlist(dev, CR_CHAN(insn->chanspec), 1) < 0) + return -1; + + // set dc coupling + devpriv->config_bits &= ~AC0_BIT; + devpriv->config_bits &= ~AC1_BIT; + + // send timing, channel, config bits + outw(devpriv->config_bits, dev->iobase + CONFIG_REG); + + // disable dma on card + devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT; + outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); + + // setup start triggering + outw(0, dev->iobase + TRIGGER_REG); + + // start aquisition for soft trigger + outw(0, dev->iobase + FIFO_START_REG); + + /* there is a 35.6 sample delay for data to get through the antialias filter */ + for (n = 0; n < filter_delay; n++) { + for (i = 0; i < timeout; i++) { + if (inw(dev->iobase + STATUS_REG) & FNE_BIT) + break; + comedi_udelay(1); + } + if (i == timeout) { + comedi_error(dev, "timeout"); + return -ETIME; + } + inw(dev->iobase + FIFO_DATA_REG); + } + + // read data + for (n = 0; n < insn->n; n++) { + for (i = 0; i < timeout; i++) { + if (inw(dev->iobase + STATUS_REG) & FNE_BIT) + break; + comedi_udelay(1); + } + if (i == timeout) { + comedi_error(dev, "timeout"); + return -ETIME; + } +#ifdef A2150_DEBUG + ni_dump_regs(dev); +#endif + data[n] = inw(dev->iobase + FIFO_DATA_REG); +#ifdef A2150_DEBUG + rt_printk(" data is %i\n", data[n]); +#endif + data[n] ^= 0x8000; + } + + // clear fifo and reset triggering circuitry + outw(0, dev->iobase + FIFO_RESET_REG); + + return n; +} + +/* sets bits in devpriv->clock_bits to nearest approximation of requested period, + * adjusts requested period to actual timing. */ +static int a2150_get_timing(struct comedi_device * dev, unsigned int *period, + int flags) +{ + int lub, glb, temp; + int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index; + int i, j; + + // initialize greatest lower and least upper bounds + lub_divisor_shift = 3; + lub_index = 0; + lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift); + glb_divisor_shift = 0; + glb_index = thisboard->num_clocks - 1; + glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift); + + // make sure period is in available range + if (*period < glb) + *period = glb; + if (*period > lub) + *period = lub; + + // we can multiply period by 1, 2, 4, or 8, using (1 << i) + for (i = 0; i < 4; i++) { + // there are a maximum of 4 master clocks + for (j = 0; j < thisboard->num_clocks; j++) { + // temp is the period in nanosec we are evaluating + temp = thisboard->clock[j] * (1 << i); + // if it is the best match yet + if (temp < lub && temp >= *period) { + lub_divisor_shift = i; + lub_index = j; + lub = temp; + } + if (temp > glb && temp <= *period) { + glb_divisor_shift = i; + glb_index = j; + glb = temp; + } + } + } + flags &= TRIG_ROUND_MASK; + switch (flags) { + case TRIG_ROUND_NEAREST: + default: + // if least upper bound is better approximation + if (lub - *period < *period - glb) { + *period = lub; + } else { + *period = glb; + } + break; + case TRIG_ROUND_UP: + *period = lub; + break; + case TRIG_ROUND_DOWN: + *period = glb; + break; + } + + // set clock bits for config register appropriately + devpriv->config_bits &= ~CLOCK_MASK; + if (*period == lub) { + devpriv->config_bits |= + CLOCK_SELECT_BITS(lub_index) | + CLOCK_DIVISOR_BITS(lub_divisor_shift); + } else { + devpriv->config_bits |= + CLOCK_SELECT_BITS(glb_index) | + CLOCK_DIVISOR_BITS(glb_divisor_shift); + } + + return 0; +} + +static int a2150_set_chanlist(struct comedi_device * dev, unsigned int start_channel, + unsigned int num_channels) +{ + if (start_channel + num_channels > 4) + return -1; + + devpriv->config_bits &= ~CHANNEL_MASK; + + switch (num_channels) { + case 1: + devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel); + break; + case 2: + if (start_channel == 0) { + devpriv->config_bits |= CHANNEL_BITS(0x2); + } else if (start_channel == 2) { + devpriv->config_bits |= CHANNEL_BITS(0x3); + } else { + return -1; + } + break; + case 4: + devpriv->config_bits |= CHANNEL_BITS(0x1); + break; + default: + return -1; + break; + } + + return 0; +} diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c new file mode 100644 index 000000000000..2cc46b672588 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -0,0 +1,454 @@ +/* + comedi/drivers/ni_at_ao.c + Driver for NI AT-AO-6/10 boards + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000,2002 David A. Schleef + + 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: ni_at_ao +Description: National Instruments AT-AO-6/10 +Devices: [National Instruments] AT-AO-6 (at-ao-6), AT-AO-10 (at-ao-10) +Status: should work +Author: ds +Updated: Sun Dec 26 12:26:28 EST 2004 + +Configuration options: + [0] - I/O port base address + [1] - IRQ (unused) + [2] - DMA (unused) + [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V bipolar, 1 for 0V to 10V unipolar) + +*/ +/* + * Register-level programming information can be found in NI + * document 320379.pdf. + */ + +#include "../comedidev.h" + +#include + +/* board egisters */ +/* registers with _2_ are accessed when GRP2WR is set in CFG1 */ + +#define ATAO_SIZE 0x20 + +#define ATAO_2_DMATCCLR 0x00 /* W 16 */ +#define ATAO_DIN 0x00 /* R 16 */ +#define ATAO_DOUT 0x00 /* W 16 */ + +#define ATAO_CFG2 0x02 /* W 16 */ +#define CALLD1 0x8000 +#define CALLD0 0x4000 +#define FFRTEN 0x2000 +#define DAC2S8 0x1000 +#define DAC2S6 0x0800 +#define DAC2S4 0x0400 +#define DAC2S2 0x0200 +#define DAC2S0 0x0100 +#define LDAC8 0x0080 +#define LDAC6 0x0040 +#define LDAC4 0x0020 +#define LDAC2 0x0010 +#define LDAC0 0x0008 +#define PROMEN 0x0004 +#define SCLK 0x0002 +#define SDATA 0x0001 + +#define ATAO_2_INT1CLR 0x02 /* W 16 */ + +#define ATAO_CFG3 0x04 /* W 16 */ +#define DMAMODE 0x0040 +#define CLKOUT 0x0020 +#define RCLKEN 0x0010 +#define DOUTEN2 0x0008 +#define DOUTEN1 0x0004 +#define EN2_5V 0x0002 +#define SCANEN 0x0001 + +#define ATAO_2_INT2CLR 0x04 /* W 16 */ + +#define ATAO_82C53_BASE 0x06 /* RW 8 */ + +#define ATAO_82C53_CNTR1 0x06 /* RW 8 */ +#define ATAO_82C53_CNTR2 0x07 /* RW 8 */ +#define ATAO_82C53_CNTR3 0x08 /* RW 8 */ +#define ATAO_82C53_CNTRCMD 0x09 /* W 8 */ +#define CNTRSEL1 0x80 +#define CNTRSEL0 0x40 +#define RWSEL1 0x20 +#define RWSEL0 0x10 +#define MODESEL2 0x08 +#define MODESEL1 0x04 +#define MODESEL0 0x02 +#define BCDSEL 0x01 + /* read-back command */ +#define COUNT 0x20 +#define STATUS 0x10 +#define CNTR3 0x08 +#define CNTR2 0x04 +#define CNTR1 0x02 + /* status */ +#define OUT 0x80 +#define _NULL 0x40 +#define RW1 0x20 +#define RW0 0x10 +#define MODE2 0x08 +#define MODE1 0x04 +#define MODE0 0x02 +#define BCD 0x01 + +#define ATAO_2_RTSISHFT 0x06 /* W 8 */ +#define RSI 0x01 + +#define ATAO_2_RTSISTRB 0x07 /* W 8 */ + +#define ATAO_CFG1 0x0a /* W 16 */ +#define EXTINT2EN 0x8000 +#define EXTINT1EN 0x4000 +#define CNTINT2EN 0x2000 +#define CNTINT1EN 0x1000 +#define TCINTEN 0x0800 +#define CNT1SRC 0x0400 +#define CNT2SRC 0x0200 +#define FIFOEN 0x0100 +#define GRP2WR 0x0080 +#define EXTUPDEN 0x0040 +#define DMARQ 0x0020 +#define DMAEN 0x0010 +#define CH_mask 0x000f +#define ATAO_STATUS 0x0a /* R 16 */ +#define FH 0x0040 +#define FE 0x0020 +#define FF 0x0010 +#define INT2 0x0008 +#define INT1 0x0004 +#define TCINT 0x0002 +#define PROMOUT 0x0001 + +#define ATAO_FIFO_WRITE 0x0c /* W 16 */ +#define ATAO_FIFO_CLEAR 0x0c /* R 16 */ +#define ATAO_DACn(x) (0x0c + 2*(x)) /* W */ + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct atao_board { + const char *name; + int n_ao_chans; +}; + +static const struct atao_board atao_boards[] = { + { + name: "ai-ao-6", + n_ao_chans:6, + }, + { + name: "ai-ao-10", + n_ao_chans:10, + }, +}; + +#define thisboard ((struct atao_board *)dev->board_ptr) + +struct atao_private { + + unsigned short cfg1; + unsigned short cfg2; + unsigned short cfg3; + + /* Used for AO readback */ + unsigned int ao_readback[10]; +}; + +#define devpriv ((struct atao_private *)dev->private) + +static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int atao_detach(struct comedi_device * dev); +static struct comedi_driver driver_atao = { + driver_name:"ni_at_ao", + module:THIS_MODULE, + attach:atao_attach, + detach:atao_detach, + board_name:&atao_boards[0].name, + offset:sizeof(struct atao_board), + num_names:sizeof(atao_boards) / sizeof(struct atao_board), +}; + +COMEDI_INITCLEANUP(driver_atao); + +static void atao_reset(struct comedi_device * dev); + +static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + int ao_unipolar; + + iobase = it->options[0]; + if (iobase == 0) + iobase = 0x1c0; + ao_unipolar = it->options[3]; + + printk("comedi%d: ni_at_ao: 0x%04lx", dev->minor, iobase); + + if (!request_region(iobase, ATAO_SIZE, "ni_at_ao")) { + printk(" I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + //dev->board_ptr = atao_probe(dev); + + dev->board_name = thisboard->name; + + if (alloc_private(dev, sizeof(struct atao_private)) < 0) + return -ENOMEM; + + if (alloc_subdevices(dev, 4) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = thisboard->n_ao_chans; + s->maxdata = (1 << 12) - 1; + if (ao_unipolar) + s->range_table = &range_unipolar10; + else + s->range_table = &range_bipolar10; + s->insn_write = &atao_ao_winsn; + s->insn_read = &atao_ao_rinsn; + + s = dev->subdevices + 1; + /* digital i/o subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = atao_dio_insn_bits; + s->insn_config = atao_dio_insn_config; + + s = dev->subdevices + 2; + /* caldac subdevice */ + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 21; + s->maxdata = 0xff; + s->insn_read = atao_calib_insn_read; + s->insn_write = atao_calib_insn_write; + + s = dev->subdevices + 3; + /* eeprom subdevice */ + //s->type=COMEDI_SUBD_EEPROM; + s->type = COMEDI_SUBD_UNUSED; + + atao_reset(dev); + + printk("\n"); + + return 0; +} + +static int atao_detach(struct comedi_device * dev) +{ + printk("comedi%d: atao: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, ATAO_SIZE); + + return 0; +} + +static void atao_reset(struct comedi_device * dev) +{ + /* This is the reset sequence described in the manual */ + + devpriv->cfg1 = 0; + outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); + + outb(RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD); + outb(0x03, dev->iobase + ATAO_82C53_CNTR1); + outb(CNTRSEL0 | RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD); + + devpriv->cfg2 = 0; + outw(devpriv->cfg2, dev->iobase + ATAO_CFG2); + + devpriv->cfg3 = 0; + outw(devpriv->cfg3, dev->iobase + ATAO_CFG3); + + inw(dev->iobase + ATAO_FIFO_CLEAR); + + devpriv->cfg1 |= GRP2WR; + outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); + + outw(0, dev->iobase + ATAO_2_INT1CLR); + outw(0, dev->iobase + ATAO_2_INT2CLR); + outw(0, dev->iobase + ATAO_2_DMATCCLR); + + devpriv->cfg1 &= ~GRP2WR; + outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); +} + +static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + short bits; + + for (i = 0; i < insn->n; i++) { + bits = data[i] - 0x800; + if (chan == 0) { + devpriv->cfg1 |= GRP2WR; + outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); + } + outw(bits, dev->iobase + ATAO_DACn(chan)); + if (chan == 0) { + devpriv->cfg1 &= ~GRP2WR; + outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); + } + devpriv->ao_readback[chan] = data[i]; + } + + return i; +} + +static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +static int atao_dio_insn_bits(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]; + outw(s->state, dev->iobase + ATAO_DOUT); + } + + data[1] = inw(dev->iobase + ATAO_DIN); + + return 2; +} + +static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + unsigned int mask, bit; + + /* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ + + mask = (chan < 4) ? 0x0f : 0xf0; + bit = (chan < 4) ? DOUTEN1 : DOUTEN2; + + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= mask; + devpriv->cfg3 |= bit; + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~mask; + devpriv->cfg3 &= ~bit; + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s-> + io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + break; + } + + outw(devpriv->cfg3, dev->iobase + ATAO_CFG3); + + return 1; +} + +/* + * Figure 2-1 in the manual shows 3 chips labeled DAC8800, which + * are 8-channel 8-bit DACs. These are most likely the calibration + * DACs. It is not explicitly stated in the manual how to access + * the caldacs, but we can guess. + */ +static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + for (i = 0; i < insn->n; i++) { + data[i] = 0; /* XXX */ + } + return insn->n; +} + +static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int bitstring, bit; + unsigned int chan = CR_CHAN(insn->chanspec); + + bitstring = ((chan & 0x7) << 8) | (data[insn->n - 1] & 0xff); + + for (bit = 1 << (11 - 1); bit; bit >>= 1) { + outw(devpriv->cfg2 | ((bit & bitstring) ? SDATA : 0), + dev->iobase + ATAO_CFG2); + outw(devpriv->cfg2 | SCLK | ((bit & bitstring) ? SDATA : 0), + dev->iobase + ATAO_CFG2); + } + /* strobe the appropriate caldac */ + outw(devpriv->cfg2 | (((chan >> 3) + 1) << 14), + dev->iobase + ATAO_CFG2); + outw(devpriv->cfg2, dev->iobase + ATAO_CFG2); + + return insn->n; +} diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c new file mode 100644 index 000000000000..fcc38535afc5 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -0,0 +1,513 @@ +/* + comedi/drivers/ni_atmio.c + Hardware driver for NI AT-MIO E series cards + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-2001 David A. Schleef + + 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: ni_atmio +Description: National Instruments AT-MIO-E series +Author: ds +Devices: [National Instruments] AT-MIO-16E-1 (ni_atmio), + AT-MIO-16E-2, AT-MIO-16E-10, AT-MIO-16DE-10, AT-MIO-64E-3, + AT-MIO-16XE-50, AT-MIO-16XE-10, AT-AI-16XE-10 +Status: works +Updated: Thu May 1 20:03:02 CDT 2003 + +The driver has 2.6 kernel isapnp support, and +will automatically probe for a supported board if the +I/O base is left unspecified with comedi_config. +However, many of +the isapnp id numbers are unknown. If your board is not +recognized, please send the output of 'cat /proc/isapnp' +(you may need to modprobe the isa-pnp module for +/proc/isapnp to exist) so the +id numbers for your board can be added to the driver. + +Otherwise, you can use the isapnptools package to configure +your board. Use isapnp to +configure the I/O base and IRQ for the board, and then pass +the same values as +parameters in comedi_config. A sample isapnp.conf file is included +in the etc/ directory of Comedilib. + +Comedilib includes a utility to autocalibrate these boards. The +boards seem to boot into a state where the all calibration DACs +are at one extreme of their range, thus the default calibration +is terrible. Calibration at boot is strongly encouraged. + +To use the extended digital I/O on some of the boards, enable the +8255 driver when configuring the Comedi source tree. + +External triggering is supported for some events. The channel index +(scan_begin_arg, etc.) maps to PFI0 - PFI9. + +Some of the more esoteric triggering possibilities of these boards +are not supported. +*/ +/* + The real guts of the driver is in ni_mio_common.c, which is included + both here and in ni_pcimio.c + + Interrupt support added by Truxton Fulton + + References for specifications: + + 340747b.pdf Register Level Programmer Manual (obsolete) + 340747c.pdf Register Level Programmer Manual (new) + DAQ-STC reference manual + + Other possibly relevant info: + + 320517c.pdf User manual (obsolete) + 320517f.pdf User manual (new) + 320889a.pdf delete + 320906c.pdf maximum signal ratings + 321066a.pdf about 16x + 321791a.pdf discontinuation of at-mio-16e-10 rev. c + 321808a.pdf about at-mio-16e-10 rev P + 321837a.pdf discontinuation of at-mio-16de-10 rev d + 321838a.pdf about at-mio-16de-10 rev N + + ISSUES: + + need to deal with external reference for DAC, and other DAC + properties in board properties + + deal with at-mio-16de-10 revision D to N changes, etc. + +*/ + +#include "../comedidev.h" + +#include +#include + +#include "ni_stc.h" +#include "8255.h" + +#undef DEBUG + +#define ATMIO 1 +#undef PCIMIO + +/* + * AT specific setup + */ + +#define NI_SIZE 0x20 + +#define MAX_N_CALDACS 32 + +static const ni_board ni_boards[] = { + {device_id:44, + isapnp_id:0x0000,/* XXX unknown */ + name: "at-mio-16e-1", + n_adchan:16, + adbits: 12, + ai_fifo_depth:8192, + alwaysdither:0, + gainlkup:ai_gain_16, + ai_speed:800, + n_aochan:2, + aobits: 12, + ao_fifo_depth:2048, + .ao_range_table = &range_ni_E_ao_ext, + ao_unipolar:1, + ao_speed:1000, + has_8255:0, + .num_p0_dio_channels = 8, + caldac: {mb88341}, + }, + {device_id:25, + isapnp_id:0x1900, + name: "at-mio-16e-2", + n_adchan:16, + adbits: 12, + ai_fifo_depth:2048, + alwaysdither:0, + gainlkup:ai_gain_16, + ai_speed:2000, + n_aochan:2, + aobits: 12, + ao_fifo_depth:2048, + .ao_range_table = &range_ni_E_ao_ext, + ao_unipolar:1, + ao_speed:1000, + has_8255:0, + .num_p0_dio_channels = 8, + caldac: {mb88341}, + }, + {device_id:36, + isapnp_id:0x2400, + name: "at-mio-16e-10", + n_adchan:16, + adbits: 12, + ai_fifo_depth:512, + alwaysdither:0, + gainlkup:ai_gain_16, + ai_speed:10000, + n_aochan:2, + aobits: 12, + ao_fifo_depth:0, + .ao_range_table = &range_ni_E_ao_ext, + ao_unipolar:1, + ao_speed:10000, + .num_p0_dio_channels = 8, + caldac: {ad8804_debug}, + has_8255:0, + }, + {device_id:37, + isapnp_id:0x2500, + name: "at-mio-16de-10", + n_adchan:16, + adbits: 12, + ai_fifo_depth:512, + alwaysdither:0, + gainlkup:ai_gain_16, + ai_speed:10000, + n_aochan:2, + aobits: 12, + ao_fifo_depth:0, + .ao_range_table = &range_ni_E_ao_ext, + ao_unipolar:1, + ao_speed:10000, + .num_p0_dio_channels = 8, + caldac: {ad8804_debug}, + has_8255:1, + }, + {device_id:38, + isapnp_id:0x2600, + name: "at-mio-64e-3", + n_adchan:64, + adbits: 12, + ai_fifo_depth:2048, + alwaysdither:0, + gainlkup:ai_gain_16, + ai_speed:2000, + n_aochan:2, + aobits: 12, + ao_fifo_depth:2048, + .ao_range_table = &range_ni_E_ao_ext, + ao_unipolar:1, + ao_speed:1000, + has_8255:0, + .num_p0_dio_channels = 8, + caldac: {ad8804_debug}, + }, + {device_id:39, + isapnp_id:0x2700, + name: "at-mio-16xe-50", + n_adchan:16, + adbits: 16, + ai_fifo_depth:512, + alwaysdither:1, + gainlkup:ai_gain_8, + ai_speed:50000, + n_aochan:2, + aobits: 12, + ao_fifo_depth:0, + .ao_range_table = &range_bipolar10, + ao_unipolar:0, + ao_speed:50000, + .num_p0_dio_channels = 8, + caldac: {dac8800, dac8043}, + has_8255:0, + }, + {device_id:50, + isapnp_id:0x0000,/* XXX unknown */ + name: "at-mio-16xe-10", + n_adchan:16, + adbits: 16, + ai_fifo_depth:512, + alwaysdither:1, + gainlkup:ai_gain_14, + ai_speed:10000, + n_aochan:2, + aobits: 16, + ao_fifo_depth:2048, + .ao_range_table = &range_ni_E_ao_ext, + ao_unipolar:1, + ao_speed:1000, + .num_p0_dio_channels = 8, + caldac: {dac8800, dac8043, ad8522}, + has_8255:0, + }, + {device_id:51, + isapnp_id:0x0000,/* XXX unknown */ + name: "at-ai-16xe-10", + n_adchan:16, + adbits: 16, + ai_fifo_depth:512, + alwaysdither:1, /* unknown */ + gainlkup:ai_gain_14, + ai_speed:10000, + n_aochan:0, + aobits: 0, + ao_fifo_depth:0, + ao_unipolar:0, + .num_p0_dio_channels = 8, + caldac: {dac8800, dac8043, ad8522}, + has_8255:0, + } +}; + +static const int ni_irqpin[] = + { -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7 }; + +#define interrupt_pin(a) (ni_irqpin[(a)]) + +#define IRQ_POLARITY 0 + +#define NI_E_IRQ_FLAGS 0 + +typedef struct { + struct pnp_dev *isapnp_dev; + NI_PRIVATE_COMMON} ni_private; +#define devpriv ((ni_private *)dev->private) + +/* How we access registers */ + +#define ni_writel(a,b) (outl((a),(b)+dev->iobase)) +#define ni_readl(a) (inl((a)+dev->iobase)) +#define ni_writew(a,b) (outw((a),(b)+dev->iobase)) +#define ni_readw(a) (inw((a)+dev->iobase)) +#define ni_writeb(a,b) (outb((a),(b)+dev->iobase)) +#define ni_readb(a) (inb((a)+dev->iobase)) + +/* How we access windowed registers */ + +/* We automatically take advantage of STC registers that can be + * read/written directly in the I/O space of the board. The + * AT-MIO devices map the low 8 STC registers to iobase+addr*2. */ + +static void ni_atmio_win_out(struct comedi_device * dev, uint16_t data, int addr) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->window_lock, flags); + if ((addr) < 8) { + ni_writew(data, addr * 2); + } else { + ni_writew(addr, Window_Address); + ni_writew(data, Window_Data); + } + comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags); +} + +static uint16_t ni_atmio_win_in(struct comedi_device * dev, int addr) +{ + unsigned long flags; + uint16_t ret; + + comedi_spin_lock_irqsave(&devpriv->window_lock, flags); + if (addr < 8) { + ret = ni_readw(addr * 2); + } else { + ni_writew(addr, Window_Address); + ret = ni_readw(Window_Data); + } + comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags); + + return ret; +} + +static struct pnp_device_id device_ids[] = { + {.id = "NIC1900",.driver_data = 0}, + {.id = "NIC2400",.driver_data = 0}, + {.id = "NIC2500",.driver_data = 0}, + {.id = "NIC2600",.driver_data = 0}, + {.id = "NIC2700",.driver_data = 0}, + {.id = ""} +}; + +MODULE_DEVICE_TABLE(pnp, device_ids); + +static int ni_atmio_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int ni_atmio_detach(struct comedi_device * dev); +static struct comedi_driver driver_atmio = { + driver_name:"ni_atmio", + module:THIS_MODULE, + attach:ni_atmio_attach, + detach:ni_atmio_detach, +}; + +COMEDI_INITCLEANUP(driver_atmio); + +#include "ni_mio_common.c" + +static int ni_getboardtype(struct comedi_device * dev); + +/* clean up allocated resources */ +static int ni_atmio_detach(struct comedi_device * dev) +{ + mio_common_detach(dev); + + if (dev->iobase) + release_region(dev->iobase, NI_SIZE); + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + if (devpriv->isapnp_dev) + pnp_device_detach(devpriv->isapnp_dev); + + return 0; +} + +static int ni_isapnp_find_board(struct pnp_dev **dev) +{ + struct pnp_dev *isapnp_dev = NULL; + int i; + + for (i = 0; i < n_ni_boards; i++) { + isapnp_dev = pnp_find_dev(NULL, + ISAPNP_VENDOR('N', 'I', 'C'), + ISAPNP_FUNCTION(ni_boards[i].isapnp_id), NULL); + + if (isapnp_dev == NULL || isapnp_dev->card == NULL) + continue; + + if (pnp_device_attach(isapnp_dev) < 0) { + printk("ni_atmio: %s found but already active, skipping.\n", ni_boards[i].name); + continue; + } + if (pnp_activate_dev(isapnp_dev) < 0) { + pnp_device_detach(isapnp_dev); + return -EAGAIN; + } + if (!pnp_port_valid(isapnp_dev, 0) + || !pnp_irq_valid(isapnp_dev, 0)) { + pnp_device_detach(isapnp_dev); + printk("ni_atmio: pnp invalid port or irq, aborting\n"); + return -ENOMEM; + } + break; + } + if (i == n_ni_boards) + return -ENODEV; + *dev = isapnp_dev; + return 0; +} + +static int ni_atmio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct pnp_dev *isapnp_dev; + int ret; + unsigned long iobase; + int board; + unsigned int irq; + + /* allocate private area */ + if ((ret = ni_alloc_private(dev)) < 0) + return ret; + devpriv->stc_writew = &ni_atmio_win_out; + devpriv->stc_readw = &ni_atmio_win_in; + devpriv->stc_writel = &win_out2; + devpriv->stc_readl = &win_in2; + + iobase = it->options[0]; + irq = it->options[1]; + isapnp_dev = NULL; + if (iobase == 0) { + ret = ni_isapnp_find_board(&isapnp_dev); + if (ret < 0) + return ret; + + iobase = pnp_port_start(isapnp_dev, 0); + irq = pnp_irq(isapnp_dev, 0); + devpriv->isapnp_dev = isapnp_dev; + } + + /* reserve our I/O region */ + + printk("comedi%d: ni_atmio: 0x%04lx", dev->minor, iobase); + if (!request_region(iobase, NI_SIZE, "ni_atmio")) { + printk(" I/O port conflict\n"); + return -EIO; + } + + dev->iobase = iobase; + +#ifdef DEBUG + /* board existence sanity check */ + { + int i; + + printk(" board fingerprint:"); + for (i = 0; i < 16; i += 2) { + printk(" %04x %02x", inw(dev->iobase + i), + inb(dev->iobase + i + 1)); + } + } +#endif + + /* get board type */ + + board = ni_getboardtype(dev); + if (board < 0) + return -EIO; + + dev->board_ptr = ni_boards + board; + + printk(" %s", boardtype.name); + dev->board_name = boardtype.name; + + /* irq stuff */ + + if (irq != 0) { + if (irq > 15 || ni_irqpin[irq] == -1) { + printk(" invalid irq %u\n", irq); + return -EINVAL; + } + printk(" ( irq = %u )", irq); + if ((ret = comedi_request_irq(irq, ni_E_interrupt, + NI_E_IRQ_FLAGS, "ni_atmio", dev)) < 0) { + printk(" irq not available\n"); + return -EINVAL; + } + dev->irq = irq; + } + + /* generic E series stuff in ni_mio_common.c */ + + if ((ret = ni_E_init(dev, it)) < 0) { + return ret; + } + + return 0; +} + +static int ni_getboardtype(struct comedi_device * dev) +{ + int device_id = ni_read_eeprom(dev, 511); + int i; + + for (i = 0; i < n_ni_boards; i++) { + if (ni_boards[i].device_id == device_id) { + return i; + } + } + if (device_id == 255) { + printk(" can't find board\n"); + } else if (device_id == 0) { + printk(" EEPROM read error (?) or device not found\n"); + } else { + printk(" unknown device ID %d -- contact author\n", device_id); + } + return -1; +} diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c new file mode 100644 index 000000000000..35fcd172af2e --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -0,0 +1,860 @@ +/* + comedi/drivers/ni_atmio16d.c + Hardware driver for National Instruments AT-MIO16D board + Copyright (C) 2000 Chris R. Baugher + + 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: ni_atmio16d +Description: National Instruments AT-MIO-16D +Author: Chris R. Baugher +Status: unknown +Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) +*/ +/* + * I must give credit here to Michal Dobes who + * wrote the driver for Advantec's pcl812 boards. I used the interrupt + * handling code from his driver as an example for this one. + * + * Chris Baugher + * 5/1/2000 + * + */ + +#include "../comedidev.h" + +#include + +#include "8255.h" + +/* Configuration and Status Registers */ +#define COM_REG_1 0x00 /* wo 16 */ +#define STAT_REG 0x00 /* ro 16 */ +#define COM_REG_2 0x02 /* wo 16 */ +/* Event Strobe Registers */ +#define START_CONVERT_REG 0x08 /* wo 16 */ +#define START_DAQ_REG 0x0A /* wo 16 */ +#define AD_CLEAR_REG 0x0C /* wo 16 */ +#define EXT_STROBE_REG 0x0E /* wo 16 */ +/* Analog Output Registers */ +#define DAC0_REG 0x10 /* wo 16 */ +#define DAC1_REG 0x12 /* wo 16 */ +#define INT2CLR_REG 0x14 /* wo 16 */ +/* Analog Input Registers */ +#define MUX_CNTR_REG 0x04 /* wo 16 */ +#define MUX_GAIN_REG 0x06 /* wo 16 */ +#define AD_FIFO_REG 0x16 /* ro 16 */ +#define DMA_TC_INT_CLR_REG 0x16 /* wo 16 */ +/* AM9513A Counter/Timer Registers */ +#define AM9513A_DATA_REG 0x18 /* rw 16 */ +#define AM9513A_COM_REG 0x1A /* wo 16 */ +#define AM9513A_STAT_REG 0x1A /* ro 16 */ +/* MIO-16 Digital I/O Registers */ +#define MIO_16_DIG_IN_REG 0x1C /* ro 16 */ +#define MIO_16_DIG_OUT_REG 0x1C /* wo 16 */ +/* RTSI Switch Registers */ +#define RTSI_SW_SHIFT_REG 0x1E /* wo 8 */ +#define RTSI_SW_STROBE_REG 0x1F /* wo 8 */ +/* DIO-24 Registers */ +#define DIO_24_PORTA_REG 0x00 /* rw 8 */ +#define DIO_24_PORTB_REG 0x01 /* rw 8 */ +#define DIO_24_PORTC_REG 0x02 /* rw 8 */ +#define DIO_24_CNFG_REG 0x03 /* wo 8 */ + +/* Command Register bits */ +#define COMREG1_2SCADC 0x0001 +#define COMREG1_1632CNT 0x0002 +#define COMREG1_SCANEN 0x0008 +#define COMREG1_DAQEN 0x0010 +#define COMREG1_DMAEN 0x0020 +#define COMREG1_CONVINTEN 0x0080 +#define COMREG2_SCN2 0x0010 +#define COMREG2_INTEN 0x0080 +#define COMREG2_DOUTEN0 0x0100 +#define COMREG2_DOUTEN1 0x0200 +/* Status Register bits */ +#define STAT_AD_OVERRUN 0x0100 +#define STAT_AD_OVERFLOW 0x0200 +#define STAT_AD_DAQPROG 0x0800 +#define STAT_AD_CONVAVAIL 0x2000 +#define STAT_AD_DAQSTOPINT 0x4000 +/* AM9513A Counter/Timer defines */ +#define CLOCK_1_MHZ 0x8B25 +#define CLOCK_100_KHZ 0x8C25 +#define CLOCK_10_KHZ 0x8D25 +#define CLOCK_1_KHZ 0x8E25 +#define CLOCK_100_HZ 0x8F25 +/* Other miscellaneous defines */ +#define ATMIO16D_SIZE 32 /* bus address range */ +#define devpriv ((struct atmio16d_private *)dev->private) +#define ATMIO16D_TIMEOUT 10 + +struct atmio16_board_t { + + const char *name; + int has_8255; +}; + +static const struct atmio16_board_t atmio16_boards[] = { + { + name: "atmio16", + has_8255:0, + }, + { + name: "atmio16d", + has_8255:1, + }, +}; + +#define n_atmio16_boards sizeof(atmio16_boards)/sizeof(atmio16_boards[0]) + +#define boardtype ((const struct atmio16_board_t *)dev->board_ptr) + +/* function prototypes */ +static int atmio16d_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int atmio16d_detach(struct comedi_device * dev); +static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG); +static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int atmio16d_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int atmio16d_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void reset_counters(struct comedi_device * dev); +static void reset_atmio16d(struct comedi_device * dev); + +/* main driver struct */ +static struct comedi_driver driver_atmio16d = { + driver_name:"atmio16", + module:THIS_MODULE, + attach:atmio16d_attach, + detach:atmio16d_detach, + board_name:&atmio16_boards[0].name, + num_names:n_atmio16_boards, + offset:sizeof(struct atmio16_board_t), +}; + +COMEDI_INITCLEANUP(driver_atmio16d); + +/* range structs */ +static const struct comedi_lrange range_atmio16d_ai_10_bipolar = { 4, { + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.02) + } +}; + +static const struct comedi_lrange range_atmio16d_ai_5_bipolar = { 4, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.01) + } +}; + +static const struct comedi_lrange range_atmio16d_ai_unipolar = { 4, { + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.02) + } +}; + +/* private data struct */ +struct atmio16d_private { + enum { adc_diff, adc_singleended } adc_mux; + enum { adc_bipolar10, adc_bipolar5, adc_unipolar10 } adc_range; + enum { adc_2comp, adc_straight } adc_coding; + enum { dac_bipolar, dac_unipolar } dac0_range, dac1_range; + enum { dac_internal, dac_external } dac0_reference, dac1_reference; + enum { dac_2comp, dac_straight } dac0_coding, dac1_coding; + const struct comedi_lrange *ao_range_type_list[2]; + unsigned int ao_readback[2]; + unsigned int com_reg_1_state; /* current state of command register 1 */ + unsigned int com_reg_2_state; /* current state of command register 2 */ +}; + +static void reset_counters(struct comedi_device * dev) +{ + /* Counter 2 */ + outw(0xFFC2, dev->iobase + AM9513A_COM_REG); + outw(0xFF02, dev->iobase + AM9513A_COM_REG); + outw(0x4, dev->iobase + AM9513A_DATA_REG); + outw(0xFF0A, dev->iobase + AM9513A_COM_REG); + outw(0x3, dev->iobase + AM9513A_DATA_REG); + outw(0xFF42, dev->iobase + AM9513A_COM_REG); + outw(0xFF42, dev->iobase + AM9513A_COM_REG); + /* Counter 3 */ + outw(0xFFC4, dev->iobase + AM9513A_COM_REG); + outw(0xFF03, dev->iobase + AM9513A_COM_REG); + outw(0x4, dev->iobase + AM9513A_DATA_REG); + outw(0xFF0B, dev->iobase + AM9513A_COM_REG); + outw(0x3, dev->iobase + AM9513A_DATA_REG); + outw(0xFF44, dev->iobase + AM9513A_COM_REG); + outw(0xFF44, dev->iobase + AM9513A_COM_REG); + /* Counter 4 */ + outw(0xFFC8, dev->iobase + AM9513A_COM_REG); + outw(0xFF04, dev->iobase + AM9513A_COM_REG); + outw(0x4, dev->iobase + AM9513A_DATA_REG); + outw(0xFF0C, dev->iobase + AM9513A_COM_REG); + outw(0x3, dev->iobase + AM9513A_DATA_REG); + outw(0xFF48, dev->iobase + AM9513A_COM_REG); + outw(0xFF48, dev->iobase + AM9513A_COM_REG); + /* Counter 5 */ + outw(0xFFD0, dev->iobase + AM9513A_COM_REG); + outw(0xFF05, dev->iobase + AM9513A_COM_REG); + outw(0x4, dev->iobase + AM9513A_DATA_REG); + outw(0xFF0D, dev->iobase + AM9513A_COM_REG); + outw(0x3, dev->iobase + AM9513A_DATA_REG); + outw(0xFF50, dev->iobase + AM9513A_COM_REG); + outw(0xFF50, dev->iobase + AM9513A_COM_REG); + + outw(0, dev->iobase + AD_CLEAR_REG); +} + +static void reset_atmio16d(struct comedi_device * dev) +{ + int i; + + /* now we need to initialize the board */ + outw(0, dev->iobase + COM_REG_1); + outw(0, dev->iobase + COM_REG_2); + outw(0, dev->iobase + MUX_GAIN_REG); + /* init AM9513A timer */ + outw(0xFFFF, dev->iobase + AM9513A_COM_REG); + outw(0xFFEF, dev->iobase + AM9513A_COM_REG); + outw(0xFF17, dev->iobase + AM9513A_COM_REG); + outw(0xF000, dev->iobase + AM9513A_DATA_REG); + for (i = 1; i <= 5; ++i) { + outw(0xFF00 + i, dev->iobase + AM9513A_COM_REG); + outw(0x0004, dev->iobase + AM9513A_DATA_REG); + outw(0xFF08 + i, dev->iobase + AM9513A_COM_REG); + outw(0x3, dev->iobase + AM9513A_DATA_REG); + } + outw(0xFF5F, dev->iobase + AM9513A_COM_REG); + /* timer init done */ + outw(0, dev->iobase + AD_CLEAR_REG); + outw(0, dev->iobase + INT2CLR_REG); + /* select straight binary mode for Analog Input */ + devpriv->com_reg_1_state |= 1; + outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); + devpriv->adc_coding = adc_straight; + /* zero the analog outputs */ + outw(2048, dev->iobase + DAC0_REG); + outw(2048, dev->iobase + DAC1_REG); +} + +static irqreturn_t atmio16d_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + +// printk("atmio16d_interrupt!\n"); + + comedi_buf_put(s->async, inw(dev->iobase + AD_FIFO_REG)); + + comedi_event(dev, s); + return IRQ_HANDLED; +} + +static int atmio16d_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0, tmp; +#ifdef DEBUG1 + printk("atmio16d_ai_cmdtest\n"); +#endif + /* make sure triggers are valid */ + 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_FOLLOW | TRIG_TIMER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + /* note that mutual compatiblity is not an issue here */ + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_TIMER) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + if (cmd->scan_begin_src == TRIG_FOLLOW) { + /* internal trigger */ + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + } else { +#if 0 + /* external trigger */ + /* should be level/edge, hi/lo specification here */ + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } +#endif + } + + if (cmd->convert_arg < 10000) { + cmd->convert_arg = 10000; + err++; + } +#if 0 + if (cmd->convert_arg > SLOWEST_TIMER) { + cmd->convert_arg = SLOWEST_TIMER; + err++; + } +#endif + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + /* any count is allowed */ + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + return 0; +} + +static int atmio16d_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int timer, base_clock; + unsigned int sample_count, tmp, chan, gain; + int i; +#ifdef DEBUG1 + printk("atmio16d_ai_cmd\n"); +#endif + /* This is slowly becoming a working command interface. * + * It is still uber-experimental */ + + reset_counters(dev); + s->async->cur_chan = 0; + + /* check if scanning multiple channels */ + if (cmd->chanlist_len < 2) { + devpriv->com_reg_1_state &= ~COMREG1_SCANEN; + outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); + } else { + devpriv->com_reg_1_state |= COMREG1_SCANEN; + devpriv->com_reg_2_state |= COMREG2_SCN2; + outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); + outw(devpriv->com_reg_2_state, dev->iobase + COM_REG_2); + } + + /* Setup the Mux-Gain Counter */ + for (i = 0; i < cmd->chanlist_len; ++i) { + chan = CR_CHAN(cmd->chanlist[i]); + gain = CR_RANGE(cmd->chanlist[i]); + outw(i, dev->iobase + MUX_CNTR_REG); + tmp = chan | (gain << 6); + if (i == cmd->scan_end_arg - 1) + tmp |= 0x0010; /* set LASTONE bit */ + outw(tmp, dev->iobase + MUX_GAIN_REG); + } + + /* Now program the sample interval timer */ + /* Figure out which clock to use then get an + * appropriate timer value */ + if (cmd->convert_arg < 65536000) { + base_clock = CLOCK_1_MHZ; + timer = cmd->convert_arg / 1000; + } else if (cmd->convert_arg < 655360000) { + base_clock = CLOCK_100_KHZ; + timer = cmd->convert_arg / 10000; + } else if (cmd->convert_arg <= 0xffffffff /* 6553600000 */ ) { + base_clock = CLOCK_10_KHZ; + timer = cmd->convert_arg / 100000; + } else if (cmd->convert_arg <= 0xffffffff /* 65536000000 */ ) { + base_clock = CLOCK_1_KHZ; + timer = cmd->convert_arg / 1000000; + } + outw(0xFF03, dev->iobase + AM9513A_COM_REG); + outw(base_clock, dev->iobase + AM9513A_DATA_REG); + outw(0xFF0B, dev->iobase + AM9513A_COM_REG); + outw(0x2, dev->iobase + AM9513A_DATA_REG); + outw(0xFF44, dev->iobase + AM9513A_COM_REG); + outw(0xFFF3, dev->iobase + AM9513A_COM_REG); + outw(timer, dev->iobase + AM9513A_DATA_REG); + outw(0xFF24, dev->iobase + AM9513A_COM_REG); + + /* Now figure out how many samples to get */ + /* and program the sample counter */ + sample_count = cmd->stop_arg * cmd->scan_end_arg; + outw(0xFF04, dev->iobase + AM9513A_COM_REG); + outw(0x1025, dev->iobase + AM9513A_DATA_REG); + outw(0xFF0C, dev->iobase + AM9513A_COM_REG); + if (sample_count < 65536) { + /* use only Counter 4 */ + outw(sample_count, dev->iobase + AM9513A_DATA_REG); + outw(0xFF48, dev->iobase + AM9513A_COM_REG); + outw(0xFFF4, dev->iobase + AM9513A_COM_REG); + outw(0xFF28, dev->iobase + AM9513A_COM_REG); + devpriv->com_reg_1_state &= ~COMREG1_1632CNT; + outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); + } else { + /* Counter 4 and 5 are needed */ + if ((tmp = sample_count & 0xFFFF)) { + outw(tmp - 1, dev->iobase + AM9513A_DATA_REG); + } else { + outw(0xFFFF, dev->iobase + AM9513A_DATA_REG); + } + outw(0xFF48, dev->iobase + AM9513A_COM_REG); + outw(0, dev->iobase + AM9513A_DATA_REG); + outw(0xFF28, dev->iobase + AM9513A_COM_REG); + outw(0xFF05, dev->iobase + AM9513A_COM_REG); + outw(0x25, dev->iobase + AM9513A_DATA_REG); + outw(0xFF0D, dev->iobase + AM9513A_COM_REG); + tmp = sample_count & 0xFFFF; + if ((tmp == 0) || (tmp == 1)) { + outw((sample_count >> 16) & 0xFFFF, + dev->iobase + AM9513A_DATA_REG); + } else { + outw(((sample_count >> 16) & 0xFFFF) + 1, + dev->iobase + AM9513A_DATA_REG); + } + outw(0xFF70, dev->iobase + AM9513A_COM_REG); + devpriv->com_reg_1_state |= COMREG1_1632CNT; + outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); + } + + /* Program the scan interval timer ONLY IF SCANNING IS ENABLED */ + /* Figure out which clock to use then get an + * appropriate timer value */ + if (cmd->chanlist_len > 1) { + if (cmd->scan_begin_arg < 65536000) { + base_clock = CLOCK_1_MHZ; + timer = cmd->scan_begin_arg / 1000; + } else if (cmd->scan_begin_arg < 655360000) { + base_clock = CLOCK_100_KHZ; + timer = cmd->scan_begin_arg / 10000; + } else if (cmd->scan_begin_arg < 0xffffffff /* 6553600000 */ ) { + base_clock = CLOCK_10_KHZ; + timer = cmd->scan_begin_arg / 100000; + } else if (cmd->scan_begin_arg < 0xffffffff /* 65536000000 */ ) { + base_clock = CLOCK_1_KHZ; + timer = cmd->scan_begin_arg / 1000000; + } + outw(0xFF02, dev->iobase + AM9513A_COM_REG); + outw(base_clock, dev->iobase + AM9513A_DATA_REG); + outw(0xFF0A, dev->iobase + AM9513A_COM_REG); + outw(0x2, dev->iobase + AM9513A_DATA_REG); + outw(0xFF42, dev->iobase + AM9513A_COM_REG); + outw(0xFFF2, dev->iobase + AM9513A_COM_REG); + outw(timer, dev->iobase + AM9513A_DATA_REG); + outw(0xFF22, dev->iobase + AM9513A_COM_REG); + } + + /* Clear the A/D FIFO and reset the MUX counter */ + outw(0, dev->iobase + AD_CLEAR_REG); + outw(0, dev->iobase + MUX_CNTR_REG); + outw(0, dev->iobase + INT2CLR_REG); + /* enable this acquisition operation */ + devpriv->com_reg_1_state |= COMREG1_DAQEN; + outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); + /* enable interrupts for conversion completion */ + devpriv->com_reg_1_state |= COMREG1_CONVINTEN; + devpriv->com_reg_2_state |= COMREG2_INTEN; + outw(devpriv->com_reg_1_state, dev->iobase + COM_REG_1); + outw(devpriv->com_reg_2_state, dev->iobase + COM_REG_2); + /* apply a trigger. this starts the counters! */ + outw(0, dev->iobase + START_DAQ_REG); + + return 0; +} + +/* This will cancel a running acquisition operation */ +static int atmio16d_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + reset_atmio16d(dev); + + return 0; +} + +/* Mode 0 is used to get a single conversion on demand */ +static int atmio16d_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, t; + int chan; + int gain; + int status; + +#ifdef DEBUG1 + printk("atmio16d_ai_insn_read\n"); +#endif + chan = CR_CHAN(insn->chanspec); + gain = CR_RANGE(insn->chanspec); + + /* reset the Analog input circuitry */ + //outw( 0, dev->iobase+AD_CLEAR_REG ); + /* reset the Analog Input MUX Counter to 0 */ + //outw( 0, dev->iobase+MUX_CNTR_REG ); + + /* set the Input MUX gain */ + outw(chan | (gain << 6), dev->iobase + MUX_GAIN_REG); + + for (i = 0; i < insn->n; i++) { + /* start the conversion */ + outw(0, dev->iobase + START_CONVERT_REG); + /* wait for it to finish */ + for (t = 0; t < ATMIO16D_TIMEOUT; t++) { + /* check conversion status */ + status = inw(dev->iobase + STAT_REG); +#ifdef DEBUG1 + printk("status=%x\n", status); +#endif + if (status & STAT_AD_CONVAVAIL) { + /* read the data now */ + data[i] = inw(dev->iobase + AD_FIFO_REG); + /* change to two's complement if need be */ + if (devpriv->adc_coding == adc_2comp) { + data[i] ^= 0x800; + } + break; + } + if (status & STAT_AD_OVERFLOW) { + printk("atmio16d: a/d FIFO overflow\n"); + outw(0, dev->iobase + AD_CLEAR_REG); + + return -ETIME; + } + } + /* end waiting, now check if it timed out */ + if (t == ATMIO16D_TIMEOUT) { + rt_printk("atmio16d: timeout\n"); + + return -ETIME; + } + } + + return i; +} + +static int atmio16d_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; +#ifdef DEBUG1 + printk("atmio16d_ao_insn_read\n"); +#endif + + for (i = 0; i < insn->n; i++) { + data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; + } + + return i; +} + +static int atmio16d_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan; + int d; +#ifdef DEBUG1 + printk("atmio16d_ao_insn_write\n"); +#endif + + chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + d = data[i]; + switch (chan) { + case 0: + if (devpriv->dac0_coding == dac_2comp) { + d ^= 0x800; + } + outw(d, dev->iobase + DAC0_REG); + break; + case 1: + if (devpriv->dac1_coding == dac_2comp) { + d ^= 0x800; + } + outw(d, dev->iobase + DAC1_REG); + break; + default: + return -EINVAL; + } + devpriv->ao_readback[chan] = data[i]; + } + return i; +} + +static int atmio16d_dio_insn_bits(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]); + outw(s->state, dev->iobase + MIO_16_DIG_OUT_REG); + } + data[1] = inw(dev->iobase + MIO_16_DIG_IN_REG); + + return 2; +} + +static int atmio16d_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int mask; + + for (i = 0; i < insn->n; i++) { + mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0; + s->io_bits &= ~mask; + if (data[i]) + s->io_bits |= mask; + } + devpriv->com_reg_2_state &= ~(COMREG2_DOUTEN0 | COMREG2_DOUTEN1); + if (s->io_bits & 0x0f) + devpriv->com_reg_2_state |= COMREG2_DOUTEN0; + if (s->io_bits & 0xf0) + devpriv->com_reg_2_state |= COMREG2_DOUTEN1; + outw(devpriv->com_reg_2_state, dev->iobase + COM_REG_2); + + return i; +} + +/* + options[0] - I/O port + options[1] - MIO irq + 0 == no irq + N == irq N {3,4,5,6,7,9,10,11,12,14,15} + options[2] - DIO irq + 0 == no irq + N == irq N {3,4,5,6,7,9} + options[3] - DMA1 channel + 0 == no DMA + N == DMA N {5,6,7} + options[4] - DMA2 channel + 0 == no DMA + N == DMA N {5,6,7} + + options[5] - a/d mux + 0=differential, 1=single + options[6] - a/d range + 0=bipolar10, 1=bipolar5, 2=unipolar10 + + options[7] - dac0 range + 0=bipolar, 1=unipolar + options[8] - dac0 reference + 0=internal, 1=external + options[9] - dac0 coding + 0=2's comp, 1=straight binary + + options[10] - dac1 range + options[11] - dac1 reference + options[12] - dac1 coding + */ + +static int atmio16d_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + unsigned int irq; + unsigned long iobase; + int ret; + + struct comedi_subdevice *s; + + /* make sure the address range is free and allocate it */ + iobase = it->options[0]; + printk("comedi%d: atmio16d: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, ATMIO16D_SIZE, "ni_atmio16d")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + /* board name */ + dev->board_name = boardtype->name; + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + if ((ret = alloc_private(dev, sizeof(struct atmio16d_private))) < 0) + return ret; + + /* reset the atmio16d hardware */ + reset_atmio16d(dev); + + /* check if our interrupt is available and get it */ + irq = it->options[1]; + if (irq) { + if ((ret = comedi_request_irq(irq, atmio16d_interrupt, + 0, "atmio16d", dev)) < 0) { + printk("failed to allocate irq %u\n", irq); + return ret; + } + dev->irq = irq; + printk("( irq = %u )\n", irq); + } else { + printk("( no irq )"); + } + + /* set device options */ + devpriv->adc_mux = it->options[5]; + devpriv->adc_range = it->options[6]; + + devpriv->dac0_range = it->options[7]; + devpriv->dac0_reference = it->options[8]; + devpriv->dac0_coding = it->options[9]; + devpriv->dac1_range = it->options[10]; + devpriv->dac1_reference = it->options[11]; + devpriv->dac1_coding = it->options[12]; + + /* setup sub-devices */ + s = dev->subdevices + 0; + dev->read_subdev = s; + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; + s->n_chan = (devpriv->adc_mux ? 16 : 8); + s->len_chanlist = 16; + s->insn_read = atmio16d_ai_insn_read; + s->do_cmdtest = atmio16d_ai_cmdtest; + s->do_cmd = atmio16d_ai_cmd; + s->cancel = atmio16d_ai_cancel; + s->maxdata = 0xfff; /* 4095 decimal */ + switch (devpriv->adc_range) { + case adc_bipolar10: + s->range_table = &range_atmio16d_ai_10_bipolar; + break; + case adc_bipolar5: + s->range_table = &range_atmio16d_ai_5_bipolar; + break; + case adc_unipolar10: + s->range_table = &range_atmio16d_ai_unipolar; + break; + } + + /* ao subdevice */ + s++; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->insn_read = atmio16d_ao_insn_read; + s->insn_write = atmio16d_ao_insn_write; + s->maxdata = 0xfff; /* 4095 decimal */ + s->range_table_list = devpriv->ao_range_type_list; + switch (devpriv->dac0_range) { + case dac_bipolar: + devpriv->ao_range_type_list[0] = &range_bipolar10; + break; + case dac_unipolar: + devpriv->ao_range_type_list[0] = &range_unipolar10; + break; + } + switch (devpriv->dac1_range) { + case dac_bipolar: + devpriv->ao_range_type_list[1] = &range_bipolar10; + break; + case dac_unipolar: + devpriv->ao_range_type_list[1] = &range_unipolar10; + break; + } + + /* Digital I/O */ + s++; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 8; + s->insn_bits = atmio16d_dio_insn_bits; + s->insn_config = atmio16d_dio_insn_config; + s->maxdata = 1; + s->range_table = &range_digital; + + /* 8255 subdevice */ + s++; + if (boardtype->has_8255) { + subdev_8255_init(dev, s, NULL, dev->iobase); + } else { + s->type = COMEDI_SUBD_UNUSED; + } + +/* don't yet know how to deal with counter/timers */ +#if 0 + s++; + /* do */ + s->type = COMEDI_SUBD_TIMER; + s->n_chan = 0; + s->maxdata = 0 +#endif + printk("\n"); + + return 0; +} + +static int atmio16d_detach(struct comedi_device * dev) +{ + printk("comedi%d: atmio16d: remove\n", dev->minor); + + if (dev->subdevices && boardtype->has_8255) + subdev_8255_cleanup(dev, dev->subdevices + 3); + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + reset_atmio16d(dev); + + if (dev->iobase) + release_region(dev->iobase, ATMIO16D_SIZE); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c new file mode 100644 index 000000000000..61a31ad2d030 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -0,0 +1,841 @@ +/* + * comedi/drivers/ni_daq_700.c + * Driver for DAQCard-700 DIO only + * copied from 8255 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef + * + * 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: ni_daq_700 +Description: National Instruments PCMCIA DAQCard-700 DIO only +Author: Fred Brooks , + based on ni_daq_dio24 by Daniel Vecino Castel +Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700) +Status: works +Updated: Thu, 21 Feb 2008 12:07:20 +0000 + +The daqcard-700 appears in Comedi as a single digital I/O subdevice with +16 channels. The channel 0 corresponds to the daqcard-700's output +port, bit 0; channel 8 corresponds to the input port, bit 0. + +Direction configuration: channels 0-7 output, 8-15 input (8225 device +emu as port A output, port B input, port C N/A). + +IRQ is assigned but not used. +*/ + +#include "../comedidev.h" + +#include + +#include +#include +#include +#include +#include + +static struct pcmcia_device *pcmcia_cur_dev = NULL; + +#define DIO700_SIZE 8 // size of io region used by board + +static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dio700_detach(struct comedi_device * dev); + +enum dio700_bustype { pcmcia_bustype }; + +struct dio700_board { + const char *name; + int device_id; // device id for pcmcia board + enum dio700_bustype bustype; // PCMCIA + int have_dio; // have daqcard-700 dio + // function pointers so we can use inb/outb or readb/writeb + // as appropriate + unsigned int (*read_byte) (unsigned int address); + void (*write_byte) (unsigned int byte, unsigned int address); +}; + +static const struct dio700_board dio700_boards[] = { + { + name: "daqcard-700", + device_id:0x4743,// 0x10b is manufacturer id, 0x4743 is device id + bustype: pcmcia_bustype, + have_dio:1, + }, + { + name: "ni_daq_700", + device_id:0x4743,// 0x10b is manufacturer id, 0x4743 is device id + bustype: pcmcia_bustype, + have_dio:1, + }, +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct dio700_board *)dev->board_ptr) + +struct dio700_private { + + int data; /* number of data points left to be taken */ +}; + + +#define devpriv ((struct dio700_private *)dev->private) + +static struct comedi_driver driver_dio700 = { + driver_name:"ni_daq_700", + module:THIS_MODULE, + attach:dio700_attach, + detach:dio700_detach, + num_names:sizeof(dio700_boards) / sizeof(struct dio700_board), + board_name:&dio700_boards[0].name, + offset:sizeof(struct dio700_board), +}; + +/* the real driver routines */ + +#define _700_SIZE 8 + +#define _700_DATA 0 + +#define DIO_W 0x04 +#define DIO_R 0x05 + +struct subdev_700_struct { + unsigned long cb_arg; + int (*cb_func) (int, int, int, unsigned long); + int have_irq; +}; + +#define CALLBACK_ARG (((struct subdev_700_struct *)s->private)->cb_arg) +#define CALLBACK_FUNC (((struct subdev_700_struct *)s->private)->cb_func) +#define subdevpriv ((struct subdev_700_struct *)s->private) + +static void do_config(struct comedi_device * dev, struct comedi_subdevice * s); + +void subdev_700_interrupt(struct comedi_device * dev, struct comedi_subdevice * s) +{ + short d; + + d = CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG); + + comedi_buf_put(s->async, d); + s->async->events |= COMEDI_CB_EOS; + + comedi_event(dev, s); +} + +static int subdev_700_cb(int dir, int port, int data, unsigned long arg) +{ + /* port is always A for output and B for input (8255 emu) */ + unsigned long iobase = arg; + + if (dir) { + outb(data, iobase + DIO_W); + return 0; + } else { + return inb(iobase + DIO_R); + } +} + +static int subdev_700_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, _700_DATA, s->state & 0xff, + CALLBACK_ARG); + } + + data[1] = s->state & 0xff; + data[1] |= CALLBACK_FUNC(0, _700_DATA, 0, CALLBACK_ARG) << 8; + + return 2; +} + +static int subdev_700_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + + switch (data[0]) { + case INSN_CONFIG_DIO_INPUT: + break; + case INSN_CONFIG_DIO_OUTPUT: + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s->io_bits & (1 << CR_CHAN(insn-> + chanspec))) ? COMEDI_OUTPUT : + COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + } + + return 1; +} + +static void do_config(struct comedi_device * dev, struct comedi_subdevice * s) +{ /* use powerup defaults */ + return; +} + +static int subdev_700_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_700_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + /* FIXME */ + + return 0; +} + +static int subdev_700_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + /* FIXME */ + + return 0; +} + +int subdev_700_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 = 16; + s->range_table = &range_digital; + s->maxdata = 1; + + s->private = kmalloc(sizeof(struct subdev_700_struct), GFP_KERNEL); + if (!s->private) + return -ENOMEM; + + CALLBACK_ARG = arg; + if (cb == NULL) { + CALLBACK_FUNC = subdev_700_cb; + } else { + CALLBACK_FUNC = cb; + } + s->insn_bits = subdev_700_insn; + s->insn_config = subdev_700_insn_config; + + s->state = 0; + s->io_bits = 0x00ff; + do_config(dev, s); + + return 0; +} + +int subdev_700_init_irq(struct comedi_device * dev, struct comedi_subdevice * s, + int (*cb) (int, int, int, unsigned long), unsigned long arg) +{ + int ret; + + ret = subdev_700_init(dev, s, cb, arg); + if (ret < 0) + return ret; + + s->do_cmdtest = subdev_700_cmdtest; + s->do_cmd = subdev_700_cmd; + s->cancel = subdev_700_cancel; + + subdevpriv->have_irq = 1; + + return 0; +} + +void subdev_700_cleanup(struct comedi_device * dev, struct comedi_subdevice * s) +{ + if (s->private) { + if (subdevpriv->have_irq) { + } + + kfree(s->private); + } +} + +EXPORT_SYMBOL(subdev_700_init); +EXPORT_SYMBOL(subdev_700_init_irq); +EXPORT_SYMBOL(subdev_700_cleanup); +EXPORT_SYMBOL(subdev_700_interrupt); + +static int dio700_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase = 0; +#ifdef incomplete + unsigned int irq = 0; +#endif + struct pcmcia_device *link; + + /* allocate and initialize dev->private */ + if (alloc_private(dev, sizeof(struct dio700_private)) < 0) + return -ENOMEM; + + // get base address, irq etc. based on bustype + switch (thisboard->bustype) { + case pcmcia_bustype: + link = pcmcia_cur_dev; /* XXX hack */ + if (!link) + return -EIO; + iobase = link->io.BasePort1; +#ifdef incomplete + irq = link->irq.AssignedIRQ; +#endif + break; + default: + printk("bug! couldn't determine board type\n"); + return -EINVAL; + break; + } + printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor, + thisboard->name, iobase); +#ifdef incomplete + if (irq) { + printk(", irq %u", irq); + } +#endif + + printk("\n"); + + if (iobase == 0) { + printk("io base address is zero!\n"); + return -EINVAL; + } + + dev->iobase = iobase; + +#ifdef incomplete + /* grab our IRQ */ + dev->irq = irq; +#endif + + dev->board_name = thisboard->name; + + if (alloc_subdevices(dev, 1) < 0) + return -ENOMEM; + + /* DAQCard-700 dio */ + s = dev->subdevices + 0; + subdev_700_init(dev, s, NULL, dev->iobase); + + return 0; +}; + +static int dio700_detach(struct comedi_device * dev) +{ + printk("comedi%d: ni_daq_700: cs-remove\n", dev->minor); + + if (dev->subdevices) + subdev_700_cleanup(dev, dev->subdevices + 0); + + if (thisboard->bustype != pcmcia_bustype && dev->iobase) + release_region(dev->iobase, DIO700_SIZE); + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + return 0; +}; + +// PCMCIA crap + +/* + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + you do not define PCMCIA_DEBUG at all, all the debug code will be + left out. If you compile with PCMCIA_DEBUG=0, the debug code will + be present but disabled -- but it can then be enabled for specific + modules at load time with a 'pc_debug=#' option to insmod. +*/ +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +module_param(pc_debug, int, 0644); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = "ni_daq_700.c, based on dummy_cs.c"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +static void dio700_config(struct pcmcia_device *link); +static void dio700_release(struct pcmcia_device *link); +static int dio700_cs_suspend(struct pcmcia_device *p_dev); +static int dio700_cs_resume(struct pcmcia_device *p_dev); + +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static int dio700_cs_attach(struct pcmcia_device *); +static void dio700_cs_detach(struct pcmcia_device *); + +/* + You'll also need to prototype all the functions that will actually + be used to talk to your device. See 'memory_cs' for a good example + of a fully self-sufficient driver; the other drivers rely more or + less on other parts of the kernel. +*/ + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static const dev_info_t dev_info = "ni_daq_700"; + +struct local_info_t { + struct pcmcia_device *link; + dev_node_t node; + int stop; + struct bus_operations *bus; +}; + +/*====================================================================== + + dio700_cs_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + +======================================================================*/ + +static int dio700_cs_attach(struct pcmcia_device *link) +{ + struct local_info_t *local; + + printk(KERN_INFO "ni_daq_700: cs-attach\n"); + + DEBUG(0, "dio700_cs_attach()\n"); + + /* Allocate space for private device-specific data */ + local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); + if (!local) + return -ENOMEM; + local->link = link; + link->priv = local; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->irq.Handler = NULL; + + /* + General socket configuration defaults can go here. In this + client, we assume very little, and rely on the CIS for almost + everything. In most clients, many details (i.e., number, sizes, + and attributes of IO windows) are fixed by the nature of the + device, and can be hard-wired here. + */ + link->conf.Attributes = 0; + link->conf.IntType = INT_MEMORY_AND_IO; + + pcmcia_cur_dev = link; + + dio700_config(link); + + return 0; +} /* dio700_cs_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void dio700_cs_detach(struct pcmcia_device *link) +{ + + printk(KERN_INFO "ni_daq_700: cs-detach!\n"); + + DEBUG(0, "dio700_cs_detach(0x%p)\n", link); + + if (link->dev_node) { + ((struct local_info_t *) link->priv)->stop = 1; + dio700_release(link); + } + + /* This points to the parent struct local_info_t struct */ + if (link->priv) + kfree(link->priv); + +} /* dio700_cs_detach */ + +/*====================================================================== + + dio700_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + device available to the system. + +======================================================================*/ + +static void dio700_config(struct pcmcia_device *link) +{ + struct local_info_t *dev = link->priv; + tuple_t tuple; + cisparse_t parse; + int last_ret; + u_char buf[64]; + win_req_t req; + memreq_t map; + cistpl_cftable_entry_t dflt = { 0 }; + + printk(KERN_INFO "ni_daq_700: cs-config\n"); + + DEBUG(0, "dio700_config(0x%p)\n", link); + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) { + cs_error(link, GetFirstTuple, last_ret); + goto cs_failed; + } + if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) { + cs_error(link, GetTupleData, last_ret); + goto cs_failed; + } + if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) { + cs_error(link, ParseTuple, last_ret); + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* + In this loop, we scan the CIS for configuration table entries, + each of which describes a valid card configuration, including + voltage, IO window, memory window, and interrupt settings. + + We make no assumptions about the card to be configured: we use + just the information available in the CIS. In an ideal world, + this would work for any PCMCIA card, but it requires a complete + and accurate CIS. In practice, a driver usually "knows" most of + these things without consulting the CIS, and most client drivers + will only use the CIS to fill in implementation-defined details. + */ + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) { + cs_error(link, GetFirstTuple, last_ret); + goto cs_failed; + } + while (1) { + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + if (pcmcia_get_tuple_data(link, &tuple) != 0) + goto next_entry; + if (pcmcia_parse_tuple(&tuple, &parse) != 0) + goto next_entry; + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + if (cfg->index == 0) + goto next_entry; + link->conf.ConfigIndex = cfg->index; + + /* Does this card need audio output? */ + if (cfg->flags & CISTPL_CFTABLE_AUDIO) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + /* This reserves IO space but doesn't actually enable it */ + if (pcmcia_request_io(link, &link->io) != 0) + goto next_entry; + } + + if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { + cistpl_mem_t *mem = + (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; + req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; + req.Attributes |= WIN_ENABLE; + req.Base = mem->win[0].host_addr; + req.Size = mem->win[0].len; + if (req.Size < 0x1000) + req.Size = 0x1000; + req.AccessSpeed = 0; + if (pcmcia_request_window(&link, &req, &link->win)) + goto next_entry; + map.Page = 0; + map.CardOffset = mem->win[0].card_addr; + if (pcmcia_map_mem_page(link->win, &map)) + goto next_entry; + } + /* If we got this far, we're cool! */ + break; + + next_entry: + if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0) { + cs_error(link, GetNextTuple, last_ret); + goto cs_failed; + } + } + + /* + Allocate an interrupt line. Note that this does not assign a + handler to the interrupt, unless the 'Handler' member of the + irq structure is initialized. + */ + if (link->conf.Attributes & CONF_ENABLE_IRQ) + if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0) { + cs_error(link, RequestIRQ, last_ret); + goto cs_failed; + } + + /* + This actually configures the PCMCIA socket -- setting up + the I/O windows and the interrupt mapping, and putting the + card and host interface into "Memory and IO" mode. + */ + if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0) { + cs_error(link, RequestConfiguration, last_ret); + goto cs_failed; + } + + /* + At this point, the dev_node_t structure(s) need to be + initialized and arranged in a linked list at link->dev. + */ + sprintf(dev->node.dev_name, "ni_daq_700"); + dev->node.major = dev->node.minor = 0; + link->dev_node = &dev->node; + + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %d", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1 + link->io.NumPorts1 - 1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->win) + printk(", mem 0x%06lx-0x%06lx", req.Base, + req.Base + req.Size - 1); + printk("\n"); + + return; + + cs_failed: + printk(KERN_INFO "ni_daq_700 cs failed"); + dio700_release(link); + +} /* dio700_config */ + +static void dio700_release(struct pcmcia_device *link) +{ + DEBUG(0, "dio700_release(0x%p)\n", link); + + pcmcia_disable_device(link); +} /* dio700_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. + + When a CARD_REMOVAL event is received, we immediately set a + private flag to block future accesses to this device. All the + functions that actually access the device should check this flag + to make sure the card is still present. + +======================================================================*/ + +static int dio700_cs_suspend(struct pcmcia_device *link) +{ + struct local_info_t *local = link->priv; + + /* Mark the device as stopped, to block IO until later */ + local->stop = 1; + return 0; +} /* dio700_cs_suspend */ + +static int dio700_cs_resume(struct pcmcia_device *link) +{ + struct local_info_t *local = link->priv; + + local->stop = 0; + return 0; +} /* dio700_cs_resume */ + +/*====================================================================*/ + +static struct pcmcia_device_id dio700_cs_ids[] = { + /* N.B. These IDs should match those in dio700_boards */ + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743), /* daqcard-700 */ + PCMCIA_DEVICE_NULL +}; + +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids); + +struct pcmcia_driver dio700_cs_driver = { + .probe = dio700_cs_attach, + .remove = dio700_cs_detach, + .suspend = dio700_cs_suspend, + .resume = dio700_cs_resume, + .id_table = dio700_cs_ids, + .owner = THIS_MODULE, + .drv = { + .name = dev_info, + }, +}; + +static int __init init_dio700_cs(void) +{ + printk("ni_daq_700: cs-init \n"); + DEBUG(0, "%s\n", version); + pcmcia_register_driver(&dio700_cs_driver); + return 0; +} + +static void __exit exit_dio700_cs(void) +{ + DEBUG(0, "ni_daq_700: unloading\n"); + pcmcia_unregister_driver(&dio700_cs_driver); +} +int __init init_module(void) +{ + int ret; + + ret = init_dio700_cs(); + if (ret < 0) + return ret; + + return comedi_driver_register(&driver_dio700); +} + +void __exit cleanup_module(void) +{ + exit_dio700_cs(); + comedi_driver_unregister(&driver_dio700); +} diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c new file mode 100644 index 000000000000..daec5c4b4c95 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -0,0 +1,598 @@ +/* + comedi/drivers/ni_daq_dio24.c + Driver for National Instruments PCMCIA DAQ-Card DIO-24 + Copyright (C) 2002 Daniel Vecino Castel + + PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 2001/08/24 12:13:13 + from the pcmcia package. + The initial developer of the pcmcia dummy_cs.c code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + + 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: ni_daq_dio24 +Description: National Instruments PCMCIA DAQ-Card DIO-24 +Author: Daniel Vecino Castel +Devices: [National Instruments] PCMCIA DAQ-Card DIO-24 (ni_daq_dio24) +Status: ? +Updated: Thu, 07 Nov 2002 21:53:06 -0800 + +This is just a wrapper around the 8255.o driver to properly handle +the PCMCIA interface. +*/ + +//#define LABPC_DEBUG // enable debugging messages +#undef LABPC_DEBUG + +#include "../comedidev.h" + +#include + +#include "8255.h" + +#include +#include +#include +#include +#include + +static struct pcmcia_device *pcmcia_cur_dev = NULL; + +#define DIO24_SIZE 4 // size of io region used by board + +static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dio24_detach(struct comedi_device * dev); + +enum dio24_bustype { pcmcia_bustype }; + +typedef struct dio24_board_struct { + const char *name; + int device_id; // device id for pcmcia board + enum dio24_bustype bustype; // PCMCIA + int have_dio; // have 8255 chip + // function pointers so we can use inb/outb or readb/writeb as appropriate + unsigned int (*read_byte) (unsigned int address); + void (*write_byte) (unsigned int byte, unsigned int address); +} dio24_board; + +static const dio24_board dio24_boards[] = { + { + name: "daqcard-dio24", + device_id:0x475c,// 0x10b is manufacturer id, 0x475c is device id + bustype: pcmcia_bustype, + have_dio:1, + }, + { + name: "ni_daq_dio24", + device_id:0x475c,// 0x10b is manufacturer id, 0x475c is device id + bustype: pcmcia_bustype, + have_dio:1, + }, +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const dio24_board *)dev->board_ptr) + +struct dio24_private { + + int data; /* number of data points left to be taken */ +}; + + +#define devpriv ((struct dio24_private *)dev->private) + +static struct comedi_driver driver_dio24 = { + driver_name:"ni_daq_dio24", + module:THIS_MODULE, + attach:dio24_attach, + detach:dio24_detach, + num_names:sizeof(dio24_boards) / sizeof(dio24_board), + board_name:&dio24_boards[0].name, + offset:sizeof(dio24_board), +}; + +static int dio24_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase = 0; +#ifdef incomplete + unsigned int irq = 0; +#endif + struct pcmcia_device *link; + + /* allocate and initialize dev->private */ + if (alloc_private(dev, sizeof(struct dio24_private)) < 0) + return -ENOMEM; + + // get base address, irq etc. based on bustype + switch (thisboard->bustype) { + case pcmcia_bustype: + link = pcmcia_cur_dev; /* XXX hack */ + if (!link) + return -EIO; + iobase = link->io.BasePort1; +#ifdef incomplete + irq = link->irq.AssignedIRQ; +#endif + break; + default: + printk("bug! couldn't determine board type\n"); + return -EINVAL; + break; + } + printk("comedi%d: ni_daq_dio24: %s, io 0x%lx", dev->minor, + thisboard->name, iobase); +#ifdef incomplete + if (irq) { + printk(", irq %u", irq); + } +#endif + + printk("\n"); + + if (iobase == 0) { + printk("io base address is zero!\n"); + return -EINVAL; + } + + dev->iobase = iobase; + +#ifdef incomplete + /* grab our IRQ */ + dev->irq = irq; +#endif + + dev->board_name = thisboard->name; + + if (alloc_subdevices(dev, 1) < 0) + return -ENOMEM; + + /* 8255 dio */ + s = dev->subdevices + 0; + subdev_8255_init(dev, s, NULL, dev->iobase); + + return 0; +}; + +static int dio24_detach(struct comedi_device * dev) +{ + printk("comedi%d: ni_daq_dio24: remove\n", dev->minor); + + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 0); + + if (thisboard->bustype != pcmcia_bustype && dev->iobase) + release_region(dev->iobase, DIO24_SIZE); + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + return 0; +}; + +// PCMCIA crap + +/* + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + you do not define PCMCIA_DEBUG at all, all the debug code will be + left out. If you compile with PCMCIA_DEBUG=0, the debug code will + be present but disabled -- but it can then be enabled for specific + modules at load time with a 'pc_debug=#' option to insmod. +*/ +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +module_param(pc_debug, int, 0644); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = "ni_daq_dio24.c, based on dummy_cs.c"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +static void dio24_config(struct pcmcia_device *link); +static void dio24_release(struct pcmcia_device *link); +static int dio24_cs_suspend(struct pcmcia_device *p_dev); +static int dio24_cs_resume(struct pcmcia_device *p_dev); + +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static int dio24_cs_attach(struct pcmcia_device *); +static void dio24_cs_detach(struct pcmcia_device *); + +/* + You'll also need to prototype all the functions that will actually + be used to talk to your device. See 'memory_cs' for a good example + of a fully self-sufficient driver; the other drivers rely more or + less on other parts of the kernel. +*/ + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static const dev_info_t dev_info = "ni_daq_dio24"; + +typedef struct local_info_t { + struct pcmcia_device *link; + dev_node_t node; + int stop; + struct bus_operations *bus; +} local_info_t; + +/*====================================================================== + + dio24_cs_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + +======================================================================*/ + +static int dio24_cs_attach(struct pcmcia_device *link) +{ + local_info_t *local; + + printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n"); + + DEBUG(0, "dio24_cs_attach()\n"); + + /* Allocate space for private device-specific data */ + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); + if (!local) + return -ENOMEM; + local->link = link; + link->priv = local; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->irq.Handler = NULL; + + /* + General socket configuration defaults can go here. In this + client, we assume very little, and rely on the CIS for almost + everything. In most clients, many details (i.e., number, sizes, + and attributes of IO windows) are fixed by the nature of the + device, and can be hard-wired here. + */ + link->conf.Attributes = 0; + link->conf.IntType = INT_MEMORY_AND_IO; + + pcmcia_cur_dev = link; + + dio24_config(link); + + return 0; +} /* dio24_cs_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void dio24_cs_detach(struct pcmcia_device *link) +{ + + printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - cs-detach!\n"); + + DEBUG(0, "dio24_cs_detach(0x%p)\n", link); + + if (link->dev_node) { + ((local_info_t *) link->priv)->stop = 1; + dio24_release(link); + } + + /* This points to the parent local_info_t struct */ + if (link->priv) + kfree(link->priv); + +} /* dio24_cs_detach */ + +/*====================================================================== + + dio24_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + device available to the system. + +======================================================================*/ + +static void dio24_config(struct pcmcia_device *link) +{ + local_info_t *dev = link->priv; + tuple_t tuple; + cisparse_t parse; + int last_ret; + u_char buf[64]; + win_req_t req; + memreq_t map; + cistpl_cftable_entry_t dflt = { 0 }; + + printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n"); + + DEBUG(0, "dio24_config(0x%p)\n", link); + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) { + cs_error(link, GetFirstTuple, last_ret); + goto cs_failed; + } + if ((last_ret = pcmcia_get_tuple_data(link, &tuple)) != 0) { + cs_error(link, GetTupleData, last_ret); + goto cs_failed; + } + if ((last_ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) { + cs_error(link, ParseTuple, last_ret); + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* + In this loop, we scan the CIS for configuration table entries, + each of which describes a valid card configuration, including + voltage, IO window, memory window, and interrupt settings. + + We make no assumptions about the card to be configured: we use + just the information available in the CIS. In an ideal world, + this would work for any PCMCIA card, but it requires a complete + and accurate CIS. In practice, a driver usually "knows" most of + these things without consulting the CIS, and most client drivers + will only use the CIS to fill in implementation-defined details. + */ + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple)) != 0) { + cs_error(link, GetFirstTuple, last_ret); + goto cs_failed; + } + while (1) { + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + if (pcmcia_get_tuple_data(link, &tuple) != 0) + goto next_entry; + if (pcmcia_parse_tuple(&tuple, &parse) != 0) + goto next_entry; + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + if (cfg->index == 0) + goto next_entry; + link->conf.ConfigIndex = cfg->index; + + /* Does this card need audio output? */ + if (cfg->flags & CISTPL_CFTABLE_AUDIO) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + /* This reserves IO space but doesn't actually enable it */ + if (pcmcia_request_io(link, &link->io) != 0) + goto next_entry; + } + + if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { + cistpl_mem_t *mem = + (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; + req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; + req.Attributes |= WIN_ENABLE; + req.Base = mem->win[0].host_addr; + req.Size = mem->win[0].len; + if (req.Size < 0x1000) + req.Size = 0x1000; + req.AccessSpeed = 0; + if (pcmcia_request_window(&link, &req, &link->win)) + goto next_entry; + map.Page = 0; + map.CardOffset = mem->win[0].card_addr; + if (pcmcia_map_mem_page(link->win, &map)) + goto next_entry; + } + /* If we got this far, we're cool! */ + break; + + next_entry: + if ((last_ret = pcmcia_get_next_tuple(link, &tuple)) != 0) { + cs_error(link, GetNextTuple, last_ret); + goto cs_failed; + } + } + + /* + Allocate an interrupt line. Note that this does not assign a + handler to the interrupt, unless the 'Handler' member of the + irq structure is initialized. + */ + if (link->conf.Attributes & CONF_ENABLE_IRQ) + if ((last_ret = pcmcia_request_irq(link, &link->irq)) != 0) { + cs_error(link, RequestIRQ, last_ret); + goto cs_failed; + } + + /* + This actually configures the PCMCIA socket -- setting up + the I/O windows and the interrupt mapping, and putting the + card and host interface into "Memory and IO" mode. + */ + if ((last_ret = pcmcia_request_configuration(link, &link->conf)) != 0) { + cs_error(link, RequestConfiguration, last_ret); + goto cs_failed; + } + + /* + At this point, the dev_node_t structure(s) need to be + initialized and arranged in a linked list at link->dev. + */ + sprintf(dev->node.dev_name, "ni_daq_dio24"); + dev->node.major = dev->node.minor = 0; + link->dev_node = &dev->node; + + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %d", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1 + link->io.NumPorts1 - 1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->win) + printk(", mem 0x%06lx-0x%06lx", req.Base, + req.Base + req.Size - 1); + printk("\n"); + + return; + + cs_failed: + printk(KERN_INFO "Fallo"); + dio24_release(link); + +} /* dio24_config */ + +static void dio24_release(struct pcmcia_device *link) +{ + DEBUG(0, "dio24_release(0x%p)\n", link); + + pcmcia_disable_device(link); +} /* dio24_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. + + When a CARD_REMOVAL event is received, we immediately set a + private flag to block future accesses to this device. All the + functions that actually access the device should check this flag + to make sure the card is still present. + +======================================================================*/ + +static int dio24_cs_suspend(struct pcmcia_device *link) +{ + local_info_t *local = link->priv; + + /* Mark the device as stopped, to block IO until later */ + local->stop = 1; + return 0; +} /* dio24_cs_suspend */ + +static int dio24_cs_resume(struct pcmcia_device *link) +{ + local_info_t *local = link->priv; + + local->stop = 0; + return 0; +} /* dio24_cs_resume */ + +/*====================================================================*/ + +static struct pcmcia_device_id dio24_cs_ids[] = { + /* N.B. These IDs should match those in dio24_boards */ + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x475c), /* daqcard-dio24 */ + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, dio24_cs_ids); + +struct pcmcia_driver dio24_cs_driver = { + .probe = dio24_cs_attach, + .remove = dio24_cs_detach, + .suspend = dio24_cs_suspend, + .resume = dio24_cs_resume, + .id_table = dio24_cs_ids, + .owner = THIS_MODULE, + .drv = { + .name = dev_info, + }, +}; + +static int __init init_dio24_cs(void) +{ + printk("ni_daq_dio24: HOLA SOY YO!\n"); + DEBUG(0, "%s\n", version); + pcmcia_register_driver(&dio24_cs_driver); + return 0; +} + +static void __exit exit_dio24_cs(void) +{ + DEBUG(0, "ni_dio24: unloading\n"); + pcmcia_unregister_driver(&dio24_cs_driver); +} + +int __init init_module(void) +{ + int ret; + + ret = init_dio24_cs(); + if (ret < 0) + return ret; + + return comedi_driver_register(&driver_dio24); +} + +void __exit cleanup_module(void) +{ + exit_dio24_cs(); + comedi_driver_unregister(&driver_dio24); +} diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c new file mode 100644 index 000000000000..37898d8474cd --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -0,0 +1,2005 @@ +/* + comedi/drivers/ni_labpc.c + Driver for National Instruments Lab-PC series boards and compatibles + Copyright (C) 2001, 2002, 2003 Frank Mori Hess + + 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: ni_labpc +Description: National Instruments Lab-PC (& compatibles) +Author: Frank Mori Hess +Devices: [National Instruments] Lab-PC-1200 (labpc-1200), + Lab-PC-1200AI (labpc-1200ai), Lab-PC+ (lab-pc+), PCI-1200 (ni_labpc) +Status: works + +Tested with lab-pc-1200. For the older Lab-PC+, not all input ranges +and analog references will work, the available ranges/arefs will +depend on how you have configured the jumpers on your board +(see your owner's manual). + +Kernel-level ISA plug-and-play support for the lab-pc-1200 +boards has not +yet been added to the driver, mainly due to the fact that +I don't know the device id numbers. If you have one +of these boards, +please file a bug report at https://bugs.comedi.org/ +so I can get the necessary information from you. + +The 1200 series boards have onboard calibration dacs for correcting +analog input/output offsets and gains. The proper settings for these +caldacs are stored on the board's eeprom. To read the caldac values +from the eeprom and store them into a file that can be then be used by +comedilib, use the comedi_calibrate program. + +Configuration options - ISA boards: + [0] - I/O port base address + [1] - IRQ (optional, required for timed or externally triggered conversions) + [2] - DMA channel (optional) + +Configuration options - PCI boards: + [0] - bus (optional) + [1] - slot (optional) + +The Lab-pc+ has quirky chanlist requirements +when scanning multiple channels. Multiple channel scan +sequence must start at highest channel, then decrement down to +channel 0. The rest of the cards can scan down like lab-pc+ or scan +up from channel zero. Chanlists consisting of all one channel +are also legal, and allow you to pace conversions in bursts. + +*/ + +/* + +NI manuals: +341309a (labpc-1200 register manual) +340914a (pci-1200) +320502b (lab-pc+) + +*/ + +#undef LABPC_DEBUG +//#define LABPC_DEBUG // enable debugging messages + +#include "../comedidev.h" + +#include +#include + +#include "8253.h" +#include "8255.h" +#include "mite.h" +#include "comedi_fc.h" +#include "ni_labpc.h" + +#define DRV_NAME "ni_labpc" + +#define LABPC_SIZE 32 // size of io region used by board +#define LABPC_TIMER_BASE 500 // 2 MHz master clock + +/* Registers for the lab-pc+ */ + +//write-only registers +#define COMMAND1_REG 0x0 +#define ADC_GAIN_MASK (0x7 << 4) +#define ADC_CHAN_BITS(x) ((x) & 0x7) +#define ADC_SCAN_EN_BIT 0x80 // enables multi channel scans +#define COMMAND2_REG 0x1 +#define PRETRIG_BIT 0x1 // enable pretriggering (used in conjunction with SWTRIG) +#define HWTRIG_BIT 0x2 // enable paced conversions on external trigger +#define SWTRIG_BIT 0x4 // enable paced conversions +#define CASCADE_BIT 0x8 // use two cascaded counters for pacing +#define DAC_PACED_BIT(channel) (0x40 << ((channel) & 0x1)) +#define COMMAND3_REG 0x2 +#define DMA_EN_BIT 0x1 // enable dma transfers +#define DIO_INTR_EN_BIT 0x2 // enable interrupts for 8255 +#define DMATC_INTR_EN_BIT 0x4 // enable dma terminal count interrupt +#define TIMER_INTR_EN_BIT 0x8 // enable timer interrupt +#define ERR_INTR_EN_BIT 0x10 // enable error interrupt +#define ADC_FNE_INTR_EN_BIT 0x20 // enable fifo not empty interrupt +#define ADC_CONVERT_REG 0x3 +#define DAC_LSB_REG(channel) (0x4 + 2 * ((channel) & 0x1)) +#define DAC_MSB_REG(channel) (0x5 + 2 * ((channel) & 0x1)) +#define ADC_CLEAR_REG 0x8 +#define DMATC_CLEAR_REG 0xa +#define TIMER_CLEAR_REG 0xc +#define COMMAND6_REG 0xe // 1200 boards only +#define ADC_COMMON_BIT 0x1 // select ground or common-mode reference +#define ADC_UNIP_BIT 0x2 // adc unipolar +#define DAC_UNIP_BIT(channel) (0x4 << ((channel) & 0x1)) // dac unipolar +#define ADC_FHF_INTR_EN_BIT 0x20 // enable fifo half full interrupt +#define A1_INTR_EN_BIT 0x40 // enable interrupt on end of hardware count +#define ADC_SCAN_UP_BIT 0x80 // scan up from channel zero instead of down to zero +#define COMMAND4_REG 0xf +#define INTERVAL_SCAN_EN_BIT 0x1 // enables 'interval' scanning +#define EXT_SCAN_EN_BIT 0x2 // enables external signal on counter b1 output to trigger scan +#define EXT_CONVERT_OUT_BIT 0x4 // chooses direction (output or input) for EXTCONV* line +#define ADC_DIFF_BIT 0x8 // chooses differential inputs for adc (in conjunction with board jumper) +#define EXT_CONVERT_DISABLE_BIT 0x10 +#define COMMAND5_REG 0x1c // 1200 boards only, calibration stuff +#define EEPROM_WRITE_UNPROTECT_BIT 0x4 // enable eeprom for write +#define DITHER_EN_BIT 0x8 // enable dithering +#define CALDAC_LOAD_BIT 0x10 // load calibration dac +#define SCLOCK_BIT 0x20 // serial clock - rising edge writes, falling edge reads +#define SDATA_BIT 0x40 // serial data bit for writing to eeprom or calibration dacs +#define EEPROM_EN_BIT 0x80 // enable eeprom for read/write +#define INTERVAL_COUNT_REG 0x1e +#define INTERVAL_LOAD_REG 0x1f +#define INTERVAL_LOAD_BITS 0x1 + +// read-only registers +#define STATUS1_REG 0x0 +#define DATA_AVAIL_BIT 0x1 // data is available in fifo +#define OVERRUN_BIT 0x2 // overrun has occurred +#define OVERFLOW_BIT 0x4 // fifo overflow +#define TIMER_BIT 0x8 // timer interrupt has occured +#define DMATC_BIT 0x10 // dma terminal count has occured +#define EXT_TRIG_BIT 0x40 // external trigger has occured +#define STATUS2_REG 0x1d // 1200 boards only +#define EEPROM_OUT_BIT 0x1 // programmable eeprom serial output +#define A1_TC_BIT 0x2 // counter A1 terminal count +#define FNHF_BIT 0x4 // fifo not half full +#define ADC_FIFO_REG 0xa + +#define DIO_BASE_REG 0x10 +#define COUNTER_A_BASE_REG 0x14 +#define COUNTER_A_CONTROL_REG (COUNTER_A_BASE_REG + 0x3) +#define INIT_A0_BITS 0x14 // check modes put conversion pacer output in harmless state (a0 mode 2) +#define INIT_A1_BITS 0x70 // put hardware conversion counter output in harmless state (a1 mode 0) +#define COUNTER_B_BASE_REG 0x18 + +static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int labpc_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG); +static int labpc_drain_fifo(struct comedi_device * dev); +static void labpc_drain_dma(struct comedi_device * dev); +static void handle_isa_dma(struct comedi_device * dev); +static void labpc_drain_dregs(struct comedi_device * dev); +static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int labpc_calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd); +static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd); +#ifdef CONFIG_COMEDI_PCI +static int labpc_find_device(struct comedi_device *dev, int bus, int slot); +#endif +static int labpc_dio_mem_callback(int dir, int port, int data, + unsigned long arg); +static void labpc_serial_out(struct comedi_device * dev, unsigned int value, + unsigned int num_bits); +static unsigned int labpc_serial_in(struct comedi_device * dev); +static unsigned int labpc_eeprom_read(struct comedi_device * dev, + unsigned int address); +static unsigned int labpc_eeprom_read_status(struct comedi_device * dev); +static unsigned int labpc_eeprom_write(struct comedi_device * dev, + unsigned int address, unsigned int value); +static void write_caldac(struct comedi_device * dev, unsigned int channel, + unsigned int value); + +enum scan_mode { + MODE_SINGLE_CHAN, + MODE_SINGLE_CHAN_INTERVAL, + MODE_MULT_CHAN_UP, + MODE_MULT_CHAN_DOWN, +}; + +//analog input ranges +#define NUM_LABPC_PLUS_AI_RANGES 16 +// indicates unipolar ranges +static const int labpc_plus_is_unipolar[NUM_LABPC_PLUS_AI_RANGES] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; + +// map range index to gain bits +static const int labpc_plus_ai_gain_bits[NUM_LABPC_PLUS_AI_RANGES] = { + 0x00, + 0x10, + 0x20, + 0x30, + 0x40, + 0x50, + 0x60, + 0x70, + 0x00, + 0x10, + 0x20, + 0x30, + 0x40, + 0x50, + 0x60, + 0x70, +}; +static const struct comedi_lrange range_labpc_plus_ai = { + NUM_LABPC_PLUS_AI_RANGES, + { + BIP_RANGE(5), + BIP_RANGE(4), + BIP_RANGE(2.5), + BIP_RANGE(1), + BIP_RANGE(0.5), + BIP_RANGE(0.25), + BIP_RANGE(0.1), + BIP_RANGE(0.05), + UNI_RANGE(10), + UNI_RANGE(8), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1), + UNI_RANGE(0.5), + UNI_RANGE(0.2), + UNI_RANGE(0.1), + } +}; + +#define NUM_LABPC_1200_AI_RANGES 14 +// indicates unipolar ranges +const int labpc_1200_is_unipolar[NUM_LABPC_1200_AI_RANGES] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; + +// map range index to gain bits +const int labpc_1200_ai_gain_bits[NUM_LABPC_1200_AI_RANGES] = { + 0x00, + 0x20, + 0x30, + 0x40, + 0x50, + 0x60, + 0x70, + 0x00, + 0x20, + 0x30, + 0x40, + 0x50, + 0x60, + 0x70, +}; +const struct comedi_lrange range_labpc_1200_ai = { + NUM_LABPC_1200_AI_RANGES, + { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1), + BIP_RANGE(0.5), + BIP_RANGE(0.25), + BIP_RANGE(0.1), + BIP_RANGE(0.05), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1), + UNI_RANGE(0.5), + UNI_RANGE(0.2), + UNI_RANGE(0.1), + } +}; + +//analog output ranges +#define AO_RANGE_IS_UNIPOLAR 0x1 +static const struct comedi_lrange range_labpc_ao = { + 2, + { + BIP_RANGE(5), + UNI_RANGE(10), + } +}; + +/* functions that do inb/outb and readb/writeb so we can use + * function pointers to decide which to use */ +static inline unsigned int labpc_inb(unsigned long address) +{ + return inb(address); +} +static inline void labpc_outb(unsigned int byte, unsigned long address) +{ + outb(byte, address); +} +static inline unsigned int labpc_readb(unsigned long address) +{ + return readb((void *)address); +} +static inline void labpc_writeb(unsigned int byte, unsigned long address) +{ + writeb(byte, (void *)address); +} + +static const labpc_board labpc_boards[] = { + { + name: "lab-pc-1200", + ai_speed:10000, + bustype: isa_bustype, + register_layout:labpc_1200_layout, + has_ao: 1, + ai_range_table:&range_labpc_1200_ai, + ai_range_code:labpc_1200_ai_gain_bits, + ai_range_is_unipolar:labpc_1200_is_unipolar, + ai_scan_up:1, + memory_mapped_io:0, + }, + { + name: "lab-pc-1200ai", + ai_speed:10000, + bustype: isa_bustype, + register_layout:labpc_1200_layout, + has_ao: 0, + ai_range_table:&range_labpc_1200_ai, + ai_range_code:labpc_1200_ai_gain_bits, + ai_range_is_unipolar:labpc_1200_is_unipolar, + ai_scan_up:1, + memory_mapped_io:0, + }, + { + name: "lab-pc+", + ai_speed:12000, + bustype: isa_bustype, + register_layout:labpc_plus_layout, + has_ao: 1, + ai_range_table:&range_labpc_plus_ai, + ai_range_code:labpc_plus_ai_gain_bits, + ai_range_is_unipolar:labpc_plus_is_unipolar, + ai_scan_up:0, + memory_mapped_io:0, + }, +#ifdef CONFIG_COMEDI_PCI + { + name: "pci-1200", + device_id:0x161, + ai_speed:10000, + bustype: pci_bustype, + register_layout:labpc_1200_layout, + has_ao: 1, + ai_range_table:&range_labpc_1200_ai, + ai_range_code:labpc_1200_ai_gain_bits, + ai_range_is_unipolar:labpc_1200_is_unipolar, + ai_scan_up:1, + memory_mapped_io:1, + }, + // dummy entry so pci board works when comedi_config is passed driver name + { + .name = DRV_NAME, + .bustype = pci_bustype, + }, +#endif +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((labpc_board *)dev->board_ptr) + +static const int dma_buffer_size = 0xff00; // size in bytes of dma buffer +static const int sample_size = 2; // 2 bytes per sample + +#define devpriv ((labpc_private *)dev->private) + +static struct comedi_driver driver_labpc = { + .driver_name = DRV_NAME, + .module = THIS_MODULE, + .attach = labpc_attach, + .detach = labpc_common_detach, + .num_names = sizeof(labpc_boards) / sizeof(labpc_board), + .board_name = &labpc_boards[0].name, + .offset = sizeof(labpc_board), +}; + +#ifdef CONFIG_COMEDI_PCI +static DEFINE_PCI_DEVICE_TABLE(labpc_pci_table) = { + {PCI_VENDOR_ID_NATINST, 0x161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, labpc_pci_table); +#endif /* CONFIG_COMEDI_PCI */ + +static inline int labpc_counter_load(struct comedi_device * dev, + unsigned long base_address, unsigned int counter_number, + unsigned int count, unsigned int mode) +{ + if (thisboard->memory_mapped_io) + return i8254_mm_load((void *)base_address, 0, counter_number, + count, mode); + else + return i8254_load(base_address, 0, counter_number, count, mode); +} + +int labpc_common_attach(struct comedi_device * dev, unsigned long iobase, + unsigned int irq, unsigned int dma_chan) +{ + struct comedi_subdevice *s; + int i; + unsigned long dma_flags, isr_flags; + short lsb, msb; + + printk("comedi%d: ni_labpc: %s, io 0x%lx", dev->minor, thisboard->name, + iobase); + if (irq) { + printk(", irq %u", irq); + } + if (dma_chan) { + printk(", dma %u", dma_chan); + } + printk("\n"); + + if (iobase == 0) { + printk("io base address is zero!\n"); + return -EINVAL; + } + // request io regions for isa boards + if (thisboard->bustype == isa_bustype) { + /* check if io addresses are available */ + if (!request_region(iobase, LABPC_SIZE, + driver_labpc.driver_name)) { + printk("I/O port conflict\n"); + return -EIO; + } + } + dev->iobase = iobase; + + if (thisboard->memory_mapped_io) { + devpriv->read_byte = labpc_readb; + devpriv->write_byte = labpc_writeb; + } else { + devpriv->read_byte = labpc_inb; + devpriv->write_byte = labpc_outb; + } + // initialize board's command registers + devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); + devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); + devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); + if (thisboard->register_layout == labpc_1200_layout) { + devpriv->write_byte(devpriv->command5_bits, + dev->iobase + COMMAND5_REG); + devpriv->write_byte(devpriv->command6_bits, + dev->iobase + COMMAND6_REG); + } + + /* grab our IRQ */ + if (irq) { + isr_flags = 0; + if (thisboard->bustype == pci_bustype) + isr_flags |= IRQF_SHARED; + if (comedi_request_irq(irq, labpc_interrupt, isr_flags, + driver_labpc.driver_name, dev)) { + printk("unable to allocate irq %u\n", irq); + return -EINVAL; + } + } + dev->irq = irq; + + // grab dma channel + if (dma_chan > 3) { + printk(" invalid dma channel %u\n", dma_chan); + return -EINVAL; + } else if (dma_chan) { + // allocate dma buffer + devpriv->dma_buffer = + kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA); + if (devpriv->dma_buffer == NULL) { + printk(" failed to allocate dma buffer\n"); + return -ENOMEM; + } + if (request_dma(dma_chan, driver_labpc.driver_name)) { + printk(" failed to allocate dma channel %u\n", + dma_chan); + return -EINVAL; + } + devpriv->dma_chan = dma_chan; + dma_flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); + release_dma_lock(dma_flags); + } + + dev->board_name = thisboard->name; + + if (alloc_subdevices(dev, 5) < 0) + return -ENOMEM; + + /* analog input subdevice */ + s = dev->subdevices + 0; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = + SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | + SDF_CMD_READ; + s->n_chan = 8; + s->len_chanlist = 8; + s->maxdata = (1 << 12) - 1; // 12 bit resolution + s->range_table = thisboard->ai_range_table; + s->do_cmd = labpc_ai_cmd; + s->do_cmdtest = labpc_ai_cmdtest; + s->insn_read = labpc_ai_rinsn; + s->cancel = labpc_cancel; + + /* analog output */ + s = dev->subdevices + 1; + if (thisboard->has_ao) { +/* Could provide command support, except it only has a one sample + * hardware buffer for analog output and no underrun flag. */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; + s->n_chan = NUM_AO_CHAN; + s->maxdata = (1 << 12) - 1; // 12 bit resolution + s->range_table = &range_labpc_ao; + s->insn_read = labpc_ao_rinsn; + s->insn_write = labpc_ao_winsn; + /* initialize analog outputs to a known value */ + for (i = 0; i < s->n_chan; i++) { + devpriv->ao_value[i] = s->maxdata / 2; + lsb = devpriv->ao_value[i] & 0xff; + msb = (devpriv->ao_value[i] >> 8) & 0xff; + devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(i)); + devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(i)); + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* 8255 dio */ + s = dev->subdevices + 2; + // if board uses io memory we have to give a custom callback function to the 8255 driver + if (thisboard->memory_mapped_io) + subdev_8255_init(dev, s, labpc_dio_mem_callback, + (unsigned long)(dev->iobase + DIO_BASE_REG)); + else + subdev_8255_init(dev, s, NULL, dev->iobase + DIO_BASE_REG); + + // calibration subdevices for boards that have one + s = dev->subdevices + 3; + if (thisboard->register_layout == labpc_1200_layout) { + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 16; + s->maxdata = 0xff; + s->insn_read = labpc_calib_read_insn; + s->insn_write = labpc_calib_write_insn; + + for (i = 0; i < s->n_chan; i++) + write_caldac(dev, i, s->maxdata / 2); + } else + s->type = COMEDI_SUBD_UNUSED; + + /* EEPROM */ + s = dev->subdevices + 4; + if (thisboard->register_layout == labpc_1200_layout) { + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = EEPROM_SIZE; + s->maxdata = 0xff; + s->insn_read = labpc_eeprom_read_insn; + s->insn_write = labpc_eeprom_write_insn; + + for (i = 0; i < EEPROM_SIZE; i++) { + devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i); + } +#ifdef LABPC_DEBUG + printk(" eeprom:"); + for (i = 0; i < EEPROM_SIZE; i++) { + printk(" %i:0x%x ", i, devpriv->eeprom_data[i]); + } + printk("\n"); +#endif + } else + s->type = COMEDI_SUBD_UNUSED; + + return 0; +} + +static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + unsigned long iobase = 0; + unsigned int irq = 0; + unsigned int dma_chan = 0; +#ifdef CONFIG_COMEDI_PCI + int retval; +#endif + + /* allocate and initialize dev->private */ + if (alloc_private(dev, sizeof(labpc_private)) < 0) + return -ENOMEM; + + // get base address, irq etc. based on bustype + switch (thisboard->bustype) { + case isa_bustype: + iobase = it->options[0]; + irq = it->options[1]; + dma_chan = it->options[2]; + break; + case pci_bustype: +#ifdef CONFIG_COMEDI_PCI + retval = labpc_find_device(dev, it->options[0], it->options[1]); + if (retval < 0) { + return retval; + } + retval = mite_setup(devpriv->mite); + if (retval < 0) + return retval; + iobase = (unsigned long)devpriv->mite->daq_io_addr; + irq = mite_irq(devpriv->mite); +#else + printk(" this driver has not been built with PCI support.\n"); + return -EINVAL; +#endif + break; + case pcmcia_bustype: + printk(" this driver does not support pcmcia cards, use ni_labpc_cs.o\n"); + return -EINVAL; + break; + default: + printk("bug! couldn't determine board type\n"); + return -EINVAL; + break; + } + + return labpc_common_attach(dev, iobase, irq, dma_chan); +} + +// adapted from ni_pcimio for finding mite based boards (pc-1200) +#ifdef CONFIG_COMEDI_PCI +static int labpc_find_device(struct comedi_device *dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + // if bus/slot are specified then make sure we have the right bus/slot + if (bus || slot) { + if (bus != mite->pcidev->bus->number + || slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + for (i = 0; i < driver_labpc.num_names; i++) { + if (labpc_boards[i].bustype != pci_bustype) + continue; + if (mite_device_id(mite) == labpc_boards[i].device_id) { + devpriv->mite = mite; + // fixup board pointer, in case we were using the dummy "ni_labpc" entry + dev->board_ptr = &labpc_boards[i]; + return 0; + } + } + } + printk("no device found\n"); + mite_list_devices(); + return -EIO; +} +#endif + +int labpc_common_detach(struct comedi_device * dev) +{ + printk("comedi%d: ni_labpc: detach\n", dev->minor); + + if (dev->subdevices) + subdev_8255_cleanup(dev, dev->subdevices + 2); + + /* only free stuff if it has been allocated by _attach */ + if (devpriv->dma_buffer) + kfree(devpriv->dma_buffer); + if (devpriv->dma_chan) + free_dma(devpriv->dma_chan); + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (thisboard->bustype == isa_bustype && dev->iobase) + release_region(dev->iobase, LABPC_SIZE); +#ifdef CONFIG_COMEDI_PCI + if (devpriv->mite) + mite_unsetup(devpriv->mite); +#endif + + return 0; +}; + +static void labpc_clear_adc_fifo(const struct comedi_device * dev) +{ + devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG); + devpriv->read_byte(dev->iobase + ADC_FIFO_REG); + devpriv->read_byte(dev->iobase + ADC_FIFO_REG); +} + +static int labpc_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; + devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + devpriv->command3_bits = 0; + devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + + return 0; +} + +static enum scan_mode labpc_ai_scan_mode(const struct comedi_cmd * cmd) +{ + if (cmd->chanlist_len == 1) + return MODE_SINGLE_CHAN; + + /* chanlist may be NULL during cmdtest. */ + if (cmd->chanlist == NULL) + return MODE_MULT_CHAN_UP; + + if (CR_CHAN(cmd->chanlist[0]) == CR_CHAN(cmd->chanlist[1])) + return MODE_SINGLE_CHAN_INTERVAL; + + if (CR_CHAN(cmd->chanlist[0]) < CR_CHAN(cmd->chanlist[1])) + return MODE_MULT_CHAN_UP; + + if (CR_CHAN(cmd->chanlist[0]) > CR_CHAN(cmd->chanlist[1])) + return MODE_MULT_CHAN_DOWN; + + rt_printk("ni_labpc: bug! this should never happen\n"); + + return 0; +} + +static int labpc_ai_chanlist_invalid(const struct comedi_device * dev, + const struct comedi_cmd * cmd) +{ + int mode, channel, range, aref, i; + + if (cmd->chanlist == NULL) + return 0; + + mode = labpc_ai_scan_mode(cmd); + + if (mode == MODE_SINGLE_CHAN) + return 0; + + if (mode == MODE_SINGLE_CHAN_INTERVAL) { + if (cmd->chanlist_len > 0xff) { + comedi_error(dev, + "ni_labpc: chanlist too long for single channel interval mode\n"); + return 1; + } + } + + channel = CR_CHAN(cmd->chanlist[0]); + range = CR_RANGE(cmd->chanlist[0]); + aref = CR_AREF(cmd->chanlist[0]); + + for (i = 0; i < cmd->chanlist_len; i++) { + + switch (mode) { + case MODE_SINGLE_CHAN_INTERVAL: + if (CR_CHAN(cmd->chanlist[i]) != channel) { + comedi_error(dev, + "channel scanning order specified in chanlist is not supported by hardware.\n"); + return 1; + } + break; + case MODE_MULT_CHAN_UP: + if (CR_CHAN(cmd->chanlist[i]) != i) { + comedi_error(dev, + "channel scanning order specified in chanlist is not supported by hardware.\n"); + return 1; + } + break; + case MODE_MULT_CHAN_DOWN: + if (CR_CHAN(cmd->chanlist[i]) != + cmd->chanlist_len - i - 1) { + comedi_error(dev, + "channel scanning order specified in chanlist is not supported by hardware.\n"); + return 1; + } + break; + default: + rt_printk("ni_labpc: bug! in chanlist check\n"); + return 1; + break; + } + + if (CR_RANGE(cmd->chanlist[i]) != range) { + comedi_error(dev, + "entries in chanlist must all have the same range\n"); + return 1; + } + + if (CR_AREF(cmd->chanlist[i]) != aref) { + comedi_error(dev, + "entries in chanlist must all have the same reference\n"); + return 1; + } + } + + return 0; +} + +static int labpc_use_continuous_mode(const struct comedi_cmd * cmd) +{ + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN) + return 1; + + if (cmd->scan_begin_src == TRIG_FOLLOW) + return 1; + + return 0; +} + +static unsigned int labpc_ai_convert_period(const struct comedi_cmd * cmd) +{ + if (cmd->convert_src != TRIG_TIMER) + return 0; + + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && + cmd->scan_begin_src == TRIG_TIMER) + return cmd->scan_begin_arg; + + return cmd->convert_arg; +} + +static void labpc_set_ai_convert_period(struct comedi_cmd * cmd, unsigned int ns) +{ + if (cmd->convert_src != TRIG_TIMER) + return; + + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && + cmd->scan_begin_src == TRIG_TIMER) { + cmd->scan_begin_arg = ns; + if (cmd->convert_arg > cmd->scan_begin_arg) + cmd->convert_arg = cmd->scan_begin_arg; + } else + cmd->convert_arg = ns; +} + +static unsigned int labpc_ai_scan_period(const struct comedi_cmd * cmd) +{ + if (cmd->scan_begin_src != TRIG_TIMER) + return 0; + + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && + cmd->convert_src == TRIG_TIMER) + return 0; + + return cmd->scan_begin_arg; +} + +static void labpc_set_ai_scan_period(struct comedi_cmd * cmd, unsigned int ns) +{ + if (cmd->scan_begin_src != TRIG_TIMER) + return; + + if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN && + cmd->convert_src == TRIG_TIMER) + return; + + cmd->scan_begin_arg = ns; +} + +static int labpc_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp, tmp2; + int stop_mask; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + 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; + stop_mask = TRIG_COUNT | TRIG_NONE; + if (thisboard->register_layout == labpc_1200_layout) + stop_mask |= TRIG_EXT; + cmd->stop_src &= stop_mask; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && + cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE) + err++; + + // can't have external stop and start triggers at once + if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg == TRIG_NOW && cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + if (!cmd->chanlist_len) { + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < thisboard->ai_speed) { + cmd->convert_arg = thisboard->ai_speed; + err++; + } + } + // make sure scan timing is not too fast + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->convert_src == TRIG_TIMER && + cmd->scan_begin_arg < + cmd->convert_arg * cmd->chanlist_len) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->chanlist_len; + err++; + } + if (cmd->scan_begin_arg < + thisboard->ai_speed * cmd->chanlist_len) { + cmd->scan_begin_arg = + thisboard->ai_speed * cmd->chanlist_len; + err++; + } + } + // stop source + switch (cmd->stop_src) { + case TRIG_COUNT: + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + break; + case TRIG_NONE: + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + break; + // TRIG_EXT doesn't care since it doesn't trigger off a numbered channel + default: + break; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + tmp = cmd->convert_arg; + tmp2 = cmd->scan_begin_arg; + labpc_adc_timing(dev, cmd); + if (tmp != cmd->convert_arg || tmp2 != cmd->scan_begin_arg) + err++; + + if (err) + return 4; + + if (labpc_ai_chanlist_invalid(dev, cmd)) + return 5; + + return 0; +} + +static int labpc_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int channel, range, aref; + unsigned long irq_flags; + int ret; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + enum transfer_type xfer; + unsigned long flags; + + if (!dev->irq) { + comedi_error(dev, "no irq assigned, cannot perform command"); + return -1; + } + + range = CR_RANGE(cmd->chanlist[0]); + aref = CR_AREF(cmd->chanlist[0]); + + // make sure board is disabled before setting up aquisition + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; + devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + devpriv->command3_bits = 0; + devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + + // initialize software conversion count + if (cmd->stop_src == TRIG_COUNT) { + devpriv->count = cmd->stop_arg * cmd->chanlist_len; + } + // setup hardware conversion counter + if (cmd->stop_src == TRIG_EXT) { + // load counter a1 with count of 3 (pc+ manual says this is minimum allowed) using mode 0 + ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, + 1, 3, 0); + if (ret < 0) { + comedi_error(dev, "error loading counter a1"); + return -1; + } + } else // otherwise, just put a1 in mode 0 with no count to set its output low + devpriv->write_byte(INIT_A1_BITS, + dev->iobase + COUNTER_A_CONTROL_REG); + + // figure out what method we will use to transfer data + if (devpriv->dma_chan && // need a dma channel allocated + // dma unsafe at RT priority, and too much setup time for TRIG_WAKE_EOS for + (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0 && + // only available on the isa boards + thisboard->bustype == isa_bustype) { + xfer = isa_dma_transfer; + } else if (thisboard->register_layout == labpc_1200_layout && // pc-plus has no fifo-half full interrupt + // wake-end-of-scan should interrupt on fifo not empty + (cmd->flags & TRIG_WAKE_EOS) == 0 && + // make sure we are taking more than just a few points + (cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) { + xfer = fifo_half_full_transfer; + } else + xfer = fifo_not_empty_transfer; + devpriv->current_transfer = xfer; + + // setup command6 register for 1200 boards + if (thisboard->register_layout == labpc_1200_layout) { + // reference inputs to ground or common? + if (aref != AREF_GROUND) + devpriv->command6_bits |= ADC_COMMON_BIT; + else + devpriv->command6_bits &= ~ADC_COMMON_BIT; + // bipolar or unipolar range? + if (thisboard->ai_range_is_unipolar[range]) + devpriv->command6_bits |= ADC_UNIP_BIT; + else + devpriv->command6_bits &= ~ADC_UNIP_BIT; + // interrupt on fifo half full? + if (xfer == fifo_half_full_transfer) + devpriv->command6_bits |= ADC_FHF_INTR_EN_BIT; + else + devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT; + // enable interrupt on counter a1 terminal count? + if (cmd->stop_src == TRIG_EXT) + devpriv->command6_bits |= A1_INTR_EN_BIT; + else + devpriv->command6_bits &= ~A1_INTR_EN_BIT; + // are we scanning up or down through channels? + if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP) + devpriv->command6_bits |= ADC_SCAN_UP_BIT; + else + devpriv->command6_bits &= ~ADC_SCAN_UP_BIT; + // write to register + devpriv->write_byte(devpriv->command6_bits, + dev->iobase + COMMAND6_REG); + } + + /* setup channel list, etc (command1 register) */ + devpriv->command1_bits = 0; + if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP) + channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); + else + channel = CR_CHAN(cmd->chanlist[0]); + // munge channel bits for differential / scan disabled mode + if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF) + channel *= 2; + devpriv->command1_bits |= ADC_CHAN_BITS(channel); + devpriv->command1_bits |= thisboard->ai_range_code[range]; + devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); + // manual says to set scan enable bit on second pass + if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP || + labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_DOWN) { + devpriv->command1_bits |= ADC_SCAN_EN_BIT; + /* need a brief delay before enabling scan, or scan list will get screwed when you switch + * between scan up to scan down mode - dunno why */ + comedi_udelay(1); + devpriv->write_byte(devpriv->command1_bits, + dev->iobase + COMMAND1_REG); + } + // setup any external triggering/pacing (command4 register) + devpriv->command4_bits = 0; + if (cmd->convert_src != TRIG_EXT) + devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; + /* XXX should discard first scan when using interval scanning + * since manual says it is not synced with scan clock */ + if (labpc_use_continuous_mode(cmd) == 0) { + devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT; + if (cmd->scan_begin_src == TRIG_EXT) + devpriv->command4_bits |= EXT_SCAN_EN_BIT; + } + // single-ended/differential + if (aref == AREF_DIFF) + devpriv->command4_bits |= ADC_DIFF_BIT; + devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); + + devpriv->write_byte(cmd->chanlist_len, + dev->iobase + INTERVAL_COUNT_REG); + // load count + devpriv->write_byte(INTERVAL_LOAD_BITS, + dev->iobase + INTERVAL_LOAD_REG); + + if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) { + // set up pacing + labpc_adc_timing(dev, cmd); + // load counter b0 in mode 3 + ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, + 0, devpriv->divisor_b0, 3); + if (ret < 0) { + comedi_error(dev, "error loading counter b0"); + return -1; + } + } + // set up conversion pacing + if (labpc_ai_convert_period(cmd)) { + // load counter a0 in mode 2 + ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG, + 0, devpriv->divisor_a0, 2); + if (ret < 0) { + comedi_error(dev, "error loading counter a0"); + return -1; + } + } else + devpriv->write_byte(INIT_A0_BITS, + dev->iobase + COUNTER_A_CONTROL_REG); + + // set up scan pacing + if (labpc_ai_scan_period(cmd)) { + // load counter b1 in mode 2 + ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG, + 1, devpriv->divisor_b1, 2); + if (ret < 0) { + comedi_error(dev, "error loading counter b1"); + return -1; + } + } + + labpc_clear_adc_fifo(dev); + + // set up dma transfer + if (xfer == isa_dma_transfer) { + irq_flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + /* clear flip-flop to make sure 2-byte registers for + * count and address get set correctly */ + clear_dma_ff(devpriv->dma_chan); + set_dma_addr(devpriv->dma_chan, + virt_to_bus(devpriv->dma_buffer)); + // set appropriate size of transfer + devpriv->dma_transfer_size = labpc_suggest_transfer_size(*cmd); + if (cmd->stop_src == TRIG_COUNT && + devpriv->count * sample_size < + devpriv->dma_transfer_size) { + devpriv->dma_transfer_size = + devpriv->count * sample_size; + } + set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); + enable_dma(devpriv->dma_chan); + release_dma_lock(irq_flags); + // enable board's dma + devpriv->command3_bits |= DMA_EN_BIT | DMATC_INTR_EN_BIT; + } else + devpriv->command3_bits &= ~DMA_EN_BIT & ~DMATC_INTR_EN_BIT; + + // enable error interrupts + devpriv->command3_bits |= ERR_INTR_EN_BIT; + // enable fifo not empty interrupt? + if (xfer == fifo_not_empty_transfer) + devpriv->command3_bits |= ADC_FNE_INTR_EN_BIT; + else + devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT; + devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + + // startup aquisition + + // command2 reg + // use 2 cascaded counters for pacing + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->command2_bits |= CASCADE_BIT; + switch (cmd->start_src) { + case TRIG_EXT: + devpriv->command2_bits |= HWTRIG_BIT; + devpriv->command2_bits &= ~PRETRIG_BIT & ~SWTRIG_BIT; + break; + case TRIG_NOW: + devpriv->command2_bits |= SWTRIG_BIT; + devpriv->command2_bits &= ~PRETRIG_BIT & ~HWTRIG_BIT; + break; + default: + comedi_error(dev, "bug with start_src"); + return -1; + break; + } + switch (cmd->stop_src) { + case TRIG_EXT: + devpriv->command2_bits |= HWTRIG_BIT | PRETRIG_BIT; + break; + case TRIG_COUNT: + case TRIG_NONE: + break; + default: + comedi_error(dev, "bug with stop_src"); + return -1; + } + devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + return 0; +} + +/* interrupt service routine */ +static irqreturn_t labpc_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async; + struct comedi_cmd *cmd; + + if (dev->attached == 0) { + comedi_error(dev, "premature interrupt"); + return IRQ_HANDLED; + } + + async = s->async; + cmd = &async->cmd; + async->events = 0; + + // read board status + devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG); + if (thisboard->register_layout == labpc_1200_layout) + devpriv->status2_bits = + devpriv->read_byte(dev->iobase + STATUS2_REG); + + if ((devpriv->status1_bits & (DMATC_BIT | TIMER_BIT | OVERFLOW_BIT | + OVERRUN_BIT | DATA_AVAIL_BIT)) == 0 + && (devpriv->status2_bits & A1_TC_BIT) == 0 + && (devpriv->status2_bits & FNHF_BIT)) { + return IRQ_NONE; + } + + if (devpriv->status1_bits & OVERRUN_BIT) { + // clear error interrupt + devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + comedi_event(dev, s); + comedi_error(dev, "overrun"); + return IRQ_HANDLED; + } + + if (devpriv->current_transfer == isa_dma_transfer) { + // if a dma terminal count of external stop trigger has occurred + if (devpriv->status1_bits & DMATC_BIT || + (thisboard->register_layout == labpc_1200_layout + && devpriv->status2_bits & A1_TC_BIT)) { + handle_isa_dma(dev); + } + } else + labpc_drain_fifo(dev); + + if (devpriv->status1_bits & TIMER_BIT) { + comedi_error(dev, "handled timer interrupt?"); + // clear it + devpriv->write_byte(0x1, dev->iobase + TIMER_CLEAR_REG); + } + + if (devpriv->status1_bits & OVERFLOW_BIT) { + // clear error interrupt + devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + comedi_event(dev, s); + comedi_error(dev, "overflow"); + return IRQ_HANDLED; + } + // handle external stop trigger + if (cmd->stop_src == TRIG_EXT) { + if (devpriv->status2_bits & A1_TC_BIT) { + labpc_drain_dregs(dev); + labpc_cancel(dev, s); + async->events |= COMEDI_CB_EOA; + } + } + + /* TRIG_COUNT end of acquisition */ + if (cmd->stop_src == TRIG_COUNT) { + if (devpriv->count == 0) { + labpc_cancel(dev, s); + async->events |= COMEDI_CB_EOA; + } + } + + comedi_event(dev, s); + return IRQ_HANDLED; +} + +// read all available samples from ai fifo +static int labpc_drain_fifo(struct comedi_device * dev) +{ + unsigned int lsb, msb; + short data; + struct comedi_async *async = dev->read_subdev->async; + const int timeout = 10000; + unsigned int i; + + devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG); + + for (i = 0; (devpriv->status1_bits & DATA_AVAIL_BIT) && i < timeout; + i++) { + // quit if we have all the data we want + if (async->cmd.stop_src == TRIG_COUNT) { + if (devpriv->count == 0) + break; + devpriv->count--; + } + lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); + msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); + data = (msb << 8) | lsb; + cfc_write_to_buffer(dev->read_subdev, data); + devpriv->status1_bits = + devpriv->read_byte(dev->iobase + STATUS1_REG); + } + if (i == timeout) { + comedi_error(dev, "ai timeout, fifo never empties"); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + return -1; + } + + return 0; +} + +static void labpc_drain_dma(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async = s->async; + int status; + unsigned long flags; + unsigned int max_points, num_points, residue, leftover; + int i; + + status = devpriv->status1_bits; + + flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + /* clear flip-flop to make sure 2-byte registers for + * count and address get set correctly */ + clear_dma_ff(devpriv->dma_chan); + + // figure out how many points to read + max_points = devpriv->dma_transfer_size / sample_size; + /* residue is the number of points left to be done on the dma + * transfer. It should always be zero at this point unless + * the stop_src is set to external triggering. + */ + residue = get_dma_residue(devpriv->dma_chan) / sample_size; + num_points = max_points - residue; + if (devpriv->count < num_points && async->cmd.stop_src == TRIG_COUNT) + num_points = devpriv->count; + + // figure out how many points will be stored next time + leftover = 0; + if (async->cmd.stop_src != TRIG_COUNT) { + leftover = devpriv->dma_transfer_size / sample_size; + } else if (devpriv->count > num_points) { + leftover = devpriv->count - num_points; + if (leftover > max_points) + leftover = max_points; + } + + /* write data to comedi buffer */ + for (i = 0; i < num_points; i++) { + cfc_write_to_buffer(s, devpriv->dma_buffer[i]); + } + if (async->cmd.stop_src == TRIG_COUNT) + devpriv->count -= num_points; + + // set address and count for next transfer + set_dma_addr(devpriv->dma_chan, virt_to_bus(devpriv->dma_buffer)); + set_dma_count(devpriv->dma_chan, leftover * sample_size); + release_dma_lock(flags); + + async->events |= COMEDI_CB_BLOCK; +} + +static void handle_isa_dma(struct comedi_device * dev) +{ + labpc_drain_dma(dev); + + enable_dma(devpriv->dma_chan); + + // clear dma tc interrupt + devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG); +} + +/* makes sure all data aquired by board is transfered to comedi (used + * when aquisition is terminated by stop_src == TRIG_EXT). */ +static void labpc_drain_dregs(struct comedi_device * dev) +{ + if (devpriv->current_transfer == isa_dma_transfer) + labpc_drain_dma(dev); + + labpc_drain_fifo(dev); +} + +static int labpc_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, n; + int chan, range; + int lsb, msb; + int timeout = 1000; + unsigned long flags; + + // disable timed conversions + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT; + devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // disable interrupt generation and dma + devpriv->command3_bits = 0; + devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + + /* set gain and channel */ + devpriv->command1_bits = 0; + chan = CR_CHAN(insn->chanspec); + range = CR_RANGE(insn->chanspec); + devpriv->command1_bits |= thisboard->ai_range_code[range]; + // munge channel bits for differential/scan disabled mode + if (CR_AREF(insn->chanspec) == AREF_DIFF) + chan *= 2; + devpriv->command1_bits |= ADC_CHAN_BITS(chan); + devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); + + // setup command6 register for 1200 boards + if (thisboard->register_layout == labpc_1200_layout) { + // reference inputs to ground or common? + if (CR_AREF(insn->chanspec) != AREF_GROUND) + devpriv->command6_bits |= ADC_COMMON_BIT; + else + devpriv->command6_bits &= ~ADC_COMMON_BIT; + // bipolar or unipolar range? + if (thisboard->ai_range_is_unipolar[range]) + devpriv->command6_bits |= ADC_UNIP_BIT; + else + devpriv->command6_bits &= ~ADC_UNIP_BIT; + // don't interrupt on fifo half full + devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT; + // don't enable interrupt on counter a1 terminal count? + devpriv->command6_bits &= ~A1_INTR_EN_BIT; + // write to register + devpriv->write_byte(devpriv->command6_bits, + dev->iobase + COMMAND6_REG); + } + // setup command4 register + devpriv->command4_bits = 0; + devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; + // single-ended/differential + if (CR_AREF(insn->chanspec) == AREF_DIFF) + devpriv->command4_bits |= ADC_DIFF_BIT; + devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); + + // initialize pacer counter output to make sure it doesn't cause any problems + devpriv->write_byte(INIT_A0_BITS, dev->iobase + COUNTER_A_CONTROL_REG); + + labpc_clear_adc_fifo(dev); + + for (n = 0; n < insn->n; n++) { + /* trigger conversion */ + devpriv->write_byte(0x1, dev->iobase + ADC_CONVERT_REG); + + for (i = 0; i < timeout; i++) { + if (devpriv->read_byte(dev->iobase + + STATUS1_REG) & DATA_AVAIL_BIT) + break; + comedi_udelay(1); + } + if (i == timeout) { + comedi_error(dev, "timeout"); + return -ETIME; + } + lsb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); + msb = devpriv->read_byte(dev->iobase + ADC_FIFO_REG); + data[n] = (msb << 8) | lsb; + } + + return n; +} + +// analog output insn +static int labpc_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int channel, range; + unsigned long flags; + int lsb, msb; + + channel = CR_CHAN(insn->chanspec); + + // turn off pacing of analog output channel + /* note: hardware bug in daqcard-1200 means pacing cannot + * be independently enabled/disabled for its the two channels */ + comedi_spin_lock_irqsave(&dev->spinlock, flags); + devpriv->command2_bits &= ~DAC_PACED_BIT(channel); + devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG); + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + // set range + if (thisboard->register_layout == labpc_1200_layout) { + range = CR_RANGE(insn->chanspec); + if (range & AO_RANGE_IS_UNIPOLAR) + devpriv->command6_bits |= DAC_UNIP_BIT(channel); + else + devpriv->command6_bits &= ~DAC_UNIP_BIT(channel); + // write to register + devpriv->write_byte(devpriv->command6_bits, + dev->iobase + COMMAND6_REG); + } + // send data + lsb = data[0] & 0xff; + msb = (data[0] >> 8) & 0xff; + devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(channel)); + devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(channel)); + + // remember value for readback + devpriv->ao_value[channel] = data[0]; + + return 1; +} + +// analog output readback insn +static int labpc_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int labpc_calib_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->caldac[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int labpc_calib_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int channel = CR_CHAN(insn->chanspec); + + write_caldac(dev, channel, data[0]); + return 1; +} + +static int labpc_eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->eeprom_data[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int labpc_eeprom_write_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int channel = CR_CHAN(insn->chanspec); + int ret; + + // only allow writes to user area of eeprom + if (channel < 16 || channel > 127) { + printk("eeprom writes are only allowed to channels 16 through 127 (the pointer and user areas)"); + return -EINVAL; + } + + ret = labpc_eeprom_write(dev, channel, data[0]); + if (ret < 0) + return ret; + + return 1; +} + +// utility function that suggests a dma transfer size in bytes +static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd) +{ + unsigned int size; + unsigned int freq; + + if (cmd.convert_src == TRIG_TIMER) + freq = 1000000000 / cmd.convert_arg; + // return some default value + else + freq = 0xffffffff; + + // make buffer fill in no more than 1/3 second + size = (freq / 3) * sample_size; + + // set a minimum and maximum size allowed + if (size > dma_buffer_size) + size = dma_buffer_size - dma_buffer_size % sample_size; + else if (size < sample_size) + size = sample_size; + + return size; +} + +// figures out what counter values to use based on command +static void labpc_adc_timing(struct comedi_device * dev, struct comedi_cmd * cmd) +{ + const int max_counter_value = 0x10000; // max value for 16 bit counter in mode 2 + const int min_counter_value = 2; // min value for 16 bit counter in mode 2 + unsigned int base_period; + + // if both convert and scan triggers are TRIG_TIMER, then they both rely on counter b0 + if (labpc_ai_convert_period(cmd) && labpc_ai_scan_period(cmd)) { + // pick the lowest b0 divisor value we can (for maximum input clock speed on convert and scan counters) + devpriv->divisor_b0 = (labpc_ai_scan_period(cmd) - 1) / + (LABPC_TIMER_BASE * max_counter_value) + 1; + if (devpriv->divisor_b0 < min_counter_value) + devpriv->divisor_b0 = min_counter_value; + if (devpriv->divisor_b0 > max_counter_value) + devpriv->divisor_b0 = max_counter_value; + + base_period = LABPC_TIMER_BASE * devpriv->divisor_b0; + + // set a0 for conversion frequency and b1 for scan frequency + switch (cmd->flags & TRIG_ROUND_MASK) { + default: + case TRIG_ROUND_NEAREST: + devpriv->divisor_a0 = + (labpc_ai_convert_period(cmd) + + (base_period / 2)) / base_period; + devpriv->divisor_b1 = + (labpc_ai_scan_period(cmd) + + (base_period / 2)) / base_period; + break; + case TRIG_ROUND_UP: + devpriv->divisor_a0 = + (labpc_ai_convert_period(cmd) + (base_period - + 1)) / base_period; + devpriv->divisor_b1 = + (labpc_ai_scan_period(cmd) + (base_period - + 1)) / base_period; + break; + case TRIG_ROUND_DOWN: + devpriv->divisor_a0 = + labpc_ai_convert_period(cmd) / base_period; + devpriv->divisor_b1 = + labpc_ai_scan_period(cmd) / base_period; + break; + } + // make sure a0 and b1 values are acceptable + if (devpriv->divisor_a0 < min_counter_value) + devpriv->divisor_a0 = min_counter_value; + if (devpriv->divisor_a0 > max_counter_value) + devpriv->divisor_a0 = max_counter_value; + if (devpriv->divisor_b1 < min_counter_value) + devpriv->divisor_b1 = min_counter_value; + if (devpriv->divisor_b1 > max_counter_value) + devpriv->divisor_b1 = max_counter_value; + // write corrected timings to command + labpc_set_ai_convert_period(cmd, + base_period * devpriv->divisor_a0); + labpc_set_ai_scan_period(cmd, + base_period * devpriv->divisor_b1); + // if only one TRIG_TIMER is used, we can employ the generic cascaded timing functions + } else if (labpc_ai_scan_period(cmd)) { + unsigned int scan_period; + + scan_period = labpc_ai_scan_period(cmd); + /* calculate cascaded counter values that give desired scan timing */ + i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, + &(devpriv->divisor_b1), &(devpriv->divisor_b0), + &scan_period, cmd->flags & TRIG_ROUND_MASK); + labpc_set_ai_scan_period(cmd, scan_period); + } else if (labpc_ai_convert_period(cmd)) { + unsigned int convert_period; + + convert_period = labpc_ai_convert_period(cmd); + /* calculate cascaded counter values that give desired conversion timing */ + i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, + &(devpriv->divisor_a0), &(devpriv->divisor_b0), + &convert_period, cmd->flags & TRIG_ROUND_MASK); + labpc_set_ai_convert_period(cmd, convert_period); + } +} + +static int labpc_dio_mem_callback(int dir, int port, int data, + unsigned long iobase) +{ + if (dir) { + writeb(data, (void *)(iobase + port)); + return 0; + } else { + return readb((void *)(iobase + port)); + } +} + +// lowlevel write to eeprom/dac +static void labpc_serial_out(struct comedi_device * dev, unsigned int value, + unsigned int value_width) +{ + int i; + + for (i = 1; i <= value_width; i++) { + // clear serial clock + devpriv->command5_bits &= ~SCLOCK_BIT; + // send bits most significant bit first + if (value & (1 << (value_width - i))) + devpriv->command5_bits |= SDATA_BIT; + else + devpriv->command5_bits &= ~SDATA_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, + dev->iobase + COMMAND5_REG); + // set clock to load bit + devpriv->command5_bits |= SCLOCK_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, + dev->iobase + COMMAND5_REG); + } +} + +// lowlevel read from eeprom +static unsigned int labpc_serial_in(struct comedi_device * dev) +{ + unsigned int value = 0; + int i; + const int value_width = 8; // number of bits wide values are + + for (i = 1; i <= value_width; i++) { + // set serial clock + devpriv->command5_bits |= SCLOCK_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, + dev->iobase + COMMAND5_REG); + // clear clock bit + devpriv->command5_bits &= ~SCLOCK_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, + dev->iobase + COMMAND5_REG); + // read bits most significant bit first + comedi_udelay(1); + devpriv->status2_bits = + devpriv->read_byte(dev->iobase + STATUS2_REG); + if (devpriv->status2_bits & EEPROM_OUT_BIT) { + value |= 1 << (value_width - i); + } + } + + return value; +} + +static unsigned int labpc_eeprom_read(struct comedi_device * dev, unsigned int address) +{ + unsigned int value; + const int read_instruction = 0x3; // bits to tell eeprom to expect a read + const int write_length = 8; // 8 bit write lengths to eeprom + + // enable read/write to eeprom + devpriv->command5_bits &= ~EEPROM_EN_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + + // send read instruction + labpc_serial_out(dev, read_instruction, write_length); + // send 8 bit address to read from + labpc_serial_out(dev, address, write_length); + // read result + value = labpc_serial_in(dev); + + // disable read/write to eeprom + devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + + return value; +} + +static unsigned int labpc_eeprom_write(struct comedi_device * dev, + unsigned int address, unsigned int value) +{ + const int write_enable_instruction = 0x6; + const int write_instruction = 0x2; + const int write_length = 8; // 8 bit write lengths to eeprom + const int write_in_progress_bit = 0x1; + const int timeout = 10000; + int i; + + // make sure there isn't already a write in progress + for (i = 0; i < timeout; i++) { + if ((labpc_eeprom_read_status(dev) & write_in_progress_bit) == + 0) + break; + } + if (i == timeout) { + comedi_error(dev, "eeprom write timed out"); + return -ETIME; + } + // update software copy of eeprom + devpriv->eeprom_data[address] = value; + + // enable read/write to eeprom + devpriv->command5_bits &= ~EEPROM_EN_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + + // send write_enable instruction + labpc_serial_out(dev, write_enable_instruction, write_length); + devpriv->command5_bits &= ~EEPROM_EN_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + + // send write instruction + devpriv->command5_bits |= EEPROM_EN_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + labpc_serial_out(dev, write_instruction, write_length); + // send 8 bit address to write to + labpc_serial_out(dev, address, write_length); + // write value + labpc_serial_out(dev, value, write_length); + devpriv->command5_bits &= ~EEPROM_EN_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + + // disable read/write to eeprom + devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + + return 0; +} + +static unsigned int labpc_eeprom_read_status(struct comedi_device * dev) +{ + unsigned int value; + const int read_status_instruction = 0x5; + const int write_length = 8; // 8 bit write lengths to eeprom + + // enable read/write to eeprom + devpriv->command5_bits &= ~EEPROM_EN_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->command5_bits |= EEPROM_EN_BIT | EEPROM_WRITE_UNPROTECT_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + + // send read status instruction + labpc_serial_out(dev, read_status_instruction, write_length); + // read result + value = labpc_serial_in(dev); + + // disable read/write to eeprom + devpriv->command5_bits &= ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + + return value; +} + +// writes to 8 bit calibration dacs +static void write_caldac(struct comedi_device * dev, unsigned int channel, + unsigned int value) +{ + if (value == devpriv->caldac[channel]) + return; + devpriv->caldac[channel] = value; + + // clear caldac load bit and make sure we don't write to eeprom + devpriv->command5_bits &= + ~CALDAC_LOAD_BIT & ~EEPROM_EN_BIT & ~EEPROM_WRITE_UNPROTECT_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + + // write 4 bit channel + labpc_serial_out(dev, channel, 4); + // write 8 bit caldac value + labpc_serial_out(dev, value, 8); + + // set and clear caldac bit to load caldac value + devpriv->command5_bits |= CALDAC_LOAD_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); + devpriv->command5_bits &= ~CALDAC_LOAD_BIT; + comedi_udelay(1); + devpriv->write_byte(devpriv->command5_bits, dev->iobase + COMMAND5_REG); +} + +#ifdef CONFIG_COMEDI_PCI +COMEDI_PCI_INITCLEANUP(driver_labpc, labpc_pci_table); +#else +COMEDI_INITCLEANUP(driver_labpc); +#endif + +EXPORT_SYMBOL_GPL(labpc_common_attach); +EXPORT_SYMBOL_GPL(labpc_common_detach); +EXPORT_SYMBOL_GPL(range_labpc_1200_ai); +EXPORT_SYMBOL_GPL(labpc_1200_ai_gain_bits); +EXPORT_SYMBOL_GPL(labpc_1200_is_unipolar); diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h new file mode 100644 index 000000000000..b44b0d3d02f1 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -0,0 +1,85 @@ +/* + ni_labpc.h + + Header for ni_labpc.c and ni_labpc_cs.c + + Copyright (C) 2003 Frank Mori Hess + + 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 _NI_LABPC_H +#define _NI_LABPC_H + +#define EEPROM_SIZE 256 // 256 byte eeprom +#define NUM_AO_CHAN 2 // boards have two analog output channels + +enum labpc_bustype { isa_bustype, pci_bustype, pcmcia_bustype }; +enum labpc_register_layout { labpc_plus_layout, labpc_1200_layout }; +enum transfer_type { fifo_not_empty_transfer, fifo_half_full_transfer, + isa_dma_transfer }; + +typedef struct labpc_board_struct { + const char *name; + int device_id; // device id for pci and pcmcia boards + int ai_speed; // maximum input speed in nanoseconds + enum labpc_bustype bustype; // ISA/PCI/etc. + enum labpc_register_layout register_layout; // 1200 has extra registers compared to pc+ + int has_ao; // has analog output true/false + const struct comedi_lrange *ai_range_table; + const int *ai_range_code; + const int *ai_range_is_unipolar; + unsigned ai_scan_up:1; // board can auto scan up in ai channels, not just down + unsigned memory_mapped_io:1; /* uses memory mapped io instead of ioports */ +} labpc_board; + +typedef struct { + struct mite_struct *mite; // for mite chip on pci-1200 + volatile unsigned long long count; /* number of data points left to be taken */ + unsigned int ao_value[NUM_AO_CHAN]; // software copy of analog output values + // software copys of bits written to command registers + volatile unsigned int command1_bits; + volatile unsigned int command2_bits; + volatile unsigned int command3_bits; + volatile unsigned int command4_bits; + volatile unsigned int command5_bits; + volatile unsigned int command6_bits; + // store last read of board status registers + volatile unsigned int status1_bits; + volatile unsigned int status2_bits; + unsigned int divisor_a0; /* value to load into board's counter a0 (conversion pacing) for timed conversions */ + unsigned int divisor_b0; /* value to load into board's counter b0 (master) for timed conversions */ + unsigned int divisor_b1; /* value to load into board's counter b1 (scan pacing) for timed conversions */ + unsigned int dma_chan; // dma channel to use + u16 *dma_buffer; // buffer ai will dma into + unsigned int dma_transfer_size; // transfer size in bytes for current transfer + enum transfer_type current_transfer; // we are using dma/fifo-half-full/etc. + unsigned int eeprom_data[EEPROM_SIZE]; // stores contents of board's eeprom + unsigned int caldac[16]; // stores settings of calibration dacs + // function pointers so we can use inb/outb or readb/writeb as appropriate + unsigned int (*read_byte) (unsigned long address); + void (*write_byte) (unsigned int byte, unsigned long address); +} labpc_private; + +int labpc_common_attach(struct comedi_device * dev, unsigned long iobase, + unsigned int irq, unsigned int dma); +int labpc_common_detach(struct comedi_device * dev); + +extern const int labpc_1200_is_unipolar[]; +extern const int labpc_1200_ai_gain_bits[]; +extern const struct comedi_lrange range_labpc_1200_ai; + +#endif /* _NI_LABPC_H */ diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c new file mode 100644 index 000000000000..ac0ce2f58f5f --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -0,0 +1,573 @@ +/* + comedi/drivers/ni_labpc_cs.c + Driver for National Instruments daqcard-1200 boards + Copyright (C) 2001, 2002, 2003 Frank Mori Hess + + PCMCIA crap is adapted from dummy_cs.c 1.31 2001/08/24 12:13:13 + from the pcmcia package. + The initial developer of the pcmcia dummy_cs.c code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. + + 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: ni_labpc_cs +Description: National Instruments Lab-PC (& compatibles) +Author: Frank Mori Hess +Devices: [National Instruments] DAQCard-1200 (daqcard-1200) +Status: works + +Thanks go to Fredrik Lingvall for much testing and perseverance in +helping to debug daqcard-1200 support. + +The 1200 series boards have onboard calibration dacs for correcting +analog input/output offsets and gains. The proper settings for these +caldacs are stored on the board's eeprom. To read the caldac values +from the eeprom and store them into a file that can be then be used by +comedilib, use the comedi_calibrate program. + +Configuration options: + none + +The daqcard-1200 has quirky chanlist requirements +when scanning multiple channels. Multiple channel scan +sequence must start at highest channel, then decrement down to +channel 0. Chanlists consisting of all one channel +are also legal, and allow you to pace conversions in bursts. + +*/ + +/* + +NI manuals: +340988a (daqcard-1200) + +*/ + +#undef LABPC_DEBUG +//#define LABPC_DEBUG // enable debugging messages + +#include "../comedidev.h" + +#include + +#include "8253.h" +#include "8255.h" +#include "comedi_fc.h" +#include "ni_labpc.h" + +#include +#include +#include +#include +#include + +static struct pcmcia_device *pcmcia_cur_dev = NULL; + +static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it); + +static const labpc_board labpc_cs_boards[] = { + { + name: "daqcard-1200", + device_id:0x103, // 0x10b is manufacturer id, 0x103 is device id + ai_speed:10000, + bustype: pcmcia_bustype, + register_layout:labpc_1200_layout, + has_ao: 1, + ai_range_table:&range_labpc_1200_ai, + ai_range_code:labpc_1200_ai_gain_bits, + ai_range_is_unipolar:labpc_1200_is_unipolar, + ai_scan_up:0, + memory_mapped_io:0, + }, + /* duplicate entry, to support using alternate name */ + { + name: "ni_labpc_cs", + device_id:0x103, + ai_speed:10000, + bustype: pcmcia_bustype, + register_layout:labpc_1200_layout, + has_ao: 1, + ai_range_table:&range_labpc_1200_ai, + ai_range_code:labpc_1200_ai_gain_bits, + ai_range_is_unipolar:labpc_1200_is_unipolar, + ai_scan_up:0, + memory_mapped_io:0, + }, +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const labpc_board *)dev->board_ptr) + +static struct comedi_driver driver_labpc_cs = { + .driver_name = "ni_labpc_cs", + .module = THIS_MODULE, + .attach = &labpc_attach, + .detach = &labpc_common_detach, + .num_names = sizeof(labpc_cs_boards) / sizeof(labpc_board), + .board_name = &labpc_cs_boards[0].name, + .offset = sizeof(labpc_board), +}; + +static int labpc_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + unsigned long iobase = 0; + unsigned int irq = 0; + struct pcmcia_device *link; + + /* allocate and initialize dev->private */ + if (alloc_private(dev, sizeof(labpc_private)) < 0) + return -ENOMEM; + + // get base address, irq etc. based on bustype + switch (thisboard->bustype) { + case pcmcia_bustype: + link = pcmcia_cur_dev; /* XXX hack */ + if (!link) + return -EIO; + iobase = link->io.BasePort1; + irq = link->irq.AssignedIRQ; + break; + default: + printk("bug! couldn't determine board type\n"); + return -EINVAL; + break; + } + return labpc_common_attach(dev, iobase, irq, 0); +} + +/* + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + you do not define PCMCIA_DEBUG at all, all the debug code will be + left out. If you compile with PCMCIA_DEBUG=0, the debug code will + be present but disabled -- but it can then be enabled for specific + modules at load time with a 'pc_debug=#' option to insmod. +*/ +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +module_param(pc_debug, int, 0644); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static const char *version = + "ni_labpc.c, based on dummy_cs.c 1.31 2001/08/24 12:13:13"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* + The event() function is this driver's Card Services event handler. + It will be called by Card Services when an appropriate card status + event is received. The config() and release() entry points are + used to configure or release a socket, in response to card + insertion and ejection events. They are invoked from the dummy + event handler. + + Kernel version 2.6.16 upwards uses suspend() and resume() functions + instead of an event() function. +*/ + +static void labpc_config(struct pcmcia_device *link); +static void labpc_release(struct pcmcia_device *link); +static int labpc_cs_suspend(struct pcmcia_device *p_dev); +static int labpc_cs_resume(struct pcmcia_device *p_dev); + +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static int labpc_cs_attach(struct pcmcia_device *); +static void labpc_cs_detach(struct pcmcia_device *); + +/* + You'll also need to prototype all the functions that will actually + be used to talk to your device. See 'memory_cs' for a good example + of a fully self-sufficient driver; the other drivers rely more or + less on other parts of the kernel. +*/ + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static const dev_info_t dev_info = "daqcard-1200"; + +typedef struct local_info_t { + struct pcmcia_device *link; + dev_node_t node; + int stop; + struct bus_operations *bus; +} local_info_t; + +/*====================================================================== + + labpc_cs_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + +======================================================================*/ + +static int labpc_cs_attach(struct pcmcia_device *link) +{ + local_info_t *local; + + DEBUG(0, "labpc_cs_attach()\n"); + + /* Allocate space for private device-specific data */ + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); + if (!local) + return -ENOMEM; + local->link = link; + link->priv = local; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_FORCED_PULSE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_PULSE_ID; + link->irq.Handler = NULL; + + /* + General socket configuration defaults can go here. In this + client, we assume very little, and rely on the CIS for almost + everything. In most clients, many details (i.e., number, sizes, + and attributes of IO windows) are fixed by the nature of the + device, and can be hard-wired here. + */ + link->conf.Attributes = 0; + link->conf.IntType = INT_MEMORY_AND_IO; + + pcmcia_cur_dev = link; + + labpc_config(link); + + return 0; +} /* labpc_cs_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void labpc_cs_detach(struct pcmcia_device *link) +{ + DEBUG(0, "labpc_cs_detach(0x%p)\n", link); + + /* + If the device is currently configured and active, we won't + actually delete it yet. Instead, it is marked so that when + the release() function is called, that will trigger a proper + detach(). + */ + if (link->dev_node) { + ((local_info_t *) link->priv)->stop = 1; + labpc_release(link); + } + + /* This points to the parent local_info_t struct */ + if (link->priv) + kfree(link->priv); + +} /* labpc_cs_detach */ + +/*====================================================================== + + labpc_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + device available to the system. + +======================================================================*/ + +static void labpc_config(struct pcmcia_device *link) +{ + local_info_t *dev = link->priv; + tuple_t tuple; + cisparse_t parse; + int last_ret; + u_char buf[64]; + win_req_t req; + memreq_t map; + cistpl_cftable_entry_t dflt = { 0 }; + + DEBUG(0, "labpc_config(0x%p)\n", link); + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple))) { + cs_error(link, GetFirstTuple, last_ret); + goto cs_failed; + } + if ((last_ret = pcmcia_get_tuple_data(link, &tuple))) { + cs_error(link, GetTupleData, last_ret); + goto cs_failed; + } + if ((last_ret = pcmcia_parse_tuple(&tuple, &parse))) { + cs_error(link, ParseTuple, last_ret); + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* + In this loop, we scan the CIS for configuration table entries, + each of which describes a valid card configuration, including + voltage, IO window, memory window, and interrupt settings. + + We make no assumptions about the card to be configured: we use + just the information available in the CIS. In an ideal world, + this would work for any PCMCIA card, but it requires a complete + and accurate CIS. In practice, a driver usually "knows" most of + these things without consulting the CIS, and most client drivers + will only use the CIS to fill in implementation-defined details. + */ + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple))) { + cs_error(link, GetFirstTuple, last_ret); + goto cs_failed; + } + while (1) { + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + if (pcmcia_get_tuple_data(link, &tuple)) + goto next_entry; + if (pcmcia_parse_tuple(&tuple, &parse)) + goto next_entry; + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + if (cfg->index == 0) + goto next_entry; + link->conf.ConfigIndex = cfg->index; + + /* Does this card need audio output? */ + if (cfg->flags & CISTPL_CFTABLE_AUDIO) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + /* This reserves IO space but doesn't actually enable it */ + if (pcmcia_request_io(link, &link->io)) + goto next_entry; + } + + if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { + cistpl_mem_t *mem = + (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; + req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; + req.Attributes |= WIN_ENABLE; + req.Base = mem->win[0].host_addr; + req.Size = mem->win[0].len; + if (req.Size < 0x1000) + req.Size = 0x1000; + req.AccessSpeed = 0; + link->win = (window_handle_t) link; + if (pcmcia_request_window(&link, &req, &link->win)) + goto next_entry; + map.Page = 0; + map.CardOffset = mem->win[0].card_addr; + if (pcmcia_map_mem_page(link->win, &map)) + goto next_entry; + } + /* If we got this far, we're cool! */ + break; + + next_entry: + if ((last_ret = pcmcia_get_next_tuple(link, &tuple))) { + cs_error(link, GetNextTuple, last_ret); + goto cs_failed; + } + } + + /* + Allocate an interrupt line. Note that this does not assign a + handler to the interrupt, unless the 'Handler' member of the + irq structure is initialized. + */ + if (link->conf.Attributes & CONF_ENABLE_IRQ) + if ((last_ret = pcmcia_request_irq(link, &link->irq))) { + cs_error(link, RequestIRQ, last_ret); + goto cs_failed; + } + + /* + This actually configures the PCMCIA socket -- setting up + the I/O windows and the interrupt mapping, and putting the + card and host interface into "Memory and IO" mode. + */ + if ((last_ret = pcmcia_request_configuration(link, &link->conf))) { + cs_error(link, RequestConfiguration, last_ret); + goto cs_failed; + } + + /* + At this point, the dev_node_t structure(s) need to be + initialized and arranged in a linked list at link->dev. + */ + sprintf(dev->node.dev_name, "daqcard-1200"); + dev->node.major = dev->node.minor = 0; + link->dev_node = &dev->node; + + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %d", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1 + link->io.NumPorts1 - 1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2 + link->io.NumPorts2 - 1); + if (link->win) + printk(", mem 0x%06lx-0x%06lx", req.Base, + req.Base + req.Size - 1); + printk("\n"); + + return; + + cs_failed: + labpc_release(link); + +} /* labpc_config */ + +static void labpc_release(struct pcmcia_device *link) +{ + DEBUG(0, "labpc_release(0x%p)\n", link); + + pcmcia_disable_device(link); +} /* labpc_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. + + When a CARD_REMOVAL event is received, we immediately set a + private flag to block future accesses to this device. All the + functions that actually access the device should check this flag + to make sure the card is still present. + +======================================================================*/ + +static int labpc_cs_suspend(struct pcmcia_device *link) +{ + local_info_t *local = link->priv; + + /* Mark the device as stopped, to block IO until later */ + local->stop = 1; + return 0; +} /* labpc_cs_suspend */ + +static int labpc_cs_resume(struct pcmcia_device *link) +{ + local_info_t *local = link->priv; + + local->stop = 0; + return 0; +} /* labpc_cs_resume */ + +/*====================================================================*/ + +static struct pcmcia_device_id labpc_cs_ids[] = { + /* N.B. These IDs should match those in labpc_cs_boards (ni_labpc.c) */ + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0103), /* daqcard-1200 */ + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, labpc_cs_ids); + +struct pcmcia_driver labpc_cs_driver = { + .probe = labpc_cs_attach, + .remove = labpc_cs_detach, + .suspend = labpc_cs_suspend, + .resume = labpc_cs_resume, + .id_table = labpc_cs_ids, + .owner = THIS_MODULE, + .drv = { + .name = dev_info, + }, +}; + +static int __init init_labpc_cs(void) +{ + DEBUG(0, "%s\n", version); + pcmcia_register_driver(&labpc_cs_driver); + return 0; +} + +static void __exit exit_labpc_cs(void) +{ + DEBUG(0, "ni_labpc: unloading\n"); + pcmcia_unregister_driver(&labpc_cs_driver); +} + +int __init labpc_init_module(void) +{ + int ret; + + ret = init_labpc_cs(); + if (ret < 0) + return ret; + + return comedi_driver_register(&driver_labpc_cs); +} + +void __exit labpc_exit_module(void) +{ + exit_labpc_cs(); + comedi_driver_unregister(&driver_labpc_cs); +} + +MODULE_LICENSE("GPL"); +module_init(labpc_init_module); +module_exit(labpc_exit_module); diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c new file mode 100644 index 000000000000..542bd0dcd44d --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -0,0 +1,5862 @@ +/* + comedi/drivers/ni_mio_common.c + Hardware driver for DAQ-STC based boards + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-2001 David A. Schleef + Copyright (C) 2002-2006 Frank Mori Hess + + 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. + +*/ + +/* + This file is meant to be included by another file, e.g., + ni_atmio.c or ni_pcimio.c. + + Interrupt support originally added by Truxton Fulton + + + References (from ftp://ftp.natinst.com/support/manuals): + + 340747b.pdf AT-MIO E series Register Level Programmer Manual + 341079b.pdf PCI E Series RLPM + 340934b.pdf DAQ-STC reference manual + 67xx and 611x registers (from http://www.ni.com/pdf/daq/us) + release_ni611x.pdf + release_ni67xx.pdf + Other possibly relevant info: + + 320517c.pdf User manual (obsolete) + 320517f.pdf User manual (new) + 320889a.pdf delete + 320906c.pdf maximum signal ratings + 321066a.pdf about 16x + 321791a.pdf discontinuation of at-mio-16e-10 rev. c + 321808a.pdf about at-mio-16e-10 rev P + 321837a.pdf discontinuation of at-mio-16de-10 rev d + 321838a.pdf about at-mio-16de-10 rev N + + ISSUES: + + - the interrupt routine needs to be cleaned up + + 2006-02-07: S-Series PCI-6143: Support has been added but is not + fully tested as yet. Terry Barnaby, BEAM Ltd. +*/ + +//#define DEBUG_INTERRUPT +//#define DEBUG_STATUS_A +//#define DEBUG_STATUS_B + +#include "8255.h" +#include "mite.h" +#include "comedi_fc.h" + +#ifndef MDPRINTK +#define MDPRINTK(format,args...) +#endif + +/* A timeout count */ +#define NI_TIMEOUT 1000 +static const unsigned old_RTSI_clock_channel = 7; + +/* Note: this table must match the ai_gain_* definitions */ +static const short ni_gainlkup[][16] = { + [ai_gain_16] = {0, 1, 2, 3, 4, 5, 6, 7, + 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107}, + [ai_gain_8] = {1, 2, 4, 7, 0x101, 0x102, 0x104, 0x107}, + [ai_gain_14] = {1, 2, 3, 4, 5, 6, 7, + 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107}, + [ai_gain_4] = {0, 1, 4, 7}, + [ai_gain_611x] = {0x00a, 0x00b, 0x001, 0x002, + 0x003, 0x004, 0x005, 0x006}, + [ai_gain_622x] = {0, 1, 4, 5}, + [ai_gain_628x] = {1, 2, 3, 4, 5, 6, 7}, + [ai_gain_6143] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, +}; + +static const struct comedi_lrange range_ni_E_ai = { 16, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2.5, 2.5), + RANGE(-1, 1), + RANGE(-0.5, 0.5), + RANGE(-0.25, 0.25), + RANGE(-0.1, 0.1), + RANGE(-0.05, 0.05), + RANGE(0, 20), + RANGE(0, 10), + RANGE(0, 5), + RANGE(0, 2), + RANGE(0, 1), + RANGE(0, 0.5), + RANGE(0, 0.2), + RANGE(0, 0.1), + } +}; +static const struct comedi_lrange range_ni_E_ai_limited = { 8, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-1, 1), + RANGE(-0.1, 0.1), + RANGE(0, 10), + RANGE(0, 5), + RANGE(0, 1), + RANGE(0, 0.1), + } +}; +static const struct comedi_lrange range_ni_E_ai_limited14 = { 14, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2, 2), + RANGE(-1, 1), + RANGE(-0.5, 0.5), + RANGE(-0.2, 0.2), + RANGE(-0.1, 0.1), + RANGE(0, 10), + RANGE(0, 5), + RANGE(0, 2), + RANGE(0, 1), + RANGE(0, 0.5), + RANGE(0, 0.2), + RANGE(0, 0.1), + } +}; +static const struct comedi_lrange range_ni_E_ai_bipolar4 = { 4, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-0.5, 0.5), + RANGE(-0.05, 0.05), + } +}; +static const struct comedi_lrange range_ni_E_ai_611x = { 8, { + RANGE(-50, 50), + RANGE(-20, 20), + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2, 2), + RANGE(-1, 1), + RANGE(-0.5, 0.5), + RANGE(-0.2, 0.2), + } +}; +static const struct comedi_lrange range_ni_M_ai_622x = { 4, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-1, 1), + RANGE(-0.2, 0.2), + } +}; +static const struct comedi_lrange range_ni_M_ai_628x = { 7, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2, 2), + RANGE(-1, 1), + RANGE(-0.5, 0.5), + RANGE(-0.2, 0.2), + RANGE(-0.1, 0.1), + } +}; +static const struct comedi_lrange range_ni_S_ai_6143 = { 1, { + RANGE(-5, +5), + } +}; +static const struct comedi_lrange range_ni_E_ao_ext = { 4, { + RANGE(-10, 10), + RANGE(0, 10), + RANGE_ext(-1, 1), + RANGE_ext(0, 1), + } +}; + +static const struct comedi_lrange *const ni_range_lkup[] = { + [ai_gain_16] = &range_ni_E_ai, + [ai_gain_8] = &range_ni_E_ai_limited, + [ai_gain_14] = &range_ni_E_ai_limited14, + [ai_gain_4] = &range_ni_E_ai_bipolar4, + [ai_gain_611x] = &range_ni_E_ai_611x, + [ai_gain_622x] = &range_ni_M_ai_622x, + [ai_gain_628x] = &range_ni_M_ai_628x, + [ai_gain_6143] = &range_ni_S_ai_6143 +}; + +static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int ni_cdio_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void handle_cdio_interrupt(struct comedi_device * dev); +static int ni_cdo_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum); + +static int ni_serial_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_serial_hw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned char data_out, unsigned char *data_in); +static int ni_serial_sw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned char data_out, unsigned char *data_in); + +static int ni_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int ni_eeprom_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_m_series_eeprom_insn_read(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan); + +static void ni_rtsi_init(struct comedi_device * dev); +static int ni_rtsi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_rtsi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static void caldac_setup(struct comedi_device * dev, struct comedi_subdevice * s); +static int ni_read_eeprom(struct comedi_device * dev, int addr); + +#ifdef DEBUG_STATUS_A +static void ni_mio_print_status_a(int status); +#else +#define ni_mio_print_status_a(a) +#endif +#ifdef DEBUG_STATUS_B +static void ni_mio_print_status_b(int status); +#else +#define ni_mio_print_status_b(a) +#endif + +static int ni_ai_reset(struct comedi_device * dev, struct comedi_subdevice * s); +#ifndef PCIDMA +static void ni_handle_fifo_half_full(struct comedi_device * dev); +static int ni_ao_fifo_half_empty(struct comedi_device * dev, struct comedi_subdevice * s); +#endif +static void ni_handle_fifo_dregs(struct comedi_device * dev); +static int ni_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum); +static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_chan, + unsigned int *list); +static void shutdown_ai_command(struct comedi_device * dev); + +static int ni_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum); + +static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s); + +static int ni_8255_callback(int dir, int port, int data, unsigned long arg); + +static int ni_gpct_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_gpct_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int ni_gpct_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void handle_gpct_interrupt(struct comedi_device * dev, + unsigned short counter_index); + +static int init_cs5529(struct comedi_device * dev); +static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data); +static int cs5529_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +#ifdef NI_CS5529_DEBUG +static unsigned int cs5529_config_read(struct comedi_device * dev, + unsigned int reg_select_bits); +#endif +static void cs5529_config_write(struct comedi_device * dev, unsigned int value, + unsigned int reg_select_bits); + +static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ni_6143_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int ni_set_master_clock(struct comedi_device * dev, unsigned source, + unsigned period_ns); +static void ack_a_interrupt(struct comedi_device * dev, unsigned short a_status); +static void ack_b_interrupt(struct comedi_device * dev, unsigned short b_status); + +enum aimodes { + AIMODE_NONE = 0, + AIMODE_HALF_FULL = 1, + AIMODE_SCAN = 2, + AIMODE_SAMPLE = 3, +}; + +enum ni_common_subdevices { + NI_AI_SUBDEV, + NI_AO_SUBDEV, + NI_DIO_SUBDEV, + NI_8255_DIO_SUBDEV, + NI_UNUSED_SUBDEV, + NI_CALIBRATION_SUBDEV, + NI_EEPROM_SUBDEV, + NI_PFI_DIO_SUBDEV, + NI_CS5529_CALIBRATION_SUBDEV, + NI_SERIAL_SUBDEV, + NI_RTSI_SUBDEV, + NI_GPCT0_SUBDEV, + NI_GPCT1_SUBDEV, + NI_FREQ_OUT_SUBDEV, + NI_NUM_SUBDEVICES +}; +static inline unsigned NI_GPCT_SUBDEV(unsigned counter_index) +{ + switch (counter_index) { + case 0: + return NI_GPCT0_SUBDEV; + break; + case 1: + return NI_GPCT1_SUBDEV; + break; + default: + break; + } + BUG(); + return NI_GPCT0_SUBDEV; +} + +enum timebase_nanoseconds { + TIMEBASE_1_NS = 50, + TIMEBASE_2_NS = 10000 +}; + +#define SERIAL_DISABLED 0 +#define SERIAL_600NS 600 +#define SERIAL_1_2US 1200 +#define SERIAL_10US 10000 + +static const int num_adc_stages_611x = 3; + +static void handle_a_interrupt(struct comedi_device * dev, unsigned short status, + unsigned ai_mite_status); +static void handle_b_interrupt(struct comedi_device * dev, unsigned short status, + unsigned ao_mite_status); +static void get_last_sample_611x(struct comedi_device * dev); +static void get_last_sample_6143(struct comedi_device * dev); + +static inline void ni_set_bitfield(struct comedi_device * dev, int reg, + unsigned bit_mask, unsigned bit_values) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); + switch (reg) { + case Interrupt_A_Enable_Register: + devpriv->int_a_enable_reg &= ~bit_mask; + devpriv->int_a_enable_reg |= bit_values & bit_mask; + devpriv->stc_writew(dev, devpriv->int_a_enable_reg, + Interrupt_A_Enable_Register); + break; + case Interrupt_B_Enable_Register: + devpriv->int_b_enable_reg &= ~bit_mask; + devpriv->int_b_enable_reg |= bit_values & bit_mask; + devpriv->stc_writew(dev, devpriv->int_b_enable_reg, + Interrupt_B_Enable_Register); + break; + case IO_Bidirection_Pin_Register: + devpriv->io_bidirection_pin_reg &= ~bit_mask; + devpriv->io_bidirection_pin_reg |= bit_values & bit_mask; + devpriv->stc_writew(dev, devpriv->io_bidirection_pin_reg, + IO_Bidirection_Pin_Register); + break; + case AI_AO_Select: + devpriv->ai_ao_select_reg &= ~bit_mask; + devpriv->ai_ao_select_reg |= bit_values & bit_mask; + ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select); + break; + case G0_G1_Select: + devpriv->g0_g1_select_reg &= ~bit_mask; + devpriv->g0_g1_select_reg |= bit_values & bit_mask; + ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select); + break; + default: + rt_printk("Warning %s() called with invalid register\n", + __FUNCTION__); + rt_printk("reg is %d\n", reg); + break; + } + mmiowb(); + comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); +} + +#ifdef PCIDMA +static int ni_ai_drain_dma(struct comedi_device * dev); + +/* DMA channel setup */ + +// negative channel means no channel +static inline void ni_set_ai_dma_channel(struct comedi_device * dev, int channel) +{ + unsigned bitfield; + + if (channel >= 0) { + bitfield = + (ni_stc_dma_channel_select_bitfield(channel) << + AI_DMA_Select_Shift) & AI_DMA_Select_Mask; + } else { + bitfield = 0; + } + ni_set_bitfield(dev, AI_AO_Select, AI_DMA_Select_Mask, bitfield); +} + +// negative channel means no channel +static inline void ni_set_ao_dma_channel(struct comedi_device * dev, int channel) +{ + unsigned bitfield; + + if (channel >= 0) { + bitfield = + (ni_stc_dma_channel_select_bitfield(channel) << + AO_DMA_Select_Shift) & AO_DMA_Select_Mask; + } else { + bitfield = 0; + } + ni_set_bitfield(dev, AI_AO_Select, AO_DMA_Select_Mask, bitfield); +} + +// negative mite_channel means no channel +static inline void ni_set_gpct_dma_channel(struct comedi_device * dev, + unsigned gpct_index, int mite_channel) +{ + unsigned bitfield; + + if (mite_channel >= 0) { + bitfield = GPCT_DMA_Select_Bits(gpct_index, mite_channel); + } else { + bitfield = 0; + } + ni_set_bitfield(dev, G0_G1_Select, GPCT_DMA_Select_Mask(gpct_index), + bitfield); +} + +// negative mite_channel means no channel +static inline void ni_set_cdo_dma_channel(struct comedi_device * dev, int mite_channel) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); + devpriv->cdio_dma_select_reg &= ~CDO_DMA_Select_Mask; + if (mite_channel >= 0) { + /*XXX just guessing ni_stc_dma_channel_select_bitfield() returns the right bits, + under the assumption the cdio dma selection works just like ai/ao/gpct. + Definitely works for dma channels 0 and 1. */ + devpriv->cdio_dma_select_reg |= + (ni_stc_dma_channel_select_bitfield(mite_channel) << + CDO_DMA_Select_Shift) & CDO_DMA_Select_Mask; + } + ni_writeb(devpriv->cdio_dma_select_reg, M_Offset_CDIO_DMA_Select); + mmiowb(); + comedi_spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); +} + +static int ni_request_ai_mite_channel(struct comedi_device * dev) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + BUG_ON(devpriv->ai_mite_chan); + devpriv->ai_mite_chan = + mite_request_channel(devpriv->mite, devpriv->ai_mite_ring); + if (devpriv->ai_mite_chan == NULL) { + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, + flags); + comedi_error(dev, + "failed to reserve mite dma channel for analog input."); + return -EBUSY; + } + devpriv->ai_mite_chan->dir = COMEDI_INPUT; + ni_set_ai_dma_channel(dev, devpriv->ai_mite_chan->channel); + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + return 0; +} + +static int ni_request_ao_mite_channel(struct comedi_device * dev) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + BUG_ON(devpriv->ao_mite_chan); + devpriv->ao_mite_chan = + mite_request_channel(devpriv->mite, devpriv->ao_mite_ring); + if (devpriv->ao_mite_chan == NULL) { + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, + flags); + comedi_error(dev, + "failed to reserve mite dma channel for analog outut."); + return -EBUSY; + } + devpriv->ao_mite_chan->dir = COMEDI_OUTPUT; + ni_set_ao_dma_channel(dev, devpriv->ao_mite_chan->channel); + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + return 0; +} + +static int ni_request_gpct_mite_channel(struct comedi_device * dev, + unsigned gpct_index, enum comedi_io_direction direction) +{ + unsigned long flags; + struct mite_channel *mite_chan; + + BUG_ON(gpct_index >= NUM_GPCT); + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + BUG_ON(devpriv->counter_dev->counters[gpct_index].mite_chan); + mite_chan = + mite_request_channel(devpriv->mite, + devpriv->gpct_mite_ring[gpct_index]); + if (mite_chan == NULL) { + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, + flags); + comedi_error(dev, + "failed to reserve mite dma channel for counter."); + return -EBUSY; + } + mite_chan->dir = direction; + ni_tio_set_mite_channel(&devpriv->counter_dev->counters[gpct_index], + mite_chan); + ni_set_gpct_dma_channel(dev, gpct_index, mite_chan->channel); + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + return 0; +} + +#endif // PCIDMA + +static int ni_request_cdo_mite_channel(struct comedi_device * dev) +{ +#ifdef PCIDMA + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + BUG_ON(devpriv->cdo_mite_chan); + devpriv->cdo_mite_chan = + mite_request_channel(devpriv->mite, devpriv->cdo_mite_ring); + if (devpriv->cdo_mite_chan == NULL) { + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, + flags); + comedi_error(dev, + "failed to reserve mite dma channel for correlated digital outut."); + return -EBUSY; + } + devpriv->cdo_mite_chan->dir = COMEDI_OUTPUT; + ni_set_cdo_dma_channel(dev, devpriv->cdo_mite_chan->channel); + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +#endif // PCIDMA + return 0; +} + +static void ni_release_ai_mite_channel(struct comedi_device * dev) +{ +#ifdef PCIDMA + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->ai_mite_chan) { + ni_set_ai_dma_channel(dev, -1); + mite_release_channel(devpriv->ai_mite_chan); + devpriv->ai_mite_chan = NULL; + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +#endif // PCIDMA +} + +static void ni_release_ao_mite_channel(struct comedi_device * dev) +{ +#ifdef PCIDMA + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->ao_mite_chan) { + ni_set_ao_dma_channel(dev, -1); + mite_release_channel(devpriv->ao_mite_chan); + devpriv->ao_mite_chan = NULL; + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +#endif // PCIDMA +} + +void ni_release_gpct_mite_channel(struct comedi_device * dev, unsigned gpct_index) +{ +#ifdef PCIDMA + unsigned long flags; + + BUG_ON(gpct_index >= NUM_GPCT); + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->counter_dev->counters[gpct_index].mite_chan) { + struct mite_channel *mite_chan = + devpriv->counter_dev->counters[gpct_index].mite_chan; + + ni_set_gpct_dma_channel(dev, gpct_index, -1); + ni_tio_set_mite_channel(&devpriv->counter_dev-> + counters[gpct_index], NULL); + mite_release_channel(mite_chan); + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +#endif // PCIDMA +} + +static void ni_release_cdo_mite_channel(struct comedi_device * dev) +{ +#ifdef PCIDMA + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->cdo_mite_chan) { + ni_set_cdo_dma_channel(dev, -1); + mite_release_channel(devpriv->cdo_mite_chan); + devpriv->cdo_mite_chan = NULL; + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +#endif // PCIDMA +} + +// e-series boards use the second irq signals to generate dma requests for their counters +#ifdef PCIDMA +static void ni_e_series_enable_second_irq(struct comedi_device * dev, + unsigned gpct_index, short enable) +{ + if (boardtype.reg_type & ni_reg_m_series_mask) + return; + switch (gpct_index) { + case 0: + if (enable) { + devpriv->stc_writew(dev, G0_Gate_Second_Irq_Enable, + Second_IRQ_A_Enable_Register); + } else { + devpriv->stc_writew(dev, 0, + Second_IRQ_A_Enable_Register); + } + break; + case 1: + if (enable) { + devpriv->stc_writew(dev, G1_Gate_Second_Irq_Enable, + Second_IRQ_B_Enable_Register); + } else { + devpriv->stc_writew(dev, 0, + Second_IRQ_B_Enable_Register); + } + break; + default: + BUG(); + break; + } +} +#endif // PCIDMA + +static void ni_clear_ai_fifo(struct comedi_device * dev) +{ + if (boardtype.reg_type == ni_reg_6143) { + // Flush the 6143 data FIFO + ni_writel(0x10, AIFIFO_Control_6143); // Flush fifo + ni_writel(0x00, AIFIFO_Control_6143); // Flush fifo + while (ni_readl(AIFIFO_Status_6143) & 0x10) ; // Wait for complete + } else { + devpriv->stc_writew(dev, 1, ADC_FIFO_Clear); + if (boardtype.reg_type == ni_reg_625x) { + ni_writeb(0, M_Offset_Static_AI_Control(0)); + ni_writeb(1, M_Offset_Static_AI_Control(0)); +#if 0 + /* the NI example code does 3 convert pulses for 625x boards, + but that appears to be wrong in practice. */ + devpriv->stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); + devpriv->stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); + devpriv->stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); +#endif + } + } +} + +static void win_out2(struct comedi_device * dev, uint32_t data, int reg) +{ + devpriv->stc_writew(dev, data >> 16, reg); + devpriv->stc_writew(dev, data & 0xffff, reg + 1); +} + +static uint32_t win_in2(struct comedi_device * dev, int reg) +{ + uint32_t bits; + bits = devpriv->stc_readw(dev, reg) << 16; + bits |= devpriv->stc_readw(dev, reg + 1); + return bits; +} + +#define ao_win_out(data,addr) ni_ao_win_outw(dev,data,addr) +static inline void ni_ao_win_outw(struct comedi_device * dev, uint16_t data, int addr) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->window_lock, flags); + ni_writew(addr, AO_Window_Address_611x); + ni_writew(data, AO_Window_Data_611x); + comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags); +} + +static inline void ni_ao_win_outl(struct comedi_device * dev, uint32_t data, int addr) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->window_lock, flags); + ni_writew(addr, AO_Window_Address_611x); + ni_writel(data, AO_Window_Data_611x); + comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags); +} + +static inline unsigned short ni_ao_win_inw(struct comedi_device * dev, int addr) +{ + unsigned long flags; + unsigned short data; + + comedi_spin_lock_irqsave(&devpriv->window_lock, flags); + ni_writew(addr, AO_Window_Address_611x); + data = ni_readw(AO_Window_Data_611x); + comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags); + return data; +} + +/* ni_set_bits( ) allows different parts of the ni_mio_common driver to +* share registers (such as Interrupt_A_Register) without interfering with +* each other. +* +* NOTE: the switch/case statements are optimized out for a constant argument +* so this is actually quite fast--- If you must wrap another function around this +* make it inline to avoid a large speed penalty. +* +* value should only be 1 or 0. +*/ +static inline void ni_set_bits(struct comedi_device * dev, int reg, unsigned bits, + unsigned value) +{ + unsigned bit_values; + + if (value) + bit_values = bits; + else + bit_values = 0; + ni_set_bitfield(dev, reg, bits, bit_values); +} + +static irqreturn_t ni_E_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + unsigned short a_status; + unsigned short b_status; + unsigned int ai_mite_status = 0; + unsigned int ao_mite_status = 0; + unsigned long flags; +#ifdef PCIDMA + struct mite_struct *mite = devpriv->mite; +#endif + + if (dev->attached == 0) + return IRQ_NONE; + smp_mb(); // make sure dev->attached is checked before handler does anything else. + + // lock to avoid race with comedi_poll + comedi_spin_lock_irqsave(&dev->spinlock, flags); + a_status = devpriv->stc_readw(dev, AI_Status_1_Register); + b_status = devpriv->stc_readw(dev, AO_Status_1_Register); +#ifdef PCIDMA + if (mite) { + unsigned long flags_too; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, + flags_too); + if (devpriv->ai_mite_chan) { + ai_mite_status = mite_get_status(devpriv->ai_mite_chan); + if (ai_mite_status & CHSR_LINKC) + writel(CHOR_CLRLC, + devpriv->mite->mite_io_addr + + MITE_CHOR(devpriv->ai_mite_chan-> + channel)); + } + if (devpriv->ao_mite_chan) { + ao_mite_status = mite_get_status(devpriv->ao_mite_chan); + if (ao_mite_status & CHSR_LINKC) + writel(CHOR_CLRLC, + mite->mite_io_addr + + MITE_CHOR(devpriv->ao_mite_chan-> + channel)); + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, + flags_too); + } +#endif + ack_a_interrupt(dev, a_status); + ack_b_interrupt(dev, b_status); + if ((a_status & Interrupt_A_St) || (ai_mite_status & CHSR_INT)) + handle_a_interrupt(dev, a_status, ai_mite_status); + if ((b_status & Interrupt_B_St) || (ao_mite_status & CHSR_INT)) + handle_b_interrupt(dev, b_status, ao_mite_status); + handle_gpct_interrupt(dev, 0); + handle_gpct_interrupt(dev, 1); + handle_cdio_interrupt(dev); + + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + return IRQ_HANDLED; +} + +#ifdef PCIDMA +static void ni_sync_ai_dma(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->ai_mite_chan) + mite_sync_input_dma(devpriv->ai_mite_chan, s->async); + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +} + +static void mite_handle_b_linkc(struct mite_struct *mite, struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV; + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->ao_mite_chan) { + mite_sync_output_dma(devpriv->ao_mite_chan, s->async); + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +} + +static int ni_ao_wait_for_dma_load(struct comedi_device * dev) +{ + static const int timeout = 10000; + int i; + for (i = 0; i < timeout; i++) { + unsigned short b_status; + + b_status = devpriv->stc_readw(dev, AO_Status_1_Register); + if (b_status & AO_FIFO_Half_Full_St) + break; + /* if we poll too often, the pci bus activity seems + to slow the dma transfer down */ + comedi_udelay(10); + } + if (i == timeout) { + comedi_error(dev, "timed out waiting for dma load"); + return -EPIPE; + } + return 0; +} + +#endif //PCIDMA +static void ni_handle_eos(struct comedi_device * dev, struct comedi_subdevice * s) +{ + if (devpriv->aimode == AIMODE_SCAN) { +#ifdef PCIDMA + static const int timeout = 10; + int i; + + for (i = 0; i < timeout; i++) { + ni_sync_ai_dma(dev); + if ((s->async->events & COMEDI_CB_EOS)) + break; + comedi_udelay(1); + } +#else + ni_handle_fifo_dregs(dev); + s->async->events |= COMEDI_CB_EOS; +#endif + } + /* handle special case of single scan using AI_End_On_End_Of_Scan */ + if ((devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)) { + shutdown_ai_command(dev); + } +} + +static void shutdown_ai_command(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; + +#ifdef PCIDMA + ni_ai_drain_dma(dev); +#endif + ni_handle_fifo_dregs(dev); + get_last_sample_611x(dev); + get_last_sample_6143(dev); + + s->async->events |= COMEDI_CB_EOA; +} + +static void ni_event(struct comedi_device * dev, struct comedi_subdevice * s) +{ + if (s->async-> + events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW | COMEDI_CB_EOA)) + { + switch (s - dev->subdevices) { + case NI_AI_SUBDEV: + ni_ai_reset(dev, s); + break; + case NI_AO_SUBDEV: + ni_ao_reset(dev, s); + break; + case NI_GPCT0_SUBDEV: + case NI_GPCT1_SUBDEV: + ni_gpct_cancel(dev, s); + break; + case NI_DIO_SUBDEV: + ni_cdio_cancel(dev, s); + break; + default: + break; + } + } + comedi_event(dev, s); +} + +static void handle_gpct_interrupt(struct comedi_device * dev, + unsigned short counter_index) +{ +#ifdef PCIDMA + struct comedi_subdevice *s = dev->subdevices + NI_GPCT_SUBDEV(counter_index); + + ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index], + s); + if (s->async->events) + ni_event(dev, s); +#endif +} + +static void ack_a_interrupt(struct comedi_device * dev, unsigned short a_status) +{ + unsigned short ack = 0; + + if (a_status & AI_SC_TC_St) { + ack |= AI_SC_TC_Interrupt_Ack; + } + if (a_status & AI_START1_St) { + ack |= AI_START1_Interrupt_Ack; + } + if (a_status & AI_START_St) { + ack |= AI_START_Interrupt_Ack; + } + if (a_status & AI_STOP_St) { + /* not sure why we used to ack the START here also, instead of doing it independently. Frank Hess 2007-07-06 */ + ack |= AI_STOP_Interrupt_Ack /*| AI_START_Interrupt_Ack */ ; + } + if (ack) + devpriv->stc_writew(dev, ack, Interrupt_A_Ack_Register); +} + +static void handle_a_interrupt(struct comedi_device * dev, unsigned short status, + unsigned ai_mite_status) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; + + //67xx boards don't have ai subdevice, but their gpct0 might generate an a interrupt + if (s->type == COMEDI_SUBD_UNUSED) + return; + +#ifdef DEBUG_INTERRUPT + rt_printk + ("ni_mio_common: interrupt: a_status=%04x ai_mite_status=%08x\n", + status, ai_mite_status); + ni_mio_print_status_a(status); +#endif +#ifdef PCIDMA + if (ai_mite_status & CHSR_LINKC) { + ni_sync_ai_dma(dev); + } + + if (ai_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | + CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | + CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) { + rt_printk + ("unknown mite interrupt, ack! (ai_mite_status=%08x)\n", + ai_mite_status); + //mite_print_chsr(ai_mite_status); + s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + //disable_irq(dev->irq); + } +#endif + + /* test for all uncommon interrupt events at the same time */ + if (status & (AI_Overrun_St | AI_Overflow_St | AI_SC_TC_Error_St | + AI_SC_TC_St | AI_START1_St)) { + if (status == 0xffff) { + rt_printk + ("ni_mio_common: a_status=0xffff. Card removed?\n"); + /* we probably aren't even running a command now, + * so it's a good idea to be careful. */ + if (comedi_get_subdevice_runflags(s) & SRF_RUNNING) { + s->async->events |= + COMEDI_CB_ERROR | COMEDI_CB_EOA; + ni_event(dev, s); + } + return; + } + if (status & (AI_Overrun_St | AI_Overflow_St | + AI_SC_TC_Error_St)) { + rt_printk("ni_mio_common: ai error a_status=%04x\n", + status); + ni_mio_print_status_a(status); + + shutdown_ai_command(dev); + + s->async->events |= COMEDI_CB_ERROR; + if (status & (AI_Overrun_St | AI_Overflow_St)) + s->async->events |= COMEDI_CB_OVERFLOW; + + ni_event(dev, s); + + return; + } + if (status & AI_SC_TC_St) { +#ifdef DEBUG_INTERRUPT + rt_printk("ni_mio_common: SC_TC interrupt\n"); +#endif + if (!devpriv->ai_continuous) { + shutdown_ai_command(dev); + } + } + } +#ifndef PCIDMA + if (status & AI_FIFO_Half_Full_St) { + int i; + static const int timeout = 10; + /* pcmcia cards (at least 6036) seem to stop producing interrupts if we + *fail to get the fifo less than half full, so loop to be sure.*/ + for (i = 0; i < timeout; ++i) { + ni_handle_fifo_half_full(dev); + if ((devpriv->stc_readw(dev, + AI_Status_1_Register) & + AI_FIFO_Half_Full_St) == 0) + break; + } + } +#endif // !PCIDMA + + if ((status & AI_STOP_St)) { + ni_handle_eos(dev, s); + } + + ni_event(dev, s); + +#ifdef DEBUG_INTERRUPT + status = devpriv->stc_readw(dev, AI_Status_1_Register); + if (status & Interrupt_A_St) { + rt_printk + ("handle_a_interrupt: didn't clear interrupt? status=0x%x\n", + status); + } +#endif +} + +static void ack_b_interrupt(struct comedi_device * dev, unsigned short b_status) +{ + unsigned short ack = 0; + if (b_status & AO_BC_TC_St) { + ack |= AO_BC_TC_Interrupt_Ack; + } + if (b_status & AO_Overrun_St) { + ack |= AO_Error_Interrupt_Ack; + } + if (b_status & AO_START_St) { + ack |= AO_START_Interrupt_Ack; + } + if (b_status & AO_START1_St) { + ack |= AO_START1_Interrupt_Ack; + } + if (b_status & AO_UC_TC_St) { + ack |= AO_UC_TC_Interrupt_Ack; + } + if (b_status & AO_UI2_TC_St) { + ack |= AO_UI2_TC_Interrupt_Ack; + } + if (b_status & AO_UPDATE_St) { + ack |= AO_UPDATE_Interrupt_Ack; + } + if (ack) + devpriv->stc_writew(dev, ack, Interrupt_B_Ack_Register); +} + +static void handle_b_interrupt(struct comedi_device * dev, unsigned short b_status, + unsigned ao_mite_status) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV; + //unsigned short ack=0; +#ifdef DEBUG_INTERRUPT + rt_printk("ni_mio_common: interrupt: b_status=%04x m1_status=%08x\n", + b_status, ao_mite_status); + ni_mio_print_status_b(b_status); +#endif + +#ifdef PCIDMA + /* Currently, mite.c requires us to handle LINKC */ + if (ao_mite_status & CHSR_LINKC) { + mite_handle_b_linkc(devpriv->mite, dev); + } + + if (ao_mite_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_MRDY | + CHSR_DRDY | CHSR_DRQ1 | CHSR_DRQ0 | CHSR_ERROR | + CHSR_SABORT | CHSR_XFERR | CHSR_LxERR_mask)) { + rt_printk + ("unknown mite interrupt, ack! (ao_mite_status=%08x)\n", + ao_mite_status); + //mite_print_chsr(ao_mite_status); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + } +#endif + + if (b_status == 0xffff) + return; + if (b_status & AO_Overrun_St) { + rt_printk + ("ni_mio_common: AO FIFO underrun status=0x%04x status2=0x%04x\n", + b_status, devpriv->stc_readw(dev, + AO_Status_2_Register)); + s->async->events |= COMEDI_CB_OVERFLOW; + } + + if (b_status & AO_BC_TC_St) { + MDPRINTK("ni_mio_common: AO BC_TC status=0x%04x status2=0x%04x\n", b_status, devpriv->stc_readw(dev, AO_Status_2_Register)); + s->async->events |= COMEDI_CB_EOA; + } +#ifndef PCIDMA + if (b_status & AO_FIFO_Request_St) { + int ret; + + ret = ni_ao_fifo_half_empty(dev, s); + if (!ret) { + rt_printk("ni_mio_common: AO buffer underrun\n"); + ni_set_bits(dev, Interrupt_B_Enable_Register, + AO_FIFO_Interrupt_Enable | + AO_Error_Interrupt_Enable, 0); + s->async->events |= COMEDI_CB_OVERFLOW; + } + } +#endif + + ni_event(dev, s); +} + +#ifdef DEBUG_STATUS_A +static const char *const status_a_strings[] = { + "passthru0", "fifo", "G0_gate", "G0_TC", + "stop", "start", "sc_tc", "start1", + "start2", "sc_tc_error", "overflow", "overrun", + "fifo_empty", "fifo_half_full", "fifo_full", "interrupt_a" +}; + +static void ni_mio_print_status_a(int status) +{ + int i; + + rt_printk("A status:"); + for (i = 15; i >= 0; i--) { + if (status & (1 << i)) { + rt_printk(" %s", status_a_strings[i]); + } + } + rt_printk("\n"); +} +#endif + +#ifdef DEBUG_STATUS_B +static const char *const status_b_strings[] = { + "passthru1", "fifo", "G1_gate", "G1_TC", + "UI2_TC", "UPDATE", "UC_TC", "BC_TC", + "start1", "overrun", "start", "bc_tc_error", + "fifo_empty", "fifo_half_full", "fifo_full", "interrupt_b" +}; + +static void ni_mio_print_status_b(int status) +{ + int i; + + rt_printk("B status:"); + for (i = 15; i >= 0; i--) { + if (status & (1 << i)) { + rt_printk(" %s", status_b_strings[i]); + } + } + rt_printk("\n"); +} +#endif + +#ifndef PCIDMA + +static void ni_ao_fifo_load(struct comedi_device * dev, struct comedi_subdevice * s, int n) +{ + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + int chan; + int i; + short d; + u32 packed_data; + int range; + int err = 1; + + chan = async->cur_chan; + for (i = 0; i < n; i++) { + err &= comedi_buf_get(async, &d); + if (err == 0) + break; + + range = CR_RANGE(cmd->chanlist[chan]); + + if (boardtype.reg_type & ni_reg_6xxx_mask) { + packed_data = d & 0xffff; + /* 6711 only has 16 bit wide ao fifo */ + if (boardtype.reg_type != ni_reg_6711) { + err &= comedi_buf_get(async, &d); + if (err == 0) + break; + chan++; + i++; + packed_data |= (d << 16) & 0xffff0000; + } + ni_writel(packed_data, DAC_FIFO_Data_611x); + } else { + ni_writew(d, DAC_FIFO_Data); + } + chan++; + chan %= cmd->chanlist_len; + } + async->cur_chan = chan; + if (err == 0) { + async->events |= COMEDI_CB_OVERFLOW; + } +} + +/* + * There's a small problem if the FIFO gets really low and we + * don't have the data to fill it. Basically, if after we fill + * the FIFO with all the data available, the FIFO is _still_ + * less than half full, we never clear the interrupt. If the + * IRQ is in edge mode, we never get another interrupt, because + * this one wasn't cleared. If in level mode, we get flooded + * with interrupts that we can't fulfill, because nothing ever + * gets put into the buffer. + * + * This kind of situation is recoverable, but it is easier to + * just pretend we had a FIFO underrun, since there is a good + * chance it will happen anyway. This is _not_ the case for + * RT code, as RT code might purposely be running close to the + * metal. Needs to be fixed eventually. + */ +static int ni_ao_fifo_half_empty(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int n; + + n = comedi_buf_read_n_available(s->async); + if (n == 0) { + s->async->events |= COMEDI_CB_OVERFLOW; + return 0; + } + + n /= sizeof(short); + if (n > boardtype.ao_fifo_depth / 2) + n = boardtype.ao_fifo_depth / 2; + + ni_ao_fifo_load(dev, s, n); + + s->async->events |= COMEDI_CB_BLOCK; + + return 1; +} + +static int ni_ao_prep_fifo(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int n; + + /* reset fifo */ + devpriv->stc_writew(dev, 1, DAC_FIFO_Clear); + if (boardtype.reg_type & ni_reg_6xxx_mask) + ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); + + /* load some data */ + n = comedi_buf_read_n_available(s->async); + if (n == 0) + return 0; + + n /= sizeof(short); + if (n > boardtype.ao_fifo_depth) + n = boardtype.ao_fifo_depth; + + ni_ao_fifo_load(dev, s, n); + + return n; +} + +static void ni_ai_fifo_read(struct comedi_device * dev, struct comedi_subdevice * s, int n) +{ + struct comedi_async *async = s->async; + int i; + + if (boardtype.reg_type == ni_reg_611x) { + short data[2]; + u32 dl; + + for (i = 0; i < n / 2; i++) { + dl = ni_readl(ADC_FIFO_Data_611x); + /* This may get the hi/lo data in the wrong order */ + data[0] = (dl >> 16) & 0xffff; + data[1] = dl & 0xffff; + cfc_write_array_to_buffer(s, data, sizeof(data)); + } + /* Check if there's a single sample stuck in the FIFO */ + if (n % 2) { + dl = ni_readl(ADC_FIFO_Data_611x); + data[0] = dl & 0xffff; + cfc_write_to_buffer(s, data[0]); + } + } else if (boardtype.reg_type == ni_reg_6143) { + short data[2]; + u32 dl; + + // This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed + for (i = 0; i < n / 2; i++) { + dl = ni_readl(AIFIFO_Data_6143); + + data[0] = (dl >> 16) & 0xffff; + data[1] = dl & 0xffff; + cfc_write_array_to_buffer(s, data, sizeof(data)); + } + if (n % 2) { + /* Assume there is a single sample stuck in the FIFO */ + ni_writel(0x01, AIFIFO_Control_6143); // Get stranded sample into FIFO + dl = ni_readl(AIFIFO_Data_6143); + data[0] = (dl >> 16) & 0xffff; + cfc_write_to_buffer(s, data[0]); + } + } else { + if (n > sizeof(devpriv->ai_fifo_buffer) / + sizeof(devpriv->ai_fifo_buffer[0])) { + comedi_error(dev, "bug! ai_fifo_buffer too small"); + async->events |= COMEDI_CB_ERROR; + return; + } + for (i = 0; i < n; i++) { + devpriv->ai_fifo_buffer[i] = + ni_readw(ADC_FIFO_Data_Register); + } + cfc_write_array_to_buffer(s, devpriv->ai_fifo_buffer, + n * sizeof(devpriv->ai_fifo_buffer[0])); + } +} + +static void ni_handle_fifo_half_full(struct comedi_device * dev) +{ + int n; + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; + + n = boardtype.ai_fifo_depth / 2; + + ni_ai_fifo_read(dev, s, n); +} +#endif + +#ifdef PCIDMA +static int ni_ai_drain_dma(struct comedi_device * dev) +{ + int i; + static const int timeout = 10000; + unsigned long flags; + int retval = 0; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->ai_mite_chan) { + for (i = 0; i < timeout; i++) { + if ((devpriv->stc_readw(dev, + AI_Status_1_Register) & + AI_FIFO_Empty_St) + && mite_bytes_in_transit(devpriv-> + ai_mite_chan) == 0) + break; + comedi_udelay(5); + } + if (i == timeout) { + rt_printk + ("ni_mio_common: wait for dma drain timed out\n"); + rt_printk + ("mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n", + mite_bytes_in_transit(devpriv->ai_mite_chan), + devpriv->stc_readw(dev, AI_Status_1_Register)); + retval = -1; + } + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + + ni_sync_ai_dma(dev); + + return retval; +} +#endif +/* + Empties the AI fifo +*/ +static void ni_handle_fifo_dregs(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; + short data[2]; + u32 dl; + short fifo_empty; + int i; + + if (boardtype.reg_type == ni_reg_611x) { + while ((devpriv->stc_readw(dev, + AI_Status_1_Register) & + AI_FIFO_Empty_St) == 0) { + dl = ni_readl(ADC_FIFO_Data_611x); + + /* This may get the hi/lo data in the wrong order */ + data[0] = (dl >> 16); + data[1] = (dl & 0xffff); + cfc_write_array_to_buffer(s, data, sizeof(data)); + } + } else if (boardtype.reg_type == ni_reg_6143) { + i = 0; + while (ni_readl(AIFIFO_Status_6143) & 0x04) { + dl = ni_readl(AIFIFO_Data_6143); + + /* This may get the hi/lo data in the wrong order */ + data[0] = (dl >> 16); + data[1] = (dl & 0xffff); + cfc_write_array_to_buffer(s, data, sizeof(data)); + i += 2; + } + // Check if stranded sample is present + if (ni_readl(AIFIFO_Status_6143) & 0x01) { + ni_writel(0x01, AIFIFO_Control_6143); // Get stranded sample into FIFO + dl = ni_readl(AIFIFO_Data_6143); + data[0] = (dl >> 16) & 0xffff; + cfc_write_to_buffer(s, data[0]); + } + + } else { + fifo_empty = + devpriv->stc_readw(dev, + AI_Status_1_Register) & AI_FIFO_Empty_St; + while (fifo_empty == 0) { + for (i = 0; + i < + sizeof(devpriv->ai_fifo_buffer) / + sizeof(devpriv->ai_fifo_buffer[0]); i++) { + fifo_empty = + devpriv->stc_readw(dev, + AI_Status_1_Register) & + AI_FIFO_Empty_St; + if (fifo_empty) + break; + devpriv->ai_fifo_buffer[i] = + ni_readw(ADC_FIFO_Data_Register); + } + cfc_write_array_to_buffer(s, devpriv->ai_fifo_buffer, + i * sizeof(devpriv->ai_fifo_buffer[0])); + } + } +} + +static void get_last_sample_611x(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; + short data; + u32 dl; + + if (boardtype.reg_type != ni_reg_611x) + return; + + /* Check if there's a single sample stuck in the FIFO */ + if (ni_readb(XXX_Status) & 0x80) { + dl = ni_readl(ADC_FIFO_Data_611x); + data = (dl & 0xffff); + cfc_write_to_buffer(s, data); + } +} + +static void get_last_sample_6143(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; + short data; + u32 dl; + + if (boardtype.reg_type != ni_reg_6143) + return; + + /* Check if there's a single sample stuck in the FIFO */ + if (ni_readl(AIFIFO_Status_6143) & 0x01) { + ni_writel(0x01, AIFIFO_Control_6143); // Get stranded sample into FIFO + dl = ni_readl(AIFIFO_Data_6143); + + /* This may get the hi/lo data in the wrong order */ + data = (dl >> 16) & 0xffff; + cfc_write_to_buffer(s, data); + } +} + +static void ni_ai_munge(struct comedi_device * dev, struct comedi_subdevice * s, + void *data, unsigned int num_bytes, unsigned int chan_index) +{ + struct comedi_async *async = s->async; + unsigned int i; + unsigned int length = num_bytes / bytes_per_sample(s); + short *array = data; + unsigned int *larray = data; + for (i = 0; i < length; i++) { +#ifdef PCIDMA + if (s->subdev_flags & SDF_LSAMPL) + larray[i] = le32_to_cpu(larray[i]); + else + array[i] = le16_to_cpu(array[i]); +#endif + if (s->subdev_flags & SDF_LSAMPL) + larray[i] += devpriv->ai_offset[chan_index]; + else + array[i] += devpriv->ai_offset[chan_index]; + chan_index++; + chan_index %= async->cmd.chanlist_len; + } +} + +#ifdef PCIDMA + +static int ni_ai_setup_MITE_dma(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AI_SUBDEV; + int retval; + unsigned long flags; + + retval = ni_request_ai_mite_channel(dev); + if (retval) + return retval; +// rt_printk("comedi_debug: using mite channel %i for ai.\n", devpriv->ai_mite_chan->channel); + + /* write alloc the entire buffer */ + comedi_buf_write_alloc(s->async, s->async->prealloc_bufsz); + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if(devpriv->ai_mite_chan == NULL) + { + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + return -EIO; + } + + switch (boardtype.reg_type) { + case ni_reg_611x: + case ni_reg_6143: + mite_prep_dma(devpriv->ai_mite_chan, 32, 16); + break; + case ni_reg_628x: + mite_prep_dma(devpriv->ai_mite_chan, 32, 32); + break; + default: + mite_prep_dma(devpriv->ai_mite_chan, 16, 16); + break; + }; + /*start the MITE */ + mite_dma_arm(devpriv->ai_mite_chan); + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + + return 0; +} + +static int ni_ao_setup_MITE_dma(struct comedi_device * dev) +{ + struct comedi_subdevice *s = dev->subdevices + NI_AO_SUBDEV; + int retval; + unsigned long flags; + + retval = ni_request_ao_mite_channel(dev); + if (retval) + return retval; + + /* read alloc the entire buffer */ + comedi_buf_read_alloc(s->async, s->async->prealloc_bufsz); + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->ao_mite_chan) { + if (boardtype.reg_type & (ni_reg_611x | ni_reg_6713)) { + mite_prep_dma(devpriv->ao_mite_chan, 32, 32); + } else { + /* doing 32 instead of 16 bit wide transfers from memory + makes the mite do 32 bit pci transfers, doubling pci bandwidth. */ + mite_prep_dma(devpriv->ao_mite_chan, 16, 32); + } + mite_dma_arm(devpriv->ao_mite_chan); + } else + retval = -EIO; + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + + return retval; +} + +#endif // PCIDMA + +/* + used for both cancel ioctl and board initialization + + this is pretty harsh for a cancel, but it works... + */ + +static int ni_ai_reset(struct comedi_device * dev, struct comedi_subdevice * s) +{ + ni_release_ai_mite_channel(dev); + /* ai configuration */ + devpriv->stc_writew(dev, AI_Configuration_Start | AI_Reset, + Joint_Reset_Register); + + ni_set_bits(dev, Interrupt_A_Enable_Register, + AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable | + AI_START2_Interrupt_Enable | AI_START_Interrupt_Enable | + AI_STOP_Interrupt_Enable | AI_Error_Interrupt_Enable | + AI_FIFO_Interrupt_Enable, 0); + + ni_clear_ai_fifo(dev); + + if (boardtype.reg_type != ni_reg_6143) + ni_writeb(0, Misc_Command); + + devpriv->stc_writew(dev, AI_Disarm, AI_Command_1_Register); /* reset pulses */ + devpriv->stc_writew(dev, + AI_Start_Stop | AI_Mode_1_Reserved /*| AI_Trigger_Once */ , + AI_Mode_1_Register); + devpriv->stc_writew(dev, 0x0000, AI_Mode_2_Register); + /* generate FIFO interrupts on non-empty */ + devpriv->stc_writew(dev, (0 << 6) | 0x0000, AI_Mode_3_Register); + if (boardtype.reg_type == ni_reg_611x) { + devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | + AI_SOC_Polarity | + AI_LOCALMUX_CLK_Pulse_Width, AI_Personal_Register); + devpriv->stc_writew(dev, AI_SCAN_IN_PROG_Output_Select(3) | + AI_EXTMUX_CLK_Output_Select(0) | + AI_LOCALMUX_CLK_Output_Select(2) | + AI_SC_TC_Output_Select(3) | + AI_CONVERT_Output_Select(AI_CONVERT_Output_Enable_High), + AI_Output_Control_Register); + } else if (boardtype.reg_type == ni_reg_6143) { + devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | + AI_SOC_Polarity | + AI_LOCALMUX_CLK_Pulse_Width, AI_Personal_Register); + devpriv->stc_writew(dev, AI_SCAN_IN_PROG_Output_Select(3) | + AI_EXTMUX_CLK_Output_Select(0) | + AI_LOCALMUX_CLK_Output_Select(2) | + AI_SC_TC_Output_Select(3) | + AI_CONVERT_Output_Select(AI_CONVERT_Output_Enable_Low), + AI_Output_Control_Register); + } else { + unsigned ai_output_control_bits; + devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | + AI_SOC_Polarity | + AI_CONVERT_Pulse_Width | + AI_LOCALMUX_CLK_Pulse_Width, AI_Personal_Register); + ai_output_control_bits = AI_SCAN_IN_PROG_Output_Select(3) | + AI_EXTMUX_CLK_Output_Select(0) | + AI_LOCALMUX_CLK_Output_Select(2) | + AI_SC_TC_Output_Select(3); + if (boardtype.reg_type == ni_reg_622x) + ai_output_control_bits |= + AI_CONVERT_Output_Select + (AI_CONVERT_Output_Enable_High); + else + ai_output_control_bits |= + AI_CONVERT_Output_Select + (AI_CONVERT_Output_Enable_Low); + devpriv->stc_writew(dev, ai_output_control_bits, + AI_Output_Control_Register); + } + /* the following registers should not be changed, because there + * are no backup registers in devpriv. If you want to change + * any of these, add a backup register and other appropriate code: + * AI_Mode_1_Register + * AI_Mode_3_Register + * AI_Personal_Register + * AI_Output_Control_Register + */ + devpriv->stc_writew(dev, AI_SC_TC_Error_Confirm | AI_START_Interrupt_Ack | AI_START2_Interrupt_Ack | AI_START1_Interrupt_Ack | AI_SC_TC_Interrupt_Ack | AI_Error_Interrupt_Ack | AI_STOP_Interrupt_Ack, Interrupt_A_Ack_Register); /* clear interrupts */ + + devpriv->stc_writew(dev, AI_Configuration_End, Joint_Reset_Register); + + return 0; +} + +static int ni_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags = 0; + int count; + + // lock to avoid race with interrupt handler + if (in_interrupt() == 0) + comedi_spin_lock_irqsave(&dev->spinlock, flags); +#ifndef PCIDMA + ni_handle_fifo_dregs(dev); +#else + ni_sync_ai_dma(dev); +#endif + count = s->async->buf_write_count - s->async->buf_read_count; + if (in_interrupt() == 0) + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + return count; +} + +static int ni_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, n; + const unsigned int mask = (1 << boardtype.adbits) - 1; + unsigned signbits; + unsigned short d; + unsigned long dl; + + ni_load_channelgain_list(dev, 1, &insn->chanspec); + + ni_clear_ai_fifo(dev); + + signbits = devpriv->ai_offset[0]; + if (boardtype.reg_type == ni_reg_611x) { + for (n = 0; n < num_adc_stages_611x; n++) { + devpriv->stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); + comedi_udelay(1); + } + for (n = 0; n < insn->n; n++) { + devpriv->stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); + /* The 611x has screwy 32-bit FIFOs. */ + d = 0; + for (i = 0; i < NI_TIMEOUT; i++) { + if (ni_readb(XXX_Status) & 0x80) { + d = (ni_readl(ADC_FIFO_Data_611x) >> 16) + & 0xffff; + break; + } + if (!(devpriv->stc_readw(dev, + AI_Status_1_Register) & + AI_FIFO_Empty_St)) { + d = ni_readl(ADC_FIFO_Data_611x) & + 0xffff; + break; + } + } + if (i == NI_TIMEOUT) { + rt_printk + ("ni_mio_common: timeout in 611x ni_ai_insn_read\n"); + return -ETIME; + } + d += signbits; + data[n] = d; + } + } else if (boardtype.reg_type == ni_reg_6143) { + for (n = 0; n < insn->n; n++) { + devpriv->stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); + + /* The 6143 has 32-bit FIFOs. You need to strobe a bit to move a single 16bit stranded sample into the FIFO */ + dl = 0; + for (i = 0; i < NI_TIMEOUT; i++) { + if (ni_readl(AIFIFO_Status_6143) & 0x01) { + ni_writel(0x01, AIFIFO_Control_6143); // Get stranded sample into FIFO + dl = ni_readl(AIFIFO_Data_6143); + break; + } + } + if (i == NI_TIMEOUT) { + rt_printk + ("ni_mio_common: timeout in 6143 ni_ai_insn_read\n"); + return -ETIME; + } + data[n] = (((dl >> 16) & 0xFFFF) + signbits) & 0xFFFF; + } + } else { + for (n = 0; n < insn->n; n++) { + devpriv->stc_writew(dev, AI_CONVERT_Pulse, + AI_Command_1_Register); + for (i = 0; i < NI_TIMEOUT; i++) { + if (!(devpriv->stc_readw(dev, + AI_Status_1_Register) & + AI_FIFO_Empty_St)) + break; + } + if (i == NI_TIMEOUT) { + rt_printk + ("ni_mio_common: timeout in ni_ai_insn_read\n"); + return -ETIME; + } + if (boardtype.reg_type & ni_reg_m_series_mask) { + data[n] = + ni_readl(M_Offset_AI_FIFO_Data) & mask; + } else { + d = ni_readw(ADC_FIFO_Data_Register); + d += signbits; /* subtle: needs to be short addition */ + data[n] = d; + } + } + } + return insn->n; +} + +void ni_prime_channelgain_list(struct comedi_device * dev) +{ + int i; + devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register); + for (i = 0; i < NI_TIMEOUT; ++i) { + if (!(devpriv->stc_readw(dev, + AI_Status_1_Register) & + AI_FIFO_Empty_St)) { + devpriv->stc_writew(dev, 1, ADC_FIFO_Clear); + return; + } + comedi_udelay(1); + } + rt_printk("ni_mio_common: timeout loading channel/gain list\n"); +} + +static void ni_m_series_load_channelgain_list(struct comedi_device * dev, + unsigned int n_chan, unsigned int *list) +{ + unsigned int chan, range, aref; + unsigned int i; + unsigned offset; + unsigned int dither; + unsigned range_code; + + devpriv->stc_writew(dev, 1, Configuration_Memory_Clear); + +// offset = 1 << (boardtype.adbits - 1); + if ((list[0] & CR_ALT_SOURCE)) { + unsigned bypass_bits; + chan = CR_CHAN(list[0]); + range = CR_RANGE(list[0]); + range_code = ni_gainlkup[boardtype.gainlkup][range]; + dither = ((list[0] & CR_ALT_FILTER) != 0); + bypass_bits = MSeries_AI_Bypass_Config_FIFO_Bit; + bypass_bits |= chan; + bypass_bits |= + (devpriv-> + ai_calib_source) & (MSeries_AI_Bypass_Cal_Sel_Pos_Mask | + MSeries_AI_Bypass_Cal_Sel_Neg_Mask | + MSeries_AI_Bypass_Mode_Mux_Mask | + MSeries_AO_Bypass_AO_Cal_Sel_Mask); + bypass_bits |= MSeries_AI_Bypass_Gain_Bits(range_code); + if (dither) + bypass_bits |= MSeries_AI_Bypass_Dither_Bit; + // don't use 2's complement encoding + bypass_bits |= MSeries_AI_Bypass_Polarity_Bit; + ni_writel(bypass_bits, M_Offset_AI_Config_FIFO_Bypass); + } else { + ni_writel(0, M_Offset_AI_Config_FIFO_Bypass); + } + offset = 0; + for (i = 0; i < n_chan; i++) { + unsigned config_bits = 0; + chan = CR_CHAN(list[i]); + aref = CR_AREF(list[i]); + range = CR_RANGE(list[i]); + dither = ((list[i] & CR_ALT_FILTER) != 0); + + range_code = ni_gainlkup[boardtype.gainlkup][range]; + devpriv->ai_offset[i] = offset; + switch (aref) { + case AREF_DIFF: + config_bits |= + MSeries_AI_Config_Channel_Type_Differential_Bits; + break; + case AREF_COMMON: + config_bits |= + MSeries_AI_Config_Channel_Type_Common_Ref_Bits; + break; + case AREF_GROUND: + config_bits |= + MSeries_AI_Config_Channel_Type_Ground_Ref_Bits; + break; + case AREF_OTHER: + break; + } + config_bits |= MSeries_AI_Config_Channel_Bits(chan); + config_bits |= + MSeries_AI_Config_Bank_Bits(boardtype.reg_type, chan); + config_bits |= MSeries_AI_Config_Gain_Bits(range_code); + if (i == n_chan - 1) + config_bits |= MSeries_AI_Config_Last_Channel_Bit; + if (dither) + config_bits |= MSeries_AI_Config_Dither_Bit; + // don't use 2's complement encoding + config_bits |= MSeries_AI_Config_Polarity_Bit; + ni_writew(config_bits, M_Offset_AI_Config_FIFO_Data); + } + ni_prime_channelgain_list(dev); +} + +/* + * Notes on the 6110 and 6111: + * These boards a slightly different than the rest of the series, since + * they have multiple A/D converters. + * From the driver side, the configuration memory is a + * little different. + * Configuration Memory Low: + * bits 15-9: same + * bit 8: unipolar/bipolar (should be 0 for bipolar) + * bits 0-3: gain. This is 4 bits instead of 3 for the other boards + * 1001 gain=0.1 (+/- 50) + * 1010 0.2 + * 1011 0.1 + * 0001 1 + * 0010 2 + * 0011 5 + * 0100 10 + * 0101 20 + * 0110 50 + * Configuration Memory High: + * bits 12-14: Channel Type + * 001 for differential + * 000 for calibration + * bit 11: coupling (this is not currently handled) + * 1 AC coupling + * 0 DC coupling + * bits 0-2: channel + * valid channels are 0-3 + */ +static void ni_load_channelgain_list(struct comedi_device * dev, unsigned int n_chan, + unsigned int *list) +{ + unsigned int chan, range, aref; + unsigned int i; + unsigned int hi, lo; + unsigned offset; + unsigned int dither; + + if (boardtype.reg_type & ni_reg_m_series_mask) { + ni_m_series_load_channelgain_list(dev, n_chan, list); + return; + } + if (n_chan == 1 && (boardtype.reg_type != ni_reg_611x) + && (boardtype.reg_type != ni_reg_6143)) { + if (devpriv->changain_state + && devpriv->changain_spec == list[0]) { + // ready to go. + return; + } + devpriv->changain_state = 1; + devpriv->changain_spec = list[0]; + } else { + devpriv->changain_state = 0; + } + + devpriv->stc_writew(dev, 1, Configuration_Memory_Clear); + + // Set up Calibration mode if required + if (boardtype.reg_type == ni_reg_6143) { + if ((list[0] & CR_ALT_SOURCE) + && !devpriv->ai_calib_source_enabled) { + // Strobe Relay enable bit + ni_writew(devpriv-> + ai_calib_source | + Calibration_Channel_6143_RelayOn, + Calibration_Channel_6143); + ni_writew(devpriv->ai_calib_source, + Calibration_Channel_6143); + devpriv->ai_calib_source_enabled = 1; + msleep_interruptible(100); // Allow relays to change + } else if (!(list[0] & CR_ALT_SOURCE) + && devpriv->ai_calib_source_enabled) { + // Strobe Relay disable bit + ni_writew(devpriv-> + ai_calib_source | + Calibration_Channel_6143_RelayOff, + Calibration_Channel_6143); + ni_writew(devpriv->ai_calib_source, + Calibration_Channel_6143); + devpriv->ai_calib_source_enabled = 0; + msleep_interruptible(100); // Allow relays to change + } + } + + offset = 1 << (boardtype.adbits - 1); + for (i = 0; i < n_chan; i++) { + if ((boardtype.reg_type != ni_reg_6143) + && (list[i] & CR_ALT_SOURCE)) { + chan = devpriv->ai_calib_source; + } else { + chan = CR_CHAN(list[i]); + } + aref = CR_AREF(list[i]); + range = CR_RANGE(list[i]); + dither = ((list[i] & CR_ALT_FILTER) != 0); + + /* fix the external/internal range differences */ + range = ni_gainlkup[boardtype.gainlkup][range]; + if (boardtype.reg_type == ni_reg_611x) + devpriv->ai_offset[i] = offset; + else + devpriv->ai_offset[i] = (range & 0x100) ? 0 : offset; + + hi = 0; + if ((list[i] & CR_ALT_SOURCE)) { + if (boardtype.reg_type == ni_reg_611x) + ni_writew(CR_CHAN(list[i]) & 0x0003, + Calibration_Channel_Select_611x); + } else { + if (boardtype.reg_type == ni_reg_611x) + aref = AREF_DIFF; + else if (boardtype.reg_type == ni_reg_6143) + aref = AREF_OTHER; + switch (aref) { + case AREF_DIFF: + hi |= AI_DIFFERENTIAL; + break; + case AREF_COMMON: + hi |= AI_COMMON; + break; + case AREF_GROUND: + hi |= AI_GROUND; + break; + case AREF_OTHER: + break; + } + } + hi |= AI_CONFIG_CHANNEL(chan); + + ni_writew(hi, Configuration_Memory_High); + + if (boardtype.reg_type != ni_reg_6143) { + lo = range; + if (i == n_chan - 1) + lo |= AI_LAST_CHANNEL; + if (dither) + lo |= AI_DITHER; + + ni_writew(lo, Configuration_Memory_Low); + } + } + + /* prime the channel/gain list */ + if ((boardtype.reg_type != ni_reg_611x) + && (boardtype.reg_type != ni_reg_6143)) { + ni_prime_channelgain_list(dev); + } +} + +static int ni_ns_to_timer(const struct comedi_device * dev, unsigned nanosec, + int round_mode) +{ + int divider; + switch (round_mode) { + case TRIG_ROUND_NEAREST: + default: + divider = (nanosec + devpriv->clock_ns / 2) / devpriv->clock_ns; + break; + case TRIG_ROUND_DOWN: + divider = (nanosec) / devpriv->clock_ns; + break; + case TRIG_ROUND_UP: + divider = (nanosec + devpriv->clock_ns - 1) / devpriv->clock_ns; + break; + } + return divider - 1; +} + +static unsigned ni_timer_to_ns(const struct comedi_device * dev, int timer) +{ + return devpriv->clock_ns * (timer + 1); +} + +static unsigned ni_min_ai_scan_period_ns(struct comedi_device * dev, + unsigned num_channels) +{ + switch (boardtype.reg_type) { + case ni_reg_611x: + case ni_reg_6143: + // simultaneously-sampled inputs + return boardtype.ai_speed; + break; + default: + // multiplexed inputs + break; + }; + return boardtype.ai_speed * num_channels; +} + +static int ni_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + int sources; + + /* step 1: make sure trigger sources are trivially valid */ + + if ((cmd->flags & CMDF_WRITE)) { + cmd->flags &= ~CMDF_WRITE; + } + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + sources = TRIG_TIMER | TRIG_EXT; + if ((boardtype.reg_type == ni_reg_611x) + || (boardtype.reg_type == ni_reg_6143)) + sources |= TRIG_NOW; + cmd->convert_src &= sources; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->start_src != TRIG_NOW && + cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_OTHER) + err++; + if (cmd->convert_src != TRIG_TIMER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_src == TRIG_EXT) { + /* external trigger */ + unsigned int tmp = CR_CHAN(cmd->start_arg); + + if (tmp > 16) + tmp = 16; + tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE)); + if (cmd->start_arg != tmp) { + cmd->start_arg = tmp; + err++; + } + } else { + if (cmd->start_arg != 0) { + /* true for both TRIG_NOW and TRIG_INT */ + cmd->start_arg = 0; + err++; + } + } + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < ni_min_ai_scan_period_ns(dev, + cmd->chanlist_len)) { + cmd->scan_begin_arg = + ni_min_ai_scan_period_ns(dev, + cmd->chanlist_len); + err++; + } + if (cmd->scan_begin_arg > devpriv->clock_ns * 0xffffff) { + cmd->scan_begin_arg = devpriv->clock_ns * 0xffffff; + err++; + } + } else if (cmd->scan_begin_src == TRIG_EXT) { + /* external trigger */ + unsigned int tmp = CR_CHAN(cmd->scan_begin_arg); + + if (tmp > 16) + tmp = 16; + tmp |= (cmd->scan_begin_arg & (CR_INVERT | CR_EDGE)); + if (cmd->scan_begin_arg != tmp) { + cmd->scan_begin_arg = tmp; + err++; + } + } else { /* TRIG_OTHER */ + if (cmd->scan_begin_arg) { + cmd->scan_begin_arg = 0; + err++; + } + } + if (cmd->convert_src == TRIG_TIMER) { + if ((boardtype.reg_type == ni_reg_611x) + || (boardtype.reg_type == ni_reg_6143)) { + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + } else { + if (cmd->convert_arg < boardtype.ai_speed) { + cmd->convert_arg = boardtype.ai_speed; + err++; + } + if (cmd->convert_arg > devpriv->clock_ns * 0xffff) { + cmd->convert_arg = devpriv->clock_ns * 0xffff; + err++; + } + } + } else if (cmd->convert_src == TRIG_EXT) { + /* external trigger */ + unsigned int tmp = CR_CHAN(cmd->convert_arg); + + if (tmp > 16) + tmp = 16; + tmp |= (cmd->convert_arg & (CR_ALT_FILTER | CR_INVERT)); + if (cmd->convert_arg != tmp) { + cmd->convert_arg = tmp; + err++; + } + } else if (cmd->convert_src == TRIG_NOW) { + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + unsigned int max_count = 0x01000000; + + if (boardtype.reg_type == ni_reg_611x) + max_count -= num_adc_stages_611x; + if (cmd->stop_arg > max_count) { + cmd->stop_arg = max_count; + err++; + } + if (cmd->stop_arg < 1) { + cmd->stop_arg = 1; + err++; + } + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + cmd->scan_begin_arg = + ni_timer_to_ns(dev, ni_ns_to_timer(dev, + cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK)); + if (tmp != cmd->scan_begin_arg) + err++; + } + if (cmd->convert_src == TRIG_TIMER) { + if ((boardtype.reg_type != ni_reg_611x) + && (boardtype.reg_type != ni_reg_6143)) { + tmp = cmd->convert_arg; + cmd->convert_arg = + ni_timer_to_ns(dev, ni_ns_to_timer(dev, + cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK)); + if (tmp != cmd->convert_arg) + err++; + if (cmd->scan_begin_src == TRIG_TIMER && + cmd->scan_begin_arg < + cmd->convert_arg * cmd->scan_end_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->scan_end_arg; + err++; + } + } + } + + if (err) + return 4; + + return 0; +} + +static int ni_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + const struct comedi_cmd *cmd = &s->async->cmd; + int timer; + int mode1 = 0; /* mode1 is needed for both stop and convert */ + int mode2 = 0; + int start_stop_select = 0; + unsigned int stop_count; + int interrupt_a_enable = 0; + + MDPRINTK("ni_ai_cmd\n"); + if (dev->irq == 0) { + comedi_error(dev, "cannot run command without an irq"); + return -EIO; + } + ni_clear_ai_fifo(dev); + + ni_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist); + + /* start configuration */ + devpriv->stc_writew(dev, AI_Configuration_Start, Joint_Reset_Register); + + /* disable analog triggering for now, since it + * interferes with the use of pfi0 */ + devpriv->an_trig_etc_reg &= ~Analog_Trigger_Enable; + devpriv->stc_writew(dev, devpriv->an_trig_etc_reg, + Analog_Trigger_Etc_Register); + + switch (cmd->start_src) { + case TRIG_INT: + case TRIG_NOW: + devpriv->stc_writew(dev, AI_START2_Select(0) | + AI_START1_Sync | AI_START1_Edge | AI_START1_Select(0), + AI_Trigger_Select_Register); + break; + case TRIG_EXT: + { + int chan = CR_CHAN(cmd->start_arg); + unsigned int bits = AI_START2_Select(0) | + AI_START1_Sync | AI_START1_Select(chan + 1); + + if (cmd->start_arg & CR_INVERT) + bits |= AI_START1_Polarity; + if (cmd->start_arg & CR_EDGE) + bits |= AI_START1_Edge; + devpriv->stc_writew(dev, bits, + AI_Trigger_Select_Register); + break; + } + } + + mode2 &= ~AI_Pre_Trigger; + mode2 &= ~AI_SC_Initial_Load_Source; + mode2 &= ~AI_SC_Reload_Mode; + devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + + if (cmd->chanlist_len == 1 || (boardtype.reg_type == ni_reg_611x) + || (boardtype.reg_type == ni_reg_6143)) { + start_stop_select |= AI_STOP_Polarity; + start_stop_select |= AI_STOP_Select(31); // logic low + start_stop_select |= AI_STOP_Sync; + } else { + start_stop_select |= AI_STOP_Select(19); // ai configuration memory + } + devpriv->stc_writew(dev, start_stop_select, + AI_START_STOP_Select_Register); + + devpriv->ai_cmd2 = 0; + switch (cmd->stop_src) { + case TRIG_COUNT: + stop_count = cmd->stop_arg - 1; + + if (boardtype.reg_type == ni_reg_611x) { + // have to take 3 stage adc pipeline into account + stop_count += num_adc_stages_611x; + } + /* stage number of scans */ + devpriv->stc_writel(dev, stop_count, AI_SC_Load_A_Registers); + + mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Trigger_Once; + devpriv->stc_writew(dev, mode1, AI_Mode_1_Register); + /* load SC (Scan Count) */ + devpriv->stc_writew(dev, AI_SC_Load, AI_Command_1_Register); + + devpriv->ai_continuous = 0; + if (stop_count == 0) { + devpriv->ai_cmd2 |= AI_End_On_End_Of_Scan; + interrupt_a_enable |= AI_STOP_Interrupt_Enable; + // this is required to get the last sample for chanlist_len > 1, not sure why + if (cmd->chanlist_len > 1) + start_stop_select |= + AI_STOP_Polarity | AI_STOP_Edge; + } + break; + case TRIG_NONE: + /* stage number of scans */ + devpriv->stc_writel(dev, 0, AI_SC_Load_A_Registers); + + mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Continuous; + devpriv->stc_writew(dev, mode1, AI_Mode_1_Register); + + /* load SC (Scan Count) */ + devpriv->stc_writew(dev, AI_SC_Load, AI_Command_1_Register); + + devpriv->ai_continuous = 1; + + break; + } + + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + /* + stop bits for non 611x boards + AI_SI_Special_Trigger_Delay=0 + AI_Pre_Trigger=0 + AI_START_STOP_Select_Register: + AI_START_Polarity=0 (?) rising edge + AI_START_Edge=1 edge triggered + AI_START_Sync=1 (?) + AI_START_Select=0 SI_TC + AI_STOP_Polarity=0 rising edge + AI_STOP_Edge=0 level + AI_STOP_Sync=1 + AI_STOP_Select=19 external pin (configuration mem) + */ + start_stop_select |= AI_START_Edge | AI_START_Sync; + devpriv->stc_writew(dev, start_stop_select, + AI_START_STOP_Select_Register); + + mode2 |= AI_SI_Reload_Mode(0); + /* AI_SI_Initial_Load_Source=A */ + mode2 &= ~AI_SI_Initial_Load_Source; + //mode2 |= AI_SC_Reload_Mode; + devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + + /* load SI */ + timer = ni_ns_to_timer(dev, cmd->scan_begin_arg, + TRIG_ROUND_NEAREST); + devpriv->stc_writel(dev, timer, AI_SI_Load_A_Registers); + devpriv->stc_writew(dev, AI_SI_Load, AI_Command_1_Register); + break; + case TRIG_EXT: + if (cmd->scan_begin_arg & CR_EDGE) + start_stop_select |= AI_START_Edge; + /* AI_START_Polarity==1 is falling edge */ + if (cmd->scan_begin_arg & CR_INVERT) + start_stop_select |= AI_START_Polarity; + if (cmd->scan_begin_src != cmd->convert_src || + (cmd->scan_begin_arg & ~CR_EDGE) != + (cmd->convert_arg & ~CR_EDGE)) + start_stop_select |= AI_START_Sync; + start_stop_select |= + AI_START_Select(1 + CR_CHAN(cmd->scan_begin_arg)); + devpriv->stc_writew(dev, start_stop_select, + AI_START_STOP_Select_Register); + break; + } + + switch (cmd->convert_src) { + case TRIG_TIMER: + case TRIG_NOW: + if (cmd->convert_arg == 0 || cmd->convert_src == TRIG_NOW) + timer = 1; + else + timer = ni_ns_to_timer(dev, cmd->convert_arg, + TRIG_ROUND_NEAREST); + devpriv->stc_writew(dev, 1, AI_SI2_Load_A_Register); /* 0,0 does not work. */ + devpriv->stc_writew(dev, timer, AI_SI2_Load_B_Register); + + /* AI_SI2_Reload_Mode = alternate */ + /* AI_SI2_Initial_Load_Source = A */ + mode2 &= ~AI_SI2_Initial_Load_Source; + mode2 |= AI_SI2_Reload_Mode; + devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + + /* AI_SI2_Load */ + devpriv->stc_writew(dev, AI_SI2_Load, AI_Command_1_Register); + + mode2 |= AI_SI2_Reload_Mode; // alternate + mode2 |= AI_SI2_Initial_Load_Source; // B + + devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + break; + case TRIG_EXT: + mode1 |= AI_CONVERT_Source_Select(1 + cmd->convert_arg); + if ((cmd->convert_arg & CR_INVERT) == 0) + mode1 |= AI_CONVERT_Source_Polarity; + devpriv->stc_writew(dev, mode1, AI_Mode_1_Register); + + mode2 |= AI_Start_Stop_Gate_Enable | AI_SC_Gate_Enable; + devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); + + break; + } + + if (dev->irq) { + + /* interrupt on FIFO, errors, SC_TC */ + interrupt_a_enable |= AI_Error_Interrupt_Enable | + AI_SC_TC_Interrupt_Enable; + +#ifndef PCIDMA + interrupt_a_enable |= AI_FIFO_Interrupt_Enable; +#endif + + if (cmd->flags & TRIG_WAKE_EOS + || (devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)) { + /* wake on end-of-scan */ + devpriv->aimode = AIMODE_SCAN; + } else { + devpriv->aimode = AIMODE_HALF_FULL; + } + + switch (devpriv->aimode) { + case AIMODE_HALF_FULL: + /*generate FIFO interrupts and DMA requests on half-full */ +#ifdef PCIDMA + devpriv->stc_writew(dev, AI_FIFO_Mode_HF_to_E, + AI_Mode_3_Register); +#else + devpriv->stc_writew(dev, AI_FIFO_Mode_HF, + AI_Mode_3_Register); +#endif + break; + case AIMODE_SAMPLE: + /*generate FIFO interrupts on non-empty */ + devpriv->stc_writew(dev, AI_FIFO_Mode_NE, + AI_Mode_3_Register); + break; + case AIMODE_SCAN: +#ifdef PCIDMA + devpriv->stc_writew(dev, AI_FIFO_Mode_NE, + AI_Mode_3_Register); +#else + devpriv->stc_writew(dev, AI_FIFO_Mode_HF, + AI_Mode_3_Register); +#endif + interrupt_a_enable |= AI_STOP_Interrupt_Enable; + break; + default: + break; + } + + devpriv->stc_writew(dev, AI_Error_Interrupt_Ack | AI_STOP_Interrupt_Ack | AI_START_Interrupt_Ack | AI_START2_Interrupt_Ack | AI_START1_Interrupt_Ack | AI_SC_TC_Interrupt_Ack | AI_SC_TC_Error_Confirm, Interrupt_A_Ack_Register); /* clear interrupts */ + + ni_set_bits(dev, Interrupt_A_Enable_Register, + interrupt_a_enable, 1); + + MDPRINTK("Interrupt_A_Enable_Register = 0x%04x\n", + devpriv->int_a_enable_reg); + } else { + /* interrupt on nothing */ + ni_set_bits(dev, Interrupt_A_Enable_Register, ~0, 0); + + /* XXX start polling if necessary */ + MDPRINTK("interrupting on nothing\n"); + } + + /* end configuration */ + devpriv->stc_writew(dev, AI_Configuration_End, Joint_Reset_Register); + + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + devpriv->stc_writew(dev, + AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, + AI_Command_1_Register); + break; + case TRIG_EXT: + /* XXX AI_SI_Arm? */ + devpriv->stc_writew(dev, + AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, + AI_Command_1_Register); + break; + } + +#ifdef PCIDMA + { + int retval = ni_ai_setup_MITE_dma(dev); + if (retval) + return retval; + } + //mite_dump_regs(devpriv->mite); +#endif + + switch (cmd->start_src) { + case TRIG_NOW: + /* AI_START1_Pulse */ + devpriv->stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, + AI_Command_2_Register); + s->async->inttrig = NULL; + break; + case TRIG_EXT: + s->async->inttrig = NULL; + break; + case TRIG_INT: + s->async->inttrig = &ni_ai_inttrig; + break; + } + + MDPRINTK("exit ni_ai_cmd\n"); + + return 0; +} + +static int ni_ai_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ + if (trignum != 0) + return -EINVAL; + + devpriv->stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, + AI_Command_2_Register); + s->async->inttrig = NULL; + + return 1; +} + +static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int ni_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n < 1) + return -EINVAL; + + switch (data[0]) { + case INSN_CONFIG_ANALOG_TRIG: + return ni_ai_config_analog_trig(dev, s, insn, data); + case INSN_CONFIG_ALT_SOURCE: + if (boardtype.reg_type & ni_reg_m_series_mask) { + if (data[1] & ~(MSeries_AI_Bypass_Cal_Sel_Pos_Mask | + MSeries_AI_Bypass_Cal_Sel_Neg_Mask | + MSeries_AI_Bypass_Mode_Mux_Mask | + MSeries_AO_Bypass_AO_Cal_Sel_Mask)) { + return -EINVAL; + } + devpriv->ai_calib_source = data[1]; + } else if (boardtype.reg_type == ni_reg_6143) { + unsigned int calib_source; + + calib_source = data[1] & 0xf; + + if (calib_source > 0xF) + return -EINVAL; + + devpriv->ai_calib_source = calib_source; + ni_writew(calib_source, Calibration_Channel_6143); + } else { + unsigned int calib_source; + unsigned int calib_source_adjust; + + calib_source = data[1] & 0xf; + calib_source_adjust = (data[1] >> 4) & 0xff; + + if (calib_source >= 8) + return -EINVAL; + devpriv->ai_calib_source = calib_source; + if (boardtype.reg_type == ni_reg_611x) { + ni_writeb(calib_source_adjust, + Cal_Gain_Select_611x); + } + } + return 2; + default: + break; + } + + return -EINVAL; +} + +static int ni_ai_config_analog_trig(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int a, b, modebits; + int err = 0; + + /* data[1] is flags + * data[2] is analog line + * data[3] is set level + * data[4] is reset level */ + if (!boardtype.has_analog_trig) + return -EINVAL; + if ((data[1] & 0xffff0000) != COMEDI_EV_SCAN_BEGIN) { + data[1] &= (COMEDI_EV_SCAN_BEGIN | 0xffff); + err++; + } + if (data[2] >= boardtype.n_adchan) { + data[2] = boardtype.n_adchan - 1; + err++; + } + if (data[3] > 255) { /* a */ + data[3] = 255; + err++; + } + if (data[4] > 255) { /* b */ + data[4] = 255; + err++; + } + /* + * 00 ignore + * 01 set + * 10 reset + * + * modes: + * 1 level: +b- +a- + * high mode 00 00 01 10 + * low mode 00 00 10 01 + * 2 level: (a> + 4); + } + devpriv->atrig_low = a; + devpriv->atrig_high = b; + switch (modebits) { + case 0x81: /* low hysteresis mode */ + devpriv->atrig_mode = 6; + break; + case 0x42: /* high hysteresis mode */ + devpriv->atrig_mode = 3; + break; + case 0x96: /* middle window mode */ + devpriv->atrig_mode = 2; + break; + default: + data[1] &= ~0xff; + err++; + } + } else { + /* one level mode */ + if (b != 0) { + data[4] = 0; + err++; + } + switch (modebits) { + case 0x06: /* high window mode */ + devpriv->atrig_high = a; + devpriv->atrig_mode = 0; + break; + case 0x09: /* low window mode */ + devpriv->atrig_low = a; + devpriv->atrig_mode = 1; + break; + default: + data[1] &= ~0xff; + err++; + } + } + if (err) + return -EAGAIN; + return 5; +} + +/* munge data from unsigned to 2's complement for analog output bipolar modes */ +static void ni_ao_munge(struct comedi_device * dev, struct comedi_subdevice * s, + void *data, unsigned int num_bytes, unsigned int chan_index) +{ + struct comedi_async *async = s->async; + unsigned int range; + unsigned int i; + unsigned int offset; + unsigned int length = num_bytes / sizeof(short); + short *array = data; + + offset = 1 << (boardtype.aobits - 1); + for (i = 0; i < length; i++) { + range = CR_RANGE(async->cmd.chanlist[chan_index]); + if (boardtype.ao_unipolar == 0 || (range & 1) == 0) + array[i] -= offset; +#ifdef PCIDMA + array[i] = cpu_to_le16(array[i]); +#endif + chan_index++; + chan_index %= async->cmd.chanlist_len; + } +} + +static int ni_m_series_ao_config_chanlist(struct comedi_device * dev, + struct comedi_subdevice * s, unsigned int chanspec[], unsigned int n_chans, + int timed) +{ + unsigned int range; + unsigned int chan; + unsigned int conf; + int i; + int invert = 0; + + if(timed) { + for (i = 0; i < boardtype.n_aochan; ++i) { + devpriv->ao_conf[i] &= ~MSeries_AO_Update_Timed_Bit; + ni_writeb(devpriv->ao_conf[i], M_Offset_AO_Config_Bank(i)); + ni_writeb(0xf, M_Offset_AO_Waveform_Order(i)); + } + } + for (i = 0; i < n_chans; i++) { + const struct comedi_krange *krange; + chan = CR_CHAN(chanspec[i]); + range = CR_RANGE(chanspec[i]); + krange = s->range_table->range + range; + invert = 0; + conf = 0; + switch (krange->max - krange->min) { + case 20000000: + conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; + ni_writeb(0, M_Offset_AO_Reference_Attenuation(chan)); + break; + case 10000000: + conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; + ni_writeb(0, M_Offset_AO_Reference_Attenuation(chan)); + break; + case 4000000: + conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; + ni_writeb(MSeries_Attenuate_x5_Bit, + M_Offset_AO_Reference_Attenuation(chan)); + break; + case 2000000: + conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; + ni_writeb(MSeries_Attenuate_x5_Bit, + M_Offset_AO_Reference_Attenuation(chan)); + break; + default: + rt_printk("%s: bug! unhandled ao reference voltage\n", + __FUNCTION__); + break; + } + switch (krange->max + krange->min) { + case 0: + conf |= MSeries_AO_DAC_Offset_0V_Bits; + break; + case 10000000: + conf |= MSeries_AO_DAC_Offset_5V_Bits; + break; + default: + rt_printk("%s: bug! unhandled ao offset voltage\n", + __FUNCTION__); + break; + } + if (timed) + conf |= MSeries_AO_Update_Timed_Bit; + ni_writeb(conf, M_Offset_AO_Config_Bank(chan)); + devpriv->ao_conf[chan] = conf; + ni_writeb(i, M_Offset_AO_Waveform_Order(chan)); + } + return invert; +} + +static int ni_old_ao_config_chanlist(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int chanspec[], unsigned int n_chans) +{ + unsigned int range; + unsigned int chan; + unsigned int conf; + int i; + int invert = 0; + + for (i = 0; i < n_chans; i++) { + chan = CR_CHAN(chanspec[i]); + range = CR_RANGE(chanspec[i]); + conf = AO_Channel(chan); + + if (boardtype.ao_unipolar) { + if ((range & 1) == 0) { + conf |= AO_Bipolar; + invert = (1 << (boardtype.aobits - 1)); + } else { + invert = 0; + } + if (range & 2) + conf |= AO_Ext_Ref; + } else { + conf |= AO_Bipolar; + invert = (1 << (boardtype.aobits - 1)); + } + + /* not all boards can deglitch, but this shouldn't hurt */ + if (chanspec[i] & CR_DEGLITCH) + conf |= AO_Deglitch; + + /* analog reference */ + /* AREF_OTHER connects AO ground to AI ground, i think */ + conf |= (CR_AREF(chanspec[i]) == + AREF_OTHER) ? AO_Ground_Ref : 0; + + ni_writew(conf, AO_Configuration); + devpriv->ao_conf[chan] = conf; + } + return invert; +} + +static int ni_ao_config_chanlist(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int chanspec[], unsigned int n_chans, int timed) +{ + if (boardtype.reg_type & ni_reg_m_series_mask) + return ni_m_series_ao_config_chanlist(dev, s, chanspec, n_chans, + timed); + else + return ni_old_ao_config_chanlist(dev, s, chanspec, n_chans); +} +static int ni_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->ao[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int ni_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int invert; + + invert = ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); + + devpriv->ao[chan] = data[0]; + + if (boardtype.reg_type & ni_reg_m_series_mask) { + ni_writew(data[0], M_Offset_DAC_Direct_Data(chan)); + } else + ni_writew(data[0] ^ invert, + (chan) ? DAC1_Direct_Data : DAC0_Direct_Data); + + return 1; +} + +static int ni_ao_insn_write_671x(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int invert; + + ao_win_out(1 << chan, AO_Immediate_671x); + invert = 1 << (boardtype.aobits - 1); + + ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); + + devpriv->ao[chan] = data[0]; + ao_win_out(data[0] ^ invert, DACx_Direct_Data_671x(chan)); + + return 1; +} + +static int ni_ao_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + switch (data[0]) { + case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE: + switch(data[1]) + { + case COMEDI_OUTPUT: + data[2] = 1 + boardtype.ao_fifo_depth * sizeof(short); + if(devpriv->mite) data[2] += devpriv->mite->fifo_size; + break; + case COMEDI_INPUT: + data[2] = 0; + break; + default: + return -EINVAL; + break; + } + return 0; + default: + break; + } + + return -EINVAL; +} + +static int ni_ao_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ + int ret; + int interrupt_b_bits; + int i; + static const int timeout = 1000; + + if (trignum != 0) + return -EINVAL; + + /* Null trig at beginning prevent ao start trigger from executing more than + once per command (and doing things like trying to allocate the ao dma channel + multiple times) */ + s->async->inttrig = NULL; + + ni_set_bits(dev, Interrupt_B_Enable_Register, + AO_FIFO_Interrupt_Enable | AO_Error_Interrupt_Enable, 0); + interrupt_b_bits = AO_Error_Interrupt_Enable; +#ifdef PCIDMA + devpriv->stc_writew(dev, 1, DAC_FIFO_Clear); + if (boardtype.reg_type & ni_reg_6xxx_mask) + ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); + ret = ni_ao_setup_MITE_dma(dev); + if (ret) + return ret; + ret = ni_ao_wait_for_dma_load(dev); + if (ret < 0) + return ret; +#else + ret = ni_ao_prep_fifo(dev, s); + if (ret == 0) + return -EPIPE; + + interrupt_b_bits |= AO_FIFO_Interrupt_Enable; +#endif + + devpriv->stc_writew(dev, devpriv->ao_mode3 | AO_Not_An_UPDATE, + AO_Mode_3_Register); + devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + /* wait for DACs to be loaded */ + for (i = 0; i < timeout; i++) { + comedi_udelay(1); + if ((devpriv->stc_readw(dev, + Joint_Status_2_Register) & + AO_TMRDACWRs_In_Progress_St) == 0) + break; + } + if (i == timeout) { + comedi_error(dev, + "timed out waiting for AO_TMRDACWRs_In_Progress_St to clear"); + return -EIO; + } + // stc manual says we are need to clear error interrupt after AO_TMRDACWRs_In_Progress_St clears + devpriv->stc_writew(dev, AO_Error_Interrupt_Ack, + Interrupt_B_Ack_Register); + + ni_set_bits(dev, Interrupt_B_Enable_Register, interrupt_b_bits, 1); + + devpriv->stc_writew(dev, + devpriv-> + ao_cmd1 | AO_UI_Arm | AO_UC_Arm | AO_BC_Arm | + AO_DAC1_Update_Mode | AO_DAC0_Update_Mode, + AO_Command_1_Register); + + devpriv->stc_writew(dev, devpriv->ao_cmd2 | AO_START1_Pulse, + AO_Command_2_Register); + + return 0; +} + +static int ni_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + const struct comedi_cmd *cmd = &s->async->cmd; + int bits; + int i; + unsigned trigvar; + + if (dev->irq == 0) { + comedi_error(dev, "cannot run command without an irq"); + return -EIO; + } + + devpriv->stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); + + devpriv->stc_writew(dev, AO_Disarm, AO_Command_1_Register); + + if (boardtype.reg_type & ni_reg_6xxx_mask) { + ao_win_out(CLEAR_WG, AO_Misc_611x); + + bits = 0; + for (i = 0; i < cmd->chanlist_len; i++) { + int chan; + + chan = CR_CHAN(cmd->chanlist[i]); + bits |= 1 << chan; + ao_win_out(chan, AO_Waveform_Generation_611x); + } + ao_win_out(bits, AO_Timed_611x); + } + + ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); + + if (cmd->stop_src == TRIG_NONE) { + devpriv->ao_mode1 |= AO_Continuous; + devpriv->ao_mode1 &= ~AO_Trigger_Once; + } else { + devpriv->ao_mode1 &= ~AO_Continuous; + devpriv->ao_mode1 |= AO_Trigger_Once; + } + devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + switch (cmd->start_src) { + case TRIG_INT: + case TRIG_NOW: + devpriv->ao_trigger_select &= + ~(AO_START1_Polarity | AO_START1_Select(-1)); + devpriv->ao_trigger_select |= AO_START1_Edge | AO_START1_Sync; + devpriv->stc_writew(dev, devpriv->ao_trigger_select, + AO_Trigger_Select_Register); + break; + case TRIG_EXT: + devpriv->ao_trigger_select = AO_START1_Select(CR_CHAN(cmd->start_arg)+1); + if (cmd->start_arg & CR_INVERT) + devpriv->ao_trigger_select |= AO_START1_Polarity; // 0=active high, 1=active low. see daq-stc 3-24 (p186) + if (cmd->start_arg & CR_EDGE) + devpriv->ao_trigger_select |= AO_START1_Edge; // 0=edge detection disabled, 1=enabled + devpriv->stc_writew(dev, devpriv->ao_trigger_select, AO_Trigger_Select_Register); + break; + default: + BUG(); + break; + } + devpriv->ao_mode3 &= ~AO_Trigger_Length; + devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + + devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + devpriv->ao_mode2 &= ~AO_BC_Initial_Load_Source; + devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + if (cmd->stop_src == TRIG_NONE) { + devpriv->stc_writel(dev, 0xffffff, AO_BC_Load_A_Register); + } else { + devpriv->stc_writel(dev, 0, AO_BC_Load_A_Register); + } + devpriv->stc_writew(dev, AO_BC_Load, AO_Command_1_Register); + devpriv->ao_mode2 &= ~AO_UC_Initial_Load_Source; + devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + switch (cmd->stop_src) { + case TRIG_COUNT: + if(boardtype.reg_type & ni_reg_m_series_mask) + { + // this is how the NI example code does it for m-series boards, verified correct with 6259 + devpriv->stc_writel(dev, cmd->stop_arg - 1, AO_UC_Load_A_Register); + devpriv->stc_writew(dev, AO_UC_Load, AO_Command_1_Register); + }else + { + devpriv->stc_writel(dev, cmd->stop_arg, AO_UC_Load_A_Register); + devpriv->stc_writew(dev, AO_UC_Load, AO_Command_1_Register); + devpriv->stc_writel(dev, cmd->stop_arg - 1, + AO_UC_Load_A_Register); + } + break; + case TRIG_NONE: + devpriv->stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); + devpriv->stc_writew(dev, AO_UC_Load, AO_Command_1_Register); + devpriv->stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); + break; + default: + devpriv->stc_writel(dev, 0, AO_UC_Load_A_Register); + devpriv->stc_writew(dev, AO_UC_Load, AO_Command_1_Register); + devpriv->stc_writel(dev, cmd->stop_arg, AO_UC_Load_A_Register); + } + + devpriv->ao_mode1 &= + ~(AO_UI_Source_Select(0x1f) | AO_UI_Source_Polarity | + AO_UPDATE_Source_Select(0x1f) | AO_UPDATE_Source_Polarity); + switch (cmd->scan_begin_src) { + case TRIG_TIMER: + devpriv->ao_cmd2 &= ~AO_BC_Gate_Enable; + trigvar = + ni_ns_to_timer(dev, cmd->scan_begin_arg, + TRIG_ROUND_NEAREST); + devpriv->stc_writel(dev, 1, AO_UI_Load_A_Register); + devpriv->stc_writew(dev, AO_UI_Load, AO_Command_1_Register); + devpriv->stc_writel(dev, trigvar, AO_UI_Load_A_Register); + break; + case TRIG_EXT: + devpriv->ao_mode1 |= + AO_UPDATE_Source_Select(cmd->scan_begin_arg); + if (cmd->scan_begin_arg & CR_INVERT) + devpriv->ao_mode1 |= AO_UPDATE_Source_Polarity; + devpriv->ao_cmd2 |= AO_BC_Gate_Enable; + break; + default: + BUG(); + break; + } + devpriv->stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); + devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + devpriv->ao_mode2 &= + ~(AO_UI_Reload_Mode(3) | AO_UI_Initial_Load_Source); + devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + + if (cmd->scan_end_arg > 1) { + devpriv->ao_mode1 |= AO_Multiple_Channels; + devpriv->stc_writew(dev, + AO_Number_Of_Channels(cmd->scan_end_arg - + 1) | + AO_UPDATE_Output_Select + (AO_Update_Output_High_Z), + AO_Output_Control_Register); + } else { + unsigned bits; + devpriv->ao_mode1 &= ~AO_Multiple_Channels; + bits = AO_UPDATE_Output_Select(AO_Update_Output_High_Z); + if (boardtype.reg_type & (ni_reg_m_series_mask | ni_reg_6xxx_mask)) { + bits |= AO_Number_Of_Channels(0); + } else { + bits |= AO_Number_Of_Channels(CR_CHAN(cmd-> + chanlist[0])); + } + devpriv->stc_writew(dev, bits, + AO_Output_Control_Register); + } + devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + + devpriv->stc_writew(dev, AO_DAC0_Update_Mode | AO_DAC1_Update_Mode, + AO_Command_1_Register); + + devpriv->ao_mode3 |= AO_Stop_On_Overrun_Error; + devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + + devpriv->ao_mode2 &= ~AO_FIFO_Mode_Mask; +#ifdef PCIDMA + devpriv->ao_mode2 |= AO_FIFO_Mode_HF_to_F; +#else + devpriv->ao_mode2 |= AO_FIFO_Mode_HF; +#endif + devpriv->ao_mode2 &= ~AO_FIFO_Retransmit_Enable; + devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + + bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width | + AO_TMRDACWR_Pulse_Width; + if (boardtype.ao_fifo_depth) + bits |= AO_FIFO_Enable; + else + bits |= AO_DMA_PIO_Control; +#if 0 + /* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281, + verified with bus analyzer. */ + if (boardtype.reg_type & ni_reg_m_series_mask) + bits |= AO_Number_Of_DAC_Packages; +#endif + devpriv->stc_writew(dev, bits, AO_Personal_Register); + // enable sending of ao dma requests + devpriv->stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register); + + devpriv->stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); + + if (cmd->stop_src == TRIG_COUNT) { + devpriv->stc_writew(dev, AO_BC_TC_Interrupt_Ack, + Interrupt_B_Ack_Register); + ni_set_bits(dev, Interrupt_B_Enable_Register, + AO_BC_TC_Interrupt_Enable, 1); + } + + s->async->inttrig = &ni_ao_inttrig; + + return 0; +} + +static int ni_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + if ((cmd->flags & CMDF_WRITE) == 0) { + cmd->flags |= CMDF_WRITE; + } + + tmp = cmd->start_src; + cmd->start_src &= TRIG_INT | TRIG_EXT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_src == TRIG_EXT) { + /* external trigger */ + unsigned int tmp = CR_CHAN(cmd->start_arg); + + if (tmp > 18) + tmp = 18; + tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE)); + if (cmd->start_arg != tmp) { + cmd->start_arg = tmp; + err++; + } + } else { + if (cmd->start_arg != 0) { + /* true for both TRIG_NOW and TRIG_INT */ + cmd->start_arg = 0; + err++; + } + } + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < boardtype.ao_speed) { + cmd->scan_begin_arg = boardtype.ao_speed; + err++; + } + if (cmd->scan_begin_arg > devpriv->clock_ns * 0xffffff) { /* XXX check */ + cmd->scan_begin_arg = devpriv->clock_ns * 0xffffff; + err++; + } + } + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { /* XXX check */ + if (cmd->stop_arg > 0x00ffffff) { + cmd->stop_arg = 0x00ffffff; + err++; + } + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + cmd->scan_begin_arg = + ni_timer_to_ns(dev, ni_ns_to_timer(dev, + cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK)); + if (tmp != cmd->scan_begin_arg) + err++; + } + if (err) + return 4; + + /* step 5: fix up chanlist */ + + if (err) + return 5; + + return 0; +} + +static int ni_ao_reset(struct comedi_device * dev, struct comedi_subdevice * s) +{ + //devpriv->ao0p=0x0000; + //ni_writew(devpriv->ao0p,AO_Configuration); + + //devpriv->ao1p=AO_Channel(1); + //ni_writew(devpriv->ao1p,AO_Configuration); + + ni_release_ao_mite_channel(dev); + + devpriv->stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); + devpriv->stc_writew(dev, AO_Disarm, AO_Command_1_Register); + ni_set_bits(dev, Interrupt_B_Enable_Register, ~0, 0); + devpriv->stc_writew(dev, AO_BC_Source_Select, AO_Personal_Register); + devpriv->stc_writew(dev, 0x3f98, Interrupt_B_Ack_Register); + devpriv->stc_writew(dev, AO_BC_Source_Select | AO_UPDATE_Pulse_Width | + AO_TMRDACWR_Pulse_Width, AO_Personal_Register); + devpriv->stc_writew(dev, 0, AO_Output_Control_Register); + devpriv->stc_writew(dev, 0, AO_Start_Select_Register); + devpriv->ao_cmd1 = 0; + devpriv->stc_writew(dev, devpriv->ao_cmd1, AO_Command_1_Register); + devpriv->ao_cmd2 = 0; + devpriv->stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); + devpriv->ao_mode1 = 0; + devpriv->stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); + devpriv->ao_mode2 = 0; + devpriv->stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); + if (boardtype.reg_type & ni_reg_m_series_mask) + devpriv->ao_mode3 = AO_Last_Gate_Disable; + else + devpriv->ao_mode3 = 0; + devpriv->stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); + devpriv->ao_trigger_select = 0; + devpriv->stc_writew(dev, devpriv->ao_trigger_select, + AO_Trigger_Select_Register); + if (boardtype.reg_type & ni_reg_6xxx_mask) { + unsigned immediate_bits = 0; + unsigned i; + for(i = 0; i < s->n_chan; ++i) + { + immediate_bits |= 1 << i; + } + ao_win_out(immediate_bits, AO_Immediate_671x); + ao_win_out(CLEAR_WG, AO_Misc_611x); + } + devpriv->stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); + + return 0; +} + +// digital io + +static int ni_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ +#ifdef DEBUG_DIO + rt_printk("ni_dio_insn_config() chan=%d io=%d\n", + CR_CHAN(insn->chanspec), data[0]); +#endif + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= 1 << CR_CHAN(insn->chanspec); + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~(1 << CR_CHAN(insn->chanspec)); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s->io_bits & (1 << CR_CHAN(insn-> + chanspec))) ? COMEDI_OUTPUT : + COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + } + + devpriv->dio_control &= ~DIO_Pins_Dir_Mask; + devpriv->dio_control |= DIO_Pins_Dir(s->io_bits); + devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + + return 1; +} + +static int ni_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ +#ifdef DEBUG_DIO + rt_printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]); +#endif + if (insn->n != 2) + return -EINVAL; + if (data[0]) { + /* Perform check to make sure we're not using the + serial part of the dio */ + if ((data[0] & (DIO_SDIN | DIO_SDOUT)) + && devpriv->serial_interval_ns) + return -EBUSY; + + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + devpriv->dio_output &= ~DIO_Parallel_Data_Mask; + devpriv->dio_output |= DIO_Parallel_Data_Out(s->state); + devpriv->stc_writew(dev, devpriv->dio_output, + DIO_Output_Register); + } + data[1] = devpriv->stc_readw(dev, DIO_Parallel_Input_Register); + + return 2; +} + +static int ni_m_series_dio_insn_config(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ +#ifdef DEBUG_DIO + rt_printk("ni_m_series_dio_insn_config() chan=%d io=%d\n", + CR_CHAN(insn->chanspec), data[0]); +#endif + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= 1 << CR_CHAN(insn->chanspec); + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~(1 << CR_CHAN(insn->chanspec)); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s->io_bits & (1 << CR_CHAN(insn-> + chanspec))) ? COMEDI_OUTPUT : + COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + } + + ni_writel(s->io_bits, M_Offset_DIO_Direction); + + return 1; +} + +static int ni_m_series_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ +#ifdef DEBUG_DIO + rt_printk("ni_m_series_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], + data[1]); +#endif + if (insn->n != 2) + return -EINVAL; + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + ni_writel(s->state, M_Offset_Static_Digital_Output); + } + data[1] = ni_readl(M_Offset_Static_Digital_Input); + + return 2; +} + +static int ni_cdio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + int sources; + unsigned i; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + sources = TRIG_INT; + cmd->start_src &= sources; + 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_NOW; + 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: make sure trigger sources are unique... */ + + if (cmd->start_src != TRIG_INT) + err++; + if (cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_NONE) + err++; + /* ... and mutually compatible */ + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + if (cmd->start_src == TRIG_INT) { + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + } + if (cmd->scan_begin_src == TRIG_EXT) { + tmp = cmd->scan_begin_arg; + tmp &= CR_PACK_FLAGS(CDO_Sample_Source_Select_Mask, 0, 0, + CR_INVERT); + if (tmp != cmd->scan_begin_arg) { + err++; + } + } + if (cmd->convert_src == TRIG_NOW) { + if (cmd->convert_arg) { + cmd->convert_arg = 0; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + if (cmd->stop_src == TRIG_NONE) { + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (err) + return 4; + + /* step 5: check chanlist */ + + for (i = 0; i < cmd->chanlist_len; ++i) { + if (cmd->chanlist[i] != i) + err = 1; + } + + if (err) + return 5; + + return 0; +} + +static int ni_cdio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + const struct comedi_cmd *cmd = &s->async->cmd; + unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit; + int retval; + + ni_writel(CDO_Reset_Bit, M_Offset_CDIO_Command); + switch (cmd->scan_begin_src) { + case TRIG_EXT: + cdo_mode_bits |= + CR_CHAN(cmd-> + scan_begin_arg) & CDO_Sample_Source_Select_Mask; + break; + default: + BUG(); + break; + } + if (cmd->scan_begin_arg & CR_INVERT) + cdo_mode_bits |= CDO_Polarity_Bit; + ni_writel(cdo_mode_bits, M_Offset_CDO_Mode); + if (s->io_bits) { + ni_writel(s->state, M_Offset_CDO_FIFO_Data); + ni_writel(CDO_SW_Update_Bit, M_Offset_CDIO_Command); + ni_writel(s->io_bits, M_Offset_CDO_Mask_Enable); + } else { + comedi_error(dev, + "attempted to run digital output command with no lines configured as outputs"); + return -EIO; + } + retval = ni_request_cdo_mite_channel(dev); + if (retval < 0) { + return retval; + } + s->async->inttrig = &ni_cdo_inttrig; + return 0; +} + +static int ni_cdo_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ +#ifdef PCIDMA + unsigned long flags; +#endif + int retval = 0; + unsigned i; + const unsigned timeout = 100; + + s->async->inttrig = NULL; + + /* read alloc the entire buffer */ + comedi_buf_read_alloc(s->async, s->async->prealloc_bufsz); + +#ifdef PCIDMA + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->cdo_mite_chan) { + mite_prep_dma(devpriv->cdo_mite_chan, 32, 32); + mite_dma_arm(devpriv->cdo_mite_chan); + } else { + comedi_error(dev, "BUG: no cdo mite channel?"); + retval = -EIO; + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + if (retval < 0) + return retval; +#endif +// XXX not sure what interrupt C group does +// ni_writeb(Interrupt_Group_C_Enable_Bit, M_Offset_Interrupt_C_Enable); + //wait for dma to fill output fifo + for (i = 0; i < timeout; ++i) { + if (ni_readl(M_Offset_CDIO_Status) & CDO_FIFO_Full_Bit) + break; + comedi_udelay(10); + } + if (i == timeout) { + comedi_error(dev, "dma failed to fill cdo fifo!"); + ni_cdio_cancel(dev, s); + return -EIO; + } + ni_writel(CDO_Arm_Bit | CDO_Error_Interrupt_Enable_Set_Bit | + CDO_Empty_FIFO_Interrupt_Enable_Set_Bit, M_Offset_CDIO_Command); + return retval; +} + +static int ni_cdio_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + ni_writel(CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit | + CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit | + CDO_FIFO_Request_Interrupt_Enable_Clear_Bit, + M_Offset_CDIO_Command); +// XXX not sure what interrupt C group does +// ni_writeb(0, M_Offset_Interrupt_C_Enable); + ni_writel(0, M_Offset_CDO_Mask_Enable); + ni_release_cdo_mite_channel(dev); + return 0; +} + +static void handle_cdio_interrupt(struct comedi_device * dev) +{ + unsigned cdio_status; + struct comedi_subdevice *s = dev->subdevices + NI_DIO_SUBDEV; +#ifdef PCIDMA + unsigned long flags; +#endif + + if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) { + return; + } +#ifdef PCIDMA + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->cdo_mite_chan) { + unsigned cdo_mite_status = + mite_get_status(devpriv->cdo_mite_chan); + if (cdo_mite_status & CHSR_LINKC) { + writel(CHOR_CLRLC, + devpriv->mite->mite_io_addr + + MITE_CHOR(devpriv->cdo_mite_chan->channel)); + } + mite_sync_output_dma(devpriv->cdo_mite_chan, s->async); + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +#endif + + cdio_status = ni_readl(M_Offset_CDIO_Status); + if (cdio_status & (CDO_Overrun_Bit | CDO_Underflow_Bit)) { +// rt_printk("cdio error: statux=0x%x\n", cdio_status); + ni_writel(CDO_Error_Interrupt_Confirm_Bit, M_Offset_CDIO_Command); // XXX just guessing this is needed and does something useful + s->async->events |= COMEDI_CB_OVERFLOW; + } + if (cdio_status & CDO_FIFO_Empty_Bit) { +// rt_printk("cdio fifo empty\n"); + ni_writel(CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit, + M_Offset_CDIO_Command); +// s->async->events |= COMEDI_CB_EOA; + } + ni_event(dev, s); +} + +static int ni_serial_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int err = insn->n; + unsigned char byte_out, byte_in = 0; + + if (insn->n != 2) + return -EINVAL; + + switch (data[0]) { + case INSN_CONFIG_SERIAL_CLOCK: + +#ifdef DEBUG_DIO + rt_printk("SPI serial clock Config cd\n", data[1]); +#endif + devpriv->serial_hw_mode = 1; + devpriv->dio_control |= DIO_HW_Serial_Enable; + + if (data[1] == SERIAL_DISABLED) { + devpriv->serial_hw_mode = 0; + devpriv->dio_control &= ~(DIO_HW_Serial_Enable | + DIO_Software_Serial_Control); + data[1] = SERIAL_DISABLED; + devpriv->serial_interval_ns = data[1]; + } else if (data[1] <= SERIAL_600NS) { + /* Warning: this clock speed is too fast to reliably + control SCXI. */ + devpriv->dio_control &= ~DIO_HW_Serial_Timebase; + devpriv->clock_and_fout |= Slow_Internal_Timebase; + devpriv->clock_and_fout &= ~DIO_Serial_Out_Divide_By_2; + data[1] = SERIAL_600NS; + devpriv->serial_interval_ns = data[1]; + } else if (data[1] <= SERIAL_1_2US) { + devpriv->dio_control &= ~DIO_HW_Serial_Timebase; + devpriv->clock_and_fout |= Slow_Internal_Timebase | + DIO_Serial_Out_Divide_By_2; + data[1] = SERIAL_1_2US; + devpriv->serial_interval_ns = data[1]; + } else if (data[1] <= SERIAL_10US) { + devpriv->dio_control |= DIO_HW_Serial_Timebase; + devpriv->clock_and_fout |= Slow_Internal_Timebase | + DIO_Serial_Out_Divide_By_2; + /* Note: DIO_Serial_Out_Divide_By_2 only affects + 600ns/1.2us. If you turn divide_by_2 off with the + slow clock, you will still get 10us, except then + all your delays are wrong. */ + data[1] = SERIAL_10US; + devpriv->serial_interval_ns = data[1]; + } else { + devpriv->dio_control &= ~(DIO_HW_Serial_Enable | + DIO_Software_Serial_Control); + devpriv->serial_hw_mode = 0; + data[1] = (data[1] / 1000) * 1000; + devpriv->serial_interval_ns = data[1]; + } + + devpriv->stc_writew(dev, devpriv->dio_control, + DIO_Control_Register); + devpriv->stc_writew(dev, devpriv->clock_and_fout, + Clock_and_FOUT_Register); + return 1; + + break; + + case INSN_CONFIG_BIDIRECTIONAL_DATA: + + if (devpriv->serial_interval_ns == 0) { + return -EINVAL; + } + + byte_out = data[1] & 0xFF; + + if (devpriv->serial_hw_mode) { + err = ni_serial_hw_readwrite8(dev, s, byte_out, + &byte_in); + } else if (devpriv->serial_interval_ns > 0) { + err = ni_serial_sw_readwrite8(dev, s, byte_out, + &byte_in); + } else { + rt_printk("ni_serial_insn_config: serial disabled!\n"); + return -EINVAL; + } + if (err < 0) + return err; + data[1] = byte_in & 0xFF; + return insn->n; + + break; + default: + return -EINVAL; + } + +} + +static int ni_serial_hw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned char data_out, unsigned char *data_in) +{ + unsigned int status1; + int err = 0, count = 20; + +#ifdef DEBUG_DIO + rt_printk("ni_serial_hw_readwrite8: outputting 0x%x\n", data_out); +#endif + + devpriv->dio_output &= ~DIO_Serial_Data_Mask; + devpriv->dio_output |= DIO_Serial_Data_Out(data_out); + devpriv->stc_writew(dev, devpriv->dio_output, DIO_Output_Register); + + status1 = devpriv->stc_readw(dev, Joint_Status_1_Register); + if (status1 & DIO_Serial_IO_In_Progress_St) { + err = -EBUSY; + goto Error; + } + + devpriv->dio_control |= DIO_HW_Serial_Start; + devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + devpriv->dio_control &= ~DIO_HW_Serial_Start; + + /* Wait until STC says we're done, but don't loop infinitely. */ + while ((status1 = + devpriv->stc_readw(dev, + Joint_Status_1_Register)) & + DIO_Serial_IO_In_Progress_St) { + /* Delay one bit per loop */ + comedi_udelay((devpriv->serial_interval_ns + 999) / 1000); + if (--count < 0) { + rt_printk + ("ni_serial_hw_readwrite8: SPI serial I/O didn't finish in time!\n"); + err = -ETIME; + goto Error; + } + } + + /* Delay for last bit. This delay is absolutely necessary, because + DIO_Serial_IO_In_Progress_St goes high one bit too early. */ + comedi_udelay((devpriv->serial_interval_ns + 999) / 1000); + + if (data_in != NULL) { + *data_in = devpriv->stc_readw(dev, DIO_Serial_Input_Register); +#ifdef DEBUG_DIO + rt_printk("ni_serial_hw_readwrite8: inputted 0x%x\n", *data_in); +#endif + } + + Error: + devpriv->stc_writew(dev, devpriv->dio_control, DIO_Control_Register); + + return err; +} + +static int ni_serial_sw_readwrite8(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned char data_out, unsigned char *data_in) +{ + unsigned char mask, input = 0; + +#ifdef DEBUG_DIO + rt_printk("ni_serial_sw_readwrite8: outputting 0x%x\n", data_out); +#endif + + /* Wait for one bit before transfer */ + comedi_udelay((devpriv->serial_interval_ns + 999) / 1000); + + for (mask = 0x80; mask; mask >>= 1) { + /* Output current bit; note that we cannot touch s->state + because it is a per-subdevice field, and serial is + a separate subdevice from DIO. */ + devpriv->dio_output &= ~DIO_SDOUT; + if (data_out & mask) { + devpriv->dio_output |= DIO_SDOUT; + } + devpriv->stc_writew(dev, devpriv->dio_output, + DIO_Output_Register); + + /* Assert SDCLK (active low, inverted), wait for half of + the delay, deassert SDCLK, and wait for the other half. */ + devpriv->dio_control |= DIO_Software_Serial_Control; + devpriv->stc_writew(dev, devpriv->dio_control, + DIO_Control_Register); + + comedi_udelay((devpriv->serial_interval_ns + 999) / 2000); + + devpriv->dio_control &= ~DIO_Software_Serial_Control; + devpriv->stc_writew(dev, devpriv->dio_control, + DIO_Control_Register); + + comedi_udelay((devpriv->serial_interval_ns + 999) / 2000); + + /* Input current bit */ + if (devpriv->stc_readw(dev, + DIO_Parallel_Input_Register) & DIO_SDIN) { +/* rt_printk("DIO_P_I_R: 0x%x\n", devpriv->stc_readw(dev, DIO_Parallel_Input_Register)); */ + input |= mask; + } + } +#ifdef DEBUG_DIO + rt_printk("ni_serial_sw_readwrite8: inputted 0x%x\n", input); +#endif + if (data_in) + *data_in = input; + + return 0; +} + +static void mio_common_detach(struct comedi_device * dev) +{ + if (dev->private) { + if (devpriv->counter_dev) { + ni_gpct_device_destroy(devpriv->counter_dev); + } + } + if (dev->subdevices && boardtype.has_8255) + subdev_8255_cleanup(dev, dev->subdevices + NI_8255_DIO_SUBDEV); +} + +static void init_ao_67xx(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int i; + + for (i = 0; i < s->n_chan; i++) + { + ni_ao_win_outw(dev, AO_Channel(i) | 0x0, + AO_Configuration_2_67xx); + } + ao_win_out(0x0, AO_Later_Single_Point_Updates); +} + +static unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg) +{ + unsigned stc_register; + switch (reg) { + case NITIO_G0_Autoincrement_Reg: + stc_register = G_Autoincrement_Register(0); + break; + case NITIO_G1_Autoincrement_Reg: + stc_register = G_Autoincrement_Register(1); + break; + case NITIO_G0_Command_Reg: + stc_register = G_Command_Register(0); + break; + case NITIO_G1_Command_Reg: + stc_register = G_Command_Register(1); + break; + case NITIO_G0_HW_Save_Reg: + stc_register = G_HW_Save_Register(0); + break; + case NITIO_G1_HW_Save_Reg: + stc_register = G_HW_Save_Register(1); + break; + case NITIO_G0_SW_Save_Reg: + stc_register = G_Save_Register(0); + break; + case NITIO_G1_SW_Save_Reg: + stc_register = G_Save_Register(1); + break; + case NITIO_G0_Mode_Reg: + stc_register = G_Mode_Register(0); + break; + case NITIO_G1_Mode_Reg: + stc_register = G_Mode_Register(1); + break; + case NITIO_G0_LoadA_Reg: + stc_register = G_Load_A_Register(0); + break; + case NITIO_G1_LoadA_Reg: + stc_register = G_Load_A_Register(1); + break; + case NITIO_G0_LoadB_Reg: + stc_register = G_Load_B_Register(0); + break; + case NITIO_G1_LoadB_Reg: + stc_register = G_Load_B_Register(1); + break; + case NITIO_G0_Input_Select_Reg: + stc_register = G_Input_Select_Register(0); + break; + case NITIO_G1_Input_Select_Reg: + stc_register = G_Input_Select_Register(1); + break; + case NITIO_G01_Status_Reg: + stc_register = G_Status_Register; + break; + case NITIO_G01_Joint_Reset_Reg: + stc_register = Joint_Reset_Register; + break; + case NITIO_G01_Joint_Status1_Reg: + stc_register = Joint_Status_1_Register; + break; + case NITIO_G01_Joint_Status2_Reg: + stc_register = Joint_Status_2_Register; + break; + case NITIO_G0_Interrupt_Acknowledge_Reg: + stc_register = Interrupt_A_Ack_Register; + break; + case NITIO_G1_Interrupt_Acknowledge_Reg: + stc_register = Interrupt_B_Ack_Register; + break; + case NITIO_G0_Status_Reg: + stc_register = AI_Status_1_Register; + break; + case NITIO_G1_Status_Reg: + stc_register = AO_Status_1_Register; + break; + case NITIO_G0_Interrupt_Enable_Reg: + stc_register = Interrupt_A_Enable_Register; + break; + case NITIO_G1_Interrupt_Enable_Reg: + stc_register = Interrupt_B_Enable_Register; + break; + default: + rt_printk("%s: unhandled register 0x%x in switch.\n", + __FUNCTION__, reg); + BUG(); + return 0; + break; + } + return stc_register; +} + +static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, + enum ni_gpct_register reg) +{ + struct comedi_device *dev = counter->counter_dev->dev; + unsigned stc_register; + /* bits in the join reset register which are relevant to counters */ + static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset; + static const unsigned gpct_interrupt_a_enable_mask = + G0_Gate_Interrupt_Enable | G0_TC_Interrupt_Enable; + static const unsigned gpct_interrupt_b_enable_mask = + G1_Gate_Interrupt_Enable | G1_TC_Interrupt_Enable; + + switch (reg) { + /* m-series-only registers */ + case NITIO_G0_Counting_Mode_Reg: + ni_writew(bits, M_Offset_G0_Counting_Mode); + break; + case NITIO_G1_Counting_Mode_Reg: + ni_writew(bits, M_Offset_G1_Counting_Mode); + break; + case NITIO_G0_Second_Gate_Reg: + ni_writew(bits, M_Offset_G0_Second_Gate); + break; + case NITIO_G1_Second_Gate_Reg: + ni_writew(bits, M_Offset_G1_Second_Gate); + break; + case NITIO_G0_DMA_Config_Reg: + ni_writew(bits, M_Offset_G0_DMA_Config); + break; + case NITIO_G1_DMA_Config_Reg: + ni_writew(bits, M_Offset_G1_DMA_Config); + break; + case NITIO_G0_ABZ_Reg: + ni_writew(bits, M_Offset_G0_MSeries_ABZ); + break; + case NITIO_G1_ABZ_Reg: + ni_writew(bits, M_Offset_G1_MSeries_ABZ); + break; + + /* 32 bit registers */ + case NITIO_G0_LoadA_Reg: + case NITIO_G1_LoadA_Reg: + case NITIO_G0_LoadB_Reg: + case NITIO_G1_LoadB_Reg: + stc_register = ni_gpct_to_stc_register(reg); + devpriv->stc_writel(dev, bits, stc_register); + break; + + /* 16 bit registers */ + case NITIO_G0_Interrupt_Enable_Reg: + BUG_ON(bits & ~gpct_interrupt_a_enable_mask); + ni_set_bitfield(dev, Interrupt_A_Enable_Register, + gpct_interrupt_a_enable_mask, bits); + break; + case NITIO_G1_Interrupt_Enable_Reg: + BUG_ON(bits & ~gpct_interrupt_b_enable_mask); + ni_set_bitfield(dev, Interrupt_B_Enable_Register, + gpct_interrupt_b_enable_mask, bits); + break; + case NITIO_G01_Joint_Reset_Reg: + BUG_ON(bits & ~gpct_joint_reset_mask); + /* fall-through */ + default: + stc_register = ni_gpct_to_stc_register(reg); + devpriv->stc_writew(dev, bits, stc_register); + } +} + +static unsigned ni_gpct_read_register(struct ni_gpct *counter, + enum ni_gpct_register reg) +{ + struct comedi_device *dev = counter->counter_dev->dev; + unsigned stc_register; + switch (reg) { + /* m-series only registers */ + case NITIO_G0_DMA_Status_Reg: + return ni_readw(M_Offset_G0_DMA_Status); + break; + case NITIO_G1_DMA_Status_Reg: + return ni_readw(M_Offset_G1_DMA_Status); + break; + + /* 32 bit registers */ + case NITIO_G0_HW_Save_Reg: + case NITIO_G1_HW_Save_Reg: + case NITIO_G0_SW_Save_Reg: + case NITIO_G1_SW_Save_Reg: + stc_register = ni_gpct_to_stc_register(reg); + return devpriv->stc_readl(dev, stc_register); + break; + + /* 16 bit registers */ + default: + stc_register = ni_gpct_to_stc_register(reg); + return devpriv->stc_readw(dev, stc_register); + break; + } + return 0; +} + +static int ni_freq_out_insn_read(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->clock_and_fout & FOUT_Divider_mask; + return 1; +} + +static int ni_freq_out_insn_write(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + devpriv->clock_and_fout &= ~FOUT_Enable; + devpriv->stc_writew(dev, devpriv->clock_and_fout, + Clock_and_FOUT_Register); + devpriv->clock_and_fout &= ~FOUT_Divider_mask; + devpriv->clock_and_fout |= FOUT_Divider(data[0]); + devpriv->clock_and_fout |= FOUT_Enable; + devpriv->stc_writew(dev, devpriv->clock_and_fout, + Clock_and_FOUT_Register); + return insn->n; +} + +static int ni_set_freq_out_clock(struct comedi_device * dev, unsigned int clock_source) +{ + switch (clock_source) { + case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC: + devpriv->clock_and_fout &= ~FOUT_Timebase_Select; + break; + case NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC: + devpriv->clock_and_fout |= FOUT_Timebase_Select; + break; + default: + return -EINVAL; + } + devpriv->stc_writew(dev, devpriv->clock_and_fout, + Clock_and_FOUT_Register); + return 3; +} + +static void ni_get_freq_out_clock(struct comedi_device * dev, unsigned int * clock_source, + unsigned int * clock_period_ns) +{ + if (devpriv->clock_and_fout & FOUT_Timebase_Select) { + *clock_source = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC; + *clock_period_ns = TIMEBASE_2_NS; + } else { + *clock_source = NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC; + *clock_period_ns = TIMEBASE_1_NS * 2; + } +} + +static int ni_freq_out_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + switch (data[0]) { + case INSN_CONFIG_SET_CLOCK_SRC: + return ni_set_freq_out_clock(dev, data[1]); + break; + case INSN_CONFIG_GET_CLOCK_SRC: + ni_get_freq_out_clock(dev, &data[1], &data[2]); + return 3; + default: + break; + } + return -EINVAL; +} + +static int ni_alloc_private(struct comedi_device * dev) +{ + int ret; + + ret = alloc_private(dev, sizeof(ni_private)); + if (ret < 0) + return ret; + + spin_lock_init(&devpriv->window_lock); + spin_lock_init(&devpriv->soft_reg_copy_lock); + spin_lock_init(&devpriv->mite_channel_lock); + + return 0; +}; + +static int ni_E_init(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned j; + enum ni_gpct_variant counter_variant; + + if (boardtype.n_aochan > MAX_N_AO_CHAN) { + printk("bug! boardtype.n_aochan > MAX_N_AO_CHAN\n"); + return -EINVAL; + } + + if (alloc_subdevices(dev, NI_NUM_SUBDEVICES) < 0) + return -ENOMEM; + + /* analog input subdevice */ + + s = dev->subdevices + NI_AI_SUBDEV; + dev->read_subdev = s; + if (boardtype.n_adchan) { + s->type = COMEDI_SUBD_AI; + s->subdev_flags = + SDF_READABLE | SDF_DIFF | SDF_DITHER | SDF_CMD_READ; + if (boardtype.reg_type != ni_reg_611x) + s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER; + if (boardtype.adbits > 16) + s->subdev_flags |= SDF_LSAMPL; + if (boardtype.reg_type & ni_reg_m_series_mask) + s->subdev_flags |= SDF_SOFT_CALIBRATED; + s->n_chan = boardtype.n_adchan; + s->len_chanlist = 512; + s->maxdata = (1 << boardtype.adbits) - 1; + s->range_table = ni_range_lkup[boardtype.gainlkup]; + s->insn_read = &ni_ai_insn_read; + s->insn_config = &ni_ai_insn_config; + s->do_cmdtest = &ni_ai_cmdtest; + s->do_cmd = &ni_ai_cmd; + s->cancel = &ni_ai_reset; + s->poll = &ni_ai_poll; + s->munge = &ni_ai_munge; +#ifdef PCIDMA + s->async_dma_dir = DMA_FROM_DEVICE; +#endif + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* analog output subdevice */ + + s = dev->subdevices + NI_AO_SUBDEV; + if (boardtype.n_aochan) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND; + if (boardtype.reg_type & ni_reg_m_series_mask) + s->subdev_flags |= SDF_SOFT_CALIBRATED; + s->n_chan = boardtype.n_aochan; + s->maxdata = (1 << boardtype.aobits) - 1; + s->range_table = boardtype.ao_range_table; + s->insn_read = &ni_ao_insn_read; + if (boardtype.reg_type & ni_reg_6xxx_mask) { + s->insn_write = &ni_ao_insn_write_671x; + } else { + s->insn_write = &ni_ao_insn_write; + } + s->insn_config = &ni_ao_insn_config; +#ifdef PCIDMA + if (boardtype.n_aochan) { + s->async_dma_dir = DMA_TO_DEVICE; +#else + if (boardtype.ao_fifo_depth) { +#endif + dev->write_subdev = s; + s->subdev_flags |= SDF_CMD_WRITE; + s->do_cmd = &ni_ao_cmd; + s->do_cmdtest = &ni_ao_cmdtest; + s->len_chanlist = boardtype.n_aochan; + if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) + s->munge = ni_ao_munge; + } + s->cancel = &ni_ao_reset; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + if ((boardtype.reg_type & ni_reg_67xx_mask)) + init_ao_67xx(dev, s); + + /* digital i/o subdevice */ + + s = dev->subdevices + NI_DIO_SUBDEV; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->maxdata = 1; + s->io_bits = 0; /* all bits input */ + s->range_table = &range_digital; + s->n_chan = boardtype.num_p0_dio_channels; + if (boardtype.reg_type & ni_reg_m_series_mask) { + s->subdev_flags |= + SDF_LSAMPL | SDF_CMD_WRITE /* | SDF_CMD_READ */ ; + s->insn_bits = &ni_m_series_dio_insn_bits; + s->insn_config = &ni_m_series_dio_insn_config; + s->do_cmd = &ni_cdio_cmd; + s->do_cmdtest = &ni_cdio_cmdtest; + s->cancel = &ni_cdio_cancel; + s->async_dma_dir = DMA_BIDIRECTIONAL; + s->len_chanlist = s->n_chan; + + ni_writel(CDO_Reset_Bit | CDI_Reset_Bit, M_Offset_CDIO_Command); + ni_writel(s->io_bits, M_Offset_DIO_Direction); + } else { + s->insn_bits = &ni_dio_insn_bits; + s->insn_config = &ni_dio_insn_config; + devpriv->dio_control = DIO_Pins_Dir(s->io_bits); + ni_writew(devpriv->dio_control, DIO_Control_Register); + } + + /* 8255 device */ + s = dev->subdevices + NI_8255_DIO_SUBDEV; + if (boardtype.has_8255) { + subdev_8255_init(dev, s, ni_8255_callback, (unsigned long)dev); + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* formerly general purpose counter/timer device, but no longer used */ + s = dev->subdevices + NI_UNUSED_SUBDEV; + s->type = COMEDI_SUBD_UNUSED; + + /* calibration subdevice -- ai and ao */ + s = dev->subdevices + NI_CALIBRATION_SUBDEV; + s->type = COMEDI_SUBD_CALIB; + if (boardtype.reg_type & ni_reg_m_series_mask) { + // internal PWM analog output used for AI nonlinearity calibration + s->subdev_flags = SDF_INTERNAL; + s->insn_config = &ni_m_series_pwm_config; + s->n_chan = 1; + s->maxdata = 0; + ni_writel(0x0, M_Offset_Cal_PWM); + } else if (boardtype.reg_type == ni_reg_6143) { + // internal PWM analog output used for AI nonlinearity calibration + s->subdev_flags = SDF_INTERNAL; + s->insn_config = &ni_6143_pwm_config; + s->n_chan = 1; + s->maxdata = 0; + } else { + s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; + s->insn_read = &ni_calib_insn_read; + s->insn_write = &ni_calib_insn_write; + caldac_setup(dev, s); + } + + /* EEPROM */ + s = dev->subdevices + NI_EEPROM_SUBDEV; + s->type = COMEDI_SUBD_MEMORY; + s->subdev_flags = SDF_READABLE | SDF_INTERNAL; + s->maxdata = 0xff; + if (boardtype.reg_type & ni_reg_m_series_mask) { + s->n_chan = M_SERIES_EEPROM_SIZE; + s->insn_read = &ni_m_series_eeprom_insn_read; + } else { + s->n_chan = 512; + s->insn_read = &ni_eeprom_insn_read; + } + + /* PFI */ + s = dev->subdevices + NI_PFI_DIO_SUBDEV; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + if (boardtype.reg_type & ni_reg_m_series_mask) { + unsigned i; + s->n_chan = 16; + ni_writew(s->state, M_Offset_PFI_DO); + for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) { + ni_writew(devpriv->pfi_output_select_reg[i], + M_Offset_PFI_Output_Select(i + 1)); + } + } else { + s->n_chan = 10; + } + s->maxdata = 1; + if (boardtype.reg_type & ni_reg_m_series_mask) { + s->insn_bits = &ni_pfi_insn_bits; + } + s->insn_config = &ni_pfi_insn_config; + ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0); + + /* cs5529 calibration adc */ + s = dev->subdevices + NI_CS5529_CALIBRATION_SUBDEV; + if (boardtype.reg_type & ni_reg_67xx_mask) { + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL; + // one channel for each analog output channel + s->n_chan = boardtype.n_aochan; + s->maxdata = (1 << 16) - 1; + s->range_table = &range_unknown; /* XXX */ + s->insn_read = cs5529_ai_insn_read; + s->insn_config = NULL; + init_cs5529(dev); + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + /* Serial */ + s = dev->subdevices + NI_SERIAL_SUBDEV; + s->type = COMEDI_SUBD_SERIAL; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 1; + s->maxdata = 0xff; + s->insn_config = ni_serial_insn_config; + devpriv->serial_interval_ns = 0; + devpriv->serial_hw_mode = 0; + + /* RTSI */ + s = dev->subdevices + NI_RTSI_SUBDEV; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = 8; + s->maxdata = 1; + s->insn_bits = ni_rtsi_insn_bits; + s->insn_config = ni_rtsi_insn_config; + ni_rtsi_init(dev); + + if (boardtype.reg_type & ni_reg_m_series_mask) { + counter_variant = ni_gpct_variant_m_series; + } else { + counter_variant = ni_gpct_variant_e_series; + } + devpriv->counter_dev = ni_gpct_device_construct(dev, + &ni_gpct_write_register, &ni_gpct_read_register, + counter_variant, NUM_GPCT); + /* General purpose counters */ + for (j = 0; j < NUM_GPCT; ++j) { + s = dev->subdevices + NI_GPCT_SUBDEV(j); + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = + SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ + /* | SDF_CMD_WRITE */ ; + s->n_chan = 3; + if (boardtype.reg_type & ni_reg_m_series_mask) + s->maxdata = 0xffffffff; + else + s->maxdata = 0xffffff; + s->insn_read = &ni_gpct_insn_read; + s->insn_write = &ni_gpct_insn_write; + s->insn_config = &ni_gpct_insn_config; + s->do_cmd = &ni_gpct_cmd; + s->len_chanlist = 1; + s->do_cmdtest = &ni_gpct_cmdtest; + s->cancel = &ni_gpct_cancel; + s->async_dma_dir = DMA_BIDIRECTIONAL; + s->private = &devpriv->counter_dev->counters[j]; + + devpriv->counter_dev->counters[j].chip_index = 0; + devpriv->counter_dev->counters[j].counter_index = j; + ni_tio_init_counter(&devpriv->counter_dev->counters[j]); + } + + /* Frequency output */ + s = dev->subdevices + NI_FREQ_OUT_SUBDEV; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 1; + s->maxdata = 0xf; + s->insn_read = &ni_freq_out_insn_read; + s->insn_write = &ni_freq_out_insn_write; + s->insn_config = &ni_freq_out_insn_config; + + /* ai configuration */ + ni_ai_reset(dev, dev->subdevices + NI_AI_SUBDEV); + if ((boardtype.reg_type & ni_reg_6xxx_mask) == 0) { + // BEAM is this needed for PCI-6143 ?? + devpriv->clock_and_fout = + Slow_Internal_Time_Divide_By_2 | + Slow_Internal_Timebase | + Clock_To_Board_Divide_By_2 | + Clock_To_Board | + AI_Output_Divide_By_2 | AO_Output_Divide_By_2; + } else { + devpriv->clock_and_fout = + Slow_Internal_Time_Divide_By_2 | + Slow_Internal_Timebase | + Clock_To_Board_Divide_By_2 | Clock_To_Board; + } + devpriv->stc_writew(dev, devpriv->clock_and_fout, + Clock_and_FOUT_Register); + + /* analog output configuration */ + ni_ao_reset(dev, dev->subdevices + NI_AO_SUBDEV); + + if (dev->irq) { + devpriv->stc_writew(dev, + (IRQ_POLARITY ? Interrupt_Output_Polarity : 0) | + (Interrupt_Output_On_3_Pins & 0) | Interrupt_A_Enable | + Interrupt_B_Enable | + Interrupt_A_Output_Select(interrupt_pin(dev-> + irq)) | + Interrupt_B_Output_Select(interrupt_pin(dev->irq)), + Interrupt_Control_Register); + } + + /* DMA setup */ + ni_writeb(devpriv->ai_ao_select_reg, AI_AO_Select); + ni_writeb(devpriv->g0_g1_select_reg, G0_G1_Select); + + if (boardtype.reg_type & ni_reg_6xxx_mask) { + ni_writeb(0, Magic_611x); + } else if (boardtype.reg_type & ni_reg_m_series_mask) { + int channel; + for (channel = 0; channel < boardtype.n_aochan; ++channel) { + ni_writeb(0xf, M_Offset_AO_Waveform_Order(channel)); + ni_writeb(0x0, + M_Offset_AO_Reference_Attenuation(channel)); + } + ni_writeb(0x0, M_Offset_AO_Calibration); + } + + printk("\n"); + return 0; +} + +static int ni_8255_callback(int dir, int port, int data, unsigned long arg) +{ + struct comedi_device *dev = (struct comedi_device *) arg; + + if (dir) { + ni_writeb(data, Port_A + 2 * port); + return 0; + } else { + return ni_readb(Port_A + 2 * port); + } +} + +/* + presents the EEPROM as a subdevice +*/ + +static int ni_eeprom_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = ni_read_eeprom(dev, CR_CHAN(insn->chanspec)); + + return 1; +} + +/* + reads bytes out of eeprom +*/ + +static int ni_read_eeprom(struct comedi_device * dev, int addr) +{ + int bit; + int bitstring; + + bitstring = 0x0300 | ((addr & 0x100) << 3) | (addr & 0xff); + ni_writeb(0x04, Serial_Command); + for (bit = 0x8000; bit; bit >>= 1) { + ni_writeb(0x04 | ((bit & bitstring) ? 0x02 : 0), + Serial_Command); + ni_writeb(0x05 | ((bit & bitstring) ? 0x02 : 0), + Serial_Command); + } + bitstring = 0; + for (bit = 0x80; bit; bit >>= 1) { + ni_writeb(0x04, Serial_Command); + ni_writeb(0x05, Serial_Command); + bitstring |= ((ni_readb(XXX_Status) & PROMOUT) ? bit : 0); + } + ni_writeb(0x00, Serial_Command); + + return bitstring; +} + +static int ni_m_series_eeprom_insn_read(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int ni_get_pwm_config(struct comedi_device * dev, unsigned int * data) +{ + data[1] = devpriv->pwm_up_count * devpriv->clock_ns; + data[2] = devpriv->pwm_down_count * devpriv->clock_ns; + return 3; +} + +static int ni_m_series_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned up_count, down_count; + switch (data[0]) { + case INSN_CONFIG_PWM_OUTPUT: + switch (data[1]) { + case TRIG_ROUND_NEAREST: + up_count = + (data[2] + + devpriv->clock_ns / 2) / devpriv->clock_ns; + break; + case TRIG_ROUND_DOWN: + up_count = data[2] / devpriv->clock_ns; + break; + case TRIG_ROUND_UP: + up_count = + (data[2] + devpriv->clock_ns - + 1) / devpriv->clock_ns; + break; + default: + return -EINVAL; + break; + } + switch (data[3]) { + case TRIG_ROUND_NEAREST: + down_count = + (data[4] + + devpriv->clock_ns / 2) / devpriv->clock_ns; + break; + case TRIG_ROUND_DOWN: + down_count = data[4] / devpriv->clock_ns; + break; + case TRIG_ROUND_UP: + down_count = + (data[4] + devpriv->clock_ns - + 1) / devpriv->clock_ns; + break; + default: + return -EINVAL; + break; + } + if (up_count * devpriv->clock_ns != data[2] || + down_count * devpriv->clock_ns != data[4]) { + data[2] = up_count * devpriv->clock_ns; + data[4] = down_count * devpriv->clock_ns; + return -EAGAIN; + } + ni_writel(MSeries_Cal_PWM_High_Time_Bits(up_count) | + MSeries_Cal_PWM_Low_Time_Bits(down_count), + M_Offset_Cal_PWM); + devpriv->pwm_up_count = up_count; + devpriv->pwm_down_count = down_count; + return 5; + break; + case INSN_CONFIG_GET_PWM_OUTPUT: + return ni_get_pwm_config(dev, data); + break; + default: + return -EINVAL; + break; + } + return 0; +} + +static int ni_6143_pwm_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned up_count, down_count; + switch (data[0]) { + case INSN_CONFIG_PWM_OUTPUT: + switch (data[1]) { + case TRIG_ROUND_NEAREST: + up_count = + (data[2] + + devpriv->clock_ns / 2) / devpriv->clock_ns; + break; + case TRIG_ROUND_DOWN: + up_count = data[2] / devpriv->clock_ns; + break; + case TRIG_ROUND_UP: + up_count = + (data[2] + devpriv->clock_ns - + 1) / devpriv->clock_ns; + break; + default: + return -EINVAL; + break; + } + switch (data[3]) { + case TRIG_ROUND_NEAREST: + down_count = + (data[4] + + devpriv->clock_ns / 2) / devpriv->clock_ns; + break; + case TRIG_ROUND_DOWN: + down_count = data[4] / devpriv->clock_ns; + break; + case TRIG_ROUND_UP: + down_count = + (data[4] + devpriv->clock_ns - + 1) / devpriv->clock_ns; + break; + default: + return -EINVAL; + break; + } + if (up_count * devpriv->clock_ns != data[2] || + down_count * devpriv->clock_ns != data[4]) { + data[2] = up_count * devpriv->clock_ns; + data[4] = down_count * devpriv->clock_ns; + return -EAGAIN; + } + ni_writel(up_count, Calibration_HighTime_6143); + devpriv->pwm_up_count = up_count; + ni_writel(down_count, Calibration_LowTime_6143); + devpriv->pwm_down_count = down_count; + return 5; + break; + case INSN_CONFIG_GET_PWM_OUTPUT: + return ni_get_pwm_config(dev, data); + default: + return -EINVAL; + break; + } + return 0; +} + +static void ni_write_caldac(struct comedi_device * dev, int addr, int val); +/* + calibration subdevice +*/ +static int ni_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + ni_write_caldac(dev, CR_CHAN(insn->chanspec), data[0]); + + return 1; +} + +static int ni_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)]; + + return 1; +} + +static int pack_mb88341(int addr, int val, int *bitstring); +static int pack_dac8800(int addr, int val, int *bitstring); +static int pack_dac8043(int addr, int val, int *bitstring); +static int pack_ad8522(int addr, int val, int *bitstring); +static int pack_ad8804(int addr, int val, int *bitstring); +static int pack_ad8842(int addr, int val, int *bitstring); + +struct caldac_struct { + int n_chans; + int n_bits; + int (*packbits) (int, int, int *); +}; + +static struct caldac_struct caldacs[] = { + [mb88341] = {12, 8, pack_mb88341}, + [dac8800] = {8, 8, pack_dac8800}, + [dac8043] = {1, 12, pack_dac8043}, + [ad8522] = {2, 12, pack_ad8522}, + [ad8804] = {12, 8, pack_ad8804}, + [ad8842] = {8, 8, pack_ad8842}, + [ad8804_debug] = {16, 8, pack_ad8804}, +}; + +static void caldac_setup(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int i, j; + int n_dacs; + int n_chans = 0; + int n_bits; + int diffbits = 0; + int type; + int chan; + + type = boardtype.caldac[0]; + if (type == caldac_none) + return; + n_bits = caldacs[type].n_bits; + for (i = 0; i < 3; i++) { + type = boardtype.caldac[i]; + if (type == caldac_none) + break; + if (caldacs[type].n_bits != n_bits) + diffbits = 1; + n_chans += caldacs[type].n_chans; + } + n_dacs = i; + s->n_chan = n_chans; + + if (diffbits) { + unsigned int *maxdata_list; + + if (n_chans > MAX_N_CALDACS) { + printk("BUG! MAX_N_CALDACS too small\n"); + } + s->maxdata_list = maxdata_list = devpriv->caldac_maxdata_list; + chan = 0; + for (i = 0; i < n_dacs; i++) { + type = boardtype.caldac[i]; + for (j = 0; j < caldacs[type].n_chans; j++) { + maxdata_list[chan] = + (1 << caldacs[type].n_bits) - 1; + chan++; + } + } + + for (chan = 0; chan < s->n_chan; chan++) + ni_write_caldac(dev, i, s->maxdata_list[i] / 2); + } else { + type = boardtype.caldac[0]; + s->maxdata = (1 << caldacs[type].n_bits) - 1; + + for (chan = 0; chan < s->n_chan; chan++) + ni_write_caldac(dev, i, s->maxdata / 2); + } +} + +static void ni_write_caldac(struct comedi_device * dev, int addr, int val) +{ + unsigned int loadbit = 0, bits = 0, bit, bitstring = 0; + int i; + int type; + + //printk("ni_write_caldac: chan=%d val=%d\n",addr,val); + if (devpriv->caldacs[addr] == val) + return; + devpriv->caldacs[addr] = val; + + for (i = 0; i < 3; i++) { + type = boardtype.caldac[i]; + if (type == caldac_none) + break; + if (addr < caldacs[type].n_chans) { + bits = caldacs[type].packbits(addr, val, &bitstring); + loadbit = SerDacLd(i); + //printk("caldac: using i=%d addr=%d %x\n",i,addr,bitstring); + break; + } + addr -= caldacs[type].n_chans; + } + + for (bit = 1 << (bits - 1); bit; bit >>= 1) { + ni_writeb(((bit & bitstring) ? 0x02 : 0), Serial_Command); + comedi_udelay(1); + ni_writeb(1 | ((bit & bitstring) ? 0x02 : 0), Serial_Command); + comedi_udelay(1); + } + ni_writeb(loadbit, Serial_Command); + comedi_udelay(1); + ni_writeb(0, Serial_Command); +} + +static int pack_mb88341(int addr, int val, int *bitstring) +{ + /* + Fujitsu MB 88341 + Note that address bits are reversed. Thanks to + Ingo Keen for noticing this. + + Note also that the 88341 expects address values from + 1-12, whereas we use channel numbers 0-11. The NI + docs use 1-12, also, so be careful here. + */ + addr++; + *bitstring = ((addr & 0x1) << 11) | + ((addr & 0x2) << 9) | + ((addr & 0x4) << 7) | ((addr & 0x8) << 5) | (val & 0xff); + return 12; +} + +static int pack_dac8800(int addr, int val, int *bitstring) +{ + *bitstring = ((addr & 0x7) << 8) | (val & 0xff); + return 11; +} + +static int pack_dac8043(int addr, int val, int *bitstring) +{ + *bitstring = val & 0xfff; + return 12; +} + +static int pack_ad8522(int addr, int val, int *bitstring) +{ + *bitstring = (val & 0xfff) | (addr ? 0xc000 : 0xa000); + return 16; +} + +static int pack_ad8804(int addr, int val, int *bitstring) +{ + *bitstring = ((addr & 0xf) << 8) | (val & 0xff); + return 12; +} + +static int pack_ad8842(int addr, int val, int *bitstring) +{ + *bitstring = ((addr + 1) << 8) | (val & 0xff); + return 12; +} + +#if 0 +/* + * Read the GPCTs current value. + */ +static int GPCT_G_Watch(struct comedi_device * dev, int chan) +{ + unsigned int hi1, hi2, lo; + + devpriv->gpct_command[chan] &= ~G_Save_Trace; + devpriv->stc_writew(dev, devpriv->gpct_command[chan], + G_Command_Register(chan)); + + devpriv->gpct_command[chan] |= G_Save_Trace; + devpriv->stc_writew(dev, devpriv->gpct_command[chan], + G_Command_Register(chan)); + + /* This procedure is used because the two registers cannot + * be read atomically. */ + do { + hi1 = devpriv->stc_readw(dev, G_Save_Register_High(chan)); + lo = devpriv->stc_readw(dev, G_Save_Register_Low(chan)); + hi2 = devpriv->stc_readw(dev, G_Save_Register_High(chan)); + } while (hi1 != hi2); + + return (hi1 << 16) | lo; +} + +static void GPCT_Reset(struct comedi_device * dev, int chan) +{ + int temp_ack_reg = 0; + + //printk("GPCT_Reset..."); + devpriv->gpct_cur_operation[chan] = GPCT_RESET; + + switch (chan) { + case 0: + devpriv->stc_writew(dev, G0_Reset, Joint_Reset_Register); + ni_set_bits(dev, Interrupt_A_Enable_Register, + G0_TC_Interrupt_Enable, 0); + ni_set_bits(dev, Interrupt_A_Enable_Register, + G0_Gate_Interrupt_Enable, 0); + temp_ack_reg |= G0_Gate_Error_Confirm; + temp_ack_reg |= G0_TC_Error_Confirm; + temp_ack_reg |= G0_TC_Interrupt_Ack; + temp_ack_reg |= G0_Gate_Interrupt_Ack; + devpriv->stc_writew(dev, temp_ack_reg, + Interrupt_A_Ack_Register); + + //problem...this interferes with the other ctr... + devpriv->an_trig_etc_reg |= GPFO_0_Output_Enable; + devpriv->stc_writew(dev, devpriv->an_trig_etc_reg, + Analog_Trigger_Etc_Register); + break; + case 1: + devpriv->stc_writew(dev, G1_Reset, Joint_Reset_Register); + ni_set_bits(dev, Interrupt_B_Enable_Register, + G1_TC_Interrupt_Enable, 0); + ni_set_bits(dev, Interrupt_B_Enable_Register, + G0_Gate_Interrupt_Enable, 0); + temp_ack_reg |= G1_Gate_Error_Confirm; + temp_ack_reg |= G1_TC_Error_Confirm; + temp_ack_reg |= G1_TC_Interrupt_Ack; + temp_ack_reg |= G1_Gate_Interrupt_Ack; + devpriv->stc_writew(dev, temp_ack_reg, + Interrupt_B_Ack_Register); + + devpriv->an_trig_etc_reg |= GPFO_1_Output_Enable; + devpriv->stc_writew(dev, devpriv->an_trig_etc_reg, + Analog_Trigger_Etc_Register); + break; + }; + + devpriv->gpct_mode[chan] = 0; + devpriv->gpct_input_select[chan] = 0; + devpriv->gpct_command[chan] = 0; + + devpriv->gpct_command[chan] |= G_Synchronized_Gate; + + devpriv->stc_writew(dev, devpriv->gpct_mode[chan], + G_Mode_Register(chan)); + devpriv->stc_writew(dev, devpriv->gpct_input_select[chan], + G_Input_Select_Register(chan)); + devpriv->stc_writew(dev, 0, G_Autoincrement_Register(chan)); + + //printk("exit GPCT_Reset\n"); +} + +#endif + +static int ni_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct ni_gpct *counter = s->private; + return ni_tio_insn_config(counter, insn, data); +} + +static int ni_gpct_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct ni_gpct *counter = s->private; + return ni_tio_rinsn(counter, insn, data); +} + +static int ni_gpct_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct ni_gpct *counter = s->private; + return ni_tio_winsn(counter, insn, data); +} + +static int ni_gpct_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int retval; +#ifdef PCIDMA + struct ni_gpct *counter = s->private; +// const struct comedi_cmd *cmd = &s->async->cmd; + + retval = ni_request_gpct_mite_channel(dev, counter->counter_index, + COMEDI_INPUT); + if (retval) { + comedi_error(dev, + "no dma channel available for use by counter"); + return retval; + } + ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL); + ni_e_series_enable_second_irq(dev, counter->counter_index, 1); + retval = ni_tio_cmd(counter, s->async); +#else + retval = -ENOTSUPP; +#endif + return retval; +} + +static int ni_gpct_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ +#ifdef PCIDMA + struct ni_gpct *counter = s->private; + + return ni_tio_cmdtest(counter, cmd); +#else + return -ENOTSUPP; +#endif +} + +static int ni_gpct_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ +#ifdef PCIDMA + struct ni_gpct *counter = s->private; + int retval; + + retval = ni_tio_cancel(counter); + ni_e_series_enable_second_irq(dev, counter->counter_index, 0); + ni_release_gpct_mite_channel(dev, counter->counter_index); + return retval; +#else + return 0; +#endif +} + +/* + * + * Programmable Function Inputs + * + */ + +static int ni_m_series_set_pfi_routing(struct comedi_device * dev, unsigned chan, + unsigned source) +{ + unsigned pfi_reg_index; + unsigned array_offset; + if ((source & 0x1f) != source) + return -EINVAL; + pfi_reg_index = 1 + chan / 3; + array_offset = pfi_reg_index - 1; + devpriv->pfi_output_select_reg[array_offset] &= + ~MSeries_PFI_Output_Select_Mask(chan); + devpriv->pfi_output_select_reg[array_offset] |= + MSeries_PFI_Output_Select_Bits(chan, source); + ni_writew(devpriv->pfi_output_select_reg[array_offset], + M_Offset_PFI_Output_Select(pfi_reg_index)); + return 2; +} + +static int ni_old_set_pfi_routing(struct comedi_device * dev, unsigned chan, + unsigned source) +{ + // pre-m-series boards have fixed signals on pfi pins + if (source != ni_old_get_pfi_routing(dev, chan)) + return -EINVAL; + return 2; +} + +static int ni_set_pfi_routing(struct comedi_device * dev, unsigned chan, + unsigned source) +{ + if (boardtype.reg_type & ni_reg_m_series_mask) + return ni_m_series_set_pfi_routing(dev, chan, source); + else + return ni_old_set_pfi_routing(dev, chan, source); +} + +static unsigned ni_m_series_get_pfi_routing(struct comedi_device * dev, unsigned chan) +{ + const unsigned array_offset = chan / 3; + return MSeries_PFI_Output_Select_Source(chan, + devpriv->pfi_output_select_reg[array_offset]); +} + +static unsigned ni_old_get_pfi_routing(struct comedi_device * dev, unsigned chan) +{ + // pre-m-series boards have fixed signals on pfi pins + switch (chan) { + case 0: + return NI_PFI_OUTPUT_AI_START1; + break; + case 1: + return NI_PFI_OUTPUT_AI_START2; + break; + case 2: + return NI_PFI_OUTPUT_AI_CONVERT; + break; + case 3: + return NI_PFI_OUTPUT_G_SRC1; + break; + case 4: + return NI_PFI_OUTPUT_G_GATE1; + break; + case 5: + return NI_PFI_OUTPUT_AO_UPDATE_N; + break; + case 6: + return NI_PFI_OUTPUT_AO_START1; + break; + case 7: + return NI_PFI_OUTPUT_AI_START_PULSE; + break; + case 8: + return NI_PFI_OUTPUT_G_SRC0; + break; + case 9: + return NI_PFI_OUTPUT_G_GATE0; + break; + default: + rt_printk("%s: bug, unhandled case in switch.\n", __FUNCTION__); + break; + } + return 0; +} + +static unsigned ni_get_pfi_routing(struct comedi_device * dev, unsigned chan) +{ + if (boardtype.reg_type & ni_reg_m_series_mask) + return ni_m_series_get_pfi_routing(dev, chan); + else + return ni_old_get_pfi_routing(dev, chan); +} + +static int ni_config_filter(struct comedi_device * dev, unsigned pfi_channel, + enum ni_pfi_filter_select filter) +{ + unsigned bits; + if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) { + return -ENOTSUPP; + } + bits = ni_readl(M_Offset_PFI_Filter); + bits &= ~MSeries_PFI_Filter_Select_Mask(pfi_channel); + bits |= MSeries_PFI_Filter_Select_Bits(pfi_channel, filter); + ni_writel(bits, M_Offset_PFI_Filter); + return 0; +} + +static int ni_pfi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if ((boardtype.reg_type & ni_reg_m_series_mask) == 0) { + return -ENOTSUPP; + } + if (data[0]) { + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + ni_writew(s->state, M_Offset_PFI_DO); + } + data[1] = ni_readw(M_Offset_PFI_DI); + return 2; +} + +static int ni_pfi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int chan; + + if (insn->n < 1) + return -EINVAL; + + chan = CR_CHAN(insn->chanspec); + + switch (data[0]) { + case COMEDI_OUTPUT: + ni_set_bits(dev, IO_Bidirection_Pin_Register, 1 << chan, 1); + break; + case COMEDI_INPUT: + ni_set_bits(dev, IO_Bidirection_Pin_Register, 1 << chan, 0); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (devpriv-> + io_bidirection_pin_reg & (1 << chan)) ? COMEDI_OUTPUT : + COMEDI_INPUT; + return 0; + break; + case INSN_CONFIG_SET_ROUTING: + return ni_set_pfi_routing(dev, chan, data[1]); + break; + case INSN_CONFIG_GET_ROUTING: + data[1] = ni_get_pfi_routing(dev, chan); + break; + case INSN_CONFIG_FILTER: + return ni_config_filter(dev, chan, data[1]); + break; + default: + return -EINVAL; + } + return 0; +} + +/* + * + * NI RTSI Bus Functions + * + */ +static void ni_rtsi_init(struct comedi_device * dev) +{ + // Initialises the RTSI bus signal switch to a default state + + // Set clock mode to internal + devpriv->clock_and_fout2 = MSeries_RTSI_10MHz_Bit; + if (ni_set_master_clock(dev, NI_MIO_INTERNAL_CLOCK, 0) < 0) { + rt_printk("ni_set_master_clock failed, bug?"); + } + // default internal lines routing to RTSI bus lines + devpriv->rtsi_trig_a_output_reg = + RTSI_Trig_Output_Bits(0, + NI_RTSI_OUTPUT_ADR_START1) | RTSI_Trig_Output_Bits(1, + NI_RTSI_OUTPUT_ADR_START2) | RTSI_Trig_Output_Bits(2, + NI_RTSI_OUTPUT_SCLKG) | RTSI_Trig_Output_Bits(3, + NI_RTSI_OUTPUT_DACUPDN); + devpriv->stc_writew(dev, devpriv->rtsi_trig_a_output_reg, + RTSI_Trig_A_Output_Register); + devpriv->rtsi_trig_b_output_reg = + RTSI_Trig_Output_Bits(4, + NI_RTSI_OUTPUT_DA_START1) | RTSI_Trig_Output_Bits(5, + NI_RTSI_OUTPUT_G_SRC0) | RTSI_Trig_Output_Bits(6, + NI_RTSI_OUTPUT_G_GATE0); + if (boardtype.reg_type & ni_reg_m_series_mask) + devpriv->rtsi_trig_b_output_reg |= + RTSI_Trig_Output_Bits(7, NI_RTSI_OUTPUT_RTSI_OSC); + devpriv->stc_writew(dev, devpriv->rtsi_trig_b_output_reg, + RTSI_Trig_B_Output_Register); + + // Sets the source and direction of the 4 on board lines +// devpriv->stc_writew(dev, 0x0000, RTSI_Board_Register); +} + +static int ni_rtsi_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + data[1] = 0; + + return 2; +} + +/* Find best multiplier/divider to try and get the PLL running at 80 MHz + * given an arbitrary frequency input clock */ +static int ni_mseries_get_pll_parameters(unsigned reference_period_ns, + unsigned *freq_divider, unsigned *freq_multiplier, + unsigned *actual_period_ns) +{ + unsigned div; + unsigned best_div = 1; + static const unsigned max_div = 0x10; + unsigned mult; + unsigned best_mult = 1; + static const unsigned max_mult = 0x100; + static const unsigned pico_per_nano = 1000; + + const unsigned reference_picosec = reference_period_ns * pico_per_nano; + /* m-series wants the phased-locked loop to output 80MHz, which is divided by 4 to + * 20 MHz for most timing clocks */ + static const unsigned target_picosec = 12500; + static const unsigned fudge_factor_80_to_20Mhz = 4; + int best_period_picosec = 0; + for (div = 1; div <= max_div; ++div) { + for (mult = 1; mult <= max_mult; ++mult) { + unsigned new_period_ps = + (reference_picosec * div) / mult; + if (abs(new_period_ps - target_picosec) < + abs(best_period_picosec - target_picosec)) { + best_period_picosec = new_period_ps; + best_div = div; + best_mult = mult; + } + } + } + if (best_period_picosec == 0) { + rt_printk("%s: bug, failed to find pll parameters\n", + __FUNCTION__); + return -EIO; + } + *freq_divider = best_div; + *freq_multiplier = best_mult; + *actual_period_ns = + (best_period_picosec * fudge_factor_80_to_20Mhz + + (pico_per_nano / 2)) / pico_per_nano; + return 0; +} + +static inline unsigned num_configurable_rtsi_channels(struct comedi_device * dev) +{ + if (boardtype.reg_type & ni_reg_m_series_mask) + return 8; + else + return 7; +} + +static int ni_mseries_set_pll_master_clock(struct comedi_device * dev, unsigned source, + unsigned period_ns) +{ + static const unsigned min_period_ns = 50; + static const unsigned max_period_ns = 1000; + static const unsigned timeout = 1000; + unsigned pll_control_bits; + unsigned freq_divider; + unsigned freq_multiplier; + unsigned i; + int retval; + if (source == NI_MIO_PLL_PXI10_CLOCK) + period_ns = 100; + // these limits are somewhat arbitrary, but NI advertises 1 to 20MHz range so we'll use that + if (period_ns < min_period_ns || period_ns > max_period_ns) { + rt_printk + ("%s: you must specify an input clock frequency between %i and %i nanosec " + "for the phased-lock loop.\n", __FUNCTION__, + min_period_ns, max_period_ns); + return -EINVAL; + } + devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit; + devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, + RTSI_Trig_Direction_Register); + pll_control_bits = + MSeries_PLL_Enable_Bit | MSeries_PLL_VCO_Mode_75_150MHz_Bits; + devpriv->clock_and_fout2 |= + MSeries_Timebase1_Select_Bit | MSeries_Timebase3_Select_Bit; + devpriv->clock_and_fout2 &= ~MSeries_PLL_In_Source_Select_Mask; + switch (source) { + case NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK: + devpriv->clock_and_fout2 |= + MSeries_PLL_In_Source_Select_Star_Trigger_Bits; + retval = ni_mseries_get_pll_parameters(period_ns, &freq_divider, + &freq_multiplier, &devpriv->clock_ns); + if (retval < 0) + return retval; + break; + case NI_MIO_PLL_PXI10_CLOCK: + /* pxi clock is 10MHz */ + devpriv->clock_and_fout2 |= + MSeries_PLL_In_Source_Select_PXI_Clock10; + retval = ni_mseries_get_pll_parameters(period_ns, &freq_divider, + &freq_multiplier, &devpriv->clock_ns); + if (retval < 0) + return retval; + break; + default: + { + unsigned rtsi_channel; + static const unsigned max_rtsi_channel = 7; + for (rtsi_channel = 0; rtsi_channel <= max_rtsi_channel; + ++rtsi_channel) { + if (source == + NI_MIO_PLL_RTSI_CLOCK(rtsi_channel)) { + devpriv->clock_and_fout2 |= + MSeries_PLL_In_Source_Select_RTSI_Bits + (rtsi_channel); + break; + } + } + if (rtsi_channel > max_rtsi_channel) + return -EINVAL; + retval = ni_mseries_get_pll_parameters(period_ns, + &freq_divider, &freq_multiplier, + &devpriv->clock_ns); + if (retval < 0) + return retval; + } + break; + } + ni_writew(devpriv->clock_and_fout2, M_Offset_Clock_and_Fout2); + pll_control_bits |= + MSeries_PLL_Divisor_Bits(freq_divider) | + MSeries_PLL_Multiplier_Bits(freq_multiplier); +// rt_printk("using divider=%i, multiplier=%i for PLL. pll_control_bits = 0x%x\n", freq_divider, freq_multiplier, pll_control_bits); +// rt_printk("clock_ns=%d\n", devpriv->clock_ns); + ni_writew(pll_control_bits, M_Offset_PLL_Control); + devpriv->clock_source = source; + /* it seems to typically take a few hundred microseconds for PLL to lock */ + for (i = 0; i < timeout; ++i) { + if (ni_readw(M_Offset_PLL_Status) & MSeries_PLL_Locked_Bit) { + break; + } + udelay(1); + } + if (i == timeout) { + rt_printk + ("%s: timed out waiting for PLL to lock to reference clock source %i with period %i ns.\n", + __FUNCTION__, source, period_ns); + return -ETIMEDOUT; + } + return 3; +} + +static int ni_set_master_clock(struct comedi_device * dev, unsigned source, + unsigned period_ns) +{ + if (source == NI_MIO_INTERNAL_CLOCK) { + devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit; + devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, + RTSI_Trig_Direction_Register); + devpriv->clock_ns = TIMEBASE_1_NS; + if (boardtype.reg_type & ni_reg_m_series_mask) { + devpriv->clock_and_fout2 &= + ~(MSeries_Timebase1_Select_Bit | + MSeries_Timebase3_Select_Bit); + ni_writew(devpriv->clock_and_fout2, + M_Offset_Clock_and_Fout2); + ni_writew(0, M_Offset_PLL_Control); + } + devpriv->clock_source = source; + } else { + if (boardtype.reg_type & ni_reg_m_series_mask) { + return ni_mseries_set_pll_master_clock(dev, source, + period_ns); + } else { + if (source == NI_MIO_RTSI_CLOCK) { + devpriv->rtsi_trig_direction_reg |= + Use_RTSI_Clock_Bit; + devpriv->stc_writew(dev, + devpriv->rtsi_trig_direction_reg, + RTSI_Trig_Direction_Register); + if (period_ns == 0) { + rt_printk + ("%s: we don't handle an unspecified clock period correctly yet, returning error.\n", + __FUNCTION__); + return -EINVAL; + } else { + devpriv->clock_ns = period_ns; + } + devpriv->clock_source = source; + } else + return -EINVAL; + } + } + return 3; +} + +static int ni_valid_rtsi_output_source(struct comedi_device * dev, unsigned chan, + unsigned source) +{ + if (chan >= num_configurable_rtsi_channels(dev)) { + if (chan == old_RTSI_clock_channel) { + if (source == NI_RTSI_OUTPUT_RTSI_OSC) + return 1; + else { + rt_printk + ("%s: invalid source for channel=%i, channel %i is always the RTSI clock for pre-m-series boards.\n", + __FUNCTION__, chan, + old_RTSI_clock_channel); + return 0; + } + } + return 0; + } + switch (source) { + case NI_RTSI_OUTPUT_ADR_START1: + case NI_RTSI_OUTPUT_ADR_START2: + case NI_RTSI_OUTPUT_SCLKG: + case NI_RTSI_OUTPUT_DACUPDN: + case NI_RTSI_OUTPUT_DA_START1: + case NI_RTSI_OUTPUT_G_SRC0: + case NI_RTSI_OUTPUT_G_GATE0: + case NI_RTSI_OUTPUT_RGOUT0: + case NI_RTSI_OUTPUT_RTSI_BRD_0: + return 1; + break; + case NI_RTSI_OUTPUT_RTSI_OSC: + if (boardtype.reg_type & ni_reg_m_series_mask) + return 1; + else + return 0; + break; + default: + return 0; + break; + } +} + +static int ni_set_rtsi_routing(struct comedi_device * dev, unsigned chan, + unsigned source) +{ + if (ni_valid_rtsi_output_source(dev, chan, source) == 0) + return -EINVAL; + if (chan < 4) { + devpriv->rtsi_trig_a_output_reg &= ~RTSI_Trig_Output_Mask(chan); + devpriv->rtsi_trig_a_output_reg |= + RTSI_Trig_Output_Bits(chan, source); + devpriv->stc_writew(dev, devpriv->rtsi_trig_a_output_reg, + RTSI_Trig_A_Output_Register); + } else if (chan < 8) { + devpriv->rtsi_trig_b_output_reg &= ~RTSI_Trig_Output_Mask(chan); + devpriv->rtsi_trig_b_output_reg |= + RTSI_Trig_Output_Bits(chan, source); + devpriv->stc_writew(dev, devpriv->rtsi_trig_b_output_reg, + RTSI_Trig_B_Output_Register); + } + return 2; +} + +static unsigned ni_get_rtsi_routing(struct comedi_device * dev, unsigned chan) +{ + if (chan < 4) { + return RTSI_Trig_Output_Source(chan, + devpriv->rtsi_trig_a_output_reg); + } else if (chan < num_configurable_rtsi_channels(dev)) { + return RTSI_Trig_Output_Source(chan, + devpriv->rtsi_trig_b_output_reg); + } else { + if (chan == old_RTSI_clock_channel) + return NI_RTSI_OUTPUT_RTSI_OSC; + rt_printk("%s: bug! should never get here?\n", __FUNCTION__); + return 0; + } +} + +static int ni_rtsi_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + if (chan < num_configurable_rtsi_channels(dev)) { + devpriv->rtsi_trig_direction_reg |= + RTSI_Output_Bit(chan, + (boardtype.reg_type & ni_reg_m_series_mask) != + 0); + } else if (chan == old_RTSI_clock_channel) { + devpriv->rtsi_trig_direction_reg |= + Drive_RTSI_Clock_Bit; + } + devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, + RTSI_Trig_Direction_Register); + break; + case INSN_CONFIG_DIO_INPUT: + if (chan < num_configurable_rtsi_channels(dev)) { + devpriv->rtsi_trig_direction_reg &= + ~RTSI_Output_Bit(chan, + (boardtype.reg_type & ni_reg_m_series_mask) != + 0); + } else if (chan == old_RTSI_clock_channel) { + devpriv->rtsi_trig_direction_reg &= + ~Drive_RTSI_Clock_Bit; + } + devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, + RTSI_Trig_Direction_Register); + break; + case INSN_CONFIG_DIO_QUERY: + if (chan < num_configurable_rtsi_channels(dev)) { + data[1] = + (devpriv-> + rtsi_trig_direction_reg & RTSI_Output_Bit(chan, + (boardtype. + reg_type & ni_reg_m_series_mask) + != + 0)) ? INSN_CONFIG_DIO_OUTPUT : + INSN_CONFIG_DIO_INPUT; + } else if (chan == old_RTSI_clock_channel) { + data[1] = + (devpriv-> + rtsi_trig_direction_reg & Drive_RTSI_Clock_Bit) + ? INSN_CONFIG_DIO_OUTPUT : + INSN_CONFIG_DIO_INPUT; + } + return 2; + break; + case INSN_CONFIG_SET_CLOCK_SRC: + return ni_set_master_clock(dev, data[1], data[2]); + break; + case INSN_CONFIG_GET_CLOCK_SRC: + data[1] = devpriv->clock_source; + data[2] = devpriv->clock_ns; + return 3; + break; + case INSN_CONFIG_SET_ROUTING: + return ni_set_rtsi_routing(dev, chan, data[1]); + break; + case INSN_CONFIG_GET_ROUTING: + data[1] = ni_get_rtsi_routing(dev, chan); + return 2; + break; + default: + return -EINVAL; + break; + } + return 1; +} + +static int cs5529_wait_for_idle(struct comedi_device * dev) +{ + unsigned short status; + const int timeout = HZ; + int i; + + for (i = 0; i < timeout; i++) { + status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx); + if ((status & CSS_ADC_BUSY) == 0) { + break; + } + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout(1)) { + return -EIO; + } + } +//printk("looped %i times waiting for idle\n", i); + if (i == timeout) { + rt_printk("%s: %s: timeout\n", __FILE__, __FUNCTION__); + return -ETIME; + } + return 0; +} + +static void cs5529_command(struct comedi_device * dev, unsigned short value) +{ + static const int timeout = 100; + int i; + + ni_ao_win_outw(dev, value, CAL_ADC_Command_67xx); + /* give time for command to start being serially clocked into cs5529. + * this insures that the CSS_ADC_BUSY bit will get properly + * set before we exit this function. + */ + for (i = 0; i < timeout; i++) { + if ((ni_ao_win_inw(dev, CAL_ADC_Status_67xx) & CSS_ADC_BUSY)) + break; + comedi_udelay(1); + } +//printk("looped %i times writing command to cs5529\n", i); + if (i == timeout) { + comedi_error(dev, "possible problem - never saw adc go busy?"); + } +} + +/* write to cs5529 register */ +static void cs5529_config_write(struct comedi_device * dev, unsigned int value, + unsigned int reg_select_bits) +{ + ni_ao_win_outw(dev, ((value >> 16) & 0xff), + CAL_ADC_Config_Data_High_Word_67xx); + ni_ao_win_outw(dev, (value & 0xffff), + CAL_ADC_Config_Data_Low_Word_67xx); + reg_select_bits &= CSCMD_REGISTER_SELECT_MASK; + cs5529_command(dev, CSCMD_COMMAND | reg_select_bits); + if (cs5529_wait_for_idle(dev)) + comedi_error(dev, "time or signal in cs5529_config_write()"); +} + +#ifdef NI_CS5529_DEBUG +/* read from cs5529 register */ +static unsigned int cs5529_config_read(struct comedi_device * dev, + unsigned int reg_select_bits) +{ + unsigned int value; + + reg_select_bits &= CSCMD_REGISTER_SELECT_MASK; + cs5529_command(dev, CSCMD_COMMAND | CSCMD_READ | reg_select_bits); + if (cs5529_wait_for_idle(dev)) + comedi_error(dev, "timeout or signal in cs5529_config_read()"); + value = (ni_ao_win_inw(dev, + CAL_ADC_Config_Data_High_Word_67xx) << 16) & 0xff0000; + value |= ni_ao_win_inw(dev, CAL_ADC_Config_Data_Low_Word_67xx) & 0xffff; + return value; +} +#endif + +static int cs5529_do_conversion(struct comedi_device * dev, unsigned short *data) +{ + int retval; + unsigned short status; + + cs5529_command(dev, CSCMD_COMMAND | CSCMD_SINGLE_CONVERSION); + retval = cs5529_wait_for_idle(dev); + if (retval) { + comedi_error(dev, + "timeout or signal in cs5529_do_conversion()"); + return -ETIME; + } + status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx); + if (status & CSS_OSC_DETECT) { + rt_printk + ("ni_mio_common: cs5529 conversion error, status CSS_OSC_DETECT\n"); + return -EIO; + } + if (status & CSS_OVERRANGE) { + rt_printk + ("ni_mio_common: cs5529 conversion error, overrange (ignoring)\n"); + } + if (data) { + *data = ni_ao_win_inw(dev, CAL_ADC_Data_67xx); + /* cs5529 returns 16 bit signed data in bipolar mode */ + *data ^= (1 << 15); + } + return 0; +} + +static int cs5529_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, retval; + unsigned short sample; + unsigned int channel_select; + const unsigned int INTERNAL_REF = 0x1000; + + /* Set calibration adc source. Docs lie, reference select bits 8 to 11 + * do nothing. bit 12 seems to chooses internal reference voltage, bit + * 13 causes the adc input to go overrange (maybe reads external reference?) */ + if (insn->chanspec & CR_ALT_SOURCE) + channel_select = INTERNAL_REF; + else + channel_select = CR_CHAN(insn->chanspec); + ni_ao_win_outw(dev, channel_select, AO_Calibration_Channel_Select_67xx); + + for (n = 0; n < insn->n; n++) { + retval = cs5529_do_conversion(dev, &sample); + if (retval < 0) + return retval; + data[n] = sample; + } + return insn->n; +} + +static int init_cs5529(struct comedi_device * dev) +{ + unsigned int config_bits = + CSCFG_PORT_MODE | CSCFG_WORD_RATE_2180_CYCLES; + +#if 1 + /* do self-calibration */ + cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET_GAIN, + CSCMD_CONFIG_REGISTER); + /* need to force a conversion for calibration to run */ + cs5529_do_conversion(dev, NULL); +#else + /* force gain calibration to 1 */ + cs5529_config_write(dev, 0x400000, CSCMD_GAIN_REGISTER); + cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET, + CSCMD_CONFIG_REGISTER); + if (cs5529_wait_for_idle(dev)) + comedi_error(dev, "timeout or signal in init_cs5529()\n"); +#endif +#ifdef NI_CS5529_DEBUG + rt_printk("config: 0x%x\n", cs5529_config_read(dev, + CSCMD_CONFIG_REGISTER)); + rt_printk("gain: 0x%x\n", cs5529_config_read(dev, + CSCMD_GAIN_REGISTER)); + rt_printk("offset: 0x%x\n", cs5529_config_read(dev, + CSCMD_OFFSET_REGISTER)); +#endif + return 0; +} diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c new file mode 100644 index 000000000000..d6357c25aca5 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -0,0 +1,551 @@ +/* + comedi/drivers/ni_mio_cs.c + Hardware driver for NI PCMCIA MIO E series cards + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-2000 David A. Schleef + + 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: ni_mio_cs +Description: National Instruments DAQCard E series +Author: ds +Status: works +Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs), + DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E, DAQCard-6036E +Updated: Thu Oct 23 19:43:17 CDT 2003 + +See the notes in the ni_atmio.o driver. +*/ +/* + The real guts of the driver is in ni_mio_common.c, which is + included by all the E series drivers. + + References for specifications: + + 341080a.pdf DAQCard E Series Register Level Programmer Manual + +*/ + +#include "../comedidev.h" + +#include + +#include "ni_stc.h" +#include "8255.h" + +#include +#include +#include +#include + +#undef DEBUG + +#define ATMIO 1 +#undef PCIMIO + +/* + * AT specific setup + */ + +#define NI_SIZE 0x20 + +#define MAX_N_CALDACS 32 + +static const ni_board ni_boards[] = { + {device_id:0x010d, + name: "DAQCard-ai-16xe-50", + n_adchan:16, + adbits: 16, + ai_fifo_depth:1024, + alwaysdither:0, + gainlkup:ai_gain_8, + ai_speed:5000, + n_aochan:0, + aobits: 0, + ao_fifo_depth:0, + ao_unipolar:0, + num_p0_dio_channels:8, + has_8255:0, + caldac: {dac8800, dac8043}, + }, + {device_id:0x010c, + name: "DAQCard-ai-16e-4", + n_adchan:16, + adbits: 12, + ai_fifo_depth:1024, + alwaysdither:0, + gainlkup:ai_gain_16, + ai_speed:4000, + n_aochan:0, + aobits: 0, + ao_fifo_depth:0, + ao_unipolar:0, + num_p0_dio_channels:8, + has_8255:0, + caldac: {mb88341}, /* verified */ + }, + {device_id:0x02c4, + name: "DAQCard-6062E", + n_adchan:16, + adbits: 12, + ai_fifo_depth:8192, + alwaysdither:0, + gainlkup:ai_gain_16, + ai_speed:2000, + n_aochan:2, + aobits: 12, + ao_fifo_depth:2048, + ao_range_table:&range_bipolar10, + ao_unipolar:0, + ao_speed:1176, + num_p0_dio_channels:8, + has_8255:0, + caldac: {ad8804_debug}, /* verified */ + }, + {device_id:0x075e, + name: "DAQCard-6024E", /* specs incorrect! */ + n_adchan:16, + adbits: 12, + ai_fifo_depth:1024, + alwaysdither:0, + gainlkup:ai_gain_16, + ai_speed:5000, + n_aochan:2, + aobits: 12, + ao_fifo_depth:0, + ao_range_table:&range_bipolar10, + ao_unipolar:0, + ao_speed:1000000, + num_p0_dio_channels:8, + has_8255:0, + caldac: {ad8804_debug}, + }, + {device_id:0x0245, + name: "DAQCard-6036E", /* specs incorrect! */ + n_adchan:16, + adbits: 16, + ai_fifo_depth:1024, + alwaysdither:1, + gainlkup:ai_gain_4, + ai_speed:5000, + n_aochan:2, + aobits: 16, + ao_fifo_depth:0, + ao_range_table:&range_bipolar10, + ao_unipolar:0, + ao_speed:1000000, + num_p0_dio_channels:8, + has_8255:0, + caldac: {ad8804_debug}, + }, +#if 0 + {device_id:0x0000, /* unknown */ + name: "DAQCard-6715", + n_adchan:0, + n_aochan:8, + aobits: 12, + ao_671x: 8192, + num_p0_dio_channels:8, + caldac: {mb88341, mb88341}, + }, +#endif + /* N.B. Update ni_mio_cs_ids[] when entries added above. */ +}; + +#define interrupt_pin(a) 0 + +#define IRQ_POLARITY 1 + +#define NI_E_IRQ_FLAGS IRQF_SHARED + +struct ni_private { + + struct pcmcia_device *link; + + NI_PRIVATE_COMMON}; + +#define devpriv ((struct ni_private *)dev->private) + +/* How we access registers */ + +#define ni_writel(a,b) (outl((a),(b)+dev->iobase)) +#define ni_readl(a) (inl((a)+dev->iobase)) +#define ni_writew(a,b) (outw((a),(b)+dev->iobase)) +#define ni_readw(a) (inw((a)+dev->iobase)) +#define ni_writeb(a,b) (outb((a),(b)+dev->iobase)) +#define ni_readb(a) (inb((a)+dev->iobase)) + +/* How we access windowed registers */ + +/* We automatically take advantage of STC registers that can be + * read/written directly in the I/O space of the board. The + * DAQCard devices map the low 8 STC registers to iobase+addr*2. */ + +static void mio_cs_win_out(struct comedi_device * dev, uint16_t data, int addr) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->window_lock, flags); + if (addr < 8) { + ni_writew(data, addr * 2); + } else { + ni_writew(addr, Window_Address); + ni_writew(data, Window_Data); + } + comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags); +} + +static uint16_t mio_cs_win_in(struct comedi_device * dev, int addr) +{ + unsigned long flags; + uint16_t ret; + + comedi_spin_lock_irqsave(&devpriv->window_lock, flags); + if (addr < 8) { + ret = ni_readw(addr * 2); + } else { + ni_writew(addr, Window_Address); + ret = ni_readw(Window_Data); + } + comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags); + + return ret; +} + +static int mio_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int mio_cs_detach(struct comedi_device * dev); +static struct comedi_driver driver_ni_mio_cs = { + driver_name:"ni_mio_cs", + module:THIS_MODULE, + attach:mio_cs_attach, + detach:mio_cs_detach, +}; + +#include "ni_mio_common.c" + +static int ni_getboardtype(struct comedi_device * dev, struct pcmcia_device *link); + +/* clean up allocated resources */ +/* called when driver is removed */ +static int mio_cs_detach(struct comedi_device * dev) +{ + mio_common_detach(dev); + + /* PCMCIA layer frees the IO region */ + + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + + return 0; +} + +static void mio_cs_config(struct pcmcia_device *link); +static void cs_release(struct pcmcia_device *link); +static void cs_detach(struct pcmcia_device *); + +static struct pcmcia_device *cur_dev = NULL; +static const dev_info_t dev_info = "ni_mio_cs"; +static dev_node_t dev_node = { + "ni_mio_cs", + COMEDI_MAJOR, 0, + NULL +}; +static int cs_attach(struct pcmcia_device *link) +{ + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + link->io.NumPorts1 = 16; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.IntType = INT_MEMORY_AND_IO; + + cur_dev = link; + + mio_cs_config(link); + + return 0; +} + +static void cs_release(struct pcmcia_device *link) +{ + pcmcia_disable_device(link); +} + +static void cs_detach(struct pcmcia_device *link) +{ + DPRINTK("cs_detach(link=%p)\n", link); + + if (link->dev_node) { + cs_release(link); + } +} + +static int mio_cs_suspend(struct pcmcia_device *link) +{ + DPRINTK("pm suspend\n"); + + return 0; +} + +static int mio_cs_resume(struct pcmcia_device *link) +{ + DPRINTK("pm resume\n"); + return 0; +} + +static void mio_cs_config(struct pcmcia_device *link) +{ + tuple_t tuple; + u_short buf[128]; + cisparse_t parse; + int manfid = 0, prodid = 0; + int ret; + + DPRINTK("mio_cs_config(link=%p)\n", link); + + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + + tuple.DesiredTuple = CISTPL_CONFIG; + ret = pcmcia_get_first_tuple(link, &tuple); + ret = pcmcia_get_tuple_data(link, &tuple); + ret = pcmcia_parse_tuple(&tuple, &parse); + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + +#if 0 + tuple.DesiredTuple = CISTPL_LONGLINK_MFC; + tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; + info->multi(first_tuple(link, &tuple, &parse) == 0); +#endif + + tuple.DesiredTuple = CISTPL_MANFID; + tuple.Attributes = TUPLE_RETURN_COMMON; + if ((pcmcia_get_first_tuple(link, &tuple) == 0) && + (pcmcia_get_tuple_data(link, &tuple) == 0)) { + manfid = le16_to_cpu(buf[0]); + prodid = le16_to_cpu(buf[1]); + } + //printk("manfid = 0x%04x, 0x%04x\n",manfid,prodid); + + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple.Attributes = 0; + ret = pcmcia_get_first_tuple(link, &tuple); + ret = pcmcia_get_tuple_data(link, &tuple); + ret = pcmcia_parse_tuple(&tuple, &parse); + +#if 0 + printk(" index: 0x%x\n", parse.cftable_entry.index); + printk(" flags: 0x%x\n", parse.cftable_entry.flags); + printk(" io flags: 0x%x\n", parse.cftable_entry.io.flags); + printk(" io nwin: 0x%x\n", parse.cftable_entry.io.nwin); + printk(" io base: 0x%x\n", parse.cftable_entry.io.win[0].base); + printk(" io len: 0x%x\n", parse.cftable_entry.io.win[0].len); + printk(" irq1: 0x%x\n", parse.cftable_entry.irq.IRQInfo1); + printk(" irq2: 0x%x\n", parse.cftable_entry.irq.IRQInfo2); + printk(" mem flags: 0x%x\n", parse.cftable_entry.mem.flags); + printk(" mem nwin: 0x%x\n", parse.cftable_entry.mem.nwin); + printk(" subtuples: 0x%x\n", parse.cftable_entry.subtuples); +#endif + +#if 0 + link->io.NumPorts1 = 0x20; + link->io.IOAddrLines = 5; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +#endif + link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; + link->io.IOAddrLines = + parse.cftable_entry.io.flags & CISTPL_IO_LINES_MASK; + link->io.NumPorts2 = 0; + + { + int base; + for (base = 0x000; base < 0x400; base += 0x20) { + link->io.BasePort1 = base; + ret = pcmcia_request_io(link, &link->io); + //printk("RequestIO 0x%02x\n",ret); + if (!ret) + break; + } + } + + link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1; + link->irq.IRQInfo2 = parse.cftable_entry.irq.IRQInfo2; + ret = pcmcia_request_irq(link, &link->irq); + if (ret) { + printk("pcmcia_request_irq() returned error: %i\n", ret); + } + //printk("RequestIRQ 0x%02x\n",ret); + + link->conf.ConfigIndex = 1; + + ret = pcmcia_request_configuration(link, &link->conf); + //printk("RequestConfiguration %d\n",ret); + + link->dev_node = &dev_node; +} + +static int mio_cs_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct pcmcia_device *link; + unsigned int irq; + int ret; + + DPRINTK("mio_cs_attach(dev=%p,it=%p)\n", dev, it); + + link = cur_dev; /* XXX hack */ + if (!link) + return -EIO; + + dev->driver = &driver_ni_mio_cs; + dev->iobase = link->io.BasePort1; + + irq = link->irq.AssignedIRQ; + + printk("comedi%d: %s: DAQCard: io 0x%04lx, irq %u, ", + dev->minor, dev->driver->driver_name, dev->iobase, irq); + +#if 0 + { + int i; + + printk(" board fingerprint:"); + for (i = 0; i < 32; i += 2) { + printk(" %04x %02x", inw(dev->iobase + i), + inb(dev->iobase + i + 1)); + } + printk("\n"); + printk(" board fingerprint (windowed):"); + for (i = 0; i < 10; i++) { + printk(" 0x%04x", win_in(i)); + } + printk("\n"); + } +#endif + + dev->board_ptr = ni_boards + ni_getboardtype(dev, link); + + printk(" %s", boardtype.name); + dev->board_name = boardtype.name; + + if ((ret = comedi_request_irq(irq, ni_E_interrupt, NI_E_IRQ_FLAGS, + "ni_mio_cs", dev)) < 0) { + printk(" irq not available\n"); + return -EINVAL; + } + dev->irq = irq; + + /* allocate private area */ + if ((ret = ni_alloc_private(dev)) < 0) + return ret; + devpriv->stc_writew = &mio_cs_win_out; + devpriv->stc_readw = &mio_cs_win_in; + devpriv->stc_writel = &win_out2; + devpriv->stc_readl = &win_in2; + + if ((ret = ni_E_init(dev, it)) < 0) { + return ret; + } + + return 0; +} + +static int get_prodid(struct comedi_device * dev, struct pcmcia_device *link) +{ + tuple_t tuple; + u_short buf[128]; + int prodid = 0; + + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.DesiredTuple = CISTPL_MANFID; + tuple.Attributes = TUPLE_RETURN_COMMON; + if ((pcmcia_get_first_tuple(link, &tuple) == 0) && + (pcmcia_get_tuple_data(link, &tuple) == 0)) { + prodid = le16_to_cpu(buf[1]); + } + + return prodid; +} + +static int ni_getboardtype(struct comedi_device * dev, struct pcmcia_device *link) +{ + int id; + int i; + + id = get_prodid(dev, link); + + for (i = 0; i < n_ni_boards; i++) { + if (ni_boards[i].device_id == id) { + return i; + } + } + + printk("unknown board 0x%04x -- pretend it is a ", id); + + return 0; +} + +#ifdef MODULE + +MODULE_LICENSE("GPL"); + +static struct pcmcia_device_id ni_mio_cs_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010d), /* DAQCard-ai-16xe-50 */ + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010c), /* DAQCard-ai-16e-4 */ + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x02c4), /* DAQCard-6062E */ + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x075e), /* DAQCard-6024E */ + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0245), /* DAQCard-6036E */ + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, ni_mio_cs_ids); + +struct pcmcia_driver ni_mio_cs_driver = { + .probe = &cs_attach, + .remove = &cs_detach, + .suspend = &mio_cs_suspend, + .resume = &mio_cs_resume, + .id_table = ni_mio_cs_ids, + .owner = THIS_MODULE, + .drv = { + .name = dev_info, + }, +}; + +int init_module(void) +{ + pcmcia_register_driver(&ni_mio_cs_driver); + comedi_driver_register(&driver_ni_mio_cs); + return 0; +} + +void cleanup_module(void) +{ + pcmcia_unregister_driver(&ni_mio_cs_driver); +#if 0 + while (cur_dev != NULL) + cs_detach(cur_dev->handle); +#endif + comedi_driver_unregister(&driver_ni_mio_cs); +} +#endif diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c new file mode 100644 index 000000000000..87def2cc9a29 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -0,0 +1,1302 @@ +/* + comedi/drivers/ni_pcidio.c + driver for National Instruments PCI-DIO-96/PCI-6508 + National Instruments PCI-DIO-32HS + National Instruments PCI-6503 + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999,2002 David A. Schleef + + 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: ni_pcidio +Description: National Instruments PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 +Author: ds +Status: works +Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio), PXI-6533, + PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X, + PXI-6503, PCI-6533, PCI-6534 +Updated: Sun, 21 Apr 2002 21:03:38 -0700 + +The DIO-96 appears as four 8255 subdevices. See the 8255 +driver notes for details. + +The DIO32HS board appears as one subdevice, with 32 channels. +Each channel is individually I/O configurable. The channel order +is 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0. The driver only +supports simple digital I/O; no handshaking is supported. + +DMA mostly works for the PCI-DIO32HS, but only in timed input mode. + +This driver could be easily modified to support AT-MIO32HS and +AT-MIO96. + +The PCI-6534 requires a firmware upload after power-up to work, the +firmware data and instructions for loading it with comedi_config +it are contained in the +comedi_nonfree_firmware tarball available from http://www.comedi.org +*/ + +/* + This driver is for both the NI PCI-DIO-32HS and the PCI-DIO-96, + which have very different architectures. But, since the '96 is + so simple, it is included here. + + Manuals (available from ftp://ftp.natinst.com/support/manuals) + + 320938c.pdf PCI-DIO-96/PXI-6508/PCI-6503 User Manual + 321464b.pdf AT/PCI-DIO-32HS User Manual + 341329A.pdf PCI-6533 Register-Level Programmer Manual + 341330A.pdf DAQ-DIO Technical Reference Manual + + */ + +#define USE_DMA +//#define DEBUG 1 +//#define DEBUG_FLAGS + +#include "../comedidev.h" + +#include "mite.h" +#include "8255.h" + +#undef DPRINTK +#ifdef DEBUG +#define DPRINTK(format, args...) printk(format, ## args) +#else +#define DPRINTK(format, args...) +#endif + +#define PCI_VENDOR_ID_NATINST 0x1093 + +#define PCI_DIO_SIZE 4096 +#define PCI_MITE_SIZE 4096 + +/* defines for the PCI-DIO-96 */ + +#define NIDIO_8255_BASE(x) ((x)*4) +#define NIDIO_A 0 +#define NIDIO_B 4 +#define NIDIO_C 8 +#define NIDIO_D 12 + +/* defines for the PCI-DIO-32HS */ + +#define Window_Address 4 /* W */ +#define Interrupt_And_Window_Status 4 /* R */ +#define IntStatus1 (1<<0) +#define IntStatus2 (1<<1) +#define WindowAddressStatus_mask 0x7c + +#define Master_DMA_And_Interrupt_Control 5 /* W */ +#define InterruptLine(x) ((x)&3) +#define OpenInt (1<<2) +#define Group_Status 5 /* R */ +#define DataLeft (1<<0) +#define Req (1<<2) +#define StopTrig (1<<3) + +#define Group_1_Flags 6 /* R */ +#define Group_2_Flags 7 /* R */ +#define TransferReady (1<<0) +#define CountExpired (1<<1) +#define Waited (1<<5) +#define PrimaryTC (1<<6) +#define SecondaryTC (1<<7) + //#define SerialRose + //#define ReqRose + //#define Paused + +#define Group_1_First_Clear 6 /* W */ +#define Group_2_First_Clear 7 /* W */ +#define ClearWaited (1<<3) +#define ClearPrimaryTC (1<<4) +#define ClearSecondaryTC (1<<5) +#define DMAReset (1<<6) +#define FIFOReset (1<<7) +#define ClearAll 0xf8 + +#define Group_1_FIFO 8 /* W */ +#define Group_2_FIFO 12 /* W */ + +#define Transfer_Count 20 +#define Chip_ID_D 24 +#define Chip_ID_I 25 +#define Chip_ID_O 26 +#define Chip_Version 27 +#define Port_IO(x) (28+(x)) +#define Port_Pin_Directions(x) (32+(x)) +#define Port_Pin_Mask(x) (36+(x)) +#define Port_Pin_Polarities(x) (40+(x)) + +#define Master_Clock_Routing 45 +#define RTSIClocking(x) (((x)&3)<<4) + +#define Group_1_Second_Clear 46 /* W */ +#define Group_2_Second_Clear 47 /* W */ +#define ClearExpired (1<<0) + +#define Port_Pattern(x) (48+(x)) + +#define Data_Path 64 +#define FIFOEnableA (1<<0) +#define FIFOEnableB (1<<1) +#define FIFOEnableC (1<<2) +#define FIFOEnableD (1<<3) +#define Funneling(x) (((x)&3)<<4) +#define GroupDirection (1<<7) + +#define Protocol_Register_1 65 +#define OpMode Protocol_Register_1 +#define RunMode(x) ((x)&7) +#define Numbered (1<<3) + +#define Protocol_Register_2 66 +#define ClockReg Protocol_Register_2 +#define ClockLine(x) (((x)&3)<<5) +#define InvertStopTrig (1<<7) +#define DataLatching(x) (((x)&3)<<5) + +#define Protocol_Register_3 67 +#define Sequence Protocol_Register_3 + +#define Protocol_Register_14 68 /* 16 bit */ +#define ClockSpeed Protocol_Register_14 + +#define Protocol_Register_4 70 +#define ReqReg Protocol_Register_4 +#define ReqConditioning(x) (((x)&7)<<3) + +#define Protocol_Register_5 71 +#define BlockMode Protocol_Register_5 + +#define FIFO_Control 72 +#define ReadyLevel(x) ((x)&7) + +#define Protocol_Register_6 73 +#define LinePolarities Protocol_Register_6 +#define InvertAck (1<<0) +#define InvertReq (1<<1) +#define InvertClock (1<<2) +#define InvertSerial (1<<3) +#define OpenAck (1<<4) +#define OpenClock (1<<5) + +#define Protocol_Register_7 74 +#define AckSer Protocol_Register_7 +#define AckLine(x) (((x)&3)<<2) +#define ExchangePins (1<<7) + +#define Interrupt_Control 75 + /* bits same as flags */ + +#define DMA_Line_Control_Group1 76 +#define DMA_Line_Control_Group2 108 +// channel zero is none +static inline unsigned primary_DMAChannel_bits(unsigned channel) +{ + return channel & 0x3; +} +static inline unsigned secondary_DMAChannel_bits(unsigned channel) +{ + return (channel << 2) & 0xc; +} + +#define Transfer_Size_Control 77 +#define TransferWidth(x) ((x)&3) +#define TransferLength(x) (((x)&3)<<3) +#define RequireRLevel (1<<5) + +#define Protocol_Register_15 79 +#define DAQOptions Protocol_Register_15 +#define StartSource(x) ((x)&0x3) +#define InvertStart (1<<2) +#define StopSource(x) (((x)&0x3)<<3) +#define ReqStart (1<<6) +#define PreStart (1<<7) + +#define Pattern_Detection 81 +#define DetectionMethod (1<<0) +#define InvertMatch (1<<1) +#define IE_Pattern_Detection (1<<2) + +#define Protocol_Register_9 82 +#define ReqDelay Protocol_Register_9 + +#define Protocol_Register_10 83 +#define ReqNotDelay Protocol_Register_10 + +#define Protocol_Register_11 84 +#define AckDelay Protocol_Register_11 + +#define Protocol_Register_12 85 +#define AckNotDelay Protocol_Register_12 + +#define Protocol_Register_13 86 +#define Data1Delay Protocol_Register_13 + +#define Protocol_Register_8 88 /* 32 bit */ +#define StartDelay Protocol_Register_8 + +enum pci_6534_firmware_registers { /* 16 bit */ + Firmware_Control_Register = 0x100, + Firmware_Status_Register = 0x104, + Firmware_Data_Register = 0x108, + Firmware_Mask_Register = 0x10c, + Firmware_Debug_Register = 0x110, +}; +/* main fpga registers (32 bit)*/ +enum pci_6534_fpga_registers { + FPGA_Control1_Register = 0x200, + FPGA_Control2_Register = 0x204, + FPGA_Irq_Mask_Register = 0x208, + FPGA_Status_Register = 0x20c, + FPGA_Signature_Register = 0x210, + FPGA_SCALS_Counter_Register = 0x280, /*write-clear */ + FPGA_SCAMS_Counter_Register = 0x284, /*write-clear */ + FPGA_SCBLS_Counter_Register = 0x288, /*write-clear */ + FPGA_SCBMS_Counter_Register = 0x28c, /*write-clear */ + FPGA_Temp_Control_Register = 0x2a0, + FPGA_DAR_Register = 0x2a8, + FPGA_ELC_Read_Register = 0x2b8, + FPGA_ELC_Write_Register = 0x2bc, +}; +enum FPGA_Control_Bits { + FPGA_Enable_Bit = 0x8000, +}; + +#define TIMER_BASE 50 /* nanoseconds */ + +#ifdef USE_DMA +#define IntEn (CountExpired|Waited|PrimaryTC|SecondaryTC) +#else +#define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC) +#endif + +static int nidio_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int nidio_detach(struct comedi_device * dev); +static int ni_pcidio_cancel(struct comedi_device * dev, struct comedi_subdevice * s); + +static struct comedi_driver driver_pcidio = { + driver_name:"ni_pcidio", + module:THIS_MODULE, + attach:nidio_attach, + detach:nidio_detach, +}; + +struct nidio_board { + + int dev_id; + const char *name; + int n_8255; + unsigned int is_diodaq:1; + unsigned int uses_firmware:1; +}; + +static const struct nidio_board nidio_boards[] = { + { + dev_id: 0x1150, + name: "pci-dio-32hs", + n_8255: 0, + is_diodaq:1, + }, + { + dev_id: 0x1320, + name: "pxi-6533", + n_8255: 0, + is_diodaq:1, + }, + { + dev_id: 0x12b0, + name: "pci-6534", + n_8255: 0, + is_diodaq:1, + uses_firmware:1, + }, + { + dev_id: 0x0160, + name: "pci-dio-96", + n_8255: 4, + is_diodaq:0, + }, + { + dev_id: 0x1630, + name: "pci-dio-96b", + n_8255: 4, + is_diodaq:0, + }, + { + dev_id: 0x13c0, + name: "pxi-6508", + n_8255: 4, + is_diodaq:0, + }, + { + dev_id: 0x0400, + name: "pci-6503", + n_8255: 1, + is_diodaq:0, + }, + { + dev_id: 0x1250, + name: "pci-6503b", + n_8255: 1, + is_diodaq:0, + }, + { + dev_id: 0x17d0, + name: "pci-6503x", + n_8255: 1, + is_diodaq:0, + }, + { + dev_id: 0x1800, + name: "pxi-6503", + n_8255: 1, + is_diodaq:0, + }, +}; + +#define n_nidio_boards (sizeof(nidio_boards)/sizeof(nidio_boards[0])) +#define this_board ((const struct nidio_board *)dev->board_ptr) + +static DEFINE_PCI_DEVICE_TABLE(ni_pcidio_pci_table) = { + {PCI_VENDOR_ID_NATINST, 0x1150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x12b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x0160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1630, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x13c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x0400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x17d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table); + +struct nidio96_private { + struct mite_struct *mite; + int boardtype; + int dio; + unsigned short OpModeBits; + struct mite_channel *di_mite_chan; + struct mite_dma_descriptor_ring *di_mite_ring; + spinlock_t mite_channel_lock; +}; +#define devpriv ((struct nidio96_private *)dev->private) + +static int ni_pcidio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int ni_pcidio_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int ni_pcidio_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum); +static int nidio_find_device(struct comedi_device * dev, int bus, int slot); +static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode); +static int setup_mite_dma(struct comedi_device * dev, struct comedi_subdevice * s); + +#ifdef DEBUG_FLAGS +static void ni_pcidio_print_flags(unsigned int flags); +static void ni_pcidio_print_status(unsigned int status); +#else +#define ni_pcidio_print_flags(x) +#define ni_pcidio_print_status(x) +#endif + +static int ni_pcidio_request_di_mite_channel(struct comedi_device * dev) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + BUG_ON(devpriv->di_mite_chan); + devpriv->di_mite_chan = + mite_request_channel_in_range(devpriv->mite, + devpriv->di_mite_ring, 1, 2); + if (devpriv->di_mite_chan == NULL) { + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, + flags); + comedi_error(dev, "failed to reserve mite dma channel."); + return -EBUSY; + } + writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) | + secondary_DMAChannel_bits(devpriv->di_mite_chan->channel), + devpriv->mite->daq_io_addr + DMA_Line_Control_Group1); + mmiowb(); + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); + return 0; +} + +static void ni_pcidio_release_di_mite_channel(struct comedi_device * dev) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, flags); + if (devpriv->di_mite_chan) { + mite_dma_disarm(devpriv->di_mite_chan); + mite_dma_reset(devpriv->di_mite_chan); + mite_release_channel(devpriv->di_mite_chan); + devpriv->di_mite_chan = NULL; + writeb(primary_DMAChannel_bits(0) | + secondary_DMAChannel_bits(0), + devpriv->mite->daq_io_addr + DMA_Line_Control_Group1); + mmiowb(); + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); +} + +static int nidio96_8255_cb(int dir, int port, int data, unsigned long iobase) +{ + if (dir) { + writeb(data, (void *)(iobase + port)); + return 0; + } else { + return readb((void *)(iobase + port)); + } +} + +void ni_pcidio_event(struct comedi_device * dev, struct comedi_subdevice * s) +{ + if (s->async-> + events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) + { + ni_pcidio_cancel(dev, s); + } + comedi_event(dev, s); +} + +static irqreturn_t nidio_interrupt(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices; + struct comedi_async *async = s->async; + struct mite_struct *mite = devpriv->mite; + + //int i, j; + long int AuxData = 0; + short data1 = 0; + short data2 = 0; + int flags; + int status; + int work = 0; + unsigned int m_status = 0; + unsigned long irq_flags; + + //interrupcions parasites + if (dev->attached == 0) { + // assume it's from another card + return IRQ_NONE; + } + + status = readb(devpriv->mite->daq_io_addr + + Interrupt_And_Window_Status); + flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); + + DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x\n", + status, flags); + ni_pcidio_print_flags(flags); + ni_pcidio_print_status(status); + + //printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); + //printk("buf[4096]=%08x\n",*(unsigned int *)(async->prealloc_buf+4096)); + + comedi_spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags); + if (devpriv->di_mite_chan) + m_status = mite_get_status(devpriv->di_mite_chan); +#ifdef MITE_DEBUG + mite_print_chsr(m_status); +#endif + //printk("mite_bytes_transferred: %d\n",mite_bytes_transferred(mite,DI_DMA_CHAN)); + //mite_dump_regs(mite); + if (m_status & CHSR_INT) { + if (m_status & CHSR_LINKC) { + writel(CHOR_CLRLC, + mite->mite_io_addr + + MITE_CHOR(devpriv->di_mite_chan->channel)); + mite_sync_input_dma(devpriv->di_mite_chan, s->async); + /* XXX need to byteswap */ + } + if (m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY | + CHSR_DRQ1 | CHSR_MRDY)) { + DPRINTK("unknown mite interrupt, disabling IRQ\n"); + async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + disable_irq(dev->irq); + } + } + comedi_spin_unlock_irqrestore(&devpriv->mite_channel_lock, irq_flags); + + while (status & DataLeft) { + work++; + if (work > 20) { + DPRINTK("too much work in interrupt\n"); + writeb(0x00, + devpriv->mite->daq_io_addr + + Master_DMA_And_Interrupt_Control); + break; + } + + flags &= IntEn; + + if (flags & TransferReady) { + //DPRINTK("TransferReady\n"); + while (flags & TransferReady) { + work++; + if (work > 100) { + DPRINTK("too much work in interrupt\n"); + writeb(0x00, + devpriv->mite->daq_io_addr + + Master_DMA_And_Interrupt_Control); + goto out; + } + AuxData = + readl(devpriv->mite->daq_io_addr + + Group_1_FIFO); + data1 = AuxData & 0xffff; + data2 = (AuxData & 0xffff0000) >> 16; + comedi_buf_put(async, data1); + comedi_buf_put(async, data2); + //DPRINTK("read:%d, %d\n",data1,data2); + flags = readb(devpriv->mite->daq_io_addr + + Group_1_Flags); + } + //DPRINTK("buf_int_count: %d\n",async->buf_int_count); + //DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",IntEn,flags,status); + //ni_pcidio_print_flags(flags); + //ni_pcidio_print_status(status); + async->events |= COMEDI_CB_BLOCK; + } + + if (flags & CountExpired) { + DPRINTK("CountExpired\n"); + writeb(ClearExpired, + devpriv->mite->daq_io_addr + + Group_1_Second_Clear); + async->events |= COMEDI_CB_EOA; + + writeb(0x00, devpriv->mite->daq_io_addr + OpMode); + break; + } else if (flags & Waited) { + DPRINTK("Waited\n"); + writeb(ClearWaited, + devpriv->mite->daq_io_addr + + Group_1_First_Clear); + async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + break; + } else if (flags & PrimaryTC) { + DPRINTK("PrimaryTC\n"); + writeb(ClearPrimaryTC, + devpriv->mite->daq_io_addr + + Group_1_First_Clear); + async->events |= COMEDI_CB_EOA; + } else if (flags & SecondaryTC) { + DPRINTK("SecondaryTC\n"); + writeb(ClearSecondaryTC, + devpriv->mite->daq_io_addr + + Group_1_First_Clear); + async->events |= COMEDI_CB_EOA; + } +#if 0 + else { + printk("ni_pcidio: unknown interrupt\n"); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + writeb(0x00, + devpriv->mite->daq_io_addr + + Master_DMA_And_Interrupt_Control); + } +#endif + flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); + status = readb(devpriv->mite->daq_io_addr + + Interrupt_And_Window_Status); + //DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,status=0x%02x\n", + // IntEn,flags,status); + //ni_pcidio_print_flags(flags); + //ni_pcidio_print_status(status); + } + + out: + ni_pcidio_event(dev, s); +#if 0 + if (!tag) { + writeb(0x03, + devpriv->mite->daq_io_addr + + Master_DMA_And_Interrupt_Control); + } +#endif + return IRQ_HANDLED; +} + +#ifdef DEBUG_FLAGS +static const char *const flags_strings[] = { + "TransferReady", "CountExpired", "2", "3", + "4", "Waited", "PrimaryTC", "SecondaryTC", +}; +static void ni_pcidio_print_flags(unsigned int flags) +{ + int i; + + printk("group_1_flags:"); + for (i = 7; i >= 0; i--) { + if (flags & (1 << i)) { + printk(" %s", flags_strings[i]); + } + } + printk("\n"); +} +static char *status_strings[] = { + "DataLeft1", "Reserved1", "Req1", "StopTrig1", + "DataLeft2", "Reserved2", "Req2", "StopTrig2", +}; +static void ni_pcidio_print_status(unsigned int flags) +{ + int i; + + printk("group_status:"); + for (i = 7; i >= 0; i--) { + if (flags & (1 << i)) { + printk(" %s", status_strings[i]); + } + } + printk("\n"); +} +#endif + +#ifdef unused +static void debug_int(struct comedi_device * dev) +{ + int a, b; + static int n_int = 0; + struct timeval tv; + + do_gettimeofday(&tv); + a = readb(devpriv->mite->daq_io_addr + Group_Status); + b = readb(devpriv->mite->daq_io_addr + Group_1_Flags); + + if (n_int < 10) { + DPRINTK("status 0x%02x flags 0x%02x time %06d\n", a, b, + (int)tv.tv_usec); + } + + while (b & 1) { + writew(0xff, devpriv->mite->daq_io_addr + Group_1_FIFO); + b = readb(devpriv->mite->daq_io_addr + Group_1_Flags); + } + + b = readb(devpriv->mite->daq_io_addr + Group_1_Flags); + + if (n_int < 10) { + DPRINTK("new status 0x%02x\n", b); + n_int++; + } +} +#endif + +static int ni_pcidio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 1) + return -EINVAL; + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= 1 << CR_CHAN(insn->chanspec); + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~(1 << CR_CHAN(insn->chanspec)); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s->io_bits & (1 << CR_CHAN(insn-> + chanspec))) ? COMEDI_OUTPUT : + COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + } + writel(s->io_bits, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); + + return 1; +} + +static int ni_pcidio_insn_bits(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]); + writel(s->state, devpriv->mite->daq_io_addr + Port_IO(0)); + } + data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0)); + + return 2; +} + +static int ni_pcidio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= TRIG_NOW | TRIG_INT; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT) + err++; + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + /* same for both TRIG_INT and TRIG_NOW */ + cmd->start_arg = 0; + err++; + } +#define MAX_SPEED (TIMER_BASE) /* in nanoseconds */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < MAX_SPEED) { + cmd->scan_begin_arg = MAX_SPEED; + err++; + } + /* no minumum speed */ + } else { + /* TRIG_EXT */ + /* should be level/edge, hi/lo specification here */ + 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 != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + /* no limit */ + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + ni_pcidio_ns_to_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + + if (err) + return 4; + + return 0; +} + +static int ni_pcidio_ns_to_timer(int *nanosec, int round_mode) +{ + int divider, base; + + base = TIMER_BASE; + + switch (round_mode) { + case TRIG_ROUND_NEAREST: + default: + divider = (*nanosec + base / 2) / base; + break; + case TRIG_ROUND_DOWN: + divider = (*nanosec) / base; + break; + case TRIG_ROUND_UP: + divider = (*nanosec + base - 1) / base; + break; + } + + *nanosec = base * divider; + return divider; +} + +static int ni_pcidio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + + /* XXX configure ports for input */ + writel(0x0000, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); + + if (1) { + /* enable fifos A B C D */ + writeb(0x0f, devpriv->mite->daq_io_addr + Data_Path); + + /* set transfer width a 32 bits */ + writeb(TransferWidth(0) | TransferLength(0), + devpriv->mite->daq_io_addr + Transfer_Size_Control); + } else { + writeb(0x03, devpriv->mite->daq_io_addr + Data_Path); + writeb(TransferWidth(3) | TransferLength(0), + devpriv->mite->daq_io_addr + Transfer_Size_Control); + } + + /* protocol configuration */ + if (cmd->scan_begin_src == TRIG_TIMER) { + /* page 4-5, "input with internal REQs" */ + writeb(0, devpriv->mite->daq_io_addr + OpMode); + writeb(0x00, devpriv->mite->daq_io_addr + ClockReg); + writeb(1, devpriv->mite->daq_io_addr + Sequence); + writeb(0x04, devpriv->mite->daq_io_addr + ReqReg); + writeb(4, devpriv->mite->daq_io_addr + BlockMode); + writeb(3, devpriv->mite->daq_io_addr + LinePolarities); + writeb(0xc0, devpriv->mite->daq_io_addr + AckSer); + writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg, + TRIG_ROUND_NEAREST), + devpriv->mite->daq_io_addr + StartDelay); + writeb(1, devpriv->mite->daq_io_addr + ReqDelay); + writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay); + writeb(1, devpriv->mite->daq_io_addr + AckDelay); + writeb(0x0b, devpriv->mite->daq_io_addr + AckNotDelay); + writeb(0x01, devpriv->mite->daq_io_addr + Data1Delay); + /* manual, page 4-5: ClockSpeed comment is incorrectly listed + * on DAQOptions */ + writew(0, devpriv->mite->daq_io_addr + ClockSpeed); + writeb(0, devpriv->mite->daq_io_addr + DAQOptions); + } else { + /* TRIG_EXT */ + /* page 4-5, "input with external REQs" */ + writeb(0, devpriv->mite->daq_io_addr + OpMode); + writeb(0x00, devpriv->mite->daq_io_addr + ClockReg); + writeb(0, devpriv->mite->daq_io_addr + Sequence); + writeb(0x00, devpriv->mite->daq_io_addr + ReqReg); + writeb(4, devpriv->mite->daq_io_addr + BlockMode); + writeb(0, devpriv->mite->daq_io_addr + LinePolarities); + writeb(0x00, devpriv->mite->daq_io_addr + AckSer); + writel(1, devpriv->mite->daq_io_addr + StartDelay); + writeb(1, devpriv->mite->daq_io_addr + ReqDelay); + writeb(1, devpriv->mite->daq_io_addr + ReqNotDelay); + writeb(1, devpriv->mite->daq_io_addr + AckDelay); + writeb(0x0C, devpriv->mite->daq_io_addr + AckNotDelay); + writeb(0x10, devpriv->mite->daq_io_addr + Data1Delay); + writew(0, devpriv->mite->daq_io_addr + ClockSpeed); + writeb(0x60, devpriv->mite->daq_io_addr + DAQOptions); + } + + if (cmd->stop_src == TRIG_COUNT) { + writel(cmd->stop_arg, + devpriv->mite->daq_io_addr + Transfer_Count); + } else { + /* XXX */ + } + +#ifdef USE_DMA + writeb(ClearPrimaryTC | ClearSecondaryTC, + devpriv->mite->daq_io_addr + Group_1_First_Clear); + + { + int retval = setup_mite_dma(dev, s); + if (retval) + return retval; + } +#else + writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group1); +#endif + writeb(0x00, devpriv->mite->daq_io_addr + DMA_Line_Control_Group2); + + /* clear and enable interrupts */ + writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear); + //writeb(ClearExpired,devpriv->mite->daq_io_addr+Group_1_Second_Clear); + + writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control); + writeb(0x03, + devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); + + if (cmd->stop_src == TRIG_NONE) { + devpriv->OpModeBits = DataLatching(0) | RunMode(7); + } else { // TRIG_TIMER + devpriv->OpModeBits = Numbered | RunMode(7); + } + if (cmd->start_src == TRIG_NOW) { + /* start */ + writeb(devpriv->OpModeBits, + devpriv->mite->daq_io_addr + OpMode); + s->async->inttrig = NULL; + } else { + /* TRIG_INT */ + s->async->inttrig = ni_pcidio_inttrig; + } + + DPRINTK("ni_pcidio: command started\n"); + return 0; +} + +static int setup_mite_dma(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int retval; + + retval = ni_pcidio_request_di_mite_channel(dev); + if (retval) + return retval; + + devpriv->di_mite_chan->dir = COMEDI_INPUT; + + mite_prep_dma(devpriv->di_mite_chan, 32, 32); + + mite_dma_arm(devpriv->di_mite_chan); + return 0; +} + +static int ni_pcidio_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ + if (trignum != 0) + return -EINVAL; + + writeb(devpriv->OpModeBits, devpriv->mite->daq_io_addr + OpMode); + s->async->inttrig = NULL; + + return 1; +} + +static int ni_pcidio_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + writeb(0x00, + devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); + ni_pcidio_release_di_mite_channel(dev); + + return 0; +} + +static int ni_pcidio_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size) +{ + int ret; + + ret = mite_buf_change(devpriv->di_mite_ring, s->async); + if (ret < 0) + return ret; + + memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz); + + return 0; +} + +static int pci_6534_load_fpga(struct comedi_device * dev, int fpga_index, u8 * data, + int data_len) +{ + static const int timeout = 1000; + int i, j; + writew(0x80 | fpga_index, + devpriv->mite->daq_io_addr + Firmware_Control_Register); + writew(0xc0 | fpga_index, + devpriv->mite->daq_io_addr + Firmware_Control_Register); + for (i = 0; + (readw(devpriv->mite->daq_io_addr + + Firmware_Status_Register) & 0x2) == 0 + && i < timeout; ++i) { + udelay(1); + } + if (i == timeout) { + printk("ni_pcidio: failed to load fpga %i, waiting for status 0x2\n", fpga_index); + return -EIO; + } + writew(0x80 | fpga_index, + devpriv->mite->daq_io_addr + Firmware_Control_Register); + for (i = 0; + readw(devpriv->mite->daq_io_addr + Firmware_Status_Register) != + 0x3 && i < timeout; ++i) { + udelay(1); + } + if (i == timeout) { + printk("ni_pcidio: failed to load fpga %i, waiting for status 0x3\n", fpga_index); + return -EIO; + } + for (j = 0; j + 1 < data_len;) { + unsigned int value = data[j++]; + value |= data[j++] << 8; + writew(value, + devpriv->mite->daq_io_addr + Firmware_Data_Register); + for (i = 0; + (readw(devpriv->mite->daq_io_addr + + Firmware_Status_Register) & 0x2) == 0 + && i < timeout; ++i) { + udelay(1); + } + if (i == timeout) { + printk("ni_pcidio: failed to load word into fpga %i\n", + fpga_index); + return -EIO; + } + if (need_resched()) + schedule(); + } + writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register); + return 0; +} + +static int pci_6534_reset_fpga(struct comedi_device * dev, int fpga_index) +{ + return pci_6534_load_fpga(dev, fpga_index, NULL, 0); +} + +static int pci_6534_reset_fpgas(struct comedi_device * dev) +{ + int ret; + int i; + writew(0x0, devpriv->mite->daq_io_addr + Firmware_Control_Register); + for (i = 0; i < 3; ++i) { + ret = pci_6534_reset_fpga(dev, i); + if (ret < 0) + break; + } + writew(0x0, devpriv->mite->daq_io_addr + Firmware_Mask_Register); + return ret; +} + +static void pci_6534_init_main_fpga(struct comedi_device * dev) +{ + writel(0, devpriv->mite->daq_io_addr + FPGA_Control1_Register); + writel(0, devpriv->mite->daq_io_addr + FPGA_Control2_Register); + writel(0, devpriv->mite->daq_io_addr + FPGA_SCALS_Counter_Register); + writel(0, devpriv->mite->daq_io_addr + FPGA_SCAMS_Counter_Register); + writel(0, devpriv->mite->daq_io_addr + FPGA_SCBLS_Counter_Register); + writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register); +} + +static int pci_6534_upload_firmware(struct comedi_device * dev, int options[]) +{ + int ret; + void *main_fpga_data, *scarab_a_data, *scarab_b_data; + int main_fpga_data_len, scarab_a_data_len, scarab_b_data_len; + + if (options[COMEDI_DEVCONF_AUX_DATA_LENGTH] == 0) + return 0; + ret = pci_6534_reset_fpgas(dev); + if (ret < 0) + return ret; + main_fpga_data = comedi_aux_data(options, 0); + main_fpga_data_len = options[COMEDI_DEVCONF_AUX_DATA0_LENGTH]; + ret = pci_6534_load_fpga(dev, 2, main_fpga_data, main_fpga_data_len); + if (ret < 0) + return ret; + pci_6534_init_main_fpga(dev); + scarab_a_data = comedi_aux_data(options, 1); + scarab_a_data_len = options[COMEDI_DEVCONF_AUX_DATA1_LENGTH]; + ret = pci_6534_load_fpga(dev, 0, scarab_a_data, scarab_a_data_len); + if (ret < 0) + return ret; + scarab_b_data = comedi_aux_data(options, 2); + scarab_b_data_len = options[COMEDI_DEVCONF_AUX_DATA2_LENGTH]; + ret = pci_6534_load_fpga(dev, 1, scarab_b_data, scarab_b_data_len); + if (ret < 0) + return ret; + return 0; +} + +static int nidio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int i; + int ret; + int n_subdevices; + unsigned int irq; + + printk("comedi%d: nidio:", dev->minor); + + if ((ret = alloc_private(dev, sizeof(struct nidio96_private))) < 0) + return ret; + spin_lock_init(&devpriv->mite_channel_lock); + + ret = nidio_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; + + ret = mite_setup(devpriv->mite); + if (ret < 0) { + printk("error setting up mite\n"); + return ret; + } + comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev); + devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite); + if (devpriv->di_mite_ring == NULL) + return -ENOMEM; + + dev->board_name = this_board->name; + irq = mite_irq(devpriv->mite); + printk(" %s", dev->board_name); + if (this_board->uses_firmware) { + ret = pci_6534_upload_firmware(dev, it->options); + if (ret < 0) + return ret; + } + if (!this_board->is_diodaq) { + n_subdevices = this_board->n_8255; + } else { + n_subdevices = 1; + } + if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) + return ret; + + if (!this_board->is_diodaq) { + for (i = 0; i < this_board->n_8255; i++) { + subdev_8255_init(dev, dev->subdevices + i, + nidio96_8255_cb, + (unsigned long)(devpriv->mite->daq_io_addr + + NIDIO_8255_BASE(i))); + } + } else { + + printk(" rev=%d", + readb(devpriv->mite->daq_io_addr + Chip_Version)); + + s = dev->subdevices + 0; + + dev->read_subdev = s; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = + SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED | + SDF_CMD_READ; + s->n_chan = 32; + s->range_table = &range_digital; + s->maxdata = 1; + s->insn_config = &ni_pcidio_insn_config; + s->insn_bits = &ni_pcidio_insn_bits; + s->do_cmd = &ni_pcidio_cmd; + s->do_cmdtest = &ni_pcidio_cmdtest; + s->cancel = &ni_pcidio_cancel; + s->len_chanlist = 32; /* XXX */ + s->buf_change = &ni_pcidio_change; + s->async_dma_dir = DMA_BIDIRECTIONAL; + + writel(0, devpriv->mite->daq_io_addr + Port_IO(0)); + writel(0, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); + writel(0, devpriv->mite->daq_io_addr + Port_Pin_Mask(0)); + + /* disable interrupts on board */ + writeb(0x00, + devpriv->mite->daq_io_addr + + Master_DMA_And_Interrupt_Control); + + ret = comedi_request_irq(irq, nidio_interrupt, IRQF_SHARED, + "ni_pcidio", dev); + if (ret < 0) { + printk(" irq not available"); + } + dev->irq = irq; + } + + printk("\n"); + + return 0; +} + +static int nidio_detach(struct comedi_device * dev) +{ + int i; + + if (this_board && !this_board->is_diodaq) { + for (i = 0; i < this_board->n_8255; i++) { + subdev_8255_cleanup(dev, dev->subdevices + i); + } + } + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + if (devpriv) { + if (devpriv->di_mite_ring) { + mite_free_ring(devpriv->di_mite_ring); + devpriv->di_mite_ring = NULL; + } + if (devpriv->mite) + mite_unsetup(devpriv->mite); + } + return 0; +} + +static int nidio_find_device(struct comedi_device * dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + for (i = 0; i < n_nidio_boards; i++) { + if (mite_device_id(mite) == nidio_boards[i].dev_id) { + dev->board_ptr = nidio_boards + i; + devpriv->mite = mite; + + return 0; + } + } + } + printk("no device found\n"); + mite_list_devices(); + return -EIO; +} + +COMEDI_PCI_INITCLEANUP(driver_pcidio, ni_pcidio_pci_table); diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c new file mode 100644 index 000000000000..3a2aba7c8dd3 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -0,0 +1,1788 @@ +/* + comedi/drivers/ni_pcimio.c + Hardware driver for NI PCI-MIO E series cards + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-8 David A. Schleef + + 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: ni_pcimio +Description: National Instruments PCI-MIO-E series and M series (all boards) +Author: ds, John Hallen, Frank Mori Hess, Rolf Mueller, Herbert Peremans, + Herman Bruyninckx, Terry Barnaby +Status: works +Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio), + PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6014, PCI-6040E, + PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E, + PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E, + PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, PCI-6225, + PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PCI-6254, PCI-6259, PCIe-6259, + PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289, + PCI-6711, PXI-6711, PCI-6713, PXI-6713, + PXI-6071E, PCI-6070E, PXI-6070E, + PXI-6052E, PCI-6036E, PCI-6731, PCI-6733, PXI-6733, + PCI-6143, PXI-6143 +Updated: Wed, 03 Dec 2008 10:51:47 +0000 + +These boards are almost identical to the AT-MIO E series, except that +they use the PCI bus instead of ISA (i.e., AT). See the notes for +the ni_atmio.o driver for additional information about these boards. + +Autocalibration is supported on many of the devices, using the +comedi_calibrate (or comedi_soft_calibrate for m-series) utility. +M-Series boards do analog input and analog output calibration entirely +in software. The software calibration corrects +the analog input for offset, gain and +nonlinearity. The analog outputs are corrected for offset and gain. +See the comedilib documentation on comedi_get_softcal_converter() for +more information. + +By default, the driver uses DMA to transfer analog input data to +memory. When DMA is enabled, not all triggering features are +supported. + +Digital I/O may not work on 673x. + +Note that the PCI-6143 is a simultaineous sampling device with 8 convertors. +With this board all of the convertors perform one simultaineous sample during +a scan interval. The period for a scan is used for the convert time in a +Comedi cmd. The convert trigger source is normally set to TRIG_NOW by default. + +The RTSI trigger bus is supported on these cards on +subdevice 10. See the comedilib documentation for details. + +Information (number of channels, bits, etc.) for some devices may be +incorrect. Please check this and submit a bug if there are problems +for your device. + +SCXI is probably broken for m-series boards. + +Bugs: + - When DMA is enabled, COMEDI_EV_CONVERT does + not work correctly. + +*/ +/* + The PCI-MIO E series driver was originally written by + Tomasz Motylewski <...>, and ported to comedi by ds. + + References: + + 341079b.pdf PCI E Series Register-Level Programmer Manual + 340934b.pdf DAQ-STC reference manual + + 322080b.pdf 6711/6713/6715 User Manual + + 320945c.pdf PCI E Series User Manual + 322138a.pdf PCI-6052E and DAQPad-6052E User Manual + + ISSUES: + + need to deal with external reference for DAC, and other DAC + properties in board properties + + deal with at-mio-16de-10 revision D to N changes, etc. + + need to add other CALDAC type + + need to slow down DAC loading. I don't trust NI's claim that + two writes to the PCI bus slows IO enough. I would prefer to + use comedi_udelay(). Timing specs: (clock) + AD8522 30ns + DAC8043 120ns + DAC8800 60ns + MB88341 ? + +*/ + +#include "../comedidev.h" + +#include +#include + +#include "ni_stc.h" +#include "mite.h" + +//#define PCI_DEBUG + +#define PCIDMA + +#define PCIMIO 1 +#undef ATMIO + +#define MAX_N_CALDACS (16+16+2) + +#define DRV_NAME "ni_pcimio" + +/* The following two tables must be in the same order */ +static DEFINE_PCI_DEVICE_TABLE(ni_pci_table) = { + {PCI_VENDOR_ID_NATINST, 0x0162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1170, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1190, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x11b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x11c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x11d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1270, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x14e0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x14f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1580, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x15b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x1870, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x18b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x18c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2890, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x28c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2a60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2a70, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2a80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2ab0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2b80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2b90, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2c80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x2ca0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70aa, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70ab, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70ac, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70af, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70b4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70b6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70b7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70bc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70bf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x70f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x710d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x716c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x717f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x71bc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NATINST, 0x717d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, ni_pci_table); + +/* These are not all the possible ao ranges for 628x boards. + They can do OFFSET +- REFERENCE where OFFSET can be + 0V, 5V, APFI<0,1>, or AO<0...3> and RANGE can + be 10V, 5V, 2V, 1V, APFI<0,1>, AO<0...3>. That's + 63 different possibilities. An AO channel + can not act as it's own OFFSET or REFERENCE. +*/ +static const struct comedi_lrange range_ni_M_628x_ao = { 8, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE(-2, 2), + RANGE(-1, 1), + RANGE(-5, 15), + RANGE(0, 10), + RANGE(3, 7), + RANGE(4, 6), + RANGE_ext(-1, 1) + } +}; +static const struct comedi_lrange range_ni_M_625x_ao = { 3, { + RANGE(-10, 10), + RANGE(-5, 5), + RANGE_ext(-1, 1) + } +}; +static const struct comedi_lrange range_ni_M_622x_ao = { 1, { + RANGE(-10, 10), + } +}; + +static const ni_board ni_boards[] = { + { + .device_id = 0x0162, // NI also says 0x1620. typo? + .name = "pci-mio-16xe-50", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 2048, + .alwaysdither = 1, + .gainlkup = ai_gain_8, + .ai_speed = 50000, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 0, + .ao_range_table = &range_bipolar10, + .ao_unipolar = 0, + .ao_speed = 50000, + .num_p0_dio_channels = 8, + .caldac = {dac8800, dac8043}, + .has_8255 = 0, + }, + { + .device_id = 0x1170, + .name = "pci-mio-16xe-10", // aka pci-6030E + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_14, + .ai_speed = 10000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 10000, + .num_p0_dio_channels = 8, + .caldac = {dac8800, dac8043, ad8522}, + .has_8255 = 0, + }, + { + .device_id = 0x28c0, + .name = "pci-6014", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 0, + .ao_range_table = &range_bipolar10, + .ao_unipolar = 0, + .ao_speed = 100000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, + .has_8255 = 0, + }, + { + .device_id = 0x11d0, + .name = "pxi-6030e", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_14, + .ai_speed = 10000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 10000, + .num_p0_dio_channels = 8, + .caldac = {dac8800, dac8043, ad8522}, + .has_8255 = 0, + }, + { + .device_id = 0x1180, + .name = "pci-mio-16e-1", /* aka pci-6070e */ + .n_adchan = 16, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 0, + .gainlkup = ai_gain_16, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .caldac = {mb88341}, + .has_8255 = 0, + }, + { + .device_id = 0x1190, + .name = "pci-mio-16e-4", /* aka pci-6040e */ + .n_adchan = 16, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 0, + .gainlkup = ai_gain_16, + /* Note: there have been reported problems with full speed + * on this board */ + .ai_speed = 2000, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 512, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, // doc says mb88341 + .has_8255 = 0, + }, + { + .device_id = 0x11c0, + .name = "pxi-6040e", + .n_adchan = 16, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 0, + .gainlkup = ai_gain_16, + .ai_speed = 2000, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 512, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .caldac = {mb88341}, + .has_8255 = 0, + }, + + { + .device_id = 0x1330, + .name = "pci-6031e", + .n_adchan = 64, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_14, + .ai_speed = 10000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 10000, + .num_p0_dio_channels = 8, + .caldac = {dac8800, dac8043, ad8522}, + .has_8255 = 0, + }, + { + .device_id = 0x1270, + .name = "pci-6032e", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_14, + .ai_speed = 10000, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 0, + .ao_unipolar = 0, + .num_p0_dio_channels = 8, + .caldac = {dac8800, dac8043, ad8522}, + .has_8255 = 0, + }, + { + .device_id = 0x1340, + .name = "pci-6033e", + .n_adchan = 64, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_14, + .ai_speed = 10000, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 0, + .ao_unipolar = 0, + .num_p0_dio_channels = 8, + .caldac = {dac8800, dac8043, ad8522}, + .has_8255 = 0, + }, + { + .device_id = 0x1350, + .name = "pci-6071e", + .n_adchan = 64, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_16, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, + .has_8255 = 0, + }, + { + .device_id = 0x2a60, + .name = "pci-6023e", + .n_adchan = 16, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 0, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 0, + .aobits = 0, + .ao_unipolar = 0, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, /* manual is wrong */ + .has_8255 = 0, + }, + { + .device_id = 0x2a70, + .name = "pci-6024e", + .n_adchan = 16, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 0, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 0, + .ao_range_table = &range_bipolar10, + .ao_unipolar = 0, + .ao_speed = 100000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, /* manual is wrong */ + .has_8255 = 0, + }, + { + .device_id = 0x2a80, + .name = "pci-6025e", + .n_adchan = 16, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 0, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 0, + .ao_range_table = &range_bipolar10, + .ao_unipolar = 0, + .ao_speed = 100000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, /* manual is wrong */ + .has_8255 = 1, + }, + { + .device_id = 0x2ab0, + .name = "pxi-6025e", + .n_adchan = 16, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 0, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 0, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 100000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, /* manual is wrong */ + .has_8255 = 1, + }, + + { + .device_id = 0x2ca0, + .name = "pci-6034e", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 0, + .ao_unipolar = 0, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, + .has_8255 = 0, + }, + { + .device_id = 0x2c80, + .name = "pci-6035e", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 0, + .ao_range_table = &range_bipolar10, + .ao_unipolar = 0, + .ao_speed = 100000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, + .has_8255 = 0, + }, + { + .device_id = 0x18b0, + .name = "pci-6052e", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_16, + .ai_speed = 3000, + .n_aochan = 2, + .aobits = 16, + .ao_unipolar = 1, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_speed = 3000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug, ad8804_debug, ad8522}, /* manual is wrong */ + }, + {.device_id = 0x14e0, + .name = "pci-6110", + .n_adchan = 4, + .adbits = 12, + .ai_fifo_depth = 8192, + .alwaysdither = 0, + .gainlkup = ai_gain_611x, + .ai_speed = 200, + .n_aochan = 2, + .aobits = 16, + .reg_type = ni_reg_611x, + .ao_range_table = &range_bipolar10, + .ao_unipolar = 0, + .ao_fifo_depth = 2048, + .ao_speed = 250, + .num_p0_dio_channels = 8, + .caldac = {ad8804, ad8804}, + }, + { + .device_id = 0x14f0, + .name = "pci-6111", + .n_adchan = 2, + .adbits = 12, + .ai_fifo_depth = 8192, + .alwaysdither = 0, + .gainlkup = ai_gain_611x, + .ai_speed = 200, + .n_aochan = 2, + .aobits = 16, + .reg_type = ni_reg_611x, + .ao_range_table = &range_bipolar10, + .ao_unipolar = 0, + .ao_fifo_depth = 2048, + .ao_speed = 250, + .num_p0_dio_channels = 8, + .caldac = {ad8804, ad8804}, + }, +#if 0 + /* The 6115 boards probably need their own driver */ + { + .device_id = 0x2ed0, + .name = "pci-6115", + .n_adchan = 4, + .adbits = 12, + .ai_fifo_depth = 8192, + .alwaysdither = 0, + .gainlkup = ai_gain_611x, + .ai_speed = 100, + .n_aochan = 2, + .aobits = 16, + .ao_671x = 1, + .ao_unipolar = 0, + .ao_fifo_depth = 2048, + .ao_speed = 250, + .num_p0_dio_channels = 8, + .reg_611x = 1, + .caldac = {ad8804_debug, ad8804_debug, ad8804_debug}, /* XXX */ + }, +#endif +#if 0 + { + .device_id = 0x0000, + .name = "pxi-6115", + .n_adchan = 4, + .adbits = 12, + .ai_fifo_depth = 8192, + .alwaysdither = 0, + .gainlkup = ai_gain_611x, + .ai_speed = 100, + .n_aochan = 2, + .aobits = 16, + .ao_671x = 1, + .ao_unipolar = 0, + .ao_fifo_depth = 2048, + .ao_speed = 250, + .reg_611x = 1, + .num_p0_dio_channels = 8, + caldac = {ad8804_debug, ad8804_debug, ad8804_debug}, /* XXX */ + }, +#endif + { + .device_id = 0x1880, + .name = "pci-6711", + .n_adchan = 0, /* no analog input */ + .n_aochan = 4, + .aobits = 12, + .ao_unipolar = 0, + .ao_fifo_depth = 16384, + /* data sheet says 8192, but fifo really holds 16384 samples */ + .ao_range_table = &range_bipolar10, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6711, + .caldac = {ad8804_debug}, + }, + { + .device_id = 0x2b90, + .name = "pxi-6711", + .n_adchan = 0, /* no analog input */ + .n_aochan = 4, + .aobits = 12, + .ao_unipolar = 0, + .ao_fifo_depth = 16384, + .ao_range_table = &range_bipolar10, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6711, + .caldac = {ad8804_debug}, + }, + { + .device_id = 0x1870, + .name = "pci-6713", + .n_adchan = 0, /* no analog input */ + .n_aochan = 8, + .aobits = 12, + .ao_unipolar = 0, + .ao_fifo_depth = 16384, + .ao_range_table = &range_bipolar10, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6713, + .caldac = {ad8804_debug, ad8804_debug}, + }, + { + .device_id = 0x2b80, + .name = "pxi-6713", + .n_adchan = 0, /* no analog input */ + .n_aochan = 8, + .aobits = 12, + .ao_unipolar = 0, + .ao_fifo_depth = 16384, + .ao_range_table = &range_bipolar10, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6713, + .caldac = {ad8804_debug, ad8804_debug}, + }, + { + .device_id = 0x2430, + .name = "pci-6731", + .n_adchan = 0, /* no analog input */ + .n_aochan = 4, + .aobits = 16, + .ao_unipolar = 0, + .ao_fifo_depth = 8192, + .ao_range_table = &range_bipolar10, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6711, + .caldac = {ad8804_debug}, + }, +#if 0 /* need device ids */ + { + .device_id = 0x0, + .name = "pxi-6731", + .n_adchan = 0, /* no analog input */ + .n_aochan = 4, + .aobits = 16, + .ao_unipolar = 0, + .ao_fifo_depth = 8192, + .ao_range_table = &range_bipolar10, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6711, + .caldac = {ad8804_debug}, + }, +#endif + { + .device_id = 0x2410, + .name = "pci-6733", + .n_adchan = 0, /* no analog input */ + .n_aochan = 8, + .aobits = 16, + .ao_unipolar = 0, + .ao_fifo_depth = 16384, + .ao_range_table = &range_bipolar10, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6713, + .caldac = {ad8804_debug, ad8804_debug}, + }, + { + .device_id = 0x2420, + .name = "pxi-6733", + .n_adchan = 0, /* no analog input */ + .n_aochan = 8, + .aobits = 16, + .ao_unipolar = 0, + .ao_fifo_depth = 16384, + .ao_range_table = &range_bipolar10, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_6713, + .caldac = {ad8804_debug, ad8804_debug}, + }, + { + .device_id = 0x15b0, + .name = "pxi-6071e", + .n_adchan = 64, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_16, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, + .has_8255 = 0, + }, + { + .device_id = 0x11b0, + .name = "pxi-6070e", + .n_adchan = 16, + .adbits = 12, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_16, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 12, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 1000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, + .has_8255 = 0, + }, + { + .device_id = 0x18c0, + .name = "pxi-6052e", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_16, + .ai_speed = 3000, + .n_aochan = 2, + .aobits = 16, + .ao_unipolar = 1, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_speed = 3000, + .num_p0_dio_channels = 8, + .caldac = {mb88341, mb88341, ad8522}, + }, + { + .device_id = 0x1580, + .name = "pxi-6031e", + .n_adchan = 64, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_14, + .ai_speed = 10000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 2048, + .ao_range_table = &range_ni_E_ao_ext, + .ao_unipolar = 1, + .ao_speed = 10000, + .num_p0_dio_channels = 8, + .caldac = {dac8800, dac8043, ad8522}, + }, + { + .device_id = 0x2890, + .name = "pci-6036e", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + .alwaysdither = 1, + .gainlkup = ai_gain_4, + .ai_speed = 5000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 0, + .ao_range_table = &range_bipolar10, + .ao_unipolar = 0, + .ao_speed = 100000, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug}, + .has_8255 = 0, + }, + { + .device_id = 0x70b0, + .name = "pci-6220", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 512, + //FIXME: guess + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 0, + .num_p0_dio_channels = 8, + .reg_type = ni_reg_622x, + .ao_unipolar = 0, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70af, + .name = "pci-6221", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_622x_ao, + .reg_type = ni_reg_622x, + .ao_unipolar = 0, + .ao_speed = 1200, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x71bc, + .name = "pci-6221_37pin", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_622x_ao, + .reg_type = ni_reg_622x, + .ao_unipolar = 0, + .ao_speed = 1200, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70f2, + .name = "pci-6224", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 0, + .reg_type = ni_reg_622x, + .ao_unipolar = 0, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70f3, + .name = "pxi-6224", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 0, + .reg_type = ni_reg_622x, + .ao_unipolar = 0, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x716c, + .name = "pci-6225", + .n_adchan = 80, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_622x_ao, + .reg_type = ni_reg_622x, + .ao_unipolar = 0, + .ao_speed = 1200, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70aa, + .name = "pci-6229", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_622x, + .ai_speed = 4000, + .n_aochan = 4, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_622x_ao, + .reg_type = ni_reg_622x, + .ao_unipolar = 0, + .ao_speed = 1200, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70b4, + .name = "pci-6250", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 0, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70b8, + .name = "pci-6251", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, + .ao_speed = 357, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x717d, + .name = "pcie-6251", + .n_adchan = 16, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, + .ao_speed = 357, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70b7, + .name = "pci-6254", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 0, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70ab, + .name = "pci-6259", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 4, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, + .ao_speed = 357, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x717f, + .name = "pcie-6259", + .n_adchan = 32, + .adbits = 16, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 4, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, + .ao_speed = 357, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70b6, + .name = "pci-6280", + .n_adchan = 16, + .adbits = 18, + .ai_fifo_depth = 2047, + .gainlkup = ai_gain_628x, + .ai_speed = 1600, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 8191, + .reg_type = ni_reg_628x, + .ao_unipolar = 0, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70bd, + .name = "pci-6281", + .n_adchan = 16, + .adbits = 18, + .ai_fifo_depth = 2047, + .gainlkup = ai_gain_628x, + .ai_speed = 1600, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_628x_ao, + .reg_type = ni_reg_628x, + .ao_unipolar = 1, + .ao_speed = 357, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70bf, + .name = "pxi-6281", + .n_adchan = 16, + .adbits = 18, + .ai_fifo_depth = 2047, + .gainlkup = ai_gain_628x, + .ai_speed = 1600, + .n_aochan = 2, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_628x_ao, + .reg_type = ni_reg_628x, + .ao_unipolar = 1, + .ao_speed = 357, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70bc, + .name = "pci-6284", + .n_adchan = 32, + .adbits = 18, + .ai_fifo_depth = 2047, + .gainlkup = ai_gain_628x, + .ai_speed = 1600, + .n_aochan = 0, + .aobits = 0, + .ao_fifo_depth = 0, + .reg_type = ni_reg_628x, + .ao_unipolar = 0, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70ac, + .name = "pci-6289", + .n_adchan = 32, + .adbits = 18, + .ai_fifo_depth = 2047, + .gainlkup = ai_gain_628x, + .ai_speed = 1600, + .n_aochan = 4, + .aobits = 16, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_628x_ao, + .reg_type = ni_reg_628x, + .ao_unipolar = 1, + .ao_speed = 357, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, + }, + { + .device_id = 0x70C0, + .name = "pci-6143", + .n_adchan = 8, + .adbits = 16, + .ai_fifo_depth = 1024, + .alwaysdither = 0, + .gainlkup = ai_gain_6143, + .ai_speed = 4000, + .n_aochan = 0, + .aobits = 0, + .reg_type = ni_reg_6143, + .ao_unipolar = 0, + .ao_fifo_depth = 0, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug, ad8804_debug}, + }, + { + .device_id = 0x710D, + .name = "pxi-6143", + .n_adchan = 8, + .adbits = 16, + .ai_fifo_depth = 1024, + .alwaysdither = 0, + .gainlkup = ai_gain_6143, + .ai_speed = 4000, + .n_aochan = 0, + .aobits = 0, + .reg_type = ni_reg_6143, + .ao_unipolar = 0, + .ao_fifo_depth = 0, + .num_p0_dio_channels = 8, + .caldac = {ad8804_debug, ad8804_debug}, + }, +}; + +#define n_pcimio_boards ((sizeof(ni_boards)/sizeof(ni_boards[0]))) + +static int pcimio_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcimio_detach(struct comedi_device * dev); +static struct comedi_driver driver_pcimio = { + driver_name: DRV_NAME, + module:THIS_MODULE, + attach:pcimio_attach, + detach:pcimio_detach, +}; + +COMEDI_PCI_INITCLEANUP(driver_pcimio, ni_pci_table) + +typedef struct { +NI_PRIVATE_COMMON} ni_private; +#define devpriv ((ni_private *)dev->private) + +/* How we access registers */ + +#define ni_writel(a,b) (writel((a), devpriv->mite->daq_io_addr + (b))) +#define ni_readl(a) (readl(devpriv->mite->daq_io_addr + (a))) +#define ni_writew(a,b) (writew((a), devpriv->mite->daq_io_addr + (b))) +#define ni_readw(a) (readw(devpriv->mite->daq_io_addr + (a))) +#define ni_writeb(a,b) (writeb((a), devpriv->mite->daq_io_addr + (b))) +#define ni_readb(a) (readb(devpriv->mite->daq_io_addr + (a))) + +/* How we access STC registers */ + +/* We automatically take advantage of STC registers that can be + * read/written directly in the I/O space of the board. Most + * PCIMIO devices map the low 8 STC registers to iobase+addr*2. + * The 611x devices map the write registers to iobase+addr*2, and + * the read registers to iobase+(addr-1)*2. */ +/* However, the 611x boards still aren't working, so I'm disabling + * non-windowed STC access temporarily */ + +static void e_series_win_out(struct comedi_device * dev, uint16_t data, int reg) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&devpriv->window_lock, flags); + ni_writew(reg, Window_Address); + ni_writew(data, Window_Data); + comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags); +} + +static uint16_t e_series_win_in(struct comedi_device * dev, int reg) +{ + unsigned long flags; + uint16_t ret; + + comedi_spin_lock_irqsave(&devpriv->window_lock, flags); + ni_writew(reg, Window_Address); + ret = ni_readw(Window_Data); + comedi_spin_unlock_irqrestore(&devpriv->window_lock, flags); + + return ret; +} + +static void m_series_stc_writew(struct comedi_device * dev, uint16_t data, int reg) +{ + unsigned offset; + switch (reg) { + case ADC_FIFO_Clear: + offset = M_Offset_AI_FIFO_Clear; + break; + case AI_Command_1_Register: + offset = M_Offset_AI_Command_1; + break; + case AI_Command_2_Register: + offset = M_Offset_AI_Command_2; + break; + case AI_Mode_1_Register: + offset = M_Offset_AI_Mode_1; + break; + case AI_Mode_2_Register: + offset = M_Offset_AI_Mode_2; + break; + case AI_Mode_3_Register: + offset = M_Offset_AI_Mode_3; + break; + case AI_Output_Control_Register: + offset = M_Offset_AI_Output_Control; + break; + case AI_Personal_Register: + offset = M_Offset_AI_Personal; + break; + case AI_SI2_Load_A_Register: + // this is actually a 32 bit register on m series boards + ni_writel(data, M_Offset_AI_SI2_Load_A); + return; + break; + case AI_SI2_Load_B_Register: + // this is actually a 32 bit register on m series boards + ni_writel(data, M_Offset_AI_SI2_Load_B); + return; + break; + case AI_START_STOP_Select_Register: + offset = M_Offset_AI_START_STOP_Select; + break; + case AI_Trigger_Select_Register: + offset = M_Offset_AI_Trigger_Select; + break; + case Analog_Trigger_Etc_Register: + offset = M_Offset_Analog_Trigger_Etc; + break; + case AO_Command_1_Register: + offset = M_Offset_AO_Command_1; + break; + case AO_Command_2_Register: + offset = M_Offset_AO_Command_2; + break; + case AO_Mode_1_Register: + offset = M_Offset_AO_Mode_1; + break; + case AO_Mode_2_Register: + offset = M_Offset_AO_Mode_2; + break; + case AO_Mode_3_Register: + offset = M_Offset_AO_Mode_3; + break; + case AO_Output_Control_Register: + offset = M_Offset_AO_Output_Control; + break; + case AO_Personal_Register: + offset = M_Offset_AO_Personal; + break; + case AO_Start_Select_Register: + offset = M_Offset_AO_Start_Select; + break; + case AO_Trigger_Select_Register: + offset = M_Offset_AO_Trigger_Select; + break; + case Clock_and_FOUT_Register: + offset = M_Offset_Clock_and_FOUT; + break; + case Configuration_Memory_Clear: + offset = M_Offset_Configuration_Memory_Clear; + break; + case DAC_FIFO_Clear: + offset = M_Offset_AO_FIFO_Clear; + break; + case DIO_Control_Register: + rt_printk + ("%s: FIXME: register 0x%x does not map cleanly on to m-series boards.\n", + __FUNCTION__, reg); + return; + break; + case G_Autoincrement_Register(0): + offset = M_Offset_G0_Autoincrement; + break; + case G_Autoincrement_Register(1): + offset = M_Offset_G1_Autoincrement; + break; + case G_Command_Register(0): + offset = M_Offset_G0_Command; + break; + case G_Command_Register(1): + offset = M_Offset_G1_Command; + break; + case G_Input_Select_Register(0): + offset = M_Offset_G0_Input_Select; + break; + case G_Input_Select_Register(1): + offset = M_Offset_G1_Input_Select; + break; + case G_Mode_Register(0): + offset = M_Offset_G0_Mode; + break; + case G_Mode_Register(1): + offset = M_Offset_G1_Mode; + break; + case Interrupt_A_Ack_Register: + offset = M_Offset_Interrupt_A_Ack; + break; + case Interrupt_A_Enable_Register: + offset = M_Offset_Interrupt_A_Enable; + break; + case Interrupt_B_Ack_Register: + offset = M_Offset_Interrupt_B_Ack; + break; + case Interrupt_B_Enable_Register: + offset = M_Offset_Interrupt_B_Enable; + break; + case Interrupt_Control_Register: + offset = M_Offset_Interrupt_Control; + break; + case IO_Bidirection_Pin_Register: + offset = M_Offset_IO_Bidirection_Pin; + break; + case Joint_Reset_Register: + offset = M_Offset_Joint_Reset; + break; + case RTSI_Trig_A_Output_Register: + offset = M_Offset_RTSI_Trig_A_Output; + break; + case RTSI_Trig_B_Output_Register: + offset = M_Offset_RTSI_Trig_B_Output; + break; + case RTSI_Trig_Direction_Register: + offset = M_Offset_RTSI_Trig_Direction; + break; + /* FIXME: DIO_Output_Register (16 bit reg) is replaced by M_Offset_Static_Digital_Output (32 bit) + and M_Offset_SCXI_Serial_Data_Out (8 bit) */ + default: + rt_printk("%s: bug! unhandled register=0x%x in switch.\n", + __FUNCTION__, reg); + BUG(); + return; + break; + } + ni_writew(data, offset); +} + +static uint16_t m_series_stc_readw(struct comedi_device * dev, int reg) +{ + unsigned offset; + switch (reg) { + case AI_Status_1_Register: + offset = M_Offset_AI_Status_1; + break; + case AO_Status_1_Register: + offset = M_Offset_AO_Status_1; + break; + case AO_Status_2_Register: + offset = M_Offset_AO_Status_2; + break; + case DIO_Serial_Input_Register: + return ni_readb(M_Offset_SCXI_Serial_Data_In); + break; + case Joint_Status_1_Register: + offset = M_Offset_Joint_Status_1; + break; + case Joint_Status_2_Register: + offset = M_Offset_Joint_Status_2; + break; + case G_Status_Register: + offset = M_Offset_G01_Status; + break; + default: + rt_printk("%s: bug! unhandled register=0x%x in switch.\n", + __FUNCTION__, reg); + BUG(); + return 0; + break; + } + return ni_readw(offset); +} + +static void m_series_stc_writel(struct comedi_device * dev, uint32_t data, int reg) +{ + unsigned offset; + switch (reg) { + case AI_SC_Load_A_Registers: + offset = M_Offset_AI_SC_Load_A; + break; + case AI_SI_Load_A_Registers: + offset = M_Offset_AI_SI_Load_A; + break; + case AO_BC_Load_A_Register: + offset = M_Offset_AO_BC_Load_A; + break; + case AO_UC_Load_A_Register: + offset = M_Offset_AO_UC_Load_A; + break; + case AO_UI_Load_A_Register: + offset = M_Offset_AO_UI_Load_A; + break; + case G_Load_A_Register(0): + offset = M_Offset_G0_Load_A; + break; + case G_Load_A_Register(1): + offset = M_Offset_G1_Load_A; + break; + case G_Load_B_Register(0): + offset = M_Offset_G0_Load_B; + break; + case G_Load_B_Register(1): + offset = M_Offset_G1_Load_B; + break; + default: + rt_printk("%s: bug! unhandled register=0x%x in switch.\n", + __FUNCTION__, reg); + BUG(); + return; + break; + } + ni_writel(data, offset); +} + +static uint32_t m_series_stc_readl(struct comedi_device * dev, int reg) +{ + unsigned offset; + switch (reg) { + case G_HW_Save_Register(0): + offset = M_Offset_G0_HW_Save; + break; + case G_HW_Save_Register(1): + offset = M_Offset_G1_HW_Save; + break; + case G_Save_Register(0): + offset = M_Offset_G0_Save; + break; + case G_Save_Register(1): + offset = M_Offset_G1_Save; + break; + default: + rt_printk("%s: bug! unhandled register=0x%x in switch.\n", + __FUNCTION__, reg); + BUG(); + return 0; + break; + } + return ni_readl(offset); +} + +#define interrupt_pin(a) 0 +#define IRQ_POLARITY 1 + +#define NI_E_IRQ_FLAGS IRQF_SHARED + +#include "ni_mio_common.c" + +static int pcimio_find_device(struct comedi_device * dev, int bus, int slot); +static int pcimio_ai_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size); +static int pcimio_ao_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size); +static int pcimio_gpct0_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size); +static int pcimio_gpct1_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size); +static int pcimio_dio_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size); + +static void m_series_init_eeprom_buffer(struct comedi_device * dev) +{ + static const int Start_Cal_EEPROM = 0x400; + static const unsigned window_size = 10; + static const int serial_number_eeprom_offset = 0x4; + static const int serial_number_eeprom_length = 0x4; + unsigned old_iodwbsr_bits; + unsigned old_iodwbsr1_bits; + unsigned old_iodwcr1_bits; + int i; + + old_iodwbsr_bits = readl(devpriv->mite->mite_io_addr + MITE_IODWBSR); + old_iodwbsr1_bits = readl(devpriv->mite->mite_io_addr + MITE_IODWBSR_1); + old_iodwcr1_bits = readl(devpriv->mite->mite_io_addr + MITE_IODWCR_1); + writel(0x0, devpriv->mite->mite_io_addr + MITE_IODWBSR); + writel(((0x80 | window_size) | devpriv->mite->daq_phys_addr), + devpriv->mite->mite_io_addr + MITE_IODWBSR_1); + writel(0x1 | old_iodwcr1_bits, devpriv->mite->mite_io_addr + MITE_IODWCR_1); + writel(0xf, devpriv->mite->mite_io_addr + 0x30); + + BUG_ON(serial_number_eeprom_length > sizeof(devpriv->serial_number)); + for (i = 0; i < serial_number_eeprom_length; ++i) { + char *byte_ptr = (char*)&devpriv->serial_number + i; + *byte_ptr = ni_readb(serial_number_eeprom_offset + i); + } + devpriv->serial_number = be32_to_cpu(devpriv->serial_number); + + for (i = 0; i < M_SERIES_EEPROM_SIZE; ++i) { + devpriv->eeprom_buffer[i] = ni_readb(Start_Cal_EEPROM + i); + } + + writel(old_iodwbsr1_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR_1); + writel(old_iodwbsr_bits, devpriv->mite->mite_io_addr + MITE_IODWBSR); + writel(old_iodwcr1_bits, devpriv->mite->mite_io_addr + MITE_IODWCR_1); + writel(0x0, devpriv->mite->mite_io_addr + 0x30); +} + +static void init_6143(struct comedi_device * dev) +{ + // Disable interrupts + devpriv->stc_writew(dev, 0, Interrupt_Control_Register); + + // Initialise 6143 AI specific bits + ni_writeb(0x00, Magic_6143); // Set G0,G1 DMA mode to E series version + ni_writeb(0x80, PipelineDelay_6143); // Set EOCMode, ADCMode and pipelinedelay + ni_writeb(0x00, EOC_Set_6143); // Set EOC Delay + + ni_writel(boardtype.ai_fifo_depth / 2, AIFIFO_Flag_6143); // Set the FIFO half full level + + // Strobe Relay disable bit + devpriv->ai_calib_source_enabled = 0; + ni_writew(devpriv->ai_calib_source | Calibration_Channel_6143_RelayOff, + Calibration_Channel_6143); + ni_writew(devpriv->ai_calib_source, Calibration_Channel_6143); +} + +/* cleans up allocated resources */ +static int pcimio_detach(struct comedi_device * dev) +{ + mio_common_detach(dev); + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } + if (dev->private) { + mite_free_ring(devpriv->ai_mite_ring); + mite_free_ring(devpriv->ao_mite_ring); + mite_free_ring(devpriv->cdo_mite_ring); + mite_free_ring(devpriv->gpct_mite_ring[0]); + mite_free_ring(devpriv->gpct_mite_ring[1]); + if (devpriv->mite) + mite_unsetup(devpriv->mite); + } + + return 0; +} + +static int pcimio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + + printk("comedi%d: ni_pcimio:", dev->minor); + + ret = ni_alloc_private(dev); + if (ret < 0) + return ret; + + ret = pcimio_find_device(dev, it->options[0], it->options[1]); + if (ret < 0) + return ret; + + printk(" %s", boardtype.name); + dev->board_name = boardtype.name; + + if (boardtype.reg_type & ni_reg_m_series_mask) { + devpriv->stc_writew = &m_series_stc_writew; + devpriv->stc_readw = &m_series_stc_readw; + devpriv->stc_writel = &m_series_stc_writel; + devpriv->stc_readl = &m_series_stc_readl; + } else { + devpriv->stc_writew = &e_series_win_out; + devpriv->stc_readw = &e_series_win_in; + devpriv->stc_writel = &win_out2; + devpriv->stc_readl = &win_in2; + } + + ret = mite_setup(devpriv->mite); + if (ret < 0) { + printk(" error setting up mite\n"); + return ret; + } + comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev); + devpriv->ai_mite_ring = mite_alloc_ring(devpriv->mite); + if (devpriv->ai_mite_ring == NULL) + return -ENOMEM; + devpriv->ao_mite_ring = mite_alloc_ring(devpriv->mite); + if (devpriv->ao_mite_ring == NULL) + return -ENOMEM; + devpriv->cdo_mite_ring = mite_alloc_ring(devpriv->mite); + if (devpriv->cdo_mite_ring == NULL) + return -ENOMEM; + devpriv->gpct_mite_ring[0] = mite_alloc_ring(devpriv->mite); + if (devpriv->gpct_mite_ring[0] == NULL) + return -ENOMEM; + devpriv->gpct_mite_ring[1] = mite_alloc_ring(devpriv->mite); + if (devpriv->gpct_mite_ring[1] == NULL) + return -ENOMEM; + + if (boardtype.reg_type & ni_reg_m_series_mask) + m_series_init_eeprom_buffer(dev); + if (boardtype.reg_type == ni_reg_6143) + init_6143(dev); + + dev->irq = mite_irq(devpriv->mite); + + if (dev->irq == 0) { + printk(" unknown irq (bad)\n"); + } else { + printk(" ( irq = %u )", dev->irq); + if ((ret = comedi_request_irq(dev->irq, ni_E_interrupt, + NI_E_IRQ_FLAGS, DRV_NAME, + dev)) < 0) { + printk(" irq not available\n"); + dev->irq = 0; + } + } + + ret = ni_E_init(dev, it); + if (ret < 0) + return ret; + + dev->subdevices[NI_AI_SUBDEV].buf_change = &pcimio_ai_change; + dev->subdevices[NI_AO_SUBDEV].buf_change = &pcimio_ao_change; + dev->subdevices[NI_GPCT_SUBDEV(0)].buf_change = &pcimio_gpct0_change; + dev->subdevices[NI_GPCT_SUBDEV(1)].buf_change = &pcimio_gpct1_change; + dev->subdevices[NI_DIO_SUBDEV].buf_change = &pcimio_dio_change; + + return ret; +} + +static int pcimio_find_device(struct comedi_device * dev, int bus, int slot) +{ + struct mite_struct *mite; + int i; + + for (mite = mite_devices; mite; mite = mite->next) { + if (mite->used) + continue; + if (bus || slot) { + if (bus != mite->pcidev->bus->number || + slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + } + + for (i = 0; i < n_pcimio_boards; i++) { + if (mite_device_id(mite) == ni_boards[i].device_id) { + dev->board_ptr = ni_boards + i; + devpriv->mite = mite; + + return 0; + } + } + } + printk("no device found\n"); + mite_list_devices(); + return -EIO; +} + +static int pcimio_ai_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size) +{ + int ret; + + ret = mite_buf_change(devpriv->ai_mite_ring, s->async); + if (ret < 0) + return ret; + + return 0; +} + +static int pcimio_ao_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size) +{ + int ret; + + ret = mite_buf_change(devpriv->ao_mite_ring, s->async); + if (ret < 0) + return ret; + + return 0; +} + +static int pcimio_gpct0_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size) +{ + int ret; + + ret = mite_buf_change(devpriv->gpct_mite_ring[0], s->async); + if (ret < 0) + return ret; + + return 0; +} + +static int pcimio_gpct1_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size) +{ + int ret; + + ret = mite_buf_change(devpriv->gpct_mite_ring[1], s->async); + if (ret < 0) + return ret; + + return 0; +} + +static int pcimio_dio_change(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned long new_size) +{ + int ret; + + ret = mite_buf_change(devpriv->cdo_mite_ring, s->async); + if (ret < 0) + return ret; + + return 0; +} diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h new file mode 100644 index 000000000000..1ebf521ab773 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_stc.h @@ -0,0 +1,1498 @@ +/* + module/ni_stc.h + Register descriptions for NI DAQ-STC chip + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998-9 David A. Schleef + + 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. + +*/ + +/* + References: + DAQ-STC Technical Reference Manual +*/ + +#ifndef _COMEDI_NI_STC_H +#define _COMEDI_NI_STC_H + +#include "ni_tio.h" + +#define _bit15 0x8000 +#define _bit14 0x4000 +#define _bit13 0x2000 +#define _bit12 0x1000 +#define _bit11 0x0800 +#define _bit10 0x0400 +#define _bit9 0x0200 +#define _bit8 0x0100 +#define _bit7 0x0080 +#define _bit6 0x0040 +#define _bit5 0x0020 +#define _bit4 0x0010 +#define _bit3 0x0008 +#define _bit2 0x0004 +#define _bit1 0x0002 +#define _bit0 0x0001 + +#define NUM_PFI_OUTPUT_SELECT_REGS 6 + +/* Registers in the National Instruments DAQ-STC chip */ + +#define Interrupt_A_Ack_Register 2 +#define G0_Gate_Interrupt_Ack _bit15 +#define G0_TC_Interrupt_Ack _bit14 +#define AI_Error_Interrupt_Ack _bit13 +#define AI_STOP_Interrupt_Ack _bit12 +#define AI_START_Interrupt_Ack _bit11 +#define AI_START2_Interrupt_Ack _bit10 +#define AI_START1_Interrupt_Ack _bit9 +#define AI_SC_TC_Interrupt_Ack _bit8 +#define AI_SC_TC_Error_Confirm _bit7 +#define G0_TC_Error_Confirm _bit6 +#define G0_Gate_Error_Confirm _bit5 + +#define AI_Status_1_Register 2 +#define Interrupt_A_St 0x8000 +#define AI_FIFO_Full_St 0x4000 +#define AI_FIFO_Half_Full_St 0x2000 +#define AI_FIFO_Empty_St 0x1000 +#define AI_Overrun_St 0x0800 +#define AI_Overflow_St 0x0400 +#define AI_SC_TC_Error_St 0x0200 +#define AI_START2_St 0x0100 +#define AI_START1_St 0x0080 +#define AI_SC_TC_St 0x0040 +#define AI_START_St 0x0020 +#define AI_STOP_St 0x0010 +#define G0_TC_St 0x0008 +#define G0_Gate_Interrupt_St 0x0004 +#define AI_FIFO_Request_St 0x0002 +#define Pass_Thru_0_Interrupt_St 0x0001 + +#define AI_Status_2_Register 5 + +#define Interrupt_B_Ack_Register 3 +enum Interrupt_B_Ack_Bits { + G1_Gate_Error_Confirm = _bit1, + G1_TC_Error_Confirm = _bit2, + AO_BC_TC_Trigger_Error_Confirm = _bit3, + AO_BC_TC_Error_Confirm = _bit4, + AO_UI2_TC_Error_Confrim = _bit5, + AO_UI2_TC_Interrupt_Ack = _bit6, + AO_UC_TC_Interrupt_Ack = _bit7, + AO_BC_TC_Interrupt_Ack = _bit8, + AO_START1_Interrupt_Ack = _bit9, + AO_UPDATE_Interrupt_Ack = _bit10, + AO_START_Interrupt_Ack = _bit11, + AO_STOP_Interrupt_Ack = _bit12, + AO_Error_Interrupt_Ack = _bit13, + G1_TC_Interrupt_Ack = _bit14, + G1_Gate_Interrupt_Ack = _bit15 +}; + +#define AO_Status_1_Register 3 +#define Interrupt_B_St _bit15 +#define AO_FIFO_Full_St _bit14 +#define AO_FIFO_Half_Full_St _bit13 +#define AO_FIFO_Empty_St _bit12 +#define AO_BC_TC_Error_St _bit11 +#define AO_START_St _bit10 +#define AO_Overrun_St _bit9 +#define AO_START1_St _bit8 +#define AO_BC_TC_St _bit7 +#define AO_UC_TC_St _bit6 +#define AO_UPDATE_St _bit5 +#define AO_UI2_TC_St _bit4 +#define G1_TC_St _bit3 +#define G1_Gate_Interrupt_St _bit2 +#define AO_FIFO_Request_St _bit1 +#define Pass_Thru_1_Interrupt_St _bit0 + +#define AI_Command_2_Register 4 +#define AI_End_On_SC_TC _bit15 +#define AI_End_On_End_Of_Scan _bit14 +#define AI_START1_Disable _bit11 +#define AI_SC_Save_Trace _bit10 +#define AI_SI_Switch_Load_On_SC_TC _bit9 +#define AI_SI_Switch_Load_On_STOP _bit8 +#define AI_SI_Switch_Load_On_TC _bit7 +#define AI_SC_Switch_Load_On_TC _bit4 +#define AI_STOP_Pulse _bit3 +#define AI_START_Pulse _bit2 +#define AI_START2_Pulse _bit1 +#define AI_START1_Pulse _bit0 + +#define AO_Command_2_Register 5 +#define AO_End_On_BC_TC(x) (((x) & 0x3) << 14) +#define AO_Start_Stop_Gate_Enable _bit13 +#define AO_UC_Save_Trace _bit12 +#define AO_BC_Gate_Enable _bit11 +#define AO_BC_Save_Trace _bit10 +#define AO_UI_Switch_Load_On_BC_TC _bit9 +#define AO_UI_Switch_Load_On_Stop _bit8 +#define AO_UI_Switch_Load_On_TC _bit7 +#define AO_UC_Switch_Load_On_BC_TC _bit6 +#define AO_UC_Switch_Load_On_TC _bit5 +#define AO_BC_Switch_Load_On_TC _bit4 +#define AO_Mute_B _bit3 +#define AO_Mute_A _bit2 +#define AO_UPDATE2_Pulse _bit1 +#define AO_START1_Pulse _bit0 + +#define AO_Status_2_Register 6 + +#define DIO_Parallel_Input_Register 7 + +#define AI_Command_1_Register 8 +#define AI_Analog_Trigger_Reset _bit14 +#define AI_Disarm _bit13 +#define AI_SI2_Arm _bit12 +#define AI_SI2_Load _bit11 +#define AI_SI_Arm _bit10 +#define AI_SI_Load _bit9 +#define AI_DIV_Arm _bit8 +#define AI_DIV_Load _bit7 +#define AI_SC_Arm _bit6 +#define AI_SC_Load _bit5 +#define AI_SCAN_IN_PROG_Pulse _bit4 +#define AI_EXTMUX_CLK_Pulse _bit3 +#define AI_LOCALMUX_CLK_Pulse _bit2 +#define AI_SC_TC_Pulse _bit1 +#define AI_CONVERT_Pulse _bit0 + +#define AO_Command_1_Register 9 +#define AO_Analog_Trigger_Reset _bit15 +#define AO_START_Pulse _bit14 +#define AO_Disarm _bit13 +#define AO_UI2_Arm_Disarm _bit12 +#define AO_UI2_Load _bit11 +#define AO_UI_Arm _bit10 +#define AO_UI_Load _bit9 +#define AO_UC_Arm _bit8 +#define AO_UC_Load _bit7 +#define AO_BC_Arm _bit6 +#define AO_BC_Load _bit5 +#define AO_DAC1_Update_Mode _bit4 +#define AO_LDAC1_Source_Select _bit3 +#define AO_DAC0_Update_Mode _bit2 +#define AO_LDAC0_Source_Select _bit1 +#define AO_UPDATE_Pulse _bit0 + +#define DIO_Output_Register 10 +#define DIO_Parallel_Data_Out(a) ((a)&0xff) +#define DIO_Parallel_Data_Mask 0xff +#define DIO_SDOUT _bit0 +#define DIO_SDIN _bit4 +#define DIO_Serial_Data_Out(a) (((a)&0xff)<<8) +#define DIO_Serial_Data_Mask 0xff00 + +#define DIO_Control_Register 11 +#define DIO_Software_Serial_Control _bit11 +#define DIO_HW_Serial_Timebase _bit10 +#define DIO_HW_Serial_Enable _bit9 +#define DIO_HW_Serial_Start _bit8 +#define DIO_Pins_Dir(a) ((a)&0xff) +#define DIO_Pins_Dir_Mask 0xff + +#define AI_Mode_1_Register 12 +#define AI_CONVERT_Source_Select(a) (((a) & 0x1f) << 11) +#define AI_SI_Source_select(a) (((a) & 0x1f) << 6) +#define AI_CONVERT_Source_Polarity _bit5 +#define AI_SI_Source_Polarity _bit4 +#define AI_Start_Stop _bit3 +#define AI_Mode_1_Reserved _bit2 +#define AI_Continuous _bit1 +#define AI_Trigger_Once _bit0 + +#define AI_Mode_2_Register 13 +#define AI_SC_Gate_Enable _bit15 +#define AI_Start_Stop_Gate_Enable _bit14 +#define AI_Pre_Trigger _bit13 +#define AI_External_MUX_Present _bit12 +#define AI_SI2_Initial_Load_Source _bit9 +#define AI_SI2_Reload_Mode _bit8 +#define AI_SI_Initial_Load_Source _bit7 +#define AI_SI_Reload_Mode(a) (((a) & 0x7)<<4) +#define AI_SI_Write_Switch _bit3 +#define AI_SC_Initial_Load_Source _bit2 +#define AI_SC_Reload_Mode _bit1 +#define AI_SC_Write_Switch _bit0 + +#define AI_SI_Load_A_Registers 14 +#define AI_SI_Load_B_Registers 16 +#define AI_SC_Load_A_Registers 18 +#define AI_SC_Load_B_Registers 20 +#define AI_SI_Save_Registers 64 +#define AI_SC_Save_Registers 66 + +#define AI_SI2_Load_A_Register 23 +#define AI_SI2_Load_B_Register 25 + +#define Joint_Status_1_Register 27 +#define DIO_Serial_IO_In_Progress_St _bit12 + +#define DIO_Serial_Input_Register 28 +#define Joint_Status_2_Register 29 +enum Joint_Status_2_Bits { + AO_TMRDACWRs_In_Progress_St = 0x20, +}; + +#define AO_Mode_1_Register 38 +#define AO_UPDATE_Source_Select(x) (((x)&0x1f)<<11) +#define AO_UI_Source_Select(x) (((x)&0x1f)<<6) +#define AO_Multiple_Channels _bit5 +#define AO_UPDATE_Source_Polarity _bit4 +#define AO_UI_Source_Polarity _bit3 +#define AO_UC_Switch_Load_Every_TC _bit2 +#define AO_Continuous _bit1 +#define AO_Trigger_Once _bit0 + +#define AO_Mode_2_Register 39 +#define AO_FIFO_Mode_Mask ( 0x3 << 14 ) +enum AO_FIFO_Mode_Bits { + AO_FIFO_Mode_HF_to_F = (3 << 14), + AO_FIFO_Mode_F = (2 << 14), + AO_FIFO_Mode_HF = (1 << 14), + AO_FIFO_Mode_E = (0 << 14), +}; +#define AO_FIFO_Retransmit_Enable _bit13 +#define AO_START1_Disable _bit12 +#define AO_UC_Initial_Load_Source _bit11 +#define AO_UC_Write_Switch _bit10 +#define AO_UI2_Initial_Load_Source _bit9 +#define AO_UI2_Reload_Mode _bit8 +#define AO_UI_Initial_Load_Source _bit7 +#define AO_UI_Reload_Mode(x) (((x) & 0x7) << 4) +#define AO_UI_Write_Switch _bit3 +#define AO_BC_Initial_Load_Source _bit2 +#define AO_BC_Reload_Mode _bit1 +#define AO_BC_Write_Switch _bit0 + +#define AO_UI_Load_A_Register 40 +#define AO_UI_Load_A_Register_High 40 +#define AO_UI_Load_A_Register_Low 41 +#define AO_UI_Load_B_Register 42 +#define AO_UI_Save_Registers 16 +#define AO_BC_Load_A_Register 44 +#define AO_BC_Load_A_Register_High 44 +#define AO_BC_Load_A_Register_Low 45 +#define AO_BC_Load_B_Register 46 +#define AO_BC_Load_B_Register_High 46 +#define AO_BC_Load_B_Register_Low 47 +#define AO_BC_Save_Registers 18 +#define AO_UC_Load_A_Register 48 +#define AO_UC_Load_A_Register_High 48 +#define AO_UC_Load_A_Register_Low 49 +#define AO_UC_Load_B_Register 50 +#define AO_UC_Save_Registers 20 + +#define Clock_and_FOUT_Register 56 +enum Clock_and_FOUT_bits { + FOUT_Enable = _bit15, + FOUT_Timebase_Select = _bit14, + DIO_Serial_Out_Divide_By_2 = _bit13, + Slow_Internal_Time_Divide_By_2 = _bit12, + Slow_Internal_Timebase = _bit11, + G_Source_Divide_By_2 = _bit10, + Clock_To_Board_Divide_By_2 = _bit9, + Clock_To_Board = _bit8, + AI_Output_Divide_By_2 = _bit7, + AI_Source_Divide_By_2 = _bit6, + AO_Output_Divide_By_2 = _bit5, + AO_Source_Divide_By_2 = _bit4, + FOUT_Divider_mask = 0xf +}; +static inline unsigned FOUT_Divider(unsigned divider) +{ + return (divider & FOUT_Divider_mask); +} + +#define IO_Bidirection_Pin_Register 57 +#define RTSI_Trig_Direction_Register 58 +enum RTSI_Trig_Direction_Bits { + Drive_RTSI_Clock_Bit = 0x1, + Use_RTSI_Clock_Bit = 0x2, +}; +static inline unsigned RTSI_Output_Bit(unsigned channel, int is_mseries) +{ + unsigned max_channel; + unsigned base_bit_shift; + if (is_mseries) { + base_bit_shift = 8; + max_channel = 7; + } else { + base_bit_shift = 9; + max_channel = 6; + } + if (channel > max_channel) { + rt_printk("%s: bug, invalid RTSI_channel=%i\n", __FUNCTION__, + channel); + return 0; + } + return 1 << (base_bit_shift + channel); +} + +#define Interrupt_Control_Register 59 +#define Interrupt_B_Enable _bit15 +#define Interrupt_B_Output_Select(x) ((x)<<12) +#define Interrupt_A_Enable _bit11 +#define Interrupt_A_Output_Select(x) ((x)<<8) +#define Pass_Thru_0_Interrupt_Polarity _bit3 +#define Pass_Thru_1_Interrupt_Polarity _bit2 +#define Interrupt_Output_On_3_Pins _bit1 +#define Interrupt_Output_Polarity _bit0 + +#define AI_Output_Control_Register 60 +#define AI_START_Output_Select _bit10 +#define AI_SCAN_IN_PROG_Output_Select(x) (((x) & 0x3) << 8) +#define AI_EXTMUX_CLK_Output_Select(x) (((x) & 0x3) << 6) +#define AI_LOCALMUX_CLK_Output_Select(x) ((x)<<4) +#define AI_SC_TC_Output_Select(x) ((x)<<2) +enum ai_convert_output_selection { + AI_CONVERT_Output_High_Z = 0, + AI_CONVERT_Output_Ground = 1, + AI_CONVERT_Output_Enable_Low = 2, + AI_CONVERT_Output_Enable_High = 3 +}; +static unsigned AI_CONVERT_Output_Select(enum ai_convert_output_selection + selection) +{ + return selection & 0x3; +} + +#define AI_START_STOP_Select_Register 62 +#define AI_START_Polarity _bit15 +#define AI_STOP_Polarity _bit14 +#define AI_STOP_Sync _bit13 +#define AI_STOP_Edge _bit12 +#define AI_STOP_Select(a) (((a) & 0x1f)<<7) +#define AI_START_Sync _bit6 +#define AI_START_Edge _bit5 +#define AI_START_Select(a) ((a) & 0x1f) + +#define AI_Trigger_Select_Register 63 +#define AI_START1_Polarity _bit15 +#define AI_START2_Polarity _bit14 +#define AI_START2_Sync _bit13 +#define AI_START2_Edge _bit12 +#define AI_START2_Select(a) (((a) & 0x1f) << 7) +#define AI_START1_Sync _bit6 +#define AI_START1_Edge _bit5 +#define AI_START1_Select(a) ((a) & 0x1f) + +#define AI_DIV_Load_A_Register 64 + +#define AO_Start_Select_Register 66 +#define AO_UI2_Software_Gate _bit15 +#define AO_UI2_External_Gate_Polarity _bit14 +#define AO_START_Polarity _bit13 +#define AO_AOFREQ_Enable _bit12 +#define AO_UI2_External_Gate_Select(a) (((a) & 0x1f) << 7) +#define AO_START_Sync _bit6 +#define AO_START_Edge _bit5 +#define AO_START_Select(a) ((a) & 0x1f) + +#define AO_Trigger_Select_Register 67 +#define AO_UI2_External_Gate_Enable _bit15 +#define AO_Delayed_START1 _bit14 +#define AO_START1_Polarity _bit13 +#define AO_UI2_Source_Polarity _bit12 +#define AO_UI2_Source_Select(x) (((x)&0x1f)<<7) +#define AO_START1_Sync _bit6 +#define AO_START1_Edge _bit5 +#define AO_START1_Select(x) (((x)&0x1f)<<0) + +#define AO_Mode_3_Register 70 +#define AO_UI2_Switch_Load_Next_TC _bit13 +#define AO_UC_Switch_Load_Every_BC_TC _bit12 +#define AO_Trigger_Length _bit11 +#define AO_Stop_On_Overrun_Error _bit5 +#define AO_Stop_On_BC_TC_Trigger_Error _bit4 +#define AO_Stop_On_BC_TC_Error _bit3 +#define AO_Not_An_UPDATE _bit2 +#define AO_Software_Gate _bit1 +#define AO_Last_Gate_Disable _bit0 /* M Series only */ + +#define Joint_Reset_Register 72 +#define Software_Reset _bit11 +#define AO_Configuration_End _bit9 +#define AI_Configuration_End _bit8 +#define AO_Configuration_Start _bit5 +#define AI_Configuration_Start _bit4 +#define G1_Reset _bit3 +#define G0_Reset _bit2 +#define AO_Reset _bit1 +#define AI_Reset _bit0 + +#define Interrupt_A_Enable_Register 73 +#define Pass_Thru_0_Interrupt_Enable _bit9 +#define G0_Gate_Interrupt_Enable _bit8 +#define AI_FIFO_Interrupt_Enable _bit7 +#define G0_TC_Interrupt_Enable _bit6 +#define AI_Error_Interrupt_Enable _bit5 +#define AI_STOP_Interrupt_Enable _bit4 +#define AI_START_Interrupt_Enable _bit3 +#define AI_START2_Interrupt_Enable _bit2 +#define AI_START1_Interrupt_Enable _bit1 +#define AI_SC_TC_Interrupt_Enable _bit0 + +#define Interrupt_B_Enable_Register 75 +#define Pass_Thru_1_Interrupt_Enable _bit11 +#define G1_Gate_Interrupt_Enable _bit10 +#define G1_TC_Interrupt_Enable _bit9 +#define AO_FIFO_Interrupt_Enable _bit8 +#define AO_UI2_TC_Interrupt_Enable _bit7 +#define AO_UC_TC_Interrupt_Enable _bit6 +#define AO_Error_Interrupt_Enable _bit5 +#define AO_STOP_Interrupt_Enable _bit4 +#define AO_START_Interrupt_Enable _bit3 +#define AO_UPDATE_Interrupt_Enable _bit2 +#define AO_START1_Interrupt_Enable _bit1 +#define AO_BC_TC_Interrupt_Enable _bit0 + +#define Second_IRQ_A_Enable_Register 74 +enum Second_IRQ_A_Enable_Bits { + AI_SC_TC_Second_Irq_Enable = _bit0, + AI_START1_Second_Irq_Enable = _bit1, + AI_START2_Second_Irq_Enable = _bit2, + AI_START_Second_Irq_Enable = _bit3, + AI_STOP_Second_Irq_Enable = _bit4, + AI_Error_Second_Irq_Enable = _bit5, + G0_TC_Second_Irq_Enable = _bit6, + AI_FIFO_Second_Irq_Enable = _bit7, + G0_Gate_Second_Irq_Enable = _bit8, + Pass_Thru_0_Second_Irq_Enable = _bit9 +}; + +#define Second_IRQ_B_Enable_Register 76 +enum Second_IRQ_B_Enable_Bits { + AO_BC_TC_Second_Irq_Enable = _bit0, + AO_START1_Second_Irq_Enable = _bit1, + AO_UPDATE_Second_Irq_Enable = _bit2, + AO_START_Second_Irq_Enable = _bit3, + AO_STOP_Second_Irq_Enable = _bit4, + AO_Error_Second_Irq_Enable = _bit5, + AO_UC_TC_Second_Irq_Enable = _bit6, + AO_UI2_TC_Second_Irq_Enable = _bit7, + AO_FIFO_Second_Irq_Enable = _bit8, + G1_TC_Second_Irq_Enable = _bit9, + G1_Gate_Second_Irq_Enable = _bit10, + Pass_Thru_1_Second_Irq_Enable = _bit11 +}; + +#define AI_Personal_Register 77 +#define AI_SHIFTIN_Pulse_Width _bit15 +#define AI_EOC_Polarity _bit14 +#define AI_SOC_Polarity _bit13 +#define AI_SHIFTIN_Polarity _bit12 +#define AI_CONVERT_Pulse_Timebase _bit11 +#define AI_CONVERT_Pulse_Width _bit10 +#define AI_CONVERT_Original_Pulse _bit9 +#define AI_FIFO_Flags_Polarity _bit8 +#define AI_Overrun_Mode _bit7 +#define AI_EXTMUX_CLK_Pulse_Width _bit6 +#define AI_LOCALMUX_CLK_Pulse_Width _bit5 +#define AI_AIFREQ_Polarity _bit4 + +#define AO_Personal_Register 78 +enum AO_Personal_Bits { + AO_Interval_Buffer_Mode = 1 << 3, + AO_BC_Source_Select = 1 << 4, + AO_UPDATE_Pulse_Width = 1 << 5, + AO_UPDATE_Pulse_Timebase = 1 << 6, + AO_UPDATE_Original_Pulse = 1 << 7, + AO_DMA_PIO_Control = 1 << 8, /* M Series: reserved */ + AO_AOFREQ_Polarity = 1 << 9, /* M Series: reserved */ + AO_FIFO_Enable = 1 << 10, + AO_FIFO_Flags_Polarity = 1 << 11, /* M Series: reserved */ + AO_TMRDACWR_Pulse_Width = 1 << 12, + AO_Fast_CPU = 1 << 13, /* M Series: reserved */ + AO_Number_Of_DAC_Packages = 1 << 14, // 1 for "single" mode, 0 for "dual" + AO_Multiple_DACS_Per_Package = 1 << 15 // m-series only +}; +#define RTSI_Trig_A_Output_Register 79 +#define RTSI_Trig_B_Output_Register 80 +enum RTSI_Trig_B_Output_Bits { + RTSI_Sub_Selection_1_Bit = 0x8000 // not for m-series +}; +static inline unsigned RTSI_Trig_Output_Bits(unsigned rtsi_channel, + unsigned source) +{ + return (source & 0xf) << ((rtsi_channel % 4) * 4); +}; +static inline unsigned RTSI_Trig_Output_Mask(unsigned rtsi_channel) +{ + return 0xf << ((rtsi_channel % 4) * 4); +}; + +// inverse to RTSI_Trig_Output_Bits() +static inline unsigned RTSI_Trig_Output_Source(unsigned rtsi_channel, + unsigned bits) +{ + return (bits >> ((rtsi_channel % 4) * 4)) & 0xf; +}; + +#define RTSI_Board_Register 81 +#define Write_Strobe_0_Register 82 +#define Write_Strobe_1_Register 83 +#define Write_Strobe_2_Register 84 +#define Write_Strobe_3_Register 85 + +#define AO_Output_Control_Register 86 +#define AO_External_Gate_Enable _bit15 +#define AO_External_Gate_Select(x) (((x)&0x1f)<<10) +#define AO_Number_Of_Channels(x) (((x)&0xf)<<6) +#define AO_UPDATE2_Output_Select(x) (((x)&0x3)<<4) +#define AO_External_Gate_Polarity _bit3 +#define AO_UPDATE2_Output_Toggle _bit2 +enum ao_update_output_selection { + AO_Update_Output_High_Z = 0, + AO_Update_Output_Ground = 1, + AO_Update_Output_Enable_Low = 2, + AO_Update_Output_Enable_High = 3 +}; +static unsigned AO_UPDATE_Output_Select(enum ao_update_output_selection + selection) +{ + return selection & 0x3; +} + +#define AI_Mode_3_Register 87 +#define AI_Trigger_Length _bit15 +#define AI_Delay_START _bit14 +#define AI_Software_Gate _bit13 +#define AI_SI_Special_Trigger_Delay _bit12 +#define AI_SI2_Source_Select _bit11 +#define AI_Delayed_START2 _bit10 +#define AI_Delayed_START1 _bit9 +#define AI_External_Gate_Mode _bit8 +#define AI_FIFO_Mode_HF_to_E (3<<6) +#define AI_FIFO_Mode_F (2<<6) +#define AI_FIFO_Mode_HF (1<<6) +#define AI_FIFO_Mode_NE (0<<6) +#define AI_External_Gate_Polarity _bit5 +#define AI_External_Gate_Select(a) ((a) & 0x1f) + +#define G_Autoincrement_Register(a) (68+(a)) +#define G_Command_Register(a) (6+(a)) +#define G_HW_Save_Register(a) (8+(a)*2) +#define G_HW_Save_Register_High(a) (8+(a)*2) +#define G_HW_Save_Register_Low(a) (9+(a)*2) +#define G_Input_Select_Register(a) (36+(a)) +#define G_Load_A_Register(a) (28+(a)*4) +#define G_Load_A_Register_High(a) (28+(a)*4) +#define G_Load_A_Register_Low(a) (29+(a)*4) +#define G_Load_B_Register(a) (30+(a)*4) +#define G_Load_B_Register_High(a) (30+(a)*4) +#define G_Load_B_Register_Low(a) (31+(a)*4) +#define G_Mode_Register(a) (26+(a)) +#define G_Save_Register(a) (12+(a)*2) +#define G_Save_Register_High(a) (12+(a)*2) +#define G_Save_Register_Low(a) (13+(a)*2) +#define G_Status_Register 4 +#define Analog_Trigger_Etc_Register 61 + +/* command register */ +#define G_Disarm_Copy _bit15 /* strobe */ +#define G_Save_Trace_Copy _bit14 +#define G_Arm_Copy _bit13 /* strobe */ +#define G_Bank_Switch_Start _bit10 /* strobe */ +#define G_Little_Big_Endian _bit9 +#define G_Synchronized_Gate _bit8 +#define G_Write_Switch _bit7 +#define G_Up_Down(a) (((a)&0x03)<<5) +#define G_Disarm _bit4 /* strobe */ +#define G_Analog_Trigger_Reset _bit3 /* strobe */ +#define G_Save_Trace _bit1 +#define G_Arm _bit0 /* strobe */ + +/*channel agnostic names for the command register #defines */ +#define G_Bank_Switch_Enable _bit12 +#define G_Bank_Switch_Mode _bit11 +#define G_Load _bit2 /* strobe */ + +/* input select register */ +#define G_Gate_Select(a) (((a)&0x1f)<<7) +#define G_Source_Select(a) (((a)&0x1f)<<2) +#define G_Write_Acknowledges_Irq _bit1 +#define G_Read_Acknowledges_Irq _bit0 + +/* same input select register, but with channel agnostic names */ +#define G_Source_Polarity _bit15 +#define G_Output_Polarity _bit14 +#define G_OR_Gate _bit13 +#define G_Gate_Select_Load_Source _bit12 + +/* mode register */ +#define G_Loading_On_TC _bit12 +#define G_Output_Mode(a) (((a)&0x03)<<8) +#define G_Trigger_Mode_For_Edge_Gate(a) (((a)&0x03)<<3) +#define G_Gating_Mode(a) (((a)&0x03)<<0) + +/* same input mode register, but with channel agnostic names */ +#define G_Load_Source_Select _bit7 +#define G_Reload_Source_Switching _bit15 +#define G_Loading_On_Gate _bit14 +#define G_Gate_Polarity _bit13 + +#define G_Counting_Once(a) (((a)&0x03)<<10) +#define G_Stop_Mode(a) (((a)&0x03)<<5) +#define G_Gate_On_Both_Edges _bit2 + +/* G_Status_Register */ +#define G1_Gate_Error_St _bit15 +#define G0_Gate_Error_St _bit14 +#define G1_TC_Error_St _bit13 +#define G0_TC_Error_St _bit12 +#define G1_No_Load_Between_Gates_St _bit11 +#define G0_No_Load_Between_Gates_St _bit10 +#define G1_Armed_St _bit9 +#define G0_Armed_St _bit8 +#define G1_Stale_Data_St _bit7 +#define G0_Stale_Data_St _bit6 +#define G1_Next_Load_Source_St _bit5 +#define G0_Next_Load_Source_St _bit4 +#define G1_Counting_St _bit3 +#define G0_Counting_St _bit2 +#define G1_Save_St _bit1 +#define G0_Save_St _bit0 + +/* general purpose counter timer */ +#define G_Autoincrement(a) ((a)<<0) + +/*Analog_Trigger_Etc_Register*/ +#define Analog_Trigger_Mode(x) ((x) & 0x7) +#define Analog_Trigger_Enable _bit3 +#define Analog_Trigger_Drive _bit4 +#define GPFO_1_Output_Select _bit7 +#define GPFO_0_Output_Select(a) ((a)<<11) +#define GPFO_0_Output_Enable _bit14 +#define GPFO_1_Output_Enable _bit15 + +/* Additional windowed registers unique to E series */ + +/* 16 bit registers shadowed from DAQ-STC */ +#define Window_Address 0x00 +#define Window_Data 0x02 + +#define Configuration_Memory_Clear 82 +#define ADC_FIFO_Clear 83 +#define DAC_FIFO_Clear 84 + +/* i/o port offsets */ + +/* 8 bit registers */ +#define XXX_Status 0x01 +enum XXX_Status_Bits { + PROMOUT = 0x1, + AI_FIFO_LOWER_NOT_EMPTY = 0x8, +}; +#define Serial_Command 0x0d +#define Misc_Command 0x0f +#define Port_A 0x19 +#define Port_B 0x1b +#define Port_C 0x1d +#define Configuration 0x1f +#define Strobes 0x01 +#define Channel_A_Mode 0x03 +#define Channel_B_Mode 0x05 +#define Channel_C_Mode 0x07 +#define AI_AO_Select 0x09 +enum AI_AO_Select_Bits { + AI_DMA_Select_Shift = 0, + AI_DMA_Select_Mask = 0xf, + AO_DMA_Select_Shift = 4, + AO_DMA_Select_Mask = 0xf << AO_DMA_Select_Shift +}; +#define G0_G1_Select 0x0b +static inline unsigned ni_stc_dma_channel_select_bitfield(unsigned channel) +{ + if (channel < 4) + return 1 << channel; + if (channel == 4) + return 0x3; + if (channel == 5) + return 0x5; + BUG(); + return 0; +} +static inline unsigned GPCT_DMA_Select_Bits(unsigned gpct_index, + unsigned mite_channel) +{ + BUG_ON(gpct_index > 1); + return ni_stc_dma_channel_select_bitfield(mite_channel) << (4 * + gpct_index); +} +static inline unsigned GPCT_DMA_Select_Mask(unsigned gpct_index) +{ + BUG_ON(gpct_index > 1); + return 0xf << (4 * gpct_index); +} + +/* 16 bit registers */ + +#define Configuration_Memory_Low 0x10 +enum Configuration_Memory_Low_Bits { + AI_DITHER = 0x200, + AI_LAST_CHANNEL = 0x8000, +}; +#define Configuration_Memory_High 0x12 +enum Configuration_Memory_High_Bits { + AI_AC_COUPLE = 0x800, + AI_DIFFERENTIAL = 0x1000, + AI_COMMON = 0x2000, + AI_GROUND = 0x3000, +}; +static inline unsigned int AI_CONFIG_CHANNEL(unsigned int channel) +{ + return (channel & 0x3f); +} + +#define ADC_FIFO_Data_Register 0x1c + +#define AO_Configuration 0x16 +#define AO_Bipolar _bit0 +#define AO_Deglitch _bit1 +#define AO_Ext_Ref _bit2 +#define AO_Ground_Ref _bit3 +#define AO_Channel(x) ((x) << 8) + +#define DAC_FIFO_Data 0x1e +#define DAC0_Direct_Data 0x18 +#define DAC1_Direct_Data 0x1a + +/* 611x registers (these boards differ from the e-series) */ + +#define Magic_611x 0x19 /* w8 (new) */ +#define Calibration_Channel_Select_611x 0x1a /* w16 (new) */ +#define ADC_FIFO_Data_611x 0x1c /* r32 (incompatible) */ +#define AI_FIFO_Offset_Load_611x 0x05 /* r8 (new) */ +#define DAC_FIFO_Data_611x 0x14 /* w32 (incompatible) */ +#define Cal_Gain_Select_611x 0x05 /* w8 (new) */ + +#define AO_Window_Address_611x 0x18 +#define AO_Window_Data_611x 0x1e + +/* 6143 registers */ +#define Magic_6143 0x19 /* w8 */ +#define G0G1_DMA_Select_6143 0x0B /* w8 */ +#define PipelineDelay_6143 0x1f /* w8 */ +#define EOC_Set_6143 0x1D /* w8 */ +#define AIDMA_Select_6143 0x09 /* w8 */ +#define AIFIFO_Data_6143 0x8C /* w32 */ +#define AIFIFO_Flag_6143 0x84 /* w32 */ +#define AIFIFO_Control_6143 0x88 /* w32 */ +#define AIFIFO_Status_6143 0x88 /* w32 */ +#define AIFIFO_DMAThreshold_6143 0x90 /* w32 */ +#define AIFIFO_Words_Available_6143 0x94 /* w32 */ + +#define Calibration_Channel_6143 0x42 /* w16 */ +#define Calibration_LowTime_6143 0x20 /* w16 */ +#define Calibration_HighTime_6143 0x22 /* w16 */ +#define Relay_Counter_Load_Val__6143 0x4C /* w32 */ +#define Signature_6143 0x50 /* w32 */ +#define Release_Date_6143 0x54 /* w32 */ +#define Release_Oldest_Date_6143 0x58 /* w32 */ + +#define Calibration_Channel_6143_RelayOn 0x8000 /* Calibration relay switch On */ +#define Calibration_Channel_6143_RelayOff 0x4000 /* Calibration relay switch Off */ +#define Calibration_Channel_Gnd_Gnd 0x00 /* Offset Calibration */ +#define Calibration_Channel_2v5_Gnd 0x02 /* 2.5V Reference */ +#define Calibration_Channel_Pwm_Gnd 0x05 /* +/- 5V Self Cal */ +#define Calibration_Channel_2v5_Pwm 0x0a /* PWM Calibration */ +#define Calibration_Channel_Pwm_Pwm 0x0d /* CMRR */ +#define Calibration_Channel_Gnd_Pwm 0x0e /* PWM Calibration */ + +/* 671x, 611x registers */ + +/* 671xi, 611x windowed ao registers */ +enum windowed_regs_67xx_61xx { + AO_Immediate_671x = 0x11, /* W 16 */ + AO_Timed_611x = 0x10, /* W 16 */ + AO_FIFO_Offset_Load_611x = 0x13, /* W32 */ + AO_Later_Single_Point_Updates = 0x14, /* W 16 */ + AO_Waveform_Generation_611x = 0x15, /* W 16 */ + AO_Misc_611x = 0x16, /* W 16 */ + AO_Calibration_Channel_Select_67xx = 0x17, /* W 16 */ + AO_Configuration_2_67xx = 0x18, /* W 16 */ + CAL_ADC_Command_67xx = 0x19, /* W 8 */ + CAL_ADC_Status_67xx = 0x1a, /* R 8 */ + CAL_ADC_Data_67xx = 0x1b, /* R 16 */ + CAL_ADC_Config_Data_High_Word_67xx = 0x1c, /* RW 16 */ + CAL_ADC_Config_Data_Low_Word_67xx = 0x1d, /* RW 16 */ +}; +static inline unsigned int DACx_Direct_Data_671x(int channel) +{ + return channel; +} +enum AO_Misc_611x_Bits { + CLEAR_WG = 1, +}; +enum cs5529_configuration_bits { + CSCFG_CAL_CONTROL_MASK = 0x7, + CSCFG_SELF_CAL_OFFSET = 0x1, + CSCFG_SELF_CAL_GAIN = 0x2, + CSCFG_SELF_CAL_OFFSET_GAIN = 0x3, + CSCFG_SYSTEM_CAL_OFFSET = 0x5, + CSCFG_SYSTEM_CAL_GAIN = 0x6, + CSCFG_DONE = 1 << 3, + CSCFG_POWER_SAVE_SELECT = 1 << 4, + CSCFG_PORT_MODE = 1 << 5, + CSCFG_RESET_VALID = 1 << 6, + CSCFG_RESET = 1 << 7, + CSCFG_UNIPOLAR = 1 << 12, + CSCFG_WORD_RATE_2180_CYCLES = 0x0 << 13, + CSCFG_WORD_RATE_1092_CYCLES = 0x1 << 13, + CSCFG_WORD_RATE_532_CYCLES = 0x2 << 13, + CSCFG_WORD_RATE_388_CYCLES = 0x3 << 13, + CSCFG_WORD_RATE_324_CYCLES = 0x4 << 13, + CSCFG_WORD_RATE_17444_CYCLES = 0x5 << 13, + CSCFG_WORD_RATE_8724_CYCLES = 0x6 << 13, + CSCFG_WORD_RATE_4364_CYCLES = 0x7 << 13, + CSCFG_WORD_RATE_MASK = 0x7 << 13, + CSCFG_LOW_POWER = 1 << 16, +}; +static inline unsigned int CS5529_CONFIG_DOUT(int output) +{ + return 1 << (18 + output); +} +static inline unsigned int CS5529_CONFIG_AOUT(int output) +{ + return 1 << (22 + output); +} +enum cs5529_command_bits { + CSCMD_POWER_SAVE = 0x1, + CSCMD_REGISTER_SELECT_MASK = 0xe, + CSCMD_OFFSET_REGISTER = 0x0, + CSCMD_GAIN_REGISTER = 0x2, + CSCMD_CONFIG_REGISTER = 0x4, + CSCMD_READ = 0x10, + CSCMD_CONTINUOUS_CONVERSIONS = 0x20, + CSCMD_SINGLE_CONVERSION = 0x40, + CSCMD_COMMAND = 0x80, +}; +enum cs5529_status_bits { + CSS_ADC_BUSY = 0x1, + CSS_OSC_DETECT = 0x2, /* indicates adc error */ + CSS_OVERRANGE = 0x4, +}; +#define SerDacLd(x) (0x08<<(x)) + +/* + This is stuff unique to the NI E series drivers, + but I thought I'd put it here anyway. +*/ + +enum { ai_gain_16 = + 0, ai_gain_8, ai_gain_14, ai_gain_4, ai_gain_611x, ai_gain_622x, + ai_gain_628x, ai_gain_6143 }; +enum caldac_enum { caldac_none = 0, mb88341, dac8800, dac8043, ad8522, + ad8804, ad8842, ad8804_debug +}; +enum ni_reg_type { + ni_reg_normal = 0x0, + ni_reg_611x = 0x1, + ni_reg_6711 = 0x2, + ni_reg_6713 = 0x4, + ni_reg_67xx_mask = 0x6, + ni_reg_6xxx_mask = 0x7, + ni_reg_622x = 0x8, + ni_reg_625x = 0x10, + ni_reg_628x = 0x18, + ni_reg_m_series_mask = 0x18, + ni_reg_6143 = 0x20 +}; + +static const struct comedi_lrange range_ni_E_ao_ext; + +enum m_series_register_offsets { + M_Offset_CDIO_DMA_Select = 0x7, // write + M_Offset_SCXI_Status = 0x7, // read + M_Offset_AI_AO_Select = 0x9, // write, same offset as e-series + M_Offset_SCXI_Serial_Data_In = 0x9, // read + M_Offset_G0_G1_Select = 0xb, // write, same offset as e-series + M_Offset_Misc_Command = 0xf, + M_Offset_SCXI_Serial_Data_Out = 0x11, + M_Offset_SCXI_Control = 0x13, + M_Offset_SCXI_Output_Enable = 0x15, + M_Offset_AI_FIFO_Data = 0x1c, + M_Offset_Static_Digital_Output = 0x24, // write + M_Offset_Static_Digital_Input = 0x24, // read + M_Offset_DIO_Direction = 0x28, + M_Offset_Cal_PWM = 0x40, + M_Offset_AI_Config_FIFO_Data = 0x5e, + M_Offset_Interrupt_C_Enable = 0x88, // write + M_Offset_Interrupt_C_Status = 0x88, // read + M_Offset_Analog_Trigger_Control = 0x8c, + M_Offset_AO_Serial_Interrupt_Enable = 0xa0, + M_Offset_AO_Serial_Interrupt_Ack = 0xa1, // write + M_Offset_AO_Serial_Interrupt_Status = 0xa1, // read + M_Offset_AO_Calibration = 0xa3, + M_Offset_AO_FIFO_Data = 0xa4, + M_Offset_PFI_Filter = 0xb0, + M_Offset_RTSI_Filter = 0xb4, + M_Offset_SCXI_Legacy_Compatibility = 0xbc, + M_Offset_Interrupt_A_Ack = 0x104, // write + M_Offset_AI_Status_1 = 0x104, // read + M_Offset_Interrupt_B_Ack = 0x106, // write + M_Offset_AO_Status_1 = 0x106, // read + M_Offset_AI_Command_2 = 0x108, // write + M_Offset_G01_Status = 0x108, // read + M_Offset_AO_Command_2 = 0x10a, + M_Offset_AO_Status_2 = 0x10c, // read + M_Offset_G0_Command = 0x10c, // write + M_Offset_G1_Command = 0x10e, // write + M_Offset_G0_HW_Save = 0x110, + M_Offset_G0_HW_Save_High = 0x110, + M_Offset_AI_Command_1 = 0x110, + M_Offset_G0_HW_Save_Low = 0x112, + M_Offset_AO_Command_1 = 0x112, + M_Offset_G1_HW_Save = 0x114, + M_Offset_G1_HW_Save_High = 0x114, + M_Offset_G1_HW_Save_Low = 0x116, + M_Offset_AI_Mode_1 = 0x118, + M_Offset_G0_Save = 0x118, + M_Offset_G0_Save_High = 0x118, + M_Offset_AI_Mode_2 = 0x11a, + M_Offset_G0_Save_Low = 0x11a, + M_Offset_AI_SI_Load_A = 0x11c, + M_Offset_G1_Save = 0x11c, + M_Offset_G1_Save_High = 0x11c, + M_Offset_G1_Save_Low = 0x11e, + M_Offset_AI_SI_Load_B = 0x120, // write + M_Offset_AO_UI_Save = 0x120, // read + M_Offset_AI_SC_Load_A = 0x124, // write + M_Offset_AO_BC_Save = 0x124, // read + M_Offset_AI_SC_Load_B = 0x128, // write + M_Offset_AO_UC_Save = 0x128, //read + M_Offset_AI_SI2_Load_A = 0x12c, + M_Offset_AI_SI2_Load_B = 0x130, + M_Offset_G0_Mode = 0x134, + M_Offset_G1_Mode = 0x136, // write + M_Offset_Joint_Status_1 = 0x136, // read + M_Offset_G0_Load_A = 0x138, + M_Offset_Joint_Status_2 = 0x13a, + M_Offset_G0_Load_B = 0x13c, + M_Offset_G1_Load_A = 0x140, + M_Offset_G1_Load_B = 0x144, + M_Offset_G0_Input_Select = 0x148, + M_Offset_G1_Input_Select = 0x14a, + M_Offset_AO_Mode_1 = 0x14c, + M_Offset_AO_Mode_2 = 0x14e, + M_Offset_AO_UI_Load_A = 0x150, + M_Offset_AO_UI_Load_B = 0x154, + M_Offset_AO_BC_Load_A = 0x158, + M_Offset_AO_BC_Load_B = 0x15c, + M_Offset_AO_UC_Load_A = 0x160, + M_Offset_AO_UC_Load_B = 0x164, + M_Offset_Clock_and_FOUT = 0x170, + M_Offset_IO_Bidirection_Pin = 0x172, + M_Offset_RTSI_Trig_Direction = 0x174, + M_Offset_Interrupt_Control = 0x176, + M_Offset_AI_Output_Control = 0x178, + M_Offset_Analog_Trigger_Etc = 0x17a, + M_Offset_AI_START_STOP_Select = 0x17c, + M_Offset_AI_Trigger_Select = 0x17e, + M_Offset_AI_SI_Save = 0x180, // read + M_Offset_AI_DIV_Load_A = 0x180, // write + M_Offset_AI_SC_Save = 0x184, // read + M_Offset_AO_Start_Select = 0x184, // write + M_Offset_AO_Trigger_Select = 0x186, + M_Offset_AO_Mode_3 = 0x18c, + M_Offset_G0_Autoincrement = 0x188, + M_Offset_G1_Autoincrement = 0x18a, + M_Offset_Joint_Reset = 0x190, + M_Offset_Interrupt_A_Enable = 0x192, + M_Offset_Interrupt_B_Enable = 0x196, + M_Offset_AI_Personal = 0x19a, + M_Offset_AO_Personal = 0x19c, + M_Offset_RTSI_Trig_A_Output = 0x19e, + M_Offset_RTSI_Trig_B_Output = 0x1a0, + M_Offset_RTSI_Shared_MUX = 0x1a2, + M_Offset_AO_Output_Control = 0x1ac, + M_Offset_AI_Mode_3 = 0x1ae, + M_Offset_Configuration_Memory_Clear = 0x1a4, + M_Offset_AI_FIFO_Clear = 0x1a6, + M_Offset_AO_FIFO_Clear = 0x1a8, + M_Offset_G0_Counting_Mode = 0x1b0, + M_Offset_G1_Counting_Mode = 0x1b2, + M_Offset_G0_Second_Gate = 0x1b4, + M_Offset_G1_Second_Gate = 0x1b6, + M_Offset_G0_DMA_Config = 0x1b8, // write + M_Offset_G0_DMA_Status = 0x1b8, // read + M_Offset_G1_DMA_Config = 0x1ba, // write + M_Offset_G1_DMA_Status = 0x1ba, // read + M_Offset_G0_MSeries_ABZ = 0x1c0, + M_Offset_G1_MSeries_ABZ = 0x1c2, + M_Offset_Clock_and_Fout2 = 0x1c4, + M_Offset_PLL_Control = 0x1c6, + M_Offset_PLL_Status = 0x1c8, + M_Offset_PFI_Output_Select_1 = 0x1d0, + M_Offset_PFI_Output_Select_2 = 0x1d2, + M_Offset_PFI_Output_Select_3 = 0x1d4, + M_Offset_PFI_Output_Select_4 = 0x1d6, + M_Offset_PFI_Output_Select_5 = 0x1d8, + M_Offset_PFI_Output_Select_6 = 0x1da, + M_Offset_PFI_DI = 0x1dc, + M_Offset_PFI_DO = 0x1de, + M_Offset_AI_Config_FIFO_Bypass = 0x218, + M_Offset_SCXI_DIO_Enable = 0x21c, + M_Offset_CDI_FIFO_Data = 0x220, // read + M_Offset_CDO_FIFO_Data = 0x220, // write + M_Offset_CDIO_Status = 0x224, // read + M_Offset_CDIO_Command = 0x224, // write + M_Offset_CDI_Mode = 0x228, + M_Offset_CDO_Mode = 0x22c, + M_Offset_CDI_Mask_Enable = 0x230, + M_Offset_CDO_Mask_Enable = 0x234, +}; +static inline int M_Offset_AO_Waveform_Order(int channel) +{ + return 0xc2 + 0x4 * channel; +}; +static inline int M_Offset_AO_Config_Bank(int channel) +{ + return 0xc3 + 0x4 * channel; +}; +static inline int M_Offset_DAC_Direct_Data(int channel) +{ + return 0xc0 + 0x4 * channel; +} +static inline int M_Offset_Gen_PWM(int channel) +{ + return 0x44 + 0x2 * channel; +} +static inline int M_Offset_Static_AI_Control(int i) +{ + int offset[] = { + 0x64, + 0x261, + 0x262, + 0x263, + }; + if (((unsigned)i) >= sizeof(offset) / sizeof(offset[0])) { + rt_printk("%s: invalid channel=%i\n", __FUNCTION__, i); + return offset[0]; + } + return offset[i]; +}; +static inline int M_Offset_AO_Reference_Attenuation(int channel) +{ + int offset[] = { + 0x264, + 0x265, + 0x266, + 0x267 + }; + if (((unsigned)channel) >= sizeof(offset) / sizeof(offset[0])) { + rt_printk("%s: invalid channel=%i\n", __FUNCTION__, channel); + return offset[0]; + } + return offset[channel]; +}; +static inline unsigned M_Offset_PFI_Output_Select(unsigned n) +{ + if (n < 1 || n > NUM_PFI_OUTPUT_SELECT_REGS) { + rt_printk("%s: invalid pfi output select register=%i\n", + __FUNCTION__, n); + return M_Offset_PFI_Output_Select_1; + } + return M_Offset_PFI_Output_Select_1 + (n - 1) * 2; +} + +enum MSeries_AI_Config_FIFO_Data_Bits { + MSeries_AI_Config_Channel_Type_Mask = 0x7 << 6, + MSeries_AI_Config_Channel_Type_Calibration_Bits = 0x0, + MSeries_AI_Config_Channel_Type_Differential_Bits = 0x1 << 6, + MSeries_AI_Config_Channel_Type_Common_Ref_Bits = 0x2 << 6, + MSeries_AI_Config_Channel_Type_Ground_Ref_Bits = 0x3 << 6, + MSeries_AI_Config_Channel_Type_Aux_Bits = 0x5 << 6, + MSeries_AI_Config_Channel_Type_Ghost_Bits = 0x7 << 6, + MSeries_AI_Config_Polarity_Bit = 0x1000, // 0 for 2's complement encoding + MSeries_AI_Config_Dither_Bit = 0x2000, + MSeries_AI_Config_Last_Channel_Bit = 0x4000, +}; +static inline unsigned MSeries_AI_Config_Channel_Bits(unsigned channel) +{ + return channel & 0xf; +} +static inline unsigned MSeries_AI_Config_Bank_Bits(enum ni_reg_type reg_type, + unsigned channel) +{ + unsigned bits = channel & 0x30; + if (reg_type == ni_reg_622x) { + if (channel & 0x40) + bits |= 0x400; + } + return bits; +} +static inline unsigned MSeries_AI_Config_Gain_Bits(unsigned range) +{ + return (range & 0x7) << 9; +} + +enum MSeries_Clock_and_Fout2_Bits { + MSeries_PLL_In_Source_Select_RTSI0_Bits = 0xb, + MSeries_PLL_In_Source_Select_Star_Trigger_Bits = 0x14, + MSeries_PLL_In_Source_Select_RTSI7_Bits = 0x1b, + MSeries_PLL_In_Source_Select_PXI_Clock10 = 0x1d, + MSeries_PLL_In_Source_Select_Mask = 0x1f, + MSeries_Timebase1_Select_Bit = 0x20, // use PLL for timebase 1 + MSeries_Timebase3_Select_Bit = 0x40, // use PLL for timebase 3 + /* use 10MHz instead of 20MHz for RTSI clock frequency. Appears + to have no effect, at least on pxi-6281, which always uses + 20MHz rtsi clock frequency */ + MSeries_RTSI_10MHz_Bit = 0x80 +}; +static inline unsigned MSeries_PLL_In_Source_Select_RTSI_Bits(unsigned + RTSI_channel) +{ + if (RTSI_channel > 7) { + rt_printk("%s: bug, invalid RTSI_channel=%i\n", __FUNCTION__, + RTSI_channel); + return 0; + } + if (RTSI_channel == 7) + return MSeries_PLL_In_Source_Select_RTSI7_Bits; + else + return MSeries_PLL_In_Source_Select_RTSI0_Bits + RTSI_channel; +} + +enum MSeries_PLL_Control_Bits { + MSeries_PLL_Enable_Bit = 0x1000, + MSeries_PLL_VCO_Mode_200_325MHz_Bits = 0x0, + MSeries_PLL_VCO_Mode_175_225MHz_Bits = 0x2000, + MSeries_PLL_VCO_Mode_100_225MHz_Bits = 0x4000, + MSeries_PLL_VCO_Mode_75_150MHz_Bits = 0x6000, +}; +static inline unsigned MSeries_PLL_Divisor_Bits(unsigned divisor) +{ + static const unsigned max_divisor = 0x10; + if (divisor < 1 || divisor > max_divisor) { + rt_printk("%s: bug, invalid divisor=%i\n", __FUNCTION__, + divisor); + return 0; + } + return (divisor & 0xf) << 8; +} +static inline unsigned MSeries_PLL_Multiplier_Bits(unsigned multiplier) +{ + static const unsigned max_multiplier = 0x100; + if (multiplier < 1 || multiplier > max_multiplier) { + rt_printk("%s: bug, invalid multiplier=%i\n", __FUNCTION__, + multiplier); + return 0; + } + return multiplier & 0xff; +} + +enum MSeries_PLL_Status { + MSeries_PLL_Locked_Bit = 0x1 +}; + +enum MSeries_AI_Config_FIFO_Bypass_Bits { + MSeries_AI_Bypass_Channel_Mask = 0x7, + MSeries_AI_Bypass_Bank_Mask = 0x78, + MSeries_AI_Bypass_Cal_Sel_Pos_Mask = 0x380, + MSeries_AI_Bypass_Cal_Sel_Neg_Mask = 0x1c00, + MSeries_AI_Bypass_Mode_Mux_Mask = 0x6000, + MSeries_AO_Bypass_AO_Cal_Sel_Mask = 0x38000, + MSeries_AI_Bypass_Gain_Mask = 0x1c0000, + MSeries_AI_Bypass_Dither_Bit = 0x200000, + MSeries_AI_Bypass_Polarity_Bit = 0x400000, // 0 for 2's complement encoding + MSeries_AI_Bypass_Config_FIFO_Bit = 0x80000000 +}; +static inline unsigned MSeries_AI_Bypass_Cal_Sel_Pos_Bits(int + calibration_source) +{ + return (calibration_source << 7) & MSeries_AI_Bypass_Cal_Sel_Pos_Mask; +} +static inline unsigned MSeries_AI_Bypass_Cal_Sel_Neg_Bits(int + calibration_source) +{ + return (calibration_source << 10) & MSeries_AI_Bypass_Cal_Sel_Pos_Mask; +} +static inline unsigned MSeries_AI_Bypass_Gain_Bits(int gain) +{ + return (gain << 18) & MSeries_AI_Bypass_Gain_Mask; +} + +enum MSeries_AO_Config_Bank_Bits { + MSeries_AO_DAC_Offset_Select_Mask = 0x7, + MSeries_AO_DAC_Offset_0V_Bits = 0x0, + MSeries_AO_DAC_Offset_5V_Bits = 0x1, + MSeries_AO_DAC_Reference_Mask = 0x38, + MSeries_AO_DAC_Reference_10V_Internal_Bits = 0x0, + MSeries_AO_DAC_Reference_5V_Internal_Bits = 0x8, + MSeries_AO_Update_Timed_Bit = 0x40, + MSeries_AO_Bipolar_Bit = 0x80 // turns on 2's complement encoding +}; + +enum MSeries_AO_Reference_Attenuation_Bits { + MSeries_Attenuate_x5_Bit = 0x1 +}; + +static inline unsigned MSeries_Cal_PWM_High_Time_Bits(unsigned count) +{ + return (count << 16) & 0xffff0000; +} + +static inline unsigned MSeries_Cal_PWM_Low_Time_Bits(unsigned count) +{ + return count & 0xffff; +} + +static inline unsigned MSeries_PFI_Output_Select_Mask(unsigned channel) +{ + return 0x1f << (channel % 3) * 5; +}; +static inline unsigned MSeries_PFI_Output_Select_Bits(unsigned channel, + unsigned source) +{ + return (source & 0x1f) << ((channel % 3) * 5); +}; + +// inverse to MSeries_PFI_Output_Select_Bits +static inline unsigned MSeries_PFI_Output_Select_Source(unsigned channel, + unsigned bits) +{ + return (bits >> ((channel % 3) * 5)) & 0x1f; +}; + +enum MSeries_Gi_DMA_Config_Bits { + Gi_DMA_BankSW_Error_Bit = 0x10, + Gi_DMA_Reset_Bit = 0x8, + Gi_DMA_Int_Enable_Bit = 0x4, + Gi_DMA_Write_Bit = 0x2, + Gi_DMA_Enable_Bit = 0x1, +}; + +static inline unsigned MSeries_PFI_Filter_Select_Mask(unsigned channel) +{ + return 0x3 << (channel * 2); +} +static inline unsigned MSeries_PFI_Filter_Select_Bits(unsigned channel, + unsigned filter) +{ + return (filter << (channel * + 2)) & MSeries_PFI_Filter_Select_Mask(channel); +} + +enum CDIO_DMA_Select_Bits { + CDI_DMA_Select_Shift = 0, + CDI_DMA_Select_Mask = 0xf, + CDO_DMA_Select_Shift = 4, + CDO_DMA_Select_Mask = 0xf << CDO_DMA_Select_Shift +}; + +enum CDIO_Status_Bits { + CDO_FIFO_Empty_Bit = 0x1, + CDO_FIFO_Full_Bit = 0x2, + CDO_FIFO_Request_Bit = 0x4, + CDO_Overrun_Bit = 0x8, + CDO_Underflow_Bit = 0x10, + CDI_FIFO_Empty_Bit = 0x10000, + CDI_FIFO_Full_Bit = 0x20000, + CDI_FIFO_Request_Bit = 0x40000, + CDI_Overrun_Bit = 0x80000, + CDI_Overflow_Bit = 0x100000 +}; + +enum CDIO_Command_Bits { + CDO_Disarm_Bit = 0x1, + CDO_Arm_Bit = 0x2, + CDI_Disarm_Bit = 0x4, + CDI_Arm_Bit = 0x8, + CDO_Reset_Bit = 0x10, + CDI_Reset_Bit = 0x20, + CDO_Error_Interrupt_Enable_Set_Bit = 0x40, + CDO_Error_Interrupt_Enable_Clear_Bit = 0x80, + CDI_Error_Interrupt_Enable_Set_Bit = 0x100, + CDI_Error_Interrupt_Enable_Clear_Bit = 0x200, + CDO_FIFO_Request_Interrupt_Enable_Set_Bit = 0x400, + CDO_FIFO_Request_Interrupt_Enable_Clear_Bit = 0x800, + CDI_FIFO_Request_Interrupt_Enable_Set_Bit = 0x1000, + CDI_FIFO_Request_Interrupt_Enable_Clear_Bit = 0x2000, + CDO_Error_Interrupt_Confirm_Bit = 0x4000, + CDI_Error_Interrupt_Confirm_Bit = 0x8000, + CDO_Empty_FIFO_Interrupt_Enable_Set_Bit = 0x10000, + CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit = 0x20000, + CDO_SW_Update_Bit = 0x80000, + CDI_SW_Update_Bit = 0x100000 +}; + +enum CDI_Mode_Bits { + CDI_Sample_Source_Select_Mask = 0x3f, + CDI_Halt_On_Error_Bit = 0x200, + CDI_Polarity_Bit = 0x400, // sample clock on falling edge + CDI_FIFO_Mode_Bit = 0x800, // set for half full mode, clear for not empty mode + CDI_Data_Lane_Mask = 0x3000, // data lanes specify which dio channels map to byte or word accesses to the dio fifos + CDI_Data_Lane_0_15_Bits = 0x0, + CDI_Data_Lane_16_31_Bits = 0x1000, + CDI_Data_Lane_0_7_Bits = 0x0, + CDI_Data_Lane_8_15_Bits = 0x1000, + CDI_Data_Lane_16_23_Bits = 0x2000, + CDI_Data_Lane_24_31_Bits = 0x3000 +}; + +enum CDO_Mode_Bits { + CDO_Sample_Source_Select_Mask = 0x3f, + CDO_Retransmit_Bit = 0x100, + CDO_Halt_On_Error_Bit = 0x200, + CDO_Polarity_Bit = 0x400, // sample clock on falling edge + CDO_FIFO_Mode_Bit = 0x800, // set for half full mode, clear for not full mode + CDO_Data_Lane_Mask = 0x3000, // data lanes specify which dio channels map to byte or word accesses to the dio fifos + CDO_Data_Lane_0_15_Bits = 0x0, + CDO_Data_Lane_16_31_Bits = 0x1000, + CDO_Data_Lane_0_7_Bits = 0x0, + CDO_Data_Lane_8_15_Bits = 0x1000, + CDO_Data_Lane_16_23_Bits = 0x2000, + CDO_Data_Lane_24_31_Bits = 0x3000 +}; + +enum Interrupt_C_Enable_Bits { + Interrupt_Group_C_Enable_Bit = 0x1 +}; + +enum Interrupt_C_Status_Bits { + Interrupt_Group_C_Status_Bit = 0x1 +}; + +#define M_SERIES_EEPROM_SIZE 1024 + +typedef struct ni_board_struct { + int device_id; + int isapnp_id; + char *name; + + int n_adchan; + int adbits; + + int ai_fifo_depth; + unsigned int alwaysdither:1; + int gainlkup; + int ai_speed; + + int n_aochan; + int aobits; + int ao_fifo_depth; + const struct comedi_lrange *ao_range_table; + unsigned ao_speed; + + unsigned num_p0_dio_channels; + + int reg_type; + unsigned int ao_unipolar:1; + unsigned int has_8255:1; + unsigned int has_analog_trig:1; + + enum caldac_enum caldac[3]; +} ni_board; + +#define n_ni_boards (sizeof(ni_boards)/sizeof(ni_board)) + +#define boardtype (*(ni_board *)dev->board_ptr) + +#define MAX_N_AO_CHAN 8 +#define NUM_GPCT 2 + +#define NI_PRIVATE_COMMON \ + uint16_t (*stc_readw)(struct comedi_device *dev, int register); \ + uint32_t (*stc_readl)(struct comedi_device *dev, int register); \ + void (*stc_writew)(struct comedi_device *dev, uint16_t value, int register); \ + void (*stc_writel)(struct comedi_device *dev, uint32_t value, int register); \ + \ + unsigned short dio_output; \ + unsigned short dio_control; \ + int ao0p,ao1p; \ + int lastchan; \ + int last_do; \ + int rt_irq; \ + int irqmask; \ + int aimode; \ + int ai_continuous; \ + int blocksize; \ + int n_left; \ + unsigned int ai_calib_source; \ + unsigned int ai_calib_source_enabled; \ + spinlock_t window_lock; \ + spinlock_t soft_reg_copy_lock; \ + spinlock_t mite_channel_lock; \ + \ + int changain_state; \ + unsigned int changain_spec; \ + \ + unsigned int caldac_maxdata_list[MAX_N_CALDACS]; \ + unsigned short ao[MAX_N_AO_CHAN]; \ + unsigned short caldacs[MAX_N_CALDACS]; \ + \ + unsigned short ai_cmd2; \ + \ + unsigned short ao_conf[MAX_N_AO_CHAN]; \ + unsigned short ao_mode1; \ + unsigned short ao_mode2; \ + unsigned short ao_mode3; \ + unsigned short ao_cmd1; \ + unsigned short ao_cmd2; \ + unsigned short ao_cmd3; \ + unsigned short ao_trigger_select; \ + \ + struct ni_gpct_device *counter_dev; \ + unsigned short an_trig_etc_reg; \ + \ + unsigned ai_offset[512]; \ + \ + unsigned long serial_interval_ns; \ + unsigned char serial_hw_mode; \ + unsigned short clock_and_fout; \ + unsigned short clock_and_fout2; \ + \ + unsigned short int_a_enable_reg; \ + unsigned short int_b_enable_reg; \ + unsigned short io_bidirection_pin_reg; \ + unsigned short rtsi_trig_direction_reg; \ + unsigned short rtsi_trig_a_output_reg; \ + unsigned short rtsi_trig_b_output_reg; \ + unsigned short pfi_output_select_reg[NUM_PFI_OUTPUT_SELECT_REGS]; \ + unsigned short ai_ao_select_reg; \ + unsigned short g0_g1_select_reg; \ + unsigned short cdio_dma_select_reg; \ + \ + unsigned clock_ns; \ + unsigned clock_source; \ + \ + unsigned short atrig_mode; \ + unsigned short atrig_high; \ + unsigned short atrig_low; \ + \ + unsigned short pwm_up_count; \ + unsigned short pwm_down_count; \ + \ + short ai_fifo_buffer[0x2000]; \ + uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE]; \ + uint32_t serial_number; \ + \ + struct mite_struct *mite; \ + struct mite_channel *ai_mite_chan; \ + struct mite_channel *ao_mite_chan;\ + struct mite_channel *cdo_mite_chan;\ + struct mite_dma_descriptor_ring *ai_mite_ring; \ + struct mite_dma_descriptor_ring *ao_mite_ring; \ + struct mite_dma_descriptor_ring *cdo_mite_ring; \ + struct mite_dma_descriptor_ring *gpct_mite_ring[NUM_GPCT]; + +#endif /* _COMEDI_NI_STC_H */ diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c new file mode 100644 index 000000000000..05a957540398 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -0,0 +1,1691 @@ +/* + comedi/drivers/ni_tio.c + Support for NI general purpose counters + + Copyright (C) 2006 Frank Mori Hess + + 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: ni_tio +Description: National Instruments general purpose counters +Devices: +Author: J.P. Mellor , + Herman.Bruyninckx@mech.kuleuven.ac.be, + Wim.Meeussen@mech.kuleuven.ac.be, + Klaas.Gadeyne@mech.kuleuven.ac.be, + Frank Mori Hess +Updated: Thu Nov 16 09:50:32 EST 2006 +Status: works + +This module is not used directly by end-users. Rather, it +is used by other drivers (for example ni_660x and ni_pcimio) +to provide support for NI's general purpose counters. It was +originally based on the counter code from ni_660x.c and +ni_mio_common.c. + +References: +DAQ 660x Register-Level Programmer Manual (NI 370505A-01) +DAQ 6601/6602 User Manual (NI 322137B-01) +340934b.pdf DAQ-STC reference manual + +*/ +/* +TODO: + Support use of both banks X and Y +*/ + +#include "ni_tio_internal.h" + +static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, + unsigned generic_clock_source); +static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter); + +MODULE_AUTHOR("Comedi "); +MODULE_DESCRIPTION("Comedi support for NI general-purpose counters"); +MODULE_LICENSE("GPL"); + +static inline enum Gi_Counting_Mode_Reg_Bits Gi_Alternate_Sync_Bit(enum + ni_gpct_variant variant) +{ + switch (variant) { + case ni_gpct_variant_e_series: + return 0; + break; + case ni_gpct_variant_m_series: + return Gi_M_Series_Alternate_Sync_Bit; + break; + case ni_gpct_variant_660x: + return Gi_660x_Alternate_Sync_Bit; + break; + default: + BUG(); + break; + } + return 0; +} +static inline enum Gi_Counting_Mode_Reg_Bits Gi_Prescale_X2_Bit(enum + ni_gpct_variant variant) +{ + switch (variant) { + case ni_gpct_variant_e_series: + return 0; + break; + case ni_gpct_variant_m_series: + return Gi_M_Series_Prescale_X2_Bit; + break; + case ni_gpct_variant_660x: + return Gi_660x_Prescale_X2_Bit; + break; + default: + BUG(); + break; + } + return 0; +} +static inline enum Gi_Counting_Mode_Reg_Bits Gi_Prescale_X8_Bit(enum + ni_gpct_variant variant) +{ + switch (variant) { + case ni_gpct_variant_e_series: + return 0; + break; + case ni_gpct_variant_m_series: + return Gi_M_Series_Prescale_X8_Bit; + break; + case ni_gpct_variant_660x: + return Gi_660x_Prescale_X8_Bit; + break; + default: + BUG(); + break; + } + return 0; +} +static inline enum Gi_Counting_Mode_Reg_Bits Gi_HW_Arm_Select_Mask(enum + ni_gpct_variant variant) +{ + switch (variant) { + case ni_gpct_variant_e_series: + return 0; + break; + case ni_gpct_variant_m_series: + return Gi_M_Series_HW_Arm_Select_Mask; + break; + case ni_gpct_variant_660x: + return Gi_660x_HW_Arm_Select_Mask; + break; + default: + BUG(); + break; + } + return 0; +} + +/* clock sources for ni_660x boards, get bits with Gi_Source_Select_Bits() */ +enum ni_660x_clock_source { + NI_660x_Timebase_1_Clock = 0x0, /* 20MHz */ + NI_660x_Source_Pin_i_Clock = 0x1, + NI_660x_Next_Gate_Clock = 0xa, + NI_660x_Timebase_2_Clock = 0x12, /* 100KHz */ + NI_660x_Next_TC_Clock = 0x13, + NI_660x_Timebase_3_Clock = 0x1e, /* 80MHz */ + NI_660x_Logic_Low_Clock = 0x1f, +}; +static const unsigned ni_660x_max_rtsi_channel = 6; +static inline unsigned NI_660x_RTSI_Clock(unsigned n) +{ + BUG_ON(n > ni_660x_max_rtsi_channel); + return (0xb + n); +} +static const unsigned ni_660x_max_source_pin = 7; +static inline unsigned NI_660x_Source_Pin_Clock(unsigned n) +{ + BUG_ON(n > ni_660x_max_source_pin); + return (0x2 + n); +} + +/* clock sources for ni e and m series boards, get bits with Gi_Source_Select_Bits() */ +enum ni_m_series_clock_source { + NI_M_Series_Timebase_1_Clock = 0x0, /* 20MHz */ + NI_M_Series_Timebase_2_Clock = 0x12, /* 100KHz */ + NI_M_Series_Next_TC_Clock = 0x13, + NI_M_Series_Next_Gate_Clock = 0x14, /* when Gi_Src_SubSelect = 0 */ + NI_M_Series_PXI_Star_Trigger_Clock = 0x14, /* when Gi_Src_SubSelect = 1 */ + NI_M_Series_PXI10_Clock = 0x1d, + NI_M_Series_Timebase_3_Clock = 0x1e, /* 80MHz, when Gi_Src_SubSelect = 0 */ + NI_M_Series_Analog_Trigger_Out_Clock = 0x1e, /* when Gi_Src_SubSelect = 1 */ + NI_M_Series_Logic_Low_Clock = 0x1f, +}; +static const unsigned ni_m_series_max_pfi_channel = 15; +static inline unsigned NI_M_Series_PFI_Clock(unsigned n) +{ + BUG_ON(n > ni_m_series_max_pfi_channel); + if (n < 10) + return 1 + n; + else + return 0xb + n; +} +static const unsigned ni_m_series_max_rtsi_channel = 7; +static inline unsigned NI_M_Series_RTSI_Clock(unsigned n) +{ + BUG_ON(n > ni_m_series_max_rtsi_channel); + if (n == 7) + return 0x1b; + else + return 0xb + n; +} + +enum ni_660x_gate_select { + NI_660x_Source_Pin_i_Gate_Select = 0x0, + NI_660x_Gate_Pin_i_Gate_Select = 0x1, + NI_660x_Next_SRC_Gate_Select = 0xa, + NI_660x_Next_Out_Gate_Select = 0x14, + NI_660x_Logic_Low_Gate_Select = 0x1f, +}; +static const unsigned ni_660x_max_gate_pin = 7; +static inline unsigned NI_660x_Gate_Pin_Gate_Select(unsigned n) +{ + BUG_ON(n > ni_660x_max_gate_pin); + return 0x2 + n; +} +static inline unsigned NI_660x_RTSI_Gate_Select(unsigned n) +{ + BUG_ON(n > ni_660x_max_rtsi_channel); + return 0xb + n; +} + +enum ni_m_series_gate_select { + NI_M_Series_Timestamp_Mux_Gate_Select = 0x0, + NI_M_Series_AI_START2_Gate_Select = 0x12, + NI_M_Series_PXI_Star_Trigger_Gate_Select = 0x13, + NI_M_Series_Next_Out_Gate_Select = 0x14, + NI_M_Series_AI_START1_Gate_Select = 0x1c, + NI_M_Series_Next_SRC_Gate_Select = 0x1d, + NI_M_Series_Analog_Trigger_Out_Gate_Select = 0x1e, + NI_M_Series_Logic_Low_Gate_Select = 0x1f, +}; +static inline unsigned NI_M_Series_RTSI_Gate_Select(unsigned n) +{ + BUG_ON(n > ni_m_series_max_rtsi_channel); + if (n == 7) + return 0x1b; + return 0xb + n; +} +static inline unsigned NI_M_Series_PFI_Gate_Select(unsigned n) +{ + BUG_ON(n > ni_m_series_max_pfi_channel); + if (n < 10) + return 1 + n; + return 0xb + n; +} + +static inline unsigned Gi_Source_Select_Bits(unsigned source) +{ + return (source << Gi_Source_Select_Shift) & Gi_Source_Select_Mask; +} +static inline unsigned Gi_Gate_Select_Bits(unsigned gate_select) +{ + return (gate_select << Gi_Gate_Select_Shift) & Gi_Gate_Select_Mask; +} + +enum ni_660x_second_gate_select { + NI_660x_Source_Pin_i_Second_Gate_Select = 0x0, + NI_660x_Up_Down_Pin_i_Second_Gate_Select = 0x1, + NI_660x_Next_SRC_Second_Gate_Select = 0xa, + NI_660x_Next_Out_Second_Gate_Select = 0x14, + NI_660x_Selected_Gate_Second_Gate_Select = 0x1e, + NI_660x_Logic_Low_Second_Gate_Select = 0x1f, +}; +static const unsigned ni_660x_max_up_down_pin = 7; +static inline unsigned NI_660x_Up_Down_Pin_Second_Gate_Select(unsigned n) +{ + BUG_ON(n > ni_660x_max_up_down_pin); + return 0x2 + n; +} +static inline unsigned NI_660x_RTSI_Second_Gate_Select(unsigned n) +{ + BUG_ON(n > ni_660x_max_rtsi_channel); + return 0xb + n; +} + +static const unsigned int counter_status_mask = + COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING; + +static int __init ni_tio_init_module(void) +{ + return 0; +} + +module_init(ni_tio_init_module); + +static void __exit ni_tio_cleanup_module(void) +{ +} + +module_exit(ni_tio_cleanup_module); + +struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device * dev, + void (*write_register) (struct ni_gpct * counter, unsigned bits, + enum ni_gpct_register reg), + unsigned (*read_register) (struct ni_gpct * counter, + enum ni_gpct_register reg), enum ni_gpct_variant variant, + unsigned num_counters) +{ + unsigned i; + + struct ni_gpct_device *counter_dev = + kzalloc(sizeof(struct ni_gpct_device), GFP_KERNEL); + if (counter_dev == NULL) + return NULL; + counter_dev->dev = dev; + counter_dev->write_register = write_register; + counter_dev->read_register = read_register; + counter_dev->variant = variant; + spin_lock_init(&counter_dev->regs_lock); + BUG_ON(num_counters == 0); + counter_dev->counters = + kzalloc(sizeof(struct ni_gpct) * num_counters, GFP_KERNEL); + if (counter_dev->counters == NULL) { + kfree(counter_dev); + return NULL; + } + for (i = 0; i < num_counters; ++i) { + counter_dev->counters[i].counter_dev = counter_dev; + spin_lock_init(&counter_dev->counters[i].lock); + } + counter_dev->num_counters = num_counters; + return counter_dev; +} + +void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev) +{ + if (counter_dev->counters == NULL) + return; + kfree(counter_dev->counters); + kfree(counter_dev); +} + +static int ni_tio_second_gate_registers_present(const struct ni_gpct_device + *counter_dev) +{ + switch (counter_dev->variant) { + case ni_gpct_variant_e_series: + return 0; + break; + case ni_gpct_variant_m_series: + case ni_gpct_variant_660x: + return 1; + break; + default: + BUG(); + break; + } + return 0; +} + +static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter) +{ + write_register(counter, Gi_Reset_Bit(counter->counter_index), + NITIO_Gxx_Joint_Reset_Reg(counter->counter_index)); +} + +void ni_tio_init_counter(struct ni_gpct *counter) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + + ni_tio_reset_count_and_disarm(counter); + /* initialize counter registers */ + counter_dev->regs[NITIO_Gi_Autoincrement_Reg(counter->counter_index)] = + 0x0; + write_register(counter, + counter_dev->regs[NITIO_Gi_Autoincrement_Reg(counter-> + counter_index)], + NITIO_Gi_Autoincrement_Reg(counter->counter_index)); + ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), + ~0, Gi_Synchronize_Gate_Bit); + ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), ~0, + 0); + counter_dev->regs[NITIO_Gi_LoadA_Reg(counter->counter_index)] = 0x0; + write_register(counter, + counter_dev->regs[NITIO_Gi_LoadA_Reg(counter->counter_index)], + NITIO_Gi_LoadA_Reg(counter->counter_index)); + counter_dev->regs[NITIO_Gi_LoadB_Reg(counter->counter_index)] = 0x0; + write_register(counter, + counter_dev->regs[NITIO_Gi_LoadB_Reg(counter->counter_index)], + NITIO_Gi_LoadB_Reg(counter->counter_index)); + ni_tio_set_bits(counter, + NITIO_Gi_Input_Select_Reg(counter->counter_index), ~0, 0); + if (ni_tio_counting_mode_registers_present(counter_dev)) { + ni_tio_set_bits(counter, + NITIO_Gi_Counting_Mode_Reg(counter->counter_index), ~0, + 0); + } + if (ni_tio_second_gate_registers_present(counter_dev)) { + counter_dev->regs[NITIO_Gi_Second_Gate_Reg(counter-> + counter_index)] = 0x0; + write_register(counter, + counter_dev->regs[NITIO_Gi_Second_Gate_Reg(counter-> + counter_index)], + NITIO_Gi_Second_Gate_Reg(counter->counter_index)); + } + ni_tio_set_bits(counter, + NITIO_Gi_DMA_Config_Reg(counter->counter_index), ~0, 0x0); + ni_tio_set_bits(counter, + NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), ~0, 0x0); +} + +static unsigned int ni_tio_counter_status(struct ni_gpct *counter) +{ + unsigned int status = 0; + const unsigned bits = read_register(counter, + NITIO_Gxx_Status_Reg(counter->counter_index)); + if (bits & Gi_Armed_Bit(counter->counter_index)) { + status |= COMEDI_COUNTER_ARMED; + if (bits & Gi_Counting_Bit(counter->counter_index)) + status |= COMEDI_COUNTER_COUNTING; + } + return status; +} + +static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned counting_mode_reg = + NITIO_Gi_Counting_Mode_Reg(counter->counter_index); + static const uint64_t min_normal_sync_period_ps = 25000; + const uint64_t clock_period_ps = ni_tio_clock_period_ps(counter, + ni_tio_generic_clock_src_select(counter)); + + if (ni_tio_counting_mode_registers_present(counter_dev) == 0) + return; + + switch (ni_tio_get_soft_copy(counter, + counting_mode_reg) & Gi_Counting_Mode_Mask) { + case Gi_Counting_Mode_QuadratureX1_Bits: + case Gi_Counting_Mode_QuadratureX2_Bits: + case Gi_Counting_Mode_QuadratureX4_Bits: + case Gi_Counting_Mode_Sync_Source_Bits: + force_alt_sync = 1; + break; + default: + break; + } + /* It's not clear what we should do if clock_period is unknown, so we are not + using the alt sync bit in that case, but allow the caller to decide by using the + force_alt_sync parameter. */ + if (force_alt_sync || + (clock_period_ps + && clock_period_ps < min_normal_sync_period_ps)) { + ni_tio_set_bits(counter, counting_mode_reg, + Gi_Alternate_Sync_Bit(counter_dev->variant), + Gi_Alternate_Sync_Bit(counter_dev->variant)); + } else { + ni_tio_set_bits(counter, counting_mode_reg, + Gi_Alternate_Sync_Bit(counter_dev->variant), 0x0); + } +} + +static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + unsigned mode_reg_mask; + unsigned mode_reg_values; + unsigned input_select_bits = 0; + /* these bits map directly on to the mode register */ + static const unsigned mode_reg_direct_mask = + NI_GPCT_GATE_ON_BOTH_EDGES_BIT | NI_GPCT_EDGE_GATE_MODE_MASK | + NI_GPCT_STOP_MODE_MASK | NI_GPCT_OUTPUT_MODE_MASK | + NI_GPCT_HARDWARE_DISARM_MASK | NI_GPCT_LOADING_ON_TC_BIT | + NI_GPCT_LOADING_ON_GATE_BIT | NI_GPCT_LOAD_B_SELECT_BIT; + + mode_reg_mask = mode_reg_direct_mask | Gi_Reload_Source_Switching_Bit; + mode_reg_values = mode & mode_reg_direct_mask; + switch (mode & NI_GPCT_RELOAD_SOURCE_MASK) { + case NI_GPCT_RELOAD_SOURCE_FIXED_BITS: + break; + case NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS: + mode_reg_values |= Gi_Reload_Source_Switching_Bit; + break; + case NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS: + input_select_bits |= Gi_Gate_Select_Load_Source_Bit; + mode_reg_mask |= Gi_Gating_Mode_Mask; + mode_reg_values |= Gi_Level_Gating_Bits; + break; + default: + break; + } + ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), + mode_reg_mask, mode_reg_values); + + if (ni_tio_counting_mode_registers_present(counter_dev)) { + unsigned counting_mode_bits = 0; + counting_mode_bits |= + (mode >> NI_GPCT_COUNTING_MODE_SHIFT) & + Gi_Counting_Mode_Mask; + counting_mode_bits |= + ((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT) << + Gi_Index_Phase_Bitshift) & Gi_Index_Phase_Mask; + if (mode & NI_GPCT_INDEX_ENABLE_BIT) { + counting_mode_bits |= Gi_Index_Mode_Bit; + } + ni_tio_set_bits(counter, + NITIO_Gi_Counting_Mode_Reg(counter->counter_index), + Gi_Counting_Mode_Mask | Gi_Index_Phase_Mask | + Gi_Index_Mode_Bit, counting_mode_bits); + ni_tio_set_sync_mode(counter, 0); + } + + ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), + Gi_Up_Down_Mask, + (mode >> NI_GPCT_COUNTING_DIRECTION_SHIFT) << Gi_Up_Down_Shift); + + if (mode & NI_GPCT_OR_GATE_BIT) { + input_select_bits |= Gi_Or_Gate_Bit; + } + if (mode & NI_GPCT_INVERT_OUTPUT_BIT) { + input_select_bits |= Gi_Output_Polarity_Bit; + } + ni_tio_set_bits(counter, + NITIO_Gi_Input_Select_Reg(counter->counter_index), + Gi_Gate_Select_Load_Source_Bit | Gi_Or_Gate_Bit | + Gi_Output_Polarity_Bit, input_select_bits); + + return 0; +} + +int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + + unsigned command_transient_bits = 0; + + if (arm) { + switch (start_trigger) { + case NI_GPCT_ARM_IMMEDIATE: + command_transient_bits |= Gi_Arm_Bit; + break; + case NI_GPCT_ARM_PAIRED_IMMEDIATE: + command_transient_bits |= Gi_Arm_Bit | Gi_Arm_Copy_Bit; + break; + default: + break; + } + if (ni_tio_counting_mode_registers_present(counter_dev)) { + unsigned counting_mode_bits = 0; + + switch (start_trigger) { + case NI_GPCT_ARM_IMMEDIATE: + case NI_GPCT_ARM_PAIRED_IMMEDIATE: + break; + default: + if (start_trigger & NI_GPCT_ARM_UNKNOWN) { + /* pass-through the least significant bits so we can figure out what select later */ + unsigned hw_arm_select_bits = + (start_trigger << + Gi_HW_Arm_Select_Shift) & + Gi_HW_Arm_Select_Mask + (counter_dev->variant); + + counting_mode_bits |= + Gi_HW_Arm_Enable_Bit | + hw_arm_select_bits; + } else { + return -EINVAL; + } + break; + } + ni_tio_set_bits(counter, + NITIO_Gi_Counting_Mode_Reg(counter-> + counter_index), + Gi_HW_Arm_Select_Mask(counter_dev-> + variant) | Gi_HW_Arm_Enable_Bit, + counting_mode_bits); + } + } else { + command_transient_bits |= Gi_Disarm_Bit; + } + ni_tio_set_bits_transient(counter, + NITIO_Gi_Command_Reg(counter->counter_index), 0, 0, + command_transient_bits); + return 0; +} + +static unsigned ni_660x_source_select_bits(unsigned int clock_source) +{ + unsigned ni_660x_clock; + unsigned i; + const unsigned clock_select_bits = + clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; + + switch (clock_select_bits) { + case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: + ni_660x_clock = NI_660x_Timebase_1_Clock; + break; + case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: + ni_660x_clock = NI_660x_Timebase_2_Clock; + break; + case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: + ni_660x_clock = NI_660x_Timebase_3_Clock; + break; + case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS: + ni_660x_clock = NI_660x_Logic_Low_Clock; + break; + case NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS: + ni_660x_clock = NI_660x_Source_Pin_i_Clock; + break; + case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: + ni_660x_clock = NI_660x_Next_Gate_Clock; + break; + case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS: + ni_660x_clock = NI_660x_Next_TC_Clock; + break; + default: + for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { + if (clock_select_bits == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { + ni_660x_clock = NI_660x_RTSI_Clock(i); + break; + } + } + if (i <= ni_660x_max_rtsi_channel) + break; + for (i = 0; i <= ni_660x_max_source_pin; ++i) { + if (clock_select_bits == + NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i)) { + ni_660x_clock = NI_660x_Source_Pin_Clock(i); + break; + } + } + if (i <= ni_660x_max_source_pin) + break; + ni_660x_clock = 0; + BUG(); + break; + } + return Gi_Source_Select_Bits(ni_660x_clock); +} + +static unsigned ni_m_series_source_select_bits(unsigned int clock_source) +{ + unsigned ni_m_series_clock; + unsigned i; + const unsigned clock_select_bits = + clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; + switch (clock_select_bits) { + case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: + ni_m_series_clock = NI_M_Series_Timebase_1_Clock; + break; + case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: + ni_m_series_clock = NI_M_Series_Timebase_2_Clock; + break; + case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: + ni_m_series_clock = NI_M_Series_Timebase_3_Clock; + break; + case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS: + ni_m_series_clock = NI_M_Series_Logic_Low_Clock; + break; + case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: + ni_m_series_clock = NI_M_Series_Next_Gate_Clock; + break; + case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS: + ni_m_series_clock = NI_M_Series_Next_TC_Clock; + break; + case NI_GPCT_PXI10_CLOCK_SRC_BITS: + ni_m_series_clock = NI_M_Series_PXI10_Clock; + break; + case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS: + ni_m_series_clock = NI_M_Series_PXI_Star_Trigger_Clock; + break; + case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS: + ni_m_series_clock = NI_M_Series_Analog_Trigger_Out_Clock; + break; + default: + for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { + if (clock_select_bits == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { + ni_m_series_clock = NI_M_Series_RTSI_Clock(i); + break; + } + } + if (i <= ni_m_series_max_rtsi_channel) + break; + for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { + if (clock_select_bits == NI_GPCT_PFI_CLOCK_SRC_BITS(i)) { + ni_m_series_clock = NI_M_Series_PFI_Clock(i); + break; + } + } + if (i <= ni_m_series_max_pfi_channel) + break; + rt_printk("invalid clock source 0x%lx\n", + (unsigned long)clock_source); + BUG(); + ni_m_series_clock = 0; + break; + } + return Gi_Source_Select_Bits(ni_m_series_clock); +}; + +static void ni_tio_set_source_subselect(struct ni_gpct *counter, + unsigned int clock_source) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned second_gate_reg = + NITIO_Gi_Second_Gate_Reg(counter->counter_index); + + if (counter_dev->variant != ni_gpct_variant_m_series) + return; + switch (clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) { + /* Gi_Source_Subselect is zero */ + case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: + case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: + counter_dev->regs[second_gate_reg] &= ~Gi_Source_Subselect_Bit; + break; + /* Gi_Source_Subselect is one */ + case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS: + case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS: + counter_dev->regs[second_gate_reg] |= Gi_Source_Subselect_Bit; + break; + /* Gi_Source_Subselect doesn't matter */ + default: + return; + break; + } + write_register(counter, counter_dev->regs[second_gate_reg], + second_gate_reg); +} + +static int ni_tio_set_clock_src(struct ni_gpct *counter, + unsigned int clock_source, unsigned int period_ns) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + unsigned input_select_bits = 0; + static const uint64_t pico_per_nano = 1000; + +/*FIXME: validate clock source */ + switch (counter_dev->variant) { + case ni_gpct_variant_660x: + input_select_bits |= ni_660x_source_select_bits(clock_source); + break; + case ni_gpct_variant_e_series: + case ni_gpct_variant_m_series: + input_select_bits |= + ni_m_series_source_select_bits(clock_source); + break; + default: + BUG(); + break; + } + if (clock_source & NI_GPCT_INVERT_CLOCK_SRC_BIT) + input_select_bits |= Gi_Source_Polarity_Bit; + ni_tio_set_bits(counter, + NITIO_Gi_Input_Select_Reg(counter->counter_index), + Gi_Source_Select_Mask | Gi_Source_Polarity_Bit, + input_select_bits); + ni_tio_set_source_subselect(counter, clock_source); + if (ni_tio_counting_mode_registers_present(counter_dev)) { + const unsigned prescaling_mode = + clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK; + unsigned counting_mode_bits = 0; + + switch (prescaling_mode) { + case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: + break; + case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: + counting_mode_bits |= + Gi_Prescale_X2_Bit(counter_dev->variant); + break; + case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: + counting_mode_bits |= + Gi_Prescale_X8_Bit(counter_dev->variant); + break; + default: + return -EINVAL; + break; + } + ni_tio_set_bits(counter, + NITIO_Gi_Counting_Mode_Reg(counter->counter_index), + Gi_Prescale_X2_Bit(counter_dev-> + variant) | Gi_Prescale_X8_Bit(counter_dev-> + variant), counting_mode_bits); + } + counter->clock_period_ps = pico_per_nano * period_ns; + ni_tio_set_sync_mode(counter, 0); + return 0; +} + +static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned counting_mode_bits = ni_tio_get_soft_copy(counter, + NITIO_Gi_Counting_Mode_Reg(counter->counter_index)); + unsigned bits = 0; + + if (ni_tio_get_soft_copy(counter, + NITIO_Gi_Input_Select_Reg(counter-> + counter_index)) & Gi_Source_Polarity_Bit) + bits |= NI_GPCT_INVERT_CLOCK_SRC_BIT; + if (counting_mode_bits & Gi_Prescale_X2_Bit(counter_dev->variant)) + bits |= NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS; + if (counting_mode_bits & Gi_Prescale_X8_Bit(counter_dev->variant)) + bits |= NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS; + return bits; +} + +static unsigned ni_m_series_clock_src_select(const struct ni_gpct *counter) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned second_gate_reg = + NITIO_Gi_Second_Gate_Reg(counter->counter_index); + unsigned clock_source = 0; + unsigned i; + const unsigned input_select = (ni_tio_get_soft_copy(counter, + NITIO_Gi_Input_Select_Reg(counter-> + counter_index)) & Gi_Source_Select_Mask) >> + Gi_Source_Select_Shift; + + switch (input_select) { + case NI_M_Series_Timebase_1_Clock: + clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; + break; + case NI_M_Series_Timebase_2_Clock: + clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; + break; + case NI_M_Series_Timebase_3_Clock: + if (counter_dev-> + regs[second_gate_reg] & Gi_Source_Subselect_Bit) + clock_source = + NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS; + else + clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; + break; + case NI_M_Series_Logic_Low_Clock: + clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; + break; + case NI_M_Series_Next_Gate_Clock: + if (counter_dev-> + regs[second_gate_reg] & Gi_Source_Subselect_Bit) + clock_source = NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS; + else + clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; + break; + case NI_M_Series_PXI10_Clock: + clock_source = NI_GPCT_PXI10_CLOCK_SRC_BITS; + break; + case NI_M_Series_Next_TC_Clock: + clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; + break; + default: + for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { + if (input_select == NI_M_Series_RTSI_Clock(i)) { + clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); + break; + } + } + if (i <= ni_m_series_max_rtsi_channel) + break; + for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { + if (input_select == NI_M_Series_PFI_Clock(i)) { + clock_source = NI_GPCT_PFI_CLOCK_SRC_BITS(i); + break; + } + } + if (i <= ni_m_series_max_pfi_channel) + break; + BUG(); + break; + } + clock_source |= ni_tio_clock_src_modifiers(counter); + return clock_source; +} + +static unsigned ni_660x_clock_src_select(const struct ni_gpct *counter) +{ + unsigned clock_source = 0; + unsigned i; + const unsigned input_select = (ni_tio_get_soft_copy(counter, + NITIO_Gi_Input_Select_Reg(counter-> + counter_index)) & Gi_Source_Select_Mask) >> + Gi_Source_Select_Shift; + + switch (input_select) { + case NI_660x_Timebase_1_Clock: + clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; + break; + case NI_660x_Timebase_2_Clock: + clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; + break; + case NI_660x_Timebase_3_Clock: + clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; + break; + case NI_660x_Logic_Low_Clock: + clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; + break; + case NI_660x_Source_Pin_i_Clock: + clock_source = NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS; + break; + case NI_660x_Next_Gate_Clock: + clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; + break; + case NI_660x_Next_TC_Clock: + clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; + break; + default: + for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { + if (input_select == NI_660x_RTSI_Clock(i)) { + clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); + break; + } + } + if (i <= ni_660x_max_rtsi_channel) + break; + for (i = 0; i <= ni_660x_max_source_pin; ++i) { + if (input_select == NI_660x_Source_Pin_Clock(i)) { + clock_source = + NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i); + break; + } + } + if (i <= ni_660x_max_source_pin) + break; + BUG(); + break; + } + clock_source |= ni_tio_clock_src_modifiers(counter); + return clock_source; +} + +static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter) +{ + switch (counter->counter_dev->variant) { + case ni_gpct_variant_e_series: + case ni_gpct_variant_m_series: + return ni_m_series_clock_src_select(counter); + break; + case ni_gpct_variant_660x: + return ni_660x_clock_src_select(counter); + break; + default: + BUG(); + break; + } + return 0; +} + +static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, + unsigned generic_clock_source) +{ + uint64_t clock_period_ps; + + switch (generic_clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) { + case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: + clock_period_ps = 50000; + break; + case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: + clock_period_ps = 10000000; + break; + case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: + clock_period_ps = 12500; + break; + case NI_GPCT_PXI10_CLOCK_SRC_BITS: + clock_period_ps = 100000; + break; + default: + /* clock period is specified by user with prescaling already taken into account. */ + return counter->clock_period_ps; + break; + } + + switch (generic_clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) { + case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: + break; + case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: + clock_period_ps *= 2; + break; + case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: + clock_period_ps *= 8; + break; + default: + BUG(); + break; + } + return clock_period_ps; +} + +static void ni_tio_get_clock_src(struct ni_gpct *counter, + unsigned int * clock_source, unsigned int * period_ns) +{ + static const unsigned pico_per_nano = 1000; + uint64_t temp64; + *clock_source = ni_tio_generic_clock_src_select(counter); + temp64 = ni_tio_clock_period_ps(counter, *clock_source); + do_div(temp64, pico_per_nano); + *period_ns = temp64; +} + +static void ni_tio_set_first_gate_modifiers(struct ni_gpct *counter, + unsigned int gate_source) +{ + const unsigned mode_mask = Gi_Gate_Polarity_Bit | Gi_Gating_Mode_Mask; + unsigned mode_values = 0; + + if (gate_source & CR_INVERT) { + mode_values |= Gi_Gate_Polarity_Bit; + } + if (gate_source & CR_EDGE) { + mode_values |= Gi_Rising_Edge_Gating_Bits; + } else { + mode_values |= Gi_Level_Gating_Bits; + } + ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), + mode_mask, mode_values); +} + +static int ni_660x_set_first_gate(struct ni_gpct *counter, unsigned int gate_source) +{ + const unsigned selected_gate = CR_CHAN(gate_source); + /* bits of selected_gate that may be meaningful to input select register */ + const unsigned selected_gate_mask = 0x1f; + unsigned ni_660x_gate_select; + unsigned i; + + switch (selected_gate) { + case NI_GPCT_NEXT_SOURCE_GATE_SELECT: + ni_660x_gate_select = NI_660x_Next_SRC_Gate_Select; + break; + case NI_GPCT_NEXT_OUT_GATE_SELECT: + case NI_GPCT_LOGIC_LOW_GATE_SELECT: + case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: + case NI_GPCT_GATE_PIN_i_GATE_SELECT: + ni_660x_gate_select = selected_gate & selected_gate_mask; + break; + default: + for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { + if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { + ni_660x_gate_select = + selected_gate & selected_gate_mask; + break; + } + } + if (i <= ni_660x_max_rtsi_channel) + break; + for (i = 0; i <= ni_660x_max_gate_pin; ++i) { + if (selected_gate == NI_GPCT_GATE_PIN_GATE_SELECT(i)) { + ni_660x_gate_select = + selected_gate & selected_gate_mask; + break; + } + } + if (i <= ni_660x_max_gate_pin) + break; + return -EINVAL; + break; + } + ni_tio_set_bits(counter, + NITIO_Gi_Input_Select_Reg(counter->counter_index), + Gi_Gate_Select_Mask, Gi_Gate_Select_Bits(ni_660x_gate_select)); + return 0; +} + +static int ni_m_series_set_first_gate(struct ni_gpct *counter, + unsigned int gate_source) +{ + const unsigned selected_gate = CR_CHAN(gate_source); + /* bits of selected_gate that may be meaningful to input select register */ + const unsigned selected_gate_mask = 0x1f; + unsigned ni_m_series_gate_select; + unsigned i; + + switch (selected_gate) { + case NI_GPCT_TIMESTAMP_MUX_GATE_SELECT: + case NI_GPCT_AI_START2_GATE_SELECT: + case NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT: + case NI_GPCT_NEXT_OUT_GATE_SELECT: + case NI_GPCT_AI_START1_GATE_SELECT: + case NI_GPCT_NEXT_SOURCE_GATE_SELECT: + case NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT: + case NI_GPCT_LOGIC_LOW_GATE_SELECT: + ni_m_series_gate_select = selected_gate & selected_gate_mask; + break; + default: + for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { + if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { + ni_m_series_gate_select = + selected_gate & selected_gate_mask; + break; + } + } + if (i <= ni_m_series_max_rtsi_channel) + break; + for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { + if (selected_gate == NI_GPCT_PFI_GATE_SELECT(i)) { + ni_m_series_gate_select = + selected_gate & selected_gate_mask; + break; + } + } + if (i <= ni_m_series_max_pfi_channel) + break; + return -EINVAL; + break; + } + ni_tio_set_bits(counter, + NITIO_Gi_Input_Select_Reg(counter->counter_index), + Gi_Gate_Select_Mask, + Gi_Gate_Select_Bits(ni_m_series_gate_select)); + return 0; +} + +static int ni_660x_set_second_gate(struct ni_gpct *counter, + unsigned int gate_source) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned second_gate_reg = + NITIO_Gi_Second_Gate_Reg(counter->counter_index); + const unsigned selected_second_gate = CR_CHAN(gate_source); + /* bits of second_gate that may be meaningful to second gate register */ + static const unsigned selected_second_gate_mask = 0x1f; + unsigned ni_660x_second_gate_select; + unsigned i; + + switch (selected_second_gate) { + case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: + case NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT: + case NI_GPCT_SELECTED_GATE_GATE_SELECT: + case NI_GPCT_NEXT_OUT_GATE_SELECT: + case NI_GPCT_LOGIC_LOW_GATE_SELECT: + ni_660x_second_gate_select = + selected_second_gate & selected_second_gate_mask; + break; + case NI_GPCT_NEXT_SOURCE_GATE_SELECT: + ni_660x_second_gate_select = + NI_660x_Next_SRC_Second_Gate_Select; + break; + default: + for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { + if (selected_second_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { + ni_660x_second_gate_select = + selected_second_gate & + selected_second_gate_mask; + break; + } + } + if (i <= ni_660x_max_rtsi_channel) + break; + for (i = 0; i <= ni_660x_max_up_down_pin; ++i) { + if (selected_second_gate == + NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i)) { + ni_660x_second_gate_select = + selected_second_gate & + selected_second_gate_mask; + break; + } + } + if (i <= ni_660x_max_up_down_pin) + break; + return -EINVAL; + break; + }; + counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit; + counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask; + counter_dev->regs[second_gate_reg] |= + Gi_Second_Gate_Select_Bits(ni_660x_second_gate_select); + write_register(counter, counter_dev->regs[second_gate_reg], + second_gate_reg); + return 0; +} + +static int ni_m_series_set_second_gate(struct ni_gpct *counter, + unsigned int gate_source) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned second_gate_reg = + NITIO_Gi_Second_Gate_Reg(counter->counter_index); + const unsigned selected_second_gate = CR_CHAN(gate_source); + /* bits of second_gate that may be meaningful to second gate register */ + static const unsigned selected_second_gate_mask = 0x1f; + unsigned ni_m_series_second_gate_select; + + /* FIXME: We don't know what the m-series second gate codes are, so we'll just pass + the bits through for now. */ + switch (selected_second_gate) { + default: + ni_m_series_second_gate_select = + selected_second_gate & selected_second_gate_mask; + break; + }; + counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit; + counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask; + counter_dev->regs[second_gate_reg] |= + Gi_Second_Gate_Select_Bits(ni_m_series_second_gate_select); + write_register(counter, counter_dev->regs[second_gate_reg], + second_gate_reg); + return 0; +} + +int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, + unsigned int gate_source) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned second_gate_reg = + NITIO_Gi_Second_Gate_Reg(counter->counter_index); + + switch (gate_index) { + case 0: + if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) { + ni_tio_set_bits(counter, + NITIO_Gi_Mode_Reg(counter->counter_index), + Gi_Gating_Mode_Mask, Gi_Gating_Disabled_Bits); + return 0; + } + ni_tio_set_first_gate_modifiers(counter, gate_source); + switch (counter_dev->variant) { + case ni_gpct_variant_e_series: + case ni_gpct_variant_m_series: + return ni_m_series_set_first_gate(counter, gate_source); + break; + case ni_gpct_variant_660x: + return ni_660x_set_first_gate(counter, gate_source); + break; + default: + BUG(); + break; + } + break; + case 1: + if (ni_tio_second_gate_registers_present(counter_dev) == 0) + return -EINVAL; + if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) { + counter_dev->regs[second_gate_reg] &= + ~Gi_Second_Gate_Mode_Bit; + write_register(counter, + counter_dev->regs[second_gate_reg], + second_gate_reg); + return 0; + } + if (gate_source & CR_INVERT) { + counter_dev->regs[second_gate_reg] |= + Gi_Second_Gate_Polarity_Bit; + } else { + counter_dev->regs[second_gate_reg] &= + ~Gi_Second_Gate_Polarity_Bit; + } + switch (counter_dev->variant) { + case ni_gpct_variant_m_series: + return ni_m_series_set_second_gate(counter, + gate_source); + break; + case ni_gpct_variant_660x: + return ni_660x_set_second_gate(counter, gate_source); + break; + default: + BUG(); + break; + } + break; + default: + return -EINVAL; + break; + } + return 0; +} + +static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index, + unsigned int source) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + + if (counter_dev->variant == ni_gpct_variant_m_series) { + unsigned int abz_reg, shift, mask; + + abz_reg = NITIO_Gi_ABZ_Reg(counter->counter_index); + switch (index) { + case NI_GPCT_SOURCE_ENCODER_A: + shift = 10; + break; + case NI_GPCT_SOURCE_ENCODER_B: + shift = 5; + break; + case NI_GPCT_SOURCE_ENCODER_Z: + shift = 0; + break; + default: + return -EINVAL; + break; + } + mask = 0x1f << shift; + if (source > 0x1f) { + /* Disable gate */ + source = 0x1f; + } + counter_dev->regs[abz_reg] &= ~mask; + counter_dev->regs[abz_reg] |= (source << shift) & mask; + write_register(counter, counter_dev->regs[abz_reg], abz_reg); +// rt_printk("%s %x %d %d\n", __FUNCTION__, counter_dev->regs[abz_reg], index, source); + return 0; + } + return -EINVAL; +} + +static unsigned ni_660x_first_gate_to_generic_gate_source(unsigned + ni_660x_gate_select) +{ + unsigned i; + + switch (ni_660x_gate_select) { + case NI_660x_Source_Pin_i_Gate_Select: + return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; + break; + case NI_660x_Gate_Pin_i_Gate_Select: + return NI_GPCT_GATE_PIN_i_GATE_SELECT; + break; + case NI_660x_Next_SRC_Gate_Select: + return NI_GPCT_NEXT_SOURCE_GATE_SELECT; + break; + case NI_660x_Next_Out_Gate_Select: + return NI_GPCT_NEXT_OUT_GATE_SELECT; + break; + case NI_660x_Logic_Low_Gate_Select: + return NI_GPCT_LOGIC_LOW_GATE_SELECT; + break; + default: + for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { + if (ni_660x_gate_select == NI_660x_RTSI_Gate_Select(i)) { + return NI_GPCT_RTSI_GATE_SELECT(i); + break; + } + } + if (i <= ni_660x_max_rtsi_channel) + break; + for (i = 0; i <= ni_660x_max_gate_pin; ++i) { + if (ni_660x_gate_select == + NI_660x_Gate_Pin_Gate_Select(i)) { + return NI_GPCT_GATE_PIN_GATE_SELECT(i); + break; + } + } + if (i <= ni_660x_max_gate_pin) + break; + BUG(); + break; + } + return 0; +}; + +static unsigned ni_m_series_first_gate_to_generic_gate_source(unsigned + ni_m_series_gate_select) +{ + unsigned i; + + switch (ni_m_series_gate_select) { + case NI_M_Series_Timestamp_Mux_Gate_Select: + return NI_GPCT_TIMESTAMP_MUX_GATE_SELECT; + break; + case NI_M_Series_AI_START2_Gate_Select: + return NI_GPCT_AI_START2_GATE_SELECT; + break; + case NI_M_Series_PXI_Star_Trigger_Gate_Select: + return NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT; + break; + case NI_M_Series_Next_Out_Gate_Select: + return NI_GPCT_NEXT_OUT_GATE_SELECT; + break; + case NI_M_Series_AI_START1_Gate_Select: + return NI_GPCT_AI_START1_GATE_SELECT; + break; + case NI_M_Series_Next_SRC_Gate_Select: + return NI_GPCT_NEXT_SOURCE_GATE_SELECT; + break; + case NI_M_Series_Analog_Trigger_Out_Gate_Select: + return NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT; + break; + case NI_M_Series_Logic_Low_Gate_Select: + return NI_GPCT_LOGIC_LOW_GATE_SELECT; + break; + default: + for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { + if (ni_m_series_gate_select == + NI_M_Series_RTSI_Gate_Select(i)) { + return NI_GPCT_RTSI_GATE_SELECT(i); + break; + } + } + if (i <= ni_m_series_max_rtsi_channel) + break; + for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { + if (ni_m_series_gate_select == + NI_M_Series_PFI_Gate_Select(i)) { + return NI_GPCT_PFI_GATE_SELECT(i); + break; + } + } + if (i <= ni_m_series_max_pfi_channel) + break; + BUG(); + break; + } + return 0; +}; + +static unsigned ni_660x_second_gate_to_generic_gate_source(unsigned + ni_660x_gate_select) +{ + unsigned i; + + switch (ni_660x_gate_select) { + case NI_660x_Source_Pin_i_Second_Gate_Select: + return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; + break; + case NI_660x_Up_Down_Pin_i_Second_Gate_Select: + return NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT; + break; + case NI_660x_Next_SRC_Second_Gate_Select: + return NI_GPCT_NEXT_SOURCE_GATE_SELECT; + break; + case NI_660x_Next_Out_Second_Gate_Select: + return NI_GPCT_NEXT_OUT_GATE_SELECT; + break; + case NI_660x_Selected_Gate_Second_Gate_Select: + return NI_GPCT_SELECTED_GATE_GATE_SELECT; + break; + case NI_660x_Logic_Low_Second_Gate_Select: + return NI_GPCT_LOGIC_LOW_GATE_SELECT; + break; + default: + for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { + if (ni_660x_gate_select == + NI_660x_RTSI_Second_Gate_Select(i)) { + return NI_GPCT_RTSI_GATE_SELECT(i); + break; + } + } + if (i <= ni_660x_max_rtsi_channel) + break; + for (i = 0; i <= ni_660x_max_up_down_pin; ++i) { + if (ni_660x_gate_select == + NI_660x_Up_Down_Pin_Second_Gate_Select(i)) { + return NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i); + break; + } + } + if (i <= ni_660x_max_up_down_pin) + break; + BUG(); + break; + } + return 0; +}; + +static unsigned ni_m_series_second_gate_to_generic_gate_source(unsigned + ni_m_series_gate_select) +{ + /*FIXME: the second gate sources for the m series are undocumented, so we just return + * the raw bits for now. */ + switch (ni_m_series_gate_select) { + default: + return ni_m_series_gate_select; + break; + } + return 0; +}; + +static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index, + unsigned int * gate_source) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned mode_bits = ni_tio_get_soft_copy(counter, + NITIO_Gi_Mode_Reg(counter->counter_index)); + const unsigned second_gate_reg = + NITIO_Gi_Second_Gate_Reg(counter->counter_index); + unsigned gate_select_bits; + + switch (gate_index) { + case 0: + if ((mode_bits & Gi_Gating_Mode_Mask) == + Gi_Gating_Disabled_Bits) { + *gate_source = NI_GPCT_DISABLED_GATE_SELECT; + return 0; + } else { + gate_select_bits = + (ni_tio_get_soft_copy(counter, + NITIO_Gi_Input_Select_Reg(counter-> + counter_index)) & + Gi_Gate_Select_Mask) >> Gi_Gate_Select_Shift; + } + switch (counter_dev->variant) { + case ni_gpct_variant_e_series: + case ni_gpct_variant_m_series: + *gate_source = + ni_m_series_first_gate_to_generic_gate_source + (gate_select_bits); + break; + case ni_gpct_variant_660x: + *gate_source = + ni_660x_first_gate_to_generic_gate_source + (gate_select_bits); + break; + default: + BUG(); + break; + } + if (mode_bits & Gi_Gate_Polarity_Bit) { + *gate_source |= CR_INVERT; + } + if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) { + *gate_source |= CR_EDGE; + } + break; + case 1: + if ((mode_bits & Gi_Gating_Mode_Mask) == Gi_Gating_Disabled_Bits + || (counter_dev-> + regs[second_gate_reg] & Gi_Second_Gate_Mode_Bit) + == 0) { + *gate_source = NI_GPCT_DISABLED_GATE_SELECT; + return 0; + } else { + gate_select_bits = + (counter_dev-> + regs[second_gate_reg] & + Gi_Second_Gate_Select_Mask) >> + Gi_Second_Gate_Select_Shift; + } + switch (counter_dev->variant) { + case ni_gpct_variant_e_series: + case ni_gpct_variant_m_series: + *gate_source = + ni_m_series_second_gate_to_generic_gate_source + (gate_select_bits); + break; + case ni_gpct_variant_660x: + *gate_source = + ni_660x_second_gate_to_generic_gate_source + (gate_select_bits); + break; + default: + BUG(); + break; + } + if (counter_dev-> + regs[second_gate_reg] & Gi_Second_Gate_Polarity_Bit) { + *gate_source |= CR_INVERT; + } + /* second gate can't have edge/level mode set independently */ + if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) { + *gate_source |= CR_EDGE; + } + break; + default: + return -EINVAL; + break; + } + return 0; +} + +int ni_tio_insn_config(struct ni_gpct *counter, + struct comedi_insn * insn, unsigned int * data) +{ + switch (data[0]) { + case INSN_CONFIG_SET_COUNTER_MODE: + return ni_tio_set_counter_mode(counter, data[1]); + break; + case INSN_CONFIG_ARM: + return ni_tio_arm(counter, 1, data[1]); + break; + case INSN_CONFIG_DISARM: + ni_tio_arm(counter, 0, 0); + return 0; + break; + case INSN_CONFIG_GET_COUNTER_STATUS: + data[1] = ni_tio_counter_status(counter); + data[2] = counter_status_mask; + return 0; + break; + case INSN_CONFIG_SET_CLOCK_SRC: + return ni_tio_set_clock_src(counter, data[1], data[2]); + break; + case INSN_CONFIG_GET_CLOCK_SRC: + ni_tio_get_clock_src(counter, &data[1], &data[2]); + return 0; + break; + case INSN_CONFIG_SET_GATE_SRC: + return ni_tio_set_gate_src(counter, data[1], data[2]); + break; + case INSN_CONFIG_GET_GATE_SRC: + return ni_tio_get_gate_src(counter, data[1], &data[2]); + break; + case INSN_CONFIG_SET_OTHER_SRC: + return ni_tio_set_other_src(counter, data[1], data[2]); + break; + case INSN_CONFIG_RESET: + ni_tio_reset_count_and_disarm(counter); + return 0; + break; + default: + break; + } + return -EINVAL; +} + +int ni_tio_rinsn(struct ni_gpct *counter, struct comedi_insn * insn, unsigned int * data) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned channel = CR_CHAN(insn->chanspec); + unsigned first_read; + unsigned second_read; + unsigned correct_read; + + if (insn->n < 1) + return 0; + switch (channel) { + case 0: + ni_tio_set_bits(counter, + NITIO_Gi_Command_Reg(counter->counter_index), + Gi_Save_Trace_Bit, 0); + ni_tio_set_bits(counter, + NITIO_Gi_Command_Reg(counter->counter_index), + Gi_Save_Trace_Bit, Gi_Save_Trace_Bit); + /* The count doesn't get latched until the next clock edge, so it is possible the count + may change (once) while we are reading. Since the read of the SW_Save_Reg isn't + atomic (apparently even when it's a 32 bit register according to 660x docs), + we need to read twice and make sure the reading hasn't changed. If it has, + a third read will be correct since the count value will definitely have latched by then. */ + first_read = + read_register(counter, + NITIO_Gi_SW_Save_Reg(counter->counter_index)); + second_read = + read_register(counter, + NITIO_Gi_SW_Save_Reg(counter->counter_index)); + if (first_read != second_read) + correct_read = + read_register(counter, + NITIO_Gi_SW_Save_Reg(counter->counter_index)); + else + correct_read = first_read; + data[0] = correct_read; + return 0; + break; + case 1: + data[0] = + counter_dev->regs[NITIO_Gi_LoadA_Reg(counter-> + counter_index)]; + break; + case 2: + data[0] = + counter_dev->regs[NITIO_Gi_LoadB_Reg(counter-> + counter_index)]; + break; + }; + return 0; +} + +static unsigned ni_tio_next_load_register(struct ni_gpct *counter) +{ + const unsigned bits = read_register(counter, + NITIO_Gxx_Status_Reg(counter->counter_index)); + + if (bits & Gi_Next_Load_Source_Bit(counter->counter_index)) { + return NITIO_Gi_LoadB_Reg(counter->counter_index); + } else { + return NITIO_Gi_LoadA_Reg(counter->counter_index); + } +} + +int ni_tio_winsn(struct ni_gpct *counter, struct comedi_insn * insn, unsigned int * data) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + const unsigned channel = CR_CHAN(insn->chanspec); + unsigned load_reg; + + if (insn->n < 1) + return 0; + switch (channel) { + case 0: + /* Unsafe if counter is armed. Should probably check status and return -EBUSY if armed. */ + /* Don't disturb load source select, just use whichever load register is already selected. */ + load_reg = ni_tio_next_load_register(counter); + write_register(counter, data[0], load_reg); + ni_tio_set_bits_transient(counter, + NITIO_Gi_Command_Reg(counter->counter_index), 0, 0, + Gi_Load_Bit); + /* restore state of load reg to whatever the user set last set it to */ + write_register(counter, counter_dev->regs[load_reg], load_reg); + break; + case 1: + counter_dev->regs[NITIO_Gi_LoadA_Reg(counter->counter_index)] = + data[0]; + write_register(counter, data[0], + NITIO_Gi_LoadA_Reg(counter->counter_index)); + break; + case 2: + counter_dev->regs[NITIO_Gi_LoadB_Reg(counter->counter_index)] = + data[0]; + write_register(counter, data[0], + NITIO_Gi_LoadB_Reg(counter->counter_index)); + break; + default: + return -EINVAL; + break; + } + return 0; +} + +EXPORT_SYMBOL_GPL(ni_tio_rinsn); +EXPORT_SYMBOL_GPL(ni_tio_winsn); +EXPORT_SYMBOL_GPL(ni_tio_insn_config); +EXPORT_SYMBOL_GPL(ni_tio_init_counter); +EXPORT_SYMBOL_GPL(ni_tio_arm); +EXPORT_SYMBOL_GPL(ni_tio_set_gate_src); +EXPORT_SYMBOL_GPL(ni_gpct_device_construct); +EXPORT_SYMBOL_GPL(ni_gpct_device_destroy); diff --git a/drivers/staging/comedi/drivers/ni_tio.h b/drivers/staging/comedi/drivers/ni_tio.h new file mode 100644 index 000000000000..0729d60b01cc --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_tio.h @@ -0,0 +1,163 @@ +/* + drivers/ni_tio.h + Header file for NI general purpose counter support code (ni_tio.c) + + COMEDI - Linux Control and Measurement Device Interface + + 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 _COMEDI_NI_TIO_H +#define _COMEDI_NI_TIO_H + +#include "../comedidev.h" + +// forward declarations +struct mite_struct; +struct ni_gpct_device; + +enum ni_gpct_register { + NITIO_G0_Autoincrement_Reg, + NITIO_G1_Autoincrement_Reg, + NITIO_G2_Autoincrement_Reg, + NITIO_G3_Autoincrement_Reg, + NITIO_G0_Command_Reg, + NITIO_G1_Command_Reg, + NITIO_G2_Command_Reg, + NITIO_G3_Command_Reg, + NITIO_G0_HW_Save_Reg, + NITIO_G1_HW_Save_Reg, + NITIO_G2_HW_Save_Reg, + NITIO_G3_HW_Save_Reg, + NITIO_G0_SW_Save_Reg, + NITIO_G1_SW_Save_Reg, + NITIO_G2_SW_Save_Reg, + NITIO_G3_SW_Save_Reg, + NITIO_G0_Mode_Reg, + NITIO_G1_Mode_Reg, + NITIO_G2_Mode_Reg, + NITIO_G3_Mode_Reg, + NITIO_G0_LoadA_Reg, + NITIO_G1_LoadA_Reg, + NITIO_G2_LoadA_Reg, + NITIO_G3_LoadA_Reg, + NITIO_G0_LoadB_Reg, + NITIO_G1_LoadB_Reg, + NITIO_G2_LoadB_Reg, + NITIO_G3_LoadB_Reg, + NITIO_G0_Input_Select_Reg, + NITIO_G1_Input_Select_Reg, + NITIO_G2_Input_Select_Reg, + NITIO_G3_Input_Select_Reg, + NITIO_G0_Counting_Mode_Reg, + NITIO_G1_Counting_Mode_Reg, + NITIO_G2_Counting_Mode_Reg, + NITIO_G3_Counting_Mode_Reg, + NITIO_G0_Second_Gate_Reg, + NITIO_G1_Second_Gate_Reg, + NITIO_G2_Second_Gate_Reg, + NITIO_G3_Second_Gate_Reg, + NITIO_G01_Status_Reg, + NITIO_G23_Status_Reg, + NITIO_G01_Joint_Reset_Reg, + NITIO_G23_Joint_Reset_Reg, + NITIO_G01_Joint_Status1_Reg, + NITIO_G23_Joint_Status1_Reg, + NITIO_G01_Joint_Status2_Reg, + NITIO_G23_Joint_Status2_Reg, + NITIO_G0_DMA_Config_Reg, + NITIO_G1_DMA_Config_Reg, + NITIO_G2_DMA_Config_Reg, + NITIO_G3_DMA_Config_Reg, + NITIO_G0_DMA_Status_Reg, + NITIO_G1_DMA_Status_Reg, + NITIO_G2_DMA_Status_Reg, + NITIO_G3_DMA_Status_Reg, + NITIO_G0_ABZ_Reg, + NITIO_G1_ABZ_Reg, + NITIO_G0_Interrupt_Acknowledge_Reg, + NITIO_G1_Interrupt_Acknowledge_Reg, + NITIO_G2_Interrupt_Acknowledge_Reg, + NITIO_G3_Interrupt_Acknowledge_Reg, + NITIO_G0_Status_Reg, + NITIO_G1_Status_Reg, + NITIO_G2_Status_Reg, + NITIO_G3_Status_Reg, + NITIO_G0_Interrupt_Enable_Reg, + NITIO_G1_Interrupt_Enable_Reg, + NITIO_G2_Interrupt_Enable_Reg, + NITIO_G3_Interrupt_Enable_Reg, + NITIO_Num_Registers, +}; + +enum ni_gpct_variant { + ni_gpct_variant_e_series, + ni_gpct_variant_m_series, + ni_gpct_variant_660x +}; + +struct ni_gpct { + struct ni_gpct_device *counter_dev; + unsigned counter_index; + unsigned chip_index; + uint64_t clock_period_ps; /* clock period in picoseconds */ + struct mite_channel *mite_chan; + spinlock_t lock; +}; + +struct ni_gpct_device { + struct comedi_device *dev; + void (*write_register) (struct ni_gpct * counter, unsigned bits, + enum ni_gpct_register reg); + unsigned (*read_register) (struct ni_gpct * counter, + enum ni_gpct_register reg); + enum ni_gpct_variant variant; + struct ni_gpct *counters; + unsigned num_counters; + unsigned regs[NITIO_Num_Registers]; + spinlock_t regs_lock; +}; + +extern struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device * dev, + void (*write_register) (struct ni_gpct * counter, unsigned bits, + enum ni_gpct_register reg), + unsigned (*read_register) (struct ni_gpct * counter, + enum ni_gpct_register reg), enum ni_gpct_variant variant, + unsigned num_counters); +extern void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev); +extern void ni_tio_init_counter(struct ni_gpct *counter); +extern int ni_tio_rinsn(struct ni_gpct *counter, + struct comedi_insn * insn, unsigned int * data); +extern int ni_tio_insn_config(struct ni_gpct *counter, + struct comedi_insn * insn, unsigned int * data); +extern int ni_tio_winsn(struct ni_gpct *counter, + struct comedi_insn * insn, unsigned int * data); +extern int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async); +extern int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd * cmd); +extern int ni_tio_cancel(struct ni_gpct *counter); +extern void ni_tio_handle_interrupt(struct ni_gpct *counter, + struct comedi_subdevice * s); +extern void ni_tio_set_mite_channel(struct ni_gpct *counter, + struct mite_channel *mite_chan); +extern void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, + int *gate_error, int *tc_error, int *perm_stale_data, int *stale_data); + +static inline struct ni_gpct *subdev_to_counter(struct comedi_subdevice * s) +{ + return s->private; +} + +#endif /* _COMEDI_NI_TIO_H */ diff --git a/drivers/staging/comedi/drivers/ni_tio_internal.h b/drivers/staging/comedi/drivers/ni_tio_internal.h new file mode 100644 index 000000000000..ac5b171cbe18 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_tio_internal.h @@ -0,0 +1,774 @@ +/* + drivers/ni_tio_internal.h + Header file for NI general purpose counter support code (ni_tio.c and + ni_tiocmd.c) + + COMEDI - Linux Control and Measurement Device Interface + + 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 _COMEDI_NI_TIO_INTERNAL_H +#define _COMEDI_NI_TIO_INTERNAL_H + +#include "ni_tio.h" + +static inline enum ni_gpct_register NITIO_Gi_Autoincrement_Reg(unsigned + counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_Autoincrement_Reg; + break; + case 1: + return NITIO_G1_Autoincrement_Reg; + break; + case 2: + return NITIO_G2_Autoincrement_Reg; + break; + case 3: + return NITIO_G3_Autoincrement_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_Command_Reg(unsigned counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_Command_Reg; + break; + case 1: + return NITIO_G1_Command_Reg; + break; + case 2: + return NITIO_G2_Command_Reg; + break; + case 3: + return NITIO_G3_Command_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_Counting_Mode_Reg(unsigned + counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_Counting_Mode_Reg; + break; + case 1: + return NITIO_G1_Counting_Mode_Reg; + break; + case 2: + return NITIO_G2_Counting_Mode_Reg; + break; + case 3: + return NITIO_G3_Counting_Mode_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_Input_Select_Reg(unsigned + counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_Input_Select_Reg; + break; + case 1: + return NITIO_G1_Input_Select_Reg; + break; + case 2: + return NITIO_G2_Input_Select_Reg; + break; + case 3: + return NITIO_G3_Input_Select_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gxx_Joint_Reset_Reg(unsigned + counter_index) +{ + switch (counter_index) { + case 0: + case 1: + return NITIO_G01_Joint_Reset_Reg; + break; + case 2: + case 3: + return NITIO_G23_Joint_Reset_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gxx_Joint_Status1_Reg(unsigned + counter_index) +{ + switch (counter_index) { + case 0: + case 1: + return NITIO_G01_Joint_Status1_Reg; + break; + case 2: + case 3: + return NITIO_G23_Joint_Status1_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gxx_Joint_Status2_Reg(unsigned + counter_index) +{ + switch (counter_index) { + case 0: + case 1: + return NITIO_G01_Joint_Status2_Reg; + break; + case 2: + case 3: + return NITIO_G23_Joint_Status2_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gxx_Status_Reg(unsigned counter_index) +{ + switch (counter_index) { + case 0: + case 1: + return NITIO_G01_Status_Reg; + break; + case 2: + case 3: + return NITIO_G23_Status_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_LoadA_Reg(unsigned counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_LoadA_Reg; + break; + case 1: + return NITIO_G1_LoadA_Reg; + break; + case 2: + return NITIO_G2_LoadA_Reg; + break; + case 3: + return NITIO_G3_LoadA_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_LoadB_Reg(unsigned counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_LoadB_Reg; + break; + case 1: + return NITIO_G1_LoadB_Reg; + break; + case 2: + return NITIO_G2_LoadB_Reg; + break; + case 3: + return NITIO_G3_LoadB_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_Mode_Reg(unsigned counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_Mode_Reg; + break; + case 1: + return NITIO_G1_Mode_Reg; + break; + case 2: + return NITIO_G2_Mode_Reg; + break; + case 3: + return NITIO_G3_Mode_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_SW_Save_Reg(int counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_SW_Save_Reg; + break; + case 1: + return NITIO_G1_SW_Save_Reg; + break; + case 2: + return NITIO_G2_SW_Save_Reg; + break; + case 3: + return NITIO_G3_SW_Save_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_Second_Gate_Reg(int counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_Second_Gate_Reg; + break; + case 1: + return NITIO_G1_Second_Gate_Reg; + break; + case 2: + return NITIO_G2_Second_Gate_Reg; + break; + case 3: + return NITIO_G3_Second_Gate_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_DMA_Config_Reg(int counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_DMA_Config_Reg; + break; + case 1: + return NITIO_G1_DMA_Config_Reg; + break; + case 2: + return NITIO_G2_DMA_Config_Reg; + break; + case 3: + return NITIO_G3_DMA_Config_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_DMA_Status_Reg(int counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_DMA_Status_Reg; + break; + case 1: + return NITIO_G1_DMA_Status_Reg; + break; + case 2: + return NITIO_G2_DMA_Status_Reg; + break; + case 3: + return NITIO_G3_DMA_Status_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_ABZ_Reg(int counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_ABZ_Reg; + break; + case 1: + return NITIO_G1_ABZ_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_Interrupt_Acknowledge_Reg(int + counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_Interrupt_Acknowledge_Reg; + break; + case 1: + return NITIO_G1_Interrupt_Acknowledge_Reg; + break; + case 2: + return NITIO_G2_Interrupt_Acknowledge_Reg; + break; + case 3: + return NITIO_G3_Interrupt_Acknowledge_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_Status_Reg(int counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_Status_Reg; + break; + case 1: + return NITIO_G1_Status_Reg; + break; + case 2: + return NITIO_G2_Status_Reg; + break; + case 3: + return NITIO_G3_Status_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline enum ni_gpct_register NITIO_Gi_Interrupt_Enable_Reg(int + counter_index) +{ + switch (counter_index) { + case 0: + return NITIO_G0_Interrupt_Enable_Reg; + break; + case 1: + return NITIO_G1_Interrupt_Enable_Reg; + break; + case 2: + return NITIO_G2_Interrupt_Enable_Reg; + break; + case 3: + return NITIO_G3_Interrupt_Enable_Reg; + break; + default: + BUG(); + break; + } + return 0; +} + +enum Gi_Auto_Increment_Reg_Bits { + Gi_Auto_Increment_Mask = 0xff +}; + +#define Gi_Up_Down_Shift 5 +enum Gi_Command_Reg_Bits { + Gi_Arm_Bit = 0x1, + Gi_Save_Trace_Bit = 0x2, + Gi_Load_Bit = 0x4, + Gi_Disarm_Bit = 0x10, + Gi_Up_Down_Mask = 0x3 << Gi_Up_Down_Shift, + Gi_Always_Down_Bits = 0x0 << Gi_Up_Down_Shift, + Gi_Always_Up_Bits = 0x1 << Gi_Up_Down_Shift, + Gi_Up_Down_Hardware_IO_Bits = 0x2 << Gi_Up_Down_Shift, + Gi_Up_Down_Hardware_Gate_Bits = 0x3 << Gi_Up_Down_Shift, + Gi_Write_Switch_Bit = 0x80, + Gi_Synchronize_Gate_Bit = 0x100, + Gi_Little_Big_Endian_Bit = 0x200, + Gi_Bank_Switch_Start_Bit = 0x400, + Gi_Bank_Switch_Mode_Bit = 0x800, + Gi_Bank_Switch_Enable_Bit = 0x1000, + Gi_Arm_Copy_Bit = 0x2000, + Gi_Save_Trace_Copy_Bit = 0x4000, + Gi_Disarm_Copy_Bit = 0x8000 +}; + +#define Gi_Index_Phase_Bitshift 5 +#define Gi_HW_Arm_Select_Shift 8 +enum Gi_Counting_Mode_Reg_Bits { + Gi_Counting_Mode_Mask = 0x7, + Gi_Counting_Mode_Normal_Bits = 0x0, + Gi_Counting_Mode_QuadratureX1_Bits = 0x1, + Gi_Counting_Mode_QuadratureX2_Bits = 0x2, + Gi_Counting_Mode_QuadratureX4_Bits = 0x3, + Gi_Counting_Mode_Two_Pulse_Bits = 0x4, + Gi_Counting_Mode_Sync_Source_Bits = 0x6, + Gi_Index_Mode_Bit = 0x10, + Gi_Index_Phase_Mask = 0x3 << Gi_Index_Phase_Bitshift, + Gi_Index_Phase_LowA_LowB = 0x0 << Gi_Index_Phase_Bitshift, + Gi_Index_Phase_LowA_HighB = 0x1 << Gi_Index_Phase_Bitshift, + Gi_Index_Phase_HighA_LowB = 0x2 << Gi_Index_Phase_Bitshift, + Gi_Index_Phase_HighA_HighB = 0x3 << Gi_Index_Phase_Bitshift, + Gi_HW_Arm_Enable_Bit = 0x80, /* from m-series example code, not documented in 660x register level manual */ + Gi_660x_HW_Arm_Select_Mask = 0x7 << Gi_HW_Arm_Select_Shift, /* from m-series example code, not documented in 660x register level manual */ + Gi_660x_Prescale_X8_Bit = 0x1000, + Gi_M_Series_Prescale_X8_Bit = 0x2000, + Gi_M_Series_HW_Arm_Select_Mask = 0x1f << Gi_HW_Arm_Select_Shift, + /* must be set for clocks over 40MHz, which includes synchronous counting and quadrature modes */ + Gi_660x_Alternate_Sync_Bit = 0x2000, + Gi_M_Series_Alternate_Sync_Bit = 0x4000, + Gi_660x_Prescale_X2_Bit = 0x4000, /* from m-series example code, not documented in 660x register level manual */ + Gi_M_Series_Prescale_X2_Bit = 0x8000, +}; + +#define Gi_Source_Select_Shift 2 +#define Gi_Gate_Select_Shift 7 +enum Gi_Input_Select_Bits { + Gi_Read_Acknowledges_Irq = 0x1, // not present on 660x + Gi_Write_Acknowledges_Irq = 0x2, // not present on 660x + Gi_Source_Select_Mask = 0x7c, + Gi_Gate_Select_Mask = 0x1f << Gi_Gate_Select_Shift, + Gi_Gate_Select_Load_Source_Bit = 0x1000, + Gi_Or_Gate_Bit = 0x2000, + Gi_Output_Polarity_Bit = 0x4000, /* set to invert */ + Gi_Source_Polarity_Bit = 0x8000 /* set to invert */ +}; + +enum Gi_Mode_Bits { + Gi_Gating_Mode_Mask = 0x3, + Gi_Gating_Disabled_Bits = 0x0, + Gi_Level_Gating_Bits = 0x1, + Gi_Rising_Edge_Gating_Bits = 0x2, + Gi_Falling_Edge_Gating_Bits = 0x3, + Gi_Gate_On_Both_Edges_Bit = 0x4, /* used in conjunction with rising edge gating mode */ + Gi_Trigger_Mode_for_Edge_Gate_Mask = 0x18, + Gi_Edge_Gate_Starts_Stops_Bits = 0x0, + Gi_Edge_Gate_Stops_Starts_Bits = 0x8, + Gi_Edge_Gate_Starts_Bits = 0x10, + Gi_Edge_Gate_No_Starts_or_Stops_Bits = 0x18, + Gi_Stop_Mode_Mask = 0x60, + Gi_Stop_on_Gate_Bits = 0x00, + Gi_Stop_on_Gate_or_TC_Bits = 0x20, + Gi_Stop_on_Gate_or_Second_TC_Bits = 0x40, + Gi_Load_Source_Select_Bit = 0x80, + Gi_Output_Mode_Mask = 0x300, + Gi_Output_TC_Pulse_Bits = 0x100, + Gi_Output_TC_Toggle_Bits = 0x200, + Gi_Output_TC_or_Gate_Toggle_Bits = 0x300, + Gi_Counting_Once_Mask = 0xc00, + Gi_No_Hardware_Disarm_Bits = 0x000, + Gi_Disarm_at_TC_Bits = 0x400, + Gi_Disarm_at_Gate_Bits = 0x800, + Gi_Disarm_at_TC_or_Gate_Bits = 0xc00, + Gi_Loading_On_TC_Bit = 0x1000, + Gi_Gate_Polarity_Bit = 0x2000, + Gi_Loading_On_Gate_Bit = 0x4000, + Gi_Reload_Source_Switching_Bit = 0x8000 +}; + +#define Gi_Second_Gate_Select_Shift 7 +/*FIXME: m-series has a second gate subselect bit */ +/*FIXME: m-series second gate sources are undocumented (by NI)*/ +enum Gi_Second_Gate_Bits { + Gi_Second_Gate_Mode_Bit = 0x1, + Gi_Second_Gate_Select_Mask = 0x1f << Gi_Second_Gate_Select_Shift, + Gi_Second_Gate_Polarity_Bit = 0x2000, + Gi_Second_Gate_Subselect_Bit = 0x4000, /* m-series only */ + Gi_Source_Subselect_Bit = 0x8000 /* m-series only */ +}; +static inline unsigned Gi_Second_Gate_Select_Bits(unsigned second_gate_select) +{ + return (second_gate_select << Gi_Second_Gate_Select_Shift) & + Gi_Second_Gate_Select_Mask; +} + +enum Gxx_Status_Bits { + G0_Save_Bit = 0x1, + G1_Save_Bit = 0x2, + G0_Counting_Bit = 0x4, + G1_Counting_Bit = 0x8, + G0_Next_Load_Source_Bit = 0x10, + G1_Next_Load_Source_Bit = 0x20, + G0_Stale_Data_Bit = 0x40, + G1_Stale_Data_Bit = 0x80, + G0_Armed_Bit = 0x100, + G1_Armed_Bit = 0x200, + G0_No_Load_Between_Gates_Bit = 0x400, + G1_No_Load_Between_Gates_Bit = 0x800, + G0_TC_Error_Bit = 0x1000, + G1_TC_Error_Bit = 0x2000, + G0_Gate_Error_Bit = 0x4000, + G1_Gate_Error_Bit = 0x8000 +}; +static inline enum Gxx_Status_Bits Gi_Counting_Bit(unsigned counter_index) +{ + if (counter_index % 2) + return G1_Counting_Bit; + return G0_Counting_Bit; +} +static inline enum Gxx_Status_Bits Gi_Armed_Bit(unsigned counter_index) +{ + if (counter_index % 2) + return G1_Armed_Bit; + return G0_Armed_Bit; +} +static inline enum Gxx_Status_Bits Gi_Next_Load_Source_Bit(unsigned + counter_index) +{ + if (counter_index % 2) + return G1_Next_Load_Source_Bit; + return G0_Next_Load_Source_Bit; +} +static inline enum Gxx_Status_Bits Gi_Stale_Data_Bit(unsigned counter_index) +{ + if (counter_index % 2) + return G1_Stale_Data_Bit; + return G0_Stale_Data_Bit; +} +static inline enum Gxx_Status_Bits Gi_TC_Error_Bit(unsigned counter_index) +{ + if (counter_index % 2) + return G1_TC_Error_Bit; + return G0_TC_Error_Bit; +} +static inline enum Gxx_Status_Bits Gi_Gate_Error_Bit(unsigned counter_index) +{ + if (counter_index % 2) + return G1_Gate_Error_Bit; + return G0_Gate_Error_Bit; +} + +/* joint reset register bits */ +static inline unsigned Gi_Reset_Bit(unsigned counter_index) +{ + return 0x1 << (2 + (counter_index % 2)); +} + +enum Gxx_Joint_Status2_Bits { + G0_Output_Bit = 0x1, + G1_Output_Bit = 0x2, + G0_HW_Save_Bit = 0x1000, + G1_HW_Save_Bit = 0x2000, + G0_Permanent_Stale_Bit = 0x4000, + G1_Permanent_Stale_Bit = 0x8000 +}; +static inline enum Gxx_Joint_Status2_Bits Gi_Permanent_Stale_Bit(unsigned + counter_index) +{ + if (counter_index % 2) + return G1_Permanent_Stale_Bit; + return G0_Permanent_Stale_Bit; +} + +enum Gi_DMA_Config_Reg_Bits { + Gi_DMA_Enable_Bit = 0x1, + Gi_DMA_Write_Bit = 0x2, + Gi_DMA_Int_Bit = 0x4 +}; + +enum Gi_DMA_Status_Reg_Bits { + Gi_DMA_Readbank_Bit = 0x2000, + Gi_DRQ_Error_Bit = 0x4000, + Gi_DRQ_Status_Bit = 0x8000 +}; + +enum G02_Interrupt_Acknowledge_Bits { + G0_Gate_Error_Confirm_Bit = 0x20, + G0_TC_Error_Confirm_Bit = 0x40 +}; +enum G13_Interrupt_Acknowledge_Bits { + G1_Gate_Error_Confirm_Bit = 0x2, + G1_TC_Error_Confirm_Bit = 0x4 +}; +static inline unsigned Gi_Gate_Error_Confirm_Bit(unsigned counter_index) +{ + if (counter_index % 2) + return G1_Gate_Error_Confirm_Bit; + return G0_Gate_Error_Confirm_Bit; +} +static inline unsigned Gi_TC_Error_Confirm_Bit(unsigned counter_index) +{ + if (counter_index % 2) + return G1_TC_Error_Confirm_Bit; + return G0_TC_Error_Confirm_Bit; +} + +// bits that are the same in G0/G2 and G1/G3 interrupt acknowledge registers +enum Gxx_Interrupt_Acknowledge_Bits { + Gi_TC_Interrupt_Ack_Bit = 0x4000, + Gi_Gate_Interrupt_Ack_Bit = 0x8000 +}; + +enum Gi_Status_Bits { + Gi_Gate_Interrupt_Bit = 0x4, + Gi_TC_Bit = 0x8, + Gi_Interrupt_Bit = 0x8000 +}; + +enum G02_Interrupt_Enable_Bits { + G0_TC_Interrupt_Enable_Bit = 0x40, + G0_Gate_Interrupt_Enable_Bit = 0x100 +}; +enum G13_Interrupt_Enable_Bits { + G1_TC_Interrupt_Enable_Bit = 0x200, + G1_Gate_Interrupt_Enable_Bit = 0x400 +}; +static inline unsigned Gi_Gate_Interrupt_Enable_Bit(unsigned counter_index) +{ + unsigned bit; + + if (counter_index % 2) { + bit = G1_Gate_Interrupt_Enable_Bit; + } else { + bit = G0_Gate_Interrupt_Enable_Bit; + } + return bit; +} + +static inline void write_register(struct ni_gpct *counter, unsigned bits, + enum ni_gpct_register reg) +{ + BUG_ON(reg >= NITIO_Num_Registers); + counter->counter_dev->write_register(counter, bits, reg); +} + +static inline unsigned read_register(struct ni_gpct *counter, + enum ni_gpct_register reg) +{ + BUG_ON(reg >= NITIO_Num_Registers); + return counter->counter_dev->read_register(counter, reg); +} + +static inline int ni_tio_counting_mode_registers_present( + const struct ni_gpct_device *counter_dev) +{ + switch (counter_dev->variant) { + case ni_gpct_variant_e_series: + return 0; + break; + case ni_gpct_variant_m_series: + case ni_gpct_variant_660x: + return 1; + break; + default: + BUG(); + break; + } + return 0; +} + +static inline void ni_tio_set_bits_transient(struct ni_gpct *counter, + enum ni_gpct_register register_index, unsigned bit_mask, + unsigned bit_values, unsigned transient_bit_values) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + unsigned long flags; + + BUG_ON(register_index >= NITIO_Num_Registers); + comedi_spin_lock_irqsave(&counter_dev->regs_lock, flags); + counter_dev->regs[register_index] &= ~bit_mask; + counter_dev->regs[register_index] |= (bit_values & bit_mask); + write_register(counter, + counter_dev->regs[register_index] | transient_bit_values, + register_index); + mmiowb(); + comedi_spin_unlock_irqrestore(&counter_dev->regs_lock, flags); +} + +/* ni_tio_set_bits( ) is for safely writing to registers whose bits may be +twiddled in interrupt context, or whose software copy may be read in interrupt context. +*/ +static inline void ni_tio_set_bits(struct ni_gpct *counter, + enum ni_gpct_register register_index, unsigned bit_mask, + unsigned bit_values) +{ + ni_tio_set_bits_transient(counter, register_index, bit_mask, bit_values, + 0x0); +} + +/* ni_tio_get_soft_copy( ) is for safely reading the software copy of a register +whose bits might be modified in interrupt context, or whose software copy +might need to be read in interrupt context. +*/ +static inline unsigned ni_tio_get_soft_copy(const struct ni_gpct *counter, + enum ni_gpct_register register_index) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + unsigned long flags; + unsigned value; + + BUG_ON(register_index >= NITIO_Num_Registers); + comedi_spin_lock_irqsave(&counter_dev->regs_lock, flags); + value = counter_dev->regs[register_index]; + comedi_spin_unlock_irqrestore(&counter_dev->regs_lock, flags); + return value; +} + +int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger); +int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, + unsigned int gate_source); + +#endif /* _COMEDI_NI_TIO_INTERNAL_H */ diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c new file mode 100644 index 000000000000..16a26e73c994 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -0,0 +1,523 @@ +/* + comedi/drivers/ni_tiocmd.c + Command support for NI general purpose counters + + Copyright (C) 2006 Frank Mori Hess + + 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: ni_tiocmd +Description: National Instruments general purpose counters command support +Devices: +Author: J.P. Mellor , + Herman.Bruyninckx@mech.kuleuven.ac.be, + Wim.Meeussen@mech.kuleuven.ac.be, + Klaas.Gadeyne@mech.kuleuven.ac.be, + Frank Mori Hess +Updated: Fri, 11 Apr 2008 12:32:35 +0100 +Status: works + +This module is not used directly by end-users. Rather, it +is used by other drivers (for example ni_660x and ni_pcimio) +to provide command support for NI's general purpose counters. +It was originally split out of ni_tio.c to stop the 'ni_tio' +module depending on the 'mite' module. + +References: +DAQ 660x Register-Level Programmer Manual (NI 370505A-01) +DAQ 6601/6602 User Manual (NI 322137B-01) +340934b.pdf DAQ-STC reference manual + +*/ +/* +TODO: + Support use of both banks X and Y +*/ + +#include "ni_tio_internal.h" +#include "mite.h" + +MODULE_AUTHOR("Comedi "); +MODULE_DESCRIPTION("Comedi command support for NI general-purpose counters"); +MODULE_LICENSE("GPL"); + +static void ni_tio_configure_dma(struct ni_gpct *counter, short enable, + short read_not_write) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + unsigned input_select_bits = 0; + + if (enable) { + if (read_not_write) { + input_select_bits |= Gi_Read_Acknowledges_Irq; + } else { + input_select_bits |= Gi_Write_Acknowledges_Irq; + } + } + ni_tio_set_bits(counter, + NITIO_Gi_Input_Select_Reg(counter->counter_index), + Gi_Read_Acknowledges_Irq | Gi_Write_Acknowledges_Irq, + input_select_bits); + switch (counter_dev->variant) { + case ni_gpct_variant_e_series: + break; + case ni_gpct_variant_m_series: + case ni_gpct_variant_660x: + { + unsigned gi_dma_config_bits = 0; + + if (enable) { + gi_dma_config_bits |= Gi_DMA_Enable_Bit; + gi_dma_config_bits |= Gi_DMA_Int_Bit; + } + if (read_not_write == 0) { + gi_dma_config_bits |= Gi_DMA_Write_Bit; + } + ni_tio_set_bits(counter, + NITIO_Gi_DMA_Config_Reg(counter->counter_index), + Gi_DMA_Enable_Bit | Gi_DMA_Int_Bit | + Gi_DMA_Write_Bit, gi_dma_config_bits); + } + break; + } +} + +static int ni_tio_input_inttrig(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ + unsigned long flags; + int retval = 0; + struct ni_gpct *counter = s->private; + + BUG_ON(counter == NULL); + if (trignum != 0) + return -EINVAL; + + comedi_spin_lock_irqsave(&counter->lock, flags); + if (counter->mite_chan) + mite_dma_arm(counter->mite_chan); + else + retval = -EIO; + comedi_spin_unlock_irqrestore(&counter->lock, flags); + if (retval < 0) + return retval; + retval = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); + s->async->inttrig = NULL; + + return retval; +} + +static int ni_tio_input_cmd(struct ni_gpct *counter, struct comedi_async *async) +{ + struct ni_gpct_device *counter_dev = counter->counter_dev; + struct comedi_cmd *cmd = &async->cmd; + int retval = 0; + + /* write alloc the entire buffer */ + comedi_buf_write_alloc(async, async->prealloc_bufsz); + counter->mite_chan->dir = COMEDI_INPUT; + switch (counter_dev->variant) { + case ni_gpct_variant_m_series: + case ni_gpct_variant_660x: + mite_prep_dma(counter->mite_chan, 32, 32); + break; + case ni_gpct_variant_e_series: + mite_prep_dma(counter->mite_chan, 16, 32); + break; + default: + BUG(); + break; + } + ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), + Gi_Save_Trace_Bit, 0); + ni_tio_configure_dma(counter, 1, 1); + switch (cmd->start_src) { + case TRIG_NOW: + async->inttrig = NULL; + mite_dma_arm(counter->mite_chan); + retval = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); + break; + case TRIG_INT: + async->inttrig = &ni_tio_input_inttrig; + break; + case TRIG_EXT: + async->inttrig = NULL; + mite_dma_arm(counter->mite_chan); + retval = ni_tio_arm(counter, 1, cmd->start_arg); + case TRIG_OTHER: + async->inttrig = NULL; + mite_dma_arm(counter->mite_chan); + break; + default: + BUG(); + break; + } + return retval; +} + +static int ni_tio_output_cmd(struct ni_gpct *counter, struct comedi_async *async) +{ + rt_printk("ni_tio: output commands not yet implemented.\n"); + return -ENOTSUPP; + + counter->mite_chan->dir = COMEDI_OUTPUT; + mite_prep_dma(counter->mite_chan, 32, 32); + ni_tio_configure_dma(counter, 1, 0); + mite_dma_arm(counter->mite_chan); + return ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); +} + +static int ni_tio_cmd_setup(struct ni_gpct *counter, struct comedi_async *async) +{ + struct comedi_cmd *cmd = &async->cmd; + int set_gate_source = 0; + unsigned gate_source; + int retval = 0; + + if (cmd->scan_begin_src == TRIG_EXT) { + set_gate_source = 1; + gate_source = cmd->scan_begin_arg; + } else if (cmd->convert_src == TRIG_EXT) { + set_gate_source = 1; + gate_source = cmd->convert_arg; + } + if (set_gate_source) { + retval = ni_tio_set_gate_src(counter, 0, gate_source); + } + if (cmd->flags & TRIG_WAKE_EOS) { + ni_tio_set_bits(counter, + NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), + Gi_Gate_Interrupt_Enable_Bit(counter->counter_index), + Gi_Gate_Interrupt_Enable_Bit(counter->counter_index)); + } + return retval; +} + +int ni_tio_cmd(struct ni_gpct *counter, struct comedi_async *async) +{ + struct comedi_cmd *cmd = &async->cmd; + int retval = 0; + unsigned long flags; + + comedi_spin_lock_irqsave(&counter->lock, flags); + if (counter->mite_chan == NULL) { + rt_printk + ("ni_tio: commands only supported with DMA. Interrupt-driven commands not yet implemented.\n"); + retval = -EIO; + } else { + retval = ni_tio_cmd_setup(counter, async); + if (retval == 0) { + if (cmd->flags & CMDF_WRITE) { + retval = ni_tio_output_cmd(counter, async); + } else { + retval = ni_tio_input_cmd(counter, async); + } + } + } + comedi_spin_unlock_irqrestore(&counter->lock, flags); + return retval; +} + +int ni_tio_cmdtest(struct ni_gpct *counter, struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + int sources; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + sources = TRIG_NOW | TRIG_INT | TRIG_OTHER; + if (ni_tio_counting_mode_registers_present(counter->counter_dev)) + sources |= TRIG_EXT; + cmd->start_src &= sources; + if (!cmd->start_src || tmp != cmd->start_src) + err++; + + tmp = cmd->scan_begin_src; + cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + sources = TRIG_NOW | TRIG_EXT | TRIG_OTHER; + cmd->convert_src &= sources; + 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: make sure trigger sources are unique... */ + + if (cmd->start_src != TRIG_NOW && + cmd->start_src != TRIG_INT && + cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_OTHER) + err++; + if (cmd->scan_begin_src != TRIG_FOLLOW && + cmd->scan_begin_src != TRIG_EXT && + cmd->scan_begin_src != TRIG_OTHER) + err++; + if (cmd->convert_src != TRIG_OTHER && + cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_NONE) + err++; + /* ... and mutually compatible */ + if (cmd->convert_src != TRIG_NOW && cmd->scan_begin_src != TRIG_FOLLOW) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + if (cmd->start_src != TRIG_EXT) { + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + } + if (cmd->scan_begin_src != TRIG_EXT) { + if (cmd->scan_begin_arg) { + cmd->scan_begin_arg = 0; + err++; + } + } + if (cmd->convert_src != TRIG_EXT) { + if (cmd->convert_arg) { + cmd->convert_arg = 0; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + if (cmd->stop_src == TRIG_NONE) { + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (err) + return 4; + + return 0; +} + +int ni_tio_cancel(struct ni_gpct *counter) +{ + unsigned long flags; + + ni_tio_arm(counter, 0, 0); + comedi_spin_lock_irqsave(&counter->lock, flags); + if (counter->mite_chan) { + mite_dma_disarm(counter->mite_chan); + } + comedi_spin_unlock_irqrestore(&counter->lock, flags); + ni_tio_configure_dma(counter, 0, 0); + + ni_tio_set_bits(counter, + NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), + Gi_Gate_Interrupt_Enable_Bit(counter->counter_index), 0x0); + return 0; +} + + /* During buffered input counter operation for e-series, the gate interrupt is acked + automatically by the dma controller, due to the Gi_Read/Write_Acknowledges_IRQ bits + in the input select register. */ +static int should_ack_gate(struct ni_gpct *counter) +{ + unsigned long flags; + int retval = 0; + + switch (counter->counter_dev->variant) { + case ni_gpct_variant_m_series: + case ni_gpct_variant_660x: // not sure if 660x really supports gate interrupts (the bits are not listed in register-level manual) + return 1; + break; + case ni_gpct_variant_e_series: + comedi_spin_lock_irqsave(&counter->lock, flags); + { + if (counter->mite_chan == NULL || + counter->mite_chan->dir != COMEDI_INPUT || + (mite_done(counter->mite_chan))) { + retval = 1; + } + } + comedi_spin_unlock_irqrestore(&counter->lock, flags); + break; + } + return retval; +} + +void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter, int *gate_error, + int *tc_error, int *perm_stale_data, int *stale_data) +{ + const unsigned short gxx_status = read_register(counter, + NITIO_Gxx_Status_Reg(counter->counter_index)); + const unsigned short gi_status = read_register(counter, + NITIO_Gi_Status_Reg(counter->counter_index)); + unsigned ack = 0; + + if (gate_error) + *gate_error = 0; + if (tc_error) + *tc_error = 0; + if (perm_stale_data) + *perm_stale_data = 0; + if (stale_data) + *stale_data = 0; + + if (gxx_status & Gi_Gate_Error_Bit(counter->counter_index)) { + ack |= Gi_Gate_Error_Confirm_Bit(counter->counter_index); + if (gate_error) { + /*660x don't support automatic acknowledgement of gate interrupt via dma read/write + and report bogus gate errors */ + if (counter->counter_dev->variant != + ni_gpct_variant_660x) { + *gate_error = 1; + } + } + } + if (gxx_status & Gi_TC_Error_Bit(counter->counter_index)) { + ack |= Gi_TC_Error_Confirm_Bit(counter->counter_index); + if (tc_error) + *tc_error = 1; + } + if (gi_status & Gi_TC_Bit) { + ack |= Gi_TC_Interrupt_Ack_Bit; + } + if (gi_status & Gi_Gate_Interrupt_Bit) { + if (should_ack_gate(counter)) + ack |= Gi_Gate_Interrupt_Ack_Bit; + } + if (ack) + write_register(counter, ack, + NITIO_Gi_Interrupt_Acknowledge_Reg(counter-> + counter_index)); + if (ni_tio_get_soft_copy(counter, + NITIO_Gi_Mode_Reg(counter-> + counter_index)) & Gi_Loading_On_Gate_Bit) { + if (gxx_status & Gi_Stale_Data_Bit(counter->counter_index)) { + if (stale_data) + *stale_data = 1; + } + if (read_register(counter, + NITIO_Gxx_Joint_Status2_Reg(counter-> + counter_index)) & + Gi_Permanent_Stale_Bit(counter->counter_index)) { + rt_printk("%s: Gi_Permanent_Stale_Data detected.\n", + __FUNCTION__); + if (perm_stale_data) + *perm_stale_data = 1; + } + } +} + +void ni_tio_handle_interrupt(struct ni_gpct *counter, struct comedi_subdevice * s) +{ + unsigned gpct_mite_status; + unsigned long flags; + int gate_error; + int tc_error; + int perm_stale_data; + + ni_tio_acknowledge_and_confirm(counter, &gate_error, &tc_error, + &perm_stale_data, NULL); + if (gate_error) { + rt_printk("%s: Gi_Gate_Error detected.\n", __FUNCTION__); + s->async->events |= COMEDI_CB_OVERFLOW; + } + if (perm_stale_data) { + s->async->events |= COMEDI_CB_ERROR; + } + switch (counter->counter_dev->variant) { + case ni_gpct_variant_m_series: + case ni_gpct_variant_660x: + if (read_register(counter, + NITIO_Gi_DMA_Status_Reg(counter-> + counter_index)) & Gi_DRQ_Error_Bit) { + rt_printk("%s: Gi_DRQ_Error detected.\n", __FUNCTION__); + s->async->events |= COMEDI_CB_OVERFLOW; + } + break; + case ni_gpct_variant_e_series: + break; + } + comedi_spin_lock_irqsave(&counter->lock, flags); + if (counter->mite_chan == NULL) { + comedi_spin_unlock_irqrestore(&counter->lock, flags); + return; + } + gpct_mite_status = mite_get_status(counter->mite_chan); + if (gpct_mite_status & CHSR_LINKC) { + writel(CHOR_CLRLC, + counter->mite_chan->mite->mite_io_addr + + MITE_CHOR(counter->mite_chan->channel)); + } + mite_sync_input_dma(counter->mite_chan, s->async); + comedi_spin_unlock_irqrestore(&counter->lock, flags); +} + +void ni_tio_set_mite_channel(struct ni_gpct *counter, + struct mite_channel *mite_chan) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&counter->lock, flags); + counter->mite_chan = mite_chan; + comedi_spin_unlock_irqrestore(&counter->lock, flags); +} + +static int __init ni_tiocmd_init_module(void) +{ + return 0; +} + +module_init(ni_tiocmd_init_module); + +static void __exit ni_tiocmd_cleanup_module(void) +{ +} + +module_exit(ni_tiocmd_cleanup_module); + +EXPORT_SYMBOL_GPL(ni_tio_cmd); +EXPORT_SYMBOL_GPL(ni_tio_cmdtest); +EXPORT_SYMBOL_GPL(ni_tio_cancel); +EXPORT_SYMBOL_GPL(ni_tio_handle_interrupt); +EXPORT_SYMBOL_GPL(ni_tio_set_mite_channel); +EXPORT_SYMBOL_GPL(ni_tio_acknowledge_and_confirm); diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c new file mode 100644 index 000000000000..ce42506d47b5 --- /dev/null +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -0,0 +1,623 @@ +/* + comedi/drivers/pcl711.c + hardware driver for PC-LabCard PCL-711 and AdSys ACL-8112 + and compatibles + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998 David A. Schleef + Janne Jalkanen + Eric Bunn + + 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: pcl711 +Description: Advantech PCL-711 and 711b, ADLink ACL-8112 +Author: ds, Janne Jalkanen , Eric Bunn +Status: mostly complete +Devices: [Advantech] PCL-711 (pcl711), PCL-711B (pcl711b), + [AdLink] ACL-8112HG (acl8112hg), ACL-8112DG (acl8112dg) + +Since these boards do not have DMA or FIFOs, only immediate mode is +supported. + +*/ + +/* + Dave Andruczyk also wrote a + driver for the PCL-711. I used a few ideas from his driver + here. His driver also has more comments, if you are + interested in understanding how this driver works. + http://tech.buffalostate.edu/~dave/driver/ + + The ACL-8112 driver was hacked from the sources of the PCL-711 + driver (the 744 chip used on the 8112 is almost the same as + the 711b chip, but it has more I/O channels) by + Janne Jalkanen (jalkanen@cs.hut.fi) and + Erik Bunn (ebu@cs.hut.fi). Remerged with the PCL-711 driver + by ds. + + [acl-8112] + This driver supports both TRIGNOW and TRIGCLK, + but does not yet support DMA transfers. It also supports + both high (HG) and low (DG) versions of the card, though + the HG version has been untested. + + */ + +#include "../comedidev.h" + +#include +#include + +#include "8253.h" + +#define PCL711_SIZE 16 + +#define PCL711_CTR0 0 +#define PCL711_CTR1 1 +#define PCL711_CTR2 2 +#define PCL711_CTRCTL 3 +#define PCL711_AD_LO 4 +#define PCL711_DA0_LO 4 +#define PCL711_AD_HI 5 +#define PCL711_DA0_HI 5 +#define PCL711_DI_LO 6 +#define PCL711_DA1_LO 6 +#define PCL711_DI_HI 7 +#define PCL711_DA1_HI 7 +#define PCL711_CLRINTR 8 +#define PCL711_GAIN 9 +#define PCL711_MUX 10 +#define PCL711_MODE 11 +#define PCL711_SOFTTRIG 12 +#define PCL711_DO_LO 13 +#define PCL711_DO_HI 14 + +static const struct comedi_lrange range_pcl711b_ai = { 5, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + BIP_RANGE(0.3125) + } +}; +static const struct comedi_lrange range_acl8112hg_ai = { 12, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.005), + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01), + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.01) + } +}; +static const struct comedi_lrange range_acl8112dg_ai = { 9, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + BIP_RANGE(10) + } +}; + +/* + * flags + */ + +#define PCL711_TIMEOUT 100 +#define PCL711_DRDY 0x10 + +static const int i8253_osc_base = 500; /* 2 Mhz */ + +struct pcl711_board { + + const char *name; + int is_pcl711b; + int is_8112; + int is_dg; + int n_ranges; + int n_aichan; + int n_aochan; + int maxirq; + const struct comedi_lrange *ai_range_type; +}; + + +static const struct pcl711_board boardtypes[] = { + {"pcl711", 0, 0, 0, 5, 8, 1, 0, &range_bipolar5}, + {"pcl711b", 1, 0, 0, 5, 8, 1, 7, &range_pcl711b_ai}, + {"acl8112hg", 0, 1, 0, 12, 16, 2, 15, &range_acl8112hg_ai}, + {"acl8112dg", 0, 1, 1, 9, 16, 2, 15, &range_acl8112dg_ai}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl711_board)) +#define this_board ((const struct pcl711_board *)dev->board_ptr) + +static int pcl711_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcl711_detach(struct comedi_device * dev); +static struct comedi_driver driver_pcl711 = { + driver_name:"pcl711", + module:THIS_MODULE, + attach:pcl711_attach, + detach:pcl711_detach, + board_name:&boardtypes[0].name, + num_names:n_boardtypes, + offset:sizeof(struct pcl711_board), +}; + +COMEDI_INITCLEANUP(driver_pcl711); + +struct pcl711_private { + + int board; + int adchan; + int ntrig; + int aip[8]; + int mode; + unsigned int ao_readback[2]; + unsigned int divisor1; + unsigned int divisor2; +}; + + +#define devpriv ((struct pcl711_private *)dev->private) + +static irqreturn_t pcl711_interrupt(int irq, void *d PT_REGS_ARG) +{ + int lo, hi; + int data; + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + + if (!dev->attached) { + comedi_error(dev, "spurious interrupt"); + return IRQ_HANDLED; + } + + hi = inb(dev->iobase + PCL711_AD_HI); + lo = inb(dev->iobase + PCL711_AD_LO); + outb(0, dev->iobase + PCL711_CLRINTR); + + data = (hi << 8) | lo; + + /* FIXME! Nothing else sets ntrig! */ + if (!(--devpriv->ntrig)) { + if (this_board->is_8112) { + outb(1, dev->iobase + PCL711_MODE); + } else { + outb(0, dev->iobase + PCL711_MODE); + } + + s->async->events |= COMEDI_CB_EOA; + } + comedi_event(dev, s); + return IRQ_HANDLED; +} + +static void pcl711_set_changain(struct comedi_device * dev, int chan) +{ + int chan_register; + + outb(CR_RANGE(chan), dev->iobase + PCL711_GAIN); + + chan_register = CR_CHAN(chan); + + if (this_board->is_8112) { + + /* + * Set the correct channel. The two channel banks are switched + * using the mask value. + * NB: To use differential channels, you should use mask = 0x30, + * but I haven't written the support for this yet. /JJ + */ + + if (chan_register >= 8) { + chan_register = 0x20 | (chan_register & 0x7); + } else { + chan_register |= 0x10; + } + } else { + outb(chan_register, dev->iobase + PCL711_MUX); + } +} + +static int pcl711_ai_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, n; + int hi, lo; + + pcl711_set_changain(dev, insn->chanspec); + + for (n = 0; n < insn->n; n++) { + /* + * Write the correct mode (software polling) and start polling by writing + * to the trigger register + */ + outb(1, dev->iobase + PCL711_MODE); + + if (this_board->is_8112) { + } else { + outb(0, dev->iobase + PCL711_SOFTTRIG); + } + + i = PCL711_TIMEOUT; + while (--i) { + hi = inb(dev->iobase + PCL711_AD_HI); + if (!(hi & PCL711_DRDY)) + goto ok; + comedi_udelay(1); + } + rt_printk("comedi%d: pcl711: A/D timeout\n", dev->minor); + return -ETIME; + + ok: + lo = inb(dev->iobase + PCL711_AD_LO); + + data[n] = ((hi & 0xf) << 8) | lo; + } + + return n; +} + +static int pcl711_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int tmp; + int err = 0; + + /* 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_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_NOW; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2 */ + + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3 */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + if (cmd->scan_begin_src == TRIG_EXT) { + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + } else { +#define MAX_SPEED 1000 +#define TIMER_BASE 100 + if (cmd->scan_begin_arg < MAX_SPEED) { + cmd->scan_begin_arg = MAX_SPEED; + err++; + } + } + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_NONE) { + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } else { + /* ignore */ + } + + if (err) + return 3; + + /* step 4 */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + i8253_cascade_ns_to_timer_2div(TIMER_BASE, + &devpriv->divisor1, &devpriv->divisor2, + &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + + if (err) + return 4; + + return 0; +} + +static int pcl711_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int timer1, timer2; + struct comedi_cmd *cmd = &s->async->cmd; + + pcl711_set_changain(dev, cmd->chanlist[0]); + + if (cmd->scan_begin_src == TRIG_TIMER) { + /* + * Set timers + * timer chip is an 8253, with timers 1 and 2 + * cascaded + * 0x74 = Select Counter 1 | LSB/MSB | Mode=2 | Binary + * Mode 2 = Rate generator + * + * 0xb4 = Select Counter 2 | LSB/MSB | Mode=2 | Binary + */ + + i8253_cascade_ns_to_timer(i8253_osc_base, &timer1, &timer2, + &cmd->scan_begin_arg, TRIG_ROUND_NEAREST); + + outb(0x74, dev->iobase + PCL711_CTRCTL); + outb(timer1 & 0xff, dev->iobase + PCL711_CTR1); + outb((timer1 >> 8) & 0xff, dev->iobase + PCL711_CTR1); + outb(0xb4, dev->iobase + PCL711_CTRCTL); + outb(timer2 & 0xff, dev->iobase + PCL711_CTR2); + outb((timer2 >> 8) & 0xff, dev->iobase + PCL711_CTR2); + + /* clear pending interrupts (just in case) */ + outb(0, dev->iobase + PCL711_CLRINTR); + + /* + * Set mode to IRQ transfer + */ + outb(devpriv->mode | 6, dev->iobase + PCL711_MODE); + } else { + /* external trigger */ + outb(devpriv->mode | 3, dev->iobase + PCL711_MODE); + } + + return 0; +} + +/* + analog output +*/ +static int pcl711_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { + outb((data[n] & 0xff), + dev->iobase + (chan ? PCL711_DA1_LO : PCL711_DA0_LO)); + outb((data[n] >> 8), + dev->iobase + (chan ? PCL711_DA1_HI : PCL711_DA0_HI)); + + devpriv->ao_readback[chan] = data[n]; + } + + return n; +} + +static int pcl711_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { + data[n] = devpriv->ao_readback[chan]; + } + + return n; + +} + +/* Digital port read - Untested on 8112 */ +static int pcl711_di_insn_bits(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 + PCL711_DI_LO) | + (inb(dev->iobase + PCL711_DI_HI) << 8); + + return 2; +} + +/* Digital port write - Untested on 8112 */ +static int pcl711_do_insn_bits(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 + PCL711_DO_LO); + if (data[0] & 0xff00) + outb((s->state >> 8), dev->iobase + PCL711_DO_HI); + + data[1] = s->state; + + return 2; +} + +/* Free any resources that we have claimed */ +static int pcl711_detach(struct comedi_device * dev) +{ + printk("comedi%d: pcl711: remove\n", dev->minor); + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + if (dev->iobase) + release_region(dev->iobase, PCL711_SIZE); + + return 0; +} + +/* Initialization */ +static int pcl711_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + unsigned long iobase; + unsigned int irq; + struct comedi_subdevice *s; + + /* claim our I/O space */ + + iobase = it->options[0]; + printk("comedi%d: pcl711: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, PCL711_SIZE, "pcl711")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + /* there should be a sanity check here */ + + /* set up some name stuff */ + dev->board_name = this_board->name; + + /* grab our IRQ */ + irq = it->options[1]; + if (irq > this_board->maxirq) { + printk("irq out of range\n"); + return -EINVAL; + } + if (irq) { + if (comedi_request_irq(irq, pcl711_interrupt, 0, "pcl711", dev)) { + printk("unable to allocate irq %u\n", irq); + return -EINVAL; + } else { + printk("( irq = %u )\n", irq); + } + } + dev->irq = irq; + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + if ((ret = alloc_private(dev, sizeof(struct pcl711_private))) < 0) + return ret; + + s = dev->subdevices + 0; + /* AI subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = this_board->n_aichan; + s->maxdata = 0xfff; + s->len_chanlist = 1; + s->range_table = this_board->ai_range_type; + s->insn_read = pcl711_ai_insn; + if (irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->do_cmdtest = pcl711_ai_cmdtest; + s->do_cmd = pcl711_ai_cmd; + } + + s++; + /* AO subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = this_board->n_aochan; + s->maxdata = 0xfff; + s->len_chanlist = 1; + s->range_table = &range_bipolar5; + s->insn_write = pcl711_ao_insn; + s->insn_read = pcl711_ao_insn_read; + + s++; + /* 16-bit digital input */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->len_chanlist = 16; + s->range_table = &range_digital; + s->insn_bits = pcl711_di_insn_bits; + + s++; + /* 16-bit digital out */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->len_chanlist = 16; + s->range_table = &range_digital; + s->state = 0; + s->insn_bits = pcl711_do_insn_bits; + + /* + this is the "base value" for the mode register, which is + used for the irq on the PCL711 + */ + if (this_board->is_pcl711b) { + devpriv->mode = (dev->irq << 4); + } + + /* clear DAC */ + outb(0, dev->iobase + PCL711_DA0_LO); + outb(0, dev->iobase + PCL711_DA0_HI); + outb(0, dev->iobase + PCL711_DA1_LO); + outb(0, dev->iobase + PCL711_DA1_HI); + + printk("\n"); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c new file mode 100644 index 000000000000..cd1e784f25f9 --- /dev/null +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -0,0 +1,222 @@ +/* + comedi/drivers/pcl724.c + + Michal Dobes + + hardware driver for Advantech cards: + card: PCL-724, PCL-722, PCL-731 + driver: pcl724, pcl722, pcl731 + and ADLink cards: + card: ACL-7122, ACL-7124, PET-48DIO + driver: acl7122, acl7124, pet48dio + + Options for PCL-724, PCL-731, ACL-7124 and PET-48DIO: + [0] - IO Base + + Options for PCL-722 and ACL-7122: + [0] - IO Base + [1] - IRQ (0=disable IRQ) IRQ isn't supported at this time! + [2] -number of DIO: + 0, 144: 144 DIO configuration + 1, 96: 96 DIO configuration +*/ +/* +Driver: pcl724 +Description: Advantech PCL-724, PCL-722, PCL-731 ADLink ACL-7122, ACL-7124, + PET-48DIO +Author: Michal Dobes +Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731), + [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio) +Status: untested + +This is driver for digital I/O boards PCL-722/724/731 with 144/24/48 DIO +and for digital I/O boards ACL-7122/7124/PET-48DIO with 144/24/48 DIO. +It need 8255.o for operations and only immediate mode is supported. +See the source for configuration details. +*/ +/* + * check_driver overrides: + * struct comedi_insn + */ + +#include "../comedidev.h" + +#include +#include + +#include "8255.h" + +#define PCL722_SIZE 32 +#define PCL722_96_SIZE 16 +#define PCL724_SIZE 4 +#define PCL731_SIZE 8 +#define PET48_SIZE 2 + +#define SIZE_8255 4 + +// #define PCL724_IRQ 1 /* no IRQ support now */ + +static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcl724_detach(struct comedi_device * dev); + +struct pcl724_board { + + const char *name; // board name + int dio; // num of DIO + int numofports; // num of 8255 subdevices + unsigned int IRQbits; // allowed interrupts + unsigned int io_range; // len of IO space + char can_have96; + char is_pet48; +}; + + +static const struct pcl724_board boardtypes[] = { + {"pcl724", 24, 1, 0x00fc, PCL724_SIZE, 0, 0,}, + {"pcl722", 144, 6, 0x00fc, PCL722_SIZE, 1, 0,}, + {"pcl731", 48, 2, 0x9cfc, PCL731_SIZE, 0, 0,}, + {"acl7122", 144, 6, 0x9ee8, PCL722_SIZE, 1, 0,}, + {"acl7124", 24, 1, 0x00fc, PCL724_SIZE, 0, 0,}, + {"pet48dio", 48, 2, 0x9eb8, PET48_SIZE, 0, 1,}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl724_board)) +#define this_board ((const struct pcl724_board *)dev->board_ptr) + +static struct comedi_driver driver_pcl724 = { + driver_name:"pcl724", + module:THIS_MODULE, + attach:pcl724_attach, + detach:pcl724_detach, + board_name:&boardtypes[0].name, + num_names:n_boardtypes, + offset:sizeof(struct pcl724_board), +}; + +COMEDI_INITCLEANUP(driver_pcl724); + +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_8255mapped_cb(int dir, int port, int data, + unsigned long iobase) +{ + int movport = SIZE_8255 * (iobase >> 12); + + iobase &= 0x0fff; + + if (dir) { + outb(port + movport, iobase); + outb(data, iobase + 1); + return 0; + } else { + outb(port + movport, iobase); + return inb(iobase + 1); + } +} + +static int pcl724_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + unsigned long iobase; + unsigned int iorange; + int ret, i, n_subdevices; +#ifdef PCL724_IRQ + unsigned int irq; +#endif + + iobase = it->options[0]; + iorange = this_board->io_range; + if ((this_board->can_have96) && ((it->options[1] == 1) + || (it->options[1] == 96))) + iorange = PCL722_96_SIZE; // PCL-724 in 96 DIO configuration + printk("comedi%d: pcl724: board=%s, 0x%03lx ", dev->minor, + this_board->name, iobase); + if (!request_region(iobase, iorange, "pcl724")) { + printk("I/O port conflict\n"); + return -EIO; + } + + dev->iobase = iobase; + + dev->board_name = this_board->name; + +#ifdef PCL724_IRQ + irq = 0; + if (this_board->IRQbits != 0) { /* board support IRQ */ + irq = it->options[1]; + if (irq) { /* we want to use IRQ */ + if (((1 << irq) & this_board->IRQbits) == 0) { + rt_printk + (", IRQ %u is out of allowed range, DISABLING IT", + irq); + irq = 0; /* Bad IRQ */ + } else { + if (comedi_request_irq(irq, interrupt_pcl724, 0, + "pcl724", dev)) { + rt_printk + (", unable to allocate IRQ %u, DISABLING IT", + irq); + irq = 0; /* Can't use IRQ */ + } else { + rt_printk(", irq=%u", irq); + } + } + } + } + + dev->irq = irq; +#endif + + printk("\n"); + + n_subdevices = this_board->numofports; + if ((this_board->can_have96) && ((it->options[1] == 1) + || (it->options[1] == 96))) + n_subdevices = 4; // PCL-724 in 96 DIO configuration + + if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) + return ret; + + for (i = 0; i < dev->n_subdevices; i++) { + if (this_board->is_pet48) { + subdev_8255_init(dev, dev->subdevices + i, + subdev_8255mapped_cb, + (unsigned long)(dev->iobase + i * 0x1000)); + } else + subdev_8255_init(dev, dev->subdevices + i, + subdev_8255_cb, + (unsigned long)(dev->iobase + SIZE_8255 * i)); + }; + + return 0; +} + +static int pcl724_detach(struct comedi_device * dev) +{ + int i; + +// printk("comedi%d: pcl724: remove\n",dev->minor); + + for (i = 0; i < dev->n_subdevices; i++) { + subdev_8255_cleanup(dev, dev->subdevices + i); + } + +#ifdef PCL724_IRQ + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } +#endif + + release_region(dev->iobase, this_board->io_range); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c new file mode 100644 index 000000000000..0766ba02bd03 --- /dev/null +++ b/drivers/staging/comedi/drivers/pcl725.c @@ -0,0 +1,111 @@ +/* + * comedi/drivers/pcl725.c + * Driver for PCL725 and clones + * David A. Schleef + */ +/* +Driver: pcl725 +Description: Advantech PCL-725 (& compatibles) +Author: ds +Status: unknown +Devices: [Advantech] PCL-725 (pcl725) +*/ + +#include "../comedidev.h" + +#include + +#define PCL725_SIZE 2 + +#define PCL725_DO 0 +#define PCL725_DI 1 + +static int pcl725_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcl725_detach(struct comedi_device * dev); +static struct comedi_driver driver_pcl725 = { + driver_name:"pcl725", + module:THIS_MODULE, + attach:pcl725_attach, + detach:pcl725_detach, +}; + +COMEDI_INITCLEANUP(driver_pcl725); + +static int pcl725_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]); + outb(s->state, dev->iobase + PCL725_DO); + } + + data[1] = s->state; + + return 2; +} + +static int pcl725_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 + PCL725_DI); + + return 2; +} + +static int pcl725_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + + iobase = it->options[0]; + printk("comedi%d: pcl725: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, PCL725_SIZE, "pcl725")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->board_name = "pcl725"; + dev->iobase = iobase; + dev->irq = 0; + + if (alloc_subdevices(dev, 2) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* do */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 1; + s->n_chan = 8; + s->insn_bits = pcl725_do_insn; + s->range_table = &range_digital; + + s = dev->subdevices + 1; + /* di */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->maxdata = 1; + s->n_chan = 8; + s->insn_bits = pcl725_di_insn; + s->range_table = &range_digital; + + printk("\n"); + + return 0; +} + +static int pcl725_detach(struct comedi_device * dev) +{ + printk("comedi%d: pcl725: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, PCL725_SIZE); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c new file mode 100644 index 000000000000..6dbd33d7907b --- /dev/null +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -0,0 +1,377 @@ +/* + comedi/drivers/pcl726.c + + hardware driver for Advantech cards: + card: PCL-726, PCL-727, PCL-728 + driver: pcl726, pcl727, pcl728 + and for ADLink cards: + card: ACL-6126, ACL-6128 + driver: acl6126, acl6128 + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998 David A. Schleef + + 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: pcl726 +Description: Advantech PCL-726 & compatibles +Author: ds +Status: untested +Devices: [Advantech] PCL-726 (pcl726), PCL-727 (pcl727), PCL-728 (pcl728), + [ADLink] ACL-6126 (acl6126), ACL-6128 (acl6128) + +Interrupts are not supported. + + Options for PCL-726: + [0] - IO Base + [2]...[7] - D/A output range for channel 1-6: + 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, + 4: 4-20mA, 5: unknown (external reference) + + Options for PCL-727: + [0] - IO Base + [2]...[13] - D/A output range for channel 1-12: + 0: 0-5V, 1: 0-10V, 2: +/-5V, + 3: 4-20mA + + Options for PCL-728 and ACL-6128: + [0] - IO Base + [2], [3] - D/A output range for channel 1 and 2: + 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, + 4: 4-20mA, 5: 0-20mA + + Options for ACL-6126: + [0] - IO Base + [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15) (currently ignored) + [2]...[7] - D/A output range for channel 1-6: + 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, + 4: 4-20mA +*/ + +/* + Thanks to Circuit Specialists for having programming info (!) on + their web page. (http://www.cir.com/) +*/ + +#include "../comedidev.h" + +#include + +#undef ACL6126_IRQ /* no interrupt support (yet) */ + +#define PCL726_SIZE 16 +#define PCL727_SIZE 32 +#define PCL728_SIZE 8 + +#define PCL726_DAC0_HI 0 +#define PCL726_DAC0_LO 1 + +#define PCL726_DO_HI 12 +#define PCL726_DO_LO 13 +#define PCL726_DI_HI 14 +#define PCL726_DI_LO 15 + +#define PCL727_DO_HI 24 +#define PCL727_DO_LO 25 +#define PCL727_DI_HI 0 +#define PCL727_DI_LO 1 + +static const struct comedi_lrange range_4_20mA = { 1, {RANGE_mA(4, 20)} }; +static const struct comedi_lrange range_0_20mA = { 1, {RANGE_mA(0, 20)} }; + +static const struct comedi_lrange *const rangelist_726[] = { + &range_unipolar5, &range_unipolar10, + &range_bipolar5, &range_bipolar10, + &range_4_20mA, &range_unknown +}; + +static const struct comedi_lrange *const rangelist_727[] = { + &range_unipolar5, &range_unipolar10, + &range_bipolar5, + &range_4_20mA +}; + +static const struct comedi_lrange *const rangelist_728[] = { + &range_unipolar5, &range_unipolar10, + &range_bipolar5, &range_bipolar10, + &range_4_20mA, &range_0_20mA +}; + +static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcl726_detach(struct comedi_device * dev); + +struct pcl726_board { + + const char *name; // driver name + int n_aochan; // num of D/A chans + int num_of_ranges; // num of ranges + unsigned int IRQbits; // allowed interrupts + unsigned int io_range; // len of IO space + char have_dio; // 1=card have DI/DO ports + int di_hi; // ports for DI/DO operations + int di_lo; + int do_hi; + int do_lo; + const struct comedi_lrange *const *range_type_list; // list of supported ranges +}; + + +static const struct pcl726_board boardtypes[] = { + {"pcl726", 6, 6, 0x0000, PCL726_SIZE, 1, + PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO, + &rangelist_726[0],}, + {"pcl727", 12, 4, 0x0000, PCL727_SIZE, 1, + PCL727_DI_HI, PCL727_DI_LO, PCL727_DO_HI, PCL727_DO_LO, + &rangelist_727[0],}, + {"pcl728", 2, 6, 0x0000, PCL728_SIZE, 0, + 0, 0, 0, 0, + &rangelist_728[0],}, + {"acl6126", 6, 5, 0x96e8, PCL726_SIZE, 1, + PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO, + &rangelist_726[0],}, + {"acl6128", 2, 6, 0x0000, PCL728_SIZE, 0, + 0, 0, 0, 0, + &rangelist_728[0],}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl726_board)) +#define this_board ((const struct pcl726_board *)dev->board_ptr) + +static struct comedi_driver driver_pcl726 = { + driver_name:"pcl726", + module:THIS_MODULE, + attach:pcl726_attach, + detach:pcl726_detach, + board_name:&boardtypes[0].name, + num_names:n_boardtypes, + offset:sizeof(struct pcl726_board), +}; + +COMEDI_INITCLEANUP(driver_pcl726); + +struct pcl726_private { + + int bipolar[12]; + const struct comedi_lrange *rangelist[12]; + unsigned int ao_readback[12]; +}; + +#define devpriv ((struct pcl726_private *)dev->private) + +static int pcl726_ao_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int hi, lo; + int n; + int chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { + lo = data[n] & 0xff; + hi = (data[n] >> 8) & 0xf; + if (devpriv->bipolar[chan]) + hi ^= 0x8; + /* + * the programming info did not say which order + * to write bytes. switch the order of the next + * two lines if you get glitches. + */ + outb(hi, dev->iobase + PCL726_DAC0_HI + 2 * chan); + outb(lo, dev->iobase + PCL726_DAC0_LO + 2 * chan); + devpriv->ao_readback[chan] = data[n]; + } + + return n; +} + +static int pcl726_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + int n; + + for (n = 0; n < insn->n; n++) { + data[n] = devpriv->ao_readback[chan]; + } + return n; +} + +static int pcl726_di_insn_bits(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 + this_board->di_lo) | + (inb(dev->iobase + this_board->di_hi) << 8); + + return 2; +} + +static int pcl726_do_insn_bits(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[1] & 0x00ff) + outb(s->state & 0xff, dev->iobase + this_board->do_lo); + if (data[1] & 0xff00) + outb((s->state >> 8), dev->iobase + this_board->do_hi); + + data[1] = s->state; + + return 2; +} + +static int pcl726_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + unsigned int iorange; + int ret, i; +#ifdef ACL6126_IRQ + unsigned int irq; +#endif + + iobase = it->options[0]; + iorange = this_board->io_range; + printk("comedi%d: pcl726: board=%s, 0x%03lx ", dev->minor, + this_board->name, iobase); + if (!request_region(iobase, iorange, "pcl726")) { + printk("I/O port conflict\n"); + return -EIO; + } + + dev->iobase = iobase; + + dev->board_name = this_board->name; + + if ((ret = alloc_private(dev, sizeof(struct pcl726_private))) < 0) + return -ENOMEM; + + for (i = 0; i < 12; i++) { + devpriv->bipolar[i] = 0; + devpriv->rangelist[i] = &range_unknown; + } + +#ifdef ACL6126_IRQ + irq = 0; + if (boardtypes[board].IRQbits != 0) { /* board support IRQ */ + irq = it->options[1]; + devpriv->first_chan = 2; + if (irq) { /* we want to use IRQ */ + if (((1 << irq) & boardtypes[board].IRQbits) == 0) { + rt_printk + (", IRQ %d is out of allowed range, DISABLING IT", + irq); + irq = 0; /* Bad IRQ */ + } else { + if (comedi_request_irq(irq, interrupt_pcl818, 0, + "pcl726", dev)) { + rt_printk + (", unable to allocate IRQ %d, DISABLING IT", + irq); + irq = 0; /* Can't use IRQ */ + } else { + rt_printk(", irq=%d", irq); + } + } + } + } + + dev->irq = irq; +#endif + + printk("\n"); + + if ((ret = alloc_subdevices(dev, 3)) < 0) + return ret; + + s = dev->subdevices + 0; + /* ao */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = this_board->n_aochan; + s->maxdata = 0xfff; + s->len_chanlist = 1; + s->insn_write = pcl726_ao_insn; + s->insn_read = pcl726_ao_insn_read; + s->range_table_list = devpriv->rangelist; + for (i = 0; i < this_board->n_aochan; i++) { + int j; + + j = it->options[2 + 1]; + if ((j < 0) || (j >= this_board->num_of_ranges)) { + printk("Invalid range for channel %d! Must be 0<=%d<%d\n", i, j, this_board->num_of_ranges - 1); + j = 0; + } + devpriv->rangelist[i] = this_board->range_type_list[j]; + if (devpriv->rangelist[i]->range[0].min == + -devpriv->rangelist[i]->range[0].max) + devpriv->bipolar[i] = 1; /* bipolar range */ + } + + s = dev->subdevices + 1; + /* di */ + if (!this_board->have_dio) { + s->type = COMEDI_SUBD_UNUSED; + } else { + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 16; + s->maxdata = 1; + s->len_chanlist = 1; + s->insn_bits = pcl726_di_insn_bits; + s->range_table = &range_digital; + } + + s = dev->subdevices + 2; + /* do */ + if (!this_board->have_dio) { + s->type = COMEDI_SUBD_UNUSED; + } else { + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = 16; + s->maxdata = 1; + s->len_chanlist = 1; + s->insn_bits = pcl726_do_insn_bits; + s->range_table = &range_digital; + } + + return 0; +} + +static int pcl726_detach(struct comedi_device * dev) +{ +// printk("comedi%d: pcl726: remove\n",dev->minor); + +#ifdef ACL6126_IRQ + if (dev->irq) { + comedi_free_irq(dev->irq, dev); + } +#endif + + if (dev->iobase) + release_region(dev->iobase, this_board->io_range); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c new file mode 100644 index 000000000000..f2c6d7c5693c --- /dev/null +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -0,0 +1,168 @@ +/* + * comedi/drivers/pcl730.c + * Driver for Advantech PCL-730 and clones + * José Luis Sánchez + */ +/* +Driver: pcl730 +Description: Advantech PCL-730 (& compatibles) +Author: José Luis Sánchez (jsanchezv@teleline.es) +Status: untested +Devices: [Advantech] PCL-730 (pcl730), [ICP] ISO-730 (iso730), + [Adlink] ACL-7130 (acl7130) + +Interrupts are not supported. +The ACL-7130 card have an 8254 timer/counter not supported by this driver. +*/ + +#include "../comedidev.h" + +#include + +#define PCL730_SIZE 4 +#define ACL7130_SIZE 8 +#define PCL730_IDIO_LO 0 /* Isolated Digital I/O low byte (ID0-ID7) */ +#define PCL730_IDIO_HI 1 /* Isolated Digital I/O high byte (ID8-ID15) */ +#define PCL730_DIO_LO 2 /* TTL Digital I/O low byte (D0-D7) */ +#define PCL730_DIO_HI 3 /* TTL Digital I/O high byte (D8-D15) */ + +static int pcl730_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcl730_detach(struct comedi_device * dev); + +struct pcl730_board { + + const char *name; // board name + unsigned int io_range; // len of I/O space +}; + + +static const struct pcl730_board boardtypes[] = { + {"pcl730", PCL730_SIZE,}, + {"iso730", PCL730_SIZE,}, + {"acl7130", ACL7130_SIZE,}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl730_board)) +#define this_board ((const struct pcl730_board *)dev->board_ptr) + +static struct comedi_driver driver_pcl730 = { + driver_name:"pcl730", + module:THIS_MODULE, + attach:pcl730_attach, + detach:pcl730_detach, + board_name:&boardtypes[0].name, + num_names:n_boardtypes, + offset:sizeof(struct pcl730_board), +}; + +COMEDI_INITCLEANUP(driver_pcl730); + +static int pcl730_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 pcl730_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 pcl730_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + unsigned int iorange; + + iobase = it->options[0]; + iorange = this_board->io_range; + printk("comedi%d: pcl730: board=%s 0x%04lx ", dev->minor, + this_board->name, iobase); + if (!request_region(iobase, iorange, "pcl730")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->board_name = this_board->name; + dev->iobase = iobase; + dev->irq = 0; + + if (alloc_subdevices(dev, 4) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* Isolated do */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 1; + s->n_chan = 16; + s->insn_bits = pcl730_do_insn; + s->range_table = &range_digital; + s->private = (void *)PCL730_IDIO_LO; + + s = dev->subdevices + 1; + /* Isolated di */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->maxdata = 1; + s->n_chan = 16; + s->insn_bits = pcl730_di_insn; + s->range_table = &range_digital; + s->private = (void *)PCL730_IDIO_LO; + + s = dev->subdevices + 2; + /* TTL do */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 1; + s->n_chan = 16; + s->insn_bits = pcl730_do_insn; + s->range_table = &range_digital; + s->private = (void *)PCL730_DIO_LO; + + s = dev->subdevices + 3; + /* TTL di */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->maxdata = 1; + s->n_chan = 16; + s->insn_bits = pcl730_di_insn; + s->range_table = &range_digital; + s->private = (void *)PCL730_DIO_LO; + + printk("\n"); + + return 0; +} + +static int pcl730_detach(struct comedi_device * dev) +{ + printk("comedi%d: pcl730: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, this_board->io_range); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c new file mode 100644 index 000000000000..11dfd230e565 --- /dev/null +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -0,0 +1,1605 @@ +/* + * comedi/drivers/pcl812.c + * + * Author: Michal Dobes + * + * hardware driver for Advantech cards + * card: PCL-812, PCL-812PG, PCL-813, PCL-813B + * driver: pcl812, pcl812pg, pcl813, pcl813b + * and for ADlink cards + * card: ACL-8112DG, ACL-8112HG, ACL-8112PG, ACL-8113, ACL-8216 + * driver: acl8112dg, acl8112hg, acl8112pg, acl8113, acl8216 + * and for ICP DAS cards + * card: ISO-813, A-821PGH, A-821PGL, A-821PGL-NDA, A-822PGH, A-822PGL, + * driver: iso813, a821pgh, a-821pgl, a-821pglnda, a822pgh, a822pgl, + * card: A-823PGH, A-823PGL, A-826PG + * driver: a823pgh, a823pgl, a826pg + */ +/* +Driver: pcl812 +Description: Advantech PCL-812/PG, PCL-813/B, + ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216, + ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG, + ICP DAS ISO-813 +Author: Michal Dobes +Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg), + PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg), + ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216), + [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl), + A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl), + A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg) +Updated: Mon, 06 Aug 2007 12:03:15 +0100 +Status: works (I hope. My board fire up under my hands + and I cann't test all features.) + +This driver supports insn and cmd interfaces. Some boards support only insn +becouse their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813). +Data transfer over DMA is supported only when you measure only one +channel, this is too hardware limitation of these boards. + +Options for PCL-812: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) + [2] - DMA (0=disable, 1, 3) + [3] - 0=trigger source is internal 8253 with 2MHz clock + 1=trigger source is external + [4] - 0=A/D input range is +/-10V + 1=A/D input range is +/-5V + 2=A/D input range is +/-2.5V + 3=A/D input range is +/-1.25V + 4=A/D input range is +/-0.625V + 5=A/D input range is +/-0.3125V + [5] - 0=D/A outputs 0-5V (internal reference -5V) + 1=D/A outputs 0-10V (internal reference -10V) + 2=D/A outputs unknow (external reference) + +Options for PCL-812PG, ACL-8112PG: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) + [2] - DMA (0=disable, 1, 3) + [3] - 0=trigger source is internal 8253 with 2MHz clock + 1=trigger source is external + [4] - 0=A/D have max +/-5V input + 1=A/D have max +/-10V input + [5] - 0=D/A outputs 0-5V (internal reference -5V) + 1=D/A outputs 0-10V (internal reference -10V) + 2=D/A outputs unknow (external reference) + +Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15) + [2] - DMA (0=disable, 1, 3) + [3] - 0=trigger source is internal 8253 with 2MHz clock + 1=trigger source is external + [4] - 0=A/D channels are S.E. + 1=A/D channels are DIFF + [5] - 0=D/A outputs 0-5V (internal reference -5V) + 1=D/A outputs 0-10V (internal reference -10V) + 2=D/A outputs unknow (external reference) + +Options for A-821PGL/PGH: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + [2] - 0=A/D channels are S.E. + 1=A/D channels are DIFF + [3] - 0=D/A output 0-5V (internal reference -5V) + 1=D/A output 0-10V (internal reference -10V) + +Options for A-821PGL-NDA: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + [2] - 0=A/D channels are S.E. + 1=A/D channels are DIFF + +Options for PCL-813: + [0] - IO Base + +Options for PCL-813B: + [0] - IO Base + [1] - 0= bipolar inputs + 1= unipolar inputs + +Options for ACL-8113, ISO-813: + [0] - IO Base + [1] - 0= 10V bipolar inputs + 1= 10V unipolar inputs + 2= 20V bipolar inputs + 3= 20V unipolar inputs +*/ + +#include "../comedidev.h" + +#include +#include +#include + +#include "8253.h" + +#undef PCL812_EXTDEBUG /* if this is defined then a lot of messages is printed */ + +// hardware types of the cards +#define boardPCL812PG 0 /* and ACL-8112PG */ +#define boardPCL813B 1 +#define boardPCL812 2 +#define boardPCL813 3 +#define boardISO813 5 +#define boardACL8113 6 +#define boardACL8112 7 /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */ +#define boardACL8216 8 /* and ICP DAS A-826PG */ +#define boardA821 9 /* PGH, PGL, PGL/NDA versions */ + +#define PCLx1x_IORANGE 16 + +#define PCL812_CTR0 0 +#define PCL812_CTR1 1 +#define PCL812_CTR2 2 +#define PCL812_CTRCTL 3 +#define PCL812_AD_LO 4 +#define PCL812_DA1_LO 4 +#define PCL812_AD_HI 5 +#define PCL812_DA1_HI 5 +#define PCL812_DA2_LO 6 +#define PCL812_DI_LO 6 +#define PCL812_DA2_HI 7 +#define PCL812_DI_HI 7 +#define PCL812_CLRINT 8 +#define PCL812_GAIN 9 +#define PCL812_MUX 10 +#define PCL812_MODE 11 +#define PCL812_CNTENABLE 10 +#define PCL812_SOFTTRIG 12 +#define PCL812_DO_LO 13 +#define PCL812_DO_HI 14 + +#define PCL812_DRDY 0x10 /* =0 data ready */ + +#define ACL8216_STATUS 8 /* 5. bit signalize data ready */ + +#define ACL8216_DRDY 0x20 /* =0 data ready */ + +#define MAX_CHANLIST_LEN 256 /* length of scan list */ + +static const struct comedi_lrange range_pcl812pg_ai = { 5, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + BIP_RANGE(0.3125), + } +}; +static const struct comedi_lrange range_pcl812pg2_ai = { 5, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + } +}; +static const struct comedi_lrange range812_bipolar1_25 = { 1, { + BIP_RANGE(1.25), + } +}; +static const struct comedi_lrange range812_bipolar0_625 = { 1, { + BIP_RANGE(0.625), + } +}; +static const struct comedi_lrange range812_bipolar0_3125 = { 1, { + BIP_RANGE(0.3125), + } +}; +static const struct comedi_lrange range_pcl813b_ai = { 4, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + } +}; +static const struct comedi_lrange range_pcl813b2_ai = { 4, { + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + } +}; +static const struct comedi_lrange range_iso813_1_ai = { 5, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + BIP_RANGE(0.3125), + } +}; +static const struct comedi_lrange range_iso813_1_2_ai = { 5, { + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + UNI_RANGE(0.625), + } +}; +static const struct comedi_lrange range_iso813_2_ai = { 4, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + } +}; +static const struct comedi_lrange range_iso813_2_2_ai = { 4, { + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + } +}; +static const struct comedi_lrange range_acl8113_1_ai = { 4, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + } +}; +static const struct comedi_lrange range_acl8113_1_2_ai = { 4, { + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + } +}; +static const struct comedi_lrange range_acl8113_2_ai = { 3, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + } +}; +static const struct comedi_lrange range_acl8113_2_2_ai = { 3, { + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + } +}; +static const struct comedi_lrange range_acl8112dg_ai = { 9, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + BIP_RANGE(10), + } +}; +static const struct comedi_lrange range_acl8112hg_ai = { 12, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.005), + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01), + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.01), + } +}; +static const struct comedi_lrange range_a821pgh_ai = { 4, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.005), + } +}; + +static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcl812_detach(struct comedi_device * dev); + +struct pcl812_board { + + const char *name; // board name + int board_type; // type of this board + int n_aichan; // num of AI chans in S.E. + int n_aichan_diff; // DIFF num of chans + int n_aochan; // num of DA chans + int n_dichan; // DI and DO chans + int n_dochan; + int ai_maxdata; // AI resolution + unsigned int ai_ns_min; // max sample speed of card v ns + unsigned int i8254_osc_base; // clock base + const struct comedi_lrange *rangelist_ai; // rangelist for A/D + const struct comedi_lrange *rangelist_ao; // rangelist for D/A + unsigned int IRQbits; // allowed IRQ + unsigned char DMAbits; // allowed DMA chans + unsigned char io_range; // iorange for this board + unsigned char haveMPC508; // 1=board use MPC508A multiplexor +}; + + +static const struct pcl812_board boardtypes[] = { + {"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff, + 33000, 500, &range_bipolar10, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, + {"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff, + 33000, 500, &range_pcl812pg_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, + {"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff, + 10000, 500, &range_pcl812pg_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, + {"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, + 10000, 500, &range_acl8112dg_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 1}, + {"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, + 10000, 500, &range_acl8112hg_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 1}, + {"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff, + 10000, 500, &range_pcl813b_ai, &range_unipolar5, + 0x000c, 0x00, PCLx1x_IORANGE, 0}, + {"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff, + 10000, 500, &range_pcl813b_ai, NULL, + 0x000c, 0x00, PCLx1x_IORANGE, 0}, + {"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff, + 10000, 500, &range_a821pgh_ai, &range_unipolar5, + 0x000c, 0x00, PCLx1x_IORANGE, 0}, + {"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, + 10000, 500, &range_acl8112dg_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, + {"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, + 10000, 500, &range_acl8112hg_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, + {"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, + 8000, 500, &range_acl8112dg_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, + {"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, + 8000, 500, &range_acl8112hg_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, + {"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff, + 0, 0, &range_pcl813b_ai, NULL, + 0x0000, 0x00, PCLx1x_IORANGE, 0}, + {"pcl813b", boardPCL813B, 32, 0, 0, 0, 0, 0x0fff, + 0, 0, &range_pcl813b_ai, NULL, + 0x0000, 0x00, PCLx1x_IORANGE, 0}, + {"acl8113", boardACL8113, 32, 0, 0, 0, 0, 0x0fff, + 0, 0, &range_acl8113_1_ai, NULL, + 0x0000, 0x00, PCLx1x_IORANGE, 0}, + {"iso813", boardISO813, 32, 0, 0, 0, 0, 0x0fff, + 0, 0, &range_iso813_1_ai, NULL, + 0x0000, 0x00, PCLx1x_IORANGE, 0}, + {"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff, + 10000, 500, &range_pcl813b2_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 1}, + {"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff, + 10000, 500, &range_pcl813b2_ai, &range_unipolar5, + 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl812_board)) +#define this_board ((const struct pcl812_board *)dev->board_ptr) + +static struct comedi_driver driver_pcl812 = { + driver_name:"pcl812", + module:THIS_MODULE, + attach:pcl812_attach, + detach:pcl812_detach, + board_name:&boardtypes[0].name, + num_names:n_boardtypes, + offset:sizeof(struct pcl812_board), +}; + +COMEDI_INITCLEANUP(driver_pcl812); + +struct pcl812_private { + + unsigned char valid; // =1 device is OK + unsigned char dma; // >0 use dma ( usedDMA channel) + unsigned char use_diff; // =1 diff inputs + unsigned char use_MPC; // 1=board uses MPC508A multiplexor + unsigned char use_ext_trg; // 1=board uses external trigger + unsigned char range_correction; // =1 we must add 1 to range number + unsigned char old_chan_reg; // lastly used chan/gain pair + unsigned char old_gain_reg; + unsigned char mode_reg_int; // there is stored INT number for some card + unsigned char ai_neverending; // =1 we do unlimited AI + unsigned char ai_eos; // 1=EOS wake up + unsigned char ai_dma; // =1 we use DMA + unsigned int ai_poll_ptr; // how many sampes transfer poll + unsigned int ai_scans; // len of scanlist + unsigned int ai_act_scan; // how many scans we finished + unsigned int ai_chanlist[MAX_CHANLIST_LEN]; // our copy of channel/range list + unsigned int ai_n_chan; // how many channels is measured + unsigned int ai_flags; // flaglist + unsigned int ai_data_len; // len of data buffer + short *ai_data; // data buffer + unsigned int ai_is16b; // =1 we have 16 bit card + unsigned long dmabuf[2]; // PTR to DMA buf + unsigned int dmapages[2]; // how many pages we have allocated + unsigned int hwdmaptr[2]; // HW PTR to DMA buf + unsigned int hwdmasize[2]; // DMA buf size in bytes + unsigned int dmabytestomove[2]; // how many bytes DMA transfer + int next_dma_buf; // which buffer is next to use + unsigned int dma_runs_to_end; // how many times we must switch DMA buffers + unsigned int last_dma_run; // how many bytes to transfer on last DMA buffer + unsigned int max_812_ai_mode0_rangewait; // setling time for gain + unsigned int ao_readback[2]; // data for AO readback +}; + + +#define devpriv ((struct pcl812_private *)dev->private) + +/* +============================================================================== +*/ +static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2); +static void setup_range_channel(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int rangechan, char wait); +static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +/* +============================================================================== +*/ +static int pcl812_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int timeout, hi; + + outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE); /* select software trigger */ + setup_range_channel(dev, s, insn->chanspec, 1); // select channel and renge + for (n = 0; n < insn->n; n++) { + outb(255, dev->iobase + PCL812_SOFTTRIG); /* start conversion */ + comedi_udelay(5); + timeout = 50; /* wait max 50us, it must finish under 33us */ + while (timeout--) { + hi = inb(dev->iobase + PCL812_AD_HI); + if (!(hi & PCL812_DRDY)) + goto conv_finish; + comedi_udelay(1); + } + rt_printk + ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n", + dev->minor, dev->board_name, dev->iobase); + outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); + return -ETIME; + + conv_finish: + data[n] = ((hi & 0xf) << 8) | inb(dev->iobase + PCL812_AD_LO); + } + outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); + return n; +} + +/* +============================================================================== +*/ +static int acl8216_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int timeout; + + outb(1, dev->iobase + PCL812_MODE); /* select software trigger */ + setup_range_channel(dev, s, insn->chanspec, 1); // select channel and renge + for (n = 0; n < insn->n; n++) { + outb(255, dev->iobase + PCL812_SOFTTRIG); /* start conversion */ + comedi_udelay(5); + timeout = 50; /* wait max 50us, it must finish under 33us */ + while (timeout--) { + if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) + goto conv_finish; + comedi_udelay(1); + } + rt_printk + ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n", + dev->minor, dev->board_name, dev->iobase); + outb(0, dev->iobase + PCL812_MODE); + return -ETIME; + + conv_finish: + data[n] = + (inb(dev->iobase + + PCL812_AD_HI) << 8) | inb(dev->iobase + + PCL812_AD_LO); + } + outb(0, dev->iobase + PCL812_MODE); + return n; +} + +/* +============================================================================== +*/ +static int pcl812_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + int i; + + for (i = 0; i < insn->n; i++) { + outb((data[i] & 0xff), + dev->iobase + (chan ? PCL812_DA2_LO : PCL812_DA1_LO)); + outb((data[i] >> 8) & 0x0f, + dev->iobase + (chan ? PCL812_DA2_HI : PCL812_DA1_HI)); + devpriv->ao_readback[chan] = data[i]; + } + + return i; +} + +/* +============================================================================== +*/ +static int pcl812_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + int i; + + for (i = 0; i < insn->n; i++) { + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +/* +============================================================================== +*/ +static int pcl812_di_insn_bits(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 + PCL812_DI_LO); + data[1] |= inb(dev->iobase + PCL812_DI_HI) << 8; + + return 2; +} + +/* +============================================================================== +*/ +static int pcl812_do_insn_bits(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]; + outb(s->state & 0xff, dev->iobase + PCL812_DO_LO); + outb((s->state >> 8), dev->iobase + PCL812_DO_HI); + } + data[1] = s->state; + + return 2; +} + +#ifdef PCL812_EXTDEBUG +/* +============================================================================== +*/ +static void pcl812_cmdtest_out(int e, struct comedi_cmd * cmd) +{ + rt_printk("pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, + cmd->start_src, cmd->scan_begin_src, cmd->convert_src); + rt_printk("pcl812 e=%d startarg=%d scanarg=%d convarg=%d\n", e, + cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); + rt_printk("pcl812 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src, + cmd->scan_end_src); + rt_printk("pcl812 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", e, + cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); +} +#endif + +/* +============================================================================== +*/ +static int pcl812_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp, divisor1, divisor2; + +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...)\n"); + pcl812_cmdtest_out(-1, cmd); +#endif + /* step 1: make sure trigger sources are trivially valid */ + + 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_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + if (devpriv->use_ext_trg) { + cmd->convert_src &= TRIG_EXT; + } else { + cmd->convert_src &= TRIG_TIMER; + } + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) { +#ifdef PCL812_EXTDEBUG + pcl812_cmdtest_out(1, cmd); + rt_printk + ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=1\n", + err); +#endif + return 1; + } + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW) { + cmd->start_src = TRIG_NOW; + err++; + } + + if (cmd->scan_begin_src != TRIG_FOLLOW) { + cmd->scan_begin_src = TRIG_FOLLOW; + err++; + } + + if (devpriv->use_ext_trg) { + if (cmd->convert_src != TRIG_EXT) { + cmd->convert_src = TRIG_EXT; + err++; + } + } else { + if (cmd->convert_src != TRIG_TIMER) { + cmd->convert_src = TRIG_TIMER; + err++; + } + } + + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; + + if (err) { +#ifdef PCL812_EXTDEBUG + pcl812_cmdtest_out(2, cmd); + rt_printk + ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=2\n", + err); +#endif + return 2; + } + + /* step 3: make sure arguments are trivially compatible */ + + 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_src == TRIG_TIMER) { + if (cmd->convert_arg < this_board->ai_ns_min) { + cmd->convert_arg = this_board->ai_ns_min; + err++; + } + } else { /* TRIG_EXT */ + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + } + + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->chanlist_len > MAX_CHANLIST_LEN) { + cmd->chanlist_len = this_board->n_aichan; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + } else { /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) { +#ifdef PCL812_EXTDEBUG + pcl812_cmdtest_out(3, cmd); + rt_printk + ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=3\n", + err); +#endif + return 3; + } + + /* step 4: fix up any arguments */ + + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + i8253_cascade_ns_to_timer(this_board->i8254_osc_base, &divisor1, + &divisor2, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (cmd->convert_arg < this_board->ai_ns_min) + cmd->convert_arg = this_board->ai_ns_min; + if (tmp != cmd->convert_arg) + err++; + } + + if (err) { +#ifdef PCL812_EXTDEBUG + rt_printk + ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=4\n", + err); +#endif + return 4; + } + + return 0; +} + +/* +============================================================================== +*/ +static int pcl812_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes; + struct comedi_cmd *cmd = &s->async->cmd; + +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmd(...)\n"); +#endif + + if (cmd->start_src != TRIG_NOW) + return -EINVAL; + if (cmd->scan_begin_src != TRIG_FOLLOW) + return -EINVAL; + if (devpriv->use_ext_trg) { + if (cmd->convert_src != TRIG_EXT) + return -EINVAL; + } else { + if (cmd->convert_src != TRIG_TIMER) + return -EINVAL; + } + if (cmd->scan_end_src != TRIG_COUNT) + return -EINVAL; + if (cmd->scan_end_arg != cmd->chanlist_len) + return -EINVAL; + if (cmd->chanlist_len > MAX_CHANLIST_LEN) + return -EINVAL; + + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < this_board->ai_ns_min) + cmd->convert_arg = this_board->ai_ns_min; + i8253_cascade_ns_to_timer(this_board->i8254_osc_base, + &divisor1, &divisor2, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + } + + start_pacer(dev, -1, 0, 0); // stop pacer + + devpriv->ai_n_chan = cmd->chanlist_len; + memcpy(devpriv->ai_chanlist, cmd->chanlist, + sizeof(unsigned int) * cmd->scan_end_arg); + setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1); // select first channel and range + + if (devpriv->dma) { // check if we can use DMA transfer + devpriv->ai_dma = 1; + for (i = 1; i < devpriv->ai_n_chan; i++) + if (devpriv->ai_chanlist[0] != devpriv->ai_chanlist[i]) { + devpriv->ai_dma = 0; // we cann't use DMA :-( + break; + } + } else + devpriv->ai_dma = 0; + + devpriv->ai_flags = cmd->flags; + devpriv->ai_data_len = s->async->prealloc_bufsz; + devpriv->ai_data = s->async->prealloc_buf; + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ai_scans = cmd->stop_arg; + devpriv->ai_neverending = 0; + } else { + devpriv->ai_scans = 0; + devpriv->ai_neverending = 1; + } + + devpriv->ai_act_scan = 0; + devpriv->ai_poll_ptr = 0; + s->async->cur_chan = 0; + + if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { // don't we want wake up every scan? + devpriv->ai_eos = 1; + if (devpriv->ai_n_chan == 1) + devpriv->ai_dma = 0; // DMA is useless for this situation + } + + if (devpriv->ai_dma) { + if (devpriv->ai_eos) { // we use EOS, so adapt DMA buffer to one scan + devpriv->dmabytestomove[0] = + devpriv->ai_n_chan * sizeof(short); + devpriv->dmabytestomove[1] = + devpriv->ai_n_chan * sizeof(short); + devpriv->dma_runs_to_end = 1; + } else { + devpriv->dmabytestomove[0] = devpriv->hwdmasize[0]; + devpriv->dmabytestomove[1] = devpriv->hwdmasize[1]; + if (devpriv->ai_data_len < devpriv->hwdmasize[0]) + devpriv->dmabytestomove[0] = + devpriv->ai_data_len; + if (devpriv->ai_data_len < devpriv->hwdmasize[1]) + devpriv->dmabytestomove[1] = + devpriv->ai_data_len; + if (devpriv->ai_neverending) { + devpriv->dma_runs_to_end = 1; + } else { + bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); // how many samples we must transfer? + devpriv->dma_runs_to_end = bytes / devpriv->dmabytestomove[0]; // how many DMA pages we must fill + devpriv->last_dma_run = bytes % devpriv->dmabytestomove[0]; //on last dma transfer must be moved + if (devpriv->dma_runs_to_end == 0) + devpriv->dmabytestomove[0] = + devpriv->last_dma_run; + devpriv->dma_runs_to_end--; + } + } + if (devpriv->dmabytestomove[0] > devpriv->hwdmasize[0]) { + devpriv->dmabytestomove[0] = devpriv->hwdmasize[0]; + devpriv->ai_eos = 0; + } + if (devpriv->dmabytestomove[1] > devpriv->hwdmasize[1]) { + devpriv->dmabytestomove[1] = devpriv->hwdmasize[1]; + devpriv->ai_eos = 0; + } + devpriv->next_dma_buf = 0; + set_dma_mode(devpriv->dma, DMA_MODE_READ); + dma_flags = claim_dma_lock(); + clear_dma_ff(devpriv->dma); + set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); + set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]); + release_dma_lock(dma_flags); + enable_dma(devpriv->dma); +#ifdef PCL812_EXTDEBUG + rt_printk + ("pcl812 EDBG: DMA %d PTR 0x%0x/0x%0x LEN %u/%u EOS %d\n", + devpriv->dma, devpriv->hwdmaptr[0], + devpriv->hwdmaptr[1], devpriv->dmabytestomove[0], + devpriv->dmabytestomove[1], devpriv->ai_eos); +#endif + } + + switch (cmd->convert_src) { + case TRIG_TIMER: + start_pacer(dev, 1, divisor1, divisor2); + break; + } + + if (devpriv->ai_dma) { + outb(devpriv->mode_reg_int | 2, dev->iobase + PCL812_MODE); // let's go! + } else { + outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE); // let's go! + } + +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: END: pcl812_ai_cmd(...)\n"); +#endif + + return 0; +} + +/* +============================================================================== +*/ +static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d) +{ + char err = 1; + unsigned int mask, timeout; + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + + s->async->events = 0; + + timeout = 50; /* wait max 50us, it must finish under 33us */ + if (devpriv->ai_is16b) { + mask = 0xffff; + while (timeout--) { + if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) { + err = 0; + break; + } + comedi_udelay(1); + } + } else { + mask = 0x0fff; + while (timeout--) { + if (!(inb(dev->iobase + PCL812_AD_HI) & PCL812_DRDY)) { + err = 0; + break; + } + comedi_udelay(1); + } + } + + if (err) { + rt_printk + ("comedi%d: pcl812: (%s at 0x%lx) A/D cmd IRQ without DRDY!\n", + dev->minor, dev->board_name, dev->iobase); + pcl812_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + } + + comedi_buf_put(s->async, + ((inb(dev->iobase + PCL812_AD_HI) << 8) | inb(dev->iobase + + PCL812_AD_LO)) & mask); + + outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ + + if (s->async->cur_chan == 0) { /* one scan done */ + devpriv->ai_act_scan++; + if (!(devpriv->ai_neverending)) + if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + pcl812_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + } + } + + comedi_event(dev, s); + return IRQ_HANDLED; +} + +/* +============================================================================== +*/ +static void transfer_from_dma_buf(struct comedi_device * dev, struct comedi_subdevice * s, + short * ptr, unsigned int bufptr, unsigned int len) +{ + unsigned int i; + + s->async->events = 0; + for (i = len; i; i--) { + comedi_buf_put(s->async, ptr[bufptr++]); // get one sample + + if (s->async->cur_chan == 0) { + devpriv->ai_act_scan++; + if (!devpriv->ai_neverending) + if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + pcl812_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + break; + } + } + } + + comedi_event(dev, s); +} + +/* +============================================================================== +*/ +static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + unsigned long dma_flags; + int len, bufptr; + short *ptr; + +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: BGN: interrupt_pcl812_ai_dma(...)\n"); +#endif + ptr = (short *) devpriv->dmabuf[devpriv->next_dma_buf]; + len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - + devpriv->ai_poll_ptr; + + devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; + disable_dma(devpriv->dma); + set_dma_mode(devpriv->dma, DMA_MODE_READ); + dma_flags = claim_dma_lock(); + set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]); + if (devpriv->ai_eos) { + set_dma_count(devpriv->dma, + devpriv->dmabytestomove[devpriv->next_dma_buf]); + } else { + if (devpriv->dma_runs_to_end) { + set_dma_count(devpriv->dma, + devpriv->dmabytestomove[devpriv->next_dma_buf]); + } else { + set_dma_count(devpriv->dma, devpriv->last_dma_run); + } + devpriv->dma_runs_to_end--; + } + release_dma_lock(dma_flags); + enable_dma(devpriv->dma); + + outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ + + bufptr = devpriv->ai_poll_ptr; + devpriv->ai_poll_ptr = 0; + + transfer_from_dma_buf(dev, s, ptr, bufptr, len); + +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: END: interrupt_pcl812_ai_dma(...)\n"); +#endif + return IRQ_HANDLED; +} + +/* +============================================================================== +*/ +static irqreturn_t interrupt_pcl812(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + + if (!dev->attached) { + comedi_error(dev, "spurious interrupt"); + return IRQ_HANDLED; + } + if (devpriv->ai_dma) { + return interrupt_pcl812_ai_dma(irq, d); + } else { + return interrupt_pcl812_ai_int(irq, d); + }; +} + +/* +============================================================================== +*/ +static int pcl812_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + unsigned int top1, top2, i; + + if (!devpriv->ai_dma) + return 0; // poll is valid only for DMA transfer + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + + for (i = 0; i < 10; i++) { + top1 = get_dma_residue(devpriv->ai_dma); // where is now DMA + top2 = get_dma_residue(devpriv->ai_dma); + if (top1 == top2) + break; + } + + if (top1 != top2) { + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + return 0; + } + + top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1; // where is now DMA in buffer + top1 >>= 1; // sample position + top2 = top1 - devpriv->ai_poll_ptr; + if (top2 < 1) { // no new samples + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + return 0; + } + + transfer_from_dma_buf(dev, s, + (void *)devpriv->dmabuf[1 - devpriv->next_dma_buf], + devpriv->ai_poll_ptr, top2); + + devpriv->ai_poll_ptr = top1; // new buffer position + + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + return s->async->buf_write_count - s->async->buf_read_count; +} + +/* +============================================================================== +*/ +static void setup_range_channel(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int rangechan, char wait) +{ + unsigned char chan_reg = CR_CHAN(rangechan); // normal board + unsigned char gain_reg = CR_RANGE(rangechan) + devpriv->range_correction; // gain index + + if ((chan_reg == devpriv->old_chan_reg) + && (gain_reg == devpriv->old_gain_reg)) + return; // we can return, no change + + devpriv->old_chan_reg = chan_reg; + devpriv->old_gain_reg = gain_reg; + + if (devpriv->use_MPC) { + if (devpriv->use_diff) { + chan_reg = chan_reg | 0x30; // DIFF inputs + } else { + if (chan_reg & 0x80) { + chan_reg = chan_reg | 0x20; // SE inputs 8-15 + } else { + chan_reg = chan_reg | 0x10; // SE inputs 0-7 + } + } + } + + outb(chan_reg, dev->iobase + PCL812_MUX); /* select channel */ + outb(gain_reg, dev->iobase + PCL812_GAIN); /* select gain */ + + if (wait) { + comedi_udelay(devpriv->max_812_ai_mode0_rangewait); // XXX this depends on selected range and can be very long for some high gain ranges! + } +} + +/* +============================================================================== +*/ +static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2) +{ +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, divisor1, + divisor2); +#endif + outb(0xb4, dev->iobase + PCL812_CTRCTL); + outb(0x74, dev->iobase + PCL812_CTRCTL); + comedi_udelay(1); + + if (mode == 1) { + outb(divisor2 & 0xff, dev->iobase + PCL812_CTR2); + outb((divisor2 >> 8) & 0xff, dev->iobase + PCL812_CTR2); + outb(divisor1 & 0xff, dev->iobase + PCL812_CTR1); + outb((divisor1 >> 8) & 0xff, dev->iobase + PCL812_CTR1); + } +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: END: start_pacer(...)\n"); +#endif +} + +/* +============================================================================== +*/ +static void free_resources(struct comedi_device * dev) +{ + + if (dev->private) { + if (devpriv->dmabuf[0]) + free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); + if (devpriv->dmabuf[1]) + free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); + if (devpriv->dma) + free_dma(devpriv->dma); + } + if (dev->irq) + comedi_free_irq(dev->irq, dev); + if (dev->iobase) + release_region(dev->iobase, this_board->io_range); +} + +/* +============================================================================== +*/ +static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n"); +#endif + if (devpriv->ai_dma) + disable_dma(devpriv->dma); + outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ + outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); /* Stop A/D */ + start_pacer(dev, -1, 0, 0); // stop 8254 + outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */ +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: END: pcl812_ai_cancel(...)\n"); +#endif + return 0; +} + +/* +============================================================================== +*/ +static void pcl812_reset(struct comedi_device * dev) +{ +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: BGN: pcl812_reset(...)\n"); +#endif + outb(0, dev->iobase + PCL812_MUX); + outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN); + devpriv->old_chan_reg = -1; // invalidate chain/gain memory + devpriv->old_gain_reg = -1; + + switch (this_board->board_type) { + case boardPCL812PG: + case boardPCL812: + case boardACL8112: + case boardACL8216: + outb(0, dev->iobase + PCL812_DA2_LO); + outb(0, dev->iobase + PCL812_DA2_HI); + case boardA821: + outb(0, dev->iobase + PCL812_DA1_LO); + outb(0, dev->iobase + PCL812_DA1_HI); + start_pacer(dev, -1, 0, 0); // stop 8254 + outb(0, dev->iobase + PCL812_DO_HI); + outb(0, dev->iobase + PCL812_DO_LO); + outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE); + outb(0, dev->iobase + PCL812_CLRINT); + break; + case boardPCL813B: + case boardPCL813: + case boardISO813: + case boardACL8113: + comedi_udelay(5); + break; + } + comedi_udelay(5); +#ifdef PCL812_EXTDEBUG + rt_printk("pcl812 EDBG: END: pcl812_reset(...)\n"); +#endif +} + +/* +============================================================================== +*/ +static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret, subdev; + unsigned long iobase; + unsigned int irq; + unsigned int dma; + unsigned long pages; + struct comedi_subdevice *s; + int n_subdevices; + + iobase = it->options[0]; + printk("comedi%d: pcl812: board=%s, ioport=0x%03lx", dev->minor, + this_board->name, iobase); + + if (!request_region(iobase, this_board->io_range, "pcl812")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + if ((ret = alloc_private(dev, sizeof(struct pcl812_private))) < 0) { + free_resources(dev); + return ret; /* Can't alloc mem */ + } + + dev->board_name = this_board->name; + + irq = 0; + if (this_board->IRQbits != 0) { /* board support IRQ */ + irq = it->options[1]; + if (irq) { /* we want to use IRQ */ + if (((1 << irq) & this_board->IRQbits) == 0) { + printk(", IRQ %u is out of allowed range, DISABLING IT", irq); + irq = 0; /* Bad IRQ */ + } else { + if (comedi_request_irq(irq, interrupt_pcl812, 0, + "pcl812", dev)) { + printk(", unable to allocate IRQ %u, DISABLING IT", irq); + irq = 0; /* Can't use IRQ */ + } else { + printk(", irq=%u", irq); + } + } + } + } + + dev->irq = irq; + + dma = 0; + devpriv->dma = dma; + if (!dev->irq) + goto no_dma; /* if we haven't IRQ, we can't use DMA */ + if (this_board->DMAbits != 0) { /* board support DMA */ + dma = it->options[2]; + if (((1 << dma) & this_board->DMAbits) == 0) { + printk(", DMA is out of allowed range, FAIL!\n"); + return -EINVAL; /* Bad DMA */ + } + ret = request_dma(dma, "pcl812"); + if (ret) { + printk(", unable to allocate DMA %u, FAIL!\n", dma); + return -EBUSY; /* DMA isn't free */ + } + devpriv->dma = dma; + printk(", dma=%u", dma); + pages = 1; /* we want 8KB */ + devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); + if (!devpriv->dmabuf[0]) { + printk(", unable to allocate DMA buffer, FAIL!\n"); + /* maybe experiment with try_to_free_pages() will help .... */ + free_resources(dev); + return -EBUSY; /* no buffer :-( */ + } + devpriv->dmapages[0] = pages; + devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); + devpriv->hwdmasize[0] = PAGE_SIZE * (1 << pages); + devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); + if (!devpriv->dmabuf[1]) { + printk(", unable to allocate DMA buffer, FAIL!\n"); + free_resources(dev); + return -EBUSY; + } + devpriv->dmapages[1] = pages; + devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]); + devpriv->hwdmasize[1] = PAGE_SIZE * (1 << pages); + } + no_dma: + + n_subdevices = 0; + if (this_board->n_aichan > 0) + n_subdevices++; + if (this_board->n_aochan > 0) + n_subdevices++; + if (this_board->n_dichan > 0) + n_subdevices++; + if (this_board->n_dochan > 0) + n_subdevices++; + + if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) { + free_resources(dev); + return ret; + } + + subdev = 0; + + /* analog input */ + if (this_board->n_aichan > 0) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE; + switch (this_board->board_type) { + case boardA821: + if (it->options[2] == 1) { + s->n_chan = this_board->n_aichan_diff; + s->subdev_flags |= SDF_DIFF; + devpriv->use_diff = 1; + } else { + s->n_chan = this_board->n_aichan; + s->subdev_flags |= SDF_GROUND; + } + break; + case boardACL8112: + case boardACL8216: + if (it->options[4] == 1) { + s->n_chan = this_board->n_aichan_diff; + s->subdev_flags |= SDF_DIFF; + devpriv->use_diff = 1; + } else { + s->n_chan = this_board->n_aichan; + s->subdev_flags |= SDF_GROUND; + } + break; + default: + s->n_chan = this_board->n_aichan; + s->subdev_flags |= SDF_GROUND; + break; + } + s->maxdata = this_board->ai_maxdata; + s->len_chanlist = MAX_CHANLIST_LEN; + s->range_table = this_board->rangelist_ai; + if (this_board->board_type == boardACL8216) { + s->insn_read = acl8216_ai_insn_read; + } else { + s->insn_read = pcl812_ai_insn_read; + } + devpriv->use_MPC = this_board->haveMPC508; + s->cancel = pcl812_ai_cancel; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->do_cmdtest = pcl812_ai_cmdtest; + s->do_cmd = pcl812_ai_cmd; + s->poll = pcl812_ai_poll; + } + switch (this_board->board_type) { + case boardPCL812PG: + if (it->options[4] == 1) + s->range_table = &range_pcl812pg2_ai; + break; + case boardPCL812: + switch (it->options[4]) { + case 0: + s->range_table = &range_bipolar10; + break; + case 1: + s->range_table = &range_bipolar5; + break; + case 2: + s->range_table = &range_bipolar2_5; + break; + case 3: + s->range_table = &range812_bipolar1_25; + break; + case 4: + s->range_table = &range812_bipolar0_625; + break; + case 5: + s->range_table = &range812_bipolar0_3125; + break; + default: + s->range_table = &range_bipolar10; + break; + printk(", incorrect range number %d, changing to 0 (+/-10V)", it->options[4]); + break; + } + break; + break; + case boardPCL813B: + if (it->options[1] == 1) + s->range_table = &range_pcl813b2_ai; + break; + case boardISO813: + switch (it->options[1]) { + case 0: + s->range_table = &range_iso813_1_ai; + break; + case 1: + s->range_table = &range_iso813_1_2_ai; + break; + case 2: + s->range_table = &range_iso813_2_ai; + devpriv->range_correction = 1; + break; + case 3: + s->range_table = &range_iso813_2_2_ai; + devpriv->range_correction = 1; + break; + default: + s->range_table = &range_iso813_1_ai; + break; + printk(", incorrect range number %d, changing to 0 ", it->options[1]); + break; + } + break; + case boardACL8113: + switch (it->options[1]) { + case 0: + s->range_table = &range_acl8113_1_ai; + break; + case 1: + s->range_table = &range_acl8113_1_2_ai; + break; + case 2: + s->range_table = &range_acl8113_2_ai; + devpriv->range_correction = 1; + break; + case 3: + s->range_table = &range_acl8113_2_2_ai; + devpriv->range_correction = 1; + break; + default: + s->range_table = &range_acl8113_1_ai; + break; + printk(", incorrect range number %d, changing to 0 ", it->options[1]); + break; + } + break; + } + subdev++; + } + + /* analog output */ + if (this_board->n_aochan > 0) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = this_board->n_aochan; + s->maxdata = 0xfff; + s->len_chanlist = 1; + s->range_table = this_board->rangelist_ao; + s->insn_read = pcl812_ao_insn_read; + s->insn_write = pcl812_ao_insn_write; + switch (this_board->board_type) { + case boardA821: + if (it->options[3] == 1) + s->range_table = &range_unipolar10; + break; + case boardPCL812: + case boardACL8112: + case boardPCL812PG: + case boardACL8216: + if (it->options[5] == 1) + s->range_table = &range_unipolar10; + if (it->options[5] == 2) + s->range_table = &range_unknown; + break; + } + subdev++; + } + + /* digital input */ + if (this_board->n_dichan > 0) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = this_board->n_dichan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dichan; + s->range_table = &range_digital; + s->insn_bits = pcl812_di_insn_bits; + subdev++; + } + + /* digital output */ + if (this_board->n_dochan > 0) { + s = dev->subdevices + subdev; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = this_board->n_dochan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dochan; + s->range_table = &range_digital; + s->insn_bits = pcl812_do_insn_bits; + subdev++; + } + + switch (this_board->board_type) { + case boardACL8216: + devpriv->ai_is16b = 1; + case boardPCL812PG: + case boardPCL812: + case boardACL8112: + devpriv->max_812_ai_mode0_rangewait = 1; + if (it->options[3] > 0) + devpriv->use_ext_trg = 1; // we use external trigger + case boardA821: + devpriv->max_812_ai_mode0_rangewait = 1; + devpriv->mode_reg_int = (irq << 4) & 0xf0; + break; + case boardPCL813B: + case boardPCL813: + case boardISO813: + case boardACL8113: + devpriv->max_812_ai_mode0_rangewait = 5; /* maybe there must by greatest timeout */ + break; + } + + printk("\n"); + devpriv->valid = 1; + + pcl812_reset(dev); + + return 0; +} + +/* +============================================================================== + */ +static int pcl812_detach(struct comedi_device * dev) +{ + +#ifdef PCL812_EXTDEBUG + rt_printk("comedi%d: pcl812: remove\n", dev->minor); +#endif + free_resources(dev); + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c new file mode 100644 index 000000000000..515ba74cc7fe --- /dev/null +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -0,0 +1,1251 @@ +/* + comedi/drivers/pcl816.c + + Author: Juan Grigera + based on pcl818 by Michal Dobes and bits of pcl812 + + hardware driver for Advantech cards: + card: PCL-816, PCL814B + driver: pcl816 +*/ +/* +Driver: pcl816 +Description: Advantech PCL-816 cards, PCL-814 +Author: Juan Grigera +Devices: [Advantech] PCL-816 (pcl816), PCL-814B (pcl814b) +Status: works +Updated: Tue, 2 Apr 2002 23:15:21 -0800 + +PCL 816 and 814B have 16 SE/DIFF ADCs, 16 DACs, 16 DI and 16 DO. +Differences are at resolution (16 vs 12 bits). + +The driver support AI command mode, other subdevices not written. + +Analog output and digital input and output are not supported. + +Configuration Options: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + [2] - DMA (0=disable, 1, 3) + [3] - 0, 10=10MHz clock for 8254 + 1= 1MHz clock for 8254 + +*/ + +#include "../comedidev.h" + +#include +#include +#include +#include + +#include "8253.h" + +#define DEBUG(x) x + +// boards constants +// IO space len +#define PCLx1x_RANGE 16 + +//#define outb(x,y) printk("OUTB(%x, 200+%d)\n", x,y-0x200); outb(x,y) + +// INTEL 8254 counters +#define PCL816_CTR0 4 +#define PCL816_CTR1 5 +#define PCL816_CTR2 6 +// R: counter read-back register W: counter control +#define PCL816_CTRCTL 7 + +// R: A/D high byte W: A/D range control +#define PCL816_RANGE 9 +// W: clear INT request +#define PCL816_CLRINT 10 +// R: next mux scan channel W: mux scan channel & range control pointer +#define PCL816_MUX 11 +// R/W: operation control register +#define PCL816_CONTROL 12 + +// R: return status byte W: set DMA/IRQ +#define PCL816_STATUS 13 +#define PCL816_STATUS_DRDY_MASK 0x80 + +// R: low byte of A/D W: soft A/D trigger +#define PCL816_AD_LO 8 +// R: high byte of A/D W: A/D range control +#define PCL816_AD_HI 9 + +// type of interrupt handler +#define INT_TYPE_AI1_INT 1 +#define INT_TYPE_AI1_DMA 2 +#define INT_TYPE_AI3_INT 4 +#define INT_TYPE_AI3_DMA 5 +#ifdef unused +#define INT_TYPE_AI1_DMA_RTC 9 +#define INT_TYPE_AI3_DMA_RTC 10 + +// RTC stuff... +#define RTC_IRQ 8 +#define RTC_IO_EXTENT 0x10 +#endif + +#define MAGIC_DMA_WORD 0x5a5a + +static const struct comedi_lrange range_pcl816 = { 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + } +}; +struct pcl816_board { + + const char *name; // board name + int n_ranges; // len of range list + int n_aichan; // num of A/D chans in diferencial mode + unsigned int ai_ns_min; // minimal alllowed delay between samples (in ns) + int n_aochan; // num of D/A chans + int n_dichan; // num of DI chans + int n_dochan; // num of DO chans + const struct comedi_lrange *ai_range_type; // default A/D rangelist + const struct comedi_lrange *ao_range_type; // dafault D/A rangelist + unsigned int io_range; // len of IO space + unsigned int IRQbits; // allowed interrupts + unsigned int DMAbits; // allowed DMA chans + int ai_maxdata; // maxdata for A/D + int ao_maxdata; // maxdata for D/A + int ai_chanlist; // allowed len of channel list A/D + int ao_chanlist; // allowed len of channel list D/A + int i8254_osc_base; // 1/frequency of on board oscilator in ns +}; + + +static const struct pcl816_board boardtypes[] = { + {"pcl816", 8, 16, 10000, 1, 16, 16, &range_pcl816, + &range_pcl816, PCLx1x_RANGE, + 0x00fc, // IRQ mask + 0x0a, // DMA mask + 0xffff, // 16-bit card + 0xffff, // D/A maxdata + 1024, + 1, // ao chan list + 100}, + {"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816, + &range_pcl816, PCLx1x_RANGE, + 0x00fc, + 0x0a, + 0x3fff, /* 14 bit card */ + 0x3fff, + 1024, + 1, + 100}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl816_board)) +#define devpriv ((struct pcl816_private *)dev->private) +#define this_board ((const struct pcl816_board *)dev->board_ptr) + +static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcl816_detach(struct comedi_device * dev); + +#ifdef unused +static int RTC_lock = 0; /* RTC lock */ +static int RTC_timer_lock = 0; /* RTC int lock */ +#endif + +static struct comedi_driver driver_pcl816 = { + driver_name:"pcl816", + module:THIS_MODULE, + attach:pcl816_attach, + detach:pcl816_detach, + board_name:&boardtypes[0].name, + num_names:n_boardtypes, + offset:sizeof(struct pcl816_board), +}; + +COMEDI_INITCLEANUP(driver_pcl816); + +struct pcl816_private { + + unsigned int dma; // used DMA, 0=don't use DMA + int dma_rtc; // 1=RTC used with DMA, 0=no RTC alloc +#ifdef unused + unsigned long rtc_iobase; // RTC port region + unsigned int rtc_iosize; + unsigned int rtc_irq; +#endif + unsigned long dmabuf[2]; // pointers to begin of DMA buffers + unsigned int dmapages[2]; // len of DMA buffers in PAGE_SIZEs + unsigned int hwdmaptr[2]; // hardware address of DMA buffers + unsigned int hwdmasize[2]; // len of DMA buffers in Bytes + unsigned int dmasamplsize; // size in samples hwdmasize[0]/2 + unsigned int last_top_dma; // DMA pointer in last RTC int + int next_dma_buf; // which DMA buffer will be used next round + long dma_runs_to_end; // how many we must permorm DMA transfer to end of record + unsigned long last_dma_run; // how many bytes we must transfer on last DMA page + + unsigned int ai_scans; // len of scanlist + unsigned char ai_neverending; // if=1, then we do neverending record (you must use cancel()) + int irq_free; // 1=have allocated IRQ + int irq_blocked; // 1=IRQ now uses any subdev +#ifdef unused + int rtc_irq_blocked; // 1=we now do AI with DMA&RTC +#endif + int irq_was_now_closed; // when IRQ finish, there's stored int816_mode for last interrupt + int int816_mode; // who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma + struct comedi_subdevice *last_int_sub; // ptr to subdevice which now finish + int ai_act_scan; // how many scans we finished + unsigned int ai_act_chanlist[16]; // MUX setting for actual AI operations + unsigned int ai_act_chanlist_len; // how long is actual MUX list + unsigned int ai_act_chanlist_pos; // actual position in MUX list + unsigned int ai_poll_ptr; // how many sampes transfer poll + struct comedi_subdevice *sub_ai; // ptr to AI subdevice +#ifdef unused + struct timer_list rtc_irq_timer; // timer for RTC sanity check + unsigned long rtc_freq; // RTC int freq +#endif +}; + + +/* +============================================================================== +*/ +static int check_and_setup_channel_list(struct comedi_device * dev, + struct comedi_subdevice * s, unsigned int *chanlist, int chanlen); +static int pcl816_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2); +#ifdef unused +static int set_rtc_irq_bit(unsigned char bit); +#endif + +static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s); + +/* +============================================================================== + ANALOG INPUT MODE0, 816 cards, slow version +*/ +static int pcl816_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int timeout; + + DPRINTK("mode 0 analog input\n"); + // software trigger, DMA and INT off + outb(0, dev->iobase + PCL816_CONTROL); + // clear INT (conversion end) flag + outb(0, dev->iobase + PCL816_CLRINT); + + // Set the input channel + outb(CR_CHAN(insn->chanspec) & 0xf, dev->iobase + PCL816_MUX); + outb(CR_RANGE(insn->chanspec), dev->iobase + PCL816_RANGE); /* select gain */ + + for (n = 0; n < insn->n; n++) { + + outb(0, dev->iobase + PCL816_AD_LO); /* start conversion */ + + timeout = 100; + while (timeout--) { + if (!(inb(dev->iobase + PCL816_STATUS) & + PCL816_STATUS_DRDY_MASK)) { + // return read value + data[n] = + ((inb(dev->iobase + + PCL816_AD_HI) << 8) | + (inb(dev->iobase + PCL816_AD_LO))); + + outb(0, dev->iobase + PCL816_CLRINT); /* clear INT (conversion end) flag */ + break; + } + comedi_udelay(1); + } + // Return timeout error + if (!timeout) { + comedi_error(dev, "A/D insn timeout\n"); + data[0] = 0; + outb(0, dev->iobase + PCL816_CLRINT); /* clear INT (conversion end) flag */ + return -EIO; + } + + } + return n; +} + +/* +============================================================================== + analog input interrupt mode 1 & 3, 818 cards + one sample per interrupt version +*/ +static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + int low, hi; + int timeout = 50; /* wait max 50us */ + + while (timeout--) { + if (!(inb(dev->iobase + PCL816_STATUS) & + PCL816_STATUS_DRDY_MASK)) + break; + comedi_udelay(1); + } + if (!timeout) { // timeout, bail error + outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ + comedi_error(dev, "A/D mode1/3 IRQ without DRDY!"); + pcl816_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + + } + + // get the sample + low = inb(dev->iobase + PCL816_AD_LO); + hi = inb(dev->iobase + PCL816_AD_HI); + + comedi_buf_put(s->async, (hi << 8) | low); + + outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ + + if (++devpriv->ai_act_chanlist_pos >= devpriv->ai_act_chanlist_len) + devpriv->ai_act_chanlist_pos = 0; + + if (s->async->cur_chan == 0) { + devpriv->ai_act_scan++; + } + + if (!devpriv->ai_neverending) + if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ + /* all data sampled */ + pcl816_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + } + comedi_event(dev, s); + return IRQ_HANDLED; +} + +/* +============================================================================== + analog input dma mode 1 & 3, 816 cards +*/ +static void transfer_from_dma_buf(struct comedi_device * dev, struct comedi_subdevice * s, + short * ptr, unsigned int bufptr, unsigned int len) +{ + int i; + + s->async->events = 0; + + for (i = 0; i < len; i++) { + + comedi_buf_put(s->async, ptr[bufptr++]); + + if (++devpriv->ai_act_chanlist_pos >= + devpriv->ai_act_chanlist_len) { + devpriv->ai_act_chanlist_pos = 0; + devpriv->ai_act_scan++; + } + + if (!devpriv->ai_neverending) + if (devpriv->ai_act_scan >= devpriv->ai_scans) { // all data sampled + pcl816_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_BLOCK; + break; + } + } + + comedi_event(dev, s); +} + +static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + int len, bufptr, this_dma_buf; + unsigned long dma_flags; + short *ptr; + + disable_dma(devpriv->dma); + this_dma_buf = devpriv->next_dma_buf; + + if ((devpriv->dma_runs_to_end > -1) || devpriv->ai_neverending) { // switch dma bufs + + devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; + set_dma_mode(devpriv->dma, DMA_MODE_READ); + dma_flags = claim_dma_lock(); +// clear_dma_ff (devpriv->dma); + set_dma_addr(devpriv->dma, + devpriv->hwdmaptr[devpriv->next_dma_buf]); + if (devpriv->dma_runs_to_end) { + set_dma_count(devpriv->dma, + devpriv->hwdmasize[devpriv->next_dma_buf]); + } else { + set_dma_count(devpriv->dma, devpriv->last_dma_run); + } + release_dma_lock(dma_flags); + enable_dma(devpriv->dma); + } + + devpriv->dma_runs_to_end--; + outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ + + ptr = (short *) devpriv->dmabuf[this_dma_buf]; + + len = (devpriv->hwdmasize[0] >> 1) - devpriv->ai_poll_ptr; + bufptr = devpriv->ai_poll_ptr; + devpriv->ai_poll_ptr = 0; + + transfer_from_dma_buf(dev, s, ptr, bufptr, len); + return IRQ_HANDLED; +} + +/* +============================================================================== + INT procedure +*/ +static irqreturn_t interrupt_pcl816(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + DPRINTK(""); + + if (!dev->attached) { + comedi_error(dev, "premature interrupt"); + return IRQ_HANDLED; + } + + switch (devpriv->int816_mode) { + case INT_TYPE_AI1_DMA: + case INT_TYPE_AI3_DMA: + return interrupt_pcl816_ai_mode13_dma(irq, d); + case INT_TYPE_AI1_INT: + case INT_TYPE_AI3_INT: + return interrupt_pcl816_ai_mode13_int(irq, d); + } + + outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ + if ((!dev->irq) | (!devpriv->irq_free) | (!devpriv->irq_blocked) | + (!devpriv->int816_mode)) { + if (devpriv->irq_was_now_closed) { + devpriv->irq_was_now_closed = 0; + // comedi_error(dev,"last IRQ.."); + return IRQ_HANDLED; + } + comedi_error(dev, "bad IRQ!"); + return IRQ_NONE; + } + comedi_error(dev, "IRQ from unknow source!"); + return IRQ_NONE; +} + +/* +============================================================================== + COMMAND MODE +*/ +static void pcl816_cmdtest_out(int e, struct comedi_cmd * cmd) +{ + rt_printk("pcl816 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, + cmd->start_src, cmd->scan_begin_src, cmd->convert_src); + rt_printk("pcl816 e=%d startarg=%d scanarg=%d convarg=%d\n", e, + cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); + rt_printk("pcl816 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src, + cmd->scan_end_src); + rt_printk("pcl816 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", e, + cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); +} + +/* +============================================================================== +*/ +static int pcl816_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp, divisor1, divisor2; + + DEBUG(rt_printk("pcl816 pcl812_ai_cmdtest\n"); + pcl816_cmdtest_out(-1, cmd);); + + /* step 1: make sure trigger sources are trivially valid */ + 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_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + if (!cmd->convert_src & (TRIG_EXT | TRIG_TIMER)) + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) { + return 1; + } + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW) { + cmd->start_src = TRIG_NOW; + err++; + } + + if (cmd->scan_begin_src != TRIG_FOLLOW) { + cmd->scan_begin_src = TRIG_FOLLOW; + err++; + } + + if (cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_TIMER) { + cmd->convert_src = TRIG_TIMER; + err++; + } + + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; + + if (err) { + return 2; + } + + /* step 3: make sure arguments are trivially compatible */ + 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_src == TRIG_TIMER) { + if (cmd->convert_arg < this_board->ai_ns_min) { + cmd->convert_arg = this_board->ai_ns_min; + err++; + } + } else { /* TRIG_EXT */ + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + } + + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->chanlist_len > this_board->n_aichan) { + cmd->chanlist_len = this_board->n_aichan; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + } else { /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) { + return 3; + } + + /* step 4: fix up any arguments */ + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + i8253_cascade_ns_to_timer(this_board->i8254_osc_base, + &divisor1, &divisor2, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (cmd->convert_arg < this_board->ai_ns_min) + cmd->convert_arg = this_board->ai_ns_min; + if (tmp != cmd->convert_arg) + err++; + } + + if (err) { + return 4; + } + + return 0; +} + +static int pcl816_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq; + struct comedi_cmd *cmd = &s->async->cmd; + + if (cmd->start_src != TRIG_NOW) + return -EINVAL; + if (cmd->scan_begin_src != TRIG_FOLLOW) + return -EINVAL; + if (cmd->scan_end_src != TRIG_COUNT) + return -EINVAL; + if (cmd->scan_end_arg != cmd->chanlist_len) + return -EINVAL; +// if(cmd->chanlist_len>MAX_CHANLIST_LEN) return -EINVAL; + if (devpriv->irq_blocked) + return -EBUSY; + + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < this_board->ai_ns_min) + cmd->convert_arg = this_board->ai_ns_min; + + i8253_cascade_ns_to_timer(this_board->i8254_osc_base, &divisor1, + &divisor2, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (divisor1 == 1) { // PCL816 crash if any divisor is set to 1 + divisor1 = 2; + divisor2 /= 2; + } + if (divisor2 == 1) { + divisor2 = 2; + divisor1 /= 2; + } + } + + start_pacer(dev, -1, 0, 0); // stop pacer + + if (!check_and_setup_channel_list(dev, s, cmd->chanlist, + cmd->chanlist_len)) + return -EINVAL; + comedi_udelay(1); + + devpriv->ai_act_scan = 0; + s->async->cur_chan = 0; + devpriv->irq_blocked = 1; + devpriv->ai_poll_ptr = 0; + devpriv->irq_was_now_closed = 0; + + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ai_scans = cmd->stop_arg; + devpriv->ai_neverending = 0; + } else { + devpriv->ai_scans = 0; + devpriv->ai_neverending = 1; + } + + if ((cmd->flags & TRIG_WAKE_EOS)) { // don't we want wake up every scan? + printk("pl816: You wankt WAKE_EOS but I dont want handle it"); + // devpriv->ai_eos=1; + //if (devpriv->ai_n_chan==1) + // devpriv->dma=0; // DMA is useless for this situation + } + + if (devpriv->dma) { + bytes = devpriv->hwdmasize[0]; + if (!devpriv->ai_neverending) { + bytes = s->async->cmd.chanlist_len * s->async->cmd.chanlist_len * sizeof(short); // how many + devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0]; // how many DMA pages we must fill + devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; //on last dma transfer must be moved + devpriv->dma_runs_to_end--; + if (devpriv->dma_runs_to_end >= 0) + bytes = devpriv->hwdmasize[0]; + } else + devpriv->dma_runs_to_end = -1; + + devpriv->next_dma_buf = 0; + set_dma_mode(devpriv->dma, DMA_MODE_READ); + dma_flags = claim_dma_lock(); + clear_dma_ff(devpriv->dma); + set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); + set_dma_count(devpriv->dma, bytes); + release_dma_lock(dma_flags); + enable_dma(devpriv->dma); + } + + start_pacer(dev, 1, divisor1, divisor2); + dmairq = ((devpriv->dma & 0x3) << 4) | (dev->irq & 0x7); + + switch (cmd->convert_src) { + case TRIG_TIMER: + devpriv->int816_mode = INT_TYPE_AI1_DMA; + outb(0x32, dev->iobase + PCL816_CONTROL); // Pacer+IRQ+DMA + outb(dmairq, dev->iobase + PCL816_STATUS); // write irq and DMA to card + break; + + default: + devpriv->int816_mode = INT_TYPE_AI3_DMA; + outb(0x34, dev->iobase + PCL816_CONTROL); // Ext trig+IRQ+DMA + outb(dmairq, dev->iobase + PCL816_STATUS); // write irq to card + break; + } + + DPRINTK("pcl816 END: pcl812_ai_cmd()\n"); + return 0; +} + +static int pcl816_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + unsigned int top1, top2, i; + + if (!devpriv->dma) + return 0; // poll is valid only for DMA transfer + + comedi_spin_lock_irqsave(&dev->spinlock, flags); + + for (i = 0; i < 20; i++) { + top1 = get_dma_residue(devpriv->dma); // where is now DMA + top2 = get_dma_residue(devpriv->dma); + if (top1 == top2) + break; + } + if (top1 != top2) { + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + return 0; + } + + top1 = devpriv->hwdmasize[0] - top1; // where is now DMA in buffer + top1 >>= 1; // sample position + top2 = top1 - devpriv->ai_poll_ptr; + if (top2 < 1) { // no new samples + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + return 0; + } + + transfer_from_dma_buf(dev, s, + (short *) devpriv->dmabuf[devpriv->next_dma_buf], + devpriv->ai_poll_ptr, top2); + + devpriv->ai_poll_ptr = top1; // new buffer position + comedi_spin_unlock_irqrestore(&dev->spinlock, flags); + + return s->async->buf_write_count - s->async->buf_read_count; +} + +/* +============================================================================== + cancel any mode 1-4 AI +*/ +static int pcl816_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ +// DEBUG(rt_printk("pcl816_ai_cancel()\n");) + + if (devpriv->irq_blocked > 0) { + switch (devpriv->int816_mode) { +#ifdef unused + case INT_TYPE_AI1_DMA_RTC: + case INT_TYPE_AI3_DMA_RTC: + set_rtc_irq_bit(0); // stop RTC + del_timer(&devpriv->rtc_irq_timer); +#endif + case INT_TYPE_AI1_DMA: + case INT_TYPE_AI3_DMA: + disable_dma(devpriv->dma); + case INT_TYPE_AI1_INT: + case INT_TYPE_AI3_INT: + outb(inb(dev->iobase + PCL816_CONTROL) & 0x73, dev->iobase + PCL816_CONTROL); /* Stop A/D */ + comedi_udelay(1); + outb(0, dev->iobase + PCL816_CONTROL); /* Stop A/D */ + outb(0xb0, dev->iobase + PCL816_CTRCTL); /* Stop pacer */ + outb(0x70, dev->iobase + PCL816_CTRCTL); + outb(0, dev->iobase + PCL816_AD_LO); + inb(dev->iobase + PCL816_AD_LO); + inb(dev->iobase + PCL816_AD_HI); + outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ + outb(0, dev->iobase + PCL816_CONTROL); /* Stop A/D */ + devpriv->irq_blocked = 0; + devpriv->irq_was_now_closed = devpriv->int816_mode; + devpriv->int816_mode = 0; + devpriv->last_int_sub = s; +// s->busy = 0; + break; + } + } + + DEBUG(rt_printk("comedi: pcl816_ai_cancel() successful\n"); + ) + return 0; +} + +/* +============================================================================== + chech for PCL816 +*/ +static int pcl816_check(unsigned long iobase) +{ + outb(0x00, iobase + PCL816_MUX); + comedi_udelay(1); + if (inb(iobase + PCL816_MUX) != 0x00) + return 1; //there isn't card + outb(0x55, iobase + PCL816_MUX); + comedi_udelay(1); + if (inb(iobase + PCL816_MUX) != 0x55) + return 1; //there isn't card + outb(0x00, iobase + PCL816_MUX); + comedi_udelay(1); + outb(0x18, iobase + PCL816_CONTROL); + comedi_udelay(1); + if (inb(iobase + PCL816_CONTROL) != 0x18) + return 1; //there isn't card + return 0; // ok, card exist +} + +/* +============================================================================== + reset whole PCL-816 cards +*/ +static void pcl816_reset(struct comedi_device * dev) +{ +// outb (0, dev->iobase + PCL818_DA_LO); // DAC=0V +// outb (0, dev->iobase + PCL818_DA_HI); +// comedi_udelay (1); +// outb (0, dev->iobase + PCL818_DO_HI); // DO=$0000 +// outb (0, dev->iobase + PCL818_DO_LO); +// comedi_udelay (1); + outb(0, dev->iobase + PCL816_CONTROL); + outb(0, dev->iobase + PCL816_MUX); + outb(0, dev->iobase + PCL816_CLRINT); + outb(0xb0, dev->iobase + PCL816_CTRCTL); /* Stop pacer */ + outb(0x70, dev->iobase + PCL816_CTRCTL); + outb(0x30, dev->iobase + PCL816_CTRCTL); + outb(0, dev->iobase + PCL816_RANGE); +} + +/* +============================================================================== + Start/stop pacer onboard pacer +*/ +static void +start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2) +{ + outb(0x32, dev->iobase + PCL816_CTRCTL); + outb(0xff, dev->iobase + PCL816_CTR0); + outb(0x00, dev->iobase + PCL816_CTR0); + comedi_udelay(1); + outb(0xb4, dev->iobase + PCL816_CTRCTL); // set counter 2 as mode 3 + outb(0x74, dev->iobase + PCL816_CTRCTL); // set counter 1 as mode 3 + comedi_udelay(1); + + if (mode == 1) { + DPRINTK("mode %d, divisor1 %d, divisor2 %d\n", mode, divisor1, + divisor2); + outb(divisor2 & 0xff, dev->iobase + PCL816_CTR2); + outb((divisor2 >> 8) & 0xff, dev->iobase + PCL816_CTR2); + outb(divisor1 & 0xff, dev->iobase + PCL816_CTR1); + outb((divisor1 >> 8) & 0xff, dev->iobase + PCL816_CTR1); + } + + /* clear pending interrupts (just in case) */ +// outb(0, dev->iobase + PCL816_CLRINT); +} + +/* +============================================================================== + Check if channel list from user is builded correctly + If it's ok, then program scan/gain logic +*/ +static int +check_and_setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int *chanlist, int chanlen) +{ + unsigned int chansegment[16]; + unsigned int i, nowmustbechan, seglen, segpos; + + // correct channel and range number check itself comedi/range.c + if (chanlen < 1) { + comedi_error(dev, "range/channel list is empty!"); + return 0; + } + + if (chanlen > 1) { + chansegment[0] = chanlist[0]; // first channel is everytime ok + for (i = 1, seglen = 1; i < chanlen; i++, seglen++) { + // build part of chanlist + DEBUG(rt_printk("%d. %d %d\n", i, CR_CHAN(chanlist[i]), + CR_RANGE(chanlist[i])); + ) + if (chanlist[0] == chanlist[i]) + break; // we detect loop, this must by finish + nowmustbechan = + (CR_CHAN(chansegment[i - 1]) + 1) % chanlen; + if (nowmustbechan != CR_CHAN(chanlist[i])) { + // channel list isn't continous :-( + rt_printk + ("comedi%d: pcl816: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n", + dev->minor, i, CR_CHAN(chanlist[i]), + nowmustbechan, CR_CHAN(chanlist[0])); + return 0; + } + chansegment[i] = chanlist[i]; // well, this is next correct channel in list + } + + for (i = 0, segpos = 0; i < chanlen; i++) { // check whole chanlist + DEBUG(rt_printk("%d %d=%d %d\n", + CR_CHAN(chansegment[i % seglen]), + CR_RANGE(chansegment[i % seglen]), + CR_CHAN(chanlist[i]), + CR_RANGE(chanlist[i])); + ) + if (chanlist[i] != chansegment[i % seglen]) { + rt_printk + ("comedi%d: pcl816: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", + dev->minor, i, CR_CHAN(chansegment[i]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(chanlist[i % seglen]), + CR_RANGE(chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); + return 0; // chan/gain list is strange + } + } + } else { + seglen = 1; + } + + devpriv->ai_act_chanlist_len = seglen; + devpriv->ai_act_chanlist_pos = 0; + + for (i = 0; i < seglen; i++) { // store range list to card + devpriv->ai_act_chanlist[i] = CR_CHAN(chanlist[i]); + outb(CR_CHAN(chanlist[0]) & 0xf, dev->iobase + PCL816_MUX); + outb(CR_RANGE(chanlist[0]), dev->iobase + PCL816_RANGE); /* select gain */ + } + + comedi_udelay(1); + + outb(devpriv->ai_act_chanlist[0] | (devpriv->ai_act_chanlist[seglen - 1] << 4), dev->iobase + PCL816_MUX); /* select channel interval to scan */ + + return 1; // we can serve this with MUX logic +} + +#ifdef unused +/* +============================================================================== + Enable(1)/disable(0) periodic interrupts from RTC +*/ +static int set_rtc_irq_bit(unsigned char bit) +{ + unsigned char val; + unsigned long flags; + + if (bit == 1) { + RTC_timer_lock++; + if (RTC_timer_lock > 1) + return 0; + } else { + RTC_timer_lock--; + if (RTC_timer_lock < 0) + RTC_timer_lock = 0; + if (RTC_timer_lock > 0) + return 0; + } + + save_flags(flags); + cli(); + val = CMOS_READ(RTC_CONTROL); + if (bit) { + val |= RTC_PIE; + } else { + val &= ~RTC_PIE; + } + CMOS_WRITE(val, RTC_CONTROL); + CMOS_READ(RTC_INTR_FLAGS); + restore_flags(flags); + return 0; +} +#endif + +/* +============================================================================== + Free any resources that we have claimed +*/ +static void free_resources(struct comedi_device * dev) +{ + //rt_printk("free_resource()\n"); + if (dev->private) { + pcl816_ai_cancel(dev, devpriv->sub_ai); + pcl816_reset(dev); + if (devpriv->dma) + free_dma(devpriv->dma); + if (devpriv->dmabuf[0]) + free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); + if (devpriv->dmabuf[1]) + free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); +#ifdef unused + if (devpriv->rtc_irq) + comedi_free_irq(devpriv->rtc_irq, dev); + if ((devpriv->dma_rtc) && (RTC_lock == 1)) { + if (devpriv->rtc_iobase) + release_region(devpriv->rtc_iobase, + devpriv->rtc_iosize); + } +#endif + } + + if (dev->irq) + free_irq(dev->irq, dev); + if (dev->iobase) + release_region(dev->iobase, this_board->io_range); + //rt_printk("free_resource() end\n"); +} + +/* +============================================================================== + + Initialization + +*/ +static int pcl816_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + unsigned long iobase; + unsigned int irq, dma; + unsigned long pages; + //int i; + struct comedi_subdevice *s; + + /* claim our I/O space */ + iobase = it->options[0]; + printk("comedi%d: pcl816: board=%s, ioport=0x%03lx", dev->minor, + this_board->name, iobase); + + if (!request_region(iobase, this_board->io_range, "pcl816")) { + rt_printk("I/O port conflict\n"); + return -EIO; + } + + dev->iobase = iobase; + + if (pcl816_check(iobase)) { + rt_printk(", I cann't detect board. FAIL!\n"); + return -EIO; + } + + if ((ret = alloc_private(dev, sizeof(struct pcl816_private))) < 0) + return ret; /* Can't alloc mem */ + + /* set up some name stuff */ + dev->board_name = this_board->name; + + /* grab our IRQ */ + irq = 0; + if (this_board->IRQbits != 0) { /* board support IRQ */ + irq = it->options[1]; + if (irq) { /* we want to use IRQ */ + if (((1 << irq) & this_board->IRQbits) == 0) { + rt_printk + (", IRQ %u is out of allowed range, DISABLING IT", + irq); + irq = 0; /* Bad IRQ */ + } else { + if (comedi_request_irq(irq, interrupt_pcl816, 0, + "pcl816", dev)) { + rt_printk + (", unable to allocate IRQ %u, DISABLING IT", + irq); + irq = 0; /* Can't use IRQ */ + } else { + rt_printk(", irq=%u", irq); + } + } + } + } + + dev->irq = irq; + if (irq) { + devpriv->irq_free = 1; + } /* 1=we have allocated irq */ + else { + devpriv->irq_free = 0; + } + devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ + devpriv->int816_mode = 0; /* mode of irq */ + +#ifdef unused + /* grab RTC for DMA operations */ + devpriv->dma_rtc = 0; + if (it->options[2] > 0) { // we want to use DMA + if (RTC_lock == 0) { + if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, + "pcl816 (RTC)")) + goto no_rtc; + } + devpriv->rtc_iobase = RTC_PORT(0); + devpriv->rtc_iosize = RTC_IO_EXTENT; + RTC_lock++; +#ifdef UNTESTED_CODE + if (!comedi_request_irq(RTC_IRQ, + interrupt_pcl816_ai_mode13_dma_rtc, 0, + "pcl816 DMA (RTC)", dev)) { + devpriv->dma_rtc = 1; + devpriv->rtc_irq = RTC_IRQ; + rt_printk(", dma_irq=%u", devpriv->rtc_irq); + } else { + RTC_lock--; + if (RTC_lock == 0) { + if (devpriv->rtc_iobase) + release_region(devpriv->rtc_iobase, + devpriv->rtc_iosize); + } + devpriv->rtc_iobase = 0; + devpriv->rtc_iosize = 0; + } +#else + printk("pcl816: RTC code missing"); +#endif + + } + + no_rtc: +#endif + /* grab our DMA */ + dma = 0; + devpriv->dma = dma; + if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0)) + goto no_dma; /* if we haven't IRQ, we can't use DMA */ + + if (this_board->DMAbits != 0) { /* board support DMA */ + dma = it->options[2]; + if (dma < 1) + goto no_dma; /* DMA disabled */ + + if (((1 << dma) & this_board->DMAbits) == 0) { + rt_printk(", DMA is out of allowed range, FAIL!\n"); + return -EINVAL; /* Bad DMA */ + } + ret = request_dma(dma, "pcl816"); + if (ret) { + rt_printk(", unable to allocate DMA %u, FAIL!\n", dma); + return -EBUSY; /* DMA isn't free */ + } + + devpriv->dma = dma; + rt_printk(", dma=%u", dma); + pages = 2; /* we need 16KB */ + devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); + + if (!devpriv->dmabuf[0]) { + rt_printk(", unable to allocate DMA buffer, FAIL!\n"); + /* maybe experiment with try_to_free_pages() will help .... */ + return -EBUSY; /* no buffer :-( */ + } + devpriv->dmapages[0] = pages; + devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); + devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE; + //rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); + + if (devpriv->dma_rtc == 0) { // we must do duble buff :-( + devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); + if (!devpriv->dmabuf[1]) { + rt_printk + (", unable to allocate DMA buffer, FAIL!\n"); + return -EBUSY; + } + devpriv->dmapages[1] = pages; + devpriv->hwdmaptr[1] = + virt_to_bus((void *)devpriv->dmabuf[1]); + devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE; + } + } + + no_dma: + +/* if (this_board->n_aochan > 0) + subdevs[1] = COMEDI_SUBD_AO; + if (this_board->n_dichan > 0) + subdevs[2] = COMEDI_SUBD_DI; + if (this_board->n_dochan > 0) + subdevs[3] = COMEDI_SUBD_DO; +*/ + if ((ret = alloc_subdevices(dev, 1)) < 0) + return ret; + + s = dev->subdevices + 0; + if (this_board->n_aichan > 0) { + s->type = COMEDI_SUBD_AI; + devpriv->sub_ai = s; + dev->read_subdev = s; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = this_board->n_aichan; + s->subdev_flags |= SDF_DIFF; + //printk (", %dchans DIFF DAC - %d", s->n_chan, i); + s->maxdata = this_board->ai_maxdata; + s->len_chanlist = this_board->ai_chanlist; + s->range_table = this_board->ai_range_type; + s->cancel = pcl816_ai_cancel; + s->do_cmdtest = pcl816_ai_cmdtest; + s->do_cmd = pcl816_ai_cmd; + s->poll = pcl816_ai_poll; + s->insn_read = pcl816_ai_insn_read; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + +#if 0 +case COMEDI_SUBD_AO: + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = this_board->n_aochan; + s->maxdata = this_board->ao_maxdata; + s->len_chanlist = this_board->ao_chanlist; + s->range_table = this_board->ao_range_type; + break; + +case COMEDI_SUBD_DI: + s->subdev_flags = SDF_READABLE; + s->n_chan = this_board->n_dichan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dichan; + s->range_table = &range_digital; + break; + +case COMEDI_SUBD_DO: + s->subdev_flags = SDF_WRITABLE; + s->n_chan = this_board->n_dochan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dochan; + s->range_table = &range_digital; + break; +#endif + + pcl816_reset(dev); + + rt_printk("\n"); + + return 0; +} + +/* +============================================================================== + Removes device + */ +static int pcl816_detach(struct comedi_device * dev) +{ + DEBUG(rt_printk("comedi%d: pcl816: remove\n", dev->minor); + ) + free_resources(dev); +#ifdef unused + if (devpriv->dma_rtc) + RTC_lock--; +#endif + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c new file mode 100644 index 000000000000..43a9d56c6a43 --- /dev/null +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -0,0 +1,1988 @@ +/* + comedi/drivers/pcl818.c + + Author: Michal Dobes + + hardware driver for Advantech cards: + card: PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818, PCL-718 + driver: pcl818l, pcl818h, pcl818hd, pcl818hg, pcl818, pcl718 +*/ +/* +Driver: pcl818 +Description: Advantech PCL-818 cards, PCL-718 +Author: Michal Dobes +Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h), + PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818), + PCL-718 (pcl718) +Status: works + +All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO. +Differences are only at maximal sample speed, range list and FIFO +support. +The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support +only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0. +PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO +but this code is untested. +A word or two about DMA. Driver support DMA operations at two ways: +1) DMA uses two buffers and after one is filled then is generated + INT and DMA restart with second buffer. With this mode I'm unable run + more that 80Ksamples/secs without data dropouts on K6/233. +2) DMA uses one buffer and run in autoinit mode and the data are + from DMA buffer moved on the fly with 2kHz interrupts from RTC. + This mode is used if the interrupt 8 is available for allocation. + If not, then first DMA mode is used. With this I can run at + full speed one card (100ksamples/secs) or two cards with + 60ksamples/secs each (more is problem on account of ISA limitations). + To use this mode you must have compiled kernel with disabled + "Enhanced Real Time Clock Support". + Maybe you can have problems if you use xntpd or similar. + If you've data dropouts with DMA mode 2 then: + a) disable IDE DMA + b) switch text mode console to fb. + + Options for PCL-818L: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + [2] - DMA (0=disable, 1, 3) + [3] - 0, 10=10MHz clock for 8254 + 1= 1MHz clock for 8254 + [4] - 0, 5=A/D input -5V.. +5V + 1, 10=A/D input -10V..+10V + [5] - 0, 5=D/A output 0-5V (internal reference -5V) + 1, 10=D/A output 0-10V (internal reference -10V) + 2 =D/A output unknow (external reference) + + Options for PCL-818, PCL-818H: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + [2] - DMA (0=disable, 1, 3) + [3] - 0, 10=10MHz clock for 8254 + 1= 1MHz clock for 8254 + [4] - 0, 5=D/A output 0-5V (internal reference -5V) + 1, 10=D/A output 0-10V (internal reference -10V) + 2 =D/A output unknow (external reference) + + Options for PCL-818HD, PCL-818HG: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA, + 1=use DMA ch 1, 3=use DMA ch 3) + [3] - 0, 10=10MHz clock for 8254 + 1= 1MHz clock for 8254 + [4] - 0, 5=D/A output 0-5V (internal reference -5V) + 1, 10=D/A output 0-10V (internal reference -10V) + 2 =D/A output unknow (external reference) + + Options for PCL-718: + [0] - IO Base + [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + [2] - DMA (0=disable, 1, 3) + [3] - 0, 10=10MHz clock for 8254 + 1= 1MHz clock for 8254 + [4] - 0=A/D Range is +/-10V + 1= +/-5V + 2= +/-2.5V + 3= +/-1V + 4= +/-0.5V + 5= user defined bipolar + 6= 0-10V + 7= 0-5V + 8= 0-2V + 9= 0-1V + 10= user defined unipolar + [5] - 0, 5=D/A outputs 0-5V (internal reference -5V) + 1, 10=D/A outputs 0-10V (internal reference -10V) + 2=D/A outputs unknow (external reference) + [6] - 0, 60=max 60kHz A/D sampling + 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed) + +*/ + +#include "../comedidev.h" + +#include +#include +#include +#include + +#include "8253.h" + +// #define PCL818_MODE13_AO 1 + +// boards constants + +#define boardPCL818L 0 +#define boardPCL818H 1 +#define boardPCL818HD 2 +#define boardPCL818HG 3 +#define boardPCL818 4 +#define boardPCL718 5 + +// IO space len +#define PCLx1x_RANGE 16 +// IO space len if we use FIFO +#define PCLx1xFIFO_RANGE 32 + +// W: clear INT request +#define PCL818_CLRINT 8 +// R: return status byte +#define PCL818_STATUS 8 +// R: A/D high byte W: A/D range control +#define PCL818_RANGE 1 +// R: next mux scan channel W: mux scan channel & range control pointer +#define PCL818_MUX 2 +// R/W: operation control register +#define PCL818_CONTROL 9 +// W: counter enable +#define PCL818_CNTENABLE 10 + +// R: low byte of A/D W: soft A/D trigger +#define PCL818_AD_LO 0 +// R: high byte of A/D W: A/D range control +#define PCL818_AD_HI 1 +// W: D/A low&high byte +#define PCL818_DA_LO 4 +#define PCL818_DA_HI 5 +// R: low&high byte of DI +#define PCL818_DI_LO 3 +#define PCL818_DI_HI 11 +// W: low&high byte of DO +#define PCL818_DO_LO 3 +#define PCL818_DO_HI 11 +// W: PCL718 second D/A +#define PCL718_DA2_LO 6 +#define PCL718_DA2_HI 7 +// counters +#define PCL818_CTR0 12 +#define PCL818_CTR1 13 +#define PCL818_CTR2 14 +// W: counter control +#define PCL818_CTRCTL 15 + +// W: fifo enable/disable +#define PCL818_FI_ENABLE 6 +// W: fifo interrupt clear +#define PCL818_FI_INTCLR 20 +// W: fifo interrupt clear +#define PCL818_FI_FLUSH 25 +// R: fifo status +#define PCL818_FI_STATUS 25 +// R: one record from FIFO +#define PCL818_FI_DATALO 23 +#define PCL818_FI_DATAHI 23 + +// type of interrupt handler +#define INT_TYPE_AI1_INT 1 +#define INT_TYPE_AI1_DMA 2 +#define INT_TYPE_AI1_FIFO 3 +#define INT_TYPE_AI3_INT 4 +#define INT_TYPE_AI3_DMA 5 +#define INT_TYPE_AI3_FIFO 6 +#ifdef PCL818_MODE13_AO +#define INT_TYPE_AO1_INT 7 +#define INT_TYPE_AO3_INT 8 +#endif + +#ifdef unused +// RTC stuff... +#define INT_TYPE_AI1_DMA_RTC 9 +#define INT_TYPE_AI3_DMA_RTC 10 + +#define RTC_IRQ 8 +#define RTC_IO_EXTENT 0x10 +#endif + +#define MAGIC_DMA_WORD 0x5a5a + +static const struct comedi_lrange range_pcl818h_ai = { 9, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + BIP_RANGE(10), + } +}; + +static const struct comedi_lrange range_pcl818hg_ai = { 10, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.005), + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01), + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.01), + } +}; + +static const struct comedi_lrange range_pcl818l_l_ai = { 4, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + } +}; + +static const struct comedi_lrange range_pcl818l_h_ai = { 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + } +}; + +static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} }; +static const struct comedi_lrange range718_bipolar0_5 = { 1, {BIP_RANGE(0.5),} }; +static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} }; +static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} }; + +static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcl818_detach(struct comedi_device * dev); + +#ifdef unused +static int RTC_lock = 0; /* RTC lock */ +static int RTC_timer_lock = 0; /* RTC int lock */ +#endif + +struct pcl818_board { + + const char *name; // driver name + int n_ranges; // len of range list + int n_aichan_se; // num of A/D chans in single ended mode + int n_aichan_diff; // num of A/D chans in diferencial mode + unsigned int ns_min; // minimal alllowed delay between samples (in ns) + int n_aochan; // num of D/A chans + int n_dichan; // num of DI chans + int n_dochan; // num of DO chans + const struct comedi_lrange *ai_range_type; // default A/D rangelist + const struct comedi_lrange *ao_range_type; // default D/A rangelist + unsigned int io_range; // len of IO space + unsigned int IRQbits; // allowed interrupts + unsigned int DMAbits; // allowed DMA chans + int ai_maxdata; // maxdata for A/D + int ao_maxdata; // maxdata for D/A + unsigned char fifo; // 1=board has FIFO + int is_818; +}; + + +static const struct pcl818_board boardtypes[] = { + {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai, + &range_unipolar5, PCLx1x_RANGE, 0x00fc, + 0x0a, 0xfff, 0xfff, 0, 1}, + {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai, + &range_unipolar5, PCLx1x_RANGE, 0x00fc, + 0x0a, 0xfff, 0xfff, 0, 1}, + {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai, + &range_unipolar5, PCLx1x_RANGE, 0x00fc, + 0x0a, 0xfff, 0xfff, 1, 1}, + {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai, + &range_unipolar5, PCLx1x_RANGE, 0x00fc, + 0x0a, 0xfff, 0xfff, 1, 1}, + {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai, + &range_unipolar5, PCLx1x_RANGE, 0x00fc, + 0x0a, 0xfff, 0xfff, 0, 1}, + {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5, + &range_unipolar5, PCLx1x_RANGE, 0x00fc, + 0x0a, 0xfff, 0xfff, 0, 0}, + /* pcm3718 */ + {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai, + &range_unipolar5, PCLx1x_RANGE, 0x00fc, + 0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ }, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl818_board)) + +static struct comedi_driver driver_pcl818 = { + driver_name:"pcl818", + module:THIS_MODULE, + attach:pcl818_attach, + detach:pcl818_detach, + board_name:&boardtypes[0].name, + num_names:n_boardtypes, + offset:sizeof(struct pcl818_board), +}; + +COMEDI_INITCLEANUP(driver_pcl818); + +struct pcl818_private { + + unsigned int dma; // used DMA, 0=don't use DMA + int dma_rtc; // 1=RTC used with DMA, 0=no RTC alloc + unsigned int io_range; +#ifdef unused + unsigned long rtc_iobase; // RTC port region + unsigned int rtc_iosize; + unsigned int rtc_irq; + struct timer_list rtc_irq_timer; // timer for RTC sanity check + unsigned long rtc_freq; // RTC int freq + int rtc_irq_blocked; // 1=we now do AI with DMA&RTC +#endif + unsigned long dmabuf[2]; // pointers to begin of DMA buffers + unsigned int dmapages[2]; // len of DMA buffers in PAGE_SIZEs + unsigned int hwdmaptr[2]; // hardware address of DMA buffers + unsigned int hwdmasize[2]; // len of DMA buffers in Bytes + unsigned int dmasamplsize; // size in samples hwdmasize[0]/2 + unsigned int last_top_dma; // DMA pointer in last RTC int + int next_dma_buf; // which DMA buffer will be used next round + long dma_runs_to_end; // how many we must permorm DMA transfer to end of record + unsigned long last_dma_run; // how many bytes we must transfer on last DMA page + unsigned char neverending_ai; // if=1, then we do neverending record (you must use cancel()) + unsigned int ns_min; // manimal alllowed delay between samples (in us) for actual card + int i8253_osc_base; // 1/frequency of on board oscilator in ns + int irq_free; // 1=have allocated IRQ + int irq_blocked; // 1=IRQ now uses any subdev + int irq_was_now_closed; // when IRQ finish, there's stored int818_mode for last interrupt + int ai_mode; // who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma + struct comedi_subdevice *last_int_sub; // ptr to subdevice which now finish + int ai_act_scan; // how many scans we finished + int ai_act_chan; // actual position in actual scan + unsigned int act_chanlist[16]; // MUX setting for actual AI operations + unsigned int act_chanlist_len; // how long is actual MUX list + unsigned int act_chanlist_pos; // actual position in MUX list + unsigned int ai_scans; // len of scanlist + unsigned int ai_n_chan; // how many channels is measured + unsigned int *ai_chanlist; // actaul chanlist + unsigned int ai_flags; // flaglist + unsigned int ai_data_len; // len of data buffer + short *ai_data; // data buffer + unsigned int ai_timer1; // timers + unsigned int ai_timer2; + struct comedi_subdevice *sub_ai; // ptr to AI subdevice + unsigned char usefifo; // 1=use fifo + unsigned int ao_readback[2]; +}; + + +static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // used for gain list programming + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff +}; + +#define devpriv ((struct pcl818_private *)dev->private) +#define this_board ((const struct pcl818_board *)dev->board_ptr) + +/* +============================================================================== +*/ +static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int *chanlist, unsigned int n_chan, unsigned int seglen); +static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int *chanlist, unsigned int n_chan); + +static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2); + +#ifdef unused +static int set_rtc_irq_bit(unsigned char bit); +static void rtc_dropped_irq(unsigned long data); +static int rtc_setfreq_irq(int freq); +#endif + +/* +============================================================================== + ANALOG INPUT MODE0, 818 cards, slow version +*/ +static int pcl818_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int timeout; + + /* software trigger, DMA and INT off */ + outb(0, dev->iobase + PCL818_CONTROL); + + /* select channel */ + outb(muxonechan[CR_CHAN(insn->chanspec)], dev->iobase + PCL818_MUX); + + /* select gain */ + outb(CR_RANGE(insn->chanspec), dev->iobase + PCL818_RANGE); + + for (n = 0; n < insn->n; n++) { + + /* clear INT (conversion end) flag */ + outb(0, dev->iobase + PCL818_CLRINT); + + /* start conversion */ + outb(0, dev->iobase + PCL818_AD_LO); + + timeout = 100; + while (timeout--) { + if (inb(dev->iobase + PCL818_STATUS) & 0x10) + goto conv_finish; + comedi_udelay(1); + } + comedi_error(dev, "A/D insn timeout"); + /* clear INT (conversion end) flag */ + outb(0, dev->iobase + PCL818_CLRINT); + return -EIO; + + conv_finish: + data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) | + (inb(dev->iobase + PCL818_AD_LO) >> 4)); + } + + return n; +} + +/* +============================================================================== + ANALOG OUTPUT MODE0, 818 cards + only one sample per call is supported +*/ +static int pcl818_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { + data[n] = devpriv->ao_readback[chan]; + } + + return n; +} + +static int pcl818_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { + devpriv->ao_readback[chan] = data[n]; + outb((data[n] & 0x000f) << 4, dev->iobase + + (chan) ? PCL718_DA2_LO : PCL818_DA_LO); + outb((data[n] & 0x0ff0) >> 4, dev->iobase + + (chan) ? PCL718_DA2_HI : PCL818_DA_HI); + } + + return n; +} + +/* +============================================================================== + DIGITAL INPUT MODE0, 818 cards + + only one sample per call is supported +*/ +static int pcl818_di_insn_bits(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 + PCL818_DI_LO) | + (inb(dev->iobase + PCL818_DI_HI) << 8); + + return 2; +} + +/* +============================================================================== + DIGITAL OUTPUT MODE0, 818 cards + + only one sample per call is supported +*/ +static int pcl818_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + s->state &= ~data[0]; + s->state |= (data[0] & data[1]); + + outb(s->state & 0xff, dev->iobase + PCL818_DO_LO); + outb((s->state >> 8), dev->iobase + PCL818_DO_HI); + + data[1] = s->state; + + return 2; +} + +/* +============================================================================== + analog input interrupt mode 1 & 3, 818 cards + one sample per interrupt version +*/ +static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + int low; + int timeout = 50; /* wait max 50us */ + + while (timeout--) { + if (inb(dev->iobase + PCL818_STATUS) & 0x10) + goto conv_finish; + comedi_udelay(1); + } + outb(0, dev->iobase + PCL818_STATUS); /* clear INT request */ + comedi_error(dev, "A/D mode1/3 IRQ without DRDY!"); + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + + conv_finish: + low = inb(dev->iobase + PCL818_AD_LO); + comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4))); // get one sample + outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ + + if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { // dropout! + rt_printk + ("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n", + (low & 0xf), + devpriv->act_chanlist[devpriv->act_chanlist_pos]); + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + } + if (s->async->cur_chan == 0) { + // rt_printk("E"); + devpriv->ai_act_scan--; + } + + if (!devpriv->neverending_ai) { + if (devpriv->ai_act_scan == 0) { /* all data sampled */ + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + } + } + comedi_event(dev, s); + return IRQ_HANDLED; +} + +/* +============================================================================== + analog input dma mode 1 & 3, 818 cards +*/ +static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + int i, len, bufptr; + unsigned long flags; + short *ptr; + + disable_dma(devpriv->dma); + devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; + if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) { // switch dma bufs + set_dma_mode(devpriv->dma, DMA_MODE_READ); + flags = claim_dma_lock(); + set_dma_addr(devpriv->dma, + devpriv->hwdmaptr[devpriv->next_dma_buf]); + if (devpriv->dma_runs_to_end || devpriv->neverending_ai) { + set_dma_count(devpriv->dma, + devpriv->hwdmasize[devpriv->next_dma_buf]); + } else { + set_dma_count(devpriv->dma, devpriv->last_dma_run); + } + release_dma_lock(flags); + enable_dma(devpriv->dma); + } + rt_printk("comedi: A/D mode1/3 IRQ \n"); + + devpriv->dma_runs_to_end--; + outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ + ptr = (short *) devpriv->dmabuf[1 - devpriv->next_dma_buf]; + + len = devpriv->hwdmasize[0] >> 1; + bufptr = 0; + + for (i = 0; i < len; i++) { + if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { // dropout! + rt_printk + ("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n", + (ptr[bufptr] & 0xf), + devpriv->act_chanlist[devpriv-> + act_chanlist_pos], + devpriv->act_chanlist_pos); + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + } + + comedi_buf_put(s->async, ptr[bufptr++] >> 4); // get one sample + + devpriv->act_chanlist_pos++; + if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) { + devpriv->ai_act_scan--; + devpriv->act_chanlist_pos = 0; + } + + if (!devpriv->neverending_ai) + if (devpriv->ai_act_scan == 0) { /* all data sampled */ + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + // printk("done int ai13 dma\n"); + return IRQ_HANDLED; + } + } + + if (len > 0) + comedi_event(dev, s); + return IRQ_HANDLED; +} + +#ifdef unused +/* +============================================================================== + analog input dma mode 1 & 3 over RTC, 818 cards +*/ +static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + unsigned long tmp; + unsigned int top1, top2, i, bufptr; + long ofs_dats; + short *dmabuf = (short *) devpriv->dmabuf[0]; + + //outb(2,0x378); + switch (devpriv->ai_mode) { + case INT_TYPE_AI1_DMA_RTC: + case INT_TYPE_AI3_DMA_RTC: + tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); + mod_timer(&devpriv->rtc_irq_timer, + jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100); + + for (i = 0; i < 10; i++) { + top1 = get_dma_residue(devpriv->dma); + top2 = get_dma_residue(devpriv->dma); + if (top1 == top2) + break; + } + + if (top1 != top2) + return IRQ_HANDLED; + top1 = devpriv->hwdmasize[0] - top1; // where is now DMA in buffer + top1 >>= 1; + ofs_dats = top1 - devpriv->last_top_dma; // new samples from last call + if (ofs_dats < 0) + ofs_dats = (devpriv->dmasamplsize) + ofs_dats; + if (!ofs_dats) + return IRQ_HANDLED; // exit=no new samples from last call + // obsluz data + i = devpriv->last_top_dma - 1; + i &= (devpriv->dmasamplsize - 1); + + if (dmabuf[i] != MAGIC_DMA_WORD) { // DMA overflow! + comedi_error(dev, "A/D mode1/3 DMA buffer overflow!"); + //rt_printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + } + //rt_printk("r %ld ",ofs_dats); + + bufptr = devpriv->last_top_dma; + + for (i = 0; i < ofs_dats; i++) { + if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { // dropout! + rt_printk + ("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n", + (dmabuf[bufptr] & 0xf), + devpriv->act_chanlist[devpriv-> + act_chanlist_pos]); + pcl818_ai_cancel(dev, s); + s->async->events |= + COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + } + + comedi_buf_put(s->async, dmabuf[bufptr++] >> 4); // get one sample + bufptr &= (devpriv->dmasamplsize - 1); + + if (s->async->cur_chan == 0) { + devpriv->ai_act_scan--; + } + + if (!devpriv->neverending_ai) + if (devpriv->ai_act_scan == 0) { /* all data sampled */ + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + //printk("done int ai13 dma\n"); + return IRQ_HANDLED; + } + } + + devpriv->last_top_dma = bufptr; + bufptr--; + bufptr &= (devpriv->dmasamplsize - 1); + dmabuf[bufptr] = MAGIC_DMA_WORD; + comedi_event(dev, s); + //outb(0,0x378); + return IRQ_HANDLED; + } + + //outb(0,0x378); + return IRQ_HANDLED; +} +#endif + +/* +============================================================================== + analog input interrupt mode 1 & 3, 818HD/HG cards +*/ +static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->subdevices + 0; + int i, len, lo; + + outb(0, dev->iobase + PCL818_FI_INTCLR); // clear fifo int request + + lo = inb(dev->iobase + PCL818_FI_STATUS); + + if (lo & 4) { + comedi_error(dev, "A/D mode1/3 FIFO overflow!"); + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + } + + if (lo & 1) { + comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!"); + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + } + + if (lo & 2) { + len = 512; + } else { + len = 0; + } + + for (i = 0; i < len; i++) { + lo = inb(dev->iobase + PCL818_FI_DATALO); + if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { // dropout! + rt_printk + ("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n", + (lo & 0xf), + devpriv->act_chanlist[devpriv-> + act_chanlist_pos]); + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return IRQ_HANDLED; + } + + comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4)); // get one sample + + if (s->async->cur_chan == 0) { + devpriv->ai_act_scan--; + } + + if (!devpriv->neverending_ai) + if (devpriv->ai_act_scan == 0) { /* all data sampled */ + pcl818_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + return IRQ_HANDLED; + } + } + + if (len > 0) + comedi_event(dev, s); + return IRQ_HANDLED; +} + +/* +============================================================================== + INT procedure +*/ +static irqreturn_t interrupt_pcl818(int irq, void *d PT_REGS_ARG) +{ + struct comedi_device *dev = d; + + if (!dev->attached) { + comedi_error(dev, "premature interrupt"); + return IRQ_HANDLED; + } + //rt_printk("I\n"); + + switch (devpriv->ai_mode) { + case INT_TYPE_AI1_DMA: + case INT_TYPE_AI3_DMA: + return interrupt_pcl818_ai_mode13_dma(irq, d); + case INT_TYPE_AI1_INT: + case INT_TYPE_AI3_INT: + return interrupt_pcl818_ai_mode13_int(irq, d); + case INT_TYPE_AI1_FIFO: + case INT_TYPE_AI3_FIFO: + return interrupt_pcl818_ai_mode13_fifo(irq, d); +#ifdef PCL818_MODE13_AO + case INT_TYPE_AO1_INT: + case INT_TYPE_AO3_INT: + return interrupt_pcl818_ao_mode13_int(irq, d); +#endif + default: + break; + } + + outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ + + if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked) + || (!devpriv->ai_mode)) { + if (devpriv->irq_was_now_closed) { + if (devpriv->neverending_ai && + (devpriv->ai_mode == INT_TYPE_AI1_DMA + || devpriv->ai_mode == + INT_TYPE_AI3_DMA)) { + /* we had neverending ai but ai_cancel() has been called + the cleanup from ai_cancel() has been delayed until know + because the card doesn't seem to like being reprogrammed + while a DMA transfer is in progress + */ + struct comedi_subdevice *s = dev->subdevices + 0; + devpriv->ai_mode = devpriv->irq_was_now_closed; + devpriv->irq_was_now_closed = 0; + devpriv->neverending_ai = 0; + pcl818_ai_cancel(dev, s); + } + devpriv->irq_was_now_closed = 0; + return IRQ_HANDLED; + } + comedi_error(dev, "bad IRQ!"); + return IRQ_NONE; + } + + comedi_error(dev, "IRQ from unknow source!"); + return IRQ_NONE; +} + +/* +============================================================================== + ANALOG INPUT MODE 1 or 3 DMA , 818 cards +*/ +static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev, + struct comedi_subdevice * s) +{ + unsigned int flags; + unsigned int bytes; + + rt_printk("mode13dma_int, mode: %d\n", mode); + disable_dma(devpriv->dma); // disable dma + bytes = devpriv->hwdmasize[0]; + if (!devpriv->neverending_ai) { + bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); // how many + devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0]; // how many DMA pages we must fiil + devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; //on last dma transfer must be moved + devpriv->dma_runs_to_end--; + if (devpriv->dma_runs_to_end >= 0) + bytes = devpriv->hwdmasize[0]; + } + + devpriv->next_dma_buf = 0; + set_dma_mode(devpriv->dma, DMA_MODE_READ); + flags = claim_dma_lock(); + clear_dma_ff(devpriv->dma); + set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); + set_dma_count(devpriv->dma, bytes); + release_dma_lock(flags); + enable_dma(devpriv->dma); + + if (mode == 1) { + devpriv->ai_mode = INT_TYPE_AI1_DMA; + outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ+DMA */ + } else { + devpriv->ai_mode = INT_TYPE_AI3_DMA; + outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ+DMA */ + }; +} + +#ifdef unused +/* +============================================================================== + ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards +*/ +static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev, + struct comedi_subdevice * s) +{ + unsigned int flags; + short *pole; + + set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT); + flags = claim_dma_lock(); + clear_dma_ff(devpriv->dma); + set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); + set_dma_count(devpriv->dma, devpriv->hwdmasize[0]); + release_dma_lock(flags); + enable_dma(devpriv->dma); + devpriv->last_top_dma = 0; //devpriv->hwdmasize[0]; + pole = (short *) devpriv->dmabuf[0]; + devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2; + pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD; +#ifdef unused + devpriv->rtc_freq = rtc_setfreq_irq(2048); + devpriv->rtc_irq_timer.expires = + jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100; + devpriv->rtc_irq_timer.data = (unsigned long)dev; + devpriv->rtc_irq_timer.function = rtc_dropped_irq; + + add_timer(&devpriv->rtc_irq_timer); +#endif + + if (mode == 1) { + devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC; + outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+DMA */ + } else { + devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC; + outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+DMA */ + }; +} +#endif + +/* +============================================================================== + ANALOG INPUT MODE 1 or 3, 818 cards +*/ +static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev, + struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + int divisor1, divisor2; + unsigned int seglen; + + rt_printk("pcl818_ai_cmd_mode()\n"); + if ((!dev->irq) && (!devpriv->dma_rtc)) { + comedi_error(dev, "IRQ not defined!"); + return -EINVAL; + } + + if (devpriv->irq_blocked) + return -EBUSY; + + start_pacer(dev, -1, 0, 0); // stop pacer + + seglen = check_channel_list(dev, s, devpriv->ai_chanlist, + devpriv->ai_n_chan); + if (seglen < 1) + return -EINVAL; + setup_channel_list(dev, s, devpriv->ai_chanlist, + devpriv->ai_n_chan, seglen); + + comedi_udelay(1); + + devpriv->ai_act_scan = devpriv->ai_scans; + devpriv->ai_act_chan = 0; + devpriv->irq_blocked = 1; + devpriv->irq_was_now_closed = 0; + devpriv->neverending_ai = 0; + devpriv->act_chanlist_pos = 0; + devpriv->dma_runs_to_end = 0; + + if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1)) + devpriv->neverending_ai = 1; //well, user want neverending + + if (mode == 1) { + i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, + &divisor2, &cmd->convert_arg, TRIG_ROUND_NEAREST); + if (divisor1 == 1) { /* PCL718/818 crash if any divisor is set to 1 */ + divisor1 = 2; + divisor2 /= 2; + } + if (divisor2 == 1) { + divisor2 = 2; + divisor1 /= 2; + } + } + + outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */ + + switch (devpriv->dma) { + case 1: // DMA + case 3: + if (devpriv->dma_rtc == 0) { + pcl818_ai_mode13dma_int(mode, dev, s); + } +#ifdef unused + else { + pcl818_ai_mode13dma_rtc(mode, dev, s); + } +#else + else { + return -EINVAL; + } +#endif + break; + case 0: // IRQ + // rt_printk("IRQ\n"); + if (mode == 1) { + devpriv->ai_mode = INT_TYPE_AI1_INT; + outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ */ + } else { + devpriv->ai_mode = INT_TYPE_AI3_INT; + outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ */ + }; + break; + case -1: // FIFO + outb(1, dev->iobase + PCL818_FI_ENABLE); // enable FIFO + if (mode == 1) { + devpriv->ai_mode = INT_TYPE_AI1_FIFO; + outb(0x03, dev->iobase + PCL818_CONTROL); /* Pacer */ + } else { + devpriv->ai_mode = INT_TYPE_AI3_FIFO; + outb(0x02, dev->iobase + PCL818_CONTROL); + }; /* Ext trig */ + break; + } + + start_pacer(dev, mode, divisor1, divisor2); + +#ifdef unused + switch (devpriv->ai_mode) { + case INT_TYPE_AI1_DMA_RTC: + case INT_TYPE_AI3_DMA_RTC: + set_rtc_irq_bit(1); /* start RTC */ + break; + } +#endif + rt_printk("pcl818_ai_cmd_mode() end\n"); + return 0; +} + +#ifdef unused +/* +============================================================================== + ANALOG OUTPUT MODE 1 or 3, 818 cards +*/ +#ifdef PCL818_MODE13_AO +static int pcl818_ao_mode13(int mode, struct comedi_device * dev, struct comedi_subdevice * s, + comedi_trig * it) +{ + int divisor1, divisor2; + + if (!dev->irq) { + comedi_error(dev, "IRQ not defined!"); + return -EINVAL; + } + + if (devpriv->irq_blocked) + return -EBUSY; + + start_pacer(dev, -1, 0, 0); // stop pacer + + devpriv->int13_act_scan = it->n; + devpriv->int13_act_chan = 0; + devpriv->irq_blocked = 1; + devpriv->irq_was_now_closed = 0; + devpriv->neverending_ai = 0; + devpriv->act_chanlist_pos = 0; + + if (mode == 1) { + i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, + &divisor2, &it->trigvar, TRIG_ROUND_NEAREST); + if (divisor1 == 1) { /* PCL818 crash if any divisor is set to 1 */ + divisor1 = 2; + divisor2 /= 2; + } + if (divisor2 == 1) { + divisor2 = 2; + divisor1 /= 2; + } + } + + outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */ + if (mode == 1) { + devpriv->int818_mode = INT_TYPE_AO1_INT; + outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ */ + } else { + devpriv->int818_mode = INT_TYPE_AO3_INT; + outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ */ + }; + + start_pacer(dev, mode, divisor1, divisor2); + + return 0; +} + +/* +============================================================================== + ANALOG OUTPUT MODE 1, 818 cards +*/ +static int pcl818_ao_mode1(struct comedi_device * dev, struct comedi_subdevice * s, + comedi_trig * it) +{ + return pcl818_ao_mode13(1, dev, s, it); +} + +/* +============================================================================== + ANALOG OUTPUT MODE 3, 818 cards +*/ +static int pcl818_ao_mode3(struct comedi_device * dev, struct comedi_subdevice * s, + comedi_trig * it) +{ + return pcl818_ao_mode13(3, dev, s, it); +} +#endif +#endif + +/* +============================================================================== + Start/stop pacer onboard pacer +*/ +static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1, + unsigned int divisor2) +{ + outb(0xb4, dev->iobase + PCL818_CTRCTL); + outb(0x74, dev->iobase + PCL818_CTRCTL); + comedi_udelay(1); + + if (mode == 1) { + outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2); + outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2); + outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1); + outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1); + } +} + +/* +============================================================================== + Check if channel list from user is builded correctly + If it's ok, then program scan/gain logic +*/ +static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int *chanlist, unsigned int n_chan) +{ + unsigned int chansegment[16]; + unsigned int i, nowmustbechan, seglen, segpos; + + /* correct channel and range number check itself comedi/range.c */ + if (n_chan < 1) { + comedi_error(dev, "range/channel list is empty!"); + return 0; + } + + if (n_chan > 1) { + // first channel is everytime ok + chansegment[0] = chanlist[0]; + // build part of chanlist + for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { + // rt_printk("%d. %d %d\n",i,CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i])); + // we detect loop, this must by finish + if (chanlist[0] == chanlist[i]) + break; + nowmustbechan = + (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; + if (nowmustbechan != CR_CHAN(chanlist[i])) { // channel list isn't continous :-( + rt_printk + ("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n", + dev->minor, i, CR_CHAN(chanlist[i]), + nowmustbechan, CR_CHAN(chanlist[0])); + return 0; + } + // well, this is next correct channel in list + chansegment[i] = chanlist[i]; + } + + // check whole chanlist + for (i = 0, segpos = 0; i < n_chan; i++) { + //rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i])); + if (chanlist[i] != chansegment[i % seglen]) { + rt_printk + ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", + dev->minor, i, CR_CHAN(chansegment[i]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(chanlist[i % seglen]), + CR_RANGE(chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); + return 0; // chan/gain list is strange + } + } + } else { + seglen = 1; + } + rt_printk("check_channel_list: seglen %d\n", seglen); + return seglen; +} + +static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int *chanlist, unsigned int n_chan, unsigned int seglen) +{ + int i; + + devpriv->act_chanlist_len = seglen; + devpriv->act_chanlist_pos = 0; + + for (i = 0; i < seglen; i++) { // store range list to card + devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); + outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX); /* select channel */ + outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE); /* select gain */ + } + + comedi_udelay(1); + + /* select channel interval to scan */ + outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen - + 1] << 4), dev->iobase + PCL818_MUX); +} + +/* +============================================================================== + Check if board is switched to SE (1) or DIFF(0) mode +*/ +static int check_single_ended(unsigned int port) +{ + if (inb(port + PCL818_STATUS) & 0x20) { + return 1; + } else { + return 0; + } +} + +/* +============================================================================== +*/ +static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp, divisor1, divisor2; + + /* step 1: make sure trigger sources are trivially valid */ + + 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_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) { + return 1; + } + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + if (cmd->start_src != TRIG_NOW) { + cmd->start_src = TRIG_NOW; + err++; + } + if (cmd->scan_begin_src != TRIG_FOLLOW) { + cmd->scan_begin_src = TRIG_FOLLOW; + err++; + } + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + + if (cmd->scan_end_src != TRIG_COUNT) { + cmd->scan_end_src = TRIG_COUNT; + err++; + } + + if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) + err++; + + if (err) { + return 2; + } + + /* step 3: make sure arguments are trivially compatible */ + + 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_src == TRIG_TIMER) { + if (cmd->convert_arg < this_board->ns_min) { + cmd->convert_arg = this_board->ns_min; + err++; + } + } else { /* TRIG_EXT */ + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + } + + if (!cmd->chanlist_len) { + cmd->chanlist_len = 1; + err++; + } + if (cmd->chanlist_len > s->n_chan) { + cmd->chanlist_len = s->n_chan; + err++; + } + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (!cmd->stop_arg) { + cmd->stop_arg = 1; + err++; + } + } else { /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) { + return 3; + } + + /* step 4: fix up any arguments */ + + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, + &divisor2, &cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (cmd->convert_arg < this_board->ns_min) + cmd->convert_arg = this_board->ns_min; + if (tmp != cmd->convert_arg) + err++; + } + + if (err) { + return 4; + } + + /* step 5: complain about special chanlist considerations */ + + if (cmd->chanlist) { + if (!check_channel_list(dev, s, cmd->chanlist, + cmd->chanlist_len)) + return 5; // incorrect channels list + } + + return 0; +} + +/* +============================================================================== +*/ +static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + int retval; + + rt_printk("pcl818_ai_cmd()\n"); + devpriv->ai_n_chan = cmd->chanlist_len; + devpriv->ai_chanlist = cmd->chanlist; + devpriv->ai_flags = cmd->flags; + devpriv->ai_data_len = s->async->prealloc_bufsz; + devpriv->ai_data = s->async->prealloc_buf; + devpriv->ai_timer1 = 0; + devpriv->ai_timer2 = 0; + + if (cmd->stop_src == TRIG_COUNT) { + devpriv->ai_scans = cmd->stop_arg; + } else { + devpriv->ai_scans = 0; + } + + if (cmd->scan_begin_src == TRIG_FOLLOW) { // mode 1, 3 + if (cmd->convert_src == TRIG_TIMER) { // mode 1 + devpriv->ai_timer1 = cmd->convert_arg; + retval = pcl818_ai_cmd_mode(1, dev, s); + rt_printk("pcl818_ai_cmd() end\n"); + return retval; + } + if (cmd->convert_src == TRIG_EXT) { // mode 3 + return pcl818_ai_cmd_mode(3, dev, s); + } + } + + return -1; +} + +/* +============================================================================== + cancel any mode 1-4 AI +*/ +static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + if (devpriv->irq_blocked > 0) { + rt_printk("pcl818_ai_cancel()\n"); + devpriv->irq_was_now_closed = devpriv->ai_mode; + devpriv->ai_mode = 0; + + switch (devpriv->irq_was_now_closed) { +#ifdef unused + case INT_TYPE_AI1_DMA_RTC: + case INT_TYPE_AI3_DMA_RTC: + set_rtc_irq_bit(0); // stop RTC + del_timer(&devpriv->rtc_irq_timer); +#endif + case INT_TYPE_AI1_DMA: + case INT_TYPE_AI3_DMA: + if (devpriv->neverending_ai) { + /* wait for running dma transfer to end, do cleanup in interrupt */ + goto end; + } + disable_dma(devpriv->dma); + case INT_TYPE_AI1_INT: + case INT_TYPE_AI3_INT: + case INT_TYPE_AI1_FIFO: + case INT_TYPE_AI3_FIFO: +#ifdef PCL818_MODE13_AO + case INT_TYPE_AO1_INT: + case INT_TYPE_AO3_INT: +#endif + outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL); /* Stop A/D */ + comedi_udelay(1); + start_pacer(dev, -1, 0, 0); + outb(0, dev->iobase + PCL818_AD_LO); + inb(dev->iobase + PCL818_AD_LO); + inb(dev->iobase + PCL818_AD_HI); + outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ + outb(0, dev->iobase + PCL818_CONTROL); /* Stop A/D */ + if (devpriv->usefifo) { // FIFO shutdown + outb(0, dev->iobase + PCL818_FI_INTCLR); + outb(0, dev->iobase + PCL818_FI_FLUSH); + outb(0, dev->iobase + PCL818_FI_ENABLE); + } + devpriv->irq_blocked = 0; + devpriv->last_int_sub = s; + devpriv->neverending_ai = 0; + break; + } + } + + end: + rt_printk("pcl818_ai_cancel() end\n"); + return 0; +} + +/* +============================================================================== + chech for PCL818 +*/ +static int pcl818_check(unsigned long iobase) +{ + outb(0x00, iobase + PCL818_MUX); + comedi_udelay(1); + if (inb(iobase + PCL818_MUX) != 0x00) + return 1; //there isn't card + outb(0x55, iobase + PCL818_MUX); + comedi_udelay(1); + if (inb(iobase + PCL818_MUX) != 0x55) + return 1; //there isn't card + outb(0x00, iobase + PCL818_MUX); + comedi_udelay(1); + outb(0x18, iobase + PCL818_CONTROL); + comedi_udelay(1); + if (inb(iobase + PCL818_CONTROL) != 0x18) + return 1; //there isn't card + return 0; // ok, card exist +} + +/* +============================================================================== + reset whole PCL-818 cards +*/ +static void pcl818_reset(struct comedi_device * dev) +{ + if (devpriv->usefifo) { // FIFO shutdown + outb(0, dev->iobase + PCL818_FI_INTCLR); + outb(0, dev->iobase + PCL818_FI_FLUSH); + outb(0, dev->iobase + PCL818_FI_ENABLE); + } + outb(0, dev->iobase + PCL818_DA_LO); // DAC=0V + outb(0, dev->iobase + PCL818_DA_HI); + comedi_udelay(1); + outb(0, dev->iobase + PCL818_DO_HI); // DO=$0000 + outb(0, dev->iobase + PCL818_DO_LO); + comedi_udelay(1); + outb(0, dev->iobase + PCL818_CONTROL); + outb(0, dev->iobase + PCL818_CNTENABLE); + outb(0, dev->iobase + PCL818_MUX); + outb(0, dev->iobase + PCL818_CLRINT); + outb(0xb0, dev->iobase + PCL818_CTRCTL); /* Stop pacer */ + outb(0x70, dev->iobase + PCL818_CTRCTL); + outb(0x30, dev->iobase + PCL818_CTRCTL); + if (this_board->is_818) { + outb(0, dev->iobase + PCL818_RANGE); + } else { + outb(0, dev->iobase + PCL718_DA2_LO); + outb(0, dev->iobase + PCL718_DA2_HI); + } +} + +#ifdef unused +/* +============================================================================== + Enable(1)/disable(0) periodic interrupts from RTC +*/ +static int set_rtc_irq_bit(unsigned char bit) +{ + unsigned char val; + unsigned long flags; + + if (bit == 1) { + RTC_timer_lock++; + if (RTC_timer_lock > 1) + return 0; + } else { + RTC_timer_lock--; + if (RTC_timer_lock < 0) + RTC_timer_lock = 0; + if (RTC_timer_lock > 0) + return 0; + } + + save_flags(flags); + cli(); + val = CMOS_READ(RTC_CONTROL); + if (bit) { + val |= RTC_PIE; + } else { + val &= ~RTC_PIE; + } + CMOS_WRITE(val, RTC_CONTROL); + CMOS_READ(RTC_INTR_FLAGS); + restore_flags(flags); + return 0; +} + +/* +============================================================================== + Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers) +*/ +static void rtc_dropped_irq(unsigned long data) +{ + struct comedi_device *dev = (void *)data; + unsigned long flags, tmp; + + switch (devpriv->int818_mode) { + case INT_TYPE_AI1_DMA_RTC: + case INT_TYPE_AI3_DMA_RTC: + mod_timer(&devpriv->rtc_irq_timer, + jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100); + save_flags(flags); + cli(); + tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ + restore_flags(flags); + break; + }; +} + +/* +============================================================================== + Set frequency of interrupts from RTC +*/ +static int rtc_setfreq_irq(int freq) +{ + int tmp = 0; + int rtc_freq; + unsigned char val; + unsigned long flags; + + if (freq < 2) + freq = 2; + if (freq > 8192) + freq = 8192; + + while (freq > (1 << tmp)) + tmp++; + + rtc_freq = 1 << tmp; + + save_flags(flags); + cli(); + val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0; + val |= (16 - tmp); + CMOS_WRITE(val, RTC_FREQ_SELECT); + restore_flags(flags); + return rtc_freq; +} +#endif + +/* +============================================================================== + Free any resources that we have claimed +*/ +static void free_resources(struct comedi_device * dev) +{ + //rt_printk("free_resource()\n"); + if (dev->private) { + pcl818_ai_cancel(dev, devpriv->sub_ai); + pcl818_reset(dev); + if (devpriv->dma) + free_dma(devpriv->dma); + if (devpriv->dmabuf[0]) + free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]); + if (devpriv->dmabuf[1]) + free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]); +#ifdef unused + if (devpriv->rtc_irq) + comedi_free_irq(devpriv->rtc_irq, dev); + if ((devpriv->dma_rtc) && (RTC_lock == 1)) { + if (devpriv->rtc_iobase) + release_region(devpriv->rtc_iobase, + devpriv->rtc_iosize); + } + if (devpriv->dma_rtc) + RTC_lock--; +#endif + } + + if (dev->irq) + free_irq(dev->irq, dev); + if (dev->iobase) + release_region(dev->iobase, devpriv->io_range); + //rt_printk("free_resource() end\n"); +} + +/* +============================================================================== + + Initialization + +*/ +static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + unsigned long iobase; + unsigned int irq, dma; + unsigned long pages; + struct comedi_subdevice *s; + + if ((ret = alloc_private(dev, sizeof(struct pcl818_private))) < 0) + return ret; /* Can't alloc mem */ + + /* claim our I/O space */ + iobase = it->options[0]; + printk("comedi%d: pcl818: board=%s, ioport=0x%03lx", + dev->minor, this_board->name, iobase); + devpriv->io_range = this_board->io_range; + if ((this_board->fifo) && (it->options[2] == -1)) { // we've board with FIFO and we want to use FIFO + devpriv->io_range = PCLx1xFIFO_RANGE; + devpriv->usefifo = 1; + } + if (!request_region(iobase, devpriv->io_range, "pcl818")) { + rt_printk("I/O port conflict\n"); + return -EIO; + } + + dev->iobase = iobase; + + if (pcl818_check(iobase)) { + rt_printk(", I can't detect board. FAIL!\n"); + return -EIO; + } + + /* set up some name stuff */ + dev->board_name = this_board->name; + /* grab our IRQ */ + irq = 0; + if (this_board->IRQbits != 0) { /* board support IRQ */ + irq = it->options[1]; + if (irq) { /* we want to use IRQ */ + if (((1 << irq) & this_board->IRQbits) == 0) { + rt_printk + (", IRQ %u is out of allowed range, DISABLING IT", + irq); + irq = 0; /* Bad IRQ */ + } else { + if (comedi_request_irq(irq, interrupt_pcl818, 0, + "pcl818", dev)) { + rt_printk + (", unable to allocate IRQ %u, DISABLING IT", + irq); + irq = 0; /* Can't use IRQ */ + } else { + rt_printk(", irq=%u", irq); + } + } + } + } + + dev->irq = irq; + if (irq) { + devpriv->irq_free = 1; + } /* 1=we have allocated irq */ + else { + devpriv->irq_free = 0; + } + devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */ + devpriv->ai_mode = 0; /* mode of irq */ + +#ifdef unused + /* grab RTC for DMA operations */ + devpriv->dma_rtc = 0; + if (it->options[2] > 0) { // we want to use DMA + if (RTC_lock == 0) { + if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, + "pcl818 (RTC)")) + goto no_rtc; + } + devpriv->rtc_iobase = RTC_PORT(0); + devpriv->rtc_iosize = RTC_IO_EXTENT; + RTC_lock++; + if (!comedi_request_irq(RTC_IRQ, + interrupt_pcl818_ai_mode13_dma_rtc, 0, + "pcl818 DMA (RTC)", dev)) { + devpriv->dma_rtc = 1; + devpriv->rtc_irq = RTC_IRQ; + rt_printk(", dma_irq=%u", devpriv->rtc_irq); + } else { + RTC_lock--; + if (RTC_lock == 0) { + if (devpriv->rtc_iobase) + release_region(devpriv->rtc_iobase, + devpriv->rtc_iosize); + } + devpriv->rtc_iobase = 0; + devpriv->rtc_iosize = 0; + } + } + + no_rtc: +#endif + /* grab our DMA */ + dma = 0; + devpriv->dma = dma; + if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0)) + goto no_dma; /* if we haven't IRQ, we can't use DMA */ + if (this_board->DMAbits != 0) { /* board support DMA */ + dma = it->options[2]; + if (dma < 1) + goto no_dma; /* DMA disabled */ + if (((1 << dma) & this_board->DMAbits) == 0) { + rt_printk(", DMA is out of allowed range, FAIL!\n"); + return -EINVAL; /* Bad DMA */ + } + ret = request_dma(dma, "pcl818"); + if (ret) { + rt_printk(", unable to allocate DMA %u, FAIL!\n", dma); + return -EBUSY; /* DMA isn't free */ + } + devpriv->dma = dma; + rt_printk(", dma=%u", dma); + pages = 2; /* we need 16KB */ + devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages); + if (!devpriv->dmabuf[0]) { + rt_printk(", unable to allocate DMA buffer, FAIL!\n"); + /* maybe experiment with try_to_free_pages() will help .... */ + return -EBUSY; /* no buffer :-( */ + } + devpriv->dmapages[0] = pages; + devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]); + devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE; + //rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); + if (devpriv->dma_rtc == 0) { // we must do duble buff :-( + devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages); + if (!devpriv->dmabuf[1]) { + rt_printk + (", unable to allocate DMA buffer, FAIL!\n"); + return -EBUSY; + } + devpriv->dmapages[1] = pages; + devpriv->hwdmaptr[1] = + virt_to_bus((void *)devpriv->dmabuf[1]); + devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE; + } + } + + no_dma: + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + + s = dev->subdevices + 0; + if (!this_board->n_aichan_se) { + s->type = COMEDI_SUBD_UNUSED; + } else { + s->type = COMEDI_SUBD_AI; + devpriv->sub_ai = s; + s->subdev_flags = SDF_READABLE; + if (check_single_ended(dev->iobase)) { + s->n_chan = this_board->n_aichan_se; + s->subdev_flags |= SDF_COMMON | SDF_GROUND; + printk(", %dchans S.E. DAC", s->n_chan); + } else { + s->n_chan = this_board->n_aichan_diff; + s->subdev_flags |= SDF_DIFF; + printk(", %dchans DIFF DAC", s->n_chan); + } + s->maxdata = this_board->ai_maxdata; + s->len_chanlist = s->n_chan; + s->range_table = this_board->ai_range_type; + s->cancel = pcl818_ai_cancel; + s->insn_read = pcl818_ai_insn_read; + if ((irq) || (devpriv->dma_rtc)) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->do_cmdtest = ai_cmdtest; + s->do_cmd = ai_cmd; + } + if (this_board->is_818) { + if ((it->options[4] == 1) || (it->options[4] == 10)) + s->range_table = &range_pcl818l_h_ai; // secondary range list jumper selectable + } else { + switch (it->options[4]) { + case 0: + s->range_table = &range_bipolar10; + break; + case 1: + s->range_table = &range_bipolar5; + break; + case 2: + s->range_table = &range_bipolar2_5; + break; + case 3: + s->range_table = &range718_bipolar1; + break; + case 4: + s->range_table = &range718_bipolar0_5; + break; + case 6: + s->range_table = &range_unipolar10; + break; + case 7: + s->range_table = &range_unipolar5; + break; + case 8: + s->range_table = &range718_unipolar2; + break; + case 9: + s->range_table = &range718_unipolar1; + break; + default: + s->range_table = &range_unknown; + break; + } + } + } + + s = dev->subdevices + 1; + if (!this_board->n_aochan) { + s->type = COMEDI_SUBD_UNUSED; + } else { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = this_board->n_aochan; + s->maxdata = this_board->ao_maxdata; + s->len_chanlist = this_board->n_aochan; + s->range_table = this_board->ao_range_type; + s->insn_read = pcl818_ao_insn_read; + s->insn_write = pcl818_ao_insn_write; +#ifdef unused +#ifdef PCL818_MODE13_AO + if (irq) { + s->trig[1] = pcl818_ao_mode1; + s->trig[3] = pcl818_ao_mode3; + } +#endif +#endif + if (this_board->is_818) { + if ((it->options[4] == 1) || (it->options[4] == 10)) + s->range_table = &range_unipolar10; + if (it->options[4] == 2) + s->range_table = &range_unknown; + } else { + if ((it->options[5] == 1) || (it->options[5] == 10)) + s->range_table = &range_unipolar10; + if (it->options[5] == 2) + s->range_table = &range_unknown; + } + } + + s = dev->subdevices + 2; + if (!this_board->n_dichan) { + s->type = COMEDI_SUBD_UNUSED; + } else { + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = this_board->n_dichan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dichan; + s->range_table = &range_digital; + s->insn_bits = pcl818_di_insn_bits; + } + + s = dev->subdevices + 3; + if (!this_board->n_dochan) { + s->type = COMEDI_SUBD_UNUSED; + } else { + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = this_board->n_dochan; + s->maxdata = 1; + s->len_chanlist = this_board->n_dochan; + s->range_table = &range_digital; + s->insn_bits = pcl818_do_insn_bits; + } + + /* select 1/10MHz oscilator */ + if ((it->options[3] == 0) || (it->options[3] == 10)) { + devpriv->i8253_osc_base = 100; + } else { + devpriv->i8253_osc_base = 1000; + } + + /* max sampling speed */ + devpriv->ns_min = this_board->ns_min; + + if (!this_board->is_818) { + if ((it->options[6] == 1) || (it->options[6] == 100)) + devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */ + } + + pcl818_reset(dev); + + rt_printk("\n"); + + return 0; +} + +/* +============================================================================== + Removes device + */ +static int pcl818_detach(struct comedi_device * dev) +{ + // rt_printk("comedi%d: pcl818: remove\n", dev->minor); + free_resources(dev); + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c new file mode 100644 index 000000000000..a3ed3a0e855a --- /dev/null +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -0,0 +1,307 @@ +/* + comedi/drivers/pcm724.c + + Drew Csillag + + hardware driver for Advantech card: + card: PCM-3724 + driver: pcm3724 + + Options for PCM-3724 + [0] - IO Base +*/ +/* +Driver: pcm3724 +Description: Advantech PCM-3724 +Author: Drew Csillag +Devices: [Advantech] PCM-3724 (pcm724) +Status: tested + +This is driver for digital I/O boards PCM-3724 with 48 DIO. +It needs 8255.o for operations and only immediate mode is supported. +See the source for configuration details. + +Copy/pasted/hacked from pcm724.c +*/ +/* + * check_driver overrides: + * struct comedi_insn + */ + +#include "../comedidev.h" + +#include +#include + +#include "8255.h" + +#define PCM3724_SIZE 16 +#define SIZE_8255 4 + +#define BUF_C0 0x1 +#define BUF_B0 0x2 +#define BUF_A0 0x4 +#define BUF_C1 0x8 +#define BUF_B1 0x10 +#define BUF_A1 0x20 + +#define GATE_A0 0x4 +#define GATE_B0 0x2 +#define GATE_C0 0x1 +#define GATE_A1 0x20 +#define GATE_B1 0x10 +#define GATE_C1 0x8 + +/* from 8255.c */ +#define CR_CW 0x80 +#define _8255_CR 3 +#define CR_B_IO 0x02 +#define CR_B_MODE 0x04 +#define CR_C_IO 0x09 +#define CR_A_IO 0x10 +#define CR_A_MODE(a) ((a)<<5) +#define CR_CW 0x80 + +static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcm3724_detach(struct comedi_device * dev); + +struct pcm3724_board { + const char *name; // driver name + int dio; // num of DIO + int numofports; // num of 8255 subdevices + unsigned int IRQbits; // allowed interrupts + unsigned int io_range; // len of IO space +}; + +//used to track configured dios +struct priv_pcm3724 { + int dio_1; + int dio_2; +}; + +static const struct pcm3724_board boardtypes[] = { + {"pcm3724", 48, 2, 0x00fc, PCM3724_SIZE,}, +}; + +#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcm3724_board)) +#define this_board ((const struct pcm3724_board *)dev->board_ptr) + +static struct comedi_driver driver_pcm3724 = { + driver_name:"pcm3724", + module:THIS_MODULE, + attach:pcm3724_attach, + detach:pcm3724_detach, + board_name:&boardtypes[0].name, + num_names:n_boardtypes, + offset:sizeof(struct pcm3724_board), +}; + +COMEDI_INITCLEANUP(driver_pcm3724); + +// (setq c-basic-offset 8) + +static int subdev_8255_cb(int dir, int port, int data, unsigned long arg) +{ + unsigned long iobase = arg; + unsigned char inbres; + //printk("8255cb %d %d %d %lx\n", dir,port,data,arg); + if (dir) { + //printk("8255 cb outb(%x, %lx)\n", data, iobase+port); + outb(data, iobase + port); + return 0; + } else { + inbres = inb(iobase + port); + //printk("8255 cb inb(%lx) = %x\n", iobase+port, inbres); + return inbres; + } +} + +static int compute_buffer(int config, int devno, struct comedi_subdevice * s) +{ + /* 1 in io_bits indicates output */ + if (s->io_bits & 0x0000ff) { + if (devno == 0) { + config |= BUF_A0; + } else { + config |= BUF_A1; + } + } + if (s->io_bits & 0x00ff00) { + if (devno == 0) { + config |= BUF_B0; + } else { + config |= BUF_B1; + } + } + if (s->io_bits & 0xff0000) { + if (devno == 0) { + config |= BUF_C0; + } else { + config |= BUF_C1; + } + } + return config; +} + +static void do_3724_config(struct comedi_device * dev, struct comedi_subdevice * s, + int chanspec) +{ + int config; + int buffer_config; + unsigned long port_8255_cfg; + + config = CR_CW; + buffer_config = 0; + + /* 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 & 0xff0000)) { + config |= CR_C_IO; + } + + buffer_config = compute_buffer(0, 0, dev->subdevices); + buffer_config = compute_buffer(buffer_config, 1, (dev->subdevices) + 1); + + if (s == dev->subdevices) { + port_8255_cfg = dev->iobase + _8255_CR; + } else { + port_8255_cfg = dev->iobase + SIZE_8255 + _8255_CR; + } + outb(buffer_config, dev->iobase + 8); /* update buffer register */ + //printk("pcm3724 buffer_config (%lx) %d, %x\n", dev->iobase + _8255_CR, chanspec, buffer_config); + outb(config, port_8255_cfg); +} + +static void enable_chan(struct comedi_device * dev, struct comedi_subdevice * s, int chanspec) +{ + unsigned int mask; + int gatecfg; + struct priv_pcm3724 *priv; + + gatecfg = 0; + priv = (struct priv_pcm3724 *) (dev->private); + + mask = 1 << CR_CHAN(chanspec); + if (s == dev->subdevices) { // subdev 0 + priv->dio_1 |= mask; + } else { //subdev 1 + priv->dio_2 |= mask; + } + if (priv->dio_1 & 0xff0000) { + gatecfg |= GATE_C0; + } + if (priv->dio_1 & 0xff00) { + gatecfg |= GATE_B0; + } + if (priv->dio_1 & 0xff) { + gatecfg |= GATE_A0; + } + if (priv->dio_2 & 0xff0000) { + gatecfg |= GATE_C1; + } + if (priv->dio_2 & 0xff00) { + gatecfg |= GATE_B1; + } + if (priv->dio_2 & 0xff) { + gatecfg |= GATE_A1; + } + // printk("gate control %x\n", gatecfg); + outb(gatecfg, dev->iobase + 9); +} + +/* overriding the 8255 insn config */ +static int subdev_3724_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_3724_config(dev, s, insn->chanspec); + enable_chan(dev, s, insn->chanspec); + return 1; +} + +static int pcm3724_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + unsigned long iobase; + unsigned int iorange; + int ret, i, n_subdevices; + + iobase = it->options[0]; + iorange = this_board->io_range; + if ((ret = alloc_private(dev, sizeof(struct priv_pcm3724))) < 0) + return -ENOMEM; + + ((struct priv_pcm3724 *) (dev->private))->dio_1 = 0; + ((struct priv_pcm3724 *) (dev->private))->dio_2 = 0; + + printk("comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor, + this_board->name, iobase); + if (!iobase || !request_region(iobase, iorange, "pcm3724")) { + printk("I/O port conflict\n"); + return -EIO; + } + + dev->iobase = iobase; + dev->board_name = this_board->name; + printk("\n"); + + n_subdevices = this_board->numofports; + + if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) + return ret; + + for (i = 0; i < dev->n_subdevices; i++) { + subdev_8255_init(dev, dev->subdevices + i, subdev_8255_cb, + (unsigned long)(dev->iobase + SIZE_8255 * i)); + ((dev->subdevices) + i)->insn_config = subdev_3724_insn_config; + }; + return 0; +} + +static int pcm3724_detach(struct comedi_device * dev) +{ + int i; + + if (dev->subdevices) { + for (i = 0; i < dev->n_subdevices; i++) { + subdev_8255_cleanup(dev, dev->subdevices + i); + } + } + if (dev->iobase) { + release_region(dev->iobase, this_board->io_range); + } + + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c new file mode 100644 index 000000000000..1de555fe645c --- /dev/null +++ b/drivers/staging/comedi/drivers/pcm3730.c @@ -0,0 +1,152 @@ +/* + * comedi/drivers/pcm3730.c + * Driver for PCM3730 and clones + * Blaine Lee + * from pcl725 by David S. + */ +/* +Driver: pcm3730 +Description: PCM3730 +Author: Blaine Lee +Devices: [Advantech] PCM-3730 (pcm3730) +Status: unknown + +Configuration options: + [0] - I/O port base +*/ + +#include "../comedidev.h" + +#include + +#define PCM3730_SIZE 4 // consecutive io port addresses + +#define PCM3730_DOA 0 // offsets for each port +#define PCM3730_DOB 2 +#define PCM3730_DOC 3 +#define PCM3730_DIA 0 +#define PCM3730_DIB 2 +#define PCM3730_DIC 3 + +static int pcm3730_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcm3730_detach(struct comedi_device * dev); +static struct comedi_driver driver_pcm3730 = { + driver_name:"pcm3730", + module:THIS_MODULE, + attach:pcm3730_attach, + detach:pcm3730_detach, +}; + +COMEDI_INITCLEANUP(driver_pcm3730); + +static int pcm3730_do_insn_bits(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]); + outb(s->state, dev->iobase + (unsigned long)(s->private)); + } + data[1] = s->state; + + return 2; +} + +static int pcm3730_di_insn_bits(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)); + return 2; +} + +static int pcm3730_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + + iobase = it->options[0]; + printk("comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, PCM3730_SIZE, "pcm3730")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + dev->board_name = "pcm3730"; + dev->iobase = dev->iobase; + dev->irq = 0; + + if (alloc_subdevices(dev, 6) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 1; + s->n_chan = 8; + s->insn_bits = pcm3730_do_insn_bits; + s->range_table = &range_digital; + s->private = (void *)PCM3730_DOA; + + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 1; + s->n_chan = 8; + s->insn_bits = pcm3730_do_insn_bits; + s->range_table = &range_digital; + s->private = (void *)PCM3730_DOB; + + s = dev->subdevices + 2; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 1; + s->n_chan = 8; + s->insn_bits = pcm3730_do_insn_bits; + s->range_table = &range_digital; + s->private = (void *)PCM3730_DOC; + + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->maxdata = 1; + s->n_chan = 8; + s->insn_bits = pcm3730_di_insn_bits; + s->range_table = &range_digital; + s->private = (void *)PCM3730_DIA; + + s = dev->subdevices + 4; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->maxdata = 1; + s->n_chan = 8; + s->insn_bits = pcm3730_di_insn_bits; + s->range_table = &range_digital; + s->private = (void *)PCM3730_DIB; + + s = dev->subdevices + 5; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->maxdata = 1; + s->n_chan = 8; + s->insn_bits = pcm3730_di_insn_bits; + s->range_table = &range_digital; + s->private = (void *)PCM3730_DIC; + + printk("\n"); + + return 0; +} + +static int pcm3730_detach(struct comedi_device * dev) +{ + printk("comedi%d: pcm3730: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, PCM3730_SIZE); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c new file mode 100644 index 000000000000..fc2a73d97c24 --- /dev/null +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -0,0 +1,173 @@ +/* + comedi/drivers/pcmad.c + Hardware driver for Winsystems PCM-A/D12 and PCM-A/D16 + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000,2001 David A. Schleef + + 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: pcmad +Description: Winsystems PCM-A/D12, PCM-A/D16 +Author: ds +Devices: [Winsystems] PCM-A/D12 (pcmad12), PCM-A/D16 (pcmad16) +Status: untested + +This driver was written on a bet that I couldn't write a driver +in less than 2 hours. I won the bet, but never got paid. =( + +Configuration options: + [0] - I/O port base + [1] - unused + [2] - Analog input reference + 0 = single ended + 1 = differential + [3] - Analog input encoding (must match jumpers) + 0 = straight binary + 1 = two's complement +*/ + +#include "../comedidev.h" + +#include + +#define PCMAD_SIZE 4 + +#define PCMAD_STATUS 0 +#define PCMAD_LSB 1 +#define PCMAD_MSB 2 +#define PCMAD_CONVERT 1 + +struct pcmad_board_struct { + const char *name; + int n_ai_bits; +}; +static const struct pcmad_board_struct pcmad_boards[] = { + { + name: "pcmad12", + n_ai_bits:12, + }, + { + name: "pcmad16", + n_ai_bits:16, + }, +}; + +#define this_board ((const struct pcmad_board_struct *)(dev->board_ptr)) +#define n_pcmad_boards (sizeof(pcmad_boards)/sizeof(pcmad_boards[0])) + +struct pcmad_priv_struct { + int differential; + int twos_comp; +}; +#define devpriv ((struct pcmad_priv_struct *)dev->private) + +static int pcmad_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcmad_detach(struct comedi_device * dev); +static struct comedi_driver driver_pcmad = { + driver_name:"pcmad", + module:THIS_MODULE, + attach:pcmad_attach, + detach:pcmad_detach, + board_name:&pcmad_boards[0].name, + num_names:n_pcmad_boards, + offset:sizeof(pcmad_boards[0]), +}; + +COMEDI_INITCLEANUP(driver_pcmad); + +#define TIMEOUT 100 + +static int pcmad_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan; + int n; + + chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { + outb(chan, dev->iobase + PCMAD_CONVERT); + + for (i = 0; i < TIMEOUT; i++) { + if ((inb(dev->iobase + PCMAD_STATUS) & 0x3) == 0x3) + break; + } + data[n] = inb(dev->iobase + PCMAD_LSB); + data[n] |= (inb(dev->iobase + PCMAD_MSB) << 8); + + if (devpriv->twos_comp) { + data[n] ^= (1 << (this_board->n_ai_bits - 1)); + } + } + + return n; +} + +/* + * options: + * 0 i/o base + * 1 unused + * 2 0=single ended 1=differential + * 3 0=straight binary 1=two's comp + */ +static int pcmad_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + struct comedi_subdevice *s; + unsigned long iobase; + + iobase = it->options[0]; + printk("comedi%d: pcmad: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, PCMAD_SIZE, "pcmad")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + if ((ret = alloc_subdevices(dev, 1)) < 0) + return ret; + if ((ret = alloc_private(dev, sizeof(struct pcmad_priv_struct))) < 0) + return ret; + + dev->board_name = this_board->name; + + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | AREF_GROUND; + s->n_chan = 16; /* XXX */ + s->len_chanlist = 1; + s->insn_read = pcmad_ai_insn_read; + s->maxdata = (1 << this_board->n_ai_bits) - 1; + s->range_table = &range_unknown; + + return 0; +} + +static int pcmad_detach(struct comedi_device * dev) +{ + printk("comedi%d: pcmad: remove\n", dev->minor); + + if (dev->irq) { + free_irq(dev->irq, dev); + } + if (dev->iobase) + release_region(dev->iobase, PCMAD_SIZE); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c new file mode 100644 index 000000000000..2a1ff465602a --- /dev/null +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -0,0 +1,306 @@ +/* + comedi/drivers/pcmda12.c + Driver for Winsystems PC-104 based PCM-D/A-12 8-channel AO board. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2006 Calin A. Culianu + + 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: pcmda12 +Description: A driver for the Winsystems PCM-D/A-12 +Devices: [Winsystems] PCM-D/A-12 (pcmda12) +Author: Calin Culianu +Updated: Fri, 13 Jan 2006 12:01:01 -0500 +Status: works + +A driver for the relatively straightforward-to-program PCM-D/A-12. +This board doesn't support commands, and the only way to set its +analog output range is to jumper the board. As such, +comedi_data_write() ignores the range value specified. + +The board uses 16 consecutive I/O addresses starting at the I/O port +base address. Each address corresponds to the LSB then MSB of a +particular channel from 0-7. + +Note that the board is not ISA-PNP capable and thus +needs the I/O port comedi_config parameter. + +Note that passing a nonzero value as the second config option will +enable "simultaneous xfer" mode for this board, in which AO writes +will not take effect until a subsequent read of any AO channel. This +is so that one can speed up programming by preloading all AO registers +with values before simultaneously setting them to take effect with one +read command. + +Configuration Options: + [0] - I/O port base address + [1] - Do Simultaneous Xfer (see description) +*/ + +#include "../comedidev.h" + +#include /* for PCI devices */ + +#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) ) +#define SDEV_NO ((int)(s - dev->subdevices)) +#define CHANS 8 +#define IOSIZE 16 +#define LSB(x) ((unsigned char)((x) & 0xff)) +#define MSB(x) ((unsigned char)((((unsigned short)(x))>>8) & 0xff)) +#define LSB_PORT(chan) (dev->iobase + (chan)*2) +#define MSB_PORT(chan) (LSB_PORT(chan)+1) +#define BITS 12 + +/* + * Bords + */ +struct pcmda12_board { + const char *name; +}; + +/* note these have no effect and are merely here for reference.. + these are configured by jumpering the board! */ +static const struct comedi_lrange pcmda12_ranges = { + 3, + { + UNI_RANGE(5), UNI_RANGE(10), BIP_RANGE(5) + } +}; + +static const struct pcmda12_board pcmda12_boards[] = { + { + name: "pcmda12", + }, +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct pcmda12_board *)dev->board_ptr) + +struct pcmda12_private { + + unsigned int ao_readback[CHANS]; + int simultaneous_xfer_mode; +}; + + +#define devpriv ((struct pcmda12_private *)(dev->private)) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int pcmda12_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcmda12_detach(struct comedi_device * dev); + +static void zero_chans(struct comedi_device * dev); + +static struct comedi_driver driver = { + driver_name:"pcmda12", + module:THIS_MODULE, + attach:pcmda12_attach, + detach:pcmda12_detach, +/* It is not necessary to implement the following members if you are + * writing a driver for a ISA PnP or PCI card */ + /* Most drivers will support multiple types of boards by + * having an array of board structures. These were defined + * in pcmda12_boards[] above. Note that the element 'name' + * was first in the structure -- Comedi uses this fact to + * extract the name of the board without knowing any details + * about the structure except for its length. + * When a device is attached (by comedi_config), the name + * of the device is given to Comedi, and Comedi tries to + * match it by going through the list of board names. If + * there is a match, the address of the pointer is put + * into dev->board_ptr and driver->attach() is called. + * + * Note that these are not necessary if you can determine + * the type of board in software. ISA PnP, PCI, and PCMCIA + * devices are such boards. + */ + board_name:&pcmda12_boards[0].name, + offset:sizeof(struct pcmda12_board), + num_names:sizeof(pcmda12_boards) / sizeof(struct pcmda12_board), +}; + +static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pcmda12_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + + iobase = it->options[0]; + printk("comedi%d: %s: io: %lx %s ", dev->minor, driver.driver_name, + iobase, it->options[1] ? "simultaneous xfer mode enabled" : ""); + + if (!request_region(iobase, IOSIZE, driver.driver_name)) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct pcmda12_private)) < 0) { + printk("cannot allocate private data structure\n"); + return -ENOMEM; + } + + devpriv->simultaneous_xfer_mode = it->options[1]; + + /* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + * + * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the + * 96-channel version of the board. + */ + if (alloc_subdevices(dev, 1) < 0) { + printk("cannot allocate subdevice data structures\n"); + return -ENOMEM; + } + + s = dev->subdevices; + s->private = NULL; + s->maxdata = (0x1 << BITS) - 1; + s->range_table = &pcmda12_ranges; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = CHANS; + s->insn_write = &ao_winsn; + s->insn_read = &ao_rinsn; + + zero_chans(dev); /* clear out all the registers, basically */ + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pcmda12_detach(struct comedi_device * dev) +{ + printk("comedi%d: %s: remove\n", dev->minor, driver.driver_name); + if (dev->iobase) + release_region(dev->iobase, IOSIZE); + return 0; +} + +static void zero_chans(struct comedi_device * dev) +{ /* sets up an + ASIC chip to defaults */ + int i; + for (i = 0; i < CHANS; ++i) { +/* /\* do this as one instruction?? *\/ */ +/* outw(0, LSB_PORT(chan)); */ + outb(0, LSB_PORT(i)); + outb(0, MSB_PORT(i)); + } + inb(LSB_PORT(0)); /* update chans. */ +} + +static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; ++i) { + +/* /\* do this as one instruction?? *\/ */ +/* outw(data[i], LSB_PORT(chan)); */ + + /* Need to do this as two instructions due to 8-bit bus?? */ + /* first, load the low byte */ + outb(LSB(data[i]), LSB_PORT(chan)); + /* next, write the high byte */ + outb(MSB(data[i]), MSB_PORT(chan)); + + /* save shadow register */ + devpriv->ao_readback[chan] = data[i]; + + if (!devpriv->simultaneous_xfer_mode) + inb(LSB_PORT(chan)); + } + + /* return the number of samples written */ + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + + Usually this means copying a value stored in devpriv->ao_readback. + However, since this driver supports simultaneous xfer then sometimes + this function actually accomplishes work. + + Simultaneaous xfer mode is accomplished by loading ALL the values + you want for AO in all the channels, then READing off one of the AO + registers to initiate the instantaneous simultaneous update of all + DAC outputs, which makes all AO channels update simultaneously. + This is useful for some control applications, I would imagine. +*/ +static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + if (devpriv->simultaneous_xfer_mode) + inb(LSB_PORT(chan)); + /* read back shadow register */ + data[i] = devpriv->ao_readback[chan]; + } + + return i; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver); diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c new file mode 100644 index 000000000000..01e40f1b5628 --- /dev/null +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -0,0 +1,1333 @@ +/* + comedi/drivers/pcmmio.c + Driver for Winsystems PC-104 based multifunction IO board. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2007 Calin A. Culianu + + 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: pcmmio +Description: A driver for the PCM-MIO multifunction board +Devices: [Winsystems] PCM-MIO (pcmmio) +Author: Calin Culianu +Updated: Wed, May 16 2007 16:21:10 -0500 +Status: works + +A driver for the relatively new PCM-MIO multifunction board from +Winsystems. This board is a PC-104 based I/O board. It contains +four subdevices: + subdevice 0 - 16 channels of 16-bit AI + subdevice 1 - 8 channels of 16-bit AO + subdevice 2 - first 24 channels of the 48 channel of DIO (with edge-triggered interrupt support) + subdevice 3 - last 24 channels of the 48 channel DIO (no interrupt support for this bank of channels) + + Some notes: + + Synchronous reads and writes are the only things implemented for AI and AO, + even though the hardware itself can do streaming acquisition, etc. Anyone + want to add asynchronous I/O for AI/AO as a feature? Be my guest... + + Asynchronous I/O for the DIO subdevices *is* implemented, however! They are + basically edge-triggered interrupts for any configuration of the first + 24 DIO-lines. + + Also note that this interrupt support is untested. + + A few words about edge-detection IRQ support (commands on DIO): + + * To use edge-detection IRQ support for the DIO subdevice, pass the IRQ + of the board to the comedi_config command. The board IRQ is not jumpered + but rather configured through software, so any IRQ from 1-15 is OK. + + * Due to the genericity of the comedi API, you need to create a special + comedi_command in order to use edge-triggered interrupts for DIO. + + * Use comedi_commands with TRIG_NOW. Your callback will be called each + time an edge is detected on the specified DIO line(s), and the data + values will be two sample_t's, which should be concatenated to form + one 32-bit unsigned int. This value is the mask of channels that had + edges detected from your channel list. Note that the bits positions + in the mask correspond to positions in your chanlist when you + specified the command and *not* channel id's! + + * To set the polarity of the edge-detection interrupts pass a nonzero value + for either CR_RANGE or CR_AREF for edge-up polarity, or a zero + value for both CR_RANGE and CR_AREF if you want edge-down polarity. + +Configuration Options: + [0] - I/O port base address + [1] - IRQ (optional -- for edge-detect interrupt support only, leave out if you don't need this feature) +*/ + +#include "../comedidev.h" +#include /* for PCI devices */ + +#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) ) + +/* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */ +#define CHANS_PER_PORT 8 +#define PORTS_PER_ASIC 6 +#define INTR_PORTS_PER_ASIC 3 +#define MAX_CHANS_PER_SUBDEV 24 /* number of channels per comedi subdevice */ +#define PORTS_PER_SUBDEV (MAX_CHANS_PER_SUBDEV/CHANS_PER_PORT) +#define CHANS_PER_ASIC (CHANS_PER_PORT*PORTS_PER_ASIC) +#define INTR_CHANS_PER_ASIC 24 +#define INTR_PORTS_PER_SUBDEV (INTR_CHANS_PER_ASIC/CHANS_PER_PORT) +#define MAX_DIO_CHANS (PORTS_PER_ASIC*1*CHANS_PER_PORT) +#define MAX_ASICS (MAX_DIO_CHANS/CHANS_PER_ASIC) +#define SDEV_NO ((int)(s - dev->subdevices)) +#define CALC_N_DIO_SUBDEVS(nchans) ((nchans)/MAX_CHANS_PER_SUBDEV + (!!((nchans)%MAX_CHANS_PER_SUBDEV)) /*+ (nchans > INTR_CHANS_PER_ASIC ? 2 : 1)*/) +/* IO Memory sizes */ +#define ASIC_IOSIZE (0x0B) +#define PCMMIO48_IOSIZE ASIC_IOSIZE + +/* Some offsets - these are all in the 16byte IO memory offset from + the base address. Note that there is a paging scheme to swap out + offsets 0x8-0xA using the PAGELOCK register. See the table below. + + Register(s) Pages R/W? Description + -------------------------------------------------------------- + REG_PORTx All R/W Read/Write/Configure IO + REG_INT_PENDING All ReadOnly Quickly see which INT_IDx has int. + REG_PAGELOCK All WriteOnly Select a page + REG_POLx Pg. 1 only WriteOnly Select edge-detection polarity + REG_ENABx Pg. 2 only WriteOnly Enable/Disable edge-detect. int. + REG_INT_IDx Pg. 3 only R/W See which ports/bits have ints. + */ +#define REG_PORT0 0x0 +#define REG_PORT1 0x1 +#define REG_PORT2 0x2 +#define REG_PORT3 0x3 +#define REG_PORT4 0x4 +#define REG_PORT5 0x5 +#define REG_INT_PENDING 0x6 +#define REG_PAGELOCK 0x7 /* page selector register, upper 2 bits select a page + and bits 0-5 are used to 'lock down' a particular + port above to make it readonly. */ +#define REG_POL0 0x8 +#define REG_POL1 0x9 +#define REG_POL2 0xA +#define REG_ENAB0 0x8 +#define REG_ENAB1 0x9 +#define REG_ENAB2 0xA +#define REG_INT_ID0 0x8 +#define REG_INT_ID1 0x9 +#define REG_INT_ID2 0xA + +#define NUM_PAGED_REGS 3 +#define NUM_PAGES 4 +#define FIRST_PAGED_REG 0x8 +#define REG_PAGE_BITOFFSET 6 +#define REG_LOCK_BITOFFSET 0 +#define REG_PAGE_MASK (~((0x1<board_ptr) + +/* this structure is for data unique to this subdevice. */ +struct pcmmio_subdev_private { + + union { + /* for DIO: mapping of halfwords (bytes) in port/chanarray to iobase */ + unsigned long iobases[PORTS_PER_SUBDEV]; + + /* for AI/AO */ + unsigned long iobase; + }; + union { + struct { + + /* The below is only used for intr subdevices */ + struct { + int asic; /* if non-negative, this subdev has an interrupt asic */ + int first_chan; /* if nonnegative, the first channel id for + interrupts. */ + int num_asic_chans; /* the number of asic channels in this subdev + that have interrutps */ + int asic_chan; /* if nonnegative, the first channel id with + respect to the asic that has interrupts */ + int enabled_mask; /* subdev-relative channel mask for channels + we are interested in */ + int active; + int stop_count; + int continuous; + spinlock_t spinlock; + } intr; + } dio; + struct { + unsigned int shadow_samples[8]; /* the last unsigned int data written */ + } ao; + }; +}; + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct pcmmio_private { + /* stuff for DIO */ + struct { + unsigned char pagelock; /* current page and lock */ + unsigned char pol[NUM_PAGED_REGS]; /* shadow of POLx registers */ + unsigned char enab[NUM_PAGED_REGS]; /* shadow of ENABx registers */ + int num; + unsigned long iobase; + unsigned int irq; + spinlock_t spinlock; + } asics[MAX_ASICS]; + struct pcmmio_subdev_private *sprivs; +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct pcmmio_private *)dev->private) +#define subpriv ((struct pcmmio_subdev_private *)s->private) +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcmmio_detach(struct comedi_device * dev); + +static struct comedi_driver driver = { + driver_name:"pcmmio", + module:THIS_MODULE, + attach:pcmmio_attach, + detach:pcmmio_detach, +/* It is not necessary to implement the following members if you are + * writing a driver for a ISA PnP or PCI card */ + /* Most drivers will support multiple types of boards by + * having an array of board structures. These were defined + * in pcmmio_boards[] above. Note that the element 'name' + * was first in the structure -- Comedi uses this fact to + * extract the name of the board without knowing any details + * about the structure except for its length. + * When a device is attached (by comedi_config), the name + * of the device is given to Comedi, and Comedi tries to + * match it by going through the list of board names. If + * there is a match, the address of the pointer is put + * into dev->board_ptr and driver->attach() is called. + * + * Note that these are not necessary if you can determine + * the type of board in software. ISA PnP, PCI, and PCMCIA + * devices are such boards. + */ + board_name:&pcmmio_boards[0].name, + offset:sizeof(struct pcmmio_board), + num_names:sizeof(pcmmio_boards) / sizeof(struct pcmmio_board), +}; + +static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pcmmio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG); +static void pcmmio_stop_intr(struct comedi_device *, struct comedi_subdevice *); +static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int pcmmio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); + +/* some helper functions to deal with specifics of this device's registers */ +static void init_asics(struct comedi_device * dev); /* sets up/clears ASIC chips to defaults */ +static void switch_page(struct comedi_device * dev, int asic, int page); +#ifdef notused +static void lock_port(struct comedi_device * dev, int asic, int port); +static void unlock_port(struct comedi_device * dev, int asic, int port); +#endif + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic, + thisasic_chanct = 0; + unsigned long iobase; + unsigned int irq[MAX_ASICS]; + + iobase = it->options[0]; + irq[0] = it->options[1]; + + printk("comedi%d: %s: io: %lx ", dev->minor, driver.driver_name, + iobase); + + dev->iobase = iobase; + + if (!iobase || !request_region(iobase, + thisboard->total_iosize, driver.driver_name)) { + printk("I/O port conflict\n"); + return -EIO; + } + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) { + printk("cannot allocate private data structure\n"); + return -ENOMEM; + } + + for (asic = 0; asic < MAX_ASICS; ++asic) { + devpriv->asics[asic].num = asic; + devpriv->asics[asic].iobase = + dev->iobase + 16 + asic * ASIC_IOSIZE; + devpriv->asics[asic].irq = 0; /* this gets actually set at the end of + this function when we + comedi_request_irqs */ + spin_lock_init(&devpriv->asics[asic].spinlock); + } + + chans_left = CHANS_PER_ASIC * thisboard->dio_num_asics; + n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left); + n_subdevs = n_dio_subdevs + 2; + devpriv->sprivs = + kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private), GFP_KERNEL); + if (!devpriv->sprivs) { + printk("cannot allocate subdevice private data structures\n"); + return -ENOMEM; + } + /* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + * + * Allocate 1 AI + 1 AO + 2 DIO subdevs (24 lines per DIO) + */ + if (alloc_subdevices(dev, n_subdevs) < 0) { + printk("cannot allocate subdevice data structures\n"); + return -ENOMEM; + } + + /* First, AI */ + sdev_no = 0; + s = dev->subdevices + sdev_no; + s->private = devpriv->sprivs + sdev_no; + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = thisboard->ai_range_table; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; + s->type = COMEDI_SUBD_AI; + s->n_chan = thisboard->n_ai_chans; + s->len_chanlist = s->n_chan; + s->insn_read = thisboard->ai_rinsn; + subpriv->iobase = dev->iobase + 0; + /* initialize the resource enable register by clearing it */ + outb(0, subpriv->iobase + 3); + outb(0, subpriv->iobase + 4 + 3); + + /* Next, AO */ + ++sdev_no; + s = dev->subdevices + sdev_no; + s->private = devpriv->sprivs + sdev_no; + s->maxdata = (1 << thisboard->ao_bits) - 1; + s->range_table = thisboard->ao_range_table; + s->subdev_flags = SDF_READABLE; + s->type = COMEDI_SUBD_AO; + s->n_chan = thisboard->n_ao_chans; + s->len_chanlist = s->n_chan; + s->insn_read = thisboard->ao_rinsn; + s->insn_write = thisboard->ao_winsn; + subpriv->iobase = dev->iobase + 8; + /* initialize the resource enable register by clearing it */ + outb(0, subpriv->iobase + 3); + outb(0, subpriv->iobase + 4 + 3); + + ++sdev_no; + port = 0; + asic = 0; + for (; sdev_no < (int)dev->n_subdevices; ++sdev_no) { + int byte_no; + + s = dev->subdevices + sdev_no; + s->private = devpriv->sprivs + sdev_no; + s->maxdata = 1; + s->range_table = &range_digital; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->type = COMEDI_SUBD_DIO; + s->insn_bits = pcmmio_dio_insn_bits; + s->insn_config = pcmmio_dio_insn_config; + s->n_chan = MIN(chans_left, MAX_CHANS_PER_SUBDEV); + subpriv->dio.intr.asic = -1; + subpriv->dio.intr.first_chan = -1; + subpriv->dio.intr.asic_chan = -1; + subpriv->dio.intr.num_asic_chans = -1; + subpriv->dio.intr.active = 0; + s->len_chanlist = 1; + + /* save the ioport address for each 'port' of 8 channels in the + subdevice */ + for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) { + if (port >= PORTS_PER_ASIC) { + port = 0; + ++asic; + thisasic_chanct = 0; + } + subpriv->iobases[byte_no] = + devpriv->asics[asic].iobase + port; + + if (thisasic_chanct < + CHANS_PER_PORT * INTR_PORTS_PER_ASIC + && subpriv->dio.intr.asic < 0) { + /* this is an interrupt subdevice, so setup the struct */ + subpriv->dio.intr.asic = asic; + subpriv->dio.intr.active = 0; + subpriv->dio.intr.stop_count = 0; + subpriv->dio.intr.first_chan = byte_no * 8; + subpriv->dio.intr.asic_chan = thisasic_chanct; + subpriv->dio.intr.num_asic_chans = + s->n_chan - + subpriv->dio.intr.first_chan; + s->cancel = pcmmio_cancel; + s->do_cmd = pcmmio_cmd; + s->do_cmdtest = pcmmio_cmdtest; + s->len_chanlist = + subpriv->dio.intr.num_asic_chans; + } + thisasic_chanct += CHANS_PER_PORT; + } + spin_lock_init(&subpriv->dio.intr.spinlock); + + chans_left -= s->n_chan; + + if (!chans_left) { + asic = 0; /* reset the asic to our first asic, to do intr subdevs */ + port = 0; + } + + } + + init_asics(dev); /* clear out all the registers, basically */ + + for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) { + if (irq[asic] + && comedi_request_irq(irq[asic], interrupt_pcmmio, + IRQF_SHARED, thisboard->name, dev)) { + int i; + /* unroll the allocated irqs.. */ + for (i = asic - 1; i >= 0; --i) { + comedi_free_irq(irq[i], dev); + devpriv->asics[i].irq = irq[i] = 0; + } + irq[asic] = 0; + } + devpriv->asics[asic].irq = irq[asic]; + } + + dev->irq = irq[0]; /* grr.. wish comedi dev struct supported multiple + irqs.. */ + + if (irq[0]) { + printk("irq: %u ", irq[0]); + if (irq[1] && thisboard->dio_num_asics == 2) + printk("second ASIC irq: %u ", irq[1]); + } else { + printk("(IRQ mode disabled) "); + } + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pcmmio_detach(struct comedi_device * dev) +{ + int i; + + printk("comedi%d: %s: remove\n", dev->minor, driver.driver_name); + if (dev->iobase) + release_region(dev->iobase, thisboard->total_iosize); + + for (i = 0; i < MAX_ASICS; ++i) { + if (devpriv && devpriv->asics[i].irq) + comedi_free_irq(devpriv->asics[i].irq, dev); + } + + if (devpriv && devpriv->sprivs) + kfree(devpriv->sprivs); + + return 0; +} + +/* DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write */ +static int pcmmio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int byte_no; + if (insn->n != 2) + return -EINVAL; + + /* NOTE: + reading a 0 means this channel was high + writine a 0 sets the channel high + reading a 1 means this channel was low + writing a 1 means set this channel low + + Therefore everything is always inverted. */ + + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + +#ifdef DAMMIT_ITS_BROKEN + /* DEBUG */ + printk("write mask: %08x data: %08x\n", data[0], data[1]); +#endif + + s->state = 0; + + for (byte_no = 0; byte_no < s->n_chan / CHANS_PER_PORT; ++byte_no) { + /* address of 8-bit port */ + unsigned long ioaddr = subpriv->iobases[byte_no], + /* bit offset of port in 32-bit doubleword */ + offset = byte_no * 8; + /* this 8-bit port's data */ + unsigned char byte = 0, + /* The write mask for this port (if any) */ + write_mask_byte = (data[0] >> offset) & 0xff, + /* The data byte for this port */ + data_byte = (data[1] >> offset) & 0xff; + + byte = inb(ioaddr); /* read all 8-bits for this port */ + +#ifdef DAMMIT_ITS_BROKEN + /* DEBUG */ + printk("byte %d wmb %02x db %02x offset %02d io %04x, data_in %02x ", byte_no, (unsigned)write_mask_byte, (unsigned)data_byte, offset, ioaddr, (unsigned)byte); +#endif + + if (write_mask_byte) { + /* this byte has some write_bits -- so set the output lines */ + byte &= ~write_mask_byte; /* clear bits for write mask */ + byte |= ~data_byte & write_mask_byte; /* set to inverted data_byte */ + /* Write out the new digital output state */ + outb(byte, ioaddr); + } +#ifdef DAMMIT_ITS_BROKEN + /* DEBUG */ + printk("data_out_byte %02x\n", (unsigned)byte); +#endif + /* save the digital input lines for this byte.. */ + s->state |= ((unsigned int)byte) << offset; + } + + /* now return the DIO lines to data[1] - note they came inverted! */ + data[1] = ~s->state; + +#ifdef DAMMIT_ITS_BROKEN + /* DEBUG */ + printk("s->state %08x data_out %08x\n", s->state, data[1]); +#endif + + return 2; +} + +/* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ +static int pcmmio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no = + chan % 8; + unsigned long ioaddr; + unsigned char byte; + + /* Compute ioaddr for this channel */ + ioaddr = subpriv->iobases[byte_no]; + + /* NOTE: + writing a 0 an IO channel's bit sets the channel to INPUT + and pulls the line high as well + + writing a 1 to an IO channel's bit pulls the line low + + All channels are implicitly always in OUTPUT mode -- but when + they are high they can be considered to be in INPUT mode.. + + Thus, we only force channels low if the config request was INPUT, + otherwise we do nothing to the hardware. */ + + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + /* save to io_bits -- don't actually do anything since + all input channels are also output channels... */ + s->io_bits |= 1 << chan; + break; + case INSN_CONFIG_DIO_INPUT: + /* write a 0 to the actual register representing the channel + to set it to 'input'. 0 means "float high". */ + byte = inb(ioaddr); + byte &= ~(1 << bit_no); + /**< set input channel to '0' */ + + /* write out byte -- this is the only time we actually affect the + hardware as all channels are implicitly output -- but input + channels are set to float-high */ + outb(byte, ioaddr); + + /* save to io_bits */ + s->io_bits &= ~(1 << chan); + break; + + case INSN_CONFIG_DIO_QUERY: + /* retreive from shadow register */ + data[1] = + (s-> + io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + + default: + return -EINVAL; + break; + } + + return insn->n; +} + +static void init_asics(struct comedi_device * dev) +{ /* sets up an + ASIC chip to defaults */ + int asic; + + for (asic = 0; asic < thisboard->dio_num_asics; ++asic) { + int port, page; + unsigned long baseaddr = devpriv->asics[asic].iobase; + + switch_page(dev, asic, 0); /* switch back to page 0 */ + + /* first, clear all the DIO port bits */ + for (port = 0; port < PORTS_PER_ASIC; ++port) + outb(0, baseaddr + REG_PORT0 + port); + + /* Next, clear all the paged registers for each page */ + for (page = 1; page < NUM_PAGES; ++page) { + int reg; + /* now clear all the paged registers */ + switch_page(dev, asic, page); + for (reg = FIRST_PAGED_REG; + reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg) + outb(0, baseaddr + reg); + } + + /* DEBUG set rising edge interrupts on port0 of both asics */ + /*switch_page(dev, asic, PAGE_POL); + outb(0xff, baseaddr + REG_POL0); + switch_page(dev, asic, PAGE_ENAB); + outb(0xff, baseaddr + REG_ENAB0); */ + /* END DEBUG */ + + switch_page(dev, asic, 0); /* switch back to default page 0 */ + + } +} + +static void switch_page(struct comedi_device * dev, int asic, int page) +{ + if (asic < 0 || asic >= thisboard->dio_num_asics) + return; /* paranoia */ + if (page < 0 || page >= NUM_PAGES) + return; /* more paranoia */ + + devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK; + devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET; + + /* now write out the shadow register */ + outb(devpriv->asics[asic].pagelock, + devpriv->asics[asic].iobase + REG_PAGELOCK); +} + +#ifdef notused +static void lock_port(struct comedi_device * dev, int asic, int port) +{ + if (asic < 0 || asic >= thisboard->dio_num_asics) + return; /* paranoia */ + if (port < 0 || port >= PORTS_PER_ASIC) + return; /* more paranoia */ + + devpriv->asics[asic].pagelock |= 0x1 << port; + /* now write out the shadow register */ + outb(devpriv->asics[asic].pagelock, + devpriv->asics[asic].iobase + REG_PAGELOCK); + return; +} + +static void unlock_port(struct comedi_device * dev, int asic, int port) +{ + if (asic < 0 || asic >= thisboard->dio_num_asics) + return; /* paranoia */ + if (port < 0 || port >= PORTS_PER_ASIC) + return; /* more paranoia */ + devpriv->asics[asic].pagelock &= ~(0x1 << port) | REG_LOCK_MASK; + /* now write out the shadow register */ + outb(devpriv->asics[asic].pagelock, + devpriv->asics[asic].iobase + REG_PAGELOCK); +} +#endif /* notused */ + +static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG) +{ + int asic, got1 = 0; + struct comedi_device *dev = (struct comedi_device *) d; + + for (asic = 0; asic < MAX_ASICS; ++asic) { + if (irq == devpriv->asics[asic].irq) { + unsigned long flags; + unsigned triggered = 0; + unsigned long iobase = devpriv->asics[asic].iobase; + /* it is an interrupt for ASIC #asic */ + unsigned char int_pend; + + comedi_spin_lock_irqsave(&devpriv->asics[asic].spinlock, + flags); + + int_pend = inb(iobase + REG_INT_PENDING) & 0x07; + + if (int_pend) { + int port; + for (port = 0; port < INTR_PORTS_PER_ASIC; + ++port) { + if (int_pend & (0x1 << port)) { + unsigned char + io_lines_with_edges = 0; + switch_page(dev, asic, + PAGE_INT_ID); + io_lines_with_edges = + inb(iobase + + REG_INT_ID0 + port); + + if (io_lines_with_edges) + /* clear pending interrupt */ + outb(0, iobase + + REG_INT_ID0 + + port); + + triggered |= + io_lines_with_edges << + port * 8; + } + } + + ++got1; + } + + comedi_spin_unlock_irqrestore(&devpriv->asics[asic]. + spinlock, flags); + + if (triggered) { + struct comedi_subdevice *s; + /* TODO here: dispatch io lines to subdevs with commands.. */ + printk("PCMMIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n", irq, asic, triggered); + for (s = dev->subdevices + 2; + s < dev->subdevices + dev->n_subdevices; + ++s) { + if (subpriv->dio.intr.asic == asic) { /* this is an interrupt subdev, and it matches this asic! */ + unsigned long flags; + unsigned oldevents; + + comedi_spin_lock_irqsave + (&subpriv->dio.intr. + spinlock, flags); + + oldevents = s->async->events; + + if (subpriv->dio.intr.active) { + unsigned mytrig = + ((triggered >> + subpriv-> + dio. + intr. + asic_chan) + & ((0x1 << subpriv->dio.intr.num_asic_chans) - 1)) << subpriv->dio.intr.first_chan; + if (mytrig & subpriv-> + dio.intr. + enabled_mask) { + unsigned int val = + 0; + unsigned int n, + ch, len; + + len = s->async-> + cmd. + chanlist_len; + for (n = 0; + n < len; + n++) { + ch = CR_CHAN(s->async->cmd.chanlist[n]); + if (mytrig & (1U << ch)) { + val |= (1U << n); + } + } + /* Write the scan to the buffer. */ + if (comedi_buf_put(s->async, ((short *) & val)[0]) + && + comedi_buf_put + (s->async, ((short *) & val)[1])) { + s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); + } else { + /* Overflow! Stop acquisition!! */ + /* TODO: STOP_ACQUISITION_CALL_HERE!! */ + pcmmio_stop_intr + (dev, + s); + } + + /* Check for end of acquisition. */ + if (!subpriv-> + dio. + intr. + continuous) + { + /* stop_src == TRIG_COUNT */ + if (subpriv->dio.intr.stop_count > 0) { + subpriv-> + dio. + intr. + stop_count--; + if (subpriv->dio.intr.stop_count == 0) { + s->async->events |= COMEDI_CB_EOA; + /* TODO: STOP_ACQUISITION_CALL_HERE!! */ + pcmmio_stop_intr + (dev, + s); + } + } + } + } + } + + comedi_spin_unlock_irqrestore + (&subpriv->dio.intr. + spinlock, flags); + + if (oldevents != + s->async->events) { + comedi_event(dev, s); + } + + } + + } + } + + } + } + if (!got1) + return IRQ_NONE; /* interrupt from other source */ + return IRQ_HANDLED; +} + +static void pcmmio_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int nports, firstport, asic, port; + + if ((asic = subpriv->dio.intr.asic) < 0) + return; /* not an interrupt subdev */ + + subpriv->dio.intr.enabled_mask = 0; + subpriv->dio.intr.active = 0; + s->async->inttrig = 0; + nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT; + firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT; + switch_page(dev, asic, PAGE_ENAB); + for (port = firstport; port < firstport + nports; ++port) { + /* disable all intrs for this subdev.. */ + outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port); + } +} + +static int pcmmio_start_intr(struct comedi_device * dev, struct comedi_subdevice * s) +{ + if (!subpriv->dio.intr.continuous && subpriv->dio.intr.stop_count == 0) { + /* An empty acquisition! */ + s->async->events |= COMEDI_CB_EOA; + subpriv->dio.intr.active = 0; + return 1; + } else { + unsigned bits = 0, pol_bits = 0, n; + int nports, firstport, asic, port; + struct comedi_cmd *cmd = &s->async->cmd; + + if ((asic = subpriv->dio.intr.asic) < 0) + return 1; /* not an interrupt + subdev */ + subpriv->dio.intr.enabled_mask = 0; + subpriv->dio.intr.active = 1; + nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT; + firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT; + if (cmd->chanlist) { + for (n = 0; n < cmd->chanlist_len; n++) { + bits |= (1U << CR_CHAN(cmd->chanlist[n])); + pol_bits |= (CR_AREF(cmd->chanlist[n]) + || CR_RANGE(cmd->chanlist[n]) ? 1U : 0U) + << CR_CHAN(cmd->chanlist[n]); + } + } + bits &= ((0x1 << subpriv->dio.intr.num_asic_chans) - + 1) << subpriv->dio.intr.first_chan; + subpriv->dio.intr.enabled_mask = bits; + + { /* the below code configures the board to use a specific IRQ from 0-15. */ + unsigned char b; + /* set resource enable register to enable IRQ operation */ + outb(1 << 4, dev->iobase + 3); + /* set bits 0-3 of b to the irq number from 0-15 */ + b = dev->irq & ((1 << 4) - 1); + outb(b, dev->iobase + 2); + /* done, we told the board what irq to use */ + } + + switch_page(dev, asic, PAGE_ENAB); + for (port = firstport; port < firstport + nports; ++port) { + unsigned enab = + bits >> (subpriv->dio.intr.first_chan + (port - + firstport) * 8) & 0xff, pol = + pol_bits >> (subpriv->dio.intr.first_chan + + (port - firstport) * 8) & 0xff; + /* set enab intrs for this subdev.. */ + outb(enab, + devpriv->asics[asic].iobase + REG_ENAB0 + port); + switch_page(dev, asic, PAGE_POL); + outb(pol, + devpriv->asics[asic].iobase + REG_ENAB0 + port); + } + } + return 0; +} + +static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); + if (subpriv->dio.intr.active) + pcmmio_stop_intr(dev, s); + comedi_spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); + + return 0; +} + +/* + * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. + */ +static int +pcmmio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ + unsigned long flags; + int event = 0; + + if (trignum != 0) + return -EINVAL; + + comedi_spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); + s->async->inttrig = 0; + if (subpriv->dio.intr.active) { + event = pcmmio_start_intr(dev, s); + } + comedi_spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); + + if (event) { + comedi_event(dev, s); + } + + return 1; +} + +/* + * 'do_cmd' function for an 'INTERRUPT' subdevice. + */ +static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + unsigned long flags; + int event = 0; + + comedi_spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); + subpriv->dio.intr.active = 1; + + /* Set up end of acquisition. */ + switch (cmd->stop_src) { + case TRIG_COUNT: + subpriv->dio.intr.continuous = 0; + subpriv->dio.intr.stop_count = cmd->stop_arg; + break; + default: + /* TRIG_NONE */ + subpriv->dio.intr.continuous = 1; + subpriv->dio.intr.stop_count = 0; + break; + } + + /* Set up start of acquisition. */ + switch (cmd->start_src) { + case TRIG_INT: + s->async->inttrig = pcmmio_inttrig_start_intr; + break; + default: + /* TRIG_NOW */ + event = pcmmio_start_intr(dev, s); + break; + } + comedi_spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); + + if (event) { + comedi_event(dev, s); + } + + return 0; +} + +/* + * 'do_cmdtest' function for an 'INTERRUPT' subdevice. + */ +static int +pcmmio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd) +{ + int err = 0; + unsigned int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= (TRIG_NOW | TRIG_INT); + 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_NOW; + 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_COUNT | TRIG_NONE); + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */ + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + /* cmd->scan_begin_src == TRIG_EXT */ + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + + /* cmd->convert_src == TRIG_NOW */ + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + + /* cmd->scan_end_src == TRIG_COUNT */ + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + switch (cmd->stop_src) { + case TRIG_COUNT: + /* any count allowed */ + break; + case TRIG_NONE: + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + break; + default: + break; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + /* if (err) return 4; */ + + return 0; +} + +static int adc_wait_ready(unsigned long iobase) +{ + unsigned long retry = 100000; + while (retry--) + if (inb(iobase + 3) & 0x80) + return 0; + return 1; +} + +/* All this is for AI and AO */ +static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + unsigned long iobase = subpriv->iobase; + + /* + 1. write the CMD byte (to BASE+2) + 2. read junk lo byte (BASE+0) + 3. read junk hi byte (BASE+1) + 4. (mux settled so) write CMD byte again (BASE+2) + 5. read valid lo byte(BASE+0) + 6. read valid hi byte(BASE+1) + + Additionally note that the BASE += 4 if the channel >= 8 + */ + + /* convert n samples */ + for (n = 0; n < insn->n; n++) { + unsigned chan = CR_CHAN(insn->chanspec), range = + CR_RANGE(insn->chanspec), aref = + CR_AREF(insn->chanspec); + unsigned char command_byte = 0; + unsigned iooffset = 0; + short sample, adc_adjust = 0; + + if (chan > 7) + chan -= 8, iooffset = 4; /* use the second dword for channels > 7 */ + + if (aref != AREF_DIFF) { + aref = AREF_GROUND; + command_byte |= 1 << 7; /* set bit 7 to indicate single-ended */ + } + if (range < 2) + adc_adjust = 0x8000; /* bipolar ranges (-5,5 .. -10,10 need to be adjusted -- that is.. they need to wrap around by adding 0x8000 */ + + if (chan % 2) { + command_byte |= 1 << 6; /* odd-numbered channels have bit 6 set */ + } + + /* select the channel, bits 4-5 == chan/2 */ + command_byte |= ((chan / 2) & 0x3) << 4; + + /* set the range, bits 2-3 */ + command_byte |= (range & 0x3) << 2; + + /* need to do this twice to make sure mux settled */ + outb(command_byte, iobase + iooffset + 2); /* chan/range/aref select */ + + adc_wait_ready(iobase + iooffset); /* wait for the adc to say it finised the conversion */ + + outb(command_byte, iobase + iooffset + 2); /* select the chan/range/aref AGAIN */ + + adc_wait_ready(iobase + iooffset); + + sample = inb(iobase + iooffset + 0); /* read data lo byte */ + sample |= inb(iobase + iooffset + 1) << 8; /* read data hi byte */ + sample += adc_adjust; /* adjustment .. munge data */ + data[n] = sample; + } + /* return the number of samples read/written */ + return n; +} + +static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + for (n = 0; n < insn->n; n++) { + unsigned chan = CR_CHAN(insn->chanspec); + if (chan < s->n_chan) + data[n] = subpriv->ao.shadow_samples[chan]; + } + return n; +} + +static int wait_dac_ready(unsigned long iobase) +{ + unsigned long retry = 100000L; + + /* This may seem like an absurd way to handle waiting and violates the + "no busy waiting" policy. The fact is that the hardware is + normally so fast that we usually only need one time through the loop + anyway. The longer timeout is for rare occasions and for detecting + non-existant hardware. */ + + while (retry--) { + if (inb(iobase + 3) & 0x80) + return 0; + + } + return 1; +} + +static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + unsigned iobase = subpriv->iobase, iooffset = 0; + + for (n = 0; n < insn->n; n++) { + unsigned chan = CR_CHAN(insn->chanspec), range = + CR_RANGE(insn->chanspec); + if (chan < s->n_chan) { + unsigned char command_byte = 0, range_byte = + range & ((1 << 4) - 1); + if (chan >= 4) + chan -= 4, iooffset += 4; + /* set the range.. */ + outb(range_byte, iobase + iooffset + 0); + outb(0, iobase + iooffset + 1); + + /* tell it to begin */ + command_byte = (chan << 1) | 0x60; + outb(command_byte, iobase + iooffset + 2); + + wait_dac_ready(iobase + iooffset); + + outb(data[n] & 0xff, iobase + iooffset + 0); /* low order byte */ + outb((data[n] >> 8) & 0xff, iobase + iooffset + 1); /* high order byte */ + command_byte = 0x70 | (chan << 1); /* set bit 4 of command byte to indicate data is loaded and trigger conversion */ + /* trigger converion */ + outb(command_byte, iobase + iooffset + 2); + + wait_dac_ready(iobase + iooffset); + + subpriv->ao.shadow_samples[chan] = data[n]; /* save to shadow register for ao_rinsn */ + } + } + return n; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver); diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c new file mode 100644 index 000000000000..4e7d8b6327fd --- /dev/null +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -0,0 +1,1101 @@ +/* + comedi/drivers/pcmuio.c + Driver for Winsystems PC-104 based 48-channel and 96-channel DIO boards. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2006 Calin A. Culianu + + 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: pcmuio +Description: A driver for the PCM-UIO48A and PCM-UIO96A boards from Winsystems. +Devices: [Winsystems] PCM-UIO48A (pcmuio48), PCM-UIO96A (pcmuio96) +Author: Calin Culianu +Updated: Fri, 13 Jan 2006 12:01:01 -0500 +Status: works + +A driver for the relatively straightforward-to-program PCM-UIO48A and +PCM-UIO96A boards from Winsystems. These boards use either one or two +(in the 96-DIO version) WS16C48 ASIC HighDensity I/O Chips (HDIO). +This chip is interesting in that each I/O line is individually +programmable for INPUT or OUTPUT (thus comedi_dio_config can be done +on a per-channel basis). Also, each chip supports edge-triggered +interrupts for the first 24 I/O lines. Of course, since the +96-channel version of the board has two ASICs, it can detect polarity +changes on up to 48 I/O lines. Since this is essentially an (non-PnP) +ISA board, I/O Address and IRQ selection are done through jumpers on +the board. You need to pass that information to this driver as the +first and second comedi_config option, respectively. Note that the +48-channel version uses 16 bytes of IO memory and the 96-channel +version uses 32-bytes (in case you are worried about conflicts). The +48-channel board is split into two 24-channel comedi subdevices. +The 96-channel board is split into 4 24-channel DIO subdevices. + +Note that IRQ support has been added, but it is untested. + +To use edge-detection IRQ support, pass the IRQs of both ASICS +(for the 96 channel version) or just 1 ASIC (for 48-channel version). +Then, use use comedi_commands with TRIG_NOW. +Your callback will be called each time an edge is triggered, and the data +values will be two sample_t's, which should be concatenated to form one +32-bit unsigned int. This value is the mask of channels that had +edges detected from your channel list. Note that the bits positions +in the mask correspond to positions in your chanlist when you specified +the command and *not* channel id's! + +To set the polarity of the edge-detection interrupts pass a nonzero value for +either CR_RANGE or CR_AREF for edge-up polarity, or a zero value for both +CR_RANGE and CR_AREF if you want edge-down polarity. + +In the 48-channel version: + +On subdev 0, the first 24 channels channels are edge-detect channels. + +In the 96-channel board you have the collowing channels that can do edge detection: + +subdev 0, channels 0-24 (first 24 channels of 1st ASIC) +subdev 2, channels 0-24 (first 24 channels of 2nd ASIC) + +Configuration Options: + [0] - I/O port base address + [1] - IRQ (for first ASIC, or first 24 channels) + [2] - IRQ for second ASIC (pcmuio96 only - IRQ for chans 48-72 .. can be the same as first irq!) +*/ + +#include "../comedidev.h" + +#include /* for PCI devices */ + +#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) ) +#define CHANS_PER_PORT 8 +#define PORTS_PER_ASIC 6 +#define INTR_PORTS_PER_ASIC 3 +#define MAX_CHANS_PER_SUBDEV 24 /* number of channels per comedi subdevice */ +#define PORTS_PER_SUBDEV (MAX_CHANS_PER_SUBDEV/CHANS_PER_PORT) +#define CHANS_PER_ASIC (CHANS_PER_PORT*PORTS_PER_ASIC) +#define INTR_CHANS_PER_ASIC 24 +#define INTR_PORTS_PER_SUBDEV (INTR_CHANS_PER_ASIC/CHANS_PER_PORT) +#define MAX_DIO_CHANS (PORTS_PER_ASIC*2*CHANS_PER_PORT) +#define MAX_ASICS (MAX_DIO_CHANS/CHANS_PER_ASIC) +#define SDEV_NO ((int)(s - dev->subdevices)) +#define CALC_N_SUBDEVS(nchans) ((nchans)/MAX_CHANS_PER_SUBDEV + (!!((nchans)%MAX_CHANS_PER_SUBDEV)) /*+ (nchans > INTR_CHANS_PER_ASIC ? 2 : 1)*/) +/* IO Memory sizes */ +#define ASIC_IOSIZE (0x10) +#define PCMUIO48_IOSIZE ASIC_IOSIZE +#define PCMUIO96_IOSIZE (ASIC_IOSIZE*2) + +/* Some offsets - these are all in the 16byte IO memory offset from + the base address. Note that there is a paging scheme to swap out + offsets 0x8-0xA using the PAGELOCK register. See the table below. + + Register(s) Pages R/W? Description + -------------------------------------------------------------- + REG_PORTx All R/W Read/Write/Configure IO + REG_INT_PENDING All ReadOnly Quickly see which INT_IDx has int. + REG_PAGELOCK All WriteOnly Select a page + REG_POLx Pg. 1 only WriteOnly Select edge-detection polarity + REG_ENABx Pg. 2 only WriteOnly Enable/Disable edge-detect. int. + REG_INT_IDx Pg. 3 only R/W See which ports/bits have ints. + */ +#define REG_PORT0 0x0 +#define REG_PORT1 0x1 +#define REG_PORT2 0x2 +#define REG_PORT3 0x3 +#define REG_PORT4 0x4 +#define REG_PORT5 0x5 +#define REG_INT_PENDING 0x6 +#define REG_PAGELOCK 0x7 /* page selector register, upper 2 bits select a page + and bits 0-5 are used to 'lock down' a particular + port above to make it readonly. */ +#define REG_POL0 0x8 +#define REG_POL1 0x9 +#define REG_POL2 0xA +#define REG_ENAB0 0x8 +#define REG_ENAB1 0x9 +#define REG_ENAB2 0xA +#define REG_INT_ID0 0x8 +#define REG_INT_ID1 0x9 +#define REG_INT_ID2 0xA + +#define NUM_PAGED_REGS 3 +#define NUM_PAGES 4 +#define FIRST_PAGED_REG 0x8 +#define REG_PAGE_BITOFFSET 6 +#define REG_LOCK_BITOFFSET 0 +#define REG_PAGE_MASK (~((0x1<board_ptr) + +/* this structure is for data unique to this subdevice. */ +struct pcmuio_subdev_private { + /* mapping of halfwords (bytes) in port/chanarray to iobase */ + unsigned long iobases[PORTS_PER_SUBDEV]; + + /* The below is only used for intr subdevices */ + struct { + int asic; /* if non-negative, this subdev has an interrupt asic */ + int first_chan; /* if nonnegative, the first channel id for + interrupts. */ + int num_asic_chans; /* the number of asic channels in this subdev + that have interrutps */ + int asic_chan; /* if nonnegative, the first channel id with + respect to the asic that has interrupts */ + int enabled_mask; /* subdev-relative channel mask for channels + we are interested in */ + int active; + int stop_count; + int continuous; + spinlock_t spinlock; + } intr; +}; + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct pcmuio_private { + struct { + unsigned char pagelock; /* current page and lock */ + unsigned char pol[NUM_PAGED_REGS]; /* shadow of POLx registers */ + unsigned char enab[NUM_PAGED_REGS]; /* shadow of ENABx registers */ + int num; + unsigned long iobase; + unsigned int irq; + spinlock_t spinlock; + } asics[MAX_ASICS]; + struct pcmuio_subdev_private *sprivs; +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct pcmuio_private *)dev->private) +#define subpriv ((struct pcmuio_subdev_private *)s->private) +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int pcmuio_detach(struct comedi_device * dev); + +static struct comedi_driver driver = { + driver_name:"pcmuio", + module:THIS_MODULE, + attach:pcmuio_attach, + detach:pcmuio_detach, +/* It is not necessary to implement the following members if you are + * writing a driver for a ISA PnP or PCI card */ + /* Most drivers will support multiple types of boards by + * having an array of board structures. These were defined + * in pcmuio_boards[] above. Note that the element 'name' + * was first in the structure -- Comedi uses this fact to + * extract the name of the board without knowing any details + * about the structure except for its length. + * When a device is attached (by comedi_config), the name + * of the device is given to Comedi, and Comedi tries to + * match it by going through the list of board names. If + * there is a match, the address of the pointer is put + * into dev->board_ptr and driver->attach() is called. + * + * Note that these are not necessary if you can determine + * the type of board in software. ISA PnP, PCI, and PCMCIA + * devices are such boards. + */ + board_name:&pcmuio_boards[0].name, + offset:sizeof(struct pcmuio_board), + num_names:sizeof(pcmuio_boards) / sizeof(struct pcmuio_board), +}; + +static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG); +static void pcmuio_stop_intr(struct comedi_device *, struct comedi_subdevice *); +static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s); +static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s); +static int pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); + +/* some helper functions to deal with specifics of this device's registers */ +static void init_asics(struct comedi_device * dev); /* sets up/clears ASIC chips to defaults */ +static void switch_page(struct comedi_device * dev, int asic, int page); +#ifdef notused +static void lock_port(struct comedi_device * dev, int asic, int port); +static void unlock_port(struct comedi_device * dev, int asic, int port); +#endif + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0; + unsigned long iobase; + unsigned int irq[MAX_ASICS]; + + iobase = it->options[0]; + irq[0] = it->options[1]; + irq[1] = it->options[2]; + + printk("comedi%d: %s: io: %lx ", dev->minor, driver.driver_name, + iobase); + + dev->iobase = iobase; + + if (!iobase || !request_region(iobase, + thisboard->num_asics * ASIC_IOSIZE, + driver.driver_name)) { + printk("I/O port conflict\n"); + return -EIO; + } + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct pcmuio_private)) < 0) { + printk("cannot allocate private data structure\n"); + return -ENOMEM; + } + + for (asic = 0; asic < MAX_ASICS; ++asic) { + devpriv->asics[asic].num = asic; + devpriv->asics[asic].iobase = dev->iobase + asic * ASIC_IOSIZE; + devpriv->asics[asic].irq = 0; /* this gets actually set at the end of + this function when we + comedi_request_irqs */ + spin_lock_init(&devpriv->asics[asic].spinlock); + } + + chans_left = CHANS_PER_ASIC * thisboard->num_asics; + n_subdevs = CALC_N_SUBDEVS(chans_left); + devpriv->sprivs = + kcalloc(n_subdevs, sizeof(struct pcmuio_subdev_private), GFP_KERNEL); + if (!devpriv->sprivs) { + printk("cannot allocate subdevice private data structures\n"); + return -ENOMEM; + } + /* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + * + * Allocate 2 subdevs (32 + 16 DIO lines) or 3 32 DIO subdevs for the + * 96-channel version of the board. + */ + if (alloc_subdevices(dev, n_subdevs) < 0) { + printk("cannot allocate subdevice data structures\n"); + return -ENOMEM; + } + + port = 0; + asic = 0; + for (sdev_no = 0; sdev_no < (int)dev->n_subdevices; ++sdev_no) { + int byte_no; + + s = dev->subdevices + sdev_no; + s->private = devpriv->sprivs + sdev_no; + s->maxdata = 1; + s->range_table = &range_digital; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->type = COMEDI_SUBD_DIO; + s->insn_bits = pcmuio_dio_insn_bits; + s->insn_config = pcmuio_dio_insn_config; + s->n_chan = MIN(chans_left, MAX_CHANS_PER_SUBDEV); + subpriv->intr.asic = -1; + subpriv->intr.first_chan = -1; + subpriv->intr.asic_chan = -1; + subpriv->intr.num_asic_chans = -1; + subpriv->intr.active = 0; + s->len_chanlist = 1; + + /* save the ioport address for each 'port' of 8 channels in the + subdevice */ + for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) { + if (port >= PORTS_PER_ASIC) { + port = 0; + ++asic; + thisasic_chanct = 0; + } + subpriv->iobases[byte_no] = + devpriv->asics[asic].iobase + port; + + if (thisasic_chanct < + CHANS_PER_PORT * INTR_PORTS_PER_ASIC + && subpriv->intr.asic < 0) { + /* this is an interrupt subdevice, so setup the struct */ + subpriv->intr.asic = asic; + subpriv->intr.active = 0; + subpriv->intr.stop_count = 0; + subpriv->intr.first_chan = byte_no * 8; + subpriv->intr.asic_chan = thisasic_chanct; + subpriv->intr.num_asic_chans = + s->n_chan - subpriv->intr.first_chan; + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->cancel = pcmuio_cancel; + s->do_cmd = pcmuio_cmd; + s->do_cmdtest = pcmuio_cmdtest; + s->len_chanlist = subpriv->intr.num_asic_chans; + } + thisasic_chanct += CHANS_PER_PORT; + } + spin_lock_init(&subpriv->intr.spinlock); + + chans_left -= s->n_chan; + + if (!chans_left) { + asic = 0; /* reset the asic to our first asic, to do intr subdevs */ + port = 0; + } + + } + + init_asics(dev); /* clear out all the registers, basically */ + + for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) { + if (irq[asic] + && comedi_request_irq(irq[asic], interrupt_pcmuio, + IRQF_SHARED, thisboard->name, dev)) { + int i; + /* unroll the allocated irqs.. */ + for (i = asic - 1; i >= 0; --i) { + comedi_free_irq(irq[i], dev); + devpriv->asics[i].irq = irq[i] = 0; + } + irq[asic] = 0; + } + devpriv->asics[asic].irq = irq[asic]; + } + + dev->irq = irq[0]; /* grr.. wish comedi dev struct supported multiple + irqs.. */ + + if (irq[0]) { + printk("irq: %u ", irq[0]); + if (irq[1] && thisboard->num_asics == 2) + printk("second ASIC irq: %u ", irq[1]); + } else { + printk("(IRQ mode disabled) "); + } + + printk("attached\n"); + + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int pcmuio_detach(struct comedi_device * dev) +{ + int i; + + printk("comedi%d: %s: remove\n", dev->minor, driver.driver_name); + if (dev->iobase) + release_region(dev->iobase, ASIC_IOSIZE * thisboard->num_asics); + + for (i = 0; i < MAX_ASICS; ++i) { + if (devpriv->asics[i].irq) + comedi_free_irq(devpriv->asics[i].irq, dev); + } + + if (devpriv && devpriv->sprivs) + kfree(devpriv->sprivs); + + return 0; +} + +/* DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write */ +static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int byte_no; + if (insn->n != 2) + return -EINVAL; + + /* NOTE: + reading a 0 means this channel was high + writine a 0 sets the channel high + reading a 1 means this channel was low + writing a 1 means set this channel low + + Therefore everything is always inverted. */ + + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + +#ifdef DAMMIT_ITS_BROKEN + /* DEBUG */ + printk("write mask: %08x data: %08x\n", data[0], data[1]); +#endif + + s->state = 0; + + for (byte_no = 0; byte_no < s->n_chan / CHANS_PER_PORT; ++byte_no) { + /* address of 8-bit port */ + unsigned long ioaddr = subpriv->iobases[byte_no], + /* bit offset of port in 32-bit doubleword */ + offset = byte_no * 8; + /* this 8-bit port's data */ + unsigned char byte = 0, + /* The write mask for this port (if any) */ + write_mask_byte = (data[0] >> offset) & 0xff, + /* The data byte for this port */ + data_byte = (data[1] >> offset) & 0xff; + + byte = inb(ioaddr); /* read all 8-bits for this port */ + +#ifdef DAMMIT_ITS_BROKEN + /* DEBUG */ + printk("byte %d wmb %02x db %02x offset %02d io %04x, data_in %02x ", byte_no, (unsigned)write_mask_byte, (unsigned)data_byte, offset, ioaddr, (unsigned)byte); +#endif + + if (write_mask_byte) { + /* this byte has some write_bits -- so set the output lines */ + byte &= ~write_mask_byte; /* clear bits for write mask */ + byte |= ~data_byte & write_mask_byte; /* set to inverted data_byte */ + /* Write out the new digital output state */ + outb(byte, ioaddr); + } +#ifdef DAMMIT_ITS_BROKEN + /* DEBUG */ + printk("data_out_byte %02x\n", (unsigned)byte); +#endif + /* save the digital input lines for this byte.. */ + s->state |= ((unsigned int)byte) << offset; + } + + /* now return the DIO lines to data[1] - note they came inverted! */ + data[1] = ~s->state; + +#ifdef DAMMIT_ITS_BROKEN + /* DEBUG */ + printk("s->state %08x data_out %08x\n", s->state, data[1]); +#endif + + return 2; +} + +/* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ +static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no = + chan % 8; + unsigned long ioaddr; + unsigned char byte; + + /* Compute ioaddr for this channel */ + ioaddr = subpriv->iobases[byte_no]; + + /* NOTE: + writing a 0 an IO channel's bit sets the channel to INPUT + and pulls the line high as well + + writing a 1 to an IO channel's bit pulls the line low + + All channels are implicitly always in OUTPUT mode -- but when + they are high they can be considered to be in INPUT mode.. + + Thus, we only force channels low if the config request was INPUT, + otherwise we do nothing to the hardware. */ + + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + /* save to io_bits -- don't actually do anything since + all input channels are also output channels... */ + s->io_bits |= 1 << chan; + break; + case INSN_CONFIG_DIO_INPUT: + /* write a 0 to the actual register representing the channel + to set it to 'input'. 0 means "float high". */ + byte = inb(ioaddr); + byte &= ~(1 << bit_no); + /**< set input channel to '0' */ + + /* write out byte -- this is the only time we actually affect the + hardware as all channels are implicitly output -- but input + channels are set to float-high */ + outb(byte, ioaddr); + + /* save to io_bits */ + s->io_bits &= ~(1 << chan); + break; + + case INSN_CONFIG_DIO_QUERY: + /* retreive from shadow register */ + data[1] = + (s-> + io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + + default: + return -EINVAL; + break; + } + + return insn->n; +} + +static void init_asics(struct comedi_device * dev) +{ /* sets up an + ASIC chip to defaults */ + int asic; + + for (asic = 0; asic < thisboard->num_asics; ++asic) { + int port, page; + unsigned long baseaddr = dev->iobase + asic * ASIC_IOSIZE; + + switch_page(dev, asic, 0); /* switch back to page 0 */ + + /* first, clear all the DIO port bits */ + for (port = 0; port < PORTS_PER_ASIC; ++port) + outb(0, baseaddr + REG_PORT0 + port); + + /* Next, clear all the paged registers for each page */ + for (page = 1; page < NUM_PAGES; ++page) { + int reg; + /* now clear all the paged registers */ + switch_page(dev, asic, page); + for (reg = FIRST_PAGED_REG; + reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg) + outb(0, baseaddr + reg); + } + + /* DEBUG set rising edge interrupts on port0 of both asics */ + /*switch_page(dev, asic, PAGE_POL); + outb(0xff, baseaddr + REG_POL0); + switch_page(dev, asic, PAGE_ENAB); + outb(0xff, baseaddr + REG_ENAB0); */ + /* END DEBUG */ + + switch_page(dev, asic, 0); /* switch back to default page 0 */ + + } +} + +static void switch_page(struct comedi_device * dev, int asic, int page) +{ + if (asic < 0 || asic >= thisboard->num_asics) + return; /* paranoia */ + if (page < 0 || page >= NUM_PAGES) + return; /* more paranoia */ + + devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK; + devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET; + + /* now write out the shadow register */ + outb(devpriv->asics[asic].pagelock, + dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK); +} + +#ifdef notused +static void lock_port(struct comedi_device * dev, int asic, int port) +{ + if (asic < 0 || asic >= thisboard->num_asics) + return; /* paranoia */ + if (port < 0 || port >= PORTS_PER_ASIC) + return; /* more paranoia */ + + devpriv->asics[asic].pagelock |= 0x1 << port; + /* now write out the shadow register */ + outb(devpriv->asics[asic].pagelock, + dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK); +} + +static void unlock_port(struct comedi_device * dev, int asic, int port) +{ + if (asic < 0 || asic >= thisboard->num_asics) + return; /* paranoia */ + if (port < 0 || port >= PORTS_PER_ASIC) + return; /* more paranoia */ + devpriv->asics[asic].pagelock &= ~(0x1 << port) | REG_LOCK_MASK; + /* now write out the shadow register */ + outb(devpriv->asics[asic].pagelock, + dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK); +} +#endif /* notused */ + +static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG) +{ + int asic, got1 = 0; + struct comedi_device *dev = (struct comedi_device *) d; + + for (asic = 0; asic < MAX_ASICS; ++asic) { + if (irq == devpriv->asics[asic].irq) { + unsigned long flags; + unsigned triggered = 0; + unsigned long iobase = devpriv->asics[asic].iobase; + /* it is an interrupt for ASIC #asic */ + unsigned char int_pend; + + comedi_spin_lock_irqsave(&devpriv->asics[asic].spinlock, + flags); + + int_pend = inb(iobase + REG_INT_PENDING) & 0x07; + + if (int_pend) { + int port; + for (port = 0; port < INTR_PORTS_PER_ASIC; + ++port) { + if (int_pend & (0x1 << port)) { + unsigned char + io_lines_with_edges = 0; + switch_page(dev, asic, + PAGE_INT_ID); + io_lines_with_edges = + inb(iobase + + REG_INT_ID0 + port); + + if (io_lines_with_edges) + /* clear pending interrupt */ + outb(0, iobase + + REG_INT_ID0 + + port); + + triggered |= + io_lines_with_edges << + port * 8; + } + } + + ++got1; + } + + comedi_spin_unlock_irqrestore(&devpriv->asics[asic]. + spinlock, flags); + + if (triggered) { + struct comedi_subdevice *s; + /* TODO here: dispatch io lines to subdevs with commands.. */ + printk("PCMUIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n", irq, asic, triggered); + for (s = dev->subdevices; + s < dev->subdevices + dev->n_subdevices; + ++s) { + if (subpriv->intr.asic == asic) { /* this is an interrupt subdev, and it matches this asic! */ + unsigned long flags; + unsigned oldevents; + + comedi_spin_lock_irqsave + (&subpriv->intr. + spinlock, flags); + + oldevents = s->async->events; + + if (subpriv->intr.active) { + unsigned mytrig = + ((triggered >> + subpriv-> + intr. + asic_chan) + & ((0x1 << subpriv->intr.num_asic_chans) - 1)) << subpriv->intr.first_chan; + if (mytrig & subpriv-> + intr. + enabled_mask) { + unsigned int val = + 0; + unsigned int n, + ch, len; + + len = s->async-> + cmd. + chanlist_len; + for (n = 0; + n < len; + n++) { + ch = CR_CHAN(s->async->cmd.chanlist[n]); + if (mytrig & (1U << ch)) { + val |= (1U << n); + } + } + /* Write the scan to the buffer. */ + if (comedi_buf_put(s->async, ((short *) & val)[0]) + && + comedi_buf_put + (s->async, ((short *) & val)[1])) { + s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); + } else { + /* Overflow! Stop acquisition!! */ + /* TODO: STOP_ACQUISITION_CALL_HERE!! */ + pcmuio_stop_intr + (dev, + s); + } + + /* Check for end of acquisition. */ + if (!subpriv-> + intr. + continuous) + { + /* stop_src == TRIG_COUNT */ + if (subpriv->intr.stop_count > 0) { + subpriv-> + intr. + stop_count--; + if (subpriv->intr.stop_count == 0) { + s->async->events |= COMEDI_CB_EOA; + /* TODO: STOP_ACQUISITION_CALL_HERE!! */ + pcmuio_stop_intr + (dev, + s); + } + } + } + } + } + + comedi_spin_unlock_irqrestore + (&subpriv->intr. + spinlock, flags); + + if (oldevents != + s->async->events) { + comedi_event(dev, s); + } + + } + + } + } + + } + } + if (!got1) + return IRQ_NONE; /* interrupt from other source */ + return IRQ_HANDLED; +} + +static void pcmuio_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s) +{ + int nports, firstport, asic, port; + + if ((asic = subpriv->intr.asic) < 0) + return; /* not an interrupt subdev */ + + subpriv->intr.enabled_mask = 0; + subpriv->intr.active = 0; + s->async->inttrig = 0; + nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT; + firstport = subpriv->intr.asic_chan / CHANS_PER_PORT; + switch_page(dev, asic, PAGE_ENAB); + for (port = firstport; port < firstport + nports; ++port) { + /* disable all intrs for this subdev.. */ + outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port); + } +} + +static int pcmuio_start_intr(struct comedi_device * dev, struct comedi_subdevice * s) +{ + if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) { + /* An empty acquisition! */ + s->async->events |= COMEDI_CB_EOA; + subpriv->intr.active = 0; + return 1; + } else { + unsigned bits = 0, pol_bits = 0, n; + int nports, firstport, asic, port; + struct comedi_cmd *cmd = &s->async->cmd; + + if ((asic = subpriv->intr.asic) < 0) + return 1; /* not an interrupt + subdev */ + subpriv->intr.enabled_mask = 0; + subpriv->intr.active = 1; + nports = subpriv->intr.num_asic_chans / CHANS_PER_PORT; + firstport = subpriv->intr.asic_chan / CHANS_PER_PORT; + if (cmd->chanlist) { + for (n = 0; n < cmd->chanlist_len; n++) { + bits |= (1U << CR_CHAN(cmd->chanlist[n])); + pol_bits |= (CR_AREF(cmd->chanlist[n]) + || CR_RANGE(cmd->chanlist[n]) ? 1U : 0U) + << CR_CHAN(cmd->chanlist[n]); + } + } + bits &= ((0x1 << subpriv->intr.num_asic_chans) - + 1) << subpriv->intr.first_chan; + subpriv->intr.enabled_mask = bits; + + switch_page(dev, asic, PAGE_ENAB); + for (port = firstport; port < firstport + nports; ++port) { + unsigned enab = + bits >> (subpriv->intr.first_chan + (port - + firstport) * 8) & 0xff, pol = + pol_bits >> (subpriv->intr.first_chan + (port - + firstport) * 8) & 0xff; + /* set enab intrs for this subdev.. */ + outb(enab, + devpriv->asics[asic].iobase + REG_ENAB0 + port); + switch_page(dev, asic, PAGE_POL); + outb(pol, + devpriv->asics[asic].iobase + REG_ENAB0 + port); + } + } + return 0; +} + +static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + unsigned long flags; + + comedi_spin_lock_irqsave(&subpriv->intr.spinlock, flags); + if (subpriv->intr.active) + pcmuio_stop_intr(dev, s); + comedi_spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + + return 0; +} + +/* + * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. + */ +static int +pcmuio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s, + unsigned int trignum) +{ + unsigned long flags; + int event = 0; + + if (trignum != 0) + return -EINVAL; + + comedi_spin_lock_irqsave(&subpriv->intr.spinlock, flags); + s->async->inttrig = 0; + if (subpriv->intr.active) { + event = pcmuio_start_intr(dev, s); + } + comedi_spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + + if (event) { + comedi_event(dev, s); + } + + return 1; +} + +/* + * 'do_cmd' function for an 'INTERRUPT' subdevice. + */ +static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct comedi_cmd *cmd = &s->async->cmd; + unsigned long flags; + int event = 0; + + comedi_spin_lock_irqsave(&subpriv->intr.spinlock, flags); + subpriv->intr.active = 1; + + /* Set up end of acquisition. */ + switch (cmd->stop_src) { + case TRIG_COUNT: + subpriv->intr.continuous = 0; + subpriv->intr.stop_count = cmd->stop_arg; + break; + default: + /* TRIG_NONE */ + subpriv->intr.continuous = 1; + subpriv->intr.stop_count = 0; + break; + } + + /* Set up start of acquisition. */ + switch (cmd->start_src) { + case TRIG_INT: + s->async->inttrig = pcmuio_inttrig_start_intr; + break; + default: + /* TRIG_NOW */ + event = pcmuio_start_intr(dev, s); + break; + } + comedi_spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + + if (event) { + comedi_event(dev, s); + } + + return 0; +} + +/* + * 'do_cmdtest' function for an 'INTERRUPT' subdevice. + */ +static int +pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd) +{ + int err = 0; + unsigned int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + tmp = cmd->start_src; + cmd->start_src &= (TRIG_NOW | TRIG_INT); + 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_NOW; + 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_COUNT | TRIG_NONE); + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* these tests are true if more than one _src bit is set */ + if ((cmd->start_src & (cmd->start_src - 1)) != 0) + err++; + if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) + err++; + if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) + err++; + if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) + err++; + if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */ + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } + + /* cmd->scan_begin_src == TRIG_EXT */ + if (cmd->scan_begin_arg != 0) { + cmd->scan_begin_arg = 0; + err++; + } + + /* cmd->convert_src == TRIG_NOW */ + if (cmd->convert_arg != 0) { + cmd->convert_arg = 0; + err++; + } + + /* cmd->scan_end_src == TRIG_COUNT */ + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + + switch (cmd->stop_src) { + case TRIG_COUNT: + /* any count allowed */ + break; + case TRIG_NONE: + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + break; + default: + break; + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + /* if (err) return 4; */ + + return 0; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver); diff --git a/drivers/staging/comedi/drivers/plx9052.h b/drivers/staging/comedi/drivers/plx9052.h new file mode 100644 index 000000000000..5894739ff426 --- /dev/null +++ b/drivers/staging/comedi/drivers/plx9052.h @@ -0,0 +1,86 @@ +/* + comedi/drivers/plx9052.h + Definitions for the PLX-9052 PCI interface chip + + Copyright (C) 2002 MEV Ltd. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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 _PLX9052_H_ +#define _PLX9052_H_ + +/* + * PLX PCI9052 INTCSR register. + */ +#define PLX9052_INTCSR 0x4C /* Offset in Local Configuration Registers */ +/* Local Interrupt 1 Enable */ +#define PLX9052_INTCSR_LI1ENAB_MASK 0x0001 +#define PLX9052_INTCSR_LI1ENAB_DISABLED 0x0000 +#define PLX9052_INTCSR_LI1ENAB_ENABLED 0x0001 +/* Local Interrupt 1 Polarity */ +#define PLX9052_INTCSR_LI1POL_MASK 0x0002 +#define PLX9052_INTCSR_LI1POL_LOW 0x0000 +#define PLX9052_INTCSR_LI1POL_HIGH 0x0002 +/* Local Interrupt 1 Status (read-only) */ +#define PLX9052_INTCSR_LI1STAT_MASK 0x0004 +#define PLX9052_INTCSR_LI1STAT_INACTIVE 0x0000 +#define PLX9052_INTCSR_LI1STAT_ACTIVE 0x0004 +/* Local Interrupt 2 Enable */ +#define PLX9052_INTCSR_LI2ENAB_MASK 0x0008 +#define PLX9052_INTCSR_LI2ENAB_DISABLED 0x0000 +#define PLX9052_INTCSR_LI2ENAB_ENABLED 0x0008 +/* Local Interrupt 2 Polarity */ +#define PLX9052_INTCSR_LI2POL_MASK 0x0010 +#define PLX9052_INTCSR_LI2POL_LOW 0x0000 +#define PLX9052_INTCSR_LI2POL_HIGH 0x0010 +/* Local Interrupt 2 Status (read-only) */ +#define PLX9052_INTCSR_LI2STAT_MASK 0x0020 +#define PLX9052_INTCSR_LI2STAT_INACTIVE 0x0000 +#define PLX9052_INTCSR_LI2STAT_ACTIVE 0x0020 +/* PCI Interrupt Enable */ +#define PLX9052_INTCSR_PCIENAB_MASK 0x0040 +#define PLX9052_INTCSR_PCIENAB_DISABLED 0x0000 +#define PLX9052_INTCSR_PCIENAB_ENABLED 0x0040 +/* Software Interrupt */ +#define PLX9052_INTCSR_SOFTINT_MASK 0x0080 +#define PLX9052_INTCSR_SOFTINT_UNASSERTED 0x0000 +#define PLX9052_INTCSR_SOFTINT_ASSERTED 0x0080 +/* Local Interrupt 1 Select Enable */ +#define PLX9052_INTCSR_LI1SEL_MASK 0x0100 +#define PLX9052_INTCSR_LI1SEL_LEVEL 0x0000 +#define PLX9052_INTCSR_LI1SEL_EDGE 0x0100 +/* Local Interrupt 2 Select Enable */ +#define PLX9052_INTCSR_LI2SEL_MASK 0x0200 +#define PLX9052_INTCSR_LI2SEL_LEVEL 0x0000 +#define PLX9052_INTCSR_LI2SEL_EDGE 0x0200 +/* Local Edge Triggerable Interrupt 1 Clear Bit */ +#define PLX9052_INTCSR_LI1CLRINT_MASK 0x0400 +#define PLX9052_INTCSR_LI1CLRINT_UNASSERTED 0x0000 +#define PLX9052_INTCSR_LI1CLRINT_ASSERTED 0x0400 +/* Local Edge Triggerable Interrupt 2 Clear Bit */ +#define PLX9052_INTCSR_LI2CLRINT_MASK 0x0800 +#define PLX9052_INTCSR_LI2CLRINT_UNASSERTED 0x0000 +#define PLX9052_INTCSR_LI2CLRINT_ASSERTED 0x0800 +/* ISA Interface Mode Enable (read-only over PCI bus) */ +#define PLX9052_INTCSR_ISAMODE_MASK 0x1000 +#define PLX9052_INTCSR_ISAMODE_DISABLED 0x0000 +#define PLX9052_INTCSR_ISAMODE_ENABLED 0x1000 + +#endif /* _PLX9052_H_ */ diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h index a5a1a6808c5d..9231ba802030 100644 --- a/drivers/staging/comedi/drivers/plx9080.h +++ b/drivers/staging/comedi/drivers/plx9080.h @@ -27,7 +27,7 @@ #ifndef __COMEDI_PLX9080_H #define __COMEDI_PLX9080_H -// descriptor block used for chained dma transfers +/* descriptor block used for chained dma transfers */ struct plx_dma_desc { volatile uint32_t pci_start_addr; volatile uint32_t local_start_addr; @@ -52,14 +52,14 @@ struct plx_dma_desc { #define LRNG_ANY32 0x00000000 /* Locate anywhere in 32 bit */ #define LRNG_LT1MB 0x00000002 /* Locate in 1st meg */ #define LRNG_ANY64 0x00000004 /* Locate anywhere in 64 bit */ -#define LRNG_MEM_MASK 0xfffffff0 // bits that specify range for memory io -#define LRNG_IO_MASK 0xfffffffa // bits that specify range for normal io +#define LRNG_MEM_MASK 0xfffffff0 /* bits that specify range for memory io */ +#define LRNG_IO_MASK 0xfffffffa /* bits that specify range for normal io */ #define PLX_LAS0MAP_REG 0x0004 /* L, Local Addr Space 0 Remap Register */ #define PLX_LAS1MAP_REG 0x00f4 /* L, Local Addr Space 1 Remap Register */ #define LMAP_EN 0x00000001 /* Enable slave decode */ -#define LMAP_MEM_MASK 0xfffffff0 // bits that specify decode for memory io -#define LMAP_IO_MASK 0xfffffffa // bits that specify decode bits for normal io +#define LMAP_MEM_MASK 0xfffffff0 /* bits that specify decode for memory io */ +#define LMAP_IO_MASK 0xfffffffa /* bits that specify decode bits for normal io */ /* Mode/Arbitration Register. */ @@ -169,7 +169,7 @@ enum bigend_bits { #define ICS_AERR 0x00000001 /* Assert LSERR on ABORT */ #define ICS_PERR 0x00000002 /* Assert LSERR on Parity Error */ #define ICS_SERR 0x00000004 /* Generate PCI SERR# */ -#define ICS_MBIE 0x00000008 // mailbox interrupt enable +#define ICS_MBIE 0x00000008 /* mailbox interrupt enable */ #define ICS_PIE 0x00000100 /* PCI Interrupt Enable */ #define ICS_PDIE 0x00000200 /* PCI Doorbell Interrupt Enable */ #define ICS_PAIE 0x00000400 /* PCI Abort Interrupt Enable */ @@ -190,7 +190,7 @@ enum bigend_bits { #define ICS_TA_DMA0 0x02000000 /* Target Abort - DMA #0 */ #define ICS_TA_DMA1 0x04000000 /* Target Abort - DMA #1 */ #define ICS_TA_RA 0x08000000 /* Target Abort - Retry Timeout */ -#define ICS_MBIA(x) (0x10000000 << ((x) & 0x3)) // mailbox x is active +#define ICS_MBIA(x) (0x10000000 << ((x) & 0x3)) /* mailbox x is active */ #define PLX_CONTROL_REG 0x006C /* L, EEPROM Cntl & PCI Cmd Codes */ #define CTL_RDMA 0x0000000E /* DMA Read Command */ @@ -208,51 +208,51 @@ enum bigend_bits { #define CTL_RESET 0x40000000 /* !! Adapter Reset !! */ #define CTL_READY 0x80000000 /* Local Init Done */ -#define PLX_ID_REG 0x70 // hard-coded plx vendor and device ids +#define PLX_ID_REG 0x70 /* hard-coded plx vendor and device ids */ -#define PLX_REVISION_REG 0x74 // silicon revision +#define PLX_REVISION_REG 0x74 /* silicon revision */ -#define PLX_DMA0_MODE_REG 0x80 // dma channel 0 mode register -#define PLX_DMA1_MODE_REG 0x94 // dma channel 0 mode register +#define PLX_DMA0_MODE_REG 0x80 /* dma channel 0 mode register */ +#define PLX_DMA1_MODE_REG 0x94 /* dma channel 0 mode register */ #define PLX_LOCAL_BUS_16_WIDE_BITS 0x1 #define PLX_LOCAL_BUS_32_WIDE_BITS 0x3 #define PLX_LOCAL_BUS_WIDTH_MASK 0x3 -#define PLX_DMA_EN_READYIN_BIT 0x40 // enable ready in input -#define PLX_EN_BTERM_BIT 0x80 // enable BTERM# input -#define PLX_DMA_LOCAL_BURST_EN_BIT 0x100 // enable local burst mode -#define PLX_EN_CHAIN_BIT 0x200 // enables chaining -#define PLX_EN_DMA_DONE_INTR_BIT 0x400 // enables interrupt on dma done -#define PLX_LOCAL_ADDR_CONST_BIT 0x800 // hold local address constant (don't increment) -#define PLX_DEMAND_MODE_BIT 0x1000 // enables demand-mode for dma transfer +#define PLX_DMA_EN_READYIN_BIT 0x40 /* enable ready in input */ +#define PLX_EN_BTERM_BIT 0x80 /* enable BTERM# input */ +#define PLX_DMA_LOCAL_BURST_EN_BIT 0x100 /* enable local burst mode */ +#define PLX_EN_CHAIN_BIT 0x200 /* enables chaining */ +#define PLX_EN_DMA_DONE_INTR_BIT 0x400 /* enables interrupt on dma done */ +#define PLX_LOCAL_ADDR_CONST_BIT 0x800 /* hold local address constant (don't increment) */ +#define PLX_DEMAND_MODE_BIT 0x1000 /* enables demand-mode for dma transfer */ #define PLX_EOT_ENABLE_BIT 0x4000 #define PLX_STOP_MODE_BIT 0x8000 -#define PLX_DMA_INTR_PCI_BIT 0x20000 // routes dma interrupt to pci bus (instead of local bus) +#define PLX_DMA_INTR_PCI_BIT 0x20000 /* routes dma interrupt to pci bus (instead of local bus) */ -#define PLX_DMA0_PCI_ADDRESS_REG 0x84 // pci address that dma transfers start at +#define PLX_DMA0_PCI_ADDRESS_REG 0x84 /* pci address that dma transfers start at */ #define PLX_DMA1_PCI_ADDRESS_REG 0x98 -#define PLX_DMA0_LOCAL_ADDRESS_REG 0x88 // local address that dma transfers start at +#define PLX_DMA0_LOCAL_ADDRESS_REG 0x88 /* local address that dma transfers start at */ #define PLX_DMA1_LOCAL_ADDRESS_REG 0x9c -#define PLX_DMA0_TRANSFER_SIZE_REG 0x8c // number of bytes to transfer (first 23 bits) +#define PLX_DMA0_TRANSFER_SIZE_REG 0x8c /* number of bytes to transfer (first 23 bits) */ #define PLX_DMA1_TRANSFER_SIZE_REG 0xa0 -#define PLX_DMA0_DESCRIPTOR_REG 0x90 // descriptor pointer register +#define PLX_DMA0_DESCRIPTOR_REG 0x90 /* descriptor pointer register */ #define PLX_DMA1_DESCRIPTOR_REG 0xa4 -#define PLX_DESC_IN_PCI_BIT 0x1 // descriptor is located in pci space (not local space) -#define PLX_END_OF_CHAIN_BIT 0x2 // end of chain bit -#define PLX_INTR_TERM_COUNT 0x4 // interrupt when this descriptor's transfer is finished -#define PLX_XFER_LOCAL_TO_PCI 0x8 // transfer from local to pci bus (not pci to local) +#define PLX_DESC_IN_PCI_BIT 0x1 /* descriptor is located in pci space (not local space) */ +#define PLX_END_OF_CHAIN_BIT 0x2 /* end of chain bit */ +#define PLX_INTR_TERM_COUNT 0x4 /* interrupt when this descriptor's transfer is finished */ +#define PLX_XFER_LOCAL_TO_PCI 0x8 /* transfer from local to pci bus (not pci to local) */ -#define PLX_DMA0_CS_REG 0xa8 // command status register +#define PLX_DMA0_CS_REG 0xa8 /* command status register */ #define PLX_DMA1_CS_REG 0xa9 -#define PLX_DMA_EN_BIT 0x1 // enable dma channel -#define PLX_DMA_START_BIT 0x2 // start dma transfer -#define PLX_DMA_ABORT_BIT 0x4 // abort dma transfer -#define PLX_CLEAR_DMA_INTR_BIT 0x8 // clear dma interrupt -#define PLX_DMA_DONE_BIT 0x10 // transfer done status bit +#define PLX_DMA_EN_BIT 0x1 /* enable dma channel */ +#define PLX_DMA_START_BIT 0x2 /* start dma transfer */ +#define PLX_DMA_ABORT_BIT 0x4 /* abort dma transfer */ +#define PLX_CLEAR_DMA_INTR_BIT 0x8 /* clear dma interrupt */ +#define PLX_DMA_DONE_BIT 0x10 /* transfer done status bit */ -#define PLX_DMA0_THRESHOLD_REG 0xb0 // command status register +#define PLX_DMA0_THRESHOLD_REG 0xb0 /* command status register */ /* * Accesses near the end of memory can cause the PLX chip @@ -392,12 +392,12 @@ static inline int plx9080_abort_dma(void *iobase, unsigned int channel) else dma_cs_addr = iobase + PLX_DMA0_CS_REG; - // abort dma transfer if necessary + /* abort dma transfer if necessary */ dma_status = readb(dma_cs_addr); - if ((dma_status & PLX_DMA_EN_BIT) == 0) { + if ((dma_status & PLX_DMA_EN_BIT) == 0) return 0; - } - // wait to make sure done bit is zero + + /* wait to make sure done bit is zero */ for (i = 0; (dma_status & PLX_DMA_DONE_BIT) && i < timeout; i++) { comedi_udelay(1); dma_status = readb(dma_cs_addr); @@ -408,9 +408,9 @@ static inline int plx9080_abort_dma(void *iobase, unsigned int channel) channel); return -ETIMEDOUT; } - // disable and abort channel + /* disable and abort channel */ writeb(PLX_DMA_ABORT_BIT, dma_cs_addr); - // wait for dma done bit + /* wait for dma done bit */ dma_status = readb(dma_cs_addr); for (i = 0; (dma_status & PLX_DMA_DONE_BIT) == 0 && i < timeout; i++) { comedi_udelay(1); diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c new file mode 100644 index 000000000000..8a0bf6854939 --- /dev/null +++ b/drivers/staging/comedi/drivers/poc.c @@ -0,0 +1,247 @@ +/* + comedi/drivers/poc.c + Mini-drivers for POC (Piece of Crap) boards + Copyright (C) 2000 Frank Mori Hess + Copyright (C) 2001 David A. Schleef + + 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: poc +Description: Generic driver for very simple devices +Author: ds +Devices: [Keithley Metrabyte] DAC-02 (dac02), [Advantech] PCL-733 (pcl733), + PCL-734 (pcl734) +Updated: Sat, 16 Mar 2002 17:34:48 -0800 +Status: unknown + +This driver is indended to support very simple ISA-based devices, +including: + dac02 - Keithley DAC-02 analog output board + pcl733 - Advantech PCL-733 + pcl734 - Advantech PCL-734 + +Configuration options: + [0] - I/O port base +*/ + +#include "../comedidev.h" + +#include + +static int poc_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int poc_detach(struct comedi_device * dev); +static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pcl733_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int pcl734_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +struct boarddef_struct { + const char *name; + unsigned int iosize; + int (*setup) (struct comedi_device *); + int type; + int n_chan; + int n_bits; + int (*winsn) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + int (*rinsn) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + int (*insnbits) (struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, + unsigned int *); + const struct comedi_lrange *range; +}; +static const struct boarddef_struct boards[] = { + { + name: "dac02", + iosize: 8, + //setup: dac02_setup, + type: COMEDI_SUBD_AO, + n_chan: 2, + n_bits: 12, + winsn: dac02_ao_winsn, + rinsn: readback_insn, + range: &range_unknown, + }, + { + name: "pcl733", + iosize: 4, + type: COMEDI_SUBD_DI, + n_chan: 32, + n_bits: 1, + insnbits:pcl733_insn_bits, + range: &range_digital, + }, + { + name: "pcl734", + iosize: 4, + type: COMEDI_SUBD_DO, + n_chan: 32, + n_bits: 1, + insnbits:pcl734_insn_bits, + range: &range_digital, + }, +}; + +#define n_boards (sizeof(boards)/sizeof(boards[0])) +#define this_board ((const struct boarddef_struct *)dev->board_ptr) + +static struct comedi_driver driver_poc = { + driver_name:"poc", + module:THIS_MODULE, + attach:poc_attach, + detach:poc_detach, + board_name:&boards[0].name, + num_names:n_boards, + offset:sizeof(boards[0]), +}; + +static int poc_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + unsigned long iobase; + unsigned int iosize; + + iobase = it->options[0]; + printk("comedi%d: poc: using %s iobase 0x%lx\n", dev->minor, + this_board->name, iobase); + + dev->board_name = this_board->name; + + if (iobase == 0) { + printk("io base address required\n"); + return -EINVAL; + } + + iosize = this_board->iosize; + /* check if io addresses are available */ + if (!request_region(iobase, iosize, "dac02")) { + printk("I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase, iobase + iosize - 1); + return -EIO; + } + dev->iobase = iobase; + + if (alloc_subdevices(dev, 1) < 0) + return -ENOMEM; + if (alloc_private(dev, sizeof(unsigned int) * this_board->n_chan) < 0) + return -ENOMEM; + + /* analog output subdevice */ + s = dev->subdevices + 0; + s->type = this_board->type; + s->n_chan = this_board->n_chan; + s->maxdata = (1 << this_board->n_bits) - 1; + s->range_table = this_board->range; + s->insn_write = this_board->winsn; + s->insn_read = this_board->rinsn; + s->insn_bits = this_board->insnbits; + if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO) { + s->subdev_flags = SDF_WRITABLE; + } + + return 0; +} + +static int poc_detach(struct comedi_device * dev) +{ + /* only free stuff if it has been allocated by _attach */ + if (dev->iobase) + release_region(dev->iobase, this_board->iosize); + + printk("comedi%d: dac02: remove\n", dev->minor); + + return 0; +} + +static int readback_insn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan; + + chan = CR_CHAN(insn->chanspec); + data[0] = ((unsigned int *) dev->private)[chan]; + + return 1; +} + +/* DAC-02 registers */ +#define DAC02_LSB(a) (2 * a) +#define DAC02_MSB(a) (2 * a + 1) + +static int dac02_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int temp; + int chan; + int output; + + chan = CR_CHAN(insn->chanspec); + ((unsigned int *) dev->private)[chan] = data[0]; + output = data[0]; +#ifdef wrong + // convert to complementary binary if range is bipolar + if ((CR_RANGE(insn->chanspec) & 0x2) == 0) + output = ~output; +#endif + temp = (output << 4) & 0xf0; + outb(temp, dev->iobase + DAC02_LSB(chan)); + temp = (output >> 4) & 0xff; + outb(temp, dev->iobase + DAC02_MSB(chan)); + + return 1; +} + +static int pcl733_insn_bits(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 + 0); + data[1] |= (inb(dev->iobase + 1) << 8); + data[1] |= (inb(dev->iobase + 2) << 16); + data[1] |= (inb(dev->iobase + 3) << 24); + + return 2; +} + +static int pcl734_insn_bits(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] >> 0) & 0xff) + outb((s->state >> 0) & 0xff, dev->iobase + 0); + if ((data[0] >> 8) & 0xff) + outb((s->state >> 8) & 0xff, dev->iobase + 1); + if ((data[0] >> 16) & 0xff) + outb((s->state >> 16) & 0xff, dev->iobase + 2); + if ((data[0] >> 24) & 0xff) + outb((s->state >> 24) & 0xff, dev->iobase + 3); + } + data[1] = s->state; + + return 2; +} + +COMEDI_INITCLEANUP(driver_poc); diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c new file mode 100644 index 000000000000..795c4522867f --- /dev/null +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -0,0 +1,1363 @@ +/*====================================================================== + + comedi/drivers/quatech_daqp_cs.c + + Quatech DAQP PCMCIA data capture cards COMEDI client driver + Copyright (C) 2000, 2003 Brent Baccala + The DAQP interface code in this file is released into the public domain. + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998 David A. Schleef + http://www.comedi.org/ + + quatech_daqp_cs.c 1.10 + + Documentation for the DAQP PCMCIA cards can be found on Quatech's site: + + ftp://ftp.quatech.com/Manuals/daqp-208.pdf + + This manual is for both the DAQP-208 and the DAQP-308. + + What works: + + - A/D conversion + - 8 channels + - 4 gain ranges + - ground ref or differential + - single-shot and timed both supported + - D/A conversion, single-shot + - digital I/O + + What doesn't: + + - any kind of triggering - external or D/A channel 1 + - the card's optional expansion board + - the card's timer (for anything other than A/D conversion) + - D/A update modes other than immediate (i.e, timed) + - fancier timing modes + - setting card's FIFO buffer thresholds to anything but default + +======================================================================*/ + +/* +Driver: quatech_daqp_cs +Description: Quatech DAQP PCMCIA data capture cards +Author: Brent Baccala +Status: works +Devices: [Quatech] DAQP-208 (daqp), DAQP-308 +*/ + +#include "../comedidev.h" + +#include +#include +#include +#include +#include + +/* + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + you do not define PCMCIA_DEBUG at all, all the debug code will be + left out. If you compile with PCMCIA_DEBUG=0, the debug code will + be present but disabled -- but it can then be enabled for specific + modules at load time with a 'pc_debug=#' option to insmod. +*/ + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +module_param(pc_debug, int, 0644); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = "quatech_daqp_cs.c 1.10 2003/04/21 (Brent Baccala)"; +#else +#define DEBUG(n, args...) +#endif + +/* Maximum number of separate DAQP devices we'll allow */ +#define MAX_DEV 4 + +struct local_info_t { + struct pcmcia_device *link; + dev_node_t node; + int stop; + int table_index; + char board_name[32]; + + enum { semaphore, buffer } interrupt_mode; + + struct semaphore eos; + + struct comedi_device *dev; + struct comedi_subdevice *s; + int count; +}; + +/* A list of "instances" of the device. */ + +static struct local_info_t *dev_table[MAX_DEV] = { NULL, /* ... */ }; + +/* The DAQP communicates with the system through a 16 byte I/O window. */ + +#define DAQP_FIFO_SIZE 4096 + +#define DAQP_FIFO 0 +#define DAQP_SCANLIST 1 +#define DAQP_CONTROL 2 +#define DAQP_STATUS 2 +#define DAQP_DIGITAL_IO 3 +#define DAQP_PACER_LOW 4 +#define DAQP_PACER_MID 5 +#define DAQP_PACER_HIGH 6 +#define DAQP_COMMAND 7 +#define DAQP_DA 8 +#define DAQP_TIMER 10 +#define DAQP_AUX 15 + +#define DAQP_SCANLIST_DIFFERENTIAL 0x4000 +#define DAQP_SCANLIST_GAIN(x) ((x)<<12) +#define DAQP_SCANLIST_CHANNEL(x) ((x)<<8) +#define DAQP_SCANLIST_START 0x0080 +#define DAQP_SCANLIST_EXT_GAIN(x) ((x)<<4) +#define DAQP_SCANLIST_EXT_CHANNEL(x) (x) + +#define DAQP_CONTROL_PACER_100kHz 0xc0 +#define DAQP_CONTROL_PACER_1MHz 0x80 +#define DAQP_CONTROL_PACER_5MHz 0x40 +#define DAQP_CONTROL_PACER_EXTERNAL 0x00 +#define DAQP_CONTORL_EXPANSION 0x20 +#define DAQP_CONTROL_EOS_INT_ENABLE 0x10 +#define DAQP_CONTROL_FIFO_INT_ENABLE 0x08 +#define DAQP_CONTROL_TRIGGER_ONESHOT 0x00 +#define DAQP_CONTROL_TRIGGER_CONTINUOUS 0x04 +#define DAQP_CONTROL_TRIGGER_INTERNAL 0x00 +#define DAQP_CONTROL_TRIGGER_EXTERNAL 0x02 +#define DAQP_CONTROL_TRIGGER_RISING 0x00 +#define DAQP_CONTROL_TRIGGER_FALLING 0x01 + +#define DAQP_STATUS_IDLE 0x80 +#define DAQP_STATUS_RUNNING 0x40 +#define DAQP_STATUS_EVENTS 0x38 +#define DAQP_STATUS_DATA_LOST 0x20 +#define DAQP_STATUS_END_OF_SCAN 0x10 +#define DAQP_STATUS_FIFO_THRESHOLD 0x08 +#define DAQP_STATUS_FIFO_FULL 0x04 +#define DAQP_STATUS_FIFO_NEARFULL 0x02 +#define DAQP_STATUS_FIFO_EMPTY 0x01 + +#define DAQP_COMMAND_ARM 0x80 +#define DAQP_COMMAND_RSTF 0x40 +#define DAQP_COMMAND_RSTQ 0x20 +#define DAQP_COMMAND_STOP 0x10 +#define DAQP_COMMAND_LATCH 0x08 +#define DAQP_COMMAND_100kHz 0x00 +#define DAQP_COMMAND_50kHz 0x02 +#define DAQP_COMMAND_25kHz 0x04 +#define DAQP_COMMAND_FIFO_DATA 0x01 +#define DAQP_COMMAND_FIFO_PROGRAM 0x00 + +#define DAQP_AUX_TRIGGER_TTL 0x00 +#define DAQP_AUX_TRIGGER_ANALOG 0x80 +#define DAQP_AUX_TRIGGER_PRETRIGGER 0x40 +#define DAQP_AUX_TIMER_INT_ENABLE 0x20 +#define DAQP_AUX_TIMER_RELOAD 0x00 +#define DAQP_AUX_TIMER_PAUSE 0x08 +#define DAQP_AUX_TIMER_GO 0x10 +#define DAQP_AUX_TIMER_GO_EXTERNAL 0x18 +#define DAQP_AUX_TIMER_EXTERNAL_SRC 0x04 +#define DAQP_AUX_TIMER_INTERNAL_SRC 0x00 +#define DAQP_AUX_DA_DIRECT 0x00 +#define DAQP_AUX_DA_OVERFLOW 0x01 +#define DAQP_AUX_DA_EXTERNAL 0x02 +#define DAQP_AUX_DA_PACER 0x03 + +#define DAQP_AUX_RUNNING 0x80 +#define DAQP_AUX_TRIGGERED 0x40 +#define DAQP_AUX_DA_BUFFER 0x20 +#define DAQP_AUX_TIMER_OVERFLOW 0x10 +#define DAQP_AUX_CONVERSION 0x08 +#define DAQP_AUX_DATA_LOST 0x04 +#define DAQP_AUX_FIFO_NEARFULL 0x02 +#define DAQP_AUX_FIFO_EMPTY 0x01 + +/* These range structures tell COMEDI how the sample values map to + * voltages. The A/D converter has four ranges: +/- 10V through + * +/- 1.25V, and the D/A converter has only one: +/- 5V. + */ + +static const struct comedi_lrange range_daqp_ai = { 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25) + } +}; + +static const struct comedi_lrange range_daqp_ao = { 1, {BIP_RANGE(5)} }; + +/*====================================================================*/ + +/* comedi interface code */ + +static int daqp_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int daqp_detach(struct comedi_device * dev); +static struct comedi_driver driver_daqp = { + driver_name:"quatech_daqp_cs", + module:THIS_MODULE, + attach:daqp_attach, + detach:daqp_detach, +}; + +#ifdef DAQP_DEBUG + +static void daqp_dump(struct comedi_device * dev) +{ + printk("DAQP: status %02x; aux status %02x\n", + inb(dev->iobase + DAQP_STATUS), inb(dev->iobase + DAQP_AUX)); +} + +static void hex_dump(char *str, void *ptr, int len) +{ + unsigned char *cptr = ptr; + int i; + + printk(str); + + for (i = 0; i < len; i++) { + if (i % 16 == 0) { + printk("\n0x%08x:", (unsigned int)cptr); + } + printk(" %02x", *(cptr++)); + } + printk("\n"); +} + +#endif + +/* Cancel a running acquisition */ + +static int daqp_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct local_info_t *local = (struct local_info_t *) s->private; + + if (local->stop) { + return -EIO; + } + + outb(DAQP_COMMAND_STOP, dev->iobase + DAQP_COMMAND); + + /* flush any linguring data in FIFO - superfluous here */ + /* outb(DAQP_COMMAND_RSTF, dev->iobase+DAQP_COMMAND); */ + + local->interrupt_mode = semaphore; + + return 0; +} + +/* Interrupt handler + * + * Operates in one of two modes. If local->interrupt_mode is + * 'semaphore', just signal the local->eos semaphore and return + * (one-shot mode). Otherwise (continuous mode), read data in from + * the card, transfer it to the buffer provided by the higher-level + * comedi kernel module, and signal various comedi callback routines, + * which run pretty quick. + */ + +static void daqp_interrupt(int irq, void *dev_id PT_REGS_ARG) +{ + struct local_info_t *local = (struct local_info_t *) dev_id; + struct comedi_device *dev; + struct comedi_subdevice *s; + int loop_limit = 10000; + int status; + + if (local == NULL) { + printk(KERN_WARNING + "daqp_interrupt(): irq %d for unknown device.\n", irq); + return; + } + + dev = local->dev; + if (dev == NULL) { + printk(KERN_WARNING "daqp_interrupt(): NULL comedi_device.\n"); + return; + } + + if (!dev->attached) { + printk(KERN_WARNING + "daqp_interrupt(): struct comedi_device not yet attached.\n"); + return; + } + + s = local->s; + if (s == NULL) { + printk(KERN_WARNING + "daqp_interrupt(): NULL comedi_subdevice.\n"); + return; + } + + if ((struct local_info_t *) s->private != local) { + printk(KERN_WARNING + "daqp_interrupt(): invalid comedi_subdevice.\n"); + return; + } + + switch (local->interrupt_mode) { + + case semaphore: + + up(&local->eos); + break; + + case buffer: + + while (!((status = inb(dev->iobase + DAQP_STATUS)) + & DAQP_STATUS_FIFO_EMPTY)) { + + short data; + + if (status & DAQP_STATUS_DATA_LOST) { + s->async->events |= + COMEDI_CB_EOA | COMEDI_CB_OVERFLOW; + printk("daqp: data lost\n"); + daqp_ai_cancel(dev, s); + break; + } + + data = inb(dev->iobase + DAQP_FIFO); + data |= inb(dev->iobase + DAQP_FIFO) << 8; + data ^= 0x8000; + + comedi_buf_put(s->async, data); + + /* If there's a limit, decrement it + * and stop conversion if zero + */ + + if (local->count > 0) { + local->count--; + if (local->count == 0) { + daqp_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA; + break; + } + } + + if ((loop_limit--) <= 0) + break; + } + + if (loop_limit <= 0) { + printk(KERN_WARNING + "loop_limit reached in daqp_interrupt()\n"); + daqp_ai_cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + } + + s->async->events |= COMEDI_CB_BLOCK; + + comedi_event(dev, s); + } +} + +/* One-shot analog data acquisition routine */ + +static int daqp_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct local_info_t *local = (struct local_info_t *) s->private; + int i; + int v; + int counter = 10000; + + if (local->stop) { + return -EIO; + } + + /* Stop any running conversion */ + daqp_ai_cancel(dev, s); + + outb(0, dev->iobase + DAQP_AUX); + + /* Reset scan list queue */ + outb(DAQP_COMMAND_RSTQ, dev->iobase + DAQP_COMMAND); + + /* Program one scan list entry */ + + v = DAQP_SCANLIST_CHANNEL(CR_CHAN(insn->chanspec)) + | DAQP_SCANLIST_GAIN(CR_RANGE(insn->chanspec)); + + if (CR_AREF(insn->chanspec) == AREF_DIFF) { + v |= DAQP_SCANLIST_DIFFERENTIAL; + } + + v |= DAQP_SCANLIST_START; + + outb(v & 0xff, dev->iobase + DAQP_SCANLIST); + outb(v >> 8, dev->iobase + DAQP_SCANLIST); + + /* Reset data FIFO (see page 28 of DAQP User's Manual) */ + + outb(DAQP_COMMAND_RSTF, dev->iobase + DAQP_COMMAND); + + /* Set trigger */ + + v = DAQP_CONTROL_TRIGGER_ONESHOT | DAQP_CONTROL_TRIGGER_INTERNAL + | DAQP_CONTROL_PACER_100kHz | DAQP_CONTROL_EOS_INT_ENABLE; + + outb(v, dev->iobase + DAQP_CONTROL); + + /* Reset any pending interrupts (my card has a tendancy to require + * require multiple reads on the status register to achieve this) + */ + + while (--counter + && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS)) ; + if (!counter) { + printk("daqp: couldn't clear interrupts in status register\n"); + return -1; + } + + /* Make sure semaphore is blocked */ + sema_init(&local->eos, 0); + local->interrupt_mode = semaphore; + local->dev = dev; + local->s = s; + + for (i = 0; i < insn->n; i++) { + + /* Start conversion */ + outb(DAQP_COMMAND_ARM | DAQP_COMMAND_FIFO_DATA, + dev->iobase + DAQP_COMMAND); + + /* Wait for interrupt service routine to unblock semaphore */ + /* Maybe could use a timeout here, but it's interruptible */ + if (down_interruptible(&local->eos)) + return -EINTR; + + data[i] = inb(dev->iobase + DAQP_FIFO); + data[i] |= inb(dev->iobase + DAQP_FIFO) << 8; + data[i] ^= 0x8000; + } + + return insn->n; +} + +/* This function converts ns nanoseconds to a counter value suitable + * for programming the device. We always use the DAQP's 5 MHz clock, + * which with its 24-bit counter, allows values up to 84 seconds. + * Also, the function adjusts ns so that it cooresponds to the actual + * time that the device will use. + */ + +static int daqp_ns_to_timer(unsigned int *ns, int round) +{ + int timer; + + timer = *ns / 200; + *ns = timer * 200; + + return timer; +} + +/* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executed by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. + */ + +static int daqp_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* step 1: make sure trigger sources are trivially valid */ + + 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_TIMER | TRIG_FOLLOW; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_NOW; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_FOLLOW) + err++; + if (cmd->convert_src != TRIG_NOW && cmd->convert_src != TRIG_TIMER) + err++; + if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } +#define MAX_SPEED 10000 /* 100 kHz - in nanoseconds */ + + if (cmd->scan_begin_src == TRIG_TIMER + && cmd->scan_begin_arg < MAX_SPEED) { + cmd->scan_begin_arg = MAX_SPEED; + err++; + } + + /* If both scan_begin and convert are both timer values, the only + * way that can make sense is if the scan time is the number of + * conversions times the convert time + */ + + if (cmd->scan_begin_src == TRIG_TIMER && cmd->convert_src == TRIG_TIMER + && cmd->scan_begin_arg != + cmd->convert_arg * cmd->scan_end_arg) { + err++; + } + + if (cmd->convert_src == TRIG_TIMER && cmd->convert_arg < MAX_SPEED) { + cmd->convert_arg = MAX_SPEED; + err++; + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_arg > 0x00ffffff) { + cmd->stop_arg = 0x00ffffff; + err++; + } + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + daqp_ns_to_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + daqp_ns_to_timer(&cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + } + + if (err) + return 4; + + return 0; +} + +static int daqp_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +{ + struct local_info_t *local = (struct local_info_t *) s->private; + struct comedi_cmd *cmd = &s->async->cmd; + int counter = 100; + int scanlist_start_on_every_entry; + int threshold; + + int i; + int v; + + if (local->stop) { + return -EIO; + } + + /* Stop any running conversion */ + daqp_ai_cancel(dev, s); + + outb(0, dev->iobase + DAQP_AUX); + + /* Reset scan list queue */ + outb(DAQP_COMMAND_RSTQ, dev->iobase + DAQP_COMMAND); + + /* Program pacer clock + * + * There's two modes we can operate in. If convert_src is + * TRIG_TIMER, then convert_arg specifies the time between + * each conversion, so we program the pacer clock to that + * frequency and set the SCANLIST_START bit on every scanlist + * entry. Otherwise, convert_src is TRIG_NOW, which means + * we want the fastest possible conversions, scan_begin_src + * is TRIG_TIMER, and scan_begin_arg specifies the time between + * each scan, so we program the pacer clock to this frequency + * and only set the SCANLIST_START bit on the first entry. + */ + + if (cmd->convert_src == TRIG_TIMER) { + int counter = daqp_ns_to_timer(&cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + outb(counter & 0xff, dev->iobase + DAQP_PACER_LOW); + outb((counter >> 8) & 0xff, dev->iobase + DAQP_PACER_MID); + outb((counter >> 16) & 0xff, dev->iobase + DAQP_PACER_HIGH); + scanlist_start_on_every_entry = 1; + } else { + int counter = daqp_ns_to_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + outb(counter & 0xff, dev->iobase + DAQP_PACER_LOW); + outb((counter >> 8) & 0xff, dev->iobase + DAQP_PACER_MID); + outb((counter >> 16) & 0xff, dev->iobase + DAQP_PACER_HIGH); + scanlist_start_on_every_entry = 0; + } + + /* Program scan list */ + + for (i = 0; i < cmd->chanlist_len; i++) { + + int chanspec = cmd->chanlist[i]; + + /* Program one scan list entry */ + + v = DAQP_SCANLIST_CHANNEL(CR_CHAN(chanspec)) + | DAQP_SCANLIST_GAIN(CR_RANGE(chanspec)); + + if (CR_AREF(chanspec) == AREF_DIFF) { + v |= DAQP_SCANLIST_DIFFERENTIAL; + } + + if (i == 0 || scanlist_start_on_every_entry) { + v |= DAQP_SCANLIST_START; + } + + outb(v & 0xff, dev->iobase + DAQP_SCANLIST); + outb(v >> 8, dev->iobase + DAQP_SCANLIST); + } + + /* Now it's time to program the FIFO threshold, basically the + * number of samples the card will buffer before it interrupts + * the CPU. + * + * If we don't have a stop count, then use half the size of + * the FIFO (the manufacturer's recommendation). Consider + * that the FIFO can hold 2K samples (4K bytes). With the + * threshold set at half the FIFO size, we have a margin of + * error of 1024 samples. At the chip's maximum sample rate + * of 100,000 Hz, the CPU would have to delay interrupt + * service for a full 10 milliseconds in order to lose data + * here (as opposed to higher up in the kernel). I've never + * seen it happen. However, for slow sample rates it may + * buffer too much data and introduce too much delay for the + * user application. + * + * If we have a stop count, then things get more interesting. + * If the stop count is less than the FIFO size (actually + * three-quarters of the FIFO size - see below), we just use + * the stop count itself as the threshold, the card interrupts + * us when that many samples have been taken, and we kill the + * acquisition at that point and are done. If the stop count + * is larger than that, then we divide it by 2 until it's less + * than three quarters of the FIFO size (we always leave the + * top quarter of the FIFO as protection against sluggish CPU + * interrupt response) and use that as the threshold. So, if + * the stop count is 4000 samples, we divide by two twice to + * get 1000 samples, use that as the threshold, take four + * interrupts to get our 4000 samples and are done. + * + * The algorithm could be more clever. For example, if 81000 + * samples are requested, we could set the threshold to 1500 + * samples and take 54 interrupts to get 81000. But 54 isn't + * a power of two, so this algorithm won't find that option. + * Instead, it'll set the threshold at 1266 and take 64 + * interrupts to get 81024 samples, of which the last 24 will + * be discarded... but we won't get the last interrupt until + * they've been collected. To find the first option, the + * computer could look at the prime decomposition of the + * sample count (81000 = 3^4 * 5^3 * 2^3) and factor it into a + * threshold (1500 = 3 * 5^3 * 2^2) and an interrupt count (54 + * = 3^3 * 2). Hmmm... a one-line while loop or prime + * decomposition of integers... I'll leave it the way it is. + * + * I'll also note a mini-race condition before ignoring it in + * the code. Let's say we're taking 4000 samples, as before. + * After 1000 samples, we get an interrupt. But before that + * interrupt is completely serviced, another sample is taken + * and loaded into the FIFO. Since the interrupt handler + * empties the FIFO before returning, it will read 1001 samples. + * If that happens four times, we'll end up taking 4004 samples, + * not 4000. The interrupt handler will discard the extra four + * samples (by halting the acquisition with four samples still + * in the FIFO), but we will have to wait for them. + * + * In short, this code works pretty well, but for either of + * the two reasons noted, might end up waiting for a few more + * samples than actually requested. Shouldn't make too much + * of a difference. + */ + + /* Save away the number of conversions we should perform, and + * compute the FIFO threshold (in bytes, not samples - that's + * why we multiple local->count by 2 = sizeof(sample)) + */ + + if (cmd->stop_src == TRIG_COUNT) { + local->count = cmd->stop_arg * cmd->scan_end_arg; + threshold = 2 * local->count; + while (threshold > DAQP_FIFO_SIZE * 3 / 4) + threshold /= 2; + } else { + local->count = -1; + threshold = DAQP_FIFO_SIZE / 2; + } + + /* Reset data FIFO (see page 28 of DAQP User's Manual) */ + + outb(DAQP_COMMAND_RSTF, dev->iobase + DAQP_COMMAND); + + /* Set FIFO threshold. First two bytes are near-empty + * threshold, which is unused; next two bytes are near-full + * threshold. We computed the number of bytes we want in the + * FIFO when the interrupt is generated, what the card wants + * is actually the number of available bytes left in the FIFO + * when the interrupt is to happen. + */ + + outb(0x00, dev->iobase + DAQP_FIFO); + outb(0x00, dev->iobase + DAQP_FIFO); + + outb((DAQP_FIFO_SIZE - threshold) & 0xff, dev->iobase + DAQP_FIFO); + outb((DAQP_FIFO_SIZE - threshold) >> 8, dev->iobase + DAQP_FIFO); + + /* Set trigger */ + + v = DAQP_CONTROL_TRIGGER_CONTINUOUS | DAQP_CONTROL_TRIGGER_INTERNAL + | DAQP_CONTROL_PACER_5MHz | DAQP_CONTROL_FIFO_INT_ENABLE; + + outb(v, dev->iobase + DAQP_CONTROL); + + /* Reset any pending interrupts (my card has a tendancy to require + * require multiple reads on the status register to achieve this) + */ + + while (--counter + && (inb(dev->iobase + DAQP_STATUS) & DAQP_STATUS_EVENTS)) ; + if (!counter) { + printk("daqp: couldn't clear interrupts in status register\n"); + return -1; + } + + local->interrupt_mode = buffer; + local->dev = dev; + local->s = s; + + /* Start conversion */ + outb(DAQP_COMMAND_ARM | DAQP_COMMAND_FIFO_DATA, + dev->iobase + DAQP_COMMAND); + + return 0; +} + +/* Single-shot analog output routine */ + +static int daqp_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct local_info_t *local = (struct local_info_t *) s->private; + int d; + unsigned int chan; + + if (local->stop) { + return -EIO; + } + + chan = CR_CHAN(insn->chanspec); + d = data[0]; + d &= 0x0fff; + d ^= 0x0800; /* Flip the sign */ + d |= chan << 12; + + /* Make sure D/A update mode is direct update */ + outb(0, dev->iobase + DAQP_AUX); + + outw(d, dev->iobase + DAQP_DA); + + return 1; +} + +/* Digital input routine */ + +static int daqp_di_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct local_info_t *local = (struct local_info_t *) s->private; + + if (local->stop) { + return -EIO; + } + + data[0] = inb(dev->iobase + DAQP_DIGITAL_IO); + + return 1; +} + +/* Digital output routine */ + +static int daqp_do_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + struct local_info_t *local = (struct local_info_t *) s->private; + + if (local->stop) { + return -EIO; + } + + outw(data[0] & 0xf, dev->iobase + DAQP_DIGITAL_IO); + + return 1; +} + +/* daqp_attach is called via comedi_config to attach a comedi device + * to a /dev/comedi*. Note that this is different from daqp_cs_attach() + * which is called by the pcmcia subsystem to attach the PCMCIA card + * when it is inserted. + */ + +static int daqp_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int ret; + struct local_info_t *local = dev_table[it->options[0]]; + tuple_t tuple; + int i; + struct comedi_subdevice *s; + + if (it->options[0] < 0 || it->options[0] >= MAX_DEV || !local) { + printk("comedi%d: No such daqp device %d\n", + dev->minor, it->options[0]); + return -EIO; + } + + /* Typically brittle code that I don't completely understand, + * but "it works on my card". The intent is to pull the model + * number of the card out the PCMCIA CIS and stash it away as + * the COMEDI board_name. Looks like the third field in + * CISTPL_VERS_1 (offset 2) holds what we're looking for. If + * it doesn't work, who cares, just leave it as "DAQP". + */ + + strcpy(local->board_name, "DAQP"); + dev->board_name = local->board_name; + + tuple.DesiredTuple = CISTPL_VERS_1; + if (pcmcia_get_first_tuple(local->link, &tuple) == 0) { + u_char buf[128]; + + buf[0] = buf[sizeof(buf) - 1] = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 2; + if (pcmcia_get_tuple_data(local->link, &tuple) == 0) { + + for (i = 0; i < tuple.TupleDataLen - 4; i++) + if (buf[i] == 0) + break; + for (i++; i < tuple.TupleDataLen - 4; i++) + if (buf[i] == 0) + break; + i++; + if ((i < tuple.TupleDataLen - 4) + && (strncmp(buf + i, "DAQP", 4) == 0)) { + strncpy(local->board_name, buf + i, + sizeof(local->board_name)); + } + } + } + + dev->iobase = local->link->io.BasePort1; + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + + printk("comedi%d: attaching daqp%d (io 0x%04lx)\n", + dev->minor, it->options[0], dev->iobase); + + s = dev->subdevices + 0; + dev->read_subdev = s; + s->private = local; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; + s->n_chan = 8; + s->len_chanlist = 2048; + s->maxdata = 0xffff; + s->range_table = &range_daqp_ai; + s->insn_read = daqp_ai_insn_read; + s->do_cmdtest = daqp_ai_cmdtest; + s->do_cmd = daqp_ai_cmd; + s->cancel = daqp_ai_cancel; + + s = dev->subdevices + 1; + dev->write_subdev = s; + s->private = local; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 2; + s->len_chanlist = 1; + s->maxdata = 0x0fff; + s->range_table = &range_daqp_ao; + s->insn_write = daqp_ao_insn_write; + + s = dev->subdevices + 2; + s->private = local; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 1; + s->len_chanlist = 1; + s->insn_read = daqp_di_insn_read; + + s = dev->subdevices + 3; + s->private = local; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 1; + s->len_chanlist = 1; + s->insn_write = daqp_do_insn_write; + + return 1; +} + +/* daqp_detach (called from comedi_comdig) does nothing. If the PCMCIA + * card is removed, daqp_cs_detach() is called by the pcmcia subsystem. + */ + +static int daqp_detach(struct comedi_device * dev) +{ + printk("comedi%d: detaching daqp\n", dev->minor); + + return 0; +} + +/*==================================================================== + + PCMCIA interface code + + The rest of the code in this file is based on dummy_cs.c v1.24 + from the Linux pcmcia_cs distribution v3.1.8 and is subject + to the following license agreement. + + The remaining contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU Public License version 2 (the "GPL"), in which + case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + +/* + The event() function is this driver's Card Services event handler. + It will be called by Card Services when an appropriate card status + event is received. The config() and release() entry points are + used to configure or release a socket, in response to card + insertion and ejection events. + + Kernel version 2.6.16 upwards uses suspend() and resume() functions + instead of an event() function. +*/ + +static void daqp_cs_config(struct pcmcia_device *link); +static void daqp_cs_release(struct pcmcia_device *link); +static int daqp_cs_suspend(struct pcmcia_device *p_dev); +static int daqp_cs_resume(struct pcmcia_device *p_dev); + +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static int daqp_cs_attach(struct pcmcia_device *); +static void daqp_cs_detach(struct pcmcia_device *); + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static const dev_info_t dev_info = "quatech_daqp_cs"; + +/*====================================================================== + + daqp_cs_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + +======================================================================*/ + +static int daqp_cs_attach(struct pcmcia_device *link) +{ + struct local_info_t *local; + int i; + + DEBUG(0, "daqp_cs_attach()\n"); + + for (i = 0; i < MAX_DEV; i++) + if (dev_table[i] == NULL) + break; + if (i == MAX_DEV) { + printk(KERN_NOTICE "daqp_cs: no devices available\n"); + return -ENODEV; + } + + /* Allocate space for private device-specific data */ + local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); + if (!local) + return -ENOMEM; + + local->table_index = i; + dev_table[i] = local; + local->link = link; + link->priv = local; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->irq.Handler = daqp_interrupt; + link->irq.Instance = local; + + /* + General socket configuration defaults can go here. In this + client, we assume very little, and rely on the CIS for almost + everything. In most clients, many details (i.e., number, sizes, + and attributes of IO windows) are fixed by the nature of the + device, and can be hard-wired here. + */ + link->conf.Attributes = 0; + link->conf.IntType = INT_MEMORY_AND_IO; + + daqp_cs_config(link); + + return 0; +} /* daqp_cs_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void daqp_cs_detach(struct pcmcia_device *link) +{ + struct local_info_t *dev = link->priv; + + DEBUG(0, "daqp_cs_detach(0x%p)\n", link); + + if (link->dev_node) { + dev->stop = 1; + daqp_cs_release(link); + } + + /* Unlink device structure, and free it */ + dev_table[dev->table_index] = NULL; + if (dev) + kfree(dev); + +} /* daqp_cs_detach */ + +/*====================================================================== + + daqp_cs_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + device available to the system. + +======================================================================*/ + +static void daqp_cs_config(struct pcmcia_device *link) +{ + struct local_info_t *dev = link->priv; + tuple_t tuple; + cisparse_t parse; + int last_ret; + u_char buf[64]; + + DEBUG(0, "daqp_cs_config(0x%p)\n", link); + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple))) { + cs_error(link, GetFirstTuple, last_ret); + goto cs_failed; + } + if ((last_ret = pcmcia_get_tuple_data(link, &tuple))) { + cs_error(link, GetTupleData, last_ret); + goto cs_failed; + } + if ((last_ret = pcmcia_parse_tuple(&tuple, &parse))) { + cs_error(link, ParseTuple, last_ret); + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* + In this loop, we scan the CIS for configuration table entries, + each of which describes a valid card configuration, including + voltage, IO window, memory window, and interrupt settings. + + We make no assumptions about the card to be configured: we use + just the information available in the CIS. In an ideal world, + this would work for any PCMCIA card, but it requires a complete + and accurate CIS. In practice, a driver usually "knows" most of + these things without consulting the CIS, and most client drivers + will only use the CIS to fill in implementation-defined details. + */ + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + if ((last_ret = pcmcia_get_first_tuple(link, &tuple))) { + cs_error(link, GetFirstTuple, last_ret); + goto cs_failed; + } + while (1) { + cistpl_cftable_entry_t dflt = { 0 }; + cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); + if (pcmcia_get_tuple_data(link, &tuple)) + goto next_entry; + if (pcmcia_parse_tuple(&tuple, &parse)) + goto next_entry; + + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + dflt = *cfg; + if (cfg->index == 0) + goto next_entry; + link->conf.ConfigIndex = cfg->index; + + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) + link->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + link->io.NumPorts1 = link->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; + link->io.BasePort1 = io->win[0].base; + link->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + link->io.Attributes2 = link->io.Attributes1; + link->io.BasePort2 = io->win[1].base; + link->io.NumPorts2 = io->win[1].len; + } + } + + /* This reserves IO space but doesn't actually enable it */ + if (pcmcia_request_io(link, &link->io)) + goto next_entry; + + /* If we got this far, we're cool! */ + break; + + next_entry: + if ((last_ret = pcmcia_get_next_tuple(link, &tuple))) { + cs_error(link, GetNextTuple, last_ret); + goto cs_failed; + } + } + + /* + Allocate an interrupt line. Note that this does not assign a + handler to the interrupt, unless the 'Handler' member of the + irq structure is initialized. + */ + if (link->conf.Attributes & CONF_ENABLE_IRQ) + if ((last_ret = pcmcia_request_irq(link, &link->irq))) { + cs_error(link, RequestIRQ, last_ret); + goto cs_failed; + } + + /* + This actually configures the PCMCIA socket -- setting up + the I/O windows and the interrupt mapping, and putting the + card and host interface into "Memory and IO" mode. + */ + if ((last_ret = pcmcia_request_configuration(link, &link->conf))) { + cs_error(link, RequestConfiguration, last_ret); + goto cs_failed; + } + + /* + At this point, the dev_node_t structure(s) need to be + initialized and arranged in a linked list at link->dev. + */ + /* Comedi's PCMCIA script uses this device name (extracted + * from /var/lib/pcmcia/stab) to pass to comedi_config + */ + /* sprintf(dev->node.dev_name, "daqp%d", dev->table_index); */ + sprintf(dev->node.dev_name, "quatech_daqp_cs"); + dev->node.major = dev->node.minor = 0; + link->dev_node = &dev->node; + + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %u", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1 + link->io.NumPorts1 - 1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2 + link->io.NumPorts2 - 1); + printk("\n"); + + return; + + cs_failed: + daqp_cs_release(link); + +} /* daqp_cs_config */ + +static void daqp_cs_release(struct pcmcia_device *link) +{ + DEBUG(0, "daqp_cs_release(0x%p)\n", link); + + pcmcia_disable_device(link); +} /* daqp_cs_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. + + When a CARD_REMOVAL event is received, we immediately set a + private flag to block future accesses to this device. All the + functions that actually access the device should check this flag + to make sure the card is still present. + +======================================================================*/ + +static int daqp_cs_suspend(struct pcmcia_device *link) +{ + struct local_info_t *local = link->priv; + + /* Mark the device as stopped, to block IO until later */ + local->stop = 1; + return 0; +} + +static int daqp_cs_resume(struct pcmcia_device *link) +{ + struct local_info_t *local = link->priv; + + local->stop = 0; + + return 0; +} + +/*====================================================================*/ + +#ifdef MODULE + +static struct pcmcia_device_id daqp_cs_id_table[] = { + PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0027), + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, daqp_cs_id_table); + +struct pcmcia_driver daqp_cs_driver = { + .probe = daqp_cs_attach, + .remove = daqp_cs_detach, + .suspend = daqp_cs_suspend, + .resume = daqp_cs_resume, + .id_table = daqp_cs_id_table, + .owner = THIS_MODULE, + .drv = { + .name = dev_info, + }, +}; + +int __init init_module(void) +{ + DEBUG(0, "%s\n", version); + pcmcia_register_driver(&daqp_cs_driver); + comedi_driver_register(&driver_daqp); + return 0; +} + +void __exit cleanup_module(void) +{ + DEBUG(0, "daqp_cs: unloading\n"); + comedi_driver_unregister(&driver_daqp); + pcmcia_unregister_driver(&daqp_cs_driver); +} + +#endif diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 65d5242a2585..ca347f21d140 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -196,7 +196,7 @@ Configuration options: /* The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128) */ -static const comedi_lrange rtd_ai_7520_range = { 18, { +static const struct comedi_lrange rtd_ai_7520_range = { 18, { /* +-5V input range gain steps */ BIP_RANGE(5.0), BIP_RANGE(5.0 / 2), @@ -223,7 +223,7 @@ static const comedi_lrange rtd_ai_7520_range = { 18, { }; /* PCI4520 has two more gains (6 more entries) */ -static const comedi_lrange rtd_ai_4520_range = { 24, { +static const struct comedi_lrange rtd_ai_4520_range = { 24, { /* +-5V input range gain steps */ BIP_RANGE(5.0), BIP_RANGE(5.0 / 2), @@ -255,7 +255,7 @@ static const comedi_lrange rtd_ai_4520_range = { 24, { }; /* Table order matches range values */ -static const comedi_lrange rtd_ao_range = { 4, { +static const struct comedi_lrange rtd_ao_range = { 4, { RANGE(0, 5), RANGE(0, 10), RANGE(-5, 5), @@ -266,7 +266,7 @@ static const comedi_lrange rtd_ao_range = { 4, { /* Board descriptions */ -typedef struct rtdBoard_struct { +struct rtdBoard { const char *name; /* must be first */ int device_id; int aiChans; @@ -274,12 +274,12 @@ typedef struct rtdBoard_struct { int aiMaxGain; int range10Start; /* start of +-10V range */ int rangeUniStart; /* start of +10V range */ -} rtdBoard; +}; -static const rtdBoard rtd520Boards[] = { +static const struct rtdBoard rtd520Boards[] = { { name: "DM7520", - device_id:0x7520, + device_id : 0x7520, aiChans: 16, aiBits: 12, aiMaxGain:32, @@ -288,7 +288,7 @@ static const rtdBoard rtd520Boards[] = { }, { name: "PCI4520", - device_id:0x4520, + device_id : 0x4520, aiChans: 16, aiBits: 12, aiMaxGain:128, @@ -308,13 +308,13 @@ MODULE_DEVICE_TABLE(pci, rtd520_pci_table); /* * Useful for shorthand access to the particular board structure */ -#define thisboard ((const rtdBoard *)dev->board_ptr) +#define thisboard ((const struct rtdBoard *)dev->board_ptr) /* This structure is for data unique to this hardware driver. This is also unique for each board in the system. */ -typedef struct { +struct rtdPrivate { /* memory mapped board structures */ void *las0; void *las1; @@ -334,7 +334,7 @@ typedef struct { unsigned char chanBipolar[RTD_MAX_CHANLIST / 8]; /* bit array */ /* read back data */ - lsampl_t aoValue[2]; /* Used for AO read back */ + unsigned int aoValue[2]; /* Used for AO read back */ /* timer gate (when enabled) */ u8 utcGate[4]; /* 1 extra allows simple range check */ @@ -358,7 +358,7 @@ typedef struct { u8 dma1Control; #endif /* USE_DMA */ unsigned fifoLen; -} rtdPrivate; +}; /* bit defines for "flags" */ #define SEND_EOS 0x01 /* send End Of Scan events */ @@ -366,18 +366,18 @@ typedef struct { #define DMA1_ACTIVE 0x04 /* DMA1 is active */ /* Macros for accessing channel list bit array */ -#define CHAN_ARRAY_TEST(array,index) \ +#define CHAN_ARRAY_TEST(array, index) \ (((array)[(index)/8] >> ((index) & 0x7)) & 0x1) -#define CHAN_ARRAY_SET(array,index) \ +#define CHAN_ARRAY_SET(array, index) \ (((array)[(index)/8] |= 1 << ((index) & 0x7))) -#define CHAN_ARRAY_CLEAR(array,index) \ +#define CHAN_ARRAY_CLEAR(array, index) \ (((array)[(index)/8] &= ~(1 << ((index) & 0x7)))) /* * most drivers define the following macro to make it easy to * access the private structure. */ -#define devpriv ((rtdPrivate *)dev->private) +#define devpriv ((struct rtdPrivate *)dev->private) /* Macros to access registers */ @@ -394,15 +394,15 @@ typedef struct { writel (0, devpriv->las0+LAS0_CGT_CLEAR) /* Reset channel gain table read and write pointers */ -#define RtdEnableCGT(dev,v) \ +#define RtdEnableCGT(dev, v) \ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_CGT_ENABLE) /* Write channel gain table entry */ -#define RtdWriteCGTable(dev,v) \ +#define RtdWriteCGTable(dev, v) \ writel (v, devpriv->las0+LAS0_CGT_WRITE) /* Write Channel Gain Latch */ -#define RtdWriteCGLatch(dev,v) \ +#define RtdWriteCGLatch(dev, v) \ writel (v, devpriv->las0+LAS0_CGL_WRITE) /* Reset ADC FIFO */ @@ -410,39 +410,39 @@ typedef struct { writel (0, devpriv->las0+LAS0_ADC_FIFO_CLEAR) /* Set ADC start conversion source select (write only) */ -#define RtdAdcConversionSource(dev,v) \ +#define RtdAdcConversionSource(dev, v) \ writel (v, devpriv->las0+LAS0_ADC_CONVERSION) /* Set burst start source select (write only) */ -#define RtdBurstStartSource(dev,v) \ +#define RtdBurstStartSource(dev, v) \ writel (v, devpriv->las0+LAS0_BURST_START) /* Set Pacer start source select (write only) */ -#define RtdPacerStartSource(dev,v) \ +#define RtdPacerStartSource(dev, v) \ writel (v, devpriv->las0+LAS0_PACER_START) /* Set Pacer stop source select (write only) */ -#define RtdPacerStopSource(dev,v) \ +#define RtdPacerStopSource(dev, v) \ writel (v, devpriv->las0+LAS0_PACER_STOP) /* Set Pacer clock source select (write only) 0=external 1=internal */ -#define RtdPacerClockSource(dev,v) \ +#define RtdPacerClockSource(dev, v) \ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_SELECT) /* Set sample counter source select (write only) */ -#define RtdAdcSampleCounterSource(dev,v) \ +#define RtdAdcSampleCounterSource(dev, v) \ writel (v, devpriv->las0+LAS0_ADC_SCNT_SRC) /* Set Pacer trigger mode select (write only) 0=single cycle, 1=repeat */ -#define RtdPacerTriggerMode(dev,v) \ +#define RtdPacerTriggerMode(dev, v) \ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_REPEAT) /* Set About counter stop enable (write only) */ -#define RtdAboutStopEnable(dev,v) \ +#define RtdAboutStopEnable(dev, v) \ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ACNT_STOP_ENABLE) /* Set external trigger polarity (write only) 0=positive edge, 1=negative */ -#define RtdTriggerPolarity(dev,v) \ +#define RtdTriggerPolarity(dev, v) \ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ETRG_POLARITY) /* Start single ADC conversion */ @@ -473,15 +473,15 @@ typedef struct { readw (devpriv->las0+LAS0_IT) /* Interrupt mask */ -#define RtdInterruptMask(dev,v) \ - writew ((devpriv->intMask = (v)),devpriv->las0+LAS0_IT) +#define RtdInterruptMask(dev, v) \ + writew ((devpriv->intMask = (v)), devpriv->las0+LAS0_IT) /* Interrupt status clear (only bits set in mask) */ #define RtdInterruptClear(dev) \ readw (devpriv->las0+LAS0_CLEAR) /* Interrupt clear mask */ -#define RtdInterruptClearMask(dev,v) \ +#define RtdInterruptClearMask(dev, v) \ writew ((devpriv->intClearMask = (v)), devpriv->las0+LAS0_CLEAR) /* Interrupt overrun status */ @@ -495,92 +495,92 @@ typedef struct { /* Pacer counter, 24bit */ #define RtdPacerCount(dev) \ readl (devpriv->las0+LAS0_PCLK) -#define RtdPacerCounter(dev,v) \ - writel ((v) & 0xffffff,devpriv->las0+LAS0_PCLK) +#define RtdPacerCounter(dev, v) \ + writel ((v) & 0xffffff, devpriv->las0+LAS0_PCLK) /* Burst counter, 10bit */ #define RtdBurstCount(dev) \ readl (devpriv->las0+LAS0_BCLK) -#define RtdBurstCounter(dev,v) \ - writel ((v) & 0x3ff,devpriv->las0+LAS0_BCLK) +#define RtdBurstCounter(dev, v) \ + writel ((v) & 0x3ff, devpriv->las0+LAS0_BCLK) /* Delay counter, 16bit */ #define RtdDelayCount(dev) \ readl (devpriv->las0+LAS0_DCLK) -#define RtdDelayCounter(dev,v) \ +#define RtdDelayCounter(dev, v) \ writel ((v) & 0xffff, devpriv->las0+LAS0_DCLK) /* About counter, 16bit */ #define RtdAboutCount(dev) \ readl (devpriv->las0+LAS0_ACNT) -#define RtdAboutCounter(dev,v) \ +#define RtdAboutCounter(dev, v) \ writel ((v) & 0xffff, devpriv->las0+LAS0_ACNT) /* ADC sample counter, 10bit */ #define RtdAdcSampleCount(dev) \ readl (devpriv->las0+LAS0_ADC_SCNT) -#define RtdAdcSampleCounter(dev,v) \ +#define RtdAdcSampleCounter(dev, v) \ writel ((v) & 0x3ff, devpriv->las0+LAS0_ADC_SCNT) /* User Timer/Counter (8254) */ -#define RtdUtcCounterGet(dev,n) \ +#define RtdUtcCounterGet(dev, n) \ readb (devpriv->las0 \ + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2))) -#define RtdUtcCounterPut(dev,n,v) \ +#define RtdUtcCounterPut(dev, n, v) \ writeb ((v) & 0xff, devpriv->las0 \ + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2))) /* Set UTC (8254) control byte */ -#define RtdUtcCtrlPut(dev,n,v) \ +#define RtdUtcCtrlPut(dev, n, v) \ writeb (devpriv->utcCtrl[(n) & 3] = (((n) & 3) << 6) | ((v) & 0x3f), \ devpriv->las0 + LAS0_UTC_CTRL) /* Set UTCn clock source (write only) */ -#define RtdUtcClockSource(dev,n,v) \ +#define RtdUtcClockSource(dev, n, v) \ writew (v, devpriv->las0 \ + ((n <= 0) ? LAS0_UTC0_CLOCK : \ ((1 == n) ? LAS0_UTC1_CLOCK : LAS0_UTC2_CLOCK))) /* Set UTCn gate source (write only) */ -#define RtdUtcGateSource(dev,n,v) \ +#define RtdUtcGateSource(dev, n, v) \ writew (v, devpriv->las0 \ + ((n <= 0) ? LAS0_UTC0_GATE : \ ((1 == n) ? LAS0_UTC1_GATE : LAS0_UTC2_GATE))) /* User output N source select (write only) */ -#define RtdUsrOutSource(dev,n,v) \ - writel (v,devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT)) +#define RtdUsrOutSource(dev, n, v) \ + writel (v, devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT)) /* Digital IO */ #define RtdDio0Read(dev) \ (readw (devpriv->las0+LAS0_DIO0) & 0xff) -#define RtdDio0Write(dev,v) \ +#define RtdDio0Write(dev, v) \ writew ((v) & 0xff, devpriv->las0+LAS0_DIO0) #define RtdDio1Read(dev) \ (readw (devpriv->las0+LAS0_DIO1) & 0xff) -#define RtdDio1Write(dev,v) \ +#define RtdDio1Write(dev, v) \ writew ((v) & 0xff, devpriv->las0+LAS0_DIO1) #define RtdDioStatusRead(dev) \ (readw (devpriv->las0+LAS0_DIO_STATUS) & 0xff) -#define RtdDioStatusWrite(dev,v) \ +#define RtdDioStatusWrite(dev, v) \ writew ((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS) #define RtdDio0CtrlRead(dev) \ (readw (devpriv->las0+LAS0_DIO0_CTRL) & 0xff) -#define RtdDio0CtrlWrite(dev,v) \ +#define RtdDio0CtrlWrite(dev, v) \ writew ((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL) /* Digital to Analog converter */ /* Write one data value (sign + 12bit + marker bits) */ /* Note: matches what DMA would put. Actual value << 3 */ -#define RtdDacFifoPut(dev,n,v) \ +#define RtdDacFifoPut(dev, n, v) \ writew ((v), devpriv->las1 +(((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO)) /* Start single DAC conversion */ -#define RtdDacUpdate(dev,n) \ +#define RtdDacUpdate(dev, n) \ writew (0, devpriv->las0 +(((n) == 0) ? LAS0_DAC1 : LAS0_DAC2)) /* Start single DAC conversion on both DACs */ @@ -588,20 +588,20 @@ typedef struct { writew (0, devpriv->las0+LAS0_DAC) /* Set DAC output type and range */ -#define RtdDacRange(dev,n,v) \ +#define RtdDacRange(dev, n, v) \ writew ((v) & 7, devpriv->las0 \ +(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL)) /* Reset DAC FIFO */ -#define RtdDacClearFifo(dev,n) \ +#define RtdDacClearFifo(dev, n) \ writel (0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET)) /* Set source for DMA 0 (write only, shadow?) */ -#define RtdDma0Source(dev,n) \ +#define RtdDma0Source(dev, n) \ writel ((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC) /* Set source for DMA 1 (write only, shadow?) */ -#define RtdDma1Source(dev,n) \ +#define RtdDma1Source(dev, n) \ writel ((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC) /* Reset board state for DMA 0 */ @@ -615,51 +615,51 @@ typedef struct { /* PLX9080 interrupt mask and status */ #define RtdPlxInterruptRead(dev) \ readl (devpriv->lcfg+LCFG_ITCSR) -#define RtdPlxInterruptWrite(dev,v) \ +#define RtdPlxInterruptWrite(dev, v) \ writel (v, devpriv->lcfg+LCFG_ITCSR) /* Set mode for DMA 0 */ -#define RtdDma0Mode(dev,m) \ +#define RtdDma0Mode(dev, m) \ writel ((m), devpriv->lcfg+LCFG_DMAMODE0) /* Set PCI address for DMA 0 */ -#define RtdDma0PciAddr(dev,a) \ +#define RtdDma0PciAddr(dev, a) \ writel ((a), devpriv->lcfg+LCFG_DMAPADR0) /* Set local address for DMA 0 */ -#define RtdDma0LocalAddr(dev,a) \ +#define RtdDma0LocalAddr(dev, a) \ writel ((a), devpriv->lcfg+LCFG_DMALADR0) /* Set byte count for DMA 0 */ -#define RtdDma0Count(dev,c) \ +#define RtdDma0Count(dev, c) \ writel ((c), devpriv->lcfg+LCFG_DMASIZ0) /* Set next descriptor for DMA 0 */ -#define RtdDma0Next(dev,a) \ +#define RtdDma0Next(dev, a) \ writel ((a), devpriv->lcfg+LCFG_DMADPR0) /* Set mode for DMA 1 */ -#define RtdDma1Mode(dev,m) \ +#define RtdDma1Mode(dev, m) \ writel ((m), devpriv->lcfg+LCFG_DMAMODE1) /* Set PCI address for DMA 1 */ -#define RtdDma1PciAddr(dev,a) \ +#define RtdDma1PciAddr(dev, a) \ writel ((a), devpriv->lcfg+LCFG_DMAADR1) /* Set local address for DMA 1 */ -#define RtdDma1LocalAddr(dev,a) \ +#define RtdDma1LocalAddr(dev, a) \ writel ((a), devpriv->lcfg+LCFG_DMALADR1) /* Set byte count for DMA 1 */ -#define RtdDma1Count(dev,c) \ +#define RtdDma1Count(dev, c) \ writel ((c), devpriv->lcfg+LCFG_DMASIZ1) /* Set next descriptor for DMA 1 */ -#define RtdDma1Next(dev,a) \ +#define RtdDma1Next(dev, a) \ writel ((a), devpriv->lcfg+LCFG_DMADPR1) /* Set control for DMA 0 (write only, shadow?) */ -#define RtdDma0Control(dev,n) \ +#define RtdDma0Control(dev, n) \ writeb (devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0) /* Get status for DMA 0 */ @@ -667,7 +667,7 @@ typedef struct { readb (devpriv->lcfg+LCFG_DMACSR0) /* Set control for DMA 1 (write only, shadow?) */ -#define RtdDma1Control(dev,n) \ +#define RtdDma1Control(dev, n) \ writeb (devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1) /* Get status for DMA 1 */ @@ -675,39 +675,39 @@ typedef struct { readb (devpriv->lcfg+LCFG_DMACSR1) /* - * The comedi_driver structure tells the Comedi core module + * The struct comedi_driver structure tells the Comedi core module * which functions to call to configure/deconfigure (attac/detach) * the board, and also about the kernel module that contains * the device code. */ -static int rtd_attach(comedi_device * dev, comedi_devconfig * it); -static int rtd_detach(comedi_device * dev); +static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int rtd_detach(struct comedi_device *dev); -static comedi_driver rtd520Driver = { +static struct comedi_driver rtd520Driver = { driver_name: DRV_NAME, - module:THIS_MODULE, - attach:rtd_attach, - detach:rtd_detach, + module : THIS_MODULE, + attach : rtd_attach, + detach : rtd_detach, }; -static int rtd_ai_rinsn(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int rtd_ao_winsn(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int rtd_ao_rinsn(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int rtd_dio_insn_bits(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int rtd_dio_insn_config(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int rtd_ai_cmdtest(comedi_device * dev, comedi_subdevice * s, - comedi_cmd * cmd); -static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s); -static int rtd_ai_cancel(comedi_device * dev, comedi_subdevice * s); -//static int rtd_ai_poll (comedi_device *dev,comedi_subdevice *s); +static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int rtd_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int rtd_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int rtd_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int rtd_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd); +static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s); +static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s); +/* static int rtd_ai_poll (struct comedi_device *dev,struct comedi_subdevice *s); */ static int rtd_ns_to_timer(unsigned int *ns, int roundMode); static irqreturn_t rtd_interrupt(int irq, void *d PT_REGS_ARG); -static int rtd520_probe_fifo_depth(comedi_device *dev); +static int rtd520_probe_fifo_depth(struct comedi_device *dev); /* * Attach is called by the Comedi core to configure the driver @@ -715,9 +715,9 @@ static int rtd520_probe_fifo_depth(comedi_device *dev); * in the driver structure, dev->board_ptr contains that * address. */ -static int rtd_attach(comedi_device * dev, comedi_devconfig * it) +static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) { /* board name and options flags */ - comedi_subdevice *s; + struct comedi_subdevice *s; struct pci_dev *pcidev; int ret; resource_size_t physLas0; /* configuation */ @@ -739,7 +739,7 @@ static int rtd_attach(comedi_device * dev, comedi_devconfig * it) * Allocate the private structure area. alloc_private() is a * convenient macro defined in comedidev.h. */ - if (alloc_private(dev, sizeof(rtdPrivate)) < 0) + if (alloc_private(dev, sizeof(struct rtdPrivate)) < 0) return -ENOMEM; /* @@ -779,7 +779,8 @@ static int rtd_attach(comedi_device * dev, comedi_devconfig * it) devpriv->pci_dev = pcidev; dev->board_name = thisboard->name; - if ((ret = comedi_pci_enable(pcidev, DRV_NAME)) < 0) { + ret = comedi_pci_enable(pcidev, DRV_NAME); + if (ret < 0) { printk("Failed to enable PCI device and request regions.\n"); return ret; } @@ -866,7 +867,7 @@ static int rtd_attach(comedi_device * dev, comedi_devconfig * it) s->do_cmd = rtd_ai_cmd; s->do_cmdtest = rtd_ai_cmdtest; s->cancel = rtd_ai_cancel; - /*s->poll = rtd_ai_poll; *//* not ready yet */ + /* s->poll = rtd_ai_poll; */ /* not ready yet */ s = dev->subdevices + 1; /* analog output subdevice */ @@ -918,8 +919,10 @@ static int rtd_attach(comedi_device * dev, comedi_devconfig * it) /* TODO: set user out source ??? */ /* check if our interrupt is available and get it */ - if ((ret = comedi_request_irq(devpriv->pci_dev->irq, rtd_interrupt, - IRQF_SHARED, DRV_NAME, dev)) < 0) { + ret = comedi_request_irq(devpriv->pci_dev->irq, rtd_interrupt, + IRQF_SHARED, DRV_NAME, dev); + + if (ret < 0) { printk("Could not get interrupt! (%u)\n", devpriv->pci_dev->irq); return ret; @@ -1005,7 +1008,7 @@ static int rtd_attach(comedi_device * dev, comedi_devconfig * it) #if 0 /* hit an error, clean up memory and return ret */ -//rtd_attach_die_error: +/* rtd_attach_die_error: */ #ifdef USE_DMA for (index = 0; index < DMA_CHAIN_COUNT; index++) { if (NULL != devpriv->dma0Buff[index]) { /* free buffer memory */ @@ -1057,7 +1060,7 @@ static int rtd_attach(comedi_device * dev, comedi_devconfig * it) * allocated by _attach(). dev->private and dev->subdevices are * deallocated automatically by the core. */ -static int rtd_detach(comedi_device * dev) +static int rtd_detach(struct comedi_device *dev) { #ifdef USE_DMA int index; @@ -1137,7 +1140,7 @@ static int rtd_detach(comedi_device * dev) /* Convert a single comedi channel-gain entry to a RTD520 table entry */ -static unsigned short rtdConvertChanGain(comedi_device * dev, +static unsigned short rtdConvertChanGain(struct comedi_device *dev, unsigned int comediChan, int chanIndex) { /* index in channel list */ unsigned int chan, range, aref; @@ -1187,7 +1190,7 @@ static unsigned short rtdConvertChanGain(comedi_device * dev, /* Setup the channel-gain table from a comedi list */ -static void rtd_load_channelgain_list(comedi_device * dev, +static void rtd_load_channelgain_list(struct comedi_device *dev, unsigned int n_chan, unsigned int *list) { if (n_chan > 1) { /* setup channel gain table */ @@ -1206,9 +1209,9 @@ static void rtd_load_channelgain_list(comedi_device * dev, /* determine fifo size by doing adc conversions until the fifo half empty status flag clears */ -static int rtd520_probe_fifo_depth(comedi_device *dev) +static int rtd520_probe_fifo_depth(struct comedi_device *dev) { - lsampl_t chanspec = CR_PACK(0, 0, AREF_GROUND); + unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND); unsigned i; static const unsigned limit = 0x2000; unsigned fifo_size = 0; @@ -1234,7 +1237,7 @@ static int rtd520_probe_fifo_depth(comedi_device *dev) return -EIO; } RtdAdcClearFifo(dev); - if(fifo_size != 0x400 || fifo_size != 0x2000) + if(fifo_size != 0x400 && fifo_size != 0x2000) { rt_printk("\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n", DRV_NAME, fifo_size); @@ -1251,8 +1254,8 @@ static int rtd520_probe_fifo_depth(comedi_device *dev) Note, we don't do any settling delays. Use a instruction list to select, delay, then read. */ -static int rtd_ai_rinsn(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int rtd_ai_rinsn(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int n, ii; int stat; @@ -1304,12 +1307,12 @@ static int rtd_ai_rinsn(comedi_device * dev, The manual claims that we can do a lword read, but it doesn't work here. */ -static int ai_read_n(comedi_device * dev, comedi_subdevice * s, int count) +static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, int count) { int ii; for (ii = 0; ii < count; ii++) { - sampl_t sample; + short sample; s16 d; if (0 == devpriv->aiCount) { /* done */ @@ -1343,10 +1346,10 @@ static int ai_read_n(comedi_device * dev, comedi_subdevice * s, int count) /* unknown amout of data is waiting in fifo. */ -static int ai_read_dregs(comedi_device * dev, comedi_subdevice * s) +static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) { while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */ - sampl_t sample; + short sample; s16 d = RtdAdcFifoGet(dev); /* get 2s comp value */ if (0 == devpriv->aiCount) { /* done */ @@ -1372,20 +1375,20 @@ static int ai_read_dregs(comedi_device * dev, comedi_subdevice * s) /* Terminate a DMA transfer and wait for everything to quiet down */ -void abort_dma(comedi_device * dev, unsigned int channel) +void abort_dma(struct comedi_device *dev, unsigned int channel) { /* DMA channel 0, 1 */ unsigned long dma_cs_addr; /* the control/status register */ uint8_t status; unsigned int ii; - //unsigned long flags; + /* unsigned long flags; */ dma_cs_addr = (unsigned long)devpriv->lcfg + ((channel == 0) ? LCFG_DMACSR0 : LCFG_DMACSR1); - // spinlock for plx dma control/status reg - //comedi_spin_lock_irqsave( &dev->spinlock, flags ); + /* spinlock for plx dma control/status reg */ + /* comedi_spin_lock_irqsave( &dev->spinlock, flags ); */ - // abort dma transfer if necessary + /* abort dma transfer if necessary */ status = readb(dma_cs_addr); if ((status & PLX_DMA_EN_BIT) == 0) { /* not enabled (Error?) */ DPRINTK("rtd520: AbortDma on non-active channel %d (0x%x)\n", @@ -1410,7 +1413,7 @@ void abort_dma(comedi_device * dev, unsigned int channel) /* set abort bit for channel */ writeb(PLX_DMA_ABORT_BIT, dma_cs_addr); - // wait for dma done bit to be set + /* wait for dma done bit to be set */ status = readb(dma_cs_addr); for (ii = 0; (status & PLX_DMA_DONE_BIT) == 0 && ii < RTD_DMA_TIMEOUT; @@ -1424,14 +1427,14 @@ void abort_dma(comedi_device * dev, unsigned int channel) } abortDmaExit: - //comedi_spin_unlock_irqrestore( &dev->spinlock, flags ); + /* comedi_spin_unlock_irqrestore( &dev->spinlock, flags ); */ } /* Process what is in the DMA transfer buffer and pass to comedi Note: this is not re-entrant */ -static int ai_process_dma(comedi_device * dev, comedi_subdevice * s) +static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s) { int ii, n; s16 *dp; @@ -1441,7 +1444,7 @@ static int ai_process_dma(comedi_device * dev, comedi_subdevice * s) dp = devpriv->dma0Buff[devpriv->dma0Offset]; for (ii = 0; ii < devpriv->fifoLen / 2;) { /* convert samples */ - sampl_t sample; + short sample; if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) { sample = (*dp >> 3) + 2048; /* convert to comedi unsigned data */ @@ -1494,10 +1497,10 @@ static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ void *d /* our data */ PT_REGS_ARG) { /* cpu context (ignored) */ - comedi_device *dev = d; /* must be called "dev" for devpriv */ + struct comedi_device *dev = d; /* must be called "dev" for devpriv */ u16 status; u16 fifoStatus; - comedi_subdevice *s = dev->subdevices + 0; /* analog in subdevice */ + struct comedi_subdevice *s = dev->subdevices + 0; /* analog in subdevice */ if (!dev->attached) { return IRQ_NONE; @@ -1645,7 +1648,7 @@ static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */ /* return the number of samples available */ -static int rtd_ai_poll(comedi_device * dev, comedi_subdevice * s) +static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) { /* TODO: This needs to mask interrupts, read_dregs, and then re-enable */ /* Not sure what to do if DMA is active */ @@ -1662,8 +1665,8 @@ static int rtd_ai_poll(comedi_device * dev, comedi_subdevice * s) the command passes. */ -static int rtd_ai_cmdtest(comedi_device * dev, - comedi_subdevice * s, comedi_cmd * cmd) +static int rtd_ai_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0; int tmp; @@ -1867,9 +1870,9 @@ static int rtd_ai_cmdtest(comedi_device * dev, This is usually done by an interrupt handler. Userland gets to the data using read calls. */ -static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s) +static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - comedi_cmd *cmd = &s->async->cmd; + struct comedi_cmd *cmd = &s->async->cmd; int timer; /* stop anything currently running */ @@ -2064,7 +2067,7 @@ static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s) /* Stop a running data aquisition. */ -static int rtd_ai_cancel(comedi_device * dev, comedi_subdevice * s) +static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { u16 status; @@ -2132,8 +2135,8 @@ static int rtd_ns_to_timer(unsigned int *ns, int round_mode) /* Output one (or more) analog values to a single port as fast as possible. */ -static int rtd_ao_winsn(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int rtd_ao_winsn(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int i; int chan = CR_CHAN(insn->chanspec); @@ -2152,7 +2155,7 @@ static int rtd_ao_winsn(comedi_device * dev, /* VERIFY: comedi range and offset conversions */ if ((range > 1) /* bipolar */ - &&(data[i] < 2048)) { + && (data[i] < 2048)) { /* offset and sign extend */ val = (((int)data[i]) - 2048) << 3; } else { /* unipolor */ @@ -2187,8 +2190,8 @@ static int rtd_ao_winsn(comedi_device * dev, /* AO subdevices should have a read insn as well as a write insn. * Usually this means copying a value stored in devpriv. */ -static int rtd_ao_rinsn(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int rtd_ao_rinsn(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int i; int chan = CR_CHAN(insn->chanspec); @@ -2210,8 +2213,8 @@ static int rtd_ao_rinsn(comedi_device * dev, * This allows packed reading/writing of the DIO channels. The * comedi core can convert between insn_bits and insn_read/write */ -static int rtd_dio_insn_bits(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int rtd_dio_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { if (insn->n != 2) return -EINVAL; @@ -2237,8 +2240,8 @@ static int rtd_dio_insn_bits(comedi_device * dev, /* Configure one bit on a IO port as Input or Output (hence the name :-). */ -static int rtd_dio_insn_config(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +static int rtd_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int chan = CR_CHAN(insn->chanspec); diff --git a/drivers/staging/comedi/drivers/rtd520.h b/drivers/staging/comedi/drivers/rtd520.h index 0eb50b8e605e..a3ec2599c4b8 100644 --- a/drivers/staging/comedi/drivers/rtd520.h +++ b/drivers/staging/comedi/drivers/rtd520.h @@ -29,366 +29,366 @@ LAS0 Runtime Area Local Address Space 0 Offset Read Function Write Function */ -#define LAS0_SPARE_00 0x0000 // - - -#define LAS0_SPARE_04 0x0004 // - - -#define LAS0_USER_IO 0x0008 // Read User Inputs Write User Outputs -#define LAS0_SPARE_0C 0x000C // - - -#define LAS0_ADC 0x0010 // Read FIFO Status Software A/D Start -#define LAS0_DAC1 0x0014 // - Software D/A1 Update -#define LAS0_DAC2 0x0018 // - Software D/A2 Update -#define LAS0_SPARE_1C 0x001C // - - -#define LAS0_SPARE_20 0x0020 // - - -#define LAS0_DAC 0x0024 // - Software Simultaneous D/A1 and D/A2 Update -#define LAS0_PACER 0x0028 // Software Pacer Start Software Pacer Stop -#define LAS0_TIMER 0x002C // Read Timer Counters Status HDIN Software Trigger -#define LAS0_IT 0x0030 // Read Interrupt Status Write Interrupt Enable Mask Register -#define LAS0_CLEAR 0x0034 // Clear ITs set by Clear Mask Set Interrupt Clear Mask -#define LAS0_OVERRUN 0x0038 // Read pending interrupts Clear Overrun Register -#define LAS0_SPARE_3C 0x003C // - - +#define LAS0_SPARE_00 0x0000 /* - - */ +#define LAS0_SPARE_04 0x0004 /* - - */ +#define LAS0_USER_IO 0x0008 /* Read User Inputs Write User Outputs */ +#define LAS0_SPARE_0C 0x000C /* - - */ +#define LAS0_ADC 0x0010 /* Read FIFO Status Software A/D Start */ +#define LAS0_DAC1 0x0014 /* - Software D/A1 Update */ +#define LAS0_DAC2 0x0018 /* - Software D/A2 Update */ +#define LAS0_SPARE_1C 0x001C /* - - */ +#define LAS0_SPARE_20 0x0020 /* - - */ +#define LAS0_DAC 0x0024 /* - Software Simultaneous D/A1 and D/A2 Update */ +#define LAS0_PACER 0x0028 /* Software Pacer Start Software Pacer Stop */ +#define LAS0_TIMER 0x002C /* Read Timer Counters Status HDIN Software Trigger */ +#define LAS0_IT 0x0030 /* Read Interrupt Status Write Interrupt Enable Mask Register */ +#define LAS0_CLEAR 0x0034 /* Clear ITs set by Clear Mask Set Interrupt Clear Mask */ +#define LAS0_OVERRUN 0x0038 /* Read pending interrupts Clear Overrun Register */ +#define LAS0_SPARE_3C 0x003C /* - - */ /* LAS0 Runtime Area Timer/Counter,Dig.IO Name Local Address Function */ -#define LAS0_PCLK 0x0040 // Pacer Clock value (24bit) Pacer Clock load (24bit) -#define LAS0_BCLK 0x0044 // Burst Clock value (10bit) Burst Clock load (10bit) -#define LAS0_ADC_SCNT 0x0048 // A/D Sample counter value (10bit) A/D Sample counter load (10bit) -#define LAS0_DAC1_UCNT 0x004C // D/A1 Update counter value (10 bit) D/A1 Update counter load (10bit) -#define LAS0_DAC2_UCNT 0x0050 // D/A2 Update counter value (10 bit) D/A2 Update counter load (10bit) -#define LAS0_DCNT 0x0054 // Delay counter value (16 bit) Delay counter load (16bit) -#define LAS0_ACNT 0x0058 // About counter value (16 bit) About counter load (16bit) -#define LAS0_DAC_CLK 0x005C // DAC clock value (16bit) DAC clock load (16bit) -#define LAS0_UTC0 0x0060 // 8254 TC Counter 0 User TC 0 value Load count in TC Counter 0 -#define LAS0_UTC1 0x0064 // 8254 TC Counter 1 User TC 1 value Load count in TC Counter 1 -#define LAS0_UTC2 0x0068 // 8254 TC Counter 2 User TC 2 value Load count in TC Counter 2 -#define LAS0_UTC_CTRL 0x006C // 8254 TC Control Word Program counter mode for TC -#define LAS0_DIO0 0x0070 // Digital I/O Port 0 Read Port Digital I/O Port 0 Write Port -#define LAS0_DIO1 0x0074 // Digital I/O Port 1 Read Port Digital I/O Port 1 Write Port -#define LAS0_DIO0_CTRL 0x0078 // Clear digital IRQ status flag/read Clear digital chip/program Port 0 -#define LAS0_DIO_STATUS 0x007C // Read Digital I/O Status word Program digital control register & +#define LAS0_PCLK 0x0040 /* Pacer Clock value (24bit) Pacer Clock load (24bit) */ +#define LAS0_BCLK 0x0044 /* Burst Clock value (10bit) Burst Clock load (10bit) */ +#define LAS0_ADC_SCNT 0x0048 /* A/D Sample counter value (10bit) A/D Sample counter load (10bit) */ +#define LAS0_DAC1_UCNT 0x004C /* D/A1 Update counter value (10 bit) D/A1 Update counter load (10bit) */ +#define LAS0_DAC2_UCNT 0x0050 /* D/A2 Update counter value (10 bit) D/A2 Update counter load (10bit) */ +#define LAS0_DCNT 0x0054 /* Delay counter value (16 bit) Delay counter load (16bit) */ +#define LAS0_ACNT 0x0058 /* About counter value (16 bit) About counter load (16bit) */ +#define LAS0_DAC_CLK 0x005C /* DAC clock value (16bit) DAC clock load (16bit) */ +#define LAS0_UTC0 0x0060 /* 8254 TC Counter 0 User TC 0 value Load count in TC Counter 0 */ +#define LAS0_UTC1 0x0064 /* 8254 TC Counter 1 User TC 1 value Load count in TC Counter 1 */ +#define LAS0_UTC2 0x0068 /* 8254 TC Counter 2 User TC 2 value Load count in TC Counter 2 */ +#define LAS0_UTC_CTRL 0x006C /* 8254 TC Control Word Program counter mode for TC */ +#define LAS0_DIO0 0x0070 /* Digital I/O Port 0 Read Port Digital I/O Port 0 Write Port */ +#define LAS0_DIO1 0x0074 /* Digital I/O Port 1 Read Port Digital I/O Port 1 Write Port */ +#define LAS0_DIO0_CTRL 0x0078 /* Clear digital IRQ status flag/read Clear digital chip/program Port 0 */ +#define LAS0_DIO_STATUS 0x007C /* Read Digital I/O Status word Program digital control register & */ /* LAS0 Setup Area Name Local Address Function */ -#define LAS0_BOARD_RESET 0x0100 // Board reset -#define LAS0_DMA0_SRC 0x0104 // DMA 0 Sources select -#define LAS0_DMA1_SRC 0x0108 // DMA 1 Sources select -#define LAS0_ADC_CONVERSION 0x010C // A/D Conversion Signal select -#define LAS0_BURST_START 0x0110 // Burst Clock Start Trigger select -#define LAS0_PACER_START 0x0114 // Pacer Clock Start Trigger select -#define LAS0_PACER_STOP 0x0118 // Pacer Clock Stop Trigger select -#define LAS0_ACNT_STOP_ENABLE 0x011C // About Counter Stop Enable -#define LAS0_PACER_REPEAT 0x0120 // Pacer Start Trigger Mode select -#define LAS0_DIN_START 0x0124 // High Speed Digital Input Sampling Signal select -#define LAS0_DIN_FIFO_CLEAR 0x0128 // Digital Input FIFO Clear -#define LAS0_ADC_FIFO_CLEAR 0x012C // A/D FIFO Clear -#define LAS0_CGT_WRITE 0x0130 // Channel Gain Table Write -#define LAS0_CGL_WRITE 0x0134 // Channel Gain Latch Write -#define LAS0_CG_DATA 0x0138 // Digital Table Write -#define LAS0_CGT_ENABLE 0x013C // Channel Gain Table Enable -#define LAS0_CG_ENABLE 0x0140 // Digital Table Enable -#define LAS0_CGT_PAUSE 0x0144 // Table Pause Enable -#define LAS0_CGT_RESET 0x0148 // Reset Channel Gain Table -#define LAS0_CGT_CLEAR 0x014C // Clear Channel Gain Table -#define LAS0_DAC1_CTRL 0x0150 // D/A1 output type/range -#define LAS0_DAC1_SRC 0x0154 // D/A1 update source -#define LAS0_DAC1_CYCLE 0x0158 // D/A1 cycle mode -#define LAS0_DAC1_RESET 0x015C // D/A1 FIFO reset -#define LAS0_DAC1_FIFO_CLEAR 0x0160 // D/A1 FIFO clear -#define LAS0_DAC2_CTRL 0x0164 // D/A2 output type/range -#define LAS0_DAC2_SRC 0x0168 // D/A2 update source -#define LAS0_DAC2_CYCLE 0x016C // D/A2 cycle mode -#define LAS0_DAC2_RESET 0x0170 // D/A2 FIFO reset -#define LAS0_DAC2_FIFO_CLEAR 0x0174 // D/A2 FIFO clear -#define LAS0_ADC_SCNT_SRC 0x0178 // A/D Sample Counter Source select -#define LAS0_PACER_SELECT 0x0180 // Pacer Clock select -#define LAS0_SBUS0_SRC 0x0184 // SyncBus 0 Source select -#define LAS0_SBUS0_ENABLE 0x0188 // SyncBus 0 enable -#define LAS0_SBUS1_SRC 0x018C // SyncBus 1 Source select -#define LAS0_SBUS1_ENABLE 0x0190 // SyncBus 1 enable -#define LAS0_SBUS2_SRC 0x0198 // SyncBus 2 Source select -#define LAS0_SBUS2_ENABLE 0x019C // SyncBus 2 enable -#define LAS0_ETRG_POLARITY 0x01A4 // External Trigger polarity select -#define LAS0_EINT_POLARITY 0x01A8 // External Interrupt polarity select -#define LAS0_UTC0_CLOCK 0x01AC // UTC0 Clock select -#define LAS0_UTC0_GATE 0x01B0 // UTC0 Gate select -#define LAS0_UTC1_CLOCK 0x01B4 // UTC1 Clock select -#define LAS0_UTC1_GATE 0x01B8 // UTC1 Gate select -#define LAS0_UTC2_CLOCK 0x01BC // UTC2 Clock select -#define LAS0_UTC2_GATE 0x01C0 // UTC2 Gate select -#define LAS0_UOUT0_SELECT 0x01C4 // User Output 0 source select -#define LAS0_UOUT1_SELECT 0x01C8 // User Output 1 source select -#define LAS0_DMA0_RESET 0x01CC // DMA0 Request state machine reset -#define LAS0_DMA1_RESET 0x01D0 // DMA1 Request state machine reset +#define LAS0_BOARD_RESET 0x0100 /* Board reset */ +#define LAS0_DMA0_SRC 0x0104 /* DMA 0 Sources select */ +#define LAS0_DMA1_SRC 0x0108 /* DMA 1 Sources select */ +#define LAS0_ADC_CONVERSION 0x010C /* A/D Conversion Signal select */ +#define LAS0_BURST_START 0x0110 /* Burst Clock Start Trigger select */ +#define LAS0_PACER_START 0x0114 /* Pacer Clock Start Trigger select */ +#define LAS0_PACER_STOP 0x0118 /* Pacer Clock Stop Trigger select */ +#define LAS0_ACNT_STOP_ENABLE 0x011C /* About Counter Stop Enable */ +#define LAS0_PACER_REPEAT 0x0120 /* Pacer Start Trigger Mode select */ +#define LAS0_DIN_START 0x0124 /* High Speed Digital Input Sampling Signal select */ +#define LAS0_DIN_FIFO_CLEAR 0x0128 /* Digital Input FIFO Clear */ +#define LAS0_ADC_FIFO_CLEAR 0x012C /* A/D FIFO Clear */ +#define LAS0_CGT_WRITE 0x0130 /* Channel Gain Table Write */ +#define LAS0_CGL_WRITE 0x0134 /* Channel Gain Latch Write */ +#define LAS0_CG_DATA 0x0138 /* Digital Table Write */ +#define LAS0_CGT_ENABLE 0x013C /* Channel Gain Table Enable */ +#define LAS0_CG_ENABLE 0x0140 /* Digital Table Enable */ +#define LAS0_CGT_PAUSE 0x0144 /* Table Pause Enable */ +#define LAS0_CGT_RESET 0x0148 /* Reset Channel Gain Table */ +#define LAS0_CGT_CLEAR 0x014C /* Clear Channel Gain Table */ +#define LAS0_DAC1_CTRL 0x0150 /* D/A1 output type/range */ +#define LAS0_DAC1_SRC 0x0154 /* D/A1 update source */ +#define LAS0_DAC1_CYCLE 0x0158 /* D/A1 cycle mode */ +#define LAS0_DAC1_RESET 0x015C /* D/A1 FIFO reset */ +#define LAS0_DAC1_FIFO_CLEAR 0x0160 /* D/A1 FIFO clear */ +#define LAS0_DAC2_CTRL 0x0164 /* D/A2 output type/range */ +#define LAS0_DAC2_SRC 0x0168 /* D/A2 update source */ +#define LAS0_DAC2_CYCLE 0x016C /* D/A2 cycle mode */ +#define LAS0_DAC2_RESET 0x0170 /* D/A2 FIFO reset */ +#define LAS0_DAC2_FIFO_CLEAR 0x0174 /* D/A2 FIFO clear */ +#define LAS0_ADC_SCNT_SRC 0x0178 /* A/D Sample Counter Source select */ +#define LAS0_PACER_SELECT 0x0180 /* Pacer Clock select */ +#define LAS0_SBUS0_SRC 0x0184 /* SyncBus 0 Source select */ +#define LAS0_SBUS0_ENABLE 0x0188 /* SyncBus 0 enable */ +#define LAS0_SBUS1_SRC 0x018C /* SyncBus 1 Source select */ +#define LAS0_SBUS1_ENABLE 0x0190 /* SyncBus 1 enable */ +#define LAS0_SBUS2_SRC 0x0198 /* SyncBus 2 Source select */ +#define LAS0_SBUS2_ENABLE 0x019C /* SyncBus 2 enable */ +#define LAS0_ETRG_POLARITY 0x01A4 /* External Trigger polarity select */ +#define LAS0_EINT_POLARITY 0x01A8 /* External Interrupt polarity select */ +#define LAS0_UTC0_CLOCK 0x01AC /* UTC0 Clock select */ +#define LAS0_UTC0_GATE 0x01B0 /* UTC0 Gate select */ +#define LAS0_UTC1_CLOCK 0x01B4 /* UTC1 Clock select */ +#define LAS0_UTC1_GATE 0x01B8 /* UTC1 Gate select */ +#define LAS0_UTC2_CLOCK 0x01BC /* UTC2 Clock select */ +#define LAS0_UTC2_GATE 0x01C0 /* UTC2 Gate select */ +#define LAS0_UOUT0_SELECT 0x01C4 /* User Output 0 source select */ +#define LAS0_UOUT1_SELECT 0x01C8 /* User Output 1 source select */ +#define LAS0_DMA0_RESET 0x01CC /* DMA0 Request state machine reset */ +#define LAS0_DMA1_RESET 0x01D0 /* DMA1 Request state machine reset */ /* LAS1 Name Local Address Function */ -#define LAS1_ADC_FIFO 0x0000 // Read A/D FIFO (16bit) - -#define LAS1_HDIO_FIFO 0x0004 // Read High Speed Digital Input FIFO (16bit) - -#define LAS1_DAC1_FIFO 0x0008 // - Write D/A1 FIFO (16bit) -#define LAS1_DAC2_FIFO 0x000C // - Write D/A2 FIFO (16bit) +#define LAS1_ADC_FIFO 0x0000 /* Read A/D FIFO (16bit) - */ +#define LAS1_HDIO_FIFO 0x0004 /* Read High Speed Digital Input FIFO (16bit) - */ +#define LAS1_DAC1_FIFO 0x0008 /* - Write D/A1 FIFO (16bit) */ +#define LAS1_DAC2_FIFO 0x000C /* - Write D/A2 FIFO (16bit) */ /* LCFG: PLX 9080 local config & runtime registers Name Local Address Function */ -#define LCFG_ITCSR 0x0068 // INTCSR, Interrupt Control/Status Register -#define LCFG_DMAMODE0 0x0080 // DMA Channel 0 Mode Register -#define LCFG_DMAPADR0 0x0084 // DMA Channel 0 PCI Address Register -#define LCFG_DMALADR0 0x0088 // DMA Channel 0 Local Address Reg -#define LCFG_DMASIZ0 0x008C // DMA Channel 0 Transfer Size (Bytes) Register -#define LCFG_DMADPR0 0x0090 // DMA Channel 0 Descriptor Pointer Register -#define LCFG_DMAMODE1 0x0094 // DMA Channel 1 Mode Register -#define LCFG_DMAPADR1 0x0098 // DMA Channel 1 PCI Address Register -#define LCFG_DMALADR1 0x009C // DMA Channel 1 Local Address Register -#define LCFG_DMASIZ1 0x00A0 // DMA Channel 1 Transfer Size (Bytes) Register -#define LCFG_DMADPR1 0x00A4 // DMA Channel 1 Descriptor Pointer Register -#define LCFG_DMACSR0 0x00A8 // DMA Channel 0 Command/Status Register -#define LCFG_DMACSR1 0x00A9 // DMA Channel 0 Command/Status Register -#define LCFG_DMAARB 0x00AC // DMA Arbitration Register -#define LCFG_DMATHR 0x00B0 // DMA Threshold Register +#define LCFG_ITCSR 0x0068 /* INTCSR, Interrupt Control/Status Register */ +#define LCFG_DMAMODE0 0x0080 /* DMA Channel 0 Mode Register */ +#define LCFG_DMAPADR0 0x0084 /* DMA Channel 0 PCI Address Register */ +#define LCFG_DMALADR0 0x0088 /* DMA Channel 0 Local Address Reg */ +#define LCFG_DMASIZ0 0x008C /* DMA Channel 0 Transfer Size (Bytes) Register */ +#define LCFG_DMADPR0 0x0090 /* DMA Channel 0 Descriptor Pointer Register */ +#define LCFG_DMAMODE1 0x0094 /* DMA Channel 1 Mode Register */ +#define LCFG_DMAPADR1 0x0098 /* DMA Channel 1 PCI Address Register */ +#define LCFG_DMALADR1 0x009C /* DMA Channel 1 Local Address Register */ +#define LCFG_DMASIZ1 0x00A0 /* DMA Channel 1 Transfer Size (Bytes) Register */ +#define LCFG_DMADPR1 0x00A4 /* DMA Channel 1 Descriptor Pointer Register */ +#define LCFG_DMACSR0 0x00A8 /* DMA Channel 0 Command/Status Register */ +#define LCFG_DMACSR1 0x00A9 /* DMA Channel 0 Command/Status Register */ +#define LCFG_DMAARB 0x00AC /* DMA Arbitration Register */ +#define LCFG_DMATHR 0x00B0 /* DMA Threshold Register */ /*====================================================================== Resister bit definitions ======================================================================*/ -// FIFO Status Word Bits (RtdFifoStatus) -#define FS_DAC1_NOT_EMPTY 0x0001 // D0 - DAC1 FIFO not empty -#define FS_DAC1_HEMPTY 0x0002 // D1 - DAC1 FIFO half empty -#define FS_DAC1_NOT_FULL 0x0004 // D2 - DAC1 FIFO not full -#define FS_DAC2_NOT_EMPTY 0x0010 // D4 - DAC2 FIFO not empty -#define FS_DAC2_HEMPTY 0x0020 // D5 - DAC2 FIFO half empty -#define FS_DAC2_NOT_FULL 0x0040 // D6 - DAC2 FIFO not full -#define FS_ADC_NOT_EMPTY 0x0100 // D8 - ADC FIFO not empty -#define FS_ADC_HEMPTY 0x0200 // D9 - ADC FIFO half empty -#define FS_ADC_NOT_FULL 0x0400 // D10 - ADC FIFO not full -#define FS_DIN_NOT_EMPTY 0x1000 // D12 - DIN FIFO not empty -#define FS_DIN_HEMPTY 0x2000 // D13 - DIN FIFO half empty -#define FS_DIN_NOT_FULL 0x4000 // D14 - DIN FIFO not full +/* FIFO Status Word Bits (RtdFifoStatus) */ +#define FS_DAC1_NOT_EMPTY 0x0001 /* D0 - DAC1 FIFO not empty */ +#define FS_DAC1_HEMPTY 0x0002 /* D1 - DAC1 FIFO half empty */ +#define FS_DAC1_NOT_FULL 0x0004 /* D2 - DAC1 FIFO not full */ +#define FS_DAC2_NOT_EMPTY 0x0010 /* D4 - DAC2 FIFO not empty */ +#define FS_DAC2_HEMPTY 0x0020 /* D5 - DAC2 FIFO half empty */ +#define FS_DAC2_NOT_FULL 0x0040 /* D6 - DAC2 FIFO not full */ +#define FS_ADC_NOT_EMPTY 0x0100 /* D8 - ADC FIFO not empty */ +#define FS_ADC_HEMPTY 0x0200 /* D9 - ADC FIFO half empty */ +#define FS_ADC_NOT_FULL 0x0400 /* D10 - ADC FIFO not full */ +#define FS_DIN_NOT_EMPTY 0x1000 /* D12 - DIN FIFO not empty */ +#define FS_DIN_HEMPTY 0x2000 /* D13 - DIN FIFO half empty */ +#define FS_DIN_NOT_FULL 0x4000 /* D14 - DIN FIFO not full */ -// Timer Status Word Bits (GetTimerStatus) +/* Timer Status Word Bits (GetTimerStatus) */ #define TS_PCLK_GATE 0x0001 -// D0 - Pacer Clock Gate [0 - gated, 1 - enabled] +/* D0 - Pacer Clock Gate [0 - gated, 1 - enabled] */ #define TS_BCLK_GATE 0x0002 -// D1 - Burst Clock Gate [0 - disabled, 1 - running] +/* D1 - Burst Clock Gate [0 - disabled, 1 - running] */ #define TS_DCNT_GATE 0x0004 -// D2 - Pacer Clock Delayed Start Trigger [0 - delay over, 1 - delay in -// progress] +/* D2 - Pacer Clock Delayed Start Trigger [0 - delay over, 1 - delay in */ +/* progress] */ #define TS_ACNT_GATE 0x0008 -// D3 - Pacer Clock About Trigger [0 - completed, 1 - in progress] +/* D3 - Pacer Clock About Trigger [0 - completed, 1 - in progress] */ #define TS_PCLK_RUN 0x0010 -// D4 - Pacer Clock Shutdown Flag [0 - Pacer Clock cannot be start -// triggered only by Software Pacer Start Command, 1 - Pacer Clock can -// be start triggered] +/* D4 - Pacer Clock Shutdown Flag [0 - Pacer Clock cannot be start */ +/* triggered only by Software Pacer Start Command, 1 - Pacer Clock can */ +/* be start triggered] */ -// External Trigger polarity select -// External Interrupt polarity select -#define POL_POSITIVE 0x0 // positive edge -#define POL_NEGATIVE 0x1 // negative edge +/* External Trigger polarity select */ +/* External Interrupt polarity select */ +#define POL_POSITIVE 0x0 /* positive edge */ +#define POL_NEGATIVE 0x1 /* negative edge */ -// User Output Signal select (SetUout0Source, SetUout1Source) -#define UOUT_ADC 0x0 // A/D Conversion Signal -#define UOUT_DAC1 0x1 // D/A1 Update -#define UOUT_DAC2 0x2 // D/A2 Update -#define UOUT_SOFTWARE 0x3 // Software Programmable +/* User Output Signal select (SetUout0Source, SetUout1Source) */ +#define UOUT_ADC 0x0 /* A/D Conversion Signal */ +#define UOUT_DAC1 0x1 /* D/A1 Update */ +#define UOUT_DAC2 0x2 /* D/A2 Update */ +#define UOUT_SOFTWARE 0x3 /* Software Programmable */ -// Pacer clock select (SetPacerSource) -#define PCLK_INTERNAL 1 // Internal Pacer Clock -#define PCLK_EXTERNAL 0 // External Pacer Clock +/* Pacer clock select (SetPacerSource) */ +#define PCLK_INTERNAL 1 /* Internal Pacer Clock */ +#define PCLK_EXTERNAL 0 /* External Pacer Clock */ -// A/D Sample Counter Sources (SetAdcntSource, SetupSampleCounter) -#define ADC_SCNT_CGT_RESET 0x0 // needs restart with StartPacer +/* A/D Sample Counter Sources (SetAdcntSource, SetupSampleCounter) */ +#define ADC_SCNT_CGT_RESET 0x0 /* needs restart with StartPacer */ #define ADC_SCNT_FIFO_WRITE 0x1 -// A/D Conversion Signal Select (for SetConversionSelect) -#define ADC_START_SOFTWARE 0x0 // Software A/D Start -#define ADC_START_PCLK 0x1 // Pacer Clock (Ext. Int. see Func.509) -#define ADC_START_BCLK 0x2 // Burst Clock -#define ADC_START_DIGITAL_IT 0x3 // Digital Interrupt -#define ADC_START_DAC1_MARKER1 0x4 // D/A 1 Data Marker 1 -#define ADC_START_DAC2_MARKER1 0x5 // D/A 2 Data Marker 1 -#define ADC_START_SBUS0 0x6 // SyncBus 0 -#define ADC_START_SBUS1 0x7 // SyncBus 1 -#define ADC_START_SBUS2 0x8 // SyncBus 2 +/* A/D Conversion Signal Select (for SetConversionSelect) */ +#define ADC_START_SOFTWARE 0x0 /* Software A/D Start */ +#define ADC_START_PCLK 0x1 /* Pacer Clock (Ext. Int. see Func.509) */ +#define ADC_START_BCLK 0x2 /* Burst Clock */ +#define ADC_START_DIGITAL_IT 0x3 /* Digital Interrupt */ +#define ADC_START_DAC1_MARKER1 0x4 /* D/A 1 Data Marker 1 */ +#define ADC_START_DAC2_MARKER1 0x5 /* D/A 2 Data Marker 1 */ +#define ADC_START_SBUS0 0x6 /* SyncBus 0 */ +#define ADC_START_SBUS1 0x7 /* SyncBus 1 */ +#define ADC_START_SBUS2 0x8 /* SyncBus 2 */ -// Burst Clock start trigger select (SetBurstStart) -#define BCLK_START_SOFTWARE 0x0 // Software A/D Start (StartBurst) -#define BCLK_START_PCLK 0x1 // Pacer Clock -#define BCLK_START_ETRIG 0x2 // External Trigger -#define BCLK_START_DIGITAL_IT 0x3 // Digital Interrupt -#define BCLK_START_SBUS0 0x4 // SyncBus 0 -#define BCLK_START_SBUS1 0x5 // SyncBus 1 -#define BCLK_START_SBUS2 0x6 // SyncBus 2 +/* Burst Clock start trigger select (SetBurstStart) */ +#define BCLK_START_SOFTWARE 0x0 /* Software A/D Start (StartBurst) */ +#define BCLK_START_PCLK 0x1 /* Pacer Clock */ +#define BCLK_START_ETRIG 0x2 /* External Trigger */ +#define BCLK_START_DIGITAL_IT 0x3 /* Digital Interrupt */ +#define BCLK_START_SBUS0 0x4 /* SyncBus 0 */ +#define BCLK_START_SBUS1 0x5 /* SyncBus 1 */ +#define BCLK_START_SBUS2 0x6 /* SyncBus 2 */ -// Pacer Clock start trigger select (SetPacerStart) -#define PCLK_START_SOFTWARE 0x0 // Software Pacer Start (StartPacer) -#define PCLK_START_ETRIG 0x1 // External trigger -#define PCLK_START_DIGITAL_IT 0x2 // Digital interrupt -#define PCLK_START_UTC2 0x3 // User TC 2 out -#define PCLK_START_SBUS0 0x4 // SyncBus 0 -#define PCLK_START_SBUS1 0x5 // SyncBus 1 -#define PCLK_START_SBUS2 0x6 // SyncBus 2 -#define PCLK_START_D_SOFTWARE 0x8 // Delayed Software Pacer Start -#define PCLK_START_D_ETRIG 0x9 // Delayed external trigger -#define PCLK_START_D_DIGITAL_IT 0xA // Delayed digital interrupt -#define PCLK_START_D_UTC2 0xB // Delayed User TC 2 out -#define PCLK_START_D_SBUS0 0xC // Delayed SyncBus 0 -#define PCLK_START_D_SBUS1 0xD // Delayed SyncBus 1 -#define PCLK_START_D_SBUS2 0xE // Delayed SyncBus 2 -#define PCLK_START_ETRIG_GATED 0xF // External Trigger Gated controlled mode +/* Pacer Clock start trigger select (SetPacerStart) */ +#define PCLK_START_SOFTWARE 0x0 /* Software Pacer Start (StartPacer) */ +#define PCLK_START_ETRIG 0x1 /* External trigger */ +#define PCLK_START_DIGITAL_IT 0x2 /* Digital interrupt */ +#define PCLK_START_UTC2 0x3 /* User TC 2 out */ +#define PCLK_START_SBUS0 0x4 /* SyncBus 0 */ +#define PCLK_START_SBUS1 0x5 /* SyncBus 1 */ +#define PCLK_START_SBUS2 0x6 /* SyncBus 2 */ +#define PCLK_START_D_SOFTWARE 0x8 /* Delayed Software Pacer Start */ +#define PCLK_START_D_ETRIG 0x9 /* Delayed external trigger */ +#define PCLK_START_D_DIGITAL_IT 0xA /* Delayed digital interrupt */ +#define PCLK_START_D_UTC2 0xB /* Delayed User TC 2 out */ +#define PCLK_START_D_SBUS0 0xC /* Delayed SyncBus 0 */ +#define PCLK_START_D_SBUS1 0xD /* Delayed SyncBus 1 */ +#define PCLK_START_D_SBUS2 0xE /* Delayed SyncBus 2 */ +#define PCLK_START_ETRIG_GATED 0xF /* External Trigger Gated controlled mode */ -// Pacer Clock Stop Trigger select (SetPacerStop) -#define PCLK_STOP_SOFTWARE 0x0 // Software Pacer Stop (StopPacer) -#define PCLK_STOP_ETRIG 0x1 // External Trigger -#define PCLK_STOP_DIGITAL_IT 0x2 // Digital Interrupt -#define PCLK_STOP_ACNT 0x3 // About Counter -#define PCLK_STOP_UTC2 0x4 // User TC2 out -#define PCLK_STOP_SBUS0 0x5 // SyncBus 0 -#define PCLK_STOP_SBUS1 0x6 // SyncBus 1 -#define PCLK_STOP_SBUS2 0x7 // SyncBus 2 -#define PCLK_STOP_A_SOFTWARE 0x8 // About Software Pacer Stop -#define PCLK_STOP_A_ETRIG 0x9 // About External Trigger -#define PCLK_STOP_A_DIGITAL_IT 0xA // About Digital Interrupt -#define PCLK_STOP_A_UTC2 0xC // About User TC2 out -#define PCLK_STOP_A_SBUS0 0xD // About SyncBus 0 -#define PCLK_STOP_A_SBUS1 0xE // About SyncBus 1 -#define PCLK_STOP_A_SBUS2 0xF // About SyncBus 2 +/* Pacer Clock Stop Trigger select (SetPacerStop) */ +#define PCLK_STOP_SOFTWARE 0x0 /* Software Pacer Stop (StopPacer) */ +#define PCLK_STOP_ETRIG 0x1 /* External Trigger */ +#define PCLK_STOP_DIGITAL_IT 0x2 /* Digital Interrupt */ +#define PCLK_STOP_ACNT 0x3 /* About Counter */ +#define PCLK_STOP_UTC2 0x4 /* User TC2 out */ +#define PCLK_STOP_SBUS0 0x5 /* SyncBus 0 */ +#define PCLK_STOP_SBUS1 0x6 /* SyncBus 1 */ +#define PCLK_STOP_SBUS2 0x7 /* SyncBus 2 */ +#define PCLK_STOP_A_SOFTWARE 0x8 /* About Software Pacer Stop */ +#define PCLK_STOP_A_ETRIG 0x9 /* About External Trigger */ +#define PCLK_STOP_A_DIGITAL_IT 0xA /* About Digital Interrupt */ +#define PCLK_STOP_A_UTC2 0xC /* About User TC2 out */ +#define PCLK_STOP_A_SBUS0 0xD /* About SyncBus 0 */ +#define PCLK_STOP_A_SBUS1 0xE /* About SyncBus 1 */ +#define PCLK_STOP_A_SBUS2 0xF /* About SyncBus 2 */ -// About Counter Stop Enable -#define ACNT_STOP 0x0 // stop enable -#define ACNT_NO_STOP 0x1 // stop disabled +/* About Counter Stop Enable */ +#define ACNT_STOP 0x0 /* stop enable */ +#define ACNT_NO_STOP 0x1 /* stop disabled */ -// DAC update source (SetDAC1Start & SetDAC2Start) -#define DAC_START_SOFTWARE 0x0 // Software Update -#define DAC_START_CGT 0x1 // CGT controlled Update -#define DAC_START_DAC_CLK 0x2 // D/A Clock -#define DAC_START_EPCLK 0x3 // External Pacer Clock -#define DAC_START_SBUS0 0x4 // SyncBus 0 -#define DAC_START_SBUS1 0x5 // SyncBus 1 -#define DAC_START_SBUS2 0x6 // SyncBus 2 +/* DAC update source (SetDAC1Start & SetDAC2Start) */ +#define DAC_START_SOFTWARE 0x0 /* Software Update */ +#define DAC_START_CGT 0x1 /* CGT controlled Update */ +#define DAC_START_DAC_CLK 0x2 /* D/A Clock */ +#define DAC_START_EPCLK 0x3 /* External Pacer Clock */ +#define DAC_START_SBUS0 0x4 /* SyncBus 0 */ +#define DAC_START_SBUS1 0x5 /* SyncBus 1 */ +#define DAC_START_SBUS2 0x6 /* SyncBus 2 */ -// DAC Cycle Mode (SetDAC1Cycle, SetDAC2Cycle, SetupDAC) -#define DAC_CYCLE_SINGLE 0x0 // not cycle -#define DAC_CYCLE_MULTI 0x1 // cycle +/* DAC Cycle Mode (SetDAC1Cycle, SetDAC2Cycle, SetupDAC) */ +#define DAC_CYCLE_SINGLE 0x0 /* not cycle */ +#define DAC_CYCLE_MULTI 0x1 /* cycle */ -// 8254 Operation Modes (Set8254Mode, SetupTimerCounter) -#define M8254_EVENT_COUNTER 0 // Event Counter -#define M8254_HW_ONE_SHOT 1 // Hardware-Retriggerable One-Shot -#define M8254_RATE_GENERATOR 2 // Rate Generator -#define M8254_SQUARE_WAVE 3 // Square Wave Mode -#define M8254_SW_STROBE 4 // Software Triggered Strobe -#define M8254_HW_STROBE 5 // Hardware Triggered Strobe (Retriggerable) +/* 8254 Operation Modes (Set8254Mode, SetupTimerCounter) */ +#define M8254_EVENT_COUNTER 0 /* Event Counter */ +#define M8254_HW_ONE_SHOT 1 /* Hardware-Retriggerable One-Shot */ +#define M8254_RATE_GENERATOR 2 /* Rate Generator */ +#define M8254_SQUARE_WAVE 3 /* Square Wave Mode */ +#define M8254_SW_STROBE 4 /* Software Triggered Strobe */ +#define M8254_HW_STROBE 5 /* Hardware Triggered Strobe (Retriggerable) */ -// User Timer/Counter 0 Clock Select (SetUtc0Clock) -#define CUTC0_8MHZ 0x0 // 8MHz -#define CUTC0_EXT_TC_CLOCK1 0x1 // Ext. TC Clock 1 -#define CUTC0_EXT_TC_CLOCK2 0x2 // Ext. TC Clock 2 -#define CUTC0_EXT_PCLK 0x3 // Ext. Pacer Clock +/* User Timer/Counter 0 Clock Select (SetUtc0Clock) */ +#define CUTC0_8MHZ 0x0 /* 8MHz */ +#define CUTC0_EXT_TC_CLOCK1 0x1 /* Ext. TC Clock 1 */ +#define CUTC0_EXT_TC_CLOCK2 0x2 /* Ext. TC Clock 2 */ +#define CUTC0_EXT_PCLK 0x3 /* Ext. Pacer Clock */ -// User Timer/Counter 1 Clock Select (SetUtc1Clock) -#define CUTC1_8MHZ 0x0 // 8MHz -#define CUTC1_EXT_TC_CLOCK1 0x1 // Ext. TC Clock 1 -#define CUTC1_EXT_TC_CLOCK2 0x2 // Ext. TC Clock 2 -#define CUTC1_EXT_PCLK 0x3 // Ext. Pacer Clock -#define CUTC1_UTC0_OUT 0x4 // User Timer/Counter 0 out -#define CUTC1_DIN_SIGNAL 0x5 // High-Speed Digital Input Sampling signal +/* User Timer/Counter 1 Clock Select (SetUtc1Clock) */ +#define CUTC1_8MHZ 0x0 /* 8MHz */ +#define CUTC1_EXT_TC_CLOCK1 0x1 /* Ext. TC Clock 1 */ +#define CUTC1_EXT_TC_CLOCK2 0x2 /* Ext. TC Clock 2 */ +#define CUTC1_EXT_PCLK 0x3 /* Ext. Pacer Clock */ +#define CUTC1_UTC0_OUT 0x4 /* User Timer/Counter 0 out */ +#define CUTC1_DIN_SIGNAL 0x5 /* High-Speed Digital Input Sampling signal */ -// User Timer/Counter 2 Clock Select (SetUtc2Clock) -#define CUTC2_8MHZ 0x0 // 8MHz -#define CUTC2_EXT_TC_CLOCK1 0x1 // Ext. TC Clock 1 -#define CUTC2_EXT_TC_CLOCK2 0x2 // Ext. TC Clock 2 -#define CUTC2_EXT_PCLK 0x3 // Ext. Pacer Clock -#define CUTC2_UTC1_OUT 0x4 // User Timer/Counter 1 out +/* User Timer/Counter 2 Clock Select (SetUtc2Clock) */ +#define CUTC2_8MHZ 0x0 /* 8MHz */ +#define CUTC2_EXT_TC_CLOCK1 0x1 /* Ext. TC Clock 1 */ +#define CUTC2_EXT_TC_CLOCK2 0x2 /* Ext. TC Clock 2 */ +#define CUTC2_EXT_PCLK 0x3 /* Ext. Pacer Clock */ +#define CUTC2_UTC1_OUT 0x4 /* User Timer/Counter 1 out */ -// User Timer/Counter 0 Gate Select (SetUtc0Gate) -#define GUTC0_NOT_GATED 0x0 // Not gated -#define GUTC0_GATED 0x1 // Gated -#define GUTC0_EXT_TC_GATE1 0x2 // Ext. TC Gate 1 -#define GUTC0_EXT_TC_GATE2 0x3 // Ext. TC Gate 2 +/* User Timer/Counter 0 Gate Select (SetUtc0Gate) */ +#define GUTC0_NOT_GATED 0x0 /* Not gated */ +#define GUTC0_GATED 0x1 /* Gated */ +#define GUTC0_EXT_TC_GATE1 0x2 /* Ext. TC Gate 1 */ +#define GUTC0_EXT_TC_GATE2 0x3 /* Ext. TC Gate 2 */ -// User Timer/Counter 1 Gate Select (SetUtc1Gate) -#define GUTC1_NOT_GATED 0x0 // Not gated -#define GUTC1_GATED 0x1 // Gated -#define GUTC1_EXT_TC_GATE1 0x2 // Ext. TC Gate 1 -#define GUTC1_EXT_TC_GATE2 0x3 // Ext. TC Gate 2 -#define GUTC1_UTC0_OUT 0x4 // User Timer/Counter 0 out +/* User Timer/Counter 1 Gate Select (SetUtc1Gate) */ +#define GUTC1_NOT_GATED 0x0 /* Not gated */ +#define GUTC1_GATED 0x1 /* Gated */ +#define GUTC1_EXT_TC_GATE1 0x2 /* Ext. TC Gate 1 */ +#define GUTC1_EXT_TC_GATE2 0x3 /* Ext. TC Gate 2 */ +#define GUTC1_UTC0_OUT 0x4 /* User Timer/Counter 0 out */ -// User Timer/Counter 2 Gate Select (SetUtc2Gate) -#define GUTC2_NOT_GATED 0x0 // Not gated -#define GUTC2_GATED 0x1 // Gated -#define GUTC2_EXT_TC_GATE1 0x2 // Ext. TC Gate 1 -#define GUTC2_EXT_TC_GATE2 0x3 // Ext. TC Gate 2 -#define GUTC2_UTC1_OUT 0x4 // User Timer/Counter 1 out +/* User Timer/Counter 2 Gate Select (SetUtc2Gate) */ +#define GUTC2_NOT_GATED 0x0 /* Not gated */ +#define GUTC2_GATED 0x1 /* Gated */ +#define GUTC2_EXT_TC_GATE1 0x2 /* Ext. TC Gate 1 */ +#define GUTC2_EXT_TC_GATE2 0x3 /* Ext. TC Gate 2 */ +#define GUTC2_UTC1_OUT 0x4 /* User Timer/Counter 1 out */ -// Interrupt Source Masks (SetITMask, ClearITMask, GetITStatus) -#define IRQM_ADC_FIFO_WRITE 0x0001 // ADC FIFO Write -#define IRQM_CGT_RESET 0x0002 // Reset CGT -#define IRQM_CGT_PAUSE 0x0008 // Pause CGT -#define IRQM_ADC_ABOUT_CNT 0x0010 // About Counter out -#define IRQM_ADC_DELAY_CNT 0x0020 // Delay Counter out -#define IRQM_ADC_SAMPLE_CNT 0x0040 // ADC Sample Counter -#define IRQM_DAC1_UCNT 0x0080 // DAC1 Update Counter -#define IRQM_DAC2_UCNT 0x0100 // DAC2 Update Counter -#define IRQM_UTC1 0x0200 // User TC1 out -#define IRQM_UTC1_INV 0x0400 // User TC1 out, inverted -#define IRQM_UTC2 0x0800 // User TC2 out -#define IRQM_DIGITAL_IT 0x1000 // Digital Interrupt -#define IRQM_EXTERNAL_IT 0x2000 // External Interrupt -#define IRQM_ETRIG_RISING 0x4000 // External Trigger rising-edge -#define IRQM_ETRIG_FALLING 0x8000 // External Trigger falling-edge +/* Interrupt Source Masks (SetITMask, ClearITMask, GetITStatus) */ +#define IRQM_ADC_FIFO_WRITE 0x0001 /* ADC FIFO Write */ +#define IRQM_CGT_RESET 0x0002 /* Reset CGT */ +#define IRQM_CGT_PAUSE 0x0008 /* Pause CGT */ +#define IRQM_ADC_ABOUT_CNT 0x0010 /* About Counter out */ +#define IRQM_ADC_DELAY_CNT 0x0020 /* Delay Counter out */ +#define IRQM_ADC_SAMPLE_CNT 0x0040 /* ADC Sample Counter */ +#define IRQM_DAC1_UCNT 0x0080 /* DAC1 Update Counter */ +#define IRQM_DAC2_UCNT 0x0100 /* DAC2 Update Counter */ +#define IRQM_UTC1 0x0200 /* User TC1 out */ +#define IRQM_UTC1_INV 0x0400 /* User TC1 out, inverted */ +#define IRQM_UTC2 0x0800 /* User TC2 out */ +#define IRQM_DIGITAL_IT 0x1000 /* Digital Interrupt */ +#define IRQM_EXTERNAL_IT 0x2000 /* External Interrupt */ +#define IRQM_ETRIG_RISING 0x4000 /* External Trigger rising-edge */ +#define IRQM_ETRIG_FALLING 0x8000 /* External Trigger falling-edge */ -// DMA Request Sources (LAS0) -#define DMAS_DISABLED 0x0 // DMA Disabled -#define DMAS_ADC_SCNT 0x1 // ADC Sample Counter -#define DMAS_DAC1_UCNT 0x2 // D/A1 Update Counter -#define DMAS_DAC2_UCNT 0x3 // D/A2 Update Counter -#define DMAS_UTC1 0x4 // User TC1 out -#define DMAS_ADFIFO_HALF_FULL 0x8 // A/D FIFO half full -#define DMAS_DAC1_FIFO_HALF_EMPTY 0x9 // D/A1 FIFO half empty -#define DMAS_DAC2_FIFO_HALF_EMPTY 0xA // D/A2 FIFO half empty +/* DMA Request Sources (LAS0) */ +#define DMAS_DISABLED 0x0 /* DMA Disabled */ +#define DMAS_ADC_SCNT 0x1 /* ADC Sample Counter */ +#define DMAS_DAC1_UCNT 0x2 /* D/A1 Update Counter */ +#define DMAS_DAC2_UCNT 0x3 /* D/A2 Update Counter */ +#define DMAS_UTC1 0x4 /* User TC1 out */ +#define DMAS_ADFIFO_HALF_FULL 0x8 /* A/D FIFO half full */ +#define DMAS_DAC1_FIFO_HALF_EMPTY 0x9 /* D/A1 FIFO half empty */ +#define DMAS_DAC2_FIFO_HALF_EMPTY 0xA /* D/A2 FIFO half empty */ -// DMA Local Addresses (0x40000000+LAS1 offset) -#define DMALADDR_ADC 0x40000000 // A/D FIFO -#define DMALADDR_HDIN 0x40000004 // High Speed Digital Input FIFO -#define DMALADDR_DAC1 0x40000008 // D/A1 FIFO -#define DMALADDR_DAC2 0x4000000C // D/A2 FIFO +/* DMA Local Addresses (0x40000000+LAS1 offset) */ +#define DMALADDR_ADC 0x40000000 /* A/D FIFO */ +#define DMALADDR_HDIN 0x40000004 /* High Speed Digital Input FIFO */ +#define DMALADDR_DAC1 0x40000008 /* D/A1 FIFO */ +#define DMALADDR_DAC2 0x4000000C /* D/A2 FIFO */ -// Port 0 compare modes (SetDIO0CompareMode) -#define DIO_MODE_EVENT 0 // Event Mode -#define DIO_MODE_MATCH 1 // Match Mode +/* Port 0 compare modes (SetDIO0CompareMode) */ +#define DIO_MODE_EVENT 0 /* Event Mode */ +#define DIO_MODE_MATCH 1 /* Match Mode */ -// Digital Table Enable (Port 1 disable) -#define DTBL_DISABLE 0 // Enable Digital Table -#define DTBL_ENABLE 1 // Disable Digital Table +/* Digital Table Enable (Port 1 disable) */ +#define DTBL_DISABLE 0 /* Enable Digital Table */ +#define DTBL_ENABLE 1 /* Disable Digital Table */ -// Sampling Signal for High Speed Digital Input (SetHdinStart) -#define HDIN_SOFTWARE 0x0 // Software Trigger -#define HDIN_ADC 0x1 // A/D Conversion Signal -#define HDIN_UTC0 0x2 // User TC out 0 -#define HDIN_UTC1 0x3 // User TC out 1 -#define HDIN_UTC2 0x4 // User TC out 2 -#define HDIN_EPCLK 0x5 // External Pacer Clock -#define HDIN_ETRG 0x6 // External Trigger +/* Sampling Signal for High Speed Digital Input (SetHdinStart) */ +#define HDIN_SOFTWARE 0x0 /* Software Trigger */ +#define HDIN_ADC 0x1 /* A/D Conversion Signal */ +#define HDIN_UTC0 0x2 /* User TC out 0 */ +#define HDIN_UTC1 0x3 /* User TC out 1 */ +#define HDIN_UTC2 0x4 /* User TC out 2 */ +#define HDIN_EPCLK 0x5 /* External Pacer Clock */ +#define HDIN_ETRG 0x6 /* External Trigger */ -// Channel Gain Table / Channel Gain Latch -#define CSC_LATCH 0 // Channel Gain Latch mode -#define CSC_CGT 1 // Channel Gain Table mode +/* Channel Gain Table / Channel Gain Latch */ +#define CSC_LATCH 0 /* Channel Gain Latch mode */ +#define CSC_CGT 1 /* Channel Gain Table mode */ -// Channel Gain Table Pause Enable -#define CGT_PAUSE_DISABLE 0 // Channel Gain Table Pause Disable -#define CGT_PAUSE_ENABLE 1 // Channel Gain Table Pause Enable +/* Channel Gain Table Pause Enable */ +#define CGT_PAUSE_DISABLE 0 /* Channel Gain Table Pause Disable */ +#define CGT_PAUSE_ENABLE 1 /* Channel Gain Table Pause Enable */ -// DAC output type/range (p63) -#define AOUT_UNIP5 0 // 0..+5 Volt -#define AOUT_UNIP10 1 // 0..+10 Volt -#define AOUT_BIP5 2 // -5..+5 Volt -#define AOUT_BIP10 3 // -10..+10 Volt +/* DAC output type/range (p63) */ +#define AOUT_UNIP5 0 /* 0..+5 Volt */ +#define AOUT_UNIP10 1 /* 0..+10 Volt */ +#define AOUT_BIP5 2 /* -5..+5 Volt */ +#define AOUT_BIP10 3 /* -10..+10 Volt */ -// Ghannel Gain Table field definitions (p61) -// Gain +/* Ghannel Gain Table field definitions (p61) */ +/* Gain */ #define GAIN1 0 #define GAIN2 1 #define GAIN4 2 @@ -398,15 +398,15 @@ #define GAIN64 6 #define GAIN128 7 -// Input range/polarity -#define AIN_BIP5 0 // -5..+5 Volt -#define AIN_BIP10 1 // -10..+10 Volt -#define AIN_UNIP10 2 // 0..+10 Volt +/* Input range/polarity */ +#define AIN_BIP5 0 /* -5..+5 Volt */ +#define AIN_BIP10 1 /* -10..+10 Volt */ +#define AIN_UNIP10 2 /* 0..+10 Volt */ -// non referenced single ended select bit -#define NRSE_AGND 0 // AGND referenced SE input -#define NRSE_AINS 1 // AIN SENSE referenced SE input +/* non referenced single ended select bit */ +#define NRSE_AGND 0 /* AGND referenced SE input */ +#define NRSE_AINS 1 /* AIN SENSE referenced SE input */ -// single ended vs differential -#define GND_SE 0 // Single-Ended -#define GND_DIFF 1 // Differential +/* single ended vs differential */ +#define GND_SE 0 /* Single-Ended */ +#define GND_DIFF 1 /* Differential */ diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c new file mode 100644 index 000000000000..334ac5773a13 --- /dev/null +++ b/drivers/staging/comedi/drivers/rti800.c @@ -0,0 +1,458 @@ +/* + comedi/drivers/rti800.c + Hardware driver for Analog Devices RTI-800/815 board + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1998 David A. Schleef + + 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: rti800 +Description: Analog Devices RTI-800/815 +Author: ds +Status: unknown +Updated: Fri, 05 Sep 2008 14:50:44 +0100 +Devices: [Analog Devices] RTI-800 (rti800), RTI-815 (rti815) + +Configuration options: + [0] - I/O port base address + [1] - IRQ + [2] - A/D reference + 0 = differential + 1 = pseudodifferential (common) + 2 = single-ended + [3] - A/D range + 0 = [-10,10] + 1 = [-5,5] + 2 = [0,10] + [4] - A/D encoding + 0 = two's complement + 1 = straight binary + [5] - DAC 0 range + 0 = [-10,10] + 1 = [0,10] + [6] - DAC 0 encoding + 0 = two's complement + 1 = straight binary + [7] - DAC 1 range (same as DAC 0) + [8] - DAC 1 encoding (same as DAC 0) +*/ + +#include "../comedidev.h" + +#include + +#define RTI800_SIZE 16 + +#define RTI800_CSR 0 +#define RTI800_MUXGAIN 1 +#define RTI800_CONVERT 2 +#define RTI800_ADCLO 3 +#define RTI800_ADCHI 4 +#define RTI800_DAC0LO 5 +#define RTI800_DAC0HI 6 +#define RTI800_DAC1LO 7 +#define RTI800_DAC1HI 8 +#define RTI800_CLRFLAGS 9 +#define RTI800_DI 10 +#define RTI800_DO 11 +#define RTI800_9513A_DATA 12 +#define RTI800_9513A_CNTRL 13 +#define RTI800_9513A_STATUS 13 + +/* + * flags for CSR register + */ + +#define RTI800_BUSY 0x80 +#define RTI800_DONE 0x40 +#define RTI800_OVERRUN 0x20 +#define RTI800_TCR 0x10 +#define RTI800_DMA_ENAB 0x08 +#define RTI800_INTR_TC 0x04 +#define RTI800_INTR_EC 0x02 +#define RTI800_INTR_OVRN 0x01 + +#define Am9513_8BITBUS + +#define Am9513_output_control(a) outb(a,dev->iobase+RTI800_9513A_CNTRL) +#define Am9513_output_data(a) outb(a,dev->iobase+RTI800_9513A_DATA) +#define Am9513_input_data() inb(dev->iobase+RTI800_9513A_DATA) +#define Am9513_input_status() inb(dev->iobase+RTI800_9513A_STATUS) + +#include "am9513.h" + +static const struct comedi_lrange range_rti800_ai_10_bipolar = { 4, { + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.02) + } +}; +static const struct comedi_lrange range_rti800_ai_5_bipolar = { 4, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.01) + } +}; +static const struct comedi_lrange range_rti800_ai_unipolar = { 4, { + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.02) + } +}; + +struct rti800_board { + + const char *name; + int has_ao; +}; + +static const struct rti800_board boardtypes[] = { + {"rti800", 0}, + {"rti815", 1}, +}; + +#define this_board ((const struct rti800_board *)dev->board_ptr) + +static int rti800_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int rti800_detach(struct comedi_device * dev); +static struct comedi_driver driver_rti800 = { + driver_name:"rti800", + module:THIS_MODULE, + attach:rti800_attach, + detach:rti800_detach, + num_names:sizeof(boardtypes) / sizeof(struct rti800_board), + board_name:&boardtypes[0].name, + offset:sizeof(struct rti800_board), +}; + +COMEDI_INITCLEANUP(driver_rti800); + +static irqreturn_t rti800_interrupt(int irq, void *dev PT_REGS_ARG); + +struct rti800_private { + enum { + adc_diff, adc_pseudodiff, adc_singleended + } adc_mux; + enum { + adc_bipolar10, adc_bipolar5, adc_unipolar10 + } adc_range; + enum { + adc_2comp, adc_straight + } adc_coding; + enum { + dac_bipolar10, dac_unipolar10 + } dac0_range, dac1_range; + enum { + dac_2comp, dac_straight + } dac0_coding, dac1_coding; + const struct comedi_lrange *ao_range_type_list[2]; + unsigned int ao_readback[2]; + int muxgain_bits; +}; + +#define devpriv ((struct rti800_private *)dev->private) + +#define RTI800_TIMEOUT 100 + +static irqreturn_t rti800_interrupt(int irq, void *dev PT_REGS_ARG) +{ + return IRQ_HANDLED; +} + +// settling delay times in usec for different gains +static const int gaindelay[] = { 10, 20, 40, 80 }; + +static int rti800_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, t; + int status; + int chan = CR_CHAN(insn->chanspec); + unsigned gain = CR_RANGE(insn->chanspec); + unsigned muxgain_bits; + + inb(dev->iobase + RTI800_ADCHI); + outb(0, dev->iobase + RTI800_CLRFLAGS); + + muxgain_bits = chan | (gain << 5); + if (muxgain_bits != devpriv->muxgain_bits) { + devpriv->muxgain_bits = muxgain_bits; + outb(devpriv->muxgain_bits, dev->iobase + RTI800_MUXGAIN); + /* without a delay here, the RTI_OVERRUN bit + * gets set, and you will have an error. */ + if (insn->n > 0) { + BUG_ON(gain >= + sizeof(gaindelay) / sizeof(gaindelay[0])); + comedi_udelay(gaindelay[gain]); + } + } + + for (i = 0; i < insn->n; i++) { + outb(0, dev->iobase + RTI800_CONVERT); + for (t = RTI800_TIMEOUT; t; t--) { + status = inb(dev->iobase + RTI800_CSR); + if (status & RTI800_OVERRUN) { + rt_printk("rti800: a/d overrun\n"); + outb(0, dev->iobase + RTI800_CLRFLAGS); + return -EIO; + } + if (status & RTI800_DONE) + break; + comedi_udelay(1); + } + if (t == 0) { + rt_printk("rti800: timeout\n"); + return -ETIME; + } + data[i] = inb(dev->iobase + RTI800_ADCLO); + data[i] |= (0xf & inb(dev->iobase + RTI800_ADCHI)) << 8; + + if (devpriv->adc_coding == adc_2comp) { + data[i] ^= 0x800; + } + } + + return i; +} + +static int rti800_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +static int rti800_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + int d; + int i; + + for (i = 0; i < insn->n; i++) { + devpriv->ao_readback[chan] = d = data[i]; + if (devpriv->dac0_coding == dac_2comp) { + d ^= 0x800; + } + outb(d & 0xff, + dev->iobase + (chan ? RTI800_DAC1LO : RTI800_DAC0LO)); + outb(d >> 8, + dev->iobase + (chan ? RTI800_DAC1HI : RTI800_DAC0HI)); + } + return i; +} + +static int rti800_di_insn_bits(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 + RTI800_DI); + return 2; +} + +static int rti800_do_insn_bits(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]; + /* Outputs are inverted... */ + outb(s->state ^ 0xff, dev->iobase + RTI800_DO); + } + + data[1] = s->state; + + return 2; +} + +/* + options[0] - I/O port + options[1] - irq + options[2] - a/d mux + 0=differential, 1=pseudodiff, 2=single + options[3] - a/d range + 0=bipolar10, 1=bipolar5, 2=unipolar10 + options[4] - a/d coding + 0=2's comp, 1=straight binary + options[5] - dac0 range + 0=bipolar10, 1=unipolar10 + options[6] - dac0 coding + 0=2's comp, 1=straight binary + options[7] - dac1 range + options[8] - dac1 coding + */ + +static int rti800_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + unsigned int irq; + unsigned long iobase; + int ret; + struct comedi_subdevice *s; + + iobase = it->options[0]; + printk("comedi%d: rti800: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, RTI800_SIZE, "rti800")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + +#ifdef DEBUG + printk("fingerprint=%x,%x,%x,%x,%x ", + inb(dev->iobase + 0), + inb(dev->iobase + 1), + inb(dev->iobase + 2), + inb(dev->iobase + 3), inb(dev->iobase + 4)); +#endif + + outb(0, dev->iobase + RTI800_CSR); + inb(dev->iobase + RTI800_ADCHI); + outb(0, dev->iobase + RTI800_CLRFLAGS); + + irq = it->options[1]; + if (irq) { + printk("( irq = %u )", irq); + if ((ret = comedi_request_irq(irq, rti800_interrupt, 0, + "rti800", dev)) < 0) { + printk(" Failed to allocate IRQ\n"); + return ret; + } + dev->irq = irq; + } else { + printk("( no irq )"); + } + + dev->board_name = this_board->name; + + if ((ret = alloc_subdevices(dev, 4)) < 0) + return ret; + if ((ret = alloc_private(dev, sizeof(struct rti800_private))) < 0) + return ret; + + devpriv->adc_mux = it->options[2]; + devpriv->adc_range = it->options[3]; + devpriv->adc_coding = it->options[4]; + devpriv->dac0_range = it->options[5]; + devpriv->dac0_coding = it->options[6]; + devpriv->dac1_range = it->options[7]; + devpriv->dac1_coding = it->options[8]; + devpriv->muxgain_bits = -1; + + s = dev->subdevices + 0; + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = (devpriv->adc_mux ? 16 : 8); + s->insn_read = rti800_ai_insn_read; + s->maxdata = 0xfff; + switch (devpriv->adc_range) { + case adc_bipolar10: + s->range_table = &range_rti800_ai_10_bipolar; + break; + case adc_bipolar5: + s->range_table = &range_rti800_ai_5_bipolar; + break; + case adc_unipolar10: + s->range_table = &range_rti800_ai_unipolar; + break; + } + + s++; + if (this_board->has_ao) { + /* ao subdevice (only on rti815) */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->insn_read = rti800_ao_insn_read; + s->insn_write = rti800_ao_insn_write; + s->maxdata = 0xfff; + s->range_table_list = devpriv->ao_range_type_list; + switch (devpriv->dac0_range) { + case dac_bipolar10: + devpriv->ao_range_type_list[0] = &range_bipolar10; + break; + case dac_unipolar10: + devpriv->ao_range_type_list[0] = &range_unipolar10; + break; + } + switch (devpriv->dac1_range) { + case dac_bipolar10: + devpriv->ao_range_type_list[1] = &range_bipolar10; + break; + case dac_unipolar10: + devpriv->ao_range_type_list[1] = &range_unipolar10; + break; + } + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + s++; + /* di */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 8; + s->insn_bits = rti800_di_insn_bits; + s->maxdata = 1; + s->range_table = &range_digital; + + s++; + /* do */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 8; + s->insn_bits = rti800_do_insn_bits; + s->maxdata = 1; + s->range_table = &range_digital; + +/* don't yet know how to deal with counter/timers */ +#if 0 + s++; + /* do */ + s->type = COMEDI_SUBD_TIMER; +#endif + + printk("\n"); + + return 0; +} + +static int rti800_detach(struct comedi_device * dev) +{ + printk("comedi%d: rti800: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, RTI800_SIZE); + + if (dev->irq) + comedi_free_irq(dev->irq, dev); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c new file mode 100644 index 000000000000..cc2c385db0b0 --- /dev/null +++ b/drivers/staging/comedi/drivers/rti802.c @@ -0,0 +1,151 @@ +/* + comedi/drivers/rti802.c + Hardware driver for Analog Devices RTI-802 board + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999 Anders Blomdell + + 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: rti802 +Description: Analog Devices RTI-802 +Author: Anders Blomdell +Devices: [Analog Devices] RTI-802 (rti802) +Status: works + +Configuration Options: + [0] - i/o base + [1] - unused + [2] - dac#0 0=two's comp, 1=straight + [3] - dac#0 0=bipolar, 1=unipolar + [4] - dac#1 ... + ... + [17] - dac#7 ... +*/ + +#include "../comedidev.h" + +#include + +#define RTI802_SIZE 4 + +#define RTI802_SELECT 0 +#define RTI802_DATALOW 1 +#define RTI802_DATAHIGH 2 + +static int rti802_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int rti802_detach(struct comedi_device * dev); +static struct comedi_driver driver_rti802 = { + driver_name:"rti802", + module:THIS_MODULE, + attach:rti802_attach, + detach:rti802_detach, +}; + +COMEDI_INITCLEANUP(driver_rti802); + +struct rti802_private { + enum { + dac_2comp, dac_straight + } dac_coding[8]; + const struct comedi_lrange *range_type_list[8]; + unsigned int ao_readback[8]; +}; + +#define devpriv ((struct rti802_private *)dev->private) + +static int rti802_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; + + return i; +} + +static int rti802_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i, d; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + d = devpriv->ao_readback[chan] = data[i]; + if (devpriv->dac_coding[chan] == dac_2comp) + d ^= 0x800; + outb(chan, dev->iobase + RTI802_SELECT); + outb(d & 0xff, dev->iobase + RTI802_DATALOW); + outb(d >> 8, dev->iobase + RTI802_DATAHIGH); + } + return i; +} + +static int rti802_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int i; + unsigned long iobase; + + iobase = it->options[0]; + printk("comedi%d: rti802: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, RTI802_SIZE, "rti802")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + dev->board_name = "rti802"; + + if (alloc_subdevices(dev, 1) < 0 + || alloc_private(dev, sizeof(struct rti802_private))) { + return -ENOMEM; + } + + s = dev->subdevices; + /* ao subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 0xfff; + s->n_chan = 8; + s->insn_read = rti802_ao_insn_read; + s->insn_write = rti802_ao_insn_write; + s->range_table_list = devpriv->range_type_list; + + for (i = 0; i < 8; i++) { + devpriv->dac_coding[i] = (it->options[3 + 2 * i]) + ? (dac_straight) + : (dac_2comp); + devpriv->range_type_list[i] = (it->options[2 + 2 * i]) + ? &range_unipolar10 : &range_bipolar10; + } + + printk("\n"); + + return 0; +} + +static int rti802_detach(struct comedi_device * dev) +{ + printk("comedi%d: rti802: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, RTI802_SIZE); + + return 0; +} diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c new file mode 100644 index 000000000000..a7b6f711afca --- /dev/null +++ b/drivers/staging/comedi/drivers/s526.c @@ -0,0 +1,977 @@ +/* + comedi/drivers/s526.c + Sensoray s526 Comedi driver + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: s526 +Description: Sensoray 526 driver +Devices: [Sensoray] 526 (s526) +Author: Richie + Everett Wang +Updated: Thu, 14 Sep. 2006 +Status: experimental + +Encoder works +Analog input works +Analog output works +PWM output works +Commands are not supported yet. + +Configuration Options: + +comedi_config /dev/comedi0 s526 0x2C0,0x3 + +*/ + +#include "../comedidev.h" +#include + +#define S526_SIZE 64 + +#define S526_START_AI_CONV 0 +#define S526_AI_READ 0 + +/* Ports */ +#define S526_IOSIZE 0x40 +#define S526_NUM_PORTS 27 + +/* registers */ +#define REG_TCR 0x00 +#define REG_WDC 0x02 +#define REG_DAC 0x04 +#define REG_ADC 0x06 +#define REG_ADD 0x08 +#define REG_DIO 0x0A +#define REG_IER 0x0C +#define REG_ISR 0x0E +#define REG_MSC 0x10 +#define REG_C0L 0x12 +#define REG_C0H 0x14 +#define REG_C0M 0x16 +#define REG_C0C 0x18 +#define REG_C1L 0x1A +#define REG_C1H 0x1C +#define REG_C1M 0x1E +#define REG_C1C 0x20 +#define REG_C2L 0x22 +#define REG_C2H 0x24 +#define REG_C2M 0x26 +#define REG_C2C 0x28 +#define REG_C3L 0x2A +#define REG_C3H 0x2C +#define REG_C3M 0x2E +#define REG_C3C 0x30 +#define REG_EED 0x32 +#define REG_EEC 0x34 + +static const int s526_ports[] = { + REG_TCR, + REG_WDC, + REG_DAC, + REG_ADC, + REG_ADD, + REG_DIO, + REG_IER, + REG_ISR, + REG_MSC, + REG_C0L, + REG_C0H, + REG_C0M, + REG_C0C, + REG_C1L, + REG_C1H, + REG_C1M, + REG_C1C, + REG_C2L, + REG_C2H, + REG_C2M, + REG_C2C, + REG_C3L, + REG_C3H, + REG_C3M, + REG_C3C, + REG_EED, + REG_EEC +}; + +struct counter_mode_register_t { + unsigned short coutSource:1; + unsigned short coutPolarity:1; + unsigned short autoLoadResetRcap:3; + unsigned short hwCtEnableSource:2; + unsigned short ctEnableCtrl:2; + unsigned short clockSource:2; + unsigned short countDir:1; + unsigned short countDirCtrl:1; + unsigned short outputRegLatchCtrl:1; + unsigned short preloadRegSel:1; + unsigned short reserved:1; +}; + +union { + struct counter_mode_register_t reg; + unsigned short value; +} cmReg; + +#define MAX_GPCT_CONFIG_DATA 6 + +/* Different Application Classes for GPCT Subdevices */ +/* The list is not exhaustive and needs discussion! */ +enum S526_GPCT_APP_CLASS { + CountingAndTimeMeasurement, + SinglePulseGeneration, + PulseTrainGeneration, + PositionMeasurement, + Miscellaneous +}; + +/* Config struct for different GPCT subdevice Application Classes and + their options +*/ +struct s526GPCTConfig { + enum S526_GPCT_APP_CLASS app; + int data[MAX_GPCT_CONFIG_DATA]; +}; + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct s526_board { + const char *name; + int gpct_chans; + int gpct_bits; + int ad_chans; + int ad_bits; + int da_chans; + int da_bits; + int have_dio; +}; + +static const struct s526_board s526_boards[] = { + { + name: "s526", + gpct_chans:4, + gpct_bits:24, + ad_chans:8, + ad_bits: 16, + da_chans:4, + da_bits: 16, + have_dio:1, + } +}; + +#define ADDR_REG(reg) (dev->iobase + (reg)) +#define ADDR_CHAN_REG(reg, chan) (dev->iobase + (reg) + (chan) * 8) + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct s526_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct s526_private { + + int data; + + /* would be useful for a PCI device */ + struct pci_dev *pci_dev; + + /* Used for AO readback */ + unsigned int ao_readback[2]; + + struct s526GPCTConfig s526_gpct_config[4]; + unsigned short s526_ai_config; +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct s526_private *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int s526_detach(struct comedi_device * dev); +static struct comedi_driver driver_s526 = { + driver_name:"s526", + module:THIS_MODULE, + attach:s526_attach, + detach:s526_detach, +/* It is not necessary to implement the following members if you are + * writing a driver for a ISA PnP or PCI card */ + /* Most drivers will support multiple types of boards by + * having an array of board structures. These were defined + * in s526_boards[] above. Note that the element 'name' + * was first in the structure -- Comedi uses this fact to + * extract the name of the board without knowing any details + * about the structure except for its length. + * When a device is attached (by comedi_config), the name + * of the device is given to Comedi, and Comedi tries to + * match it by going through the list of board names. If + * there is a match, the address of the pointer is put + * into dev->board_ptr and driver->attach() is called. + * + * Note that these are not necessary if you can determine + * the type of board in software. ISA PnP, PCI, and PCMCIA + * devices are such boards. + */ + board_name:&s526_boards[0].name, + offset:sizeof(struct s526_board), + num_names:sizeof(s526_boards) / sizeof(struct s526_board), +}; + +static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int s526_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + int iobase; + int i, n; +// short value; +// int subdev_channel = 0; + + printk("comedi%d: s526: ", dev->minor); + + iobase = it->options[0]; + if (!iobase || !request_region(iobase, S526_IOSIZE, thisboard->name)) { + comedi_error(dev, "I/O port conflict"); + return -EIO; + } + dev->iobase = iobase; + + printk("iobase=0x%lx\n", dev->iobase); + + /*** make it a little quieter, exw, 8/29/06 + for (i = 0; i < S526_NUM_PORTS; i++) { + printk("0x%02x: 0x%04x\n", ADDR_REG(s526_ports[i]), inw(ADDR_REG(s526_ports[i]))); + } + ***/ + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_ptr = &s526_boards[0]; + + dev->board_name = thisboard->name; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct s526_private)) < 0) + return -ENOMEM; + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + dev->n_subdevices = 4; + if (alloc_subdevices(dev, dev->n_subdevices) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* GENERAL-PURPOSE COUNTER/TIME (GPCT) */ + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL; + /* KG: What does SDF_LSAMPL (see multiq3.c) mean? */ + s->n_chan = thisboard->gpct_chans; + s->maxdata = 0x00ffffff; /* 24 bit counter */ + s->insn_read = s526_gpct_rinsn; + s->insn_config = s526_gpct_insn_config; + s->insn_write = s526_gpct_winsn; + + /* Command are not implemented yet, however they are necessary to + allocate the necessary memory for the comedi_async struct (used + to trigger the GPCT in case of pulsegenerator function */ + //s->do_cmd = s526_gpct_cmd; + //s->do_cmdtest = s526_gpct_cmdtest; + //s->cancel = s526_gpct_cancel; + + s = dev->subdevices + 1; + //dev->read_subdev=s; + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + /* we support differential */ + s->subdev_flags = SDF_READABLE | SDF_DIFF; + /* channels 0 to 7 are the regular differential inputs */ + /* channel 8 is "reference 0" (+10V), channel 9 is "reference 1" (0V) */ + s->n_chan = 10; + s->maxdata = 0xffff; + s->range_table = &range_bipolar10; + s->len_chanlist = 16; /* This is the maximum chanlist length that + the board can handle */ + s->insn_read = s526_ai_rinsn; + s->insn_config = s526_ai_insn_config; + + s = dev->subdevices + 2; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->range_table = &range_bipolar10; + s->insn_write = s526_ao_winsn; + s->insn_read = s526_ao_rinsn; + + s = dev->subdevices + 3; + /* digital i/o subdevice */ + if (thisboard->have_dio) { + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 2; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = s526_dio_insn_bits; + s->insn_config = s526_dio_insn_config; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + printk("attached\n"); + + return 1; + +#if 0 + // Example of Counter Application + //One-shot (software trigger) + cmReg.reg.coutSource = 0; // out RCAP + cmReg.reg.coutPolarity = 1; // Polarity inverted + cmReg.reg.autoLoadResetRcap = 1; // Auto load 0:disabled, 1:enabled + cmReg.reg.hwCtEnableSource = 3; // NOT RCAP + cmReg.reg.ctEnableCtrl = 2; // Hardware + cmReg.reg.clockSource = 2; // Internal + cmReg.reg.countDir = 1; // Down + cmReg.reg.countDirCtrl = 1; // Software + cmReg.reg.outputRegLatchCtrl = 0; // latch on read + cmReg.reg.preloadRegSel = 0; // PR0 + cmReg.reg.reserved = 0; + + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + + outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + + outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Reset the counter + outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Load the counter from PR0 + + outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Reset RCAP (fires one-shot) + +#else + + // Set Counter Mode Register + cmReg.reg.coutSource = 0; // out RCAP + cmReg.reg.coutPolarity = 0; // Polarity inverted + cmReg.reg.autoLoadResetRcap = 0; // Auto load disabled + cmReg.reg.hwCtEnableSource = 2; // NOT RCAP + cmReg.reg.ctEnableCtrl = 1; // 1: Software, >1 : Hardware + cmReg.reg.clockSource = 3; // x4 + cmReg.reg.countDir = 0; // up + cmReg.reg.countDirCtrl = 0; // quadrature + cmReg.reg.outputRegLatchCtrl = 0; // latch on read + cmReg.reg.preloadRegSel = 0; // PR0 + cmReg.reg.reserved = 0; + + n = 0; + printk("Mode reg=0x%04x, 0x%04lx\n", cmReg.value, ADDR_CHAN_REG(REG_C0M, + n)); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n)); + udelay(1000); + printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n))); + + // Load the pre-laod register high word +// value = (short) (0x55); +// outw(value, ADDR_CHAN_REG(REG_C0H, n)); + + // Load the pre-laod register low word +// value = (short)(0xaa55); +// outw(value, ADDR_CHAN_REG(REG_C0L, n)); + + // Write the Counter Control Register +// outw(value, ADDR_CHAN_REG(REG_C0C, 0)); + + // Reset the counter if it is software preload + if (cmReg.reg.autoLoadResetRcap == 0) { + outw(0x8000, ADDR_CHAN_REG(REG_C0C, n)); // Reset the counter + outw(0x4000, ADDR_CHAN_REG(REG_C0C, n)); // Load the counter from PR0 + } + + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n)); + udelay(1000); + printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n))); + +#endif + printk("Current registres:\n"); + + for (i = 0; i < S526_NUM_PORTS; i++) { + printk("0x%02lx: 0x%04x\n", ADDR_REG(s526_ports[i]), + inw(ADDR_REG(s526_ports[i]))); + } + return 1; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int s526_detach(struct comedi_device * dev) +{ + printk("comedi%d: s526: remove\n", dev->minor); + + if (dev->iobase > 0) + release_region(dev->iobase, S526_IOSIZE); + + return 0; +} + +static int s526_gpct_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; // counts the Data + int counter_channel = CR_CHAN(insn->chanspec); + unsigned short datalow; + unsigned short datahigh; + + // Check if (n > 0) + if (insn->n <= 0) { + printk("s526: INSN_READ: n should be > 0\n"); + return -EINVAL; + } + // Read the low word first + for (i = 0; i < insn->n; i++) { + datalow = inw(ADDR_CHAN_REG(REG_C0L, counter_channel)); + datahigh = inw(ADDR_CHAN_REG(REG_C0H, counter_channel)); + data[i] = (int)(datahigh & 0x00FF); + data[i] = (data[i] << 16) | (datalow & 0xFFFF); +// printk("s526 GPCT[%d]: %x(0x%04x, 0x%04x)\n", counter_channel, data[i], datahigh, datalow); + } + return i; +} + +static int s526_gpct_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int subdev_channel = CR_CHAN(insn->chanspec); // Unpack chanspec + int i; + short value; + +// printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel); + + for (i = 0; i < MAX_GPCT_CONFIG_DATA; i++) { + devpriv->s526_gpct_config[subdev_channel].data[i] = + insn->data[i]; +// printk("data[%d]=%x\n", i, insn->data[i]); + } + + // Check what type of Counter the user requested, data[0] contains + // the Application type + switch (insn->data[0]) { + case INSN_CONFIG_GPCT_QUADRATURE_ENCODER: + /* + data[0]: Application Type + data[1]: Counter Mode Register Value + data[2]: Pre-load Register Value + data[3]: Conter Control Register + */ + printk("s526: GPCT_INSN_CONFIG: Configuring Encoder\n"); + devpriv->s526_gpct_config[subdev_channel].app = + PositionMeasurement; + +/* + // Example of Counter Application + //One-shot (software trigger) + cmReg.reg.coutSource = 0; // out RCAP + cmReg.reg.coutPolarity = 1; // Polarity inverted + cmReg.reg.autoLoadResetRcap = 0; // Auto load disabled + cmReg.reg.hwCtEnableSource = 3; // NOT RCAP + cmReg.reg.ctEnableCtrl = 2; // Hardware + cmReg.reg.clockSource = 2; // Internal + cmReg.reg.countDir = 1; // Down + cmReg.reg.countDirCtrl = 1; // Software + cmReg.reg.outputRegLatchCtrl = 0; // latch on read + cmReg.reg.preloadRegSel = 0; // PR0 + cmReg.reg.reserved = 0; + + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + + outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + + outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Reset the counter + outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Load the counter from PR0 + + outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Reset RCAP (fires one-shot) + +*/ + +#if 1 + // Set Counter Mode Register + cmReg.reg.coutSource = 0; // out RCAP + cmReg.reg.coutPolarity = 0; // Polarity inverted + cmReg.reg.autoLoadResetRcap = 0; // Auto load disabled + cmReg.reg.hwCtEnableSource = 2; // NOT RCAP + cmReg.reg.ctEnableCtrl = 1; // 1: Software, >1 : Hardware + cmReg.reg.clockSource = 3; // x4 + cmReg.reg.countDir = 0; // up + cmReg.reg.countDirCtrl = 0; // quadrature + cmReg.reg.outputRegLatchCtrl = 0; // latch on read + cmReg.reg.preloadRegSel = 0; // PR0 + cmReg.reg.reserved = 0; + + // Set Counter Mode Register +// printk("s526: Counter Mode register=%x\n", cmReg.value); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + + // Reset the counter if it is software preload + if (cmReg.reg.autoLoadResetRcap == 0) { + outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Reset the counter +// outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Load the counter from PR0 + } +#else + cmReg.reg.countDirCtrl = 0; // 0 quadrature, 1 software control + + // data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4 + if (insn->data[1] == GPCT_X2) { + cmReg.reg.clockSource = 1; + } else if (insn->data[1] == GPCT_X4) { + cmReg.reg.clockSource = 2; + } else { + cmReg.reg.clockSource = 0; + } + + // When to take into account the indexpulse: + if (insn->data[2] == GPCT_IndexPhaseLowLow) { + } else if (insn->data[2] == GPCT_IndexPhaseLowHigh) { + } else if (insn->data[2] == GPCT_IndexPhaseHighLow) { + } else if (insn->data[2] == GPCT_IndexPhaseHighHigh) { + } + // Take into account the index pulse? + if (insn->data[3] == GPCT_RESET_COUNTER_ON_INDEX) + cmReg.reg.autoLoadResetRcap = 4; // Auto load with INDEX^ + + // Set Counter Mode Register + cmReg.value = (short) (insn->data[1] & 0xFFFF); + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + + // Load the pre-laod register high word + value = (short) ((insn->data[2] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + + // Load the pre-laod register low word + value = (short) (insn->data[2] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + + // Write the Counter Control Register + if (insn->data[3] != 0) { + value = (short) (insn->data[3] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + } + // Reset the counter if it is software preload + if (cmReg.reg.autoLoadResetRcap == 0) { + outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Reset the counter + outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel)); // Load the counter from PR0 + } +#endif + break; + + case INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR: + /* + data[0]: Application Type + data[1]: Counter Mode Register Value + data[2]: Pre-load Register 0 Value + data[3]: Pre-load Register 1 Value + data[4]: Conter Control Register + */ + printk("s526: GPCT_INSN_CONFIG: Configuring SPG\n"); + devpriv->s526_gpct_config[subdev_channel].app = + SinglePulseGeneration; + + // Set Counter Mode Register + cmReg.value = (short) (insn->data[1] & 0xFFFF); + cmReg.reg.preloadRegSel = 0; // PR0 + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + + // Load the pre-laod register 0 high word + value = (short) ((insn->data[2] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + + // Load the pre-laod register 0 low word + value = (short) (insn->data[2] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + + // Set Counter Mode Register + cmReg.value = (short) (insn->data[1] & 0xFFFF); + cmReg.reg.preloadRegSel = 1; // PR1 + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + + // Load the pre-laod register 1 high word + value = (short) ((insn->data[3] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + + // Load the pre-laod register 1 low word + value = (short) (insn->data[3] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + + // Write the Counter Control Register + if (insn->data[3] != 0) { + value = (short) (insn->data[3] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + } + break; + + case INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR: + /* + data[0]: Application Type + data[1]: Counter Mode Register Value + data[2]: Pre-load Register 0 Value + data[3]: Pre-load Register 1 Value + data[4]: Conter Control Register + */ + printk("s526: GPCT_INSN_CONFIG: Configuring PTG\n"); + devpriv->s526_gpct_config[subdev_channel].app = + PulseTrainGeneration; + + // Set Counter Mode Register + cmReg.value = (short) (insn->data[1] & 0xFFFF); + cmReg.reg.preloadRegSel = 0; // PR0 + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + + // Load the pre-laod register 0 high word + value = (short) ((insn->data[2] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + + // Load the pre-laod register 0 low word + value = (short) (insn->data[2] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + + // Set Counter Mode Register + cmReg.value = (short) (insn->data[1] & 0xFFFF); + cmReg.reg.preloadRegSel = 1; // PR1 + outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel)); + + // Load the pre-laod register 1 high word + value = (short) ((insn->data[3] >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + + // Load the pre-laod register 1 low word + value = (short) (insn->data[3] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + + // Write the Counter Control Register + if (insn->data[3] != 0) { + value = (short) (insn->data[3] & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel)); + } + break; + + default: + printk("s526: unsupported GPCT_insn_config\n"); + return -EINVAL; + break; + } + + return insn->n; +} + +static int s526_gpct_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int subdev_channel = CR_CHAN(insn->chanspec); // Unpack chanspec + short value; + + printk("s526: GPCT_INSN_WRITE on channel %d\n", subdev_channel); + cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel)); + printk("s526: Counter Mode Register: %x\n", cmReg.value); + // Check what Application of Counter this channel is configured for + switch (devpriv->s526_gpct_config[subdev_channel].app) { + case PositionMeasurement: + printk("S526: INSN_WRITE: PM\n"); + outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H, + subdev_channel)); + outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel)); + break; + + case SinglePulseGeneration: + printk("S526: INSN_WRITE: SPG\n"); + outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H, + subdev_channel)); + outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel)); + break; + + case PulseTrainGeneration: + /* data[0] contains the PULSE_WIDTH + data[1] contains the PULSE_PERIOD + @pre PULSE_PERIOD > PULSE_WIDTH > 0 + The above periods must be expressed as a multiple of the + pulse frequency on the selected source + */ + printk("S526: INSN_WRITE: PTG\n"); + if ((insn->data[1] > insn->data[0]) && (insn->data[0] > 0)) { + (devpriv->s526_gpct_config[subdev_channel]).data[0] = + insn->data[0]; + (devpriv->s526_gpct_config[subdev_channel]).data[1] = + insn->data[1]; + } else { + printk("%d \t %d\n", insn->data[1], insn->data[2]); + printk("s526: INSN_WRITE: PTG: Problem with Pulse params\n"); + return -EINVAL; + } + + value = (short) ((*data >> 16) & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel)); + value = (short) (*data & 0xFFFF); + outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel)); + break; + default: // Impossible + printk("s526: INSN_WRITE: Functionality %d not implemented yet\n", devpriv->s526_gpct_config[subdev_channel].app); + return -EINVAL; + break; + } + // return the number of samples written + return insn->n; +} + +#define ISR_ADC_DONE 0x4 +static int s526_ai_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int result = -EINVAL; + + if (insn->n < 1) + return result; + + result = insn->n; + + /* data[0] : channels was set in relevant bits. + data[1] : delay + */ + /* COMMENT: abbotti 2008-07-24: I don't know why you'd want to + * enable channels here. The channel should be enabled in the + * INSN_READ handler. */ + + // Enable ADC interrupt + outw(ISR_ADC_DONE, ADDR_REG(REG_IER)); +// printk("s526: ADC current value: 0x%04x\n", inw(ADDR_REG(REG_ADC))); + devpriv->s526_ai_config = (data[0] & 0x3FF) << 5; + if (data[1] > 0) + devpriv->s526_ai_config |= 0x8000; //set the delay + + devpriv->s526_ai_config |= 0x0001; // ADC start bit. + + return result; +} + +/* + * "instructions" read/write data in "one-shot" or "software-triggered" + * mode. + */ +static int s526_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, i; + int chan = CR_CHAN(insn->chanspec); + unsigned short value; + unsigned int d; + unsigned int status; + + /* Set configured delay, enable channel for this channel only, + * select "ADC read" channel, set "ADC start" bit. */ + value = (devpriv->s526_ai_config & 0x8000) | + ((1 << 5) << chan) | (chan << 1) | 0x0001; + + /* convert n samples */ + for (n = 0; n < insn->n; n++) { + /* trigger conversion */ + outw(value, ADDR_REG(REG_ADC)); +// printk("s526: Wrote 0x%04x to ADC\n", value); +// printk("s526: ADC reg=0x%04x\n", inw(ADDR_REG(REG_ADC))); + +#define TIMEOUT 100 + /* wait for conversion to end */ + for (i = 0; i < TIMEOUT; i++) { + status = inw(ADDR_REG(REG_ISR)); + if (status & ISR_ADC_DONE) { + outw(ISR_ADC_DONE, ADDR_REG(REG_ISR)); + break; + } + } + if (i == TIMEOUT) { + /* rt_printk() should be used instead of printk() + * whenever the code can be called from real-time. */ + rt_printk("s526: ADC(0x%04x) timeout\n", + inw(ADDR_REG(REG_ISR))); + return -ETIMEDOUT; + } + + /* read data */ + d = inw(ADDR_REG(REG_ADD)); +// printk("AI[%d]=0x%04x\n", n, (unsigned short)(d & 0xFFFF)); + + /* munge data */ + data[n] = d ^ 0x8000; + } + + /* return the number of samples read/written */ + return n; +} + +static int s526_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + unsigned short val; + +// printk("s526_ao_winsn\n"); + val = chan << 1; +// outw(val, dev->iobase + REG_DAC); + outw(val, ADDR_REG(REG_DAC)); + + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { + /* a typical programming sequence */ +// outw(data[i], dev->iobase + REG_ADD); // write the data to preload register + outw(data[i], ADDR_REG(REG_ADD)); // write the data to preload register + devpriv->ao_readback[chan] = data[i]; +// outw(val + 1, dev->iobase + REG_DAC); // starts the D/A conversion. + outw(val + 1, ADDR_REG(REG_DAC)); // starts the D/A conversion. + } + + /* return the number of samples read/written */ + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. */ +static int s526_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +/* DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write */ +static int s526_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + /* Write out the new digital output lines */ + outw(s->state, ADDR_REG(REG_DIO)); + } + + /* on return, data[1] contains the value of the digital + * input and output lines. */ + data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF; // low 8 bits are the data + /* or we could just return the software copy of the output values if + * it was a purely digital output subdevice */ + //data[1]=s->state; + + return 2; +} + +static int s526_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + short value; + + printk("S526 DIO insn_config\n"); + + if (insn->n != 1) + return -EINVAL; + + value = inw(ADDR_REG(REG_DIO)); + + /* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ + + if (data[0] == COMEDI_OUTPUT) { + value |= 1 << (chan + 10); // bit 10/11 set the group 1/2's mode + s->io_bits |= (0xF << chan); + } else { + value &= ~(1 << (chan + 10)); // 1 is output, 0 is input. + s->io_bits &= ~(0xF << chan); + } + outw(value, ADDR_REG(REG_DIO)); + + return 1; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver_s526); diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 469ee8c474c9..30dec9dab19b 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -82,7 +82,7 @@ MODULE_AUTHOR("Gianluca Palli "); MODULE_DESCRIPTION("Sensoray 626 Comedi driver module"); MODULE_LICENSE("GPL"); -typedef struct s626_board_struct { +struct s626_board { const char *name; int ai_chans; int ai_bits; @@ -91,22 +91,22 @@ typedef struct s626_board_struct { int dio_chans; int dio_banks; int enc_chans; -} s626_board; +}; -static const s626_board s626_boards[] = { +static const struct s626_board s626_boards[] = { { name: "s626", - ai_chans:S626_ADC_CHANNELS, + ai_chans : S626_ADC_CHANNELS, ai_bits: 14, - ao_chans:S626_DAC_CHANNELS, + ao_chans : S626_DAC_CHANNELS, ao_bits: 13, - dio_chans:S626_DIO_CHANNELS, - dio_banks:S626_DIO_BANKS, - enc_chans:S626_ENCODER_CHANNELS, + dio_chans : S626_DIO_CHANNELS, + dio_banks : S626_DIO_BANKS, + enc_chans : S626_ENCODER_CHANNELS, } }; -#define thisboard ((const s626_board *)dev->board_ptr) +#define thisboard ((const struct s626_board *)dev->board_ptr) #define PCI_VENDOR_ID_S626 0x1131 #define PCI_DEVICE_ID_S626 0x7146 @@ -118,57 +118,49 @@ static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = { MODULE_DEVICE_TABLE(pci, s626_pci_table); -static int s626_attach(comedi_device * dev, comedi_devconfig * it); -static int s626_detach(comedi_device * dev); +static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int s626_detach(struct comedi_device *dev); -static comedi_driver driver_s626 = { +static struct comedi_driver driver_s626 = { driver_name:"s626", - module:THIS_MODULE, - attach:s626_attach, - detach:s626_detach, + module : THIS_MODULE, + attach : s626_attach, + detach : s626_detach, }; -typedef struct { +struct s626_private { struct pci_dev *pdev; void *base_addr; int got_regions; short allocatedBuf; - uint8_t ai_cmd_running; // ai_cmd is running - uint8_t ai_continous; // continous aquisition - int ai_sample_count; // number of samples to aquire - unsigned int ai_sample_timer; // time between samples in - // units of the timer - int ai_convert_count; // conversion counter - unsigned int ai_convert_timer; // time between conversion in - // units of the timer - uint16_t CounterIntEnabs; //Counter interrupt enable - //mask for MISC2 register. - uint8_t AdcItems; //Number of items in ADC poll - //list. - DMABUF RPSBuf; //DMA buffer used to hold ADC - //(RPS1) program. - DMABUF ANABuf; //DMA buffer used to receive - //ADC data and hold DAC data. - uint32_t *pDacWBuf; //Pointer to logical adrs of - //DMA buffer used to hold DAC - //data. - uint16_t Dacpol; //Image of DAC polarity - //register. - uint8_t TrimSetpoint[12]; //Images of TrimDAC setpoints. - //registers. - uint16_t ChargeEnabled; //Image of MISC2 Battery - //Charge Enabled (0 or - //WRMISC2_CHARGE_ENABLE). - uint16_t WDInterval; //Image of MISC2 watchdog - //interval control bits. - uint32_t I2CAdrs; //I2C device address for - //onboard EEPROM (board rev - //dependent). - // short I2Cards; - lsampl_t ao_readback[S626_DAC_CHANNELS]; -} s626_private; + uint8_t ai_cmd_running; /* ai_cmd is running */ + uint8_t ai_continous; /* continous aquisition */ + int ai_sample_count; /* number of samples to aquire */ + unsigned int ai_sample_timer; + /* time between samples in units of the timer */ + int ai_convert_count; /* conversion counter */ + unsigned int ai_convert_timer; + /* time between conversion in units of the timer */ + uint16_t CounterIntEnabs; + /* Counter interrupt enable mask for MISC2 register. */ + uint8_t AdcItems; /* Number of items in ADC poll list. */ + struct bufferDMA RPSBuf; /* DMA buffer used to hold ADC (RPS1) program. */ + struct bufferDMA ANABuf; + /* DMA buffer used to receive ADC data and hold DAC data. */ + uint32_t *pDacWBuf; + /* Pointer to logical adrs of DMA buffer used to hold DAC data. */ + uint16_t Dacpol; /* Image of DAC polarity register. */ + uint8_t TrimSetpoint[12]; /* Images of TrimDAC setpoints */ + uint16_t ChargeEnabled; /* Image of MISC2 Battery */ + /* Charge Enabled (0 or WRMISC2_CHARGE_ENABLE). */ + uint16_t WDInterval; /* Image of MISC2 watchdog interval control bits. */ + uint32_t I2CAdrs; + /* I2C device address for onboard EEPROM (board rev dependent). */ + /* short I2Cards; */ + unsigned int ao_readback[S626_DAC_CHANNELS]; +}; -typedef struct { +struct dio_private { uint16_t RDDIn; uint16_t WRDOut; uint16_t RDEdgSel; @@ -178,324 +170,322 @@ typedef struct { uint16_t RDCapFlg; uint16_t RDIntSel; uint16_t WRIntSel; -} dio_private; +}; -static dio_private dio_private_A = { +static struct dio_private dio_private_A = { RDDIn:LP_RDDINA, - WRDOut:LP_WRDOUTA, - RDEdgSel:LP_RDEDGSELA, - WREdgSel:LP_WREDGSELA, - RDCapSel:LP_RDCAPSELA, - WRCapSel:LP_WRCAPSELA, - RDCapFlg:LP_RDCAPFLGA, - RDIntSel:LP_RDINTSELA, - WRIntSel:LP_WRINTSELA, + WRDOut : LP_WRDOUTA, + RDEdgSel : LP_RDEDGSELA, + WREdgSel : LP_WREDGSELA, + RDCapSel : LP_RDCAPSELA, + WRCapSel : LP_WRCAPSELA, + RDCapFlg : LP_RDCAPFLGA, + RDIntSel : LP_RDINTSELA, + WRIntSel : LP_WRINTSELA, }; -static dio_private dio_private_B = { +static struct dio_private dio_private_B = { RDDIn:LP_RDDINB, - WRDOut:LP_WRDOUTB, - RDEdgSel:LP_RDEDGSELB, - WREdgSel:LP_WREDGSELB, - RDCapSel:LP_RDCAPSELB, - WRCapSel:LP_WRCAPSELB, - RDCapFlg:LP_RDCAPFLGB, - RDIntSel:LP_RDINTSELB, - WRIntSel:LP_WRINTSELB, + WRDOut : LP_WRDOUTB, + RDEdgSel : LP_RDEDGSELB, + WREdgSel : LP_WREDGSELB, + RDCapSel : LP_RDCAPSELB, + WRCapSel : LP_WRCAPSELB, + RDCapFlg : LP_RDCAPFLGB, + RDIntSel : LP_RDINTSELB, + WRIntSel : LP_WRINTSELB, }; -static dio_private dio_private_C = { +static struct dio_private dio_private_C = { RDDIn:LP_RDDINC, - WRDOut:LP_WRDOUTC, - RDEdgSel:LP_RDEDGSELC, - WREdgSel:LP_WREDGSELC, - RDCapSel:LP_RDCAPSELC, - WRCapSel:LP_WRCAPSELC, - RDCapFlg:LP_RDCAPFLGC, - RDIntSel:LP_RDINTSELC, - WRIntSel:LP_WRINTSELC, + WRDOut : LP_WRDOUTC, + RDEdgSel : LP_RDEDGSELC, + WREdgSel : LP_WREDGSELC, + RDCapSel : LP_RDCAPSELC, + WRCapSel : LP_WRCAPSELC, + RDCapFlg : LP_RDCAPFLGC, + RDIntSel : LP_RDINTSELC, + WRIntSel : LP_WRINTSELC, }; /* to group dio devices (48 bits mask and data are not allowed ???) -static dio_private *dio_private_word[]={ +static struct dio_private *dio_private_word[]={ &dio_private_A, &dio_private_B, &dio_private_C, }; */ -#define devpriv ((s626_private *)dev->private) -#define diopriv ((dio_private *)s->private) +#define devpriv ((struct s626_private *)dev->private) +#define diopriv ((struct dio_private *)s->private) COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table); -//ioctl routines -static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); */ -static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s); -static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s, - comedi_cmd * cmd); -static int s626_ai_cancel(comedi_device * dev, comedi_subdevice * s); -static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int s626_dio_set_irq(comedi_device * dev, unsigned int chan); -static int s626_dio_reset_irq(comedi_device * dev, unsigned int gruop, +/* ioctl routines */ +static int s626_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */ +static int s626_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s); +static int s626_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd); +static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s); +static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int s626_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int s626_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan); +static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int gruop, unsigned int mask); -static int s626_dio_clear_irq(comedi_device * dev); -static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); -static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data); +static int s626_dio_clear_irq(struct comedi_device *dev); +static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); static int s626_ns_to_timer(int *nanosec, int round_mode); -static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd); -static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s, +static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd); +static int s626_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum); static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG); -static lsampl_t s626_ai_reg_to_uint(int data); -/* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data); */ +static unsigned int s626_ai_reg_to_uint(int data); +/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data); */ -//end ioctl routines +/* end ioctl routines */ -//internal routines -static void s626_dio_init(comedi_device * dev); -static void ResetADC(comedi_device * dev, uint8_t * ppl); -static void LoadTrimDACs(comedi_device * dev); -static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan, +/* internal routines */ +static void s626_dio_init(struct comedi_device *dev); +static void ResetADC(struct comedi_device *dev, uint8_t *ppl); +static void LoadTrimDACs(struct comedi_device *dev); +static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan, uint8_t DacData); -static uint8_t I2Cread(comedi_device * dev, uint8_t addr); -static uint32_t I2Chandshake(comedi_device * dev, uint32_t val); -static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata); -static void SendDAC(comedi_device * dev, uint32_t val); -static void WriteMISC2(comedi_device * dev, uint16_t NewImage); -static void DEBItransfer(comedi_device * dev); -static uint16_t DEBIread(comedi_device * dev, uint16_t addr); -static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata); -static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask, +static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr); +static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val); +static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata); +static void SendDAC(struct comedi_device *dev, uint32_t val); +static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage); +static void DEBItransfer(struct comedi_device *dev); +static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr); +static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata); +static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask, uint16_t wdata); -static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize); +static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, size_t bsize); -// COUNTER OBJECT ------------------------------------------------ -typedef struct enc_private_struct { - // Pointers to functions that differ for A and B counters: - uint16_t(*GetEnable) (comedi_device * dev, struct enc_private_struct *); //Return clock enable. - uint16_t(*GetIntSrc) (comedi_device * dev, struct enc_private_struct *); //Return interrupt source. - uint16_t(*GetLoadTrig) (comedi_device * dev, struct enc_private_struct *); //Return preload trigger source. - uint16_t(*GetMode) (comedi_device * dev, struct enc_private_struct *); //Return standardized operating mode. - void (*PulseIndex) (comedi_device * dev, struct enc_private_struct *); //Generate soft index strobe. - void (*SetEnable) (comedi_device * dev, struct enc_private_struct *, uint16_t enab); //Program clock enable. - void (*SetIntSrc) (comedi_device * dev, struct enc_private_struct *, uint16_t IntSource); //Program interrupt source. - void (*SetLoadTrig) (comedi_device * dev, struct enc_private_struct *, uint16_t Trig); //Program preload trigger source. - void (*SetMode) (comedi_device * dev, struct enc_private_struct *, uint16_t Setup, uint16_t DisableIntSrc); //Program standardized operating mode. - void (*ResetCapFlags) (comedi_device * dev, struct enc_private_struct *); //Reset event capture flags. +/* COUNTER OBJECT ------------------------------------------------ */ +struct enc_private { + /* Pointers to functions that differ for A and B counters: */ + uint16_t(*GetEnable) (struct comedi_device *dev, struct enc_private *); /* Return clock enable. */ + uint16_t(*GetIntSrc) (struct comedi_device *dev, struct enc_private *); /* Return interrupt source. */ + uint16_t(*GetLoadTrig) (struct comedi_device *dev, struct enc_private *); /* Return preload trigger source. */ + uint16_t(*GetMode) (struct comedi_device *dev, struct enc_private *); /* Return standardized operating mode. */ + void (*PulseIndex) (struct comedi_device *dev, struct enc_private *); /* Generate soft index strobe. */ + void (*SetEnable) (struct comedi_device *dev, struct enc_private *, uint16_t enab); /* Program clock enable. */ + void (*SetIntSrc) (struct comedi_device *dev, struct enc_private *, uint16_t IntSource); /* Program interrupt source. */ + void (*SetLoadTrig) (struct comedi_device *dev, struct enc_private *, uint16_t Trig); /* Program preload trigger source. */ + void (*SetMode) (struct comedi_device *dev, struct enc_private *, uint16_t Setup, uint16_t DisableIntSrc); /* Program standardized operating mode. */ + void (*ResetCapFlags) (struct comedi_device *dev, struct enc_private *); /* Reset event capture flags. */ - uint16_t MyCRA; // Address of CRA register. - uint16_t MyCRB; // Address of CRB register. - uint16_t MyLatchLsw; // Address of Latch least-significant-word - // register. - uint16_t MyEventBits[4]; // Bit translations for IntSrc -->RDMISC2. -} enc_private; //counter object + uint16_t MyCRA; /* Address of CRA register. */ + uint16_t MyCRB; /* Address of CRB register. */ + uint16_t MyLatchLsw; /* Address of Latch least-significant-word */ + /* register. */ + uint16_t MyEventBits[4]; /* Bit translations for IntSrc -->RDMISC2. */ +}; -#define encpriv ((enc_private *)(dev->subdevices+5)->private) +#define encpriv ((struct enc_private *)(dev->subdevices+5)->private) -//counters routines -static void s626_timer_load(comedi_device * dev, enc_private * k, int tick); -static uint32_t ReadLatch(comedi_device * dev, enc_private * k); -static void ResetCapFlags_A(comedi_device * dev, enc_private * k); -static void ResetCapFlags_B(comedi_device * dev, enc_private * k); -static uint16_t GetMode_A(comedi_device * dev, enc_private * k); -static uint16_t GetMode_B(comedi_device * dev, enc_private * k); -static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup, +/* counters routines */ +static void s626_timer_load(struct comedi_device *dev, struct enc_private *k, int tick); +static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k); +static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k); +static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k); +static uint16_t GetMode_A(struct comedi_device *dev, struct enc_private *k); +static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k); +static void SetMode_A(struct comedi_device *dev, struct enc_private *k, uint16_t Setup, uint16_t DisableIntSrc); -static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup, +static void SetMode_B(struct comedi_device *dev, struct enc_private *k, uint16_t Setup, uint16_t DisableIntSrc); -static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab); -static void SetEnable_B(comedi_device * dev, enc_private * k, uint16_t enab); -static uint16_t GetEnable_A(comedi_device * dev, enc_private * k); -static uint16_t GetEnable_B(comedi_device * dev, enc_private * k); -static void SetLatchSource(comedi_device * dev, enc_private * k, +static void SetEnable_A(struct comedi_device *dev, struct enc_private *k, uint16_t enab); +static void SetEnable_B(struct comedi_device *dev, struct enc_private *k, uint16_t enab); +static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k); +static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k); +static void SetLatchSource(struct comedi_device *dev, struct enc_private *k, uint16_t value); -/* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ); */ -static void SetLoadTrig_A(comedi_device * dev, enc_private * k, uint16_t Trig); -static void SetLoadTrig_B(comedi_device * dev, enc_private * k, uint16_t Trig); -static uint16_t GetLoadTrig_A(comedi_device * dev, enc_private * k); -static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k); -static void SetIntSrc_B(comedi_device * dev, enc_private * k, +/* static uint16_t GetLatchSource(struct comedi_device *dev, struct enc_private *k ); */ +static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k, uint16_t Trig); +static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k, uint16_t Trig); +static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k); +static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k); +static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k, uint16_t IntSource); -static void SetIntSrc_A(comedi_device * dev, enc_private * k, +static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k, uint16_t IntSource); -static uint16_t GetIntSrc_A(comedi_device * dev, enc_private * k); -static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k); -/* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) ; */ -/* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) ; */ -/* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ); */ -/* static uint16_t GetClkPol(comedi_device *dev, enc_private *k ) ; */ -/* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value ); */ -/* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k ); */ -/* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value ); */ -/* static uint16_t GetIndexSrc( comedi_device *dev,enc_private *k ); */ -static void PulseIndex_A(comedi_device * dev, enc_private * k); -static void PulseIndex_B(comedi_device * dev, enc_private * k); -static void Preload(comedi_device * dev, enc_private * k, uint32_t value); -static void CountersInit(comedi_device * dev); -//end internal routines +static uint16_t GetIntSrc_A(struct comedi_device *dev, struct enc_private *k); +static uint16_t GetIntSrc_B(struct comedi_device *dev, struct enc_private *k); +/* static void SetClkMult(struct comedi_device *dev, struct enc_private *k, uint16_t value ) ; */ +/* static uint16_t GetClkMult(struct comedi_device *dev, struct enc_private *k ) ; */ +/* static void SetIndexPol(struct comedi_device *dev, struct enc_private *k, uint16_t value ); */ +/* static uint16_t GetClkPol(struct comedi_device *dev, struct enc_private *k ) ; */ +/* static void SetIndexSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value ); */ +/* static uint16_t GetClkSrc( struct comedi_device *dev,struct enc_private *k ); */ +/* static void SetIndexSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value ); */ +/* static uint16_t GetIndexSrc( struct comedi_device *dev,struct enc_private *k ); */ +static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k); +static void PulseIndex_B(struct comedi_device *dev, struct enc_private *k); +static void Preload(struct comedi_device *dev, struct enc_private *k, uint32_t value); +static void CountersInit(struct comedi_device *dev); +/* end internal routines */ -///////////////////////////////////////////////////////////////////////// -// Counter objects constructor. +/* Counter objects constructor. */ -// Counter overflow/index event flag masks for RDMISC2. -#define INDXMASK(C) ( 1 << ( ( (C) > 2 ) ? ( (C) * 2 - 1 ) : ( (C) * 2 + 4 ) ) ) -#define OVERMASK(C) ( 1 << ( ( (C) > 2 ) ? ( (C) * 2 + 5 ) : ( (C) * 2 + 10 ) ) ) +/* Counter overflow/index event flag masks for RDMISC2. */ +#define INDXMASK(C) (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 + 4))) +#define OVERMASK(C) (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10))) #define EVBITS(C) { 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) } -// Translation table to map IntSrc into equivalent RDMISC2 event flag -// bits. -//static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; +/* Translation table to map IntSrc into equivalent RDMISC2 event flag bits. */ +/* static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; */ -/* enc_private; */ -static enc_private enc_private_data[] = { +/* struct enc_private; */ +static struct enc_private enc_private_data[] = { { GetEnable:GetEnable_A, - GetIntSrc:GetIntSrc_A, - GetLoadTrig:GetLoadTrig_A, - GetMode: GetMode_A, - PulseIndex:PulseIndex_A, - SetEnable:SetEnable_A, - SetIntSrc:SetIntSrc_A, - SetLoadTrig:SetLoadTrig_A, - SetMode: SetMode_A, - ResetCapFlags:ResetCapFlags_A, - MyCRA: LP_CR0A, - MyCRB: LP_CR0B, - MyLatchLsw:LP_CNTR0ALSW, - MyEventBits:EVBITS(0), + GetIntSrc : GetIntSrc_A, + GetLoadTrig : GetLoadTrig_A, + GetMode : GetMode_A, + PulseIndex : PulseIndex_A, + SetEnable : SetEnable_A, + SetIntSrc : SetIntSrc_A, + SetLoadTrig : SetLoadTrig_A, + SetMode : SetMode_A, + ResetCapFlags : ResetCapFlags_A, + MyCRA : LP_CR0A, + MyCRB : LP_CR0B, + MyLatchLsw : LP_CNTR0ALSW, + MyEventBits : EVBITS(0), }, { GetEnable:GetEnable_A, - GetIntSrc:GetIntSrc_A, - GetLoadTrig:GetLoadTrig_A, - GetMode: GetMode_A, - PulseIndex:PulseIndex_A, - SetEnable:SetEnable_A, - SetIntSrc:SetIntSrc_A, - SetLoadTrig:SetLoadTrig_A, - SetMode: SetMode_A, - ResetCapFlags:ResetCapFlags_A, - MyCRA: LP_CR1A, - MyCRB: LP_CR1B, - MyLatchLsw:LP_CNTR1ALSW, - MyEventBits:EVBITS(1), + GetIntSrc : GetIntSrc_A, + GetLoadTrig : GetLoadTrig_A, + GetMode : GetMode_A, + PulseIndex : PulseIndex_A, + SetEnable : SetEnable_A, + SetIntSrc : SetIntSrc_A, + SetLoadTrig : SetLoadTrig_A, + SetMode : SetMode_A, + ResetCapFlags : ResetCapFlags_A, + MyCRA : LP_CR1A, + MyCRB : LP_CR1B, + MyLatchLsw : LP_CNTR1ALSW, + MyEventBits : EVBITS(1), }, { GetEnable:GetEnable_A, - GetIntSrc:GetIntSrc_A, - GetLoadTrig:GetLoadTrig_A, - GetMode: GetMode_A, - PulseIndex:PulseIndex_A, - SetEnable:SetEnable_A, - SetIntSrc:SetIntSrc_A, - SetLoadTrig:SetLoadTrig_A, - SetMode: SetMode_A, - ResetCapFlags:ResetCapFlags_A, - MyCRA: LP_CR2A, - MyCRB: LP_CR2B, - MyLatchLsw:LP_CNTR2ALSW, - MyEventBits:EVBITS(2), + GetIntSrc : GetIntSrc_A, + GetLoadTrig : GetLoadTrig_A, + GetMode : GetMode_A, + PulseIndex : PulseIndex_A, + SetEnable : SetEnable_A, + SetIntSrc : SetIntSrc_A, + SetLoadTrig : SetLoadTrig_A, + SetMode : SetMode_A, + ResetCapFlags : ResetCapFlags_A, + MyCRA : LP_CR2A, + MyCRB : LP_CR2B, + MyLatchLsw : LP_CNTR2ALSW, + MyEventBits : EVBITS(2), }, { GetEnable:GetEnable_B, - GetIntSrc:GetIntSrc_B, - GetLoadTrig:GetLoadTrig_B, - GetMode: GetMode_B, - PulseIndex:PulseIndex_B, - SetEnable:SetEnable_B, - SetIntSrc:SetIntSrc_B, - SetLoadTrig:SetLoadTrig_B, - SetMode: SetMode_B, - ResetCapFlags:ResetCapFlags_B, - MyCRA: LP_CR0A, - MyCRB: LP_CR0B, - MyLatchLsw:LP_CNTR0BLSW, - MyEventBits:EVBITS(3), + GetIntSrc : GetIntSrc_B, + GetLoadTrig : GetLoadTrig_B, + GetMode : GetMode_B, + PulseIndex : PulseIndex_B, + SetEnable : SetEnable_B, + SetIntSrc : SetIntSrc_B, + SetLoadTrig : SetLoadTrig_B, + SetMode : SetMode_B, + ResetCapFlags : ResetCapFlags_B, + MyCRA : LP_CR0A, + MyCRB : LP_CR0B, + MyLatchLsw : LP_CNTR0BLSW, + MyEventBits : EVBITS(3), }, { GetEnable:GetEnable_B, - GetIntSrc:GetIntSrc_B, - GetLoadTrig:GetLoadTrig_B, - GetMode: GetMode_B, - PulseIndex:PulseIndex_B, - SetEnable:SetEnable_B, - SetIntSrc:SetIntSrc_B, - SetLoadTrig:SetLoadTrig_B, - SetMode: SetMode_B, - ResetCapFlags:ResetCapFlags_B, - MyCRA: LP_CR1A, - MyCRB: LP_CR1B, - MyLatchLsw:LP_CNTR1BLSW, - MyEventBits:EVBITS(4), + GetIntSrc : GetIntSrc_B, + GetLoadTrig : GetLoadTrig_B, + GetMode : GetMode_B, + PulseIndex : PulseIndex_B, + SetEnable : SetEnable_B, + SetIntSrc : SetIntSrc_B, + SetLoadTrig : SetLoadTrig_B, + SetMode : SetMode_B, + ResetCapFlags : ResetCapFlags_B, + MyCRA : LP_CR1A, + MyCRB : LP_CR1B, + MyLatchLsw : LP_CNTR1BLSW, + MyEventBits : EVBITS(4), }, { GetEnable:GetEnable_B, - GetIntSrc:GetIntSrc_B, - GetLoadTrig:GetLoadTrig_B, - GetMode: GetMode_B, - PulseIndex:PulseIndex_B, - SetEnable:SetEnable_B, - SetIntSrc:SetIntSrc_B, - SetLoadTrig:SetLoadTrig_B, - SetMode: SetMode_B, - ResetCapFlags:ResetCapFlags_B, - MyCRA: LP_CR2A, - MyCRB: LP_CR2B, - MyLatchLsw:LP_CNTR2BLSW, - MyEventBits:EVBITS(5), + GetIntSrc : GetIntSrc_B, + GetLoadTrig : GetLoadTrig_B, + GetMode : GetMode_B, + PulseIndex : PulseIndex_B, + SetEnable : SetEnable_B, + SetIntSrc : SetIntSrc_B, + SetLoadTrig : SetLoadTrig_B, + SetMode : SetMode_B, + ResetCapFlags : ResetCapFlags_B, + MyCRA : LP_CR2A, + MyCRB : LP_CR2B, + MyLatchLsw : LP_CNTR2BLSW, + MyEventBits : EVBITS(5), }, }; -// enab/disable a function or test status bit(s) that are accessed -// through Main Control Registers 1 or 2. -#define MC_ENABLE( REGADRS, CTRLWORD ) writel( ( (uint32_t)( CTRLWORD ) << 16 ) | (uint32_t)( CTRLWORD ),devpriv->base_addr+( REGADRS ) ) +/* enab/disable a function or test status bit(s) that are accessed */ +/* through Main Control Registers 1 or 2. */ +#define MC_ENABLE(REGADRS, CTRLWORD) writel(((uint32_t)(CTRLWORD) << 16) | (uint32_t)(CTRLWORD), devpriv->base_addr+(REGADRS)) -#define MC_DISABLE( REGADRS, CTRLWORD ) writel( (uint32_t)( CTRLWORD ) << 16 , devpriv->base_addr+( REGADRS ) ) +#define MC_DISABLE(REGADRS, CTRLWORD) writel((uint32_t)(CTRLWORD) << 16 , devpriv->base_addr+(REGADRS)) -#define MC_TEST( REGADRS, CTRLWORD ) ( ( readl(devpriv->base_addr+( REGADRS )) & CTRLWORD ) != 0 ) +#define MC_TEST(REGADRS, CTRLWORD) ((readl(devpriv->base_addr+(REGADRS)) & CTRLWORD) != 0) /* #define WR7146(REGARDS,CTRLWORD) writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */ -#define WR7146(REGARDS,CTRLWORD) writel(CTRLWORD,devpriv->base_addr+(REGARDS)) +#define WR7146(REGARDS, CTRLWORD) writel(CTRLWORD, devpriv->base_addr+(REGARDS)) /* #define RR7146(REGARDS) readl((uint32_t)(devpriv->base_addr+(REGARDS))) */ #define RR7146(REGARDS) readl(devpriv->base_addr+(REGARDS)) -#define BUGFIX_STREG(REGADRS) ( REGADRS - 4 ) +#define BUGFIX_STREG(REGADRS) (REGADRS - 4) -// Write a time slot control record to TSL2. -#define VECTPORT( VECTNUM ) (P_TSL2 + ( (VECTNUM) << 2 )) -#define SETVECT( VECTNUM, VECTVAL ) WR7146(VECTPORT( VECTNUM ), (VECTVAL)) +/* Write a time slot control record to TSL2. */ +#define VECTPORT(VECTNUM) (P_TSL2 + ((VECTNUM) << 2)) +#define SETVECT(VECTNUM, VECTVAL) WR7146(VECTPORT(VECTNUM), (VECTVAL)) -// Code macros used for constructing I2C command bytes. -#define I2C_B2(ATTR,VAL) ( ( (ATTR) << 6 ) | ( (VAL) << 24 ) ) -#define I2C_B1(ATTR,VAL) ( ( (ATTR) << 4 ) | ( (VAL) << 16 ) ) -#define I2C_B0(ATTR,VAL) ( ( (ATTR) << 2 ) | ( (VAL) << 8 ) ) +/* Code macros used for constructing I2C command bytes. */ +#define I2C_B2(ATTR, VAL) (((ATTR) << 6) | ((VAL) << 24)) +#define I2C_B1(ATTR, VAL) (((ATTR) << 4) | ((VAL) << 16)) +#define I2C_B0(ATTR, VAL) (((ATTR) << 2) | ((VAL) << 8)) -static const comedi_lrange s626_range_table = { 2, { +static const struct comedi_lrange s626_range_table = { 2, { RANGE(-5, 5), RANGE(-10, 10), } }; -static int s626_attach(comedi_device * dev, comedi_devconfig * it) +static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it) { /* uint8_t PollList; */ /* uint16_t AdcData; */ @@ -507,10 +497,10 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it) int ret; resource_size_t resourceStart; dma_addr_t appdma; - comedi_subdevice *s; + struct comedi_subdevice *s; struct pci_dev *pdev; - if (alloc_private(dev, sizeof(s626_private)) < 0) + if (alloc_private(dev, sizeof(struct s626_private)) < 0) return -ENOMEM; for (pdev = pci_get_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, @@ -535,7 +525,8 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it) return -ENODEV; } - if ((result = comedi_pci_enable(pdev, "s626")) < 0) { + result = comedi_pci_enable(pdev, "s626"); + if (result < 0) { printk("s626_attach: comedi_pci_enable fails\n"); return -ENODEV; } @@ -550,21 +541,22 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it) } if (devpriv->base_addr) { - //disable master interrupt + /* disable master interrupt */ writel(0, devpriv->base_addr + P_IER); - //soft reset + /* soft reset */ writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1); - //DMA FIXME DMA// + /* DMA FIXME DMA// */ DEBUG("s626_attach: DMA ALLOCATION\n"); - //adc buffer allocation + /* adc buffer allocation */ devpriv->allocatedBuf = 0; - if ((devpriv->ANABuf.LogicalBase = - pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, - &appdma)) == NULL) { + devpriv->ANABuf.LogicalBase = + pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma); + + if (devpriv->ANABuf.LogicalBase == NULL) { printk("s626_attach: DMA Memory mapping error\n"); return -ENOMEM; } @@ -575,9 +567,10 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it) devpriv->allocatedBuf++; - if ((devpriv->RPSBuf.LogicalBase = - pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, - &appdma)) == NULL) { + devpriv->RPSBuf.LogicalBase = + pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, &appdma); + + if (devpriv->RPSBuf.LogicalBase == NULL) { printk("s626_attach: DMA Memory mapping error\n"); return -ENOMEM; } @@ -599,12 +592,14 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it) dev->iobase = (unsigned long)devpriv->base_addr; dev->irq = devpriv->pdev->irq; - //set up interrupt handler + /* set up interrupt handler */ if (dev->irq == 0) { printk(" unknown irq (bad)\n"); } else { - if ((ret = comedi_request_irq(dev->irq, s626_irq_handler, - IRQF_SHARED, "s626", dev)) < 0) { + ret = comedi_request_irq(dev->irq, s626_irq_handler, + IRQF_SHARED, "s626", dev); + + if (ret < 0) { printk(" irq not available\n"); dev->irq = 0; } @@ -689,119 +684,121 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it) s->maxdata = 0xffffff; s->range_table = &range_unknown; - //stop ai_command + /* stop ai_command */ devpriv->ai_cmd_running = 0; if (devpriv->base_addr && (devpriv->allocatedBuf == 2)) { dma_addr_t pPhysBuf; uint16_t chan; - // enab DEBI and audio pins, enable I2C interface. + /* enab DEBI and audio pins, enable I2C interface. */ MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C); - // Configure DEBI operating mode. - WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 // Local bus is 16 - // bits wide. - | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) // Declare DEBI - // transfer timeout - // interval. - | DEBI_SWAP // Set up byte lane - // steering. - | DEBI_CFG_INTEL); // Intel-compatible - // local bus (DEBI - // never times out). + /* Configure DEBI operating mode. */ + WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 /* Local bus is 16 */ + /* bits wide. */ + | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) /* Declare DEBI */ + /* transfer timeout */ + /* interval. */ + | DEBI_SWAP /* Set up byte lane */ + /* steering. */ + | DEBI_CFG_INTEL); /* Intel-compatible */ + /* local bus (DEBI */ + /* never times out). */ DEBUG("s626_attach: %d debi init -- %d\n", DEBI_CFG_SLAVE16 | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) | DEBI_SWAP | DEBI_CFG_INTEL, DEBI_CFG_INTEL | DEBI_CFG_TOQ | DEBI_CFG_INCQ | DEBI_CFG_16Q); - //DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ - //| DEBI_CFG_INCQ| DEBI_CFG_16Q); //end + /* DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ */ + /* | DEBI_CFG_INCQ| DEBI_CFG_16Q); //end */ - // Paging is disabled. - WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE); // Disable MMU paging. + /* Paging is disabled. */ + WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE); /* Disable MMU paging. */ - // Init GPIO so that ADC Start* is negated. + /* Init GPIO so that ADC Start* is negated. */ WR7146(P_GPIO, GPIO_BASE | GPIO1_HI); - //IsBoardRevA is a boolean that indicates whether the board is - //RevA. + /* IsBoardRevA is a boolean that indicates whether the board is RevA. + * + * VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC + * EEPROM ADDRESS SELECTION. Initialize the I2C interface, which + * is used to access the onboard serial EEPROM. The EEPROM's I2C + * DeviceAddress is hardwired to a value that is dependent on the + * 626 board revision. On all board revisions, the EEPROM stores + * TrimDAC calibration constants for analog I/O. On RevB and + * higher boards, the DeviceAddress is hardwired to 0 to enable + * the EEPROM to also store the PCI SubVendorID and SubDeviceID; + * this is the address at which the SAA7146 expects a + * configuration EEPROM to reside. On RevA boards, the EEPROM + * device address, which is hardwired to 4, prevents the SAA7146 + * from retrieving PCI sub-IDs, so the SAA7146 uses its built-in + * default values, instead. + */ - // VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC - // EEPROM ADDRESS SELECTION. Initialize the I2C interface, which - // is used to access the onboard serial EEPROM. The EEPROM's I2C - // DeviceAddress is hardwired to a value that is dependent on the - // 626 board revision. On all board revisions, the EEPROM stores - // TrimDAC calibration constants for analog I/O. On RevB and - // higher boards, the DeviceAddress is hardwired to 0 to enable - // the EEPROM to also store the PCI SubVendorID and SubDeviceID; - // this is the address at which the SAA7146 expects a - // configuration EEPROM to reside. On RevA boards, the EEPROM - // device address, which is hardwired to 4, prevents the SAA7146 - // from retrieving PCI sub-IDs, so the SAA7146 uses its built-in - // default values, instead. + /* devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM */ + /* DeviceType (0xA0) */ + /* and DeviceAddress<<1. */ - // devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM - // DeviceType (0xA0) - // and DeviceAddress<<1. + devpriv->I2CAdrs = 0xA0; /* I2C device address for onboard */ + /* eeprom(revb) */ - devpriv->I2CAdrs = 0xA0; // I2C device address for onboard - // eeprom(revb) + /* Issue an I2C ABORT command to halt any I2C operation in */ + /* progress and reset BUSY flag. */ + WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT); + /* Write I2C control: abort any I2C activity. */ + MC_ENABLE(P_MC2, MC2_UPLD_IIC); + /* Invoke command upload */ + while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0) + ; + /* and wait for upload to complete. */ - // Issue an I2C ABORT command to halt any I2C operation in - //progress and reset BUSY flag. - WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT); // Write I2C control: - // abort any I2C - // activity. - MC_ENABLE(P_MC2, MC2_UPLD_IIC); // Invoke command - // upload - while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0) ; // and wait for - // upload to - // complete. - - // Per SAA7146 data sheet, write to STATUS reg twice to reset all - // I2C error flags. + /* Per SAA7146 data sheet, write to STATUS reg twice to + * reset all I2C error flags. */ for (i = 0; i < 2; i++) { - WR7146(P_I2CSTAT, I2C_CLKSEL); // Write I2C control: reset - // error flags. - MC_ENABLE(P_MC2, MC2_UPLD_IIC); // Invoke command upload - while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ; // and wait for - // upload to - // complete. + WR7146(P_I2CSTAT, I2C_CLKSEL); + /* Write I2C control: reset error flags. */ + MC_ENABLE(P_MC2, MC2_UPLD_IIC); /* Invoke command upload */ + while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) + ; + /* and wait for upload to complete. */ } - // Init audio interface functional attributes: set DAC/ADC serial - // clock rates, invert DAC serial clock so that DAC data setup - // times are satisfied, enable DAC serial clock out. + /* Init audio interface functional attributes: set DAC/ADC + * serial clock rates, invert DAC serial clock so that + * DAC data setup times are satisfied, enable DAC serial + * clock out. + */ + WR7146(P_ACON2, ACON2_INIT); - // Set up TSL1 slot list, which is used to control the - // accumulation of ADC data: RSD1 = shift data in on SD1. SIB_A1 - // = store data uint8_t at next available location in FB BUFFER1 - // register. - WR7146(P_TSL1, RSD1 | SIB_A1); // Fetch ADC high data - // uint8_t. - WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS); // Fetch ADC low data - // uint8_t; end of - // TSL1. + /* Set up TSL1 slot list, which is used to control the + * accumulation of ADC data: RSD1 = shift data in on SD1. + * SIB_A1 = store data uint8_t at next available location in + * FB BUFFER1 register. */ + WR7146(P_TSL1, RSD1 | SIB_A1); + /* Fetch ADC high data uint8_t. */ + WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS); + /* Fetch ADC low data uint8_t; end of TSL1. */ - // enab TSL1 slot list so that it executes all the time. + /* enab TSL1 slot list so that it executes all the time. */ WR7146(P_ACON1, ACON1_ADCSTART); - // Initialize RPS registers used for ADC. + /* Initialize RPS registers used for ADC. */ - //Physical start of RPS program. + /* Physical start of RPS program. */ WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase); - WR7146(P_RPSPAGE1, 0); // RPS program performs no - // explicit mem writes. - WR7146(P_RPS1_TOUT, 0); // Disable RPS timeouts. + WR7146(P_RPSPAGE1, 0); + /* RPS program performs no explicit mem writes. */ + WR7146(P_RPS1_TOUT, 0); /* Disable RPS timeouts. */ - // SAA7146 BUG WORKAROUND. Initialize SAA7146 ADC interface to a - // known state by invoking ADCs until FB BUFFER 1 register shows - // that it is correctly receiving ADC data. This is necessary - // because the SAA7146 ADC interface does not start up in a - // defined state after a PCI reset. + /* SAA7146 BUG WORKAROUND. Initialize SAA7146 ADC interface + * to a known state by invoking ADCs until FB BUFFER 1 + * register shows that it is correctly receiving ADC data. + * This is necessary because the SAA7146 ADC interface does + * not start up in a defined state after a PCI reset. + */ /* PollList = EOPL; // Create a simple polling */ /* // list for analog input */ @@ -829,115 +826,123 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it) /* break; */ /* } */ - // end initADC + /* end initADC */ - // init the DAC interface + /* init the DAC interface */ - // Init Audio2's output DMAC attributes: burst length = 1 DWORD, - // threshold = 1 DWORD. + /* Init Audio2's output DMAC attributes: burst length = 1 + * DWORD, threshold = 1 DWORD. + */ WR7146(P_PCI_BT_A, 0); - // Init Audio2's output DMA physical addresses. The protection - // address is set to 1 DWORD past the base address so that a - // single DWORD will be transferred each time a DMA transfer is - // enabled. + /* Init Audio2's output DMA physical addresses. The protection + * address is set to 1 DWORD past the base address so that a + * single DWORD will be transferred each time a DMA transfer is + * enabled. */ pPhysBuf = devpriv->ANABuf.PhysicalBase + (DAC_WDMABUF_OS * sizeof(uint32_t)); - WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf); // Buffer base adrs. - WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t))); // Protection address. + WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf); /* Buffer base adrs. */ + WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t))); /* Protection address. */ - // Cache Audio2's output DMA buffer logical address. This is - // where DAC data is buffered for A2 output DMA transfers. + /* Cache Audio2's output DMA buffer logical address. This is + * where DAC data is buffered for A2 output DMA transfers. */ devpriv->pDacWBuf = (uint32_t *) devpriv->ANABuf.LogicalBase + DAC_WDMABUF_OS; - // Audio2's output channels does not use paging. The protection - // violation handling bit is set so that the DMAC will - // automatically halt and its PCI address pointer will be reset - // when the protection address is reached. + /* Audio2's output channels does not use paging. The protection + * violation handling bit is set so that the DMAC will + * automatically halt and its PCI address pointer will be reset + * when the protection address is reached. */ + WR7146(P_PAGEA2_OUT, 8); - // Initialize time slot list 2 (TSL2), which is used to control - // the clock generation for and serialization of data to be sent - // to the DAC devices. Slot 0 is a NOP that is used to trap TSL - // execution; this permits other slots to be safely modified - // without first turning off the TSL sequencer (which is - // apparently impossible to do). Also, SD3 (which is driven by a - // pull-up resistor) is shifted in and stored to the MSB of - // FB_BUFFER2 to be used as evidence that the slot sequence has - // not yet finished executing. - SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS); // Slot 0: Trap TSL - // execution, shift 0xFF - // into FB_BUFFER2. + /* Initialize time slot list 2 (TSL2), which is used to control + * the clock generation for and serialization of data to be sent + * to the DAC devices. Slot 0 is a NOP that is used to trap TSL + * execution; this permits other slots to be safely modified + * without first turning off the TSL sequencer (which is + * apparently impossible to do). Also, SD3 (which is driven by a + * pull-up resistor) is shifted in and stored to the MSB of + * FB_BUFFER2 to be used as evidence that the slot sequence has + * not yet finished executing. + */ - // Initialize slot 1, which is constant. Slot 1 causes a DWORD to - // be transferred from audio channel 2's output FIFO to the FIFO's - // output buffer so that it can be serialized and sent to the DAC - // during subsequent slots. All remaining slots are dynamically - // populated as required by the target DAC device. - SETVECT(1, LF_A2); // Slot 1: Fetch DWORD from Audio2's - // output FIFO. + SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS); + /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2. */ - // Start DAC's audio interface (TSL2) running. + /* Initialize slot 1, which is constant. Slot 1 causes a + * DWORD to be transferred from audio channel 2's output FIFO + * to the FIFO's output buffer so that it can be serialized + * and sent to the DAC during subsequent slots. All remaining + * slots are dynamically populated as required by the target + * DAC device. + */ + SETVECT(1, LF_A2); + /* Slot 1: Fetch DWORD from Audio2's output FIFO. */ + + /* Start DAC's audio interface (TSL2) running. */ WR7146(P_ACON1, ACON1_DACSTART); - //////////////////////////////////////////////////////// + /* end init DAC interface */ - // end init DAC interface - - // Init Trim DACs to calibrated values. Do it twice because the - // SAA7146 audio channel does not always reset properly and - // sometimes causes the first few TrimDAC writes to malfunction. + /* Init Trim DACs to calibrated values. Do it twice because the + * SAA7146 audio channel does not always reset properly and + * sometimes causes the first few TrimDAC writes to malfunction. + */ LoadTrimDACs(dev); - LoadTrimDACs(dev); // Insurance. + LoadTrimDACs(dev); /* Insurance. */ - ////////////////////////////////////////////////////////////////// - // Manually init all gate array hardware in case this is a soft - // reset (we have no way of determining whether this is a warm or - // cold start). This is necessary because the gate array will - // reset only in response to a PCI hard reset; there is no soft - // reset function. + /* Manually init all gate array hardware in case this is a soft + * reset (we have no way of determining whether this is a warm + * or cold start). This is necessary because the gate array will + * reset only in response to a PCI hard reset; there is no soft + * reset function. */ - // Init all DAC outputs to 0V and init all DAC setpoint and - // polarity images. + /* Init all DAC outputs to 0V and init all DAC setpoint and + * polarity images. + */ for (chan = 0; chan < S626_DAC_CHANNELS; chan++) SetDAC(dev, chan, 0); - // Init image of WRMISC2 Battery Charger Enabled control bit. - // This image is used when the state of the charger control bit, - // which has no direct hardware readback mechanism, is queried. + /* Init image of WRMISC2 Battery Charger Enabled control bit. + * This image is used when the state of the charger control bit, + * which has no direct hardware readback mechanism, is queried. + */ devpriv->ChargeEnabled = 0; - // Init image of watchdog timer interval in WRMISC2. This image - // maintains the value of the control bits of MISC2 are - // continuously reset to zero as long as the WD timer is disabled. + /* Init image of watchdog timer interval in WRMISC2. This image + * maintains the value of the control bits of MISC2 are + * continuously reset to zero as long as the WD timer is disabled. + */ devpriv->WDInterval = 0; - // Init Counter Interrupt enab mask for RDMISC2. This mask is - // applied against MISC2 when testing to determine which timer - // events are requesting interrupt service. + /* Init Counter Interrupt enab mask for RDMISC2. This mask is + * applied against MISC2 when testing to determine which timer + * events are requesting interrupt service. + */ devpriv->CounterIntEnabs = 0; - // Init counters. + /* Init counters. */ CountersInit(dev); - // Without modifying the state of the Battery Backup enab, disable - // the watchdog timer, set DIO channels 0-5 to operate in the - // standard DIO (vs. counter overflow) mode, disable the battery - // charger, and reset the watchdog interval selector to zero. + /* Without modifying the state of the Battery Backup enab, disable + * the watchdog timer, set DIO channels 0-5 to operate in the + * standard DIO (vs. counter overflow) mode, disable the battery + * charger, and reset the watchdog interval selector to zero. + */ WriteMISC2(dev, (uint16_t) (DEBIread(dev, LP_RDMISC2) & MISC2_BATT_ENABLE)); - // Initialize the digital I/O subsystem. + /* Initialize the digital I/O subsystem. */ s626_dio_init(dev); - //enable interrupt test - // writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER); + /* enable interrupt test */ + /* writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER); */ } DEBUG("s626_attach: comedi%d s626 attached %04x\n", dev->minor, @@ -946,9 +951,9 @@ static int s626_attach(comedi_device * dev, comedi_devconfig * it) return 1; } -static lsampl_t s626_ai_reg_to_uint(int data) +static unsigned int s626_ai_reg_to_uint(int data) { - lsampl_t tempdata; + unsigned int tempdata; tempdata = (data >> 18); if (tempdata & 0x2000) @@ -959,21 +964,21 @@ static lsampl_t s626_ai_reg_to_uint(int data) return tempdata; } -/* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data){ */ +/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data){ */ /* return 0; */ /* } */ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) { - comedi_device *dev = d; - comedi_subdevice *s; - comedi_cmd *cmd; - enc_private *k; + struct comedi_device *dev = d; + struct comedi_subdevice *s; + struct comedi_cmd *cmd; + struct enc_private *k; unsigned long flags; int32_t *readaddr; uint32_t irqtype, irqstatus; int i = 0; - sampl_t tempdata; + short tempdata; uint8_t group; uint16_t irqbit; @@ -981,47 +986,48 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) if (dev->attached == 0) return IRQ_NONE; - // lock to avoid race with comedi_poll + /* lock to avoid race with comedi_poll */ comedi_spin_lock_irqsave(&dev->spinlock, flags); - //save interrupt enable register state + /* save interrupt enable register state */ irqstatus = readl(devpriv->base_addr + P_IER); - //read interrupt type + /* read interrupt type */ irqtype = readl(devpriv->base_addr + P_ISR); - //disable master interrupt + /* disable master interrupt */ writel(0, devpriv->base_addr + P_IER); - //clear interrupt + /* clear interrupt */ writel(irqtype, devpriv->base_addr + P_ISR); - //do somethings + /* do somethings */ DEBUG("s626_irq_handler: interrupt type %d\n", irqtype); switch (irqtype) { - case IRQ_RPS1: // end_of_scan occurs + case IRQ_RPS1: /* end_of_scan occurs */ DEBUG("s626_irq_handler: RPS1 irq detected\n"); - // manage ai subdevice + /* manage ai subdevice */ s = dev->subdevices; cmd = &(s->async->cmd); - // Init ptr to DMA buffer that holds new ADC data. We skip the - // first uint16_t in the buffer because it contains junk data from - // the final ADC of the previous poll list scan. + /* Init ptr to DMA buffer that holds new ADC data. We skip the + * first uint16_t in the buffer because it contains junk data from + * the final ADC of the previous poll list scan. + */ readaddr = (int32_t *) devpriv->ANABuf.LogicalBase + 1; - // get the data and hand it over to comedi + /* get the data and hand it over to comedi */ for (i = 0; i < (s->async->cmd.chanlist_len); i++) { - // Convert ADC data to 16-bit integer values and copy to application - // buffer. + /* Convert ADC data to 16-bit integer values and copy to application */ + /* buffer. */ tempdata = s626_ai_reg_to_uint((int)*readaddr); readaddr++; - //put data into read buffer - // comedi_buf_put(s->async, tempdata); + /* put data into read buffer */ + /* comedi_buf_put(s->async, tempdata); */ if (cfc_write_to_buffer(s, tempdata) == 0) printk("s626_irq_handler: cfc_write_to_buffer error!\n"); @@ -1029,7 +1035,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) i, tempdata); } - //end of scan occurs + /* end of scan occurs */ s->async->events |= COMEDI_CB_EOS; if (!(devpriv->ai_continous)) @@ -1037,13 +1043,13 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) if (devpriv->ai_sample_count <= 0) { devpriv->ai_cmd_running = 0; - // Stop RPS program. + /* Stop RPS program. */ MC_DISABLE(P_MC1, MC1_ERPS1); - //send end of acquisition + /* send end of acquisition */ s->async->events |= COMEDI_CB_EOA; - //disable master interrupt + /* disable master interrupt */ irqstatus = 0; } @@ -1054,40 +1060,40 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) DEBUG("s626_irq_handler: External trigger is set!!!\n"); } - // tell comedi that data is there + /* tell comedi that data is there */ DEBUG("s626_irq_handler: events %d\n", s->async->events); comedi_event(dev, s); break; - case IRQ_GPIO3: //check dio and conter interrupt + case IRQ_GPIO3: /* check dio and conter interrupt */ DEBUG("s626_irq_handler: GPIO3 irq detected\n"); - // manage ai subdevice + /* manage ai subdevice */ s = dev->subdevices; cmd = &(s->async->cmd); - //s626_dio_clear_irq(dev); + /* s626_dio_clear_irq(dev); */ for (group = 0; group < S626_DIO_BANKS; group++) { irqbit = 0; - //read interrupt type + /* read interrupt type */ irqbit = DEBIread(dev, - ((dio_private *) (dev->subdevices + 2 + + ((struct dio_private *) (dev->subdevices + 2 + group)->private)->RDCapFlg); - //check if interrupt is generated from dio channels + /* check if interrupt is generated from dio channels */ if (irqbit) { s626_dio_reset_irq(dev, group, irqbit); DEBUG("s626_irq_handler: check interrupt on dio group %d %d\n", group, i); if (devpriv->ai_cmd_running) { - //check if interrupt is an ai acquisition start trigger + /* check if interrupt is an ai acquisition start trigger */ if ((irqbit >> (cmd->start_arg - (16 * group))) == 1 && cmd->start_src == TRIG_EXT) { DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->start_arg); - // Start executing the RPS program. + /* Start executing the RPS program. */ MC_ENABLE(P_MC1, MC1_ERPS1); DEBUG("s626_irq_handler: aquisition start triggered!!!\n"); @@ -1110,7 +1116,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) TRIG_EXT) { DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->scan_begin_arg); - // Trigger ADC scan loop start by setting RPS Signal 0. + /* Trigger ADC scan loop start by setting RPS Signal 0. */ MC_ENABLE(P_MC2, MC2_ADC_RPS); DEBUG("s626_irq_handler: scan triggered!!! %d\n", devpriv->ai_sample_count); @@ -1151,7 +1157,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) TRIG_EXT) { DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->convert_arg); - // Trigger ADC scan loop start by setting RPS Signal 0. + /* Trigger ADC scan loop start by setting RPS Signal 0. */ MC_ENABLE(P_MC2, MC2_ADC_RPS); DEBUG("s626_irq_handler: adc convert triggered!!!\n"); @@ -1175,10 +1181,10 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) } } - //read interrupt type + /* read interrupt type */ irqbit = DEBIread(dev, LP_RDMISC2); - //check interrupt on counters + /* check interrupt on counters */ DEBUG("s626_irq_handler: check counters interrupt %d\n", irqbit); @@ -1186,35 +1192,35 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) DEBUG("s626_irq_handler: interrupt on counter 1A overflow\n"); k = &encpriv[0]; - //clear interrupt capture flag + /* clear interrupt capture flag */ k->ResetCapFlags(dev, k); } if (irqbit & IRQ_COINT2A) { DEBUG("s626_irq_handler: interrupt on counter 2A overflow\n"); k = &encpriv[1]; - //clear interrupt capture flag + /* clear interrupt capture flag */ k->ResetCapFlags(dev, k); } if (irqbit & IRQ_COINT3A) { DEBUG("s626_irq_handler: interrupt on counter 3A overflow\n"); k = &encpriv[2]; - //clear interrupt capture flag + /* clear interrupt capture flag */ k->ResetCapFlags(dev, k); } if (irqbit & IRQ_COINT1B) { DEBUG("s626_irq_handler: interrupt on counter 1B overflow\n"); k = &encpriv[3]; - //clear interrupt capture flag + /* clear interrupt capture flag */ k->ResetCapFlags(dev, k); } if (irqbit & IRQ_COINT2B) { DEBUG("s626_irq_handler: interrupt on counter 2B overflow\n"); k = &encpriv[4]; - //clear interrupt capture flag + /* clear interrupt capture flag */ k->ResetCapFlags(dev, k); if (devpriv->ai_convert_count > 0) { @@ -1225,7 +1231,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) if (cmd->convert_src == TRIG_TIMER) { DEBUG("s626_irq_handler: conver timer trigger!!! %d\n", devpriv->ai_convert_count); - // Trigger ADC scan loop start by setting RPS Signal 0. + /* Trigger ADC scan loop start by setting RPS Signal 0. */ MC_ENABLE(P_MC2, MC2_ADC_RPS); } } @@ -1234,13 +1240,13 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) DEBUG("s626_irq_handler: interrupt on counter 3B overflow\n"); k = &encpriv[5]; - //clear interrupt capture flag + /* clear interrupt capture flag */ k->ResetCapFlags(dev, k); if (cmd->scan_begin_src == TRIG_TIMER) { DEBUG("s626_irq_handler: scan timer trigger!!!\n"); - // Trigger ADC scan loop start by setting RPS Signal 0. + /* Trigger ADC scan loop start by setting RPS Signal 0. */ MC_ENABLE(P_MC2, MC2_ADC_RPS); } @@ -1253,7 +1259,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) } } - //enable interrupt + /* enable interrupt */ writel(irqstatus, devpriv->base_addr + P_IER); DEBUG("s626_irq_handler: exit interrupt service routine.\n"); @@ -1262,21 +1268,21 @@ static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) return IRQ_HANDLED; } -static int s626_detach(comedi_device * dev) +static int s626_detach(struct comedi_device *dev) { if (devpriv) { - //stop ai_command + /* stop ai_command */ devpriv->ai_cmd_running = 0; if (devpriv->base_addr) { - //interrupt mask - WR7146(P_IER, 0); // Disable master interrupt. - WR7146(P_ISR, IRQ_GPIO3 | IRQ_RPS1); // Clear board's IRQ status flag. + /* interrupt mask */ + WR7146(P_IER, 0); /* Disable master interrupt. */ + WR7146(P_ISR, IRQ_GPIO3 | IRQ_RPS1); /* Clear board's IRQ status flag. */ - // Disable the watchdog timer and battery charger. + /* Disable the watchdog timer and battery charger. */ WriteMISC2(dev, 0); - // Close all interfaces on 7146 device. + /* Close all interfaces on 7146 device. */ WR7146(P_MC1, MC1_SHUTDOWN); WR7146(P_ACON1, ACON1_BASE); @@ -1284,18 +1290,15 @@ static int s626_detach(comedi_device * dev) CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE); } - if (dev->irq) { + if (dev->irq) comedi_free_irq(dev->irq, dev); - } - if (devpriv->base_addr) { + if (devpriv->base_addr) iounmap(devpriv->base_addr); - } if (devpriv->pdev) { - if (devpriv->got_regions) { + if (devpriv->got_regions) comedi_pci_disable(devpriv->pdev); - } pci_dev_put(devpriv->pdev); } } @@ -1308,213 +1311,225 @@ static int s626_detach(comedi_device * dev) /* * this functions build the RPS program for hardware driven acquistion */ -void ResetADC(comedi_device * dev, uint8_t * ppl) +void ResetADC(struct comedi_device *dev, uint8_t *ppl) { register uint32_t *pRPS; uint32_t JmpAdrs; uint16_t i; uint16_t n; uint32_t LocalPPL; - comedi_cmd *cmd = &(dev->subdevices->async->cmd); + struct comedi_cmd *cmd = &(dev->subdevices->async->cmd); - // Stop RPS program in case it is currently running. + /* Stop RPS program in case it is currently running. */ MC_DISABLE(P_MC1, MC1_ERPS1); - // Set starting logical address to write RPS commands. + /* Set starting logical address to write RPS commands. */ pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase; - // Initialize RPS instruction pointer. + /* Initialize RPS instruction pointer. */ WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase); - // Construct RPS program in RPSBuf DMA buffer + /* Construct RPS program in RPSBuf DMA buffer */ if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) { DEBUG("ResetADC: scan_begin pause inserted\n"); - // Wait for Start trigger. + /* Wait for Start trigger. */ *pRPS++ = RPS_PAUSE | RPS_SIGADC; *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC; } - // SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary - // because the first RPS DEBI Write following a non-RPS DEBI write - // seems to always fail. If we don't do this dummy write, the ADC - // gain might not be set to the value required for the first slot in - // the poll list; the ADC gain would instead remain unchanged from - // the previously programmed value. - *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); // Write DEBI Write command - // and address to shadow RAM. - *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL; - *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); // Write DEBI immediate data - // to shadow RAM: - *pRPS++ = GSEL_BIPOLAR5V; // arbitrary immediate data - // value. - *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; // Reset "shadow RAM - // uploaded" flag. - *pRPS++ = RPS_UPLOAD | RPS_DEBI; // Invoke shadow RAM upload. - *pRPS++ = RPS_PAUSE | RPS_DEBI; // Wait for shadow upload to finish. - // Digitize all slots in the poll list. This is implemented as a - // for loop to limit the slot count to 16 in case the application - // forgot to set the EOPL flag in the final slot. + /* SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary + * because the first RPS DEBI Write following a non-RPS DEBI write + * seems to always fail. If we don't do this dummy write, the ADC + * gain might not be set to the value required for the first slot in + * the poll list; the ADC gain would instead remain unchanged from + * the previously programmed value. + */ + *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); + /* Write DEBI Write command and address to shadow RAM. */ + + *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL; + *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); + /* Write DEBI immediate data to shadow RAM: */ + + *pRPS++ = GSEL_BIPOLAR5V; + /* arbitrary immediate data value. */ + + *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; + /* Reset "shadow RAM uploaded" flag. */ + *pRPS++ = RPS_UPLOAD | RPS_DEBI; /* Invoke shadow RAM upload. */ + *pRPS++ = RPS_PAUSE | RPS_DEBI; /* Wait for shadow upload to finish. */ + + /* Digitize all slots in the poll list. This is implemented as a + * for loop to limit the slot count to 16 in case the application + * forgot to set the EOPL flag in the final slot. + */ for (devpriv->AdcItems = 0; devpriv->AdcItems < 16; devpriv->AdcItems++) { - // Convert application's poll list item to private board class - // format. Each app poll list item is an uint8_t with form - // (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 = - // +-10V, 1 = +-5V, and EOPL = End of Poll List marker. + /* Convert application's poll list item to private board class + * format. Each app poll list item is an uint8_t with form + * (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 = + * +-10V, 1 = +-5V, and EOPL = End of Poll List marker. + */ LocalPPL = (*ppl << 8) | (*ppl & 0x10 ? GSEL_BIPOLAR5V : GSEL_BIPOLAR10V); - // Switch ADC analog gain. - *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); // Write DEBI command - // and address to - // shadow RAM. + /* Switch ADC analog gain. */ + *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); /* Write DEBI command */ + /* and address to */ + /* shadow RAM. */ *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL; - *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); // Write DEBI - // immediate data to - // shadow RAM. + *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); /* Write DEBI */ + /* immediate data to */ + /* shadow RAM. */ *pRPS++ = LocalPPL; - *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; // Reset "shadow RAM uploaded" - // flag. - *pRPS++ = RPS_UPLOAD | RPS_DEBI; // Invoke shadow RAM upload. - *pRPS++ = RPS_PAUSE | RPS_DEBI; // Wait for shadow upload to - // finish. + *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; /* Reset "shadow RAM uploaded" */ + /* flag. */ + *pRPS++ = RPS_UPLOAD | RPS_DEBI; /* Invoke shadow RAM upload. */ + *pRPS++ = RPS_PAUSE | RPS_DEBI; /* Wait for shadow upload to */ + /* finish. */ - // Select ADC analog input channel. - *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); // Write DEBI command - // and address to - // shadow RAM. + /* Select ADC analog input channel. */ + *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); + /* Write DEBI command and address to shadow RAM. */ *pRPS++ = DEBI_CMD_WRWORD | LP_ISEL; - *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); // Write DEBI - // immediate data to - // shadow RAM. + *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); + /* Write DEBI immediate data to shadow RAM. */ *pRPS++ = LocalPPL; - *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; // Reset "shadow RAM uploaded" - // flag. - *pRPS++ = RPS_UPLOAD | RPS_DEBI; // Invoke shadow RAM upload. - *pRPS++ = RPS_PAUSE | RPS_DEBI; // Wait for shadow upload to - // finish. + *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; + /* Reset "shadow RAM uploaded" flag. */ - // Delay at least 10 microseconds for analog input settling. - // Instead of padding with NOPs, we use RPS_JUMP instructions - // here; this allows us to produce a longer delay than is - // possible with NOPs because each RPS_JUMP flushes the RPS' - // instruction prefetch pipeline. + *pRPS++ = RPS_UPLOAD | RPS_DEBI; + /* Invoke shadow RAM upload. */ + + *pRPS++ = RPS_PAUSE | RPS_DEBI; + /* Wait for shadow upload to finish. */ + + /* Delay at least 10 microseconds for analog input settling. + * Instead of padding with NOPs, we use RPS_JUMP instructions + * here; this allows us to produce a longer delay than is + * possible with NOPs because each RPS_JUMP flushes the RPS' + * instruction prefetch pipeline. + */ JmpAdrs = (uint32_t) devpriv->RPSBuf.PhysicalBase + (uint32_t) ((unsigned long)pRPS - (unsigned long)devpriv->RPSBuf.LogicalBase); for (i = 0; i < (10 * RPSCLK_PER_US / 2); i++) { - JmpAdrs += 8; // Repeat to implement time delay: - *pRPS++ = RPS_JUMP; // Jump to next RPS instruction. + JmpAdrs += 8; /* Repeat to implement time delay: */ + *pRPS++ = RPS_JUMP; /* Jump to next RPS instruction. */ *pRPS++ = JmpAdrs; } if (cmd != NULL && cmd->convert_src != TRIG_NOW) { DEBUG("ResetADC: convert pause inserted\n"); - // Wait for Start trigger. + /* Wait for Start trigger. */ *pRPS++ = RPS_PAUSE | RPS_SIGADC; *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC; } - // Start ADC by pulsing GPIO1. - *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // Begin ADC Start pulse. + /* Start ADC by pulsing GPIO1. */ + *pRPS++ = RPS_LDREG | (P_GPIO >> 2); /* Begin ADC Start pulse. */ *pRPS++ = GPIO_BASE | GPIO1_LO; *pRPS++ = RPS_NOP; - // VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. - *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // End ADC Start pulse. + /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */ + *pRPS++ = RPS_LDREG | (P_GPIO >> 2); /* End ADC Start pulse. */ *pRPS++ = GPIO_BASE | GPIO1_HI; - // Wait for ADC to complete (GPIO2 is asserted high when ADC not - // busy) and for data from previous conversion to shift into FB - // BUFFER 1 register. - *pRPS++ = RPS_PAUSE | RPS_GPIO2; // Wait for ADC done. + /* Wait for ADC to complete (GPIO2 is asserted high when ADC not + * busy) and for data from previous conversion to shift into FB + * BUFFER 1 register. + */ + *pRPS++ = RPS_PAUSE | RPS_GPIO2; /* Wait for ADC done. */ - // Transfer ADC data from FB BUFFER 1 register to DMA buffer. + /* Transfer ADC data from FB BUFFER 1 register to DMA buffer. */ *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2); *pRPS++ = (uint32_t) devpriv->ANABuf.PhysicalBase + (devpriv->AdcItems << 2); - // If this slot's EndOfPollList flag is set, all channels have - // now been processed. + /* If this slot's EndOfPollList flag is set, all channels have */ + /* now been processed. */ if (*ppl++ & EOPL) { - devpriv->AdcItems++; // Adjust poll list item count. - break; // Exit poll list processing loop. + devpriv->AdcItems++; /* Adjust poll list item count. */ + break; /* Exit poll list processing loop. */ } } DEBUG("ResetADC: ADC items %d \n", devpriv->AdcItems); - // VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the - // ADC to stabilize for 2 microseconds before starting the final - // (dummy) conversion. This delay is necessary to allow sufficient - // time between last conversion finished and the start of the dummy - // conversion. Without this delay, the last conversion's data value - // is sometimes set to the previous conversion's data value. + /* VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the + * ADC to stabilize for 2 microseconds before starting the final + * (dummy) conversion. This delay is necessary to allow sufficient + * time between last conversion finished and the start of the dummy + * conversion. Without this delay, the last conversion's data value + * is sometimes set to the previous conversion's data value. + */ for (n = 0; n < (2 * RPSCLK_PER_US); n++) *pRPS++ = RPS_NOP; - // Start a dummy conversion to cause the data from the last - // conversion of interest to be shifted in. - *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // Begin ADC Start pulse. + /* Start a dummy conversion to cause the data from the last + * conversion of interest to be shifted in. + */ + *pRPS++ = RPS_LDREG | (P_GPIO >> 2); /* Begin ADC Start pulse. */ *pRPS++ = GPIO_BASE | GPIO1_LO; *pRPS++ = RPS_NOP; - // VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. - *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // End ADC Start pulse. + /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */ + *pRPS++ = RPS_LDREG | (P_GPIO >> 2); /* End ADC Start pulse. */ *pRPS++ = GPIO_BASE | GPIO1_HI; - // Wait for the data from the last conversion of interest to arrive - // in FB BUFFER 1 register. - *pRPS++ = RPS_PAUSE | RPS_GPIO2; // Wait for ADC done. + /* Wait for the data from the last conversion of interest to arrive + * in FB BUFFER 1 register. + */ + *pRPS++ = RPS_PAUSE | RPS_GPIO2; /* Wait for ADC done. */ - // Transfer final ADC data from FB BUFFER 1 register to DMA buffer. - *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2); // + /* Transfer final ADC data from FB BUFFER 1 register to DMA buffer. */ + *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2); /* */ *pRPS++ = (uint32_t) devpriv->ANABuf.PhysicalBase + (devpriv->AdcItems << 2); - // Indicate ADC scan loop is finished. - // *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ; // Signal ReadADC() that scan is done. + /* Indicate ADC scan loop is finished. */ + /* *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ; // Signal ReadADC() that scan is done. */ - //invoke interrupt + /* invoke interrupt */ if (devpriv->ai_cmd_running == 1) { DEBUG("ResetADC: insert irq in ADC RPS task\n"); *pRPS++ = RPS_IRQ; } - // Restart RPS program at its beginning. - *pRPS++ = RPS_JUMP; // Branch to start of RPS program. + /* Restart RPS program at its beginning. */ + *pRPS++ = RPS_JUMP; /* Branch to start of RPS program. */ *pRPS++ = (uint32_t) devpriv->RPSBuf.PhysicalBase; - // End of RPS program build - // ------------------------------------------------------------ + /* End of RPS program build */ } /* TO COMPLETE, IF NECESSARY */ -static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int s626_ai_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { return -EINVAL; } -/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) */ +/* static int s626_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) */ /* { */ /* register uint8_t i; */ /* register int32_t *readaddr; */ /* DEBUG("as626_ai_rinsn: ai_rinsn enter \n"); */ -/* // Trigger ADC scan loop start by setting RPS Signal 0. */ +/* Trigger ADC scan loop start by setting RPS Signal 0. */ /* MC_ENABLE( P_MC2, MC2_ADC_RPS ); */ -/* // Wait until ADC scan loop is finished (RPS Signal 0 reset). */ +/* Wait until ADC scan loop is finished (RPS Signal 0 reset). */ /* while ( MC_TEST( P_MC2, MC2_ADC_RPS ) ); */ -/* // Init ptr to DMA buffer that holds new ADC data. We skip the */ -/* // first uint16_t in the buffer because it contains junk data from */ -/* // the final ADC of the previous poll list scan. */ +/* Init ptr to DMA buffer that holds new ADC data. We skip the + * first uint16_t in the buffer because it contains junk data from + * the final ADC of the previous poll list scan. + */ /* readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; */ -/* // Convert ADC data to 16-bit integer values and copy to application */ -/* // buffer. */ +/* Convert ADC data to 16-bit integer values and copy to application buffer. */ /* for ( i = 0; i < devpriv->AdcItems; i++ ) { */ /* *data = s626_ai_reg_to_uint( *readaddr++ ); */ /* DEBUG("s626_ai_rinsn: data %d \n",*data); */ @@ -1525,8 +1540,8 @@ static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s, /* return i; */ /* } */ -static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int s626_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { uint16_t chan = CR_CHAN(insn->chanspec); uint16_t range = CR_RANGE(insn->chanspec); @@ -1534,86 +1549,87 @@ static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s, uint32_t GpioImage; int n; -/* //interrupt call test */ -/* writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); //Writing a logical 1 */ -/* //into any of the RPS_PSR */ -/* //bits causes the */ -/* //corresponding interrupt */ -/* //to be generated if */ -/* //enabled */ + /* interrupt call test */ +/* writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); */ + /* Writing a logical 1 into any of the RPS_PSR bits causes the + * corresponding interrupt to be generated if enabled + */ DEBUG("s626_ai_insn_read: entering\n"); - // Convert application's ADC specification into form - // appropriate for register programming. + /* Convert application's ADC specification into form + * appropriate for register programming. + */ if (range == 0) AdcSpec = (chan << 8) | (GSEL_BIPOLAR5V); else AdcSpec = (chan << 8) | (GSEL_BIPOLAR10V); - // Switch ADC analog gain. - DEBIwrite(dev, LP_GSEL, AdcSpec); // Set gain. + /* Switch ADC analog gain. */ + DEBIwrite(dev, LP_GSEL, AdcSpec); /* Set gain. */ - // Select ADC analog input channel. - DEBIwrite(dev, LP_ISEL, AdcSpec); // Select channel. + /* Select ADC analog input channel. */ + DEBIwrite(dev, LP_ISEL, AdcSpec); /* Select channel. */ for (n = 0; n < insn->n; n++) { - // Delay 10 microseconds for analog input settling. + /* Delay 10 microseconds for analog input settling. */ comedi_udelay(10); - // Start ADC by pulsing GPIO1 low. + /* Start ADC by pulsing GPIO1 low. */ GpioImage = RR7146(P_GPIO); - // Assert ADC Start command + /* Assert ADC Start command */ WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - // and stretch it out. + /* and stretch it out. */ WR7146(P_GPIO, GpioImage & ~GPIO1_HI); WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - // Negate ADC Start command. + /* Negate ADC Start command. */ WR7146(P_GPIO, GpioImage | GPIO1_HI); - // Wait for ADC to complete (GPIO2 is asserted high when - // ADC not busy) and for data from previous conversion to - // shift into FB BUFFER 1 register. + /* Wait for ADC to complete (GPIO2 is asserted high when */ + /* ADC not busy) and for data from previous conversion to */ + /* shift into FB BUFFER 1 register. */ - // Wait for ADC done. - while (!(RR7146(P_PSR) & PSR_GPIO2)) ; + /* Wait for ADC done. */ + while (!(RR7146(P_PSR) & PSR_GPIO2)) + ; - // Fetch ADC data. + /* Fetch ADC data. */ if (n != 0) data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1)); - // Allow the ADC to stabilize for 4 microseconds before - // starting the next (final) conversion. This delay is - // necessary to allow sufficient time between last - // conversion finished and the start of the next - // conversion. Without this delay, the last conversion's - // data value is sometimes set to the previous - // conversion's data value. + /* Allow the ADC to stabilize for 4 microseconds before + * starting the next (final) conversion. This delay is + * necessary to allow sufficient time between last + * conversion finished and the start of the next + * conversion. Without this delay, the last conversion's + * data value is sometimes set to the previous + * conversion's data value. + */ comedi_udelay(4); } - // Start a dummy conversion to cause the data from the - // previous conversion to be shifted in. + /* Start a dummy conversion to cause the data from the + * previous conversion to be shifted in. */ GpioImage = RR7146(P_GPIO); - //Assert ADC Start command + /* Assert ADC Start command */ WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - // and stretch it out. + /* and stretch it out. */ WR7146(P_GPIO, GpioImage & ~GPIO1_HI); WR7146(P_GPIO, GpioImage & ~GPIO1_HI); - // Negate ADC Start command. + /* Negate ADC Start command. */ WR7146(P_GPIO, GpioImage | GPIO1_HI); - // Wait for the data to arrive in FB BUFFER 1 register. + /* Wait for the data to arrive in FB BUFFER 1 register. */ - // Wait for ADC done. - while (!(RR7146(P_PSR) & PSR_GPIO2)) ; + /* Wait for ADC done. */ + while (!(RR7146(P_PSR) & PSR_GPIO2)) + ; - // Fetch ADC data from audio interface's input shift - // register. + /* Fetch ADC data from audio interface's input shift register. */ - // Fetch ADC data. + /* Fetch ADC data. */ if (n != 0) data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1)); @@ -1622,7 +1638,7 @@ static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s, return n; } -static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd) +static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd) { int n; @@ -1638,7 +1654,7 @@ static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd) return n; } -static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s, +static int s626_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { if (trignum != 0) @@ -1646,7 +1662,7 @@ static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s, DEBUG("s626_ai_inttrig: trigger adc start..."); - // Start executing the RPS program. + /* Start executing the RPS program. */ MC_ENABLE(P_MC1, MC1_ERPS1); s->async->inttrig = NULL; @@ -1657,12 +1673,12 @@ static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s, } /* TO COMPLETE */ -static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) +static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { uint8_t ppl[16]; - comedi_cmd *cmd = &s->async->cmd; - enc_private *k; + struct comedi_cmd *cmd = &s->async->cmd; + struct enc_private *k; int tick; DEBUG("s626_ai_cmd: entering command function\n"); @@ -1672,20 +1688,20 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) dev->minor); return -EBUSY; } - //disable interrupt + /* disable interrupt */ writel(0, devpriv->base_addr + P_IER); - //clear interrupt request + /* clear interrupt request */ writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->base_addr + P_ISR); - //clear any pending interrupt + /* clear any pending interrupt */ s626_dio_clear_irq(dev); - // s626_enc_clear_irq(dev); + /* s626_enc_clear_irq(dev); */ - //reset ai_cmd_running flag + /* reset ai_cmd_running flag */ devpriv->ai_cmd_running = 0; - // test if cmd is valid + /* test if cmd is valid */ if (cmd == NULL) { DEBUG("s626_ai_cmd: NULL command\n"); return -EINVAL; @@ -1707,12 +1723,12 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) case TRIG_FOLLOW: break; case TRIG_TIMER: - // set a conter to generate adc trigger at scan_begin_arg interval + /* set a conter to generate adc trigger at scan_begin_arg interval */ k = &encpriv[5]; tick = s626_ns_to_timer((int *)&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); - //load timer value and enable interrupt + /* load timer value and enable interrupt */ s626_timer_load(dev, k, tick); k->SetEnable(dev, k, CLKENAB_ALWAYS); @@ -1721,7 +1737,7 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) break; case TRIG_EXT: - // set the digital line and interrupt for scan trigger + /* set the digital line and interrupt for scan trigger */ if (cmd->start_src != TRIG_EXT) s626_dio_set_irq(dev, cmd->scan_begin_arg); @@ -1734,19 +1750,19 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) case TRIG_NOW: break; case TRIG_TIMER: - // set a conter to generate adc trigger at convert_arg interval + /* set a conter to generate adc trigger at convert_arg interval */ k = &encpriv[4]; tick = s626_ns_to_timer((int *)&cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); - //load timer value and enable interrupt + /* load timer value and enable interrupt */ s626_timer_load(dev, k, tick); k->SetEnable(dev, k, CLKENAB_INDEX); DEBUG("s626_ai_cmd: convert trigger timer is set with value %d\n", tick); break; case TRIG_EXT: - // set the digital line and interrupt for convert trigger + /* set the digital line and interrupt for convert trigger */ if (cmd->scan_begin_src != TRIG_EXT && cmd->start_src == TRIG_EXT) s626_dio_set_irq(dev, cmd->convert_arg); @@ -1758,12 +1774,12 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) switch (cmd->stop_src) { case TRIG_COUNT: - // data arrives as one packet + /* data arrives as one packet */ devpriv->ai_sample_count = cmd->stop_arg; devpriv->ai_continous = 0; break; case TRIG_NONE: - // continous aquisition + /* continous aquisition */ devpriv->ai_continous = 1; devpriv->ai_sample_count = 0; break; @@ -1773,17 +1789,17 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) switch (cmd->start_src) { case TRIG_NOW: - // Trigger ADC scan loop start by setting RPS Signal 0. - // MC_ENABLE( P_MC2, MC2_ADC_RPS ); + /* Trigger ADC scan loop start by setting RPS Signal 0. */ + /* MC_ENABLE( P_MC2, MC2_ADC_RPS ); */ - // Start executing the RPS program. + /* Start executing the RPS program. */ MC_ENABLE(P_MC1, MC1_ERPS1); DEBUG("s626_ai_cmd: ADC triggered\n"); s->async->inttrig = NULL; break; case TRIG_EXT: - //configure DIO channel for acquisition trigger + /* configure DIO channel for acquisition trigger */ s626_dio_set_irq(dev, cmd->start_arg); DEBUG("s626_ai_cmd: External start trigger is set!!!\n"); @@ -1795,7 +1811,7 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) break; } - //enable interrupt + /* enable interrupt */ writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER); DEBUG("s626_ai_cmd: command function terminated\n"); @@ -1803,8 +1819,8 @@ static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) return 0; } -static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s, - comedi_cmd * cmd) +static int s626_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd) { int err = 0; int tmp; @@ -1988,12 +2004,12 @@ static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s, return 0; } -static int s626_ai_cancel(comedi_device * dev, comedi_subdevice * s) +static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - // Stop RPS program in case it is currently running. + /* Stop RPS program in case it is currently running. */ MC_DISABLE(P_MC1, MC1_ERPS1); - //disable master interrupt + /* disable master interrupt */ writel(0, devpriv->base_addr + P_IER); devpriv->ai_cmd_running = 0; @@ -2010,7 +2026,7 @@ static int s626_ns_to_timer(int *nanosec, int round_mode) { int divider, base; - base = 500; //2MHz internal clock + base = 500; /* 2MHz internal clock */ switch (round_mode) { case TRIG_ROUND_NEAREST: @@ -2029,8 +2045,8 @@ static int s626_ns_to_timer(int *nanosec, int round_mode) return divider - 1; } -static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int i; @@ -2048,45 +2064,42 @@ static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s, return i; } -static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int i; - for (i = 0; i < insn->n; i++) { + for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; - } return i; } -///////////////////////////////////////////////////////////////////// -/////////////// DIGITAL I/O FUNCTIONS ///////////////////////////// -///////////////////////////////////////////////////////////////////// -// All DIO functions address a group of DIO channels by means of -// "group" argument. group may be 0, 1 or 2, which correspond to DIO -// ports A, B and C, respectively. -///////////////////////////////////////////////////////////////////// +/* *************** DIGITAL I/O FUNCTIONS *************** + * All DIO functions address a group of DIO channels by means of + * "group" argument. group may be 0, 1 or 2, which correspond to DIO + * ports A, B and C, respectively. + */ -static void s626_dio_init(comedi_device * dev) +static void s626_dio_init(struct comedi_device *dev) { uint16_t group; - comedi_subdevice *s; + struct comedi_subdevice *s; - // Prepare to treat writes to WRCapSel as capture disables. + /* Prepare to treat writes to WRCapSel as capture disables. */ DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); - // For each group of sixteen channels ... + /* For each group of sixteen channels ... */ for (group = 0; group < S626_DIO_BANKS; group++) { s = dev->subdevices + 2 + group; - DEBIwrite(dev, diopriv->WRIntSel, 0); // Disable all interrupts. - DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF); // Disable all event - // captures. - DEBIwrite(dev, diopriv->WREdgSel, 0); // Init all DIOs to - // default edge - // polarity. - DEBIwrite(dev, diopriv->WRDOut, 0); // Program all outputs - // to inactive state. + DEBIwrite(dev, diopriv->WRIntSel, 0); /* Disable all interrupts. */ + DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF); /* Disable all event */ + /* captures. */ + DEBIwrite(dev, diopriv->WREdgSel, 0); /* Init all DIOs to */ + /* default edge */ + /* polarity. */ + DEBIwrite(dev, diopriv->WRDOut, 0); /* Program all outputs */ + /* to inactive state. */ } DEBUG("s626_dio_init: DIO initialized \n"); } @@ -2097,14 +2110,14 @@ static void s626_dio_init(comedi_device * dev) * This allows packed reading/writing of the DIO channels. The comedi * core can convert between insn_bits and insn_read/write */ -static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int s626_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { /* Length of data must be 2 (mask and new data, see below) */ - if (insn->n == 0) { + if (insn->n == 0) return 0; - } + if (insn->n != 2) { printk("comedi%d: s626: s626_dio_insn_bits(): Invalid instruction length\n", dev->minor); return -EINVAL; @@ -2133,8 +2146,8 @@ static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s, return 2; } -static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int s626_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { switch (data[0]) { @@ -2160,75 +2173,75 @@ static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s, return 1; } -static int s626_dio_set_irq(comedi_device * dev, unsigned int chan) +static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan) { unsigned int group; unsigned int bitmask; unsigned int status; - //select dio bank + /* select dio bank */ group = chan / 16; bitmask = 1 << (chan - (16 * group)); DEBUG("s626_dio_set_irq: enable interrupt on dio channel %d group %d\n", chan - (16 * group), group); - //set channel to capture positive edge + /* set channel to capture positive edge */ status = DEBIread(dev, - ((dio_private *) (dev->subdevices + 2 + + ((struct dio_private *) (dev->subdevices + 2 + group)->private)->RDEdgSel); DEBIwrite(dev, - ((dio_private *) (dev->subdevices + 2 + + ((struct dio_private *) (dev->subdevices + 2 + group)->private)->WREdgSel, bitmask | status); - //enable interrupt on selected channel + /* enable interrupt on selected channel */ status = DEBIread(dev, - ((dio_private *) (dev->subdevices + 2 + + ((struct dio_private *) (dev->subdevices + 2 + group)->private)->RDIntSel); DEBIwrite(dev, - ((dio_private *) (dev->subdevices + 2 + + ((struct dio_private *) (dev->subdevices + 2 + group)->private)->WRIntSel, bitmask | status); - //enable edge capture write command + /* enable edge capture write command */ DEBIwrite(dev, LP_MISC1, MISC1_EDCAP); - //enable edge capture on selected channel + /* enable edge capture on selected channel */ status = DEBIread(dev, - ((dio_private *) (dev->subdevices + 2 + + ((struct dio_private *) (dev->subdevices + 2 + group)->private)->RDCapSel); DEBIwrite(dev, - ((dio_private *) (dev->subdevices + 2 + + ((struct dio_private *) (dev->subdevices + 2 + group)->private)->WRCapSel, bitmask | status); return 0; } -static int s626_dio_reset_irq(comedi_device * dev, unsigned int group, +static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group, unsigned int mask) { DEBUG("s626_dio_reset_irq: disable interrupt on dio channel %d group %d\n", mask, group); - //disable edge capture write command + /* disable edge capture write command */ DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); - //enable edge capture on selected channel + /* enable edge capture on selected channel */ DEBIwrite(dev, - ((dio_private *) (dev->subdevices + 2 + + ((struct dio_private *) (dev->subdevices + 2 + group)->private)->WRCapSel, mask); return 0; } -static int s626_dio_clear_irq(comedi_device * dev) +static int s626_dio_clear_irq(struct comedi_device *dev) { unsigned int group; - //disable edge capture write command + /* disable edge capture write command */ DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); for (group = 0; group < S626_DIO_BANKS; group++) { - //clear pending events and interrupt + /* clear pending events and interrupt */ DEBIwrite(dev, - ((dio_private *) (dev->subdevices + 2 + + ((struct dio_private *) (dev->subdevices + 2 + group)->private)->WRCapSel, 0xffff); } @@ -2238,26 +2251,26 @@ static int s626_dio_clear_irq(comedi_device * dev) /* Now this function initializes the value of the counter (data[0]) and set the subdevice. To complete with trigger and interrupt configuration */ -static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | // Preload upon - // index. - (INDXSRC_SOFT << BF_INDXSRC) | // Disable hardware index. - (CLKSRC_COUNTER << BF_CLKSRC) | // Operating mode is Counter. - (CLKPOL_POS << BF_CLKPOL) | // Active high clock. - //( CNTDIR_UP << BF_CLKPOL ) | // Count direction is Down. - (CLKMULT_1X << BF_CLKMULT) | // Clock multiplier is 1x. + uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | /* Preload upon */ + /* index. */ + (INDXSRC_SOFT << BF_INDXSRC) | /* Disable hardware index. */ + (CLKSRC_COUNTER << BF_CLKSRC) | /* Operating mode is Counter. */ + (CLKPOL_POS << BF_CLKPOL) | /* Active high clock. */ + /* ( CNTDIR_UP << BF_CLKPOL ) | // Count direction is Down. */ + (CLKMULT_1X << BF_CLKMULT) | /* Clock multiplier is 1x. */ (CLKENAB_INDEX << BF_CLKENAB); /* uint16_t DisableIntSrc=TRUE; */ - // uint32_t Preloadvalue; //Counter initial value + /* uint32_t Preloadvalue; //Counter initial value */ uint16_t valueSrclatch = LATCHSRC_AB_READ; uint16_t enab = CLKENAB_ALWAYS; - enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; + struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; DEBUG("s626_enc_insn_config: encoder config\n"); - // (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); + /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ k->SetMode(dev, k, Setup, TRUE); Preload(dev, k, *(insn->data)); @@ -2268,12 +2281,12 @@ static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s, return insn->n; } -static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; - enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; + struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; DEBUG("s626_enc_insn_read: encoder read channel %d \n", CR_CHAN(insn->chanspec)); @@ -2286,20 +2299,20 @@ static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s, return n; } -static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s, - comedi_insn * insn, lsampl_t * data) +static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { - enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; + struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; DEBUG("s626_enc_insn_write: encoder write channel %d \n", CR_CHAN(insn->chanspec)); - // Set the preload register + /* Set the preload register */ Preload(dev, k, data[0]); - // Software index pulse forces the preload register to load - // into the counter + /* Software index pulse forces the preload register to load */ + /* into the counter */ k->SetLoadTrig(dev, k, 0); k->PulseIndex(dev, k); k->SetLoadTrig(dev, k, 2); @@ -2309,175 +2322,165 @@ static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s, return 1; } -static void s626_timer_load(comedi_device * dev, enc_private * k, int tick) +static void s626_timer_load(struct comedi_device *dev, struct enc_private *k, int tick) { - uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | // Preload upon - // index. - (INDXSRC_SOFT << BF_INDXSRC) | // Disable hardware index. - (CLKSRC_TIMER << BF_CLKSRC) | // Operating mode is Timer. - (CLKPOL_POS << BF_CLKPOL) | // Active high clock. - (CNTDIR_DOWN << BF_CLKPOL) | // Count direction is Down. - (CLKMULT_1X << BF_CLKMULT) | // Clock multiplier is 1x. + uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | /* Preload upon */ + /* index. */ + (INDXSRC_SOFT << BF_INDXSRC) | /* Disable hardware index. */ + (CLKSRC_TIMER << BF_CLKSRC) | /* Operating mode is Timer. */ + (CLKPOL_POS << BF_CLKPOL) | /* Active high clock. */ + (CNTDIR_DOWN << BF_CLKPOL) | /* Count direction is Down. */ + (CLKMULT_1X << BF_CLKMULT) | /* Clock multiplier is 1x. */ (CLKENAB_INDEX << BF_CLKENAB); uint16_t valueSrclatch = LATCHSRC_A_INDXA; - // uint16_t enab=CLKENAB_ALWAYS; + /* uint16_t enab=CLKENAB_ALWAYS; */ k->SetMode(dev, k, Setup, FALSE); - // Set the preload register + /* Set the preload register */ Preload(dev, k, tick); - // Software index pulse forces the preload register to load - // into the counter + /* Software index pulse forces the preload register to load */ + /* into the counter */ k->SetLoadTrig(dev, k, 0); k->PulseIndex(dev, k); - //set reload on counter overflow + /* set reload on counter overflow */ k->SetLoadTrig(dev, k, 1); - //set interrupt on overflow + /* set interrupt on overflow */ k->SetIntSrc(dev, k, INTSRC_OVER); SetLatchSource(dev, k, valueSrclatch); - // k->SetEnable(dev,k,(uint16_t)(enab != 0)); + /* k->SetEnable(dev,k,(uint16_t)(enab != 0)); */ } -/////////////////////////////////////////////////////////////////////// -///////////////////// DAC FUNCTIONS ///////////////////////////////// -/////////////////////////////////////////////////////////////////////// +/* *********** DAC FUNCTIONS *********** */ -// Slot 0 base settings. -#define VECT0 ( XSD2 | RSD3 | SIB_A2 ) // Slot 0 always shifts in - // 0xFF and store it to - // FB_BUFFER2. +/* Slot 0 base settings. */ +#define VECT0 (XSD2 | RSD3 | SIB_A2) +/* Slot 0 always shifts in 0xFF and store it to FB_BUFFER2. */ -// TrimDac LogicalChan-to-PhysicalChan mapping table. +/* TrimDac LogicalChan-to-PhysicalChan mapping table. */ static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 }; -// TrimDac LogicalChan-to-EepromAdrs mapping table. +/* TrimDac LogicalChan-to-EepromAdrs mapping table. */ static uint8_t trimadrs[] = { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 }; -static void LoadTrimDACs(comedi_device * dev) +static void LoadTrimDACs(struct comedi_device *dev) { register uint8_t i; - // Copy TrimDac setpoint values from EEPROM to TrimDacs. + /* Copy TrimDac setpoint values from EEPROM to TrimDacs. */ for (i = 0; i < (sizeof(trimchan) / sizeof(trimchan[0])); i++) WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i])); } -static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan, +static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan, uint8_t DacData) { uint32_t chan; - // Save the new setpoint in case the application needs to read it back later. + /* Save the new setpoint in case the application needs to read it back later. */ devpriv->TrimSetpoint[LogicalChan] = (uint8_t) DacData; - // Map logical channel number to physical channel number. + /* Map logical channel number to physical channel number. */ chan = (uint32_t) trimchan[LogicalChan]; - // Set up TSL2 records for TrimDac write operation. All slots shift - // 0xFF in from pulled-up SD3 so that the end of the slot sequence - // can be detected. - SETVECT(2, XSD2 | XFIFO_1 | WS3); // Slot 2: Send high uint8_t - // to target TrimDac. - SETVECT(3, XSD2 | XFIFO_0 | WS3); // Slot 3: Send low uint8_t to - // target TrimDac. - SETVECT(4, XSD2 | XFIFO_3 | WS1); // Slot 4: Send NOP high - // uint8_t to DAC0 to keep - // clock running. - SETVECT(5, XSD2 | XFIFO_2 | WS1 | EOS); // Slot 5: Send NOP low - // uint8_t to DAC0. + /* Set up TSL2 records for TrimDac write operation. All slots shift + * 0xFF in from pulled-up SD3 so that the end of the slot sequence + * can be detected. + */ - // Construct and transmit target DAC's serial packet: ( 0000 AAAA - // ),( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the DAC - // channel's address, and D<7:0> is the DAC setpoint. Append a WORD - // value (that writes a channel 0 NOP command to a non-existent main - // DAC channel) that serves to keep the clock running after the - // packet has been sent to the target DAC. + SETVECT(2, XSD2 | XFIFO_1 | WS3); + /* Slot 2: Send high uint8_t to target TrimDac. */ + SETVECT(3, XSD2 | XFIFO_0 | WS3); + /* Slot 3: Send low uint8_t to target TrimDac. */ + SETVECT(4, XSD2 | XFIFO_3 | WS1); + /* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running. */ + SETVECT(5, XSD2 | XFIFO_2 | WS1 | EOS); + /* Slot 5: Send NOP low uint8_t to DAC0. */ - SendDAC(dev, ((uint32_t) chan << 8) // Address the DAC channel - // within the trimdac device. - | (uint32_t) DacData); // Include DAC setpoint data. + /* Construct and transmit target DAC's serial packet: + * ( 0000 AAAA ), ( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the + * DAC channel's address, and D<7:0> is the DAC setpoint. Append a + * WORD value (that writes a channel 0 NOP command to a non-existent + * main DAC channel) that serves to keep the clock running after the + * packet has been sent to the target DAC. + */ + + /* Address the DAC channel within the trimdac device. */ + SendDAC(dev, ((uint32_t) chan << 8) + | (uint32_t) DacData); /* Include DAC setpoint data. */ } -///////////////////////////////////////////////////////////////////////// -//////////////// EEPROM ACCESS FUNCTIONS ////////////////////////////// -///////////////////////////////////////////////////////////////////////// +/* ************** EEPROM ACCESS FUNCTIONS ************** */ +/* Read uint8_t from EEPROM. */ -/////////////////////////////////////////// -// Read uint8_t from EEPROM. - -static uint8_t I2Cread(comedi_device * dev, uint8_t addr) +static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr) { uint8_t rtnval; - // Send EEPROM target address. - if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW) // Byte2 = I2C - // command: - // write to - // I2C EEPROM - // device. - | I2C_B1(I2C_ATTRSTOP, addr) // Byte1 = EEPROM - // internal target - // address. - | I2C_B0(I2C_ATTRNOP, 0))) // Byte0 = Not - // sent. - { - // Abort function and declare error if handshake failed. + /* Send EEPROM target address. */ + if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW) + /* Byte2 = I2C command: write to I2C EEPROM device. */ + | I2C_B1(I2C_ATTRSTOP, addr) + /* Byte1 = EEPROM internal target address. */ + | I2C_B0(I2C_ATTRNOP, 0))) { /* Byte0 = Not sent. */ + /* Abort function and declare error if handshake failed. */ DEBUG("I2Cread: error handshake I2Cread a\n"); return 0; } - // Execute EEPROM read. - if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CR) // Byte2 = I2C - // command: read - // from I2C EEPROM - // device. - | I2C_B1(I2C_ATTRSTOP, 0) // Byte1 receives - // uint8_t from - // EEPROM. - | I2C_B0(I2C_ATTRNOP, 0))) // Byte0 = Not - // sent. - { - // Abort function and declare error if handshake failed. + /* Execute EEPROM read. */ + if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CR) /* Byte2 = I2C */ + /* command: read */ + /* from I2C EEPROM */ + /* device. */ + | I2C_B1(I2C_ATTRSTOP, 0) /* Byte1 receives */ + /* uint8_t from */ + /* EEPROM. */ + | I2C_B0(I2C_ATTRNOP, 0))) { /* Byte0 = Not sent. */ + + /* Abort function and declare error if handshake failed. */ DEBUG("I2Cread: error handshake I2Cread b\n"); return 0; } - // Return copy of EEPROM value. + /* Return copy of EEPROM value. */ rtnval = (uint8_t) (RR7146(P_I2CCTRL) >> 16); return rtnval; } -static uint32_t I2Chandshake(comedi_device * dev, uint32_t val) +static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val) { - // Write I2C command to I2C Transfer Control shadow register. + /* Write I2C command to I2C Transfer Control shadow register. */ WR7146(P_I2CCTRL, val); - // Upload I2C shadow registers into working registers and wait for - // upload confirmation. + /* Upload I2C shadow registers into working registers and wait for */ + /* upload confirmation. */ MC_ENABLE(P_MC2, MC2_UPLD_IIC); - while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ; + while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) + ; - // Wait until I2C bus transfer is finished or an error occurs. - while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY) ; + /* Wait until I2C bus transfer is finished or an error occurs. */ + while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY) + ; - // Return non-zero if I2C error occured. + /* Return non-zero if I2C error occured. */ return RR7146(P_I2CCTRL) & I2C_ERR; } -// Private helper function: Write setpoint to an application DAC channel. +/* Private helper function: Write setpoint to an application DAC channel. */ -static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata) +static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata) { register uint16_t signmask; register uint32_t WSImage; - // Adjust DAC data polarity and set up Polarity Control Register - // image. + /* Adjust DAC data polarity and set up Polarity Control Register */ + /* image. */ signmask = 1 << chan; if (dacdata < 0) { dacdata = -dacdata; @@ -2485,237 +2488,252 @@ static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata) } else devpriv->Dacpol &= ~signmask; - // Limit DAC setpoint value to valid range. + /* Limit DAC setpoint value to valid range. */ if ((uint16_t) dacdata > 0x1FFF) dacdata = 0x1FFF; - // Set up TSL2 records (aka "vectors") for DAC update. Vectors V2 - // and V3 transmit the setpoint to the target DAC. V4 and V5 send - // data to a non-existent TrimDac channel just to keep the clock - // running after sending data to the target DAC. This is necessary - // to eliminate the clock glitch that would otherwise occur at the - // end of the target DAC's serial data stream. When the sequence - // restarts at V0 (after executing V5), the gate array automatically - // disables gating for the DAC clock and all DAC chip selects. - WSImage = (chan & 2) ? WS1 : WS2; // Choose DAC chip select to - // be asserted. - SETVECT(2, XSD2 | XFIFO_1 | WSImage); // Slot 2: Transmit high - // data byte to target DAC. - SETVECT(3, XSD2 | XFIFO_0 | WSImage); // Slot 3: Transmit low data - // byte to target DAC. - SETVECT(4, XSD2 | XFIFO_3 | WS3); // Slot 4: Transmit to - // non-existent TrimDac - // channel to keep clock - SETVECT(5, XSD2 | XFIFO_2 | WS3 | EOS); // Slot 5: running after - // writing target DAC's - // low data byte. + /* Set up TSL2 records (aka "vectors") for DAC update. Vectors V2 + * and V3 transmit the setpoint to the target DAC. V4 and V5 send + * data to a non-existent TrimDac channel just to keep the clock + * running after sending data to the target DAC. This is necessary + * to eliminate the clock glitch that would otherwise occur at the + * end of the target DAC's serial data stream. When the sequence + * restarts at V0 (after executing V5), the gate array automatically + * disables gating for the DAC clock and all DAC chip selects. + */ - // Construct and transmit target DAC's serial packet: ( A10D DDDD - // ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>, and D<12:0> - // is the DAC setpoint. Append a WORD value (that writes to a - // non-existent TrimDac channel) that serves to keep the clock - // running after the packet has been sent to the target DAC. - SendDAC(dev, 0x0F000000 //Continue clock after target DAC - //data (write to non-existent - //trimdac). - | 0x00004000 // Address the two main dual-DAC - // devices (TSL's chip select enables - // target device). - | ((uint32_t) (chan & 1) << 15) // Address the DAC - // channel within the - // device. - | (uint32_t) dacdata); // Include DAC setpoint data. + WSImage = (chan & 2) ? WS1 : WS2; + /* Choose DAC chip select to be asserted. */ + SETVECT(2, XSD2 | XFIFO_1 | WSImage); + /* Slot 2: Transmit high data byte to target DAC. */ + SETVECT(3, XSD2 | XFIFO_0 | WSImage); + /* Slot 3: Transmit low data byte to target DAC. */ + SETVECT(4, XSD2 | XFIFO_3 | WS3); + /* Slot 4: Transmit to non-existent TrimDac channel to keep clock */ + SETVECT(5, XSD2 | XFIFO_2 | WS3 | EOS); + /* Slot 5: running after writing target DAC's low data byte. */ + + /* Construct and transmit target DAC's serial packet: + * ( A10D DDDD ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>, + * and D<12:0> is the DAC setpoint. Append a WORD value (that writes + * to a non-existent TrimDac channel) that serves to keep the clock + * running after the packet has been sent to the target DAC. + */ + SendDAC(dev, 0x0F000000 + /* Continue clock after target DAC data (write to non-existent trimdac). */ + | 0x00004000 + /* Address the two main dual-DAC devices (TSL's chip select enables + * target device). */ + | ((uint32_t) (chan & 1) << 15) + /* Address the DAC channel within the device. */ + | (uint32_t) dacdata); /* Include DAC setpoint data. */ } -//////////////////////////////////////////////////////// -// Private helper function: Transmit serial data to DAC via Audio -// channel 2. Assumes: (1) TSL2 slot records initialized, and (2) -// Dacpol contains valid target image. +/* Private helper function: Transmit serial data to DAC via Audio + * channel 2. Assumes: (1) TSL2 slot records initialized, and (2) + * Dacpol contains valid target image. + */ -static void SendDAC(comedi_device * dev, uint32_t val) +static void SendDAC(struct comedi_device *dev, uint32_t val) { - // START THE SERIAL CLOCK RUNNING ------------- + /* START THE SERIAL CLOCK RUNNING ------------- */ - // Assert DAC polarity control and enable gating of DAC serial clock - // and audio bit stream signals. At this point in time we must be - // assured of being in time slot 0. If we are not in slot 0, the - // serial clock and audio stream signals will be disabled; this is - // because the following DEBIwrite statement (which enables signals - // to be passed through the gate array) would execute before the - // trailing edge of WS1/WS3 (which turns off the signals), thus - // causing the signals to be inactive during the DAC write. + /* Assert DAC polarity control and enable gating of DAC serial clock + * and audio bit stream signals. At this point in time we must be + * assured of being in time slot 0. If we are not in slot 0, the + * serial clock and audio stream signals will be disabled; this is + * because the following DEBIwrite statement (which enables signals + * to be passed through the gate array) would execute before the + * trailing edge of WS1/WS3 (which turns off the signals), thus + * causing the signals to be inactive during the DAC write. + */ DEBIwrite(dev, LP_DACPOL, devpriv->Dacpol); - // TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- + /* TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- */ - // Copy DAC setpoint value to DAC's output DMA buffer. + /* Copy DAC setpoint value to DAC's output DMA buffer. */ - //WR7146( (uint32_t)devpriv->pDacWBuf, val ); + /* WR7146( (uint32_t)devpriv->pDacWBuf, val ); */ *devpriv->pDacWBuf = val; - // enab the output DMA transfer. This will cause the DMAC to copy - // the DAC's data value to A2's output FIFO. The DMA transfer will - // then immediately terminate because the protection address is - // reached upon transfer of the first DWORD value. + /* enab the output DMA transfer. This will cause the DMAC to copy + * the DAC's data value to A2's output FIFO. The DMA transfer will + * then immediately terminate because the protection address is + * reached upon transfer of the first DWORD value. + */ MC_ENABLE(P_MC1, MC1_A2OUT); - // While the DMA transfer is executing ... + /* While the DMA transfer is executing ... */ - // Reset Audio2 output FIFO's underflow flag (along with any other - // FIFO underflow/overflow flags). When set, this flag will - // indicate that we have emerged from slot 0. + /* Reset Audio2 output FIFO's underflow flag (along with any other + * FIFO underflow/overflow flags). When set, this flag will + * indicate that we have emerged from slot 0. + */ WR7146(P_ISR, ISR_AFOU); - // Wait for the DMA transfer to finish so that there will be data - // available in the FIFO when time slot 1 tries to transfer a DWORD - // from the FIFO to the output buffer register. We test for DMA - // Done by polling the DMAC enable flag; this flag is automatically - // cleared when the transfer has finished. - while ((RR7146(P_MC1) & MC1_A2OUT) != 0) ; + /* Wait for the DMA transfer to finish so that there will be data + * available in the FIFO when time slot 1 tries to transfer a DWORD + * from the FIFO to the output buffer register. We test for DMA + * Done by polling the DMAC enable flag; this flag is automatically + * cleared when the transfer has finished. + */ + while ((RR7146(P_MC1) & MC1_A2OUT) != 0) + ; - // START THE OUTPUT STREAM TO THE TARGET DAC -------------------- + /* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */ - // FIFO data is now available, so we enable execution of time slots - // 1 and higher by clearing the EOS flag in slot 0. Note that SD3 - // will be shifted in and stored in FB_BUFFER2 for end-of-slot-list - // detection. + /* FIFO data is now available, so we enable execution of time slots + * 1 and higher by clearing the EOS flag in slot 0. Note that SD3 + * will be shifted in and stored in FB_BUFFER2 for end-of-slot-list + * detection. + */ SETVECT(0, XSD2 | RSD3 | SIB_A2); - // Wait for slot 1 to execute to ensure that the Packet will be - // transmitted. This is detected by polling the Audio2 output FIFO - // underflow flag, which will be set when slot 1 execution has - // finished transferring the DAC's data DWORD from the output FIFO - // to the output buffer register. - while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0) ; + /* Wait for slot 1 to execute to ensure that the Packet will be + * transmitted. This is detected by polling the Audio2 output FIFO + * underflow flag, which will be set when slot 1 execution has + * finished transferring the DAC's data DWORD from the output FIFO + * to the output buffer register. + */ + while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0) + ; - // Set up to trap execution at slot 0 when the TSL sequencer cycles - // back to slot 0 after executing the EOS in slot 5. Also, - // simultaneously shift out and in the 0x00 that is ALWAYS the value - // stored in the last byte to be shifted out of the FIFO's DWORD - // buffer register. + /* Set up to trap execution at slot 0 when the TSL sequencer cycles + * back to slot 0 after executing the EOS in slot 5. Also, + * simultaneously shift out and in the 0x00 that is ALWAYS the value + * stored in the last byte to be shifted out of the FIFO's DWORD + * buffer register. + */ SETVECT(0, XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS); - // WAIT FOR THE TRANSACTION TO FINISH ----------------------- + /* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */ - // Wait for the TSL to finish executing all time slots before - // exiting this function. We must do this so that the next DAC - // write doesn't start, thereby enabling clock/chip select signals: - // 1. Before the TSL sequence cycles back to slot 0, which disables - // the clock/cs signal gating and traps slot // list execution. If - // we have not yet finished slot 5 then the clock/cs signals are - // still gated and we have // not finished transmitting the stream. - // 2. While slots 2-5 are executing due to a late slot 0 trap. In - // this case, the slot sequence is currently // repeating, but with - // clock/cs signals disabled. We must wait for slot 0 to trap - // execution before setting // up the next DAC setpoint DMA transfer - // and enabling the clock/cs signals. To detect the end of slot 5, - // we test for the FB_BUFFER2 MSB contents to be equal to 0xFF. If - // the TSL has not yet finished executing slot 5 ... + /* Wait for the TSL to finish executing all time slots before + * exiting this function. We must do this so that the next DAC + * write doesn't start, thereby enabling clock/chip select signals: + * + * 1. Before the TSL sequence cycles back to slot 0, which disables + * the clock/cs signal gating and traps slot // list execution. + * we have not yet finished slot 5 then the clock/cs signals are + * still gated and we have not finished transmitting the stream. + * + * 2. While slots 2-5 are executing due to a late slot 0 trap. In + * this case, the slot sequence is currently repeating, but with + * clock/cs signals disabled. We must wait for slot 0 to trap + * execution before setting up the next DAC setpoint DMA transfer + * and enabling the clock/cs signals. To detect the end of slot 5, + * we test for the FB_BUFFER2 MSB contents to be equal to 0xFF. If + * the TSL has not yet finished executing slot 5 ... + */ if ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) { - // The trap was set on time and we are still executing somewhere - // in slots 2-5, so we now wait for slot 0 to execute and trap - // TSL execution. This is detected when FB_BUFFER2 MSB changes - // from 0xFF to 0x00, which slot 0 causes to happen by shifting - // out/in on SD2 the 0x00 that is always referenced by slot 5. - while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) ; + /* The trap was set on time and we are still executing somewhere + * in slots 2-5, so we now wait for slot 0 to execute and trap + * TSL execution. This is detected when FB_BUFFER2 MSB changes + * from 0xFF to 0x00, which slot 0 causes to happen by shifting + * out/in on SD2 the 0x00 that is always referenced by slot 5. + */ + while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) + ; } - // Either (1) we were too late setting the slot 0 trap; the TSL - // sequencer restarted slot 0 before we could set the EOS trap flag, - // or (2) we were not late and execution is now trapped at slot 0. - // In either case, we must now change slot 0 so that it will store - // value 0xFF (instead of 0x00) to FB_BUFFER2 next time it executes. - // In order to do this, we reprogram slot 0 so that it will shift in - // SD3, which is driven only by a pull-up resistor. + /* Either (1) we were too late setting the slot 0 trap; the TSL + * sequencer restarted slot 0 before we could set the EOS trap flag, + * or (2) we were not late and execution is now trapped at slot 0. + * In either case, we must now change slot 0 so that it will store + * value 0xFF (instead of 0x00) to FB_BUFFER2 next time it executes. + * In order to do this, we reprogram slot 0 so that it will shift in + * SD3, which is driven only by a pull-up resistor. + */ SETVECT(0, RSD3 | SIB_A2 | EOS); - // Wait for slot 0 to execute, at which time the TSL is setup for - // the next DAC write. This is detected when FB_BUFFER2 MSB changes - // from 0x00 to 0xFF. - while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0) ; + /* Wait for slot 0 to execute, at which time the TSL is setup for + * the next DAC write. This is detected when FB_BUFFER2 MSB changes + * from 0x00 to 0xFF. + */ + while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0) + ; } -static void WriteMISC2(comedi_device * dev, uint16_t NewImage) +static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage) { - DEBIwrite(dev, LP_MISC1, MISC1_WENABLE); // enab writes to - // MISC2 register. - DEBIwrite(dev, LP_WRMISC2, NewImage); // Write new image to MISC2. - DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE); // Disable writes to MISC2. + DEBIwrite(dev, LP_MISC1, MISC1_WENABLE); /* enab writes to */ + /* MISC2 register. */ + DEBIwrite(dev, LP_WRMISC2, NewImage); /* Write new image to MISC2. */ + DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE); /* Disable writes to MISC2. */ } -///////////////////////////////////////////////////////////////////// -// Initialize the DEBI interface for all transfers. +/* Initialize the DEBI interface for all transfers. */ -static uint16_t DEBIread(comedi_device * dev, uint16_t addr) +static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr) { uint16_t retval; - // Set up DEBI control register value in shadow RAM. + /* Set up DEBI control register value in shadow RAM. */ WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr); - // Execute the DEBI transfer. + /* Execute the DEBI transfer. */ DEBItransfer(dev); - // Fetch target register value. + /* Fetch target register value. */ retval = (uint16_t) RR7146(P_DEBIAD); - // Return register value. + /* Return register value. */ return retval; } -// Execute a DEBI transfer. This must be called from within a -// critical section. -static void DEBItransfer(comedi_device * dev) +/* Execute a DEBI transfer. This must be called from within a */ +/* critical section. */ +static void DEBItransfer(struct comedi_device *dev) { - // Initiate upload of shadow RAM to DEBI control register. + /* Initiate upload of shadow RAM to DEBI control register. */ MC_ENABLE(P_MC2, MC2_UPLD_DEBI); - // Wait for completion of upload from shadow RAM to DEBI control - // register. - while (!MC_TEST(P_MC2, MC2_UPLD_DEBI)) ; + /* Wait for completion of upload from shadow RAM to DEBI control */ + /* register. */ + while (!MC_TEST(P_MC2, MC2_UPLD_DEBI)) + ; - // Wait until DEBI transfer is done. - while (RR7146(P_PSR) & PSR_DEBI_S) ; + /* Wait until DEBI transfer is done. */ + while (RR7146(P_PSR) & PSR_DEBI_S) + ; } -// Write a value to a gate array register. -static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata) +/* Write a value to a gate array register. */ +static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata) { - // Set up DEBI control register value in shadow RAM. + /* Set up DEBI control register value in shadow RAM. */ WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr); WR7146(P_DEBIAD, wdata); - // Execute the DEBI transfer. + /* Execute the DEBI transfer. */ DEBItransfer(dev); } -///////////////////////////////////////////////////////////////////////////// -// Replace the specified bits in a gate array register. Imports: mask -// specifies bits that are to be preserved, wdata is new value to be -// or'd with the masked original. -static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask, +/* Replace the specified bits in a gate array register. Imports: mask + * specifies bits that are to be preserved, wdata is new value to be + * or'd with the masked original. + */ +static void DEBIreplace(struct comedi_device *dev, uint16_t addr, uint16_t mask, uint16_t wdata) { - // Copy target gate array register into P_DEBIAD register. - WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr); // Set up DEBI control - // reg value in shadow - // RAM. - DEBItransfer(dev); // Execute the DEBI - // Read transfer. + /* Copy target gate array register into P_DEBIAD register. */ + WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr); + /* Set up DEBI control reg value in shadow RAM. */ + DEBItransfer(dev); /* Execute the DEBI Read transfer. */ - // Write back the modified image. - WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr); // Set up DEBI control - // reg value in shadow - // RAM. + /* Write back the modified image. */ + WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr); + /* Set up DEBI control reg value in shadow RAM. */ - WR7146(P_DEBIAD, wdata | ((uint16_t) RR7146(P_DEBIAD) & mask)); // Modify the register image. - DEBItransfer(dev); // Execute the DEBI Write transfer. + WR7146(P_DEBIAD, wdata | ((uint16_t) RR7146(P_DEBIAD) & mask)); + /* Modify the register image. */ + DEBItransfer(dev); /* Execute the DEBI Write transfer. */ } -static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize) +static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, size_t bsize) { void *vbptr; dma_addr_t vpptr; @@ -2723,7 +2741,7 @@ static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize) DEBUG("CloseDMAB: Entering S626DRV_CloseDMAB():\n"); if (pdma == NULL) return; - //find the matching allocation from the board struct + /* find the matching allocation from the board struct */ vbptr = pdma->LogicalBase; vpptr = pdma->PhysicalBase; @@ -2737,268 +2755,260 @@ static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize) } } -//////////////////////////////////////////////////////////////////////// -///////////////// COUNTER FUNCTIONS ////////////////////////////////// -//////////////////////////////////////////////////////////////////////// -// All counter functions address a specific counter by means of the -// "Counter" argument, which is a logical counter number. The Counter -// argument may have any of the following legal values: 0=0A, 1=1A, -// 2=2A, 3=0B, 4=1B, 5=2B. -//////////////////////////////////////////////////////////////////////// +/* ****** COUNTER FUNCTIONS ******* */ +/* All counter functions address a specific counter by means of the + * "Counter" argument, which is a logical counter number. The Counter + * argument may have any of the following legal values: 0=0A, 1=1A, + * 2=2A, 3=0B, 4=1B, 5=2B. + */ -// Forward declarations for functions that are common to both A and B -// counters: +/* Forward declarations for functions that are common to both A and B counters: */ -///////////////////////////////////////////////////////////////////// -//////////////////// PRIVATE COUNTER FUNCTIONS ///////////////////// -///////////////////////////////////////////////////////////////////// +/* ****** PRIVATE COUNTER FUNCTIONS ****** */ -///////////////////////////////////////////////////////////////// -// Read a counter's output latch. +/* Read a counter's output latch. */ -static uint32_t ReadLatch(comedi_device * dev, enc_private * k) +static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k) { register uint32_t value; - //DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n"); + /* DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n"); */ - // Latch counts and fetch LSW of latched counts value. + /* Latch counts and fetch LSW of latched counts value. */ value = (uint32_t) DEBIread(dev, k->MyLatchLsw); - // Fetch MSW of latched counts and combine with LSW. + /* Fetch MSW of latched counts and combine with LSW. */ value |= ((uint32_t) DEBIread(dev, k->MyLatchLsw + 2) << 16); - // DEBUG FIXME DEBUG("ReadLatch: Read Latch exit\n"); + /* DEBUG FIXME DEBUG("ReadLatch: Read Latch exit\n"); */ - // Return latched counts. + /* Return latched counts. */ return value; } -/////////////////////////////////////////////////////////////////// -// Reset a counter's index and overflow event capture flags. +/* Reset a counter's index and overflow event capture flags. */ -static void ResetCapFlags_A(comedi_device * dev, enc_private * k) +static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k) { DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL), CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); } -static void ResetCapFlags_B(comedi_device * dev, enc_private * k) +static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k) { DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL), CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B); } -///////////////////////////////////////////////////////////////////////// -// Return counter setup in a format (COUNTER_SETUP) that is consistent -// for both A and B counters. +/* Return counter setup in a format (COUNTER_SETUP) that is consistent */ +/* for both A and B counters. */ -static uint16_t GetMode_A(comedi_device * dev, enc_private * k) +static uint16_t GetMode_A(struct comedi_device *dev, struct enc_private *k) { register uint16_t cra; register uint16_t crb; register uint16_t setup; - // Fetch CRA and CRB register images. + /* Fetch CRA and CRB register images. */ cra = DEBIread(dev, k->MyCRA); crb = DEBIread(dev, k->MyCRB); - // Populate the standardized counter setup bit fields. Note: - // IndexSrc is restricted to ENC_X or IndxPol. - setup = ((cra & STDMSK_LOADSRC) // LoadSrc = LoadSrcA. - | ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) // LatchSrc = LatchSrcA. - | ((cra << (STDBIT_INTSRC - CRABIT_INTSRC_A)) & STDMSK_INTSRC) // IntSrc = IntSrcA. - | ((cra << (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))) & STDMSK_INDXSRC) // IndxSrc = IndxSrcA<1>. - | ((cra >> (CRABIT_INDXPOL_A - STDBIT_INDXPOL)) & STDMSK_INDXPOL) // IndxPol = IndxPolA. - | ((crb >> (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)) & STDMSK_CLKENAB)); // ClkEnab = ClkEnabA. + /* Populate the standardized counter setup bit fields. Note: */ + /* IndexSrc is restricted to ENC_X or IndxPol. */ + setup = ((cra & STDMSK_LOADSRC) /* LoadSrc = LoadSrcA. */ + | ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) /* LatchSrc = LatchSrcA. */ + | ((cra << (STDBIT_INTSRC - CRABIT_INTSRC_A)) & STDMSK_INTSRC) /* IntSrc = IntSrcA. */ + | ((cra << (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))) & STDMSK_INDXSRC) /* IndxSrc = IndxSrcA<1>. */ + | ((cra >> (CRABIT_INDXPOL_A - STDBIT_INDXPOL)) & STDMSK_INDXPOL) /* IndxPol = IndxPolA. */ + | ((crb >> (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)) & STDMSK_CLKENAB)); /* ClkEnab = ClkEnabA. */ - // Adjust mode-dependent parameters. - if (cra & (2 << CRABIT_CLKSRC_A)) // If Timer mode (ClkSrcA<1> == 1): - setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) // Indicate Timer mode. - | ((cra << (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) & STDMSK_CLKPOL) // Set ClkPol to indicate count direction (ClkSrcA<0>). - | (MULT_X1 << STDBIT_CLKMULT)); // ClkMult must be 1x in Timer mode. + /* Adjust mode-dependent parameters. */ + if (cra & (2 << CRABIT_CLKSRC_A)) /* If Timer mode (ClkSrcA<1> == 1): */ + setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) /* Indicate Timer mode. */ + | ((cra << (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) & STDMSK_CLKPOL) /* Set ClkPol to indicate count direction (ClkSrcA<0>). */ + | (MULT_X1 << STDBIT_CLKMULT)); /* ClkMult must be 1x in Timer mode. */ - else // If Counter mode (ClkSrcA<1> == 0): - setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) // Indicate Counter mode. - | ((cra >> (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) & STDMSK_CLKPOL) // Pass through ClkPol. - | (((cra & CRAMSK_CLKMULT_A) == (MULT_X0 << CRABIT_CLKMULT_A)) ? // Force ClkMult to 1x if not legal, else pass through. + else /* If Counter mode (ClkSrcA<1> == 0): */ + setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) /* Indicate Counter mode. */ + | ((cra >> (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) & STDMSK_CLKPOL) /* Pass through ClkPol. */ + | (((cra & CRAMSK_CLKMULT_A) == (MULT_X0 << CRABIT_CLKMULT_A)) ? /* Force ClkMult to 1x if not legal, else pass through. */ (MULT_X1 << STDBIT_CLKMULT) : ((cra >> (CRABIT_CLKMULT_A - STDBIT_CLKMULT)) & STDMSK_CLKMULT))); - // Return adjusted counter setup. + /* Return adjusted counter setup. */ return setup; } -static uint16_t GetMode_B(comedi_device * dev, enc_private * k) +static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k) { register uint16_t cra; register uint16_t crb; register uint16_t setup; - // Fetch CRA and CRB register images. + /* Fetch CRA and CRB register images. */ cra = DEBIread(dev, k->MyCRA); crb = DEBIread(dev, k->MyCRB); - // Populate the standardized counter setup bit fields. Note: - // IndexSrc is restricted to ENC_X or IndxPol. - setup = (((crb << (STDBIT_INTSRC - CRBBIT_INTSRC_B)) & STDMSK_INTSRC) // IntSrc = IntSrcB. - | ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) // LatchSrc = LatchSrcB. - | ((crb << (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)) & STDMSK_LOADSRC) // LoadSrc = LoadSrcB. - | ((crb << (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)) & STDMSK_INDXPOL) // IndxPol = IndxPolB. - | ((crb >> (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) & STDMSK_CLKENAB) // ClkEnab = ClkEnabB. - | ((cra >> ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)) & STDMSK_INDXSRC)); // IndxSrc = IndxSrcB<1>. + /* Populate the standardized counter setup bit fields. Note: */ + /* IndexSrc is restricted to ENC_X or IndxPol. */ + setup = (((crb << (STDBIT_INTSRC - CRBBIT_INTSRC_B)) & STDMSK_INTSRC) /* IntSrc = IntSrcB. */ + | ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) /* LatchSrc = LatchSrcB. */ + | ((crb << (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)) & STDMSK_LOADSRC) /* LoadSrc = LoadSrcB. */ + | ((crb << (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)) & STDMSK_INDXPOL) /* IndxPol = IndxPolB. */ + | ((crb >> (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) & STDMSK_CLKENAB) /* ClkEnab = ClkEnabB. */ + | ((cra >> ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)) & STDMSK_INDXSRC)); /* IndxSrc = IndxSrcB<1>. */ - // Adjust mode-dependent parameters. - if ((crb & CRBMSK_CLKMULT_B) == (MULT_X0 << CRBBIT_CLKMULT_B)) // If Extender mode (ClkMultB == MULT_X0): - setup |= ((CLKSRC_EXTENDER << STDBIT_CLKSRC) // Indicate Extender mode. - | (MULT_X1 << STDBIT_CLKMULT) // Indicate multiplier is 1x. - | ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); // Set ClkPol equal to Timer count direction (ClkSrcB<0>). + /* Adjust mode-dependent parameters. */ + if ((crb & CRBMSK_CLKMULT_B) == (MULT_X0 << CRBBIT_CLKMULT_B)) /* If Extender mode (ClkMultB == MULT_X0): */ + setup |= ((CLKSRC_EXTENDER << STDBIT_CLKSRC) /* Indicate Extender mode. */ + | (MULT_X1 << STDBIT_CLKMULT) /* Indicate multiplier is 1x. */ + | ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); /* Set ClkPol equal to Timer count direction (ClkSrcB<0>). */ - else if (cra & (2 << CRABIT_CLKSRC_B)) // If Timer mode (ClkSrcB<1> == 1): - setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) // Indicate Timer mode. - | (MULT_X1 << STDBIT_CLKMULT) // Indicate multiplier is 1x. - | ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); // Set ClkPol equal to Timer count direction (ClkSrcB<0>). + else if (cra & (2 << CRABIT_CLKSRC_B)) /* If Timer mode (ClkSrcB<1> == 1): */ + setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) /* Indicate Timer mode. */ + | (MULT_X1 << STDBIT_CLKMULT) /* Indicate multiplier is 1x. */ + | ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); /* Set ClkPol equal to Timer count direction (ClkSrcB<0>). */ - else // If Counter mode (ClkSrcB<1> == 0): - setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) // Indicate Timer mode. - | ((crb >> (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)) & STDMSK_CLKMULT) // Clock multiplier is passed through. - | ((crb << (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) & STDMSK_CLKPOL)); // Clock polarity is passed through. + else /* If Counter mode (ClkSrcB<1> == 0): */ + setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) /* Indicate Timer mode. */ + | ((crb >> (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)) & STDMSK_CLKMULT) /* Clock multiplier is passed through. */ + | ((crb << (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) & STDMSK_CLKPOL)); /* Clock polarity is passed through. */ - // Return adjusted counter setup. + /* Return adjusted counter setup. */ return setup; } -///////////////////////////////////////////////////////////////////////////////////////////// -// Set the operating mode for the specified counter. The setup -// parameter is treated as a COUNTER_SETUP data type. The following -// parameters are programmable (all other parms are ignored): ClkMult, -// ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc. +/* + * Set the operating mode for the specified counter. The setup + * parameter is treated as a COUNTER_SETUP data type. The following + * parameters are programmable (all other parms are ignored): ClkMult, + * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc. + */ -static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup, +static void SetMode_A(struct comedi_device *dev, struct enc_private *k, uint16_t Setup, uint16_t DisableIntSrc) { register uint16_t cra; register uint16_t crb; - register uint16_t setup = Setup; // Cache the Standard Setup. + register uint16_t setup = Setup; /* Cache the Standard Setup. */ - // Initialize CRA and CRB images. - cra = ((setup & CRAMSK_LOADSRC_A) // Preload trigger is passed through. - | ((setup & STDMSK_INDXSRC) >> (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1)))); // IndexSrc is restricted to ENC_X or IndxPol. + /* Initialize CRA and CRB images. */ + cra = ((setup & CRAMSK_LOADSRC_A) /* Preload trigger is passed through. */ + | ((setup & STDMSK_INDXSRC) >> (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1)))); /* IndexSrc is restricted to ENC_X or IndxPol. */ - crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A // Reset any pending CounterA event captures. - | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_A - STDBIT_CLKENAB))); // Clock enable is passed through. + crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A /* Reset any pending CounterA event captures. */ + | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_A - STDBIT_CLKENAB))); /* Clock enable is passed through. */ - // Force IntSrc to Disabled if DisableIntSrc is asserted. + /* Force IntSrc to Disabled if DisableIntSrc is asserted. */ if (!DisableIntSrc) cra |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC - CRABIT_INTSRC_A)); - // Populate all mode-dependent attributes of CRA & CRB images. + /* Populate all mode-dependent attributes of CRA & CRB images. */ switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) { - case CLKSRC_EXTENDER: // Extender Mode: Force to Timer mode - // (Extender valid only for B counters). + case CLKSRC_EXTENDER: /* Extender Mode: Force to Timer mode */ + /* (Extender valid only for B counters). */ - case CLKSRC_TIMER: // Timer Mode: - cra |= ((2 << CRABIT_CLKSRC_A) // ClkSrcA<1> selects system clock - | ((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) // with count direction (ClkSrcA<0>) obtained from ClkPol. - | (1 << CRABIT_CLKPOL_A) // ClkPolA behaves as always-on clock enable. - | (MULT_X1 << CRABIT_CLKMULT_A)); // ClkMult must be 1x. + case CLKSRC_TIMER: /* Timer Mode: */ + cra |= ((2 << CRABIT_CLKSRC_A) /* ClkSrcA<1> selects system clock */ + | ((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) /* with count direction (ClkSrcA<0>) obtained from ClkPol. */ + | (1 << CRABIT_CLKPOL_A) /* ClkPolA behaves as always-on clock enable. */ + | (MULT_X1 << CRABIT_CLKMULT_A)); /* ClkMult must be 1x. */ break; - default: // Counter Mode: - cra |= (CLKSRC_COUNTER // Select ENC_C and ENC_D as clock/direction inputs. - | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) // Clock polarity is passed through. - | (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? // Force multiplier to x1 if not legal, otherwise pass through. + default: /* Counter Mode: */ + cra |= (CLKSRC_COUNTER /* Select ENC_C and ENC_D as clock/direction inputs. */ + | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) /* Clock polarity is passed through. */ + | (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? /* Force multiplier to x1 if not legal, otherwise pass through. */ (MULT_X1 << CRABIT_CLKMULT_A) : ((setup & STDMSK_CLKMULT) << (CRABIT_CLKMULT_A - STDBIT_CLKMULT)))); } - // Force positive index polarity if IndxSrc is software-driven only, - // otherwise pass it through. + /* Force positive index polarity if IndxSrc is software-driven only, */ + /* otherwise pass it through. */ if (~setup & STDMSK_INDXSRC) cra |= ((setup & STDMSK_INDXPOL) << (CRABIT_INDXPOL_A - STDBIT_INDXPOL)); - // If IntSrc has been forced to Disabled, update the MISC2 interrupt - // enable mask to indicate the counter interrupt is disabled. + /* If IntSrc has been forced to Disabled, update the MISC2 interrupt */ + /* enable mask to indicate the counter interrupt is disabled. */ if (DisableIntSrc) devpriv->CounterIntEnabs &= ~k->MyEventBits[3]; - // While retaining CounterB and LatchSrc configurations, program the - // new counter operating mode. + /* While retaining CounterB and LatchSrc configurations, program the */ + /* new counter operating mode. */ DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra); DEBIreplace(dev, k->MyCRB, (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb); } -static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup, +static void SetMode_B(struct comedi_device *dev, struct enc_private *k, uint16_t Setup, uint16_t DisableIntSrc) { register uint16_t cra; register uint16_t crb; - register uint16_t setup = Setup; // Cache the Standard Setup. + register uint16_t setup = Setup; /* Cache the Standard Setup. */ - // Initialize CRA and CRB images. - cra = ((setup & STDMSK_INDXSRC) << ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)); // IndexSrc field is restricted to ENC_X or IndxPol. + /* Initialize CRA and CRB images. */ + cra = ((setup & STDMSK_INDXSRC) << ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)); /* IndexSrc field is restricted to ENC_X or IndxPol. */ - crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B // Reset event captures and disable interrupts. - | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) // Clock enable is passed through. - | ((setup & STDMSK_LOADSRC) >> (STDBIT_LOADSRC - CRBBIT_LOADSRC_B))); // Preload trigger source is passed through. + crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B /* Reset event captures and disable interrupts. */ + | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) /* Clock enable is passed through. */ + | ((setup & STDMSK_LOADSRC) >> (STDBIT_LOADSRC - CRBBIT_LOADSRC_B))); /* Preload trigger source is passed through. */ - // Force IntSrc to Disabled if DisableIntSrc is asserted. + /* Force IntSrc to Disabled if DisableIntSrc is asserted. */ if (!DisableIntSrc) crb |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC - CRBBIT_INTSRC_B)); - // Populate all mode-dependent attributes of CRA & CRB images. + /* Populate all mode-dependent attributes of CRA & CRB images. */ switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) { - case CLKSRC_TIMER: // Timer Mode: - cra |= ((2 << CRABIT_CLKSRC_B) // ClkSrcB<1> selects system clock - | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); // with direction (ClkSrcB<0>) obtained from ClkPol. - crb |= ((1 << CRBBIT_CLKPOL_B) // ClkPolB behaves as always-on clock enable. - | (MULT_X1 << CRBBIT_CLKMULT_B)); // ClkMultB must be 1x. + case CLKSRC_TIMER: /* Timer Mode: */ + cra |= ((2 << CRABIT_CLKSRC_B) /* ClkSrcB<1> selects system clock */ + | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); /* with direction (ClkSrcB<0>) obtained from ClkPol. */ + crb |= ((1 << CRBBIT_CLKPOL_B) /* ClkPolB behaves as always-on clock enable. */ + | (MULT_X1 << CRBBIT_CLKMULT_B)); /* ClkMultB must be 1x. */ break; - case CLKSRC_EXTENDER: // Extender Mode: - cra |= ((2 << CRABIT_CLKSRC_B) // ClkSrcB source is OverflowA (same as "timer") - | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); // with direction obtained from ClkPol. - crb |= ((1 << CRBBIT_CLKPOL_B) // ClkPolB controls IndexB -- always set to active. - | (MULT_X0 << CRBBIT_CLKMULT_B)); // ClkMultB selects OverflowA as the clock source. + case CLKSRC_EXTENDER: /* Extender Mode: */ + cra |= ((2 << CRABIT_CLKSRC_B) /* ClkSrcB source is OverflowA (same as "timer") */ + | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); /* with direction obtained from ClkPol. */ + crb |= ((1 << CRBBIT_CLKPOL_B) /* ClkPolB controls IndexB -- always set to active. */ + | (MULT_X0 << CRBBIT_CLKMULT_B)); /* ClkMultB selects OverflowA as the clock source. */ break; - default: // Counter Mode: - cra |= (CLKSRC_COUNTER << CRABIT_CLKSRC_B); // Select ENC_C and ENC_D as clock/direction inputs. - crb |= (((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) // ClkPol is passed through. - | (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? // Force ClkMult to x1 if not legal, otherwise pass through. + default: /* Counter Mode: */ + cra |= (CLKSRC_COUNTER << CRABIT_CLKSRC_B); /* Select ENC_C and ENC_D as clock/direction inputs. */ + crb |= (((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) /* ClkPol is passed through. */ + | (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? /* Force ClkMult to x1 if not legal, otherwise pass through. */ (MULT_X1 << CRBBIT_CLKMULT_B) : ((setup & STDMSK_CLKMULT) << (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)))); } - // Force positive index polarity if IndxSrc is software-driven only, - // otherwise pass it through. + /* Force positive index polarity if IndxSrc is software-driven only, */ + /* otherwise pass it through. */ if (~setup & STDMSK_INDXSRC) crb |= ((setup & STDMSK_INDXPOL) >> (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)); - // If IntSrc has been forced to Disabled, update the MISC2 interrupt - // enable mask to indicate the counter interrupt is disabled. + /* If IntSrc has been forced to Disabled, update the MISC2 interrupt */ + /* enable mask to indicate the counter interrupt is disabled. */ if (DisableIntSrc) devpriv->CounterIntEnabs &= ~k->MyEventBits[3]; - // While retaining CounterA and LatchSrc configurations, program the - // new counter operating mode. + /* While retaining CounterA and LatchSrc configurations, program the */ + /* new counter operating mode. */ DEBIreplace(dev, k->MyCRA, (uint16_t) (~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B)), cra); DEBIreplace(dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb); } -//////////////////////////////////////////////////////////////////////// -// Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index. +/* Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index. */ -static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab) +static void SetEnable_A(struct comedi_device *dev, struct enc_private *k, uint16_t enab) { DEBUG("SetEnable_A: SetEnable_A enter 3541\n"); DEBIreplace(dev, k->MyCRB, @@ -3006,29 +3016,29 @@ static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab) (uint16_t) (enab << CRBBIT_CLKENAB_A)); } -static void SetEnable_B(comedi_device * dev, enc_private * k, uint16_t enab) +static void SetEnable_B(struct comedi_device *dev, struct enc_private *k, uint16_t enab) { DEBIreplace(dev, k->MyCRB, (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B)), (uint16_t) (enab << CRBBIT_CLKENAB_B)); } -static uint16_t GetEnable_A(comedi_device * dev, enc_private * k) +static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k) { return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_A) & 1; } -static uint16_t GetEnable_B(comedi_device * dev, enc_private * k) +static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k) { return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1; } -//////////////////////////////////////////////////////////////////////// -// Return/set a counter pair's latch trigger source. 0: On read -// access, 1: A index latches A, 2: B index latches B, 3: A overflow -// latches B. +/* Return/set a counter pair's latch trigger source. 0: On read + * access, 1: A index latches A, 2: B index latches B, 3: A overflow + * latches B. + */ -static void SetLatchSource(comedi_device * dev, enc_private * k, uint16_t value) +static void SetLatchSource(struct comedi_device *dev, struct enc_private *k, uint16_t value) { DEBUG("SetLatchSource: SetLatchSource enter 3550 \n"); DEBIreplace(dev, k->MyCRB, @@ -3038,210 +3048,206 @@ static void SetLatchSource(comedi_device * dev, enc_private * k, uint16_t value) DEBUG("SetLatchSource: SetLatchSource exit \n"); } -/* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ) */ -/* { */ -/* return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3; */ -/* } */ +/* + * static uint16_t GetLatchSource(struct comedi_device *dev, struct enc_private *k ) + * { + * return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3; + * } + */ -///////////////////////////////////////////////////////////////////////// -// Return/set the event that will trigger transfer of the preload -// register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow, -// 2=OverflowA (B counters only), 3=disabled. +/* + * Return/set the event that will trigger transfer of the preload + * register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow, + * 2=OverflowA (B counters only), 3=disabled. + */ -static void SetLoadTrig_A(comedi_device * dev, enc_private * k, uint16_t Trig) +static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k, uint16_t Trig) { DEBIreplace(dev, k->MyCRA, (uint16_t) (~CRAMSK_LOADSRC_A), (uint16_t) (Trig << CRABIT_LOADSRC_A)); } -static void SetLoadTrig_B(comedi_device * dev, enc_private * k, uint16_t Trig) +static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k, uint16_t Trig) { DEBIreplace(dev, k->MyCRB, (uint16_t) (~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL)), (uint16_t) (Trig << CRBBIT_LOADSRC_B)); } -static uint16_t GetLoadTrig_A(comedi_device * dev, enc_private * k) +static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k) { return (DEBIread(dev, k->MyCRA) >> CRABIT_LOADSRC_A) & 3; } -static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k) +static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k) { return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3; } -//////////////////// -// Return/set counter interrupt source and clear any captured -// index/overflow events. IntSource: 0=Disabled, 1=OverflowOnly, -// 2=IndexOnly, 3=IndexAndOverflow. +/* Return/set counter interrupt source and clear any captured + * index/overflow events. IntSource: 0=Disabled, 1=OverflowOnly, + * 2=IndexOnly, 3=IndexAndOverflow. + */ -static void SetIntSrc_A(comedi_device * dev, enc_private * k, +static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k, uint16_t IntSource) { - // Reset any pending counter overflow or index captures. + /* Reset any pending counter overflow or index captures. */ DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL), CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); - // Program counter interrupt source. + /* Program counter interrupt source. */ DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A, (uint16_t) (IntSource << CRABIT_INTSRC_A)); - // Update MISC2 interrupt enable mask. + /* Update MISC2 interrupt enable mask. */ devpriv->CounterIntEnabs = (devpriv->CounterIntEnabs & ~k->MyEventBits[3]) | k-> MyEventBits[IntSource]; } -static void SetIntSrc_B(comedi_device * dev, enc_private * k, +static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k, uint16_t IntSource) { uint16_t crb; - // Cache writeable CRB register image. + /* Cache writeable CRB register image. */ crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL; - // Reset any pending counter overflow or index captures. + /* Reset any pending counter overflow or index captures. */ DEBIwrite(dev, k->MyCRB, (uint16_t) (crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B)); - // Program counter interrupt source. + /* Program counter interrupt source. */ DEBIwrite(dev, k->MyCRB, (uint16_t) ((crb & ~CRBMSK_INTSRC_B) | (IntSource << CRBBIT_INTSRC_B))); - // Update MISC2 interrupt enable mask. + /* Update MISC2 interrupt enable mask. */ devpriv->CounterIntEnabs = (devpriv->CounterIntEnabs & ~k->MyEventBits[3]) | k-> MyEventBits[IntSource]; } -static uint16_t GetIntSrc_A(comedi_device * dev, enc_private * k) +static uint16_t GetIntSrc_A(struct comedi_device *dev, struct enc_private *k) { return (DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A) & 3; } -static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k) +static uint16_t GetIntSrc_B(struct comedi_device *dev, struct enc_private *k) { return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3; } -///////////////////////////////////////////////////////////////////////// -// Return/set the clock multiplier. +/* Return/set the clock multiplier. */ -/* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) */ +/* static void SetClkMult(struct comedi_device *dev, struct enc_private *k, uint16_t value ) */ /* { */ /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKMULT ) | ( value << STDBIT_CLKMULT ) ), FALSE ); */ /* } */ -/* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) */ +/* static uint16_t GetClkMult(struct comedi_device *dev, struct enc_private *k ) */ /* { */ /* return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */ /* } */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // Return/set the clock polarity. */ +/* Return/set the clock polarity. */ -/* static void SetClkPol( comedi_device *dev,enc_private *k, uint16_t value ) */ +/* static void SetClkPol( struct comedi_device *dev,struct enc_private *k, uint16_t value ) */ /* { */ /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKPOL ) | ( value << STDBIT_CLKPOL ) ), FALSE ); */ /* } */ -/* static uint16_t GetClkPol(comedi_device *dev, enc_private *k ) */ +/* static uint16_t GetClkPol(struct comedi_device *dev, struct enc_private *k ) */ /* { */ /* return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */ /* } */ -/* /////////////////////////////////////////////////////////////////////// */ -/* // Return/set the clock source. */ +/* Return/set the clock source. */ -/* static void SetClkSrc( comedi_device *dev,enc_private *k, uint16_t value ) */ +/* static void SetClkSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value ) */ /* { */ /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKSRC ) | ( value << STDBIT_CLKSRC ) ), FALSE ); */ /* } */ -/* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k ) */ +/* static uint16_t GetClkSrc( struct comedi_device *dev,struct enc_private *k ) */ /* { */ /* return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */ /* } */ -/* //////////////////////////////////////////////////////////////////////// */ -/* // Return/set the index polarity. */ +/* Return/set the index polarity. */ -/* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ) */ +/* static void SetIndexPol(struct comedi_device *dev, struct enc_private *k, uint16_t value ) */ /* { */ /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXPOL ) | ( (value != 0) << STDBIT_INDXPOL ) ), FALSE ); */ /* } */ -/* static uint16_t GetIndexPol(comedi_device *dev, enc_private *k ) */ +/* static uint16_t GetIndexPol(struct comedi_device *dev, struct enc_private *k ) */ /* { */ /* return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */ /* } */ -/* //////////////////////////////////////////////////////////////////////// */ -/* // Return/set the index source. */ +/* Return/set the index source. */ -/* static void SetIndexSrc(comedi_device *dev, enc_private *k, uint16_t value ) */ +/* static void SetIndexSrc(struct comedi_device *dev, struct enc_private *k, uint16_t value ) */ /* { */ /* DEBUG("SetIndexSrc: set index src enter 3700\n"); */ /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */ /* } */ -/* static uint16_t GetIndexSrc(comedi_device *dev, enc_private *k ) */ +/* static uint16_t GetIndexSrc(struct comedi_device *dev, struct enc_private *k ) */ /* { */ /* return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */ /* } */ -/////////////////////////////////////////////////////////////////// -// Generate an index pulse. +/* Generate an index pulse. */ -static void PulseIndex_A(comedi_device * dev, enc_private * k) +static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k) { register uint16_t cra; DEBUG("PulseIndex_A: pulse index enter\n"); - cra = DEBIread(dev, k->MyCRA); // Pulse index. + cra = DEBIread(dev, k->MyCRA); /* Pulse index. */ DEBIwrite(dev, k->MyCRA, (uint16_t) (cra ^ CRAMSK_INDXPOL_A)); DEBUG("PulseIndex_A: pulse index step1\n"); DEBIwrite(dev, k->MyCRA, cra); } -static void PulseIndex_B(comedi_device * dev, enc_private * k) +static void PulseIndex_B(struct comedi_device *dev, struct enc_private *k) { register uint16_t crb; - crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL; // Pulse index. + crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL; /* Pulse index. */ DEBIwrite(dev, k->MyCRB, (uint16_t) (crb ^ CRBMSK_INDXPOL_B)); DEBIwrite(dev, k->MyCRB, crb); } -///////////////////////////////////////////////////////// -// Write value into counter preload register. +/* Write value into counter preload register. */ -static void Preload(comedi_device * dev, enc_private * k, uint32_t value) +static void Preload(struct comedi_device *dev, struct enc_private *k, uint32_t value) { DEBUG("Preload: preload enter\n"); - DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value); // Write value to preload register. + DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value); /* Write value to preload register. */ DEBUG("Preload: preload step 1\n"); DEBIwrite(dev, (uint16_t) (k->MyLatchLsw + 2), (uint16_t) (value >> 16)); } -static void CountersInit(comedi_device * dev) +static void CountersInit(struct comedi_device *dev) { int chan; - enc_private *k; - uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | // Preload upon - // index. - (INDXSRC_SOFT << BF_INDXSRC) | // Disable hardware index. - (CLKSRC_COUNTER << BF_CLKSRC) | // Operating mode is counter. - (CLKPOL_POS << BF_CLKPOL) | // Active high clock. - (CNTDIR_UP << BF_CLKPOL) | // Count direction is up. - (CLKMULT_1X << BF_CLKMULT) | // Clock multiplier is 1x. - (CLKENAB_INDEX << BF_CLKENAB); // Enabled by index + struct enc_private *k; + uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | /* Preload upon */ + /* index. */ + (INDXSRC_SOFT << BF_INDXSRC) | /* Disable hardware index. */ + (CLKSRC_COUNTER << BF_CLKSRC) | /* Operating mode is counter. */ + (CLKPOL_POS << BF_CLKPOL) | /* Active high clock. */ + (CNTDIR_UP << BF_CLKPOL) | /* Count direction is up. */ + (CLKMULT_1X << BF_CLKMULT) | /* Clock multiplier is 1x. */ + (CLKENAB_INDEX << BF_CLKENAB); /* Enabled by index */ - // Disable all counter interrupts and clear any captured counter events. + /* Disable all counter interrupts and clear any captured counter events. */ for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) { k = &encpriv[chan]; k->SetMode(dev, k, Setup, TRUE); diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index 11d8b1ceb0b8..891126f25099 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -51,15 +51,15 @@ Example code - insn.insn=INSN_CONFIG; //configuration instruction - insn.n=1; //number of operation (must be 1) - insn.data=&initialvalue; //initial value loaded into encoder - //during configuration - insn.subdev=5; //encoder subdevice - insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel - //to configure + insn.insn=INSN_CONFIG; // configuration instruction + insn.n=1; // number of operation (must be 1) + insn.data=&initialvalue; // initial value loaded into encoder + // during configuration + insn.subdev=5; // encoder subdevice + insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); // encoder_channel + // to configure - comedi_do_insn(cf,&insn); //executing configuration + comedi_do_insn(cf,&insn); // executing configuration */ #ifdef _DEBUG_ @@ -88,147 +88,136 @@ #define INLINE static __inline #endif -///////////////////////////////////////////////////// #include #define S626_SIZE 0x0200 #define SIZEOF_ADDRESS_SPACE 0x0200 -#define DMABUF_SIZE 4096 // 4k pages +#define DMABUF_SIZE 4096 /* 4k pages */ #define S626_ADC_CHANNELS 16 #define S626_DAC_CHANNELS 4 #define S626_ENCODER_CHANNELS 6 #define S626_DIO_CHANNELS 48 -#define S626_DIO_BANKS 3 // Number of DIO groups. -#define S626_DIO_EXTCHANS 40 // Number of - // extended-capability - // DIO channels. +#define S626_DIO_BANKS 3 /* Number of DIO groups. */ +#define S626_DIO_EXTCHANS 40 /* Number of */ + /* extended-capability */ + /* DIO channels. */ -#define NUM_TRIMDACS 12 // Number of valid TrimDAC channels. +#define NUM_TRIMDACS 12 /* Number of valid TrimDAC channels. */ -// PCI bus interface types. -#define INTEL 1 // Intel bus type. -#define MOTOROLA 2 // Motorola bus type. +/* PCI bus interface types. */ +#define INTEL 1 /* Intel bus type. */ +#define MOTOROLA 2 /* Motorola bus type. */ -////////////////////////////////////////////////////////// +#define PLATFORM INTEL /* *** SELECT PLATFORM TYPE *** */ -////////////////////////////////////////////////////////// -#define PLATFORM INTEL // *** SELECT PLATFORM TYPE *** -////////////////////////////////////////////////////////// +#define RANGE_5V 0x10 /* +/-5V range */ +#define RANGE_10V 0x00 /* +/-10V range */ -#define RANGE_5V 0x10 // +/-5V range -#define RANGE_10V 0x00 // +/-10V range +#define EOPL 0x80 /* End of ADC poll list marker. */ +#define GSEL_BIPOLAR5V 0x00F0 /* LP_GSEL setting for 5V bipolar range. */ +#define GSEL_BIPOLAR10V 0x00A0 /* LP_GSEL setting for 10V bipolar range. */ -#define EOPL 0x80 // End of ADC poll list marker. -#define GSEL_BIPOLAR5V 0x00F0 // LP_GSEL setting for 5V bipolar range. -#define GSEL_BIPOLAR10V 0x00A0 // LP_GSEL setting for 10V bipolar range. +/* Error codes that must be visible to this base class. */ +#define ERR_ILLEGAL_PARM 0x00010000 /* Illegal function parameter value was specified. */ +#define ERR_I2C 0x00020000 /* I2C error. */ +#define ERR_COUNTERSETUP 0x00200000 /* Illegal setup specified for counter channel. */ +#define ERR_DEBI_TIMEOUT 0x00400000 /* DEBI transfer timed out. */ -// Error codes that must be visible to this base class. -#define ERR_ILLEGAL_PARM 0x00010000 // Illegal function parameter value was specified. -#define ERR_I2C 0x00020000 // I2C error. -#define ERR_COUNTERSETUP 0x00200000 // Illegal setup specified for counter channel. -#define ERR_DEBI_TIMEOUT 0x00400000 // DEBI transfer timed out. +/* Organization (physical order) and size (in DWORDs) of logical DMA buffers contained by ANA_DMABUF. */ +#define ADC_DMABUF_DWORDS 40 /* ADC DMA buffer must hold 16 samples, plus pre/post garbage samples. */ +#define DAC_WDMABUF_DWORDS 1 /* DAC output DMA buffer holds a single sample. */ -// Organization (physical order) and size (in DWORDs) of logical DMA buffers contained by ANA_DMABUF. -#define ADC_DMABUF_DWORDS 40 // ADC DMA buffer must hold 16 samples, plus pre/post garbage samples. -#define DAC_WDMABUF_DWORDS 1 // DAC output DMA buffer holds a single sample. +/* All remaining space in 4KB DMA buffer is available for the RPS1 program. */ -// All remaining space in 4KB DMA buffer is available for the RPS1 program. - -// Address offsets, in DWORDS, from base of DMA buffer. +/* Address offsets, in DWORDS, from base of DMA buffer. */ #define DAC_WDMABUF_OS ADC_DMABUF_DWORDS -// Interrupt enab bit in ISR and IER. -#define IRQ_GPIO3 0x00000040 // IRQ enable for GPIO3. +/* Interrupt enab bit in ISR and IER. */ +#define IRQ_GPIO3 0x00000040 /* IRQ enable for GPIO3. */ #define IRQ_RPS1 0x10000000 -#define ISR_AFOU 0x00000800 // Audio fifo - // under/overflow - // detected. -#define IRQ_COINT1A 0x0400 // conter 1A overflow - // interrupt mask -#define IRQ_COINT1B 0x0800 // conter 1B overflow - // interrupt mask -#define IRQ_COINT2A 0x1000 // conter 2A overflow - // interrupt mask -#define IRQ_COINT2B 0x2000 // conter 2B overflow - // interrupt mask -#define IRQ_COINT3A 0x4000 // conter 3A overflow - // interrupt mask -#define IRQ_COINT3B 0x8000 // conter 3B overflow - // interrupt mask +#define ISR_AFOU 0x00000800 +/* Audio fifo under/overflow detected. */ -// RPS command codes. -#define RPS_CLRSIGNAL 0x00000000 // CLEAR SIGNAL -#define RPS_SETSIGNAL 0x10000000 // SET SIGNAL -#define RPS_NOP 0x00000000 // NOP -#define RPS_PAUSE 0x20000000 // PAUSE -#define RPS_UPLOAD 0x40000000 // UPLOAD -#define RPS_JUMP 0x80000000 // JUMP -#define RPS_LDREG 0x90000100 // LDREG (1 uint32_t only) -#define RPS_STREG 0xA0000100 // STREG (1 uint32_t only) -#define RPS_STOP 0x50000000 // STOP -#define RPS_IRQ 0x60000000 // IRQ +#define IRQ_COINT1A 0x0400 /* conter 1A overflow interrupt mask */ +#define IRQ_COINT1B 0x0800 /* conter 1B overflow interrupt mask */ +#define IRQ_COINT2A 0x1000 /* conter 2A overflow interrupt mask */ +#define IRQ_COINT2B 0x2000 /* conter 2B overflow interrupt mask */ +#define IRQ_COINT3A 0x4000 /* conter 3A overflow interrupt mask */ +#define IRQ_COINT3B 0x8000 /* conter 3B overflow interrupt mask */ -#define RPS_LOGICAL_OR 0x08000000 // Logical OR conditionals. -#define RPS_INVERT 0x04000000 // Test for negated semaphores. -#define RPS_DEBI 0x00000002 // DEBI done +/* RPS command codes. */ +#define RPS_CLRSIGNAL 0x00000000 /* CLEAR SIGNAL */ +#define RPS_SETSIGNAL 0x10000000 /* SET SIGNAL */ +#define RPS_NOP 0x00000000 /* NOP */ +#define RPS_PAUSE 0x20000000 /* PAUSE */ +#define RPS_UPLOAD 0x40000000 /* UPLOAD */ +#define RPS_JUMP 0x80000000 /* JUMP */ +#define RPS_LDREG 0x90000100 /* LDREG (1 uint32_t only) */ +#define RPS_STREG 0xA0000100 /* STREG (1 uint32_t only) */ +#define RPS_STOP 0x50000000 /* STOP */ +#define RPS_IRQ 0x60000000 /* IRQ */ -#define RPS_SIG0 0x00200000 // RPS semaphore 0 (used by ADC). -#define RPS_SIG1 0x00400000 // RPS semaphore 1 (used by DAC). -#define RPS_SIG2 0x00800000 // RPS semaphore 2 (not used). -#define RPS_GPIO2 0x00080000 // RPS GPIO2 -#define RPS_GPIO3 0x00100000 // RPS GPIO3 +#define RPS_LOGICAL_OR 0x08000000 /* Logical OR conditionals. */ +#define RPS_INVERT 0x04000000 /* Test for negated semaphores. */ +#define RPS_DEBI 0x00000002 /* DEBI done */ -#define RPS_SIGADC RPS_SIG0 // Trigger/status for ADC's RPS program. -#define RPS_SIGDAC RPS_SIG1 // Trigger/status for DAC's RPS program. +#define RPS_SIG0 0x00200000 /* RPS semaphore 0 (used by ADC). */ +#define RPS_SIG1 0x00400000 /* RPS semaphore 1 (used by DAC). */ +#define RPS_SIG2 0x00800000 /* RPS semaphore 2 (not used). */ +#define RPS_GPIO2 0x00080000 /* RPS GPIO2 */ +#define RPS_GPIO3 0x00100000 /* RPS GPIO3 */ -// RPS clock parameters. -#define RPSCLK_SCALAR 8 // This is apparent ratio of PCI/RPS clks (undocumented!!). -#define RPSCLK_PER_US ( 33 / RPSCLK_SCALAR ) // Number of RPS clocks in one microsecond. +#define RPS_SIGADC RPS_SIG0 /* Trigger/status for ADC's RPS program. */ +#define RPS_SIGDAC RPS_SIG1 /* Trigger/status for DAC's RPS program. */ -// Event counter source addresses. -#define SBA_RPS_A0 0x27 // Time of RPS0 busy, in PCI clocks. +/* RPS clock parameters. */ +#define RPSCLK_SCALAR 8 /* This is apparent ratio of PCI/RPS clks (undocumented!!). */ +#define RPSCLK_PER_US (33 / RPSCLK_SCALAR) /* Number of RPS clocks in one microsecond. */ -// GPIO constants. -#define GPIO_BASE 0x10004000 // GPIO 0,2,3 = inputs, GPIO3 = IRQ; GPIO1 = out. -#define GPIO1_LO 0x00000000 // GPIO1 set to LOW. -#define GPIO1_HI 0x00001000 // GPIO1 set to HIGH. +/* Event counter source addresses. */ +#define SBA_RPS_A0 0x27 /* Time of RPS0 busy, in PCI clocks. */ -// Primary Status Register (PSR) constants. -#define PSR_DEBI_E 0x00040000 // DEBI event flag. -#define PSR_DEBI_S 0x00080000 // DEBI status flag. -#define PSR_A2_IN 0x00008000 // Audio output DMA2 protection address reached. -#define PSR_AFOU 0x00000800 // Audio FIFO under/overflow detected. -#define PSR_GPIO2 0x00000020 // GPIO2 input pin: 0=AdcBusy, 1=AdcIdle. -#define PSR_EC0S 0x00000001 // Event counter 0 threshold reached. +/* GPIO constants. */ +#define GPIO_BASE 0x10004000 /* GPIO 0,2,3 = inputs, GPIO3 = IRQ; GPIO1 = out. */ +#define GPIO1_LO 0x00000000 /* GPIO1 set to LOW. */ +#define GPIO1_HI 0x00001000 /* GPIO1 set to HIGH. */ -// Secondary Status Register (SSR) constants. -#define SSR_AF2_OUT 0x00000200 // Audio 2 output FIFO under/overflow detected. +/* Primary Status Register (PSR) constants. */ +#define PSR_DEBI_E 0x00040000 /* DEBI event flag. */ +#define PSR_DEBI_S 0x00080000 /* DEBI status flag. */ +#define PSR_A2_IN 0x00008000 /* Audio output DMA2 protection address reached. */ +#define PSR_AFOU 0x00000800 /* Audio FIFO under/overflow detected. */ +#define PSR_GPIO2 0x00000020 /* GPIO2 input pin: 0=AdcBusy, 1=AdcIdle. */ +#define PSR_EC0S 0x00000001 /* Event counter 0 threshold reached. */ -// Master Control Register 1 (MC1) constants. -#define MC1_SOFT_RESET 0x80000000 // Invoke 7146 soft reset. -#define MC1_SHUTDOWN 0x3FFF0000 // Shut down all MC1-controlled enables. +/* Secondary Status Register (SSR) constants. */ +#define SSR_AF2_OUT 0x00000200 /* Audio 2 output FIFO under/overflow detected. */ -#define MC1_ERPS1 0x2000 // enab/disable RPS task 1. -#define MC1_ERPS0 0x1000 // enab/disable RPS task 0. -#define MC1_DEBI 0x0800 // enab/disable DEBI pins. -#define MC1_AUDIO 0x0200 // enab/disable audio port pins. -#define MC1_I2C 0x0100 // enab/disable I2C interface. -#define MC1_A2OUT 0x0008 // enab/disable transfer on A2 out. -#define MC1_A2IN 0x0004 // enab/disable transfer on A2 in. -#define MC1_A1IN 0x0001 // enab/disable transfer on A1 in. +/* Master Control Register 1 (MC1) constants. */ +#define MC1_SOFT_RESET 0x80000000 /* Invoke 7146 soft reset. */ +#define MC1_SHUTDOWN 0x3FFF0000 /* Shut down all MC1-controlled enables. */ -// Master Control Register 2 (MC2) constants. -#define MC2_UPLD_DEBIq 0x00020002 // Upload DEBI registers. -#define MC2_UPLD_IICq 0x00010001 // Upload I2C registers. -#define MC2_RPSSIG2_ONq 0x20002000 // Assert RPS_SIG2. -#define MC2_RPSSIG1_ONq 0x10001000 // Assert RPS_SIG1. -#define MC2_RPSSIG0_ONq 0x08000800 // Assert RPS_SIG0. -#define MC2_UPLD_DEBI_MASKq 0x00000002 // Upload DEBI mask. -#define MC2_UPLD_IIC_MASKq 0x00000001 // Upload I2C mask. -#define MC2_RPSSIG2_MASKq 0x00002000 // RPS_SIG2 bit mask. -#define MC2_RPSSIG1_MASKq 0x00001000 // RPS_SIG1 bit mask. -#define MC2_RPSSIG0_MASKq 0x00000800 // RPS_SIG0 bit mask. +#define MC1_ERPS1 0x2000 /* enab/disable RPS task 1. */ +#define MC1_ERPS0 0x1000 /* enab/disable RPS task 0. */ +#define MC1_DEBI 0x0800 /* enab/disable DEBI pins. */ +#define MC1_AUDIO 0x0200 /* enab/disable audio port pins. */ +#define MC1_I2C 0x0100 /* enab/disable I2C interface. */ +#define MC1_A2OUT 0x0008 /* enab/disable transfer on A2 out. */ +#define MC1_A2IN 0x0004 /* enab/disable transfer on A2 in. */ +#define MC1_A1IN 0x0001 /* enab/disable transfer on A1 in. */ + +/* Master Control Register 2 (MC2) constants. */ +#define MC2_UPLD_DEBIq 0x00020002 /* Upload DEBI registers. */ +#define MC2_UPLD_IICq 0x00010001 /* Upload I2C registers. */ +#define MC2_RPSSIG2_ONq 0x20002000 /* Assert RPS_SIG2. */ +#define MC2_RPSSIG1_ONq 0x10001000 /* Assert RPS_SIG1. */ +#define MC2_RPSSIG0_ONq 0x08000800 /* Assert RPS_SIG0. */ +#define MC2_UPLD_DEBI_MASKq 0x00000002 /* Upload DEBI mask. */ +#define MC2_UPLD_IIC_MASKq 0x00000001 /* Upload I2C mask. */ +#define MC2_RPSSIG2_MASKq 0x00002000 /* RPS_SIG2 bit mask. */ +#define MC2_RPSSIG1_MASKq 0x00001000 /* RPS_SIG1 bit mask. */ +#define MC2_RPSSIG0_MASKq 0x00000800 /* RPS_SIG0 bit mask. */ #define MC2_DELAYTRIG_4USq MC2_RPSSIG1_ON #define MC2_DELAYBUSY_4USq MC2_RPSSIG1_MASK @@ -236,469 +225,425 @@ #define MC2_DELAYTRIG_6USq MC2_RPSSIG2_ON #define MC2_DELAYBUSY_6USq MC2_RPSSIG2_MASK -#define MC2_UPLD_DEBI 0x0002 // Upload DEBI. -#define MC2_UPLD_IIC 0x0001 // Upload I2C. -#define MC2_RPSSIG2 0x2000 // RPS signal 2 (not used). -#define MC2_RPSSIG1 0x1000 // RPS signal 1 (DAC RPS busy). -#define MC2_RPSSIG0 0x0800 // RPS signal 0 (ADC RPS busy). +#define MC2_UPLD_DEBI 0x0002 /* Upload DEBI. */ +#define MC2_UPLD_IIC 0x0001 /* Upload I2C. */ +#define MC2_RPSSIG2 0x2000 /* RPS signal 2 (not used). */ +#define MC2_RPSSIG1 0x1000 /* RPS signal 1 (DAC RPS busy). */ +#define MC2_RPSSIG0 0x0800 /* RPS signal 0 (ADC RPS busy). */ -#define MC2_ADC_RPS MC2_RPSSIG0 // ADC RPS busy. -#define MC2_DAC_RPS MC2_RPSSIG1 // DAC RPS busy. +#define MC2_ADC_RPS MC2_RPSSIG0 /* ADC RPS busy. */ +#define MC2_DAC_RPS MC2_RPSSIG1 /* DAC RPS busy. */ -///////////////////oldies/////////// -#define MC2_UPLD_DEBIQ 0x00020002 // Upload DEBI registers. -#define MC2_UPLD_IICQ 0x00010001 // Upload I2C registers. -//////////////////////////////////////// +/* ***** oldies ***** */ +#define MC2_UPLD_DEBIQ 0x00020002 /* Upload DEBI registers. */ +#define MC2_UPLD_IICQ 0x00010001 /* Upload I2C registers. */ -// PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS //////////////////////// -#define P_PCI_BT_A 0x004C // Audio DMA - // burst/threshold - // control. -#define P_DEBICFG 0x007C // DEBI configuration. -#define P_DEBICMD 0x0080 // DEBI command. -#define P_DEBIPAGE 0x0084 // DEBI page. -#define P_DEBIAD 0x0088 // DEBI target address. -#define P_I2CCTRL 0x008C // I2C control. -#define P_I2CSTAT 0x0090 // I2C status. -#define P_BASEA2_IN 0x00AC // Audio input 2 base - // physical DMAbuf - // address. -#define P_PROTA2_IN 0x00B0 // Audio input 2 - // physical DMAbuf - // protection address. -#define P_PAGEA2_IN 0x00B4 // Audio input 2 - // paging attributes. -#define P_BASEA2_OUT 0x00B8 // Audio output 2 base - // physical DMAbuf - // address. -#define P_PROTA2_OUT 0x00BC // Audio output 2 - // physical DMAbuf - // protection address. -#define P_PAGEA2_OUT 0x00C0 // Audio output 2 - // paging attributes. -#define P_RPSPAGE0 0x00C4 // RPS0 page. -#define P_RPSPAGE1 0x00C8 // RPS1 page. -#define P_RPS0_TOUT 0x00D4 // RPS0 time-out. -#define P_RPS1_TOUT 0x00D8 // RPS1 time-out. -#define P_IER 0x00DC // Interrupt enable. -#define P_GPIO 0x00E0 // General-purpose I/O. -#define P_EC1SSR 0x00E4 // Event counter set 1 - // source select. -#define P_ECT1R 0x00EC // Event counter - // threshold set 1. -#define P_ACON1 0x00F4 // Audio control 1. -#define P_ACON2 0x00F8 // Audio control 2. -#define P_MC1 0x00FC // Master control 1. -#define P_MC2 0x0100 // Master control 2. -#define P_RPSADDR0 0x0104 // RPS0 instruction pointer. -#define P_RPSADDR1 0x0108 // RPS1 instruction pointer. -#define P_ISR 0x010C // Interrupt status. -#define P_PSR 0x0110 // Primary status. -#define P_SSR 0x0114 // Secondary status. -#define P_EC1R 0x0118 // Event counter set 1. -#define P_ADP4 0x0138 // Logical audio DMA - // pointer of audio - // input FIFO A2_IN. -#define P_FB_BUFFER1 0x0144 // Audio feedback buffer 1. -#define P_FB_BUFFER2 0x0148 // Audio feedback buffer 2. -#define P_TSL1 0x0180 // Audio time slot list 1. -#define P_TSL2 0x01C0 // Audio time slot list 2. +/* PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS */ +#define P_PCI_BT_A 0x004C /* Audio DMA burst/threshold control. */ +#define P_DEBICFG 0x007C /* DEBI configuration. */ +#define P_DEBICMD 0x0080 /* DEBI command. */ +#define P_DEBIPAGE 0x0084 /* DEBI page. */ +#define P_DEBIAD 0x0088 /* DEBI target address. */ +#define P_I2CCTRL 0x008C /* I2C control. */ +#define P_I2CSTAT 0x0090 /* I2C status. */ +#define P_BASEA2_IN 0x00AC /* Audio input 2 base physical DMAbuf + * address. */ +#define P_PROTA2_IN 0x00B0 /* Audio input 2 physical DMAbuf + * protection address. */ +#define P_PAGEA2_IN 0x00B4 /* Audio input 2 paging attributes. */ +#define P_BASEA2_OUT 0x00B8 /* Audio output 2 base physical DMAbuf + * address. */ +#define P_PROTA2_OUT 0x00BC /* Audio output 2 physical DMAbuf + * protection address. */ +#define P_PAGEA2_OUT 0x00C0 /* Audio output 2 paging attributes. */ +#define P_RPSPAGE0 0x00C4 /* RPS0 page. */ +#define P_RPSPAGE1 0x00C8 /* RPS1 page. */ +#define P_RPS0_TOUT 0x00D4 /* RPS0 time-out. */ +#define P_RPS1_TOUT 0x00D8 /* RPS1 time-out. */ +#define P_IER 0x00DC /* Interrupt enable. */ +#define P_GPIO 0x00E0 /* General-purpose I/O. */ +#define P_EC1SSR 0x00E4 /* Event counter set 1 source select. */ +#define P_ECT1R 0x00EC /* Event counter threshold set 1. */ +#define P_ACON1 0x00F4 /* Audio control 1. */ +#define P_ACON2 0x00F8 /* Audio control 2. */ +#define P_MC1 0x00FC /* Master control 1. */ +#define P_MC2 0x0100 /* Master control 2. */ +#define P_RPSADDR0 0x0104 /* RPS0 instruction pointer. */ +#define P_RPSADDR1 0x0108 /* RPS1 instruction pointer. */ +#define P_ISR 0x010C /* Interrupt status. */ +#define P_PSR 0x0110 /* Primary status. */ +#define P_SSR 0x0114 /* Secondary status. */ +#define P_EC1R 0x0118 /* Event counter set 1. */ +#define P_ADP4 0x0138 /* Logical audio DMA pointer of audio + * input FIFO A2_IN. */ +#define P_FB_BUFFER1 0x0144 /* Audio feedback buffer 1. */ +#define P_FB_BUFFER2 0x0148 /* Audio feedback buffer 2. */ +#define P_TSL1 0x0180 /* Audio time slot list 1. */ +#define P_TSL2 0x01C0 /* Audio time slot list 2. */ -// LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS ///////////////// -// Analog I/O registers: -#define LP_DACPOL 0x0082 // Write DAC polarity. -#define LP_GSEL 0x0084 // Write ADC gain. -#define LP_ISEL 0x0086 // Write ADC channel select. -// Digital I/O (write only): -#define LP_WRINTSELA 0x0042 // Write A interrupt enable. -#define LP_WREDGSELA 0x0044 // Write A edge selection. -#define LP_WRCAPSELA 0x0046 // Write A capture enable. -#define LP_WRDOUTA 0x0048 // Write A digital output. -#define LP_WRINTSELB 0x0052 // Write B interrupt enable. -#define LP_WREDGSELB 0x0054 // Write B edge selection. -#define LP_WRCAPSELB 0x0056 // Write B capture enable. -#define LP_WRDOUTB 0x0058 // Write B digital output. -#define LP_WRINTSELC 0x0062 // Write C interrupt enable. -#define LP_WREDGSELC 0x0064 // Write C edge selection. -#define LP_WRCAPSELC 0x0066 // Write C capture enable. -#define LP_WRDOUTC 0x0068 // Write C digital output. +/* LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS */ +/* Analog I/O registers: */ +#define LP_DACPOL 0x0082 /* Write DAC polarity. */ +#define LP_GSEL 0x0084 /* Write ADC gain. */ +#define LP_ISEL 0x0086 /* Write ADC channel select. */ +/* Digital I/O (write only): */ +#define LP_WRINTSELA 0x0042 /* Write A interrupt enable. */ +#define LP_WREDGSELA 0x0044 /* Write A edge selection. */ +#define LP_WRCAPSELA 0x0046 /* Write A capture enable. */ +#define LP_WRDOUTA 0x0048 /* Write A digital output. */ +#define LP_WRINTSELB 0x0052 /* Write B interrupt enable. */ +#define LP_WREDGSELB 0x0054 /* Write B edge selection. */ +#define LP_WRCAPSELB 0x0056 /* Write B capture enable. */ +#define LP_WRDOUTB 0x0058 /* Write B digital output. */ +#define LP_WRINTSELC 0x0062 /* Write C interrupt enable. */ +#define LP_WREDGSELC 0x0064 /* Write C edge selection. */ +#define LP_WRCAPSELC 0x0066 /* Write C capture enable. */ +#define LP_WRDOUTC 0x0068 /* Write C digital output. */ -// Digital I/O (read only): -#define LP_RDDINA 0x0040 // Read digital input. -#define LP_RDCAPFLGA 0x0048 // Read edges captured. -#define LP_RDINTSELA 0x004A // Read interrupt - // enable register. -#define LP_RDEDGSELA 0x004C // Read edge - // selection - // register. -#define LP_RDCAPSELA 0x004E // Read capture - // enable register. -#define LP_RDDINB 0x0050 // Read digital input. -#define LP_RDCAPFLGB 0x0058 // Read edges captured. -#define LP_RDINTSELB 0x005A // Read interrupt - // enable register. -#define LP_RDEDGSELB 0x005C // Read edge - // selection - // register. -#define LP_RDCAPSELB 0x005E // Read capture - // enable register. -#define LP_RDDINC 0x0060 // Read digital input. -#define LP_RDCAPFLGC 0x0068 // Read edges captured. -#define LP_RDINTSELC 0x006A // Read interrupt - // enable register. -#define LP_RDEDGSELC 0x006C // Read edge - // selection - // register. -#define LP_RDCAPSELC 0x006E // Read capture - // enable register. -// Counter Registers (read/write): -#define LP_CR0A 0x0000 // 0A setup register. -#define LP_CR0B 0x0002 // 0B setup register. -#define LP_CR1A 0x0004 // 1A setup register. -#define LP_CR1B 0x0006 // 1B setup register. -#define LP_CR2A 0x0008 // 2A setup register. -#define LP_CR2B 0x000A // 2B setup register. -// Counter PreLoad (write) and Latch (read) Registers: -#define LP_CNTR0ALSW 0x000C // 0A lsw. -#define LP_CNTR0AMSW 0x000E // 0A msw. -#define LP_CNTR0BLSW 0x0010 // 0B lsw. -#define LP_CNTR0BMSW 0x0012 // 0B msw. -#define LP_CNTR1ALSW 0x0014 // 1A lsw. -#define LP_CNTR1AMSW 0x0016 // 1A msw. -#define LP_CNTR1BLSW 0x0018 // 1B lsw. -#define LP_CNTR1BMSW 0x001A // 1B msw. -#define LP_CNTR2ALSW 0x001C // 2A lsw. -#define LP_CNTR2AMSW 0x001E // 2A msw. -#define LP_CNTR2BLSW 0x0020 // 2B lsw. -#define LP_CNTR2BMSW 0x0022 // 2B msw. -// Miscellaneous Registers (read/write): -#define LP_MISC1 0x0088 // Read/write Misc1. -#define LP_WRMISC2 0x0090 // Write Misc2. -#define LP_RDMISC2 0x0082 // Read Misc2. +/* Digital I/O (read only): */ +#define LP_RDDINA 0x0040 /* Read digital input. */ +#define LP_RDCAPFLGA 0x0048 /* Read edges captured. */ +#define LP_RDINTSELA 0x004A /* Read interrupt enable register. */ +#define LP_RDEDGSELA 0x004C /* Read edge selection register. */ +#define LP_RDCAPSELA 0x004E /* Read capture enable register. */ +#define LP_RDDINB 0x0050 /* Read digital input. */ +#define LP_RDCAPFLGB 0x0058 /* Read edges captured. */ +#define LP_RDINTSELB 0x005A /* Read interrupt enable register. */ +#define LP_RDEDGSELB 0x005C /* Read edge selection register. */ +#define LP_RDCAPSELB 0x005E /* Read capture enable register. */ +#define LP_RDDINC 0x0060 /* Read digital input. */ +#define LP_RDCAPFLGC 0x0068 /* Read edges captured. */ +#define LP_RDINTSELC 0x006A /* Read interrupt enable register. */ +#define LP_RDEDGSELC 0x006C /* Read edge selection register. */ +#define LP_RDCAPSELC 0x006E /* Read capture enable register. */ -// Bit masks for MISC1 register that are the same for reads and writes. -#define MISC1_WENABLE 0x8000 // enab writes to - // MISC2 (except Clear - // Watchdog bit). -#define MISC1_WDISABLE 0x0000 // Disable writes to MISC2. -#define MISC1_EDCAP 0x1000 // enab edge capture - // on DIO chans - // specified by - // LP_WRCAPSELx. -#define MISC1_NOEDCAP 0x0000 // Disable edge - // capture on - // specified DIO - // chans. +/* Counter Registers (read/write): */ +#define LP_CR0A 0x0000 /* 0A setup register. */ +#define LP_CR0B 0x0002 /* 0B setup register. */ +#define LP_CR1A 0x0004 /* 1A setup register. */ +#define LP_CR1B 0x0006 /* 1B setup register. */ +#define LP_CR2A 0x0008 /* 2A setup register. */ +#define LP_CR2B 0x000A /* 2B setup register. */ -// Bit masks for MISC1 register reads. -#define RDMISC1_WDTIMEOUT 0x4000 // Watchdog timer timed out. +/* Counter PreLoad (write) and Latch (read) Registers: */ +#define LP_CNTR0ALSW 0x000C /* 0A lsw. */ +#define LP_CNTR0AMSW 0x000E /* 0A msw. */ +#define LP_CNTR0BLSW 0x0010 /* 0B lsw. */ +#define LP_CNTR0BMSW 0x0012 /* 0B msw. */ +#define LP_CNTR1ALSW 0x0014 /* 1A lsw. */ +#define LP_CNTR1AMSW 0x0016 /* 1A msw. */ +#define LP_CNTR1BLSW 0x0018 /* 1B lsw. */ +#define LP_CNTR1BMSW 0x001A /* 1B msw. */ +#define LP_CNTR2ALSW 0x001C /* 2A lsw. */ +#define LP_CNTR2AMSW 0x001E /* 2A msw. */ +#define LP_CNTR2BLSW 0x0020 /* 2B lsw. */ +#define LP_CNTR2BMSW 0x0022 /* 2B msw. */ -// Bit masks for MISC2 register writes. -#define WRMISC2_WDCLEAR 0x8000 // Reset watchdog - // timer to zero. -#define WRMISC2_CHARGE_ENABLE 0x4000 // enab battery - // trickle charging. +/* Miscellaneous Registers (read/write): */ +#define LP_MISC1 0x0088 /* Read/write Misc1. */ +#define LP_WRMISC2 0x0090 /* Write Misc2. */ +#define LP_RDMISC2 0x0082 /* Read Misc2. */ -// Bit masks for MISC2 register that are the same for reads and writes. -#define MISC2_BATT_ENABLE 0x0008 // Backup battery enable. -#define MISC2_WDENABLE 0x0004 // Watchdog timer enable. -#define MISC2_WDPERIOD_MASK 0x0003 // Watchdog interval - // select mask. +/* Bit masks for MISC1 register that are the same for reads and writes. */ +#define MISC1_WENABLE 0x8000 /* enab writes to MISC2 (except Clear + * Watchdog bit). */ +#define MISC1_WDISABLE 0x0000 /* Disable writes to MISC2. */ +#define MISC1_EDCAP 0x1000 /* enab edge capture on DIO chans + * specified by LP_WRCAPSELx. */ +#define MISC1_NOEDCAP 0x0000 /* Disable edge capture on specified + * DIO chans. */ -// Bit masks for ACON1 register. -#define A2_RUN 0x40000000 // Run A2 based on TSL2. -#define A1_RUN 0x20000000 // Run A1 based on TSL1. -#define A1_SWAP 0x00200000 // Use big-endian for A1. -#define A2_SWAP 0x00100000 // Use big-endian for A2. -#define WS_MODES 0x00019999 // WS0 = TSL1 trigger - // input, WS1-WS4 = - // CS* outputs. +/* Bit masks for MISC1 register reads. */ +#define RDMISC1_WDTIMEOUT 0x4000 /* Watchdog timer timed out. */ -#if PLATFORM == INTEL // Base ACON1 config: - // always run A1 based - // on TSL1. -#define ACON1_BASE ( WS_MODES | A1_RUN ) +/* Bit masks for MISC2 register writes. */ +#define WRMISC2_WDCLEAR 0x8000 /* Reset watchdog timer to zero. */ +#define WRMISC2_CHARGE_ENABLE 0x4000 /* enab battery trickle charging. */ + +/* Bit masks for MISC2 register that are the same for reads and writes. */ +#define MISC2_BATT_ENABLE 0x0008 /* Backup battery enable. */ +#define MISC2_WDENABLE 0x0004 /* Watchdog timer enable. */ +#define MISC2_WDPERIOD_MASK 0x0003 /* Watchdog interval */ + /* select mask. */ + +/* Bit masks for ACON1 register. */ +#define A2_RUN 0x40000000 /* Run A2 based on TSL2. */ +#define A1_RUN 0x20000000 /* Run A1 based on TSL1. */ +#define A1_SWAP 0x00200000 /* Use big-endian for A1. */ +#define A2_SWAP 0x00100000 /* Use big-endian for A2. */ +#define WS_MODES 0x00019999 /* WS0 = TSL1 trigger */ + /* input, WS1-WS4 = */ + /* CS* outputs. */ + +#if PLATFORM == INTEL /* Base ACON1 config: always run A1 based + * on TSL1. */ +#define ACON1_BASE (WS_MODES | A1_RUN) #elif PLATFORM == MOTOROLA -#define ACON1_BASE ( WS_MODES | A1_RUN | A1_SWAP | A2_SWAP ) +#define ACON1_BASE (WS_MODES | A1_RUN | A1_SWAP | A2_SWAP) #endif -#define ACON1_ADCSTART ACON1_BASE // Start ADC: run A1 - // based on TSL1. -#define ACON1_DACSTART ( ACON1_BASE | A2_RUN ) // Start - // transmit to - // DAC: run A2 - // based on - // TSL2. -#define ACON1_DACSTOP ACON1_BASE // Halt A2. +#define ACON1_ADCSTART ACON1_BASE /* Start ADC: run A1 + * based on TSL1. */ +#define ACON1_DACSTART (ACON1_BASE | A2_RUN) +/* Start transmit to DAC: run A2 based on TSL2. */ +#define ACON1_DACSTOP ACON1_BASE /* Halt A2. */ -// Bit masks for ACON2 register. -#define A1_CLKSRC_BCLK1 0x00000000 // A1 bit rate = BCLK1 (ADC). -#define A2_CLKSRC_X1 0x00800000 // A2 bit rate = ACLK/1 (DACs). -#define A2_CLKSRC_X2 0x00C00000 // A2 bit rate = ACLK/2 (DACs). -#define A2_CLKSRC_X4 0x01400000 // A2 bit rate = ACLK/4 (DACs). -#define INVERT_BCLK2 0x00100000 // Invert BCLK2 (DACs). -#define BCLK2_OE 0x00040000 // enab BCLK2 (DACs). -#define ACON2_XORMASK 0x000C0000 // XOR mask for ACON2 - // active-low bits. +/* Bit masks for ACON2 register. */ +#define A1_CLKSRC_BCLK1 0x00000000 /* A1 bit rate = BCLK1 (ADC). */ +#define A2_CLKSRC_X1 0x00800000 /* A2 bit rate = ACLK/1 (DACs). */ +#define A2_CLKSRC_X2 0x00C00000 /* A2 bit rate = ACLK/2 (DACs). */ +#define A2_CLKSRC_X4 0x01400000 /* A2 bit rate = ACLK/4 (DACs). */ +#define INVERT_BCLK2 0x00100000 /* Invert BCLK2 (DACs). */ +#define BCLK2_OE 0x00040000 /* enab BCLK2 (DACs). */ +#define ACON2_XORMASK 0x000C0000 /* XOR mask for ACON2 */ + /* active-low bits. */ -#define ACON2_INIT ( ACON2_XORMASK ^ ( A1_CLKSRC_BCLK1 | A2_CLKSRC_X2 | INVERT_BCLK2 | BCLK2_OE ) ) +#define ACON2_INIT (ACON2_XORMASK ^ (A1_CLKSRC_BCLK1 | A2_CLKSRC_X2 | INVERT_BCLK2 | BCLK2_OE)) -// Bit masks for timeslot records. -#define WS1 0x40000000 // WS output to assert. +/* Bit masks for timeslot records. */ +#define WS1 0x40000000 /* WS output to assert. */ #define WS2 0x20000000 #define WS3 0x10000000 #define WS4 0x08000000 -#define RSD1 0x01000000 // Shift A1 data in on SD1. -#define SDW_A1 0x00800000 // Store rcv'd char at - // next char slot of - // DWORD1 buffer. -#define SIB_A1 0x00400000 // Store rcv'd char at - // next char slot of - // FB1 buffer. -#define SF_A1 0x00200000 // Write unsigned long - // buffer to input - // FIFO. +#define RSD1 0x01000000 /* Shift A1 data in on SD1. */ +#define SDW_A1 0x00800000 /* Store rcv'd char at next + * char slot of DWORD1 buffer. */ +#define SIB_A1 0x00400000 /* Store rcv'd char at next + * char slot of FB1 buffer. */ +#define SF_A1 0x00200000 /* Write unsigned long + * buffer to input FIFO. */ -//Select parallel-to-serial converter's data source: -#define XFIFO_0 0x00000000 // Data fifo byte 0. -#define XFIFO_1 0x00000010 // Data fifo byte 1. -#define XFIFO_2 0x00000020 // Data fifo byte 2. -#define XFIFO_3 0x00000030 // Data fifo byte 3. -#define XFB0 0x00000040 // FB_BUFFER byte 0. -#define XFB1 0x00000050 // FB_BUFFER byte 1. -#define XFB2 0x00000060 // FB_BUFFER byte 2. -#define XFB3 0x00000070 // FB_BUFFER byte 3. -#define SIB_A2 0x00000200 // Store next dword - // from A2's input - // shifter to FB2 - // buffer. -#define SF_A2 0x00000100 // Store next dword - // from A2's input - // shifter to its - // input fifo. -#define LF_A2 0x00000080 // Load next dword - // from A2's output - // fifo into its - // output dword - // buffer. -#define XSD2 0x00000008 // Shift data out on SD2. -#define RSD3 0x00001800 // Shift data in on SD3. -#define RSD2 0x00001000 // Shift data in on SD2. -#define LOW_A2 0x00000002 // Drive last SD low - // for 7 clks, then - // tri-state. -#define EOS 0x00000001 // End of superframe. +/* Select parallel-to-serial converter's data source: */ +#define XFIFO_0 0x00000000 /* Data fifo byte 0. */ +#define XFIFO_1 0x00000010 /* Data fifo byte 1. */ +#define XFIFO_2 0x00000020 /* Data fifo byte 2. */ +#define XFIFO_3 0x00000030 /* Data fifo byte 3. */ +#define XFB0 0x00000040 /* FB_BUFFER byte 0. */ +#define XFB1 0x00000050 /* FB_BUFFER byte 1. */ +#define XFB2 0x00000060 /* FB_BUFFER byte 2. */ +#define XFB3 0x00000070 /* FB_BUFFER byte 3. */ +#define SIB_A2 0x00000200 /* Store next dword from A2's + * input shifter to FB2 buffer. */ +#define SF_A2 0x00000100 /* Store next dword from A2's + * input shifter to its input + * fifo. */ +#define LF_A2 0x00000080 /* Load next dword from A2's + * output fifo into its + * output dword buffer. */ +#define XSD2 0x00000008 /* Shift data out on SD2. */ +#define RSD3 0x00001800 /* Shift data in on SD3. */ +#define RSD2 0x00001000 /* Shift data in on SD2. */ +#define LOW_A2 0x00000002 /* Drive last SD low */ + /* for 7 clks, then */ + /* tri-state. */ +#define EOS 0x00000001 /* End of superframe. */ -////////////////////// -// I2C configuration constants. -#define I2C_CLKSEL 0x0400 // I2C bit rate = - // PCIclk/480 = 68.75 - // KHz. -#define I2C_BITRATE 68.75 // I2C bus data bit - // rate (determined by - // I2C_CLKSEL) in KHz. -#define I2C_WRTIME 15.0 // Worst case time,in - // msec, for EEPROM - // internal write op. +/* I2C configuration constants. */ +#define I2C_CLKSEL 0x0400 +/* I2C bit rate = PCIclk/480 = 68.75 KHz. */ -// I2C manifest constants. +#define I2C_BITRATE 68.75 +/* I2C bus data bit rate (determined by I2C_CLKSEL) in KHz. */ -// Max retries to wait for EEPROM write. -#define I2C_RETRIES ( I2C_WRTIME * I2C_BITRATE / 9.0 ) -#define I2C_ERR 0x0002 // I2C control/status - // flag ERROR. -#define I2C_BUSY 0x0001 // I2C control/status - // flag BUSY. -#define I2C_ABORT 0x0080 // I2C status flag ABORT. -#define I2C_ATTRSTART 0x3 // I2C attribute START. -#define I2C_ATTRCONT 0x2 // I2C attribute CONT. -#define I2C_ATTRSTOP 0x1 // I2C attribute STOP. -#define I2C_ATTRNOP 0x0 // I2C attribute NOP. +#define I2C_WRTIME 15.0 +/* Worst case time, in msec, for EEPROM internal write op. */ -// I2C read command | EEPROM address. -#define I2CR ( devpriv->I2CAdrs | 1 ) +/* I2C manifest constants. */ -// I2C write command | EEPROM address. -#define I2CW ( devpriv->I2CAdrs ) +/* Max retries to wait for EEPROM write. */ +#define I2C_RETRIES (I2C_WRTIME * I2C_BITRATE / 9.0) +#define I2C_ERR 0x0002 /* I2C control/status */ + /* flag ERROR. */ +#define I2C_BUSY 0x0001 /* I2C control/status */ + /* flag BUSY. */ +#define I2C_ABORT 0x0080 /* I2C status flag ABORT. */ +#define I2C_ATTRSTART 0x3 /* I2C attribute START. */ +#define I2C_ATTRCONT 0x2 /* I2C attribute CONT. */ +#define I2C_ATTRSTOP 0x1 /* I2C attribute STOP. */ +#define I2C_ATTRNOP 0x0 /* I2C attribute NOP. */ -// Code macros used for constructing I2C command bytes. -#define I2C_B2(ATTR,VAL) ( ( (ATTR) << 6 ) | ( (VAL) << 24 ) ) -#define I2C_B1(ATTR,VAL) ( ( (ATTR) << 4 ) | ( (VAL) << 16 ) ) -#define I2C_B0(ATTR,VAL) ( ( (ATTR) << 2 ) | ( (VAL) << 8 ) ) +/* I2C read command | EEPROM address. */ +#define I2CR (devpriv->I2CAdrs | 1) -//////////////////////////////////////////////////////// -//oldest -#define P_DEBICFGq 0x007C // DEBI configuration. -#define P_DEBICMDq 0x0080 // DEBI command. -#define P_DEBIPAGEq 0x0084 // DEBI page. -#define P_DEBIADq 0x0088 // DEBI target address. +/* I2C write command | EEPROM address. */ +#define I2CW (devpriv->I2CAdrs) -#define DEBI_CFG_TOQ 0x03C00000 // timeout (15 PCI cycles) -#define DEBI_CFG_FASTQ 0x10000000 // fast mode enable -#define DEBI_CFG_16Q 0x00080000 // 16-bit access enable -#define DEBI_CFG_INCQ 0x00040000 // enable address increment -#define DEBI_CFG_TIMEROFFQ 0x00010000 // disable timer -#define DEBI_CMD_RDQ 0x00050000 // read immediate 2 bytes -#define DEBI_CMD_WRQ 0x00040000 // write immediate 2 bytes -#define DEBI_PAGE_DISABLEQ 0x00000000 // paging disable +/* Code macros used for constructing I2C command bytes. */ +#define I2C_B2(ATTR, VAL) (((ATTR) << 6) | ((VAL) << 24)) +#define I2C_B1(ATTR, VAL) (((ATTR) << 4) | ((VAL) << 16)) +#define I2C_B0(ATTR, VAL) (((ATTR) << 2) | ((VAL) << 8)) -/////////////////////////////////////////// -// DEBI command constants. -#define DEBI_CMD_SIZE16 ( 2 << 17 ) // Transfer size is - // always 2 bytes. -#define DEBI_CMD_READ 0x00010000 // Read operation. -#define DEBI_CMD_WRITE 0x00000000 // Write operation. +/* oldest */ +#define P_DEBICFGq 0x007C /* DEBI configuration. */ +#define P_DEBICMDq 0x0080 /* DEBI command. */ +#define P_DEBIPAGEq 0x0084 /* DEBI page. */ +#define P_DEBIADq 0x0088 /* DEBI target address. */ -// Read immediate 2 bytes. -#define DEBI_CMD_RDWORD ( DEBI_CMD_READ | DEBI_CMD_SIZE16 ) +#define DEBI_CFG_TOQ 0x03C00000 /* timeout (15 PCI cycles) */ +#define DEBI_CFG_FASTQ 0x10000000 /* fast mode enable */ +#define DEBI_CFG_16Q 0x00080000 /* 16-bit access enable */ +#define DEBI_CFG_INCQ 0x00040000 /* enable address increment */ +#define DEBI_CFG_TIMEROFFQ 0x00010000 /* disable timer */ +#define DEBI_CMD_RDQ 0x00050000 /* read immediate 2 bytes */ +#define DEBI_CMD_WRQ 0x00040000 /* write immediate 2 bytes */ +#define DEBI_PAGE_DISABLEQ 0x00000000 /* paging disable */ -// Write immediate 2 bytes. -#define DEBI_CMD_WRWORD ( DEBI_CMD_WRITE | DEBI_CMD_SIZE16 ) +/* DEBI command constants. */ +#define DEBI_CMD_SIZE16 (2 << 17) /* Transfer size is */ + /* always 2 bytes. */ +#define DEBI_CMD_READ 0x00010000 /* Read operation. */ +#define DEBI_CMD_WRITE 0x00000000 /* Write operation. */ -// DEBI configuration constants. -#define DEBI_CFG_XIRQ_EN 0x80000000 // enab external - // interrupt on GPIO3. -#define DEBI_CFG_XRESUME 0x40000000 // Resume block - // transfer when XIRQ - // deasserted. -#define DEBI_CFG_FAST 0x10000000 // Fast mode enable. +/* Read immediate 2 bytes. */ +#define DEBI_CMD_RDWORD (DEBI_CMD_READ | DEBI_CMD_SIZE16) -// 4-bit field that specifies DEBI timeout value in PCI clock cycles: -#define DEBI_CFG_TOUT_BIT 22 // Finish DEBI cycle after - // this many clocks. +/* Write immediate 2 bytes. */ +#define DEBI_CMD_WRWORD (DEBI_CMD_WRITE | DEBI_CMD_SIZE16) -// 2-bit field that specifies Endian byte lane steering: -#define DEBI_CFG_SWAP_NONE 0x00000000 // Straight - don't - // swap any bytes - // (Intel). -#define DEBI_CFG_SWAP_2 0x00100000 // 2-byte swap (Motorola). -#define DEBI_CFG_SWAP_4 0x00200000 // 4-byte swap. -#define DEBI_CFG_16 0x00080000 // Slave is able to - // serve 16-bit - // cycles. +/* DEBI configuration constants. */ +#define DEBI_CFG_XIRQ_EN 0x80000000 /* enab external */ + /* interrupt on GPIO3. */ +#define DEBI_CFG_XRESUME 0x40000000 /* Resume block */ + /* transfer when XIRQ */ + /* deasserted. */ +#define DEBI_CFG_FAST 0x10000000 /* Fast mode enable. */ -#define DEBI_CFG_SLAVE16 0x00080000 // Slave is able to - // serve 16-bit - // cycles. -#define DEBI_CFG_INC 0x00040000 // enab address - // increment for block - // transfers. -#define DEBI_CFG_INTEL 0x00020000 // Intel style local bus. -#define DEBI_CFG_TIMEROFF 0x00010000 // Disable timer. +/* 4-bit field that specifies DEBI timeout value in PCI clock cycles: */ +#define DEBI_CFG_TOUT_BIT 22 /* Finish DEBI cycle after */ + /* this many clocks. */ + +/* 2-bit field that specifies Endian byte lane steering: */ +#define DEBI_CFG_SWAP_NONE 0x00000000 /* Straight - don't */ + /* swap any bytes */ + /* (Intel). */ +#define DEBI_CFG_SWAP_2 0x00100000 /* 2-byte swap (Motorola). */ +#define DEBI_CFG_SWAP_4 0x00200000 /* 4-byte swap. */ +#define DEBI_CFG_16 0x00080000 /* Slave is able to */ + /* serve 16-bit */ + /* cycles. */ + +#define DEBI_CFG_SLAVE16 0x00080000 /* Slave is able to */ + /* serve 16-bit */ + /* cycles. */ +#define DEBI_CFG_INC 0x00040000 /* enab address */ + /* increment for block */ + /* transfers. */ +#define DEBI_CFG_INTEL 0x00020000 /* Intel style local bus. */ +#define DEBI_CFG_TIMEROFF 0x00010000 /* Disable timer. */ #if PLATFORM == INTEL -#define DEBI_TOUT 7 // Wait 7 PCI clocks - // (212 ns) before - // polling RDY. +#define DEBI_TOUT 7 /* Wait 7 PCI clocks */ + /* (212 ns) before */ + /* polling RDY. */ -// Intel byte lane steering (pass through all byte lanes). +/* Intel byte lane steering (pass through all byte lanes). */ #define DEBI_SWAP DEBI_CFG_SWAP_NONE #elif PLATFORM == MOTOROLA -#define DEBI_TOUT 15 // Wait 15 PCI clocks (454 ns) - // maximum before timing out. -#define DEBI_SWAP DEBI_CFG_SWAP_2 // Motorola byte lane steering. +#define DEBI_TOUT 15 /* Wait 15 PCI clocks (454 ns) */ + /* maximum before timing out. */ +#define DEBI_SWAP DEBI_CFG_SWAP_2 /* Motorola byte lane steering. */ #endif -// DEBI page table constants. -#define DEBI_PAGE_DISABLE 0x00000000 // Paging disable. +/* DEBI page table constants. */ +#define DEBI_PAGE_DISABLE 0x00000000 /* Paging disable. */ -///////////////////EXTRA FROM OTHER SANSORAY * .h//////// +/* ******* EXTRA FROM OTHER SANSORAY * .h ******* */ -// LoadSrc values: -#define LOADSRC_INDX 0 // Preload core in response to - // Index. -#define LOADSRC_OVER 1 // Preload core in response to - // Overflow. -#define LOADSRCB_OVERA 2 // Preload B core in response - // to A Overflow. -#define LOADSRC_NONE 3 // Never preload core. +/* LoadSrc values: */ +#define LOADSRC_INDX 0 /* Preload core in response to */ + /* Index. */ +#define LOADSRC_OVER 1 /* Preload core in response to */ + /* Overflow. */ +#define LOADSRCB_OVERA 2 /* Preload B core in response */ + /* to A Overflow. */ +#define LOADSRC_NONE 3 /* Never preload core. */ -// IntSrc values: -#define INTSRC_NONE 0 // Interrupts disabled. -#define INTSRC_OVER 1 // Interrupt on Overflow. -#define INTSRC_INDX 2 // Interrupt on Index. -#define INTSRC_BOTH 3 // Interrupt on Index or Overflow. +/* IntSrc values: */ +#define INTSRC_NONE 0 /* Interrupts disabled. */ +#define INTSRC_OVER 1 /* Interrupt on Overflow. */ +#define INTSRC_INDX 2 /* Interrupt on Index. */ +#define INTSRC_BOTH 3 /* Interrupt on Index or Overflow. */ -// LatchSrc values: -#define LATCHSRC_AB_READ 0 // Latch on read. -#define LATCHSRC_A_INDXA 1 // Latch A on A Index. -#define LATCHSRC_B_INDXB 2 // Latch B on B Index. -#define LATCHSRC_B_OVERA 3 // Latch B on A Overflow. +/* LatchSrc values: */ +#define LATCHSRC_AB_READ 0 /* Latch on read. */ +#define LATCHSRC_A_INDXA 1 /* Latch A on A Index. */ +#define LATCHSRC_B_INDXB 2 /* Latch B on B Index. */ +#define LATCHSRC_B_OVERA 3 /* Latch B on A Overflow. */ -// IndxSrc values: -#define INDXSRC_HARD 0 // Hardware or software index. -#define INDXSRC_SOFT 1 // Software index only. +/* IndxSrc values: */ +#define INDXSRC_HARD 0 /* Hardware or software index. */ +#define INDXSRC_SOFT 1 /* Software index only. */ -// IndxPol values: -#define INDXPOL_POS 0 // Index input is active high. -#define INDXPOL_NEG 1 // Index input is active low. +/* IndxPol values: */ +#define INDXPOL_POS 0 /* Index input is active high. */ +#define INDXPOL_NEG 1 /* Index input is active low. */ -// ClkSrc values: -#define CLKSRC_COUNTER 0 // Counter mode. -#define CLKSRC_TIMER 2 // Timer mode. -#define CLKSRC_EXTENDER 3 // Extender mode. +/* ClkSrc values: */ +#define CLKSRC_COUNTER 0 /* Counter mode. */ +#define CLKSRC_TIMER 2 /* Timer mode. */ +#define CLKSRC_EXTENDER 3 /* Extender mode. */ -// ClkPol values: -#define CLKPOL_POS 0 // Counter/Extender clock is - // active high. -#define CLKPOL_NEG 1 // Counter/Extender clock is - // active low. -#define CNTDIR_UP 0 // Timer counts up. -#define CNTDIR_DOWN 1 // Timer counts down. +/* ClkPol values: */ +#define CLKPOL_POS 0 /* Counter/Extender clock is */ + /* active high. */ +#define CLKPOL_NEG 1 /* Counter/Extender clock is */ + /* active low. */ +#define CNTDIR_UP 0 /* Timer counts up. */ +#define CNTDIR_DOWN 1 /* Timer counts down. */ -// ClkEnab values: -#define CLKENAB_ALWAYS 0 // Clock always enabled. -#define CLKENAB_INDEX 1 // Clock is enabled by index. +/* ClkEnab values: */ +#define CLKENAB_ALWAYS 0 /* Clock always enabled. */ +#define CLKENAB_INDEX 1 /* Clock is enabled by index. */ -// ClkMult values: -#define CLKMULT_4X 0 // 4x clock multiplier. -#define CLKMULT_2X 1 // 2x clock multiplier. -#define CLKMULT_1X 2 // 1x clock multiplier. +/* ClkMult values: */ +#define CLKMULT_4X 0 /* 4x clock multiplier. */ +#define CLKMULT_2X 1 /* 2x clock multiplier. */ +#define CLKMULT_1X 2 /* 1x clock multiplier. */ -// Bit Field positions in COUNTER_SETUP structure: -#define BF_LOADSRC 9 // Preload trigger. -#define BF_INDXSRC 7 // Index source. -#define BF_INDXPOL 6 // Index polarity. -#define BF_CLKSRC 4 // Clock source. -#define BF_CLKPOL 3 // Clock polarity/count direction. -#define BF_CLKMULT 1 // Clock multiplier. -#define BF_CLKENAB 0 // Clock enable. +/* Bit Field positions in COUNTER_SETUP structure: */ +#define BF_LOADSRC 9 /* Preload trigger. */ +#define BF_INDXSRC 7 /* Index source. */ +#define BF_INDXPOL 6 /* Index polarity. */ +#define BF_CLKSRC 4 /* Clock source. */ +#define BF_CLKPOL 3 /* Clock polarity/count direction. */ +#define BF_CLKMULT 1 /* Clock multiplier. */ +#define BF_CLKENAB 0 /* Clock enable. */ -// Enumerated counter operating modes specified by ClkSrc bit field in -// a COUNTER_SETUP. +/* Enumerated counter operating modes specified by ClkSrc bit field in */ +/* a COUNTER_SETUP. */ -#define CLKSRC_COUNTER 0 // Counter: ENC_C clock, ENC_D - // direction. -#define CLKSRC_TIMER 2 // Timer: SYS_C clock, - // direction specified by - // ClkPol. -#define CLKSRC_EXTENDER 3 // Extender: OVR_A clock, - // ENC_D direction. +#define CLKSRC_COUNTER 0 /* Counter: ENC_C clock, ENC_D */ + /* direction. */ +#define CLKSRC_TIMER 2 /* Timer: SYS_C clock, */ + /* direction specified by */ + /* ClkPol. */ +#define CLKSRC_EXTENDER 3 /* Extender: OVR_A clock, */ + /* ENC_D direction. */ -// Enumerated counter clock multipliers. +/* Enumerated counter clock multipliers. */ -#define MULT_X0 0x0003 // Supports no multipliers; - // fixed physical multiplier = - // 3. -#define MULT_X1 0x0002 // Supports multiplier x1; - // fixed physical multiplier = - // 2. -#define MULT_X2 0x0001 // Supports multipliers x1, - // x2; physical multipliers = - // 1 or 2. -#define MULT_X4 0x0000 // Supports multipliers x1, - // x2, x4; physical - // multipliers = 0, 1 or 2. +#define MULT_X0 0x0003 /* Supports no multipliers; */ + /* fixed physical multiplier = */ + /* 3. */ +#define MULT_X1 0x0002 /* Supports multiplier x1; */ + /* fixed physical multiplier = */ + /* 2. */ +#define MULT_X2 0x0001 /* Supports multipliers x1, */ + /* x2; physical multipliers = */ + /* 1 or 2. */ +#define MULT_X4 0x0000 /* Supports multipliers x1, */ + /* x2, x4; physical */ + /* multipliers = 0, 1 or 2. */ -// Sanity-check limits for parameters. +/* Sanity-check limits for parameters. */ -#define NUM_COUNTERS 6 // Maximum valid counter - // logical channel number. +#define NUM_COUNTERS 6 /* Maximum valid counter */ + /* logical channel number. */ #define NUM_INTSOURCES 4 #define NUM_LATCHSOURCES 4 #define NUM_CLKMULTS 4 @@ -708,59 +653,59 @@ #define NUM_INDEXSOURCES 2 #define NUM_LOADTRIGS 4 -// Bit field positions in CRA and CRB counter control registers. +/* Bit field positions in CRA and CRB counter control registers. */ -// Bit field positions in CRA: -#define CRABIT_INDXSRC_B 14 // B index source. -#define CRABIT_CLKSRC_B 12 // B clock source. -#define CRABIT_INDXPOL_A 11 // A index polarity. -#define CRABIT_LOADSRC_A 9 // A preload trigger. -#define CRABIT_CLKMULT_A 7 // A clock multiplier. -#define CRABIT_INTSRC_A 5 // A interrupt source. -#define CRABIT_CLKPOL_A 4 // A clock polarity. -#define CRABIT_INDXSRC_A 2 // A index source. -#define CRABIT_CLKSRC_A 0 // A clock source. +/* Bit field positions in CRA: */ +#define CRABIT_INDXSRC_B 14 /* B index source. */ +#define CRABIT_CLKSRC_B 12 /* B clock source. */ +#define CRABIT_INDXPOL_A 11 /* A index polarity. */ +#define CRABIT_LOADSRC_A 9 /* A preload trigger. */ +#define CRABIT_CLKMULT_A 7 /* A clock multiplier. */ +#define CRABIT_INTSRC_A 5 /* A interrupt source. */ +#define CRABIT_CLKPOL_A 4 /* A clock polarity. */ +#define CRABIT_INDXSRC_A 2 /* A index source. */ +#define CRABIT_CLKSRC_A 0 /* A clock source. */ -// Bit field positions in CRB: -#define CRBBIT_INTRESETCMD 15 // Interrupt reset command. -#define CRBBIT_INTRESET_B 14 // B interrupt reset enable. -#define CRBBIT_INTRESET_A 13 // A interrupt reset enable. -#define CRBBIT_CLKENAB_A 12 // A clock enable. -#define CRBBIT_INTSRC_B 10 // B interrupt source. -#define CRBBIT_LATCHSRC 8 // A/B latch source. -#define CRBBIT_LOADSRC_B 6 // B preload trigger. -#define CRBBIT_CLKMULT_B 3 // B clock multiplier. -#define CRBBIT_CLKENAB_B 2 // B clock enable. -#define CRBBIT_INDXPOL_B 1 // B index polarity. -#define CRBBIT_CLKPOL_B 0 // B clock polarity. +/* Bit field positions in CRB: */ +#define CRBBIT_INTRESETCMD 15 /* Interrupt reset command. */ +#define CRBBIT_INTRESET_B 14 /* B interrupt reset enable. */ +#define CRBBIT_INTRESET_A 13 /* A interrupt reset enable. */ +#define CRBBIT_CLKENAB_A 12 /* A clock enable. */ +#define CRBBIT_INTSRC_B 10 /* B interrupt source. */ +#define CRBBIT_LATCHSRC 8 /* A/B latch source. */ +#define CRBBIT_LOADSRC_B 6 /* B preload trigger. */ +#define CRBBIT_CLKMULT_B 3 /* B clock multiplier. */ +#define CRBBIT_CLKENAB_B 2 /* B clock enable. */ +#define CRBBIT_INDXPOL_B 1 /* B index polarity. */ +#define CRBBIT_CLKPOL_B 0 /* B clock polarity. */ -// Bit field masks for CRA and CRB. +/* Bit field masks for CRA and CRB. */ -#define CRAMSK_INDXSRC_B ( (uint16_t)( 3 << CRABIT_INDXSRC_B) ) -#define CRAMSK_CLKSRC_B ( (uint16_t)( 3 << CRABIT_CLKSRC_B) ) -#define CRAMSK_INDXPOL_A ( (uint16_t)( 1 << CRABIT_INDXPOL_A) ) -#define CRAMSK_LOADSRC_A ( (uint16_t)( 3 << CRABIT_LOADSRC_A) ) -#define CRAMSK_CLKMULT_A ( (uint16_t)( 3 << CRABIT_CLKMULT_A) ) -#define CRAMSK_INTSRC_A ( (uint16_t)( 3 << CRABIT_INTSRC_A) ) -#define CRAMSK_CLKPOL_A ( (uint16_t)( 3 << CRABIT_CLKPOL_A) ) -#define CRAMSK_INDXSRC_A ( (uint16_t)( 3 << CRABIT_INDXSRC_A) ) -#define CRAMSK_CLKSRC_A ( (uint16_t)( 3 << CRABIT_CLKSRC_A) ) +#define CRAMSK_INDXSRC_B ((uint16_t)(3 << CRABIT_INDXSRC_B)) +#define CRAMSK_CLKSRC_B ((uint16_t)(3 << CRABIT_CLKSRC_B)) +#define CRAMSK_INDXPOL_A ((uint16_t)(1 << CRABIT_INDXPOL_A)) +#define CRAMSK_LOADSRC_A ((uint16_t)(3 << CRABIT_LOADSRC_A)) +#define CRAMSK_CLKMULT_A ((uint16_t)(3 << CRABIT_CLKMULT_A)) +#define CRAMSK_INTSRC_A ((uint16_t)(3 << CRABIT_INTSRC_A)) +#define CRAMSK_CLKPOL_A ((uint16_t)(3 << CRABIT_CLKPOL_A)) +#define CRAMSK_INDXSRC_A ((uint16_t)(3 << CRABIT_INDXSRC_A)) +#define CRAMSK_CLKSRC_A ((uint16_t)(3 << CRABIT_CLKSRC_A)) -#define CRBMSK_INTRESETCMD ( (uint16_t)( 1 << CRBBIT_INTRESETCMD) ) -#define CRBMSK_INTRESET_B ( (uint16_t)( 1 << CRBBIT_INTRESET_B) ) -#define CRBMSK_INTRESET_A ( (uint16_t)( 1 << CRBBIT_INTRESET_A) ) -#define CRBMSK_CLKENAB_A ( (uint16_t)( 1 << CRBBIT_CLKENAB_A) ) -#define CRBMSK_INTSRC_B ( (uint16_t)( 3 << CRBBIT_INTSRC_B) ) -#define CRBMSK_LATCHSRC ( (uint16_t)( 3 << CRBBIT_LATCHSRC) ) -#define CRBMSK_LOADSRC_B ( (uint16_t)( 3 << CRBBIT_LOADSRC_B) ) -#define CRBMSK_CLKMULT_B ( (uint16_t)( 3 << CRBBIT_CLKMULT_B) ) -#define CRBMSK_CLKENAB_B ( (uint16_t)( 1 << CRBBIT_CLKENAB_B) ) -#define CRBMSK_INDXPOL_B ( (uint16_t)( 1 << CRBBIT_INDXPOL_B) ) -#define CRBMSK_CLKPOL_B ( (uint16_t)( 1 << CRBBIT_CLKPOL_B) ) +#define CRBMSK_INTRESETCMD ((uint16_t)(1 << CRBBIT_INTRESETCMD)) +#define CRBMSK_INTRESET_B ((uint16_t)(1 << CRBBIT_INTRESET_B)) +#define CRBMSK_INTRESET_A ((uint16_t)(1 << CRBBIT_INTRESET_A)) +#define CRBMSK_CLKENAB_A ((uint16_t)(1 << CRBBIT_CLKENAB_A)) +#define CRBMSK_INTSRC_B ((uint16_t)(3 << CRBBIT_INTSRC_B)) +#define CRBMSK_LATCHSRC ((uint16_t)(3 << CRBBIT_LATCHSRC)) +#define CRBMSK_LOADSRC_B ((uint16_t)(3 << CRBBIT_LOADSRC_B)) +#define CRBMSK_CLKMULT_B ((uint16_t)(3 << CRBBIT_CLKMULT_B)) +#define CRBMSK_CLKENAB_B ((uint16_t)(1 << CRBBIT_CLKENAB_B)) +#define CRBMSK_INDXPOL_B ((uint16_t)(1 << CRBBIT_INDXPOL_B)) +#define CRBMSK_CLKPOL_B ((uint16_t)(1 << CRBBIT_CLKPOL_B)) -#define CRBMSK_INTCTRL ( CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B ) // Interrupt reset control bits. +#define CRBMSK_INTCTRL (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B) /* Interrupt reset control bits. */ -// Bit field positions for standardized SETUP structure. +/* Bit field positions for standardized SETUP structure. */ #define STDBIT_INTSRC 13 #define STDBIT_LATCHSRC 11 @@ -772,19 +717,18 @@ #define STDBIT_CLKMULT 1 #define STDBIT_CLKENAB 0 -// Bit field masks for standardized SETUP structure. +/* Bit field masks for standardized SETUP structure. */ -#define STDMSK_INTSRC ( (uint16_t)( 3 << STDBIT_INTSRC ) ) -#define STDMSK_LATCHSRC ( (uint16_t)( 3 << STDBIT_LATCHSRC ) ) -#define STDMSK_LOADSRC ( (uint16_t)( 3 << STDBIT_LOADSRC ) ) -#define STDMSK_INDXSRC ( (uint16_t)( 1 << STDBIT_INDXSRC ) ) -#define STDMSK_INDXPOL ( (uint16_t)( 1 << STDBIT_INDXPOL ) ) -#define STDMSK_CLKSRC ( (uint16_t)( 3 << STDBIT_CLKSRC ) ) -#define STDMSK_CLKPOL ( (uint16_t)( 1 << STDBIT_CLKPOL ) ) -#define STDMSK_CLKMULT ( (uint16_t)( 3 << STDBIT_CLKMULT ) ) -#define STDMSK_CLKENAB ( (uint16_t)( 1 << STDBIT_CLKENAB ) ) +#define STDMSK_INTSRC ((uint16_t)(3 << STDBIT_INTSRC)) +#define STDMSK_LATCHSRC ((uint16_t)(3 << STDBIT_LATCHSRC)) +#define STDMSK_LOADSRC ((uint16_t)(3 << STDBIT_LOADSRC)) +#define STDMSK_INDXSRC ((uint16_t)(1 << STDBIT_INDXSRC)) +#define STDMSK_INDXPOL ((uint16_t)(1 << STDBIT_INDXPOL)) +#define STDMSK_CLKSRC ((uint16_t)(3 << STDBIT_CLKSRC)) +#define STDMSK_CLKPOL ((uint16_t)(1 << STDBIT_CLKPOL)) +#define STDMSK_CLKMULT ((uint16_t)(3 << STDBIT_CLKMULT)) +#define STDMSK_CLKENAB ((uint16_t)(1 << STDBIT_CLKENAB)) -////////////////////////////////////////////////////////// /* typedef struct indexCounter */ /* { */ @@ -795,8 +739,8 @@ /* unsigned int enc; */ /* }CallCounter; */ -typedef struct bufferDMA { +struct bufferDMA { dma_addr_t PhysicalBase; void *LogicalBase; uint32_t DMAHandle; -} DMABUF; +}; diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c new file mode 100644 index 000000000000..844fd5e2e3a9 --- /dev/null +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -0,0 +1,870 @@ +/* + comedi/drivers/serial2002.c + Skeleton code for a Comedi driver + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2002 Anders Blomdell + + 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: serial2002 +Description: Driver for serial connected hardware +Devices: +Author: Anders Blomdell +Updated: Fri, 7 Jun 2002 12:56:45 -0700 +Status: in development + +*/ + +#include "../comedidev.h" + +#include +#include + +#include +#include +#include +#include + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct serial2002_board { + const char *name; +}; + +static const struct serial2002_board serial2002_boards[] = { + { + name: "serial2002"} +}; + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct serial2002_board *)dev->board_ptr) + +struct serial2002_range_table_t { + + // HACK... + int length; + struct comedi_krange range; +}; + + +struct serial2002_private { + + int port; // /dev/ttyS + int speed; // baudrate + struct file *tty; + unsigned int ao_readback[32]; + unsigned char digital_in_mapping[32]; + unsigned char digital_out_mapping[32]; + unsigned char analog_in_mapping[32]; + unsigned char analog_out_mapping[32]; + unsigned char encoder_in_mapping[32]; + struct serial2002_range_table_t in_range[32], out_range[32]; +}; + + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct serial2002_private *)dev->private) + +static int serial2002_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int serial2002_detach(struct comedi_device * dev); +struct comedi_driver driver_serial2002 = { + driver_name:"serial2002", + module:THIS_MODULE, + attach:serial2002_attach, + detach:serial2002_detach, + board_name:&serial2002_boards[0].name, + offset:sizeof(struct serial2002_board), + num_names:sizeof(serial2002_boards) / sizeof(struct serial2002_board), +}; + +static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); + +struct serial_data { + enum { is_invalid, is_digital, is_channel } kind; + int index; + unsigned long value; +}; + +static long tty_ioctl(struct file *f, unsigned op, unsigned long param) +{ +#ifdef HAVE_UNLOCKED_IOCTL + if (f->f_op->unlocked_ioctl) { + return f->f_op->unlocked_ioctl(f, op, param); + } +#endif + if (f->f_op->ioctl) { + return f->f_op->ioctl(f->f_dentry->d_inode, f, op, param); + } + return -ENOSYS; +} + +static int tty_write(struct file *f, unsigned char *buf, int count) +{ + int result; + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + f->f_pos = 0; + result = f->f_op->write(f, buf, count, &f->f_pos); + set_fs(oldfs); + return result; +} + +#if 0 +/* + * On 2.6.26.3 this occaisonally gave me page faults, worked around by + * settings.c_cc[VMIN] = 0; settings.c_cc[VTIME] = 0 + */ +static int tty_available(struct file *f) +{ + long result = 0; + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + tty_ioctl(f, FIONREAD, (unsigned long)&result); + set_fs(oldfs); + return result; +} +#endif + +static int tty_read(struct file *f, int timeout) +{ + int result; + + result = -1; + if (!IS_ERR(f)) { + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + if (f->f_op->poll) { + struct poll_wqueues table; + struct timeval start, now; + + do_gettimeofday(&start); + poll_initwait(&table); + while (1) { + long elapsed; + int mask; + + mask = f->f_op->poll(f, &table.pt); + if (mask & (POLLRDNORM | POLLRDBAND | POLLIN | + POLLHUP | POLLERR)) { + break; + } + do_gettimeofday(&now); + elapsed = + (1000000 * (now.tv_sec - start.tv_sec) + + now.tv_usec - start.tv_usec); + if (elapsed > timeout) { + break; + } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(((timeout - + elapsed) * HZ) / 10000); + } + poll_freewait(&table); + { + unsigned char ch; + + f->f_pos = 0; + if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) { + result = ch; + } + } + } else { + /* Device does not support poll, busy wait */ + int retries = 0; + while (1) { + unsigned char ch; + + retries++; + if (retries >= timeout) { + break; + } + + f->f_pos = 0; + if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) { + result = ch; + break; + } + comedi_udelay(100); + } + } + set_fs(oldfs); + } + return result; +} + +static void tty_setspeed(struct file *f, int speed) +{ + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + { + // Set speed + struct termios settings; + + tty_ioctl(f, TCGETS, (unsigned long)&settings); +// printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); + settings.c_iflag = 0; + settings.c_oflag = 0; + settings.c_lflag = 0; + settings.c_cflag = CLOCAL | CS8 | CREAD; + settings.c_cc[VMIN] = 0; + settings.c_cc[VTIME] = 0; + switch (speed) { + case 2400:{ + settings.c_cflag |= B2400; + } + break; + case 4800:{ + settings.c_cflag |= B4800; + } + break; + case 9600:{ + settings.c_cflag |= B9600; + } + break; + case 19200:{ + settings.c_cflag |= B19200; + } + break; + case 38400:{ + settings.c_cflag |= B38400; + } + break; + case 57600:{ + settings.c_cflag |= B57600; + } + break; + case 115200:{ + settings.c_cflag |= B115200; + } + break; + default:{ + settings.c_cflag |= B9600; + } + break; + } + tty_ioctl(f, TCSETS, (unsigned long)&settings); +// printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); + } + { + // Set low latency + struct serial_struct settings; + + tty_ioctl(f, TIOCGSERIAL, (unsigned long)&settings); + settings.flags |= ASYNC_LOW_LATENCY; + tty_ioctl(f, TIOCSSERIAL, (unsigned long)&settings); + } + + set_fs(oldfs); +} + +static void poll_digital(struct file *f, int channel) +{ + char cmd; + + cmd = 0x40 | (channel & 0x1f); + tty_write(f, &cmd, 1); +} + +static void poll_channel(struct file *f, int channel) +{ + char cmd; + + cmd = 0x60 | (channel & 0x1f); + tty_write(f, &cmd, 1); +} + +static struct serial_data serial_read(struct file *f, int timeout) +{ + struct serial_data result; + int length; + + result.kind = is_invalid; + result.index = 0; + result.value = 0; + length = 0; + while (1) { + int data = tty_read(f, timeout); + + length++; + if (data < 0) { + printk("serial2002 error\n"); + break; + } else if (data & 0x80) { + result.value = (result.value << 7) | (data & 0x7f); + } else { + if (length == 1) { + switch ((data >> 5) & 0x03) { + case 0:{ + result.value = 0; + result.kind = is_digital; + } + break; + case 1:{ + result.value = 1; + result.kind = is_digital; + } + break; + } + } else { + result.value = + (result. + value << 2) | ((data & 0x60) >> 5); + result.kind = is_channel; + } + result.index = data & 0x1f; + break; + } + } + return result; + +} + +static void serial_write(struct file *f, struct serial_data data) +{ + if (data.kind == is_digital) { + unsigned char ch = + ((data.value << 5) & 0x20) | (data.index & 0x1f); + tty_write(f, &ch, 1); + } else { + unsigned char ch[6]; + int i = 0; + if (data.value >= (1L << 30)) { + ch[i] = 0x80 | ((data.value >> 30) & 0x03); + i++; + } + if (data.value >= (1L << 23)) { + ch[i] = 0x80 | ((data.value >> 23) & 0x7f); + i++; + } + if (data.value >= (1L << 16)) { + ch[i] = 0x80 | ((data.value >> 16) & 0x7f); + i++; + } + if (data.value >= (1L << 9)) { + ch[i] = 0x80 | ((data.value >> 9) & 0x7f); + i++; + } + ch[i] = 0x80 | ((data.value >> 2) & 0x7f); + i++; + ch[i] = ((data.value << 5) & 0x60) | (data.index & 0x1f); + i++; + tty_write(f, ch, i); + } +} + +static void serial_2002_open(struct comedi_device * dev) +{ + char port[20]; + + sprintf(port, "/dev/ttyS%d", devpriv->port); + devpriv->tty = filp_open(port, 0, O_RDWR); + if (IS_ERR(devpriv->tty)) { + printk("serial_2002: file open error = %ld\n", + PTR_ERR(devpriv->tty)); + } else { + struct config_t { + + int kind; + int bits; + int min; + int max; + }; + + struct config_t dig_in_config[32]; + struct config_t dig_out_config[32]; + struct config_t chan_in_config[32]; + struct config_t chan_out_config[32]; + int i; + + for (i = 0; i < 32; i++) { + dig_in_config[i].kind = 0; + dig_in_config[i].bits = 0; + dig_in_config[i].min = 0; + dig_in_config[i].max = 0; + dig_out_config[i].kind = 0; + dig_out_config[i].bits = 0; + dig_out_config[i].min = 0; + dig_out_config[i].max = 0; + chan_in_config[i].kind = 0; + chan_in_config[i].bits = 0; + chan_in_config[i].min = 0; + chan_in_config[i].max = 0; + chan_out_config[i].kind = 0; + chan_out_config[i].bits = 0; + chan_out_config[i].min = 0; + chan_out_config[i].max = 0; + } + + tty_setspeed(devpriv->tty, devpriv->speed); + poll_channel(devpriv->tty, 31); // Start reading configuration + while (1) { + struct serial_data data; + + data = serial_read(devpriv->tty, 1000); + if (data.kind != is_channel || data.index != 31 + || !(data.value & 0xe0)) { + break; + } else { + int command, channel, kind; + struct config_t *cur_config = 0; + + channel = data.value & 0x1f; + kind = (data.value >> 5) & 0x7; + command = (data.value >> 8) & 0x3; + switch (kind) { + case 1:{ + cur_config = dig_in_config; + } + break; + case 2:{ + cur_config = dig_out_config; + } + break; + case 3:{ + cur_config = chan_in_config; + } + break; + case 4:{ + cur_config = chan_out_config; + } + break; + case 5:{ + cur_config = chan_in_config; + } + break; + } + + if (cur_config) { + cur_config[channel].kind = kind; + switch (command) { + case 0:{ + cur_config[channel]. + bits = + (data. + value >> 10) & + 0x3f; + } + break; + case 1:{ + int unit, sign, min; + unit = (data. + value >> 10) & + 0x7; + sign = (data. + value >> 13) & + 0x1; + min = (data. + value >> 14) & + 0xfffff; + + switch (unit) { + case 0:{ + min = min * 1000000; + } + break; + case 1:{ + min = min * 1000; + } + break; + case 2:{ + min = min * 1; + } + break; + } + if (sign) { + min = -min; + } + cur_config[channel]. + min = min; + } + break; + case 2:{ + int unit, sign, max; + unit = (data. + value >> 10) & + 0x7; + sign = (data. + value >> 13) & + 0x1; + max = (data. + value >> 14) & + 0xfffff; + + switch (unit) { + case 0:{ + max = max * 1000000; + } + break; + case 1:{ + max = max * 1000; + } + break; + case 2:{ + max = max * 1; + } + break; + } + if (sign) { + max = -max; + } + cur_config[channel]. + max = max; + } + break; + } + } + } + } + for (i = 0; i <= 4; i++) { + // Fill in subdev data + struct config_t *c; + unsigned char *mapping = 0; + struct serial2002_range_table_t *range = 0; + int kind = 0; + + switch (i) { + case 0:{ + c = dig_in_config; + mapping = devpriv->digital_in_mapping; + kind = 1; + } + break; + case 1:{ + c = dig_out_config; + mapping = devpriv->digital_out_mapping; + kind = 2; + } + break; + case 2:{ + c = chan_in_config; + mapping = devpriv->analog_in_mapping; + range = devpriv->in_range; + kind = 3; + } + break; + case 3:{ + c = chan_out_config; + mapping = devpriv->analog_out_mapping; + range = devpriv->out_range; + kind = 4; + } + break; + case 4:{ + c = chan_in_config; + mapping = devpriv->encoder_in_mapping; + range = devpriv->in_range; + kind = 5; + } + break; + default:{ + c = 0; + } + break; + } + if (c) { + struct comedi_subdevice *s; + const struct comedi_lrange **range_table_list = NULL; + unsigned int *maxdata_list; + int j, chan; + + for (chan = 0, j = 0; j < 32; j++) { + if (c[j].kind == kind) { + chan++; + } + } + s = &dev->subdevices[i]; + s->n_chan = chan; + s->maxdata = 0; + if (s->maxdata_list) { + kfree(s->maxdata_list); + } + s->maxdata_list = maxdata_list = + kmalloc(sizeof(unsigned int) * s->n_chan, + GFP_KERNEL); + if (s->range_table_list) { + kfree(s->range_table_list); + } + if (range) { + s->range_table = 0; + s->range_table_list = range_table_list = + kmalloc(sizeof + (struct serial2002_range_table_t) * + s->n_chan, GFP_KERNEL); + } + for (chan = 0, j = 0; j < 32; j++) { + if (c[j].kind == kind) { + if (mapping) { + mapping[chan] = j; + } + if (range) { + range[j].length = 1; + range[j].range.min = + c[j].min; + range[j].range.max = + c[j].max; + range_table_list[chan] = + (const struct + comedi_lrange *) + &range[j]; + } + maxdata_list[chan] = + ((long long)1 << c[j]. + bits) - 1; + chan++; + } + } + } + } + } +} + +static void serial_2002_close(struct comedi_device * dev) +{ + if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0)) { + filp_close(devpriv->tty, 0); + } +} + +static int serial2002_di_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan; + + chan = devpriv->digital_in_mapping[CR_CHAN(insn->chanspec)]; + for (n = 0; n < insn->n; n++) { + struct serial_data read; + + poll_digital(devpriv->tty, chan); + while (1) { + read = serial_read(devpriv->tty, 1000); + if (read.kind != is_digital || read.index == chan) { + break; + } + } + data[n] = read.value; + } + return n; +} + +static int serial2002_do_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan; + + chan = devpriv->digital_out_mapping[CR_CHAN(insn->chanspec)]; + for (n = 0; n < insn->n; n++) { + struct serial_data write; + + write.kind = is_digital; + write.index = chan; + write.value = data[n]; + serial_write(devpriv->tty, write); + } + return n; +} + +static int serial2002_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan; + + chan = devpriv->analog_in_mapping[CR_CHAN(insn->chanspec)]; + for (n = 0; n < insn->n; n++) { + struct serial_data read; + + poll_channel(devpriv->tty, chan); + while (1) { + read = serial_read(devpriv->tty, 1000); + if (read.kind != is_channel || read.index == chan) { + break; + } + } + data[n] = read.value; + } + return n; +} + +static int serial2002_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan; + + chan = devpriv->analog_out_mapping[CR_CHAN(insn->chanspec)]; + for (n = 0; n < insn->n; n++) { + struct serial_data write; + + write.kind = is_channel; + write.index = chan; + write.value = data[n]; + serial_write(devpriv->tty, write); + devpriv->ao_readback[chan] = data[n]; + } + return n; +} + +static int serial2002_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan = CR_CHAN(insn->chanspec); + + for (n = 0; n < insn->n; n++) { + data[n] = devpriv->ao_readback[chan]; + } + + return n; +} + +static int serial2002_ei_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n; + int chan; + + chan = devpriv->encoder_in_mapping[CR_CHAN(insn->chanspec)]; + for (n = 0; n < insn->n; n++) { + struct serial_data read; + + poll_channel(devpriv->tty, chan); + while (1) { + read = serial_read(devpriv->tty, 1000); + if (read.kind != is_channel || read.index == chan) { + break; + } + } + data[n] = read.value; + } + return n; +} + +static int serial2002_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + + printk("comedi%d: serial2002: ", dev->minor); + dev->board_name = thisboard->name; + if (alloc_private(dev, sizeof(struct serial2002_private)) < 0) { + return -ENOMEM; + } + dev->open = serial_2002_open; + dev->close = serial_2002_close; + devpriv->port = it->options[0]; + devpriv->speed = it->options[1]; + printk("/dev/ttyS%d @ %d\n", devpriv->port, devpriv->speed); + + if (alloc_subdevices(dev, 5) < 0) + return -ENOMEM; + + /* digital input subdevice */ + s = dev->subdevices + 0; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_read = &serial2002_di_rinsn; + + /* digital output subdevice */ + s = dev->subdevices + 1; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_write = &serial2002_do_winsn; + + /* analog input subdevice */ + s = dev->subdevices + 2; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = 0; + s->insn_read = &serial2002_ai_rinsn; + + /* analog output subdevice */ + s = dev->subdevices + 3; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = 0; + s->insn_write = &serial2002_ao_winsn; + s->insn_read = &serial2002_ao_rinsn; + + /* encoder input subdevice */ + s = dev->subdevices + 4; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_LSAMPL; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = 0; + s->insn_read = &serial2002_ei_rinsn; + + return 1; +} + +static int serial2002_detach(struct comedi_device * dev) +{ + struct comedi_subdevice *s; + int i; + + printk("comedi%d: serial2002: remove\n", dev->minor); + for (i = 0; i < 4; i++) { + s = &dev->subdevices[i]; + if (s->maxdata_list) { + kfree(s->maxdata_list); + } + if (s->range_table_list) { + kfree(s->range_table_list); + } + } + return 0; +} + +COMEDI_INITCLEANUP(driver_serial2002); diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c new file mode 100644 index 000000000000..c7700d134cc1 --- /dev/null +++ b/drivers/staging/comedi/drivers/skel.c @@ -0,0 +1,624 @@ +/* + comedi/drivers/skel.c + Skeleton code for a Comedi driver + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: skel +Description: Skeleton driver, an example for driver writers +Devices: +Author: ds +Updated: Mon, 18 Mar 2002 15:34:01 -0800 +Status: works + +This driver is a documented example on how Comedi drivers are +written. + +Configuration Options: + none +*/ + +/* + * The previous block comment is used to automatically generate + * documentation in Comedi and Comedilib. The fields: + * + * Driver: the name of the driver + * Description: a short phrase describing the driver. Don't list boards. + * Devices: a full list of the boards that attempt to be supported by + * the driver. Format is "(manufacturer) board name [comedi name]", + * where comedi_name is the name that is used to configure the board. + * See the comment near board_name: in the struct comedi_driver structure + * below. If (manufacturer) or [comedi name] is missing, the previous + * value is used. + * Author: you + * Updated: date when the _documentation_ was last updated. Use 'date -R' + * to get a value for this. + * Status: a one-word description of the status. Valid values are: + * works - driver works correctly on most boards supported, and + * passes comedi_test. + * unknown - unknown. Usually put there by ds. + * experimental - may not work in any particular release. Author + * probably wants assistance testing it. + * bitrotten - driver has not been update in a long time, probably + * doesn't work, and probably is missing support for significant + * Comedi interface features. + * untested - author probably wrote it "blind", and is believed to + * work, but no confirmation. + * + * These headers should be followed by a blank line, and any comments + * you wish to say about the driver. The comment area is the place + * to put any known bugs, limitations, unsupported features, supported + * command triggers, whether or not commands are supported on particular + * subdevices, etc. + * + * Somewhere in the comment should be information about configuration + * options that are used with comedi_config. + */ + +#include "../comedidev.h" + +#include /* for PCI devices */ + +/* Imaginary registers for the imaginary board */ + +#define SKEL_SIZE 0 + +#define SKEL_START_AI_CONV 0 +#define SKEL_AI_READ 0 + +/* + * Board descriptions for two imaginary boards. Describing the + * boards in this way is optional, and completely driver-dependent. + * Some drivers use arrays such as this, other do not. + */ +struct skel_board { + const char *name; + int ai_chans; + int ai_bits; + int have_dio; +}; + +static const struct skel_board skel_boards[] = { + { + name: "skel-100", + ai_chans:16, + ai_bits: 12, + have_dio:1, + }, + { + name: "skel-200", + ai_chans:8, + ai_bits: 16, + have_dio:0, + }, +}; + +/* This is used by modprobe to translate PCI IDs to drivers. Should + * only be used for PCI and ISA-PnP devices */ +/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded + * upstream. */ +#define PCI_VENDOR_ID_SKEL 0xdafe +static DEFINE_PCI_DEVICE_TABLE(skel_pci_table) = { + {PCI_VENDOR_ID_SKEL, 0x0100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_SKEL, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0} +}; + +MODULE_DEVICE_TABLE(pci, skel_pci_table); + +/* + * Useful for shorthand access to the particular board structure + */ +#define thisboard ((const struct skel_board *)dev->board_ptr) + +/* this structure is for data unique to this hardware driver. If + several hardware drivers keep similar information in this structure, + feel free to suggest moving the variable to the struct comedi_device struct. */ +struct skel_private { + + int data; + + /* would be useful for a PCI device */ + struct pci_dev *pci_dev; + + /* Used for AO readback */ + unsigned int ao_readback[2]; +}; + +/* + * most drivers define the following macro to make it easy to + * access the private structure. + */ +#define devpriv ((struct skel_private *)dev->private) + +/* + * The struct comedi_driver structure tells the Comedi core module + * which functions to call to configure/deconfigure (attach/detach) + * the board, and also about the kernel module that contains + * the device code. + */ +static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int skel_detach(struct comedi_device * dev); +static struct comedi_driver driver_skel = { + driver_name:"dummy", + module:THIS_MODULE, + attach:skel_attach, + detach:skel_detach, +/* It is not necessary to implement the following members if you are + * writing a driver for a ISA PnP or PCI card */ + /* Most drivers will support multiple types of boards by + * having an array of board structures. These were defined + * in skel_boards[] above. Note that the element 'name' + * was first in the structure -- Comedi uses this fact to + * extract the name of the board without knowing any details + * about the structure except for its length. + * When a device is attached (by comedi_config), the name + * of the device is given to Comedi, and Comedi tries to + * match it by going through the list of board names. If + * there is a match, the address of the pointer is put + * into dev->board_ptr and driver->attach() is called. + * + * Note that these are not necessary if you can determine + * the type of board in software. ISA PnP, PCI, and PCMCIA + * devices are such boards. + */ + board_name:&skel_boards[0].name, + offset:sizeof(struct skel_board), + num_names:sizeof(skel_boards) / sizeof(struct skel_board), +}; + +static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data); +static int skel_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd); +static int skel_ns_to_timer(unsigned int *ns, int round); + +/* + * Attach is called by the Comedi core to configure the driver + * for a particular board. If you specified a board_name array + * in the driver structure, dev->board_ptr contains that + * address. + */ +static int skel_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + struct comedi_subdevice *s; + + printk("comedi%d: skel: ", dev->minor); + +/* + * If you can probe the device to determine what device in a series + * it is, this is the place to do it. Otherwise, dev->board_ptr + * should already be initialized. + */ + /* dev->board_ptr = skel_probe(dev, it); */ + +/* + * Initialize dev->board_name. Note that we can use the "thisboard" + * macro now, since we just initialized it in the last line. + */ + dev->board_name = thisboard->name; + +/* + * Allocate the private structure area. alloc_private() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_private(dev, sizeof(struct skel_private)) < 0) + return -ENOMEM; + +/* + * Allocate the subdevice structures. alloc_subdevice() is a + * convenient macro defined in comedidev.h. + */ + if (alloc_subdevices(dev, 3) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* dev->read_subdev=s; */ + /* analog input subdevice */ + s->type = COMEDI_SUBD_AI; + /* we support single-ended (ground) and differential */ + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; + s->n_chan = thisboard->ai_chans; + s->maxdata = (1 << thisboard->ai_bits) - 1; + s->range_table = &range_bipolar10; + s->len_chanlist = 16; /* This is the maximum chanlist length that + the board can handle */ + s->insn_read = skel_ai_rinsn; +/* +* s->subdev_flags |= SDF_CMD_READ; +* s->do_cmd = skel_ai_cmd; +*/ + s->do_cmdtest = skel_ai_cmdtest; + + s = dev->subdevices + 1; + /* analog output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 1; + s->maxdata = 0xffff; + s->range_table = &range_bipolar5; + s->insn_write = skel_ao_winsn; + s->insn_read = skel_ao_rinsn; + + s = dev->subdevices + 2; + /* digital i/o subdevice */ + if (thisboard->have_dio) { + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = skel_dio_insn_bits; + s->insn_config = skel_dio_insn_config; + } else { + s->type = COMEDI_SUBD_UNUSED; + } + + printk("attached\n"); + + return 0; +} + +/* + * _detach is called to deconfigure a device. It should deallocate + * resources. + * This function is also called when _attach() fails, so it should be + * careful not to release resources that were not necessarily + * allocated by _attach(). dev->private and dev->subdevices are + * deallocated automatically by the core. + */ +static int skel_detach(struct comedi_device * dev) +{ + printk("comedi%d: skel: remove\n", dev->minor); + + return 0; +} + +/* + * "instructions" read/write data in "one-shot" or "software-triggered" + * mode. + */ +static int skel_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int n, i; + unsigned int d; + unsigned int status; + + /* a typical programming sequence */ + + /* write channel to multiplexer */ + /* outw(chan,dev->iobase + SKEL_MUX); */ + + /* don't wait for mux to settle */ + + /* convert n samples */ + for (n = 0; n < insn->n; n++) { + /* trigger conversion */ + /* outw(0,dev->iobase + SKEL_CONVERT); */ + +#define TIMEOUT 100 + /* wait for conversion to end */ + for (i = 0; i < TIMEOUT; i++) { + status = 1; + /* status = inb(dev->iobase + SKEL_STATUS); */ + if (status) + break; + } + if (i == TIMEOUT) { + /* rt_printk() should be used instead of printk() + * whenever the code can be called from real-time. */ + rt_printk("timeout\n"); + return -ETIMEDOUT; + } + + /* read data */ + /* d = inw(dev->iobase + SKEL_AI_DATA); */ + d = 0; + + /* mangle the data as necessary */ + d ^= 1 << (thisboard->ai_bits - 1); + + data[n] = d; + } + + /* return the number of samples read/written */ + return n; +} + +static int skel_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_cmd * cmd) +{ + int err = 0; + int tmp; + + /* cmdtest tests a particular command to see if it is valid. + * Using the cmdtest ioctl, a user can create a valid cmd + * and then have it executes by the cmd ioctl. + * + * cmdtest returns 1,2,3,4 or 0, depending on which tests + * the command passes. */ + + /* step 1: make sure trigger sources are trivially valid */ + + 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_TIMER | TRIG_EXT; + if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) + err++; + + tmp = cmd->convert_src; + cmd->convert_src &= TRIG_TIMER | TRIG_EXT; + 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_COUNT | TRIG_NONE; + if (!cmd->stop_src || tmp != cmd->stop_src) + err++; + + if (err) + return 1; + + /* step 2: make sure trigger sources are unique and mutually compatible */ + + /* note that mutual compatiblity is not an issue here */ + if (cmd->scan_begin_src != TRIG_TIMER && + cmd->scan_begin_src != TRIG_EXT) + err++; + if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) + err++; + if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) + err++; + + if (err) + return 2; + + /* step 3: make sure arguments are trivially compatible */ + + if (cmd->start_arg != 0) { + cmd->start_arg = 0; + err++; + } +#define MAX_SPEED 10000 /* in nanoseconds */ +#define MIN_SPEED 1000000000 /* in nanoseconds */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_arg < MAX_SPEED) { + cmd->scan_begin_arg = MAX_SPEED; + err++; + } + if (cmd->scan_begin_arg > MIN_SPEED) { + cmd->scan_begin_arg = MIN_SPEED; + err++; + } + } else { + /* external trigger */ + /* should be level/edge, hi/lo specification here */ + /* should specify multiple external triggers */ + if (cmd->scan_begin_arg > 9) { + cmd->scan_begin_arg = 9; + err++; + } + } + if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_arg < MAX_SPEED) { + cmd->convert_arg = MAX_SPEED; + err++; + } + if (cmd->convert_arg > MIN_SPEED) { + cmd->convert_arg = MIN_SPEED; + err++; + } + } else { + /* external trigger */ + /* see above */ + if (cmd->convert_arg > 9) { + cmd->convert_arg = 9; + err++; + } + } + + if (cmd->scan_end_arg != cmd->chanlist_len) { + cmd->scan_end_arg = cmd->chanlist_len; + err++; + } + if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_arg > 0x00ffffff) { + cmd->stop_arg = 0x00ffffff; + err++; + } + } else { + /* TRIG_NONE */ + if (cmd->stop_arg != 0) { + cmd->stop_arg = 0; + err++; + } + } + + if (err) + return 3; + + /* step 4: fix up any arguments */ + + if (cmd->scan_begin_src == TRIG_TIMER) { + tmp = cmd->scan_begin_arg; + skel_ns_to_timer(&cmd->scan_begin_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->scan_begin_arg) + err++; + } + if (cmd->convert_src == TRIG_TIMER) { + tmp = cmd->convert_arg; + skel_ns_to_timer(&cmd->convert_arg, + cmd->flags & TRIG_ROUND_MASK); + if (tmp != cmd->convert_arg) + err++; + if (cmd->scan_begin_src == TRIG_TIMER && + cmd->scan_begin_arg < + cmd->convert_arg * cmd->scan_end_arg) { + cmd->scan_begin_arg = + cmd->convert_arg * cmd->scan_end_arg; + err++; + } + } + + if (err) + return 4; + + return 0; +} + +/* This function doesn't require a particular form, this is just + * what happens to be used in some of the drivers. It should + * convert ns nanoseconds to a counter value suitable for programming + * the device. Also, it should adjust ns so that it cooresponds to + * the actual time that the device will use. */ +static int skel_ns_to_timer(unsigned int *ns, int round) +{ + /* trivial timer */ + /* if your timing is done through two cascaded timers, the + * i8253_cascade_ns_to_timer() function in 8253.h can be + * very helpful. There are also i8254_load() and i8254_mm_load() + * which can be used to load values into the ubiquitous 8254 counters + */ + + return *ns; +} + +static int skel_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + printk("skel_ao_winsn\n"); + /* Writing a list of values to an AO channel is probably not + * very useful, but that's how the interface is defined. */ + for (i = 0; i < insn->n; i++) { + /* a typical programming sequence */ + /* outw(data[i],dev->iobase + SKEL_DA0 + chan); */ + devpriv->ao_readback[chan] = data[i]; + } + + /* return the number of samples read/written */ + return i; +} + +/* AO subdevices should have a read insn as well as a write insn. + * Usually this means copying a value stored in devpriv. */ +static int skel_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int i; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + + return i; +} + +/* DIO devices are slightly special. Although it is possible to + * implement the insn_read/insn_write interface, it is much more + * useful to applications if you implement the insn_bits interface. + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write */ +static int skel_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + if (insn->n != 2) + return -EINVAL; + + /* The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. */ + if (data[0]) { + s->state &= ~data[0]; + s->state |= data[0] & data[1]; + /* Write out the new digital output lines */ + /* outw(s->state,dev->iobase + SKEL_DIO); */ + } + + /* on return, data[1] contains the value of the digital + * input and output lines. */ + /* data[1]=inw(dev->iobase + SKEL_DIO); */ + /* or we could just return the software copy of the output values if + * it was a purely digital output subdevice */ + /* data[1]=s->state; */ + + return 2; +} + +static int skel_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, + struct comedi_insn * insn, unsigned int * data) +{ + int chan = CR_CHAN(insn->chanspec); + + /* The input or output configuration of each digital line is + * configured by a special insn_config instruction. chanspec + * contains the channel to be changed, and data[0] contains the + * value COMEDI_INPUT or COMEDI_OUTPUT. */ + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= 1 << chan; + break; + case INSN_CONFIG_DIO_INPUT: + s->io_bits &= ~(1 << chan); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (s-> + io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + break; + } + /* outw(s->io_bits,dev->iobase + SKEL_DIO_CONFIG); */ + + return insn->n; +} + +/* + * A convenient macro that defines init_module() and cleanup_module(), + * as necessary. + */ +COMEDI_INITCLEANUP(driver_skel); +/* If you are writing a PCI driver you should use COMEDI_PCI_INITCLEANUP instead. +*/ +/* COMEDI_PCI_INITCLEANUP(driver_skel, skel_pci_table) */ diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c new file mode 100644 index 000000000000..1628d216cdd4 --- /dev/null +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -0,0 +1,311 @@ +/* + comedi/drivers/ssv_dnp.c + generic comedi driver for SSV Embedded Systems' DIL/Net-PCs + Copyright (C) 2001 Robert Schwebel + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 2000 David A. Schleef + + 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: ssv_dnp +Description: SSV Embedded Systems DIL/Net-PC +Author: Robert Schwebel +Devices: [SSV Embedded Systems] DIL/Net-PC 1486 (dnp-1486) +Status: unknown +*/ + +/* include files ----------------------------------------------------------- */ + +#include "../comedidev.h" + +/* Some global definitions: the registers of the DNP ----------------------- */ +/* */ +/* For port A and B the mode register has bits corresponding to the output */ +/* pins, where Bit-N = 0 -> input, Bit-N = 1 -> output. Note that bits */ +/* 4 to 7 correspond to pin 0..3 for port C data register. Ensure that bits */ +/* 0..3 remain unchanged! For details about Port C Mode Register see */ +/* the remarks in dnp_insn_config() below. */ + +#define CSCIR 0x22 /* Chip Setup and Control Index Register */ +#define CSCDR 0x23 /* Chip Setup and Control Data Register */ +#define PAMR 0xa5 /* Port A Mode Register */ +#define PADR 0xa9 /* Port A Data Register */ +#define PBMR 0xa4 /* Port B Mode Register */ +#define PBDR 0xa8 /* Port B Data Register */ +#define PCMR 0xa3 /* Port C Mode Register */ +#define PCDR 0xa7 /* Port C Data Register */ + +/* This data structure holds information about the supported boards -------- */ + +struct dnp_board { + const char *name; + int ai_chans; + int ai_bits; + int have_dio; +}; + +static const struct dnp_board dnp_boards[] = { /* we only support one DNP 'board' */ + { /* variant at the moment */ + name: "dnp-1486", + ai_chans:16, + ai_bits: 12, + have_dio:1, + }, +}; + +/* Useful for shorthand access to the particular board structure ----------- */ +#define thisboard ((const struct dnp_board *)dev->board_ptr) + +/* This structure is for data unique to the DNP driver --------------------- */ +struct dnp_private_data { + + // +}; + + +/* Shorthand macro for faster access to the private data ------------------- */ +#define devpriv ((dnp_private *)dev->private) + +/* ------------------------------------------------------------------------- */ +/* The struct comedi_driver structure tells the Comedi core module which functions */ +/* to call to configure/deconfigure (attach/detach) the board, and also */ +/* about the kernel module that contains the device code. */ +/* */ +/* In the following section we define the API of this driver. */ +/* ------------------------------------------------------------------------- */ + +static int dnp_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int dnp_detach(struct comedi_device * dev); + +static struct comedi_driver driver_dnp = { + driver_name:"ssv_dnp", + module:THIS_MODULE, + attach:dnp_attach, + detach:dnp_detach, + board_name:&dnp_boards[0].name, + /* only necessary for non-PnP devs */ + offset:sizeof(struct dnp_board),/* like ISA-PnP, PCI or PCMCIA. */ + num_names:sizeof(dnp_boards) / sizeof(struct dnp_board), +}; + +COMEDI_INITCLEANUP(driver_dnp); + +static int dnp_dio_insn_bits(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +static int dnp_dio_insn_config(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data); + +/* ------------------------------------------------------------------------- */ +/* Attach is called by comedi core to configure the driver for a particular */ +/* board. If you specified a board_name array in the driver structure, */ +/* dev->board_ptr contains that address. */ +/* ------------------------------------------------------------------------- */ + +static int dnp_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + + struct comedi_subdevice *s; + + printk("comedi%d: dnp: ", dev->minor); + + /* Autoprobing: this should find out which board we have. Currently only */ + /* the 1486 board is supported and autoprobing is not implemented :-) */ + //dev->board_ptr = dnp_probe(dev); + + /* Initialize the name of the board. We can use the "thisboard" macro now. */ + dev->board_name = thisboard->name; + + /* Allocate the private structure area. alloc_private() is a convenient */ + /* macro defined in comedidev.h. */ + if (alloc_private(dev, sizeof(struct dnp_private_data)) < 0) + return -ENOMEM; + + /* Allocate the subdevice structures. alloc_subdevice() is a convenient */ + /* macro defined in comedidev.h. */ + + if (alloc_subdevices(dev, 1) < 0) + return -ENOMEM; + + s = dev->subdevices + 0; + /* digital i/o subdevice */ + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 20; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = dnp_dio_insn_bits; + s->insn_config = dnp_dio_insn_config; + + printk("attached\n"); + + /* We use the I/O ports 0x22,0x23 and 0xa3-0xa9, which are always + * allocated for the primary 8259, so we don't need to allocate them + * ourselves. */ + + /* configure all ports as input (default) */ + outb(PAMR, CSCIR); + outb(0x00, CSCDR); + outb(PBMR, CSCIR); + outb(0x00, CSCDR); + outb(PCMR, CSCIR); + outb((inb(CSCDR) & 0xAA), CSCDR); + + return 1; + +} + +/* ------------------------------------------------------------------------- */ +/* detach is called to deconfigure a device. It should deallocate the */ +/* resources. This function is also called when _attach() fails, so it */ +/* should be careful not to release resources that were not necessarily */ +/* allocated by _attach(). dev->private and dev->subdevices are */ +/* deallocated automatically by the core. */ +/* ------------------------------------------------------------------------- */ + +static int dnp_detach(struct comedi_device * dev) +{ + + /* configure all ports as input (default) */ + outb(PAMR, CSCIR); + outb(0x00, CSCDR); + outb(PBMR, CSCIR); + outb(0x00, CSCDR); + outb(PCMR, CSCIR); + outb((inb(CSCDR) & 0xAA), CSCDR); + + /* announce that we are finished */ + printk("comedi%d: dnp: remove\n", dev->minor); + + return 0; + +} + +/* ------------------------------------------------------------------------- */ +/* The insn_bits interface allows packed reading/writing of DIO channels. */ +/* The comedi core can convert between insn_bits and insn_read/write, so you */ +/* are able to use these instructions as well. */ +/* ------------------------------------------------------------------------- */ + +static int dnp_dio_insn_bits(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + + if (insn->n != 2) + return -EINVAL; /* insn uses data[0] and data[1] */ + + /* The insn data is a mask in data[0] and the new data in data[1], each */ + /* channel cooresponding to a bit. */ + + /* Ports A and B are straight forward: each bit corresponds to an output */ + /* pin with the same order. Port C is different: bits 0...3 correspond to */ + /* bits 4...7 of the output register (PCDR). */ + + if (data[0]) { + + outb(PADR, CSCIR); + outb((inb(CSCDR) + & ~(u8) (data[0] & 0x0000FF)) + | (u8) (data[1] & 0x0000FF), CSCDR); + + outb(PBDR, CSCIR); + outb((inb(CSCDR) + & ~(u8) ((data[0] & 0x00FF00) >> 8)) + | (u8) ((data[1] & 0x00FF00) >> 8), CSCDR); + + outb(PCDR, CSCIR); + outb((inb(CSCDR) + & ~(u8) ((data[0] & 0x0F0000) >> 12)) + | (u8) ((data[1] & 0x0F0000) >> 12), CSCDR); + } + + /* on return, data[1] contains the value of the digital input lines. */ + outb(PADR, CSCIR); + data[0] = inb(CSCDR); + outb(PBDR, CSCIR); + data[0] += inb(CSCDR) << 8; + outb(PCDR, CSCIR); + data[0] += ((inb(CSCDR) & 0xF0) << 12); + + return 2; + +} + +/* ------------------------------------------------------------------------- */ +/* Configure the direction of the bidirectional digital i/o pins. chanspec */ +/* contains the channel to be changed and data[0] contains either */ +/* COMEDI_INPUT or COMEDI_OUTPUT. */ +/* ------------------------------------------------------------------------- */ + +static int dnp_dio_insn_config(struct comedi_device * dev, + struct comedi_subdevice * s, struct comedi_insn * insn, unsigned int * data) +{ + + u8 register_buffer; + + int chan = CR_CHAN(insn->chanspec); /* reduces chanspec to lower 16 bits */ + + switch (data[0]) { + case INSN_CONFIG_DIO_OUTPUT: + case INSN_CONFIG_DIO_INPUT: + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = + (inb(CSCDR) & (1 << chan)) ? COMEDI_OUTPUT : + COMEDI_INPUT; + return insn->n; + break; + default: + return -EINVAL; + break; + } + /* Test: which port does the channel belong to? */ + + /* We have to pay attention with port C: this is the meaning of PCMR: */ + /* Bit in PCMR: 7 6 5 4 3 2 1 0 */ + /* Corresponding port C pin: d 3 d 2 d 1 d 0 d= don't touch */ + + if ((chan >= 0) && (chan <= 7)) { + /* this is port A */ + outb(PAMR, CSCIR); + } else if ((chan >= 8) && (chan <= 15)) { + /* this is port B */ + chan -= 8; + outb(PBMR, CSCIR); + } else if ((chan >= 16) && (chan <= 19)) { + /* this is port C; multiplication with 2 brings bits into correct */ + /* position for PCMR! */ + chan -= 16; + chan *= 2; + outb(PCMR, CSCIR); + } else { + return -EINVAL; + } + + /* read 'old' direction of the port and set bits (out=1, in=0) */ + register_buffer = inb(CSCDR); + if (data[0] == COMEDI_OUTPUT) { + register_buffer |= (1 << chan); + } else { + register_buffer &= ~(1 << chan); + } + outb(register_buffer, CSCDR); + + return 1; + +} diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c new file mode 100644 index 000000000000..dd3b1119319b --- /dev/null +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -0,0 +1,515 @@ +/*************************************************************************** + * * + * comedi/drivers/unioxx5.c * + * Driver for Fastwel UNIOxx-5 (analog and digital i/o) boards. * + * * + * Copyright (C) 2006 Kruchinin Daniil (asgard) [asgard@etersoft.ru] * + * * + * COMEDI - Linux Control and Measurement Device Interface * + * Copyright (C) 1998,2000 David A. Schleef * + * * + * 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: unioxx5 +Description: Driver for Fastwel UNIOxx-5 (analog and digital i/o) boards. +Author: Kruchinin Daniil (asgard) +Status: unknown +Updated: 2006-10-09 +Devices: [Fastwel] UNIOxx-5 (unioxx5), + + This card supports digital and analog I/O. It written for g01 + subdevices only. + channels range: 0 .. 23 dio channels + and 0 .. 11 analog modules range + During attaching unioxx5 module displays modules identifiers + (see dmesg after comedi_config) in format: + | [module_number] module_id | + +*/ + +#include "../comedidev.h" +#include + +#define DRIVER_NAME "unioxx5" +#define UNIOXX5_SIZE 0x10 +#define UNIOXX5_SUBDEV_BASE 0xA000 /* base addr of first subdev */ +#define UNIOXX5_SUBDEV_ODDS 0x400 + +/* modules types */ +#define MODULE_DIGITAL 0 +#define MODULE_OUTPUT_MASK 0x80 /* analog input/output */ + +/* constants for digital i/o */ +#define UNIOXX5_NUM_OF_CHANS 24 + +/* constants for analog i/o */ +#define TxBE 0x10 /* transmit buffer enable */ +#define RxCA 0x20 /* 1 receive character available */ +#define Rx2CA 0x40 /* 2 receive character available */ +#define Rx4CA 0x80 /* 4 receive character available */ + +/* bytes mask errors */ +#define Rx2CA_ERR_MASK 0x04 /* 2 bytes receiving error */ +#define Rx4CA_ERR_MASK 0x08 /* 4 bytes receiving error */ + +/* channel modes */ +#define ALL_2_INPUT 0 /* config all digital channels to input */ +#define ALL_2_OUTPUT 1 /* config all digital channels to output */ + +/* 'private' structure for each subdevice */ +struct unioxx5_subd_priv { + int usp_iobase; + unsigned char usp_module_type[12]; /* 12 modules. each can be 70L or 73L */ + unsigned char usp_extra_data[12][4]; /* for saving previous written value for analog modules */ + unsigned char usp_prev_wr_val[3]; /* previous written value */ + unsigned char usp_prev_cn_val[3]; /* previous channel value */ +}; + +static int unioxx5_attach(struct comedi_device * dev, struct comedi_devconfig * it); +static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev, + struct comedi_insn * insn, unsigned int * data); +static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev, + struct comedi_insn * insn, unsigned int * data); +static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevice * subdev, + struct comedi_insn * insn, unsigned int * data); +static int unioxx5_detach(struct comedi_device * dev); +static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_iobase, + int minor); +static int __unioxx5_digital_write(struct unioxx5_subd_priv * usp, unsigned int * data, + int channel, int minor); +static int __unioxx5_digital_read(struct unioxx5_subd_priv * usp, unsigned int * data, + int channel, int minor); +//static void __unioxx5_digital_config(struct unioxx5_subd_priv* usp, int mode); +static int __unioxx5_analog_write(struct unioxx5_subd_priv * usp, unsigned int * data, + int channel, int minor); +static int __unioxx5_analog_read(struct unioxx5_subd_priv * usp, unsigned int * data, + int channel, int minor); +static int __unioxx5_define_chan_offset(int chan_num); +static void __unioxx5_analog_config(struct unioxx5_subd_priv * usp, int channel); + +static struct comedi_driver unioxx5_driver = { + driver_name:DRIVER_NAME, + module:THIS_MODULE, + attach:unioxx5_attach, + detach:unioxx5_detach +}; + +COMEDI_INITCLEANUP(unioxx5_driver); + +static int unioxx5_attach(struct comedi_device * dev, struct comedi_devconfig * it) +{ + int iobase, i, n_subd; + int id, num, ba; + + iobase = it->options[0]; + + dev->board_name = DRIVER_NAME; + dev->iobase = iobase; + iobase += UNIOXX5_SUBDEV_BASE; + + /* defining number of subdevices and getting they types (it must be 'g01') */ + for (i = n_subd = 0, ba = iobase; i < 4; i++, ba += UNIOXX5_SUBDEV_ODDS) { + id = inb(ba + 0xE); + num = inb(ba + 0xF); + + if (id != 'g' || num != 1) + continue; + + n_subd++; + } + + /* unioxx5 can has from two to four subdevices */ + if (n_subd < 2) { + printk(KERN_ERR + "your card must has at least 2 'g01' subdevices\n"); + return -1; + } + + if (alloc_subdevices(dev, n_subd) < 0) { + printk(KERN_ERR "out of memory\n"); + return -ENOMEM; + } + + /* initializing each of for same subdevices */ + for (i = 0; i < n_subd; i++, iobase += UNIOXX5_SUBDEV_ODDS) { + if (__unioxx5_subdev_init(&dev->subdevices[i], iobase, + dev->minor) < 0) + return -1; + } + + printk("attached\n"); + return 0; +} + +static int unioxx5_subdev_read(struct comedi_device * dev, struct comedi_subdevice * subdev, + struct comedi_insn * insn, unsigned int * data) +{ + struct unioxx5_subd_priv *usp = subdev->private; + int channel, type; + + channel = CR_CHAN(insn->chanspec); + type = usp->usp_module_type[channel / 2]; /* defining module type(analog or digital) */ + + if (type == MODULE_DIGITAL) { + if (!__unioxx5_digital_read(usp, data, channel, dev->minor)) + return -1; + } else { + if (!__unioxx5_analog_read(usp, data, channel, dev->minor)) + return -1; + } + + return 1; +} + +static int unioxx5_subdev_write(struct comedi_device * dev, struct comedi_subdevice * subdev, + struct comedi_insn * insn, unsigned int * data) +{ + struct unioxx5_subd_priv *usp = subdev->private; + int channel, type; + + channel = CR_CHAN(insn->chanspec); + type = usp->usp_module_type[channel / 2]; /* defining module type(analog or digital) */ + + if (type == MODULE_DIGITAL) { + if (!__unioxx5_digital_write(usp, data, channel, dev->minor)) + return -1; + } else { + if (!__unioxx5_analog_write(usp, data, channel, dev->minor)) + return -1; + } + + return 1; +} + +/* for digital modules only */ +static int unioxx5_insn_config(struct comedi_device * dev, struct comedi_subdevice * subdev, + struct comedi_insn * insn, unsigned int * data) +{ + int channel_offset, flags, channel = CR_CHAN(insn->chanspec), type; + struct unioxx5_subd_priv *usp = subdev->private; + int mask = 1 << (channel & 0x07); + + type = usp->usp_module_type[channel / 2]; + + if (type != MODULE_DIGITAL) { + printk(KERN_ERR + "comedi%d: channel configuration accessible only for digital modules\n", + dev->minor); + return -1; + } + + if ((channel_offset = __unioxx5_define_chan_offset(channel)) < 0) { + printk(KERN_ERR + "comedi%d: undefined channel %d. channel range is 0 .. 23\n", + dev->minor, channel); + return -1; + } + + /* gets previously written value */ + flags = usp->usp_prev_cn_val[channel_offset - 1]; + + switch (*data) { + case COMEDI_INPUT: + flags &= ~mask; + break; + case COMEDI_OUTPUT: + flags |= mask; + break; + default: + printk(KERN_ERR "comedi%d: unknown flag\n", dev->minor); + return -1; + } + + /* *\ + * sets channels buffer to 1(after this we are allowed to * + * change channel type on input or output) * + \* */ + outb(1, usp->usp_iobase + 0); + outb(flags, usp->usp_iobase + channel_offset); /* changes type of _one_ channel */ + outb(0, usp->usp_iobase + 0); /* sets channels bank to 0(allows directly input/output) */ + usp->usp_prev_cn_val[channel_offset - 1] = flags; /* saves written value */ + + return 0; +} + +static int unioxx5_detach(struct comedi_device * dev) +{ + int i; + struct comedi_subdevice *subdev; + struct unioxx5_subd_priv *usp; + + for (i = 0; i < dev->n_subdevices; i++) { + subdev = &dev->subdevices[i]; + usp = subdev->private; + release_region(usp->usp_iobase, UNIOXX5_SIZE); + kfree(subdev->private); + } + + return 0; +} + +/* initializing subdevice with given address */ +static int __unioxx5_subdev_init(struct comedi_subdevice * subdev, int subdev_iobase, + int minor) +{ + struct unioxx5_subd_priv *usp; + int i, to, ndef_flag = 0; + + if (!request_region(subdev_iobase, UNIOXX5_SIZE, DRIVER_NAME)) { + printk(KERN_ERR "comedi%d: I/O port conflict\n", minor); + return -EIO; + } + + if ((usp = (struct unioxx5_subd_priv *) kzalloc(sizeof(*usp), + GFP_KERNEL)) == NULL) { + printk(KERN_ERR "comedi%d: erorr! --> out of memory!\n", minor); + return -1; + } + + usp->usp_iobase = subdev_iobase; + printk("comedi%d: |", minor); + + /* defining modules types */ + for (i = 0; i < 12; i++) { + to = 10000; + + __unioxx5_analog_config(usp, i * 2); + outb(i + 1, subdev_iobase + 5); /* sends channel number to card */ + outb('H', subdev_iobase + 6); /* requests EEPROM world */ + while (!(inb(subdev_iobase + 0) & TxBE)) ; /* waits while writting will be allowed */ + outb(0, subdev_iobase + 6); + + /* waits while reading of two bytes will be allowed */ + while (!(inb(subdev_iobase + 0) & Rx2CA)) { + if (--to <= 0) { + ndef_flag = 1; + break; + } + } + + if (ndef_flag) { + usp->usp_module_type[i] = 0; + ndef_flag = 0; + } else + usp->usp_module_type[i] = inb(subdev_iobase + 6); + + printk(" [%d] 0x%02x |", i, usp->usp_module_type[i]); + comedi_udelay(1); + } + + printk("\n"); + + /* initial subdevice for digital or analog i/o */ + subdev->type = COMEDI_SUBD_DIO; + subdev->private = usp; + subdev->subdev_flags = SDF_READABLE | SDF_WRITABLE; + subdev->n_chan = UNIOXX5_NUM_OF_CHANS; + subdev->maxdata = 0xFFF; + subdev->range_table = &range_digital; + subdev->insn_read = unioxx5_subdev_read; + subdev->insn_write = unioxx5_subdev_write; + subdev->insn_config = unioxx5_insn_config; /* for digital modules only!!! */ + + printk("subdevice configured\n"); + + return 0; +} + +static int __unioxx5_digital_write(struct unioxx5_subd_priv * usp, unsigned int * data, + int channel, int minor) +{ + int channel_offset, val; + int mask = 1 << (channel & 0x07); + + if ((channel_offset = __unioxx5_define_chan_offset(channel)) < 0) { + printk(KERN_ERR + "comedi%d: undefined channel %d. channel range is 0 .. 23\n", + minor, channel); + return 0; + } + + val = usp->usp_prev_wr_val[channel_offset - 1]; /* getting previous written value */ + + if (*data) + val |= mask; + else + val &= ~mask; + + outb(val, usp->usp_iobase + channel_offset); + usp->usp_prev_wr_val[channel_offset - 1] = val; /* saving new written value */ + + return 1; +} + +/* function for digital reading */ +static int __unioxx5_digital_read(struct unioxx5_subd_priv * usp, unsigned int * data, + int channel, int minor) +{ + int channel_offset, mask = 1 << (channel & 0x07); + + if ((channel_offset = __unioxx5_define_chan_offset(channel)) < 0) { + printk(KERN_ERR + "comedi%d: undefined channel %d. channel range is 0 .. 23\n", + minor, channel); + return 0; + } + + *data = inb(usp->usp_iobase + channel_offset); + *data &= mask; + + if (channel_offset > 1) + channel -= 2 << channel_offset; /* this operation is created for correct readed value to 0 or 1 */ + + *data >>= channel; + return 1; +} + +#if 0 /* not used? */ +static void __unioxx5_digital_config(struct unioxx5_subd_priv * usp, int mode) +{ + int i, mask; + + mask = (mode == ALL_2_OUTPUT) ? 0xFF : 0x00; + printk("COMEDI: mode = %d\n", mask); + + outb(1, usp->usp_iobase + 0); + + for (i = 0; i < 3; i++) + outb(mask, usp->usp_iobase + i); + + outb(0, usp->usp_iobase + 0); +} +#endif + +static int __unioxx5_analog_write(struct unioxx5_subd_priv * usp, unsigned int * data, + int channel, int minor) +{ + int module, i; + + module = channel / 2; /* definig module number(0 .. 11) */ + i = (channel % 2) << 1; /* depends on type of channel (A or B) */ + + /* defining if given module can work on output */ + if (!(usp->usp_module_type[module] & MODULE_OUTPUT_MASK)) { + printk(KERN_ERR + "comedi%d: module in position %d with id 0x%0x is for input only!\n", + minor, module, usp->usp_module_type[module]); + return 0; + } + + __unioxx5_analog_config(usp, channel); + /* saving minor byte */ + usp->usp_extra_data[module][i++] = (unsigned char)(*data & 0x00FF); + /* saving major byte */ + usp->usp_extra_data[module][i] = (unsigned char)((*data & 0xFF00) >> 8); + + //while(!((inb(usp->usp_iobase + 0)) & TxBE)); + outb(module + 1, usp->usp_iobase + 5); /* sending module number to card(1 .. 12) */ + outb('W', usp->usp_iobase + 6); /* sends (W)rite command to module */ + + /* sending for bytes to module(one byte per cycle iteration) */ + for (i = 0; i < 4; i++) { + while (!((inb(usp->usp_iobase + 0)) & TxBE)) ; /* waits while writting will be allowed */ + outb(usp->usp_extra_data[module][i], usp->usp_iobase + 6); + } + + return 1; +} + +static int __unioxx5_analog_read(struct unioxx5_subd_priv * usp, unsigned int * data, + int channel, int minor) +{ + int module_no, read_ch; + char control; + + module_no = channel / 2; + read_ch = channel % 2; /* depend on type of channel (A or B) */ + + /* defining if given module can work on input */ + if (usp->usp_module_type[module_no] & MODULE_OUTPUT_MASK) { + printk(KERN_ERR + "comedi%d: module in position %d with id 0x%02x is for output only", + minor, module_no, usp->usp_module_type[module_no]); + return 0; + } + + __unioxx5_analog_config(usp, channel); + outb(module_no + 1, usp->usp_iobase + 5); /* sends module number to card(1 .. 12) */ + outb('V', usp->usp_iobase + 6); /* sends to module (V)erify command */ + control = inb(usp->usp_iobase); /* get control register byte */ + + /* waits while reading four bytes will be allowed */ + while (!((control = inb(usp->usp_iobase + 0)) & Rx4CA)) ; + + /* if four bytes readding error occurs - return 0(false) */ + if ((control & Rx4CA_ERR_MASK)) { + printk("COMEDI: 4 bytes error\n"); + return 0; + } + + if (read_ch) + *data = inw(usp->usp_iobase + 6); /* channel B */ + else + *data = inw(usp->usp_iobase + 4); /* channel A */ + + return 1; +} + +/* configure channels for analog i/o (even to output, odd to input) */ +static void __unioxx5_analog_config(struct unioxx5_subd_priv * usp, int channel) +{ + int chan_a, chan_b, conf, channel_offset; + + channel_offset = __unioxx5_define_chan_offset(channel); + conf = usp->usp_prev_cn_val[channel_offset - 1]; + chan_a = chan_b = 1; + + /* setting channel A and channel B mask */ + if (channel % 2 == 0) { + chan_a <<= channel & 0x07; + chan_b <<= (channel + 1) & 0x07; + } else { + chan_a <<= (channel - 1) & 0x07; + chan_b <<= channel & 0x07; + } + + conf |= chan_a; /* even channel ot output */ + conf &= ~chan_b; /* odd channel to input */ + + outb(1, usp->usp_iobase + 0); + outb(conf, usp->usp_iobase + channel_offset); + outb(0, usp->usp_iobase + 0); + + usp->usp_prev_cn_val[channel_offset - 1] = conf; +} + +/* *\ + * this function defines if the given channel number * + * enters in default numeric interspace(from 0 to 23) * + * and it returns address offset for usage needed * + * channel. * +\* */ + +static int __unioxx5_define_chan_offset(int chan_num) +{ + + if (chan_num < 0 || chan_num > 23) + return -1; + + return (chan_num >> 3) + 1; +} diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 35138257be7f..d0b59e98314b 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1,4 +1,4 @@ -#define DRIVER_VERSION "v2.1" +#define DRIVER_VERSION "v2.2" #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" #define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com" /* @@ -25,8 +25,8 @@ Driver: usbdux Description: University of Stirling USB DAQ & INCITE Technology Limited Devices: [ITL] USB-DUX (usbdux.o) Author: Bernd Porr -Updated: 25 Nov 2007 -Status: Testing +Updated: 8 Dec 2008 +Status: Stable Configuration options: You have to upload firmware with the -i option. The firmware is usually installed under /usr/share/usb or @@ -79,6 +79,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. * 1.2: added PWM suport via EP4 * 2.0: PWM seems to be stable and is not interfering with the other functions * 2.1: changed PWM API + * 2.2: added firmware kernel request to fix an udev problem * */ @@ -94,6 +95,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. #include #include #include +#include #include "../comedidev.h" @@ -212,7 +214,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. /**************************************************/ /* comedi constants */ -static const comedi_lrange range_usbdux_ai_range = { 4, { +static const struct comedi_lrange range_usbdux_ai_range = { 4, { BIP_RANGE(4.096), BIP_RANGE(4.096 / 2), UNI_RANGE(4.096), @@ -220,7 +222,7 @@ static const comedi_lrange range_usbdux_ai_range = { 4, { } }; -static const comedi_lrange range_usbdux_ao_range = { 2, { +static const struct comedi_lrange range_usbdux_ao_range = { 2, { BIP_RANGE(4.096), UNI_RANGE(4.096), } @@ -251,7 +253,7 @@ struct usbduxsub { /* pwm-transfer handling */ struct urb *urbPwm; /* PWM period */ - lsampl_t pwmPeriod; + unsigned int pwmPeriod; /* PWM internal delay for the GPIF in the FX2 */ int8_t pwmDelay; /* size of the PWM buffer which holds the bit pattern */ @@ -267,7 +269,7 @@ struct usbduxsub { /* interface structure in 2.6 */ struct usb_interface *interface; /* comedi device for the interrupt context */ - comedi_device *comedidev; + struct comedi_device *comedidev; /* is it USB_SPEED_HIGH or not? */ short int high_speed; /* asynchronous command is running */ @@ -361,7 +363,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink) * This will cancel a running acquisition operation. * This is called by comedi but never from inside the driver. */ -static int usbdux_ai_cancel(comedi_device *dev, comedi_subdevice *s) +static int usbdux_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct usbduxsub *this_usbduxsub; int res = 0; @@ -390,8 +392,8 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb) { int i, err, n; struct usbduxsub *this_usbduxsub; - comedi_device *this_comedidev; - comedi_subdevice *s; + struct comedi_device *this_comedidev; + struct comedi_subdevice *s; /* the context variable points to the subdevice */ this_comedidev = urb->context; @@ -559,7 +561,7 @@ static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink) } /* force unlink, is called by comedi */ -static int usbdux_ao_cancel(comedi_device *dev, comedi_subdevice *s) +static int usbdux_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct usbduxsub *this_usbduxsub = dev->private; int res = 0; @@ -584,8 +586,8 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb) int i, ret; int8_t *datap; struct usbduxsub *this_usbduxsub; - comedi_device *this_comedidev; - comedi_subdevice *s; + struct comedi_device *this_comedidev; + struct comedi_subdevice *s; /* the context variable points to the subdevice */ this_comedidev = urb->context; @@ -654,7 +656,7 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb) ((uint8_t *) (urb->transfer_buffer))[0] = s->async->cmd.chanlist_len; for (i = 0; i < s->async->cmd.chanlist_len; i++) { - sampl_t temp; + short temp; if (i >= NUMOUTCHANNELS) break; @@ -718,31 +720,29 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub) int errcode = 0; uint8_t local_transfer_buffer[16]; - if (usbduxsub->probed) { - /* 7f92 to zero */ - local_transfer_buffer[0] = 0; - errcode = usb_control_msg(usbduxsub->usbdev, - /* create a pipe for a control transfer */ - usb_sndctrlpipe(usbduxsub->usbdev, 0), - /* bRequest, "Firmware" */ - USBDUXSUB_FIRMWARE, - /* bmRequestType */ - VENDOR_DIR_OUT, - /* Value */ - USBDUXSUB_CPUCS, - /* Index */ - 0x0000, - /* address of the transfer buffer */ - local_transfer_buffer, - /* Length */ - 1, - /* Timeout */ - EZTIMEOUT); - if (errcode < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: control msg failed (start)\n"); - return errcode; - } + /* 7f92 to zero */ + local_transfer_buffer[0] = 0; + errcode = usb_control_msg(usbduxsub->usbdev, + /* create a pipe for a control transfer */ + usb_sndctrlpipe(usbduxsub->usbdev, 0), + /* bRequest, "Firmware" */ + USBDUXSUB_FIRMWARE, + /* bmRequestType */ + VENDOR_DIR_OUT, + /* Value */ + USBDUXSUB_CPUCS, + /* Index */ + 0x0000, + /* address of the transfer buffer */ + local_transfer_buffer, + /* Length */ + 1, + /* Timeout */ + EZTIMEOUT); + if (errcode < 0) { + dev_err(&usbduxsub->interface->dev, + "comedi_: control msg failed (start)\n"); + return errcode; } return 0; } @@ -752,28 +752,27 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub) int errcode = 0; uint8_t local_transfer_buffer[16]; - if (usbduxsub->probed) { - /* 7f92 to one */ - local_transfer_buffer[0] = 1; - errcode = usb_control_msg(usbduxsub->usbdev, - usb_sndctrlpipe(usbduxsub->usbdev, 0), - /* bRequest, "Firmware" */ - USBDUXSUB_FIRMWARE, - /* bmRequestType */ - VENDOR_DIR_OUT, - /* Value */ - USBDUXSUB_CPUCS, - /* Index */ - 0x0000, local_transfer_buffer, - /* Length */ - 1, - /* Timeout */ - EZTIMEOUT); - if (errcode < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: control msg failed (stop)\n"); - return errcode; - } + + /* 7f92 to one */ + local_transfer_buffer[0] = 1; + errcode = usb_control_msg(usbduxsub->usbdev, + usb_sndctrlpipe(usbduxsub->usbdev, 0), + /* bRequest, "Firmware" */ + USBDUXSUB_FIRMWARE, + /* bmRequestType */ + VENDOR_DIR_OUT, + /* Value */ + USBDUXSUB_CPUCS, + /* Index */ + 0x0000, local_transfer_buffer, + /* Length */ + 1, + /* Timeout */ + EZTIMEOUT); + if (errcode < 0) { + dev_err(&usbduxsub->interface->dev, + "comedi_: control msg failed (stop)\n"); + return errcode; } return 0; } @@ -784,13 +783,7 @@ static int usbduxsub_upload(struct usbduxsub *usbduxsub, { int errcode; - if (usbduxsub->probed) { - dev_dbg(&usbduxsub->interface->dev, - "comedi%d: usbdux: uploading %d bytes" - " to addr %d, first byte=%d.\n", - usbduxsub->comedidev->minor, len, - startAddr, local_transfer_buffer[0]); - errcode = usb_control_msg(usbduxsub->usbdev, + errcode = usb_control_msg(usbduxsub->usbdev, usb_sndctrlpipe(usbduxsub->usbdev, 0), /* brequest, firmware */ USBDUXSUB_FIRMWARE, @@ -806,16 +799,12 @@ static int usbduxsub_upload(struct usbduxsub *usbduxsub, len, /* timeout */ EZTIMEOUT); - dev_dbg(&usbduxsub->interface->dev, - "comedi_: result=%d\n", errcode); - if (errcode < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: upload failed\n"); - return errcode; - } - } else { - /* no device on the bus for this index */ - return -EFAULT; + dev_dbg(&usbduxsub->interface->dev, + "comedi_: result=%d\n", errcode); + if (errcode < 0) { + dev_err(&usbduxsub->interface->dev, + "comedi_: upload failed\n"); + return errcode; } return 0; } @@ -907,8 +896,8 @@ static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub) return 0; } -static int usbdux_ai_cmdtest(comedi_device *dev, comedi_subdevice *s, - comedi_cmd *cmd) +static int usbdux_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd) { int err = 0, tmp, i; unsigned int tmpTimer; @@ -1127,7 +1116,7 @@ static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command) return -EFAULT; } -static int usbdux_ai_inttrig(comedi_device *dev, comedi_subdevice *s, +static int usbdux_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { int ret; @@ -1171,9 +1160,9 @@ static int usbdux_ai_inttrig(comedi_device *dev, comedi_subdevice *s, return 1; } -static int usbdux_ai_cmd(comedi_device *dev, comedi_subdevice *s) +static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - comedi_cmd *cmd = &s->async->cmd; + struct comedi_cmd *cmd = &s->async->cmd; unsigned int chan, range; int i, ret; struct usbduxsub *this_usbduxsub = dev->private; @@ -1287,11 +1276,11 @@ static int usbdux_ai_cmd(comedi_device *dev, comedi_subdevice *s) } /* Mode 0 is used to get a single conversion on demand */ -static int usbdux_ai_insn_read(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int i; - lsampl_t one = 0; + unsigned int one = 0; int chan, range; int err; struct usbduxsub *this_usbduxsub = dev->private; @@ -1348,8 +1337,8 @@ static int usbdux_ai_insn_read(comedi_device *dev, comedi_subdevice *s, /************************************/ /* analog out */ -static int usbdux_ao_insn_read(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int i; int chan = CR_CHAN(insn->chanspec); @@ -1370,8 +1359,8 @@ static int usbdux_ao_insn_read(comedi_device *dev, comedi_subdevice *s, return i; } -static int usbdux_ao_insn_write(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int i, err; int chan = CR_CHAN(insn->chanspec); @@ -1420,7 +1409,7 @@ static int usbdux_ao_insn_write(comedi_device *dev, comedi_subdevice *s, return i; } -static int usbdux_ao_inttrig(comedi_device *dev, comedi_subdevice *s, +static int usbdux_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { int ret; @@ -1461,8 +1450,8 @@ static int usbdux_ao_inttrig(comedi_device *dev, comedi_subdevice *s, return 1; } -static int usbdux_ao_cmdtest(comedi_device *dev, comedi_subdevice *s, - comedi_cmd *cmd) +static int usbdux_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd) { int err = 0, tmp; struct usbduxsub *this_usbduxsub = dev->private; @@ -1600,9 +1589,9 @@ static int usbdux_ao_cmdtest(comedi_device *dev, comedi_subdevice *s, return 0; } -static int usbdux_ao_cmd(comedi_device *dev, comedi_subdevice *s) +static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - comedi_cmd *cmd = &s->async->cmd; + struct comedi_cmd *cmd = &s->async->cmd; unsigned int chan, gain; int i, ret; struct usbduxsub *this_usbduxsub = dev->private; @@ -1708,8 +1697,8 @@ static int usbdux_ao_cmd(comedi_device *dev, comedi_subdevice *s) return 0; } -static int usbdux_dio_insn_config(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int chan = CR_CHAN(insn->chanspec); @@ -1739,8 +1728,8 @@ static int usbdux_dio_insn_config(comedi_device *dev, comedi_subdevice *s, return insn->n; } -static int usbdux_dio_insn_bits(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { struct usbduxsub *this_usbduxsub = dev->private; @@ -1786,8 +1775,8 @@ static int usbdux_dio_insn_bits(comedi_device *dev, comedi_subdevice *s, } /* reads the 4 counters, only two are used just now */ -static int usbdux_counter_read(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_counter_read(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { struct usbduxsub *this_usbduxsub = dev->private; int chan = insn->chanspec; @@ -1820,8 +1809,8 @@ static int usbdux_counter_read(comedi_device *dev, comedi_subdevice *s, return 1; } -static int usbdux_counter_write(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_counter_write(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { struct usbduxsub *this_usbduxsub = dev->private; int err; @@ -1850,8 +1839,8 @@ static int usbdux_counter_write(comedi_device *dev, comedi_subdevice *s, return 1; } -static int usbdux_counter_config(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_counter_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { /* nothing to do so far */ return 2; @@ -1894,7 +1883,7 @@ static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink) } /* force unlink - is called by comedi */ -static int usbdux_pwm_cancel(comedi_device *dev, comedi_subdevice *s) +static int usbdux_pwm_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct usbduxsub *this_usbduxsub = dev->private; int res = 0; @@ -1916,8 +1905,8 @@ static void usbduxsub_pwm_irq(struct urb *urb) { int ret; struct usbduxsub *this_usbduxsub; - comedi_device *this_comedidev; - comedi_subdevice *s; + struct comedi_device *this_comedidev; + struct comedi_subdevice *s; /* printk(KERN_DEBUG "PWM: IRQ\n"); */ @@ -2007,8 +1996,8 @@ static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub) return 0; } -static int usbdux_pwm_period(comedi_device *dev, comedi_subdevice *s, - lsampl_t period) +static int usbdux_pwm_period(struct comedi_device *dev, struct comedi_subdevice *s, + unsigned int period) { struct usbduxsub *this_usbduxsub = dev->private; int fx2delay = 255; @@ -2035,7 +2024,7 @@ static int usbdux_pwm_period(comedi_device *dev, comedi_subdevice *s, } /* is called from insn so there's no need to do all the sanity checks */ -static int usbdux_pwm_start(comedi_device *dev, comedi_subdevice *s) +static int usbdux_pwm_start(struct comedi_device *dev, struct comedi_subdevice *s) { int ret, i; struct usbduxsub *this_usbduxsub = dev->private; @@ -2067,8 +2056,8 @@ static int usbdux_pwm_start(comedi_device *dev, comedi_subdevice *s) } /* generates the bit pattern for PWM with the optional sign bit */ -static int usbdux_pwm_pattern(comedi_device *dev, comedi_subdevice *s, - int channel, lsampl_t value, lsampl_t sign) +static int usbdux_pwm_pattern(struct comedi_device *dev, struct comedi_subdevice *s, + int channel, unsigned int value, unsigned int sign) { struct usbduxsub *this_usbduxsub = dev->private; int i, szbuf; @@ -2108,8 +2097,8 @@ static int usbdux_pwm_pattern(comedi_device *dev, comedi_subdevice *s, return 1; } -static int usbdux_pwm_write(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_pwm_write(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { struct usbduxsub *this_usbduxsub = dev->private; @@ -2133,16 +2122,16 @@ static int usbdux_pwm_write(comedi_device *dev, comedi_subdevice *s, data[0], 0); } -static int usbdux_pwm_read(comedi_device *x1, comedi_subdevice *x2, - comedi_insn *x3, lsampl_t *x4) +static int usbdux_pwm_read(struct comedi_device *x1, struct comedi_subdevice *x2, + struct comedi_insn *x3, unsigned int *x4) { /* not needed */ return -EINVAL; }; /* switches on/off PWM */ -static int usbdux_pwm_config(comedi_device *dev, comedi_subdevice *s, - comedi_insn *insn, lsampl_t *data) +static int usbdux_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { struct usbduxsub *this_usbduxsub = dev->private; switch (data[0]) { @@ -2292,13 +2281,13 @@ static unsigned hex2unsigned(char *h) #define FIRMWARE_MAX_LEN 0x2000 /* taken from David Brownell's fxload and adjusted for this driver */ -static int read_firmware(struct usbduxsub *usbduxsub, void *firmwarePtr, +static int read_firmware(struct usbduxsub *usbduxsub, const void *firmwarePtr, long size) { struct device *dev = &usbduxsub->interface->dev; int i = 0; unsigned char *fp = (char *)firmwarePtr; - unsigned char *firmwareBinary = NULL; + unsigned char *firmwareBinary; int res = 0; int maxAddr = 0; @@ -2322,6 +2311,7 @@ static int read_firmware(struct usbduxsub *usbduxsub, void *firmwarePtr, j++; if (j >= sizeof(buf)) { dev_err(dev, "comedi_: bogus firmware file!\n"); + kfree(firmwareBinary); return -1; } } @@ -2344,6 +2334,7 @@ static int read_firmware(struct usbduxsub *usbduxsub, void *firmwarePtr, if (buf[0] != ':') { dev_err(dev, "comedi_: upload: not an ihex record: %s", buf); + kfree(firmwareBinary); return -EFAULT; } @@ -2360,6 +2351,7 @@ static int read_firmware(struct usbduxsub *usbduxsub, void *firmwarePtr, if (maxAddr >= FIRMWARE_MAX_LEN) { dev_err(dev, "comedi_: firmware upload goes " "beyond FX2 RAM boundaries.\n"); + kfree(firmwareBinary); return -EFAULT; } /* dev_dbg(dev, "comedi_: off=%x, len=%x:\n", off, len); */ @@ -2375,6 +2367,7 @@ static int read_firmware(struct usbduxsub *usbduxsub, void *firmwarePtr, if (type != 0) { dev_err(dev, "comedi_: unsupported record type: %u\n", type); + kfree(firmwareBinary); return -EFAULT; } @@ -2395,6 +2388,34 @@ static int read_firmware(struct usbduxsub *usbduxsub, void *firmwarePtr, return res; } +static void usbdux_firmware_request_complete_handler(const struct firmware *fw, + void *context) +{ + struct usbduxsub *usbduxsub_tmp = context; + struct usb_device *usbdev = usbduxsub_tmp->usbdev; + int ret; + + if (fw == NULL) { + dev_err(&usbdev->dev, + "Firmware complete handler without firmware!\n"); + return; + } + + /* + * we need to upload the firmware here because fw will be + * freed once we've left this function + */ + ret = read_firmware(usbduxsub_tmp, fw->data, fw->size); + + if (ret) { + dev_err(&usbdev->dev, + "Could not upload firmware (err=%d)\n", + ret); + return; + } + comedi_usb_auto_config(usbdev, BOARDNAME); +} + /* allocate memory for the urbs and initialise them */ static int usbduxsub_probe(struct usb_interface *uinterf, const struct usb_device_id *id) @@ -2403,6 +2424,7 @@ static int usbduxsub_probe(struct usb_interface *uinterf, struct device *dev = &uinterf->dev; int i; int index; + int ret; dev_dbg(dev, "comedi_: usbdux_: " "finding a free structure for the usb-device\n"); @@ -2637,6 +2659,19 @@ static int usbduxsub_probe(struct usb_interface *uinterf, /* we've reached the bottom of the function */ usbduxsub[index].probed = 1; up(&start_stop_sem); + + ret = request_firmware_nowait(THIS_MODULE, + FW_ACTION_HOTPLUG, + "usbdux_firmware.hex", + &udev->dev, + usbduxsub + index, + usbdux_firmware_request_complete_handler); + + if (ret) { + dev_err(dev, "Could not load firmware (err=%d)\n", ret); + return ret; + } + dev_info(dev, "comedi_: usbdux%d " "has been successfully initialised.\n", index); /* success */ @@ -2658,6 +2693,7 @@ static void usbduxsub_disconnect(struct usb_interface *intf) "comedi_: BUG! called with wrong ptr!!!\n"); return; } + comedi_usb_auto_unconfig(udev); down(&start_stop_sem); down(&usbduxsub_tmp->sem); tidy_up(usbduxsub_tmp); @@ -2667,14 +2703,14 @@ static void usbduxsub_disconnect(struct usb_interface *intf) } /* is called when comedi-config is called */ -static int usbdux_attach(comedi_device *dev, comedi_devconfig *it) +static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int ret; int index; int i; struct usbduxsub *udev; - comedi_subdevice *s = NULL; + struct comedi_subdevice *s = NULL; dev->private = NULL; down(&start_stop_sem); @@ -2834,7 +2870,7 @@ static int usbdux_attach(comedi_device *dev, comedi_devconfig *it) return 0; } -static int usbdux_detach(comedi_device *dev) +static int usbdux_detach(struct comedi_device *dev) { struct usbduxsub *usbduxsub_tmp; @@ -2867,26 +2903,13 @@ static int usbdux_detach(comedi_device *dev) } /* main driver struct */ -static comedi_driver driver_usbdux = { +static struct comedi_driver driver_usbdux = { .driver_name = "usbdux", .module = THIS_MODULE, .attach = usbdux_attach, .detach = usbdux_detach, }; -static void init_usb_devices(void) -{ - int index; - - /* all devices entries are invalid to begin with */ - /* they will become valid by the probe function */ - /* and then finally by the attach-function */ - for (index = 0; index < NUMUSBDUX; index++) { - memset(&(usbduxsub[index]), 0x00, sizeof(usbduxsub[index])); - init_MUTEX(&(usbduxsub[index].sem)); - } -} - /* Table with the USB-devices: just now only testing IDs */ static struct usb_device_id usbduxsub_table[] = { {USB_DEVICE(0x13d8, 0x0001) }, @@ -2907,18 +2930,17 @@ static struct usb_driver usbduxsub_driver = { /* Can't use the nice macro as I have also to initialise the USB */ /* subsystem: */ /* registering the usb-system _and_ the comedi-driver */ -static int init_usbdux(void) +static int __init init_usbdux(void) { printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC "\n"); - init_usb_devices(); usb_register(&usbduxsub_driver); comedi_driver_register(&driver_usbdux); return 0; } /* deregistering the comedi driver and the usb-subsystem */ -static void exit_usbdux(void) +static void __exit exit_usbdux(void) { comedi_driver_unregister(&driver_usbdux); usb_deregister(&usbduxsub_driver); diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 3a00ff0cfc5a..2fb64de3f86b 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1,33 +1,20 @@ -#define DRIVER_VERSION "v0.99a" -#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" -#define DRIVER_DESC "USB-DUXfast, BerndPorr@f2s.com" /* - comedi/drivers/usbduxfast.c - Copyright (C) 2004 Bernd Porr, Bernd.Porr@f2s.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., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* -Driver: usbduxfast -Description: ITL USB-DUXfast -Devices: [ITL] USB-DUX (usbduxfast.o) -Author: Bernd Porr -Updated: 04 Dec 2006 -Status: testing -*/ + * Copyright (C) 2004 Bernd Porr, Bernd.Porr@f2s.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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ /* * I must give credit here to Chris Baugher who @@ -42,12 +29,16 @@ Status: testing * 0.9: Dropping the first data packet which seems to be from the last transfer. * Buffer overflows in the FX2 are handed over to comedi. * 0.92: Dropping now 4 packets. The quad buffer has to be emptied. - * Added insn command basically for testing. Sample rate is 1MHz/16ch=62.5kHz + * Added insn command basically for testing. Sample rate is + * 1MHz/16ch=62.5kHz * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks! * 0.99a: added external trigger. + * 1.00: added firmware kernel request to the driver which fixed + * udev coldplug problem */ #include +#include #include #include #include @@ -59,536 +50,549 @@ Status: testing #include "comedi_fc.h" #include "../comedidev.h" -// (un)comment this if you want to have debug info. -//#define CONFIG_COMEDI_DEBUG -#undef CONFIG_COMEDI_DEBUG +#define DRIVER_VERSION "v1.0" +#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" +#define DRIVER_DESC "USB-DUXfast, BerndPorr@f2s.com" #define BOARDNAME "usbduxfast" -// timeout for the USB-transfer -#define EZTIMEOUT 30 +/* + * timeout for the USB-transfer + */ +#define EZTIMEOUT 30 -// constants for "firmware" upload and download -#define USBDUXFASTSUB_FIRMWARE 0xA0 -#define VENDOR_DIR_IN 0xC0 -#define VENDOR_DIR_OUT 0x40 +/* + * constants for "firmware" upload and download + */ +#define USBDUXFASTSUB_FIRMWARE 0xA0 +#define VENDOR_DIR_IN 0xC0 +#define VENDOR_DIR_OUT 0x40 -// internal adresses of the 8051 processor -#define USBDUXFASTSUB_CPUCS 0xE600 +/* + * internal adresses of the 8051 processor + */ +#define USBDUXFASTSUB_CPUCS 0xE600 -// max lenghth of the transfer-buffer for software upload -#define TB_LEN 0x2000 +/* + * max lenghth of the transfer-buffer for software upload + */ +#define TB_LEN 0x2000 -// Input endpoint number -#define BULKINEP 6 +/* + * input endpoint number + */ +#define BULKINEP 6 -// Endpoint for the A/D channellist: bulk OUT -#define CHANNELLISTEP 4 +/* + * endpoint for the A/D channellist: bulk OUT + */ +#define CHANNELLISTEP 4 -// Number of channels -#define NUMCHANNELS 32 +/* + * number of channels + */ +#define NUMCHANNELS 32 -// size of the waveform descriptor -#define WAVESIZE 0x20 +/* + * size of the waveform descriptor + */ +#define WAVESIZE 0x20 -// Size of one A/D value -#define SIZEADIN ((sizeof(int16_t))) +/* + * size of one A/D value + */ +#define SIZEADIN (sizeof(int16_t)) -// Size of the input-buffer IN BYTES -#define SIZEINBUF 512 +/* + * size of the input-buffer IN BYTES + */ +#define SIZEINBUF 512 -// 16 bytes. -#define SIZEINSNBUF 512 +/* + * 16 bytes + */ +#define SIZEINSNBUF 512 -// Size of the buffer for the dux commands -#define SIZEOFDUXBUFFER 256 // bytes +/* + * size of the buffer for the dux commands in bytes + */ +#define SIZEOFDUXBUFFER 256 -// Number of in-URBs which receive the data: min=5 -#define NUMOFINBUFFERSHIGH 10 +/* + * number of in-URBs which receive the data: min=5 + */ +#define NUMOFINBUFFERSHIGH 10 -// Total number of usbduxfast devices -#define NUMUSBDUXFAST 16 +/* + * total number of usbduxfast devices + */ +#define NUMUSBDUXFAST 16 -// Number of subdevices -#define N_SUBDEVICES 1 +/* + * number of subdevices + */ +#define N_SUBDEVICES 1 -// Analogue in subdevice -#define SUBDEV_AD 0 +/* + * analogue in subdevice + */ +#define SUBDEV_AD 0 -// min delay steps for more than one channel -// basically when the mux gives up. ;-) -#define MIN_SAMPLING_PERIOD 9 // steps at 30MHz in the FX2 +/* + * min delay steps for more than one channel + * basically when the mux gives up ;-) + * + * steps at 30MHz in the FX2 + */ +#define MIN_SAMPLING_PERIOD 9 -// Max number of 1/30MHz delay steps: -#define MAX_SAMPLING_PERIOD 500 +/* + * max number of 1/30MHz delay steps + */ +#define MAX_SAMPLING_PERIOD 500 -// Number of received packets to ignore before we start handing data over to comedi. -// It's quad buffering and we have to ignore 4 packets. -#define PACKETS_TO_IGNORE 4 +/* + * number of received packets to ignore before we start handing data + * over to comedi, it's quad buffering and we have to ignore 4 packets + */ +#define PACKETS_TO_IGNORE 4 -///////////////////////////////////////////// -// comedi constants -static const comedi_lrange range_usbduxfast_ai_range = { 2, { - BIP_RANGE(0.75), - BIP_RANGE(0.5), - } +/* + * comedi constants + */ +static const struct comedi_lrange range_usbduxfast_ai_range = { + 2, { BIP_RANGE(0.75), BIP_RANGE(0.5) } }; /* * private structure of one subdevice + * + * this is the structure which holds all the data of this driver + * one sub device just now: A/D */ - -// This is the structure which holds all the data of this driver -// one sub device just now: A/D -typedef struct { - // attached? - int attached; - // is it associated with a subdevice? - int probed; - // pointer to the usb-device - struct usb_device *usbdev; - // BULK-transfer handling: urb - struct urb *urbIn; +struct usbduxfastsub_s { + int attached; /* is attached? */ + int probed; /* is it associated with a subdevice? */ + struct usb_device *usbdev; /* pointer to the usb-device */ + struct urb *urbIn; /* BULK-transfer handling: urb */ int8_t *transfer_buffer; - // input buffer for single insn - int16_t *insnBuffer; - // interface number - int ifnum; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - // interface structure in 2.6 - struct usb_interface *interface; -#endif - // comedi device for the interrupt context - comedi_device *comedidev; - // asynchronous command is running - short int ai_cmd_running; - // continous aquisition - short int ai_continous; - // number of samples to aquire - long int ai_sample_count; - // commands - uint8_t *dux_commands; - // counter which ignores the first buffers - int ignore; + int16_t *insnBuffer; /* input buffer for single insn */ + int ifnum; /* interface number */ + struct usb_interface *interface; /* interface structure */ + struct comedi_device *comedidev; /* comedi device for the interrupt + context */ + short int ai_cmd_running; /* asynchronous command is running */ + short int ai_continous; /* continous aquisition */ + long int ai_sample_count; /* number of samples to aquire */ + uint8_t *dux_commands; /* commands */ + int ignore; /* counter which ignores the first + buffers */ struct semaphore sem; -} usbduxfastsub_t; +}; -// The pointer to the private usb-data of the driver -// is also the private data for the comedi-device. -// This has to be global as the usb subsystem needs -// global variables. The other reason is that this -// structure must be there _before_ any comedi -// command is issued. The usb subsystem must be -// initialised before comedi can access it. -static usbduxfastsub_t usbduxfastsub[NUMUSBDUXFAST]; +/* + * The pointer to the private usb-data of the driver + * is also the private data for the comedi-device. + * This has to be global as the usb subsystem needs + * global variables. The other reason is that this + * structure must be there _before_ any comedi + * command is issued. The usb subsystem must be + * initialised before comedi can access it. + */ +static struct usbduxfastsub_s usbduxfastsub[NUMUSBDUXFAST]; static DECLARE_MUTEX(start_stop_sem); -// bulk transfers to usbduxfast - +/* + * bulk transfers to usbduxfast + */ #define SENDADCOMMANDS 0 #define SENDINITEP6 1 -static int send_dux_commands(usbduxfastsub_t * this_usbduxfastsub, int cmd_type) +static int send_dux_commands(struct usbduxfastsub_s *udfs, int cmd_type) { - int result, nsent; - this_usbduxfastsub->dux_commands[0] = cmd_type; + int tmp, nsent; + + udfs->dux_commands[0] = cmd_type; + #ifdef CONFIG_COMEDI_DEBUG - int i; - printk("comedi%d: usbduxfast: dux_commands: ", - this_usbduxfastsub->comedidev->minor); - for (i = 0; i < SIZEOFDUXBUFFER; i++) { - printk(" %02x", this_usbduxfastsub->dux_commands[i]); - } + printk(KERN_DEBUG "comedi%d: usbduxfast: dux_commands: ", + udfs->comedidev->minor); + for (tmp = 0; tmp < SIZEOFDUXBUFFER; tmp++) + printk(" %02x", udfs->dux_commands[tmp]); printk("\n"); #endif - result = usb_bulk_msg(this_usbduxfastsub->usbdev, - usb_sndbulkpipe(this_usbduxfastsub->usbdev, - CHANNELLISTEP), - this_usbduxfastsub->dux_commands, SIZEOFDUXBUFFER, - &nsent, 10000); - if (result < 0) { - printk("comedi%d: could not transmit dux_commands to the usb-device, err=%d\n", this_usbduxfastsub->comedidev->minor, result); - } - return result; + + tmp = usb_bulk_msg(udfs->usbdev, + usb_sndbulkpipe(udfs->usbdev, CHANNELLISTEP), + udfs->dux_commands, SIZEOFDUXBUFFER, &nsent, 10000); + if (tmp < 0) + printk(KERN_ERR "comedi%d: could not transmit dux_commands to" + "the usb-device, err=%d\n", udfs->comedidev->minor, tmp); + return tmp; } -// Stops the data acquision -// It should be safe to call this function from any context -static int usbduxfastsub_unlink_InURBs(usbduxfastsub_t * usbduxfastsub_tmp) +/* + * Stops the data acquision. + * It should be safe to call this function from any context. + */ +static int usbduxfastsub_unlink_InURBs(struct usbduxfastsub_s *udfs) { int j = 0; int err = 0; - if (usbduxfastsub_tmp && usbduxfastsub_tmp->urbIn) { - usbduxfastsub_tmp->ai_cmd_running = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) - j = usb_unlink_urb(usbduxfastsub_tmp->urbIn); - if (j < 0) { - err = j; - } -#else - // waits until a running transfer is over - usb_kill_urb(usbduxfastsub_tmp->urbIn); + if (udfs && udfs->urbIn) { + udfs->ai_cmd_running = 0; + /* waits until a running transfer is over */ + usb_kill_urb(udfs->urbIn); j = 0; -#endif } #ifdef CONFIG_COMEDI_DEBUG - printk("comedi: usbduxfast: unlinked InURB: res=%d\n", j); + printk(KERN_DEBUG "comedi: usbduxfast: unlinked InURB: res=%d\n", j); #endif return err; } -/* This will stop a running acquisition operation */ -// Is called from within this driver from both the -// interrupt context and from comedi -static int usbduxfast_ai_stop(usbduxfastsub_t * this_usbduxfastsub, +/* + * This will stop a running acquisition operation. + * Is called from within this driver from both the + * interrupt context and from comedi. + */ +static int usbduxfast_ai_stop(struct usbduxfastsub_s *udfs, int do_unlink) { int ret = 0; - if (!this_usbduxfastsub) { - printk("comedi?: usbduxfast_ai_stop: this_usbduxfastsub=NULL!\n"); + if (!udfs) { + printk(KERN_ERR "comedi?: usbduxfast_ai_stop: udfs=NULL!\n"); return -EFAULT; } + #ifdef CONFIG_COMEDI_DEBUG - printk("comedi: usbduxfast_ai_stop\n"); + printk(KERN_DEBUG "comedi: usbduxfast_ai_stop\n"); #endif - this_usbduxfastsub->ai_cmd_running = 0; + udfs->ai_cmd_running = 0; - if (do_unlink) { - // stop aquistion - ret = usbduxfastsub_unlink_InURBs(this_usbduxfastsub); - } + if (do_unlink) + ret = usbduxfastsub_unlink_InURBs(udfs); /* stop aquistion */ return ret; } -// This will cancel a running acquisition operation. -// This is called by comedi but never from inside the -// driver. -static int usbduxfast_ai_cancel(comedi_device * dev, comedi_subdevice * s) +/* + * This will cancel a running acquisition operation. + * This is called by comedi but never from inside the driver. + */ +static int usbduxfast_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - usbduxfastsub_t *this_usbduxfastsub; - int res = 0; + struct usbduxfastsub_s *udfs; + int ret; - // force unlink of all urbs + /* force unlink of all urbs */ #ifdef CONFIG_COMEDI_DEBUG - printk("comedi: usbduxfast_ai_cancel\n"); + printk(KERN_DEBUG "comedi: usbduxfast_ai_cancel\n"); #endif - this_usbduxfastsub = dev->private; - if (!this_usbduxfastsub) { - printk("comedi: usbduxfast_ai_cancel: this_usbduxfastsub=NULL\n"); + udfs = dev->private; + if (!udfs) { + printk(KERN_ERR "comedi: usbduxfast_ai_cancel: udfs=NULL\n"); return -EFAULT; } - down(&this_usbduxfastsub->sem); - if (!(this_usbduxfastsub->probed)) { - up(&this_usbduxfastsub->sem); + down(&udfs->sem); + if (!udfs->probed) { + up(&udfs->sem); return -ENODEV; } - // unlink - res = usbduxfast_ai_stop(this_usbduxfastsub, 1); - up(&this_usbduxfastsub->sem); + /* unlink */ + ret = usbduxfast_ai_stop(udfs, 1); + up(&udfs->sem); - return res; + return ret; } -// analogue IN -// interrupt service routine -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static void usbduxfastsub_ai_Irq(struct urb *urb) -#else +/* + * analogue IN + * interrupt service routine + */ static void usbduxfastsub_ai_Irq(struct urb *urb PT_REGS_ARG) -#endif { int n, err; - usbduxfastsub_t *this_usbduxfastsub; - comedi_device *this_comedidev; - comedi_subdevice *s; + struct usbduxfastsub_s *udfs; + struct comedi_device *this_comedidev; + struct comedi_subdevice *s; uint16_t *p; - // sanity checks - // is the urb there? + /* sanity checks - is the urb there? */ if (!urb) { - printk("comedi_: usbduxfast_: ao int-handler called with urb=NULL!\n"); + printk(KERN_ERR "comedi_: usbduxfast_: ao int-handler called " + "with urb=NULL!\n"); return; } - // the context variable points to the subdevice + /* the context variable points to the subdevice */ this_comedidev = urb->context; if (!this_comedidev) { - printk("comedi_: usbduxfast_: urb context is a NULL pointer!\n"); + printk(KERN_ERR "comedi_: usbduxfast_: urb context is a NULL " + "pointer!\n"); return; } - // the private structure of the subdevice is usbduxfastsub_t - this_usbduxfastsub = this_comedidev->private; - if (!this_usbduxfastsub) { - printk("comedi_: usbduxfast_: private of comedi subdev is a NULL pointer!\n"); + /* the private structure of the subdevice is usbduxfastsub_s */ + udfs = this_comedidev->private; + if (!udfs) { + printk(KERN_ERR "comedi_: usbduxfast_: private of comedi " + "subdev is a NULL pointer!\n"); return; } - // are we running a command? - if (unlikely(!(this_usbduxfastsub->ai_cmd_running))) { - // not running a command - // do not continue execution if no asynchronous command is running - // in particular not resubmit + /* are we running a command? */ + if (unlikely(!udfs->ai_cmd_running)) { + /* + * not running a command + * do not continue execution if no asynchronous command + * is running in particular not resubmit + */ return; } - if (unlikely(!(this_usbduxfastsub->attached))) { - // no comedi device there + if (unlikely(!udfs->attached)) { + /* no comedi device there */ return; } - // subdevice which is the AD converter + /* subdevice which is the AD converter */ s = this_comedidev->subdevices + SUBDEV_AD; - // first we test if something unusual has just happened + /* first we test if something unusual has just happened */ switch (urb->status) { case 0: break; - // happens after an unlink command or when the device is plugged out + /* + * happens after an unlink command or when the device + * is plugged out + */ case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: case -ECONNABORTED: - // tell this comedi + /* tell this comedi */ s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxfastsub->comedidev, s); - // stop the transfer w/o unlink - usbduxfast_ai_stop(this_usbduxfastsub, 0); + comedi_event(udfs->comedidev, s); + /* stop the transfer w/o unlink */ + usbduxfast_ai_stop(udfs, 0); return; default: - printk("comedi%d: usbduxfast: non-zero urb status received in ai intr context: %d\n", this_usbduxfastsub->comedidev->minor, urb->status); + printk("comedi%d: usbduxfast: non-zero urb status received in " + "ai intr context: %d\n", + udfs->comedidev->minor, urb->status); s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxfastsub->comedidev, s); - usbduxfast_ai_stop(this_usbduxfastsub, 0); + comedi_event(udfs->comedidev, s); + usbduxfast_ai_stop(udfs, 0); return; } p = urb->transfer_buffer; - if (!this_usbduxfastsub->ignore) { - if (!(this_usbduxfastsub->ai_continous)) { - // not continous, fixed number of samples + if (!udfs->ignore) { + if (!udfs->ai_continous) { + /* not continous, fixed number of samples */ n = urb->actual_length / sizeof(uint16_t); - if (unlikely(this_usbduxfastsub->ai_sample_count < n)) { - // we have send only a fraction of the bytes received + if (unlikely(udfs->ai_sample_count < n)) { + /* + * we have send only a fraction of the bytes + * received + */ cfc_write_array_to_buffer(s, urb->transfer_buffer, - this_usbduxfastsub->ai_sample_count * - sizeof(uint16_t)); - usbduxfast_ai_stop(this_usbduxfastsub, 0); - // say comedi that the acquistion is over + udfs->ai_sample_count + * sizeof(uint16_t)); + usbduxfast_ai_stop(udfs, 0); + /* say comedi that the acquistion is over */ s->async->events |= COMEDI_CB_EOA; - comedi_event(this_usbduxfastsub->comedidev, s); + comedi_event(udfs->comedidev, s); return; } - this_usbduxfastsub->ai_sample_count -= n; + udfs->ai_sample_count -= n; } - // write the full buffer to comedi - cfc_write_array_to_buffer(s, - urb->transfer_buffer, urb->actual_length); + /* write the full buffer to comedi */ + cfc_write_array_to_buffer(s, urb->transfer_buffer, + urb->actual_length); - // tell comedi that data is there - comedi_event(this_usbduxfastsub->comedidev, s); + /* tell comedi that data is there */ + comedi_event(udfs->comedidev, s); } else { - // ignore this packet - this_usbduxfastsub->ignore--; + /* ignore this packet */ + udfs->ignore--; } - // command is still running - // resubmit urb for BULK transfer - urb->dev = this_usbduxfastsub->usbdev; + /* + * command is still running + * resubmit urb for BULK transfer + */ + urb->dev = udfs->usbdev; urb->status = 0; err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { - printk("comedi%d: usbduxfast: urb resubm failed: %d", - this_usbduxfastsub->comedidev->minor, err); + printk(KERN_ERR "comedi%d: usbduxfast: urb resubm failed: %d", + udfs->comedidev->minor, err); s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxfastsub->comedidev, s); - usbduxfast_ai_stop(this_usbduxfastsub, 0); + comedi_event(udfs->comedidev, s); + usbduxfast_ai_stop(udfs, 0); } } -static int usbduxfastsub_start(usbduxfastsub_t * usbduxfastsub) +static int usbduxfastsub_start(struct usbduxfastsub_s *udfs) { - int errcode = 0; + int ret; unsigned char local_transfer_buffer[16]; - if (usbduxfastsub->probed) { - // 7f92 to zero - local_transfer_buffer[0] = 0; - errcode = usb_control_msg(usbduxfastsub->usbdev, - // create a pipe for a control transfer - usb_sndctrlpipe(usbduxfastsub->usbdev, 0), - // bRequest, "Firmware" - USBDUXFASTSUB_FIRMWARE, - // bmRequestType - VENDOR_DIR_OUT, - // Value - USBDUXFASTSUB_CPUCS, - // Index - 0x0000, - // address of the transfer buffer - local_transfer_buffer, - // Length - 1, - // Timeout - EZTIMEOUT); - if (errcode < 0) { - printk("comedi_: usbduxfast_: control msg failed (start)\n"); - return errcode; - } + /* 7f92 to zero */ + local_transfer_buffer[0] = 0; + ret = usb_control_msg(udfs->usbdev, + usb_sndctrlpipe(udfs->usbdev, 0), + USBDUXFASTSUB_FIRMWARE, /* bRequest, "Firmware" */ + VENDOR_DIR_OUT, /* bmRequestType */ + USBDUXFASTSUB_CPUCS, /* Value */ + 0x0000, /* Index */ + local_transfer_buffer, /* address of the transfer buffer */ + 1, /* Length */ + EZTIMEOUT); /* Timeout */ + if (ret < 0) { + printk("comedi_: usbduxfast_: control msg failed (start)\n"); + return ret; } + return 0; } -static int usbduxfastsub_stop(usbduxfastsub_t * usbduxfastsub) +static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs) { - int errcode = 0; - + int ret; unsigned char local_transfer_buffer[16]; - if (usbduxfastsub->probed) { - // 7f92 to one - local_transfer_buffer[0] = 1; - errcode = usb_control_msg(usbduxfastsub->usbdev, - usb_sndctrlpipe(usbduxfastsub->usbdev, 0), - // bRequest, "Firmware" - USBDUXFASTSUB_FIRMWARE, - // bmRequestType - VENDOR_DIR_OUT, - // Value - USBDUXFASTSUB_CPUCS, - // Index - 0x0000, local_transfer_buffer, - // Length - 1, - // Timeout - EZTIMEOUT); - if (errcode < 0) { - printk("comedi_: usbduxfast: control msg failed (stop)\n"); - return errcode; - } + + /* 7f92 to one */ + local_transfer_buffer[0] = 1; + ret = usb_control_msg(udfs->usbdev, + usb_sndctrlpipe(udfs->usbdev, 0), + USBDUXFASTSUB_FIRMWARE, /* bRequest, "Firmware" */ + VENDOR_DIR_OUT, /* bmRequestType */ + USBDUXFASTSUB_CPUCS, /* Value */ + 0x0000, /* Index */ + local_transfer_buffer, + 1, /* Length */ + EZTIMEOUT); /* Timeout */ + if (ret < 0) { + printk(KERN_ERR "comedi_: usbduxfast: control msg failed " + "(stop)\n"); + return ret; } + return 0; } -static int usbduxfastsub_upload(usbduxfastsub_t * usbduxfastsub, +static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs, unsigned char *local_transfer_buffer, unsigned int startAddr, unsigned int len) { - int errcode; + int ret; - if (usbduxfastsub->probed) { #ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: usbduxfast: uploading %d bytes", - usbduxfastsub->comedidev->minor, len); - printk(" to addr %d, first byte=%d.\n", - startAddr, local_transfer_buffer[0]); + printk(KERN_DEBUG "comedi: usbduxfast: uploading %d bytes", len); + printk(KERN_DEBUG " to addr %d, first byte=%d.\n", + startAddr, local_transfer_buffer[0]); #endif - errcode = usb_control_msg(usbduxfastsub->usbdev, - usb_sndctrlpipe(usbduxfastsub->usbdev, 0), - // brequest, firmware - USBDUXFASTSUB_FIRMWARE, - // bmRequestType - VENDOR_DIR_OUT, - // value - startAddr, - // index - 0x0000, - // our local safe buffer - local_transfer_buffer, - // length - len, - // timeout - EZTIMEOUT); + ret = usb_control_msg(udfs->usbdev, + usb_sndctrlpipe(udfs->usbdev, 0), + USBDUXFASTSUB_FIRMWARE, /* brequest, firmware */ + VENDOR_DIR_OUT, /* bmRequestType */ + startAddr, /* value */ + 0x0000, /* index */ + local_transfer_buffer, /* our local safe buffer */ + len, /* length */ + EZTIMEOUT); /* timeout */ + #ifdef CONFIG_COMEDI_DEBUG - printk("comedi_: usbduxfast: result=%d\n", errcode); + printk(KERN_DEBUG "comedi_: usbduxfast: result=%d\n", ret); #endif - if (errcode < 0) { - printk("comedi_: usbduxfast: uppload failed\n"); - return errcode; - } - } else { - // no device on the bus for this index - return -EFAULT; + + if (ret < 0) { + printk(KERN_ERR "comedi_: usbduxfast: uppload failed\n"); + return ret; } + return 0; } -int firmwareUpload(usbduxfastsub_t * usbduxfastsub, - unsigned char *firmwareBinary, int sizeFirmware) +int firmwareUpload(struct usbduxfastsub_s *udfs, unsigned char *firmwareBinary, + int sizeFirmware) { int ret; - if (!firmwareBinary) { + if (!firmwareBinary) return 0; - } - ret = usbduxfastsub_stop(usbduxfastsub); + + ret = usbduxfastsub_stop(udfs); if (ret < 0) { - printk("comedi_: usbduxfast: can not stop firmware\n"); + printk(KERN_ERR "comedi_: usbduxfast: can not stop firmware\n"); return ret; } - ret = usbduxfastsub_upload(usbduxfastsub, - firmwareBinary, 0, sizeFirmware); + ret = usbduxfastsub_upload(udfs, firmwareBinary, 0, sizeFirmware); if (ret < 0) { - printk("comedi_: usbduxfast: firmware upload failed\n"); + printk(KERN_ERR "comedi_: usbduxfast: firmware upload failed\n"); return ret; } - ret = usbduxfastsub_start(usbduxfastsub); + ret = usbduxfastsub_start(udfs); if (ret < 0) { - printk("comedi_: usbduxfast: can not start firmware\n"); + printk(KERN_ERR "comedi_: usbduxfast: can not start firmware\n"); return ret; } + return 0; } -int usbduxfastsub_submit_InURBs(usbduxfastsub_t * usbduxfastsub) +int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs) { - int errFlag; + int ret; - if (!usbduxfastsub) { + if (!udfs) return -EFAULT; - } - usb_fill_bulk_urb(usbduxfastsub->urbIn, - usbduxfastsub->usbdev, - usb_rcvbulkpipe(usbduxfastsub->usbdev, BULKINEP), - usbduxfastsub->transfer_buffer, - SIZEINBUF, usbduxfastsub_ai_Irq, usbduxfastsub->comedidev); + + usb_fill_bulk_urb(udfs->urbIn, udfs->usbdev, + usb_rcvbulkpipe(udfs->usbdev, BULKINEP), + udfs->transfer_buffer, + SIZEINBUF, usbduxfastsub_ai_Irq, udfs->comedidev); #ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: usbduxfast: submitting in-urb: %x,%x\n", - usbduxfastsub->comedidev->minor, - (int)(usbduxfastsub->urbIn->context), - (int)(usbduxfastsub->urbIn->dev)); + printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: " + "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context, + udfs->urbIn->dev); #endif - errFlag = usb_submit_urb(usbduxfastsub->urbIn, GFP_ATOMIC); - if (errFlag) { - printk("comedi_: usbduxfast: ai: usb_submit_urb error %d\n", - errFlag); - return errFlag; + ret = usb_submit_urb(udfs->urbIn, GFP_ATOMIC); + if (ret) { + printk(KERN_ERR "comedi_: usbduxfast: ai: usb_submit_urb error" + " %d\n", ret); + return ret; } return 0; } -static int usbduxfast_ai_cmdtest(comedi_device * dev, - comedi_subdevice * s, comedi_cmd * cmd) +static int usbduxfast_ai_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_cmd *cmd) { int err = 0, stop_mask = 0; - long int steps, tmp = 0; + long int steps, tmp; int minSamplPer; - usbduxfastsub_t *this_usbduxfastsub = dev->private; - if (!(this_usbduxfastsub->probed)) { + struct usbduxfastsub_s *udfs = dev->private; + + if (!udfs->probed) return -ENODEV; - } + #ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: usbduxfast_ai_cmdtest\n", dev->minor); - printk("comedi%d: usbduxfast: convert_arg=%u scan_begin_arg=%u\n", - dev->minor, cmd->convert_arg, cmd->scan_begin_arg); + printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmdtest\n", dev->minor); + printk(KERN_DEBUG "comedi%d: usbduxfast: convert_arg=%u " + "scan_begin_arg=%u\n", + dev->minor, cmd->convert_arg, cmd->scan_begin_arg); #endif /* step 1: make sure trigger sources are trivially valid */ @@ -621,7 +625,9 @@ static int usbduxfast_ai_cmdtest(comedi_device * dev, if (err) return 1; - /* step 2: make sure trigger sources are unique and mutually compatible */ + /* + * step 2: make sure trigger sources are unique and mutually compatible + */ if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_INT) @@ -636,7 +642,7 @@ static int usbduxfast_ai_cmdtest(comedi_device * dev, cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE) err++; - // can't have external stop and start triggers at once + /* can't have external stop and start triggers at once */ if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT) err++; @@ -650,29 +656,28 @@ static int usbduxfast_ai_cmdtest(comedi_device * dev, err++; } - if (!cmd->chanlist_len) { + if (!cmd->chanlist_len) err++; - } + if (cmd->scan_end_arg != cmd->chanlist_len) { cmd->scan_end_arg = cmd->chanlist_len; err++; } - if (cmd->chanlist_len == 1) { + if (cmd->chanlist_len == 1) minSamplPer = 1; - } else { + else minSamplPer = MIN_SAMPLING_PERIOD; - } if (cmd->convert_src == TRIG_TIMER) { steps = cmd->convert_arg * 30; - if (steps < (minSamplPer * 1000)) { + if (steps < (minSamplPer * 1000)) steps = minSamplPer * 1000; - } - if (steps > (MAX_SAMPLING_PERIOD * 1000)) { + + if (steps > (MAX_SAMPLING_PERIOD * 1000)) steps = MAX_SAMPLING_PERIOD * 1000; - } - // calc arg again + + /* calc arg again */ tmp = steps / 30; if (cmd->convert_arg != tmp) { cmd->convert_arg = tmp; @@ -680,10 +685,10 @@ static int usbduxfast_ai_cmdtest(comedi_device * dev, } } - if (cmd->scan_begin_src == TRIG_TIMER) { + if (cmd->scan_begin_src == TRIG_TIMER) err++; - } - // stop source + + /* stop source */ switch (cmd->stop_src) { case TRIG_COUNT: if (!cmd->stop_arg) { @@ -697,7 +702,10 @@ static int usbduxfast_ai_cmdtest(comedi_device * dev, err++; } break; - // TRIG_EXT doesn't care since it doesn't trigger off a numbered channel + /* + * TRIG_EXT doesn't care since it doesn't trigger + * off a numbered channel + */ default: break; } @@ -711,600 +719,688 @@ static int usbduxfast_ai_cmdtest(comedi_device * dev, } -static int usbduxfast_ai_inttrig(comedi_device * dev, - comedi_subdevice * s, unsigned int trignum) +static int usbduxfast_ai_inttrig(struct comedi_device *dev, + struct comedi_subdevice *s, unsigned int trignum) { int ret; - usbduxfastsub_t *this_usbduxfastsub = dev->private; - if (!this_usbduxfastsub) { + struct usbduxfastsub_s *udfs = dev->private; + + if (!udfs) return -EFAULT; - } - down(&this_usbduxfastsub->sem); - if (!(this_usbduxfastsub->probed)) { - up(&this_usbduxfastsub->sem); + + down(&udfs->sem); + if (!udfs->probed) { + up(&udfs->sem); return -ENODEV; } #ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: usbduxfast_ai_inttrig\n", dev->minor); + printk(KERN_DEBUG "comedi%d: usbduxfast_ai_inttrig\n", dev->minor); #endif if (trignum != 0) { - printk("comedi%d: usbduxfast_ai_inttrig: invalid trignum\n", - dev->minor); - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: invalid" + " trignum\n", dev->minor); + up(&udfs->sem); return -EINVAL; } - if (!(this_usbduxfastsub->ai_cmd_running)) { - this_usbduxfastsub->ai_cmd_running = 1; - ret = usbduxfastsub_submit_InURBs(this_usbduxfastsub); + if (!udfs->ai_cmd_running) { + udfs->ai_cmd_running = 1; + ret = usbduxfastsub_submit_InURBs(udfs); if (ret < 0) { - printk("comedi%d: usbduxfast_ai_inttrig: urbSubmit: err=%d\n", dev->minor, ret); - this_usbduxfastsub->ai_cmd_running = 0; - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: " + "urbSubmit: err=%d\n", dev->minor, ret); + udfs->ai_cmd_running = 0; + up(&udfs->sem); return ret; } s->async->inttrig = NULL; } else { - printk("comedi%d: ai_inttrig but acqu is already running\n", - dev->minor); + printk(KERN_ERR "comedi%d: ai_inttrig but acqu is already" + " running\n", dev->minor); } - up(&this_usbduxfastsub->sem); + up(&udfs->sem); return 1; } -// offsets for the GPIF bytes -// the first byte is the command byte -#define LENBASE 1+0x00 -#define OPBASE 1+0x08 -#define OUTBASE 1+0x10 -#define LOGBASE 1+0x18 +/* + * offsets for the GPIF bytes + * the first byte is the command byte + */ +#define LENBASE (1+0x00) +#define OPBASE (1+0x08) +#define OUTBASE (1+0x10) +#define LOGBASE (1+0x18) -static int usbduxfast_ai_cmd(comedi_device * dev, comedi_subdevice * s) +static int usbduxfast_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - comedi_cmd *cmd = &s->async->cmd; + struct comedi_cmd *cmd = &s->async->cmd; unsigned int chan, gain, rngmask = 0xff; int i, j, ret; - usbduxfastsub_t *this_usbduxfastsub = dev->private; + struct usbduxfastsub_s *udfs; int result; long steps, steps_tmp; #ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: usbduxfast_ai_cmd\n", dev->minor); + printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmd\n", dev->minor); #endif - if (!this_usbduxfastsub) { + udfs = dev->private; + if (!udfs) return -EFAULT; - } - down(&this_usbduxfastsub->sem); - if (!(this_usbduxfastsub->probed)) { - up(&this_usbduxfastsub->sem); + + down(&udfs->sem); + if (!udfs->probed) { + up(&udfs->sem); return -ENODEV; } - if (this_usbduxfastsub->ai_cmd_running) { - printk("comedi%d: ai_cmd not possible. Another ai_cmd is running.\n", dev->minor); - up(&this_usbduxfastsub->sem); + if (udfs->ai_cmd_running) { + printk(KERN_ERR "comedi%d: ai_cmd not possible. Another ai_cmd" + " is running.\n", dev->minor); + up(&udfs->sem); return -EBUSY; } - // set current channel of the running aquisition to zero + /* set current channel of the running aquisition to zero */ s->async->cur_chan = 0; - // ignore the first buffers from the device if there is an error condition - this_usbduxfastsub->ignore = PACKETS_TO_IGNORE; + /* + * ignore the first buffers from the device if there + * is an error condition + */ + udfs->ignore = PACKETS_TO_IGNORE; if (cmd->chanlist_len > 0) { gain = CR_RANGE(cmd->chanlist[0]); for (i = 0; i < cmd->chanlist_len; ++i) { chan = CR_CHAN(cmd->chanlist[i]); if (chan != i) { - printk("comedi%d: cmd is accepting only consecutive channels.\n", dev->minor); - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: cmd is accepting " + "only consecutive channels.\n", + dev->minor); + up(&udfs->sem); return -EINVAL; } if ((gain != CR_RANGE(cmd->chanlist[i])) && (cmd->chanlist_len > 3)) { - printk("comedi%d: the gain must be the same for all channels.\n", dev->minor); - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: the gain must be" + " the same for all channels.\n", + dev->minor); + up(&udfs->sem); return -EINVAL; } if (i >= NUMCHANNELS) { - printk("comedi%d: channel list too long\n", - dev->minor); + printk(KERN_ERR "comedi%d: channel list too" + " long\n", dev->minor); break; } } } steps = 0; if (cmd->scan_begin_src == TRIG_TIMER) { - printk("comedi%d: usbduxfast: scan_begin_src==TRIG_TIMER not valid.\n", dev->minor); - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: usbduxfast: " + "scan_begin_src==TRIG_TIMER not valid.\n", dev->minor); + up(&udfs->sem); return -EINVAL; } - if (cmd->convert_src == TRIG_TIMER) { + if (cmd->convert_src == TRIG_TIMER) steps = (cmd->convert_arg * 30) / 1000; - } + if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) { - printk("comedi%d: usbduxfast: ai_cmd: steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n", dev->minor, steps, cmd->scan_begin_arg); - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: steps=%ld, " + "scan_begin_arg=%d. Not properly tested by cmdtest?\n", + dev->minor, steps, cmd->scan_begin_arg); + up(&udfs->sem); return -EINVAL; } if (steps > MAX_SAMPLING_PERIOD) { - printk("comedi%d: usbduxfast: ai_cmd: sampling rate too low.\n", - dev->minor); - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: sampling rate " + "too low.\n", dev->minor); + up(&udfs->sem); return -EINVAL; } if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1) && (cmd->chanlist_len != 16)) { - printk("comedi%d: usbduxfast: ai_cmd: TRIG_EXT only with 1 or 16 channels possible.\n", dev->minor); - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: TRIG_EXT only" + " with 1 or 16 channels possible.\n", dev->minor); + up(&udfs->sem); return -EINVAL; } #ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: usbduxfast: steps=%ld, convert_arg=%u, ai_timer=%u\n", - dev->minor, - steps, cmd->convert_arg, this_usbduxfastsub->ai_timer); + printk(KERN_DEBUG "comedi%d: usbduxfast: steps=%ld, convert_arg=%u\n", + dev->minor, steps, cmd->convert_arg); #endif switch (cmd->chanlist_len) { - // one channel case 1: + /* + * one channel + */ + if (CR_RANGE(cmd->chanlist[0]) > 0) rngmask = 0xff - 0x04; else rngmask = 0xff; - // for external trigger: looping in this state until the RDY0 pin - // becomes zero - if (cmd->start_src == TRIG_EXT) { // we loop here until ready has been set - this_usbduxfastsub->dux_commands[LENBASE + 0] = 0x01; // branch back to state 0 - this_usbduxfastsub->dux_commands[OPBASE + 0] = 0x01; // deceision state w/o data - this_usbduxfastsub->dux_commands[OUTBASE + 0] = - 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0x00; // RDY0 = 0 - } else { // we just proceed to state 1 - this_usbduxfastsub->dux_commands[LENBASE + 0] = 1; - this_usbduxfastsub->dux_commands[OPBASE + 0] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 0] = - 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0; + /* + * for external trigger: looping in this state until + * the RDY0 pin becomes zero + */ + + /* we loop here until ready has been set */ + if (cmd->start_src == TRIG_EXT) { + /* branch back to state 0 */ + udfs->dux_commands[LENBASE+0] = 0x01; + /* deceision state w/o data */ + udfs->dux_commands[OPBASE+0] = 0x01; + udfs->dux_commands[OUTBASE+0] = 0xFF & rngmask; + /* RDY0 = 0 */ + udfs->dux_commands[LOGBASE+0] = 0x00; + } else { /* we just proceed to state 1 */ + udfs->dux_commands[LENBASE+0] = 1; + udfs->dux_commands[OPBASE+0] = 0; + udfs->dux_commands[OUTBASE+0] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+0] = 0; } if (steps < MIN_SAMPLING_PERIOD) { - // for fast single channel aqu without mux + /* for fast single channel aqu without mux */ if (steps <= 1) { - // we just stay here at state 1 and rexecute the same state - // this gives us 30MHz sampling rate - this_usbduxfastsub->dux_commands[LENBASE + 1] = 0x89; // branch back to state 1 - this_usbduxfastsub->dux_commands[OPBASE + 1] = 0x03; // deceision state with data - this_usbduxfastsub->dux_commands[OUTBASE + 1] = - 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0xFF; // doesn't matter - } else { - // we loop through two states: data and delay: max rate is 15Mhz - this_usbduxfastsub->dux_commands[LENBASE + 1] = - steps - 1; - this_usbduxfastsub->dux_commands[OPBASE + 1] = 0x02; // data - this_usbduxfastsub->dux_commands[OUTBASE + 1] = - 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0; // doesn't matter + /* + * we just stay here at state 1 and rexecute + * the same state this gives us 30MHz sampling + * rate + */ - this_usbduxfastsub->dux_commands[LENBASE + 2] = 0x09; // branch back to state 1 - this_usbduxfastsub->dux_commands[OPBASE + 2] = 0x01; // deceision state w/o data - this_usbduxfastsub->dux_commands[OUTBASE + 2] = - 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0xFF; // doesn't matter + /* branch back to state 1 */ + udfs->dux_commands[LENBASE+1] = 0x89; + /* deceision state with data */ + udfs->dux_commands[OPBASE+1] = 0x03; + udfs->dux_commands[OUTBASE+1] = 0xFF & rngmask; + /* doesn't matter */ + udfs->dux_commands[LOGBASE+1] = 0xFF; + } else { + /* + * we loop through two states: data and delay + * max rate is 15MHz + */ + udfs->dux_commands[LENBASE+1] = steps - 1; + /* data */ + udfs->dux_commands[OPBASE+1] = 0x02; + udfs->dux_commands[OUTBASE+1] = 0xFF & rngmask; + /* doesn't matter */ + udfs->dux_commands[LOGBASE+1] = 0; + /* branch back to state 1 */ + udfs->dux_commands[LENBASE+2] = 0x09; + /* deceision state w/o data */ + udfs->dux_commands[OPBASE+2] = 0x01; + udfs->dux_commands[OUTBASE+2] = 0xFF & rngmask; + /* doesn't matter */ + udfs->dux_commands[LOGBASE+2] = 0xFF; } } else { - // we loop through 3 states: 2x delay and 1x data. This gives a min - // sampling rate of 60kHz. + /* + * we loop through 3 states: 2x delay and 1x data + * this gives a min sampling rate of 60kHz + */ - // we have 1 state with duration 1 + /* we have 1 state with duration 1 */ steps = steps - 1; - // do the first part of the delay - this_usbduxfastsub->dux_commands[LENBASE + 1] = - steps / 2; - this_usbduxfastsub->dux_commands[OPBASE + 1] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 1] = - 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0; + /* do the first part of the delay */ + udfs->dux_commands[LENBASE+1] = steps / 2; + udfs->dux_commands[OPBASE+1] = 0; + udfs->dux_commands[OUTBASE+1] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+1] = 0; - // and the second part - this_usbduxfastsub->dux_commands[LENBASE + 2] = - steps - steps / 2; - this_usbduxfastsub->dux_commands[OPBASE + 2] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 2] = - 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0; + /* and the second part */ + udfs->dux_commands[LENBASE+2] = steps - steps / 2; + udfs->dux_commands[OPBASE+2] = 0; + udfs->dux_commands[OUTBASE+2] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+2] = 0; - // get the data and branch back - this_usbduxfastsub->dux_commands[LENBASE + 3] = 0x09; // branch back to state 1 - this_usbduxfastsub->dux_commands[OPBASE + 3] = 0x03; // deceision state w data - this_usbduxfastsub->dux_commands[OUTBASE + 3] = - 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 3] = 0xFF; // doesn't matter + /* get the data and branch back */ + + /* branch back to state 1 */ + udfs->dux_commands[LENBASE+3] = 0x09; + /* deceision state w data */ + udfs->dux_commands[OPBASE+3] = 0x03; + udfs->dux_commands[OUTBASE+3] = 0xFF & rngmask; + /* doesn't matter */ + udfs->dux_commands[LOGBASE+3] = 0xFF; } break; case 2: - // two channels - // commit data to the FIFO + /* + * two channels + * commit data to the FIFO + */ + if (CR_RANGE(cmd->chanlist[0]) > 0) rngmask = 0xff - 0x04; else rngmask = 0xff; - this_usbduxfastsub->dux_commands[LENBASE + 0] = 1; - this_usbduxfastsub->dux_commands[OPBASE + 0] = 0x02; // data - this_usbduxfastsub->dux_commands[OUTBASE + 0] = 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0; - // we have 1 state with duration 1: state 0 + udfs->dux_commands[LENBASE+0] = 1; + /* data */ + udfs->dux_commands[OPBASE+0] = 0x02; + udfs->dux_commands[OUTBASE+0] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+0] = 0; + + /* we have 1 state with duration 1: state 0 */ steps_tmp = steps - 1; if (CR_RANGE(cmd->chanlist[1]) > 0) rngmask = 0xff - 0x04; else rngmask = 0xff; - // do the first part of the delay - this_usbduxfastsub->dux_commands[LENBASE + 1] = steps_tmp / 2; - this_usbduxfastsub->dux_commands[OPBASE + 1] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 1] = 0xFE & rngmask; //count - this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0; - // and the second part - this_usbduxfastsub->dux_commands[LENBASE + 2] = - steps_tmp - steps_tmp / 2; - this_usbduxfastsub->dux_commands[OPBASE + 2] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 2] = 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0; + /* do the first part of the delay */ + udfs->dux_commands[LENBASE+1] = steps_tmp / 2; + udfs->dux_commands[OPBASE+1] = 0; + /* count */ + udfs->dux_commands[OUTBASE+1] = 0xFE & rngmask; + udfs->dux_commands[LOGBASE+1] = 0; - this_usbduxfastsub->dux_commands[LENBASE + 3] = 1; - this_usbduxfastsub->dux_commands[OPBASE + 3] = 0x02; // data - this_usbduxfastsub->dux_commands[OUTBASE + 3] = 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 3] = 0; + /* and the second part */ + udfs->dux_commands[LENBASE+2] = steps_tmp - steps_tmp / 2; + udfs->dux_commands[OPBASE+2] = 0; + udfs->dux_commands[OUTBASE+2] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+2] = 0; - // we have 2 states with duration 1: step 6 and the IDLE state + udfs->dux_commands[LENBASE+3] = 1; + /* data */ + udfs->dux_commands[OPBASE+3] = 0x02; + udfs->dux_commands[OUTBASE+3] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+3] = 0; + + /* + * we have 2 states with duration 1: step 6 and + * the IDLE state + */ steps_tmp = steps - 2; if (CR_RANGE(cmd->chanlist[0]) > 0) rngmask = 0xff - 0x04; else rngmask = 0xff; - // do the first part of the delay - this_usbduxfastsub->dux_commands[LENBASE + 4] = steps_tmp / 2; - this_usbduxfastsub->dux_commands[OPBASE + 4] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 4] = (0xFF - 0x02) & rngmask; //reset - this_usbduxfastsub->dux_commands[LOGBASE + 4] = 0; - // and the second part - this_usbduxfastsub->dux_commands[LENBASE + 5] = - steps_tmp - steps_tmp / 2; - this_usbduxfastsub->dux_commands[OPBASE + 5] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 5] = 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 5] = 0; + /* do the first part of the delay */ + udfs->dux_commands[LENBASE+4] = steps_tmp / 2; + udfs->dux_commands[OPBASE+4] = 0; + /* reset */ + udfs->dux_commands[OUTBASE+4] = (0xFF - 0x02) & rngmask; + udfs->dux_commands[LOGBASE+4] = 0; - this_usbduxfastsub->dux_commands[LENBASE + 6] = 1; - this_usbduxfastsub->dux_commands[OPBASE + 6] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 6] = 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 6] = 0; + /* and the second part */ + udfs->dux_commands[LENBASE+5] = steps_tmp - steps_tmp / 2; + udfs->dux_commands[OPBASE+5] = 0; + udfs->dux_commands[OUTBASE+5] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+5] = 0; + + udfs->dux_commands[LENBASE+6] = 1; + udfs->dux_commands[OPBASE+6] = 0; + udfs->dux_commands[OUTBASE+6] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+6] = 0; break; case 3: - // three channels + /* + * three channels + */ for (j = 0; j < 1; j++) { if (CR_RANGE(cmd->chanlist[j]) > 0) rngmask = 0xff - 0x04; else rngmask = 0xff; - // commit data to the FIFO and do the first part of the delay - this_usbduxfastsub->dux_commands[LENBASE + j * 2] = - steps / 2; - this_usbduxfastsub->dux_commands[OPBASE + j * 2] = 0x02; // data - this_usbduxfastsub->dux_commands[OUTBASE + j * 2] = 0xFF & rngmask; // no change - this_usbduxfastsub->dux_commands[LOGBASE + j * 2] = 0; + /* + * commit data to the FIFO and do the first part + * of the delay + */ + udfs->dux_commands[LENBASE+j*2] = steps / 2; + /* data */ + udfs->dux_commands[OPBASE+j*2] = 0x02; + /* no change */ + udfs->dux_commands[OUTBASE+j*2] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+j*2] = 0; if (CR_RANGE(cmd->chanlist[j + 1]) > 0) rngmask = 0xff - 0x04; else rngmask = 0xff; - // do the second part of the delay - this_usbduxfastsub->dux_commands[LENBASE + j * 2 + 1] = - steps - steps / 2; - this_usbduxfastsub->dux_commands[OPBASE + j * 2 + 1] = 0; // no data - this_usbduxfastsub->dux_commands[OUTBASE + j * 2 + 1] = 0xFE & rngmask; //count - this_usbduxfastsub->dux_commands[LOGBASE + j * 2 + 1] = - 0; + + /* do the second part of the delay */ + udfs->dux_commands[LENBASE+j*2+1] = steps - steps / 2; + /* no data */ + udfs->dux_commands[OPBASE+j*2+1] = 0; + /* count */ + udfs->dux_commands[OUTBASE+j*2+1] = 0xFE & rngmask; + udfs->dux_commands[LOGBASE+j*2+1] = 0; } - // 2 steps with duration 1: the idele step and step 6: + /* 2 steps with duration 1: the idele step and step 6: */ steps_tmp = steps - 2; - // commit data to the FIFO and do the first part of the delay - this_usbduxfastsub->dux_commands[LENBASE + 4] = steps_tmp / 2; - this_usbduxfastsub->dux_commands[OPBASE + 4] = 0x02; // data - this_usbduxfastsub->dux_commands[OUTBASE + 4] = 0xFF & rngmask; // no change - this_usbduxfastsub->dux_commands[LOGBASE + 4] = 0; + + /* commit data to the FIFO and do the first part of the delay */ + udfs->dux_commands[LENBASE+4] = steps_tmp / 2; + /* data */ + udfs->dux_commands[OPBASE+4] = 0x02; + udfs->dux_commands[OUTBASE+4] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+4] = 0; if (CR_RANGE(cmd->chanlist[0]) > 0) rngmask = 0xff - 0x04; else rngmask = 0xff; - // do the second part of the delay - this_usbduxfastsub->dux_commands[LENBASE + 5] = - steps_tmp - steps_tmp / 2; - this_usbduxfastsub->dux_commands[OPBASE + 5] = 0; // no data - this_usbduxfastsub->dux_commands[OUTBASE + 5] = (0xFF - 0x02) & rngmask; // reset - this_usbduxfastsub->dux_commands[LOGBASE + 5] = 0; - this_usbduxfastsub->dux_commands[LENBASE + 6] = 1; - this_usbduxfastsub->dux_commands[OPBASE + 6] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 6] = 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 6] = 0; + /* do the second part of the delay */ + udfs->dux_commands[LENBASE+5] = steps_tmp - steps_tmp / 2; + /* no data */ + udfs->dux_commands[OPBASE+5] = 0; + /* reset */ + udfs->dux_commands[OUTBASE+5] = (0xFF - 0x02) & rngmask; + udfs->dux_commands[LOGBASE+5] = 0; + + udfs->dux_commands[LENBASE+6] = 1; + udfs->dux_commands[OPBASE+6] = 0; + udfs->dux_commands[OUTBASE+6] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+6] = 0; case 16: if (CR_RANGE(cmd->chanlist[0]) > 0) rngmask = 0xff - 0x04; else rngmask = 0xff; - if (cmd->start_src == TRIG_EXT) { // we loop here until ready has been set - this_usbduxfastsub->dux_commands[LENBASE + 0] = 0x01; // branch back to state 0 - this_usbduxfastsub->dux_commands[OPBASE + 0] = 0x01; // deceision state w/o data - this_usbduxfastsub->dux_commands[OUTBASE + 0] = (0xFF - 0x02) & rngmask; // reset - this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0x00; // RDY0 = 0 - } else { // we just proceed to state 1 - this_usbduxfastsub->dux_commands[LENBASE + 0] = 255; // 30us reset pulse - this_usbduxfastsub->dux_commands[OPBASE + 0] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 0] = (0xFF - 0x02) & rngmask; // reset - this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0; + + if (cmd->start_src == TRIG_EXT) { + /* + * we loop here until ready has been set + */ + + /* branch back to state 0 */ + udfs->dux_commands[LENBASE+0] = 0x01; + /* deceision state w/o data */ + udfs->dux_commands[OPBASE+0] = 0x01; + /* reset */ + udfs->dux_commands[OUTBASE+0] = (0xFF-0x02) & rngmask; + /* RDY0 = 0 */ + udfs->dux_commands[LOGBASE+0] = 0x00; + } else { + /* + * we just proceed to state 1 + */ + + /* 30us reset pulse */ + udfs->dux_commands[LENBASE+0] = 255; + udfs->dux_commands[OPBASE+0] = 0; + /* reset */ + udfs->dux_commands[OUTBASE+0] = (0xFF-0x02) & rngmask; + udfs->dux_commands[LOGBASE+0] = 0; } - // commit data to the FIFO - this_usbduxfastsub->dux_commands[LENBASE + 1] = 1; - this_usbduxfastsub->dux_commands[OPBASE + 1] = 0x02; // data - this_usbduxfastsub->dux_commands[OUTBASE + 1] = 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0; + /* commit data to the FIFO */ + udfs->dux_commands[LENBASE+1] = 1; + /* data */ + udfs->dux_commands[OPBASE+1] = 0x02; + udfs->dux_commands[OUTBASE+1] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+1] = 0; - // we have 2 states with duration 1 + /* we have 2 states with duration 1 */ steps = steps - 2; - // do the first part of the delay - this_usbduxfastsub->dux_commands[LENBASE + 2] = steps / 2; - this_usbduxfastsub->dux_commands[OPBASE + 2] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 2] = 0xFE & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0; + /* do the first part of the delay */ + udfs->dux_commands[LENBASE+2] = steps / 2; + udfs->dux_commands[OPBASE+2] = 0; + udfs->dux_commands[OUTBASE+2] = 0xFE & rngmask; + udfs->dux_commands[LOGBASE+2] = 0; - // and the second part - this_usbduxfastsub->dux_commands[LENBASE + 3] = - steps - steps / 2; - this_usbduxfastsub->dux_commands[OPBASE + 3] = 0; - this_usbduxfastsub->dux_commands[OUTBASE + 3] = 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 3] = 0; + /* and the second part */ + udfs->dux_commands[LENBASE+3] = steps - steps / 2; + udfs->dux_commands[OPBASE+3] = 0; + udfs->dux_commands[OUTBASE+3] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+3] = 0; - this_usbduxfastsub->dux_commands[LENBASE + 4] = 0x09; // branch back to state 1 - this_usbduxfastsub->dux_commands[OPBASE + 4] = 0x01; // deceision state w/o data - this_usbduxfastsub->dux_commands[OUTBASE + 4] = 0xFF & rngmask; - this_usbduxfastsub->dux_commands[LOGBASE + 4] = 0xFF; // doesn't matter + /* branch back to state 1 */ + udfs->dux_commands[LENBASE+4] = 0x09; + /* deceision state w/o data */ + udfs->dux_commands[OPBASE+4] = 0x01; + udfs->dux_commands[OUTBASE+4] = 0xFF & rngmask; + /* doesn't matter */ + udfs->dux_commands[LOGBASE+4] = 0xFF; break; default: - printk("comedi %d: unsupported combination of channels\n", - dev->minor); - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi %d: unsupported combination of " + "channels\n", dev->minor); + up(&udfs->sem); return -EFAULT; } #ifdef CONFIG_COMEDI_DEBUG - printk("comedi %d: sending commands to the usb device\n", dev->minor); + printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n", + dev->minor); #endif - // 0 means that the AD commands are sent - result = send_dux_commands(this_usbduxfastsub, SENDADCOMMANDS); + /* 0 means that the AD commands are sent */ + result = send_dux_commands(udfs, SENDADCOMMANDS); if (result < 0) { - printk("comedi%d: adc command could not be submitted. Aborting...\n", dev->minor); - up(&this_usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: adc command could not be submitted." + "Aborting...\n", dev->minor); + up(&udfs->sem); return result; } if (cmd->stop_src == TRIG_COUNT) { - this_usbduxfastsub->ai_sample_count = - (cmd->stop_arg) * (cmd->scan_end_arg); - if (usbduxfastsub->ai_sample_count < 1) { - printk("comedi%d: (cmd->stop_arg)*(cmd->scan_end_arg)<1, aborting.\n", dev->minor); - up(&this_usbduxfastsub->sem); + udfs->ai_sample_count = cmd->stop_arg * cmd->scan_end_arg; + if (udfs->ai_sample_count < 1) { + printk(KERN_ERR "comedi%d: " + "(cmd->stop_arg)*(cmd->scan_end_arg)<1, " + "aborting.\n", dev->minor); + up(&udfs->sem); return -EFAULT; } - this_usbduxfastsub->ai_continous = 0; + udfs->ai_continous = 0; } else { - // continous aquisition - this_usbduxfastsub->ai_continous = 1; - this_usbduxfastsub->ai_sample_count = 0; + /* continous aquisition */ + udfs->ai_continous = 1; + udfs->ai_sample_count = 0; } if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) { - // enable this acquisition operation - this_usbduxfastsub->ai_cmd_running = 1; - ret = usbduxfastsub_submit_InURBs(this_usbduxfastsub); + /* enable this acquisition operation */ + udfs->ai_cmd_running = 1; + ret = usbduxfastsub_submit_InURBs(udfs); if (ret < 0) { - this_usbduxfastsub->ai_cmd_running = 0; - // fixme: unlink here?? - up(&this_usbduxfastsub->sem); + udfs->ai_cmd_running = 0; + /* fixme: unlink here?? */ + up(&udfs->sem); return ret; } s->async->inttrig = NULL; } else { - /* TRIG_INT */ - // don't enable the acquision operation - // wait for an internal signal + /* + * TRIG_INT + * don't enable the acquision operation + * wait for an internal signal + */ s->async->inttrig = usbduxfast_ai_inttrig; } - up(&this_usbduxfastsub->sem); + up(&udfs->sem); return 0; } -/* Mode 0 is used to get a single conversion on demand */ -static int usbduxfast_ai_insn_read(comedi_device * dev, - comedi_subdevice * s, comedi_insn * insn, lsampl_t * data) +/* + * Mode 0 is used to get a single conversion on demand. + */ +static int usbduxfast_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int i, j, n, actual_length; int chan, range, rngmask; int err; - usbduxfastsub_t *usbduxfastsub = dev->private; + struct usbduxfastsub_s *udfs; - if (!usbduxfastsub) { - printk("comedi%d: ai_insn_read: no usb dev.\n", dev->minor); + udfs = dev->private; + if (!udfs) { + printk(KERN_ERR "comedi%d: ai_insn_read: no usb dev.\n", + dev->minor); return -ENODEV; } #ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n", - dev->minor, insn->n, insn->subdev); + printk(KERN_DEBUG "comedi%d: ai_insn_read, insn->n=%d, " + "insn->subdev=%d\n", dev->minor, insn->n, insn->subdev); #endif - down(&usbduxfastsub->sem); - if (!(usbduxfastsub->probed)) { - up(&usbduxfastsub->sem); + down(&udfs->sem); + if (!udfs->probed) { + up(&udfs->sem); return -ENODEV; } - if (usbduxfastsub->ai_cmd_running) { - printk("comedi%d: ai_insn_read not possible. Async Command is running.\n", dev->minor); - up(&usbduxfastsub->sem); + if (udfs->ai_cmd_running) { + printk(KERN_ERR "comedi%d: ai_insn_read not possible. Async " + "Command is running.\n", dev->minor); + up(&udfs->sem); return -EBUSY; } - // sample one channel + /* sample one channel */ chan = CR_CHAN(insn->chanspec); range = CR_RANGE(insn->chanspec); - // set command for the first channel + /* set command for the first channel */ if (range > 0) rngmask = 0xff - 0x04; else rngmask = 0xff; - // commit data to the FIFO - usbduxfastsub->dux_commands[LENBASE + 0] = 1; - usbduxfastsub->dux_commands[OPBASE + 0] = 0x02; // data - usbduxfastsub->dux_commands[OUTBASE + 0] = 0xFF & rngmask; - usbduxfastsub->dux_commands[LOGBASE + 0] = 0; - // do the first part of the delay - usbduxfastsub->dux_commands[LENBASE + 1] = 12; - usbduxfastsub->dux_commands[OPBASE + 1] = 0; - usbduxfastsub->dux_commands[OUTBASE + 1] = 0xFE & rngmask; - usbduxfastsub->dux_commands[LOGBASE + 1] = 0; + /* commit data to the FIFO */ + udfs->dux_commands[LENBASE+0] = 1; + /* data */ + udfs->dux_commands[OPBASE+0] = 0x02; + udfs->dux_commands[OUTBASE+0] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+0] = 0; - usbduxfastsub->dux_commands[LENBASE + 2] = 1; - usbduxfastsub->dux_commands[OPBASE + 2] = 0; - usbduxfastsub->dux_commands[OUTBASE + 2] = 0xFE & rngmask; - usbduxfastsub->dux_commands[LOGBASE + 2] = 0; + /* do the first part of the delay */ + udfs->dux_commands[LENBASE+1] = 12; + udfs->dux_commands[OPBASE+1] = 0; + udfs->dux_commands[OUTBASE+1] = 0xFE & rngmask; + udfs->dux_commands[LOGBASE+1] = 0; - usbduxfastsub->dux_commands[LENBASE + 3] = 1; - usbduxfastsub->dux_commands[OPBASE + 3] = 0; - usbduxfastsub->dux_commands[OUTBASE + 3] = 0xFE & rngmask; - usbduxfastsub->dux_commands[LOGBASE + 3] = 0; + udfs->dux_commands[LENBASE+2] = 1; + udfs->dux_commands[OPBASE+2] = 0; + udfs->dux_commands[OUTBASE+2] = 0xFE & rngmask; + udfs->dux_commands[LOGBASE+2] = 0; - usbduxfastsub->dux_commands[LENBASE + 4] = 1; - usbduxfastsub->dux_commands[OPBASE + 4] = 0; - usbduxfastsub->dux_commands[OUTBASE + 4] = 0xFE & rngmask; - usbduxfastsub->dux_commands[LOGBASE + 4] = 0; + udfs->dux_commands[LENBASE+3] = 1; + udfs->dux_commands[OPBASE+3] = 0; + udfs->dux_commands[OUTBASE+3] = 0xFE & rngmask; + udfs->dux_commands[LOGBASE+3] = 0; - // second part - usbduxfastsub->dux_commands[LENBASE + 5] = 12; - usbduxfastsub->dux_commands[OPBASE + 5] = 0; - usbduxfastsub->dux_commands[OUTBASE + 5] = 0xFF & rngmask; - usbduxfastsub->dux_commands[LOGBASE + 5] = 0; + udfs->dux_commands[LENBASE+4] = 1; + udfs->dux_commands[OPBASE+4] = 0; + udfs->dux_commands[OUTBASE+4] = 0xFE & rngmask; + udfs->dux_commands[LOGBASE+4] = 0; - usbduxfastsub->dux_commands[LENBASE + 6] = 1; - usbduxfastsub->dux_commands[OPBASE + 6] = 0; - usbduxfastsub->dux_commands[OUTBASE + 6] = 0xFF & rngmask; - usbduxfastsub->dux_commands[LOGBASE + 0] = 0; + /* second part */ + udfs->dux_commands[LENBASE+5] = 12; + udfs->dux_commands[OPBASE+5] = 0; + udfs->dux_commands[OUTBASE+5] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+5] = 0; + + udfs->dux_commands[LENBASE+6] = 1; + udfs->dux_commands[OPBASE+6] = 0; + udfs->dux_commands[OUTBASE+6] = 0xFF & rngmask; + udfs->dux_commands[LOGBASE+0] = 0; #ifdef CONFIG_COMEDI_DEBUG - printk("comedi %d: sending commands to the usb device\n", dev->minor); + printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n", + dev->minor); #endif - // 0 means that the AD commands are sent - err = send_dux_commands(usbduxfastsub, SENDADCOMMANDS); + /* 0 means that the AD commands are sent */ + err = send_dux_commands(udfs, SENDADCOMMANDS); if (err < 0) { - printk("comedi%d: adc command could not be submitted. Aborting...\n", dev->minor); - up(&usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: adc command could not be submitted." + "Aborting...\n", dev->minor); + up(&udfs->sem); return err; } #ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: usbduxfast: submitting in-urb: %x,%x\n", - usbduxfastsub->comedidev->minor, - (int)(usbduxfastsub->urbIn->context), - (int)(usbduxfastsub->urbIn->dev)); + printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: " + "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context, + udfs->urbIn->dev); #endif for (i = 0; i < PACKETS_TO_IGNORE; i++) { - err = usb_bulk_msg(usbduxfastsub->usbdev, - usb_rcvbulkpipe(usbduxfastsub->usbdev, - BULKINEP), - usbduxfastsub->transfer_buffer, SIZEINBUF, + err = usb_bulk_msg(udfs->usbdev, + usb_rcvbulkpipe(udfs->usbdev, BULKINEP), + udfs->transfer_buffer, SIZEINBUF, &actual_length, 10000); if (err < 0) { - printk("comedi%d: insn timeout. No data.\n", + printk(KERN_ERR "comedi%d: insn timeout. No data.\n", dev->minor); - up(&usbduxfastsub->sem); + up(&udfs->sem); return err; } } - // data points + /* data points */ for (i = 0; i < insn->n;) { - err = usb_bulk_msg(usbduxfastsub->usbdev, - usb_rcvbulkpipe(usbduxfastsub->usbdev, - BULKINEP), - usbduxfastsub->transfer_buffer, SIZEINBUF, + err = usb_bulk_msg(udfs->usbdev, + usb_rcvbulkpipe(udfs->usbdev, BULKINEP), + udfs->transfer_buffer, SIZEINBUF, &actual_length, 10000); if (err < 0) { - printk("comedi%d: insn data error: %d\n", + printk(KERN_ERR "comedi%d: insn data error: %d\n", dev->minor, err); - up(&usbduxfastsub->sem); + up(&udfs->sem); return err; } n = actual_length / sizeof(uint16_t); if ((n % 16) != 0) { - printk("comedi%d: insn data packet corrupted.\n", - dev->minor); - up(&usbduxfastsub->sem); + printk(KERN_ERR "comedi%d: insn data packet " + "corrupted.\n", dev->minor); + up(&udfs->sem); return -EINVAL; } for (j = chan; (j < n) && (i < insn->n); j = j + 16) { - data[i] = - ((uint16_t *) (usbduxfastsub-> - transfer_buffer))[j]; + data[i] = ((uint16_t *) (udfs->transfer_buffer))[j]; i++; } } - up(&usbduxfastsub->sem); + up(&udfs->sem); return i; } static unsigned hex2unsigned(char *h) { unsigned hi, lo; - if (h[0] > '9') { + + if (h[0] > '9') hi = h[0] - 'A' + 0x0a; - } else { + else hi = h[0] - '0'; - } - if (h[1] > '9') { + + if (h[1] > '9') lo = h[1] - 'A' + 0x0a; - } else { + else lo = h[1] - '0'; - } + return hi * 0x10 + lo; } -// for FX2 +/* for FX2 */ #define FIRMWARE_MAX_LEN 0x2000 -// taken from David Brownell's fxload and adjusted for this driver -static int read_firmware(usbduxfastsub_t * usbduxfastsub, void *firmwarePtr, - long size) +/* + * taken from David Brownell's fxload and adjusted for this driver + */ +static int read_firmware(struct usbduxfastsub_s *udfs, const void *firmwarePtr, + long size) { int i = 0; unsigned char *fp = (char *)firmwarePtr; - unsigned char *firmwareBinary = NULL; + unsigned char *firmwareBinary; int res = 0; int maxAddr = 0; firmwareBinary = kmalloc(FIRMWARE_MAX_LEN, GFP_KERNEL); if (!firmwareBinary) { - printk("comedi_: usbduxfast: mem alloc for firmware failed\n"); + printk(KERN_ERR "comedi_: usbduxfast: mem alloc for firmware " + " failed\n"); return -ENOMEM; } @@ -1315,31 +1411,37 @@ static int read_firmware(usbduxfastsub_t * usbduxfastsub, void *firmwarePtr, int idx, off; int j = 0; - // get one line + /* get one line */ while ((i < size) && (fp[i] != 13) && (fp[i] != 10)) { buf[j] = fp[i]; i++; j++; if (j >= sizeof(buf)) { - printk("comedi_: usbduxfast: bogus firmware file!\n"); + printk(KERN_ERR "comedi_: usbduxfast: bogus " + "firmware file!\n"); + kfree(firmwareBinary); return -1; } } - // get rid of LF/CR/... + /* get rid of LF/CR/... */ while ((i < size) && ((fp[i] == 13) || (fp[i] == 10) - || (fp[i] == 0))) { + || (fp[i] == 0))) i++; - } buf[j] = 0; - //printk("comedi_: buf=%s\n",buf); + /* printk("comedi_: buf=%s\n",buf); */ - /* EXTENSION: "# comment-till-end-of-line", for copyrights etc */ + /* + * EXTENSION: "# comment-till-end-of-line", + * for copyrights etc + */ if (buf[0] == '#') continue; if (buf[0] != ':') { - printk("comedi_: usbduxfast: upload: not an ihex record: %s", buf); + printk(KERN_ERR "comedi_: usbduxfast: upload: not an " + "ihex record: %s", buf); + kfree(firmwareBinary); return -EFAULT; } @@ -1349,266 +1451,309 @@ static int read_firmware(usbduxfastsub_t * usbduxfastsub, void *firmwarePtr, /* Read the target offset */ off = (hex2unsigned(buf + 3) * 0x0100) + hex2unsigned(buf + 5); - if ((off + len) > maxAddr) { + if ((off + len) > maxAddr) maxAddr = off + len; - } if (maxAddr >= FIRMWARE_MAX_LEN) { - printk("comedi_: usbduxfast: firmware upload goes beyond FX2 RAM boundaries."); + printk(KERN_ERR "comedi_: usbduxfast: firmware upload " + "goes beyond FX2 RAM boundaries."); + kfree(firmwareBinary); return -EFAULT; } - //printk("comedi_: usbduxfast: off=%x, len=%x:",off,len); + /* printk("comedi_: usbduxfast: off=%x, len=%x:",off,len); */ /* Read the record type */ type = hex2unsigned(buf + 7); /* If this is an EOF record, then make it so. */ - if (type == 1) { + if (type == 1) break; - } if (type != 0) { - printk("comedi_: usbduxfast: unsupported record type: %u\n", type); + printk(KERN_ERR "comedi_: usbduxfast: unsupported " + "record type: %u\n", type); + kfree(firmwareBinary); return -EFAULT; } for (idx = 0, cp = buf + 9; idx < len; idx += 1, cp += 2) { firmwareBinary[idx + off] = hex2unsigned(cp); - //printk("%02x ",firmwareBinary[idx+off]); + /* printk("%02x ",firmwareBinary[idx+off]); */ } - //printk("\n"); + + /* printk("\n"); */ if (i >= size) { - printk("comedi_: usbduxfast: unexpected end of hex file\n"); + printk(KERN_ERR "comedi_: usbduxfast: unexpected end " + "of hex file\n"); break; } } - res = firmwareUpload(usbduxfastsub, firmwareBinary, maxAddr + 1); + res = firmwareUpload(udfs, firmwareBinary, maxAddr + 1); kfree(firmwareBinary); return res; } -static void tidy_up(usbduxfastsub_t * usbduxfastsub_tmp) +static void tidy_up(struct usbduxfastsub_s *udfs) { #ifdef CONFIG_COMEDI_DEBUG - printk("comedi_: usbduxfast: tiding up\n"); + printk(KERN_DEBUG "comedi_: usbduxfast: tiding up\n"); #endif - if (!usbduxfastsub_tmp) { + + if (!udfs) return; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - // shows the usb subsystem that the driver is down - if (usbduxfastsub_tmp->interface) { - usb_set_intfdata(usbduxfastsub_tmp->interface, NULL); - } -#endif - usbduxfastsub_tmp->probed = 0; + /* shows the usb subsystem that the driver is down */ + if (udfs->interface) + usb_set_intfdata(udfs->interface, NULL); - if (usbduxfastsub_tmp->urbIn) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8) - // waits until a running transfer is over - // thus, under 2.4 hotplugging while a command - // is running is not safe - usb_kill_urb(usbduxfastsub_tmp->urbIn); -#endif - if (usbduxfastsub_tmp->transfer_buffer) { - kfree(usbduxfastsub_tmp->transfer_buffer); - usbduxfastsub_tmp->transfer_buffer = NULL; - } - usb_free_urb(usbduxfastsub_tmp->urbIn); - usbduxfastsub_tmp->urbIn = NULL; + udfs->probed = 0; + + if (udfs->urbIn) { + /* waits until a running transfer is over */ + usb_kill_urb(udfs->urbIn); + + kfree(udfs->transfer_buffer); + udfs->transfer_buffer = NULL; + + usb_free_urb(udfs->urbIn); + udfs->urbIn = NULL; } - if (usbduxfastsub_tmp->insnBuffer) { - kfree(usbduxfastsub_tmp->insnBuffer); - usbduxfastsub_tmp->insnBuffer = NULL; - } - if (usbduxfastsub_tmp->dux_commands) { - kfree(usbduxfastsub_tmp->dux_commands); - usbduxfastsub_tmp->dux_commands = NULL; - } - usbduxfastsub_tmp->ai_cmd_running = 0; + + kfree(udfs->insnBuffer); + udfs->insnBuffer = NULL; + + kfree(udfs->dux_commands); + udfs->dux_commands = NULL; + + udfs->ai_cmd_running = 0; } -// allocate memory for the urbs and initialise them -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static void *usbduxfastsub_probe(struct usb_device *udev, - unsigned int interfnum, const struct usb_device_id *id) +static void usbduxfast_firmware_request_complete_handler(const struct firmware *fw, + void *context) { -#else + struct usbduxfastsub_s *usbduxfastsub_tmp = context; + struct usb_device *usbdev = usbduxfastsub_tmp->usbdev; + int ret; + + if (fw == NULL) + return; + + /* + * we need to upload the firmware here because fw will be + * freed once we've left this function + */ + ret = read_firmware(usbduxfastsub_tmp, fw->data, fw->size); + + if (ret) { + dev_err(&usbdev->dev, + "Could not upload firmware (err=%d)\n", + ret); + return; + } + + comedi_usb_auto_config(usbdev, BOARDNAME); +} + +/* + * allocate memory for the urbs and initialise them + */ static int usbduxfastsub_probe(struct usb_interface *uinterf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(uinterf); -#endif int i; int index; + int ret; if (udev->speed != USB_SPEED_HIGH) { - printk("comedi_: usbduxfast_: This driver needs USB 2.0 to operate. Aborting...\n"); + printk(KERN_ERR "comedi_: usbduxfast_: This driver needs" + "USB 2.0 to operate. Aborting...\n"); return -ENODEV; } #ifdef CONFIG_COMEDI_DEBUG - printk("comedi_: usbduxfast_: finding a free structure for the usb-device\n"); + printk(KERN_DEBUG "comedi_: usbduxfast_: finding a free structure for " + "the usb-device\n"); #endif down(&start_stop_sem); - // look for a free place in the usbduxfast array + /* look for a free place in the usbduxfast array */ index = -1; for (i = 0; i < NUMUSBDUXFAST; i++) { - if (!(usbduxfastsub[i].probed)) { + if (!usbduxfastsub[i].probed) { index = i; break; } } - // no more space + /* no more space */ if (index == -1) { - printk("Too many usbduxfast-devices connected.\n"); + printk(KERN_ERR "Too many usbduxfast-devices connected.\n"); up(&start_stop_sem); return -EMFILE; } #ifdef CONFIG_COMEDI_DEBUG - printk("comedi_: usbduxfast: usbduxfastsub[%d] is ready to connect to comedi.\n", index); + printk(KERN_DEBUG "comedi_: usbduxfast: usbduxfastsub[%d] is ready to " + "connect to comedi.\n", index); #endif init_MUTEX(&(usbduxfastsub[index].sem)); - // save a pointer to the usb device + /* save a pointer to the usb device */ usbduxfastsub[index].usbdev = udev; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - // save the interface number - usbduxfastsub[index].ifnum = interfnum; -#else - // 2.6: save the interface itself + /* save the interface itself */ usbduxfastsub[index].interface = uinterf; - // get the interface number from the interface + /* get the interface number from the interface */ usbduxfastsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber; - // hand the private data over to the usb subsystem - // will be needed for disconnect + /* + * hand the private data over to the usb subsystem + * will be needed for disconnect + */ usb_set_intfdata(uinterf, &(usbduxfastsub[index])); -#endif #ifdef CONFIG_COMEDI_DEBUG - printk("comedi_: usbduxfast: ifnum=%d\n", usbduxfastsub[index].ifnum); + printk(KERN_DEBUG "comedi_: usbduxfast: ifnum=%d\n", + usbduxfastsub[index].ifnum); #endif - // create space for the commands going to the usb device + /* create space for the commands going to the usb device */ usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER, - GFP_KERNEL); + GFP_KERNEL); if (!usbduxfastsub[index].dux_commands) { - printk("comedi_: usbduxfast: error alloc space for dac commands\n"); + printk(KERN_ERR "comedi_: usbduxfast: error alloc space for " + "dac commands\n"); tidy_up(&(usbduxfastsub[index])); up(&start_stop_sem); return -ENOMEM; } - // create space of the instruction buffer + /* create space of the instruction buffer */ usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL); - if (!(usbduxfastsub[index].insnBuffer)) { - printk("comedi_: usbduxfast: could not alloc space for insnBuffer\n"); + if (!usbduxfastsub[index].insnBuffer) { + printk(KERN_ERR "comedi_: usbduxfast: could not alloc space " + "for insnBuffer\n"); tidy_up(&(usbduxfastsub[index])); up(&start_stop_sem); return -ENOMEM; } - // setting to alternate setting 1: enabling bulk ep + /* setting to alternate setting 1: enabling bulk ep */ i = usb_set_interface(usbduxfastsub[index].usbdev, usbduxfastsub[index].ifnum, 1); if (i < 0) { - printk("comedi_: usbduxfast%d: could not switch to alternate setting 1.\n", index); + printk(KERN_ERR "comedi_: usbduxfast%d: could not switch to " + "alternate setting 1.\n", index); tidy_up(&(usbduxfastsub[index])); up(&start_stop_sem); return -ENODEV; } usbduxfastsub[index].urbIn = usb_alloc_urb(0, GFP_KERNEL); - if (usbduxfastsub[index].urbIn == NULL) { - printk("comedi_: usbduxfast%d: Could not alloc. urb\n", index); + if (!usbduxfastsub[index].urbIn) { + printk(KERN_ERR "comedi_: usbduxfast%d: Could not alloc." + "urb\n", index); tidy_up(&(usbduxfastsub[index])); up(&start_stop_sem); return -ENOMEM; } usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL); - if (!(usbduxfastsub[index].transfer_buffer)) { - printk("comedi_: usbduxfast%d: could not alloc. transb.\n", - index); + if (!usbduxfastsub[index].transfer_buffer) { + printk(KERN_ERR "comedi_: usbduxfast%d: could not alloc. " + "transb.\n", index); tidy_up(&(usbduxfastsub[index])); up(&start_stop_sem); return -ENOMEM; } - // we've reached the bottom of the function + /* we've reached the bottom of the function */ usbduxfastsub[index].probed = 1; up(&start_stop_sem); - printk("comedi_: usbduxfast%d has been successfully initialized.\n", - index); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - return (void *)(&usbduxfastsub[index]); -#else - // success + + ret = request_firmware_nowait(THIS_MODULE, + FW_ACTION_HOTPLUG, + "usbduxfast_firmware.hex", + &udev->dev, + usbduxfastsub + index, + usbduxfast_firmware_request_complete_handler); + + if (ret) { + dev_err(&udev->dev, "could not load firmware (err=%d)\n", + ret); + return ret; + } + + printk(KERN_INFO "comedi_: usbduxfast%d has been successfully " + "initialized.\n", index); + /* success */ return 0; -#endif } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -static void usbduxfastsub_disconnect(struct usb_device *udev, void *ptr) -{ - usbduxfastsub_t *usbduxfastsub_tmp = (usbduxfastsub_t *) ptr; -#else static void usbduxfastsub_disconnect(struct usb_interface *intf) { - usbduxfastsub_t *usbduxfastsub_tmp = usb_get_intfdata(intf); + struct usbduxfastsub_s *udfs = usb_get_intfdata(intf); struct usb_device *udev = interface_to_usbdev(intf); -#endif - if (!usbduxfastsub_tmp) { - printk("comedi_: usbduxfast: disconnect called with null pointer.\n"); + + if (!udfs) { + printk(KERN_ERR "comedi_: usbduxfast: disconnect called with " + "null pointer.\n"); return; } - if (usbduxfastsub_tmp->usbdev != udev) { - printk("comedi_: usbduxfast: BUG! called with wrong ptr!!!\n"); + if (udfs->usbdev != udev) { + printk(KERN_ERR "comedi_: usbduxfast: BUG! called with wrong " + "ptr!!!\n"); return; } + + comedi_usb_auto_unconfig(udev); + down(&start_stop_sem); - down(&usbduxfastsub_tmp->sem); - tidy_up(usbduxfastsub_tmp); - up(&usbduxfastsub_tmp->sem); + down(&udfs->sem); + tidy_up(udfs); + up(&udfs->sem); up(&start_stop_sem); + #ifdef CONFIG_COMEDI_DEBUG - printk("comedi_: usbduxfast: disconnected from the usb\n"); + printk(KERN_DEBUG "comedi_: usbduxfast: disconnected from the usb\n"); #endif } -// is called when comedi-config is called -static int usbduxfast_attach(comedi_device * dev, comedi_devconfig * it) +/* + * is called when comedi-config is called + */ +static int usbduxfast_attach(struct comedi_device *dev, struct comedi_devconfig *it) { int ret; int index; int i; - comedi_subdevice *s = NULL; + struct comedi_subdevice *s = NULL; dev->private = NULL; down(&start_stop_sem); - // find a valid device which has been detected by the probe function of the usb + /* + * find a valid device which has been detected by the + * probe function of the usb + */ index = -1; for (i = 0; i < NUMUSBDUXFAST; i++) { - if ((usbduxfastsub[i].probed) && (!usbduxfastsub[i].attached)) { + if (usbduxfastsub[i].probed && !usbduxfastsub[i].attached) { index = i; break; } } if (index < 0) { - printk("comedi%d: usbduxfast: error: attach failed, no usbduxfast devs connected to the usb bus.\n", dev->minor); + printk(KERN_ERR "comedi%d: usbduxfast: error: attach failed, " + "no usbduxfast devs connected to the usb bus.\n", + dev->minor); up(&start_stop_sem); return -ENODEV; } down(&(usbduxfastsub[index].sem)); - // pointer back to the corresponding comedi device + /* pointer back to the corresponding comedi device */ usbduxfastsub[index].comedidev = dev; - // trying to upload the firmware into the chip + /* trying to upload the firmware into the chip */ if (comedi_aux_data(it->options, 0) && - it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { - read_firmware(usbduxfastsub, - comedi_aux_data(it->options, 0), - it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]); + it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { + read_firmware(&usbduxfastsub[index], + comedi_aux_data(it->options, 0), + it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]); } dev->board_name = BOARDNAME; @@ -1616,155 +1761,150 @@ static int usbduxfast_attach(comedi_device * dev, comedi_devconfig * it) /* set number of subdevices */ dev->n_subdevices = N_SUBDEVICES; - // allocate space for the subdevices - if ((ret = alloc_subdevices(dev, N_SUBDEVICES)) < 0) { - printk("comedi%d: usbduxfast: error alloc space for subdev\n", - dev->minor); + /* allocate space for the subdevices */ + ret = alloc_subdevices(dev, N_SUBDEVICES); + if (ret < 0) { + printk(KERN_ERR "comedi%d: usbduxfast: error alloc space for " + "subdev\n", dev->minor); + up(&(usbduxfastsub[index].sem)); up(&start_stop_sem); return ret; } - printk("comedi%d: usbduxfast: usb-device %d is attached to comedi.\n", - dev->minor, index); - // private structure is also simply the usb-structure + printk(KERN_INFO "comedi%d: usbduxfast: usb-device %d is attached to " + "comedi.\n", dev->minor, index); + /* private structure is also simply the usb-structure */ dev->private = usbduxfastsub + index; - // the first subdevice is the A/D converter + /* the first subdevice is the A/D converter */ s = dev->subdevices + SUBDEV_AD; - // the URBs get the comedi subdevice - // which is responsible for reading - // this is the subdevice which reads data + /* + * the URBs get the comedi subdevice which is responsible for reading + * this is the subdevice which reads data + */ dev->read_subdev = s; - // the subdevice receives as private structure the - // usb-structure + /* the subdevice receives as private structure the usb-structure */ s->private = NULL; - // analog input + /* analog input */ s->type = COMEDI_SUBD_AI; - // readable and ref is to ground + /* readable and ref is to ground */ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; - // 16 channels + /* 16 channels */ s->n_chan = 16; - // length of the channellist + /* length of the channellist */ s->len_chanlist = 16; - // callback functions + /* callback functions */ s->insn_read = usbduxfast_ai_insn_read; s->do_cmdtest = usbduxfast_ai_cmdtest; s->do_cmd = usbduxfast_ai_cmd; s->cancel = usbduxfast_ai_cancel; - // max value from the A/D converter (12bit+1 bit for overflow) + /* max value from the A/D converter (12bit+1 bit for overflow) */ s->maxdata = 0x1000; - // range table to convert to physical units + /* range table to convert to physical units */ s->range_table = &range_usbduxfast_ai_range; - // finally decide that it's attached + /* finally decide that it's attached */ usbduxfastsub[index].attached = 1; up(&(usbduxfastsub[index].sem)); - up(&start_stop_sem); - - printk("comedi%d: successfully attached to usbduxfast.\n", dev->minor); + printk(KERN_INFO "comedi%d: successfully attached to usbduxfast.\n", + dev->minor); return 0; } -static int usbduxfast_detach(comedi_device * dev) +static int usbduxfast_detach(struct comedi_device *dev) { - usbduxfastsub_t *usbduxfastsub_tmp; - -#ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: usbduxfast: detach usb device\n", dev->minor); -#endif + struct usbduxfastsub_s *udfs; if (!dev) { - printk("comedi?: usbduxfast: detach without dev variable...\n"); + printk(KERN_ERR "comedi?: usbduxfast: detach without dev " + "variable...\n"); return -EFAULT; } - usbduxfastsub_tmp = dev->private; - if (!usbduxfastsub_tmp) { - printk("comedi?: usbduxfast: detach without ptr to usbduxfastsub[]\n"); - return -EFAULT; - } - - down(&usbduxfastsub_tmp->sem); - down(&start_stop_sem); - // Don't allow detach to free the private structure - // It's one entry of of usbduxfastsub[] - dev->private = NULL; - usbduxfastsub_tmp->attached = 0; - usbduxfastsub_tmp->comedidev = NULL; #ifdef CONFIG_COMEDI_DEBUG - printk("comedi%d: usbduxfast: detach: successfully removed\n", - dev->minor); + printk(KERN_DEBUG "comedi%d: usbduxfast: detach usb device\n", + dev->minor); +#endif + + udfs = dev->private; + if (!udfs) { + printk(KERN_ERR "comedi?: usbduxfast: detach without ptr to " + "usbduxfastsub[]\n"); + return -EFAULT; + } + + down(&udfs->sem); + down(&start_stop_sem); + /* + * Don't allow detach to free the private structure + * It's one entry of of usbduxfastsub[] + */ + dev->private = NULL; + udfs->attached = 0; + udfs->comedidev = NULL; +#ifdef CONFIG_COMEDI_DEBUG + printk(KERN_DEBUG "comedi%d: usbduxfast: detach: successfully " + "removed\n", dev->minor); #endif up(&start_stop_sem); - up(&usbduxfastsub_tmp->sem); + up(&udfs->sem); return 0; } -/* main driver struct */ -static comedi_driver driver_usbduxfast = { - driver_name:"usbduxfast", - module:THIS_MODULE, - attach:usbduxfast_attach, - detach:usbduxfast_detach, +/* + * main driver struct + */ +static struct comedi_driver driver_usbduxfast = { + .driver_name = "usbduxfast", + .module = THIS_MODULE, + .attach = usbduxfast_attach, + .detach = usbduxfast_detach }; -static void init_usb_devices(void) -{ - int index; -#ifdef CONFIG_COMEDI_DEBUG - printk("comedi_: usbduxfast: setting all possible devs to invalid\n"); -#endif - // all devices entries are invalid to begin with - // they will become valid by the probe function - // and then finally by the attach-function - for (index = 0; index < NUMUSBDUXFAST; index++) { - memset(&(usbduxfastsub[index]), 0x00, - sizeof(usbduxfastsub[index])); - init_MUTEX(&(usbduxfastsub[index].sem)); - } -} - -// Table with the USB-devices: just now only testing IDs +/* + * Table with the USB-devices: just now only testing IDs + */ static struct usb_device_id usbduxfastsub_table[] = { - // { USB_DEVICE(0x4b4, 0x8613), //testing - // }, - {USB_DEVICE(0x13d8, 0x0010) //real ID - }, - {USB_DEVICE(0x13d8, 0x0011) //real ID - }, - {} /* Terminating entry */ + /* { USB_DEVICE(0x4b4, 0x8613) }, testing */ + { USB_DEVICE(0x13d8, 0x0010) }, /* real ID */ + { USB_DEVICE(0x13d8, 0x0011) }, /* real ID */ + { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, usbduxfastsub_table); -// The usbduxfastsub-driver +/* + * The usbduxfastsub-driver + */ static struct usb_driver usbduxfastsub_driver = { #ifdef COMEDI_HAVE_USB_DRIVER_OWNER - owner:THIS_MODULE, + .owner = THIS_MODULE, #endif - name:BOARDNAME, - probe:usbduxfastsub_probe, - disconnect:usbduxfastsub_disconnect, - id_table:usbduxfastsub_table, + .name = BOARDNAME, + .probe = usbduxfastsub_probe, + .disconnect = usbduxfastsub_disconnect, + .id_table = usbduxfastsub_table }; -// Can't use the nice macro as I have also to initialise the USB -// subsystem: -// registering the usb-system _and_ the comedi-driver -static int init_usbduxfast(void) +/* + * Can't use the nice macro as I have also to initialise the USB subsystem: + * registering the usb-system _and_ the comedi-driver + */ +static int __init init_usbduxfast(void) { - printk(KERN_INFO KBUILD_MODNAME ": " - DRIVER_VERSION ":" DRIVER_DESC "\n"); - init_usb_devices(); + printk(KERN_INFO + KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC "\n"); usb_register(&usbduxfastsub_driver); comedi_driver_register(&driver_usbduxfast); return 0; } -// deregistering the comedi driver and the usb-subsystem -static void exit_usbduxfast(void) +/* + * deregistering the comedi driver and the usb-subsystem + */ +static void __exit exit_usbduxfast(void) { comedi_driver_unregister(&driver_usbduxfast); usb_deregister(&usbduxfastsub_driver); diff --git a/drivers/staging/comedi/interrupt.h b/drivers/staging/comedi/interrupt.h index 3038e461948a..d1f09892da2e 100644 --- a/drivers/staging/comedi/interrupt.h +++ b/drivers/staging/comedi/interrupt.h @@ -21,15 +21,6 @@ #include -#include - -#ifndef IRQ_NONE -typedef void irqreturn_t; -#define IRQ_NONE -#define IRQ_HANDLED -#define IRQ_RETVAL(x) (void)(x) -#endif - #ifndef IRQF_DISABLED #define IRQF_DISABLED SA_INTERRUPT #define IRQF_SAMPLE_RANDOM SA_SAMPLE_RANDOM diff --git a/drivers/staging/comedi/kcomedilib/data.c b/drivers/staging/comedi/kcomedilib/data.c index 79aec2041150..9797e13e3774 100644 --- a/drivers/staging/comedi/kcomedilib/data.c +++ b/drivers/staging/comedi/kcomedilib/data.c @@ -27,10 +27,10 @@ #include -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_write(void *dev, unsigned int subdev, unsigned int chan, + unsigned int range, unsigned int aref, unsigned int data) { - comedi_insn insn; + struct comedi_insn insn; memset(&insn, 0, sizeof(insn)); insn.insn = INSN_WRITE; @@ -42,10 +42,10 @@ int comedi_data_write(comedi_t * dev, unsigned int subdev, unsigned int chan, return comedi_do_insn(dev, &insn); } -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(void *dev, unsigned int subdev, unsigned int chan, + unsigned int range, unsigned int aref, unsigned int *data) { - comedi_insn insn; + struct comedi_insn insn; memset(&insn, 0, sizeof(insn)); insn.insn = INSN_READ; @@ -57,11 +57,11 @@ int comedi_data_read(comedi_t * dev, unsigned int subdev, unsigned int chan, return comedi_do_insn(dev, &insn); } -int comedi_data_read_hint(comedi_t * dev, unsigned int subdev, +int comedi_data_read_hint(void *dev, unsigned int subdev, unsigned int chan, unsigned int range, unsigned int aref) { - comedi_insn insn; - lsampl_t dummy_data; + struct comedi_insn insn; + unsigned int dummy_data; memset(&insn, 0, sizeof(insn)); insn.insn = INSN_READ; @@ -73,9 +73,9 @@ int comedi_data_read_hint(comedi_t * dev, unsigned int subdev, return comedi_do_insn(dev, &insn); } -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) + unsigned int *data, unsigned int nano_sec) { int retval; diff --git a/drivers/staging/comedi/kcomedilib/dio.c b/drivers/staging/comedi/kcomedilib/dio.c index a9f488aed369..8595567e48fb 100644 --- a/drivers/staging/comedi/kcomedilib/dio.c +++ b/drivers/staging/comedi/kcomedilib/dio.c @@ -26,10 +26,10 @@ #include -int comedi_dio_config(comedi_t * dev, unsigned int subdev, unsigned int chan, +int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan, unsigned int io) { - comedi_insn insn; + struct comedi_insn insn; memset(&insn, 0, sizeof(insn)); insn.insn = INSN_CONFIG; @@ -41,10 +41,10 @@ int comedi_dio_config(comedi_t * dev, unsigned int subdev, unsigned int chan, return comedi_do_insn(dev, &insn); } -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) { - comedi_insn insn; + struct comedi_insn insn; memset(&insn, 0, sizeof(insn)); insn.insn = INSN_READ; @@ -56,10 +56,10 @@ int comedi_dio_read(comedi_t * dev, unsigned int subdev, unsigned int chan, return comedi_do_insn(dev, &insn); } -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) { - comedi_insn insn; + struct comedi_insn insn; memset(&insn, 0, sizeof(insn)); insn.insn = INSN_WRITE; @@ -71,11 +71,11 @@ int comedi_dio_write(comedi_t * dev, unsigned int subdev, unsigned int chan, return comedi_do_insn(dev, &insn); } -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) { - comedi_insn insn; - lsampl_t data[2]; + struct comedi_insn insn; + unsigned int data[2]; int ret; memset(&insn, 0, sizeof(insn)); diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c index 2004ad4480c0..b6b726a69f14 100644 --- a/drivers/staging/comedi/kcomedilib/get.c +++ b/drivers/staging/comedi/kcomedilib/get.c @@ -26,51 +26,51 @@ #include "../comedilib.h" #include "../comedidev.h" -int comedi_get_n_subdevices(comedi_t * d) +int comedi_get_n_subdevices(void *d) { - comedi_device *dev = (comedi_device *) d; + struct comedi_device *dev = (struct comedi_device *) d; return dev->n_subdevices; } -int comedi_get_version_code(comedi_t * d) +int comedi_get_version_code(void *d) { return COMEDI_VERSION_CODE; } -const char *comedi_get_driver_name(comedi_t * d) +const char *comedi_get_driver_name(void * d) { - comedi_device *dev = (comedi_device *) d; + struct comedi_device *dev = (struct comedi_device *) d; return dev->driver->driver_name; } -const char *comedi_get_board_name(comedi_t * d) +const char *comedi_get_board_name(void * d) { - comedi_device *dev = (comedi_device *) d; + struct comedi_device *dev = (struct comedi_device *) d; return dev->board_name; } -int comedi_get_subdevice_type(comedi_t * d, unsigned int subdevice) +int comedi_get_subdevice_type(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; return s->type; } -unsigned int comedi_get_subdevice_flags(comedi_t * d, unsigned int subdevice) +unsigned int comedi_get_subdevice_flags(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; return s->subdev_flags; } -int comedi_find_subdevice_by_type(comedi_t * d, int type, unsigned int subd) +int comedi_find_subdevice_by_type(void *d, int type, unsigned int subd) { - comedi_device *dev = (comedi_device *) d; + struct comedi_device *dev = (struct comedi_device *) d; if (subd > dev->n_subdevices) return -ENODEV; @@ -82,27 +82,27 @@ int comedi_find_subdevice_by_type(comedi_t * d, int type, unsigned int subd) return -1; } -int comedi_get_n_channels(comedi_t * d, unsigned int subdevice) +int comedi_get_n_channels(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; return s->n_chan; } -int comedi_get_len_chanlist(comedi_t * d, unsigned int subdevice) +int comedi_get_len_chanlist(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; return s->len_chanlist; } -lsampl_t comedi_get_maxdata(comedi_t * d, unsigned int subdevice, +unsigned int comedi_get_maxdata(void *d, unsigned int subdevice, unsigned int chan) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; if (s->maxdata_list) return s->maxdata_list[chan]; @@ -111,11 +111,11 @@ lsampl_t comedi_get_maxdata(comedi_t * d, unsigned int subdevice, } #ifdef KCOMEDILIB_DEPRECATED -int comedi_get_rangetype(comedi_t * d, unsigned int subdevice, +int comedi_get_rangetype(void *d, unsigned int subdevice, unsigned int chan) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; int ret; if (s->range_table_list) { @@ -130,10 +130,10 @@ int comedi_get_rangetype(comedi_t * d, unsigned int subdevice, } #endif -int comedi_get_n_ranges(comedi_t * d, unsigned int subdevice, unsigned int chan) +int comedi_get_n_ranges(void *d, unsigned int subdevice, unsigned int chan) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; int ret; if (s->range_table_list) { @@ -148,22 +148,22 @@ int comedi_get_n_ranges(comedi_t * d, unsigned int subdevice, unsigned int chan) /* * ALPHA (non-portable) */ -int comedi_get_krange(comedi_t * d, unsigned int subdevice, unsigned int chan, - unsigned int range, comedi_krange * krange) +int comedi_get_krange(void *d, unsigned int subdevice, unsigned int chan, + unsigned int range, struct comedi_krange *krange) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; - const comedi_lrange *lr; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; + const struct comedi_lrange *lr; if (s->range_table_list) { lr = s->range_table_list[chan]; } else { lr = s->range_table; } - if (range >= lr->length) { + if (range >= lr->length) return -EINVAL; - } - memcpy(krange, lr->range + range, sizeof(comedi_krange)); + + memcpy(krange, lr->range + range, sizeof(struct comedi_krange)); return 0; } @@ -171,11 +171,11 @@ int comedi_get_krange(comedi_t * d, unsigned int subdevice, unsigned int chan, /* * ALPHA (may be renamed) */ -unsigned int comedi_get_buf_head_pos(comedi_t * d, unsigned int subdevice) +unsigned int comedi_get_buf_head_pos(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_async *async; async = s->async; if (async == NULL) @@ -184,11 +184,11 @@ unsigned int comedi_get_buf_head_pos(comedi_t * d, unsigned int subdevice) return async->buf_write_count; } -int comedi_get_buffer_contents(comedi_t * d, unsigned int subdevice) +int comedi_get_buffer_contents(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_async *async; unsigned int num_bytes; if (subdevice >= dev->n_subdevices) @@ -203,12 +203,12 @@ int comedi_get_buffer_contents(comedi_t * d, unsigned int subdevice) /* * ALPHA */ -int comedi_set_user_int_count(comedi_t * d, unsigned int subdevice, +int comedi_set_user_int_count(void *d, unsigned int subdevice, unsigned int buf_user_count) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_async *async; int num_bytes; async = s->async; @@ -224,12 +224,12 @@ int comedi_set_user_int_count(comedi_t * d, unsigned int subdevice, return 0; } -int comedi_mark_buffer_read(comedi_t * d, unsigned int subdevice, +int comedi_mark_buffer_read(void *d, unsigned int subdevice, unsigned int num_bytes) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_async *async; if (subdevice >= dev->n_subdevices) return -1; @@ -243,12 +243,12 @@ int comedi_mark_buffer_read(comedi_t * d, unsigned int subdevice, return 0; } -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) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_async *async; int bytes_written; if (subdevice >= dev->n_subdevices) @@ -263,11 +263,11 @@ int comedi_mark_buffer_written(comedi_t * d, unsigned int subdevice, return 0; } -int comedi_get_buffer_size(comedi_t * d, unsigned int subdev) +int comedi_get_buffer_size(void *d, unsigned int subdev) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdev; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdev; + struct comedi_async *async; if (subdev >= dev->n_subdevices) return -1; @@ -278,11 +278,11 @@ int comedi_get_buffer_size(comedi_t * d, unsigned int subdev) return async->prealloc_bufsz; } -int comedi_get_buffer_offset(comedi_t * d, unsigned int subdevice) +int comedi_get_buffer_offset(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices + subdevice; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices + subdevice; + struct comedi_async *async; if (subdevice >= dev->n_subdevices) return -1; diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index 510fbdcec493..a4fa9571c58f 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -42,10 +42,10 @@ MODULE_AUTHOR("David Schleef "); MODULE_DESCRIPTION("Comedi kernel library"); MODULE_LICENSE("GPL"); -comedi_t *comedi_open(const char *filename) +void *comedi_open(const char *filename) { struct comedi_device_file_info *dev_file_info; - comedi_device *dev; + struct comedi_device *dev; unsigned int minor; if (strncmp(filename, "/dev/comedi", 11) != 0) @@ -57,41 +57,41 @@ comedi_t *comedi_open(const char *filename) return NULL; dev_file_info = comedi_get_device_file_info(minor); - if(dev_file_info == NULL) + if (dev_file_info == NULL) return NULL; dev = dev_file_info->device; - if(dev == NULL || !dev->attached) + if (dev == NULL || !dev->attached) return NULL; if (!try_module_get(dev->driver->module)) return NULL; - return (comedi_t *) dev; + return (void *) dev; } -comedi_t *comedi_open_old(unsigned int minor) +void *comedi_open_old(unsigned int minor) { struct comedi_device_file_info *dev_file_info; - comedi_device *dev; + struct comedi_device *dev; if (minor >= COMEDI_NUM_MINORS) return NULL; dev_file_info = comedi_get_device_file_info(minor); - if(dev_file_info == NULL) + if (dev_file_info == NULL) return NULL; dev = dev_file_info->device; - if(dev == NULL || !dev->attached) + if (dev == NULL || !dev->attached) return NULL; - return (comedi_t *) dev; + return (void *) dev; } -int comedi_close(comedi_t * d) +int comedi_close(void *d) { - comedi_device *dev = (comedi_device *) d; + struct comedi_device *dev = (struct comedi_device *) d; module_put(dev->driver->module); @@ -113,19 +113,19 @@ char *comedi_strerror(int err) return "unknown error"; } -int comedi_fileno(comedi_t * d) +int comedi_fileno(void *d) { - comedi_device *dev = (comedi_device *) d; + struct comedi_device *dev = (struct comedi_device *) d; /* return something random */ return dev->minor; } -int comedi_command(comedi_t * d, comedi_cmd * cmd) +int comedi_command(void *d, struct comedi_cmd *cmd) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; + struct comedi_async *async; unsigned runflags; if (cmd->subdev >= dev->n_subdevices) @@ -161,10 +161,10 @@ int comedi_command(comedi_t * d, comedi_cmd * cmd) return s->do_cmd(dev, s); } -int comedi_command_test(comedi_t * d, comedi_cmd * cmd) +int comedi_command_test(void *d, struct comedi_cmd *cmd) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; if (cmd->subdev >= dev->n_subdevices) return -ENODEV; @@ -183,10 +183,10 @@ int comedi_command_test(comedi_t * d, comedi_cmd * cmd) * COMEDI_INSN * perform an instruction */ -int comedi_do_insn(comedi_t * d, comedi_insn * insn) +int comedi_do_insn(void *d, struct comedi_insn *insn) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; int ret = 0; if (insn->insn & INSN_MASK_SPECIAL) { @@ -256,7 +256,8 @@ int comedi_do_insn(comedi_t * d, comedi_insn * insn) /* XXX check lock */ - if ((ret = check_chanlist(s, 1, &insn->chanspec)) < 0) { + ret = check_chanlist(s, 1, &insn->chanspec); + if (ret < 0) { rt_printk("bad chanspec\n"); ret = -EINVAL; goto error; @@ -323,16 +324,16 @@ int comedi_do_insn(comedi_t * d, comedi_insn * insn) - lock while subdevice being programmed */ -int comedi_lock(comedi_t * d, unsigned int subdevice) +int comedi_lock(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; unsigned long flags; int ret = 0; - if (subdevice >= dev->n_subdevices) { + if (subdevice >= dev->n_subdevices) return -EINVAL; - } + s = dev->subdevices + subdevice; comedi_spin_lock_irqsave(&s->spin_lock, flags); @@ -366,17 +367,17 @@ int comedi_lock(comedi_t * d, unsigned int subdevice) none */ -int comedi_unlock(comedi_t * d, unsigned int subdevice) +int comedi_unlock(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; unsigned long flags; - comedi_async *async; + struct comedi_async *async; int ret; - if (subdevice >= dev->n_subdevices) { + if (subdevice >= dev->n_subdevices) return -EINVAL; - } + s = dev->subdevices + subdevice; async = s->async; @@ -418,15 +419,15 @@ int comedi_unlock(comedi_t * d, unsigned int subdevice) nothing */ -int comedi_cancel(comedi_t * d, unsigned int subdevice) +int comedi_cancel(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; int ret = 0; - if (subdevice >= dev->n_subdevices) { + if (subdevice >= dev->n_subdevices) return -EINVAL; - } + s = dev->subdevices + subdevice; if (s->lock && s->lock != d) @@ -443,13 +444,15 @@ int comedi_cancel(comedi_t * d, unsigned int subdevice) if (!s->cancel || !s->async) return -EINVAL; - if ((ret = s->cancel(dev, s))) + ret = s->cancel(dev, s); + + if (ret) return ret; #ifdef CONFIG_COMEDI_RT - if (comedi_get_subdevice_runflags(s) & SRF_RT) { + if (comedi_get_subdevice_runflags(s) & SRF_RT) comedi_switch_to_non_rt(dev); - } + #endif comedi_set_subdevice_runflags(s, SRF_RUNNING | SRF_RT, 0); s->async->inttrig = NULL; @@ -461,16 +464,16 @@ int comedi_cancel(comedi_t * d, unsigned int subdevice) /* registration of callback functions */ -int comedi_register_callback(comedi_t * d, unsigned int subdevice, +int comedi_register_callback(void *d, unsigned int subdevice, unsigned int mask, int (*cb) (unsigned int, void *), void *arg) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; + struct comedi_async *async; - if (subdevice >= dev->n_subdevices) { + if (subdevice >= dev->n_subdevices) return -EINVAL; - } + s = dev->subdevices + subdevice; async = s->async; @@ -498,15 +501,15 @@ int comedi_register_callback(comedi_t * d, unsigned int subdevice, return 0; } -int comedi_poll(comedi_t * d, unsigned int subdevice) +int comedi_poll(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s = dev->subdevices; - comedi_async *async; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s = dev->subdevices; + struct comedi_async *async; - if (subdevice >= dev->n_subdevices) { + if (subdevice >= dev->n_subdevices) return -EINVAL; - } + s = dev->subdevices + subdevice; async = s->async; @@ -525,22 +528,21 @@ int comedi_poll(comedi_t * d, unsigned int subdevice) } /* WARNING: not portable */ -int comedi_map(comedi_t * d, unsigned int subdevice, void *ptr) +int comedi_map(void *d, unsigned int subdevice, void *ptr) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; - if (subdevice >= dev->n_subdevices) { + if (subdevice >= dev->n_subdevices) return -EINVAL; - } + s = dev->subdevices + subdevice; if (!s->async) return -EINVAL; - if (ptr) { + if (ptr) *((void **)ptr) = s->async->prealloc_buf; - } /* XXX no reference counting */ @@ -548,14 +550,14 @@ int comedi_map(comedi_t * d, unsigned int subdevice, void *ptr) } /* WARNING: not portable */ -int comedi_unmap(comedi_t * d, unsigned int subdevice) +int comedi_unmap(void *d, unsigned int subdevice) { - comedi_device *dev = (comedi_device *) d; - comedi_subdevice *s; + struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_subdevice *s; - if (subdevice >= dev->n_subdevices) { + if (subdevice >= dev->n_subdevices) return -EINVAL; - } + s = dev->subdevices + subdevice; if (!s->async) diff --git a/drivers/staging/comedi/kcomedilib/ksyms.c b/drivers/staging/comedi/kcomedilib/ksyms.c index 76b45063a9fc..3db86dabf878 100644 --- a/drivers/staging/comedi/kcomedilib/ksyms.c +++ b/drivers/staging/comedi/kcomedilib/ksyms.c @@ -40,8 +40,6 @@ #include #include -#if LINUX_VERSION_CODE >= 0x020200 - /* functions specific to kcomedilib */ EXPORT_SYMBOL(comedi_register_callback); @@ -140,5 +138,3 @@ EXPORT_SYMBOL(comedi_get_len_chanlist); /* alpha */ //EXPORT_SYMBOL(comedi_set_global_oor_behavior); - -#endif diff --git a/drivers/staging/comedi/pci_ids.h b/drivers/staging/comedi/pci_ids.h index c61ba90f9601..d979aa8e396b 100644 --- a/drivers/staging/comedi/pci_ids.h +++ b/drivers/staging/comedi/pci_ids.h @@ -28,4 +28,4 @@ #define PCI_DEVICE_ID_QUANCOM_GPIB 0x3302 #endif -#endif // __COMPAT_LINUX_PCI_IDS_H +#endif /* __COMPAT_LINUX_PCI_IDS_H */ diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c index 5a2b72d87572..36ae2cd92ad9 100644 --- a/drivers/staging/comedi/proc.c +++ b/drivers/staging/comedi/proc.c @@ -31,12 +31,12 @@ #define __NO_VERSION__ #include "comedidev.h" #include -//#include +/* #include */ int comedi_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data); -extern comedi_driver *comedi_drivers; +extern struct comedi_driver *comedi_drivers; int comedi_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data) @@ -44,7 +44,7 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len, int i; int devices_q = 0; int l = 0; - comedi_driver *driv; + struct comedi_driver *driv; l += sprintf(buf + l, "comedi version " COMEDI_RELEASE "\n" @@ -53,9 +53,10 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len, 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; + if (dev_file_info == NULL) + continue; dev = dev_file_info->device; if (dev->attached) { @@ -66,9 +67,8 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len, dev->board_name, dev->n_subdevices); } } - if (!devices_q) { + if (!devices_q) l += sprintf(buf + l, "no devices\n"); - } for (driv = comedi_drivers; driv; driv = driv->next) { l += sprintf(buf + l, "%s:\n", driv->driver_name); @@ -77,9 +77,8 @@ int comedi_read_procmem(char *buf, char **start, off_t offset, int len, *(char **)((char *)driv->board_name + i * driv->offset)); } - if (!driv->num_names) { + if (!driv->num_names) l += sprintf(buf + l, " %s\n", driv->driver_name); - } } return l; diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 61dc3cd6a9fd..ac200d929f35 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -24,12 +24,12 @@ #include "comedidev.h" #include -const comedi_lrange range_bipolar10 = { 1, {BIP_RANGE(10)} }; -const comedi_lrange range_bipolar5 = { 1, {BIP_RANGE(5)} }; -const comedi_lrange range_bipolar2_5 = { 1, {BIP_RANGE(2.5)} }; -const comedi_lrange range_unipolar10 = { 1, {UNI_RANGE(10)} }; -const comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} }; -const comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} }; +const struct comedi_lrange range_bipolar10 = { 1, {BIP_RANGE(10)} }; +const struct comedi_lrange range_bipolar5 = { 1, {BIP_RANGE(5)} }; +const struct comedi_lrange range_bipolar2_5 = { 1, {BIP_RANGE(2.5)} }; +const struct comedi_lrange range_unipolar10 = { 1, {UNI_RANGE(10)} }; +const struct comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} }; +const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} }; /* COMEDI_RANGEINFO @@ -42,16 +42,16 @@ const comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} }; range info structure writes: - n comedi_krange structures to rangeinfo->range_ptr + n struct comedi_krange structures to rangeinfo->range_ptr */ -int do_rangeinfo_ioctl(comedi_device * dev, comedi_rangeinfo * arg) +int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg) { - comedi_rangeinfo it; + struct comedi_rangeinfo it; int subd, chan; - const comedi_lrange *lr; - comedi_subdevice *s; + const struct comedi_lrange *lr; + struct comedi_subdevice *s; - if (copy_from_user(&it, arg, sizeof(comedi_rangeinfo))) + if (copy_from_user(&it, arg, sizeof(struct comedi_rangeinfo))) return -EFAULT; subd = (it.range_type >> 24) & 0xf; chan = (it.range_type >> 16) & 0xff; @@ -78,17 +78,17 @@ int do_rangeinfo_ioctl(comedi_device * dev, comedi_rangeinfo * arg) } if (copy_to_user(it.range_ptr, lr->range, - sizeof(comedi_krange) * lr->length)) + sizeof(struct comedi_krange) * lr->length)) return -EFAULT; return 0; } -static int aref_invalid(comedi_subdevice * s, unsigned int chanspec) +static int aref_invalid(struct comedi_subdevice *s, unsigned int chanspec) { unsigned int aref; - // disable reporting invalid arefs... maybe someday + /* disable reporting invalid arefs... maybe someday */ return 0; aref = CR_AREF(chanspec); @@ -120,7 +120,7 @@ static int aref_invalid(comedi_subdevice * s, unsigned int chanspec) This function checks each element in a channel/gain list to make make sure it is valid. */ -int check_chanlist(comedi_subdevice * s, int n, unsigned int *chanlist) +int check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist) { int i; int chan; @@ -135,9 +135,8 @@ int check_chanlist(comedi_subdevice * s, int n, unsigned int *chanlist) i, chanlist[i], s->n_chan, s->range_table->length); #if 0 - for (i = 0; i < n; i++) { + for (i = 0; i < n; i++) printk("[%d]=0x%08x\n", i, chanlist[i]); - } #endif return -EINVAL; } diff --git a/drivers/staging/comedi/rt.c b/drivers/staging/comedi/rt.c index 385b81b94ac5..e9f5777595ab 100644 --- a/drivers/staging/comedi/rt.c +++ b/drivers/staging/comedi/rt.c @@ -57,7 +57,7 @@ struct comedi_irq_struct { irqreturn_t(*handler) (int irq, void *dev_id PT_REGS_ARG); unsigned long flags; const char *device; - comedi_device *dev_id; + struct comedi_device *dev_id; }; static int comedi_rt_get_irq(struct comedi_irq_struct *it); @@ -67,7 +67,7 @@ static struct comedi_irq_struct *comedi_irqs[NR_IRQS]; int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int, void *PT_REGS_ARG), unsigned long flags, const char *device, - comedi_device * dev_id) + struct comedi_device *dev_id) { struct comedi_irq_struct *it; int ret; @@ -78,15 +78,15 @@ int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int, ret = request_irq(irq, handler, unshared_flags, device, dev_id); if (ret < 0) { - // we failed, so fall back on allowing shared interrupt (which we won't ever make RT) + /* we failed, so fall back on allowing shared interrupt (which we won't ever make RT) */ if (flags & IRQF_SHARED) { rt_printk ("comedi: cannot get unshared interrupt, will not use RT interrupts.\n"); ret = request_irq(irq, handler, flags, device, dev_id); } - if (ret < 0) { + if (ret < 0) return ret; - } + } else { it = kzalloc(sizeof(struct comedi_irq_struct), GFP_KERNEL); if (!it) @@ -102,7 +102,7 @@ int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int, return 0; } -void comedi_free_irq(unsigned int irq, comedi_device * dev_id) +void comedi_free_irq(unsigned int irq, struct comedi_device *dev_id) { struct comedi_irq_struct *it; @@ -121,7 +121,7 @@ void comedi_free_irq(unsigned int irq, comedi_device * dev_id) comedi_irqs[irq] = NULL; } -int comedi_switch_to_rt(comedi_device * dev) +int comedi_switch_to_rt(struct comedi_device *dev) { struct comedi_irq_struct *it; unsigned long flags; @@ -145,7 +145,7 @@ int comedi_switch_to_rt(comedi_device * dev) return 0; } -void comedi_switch_to_non_rt(comedi_device * dev) +void comedi_switch_to_non_rt(struct comedi_device *dev) { struct comedi_irq_struct *it; unsigned long flags; @@ -170,7 +170,7 @@ void wake_up_int_handler(int arg1, void *arg2) wake_up_interruptible((wait_queue_head_t *) arg2); } -void comedi_rt_pend_wakeup(wait_queue_head_t * q) +void comedi_rt_pend_wakeup(wait_queue_head_t *q) { rt_pend_call(wake_up_int_handler, 0, q); } @@ -180,7 +180,7 @@ void comedi_rt_pend_wakeup(wait_queue_head_t * q) #ifndef HAVE_RT_REQUEST_IRQ_WITH_ARG #define DECLARE_VOID_IRQ(irq) \ -static void handle_void_irq_ ## irq (void){ handle_void_irq(irq);} +static void handle_void_irq_ ## irq (void){ handle_void_irq(irq); } static void handle_void_irq(int irq) { @@ -192,7 +192,7 @@ static void handle_void_irq(int irq) return; } it->handler(irq, it->dev_id PT_REGS_NULL); - rt_enable_irq(irq); //needed by rtai-adeos, seems like it shouldn't hurt earlier versions + rt_enable_irq(irq); /* needed by rtai-adeos, seems like it shouldn't hurt earlier versions */ } DECLARE_VOID_IRQ(0); @@ -220,8 +220,7 @@ DECLARE_VOID_IRQ(21); DECLARE_VOID_IRQ(22); DECLARE_VOID_IRQ(23); -typedef void (*V_FP_V) (void); -static V_FP_V handle_void_irq_ptrs[] = { +static void handle_void_irq_ptrs[] = { handle_void_irq_0, handle_void_irq_1, handle_void_irq_2, @@ -402,11 +401,11 @@ static int comedi_rt_release_irq(struct comedi_irq_struct *it) void comedi_rt_init(void) { - //rt_pend_tq_init(); + /* rt_pend_tq_init(); */ } void comedi_rt_cleanup(void) { - //rt_pend_tq_cleanup(); + /* rt_pend_tq_cleanup(); */ } #endif diff --git a/drivers/staging/comedi/rt_pend_tq.c b/drivers/staging/comedi/rt_pend_tq.c index 995f076e0af3..f9dfd9d40cd3 100644 --- a/drivers/staging/comedi/rt_pend_tq.c +++ b/drivers/staging/comedi/rt_pend_tq.c @@ -3,7 +3,7 @@ #include #include #include -#include "comedidev.h" // for rt spinlocks +#include "comedidev.h" /* for rt spinlocks */ #include "rt_pend_tq.h" #ifdef CONFIG_COMEDI_RTAI #include @@ -25,9 +25,9 @@ volatile static struct rt_pend_tq rt_pend_tq[RT_PEND_TQ_SIZE]; volatile static struct rt_pend_tq *volatile rt_pend_head = rt_pend_tq, *volatile rt_pend_tail = rt_pend_tq; int rt_pend_tq_irq = 0; -spinlock_t rt_pend_tq_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(rt_pend_tq_lock); -// WARNING: following code not checked against race conditions yet. +/* WARNING: following code not checked against race conditions yet. */ #define INC_CIRCULAR_PTR(ptr,begin,size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0) #define DEC_CIRCULAR_PTR(ptr,begin,size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0) @@ -42,7 +42,7 @@ int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1, void *arg2) comedi_spin_lock_irqsave(&rt_pend_tq_lock, flags); INC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE); if (rt_pend_head == rt_pend_tail) { - // overflow, we just refuse to take this request + /* overflow, we just refuse to take this request */ DEC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE); comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags); return -EAGAIN; diff --git a/drivers/staging/dst/Kconfig b/drivers/staging/dst/Kconfig new file mode 100644 index 000000000000..448d342ac2a2 --- /dev/null +++ b/drivers/staging/dst/Kconfig @@ -0,0 +1,67 @@ +config DST + tristate "Distributed storage" + depends on NET && CRYPTO && SYSFS && BLK_DEV + select CONNECTOR + ---help--- + DST is a network block device storage, which can be used to organize + exported storage on the remote nodes into the local block device. + + DST works on top of any network media and protocol; it is just a matter + of configuration utility to understand the correct addresses. The most + common example is TCP over IP, which allows to pass through firewalls and + create remote backup storage in a different datacenter. DST requires + single port to be enabled on the exporting node and outgoing connections + on the local node. + + DST works with in-kernel client and server, which improves performance by + eliminating unneded data copies and by not depending on the version + of the external IO components. It requires userspace configuration utility + though. + + DST uses transaction model, when each store has to be explicitly acked + from the remote node to be considered as successfully written. There + may be lots of in-flight transactions. When remote host does not ack + the transaction it will be resent predefined number of times with specified + timeouts between them. All those parameters are configurable. Transactions + are marked as failed after all resends complete unsuccessfully; having + long enough resend timeout and/or large number of resends allows not to + return error to the higher (FS usually) layer in case of short network + problems or remote node outages. In case of network RAID setup this means + that storage will not degrade until transactions are marked as failed, and + thus will not force checksum recalculation and data rebuild. In case of + connection failure DST will try to reconnect to the remote node automatically. + DST sends ping commands at idle time to detect if remote node is alive. + + Because of transactional model it is possible to use zero-copy sending + without worry of data corruption (which in turn could be detected by the + strong checksums though). + + DST may fully encrypt the data channel in case of untrusted channel and implement + strong checksum of the transferred data. It is possible to configure algorithms + and crypto keys; they should match on both sides of the network channel. + Crypto processing does not introduce noticeble performance overhead, since DST + uses configurable pool of threads to perform crypto processing. + + DST utilizes memory pool model of all its transaction allocations (it is the + only additional allocation on the client) and server allocations (bio pools, + while pages are allocated from the slab). + + At startup DST performs a simple negotiation with the export node to determine + access permissions and size of the exported storage. It can be extended if + new parameters should be autonegotiated. + + DST carries block IO flags in the protocol, which allows to transparently implement + barriers and sync/flush operations. Those flags are used in the export node where + IO against the local storage is performed, which means that sync write will be sync + on the remote node too, which in turn improves data integrity and improved resistance + to errors and data corruption during power outages or storage damages. + + Homepage: http://www.ioremap.net/projects/dst + Userspace configuration utility and the latest releases: http://www.ioremap.net/archive/dst/ + +config DST_DEBUG + bool "DST debug" + depends on DST + ---help--- + This option will enable HEAVY debugging of the DST. + Turn it on ONLY if you have to debug some really obscure problem. diff --git a/drivers/staging/dst/Makefile b/drivers/staging/dst/Makefile new file mode 100644 index 000000000000..3a8b0cf9643e --- /dev/null +++ b/drivers/staging/dst/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_DST) += nst.o + +nst-y := dcore.o state.o export.o thread_pool.o crypto.o trans.o diff --git a/drivers/staging/dst/crypto.c b/drivers/staging/dst/crypto.c new file mode 100644 index 000000000000..7250f90f5924 --- /dev/null +++ b/drivers/staging/dst/crypto.c @@ -0,0 +1,731 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +/* + * Tricky bastard, but IV can be more complex with time... + */ +static inline u64 dst_gen_iv(struct dst_trans *t) +{ + return t->gen; +} + +/* + * Crypto machinery: hash/cipher support for the given crypto controls. + */ +static struct crypto_hash *dst_init_hash(struct dst_crypto_ctl *ctl, u8 *key) +{ + int err; + struct crypto_hash *hash; + + hash = crypto_alloc_hash(ctl->hash_algo, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(hash)) { + err = PTR_ERR(hash); + dprintk("%s: failed to allocate hash '%s', err: %d.\n", + __func__, ctl->hash_algo, err); + goto err_out_exit; + } + + ctl->crypto_attached_size = crypto_hash_digestsize(hash); + + if (!ctl->hash_keysize) + return hash; + + err = crypto_hash_setkey(hash, key, ctl->hash_keysize); + if (err) { + dprintk("%s: failed to set key for hash '%s', err: %d.\n", + __func__, ctl->hash_algo, err); + goto err_out_free; + } + + return hash; + +err_out_free: + crypto_free_hash(hash); +err_out_exit: + return ERR_PTR(err); +} + +static struct crypto_ablkcipher *dst_init_cipher(struct dst_crypto_ctl *ctl, u8 *key) +{ + int err = -EINVAL; + struct crypto_ablkcipher *cipher; + + if (!ctl->cipher_keysize) + goto err_out_exit; + + cipher = crypto_alloc_ablkcipher(ctl->cipher_algo, 0, 0); + if (IS_ERR(cipher)) { + err = PTR_ERR(cipher); + dprintk("%s: failed to allocate cipher '%s', err: %d.\n", + __func__, ctl->cipher_algo, err); + goto err_out_exit; + } + + crypto_ablkcipher_clear_flags(cipher, ~0); + + err = crypto_ablkcipher_setkey(cipher, key, ctl->cipher_keysize); + if (err) { + dprintk("%s: failed to set key for cipher '%s', err: %d.\n", + __func__, ctl->cipher_algo, err); + goto err_out_free; + } + + return cipher; + +err_out_free: + crypto_free_ablkcipher(cipher); +err_out_exit: + return ERR_PTR(err); +} + +/* + * Crypto engine has a pool of pages to encrypt data into before sending + * it over the network. This pool is freed/allocated here. + */ +static void dst_crypto_pages_free(struct dst_crypto_engine *e) +{ + unsigned int i; + + for (i=0; ipage_num; ++i) + __free_page(e->pages[i]); + kfree(e->pages); +} + +static int dst_crypto_pages_alloc(struct dst_crypto_engine *e, int num) +{ + int i; + + e->pages = kmalloc(num * sizeof(struct page **), GFP_KERNEL); + if (!e->pages) + return -ENOMEM; + + for (i=0; ipages[i] = alloc_page(GFP_KERNEL); + if (!e->pages[i]) + goto err_out_free_pages; + } + + e->page_num = num; + return 0; + +err_out_free_pages: + while (--i >= 0) + __free_page(e->pages[i]); + + kfree(e->pages); + return -ENOMEM; +} + +/* + * Initialize crypto engine for given node. + * Setup cipher/hash, keys, pool of threads and private data. + */ +static int dst_crypto_engine_init(struct dst_crypto_engine *e, struct dst_node *n) +{ + int err; + struct dst_crypto_ctl *ctl = &n->crypto; + + err = dst_crypto_pages_alloc(e, n->max_pages); + if (err) + goto err_out_exit; + + e->size = PAGE_SIZE; + e->data = kmalloc(e->size, GFP_KERNEL); + if (!e->data) { + err = -ENOMEM; + goto err_out_free_pages; + } + + if (ctl->hash_algo[0]) { + e->hash = dst_init_hash(ctl, n->hash_key); + if (IS_ERR(e->hash)) { + err = PTR_ERR(e->hash); + e->hash = NULL; + goto err_out_free; + } + } + + if (ctl->cipher_algo[0]) { + e->cipher = dst_init_cipher(ctl, n->cipher_key); + if (IS_ERR(e->cipher)) { + err = PTR_ERR(e->cipher); + e->cipher = NULL; + goto err_out_free_hash; + } + } + + return 0; + +err_out_free_hash: + crypto_free_hash(e->hash); +err_out_free: + kfree(e->data); +err_out_free_pages: + dst_crypto_pages_free(e); +err_out_exit: + return err; +} + +static void dst_crypto_engine_exit(struct dst_crypto_engine *e) +{ + if (e->hash) + crypto_free_hash(e->hash); + if (e->cipher) + crypto_free_ablkcipher(e->cipher); + dst_crypto_pages_free(e); + kfree(e->data); +} + +/* + * Waiting for cipher processing to be completed. + */ +struct dst_crypto_completion +{ + struct completion complete; + int error; +}; + +static void dst_crypto_complete(struct crypto_async_request *req, int err) +{ + struct dst_crypto_completion *c = req->data; + + if (err == -EINPROGRESS) + return; + + dprintk("%s: req: %p, err: %d.\n", __func__, req, err); + c->error = err; + complete(&c->complete); +} + +static int dst_crypto_process(struct ablkcipher_request *req, + struct scatterlist *sg_dst, struct scatterlist *sg_src, + void *iv, int enc, unsigned long timeout) +{ + struct dst_crypto_completion c; + int err; + + init_completion(&c.complete); + c.error = -EINPROGRESS; + + ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + dst_crypto_complete, &c); + + ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv); + + if (enc) + err = crypto_ablkcipher_encrypt(req); + else + err = crypto_ablkcipher_decrypt(req); + + switch (err) { + case -EINPROGRESS: + case -EBUSY: + err = wait_for_completion_interruptible_timeout(&c.complete, + timeout); + if (!err) + err = -ETIMEDOUT; + else + err = c.error; + break; + default: + break; + } + + return err; +} + +/* + * DST uses generic iteration approach for data crypto processing. + * Single block IO request is switched into array of scatterlists, + * which are submitted to the crypto processing iterator. + * + * Input and output iterator initialization are different, since + * in output case we can not encrypt data in-place and need a + * temporary storage, which is then being sent to the remote peer. + */ +static int dst_trans_iter_out(struct bio *bio, struct dst_crypto_engine *e, + int (* iterator) (struct dst_crypto_engine *e, + struct scatterlist *dst, + struct scatterlist *src)) +{ + struct bio_vec *bv; + int err, i; + + sg_init_table(e->src, bio->bi_vcnt); + sg_init_table(e->dst, bio->bi_vcnt); + + bio_for_each_segment(bv, bio, i) { + sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset); + sg_set_page(&e->dst[i], e->pages[i], bv->bv_len, bv->bv_offset); + + err = iterator(e, &e->dst[i], &e->src[i]); + if (err) + return err; + } + + return 0; +} + +static int dst_trans_iter_in(struct bio *bio, struct dst_crypto_engine *e, + int (* iterator) (struct dst_crypto_engine *e, + struct scatterlist *dst, + struct scatterlist *src)) +{ + struct bio_vec *bv; + int err, i; + + sg_init_table(e->src, bio->bi_vcnt); + sg_init_table(e->dst, bio->bi_vcnt); + + bio_for_each_segment(bv, bio, i) { + sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset); + sg_set_page(&e->dst[i], bv->bv_page, bv->bv_len, bv->bv_offset); + + err = iterator(e, &e->dst[i], &e->src[i]); + if (err) + return err; + } + + return 0; +} + +static int dst_crypt_iterator(struct dst_crypto_engine *e, + struct scatterlist *sg_dst, struct scatterlist *sg_src) +{ + struct ablkcipher_request *req = e->data; + u8 iv[32]; + + memset(iv, 0, sizeof(iv)); + + memcpy(iv, &e->iv, sizeof(e->iv)); + + return dst_crypto_process(req, sg_dst, sg_src, iv, e->enc, e->timeout); +} + +static int dst_crypt(struct dst_crypto_engine *e, struct bio *bio) +{ + struct ablkcipher_request *req = e->data; + + memset(req, 0, sizeof(struct ablkcipher_request)); + ablkcipher_request_set_tfm(req, e->cipher); + + if (e->enc) + return dst_trans_iter_out(bio, e, dst_crypt_iterator); + else + return dst_trans_iter_in(bio, e, dst_crypt_iterator); +} + +static int dst_hash_iterator(struct dst_crypto_engine *e, + struct scatterlist *sg_dst, struct scatterlist *sg_src) +{ + return crypto_hash_update(e->data, sg_src, sg_src->length); +} + +static int dst_hash(struct dst_crypto_engine *e, struct bio *bio, void *dst) +{ + struct hash_desc *desc = e->data; + int err; + + desc->tfm = e->hash; + desc->flags = 0; + + err = crypto_hash_init(desc); + if (err) + return err; + + err = dst_trans_iter_in(bio, e, dst_hash_iterator); + if (err) + return err; + + err = crypto_hash_final(desc, dst); + if (err) + return err; + + return 0; +} + +/* + * Initialize/cleanup a crypto thread. The only thing it should + * do is to allocate a pool of pages as temporary storage. + * And to setup cipher and/or hash. + */ +static void *dst_crypto_thread_init(void *data) +{ + struct dst_node *n = data; + struct dst_crypto_engine *e; + int err = -ENOMEM; + + e = kzalloc(sizeof(struct dst_crypto_engine), GFP_KERNEL); + if (!e) + goto err_out_exit; + e->src = kcalloc(2 * n->max_pages, sizeof(struct scatterlist), + GFP_KERNEL); + if (!e->src) + goto err_out_free; + + e->dst = e->src + n->max_pages; + + err = dst_crypto_engine_init(e, n); + if (err) + goto err_out_free_all; + + return e; + +err_out_free_all: + kfree(e->src); +err_out_free: + kfree(e); +err_out_exit: + return ERR_PTR(err); +} + +static void dst_crypto_thread_cleanup(void *private) +{ + struct dst_crypto_engine *e = private; + + dst_crypto_engine_exit(e); + kfree(e->src); + kfree(e); +} + +/* + * Initialize crypto engine for given node: store keys, create pool + * of threads, initialize each one. + * + * Each thread has unique ID, but 0 and 1 are reserved for receiving and accepting + * threads (if export node), so IDs could start from 2, but starting them + * from 10 allows easily understand what this thread is for. + */ +int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl) +{ + void *key = (ctl + 1); + int err = -ENOMEM, i; + char name[32]; + + if (ctl->hash_keysize) { + n->hash_key = kmalloc(ctl->hash_keysize, GFP_KERNEL); + if (!n->hash_key) + goto err_out_exit; + memcpy(n->hash_key, key, ctl->hash_keysize); + } + + if (ctl->cipher_keysize) { + n->cipher_key = kmalloc(ctl->cipher_keysize, GFP_KERNEL); + if (!n->cipher_key) + goto err_out_free_hash; + memcpy(n->cipher_key, key, ctl->cipher_keysize); + } + memcpy(&n->crypto, ctl, sizeof(struct dst_crypto_ctl)); + + for (i=0; ithread_num; ++i) { + snprintf(name, sizeof(name), "%s-crypto-%d", n->name, i); + /* Unique ids... */ + err = thread_pool_add_worker(n->pool, name, i+10, + dst_crypto_thread_init, dst_crypto_thread_cleanup, n); + if (err) + goto err_out_free_threads; + } + + return 0; + +err_out_free_threads: + while (--i >= 0) + thread_pool_del_worker_id(n->pool, i+10); + + if (ctl->cipher_keysize) + kfree(n->cipher_key); + ctl->cipher_keysize = 0; +err_out_free_hash: + if (ctl->hash_keysize) + kfree(n->hash_key); + ctl->hash_keysize = 0; +err_out_exit: + return err; +} + +void dst_node_crypto_exit(struct dst_node *n) +{ + struct dst_crypto_ctl *ctl = &n->crypto; + + if (ctl->cipher_algo[0] || ctl->hash_algo[0]) { + kfree(n->hash_key); + kfree(n->cipher_key); + } +} + +/* + * Thrad pool setup callback. Just stores a transaction in private data. + */ +static int dst_trans_crypto_setup(void *crypto_engine, void *trans) +{ + struct dst_crypto_engine *e = crypto_engine; + + e->private = trans; + return 0; +} + +#if 0 +static void dst_dump_bio(struct bio *bio) +{ + u8 *p; + struct bio_vec *bv; + int i; + + bio_for_each_segment(bv, bio, i) { + dprintk("%s: %llu/%u: size: %u, offset: %u, data: ", + __func__, bio->bi_sector, bio->bi_size, + bv->bv_len, bv->bv_offset); + + p = kmap(bv->bv_page) + bv->bv_offset; + for (i=0; ibv_len; ++i) + printk("%02x ", p[i]); + kunmap(bv->bv_page); + printk("\n"); + } +} +#endif + +/* + * Encrypt/hash data and send it to the network. + */ +static int dst_crypto_process_sending(struct dst_crypto_engine *e, + struct bio *bio, u8 *hash) +{ + int err; + + if (e->cipher) { + err = dst_crypt(e, bio); + if (err) + goto err_out_exit; + } + + if (e->hash) { + err = dst_hash(e, bio, hash); + if (err) + goto err_out_exit; + +#ifdef CONFIG_DST_DEBUG + { + unsigned int i; + + /* dst_dump_bio(bio); */ + + printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash: ", + __func__, (u64)bio->bi_sector, + bio->bi_size, bio_data_dir(bio)); + for (i=0; ihash); ++i) + printk("%02x ", hash[i]); + printk("\n"); + } +#endif + } + + return 0; + +err_out_exit: + return err; +} + +/* + * Check if received data is valid. Decipher if it is. + */ +static int dst_crypto_process_receiving(struct dst_crypto_engine *e, + struct bio *bio, u8 *hash, u8 *recv_hash) +{ + int err; + + if (e->hash) { + int mismatch; + + err = dst_hash(e, bio, hash); + if (err) + goto err_out_exit; + + mismatch = !!memcmp(recv_hash, hash, + crypto_hash_digestsize(e->hash)); +#ifdef CONFIG_DST_DEBUG + /* dst_dump_bio(bio); */ + + printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash mismatch: %d", + __func__, (u64)bio->bi_sector, bio->bi_size, + bio_data_dir(bio), mismatch); + if (mismatch) { + unsigned int i; + + printk(", recv/calc: "); + for (i=0; ihash); ++i) { + printk("%02x/%02x ", recv_hash[i], hash[i]); + } + } + printk("\n"); +#endif + err = -1; + if (mismatch) + goto err_out_exit; + } + + if (e->cipher) { + err = dst_crypt(e, bio); + if (err) + goto err_out_exit; + } + + return 0; + +err_out_exit: + return err; +} + +/* + * Thread pool callback to encrypt data and send it to the netowork. + */ +static int dst_trans_crypto_action(void *crypto_engine, void *schedule_data) +{ + struct dst_crypto_engine *e = crypto_engine; + struct dst_trans *t = schedule_data; + struct bio *bio = t->bio; + int err; + + dprintk("%s: t: %p, gen: %llu, cipher: %p, hash: %p.\n", + __func__, t, t->gen, e->cipher, e->hash); + + e->enc = t->enc; + e->iv = dst_gen_iv(t); + + if (bio_data_dir(bio) == WRITE) { + err = dst_crypto_process_sending(e, bio, t->cmd.hash); + if (err) + goto err_out_exit; + + if (e->hash) { + t->cmd.csize = crypto_hash_digestsize(e->hash); + t->cmd.size += t->cmd.csize; + } + + return dst_trans_send(t); + } else { + u8 *hash = e->data + e->size/2; + + err = dst_crypto_process_receiving(e, bio, hash, t->cmd.hash); + if (err) + goto err_out_exit; + + dst_trans_remove(t); + dst_trans_put(t); + } + + return 0; + +err_out_exit: + t->error = err; + dst_trans_put(t); + return err; +} + +/* + * Schedule crypto processing for given transaction. + */ +int dst_trans_crypto(struct dst_trans *t) +{ + struct dst_node *n = t->n; + int err; + + err = thread_pool_schedule(n->pool, + dst_trans_crypto_setup, dst_trans_crypto_action, + t, MAX_SCHEDULE_TIMEOUT); + if (err) + goto err_out_exit; + + return 0; + +err_out_exit: + dst_trans_put(t); + return err; +} + +/* + * Crypto machinery for the export node. + */ +static int dst_export_crypto_setup(void *crypto_engine, void *bio) +{ + struct dst_crypto_engine *e = crypto_engine; + + e->private = bio; + return 0; +} + +static int dst_export_crypto_action(void *crypto_engine, void *schedule_data) +{ + struct dst_crypto_engine *e = crypto_engine; + struct bio *bio = schedule_data; + struct dst_export_priv *p = bio->bi_private; + int err; + + dprintk("%s: e: %p, data: %p, bio: %llu/%u, dir: %lu.\n", __func__, + e, e->data, (u64)bio->bi_sector, bio->bi_size, bio_data_dir(bio)); + + e->enc = (bio_data_dir(bio) == READ); + e->iv = p->cmd.id; + + if (bio_data_dir(bio) == WRITE) { + u8 *hash = e->data + e->size/2; + + err = dst_crypto_process_receiving(e, bio, hash, p->cmd.hash); + if (err) + goto err_out_exit; + + generic_make_request(bio); + } else { + err = dst_crypto_process_sending(e, bio, p->cmd.hash); + if (err) + goto err_out_exit; + + if (e->hash) { + p->cmd.csize = crypto_hash_digestsize(e->hash); + p->cmd.size += p->cmd.csize; + } + + err = dst_export_send_bio(bio); + } + return 0; + +err_out_exit: + bio_put(bio); + return err; +} + +int dst_export_crypto(struct dst_node *n, struct bio *bio) +{ + int err; + + err = thread_pool_schedule(n->pool, + dst_export_crypto_setup, dst_export_crypto_action, + bio, MAX_SCHEDULE_TIMEOUT); + if (err) + goto err_out_exit; + + return 0; + +err_out_exit: + bio_put(bio); + return err; +} diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c new file mode 100644 index 000000000000..fad25b753042 --- /dev/null +++ b/drivers/staging/dst/dcore.c @@ -0,0 +1,995 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static int dst_major; + +static DEFINE_MUTEX(dst_hash_lock); +static struct list_head *dst_hashtable; +static unsigned int dst_hashtable_size = 128; +module_param(dst_hashtable_size, uint, 0644); + +static char dst_name[] = "Dementianting goldfish"; + +static DEFINE_IDR(dst_index_idr); +static struct cb_id cn_dst_id = { CN_DST_IDX, CN_DST_VAL }; + +/* + * DST sysfs tree for device called 'storage': + * + * /sys/bus/dst/devices/storage/ + * /sys/bus/dst/devices/storage/type : 192.168.4.80:1025 + * /sys/bus/dst/devices/storage/size : 800 + * /sys/bus/dst/devices/storage/name : storage + */ + +static int dst_dev_match(struct device *dev, struct device_driver *drv) +{ + return 1; +} + +static struct bus_type dst_dev_bus_type = { + .name = "dst", + .match = &dst_dev_match, +}; + +static void dst_node_release(struct device *dev) +{ + struct dst_info *info = container_of(dev, struct dst_info, device); + + kfree(info); +} + +static struct device dst_node_dev = { + .bus = &dst_dev_bus_type, + .release = &dst_node_release +}; + +/* + * Setting size of the node after it was changed. + */ +static void dst_node_set_size(struct dst_node *n) +{ + struct block_device *bdev; + + set_capacity(n->disk, n->size >> 9); + + bdev = bdget_disk(n->disk, 0); + if (bdev) { + mutex_lock(&bdev->bd_inode->i_mutex); + i_size_write(bdev->bd_inode, n->size); + mutex_unlock(&bdev->bd_inode->i_mutex); + bdput(bdev); + } +} + +/* + * Distributed storage request processing function. + */ +static int dst_request(struct request_queue *q, struct bio *bio) +{ + struct dst_node *n = q->queuedata; + int err = -EIO; + + if (bio_empty_barrier(bio) && !q->prepare_discard_fn) { + /* + * This is a dirty^Wnice hack, but if we complete this + * operation with -EOPNOTSUPP like intended, XFS + * will stuck and freeze the machine. This may be + * not particulary XFS problem though, but it is the + * only FS which sends empty barrier at umount time + * I worked with. + * + * Empty barriers are not allowed anyway, see 51fd77bd9f512 + * for example, although later it was changed to bio_discard() + * only, which does not work in this case. + */ + //err = -EOPNOTSUPP; + err = 0; + goto end_io; + } + + bio_get(bio); + + return dst_process_bio(n, bio); + +end_io: + bio_endio(bio, err); + return err; +} + +/* + * Open/close callbacks for appropriate block device. + */ +static int dst_bdev_open(struct block_device *bdev, fmode_t mode) +{ + struct dst_node *n = bdev->bd_disk->private_data; + + dst_node_get(n); + return 0; +} + +static int dst_bdev_release(struct gendisk *disk, fmode_t mode) +{ + struct dst_node *n = disk->private_data; + + dst_node_put(n); + return 0; +} + +static struct block_device_operations dst_blk_ops = { + .open = dst_bdev_open, + .release = dst_bdev_release, + .owner = THIS_MODULE, +}; + +/* + * Block layer binding - disk is created when array is fully configured + * by userspace request. + */ +static int dst_node_create_disk(struct dst_node *n) +{ + int err = -ENOMEM; + u32 index = 0; + + n->queue = blk_init_queue(NULL, NULL); + if (!n->queue) + goto err_out_exit; + + n->queue->queuedata = n; + blk_queue_make_request(n->queue, dst_request); + blk_queue_max_phys_segments(n->queue, n->max_pages); + blk_queue_max_hw_segments(n->queue, n->max_pages); + + err = -ENOMEM; + n->disk = alloc_disk(1); + if (!n->disk) + goto err_out_free_queue; + + if (!(n->state->permissions & DST_PERM_WRITE)) { + printk(KERN_INFO "DST node %s attached read-only.\n", n->name); + set_disk_ro(n->disk, 1); + } + + if (!idr_pre_get(&dst_index_idr, GFP_KERNEL)) + goto err_out_put; + + mutex_lock(&dst_hash_lock); + err = idr_get_new(&dst_index_idr, NULL, &index); + mutex_unlock(&dst_hash_lock); + if (err) + goto err_out_put; + + n->disk->major = dst_major; + n->disk->first_minor = index; + n->disk->fops = &dst_blk_ops; + n->disk->queue = n->queue; + n->disk->private_data = n; + snprintf(n->disk->disk_name, sizeof(n->disk->disk_name), "dst-%s", n->name); + + return 0; + +err_out_put: + put_disk(n->disk); +err_out_free_queue: + blk_cleanup_queue(n->queue); +err_out_exit: + return err; +} + +/* + * Sysfs machinery: show device's size. + */ +static ssize_t dst_show_size(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dst_info *info = container_of(dev, struct dst_info, device); + + return sprintf(buf, "%llu\n", info->size); +} + +/* + * Show local exported device. + */ +static ssize_t dst_show_local(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dst_info *info = container_of(dev, struct dst_info, device); + + return sprintf(buf, "%s\n", info->local); +} + +/* + * Shows type of the remote node - device major/minor number + * for local nodes and address (af_inet ipv4/ipv6 only) for remote nodes. + */ +static ssize_t dst_show_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dst_info *info = container_of(dev, struct dst_info, device); + int family = info->net.addr.sa_family; + + if (family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)&info->net.addr; + return sprintf(buf, "%u.%u.%u.%u:%d\n", + NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); + } else if (family == AF_INET6) { + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&info->net.addr; + return sprintf(buf, + "%pi6:%d\n", + &sin->sin6_addr, ntohs(sin->sin6_port)); + } else { + int i, sz = PAGE_SIZE - 2; /* 0 symbol and '\n' below */ + int size, addrlen = info->net.addr.sa_data_len; + unsigned char *a = (unsigned char *)&info->net.addr.sa_data; + char *buf_orig = buf; + + size = snprintf(buf, sz, "family: %d, addrlen: %u, addr: ", + family, addrlen); + sz -= size; + buf += size; + + for (i=0; iinfo->device, + &dst_node_attrs[i]); + if (err) + goto err_out_remove_all; + } + return 0; + +err_out_remove_all: + while (--i >= 0) + device_remove_file(&n->info->device, + &dst_node_attrs[i]); + + return err; +} + +static void dst_remove_node_attributes(struct dst_node *n) +{ + int i; + + for (i=0; iinfo->device, + &dst_node_attrs[i]); +} + +/* + * Sysfs cleanup and initialization. + * Shows number of useful parameters. + */ +static void dst_node_sysfs_exit(struct dst_node *n) +{ + if (n->info) { + dst_remove_node_attributes(n); + device_unregister(&n->info->device); + n->info = NULL; + } +} + +static int dst_node_sysfs_init(struct dst_node *n) +{ + int err; + + n->info = kzalloc(sizeof(struct dst_info), GFP_KERNEL); + if (!n->info) + return -ENOMEM; + + memcpy(&n->info->device, &dst_node_dev, sizeof(struct device)); + n->info->size = n->size; + + dev_set_name(&n->info->device, "dst-%s", n->name); + err = device_register(&n->info->device); + if (err) { + dprintk(KERN_ERR "Failed to register node '%s', err: %d.\n", + n->name, err); + goto err_out_exit; + } + + dst_create_node_attributes(n); + + return 0; + +err_out_exit: + kfree(n->info); + n->info = NULL; + return err; +} + +/* + * DST node hash tables machinery. + */ +static inline unsigned int dst_hash(char *str, unsigned int size) +{ + return (jhash(str, size, 0) % dst_hashtable_size); +} + +static void dst_node_remove(struct dst_node *n) +{ + mutex_lock(&dst_hash_lock); + list_del_init(&n->node_entry); + mutex_unlock(&dst_hash_lock); +} + +static void dst_node_add(struct dst_node *n) +{ + unsigned hash = dst_hash(n->name, sizeof(n->name)); + + mutex_lock(&dst_hash_lock); + list_add_tail(&n->node_entry, &dst_hashtable[hash]); + mutex_unlock(&dst_hash_lock); +} + +/* + * Cleaning node when it is about to be freed. + * There are still users of the socket though, + * so connection cleanup should be protected. + */ +static void dst_node_cleanup(struct dst_node *n) +{ + struct dst_state *st = n->state; + + if (!st) + return; + + if (n->queue) { + blk_cleanup_queue(n->queue); + + mutex_lock(&dst_hash_lock); + idr_remove(&dst_index_idr, n->disk->first_minor); + mutex_unlock(&dst_hash_lock); + + put_disk(n->disk); + } + + if (n->bdev) { + sync_blockdev(n->bdev); + blkdev_put(n->bdev, FMODE_READ|FMODE_WRITE); + } + + dst_state_lock(st); + st->need_exit = 1; + dst_state_exit_connected(st); + dst_state_unlock(st); + + wake_up(&st->thread_wait); + + dst_state_put(st); + n->state = NULL; +} + +/* + * Free security attributes attached to given node. + */ +static void dst_security_exit(struct dst_node *n) +{ + struct dst_secure *s, *tmp; + + list_for_each_entry_safe(s, tmp, &n->security_list, sec_entry) { + list_del(&s->sec_entry); + kfree(s); + } +} + +/* + * Free node when there are no more users. + * Actually node has to be freed on behalf od userspace process, + * since there are number of threads, which are embedded in the + * node, so they can not exit and free node from there, that is + * why there is a wakeup if reference counter is not equal to zero. + */ +void dst_node_put(struct dst_node *n) +{ + if (unlikely(!n)) + return; + + dprintk("%s: n: %p, refcnt: %d.\n", + __func__, n, atomic_read(&n->refcnt)); + + if (atomic_dec_and_test(&n->refcnt)) { + dst_node_remove(n); + n->trans_scan_timeout = 0; + dst_node_cleanup(n); + thread_pool_destroy(n->pool); + dst_node_sysfs_exit(n); + dst_node_crypto_exit(n); + dst_security_exit(n); + dst_node_trans_exit(n); + + kfree(n); + + dprintk("%s: freed n: %p.\n", __func__, n); + } else { + wake_up(&n->wait); + } +} + +/* + * This function finds devices major/minor numbers for given pathname. + */ +static int dst_lookup_device(const char *path, dev_t *dev) +{ + int err; + struct nameidata nd; + struct inode *inode; + + err = path_lookup(path, LOOKUP_FOLLOW, &nd); + if (err) + return err; + + inode = nd.path.dentry->d_inode; + if (!inode) { + err = -ENOENT; + goto out; + } + + if (!S_ISBLK(inode->i_mode)) { + err = -ENOTBLK; + goto out; + } + + *dev = inode->i_rdev; + +out: + path_put(&nd.path); + return err; +} + +/* + * Setting up export device: lookup by the name, get its size + * and setup listening socket, which will accept clients, which + * will submit IO for given storage. + */ +static int dst_setup_export(struct dst_node *n, struct dst_ctl *ctl, + struct dst_export_ctl *le) +{ + int err; + dev_t dev = 0; /* gcc likes to scream here */ + + snprintf(n->info->local, sizeof(n->info->local), "%s", le->device); + + err = dst_lookup_device(le->device, &dev); + if (err) + return err; + + n->bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE); + if (!n->bdev) + return -ENODEV; + + if (n->size != 0) + n->size = min_t(loff_t, n->bdev->bd_inode->i_size, n->size); + else + n->size = n->bdev->bd_inode->i_size; + + n->info->size = n->size; + err = dst_node_init_listened(n, le); + if (err) + goto err_out_cleanup; + + return 0; + +err_out_cleanup: + blkdev_put(n->bdev, FMODE_READ|FMODE_WRITE); + n->bdev = NULL; + + return err; +} + +/* Empty thread pool callbacks for the network processing threads. */ +static inline void *dst_thread_network_init(void *data) +{ + dprintk("%s: data: %p.\n", __func__, data); + return data; +} + +static inline void dst_thread_network_cleanup(void *data) +{ + dprintk("%s: data: %p.\n", __func__, data); +} + +/* + * Allocate DST node and initialize some of its parameters. + */ +static struct dst_node *dst_alloc_node(struct dst_ctl *ctl, + int (*start)(struct dst_node *), + int num) +{ + struct dst_node *n; + int err; + + n = kzalloc(sizeof(struct dst_node), GFP_KERNEL); + if (!n) + return NULL; + + INIT_LIST_HEAD(&n->node_entry); + + INIT_LIST_HEAD(&n->security_list); + mutex_init(&n->security_lock); + + init_waitqueue_head(&n->wait); + + n->trans_scan_timeout = msecs_to_jiffies(ctl->trans_scan_timeout); + if (!n->trans_scan_timeout) + n->trans_scan_timeout = HZ; + + n->trans_max_retries = ctl->trans_max_retries; + if (!n->trans_max_retries) + n->trans_max_retries = 10; + + /* + * Pretty much arbitrary default numbers. + * 32 matches maximum number of pages in bio originated from ext3 (31). + */ + n->max_pages = ctl->max_pages; + if (!n->max_pages) + n->max_pages = 32; + + if (n->max_pages > 1024) + n->max_pages = 1024; + + n->start = start; + n->size = ctl->size; + + atomic_set(&n->refcnt, 1); + atomic_long_set(&n->gen, 0); + snprintf(n->name, sizeof(n->name), "%s", ctl->name); + + err = dst_node_sysfs_init(n); + if (err) + goto err_out_free; + + n->pool = thread_pool_create(num, n->name, dst_thread_network_init, + dst_thread_network_cleanup, n); + if (IS_ERR(n->pool)) { + err = PTR_ERR(n->pool); + goto err_out_sysfs_exit; + } + + dprintk("%s: n: %p, name: %s.\n", __func__, n, n->name); + + return n; + +err_out_sysfs_exit: + dst_node_sysfs_exit(n); +err_out_free: + kfree(n); + return NULL; +} + +/* + * Starting a node, connected to the remote server: + * register block device and initialize transaction mechanism. + * In revers order though. + * + * It will autonegotiate some parameters with the remote node + * and update local if needed. + * + * Transaction initialization should be the last thing before + * starting the node, since transaction should include not only + * block IO, but also crypto related data (if any), which are + * initialized separately. + */ +static int dst_start_remote(struct dst_node *n) +{ + int err; + + err = dst_node_trans_init(n, sizeof(struct dst_trans)); + if (err) + return err; + + err = dst_node_create_disk(n); + if (err) + return err; + + dst_node_set_size(n); + add_disk(n->disk); + + dprintk("DST: started remote node '%s', minor: %d.\n", n->name, n->disk->first_minor); + + return 0; +} + +/* + * Adding remote node and initialize connection. + */ +static int dst_add_remote(struct dst_node *n, struct dst_ctl *ctl, + void *data, unsigned int size) +{ + int err; + struct dst_network_ctl *rctl = data; + + if (n) + return -EEXIST; + + if (size != sizeof(struct dst_network_ctl)) + return -EINVAL; + + n = dst_alloc_node(ctl, dst_start_remote, 1); + if (!n) + return -ENOMEM; + + memcpy(&n->info->net, rctl, sizeof(struct dst_network_ctl)); + err = dst_node_init_connected(n, rctl); + if (err) + goto err_out_free; + + dst_node_add(n); + + return 0; + +err_out_free: + dst_node_put(n); + return err; +} + +/* + * Adding export node: initializing block device and listening socket. + */ +static int dst_add_export(struct dst_node *n, struct dst_ctl *ctl, + void *data, unsigned int size) +{ + int err; + struct dst_export_ctl *le = data; + + if (n) + return -EEXIST; + + if (size != sizeof(struct dst_export_ctl)) + return -EINVAL; + + n = dst_alloc_node(ctl, dst_start_export, 2); + if (!n) + return -EINVAL; + + err = dst_setup_export(n, ctl, le); + if (err) + goto err_out_free; + + dst_node_add(n); + + return 0; + +err_out_free: + dst_node_put(n); + return err; +} + +static int dst_node_remove_unload(struct dst_node *n) +{ + printk(KERN_INFO "STOPPED name: '%s', size: %llu.\n", + n->name, n->size); + + if (n->disk) + del_gendisk(n->disk); + + dst_node_remove(n); + dst_node_sysfs_exit(n); + + /* + * This is not a hack. Really. + * Node's reference counter allows to implement fine grained + * node freeing, but since all transactions (which hold node's + * reference counter) are processed in the dedicated thread, + * it is possible that reference will hit zero in that thread, + * so we will not be able to exit thread and cleanup the node. + * + * So, we remove disk, so no new activity is possible, and + * wait until all pending transaction are completed (either + * in receiving thread or by timeout in workqueue), in this + * case reference counter will be less or equal to 2 (once set in + * dst_alloc_node() and then in connector message parser; + * or when we force module unloading, and connector message + * parser does not hold a reference, in this case reference + * counter will be equal to 1), + * and subsequent dst_node_put() calls will free the node. + */ + dprintk("%s: going to sleep with %d refcnt.\n", __func__, atomic_read(&n->refcnt)); + wait_event(n->wait, atomic_read(&n->refcnt) <= 2); + + dst_node_put(n); + return 0; +} + +/* + * Remove node from the hash table. + */ +static int dst_del_node(struct dst_node *n, struct dst_ctl *ctl, + void *data, unsigned int size) +{ + if (!n) + return -ENODEV; + + return dst_node_remove_unload(n); +} + +/* + * Initialize crypto processing for given node. + */ +static int dst_crypto_init(struct dst_node *n, struct dst_ctl *ctl, + void *data, unsigned int size) +{ + struct dst_crypto_ctl *crypto = data; + + if (!n) + return -ENODEV; + + if (size != sizeof(struct dst_crypto_ctl) + crypto->hash_keysize + + crypto->cipher_keysize) + return -EINVAL; + + if (n->trans_cache) + return -EEXIST; + + return dst_node_crypto_init(n, crypto); +} + +/* + * Security attributes for given node. + */ +static int dst_security_init(struct dst_node *n, struct dst_ctl *ctl, + void *data, unsigned int size) +{ + struct dst_secure *s; + + if (!n) + return -ENODEV; + + if (size != sizeof(struct dst_secure_user)) + return -EINVAL; + + s = kmalloc(sizeof(struct dst_secure), GFP_KERNEL); + if (!s) + return -ENOMEM; + + memcpy(&s->sec, data, size); + + mutex_lock(&n->security_lock); + list_add_tail(&s->sec_entry, &n->security_list); + mutex_unlock(&n->security_lock); + + return 0; +} + +/* + * Kill'em all! + */ +static int dst_start_node(struct dst_node *n, struct dst_ctl *ctl, + void *data, unsigned int size) +{ + int err; + + if (!n) + return -ENODEV; + + if (n->trans_cache) + return 0; + + err = n->start(n); + if (err) + return err; + + printk(KERN_INFO "STARTED name: '%s', size: %llu.\n", n->name, n->size); + return 0; +} + +typedef int (*dst_command_func)(struct dst_node *n, struct dst_ctl *ctl, + void *data, unsigned int size); + +/* + * List of userspace commands. + */ +static dst_command_func dst_commands[] = { + [DST_ADD_REMOTE] = &dst_add_remote, + [DST_ADD_EXPORT] = &dst_add_export, + [DST_DEL_NODE] = &dst_del_node, + [DST_CRYPTO] = &dst_crypto_init, + [DST_SECURITY] = &dst_security_init, + [DST_START] = &dst_start_node, +}; + +/* + * Configuration parser. + */ +static void cn_dst_callback(void *data) +{ + struct dst_ctl *ctl; + struct cn_msg *msg = data; + int err; + struct dst_ctl_ack ack; + struct dst_node *n = NULL, *tmp; + unsigned int hash; + + if (msg->len < sizeof(struct dst_ctl)) { + err = -EBADMSG; + goto out; + } + + ctl = (struct dst_ctl *)msg->data; + + if (ctl->cmd >= DST_CMD_MAX) { + err = -EINVAL; + goto out; + } + hash = dst_hash(ctl->name, sizeof(ctl->name)); + + mutex_lock(&dst_hash_lock); + list_for_each_entry(tmp, &dst_hashtable[hash], node_entry) { + if (!memcmp(tmp->name, ctl->name, sizeof(tmp->name))) { + n = tmp; + dst_node_get(n); + break; + } + } + mutex_unlock(&dst_hash_lock); + + err = dst_commands[ctl->cmd](n, ctl, msg->data + sizeof(struct dst_ctl), + msg->len - sizeof(struct dst_ctl)); + + dst_node_put(n); +out: + memcpy(&ack.msg, msg, sizeof(struct cn_msg)); + + ack.msg.ack = msg->ack + 1; + ack.msg.len = sizeof(struct dst_ctl_ack) - sizeof(struct cn_msg); + + ack.error = err; + + cn_netlink_send(&ack.msg, 0, GFP_KERNEL); +} + +/* + * Global initialization: sysfs, hash table, block device registration, + * connector and various caches. + */ +static int __init dst_sysfs_init(void) +{ + return bus_register(&dst_dev_bus_type); +} + +static void dst_sysfs_exit(void) +{ + bus_unregister(&dst_dev_bus_type); +} + +static int __init dst_hashtable_init(void) +{ + unsigned int i; + + dst_hashtable = kcalloc(dst_hashtable_size, sizeof(struct list_head), + GFP_KERNEL); + if (!dst_hashtable) + return -ENOMEM; + + for (i=0; i"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/dst/export.c b/drivers/staging/dst/export.c new file mode 100644 index 000000000000..80ae4ebe610a --- /dev/null +++ b/drivers/staging/dst/export.c @@ -0,0 +1,657 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Export bioset is used for server block IO requests. + */ +static struct bio_set *dst_bio_set; + +int __init dst_export_init(void) +{ + int err = -ENOMEM; + + dst_bio_set = bioset_create(32, sizeof(struct dst_export_priv)); + if (!dst_bio_set) + goto err_out_exit; + + return 0; + +err_out_exit: + return err; +} + +void dst_export_exit(void) +{ + bioset_free(dst_bio_set); +} + +/* + * When client connects and autonegotiates with the server node, + * its permissions are checked in a security attributes and sent + * back. + */ +static unsigned int dst_check_permissions(struct dst_state *main, struct dst_state *st) +{ + struct dst_node *n = main->node; + struct dst_secure *sentry; + struct dst_secure_user *s; + struct saddr *sa = &st->ctl.addr; + unsigned int perm = 0; + + mutex_lock(&n->security_lock); + list_for_each_entry(sentry, &n->security_list, sec_entry) { + s = &sentry->sec; + + if (s->addr.sa_family != sa->sa_family) + continue; + + if (s->addr.sa_data_len != sa->sa_data_len) + continue; + + /* + * This '2' below is a port field. This may be very wrong to do + * in atalk for example though. If there will be any need to extent + * protocol to something else, I can create per-family helpers and + * use them instead of this memcmp. + */ + if (memcmp(s->addr.sa_data + 2, sa->sa_data + 2, + sa->sa_data_len - 2)) + continue; + + perm = s->permissions; + } + mutex_unlock(&n->security_lock); + + return perm; +} + +/* + * Accept new client: allocate appropriate network state and check permissions. + */ +static struct dst_state *dst_accept_client(struct dst_state *st) +{ + unsigned int revents = 0; + unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; + unsigned int mask = err_mask | POLLIN; + struct dst_node *n = st->node; + int err = 0; + struct socket *sock = NULL; + struct dst_state *new; + + while (!err && !sock) { + revents = dst_state_poll(st); + + if (!(revents & mask)) { + DEFINE_WAIT(wait); + + for (;;) { + prepare_to_wait(&st->thread_wait, + &wait, TASK_INTERRUPTIBLE); + if (!n->trans_scan_timeout || st->need_exit) + break; + + revents = dst_state_poll(st); + + if (revents & mask) + break; + + if (signal_pending(current)) + break; + + /* + * Magic HZ? Polling check above is not safe in + * all cases (like socket reset in BH context), + * so it is simpler just to postpone it to the + * process context instead of implementing special + * locking there. + */ + schedule_timeout(HZ); + } + finish_wait(&st->thread_wait, &wait); + } + + err = -ECONNRESET; + dst_state_lock(st); + + dprintk("%s: st: %p, revents: %x [err: %d, in: %d].\n", + __func__, st, revents, revents & err_mask, + revents & POLLIN); + + if (revents & err_mask) { + dprintk("%s: revents: %x, socket: %p, err: %d.\n", + __func__, revents, st->socket, err); + err = -ECONNRESET; + } + + if (!n->trans_scan_timeout || st->need_exit) + err = -ENODEV; + + if (st->socket && (revents & POLLIN)) + err = kernel_accept(st->socket, &sock, 0); + + dst_state_unlock(st); + } + + if (err) + goto err_out_exit; + + new = dst_state_alloc(st->node); + if (!new) { + err = -ENOMEM; + goto err_out_release; + } + new->socket = sock; + + new->ctl.addr.sa_data_len = sizeof(struct sockaddr); + err = kernel_getpeername(sock, (struct sockaddr *)&new->ctl.addr, + (int *)&new->ctl.addr.sa_data_len); + if (err) + goto err_out_put; + + new->permissions = dst_check_permissions(st, new); + if (new->permissions == 0) { + err = -EPERM; + dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr, + "Client is not allowed to connect"); + goto err_out_put; + } + + err = dst_poll_init(new); + if (err) + goto err_out_put; + + dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr, + "Connected client"); + + return new; + +err_out_put: + dst_state_put(new); +err_out_release: + sock_release(sock); +err_out_exit: + return ERR_PTR(err); +} + +/* + * Each server's block request sometime finishes. + * Usually it happens in hard irq context of the appropriate controller, + * so to play good with all cases we just queue BIO into the queue + * and wake up processing thread, which gets completed request and + * send (encrypting if needed) it back to the client (if it was a read + * request), or sends back reply that writing succesfully completed. + */ +static int dst_export_process_request_queue(struct dst_state *st) +{ + unsigned long flags; + struct dst_export_priv *p = NULL; + struct bio *bio; + int err = 0; + + while (!list_empty(&st->request_list)) { + spin_lock_irqsave(&st->request_lock, flags); + if (!list_empty(&st->request_list)) { + p = list_first_entry(&st->request_list, + struct dst_export_priv, request_entry); + list_del(&p->request_entry); + } + spin_unlock_irqrestore(&st->request_lock, flags); + + if (!p) + break; + + bio = p->bio; + + if (dst_need_crypto(st->node) && (bio_data_dir(bio) == READ)) + err = dst_export_crypto(st->node, bio); + else + err = dst_export_send_bio(bio); + + if (err) + break; + } + + return err; +} + +/* + * Cleanup export state. + * It has to wait until all requests are finished, + * and then free them all. + */ +static void dst_state_cleanup_export(struct dst_state *st) +{ + struct dst_export_priv *p; + unsigned long flags; + + /* + * This loop waits for all pending bios to be completed and freed. + */ + while (atomic_read(&st->refcnt) > 1) { + dprintk("%s: st: %p, refcnt: %d, list_empty: %d.\n", + __func__, st, atomic_read(&st->refcnt), + list_empty(&st->request_list)); + wait_event_timeout(st->thread_wait, + (atomic_read(&st->refcnt) == 1) || + !list_empty(&st->request_list), + HZ/2); + + while (!list_empty(&st->request_list)) { + p = NULL; + spin_lock_irqsave(&st->request_lock, flags); + if (!list_empty(&st->request_list)) { + p = list_first_entry(&st->request_list, + struct dst_export_priv, request_entry); + list_del(&p->request_entry); + } + spin_unlock_irqrestore(&st->request_lock, flags); + + if (p) + bio_put(p->bio); + + dprintk("%s: st: %p, refcnt: %d, list_empty: %d, p: %p.\n", + __func__, st, atomic_read(&st->refcnt), + list_empty(&st->request_list), p); + } + } + + dst_state_put(st); +} + +/* + * Client accepting thread. + * Not only accepts new connection, but also schedules receiving thread + * and performs request completion described above. + */ +static int dst_accept(void *init_data, void *schedule_data) +{ + struct dst_state *main_st = schedule_data; + struct dst_node *n = init_data; + struct dst_state *st; + int err; + + while (n->trans_scan_timeout && !main_st->need_exit) { + dprintk("%s: main_st: %p, n: %p.\n", __func__, main_st, n); + st = dst_accept_client(main_st); + if (IS_ERR(st)) + continue; + + err = dst_state_schedule_receiver(st); + if (!err) { + while (n->trans_scan_timeout) { + err = wait_event_interruptible_timeout(st->thread_wait, + !list_empty(&st->request_list) || + !n->trans_scan_timeout || + st->need_exit, + HZ); + + if (!n->trans_scan_timeout || st->need_exit) + break; + + if (list_empty(&st->request_list)) + continue; + + err = dst_export_process_request_queue(st); + if (err) + break; + } + + st->need_exit = 1; + wake_up(&st->thread_wait); + } + + dst_state_cleanup_export(st); + } + + dprintk("%s: freeing listening socket st: %p.\n", __func__, main_st); + + dst_state_lock(main_st); + dst_poll_exit(main_st); + dst_state_socket_release(main_st); + dst_state_unlock(main_st); + dst_state_put(main_st); + dprintk("%s: freed listening socket st: %p.\n", __func__, main_st); + + return 0; +} + +int dst_start_export(struct dst_node *n) +{ + if (list_empty(&n->security_list)) { + printk(KERN_ERR "You are trying to export node '%s' without security attributes.\n" + "No clients will be allowed to connect. Exiting.\n", n->name); + return -EINVAL; + } + return dst_node_trans_init(n, sizeof(struct dst_export_priv)); +} + +/* + * Initialize listening state and schedule accepting thread. + */ +int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le) +{ + struct dst_state *st; + int err = -ENOMEM; + struct dst_network_ctl *ctl = &le->ctl; + + memcpy(&n->info->net, ctl, sizeof(struct dst_network_ctl)); + + st = dst_state_alloc(n); + if (IS_ERR(st)) { + err = PTR_ERR(st); + goto err_out_exit; + } + memcpy(&st->ctl, ctl, sizeof(struct dst_network_ctl)); + + err = dst_state_socket_create(st); + if (err) + goto err_out_put; + + st->socket->sk->sk_reuse = 1; + + err = kernel_bind(st->socket, (struct sockaddr *)&ctl->addr, + ctl->addr.sa_data_len); + if (err) + goto err_out_socket_release; + + err = kernel_listen(st->socket, 1024); + if (err) + goto err_out_socket_release; + n->state = st; + + err = dst_poll_init(st); + if (err) + goto err_out_socket_release; + + dst_state_get(st); + + err = thread_pool_schedule(n->pool, dst_thread_setup, + dst_accept, st, MAX_SCHEDULE_TIMEOUT); + if (err) + goto err_out_poll_exit; + + return 0; + +err_out_poll_exit: + dst_poll_exit(st); +err_out_socket_release: + dst_state_socket_release(st); +err_out_put: + dst_state_put(st); +err_out_exit: + n->state = NULL; + return err; +} + +/* + * Free bio and related private data. + * Also drop a reference counter for appropriate state, + * which waits when there are no more block IOs in-flight. + */ +static void dst_bio_destructor(struct bio *bio) +{ + struct bio_vec *bv; + struct dst_export_priv *priv = bio->bi_private; + int i; + + bio_for_each_segment(bv, bio, i) { + if (!bv->bv_page) + break; + + __free_page(bv->bv_page); + } + + if (priv) + dst_state_put(priv->state); + bio_free(bio, dst_bio_set); +} + +/* + * Block IO completion. Queue request to be sent back to + * the client (or just confirmation). + */ +static void dst_bio_end_io(struct bio *bio, int err) +{ + struct dst_export_priv *p = bio->bi_private; + struct dst_state *st = p->state; + unsigned long flags; + + spin_lock_irqsave(&st->request_lock, flags); + list_add_tail(&p->request_entry, &st->request_list); + spin_unlock_irqrestore(&st->request_lock, flags); + + wake_up(&st->thread_wait); +} + +/* + * Allocate read request for the server. + */ +static int dst_export_read_request(struct bio *bio, unsigned int total_size) +{ + unsigned int size; + struct page *page; + int err; + + while (total_size) { + err = -ENOMEM; + page = alloc_page(GFP_KERNEL); + if (!page) + goto err_out_exit; + + size = min_t(unsigned int, PAGE_SIZE, total_size); + + err = bio_add_page(bio, page, size, 0); + dprintk("%s: bio: %llu/%u, size: %u, err: %d.\n", + __func__, (u64)bio->bi_sector, bio->bi_size, + size, err); + if (err <= 0) + goto err_out_free_page; + + total_size -= size; + } + + return 0; + +err_out_free_page: + __free_page(page); +err_out_exit: + return err; +} + +/* + * Allocate write request for the server. + * Should not only get pages, but also read data from the network. + */ +static int dst_export_write_request(struct dst_state *st, + struct bio *bio, unsigned int total_size) +{ + unsigned int size; + struct page *page; + void *data; + int err; + + while (total_size) { + err = -ENOMEM; + page = alloc_page(GFP_KERNEL); + if (!page) + goto err_out_exit; + + data = kmap(page); + if (!data) + goto err_out_free_page; + + size = min_t(unsigned int, PAGE_SIZE, total_size); + + err = dst_data_recv(st, data, size); + if (err) + goto err_out_unmap_page; + + err = bio_add_page(bio, page, size, 0); + if (err <= 0) + goto err_out_unmap_page; + + kunmap(page); + + total_size -= size; + } + + return 0; + +err_out_unmap_page: + kunmap(page); +err_out_free_page: + __free_page(page); +err_out_exit: + return err; +} + +/* + * Groovy, we've gotten an IO request from the client. + * Allocate BIO from the bioset, private data from the mempool + * and lots of pages for IO. + */ +int dst_process_io(struct dst_state *st) +{ + struct dst_node *n = st->node; + struct dst_cmd *cmd = st->data; + struct bio *bio; + struct dst_export_priv *priv; + int err = -ENOMEM; + + if (unlikely(!n->bdev)) { + err = -EINVAL; + goto err_out_exit; + } + + bio = bio_alloc_bioset(GFP_KERNEL, + PAGE_ALIGN(cmd->size) >> PAGE_SHIFT, + dst_bio_set); + if (!bio) + goto err_out_exit; + + priv = (struct dst_export_priv *)(((void *)bio) - sizeof (struct dst_export_priv)); + + priv->state = dst_state_get(st); + priv->bio = bio; + + bio->bi_private = priv; + bio->bi_end_io = dst_bio_end_io; + bio->bi_destructor = dst_bio_destructor; + bio->bi_bdev = n->bdev; + + /* + * Server side is only interested in two low bits: + * uptodate (set by itself actually) and rw block + */ + bio->bi_flags |= cmd->flags & 3; + + bio->bi_rw = cmd->rw; + bio->bi_size = 0; + bio->bi_sector = cmd->sector; + + dst_bio_to_cmd(bio, &priv->cmd, DST_IO_RESPONSE, cmd->id); + + priv->cmd.flags = 0; + priv->cmd.size = cmd->size; + + if (bio_data_dir(bio) == WRITE) { + err = dst_recv_cdata(st, priv->cmd.hash); + if (err) + goto err_out_free; + + err = dst_export_write_request(st, bio, cmd->size); + if (err) + goto err_out_free; + + if (dst_need_crypto(n)) + return dst_export_crypto(n, bio); + } else { + err = dst_export_read_request(bio, cmd->size); + if (err) + goto err_out_free; + } + + dprintk("%s: bio: %llu/%u, rw: %lu, dir: %lu, flags: %lx, phys: %d.\n", + __func__, (u64)bio->bi_sector, bio->bi_size, + bio->bi_rw, bio_data_dir(bio), + bio->bi_flags, bio->bi_phys_segments); + + generic_make_request(bio); + + return 0; + +err_out_free: + bio_put(bio); +err_out_exit: + return err; +} + +/* + * Ok, block IO is ready, let's send it back to the client... + */ +int dst_export_send_bio(struct bio *bio) +{ + struct dst_export_priv *p = bio->bi_private; + struct dst_state *st = p->state; + struct dst_cmd *cmd = &p->cmd; + int err; + + dprintk("%s: id: %llu, bio: %llu/%u, csize: %u, flags: %lu, rw: %lu.\n", + __func__, cmd->id, (u64)bio->bi_sector, bio->bi_size, + cmd->csize, bio->bi_flags, bio->bi_rw); + + dst_convert_cmd(cmd); + + dst_state_lock(st); + if (!st->socket) { + err = -ECONNRESET; + goto err_out_unlock; + } + + if (bio_data_dir(bio) == WRITE) { + /* ... or just confirmation that writing has completed. */ + cmd->size = cmd->csize = 0; + err = dst_data_send_header(st->socket, cmd, + sizeof(struct dst_cmd), 0); + if (err) + goto err_out_unlock; + } else { + err = dst_send_bio(st, cmd, bio); + if (err) + goto err_out_unlock; + } + + dst_state_unlock(st); + + bio_put(bio); + return 0; + +err_out_unlock: + dst_state_unlock(st); + + bio_put(bio); + return err; +} diff --git a/drivers/staging/dst/state.c b/drivers/staging/dst/state.c new file mode 100644 index 000000000000..d057e52f3b64 --- /dev/null +++ b/drivers/staging/dst/state.c @@ -0,0 +1,839 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Polling machinery. + */ + +struct dst_poll_helper +{ + poll_table pt; + struct dst_state *st; +}; + +static int dst_queue_wake(wait_queue_t *wait, unsigned mode, int sync, void *key) +{ + struct dst_state *st = container_of(wait, struct dst_state, wait); + + wake_up(&st->thread_wait); + return 1; +} + +static void dst_queue_func(struct file *file, wait_queue_head_t *whead, + poll_table *pt) +{ + struct dst_state *st = container_of(pt, struct dst_poll_helper, pt)->st; + + st->whead = whead; + init_waitqueue_func_entry(&st->wait, dst_queue_wake); + add_wait_queue(whead, &st->wait); +} + +void dst_poll_exit(struct dst_state *st) +{ + if (st->whead) { + remove_wait_queue(st->whead, &st->wait); + st->whead = NULL; + } +} + +int dst_poll_init(struct dst_state *st) +{ + struct dst_poll_helper ph; + + ph.st = st; + init_poll_funcptr(&ph.pt, &dst_queue_func); + + st->socket->ops->poll(NULL, st->socket, &ph.pt); + return 0; +} + +/* + * Header receiving function - may block. + */ +static int dst_data_recv_header(struct socket *sock, + void *data, unsigned int size, int block) +{ + struct msghdr msg; + struct kvec iov; + int err; + + iov.iov_base = data; + iov.iov_len = size; + + msg.msg_iov = (struct iovec *)&iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = (block)?MSG_WAITALL:MSG_DONTWAIT; + + err = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, + msg.msg_flags); + if (err != size) + return -1; + + return 0; +} + +/* + * Header sending function - may block. + */ +int dst_data_send_header(struct socket *sock, + void *data, unsigned int size, int more) +{ + struct msghdr msg; + struct kvec iov; + int err; + + iov.iov_base = data; + iov.iov_len = size; + + msg.msg_iov = (struct iovec *)&iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = MSG_WAITALL | (more)?MSG_MORE:0; + + err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); + if (err != size) { + dprintk("%s: size: %u, more: %d, err: %d.\n", + __func__, size, more, err); + return -1; + } + + return 0; +} + +/* + * Block autoconfiguration: request size of the storage and permissions. + */ +static int dst_request_remote_config(struct dst_state *st) +{ + struct dst_node *n = st->node; + int err = -EINVAL; + struct dst_cmd *cmd = st->data; + + memset(cmd, 0, sizeof(struct dst_cmd)); + cmd->cmd = DST_CFG; + + dst_convert_cmd(cmd); + + err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0); + if (err) + goto out; + + err = dst_data_recv_header(st->socket, cmd, sizeof(struct dst_cmd), 1); + if (err) + goto out; + + dst_convert_cmd(cmd); + + if (cmd->cmd != DST_CFG) { + err = -EINVAL; + dprintk("%s: checking result: cmd: %d, size reported: %llu.\n", + __func__, cmd->cmd, cmd->sector); + goto out; + } + + if (n->size != 0) + n->size = min_t(loff_t, n->size, cmd->sector); + else + n->size = cmd->sector; + + n->info->size = n->size; + st->permissions = cmd->rw; + +out: + dprintk("%s: n: %p, err: %d, size: %llu, permission: %x.\n", + __func__, n, err, n->size, st->permissions); + return err; +} + +/* + * Socket machinery. + */ + +#define DST_DEFAULT_TIMEO 20000 + +int dst_state_socket_create(struct dst_state *st) +{ + int err; + struct socket *sock; + struct dst_network_ctl *ctl = &st->ctl; + + err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &sock); + if (err < 0) + return err; + + sock->sk->sk_sndtimeo = sock->sk->sk_rcvtimeo = + msecs_to_jiffies(DST_DEFAULT_TIMEO); + sock->sk->sk_allocation = GFP_NOIO; + + st->socket = st->read_socket = sock; + return 0; +} + +void dst_state_socket_release(struct dst_state *st) +{ + dprintk("%s: st: %p, socket: %p, n: %p.\n", + __func__, st, st->socket, st->node); + if (st->socket) { + sock_release(st->socket); + st->socket = NULL; + st->read_socket = NULL; + } +} + +void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str) +{ + if (sk->ops->family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + printk(KERN_INFO "%s %u.%u.%u.%u:%d.\n", + str, NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); + } else if (sk->ops->family == AF_INET6) { + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; + printk(KERN_INFO "%s %pi6:%d", + str, &sin->sin6_addr, ntohs(sin->sin6_port)); + } +} + +void dst_state_exit_connected(struct dst_state *st) +{ + if (st->socket) { + dst_poll_exit(st); + st->socket->ops->shutdown(st->socket, 2); + + dst_dump_addr(st->socket, (struct sockaddr *)&st->ctl.addr, + "Disconnected peer"); + dst_state_socket_release(st); + } +} + +static int dst_state_init_connected(struct dst_state *st) +{ + int err; + struct dst_network_ctl *ctl = &st->ctl; + + err = dst_state_socket_create(st); + if (err) + goto err_out_exit; + + err = kernel_connect(st->socket, (struct sockaddr *)&st->ctl.addr, + st->ctl.addr.sa_data_len, 0); + if (err) + goto err_out_release; + + err = dst_poll_init(st); + if (err) + goto err_out_release; + + dst_dump_addr(st->socket, (struct sockaddr *)&ctl->addr, + "Connected to peer"); + + return 0; + +err_out_release: + dst_state_socket_release(st); +err_out_exit: + return err; +} + +/* + * State reset is used to reconnect to the remote peer. + * May fail, but who cares, we will try again later. + */ +static void inline dst_state_reset_nolock(struct dst_state *st) +{ + dst_state_exit_connected(st); + dst_state_init_connected(st); +} + +static void inline dst_state_reset(struct dst_state *st) +{ + dst_state_lock(st); + dst_state_reset_nolock(st); + dst_state_unlock(st); +} + +/* + * Basic network sending/receiving functions. + * Blocked mode is used. + */ +static int dst_data_recv_raw(struct dst_state *st, void *buf, u64 size) +{ + struct msghdr msg; + struct kvec iov; + int err; + + BUG_ON(!size); + + iov.iov_base = buf; + iov.iov_len = size; + + msg.msg_iov = (struct iovec *)&iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = MSG_DONTWAIT; + + err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len, + msg.msg_flags); + if (err <= 0) { + dprintk("%s: failed to recv data: size: %llu, err: %d.\n", + __func__, size, err); + if (err == 0) + err = -ECONNRESET; + + dst_state_exit_connected(st); + } + + return err; +} + +/* + * Ping command to early detect failed nodes. + */ +static int dst_send_ping(struct dst_state *st) +{ + struct dst_cmd *cmd = st->data; + int err = -ECONNRESET; + + dst_state_lock(st); + if (st->socket) { + memset(cmd, 0, sizeof(struct dst_cmd)); + + cmd->cmd = __cpu_to_be32(DST_PING); + + err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0); + } + dprintk("%s: st: %p, socket: %p, err: %d.\n", __func__, st, st->socket, err); + dst_state_unlock(st); + + return err; +} + +/* + * Receiving function, which should either return error or read + * whole block request. If there was no traffic for a one second, + * send a ping, since remote node may die. + */ +int dst_data_recv(struct dst_state *st, void *data, unsigned int size) +{ + unsigned int revents = 0; + unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; + unsigned int mask = err_mask | POLLIN; + struct dst_node *n = st->node; + int err = 0; + + while (size && !err) { + revents = dst_state_poll(st); + + if (!(revents & mask)) { + DEFINE_WAIT(wait); + + for (;;) { + prepare_to_wait(&st->thread_wait, &wait, + TASK_INTERRUPTIBLE); + if (!n->trans_scan_timeout || st->need_exit) + break; + + revents = dst_state_poll(st); + + if (revents & mask) + break; + + if (signal_pending(current)) + break; + + if (!schedule_timeout(HZ)) { + err = dst_send_ping(st); + if (err) + return err; + } + + continue; + } + finish_wait(&st->thread_wait, &wait); + } + + err = -ECONNRESET; + dst_state_lock(st); + + if ( st->socket && + (st->read_socket == st->socket) && + (revents & POLLIN)) { + err = dst_data_recv_raw(st, data, size); + if (err > 0) { + data += err; + size -= err; + err = 0; + } + } + + if (revents & err_mask || !st->socket) { + dprintk("%s: revents: %x, socket: %p, size: %u, err: %d.\n", + __func__, revents, st->socket, size, err); + err = -ECONNRESET; + } + + dst_state_unlock(st); + + if (!n->trans_scan_timeout) + err = -ENODEV; + } + + return err; +} + +/* + * Send block autoconf reply. + */ +static int dst_process_cfg(struct dst_state *st) +{ + struct dst_node *n = st->node; + struct dst_cmd *cmd = st->data; + int err; + + cmd->sector = n->size; + cmd->rw = st->permissions; + + dst_convert_cmd(cmd); + + dst_state_lock(st); + err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0); + dst_state_unlock(st); + + return err; +} + +/* + * Receive block IO from the network. + */ +static int dst_recv_bio(struct dst_state *st, struct bio *bio, unsigned int total_size) +{ + struct bio_vec *bv; + int i, err; + void *data; + unsigned int sz; + + bio_for_each_segment(bv, bio, i) { + sz = min(total_size, bv->bv_len); + + dprintk("%s: bio: %llu/%u, total: %u, len: %u, sz: %u, off: %u.\n", + __func__, (u64)bio->bi_sector, bio->bi_size, total_size, + bv->bv_len, sz, bv->bv_offset); + + data = kmap(bv->bv_page) + bv->bv_offset; + err = dst_data_recv(st, data, sz); + kunmap(bv->bv_page); + + bv->bv_len = sz; + + if (err) + return err; + + total_size -= sz; + if (total_size == 0) + break; + } + + return 0; +} + +/* + * Our block IO has just completed and arrived: get it. + */ +static int dst_process_io_response(struct dst_state *st) +{ + struct dst_node *n = st->node; + struct dst_cmd *cmd = st->data; + struct dst_trans *t; + int err = 0; + struct bio *bio; + + mutex_lock(&n->trans_lock); + t = dst_trans_search(n, cmd->id); + mutex_unlock(&n->trans_lock); + + if (!t) + goto err_out_exit; + + bio = t->bio; + + dprintk("%s: bio: %llu/%u, cmd_size: %u, csize: %u, dir: %lu.\n", + __func__, (u64)bio->bi_sector, bio->bi_size, cmd->size, + cmd->csize, bio_data_dir(bio)); + + if (bio_data_dir(bio) == READ) { + if (bio->bi_size != cmd->size - cmd->csize) + goto err_out_exit; + + if (dst_need_crypto(n)) { + err = dst_recv_cdata(st, t->cmd.hash); + if (err) + goto err_out_exit; + } + + err = dst_recv_bio(st, t->bio, bio->bi_size); + if (err) + goto err_out_exit; + + if (dst_need_crypto(n)) + return dst_trans_crypto(t); + } else { + err = -EBADMSG; + if (cmd->size || cmd->csize) + goto err_out_exit; + } + + dst_trans_remove(t); + dst_trans_put(t); + + return 0; + +err_out_exit: + return err; +} + +/* + * Receive crypto data. + */ +int dst_recv_cdata(struct dst_state *st, void *cdata) +{ + struct dst_cmd *cmd = st->data; + struct dst_node *n = st->node; + struct dst_crypto_ctl *c = &n->crypto; + int err; + + if (cmd->csize != c->crypto_attached_size) { + dprintk("%s: cmd: cmd: %u, sector: %llu, size: %u, " + "csize: %u != digest size %u.\n", + __func__, cmd->cmd, cmd->sector, cmd->size, + cmd->csize, c->crypto_attached_size); + err = -EINVAL; + goto err_out_exit; + } + + err = dst_data_recv(st, cdata, cmd->csize); + if (err) + goto err_out_exit; + + cmd->size -= cmd->csize; + return 0; + +err_out_exit: + return err; +} + +/* + * Receive the command and start its processing. + */ +static int dst_recv_processing(struct dst_state *st) +{ + int err = -EINTR; + struct dst_cmd *cmd = st->data; + + /* + * If socket will be reset after this statement, then + * dst_data_recv() will just fail and loop will + * start again, so it can be done without any locks. + * + * st->read_socket is needed to prevents state machine + * breaking between this data reading and subsequent one + * in protocol specific functions during connection reset. + * In case of reset we have to read next command and do + * not expect data for old command to magically appear in + * new connection. + */ + st->read_socket = st->socket; + err = dst_data_recv(st, cmd, sizeof(struct dst_cmd)); + if (err) + goto out_exit; + + dst_convert_cmd(cmd); + + dprintk("%s: cmd: %u, size: %u, csize: %u, id: %llu, " + "sector: %llu, flags: %llx, rw: %llx.\n", + __func__, cmd->cmd, cmd->size, + cmd->csize, cmd->id, cmd->sector, + cmd->flags, cmd->rw); + + /* + * This should catch protocol breakage and random garbage instead of commands. + */ + if (unlikely(cmd->csize > st->size - sizeof(struct dst_cmd))) { + err = -EBADMSG; + goto out_exit; + } + + err = -EPROTO; + switch (cmd->cmd) { + case DST_IO_RESPONSE: + err = dst_process_io_response(st); + break; + case DST_IO: + err = dst_process_io(st); + break; + case DST_CFG: + err = dst_process_cfg(st); + break; + case DST_PING: + err = 0; + break; + default: + break; + } + +out_exit: + return err; +} + +/* + * Receiving thread. For the client node we should try to reconnect, + * for accepted client we just drop the state and expect it to reconnect. + */ +static int dst_recv(void *init_data, void *schedule_data) +{ + struct dst_state *st = schedule_data; + struct dst_node *n = init_data; + int err = 0; + + dprintk("%s: start st: %p, n: %p, scan: %lu, need_exit: %d.\n", + __func__, st, n, n->trans_scan_timeout, st->need_exit); + + while (n->trans_scan_timeout && !st->need_exit) { + err = dst_recv_processing(st); + if (err < 0) { + if (!st->ctl.type) + break; + + if (!n->trans_scan_timeout || st->need_exit) + break; + + dst_state_reset(st); + msleep(1000); + } + } + + st->need_exit = 1; + wake_up(&st->thread_wait); + + dprintk("%s: freeing receiving socket st: %p.\n", __func__, st); + dst_state_lock(st); + dst_state_exit_connected(st); + dst_state_unlock(st); + dst_state_put(st); + + dprintk("%s: freed receiving socket st: %p.\n", __func__, st); + + return err; +} + +/* + * Network state dies here and borns couple of lines below. + * This object is the main network state processing engine: + * sending, receiving, reconnections, all network related + * tasks are handled on behalf of the state. + */ +static void dst_state_free(struct dst_state *st) +{ + dprintk("%s: st: %p.\n", __func__, st); + if (st->cleanup) + st->cleanup(st); + kfree(st->data); + kfree(st); +} + +struct dst_state *dst_state_alloc(struct dst_node *n) +{ + struct dst_state *st; + int err = -ENOMEM; + + st = kzalloc(sizeof(struct dst_state), GFP_KERNEL); + if (!st) + goto err_out_exit; + + st->node = n; + st->need_exit = 0; + + st->size = PAGE_SIZE; + st->data = kmalloc(st->size, GFP_KERNEL); + if (!st->data) + goto err_out_free; + + spin_lock_init(&st->request_lock); + INIT_LIST_HEAD(&st->request_list); + + mutex_init(&st->state_lock); + init_waitqueue_head(&st->thread_wait); + + /* + * One for processing thread, another one for node itself. + */ + atomic_set(&st->refcnt, 2); + + dprintk("%s: st: %p, n: %p.\n", __func__, st, st->node); + + return st; + +err_out_free: + kfree(st); +err_out_exit: + return ERR_PTR(err); +} + +int dst_state_schedule_receiver(struct dst_state *st) +{ + return thread_pool_schedule_private(st->node->pool, dst_thread_setup, + dst_recv, st, MAX_SCHEDULE_TIMEOUT, st->node); +} + +/* + * Initialize client's connection to the remote peer: allocate state, + * connect and perform block IO autoconfiguration. + */ +int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r) +{ + struct dst_state *st; + int err = -ENOMEM; + + st = dst_state_alloc(n); + if (IS_ERR(st)) { + err = PTR_ERR(st); + goto err_out_exit; + } + memcpy(&st->ctl, r, sizeof(struct dst_network_ctl)); + + err = dst_state_init_connected(st); + if (err) + goto err_out_free_data; + + err = dst_request_remote_config(st); + if (err) + goto err_out_exit_connected; + n->state = st; + + err = dst_state_schedule_receiver(st); + if (err) + goto err_out_exit_connected; + + return 0; + +err_out_exit_connected: + dst_state_exit_connected(st); +err_out_free_data: + dst_state_free(st); +err_out_exit: + n->state = NULL; + return err; +} + +void dst_state_put(struct dst_state *st) +{ + dprintk("%s: st: %p, refcnt: %d.\n", + __func__, st, atomic_read(&st->refcnt)); + if (atomic_dec_and_test(&st->refcnt)) + dst_state_free(st); +} + +/* + * Send block IO to the network one by one using zero-copy ->sendpage(). + */ +int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio) +{ + struct bio_vec *bv; + struct dst_crypto_ctl *c = &st->node->crypto; + int err, i = 0; + int flags = MSG_WAITALL; + + err = dst_data_send_header(st->socket, cmd, + sizeof(struct dst_cmd) + c->crypto_attached_size, bio->bi_vcnt); + if (err) + goto err_out_exit; + + bio_for_each_segment(bv, bio, i) { + if (i < bio->bi_vcnt - 1) + flags |= MSG_MORE; + + err = kernel_sendpage(st->socket, bv->bv_page, bv->bv_offset, + bv->bv_len, flags); + if (err <= 0) + goto err_out_exit; + } + + return 0; + +err_out_exit: + dprintk("%s: %d/%d, flags: %x, err: %d.\n", + __func__, i, bio->bi_vcnt, flags, err); + return err; +} + +/* + * Send transaction to the remote peer. + */ +int dst_trans_send(struct dst_trans *t) +{ + int err; + struct dst_state *st = t->n->state; + struct bio *bio = t->bio; + + dst_convert_cmd(&t->cmd); + + dst_state_lock(st); + if (!st->socket) { + err = dst_state_init_connected(st); + if (err) + goto err_out_unlock; + } + + if (bio_data_dir(bio) == WRITE) { + err = dst_send_bio(st, &t->cmd, t->bio); + } else { + err = dst_data_send_header(st->socket, &t->cmd, + sizeof(struct dst_cmd), 0); + } + if (err) + goto err_out_reset; + + dst_state_unlock(st); + return 0; + +err_out_reset: + dst_state_reset_nolock(st); +err_out_unlock: + dst_state_unlock(st); + + return err; +} diff --git a/drivers/staging/dst/thread_pool.c b/drivers/staging/dst/thread_pool.c new file mode 100644 index 000000000000..7bed4e851029 --- /dev/null +++ b/drivers/staging/dst/thread_pool.c @@ -0,0 +1,345 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +/* + * Thread pool abstraction allows to schedule a work to be performed + * on behalf of kernel thread. One does not operate with threads itself, + * instead user provides setup and cleanup callbacks for thread pool itself, + * and action and cleanup callbacks for each submitted work. + * + * Each worker has private data initialized at creation time and data, + * provided by user at scheduling time. + * + * When action is being performed, thread can not be used by other users, + * instead they will sleep until there is free thread to pick their work. + */ +struct thread_pool_worker +{ + struct list_head worker_entry; + + struct task_struct *thread; + + struct thread_pool *pool; + + int error; + int has_data; + int need_exit; + unsigned int id; + + wait_queue_head_t wait; + + void *private; + void *schedule_data; + + int (* action)(void *private, void *schedule_data); + void (* cleanup)(void *private); +}; + +static void thread_pool_exit_worker(struct thread_pool_worker *w) +{ + kthread_stop(w->thread); + + w->cleanup(w->private); + kfree(w); +} + +/* + * Called to mark thread as ready and allow users to schedule new work. + */ +static void thread_pool_worker_make_ready(struct thread_pool_worker *w) +{ + struct thread_pool *p = w->pool; + + mutex_lock(&p->thread_lock); + + if (!w->need_exit) { + list_move_tail(&w->worker_entry, &p->ready_list); + w->has_data = 0; + mutex_unlock(&p->thread_lock); + + wake_up(&p->wait); + } else { + p->thread_num--; + list_del(&w->worker_entry); + mutex_unlock(&p->thread_lock); + + thread_pool_exit_worker(w); + } +} + +/* + * Thread action loop: waits until there is new work. + */ +static int thread_pool_worker_func(void *data) +{ + struct thread_pool_worker *w = data; + + while (!kthread_should_stop()) { + wait_event_interruptible(w->wait, + kthread_should_stop() || w->has_data); + + if (kthread_should_stop()) + break; + + if (!w->has_data) + continue; + + w->action(w->private, w->schedule_data); + thread_pool_worker_make_ready(w); + } + + return 0; +} + +/* + * Remove single worker without specifying which one. + */ +void thread_pool_del_worker(struct thread_pool *p) +{ + struct thread_pool_worker *w = NULL; + + while (!w && p->thread_num) { + wait_event(p->wait, !list_empty(&p->ready_list) || !p->thread_num); + + dprintk("%s: locking list_empty: %d, thread_num: %d.\n", + __func__, list_empty(&p->ready_list), p->thread_num); + + mutex_lock(&p->thread_lock); + if (!list_empty(&p->ready_list)) { + w = list_first_entry(&p->ready_list, + struct thread_pool_worker, + worker_entry); + + dprintk("%s: deleting w: %p, thread_num: %d, list: %p [%p.%p].\n", + __func__, w, p->thread_num, &p->ready_list, + p->ready_list.prev, p->ready_list.next); + + p->thread_num--; + list_del(&w->worker_entry); + } + mutex_unlock(&p->thread_lock); + } + + if (w) + thread_pool_exit_worker(w); + dprintk("%s: deleted w: %p, thread_num: %d.\n", + __func__, w, p->thread_num); +} + +/* + * Remove a worker with given ID. + */ +void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id) +{ + struct thread_pool_worker *w; + int found = 0; + + mutex_lock(&p->thread_lock); + list_for_each_entry(w, &p->ready_list, worker_entry) { + if (w->id == id) { + found = 1; + p->thread_num--; + list_del(&w->worker_entry); + break; + } + } + + if (!found) { + list_for_each_entry(w, &p->active_list, worker_entry) { + if (w->id == id) { + w->need_exit = 1; + break; + } + } + } + mutex_unlock(&p->thread_lock); + + if (found) + thread_pool_exit_worker(w); +} + +/* + * Add new worker thread with given parameters. + * If initialization callback fails, return error. + */ +int thread_pool_add_worker(struct thread_pool *p, + char *name, + unsigned int id, + void *(* init)(void *private), + void (* cleanup)(void *private), + void *private) +{ + struct thread_pool_worker *w; + int err = -ENOMEM; + + w = kzalloc(sizeof(struct thread_pool_worker), GFP_KERNEL); + if (!w) + goto err_out_exit; + + w->pool = p; + init_waitqueue_head(&w->wait); + w->cleanup = cleanup; + w->id = id; + + w->thread = kthread_run(thread_pool_worker_func, w, "%s", name); + if (IS_ERR(w->thread)) { + err = PTR_ERR(w->thread); + goto err_out_free; + } + + w->private = init(private); + if (IS_ERR(w->private)) { + err = PTR_ERR(w->private); + goto err_out_stop_thread; + } + + mutex_lock(&p->thread_lock); + list_add_tail(&w->worker_entry, &p->ready_list); + p->thread_num++; + mutex_unlock(&p->thread_lock); + + return 0; + +err_out_stop_thread: + kthread_stop(w->thread); +err_out_free: + kfree(w); +err_out_exit: + return err; +} + +/* + * Destroy the whole pool. + */ +void thread_pool_destroy(struct thread_pool *p) +{ + while (p->thread_num) { + dprintk("%s: num: %d.\n", __func__, p->thread_num); + thread_pool_del_worker(p); + } + + kfree(p); +} + +/* + * Create a pool with given number of threads. + * They will have sequential IDs started from zero. + */ +struct thread_pool *thread_pool_create(int num, char *name, + void *(* init)(void *private), + void (* cleanup)(void *private), + void *private) +{ + struct thread_pool_worker *w, *tmp; + struct thread_pool *p; + int err = -ENOMEM; + int i; + + p = kzalloc(sizeof(struct thread_pool), GFP_KERNEL); + if (!p) + goto err_out_exit; + + init_waitqueue_head(&p->wait); + mutex_init(&p->thread_lock); + INIT_LIST_HEAD(&p->ready_list); + INIT_LIST_HEAD(&p->active_list); + p->thread_num = 0; + + for (i=0; iready_list, worker_entry) { + list_del(&w->worker_entry); + thread_pool_exit_worker(w); + } + kfree(p); +err_out_exit: + return ERR_PTR(err); +} + +/* + * Schedule execution of the action on a given thread, + * provided ID pointer has to match previously stored + * private data. + */ +int thread_pool_schedule_private(struct thread_pool *p, + int (* setup)(void *private, void *data), + int (* action)(void *private, void *data), + void *data, long timeout, void *id) +{ + struct thread_pool_worker *w, *tmp, *worker = NULL; + int err = 0; + + while (!worker && !err) { + timeout = wait_event_interruptible_timeout(p->wait, + !list_empty(&p->ready_list), + timeout); + + if (!timeout) { + err = -ETIMEDOUT; + break; + } + + worker = NULL; + mutex_lock(&p->thread_lock); + list_for_each_entry_safe(w, tmp, &p->ready_list, worker_entry) { + if (id && id != w->private) + continue; + + worker = w; + + list_move_tail(&w->worker_entry, &p->active_list); + + err = setup(w->private, data); + if (!err) { + w->schedule_data = data; + w->action = action; + w->has_data = 1; + wake_up(&w->wait); + } else { + list_move_tail(&w->worker_entry, &p->ready_list); + } + + break; + } + mutex_unlock(&p->thread_lock); + } + + return err; +} + +/* + * Schedule execution on arbitrary thread from the pool. + */ +int thread_pool_schedule(struct thread_pool *p, + int (* setup)(void *private, void *data), + int (* action)(void *private, void *data), + void *data, long timeout) +{ + return thread_pool_schedule_private(p, setup, + action, data, timeout, NULL); +} diff --git a/drivers/staging/dst/trans.c b/drivers/staging/dst/trans.c new file mode 100644 index 000000000000..557d372a496c --- /dev/null +++ b/drivers/staging/dst/trans.c @@ -0,0 +1,335 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include + +/* + * Transaction memory pool size. + */ +static int dst_mempool_num = 32; +module_param(dst_mempool_num, int, 0644); + +/* + * Transaction tree management. + */ +static inline int dst_trans_cmp(dst_gen_t gen, dst_gen_t new) +{ + if (gen < new) + return 1; + if (gen > new) + return -1; + return 0; +} + +struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen) +{ + struct rb_root *root = &node->trans_root; + struct rb_node *n = root->rb_node; + struct dst_trans *t, *ret = NULL; + int cmp; + + while (n) { + t = rb_entry(n, struct dst_trans, trans_entry); + + cmp = dst_trans_cmp(t->gen, gen); + if (cmp < 0) + n = n->rb_left; + else if (cmp > 0) + n = n->rb_right; + else { + ret = t; + break; + } + } + + dprintk("%s: %s transaction: id: %llu.\n", __func__, + (ret)?"found":"not found", gen); + + return ret; +} + +static int dst_trans_insert(struct dst_trans *new) +{ + struct rb_root *root = &new->n->trans_root; + struct rb_node **n = &root->rb_node, *parent = NULL; + struct dst_trans *ret = NULL, *t; + int cmp; + + while (*n) { + parent = *n; + + t = rb_entry(parent, struct dst_trans, trans_entry); + + cmp = dst_trans_cmp(t->gen, new->gen); + if (cmp < 0) + n = &parent->rb_left; + else if (cmp > 0) + n = &parent->rb_right; + else { + ret = t; + break; + } + } + + new->send_time = jiffies; + if (ret) { + printk("%s: exist: old: gen: %llu, bio: %llu/%u, send_time: %lu, " + "new: gen: %llu, bio: %llu/%u, send_time: %lu.\n", + __func__, + ret->gen, (u64)ret->bio->bi_sector, + ret->bio->bi_size, ret->send_time, + new->gen, (u64)new->bio->bi_sector, + new->bio->bi_size, new->send_time); + return -EEXIST; + } + + rb_link_node(&new->trans_entry, parent, n); + rb_insert_color(&new->trans_entry, root); + + dprintk("%s: inserted: gen: %llu, bio: %llu/%u, send_time: %lu.\n", + __func__, new->gen, (u64)new->bio->bi_sector, + new->bio->bi_size, new->send_time); + + return 0; +} + +int dst_trans_remove_nolock(struct dst_trans *t) +{ + struct dst_node *n = t->n; + + if (t->trans_entry.rb_parent_color) { + rb_erase(&t->trans_entry, &n->trans_root); + t->trans_entry.rb_parent_color = 0; + } + return 0; +} + +int dst_trans_remove(struct dst_trans *t) +{ + int ret; + struct dst_node *n = t->n; + + mutex_lock(&n->trans_lock); + ret = dst_trans_remove_nolock(t); + mutex_unlock(&n->trans_lock); + + return ret; +} + +/* + * When transaction is completed and there are no more users, + * we complete appriate block IO request with given error status. + */ +void dst_trans_put(struct dst_trans *t) +{ + if (atomic_dec_and_test(&t->refcnt)) { + struct bio *bio = t->bio; + + dprintk("%s: completed t: %p, gen: %llu, bio: %p.\n", + __func__, t, t->gen, bio); + + bio_endio(bio, t->error); + bio_put(bio); + + dst_node_put(t->n); + mempool_free(t, t->n->trans_pool); + } +} + +/* + * Process given block IO request: allocate transaction, insert it into the tree + * and send/schedule crypto processing. + */ +int dst_process_bio(struct dst_node *n, struct bio *bio) +{ + struct dst_trans *t; + int err = -ENOMEM; + + t = mempool_alloc(n->trans_pool, GFP_NOFS); + if (!t) + goto err_out_exit; + + t->n = dst_node_get(n); + t->bio = bio; + t->error = 0; + t->retries = 0; + atomic_set(&t->refcnt, 1); + t->gen = atomic_long_inc_return(&n->gen); + + t->enc = bio_data_dir(bio); + dst_bio_to_cmd(bio, &t->cmd, DST_IO, t->gen); + + mutex_lock(&n->trans_lock); + err = dst_trans_insert(t); + mutex_unlock(&n->trans_lock); + if (err) + goto err_out_free; + + dprintk("%s: gen: %llu, bio: %llu/%u, dir/enc: %d, need_crypto: %d.\n", + __func__, t->gen, (u64)bio->bi_sector, + bio->bi_size, t->enc, dst_need_crypto(n)); + + if (dst_need_crypto(n) && t->enc) + dst_trans_crypto(t); + else + dst_trans_send(t); + + return 0; + +err_out_free: + dst_node_put(n); + mempool_free(t, n->trans_pool); +err_out_exit: + bio_endio(bio, err); + bio_put(bio); + return err; +} + +/* + * Scan for timeout/stale transactions. + * Each transaction is being resent multiple times before error completion. + */ +static void dst_trans_scan(struct work_struct *work) +{ + struct dst_node *n = container_of(work, struct dst_node, trans_work.work); + struct rb_node *rb_node; + struct dst_trans *t; + unsigned long timeout = n->trans_scan_timeout; + int num = 10 * n->trans_max_retries; + + mutex_lock(&n->trans_lock); + + for (rb_node = rb_first(&n->trans_root); rb_node; ) { + t = rb_entry(rb_node, struct dst_trans, trans_entry); + + if (timeout && time_after(t->send_time + timeout, jiffies) + && t->retries == 0) + break; +#if 0 + dprintk("%s: t: %p, gen: %llu, n: %s, retries: %u, max: %u.\n", + __func__, t, t->gen, n->name, + t->retries, n->trans_max_retries); +#endif + if (--num == 0) + break; + + dst_trans_get(t); + + rb_node = rb_next(rb_node); + + if (timeout && (++t->retries < n->trans_max_retries)) { + dst_trans_send(t); + } else { + t->error = -ETIMEDOUT; + dst_trans_remove_nolock(t); + dst_trans_put(t); + } + + dst_trans_put(t); + } + + mutex_unlock(&n->trans_lock); + + /* + * If no timeout specified then system is in the middle of exiting process, + * so no need to reschedule scanning process again. + */ + if (timeout) { + if (!num) + timeout = HZ; + schedule_delayed_work(&n->trans_work, timeout); + } +} + +/* + * Flush all transactions and mark them as timed out. + * Destroy transaction pools. + */ +void dst_node_trans_exit(struct dst_node *n) +{ + struct dst_trans *t; + struct rb_node *rb_node; + + if (!n->trans_cache) + return; + + dprintk("%s: n: %p, cancelling the work.\n", __func__, n); + cancel_delayed_work_sync(&n->trans_work); + flush_scheduled_work(); + dprintk("%s: n: %p, work has been cancelled.\n", __func__, n); + + for (rb_node = rb_first(&n->trans_root); rb_node; ) { + t = rb_entry(rb_node, struct dst_trans, trans_entry); + + dprintk("%s: t: %p, gen: %llu, n: %s.\n", + __func__, t, t->gen, n->name); + + rb_node = rb_next(rb_node); + + t->error = -ETIMEDOUT; + dst_trans_remove_nolock(t); + dst_trans_put(t); + } + + mempool_destroy(n->trans_pool); + kmem_cache_destroy(n->trans_cache); +} + +/* + * Initialize transaction storage for given node. + * Transaction stores not only control information, + * but also network command and crypto data (if needed) + * to reduce number of allocations. Thus transaction size + * differs from node to node. + */ +int dst_node_trans_init(struct dst_node *n, unsigned int size) +{ + /* + * We need this, since node with given name can be dropped from the + * hash table, but be still alive, so subsequent creation of the node + * with the same name may collide with existing cache name. + */ + + snprintf(n->cache_name, sizeof(n->cache_name), "%s-%p", n->name, n); + + n->trans_cache = kmem_cache_create(n->cache_name, + size + n->crypto.crypto_attached_size, + 0, 0, NULL); + if (!n->trans_cache) + goto err_out_exit; + + n->trans_pool = mempool_create_slab_pool(dst_mempool_num, n->trans_cache); + if (!n->trans_pool) + goto err_out_cache_destroy; + + mutex_init(&n->trans_lock); + n->trans_root = RB_ROOT; + + INIT_DELAYED_WORK(&n->trans_work, dst_trans_scan); + schedule_delayed_work(&n->trans_work, n->trans_scan_timeout); + + dprintk("%s: n: %p, size: %u, crypto: %u.\n", + __func__, n, size, n->crypto.crypto_attached_size); + + return 0; + +err_out_cache_destroy: + kmem_cache_destroy(n->trans_cache); +err_out_exit: + return -ENOMEM; +} diff --git a/drivers/staging/echo/bit_operations.h b/drivers/staging/echo/bit_operations.h index cecdcf3fd755..4c4ccbc97313 100644 --- a/drivers/staging/echo/bit_operations.h +++ b/drivers/staging/echo/bit_operations.h @@ -21,8 +21,6 @@ * 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. - * - * $Id: bit_operations.h,v 1.11 2006/11/28 15:37:03 steveu Exp $ */ /*! \file */ @@ -34,7 +32,7 @@ /*! \brief Find the bit position of the highest set bit in a word \param bits The word to be searched \return The bit number of the highest set bit, or -1 if the word is zero. */ -static __inline__ int top_bit(unsigned int bits) +static inline int top_bit(unsigned int bits) { int res; @@ -50,7 +48,7 @@ static __inline__ int top_bit(unsigned int bits) /*! \brief Find the bit position of the lowest set bit in a word \param bits The word to be searched \return The bit number of the lowest set bit, or -1 if the word is zero. */ -static __inline__ int bottom_bit(unsigned int bits) +static inline int bottom_bit(unsigned int bits) { int res; @@ -63,7 +61,7 @@ static __inline__ int bottom_bit(unsigned int bits) return res; } #else -static __inline__ int top_bit(unsigned int bits) +static inline int top_bit(unsigned int bits) { int i; @@ -93,7 +91,7 @@ static __inline__ int top_bit(unsigned int bits) return i; } -static __inline__ int bottom_bit(unsigned int bits) +static inline int bottom_bit(unsigned int bits) { int i; @@ -127,7 +125,7 @@ static __inline__ int bottom_bit(unsigned int bits) /*! \brief Bit reverse a byte. \param data The byte to be reversed. \return The bit reversed version of data. */ -static __inline__ uint8_t bit_reverse8(uint8_t x) +static inline uint8_t bit_reverse8(uint8_t x) { #if defined(__i386__) || defined(__x86_64__) /* If multiply is fast */ @@ -172,32 +170,32 @@ uint32_t make_mask32(uint32_t x); uint16_t make_mask16(uint16_t x); /*! \brief Find the least significant one in a word, and return a word - with just that bit set. + with just that bit set. \param x The word to be searched. \return The word with the single set bit. */ -static __inline__ uint32_t least_significant_one32(uint32_t x) +static inline uint32_t least_significant_one32(uint32_t x) { - return (x & (-(int32_t) x)); + return x & (-(int32_t) x); } /*! \brief Find the most significant one in a word, and return a word - with just that bit set. + with just that bit set. \param x The word to be searched. \return The word with the single set bit. */ -static __inline__ uint32_t most_significant_one32(uint32_t x) +static inline uint32_t most_significant_one32(uint32_t x) { #if defined(__i386__) || defined(__x86_64__) return 1 << top_bit(x); #else x = make_mask32(x); - return (x ^ (x >> 1)); + return x ^ (x >> 1); #endif } /*! \brief Find the parity of a byte. \param x The byte to be checked. \return 1 for odd, or 0 for even. */ -static __inline__ int parity8(uint8_t x) +static inline int parity8(uint8_t x) { x = (x ^ (x >> 4)) & 0x0F; return (0x6996 >> x) & 1; @@ -206,7 +204,7 @@ static __inline__ int parity8(uint8_t x) /*! \brief Find the parity of a 16 bit word. \param x The word to be checked. \return 1 for odd, or 0 for even. */ -static __inline__ int parity16(uint16_t x) +static inline int parity16(uint16_t x) { x ^= (x >> 8); x = (x ^ (x >> 4)) & 0x0F; @@ -216,7 +214,7 @@ static __inline__ int parity16(uint16_t x) /*! \brief Find the parity of a 32 bit word. \param x The word to be checked. \return 1 for odd, or 0 for even. */ -static __inline__ int parity32(uint32_t x) +static inline int parity32(uint32_t x) { x ^= (x >> 16); x ^= (x >> 8); diff --git a/drivers/staging/echo/echo.c b/drivers/staging/echo/echo.c index fd4007e329e7..6d7217e1bd06 100644 --- a/drivers/staging/echo/echo.c +++ b/drivers/staging/echo/echo.c @@ -27,8 +27,6 @@ * 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. - * - * $Id: echo.c,v 1.20 2006/12/01 18:00:48 steveu Exp $ */ /*! \file */ @@ -113,17 +111,17 @@ #define MIN_TX_POWER_FOR_ADAPTION 64 #define MIN_RX_POWER_FOR_ADAPTION 64 -#define DTD_HANGOVER 600 /* 600 samples, or 75ms */ -#define DC_LOG2BETA 3 /* log2() of DC filter Beta */ +#define DTD_HANGOVER 600 /* 600 samples, or 75ms */ +#define DC_LOG2BETA 3 /* log2() of DC filter Beta */ /*-----------------------------------------------------------------------*\ - FUNCTIONS + FUNCTIONS \*-----------------------------------------------------------------------*/ /* adapting coeffs using the traditional stochastic descent (N)LMS algorithm */ #ifdef __bfin__ -static void __inline__ lms_adapt_bg(struct oslec_state *ec, int clean, +static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift) { int i, j; @@ -147,13 +145,13 @@ static void __inline__ lms_adapt_bg(struct oslec_state *ec, int clean, /* st: and en: help us locate the assembler in echo.s */ - //asm("st:"); + /* asm("st:"); */ n = ec->taps; for (i = 0, j = offset2; i < n; i++, j++) { exp = *phist++ * factor; ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15); } - //asm("en:"); + /* asm("en:"); */ /* Note the asm for the inner loop above generated by Blackfin gcc 4.1.1 is pretty good (note even parallel instructions used): @@ -195,7 +193,7 @@ static void __inline__ lms_adapt_bg(struct oslec_state *ec, int clean, */ #else -static __inline__ void lms_adapt_bg(struct oslec_state *ec, int clean, +static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift) { int i; @@ -249,9 +247,8 @@ struct oslec_state *oslec_create(int len, int adaption_mode) fir16_create(&ec->fir_state, ec->fir_taps16[0], ec->taps); fir16_create(&ec->fir_state_bg, ec->fir_taps16[1], ec->taps); - for (i = 0; i < 5; i++) { + for (i = 0; i < 5; i++) ec->xvtx[i] = ec->yvtx[i] = ec->xvrx[i] = ec->yvrx[i] = 0; - } ec->cng_level = 1000; oslec_adaption_mode(ec, adaption_mode); @@ -271,14 +268,13 @@ struct oslec_state *oslec_create(int len, int adaption_mode) return ec; - error_oom: +error_oom: for (i = 0; i < 2; i++) kfree(ec->fir_taps16[i]); kfree(ec); return NULL; } - EXPORT_SYMBOL_GPL(oslec_create); void oslec_free(struct oslec_state *ec) @@ -292,14 +288,12 @@ void oslec_free(struct oslec_state *ec) kfree(ec->snapshot); kfree(ec); } - EXPORT_SYMBOL_GPL(oslec_free); void oslec_adaption_mode(struct oslec_state *ec, int adaption_mode) { ec->adaption_mode = adaption_mode; } - EXPORT_SYMBOL_GPL(oslec_adaption_mode); void oslec_flush(struct oslec_state *ec) @@ -326,14 +320,12 @@ void oslec_flush(struct oslec_state *ec) ec->curr_pos = ec->taps - 1; ec->Pstates = 0; } - EXPORT_SYMBOL_GPL(oslec_flush); void oslec_snapshot(struct oslec_state *ec) { memcpy(ec->snapshot, ec->fir_taps16[0], ec->taps * sizeof(int16_t)); } - EXPORT_SYMBOL_GPL(oslec_snapshot); /* Dual Path Echo Canceller ------------------------------------------------*/ @@ -399,7 +391,7 @@ int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx) /* efficient "out with the old and in with the new" algorithm so we don't have to recalculate over the whole block of samples. */ - new = (int)tx *(int)tx; + new = (int)tx * (int)tx; old = (int)ec->fir_state.history[ec->fir_state.curr_pos] * (int)ec->fir_state.history[ec->fir_state.curr_pos]; ec->Pstates += @@ -498,15 +490,15 @@ int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx) if ((ec->adaption_mode & ECHO_CAN_USE_ADAPTION) && (ec->nonupdate_dwell == 0) && - (8 * ec->Lclean_bg < - 7 * ec->Lclean) /* (ec->Lclean_bg < 0.875*ec->Lclean) */ && - (8 * ec->Lclean_bg < - ec->Ltx) /* (ec->Lclean_bg < 0.125*ec->Ltx) */ ) { + /* (ec->Lclean_bg < 0.875*ec->Lclean) */ + (8 * ec->Lclean_bg < 7 * ec->Lclean) && + /* (ec->Lclean_bg < 0.125*ec->Ltx) */ + (8 * ec->Lclean_bg < ec->Ltx)) { if (ec->cond_met == 6) { /* BG filter has had better results for 6 consecutive samples */ ec->adapt = 1; memcpy(ec->fir_taps16[0], ec->fir_taps16[1], - ec->taps * sizeof(int16_t)); + ec->taps * sizeof(int16_t)); } else ec->cond_met++; } else @@ -580,7 +572,6 @@ int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx) return (int16_t) ec->clean_nlp << 1; } - EXPORT_SYMBOL_GPL(oslec_update); /* This function is seperated from the echo canceller is it is usually called @@ -604,7 +595,7 @@ EXPORT_SYMBOL_GPL(oslec_update); precision, which noise shapes things, giving very clean DC removal. */ -int16_t oslec_hpf_tx(struct oslec_state * ec, int16_t tx) +int16_t oslec_hpf_tx(struct oslec_state *ec, int16_t tx) { int tmp, tmp1; @@ -629,7 +620,6 @@ int16_t oslec_hpf_tx(struct oslec_state * ec, int16_t tx) return tx; } - EXPORT_SYMBOL_GPL(oslec_hpf_tx); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/echo/echo.h b/drivers/staging/echo/echo.h index 34fb816b15c8..c835e5c5314c 100644 --- a/drivers/staging/echo/echo.h +++ b/drivers/staging/echo/echo.h @@ -23,8 +23,6 @@ * 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. - * - * $Id: echo.h,v 1.9 2006/10/24 13:45:28 steveu Exp $ */ #ifndef __ECHO_H diff --git a/drivers/staging/echo/fir.h b/drivers/staging/echo/fir.h index d35f16805f4b..ac6c553e89f2 100644 --- a/drivers/staging/echo/fir.h +++ b/drivers/staging/echo/fir.h @@ -21,8 +21,6 @@ * 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. - * - * $Id: fir.h,v 1.8 2006/10/24 13:45:28 steveu Exp $ */ /*! \page fir_page FIR filtering @@ -102,8 +100,8 @@ struct fir_float_state_t { float *history; }; -static __inline__ const int16_t *fir16_create(struct fir16_state_t *fir, - const int16_t * coeffs, int taps) +static inline const int16_t *fir16_create(struct fir16_state_t *fir, + const int16_t *coeffs, int taps) { fir->taps = taps; fir->curr_pos = taps - 1; @@ -116,7 +114,7 @@ static __inline__ const int16_t *fir16_create(struct fir16_state_t *fir, return fir->history; } -static __inline__ void fir16_flush(struct fir16_state_t *fir) +static inline void fir16_flush(struct fir16_state_t *fir) { #if defined(USE_MMX) || defined(USE_SSE2) || defined(__bfin__) memset(fir->history, 0, 2 * fir->taps * sizeof(int16_t)); @@ -125,7 +123,7 @@ static __inline__ void fir16_flush(struct fir16_state_t *fir) #endif } -static __inline__ void fir16_free(struct fir16_state_t *fir) +static inline void fir16_free(struct fir16_state_t *fir) { kfree(fir->history); } @@ -148,16 +146,16 @@ static inline int32_t dot_asm(short *x, short *y, int len) "A0 += R0.L*R1.L (IS);\n\t" "R0 = A0;\n\t" "%0 = R0;\n\t" - :"=&d"(dot) - :"a"(x), "a"(y), "a"(len) - :"I0", "I1", "A1", "A0", "R0", "R1" + : "=&d"(dot) + : "a"(x), "a"(y), "a"(len) + : "I0", "I1", "A1", "A0", "R0", "R1" ); return dot; } #endif -static __inline__ int16_t fir16(struct fir16_state_t *fir, int16_t sample) +static inline int16_t fir16(struct fir16_state_t *fir, int16_t sample) { int32_t y; #if defined(USE_MMX) @@ -250,8 +248,8 @@ static __inline__ int16_t fir16(struct fir16_state_t *fir, int16_t sample) return (int16_t) (y >> 15); } -static __inline__ const int16_t *fir32_create(struct fir32_state_t *fir, - const int32_t * coeffs, int taps) +static inline const int16_t *fir32_create(struct fir32_state_t *fir, + const int32_t *coeffs, int taps) { fir->taps = taps; fir->curr_pos = taps - 1; @@ -260,17 +258,17 @@ static __inline__ const int16_t *fir32_create(struct fir32_state_t *fir, return fir->history; } -static __inline__ void fir32_flush(struct fir32_state_t *fir) +static inline void fir32_flush(struct fir32_state_t *fir) { memset(fir->history, 0, fir->taps * sizeof(int16_t)); } -static __inline__ void fir32_free(struct fir32_state_t *fir) +static inline void fir32_free(struct fir32_state_t *fir) { kfree(fir->history); } -static __inline__ int16_t fir32(struct fir32_state_t *fir, int16_t sample) +static inline int16_t fir32(struct fir32_state_t *fir, int16_t sample) { int i; int32_t y; diff --git a/drivers/staging/echo/mmx.h b/drivers/staging/echo/mmx.h index 44e5cfebc18f..c1dcd7299cb5 100644 --- a/drivers/staging/echo/mmx.h +++ b/drivers/staging/echo/mmx.h @@ -44,238 +44,238 @@ union xmm_t { char b[16]; }; -#define mmx_i2r(op,imm,reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "i" (imm) ) +#define mmx_i2r(op, imm, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "i" (imm)) -#define mmx_m2r(op,mem,reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "m" (mem)) +#define mmx_m2r(op, mem, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem)) -#define mmx_r2m(op,reg,mem) \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=m" (mem) \ - : /* nothing */ ) +#define mmx_r2m(op, reg, mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=m" (mem) \ + : /* nothing */) -#define mmx_r2r(op,regs,regd) \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd) +#define mmx_r2r(op, regs, regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) -#define emms() __asm__ __volatile__ ("emms") +#define emms() __asm__ __volatile__ ("emms") -#define movd_m2r(var,reg) mmx_m2r (movd, var, reg) -#define movd_r2m(reg,var) mmx_r2m (movd, reg, var) -#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd) +#define movd_m2r(var, reg) mmx_m2r(movd, var, reg) +#define movd_r2m(reg, var) mmx_r2m(movd, reg, var) +#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd) -#define movq_m2r(var,reg) mmx_m2r (movq, var, reg) -#define movq_r2m(reg,var) mmx_r2m (movq, reg, var) -#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) +#define movq_m2r(var, reg) mmx_m2r(movq, var, reg) +#define movq_r2m(reg, var) mmx_r2m(movq, reg, var) +#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd) -#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) -#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) -#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) -#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) +#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg) +#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd) +#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg) +#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd) -#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) -#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) +#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg) +#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd) -#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) -#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) -#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) -#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) -#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) -#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) +#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg) +#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd) +#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg) +#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd) +#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg) +#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd) -#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) -#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) -#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) -#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) +#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg) +#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd) +#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg) +#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd) -#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) -#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) -#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) -#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) +#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg) +#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd) +#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg) +#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd) -#define pand_m2r(var,reg) mmx_m2r (pand, var, reg) -#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) +#define pand_m2r(var, reg) mmx_m2r(pand, var, reg) +#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd) -#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) -#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) +#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg) +#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd) -#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) -#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) -#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) -#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) -#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) -#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) +#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg) +#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd) +#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg) +#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd) +#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg) +#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd) -#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) -#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) -#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) -#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) -#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) -#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) +#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg) +#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd) +#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg) +#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd) +#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg) +#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd) -#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) -#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) +#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg) +#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd) -#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) -#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) +#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg) +#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd) -#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) -#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) +#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg) +#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd) -#define por_m2r(var,reg) mmx_m2r (por, var, reg) -#define por_r2r(regs,regd) mmx_r2r (por, regs, regd) +#define por_m2r(var, reg) mmx_m2r(por, var, reg) +#define por_r2r(regs, regd) mmx_r2r(por, regs, regd) -#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg) -#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) -#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) -#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg) -#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) -#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) -#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg) -#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) -#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) +#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg) +#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg) +#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd) +#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg) +#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg) +#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd) +#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg) +#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg) +#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd) -#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg) -#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) -#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) -#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg) -#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) -#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) +#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg) +#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg) +#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd) +#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg) +#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg) +#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd) -#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg) -#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) -#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) -#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg) -#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) -#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) -#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg) -#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) -#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) +#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg) +#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg) +#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd) +#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg) +#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg) +#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd) +#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg) +#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg) +#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd) -#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) -#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) -#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) -#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) -#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) -#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) +#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg) +#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd) +#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg) +#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd) +#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg) +#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd) -#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) -#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) -#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) -#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) +#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg) +#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd) +#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg) +#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd) -#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) -#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) -#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) -#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) +#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg) +#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd) +#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg) +#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd) -#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) -#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) -#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) -#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) -#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) -#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) +#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg) +#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd) +#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg) +#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd) +#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg) +#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd) -#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) -#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) -#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) -#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) -#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) -#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) +#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg) +#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd) +#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg) +#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd) +#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg) +#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd) -#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg) -#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd) +#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg) +#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd) /* 3DNOW extensions */ -#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg) -#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd) +#define pavgusb_m2r(var, reg) mmx_m2r(pavgusb, var, reg) +#define pavgusb_r2r(regs, regd) mmx_r2r(pavgusb, regs, regd) /* AMD MMX extensions - also available in intel SSE */ -#define mmx_m2ri(op,mem,reg,imm) \ - __asm__ __volatile__ (#op " %1, %0, %%" #reg \ - : /* nothing */ \ - : "m" (mem), "i" (imm)) -#define mmx_r2ri(op,regs,regd,imm) \ - __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ - : /* nothing */ \ - : "i" (imm) ) +#define mmx_m2ri(op, mem, reg, imm) \ + __asm__ __volatile__ (#op " %1, %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem), "i" (imm)) +#define mmx_r2ri(op, regs, regd, imm) \ + __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ + : /* nothing */ \ + : "i" (imm)) -#define mmx_fetch(mem,hint) \ - __asm__ __volatile__ ("prefetch" #hint " %0" \ - : /* nothing */ \ - : "m" (mem)) +#define mmx_fetch(mem, hint) \ + __asm__ __volatile__ ("prefetch" #hint " %0" \ + : /* nothing */ \ + : "m" (mem)) -#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) +#define maskmovq(regs, maskreg) mmx_r2ri(maskmovq, regs, maskreg) -#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) +#define movntq_r2m(mmreg, var) mmx_r2m(movntq, mmreg, var) -#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) -#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) -#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) -#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) +#define pavgb_m2r(var, reg) mmx_m2r(pavgb, var, reg) +#define pavgb_r2r(regs, regd) mmx_r2r(pavgb, regs, regd) +#define pavgw_m2r(var, reg) mmx_m2r(pavgw, var, reg) +#define pavgw_r2r(regs, regd) mmx_r2r(pavgw, regs, regd) -#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) +#define pextrw_r2r(mmreg, reg, imm) mmx_r2ri(pextrw, mmreg, reg, imm) -#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) +#define pinsrw_r2r(reg, mmreg, imm) mmx_r2ri(pinsrw, reg, mmreg, imm) -#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) -#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) +#define pmaxsw_m2r(var, reg) mmx_m2r(pmaxsw, var, reg) +#define pmaxsw_r2r(regs, regd) mmx_r2r(pmaxsw, regs, regd) -#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) -#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) +#define pmaxub_m2r(var, reg) mmx_m2r(pmaxub, var, reg) +#define pmaxub_r2r(regs, regd) mmx_r2r(pmaxub, regs, regd) -#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) -#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) +#define pminsw_m2r(var, reg) mmx_m2r(pminsw, var, reg) +#define pminsw_r2r(regs, regd) mmx_r2r(pminsw, regs, regd) -#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) -#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) +#define pminub_m2r(var, reg) mmx_m2r(pminub, var, reg) +#define pminub_r2r(regs, regd) mmx_r2r(pminub, regs, regd) -#define pmovmskb(mmreg,reg) \ - __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) +#define pmovmskb(mmreg, reg) \ + __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) -#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) -#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) +#define pmulhuw_m2r(var, reg) mmx_m2r(pmulhuw, var, reg) +#define pmulhuw_r2r(regs, regd) mmx_r2r(pmulhuw, regs, regd) -#define prefetcht0(mem) mmx_fetch (mem, t0) -#define prefetcht1(mem) mmx_fetch (mem, t1) -#define prefetcht2(mem) mmx_fetch (mem, t2) -#define prefetchnta(mem) mmx_fetch (mem, nta) +#define prefetcht0(mem) mmx_fetch(mem, t0) +#define prefetcht1(mem) mmx_fetch(mem, t1) +#define prefetcht2(mem) mmx_fetch(mem, t2) +#define prefetchnta(mem) mmx_fetch(mem, nta) -#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) -#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) +#define psadbw_m2r(var, reg) mmx_m2r(psadbw, var, reg) +#define psadbw_r2r(regs, regd) mmx_r2r(psadbw, regs, regd) -#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm) -#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm) +#define pshufw_m2r(var, reg, imm) mmx_m2ri(pshufw, var, reg, imm) +#define pshufw_r2r(regs, regd, imm) mmx_r2ri(pshufw, regs, regd, imm) -#define sfence() __asm__ __volatile__ ("sfence\n\t") +#define sfence() __asm__ __volatile__ ("sfence\n\t") /* SSE2 */ -#define pshufhw_m2r(var,reg,imm) mmx_m2ri(pshufhw, var, reg, imm) -#define pshufhw_r2r(regs,regd,imm) mmx_r2ri(pshufhw, regs, regd, imm) -#define pshuflw_m2r(var,reg,imm) mmx_m2ri(pshuflw, var, reg, imm) -#define pshuflw_r2r(regs,regd,imm) mmx_r2ri(pshuflw, regs, regd, imm) +#define pshufhw_m2r(var, reg, imm) mmx_m2ri(pshufhw, var, reg, imm) +#define pshufhw_r2r(regs, regd, imm) mmx_r2ri(pshufhw, regs, regd, imm) +#define pshuflw_m2r(var, reg, imm) mmx_m2ri(pshuflw, var, reg, imm) +#define pshuflw_r2r(regs, regd, imm) mmx_r2ri(pshuflw, regs, regd, imm) -#define pshufd_r2r(regs,regd,imm) mmx_r2ri(pshufd, regs, regd, imm) +#define pshufd_r2r(regs, regd, imm) mmx_r2ri(pshufd, regs, regd, imm) -#define movdqa_m2r(var,reg) mmx_m2r (movdqa, var, reg) -#define movdqa_r2m(reg,var) mmx_r2m (movdqa, reg, var) -#define movdqa_r2r(regs,regd) mmx_r2r (movdqa, regs, regd) -#define movdqu_m2r(var,reg) mmx_m2r (movdqu, var, reg) -#define movdqu_r2m(reg,var) mmx_r2m (movdqu, reg, var) -#define movdqu_r2r(regs,regd) mmx_r2r (movdqu, regs, regd) +#define movdqa_m2r(var, reg) mmx_m2r(movdqa, var, reg) +#define movdqa_r2m(reg, var) mmx_r2m(movdqa, reg, var) +#define movdqa_r2r(regs, regd) mmx_r2r(movdqa, regs, regd) +#define movdqu_m2r(var, reg) mmx_m2r(movdqu, var, reg) +#define movdqu_r2m(reg, var) mmx_r2m(movdqu, reg, var) +#define movdqu_r2r(regs, regd) mmx_r2r(movdqu, regs, regd) -#define pmullw_r2m(reg,var) mmx_r2m (pmullw, reg, var) +#define pmullw_r2m(reg, var) mmx_r2m(pmullw, reg, var) -#define pslldq_i2r(imm,reg) mmx_i2r (pslldq, imm, reg) -#define psrldq_i2r(imm,reg) mmx_i2r (psrldq, imm, reg) +#define pslldq_i2r(imm, reg) mmx_i2r(pslldq, imm, reg) +#define psrldq_i2r(imm, reg) mmx_i2r(psrldq, imm, reg) -#define punpcklqdq_r2r(regs,regd) mmx_r2r (punpcklqdq, regs, regd) -#define punpckhqdq_r2r(regs,regd) mmx_r2r (punpckhqdq, regs, regd) +#define punpcklqdq_r2r(regs, regd) mmx_r2r(punpcklqdq, regs, regd) +#define punpckhqdq_r2r(regs, regd) mmx_r2r(punpckhqdq, regs, regd) #endif /* AVCODEC_I386MMX_H */ diff --git a/drivers/staging/epl/Benchmark.h b/drivers/staging/epl/Benchmark.h index 62dee3b14373..4cc01bd12a1a 100644 --- a/drivers/staging/epl/Benchmark.h +++ b/drivers/staging/epl/Benchmark.h @@ -73,12 +73,6 @@ #include "global.h" -#if (TARGET_SYSTEM == _NO_OS_) && (DEV_SYSTEM == _DEV_GNU_CF548X_) -#include "common.h" - -#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) - -// #include #include #ifdef CONFIG_COLDFIRE @@ -93,12 +87,6 @@ #define BENCHMARK_MODULES 0x00000000 #endif -#else - // disable Benchmarking -#undef BENCHMARK_MODULES -#define BENCHMARK_MODULES 0x00000000 -#endif - /***************************************************************************/ /* */ /* */ diff --git a/drivers/staging/epl/Debug.h b/drivers/staging/epl/Debug.h index 05de9d541fd6..851a22213ad7 100644 --- a/drivers/staging/epl/Debug.h +++ b/drivers/staging/epl/Debug.h @@ -163,25 +163,6 @@ #endif //--------------------------------------------------------------------------- -#if (DEV_SYSTEM == _DEV_WIN32_) && defined (TRACE_MSG) - - // For WIN32 the macro DEBUG_TRACE0 can be defined as function call TraceLvl() - // or as macro TRACE(). - // - // Here the parameter 'lvl' can be used with more than one - // debug-level (using OR). - // - // Example: DEBUG_TRACE1(DEBUG_LVL_30 | DEBUG_LVL_02, "Hello %d", bCount); - -#define DEBUG_TRACE0(lvl,str) TraceLvl((lvl),str) -#define DEBUG_TRACE1(lvl,str,p1) TraceLvl((lvl),str,p1) -#define DEBUG_TRACE2(lvl,str,p1,p2) TraceLvl((lvl),str,p1,p2) -#define DEBUG_TRACE3(lvl,str,p1,p2,p3) TraceLvl((lvl),str,p1,p2,p3) -#define DEBUG_TRACE4(lvl,str,p1,p2,p3,p4) TraceLvl((lvl),str,p1,p2,p3,p4) -#define DEBUG_GLB_LVL() dwDebugLevel_g - -#else - // At microcontrollers we do reduce the memory usage by deleting DEBUG_TRACE-lines // (compiler does delete the lines). // @@ -643,25 +624,23 @@ #define DEBUG_TRACE3(lvl,str,p1,p2,p3) lvl##_TRACE3(str,p1,p2,p3) #define DEBUG_TRACE4(lvl,str,p1,p2,p3,p4) lvl##_TRACE4(str,p1,p2,p3,p4) -#endif - //--------------------------------------------------------------------------- // The macro DEBUG_DUMP_DATA() can be used with the same debug-levels to dump // out data bytes. Function DumpData() has to be included. // NOTE: DUMP_DATA has to be defined in project settings. -#if (!defined (NDEBUG) && defined (DUMP_DATA)) || (DEV_SYSTEM == _DEV_WIN32_) +#if (!defined (NDEBUG) && defined (DUMP_DATA)) #ifdef __cplusplus extern "C" { #endif - void DumpData(char *szStr_p, BYTE MEM * pbData_p, WORD wSize_p); + void DumpData(char *szStr_p, u8 *pbData_p, u16 wSize_p); #ifdef __cplusplus } // von extern "C" #endif #define DEBUG_DUMP_DATA(lvl,str,ptr,siz) if ((DEBUG_GLB_LVL() & (lvl))==(lvl)) \ - DumpData (str, (BYTE MEM*) (ptr), (WORD) (siz)); + DumpData (str, (u8 *)(ptr), (u16)(siz)); #else #define DEBUG_DUMP_DATA(lvl,str,ptr,siz) @@ -675,24 +654,6 @@ extern "C" { // deleted from compiler (in release version too). #if !defined (NDEBUG) || defined (DEBUG_KEEP_ASSERT) -#if (DEV_SYSTEM == _DEV_WIN32_) - - // For WIN32 process will be killed after closing message box. - -#define DEBUG_ASSERT0(expr,str) if (!(expr ) && ((DEBUG_GLB_LVL() & DEBUG_LVL_ASSERT)!=0)) { \ - MessageBox (NULL, \ - "Assertion failed: line " __LINE__ " file " __FILE__ \ - "\n -> " str "\n"); \ - ExitProcess (-1); } - -#define DEBUG_ASSERT1(expr,str,p1) if (!(expr ) && ((DEBUG_GLB_LVL() & DEBUG_LVL_ASSERT)!=0)) { \ - MessageBox (NULL, \ - "Assertion failed: line " __LINE__ " file " __FILE__ \ - "\n -> " str "\n"); \ - ExitProcess (-1); } - -#else - // For microcontrollers process will be stopped using endless loop. #define DEBUG_ASSERT0(expr,str) if (!(expr )) { \ @@ -705,10 +666,9 @@ extern "C" { DEBUG_LVL_ASSERT_TRACE4 ( \ "Assertion failed: line %d file '%s'\n" \ " -> '%s'\n" \ - " -> 0x%08lX\n", __LINE__, __FILE__, str, (DWORD) p1); \ + " -> 0x%08lX\n", __LINE__, __FILE__, str, (u32) p1); \ while (1); } -#endif #else diff --git a/drivers/staging/epl/Edrv8139.c b/drivers/staging/epl/Edrv8139.c index 296354aaa9c7..44e3f7b144bc 100644 --- a/drivers/staging/epl/Edrv8139.c +++ b/drivers/staging/epl/Edrv8139.c @@ -81,7 +81,6 @@ #include #include #include -#include #include #include #include @@ -234,8 +233,8 @@ // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); -void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); +void TgtDbgPostTraceValue(u32 dwTraceValue_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) #else @@ -282,9 +281,9 @@ typedef struct typedef struct { struct pci_dev *m_pPciDev; // pointer to PCI device structure void *m_pIoAddr; // pointer to register space of Ethernet controller - BYTE *m_pbRxBuf; // pointer to Rx buffer + u8 *m_pbRxBuf; // pointer to Rx buffer dma_addr_t m_pRxBufDma; - BYTE *m_pbTxBuf; // pointer to Tx buffer + u8 *m_pbTxBuf; // pointer to Tx buffer dma_addr_t m_pTxBufDma; BOOL m_afTxBufUsed[EDRV_MAX_TX_BUFFERS]; unsigned int m_uiCurTxDesc; @@ -359,7 +358,7 @@ static struct pci_driver EdrvDriver = { // local function prototypes //--------------------------------------------------------------------------- -static BYTE EdrvCalcHash(BYTE * pbMAC_p); +static u8 EdrvCalcHash(u8 * pbMAC_p); //--------------------------------------------------------------------------- // @@ -453,20 +452,20 @@ tEplKernel EdrvShutdown(void) // State: // //--------------------------------------------------------------------------- -tEplKernel EdrvDefineRxMacAddrEntry(BYTE * pbMacAddr_p) +tEplKernel EdrvDefineRxMacAddrEntry(u8 * pbMacAddr_p) { tEplKernel Ret = kEplSuccessful; - DWORD dwData; - BYTE bHash; + u32 dwData; + u8 bHash; bHash = EdrvCalcHash(pbMacAddr_p); /* dwData = ether_crc(6, pbMacAddr_p); printk("EdrvDefineRxMacAddrEntry('%02X:%02X:%02X:%02X:%02X:%02X') hash = %u / %u ether_crc = 0x%08lX\n", - (WORD) pbMacAddr_p[0], (WORD) pbMacAddr_p[1], (WORD) pbMacAddr_p[2], - (WORD) pbMacAddr_p[3], (WORD) pbMacAddr_p[4], (WORD) pbMacAddr_p[5], - (WORD) bHash, (WORD) (dwData >> 26), dwData); + (u16) pbMacAddr_p[0], (u16) pbMacAddr_p[1], (u16) pbMacAddr_p[2], + (u16) pbMacAddr_p[3], (u16) pbMacAddr_p[4], (u16) pbMacAddr_p[5], + (u16) bHash, (u16) (dwData >> 26), dwData); */ if (bHash > 31) { dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR4); @@ -494,11 +493,11 @@ tEplKernel EdrvDefineRxMacAddrEntry(BYTE * pbMacAddr_p) // State: // //--------------------------------------------------------------------------- -tEplKernel EdrvUndefineRxMacAddrEntry(BYTE * pbMacAddr_p) +tEplKernel EdrvUndefineRxMacAddrEntry(u8 * pbMacAddr_p) { tEplKernel Ret = kEplSuccessful; - DWORD dwData; - BYTE bHash; + u32 dwData; + u8 bHash; bHash = EdrvCalcHash(pbMacAddr_p); @@ -532,7 +531,7 @@ tEplKernel EdrvUndefineRxMacAddrEntry(BYTE * pbMacAddr_p) tEplKernel EdrvAllocTxMsgBuffer(tEdrvTxBuffer * pBuffer_p) { tEplKernel Ret = kEplSuccessful; - DWORD i; + u32 i; if (pBuffer_p->m_uiMaxBufferLen > EDRV_MAX_FRAME_SIZE) { Ret = kEplEdrvNoFreeBufEntry; @@ -605,7 +604,7 @@ tEplKernel EdrvSendTxMsg(tEdrvTxBuffer * pBuffer_p) { tEplKernel Ret = kEplSuccessful; unsigned int uiBufferNumber; - DWORD dwTemp; + u32 dwTemp; uiBufferNumber = pBuffer_p->m_uiBufferNumber; @@ -620,11 +619,11 @@ tEplKernel EdrvSendTxMsg(tEdrvTxBuffer * pBuffer_p) dwTemp = EDRV_REGDW_READ((EDRV_REGDW_TSD0 + (EdrvInstance_l.m_uiCurTxDesc * - sizeof(DWORD)))); - printk("%s InvOp TSD%u = 0x%08lX", __func__, + sizeof(u32)))); + printk("%s InvOp TSD%u = 0x%08X", __func__, EdrvInstance_l.m_uiCurTxDesc, dwTemp); printk(" Cmd = 0x%02X\n", - (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND)); + (u16) EDRV_REGB_READ(EDRV_REGB_COMMAND)); goto Exit; } // save pointer to buffer structure for TxHandler @@ -640,22 +639,22 @@ tEplKernel EdrvSendTxMsg(tEdrvTxBuffer * pBuffer_p) } // set DMA address of buffer EDRV_REGDW_WRITE((EDRV_REGDW_TSAD0 + - (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))), + (EdrvInstance_l.m_uiCurTxDesc * sizeof(u32))), (EdrvInstance_l.m_pTxBufDma + (uiBufferNumber * EDRV_MAX_FRAME_SIZE))); dwTemp = EDRV_REGDW_READ((EDRV_REGDW_TSAD0 + - (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD)))); + (EdrvInstance_l.m_uiCurTxDesc * sizeof(u32)))); // printk("%s TSAD%u = 0x%08lX", __func__, EdrvInstance_l.m_uiCurTxDesc, dwTemp); // start transmission EDRV_REGDW_WRITE((EDRV_REGDW_TSD0 + - (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))), + (EdrvInstance_l.m_uiCurTxDesc * sizeof(u32))), (EDRV_REGDW_TSD_TXTH_DEF | pBuffer_p->m_uiTxMsgLen)); dwTemp = EDRV_REGDW_READ((EDRV_REGDW_TSD0 + - (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD)))); -// printk(" TSD%u = 0x%08lX / 0x%08lX\n", EdrvInstance_l.m_uiCurTxDesc, dwTemp, (DWORD)(EDRV_REGDW_TSD_TXTH_DEF | pBuffer_p->m_uiTxMsgLen)); + (EdrvInstance_l.m_uiCurTxDesc * sizeof(u32)))); +// printk(" TSD%u = 0x%08lX / 0x%08lX\n", EdrvInstance_l.m_uiCurTxDesc, dwTemp, (u32)(EDRV_REGDW_TSD_TXTH_DEF | pBuffer_p->m_uiTxMsgLen)); Exit: return Ret; @@ -720,7 +719,7 @@ tEplKernel EdrvTxMsgStart(tEdrvTxBuffer * pBuffer_p) //--------------------------------------------------------------------------- static void EdrvReinitRx(void) { - BYTE bCmd; + u8 bCmd; // simply switch off and on the receiver // this will reset the CAPR register @@ -751,21 +750,16 @@ void EdrvInterruptHandler(void) } #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p) -#else -static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p, - struct pt_regs *ptRegs_p) -#endif { // EdrvInterruptHandler(); tEdrvRxBuffer RxBuffer; tEdrvTxBuffer *pTxBuffer; - WORD wStatus; - DWORD dwTxStatus; - DWORD dwRxStatus; - WORD wCurRx; - BYTE *pbRxBuf; + u16 wStatus; + u32 dwTxStatus; + u32 dwRxStatus; + u16 wCurRx; + u8 *pbRxBuf; unsigned int uiLength; int iHandled = IRQ_HANDLED; @@ -793,7 +787,7 @@ static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p, dwTxStatus = EDRV_REGDW_READ((EDRV_REGDW_TSD0 + (EdrvInstance_l.m_uiCurTxDesc * - sizeof(DWORD)))); + sizeof(u32)))); if ((dwTxStatus & (EDRV_REGDW_TSD_TOK | EDRV_REGDW_TSD_TABT | EDRV_REGDW_TSD_TUN)) != 0) { // transmit finished EdrvInstance_l.m_uiCurTxDesc = (EdrvInstance_l.m_uiCurTxDesc + 1) & 0x03; @@ -855,8 +849,8 @@ static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p, // calculate pointer to current frame in receive buffer pbRxBuf = EdrvInstance_l.m_pbRxBuf + wCurRx; - // read receive status DWORD - dwRxStatus = le32_to_cpu(*((DWORD *) pbRxBuf)); + // read receive status u32 + dwRxStatus = le32_to_cpu(*((u32 *) pbRxBuf)); // calculate length of received frame uiLength = dwRxStatus >> 16; @@ -896,9 +890,9 @@ static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p, m_pfnRxHandler(&RxBuffer); } - // calulate new offset (DWORD aligned) + // calulate new offset (u32 aligned) wCurRx = - (WORD) ((wCurRx + uiLength + sizeof(dwRxStatus) + + (u16) ((wCurRx + uiLength + sizeof(dwRxStatus) + 3) & ~0x3); EDRV_TRACE_CAPR(wCurRx - 0x10); EDRV_REGW_WRITE(EDRV_REGW_CAPR, wCurRx - 0x10); @@ -941,7 +935,7 @@ static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p, static int EdrvInitOne(struct pci_dev *pPciDev, const struct pci_device_id *pId) { int iResult = 0; - DWORD dwTemp; + u32 dwTemp; if (EdrvInstance_l.m_pPciDev != NULL) { // Edrv is already connected to a PCI device printk("%s device %s discarded\n", __func__, @@ -1008,7 +1002,7 @@ static int EdrvInitOne(struct pci_dev *pPciDev, const struct pci_device_id *pId) dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TCR); if (((dwTemp & EDRV_REGDW_TCR_VER_MASK) != EDRV_REGDW_TCR_VER_C) && ((dwTemp & EDRV_REGDW_TCR_VER_MASK) != EDRV_REGDW_TCR_VER_D)) { // unsupported chip - printk("%s Unsupported chip! TCR = 0x%08lX\n", __func__, + printk("%s Unsupported chip! TCR = 0x%08X\n", __func__, dwTemp); iResult = -ENODEV; goto Exit; @@ -1043,11 +1037,11 @@ static int EdrvInitOne(struct pci_dev *pPciDev, const struct pci_device_id *pId) printk("%s set local MAC address\n", __func__); // write this MAC address to controller EDRV_REGDW_WRITE(EDRV_REGDW_IDR0, - le32_to_cpu(*((DWORD*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[0]))); + le32_to_cpu(*((u32*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[0]))); dwTemp = EDRV_REGDW_READ(EDRV_REGDW_IDR0); EDRV_REGDW_WRITE(EDRV_REGDW_IDR4, - le32_to_cpu(*((DWORD*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[4]))); + le32_to_cpu(*((u32*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[4]))); dwTemp = EDRV_REGDW_READ(EDRV_REGDW_IDR4); break; } @@ -1087,7 +1081,7 @@ static int EdrvInitOne(struct pci_dev *pPciDev, const struct pci_device_id *pId) dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD3); printk(" Command = 0x%02X\n", - (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND)); + (u16) EDRV_REGB_READ(EDRV_REGB_COMMAND)); // set pointer for receive buffer in controller printk("%s set pointer to Rx buffer\n", __func__); @@ -1098,7 +1092,7 @@ static int EdrvInitOne(struct pci_dev *pPciDev, const struct pci_device_id *pId) EDRV_REGB_WRITE(EDRV_REGB_COMMAND, (EDRV_REGB_COMMAND_RE | EDRV_REGB_COMMAND_TE)); printk(" Command = 0x%02X\n", - (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND)); + (u16) EDRV_REGB_READ(EDRV_REGB_COMMAND)); // clear missed packet counter to enable Rx/Tx process EDRV_REGDW_WRITE(EDRV_REGDW_MPC, 0); @@ -1123,7 +1117,7 @@ static int EdrvInitOne(struct pci_dev *pPciDev, const struct pci_device_id *pId) // enable transmitter and receiver printk("%s enable Tx and Rx", __func__); EDRV_REGB_WRITE(EDRV_REGB_COMMAND, (EDRV_REGB_COMMAND_RE | EDRV_REGB_COMMAND_TE)); - printk(" Command = 0x%02X\n", (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND)); + printk(" Command = 0x%02X\n", (u16) EDRV_REGB_READ(EDRV_REGB_COMMAND)); */ // disable early interrupts EDRV_REGW_WRITE(EDRV_REGW_MULINT, 0); @@ -1215,15 +1209,15 @@ static void EdrvRemoveOne(struct pci_dev *pPciDev) //#define CRC32_POLY 0xEDB88320 // // G(x) = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 -static BYTE EdrvCalcHash(BYTE * pbMAC_p) +static u8 EdrvCalcHash(u8 * pbMAC_p) { - DWORD dwByteCounter; - DWORD dwBitCounter; - DWORD dwData; - DWORD dwCrc; - DWORD dwCarry; - BYTE *pbData; - BYTE bHash; + u32 dwByteCounter; + u32 dwBitCounter; + u32 dwData; + u32 dwCrc; + u32 dwCarry; + u8 *pbData; + u8 bHash; pbData = pbMAC_p; @@ -1246,7 +1240,7 @@ static BYTE EdrvCalcHash(BYTE * pbMAC_p) // printk("MyCRC = 0x%08lX\n", dwCrc); // only upper 6 bits (HASH_BITS) are used // which point to specific bit in the hash registers - bHash = (BYTE) ((dwCrc >> (32 - HASH_BITS)) & 0x3f); + bHash = (u8) ((dwCrc >> (32 - HASH_BITS)) & 0x3f); return bHash; } diff --git a/drivers/staging/epl/EdrvFec.h b/drivers/staging/epl/EdrvFec.h index 5f252fbed744..56728d1e95e7 100644 --- a/drivers/staging/epl/EdrvFec.h +++ b/drivers/staging/epl/EdrvFec.h @@ -96,9 +96,9 @@ // Rx and Tx buffer descriptor format typedef struct { - WORD m_wStatus; // control / status --- used by edrv, do not change in application - WORD m_wLength; // transfer length - BYTE *m_pbData; // buffer address + u16 m_wStatus; // control / status --- used by edrv, do not change in application + u16 m_wLength; // transfer length + u8 *m_pbData; // buffer address } tBufferDescr; #if ((TARGET_HARDWARE & TGT_CPU_MASK_) == TGT_CPU_5282) diff --git a/drivers/staging/epl/EdrvFec5282.h b/drivers/staging/epl/EdrvFec5282.h deleted file mode 100644 index a16bb1d4da79..000000000000 --- a/drivers/staging/epl/EdrvFec5282.h +++ /dev/null @@ -1,340 +0,0 @@ -/**************************************************************************** - - (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 - www.systec-electronic.com - - Project: openPOWERLINK - - Description: interface for ethernetdriver - "fast ethernet controller" (FEC) - freescale coldfire MCF528x and compatible FEC - - License: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of SYSTEC electronic GmbH nor the names of its - contributors may be used to endorse or promote products derived - from this software without prior written permission. For written - permission, please contact info@systec-electronic.com. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Severability Clause: - - If a provision of this License is or becomes illegal, invalid or - unenforceable in any jurisdiction, that shall not affect: - 1. the validity or enforceability in that jurisdiction of any other - provision of this License; or - 2. the validity or enforceability in other jurisdictions of that or - any other provision of this License. - - ------------------------------------------------------------------------- - - $RCSfile: EdrvFec5282.h,v $ - - $Author: D.Krueger $ - - $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ - - $State: Exp $ - - Build Environment: - Dev C++ and GNU-Compiler for m68k - - ------------------------------------------------------------------------- - - Revision History: - - 2005/08/01 m.b.: start of implementation - -****************************************************************************/ - -#ifndef _EDRVFEC_H_ -#define _EDRVFEC_H_ - -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- -// base addresses -#define FEC0_ADDR 0x0000 -#define FEC1_ADDR 0x0000 //tbd - -// control / status registers -#define FEC_EIR 0x1004 // interrupt event register -#define FEC_EIMR 0x1008 // interrupt mask register -#define FEC_RDAR 0x1010 // receive descriptor active register -#define FEC_TDAR 0x1014 // transmit descriptor active register -#define FEC_ECR 0x1024 // ethernet control register -#define FEC_MMFR 0x1040 // MII data register -#define FEC_MSCR 0x1044 // MII speed register -#define FEC_MIBC 0x1064 // MIB control/status register -#define FEC_RCR 0x1084 // receive control register -#define FEC_TCR 0x10C4 // transmit control register -#define FEC_PALR 0x10E4 // physical address low register -#define FEC_PAUR 0x10E8 // physical address high + type register -#define FEC_OPD 0x10EC // opcode + pause register -#define FEC_IAUR 0x1118 // upper 32 bit of individual hash table -#define FEC_IALR 0x111C // lower 32 bit of individual hash table -#define FEC_GAUR 0x1120 // upper 32 bit of group hash table -#define FEC_GALR 0x1124 // lower 32 bit of group hash table -#define FEC_TFWR 0x1144 // transmit FIFO watermark -#define FEC_FRBR 0x114C // FIFO receive bound register -#define FEC_FRSR 0x1150 // FIFO receive FIFO start register -#define FEC_ERDSR 0x1180 // pointer to receive descriptor ring -#define FEC_ETDSR 0x1184 // pointer to transmit descriptor ring -#define FEC_EMRBR 0x1188 // maximum receive buffer size - -// mib block counters memory map -#define FEC_RMON_T_DROP 0x1200 // count of frames not counted correctly -#define FEC_RMON_T_PACKETS 0x1204 // RMON tx packet count -#define FEC_RMON_T_BC_PKT 0x1208 // RMON tx broadcast packets -#define FEC_RMON_T_MC_PKT 0x120C // RMON tx multicast packets -#define FEC_RMON_T_CRC_ALIGN 0x1210 // RMON tx packets w CRC/align error -#define FEC_RMON_T_UNDERSIZE 0x1214 // RMON tx packets < 64 bytes, good CRC -#define FEC_RMON_T_OVERSIZE 0x1218 // RMON tx packets > MAX_FL bytes, good CRC -#define FEC_RMON_T_FRAG 0x121C // RMON tx packets < 64 bytes, bad CRC -#define FEC_RMON_T_JAB 0x1220 // RMON tx packets > MAX_FL bytes, bad CRC -#define FEC_RMON_T_COL 0x1224 // RMON tx collision count -#define FEC_RMON_T_P64 0x1228 // RMON tx 64 byte packets -#define FEC_RMON_T_P65TO127 0x122C // RMON tx 65 to 127 byte packets -#define FEC_RMON_T_P128TO255 0x1230 // RMON tx 128 to 255 byte packets -#define FEC_RMON_T_P256TO511 0x1234 // RMON tx 256 to 511 byte packets -#define FEC_RMON_T_P512TO1023 0x1238 // RMON tx 512 to 1023 byte packets -#define FEC_RMON_T_P1024TO2047 0x123C // RMON tx 1024 to 2047 byte packets -#define FEC_RMON_T_P_GTE2048 0x1240 // RMON tx w > 2048 bytes -#define FEC_RMON_T_OCTETS 0x1244 // RMON tx octets -#define FEC_IEEE_T_DROP 0x1248 // count of frames not counted correctly -#define FEC_IEEE_T_FRAME_OK 0x124C // frames transmitted OK -#define FEC_IEEE_T_1COL 0x1250 // frames transmitted with single collision -#define FEC_IEEE_T_MCOL 0x1254 // frames transmitted with multiple collisions -#define FEC_IEEE_T_DEF 0x1258 // frames transmitted after deferral delay -#define FEC_IEEE_T_LCOL 0x125C // frames transmitted with late collisions -#define FEC_IEEE_T_EXCOL 0x1260 // frames transmitted with excessive collisions -#define FEC_IEEE_T_MACERR 0x1264 // frames transmitted with tx-FIFO underrun -#define FEC_IEEE_T_CSERR 0x1268 // frames transmitted with carrier sense error -#define FEC_IEEE_T_SQE 0x126C // frames transmitted with SQE error -#define FEC_IEEE_T_FDXFC 0x1270 // flow control pause frames transmitted -#define FEC_IEEE_T_OCTETS_OK 0x1274 // octet count for frames transmitted w/o error -#define FEC_RMON_R_PACKETS 0x1284 // RMON rx packet count -#define FEC_RMON_R_BC_PKT 0x1288 // RMON rx broadcast packets -#define FEC_RMON_R_MC_PKT 0x128C // RMON rx multicast packets -#define FEC_RMON_R_CRC_ALIGN 0x1290 // RMON rx packets w CRC/align error -#define FEC_RMON_R_UNDERSIZE 0x1294 // RMON rx packets < 64 bytes, good CRC -#define FEC_RMON_R_OVERSIZE 0x1298 // RMON rx packets > MAX_FL bytes, good CRC -#define FEC_RMON_R_FRAG 0x129C // RMON rx packets < 64 bytes, bad CRC -#define FEC_RMON_R_JAB 0x12A0 // RMON rx packets > MAX_FL bytes, bad CRC -#define FEC_RMON_R_RESVD_0 0x12A4 // -#define FEC_RMON_R_P64 0x12A8 // RMON rx 64 byte packets -#define FEC_RMON_R_P65T0127 0x12AC // RMON rx 65 to 127 byte packets -#define FEC_RMON_R_P128TO255 0x12B0 // RMON rx 128 to 255 byte packets -#define FEC_RMON_R_P256TO511 0x12B4 // RMON rx 256 to 511 byte packets -#define FEC_RMON_R_P512TO1023 0x12B8 // RMON rx 512 to 1023 byte packets -#define FEC_RMON_R_P1024TO2047 0x12BC // RMON rx 1024 to 2047 byte packets -#define FEC_RMON_R_GTE2048 0x12C0 // RMON rx w > 2048 bytes -#define FEC_RMON_R_OCTETS 0x12C4 // RMON rx octets -#define FEC_IEEE_R_DROP 0x12C8 // count of frames not counted correctly -#define FEC_IEEE_R_FRAME_OK 0x12CC // frames received OK -#define FEC_IEEE_R_CRC 0x12D0 // frames received with CRC error -#define FEC_IEEE_R_ALIGN 0x12D4 // frames received with alignment error -#define FEC_IEEE_R_MACERR 0x12D8 // receive FIFO overflow count -#define FEC_IEEE_R_FDXFC 0x12DC // flow control pause frames received -#define FEC_IEEE_R_OCTETS_OK 0x12E0 // octet count for frames rcvd w/o error - -// register bit definitions and macros -#define FEC_EIR_UN (0x00080000) -#define FEC_EIR_RL (0x00100000) -#define FEC_EIR_LC (0x00200000) -#define FEC_EIR_EBERR (0x00400000) -#define FEC_EIR_MII (0x00800000) -#define FEC_EIR_RXB (0x01000000) -#define FEC_EIR_RXF (0x02000000) -#define FEC_EIR_TXB (0x04000000) -#define FEC_EIR_TXF (0x08000000) -#define FEC_EIR_GRA (0x10000000) -#define FEC_EIR_BABT (0x20000000) -#define FEC_EIR_BABR (0x40000000) -#define FEC_EIR_HBERR (0x80000000) - -#define FEC_EIMR_UN (0x00080000) -#define FEC_EIMR_RL (0x00100000) -#define FEC_EIMR_LC (0x00200000) -#define FEC_EIMR_EBERR (0x00400000) -#define FEC_EIMR_MII (0x00800000) -#define FEC_EIMR_RXB (0x01000000) -#define FEC_EIMR_RXF (0x02000000) -#define FEC_EIMR_TXB (0x04000000) -#define FEC_EIMR_TXF (0x08000000) -#define FEC_EIMR_GRA (0x10000000) -#define FEC_EIMR_BABT (0x20000000) -#define FEC_EIMR_BABR (0x40000000) -#define FEC_EIMR_HBERR (0x80000000) - -#define FEC_RDAR_R_DES_ACTIVE (0x01000000) - -#define FEC_TDAR_X_DES_ACTIVE (0x01000000) - -#define FEC_ECR_RESET (0x00000001) -#define FEC_ECR_ETHER_EN (0x00000002) - -#define FEC_MMFR_DATA(x) (((x) & 0xFFFF)) -#define FEC_MMFR_TA (0x00020000) -#define FEC_MMFR_RA(x) (((x) & 0x1F) << 18) -#define FEC_MMFR_PA(x) (((x) & 0x1F) << 23) -#define FEC_MMFR_OP_WR (0x10000000) -#define FEC_MMFR_OP_RD (0x20000000) -#define FEC_MMFR_ST (0x40000000) - -#define FEC_MSCR_MII_SPEED(x) (((x) & 0x1F) << 1) -#define FEC_MSCR_DIS_PREAMBLE (0x00000008) - -#define FEC_MIBC_MIB_IDLE (0x40000000) -#define FEC_MIBC_MIB_DISABLE (0x80000000) - -#define FEC_RCR_LOOP (0x00000001) -#define FEC_RCR_DRT (0x00000002) -#define FEC_RCR_MII_MODE (0x00000004) -#define FEC_RCR_PROM (0x00000008) -#define FEC_RCR_BC_REJ (0x00000010) -#define FEC_RCR_FCE (0x00000020) -#define FEC_RCR_MAX_FL(x) (((x) & 0x07FF) << 16) - -#define FEC_TCR_GTS (0x00000001) -#define FEC_TCR_HBC (0x00000002) -#define FEC_TCR_FDEN (0x00000004) -#define FEC_TCR_TFC_PAUSE (0x00000008) -#define FEC_TCR_RFC_PAUSE (0x00000010) - -#define FEC_PALR_BYTE3(x) (((x) & 0xFF) << 0) -#define FEC_PALR_BYTE2(x) (((x) & 0xFF) << 8) -#define FEC_PALR_BYTE1(x) (((x) & 0xFF) << 16) -#define FEC_PALR_BYTE0(x) (((x) & 0xFF) << 24) - -//#define FEC_PAUR_TYPE(x) (((x) & 0xFFFF) << 0) -#define FEC_PAUR_BYTE5(x) (((x) & 0xFF) << 16) -#define FEC_PAUR_BYTE4(x) (((x) & 0xFF) << 24) - -#define FEC_OPD_PAUSE_DUR(x) (((x) & 0xFFFF)) -//#define FEC_OPD_OPCODE(x) (((x) & 0xFFFF) << 16) - -//m.b. -#define FEC_IAUR_BYTE7(x) (((x) & 0xFF) << 0) -#define FEC_IAUR_BYTE6(x) (((x) & 0xFF) << 8) -#define FEC_IAUR_BYTE5(x) (((x) & 0xFF) << 16) -#define FEC_IAUR_BYTE4(x) (((x) & 0xFF) << 24) - -#define FEC_IALR_BYTE3(x) (((x) & 0xFF) << 0) -#define FEC_IALR_BYTE2(x) (((x) & 0xFF) << 8) -#define FEC_IALR_BYTE1(x) (((x) & 0xFF) << 16) -#define FEC_IALR_BYTE0(x) (((x) & 0xFF) << 24) - -#define FEC_GAUR_BYTE7(x) (((x) & 0xFF) << 0) -#define FEC_GAUR_BYTE6(x) (((x) & 0xFF) << 8) -#define FEC_GAUR_BYTE5(x) (((x) & 0xFF) << 16) -#define FEC_GAUR_BYTE4(x) (((x) & 0xFF) << 24) - -#define FEC_GALR_BYTE3(x) (((x) & 0xFF) << 0) -#define FEC_GALR_BYTE2(x) (((x) & 0xFF) << 8) -#define FEC_GALR_BYTE1(x) (((x) & 0xFF) << 16) -#define FEC_GALR_BYTE0(x) (((x) & 0xFF) << 24) -// ^^^^ - -#define FEC_TFWR_X_WMRK_64 (0x00000001) -#define FEC_TFWR_X_WMRK_128 (0x00000002) -#define FEC_TFWR_X_WMRK_192 (0x00000003) - -//m.b. -#define FEC_FRBR_R_BOUND(x) (((x) & 0xFF) << 2) - -//m.b. -#define FEC_FRSR_R_FSTART(x) (((x) & 0xFF) << 2) - -//m.b. -#define FEC_ERDSR_R_DES_START(x) (((x) & 0x3FFFFFFF) << 2) - -//m.b. -#define FEC_ETSDR_X_DES_START(x) (((x) & 0x3FFFFFFF) << 2) - -#define FEC_EMRBR_R_BUF_SIZE(x) (((x) & 0x7F) << 4) - -#define FEC_RxBD_TR 0x0001 -#define FEC_RxBD_OV 0x0002 -#define FEC_RxBD_CR 0x0004 -#define FEC_RxBD_NO 0x0010 -#define FEC_RxBD_LG 0x0020 -#define FEC_RxBD_MC 0x0040 -#define FEC_RxBD_BC 0x0080 -#define FEC_RxBD_M 0x0100 -#define FEC_RxBD_L 0x0800 -#define FEC_RxBD_R02 0x1000 -#define FEC_RxBD_W 0x2000 -#define FEC_RxBD_R01 0x4000 -#define FEC_RxBD_INUSE 0x4000 -#define FEC_RxBD_E 0x8000 - -//m.b. -//#define FEC_TxBD_CSL 0x0001 -//#define FEC_TxBD_UN 0x0002 -//#define FEC_TxBD_RL 0x0040 -//#define FEC_TxBD_LC 0x0080 -//#define FEC_TxBD_HB 0x0100 -//#define FEC_TxBD_DEF 0x0200 -#define FEC_TxBD_ABC 0x0200 -// ^^^^ -#define FEC_TxBD_TC 0x0400 -#define FEC_TxBD_L 0x0800 -#define FEC_TxBD_TO2 0x1000 -#define FEC_TxBD_W 0x2000 -#define FEC_TxBD_TO1 0x4000 -#define FEC_TxBD_INUSE 0x4000 -#define FEC_TxBD_R 0x8000 - -//--------------------------------------------------------------------------- -// types -//--------------------------------------------------------------------------- - -// Rx and Tx buffer descriptor format -typedef struct { - WORD m_wStatus; // control / status --- used by edrv, do not change in application - WORD m_wLength; // transfer length - BYTE *m_pbData; // buffer address -} tBufferDescr; - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - -#if (NO_OF_INSTANCES > 1) -#define ECI_WRITE_DW_REG(off,val) (*(DWORD *)(void *)(&__IPSBAR[off]) = val) -#define ECI_READ_DW_REG(off) (*(DWORD *)(void *)(&__IPSBAR[off])) -#else -#if (EDRV_USED_ETH_CTRL == 0) -#define ECI_WRITE_DW_REG(off,val) (*(DWORD *)(void *)(&__IPSBAR[FEC0_ADDR+off]) = val) -#define ECI_READ_DW_REG(off) (*(DWORD *)(void *)(&__IPSBAR[FEC0_ADDR+off])) -#else -#define ECI_WRITE_DW_REG(off,val) (*(DWORD *)(void *)(&__IPSBAR[FEC1_ADDR+off]) = val) -#define ECI_READ_DW_REG(off) (*(DWORD *)(void *)(&__IPSBAR[FEC1_ADDR+off])) -#endif -#endif - -#endif // #ifndef _EDRV_FEC_H_ diff --git a/drivers/staging/epl/EdrvSim.h b/drivers/staging/epl/EdrvSim.h index 39300e321d6c..191ec1457d26 100644 --- a/drivers/staging/epl/EdrvSim.h +++ b/drivers/staging/epl/EdrvSim.h @@ -83,7 +83,7 @@ // function prototypes //--------------------------------------------------------------------------- -void EdrvRxInterruptHandler(BYTE bBufferInFrame_p, BYTE * pbEthernetData_p, - WORD wDataLen_p); +void EdrvRxInterruptHandler(u8 bBufferInFrame_p, u8 * pbEthernetData_p, + u16 wDataLen_p); #endif // #ifndef _EDRVSIM_H_ diff --git a/drivers/staging/epl/Epl.h b/drivers/staging/epl/Epl.h index be60f771b63a..7f22b04022b2 100644 --- a/drivers/staging/epl/Epl.h +++ b/drivers/staging/epl/Epl.h @@ -89,7 +89,7 @@ typedef struct { unsigned int m_uiNodeId; tEplNmtState m_NmtState; tEplNmtNodeEvent m_NodeEvent; - WORD m_wErrorCode; // EPL error code if m_NodeEvent == kEplNmtNodeEventError + u16 m_wErrorCode; // EPL error code if m_NodeEvent == kEplNmtNodeEventError BOOL m_fMandatory; } tEplApiEventNode; @@ -97,7 +97,7 @@ typedef struct { typedef struct { tEplNmtState m_NmtState; // local NMT state tEplNmtBootEvent m_BootEvent; - WORD m_wErrorCode; // EPL error code if m_BootEvent == kEplNmtBootEventError + u16 m_wErrorCode; // EPL error code if m_BootEvent == kEplNmtBootEventError } tEplApiEventBoot; @@ -131,33 +131,33 @@ typedef union { } tEplApiEventArg; -typedef tEplKernel(PUBLIC ROM * tEplApiCbEvent) (tEplApiEventType EventType_p, // IN: event type (enum) - tEplApiEventArg * pEventArg_p, // IN: event argument (union) - void GENERIC * pUserArg_p); +typedef tEplKernel(*tEplApiCbEvent) (tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg *pEventArg_p, // IN: event argument (union) + void *pUserArg_p); typedef struct { unsigned int m_uiSizeOfStruct; BOOL m_fAsyncOnly; // do not need to register PRes unsigned int m_uiNodeId; // local node ID - BYTE m_abMacAddress[6]; // local MAC address + u8 m_abMacAddress[6]; // local MAC address // 0x1F82: NMT_FeatureFlags_U32 - DWORD m_dwFeatureFlags; + u32 m_dwFeatureFlags; // Cycle Length (0x1006: NMT_CycleLen_U32) in [us] - DWORD m_dwCycleLen; // required for error detection + u32 m_dwCycleLen; // required for error detection // 0x1F98: NMT_CycleTiming_REC // 0x1F98.1: IsochrTxMaxPayload_U16 unsigned int m_uiIsochrTxMaxPayload; // const // 0x1F98.2: IsochrRxMaxPayload_U16 unsigned int m_uiIsochrRxMaxPayload; // const // 0x1F98.3: PResMaxLatency_U32 - DWORD m_dwPresMaxLatency; // const in [ns], only required for IdentRes + u32 m_dwPresMaxLatency; // const in [ns], only required for IdentRes // 0x1F98.4: PReqActPayloadLimit_U16 unsigned int m_uiPreqActPayloadLimit; // required for initialisation (+28 bytes) // 0x1F98.5: PResActPayloadLimit_U16 unsigned int m_uiPresActPayloadLimit; // required for initialisation of Pres frame (+28 bytes) // 0x1F98.6: ASndMaxLatency_U32 - DWORD m_dwAsndMaxLatency; // const in [ns], only required for IdentRes + u32 m_dwAsndMaxLatency; // const in [ns], only required for IdentRes // 0x1F98.7: MultiplCycleCnt_U8 unsigned int m_uiMultiplCycleCnt; // required for error detection // 0x1F98.8: AsyncMTU_U16 @@ -167,30 +167,30 @@ typedef struct { // $$$ Multiplexed Slot // 0x1C14: DLL_LossOfFrameTolerance_U32 in [ns] - DWORD m_dwLossOfFrameTolerance; + u32 m_dwLossOfFrameTolerance; // 0x1F8A: NMT_MNCycleTiming_REC // 0x1F8A.1: WaitSoCPReq_U32 in [ns] - DWORD m_dwWaitSocPreq; + u32 m_dwWaitSocPreq; // 0x1F8A.2: AsyncSlotTimeout_U32 in [ns] - DWORD m_dwAsyncSlotTimeout; + u32 m_dwAsyncSlotTimeout; - DWORD m_dwDeviceType; // NMT_DeviceType_U32 - DWORD m_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32 - DWORD m_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32 - DWORD m_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32 - DWORD m_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32 - QWORD m_qwVendorSpecificExt1; - DWORD m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 - DWORD m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 - DWORD m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device - DWORD m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device - DWORD m_dwIpAddress; - DWORD m_dwSubnetMask; - DWORD m_dwDefaultGateway; - BYTE m_sHostname[32]; - BYTE m_abVendorSpecificExt2[48]; + u32 m_dwDeviceType; // NMT_DeviceType_U32 + u32 m_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32 + u32 m_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32 + u32 m_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32 + u32 m_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32 + u64 m_qwVendorSpecificExt1; + u32 m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 + u32 m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 + u32 m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device + u32 m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device + u32 m_dwIpAddress; + u32 m_dwSubnetMask; + u32 m_dwDefaultGateway; + u8 m_sHostname[32]; + u8 m_abVendorSpecificExt2[48]; char *m_pszDevName; // NMT_ManufactDevName_VS (0x1008/0 local OD) char *m_pszHwVersion; // NMT_ManufactHwVers_VS (0x1009/0 local OD) @@ -212,62 +212,61 @@ typedef struct { // function prototypes //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiInitialize(tEplApiInitParam * pInitParam_p); +tEplKernel EplApiInitialize(tEplApiInitParam *pInitParam_p); -tEplKernel PUBLIC EplApiShutdown(void); +tEplKernel EplApiShutdown(void); -tEplKernel PUBLIC EplApiReadObject(tEplSdoComConHdl * pSdoComConHdl_p, - unsigned int uiNodeId_p, - unsigned int uiIndex_p, - unsigned int uiSubindex_p, - void *pDstData_le_p, - unsigned int *puiSize_p, - tEplSdoType SdoType_p, void *pUserArg_p); +tEplKernel EplApiReadObject(tEplSdoComConHdl *pSdoComConHdl_p, + unsigned int uiNodeId_p, + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void *pDstData_le_p, + unsigned int *puiSize_p, + tEplSdoType SdoType_p, void *pUserArg_p); -tEplKernel PUBLIC EplApiWriteObject(tEplSdoComConHdl * pSdoComConHdl_p, - unsigned int uiNodeId_p, - unsigned int uiIndex_p, - unsigned int uiSubindex_p, - void *pSrcData_le_p, - unsigned int uiSize_p, - tEplSdoType SdoType_p, void *pUserArg_p); +tEplKernel EplApiWriteObject(tEplSdoComConHdl *pSdoComConHdl_p, + unsigned int uiNodeId_p, + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void *pSrcData_le_p, + unsigned int uiSize_p, + tEplSdoType SdoType_p, void *pUserArg_p); -tEplKernel PUBLIC EplApiFreeSdoChannel(tEplSdoComConHdl SdoComConHdl_p); +tEplKernel EplApiFreeSdoChannel(tEplSdoComConHdl SdoComConHdl_p); -tEplKernel PUBLIC EplApiReadLocalObject(unsigned int uiIndex_p, - unsigned int uiSubindex_p, - void *pDstData_p, - unsigned int *puiSize_p); +tEplKernel EplApiReadLocalObject(unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void *pDstData_p, + unsigned int *puiSize_p); -tEplKernel PUBLIC EplApiWriteLocalObject(unsigned int uiIndex_p, - unsigned int uiSubindex_p, - void *pSrcData_p, - unsigned int uiSize_p); +tEplKernel EplApiWriteLocalObject(unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void *pSrcData_p, + unsigned int uiSize_p); -tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM * pParam_p); +tEplKernel EplApiCbObdAccess(tEplObdCbParam *pParam_p); -tEplKernel PUBLIC EplApiLinkObject(unsigned int uiObjIndex_p, - void *pVar_p, - unsigned int *puiVarEntries_p, - tEplObdSize * pEntrySize_p, - unsigned int uiFirstSubindex_p); +tEplKernel EplApiLinkObject(unsigned int uiObjIndex_p, + void *pVar_p, + unsigned int *puiVarEntries_p, + tEplObdSize *pEntrySize_p, + unsigned int uiFirstSubindex_p); -tEplKernel PUBLIC EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p); +tEplKernel EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p); -tEplKernel PUBLIC EplApiProcess(void); +tEplKernel EplApiProcess(void); #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) -tEplKernel PUBLIC EplApiMnTriggerStateChange(unsigned int uiNodeId_p, - tEplNmtNodeCommand NodeCommand_p); +tEplKernel EplApiMnTriggerStateChange(unsigned int uiNodeId_p, + tEplNmtNodeCommand NodeCommand_p); #endif -tEplKernel PUBLIC EplApiGetIdentResponse(unsigned int uiNodeId_p, - tEplIdentResponse ** - ppIdentResponse_p); +tEplKernel EplApiGetIdentResponse(unsigned int uiNodeId_p, + tEplIdentResponse **ppIdentResponse_p); // functions for process image will be implemented in separate file -tEplKernel PUBLIC EplApiProcessImageSetup(void); -tEplKernel PUBLIC EplApiProcessImageExchangeIn(tEplApiProcessImage * pPI_p); -tEplKernel PUBLIC EplApiProcessImageExchangeOut(tEplApiProcessImage * pPI_p); +tEplKernel EplApiProcessImageSetup(void); +tEplKernel EplApiProcessImageExchangeIn(tEplApiProcessImage *pPI_p); +tEplKernel EplApiProcessImageExchangeOut(tEplApiProcessImage *pPI_p); #endif // #ifndef _EPL_API_H_ diff --git a/drivers/staging/epl/EplAmi.h b/drivers/staging/epl/EplAmi.h index 6fa04a4f0a13..3b46ea11442b 100644 --- a/drivers/staging/epl/EplAmi.h +++ b/drivers/staging/epl/EplAmi.h @@ -69,7 +69,7 @@ 16.09.2002 -as To save code space the functions AmiSetByte and AmiGetByte - are replaced by macros. For targets which assign BYTE by + are replaced by macros. For targets which assign u8 by an 16Bit type, the definition of macros must changed to functions. @@ -86,11 +86,6 @@ #ifndef _EPLAMI_H_ #define _EPLAMI_H_ -#if ((DEV_SYSTEM & _DEV_64BIT_SUPPORT_) == 0) -// #ifdef USE_VAR64 -#error 'ERROR: development system does not support 64 bit operations!' -// #endif -#endif //--------------------------------------------------------------------------- // types @@ -104,44 +99,21 @@ extern "C" { #endif -#if (TARGET_SYSTEM == _WIN32_) -#if defined(INLINE_FUNCTION_DEF) -#undef INLINE_FUNCTION -#define INLINE_FUNCTION INLINE_FUNCTION_DEF -#define INLINE_ENABLED TRUE -#define EPL_AMI_INLINED -#include "../EplStack/amix86.c" -#endif - -#elif (TARGET_SYSTEM == _LINUX_) -#if defined(__m68k__) // it is an big endian machine -#if defined(INLINE_FUNCTION_DEF) -#undef INLINE_FUNCTION -#define INLINE_FUNCTION INLINE_FUNCTION_DEF -#define INLINE_ENABLED TRUE -#define EPL_AMI_INLINED -#include "../EplStack/amibe.c" -#endif -#endif -#endif - //--------------------------------------------------------------------------- // // write functions // // To save code space the function AmiSetByte is replaced by // an macro. -// void PUBLIC AmiSetByte (void FAR* pAddr_p, BYTE bByteVal_p); +// void AmiSetByte (void * pAddr_p, u8 bByteVal_p); -#define AmiSetByteToBe(pAddr_p, bByteVal_p) {*(BYTE FAR*)(pAddr_p) = (bByteVal_p);} -#define AmiSetByteToLe(pAddr_p, bByteVal_p) {*(BYTE FAR*)(pAddr_p) = (bByteVal_p);} +#define AmiSetByteToBe(pAddr_p, bByteVal_p) {*(u8 *)(pAddr_p) = (bByteVal_p);} +#define AmiSetByteToLe(pAddr_p, bByteVal_p) {*(u8 *)(pAddr_p) = (bByteVal_p);} -#if !defined(INLINE_ENABLED) - void PUBLIC AmiSetWordToBe(void FAR * pAddr_p, WORD wWordVal_p); - void PUBLIC AmiSetDwordToBe(void FAR * pAddr_p, DWORD dwDwordVal_p); - void PUBLIC AmiSetWordToLe(void FAR * pAddr_p, WORD wWordVal_p); - void PUBLIC AmiSetDwordToLe(void FAR * pAddr_p, DWORD dwDwordVal_p); -#endif +void AmiSetWordToBe(void *pAddr_p, u16 wWordVal_p); +void AmiSetDwordToBe(void *pAddr_p, u32 dwDwordVal_p); +void AmiSetWordToLe(void *pAddr_p, u16 wWordVal_p); +void AmiSetDwordToLe(void *pAddr_p, u32 dwDwordVal_p); //--------------------------------------------------------------------------- // @@ -149,17 +121,15 @@ extern "C" { // // To save code space the function AmiGetByte is replaced by // an macro. -// BYTE PUBLIC AmiGetByte (void FAR* pAddr_p); +// u8 AmiGetByte (void * pAddr_p); -#define AmiGetByteFromBe(pAddr_p) (*(BYTE FAR*)(pAddr_p)) -#define AmiGetByteFromLe(pAddr_p) (*(BYTE FAR*)(pAddr_p)) +#define AmiGetByteFromBe(pAddr_p) (*(u8 *)(pAddr_p)) +#define AmiGetByteFromLe(pAddr_p) (*(u8 *)(pAddr_p)) -#if !defined(INLINE_ENABLED) - - WORD PUBLIC AmiGetWordFromBe(void FAR * pAddr_p); - DWORD PUBLIC AmiGetDwordFromBe(void FAR * pAddr_p); - WORD PUBLIC AmiGetWordFromLe(void FAR * pAddr_p); - DWORD PUBLIC AmiGetDwordFromLe(void FAR * pAddr_p); +u16 AmiGetWordFromBe(void *pAddr_p); +u32 AmiGetDwordFromBe(void *pAddr_p); +u16 AmiGetWordFromLe(void *pAddr_p); +u32 AmiGetDwordFromLe(void *pAddr_p); //--------------------------------------------------------------------------- // @@ -174,8 +144,8 @@ extern "C" { // //--------------------------------------------------------------------------- - void PUBLIC AmiSetDword24ToBe(void FAR * pAddr_p, DWORD dwDwordVal_p); - void PUBLIC AmiSetDword24ToLe(void FAR * pAddr_p, DWORD dwDwordVal_p); +void AmiSetDword24ToBe(void *pAddr_p, u32 dwDwordVal_p); +void AmiSetDword24ToLe(void *pAddr_p, u32 dwDwordVal_p); //--------------------------------------------------------------------------- // @@ -185,12 +155,12 @@ extern "C" { // // Parameters: pAddr_p = pointer to source buffer // -// Return: DWORD = read value +// Return: u32 = read value // //--------------------------------------------------------------------------- - DWORD PUBLIC AmiGetDword24FromBe(void FAR * pAddr_p); - DWORD PUBLIC AmiGetDword24FromLe(void FAR * pAddr_p); +u32 AmiGetDword24FromBe(void *pAddr_p); +u32 AmiGetDword24FromLe(void *pAddr_p); //#ifdef USE_VAR64 @@ -207,8 +177,8 @@ extern "C" { // //--------------------------------------------------------------------------- - void PUBLIC AmiSetQword40ToBe(void FAR * pAddr_p, QWORD qwQwordVal_p); - void PUBLIC AmiSetQword40ToLe(void FAR * pAddr_p, QWORD qwQwordVal_p); +void AmiSetQword40ToBe(void *pAddr_p, u64 qwQwordVal_p); +void AmiSetQword40ToLe(void *pAddr_p, u64 qwQwordVal_p); //--------------------------------------------------------------------------- // @@ -218,12 +188,12 @@ extern "C" { // // Parameters: pAddr_p = pointer to source buffer // -// Return: QWORD +// Return: u64 // //--------------------------------------------------------------------------- - QWORD PUBLIC AmiGetQword40FromBe(void FAR * pAddr_p); - QWORD PUBLIC AmiGetQword40FromLe(void FAR * pAddr_p); +u64 AmiGetQword40FromBe(void *pAddr_p); +u64 AmiGetQword40FromLe(void *pAddr_p); //--------------------------------------------------------------------------- // @@ -238,8 +208,8 @@ extern "C" { // //--------------------------------------------------------------------------- - void PUBLIC AmiSetQword48ToBe(void FAR * pAddr_p, QWORD qwQwordVal_p); - void PUBLIC AmiSetQword48ToLe(void FAR * pAddr_p, QWORD qwQwordVal_p); +void AmiSetQword48ToBe(void *pAddr_p, u64 qwQwordVal_p); +void AmiSetQword48ToLe(void *pAddr_p, u64 qwQwordVal_p); //--------------------------------------------------------------------------- // @@ -249,12 +219,12 @@ extern "C" { // // Parameters: pAddr_p = pointer to source buffer // -// Return: QWORD +// Return: u64 // //--------------------------------------------------------------------------- - QWORD PUBLIC AmiGetQword48FromBe(void FAR * pAddr_p); - QWORD PUBLIC AmiGetQword48FromLe(void FAR * pAddr_p); +u64 AmiGetQword48FromBe(void *pAddr_p); +u64 AmiGetQword48FromLe(void *pAddr_p); //--------------------------------------------------------------------------- // @@ -269,8 +239,8 @@ extern "C" { // //--------------------------------------------------------------------------- - void PUBLIC AmiSetQword56ToBe(void FAR * pAddr_p, QWORD qwQwordVal_p); - void PUBLIC AmiSetQword56ToLe(void FAR * pAddr_p, QWORD qwQwordVal_p); +void AmiSetQword56ToBe(void *pAddr_p, u64 qwQwordVal_p); +void AmiSetQword56ToLe(void *pAddr_p, u64 qwQwordVal_p); //--------------------------------------------------------------------------- // @@ -280,12 +250,12 @@ extern "C" { // // Parameters: pAddr_p = pointer to source buffer // -// Return: QWORD +// Return: u64 // //--------------------------------------------------------------------------- - QWORD PUBLIC AmiGetQword56FromBe(void FAR * pAddr_p); - QWORD PUBLIC AmiGetQword56FromLe(void FAR * pAddr_p); +u64 AmiGetQword56FromBe(void *pAddr_p); +u64 AmiGetQword56FromLe(void *pAddr_p); //--------------------------------------------------------------------------- // @@ -300,8 +270,8 @@ extern "C" { // //--------------------------------------------------------------------------- - void PUBLIC AmiSetQword64ToBe(void FAR * pAddr_p, QWORD qwQwordVal_p); - void PUBLIC AmiSetQword64ToLe(void FAR * pAddr_p, QWORD qwQwordVal_p); +void AmiSetQword64ToBe(void *pAddr_p, u64 qwQwordVal_p); +void AmiSetQword64ToLe(void *pAddr_p, u64 qwQwordVal_p); //--------------------------------------------------------------------------- // @@ -315,8 +285,8 @@ extern "C" { // //--------------------------------------------------------------------------- - QWORD PUBLIC AmiGetQword64FromBe(void FAR * pAddr_p); - QWORD PUBLIC AmiGetQword64FromLe(void FAR * pAddr_p); +u64 AmiGetQword64FromBe(void *pAddr_p); +u64 AmiGetQword64FromLe(void *pAddr_p); //--------------------------------------------------------------------------- // @@ -330,9 +300,7 @@ extern "C" { // Return: void // //--------------------------------------------------------------------------- - - void PUBLIC AmiSetTimeOfDay(void FAR * pAddr_p, - tTimeOfDay FAR * pTimeOfDay_p); +void AmiSetTimeOfDay(void *pAddr_p, tTimeOfDay *pTimeOfDay_p); //--------------------------------------------------------------------------- // @@ -346,14 +314,7 @@ extern "C" { // Return: void // //--------------------------------------------------------------------------- - - void PUBLIC AmiGetTimeOfDay(void FAR * pAddr_p, - tTimeOfDay FAR * pTimeOfDay_p); - -#endif - -#undef INLINE_ENABLED // disable actual inlining of functions -#define EPL_AMI_INCLUDED +void AmiGetTimeOfDay(void *pAddr_p, tTimeOfDay *pTimeOfDay_p); #ifdef __cplusplus } diff --git a/drivers/staging/epl/EplApiGeneric.c b/drivers/staging/epl/EplApiGeneric.c index ae19e34cd7b3..c4419569183f 100644 --- a/drivers/staging/epl/EplApiGeneric.c +++ b/drivers/staging/epl/EplApiGeneric.c @@ -162,44 +162,41 @@ static tEplApiInstance EplApiInstance_g; //--------------------------------------------------------------------------- // NMT state change event callback function -static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange - NmtStateChange_p); +static tEplKernel EplApiCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p); // update DLL configuration from OD -static tEplKernel PUBLIC EplApiUpdateDllConfig(BOOL fUpdateIdentity_p); +static tEplKernel EplApiUpdateDllConfig(BOOL fUpdateIdentity_p); // update OD from init param -static tEplKernel PUBLIC EplApiUpdateObd(void); +static tEplKernel EplApiUpdateObd(void); // process events from user event queue -static tEplKernel PUBLIC EplApiProcessEvent(tEplEvent * pEplEvent_p); +static tEplKernel EplApiProcessEvent(tEplEvent *pEplEvent_p); #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) // callback function of SDO module -static tEplKernel PUBLIC EplApiCbSdoCon(tEplSdoComFinished * pSdoComFinished_p); +static tEplKernel EplApiCbSdoCon(tEplSdoComFinished *pSdoComFinished_p); #endif #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) // callback functions of NmtMnu module -static tEplKernel PUBLIC EplApiCbNodeEvent(unsigned int uiNodeId_p, - tEplNmtNodeEvent NodeEvent_p, - tEplNmtState NmtState_p, - WORD wErrorCode_p, - BOOL fMandatory_p); +static tEplKernel EplApiCbNodeEvent(unsigned int uiNodeId_p, + tEplNmtNodeEvent NodeEvent_p, + tEplNmtState NmtState_p, + u16 wErrorCode_p, BOOL fMandatory_p); -static tEplKernel PUBLIC EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p, - tEplNmtState NmtState_p, - WORD wErrorCode_p); +static tEplKernel EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p, + tEplNmtState NmtState_p, + u16 wErrorCode_p); #endif #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) // callback function of Ledu module -static tEplKernel PUBLIC EplApiCbLedStateChange(tEplLedType LedType_p, - BOOL fOn_p); +static tEplKernel EplApiCbLedStateChange(tEplLedType LedType_p, BOOL fOn_p); #endif // OD initialization function (implemented in Objdict.c) -tEplKernel PUBLIC EplObdInitRam(tEplObdInitParam MEM * pInitParam_p); +tEplKernel EplObdInitRam(tEplObdInitParam *pInitParam_p); //=========================================================================// // // @@ -226,7 +223,7 @@ tEplKernel PUBLIC EplObdInitRam(tEplObdInitParam MEM * pInitParam_p); // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiInitialize(tEplApiInitParam * pInitParam_p) +tEplKernel EplApiInitialize(tEplApiInitParam *pInitParam_p) { tEplKernel Ret = kEplSuccessful; tEplObdInitParam ObdInitParam; @@ -415,7 +412,7 @@ tEplKernel PUBLIC EplApiInitialize(tEplApiInitParam * pInitParam_p) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiShutdown(void) +tEplKernel EplApiShutdown(void) { tEplKernel Ret = kEplSuccessful; @@ -523,7 +520,7 @@ tEplKernel PUBLIC EplApiShutdown(void) // State: //---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p) +tEplKernel EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p) { tEplKernel Ret = kEplSuccessful; @@ -553,15 +550,15 @@ tEplKernel PUBLIC EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p) // State: //---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiLinkObject(unsigned int uiObjIndex_p, - void *pVar_p, - unsigned int *puiVarEntries_p, - tEplObdSize * pEntrySize_p, - unsigned int uiFirstSubindex_p) +tEplKernel EplApiLinkObject(unsigned int uiObjIndex_p, + void *pVar_p, + unsigned int *puiVarEntries_p, + tEplObdSize *pEntrySize_p, + unsigned int uiFirstSubindex_p) { - BYTE bVarEntries; - BYTE bIndexEntries; - BYTE MEM *pbData; + u8 bVarEntries; + u8 bIndexEntries; + u8 *pbData; unsigned int uiSubindex; tEplVarParam VarParam; tEplObdSize EntrySize; @@ -577,8 +574,8 @@ tEplKernel PUBLIC EplApiLinkObject(unsigned int uiObjIndex_p, goto Exit; } - pbData = (BYTE MEM *) pVar_p; - bVarEntries = (BYTE) * puiVarEntries_p; + pbData = (u8 *)pVar_p; + bVarEntries = (u8) * puiVarEntries_p; UsedSize = 0; // init VarParam structure with default values @@ -591,7 +588,7 @@ tEplKernel PUBLIC EplApiLinkObject(unsigned int uiObjIndex_p, EntrySize = (tEplObdSize) sizeof(bIndexEntries); RetCode = EplObdReadEntry(uiObjIndex_p, 0x00, - (void GENERIC *)&bIndexEntries, + (void *)&bIndexEntries, &EntrySize); if ((RetCode != kEplSuccessful) || (bIndexEntries == 0x00)) { @@ -610,7 +607,7 @@ tEplKernel PUBLIC EplApiLinkObject(unsigned int uiObjIndex_p, // object actually has. if ((bIndexEntries > (bVarEntries + uiFirstSubindex_p - 1)) && (bVarEntries != 0x00)) { - bIndexEntries = (BYTE) (bVarEntries + uiFirstSubindex_p - 1); + bIndexEntries = (u8) (bVarEntries + uiFirstSubindex_p - 1); } // map entries for (uiSubindex = uiFirstSubindex_p; uiSubindex <= bIndexEntries; @@ -677,13 +674,13 @@ tEplKernel PUBLIC EplApiLinkObject(unsigned int uiObjIndex_p, // // ---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiReadObject(tEplSdoComConHdl * pSdoComConHdl_p, - unsigned int uiNodeId_p, - unsigned int uiIndex_p, - unsigned int uiSubindex_p, - void *pDstData_le_p, - unsigned int *puiSize_p, - tEplSdoType SdoType_p, void *pUserArg_p) +tEplKernel EplApiReadObject(tEplSdoComConHdl *pSdoComConHdl_p, + unsigned int uiNodeId_p, + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void *pDstData_le_p, + unsigned int *puiSize_p, + tEplSdoType SdoType_p, void *pUserArg_p) { tEplKernel Ret = kEplSuccessful; @@ -765,13 +762,13 @@ tEplKernel PUBLIC EplApiReadObject(tEplSdoComConHdl * pSdoComConHdl_p, // // ---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiWriteObject(tEplSdoComConHdl * pSdoComConHdl_p, - unsigned int uiNodeId_p, - unsigned int uiIndex_p, - unsigned int uiSubindex_p, - void *pSrcData_le_p, - unsigned int uiSize_p, - tEplSdoType SdoType_p, void *pUserArg_p) +tEplKernel EplApiWriteObject(tEplSdoComConHdl *pSdoComConHdl_p, + unsigned int uiNodeId_p, + unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void *pSrcData_le_p, + unsigned int uiSize_p, + tEplSdoType SdoType_p, void *pUserArg_p) { tEplKernel Ret = kEplSuccessful; @@ -850,7 +847,7 @@ tEplKernel PUBLIC EplApiWriteObject(tEplSdoComConHdl * pSdoComConHdl_p, // // ---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiFreeSdoChannel(tEplSdoComConHdl SdoComConHdl_p) +tEplKernel EplApiFreeSdoChannel(tEplSdoComConHdl SdoComConHdl_p) { tEplKernel Ret = kEplSuccessful; @@ -881,10 +878,9 @@ tEplKernel PUBLIC EplApiFreeSdoChannel(tEplSdoComConHdl SdoComConHdl_p) // // ---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiReadLocalObject(unsigned int uiIndex_p, - unsigned int uiSubindex_p, - void *pDstData_p, - unsigned int *puiSize_p) +tEplKernel EplApiReadLocalObject(unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void *pDstData_p, unsigned int *puiSize_p) { tEplKernel Ret = kEplSuccessful; tEplObdSize ObdSize; @@ -911,10 +907,10 @@ tEplKernel PUBLIC EplApiReadLocalObject(unsigned int uiIndex_p, // // ---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiWriteLocalObject(unsigned int uiIndex_p, - unsigned int uiSubindex_p, - void *pSrcData_p, - unsigned int uiSize_p) +tEplKernel EplApiWriteLocalObject(unsigned int uiIndex_p, + unsigned int uiSubindex_p, + void *pSrcData_p, + unsigned int uiSize_p) { tEplKernel Ret = kEplSuccessful; @@ -939,8 +935,8 @@ tEplKernel PUBLIC EplApiWriteLocalObject(unsigned int uiIndex_p, // // ---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiMnTriggerStateChange(unsigned int uiNodeId_p, - tEplNmtNodeCommand NodeCommand_p) +tEplKernel EplApiMnTriggerStateChange(unsigned int uiNodeId_p, + tEplNmtNodeCommand NodeCommand_p) { tEplKernel Ret = kEplSuccessful; @@ -966,7 +962,7 @@ tEplKernel PUBLIC EplApiMnTriggerStateChange(unsigned int uiNodeId_p, // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM * pParam_p) +tEplKernel EplApiCbObdAccess(tEplObdCbParam *pParam_p) { tEplKernel Ret = kEplSuccessful; @@ -1001,8 +997,8 @@ tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM * pParam_p) { if ((pParam_p->m_ObdEvent == kEplObdEvPostWrite) && (pParam_p->m_uiSubIndex == 3) - && (*((DWORD *) pParam_p->m_pArg) != 0)) { - DWORD dwVerifyConfInvalid = 0; + && (*((u32 *) pParam_p->m_pArg) != 0)) { + u32 dwVerifyConfInvalid = 0; // set CFM_VerifyConfiguration_REC.VerifyConfInvalid_U32 to 0 Ret = EplObdWriteEntry(0x1020, 4, @@ -1016,9 +1012,9 @@ tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM * pParam_p) case 0x1F9E: // NMT_ResetCmd_U8 { if (pParam_p->m_ObdEvent == kEplObdEvPreWrite) { - BYTE bNmtCommand; + u8 bNmtCommand; - bNmtCommand = *((BYTE *) pParam_p->m_pArg); + bNmtCommand = *((u8 *) pParam_p->m_pArg); // check value range switch ((tEplNmtCommand) bNmtCommand) { case kEplNmtCmdResetNode: @@ -1036,9 +1032,9 @@ tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM * pParam_p) break; } } else if (pParam_p->m_ObdEvent == kEplObdEvPostWrite) { - BYTE bNmtCommand; + u8 bNmtCommand; - bNmtCommand = *((BYTE *) pParam_p->m_pArg); + bNmtCommand = *((u8 *) pParam_p->m_pArg); // check value range switch ((tEplNmtCommand) bNmtCommand) { case kEplNmtCmdResetNode: @@ -1115,7 +1111,7 @@ tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM * pParam_p) // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplApiProcessEvent(tEplEvent * pEplEvent_p) +static tEplKernel EplApiProcessEvent(tEplEvent *pEplEvent_p) { tEplKernel Ret; tEplEventError *pEventError; @@ -1188,15 +1184,14 @@ static tEplKernel PUBLIC EplApiProcessEvent(tEplEvent * pEplEvent_p) // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange - NmtStateChange_p) +static tEplKernel EplApiCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p) { tEplKernel Ret = kEplSuccessful; - BYTE bNmtState; + u8 bNmtState; tEplApiEventArg EventArg; // save NMT state in OD - bNmtState = (BYTE) NmtStateChange_p.m_NewNmtState; + bNmtState = (u8) NmtStateChange_p.m_NewNmtState; Ret = EplObdWriteEntry(0x1F8C, 0, &bNmtState, 1); if (Ret != kEplSuccessful) { goto Exit; @@ -1275,7 +1270,7 @@ static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange case kEplNmtCsNotActive: { // indicate completion of reset in NMT_ResetCmd_U8 - bNmtState = (BYTE) kEplNmtCmdInvalidService; + bNmtState = (u8) kEplNmtCmdInvalidService; Ret = EplObdWriteEntry(0x1F9E, 0, &bNmtState, 1); if (Ret != kEplSuccessful) { goto Exit; @@ -1411,14 +1406,14 @@ static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplApiUpdateDllConfig(BOOL fUpdateIdentity_p) +static tEplKernel EplApiUpdateDllConfig(BOOL fUpdateIdentity_p) { tEplKernel Ret = kEplSuccessful; tEplDllConfigParam DllConfigParam; tEplDllIdentParam DllIdentParam; tEplObdSize ObdSize; - WORD wTemp; - BYTE bTemp; + u16 wTemp; + u8 bTemp; // configure Dll EPL_MEMSET(&DllConfigParam, 0, sizeof(DllConfigParam)); @@ -1634,11 +1629,11 @@ static tEplKernel PUBLIC EplApiUpdateDllConfig(BOOL fUpdateIdentity_p) // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplApiUpdateObd(void) +static tEplKernel EplApiUpdateObd(void) { tEplKernel Ret = kEplSuccessful; - WORD wTemp; - BYTE bTemp; + u16 wTemp; + u8 bTemp; // set node id in OD Ret = EplObdSetNodeId(EplApiInstance_g.m_InitParam.m_uiNodeId, // node id @@ -1680,14 +1675,14 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) } */ } - wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiIsochrTxMaxPayload; + wTemp = (u16) EplApiInstance_g.m_InitParam.m_uiIsochrTxMaxPayload; Ret = EplObdWriteEntry(0x1F98, 1, &wTemp, 2); /* if(Ret != kEplSuccessful) { goto Exit; }*/ - wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiIsochrRxMaxPayload; + wTemp = (u16) EplApiInstance_g.m_InitParam.m_uiIsochrRxMaxPayload; Ret = EplObdWriteEntry(0x1F98, 2, &wTemp, 2); /* if(Ret != kEplSuccessful) { @@ -1706,7 +1701,7 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) if (EplApiInstance_g.m_InitParam.m_uiPreqActPayloadLimit <= EPL_C_DLL_ISOCHR_MAX_PAYL) { wTemp = - (WORD) EplApiInstance_g.m_InitParam.m_uiPreqActPayloadLimit; + (u16) EplApiInstance_g.m_InitParam.m_uiPreqActPayloadLimit; Ret = EplObdWriteEntry(0x1F98, 4, &wTemp, 2); /* if(Ret != kEplSuccessful) { @@ -1717,7 +1712,7 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) if (EplApiInstance_g.m_InitParam.m_uiPresActPayloadLimit <= EPL_C_DLL_ISOCHR_MAX_PAYL) { wTemp = - (WORD) EplApiInstance_g.m_InitParam.m_uiPresActPayloadLimit; + (u16) EplApiInstance_g.m_InitParam.m_uiPresActPayloadLimit; Ret = EplObdWriteEntry(0x1F98, 5, &wTemp, 2); /* if(Ret != kEplSuccessful) { @@ -1735,7 +1730,7 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) }*/ if (EplApiInstance_g.m_InitParam.m_uiMultiplCycleCnt <= 0xFF) { - bTemp = (BYTE) EplApiInstance_g.m_InitParam.m_uiMultiplCycleCnt; + bTemp = (u8) EplApiInstance_g.m_InitParam.m_uiMultiplCycleCnt; Ret = EplObdWriteEntry(0x1F98, 7, &bTemp, 1); /* if(Ret != kEplSuccessful) { @@ -1745,7 +1740,7 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) if (EplApiInstance_g.m_InitParam.m_uiAsyncMtu <= EPL_C_DLL_MAX_ASYNC_MTU) { - wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiAsyncMtu; + wTemp = (u16) EplApiInstance_g.m_InitParam.m_uiAsyncMtu; Ret = EplObdWriteEntry(0x1F98, 8, &wTemp, 2); /* if(Ret != kEplSuccessful) { @@ -1754,7 +1749,7 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) } if (EplApiInstance_g.m_InitParam.m_uiPrescaler <= 1000) { - wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiPrescaler; + wTemp = (u16) EplApiInstance_g.m_InitParam.m_uiPrescaler; Ret = EplObdWriteEntry(0x1F98, 9, &wTemp, 2); // ignore return code Ret = kEplSuccessful; @@ -1844,7 +1839,7 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) // write Device Name (0x1008) Ret = EplObdWriteEntry(0x1008, 0, - (void GENERIC *)EplApiInstance_g. + (void *)EplApiInstance_g. m_InitParam.m_pszDevName, (tEplObdSize) strlen(EplApiInstance_g. m_InitParam. @@ -1859,7 +1854,7 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) // write Hardware version (0x1009) Ret = EplObdWriteEntry(0x1009, 0, - (void GENERIC *)EplApiInstance_g. + (void *)EplApiInstance_g. m_InitParam.m_pszHwVersion, (tEplObdSize) strlen(EplApiInstance_g. m_InitParam. @@ -1874,7 +1869,7 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) // write Software version (0x100A) Ret = EplObdWriteEntry(0x100A, 0, - (void GENERIC *)EplApiInstance_g. + (void *)EplApiInstance_g. m_InitParam.m_pszSwVersion, (tEplObdSize) strlen(EplApiInstance_g. m_InitParam. @@ -1905,7 +1900,7 @@ static tEplKernel PUBLIC EplApiUpdateObd(void) //--------------------------------------------------------------------------- #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) -static tEplKernel PUBLIC EplApiCbSdoCon(tEplSdoComFinished * pSdoComFinished_p) +static tEplKernel EplApiCbSdoCon(tEplSdoComFinished *pSdoComFinished_p) { tEplKernel Ret; tEplApiEventArg EventArg; @@ -1946,10 +1941,10 @@ static tEplKernel PUBLIC EplApiCbSdoCon(tEplSdoComFinished * pSdoComFinished_p) // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplApiCbNodeEvent(unsigned int uiNodeId_p, - tEplNmtNodeEvent NodeEvent_p, - tEplNmtState NmtState_p, - WORD wErrorCode_p, BOOL fMandatory_p) +static tEplKernel EplApiCbNodeEvent(unsigned int uiNodeId_p, + tEplNmtNodeEvent NodeEvent_p, + tEplNmtState NmtState_p, + u16 wErrorCode_p, BOOL fMandatory_p) { tEplKernel Ret; tEplApiEventArg EventArg; @@ -1990,9 +1985,9 @@ static tEplKernel PUBLIC EplApiCbNodeEvent(unsigned int uiNodeId_p, // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p, - tEplNmtState NmtState_p, - WORD wErrorCode_p) +static tEplKernel EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p, + tEplNmtState NmtState_p, + u16 wErrorCode_p) { tEplKernel Ret; tEplApiEventArg EventArg; @@ -2033,8 +2028,7 @@ static tEplKernel PUBLIC EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p, // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplApiCbLedStateChange(tEplLedType LedType_p, - BOOL fOn_p) +static tEplKernel EplApiCbLedStateChange(tEplLedType LedType_p, BOOL fOn_p) { tEplKernel Ret; tEplApiEventArg EventArg; diff --git a/drivers/staging/epl/EplApiLinuxKernel.c b/drivers/staging/epl/EplApiLinuxKernel.c index 05ca0628d6ae..cb3e275e3aad 100644 --- a/drivers/staging/epl/EplApiLinuxKernel.c +++ b/drivers/staging/epl/EplApiLinuxKernel.c @@ -72,9 +72,6 @@ // kernel modul and driver -//#include -//#include - #include #include #include @@ -92,25 +89,11 @@ #include #include -#ifdef CONFIG_DEVFS_FS -#include -#include -#endif - #include "Epl.h" #include "EplApiLinux.h" //#include "kernel/EplPdokCal.h" #include "proc_fs.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - // remove ("make invisible") obsolete symbols for kernel versions 2.6 - // and higher -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#define EXPORT_NO_SYMBOLS -#else -#error "This driver needs a 2.6.x kernel or higher" -#endif /***************************************************************************/ /* */ @@ -139,7 +122,7 @@ MODULE_DESCRIPTION("EPL API driver"); // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #else #define TGT_DBG_SIGNAL_TRACE_POINT(p) @@ -159,19 +142,10 @@ void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); // Global variables //--------------------------------------------------------------------------- -#ifdef CONFIG_DEVFS_FS - - // driver major number -static int nDrvMajorNumber_g; - -#else - // device number (major and minor) static dev_t nDevNum_g; static struct cdev *pEpl_cdev_g; -#endif - static volatile unsigned int uiEplState_g = EPL_STATE_NOTOPEN; static struct semaphore SemaphoreCbEvent_g; // semaphore for EplLinCbEvent @@ -204,11 +178,11 @@ typedef struct { // Prototypes of internal functions //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) - tEplApiEventArg * pEventArg_p, // IN: event argument (union) - void GENERIC * pUserArg_p); +tEplKernel EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg *pEventArg_p, // IN: event argument (union) + void *pUserArg_p); -tEplKernel PUBLIC EplLinCbSync(void); +tEplKernel EplLinCbSync(void); static int __init EplLinInit(void); static void __exit EplLinExit(void); @@ -226,8 +200,6 @@ static int EplLinIoctl(struct inode *pDeviceFile_p, struct file *pInstance_p, // Kernel Module specific Data Structures //--------------------------------------------------------------------------- -EXPORT_NO_SYMBOLS; - module_init(EplLinInit); module_exit(EplLinExit); @@ -259,9 +231,6 @@ static int __init EplLinInit(void) tEplKernel EplRet; int iErr; int iRet; -#ifdef CONFIG_DEVFS_FS - int nMinorNumber; -#endif TRACE0("EPL: + EplLinInit...\n"); TRACE2("EPL: Driver build: %s / %s\n", __DATE__, __TIME__); @@ -275,44 +244,6 @@ static int __init EplLinInit(void) init_waitqueue_head(&WaitQueueProcess_g); init_waitqueue_head(&WaitQueueRelease_g); -#ifdef CONFIG_DEVFS_FS - - // register character device handler - TRACE2("EPL: Installing Driver '%s', Version %s...\n", - EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION); - TRACE0("EPL: (using dynamic major number assignment)\n"); - nDrvMajorNumber_g = - register_chrdev(0, EPLLIN_DRV_NAME, &EplLinFileOps_g); - if (nDrvMajorNumber_g != 0) { - TRACE2 - ("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n", - EPLLIN_DRV_NAME, nDrvMajorNumber_g); - } else { - TRACE1 - ("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n", - EPLLIN_DRV_NAME); - iRet = -EIO; - goto Exit; - } - - // create device node in DEVFS - nMinorNumber = 0; - TRACE1("EPL: Creating device node '/dev/%s'...\n", EPLLIN_DEV_NAME); - iErr = - devfs_mk_cdev(MKDEV(nDrvMajorNumber_g, nMinorNumber), - S_IFCHR | S_IRUGO | S_IWUGO, EPLLIN_DEV_NAME); - if (iErr == 0) { - TRACE1("EPL: Device node '/dev/%s' created successful.\n", - EPLLIN_DEV_NAME); - } else { - TRACE1("EPL: ERROR: unable to create device node '/dev/%s'\n", - EPLLIN_DEV_NAME); - iRet = -EIO; - goto Exit; - } - -#else - // register character device handler // only one Minor required TRACE2("EPL: Installing Driver '%s', Version %s...\n", @@ -341,7 +272,6 @@ static int __init EplLinInit(void) iRet = -EIO; goto Exit; } -#endif // create device node in PROCFS EplRet = EplLinProcInit(); @@ -377,25 +307,12 @@ static void __exit EplLinExit(void) TRACE0("EPL: + EplLinExit...\n"); -#ifdef CONFIG_DEVFS_FS - - // remove device node from DEVFS - devfs_remove(EPLLIN_DEV_NAME); - TRACE1("EPL: Device node '/dev/%s' removed.\n", EPLLIN_DEV_NAME); - - // unregister character device handler - unregister_chrdev(nDrvMajorNumber_g, EPLLIN_DRV_NAME); - -#else - // remove cdev structure cdev_del(pEpl_cdev_g); // unregister character device handler unregister_chrdev_region(nDevNum_g, 1); -#endif - TRACE1("EPL: Driver '%s' removed.\n", EPLLIN_DRV_NAME); TRACE0("EPL: - EplLinExit\n"); @@ -416,8 +333,6 @@ static int EplLinOpen(struct inode *pDeviceFile_p, // information about the devi TRACE0("EPL: + EplLinOpen...\n"); - MOD_INC_USE_COUNT; - if (uiEplState_g != EPL_STATE_NOTOPEN) { // stack already initialized iRet = -EALREADY; } else { @@ -490,8 +405,6 @@ static int EplLinRelease(struct inode *pDeviceFile_p, // information about the d uiEplState_g = EPL_STATE_NOTOPEN; iRet = 0; - MOD_DEC_USE_COUNT; - TRACE1("EPL: - EplLinRelease (iRet=%d)\n", iRet); return (iRet); @@ -1158,9 +1071,9 @@ static int EplLinIoctl(struct inode *pDeviceFile_p, // information about the dev // // //=========================================================================// -tEplKernel PUBLIC EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) - tEplApiEventArg * pEventArg_p, // IN: event argument (union) - void GENERIC * pUserArg_p) +tEplKernel EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg *pEventArg_p, // IN: event argument (union) + void *pUserArg_p) { tEplKernel EplRet = kEplSuccessful; int iErr; @@ -1224,7 +1137,7 @@ tEplKernel PUBLIC EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type return EplRet; } -tEplKernel PUBLIC EplLinCbSync(void) +tEplKernel EplLinCbSync(void) { tEplKernel EplRet = kEplSuccessful; int iErr; diff --git a/drivers/staging/epl/EplApiProcessImage.c b/drivers/staging/epl/EplApiProcessImage.c index 2b2fdf229a75..7d55086a8e4e 100644 --- a/drivers/staging/epl/EplApiProcessImage.c +++ b/drivers/staging/epl/EplApiProcessImage.c @@ -69,11 +69,8 @@ ****************************************************************************/ #include "Epl.h" -//#include "kernel/EplPdokCal.h" -#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) -#include -#endif +#include /***************************************************************************/ /* */ @@ -129,10 +126,10 @@ #if ((EPL_API_PROCESS_IMAGE_SIZE_IN > 0) || (EPL_API_PROCESS_IMAGE_SIZE_OUT > 0)) typedef struct { #if EPL_API_PROCESS_IMAGE_SIZE_IN > 0 - BYTE m_abProcessImageInput[EPL_API_PROCESS_IMAGE_SIZE_IN]; + u8 m_abProcessImageInput[EPL_API_PROCESS_IMAGE_SIZE_IN]; #endif #if EPL_API_PROCESS_IMAGE_SIZE_OUT > 0 - BYTE m_abProcessImageOutput[EPL_API_PROCESS_IMAGE_SIZE_OUT]; + u8 m_abProcessImageOutput[EPL_API_PROCESS_IMAGE_SIZE_OUT]; #endif } tEplApiProcessImageInstance; @@ -169,7 +166,7 @@ static tEplApiProcessImageInstance EplApiProcessImageInstance_g; // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiProcessImageSetup(void) +tEplKernel EplApiProcessImageSetup(void) { tEplKernel Ret = kEplSuccessful; #if ((EPL_API_PROCESS_IMAGE_SIZE_IN > 0) || (EPL_API_PROCESS_IMAGE_SIZE_OUT > 0)) @@ -280,24 +277,16 @@ tEplKernel PUBLIC EplApiProcessImageSetup(void) // State: //---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiProcessImageExchangeIn(tEplApiProcessImage * pPI_p) +tEplKernel EplApiProcessImageExchangeIn(tEplApiProcessImage *pPI_p) { tEplKernel Ret = kEplSuccessful; #if EPL_API_PROCESS_IMAGE_SIZE_IN > 0 -#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) copy_to_user(pPI_p->m_pImage, EplApiProcessImageInstance_g.m_abProcessImageInput, min(pPI_p->m_uiSize, sizeof(EplApiProcessImageInstance_g. m_abProcessImageInput))); -#else - EPL_MEMCPY(pPI_p->m_pImage, - EplApiProcessImageInstance_g.m_abProcessImageInput, - min(pPI_p->m_uiSize, - sizeof(EplApiProcessImageInstance_g. - m_abProcessImageInput))); -#endif #endif return Ret; @@ -315,24 +304,16 @@ tEplKernel PUBLIC EplApiProcessImageExchangeIn(tEplApiProcessImage * pPI_p) // State: //---------------------------------------------------------------------------- -tEplKernel PUBLIC EplApiProcessImageExchangeOut(tEplApiProcessImage * pPI_p) +tEplKernel EplApiProcessImageExchangeOut(tEplApiProcessImage *pPI_p) { tEplKernel Ret = kEplSuccessful; #if EPL_API_PROCESS_IMAGE_SIZE_OUT > 0 -#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) copy_from_user(EplApiProcessImageInstance_g.m_abProcessImageOutput, pPI_p->m_pImage, min(pPI_p->m_uiSize, sizeof(EplApiProcessImageInstance_g. m_abProcessImageOutput))); -#else - EPL_MEMCPY(EplApiProcessImageInstance_g.m_abProcessImageOutput, - pPI_p->m_pImage, - min(pPI_p->m_uiSize, - sizeof(EplApiProcessImageInstance_g. - m_abProcessImageOutput))); -#endif #endif return Ret; diff --git a/drivers/staging/epl/EplDll.h b/drivers/staging/epl/EplDll.h index 36657f2daf8b..b960199bd0e1 100644 --- a/drivers/staging/epl/EplDll.h +++ b/drivers/staging/epl/EplDll.h @@ -135,22 +135,22 @@ typedef struct { unsigned int m_uiNodeId; // local node ID // 0x1F82: NMT_FeatureFlags_U32 - DWORD m_dwFeatureFlags; + u32 m_dwFeatureFlags; // Cycle Length (0x1006: NMT_CycleLen_U32) in [us] - DWORD m_dwCycleLen; // required for error detection + u32 m_dwCycleLen; // required for error detection // 0x1F98: NMT_CycleTiming_REC // 0x1F98.1: IsochrTxMaxPayload_U16 unsigned int m_uiIsochrTxMaxPayload; // const // 0x1F98.2: IsochrRxMaxPayload_U16 unsigned int m_uiIsochrRxMaxPayload; // const // 0x1F98.3: PResMaxLatency_U32 - DWORD m_dwPresMaxLatency; // const in [ns], only required for IdentRes + u32 m_dwPresMaxLatency; // const in [ns], only required for IdentRes // 0x1F98.4: PReqActPayloadLimit_U16 unsigned int m_uiPreqActPayloadLimit; // required for initialisation (+24 bytes) // 0x1F98.5: PResActPayloadLimit_U16 unsigned int m_uiPresActPayloadLimit; // required for initialisation of Pres frame (+24 bytes) // 0x1F98.6: ASndMaxLatency_U32 - DWORD m_dwAsndMaxLatency; // const in [ns], only required for IdentRes + u32 m_dwAsndMaxLatency; // const in [ns], only required for IdentRes // 0x1F98.7: MultiplCycleCnt_U8 unsigned int m_uiMultiplCycleCnt; // required for error detection // 0x1F98.8: AsyncMTU_U16 @@ -159,42 +159,42 @@ typedef struct { // $$$ Multiplexed Slot // 0x1C14: DLL_LossOfFrameTolerance_U32 in [ns] - DWORD m_dwLossOfFrameTolerance; + u32 m_dwLossOfFrameTolerance; // 0x1F8A: NMT_MNCycleTiming_REC // 0x1F8A.1: WaitSoCPReq_U32 in [ns] - DWORD m_dwWaitSocPreq; + u32 m_dwWaitSocPreq; // 0x1F8A.2: AsyncSlotTimeout_U32 in [ns] - DWORD m_dwAsyncSlotTimeout; + u32 m_dwAsyncSlotTimeout; } tEplDllConfigParam; typedef struct { unsigned int m_uiSizeOfStruct; - DWORD m_dwDeviceType; // NMT_DeviceType_U32 - DWORD m_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32 - DWORD m_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32 - DWORD m_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32 - DWORD m_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32 - QWORD m_qwVendorSpecificExt1; - DWORD m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 - DWORD m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 - DWORD m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device - DWORD m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device - DWORD m_dwIpAddress; - DWORD m_dwSubnetMask; - DWORD m_dwDefaultGateway; - BYTE m_sHostname[32]; - BYTE m_abVendorSpecificExt2[48]; + u32 m_dwDeviceType; // NMT_DeviceType_U32 + u32 m_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32 + u32 m_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32 + u32 m_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32 + u32 m_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32 + u64 m_qwVendorSpecificExt1; + u32 m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 + u32 m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 + u32 m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device + u32 m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device + u32 m_dwIpAddress; + u32 m_dwSubnetMask; + u32 m_dwDefaultGateway; + u8 m_sHostname[32]; + u8 m_abVendorSpecificExt2[48]; } tEplDllIdentParam; typedef struct { unsigned int m_uiNodeId; - WORD m_wPreqPayloadLimit; // object 0x1F8B: NMT_MNPReqPayloadLimitList_AU16 - WORD m_wPresPayloadLimit; // object 0x1F8D: NMT_PResPayloadLimitList_AU16 - DWORD m_dwPresTimeout; // object 0x1F92: NMT_MNCNPResTimeout_AU32 + u16 m_wPreqPayloadLimit; // object 0x1F8B: NMT_MNPReqPayloadLimitList_AU16 + u16 m_wPresPayloadLimit; // object 0x1F8D: NMT_PResPayloadLimitList_AU16 + u32 m_dwPresTimeout; // object 0x1F92: NMT_MNCNPResTimeout_AU32 } tEplDllNodeInfo; diff --git a/drivers/staging/epl/EplDllCal.h b/drivers/staging/epl/EplDllCal.h index 24460087e987..70b27b1b6768 100644 --- a/drivers/staging/epl/EplDllCal.h +++ b/drivers/staging/epl/EplDllCal.h @@ -112,7 +112,7 @@ typedef struct { typedef struct { tEplDllReqServiceId m_Service; unsigned int m_uiNodeId; - BYTE m_bSoaFlag1; + u8 m_bSoaFlag1; } tEplDllCalIssueRequest; diff --git a/drivers/staging/epl/EplDllk.c b/drivers/staging/epl/EplDllk.c index 9e22641055c6..25d2c34325db 100644 --- a/drivers/staging/epl/EplDllk.c +++ b/drivers/staging/epl/EplDllk.c @@ -121,8 +121,8 @@ // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); -void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); +void TgtDbgPostTraceValue(u32 dwTraceValue_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) #else @@ -195,12 +195,12 @@ typedef enum { } tEplDllState; typedef struct { - BYTE m_be_abSrcMac[6]; + u8 m_be_abSrcMac[6]; tEdrvTxBuffer *m_pTxBuffer; // Buffers for Tx-Frames unsigned int m_uiMaxTxFrames; - BYTE m_bFlag1; // Flag 1 with EN, EC for PRes, StatusRes - BYTE m_bMnFlag1; // Flag 1 with EA, ER from PReq, SoA of MN - BYTE m_bFlag2; // Flag 2 with PR and RS for PRes, StatusRes, IdentRes + u8 m_bFlag1; // Flag 1 with EN, EC for PRes, StatusRes + u8 m_bMnFlag1; // Flag 1 with EA, ER from PReq, SoA of MN + u8 m_bFlag2; // Flag 2 with PR and RS for PRes, StatusRes, IdentRes tEplDllConfigParam m_DllConfigParam; tEplDllIdentParam m_DllIdentParam; tEplDllState m_DllState; @@ -257,7 +257,7 @@ static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p, // called by high resolution timer module to monitor EPL cycle as CN #if EPL_TIMER_USE_HIGHRES != FALSE -static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p); +static tEplKernel EplDllkCbCnTimer(tEplTimerEventArg *pEventArg_p); #endif #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) @@ -278,10 +278,9 @@ static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId ReqServiceId_p, unsigned int uiNodeId_p); -static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p); +static tEplKernel EplDllkCbMnTimerCycle(tEplTimerEventArg *pEventArg_p); -static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg * - pEventArg_p); +static tEplKernel EplDllkCbMnTimerResponse(tEplTimerEventArg *pEventArg_p); #endif @@ -514,7 +513,7 @@ tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p, EPL_C_DLL_ETHERTYPE_EPL); // source node ID AmiSetByteToLe(&pTxFrame->m_le_bSrcNodeId, - (BYTE) EplDllkInstance_g.m_DllConfigParam. + (u8) EplDllkInstance_g.m_DllConfigParam. m_uiNodeId); // source MAC address EPL_MEMCPY(&pTxFrame->m_be_abSrcMac[0], @@ -531,7 +530,7 @@ tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p, { // IdentResponses and StatusResponses are Broadcast AmiSetByteToLe(&pTxFrame-> m_le_bDstNodeId, - (BYTE) + (u8) EPL_C_ADR_BROADCAST); break; } @@ -550,10 +549,10 @@ tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p, EPL_C_DLL_MULTICAST_SOC); // destination node ID AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId, - (BYTE) EPL_C_ADR_BROADCAST); + (u8) EPL_C_ADR_BROADCAST); // reset Flags - //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag1, (BYTE) 0); - //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag2, (BYTE) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag1, (u8) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag2, (u8) 0); break; case kEplMsgTypeSoa: @@ -562,13 +561,13 @@ tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p, EPL_C_DLL_MULTICAST_SOA); // destination node ID AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId, - (BYTE) EPL_C_ADR_BROADCAST); + (u8) EPL_C_ADR_BROADCAST); // reset Flags - //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag1, (BYTE) 0); - //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag2, (BYTE) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag1, (u8) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag2, (u8) 0); // EPL profile version AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bEplVersion, - (BYTE) EPL_SPEC_VERSION); + (u8) EPL_SPEC_VERSION); break; case kEplMsgTypePres: @@ -577,18 +576,18 @@ tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p, EPL_C_DLL_MULTICAST_PRES); // destination node ID AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId, - (BYTE) EPL_C_ADR_BROADCAST); + (u8) EPL_C_ADR_BROADCAST); // reset Flags - //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, (BYTE) 0); - //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, (BYTE) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, (u8) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, (u8) 0); // PDO size //AmiSetWordToLe(&pTxFrame->m_Data.m_Pres.m_le_wSize, 0); break; case kEplMsgTypePreq: // reset Flags - //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, (BYTE) 0); - //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag2, (BYTE) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, (u8) 0); + //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag2, (u8) 0); // PDO size //AmiSetWordToLe(&pTxFrame->m_Data.m_Preq.m_le_wSize, 0); break; @@ -597,7 +596,7 @@ tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p, break; } // EPL message type - AmiSetByteToLe(&pTxFrame->m_le_bMessageType, (BYTE) MsgType_p); + AmiSetByteToLe(&pTxFrame->m_le_bMessageType, (u8) MsgType_p); } *ppFrame_p = pTxFrame; @@ -673,7 +672,7 @@ tEplKernel EplDllkProcess(tEplEvent * pEvent_p) tEdrvTxBuffer *pTxBuffer; unsigned int uiHandle; unsigned int uiFrameSize; - BYTE abMulticastMac[6]; + u8 abMulticastMac[6]; tEplDllAsyncReqPriority AsyncReqPriority; unsigned int uiFrameCount; tEplNmtState NmtState; @@ -712,7 +711,7 @@ tEplKernel EplDllkProcess(tEplEvent * pEvent_p) // EPL profile version AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload. m_IdentResponse.m_le_bEplProfileVersion, - (BYTE) EPL_SPEC_VERSION); + (u8) EPL_SPEC_VERSION); // FeatureFlags AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload. m_IdentResponse.m_le_dwFeatureFlags, @@ -721,18 +720,18 @@ tEplKernel EplDllkProcess(tEplEvent * pEvent_p) // MTU AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload. m_IdentResponse.m_le_wMtu, - (WORD) EplDllkInstance_g. + (u16) EplDllkInstance_g. m_DllConfigParam.m_uiAsyncMtu); // PollInSize AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload. m_IdentResponse.m_le_wPollInSize, - (WORD) EplDllkInstance_g. + (u16) EplDllkInstance_g. m_DllConfigParam. m_uiPreqActPayloadLimit); // PollOutSize AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload. m_IdentResponse.m_le_wPollOutSize, - (WORD) EplDllkInstance_g. + (u16) EplDllkInstance_g. m_DllConfigParam. m_uiPresActPayloadLimit); // ResponseTime / PresMaxLatency @@ -936,7 +935,7 @@ tEplKernel EplDllkProcess(tEplEvent * pEvent_p) // EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1; EplDllkInstance_g.m_aNodeInfo[uiIndex]. m_wPresPayloadLimit = - (WORD) EplDllkInstance_g. + (u16) EplDllkInstance_g. m_DllConfigParam. m_uiIsochrRxMaxPayload; } @@ -1233,7 +1232,7 @@ tEplKernel EplDllkProcess(tEplEvent * pEvent_p) } if (uiFrameCount > 0) { EplDllkInstance_g.m_bFlag2 = - (BYTE) (((AsyncReqPriority << + (u8) (((AsyncReqPriority << EPL_FRAME_FLAG2_PR_SHIFT) & EPL_FRAME_FLAG2_PR) | (uiFrameCount & @@ -1307,7 +1306,7 @@ tEplKernel EplDllkProcess(tEplEvent * pEvent_p) } AmiSetByteToLe(&pTxFrame->m_Data.m_Pres. m_le_bNmtStatus, - (BYTE) NmtState); + (u8) NmtState); AmiSetByteToLe(&pTxFrame->m_Data.m_Pres. m_le_bFlag2, EplDllkInstance_g. @@ -1533,7 +1532,7 @@ tEplKernel EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p, // //--------------------------------------------------------------------------- -tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, BYTE bSoaFlag1_p) +tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, u8 bSoaFlag1_p) { tEplKernel Ret = kEplSuccessful; tEplDllkNodeInfo *pNodeInfo; @@ -1664,7 +1663,7 @@ tEplKernel EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p) pIntNodeInfo->m_pPreqTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle]; AmiSetByteToLe(&pFrame->m_le_bDstNodeId, - (BYTE) pNodeInfo_p->m_uiNodeId); + (u8) pNodeInfo_p->m_uiNodeId); // set up destination MAC address EPL_MEMCPY(pFrame->m_be_abDstMac, pIntNodeInfo->m_be_abMacAddr, @@ -2431,7 +2430,7 @@ static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p) tEplDllReqServiceId ReqServiceId; unsigned int uiAsndServiceId; unsigned int uiNodeId; - BYTE bFlag1; + u8 bFlag1; BENCHMARK_MOD_02_SET(3); NmtState = EplNmtkGetNmtState(); @@ -2466,7 +2465,7 @@ static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p) // update frame (NMT state, RD, RS, PR, MS, EN flags) AmiSetByteToLe(&pTxFrame->m_Data.m_Pres. m_le_bNmtStatus, - (BYTE) NmtState); + (u8) NmtState); AmiSetByteToLe(&pTxFrame->m_Data.m_Pres. m_le_bFlag2, EplDllkInstance_g. @@ -2541,7 +2540,7 @@ static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p) // update frame (NMT state, RD, RS, PR, MS, EN flags) AmiSetByteToLe(&pTxFrame->m_Data.m_Pres. m_le_bNmtStatus, - (BYTE) NmtState); + (u8) NmtState); AmiSetByteToLe(&pTxFrame->m_Data.m_Pres. m_le_bFlag2, EplDllkInstance_g. @@ -2803,7 +2802,7 @@ static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p) } AmiSetByteToLe(&pTxFrame->m_Data.m_Pres. m_le_bNmtStatus, - (BYTE) NmtState); + (u8) NmtState); AmiSetByteToLe(&pTxFrame->m_Data.m_Pres. m_le_bFlag2, EplDllkInstance_g.m_bFlag2); @@ -2888,7 +2887,7 @@ static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p) m_Payload. m_StatusResponse. m_le_bNmtStatus, - (BYTE) NmtState); + (u8) NmtState); AmiSetByteToLe(&pTxFrame-> m_Data.m_Asnd. m_Payload. @@ -2954,7 +2953,7 @@ static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p) m_Payload. m_IdentResponse. m_le_bNmtStatus, - (BYTE) NmtState); + (u8) NmtState); AmiSetByteToLe(&pTxFrame-> m_Data.m_Asnd. m_Payload. @@ -3155,7 +3154,7 @@ static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p) Exit: if (Ret != kEplSuccessful) { - DWORD dwArg; + u32 dwArg; BENCHMARK_MOD_02_TOGGLE(9); @@ -3286,7 +3285,7 @@ static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p) m_Payload. m_StatusResponse. m_le_bNmtStatus, - (BYTE) NmtState); + (u8) NmtState); AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd. m_Payload. m_StatusResponse. @@ -3322,7 +3321,7 @@ static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p) m_Payload. m_IdentResponse. m_le_bNmtStatus, - (BYTE) NmtState); + (u8) NmtState); AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd. m_Payload. m_IdentResponse. @@ -3362,12 +3361,12 @@ static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p) if ((AmiGetByteFromLe (&pTxFrame-> m_le_bMessageType) - == (BYTE) kEplMsgTypeAsnd) + == (u8) kEplMsgTypeAsnd) && (AmiGetByteFromLe (&pTxFrame->m_Data.m_Asnd. m_le_bServiceId) - == (BYTE) kEplDllAsndNmtCommand)) { // post event directly to NmtMnu module + == (u8) kEplDllAsndNmtCommand)) { // post event directly to NmtMnu module Event.m_EventSink = kEplEventSinkNmtMnu; Event.m_EventType = @@ -3449,7 +3448,7 @@ static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p) Exit: if (Ret != kEplSuccessful) { - DWORD dwArg; + u32 dwArg; BENCHMARK_MOD_02_TOGGLE(9); @@ -3485,7 +3484,7 @@ static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p, unsigned int uiFrameSize_p) { tEplMsgType MsgType; - WORD wEtherType; + u16 wEtherType; // check frame if (pFrame_p != NULL) { @@ -3506,7 +3505,7 @@ static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p, if (wEtherType == EPL_C_DLL_ETHERTYPE_EPL) { // source node ID AmiSetByteToLe(&pFrame_p->m_le_bSrcNodeId, - (BYTE) EplDllkInstance_g. + (u8) EplDllkInstance_g. m_DllConfigParam.m_uiNodeId); // check message type @@ -3515,7 +3514,7 @@ static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p, if (MsgType == 0) { MsgType = kEplMsgTypeAsnd; AmiSetByteToLe(&pFrame_p->m_le_bMessageType, - (BYTE) MsgType); + (u8) MsgType); } if (MsgType == kEplMsgTypeAsnd) { @@ -3546,7 +3545,7 @@ static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p, //--------------------------------------------------------------------------- #if EPL_TIMER_USE_HIGHRES != FALSE -static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p) +static tEplKernel EplDllkCbCnTimer(tEplTimerEventArg *pEventArg_p) { tEplKernel Ret = kEplSuccessful; tEplNmtState NmtState; @@ -3583,7 +3582,7 @@ static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p) Exit: if (Ret != kEplSuccessful) { - DWORD dwArg; + u32 dwArg; BENCHMARK_MOD_02_TOGGLE(9); @@ -3617,7 +3616,7 @@ static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p) // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p) +static tEplKernel EplDllkCbMnTimerCycle(tEplTimerEventArg *pEventArg_p) { tEplKernel Ret = kEplSuccessful; tEplNmtState NmtState; @@ -3639,7 +3638,7 @@ static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p) Exit: if (Ret != kEplSuccessful) { - DWORD dwArg; + u32 dwArg; BENCHMARK_MOD_02_TOGGLE(9); @@ -3670,8 +3669,7 @@ static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p) // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg * - pEventArg_p) +static tEplKernel EplDllkCbMnTimerResponse(tEplTimerEventArg *pEventArg_p) { tEplKernel Ret = kEplSuccessful; tEplNmtState NmtState; @@ -3693,7 +3691,7 @@ static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg * Exit: if (Ret != kEplSuccessful) { - DWORD dwArg; + u32 dwArg; BENCHMARK_MOD_02_TOGGLE(9); @@ -3827,24 +3825,24 @@ static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p, // update frame (target) AmiSetByteToLe(&pTxFrame->m_Data.m_Soa. m_le_bReqServiceId, - (BYTE) EplDllkInstance_g. + (u8) EplDllkInstance_g. m_LastReqServiceId); AmiSetByteToLe(&pTxFrame->m_Data.m_Soa. m_le_bReqServiceTarget, - (BYTE) EplDllkInstance_g. + (u8) EplDllkInstance_g. m_uiLastTargetNodeId); } else { // invite nobody // update frame (target) AmiSetByteToLe(&pTxFrame->m_Data.m_Soa. - m_le_bReqServiceId, (BYTE) 0); + m_le_bReqServiceId, (u8) 0); AmiSetByteToLe(&pTxFrame->m_Data.m_Soa. - m_le_bReqServiceTarget, (BYTE) 0); + m_le_bReqServiceTarget, (u8) 0); } // update frame (NMT state) AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bNmtStatus, - (BYTE) NmtState_p); + (u8) NmtState_p); // send SoA frame Ret = EdrvSendTxMsg(pTxBuffer); @@ -3921,7 +3919,7 @@ static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p, tEplKernel Ret = kEplSuccessful; tEdrvTxBuffer *pTxBuffer = NULL; tEplFrame *pTxFrame; - BYTE bFlag1 = 0; + u8 bFlag1 = 0; if (EplDllkInstance_g.m_pCurNodeInfo == NULL) { // start with first isochronous CN EplDllkInstance_g.m_pCurNodeInfo = @@ -3972,7 +3970,7 @@ static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p, if (pTxBuffer == &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]) { // PRes of MN will be sent // update NMT state AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bNmtStatus, - (BYTE) NmtState_p); + (u8) NmtState_p); *pDllStateProposed_p = kEplDllMsWaitSoaTrig; } // $$$ d.k. set EPL_FRAME_FLAG1_MS if necessary @@ -4015,7 +4013,7 @@ static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId unsigned int uiNodeId_p) { tEplKernel Ret = kEplSuccessful; - BYTE abBuffer[18]; + u8 abBuffer[18]; tEplFrame *pFrame = (tEplFrame *) abBuffer; tEplFrameInfo FrameInfo; @@ -4026,13 +4024,13 @@ static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId // ASnd service registered? if (EplDllkInstance_g.m_aAsndFilter[ReqServiceId_p] == kEplDllAsndFilterAny) { // ASnd service ID is registered AmiSetByteToLe(&pFrame->m_le_bSrcNodeId, - (BYTE) uiNodeId_p); + (u8) uiNodeId_p); // EPL MsgType ASnd AmiSetByteToLe(&pFrame->m_le_bMessageType, - (BYTE) kEplMsgTypeAsnd); + (u8) kEplMsgTypeAsnd); // ASnd Service ID AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId, - (BYTE) ReqServiceId_p); + (u8) ReqServiceId_p); // create frame info structure FrameInfo.m_pFrame = pFrame; FrameInfo.m_uiFrameSize = 18; // empty non existing ASnd frame diff --git a/drivers/staging/epl/EplDllkCal.c b/drivers/staging/epl/EplDllkCal.c index 359083ebe12d..0e283d5d0181 100644 --- a/drivers/staging/epl/EplDllkCal.c +++ b/drivers/staging/epl/EplDllkCal.c @@ -142,9 +142,9 @@ typedef struct { tShbInstance m_ShbInstanceTxGen; // FIFO for Tx frames with generic priority #else unsigned int m_uiFrameSizeNmt; - BYTE m_abFrameNmt[1500]; + u8 m_abFrameNmt[1500]; unsigned int m_uiFrameSizeGen; - BYTE m_abFrameGen[1500]; + u8 m_abFrameGen[1500]; #endif tEplDllkCalStatistics m_Statistics; @@ -202,7 +202,7 @@ static tEplDllkCalInstance EplDllkCalInstance_g; // //--------------------------------------------------------------------------- -tEplKernel EplDllkCalAddInstance() +tEplKernel EplDllkCalAddInstance(void) { tEplKernel Ret = kEplSuccessful; #ifndef EPL_NO_FIFO @@ -279,7 +279,7 @@ tEplKernel EplDllkCalAddInstance() // //--------------------------------------------------------------------------- -tEplKernel EplDllkCalDelInstance() +tEplKernel EplDllkCalDelInstance(void) { tEplKernel Ret = kEplSuccessful; #ifndef EPL_NO_FIFO @@ -536,7 +536,7 @@ tEplKernel EplDllkCalAsyncGetTxFrame(void *pFrame_p, case kEplDllAsyncReqPrioNmt: // NMT request priority ShbError = ShbCirReadDataBlock(EplDllkCalInstance_g.m_ShbInstanceTxNmt, - (BYTE *) pFrame_p, *puiFrameSize_p, + (u8 *) pFrame_p, *puiFrameSize_p, &ulFrameSize); // returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData break; @@ -544,7 +544,7 @@ tEplKernel EplDllkCalAsyncGetTxFrame(void *pFrame_p, default: // generic priority ShbError = ShbCirReadDataBlock(EplDllkCalInstance_g.m_ShbInstanceTxGen, - (BYTE *) pFrame_p, *puiFrameSize_p, + (u8 *) pFrame_p, *puiFrameSize_p, &ulFrameSize); // returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData break; @@ -876,7 +876,7 @@ tEplKernel EplDllkCalGetStatistics(tEplDllkCalStatistics ** ppStatistics) //--------------------------------------------------------------------------- tEplKernel EplDllkCalIssueRequest(tEplDllReqServiceId Service_p, - unsigned int uiNodeId_p, BYTE bSoaFlag1_p) + unsigned int uiNodeId_p, u8 bSoaFlag1_p) { tEplKernel Ret = kEplSuccessful; diff --git a/drivers/staging/epl/EplDlluCal.c b/drivers/staging/epl/EplDlluCal.c index 7f4a17450237..f96fe84c4972 100644 --- a/drivers/staging/epl/EplDlluCal.c +++ b/drivers/staging/epl/EplDlluCal.c @@ -173,7 +173,7 @@ static tEplKernel EplDlluCalSetAsndServiceIdFilter(tEplDllAsndServiceId // //--------------------------------------------------------------------------- -tEplKernel EplDlluCalAddInstance() +tEplKernel EplDlluCalAddInstance(void) { tEplKernel Ret = kEplSuccessful; @@ -198,7 +198,7 @@ tEplKernel EplDlluCalAddInstance() // //--------------------------------------------------------------------------- -tEplKernel EplDlluCalDelInstance() +tEplKernel EplDlluCalDelInstance(void) { tEplKernel Ret = kEplSuccessful; @@ -355,7 +355,7 @@ tEplKernel EplDlluCalAsyncSend(tEplFrameInfo * pFrameInfo_p, //--------------------------------------------------------------------------- tEplKernel EplDlluCalIssueRequest(tEplDllReqServiceId Service_p, - unsigned int uiNodeId_p, BYTE bSoaFlag1_p) + unsigned int uiNodeId_p, u8 bSoaFlag1_p) { tEplKernel Ret = kEplSuccessful; diff --git a/drivers/staging/epl/EplErrorHandlerk.c b/drivers/staging/epl/EplErrorHandlerk.c index d12521fc99a4..6baed04ef11c 100644 --- a/drivers/staging/epl/EplErrorHandlerk.c +++ b/drivers/staging/epl/EplErrorHandlerk.c @@ -97,9 +97,9 @@ //--------------------------------------------------------------------------- typedef struct { - DWORD m_dwCumulativeCnt; // subindex 1 - DWORD m_dwThresholdCnt; // subindex 2 - DWORD m_dwThreshold; // subindex 3 + u32 m_dwCumulativeCnt; // subindex 1 + u32 m_dwThresholdCnt; // subindex 2 + u32 m_dwThreshold; // subindex 3 } tEplErrorHandlerkErrorCounter; @@ -112,9 +112,9 @@ typedef struct { #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) tEplErrorHandlerkErrorCounter m_MnCrcErr; // object 0x1C00 tEplErrorHandlerkErrorCounter m_MnCycTimeExceed; // object 0x1C02 - DWORD m_adwMnCnLossPresCumCnt[254]; // object 0x1C07 - DWORD m_adwMnCnLossPresThrCnt[254]; // object 0x1C08 - DWORD m_adwMnCnLossPresThreshold[254]; // object 0x1C09 + u32 m_adwMnCnLossPresCumCnt[254]; // object 0x1C07 + u32 m_adwMnCnLossPresThrCnt[254]; // object 0x1C08 + u32 m_adwMnCnLossPresThreshold[254]; // object 0x1C09 BOOL m_afMnCnLossPresEvent[254]; #endif @@ -135,7 +135,7 @@ static tEplKernel EplErrorHandlerkLinkErrorCounter(tEplErrorHandlerkErrorCounter unsigned int uiIndex_p); #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) -static tEplKernel EplErrorHandlerkLinkArray(DWORD * pdwValue_p, +static tEplKernel EplErrorHandlerkLinkArray(u32 * pdwValue_p, unsigned int uiValueCount_p, unsigned int uiIndex_p); #endif @@ -176,7 +176,7 @@ static tEplKernel EplErrorHandlerkLinkArray(DWORD * pdwValue_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplErrorHandlerkInit(void) +tEplKernel EplErrorHandlerkInit(void) { tEplKernel Ret; @@ -203,7 +203,7 @@ tEplKernel PUBLIC EplErrorHandlerkInit(void) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplErrorHandlerkAddInstance(void) +tEplKernel EplErrorHandlerkAddInstance(void) { tEplKernel Ret; @@ -306,7 +306,7 @@ tEplKernel PUBLIC EplErrorHandlerkAddInstance(void) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplErrorHandlerkDelInstance() +tEplKernel EplErrorHandlerkDelInstance(void) { tEplKernel Ret; @@ -333,7 +333,7 @@ tEplKernel PUBLIC EplErrorHandlerkDelInstance() // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplErrorHandlerkProcess(tEplEvent * pEvent_p) +tEplKernel EplErrorHandlerkProcess(tEplEvent *pEvent_p) { tEplKernel Ret; unsigned long ulDllErrorEvents; @@ -713,7 +713,7 @@ static tEplKernel EplErrorHandlerkLinkErrorCounter(tEplErrorHandlerkErrorCounter tEplVarParam VarParam; VarParam.m_pData = &pErrorCounter_p->m_dwCumulativeCnt; - VarParam.m_Size = sizeof(DWORD); + VarParam.m_Size = sizeof(u32); VarParam.m_uiIndex = uiIndex_p; VarParam.m_uiSubindex = 0x01; VarParam.m_ValidFlag = kVarValidAll; @@ -723,7 +723,7 @@ static tEplKernel EplErrorHandlerkLinkErrorCounter(tEplErrorHandlerkErrorCounter } VarParam.m_pData = &pErrorCounter_p->m_dwThresholdCnt; - VarParam.m_Size = sizeof(DWORD); + VarParam.m_Size = sizeof(u32); VarParam.m_uiIndex = uiIndex_p; VarParam.m_uiSubindex = 0x02; VarParam.m_ValidFlag = kVarValidAll; @@ -733,7 +733,7 @@ static tEplKernel EplErrorHandlerkLinkErrorCounter(tEplErrorHandlerkErrorCounter } VarParam.m_pData = &pErrorCounter_p->m_dwThreshold; - VarParam.m_Size = sizeof(DWORD); + VarParam.m_Size = sizeof(u32); VarParam.m_uiIndex = uiIndex_p; VarParam.m_uiSubindex = 0x03; VarParam.m_ValidFlag = kVarValidAll; @@ -763,18 +763,18 @@ static tEplKernel EplErrorHandlerkLinkErrorCounter(tEplErrorHandlerkErrorCounter //--------------------------------------------------------------------------- #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) -static tEplKernel EplErrorHandlerkLinkArray(DWORD * pdwValue_p, +static tEplKernel EplErrorHandlerkLinkArray(u32 * pdwValue_p, unsigned int uiValueCount_p, unsigned int uiIndex_p) { tEplKernel Ret = kEplSuccessful; tEplVarParam VarParam; tEplObdSize EntrySize; - BYTE bIndexEntries; + u8 bIndexEntries; EntrySize = (tEplObdSize) sizeof(bIndexEntries); Ret = EplObdReadEntry(uiIndex_p, - 0x00, (void GENERIC *)&bIndexEntries, &EntrySize); + 0x00, (void *)&bIndexEntries, &EntrySize); if ((Ret != kEplSuccessful) || (bIndexEntries == 0x00)) { // Object doesn't exist or invalid entry number @@ -786,7 +786,7 @@ static tEplKernel EplErrorHandlerkLinkArray(DWORD * pdwValue_p, uiValueCount_p = bIndexEntries; } - VarParam.m_Size = sizeof(DWORD); + VarParam.m_Size = sizeof(u32); VarParam.m_uiIndex = uiIndex_p; VarParam.m_ValidFlag = kVarValidAll; diff --git a/drivers/staging/epl/EplEvent.h b/drivers/staging/epl/EplEvent.h index b6dc1b9b2ab1..910bd69a18c2 100644 --- a/drivers/staging/epl/EplEvent.h +++ b/drivers/staging/epl/EplEvent.h @@ -248,8 +248,8 @@ typedef struct { tEplEventSource m_EventSource; // module which posted this error event tEplKernel m_EplError; // EPL error which occured union { - BYTE m_bArg; - DWORD m_dwArg; + u8 m_bArg; + u32 m_dwArg; tEplEventSource m_EventSource; // from Eventk/u module (originating error source) tEplEventObdError m_ObdError; // from Obd module // tEplErrHistoryEntry m_HistoryEntry; // from Nmtk/u module @@ -267,10 +267,10 @@ typedef struct { } tEplErrorHandlerkEvent; // callback function to get informed about sync event -typedef tEplKernel(PUBLIC * tEplSyncCb) (void); +typedef tEplKernel(*tEplSyncCb) (void); // callback function for generic events -typedef tEplKernel(PUBLIC * tEplProcessEventCb) (tEplEvent * pEplEvent_p); +typedef tEplKernel(*tEplProcessEventCb) (tEplEvent *pEplEvent_p); //--------------------------------------------------------------------------- // function prototypes diff --git a/drivers/staging/epl/EplEventk.c b/drivers/staging/epl/EplEventk.c index 8068a6c5a0d0..ef36815c7984 100644 --- a/drivers/staging/epl/EplEventk.c +++ b/drivers/staging/epl/EplEventk.c @@ -100,8 +100,8 @@ // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); -void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); +void TgtDbgPostTraceValue(u32 dwTraceValue_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) #else @@ -172,7 +172,7 @@ static void EplEventkRxSignalHandlerCb(tShbInstance pShbRxInstance_p, // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventkInit(tEplSyncCb pfnCbSync_p) +tEplKernel EplEventkInit(tEplSyncCb pfnCbSync_p) { tEplKernel Ret; @@ -196,7 +196,7 @@ tEplKernel PUBLIC EplEventkInit(tEplSyncCb pfnCbSync_p) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventkAddInstance(tEplSyncCb pfnCbSync_p) +tEplKernel EplEventkAddInstance(tEplSyncCb pfnCbSync_p) { tEplKernel Ret; #ifndef EPL_NO_FIFO @@ -275,7 +275,7 @@ tEplKernel PUBLIC EplEventkAddInstance(tEplSyncCb pfnCbSync_p) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventkDelInstance() +tEplKernel EplEventkDelInstance(void) { tEplKernel Ret; #ifndef EPL_NO_FIFO @@ -339,7 +339,7 @@ tEplKernel PUBLIC EplEventkDelInstance() // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventkProcess(tEplEvent * pEvent_p) +tEplKernel EplEventkProcess(tEplEvent *pEvent_p) { tEplKernel Ret; tEplEventSource EventSource; @@ -562,7 +562,7 @@ tEplKernel PUBLIC EplEventkProcess(tEplEvent * pEvent_p) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventkPost(tEplEvent * pEvent_p) +tEplKernel EplEventkPost(tEplEvent *pEvent_p) { tEplKernel Ret; #ifndef EPL_NO_FIFO @@ -755,12 +755,12 @@ tEplKernel PUBLIC EplEventkPost(tEplEvent * pEvent_p) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventkPostError(tEplEventSource EventSource_p, - tEplKernel EplError_p, - unsigned int uiArgSize_p, void *pArg_p) +tEplKernel EplEventkPostError(tEplEventSource EventSource_p, + tEplKernel EplError_p, + unsigned int uiArgSize_p, void *pArg_p) { tEplKernel Ret; - BYTE abBuffer[EPL_MAX_EVENT_ARG_SIZE]; + u8 abBuffer[EPL_MAX_EVENT_ARG_SIZE]; tEplEventError *pEventError = (tEplEventError *) abBuffer; tEplEvent EplEvent; @@ -814,7 +814,7 @@ static void EplEventkRxSignalHandlerCb(tShbInstance pShbRxInstance_p, tShbError ShbError; //unsigned long ulBlockCount; //unsigned long ulDataSize; - BYTE abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE]; + u8 abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE]; // d.k.: abDataBuffer contains the complete tEplEvent structure // and behind this the argument diff --git a/drivers/staging/epl/EplEventu.c b/drivers/staging/epl/EplEventu.c index 815f9a87abf8..3ae2841ad023 100644 --- a/drivers/staging/epl/EplEventu.c +++ b/drivers/staging/epl/EplEventu.c @@ -96,8 +96,8 @@ // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); -void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); +void TgtDbgPostTraceValue(u32 dwTraceValue_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) #else @@ -172,7 +172,7 @@ static void EplEventuRxSignalHandlerCb(tShbInstance pShbRxInstance_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventuInit(tEplProcessEventCb pfnApiProcessEventCb_p) +tEplKernel EplEventuInit(tEplProcessEventCb pfnApiProcessEventCb_p) { tEplKernel Ret; @@ -199,8 +199,7 @@ tEplKernel PUBLIC EplEventuInit(tEplProcessEventCb pfnApiProcessEventCb_p) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventuAddInstance(tEplProcessEventCb - pfnApiProcessEventCb_p) +tEplKernel EplEventuAddInstance(tEplProcessEventCb pfnApiProcessEventCb_p) { tEplKernel Ret; #ifndef EPL_NO_FIFO @@ -280,7 +279,7 @@ tEplKernel PUBLIC EplEventuAddInstance(tEplProcessEventCb // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventuDelInstance() +tEplKernel EplEventuDelInstance(void) { tEplKernel Ret; #ifndef EPL_NO_FIFO @@ -348,7 +347,7 @@ tEplKernel PUBLIC EplEventuDelInstance() // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventuProcess(tEplEvent * pEvent_p) +tEplKernel EplEventuProcess(tEplEvent *pEvent_p) { tEplKernel Ret; tEplEventSource EventSource; @@ -515,7 +514,7 @@ tEplKernel PUBLIC EplEventuProcess(tEplEvent * pEvent_p) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventuPost(tEplEvent * pEvent_p) +tEplKernel EplEventuPost(tEplEvent *pEvent_p) { tEplKernel Ret; #ifndef EPL_NO_FIFO @@ -689,12 +688,12 @@ tEplKernel PUBLIC EplEventuPost(tEplEvent * pEvent_p) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplEventuPostError(tEplEventSource EventSource_p, - tEplKernel EplError_p, - unsigned int uiArgSize_p, void *pArg_p) +tEplKernel EplEventuPostError(tEplEventSource EventSource_p, + tEplKernel EplError_p, + unsigned int uiArgSize_p, void *pArg_p) { tEplKernel Ret; - BYTE abBuffer[EPL_MAX_EVENT_ARG_SIZE]; + u8 abBuffer[EPL_MAX_EVENT_ARG_SIZE]; tEplEventError *pEventError = (tEplEventError *) abBuffer; tEplEvent EplEvent; @@ -751,7 +750,7 @@ static void EplEventuRxSignalHandlerCb(tShbInstance pShbRxInstance_p, tShbError ShbError; //unsigned long ulBlockCount; //unsigned long ulDataSize; - BYTE abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE]; + u8 abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE]; // d.k.: abDataBuffer contains the complete tEplEvent structure // and behind this the argument diff --git a/drivers/staging/epl/EplFrame.h b/drivers/staging/epl/EplFrame.h index 9a7f8b9f594e..ba1ae9e9e907 100644 --- a/drivers/staging/epl/EplFrame.h +++ b/drivers/staging/epl/EplFrame.h @@ -122,155 +122,155 @@ typedef struct { // Offset 17 - BYTE m_le_bRes1; // reserved + u8 m_le_bRes1; // reserved // Offset 18 - BYTE m_le_bFlag1; // Flags: MC, PS + u8 m_le_bFlag1; // Flags: MC, PS // Offset 19 - BYTE m_le_bFlag2; // Flags: res + u8 m_le_bFlag2; // Flags: res // Offset 20 tEplNetTime m_le_NetTime; // supported if D_NMT_NetTimeIsRealTime_BOOL is set // Offset 28 - QWORD m_le_RelativeTime; // in us (supported if D_NMT_RelativeTime_BOOL is set) + u64 m_le_RelativeTime; // in us (supported if D_NMT_RelativeTime_BOOL is set) } PACK_STRUCT tEplSocFrame; typedef struct { // Offset 17 - BYTE m_le_bRes1; // reserved + u8 m_le_bRes1; // reserved // Offset 18 - BYTE m_le_bFlag1; // Flags: MS, EA, RD + u8 m_le_bFlag1; // Flags: MS, EA, RD // Offset 19 - BYTE m_le_bFlag2; // Flags: res + u8 m_le_bFlag2; // Flags: res // Offset 20 - BYTE m_le_bPdoVersion; + u8 m_le_bPdoVersion; // Offset 21 - BYTE m_le_bRes2; // reserved + u8 m_le_bRes2; // reserved // Offset 22 - WORD m_le_wSize; + u16 m_le_wSize; // Offset 24 - BYTE m_le_abPayload[256 /*D_NMT_IsochrRxMaxPayload_U16 */ ]; + u8 m_le_abPayload[256 /*D_NMT_IsochrRxMaxPayload_U16 */ ]; } PACK_STRUCT tEplPreqFrame; typedef struct { // Offset 17 - BYTE m_le_bNmtStatus; // NMT state + u8 m_le_bNmtStatus; // NMT state // Offset 18 - BYTE m_le_bFlag1; // Flags: MS, EN, RD + u8 m_le_bFlag1; // Flags: MS, EN, RD // Offset 19 - BYTE m_le_bFlag2; // Flags: PR, RS + u8 m_le_bFlag2; // Flags: PR, RS // Offset 20 - BYTE m_le_bPdoVersion; + u8 m_le_bPdoVersion; // Offset 21 - BYTE m_le_bRes2; // reserved + u8 m_le_bRes2; // reserved // Offset 22 - WORD m_le_wSize; + u16 m_le_wSize; // Offset 24 - BYTE m_le_abPayload[256 /*D_NMT_IsochrRxMaxPayload_U16 + u8 m_le_abPayload[256 /*D_NMT_IsochrRxMaxPayload_U16 / D_NMT_IsochrTxMaxPayload_U16 */ ]; } PACK_STRUCT tEplPresFrame; typedef struct { // Offset 17 - BYTE m_le_bNmtStatus; // NMT state + u8 m_le_bNmtStatus; // NMT state // Offset 18 - BYTE m_le_bFlag1; // Flags: EA, ER + u8 m_le_bFlag1; // Flags: EA, ER // Offset 19 - BYTE m_le_bFlag2; // Flags: res + u8 m_le_bFlag2; // Flags: res // Offset 20 - BYTE m_le_bReqServiceId; + u8 m_le_bReqServiceId; // Offset 21 - BYTE m_le_bReqServiceTarget; + u8 m_le_bReqServiceTarget; // Offset 22 - BYTE m_le_bEplVersion; + u8 m_le_bEplVersion; } PACK_STRUCT tEplSoaFrame; typedef struct { - WORD m_wEntryType; - WORD m_wErrorCode; + u16 m_wEntryType; + u16 m_wErrorCode; tEplNetTime m_TimeStamp; - BYTE m_abAddInfo[8]; + u8 m_abAddInfo[8]; } PACK_STRUCT tEplErrHistoryEntry; typedef struct { // Offset 18 - BYTE m_le_bFlag1; // Flags: EN, EC - BYTE m_le_bFlag2; // Flags: PR, RS - BYTE m_le_bNmtStatus; // NMT state - BYTE m_le_bRes1[3]; - QWORD m_le_qwStaticError; // static error bit field + u8 m_le_bFlag1; // Flags: EN, EC + u8 m_le_bFlag2; // Flags: PR, RS + u8 m_le_bNmtStatus; // NMT state + u8 m_le_bRes1[3]; + u64 m_le_qwStaticError; // static error bit field tEplErrHistoryEntry m_le_aErrHistoryEntry[14]; } PACK_STRUCT tEplStatusResponse; typedef struct { // Offset 18 - BYTE m_le_bFlag1; // Flags: res - BYTE m_le_bFlag2; // Flags: PR, RS - BYTE m_le_bNmtStatus; // NMT state - BYTE m_le_bIdentRespFlags; // Flags: FW - BYTE m_le_bEplProfileVersion; - BYTE m_le_bRes1; - DWORD m_le_dwFeatureFlags; // NMT_FeatureFlags_U32 - WORD m_le_wMtu; // NMT_CycleTiming_REC.AsyncMTU_U16: C_IP_MIN_MTU - C_IP_MAX_MTU - WORD m_le_wPollInSize; // NMT_CycleTiming_REC.PReqActPayload_U16 - WORD m_le_wPollOutSize; // NMT_CycleTiming_REC.PResActPayload_U16 - DWORD m_le_dwResponseTime; // NMT_CycleTiming_REC.PResMaxLatency_U32 - WORD m_le_wRes2; - DWORD m_le_dwDeviceType; // NMT_DeviceType_U32 - DWORD m_le_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32 - DWORD m_le_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32 - DWORD m_le_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32 - DWORD m_le_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32 - QWORD m_le_qwVendorSpecificExt1; - DWORD m_le_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 - DWORD m_le_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 - DWORD m_le_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device - DWORD m_le_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device - DWORD m_le_dwIpAddress; - DWORD m_le_dwSubnetMask; - DWORD m_le_dwDefaultGateway; - BYTE m_le_sHostname[32]; - BYTE m_le_abVendorSpecificExt2[48]; + u8 m_le_bFlag1; // Flags: res + u8 m_le_bFlag2; // Flags: PR, RS + u8 m_le_bNmtStatus; // NMT state + u8 m_le_bIdentRespFlags; // Flags: FW + u8 m_le_bEplProfileVersion; + u8 m_le_bRes1; + u32 m_le_dwFeatureFlags; // NMT_FeatureFlags_U32 + u16 m_le_wMtu; // NMT_CycleTiming_REC.AsyncMTU_U16: C_IP_MIN_MTU - C_IP_MAX_MTU + u16 m_le_wPollInSize; // NMT_CycleTiming_REC.PReqActPayload_U16 + u16 m_le_wPollOutSize; // NMT_CycleTiming_REC.PResActPayload_U16 + u32 m_le_dwResponseTime; // NMT_CycleTiming_REC.PResMaxLatency_U32 + u16 m_le_wRes2; + u32 m_le_dwDeviceType; // NMT_DeviceType_U32 + u32 m_le_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32 + u32 m_le_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32 + u32 m_le_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32 + u32 m_le_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32 + u64 m_le_qwVendorSpecificExt1; + u32 m_le_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32 + u32 m_le_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32 + u32 m_le_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device + u32 m_le_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device + u32 m_le_dwIpAddress; + u32 m_le_dwSubnetMask; + u32 m_le_dwDefaultGateway; + u8 m_le_sHostname[32]; + u8 m_le_abVendorSpecificExt2[48]; } PACK_STRUCT tEplIdentResponse; typedef struct { // Offset 18 - BYTE m_le_bNmtCommandId; - BYTE m_le_bRes1; - BYTE m_le_abNmtCommandData[32]; + u8 m_le_bNmtCommandId; + u8 m_le_bRes1; + u8 m_le_abNmtCommandData[32]; } PACK_STRUCT tEplNmtCommandService; typedef struct { - BYTE m_le_bReserved; - BYTE m_le_bTransactionId; - BYTE m_le_bFlags; - BYTE m_le_bCommandId; - WORD m_le_wSegmentSize; - WORD m_le_wReserved; - BYTE m_le_abCommandData[8]; // just reserve a minimum number of bytes as a placeholder + u8 m_le_bReserved; + u8 m_le_bTransactionId; + u8 m_le_bFlags; + u8 m_le_bCommandId; + u16 m_le_wSegmentSize; + u16 m_le_wReserved; + u8 m_le_abCommandData[8]; // just reserve a minimum number of bytes as a placeholder } PACK_STRUCT tEplAsySdoCom; // asynchronous SDO Sequence Header typedef struct { - BYTE m_le_bRecSeqNumCon; - BYTE m_le_bSendSeqNumCon; - BYTE m_le_abReserved[2]; + u8 m_le_bRecSeqNumCon; + u8 m_le_bSendSeqNumCon; + u8 m_le_abReserved[2]; tEplAsySdoCom m_le_abSdoSeqPayload; } PACK_STRUCT tEplAsySdoSeq; typedef struct { // Offset 18 - BYTE m_le_bNmtCommandId; - BYTE m_le_bTargetNodeId; - BYTE m_le_abNmtCommandData[32]; + u8 m_le_bNmtCommandId; + u8 m_le_bTargetNodeId; + u8 m_le_abNmtCommandData[32]; } PACK_STRUCT tEplNmtRequestService; @@ -281,14 +281,14 @@ typedef union { tEplNmtCommandService m_NmtCommandService; tEplNmtRequestService m_NmtRequestService; tEplAsySdoSeq m_SdoSequenceFrame; - BYTE m_le_abPayload[256 /*D_NMT_ASndTxMaxPayload_U16 + u8 m_le_abPayload[256 /*D_NMT_ASndTxMaxPayload_U16 / D_NMT_ASndRxMaxPayload_U16 */ ]; } tEplAsndPayload; typedef struct { // Offset 17 - BYTE m_le_bServiceId; + u8 m_le_bServiceId; // Offset 18 tEplAsndPayload m_Payload; @@ -306,17 +306,17 @@ typedef union { typedef struct { // Offset 0 - BYTE m_be_abDstMac[6]; // MAC address of the addressed nodes + u8 m_be_abDstMac[6]; // MAC address of the addressed nodes // Offset 6 - BYTE m_be_abSrcMac[6]; // MAC address of the transmitting node + u8 m_be_abSrcMac[6]; // MAC address of the transmitting node // Offset 12 - WORD m_be_wEtherType; // Ethernet message type (big endian) + u16 m_be_wEtherType; // Ethernet message type (big endian) // Offset 14 - BYTE m_le_bMessageType; // EPL message type + u8 m_le_bMessageType; // EPL message type // Offset 15 - BYTE m_le_bDstNodeId; // EPL node ID of the addressed nodes + u8 m_le_bDstNodeId; // EPL node ID of the addressed nodes // Offset 16 - BYTE m_le_bSrcNodeId; // EPL node ID of the transmitting node + u8 m_le_bSrcNodeId; // EPL node ID of the transmitting node // Offset 17 tEplFrameData m_Data; diff --git a/drivers/staging/epl/EplIdentu.c b/drivers/staging/epl/EplIdentu.c index ce59ef09ccdf..93d5a40a2f7b 100644 --- a/drivers/staging/epl/EplIdentu.c +++ b/drivers/staging/epl/EplIdentu.c @@ -138,7 +138,7 @@ static tEplIdentuInstance EplIdentuInstance_g; // local function prototypes //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplIdentuCbIdentResponse(tEplFrameInfo * pFrameInfo_p); +static tEplKernel EplIdentuCbIdentResponse(tEplFrameInfo *pFrameInfo_p); //=========================================================================// // // @@ -164,7 +164,7 @@ static tEplKernel PUBLIC EplIdentuCbIdentResponse(tEplFrameInfo * pFrameInfo_p); // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplIdentuInit() +tEplKernel EplIdentuInit(void) { tEplKernel Ret; @@ -191,7 +191,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplIdentuInit() // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplIdentuAddInstance() +tEplKernel EplIdentuAddInstance(void) { tEplKernel Ret; @@ -228,7 +228,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplIdentuAddInstance() // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplIdentuDelInstance() +tEplKernel EplIdentuDelInstance(void) { tEplKernel Ret; @@ -263,7 +263,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplIdentuDelInstance() // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplIdentuReset() +tEplKernel EplIdentuReset(void) { tEplKernel Ret; int iIndex; @@ -300,9 +300,8 @@ EPLDLLEXPORT tEplKernel PUBLIC EplIdentuReset() // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplIdentuGetIdentResponse(unsigned int uiNodeId_p, - tEplIdentResponse ** - ppIdentResponse_p) +tEplKernel EplIdentuGetIdentResponse(unsigned int uiNodeId_p, + tEplIdentResponse **ppIdentResponse_p) { tEplKernel Ret; @@ -338,9 +337,8 @@ tEplKernel PUBLIC EplIdentuGetIdentResponse(unsigned int uiNodeId_p, // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplIdentuRequestIdentResponse(unsigned int uiNodeId_p, - tEplIdentuCbResponse - pfnCbResponse_p) +tEplKernel EplIdentuRequestIdentResponse(unsigned int uiNodeId_p, + tEplIdentuCbResponse pfnCbResponse_p) { tEplKernel Ret; @@ -388,9 +386,9 @@ tEplKernel PUBLIC EplIdentuRequestIdentResponse(unsigned int uiNodeId_p, // //--------------------------------------------------------------------------- -EPLDLLEXPORT DWORD PUBLIC EplIdentuGetRunningRequests(void) +u32 EplIdentuGetRunningRequests(void) { - DWORD dwReqs = 0; + u32 dwReqs = 0; unsigned int uiIndex; for (uiIndex = 0; uiIndex < 32; uiIndex++) { @@ -426,7 +424,7 @@ EPLDLLEXPORT DWORD PUBLIC EplIdentuGetRunningRequests(void) // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplIdentuCbIdentResponse(tEplFrameInfo * pFrameInfo_p) +static tEplKernel EplIdentuCbIdentResponse(tEplFrameInfo *pFrameInfo_p) { tEplKernel Ret = kEplSuccessful; unsigned int uiNodeId; diff --git a/drivers/staging/epl/EplInc.h b/drivers/staging/epl/EplInc.h index 77f93d144166..f91797a3687e 100644 --- a/drivers/staging/epl/EplInc.h +++ b/drivers/staging/epl/EplInc.h @@ -140,8 +140,8 @@ // IEEE 1588 conformant net time structure typedef struct { - DWORD m_dwSec; - DWORD m_dwNanoSec; + u32 m_dwSec; + u32 m_dwNanoSec; } tEplNetTime; @@ -154,8 +154,8 @@ typedef struct { // ------------------------------------------------------------------------- #define EPL_SPEC_VERSION 0x20 // ETHERNET Powerlink V. 2.0 -#define EPL_STACK_VERSION(ver,rev,rel) ((((DWORD)(ver)) & 0xFF)|((((DWORD)(rev))&0xFF)<<8)|(((DWORD)(rel))<<16)) -#define EPL_OBJ1018_VERSION(ver,rev,rel) ((((DWORD)(ver))<<16) |(((DWORD)(rev))&0xFFFF)) +#define EPL_STACK_VERSION(ver,rev,rel) ((((u32)(ver)) & 0xFF)|((((u32)(rev))&0xFF)<<8)|(((u32)(rel))<<16)) +#define EPL_OBJ1018_VERSION(ver,rev,rel) ((((u32)(ver))<<16) |(((u32)(rev))&0xFFFF)) #define EPL_STRING_VERSION(ver,rev,rel) "V" #ver "." #rev " r" #rel #include "EplVersion.h" @@ -236,21 +236,6 @@ typedef struct { #define tabentries(a) (sizeof(a)/sizeof(*(a))) #endif -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -// definitions for DLL export -#if ((DEV_SYSTEM == _DEV_WIN32_) || (DEV_SYSTEM == _DEV_WIN_CE_)) && defined (COP_LIB) - -#define EPLDLLEXPORT __declspec (dllexport) - -#else - -#define EPLDLLEXPORT - -#endif - // ============================================================================ // common debug macros // ============================================================================ diff --git a/drivers/staging/epl/EplInstDef.h b/drivers/staging/epl/EplInstDef.h index 89efbf278264..29ab7fb7888d 100644 --- a/drivers/staging/epl/EplInstDef.h +++ b/drivers/staging/epl/EplInstDef.h @@ -71,6 +71,8 @@ #ifndef _EPLINSTDEF_H_ #define _EPLINSTDEF_H_ +#include + // ========================================================================= // types and macros for generating instances // ========================================================================= @@ -83,8 +85,8 @@ typedef enum { //------------------------------------------------------------------------------------------ -typedef void MEM *tEplPtrInstance; -typedef BYTE tEplInstanceHdl; +typedef void *tEplPtrInstance; +typedef u8 tEplInstanceHdl; // define const for illegale values #define CCM_ILLINSTANCE NULL @@ -99,8 +101,6 @@ typedef BYTE tEplInstanceHdl; //-------------------------------------------------------------------------------------- // memory attributes for instance table -#define INST_NEAR // faster access to variables -#define INST_FAR // variables wich have to located in xdata #define STATIC // prevent warnings for variables with same name #define INSTANCE_TYPE_BEGIN typedef struct { @@ -117,12 +117,12 @@ typedef BYTE tEplInstanceHdl; #define CCM_DECL_INSTANCE_HDL_ tEplInstanceHdl InstanceHandle, // macros for declaration of pointer to instance handle within function header or prototype of API functions -#define CCM_DECL_PTR_INSTANCE_HDL tEplInstanceHdl MEM* pInstanceHandle -#define CCM_DECL_PTR_INSTANCE_HDL_ tEplInstanceHdl MEM* pInstanceHandle, +#define CCM_DECL_PTR_INSTANCE_HDL tEplInstanceHdl *pInstanceHandle +#define CCM_DECL_PTR_INSTANCE_HDL_ tEplInstanceHdl *pInstanceHandle, // macros for declaration instance as lokacl variable within functions -#define CCM_DECL_INSTANCE_PTR_LOCAL tCcmInstanceInfo MEM* pInstance; -#define CCM_DECL_PTR_INSTANCE_HDL_LOCAL tEplInstanceHdl MEM* pInstanceHandle; +#define CCM_DECL_INSTANCE_PTR_LOCAL tCcmInstanceInfo *pInstance; +#define CCM_DECL_PTR_INSTANCE_HDL_LOCAL tEplInstanceHdl *pInstanceHandle; // reference: @@ -163,10 +163,10 @@ typedef BYTE tEplInstanceHdl; //-------------------------------------------------------------------------------------- // macros for declaration within the function header, prototype or local var list - // Declaration of pointers within function paramater list must defined as void MEM* + // Declaration of pointers within function paramater list must defined as void * // pointer. -#define EPL_MCO_DECL_INSTANCE_PTR void MEM* pInstance -#define EPL_MCO_DECL_INSTANCE_PTR_ void MEM* pInstance, +#define EPL_MCO_DECL_INSTANCE_PTR void *pInstance +#define EPL_MCO_DECL_INSTANCE_PTR_ void *pInstance, #define EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplPtrInstance pInstance; // macros for reference of pointer to instance @@ -191,8 +191,8 @@ typedef BYTE tEplInstanceHdl; ASSERT (((tEplPtrInstance)pInstance)->m_InstState == kStateUsed); // macros for declaration of pointer to instance pointer -#define EPL_MCO_DECL_PTR_INSTANCE_PTR void MEM* MEM* pInstancePtr -#define EPL_MCO_DECL_PTR_INSTANCE_PTR_ void MEM* MEM* pInstancePtr, +#define EPL_MCO_DECL_PTR_INSTANCE_PTR void **pInstancePtr +#define EPL_MCO_DECL_PTR_INSTANCE_PTR_ void **pInstancePtr, // macros for reference of pointer to instance pointer // These macros are used for parameter passing to called function. @@ -212,12 +212,12 @@ typedef BYTE tEplInstanceHdl; // this macro deletes all instance entries as unused #define EPL_MCO_DELETE_INSTANCE_TABLE() \ { \ - tEplInstanceInfo MEM* pInstance = &aEplInstanceTable_g[0]; \ - tFastByte InstNumber = 0; \ - tFastByte i = EPL_MAX_INSTANCES; \ + tEplInstanceInfo * pInstance = &aEplInstanceTable_g[0]; \ + tFastByte InstNumber = 0; \ + tFastByte i = EPL_MAX_INSTANCES; \ do { \ - pInstance->m_InstState = (BYTE) kStateUnused; \ - pInstance->m_bInstIndex = (BYTE) InstNumber; \ + pInstance->m_InstState = (u8) kStateUnused; \ + pInstance->m_bInstIndex = (u8) InstNumber; \ pInstance++; InstNumber++; i--; \ } while (i != 0); \ } @@ -230,8 +230,8 @@ typedef BYTE tEplInstanceHdl; static tEplPtrInstance GetInstancePtr (tEplInstanceHdl InstHandle_p) { \ return &aEplInstanceTable_g[InstHandle_p]; } \ static tEplPtrInstance GetFreeInstance (void) { \ - tEplInstanceInfo MEM* pInstance = &aEplInstanceTable_g[0]; \ - tFastByte i = EPL_MAX_INSTANCES; \ + tEplInstanceInfo *pInstance = &aEplInstanceTable_g[0]; \ + tFastByte i = EPL_MAX_INSTANCES; \ do { if (pInstance->m_InstState != kStateUsed) { \ return (tEplPtrInstance) pInstance; } \ pInstance++; i--; } \ @@ -240,13 +240,13 @@ typedef BYTE tEplInstanceHdl; // this macro defines the instance table. Each entry is reserved for an instance of CANopen. #define EPL_MCO_DECL_INSTANCE_VAR() \ - static tEplInstanceInfo MEM aEplInstanceTable_g [EPL_MAX_INSTANCES]; + static tEplInstanceInfo aEplInstanceTable_g [EPL_MAX_INSTANCES]; // this macro defines member variables in instance table which are needed in // all modules of Epl stack #define EPL_MCO_DECL_INSTANCE_MEMBER() \ - STATIC BYTE m_InstState; \ - STATIC BYTE m_bInstIndex; + STATIC u8 m_InstState; \ + STATIC u8 m_bInstIndex; #define EPL_MCO_INSTANCE_PARAM_IDX_() EPL_MCO_INSTANCE_PARAM_ (EPL_MCO_GLB_VAR (m_bInstIndex)) #define EPL_MCO_INSTANCE_PARAM_IDX() EPL_MCO_INSTANCE_PARAM (EPL_MCO_GLB_VAR (m_bInstIndex)) @@ -254,8 +254,6 @@ typedef BYTE tEplInstanceHdl; #else // only one instance is used // Memory attributes for instance table. -#define INST_NEAR NEAR // faster access to variables -#define INST_FAR MEM // variables wich have to located in xdata #define STATIC static // prevent warnings for variables with same name #define INSTANCE_TYPE_BEGIN @@ -359,18 +357,6 @@ typedef BYTE tEplInstanceHdl; #endif -/* -#if (CDRV_MAX_INSTANCES > 1) - - #define CDRV_REENTRANT REENTRANT - -#else - - #define CDRV_REENTRANT - -#endif -*/ - #endif // _EPLINSTDEF_H_ // Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler diff --git a/drivers/staging/epl/EplNmt.h b/drivers/staging/epl/EplNmt.h index 4c11e5bc74aa..e351b55eea6f 100644 --- a/drivers/staging/epl/EplNmt.h +++ b/drivers/staging/epl/EplNmt.h @@ -185,7 +185,7 @@ typedef struct { typedef struct { unsigned int m_uiNodeId; // NodeId tEplNmtState m_NmtState; // NMT state (remember distinguish between MN / CN) - WORD m_wErrorCode; // EPL error code in case of NMT state NotActive + u16 m_wErrorCode; // EPL error code in case of NMT state NotActive } tEplHeartbeatEvent; diff --git a/drivers/staging/epl/EplNmtCnu.c b/drivers/staging/epl/EplNmtCnu.c index f2f46da08c7d..c27ca8f8c2f3 100644 --- a/drivers/staging/epl/EplNmtCnu.c +++ b/drivers/staging/epl/EplNmtCnu.c @@ -108,9 +108,9 @@ static tEplNmtCnuInstance EplNmtCnuInstance_g; static tEplNmtCommand EplNmtCnuGetNmtCommand(tEplFrameInfo * pFrameInfo_p); -static BOOL EplNmtCnuNodeIdList(BYTE * pbNmtCommandDate_p); +static BOOL EplNmtCnuNodeIdList(u8 * pbNmtCommandDate_p); -static tEplKernel PUBLIC EplNmtCnuCommandCb(tEplFrameInfo * pFrameInfo_p); +static tEplKernel EplNmtCnuCommandCb(tEplFrameInfo *pFrameInfo_p); //=========================================================================// // // @@ -135,7 +135,7 @@ static tEplKernel PUBLIC EplNmtCnuCommandCb(tEplFrameInfo * pFrameInfo_p); // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuInit(unsigned int uiNodeId_p) +tEplKernel EplNmtCnuInit(unsigned int uiNodeId_p) { tEplKernel Ret; @@ -161,7 +161,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuInit(unsigned int uiNodeId_p) // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuAddInstance(unsigned int uiNodeId_p) +tEplKernel EplNmtCnuAddInstance(unsigned int uiNodeId_p) { tEplKernel Ret; @@ -201,7 +201,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuAddInstance(unsigned int uiNodeId_p) // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuDelInstance() +tEplKernel EplNmtCnuDelInstance(void) { tEplKernel Ret; @@ -234,9 +234,8 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuDelInstance() // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuSendNmtRequest(unsigned int uiNodeId_p, - tEplNmtCommand - NmtCommand_p) +tEplKernel EplNmtCnuSendNmtRequest(unsigned int uiNodeId_p, + tEplNmtCommand NmtCommand_p) { tEplKernel Ret; tEplFrameInfo NmtRequestFrameInfo; @@ -249,15 +248,15 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuSendNmtRequest(unsigned int uiNodeId_p, EPL_MEMSET(&NmtRequestFrame.m_be_abSrcMac[0], 0x00, sizeof(NmtRequestFrame.m_be_abSrcMac)); // set by DLL AmiSetWordToBe(&NmtRequestFrame.m_be_wEtherType, EPL_C_DLL_ETHERTYPE_EPL); - AmiSetByteToLe(&NmtRequestFrame.m_le_bDstNodeId, (BYTE) EPL_C_ADR_MN_DEF_NODE_ID); // node id of the MN + AmiSetByteToLe(&NmtRequestFrame.m_le_bDstNodeId, (u8) EPL_C_ADR_MN_DEF_NODE_ID); // node id of the MN AmiSetByteToLe(&NmtRequestFrame.m_le_bMessageType, - (BYTE) kEplMsgTypeAsnd); + (u8) kEplMsgTypeAsnd); AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_le_bServiceId, - (BYTE) kEplDllAsndNmtRequest); + (u8) kEplDllAsndNmtRequest); AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_Payload. m_NmtRequestService.m_le_bNmtCommandId, - (BYTE) NmtCommand_p); - AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_Payload.m_NmtRequestService.m_le_bTargetNodeId, (BYTE) uiNodeId_p); // target for the nmt command + (u8) NmtCommand_p); + AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_Payload.m_NmtRequestService.m_le_bTargetNodeId, (u8) uiNodeId_p); // target for the nmt command EPL_MEMSET(&NmtRequestFrame.m_Data.m_Asnd.m_Payload.m_NmtRequestService. m_le_abNmtCommandData[0], 0x00, sizeof(NmtRequestFrame.m_Data.m_Asnd.m_Payload. @@ -297,9 +296,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuSendNmtRequest(unsigned int uiNodeId_p, // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC -EplNmtCnuRegisterCheckEventCb(tEplNmtuCheckEventCallback - pfnEplNmtCheckEventCb_p) +tEplKernel EplNmtCnuRegisterCheckEventCb(tEplNmtuCheckEventCallback pfnEplNmtCheckEventCb_p) { tEplKernel Ret; @@ -335,7 +332,7 @@ EplNmtCnuRegisterCheckEventCb(tEplNmtuCheckEventCallback // State: // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplNmtCnuCommandCb(tEplFrameInfo * pFrameInfo_p) +static tEplKernel EplNmtCnuCommandCb(tEplFrameInfo *pFrameInfo_p) { tEplKernel Ret = kEplSuccessful; tEplNmtCommand NmtCommand; @@ -676,18 +673,18 @@ static tEplNmtCommand EplNmtCnuGetNmtCommand(tEplFrameInfo * pFrameInfo_p) // State: // //--------------------------------------------------------------------------- -static BOOL EplNmtCnuNodeIdList(BYTE * pbNmtCommandDate_p) +static BOOL EplNmtCnuNodeIdList(u8 * pbNmtCommandDate_p) { BOOL fNodeIdInList; unsigned int uiByteOffset; - BYTE bBitOffset; - BYTE bNodeListByte; + u8 bBitOffset; + u8 bNodeListByte; // get byte-offset of the own nodeid in NodeIdList // devide though 8 uiByteOffset = (unsigned int)(EplNmtCnuInstance_g.m_uiNodeId >> 3); // get bitoffset - bBitOffset = (BYTE) EplNmtCnuInstance_g.m_uiNodeId % 8; + bBitOffset = (u8) EplNmtCnuInstance_g.m_uiNodeId % 8; bNodeListByte = AmiGetByteFromLe(&pbNmtCommandDate_p[uiByteOffset]); if ((bNodeListByte & bBitOffset) == 0) { diff --git a/drivers/staging/epl/EplNmtMnu.c b/drivers/staging/epl/EplNmtMnu.c index 4ed0b6ce487c..d19434f5f6f8 100644 --- a/drivers/staging/epl/EplNmtMnu.c +++ b/drivers/staging/epl/EplNmtMnu.c @@ -94,8 +94,8 @@ // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); -void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); +void TgtDbgPostTraceValue(u32 dwTraceValue_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) #else @@ -211,8 +211,8 @@ typedef struct { tEplTimerHdl m_TimerHdlStatReq; // timer to delay StatusRequests and IdentRequests tEplTimerHdl m_TimerHdlLonger; // 2nd timer for NMT command EnableReadyToOp and CheckCommunication tEplNmtMnuNodeState m_NodeState; // internal node state (kind of sub state of NMT state) - DWORD m_dwNodeCfg; // subindex from 0x1F81 - WORD m_wFlags; // flags: CN is being accessed isochronously + u32 m_dwNodeCfg; // subindex from 0x1F81 + u16 m_wFlags; // flags: CN is being accessed isochronously } tEplNmtMnuNodeInfo; @@ -224,8 +224,8 @@ typedef struct { unsigned long m_ulStatusRequestDelay; // in [ms] (object 0x1006 * EPL_C_NMT_STATREQ_CYCLE) unsigned long m_ulTimeoutReadyToOp; // in [ms] (object 0x1F89/5) unsigned long m_ulTimeoutCheckCom; // in [ms] (object 0x1006 * MultiplexedCycleCount) - WORD m_wFlags; // global flags - DWORD m_dwNmtStartup; // object 0x1F80 NMT_StartUp_U32 + u16 m_wFlags; // global flags + u32 m_dwNmtStartup; // object 0x1F80 NMT_StartUp_U32 tEplNmtMnuCbNodeEvent m_pfnCbNodeEvent; tEplNmtMnuCbBootEvent m_pfnCbBootEvent; @@ -241,20 +241,18 @@ static tEplNmtMnuInstance EplNmtMnuInstance_g; // local function prototypes //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p); +static tEplKernel EplNmtMnuCbNmtRequest(tEplFrameInfo *pFrameInfo_p); -static tEplKernel PUBLIC EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p, - tEplIdentResponse * - pIdentResponse_p); +static tEplKernel EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p, + tEplIdentResponse *pIdentResponse_p); -static tEplKernel PUBLIC EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p, - tEplStatusResponse * - pStatusResponse_p); +static tEplKernel EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p, + tEplStatusResponse *pStatusResponse_p); static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p, tEplNmtMnuNodeInfo * pNodeInfo_p, tEplNmtState NodeNmtState_p, - WORD wErrorCode_p, + u16 wErrorCode_p, tEplNmtState LocalNmtState_p); static tEplKernel EplNmtMnuStartBootStep1(void); @@ -273,7 +271,7 @@ static tEplKernel EplNmtMnuStartNodes(void); static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p, tEplNmtState NodeNmtState_p, - WORD wErrorCode_p, + u16 wErrorCode_p, tEplNmtMnuIntNodeEvent NodeEvent_p); @@ -380,7 +378,7 @@ tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p, // //--------------------------------------------------------------------------- -tEplKernel EplNmtMnuDelInstance() +tEplKernel EplNmtMnuDelInstance(void) { tEplKernel Ret; @@ -419,7 +417,7 @@ tEplKernel EplNmtMnuSendNmtCommandEx(unsigned int uiNodeId_p, { tEplKernel Ret = kEplSuccessful; tEplFrameInfo FrameInfo; - BYTE abBuffer[EPL_C_DLL_MINSIZE_NMTCMDEXT]; + u8 abBuffer[EPL_C_DLL_MINSIZE_NMTCMDEXT]; tEplFrame *pFrame = (tEplFrame *) abBuffer; BOOL fSoftDeleteNode = FALSE; @@ -439,11 +437,11 @@ tEplKernel EplNmtMnuSendNmtCommandEx(unsigned int uiNodeId_p, // build frame EPL_MEMSET(pFrame, 0x00, sizeof(abBuffer)); - AmiSetByteToLe(&pFrame->m_le_bDstNodeId, (BYTE) uiNodeId_p); + AmiSetByteToLe(&pFrame->m_le_bDstNodeId, (u8) uiNodeId_p); AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId, - (BYTE) kEplDllAsndNmtCommand); + (u8) kEplDllAsndNmtCommand); AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService. - m_le_bNmtCommandId, (BYTE) NmtCommand_p); + m_le_bNmtCommandId, (u8) NmtCommand_p); if ((pNmtCommandData_p != NULL) && (uiDataSize_p > 0)) { // copy command data to frame EPL_MEMCPY(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService. m_le_abNmtCommandData[0], pNmtCommandData_p, @@ -574,8 +572,8 @@ tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p, tEplKernel Ret = kEplSuccessful; tEplNmtMnuIntNodeEvent NodeEvent; tEplObdSize ObdSize; - BYTE bNmtState; - WORD wErrorCode = EPL_E_NO_ERROR; + u8 bNmtState; + u16 wErrorCode = EPL_E_NO_ERROR; if ((uiNodeId_p == 0) || (uiNodeId_p >= EPL_C_ADR_BROADCAST)) { Ret = kEplInvalidNodeId; @@ -645,8 +643,7 @@ tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p, // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange - NmtStateChange_p) +tEplKernel EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p) { tEplKernel Ret = kEplSuccessful; @@ -676,7 +673,7 @@ tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange // build the configuration with infos from OD case kEplNmtGsResetConfiguration: { - DWORD dwTimeout; + u32 dwTimeout; tEplObdSize ObdSize; // read object 0x1F80 NMT_StartUp_U32 @@ -788,7 +785,7 @@ tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange // node processes only async frames case kEplNmtMsPreOperational1: { - DWORD dwTimeout; + u32 dwTimeout; tEplTimerArg TimerArg; tEplObdSize ObdSize; tEplEvent Event; @@ -928,7 +925,7 @@ tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p) +tEplKernel EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p) { tEplKernel Ret = kEplSuccessful; @@ -949,7 +946,7 @@ tEplKernel PUBLIC EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p) // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent(tEplEvent * pEvent_p) +tEplKernel EplNmtMnuProcessEvent(tEplEvent *pEvent_p) { tEplKernel Ret; @@ -970,7 +967,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent(tEplEvent * pEvent_p) EPL_NMTMNU_TIMERARG_NODE_MASK); if (uiNodeId != 0) { tEplObdSize ObdSize; - BYTE bNmtState; + u8 bNmtState; tEplNmtMnuNodeInfo *pNodeInfo; pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId); @@ -1150,7 +1147,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent(tEplEvent * pEvent_p) tEplFrame *pFrame = (tEplFrame *) pEvent_p->m_pArg; unsigned int uiNodeId; tEplNmtCommand NmtCommand; - BYTE bNmtState; + u8 bNmtState; uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId); NmtCommand = @@ -1162,30 +1159,30 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent(tEplEvent * pEvent_p) switch (NmtCommand) { case kEplNmtCmdStartNode: bNmtState = - (BYTE) (kEplNmtCsOperational & 0xFF); + (u8) (kEplNmtCsOperational & 0xFF); break; case kEplNmtCmdStopNode: - bNmtState = (BYTE) (kEplNmtCsStopped & 0xFF); + bNmtState = (u8) (kEplNmtCsStopped & 0xFF); break; case kEplNmtCmdEnterPreOperational2: bNmtState = - (BYTE) (kEplNmtCsPreOperational2 & 0xFF); + (u8) (kEplNmtCsPreOperational2 & 0xFF); break; case kEplNmtCmdEnableReadyToOperate: // d.k. do not change expected node state, because of DS 1.0.0 7.3.1.2.1 Plain NMT State Command // and because node may not change NMT state within EPL_C_NMT_STATE_TOLERANCE bNmtState = - (BYTE) (kEplNmtCsPreOperational2 & 0xFF); + (u8) (kEplNmtCsPreOperational2 & 0xFF); break; case kEplNmtCmdResetNode: case kEplNmtCmdResetCommunication: case kEplNmtCmdResetConfiguration: case kEplNmtCmdSwReset: - bNmtState = (BYTE) (kEplNmtCsNotActive & 0xFF); + bNmtState = (u8) (kEplNmtCsNotActive & 0xFF); // EplNmtMnuProcessInternalEvent() sets internal node state to kEplNmtMnuNodeStateUnknown // after next unresponded IdentRequest/StatusRequest break; @@ -1258,11 +1255,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent(tEplEvent * pEvent_p) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplNmtMnuGetDiagnosticInfo(unsigned int - *puiMandatorySlaveCount_p, - unsigned int - *puiSignalSlaveCount_p, - WORD * pwFlags_p) +tEplKernel EplNmtMnuGetDiagnosticInfo(unsigned int *puiMandatorySlaveCount_p, + unsigned int *puiSignalSlaveCount_p, + u16 *pwFlags_p) { tEplKernel Ret = kEplSuccessful; @@ -1296,7 +1291,7 @@ tEplKernel PUBLIC EplNmtMnuGetDiagnosticInfo(unsigned int // //--------------------------------------------------------------------------- /* -DWORD EplNmtMnuGetRunningTimerStatReq(void) +u32 EplNmtMnuGetRunningTimerStatReq(void) { tEplKernel Ret = kEplSuccessful; unsigned int uiIndex; @@ -1347,7 +1342,7 @@ Exit: // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p) +static tEplKernel EplNmtMnuCbNmtRequest(tEplFrameInfo *pFrameInfo_p) { tEplKernel Ret = kEplSuccessful; @@ -1371,9 +1366,8 @@ static tEplKernel PUBLIC EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p) // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p, - tEplIdentResponse * - pIdentResponse_p) +static tEplKernel EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p, + tEplIdentResponse *pIdentResponse_p) { tEplKernel Ret = kEplSuccessful; @@ -1382,8 +1376,8 @@ static tEplKernel PUBLIC EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p, kEplNmtMnuIntNodeEventNoIdentResponse); } else { // node answered IdentRequest tEplObdSize ObdSize; - DWORD dwDevType; - WORD wErrorCode = EPL_E_NO_ERROR; + u32 dwDevType; + u16 wErrorCode = EPL_E_NO_ERROR; tEplNmtState NmtState = (tEplNmtState) (AmiGetByteFromLe (&pIdentResponse_p-> @@ -1431,9 +1425,8 @@ static tEplKernel PUBLIC EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p, // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p, - tEplStatusResponse * - pStatusResponse_p) +static tEplKernel EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p, + tEplStatusResponse *pStatusResponse_p) { tEplKernel Ret = kEplSuccessful; @@ -1473,7 +1466,7 @@ static tEplKernel EplNmtMnuStartBootStep1(void) tEplKernel Ret = kEplSuccessful; unsigned int uiSubIndex; unsigned int uiLocalNodeId; - DWORD dwNodeCfg; + u32 dwNodeCfg; tEplObdSize ObdSize; // $$$ d.k.: save current time for 0x1F89/2 MNTimeoutPreOp1_U32 @@ -1633,7 +1626,7 @@ static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p, { tEplKernel Ret = kEplSuccessful; tEplDllNodeInfo DllNodeInfo; - DWORD dwNodeCfg; + u32 dwNodeCfg; tEplObdSize ObdSize; tEplTimerArg TimerArg; @@ -1782,7 +1775,7 @@ static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p, tEplNmtMnuNodeInfo * pNodeInfo_p) { tEplKernel Ret = kEplSuccessful; - DWORD dwNodeCfg; + u32 dwNodeCfg; tEplTimerArg TimerArg; dwNodeCfg = pNodeInfo_p->m_dwNodeCfg; @@ -1916,7 +1909,7 @@ static tEplKernel EplNmtMnuStartNodes(void) static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p, tEplNmtState NodeNmtState_p, - WORD wErrorCode_p, + u16 wErrorCode_p, tEplNmtMnuIntNodeEvent NodeEvent_p) { @@ -1934,7 +1927,7 @@ static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p, switch (NodeEvent_p) { case kEplNmtMnuIntNodeEventIdentResponse: { - BYTE bNmtState; + u8 bNmtState; EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, uiNodeId_p, @@ -1961,7 +1954,7 @@ static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p, ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; } // update object 0x1F8F NMT_MNNodeExpState_AU8 to PreOp1 (even if local state >= PreOp2) - bNmtState = (BYTE) (kEplNmtCsPreOperational1 & 0xFF); + bNmtState = (u8) (kEplNmtCsPreOperational1 & 0xFF); Ret = EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 1); @@ -2441,11 +2434,11 @@ static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p, case kEplNmtMnuIntNodeEventNmtCmdSent: { - BYTE bNmtState; + u8 bNmtState; // update expected NMT state with the one that results // from the sent NMT command - bNmtState = (BYTE) (NodeNmtState_p & 0xFF); + bNmtState = (u8) (NodeNmtState_p & 0xFF); // write object 0x1F8F NMT_MNNodeExpState_AU8 Ret = @@ -2630,13 +2623,13 @@ static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p, static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p, tEplNmtMnuNodeInfo * pNodeInfo_p, tEplNmtState NodeNmtState_p, - WORD wErrorCode_p, + u16 wErrorCode_p, tEplNmtState LocalNmtState_p) { tEplKernel Ret = kEplSuccessful; tEplObdSize ObdSize; - BYTE bNmtState; - BYTE bNmtStatePrev; + u8 bNmtState; + u8 bNmtStatePrev; tEplNmtState ExpNmtState; ObdSize = 1; @@ -2647,8 +2640,8 @@ static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p, } // compute expected NMT state ExpNmtState = (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS); - // compute BYTE of current NMT state - bNmtState = ((BYTE) NodeNmtState_p & 0xFF); + // compute u8 of current NMT state + bNmtState = ((u8) NodeNmtState_p & 0xFF); if (ExpNmtState == kEplNmtCsNotActive) { // ignore the current state, because the CN shall be not active Ret = kEplReject; @@ -2706,7 +2699,7 @@ static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p, } else if ((ExpNmtState != NodeNmtState_p) && !((ExpNmtState == kEplNmtCsPreOperational1) && (NodeNmtState_p == kEplNmtCsPreOperational2))) { // CN is not in expected NMT state (without the exceptions above) - WORD wbeErrorCode; + u16 wbeErrorCode; if ((pNodeInfo_p-> m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0) { diff --git a/drivers/staging/epl/EplNmtk.c b/drivers/staging/epl/EplNmtk.c index 4e2d0e15e947..609d5c02bdeb 100644 --- a/drivers/staging/epl/EplNmtk.c +++ b/drivers/staging/epl/EplNmtk.c @@ -88,8 +88,8 @@ // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); -void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); +void TgtDbgPostTraceValue(u32 dwTraceValue_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) #else @@ -107,12 +107,12 @@ void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); // struct for instance table INSTANCE_TYPE_BEGIN EPL_MCO_DECL_INSTANCE_MEMBER() -STATIC volatile tEplNmtState INST_FAR m_NmtState; -STATIC volatile BOOL INST_FAR m_fEnableReadyToOperate; -STATIC volatile BOOL INST_FAR m_fAppReadyToOperate; -STATIC volatile BOOL INST_FAR m_fTimerMsPreOp2; -STATIC volatile BOOL INST_FAR m_fAllMandatoryCNIdent; -STATIC volatile BOOL INST_FAR m_fFrozen; +STATIC volatile tEplNmtState m_NmtState; +STATIC volatile BOOL m_fEnableReadyToOperate; +STATIC volatile BOOL m_fAppReadyToOperate; +STATIC volatile BOOL m_fTimerMsPreOp2; +STATIC volatile BOOL m_fAllMandatoryCNIdent; +STATIC volatile BOOL m_fFrozen; INSTANCE_TYPE_END //--------------------------------------------------------------------------- @@ -121,7 +121,7 @@ INSTANCE_TYPE_END // This macro replace the unspecific pointer to an instance through // the modul specific type for the local instance table. This macro // must defined in each modul. -//#define tEplPtrInstance tEplInstanceInfo MEM* +//#define tEplPtrInstance tEplInstanceInfo* EPL_MCO_DECL_INSTANCE_VAR() //--------------------------------------------------------------------------- // local function prototypes @@ -163,7 +163,7 @@ EPL_MCO_DEFINE_INSTANCE_FCT() // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR) +tEplKernel EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR) { tEplKernel Ret; @@ -189,7 +189,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR) // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) +tEplKernel EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) { EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplKernel Ret; //tEplEvent Event; @@ -258,7 +258,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) // //--------------------------------------------------------------------------- #if (EPL_USE_DELETEINST_FUNC != FALSE) -EPLDLLEXPORT tEplKernel PUBLIC EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) +tEplKernel EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) { tEplKernel Ret = kEplSuccessful; // check for all API function if instance is valid @@ -296,8 +296,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_ - tEplEvent * pEvent_p) +tEplKernel EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplEvent *pEvent_p) { tEplKernel Ret; tEplNmtState OldNmtState; @@ -1804,8 +1803,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplNmtState PUBLIC -EplNmtkGetNmtState(EPL_MCO_DECL_PTR_INSTANCE_PTR) +tEplNmtState EplNmtkGetNmtState(EPL_MCO_DECL_PTR_INSTANCE_PTR) { tEplNmtState NmtState; diff --git a/drivers/staging/epl/EplNmtkCal.c b/drivers/staging/epl/EplNmtkCal.c index 4ad71a71e013..4453c09838cb 100644 --- a/drivers/staging/epl/EplNmtkCal.c +++ b/drivers/staging/epl/EplNmtkCal.c @@ -69,8 +69,6 @@ ****************************************************************************/ -#include "kernel/EplNmtkCal.h" - // TODO: init function needed to prepare EplNmtkGetNmtState for // io-controll-call from EplNmtuCal-Modul diff --git a/drivers/staging/epl/EplNmtu.c b/drivers/staging/epl/EplNmtu.c index 3de16a1eff5e..9ac2e8e4845c 100644 --- a/drivers/staging/epl/EplNmtu.c +++ b/drivers/staging/epl/EplNmtu.c @@ -132,7 +132,7 @@ static tEplNmtuInstance EplNmtuInstance_g; // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuInit() +tEplKernel EplNmtuInit(void) { tEplKernel Ret; @@ -158,7 +158,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtuInit() // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuAddInstance() +tEplKernel EplNmtuAddInstance(void) { tEplKernel Ret; @@ -187,7 +187,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtuAddInstance() // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuDelInstance() +tEplKernel EplNmtuDelInstance(void) { tEplKernel Ret; @@ -219,7 +219,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtuDelInstance() // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p) +tEplKernel EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p) { tEplKernel Ret; tEplEvent Event; @@ -253,7 +253,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p) // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplNmtState PUBLIC EplNmtuGetNmtState() +tEplNmtState EplNmtuGetNmtState(void) { tEplNmtState NmtState; @@ -284,7 +284,7 @@ EPLDLLEXPORT tEplNmtState PUBLIC EplNmtuGetNmtState() // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p) +tEplKernel EplNmtuProcessEvent(tEplEvent *pEplEvent_p) { tEplKernel Ret; @@ -382,7 +382,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p) // node listens for EPL-Frames and check timeout case kEplNmtCsNotActive: { - DWORD dwBuffer; + u32 dwBuffer; tEplObdSize ObdSize; tEplTimerArg TimerArg; @@ -475,7 +475,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p) // node listens for EPL-Frames and check timeout case kEplNmtMsNotActive: { - DWORD dwBuffer; + u32 dwBuffer; tEplObdSize ObdSize; tEplTimerArg TimerArg; @@ -544,7 +544,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p) // node processes only async frames case kEplNmtMsPreOperational1: { - DWORD dwBuffer = 0; + u32 dwBuffer = 0; tEplObdSize ObdSize; tEplTimerArg TimerArg; @@ -664,9 +664,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p) // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC -EplNmtuRegisterStateChangeCb(tEplNmtuStateChangeCallback - pfnEplNmtStateChangeCb_p) +tEplKernel EplNmtuRegisterStateChangeCb(tEplNmtuStateChangeCallback pfnEplNmtStateChangeCb_p) { tEplKernel Ret; diff --git a/drivers/staging/epl/EplNmtuCal.c b/drivers/staging/epl/EplNmtuCal.c index 4a29ef58bf9b..92164c57ea15 100644 --- a/drivers/staging/epl/EplNmtuCal.c +++ b/drivers/staging/epl/EplNmtuCal.c @@ -119,7 +119,7 @@ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplNmtState PUBLIC EplNmtkCalGetNmtState() +tEplNmtState EplNmtkCalGetNmtState(void) { tEplNmtState NmtState; // for test direkt call for EplNmtkGetNmtState() diff --git a/drivers/staging/epl/EplObd.c b/drivers/staging/epl/EplObd.c index efbb1967a5dc..1e463234d81e 100644 --- a/drivers/staging/epl/EplObd.c +++ b/drivers/staging/epl/EplObd.c @@ -101,8 +101,8 @@ // struct for instance table INSTANCE_TYPE_BEGIN EPL_MCO_DECL_INSTANCE_MEMBER() -STATIC tEplObdInitParam INST_FAR m_ObdInitParam; -STATIC tEplObdStoreLoadObjCallback INST_NEAR m_fpStoreLoadObjCallback; +STATIC tEplObdInitParam m_ObdInitParam; +STATIC tEplObdStoreLoadObjCallback m_fpStoreLoadObjCallback; INSTANCE_TYPE_END // decomposition of float @@ -119,11 +119,11 @@ typedef union { // This macro replace the unspecific pointer to an instance through // the modul specific type for the local instance table. This macro // must defined in each modul. -//#define tEplPtrInstance tEplInstanceInfo MEM* +//#define tEplPtrInstance tEplInstanceInfo * EPL_MCO_DECL_INSTANCE_VAR() -BYTE MEM abEplObdTrashObject_g[8]; +u8 abEplObdTrashObject_g[8]; //--------------------------------------------------------------------------- // local function prototypes @@ -133,7 +133,7 @@ EPL_MCO_DEFINE_INSTANCE_FCT() static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdCallback fpCallback_p, - tEplObdCbParam MEM * pCbParam_p); + tEplObdCbParam *pCbParam_p); static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p); @@ -146,7 +146,7 @@ static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p, #endif static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p, - tEplObdVarEntry MEM ** ppVarEntry_p); + tEplObdVarEntry **ppVarEntry_p); static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, @@ -156,7 +156,7 @@ static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_ static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p); -static tEplKernel EplObdGetIndexIntern(tEplObdInitParam MEM * pInitParam_p, +static tEplKernel EplObdGetIndexIntern(tEplObdInitParam *pInitParam_p, unsigned int uiIndex_p, tEplObdEntryPtr * ppObdEntry_p); @@ -170,17 +170,15 @@ static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdDir Direction_p); static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p); -static void MEM *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p); +static void *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p); #if (EPL_OBD_USE_STORE_RESTORE != FALSE) -static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdCbStoreParam MEM * - pCbStoreParam_p); +static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdCbStoreParam *pCbStoreParam_p); #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE) -static void EplObdCopyObjectData(void MEM * pDstData_p, +static void EplObdCopyObjectData(void *pDstData_p, void *pSrcData_p, tEplObdSize ObjSize_p, tEplObdType ObjType_p); @@ -189,24 +187,22 @@ void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p); static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p, BOOL * pfEntryNumerical_p); -static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - void **ppDstData_p, - tEplObdSize Size_p, - tEplObdEntryPtr * ppObdEntry_p, - tEplObdSubEntryPtr * ppSubEntry_p, - tEplObdCbParam MEM * pCbParam_p, - tEplObdSize * pObdSize_p); +static tEplKernel EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, + void **ppDstData_p, + tEplObdSize Size_p, + tEplObdEntryPtr *ppObdEntry_p, + tEplObdSubEntryPtr *ppSubEntry_p, + tEplObdCbParam *pCbParam_p, + tEplObdSize *pObdSize_p); -static tEplKernel PUBLIC EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdEntryPtr pObdEntry_p, - tEplObdSubEntryPtr pSubEntry_p, - tEplObdCbParam MEM * pCbParam_p, - void *pSrcData_p, - void *pDstData_p, - tEplObdSize ObdSize_p); +static tEplKernel EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pObdEntry_p, + tEplObdSubEntryPtr pSubEntry_p, + tEplObdCbParam *pCbParam_p, + void *pSrcData_p, + void *pDstData_p, + tEplObdSize ObdSize_p); //=========================================================================// // // @@ -228,8 +224,7 @@ static tEplKernel PUBLIC EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_ - tEplObdInitParam MEM * pInitParam_p) +tEplKernel EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplObdInitParam *pInitParam_p) { tEplKernel Ret; @@ -261,9 +256,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_ // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_ - tEplObdInitParam MEM * - pInitParam_p) +tEplKernel EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplObdInitParam *pInitParam_p) { EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplKernel Ret; @@ -308,7 +301,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_ // //--------------------------------------------------------------------------- #if (EPL_USE_DELETEINST_FUNC != FALSE) -EPLDLLEXPORT tEplKernel PUBLIC EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR) +tEplKernel EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR) { // check for all API function if instance is valid EPL_MCO_CHECK_INSTANCE_STATE(); @@ -341,18 +334,16 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR) // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p) +tEplKernel EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, tEplObdSize Size_p) { tEplKernel Ret; tEplObdEntryPtr pObdEntry; tEplObdSubEntryPtr pSubEntry; - tEplObdCbParam MEM CbParam; - void MEM *pDstData; + tEplObdCbParam CbParam; + void *pDstData; tEplObdSize ObdSize; Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_ @@ -402,17 +393,15 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_ // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p) +tEplKernel EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, tEplObdSize *pSize_p) { tEplKernel Ret; tEplObdEntryPtr pObdEntry; tEplObdSubEntryPtr pSubEntry; - tEplObdCbParam MEM CbParam; + tEplObdCbParam CbParam; void *pSrcData; tEplObdSize ObdSize; @@ -487,9 +476,8 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_ // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdPart ObdPart_p, - tEplObdDir Direction_p) +tEplKernel EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdPart ObdPart_p, + tEplObdDir Direction_p) { tEplKernel Ret = kEplSuccessful; @@ -587,12 +575,11 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_ // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_ - tEplVarParam MEM * pVarParam_p) +tEplKernel EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_ tEplVarParam *pVarParam_p) { tEplKernel Ret; - tEplObdVarEntry MEM *pVarEntry; + tEplObdVarEntry *pVarEntry; tEplVarParamValid VarValid; tEplObdSubEntryPtr pSubindexEntry; @@ -674,9 +661,8 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_ // //--------------------------------------------------------------------------- -EPLDLLEXPORT void *PUBLIC EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p) +void *EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p) { tEplKernel Ret; void *pData; @@ -719,8 +705,7 @@ EPLDLLEXPORT void *PUBLIC EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdEntryPtr pUserOd_p) +tEplKernel EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pUserOd_p) { EPL_MCO_CHECK_INSTANCE_STATE(); @@ -749,10 +734,8 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_ // //--------------------------------------------------------------------------- -EPLDLLEXPORT void PUBLIC EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdVarEntry MEM * pVarEntry_p, - tEplObdType Type_p, - tEplObdSize ObdSize_p) +void EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdVarEntry *pVarEntry_p, + tEplObdType Type_p, tEplObdSize ObdSize_p) { /* #if (EPL_PDO_USE_STATIC_MAPPING == FALSE) @@ -803,9 +786,8 @@ EPLDLLEXPORT void PUBLIC EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplObdSize PUBLIC EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p) +tEplObdSize EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p) { tEplKernel Ret; tEplObdSize ObdSize; @@ -845,11 +827,11 @@ EPLDLLEXPORT tEplObdSize PUBLIC EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT unsigned int PUBLIC EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR) +unsigned int EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR) { tEplKernel Ret; tEplObdSize ObdSize; - BYTE bNodeId; + u8 bNodeId; bNodeId = 0; ObdSize = sizeof(bNodeId); @@ -882,22 +864,21 @@ EPLDLLEXPORT unsigned int PUBLIC EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR) // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_ - unsigned int uiNodeId_p, - tEplObdNodeIdType NodeIdType_p) +tEplKernel EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_ unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p) { tEplKernel Ret; tEplObdSize ObdSize; - BYTE fHwBool; - BYTE bNodeId; + u8 fHwBool; + u8 bNodeId; // check Node Id if (uiNodeId_p == EPL_C_ADR_INVALID) { Ret = kEplInvalidNodeId; goto Exit; } - bNodeId = (BYTE) uiNodeId_p; - ObdSize = sizeof(BYTE); + bNodeId = (u8) uiNodeId_p; + ObdSize = sizeof(u8); // write NodeId to OD entry Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR_ EPL_OBD_NODE_ID_INDEX, @@ -966,10 +947,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - BOOL * pfEntryNumerical_p) +tEplKernel EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + BOOL *pfEntryNumerical_p) { tEplKernel Ret; tEplObdEntryPtr pObdEntry; @@ -1018,16 +998,14 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p) +tEplKernel EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, tEplObdSize *pSize_p) { tEplKernel Ret; tEplObdEntryPtr pObdEntry; tEplObdSubEntryPtr pSubEntry; - tEplObdCbParam MEM CbParam; + tEplObdCbParam CbParam; void *pSrcData; tEplObdSize ObdSize; @@ -1091,7 +1069,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt8: case kEplObdTypUInt8: { - AmiSetByteToLe(pDstData_p, *((BYTE *) pSrcData)); + AmiSetByteToLe(pDstData_p, *((u8 *) pSrcData)); break; } @@ -1099,7 +1077,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt16: case kEplObdTypUInt16: { - AmiSetWordToLe(pDstData_p, *((WORD *) pSrcData)); + AmiSetWordToLe(pDstData_p, *((u16 *) pSrcData)); break; } @@ -1107,7 +1085,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt24: case kEplObdTypUInt24: { - AmiSetDword24ToLe(pDstData_p, *((DWORD *) pSrcData)); + AmiSetDword24ToLe(pDstData_p, *((u32 *) pSrcData)); break; } @@ -1116,7 +1094,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypUInt32: case kEplObdTypReal32: { - AmiSetDwordToLe(pDstData_p, *((DWORD *) pSrcData)); + AmiSetDwordToLe(pDstData_p, *((u32 *) pSrcData)); break; } @@ -1124,7 +1102,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt40: case kEplObdTypUInt40: { - AmiSetQword40ToLe(pDstData_p, *((QWORD *) pSrcData)); + AmiSetQword40ToLe(pDstData_p, *((u64 *) pSrcData)); break; } @@ -1132,7 +1110,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt48: case kEplObdTypUInt48: { - AmiSetQword48ToLe(pDstData_p, *((QWORD *) pSrcData)); + AmiSetQword48ToLe(pDstData_p, *((u64 *) pSrcData)); break; } @@ -1140,7 +1118,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt56: case kEplObdTypUInt56: { - AmiSetQword56ToLe(pDstData_p, *((QWORD *) pSrcData)); + AmiSetQword56ToLe(pDstData_p, *((u64 *) pSrcData)); break; } @@ -1149,7 +1127,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypUInt64: case kEplObdTypReal64: { - AmiSetQword64ToLe(pDstData_p, *((QWORD *) pSrcData)); + AmiSetQword64ToLe(pDstData_p, *((u64 *) pSrcData)); break; } @@ -1199,19 +1177,17 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p) +tEplKernel EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, tEplObdSize Size_p) { tEplKernel Ret; tEplObdEntryPtr pObdEntry; tEplObdSubEntryPtr pSubEntry; - tEplObdCbParam MEM CbParam; - void MEM *pDstData; + tEplObdCbParam CbParam; + void *pDstData; tEplObdSize ObdSize; - QWORD qwBuffer; + u64 qwBuffer; void *pBuffer = &qwBuffer; Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_ @@ -1242,7 +1218,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt8: case kEplObdTypUInt8: { - *((BYTE *) pBuffer) = AmiGetByteFromLe(pSrcData_p); + *((u8 *) pBuffer) = AmiGetByteFromLe(pSrcData_p); break; } @@ -1250,7 +1226,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt16: case kEplObdTypUInt16: { - *((WORD *) pBuffer) = AmiGetWordFromLe(pSrcData_p); + *((u16 *) pBuffer) = AmiGetWordFromLe(pSrcData_p); break; } @@ -1258,7 +1234,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt24: case kEplObdTypUInt24: { - *((DWORD *) pBuffer) = AmiGetDword24FromLe(pSrcData_p); + *((u32 *) pBuffer) = AmiGetDword24FromLe(pSrcData_p); break; } @@ -1267,7 +1243,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypUInt32: case kEplObdTypReal32: { - *((DWORD *) pBuffer) = AmiGetDwordFromLe(pSrcData_p); + *((u32 *) pBuffer) = AmiGetDwordFromLe(pSrcData_p); break; } @@ -1275,7 +1251,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt40: case kEplObdTypUInt40: { - *((QWORD *) pBuffer) = AmiGetQword40FromLe(pSrcData_p); + *((u64 *) pBuffer) = AmiGetQword40FromLe(pSrcData_p); break; } @@ -1283,7 +1259,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt48: case kEplObdTypUInt48: { - *((QWORD *) pBuffer) = AmiGetQword48FromLe(pSrcData_p); + *((u64 *) pBuffer) = AmiGetQword48FromLe(pSrcData_p); break; } @@ -1291,7 +1267,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypInt56: case kEplObdTypUInt56: { - *((QWORD *) pBuffer) = AmiGetQword56FromLe(pSrcData_p); + *((u64 *) pBuffer) = AmiGetQword56FromLe(pSrcData_p); break; } @@ -1300,7 +1276,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ case kEplObdTypUInt64: case kEplObdTypReal64: { - *((QWORD *) pBuffer) = AmiGetQword64FromLe(pSrcData_p); + *((u64 *) pBuffer) = AmiGetQword64FromLe(pSrcData_p); break; } @@ -1345,10 +1321,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - tEplObdAccess * pAccessTyp_p) +tEplKernel EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess *pAccessTyp_p) { tEplKernel Ret; tEplObdEntryPtr pObdEntry; @@ -1388,10 +1363,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubindex_p, - tEplObdVarEntry MEM ** ppVarEntry_p) +tEplKernel EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry **ppVarEntry_p) { tEplKernel Ret; @@ -1435,11 +1409,11 @@ EPL_MCO_DECL_INSTANCE_FCT() //--------------------------------------------------------------------------- static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdCallback fpCallback_p, - tEplObdCbParam MEM * pCbParam_p) + tEplObdCbParam *pCbParam_p) { tEplKernel Ret; - tEplObdCallback MEM fpCallback; + tEplObdCallback fpCallback; // check for all API function if instance is valid EPL_MCO_CHECK_INSTANCE_STATE(); @@ -1481,7 +1455,7 @@ static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p) { tEplObdSize DataSize; - void MEM *pData; + void *pData; // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING // then the current pointer is always NULL. The function @@ -1490,8 +1464,7 @@ static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p) if (pSubIndexEntry_p->m_Type == kEplObdTypVString) { // The pointer to current value can be received from EplObdGetObjectCurrentPtr() - pData = - ((void MEM *)EplObdGetObjectCurrentPtr(pSubIndexEntry_p)); + pData = ((void *)EplObdGetObjectCurrentPtr(pSubIndexEntry_p)); if (pData != NULL) { DataSize = EplObdGetStrLen((void *)pData, DataSize, @@ -1526,7 +1499,7 @@ static tEplObdSize EplObdGetStrLen(void *pObjData_p, { tEplObdSize StrLen = 0; - BYTE *pbString; + u8 *pbString; if (pObjData_p == NULL) { goto Exit; @@ -1763,18 +1736,18 @@ static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p, case kEplObdTypInt64: // switch to lower limit - pRangeData = ((signed QWORD *)pRangeData) + 1; + pRangeData = ((signed u64 *)pRangeData) + 1; // check if value is to low - if (*((signed QWORD *)pData_p) < *((signed QWORD *)pRangeData)) { + if (*((signed u64 *)pData_p) < *((signed u64 *)pRangeData)) { Ret = kEplObdValueTooLow; break; } // switch to higher limit - pRangeData = ((signed QWORD *)pRangeData) + 1; + pRangeData = ((signed u64 *)pRangeData) + 1; // check if value is to high - if (*((signed QWORD *)pData_p) > *((signed QWORD *)pRangeData)) { + if (*((signed u64 *)pData_p) > *((signed u64 *)pRangeData)) { Ret = kEplObdValueTooHigh; } @@ -1787,20 +1760,20 @@ static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p, case kEplObdTypUInt64: // switch to lower limit - pRangeData = ((unsigned QWORD *)pRangeData) + 1; + pRangeData = ((unsigned u64 *)pRangeData) + 1; // check if value is to low - if (*((unsigned QWORD *)pData_p) < - *((unsigned QWORD *)pRangeData)) { + if (*((unsigned u64 *)pData_p) < + *((unsigned u64 *)pRangeData)) { Ret = kEplObdValueTooLow; break; } // switch to higher limit - pRangeData = ((unsigned QWORD *)pRangeData) + 1; + pRangeData = ((unsigned u64 *)pRangeData) + 1; // check if value is to high - if (*((unsigned QWORD *)pData_p) > - *((unsigned QWORD *)pRangeData)) { + if (*((unsigned u64 *)pData_p) > + *((unsigned u64 *)pRangeData)) { Ret = kEplObdValueTooHigh; } @@ -1870,29 +1843,28 @@ static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p, // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - void **ppDstData_p, - tEplObdSize Size_p, - tEplObdEntryPtr * ppObdEntry_p, - tEplObdSubEntryPtr * ppSubEntry_p, - tEplObdCbParam MEM * pCbParam_p, - tEplObdSize * pObdSize_p) +static tEplKernel EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, + void **ppDstData_p, + tEplObdSize Size_p, + tEplObdEntryPtr *ppObdEntry_p, + tEplObdSubEntryPtr *ppSubEntry_p, + tEplObdCbParam *pCbParam_p, + tEplObdSize *pObdSize_p) { tEplKernel Ret; tEplObdEntryPtr pObdEntry; tEplObdSubEntryPtr pSubEntry; tEplObdAccess Access; - void MEM *pDstData; + void *pDstData; tEplObdSize ObdSize; BOOL fEntryNumerical; #if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE) - tEplObdVStringDomain MEM MemVStringDomain; - void MEM *pCurrData; + tEplObdVStringDomain MemVStringDomain; + void *pCurrData; #endif // check for all API function if instance is valid @@ -1908,7 +1880,7 @@ static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ goto Exit; } // get pointer to object data - pDstData = (void MEM *)EplObdGetObjectDataPtrIntern(pSubEntry); + pDstData = (void *)EplObdGetObjectDataPtrIntern(pSubEntry); Access = (tEplObdAccess) pSubEntry->m_Access; @@ -1933,7 +1905,7 @@ static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ // adapted by user callback function, re-read // this values. ObdSize = EplObdGetObjectSize(pSubEntry); - pDstData = (void MEM *)EplObdGetObjectDataPtrIntern(pSubEntry); + pDstData = (void *)EplObdGetObjectDataPtrIntern(pSubEntry); // 09-dec-2004 r.d.: // Function EplObdWriteEntry() calls new event kEplObdEvWrStringDomain @@ -1967,23 +1939,19 @@ static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ pCurrData = pSubEntry->m_pCurrent; if ((pSubEntry->m_Type == kEplObdTypVString) || (pSubEntry->m_Type == kEplObdTypOString)) { - ((tEplObdVString MEM *) pCurrData)->m_Size = - MemVStringDomain.m_ObjSize; - ((tEplObdVString MEM *) pCurrData)->m_pString = - MemVStringDomain.m_pData; + ((tEplObdVString *)pCurrData)->m_Size = MemVStringDomain.m_ObjSize; + ((tEplObdVString *)pCurrData)->m_pString = MemVStringDomain.m_pData; } else // if (pSdosTableEntry_p->m_bObjType == kEplObdTypDomain) { - ((tEplObdVarEntry MEM *) pCurrData)->m_Size = - MemVStringDomain.m_ObjSize; - ((tEplObdVarEntry MEM *) pCurrData)->m_pData = - (void MEM *)MemVStringDomain.m_pData; + ((tEplObdVarEntry *)pCurrData)->m_Size = MemVStringDomain.m_ObjSize; + ((tEplObdVarEntry *)pCurrData)->m_pData = (void *)MemVStringDomain.m_pData; } // Because object size and object pointer are // adapted by user callback function, re-read // this values. ObdSize = MemVStringDomain.m_ObjSize; - pDstData = (void MEM *)MemVStringDomain.m_pData; + pDstData = (void *)MemVStringDomain.m_pData; } #endif //#if (OBD_USE_STRING_DOMAIN_IN_RAM != FALSE) @@ -2004,7 +1972,7 @@ static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ } if (pSubEntry->m_Type == kEplObdTypVString) { - if (((char MEM *)pSrcData_p)[Size_p - 1] == '\0') { // last byte of source string contains null character + if (((char *)pSrcData_p)[Size_p - 1] == '\0') { // last byte of source string contains null character // reserve one byte in destination for 0-termination Size_p -= 1; @@ -2064,13 +2032,12 @@ static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_ // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdEntryPtr pObdEntry_p, - tEplObdSubEntryPtr pSubEntry_p, - tEplObdCbParam MEM * pCbParam_p, - void *pSrcData_p, - void *pDstData_p, - tEplObdSize ObdSize_p) +static tEplKernel EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pObdEntry_p, + tEplObdSubEntryPtr pSubEntry_p, + tEplObdCbParam *pCbParam_p, + void *pSrcData_p, + void *pDstData_p, + tEplObdSize ObdSize_p) { tEplKernel Ret; @@ -2103,7 +2070,7 @@ static tEplKernel PUBLIC EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ // terminate string with 0 if (pSubEntry_p->m_Type == kEplObdTypVString) { - ((char MEM *)pDstData_p)[ObdSize_p] = '\0'; + ((char *)pDstData_p)[ObdSize_p] = '\0'; } // write address of destination to structure of callback parameters // so callback function can change data subsequently @@ -2123,7 +2090,7 @@ static tEplKernel PUBLIC EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_ // Function: EplObdGetObjectSize() // // Description: function to get size of object -// The function determines if an object type an fixed data type (BYTE, WORD, ...) +// The function determines if an object type an fixed data type (u8, u16, ...) // or non fixed object (string, domain). This information is used to decide // if download data are stored temporary or not. For objects with fixed data length // and types a value range checking can process. @@ -2192,8 +2159,8 @@ static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p) case kEplObdTypDomain: pData = (void *)pSubIndexEntry_p->m_pCurrent; - if ((void MEM *)pData != (void MEM *)NULL) { - DataSize = ((tEplObdVarEntry MEM *) pData)->m_Size; + if ((void *)pData != (void *)NULL) { + DataSize = ((tEplObdVarEntry *) pData)->m_Size; } break; @@ -2205,21 +2172,19 @@ static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p) // then the current pointer is always NULL. The function // returns the length of default string. pData = (void *)pSubIndexEntry_p->m_pCurrent; - if ((void MEM *)pData != (void MEM *)NULL) { + if ((void *)pData != (void *)NULL) { // The max. size of strings defined by STRING-Macro is stored in // tEplObdVString of current value. // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members) - DataSize = ((tEplObdVString MEM *) pData)->m_Size; + DataSize = ((tEplObdVString *) pData)->m_Size; } else { // The current position is not decleared. The string // is located in ROM, therefor use default pointer. pData = (void *)pSubIndexEntry_p->m_pDefault; - if ((CONST void ROM *)pData != (CONST void ROM *)NULL) { + if ((const void *)pData != (const void *)NULL) { // The max. size of strings defined by STRING-Macro is stored in // tEplObdVString of default value. - DataSize = - ((CONST tEplObdVString ROM *) pData)-> - m_Size; + DataSize = ((const tEplObdVString *)pData)->m_Size; } } @@ -2229,21 +2194,19 @@ static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p) case kEplObdTypOString: pData = (void *)pSubIndexEntry_p->m_pCurrent; - if ((void MEM *)pData != (void MEM *)NULL) { + if ((void *)pData != (void *)NULL) { // The max. size of strings defined by STRING-Macro is stored in // tEplObdVString of current value. // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members) - DataSize = ((tEplObdOString MEM *) pData)->m_Size; + DataSize = ((tEplObdOString *) pData)->m_Size; } else { // The current position is not decleared. The string // is located in ROM, therefor use default pointer. pData = (void *)pSubIndexEntry_p->m_pDefault; - if ((CONST void ROM *)pData != (CONST void ROM *)NULL) { + if ((const void *)pData != (const void *)NULL) { // The max. size of strings defined by STRING-Macro is stored in // tEplObdVString of default value. - DataSize = - ((CONST tEplObdOString ROM *) pData)-> - m_Size; + DataSize = ((const tEplObdOString *)pData)->m_Size; } } break; @@ -2366,7 +2329,7 @@ static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p) //--------------------------------------------------------------------------- static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p, - tEplObdVarEntry MEM ** ppVarEntry_p) + tEplObdVarEntry **ppVarEntry_p) { tEplKernel Ret = kEplObdVarEntryNotExist; @@ -2378,13 +2341,9 @@ static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p, if ((pSubindexEntry_p->m_Access & kEplObdAccVar) != 0) { // check if object is an array if ((pSubindexEntry_p->m_Access & kEplObdAccArray) != 0) { - *ppVarEntry_p = - &((tEplObdVarEntry MEM *) pSubindexEntry_p-> - m_pCurrent)[pSubindexEntry_p->m_uiSubIndex - 1]; + *ppVarEntry_p = &((tEplObdVarEntry *)pSubindexEntry_p->m_pCurrent)[pSubindexEntry_p->m_uiSubIndex - 1]; } else { - *ppVarEntry_p = - (tEplObdVarEntry MEM *) pSubindexEntry_p-> - m_pCurrent; + *ppVarEntry_p = (tEplObdVarEntry *)pSubindexEntry_p->m_pCurrent; } Ret = kEplSuccessful; @@ -2420,7 +2379,7 @@ static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_ { tEplObdEntryPtr pObdEntry; - tEplObdCbParam MEM CbParam; + tEplObdCbParam CbParam; tEplKernel Ret; // check for all API function if instance is valid @@ -2474,16 +2433,16 @@ static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_ // // Parameters: pSubIndexEntry_p // -// Return: void MEM* +// Return: void * // // State: // //--------------------------------------------------------------------------- -static void MEM *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p) +static void *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p) { - void MEM *pData; + void *pData; unsigned int uiArrayIndex; tEplObdSize Size; @@ -2500,24 +2459,21 @@ static void MEM *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p) } else { Size = EplObdGetObjectSize(pSubIndexEntry_p); } - pData = ((BYTE MEM *) pData) + (Size * uiArrayIndex); + pData = ((u8 *) pData) + (Size * uiArrayIndex); } // check if VarEntry if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) { // The data pointer is stored in VarEntry->pData - pData = ((tEplObdVarEntry MEM *) pData)->m_pData; + pData = ((tEplObdVarEntry *) pData)->m_pData; } // the default pointer is stored for strings in tEplObdVString else if ((pSubIndexEntry_p->m_Type == kEplObdTypVString) /* || (pSubIndexEntry_p->m_Type == kEplObdTypUString) */ ) { - pData = - (void MEM *)((tEplObdVString MEM *) pData)-> - m_pString; + pData = (void *)((tEplObdVString *)pData)->m_pString; } else if (pSubIndexEntry_p->m_Type == kEplObdTypOString) { pData = - (void MEM *)((tEplObdOString MEM *) pData)-> - m_pString; + (void *)((tEplObdOString *)pData)->m_pString; } } @@ -2541,7 +2497,7 @@ static void MEM *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p) // //--------------------------------------------------------------------------- -static tEplKernel EplObdGetIndexIntern(tEplObdInitParam MEM * pInitParam_p, +static tEplKernel EplObdGetIndexIntern(tEplObdInitParam *pInitParam_p, unsigned int uiIndex_p, tEplObdEntryPtr * ppObdEntry_p) { @@ -2762,9 +2718,7 @@ static tEplKernel EplObdGetSubindexIntern(tEplObdEntryPtr pObdEntry_p, // //--------------------------------------------------------------------------- #if (EPL_OBD_USE_STORE_RESTORE != FALSE) -EPLDLLEXPORT tEplKernel PUBLIC -EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdStoreLoadObjCallback fpCallback_p) +tEplKernel EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdStoreLoadObjCallback fpCallback_p) { EPL_MCO_CHECK_INSTANCE_STATE(); @@ -2802,26 +2756,26 @@ static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdSubEntryPtr pSubIndex; unsigned int nSubIndexCount; tEplObdAccess Access; - void MEM *pDstData; + void *pDstData; void *pDefault; tEplObdSize ObjSize; tEplKernel Ret; - tEplObdCbStoreParam MEM CbStore; - tEplObdVarEntry MEM *pVarEntry; + tEplObdCbStoreParam CbStore; + tEplObdVarEntry *pVarEntry; ASSERT(pObdEnty_p != NULL); Ret = kEplSuccessful; // prepare structure for STORE RESTORE callback function - CbStore.m_bCurrentOdPart = (BYTE) CurrentOdPart_p; + CbStore.m_bCurrentOdPart = (u8) CurrentOdPart_p; CbStore.m_pData = NULL; CbStore.m_ObjSize = 0; // command of first action depends on direction to access #if (EPL_OBD_USE_STORE_RESTORE != FALSE) if (Direction_p == kEplObdDirLoad) { - CbStore.m_bCommand = (BYTE) kEplObdCommOpenRead; + CbStore.m_bCommand = (u8) kEplObdCommOpenRead; // call callback function for previous command Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore); @@ -2829,9 +2783,9 @@ static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_ goto Exit; } // set command for index and subindex loop - CbStore.m_bCommand = (BYTE) kEplObdCommReadObj; + CbStore.m_bCommand = (u8) kEplObdCommReadObj; } else if (Direction_p == kEplObdDirStore) { - CbStore.m_bCommand = (BYTE) kEplObdCommOpenWrite; + CbStore.m_bCommand = (u8) kEplObdCommOpenWrite; // call callback function for previous command Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore); @@ -2839,7 +2793,7 @@ static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_ goto Exit; } // set command for index and subindex loop - CbStore.m_bCommand = (BYTE) kEplObdCommWriteObj; + CbStore.m_bCommand = (u8) kEplObdCommWriteObj; } #endif // (EPL_OBD_USE_STORE_RESTORE != FALSE) @@ -2890,7 +2844,7 @@ static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_ } else { - EplObdInitVarEntry ((tEplObdVarEntry MEM*) (((BYTE MEM*) pSubIndex->m_pCurrent) + (sizeof (tEplObdVarEntry) * pSubIndex->m_uiSubIndex)), + EplObdInitVarEntry ((tEplObdVarEntry *) (((u8 *) pSubIndex->m_pCurrent) + (sizeof (tEplObdVarEntry) * pSubIndex->m_uiSubIndex)), pSubIndex->m_Type, ObjSize); } */ @@ -2911,29 +2865,17 @@ static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_ pSubIndex->m_pCurrent; if (pDstData != NULL) { // 08-dec-2004: code optimization !!! - // entries ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_pString - // and ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read + // entries ((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_pString + // and ((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_Size were read // twice. thats not necessary! // For copying data we have to set the destination pointer to the real RAM string. This // pointer to RAM string is located in default string info structure. (translated r.d.) - pDstData = - (void MEM - *)((tEplObdVStringDef ROM *) pSubIndex->m_pDefault)->m_pString; - ObjSize = - ((tEplObdVStringDef - ROM *) pSubIndex-> - m_pDefault)-> - m_Size; + pDstData = (void *)((tEplObdVStringDef*) pSubIndex->m_pDefault)->m_pString; + ObjSize = ((tEplObdVStringDef *)pSubIndex->m_pDefault)->m_Size; - ((tEplObdVString MEM *) - pSubIndex-> - m_pCurrent)-> - m_pString = pDstData; - ((tEplObdVString MEM *) - pSubIndex-> - m_pCurrent)->m_Size = - ObjSize; + ((tEplObdVString *)pSubIndex->m_pCurrent)->m_pString = pDstData; + ((tEplObdVString *)pSubIndex->m_pCurrent)->m_Size = ObjSize; } } else if (pSubIndex->m_Type == @@ -2942,29 +2884,17 @@ static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_ pSubIndex->m_pCurrent; if (pDstData != NULL) { // 08-dec-2004: code optimization !!! - // entries ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_pString - // and ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read + // entries ((tEplObdOStringDef*) pSubIndex->m_pDefault)->m_pString + // and ((tEplObdOStringDef*) pSubIndex->m_pDefault)->m_Size were read // twice. thats not necessary! // For copying data we have to set the destination pointer to the real RAM string. This // pointer to RAM string is located in default string info structure. (translated r.d.) - pDstData = - (void MEM - *)((tEplObdOStringDef ROM *) pSubIndex->m_pDefault)->m_pString; - ObjSize = - ((tEplObdOStringDef - ROM *) pSubIndex-> - m_pDefault)-> - m_Size; + pDstData = (void *)((tEplObdOStringDef *) pSubIndex->m_pDefault)->m_pString; + ObjSize = ((tEplObdOStringDef *)pSubIndex->m_pDefault)->m_Size; - ((tEplObdOString MEM *) - pSubIndex-> - m_pCurrent)-> - m_pString = pDstData; - ((tEplObdOString MEM *) - pSubIndex-> - m_pCurrent)->m_Size = - ObjSize; + ((tEplObdOString *)pSubIndex->m_pCurrent)->m_pString = pDstData; + ((tEplObdOString *)pSubIndex->m_pCurrent)->m_Size = ObjSize; } } @@ -3069,11 +2999,11 @@ static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_ #if (EPL_OBD_USE_STORE_RESTORE != FALSE) else { if (Direction_p == kEplObdDirLoad) { - CbStore.m_bCommand = (BYTE) kEplObdCommCloseRead; + CbStore.m_bCommand = (u8) kEplObdCommCloseRead; } else if (Direction_p == kEplObdDirStore) { - CbStore.m_bCommand = (BYTE) kEplObdCommCloseWrite; + CbStore.m_bCommand = (u8) kEplObdCommCloseWrite; } else if (Direction_p == kEplObdDirRestore) { - CbStore.m_bCommand = (BYTE) kEplObdCommClear; + CbStore.m_bCommand = (u8) kEplObdCommClear; } else { goto Exit; } @@ -3104,7 +3034,7 @@ static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_ // Returns: tEplKernel = error code // ---------------------------------------------------------------------------- -static void EplObdCopyObjectData(void MEM * pDstData_p, +static void EplObdCopyObjectData(void *pDstData_p, void *pSrcData_p, tEplObdSize ObjSize_p, tEplObdType ObjType_p) { @@ -3135,7 +3065,7 @@ static void EplObdCopyObjectData(void MEM * pDstData_p, EPL_MEMCPY(pDstData_p, pSrcData_p, ObjSize_p); if (ObjType_p == kEplObdTypVString) { - ((char MEM *)pDstData_p)[StrSize] = '\0'; + ((char *)pDstData_p)[StrSize] = '\0'; } } } @@ -3196,7 +3126,7 @@ static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p, // ---------------------------------------------------------------------------- #if (EPL_OBD_USE_STORE_RESTORE != FALSE) static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdCbStoreParam MEM * + tEplObdCbStoreParam * pCbStoreParam_p) { diff --git a/drivers/staging/epl/EplObd.h b/drivers/staging/epl/EplObd.h index 88cc11e34ccd..6bb5a2780686 100644 --- a/drivers/staging/epl/EplObd.h +++ b/drivers/staging/epl/EplObd.h @@ -68,11 +68,11 @@ ****************************************************************************/ -#include "EplInc.h" - #ifndef _EPLOBD_H_ #define _EPLOBD_H_ +#include "EplInc.h" + // ============================================================================ // defines // ============================================================================ @@ -206,7 +206,7 @@ typedef unsigned int tEplObdSize; // For all objects as objects size are used an // ------------------------------------------------------------------------- // types of objects in object dictionary -// DS-301 defines these types as WORD +// DS-301 defines these types as u16 typedef enum { // types which are always supported kEplObdTypBool = 0x0001, @@ -255,15 +255,15 @@ typedef unsigned char tEplObdDomain; // 000F typedef signed long tEplObdInteger24; // 0010 typedef unsigned long tEplObdUnsigned24; // 0016 -typedef signed QWORD tEplObdInteger40; // 0012 -typedef signed QWORD tEplObdInteger48; // 0013 -typedef signed QWORD tEplObdInteger56; // 0014 -typedef signed QWORD tEplObdInteger64; // 0015 +typedef s64 tEplObdInteger40; // 0012 +typedef s64 tEplObdInteger48; // 0013 +typedef s64 tEplObdInteger56; // 0014 +typedef s64 tEplObdInteger64; // 0015 -typedef unsigned QWORD tEplObdUnsigned40; // 0018 -typedef unsigned QWORD tEplObdUnsigned48; // 0019 -typedef unsigned QWORD tEplObdUnsigned56; // 001A -typedef unsigned QWORD tEplObdUnsigned64; // 001B +typedef u64 tEplObdUnsigned40; // 0018 +typedef u64 tEplObdUnsigned48; // 0019 +typedef u64 tEplObdUnsigned56; // 001A +typedef u64 tEplObdUnsigned64; // 001B typedef double tEplObdReal64; // 0011 @@ -283,22 +283,21 @@ typedef enum { kVarValidAll = 0x03 // currently only size and data are implemented and used } tEplVarParamValid; -typedef tEplKernel(PUBLIC ROM * tEplVarCallback) (CCM_DECL_INSTANCE_HDL_ - void *pParam_p); +typedef tEplKernel(*tEplVarCallback) (CCM_DECL_INSTANCE_HDL_ void *pParam_p); typedef struct { tEplVarParamValid m_ValidFlag; unsigned int m_uiIndex; unsigned int m_uiSubindex; tEplObdSize m_Size; - void MEM *m_pData; + void *m_pData; // tEplVarCallback m_fpCallback; // void * m_pArg; } tEplVarParam; typedef struct { - void MEM *m_pData; + void *m_pData; tEplObdSize m_Size; /* #if (EPL_PDO_USE_STATIC_MAPPING == FALSE) @@ -310,7 +309,7 @@ typedef struct { typedef struct { tEplObdSize m_Size; - BYTE *m_pString; + u8 *m_pString; } tEplObdOString; // 000C @@ -328,8 +327,8 @@ typedef struct { typedef struct { tEplObdSize m_Size; - BYTE *m_pDefString; // $$$ d.k. it is unused, so we could delete it - BYTE *m_pString; + u8 *m_pDefString; // $$$ d.k. it is unused, so we could delete it + u8 *m_pString; } tEplObdOStringDef; @@ -354,7 +353,7 @@ typedef struct { tEplObdType m_Type; tEplObdAccess m_Access; void *m_pDefault; - void MEM *m_pCurrent; // points always to RAM + void *m_pCurrent; // points always to RAM } tEplObdSubEntry; @@ -371,14 +370,12 @@ typedef struct { unsigned int m_uiIndex; unsigned int m_uiSubIndex; void *m_pArg; - DWORD m_dwAbortCode; + u32 m_dwAbortCode; } tEplObdCbParam; // define type for callback function: pParam_p points to tEplObdCbParam -typedef tEplKernel(PUBLIC ROM * tEplObdCallback) (CCM_DECL_INSTANCE_HDL_ - tEplObdCbParam MEM * - pParam_p); +typedef tEplKernel(*tEplObdCallback) (CCM_DECL_INSTANCE_HDL_ tEplObdCbParam *pParam_p); // do not change the order for this struct!!! @@ -417,19 +414,14 @@ typedef struct { typedef struct { tEplObdCommand m_bCommand; tEplObdPart m_bCurrentOdPart; - void MEM *m_pData; + void *m_pData; tEplObdSize m_ObjSize; } tEplObdCbStoreParam; -typedef tEplKernel(PUBLIC ROM * tInitTabEntryCallback) (void MEM * pTabEntry_p, - unsigned int - uiObjIndex_p); +typedef tEplKernel(*tInitTabEntryCallback) (void *pTabEntry_p, unsigned int uiObjIndex_p); -typedef tEplKernel(PUBLIC ROM * - tEplObdStoreLoadObjCallback) (CCM_DECL_INSTANCE_HDL_ - tEplObdCbStoreParam MEM * - pCbStoreParam_p); +typedef tEplKernel(*tEplObdStoreLoadObjCallback) (CCM_DECL_INSTANCE_HDL_ tEplObdCbStoreParam *pCbStoreParam_p); // ------------------------------------------------------------------------- // this stucture is used for parameters for function ObdInitModuleTab() @@ -438,8 +430,8 @@ typedef struct { unsigned int m_uiLowerObjIndex; // lower limit of ObjIndex unsigned int m_uiUpperObjIndex; // upper limit of ObjIndex tInitTabEntryCallback m_fpInitTabEntry; // will be called if ObjIndex was found - void MEM *m_pTabBase; // base address of table - unsigned int m_uiEntrySize; // size of table entry // 25-feb-2005 r.d.: expansion from BYTE to WORD necessary for PDO bit mapping + void *m_pTabBase; // base address of table + unsigned int m_uiEntrySize; // size of table entry // 25-feb-2005 r.d.: expansion from u8 to u16 necessary for PDO bit mapping unsigned int m_uiMaxEntries; // max. tabel entries } tEplObdModulTabParam; diff --git a/drivers/staging/epl/EplObdMacro.h b/drivers/staging/epl/EplObdMacro.h index 23f2ad80dde8..fc325bfd604c 100644 --- a/drivers/staging/epl/EplObdMacro.h +++ b/drivers/staging/epl/EplObdMacro.h @@ -80,7 +80,7 @@ // #pragma message ("EPL_OBD_CREATE_ROM_DATA") -#define EPL_OBD_BEGIN() static DWORD dwObd_OBK_g = 0x0000; +#define EPL_OBD_BEGIN() static u32 dwObd_OBK_g = 0x0000; #define EPL_OBD_END() //--------------------------------------------------------------------------------------- @@ -102,11 +102,11 @@ #define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) static dtyp xDef##ind##_##sub##_g = val; #define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp xDef##ind##_##sub##_g[3] = {val,low,high}; #define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) -#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) static char MEM szCur##ind##_##sub##_g[size+1]; \ +#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) static char szCur##ind##_##sub##_g[size+1]; \ static tEplObdVStringDef xDef##ind##_##sub##_g = {size, val, szCur##ind##_##sub##_g}; -#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) static BYTE MEM bCur##ind##_##sub##_g[size]; \ - static tEplObdOStringDef xDef##ind##_##sub##_g = {size, ((BYTE*)""), bCur##ind##_##sub##_g}; +#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) static u8 bCur##ind##_##sub##_g[size]; \ + static tEplObdOStringDef xDef##ind##_##sub##_g = {size, ((u8*)""), bCur##ind##_##sub##_g}; #define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) #define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) static dtyp xDef##ind##_##sub##_g = val; #define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp xDef##ind##_##sub##_g[3] = {val,low,high}; @@ -129,20 +129,20 @@ //--------------------------------------------------------------------------------------- #define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) #define EPL_OBD_END_INDEX(ind) -#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static dtyp MEM axCur##ind##_g[cnt]; -#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdVarEntry MEM aVarEntry##ind##_g[cnt]; -#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdVarEntry MEM aVarEntry##ind##_g[cnt]; +#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static dtyp axCur##ind##_g[cnt]; +#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdVarEntry aVarEntry##ind##_g[cnt]; +#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdVarEntry aVarEntry##ind##_g[cnt]; //--------------------------------------------------------------------------------------- -#define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) static dtyp MEM xCur##ind##_##sub##_g; -#define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp MEM xCur##ind##_##sub##_g; -#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) static tEplObdVString MEM xCur##ind##_##sub##_g; -#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) static tEplObdOString MEM xCur##ind##_##sub##_g; -#define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) static dtyp MEM xCur##ind##_##sub##_g; -#define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g; -#define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g; -#define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g; -#define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g; +#define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) static dtyp xCur##ind##_##sub##_g; +#define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp xCur##ind##_##sub##_g; +#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) static tEplObdVString xCur##ind##_##sub##_g; +#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) static tEplObdOString xCur##ind##_##sub##_g; +#define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) static dtyp xCur##ind##_##sub##_g; +#define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) static tEplObdVarEntry VarEntry##ind##_##sub##_g; +#define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) static tEplObdVarEntry VarEntry##ind##_##sub##_g; +#define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static tEplObdVarEntry VarEntry##ind##_##sub##_g; +#define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) static tEplObdVarEntry VarEntry##ind##_##sub##_g; //------------------------------------------------------------------------------------------- #elif defined (EPL_OBD_CREATE_SUBINDEX_TAB) @@ -159,17 +159,17 @@ #define EPL_OBD_END_PART() //--------------------------------------------------------------------------------------- -#define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[cnt]= { +#define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) static tEplObdSubEntry aObdSubEntry##ind##Ram_g[cnt]= { #define EPL_OBD_END_INDEX(ind) EPL_OBD_END_SUBINDEX()}; -#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[]= { \ +#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdSubEntry aObdSubEntry##ind##Ram_g[]= { \ {0, kEplObdTypUInt8, kEplObdAccCR, &xDef##ind##_0x00_g, NULL}, \ {1, typ, (acc)|kEplObdAccArray, &xDef##ind##_0x01_g, &axCur##ind##_g[0]}, \ EPL_OBD_END_SUBINDEX()}; -#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[]= { \ +#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdSubEntry aObdSubEntry##ind##Ram_g[]= { \ {0, kEplObdTypUInt8, kEplObdAccCR, &xDef##ind##_0x00_g, NULL}, \ {1, typ, (acc)|kEplObdAccArray|kEplObdAccVar, &xDef##ind##_0x01_g, &aVarEntry##ind##_g[0]}, \ EPL_OBD_END_SUBINDEX()}; -#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[]= { \ +#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdSubEntry aObdSubEntry##ind##Ram_g[]= { \ {0, kEplObdTypUInt8, kEplObdAccCR, &xDef##ind##_0x00_g, NULL}, \ {1, typ, (acc)|kEplObdAccArray|kEplObdAccVar, NULL, &aVarEntry##ind##_g[0]}, \ EPL_OBD_END_SUBINDEX()}; diff --git a/drivers/staging/epl/EplObdkCal.c b/drivers/staging/epl/EplObdkCal.c index 4c9af89719ed..02bd72224ab3 100644 --- a/drivers/staging/epl/EplObdkCal.c +++ b/drivers/staging/epl/EplObdkCal.c @@ -70,7 +70,6 @@ ****************************************************************************/ #include "EplInc.h" -#include "kernel/EplObdkCal.h" /***************************************************************************/ /* */ diff --git a/drivers/staging/epl/EplObdu.c b/drivers/staging/epl/EplObdu.c index 218d152897cf..5f1d9986254e 100644 --- a/drivers/staging/epl/EplObdu.c +++ b/drivers/staging/epl/EplObdu.c @@ -121,10 +121,9 @@ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntry(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p) +tEplKernel EplObduWriteEntry(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, tEplObdSize Size_p) { tEplKernel Ret; @@ -153,10 +152,10 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntry(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntry(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p) +tEplKernel EplObduReadEntry(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, + tEplObdSize *pSize_p) { tEplKernel Ret; @@ -179,8 +178,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntry(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduAccessOdPart(tEplObdPart ObdPart_p, - tEplObdDir Direction_p) +tEplKernel EplObduAccessOdPart(tEplObdPart ObdPart_p, tEplObdDir Direction_p) { tEplKernel Ret; @@ -202,7 +200,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduAccessOdPart(tEplObdPart ObdPart_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduDefineVar(tEplVarParam MEM * pVarParam_p) +tEplKernel EplObduDefineVar(tEplVarParam *pVarParam_p) { tEplKernel Ret; @@ -226,8 +224,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduDefineVar(tEplVarParam MEM * pVarParam_p) // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT void *PUBLIC EplObduGetObjectDataPtr(unsigned int uiIndex_p, - unsigned int uiSubIndex_p) +void *EplObduGetObjectDataPtr(unsigned int uiIndex_p, unsigned int uiSubIndex_p) { void *pData; @@ -250,7 +247,7 @@ EPLDLLEXPORT void *PUBLIC EplObduGetObjectDataPtr(unsigned int uiIndex_p, // //--------------------------------------------------------------------------- #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) -EPLDLLEXPORT tEplKernel PUBLIC EplObduRegisterUserOd(tEplObdEntryPtr pUserOd_p) +tEplKernel EplObduRegisterUserOd(tEplObdEntryPtr pUserOd_p) { tEplKernel Ret; @@ -275,9 +272,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduRegisterUserOd(tEplObdEntryPtr pUserOd_p) // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT void PUBLIC EplObduInitVarEntry(tEplObdVarEntry MEM * pVarEntry_p, - BYTE bType_p, - tEplObdSize ObdSize_p) +void EplObduInitVarEntry(tEplObdVarEntry *pVarEntry_p, u8 bType_p, tEplObdSize ObdSize_p) { EplObduCalInitVarEntry(pVarEntry_p, bType_p, ObdSize_p); } @@ -299,8 +294,7 @@ EPLDLLEXPORT void PUBLIC EplObduInitVarEntry(tEplObdVarEntry MEM * pVarEntry_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplObdSize PUBLIC EplObduGetDataSize(unsigned int uiIndex_p, - unsigned int uiSubIndex_p) +tEplObdSize EplObduGetDataSize(unsigned int uiIndex_p, unsigned int uiSubIndex_p) { tEplObdSize Size; @@ -323,7 +317,7 @@ EPLDLLEXPORT tEplObdSize PUBLIC EplObduGetDataSize(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT unsigned int PUBLIC EplObduGetNodeId() +unsigned int EplObduGetNodeId(void) { unsigned int uiNodeId; @@ -347,8 +341,7 @@ EPLDLLEXPORT unsigned int PUBLIC EplObduGetNodeId() // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduSetNodeId(unsigned int uiNodeId_p, - tEplObdNodeIdType NodeIdType_p) +tEplKernel EplObduSetNodeId(unsigned int uiNodeId_p, tEplObdNodeIdType NodeIdType_p) { tEplKernel Ret; @@ -373,10 +366,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduSetNodeId(unsigned int uiNodeId_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduGetAccessType(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - tEplObdAccess * - pAccessTyp_p) +tEplKernel EplObduGetAccessType(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess *pAccessTyp_p) { tEplObdAccess AccessType; @@ -410,10 +402,10 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduGetAccessType(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntryToLe(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p) +tEplKernel EplObduReadEntryToLe(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, + tEplObdSize *pSize_p) { tEplKernel Ret; @@ -445,11 +437,10 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntryToLe(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntryFromLe(unsigned int uiIndex_p, - unsigned int - uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p) +tEplKernel EplObduWriteEntryFromLe(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, + tEplObdSize Size_p) { tEplKernel Ret; @@ -475,11 +466,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntryFromLe(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubindex_p, - tEplObdVarEntry MEM ** - ppVarEntry_p) +tEplKernel EplObduSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry **ppVarEntry_p) { tEplKernel Ret; diff --git a/drivers/staging/epl/EplObduCal.c b/drivers/staging/epl/EplObduCal.c index 85b3df0886b1..55612cff8211 100644 --- a/drivers/staging/epl/EplObduCal.c +++ b/drivers/staging/epl/EplObduCal.c @@ -121,10 +121,9 @@ // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntry(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p) +tEplKernel EplObduCalWriteEntry(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, tEplObdSize Size_p) { tEplKernel Ret; @@ -155,10 +154,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntry(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntry(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p) +tEplKernel EplObduCalReadEntry(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, tEplObdSize *pSize_p) { tEplKernel Ret; @@ -185,8 +183,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntry(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalAccessOdPart(tEplObdPart ObdPart_p, - tEplObdDir Direction_p) +tEplKernel EplObduCalAccessOdPart(tEplObdPart ObdPart_p, tEplObdDir Direction_p) { tEplKernel Ret; @@ -212,8 +209,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduCalAccessOdPart(tEplObdPart ObdPart_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalDefineVar(tEplVarParam MEM * - pVarParam_p) +tEplKernel EplObduCalDefineVar(tEplVarParam *pVarParam_p) { tEplKernel Ret; @@ -240,8 +236,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduCalDefineVar(tEplVarParam MEM * // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT void *PUBLIC EplObduCalGetObjectDataPtr(unsigned int uiIndex_p, - unsigned int uiSubIndex_p) +void *EplObduCalGetObjectDataPtr(unsigned int uiIndex_p, unsigned int uiSubIndex_p) { void *pData; @@ -268,8 +263,7 @@ EPLDLLEXPORT void *PUBLIC EplObduCalGetObjectDataPtr(unsigned int uiIndex_p, // //--------------------------------------------------------------------------- #if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalRegisterUserOd(tEplObdEntryPtr - pUserOd_p) +tEplKernel EplObduCalRegisterUserOd(tEplObdEntryPtr pUserOd_p) { tEplKernel Ret; @@ -298,9 +292,8 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduCalRegisterUserOd(tEplObdEntryPtr // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT void PUBLIC EplObduCalInitVarEntry(tEplObdVarEntry MEM * - pVarEntry_p, BYTE bType_p, - tEplObdSize ObdSize_p) +void EplObduCalInitVarEntry(tEplObdVarEntry *pVarEntry_p, u8 bType_p, + tEplObdSize ObdSize_p) { #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) EplObdInitVarEntry(pVarEntry_p, bType_p, ObdSize_p); @@ -324,8 +317,8 @@ EPLDLLEXPORT void PUBLIC EplObduCalInitVarEntry(tEplObdVarEntry MEM * // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplObdSize PUBLIC EplObduCalGetDataSize(unsigned int uiIndex_p, - unsigned int uiSubIndex_p) +tEplObdSize EplObduCalGetDataSize(unsigned int uiIndex_p, + unsigned int uiSubIndex_p) { tEplObdSize Size; @@ -352,7 +345,7 @@ EPLDLLEXPORT tEplObdSize PUBLIC EplObduCalGetDataSize(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT unsigned int PUBLIC EplObduCalGetNodeId() +unsigned int EplObduCalGetNodeId(void) { unsigned int uiNodeId; @@ -380,9 +373,8 @@ EPLDLLEXPORT unsigned int PUBLIC EplObduCalGetNodeId() // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalSetNodeId(unsigned int uiNodeId_p, - tEplObdNodeIdType - NodeIdType_p) +tEplKernel EplObduCalSetNodeId(unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p) { tEplKernel Ret; @@ -411,11 +403,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduCalSetNodeId(unsigned int uiNodeId_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalGetAccessType(unsigned int uiIndex_p, - unsigned int - uiSubIndex_p, - tEplObdAccess * - pAccessTyp_p) +tEplKernel EplObduCalGetAccessType(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess *pAccessTyp_p) { tEplObdAccess AccesType; @@ -447,11 +437,10 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduCalGetAccessType(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntryToLe(unsigned int uiIndex_p, - unsigned int - uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p) +tEplKernel EplObduCalReadEntryToLe(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, + tEplObdSize *pSize_p) { tEplKernel Ret; @@ -481,12 +470,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntryToLe(unsigned int uiIndex_p, // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntryFromLe(unsigned int - uiIndex_p, - unsigned int - uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p) +tEplKernel EplObduCalWriteEntryFromLe(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, tEplObdSize Size_p) { tEplKernel Ret; @@ -514,10 +500,9 @@ EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntryFromLe(unsigned int // State: // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC -EplObduCalSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, - unsigned int uiSubindex_p, - tEplObdVarEntry MEM ** ppVarEntry_p) +tEplKernel EplObduCalSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry **ppVarEntry_p) { tEplKernel Ret; diff --git a/drivers/staging/epl/EplObjDef.h b/drivers/staging/epl/EplObjDef.h deleted file mode 100644 index 7713125a3e8d..000000000000 --- a/drivers/staging/epl/EplObjDef.h +++ /dev/null @@ -1,208 +0,0 @@ -/**************************************************************************** - - (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 - www.systec-electronic.com - - Project: openPOWERLINK - - Description: defines objdict dictionary - - License: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of SYSTEC electronic GmbH nor the names of its - contributors may be used to endorse or promote products derived - from this software without prior written permission. For written - permission, please contact info@systec-electronic.com. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Severability Clause: - - If a provision of this License is or becomes illegal, invalid or - unenforceable in any jurisdiction, that shall not affect: - 1. the validity or enforceability in that jurisdiction of any other - provision of this License; or - 2. the validity or enforceability in other jurisdictions of that or - any other provision of this License. - - ------------------------------------------------------------------------- - - $RCSfile: EplObjDef.h,v $ - - $Author: D.Krueger $ - - $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ - - $State: Exp $ - - Build Environment: - GCC V3.4 - - ------------------------------------------------------------------------- - - Revision History: - - 2006/06/06 k.t.: take ObjDef.h from CANopen and modify for EPL - -****************************************************************************/ - -#ifndef _EPLOBJDEF_H_ -#define _EPLOBJDEF_H_ - -//--------------------------------------------------------------------------- -// security checks -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// macros to help building OD -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -#if (defined (EPL_OBD_USE_VARIABLE_SUBINDEX_TAB) && (EPL_OBD_USE_VARIABLE_SUBINDEX_TAB != FALSE)) - -#define CCM_SUBINDEX_RAM_ONLY(a) a; -#define CCM_SUBINDEX_RAM_ONEOF(a,b) a - -#else - -#define CCM_SUBINDEX_RAM_ONLY(a) -#define CCM_SUBINDEX_RAM_ONEOF(a,b) b - -#endif - -//--------------------------------------------------------------------------- -// To prevent unused memory in subindex tables we need this macro. -// But not all compilers support to preset the last struct value followed by a comma. -// Compilers which does not support a comma after last struct value has to place in a dummy subindex. -#if ((DEV_SYSTEM & _DEV_COMMA_EXT_) != 0) - -#define EPL_OBD_END_SUBINDEX() -#define EPL_OBD_MAX_ARRAY_SUBENTRIES 2 - -#else - -#define EPL_OBD_END_SUBINDEX() {0,0,0,NULL,NULL} -#define EPL_OBD_MAX_ARRAY_SUBENTRIES 3 - -#endif - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -// globale vars -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- - -// ------------------------------------------------------------------------- -// creation of data in ROM memory -// ------------------------------------------------------------------------- -#define EPL_OBD_CREATE_ROM_DATA -#include "objdict.h" -#undef EPL_OBD_CREATE_ROM_DATA - -// ------------------------------------------------------------------------- -// creation of data in RAM memory -// ------------------------------------------------------------------------- - -#define EPL_OBD_CREATE_RAM_DATA -#include "objdict.h" -#undef EPL_OBD_CREATE_RAM_DATA - -// ------------------------------------------------------------------------- -// creation of subindex tables in ROM and RAM -// ------------------------------------------------------------------------- - -#define EPL_OBD_CREATE_SUBINDEX_TAB -#include "objdict.h" -#undef EPL_OBD_CREATE_SUBINDEX_TAB - -// ------------------------------------------------------------------------- -// creation of index tables for generic, manufacturer and device part -// ------------------------------------------------------------------------- - -#define EPL_OBD_CREATE_INDEX_TAB -#include "objdict.h" -#undef EPL_OBD_CREATE_INDEX_TAB - -//=========================================================================// -// // -// P U B L I C F U N C T I O N S // -// // -//=========================================================================// - -// ---------------------------------------------------------------------------- -// -// Function: EPL_OBD_INIT_RAM_NAME() -// -// Description: function to initialize object dictionary -// -// Parameters: pInitParam_p = pointer to init param struct of Epl -// -// Returns: tEplKernel = error code -// -// State: -// -// ---------------------------------------------------------------------------- - -EPLDLLEXPORT tEplKernel PUBLIC EPL_OBD_INIT_RAM_NAME(tEplObdInitParam MEM * - pInitParam_p) -{ - - tEplObdInitParam MEM *pInitParam = pInitParam_p; - - // check if pointer to parameter structure is valid - // if not then only copy subindex tables below - if (pInitParam != NULL) { - // at first delete all parameters (all pointers will be set zu NULL) - EPL_MEMSET(pInitParam, 0, sizeof(tEplObdInitParam)); - -#define EPL_OBD_CREATE_INIT_FUNCTION - { - // inserts code to init pointer to index tables -#include "objdict.h" - } -#undef EPL_OBD_CREATE_INIT_FUNCTION - -#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE)) - { - // to begin no user OD is defined - pInitParam_p->m_pUserPart = NULL; - } -#endif - } -#define EPL_OBD_CREATE_INIT_SUBINDEX - { - // inserts code to copy subindex tables -#include "objdict.h" - } -#undef EPL_OBD_CREATE_INIT_SUBINDEX - - return kEplSuccessful; - -} - -#endif // _EPLOBJDEF_H_ - -// Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler -// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder). diff --git a/drivers/staging/epl/EplPdo.h b/drivers/staging/epl/EplPdo.h index d22ac86e85b6..0b3ad5bc7d5e 100644 --- a/drivers/staging/epl/EplPdo.h +++ b/drivers/staging/epl/EplPdo.h @@ -90,8 +90,8 @@ typedef struct { void *m_pVar; - WORD m_wOffset; // in Bits - WORD m_wSize; // in Bits + u16 m_wOffset; // in Bits + u16 m_wSize; // in Bits BOOL m_fNumeric; // numeric value -> use AMI functions } tEplPdoMapping; @@ -104,7 +104,7 @@ typedef struct { // TPDO: 0x00=PRes, MN: CnNodeId=PReq BOOL m_fTxRx; - BYTE m_bMappingVersion; + u8 m_bMappingVersion; unsigned int m_uiMaxMappingEntries; // maximum number of mapping entries, i.e. size of m_aPdoMapping tEplPdoMapping m_aPdoMapping[1]; diff --git a/drivers/staging/epl/EplPdok.c b/drivers/staging/epl/EplPdok.c index 15999b4f5750..db9b3f083841 100644 --- a/drivers/staging/epl/EplPdok.c +++ b/drivers/staging/epl/EplPdok.c @@ -73,11 +73,6 @@ #include "kernel/EplEventk.h" #include "kernel/EplObdk.h" -#if (DEV_SYSTEM == _DEV_GNU_CF548X_) -#include "plccore.h" -#define PDO_LED 0x08 -#endif - #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) == 0) @@ -226,11 +221,6 @@ tEplKernel EplPdokCbPdoReceived(tEplFrameInfo * pFrameInfo_p) tEplKernel Ret = kEplSuccessful; tEplEvent Event; -#if (DEV_SYSTEM == _DEV_GNU_CF548X_) - // reset LED -// MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level -#endif - Event.m_EventSink = kEplEventSinkPdok; Event.m_EventType = kEplEventTypePdoRx; // limit copied data to size of PDO (because from some CNs the frame is larger than necessary) @@ -238,11 +228,6 @@ tEplKernel EplPdokCbPdoReceived(tEplFrameInfo * pFrameInfo_p) Event.m_pArg = pFrameInfo_p->m_pFrame; Ret = EplEventkPost(&Event); -#if (DEV_SYSTEM == _DEV_GNU_CF548X_) - // set LED -// MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level -#endif - return Ret; } @@ -269,22 +254,12 @@ tEplKernel EplPdokCbPdoTransmitted(tEplFrameInfo * pFrameInfo_p) tEplKernel Ret = kEplSuccessful; tEplEvent Event; -#if (DEV_SYSTEM == _DEV_GNU_CF548X_) - // reset LED - MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level -#endif - Event.m_EventSink = kEplEventSinkPdok; Event.m_EventType = kEplEventTypePdoTx; Event.m_uiSize = sizeof(tEplFrameInfo); Event.m_pArg = pFrameInfo_p; Ret = EplEventkPost(&Event); -#if (DEV_SYSTEM == _DEV_GNU_CF548X_) - // set LED - MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level -#endif - return Ret; } @@ -339,19 +314,19 @@ tEplKernel EplPdokCbSoa(tEplFrameInfo * pFrameInfo_p) tEplKernel EplPdokProcess(tEplEvent * pEvent_p) { tEplKernel Ret = kEplSuccessful; - WORD wPdoSize; - WORD wBitOffset; - WORD wBitSize; - WORD wVarSize; - QWORD qwObjectMapping; - BYTE bMappSubindex; - BYTE bObdSubindex; - WORD wObdMappIndex; - WORD wObdCommIndex; - WORD wPdoId; - BYTE bObdData; - BYTE bObjectCount; - BYTE bFrameData; + u16 wPdoSize; + u16 wBitOffset; + u16 wBitSize; + u16 wVarSize; + u64 qwObjectMapping; + u8 bMappSubindex; + u8 bObdSubindex; + u16 wObdMappIndex; + u16 wObdCommIndex; + u16 wPdoId; + u8 bObdData; + u8 bObjectCount; + u8 bFrameData; BOOL fValid; tEplObdSize ObdSize; tEplFrame *pFrame; @@ -448,7 +423,7 @@ tEplKernel EplPdokProcess(tEplEvent * pEvent_p) // process mapping for (bMappSubindex = 1; bMappSubindex <= bObjectCount; bMappSubindex++) { - ObdSize = 8; // QWORD + ObdSize = 8; // u64 // read object mapping from OD Ret = EplObdReadEntry(wObdMappIndex, @@ -463,16 +438,16 @@ tEplKernel EplPdokProcess(tEplEvent * pEvent_p) } // decode object mapping wObdCommIndex = - (WORD) (qwObjectMapping & + (u16) (qwObjectMapping & 0x000000000000FFFFLL); bObdSubindex = - (BYTE) ((qwObjectMapping & + (u8) ((qwObjectMapping & 0x0000000000FF0000LL) >> 16); wBitOffset = - (WORD) ((qwObjectMapping & + (u16) ((qwObjectMapping & 0x0000FFFF00000000LL) >> 32); wBitSize = - (WORD) ((qwObjectMapping & + (u16) ((qwObjectMapping & 0xFFFF000000000000LL) >> 48); // check if object exceeds PDO size @@ -578,7 +553,7 @@ tEplKernel EplPdokProcess(tEplEvent * pEvent_p) // process mapping for (bMappSubindex = 1; bMappSubindex <= bObjectCount; bMappSubindex++) { - ObdSize = 8; // QWORD + ObdSize = 8; // u64 // read object mapping from OD Ret = EplObdReadEntry(wObdMappIndex, @@ -593,21 +568,21 @@ tEplKernel EplPdokProcess(tEplEvent * pEvent_p) } // decode object mapping wObdCommIndex = - (WORD) (qwObjectMapping & + (u16) (qwObjectMapping & 0x000000000000FFFFLL); bObdSubindex = - (BYTE) ((qwObjectMapping & + (u8) ((qwObjectMapping & 0x0000000000FF0000LL) >> 16); wBitOffset = - (WORD) ((qwObjectMapping & + (u16) ((qwObjectMapping & 0x0000FFFF00000000LL) >> 32); wBitSize = - (WORD) ((qwObjectMapping & + (u16) ((qwObjectMapping & 0xFFFF000000000000LL) >> 48); // calculate max PDO size ObdSize = wBitSize >> 3; - wVarSize = (wBitOffset >> 3) + (WORD) ObdSize; + wVarSize = (wBitOffset >> 3) + (u16) ObdSize; if ((unsigned int)(wVarSize + 24) > pFrameInfo->m_uiFrameSize) { // TPDO is too short // $$$ raise PDO error, set Ret goto Exit; diff --git a/drivers/staging/epl/EplPdou.c b/drivers/staging/epl/EplPdou.c index e7b10653a0ed..d6d06242d746 100644 --- a/drivers/staging/epl/EplPdou.c +++ b/drivers/staging/epl/EplPdou.c @@ -149,18 +149,18 @@ // local function prototypes //--------------------------------------------------------------------------- -static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM * pParam_p, +static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam *pParam_p, unsigned int uiIndex_p); -static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p, +static void EplPdouDecodeObjectMapping(u64 qwObjectMapping_p, unsigned int *puiIndex_p, unsigned int *puiSubIndex_p, unsigned int *puiBitOffset_p, unsigned int *puiBitSize_p); -static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p, +static tEplKernel EplPdouCheckObjectMapping(u64 qwObjectMapping_p, tEplObdAccess AccessType_p, - DWORD * pdwAbortCode_p, + u32 * pdwAbortCode_p, unsigned int *puiPdoSize_p); //=========================================================================// @@ -226,18 +226,18 @@ tEplKernel EplPdouDelInstance(void) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p) +tEplKernel EplPdouCbObdAccess(tEplObdCbParam *pParam_p) { tEplKernel Ret = kEplSuccessful; unsigned int uiPdoId; unsigned int uiIndexType; tEplObdSize ObdSize; - BYTE bObjectCount; - QWORD qwObjectMapping; + u8 bObjectCount; + u64 qwObjectMapping; tEplObdAccess AccessType; - BYTE bMappSubindex; + u8 bMappSubindex; unsigned int uiCurPdoSize; - WORD wMaxPdoSize; + u16 wMaxPdoSize; unsigned int uiSubIndex; // fetch PDO ID @@ -293,7 +293,7 @@ tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p) if (pParam_p->m_uiSubIndex == 0) { // object mapping count accessed // PDO is enabled or disabled - bObjectCount = *((BYTE *) pParam_p->m_pArg); + bObjectCount = *((u8 *) pParam_p->m_pArg); if (bObjectCount == 0) { // PDO shall be disabled @@ -326,7 +326,7 @@ tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p) for (bMappSubindex = 1; bMappSubindex <= bObjectCount; bMappSubindex++) { // read object mapping from OD - ObdSize = sizeof(qwObjectMapping); // QWORD + ObdSize = sizeof(qwObjectMapping); // u64 Ret = EplObduReadEntry(pParam_p->m_uiIndex, bMappSubindex, &qwObjectMapping, &ObdSize); @@ -360,7 +360,7 @@ tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p) } // check existence of object and validity of object length - qwObjectMapping = *((QWORD *) pParam_p->m_pArg); + qwObjectMapping = *((u64 *) pParam_p->m_pArg); Ret = EplPdouCheckObjectMapping(qwObjectMapping, AccessType, @@ -394,12 +394,12 @@ tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p) // //--------------------------------------------------------------------------- -static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM * pParam_p, +static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam *pParam_p, unsigned int uiIndex_p) { tEplKernel Ret = kEplSuccessful; tEplObdSize ObdSize; - BYTE bObjectCount; + u8 bObjectCount; ObdSize = 1; // read number of mapped objects from OD; this indicates if the PDO is valid @@ -439,7 +439,7 @@ static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM * pParam_p, // //--------------------------------------------------------------------------- -static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p, +static void EplPdouDecodeObjectMapping(u64 qwObjectMapping_p, unsigned int *puiIndex_p, unsigned int *puiSubIndex_p, unsigned int *puiBitOffset_p, @@ -480,9 +480,9 @@ static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p, // //--------------------------------------------------------------------------- -static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p, +static tEplKernel EplPdouCheckObjectMapping(u64 qwObjectMapping_p, tEplObdAccess AccessType_p, - DWORD * pdwAbortCode_p, + u32 * pdwAbortCode_p, unsigned int *puiPdoSize_p) { tEplKernel Ret = kEplSuccessful; diff --git a/drivers/staging/epl/EplSdo.h b/drivers/staging/epl/EplSdo.h index 1cb3f2de4a3c..8002e0cc4d9b 100644 --- a/drivers/staging/epl/EplSdo.h +++ b/drivers/staging/epl/EplSdo.h @@ -116,20 +116,18 @@ typedef unsigned int tEplSdoConHdl; // callback function pointer for Protocol Abstraction Layer to call // asynchronuus SDO Sequence Layer -typedef tEplKernel(PUBLIC * tEplSequLayerReceiveCb) (tEplSdoConHdl ConHdl_p, - tEplAsySdoSeq * - pSdoSeqData_p, - unsigned int uiDataSize_p); +typedef tEplKernel(*tEplSequLayerReceiveCb) (tEplSdoConHdl ConHdl_p, + tEplAsySdoSeq *pSdoSeqData_p, + unsigned int uiDataSize_p); // handle between asynchronuus SDO Sequence Layer and SDO Command layer typedef unsigned int tEplSdoSeqConHdl; // callback function pointer for asynchronuus SDO Sequence Layer to call // SDO Command layer for received data -typedef tEplKernel(PUBLIC * - tEplSdoComReceiveCb) (tEplSdoSeqConHdl SdoSeqConHdl_p, - tEplAsySdoCom * pAsySdoCom_p, - unsigned int uiDataSize_p); +typedef tEplKernel(* tEplSdoComReceiveCb) (tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoCom *pAsySdoCom_p, + unsigned int uiDataSize_p); // status of connection typedef enum { @@ -143,9 +141,8 @@ typedef enum { // callback function pointer for asynchronuus SDO Sequence Layer to call // SDO Command layer for connection status -typedef tEplKernel(PUBLIC * tEplSdoComConCb) (tEplSdoSeqConHdl SdoSeqConHdl_p, - tEplAsySdoConState - AsySdoConState_p); +typedef tEplKernel(* tEplSdoComConCb) (tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoConState AsySdoConState_p); // handle between SDO Command layer and application typedef unsigned int tEplSdoComConHdl; @@ -210,7 +207,7 @@ typedef enum { typedef struct { tEplSdoComConHdl m_SdoComConHdl; tEplSdoComConState m_SdoComConState; - DWORD m_dwAbortCode; + u32 m_dwAbortCode; tEplSdoAccessType m_SdoAccessType; unsigned int m_uiNodeId; // NodeId of the target unsigned int m_uiTargetIndex; // index which was accessed @@ -221,8 +218,7 @@ typedef struct { } tEplSdoComFinished; // callback function pointer to inform application about connection -typedef tEplKernel(PUBLIC * tEplSdoFinishedCb) (tEplSdoComFinished * - pSdoComFinished_p); +typedef tEplKernel(* tEplSdoFinishedCb) (tEplSdoComFinished *pSdoComFinished_p); // structure to init SDO transfer to Read or Write by Index typedef struct { diff --git a/drivers/staging/epl/EplSdoAsndu.c b/drivers/staging/epl/EplSdoAsndu.c index 05a00c9a731e..aa8bdef317cf 100644 --- a/drivers/staging/epl/EplSdoAsndu.c +++ b/drivers/staging/epl/EplSdoAsndu.c @@ -110,7 +110,7 @@ static tEplSdoAsndInstance SdoAsndInstance_g; // local function prototypes //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsnduCb(tEplFrameInfo * pFrameInfo_p); +tEplKernel EplSdoAsnduCb(tEplFrameInfo *pFrameInfo_p); /***************************************************************************/ /* */ @@ -149,7 +149,7 @@ tEplKernel PUBLIC EplSdoAsnduCb(tEplFrameInfo * pFrameInfo_p); // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p) +tEplKernel EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p) { tEplKernel Ret; @@ -176,7 +176,7 @@ tEplKernel PUBLIC EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p) +tEplKernel EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p) { tEplKernel Ret; @@ -218,7 +218,7 @@ tEplKernel PUBLIC EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsnduDelInstance() +tEplKernel EplSdoAsnduDelInstance(void) { tEplKernel Ret; @@ -251,8 +251,8 @@ tEplKernel PUBLIC EplSdoAsnduDelInstance() // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsnduInitCon(tEplSdoConHdl * pSdoConHandle_p, - unsigned int uiTargetNodeId_p) +tEplKernel EplSdoAsnduInitCon(tEplSdoConHdl *pSdoConHandle_p, + unsigned int uiTargetNodeId_p) { tEplKernel Ret; unsigned int uiCount; @@ -319,9 +319,9 @@ tEplKernel PUBLIC EplSdoAsnduInitCon(tEplSdoConHdl * pSdoConHandle_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p, - tEplFrame * pSrcData_p, - DWORD dwDataSize_p) +tEplKernel EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p, + tEplFrame *pSrcData_p, + u32 dwDataSize_p) { tEplKernel Ret; unsigned int uiArray; @@ -339,10 +339,10 @@ tEplKernel PUBLIC EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p, // own node id not needed -> filled by DLL // set message type - AmiSetByteToLe(&pSrcData_p->m_le_bMessageType, (BYTE) kEplMsgTypeAsnd); // ASnd == 0x06 + AmiSetByteToLe(&pSrcData_p->m_le_bMessageType, (u8) kEplMsgTypeAsnd); // ASnd == 0x06 // target node id AmiSetByteToLe(&pSrcData_p->m_le_bDstNodeId, - (BYTE) SdoAsndInstance_g. + (u8) SdoAsndInstance_g. m_auiSdoAsndConnection[uiArray]); // set source-nodeid (filled by DLL 0) AmiSetByteToLe(&pSrcData_p->m_le_bSrcNodeId, 0x00); @@ -379,7 +379,7 @@ tEplKernel PUBLIC EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p) +tEplKernel EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p) { tEplKernel Ret; unsigned int uiArray; @@ -422,7 +422,7 @@ tEplKernel PUBLIC EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsnduCb(tEplFrameInfo * pFrameInfo_p) +tEplKernel EplSdoAsnduCb(tEplFrameInfo *pFrameInfo_p) { tEplKernel Ret = kEplSuccessful; unsigned int uiCount; diff --git a/drivers/staging/epl/EplSdoAsySequ.c b/drivers/staging/epl/EplSdoAsySequ.c index 6b6a9975d78b..256d70866343 100644 --- a/drivers/staging/epl/EplSdoAsySequ.c +++ b/drivers/staging/epl/EplSdoAsySequ.c @@ -128,11 +128,11 @@ typedef enum { // structure for History-Buffer typedef struct { - BYTE m_bFreeEntries; - BYTE m_bWrite; // index of the next free buffer entry - BYTE m_bAck; // index of the next message which should become acknowledged - BYTE m_bRead; // index between m_bAck and m_bWrite to the next message for retransmission - BYTE m_aabHistoryFrame[EPL_SDO_HISTORY_SIZE] + u8 m_bFreeEntries; + u8 m_bWrite; // index of the next free buffer entry + u8 m_bAck; // index of the next message which should become acknowledged + u8 m_bRead; // index between m_bAck and m_bWrite to the next message for retransmission + u8 m_aabHistoryFrame[EPL_SDO_HISTORY_SIZE] [EPL_SEQ_HISTROY_FRAME_SIZE]; unsigned int m_auiFrameSize[EPL_SDO_HISTORY_SIZE]; @@ -152,8 +152,8 @@ typedef enum { typedef struct { tEplSdoConHdl m_ConHandle; tEplAsySdoState m_SdoState; - BYTE m_bRecSeqNum; // name from view of the communication partner - BYTE m_bSendSeqNum; // name from view of the communication partner + u8 m_bRecSeqNum; // name from view of the communication partner + u8 m_bSendSeqNum; // name from view of the communication partner tEplAsySdoConHistory m_SdoConHistory; tEplTimerHdl m_EplTimerHdl; unsigned int m_uiRetryCount; // retry counter @@ -203,9 +203,9 @@ static tEplKernel EplSdoAsySeqSendLowerLayer(tEplAsySdoSeqCon * pAsySdoSeqCon_p, unsigned int uiDataSize_p, tEplFrame * pEplFrame_p); -tEplKernel PUBLIC EplSdoAsyReceiveCb(tEplSdoConHdl ConHdl_p, - tEplAsySdoSeq * pSdoSeqData_p, - unsigned int uiDataSize_p); +tEplKernel EplSdoAsyReceiveCb(tEplSdoConHdl ConHdl_p, + tEplAsySdoSeq *pSdoSeqData_p, + unsigned int uiDataSize_p); static tEplKernel EplSdoAsyInitHistory(void); @@ -214,7 +214,7 @@ static tEplKernel EplSdoAsyAddFrameToHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p, unsigned int uiSize_p); static tEplKernel EplSdoAsyAckFrameToHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p, - BYTE bRecSeqNumber_p); + u8 bRecSeqNumber_p); static tEplKernel EplSdoAsyReadFromHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p, tEplFrame ** ppFrame_p, @@ -267,8 +267,8 @@ static tEplKernel EplSdoAsySeqSetTimer(tEplAsySdoSeqCon * pAsySdoSeqCon_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p, - tEplSdoComConCb fpSdoComConCb_p) +tEplKernel EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p, + tEplSdoComConCb fpSdoComConCb_p) { tEplKernel Ret; @@ -297,8 +297,8 @@ tEplKernel PUBLIC EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsySeqAddInstance(tEplSdoComReceiveCb fpSdoComCb_p, - tEplSdoComConCb fpSdoComConCb_p) +tEplKernel EplSdoAsySeqAddInstance(tEplSdoComReceiveCb fpSdoComCb_p, + tEplSdoComConCb fpSdoComConCb_p) { tEplKernel Ret; @@ -380,7 +380,7 @@ tEplKernel PUBLIC EplSdoAsySeqAddInstance(tEplSdoComReceiveCb fpSdoComCb_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsySeqDelInstance() +tEplKernel EplSdoAsySeqDelInstance(void) { tEplKernel Ret; unsigned int uiCount; @@ -439,9 +439,9 @@ tEplKernel PUBLIC EplSdoAsySeqDelInstance() // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsySeqInitCon(tEplSdoSeqConHdl * pSdoSeqConHdl_p, - unsigned int uiNodeId_p, - tEplSdoType SdoType) +tEplKernel EplSdoAsySeqInitCon(tEplSdoSeqConHdl *pSdoSeqConHdl_p, + unsigned int uiNodeId_p, + tEplSdoType SdoType) { tEplKernel Ret; unsigned int uiCount; @@ -594,9 +594,9 @@ tEplKernel PUBLIC EplSdoAsySeqInitCon(tEplSdoSeqConHdl * pSdoSeqConHdl_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p, - unsigned int uiDataSize_p, - tEplFrame * pabData_p) +tEplKernel EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p, + unsigned int uiDataSize_p, + tEplFrame *pabData_p) { tEplKernel Ret; unsigned int uiHandle; @@ -640,7 +640,7 @@ tEplKernel PUBLIC EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsySeqProcessEvent(tEplEvent * pEvent_p) +tEplKernel EplSdoAsySeqProcessEvent(tEplEvent *pEvent_p) { tEplKernel Ret; tEplTimerEventArg *pTimerEventArg; @@ -714,7 +714,7 @@ tEplKernel PUBLIC EplSdoAsySeqProcessEvent(tEplEvent * pEvent_p) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsySeqDelCon(tEplSdoSeqConHdl SdoSeqConHdl_p) +tEplKernel EplSdoAsySeqDelCon(tEplSdoSeqConHdl SdoSeqConHdl_p) { tEplKernel Ret = kEplSuccessful; unsigned int uiHandle; @@ -1498,7 +1498,7 @@ static tEplKernel EplSdoAsySeqProcess(unsigned int uiHandle_p, // frame received case kAsySdoSeqEventFrameRec: { - BYTE bSendSeqNumCon = + u8 bSendSeqNumCon = AmiGetByteFromLe(&pRecFrame_p-> m_le_bSendSeqNumCon); @@ -2016,7 +2016,7 @@ static tEplKernel EplSdoAsySeqSendIntern(tEplAsySdoSeqCon * pAsySdoSeqCon_p, BOOL fFrameInHistory_p) { tEplKernel Ret; - BYTE abFrame[EPL_SEQ_FRAME_SIZE]; + u8 abFrame[EPL_SEQ_FRAME_SIZE]; tEplFrame *pEplFrame; unsigned int uiFreeEntries; @@ -2139,9 +2139,9 @@ static tEplKernel EplSdoAsySeqSendLowerLayer(tEplAsySdoSeqCon * pAsySdoSeqCon_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsyReceiveCb(tEplSdoConHdl ConHdl_p, - tEplAsySdoSeq * pSdoSeqData_p, - unsigned int uiDataSize_p) +tEplKernel EplSdoAsyReceiveCb(tEplSdoConHdl ConHdl_p, + tEplAsySdoSeq *pSdoSeqData_p, + unsigned int uiDataSize_p) { tEplKernel Ret; unsigned int uiCount = 0; @@ -2154,7 +2154,7 @@ tEplKernel PUBLIC EplSdoAsyReceiveCb(tEplSdoConHdl ConHdl_p, #endif EPL_DBGLVL_SDO_TRACE2("Handle: 0x%x , First Databyte 0x%x\n", ConHdl_p, - ((BYTE *) pSdoSeqData_p)[0]); + ((u8 *) pSdoSeqData_p)[0]); // search controll structure for this connection pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[uiCount]; @@ -2328,12 +2328,12 @@ static tEplKernel EplSdoAsyAddFrameToHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p, // //--------------------------------------------------------------------------- static tEplKernel EplSdoAsyAckFrameToHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p, - BYTE bRecSeqNumber_p) + u8 bRecSeqNumber_p) { tEplKernel Ret; tEplAsySdoConHistory *pHistory; - BYTE bAckIndex; - BYTE bCurrentSeqNum; + u8 bAckIndex; + u8 bCurrentSeqNum; Ret = kEplSuccessful; @@ -2422,8 +2422,8 @@ static tEplKernel EplSdoAsyReadFromHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p, // check if entries are available for reading if ((pHistory->m_bFreeEntries < EPL_SDO_HISTORY_SIZE) && (pHistory->m_bWrite != pHistory->m_bRead)) { -// PRINTF4("EplSdoAsyReadFromHistory(): init = %d, read = %u, write = %u, ack = %u", (int) fInitRead_p, (WORD)pHistory->m_bRead, (WORD)pHistory->m_bWrite, (WORD)pHistory->m_bAck); -// PRINTF2(", free entries = %u, next frame size = %u\n", (WORD)pHistory->m_bFreeEntries, pHistory->m_auiFrameSize[pHistory->m_bRead]); +// PRINTF4("EplSdoAsyReadFromHistory(): init = %d, read = %u, write = %u, ack = %u", (int) fInitRead_p, (u16)pHistory->m_bRead, (u16)pHistory->m_bWrite, (u16)pHistory->m_bAck); +// PRINTF2(", free entries = %u, next frame size = %u\n", (u16)pHistory->m_bFreeEntries, pHistory->m_auiFrameSize[pHistory->m_bRead]); // return pointer to stored frame *ppFrame_p = @@ -2439,7 +2439,7 @@ static tEplKernel EplSdoAsyReadFromHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p, } } else { -// PRINTF3("EplSdoAsyReadFromHistory(): read = %u, ack = %u, free entries = %u, no frame\n", (WORD)pHistory->m_bRead, (WORD)pHistory->m_bAck, (WORD)pHistory->m_bFreeEntries); +// PRINTF3("EplSdoAsyReadFromHistory(): read = %u, ack = %u, free entries = %u, no frame\n", (u16)pHistory->m_bRead, (u16)pHistory->m_bAck, (u16)pHistory->m_bFreeEntries); // no more frames to send // return null pointer diff --git a/drivers/staging/epl/EplSdoComu.c b/drivers/staging/epl/EplSdoComu.c index ce0eb33f4c41..bf35afab152d 100644 --- a/drivers/staging/epl/EplSdoComu.c +++ b/drivers/staging/epl/EplSdoComu.c @@ -156,14 +156,14 @@ typedef enum { typedef struct { tEplSdoSeqConHdl m_SdoSeqConHdl; // if != 0 -> entry used tEplSdoComState m_SdoComState; - BYTE m_bTransactionId; + u8 m_bTransactionId; unsigned int m_uiNodeId; // NodeId of the target // -> needed to reinit connection // after timeout tEplSdoTransType m_SdoTransType; // Auto, Expedited, Segmented tEplSdoServiceType m_SdoServiceType; // WriteByIndex, ReadByIndex tEplSdoType m_SdoProtType; // protocol layer: Auto, Udp, Asnd, Pdo - BYTE *m_pData; // pointer to data + u8 *m_pData; // pointer to data unsigned int m_uiTransSize; // number of bytes // to transfer unsigned int m_uiTransferredByte; // number of bytes @@ -174,7 +174,7 @@ typedef struct { // the SDO transfer void *m_pUserArg; // user definable argument pointer - DWORD m_dwLastAbortCode; // save the last abort code + u32 m_dwLastAbortCode; // save the last abort code #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) // only for client unsigned int m_uiTargetIndex; // index to access @@ -205,12 +205,12 @@ static tEplSdoComInstance SdoComInstance_g; //--------------------------------------------------------------------------- // local function prototypes //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p, - tEplAsySdoCom * pAsySdoCom_p, - unsigned int uiDataSize_p); +tEplKernel EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoCom *pAsySdoCom_p, + unsigned int uiDataSize_p); -tEplKernel PUBLIC EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p, - tEplAsySdoConState AsySdoConState_p); +tEplKernel EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoConState AsySdoConState_p); static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl SdoSeqConHdl_p, tEplSdoComConEvent SdoComConEvent_p, @@ -246,7 +246,7 @@ static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p, tEplAsySdoCom * pAsySdoCom_p); static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p, - DWORD dwAbortCode_p); + u32 dwAbortCode_p); #endif /***************************************************************************/ @@ -285,7 +285,7 @@ static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoComInit(void) +tEplKernel EplSdoComInit(void) { tEplKernel Ret; @@ -312,7 +312,7 @@ tEplKernel PUBLIC EplSdoComInit(void) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoComAddInstance(void) +tEplKernel EplSdoComAddInstance(void) { tEplKernel Ret; @@ -354,7 +354,7 @@ tEplKernel PUBLIC EplSdoComAddInstance(void) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoComDelInstance(void) +tEplKernel EplSdoComDelInstance(void) { tEplKernel Ret; @@ -398,9 +398,9 @@ tEplKernel PUBLIC EplSdoComDelInstance(void) // //--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) -tEplKernel PUBLIC EplSdoComDefineCon(tEplSdoComConHdl * pSdoComConHdl_p, - unsigned int uiTargetNodeId_p, - tEplSdoType ProtType_p) +tEplKernel EplSdoComDefineCon(tEplSdoComConHdl *pSdoComConHdl_p, + unsigned int uiTargetNodeId_p, + tEplSdoType ProtType_p) { tEplKernel Ret; unsigned int uiCount; @@ -511,8 +511,7 @@ tEplKernel PUBLIC EplSdoComDefineCon(tEplSdoComConHdl * pSdoComConHdl_p, // //--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) -tEplKernel PUBLIC EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex * - pSdoComTransParam_p) +tEplKernel EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex *pSdoComTransParam_p) { tEplKernel Ret; tEplSdoComCon *pSdoComCon; @@ -603,7 +602,7 @@ tEplKernel PUBLIC EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex * // //--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) -tEplKernel PUBLIC EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p) +tEplKernel EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p) { tEplKernel Ret; tEplSdoComCon *pSdoComCon; @@ -669,8 +668,8 @@ tEplKernel PUBLIC EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p) // //--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) -tEplKernel PUBLIC EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p, - tEplSdoComFinished * pSdoComFinished_p) +tEplKernel EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p, + tEplSdoComFinished *pSdoComFinished_p) { tEplKernel Ret; tEplSdoComCon *pSdoComCon; @@ -747,8 +746,8 @@ tEplKernel PUBLIC EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p, // //--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) -tEplKernel PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, - DWORD dwAbortCode_p) +tEplKernel EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, + u32 dwAbortCode_p) { tEplKernel Ret; tEplSdoComCon *pSdoComCon; @@ -766,7 +765,7 @@ tEplKernel PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, goto Exit; } // save pointer to abort code - pSdoComCon->m_pData = (BYTE *) & dwAbortCode_p; + pSdoComCon->m_pData = (u8 *) & dwAbortCode_p; Ret = EplSdoComProcessIntern(SdoComConHdl_p, kEplSdoComConEventAbort, @@ -803,9 +802,9 @@ tEplKernel PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p, - tEplAsySdoCom * pAsySdoCom_p, - unsigned int uiDataSize_p) +tEplKernel EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoCom *pAsySdoCom_p, + unsigned int uiDataSize_p) { tEplKernel Ret; @@ -815,7 +814,7 @@ tEplKernel PUBLIC EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p, EPL_DBGLVL_SDO_TRACE3 ("EplSdoComReceiveCb SdoSeqConHdl: 0x%X, First Byte of pAsySdoCom_p: 0x%02X, uiDataSize_p: 0x%04X\n", - SdoSeqConHdl_p, (WORD) pAsySdoCom_p->m_le_abCommandData[0], + SdoSeqConHdl_p, (u16) pAsySdoCom_p->m_le_abCommandData[0], uiDataSize_p); return Ret; @@ -840,8 +839,8 @@ tEplKernel PUBLIC EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p, - tEplAsySdoConState AsySdoConState_p) +tEplKernel EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoConState AsySdoConState_p) { tEplKernel Ret; tEplSdoComConEvent SdoComConEvent = kEplSdoComConEventSendFirst; @@ -999,10 +998,10 @@ static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, { tEplKernel Ret; tEplSdoComCon *pSdoComCon; - BYTE bFlag; + u8 bFlag; #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) - DWORD dwAbortCode; + u32 dwAbortCode; unsigned int uiSize; #endif @@ -1138,7 +1137,7 @@ static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, pSdoComCon-> m_pData = - (BYTE + (u8 *) & dwAbortCode; @@ -1283,7 +1282,7 @@ static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, if (pSdoComCon-> m_dwLastAbortCode == 0) { - ( /*(BYTE*) */ + ( /*(u8*) */ pSdoComCon-> m_pData) += uiSize; @@ -1321,7 +1320,7 @@ static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, pSdoComCon-> m_pData = - (BYTE + (u8 *) & pSdoComCon-> @@ -1667,7 +1666,7 @@ static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, case kEplSdoComConEventAbort: { EplSdoComClientSendAbort(pSdoComCon, - *((DWORD *) + *((u32 *) pSdoComCon-> m_pData)); @@ -1675,7 +1674,7 @@ static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, pSdoComCon->m_bTransactionId++; // call callback of application pSdoComCon->m_dwLastAbortCode = - *((DWORD *) pSdoComCon->m_pData); + *((u32 *) pSdoComCon->m_pData); Ret = EplSdoComTransferFinished (SdoComCon_p, pSdoComCon, @@ -1869,7 +1868,7 @@ static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, case kEplSdoComConEventAbort: { EplSdoComClientSendAbort(pSdoComCon, - *((DWORD *) + *((u32 *) pSdoComCon-> m_pData)); @@ -1880,7 +1879,7 @@ static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, kEplSdoComStateClientConnected; // call callback of application pSdoComCon->m_dwLastAbortCode = - *((DWORD *) pSdoComCon->m_pData); + *((u32 *) pSdoComCon->m_pData); Ret = EplSdoComTransferFinished (SdoComCon_p, pSdoComCon, @@ -1965,7 +1964,7 @@ static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p, unsigned int uiSubindex; tEplObdSize EntrySize; tEplObdAccess AccessType; - DWORD dwAbortCode; + u32 dwAbortCode; dwAbortCode = 0; @@ -1987,7 +1986,7 @@ static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p, if (Ret == kEplObdSubindexNotExist) { // subentry doesn't exist dwAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST; // send abort - pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode; + pSdoComCon_p->m_pData = (u8 *) & dwAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -1996,7 +1995,7 @@ static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p, } else if (Ret != kEplSuccessful) { // entry doesn't exist dwAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST; // send abort - pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode; + pSdoComCon_p->m_pData = (u8 *) & dwAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -2014,7 +2013,7 @@ static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p, dwAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS; } // send abort - pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode; + pSdoComCon_p->m_pData = (u8 *) & dwAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -2051,7 +2050,7 @@ static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p, // error -> abort dwAbortCode = EPL_SDOAC_GENERAL_ERROR; // send abort - pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode; + pSdoComCon_p->m_pData = (u8 *) & dwAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -2090,11 +2089,11 @@ static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p, tEplSdoComSendType SendType_p) { tEplKernel Ret; - BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE]; + u8 abFrame[EPL_MAX_SDO_FRAME_SIZE]; tEplFrame *pFrame; tEplAsySdoCom *pCommandFrame; unsigned int uiSizeOfFrame; - BYTE bFlag; + u8 bFlag; Ret = kEplSuccessful; @@ -2167,7 +2166,7 @@ static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p, // set size of frame AmiSetWordToLe(&pCommandFrame-> m_le_wSegmentSize, - (WORD) pSdoComCon_p-> + (u16) pSdoComCon_p-> m_uiTransSize); // correct byte-counter @@ -2297,7 +2296,7 @@ static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p, // set segment size AmiSetWordToLe(&pCommandFrame-> m_le_wSegmentSize, - (WORD) pSdoComCon_p-> + (u16) pSdoComCon_p-> m_uiTransSize); // send frame @@ -2324,18 +2323,18 @@ static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p, // copy abortcode to frame AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], - *((DWORD *) pSdoComCon_p->m_pData)); + *((u32 *) pSdoComCon_p->m_pData)); // set size of segment AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, - sizeof(DWORD)); + sizeof(u32)); // update counter - pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD); + pSdoComCon_p->m_uiTransferredByte = sizeof(u32); pSdoComCon_p->m_uiTransSize = 0; // calc framesize - uiSizeOfFrame += sizeof(DWORD); + uiSizeOfFrame += sizeof(u32); Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, uiSizeOfFrame, pFrame); break; @@ -2373,8 +2372,8 @@ static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, unsigned int uiBytesToTransfer; tEplObdSize EntrySize; tEplObdAccess AccessType; - DWORD dwAbortCode; - BYTE *pbSrcData; + u32 dwAbortCode; + u8 *pbSrcData; dwAbortCode = 0; @@ -2427,7 +2426,7 @@ static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST; // send abort // d.k. This is wrong: k.t. not needed send abort on end of write - /*pSdoComCon_p->m_pData = (BYTE*)pSdoComCon_p->m_dwLastAbortCode; + /*pSdoComCon_p->m_pData = (u8*)pSdoComCon_p->m_dwLastAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -2438,7 +2437,7 @@ static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, // send abort // d.k. This is wrong: k.t. not needed send abort on end of write /* - pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + pSdoComCon_p->m_pData = (u8*)&dwAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -2458,7 +2457,7 @@ static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, } // send abort // d.k. This is wrong: k.t. not needed send abort on end of write - /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + /*pSdoComCon_p->m_pData = (u8*)&dwAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -2549,7 +2548,7 @@ static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH; // send abort // d.k. This is wrong: k.t. not needed send abort on end of write - /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode; + /*pSdoComCon_p->m_pData = (u8*)&dwAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -2571,7 +2570,7 @@ static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, EPL_SDOAC_GENERAL_ERROR; // send abort // d.k. This is wrong: k.t. not needed send abort on end of write -/* pSdoComCon_p->m_pData = (BYTE*)&pSdoComCon_p->m_dwLastAbortCode; +/* pSdoComCon_p->m_pData = (u8*)&pSdoComCon_p->m_dwLastAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -2586,7 +2585,7 @@ static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, pSdoComCon_p->m_uiTransSize -= uiBytesToTransfer; // update target pointer - ( /*(BYTE*) */ pSdoComCon_p->m_pData) += uiBytesToTransfer; + ( /*(u8*) */ pSdoComCon_p->m_pData) += uiBytesToTransfer; // send acknowledge without any Command layer data Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, @@ -2598,7 +2597,7 @@ static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, if (pSdoComCon_p->m_dwLastAbortCode != 0) { // send abort pSdoComCon_p->m_pData = - (BYTE *) & pSdoComCon_p->m_dwLastAbortCode; + (u8 *) & pSdoComCon_p->m_dwLastAbortCode; Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, uiSubindex, @@ -2635,12 +2634,12 @@ static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p) { tEplKernel Ret; - BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE]; + u8 abFrame[EPL_MAX_SDO_FRAME_SIZE]; tEplFrame *pFrame; tEplAsySdoCom *pCommandFrame; unsigned int uiSizeOfFrame; - BYTE bFlags; - BYTE *pbPayload; + u8 bFlags; + u8 *pbPayload; Ret = kEplSuccessful; @@ -2680,11 +2679,11 @@ static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p) // create command header AmiSetWordToLe(pbPayload, - (WORD) pSdoComCon_p-> + (u16) pSdoComCon_p-> m_uiTargetIndex); pbPayload += 2; AmiSetByteToLe(pbPayload, - (BYTE) pSdoComCon_p-> + (u8) pSdoComCon_p-> m_uiTargetSubIndex); // calc size uiSizeOfFrame += 4; @@ -2721,12 +2720,12 @@ static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p) bFlags); // create command header AmiSetWordToLe(pbPayload, - (WORD) + (u16) pSdoComCon_p-> m_uiTargetIndex); pbPayload += 2; AmiSetByteToLe(pbPayload, - (BYTE) + (u8) pSdoComCon_p-> m_uiTargetSubIndex); // on byte for reserved @@ -2760,12 +2759,12 @@ static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p) // create command header AmiSetWordToLe(pbPayload, - (WORD) + (u16) pSdoComCon_p-> m_uiTargetIndex); pbPayload += 2; AmiSetByteToLe(pbPayload, - (BYTE) + (u8) pSdoComCon_p-> m_uiTargetSubIndex); // + 2 -> one byte for subindex and one byte reserved @@ -2784,7 +2783,7 @@ static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p) // fill rest of header AmiSetWordToLe(&pCommandFrame-> m_le_wSegmentSize, - (WORD) (4 + + (u16) (4 + pSdoComCon_p-> m_uiTransSize)); @@ -2855,7 +2854,7 @@ static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p) AmiSetWordToLe (&pCommandFrame-> m_le_wSegmentSize, - (WORD) + (u16) pSdoComCon_p-> m_uiTransSize); bFlags = 0x30; @@ -2944,7 +2943,7 @@ static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p, tEplAsySdoCom * pAsySdoCom_p) { tEplKernel Ret; - BYTE bBuffer; + u8 bBuffer; unsigned int uiBuffer; unsigned int uiDataSize; unsigned long ulBuffer; @@ -3217,10 +3216,10 @@ static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p, //--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p, - DWORD dwAbortCode_p) + u32 dwAbortCode_p) { tEplKernel Ret; - BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE]; + u8 abFrame[EPL_MAX_SDO_FRAME_SIZE]; tEplFrame *pFrame; tEplAsySdoCom *pCommandFrame; unsigned int uiSizeOfFrame; @@ -3250,14 +3249,14 @@ static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p, AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], dwAbortCode_p); // set size of segment - AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, sizeof(DWORD)); + AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, sizeof(u32)); // update counter - pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD); + pSdoComCon_p->m_uiTransferredByte = sizeof(u32); pSdoComCon_p->m_uiTransSize = 0; // calc framesize - uiSizeOfFrame += sizeof(DWORD); + uiSizeOfFrame += sizeof(u32); // save abort code pSdoComCon_p->m_dwLastAbortCode = dwAbortCode_p; diff --git a/drivers/staging/epl/EplSdoUdpu.c b/drivers/staging/epl/EplSdoUdpu.c index be52233b3ee8..b409c9b7be48 100644 --- a/drivers/staging/epl/EplSdoUdpu.c +++ b/drivers/staging/epl/EplSdoUdpu.c @@ -72,11 +72,9 @@ #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) -#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) #include "SocketLinuxKernel.h" #include #include -#endif /***************************************************************************/ /* */ @@ -110,17 +108,9 @@ typedef struct { tEplSequLayerReceiveCb m_fpSdoAsySeqCb; SOCKET m_UdpSocket; -#if (TARGET_SYSTEM == _WIN32_) - HANDLE m_ThreadHandle; - LPCRITICAL_SECTION m_pCriticalSection; - CRITICAL_SECTION m_CriticalSection; - -#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) struct completion m_CompletionUdpThread; int m_ThreadHandle; int m_iTerminateThread; -#endif - } tEplSdoUdpInstance; //--------------------------------------------------------------------------- @@ -133,12 +123,7 @@ static tEplSdoUdpInstance SdoUdpInstance_g; // local function prototypes //--------------------------------------------------------------------------- -#if (TARGET_SYSTEM == _WIN32_) -static DWORD PUBLIC EplSdoUdpThread(LPVOID lpParameter); - -#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) static int EplSdoUdpThread(void *pArg_p); -#endif /***************************************************************************/ /* */ @@ -177,7 +162,7 @@ static int EplSdoUdpThread(void *pArg_p); // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p) +tEplKernel EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p) { tEplKernel Ret; @@ -205,16 +190,10 @@ tEplKernel PUBLIC EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p) +tEplKernel EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p) { tEplKernel Ret; -#if (TARGET_SYSTEM == _WIN32_) - int iError; - WSADATA Wsa; - -#endif - // set instance variables to 0 EPL_MEMSET(&SdoUdpInstance_g, 0x00, sizeof(SdoUdpInstance_g)); @@ -228,24 +207,8 @@ tEplKernel PUBLIC EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p) goto Exit; } -#if (TARGET_SYSTEM == _WIN32_) - // start winsock2 for win32 - // windows specific start of socket - iError = WSAStartup(MAKEWORD(2, 0), &Wsa); - if (iError != 0) { - Ret = kEplSdoUdpNoSocket; - goto Exit; - } - // create critical section for acccess of instnace variables - SdoUdpInstance_g.m_pCriticalSection = - &SdoUdpInstance_g.m_CriticalSection; - InitializeCriticalSection(SdoUdpInstance_g.m_pCriticalSection); - -#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) init_completion(&SdoUdpInstance_g.m_CompletionUdpThread); SdoUdpInstance_g.m_iTerminateThread = 0; -#endif - SdoUdpInstance_g.m_ThreadHandle = 0; SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET; @@ -273,32 +236,18 @@ tEplKernel PUBLIC EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p) // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoUdpuDelInstance() +tEplKernel EplSdoUdpuDelInstance(void) { tEplKernel Ret; -#if (TARGET_SYSTEM == _WIN32_) - BOOL fTermError; -#endif - Ret = kEplSuccessful; if (SdoUdpInstance_g.m_ThreadHandle != 0) { // listen thread was started // close thread -#if (TARGET_SYSTEM == _WIN32_) - fTermError = - TerminateThread(SdoUdpInstance_g.m_ThreadHandle, 0); - if (fTermError == FALSE) { - Ret = kEplSdoUdpThreadError; - goto Exit; - } -#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) SdoUdpInstance_g.m_iTerminateThread = 1; /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */ send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1); wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread); -#endif - SdoUdpInstance_g.m_ThreadHandle = 0; } @@ -307,19 +256,6 @@ tEplKernel PUBLIC EplSdoUdpuDelInstance() closesocket(SdoUdpInstance_g.m_UdpSocket); SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET; } -#if (TARGET_SYSTEM == _WIN32_) - // delete critical section - DeleteCriticalSection(SdoUdpInstance_g.m_pCriticalSection); -#endif - -#if (TARGET_SYSTEM == _WIN32_) - // for win 32 - WSACleanup(); -#endif - -#if (TARGET_SYSTEM == _WIN32_) - Exit: -#endif return Ret; } @@ -340,18 +276,12 @@ tEplKernel PUBLIC EplSdoUdpuDelInstance() // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p, - unsigned int uiPort_p) +tEplKernel EplSdoUdpuConfig(unsigned long ulIpAddr_p, unsigned int uiPort_p) { tEplKernel Ret; struct sockaddr_in Addr; int iError; -#if (TARGET_SYSTEM == _WIN32_) - BOOL fTermError; - unsigned long ulThreadId; -#endif - Ret = kEplSuccessful; if (uiPort_p == 0) { // set UDP port to default port number @@ -364,21 +294,11 @@ tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p, if (SdoUdpInstance_g.m_ThreadHandle != 0) { // listen thread was started // close old thread -#if (TARGET_SYSTEM == _WIN32_) - fTermError = - TerminateThread(SdoUdpInstance_g.m_ThreadHandle, 0); - if (fTermError == FALSE) { - Ret = kEplSdoUdpThreadError; - goto Exit; - } -#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) SdoUdpInstance_g.m_iTerminateThread = 1; /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */ send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1); wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread); SdoUdpInstance_g.m_iTerminateThread = 0; -#endif - SdoUdpInstance_g.m_ThreadHandle = 0; } @@ -413,28 +333,12 @@ tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p, goto Exit; } // create Listen-Thread -#if (TARGET_SYSTEM == _WIN32_) - // for win32 - - // create thread - SdoUdpInstance_g.m_ThreadHandle = CreateThread(NULL, - 0, - EplSdoUdpThread, - &SdoUdpInstance_g, - 0, &ulThreadId); - if (SdoUdpInstance_g.m_ThreadHandle == NULL) { - Ret = kEplSdoUdpThreadError; - goto Exit; - } -#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) - SdoUdpInstance_g.m_ThreadHandle = kernel_thread(EplSdoUdpThread, &SdoUdpInstance_g, CLONE_KERNEL); if (SdoUdpInstance_g.m_ThreadHandle == 0) { Ret = kEplSdoUdpThreadError; goto Exit; } -#endif Exit: return Ret; @@ -459,8 +363,8 @@ tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoUdpuInitCon(tEplSdoConHdl * pSdoConHandle_p, - unsigned int uiTargetNodeId_p) +tEplKernel EplSdoUdpuInitCon(tEplSdoConHdl *pSdoConHandle_p, + unsigned int uiTargetNodeId_p) { tEplKernel Ret; unsigned int uiCount; @@ -526,8 +430,8 @@ tEplKernel PUBLIC EplSdoUdpuInitCon(tEplSdoConHdl * pSdoConHandle_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p, - tEplFrame * pSrcData_p, DWORD dwDataSize_p) +tEplKernel EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p, + tEplFrame *pSrcData_p, u32 dwDataSize_p) { tEplKernel Ret; int iError; @@ -553,22 +457,12 @@ tEplKernel PUBLIC EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p, // call sendto Addr.sin_family = AF_INET; -#if (TARGET_SYSTEM == _WIN32_) - // enter critical section for process function - EnterCriticalSection(SdoUdpInstance_g.m_pCriticalSection); -#endif - Addr.sin_port = (unsigned short)SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray]. m_uiPort; Addr.sin_addr.s_addr = SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_ulIpAddr; -#if (TARGET_SYSTEM == _WIN32_) - // leave critical section for process function - LeaveCriticalSection(SdoUdpInstance_g.m_pCriticalSection); -#endif - iError = sendto(SdoUdpInstance_g.m_UdpSocket, // sockethandle (const char *)&pSrcData_p->m_le_bMessageType, // data to send dwDataSize_p, // number of bytes to send @@ -603,7 +497,7 @@ tEplKernel PUBLIC EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p, // State: // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p) +tEplKernel EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p) { tEplKernel Ret; unsigned int uiArray; @@ -642,17 +536,13 @@ tEplKernel PUBLIC EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p) // Parameters: lpParameter = pointer to parameter type tEplSdoUdpThreadPara // // -// Returns: DWORD = errorcode +// Returns: u32 = errorcode // // // State: // //--------------------------------------------------------------------------- -#if (TARGET_SYSTEM == _WIN32_) -static DWORD PUBLIC EplSdoUdpThread(LPVOID lpParameter) -#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) static int EplSdoUdpThread(void *pArg_p) -#endif { tEplSdoUdpInstance *pInstance; @@ -660,21 +550,15 @@ static int EplSdoUdpThread(void *pArg_p) int iError; int iCount; int iFreeEntry; - BYTE abBuffer[EPL_MAX_SDO_REC_FRAME_SIZE]; + u8 abBuffer[EPL_MAX_SDO_REC_FRAME_SIZE]; unsigned int uiSize; tEplSdoConHdl SdoConHdl; -#if (TARGET_SYSTEM == _WIN32_) - pInstance = (tEplSdoUdpInstance *) lpParameter; - - for (;;) -#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) pInstance = (tEplSdoUdpInstance *) pArg_p; daemonize("EplSdoUdpThread"); allow_signal(SIGTERM); for (; pInstance->m_iTerminateThread == 0;) -#endif { // wait for data @@ -685,20 +569,13 @@ static int EplSdoUdpThread(void *pArg_p) 0, // flags (struct sockaddr *)&RemoteAddr, (int *)&uiSize); -#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) if (iError == -ERESTARTSYS) { break; } -#endif if (iError > 0) { // get handle for higher layer iCount = 0; iFreeEntry = 0xFFFF; -#if (TARGET_SYSTEM == _WIN32_) - // enter critical section for process function - EnterCriticalSection(SdoUdpInstance_g. - m_pCriticalSection); -#endif while (iCount < EPL_SDO_MAX_CONNECTION_UDP) { // check if this connection is already known if ((pInstance->m_aSdoAbsUdpConnection[iCount]. @@ -734,11 +611,6 @@ static int EplSdoUdpThread(void *pArg_p) pInstance-> m_aSdoAbsUdpConnection[iFreeEntry]. m_uiPort = RemoteAddr.sin_port; -#if (TARGET_SYSTEM == _WIN32_) - // leave critical section for process function - LeaveCriticalSection(SdoUdpInstance_g. - m_pCriticalSection); -#endif // call callback SdoConHdl = iFreeEntry; SdoConHdl |= EPL_SDO_UDP_HANDLE; @@ -752,11 +624,6 @@ static int EplSdoUdpThread(void *pArg_p) } else { EPL_DBGLVL_SDO_TRACE0 ("Error in EplSdoUdpThread() no free handle\n"); -#if (TARGET_SYSTEM == _WIN32_) - // leave critical section for process function - LeaveCriticalSection(SdoUdpInstance_g. - m_pCriticalSection); -#endif } } else { @@ -764,11 +631,6 @@ static int EplSdoUdpThread(void *pArg_p) // call callback with correct handle SdoConHdl = iCount; SdoConHdl |= EPL_SDO_UDP_HANDLE; -#if (TARGET_SYSTEM == _WIN32_) - // leave critical section for process function - LeaveCriticalSection(SdoUdpInstance_g. - m_pCriticalSection); -#endif // offset 4 -> start of SDO Sequence header pInstance->m_fpSdoAsySeqCb(SdoConHdl, (tEplAsySdoSeq *) & @@ -778,10 +640,7 @@ static int EplSdoUdpThread(void *pArg_p) } // end of if(iError!=SOCKET_ERROR) } // end of for(;;) -#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) complete_and_exit(&SdoUdpInstance_g.m_CompletionUdpThread, 0); -#endif - return 0; } diff --git a/drivers/staging/epl/EplStatusu.c b/drivers/staging/epl/EplStatusu.c index 689f9124ae29..b291399af108 100644 --- a/drivers/staging/epl/EplStatusu.c +++ b/drivers/staging/epl/EplStatusu.c @@ -137,8 +137,7 @@ static tEplStatusuInstance EplStatusuInstance_g; // local function prototypes //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplStatusuCbStatusResponse(tEplFrameInfo * - pFrameInfo_p); +static tEplKernel EplStatusuCbStatusResponse(tEplFrameInfo *pFrameInfo_p); //=========================================================================// // // @@ -164,7 +163,7 @@ static tEplKernel PUBLIC EplStatusuCbStatusResponse(tEplFrameInfo * // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplStatusuInit() +tEplKernel EplStatusuInit(void) { tEplKernel Ret; @@ -191,7 +190,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplStatusuInit() // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplStatusuAddInstance() +tEplKernel EplStatusuAddInstance(void) { tEplKernel Ret; @@ -228,7 +227,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplStatusuAddInstance() // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplStatusuDelInstance() +tEplKernel EplStatusuDelInstance(void) { tEplKernel Ret; @@ -258,7 +257,7 @@ EPLDLLEXPORT tEplKernel PUBLIC EplStatusuDelInstance() // //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplStatusuReset() +tEplKernel EplStatusuReset(void) { tEplKernel Ret; @@ -287,9 +286,8 @@ EPLDLLEXPORT tEplKernel PUBLIC EplStatusuReset() // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplStatusuRequestStatusResponse(unsigned int uiNodeId_p, - tEplStatusuCbResponse - pfnCbResponse_p) +tEplKernel EplStatusuRequestStatusResponse(unsigned int uiNodeId_p, + tEplStatusuCbResponse pfnCbResponse_p) { tEplKernel Ret; @@ -342,8 +340,7 @@ tEplKernel PUBLIC EplStatusuRequestStatusResponse(unsigned int uiNodeId_p, // State: // //--------------------------------------------------------------------------- -static tEplKernel PUBLIC EplStatusuCbStatusResponse(tEplFrameInfo * - pFrameInfo_p) +static tEplKernel EplStatusuCbStatusResponse(tEplFrameInfo *pFrameInfo_p) { tEplKernel Ret = kEplSuccessful; unsigned int uiNodeId; diff --git a/drivers/staging/epl/EplTarget.h b/drivers/staging/epl/EplTarget.h index b2b66f82c035..e76d21ff9d99 100644 --- a/drivers/staging/epl/EplTarget.h +++ b/drivers/staging/epl/EplTarget.h @@ -83,95 +83,11 @@ // applications needs to use one common library function (e.g. memcpy()). So // you can set (or change) it here. -#if (TARGET_SYSTEM == _WIN32_) - -#define _WIN32_WINDOWS 0x0401 -#define _WIN32_WINNT 0x0400 - -#include -#include - - //29.11.2004 f.j. sonst ist memcpy und memset unbekannt -#include - -#define EPL_MEMCPY(dst,src,siz) memcpy((void*)(dst),(const void*)(src),(size_t)(siz)); -#define EPL_MEMSET(dst,val,siz) memset((void*)(dst),(int)(val),(size_t)(siz)); - - // f.j.: die Funktionen für und sind in WinMem.c definiert - //definition der Prototypen -void FAR *MemAlloc(DWORD dwMemSize_p); -void MemFree(void FAR * pMem_p); - -#define EPL_MALLOC(siz) malloc((size_t)(siz)) -#define EPL_FREE(ptr) free((void *)ptr) - -#ifndef PRINTF0 -void trace(const char *fmt, ...); -#define PRINTF TRACE -#define PRINTF0(arg) TRACE0(arg) -#define PRINTF1(arg,p1) TRACE1(arg,p1) -#define PRINTF2(arg,p1,p2) TRACE2(arg,p1,p2) -#define PRINTF3(arg,p1,p2,p3) TRACE3(arg,p1,p2,p3) -#define PRINTF4(arg,p1,p2,p3,p4) TRACE4(arg,p1,p2,p3,p4) - //#define PRINTF printf - //#define PRINTF0(arg) PRINTF(arg) - //#define PRINTF1(arg,p1) PRINTF(arg,p1) - //#define PRINTF2(arg,p1,p2) PRINTF(arg,p1,p2) - //#define PRINTF3(arg,p1,p2,p3) PRINTF(arg,p1,p2,p3) - //#define PRINTF4(arg,p1,p2,p3,p4) PRINTF(arg,p1,p2,p3,p4) -#endif - -#ifdef ASSERTMSG -#undef ASSERTMSG -#endif - -#define ASSERTMSG(expr,string) if (!(expr)) { \ - MessageBox (NULL, string, "Assertion failed", MB_OK | MB_ICONERROR); \ - exit (-1);} - -#elif (TARGET_SYSTEM == _NO_OS_) - -#include -#include - - //29.11.2004 f.j. sonst ist memcpy und memset unbekannt -// #include - -#define EPL_MEMCPY(dst,src,siz) memcpy((void*)(dst),(const void*)(src),(size_t)(siz)); -#define EPL_MEMSET(dst,val,siz) memset((void*)(dst),(int)(val),(size_t)(siz)); - -#define EPL_MALLOC(siz) malloc((size_t)(siz)) -#define EPL_FREE(ptr) free((void *)ptr) - -#ifndef PRINTF0 -#define PRINTF TRACE -#define PRINTF0(arg) TRACE0(arg) -#define PRINTF1(arg,p1) TRACE1(arg,p1) -#define PRINTF2(arg,p1,p2) TRACE2(arg,p1,p2) -#define PRINTF3(arg,p1,p2,p3) TRACE3(arg,p1,p2,p3) -#define PRINTF4(arg,p1,p2,p3,p4) TRACE4(arg,p1,p2,p3,p4) - //#define PRINTF printf - //#define PRINTF0(arg) PRINTF(arg) - //#define PRINTF1(arg,p1) PRINTF(arg,p1) - //#define PRINTF2(arg,p1,p2) PRINTF(arg,p1,p2) - //#define PRINTF3(arg,p1,p2,p3) PRINTF(arg,p1,p2,p3) - //#define PRINTF4(arg,p1,p2,p3,p4) PRINTF(arg,p1,p2,p3,p4) -#endif - -#elif (TARGET_SYSTEM == _LINUX_) - -#ifndef __KERNEL__ -#include -#include -#else -// #include #include #include #include #include #include -#include -#endif //29.11.2004 f.j. sonst ist memcpy und memset unbekannt // #include @@ -179,13 +95,8 @@ void trace(const char *fmt, ...); #define EPL_MEMCPY(dst,src,siz) memcpy((void*)(dst),(const void*)(src),(size_t)(siz)); #define EPL_MEMSET(dst,val,siz) memset((void*)(dst),(int)(val),(size_t)(siz)); -#ifndef __KERNEL__ -#define EPL_MALLOC(siz) malloc((size_t)(siz)) -#define EPL_FREE(ptr) free((void *)ptr) -#else #define EPL_MALLOC(siz) kmalloc((size_t)(siz), GFP_KERNEL) #define EPL_FREE(ptr) kfree((void *)ptr) -#endif #ifndef PRINTF0 #define PRINTF TRACE @@ -202,8 +113,6 @@ void trace(const char *fmt, ...); //#define PRINTF4(arg,p1,p2,p3,p4) PRINTF(arg,p1,p2,p3,p4) #endif -#endif - #define EPL_TGT_INTMASK_ETH 0x0001 // ethernet interrupt #define EPL_TGT_INTMASK_DMA 0x0002 // DMA interrupt @@ -217,17 +126,15 @@ void trace(const char *fmt, ...); // currently no Timer functions are needed by EPL stack // so they are not implemented yet -//void PUBLIC TgtTimerInit(void); -//DWORD PUBLIC TgtGetTickCount(void); -//void PUBLIC TgtGetNetTime(tEplNetTime * pNetTime_p); +//void TgtTimerInit(void); +//u32 TgtGetTickCount(void); +//void TgtGetNetTime(tEplNetTime * pNetTime_p); // functions for ethernet driver -tEplKernel PUBLIC TgtInitEthIsr(void); -void PUBLIC TgtFreeEthIsr(void); -void PUBLIC TgtEnableGlobalInterrupt(BYTE fEnable_p); -void PUBLIC TgtEnableEthInterrupt0(BYTE fEnable_p, - unsigned int uiInterruptMask_p); -void PUBLIC TgtEnableEthInterrupt1(BYTE fEnable_p, - unsigned int uiInterruptMask_p); +tEplKernel TgtInitEthIsr(void); +void TgtFreeEthIsr(void); +void TgtEnableGlobalInterrupt(u8 fEnable_p); +void TgtEnableEthInterrupt0(u8 fEnable_p, unsigned int uiInterruptMask_p); +void TgtEnableEthInterrupt1(u8 fEnable_p, unsigned int uiInterruptMask_p); #endif // #ifndef _EPLTARGET_H_ diff --git a/drivers/staging/epl/EplTimer.h b/drivers/staging/epl/EplTimer.h index facbfd8740e6..d1a73eaf65c1 100644 --- a/drivers/staging/epl/EplTimer.h +++ b/drivers/staging/epl/EplTimer.h @@ -107,8 +107,7 @@ typedef struct { } tEplTimerEventArg; -typedef tEplKernel(PUBLIC * tEplTimerkCallback) (tEplTimerEventArg * - pEventArg_p); +typedef tEplKernel(* tEplTimerkCallback) (tEplTimerEventArg *pEventArg_p); //--------------------------------------------------------------------------- // function prototypes diff --git a/drivers/staging/epl/EplTimeruLinuxKernel.c b/drivers/staging/epl/EplTimeruLinuxKernel.c index 08820d184055..ff80fc80d021 100644 --- a/drivers/staging/epl/EplTimeruLinuxKernel.c +++ b/drivers/staging/epl/EplTimeruLinuxKernel.c @@ -99,7 +99,7 @@ typedef struct { //--------------------------------------------------------------------------- // local function prototypes //--------------------------------------------------------------------------- -static void PUBLIC EplTimeruCbMs(unsigned long ulParameter_p); +static void EplTimeruCbMs(unsigned long ulParameter_p); /***************************************************************************/ /* */ @@ -134,7 +134,7 @@ static void PUBLIC EplTimeruCbMs(unsigned long ulParameter_p); // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruInit() +tEplKernel EplTimeruInit(void) { tEplKernel Ret; @@ -157,7 +157,7 @@ tEplKernel PUBLIC EplTimeruInit() // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruAddInstance() +tEplKernel EplTimeruAddInstance(void) { tEplKernel Ret; @@ -182,7 +182,7 @@ tEplKernel PUBLIC EplTimeruAddInstance() // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruDelInstance() +tEplKernel EplTimeruDelInstance(void) { tEplKernel Ret; @@ -207,9 +207,9 @@ tEplKernel PUBLIC EplTimeruDelInstance() // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p) +tEplKernel EplTimeruSetTimerMs(tEplTimerHdl *pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p) { tEplKernel Ret = kEplSuccessful; tEplTimeruData *pData; @@ -257,9 +257,9 @@ tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p, // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p) +tEplKernel EplTimeruModifyTimerMs(tEplTimerHdl *pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p) { tEplKernel Ret = kEplSuccessful; tEplTimeruData *pData; @@ -315,7 +315,7 @@ tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p, // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p) +tEplKernel EplTimeruDeleteTimer(tEplTimerHdl *pTimerHdl_p) { tEplKernel Ret = kEplSuccessful; tEplTimeruData *pData; @@ -370,7 +370,7 @@ tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p) // //--------------------------------------------------------------------------- -BOOL PUBLIC EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p) +BOOL EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p) { BOOL fActive = FALSE; tEplTimeruData *pData; @@ -417,7 +417,7 @@ BOOL PUBLIC EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p) // State: // //--------------------------------------------------------------------------- -static void PUBLIC EplTimeruCbMs(unsigned long ulParameter_p) +static void EplTimeruCbMs(unsigned long ulParameter_p) { tEplKernel Ret = kEplSuccessful; tEplTimeruData *pData; diff --git a/drivers/staging/epl/EplTimeruNull.c b/drivers/staging/epl/EplTimeruNull.c deleted file mode 100644 index 40ce403cbd03..000000000000 --- a/drivers/staging/epl/EplTimeruNull.c +++ /dev/null @@ -1,312 +0,0 @@ -/**************************************************************************** - - (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 - www.systec-electronic.com - - Project: openPOWERLINK - - Description: source file for Epl Userspace-Timermodule NULL-Implementation - - License: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of SYSTEC electronic GmbH nor the names of its - contributors may be used to endorse or promote products derived - from this software without prior written permission. For written - permission, please contact info@systec-electronic.com. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Severability Clause: - - If a provision of this License is or becomes illegal, invalid or - unenforceable in any jurisdiction, that shall not affect: - 1. the validity or enforceability in that jurisdiction of any other - provision of this License; or - 2. the validity or enforceability in other jurisdictions of that or - any other provision of this License. - - ------------------------------------------------------------------------- - - $RCSfile: EplTimeruNull.c,v $ - - $Author: D.Krueger $ - - $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ - - $State: Exp $ - - Build Environment: - KEIL uVision 2 - - ------------------------------------------------------------------------- - - Revision History: - - 2006/07/06 k.t.: start of the implementation - -****************************************************************************/ - -#include "user/EplTimeru.h" - -/***************************************************************************/ -/* */ -/* */ -/* G L O B A L D E F I N I T I O N S */ -/* */ -/* */ -/***************************************************************************/ - -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// local types -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// modul globale vars -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// local function prototypes -//--------------------------------------------------------------------------- - -/***************************************************************************/ -/* */ -/* */ -/* C L A S S */ -/* */ -/* */ -/***************************************************************************/ -// -// Description: Epl Userspace-Timermodule NULL-Implementation -// -// -/***************************************************************************/ - -//=========================================================================// -// // -// P U B L I C F U N C T I O N S // -// // -//=========================================================================// - -//--------------------------------------------------------------------------- -// -// Function: EplTimeruInit -// -// Description: function init first instance -// -// -// -// Parameters: -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruInit() -{ - tEplKernel Ret; - - Ret = EplTimeruAddInstance(); - - return Ret; -} - -//--------------------------------------------------------------------------- -// -// Function: EplTimeruAddInstance -// -// Description: function init additional instance -// -// -// -// Parameters: -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruAddInstance() -{ - tEplKernel Ret; - - Ret = kEplSuccessful; - - return Ret; -} - -//--------------------------------------------------------------------------- -// -// Function: EplTimeruDelInstance -// -// Description: function delte instance -// -> under Win32 nothing to do -// -> no instnace table needed -// -// -// -// Parameters: -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruDelInstance() -{ - tEplKernel Ret; - - Ret = kEplSuccessful; - - return Ret; -} - -//--------------------------------------------------------------------------- -// -// Function: EplTimeruSetTimerMs -// -// Description: function create a timer and return a handle to the pointer -// -// -// -// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle -// ulTime_p = time for timer in ms -// Argument_p = argument for timer -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p) -{ - tEplKernel Ret; - - Ret = kEplSuccessful; - - // check handle - if (pTimerHdl_p == NULL) { - Ret = kEplTimerInvalidHandle; - goto Exit; - } - - Exit: - return Ret; -} - - //--------------------------------------------------------------------------- -// -// Function: EplTimeruModifyTimerMs -// -// Description: function change a timer and return a handle to the pointer -// -// -// -// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle -// ulTime_p = time for timer in ms -// Argument_p = argument for timer -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p) -{ - tEplKernel Ret; - - Ret = kEplSuccessful; - - // check parameter - if (pTimerHdl_p == NULL) { - Ret = kEplTimerInvalidHandle; - goto Exit; - } - - Exit: - return Ret; -} - - //--------------------------------------------------------------------------- -// -// Function: EplTimeruDeleteTimer -// -// Description: function delte a timer -// -// -// -// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p) -{ - tEplKernel Ret; - - Ret = kEplSuccessful; - - // check parameter - if (pTimerHdl_p == NULL) { - Ret = kEplTimerInvalidHandle; - goto Exit; - } - // set handle invalide - *pTimerHdl_p = 0; - - Exit: - return Ret; - -} - -//=========================================================================// -// // -// P R I V A T E F U N C T I O N S // -// // -//=========================================================================// - -// EOF diff --git a/drivers/staging/epl/EplTimeruWin32.c b/drivers/staging/epl/EplTimeruWin32.c deleted file mode 100644 index a967b4e59d4b..000000000000 --- a/drivers/staging/epl/EplTimeruWin32.c +++ /dev/null @@ -1,513 +0,0 @@ -/**************************************************************************** - - (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 - www.systec-electronic.com - - Project: openPOWERLINK - - Description: source file for Epl Userspace-Timermodule for Win32 - - License: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of SYSTEC electronic GmbH nor the names of its - contributors may be used to endorse or promote products derived - from this software without prior written permission. For written - permission, please contact info@systec-electronic.com. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Severability Clause: - - If a provision of this License is or becomes illegal, invalid or - unenforceable in any jurisdiction, that shall not affect: - 1. the validity or enforceability in that jurisdiction of any other - provision of this License; or - 2. the validity or enforceability in other jurisdictions of that or - any other provision of this License. - - ------------------------------------------------------------------------- - - $RCSfile: EplTimeruWin32.c,v $ - - $Author: D.Krueger $ - - $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ - - $State: Exp $ - - Build Environment: - GCC V3.4 - - ------------------------------------------------------------------------- - - Revision History: - - 2006/07/06 k.t.: start of the implementation - -****************************************************************************/ - -#include "user/EplTimeru.h" - -/***************************************************************************/ -/* */ -/* */ -/* G L O B A L D E F I N I T I O N S */ -/* */ -/* */ -/***************************************************************************/ - -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// local types -//--------------------------------------------------------------------------- -typedef struct { - tEplTimerArg TimerArgument; - HANDLE DelteHandle; - unsigned long ulTimeout; - -} tEplTimeruThread; - -typedef struct { - LPCRITICAL_SECTION m_pCriticalSection; - CRITICAL_SECTION m_CriticalSection; -} tEplTimeruInstance; -//--------------------------------------------------------------------------- -// modul globale vars -//--------------------------------------------------------------------------- -static tEplTimeruInstance EplTimeruInstance_g; -static tEplTimeruThread ThreadData_l; -//--------------------------------------------------------------------------- -// local function prototypes -//--------------------------------------------------------------------------- -DWORD PUBLIC EplSdoTimeruThreadms(LPVOID lpParameter); - -/***************************************************************************/ -/* */ -/* */ -/* C L A S S */ -/* */ -/* */ -/***************************************************************************/ -// -// Description: Epl Userspace-Timermodule for Win32 -// -// -/***************************************************************************/ - -//=========================================================================// -// // -// P U B L I C F U N C T I O N S // -// // -//=========================================================================// - -//--------------------------------------------------------------------------- -// -// Function: EplTimeruInit -// -// Description: function init first instance -// -// -// -// Parameters: -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruInit() -{ - tEplKernel Ret; - - Ret = EplTimeruAddInstance(); - - return Ret; -} - -//--------------------------------------------------------------------------- -// -// Function: EplTimeruAddInstance -// -// Description: function init additional instance -// -// -// -// Parameters: -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruAddInstance() -{ - tEplKernel Ret; - - Ret = kEplSuccessful; - - // create critical section - EplTimeruInstance_g.m_pCriticalSection = - &EplTimeruInstance_g.m_CriticalSection; - InitializeCriticalSection(EplTimeruInstance_g.m_pCriticalSection); - - return Ret; -} - -//--------------------------------------------------------------------------- -// -// Function: EplTimeruDelInstance -// -// Description: function delte instance -// -> under Win32 nothing to do -// -> no instnace table needed -// -// -// -// Parameters: -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruDelInstance() -{ - tEplKernel Ret; - - Ret = kEplSuccessful; - - return Ret; -} - -//--------------------------------------------------------------------------- -// -// Function: EplTimeruSetTimerMs -// -// Description: function create a timer and return a handle to the pointer -// -// -// -// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle -// ulTime_p = time for timer in ms -// Argument_p = argument for timer -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p) -{ - tEplKernel Ret; - HANDLE DeleteHandle; - HANDLE ThreadHandle; - DWORD ThreadId; - - Ret = kEplSuccessful; - - // check handle - if (pTimerHdl_p == NULL) { - Ret = kEplTimerInvalidHandle; - goto Exit; - } - // enter critical section - EnterCriticalSection(EplTimeruInstance_g.m_pCriticalSection); - - // first create event to delete timer - DeleteHandle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (DeleteHandle == NULL) { - Ret = kEplTimerNoTimerCreated; - goto Exit; - } - // set handle for caller - *pTimerHdl_p = (tEplTimerHdl) DeleteHandle; - - // fill data for thread - ThreadData_l.DelteHandle = DeleteHandle; - EPL_MEMCPY(&ThreadData_l.TimerArgument, &Argument_p, - sizeof(tEplTimerArg)); - ThreadData_l.ulTimeout = ulTime_p; - - // create thread to create waitable timer and wait for timer - ThreadHandle = CreateThread(NULL, - 0, - EplSdoTimeruThreadms, - &ThreadData_l, 0, &ThreadId); - if (ThreadHandle == NULL) { - // leave critical section - LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection); - - // delte handle - CloseHandle(DeleteHandle); - - Ret = kEplTimerNoTimerCreated; - goto Exit; - } - - Exit: - return Ret; -} - - //--------------------------------------------------------------------------- -// -// Function: EplTimeruModifyTimerMs -// -// Description: function change a timer and return a handle to the pointer -// -// -// -// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle -// ulTime_p = time for timer in ms -// Argument_p = argument for timer -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p) -{ - tEplKernel Ret; - HANDLE DeleteHandle; - HANDLE ThreadHandle; - DWORD ThreadId; - - Ret = kEplSuccessful; - - // check parameter - if (pTimerHdl_p == NULL) { - Ret = kEplTimerInvalidHandle; - goto Exit; - } - - DeleteHandle = (HANDLE) (*pTimerHdl_p); - - // set event to end timer task for this timer - SetEvent(DeleteHandle); - - // create new timer - // first create event to delete timer - DeleteHandle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (DeleteHandle == NULL) { - Ret = kEplTimerNoTimerCreated; - goto Exit; - } - // set handle for caller - *pTimerHdl_p = (tEplTimerHdl) DeleteHandle; - - // enter critical section - EnterCriticalSection(EplTimeruInstance_g.m_pCriticalSection); - - // fill data for thread - ThreadData_l.DelteHandle = DeleteHandle; - EPL_MEMCPY(&ThreadData_l.TimerArgument, &Argument_p, - sizeof(tEplTimerArg)); - ThreadData_l.ulTimeout = ulTime_p; - - // create thread to create waitable timer and wait for timer - ThreadHandle = CreateThread(NULL, - 0, - EplSdoTimeruThreadms, - &ThreadData_l, 0, &ThreadId); - if (ThreadHandle == NULL) { - // leave critical section - LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection); - - // delte handle - - Ret = kEplTimerNoTimerCreated; - goto Exit; - } - - Exit: - return Ret; -} - - //--------------------------------------------------------------------------- -// -// Function: EplTimeruDeleteTimer -// -// Description: function delte a timer -// -// -// -// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle -// -// -// Returns: tEplKernel = errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p) -{ - tEplKernel Ret; - HANDLE DeleteHandle; - - Ret = kEplSuccessful; - - // check parameter - if (pTimerHdl_p == NULL) { - Ret = kEplTimerInvalidHandle; - goto Exit; - } - - DeleteHandle = (HANDLE) (*pTimerHdl_p); - - // set event to end timer task for this timer - SetEvent(DeleteHandle); - - // set handle invalide - *pTimerHdl_p = 0; - - Exit: - return Ret; - -} - -//=========================================================================// -// // -// P R I V A T E F U N C T I O N S // -// // -//=========================================================================// - -//--------------------------------------------------------------------------- -// -// Function: EplSdoTimeruThreadms -// -// Description: function to process timer as thread -// -// -// -// Parameters: lpParameter = pointer to structur of type tEplTimeruThread -// -// -// Returns: DWORD = Errorcode -// -// -// State: -// -//--------------------------------------------------------------------------- -DWORD PUBLIC EplSdoTimeruThreadms(LPVOID lpParameter) -{ - tEplKernel Ret; - tEplTimeruThread *pThreadData; - HANDLE aHandles[2]; - BOOL fReturn; - LARGE_INTEGER TimeoutTime; - unsigned long ulEvent; - tEplEvent EplEvent; - tEplTimeruThread ThreadData; - tEplTimerEventArg TimerEventArg; - - Ret = kEplSuccessful; - - // get pointer to data - pThreadData = (tEplTimeruThread *) lpParameter; - // copy thread data - EPL_MEMCPY(&ThreadData, pThreadData, sizeof(ThreadData)); - pThreadData = &ThreadData; - - // leave critical section - LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection); - - // create waitable timer - aHandles[1] = CreateWaitableTimer(NULL, FALSE, NULL); - if (aHandles[1] == NULL) { - Ret = kEplTimerNoTimerCreated; - goto Exit; - } - // set timer - // set timeout interval -> needed to be negativ - // -> because relative timeout - // -> multiply by 10000 for 100 ns timebase of function - TimeoutTime.QuadPart = (((long long)pThreadData->ulTimeout) * -10000); - fReturn = SetWaitableTimer(aHandles[1], - &TimeoutTime, 0, NULL, NULL, FALSE); - if (fReturn == 0) { - Ret = kEplTimerNoTimerCreated; - goto Exit; - } - // save delte event handle in handle array - aHandles[0] = pThreadData->DelteHandle; - - // wait for one of the events - ulEvent = WaitForMultipleObjects(2, &aHandles[0], FALSE, INFINITE); - if (ulEvent == WAIT_OBJECT_0) { // delte event - - // close handels - CloseHandle(aHandles[1]); - // terminate thread - goto Exit; - } else if (ulEvent == (WAIT_OBJECT_0 + 1)) { // timer event - // call event function - TimerEventArg.m_TimerHdl = - (tEplTimerHdl) pThreadData->DelteHandle; - TimerEventArg.m_ulArg = pThreadData->TimerArgument.m_ulArg; - - EplEvent.m_EventSink = pThreadData->TimerArgument.m_EventSink; - EplEvent.m_EventType = kEplEventTypeTimer; - EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(tEplNetTime)); - EplEvent.m_pArg = &TimerEventArg; - EplEvent.m_uiSize = sizeof(TimerEventArg); - - Ret = EplEventuPost(&EplEvent); - - // close handels - CloseHandle(aHandles[1]); - // terminate thread - goto Exit; - - } else { // error - ulEvent = GetLastError(); - TRACE1("Error in WaitForMultipleObjects Errorcode: 0x%x\n", - ulEvent); - // terminate thread - goto Exit; - } - - Exit: - return Ret; -} - -// EOF diff --git a/drivers/staging/epl/SharedBuff.c b/drivers/staging/epl/SharedBuff.c index 9fb09d6bc28e..2b10c375f3e6 100644 --- a/drivers/staging/epl/SharedBuff.c +++ b/drivers/staging/epl/SharedBuff.c @@ -85,14 +85,8 @@ #include "SharedBuff.h" #include "ShbIpc.h" -// d.k. Linux kernel modules needs other header files for memcpy() -#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__) #include -#else -#include -#include -#include -#endif +#include /***************************************************************************/ /* */ @@ -102,8 +96,6 @@ /* */ /***************************************************************************/ -#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED) - //--------------------------------------------------------------------------- // Configuration //--------------------------------------------------------------------------- @@ -177,7 +169,7 @@ typedef struct { // Get pointer to Circular Shared Buffer //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p) +tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p) { tShbCirBuff *pShbCirBuff; @@ -193,7 +185,7 @@ INLINE_FUNCTION tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p) // Get pointer to Linear Shared Buffer //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbLinBuff *ShbLinGetBuffer(tShbInstance pShbInstance_p) +tShbLinBuff *ShbLinGetBuffer(tShbInstance pShbInstance_p) { tShbLinBuff *pShbLinBuff; @@ -210,7 +202,6 @@ int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p); void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p, unsigned int fTimeOut_p); -#endif //=========================================================================// // // @@ -218,7 +209,6 @@ void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p, // // //=========================================================================// -#if !defined(INLINE_ENABLED) // not inlined external functions //--------------------------------------------------------------------------- @@ -363,18 +353,13 @@ tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p) } -#endif // !defined(INLINE_ENABLED) - -#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED) - //--------------------------------------------------------------------------- // Reset Circular Shared Buffer //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p, - unsigned long ulTimeOut_p, - tShbCirSigHndlrReset - pfnSignalHandlerReset_p) +tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p, + unsigned long ulTimeOut_p, + tShbCirSigHndlrReset pfnSignalHandlerReset_p) { tShbCirBuff *pShbCirBuff; @@ -440,9 +425,9 @@ INLINE_FUNCTION tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p, // Write data block to Circular Shared Buffer //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p, - const void *pSrcDataBlock_p, - unsigned long ulDataBlockSize_p) +tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p, + const void *pSrcDataBlock_p, + unsigned long ulDataBlockSize_p) { tShbCirBuff *pShbCirBuff; @@ -608,9 +593,9 @@ INLINE_FUNCTION tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p, // Allocate block within the Circular Shared Buffer for chunk writing //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p, - tShbCirChunk * pShbCirChunk_p, - unsigned long ulDataBufferSize_p) +tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p, + tShbCirChunk * pShbCirChunk_p, + unsigned long ulDataBufferSize_p) { tShbCirBuff *pShbCirBuff; @@ -717,12 +702,11 @@ INLINE_FUNCTION tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p, // Write data chunk into an allocated buffer of the Circular Shared Buffer //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p, - tShbCirChunk * pShbCirChunk_p, - const void *pSrcDataChunk_p, - unsigned long ulDataChunkSize_p, - unsigned int - *pfBufferCompleted_p) +tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p, + tShbCirChunk *pShbCirChunk_p, + const void *pSrcDataChunk_p, + unsigned long ulDataChunkSize_p, + unsigned int *pfBufferCompleted_p) { tShbCirBuff *pShbCirBuff; @@ -857,10 +841,10 @@ INLINE_FUNCTION tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p, // Read data block from Circular Shared Buffer //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p, - void *pDstDataBlock_p, - unsigned long ulRdBuffSize_p, - unsigned long *pulDataBlockSize_p) +tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p, + void *pDstDataBlock_p, + unsigned long ulRdBuffSize_p, + unsigned long *pulDataBlockSize_p) { tShbCirBuff *pShbCirBuff; @@ -1009,9 +993,8 @@ INLINE_FUNCTION tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p, // Get data size of next readable block from Circular Shared Buffer //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p, - unsigned long - *pulDataBlockSize_p) +tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p, + unsigned long *pulDataBlockSize_p) { tShbCirBuff *pShbCirBuff; @@ -1070,9 +1053,8 @@ INLINE_FUNCTION tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p, // Get number of readable blocks from Circular Shared Buffer //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p, - unsigned long - *pulDataBlockCount_p) +tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p, + unsigned long *pulDataBlockCount_p) { tShbCirBuff *pShbCirBuff; @@ -1113,12 +1095,9 @@ INLINE_FUNCTION tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p, // d.k.: new parameter priority as enum //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbCirSetSignalHandlerNewData(tShbInstance - pShbInstance_p, - tShbCirSigHndlrNewData - pfnSignalHandlerNewData_p, - tShbPriority - ShbPriority_p) +tShbError ShbCirSetSignalHandlerNewData(tShbInstance pShbInstance_p, + tShbCirSigHndlrNewData pfnSignalHandlerNewData_p, + tShbPriority ShbPriority_p) { tShbCirBuff *pShbCirBuff; @@ -1165,10 +1144,6 @@ INLINE_FUNCTION tShbError ShbCirSetSignalHandlerNewData(tShbInstance } -#endif - -#if !defined(INLINE_ENABLED) - //--------------------------------------------------------------------------- // DEBUG: Trace Circular Shared Buffer //--------------------------------------------------------------------------- @@ -1413,18 +1388,13 @@ tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p) } -#endif // !defined(INLINE_ENABLED) - -#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED) - //--------------------------------------------------------------------------- // Write data block to Linear Shared Buffer //--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p, - unsigned long ulDstBufferOffs_p, - const void *pSrcDataBlock_p, - unsigned long ulDataBlockSize_p) +tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p, + unsigned long ulDstBufferOffs_p, + const void *pSrcDataBlock_p, + unsigned long ulDataBlockSize_p) { tShbLinBuff *pShbLinBuff; @@ -1489,11 +1459,10 @@ INLINE_FUNCTION tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p, //--------------------------------------------------------------------------- // Read data block from Linear Shared Buffer //--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p, - void *pDstDataBlock_p, - unsigned long ulSrcBufferOffs_p, - unsigned long ulDataBlockSize_p) +tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p, + void *pDstDataBlock_p, + unsigned long ulSrcBufferOffs_p, + unsigned long ulDataBlockSize_p) { tShbLinBuff *pShbLinBuff; @@ -1555,10 +1524,6 @@ INLINE_FUNCTION tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p, } -#endif - -#if !defined(INLINE_ENABLED) - //--------------------------------------------------------------------------- // DEBUG: Trace Linear Shared Buffer //--------------------------------------------------------------------------- @@ -1639,7 +1604,7 @@ tShbError ShbTraceDump(const unsigned char *pabStartAddr_p, ulBuffSize = ulDataSize_p; if (pszInfoText_p != NULL) { - TRACE0(pszInfoText_p); + TRACE1("%s", pszInfoText_p); } // dump buffer contents for (nRow = 0;; nRow++) { @@ -1794,6 +1759,4 @@ void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p, } -#endif - // EOF diff --git a/drivers/staging/epl/SharedBuff.h b/drivers/staging/epl/SharedBuff.h index 0ec1b4b9e6ae..4edbd0b2bd5a 100644 --- a/drivers/staging/epl/SharedBuff.h +++ b/drivers/staging/epl/SharedBuff.h @@ -110,15 +110,6 @@ typedef void (*tShbCirSigHndlrReset) (tShbInstance pShbInstance_p, extern "C" { #endif -/*#if defined(INLINE_FUNCTION_DEF) - #undef INLINE_FUNCTION - #define INLINE_FUNCTION INLINE_FUNCTION_DEF - #define INLINE_ENABLED TRUE - #define SHAREDBUFF_INLINED - #include "SharedBuff.c" -#endif -*/ - tShbError ShbInit(void); tShbError ShbExit(void); @@ -129,7 +120,6 @@ extern "C" { unsigned int *pfShbNewCreated_p); tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p); -#if !defined(INLINE_ENABLED) tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p, unsigned long ulTimeOut_p, @@ -159,7 +149,6 @@ extern "C" { pfnShbSignalHandlerNewData_p, tShbPriority ShbPriority_p); -#endif // Linear Shared Buffer tShbError ShbLinAllocBuffer(unsigned long ulBufferSize_p, @@ -168,7 +157,6 @@ extern "C" { unsigned int *pfShbNewCreated_p); tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p); -#if !defined(INLINE_ENABLED) tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p, unsigned long ulDstBufferOffs_p, @@ -179,7 +167,6 @@ extern "C" { unsigned long ulSrcBufferOffs_p, unsigned long ulDataBlockSize_p); -#endif #ifndef NDEBUG tShbError ShbCirTraceBuffer(tShbInstance pShbInstance_p); @@ -194,10 +181,6 @@ extern "C" { #define ShbTraceDump(p0, p1, p2, p3) #endif -#undef INLINE_ENABLED // disable actual inlining of functions -#undef INLINE_FUNCTION -#define INLINE_FUNCTION // define INLINE_FUNCTION to nothing - #ifdef __cplusplus } #endif diff --git a/drivers/staging/epl/ShbIpc-LinuxKernel.c b/drivers/staging/epl/ShbIpc-LinuxKernel.c index 1d3cb3f13de1..497938bd09b9 100644 --- a/drivers/staging/epl/ShbIpc-LinuxKernel.c +++ b/drivers/staging/epl/ShbIpc-LinuxKernel.c @@ -79,8 +79,6 @@ /* */ /***************************************************************************/ -#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) - //--------------------------------------------------------------------------- // Configuration //--------------------------------------------------------------------------- @@ -211,13 +209,11 @@ static inline tShbMemHeader *ShbIpcGetShbMemHeader(tShbMemInst * pShbMemInst_p) // not inlined internal functions int ShbIpcThreadSignalNewData(void *pvThreadParam_p); int ShbIpcThreadSignalJobReady(void *pvThreadParam_p); -#endif //--------------------------------------------------------------------------- // modul globale vars //--------------------------------------------------------------------------- -#if !defined(SHBIPC_INLINE_ENABLED) struct sShbMemTable *psMemTableElementFirst_g; static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p); @@ -230,7 +226,6 @@ static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256]); static unsigned long ShbIpcCrc32GetCrc(const char *pcString, unsigned long aulCrcTable[256]); -#endif //=========================================================================// // // @@ -238,7 +233,6 @@ static unsigned long ShbIpcCrc32GetCrc(const char *pcString, // // //=========================================================================// -#if !defined(SHBIPC_INLINE_ENABLED) // not inlined external functions //--------------------------------------------------------------------------- @@ -433,15 +427,11 @@ tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p) return (ShbError); } -#endif // !defined(SHBIPC_INLINE_ENABLED) - -#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) - //--------------------------------------------------------------------------- // Enter atomic section for Shared Buffer access //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p) +tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p) { tShbMemInst *pShbMemInst; @@ -469,7 +459,7 @@ INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p) // Leave atomic section for Shared Buffer access //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p) +tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p) { tShbMemInst *pShbMemInst; @@ -496,12 +486,9 @@ INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p) // Start signaling of new data (called from reading process) //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance - pShbInstance_p, - tSigHndlrNewData - pfnSignalHandlerNewData_p, - tShbPriority - ShbPriority_p) +tShbError ShbIpcStartSignalingNewData(tShbInstance pShbInstance_p, + tSigHndlrNewData pfnSignalHandlerNewData_p, + tShbPriority ShbPriority_p) { tShbMemInst *pShbMemInst; tShbMemHeader *pShbMemHeader; @@ -557,8 +544,7 @@ INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance // Stop signaling of new data (called from reading process) //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance - pShbInstance_p) +tShbError ShbIpcStopSignalingNewData(tShbInstance pShbInstance_p) { tShbMemInst *pShbMemInst; tShbMemHeader *pShbMemHeader; @@ -604,7 +590,7 @@ INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance // Signal new data (called from writing process) //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p) +tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p) { tShbMemHeader *pShbMemHeader; @@ -625,12 +611,9 @@ INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p) // Start signaling for job ready (called from waiting process) //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance - pShbInstance_p, - unsigned long - ulTimeOut_p, - tSigHndlrJobReady - pfnSignalHandlerJobReady_p) +tShbError ShbIpcStartSignalingJobReady(tShbInstance pShbInstance_p, + unsigned long ulTimeOut_p, + tSigHndlrJobReady pfnSignalHandlerJobReady_p) { tShbMemInst *pShbMemInst; tShbMemHeader *pShbMemHeader; @@ -663,7 +646,7 @@ INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance // Signal job ready (called from executing process) //--------------------------------------------------------------------------- -INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p) +tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p) { tShbMemHeader *pShbMemHeader; @@ -685,7 +668,7 @@ INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p) // Get pointer to common used share memory area //--------------------------------------------------------------------------- -INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p) +void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p) { tShbMemHeader *pShbMemHeader; @@ -694,7 +677,7 @@ INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p) pShbMemHeader = ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p)); if (pShbMemHeader != NULL) { - pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader); + pShbShMemPtr = (u8 *) pShbMemHeader + sizeof(tShbMemHeader); } else { pShbShMemPtr = NULL; } @@ -703,16 +686,12 @@ INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p) } -#endif - //=========================================================================// // // // P R I V A T E F U N C T I O N S // // // //=========================================================================// -#if !defined(SHBIPC_INLINE_ENABLED) - //--------------------------------------------------------------------------- // Get pointer to process local information structure //--------------------------------------------------------------------------- @@ -963,4 +942,3 @@ static void ShbIpcDeleteListElement(int iBufferId) } -#endif diff --git a/drivers/staging/epl/ShbIpc-Win32.c b/drivers/staging/epl/ShbIpc-Win32.c deleted file mode 100644 index b9181471ae0b..000000000000 --- a/drivers/staging/epl/ShbIpc-Win32.c +++ /dev/null @@ -1,1202 +0,0 @@ -/**************************************************************************** - - (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 - www.systec-electronic.com - - Project: Project independend shared buffer (linear + circular) - - Description: Implementation of platform specific part for the - shared buffer - (Implementation for Win32) - - License: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of SYSTEC electronic GmbH nor the names of its - contributors may be used to endorse or promote products derived - from this software without prior written permission. For written - permission, please contact info@systec-electronic.com. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Severability Clause: - - If a provision of this License is or becomes illegal, invalid or - unenforceable in any jurisdiction, that shall not affect: - 1. the validity or enforceability in that jurisdiction of any other - provision of this License; or - 2. the validity or enforceability in other jurisdictions of that or - any other provision of this License. - - ------------------------------------------------------------------------- - - 2006/06/27 -rs: V 1.00 (initial version) - -****************************************************************************/ - -#define WINVER 0x0400 // #defines necessary for usage of -#define _WIN32_WINNT 0x0400 // function - -#include -#include -#include "global.h" -#include "sharedbuff.h" -#include "shbipc.h" - -/***************************************************************************/ -/* */ -/* */ -/* G L O B A L D E F I N I T I O N S */ -/* */ -/* */ -/***************************************************************************/ - -#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) - -//--------------------------------------------------------------------------- -// Configuration -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Constant definitions -//--------------------------------------------------------------------------- - -#define MAX_LEN_BUFFER_ID MAX_PATH - -#define IDX_EVENT_NEW_DATA 0 -#define IDX_EVENT_TERM_REQU 1 -#define IDX_EVENT_TERM_RESP 2 - -#define NAME_MUTEX_BUFF_ACCESS "BuffAccess" -#define NAME_EVENT_NEW_DATA "NewData" -#define NAME_EVENT_TERM_REQU "TermRequ" -#define NAME_EVENT_TERM_RESP "TermResp" -#define NAME_EVENT_JOB_READY "JobReady" - -#define TIMEOUT_ENTER_ATOMIC 1000 // for debgging: INFINITE -#define TIMEOUT_TERM_THREAD 2000 - -#define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+") -#define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*") - -//--------------------------------------------------------------------------- -// Local types -//--------------------------------------------------------------------------- - -// This structure is the common header for the shared memory region used -// by all processes attached this shared memory. It includes common -// information to administrate/manage the shared buffer from a couple of -// separated processes (e.g. the refernce counter). This structure is -// located at the start of the shared memory region itself and exists -// consequently only one times per shared memory instance. -typedef struct { - unsigned long m_SbhMagicID; // magic ID ("SBH*") - unsigned long m_ulShMemSize; - unsigned long m_ulRefCount; - char m_szBufferID[MAX_LEN_BUFFER_ID]; - -#ifndef NDEBUG - unsigned long m_ulOwnerProcID; -#endif - -} tShbMemHeader; - -// This structure is the "external entry point" from a separate process -// to get access to a shared buffer. This structure includes all platform -// resp. target specific information to administrate/manage the shared -// buffer from a separate process. Every process attached to the shared -// buffer has its own runtime instance of this structure with its individual -// runtime data (e.g. the scope of an event handle is limitted to the -// owner process only). The structure member points -// to the (process specific) start address of the shared memory region -// itself. -typedef struct { - unsigned long m_SbiMagicID; // magic ID ("SBI+") - HANDLE m_hSharedMem; - HANDLE m_hMutexBuffAccess; - HANDLE m_hThreadNewData; // thraed to signal that new data are available - HANDLE m_ahEventNewData[3]; // IDX_EVENT_NEW_DATA + IDX_EVENT_TERM_REQU + ID_EVENT_TERM_RESP - tSigHndlrNewData m_pfnSigHndlrNewData; - HANDLE m_hThreadJobReady; // thread to signal that a job/operation is ready now (e.g. reset buffer) - HANDLE m_hEventJobReady; - unsigned long m_ulTimeOutJobReady; - tSigHndlrJobReady m_pfnSigHndlrJobReady; - tShbMemHeader *m_pShbMemHeader; - -#ifndef NDEBUG - unsigned long m_ulThreadIDNewData; - unsigned long m_ulThreadIDJobReady; -#endif - -} tShbMemInst; - -//--------------------------------------------------------------------------- -// Global variables -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Local variables -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Prototypes of internal functions -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// Get pointer to process local information structure -//--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p) -{ - - tShbMemInst *pShbMemInst; - - pShbMemInst = (tShbMemInst *) pShbInstance_p; - ASSERT(pShbMemInst->m_SbiMagicID == SBI_MAGIC_ID); - - return (pShbMemInst); - -} - -//--------------------------------------------------------------------------- -// Get pointer to shared memory header -//--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbMemHeader *ShbIpcGetShbMemHeader(tShbInstance - pShbInstance_p) -{ - - tShbMemInst *pShbMemInst; - tShbMemHeader *pShbMemHeader; - - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); - pShbMemHeader = pShbMemInst->m_pShbMemHeader; - ASSERT(pShbMemHeader->m_SbhMagicID == SBH_MAGIC_ID); - - return (pShbMemHeader); - -} - -// not inlined internal functions -DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p); -DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p); -const char *ShbIpcGetUniformObjectName(const char *pszEventJobName_p, - const char *pszBufferID_p, - BOOL fGlobalObject_p); - -#endif - -#if !defined(SHBIPC_INLINE_ENABLED) -// true internal functions (not inlined) -static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p); -static void ShbIpcReleasePrivateMem(void *pMem_p); -#endif - -//=========================================================================// -// // -// P U B L I C F U N C T I O N S // -// // -//=========================================================================// - -#if !defined(SHBIPC_INLINE_ENABLED) -// not inlined external functions - -//--------------------------------------------------------------------------- -// Initialize IPC for Shared Buffer Module -//--------------------------------------------------------------------------- - -tShbError ShbIpcInit(void) -{ - - return (kShbOk); - -} - -//--------------------------------------------------------------------------- -// Deinitialize IPC for Shared Buffer Module -//--------------------------------------------------------------------------- - -tShbError ShbIpcExit(void) -{ - - return (kShbOk); - -} - -//--------------------------------------------------------------------------- -// Allocate Shared Buffer -//--------------------------------------------------------------------------- - -tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p, - const char *pszBufferID_p, - tShbInstance * ppShbInstance_p, - unsigned int *pfShbNewCreated_p) -{ - - HANDLE hSharedMem; - LPVOID pSharedMem; - unsigned long ulShMemSize; - tShbMemInst *pShbMemInst; - tShbMemHeader *pShbMemHeader; - tShbInstance pShbInstance; - unsigned int fShMemNewCreated; - const char *pszObjectName; - HANDLE hMutexBuffAccess; - HANDLE hEventNewData; - HANDLE hEventJobReady; - tShbError ShbError; - - ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader); - pSharedMem = NULL; - pShbInstance = NULL; - fShMemNewCreated = FALSE; - ShbError = kShbOk; - - //--------------------------------------------------------------- - // (1) open an existing or create a new shared memory - //--------------------------------------------------------------- - // try to open an already existing shared memory - // (created by an another process) - hSharedMem = OpenFileMapping(FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess - FALSE, // BOOL bInheritHandle - pszBufferID_p); // LPCTSTR lpName - if (hSharedMem != NULL) { - // a shared memory already exists - fShMemNewCreated = FALSE; - } else { - // it seams that this process is the first who wants to use the - // shared memory, so it has to create a new shared memory - hSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE, // HANDLE hFile - NULL, // LPSECURITY_ATTRIBUTES lpAttributes - PAGE_READWRITE, // DWORD flProtect - 0, // DWORD dwMaximumSizeHigh - ulShMemSize, // DWORD dwMaximumSizeLow - pszBufferID_p); // LPCTSTR lpName - - fShMemNewCreated = TRUE; - } - - if (hSharedMem == NULL) { - ShbError = kShbOutOfMem; - goto Exit; - } - - //--------------------------------------------------------------- - // (2) get the pointer to the shared memory - //--------------------------------------------------------------- - pSharedMem = MapViewOfFile(hSharedMem, // HANDLE hFileMappingObject - FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess, - 0, // DWORD dwFileOffsetHigh, - 0, // DWORD dwFileOffsetLow, - ulShMemSize); // SIZE_T dwNumberOfBytesToMap - - if (pSharedMem == NULL) { - ShbError = kShbOutOfMem; - goto Exit; - } - - //--------------------------------------------------------------- - // (3) setup or update header and management information - //--------------------------------------------------------------- - pShbMemHeader = (tShbMemHeader *) pSharedMem; - - // allocate a memory block from process specific mempool to save - // process local information to administrate/manage the shared buffer - pShbMemInst = - (tShbMemInst *) ShbIpcAllocPrivateMem(sizeof(tShbMemInst)); - if (pShbMemInst == NULL) { - ShbError = kShbOutOfMem; - goto Exit; - } - // reset complete header to default values - pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID; - pShbMemInst->m_hSharedMem = hSharedMem; - pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE; - pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE; - pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = - INVALID_HANDLE_VALUE; - pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = - INVALID_HANDLE_VALUE; - pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = - INVALID_HANDLE_VALUE; - pShbMemInst->m_pfnSigHndlrNewData = NULL; - pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE; - pShbMemInst->m_hEventJobReady = INVALID_HANDLE_VALUE; - pShbMemInst->m_ulTimeOutJobReady = 0; - pShbMemInst->m_pfnSigHndlrJobReady = NULL; - pShbMemInst->m_pShbMemHeader = pShbMemHeader; - -#ifndef NDEBUG - { - pShbMemInst->m_ulThreadIDNewData = 0; - pShbMemInst->m_ulThreadIDJobReady = 0; - } -#endif - - // create mutex for buffer access - pszObjectName = - ShbIpcGetUniformObjectName(NAME_MUTEX_BUFF_ACCESS, pszBufferID_p, - TRUE); - hMutexBuffAccess = CreateMutex(NULL, // LPSECURITY_ATTRIBUTES lpMutexAttributes - FALSE, // BOOL bInitialOwner - pszObjectName); // LPCTSTR lpName - pShbMemInst->m_hMutexBuffAccess = hMutexBuffAccess; - ASSERT(pShbMemInst->m_hMutexBuffAccess != NULL); - - // The EventNewData is used for signaling of new data after a write - // operation (SetEvent) as well as for waiting for new data on the - // reader side (WaitForMultipleObjects). Because it's not known if - // this process will be read or write data, the event will be - // always created here. - pszObjectName = - ShbIpcGetUniformObjectName(NAME_EVENT_NEW_DATA, pszBufferID_p, - TRUE); - hEventNewData = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes - FALSE, // BOOL bManualReset - FALSE, // BOOL bInitialState - pszObjectName); // LPCTSTR lpName - pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = hEventNewData; - ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != NULL); - - // The EventJobReady is used for signaling that a job is done (SetEvent) - // as well as for waiting for finishing of a job (WaitForMultipleObjects). - // Because it's not known if this process will signal or wait, the event - // will be always created here. - pszObjectName = - ShbIpcGetUniformObjectName(NAME_EVENT_JOB_READY, pszBufferID_p, - TRUE); - hEventJobReady = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes - FALSE, // BOOL bManualReset - FALSE, // BOOL bInitialState - pszObjectName); // LPCTSTR lpName - pShbMemInst->m_hEventJobReady = hEventJobReady; - ASSERT(pShbMemInst->m_hEventJobReady != NULL); - - if (fShMemNewCreated) { - // this process was the first who wanted to use the shared memory, - // so a new shared memory was created - // -> setup new header information inside the shared memory region - // itself - pShbMemHeader->m_SbhMagicID = SBH_MAGIC_ID; - pShbMemHeader->m_ulShMemSize = ulShMemSize; - pShbMemHeader->m_ulRefCount = 1; - strncpy(pShbMemHeader->m_szBufferID, pszBufferID_p, - sizeof(pShbMemHeader->m_szBufferID) - 1); - -#ifndef NDEBUG - { - pShbMemHeader->m_ulOwnerProcID = GetCurrentProcessId(); - } -#endif - } else { - // any other process has created the shared memory and this - // process has only attached to it - // -> check and update existing header information inside the - // shared memory region itself - if (pShbMemHeader->m_ulShMemSize != ulShMemSize) { - ShbError = kShbOpenMismatch; - goto Exit; - } -#ifndef NDEBUG - { - if (strncmp - (pShbMemHeader->m_szBufferID, pszBufferID_p, - sizeof(pShbMemHeader->m_szBufferID) - 1)) { - ShbError = kShbOpenMismatch; - goto Exit; - } - } -#endif - - pShbMemHeader->m_ulRefCount++; - } - - // set abstarct "handle" for returning to application - pShbInstance = (tShbInstance *) pShbMemInst; - - Exit: - - if (ShbError != kShbOk) { - if (pShbMemInst != NULL) { - ShbIpcReleasePrivateMem(pShbMemInst); - } - if (pSharedMem != NULL) { - UnmapViewOfFile(pSharedMem); - } - if (hSharedMem != NULL) { - CloseHandle(hSharedMem); - } - } - - *pfShbNewCreated_p = fShMemNewCreated; - *ppShbInstance_p = pShbInstance; - - return (ShbError); - -} - -//--------------------------------------------------------------------------- -// Release Shared Buffer -//--------------------------------------------------------------------------- - -tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p) -{ - - tShbMemInst *pShbMemInst; - tShbMemHeader *pShbMemHeader; - HANDLE hEventNewData; - HANDLE hMutexBuffAccess; - tShbError ShbError; - tShbError ShbError2; - - if (pShbInstance_p == NULL) { - return (kShbOk); - } - - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); - pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p); - - if (!--pShbMemHeader->m_ulRefCount) { - ShbError = kShbOk; - } else { - ShbError = kShbMemUsedByOtherProcs; - } - - ShbError2 = ShbIpcStopSignalingNewData(pShbInstance_p); - hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]; - if (hEventNewData != INVALID_HANDLE_VALUE) { - CloseHandle(hEventNewData); - pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = - INVALID_HANDLE_VALUE; - } - - hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess; - if (hMutexBuffAccess != INVALID_HANDLE_VALUE) { - CloseHandle(hMutexBuffAccess); - pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE; - } - - UnmapViewOfFile(pShbMemHeader); - if (pShbMemInst->m_hSharedMem != INVALID_HANDLE_VALUE) { - CloseHandle(pShbMemInst->m_hSharedMem); - pShbMemInst->m_hSharedMem = INVALID_HANDLE_VALUE; - } - - ShbIpcReleasePrivateMem(pShbMemInst); - - if (ShbError == kShbOk) { - ShbError = ShbError2; - } - - return (ShbError); - -} - -#endif // !defined(SHBIPC_INLINE_ENABLED) - -#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) - -//--------------------------------------------------------------------------- -// Enter atomic section for Shared Buffer access -//--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p) -{ - - tShbMemInst *pShbMemInst; - HANDLE hMutexBuffAccess; - DWORD dwWaitResult; - tShbError ShbError; - - if (pShbInstance_p == NULL) { - return (kShbInvalidArg); - } - - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); - ShbError = kShbOk; - - hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess; - if (hMutexBuffAccess != INVALID_HANDLE_VALUE) { - dwWaitResult = - WaitForSingleObject(hMutexBuffAccess, TIMEOUT_ENTER_ATOMIC); - switch (dwWaitResult) { - case WAIT_OBJECT_0 + 0: - { - break; - } - - case WAIT_TIMEOUT: - { - TRACE0 - ("\nShbIpcEnterAtomicSection(): WAIT_TIMEOUT"); - ASSERT(0); - ShbError = kShbBufferInvalid; - break; - } - - case WAIT_ABANDONED: - { - TRACE0 - ("\nShbIpcEnterAtomicSection(): WAIT_ABANDONED"); - ASSERT(0); - ShbError = kShbBufferInvalid; - break; - } - - case WAIT_FAILED: - { - TRACE1 - ("\nShbIpcEnterAtomicSection(): WAIT_FAILED -> LastError=%ld", - GetLastError()); - ASSERT(0); - ShbError = kShbBufferInvalid; - break; - } - - default: - { - TRACE1 - ("\nShbIpcEnterAtomicSection(): unknown error -> LastError=%ld", - GetLastError()); - ASSERT(0); - ShbError = kShbBufferInvalid; - break; - } - } - } else { - ShbError = kShbBufferInvalid; - } - - return (ShbError); - -} - -//--------------------------------------------------------------------------- -// Leave atomic section for Shared Buffer access -//--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p) -{ - - tShbMemInst *pShbMemInst; - HANDLE hMutexBuffAccess; - BOOL fRes; - tShbError ShbError; - - if (pShbInstance_p == NULL) { - return (kShbInvalidArg); - } - - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); - ShbError = kShbOk; - - hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess; - if (hMutexBuffAccess != INVALID_HANDLE_VALUE) { - fRes = ReleaseMutex(hMutexBuffAccess); - ASSERT(fRes); - } else { - ShbError = kShbBufferInvalid; - } - - return (ShbError); - -} - -//--------------------------------------------------------------------------- -// Start signaling of new data (called from reading process) -//--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance - pShbInstance_p, - tSigHndlrNewData - pfnSignalHandlerNewData_p, - tShbPriority - ShbPriority_p) -{ - - tShbMemInst *pShbMemInst; - tShbMemHeader *pShbMemHeader; - const char *pszObjectName; - HANDLE hEventTermRequ; - HANDLE hEventTermResp; - HANDLE hThreadNewData; - unsigned long ulThreadIDNewData; - tShbError ShbError; - int iPriority; - - if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) { - return (kShbInvalidArg); - } - - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); - pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p); - ShbError = kShbOk; - - if ((pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) || - (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != - INVALID_HANDLE_VALUE) - || (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != - INVALID_HANDLE_VALUE) - || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) { - ShbError = kShbAlreadySignaling; - goto Exit; - } - - pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p; - - // Because the event m_ahEventNewData[IDX_EVENT_NEW_DATA]> - // is used for signaling of new data after a write operation too (using - // SetEvent), it is always created here (see ). - - pszObjectName = - ShbIpcGetUniformObjectName(NAME_EVENT_TERM_REQU, - pShbMemHeader->m_szBufferID, FALSE); - hEventTermRequ = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes - FALSE, // BOOL bManualReset - FALSE, // BOOL bInitialState - pszObjectName); // LPCTSTR lpName - pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = hEventTermRequ; - ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != NULL); - - pszObjectName = - ShbIpcGetUniformObjectName(NAME_EVENT_TERM_RESP, - pShbMemHeader->m_szBufferID, FALSE); - hEventTermResp = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes - FALSE, // BOOL bManualReset - FALSE, // BOOL bInitialState - pszObjectName); // LPCTSTR lpName - pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = hEventTermResp; - ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != NULL); - - hThreadNewData = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes - 0, // SIZE_T dwStackSize - ShbIpcThreadSignalNewData, // LPTHREAD_START_ROUTINE lpStartAddress - pShbInstance_p, // LPVOID lpParameter - 0, // DWORD dwCreationFlags - &ulThreadIDNewData); // LPDWORD lpThreadId - - switch (ShbPriority_p) { - case kShbPriorityLow: - iPriority = THREAD_PRIORITY_BELOW_NORMAL; - break; - - case kShbPriorityNormal: - iPriority = THREAD_PRIORITY_NORMAL; - break; - - case kshbPriorityHigh: - iPriority = THREAD_PRIORITY_ABOVE_NORMAL; - break; - - } - - ASSERT(pShbMemInst->m_hThreadNewData != NULL); - - SetThreadPriority(hThreadNewData, iPriority); - - pShbMemInst->m_hThreadNewData = hThreadNewData; - -#ifndef NDEBUG - { - pShbMemInst->m_ulThreadIDNewData = ulThreadIDNewData; - } -#endif - - Exit: - - return (ShbError); - -} - -//--------------------------------------------------------------------------- -// Stop signaling of new data (called from reading process) -//--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance - pShbInstance_p) -{ - - tShbMemInst *pShbMemInst; - HANDLE hEventTermRequ; - HANDLE hEventTermResp; - DWORD dwWaitResult; - - if (pShbInstance_p == NULL) { - return (kShbInvalidArg); - } - - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); - - // terminate new data signaling thread - // (set event to wakeup the thread and dispose it - // to exit, then wait for confirmation using event ) - hEventTermRequ = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU]; - hEventTermResp = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]; - if ((hEventTermRequ != INVALID_HANDLE_VALUE) && - (hEventTermResp != INVALID_HANDLE_VALUE)) { - TRACE0("\nShbIpcStopSignalingNewData(): enter wait state"); - dwWaitResult = SignalObjectAndWait(hEventTermRequ, // HANDLE hObjectToSignal - hEventTermResp, // HANDLE hObjectToWaitOn - TIMEOUT_TERM_THREAD, // DWORD dwMilliseconds - FALSE); // BOOL bAlertable - TRACE0 - ("\nShbIpcStopSignalingNewData(): wait state leaved: ---> "); - switch (dwWaitResult) { - case WAIT_OBJECT_0 + 0: // event "new data signaling thread terminated" - { - TRACE0("Event = WAIT_OBJECT_0+0"); - break; - } - - default: - { - TRACE0("Unhandled Event"); - ASSERT(0); - break; - } - } - } - - if (pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) { - CloseHandle(pShbMemInst->m_hThreadNewData); - pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE; - } - - if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != - INVALID_HANDLE_VALUE) { - CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU]); - pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = - INVALID_HANDLE_VALUE; - } - - if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != - INVALID_HANDLE_VALUE) { - CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]); - pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = - INVALID_HANDLE_VALUE; - } - - pShbMemInst->m_pfnSigHndlrNewData = NULL; - - return (kShbOk); - -} - -//--------------------------------------------------------------------------- -// Signal new data (called from writing process) -//--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p) -{ - - tShbMemInst *pShbMemInst; - HANDLE hEventNewData; - BOOL fRes; - - // TRACE0("\nShbIpcSignalNewData(): enter\n"); - - if (pShbInstance_p == NULL) { - return (kShbInvalidArg); - } - - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); - - ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != - INVALID_HANDLE_VALUE); - hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]; - if (hEventNewData != INVALID_HANDLE_VALUE) { - fRes = SetEvent(hEventNewData); - // TRACE1("\nShbIpcSignalNewData(): EventNewData set (Result=%d)\n", (int)fRes); - ASSERT(fRes); - } - // TRACE0("\nShbIpcSignalNewData(): leave\n"); - return (kShbOk); - -} - -//--------------------------------------------------------------------------- -// Start signaling for job ready (called from waiting process) -//--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance - pShbInstance_p, - unsigned long - ulTimeOut_p, - tSigHndlrJobReady - pfnSignalHandlerJobReady_p) -{ - - tShbMemInst *pShbMemInst; - tShbMemHeader *pShbMemHeader; - HANDLE hThreadJobReady; - unsigned long ulThreadIDJobReady; - tShbError ShbError; - - if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) { - return (kShbInvalidArg); - } - - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); - pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p); - ShbError = kShbOk; - - if ((pShbMemInst->m_hThreadJobReady != INVALID_HANDLE_VALUE) || - (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) { - ShbError = kShbAlreadySignaling; - goto Exit; - } - - pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p; - pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p; - - // Because the event m_ahEventJobReady> is used for - // signaling of a finished job too (using SetEvent), it is always - // created here (see ). - - hThreadJobReady = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes - 0, // SIZE_T dwStackSize - ShbIpcThreadSignalJobReady, // LPTHREAD_START_ROUTINE lpStartAddress - pShbInstance_p, // LPVOID lpParameter - 0, // DWORD dwCreationFlags - &ulThreadIDJobReady); // LPDWORD lpThreadId - - pShbMemInst->m_hThreadJobReady = hThreadJobReady; - ASSERT(pShbMemInst->m_hThreadJobReady != NULL); - -#ifndef NDEBUG - { - pShbMemInst->m_ulThreadIDJobReady = ulThreadIDJobReady; - } -#endif - - Exit: - - return (ShbError); - -} - -//--------------------------------------------------------------------------- -// Signal job ready (called from executing process) -//--------------------------------------------------------------------------- - -INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p) -{ - - tShbMemInst *pShbMemInst; - HANDLE hEventJobReady; - BOOL fRes; - - // TRACE0("\nShbIpcSignalJobReady(): enter\n"); - - if (pShbInstance_p == NULL) { - return (kShbInvalidArg); - } - - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); - - ASSERT(pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE); - hEventJobReady = pShbMemInst->m_hEventJobReady; - if (hEventJobReady != INVALID_HANDLE_VALUE) { - fRes = SetEvent(hEventJobReady); - // TRACE1("\nShbIpcSignalJobReady(): EventJobReady set (Result=%d)\n", (int)fRes); - ASSERT(fRes); - } - // TRACE0("\nShbIpcSignalJobReady(): leave\n"); - return (kShbOk); - -} - -//--------------------------------------------------------------------------- -// Get pointer to common used share memory area -//--------------------------------------------------------------------------- - -INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p) -{ - - tShbMemHeader *pShbMemHeader; - void *pShbShMemPtr; - - pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p); - if (pShbMemHeader != NULL) { - pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader); - } else { - pShbShMemPtr = NULL; - } - - return (pShbShMemPtr); - -} - -#endif - -//=========================================================================// -// // -// P R I V A T E F U N C T I O N S // -// // -//=========================================================================// - -#if !defined(SHBIPC_INLINE_ENABLED) - -//--------------------------------------------------------------------------- -// Allocate a memory block from process specific mempool -//--------------------------------------------------------------------------- - -static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p) -{ - - HGLOBAL hMem; - void *pMem; - - hMem = GlobalAlloc(GMEM_FIXED, ulMemSize_p + sizeof(HGLOBAL)); - pMem = GlobalLock(hMem); - if (pMem != NULL) { - *(HGLOBAL *) pMem = hMem; - (BYTE *) pMem += sizeof(HGLOBAL); - } - -#ifndef NDEBUG - { - memset(pMem, 0xaa, ulMemSize_p); - } -#endif - - return (pMem); - -} - -//--------------------------------------------------------------------------- -// Release a memory block from process specific mempool -//--------------------------------------------------------------------------- - -static void ShbIpcReleasePrivateMem(void *pMem_p) -{ - - HGLOBAL hMem; - - if (pMem_p == NULL) { - return; - } - - (BYTE *) pMem_p -= sizeof(HGLOBAL); - hMem = *(HGLOBAL *) pMem_p; - - GlobalUnlock(hMem); - GlobalFree(hMem); - - return; - -} - -//--------------------------------------------------------------------------- -// Create uniform object name (needed for inter-process communication) -//--------------------------------------------------------------------------- - -const char *ShbIpcGetUniformObjectName(const char *pszObjectJobName_p, - const char *pszBufferID_p, - BOOL fGlobalObject_p) -{ - - static char szObjectName[MAX_PATH]; - char szObjectPrefix[MAX_PATH]; - - if (fGlobalObject_p) { - strncpy(szObjectPrefix, "Global\\", sizeof(szObjectPrefix)); - } else { - _snprintf(szObjectPrefix, sizeof(szObjectPrefix), "PID%08lX_", - (unsigned long)GetCurrentProcessId()); - } - - _snprintf(szObjectName, sizeof(szObjectName), "%s%s#%s", - szObjectPrefix, pszBufferID_p, pszObjectJobName_p); - - return (szObjectName); - -} - -//--------------------------------------------------------------------------- -// Thread for new data signaling -//--------------------------------------------------------------------------- - -DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p) -{ - - tShbInstance pShbInstance; - tShbMemInst *pShbMemInst; - DWORD dwWaitResult; - BOOL fTermRequ; - int fCallAgain; - - TRACE1 - ("\nShbIpcThreadSignalNewData(): SignalThread started (pShbInstance=0x%08lX)\n", - (DWORD) pvThreadParam_p); - - pShbInstance = (tShbMemInst *) pvThreadParam_p; - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance); - fTermRequ = FALSE; - - do { - ASSERT((pShbMemInst->m_ahEventNewData[0] != - INVALID_HANDLE_VALUE) - && (pShbMemInst->m_ahEventNewData[0] != NULL)); - ASSERT((pShbMemInst->m_ahEventNewData[1] != - INVALID_HANDLE_VALUE) - && (pShbMemInst->m_ahEventNewData[1] != NULL)); - - TRACE0("\nShbIpcThreadSignalNewData(): enter wait state"); - dwWaitResult = WaitForMultipleObjects(2, // DWORD nCount - pShbMemInst->m_ahEventNewData, // const HANDLE* lpHandles - FALSE, // BOOL bWaitAll - INFINITE); // DWORD dwMilliseconds - TRACE0 - ("\nShbIpcThreadSignalNewData(): wait state leaved: ---> "); - switch (dwWaitResult) { - case WAIT_OBJECT_0 + 0: // event "new data" - { - TRACE0("Event = WAIT_OBJECT_0+0"); - if (pShbMemInst->m_pfnSigHndlrNewData != NULL) { - TRACE0 - ("\nShbIpcThreadSignalNewData(): calling SignalHandlerNewData"); - do { - fCallAgain = - pShbMemInst-> - m_pfnSigHndlrNewData - (pShbInstance); - // d.k.: try to run any shared buffer which has higher priority. - // under Windows this is not really necessary because the Windows scheduler - // already preempts tasks with lower priority. - } while (fCallAgain != FALSE); - } - break; - } - - case WAIT_OBJECT_0 + 1: // event "terminate" - { - TRACE0("Event = WAIT_OBJECT_0+1"); - fTermRequ = TRUE; - break; - } - - default: - { - TRACE0("Unhandled Event"); - ASSERT(0); - fTermRequ = TRUE; - break; - } - } - } - while (!fTermRequ); - - if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != - INVALID_HANDLE_VALUE) { - SetEvent(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]); - } - - TRACE1 - ("\nShbIpcThreadSignalNewData(): SignalThread terminated (pShbInstance=0x%08lX)\n", - (DWORD) pShbInstance); - - ExitThread(0); - -} - -//--------------------------------------------------------------------------- -// Thread for new data signaling -//--------------------------------------------------------------------------- - -DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p) -{ - - tShbInstance *pShbInstance; - tShbMemInst *pShbMemInst; - DWORD ulTimeOut; - DWORD dwWaitResult; - unsigned int fTimeOut; - - TRACE1 - ("\nShbIpcThreadSignalJobReady(): SignalThread started (pShbInstance=0x%08lX)\n", - (DWORD) pvThreadParam_p); - - pShbInstance = (tShbInstance *) pvThreadParam_p; - pShbMemInst = ShbIpcGetShbMemInst(pShbInstance); - fTimeOut = FALSE; - - if (pShbMemInst->m_ulTimeOutJobReady != 0) { - ulTimeOut = pShbMemInst->m_ulTimeOutJobReady; - } else { - ulTimeOut = INFINITE; - } - - ASSERT((pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE) - && (pShbMemInst->m_hEventJobReady != NULL)); - - TRACE0("\nShbIpcThreadSignalJobReady(): enter wait state"); - dwWaitResult = WaitForSingleObject(pShbMemInst->m_hEventJobReady, // HANDLE hHandle - ulTimeOut); // DWORD dwMilliseconds - TRACE0("\nShbIpcThreadSignalJobReady(): wait state leaved: ---> "); - switch (dwWaitResult) { - case WAIT_OBJECT_0 + 0: // event "new data" - { - TRACE0("Event = WAIT_OBJECT_0+0"); - fTimeOut = FALSE; - break; - } - - case WAIT_TIMEOUT: - { - TRACE0("\nEvent = WAIT_TIMEOUT"); - fTimeOut = TRUE; - // ASSERT(0); - break; - } - - default: - { - TRACE0("Unhandled Event"); - fTimeOut = TRUE; - ASSERT(0); - break; - } - } - - if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) { - TRACE0 - ("\nShbIpcThreadSignalJobReady(): calling SignalHandlerJobReady"); - pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, fTimeOut); - } - - pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE; - pShbMemInst->m_pfnSigHndlrJobReady = NULL; - - TRACE1 - ("\nShbIpcThreadSignalJobReady(): SignalThread terminated (pShbInstance=0x%08lX)\n", - (DWORD) pShbInstance); - - ExitThread(0); - -} - -#endif - -// EOF diff --git a/drivers/staging/epl/ShbIpc.h b/drivers/staging/epl/ShbIpc.h index cad8846a0824..285f096e771f 100644 --- a/drivers/staging/epl/ShbIpc.h +++ b/drivers/staging/epl/ShbIpc.h @@ -65,25 +65,6 @@ typedef int (*tSigHndlrNewData) (tShbInstance pShbInstance_p); typedef void (*tSigHndlrJobReady) (tShbInstance pShbInstance_p, unsigned int fTimeOut_p); -#if (TARGET_SYSTEM == _WIN32_) -#if defined(INLINE_FUNCTION_DEF) -#undef INLINE_FUNCTION -#define INLINE_FUNCTION INLINE_FUNCTION_DEF -#define SHBIPC_INLINE_ENABLED TRUE -#define SHBIPC_INLINED -#include "ShbIpc-Win32.c" -#endif - -#elif (TARGET_SYSTEM == _LINUX_) -#if defined(INLINE_FUNCTION_DEF) -#undef INLINE_FUNCTION -#define INLINE_FUNCTION INLINE_FUNCTION_DEF -#define SHBIPC_INLINE_ENABLED TRUE -#define SHBIPC_INLINED -#include "ShbIpc-LinuxKernel.c" -#endif -#endif - //--------------------------------------------------------------------------- // Prototypes //--------------------------------------------------------------------------- @@ -97,8 +78,6 @@ tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p, unsigned int *pfShbNewCreated_p); tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p); -#if !defined(SHBIPC_INLINE_ENABLED) - tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p); tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p); @@ -116,10 +95,5 @@ tShbError ShbIpcStartSignalingJobReady(tShbInstance pShbInstance_p, tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p); void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p); -#endif - -#undef SHBIPC_INLINE_ENABLED // disable actual inlining of functions -#undef INLINE_FUNCTION -#define INLINE_FUNCTION // define INLINE_FUNCTION to nothing #endif // #ifndef _SHBIPC_H_ diff --git a/drivers/staging/epl/TimerHighReskX86.c b/drivers/staging/epl/TimerHighReskX86.c index 82eee4702aa6..d6897de4f140 100644 --- a/drivers/staging/epl/TimerHighReskX86.c +++ b/drivers/staging/epl/TimerHighReskX86.c @@ -97,14 +97,10 @@ #define PROVE_OVERRUN -#ifndef CONFIG_HIGH_RES_TIMERS -#error "Kernel symbol CONFIG_HIGH_RES_TIMERS is required." -#endif - // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); -void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); +void TgtDbgPostTraceValue(u32 dwTraceValue_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) #else @@ -172,7 +168,7 @@ enum hrtimer_restart EplTimerHighReskCallback(struct hrtimer *pTimer_p); // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimerHighReskInit(void) +tEplKernel EplTimerHighReskInit(void) { tEplKernel Ret; @@ -196,7 +192,7 @@ tEplKernel PUBLIC EplTimerHighReskInit(void) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimerHighReskAddInstance(void) +tEplKernel EplTimerHighReskAddInstance(void) { tEplKernel Ret; unsigned int uiIndex; @@ -206,13 +202,6 @@ tEplKernel PUBLIC EplTimerHighReskAddInstance(void) EPL_MEMSET(&EplTimerHighReskInstance_l, 0, sizeof(EplTimerHighReskInstance_l)); -#ifndef CONFIG_HIGH_RES_TIMERS - printk - ("EplTimerHighResk: Kernel symbol CONFIG_HIGH_RES_TIMERS is required.\n"); - Ret = kEplNoResource; - return Ret; -#endif - /* * Initialize hrtimer structures for all usable timers. */ @@ -244,7 +233,7 @@ tEplKernel PUBLIC EplTimerHighReskAddInstance(void) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimerHighReskDelInstance(void) +tEplKernel EplTimerHighReskDelInstance(void) { tEplTimerHighReskTimerInfo *pTimerInfo; tEplKernel Ret; @@ -298,12 +287,11 @@ tEplKernel PUBLIC EplTimerHighReskDelInstance(void) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimerHighReskModifyTimerNs(tEplTimerHdl * pTimerHdl_p, - unsigned long long ullTimeNs_p, - tEplTimerkCallback - pfnCallback_p, - unsigned long ulArgument_p, - BOOL fContinuously_p) +tEplKernel EplTimerHighReskModifyTimerNs(tEplTimerHdl *pTimerHdl_p, + unsigned long long ullTimeNs_p, + tEplTimerkCallback pfnCallback_p, + unsigned long ulArgument_p, + BOOL fContinuously_p) { tEplKernel Ret; unsigned int uiIndex; @@ -396,7 +384,7 @@ tEplKernel PUBLIC EplTimerHighReskModifyTimerNs(tEplTimerHdl * pTimerHdl_p, // //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplTimerHighReskDeleteTimer(tEplTimerHdl * pTimerHdl_p) +tEplKernel EplTimerHighReskDeleteTimer(tEplTimerHdl *pTimerHdl_p) { tEplKernel Ret = kEplSuccessful; unsigned int uiIndex; diff --git a/drivers/staging/epl/VirtualEthernetLinux.c b/drivers/staging/epl/VirtualEthernetLinux.c index 5d838dbf73a7..21206c4d22ff 100644 --- a/drivers/staging/epl/VirtualEthernetLinux.c +++ b/drivers/staging/epl/VirtualEthernetLinux.c @@ -74,7 +74,6 @@ ****************************************************************************/ -#include #include #include #include @@ -285,7 +284,7 @@ static tEplKernel VEthRecvFrame(tEplFrameInfo * pFrameInfo_p) return Ret; } -tEplKernel PUBLIC VEthAddInstance(tEplDllkInitParam * pInitParam_p) +tEplKernel VEthAddInstance(tEplDllkInitParam *pInitParam_p) { tEplKernel Ret = kEplSuccessful; @@ -324,7 +323,7 @@ tEplKernel PUBLIC VEthAddInstance(tEplDllkInitParam * pInitParam_p) return Ret; } -tEplKernel PUBLIC VEthDelInstance(void) +tEplKernel VEthDelInstance(void) { tEplKernel Ret = kEplSuccessful; diff --git a/drivers/staging/epl/amix86.c b/drivers/staging/epl/amix86.c index 9f742384dac0..d40ad918d3b9 100644 --- a/drivers/staging/epl/amix86.c +++ b/drivers/staging/epl/amix86.c @@ -74,24 +74,22 @@ //#include "EplAmi.h" #include "EplInc.h" -#if (!defined(EPL_AMI_INLINED)) || defined(INLINE_ENABLED) - //--------------------------------------------------------------------------- // typedef //--------------------------------------------------------------------------- typedef struct { - WORD m_wWord; + u16 m_wWord; } twStruct; typedef struct { - DWORD m_dwDword; + u32 m_dwDword; } tdwStruct; typedef struct { - QWORD m_qwQword; + u64 m_qwQword; } tqwStruct; @@ -117,37 +115,36 @@ typedef struct { // //--------------------------------------------------------------------------- -//------------< write BYTE in big endian >-------------------------- +//------------< write u8 in big endian >-------------------------- /* -void PUBLIC AmiSetByteToBe (void FAR* pAddr_p, BYTE bByteVal_p) +void AmiSetByteToBe (void *pAddr_p, u8 bByteVal_p) { - *(BYTE FAR*)pAddr_p = bByteVal_p; + *(u8 *)pAddr_p = bByteVal_p; } */ -//------------< write WORD in big endian >-------------------------- +//------------< write u16 in big endian >-------------------------- -INLINE_FUNCTION void PUBLIC AmiSetWordToBe(void FAR * pAddr_p, WORD wWordVal_p) +void AmiSetWordToBe(void * pAddr_p, u16 wWordVal_p) { - twStruct FAR *pwStruct; + twStruct *pwStruct; twStruct wValue; - wValue.m_wWord = (WORD) ((wWordVal_p & 0x00FF) << 8); //LSB to MSB - wValue.m_wWord |= (WORD) ((wWordVal_p & 0xFF00) >> 8); //MSB to LSB + wValue.m_wWord = (u16) ((wWordVal_p & 0x00FF) << 8); //LSB to MSB + wValue.m_wWord |= (u16) ((wWordVal_p & 0xFF00) >> 8); //MSB to LSB - pwStruct = (twStruct FAR *) pAddr_p; + pwStruct = (twStruct *) pAddr_p; pwStruct->m_wWord = wValue.m_wWord; } -//------------< write DWORD in big endian >------------------------- +//------------< write u32 in big endian >------------------------- -INLINE_FUNCTION void PUBLIC AmiSetDwordToBe(void FAR * pAddr_p, - DWORD dwDwordVal_p) +void AmiSetDwordToBe(void *pAddr_p, u32 dwDwordVal_p) { - tdwStruct FAR *pdwStruct; + tdwStruct *pdwStruct; tdwStruct dwValue; dwValue.m_dwDword = ((dwDwordVal_p & 0x000000FF) << 24); //LSB to MSB @@ -155,7 +152,7 @@ INLINE_FUNCTION void PUBLIC AmiSetDwordToBe(void FAR * pAddr_p, dwValue.m_dwDword |= ((dwDwordVal_p & 0x00FF0000) >> 8); dwValue.m_dwDword |= ((dwDwordVal_p & 0xFF000000) >> 24); //MSB to LSB - pdwStruct = (tdwStruct FAR *) pAddr_p; + pdwStruct = (tdwStruct *) pAddr_p; pdwStruct->m_dwDword = dwValue.m_dwDword; } @@ -176,35 +173,34 @@ INLINE_FUNCTION void PUBLIC AmiSetDwordToBe(void FAR * pAddr_p, // //--------------------------------------------------------------------------- -//------------< write BYTE in little endian >-------------------------- +//------------< write u8 in little endian >-------------------------- /* -void PUBLIC AmiSetByteToLe (void FAR* pAddr_p, BYTE bByteVal_p) +void AmiSetByteToLe (void *pAddr_p, u8 bByteVal_p) { - *(BYTE FAR*)pAddr_p = bByteVal_p; + *(u8 *)pAddr_p = bByteVal_p; } */ -//------------< write WORD in little endian >-------------------------- +//------------< write u16 in little endian >-------------------------- -INLINE_FUNCTION void PUBLIC AmiSetWordToLe(void FAR * pAddr_p, WORD wWordVal_p) +void AmiSetWordToLe(void *pAddr_p, u16 wWordVal_p) { - twStruct FAR *pwStruct; + twStruct *pwStruct; - pwStruct = (twStruct FAR *) pAddr_p; + pwStruct = (twStruct *) pAddr_p; pwStruct->m_wWord = wWordVal_p; } -//------------< write DWORD in little endian >------------------------- +//------------< write u32 in little endian >------------------------- -INLINE_FUNCTION void PUBLIC AmiSetDwordToLe(void FAR * pAddr_p, - DWORD dwDwordVal_p) +void AmiSetDwordToLe(void *pAddr_p, u32 dwDwordVal_p) { - tdwStruct FAR *pdwStruct; + tdwStruct *pdwStruct; - pdwStruct = (tdwStruct FAR *) pAddr_p; + pdwStruct = (tdwStruct *) pAddr_p; pdwStruct->m_dwDword = dwDwordVal_p; } @@ -224,40 +220,40 @@ INLINE_FUNCTION void PUBLIC AmiSetDwordToLe(void FAR * pAddr_p, // //--------------------------------------------------------------------------- -//------------< read BYTE in big endian >--------------------------- +//------------< read u8 in big endian >--------------------------- /* -BYTE PUBLIC AmiGetByteFromBe (void FAR* pAddr_p) +u8 AmiGetByteFromBe (void *pAddr_p) { - return ( *(BYTE FAR*)pAddr_p ); + return ( *(u8 *)pAddr_p ); } */ -//------------< read WORD in big endian >--------------------------- +//------------< read u16 in big endian >--------------------------- -INLINE_FUNCTION WORD PUBLIC AmiGetWordFromBe(void FAR * pAddr_p) +u16 AmiGetWordFromBe(void *pAddr_p) { - twStruct FAR *pwStruct; + twStruct *pwStruct; twStruct wValue; - pwStruct = (twStruct FAR *) pAddr_p; + pwStruct = (twStruct *) pAddr_p; - wValue.m_wWord = (WORD) ((pwStruct->m_wWord & 0x00FF) << 8); //LSB to MSB - wValue.m_wWord |= (WORD) ((pwStruct->m_wWord & 0xFF00) >> 8); //MSB to LSB + wValue.m_wWord = (u16) ((pwStruct->m_wWord & 0x00FF) << 8); //LSB to MSB + wValue.m_wWord |= (u16) ((pwStruct->m_wWord & 0xFF00) >> 8); //MSB to LSB return (wValue.m_wWord); } -//------------< read DWORD in big endian >-------------------------- +//------------< read u32 in big endian >-------------------------- -INLINE_FUNCTION DWORD PUBLIC AmiGetDwordFromBe(void FAR * pAddr_p) +u32 AmiGetDwordFromBe(void *pAddr_p) { - tdwStruct FAR *pdwStruct; + tdwStruct *pdwStruct; tdwStruct dwValue; - pdwStruct = (tdwStruct FAR *) pAddr_p; + pdwStruct = (tdwStruct *) pAddr_p; dwValue.m_dwDword = ((pdwStruct->m_dwDword & 0x000000FF) << 24); //LSB to MSB dwValue.m_dwDword |= ((pdwStruct->m_dwDword & 0x0000FF00) << 8); @@ -283,36 +279,34 @@ INLINE_FUNCTION DWORD PUBLIC AmiGetDwordFromBe(void FAR * pAddr_p) // //--------------------------------------------------------------------------- -//------------< read BYTE in little endian >--------------------------- +//------------< read u8 in little endian >--------------------------- /* -BYTE PUBLIC AmiGetByteFromLe (void FAR* pAddr_p) +u8 AmiGetByteFromLe (void *pAddr_p) { - return ( *(BYTE FAR*)pAddr_p ); + return ( *(u8 *)pAddr_p ); } */ -//------------< read WORD in little endian >--------------------------- +//------------< read u16 in little endian >--------------------------- -INLINE_FUNCTION WORD PUBLIC AmiGetWordFromLe(void FAR * pAddr_p) +u16 AmiGetWordFromLe(void *pAddr_p) { - twStruct FAR *pwStruct; + twStruct *pwStruct; - pwStruct = (twStruct FAR *) pAddr_p; + pwStruct = (twStruct *) pAddr_p; return (pwStruct->m_wWord); - } -//------------< read DWORD in little endian >-------------------------- +//------------< read u32 in little endian >-------------------------- -INLINE_FUNCTION DWORD PUBLIC AmiGetDwordFromLe(void FAR * pAddr_p) +u32 AmiGetDwordFromLe(void *pAddr_p) { - tdwStruct FAR *pdwStruct; + tdwStruct *pdwStruct; - pdwStruct = (tdwStruct FAR *) pAddr_p; + pdwStruct = (tdwStruct *) pAddr_p; return (pdwStruct->m_dwDword); - } //--------------------------------------------------------------------------- @@ -330,14 +324,11 @@ INLINE_FUNCTION DWORD PUBLIC AmiGetDwordFromLe(void FAR * pAddr_p) // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiSetDword24ToBe(void FAR * pAddr_p, - DWORD dwDwordVal_p) +void AmiSetDword24ToBe(void *pAddr_p, u32 dwDwordVal_p) { - - ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & dwDwordVal_p)[2]; - ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & dwDwordVal_p)[1]; - ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & dwDwordVal_p)[0]; - + ((u8 *) pAddr_p)[0] = ((u8 *) & dwDwordVal_p)[2]; + ((u8 *) pAddr_p)[1] = ((u8 *) & dwDwordVal_p)[1]; + ((u8 *) pAddr_p)[2] = ((u8 *) & dwDwordVal_p)[0]; } //--------------------------------------------------------------------------- @@ -355,14 +346,11 @@ INLINE_FUNCTION void PUBLIC AmiSetDword24ToBe(void FAR * pAddr_p, // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiSetDword24ToLe(void FAR * pAddr_p, - DWORD dwDwordVal_p) +void AmiSetDword24ToLe(void *pAddr_p, u32 dwDwordVal_p) { - - ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & dwDwordVal_p)[0]; - ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & dwDwordVal_p)[1]; - ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & dwDwordVal_p)[2]; - + ((u8 *) pAddr_p)[0] = ((u8 *) & dwDwordVal_p)[0]; + ((u8 *) pAddr_p)[1] = ((u8 *) & dwDwordVal_p)[1]; + ((u8 *) pAddr_p)[2] = ((u8 *) & dwDwordVal_p)[2]; } //--------------------------------------------------------------------------- @@ -373,22 +361,19 @@ INLINE_FUNCTION void PUBLIC AmiSetDword24ToLe(void FAR * pAddr_p, // // Parameters: pAddr_p = pointer to source buffer // -// Return: DWORD = read value +// Return: u32 = read value // // State: not tested // //--------------------------------------------------------------------------- - -INLINE_FUNCTION DWORD PUBLIC AmiGetDword24FromBe(void FAR * pAddr_p) +u32 AmiGetDword24FromBe(void *pAddr_p) { - tdwStruct dwStruct; dwStruct.m_dwDword = AmiGetDwordFromBe(pAddr_p); dwStruct.m_dwDword >>= 8; return (dwStruct.m_dwDword); - } //--------------------------------------------------------------------------- @@ -399,22 +384,19 @@ INLINE_FUNCTION DWORD PUBLIC AmiGetDword24FromBe(void FAR * pAddr_p) // // Parameters: pAddr_p = pointer to source buffer // -// Return: DWORD = read value +// Return: u32 = read value // // State: not tested // //--------------------------------------------------------------------------- - -INLINE_FUNCTION DWORD PUBLIC AmiGetDword24FromLe(void FAR * pAddr_p) +u32 AmiGetDword24FromLe(void *pAddr_p) { - tdwStruct dwStruct; dwStruct.m_dwDword = AmiGetDwordFromLe(pAddr_p); dwStruct.m_dwDword &= 0x00FFFFFF; return (dwStruct.m_dwDword); - } //#ifdef USE_VAR64 @@ -433,20 +415,16 @@ INLINE_FUNCTION DWORD PUBLIC AmiGetDword24FromLe(void FAR * pAddr_p) // State: not tested // //--------------------------------------------------------------------------- - -INLINE_FUNCTION void PUBLIC AmiSetQword64ToBe(void FAR * pAddr_p, - QWORD qwQwordVal_p) +void AmiSetQword64ToBe(void *pAddr_p, u64 qwQwordVal_p) { - - ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & qwQwordVal_p)[7]; - ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & qwQwordVal_p)[6]; - ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & qwQwordVal_p)[5]; - ((BYTE FAR *) pAddr_p)[3] = ((BYTE FAR *) & qwQwordVal_p)[4]; - ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[3]; - ((BYTE FAR *) pAddr_p)[5] = ((BYTE FAR *) & qwQwordVal_p)[2]; - ((BYTE FAR *) pAddr_p)[6] = ((BYTE FAR *) & qwQwordVal_p)[1]; - ((BYTE FAR *) pAddr_p)[7] = ((BYTE FAR *) & qwQwordVal_p)[0]; - + ((u8 *) pAddr_p)[0] = ((u8 *) & qwQwordVal_p)[7]; + ((u8 *) pAddr_p)[1] = ((u8 *) & qwQwordVal_p)[6]; + ((u8 *) pAddr_p)[2] = ((u8 *) & qwQwordVal_p)[5]; + ((u8 *) pAddr_p)[3] = ((u8 *) & qwQwordVal_p)[4]; + ((u8 *) pAddr_p)[4] = ((u8 *) & qwQwordVal_p)[3]; + ((u8 *) pAddr_p)[5] = ((u8 *) & qwQwordVal_p)[2]; + ((u8 *) pAddr_p)[6] = ((u8 *) & qwQwordVal_p)[1]; + ((u8 *) pAddr_p)[7] = ((u8 *) & qwQwordVal_p)[0]; } //--------------------------------------------------------------------------- @@ -463,16 +441,12 @@ INLINE_FUNCTION void PUBLIC AmiSetQword64ToBe(void FAR * pAddr_p, // State: not tested // //--------------------------------------------------------------------------- - -INLINE_FUNCTION void PUBLIC AmiSetQword64ToLe(void FAR * pAddr_p, - QWORD qwQwordVal_p) +void AmiSetQword64ToLe(void *pAddr_p, u64 qwQwordVal_p) { + u64 *pqwDst; - QWORD FAR *pqwDst; - - pqwDst = (QWORD FAR *) pAddr_p; + pqwDst = (u64 *) pAddr_p; *pqwDst = qwQwordVal_p; - } //--------------------------------------------------------------------------- @@ -488,23 +462,20 @@ INLINE_FUNCTION void PUBLIC AmiSetQword64ToLe(void FAR * pAddr_p, // State: not tested // //--------------------------------------------------------------------------- - -INLINE_FUNCTION QWORD PUBLIC AmiGetQword64FromBe(void FAR * pAddr_p) +u64 AmiGetQword64FromBe(void *pAddr_p) { - tqwStruct qwStruct; - ((BYTE FAR *) & qwStruct.m_qwQword)[0] = ((BYTE FAR *) pAddr_p)[7]; - ((BYTE FAR *) & qwStruct.m_qwQword)[1] = ((BYTE FAR *) pAddr_p)[6]; - ((BYTE FAR *) & qwStruct.m_qwQword)[2] = ((BYTE FAR *) pAddr_p)[5]; - ((BYTE FAR *) & qwStruct.m_qwQword)[3] = ((BYTE FAR *) pAddr_p)[4]; - ((BYTE FAR *) & qwStruct.m_qwQword)[4] = ((BYTE FAR *) pAddr_p)[3]; - ((BYTE FAR *) & qwStruct.m_qwQword)[5] = ((BYTE FAR *) pAddr_p)[2]; - ((BYTE FAR *) & qwStruct.m_qwQword)[6] = ((BYTE FAR *) pAddr_p)[1]; - ((BYTE FAR *) & qwStruct.m_qwQword)[7] = ((BYTE FAR *) pAddr_p)[0]; + ((u8 *) & qwStruct.m_qwQword)[0] = ((u8 *) pAddr_p)[7]; + ((u8 *) & qwStruct.m_qwQword)[1] = ((u8 *) pAddr_p)[6]; + ((u8 *) & qwStruct.m_qwQword)[2] = ((u8 *) pAddr_p)[5]; + ((u8 *) & qwStruct.m_qwQword)[3] = ((u8 *) pAddr_p)[4]; + ((u8 *) & qwStruct.m_qwQword)[4] = ((u8 *) pAddr_p)[3]; + ((u8 *) & qwStruct.m_qwQword)[5] = ((u8 *) pAddr_p)[2]; + ((u8 *) & qwStruct.m_qwQword)[6] = ((u8 *) pAddr_p)[1]; + ((u8 *) & qwStruct.m_qwQword)[7] = ((u8 *) pAddr_p)[0]; return (qwStruct.m_qwQword); - } //--------------------------------------------------------------------------- @@ -520,18 +491,15 @@ INLINE_FUNCTION QWORD PUBLIC AmiGetQword64FromBe(void FAR * pAddr_p) // State: not tested // //--------------------------------------------------------------------------- - -INLINE_FUNCTION QWORD PUBLIC AmiGetQword64FromLe(void FAR * pAddr_p) +u64 AmiGetQword64FromLe(void *pAddr_p) { - - tqwStruct FAR *pqwStruct; + tqwStruct *pqwStruct; tqwStruct qwStruct; - pqwStruct = (tqwStruct FAR *) pAddr_p; + pqwStruct = (tqwStruct *) pAddr_p; qwStruct.m_qwQword = pqwStruct->m_qwQword; return (qwStruct.m_qwQword); - } //--------------------------------------------------------------------------- @@ -549,15 +517,14 @@ INLINE_FUNCTION QWORD PUBLIC AmiGetQword64FromLe(void FAR * pAddr_p) // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiSetQword40ToBe(void FAR * pAddr_p, - QWORD qwQwordVal_p) +void AmiSetQword40ToBe(void *pAddr_p, u64 qwQwordVal_p) { - ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & qwQwordVal_p)[4]; - ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & qwQwordVal_p)[3]; - ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & qwQwordVal_p)[2]; - ((BYTE FAR *) pAddr_p)[3] = ((BYTE FAR *) & qwQwordVal_p)[1]; - ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[0]; + ((u8 *) pAddr_p)[0] = ((u8 *) & qwQwordVal_p)[4]; + ((u8 *) pAddr_p)[1] = ((u8 *) & qwQwordVal_p)[3]; + ((u8 *) pAddr_p)[2] = ((u8 *) & qwQwordVal_p)[2]; + ((u8 *) pAddr_p)[3] = ((u8 *) & qwQwordVal_p)[1]; + ((u8 *) pAddr_p)[4] = ((u8 *) & qwQwordVal_p)[0]; } @@ -576,12 +543,11 @@ INLINE_FUNCTION void PUBLIC AmiSetQword40ToBe(void FAR * pAddr_p, // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiSetQword40ToLe(void FAR * pAddr_p, - QWORD qwQwordVal_p) +void AmiSetQword40ToLe(void *pAddr_p, u64 qwQwordVal_p) { - ((DWORD FAR *) pAddr_p)[0] = ((DWORD FAR *) & qwQwordVal_p)[0]; - ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[4]; + ((u32 *) pAddr_p)[0] = ((u32 *) & qwQwordVal_p)[0]; + ((u8 *) pAddr_p)[4] = ((u8 *) & qwQwordVal_p)[4]; } @@ -593,13 +559,13 @@ INLINE_FUNCTION void PUBLIC AmiSetQword40ToLe(void FAR * pAddr_p, // // Parameters: pAddr_p = pointer to source buffer // -// Return: QWORD +// Return: u64 // // State: not tested // //--------------------------------------------------------------------------- -INLINE_FUNCTION QWORD PUBLIC AmiGetQword40FromBe(void FAR * pAddr_p) +u64 AmiGetQword40FromBe(void *pAddr_p) { tqwStruct qwStruct; @@ -619,13 +585,13 @@ INLINE_FUNCTION QWORD PUBLIC AmiGetQword40FromBe(void FAR * pAddr_p) // // Parameters: pAddr_p = pointer to source buffer // -// Return: QWORD +// Return: u64 // // State: not tested // //--------------------------------------------------------------------------- -INLINE_FUNCTION QWORD PUBLIC AmiGetQword40FromLe(void FAR * pAddr_p) +u64 AmiGetQword40FromLe(void *pAddr_p) { tqwStruct qwStruct; @@ -652,16 +618,15 @@ INLINE_FUNCTION QWORD PUBLIC AmiGetQword40FromLe(void FAR * pAddr_p) // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiSetQword48ToBe(void FAR * pAddr_p, - QWORD qwQwordVal_p) +void AmiSetQword48ToBe(void *pAddr_p, u64 qwQwordVal_p) { - ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & qwQwordVal_p)[5]; - ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & qwQwordVal_p)[4]; - ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & qwQwordVal_p)[3]; - ((BYTE FAR *) pAddr_p)[3] = ((BYTE FAR *) & qwQwordVal_p)[2]; - ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[1]; - ((BYTE FAR *) pAddr_p)[5] = ((BYTE FAR *) & qwQwordVal_p)[0]; + ((u8 *) pAddr_p)[0] = ((u8 *) & qwQwordVal_p)[5]; + ((u8 *) pAddr_p)[1] = ((u8 *) & qwQwordVal_p)[4]; + ((u8 *) pAddr_p)[2] = ((u8 *) & qwQwordVal_p)[3]; + ((u8 *) pAddr_p)[3] = ((u8 *) & qwQwordVal_p)[2]; + ((u8 *) pAddr_p)[4] = ((u8 *) & qwQwordVal_p)[1]; + ((u8 *) pAddr_p)[5] = ((u8 *) & qwQwordVal_p)[0]; } @@ -680,12 +645,11 @@ INLINE_FUNCTION void PUBLIC AmiSetQword48ToBe(void FAR * pAddr_p, // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiSetQword48ToLe(void FAR * pAddr_p, - QWORD qwQwordVal_p) +void AmiSetQword48ToLe(void *pAddr_p, u64 qwQwordVal_p) { - ((DWORD FAR *) pAddr_p)[0] = ((DWORD FAR *) & qwQwordVal_p)[0]; - ((WORD FAR *) pAddr_p)[2] = ((WORD FAR *) & qwQwordVal_p)[2]; + ((u32 *) pAddr_p)[0] = ((u32 *) & qwQwordVal_p)[0]; + ((u16 *) pAddr_p)[2] = ((u16 *) & qwQwordVal_p)[2]; } @@ -697,13 +661,13 @@ INLINE_FUNCTION void PUBLIC AmiSetQword48ToLe(void FAR * pAddr_p, // // Parameters: pAddr_p = pointer to source buffer // -// Return: QWORD +// Return: u64 // // State: not tested // //--------------------------------------------------------------------------- -INLINE_FUNCTION QWORD PUBLIC AmiGetQword48FromBe(void FAR * pAddr_p) +u64 AmiGetQword48FromBe(void *pAddr_p) { tqwStruct qwStruct; @@ -723,13 +687,13 @@ INLINE_FUNCTION QWORD PUBLIC AmiGetQword48FromBe(void FAR * pAddr_p) // // Parameters: pAddr_p = pointer to source buffer // -// Return: QWORD +// Return: u64 // // State: not tested // //--------------------------------------------------------------------------- -INLINE_FUNCTION QWORD PUBLIC AmiGetQword48FromLe(void FAR * pAddr_p) +u64 AmiGetQword48FromLe(void *pAddr_p) { tqwStruct qwStruct; @@ -756,17 +720,16 @@ INLINE_FUNCTION QWORD PUBLIC AmiGetQword48FromLe(void FAR * pAddr_p) // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiSetQword56ToBe(void FAR * pAddr_p, - QWORD qwQwordVal_p) +void AmiSetQword56ToBe(void *pAddr_p, u64 qwQwordVal_p) { - ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & qwQwordVal_p)[6]; - ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & qwQwordVal_p)[5]; - ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & qwQwordVal_p)[4]; - ((BYTE FAR *) pAddr_p)[3] = ((BYTE FAR *) & qwQwordVal_p)[3]; - ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[2]; - ((BYTE FAR *) pAddr_p)[5] = ((BYTE FAR *) & qwQwordVal_p)[1]; - ((BYTE FAR *) pAddr_p)[6] = ((BYTE FAR *) & qwQwordVal_p)[0]; + ((u8 *) pAddr_p)[0] = ((u8 *) & qwQwordVal_p)[6]; + ((u8 *) pAddr_p)[1] = ((u8 *) & qwQwordVal_p)[5]; + ((u8 *) pAddr_p)[2] = ((u8 *) & qwQwordVal_p)[4]; + ((u8 *) pAddr_p)[3] = ((u8 *) & qwQwordVal_p)[3]; + ((u8 *) pAddr_p)[4] = ((u8 *) & qwQwordVal_p)[2]; + ((u8 *) pAddr_p)[5] = ((u8 *) & qwQwordVal_p)[1]; + ((u8 *) pAddr_p)[6] = ((u8 *) & qwQwordVal_p)[0]; } @@ -785,13 +748,12 @@ INLINE_FUNCTION void PUBLIC AmiSetQword56ToBe(void FAR * pAddr_p, // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiSetQword56ToLe(void FAR * pAddr_p, - QWORD qwQwordVal_p) +void AmiSetQword56ToLe(void *pAddr_p, u64 qwQwordVal_p) { - ((DWORD FAR *) pAddr_p)[0] = ((DWORD FAR *) & qwQwordVal_p)[0]; - ((WORD FAR *) pAddr_p)[2] = ((WORD FAR *) & qwQwordVal_p)[2]; - ((BYTE FAR *) pAddr_p)[6] = ((BYTE FAR *) & qwQwordVal_p)[6]; + ((u32 *) pAddr_p)[0] = ((u32 *) & qwQwordVal_p)[0]; + ((u16 *) pAddr_p)[2] = ((u16 *) & qwQwordVal_p)[2]; + ((u8 *) pAddr_p)[6] = ((u8 *) & qwQwordVal_p)[6]; } @@ -803,13 +765,13 @@ INLINE_FUNCTION void PUBLIC AmiSetQword56ToLe(void FAR * pAddr_p, // // Parameters: pAddr_p = pointer to source buffer // -// Return: QWORD +// Return: u64 // // State: not tested // //--------------------------------------------------------------------------- -INLINE_FUNCTION QWORD PUBLIC AmiGetQword56FromBe(void FAR * pAddr_p) +u64 AmiGetQword56FromBe(void *pAddr_p) { tqwStruct qwStruct; @@ -829,13 +791,13 @@ INLINE_FUNCTION QWORD PUBLIC AmiGetQword56FromBe(void FAR * pAddr_p) // // Parameters: pAddr_p = pointer to source buffer // -// Return: QWORD +// Return: u64 // // State: not tested // //--------------------------------------------------------------------------- -INLINE_FUNCTION QWORD PUBLIC AmiGetQword56FromLe(void FAR * pAddr_p) +u64 AmiGetQword56FromLe(void *pAddr_p) { tqwStruct qwStruct; @@ -862,13 +824,11 @@ INLINE_FUNCTION QWORD PUBLIC AmiGetQword56FromLe(void FAR * pAddr_p) // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiSetTimeOfDay(void FAR * pAddr_p, - tTimeOfDay FAR * pTimeOfDay_p) +void AmiSetTimeOfDay(void *pAddr_p, tTimeOfDay *pTimeOfDay_p) { - AmiSetDwordToLe(((BYTE FAR *) pAddr_p), - pTimeOfDay_p->m_dwMs & 0x0FFFFFFF); - AmiSetWordToLe(((BYTE FAR *) pAddr_p) + 4, pTimeOfDay_p->m_wDays); + AmiSetDwordToLe(((u8 *) pAddr_p), pTimeOfDay_p->m_dwMs & 0x0FFFFFFF); + AmiSetWordToLe(((u8 *) pAddr_p) + 4, pTimeOfDay_p->m_wDays); } @@ -887,18 +847,14 @@ INLINE_FUNCTION void PUBLIC AmiSetTimeOfDay(void FAR * pAddr_p, // //--------------------------------------------------------------------------- -INLINE_FUNCTION void PUBLIC AmiGetTimeOfDay(void FAR * pAddr_p, - tTimeOfDay FAR * pTimeOfDay_p) +void AmiGetTimeOfDay(void *pAddr_p, tTimeOfDay *pTimeOfDay_p) { - pTimeOfDay_p->m_dwMs = - AmiGetDwordFromLe(((BYTE FAR *) pAddr_p)) & 0x0FFFFFFF; - pTimeOfDay_p->m_wDays = AmiGetWordFromLe(((BYTE FAR *) pAddr_p) + 4); + pTimeOfDay_p->m_dwMs = AmiGetDwordFromLe(((u8 *) pAddr_p)) & 0x0FFFFFFF; + pTimeOfDay_p->m_wDays = AmiGetWordFromLe(((u8 *) pAddr_p) + 4); } -#endif - // EOF // Die letzte Zeile muß unbedingt eine leere Zeile sein, weil manche Compiler diff --git a/drivers/staging/epl/demo_main.c b/drivers/staging/epl/demo_main.c index 263fa042291d..7ad10fc2b1d0 100644 --- a/drivers/staging/epl/demo_main.c +++ b/drivers/staging/epl/demo_main.c @@ -74,7 +74,6 @@ #include #include #include -#include #include #include #include @@ -87,16 +86,6 @@ #include "Epl.h" #include "proc_fs.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - // remove ("make invisible") obsolete symbols for kernel versions 2.6 - // and higher -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#define EXPORT_NO_SYMBOLS -#else -#error "This driver needs a 2.6.x kernel or higher" -#endif - /***************************************************************************/ /* */ /* */ @@ -118,7 +107,7 @@ MODULE_DESCRIPTION("EPL MN demo"); // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #else #define TGT_DBG_SIGNAL_TRACE_POINT(p) @@ -148,30 +137,30 @@ void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); // modul globale vars //--------------------------------------------------------------------------- -CONST BYTE abMacAddr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const u8 abMacAddr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -BYTE bVarIn1_l; -BYTE bVarOut1_l; -BYTE bVarOut1Old_l; -BYTE bModeSelect_l; // state of the pushbuttons to select the mode -BYTE bSpeedSelect_l; // state of the pushbuttons to increase/decrease the speed -BYTE bSpeedSelectOld_l; // old state of the pushbuttons -DWORD dwLeds_l; // current state of all LEDs -BYTE bLedsRow1_l; // current state of the LEDs in row 1 -BYTE bLedsRow2_l; // current state of the LEDs in row 2 -BYTE abSelect_l[3]; // pushbuttons from CNs +static u8 bVarIn1_l; +static u8 bVarOut1_l; +static u8 bVarOut1Old_l; +static u8 bModeSelect_l; // state of the pushbuttons to select the mode +static u8 bSpeedSelect_l; // state of the pushbuttons to increase/decrease the speed +static u8 bSpeedSelectOld_l; // old state of the pushbuttons +static u32 dwLeds_l; // current state of all LEDs +static u8 bLedsRow1_l; // current state of the LEDs in row 1 +static u8 bLedsRow2_l; // current state of the LEDs in row 2 +static u8 abSelect_l[3]; // pushbuttons from CNs -DWORD dwMode_l; // current mode -int iCurCycleCount_l; // current cycle count -int iMaxCycleCount_l; // maximum cycle count (i.e. number of cycles until next light movement step) -int iToggle; // indicates the light movement direction +static u32 dwMode_l; // current mode +static int iCurCycleCount_l; // current cycle count +static int iMaxCycleCount_l; // maximum cycle count (i.e. number of cycles until next light movement step) +static int iToggle; // indicates the light movement direction -BYTE abDomain_l[3000]; +//static u8 abDomain_l[3000]; static wait_queue_head_t WaitQueueShutdown_g; // wait queue for tEplNmtEventSwitchOff static atomic_t AtomicShutdown_g = ATOMIC_INIT(FALSE); -static DWORD dw_le_CycleLen_g; +static u32 dw_le_CycleLen_g; static uint uiNodeId_g = EPL_C_ADR_INVALID; module_param_named(nodeid, uiNodeId_g, uint, 0); @@ -188,23 +177,19 @@ module_param_named(cyclelen, uiCycleLen_g, uint, 0); // this function prototype here. If you want to use more than one Epl // instances then the function name of each object dictionary has to differ. -tEplKernel PUBLIC EplObdInitRam(tEplObdInitParam MEM * pInitParam_p); +tEplKernel EplObdInitRam(tEplObdInitParam *pInitParam_p); -tEplKernel PUBLIC AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) - tEplApiEventArg * pEventArg_p, // IN: event argument (union) - void GENERIC * pUserArg_p); +tEplKernel AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg *pEventArg_p, // IN: event argument (union) + void *pUserArg_p); -tEplKernel PUBLIC AppCbSync(void); +tEplKernel AppCbSync(void); -static int __init EplLinInit(void); -static void __exit EplLinExit(void); //--------------------------------------------------------------------------- // Kernel Module specific Data Structures //--------------------------------------------------------------------------- -EXPORT_NO_SYMBOLS; - //module_init(EplLinInit); //module_exit(EplLinExit); @@ -231,6 +216,7 @@ EXPORT_NO_SYMBOLS; // State: // //--------------------------------------------------------------------------- +#if 0 static int __init EplLinInit(void) { tEplKernel EplRet; @@ -263,7 +249,7 @@ static int __init EplLinInit(void) EplApiInitParam.m_uiSizeOfStruct = sizeof(EplApiInitParam); EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr, sizeof(EplApiInitParam.m_abMacAddress)); -// EplApiInitParam.m_abMacAddress[5] = (BYTE) EplApiInitParam.m_uiNodeId; +// EplApiInitParam.m_abMacAddress[5] = (u8) EplApiInitParam.m_uiNodeId; EplApiInitParam.m_dwFeatureFlags = -1; EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection EplApiInitParam.m_uiIsochrTxMaxPayload = 100; // const @@ -401,7 +387,7 @@ static int __init EplLinInit(void) // configure IP address of virtual network interface // for TCP/IP communication over the POWERLINK network - sprintf(sBuffer, "%lu.%lu.%lu.%lu", + sprintf(sBuffer, "%u.%u.%u.%u", (EplApiInitParam.m_dwIpAddress >> 24), ((EplApiInitParam.m_dwIpAddress >> 16) & 0xFF), ((EplApiInitParam.m_dwIpAddress >> 8) & 0xFF), @@ -456,7 +442,7 @@ static void __exit EplLinExit(void) printk("EplLinProcFree(): 0x%X\n", EplRet); } - +#endif //=========================================================================// // // // P R I V A T E F U N C T I O N S // @@ -484,9 +470,9 @@ static void __exit EplLinExit(void) // //--------------------------------------------------------------------------- -tEplKernel PUBLIC AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) - tEplApiEventArg * pEventArg_p, // IN: event argument (union) - void GENERIC * pUserArg_p) +tEplKernel AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum) + tEplApiEventArg *pEventArg_p, // IN: event argument (union) + void *pUserArg_p) { tEplKernel EplRet = kEplSuccessful; @@ -515,7 +501,7 @@ tEplKernel PUBLIC AppCbEvent(tEplApiEventType EventType_p, // IN: event type (en case kEplNmtGsResetCommunication: { - DWORD dwBuffer; + u32 dwBuffer; // configure OD for MN in state ResetComm after reseting the OD // TODO: setup your own network configuration here @@ -677,8 +663,8 @@ tEplKernel PUBLIC AppCbEvent(tEplApiEventType EventType_p, // IN: event type (en case kEplEventSourceDllk: { // error occured within the data link layer (e.g. interrupt processing) - // the DWORD argument contains the DLL state and the NMT event - printk(" val=%lX\n", + // the u32 argument contains the DLL state and the NMT event + printk(" val=%X\n", pEventArg_p->m_InternalError. m_Arg.m_dwArg); break; @@ -802,7 +788,7 @@ tEplKernel PUBLIC AppCbEvent(tEplApiEventType EventType_p, // IN: event type (en // //--------------------------------------------------------------------------- -tEplKernel PUBLIC AppCbSync(void) +tEplKernel AppCbSync(void) { tEplKernel EplRet = kEplSuccessful; @@ -810,7 +796,7 @@ tEplKernel PUBLIC AppCbSync(void) bVarOut1Old_l = bVarOut1_l; // set LEDs -// printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (WORD) bVarIn_l, (WORD) bVarOut_l); +// printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (u16) bVarIn_l, (u16) bVarOut_l); } if (uiNodeId_g != EPL_C_ADR_MN_DEF_NODE_ID) { bVarIn1_l++; diff --git a/drivers/staging/epl/edrv.h b/drivers/staging/epl/edrv.h index a45984dfb092..62b4e77e0695 100644 --- a/drivers/staging/epl/edrv.h +++ b/drivers/staging/epl/edrv.h @@ -104,7 +104,7 @@ typedef struct _tEdrvTxBuffer { unsigned int m_uiTxMsgLen; // IN: length of message to be send (set for each transmit call) // ---------------------- unsigned int m_uiBufferNumber; // OUT: number of the buffer, set by ethernetdriver - BYTE *m_pbBuffer; // OUT: pointer to the buffer, set by ethernetdriver + u8 *m_pbBuffer; // OUT: pointer to the buffer, set by ethernetdriver tEplNetTime m_NetTime; // OUT: Timestamp of end of transmission, set by ethernetdriver // ---------------------- unsigned int m_uiMaxBufferLen; // IN/OUT: maximum length of the buffer @@ -114,23 +114,23 @@ typedef struct _tEdrvTxBuffer { typedef struct _tEdrvRxBuffer { tEdrvBufferInFrame m_BufferInFrame; // OUT position of received buffer in an ethernet-frame unsigned int m_uiRxMsgLen; // OUT: length of received buffer (without CRC) - BYTE *m_pbBuffer; // OUT: pointer to the buffer, set by ethernetdriver + u8 *m_pbBuffer; // OUT: pointer to the buffer, set by ethernetdriver tEplNetTime m_NetTime; // OUT: Timestamp of end of receiption } tEdrvRxBuffer; -//typedef void (*tEdrvRxHandler) (BYTE bBufferInFrame_p, tBufferDescr * pbBuffer_p); -//typedef void (*tEdrvRxHandler) (BYTE bBufferInFrame_p, BYTE * pbEthernetData_p, WORD wDataLen_p); +//typedef void (*tEdrvRxHandler) (u8 bBufferInFrame_p, tBufferDescr * pbBuffer_p); +//typedef void (*tEdrvRxHandler) (u8 bBufferInFrame_p, u8 * pbEthernetData_p, u16 wDataLen_p); typedef void (*tEdrvRxHandler) (tEdrvRxBuffer * pRxBuffer_p); typedef void (*tEdrvTxHandler) (tEdrvTxBuffer * pTxBuffer_p); // format of init structure typedef struct { - BYTE m_abMyMacAddr[6]; // the own MAC address + u8 m_abMyMacAddr[6]; // the own MAC address -// BYTE m_bNoOfRxBuffDescr; // number of entries in rx bufferdescriptor table +// u8 m_bNoOfRxBuffDescr; // number of entries in rx bufferdescriptor table // tBufferDescr * m_pRxBuffDescrTable; // rx bufferdescriptor table -// WORD m_wRxBufferSize; // size of the whole rx buffer +// u16 m_wRxBufferSize; // size of the whole rx buffer tEdrvRxHandler m_pfnRxHandler; tEdrvTxHandler m_pfnTxHandler; @@ -145,11 +145,11 @@ tEplKernel EdrvInit(tEdrvInitParam * pEdrvInitParam_p); tEplKernel EdrvShutdown(void); -tEplKernel EdrvDefineRxMacAddrEntry(BYTE * pbMacAddr_p); -tEplKernel EdrvUndefineRxMacAddrEntry(BYTE * pbMacAddr_p); +tEplKernel EdrvDefineRxMacAddrEntry(u8 * pbMacAddr_p); +tEplKernel EdrvUndefineRxMacAddrEntry(u8 * pbMacAddr_p); -//tEplKernel EdrvDefineUnicastEntry (BYTE * pbUCEntry_p); -//tEplKernel EdrvUndfineUnicastEntry (BYTE * pbUCEntry_p); +//tEplKernel EdrvDefineUnicastEntry (u8 * pbUCEntry_p); +//tEplKernel EdrvUndfineUnicastEntry (u8 * pbUCEntry_p); tEplKernel EdrvAllocTxMsgBuffer(tEdrvTxBuffer * pBuffer_p); tEplKernel EdrvReleaseTxMsgBuffer(tEdrvTxBuffer * pBuffer_p); diff --git a/drivers/staging/epl/global.h b/drivers/staging/epl/global.h index fe167165a836..8c52d97ec9c0 100644 --- a/drivers/staging/epl/global.h +++ b/drivers/staging/epl/global.h @@ -22,1261 +22,21 @@ #ifndef _GLOBAL_H_ #define _GLOBAL_H_ -//--------------------------------------------------------------------------- -// elements of defines for development system -//--------------------------------------------------------------------------- -// these defines are necessary to check some of characteristics of the development system -#define _DEV_BIGEND_ 0x80000000L // big endian (motorolla format) -#define _DEV_ALIGNMENT_4_ 0x00400000L // the CPU needs alignment of 4 bytes -#define _DEV_ONLY_INT_MAIN_ 0x00004000L // the compiler needs "int main(int)" instead of "void main(void)" -#define _DEV_COMMA_EXT_ 0x00002000L // support of last comma in struct predefinition -#define _DEV_64BIT_SUPPORT_ 0x00001000L // support of 64 bit operations -#define _DEV_BIT64_ 0x00000400L // count of bits: 64 bit -#define _DEV_BIT32_ 0x00000300L // 32 bit -#define _DEV_BIT16_ 0x00000200L // 16 bit -#define _DEV_BIT8_ 0x00000100L // 8 bit -#define _DEV_RVCT_ARM_ 0x0000001CL // RealView ARM -#define _DEV_RENESASM32C 0x0000001BL // compiler from: Renesas -#define _DEV_GNUC_MIPS2_ 0x0000001AL // GNU for MIPS2 -#define _DEV_MPLAB_C30_ 0x00000019L // MPLAB C30 for Microchip dsPIC33F series -#define _DEV_GNUC_TC_ 0x00000018L // GNU for Infineon TriCore -#define _DEV_GNUC_X86_ 0x00000017L // GNU for I386 -#define _DEV_IAR_ARM_ 0x00000016L // ARM IAR C/C++ Compiler -#define _DEV_PARADGM_X86 0x00000015L // Paradigm C/C++ for Beck 1x3 -#define _DEV_GNUC_CF_ 0x00000014L // GNU for Coldfire -#define _DEV_KEIL_ARM_ 0x00000013L // Keil ARM -#define _DEV_MSEVC_ 0x00000012L // Microsoft embedded Visual C/C++ -#define _DEV_HIGHTEC_GNUC_X86_ 0x00000011L // Hightec elf386 gcc -#define _DEV_MSVC_RTX_ 0x00000010L // VC600 + RTX -#define _DEV_MSVC_V1_5_ 0x0000000FL // Microsoft Visual C/C++ V1.5 -#define _DEV_GNUC_ARM7_ 0x0000000EL // GNU Compiler gcc for ARM7 -#define _DEV_METROWERKS_CW_ 0x0000000DL // Metrowerks Code Warrior -#define _DEV_MITSUBISHIM16C_ 0x0000000CL //compiler from: Mitsubishi -#define _DEV_GNUC_C16X_ 0x0000000BL // GNU Compiler gcc166 for Infineon C16x -#define _DEV_LINUX_GCC_ 0x0000000AL // Linux GNU Compiler gcc -#define _DEV_GNUC_MPC5X5 0x00000009L // GNU for Motorola PPC5x5 -#define _DEV_TASKINGM16C_ 0x00000008L // Tasking for Mitsubishi M16C -#define _DEV_FUJITSU_ 0x00000007L // Fujitsu -#define _DEV_TASKING8_ 0x00000006L // Tasking 8051 -#define _DEV_TASKING16_ 0x00000005L // Tasking 166 -#define _DEV_KEIL8_ 0x00000004L // Keil C51 -#define _DEV_KEIL16_ 0x00000003L // Keil C166 -#define _DEV_BORLANDC_ 0x00000002L // Borland C/C++ -#define _DEV_MSVC16_ 0x00000001L // Microsoft Visual C/C++ -#define _DEV_MSVC32_ 0x00000000L // Microsoft Visual C/C++ - -// these defines can be used to mask previous elements -#define _DEV_MASK_COMPILER 0x000000FFL -#define _DEV_MASK_BITCOUNT 0x00000F00L -#define _DEV_MASK_ADDSUPPORT 0x0000F000L -#define _DEV_MASK_ALIGNMENT 0x00F00000L - -//--------------------------------------------------------------------------- -// defines for development system (DEV_SYSTEM) including previous elements -//--------------------------------------------------------------------------- - -#define _DEV_WIN16_ (_DEV_BIT16_ | _DEV_MSVC16_ ) -#define _DEV_WIN32_ (_DEV_BIT32_ | _DEV_MSVC32_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_MSVC_DOS_ (_DEV_BIT32_ | _DEV_MSVC_V1_5_ ) -#define _DEV_BORLAND_DOS_ (_DEV_BIT32_ | _DEV_BORLANDC_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_KEIL_C51X_ (_DEV_BIT8_ | _DEV_KEIL8_ | _DEV_BIGEND_ | _DEV_COMMA_EXT_) // at least C51 version 7.05 supports comma extension -#define _DEV_KEIL_C16X_ (_DEV_BIT16_ | _DEV_KEIL16_ | _DEV_COMMA_EXT_) // at least C166 version 5.03 supports comma extension -#define _DEV_TASKING_C51X_ (_DEV_BIT8_ | _DEV_TASKING8_ | _DEV_BIGEND_) -#define _DEV_TASKING_C16X_ (_DEV_BIT16_ | _DEV_TASKING16_ ) -#define _DEV_FUJITSU_F590_ (_DEV_BIT8_ | _DEV_FUJITSU_ | _DEV_COMMA_EXT_) // softune is not able to support 64 bit variables QWORD !!! -//f.j.29.04.03 M16C kann effektiv mit Bytes umgehen -//#define _DEV_TASKING_M16C_ (_DEV_BIT16_ | _DEV_TASKINGM16C_ ) -#define _DEV_TASKING_M16C_ (_DEV_BIT8_ | _DEV_TASKINGM16C_ ) -#define _DEV_MITSUBISHI_M16C_ (_DEV_BIT8_ | _DEV_MITSUBISHIM16C_ ) -#define _DEV_GNU_MPC5X5_ (_DEV_BIT32_ | _DEV_GNUC_MPC5X5| _DEV_BIGEND_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_LINUX_ (_DEV_BIT32_ | _DEV_LINUX_GCC_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_GNU_C16X_ (_DEV_BIT16_ | _DEV_GNUC_C16X_ ) //| _DEV_COMMA_EXT_) -#define _DEV_MCW_MPC5X5_ (_DEV_BIT32_ | _DEV_METROWERKS_CW_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_GNU_ARM7_ (_DEV_BIT32_ | _DEV_GNUC_ARM7_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_) -#define _DEV_WIN32_RTX_ (_DEV_BIT32_ | _DEV_MSVC_RTX_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_HIGHTEC_X86_ (_DEV_BIT32_ | _DEV_HIGHTEC_GNUC_X86_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_WIN_CE_ (_DEV_BIT32_ | _DEV_MSEVC_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_KEIL_CARM_ (_DEV_BIT32_ | _DEV_KEIL_ARM_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_IAR_CARM_ (_DEV_BIT32_ | _DEV_IAR_ARM_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_RVCT_CARM_ (_DEV_BIT32_ | _DEV_RVCT_ARM_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_) -#define _DEV_MCW_MCF5XXX_ (_DEV_BIT32_ | _DEV_METROWERKS_CW_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_GNU_CF5282_ (_DEV_BIT32_ | _DEV_GNUC_CF_ | _DEV_BIGEND_) -#define _DEV_PAR_BECK1X3_ (_DEV_BIT16_ | _DEV_PARADGM_X86) -#define _DEV_GNU_CF548X_ (_DEV_BIT32_ | _DEV_GNUC_CF_ | _DEV_BIGEND_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_) -#define _DEV_GNU_I386_ (_DEV_BIT32_ | _DEV_GNUC_X86_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_) -#define _DEV_GNU_TRICORE_ (_DEV_BIT32_ | _DEV_GNUC_TC_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_ | _DEV_ALIGNMENT_4_) -#define _DEV_MPLAB_DSPIC33F_ (_DEV_BIT16_ | _DEV_MPLAB_C30_ ) //| _DEV_COMMA_EXT_) -#define _DEV_GNU_MIPSEL_ (_DEV_BIT32_ | _DEV_GNUC_MIPS2_ | _DEV_BIGEND_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_) - -#define _DEV_RENESAS_M32C_ (_DEV_BIT32_ | _DEV_RENESASM32C) - -//--------------------------------------------------------------------------- -// usefull macros -//--------------------------------------------------------------------------- - -#define CHECK_IF_ONLY_INT_MAIN() (DEV_SYSTEM & _DEV_ONLY_INT_MAIN_) -#define CHECK_MEMORY_ALINMENT() (DEV_SYSTEM & _DEV_MASK_ALIGNMENT) - -//--------------------------------------------------------------------------- -// defines for target system (TARGET_SYSTEM) -//--------------------------------------------------------------------------- - -#define _DOS_ (16 + 0x10000) -#define _WIN16_ 16 -#define _WIN32_ 32 -#define _WINCE_ (32 + 0x20000) -#define _NO_OS_ 0 -#define _LINUX_ 1 -#define _PXROS_ 2 -#define _ECOSPRO_ 3 - -//--------------------------------------------------------------------------- -// definitions for function inlining -//--------------------------------------------------------------------------- - -#define INLINE_FUNCTION // empty define -#undef INLINE_ENABLED // disable actual inlining of functions -#undef INLINE_FUNCTION_DEF // disable inlining for all compilers per default - -//--------------------------------------------------------------------------- -// definitions for Keil C51 -//--------------------------------------------------------------------------- - -#ifdef __C51__ - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_KEIL_C51X_ - -#pragma DEBUG OBJECTEXTEND -#pragma WARNINGLEVEL(2) // maximum warning level - -#define NEAR idata // variables mapped to internal data storage location -#define FAR xdata // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM code // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC xdata // hardware access through external memory (i.e. CAN) -#define LARGE large // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM xdata // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT reentrant -#define PUBLIC - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for GNU Compiler for Infineon C16x -// - it have to be befor Keil (it has __C166__ too) -//--------------------------------------------------------------------------- -#elif defined (__GNUC__) && defined (__C166__) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_GNU_C16X_ - -// #define NEAR idata // variables mapped to internal data storage location -#define NEAR near // variables mapped to internal data storage location -// #define FAR xhuge // variables mapped to external data storage location -#define FAR huge // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -// #define HWACC sdata // hardware access through external memory (i.e. CAN) -#define HWACC huge // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -// #define GENERIC xhuge // generic pointer to point to application data -#define GENERIC huge // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf - -#define ASSERT(p) \ - if (p) \ - { \ - ; \ - } \ - else \ - { \ - PRINTF0("Assert failed: " #p " (file %s line %d)\n", __FILE__, (int) __LINE__ ); \ - while (1); \ - } -#else -#define ASSERT(p) -#endif - -//--------------------------------------------------------------------------- -// definitions for Keil C166 -//--------------------------------------------------------------------------- -#elif defined (__C166__) // 24.01.2005 r.d.: Keil ARM7 needs directive 'defined' - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_KEIL_C16X_ - -#pragma CODE -#pragma MOD167 -#pragma NOINIT -#pragma DEBUG -#pragma WARNINGLEVEL(3) // maximum warning level -#pragma WARNING DISABLE = 47 // warning = OFF -#pragma WARNING DISABLE = 38 // warning = OFF -// #pragma WARNING DISABLE = 102 // warning = OFF -#pragma WARNING DISABLE = 174 // warning = OFF -#pragma WARNING DISABLE = 183 // warning = OFF - -#define NEAR idata // variables mapped to internal data storage location -#define FAR xhuge // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -// #define HWACC sdata // hardware access through external memory (i.e. CAN) -#define HWACC huge // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC xhuge // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for MPLAB C30 for dsPIC33F series -//--------------------------------------------------------------------------- -#elif defined (__C30__) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_MPLAB_DSPIC33F_ - -#define NEAR // variables mapped to internal data storage location -#define FAR // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - -// #ifndef QWORD -// #define QWORD long long -// #endif - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for Keil ARM -//--------------------------------------------------------------------------- -#elif defined (__CA__) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_KEIL_CARM_ - -#define NEAR // variables mapped to internal data storage location -#define FAR // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - -#ifndef QWORD -#define QWORD long long -#endif - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for RealView ARM compilation tools (provided by recent Keil Microcontroller Development Kits) -//--------------------------------------------------------------------------- -#elif defined (__ARMCC_VERSION) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_RVCT_CARM_ - -#define NEAR // variables mapped to internal data storage location -#define FAR // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - -#ifndef QWORD -#define QWORD long long -#endif - -#ifndef NDEBUG -#define ASSERT(expr) if (!(expr)) {\ - TRACE0 ("Assertion failed: " #expr );\ - while (1);} -#else -#define ASSERT(expr) -#endif - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for ARM IAR C Compiler -//--------------------------------------------------------------------------- -#elif defined (__ICCARM__) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_IAR_CARM_ - -#define NEAR // variables mapped to internal data storage location -#define FAR // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - -#ifndef QWORD -#define QWORD long long -#endif - - // Workaround: - // If we use IAR and want to debug but don't want to use C-Spy Debugger - // assert() doesn't work in debug mode because it needs support for FILE descriptors - // (_DLIB_FILE_DESCRIPTOR == 1). -#ifndef NDEBUG -#define ASSERT(expr) if (!(expr)) {\ - TRACE0 ("Assertion failed: " #expr );\ - while (1);} -#else -#define ASSERT(expr) -#endif - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -// #define TRACE PRINTF4 -#endif - -//--------------------------------------------------------------------------- -// definitions for Tasking 8051 -//--------------------------------------------------------------------------- - -#elif defined (_CC51) - -#include - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_TASKING_C51X_ - -#define NEAR _data // variables mapped to internal data storage location -#define FAR _xdat // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC _xdat // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM _xdat // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT _reentrant -#define PUBLIC - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for Tasking C167CR and C164CI -//--------------------------------------------------------------------------- - -#elif defined (_C166) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_TASKING_C16X_ - -#define NEAR near // variables mapped to internal data storage location -#define FAR far // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC /* to be defined */ // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - - // Stdio.h has to be alway included here. If printf() is used stdio.h defines NULL - // without checking if it is already included. So an error occurs while compiling. - // (r.d.) -#include // prototype printf() (for TRACE) -#ifndef NDEBUG -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for FUJITSU FFMC-16LX MB90590 -//--------------------------------------------------------------------------- - -//#elif (defined (F590) || defined (F543) || defined (F598) || defined (F495) || defined (F350)) -#elif defined(__COMPILER_FCC907__) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_FUJITSU_F590_ - -#define NEAR /* to be defined */ // variables mapped to internal data storage location -#define FAR /* to be defined */ // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM /* to be defined */ // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC /* to be defined */ // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - - // softune is not able to support 64 bit variables QWORD !!! - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for Mitsubishi M16C family for TASKING Compiler CM16 -//--------------------------------------------------------------------------- - -#elif defined (_CM16C) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_TASKING_M16C_ - -#define NEAR _near // variables mapped to internal data storage location -#define FAR _far // variables mapped to external data storage location -#define CONST _farrom // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC _near // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC _far // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. - // do you use memory model SMALL, than you have to set _far -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - - // Stdio.h has to be alway included here. If printf() is used stdio.h defines NULL - // without checking if it is already included. So an error occurs while compiling. - // (r.d.) -#include // prototype printf() (for TRACE) -#ifndef NDEBUG -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for Mitsubishi M16C family for Mitsubishi Compiler NC30 -//--------------------------------------------------------------------------- -// name NC30, andere Form will der Compiler nicht !! -#elif defined (NC30) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_MITSUBISHI_M16C_ - -#define NEAR near // variables mapped to internal data storage location -#define FAR far // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC near // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC far // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for Renesas M32C family for Renesas Compiler -//--------------------------------------------------------------------------- -#elif defined (NC308) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_RENESAS_M32C_ - -#define NEAR near // variables mapped to internal data storage location -#define FAR far // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) -#define HWACC // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM far // Memory attribute to optimize speed and code of pointer access. - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -// #error ("RENESAS o.k.") - -//--------------------------------------------------------------------------- -// definitions for ARM7 family with GNU compiler -//--------------------------------------------------------------------------- - -#elif defined(__GNUC__) && defined(__arm__) && !defined(__LINUX_ARM_ARCH__) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_GNU_ARM7_ - -#define NEAR // variables mapped to internal data storage location -#define FAR // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. -#define HWACC // hardware access through external memory (i.e. CAN) - -#define REENTRANT -#define PUBLIC - -#ifndef QWORD -#define QWORD long long // i.A. durch Herr Kuschel -#endif - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for Motorola PowerPC family 5x5 (555/565) -// definitions Linux-PC -//--------------------------------------------------------------------------- - -#elif defined (__GNUC__) - -#if defined (LINUX) || defined (linux) || defined (__linux__) -#define LINUX_SYSTEM // define 'LINUX_SYSTEM' uniform for all Linux based systems - // r.d.: We will need an other solution here! There are two sections here which do check the preproc-definitions: - // LINUX and __linux__ . The first one was Linux for PC, the second one is this section for embedded Linux (MCF5xxx). - // But Linux for PC does not need the definitions for embedded Linux. -#endif - - // GNU C compiler supports function inlining -#define INLINE_FUNCTION_DEF extern inline - - // to actually enable inlining just include the following three lines - // #undef INLINE_FUNCTION - // #define INLINE_FUNCTION INLINE_FUNCTION_DEF - // #define INLINE_ENABLED TRUE - -#ifdef PXROS -#define TARGET_SYSTEM _PXROS_ -#ifdef __i386__ -#undef LINUX // this define seems to be set from compiler -#define DEV_SYSTEM _DEV_HIGHTEC_X86_ -#elif defined (__tricore__) -#define DEV_SYSTEM _DEV_GNU_TRICORE_ -#else // MPC5x5 -#define DEV_SYSTEM _DEV_GNU_MPC5X5_ -#endif - -#elif defined (LINUX) || defined (__linux__) -#define TARGET_SYSTEM _LINUX_ // Linux definition -#define DEV_SYSTEM _DEV_LINUX_ - -#elif defined (GNU_CF5282) -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_GNU_CF5282_ - -#elif defined (ECOSPRO_I386_PEAK_PCI) -#define TARGET_SYSTEM _ECOSPRO_ -#define DEV_SYSTEM _DEV_GNU_I386_ - -#elif defined (GNU_CF548X) -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_GNU_CF548X_ -#else -#error 'ERROR: DEV_SYSTEM not found!' -#endif - -#ifndef QWORD -#define QWORD long long int -#endif - -#if (TARGET_SYSTEM == _PXROS_) - -#ifndef __KERNEL__ -#include -#endif - -#define NEAR // variables mapped to internal data storage location -#define FAR // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM /* to be defined */ // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define HWACC // hardware access through external memory (i.e. CAN) - -#define REENTRANT -#define PUBLIC - -#ifndef QWORD -#define QWORD long long int -#endif - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -#endif - - // ------------------ GNUC for I386 --------------------------------------------- - -#if (TARGET_SYSTEM == _LINUX_) || (TARGET_SYSTEM == _ECOSPRO_) - -#ifndef __KERNEL__ -#include -#endif - -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#ifndef NEAR -#define NEAR // variables mapped to internal data storage location -#endif - -#ifndef FAR -#define FAR // variables mapped to external data storage location -#endif - -#ifndef CONST -#define CONST const // variables mapped to ROM (i.e. flash) -#endif - -#define LARGE - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#ifndef __KERNEL__ -#include // prototype printf() (for TRACE) -#define TRACE printf -#else #define TRACE printk -#endif -#endif -#endif - // ------------------ GNU without OS --------------------------------------------- - -#if (TARGET_SYSTEM == _NO_OS_) - -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#ifndef NEAR -#define NEAR // variables mapped to internal data storage location -#endif - -#ifndef FAR -#define FAR // variables mapped to external data storage location -#endif - -#ifndef CONST -#define CONST const // variables mapped to ROM (i.e. flash) -#endif - -#define LARGE - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -// #include "xuartdrv.h" -// #include // prototype printf() (for TRACE) -#define TRACE printf -// #define TRACE mprintf -// #ifndef TRACE -// #define TRACE trace -// void trace (char *fmt, ...); -// #endif -#endif - -#endif - -//--------------------------------------------------------------------------- -// definitions for MPC565 -//--------------------------------------------------------------------------- -#elif __MWERKS__ - -#ifdef __MC68K__ - -#define TARGET_SYSTEM = _MCF548X_ -#define DEV_SYSTEM _DEV_MCW_MCF5XXX_ - -#else -#define TARGET_SYSTEM = _MPC565_ -#define DEV_SYSTEM _DEV_MCW_MPC5X5_ -#endif - -#define NEAR // variables mapped to internal data storage location -#define FAR // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define LARGE // functions set parameters to external data storage location - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#define HWACC // hardware access through external memory (i.e. CAN) - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#include // prototype printf() (for TRACE) -#define TRACE printf -#endif - -//--------------------------------------------------------------------------- -// definitions for BECK 1x3 -//--------------------------------------------------------------------------- -#elif defined (__BORLANDC__) && defined (__PARADIGM__) - -#define TARGET_SYSTEM _NO_OS_ -#define DEV_SYSTEM _DEV_PAR_BECK1X3_ - -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. -#define NEAR __near // variables mapped to internal data storage location -#define FAR __far // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define LARGE - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#ifndef TRACE -#include -#define TRACE printf -#endif -#endif - -//--------------------------------------------------------------------------- -// definitions for PC -//--------------------------------------------------------------------------- - -#elif defined (__BORLANDC__) - - // ------------------ definition target system -------------------------- - -#ifdef _WIN32 -#define TARGET_SYSTEM _WIN32_ // WIN32 definition -#define DEV_SYSTEM _DEV_WIN32_ -#else -#define TARGET_SYSTEM _DOS_ -#define DEV_SYSTEM _DEV_BORLAND_DOS_ -#endif - - // ------------------ WIN32 --------------------------------------------- - -#if (TARGET_SYSTEM == _WIN32_) - -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#ifndef NEAR -#define NEAR // variables mapped to internal data storage location -#endif - -#ifndef FAR -#define FAR // variables mapped to external data storage location -#endif - -#ifndef CONST -#define CONST const // variables mapped to ROM (i.e. flash) -#endif - -#define LARGE - -#define REENTRANT -#define PUBLIC __stdcall - -#ifndef NDEBUG -#ifndef TRACE -#include -#define TRACE printf -#endif -#endif - -#elif (TARGET_SYSTEM == _DOS_) - -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. -#define NEAR near // variables mapped to internal data storage location -#define FAR far // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define LARGE - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#ifndef TRACE -#include -#define TRACE printf -#endif -#endif - -#endif - -#elif (_MSC_VER == 800) // PC MS Visual C/C++ for DOS applications - -#define TARGET_SYSTEM _DOS_ -#define DEV_SYSTEM _DEV_MSVC_DOS_ - -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC near // hardware access through external memory (i.e. CAN) - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. -#define NEAR near // variables mapped to internal data storage location -#define FAR far // variables mapped to external data storage location -#define CONST const // variables mapped to ROM (i.e. flash) -#define LARGE - -#define REENTRANT -#define PUBLIC - -#ifndef NDEBUG -#ifndef TRACE -#include -#define TRACE printf -#endif -#endif - -//--------------------------------------------------------------------------- -// definitions for RTX under WIN32 -//--------------------------------------------------------------------------- -#elif (defined (UNDER_RTSS) && defined (WIN32)) - - // ------------------ definition target system -------------------------- -#define TARGET_SYSTEM _WIN32_RTX_ -#define DEV_SYSTEM _DEV_WIN32_RTX_ - -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#ifndef NEAR -#define NEAR // variables mapped to internal data storage location -#endif - -#ifndef FAR -#define FAR // variables mapped to external data storage location -#endif - -#ifndef CONST -#define CONST const // variables mapped to ROM (i.e. flash) -#endif - -#define LARGE - -#define REENTRANT -#define PUBLIC __stdcall - -#ifndef NDEBUG -#ifndef TRACE -#define TRACE RtPrintf -#endif -#endif - -//--------------------------------------------------------------------------- -// definitions for WinCE -//--------------------------------------------------------------------------- -#elif defined (_WIN32_WCE) - - // ------------------ definition target system -------------------------- -#define TARGET_SYSTEM _WINCE_ -#define DEV_SYSTEM _DEV_WIN_CE_ - -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#ifndef NEAR -#define NEAR // variables mapped to internal data storage location -#endif - -#ifndef FAR -#define FAR // variables mapped to external data storage location -#endif - -#ifndef CONST -#define CONST const // variables mapped to ROM (i.e. flash) -#endif - -#define LARGE - -#ifndef QWORD - //#define QWORD long long int // MSVC .NET can use "long long int" too (like GNU) -#define QWORD __int64 -#endif - -#define REENTRANT -#define PUBLIC __cdecl - -#ifdef ASSERTMSG -#undef ASSERTMSG -#endif - -#ifndef NDEBUG -#ifndef TRACE -#define TRACE printf -// void trace (char *fmt, ...); -#endif -#endif - -#else // ===> PC MS Visual C/C++ - - // ------------------ definition target system -------------------------- - -#ifdef _WIN32 -#define TARGET_SYSTEM _WIN32_ // WIN32 definition -#define DEV_SYSTEM _DEV_WIN32_ -#else -#define TARGET_SYSTEM _WIN16_ // WIN16 definition -#define DEV_SYSTEM _DEV_WIN16_ -#endif - - // ------------------ WIN16 --------------------------------------------- - -#if (TARGET_SYSTEM == _WIN16_) - -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) - - // These types can be adjusted by users to match application requirements. The goal is to - // minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external - // or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. - -#ifndef NEAR -#define NEAR // variables mapped to internal data storage location -#endif - -#ifndef FAR -#define FAR far // variables mapped to external data storage location -#endif - -#ifndef CONST -#define CONST const // variables mapped to ROM (i.e. flash) -#endif - -#define LARGE - -#define REENTRANT -#define PUBLIC _far _pascal _export - -#ifndef NDEBUG -#ifndef TRACE -#define TRACE trace -#ifdef __cplusplus -extern "C" { -#endif - void trace(const char *fmt, ...); -#ifdef __cplusplus -} -#endif -#endif -#endif -#endif - // ------------------ WIN32 --------------------------------------------- -#if (TARGET_SYSTEM == _WIN32_) -#define ROM // code or variables mapped to ROM (i.e. flash) - // usage: CONST BYTE ROM foo = 0x00; -#define HWACC // hardware access through external memory (i.e. CAN) - // These types can be adjusted by users to match application requirements. The goal is to// minimize code memory and maximize speed. -#define GENERIC // generic pointer to point to application data - // Variables with this attribute can be located in external// or internal data memory. -#define MEM // Memory attribute to optimize speed and code of pointer access. -#ifndef NEAR -#define NEAR // variables mapped to internal data storage location -#endif -#ifndef FAR -#define FAR // variables mapped to external data storage location -#endif -#ifndef CONST -#define CONST const // variables mapped to ROM (i.e. flash) -#endif -#define LARGE -#define REENTRANT -#define PUBLIC __stdcall -#ifndef QWORD - //#define QWORD long long int // MSVC .NET can use "long long int" too (like GNU) -#define QWORD __int64 -#endif -#ifndef NDEBUG -#ifndef TRACE -#define TRACE trace -#ifdef __cplusplus -extern "C" { -#endif - void trace(const char *fmt, ...); -#ifdef __cplusplus -} -#endif -#endif -#endif - // MS Visual C++ compiler supports function inlining -#define INLINE_FUNCTION_DEF __forceinline - // to actually enable inlining just include the following two lines// #define INLINE_FUNCTION INLINE_FUNCTION_DEF// #define INLINE_ENABLED TRUE -#endif -#endif // ===> PC -//---------------------------------------------------------------------------// definitions of basic types//--------------------------------------------------------------------------- -#ifndef _WINDEF_ // defined in WINDEF.H, included by - // --- arithmetic types --- -#ifndef SHORT -#define SHORT short int -#endif -#ifndef USHORT -#define USHORT unsigned short int -#endif -#ifndef INT -#define INT int -#endif -#ifndef UINT -#define UINT unsigned int -#endif -#ifndef LONG -#define LONG long int -#endif -#ifndef ULONG -#define ULONG unsigned long int -#endif - // --- logic types --- -#ifndef BYTE -#define BYTE unsigned char -#endif -#ifndef WORD -#define WORD unsigned short int -#endif -#ifndef DWORD -#define DWORD unsigned long int -#endif +// --- logic types --- #ifndef BOOL #define BOOL unsigned char #endif - // --- alias types --- + +// --- alias types --- #ifndef TRUE #define TRUE 0xFF #endif #ifndef FALSE #define FALSE 0x00 #endif -#ifndef NULL -#define NULL ((void *) 0) -#endif -#endif #ifndef _TIME_OF_DAY_DEFINED_ typedef struct { unsigned long int m_dwMs; @@ -1359,15 +119,8 @@ typedef struct { //--------------------------------------------------------------------------- #ifndef ASSERT -#if !defined (__linux__) && !defined (__KERNEL__) -#include -#ifndef ASSERT -#define ASSERT(p) assert(p) -#endif -#else #define ASSERT(p) #endif -#endif //--------------------------------------------------------------------------- // SYS TEC extensions diff --git a/drivers/staging/epl/kernel/EplDllk.h b/drivers/staging/epl/kernel/EplDllk.h index 588e871a922b..a97920ab8841 100644 --- a/drivers/staging/epl/kernel/EplDllk.h +++ b/drivers/staging/epl/kernel/EplDllk.h @@ -74,18 +74,10 @@ #include "../EplDll.h" #include "../EplEvent.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - typedef tEplKernel(*tEplDllkCbAsync) (tEplFrameInfo * pFrameInfo_p); typedef struct { - BYTE m_be_abSrcMac[6]; + u8 m_be_abSrcMac[6]; } tEplDllkInitParam; @@ -96,22 +88,18 @@ struct _tEplDllkNodeInfo { struct _tEplDllkNodeInfo *m_pNextNodeInfo; struct _tEdrvTxBuffer *m_pPreqTxBuffer; unsigned int m_uiNodeId; - DWORD m_dwPresTimeout; + u32 m_dwPresTimeout; unsigned long m_ulDllErrorEvents; tEplNmtState m_NmtState; - WORD m_wPresPayloadLimit; - BYTE m_be_abMacAddr[6]; - BYTE m_bSoaFlag1; + u16 m_wPresPayloadLimit; + u8 m_be_abMacAddr[6]; + u8 m_bSoaFlag1; BOOL m_fSoftDelete; // delete node after error and ignore error }; typedef struct _tEplDllkNodeInfo tEplDllkNodeInfo; -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p); @@ -154,7 +142,7 @@ tEplKernel EplDllkDeleteNode(unsigned int uiNodeId_p); tEplKernel EplDllkSoftDeleteNode(unsigned int uiNodeId_p); -tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, BYTE bSoaFlag1_p); +tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, u8 bSoaFlag1_p); tEplKernel EplDllkGetFirstNodeInfo(tEplDllkNodeInfo ** ppNodeInfo_p); diff --git a/drivers/staging/epl/kernel/EplDllkCal.h b/drivers/staging/epl/kernel/EplDllkCal.h index 6c4dc7e4a80d..ddec1d5e8cc4 100644 --- a/drivers/staging/epl/kernel/EplDllkCal.h +++ b/drivers/staging/epl/kernel/EplDllkCal.h @@ -74,14 +74,6 @@ #include "../EplDll.h" #include "../EplEvent.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - typedef struct { unsigned long m_ulCurTxFrameCountGen; unsigned long m_ulCurTxFrameCountNmt; @@ -92,10 +84,6 @@ typedef struct { } tEplDllkCalStatistics; -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) tEplKernel EplDllkCalAddInstance(void); @@ -124,7 +112,7 @@ tEplKernel EplDllkCalProcess(tEplEvent * pEvent_p); tEplKernel EplDllkCalAsyncClearQueues(void); tEplKernel EplDllkCalIssueRequest(tEplDllReqServiceId Service_p, - unsigned int uiNodeId_p, BYTE bSoaFlag1_p); + unsigned int uiNodeId_p, u8 bSoaFlag1_p); tEplKernel EplDllkCalAsyncGetSoaRequest(tEplDllReqServiceId * pReqServiceId_p, unsigned int *puiNodeId_p); diff --git a/drivers/staging/epl/kernel/EplErrorHandlerk.h b/drivers/staging/epl/kernel/EplErrorHandlerk.h index 4a67ef88b97a..185b597d6e56 100644 --- a/drivers/staging/epl/kernel/EplErrorHandlerk.h +++ b/drivers/staging/epl/kernel/EplErrorHandlerk.h @@ -73,28 +73,16 @@ #include "../EplEvent.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - // init function -tEplKernel PUBLIC EplErrorHandlerkInit(void); +tEplKernel EplErrorHandlerkInit(void); // add instance -tEplKernel PUBLIC EplErrorHandlerkAddInstance(void); +tEplKernel EplErrorHandlerkAddInstance(void); // delete instance -tEplKernel PUBLIC EplErrorHandlerkDelInstance(void); +tEplKernel EplErrorHandlerkDelInstance(void); // processes error events -tEplKernel PUBLIC EplErrorHandlerkProcess(tEplEvent * pEvent_p); +tEplKernel EplErrorHandlerkProcess(tEplEvent *pEvent_p); #endif // #ifndef _EPL_ERRORHANDLERK_H_ diff --git a/drivers/staging/epl/kernel/EplEventk.h b/drivers/staging/epl/kernel/EplEventk.h index 1d25aaa2ed49..0c2a60f72073 100644 --- a/drivers/staging/epl/kernel/EplEventk.h +++ b/drivers/staging/epl/kernel/EplEventk.h @@ -73,36 +73,24 @@ #include "../EplEvent.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - // init function -tEplKernel PUBLIC EplEventkInit(tEplSyncCb fpSyncCb); +tEplKernel EplEventkInit(tEplSyncCb fpSyncCb); // add instance -tEplKernel PUBLIC EplEventkAddInstance(tEplSyncCb fpSyncCb); +tEplKernel EplEventkAddInstance(tEplSyncCb fpSyncCb); // delete instance -tEplKernel PUBLIC EplEventkDelInstance(void); +tEplKernel EplEventkDelInstance(void); // Kernelthread that dispatches events in kernelspace -tEplKernel PUBLIC EplEventkProcess(tEplEvent * pEvent_p); +tEplKernel EplEventkProcess(tEplEvent *pEvent_p); // post events from kernelspace -tEplKernel PUBLIC EplEventkPost(tEplEvent * pEvent_p); +tEplKernel EplEventkPost(tEplEvent *pEvent_p); // post errorevents from kernelspace -tEplKernel PUBLIC EplEventkPostError(tEplEventSource EventSource_p, - tEplKernel EplError_p, - unsigned int uiArgSize_p, void *pArg_p); +tEplKernel EplEventkPostError(tEplEventSource EventSource_p, + tEplKernel EplError_p, + unsigned int uiArgSize_p, void *pArg_p); #endif // #ifndef _EPL_EVENTK_H_ diff --git a/drivers/staging/epl/kernel/EplNmtk.h b/drivers/staging/epl/kernel/EplNmtk.h index 53409cc89921..5dc8a373159f 100644 --- a/drivers/staging/epl/kernel/EplNmtk.h +++ b/drivers/staging/epl/kernel/EplNmtk.h @@ -74,31 +74,16 @@ #include "../EplNmt.h" #include "EplEventk.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) -EPLDLLEXPORT tEplKernel PUBLIC EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR); +tEplKernel EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR); -EPLDLLEXPORT tEplKernel PUBLIC -EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR); +tEplKernel EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR); -EPLDLLEXPORT tEplKernel PUBLIC -EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR); +tEplKernel EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR); -EPLDLLEXPORT tEplKernel PUBLIC EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_ - tEplEvent * pEvent_p); +tEplKernel EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplEvent *pEvent_p); -EPLDLLEXPORT tEplNmtState PUBLIC -EplNmtkGetNmtState(EPL_MCO_DECL_PTR_INSTANCE_PTR); +tEplNmtState EplNmtkGetNmtState(EPL_MCO_DECL_PTR_INSTANCE_PTR); #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) diff --git a/drivers/staging/epl/kernel/EplNmtkCal.h b/drivers/staging/epl/kernel/EplNmtkCal.h deleted file mode 100644 index 9edeafca4920..000000000000 --- a/drivers/staging/epl/kernel/EplNmtkCal.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** - - (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 - www.systec-electronic.com - - Project: openPOWERLINK - - Description: include file for communication abstraction layer of the - NMT-Kernel-Module - - License: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of SYSTEC electronic GmbH nor the names of its - contributors may be used to endorse or promote products derived - from this software without prior written permission. For written - permission, please contact info@systec-electronic.com. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Severability Clause: - - If a provision of this License is or becomes illegal, invalid or - unenforceable in any jurisdiction, that shall not affect: - 1. the validity or enforceability in that jurisdiction of any other - provision of this License; or - 2. the validity or enforceability in other jurisdictions of that or - any other provision of this License. - - ------------------------------------------------------------------------- - - $RCSfile: EplNmtkCal.h,v $ - - $Author: D.Krueger $ - - $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $ - - $State: Exp $ - - Build Environment: - KEIL uVision 2 - - ------------------------------------------------------------------------- - - Revision History: - - 2006/06/16 -k.t.: start of the implementation - -****************************************************************************/ - -#include "EplNmtk.h" - -#ifndef _EPLNMTKCAL_H_ -#define _EPLNMTKCAL_H_ - -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - -#endif // #ifndef _EPLNMTKCAL_H_ diff --git a/drivers/staging/epl/kernel/EplObdk.h b/drivers/staging/epl/kernel/EplObdk.h index cf9f5837dd38..78c4d9613425 100644 --- a/drivers/staging/epl/kernel/EplObdk.h +++ b/drivers/staging/epl/kernel/EplObdk.h @@ -68,128 +68,88 @@ ****************************************************************************/ -#include "../EplObd.h" - #ifndef _EPLOBDK_H_ #define _EPLOBDK_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "../EplObd.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- +extern u8 abEplObdTrashObject_g[8]; -//--------------------------------------------------------------------------- -// global variables -//--------------------------------------------------------------------------- - -extern BYTE MEM abEplObdTrashObject_g[8]; - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_ - tEplObdInitParam MEM * pInitParam_p); +tEplKernel EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplObdInitParam *pInitParam_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_ - tEplObdInitParam MEM * - pInitParam_p); +tEplKernel EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplObdInitParam *pInitParam_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR); +tEplKernel EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p); +tEplKernel EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, tEplObdSize Size_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p); +tEplKernel EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, tEplObdSize *pSize_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC -EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdStoreLoadObjCallback fpCallback_p); +tEplKernel EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdStoreLoadObjCallback fpCallback_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdPart ObdPart_p, - tEplObdDir Direction_p); +tEplKernel EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdPart ObdPart_p, + tEplObdDir Direction_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_ - tEplVarParam MEM * pVarParam_p); +tEplKernel EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_ tEplVarParam *pVarParam_p); // --------------------------------------------------------------------- -EPLDLLEXPORT void *PUBLIC EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p); +void *EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdEntryPtr pUserOd_p); +tEplKernel EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdEntryPtr pUserOd_p); // --------------------------------------------------------------------- -EPLDLLEXPORT void PUBLIC EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ - tEplObdVarEntry MEM * pVarEntry_p, - tEplObdType Type_p, - tEplObdSize ObdSize_p); +void EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ tEplObdVarEntry *pVarEntry_p, + tEplObdType Type_p, tEplObdSize ObdSize_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplObdSize PUBLIC EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p); +tEplObdSize EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p); // --------------------------------------------------------------------- -EPLDLLEXPORT unsigned int PUBLIC EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR); +unsigned int EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdSetNodeId(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiNodeId_p, - tEplObdNodeIdType NodeIdType_p); +tEplKernel EplObdSetNodeId(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - BOOL * pfEntryNumerical); +tEplKernel EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, BOOL *pfEntryNumerical); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p); +tEplKernel EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, + tEplObdSize Size_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p); +tEplKernel EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, + tEplObdSize *pSize_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - tEplObdAccess * - pAccessTyp_p); +tEplKernel EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess *pAccessTyp_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubindex_p, - tEplObdVarEntry MEM ** - ppVarEntry_p); +tEplKernel EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry **ppVarEntry_p); #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0) diff --git a/drivers/staging/epl/kernel/EplObdkCal.h b/drivers/staging/epl/kernel/EplObdkCal.h deleted file mode 100644 index c173a950054f..000000000000 --- a/drivers/staging/epl/kernel/EplObdkCal.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** - - (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 - www.systec-electronic.com - - Project: openPOWERLINK - - Description: include file for communication abstraction layer - for the Epl-Obd-Kernelspace-Modul - - License: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of SYSTEC electronic GmbH nor the names of its - contributors may be used to endorse or promote products derived - from this software without prior written permission. For written - permission, please contact info@systec-electronic.com. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - Severability Clause: - - If a provision of this License is or becomes illegal, invalid or - unenforceable in any jurisdiction, that shall not affect: - 1. the validity or enforceability in that jurisdiction of any other - provision of this License; or - 2. the validity or enforceability in other jurisdictions of that or - any other provision of this License. - - ------------------------------------------------------------------------- - - $RCSfile: EplObdkCal.h,v $ - - $Author: D.Krueger $ - - $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $ - - $State: Exp $ - - Build Environment: - GCC V3.4 - - ------------------------------------------------------------------------- - - Revision History: - - 2006/06/19 k.t.: start of the implementation - -****************************************************************************/ - -#include "../EplObd.h" - -#ifndef _EPLOBDKCAL_H_ -#define _EPLOBDKCAL_H_ - -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - -#endif // #ifndef _EPLOBDKCAL_H_ diff --git a/drivers/staging/epl/kernel/EplPdok.h b/drivers/staging/epl/kernel/EplPdok.h index b5b18f4cf687..24bfc3f73e9c 100644 --- a/drivers/staging/epl/kernel/EplPdok.h +++ b/drivers/staging/epl/kernel/EplPdok.h @@ -75,18 +75,6 @@ #include "../EplEvent.h" #include "../EplDll.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - // process events from queue (PDOs/frames and SoA for synchronization) tEplKernel EplPdokProcess(tEplEvent * pEvent_p); diff --git a/drivers/staging/epl/kernel/EplPdokCal.h b/drivers/staging/epl/kernel/EplPdokCal.h index 6a183ebe81ef..8a31edfdb4fc 100644 --- a/drivers/staging/epl/kernel/EplPdokCal.h +++ b/drivers/staging/epl/kernel/EplPdokCal.h @@ -72,19 +72,6 @@ #define _EPL_PDOKCAL_H_ #include "../EplInc.h" -//#include "EplPdo.h" - -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- tEplKernel EplPdokCalAddInstance(void); diff --git a/drivers/staging/epl/kernel/EplTimerHighResk.h b/drivers/staging/epl/kernel/EplTimerHighResk.h index d5d046d4d370..a2124ee49f77 100644 --- a/drivers/staging/epl/kernel/EplTimerHighResk.h +++ b/drivers/staging/epl/kernel/EplTimerHighResk.h @@ -68,42 +68,29 @@ ****************************************************************************/ -#include "../EplTimer.h" - #ifndef _EPLTIMERHIGHRESK_H_ #define _EPLTIMERHIGHRESK_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "../EplTimer.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- +tEplKernel EplTimerHighReskInit(void); -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- +tEplKernel EplTimerHighReskAddInstance(void); -tEplKernel PUBLIC EplTimerHighReskInit(void); +tEplKernel EplTimerHighReskDelInstance(void); -tEplKernel PUBLIC EplTimerHighReskAddInstance(void); +tEplKernel EplTimerHighReskSetTimerNs(tEplTimerHdl *pTimerHdl_p, + unsigned long long ullTimeNs_p, + tEplTimerkCallback pfnCallback_p, + unsigned long ulArgument_p, + BOOL fContinuously_p); -tEplKernel PUBLIC EplTimerHighReskDelInstance(void); +tEplKernel EplTimerHighReskModifyTimerNs(tEplTimerHdl *pTimerHdl_p, + unsigned long long ullTimeNs_p, + tEplTimerkCallback pfnCallback_p, + unsigned long ulArgument_p, + BOOL fContinuously_p); -tEplKernel PUBLIC EplTimerHighReskSetTimerNs(tEplTimerHdl * pTimerHdl_p, - unsigned long long ullTimeNs_p, - tEplTimerkCallback pfnCallback_p, - unsigned long ulArgument_p, - BOOL fContinuously_p); - -tEplKernel PUBLIC EplTimerHighReskModifyTimerNs(tEplTimerHdl * pTimerHdl_p, - unsigned long long ullTimeNs_p, - tEplTimerkCallback - pfnCallback_p, - unsigned long ulArgument_p, - BOOL fContinuously_p); - -tEplKernel PUBLIC EplTimerHighReskDeleteTimer(tEplTimerHdl * pTimerHdl_p); +tEplKernel EplTimerHighReskDeleteTimer(tEplTimerHdl *pTimerHdl_p); #endif // #ifndef _EPLTIMERHIGHRESK_H_ diff --git a/drivers/staging/epl/kernel/EplTimerk.h b/drivers/staging/epl/kernel/EplTimerk.h index 9160e7260de8..47c5f47b8aaa 100644 --- a/drivers/staging/epl/kernel/EplTimerk.h +++ b/drivers/staging/epl/kernel/EplTimerk.h @@ -68,19 +68,16 @@ ****************************************************************************/ -#include "../EplTimer.h" -#include "../user/EplEventu.h" - #ifndef _EPLTIMERK_H_ #define _EPLTIMERK_H_ +#include "../EplTimer.h" +#include "../user/EplEventu.h" + #if EPL_TIMER_USE_USER != FALSE #include "../user/EplTimeru.h" #endif -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- #if EPL_TIMER_USE_USER != FALSE #define EplTimerkInit EplTimeruInit @@ -91,28 +88,21 @@ #define EplTimerkDeleteTimer EplTimeruDeleteTimer #endif -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- #if EPL_TIMER_USE_USER == FALSE -tEplKernel PUBLIC EplTimerkInit(void); +tEplKernel EplTimerkInit(void); -tEplKernel PUBLIC EplTimerkAddInstance(void); +tEplKernel EplTimerkAddInstance(void); -tEplKernel PUBLIC EplTimerkDelInstance(void); +tEplKernel EplTimerkDelInstance(void); -tEplKernel PUBLIC EplTimerkSetTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p); +tEplKernel EplTimerkSetTimerMs(tEplTimerHdl *pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p); -tEplKernel PUBLIC EplTimerkModifyTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p); +tEplKernel EplTimerkModifyTimerMs(tEplTimerHdl *pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p); -tEplKernel PUBLIC EplTimerkDeleteTimer(tEplTimerHdl * pTimerHdl_p); +tEplKernel EplTimerkDeleteTimer(tEplTimerHdl *pTimerHdl_p); #endif #endif // #ifndef _EPLTIMERK_H_ diff --git a/drivers/staging/epl/kernel/VirtualEthernet.h b/drivers/staging/epl/kernel/VirtualEthernet.h index deff8720e37f..4a42cce66cac 100644 --- a/drivers/staging/epl/kernel/VirtualEthernet.h +++ b/drivers/staging/epl/kernel/VirtualEthernet.h @@ -73,23 +73,11 @@ #include "EplDllk.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0) -tEplKernel PUBLIC VEthAddInstance(tEplDllkInitParam * pInitParam_p); +tEplKernel VEthAddInstance(tEplDllkInitParam *pInitParam_p); -tEplKernel PUBLIC VEthDelInstance(void); +tEplKernel VEthDelInstance(void); #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0) diff --git a/drivers/staging/epl/proc_fs.c b/drivers/staging/epl/proc_fs.c index f4910332d3c6..9ccf079e67e1 100644 --- a/drivers/staging/epl/proc_fs.c +++ b/drivers/staging/epl/proc_fs.c @@ -83,7 +83,6 @@ #include #include #include -#include #include #include #include @@ -95,6 +94,8 @@ #include "fec.h" #endif +#include "proc_fs.h" + /***************************************************************************/ /* */ /* */ @@ -129,8 +130,8 @@ #ifdef _DBG_TRACE_POINTS_ atomic_t aatmDbgTracePoint_l[DBG_TRACE_POINTS]; -DWORD adwDbgTraceValue_l[DBG_TRACE_VALUES]; -DWORD dwDbgTraceValueOld_l; +u32 adwDbgTraceValue_l[DBG_TRACE_VALUES]; +u32 dwDbgTraceValueOld_l; unsigned int uiDbgTraceValuePos_l; spinlock_t spinlockDbgTraceValue_l; unsigned long ulDbTraceValueFlags_l; @@ -145,10 +146,10 @@ static int EplLinProcRead(char *pcBuffer_p, char **ppcStart_p, off_t Offset_p, static int EplLinProcWrite(struct file *file, const char __user * buffer, unsigned long count, void *data); -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); -void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); +void TgtDbgPostTraceValue(u32 dwTraceValue_p); -EPLDLLEXPORT DWORD PUBLIC EplIdentuGetRunningRequests(void); +extern u32 EplIdentuGetRunningRequests(void); //=========================================================================// // // @@ -191,7 +192,7 @@ tEplKernel EplLinProcFree(void) //--------------------------------------------------------------------------- #ifdef _DBG_TRACE_POINTS_ -void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p) +void TgtDbgSignalTracePoint(u8 bTracePointNumber_p) { if (bTracePointNumber_p >= @@ -207,7 +208,7 @@ void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p) } -void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p) +void TgtDbgPostTraceValue(u32 dwTraceValue_p) { spin_lock_irqsave(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l); @@ -263,7 +264,7 @@ static int EplLinProcRead(char *pcBuffer_p, // ---- EPL state ---- nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize, "NMT state: 0x%04X\n", - (WORD) EplNmtkGetNmtState()); + (u16) EplNmtkGetNmtState()); EplDllkCalGetStatistics(&pDllkCalStats); @@ -279,14 +280,14 @@ static int EplLinProcRead(char *pcBuffer_p, #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) // fetch running IdentRequests nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize, - "running IdentRequests: 0x%08lX\n", + "running IdentRequests: 0x%08X\n", EplIdentuGetRunningRequests()); // fetch state of NmtMnu module { unsigned int uiMandatorySlaveCount; unsigned int uiSignalSlaveCount; - WORD wFlags; + u16 wFlags; EplNmtMnuGetDiagnosticInfo(&uiMandatorySlaveCount, &uiSignalSlaveCount, &wFlags); diff --git a/drivers/staging/epl/user/EplCfgMau.h b/drivers/staging/epl/user/EplCfgMau.h index d25a1e9d36cf..4ac770f1310c 100644 --- a/drivers/staging/epl/user/EplCfgMau.h +++ b/drivers/staging/epl/user/EplCfgMau.h @@ -69,25 +69,22 @@ ****************************************************************************/ -#include "../EplInc.h" - #ifndef _EPLCFGMA_H_ #define _EPLCFGMA_H_ +#include "../EplInc.h" + #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_CFGMA)) != 0) #include "EplObdu.h" #include "EplSdoComu.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- //define max number of timeouts for configuration of 1 device #define EPL_CFGMA_MAX_TIMEOUT 3 //callbackfunction, called if configuration is finished -typedef void (PUBLIC * tfpEplCfgMaCb) (unsigned int uiNodeId_p, - tEplKernel Errorstate_p); +typedef void (* tfpEplCfgMaCb)(unsigned int uiNodeId_p, + tEplKernel Errorstate_p); //State for configuartion manager Statemachine typedef enum { @@ -131,32 +128,28 @@ typedef enum { typedef struct { tEplCfgState m_CfgState; // state of the configuration state maschine tEplSdoComConHdl m_SdoComConHdl; // handle for sdo connection - DWORD m_dwLastAbortCode; + u32 m_dwLastAbortCode; unsigned int m_uiLastIndex; // last index of configuration, to compair with actual index - BYTE *m_pbConcise; // Ptr to concise DCF - BYTE *m_pbActualIndex; // Ptr to actual index in the DCF segment + u8 *m_pbConcise; // Ptr to concise DCF + u8 *m_pbActualIndex; // Ptr to actual index in the DCF segment tfpEplCfgMaCb m_pfnCfgMaCb; // Ptr to CfgMa Callback, is call if configuration finished tEplKernel m_EplKernelError; // errorcode - DWORD m_dwNumValueCopy; // numeric values are copied in this variable + u32 m_dwNumValueCopy; // numeric values are copied in this variable unsigned int m_uiPdoNodeId; // buffer for PDO node id - BYTE m_bNrOfMappedObject; // number of mapped objects + u8 m_bNrOfMappedObject; // number of mapped objects unsigned int m_uiNodeId; // Epl node addresse tEplSdocState m_SdocState; // bitcoded state of the SDO transfer unsigned int m_uiLastSubIndex; // last subindex of configuration BOOL m_fOneTranferOk; // atleased one transfer was successful - BYTE m_bEventFlag; // for Eventsignaling to the State Maschine - DWORD m_dwCntObjectInDcf; // number of Objects in DCF + u8 m_bEventFlag; // for Eventsignaling to the State Maschine + u32 m_dwCntObjectInDcf; // number of Objects in DCF tEplCfgMaIndexType m_SkipCfg; // TRUE if a adsitional Configurationprocess // have to insert e.g. PDO-mapping - WORD m_wTimeOutCnt; // Timeout Counter, break configuration is + u16 m_wTimeOutCnt; // Timeout Counter, break configuration is // m_wTimeOutCnt == CFGMA_MAX_TIMEOUT } tEplCfgMaNode; -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - //--------------------------------------------------------------------------- // Function: EplCfgMaInit() // @@ -166,7 +159,7 @@ typedef struct { // // Returns: tEplKernel = error code //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplCfgMaInit(); +tEplKernel EplCfgMaInit(void); //--------------------------------------------------------------------------- // Function: EplCfgMaAddInstance() @@ -177,7 +170,7 @@ tEplKernel PUBLIC EplCfgMaInit(); // // Returns: tEplKernel = error code //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplCfgMaAddInstance(); +tEplKernel EplCfgMaAddInstance(void); //--------------------------------------------------------------------------- // Function: EplCfgMaDelInstance() @@ -188,7 +181,7 @@ tEplKernel PUBLIC EplCfgMaAddInstance(); // // Returns: tEplKernel = error code //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplCfgMaDelInstance(); +tEplKernel plCfgMaDelInstance(void); //--------------------------------------------------------------------------- // Function: EplCfgMaStartConfig() @@ -199,16 +192,16 @@ tEplKernel PUBLIC EplCfgMaDelInstance(); // Parameters: uiNodeId_p = NodeId of the node to configure // pbConcise_p = pointer to DCF // fpCfgMaCb_p = pointer to callback function (should not be NULL) -// SizeOfConcise_p = size of DCF in BYTE -> for future use +// SizeOfConcise_p = size of DCF in u8 -> for future use // DcfType_p = type of the DCF // // Returns: tCopKernel = error code //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplCfgMaStartConfig(unsigned int uiNodeId_p, - BYTE * pbConcise_p, - tfpEplCfgMaCb fpCfgMaCb_p, - tEplObdSize SizeOfConcise_p, - tEplCfgMaDcfTyp DcfType_p); +tEplKernel EplCfgMaStartConfig(unsigned int uiNodeId_p, + u8 * pbConcise_p, + tfpEplCfgMaCb fpCfgMaCb_p, + tEplObdSize SizeOfConcise_p, + tEplCfgMaDcfTyp DcfType_p); //--------------------------------------------------------------------------- // Function: CfgMaStartConfigurationNode() @@ -222,9 +215,9 @@ tEplKernel PUBLIC EplCfgMaStartConfig(unsigned int uiNodeId_p, // // Returns: tCopKernel = error code //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplCfgMaStartConfigNode(unsigned int uiNodeId_p, - tfpEplCfgMaCb fpCfgMaCb_p, - tEplCfgMaDcfTyp DcfType_p); +tEplKernel EplCfgMaStartConfigNode(unsigned int uiNodeId_p, + tfpEplCfgMaCb fpCfgMaCb_p, + tEplCfgMaDcfTyp DcfType_p); //--------------------------------------------------------------------------- // Function: EplCfgMaStartConfigNodeDcf() @@ -235,16 +228,16 @@ tEplKernel PUBLIC EplCfgMaStartConfigNode(unsigned int uiNodeId_p, // Parameters: uiNodeId_p = NodeId of the node to configure // pbConcise_p = pointer to DCF // fpCfgMaCb_p = pointer to callback function (should not be NULL) -// SizeOfConcise_p = size of DCF in BYTE -> for future use +// SizeOfConcise_p = size of DCF in u8 -> for future use // DcfType_p = type of the DCF // // Returns: tCopKernel = error code //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplCfgMaStartConfigNodeDcf(unsigned int uiNodeId_p, - BYTE * pbConcise_p, - tfpEplCfgMaCb fpCfgMaCb_p, - tEplObdSize SizeOfConcise_p, - tEplCfgMaDcfTyp DcfType_p); +tEplKernel EplCfgMaStartConfigNodeDcf(unsigned int uiNodeId_p, + u8 * pbConcise_p, + tfpEplCfgMaCb fpCfgMaCb_p, + tEplObdSize SizeOfConcise_p, + tEplCfgMaDcfTyp DcfType_p); //--------------------------------------------------------------------------- // Function: EplCfgMaLinkDcf() @@ -253,15 +246,15 @@ tEplKernel PUBLIC EplCfgMaStartConfigNodeDcf(unsigned int uiNodeId_p, // // Parameters: uiNodeId_p = NodeId of the node to configure // pbConcise_p = pointer to DCF -// SizeOfConcise_p = size of DCF in BYTE -> for future use +// SizeOfConcise_p = size of DCF in u8 -> for future use // DcfType_p = type of the DCF // // Returns: tCopKernel = error code //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplCfgMaLinkDcf(unsigned int uiNodeId_p, - BYTE * pbConcise_p, - tEplObdSize SizeOfConcise_p, - tEplCfgMaDcfTyp DcfType_p); +tEplKernel EplCfgMaLinkDcf(unsigned int uiNodeId_p, + u8 * pbConcise_p, + tEplObdSize SizeOfConcise_p, + tEplCfgMaDcfTyp DcfType_p); //--------------------------------------------------------------------------- // Function: EplCfgMaCheckDcf() @@ -274,8 +267,7 @@ tEplKernel PUBLIC EplCfgMaLinkDcf(unsigned int uiNodeId_p, // // Returns: tCopKernel = error code //--------------------------------------------------------------------------- -tEplKernel PUBLIC EplCfgMaCheckDcf(unsigned int uiNodeId_p, - tEplCfgMaDcfTyp DcfType_p); +tEplKernel EplCfgMaCheckDcf(unsigned int uiNodeId_p, tEplCfgMaDcfTyp DcfType_p); #endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_CFGMA)) != 0) diff --git a/drivers/staging/epl/user/EplDllu.h b/drivers/staging/epl/user/EplDllu.h index 36f8bb76f7ca..890f83759ca9 100644 --- a/drivers/staging/epl/user/EplDllu.h +++ b/drivers/staging/epl/user/EplDllu.h @@ -73,19 +73,7 @@ #include "../EplDll.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -typedef tEplKernel(PUBLIC * tEplDlluCbAsnd) (tEplFrameInfo * pFrameInfo_p); - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- +typedef tEplKernel(* tEplDlluCbAsnd) (tEplFrameInfo * pFrameInfo_p); #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0) diff --git a/drivers/staging/epl/user/EplDlluCal.h b/drivers/staging/epl/user/EplDlluCal.h index b1dcd0609573..bc9126b1627a 100644 --- a/drivers/staging/epl/user/EplDlluCal.h +++ b/drivers/staging/epl/user/EplDlluCal.h @@ -74,19 +74,8 @@ #include "../EplDll.h" #include "../EplEvent.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -typedef tEplKernel(PUBLIC * tEplDlluCbAsnd) (tEplFrameInfo * pFrameInfo_p); - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- +typedef tEplKernel(* tEplDlluCbAsnd) (tEplFrameInfo * pFrameInfo_p); tEplKernel EplDlluCalAddInstance(void); @@ -110,7 +99,7 @@ tEplKernel EplDlluCalDeleteNode(unsigned int uiNodeId_p); tEplKernel EplDlluCalSoftDeleteNode(unsigned int uiNodeId_p); tEplKernel EplDlluCalIssueRequest(tEplDllReqServiceId Service_p, - unsigned int uiNodeId_p, BYTE bSoaFlag1_p); + unsigned int uiNodeId_p, u8 bSoaFlag1_p); #endif diff --git a/drivers/staging/epl/user/EplEventu.h b/drivers/staging/epl/user/EplEventu.h index 322cffd11874..ab85205b2397 100644 --- a/drivers/staging/epl/user/EplEventu.h +++ b/drivers/staging/epl/user/EplEventu.h @@ -73,36 +73,24 @@ #include "../EplEvent.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- // init function -tEplKernel PUBLIC EplEventuInit(tEplProcessEventCb pfnApiProcessEventCb_p); +tEplKernel EplEventuInit(tEplProcessEventCb pfnApiProcessEventCb_p); // add instance -tEplKernel PUBLIC EplEventuAddInstance(tEplProcessEventCb - pfnApiProcessEventCb_p); +tEplKernel EplEventuAddInstance(tEplProcessEventCb pfnApiProcessEventCb_p); // delete instance -tEplKernel PUBLIC EplEventuDelInstance(void); +tEplKernel EplEventuDelInstance(void); // Task that dispatches events in userspace -tEplKernel PUBLIC EplEventuProcess(tEplEvent * pEvent_p); +tEplKernel EplEventuProcess(tEplEvent * pEvent_p); // post events from userspace -tEplKernel PUBLIC EplEventuPost(tEplEvent * pEvent_p); +tEplKernel EplEventuPost(tEplEvent * pEvent_p); // post errorevents from userspace -tEplKernel PUBLIC EplEventuPostError(tEplEventSource EventSource_p, - tEplKernel EplError_p, - unsigned int uiArgSize_p, void *pArg_p); +tEplKernel EplEventuPostError(tEplEventSource EventSource_p, + tEplKernel EplError_p, + unsigned int uiArgSize_p, void *pArg_p); #endif // #ifndef _EPL_EVENTU_H_ diff --git a/drivers/staging/epl/user/EplIdentu.h b/drivers/staging/epl/user/EplIdentu.h index e7302106c741..057c9029e988 100644 --- a/drivers/staging/epl/user/EplIdentu.h +++ b/drivers/staging/epl/user/EplIdentu.h @@ -68,41 +68,27 @@ ****************************************************************************/ -#include "../EplDll.h" - #ifndef _EPLIDENTU_H_ #define _EPLIDENTU_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "../EplDll.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -typedef tEplKernel(PUBLIC * tEplIdentuCbResponse) (unsigned int uiNodeId_p, +typedef tEplKernel(* tEplIdentuCbResponse) (unsigned int uiNodeId_p, tEplIdentResponse * pIdentResponse_p); -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- +tEplKernel EplIdentuInit(void); -tEplKernel PUBLIC EplIdentuInit(void); +tEplKernel EplIdentuAddInstance(void); -tEplKernel PUBLIC EplIdentuAddInstance(void); +tEplKernel EplIdentuDelInstance(void); -tEplKernel PUBLIC EplIdentuDelInstance(void); +tEplKernel EplIdentuReset(void); -tEplKernel PUBLIC EplIdentuReset(void); +tEplKernel EplIdentuGetIdentResponse(unsigned int uiNodeId_p, + tEplIdentResponse **ppIdentResponse_p); -tEplKernel PUBLIC EplIdentuGetIdentResponse(unsigned int uiNodeId_p, - tEplIdentResponse ** - ppIdentResponse_p); - -tEplKernel PUBLIC EplIdentuRequestIdentResponse(unsigned int uiNodeId_p, - tEplIdentuCbResponse - pfnCbResponse_p); +tEplKernel EplIdentuRequestIdentResponse(unsigned int uiNodeId_p, + tEplIdentuCbResponse pfnCbResponse_p); #endif // #ifndef _EPLIDENTU_H_ diff --git a/drivers/staging/epl/user/EplLedu.h b/drivers/staging/epl/user/EplLedu.h index 78e70d064459..ca9eb431100d 100644 --- a/drivers/staging/epl/user/EplLedu.h +++ b/drivers/staging/epl/user/EplLedu.h @@ -68,41 +68,27 @@ ****************************************************************************/ +#ifndef _EPLLEDU_H_ +#define _EPLLEDU_H_ + #include "../EplLed.h" #include "../EplNmt.h" #include "EplEventu.h" -#ifndef _EPLLEDU_H_ -#define _EPLLEDU_H_ - -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -typedef tEplKernel(PUBLIC * tEplLeduStateChangeCallback) (tEplLedType LedType_p, +typedef tEplKernel(* tEplLeduStateChangeCallback) (tEplLedType LedType_p, BOOL fOn_p); -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) -tEplKernel PUBLIC EplLeduInit(tEplLeduStateChangeCallback pfnCbStateChange_p); +tEplKernel EplLeduInit(tEplLeduStateChangeCallback pfnCbStateChange_p); -tEplKernel PUBLIC EplLeduAddInstance(tEplLeduStateChangeCallback - pfnCbStateChange_p); +tEplKernel EplLeduAddInstance(tEplLeduStateChangeCallback pfnCbStateChange_p); -tEplKernel PUBLIC EplLeduDelInstance(void); +tEplKernel EplLeduDelInstance(void); -tEplKernel PUBLIC EplLeduCbNmtStateChange(tEplEventNmtStateChange - NmtStateChange_p); +tEplKernel EplLeduCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p); -tEplKernel PUBLIC EplLeduProcessEvent(tEplEvent * pEplEvent_p); +tEplKernel EplLeduProcessEvent(tEplEvent * pEplEvent_p); #endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0) diff --git a/drivers/staging/epl/user/EplNmtCnu.h b/drivers/staging/epl/user/EplNmtCnu.h index e508055b5b8f..7d230297f43c 100644 --- a/drivers/staging/epl/user/EplNmtCnu.h +++ b/drivers/staging/epl/user/EplNmtCnu.h @@ -68,40 +68,24 @@ ****************************************************************************/ +#ifndef _EPLNMTCNU_H_ +#define _EPLNMTCNU_H_ + #include "EplNmtu.h" #include "../EplDll.h" #include "../EplFrame.h" -#ifndef _EPLNMTCNU_H_ -#define _EPLNMTCNU_H_ - -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) -EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuInit(unsigned int uiNodeId_p); +tEplKernel EplNmtCnuInit(unsigned int uiNodeId_p); -EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuAddInstance(unsigned int uiNodeId_p); +tEplKernel EplNmtCnuAddInstance(unsigned int uiNodeId_p); -EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuDelInstance(void); +tEplKernel EplNmtCnuDelInstance(void); -EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuSendNmtRequest(unsigned int uiNodeId_p, - tEplNmtCommand - NmtCommand_p); +tEplKernel EplNmtCnuSendNmtRequest(unsigned int uiNodeId_p, tEplNmtCommand NmtCommand_p); -EPLDLLEXPORT tEplKernel PUBLIC -EplNmtCnuRegisterCheckEventCb(tEplNmtuCheckEventCallback - pfnEplNmtCheckEventCb_p); +tEplKernel EplNmtCnuRegisterCheckEventCb(tEplNmtuCheckEventCallback pfnEplNmtCheckEventCb_p); #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0) diff --git a/drivers/staging/epl/user/EplNmtMnu.h b/drivers/staging/epl/user/EplNmtMnu.h index c54efeba303f..5e5e0cda3246 100644 --- a/drivers/staging/epl/user/EplNmtMnu.h +++ b/drivers/staging/epl/user/EplNmtMnu.h @@ -68,34 +68,20 @@ ****************************************************************************/ -#include "EplNmtu.h" - #ifndef _EPLNMTMNU_H_ #define _EPLNMTMNU_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "EplNmtu.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- +typedef tEplKernel(* tEplNmtMnuCbNodeEvent) (unsigned int uiNodeId_p, + tEplNmtNodeEvent NodeEvent_p, + tEplNmtState NmtState_p, + u16 wErrorCode_p, + BOOL fMandatory_p); -typedef tEplKernel(PUBLIC * tEplNmtMnuCbNodeEvent) (unsigned int uiNodeId_p, - tEplNmtNodeEvent - NodeEvent_p, - tEplNmtState NmtState_p, - WORD wErrorCode_p, - BOOL fMandatory_p); - -typedef tEplKernel(PUBLIC * - tEplNmtMnuCbBootEvent) (tEplNmtBootEvent BootEvent_p, - tEplNmtState NmtState_p, - WORD wErrorCode_p); - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- +typedef tEplKernel(* tEplNmtMnuCbBootEvent) (tEplNmtBootEvent BootEvent_p, + tEplNmtState NmtState_p, + u16 wErrorCode_p); #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) @@ -107,7 +93,7 @@ tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p, tEplKernel EplNmtMnuDelInstance(void); -EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent(tEplEvent * pEvent_p); +tEplKernel EplNmtMnuProcessEvent(tEplEvent *pEvent_p); tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p, tEplNmtCommand NmtCommand_p); @@ -115,16 +101,16 @@ tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p, tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p, tEplNmtNodeCommand NodeCommand_p); -tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange +tEplKernel EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p); -tEplKernel PUBLIC EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p); +tEplKernel EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p); -tEplKernel PUBLIC EplNmtMnuGetDiagnosticInfo(unsigned int +tEplKernel EplNmtMnuGetDiagnosticInfo(unsigned int *puiMandatorySlaveCount_p, unsigned int *puiSignalSlaveCount_p, - WORD * pwFlags_p); + u16 * pwFlags_p); #endif diff --git a/drivers/staging/epl/user/EplNmtu.h b/drivers/staging/epl/user/EplNmtu.h index 5a56c5830603..c1fca80f5a06 100644 --- a/drivers/staging/epl/user/EplNmtu.h +++ b/drivers/staging/epl/user/EplNmtu.h @@ -68,19 +68,12 @@ ****************************************************************************/ -#include "../EplNmt.h" -#include "EplEventu.h" - #ifndef _EPLNMTU_H_ #define _EPLNMTU_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "../EplNmt.h" +#include "EplEventu.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- // nmt commands typedef enum { // requestable ASnd ServiceIds 0x01..0x1F @@ -121,34 +114,25 @@ typedef enum { kEplNmtCmdInvalidService = 0xFF } tEplNmtCommand; -typedef tEplKernel(PUBLIC * - tEplNmtuStateChangeCallback) (tEplEventNmtStateChange - NmtStateChange_p); +typedef tEplKernel(* tEplNmtuStateChangeCallback) (tEplEventNmtStateChange NmtStateChange_p); -typedef tEplKernel(PUBLIC * - tEplNmtuCheckEventCallback) (tEplNmtEvent NmtEvent_p); - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- +typedef tEplKernel(* tEplNmtuCheckEventCallback) (tEplNmtEvent NmtEvent_p); #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuInit(void); +tEplKernel EplNmtuInit(void); -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuAddInstance(void); +tEplKernel EplNmtuAddInstance(void); -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuDelInstance(void); +tEplKernel EplNmtuDelInstance(void); -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p); +tEplKernel EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p); -EPLDLLEXPORT tEplNmtState PUBLIC EplNmtuGetNmtState(void); +tEplNmtState EplNmtuGetNmtState(void); -EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p); +tEplKernel EplNmtuProcessEvent(tEplEvent *pEplEvent_p); -EPLDLLEXPORT tEplKernel PUBLIC -EplNmtuRegisterStateChangeCb(tEplNmtuStateChangeCallback - pfnEplNmtStateChangeCb_p); +tEplKernel EplNmtuRegisterStateChangeCb(tEplNmtuStateChangeCallback pfnEplNmtStateChangeCb_p); #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0) diff --git a/drivers/staging/epl/user/EplNmtuCal.h b/drivers/staging/epl/user/EplNmtuCal.h index c881582702bb..b9850372a4a6 100644 --- a/drivers/staging/epl/user/EplNmtuCal.h +++ b/drivers/staging/epl/user/EplNmtuCal.h @@ -69,23 +69,12 @@ ****************************************************************************/ -#include "EplNmtu.h" -#include "../kernel/EplNmtk.h" - #ifndef _EPLNMTUCAL_H_ #define _EPLNMTUCAL_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "EplNmtu.h" +#include "../kernel/EplNmtk.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- -EPLDLLEXPORT tEplNmtState PUBLIC EplNmtkCalGetNmtState(void); +tEplNmtState EplNmtkCalGetNmtState(void); #endif // #ifndef _EPLNMTUCAL_H_ diff --git a/drivers/staging/epl/user/EplObdu.h b/drivers/staging/epl/user/EplObdu.h index bc1e17303017..086371276cf6 100644 --- a/drivers/staging/epl/user/EplObdu.h +++ b/drivers/staging/epl/user/EplObdu.h @@ -68,22 +68,10 @@ ****************************************************************************/ -#include "../EplObd.h" - #ifndef _EPLOBDU_H_ #define _EPLOBDU_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- +#include "../EplObd.h" #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) @@ -91,68 +79,57 @@ #error "EPL OBDu module enabled, but OBD_USE_KERNEL == TRUE" #endif -EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntry(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p); +tEplKernel EplObduWriteEntry(unsigned int uiIndex_p, unsigned int uiSubIndex_p, + void *pSrcData_p, tEplObdSize Size_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntry(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p); +tEplKernel EplObduReadEntry(unsigned int uiIndex_p, unsigned int uiSubIndex_p, + void *pDstData_p, tEplObdSize *pSize_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduAccessOdPart(tEplObdPart ObdPart_p, - tEplObdDir Direction_p); +tEplKernel EplObduAccessOdPart(tEplObdPart ObdPart_p, tEplObdDir Direction_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduDefineVar(tEplVarParam MEM * pVarParam_p); +tEplKernel EplObduDefineVar(tEplVarParam *pVarParam_p); // --------------------------------------------------------------------- -EPLDLLEXPORT void *PUBLIC EplObduGetObjectDataPtr(unsigned int uiIndex_p, - unsigned int uiSubIndex_p); -// --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduRegisterUserOd(tEplObdEntryPtr pUserOd_p); +void *EplObduGetObjectDataPtr(unsigned int uiIndex_p, unsigned int uiSubIndex_p); // --------------------------------------------------------------------- -EPLDLLEXPORT void PUBLIC EplObduInitVarEntry(tEplObdVarEntry MEM * pVarEntry_p, - BYTE bType_p, - tEplObdSize ObdSize_p); +tEplKernel EplObduRegisterUserOd(tEplObdEntryPtr pUserOd_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplObdSize PUBLIC EplObduGetDataSize(unsigned int uiIndex_p, - unsigned int uiSubIndex_p); +void EplObduInitVarEntry(tEplObdVarEntry *pVarEntry_p, u8 bType_p, + tEplObdSize ObdSize_p); // --------------------------------------------------------------------- -EPLDLLEXPORT unsigned int PUBLIC EplObduGetNodeId(void); +tEplObdSize EplObduGetDataSize(unsigned int uiIndex_p, + unsigned int uiSubIndex_p); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduSetNodeId(unsigned int uiNodeId_p, - tEplObdNodeIdType NodeIdType_p); -// --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduGetAccessType(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - tEplObdAccess * - pAccessTyp_p); -// --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntryToLe(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p); -// --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntryFromLe(unsigned int uiIndex_p, - unsigned int - uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p); +unsigned int EplObduGetNodeId(void); // --------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ - unsigned int uiIndex_p, - unsigned int uiSubindex_p, - tEplObdVarEntry MEM ** - ppVarEntry_p); +tEplKernel EplObduSetNodeId(unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p); + +// --------------------------------------------------------------------- +tEplKernel EplObduGetAccessType(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess *pAccessTyp_p); +// --------------------------------------------------------------------- +tEplKernel EplObduReadEntryToLe(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, tEplObdSize *pSize_p); +// --------------------------------------------------------------------- +tEplKernel EplObduWriteEntryFromLe(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, tEplObdSize Size_p); + +// --------------------------------------------------------------------- +tEplKernel EplObduSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry **ppVarEntry_p); #elif EPL_OBD_USE_KERNEL != FALSE #include "../kernel/EplObdk.h" diff --git a/drivers/staging/epl/user/EplObduCal.h b/drivers/staging/epl/user/EplObduCal.h index 498e0112fac3..07277777219d 100644 --- a/drivers/staging/epl/user/EplObduCal.h +++ b/drivers/staging/epl/user/EplObduCal.h @@ -69,80 +69,58 @@ ****************************************************************************/ -#include "../EplObd.h" - #ifndef _EPLOBDUCAL_H_ #define _EPLOBDUCAL_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "../EplObd.h" +tEplKernel EplObduCalWriteEntry(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, + tEplObdSize Size_p); //--------------------------------------------------------------------------- -// typedef +tEplKernel EplObduCalReadEntry(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, + tEplObdSize *pSize_p); //--------------------------------------------------------------------------- - +tEplKernel EplObduCalAccessOdPart(tEplObdPart ObdPart_p, + tEplObdDir Direction_p); //--------------------------------------------------------------------------- -// function prototypes +tEplKernel EplObduCalDefineVar(tEplVarParam *pVarParam_p); //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntry(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p); +void *EplObduCalGetObjectDataPtr(unsigned int uiIndex_p, + unsigned int uiSubIndex_p); //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntry(unsigned int uiIndex_p, - unsigned int uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p); +tEplKernel EplObduCalRegisterUserOd(tEplObdEntryPtr pUserOd_p); //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalAccessOdPart(tEplObdPart ObdPart_p, - tEplObdDir Direction_p); +void EplObduCalInitVarEntry(tEplObdVarEntry *pVarEntry_p, + u8 bType_p, tEplObdSize ObdSize_p); //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalDefineVar(tEplVarParam MEM * - pVarParam_p); +tEplObdSize EplObduCalGetDataSize(unsigned int uiIndex_p, + unsigned int uiSubIndex_p); //--------------------------------------------------------------------------- -EPLDLLEXPORT void *PUBLIC EplObduCalGetObjectDataPtr(unsigned int uiIndex_p, - unsigned int uiSubIndex_p); +unsigned int EplObduCalGetNodeId(void); //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalRegisterUserOd(tEplObdEntryPtr - pUserOd_p); +tEplKernel EplObduCalSetNodeId(unsigned int uiNodeId_p, + tEplObdNodeIdType NodeIdType_p); //--------------------------------------------------------------------------- -EPLDLLEXPORT void PUBLIC EplObduCalInitVarEntry(tEplObdVarEntry MEM * - pVarEntry_p, BYTE bType_p, - tEplObdSize ObdSize_p); +tEplKernel EplObduCalGetAccessType(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + tEplObdAccess *pAccessTyp_p); //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplObdSize PUBLIC EplObduCalGetDataSize(unsigned int uiIndex_p, - unsigned int - uiSubIndex_p); +tEplKernel EplObduCalReadEntryToLe(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pDstData_p, + tEplObdSize *pSize_p); //--------------------------------------------------------------------------- -EPLDLLEXPORT unsigned int PUBLIC EplObduCalGetNodeId(void); +tEplKernel EplObduCalWriteEntryFromLe(unsigned int uiIndex_p, + unsigned int uiSubIndex_p, + void *pSrcData_p, + tEplObdSize Size_p); //--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalSetNodeId(unsigned int uiNodeId_p, - tEplObdNodeIdType - NodeIdType_p); -//--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalGetAccessType(unsigned int uiIndex_p, - unsigned int - uiSubIndex_p, - tEplObdAccess * - pAccessTyp_p); -//--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntryToLe(unsigned int uiIndex_p, - unsigned int - uiSubIndex_p, - void *pDstData_p, - tEplObdSize * pSize_p); -//--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntryFromLe(unsigned int - uiIndex_p, - unsigned int - uiSubIndex_p, - void *pSrcData_p, - tEplObdSize Size_p); -//--------------------------------------------------------------------------- -EPLDLLEXPORT tEplKernel PUBLIC -EplObduCalSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, - unsigned int uiSubindex_p, - tEplObdVarEntry MEM ** ppVarEntry_p); +tEplKernel EplObduCalSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p, + unsigned int uiSubindex_p, + tEplObdVarEntry **ppVarEntry_p); #endif // #ifndef _EPLOBDUCAL_H_ diff --git a/drivers/staging/epl/user/EplPdou.h b/drivers/staging/epl/user/EplPdou.h index 11de4862e8bb..b8c832b09dbf 100644 --- a/drivers/staging/epl/user/EplPdou.h +++ b/drivers/staging/epl/user/EplPdou.h @@ -72,24 +72,12 @@ #include "../EplPdo.h" -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- - tEplKernel EplPdouAddInstance(void); tEplKernel EplPdouDelInstance(void); #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0) -tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p); +tEplKernel EplPdouCbObdAccess(tEplObdCbParam *pParam_p); #else #define EplPdouCbObdAccess NULL #endif @@ -97,12 +85,12 @@ tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p); // returns error if bPdoId_p is already valid /* tEplKernel EplPdouSetMapping( - BYTE bPdoId_p, BOOL fTxRx_p, BYTE bNodeId, BYTE bMappingVersion, - tEplPdoMapping * pMapping_p, BYTE bMaxEntries_p); + u8 bPdoId_p, BOOL fTxRx_p, u8 bNodeId, u8 bMappingVersion, + tEplPdoMapping * pMapping_p, u8 bMaxEntries_p); tEplKernel EplPdouGetMapping( - BYTE bPdoId_p, BOOL fTxRx_p, BYTE * pbNodeId, BYTE * pbMappingVersion, - tEplPdoMapping * pMapping_p, BYTE * pbMaxEntries_p); + u8 bPdoId_p, BOOL fTxRx_p, u8 * pbNodeId, u8 * pbMappingVersion, + tEplPdoMapping * pMapping_p, u8 * pbMaxEntries_p); */ #endif // #ifndef _EPL_PDOU_H_ diff --git a/drivers/staging/epl/user/EplSdoAsndu.h b/drivers/staging/epl/user/EplSdoAsndu.h index e34959f42792..a62d4c97870f 100644 --- a/drivers/staging/epl/user/EplSdoAsndu.h +++ b/drivers/staging/epl/user/EplSdoAsndu.h @@ -68,39 +68,28 @@ ****************************************************************************/ -#include "../EplSdo.h" -#include "../EplDll.h" - #ifndef _EPLSDOASNDU_H_ #define _EPLSDOASNDU_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "../EplSdo.h" +#include "../EplDll.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) -tEplKernel PUBLIC EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p); +tEplKernel EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p); -tEplKernel PUBLIC EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p); +tEplKernel EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p); -tEplKernel PUBLIC EplSdoAsnduDelInstance(void); +tEplKernel EplSdoAsnduDelInstance(void); -tEplKernel PUBLIC EplSdoAsnduInitCon(tEplSdoConHdl * pSdoConHandle_p, - unsigned int uiTargetNodeId_p); +tEplKernel EplSdoAsnduInitCon(tEplSdoConHdl *pSdoConHandle_p, + unsigned int uiTargetNodeId_p); -tEplKernel PUBLIC EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p, - tEplFrame * pSrcData_p, - DWORD dwDataSize_p); +tEplKernel EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p, + tEplFrame *pSrcData_p, + u32 dwDataSize_p); -tEplKernel PUBLIC EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p); +tEplKernel EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p); #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0) diff --git a/drivers/staging/epl/user/EplSdoAsySequ.h b/drivers/staging/epl/user/EplSdoAsySequ.h index 4658b5f8c538..cc862de1a5b3 100644 --- a/drivers/staging/epl/user/EplSdoAsySequ.h +++ b/drivers/staging/epl/user/EplSdoAsySequ.h @@ -68,44 +68,33 @@ ****************************************************************************/ +#ifndef _EPLSDOASYSEQU_H_ +#define _EPLSDOASYSEQU_H_ + #include "../EplSdo.h" #include "EplSdoUdpu.h" #include "EplSdoAsndu.h" #include "../EplEvent.h" #include "EplTimeru.h" -#ifndef _EPLSDOASYSEQU_H_ -#define _EPLSDOASYSEQU_H_ +tEplKernel EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p, + tEplSdoComConCb fpSdoComConCb_p); -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p, +tEplKernel EplSdoAsySeqAddInstance(tEplSdoComReceiveCb fpSdoComCb_p, tEplSdoComConCb fpSdoComConCb_p); -tEplKernel PUBLIC EplSdoAsySeqAddInstance(tEplSdoComReceiveCb fpSdoComCb_p, - tEplSdoComConCb fpSdoComConCb_p); +tEplKernel EplSdoAsySeqDelInstance(void); -tEplKernel PUBLIC EplSdoAsySeqDelInstance(void); +tEplKernel EplSdoAsySeqInitCon(tEplSdoSeqConHdl *pSdoSeqConHdl_p, + unsigned int uiNodeId_p, + tEplSdoType SdoType); -tEplKernel PUBLIC EplSdoAsySeqInitCon(tEplSdoSeqConHdl * pSdoSeqConHdl_p, - unsigned int uiNodeId_p, - tEplSdoType SdoType); +tEplKernel EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p, + unsigned int uiDataSize_p, + tEplFrame *pData_p); -tEplKernel PUBLIC EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p, - unsigned int uiDataSize_p, - tEplFrame * pData_p); +tEplKernel EplSdoAsySeqProcessEvent(tEplEvent *pEvent_p); -tEplKernel PUBLIC EplSdoAsySeqProcessEvent(tEplEvent * pEvent_p); - -tEplKernel PUBLIC EplSdoAsySeqDelCon(tEplSdoSeqConHdl SdoSeqConHdl_p); +tEplKernel EplSdoAsySeqDelCon(tEplSdoSeqConHdl SdoSeqConHdl_p); #endif // #ifndef _EPLSDOASYSEQU_H_ diff --git a/drivers/staging/epl/user/EplSdoComu.h b/drivers/staging/epl/user/EplSdoComu.h index 3e454c7a3559..4eee6fa69747 100644 --- a/drivers/staging/epl/user/EplSdoComu.h +++ b/drivers/staging/epl/user/EplSdoComu.h @@ -68,58 +68,46 @@ ****************************************************************************/ +#ifndef _EPLSDOCOMU_H_ +#define _EPLSDOCOMU_H_ + #include "../EplSdo.h" #include "../EplObd.h" #include "../EplSdoAc.h" #include "EplObdu.h" #include "EplSdoAsySequ.h" -#ifndef _EPLSDOCOMU_H_ -#define _EPLSDOCOMU_H_ +tEplKernel EplSdoComInit(void); -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +tEplKernel EplSdoComAddInstance(void); -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- -tEplKernel PUBLIC EplSdoComInit(void); - -tEplKernel PUBLIC EplSdoComAddInstance(void); - -tEplKernel PUBLIC EplSdoComDelInstance(void); +tEplKernel EplSdoComDelInstance(void); #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) -tEplKernel PUBLIC EplSdoComDefineCon(tEplSdoComConHdl * pSdoComConHdl_p, - unsigned int uiTargetNodeId_p, - tEplSdoType ProtType_p); +tEplKernel EplSdoComDefineCon(tEplSdoComConHdl *pSdoComConHdl_p, + unsigned int uiTargetNodeId_p, + tEplSdoType ProtType_p); -tEplKernel PUBLIC EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex * - pSdoComTransParam_p); +tEplKernel EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex *pSdoComTransParam_p); -tEplKernel PUBLIC EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p); +tEplKernel EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p); -tEplKernel PUBLIC EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p, - tEplSdoComFinished * pSdoComFinished_p); +tEplKernel EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p, + tEplSdoComFinished *pSdoComFinished_p); -tEplKernel PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, - DWORD dwAbortCode_p); +tEplKernel EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, + u32 dwAbortCode_p); #endif // for future extention /* -tEplKernel PUBLIC EplSdoComInitTransferAllByIndex(tEplSdoComTransParamAllByIndex* pSdoComTransParam_p); +tEplKernel EplSdoComInitTransferAllByIndex(tEplSdoComTransParamAllByIndex* pSdoComTransParam_p); -tEplKernel PUBLIC EplSdoComInitTransferByName(tEplSdoComTransParamByName* pSdoComTransParam_p); +tEplKernel EplSdoComInitTransferByName(tEplSdoComTransParamByName* pSdoComTransParam_p); -tEplKernel PUBLIC EplSdoComInitTransferFile(tEplSdoComTransParamFile* pSdoComTransParam_p); +tEplKernel EplSdoComInitTransferFile(tEplSdoComTransParamFile* pSdoComTransParam_p); */ diff --git a/drivers/staging/epl/user/EplSdoUdpu.h b/drivers/staging/epl/user/EplSdoUdpu.h index 2d77b6fff199..13e2a278c11b 100644 --- a/drivers/staging/epl/user/EplSdoUdpu.h +++ b/drivers/staging/epl/user/EplSdoUdpu.h @@ -68,41 +68,29 @@ ****************************************************************************/ -#include "../EplSdo.h" - #ifndef _EPLSDOUDPU_H_ #define _EPLSDOUDPU_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "../EplSdo.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) -tEplKernel PUBLIC EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p); +tEplKernel EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p); -tEplKernel PUBLIC EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p); +tEplKernel EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p); -tEplKernel PUBLIC EplSdoUdpuDelInstance(void); +tEplKernel EplSdoUdpuDelInstance(void); -tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p, - unsigned int uiPort_p); +tEplKernel EplSdoUdpuConfig(unsigned long ulIpAddr_p, + unsigned int uiPort_p); -tEplKernel PUBLIC EplSdoUdpuInitCon(tEplSdoConHdl * pSdoConHandle_p, - unsigned int uiTargetNodeId_p); +tEplKernel EplSdoUdpuInitCon(tEplSdoConHdl *pSdoConHandle_p, + unsigned int uiTargetNodeId_p); -tEplKernel PUBLIC EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p, - tEplFrame * pSrcData_p, - DWORD dwDataSize_p); +tEplKernel EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p, + tEplFrame *pSrcData_p, u32 dwDataSize_p); -tEplKernel PUBLIC EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p); +tEplKernel EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p); #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0) diff --git a/drivers/staging/epl/user/EplStatusu.h b/drivers/staging/epl/user/EplStatusu.h index d211935f0e83..0fd3ebb76dcb 100644 --- a/drivers/staging/epl/user/EplStatusu.h +++ b/drivers/staging/epl/user/EplStatusu.h @@ -68,37 +68,23 @@ ****************************************************************************/ -#include "../EplDll.h" - #ifndef _EPLSTATUSU_H_ #define _EPLSTATUSU_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "../EplDll.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- +typedef tEplKernel(* tEplStatusuCbResponse) (unsigned int uiNodeId_p, + tEplStatusResponse *pStatusResponse_p); -typedef tEplKernel(PUBLIC * tEplStatusuCbResponse) (unsigned int uiNodeId_p, - tEplStatusResponse * - pStatusResponse_p); +tEplKernel EplStatusuInit(void); -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- +tEplKernel EplStatusuAddInstance(void); -tEplKernel PUBLIC EplStatusuInit(void); +tEplKernel EplStatusuDelInstance(void); -tEplKernel PUBLIC EplStatusuAddInstance(void); +tEplKernel EplStatusuReset(void); -tEplKernel PUBLIC EplStatusuDelInstance(void); - -tEplKernel PUBLIC EplStatusuReset(void); - -tEplKernel PUBLIC EplStatusuRequestStatusResponse(unsigned int uiNodeId_p, - tEplStatusuCbResponse - pfnCbResponse_p); +tEplKernel EplStatusuRequestStatusResponse(unsigned int uiNodeId_p, + tEplStatusuCbResponse pfnCbResponse_p); #endif // #ifndef _EPLSTATUSU_H_ diff --git a/drivers/staging/epl/user/EplTimeru.h b/drivers/staging/epl/user/EplTimeru.h index 404495501b8d..5c447485245c 100644 --- a/drivers/staging/epl/user/EplTimeru.h +++ b/drivers/staging/epl/user/EplTimeru.h @@ -68,40 +68,28 @@ ****************************************************************************/ -#include "../EplTimer.h" -#include "EplEventu.h" - #ifndef _EPLTIMERU_H_ #define _EPLTIMERU_H_ -//--------------------------------------------------------------------------- -// const defines -//--------------------------------------------------------------------------- +#include "../EplTimer.h" +#include "EplEventu.h" -//--------------------------------------------------------------------------- -// typedef -//--------------------------------------------------------------------------- +tEplKernel EplTimeruInit(void); -//--------------------------------------------------------------------------- -// function prototypes -//--------------------------------------------------------------------------- +tEplKernel EplTimeruAddInstance(void); -tEplKernel PUBLIC EplTimeruInit(void); +tEplKernel EplTimeruDelInstance(void); -tEplKernel PUBLIC EplTimeruAddInstance(void); +tEplKernel EplTimeruSetTimerMs(tEplTimerHdl *pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p); -tEplKernel PUBLIC EplTimeruDelInstance(void); +tEplKernel EplTimeruModifyTimerMs(tEplTimerHdl *pTimerHdl_p, + unsigned long ulTime_p, + tEplTimerArg Argument_p); -tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p); +tEplKernel EplTimeruDeleteTimer(tEplTimerHdl *pTimerHdl_p); -tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p, - unsigned long ulTime_p, - tEplTimerArg Argument_p); - -tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p); - -BOOL PUBLIC EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p); +BOOL EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p); #endif // #ifndef _EPLTIMERU_H_ diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c index ec98da5da5bc..8dc559a77ad3 100644 --- a/drivers/staging/et131x/et1310_rx.c +++ b/drivers/staging/et131x/et1310_rx.c @@ -1203,8 +1203,7 @@ void et131x_reset_recv(struct et131x_adapter *pAdapter) pMpRfd = (PMP_RFD) list_entry(element, MP_RFD, list_node); - list_del(&pMpRfd->list_node); - list_add_tail(&pMpRfd->list_node, &pAdapter->RxRing.RecvList); + list_move_tail(&pMpRfd->list_node, &pAdapter->RxRing.RecvList); } DBG_LEAVE(et131x_dbginfo); diff --git a/drivers/staging/frontier/README b/drivers/staging/frontier/README index 07c9ef9b8fc4..cd07af22406a 100644 --- a/drivers/staging/frontier/README +++ b/drivers/staging/frontier/README @@ -1,28 +1,47 @@ -This directory contains the USB Tranzport and Alphatrack Kernel drivers for Linux. +This directory contains the Linux USB Tranzport and Alphatrack Kernel drivers. -At present the tranzport does reads/writes of 8 byte cmds to /dev/tranzport0 to control -the lights and screen and wheel +See http://www.frontierdesign.com for details on these devices. -At present the alphatrack accepts reads/writes of 12 byte cmds to /dev/tranzport0 to control -the lights and screen and fader. +Userspace test code is available from -Both drivers also have some sysfs hooks that are non-functional at the moment. +git://toutatis.isc.org/home/d/src/git/frontier.git -The API is currently closely tied to the ardour revision and WILL change. +At present the tranzport does reads/writes of 8 byte cmds to +/dev/tranzport0 to control the lights, screen, and wheel. -A sysfs interface is PERFECT for simple userspace apps to do fun things with the -lights and screen. It's fairly lousy for handling input events and very lousy -for watching the state of the shuttle wheel. +At present the alphatrack accepts reads/writes of 12 byte cmds to +/dev/tranzport0 to control the lights, screen, fader and touchpad. -A linux input events interface is great for the input events and shuttle wheel. It's -theoretically OK on LEDs. A Fader can be mapped to an absolute mouse device. -But there is no LCD support at all. +The tranzport driver provides a rudimentary sysfs interface for the status of +the device and a writable parameter for turning wheel compression on and off. -In the end this is going to be driven by a midi layer, which handles all those -cases via a defined API, but - among other things - is slow, doesn't do -flow control, and is a LOT of extra work. Frankly, I'd like to keep the +The API is nothing more than the USB commands issued to the device. Why? + +The control wheel/fader can generate events far too quickly for +a typical userspace application to keep up with them via libusb. Input +needs to be 100% accurate and fast in order for the alphatrack or tranzport +to be useful. + +UIO would be useful except that usb disconnect events need +to be handled correctly. + +A sysfs interface is perfect for simple userspace apps to do fun things with +the lights and screen. But it's fairly lousy for handling input events and +very lousy for watching the state of the shuttle wheel. + +A linux input events interface is great for the input events and shuttle wheel. +* It's theoretically OK on LEDs. +* A fader can be mapped to an absolute mouse device. +* But there is no LCD support at all, or fader feedback support in that API + +So, thus, these stubby drivers exist. + +In the end this could be driven by a midi layer, which handles all those +cases via a well defined API, but - among other things - is slow, doesn't do +flow control, and is a LOT of extra work, none of which is required at +the kernel level (probably). Frankly, I'd like to keep the core driver simple because the only realtime work really required is the bottom half interrupt handler and the output overlapping. -Exposing some sort of clean aio api to userspace would be perfect. What that +Exposing some sort of clean api to userspace would be perfect. What that API looks like? Gah. beats me. diff --git a/drivers/staging/frontier/alphatrack.c b/drivers/staging/frontier/alphatrack.c index 6136e3f8762d..bcba17eae926 100644 --- a/drivers/staging/frontier/alphatrack.c +++ b/drivers/staging/frontier/alphatrack.c @@ -41,19 +41,11 @@ #include #include -#include +#include #include #include #include -#include "surface_sysfs.h" - -/* make this work on older kernel versions */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -#include "frontier_compat.h" -#endif /* older kernel versions */ - #include "alphatrack.h" #define VENDOR_ID 0x165b @@ -62,19 +54,18 @@ #ifdef CONFIG_USB_DYNAMIC_MINORS #define USB_ALPHATRACK_MINOR_BASE 0 #else -// FIXME 176 - is another driver's minor - apply for that -// #define USB_ALPHATRACK_MINOR_BASE 177 +/* FIXME 176 - is another driver's minor - apply for that */ #define USB_ALPHATRACK_MINOR_BASE 176 #endif /* table of devices that work with this driver */ -static struct usb_device_id usb_alphatrack_table [] = { - { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, - { } /* Terminating entry */ +static struct usb_device_id usb_alphatrack_table[] = { + {USB_DEVICE(VENDOR_ID, PRODUCT_ID)}, + {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, usb_alphatrack_table); -MODULE_VERSION("0.40"); +MODULE_VERSION("0.41"); MODULE_AUTHOR("Mike Taht "); MODULE_DESCRIPTION("Alphatrack USB Driver"); MODULE_LICENSE("GPL"); @@ -93,18 +84,18 @@ MODULE_SUPPORTED_DEVICE("Frontier Designs Alphatrack Control Surface"); #define ALPHATRACK_USB_TIMEOUT 10 #define OUTPUT_CMD_SIZE 8 #define INPUT_CMD_SIZE 12 +#define ALPHATRACK_DEBUG 0 - -static int debug = 0; +static int debug = ALPHATRACK_DEBUG; /* Use our own dbg macro */ -#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) +#define dbg_info(dev, format, arg...) do \ + { if (debug) dev_info(dev , format , ## arg); } while (0) #define alphatrack_ocmd_info(dev, cmd, format, arg...) #define alphatrack_icmd_info(dev, cmd, format, arg...) - /* Module parameters */ module_param(debug, int, S_IRUGO | S_IWUSR); @@ -116,14 +107,14 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); static int ring_buffer_size = RING_BUFFER_SIZE; -module_param(ring_buffer_size, int, S_IRUGO); +module_param(ring_buffer_size, int, S_IRUGO); MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size"); /* The write_buffer can one day contain more than one interrupt out transfer. */ static int write_buffer_size = WRITE_BUFFER_SIZE; -module_param(write_buffer_size, int, S_IRUGO); +module_param(write_buffer_size, int, S_IRUGO); MODULE_PARM_DESC(write_buffer_size, "Write buffer size"); /* @@ -133,55 +124,56 @@ MODULE_PARM_DESC(write_buffer_size, "Write buffer size"); static int min_interrupt_in_interval = ALPHATRACK_USB_TIMEOUT; module_param(min_interrupt_in_interval, int, 0); -MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms"); +MODULE_PARM_DESC(min_interrupt_in_interval, + "Minimum interrupt in interval in ms"); static int min_interrupt_out_interval = ALPHATRACK_USB_TIMEOUT; module_param(min_interrupt_out_interval, int, 0); -MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms"); - - +MODULE_PARM_DESC(min_interrupt_out_interval, + "Minimum interrupt out interval in ms"); /* Structure to hold all of our device specific stuff */ struct usb_alphatrack { - struct semaphore sem; /* locks this structure */ - struct usb_interface* intf; /* save off the usb interface pointer */ - int open_count; /* number of times this port has been opened */ + struct semaphore sem; /* locks this structure */ + struct usb_interface *intf; /* save off the usb interface pointer */ + int open_count; /* number of times this port has been opened */ - struct alphatrack_icmd (*ring_buffer)[RING_BUFFER_SIZE]; /* just make c happy */ - struct alphatrack_ocmd (*write_buffer)[WRITE_BUFFER_SIZE]; /* just make c happy */ - unsigned int ring_head; - unsigned int ring_tail; + /* make gcc happy */ + struct alphatrack_icmd (*ring_buffer)[RING_BUFFER_SIZE]; + struct alphatrack_ocmd (*write_buffer)[WRITE_BUFFER_SIZE]; + unsigned int ring_head; + unsigned int ring_tail; - wait_queue_head_t read_wait; - wait_queue_head_t write_wait; + wait_queue_head_t read_wait; + wait_queue_head_t write_wait; - unsigned char* interrupt_in_buffer; - unsigned char* oldi_buffer; - struct usb_endpoint_descriptor* interrupt_in_endpoint; - struct urb* interrupt_in_urb; - int interrupt_in_interval; - size_t interrupt_in_endpoint_size; - int interrupt_in_running; - int interrupt_in_done; + unsigned char *interrupt_in_buffer; + unsigned char *oldi_buffer; + struct usb_endpoint_descriptor *interrupt_in_endpoint; + struct urb *interrupt_in_urb; + int interrupt_in_interval; + size_t interrupt_in_endpoint_size; + int interrupt_in_running; + int interrupt_in_done; - char* interrupt_out_buffer; - struct usb_endpoint_descriptor* interrupt_out_endpoint; - struct urb* interrupt_out_urb; - int interrupt_out_interval; - size_t interrupt_out_endpoint_size; - int interrupt_out_busy; + char *interrupt_out_buffer; + struct usb_endpoint_descriptor *interrupt_out_endpoint; + struct urb *interrupt_out_urb; + int interrupt_out_interval; + size_t interrupt_out_endpoint_size; + int interrupt_out_busy; atomic_t writes_pending; - int event; /* alternate interface to events */ - int fader; /* 10 bits */ - int lights; /* 23 bits */ - unsigned char dump_state; /* 0 if disabled 1 if enabled */ - unsigned char enable; /* 0 if disabled 1 if enabled */ - unsigned char offline; /* if the device is out of range or asleep */ - unsigned char verbose; /* be verbose in error reporting */ - unsigned char last_cmd[OUTPUT_CMD_SIZE]; - unsigned char screen[32]; + int event; /* alternate interface to events */ + int fader; /* 10 bits */ + int lights; /* 23 bits */ + unsigned char dump_state; /* 0 if disabled 1 if enabled */ + unsigned char enable; /* 0 if disabled 1 if enabled */ + unsigned char offline; /* if the device is out of range or asleep */ + unsigned char verbose; /* be verbose in error reporting */ + unsigned char last_cmd[OUTPUT_CMD_SIZE]; + unsigned char screen[32]; }; /* prevent races between open() and disconnect() */ @@ -219,7 +211,7 @@ static void usb_alphatrack_delete(struct usb_alphatrack *dev) kfree(dev->ring_buffer); kfree(dev->interrupt_in_buffer); kfree(dev->interrupt_out_buffer); - kfree(dev); // fixme oldi_buffer + kfree(dev); /* fixme oldi_buffer */ } /** @@ -234,39 +226,52 @@ static void usb_alphatrack_interrupt_in_callback(struct urb *urb) if (urb->status) { if (urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN) { + urb->status == -ECONNRESET || urb->status == -ESHUTDOWN) { goto exit; } else { - dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", - __func__, urb->status); - goto resubmit; /* maybe we can recover */ + dbg_info(&dev->intf->dev, + "%s: nonzero status received: %d\n", __func__, + urb->status); + goto resubmit; /* maybe we can recover */ } } if (urb->actual_length != INPUT_CMD_SIZE) { dev_warn(&dev->intf->dev, - "Urb length was %d bytes!! Do something intelligent \n", urb->actual_length); + "Urb length was %d bytes!!" + "Do something intelligent \n", urb->actual_length); } else { - alphatrack_ocmd_info(&dev->intf->dev,&(*dev->ring_buffer)[dev->ring_tail].cmd,"%s", "bla"); - if(memcmp(dev->interrupt_in_buffer,dev->oldi_buffer,INPUT_CMD_SIZE)==0) { - goto resubmit; + alphatrack_ocmd_info(&dev->intf->dev, + &(*dev->ring_buffer)[dev->ring_tail].cmd, + "%s", "bla"); + if (memcmp + (dev->interrupt_in_buffer, dev->oldi_buffer, + INPUT_CMD_SIZE) == 0) { + goto resubmit; } - memcpy(dev->oldi_buffer,dev->interrupt_in_buffer,INPUT_CMD_SIZE); + memcpy(dev->oldi_buffer, dev->interrupt_in_buffer, + INPUT_CMD_SIZE); #if SUPPRESS_EXTRA_OFFLINE_EVENTS - if(dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff) { goto resubmit; } - if(dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 2; goto resubmit; } + if (dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff) + goto resubmit; + if (dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) { + dev->offline = 2; + goto resubmit; + } /* Always pass one offline event up the stack */ - if(dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) { dev->offline = 0; } - if(dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 1; } + if (dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) + dev->offline = 0; + if (dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) + dev->offline = 1; #endif - dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail); - next_ring_head = (dev->ring_head+1) % ring_buffer_size; + dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", + __func__, dev->ring_head, dev->ring_tail); + next_ring_head = (dev->ring_head + 1) % ring_buffer_size; if (next_ring_head != dev->ring_tail) { memcpy(&((*dev->ring_buffer)[dev->ring_head]), - dev->interrupt_in_buffer, urb->actual_length); + dev->interrupt_in_buffer, urb->actual_length); dev->ring_head = next_ring_head; retval = 0; memset(dev->interrupt_in_buffer, 0, urb->actual_length); @@ -330,7 +335,7 @@ static int usb_alphatrack_open(struct inode *inode, struct file *file) if (!interface) { err("%s - error, can't find device for minor %d\n", - __func__, subminor); + __func__, subminor); retval = -ENODEV; goto unlock_disconnect_exit; } @@ -361,11 +366,11 @@ static int usb_alphatrack_open(struct inode *inode, struct file *file) usb_fill_int_urb(dev->interrupt_in_urb, interface_to_usbdev(interface), usb_rcvintpipe(interface_to_usbdev(interface), - dev->interrupt_in_endpoint->bEndpointAddress), + dev->interrupt_in_endpoint-> + bEndpointAddress), dev->interrupt_in_buffer, dev->interrupt_in_endpoint_size, - usb_alphatrack_interrupt_in_callback, - dev, + usb_alphatrack_interrupt_in_callback, dev, dev->interrupt_in_interval); dev->interrupt_in_running = 1; @@ -375,7 +380,8 @@ static int usb_alphatrack_open(struct inode *inode, struct file *file) retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); if (retval) { - dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval); + dev_err(&interface->dev, + "Couldn't submit interrupt_in_urb %d\n", retval); dev->interrupt_in_running = 0; dev->open_count = 0; goto unlock_exit; @@ -384,7 +390,6 @@ static int usb_alphatrack_open(struct inode *inode, struct file *file) /* save device in the file's private structure */ file->private_data = dev; - unlock_exit: up(&dev->sem); @@ -430,7 +435,9 @@ static int usb_alphatrack_release(struct inode *inode, struct file *file) /* wait until write transfer is finished */ if (dev->interrupt_out_busy) - wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ); + wait_event_interruptible_timeout(dev->write_wait, + !dev->interrupt_out_busy, + 2 * HZ); usb_alphatrack_abort_transfers(dev); dev->open_count = 0; @@ -444,7 +451,7 @@ exit: /** * usb_alphatrack_poll */ -static unsigned int usb_alphatrack_poll(struct file *file, poll_table *wait) +static unsigned int usb_alphatrack_poll(struct file *file, poll_table * wait) { struct usb_alphatrack *dev; unsigned int mask = 0; @@ -465,8 +472,8 @@ static unsigned int usb_alphatrack_poll(struct file *file, poll_table *wait) /** * usb_alphatrack_read */ -static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer, size_t count, - loff_t *ppos) +static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) { struct usb_alphatrack *dev; int retval = 0; @@ -493,30 +500,36 @@ static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer, size_ } while (dev->ring_head == dev->ring_tail) { - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - goto unlock_exit; - } - dev->interrupt_in_done = 0 ; - retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done); - if (retval < 0) { - goto unlock_exit; - } + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto unlock_exit; + } + dev->interrupt_in_done = 0; + retval = + wait_event_interruptible(dev->read_wait, + dev->interrupt_in_done); + if (retval < 0) + goto unlock_exit; } - alphatrack_ocmd_info(&dev->intf->dev, &(*dev->ring_buffer)[dev->ring_tail].cmd, "%s", ": copying to userspace"); + alphatrack_ocmd_info(&dev->intf->dev, + &(*dev->ring_buffer)[dev->ring_tail].cmd, "%s", + ": copying to userspace"); - c = 0; - while((c < count) && (dev->ring_tail != dev->ring_head)) { - if (copy_to_user(&buffer[c], &(*dev->ring_buffer)[dev->ring_tail], INPUT_CMD_SIZE)) { - retval = -EFAULT; - goto unlock_exit; - } - dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; - c+=INPUT_CMD_SIZE; - dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail); - } - retval = c; + c = 0; + while ((c < count) && (dev->ring_tail != dev->ring_head)) { + if (copy_to_user + (&buffer[c], &(*dev->ring_buffer)[dev->ring_tail], + INPUT_CMD_SIZE)) { + retval = -EFAULT; + goto unlock_exit; + } + dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size; + c += INPUT_CMD_SIZE; + dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", + __func__, dev->ring_head, dev->ring_tail); + } + retval = c; unlock_exit: /* unlock the device */ @@ -529,8 +542,9 @@ exit: /** * usb_alphatrack_write */ -static ssize_t usb_alphatrack_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) +static ssize_t usb_alphatrack_write(struct file *file, + const char __user *buffer, size_t count, + loff_t *ppos) { struct usb_alphatrack *dev; size_t bytes_to_write; @@ -561,19 +575,24 @@ static ssize_t usb_alphatrack_write(struct file *file, const char __user *buffer retval = -EAGAIN; goto unlock_exit; } - retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy); - if (retval < 0) { + retval = + wait_event_interruptible(dev->write_wait, + !dev->interrupt_out_busy); + if (retval < 0) goto unlock_exit; - } } /* write the data into interrupt_out_buffer from userspace */ - /* FIXME - if you write more than 12 bytes this breaks */ - bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); + /* FIXME - if you write more than 12 bytes this breaks */ + bytes_to_write = + min(count, write_buffer_size * dev->interrupt_out_endpoint_size); if (bytes_to_write < count) - dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write); + dev_warn(&dev->intf->dev, + "Write buffer overflow, %zd bytes dropped\n", + count - bytes_to_write); - dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write); + dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", + __func__, count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { retval = -EFAULT; @@ -589,11 +608,10 @@ static ssize_t usb_alphatrack_write(struct file *file, const char __user *buffer usb_fill_int_urb(dev->interrupt_out_urb, interface_to_usbdev(dev->intf), usb_sndintpipe(interface_to_usbdev(dev->intf), - dev->interrupt_out_endpoint->bEndpointAddress), - dev->interrupt_out_buffer, - bytes_to_write, - usb_alphatrack_interrupt_out_callback, - dev, + dev->interrupt_out_endpoint-> + bEndpointAddress), + dev->interrupt_out_buffer, bytes_to_write, + usb_alphatrack_interrupt_out_callback, dev, dev->interrupt_out_interval); dev->interrupt_out_busy = 1; atomic_inc(&dev->writes_pending); @@ -618,12 +636,12 @@ exit: /* file operations needed when we register this driver */ static const struct file_operations usb_alphatrack_fops = { - .owner = THIS_MODULE, - .read = usb_alphatrack_read, - .write = usb_alphatrack_write, - .open = usb_alphatrack_open, - .release = usb_alphatrack_release, - .poll = usb_alphatrack_poll, + .owner = THIS_MODULE, + .read = usb_alphatrack_read, + .write = usb_alphatrack_write, + .open = usb_alphatrack_open, + .release = usb_alphatrack_release, + .poll = usb_alphatrack_poll, }; /* @@ -632,19 +650,19 @@ static const struct file_operations usb_alphatrack_fops = { */ static struct usb_class_driver usb_alphatrack_class = { - .name = "alphatrack%d", - .fops = &usb_alphatrack_fops, - .minor_base = USB_ALPHATRACK_MINOR_BASE, + .name = "alphatrack%d", + .fops = &usb_alphatrack_fops, + .minor_base = USB_ALPHATRACK_MINOR_BASE, }; - /** * usb_alphatrack_probe * * Called by the usb core when a new device is connected that it thinks * this driver might be interested in. */ -static int usb_alphatrack_probe(struct usb_interface *intf, const struct usb_device_id *id) +static int usb_alphatrack_probe(struct usb_interface *intf, + const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); struct usb_alphatrack *dev = NULL; @@ -683,28 +701,35 @@ static int usb_alphatrack_probe(struct usb_interface *intf, const struct usb_dev goto error; } if (dev->interrupt_out_endpoint == NULL) - dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); + dev_warn(&intf->dev, + "Interrupt out endpoint not found" + "(using control endpoint instead)\n"); - dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); + dev->interrupt_in_endpoint_size = + le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); if (dev->interrupt_in_endpoint_size != 64) - dev_warn(&intf->dev, "Interrupt in endpoint size is not 64!\n"); + dev_warn(&intf->dev, "Interrupt in endpoint size is not 64!\n"); - if(ring_buffer_size == 0) { ring_buffer_size = RING_BUFFER_SIZE; } + if (ring_buffer_size == 0) + ring_buffer_size = RING_BUFFER_SIZE; - true_size = min(ring_buffer_size,RING_BUFFER_SIZE); + true_size = min(ring_buffer_size, RING_BUFFER_SIZE); - /* FIXME - there are more usb_alloc routines for dma correctness. Needed? */ - -// dev->ring_buffer = kmalloc((true_size*sizeof(struct alphatrack_icmd))+12, GFP_KERNEL); - dev->ring_buffer = kmalloc((true_size*sizeof(struct alphatrack_icmd)), GFP_KERNEL); + /* FIXME - there are more usb_alloc routines for dma correctness. + Needed? */ + dev->ring_buffer = + kmalloc((true_size * sizeof(struct alphatrack_icmd)), GFP_KERNEL); if (!dev->ring_buffer) { - dev_err(&intf->dev, "Couldn't allocate input ring_buffer of size %d\n",true_size); + dev_err(&intf->dev, + "Couldn't allocate input ring_buffer of size %d\n", + true_size); goto error; } - dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); + dev->interrupt_in_buffer = + kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); if (!dev->interrupt_in_buffer) { dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n"); @@ -721,23 +746,30 @@ static int usb_alphatrack_probe(struct usb_interface *intf, const struct usb_dev goto error; } - dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) : - udev->descriptor.bMaxPacketSize0; + dev->interrupt_out_endpoint_size = + dev->interrupt_out_endpoint ? le16_to_cpu(dev-> + interrupt_out_endpoint-> + wMaxPacketSize) : udev-> + descriptor.bMaxPacketSize0; - if (dev->interrupt_out_endpoint_size !=64) - dev_warn(&intf->dev, "Interrupt out endpoint size is not 64!)\n"); + if (dev->interrupt_out_endpoint_size != 64) + dev_warn(&intf->dev, + "Interrupt out endpoint size is not 64!)\n"); - if(write_buffer_size == 0) { write_buffer_size = WRITE_BUFFER_SIZE; } - true_size = min(write_buffer_size,WRITE_BUFFER_SIZE); + if (write_buffer_size == 0) + write_buffer_size = WRITE_BUFFER_SIZE; + true_size = min(write_buffer_size, WRITE_BUFFER_SIZE); - dev->interrupt_out_buffer = kmalloc(true_size*dev->interrupt_out_endpoint_size, GFP_KERNEL); + dev->interrupt_out_buffer = + kmalloc(true_size * dev->interrupt_out_endpoint_size, GFP_KERNEL); if (!dev->interrupt_out_buffer) { dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n"); goto error; } - dev->write_buffer = kmalloc(sizeof(struct alphatrack_ocmd)*true_size, GFP_KERNEL); + dev->write_buffer = + kmalloc(sizeof(struct alphatrack_ocmd) * true_size, GFP_KERNEL); if (!dev->write_buffer) { dev_err(&intf->dev, "Couldn't allocate write_buffer \n"); @@ -749,25 +781,36 @@ static int usb_alphatrack_probe(struct usb_interface *intf, const struct usb_dev dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n"); goto error; } - dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; + dev->interrupt_in_interval = + min_interrupt_in_interval > + dev->interrupt_in_endpoint-> + bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint-> + bInterval; if (dev->interrupt_out_endpoint) - dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; + dev->interrupt_out_interval = + min_interrupt_out_interval > + dev->interrupt_out_endpoint-> + bInterval ? min_interrupt_out_interval : dev-> + interrupt_out_endpoint->bInterval; /* we can register the device now, as it is ready */ usb_set_intfdata(intf, dev); - atomic_set(&dev->writes_pending,0); + atomic_set(&dev->writes_pending, 0); retval = usb_register_dev(intf, &usb_alphatrack_class); if (retval) { /* something prevented us from registering this driver */ - dev_err(&intf->dev, "Not able to get a minor for this device.\n"); + dev_err(&intf->dev, + "Not able to get a minor for this device.\n"); usb_set_intfdata(intf, NULL); goto error; } /* let the user know what node this device is now attached to */ - dev_info(&intf->dev, "Alphatrack Device #%d now attached to major %d minor %d\n", - (intf->minor - USB_ALPHATRACK_MINOR_BASE), USB_MAJOR, intf->minor); + dev_info(&intf->dev, + "Alphatrack Device #%d now attached to major %d minor %d\n", + (intf->minor - USB_ALPHATRACK_MINOR_BASE), USB_MAJOR, + intf->minor); exit: return retval; @@ -809,7 +852,7 @@ static void usb_alphatrack_disconnect(struct usb_interface *intf) up(&dev->sem); } - atomic_set(&dev->writes_pending,0); + atomic_set(&dev->writes_pending, 0); mutex_unlock(&disconnect_mutex); dev_info(&intf->dev, "Alphatrack Surface #%d now disconnected\n", @@ -818,10 +861,10 @@ static void usb_alphatrack_disconnect(struct usb_interface *intf) /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver usb_alphatrack_driver = { - .name = "alphatrack", - .probe = usb_alphatrack_probe, - .disconnect = usb_alphatrack_disconnect, - .id_table = usb_alphatrack_table, + .name = "alphatrack", + .probe = usb_alphatrack_probe, + .disconnect = usb_alphatrack_disconnect, + .id_table = usb_alphatrack_table, }; /** @@ -834,7 +877,8 @@ static int __init usb_alphatrack_init(void) /* register this driver with the USB subsystem */ retval = usb_register(&usb_alphatrack_driver); if (retval) - err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval); + err("usb_register failed for the " __FILE__ + " driver. Error number %d\n", retval); return retval; } @@ -850,4 +894,3 @@ static void __exit usb_alphatrack_exit(void) module_init(usb_alphatrack_init); module_exit(usb_alphatrack_exit); - diff --git a/drivers/staging/frontier/alphatrack.h b/drivers/staging/frontier/alphatrack.h index 35c90a90eb08..10a797263594 100644 --- a/drivers/staging/frontier/alphatrack.h +++ b/drivers/staging/frontier/alphatrack.h @@ -1,42 +1,38 @@ -#define show_set_bit(a) show_set_mbit(alphatrack,a) -#define show_set_cmd(a) show_set_mcmd(alphatrack,a) -#define show_set_int(a) show_set_mint(alphatrack,a) -#define show_set_char(a) show_set_mchar(alphatrack,a) -#define show_set_light(a) show_set_ebit(alphatrack,LightID,lights,a) -#define show_set_button(a) show_set_ebit(alphatrack,ButtonID,button,a) - struct alphatrack_icmd { - unsigned char cmd[12]; + unsigned char cmd[12]; }; struct alphatrack_ocmd { - unsigned char cmd[8]; + unsigned char cmd[8]; }; +/* These are unused by the present driver but provide documentation for the + * userspace API. + */ enum LightID { - LIGHT_EQ = 0, - LIGHT_OUT, - LIGHT_F2, - LIGHT_SEND, - LIGHT_IN, - LIGHT_F1, - LIGHT_PAN, - LIGHT_UNDEF1, - LIGHT_UNDEF2, - LIGHT_SHIFT, - LIGHT_TRACKMUTE, - LIGHT_TRACKSOLO, - LIGHT_TRACKREC, - LIGHT_READ, - LIGHT_WRITE, - LIGHT_ANYSOLO, - LIGHT_AUTO, - LIGHT_F4, - LIGHT_RECORD, - LIGHT_WINDOW, - LIGHT_PLUGIN, - LIGHT_F3, - LIGHT_LOOP + LIGHT_EQ = 0, + LIGHT_OUT, + LIGHT_F2, + LIGHT_SEND, + LIGHT_IN, + LIGHT_F1, + LIGHT_PAN, + LIGHT_UNDEF1, + LIGHT_UNDEF2, + LIGHT_SHIFT, + LIGHT_TRACKMUTE, + LIGHT_TRACKSOLO, + LIGHT_TRACKREC, + LIGHT_READ, + LIGHT_WRITE, + LIGHT_ANYSOLO, + LIGHT_AUTO, + LIGHT_F4, + LIGHT_RECORD, + LIGHT_WINDOW, + LIGHT_PLUGIN, + LIGHT_F3, + LIGHT_LOOP }; #define BUTTONMASK_BATTERY 0x00004000 @@ -62,8 +58,9 @@ enum LightID { #define BUTTONMASK_PRESS2 0x00008010 #define BUTTONMASK_PRESS3 0x00002020 -// last 3 bytes are the slider position -// 40 is the actual slider moving, the most sig bits, and 3 lsb +/* last 3 bytes are the slider position + * 40 is the actual slider moving, the most sig bits, and 3 lsb + */ #define BUTTONMASK_FLIP 0x40000000 #define BUTTONMASK_F1 0x00100000 @@ -76,17 +73,4 @@ enum LightID { #define BUTTONMASK_PLUGIN 0x00000400 #define BUTTONMASK_AUTO 0x00000100 - -// #define BUTTONMASK_FOOTSWITCH FIXME - -// Lookup. name. midi out. midi in. - -struct buttonmap_t { - u32 mask; - short midi_in; - short midi_out; - char *name; -// void (*function) (buttonmap_t *); - void (*function) (void); -}; - +/* #define BUTTONMASK_FOOTSWITCH FIXME */ diff --git a/drivers/staging/frontier/frontier_compat.h b/drivers/staging/frontier/frontier_compat.h deleted file mode 100644 index 00450e637ac8..000000000000 --- a/drivers/staging/frontier/frontier_compat.h +++ /dev/null @@ -1,63 +0,0 @@ -/* USB defines for older kernels */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - -/** - * usb_endpoint_dir_out - check if the endpoint has OUT direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type OUT, otherwise it returns false. - */ - -static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); -} - -static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); -} - - -/** - * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type interrupt, otherwise it returns - * false. - */ -static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT); -} - - -/** - * usb_endpoint_is_int_in - check if the endpoint is interrupt IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and IN direction, - * otherwise it returns false. - */ - -static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and OUT direction, - * otherwise it returns false. - */ - -static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); -} - -#endif /* older kernel versions */ diff --git a/drivers/staging/frontier/surface_sysfs.h b/drivers/staging/frontier/surface_sysfs.h deleted file mode 100644 index d50a562d658a..000000000000 --- a/drivers/staging/frontier/surface_sysfs.h +++ /dev/null @@ -1,100 +0,0 @@ -/* If you are going to abuse the preprocessor, why not ABUSE the preprocessor? - I stuck this header in a separate file so I don't have to look at it */ - -// FIXME Need locking or atomic ops - -#define show_set_mbit(dname,value,bit) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - int temp = (1 && (t->value & (1 << bit))); \ - return sprintf(buf, "%d\n", temp); \ -} \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - int temp = simple_strtoul(buf, NULL, 10); \ - if(temp > 0) { long b = 1 << bit; t->value |= b; } \ - else { long b = ~(1 << bit); t->value &= b ; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); - -#define show_set_ebit(dname,enumname,value,bit) \ -static ssize_t show_##bit(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - enum enumname l = bit; \ - int temp = t->value & (1 << l); \ - return sprintf(buf, "%d\n", temp); \ -} \ -static ssize_t set_##bit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - int temp = simple_strtoul(buf, NULL, 10); \ - enum enumname l = bit;\ - long b = 1 << l; \ - if(temp > 0) { t->value |= b; } \ - else { t->value &= ~b ; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); - -// FIXME FOR CORRECTLY SETTING HEX from a string -#define show_set_mcmd(dname,value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - int count = 0;\ - int i; \ - for (i = 0,idname[i]); \ - return(count);\ -} \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - int temp = simple_strtoul(buf, NULL, 10); \ - t->value = temp; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); - -#define show_set_mint(dname,value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - return sprintf(buf, "%d\n", t->value); \ -} \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - int temp = simple_strtoul(buf, NULL, 10); \ - t->value = temp; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); - -#define show_set_mchar(dname,value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - return sprintf(buf, "%c\n", t->value); \ -} \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_##dname *t = usb_get_intfdata(intf); \ - int temp = simple_strtoul(buf, NULL, 10); \ - t->value = temp; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); diff --git a/drivers/staging/frontier/tranzport.c b/drivers/staging/frontier/tranzport.c index 79abb6b16f74..274b82bd7863 100644 --- a/drivers/staging/frontier/tranzport.c +++ b/drivers/staging/frontier/tranzport.c @@ -18,7 +18,7 @@ * */ -/** +/* * This driver uses a ring buffer for time critical reading of * interrupt in reports and provides read and write methods for * raw interrupt reports. @@ -30,7 +30,7 @@ * as we only have 17 commands for the tranzport. In particular this is * key for getting lights to flash in time as otherwise many commands * can be buffered up before the light change makes it to the interface. -*/ + */ #include #include @@ -40,56 +40,47 @@ #include #include -#include +#include #include #include #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -#include frontier_compat.h -#endif - /* Define these values to match your devices */ #define VENDOR_ID 0x165b -#define PRODUCT_ID 0x8101 +#define PRODUCT_ID 0x8101 #ifdef CONFIG_USB_DYNAMIC_MINORS #define USB_TRANZPORT_MINOR_BASE 0 -#else -// FIXME 176 - is the ldusb driver's minor - apply for a minor soon +#else /* FIXME 177- is the another driver's minor - apply for a minor soon */ #define USB_TRANZPORT_MINOR_BASE 177 #endif /* table of devices that work with this driver */ -static struct usb_device_id usb_tranzport_table [] = { - { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, - { } /* Terminating entry */ +static struct usb_device_id usb_tranzport_table[] = { + {USB_DEVICE(VENDOR_ID, PRODUCT_ID)}, + {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, usb_tranzport_table); -MODULE_VERSION("0.33"); +MODULE_VERSION("0.35"); MODULE_AUTHOR("Mike Taht "); MODULE_DESCRIPTION("Tranzport USB Driver"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("Frontier Designs Tranzport Control Surface"); -/* These two aren't done yet */ - -#define SUPPRESS_EXTRA_ONLINE_EVENTS 0 -#define BUFFERED_WRITES 0 - #define SUPPRESS_EXTRA_OFFLINE_EVENTS 1 #define COMPRESS_WHEEL_EVENTS 1 #define BUFFERED_READS 1 #define RING_BUFFER_SIZE 1000 #define WRITE_BUFFER_SIZE 34 #define TRANZPORT_USB_TIMEOUT 10 +#define TRANZPORT_DEBUG 0 - -static int debug = 0; +static int debug = TRANZPORT_DEBUG; /* Use our own dbg macro */ -#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) +#define dbg_info(dev, format, arg...) do \ + { if (debug) dev_info(dev , format , ## arg); } while (0) /* Module parameters */ @@ -102,13 +93,13 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); static int ring_buffer_size = RING_BUFFER_SIZE; -module_param(ring_buffer_size, int, S_IRUGO); +module_param(ring_buffer_size, int, S_IRUGO); MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports"); /* The write_buffer can one day contain more than one interrupt out transfer. */ static int write_buffer_size = WRITE_BUFFER_SIZE; -module_param(write_buffer_size, int, S_IRUGO); +module_param(write_buffer_size, int, S_IRUGO); MODULE_PARM_DESC(write_buffer_size, "Write buffer size"); /* @@ -118,69 +109,48 @@ MODULE_PARM_DESC(write_buffer_size, "Write buffer size"); static int min_interrupt_in_interval = TRANZPORT_USB_TIMEOUT; module_param(min_interrupt_in_interval, int, 0); -MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms"); +MODULE_PARM_DESC(min_interrupt_in_interval, + "Minimum interrupt in interval in ms"); static int min_interrupt_out_interval = TRANZPORT_USB_TIMEOUT; module_param(min_interrupt_out_interval, int, 0); -MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms"); +MODULE_PARM_DESC(min_interrupt_out_interval, + "Minimum interrupt out interval in ms"); struct tranzport_cmd { - unsigned char cmd[8]; + unsigned char cmd[8]; }; -enum LightID { - LightRecord = 0, - LightTrackrec, - LightTrackmute, - LightTracksolo, - LightAnysolo, - LightLoop, - LightPunch - }; - /* Structure to hold all of our device specific stuff */ struct usb_tranzport { - struct semaphore sem; /* locks this structure */ - struct usb_interface* intf; /* save off the usb interface pointer */ + struct semaphore sem; /* locks this structure */ + struct usb_interface *intf; /* save off the usb interface pointer */ + int open_count; /* number of times this port opened */ + struct tranzport_cmd (*ring_buffer)[RING_BUFFER_SIZE]; + unsigned int ring_head; + unsigned int ring_tail; + wait_queue_head_t read_wait; + wait_queue_head_t write_wait; + unsigned char *interrupt_in_buffer; + struct usb_endpoint_descriptor *interrupt_in_endpoint; + struct urb *interrupt_in_urb; + int interrupt_in_interval; + size_t interrupt_in_endpoint_size; + int interrupt_in_running; + int interrupt_in_done; + char *interrupt_out_buffer; + struct usb_endpoint_descriptor *interrupt_out_endpoint; + struct urb *interrupt_out_urb; + int interrupt_out_interval; + size_t interrupt_out_endpoint_size; + int interrupt_out_busy; - int open_count; /* number of times this port has been opened */ - - struct tranzport_cmd (*ring_buffer)[RING_BUFFER_SIZE]; /* just make c happy */ - unsigned int ring_head; - unsigned int ring_tail; - - wait_queue_head_t read_wait; - wait_queue_head_t write_wait; - - unsigned char* interrupt_in_buffer; - struct usb_endpoint_descriptor* interrupt_in_endpoint; - struct urb* interrupt_in_urb; - int interrupt_in_interval; - size_t interrupt_in_endpoint_size; - int interrupt_in_running; - int interrupt_in_done; - - char* interrupt_out_buffer; - struct usb_endpoint_descriptor* interrupt_out_endpoint; - struct urb* interrupt_out_urb; - int interrupt_out_interval; - size_t interrupt_out_endpoint_size; - int interrupt_out_busy; - - /* Sysfs and translation support */ - - int event; /* alternate interface to events */ - int wheel; /* - for negative, 0 for none, + for positive */ - unsigned char dump_state; /* 0 if disabled 1 if enabled */ - unsigned char enable; /* 0 if disabled 1 if enabled */ - unsigned char offline; /* if the device is out of range or asleep */ - unsigned char compress_wheel; /* flag to compress wheel events */ - unsigned char light; /* 7 bits used */ - unsigned char last_cmd[8]; - unsigned char last_input[8]; - unsigned char screen[40]; // We'll also have cells + /* Sysfs support */ + unsigned char enable; /* 0 if disabled 1 if enabled */ + unsigned char offline; /* if the device is out of range or asleep */ + unsigned char compress_wheel; /* flag to compress wheel events */ }; /* prevent races between open() and disconnect() */ @@ -205,84 +175,39 @@ static void usb_tranzport_abort_transfers(struct usb_tranzport *dev) usb_kill_urb(dev->interrupt_out_urb); } -// FIXME ~light not good enough or correct - need atomic set_bit +#define show_int(value) \ + static ssize_t show_##value(struct device *dev, \ + struct device_attribute *attr, char *buf) \ + { \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct usb_tranzport *t = usb_get_intfdata(intf); \ + return sprintf(buf, "%d\n", t->value); \ + } \ + static DEVICE_ATTR(value, S_IRUGO, show_##value, NULL); -#define show_set_light(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_tranzport *t = usb_get_intfdata(intf); \ - enum LightID light = value; \ - int temp = (1 && (t->light & (1 << light))); \ - return sprintf(buf, "%d\n", temp ); \ -} \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_tranzport *t = usb_get_intfdata(intf); \ - int temp = simple_strtoul(buf, NULL, 10); \ - enum LightID light = (temp << value) & (t->light << value); \ - t->light = (t->light & ~light) ; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); +#define show_set_int(value) \ + static ssize_t show_##value(struct device *dev, \ + struct device_attribute *attr, char *buf) \ + { \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct usb_tranzport *t = usb_get_intfdata(intf); \ + return sprintf(buf, "%d\n", t->value); \ + } \ + static ssize_t set_##value(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ + { \ + struct usb_interface *intf = to_usb_interface(dev); \ + struct usb_tranzport *t = usb_get_intfdata(intf); \ + int temp = simple_strtoul(buf, NULL, 10); \ + t->value = temp; \ + return count; \ + } \ + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); -show_set_light(LightRecord); -show_set_light(LightTrackrec); -show_set_light(LightTrackmute); -show_set_light(LightTracksolo); -show_set_light(LightAnysolo); -show_set_light(LightLoop); -show_set_light(LightPunch); - - -#define show_set_int(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_tranzport *t = usb_get_intfdata(intf); \ - \ - return sprintf(buf, "%d\n", t->value); \ -} \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_tranzport *t = usb_get_intfdata(intf); \ - int temp = simple_strtoul(buf, NULL, 10); \ - \ - t->value = temp; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); - -show_set_int(enable); -show_set_int(offline); +show_int(enable); +show_int(offline); show_set_int(compress_wheel); -show_set_int(dump_state); -show_set_int(wheel); -show_set_int(event); - -#define show_set_cmd(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_tranzport *t = usb_get_intfdata(intf); \ - \ - return sprintf(buf, "%d\n", t->value); \ -} \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct usb_interface *intf = to_usb_interface(dev); \ - struct usb_tranzport *t = usb_get_intfdata(intf); \ - int temp = simple_strtoul(buf, NULL, 10); \ - \ - t->value = temp; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); - - - /** * usb_tranzport_delete @@ -290,23 +215,10 @@ static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); static void usb_tranzport_delete(struct usb_tranzport *dev) { usb_tranzport_abort_transfers(dev); - /* This is just too twisted to be correct */ - if(dev->intf != NULL) { - device_remove_file(&dev->intf->dev, &dev_attr_LightRecord); - device_remove_file(&dev->intf->dev, &dev_attr_LightTrackrec); - device_remove_file(&dev->intf->dev, &dev_attr_LightTrackmute); - device_remove_file(&dev->intf->dev, &dev_attr_LightTracksolo); - device_remove_file(&dev->intf->dev, &dev_attr_LightTrackmute); - device_remove_file(&dev->intf->dev, &dev_attr_LightAnysolo); - device_remove_file(&dev->intf->dev, &dev_attr_LightLoop); - device_remove_file(&dev->intf->dev, &dev_attr_LightPunch); - device_remove_file(&dev->intf->dev, &dev_attr_wheel); - device_remove_file(&dev->intf->dev, &dev_attr_enable); - device_remove_file(&dev->intf->dev, &dev_attr_event); - device_remove_file(&dev->intf->dev, &dev_attr_offline); - device_remove_file(&dev->intf->dev, &dev_attr_compress_wheel); - - device_remove_file(&dev->intf->dev, &dev_attr_dump_state); + if (dev->intf != NULL) { + device_remove_file(&dev->intf->dev, &dev_attr_enable); + device_remove_file(&dev->intf->dev, &dev_attr_offline); + device_remove_file(&dev->intf->dev, &dev_attr_compress_wheel); } /* free data structures */ @@ -330,37 +242,56 @@ static void usb_tranzport_interrupt_in_callback(struct urb *urb) if (urb->status) { if (urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN) { + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN) { goto exit; } else { - dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", + dbg_info(&dev->intf->dev, + "%s: nonzero status received: %d\n", __func__, urb->status); - goto resubmit; /* maybe we can recover */ + goto resubmit; /* maybe we can recover */ } } if (urb->actual_length != 8) { dev_warn(&dev->intf->dev, - "Urb length was %d bytes!! Do something intelligent \n", urb->actual_length); + "Urb length was %d bytes!!" + "Do something intelligent \n", + urb->actual_length); } else { - dbg_info(&dev->intf->dev, "%s: received: %02x%02x%02x%02x%02x%02x%02x%02x\n", - __func__, dev->interrupt_in_buffer[0],dev->interrupt_in_buffer[1],dev->interrupt_in_buffer[2],dev->interrupt_in_buffer[3],dev->interrupt_in_buffer[4],dev->interrupt_in_buffer[5],dev->interrupt_in_buffer[6],dev->interrupt_in_buffer[7]); + dbg_info(&dev->intf->dev, + "%s: received: %02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, dev->interrupt_in_buffer[0], + dev->interrupt_in_buffer[1], + dev->interrupt_in_buffer[2], + dev->interrupt_in_buffer[3], + dev->interrupt_in_buffer[4], + dev->interrupt_in_buffer[5], + dev->interrupt_in_buffer[6], + dev->interrupt_in_buffer[7]); #if SUPPRESS_EXTRA_OFFLINE_EVENTS - if(dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff) { goto resubmit; } - if(dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 2; goto resubmit; } + if (dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff) + goto resubmit; + if (dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) { + dev->offline = 2; + goto resubmit; + } -/* Always pass one offline event up the stack */ - if(dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) { dev->offline = 0; } - if(dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 1; } + /* Always pass one offline event up the stack */ + if (dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) + dev->offline = 0; + if (dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) + dev->offline = 1; -#endif - dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail); +#endif /* SUPPRESS_EXTRA_OFFLINE_EVENTS */ + dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", + __func__, dev->ring_head, dev->ring_tail); - next_ring_head = (dev->ring_head+1) % ring_buffer_size; + next_ring_head = (dev->ring_head + 1) % ring_buffer_size; if (next_ring_head != dev->ring_tail) { - memcpy(&((*dev->ring_buffer)[dev->ring_head]), dev->interrupt_in_buffer, urb->actual_length); + memcpy(&((*dev->ring_buffer)[dev->ring_head]), + dev->interrupt_in_buffer, urb->actual_length); dev->ring_head = next_ring_head; retval = 0; memset(dev->interrupt_in_buffer, 0, urb->actual_length); @@ -373,7 +304,7 @@ static void usb_tranzport_interrupt_in_callback(struct urb *urb) } resubmit: - /* resubmit if we're still running */ +/* resubmit if we're still running */ if (dev->interrupt_in_running && dev->intf) { retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); if (retval) @@ -392,19 +323,17 @@ exit: static void usb_tranzport_interrupt_out_callback(struct urb *urb) { struct usb_tranzport *dev = urb->context; - /* sync/async unlink faults aren't errors */ if (urb->status && !(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN)) dbg_info(&dev->intf->dev, - "%s - nonzero write interrupt status received: %d\n", - __func__, urb->status); + "%s - nonzero write interrupt status received: %d\n", + __func__, urb->status); dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); } - /** * usb_tranzport_open */ @@ -424,7 +353,7 @@ static int usb_tranzport_open(struct inode *inode, struct file *file) if (!interface) { err("%s - error, can't find device for minor %d\n", - __func__, subminor); + __func__, subminor); retval = -ENODEV; goto unlock_disconnect_exit; } @@ -453,14 +382,14 @@ static int usb_tranzport_open(struct inode *inode, struct file *file) dev->ring_head = 0; dev->ring_tail = 0; usb_fill_int_urb(dev->interrupt_in_urb, - interface_to_usbdev(interface), - usb_rcvintpipe(interface_to_usbdev(interface), - dev->interrupt_in_endpoint->bEndpointAddress), - dev->interrupt_in_buffer, - dev->interrupt_in_endpoint_size, - usb_tranzport_interrupt_in_callback, - dev, - dev->interrupt_in_interval); + interface_to_usbdev(interface), + usb_rcvintpipe(interface_to_usbdev(interface), + dev->interrupt_in_endpoint-> + bEndpointAddress), + dev->interrupt_in_buffer, + dev->interrupt_in_endpoint_size, + usb_tranzport_interrupt_in_callback, dev, + dev->interrupt_in_interval); dev->interrupt_in_running = 1; dev->interrupt_in_done = 0; @@ -470,7 +399,8 @@ static int usb_tranzport_open(struct inode *inode, struct file *file) retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); if (retval) { - dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval); + dev_err(&interface->dev, + "Couldn't submit interrupt_in_urb %d\n", retval); dev->interrupt_in_running = 0; dev->open_count = 0; goto unlock_exit; @@ -479,7 +409,6 @@ static int usb_tranzport_open(struct inode *inode, struct file *file) /* save device in the file's private structure */ file->private_data = dev; - unlock_exit: up(&dev->sem); @@ -525,7 +454,9 @@ static int usb_tranzport_release(struct inode *inode, struct file *file) /* wait until write transfer is finished */ if (dev->interrupt_out_busy) - wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ); + wait_event_interruptible_timeout(dev->write_wait, + !dev->interrupt_out_busy, + 2 * HZ); usb_tranzport_abort_transfers(dev); dev->open_count = 0; @@ -539,37 +470,31 @@ exit: /** * usb_tranzport_poll */ -static unsigned int usb_tranzport_poll(struct file *file, poll_table *wait) +static unsigned int usb_tranzport_poll(struct file *file, poll_table * wait) { struct usb_tranzport *dev; unsigned int mask = 0; - dev = file->private_data; - poll_wait(file, &dev->read_wait, wait); poll_wait(file, &dev->write_wait, wait); - if (dev->ring_head != dev->ring_tail) mask |= POLLIN | POLLRDNORM; if (!dev->interrupt_out_busy) mask |= POLLOUT | POLLWRNORM; - return mask; } - /** * usb_tranzport_read */ -static ssize_t usb_tranzport_read(struct file *file, char __user *buffer, size_t count, - loff_t *ppos) + +static ssize_t usb_tranzport_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) { struct usb_tranzport *dev; int retval = 0; - #if BUFFERED_READS int c = 0; #endif - #if COMPRESS_WHEEL_EVENTS signed char oldwheel; signed char newwheel; @@ -577,7 +502,7 @@ static ssize_t usb_tranzport_read(struct file *file, char __user *buffer, size_t int next_tail; #endif -/* do I have such a thing as a null event? */ + /* do I have such a thing as a null event? */ dev = file->private_data; @@ -591,8 +516,7 @@ static ssize_t usb_tranzport_read(struct file *file, char __user *buffer, size_t goto exit; } - /* verify that the device wasn't unplugged */ - if (dev->intf == NULL) { + /* verify that the device wasn't unplugged */ if (dev->intf == NULL) { retval = -ENODEV; err("No device or device unplugged %d\n", retval); goto unlock_exit; @@ -604,104 +528,149 @@ static ssize_t usb_tranzport_read(struct file *file, char __user *buffer, size_t retval = -EAGAIN; goto unlock_exit; } - // atomic_cmp_exchange(&dev->interrupt_in_done,0,0); - dev->interrupt_in_done = 0 ; /* tiny race - FIXME: make atomic? */ - retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done); - if (retval < 0) { + /* tiny race - FIXME: make atomic? */ + /* atomic_cmp_exchange(&dev->interrupt_in_done,0,0); */ + dev->interrupt_in_done = 0; + retval = wait_event_interruptible(dev->read_wait, + dev->interrupt_in_done); + if (retval < 0) goto unlock_exit; - } } - dbg_info(&dev->intf->dev, "%s: copying to userspace: %02x%02x%02x%02x%02x%02x%02x%02x\n", - __func__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]); + dbg_info(&dev->intf->dev, + "%s: copying to userspace: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, + (*dev->ring_buffer)[dev->ring_tail].cmd[0], + (*dev->ring_buffer)[dev->ring_tail].cmd[1], + (*dev->ring_buffer)[dev->ring_tail].cmd[2], + (*dev->ring_buffer)[dev->ring_tail].cmd[3], + (*dev->ring_buffer)[dev->ring_tail].cmd[4], + (*dev->ring_buffer)[dev->ring_tail].cmd[5], + (*dev->ring_buffer)[dev->ring_tail].cmd[6], + (*dev->ring_buffer)[dev->ring_tail].cmd[7]); #if BUFFERED_READS - c = 0; - while((c < count) && (dev->ring_tail != dev->ring_head)) { + c = 0; + while ((c < count) && (dev->ring_tail != dev->ring_head)) { -/* This started off in the lower level service routine, and I moved it here. Then my brain died. Not done yet. */ #if COMPRESS_WHEEL_EVENTS next_tail = (dev->ring_tail+1) % ring_buffer_size; - if(dev->compress_wheel) cancompress = 1; - while(dev->ring_head != next_tail && cancompress == 1 ) { + if (dev->compress_wheel) + cancompress = 1; + while (dev->ring_head != next_tail && cancompress == 1) { newwheel = (*dev->ring_buffer)[next_tail].cmd[6]; oldwheel = (*dev->ring_buffer)[dev->ring_tail].cmd[6]; - // if both are wheel events, and no buttons have changes (FIXME, do I have to check?), - // and we are the same sign, we can compress +- 7F - // FIXME: saner check for overflow! - max of +- 7F - // FIXME the math is wrong for going in reverse, actually, as the midi spec doesn't allow signed chars + /* if both are wheel events, and + no buttons have changes (FIXME, do I have to check?), + and we are the same sign, we can compress +- 7F + */ + dbg_info(&dev->intf->dev, + "%s: trying to compress: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, + (*dev->ring_buffer)[dev->ring_tail].cmd[0], + (*dev->ring_buffer)[dev->ring_tail].cmd[1], + (*dev->ring_buffer)[dev->ring_tail].cmd[2], + (*dev->ring_buffer)[dev->ring_tail].cmd[3], + (*dev->ring_buffer)[dev->ring_tail].cmd[4], + (*dev->ring_buffer)[dev->ring_tail].cmd[5], + (*dev->ring_buffer)[dev->ring_tail].cmd[6], + (*dev->ring_buffer)[dev->ring_tail].cmd[7]); - dbg_info(&dev->intf->dev, "%s: trying to compress: %02x%02x%02x%02x%02x %02x %02x %02x\n", - __func__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]); - - - if(((*dev->ring_buffer)[dev->ring_tail].cmd[6] != 0 && - (*dev->ring_buffer)[next_tail].cmd[6] != 0 ) && + if (((*dev->ring_buffer)[dev->ring_tail].cmd[6] != 0 && + (*dev->ring_buffer)[next_tail].cmd[6] != 0) && ((newwheel > 0 && oldwheel > 0) || - (newwheel < 0 && oldwheel < 0)) && - ((*dev->ring_buffer)[dev->ring_tail].cmd[2] == (*dev->ring_buffer)[next_tail].cmd[2]) && - ((*dev->ring_buffer)[dev->ring_tail].cmd[3] == (*dev->ring_buffer)[next_tail].cmd[3]) && - ((*dev->ring_buffer)[dev->ring_tail].cmd[4] == (*dev->ring_buffer)[next_tail].cmd[4]) && - ((*dev->ring_buffer)[dev->ring_tail].cmd[5] == (*dev->ring_buffer)[next_tail].cmd[5])) - { - dbg_info(&dev->intf->dev, "%s: should compress: %02x%02x%02x%02x%02x%02x%02x%02x\n", - __func__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]); - + (newwheel < 0 && oldwheel < 0)) && + ((*dev->ring_buffer)[dev->ring_tail].cmd[2] == + (*dev->ring_buffer)[next_tail].cmd[2]) && + ((*dev->ring_buffer)[dev->ring_tail].cmd[3] == + (*dev->ring_buffer)[next_tail].cmd[3]) && + ((*dev->ring_buffer)[dev->ring_tail].cmd[4] == + (*dev->ring_buffer)[next_tail].cmd[4]) && + ((*dev->ring_buffer)[dev->ring_tail].cmd[5] == + (*dev->ring_buffer)[next_tail].cmd[5])) { + dbg_info(&dev->intf->dev, + "%s: should compress: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + __func__, + (*dev->ring_buffer)[dev->ring_tail]. + cmd[0], + (*dev->ring_buffer)[dev->ring_tail]. + cmd[1], + (*dev->ring_buffer)[dev->ring_tail]. + cmd[2], + (*dev->ring_buffer)[dev->ring_tail]. + cmd[3], + (*dev->ring_buffer)[dev->ring_tail]. + cmd[4], + (*dev->ring_buffer)[dev->ring_tail]. + cmd[5], + (*dev->ring_buffer)[dev->ring_tail]. + cmd[6], + (*dev->ring_buffer)[dev->ring_tail]. + cmd[7]); newwheel += oldwheel; - if(oldwheel > 0 && !(newwheel > 0)) { + if (oldwheel > 0 && !(newwheel > 0)) { newwheel = 0x7f; cancompress = 0; } - if(oldwheel < 0 && !(newwheel < 0)) { + if (oldwheel < 0 && !(newwheel < 0)) { newwheel = 0x80; cancompress = 0; } - (*dev->ring_buffer)[next_tail].cmd[6] = newwheel; + (*dev->ring_buffer)[next_tail].cmd[6] = + newwheel; dev->ring_tail = next_tail; - next_tail = (dev->ring_tail+1) % ring_buffer_size; + next_tail = + (dev->ring_tail + 1) % ring_buffer_size; } else { cancompress = 0; } } #endif /* COMPRESS_WHEEL_EVENTS */ - - if (copy_to_user(&buffer[c], &(*dev->ring_buffer)[dev->ring_tail], 8)) { + if (copy_to_user( + &buffer[c], + &(*dev->ring_buffer)[dev->ring_tail], 8)) { retval = -EFAULT; goto unlock_exit; } - - dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; - c+=8; - dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail); - } - retval = c; + dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size; + c += 8; + dbg_info(&dev->intf->dev, + "%s: head, tail are %x, %x\n", + __func__, dev->ring_head, dev->ring_tail); + } + retval = c; #else - if (copy_to_user(buffer, &(*dev->ring_buffer)[dev->ring_tail], 8)) { - retval = -EFAULT; - goto unlock_exit; - } +/* if (copy_to_user(buffer, &(*dev->ring_buffer)[dev->ring_tail], 8)) { */ + retval = -EFAULT; + goto unlock_exit; +} - dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; - dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail); +dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size; +dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", + __func__, dev->ring_head, dev->ring_tail); - retval = 8; +retval = 8; #endif /* BUFFERED_READS */ unlock_exit: - /* unlock the device */ - up(&dev->sem); +/* unlock the device */ +up(&dev->sem); exit: - return retval; +return retval; } /** * usb_tranzport_write */ -static ssize_t usb_tranzport_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) +static ssize_t usb_tranzport_write(struct file *file, + const char __user *buffer, size_t count, + loff_t *ppos) { struct usb_tranzport *dev; size_t bytes_to_write; @@ -718,7 +687,6 @@ static ssize_t usb_tranzport_write(struct file *file, const char __user *buffer, retval = -ERESTARTSYS; goto exit; } - /* verify that the device wasn't unplugged */ if (dev->intf == NULL) { retval = -ENODEV; @@ -732,18 +700,24 @@ static ssize_t usb_tranzport_write(struct file *file, const char __user *buffer, retval = -EAGAIN; goto unlock_exit; } - retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy); - if (retval < 0) { + retval = wait_event_interruptible(dev->write_wait, + !dev->interrupt_out_busy); + if (retval < 0) goto unlock_exit; - } } /* write the data into interrupt_out_buffer from userspace */ - bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); + bytes_to_write = min(count, + write_buffer_size * + dev->interrupt_out_endpoint_size); if (bytes_to_write < count) - dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write); + dev_warn(&dev->intf->dev, + "Write buffer overflow, %zd bytes dropped\n", + count - bytes_to_write); - dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write); + dbg_info(&dev->intf->dev, + "%s: count = %zd, bytes_to_write = %zd\n", __func__, + count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { retval = -EFAULT; @@ -757,14 +731,13 @@ static ssize_t usb_tranzport_write(struct file *file, const char __user *buffer, /* send off the urb */ usb_fill_int_urb(dev->interrupt_out_urb, - interface_to_usbdev(dev->intf), - usb_sndintpipe(interface_to_usbdev(dev->intf), - dev->interrupt_out_endpoint->bEndpointAddress), - dev->interrupt_out_buffer, - bytes_to_write, - usb_tranzport_interrupt_out_callback, - dev, - dev->interrupt_out_interval); + interface_to_usbdev(dev->intf), + usb_sndintpipe(interface_to_usbdev(dev->intf), + dev->interrupt_out_endpoint-> + bEndpointAddress), + dev->interrupt_out_buffer, bytes_to_write, + usb_tranzport_interrupt_out_callback, dev, + dev->interrupt_out_interval); dev->interrupt_out_busy = 1; wmb(); @@ -787,12 +760,12 @@ exit: /* file operations needed when we register this driver */ static const struct file_operations usb_tranzport_fops = { - .owner = THIS_MODULE, - .read = usb_tranzport_read, - .write = usb_tranzport_write, - .open = usb_tranzport_open, - .release = usb_tranzport_release, - .poll = usb_tranzport_poll, + .owner = THIS_MODULE, + .read = usb_tranzport_read, + .write = usb_tranzport_write, + .open = usb_tranzport_open, + .release = usb_tranzport_release, + .poll = usb_tranzport_poll, }; /* @@ -800,20 +773,19 @@ static const struct file_operations usb_tranzport_fops = { * and to have the device registered with the driver core */ static struct usb_class_driver usb_tranzport_class = { - .name = "tranzport%d", - .fops = &usb_tranzport_fops, - .minor_base = USB_TRANZPORT_MINOR_BASE, + .name = "tranzport%d", + .fops = &usb_tranzport_fops, + .minor_base = USB_TRANZPORT_MINOR_BASE, }; - /** * usb_tranzport_probe * * Called by the usb core when a new device is connected that it thinks * this driver might be interested in. */ -static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ +static int usb_tranzport_probe(struct usb_interface *intf, + const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); struct usb_tranzport *dev = NULL; struct usb_host_interface *iface_desc; @@ -824,7 +796,7 @@ static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_devi /* allocate memory for our device state and intialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { dev_err(&intf->dev, "Out of memory\n"); goto exit; @@ -851,25 +823,33 @@ static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_devi goto error; } if (dev->interrupt_out_endpoint == NULL) - dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); + dev_warn(&intf->dev, + "Interrupt out endpoint not found" + "(using control endpoint instead)\n"); - - dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); + dev->interrupt_in_endpoint_size = + le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); if (dev->interrupt_in_endpoint_size != 8) - dev_warn(&intf->dev, "Interrupt in endpoint size is not 8!\n"); + dev_warn(&intf->dev, "Interrupt in endpoint size is not 8!\n"); - if(ring_buffer_size == 0) { ring_buffer_size = RING_BUFFER_SIZE; } - true_size = min(ring_buffer_size,RING_BUFFER_SIZE); - /* FIXME - there are more usb_alloc routines for dma correctness. Needed? */ + if (ring_buffer_size == 0) + ring_buffer_size = RING_BUFFER_SIZE; + true_size = min(ring_buffer_size, RING_BUFFER_SIZE); - dev->ring_buffer = kmalloc((true_size*sizeof(struct tranzport_cmd))+8, GFP_KERNEL); + /* FIXME - there are more usb_alloc routines for dma correctness. + Needed? */ + + dev->ring_buffer = + kmalloc((true_size * sizeof(struct tranzport_cmd)) + 8, GFP_KERNEL); if (!dev->ring_buffer) { - dev_err(&intf->dev, "Couldn't allocate ring_buffer of size %d\n",true_size); + dev_err(&intf->dev, + "Couldn't allocate ring_buffer size %d\n", true_size); goto error; } - dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); + dev->interrupt_in_buffer = + kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); if (!dev->interrupt_in_buffer) { dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n"); goto error; @@ -879,13 +859,18 @@ static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_devi dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n"); goto error; } - dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) : - udev->descriptor.bMaxPacketSize0; + dev->interrupt_out_endpoint_size = + dev->interrupt_out_endpoint ? + le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) : + udev->descriptor.bMaxPacketSize0; - if (dev->interrupt_out_endpoint_size !=8) - dev_warn(&intf->dev, "Interrupt out endpoint size is not 8!)\n"); + if (dev->interrupt_out_endpoint_size != 8) + dev_warn(&intf->dev, + "Interrupt out endpoint size is not 8!)\n"); - dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL); + dev->interrupt_out_buffer = + kmalloc(write_buffer_size * dev->interrupt_out_endpoint_size, + GFP_KERNEL); if (!dev->interrupt_out_buffer) { dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n"); goto error; @@ -895,9 +880,18 @@ static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_devi dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n"); goto error; } - dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; - if (dev->interrupt_out_endpoint) - dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; + dev->interrupt_in_interval = + min_interrupt_in_interval > + dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval + : dev->interrupt_in_endpoint->bInterval; + + if (dev->interrupt_out_endpoint) { + dev->interrupt_out_interval = + min_interrupt_out_interval > + dev->interrupt_out_endpoint->bInterval ? + min_interrupt_out_interval : + dev->interrupt_out_endpoint->bInterval; + } /* we can register the device now, as it is ready */ usb_set_intfdata(intf, dev); @@ -905,35 +899,33 @@ static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_devi retval = usb_register_dev(intf, &usb_tranzport_class); if (retval) { /* something prevented us from registering this driver */ - dev_err(&intf->dev, "Not able to get a minor for this device.\n"); + dev_err(&intf->dev, + "Not able to get a minor for this device.\n"); usb_set_intfdata(intf, NULL); goto error; } - if((retval = device_create_file(&intf->dev, &dev_attr_LightRecord))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackrec))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackmute))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_LightTracksolo))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_LightAnysolo))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_LightLoop))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_LightPunch))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_wheel))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_event))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_dump_state))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_compress_wheel))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_enable))) goto error; - if((retval = device_create_file(&intf->dev, &dev_attr_offline))) goto error; + retval = device_create_file(&intf->dev, &dev_attr_compress_wheel); + if (retval) + goto error; + retval = device_create_file(&intf->dev, &dev_attr_enable); + if (retval) + goto error; + retval = device_create_file(&intf->dev, &dev_attr_offline); + if (retval) + goto error; /* let the user know what node this device is now attached to */ - dev_info(&intf->dev, "Tranzport Device #%d now attached to major %d minor %d\n", - (intf->minor - USB_TRANZPORT_MINOR_BASE), USB_MAJOR, intf->minor); + dev_info(&intf->dev, + "Tranzport Device #%d now attached to major %d minor %d\n", + (intf->minor - USB_TRANZPORT_MINOR_BASE), USB_MAJOR, + intf->minor); exit: return retval; error: usb_tranzport_delete(dev); - return retval; } @@ -966,15 +958,15 @@ static void usb_tranzport_disconnect(struct usb_interface *intf) mutex_unlock(&disconnect_mutex); dev_info(&intf->dev, "Tranzport Surface #%d now disconnected\n", - (minor - USB_TRANZPORT_MINOR_BASE)); + (minor - USB_TRANZPORT_MINOR_BASE)); } /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver usb_tranzport_driver = { - .name = "tranzport", - .probe = usb_tranzport_probe, - .disconnect = usb_tranzport_disconnect, - .id_table = usb_tranzport_table, + .name = "tranzport", + .probe = usb_tranzport_probe, + .disconnect = usb_tranzport_disconnect, + .id_table = usb_tranzport_table, }; /** @@ -987,14 +979,14 @@ static int __init usb_tranzport_init(void) /* register this driver with the USB subsystem */ retval = usb_register(&usb_tranzport_driver); if (retval) - err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval); - + err("usb_register failed for the " __FILE__ + " driver. Error number %d\n", retval); return retval; } - /** * usb_tranzport_exit */ + static void __exit usb_tranzport_exit(void) { /* deregister this driver with the USB subsystem */ @@ -1003,4 +995,3 @@ static void __exit usb_tranzport_exit(void) module_init(usb_tranzport_init); module_exit(usb_tranzport_exit); - diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c index 868edb65e7bf..06cacd37bbd8 100644 --- a/drivers/staging/go7007/go7007-v4l2.c +++ b/drivers/staging/go7007/go7007-v4l2.c @@ -1827,7 +1827,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { static struct video_device go7007_template = { .name = "go7007", - .vfl_type = VID_TYPE_CAPTURE, .fops = &go7007_fops, .minor = -1, .release = go7007_vfl_release, diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c index fb6845e37884..d333ea2cd774 100644 --- a/drivers/staging/go7007/s2250-board.c +++ b/drivers/staging/go7007/s2250-board.c @@ -149,7 +149,7 @@ static int go7007_usb_vendor_request(struct go7007 *go, u16 request, static int write_reg(struct i2c_client *client, u8 reg, u8 value) { struct go7007 *go = i2c_get_adapdata(client->adapter); - struct go7007_usb *usb = go->hpi_context; + struct go7007_usb *usb; int rc; int dev_addr = client->addr; u8 *buf; @@ -164,8 +164,10 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value) if (buf == NULL) return -ENOMEM; + usb = go->hpi_context; if (down_interruptible(&usb->i2c_lock) != 0) { printk(KERN_INFO "i2c lock failed\n"); + kfree(buf); return -EINTR; } rc = go7007_usb_vendor_request(go, 0x55, dev_addr, @@ -181,7 +183,7 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value) static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val) { struct go7007 *go = i2c_get_adapdata(client->adapter); - struct go7007_usb *usb = go->hpi_context; + struct go7007_usb *usb; u8 *buf; struct s2250 *dec = i2c_get_clientdata(client); @@ -200,6 +202,7 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val) memset(buf, 0xcd, 6); + usb = go->hpi_context; if (down_interruptible(&usb->i2c_lock) != 0) { printk(KERN_INFO "i2c lock failed\n"); return -EINTR; diff --git a/drivers/staging/heci/Kconfig b/drivers/staging/heci/Kconfig new file mode 100644 index 000000000000..ae8d588d3a27 --- /dev/null +++ b/drivers/staging/heci/Kconfig @@ -0,0 +1,6 @@ +config HECI + tristate "Intel Management Engine Interface (MEI) Support" + ---help--- + The Intel Management Engine Interface (Intel MEI) driver allows + applications to access the Active Management Technology + firmware and other Management Engine sub-systems. diff --git a/drivers/staging/heci/Makefile b/drivers/staging/heci/Makefile new file mode 100644 index 000000000000..0524856fa3ab --- /dev/null +++ b/drivers/staging/heci/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_HECI) += heci.o + +heci-objs := \ + heci_init.o \ + interrupt.o \ + heci_interface.o \ + io_heci.o \ + heci_main.o + diff --git a/drivers/staging/heci/TODO b/drivers/staging/heci/TODO new file mode 100644 index 000000000000..f86715d631c4 --- /dev/null +++ b/drivers/staging/heci/TODO @@ -0,0 +1,6 @@ +TODO: + - fix user/kernel pointer mess in the ioctl handlers as pointed + out by sparse. + - resolve the ioctls and see if most of them can just be simple + sysfs files + - fix locking issues that sparse points out at the least. diff --git a/drivers/staging/heci/heci.h b/drivers/staging/heci/heci.h new file mode 100644 index 000000000000..14192e0cc227 --- /dev/null +++ b/drivers/staging/heci/heci.h @@ -0,0 +1,176 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2008 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifndef _HECI_H_ +#define _HECI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "heci_data_structures.h" + +extern const struct guid heci_pthi_guid; +extern const struct guid heci_wd_guid; +extern const __u8 heci_start_wd_params[]; +extern const __u8 heci_stop_wd_params[]; +extern const __u8 heci_wd_state_independence_msg[3][4]; + +/* + * heci device ID + */ +#define HECI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */ +#define HECI_DEV_ID_82G35 0x2984 /* 82G35 Express */ +#define HECI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */ +#define HECI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */ + +#define HECI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */ +#define HECI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */ + +#define HECI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */ +#define HECI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */ +#define HECI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */ +#define HECI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */ +#define HECI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */ + +#define HECI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */ +#define HECI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */ +#define HECI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */ +#define HECI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */ +#define HECI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */ + +#define HECI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */ +#define HECI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */ +#define HECI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */ +#define HECI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */ + +#define HECI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */ +#define HECI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */ +#define HECI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */ +#define HECI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */ + +/* + * heci init function prototypes + */ +struct iamt_heci_device *init_heci_device(struct pci_dev *pdev); +void heci_reset(struct iamt_heci_device *dev, int interrupts); +int heci_hw_init(struct iamt_heci_device *dev); +int heci_task_initialize_clients(void *data); +int heci_initialize_clients(struct iamt_heci_device *dev); +struct heci_file_private *heci_alloc_file_private(struct file *file); +int heci_disconnect_host_client(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); +void heci_initialize_list(struct io_heci_list *list, + struct iamt_heci_device *dev); +void heci_flush_list(struct io_heci_list *list, + struct heci_file_private *file_ext); +void heci_flush_queues(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); + +void heci_remove_client_from_file_list(struct iamt_heci_device *dev, + __u8 host_client_id); + +/* + * interrupt function prototype + */ +irqreturn_t heci_isr_interrupt(int irq, void *dev_id); + +void heci_wd_timer(unsigned long data); + +/* + * input output function prototype + */ +int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num, + struct heci_message_data __user *u_msg, + struct heci_message_data k_msg, + struct heci_file_private *file_ext); + +int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num, + struct heci_message_data __user *u_msg, + struct heci_message_data k_msg, + struct file *file); + +int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num, + struct heci_message_data k_msg, + struct heci_file_private *file_ext); + +int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num, + struct heci_message_data k_msg, + struct heci_file_private *file_ext); + +int heci_start_read(struct iamt_heci_device *dev, int if_num, + struct heci_file_private *file_ext); + +int pthi_write(struct iamt_heci_device *dev, + struct heci_cb_private *priv_cb); + +int pthi_read(struct iamt_heci_device *dev, int if_num, struct file *file, + char __user *ubuf, size_t length, loff_t *offset); + +struct heci_cb_private *find_pthi_read_list_entry( + struct iamt_heci_device *dev, + struct file *file); + +void run_next_iamthif_cmd(struct iamt_heci_device *dev); + +void heci_free_cb_private(struct heci_cb_private *priv_cb); + +/** + * heci_fe_same_id - tell if file private data have same id + * + * @fe1: private data of 1. file object + * @fe2: private data of 2. file object + * + * returns !=0 - if ids are the same, 0 - if differ. + */ +static inline int heci_fe_same_id(const struct heci_file_private *fe1, + const struct heci_file_private *fe2) +{ + return ((fe1->host_client_id == fe2->host_client_id) + && (fe1->me_client_id == fe2->me_client_id)); +} + +#endif /* _HECI_H_ */ diff --git a/drivers/staging/heci/heci_data_structures.h b/drivers/staging/heci/heci_data_structures.h new file mode 100644 index 000000000000..575e8f8e88a3 --- /dev/null +++ b/drivers/staging/heci/heci_data_structures.h @@ -0,0 +1,530 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2008 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifndef _HECI_DATA_STRUCTURES_H_ +#define _HECI_DATA_STRUCTURES_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * error code definition + */ +#define ESLOTS_OVERFLOW 1 +#define ECORRUPTED_MESSAGE_HEADER 1000 +#define ECOMPLETE_MESSAGE 1001 + +#define HECI_FC_MESSAGE_RESERVED_LENGTH 5 + +/* + * Number of queue lists used by this driver + */ +#define HECI_IO_LISTS_NUMBER 7 + +/* + * Maximum transmission unit (MTU) of heci messages + */ +#define IAMTHIF_MTU 4160 + + +/* + * HECI HW Section + */ + +/* HECI registers */ +/* H_CB_WW - Host Circular Buffer (CB) Write Window register */ +#define H_CB_WW 0 +/* H_CSR - Host Control Status register */ +#define H_CSR 4 +/* ME_CB_RW - ME Circular Buffer Read Window register (read only) */ +#define ME_CB_RW 8 +/* ME_CSR_HA - ME Control Status Host Access register (read only) */ +#define ME_CSR_HA 0xC + + +/* register bits of H_CSR (Host Control Status register) */ +/* Host Circular Buffer Depth - maximum number of 32-bit entries in CB */ +#define H_CBD 0xFF000000 +/* Host Circular Buffer Write Pointer */ +#define H_CBWP 0x00FF0000 +/* Host Circular Buffer Read Pointer */ +#define H_CBRP 0x0000FF00 +/* Host Reset */ +#define H_RST 0x00000010 +/* Host Ready */ +#define H_RDY 0x00000008 +/* Host Interrupt Generate */ +#define H_IG 0x00000004 +/* Host Interrupt Status */ +#define H_IS 0x00000002 +/* Host Interrupt Enable */ +#define H_IE 0x00000001 + + +/* register bits of ME_CSR_HA (ME Control Status Host Access register) */ +/* ME CB (Circular Buffer) Depth HRA (Host Read Access) + * - host read only access to ME_CBD */ +#define ME_CBD_HRA 0xFF000000 +/* ME CB Write Pointer HRA - host read only access to ME_CBWP */ +#define ME_CBWP_HRA 0x00FF0000 +/* ME CB Read Pointer HRA - host read only access to ME_CBRP */ +#define ME_CBRP_HRA 0x0000FF00 +/* ME Reset HRA - host read only access to ME_RST */ +#define ME_RST_HRA 0x00000010 +/* ME Ready HRA - host read only access to ME_RDY */ +#define ME_RDY_HRA 0x00000008 +/* ME Interrupt Generate HRA - host read only access to ME_IG */ +#define ME_IG_HRA 0x00000004 +/* ME Interrupt Status HRA - host read only access to ME_IS */ +#define ME_IS_HRA 0x00000002 +/* ME Interrupt Enable HRA - host read only access to ME_IE */ +#define ME_IE_HRA 0x00000001 + +#define HECI_MINORS_BASE 1 +#define HECI_MINORS_COUNT 1 + +#define HECI_MINOR_NUMBER 1 +#define HECI_MAX_OPEN_HANDLE_COUNT 253 + +/* + * debug kernel print macro define + */ +extern int heci_debug; + +#define DBG(format, arg...) do { \ + if (heci_debug) \ + printk(KERN_INFO "heci: %s: " format, __func__, ## arg); \ +} while (0) + + +/* + * time to wait HECI become ready after init + */ +#define HECI_INTEROP_TIMEOUT (HZ * 7) + +/* + * watch dog definition + */ +#define HECI_WATCHDOG_DATA_SIZE 16 +#define HECI_START_WD_DATA_SIZE 20 +#define HECI_WD_PARAMS_SIZE 4 +#define HECI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) + +#define HECI_WD_HOST_CLIENT_ID 1 +#define HECI_IAMTHIF_HOST_CLIENT_ID 2 + +struct guid { + __u32 data1; + __u16 data2; + __u16 data3; + __u8 data4[8]; +}; + +/* File state */ +enum file_state { + HECI_FILE_INITIALIZING = 0, + HECI_FILE_CONNECTING, + HECI_FILE_CONNECTED, + HECI_FILE_DISCONNECTING, + HECI_FILE_DISCONNECTED +}; + +/* HECI device states */ +enum heci_states { + HECI_INITIALIZING = 0, + HECI_ENABLED, + HECI_RESETING, + HECI_DISABLED, + HECI_RECOVERING_FROM_RESET, + HECI_POWER_DOWN, + HECI_POWER_UP +}; + +enum iamthif_states { + HECI_IAMTHIF_IDLE, + HECI_IAMTHIF_WRITING, + HECI_IAMTHIF_FLOW_CONTROL, + HECI_IAMTHIF_READING, + HECI_IAMTHIF_READ_COMPLETE +}; + +enum heci_file_transaction_states { + HECI_IDLE, + HECI_WRITING, + HECI_WRITE_COMPLETE, + HECI_FLOW_CONTROL, + HECI_READING, + HECI_READ_COMPLETE +}; + +/* HECI CB */ +enum heci_cb_major_types { + HECI_READ = 0, + HECI_WRITE, + HECI_IOCTL, + HECI_OPEN, + HECI_CLOSE +}; + +/* HECI user data struct */ +struct heci_message_data { + __u32 size; + char *data; +} __attribute__((packed)); + +#define HECI_CONNECT_TIMEOUT 3 /* at least 2 seconds */ + +#define IAMTHIF_STALL_TIMER 12 /* seconds */ +#define IAMTHIF_READ_TIMER 15 /* seconds */ + +struct heci_cb_private { + struct list_head cb_list; + enum heci_cb_major_types major_file_operations; + void *file_private; + struct heci_message_data request_buffer; + struct heci_message_data response_buffer; + unsigned long information; + unsigned long read_time; + struct file *file_object; +}; + +/* Private file struct */ +struct heci_file_private { + struct list_head link; + struct file *file; + enum file_state state; + wait_queue_head_t tx_wait; + wait_queue_head_t rx_wait; + wait_queue_head_t wait; + spinlock_t file_lock; /* file lock */ + spinlock_t read_io_lock; /* read lock */ + spinlock_t write_io_lock; /* write lock */ + int read_pending; + int status; + /* ID of client connected */ + __u8 host_client_id; + __u8 me_client_id; + __u8 flow_ctrl_creds; + __u8 timer_count; + enum heci_file_transaction_states reading_state; + enum heci_file_transaction_states writing_state; + int sm_state; + struct heci_cb_private *read_cb; +}; + +struct io_heci_list { + struct heci_cb_private heci_cb; + int status; + struct iamt_heci_device *device_extension; +}; + +struct heci_driver_version { + __u8 major; + __u8 minor; + __u8 hotfix; + __u16 build; +} __attribute__((packed)); + + +struct heci_client { + __u32 max_msg_length; + __u8 protocol_version; +} __attribute__((packed)); + +/* + * HECI BUS Interface Section + */ +struct heci_msg_hdr { + __u32 me_addr:8; + __u32 host_addr:8; + __u32 length:9; + __u32 reserved:6; + __u32 msg_complete:1; +} __attribute__((packed)); + + +struct hbm_cmd { + __u8 cmd:7; + __u8 is_response:1; +} __attribute__((packed)); + + +struct heci_bus_message { + struct hbm_cmd cmd; + __u8 command_specific_data[]; +} __attribute__((packed)); + +struct hbm_version { + __u8 minor_version; + __u8 major_version; +} __attribute__((packed)); + +struct hbm_host_version_request { + struct hbm_cmd cmd; + __u8 reserved; + struct hbm_version host_version; +} __attribute__((packed)); + +struct hbm_host_version_response { + struct hbm_cmd cmd; + int host_version_supported; + struct hbm_version me_max_version; +} __attribute__((packed)); + +struct hbm_host_stop_request { + struct hbm_cmd cmd; + __u8 reason; + __u8 reserved[2]; +} __attribute__((packed)); + +struct hbm_host_stop_response { + struct hbm_cmd cmd; + __u8 reserved[3]; +} __attribute__((packed)); + +struct hbm_me_stop_request { + struct hbm_cmd cmd; + __u8 reason; + __u8 reserved[2]; +} __attribute__((packed)); + +struct hbm_host_enum_request { + struct hbm_cmd cmd; + __u8 reserved[3]; +} __attribute__((packed)); + +struct hbm_host_enum_response { + struct hbm_cmd cmd; + __u8 reserved[3]; + __u8 valid_addresses[32]; +} __attribute__((packed)); + +struct heci_client_properties { + struct guid protocol_name; + __u8 protocol_version; + __u8 max_number_of_connections; + __u8 fixed_address; + __u8 single_recv_buf; + __u32 max_msg_length; +} __attribute__((packed)); + +struct hbm_props_request { + struct hbm_cmd cmd; + __u8 address; + __u8 reserved[2]; +} __attribute__((packed)); + + +struct hbm_props_response { + struct hbm_cmd cmd; + __u8 address; + __u8 status; + __u8 reserved[1]; + struct heci_client_properties client_properties; +} __attribute__((packed)); + +struct hbm_client_connect_request { + struct hbm_cmd cmd; + __u8 me_addr; + __u8 host_addr; + __u8 reserved; +} __attribute__((packed)); + +struct hbm_client_connect_response { + struct hbm_cmd cmd; + __u8 me_addr; + __u8 host_addr; + __u8 status; +} __attribute__((packed)); + +struct hbm_client_disconnect_request { + struct hbm_cmd cmd; + __u8 me_addr; + __u8 host_addr; + __u8 reserved[1]; +} __attribute__((packed)); + +struct hbm_flow_control { + struct hbm_cmd cmd; + __u8 me_addr; + __u8 host_addr; + __u8 reserved[HECI_FC_MESSAGE_RESERVED_LENGTH]; +} __attribute__((packed)); + +struct heci_me_client { + struct heci_client_properties props; + __u8 client_id; + __u8 flow_ctrl_creds; +} __attribute__((packed)); + +/* private device struct */ +struct iamt_heci_device { + struct pci_dev *pdev; /* pointer to pci device struct */ + /* + * lists of queues + */ + /* array of pointers to aio lists */ + struct io_heci_list *io_list_array[HECI_IO_LISTS_NUMBER]; + struct io_heci_list read_list; /* driver read queue */ + struct io_heci_list write_list; /* driver write queue */ + struct io_heci_list write_waiting_list; /* write waiting queue */ + struct io_heci_list ctrl_wr_list; /* managed write IOCTL list */ + struct io_heci_list ctrl_rd_list; /* managed read IOCTL list */ + struct io_heci_list pthi_cmd_list; /* PTHI list for cmd waiting */ + + /* driver managed PTHI list for reading completed pthi cmd data */ + struct io_heci_list pthi_read_complete_list; + /* + * list of files + */ + struct list_head file_list; + /* + * memory of device + */ + unsigned int mem_base; + unsigned int mem_length; + void __iomem *mem_addr; + /* + * lock for the device + */ + spinlock_t device_lock; /* device lock*/ + struct work_struct work; + int recvd_msg; + + struct task_struct *reinit_tsk; + + struct timer_list wd_timer; + /* + * hw states of host and fw(ME) + */ + __u32 host_hw_state; + __u32 me_hw_state; + /* + * waiting queue for receive message from FW + */ + wait_queue_head_t wait_recvd_msg; + wait_queue_head_t wait_stop_wd; + /* + * heci device states + */ + enum heci_states heci_state; + int stop; + + __u32 extra_write_index; + __u32 rd_msg_buf[128]; /* used for control messages */ + __u32 wr_msg_buf[128]; /* used for control messages */ + __u32 ext_msg_buf[8]; /* for control responses */ + __u32 rd_msg_hdr; + + struct hbm_version version; + + int host_buffer_is_empty; + struct heci_file_private wd_file_ext; + struct heci_me_client *me_clients; /* Note: memory has to be allocated*/ + __u8 heci_me_clients[32]; /* list of existing clients */ + __u8 num_heci_me_clients; + __u8 heci_host_clients[32]; /* list of existing clients */ + __u8 current_host_client_id; + + int wd_pending; + int wd_stoped; + __u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */ + unsigned char wd_data[HECI_START_WD_DATA_SIZE]; + + + __u16 wd_due_counter; + int asf_mode; + int wd_bypass; /* if 1, don't refresh watchdog ME client */ + + struct file *iamthif_file_object; + struct heci_file_private iamthif_file_ext; + int iamthif_ioctl; + int iamthif_canceled; + __u32 iamthif_timer; + __u32 iamthif_stall_timer; + unsigned char iamthif_msg_buf[IAMTHIF_MTU]; + __u32 iamthif_msg_buf_size; + __u32 iamthif_msg_buf_index; + int iamthif_flow_control_pending; + enum iamthif_states iamthif_state; + + struct heci_cb_private *iamthif_current_cb; + __u8 write_hang; + int need_reset; + long open_handle_count; + +}; + +/** + * read_heci_register - Read a byte from the heci device + * + * @dev: the device structure + * @offset: offset from which to read the data + * + * returns the byte read. + */ +static inline __u32 read_heci_register(struct iamt_heci_device *dev, + unsigned long offset) +{ + return readl(dev->mem_addr + offset); +} + +/** + * write_heci_register - Write 4 bytes to the heci device + * + * @dev: the device structure + * @offset: offset from which to write the data + * @value: the byte to write + */ +static inline void write_heci_register(struct iamt_heci_device *dev, + unsigned long offset, __u32 value) +{ + writel(value, dev->mem_addr + offset); +} + +#endif /* _HECI_DATA_STRUCTURES_H_ */ diff --git a/drivers/staging/heci/heci_init.c b/drivers/staging/heci/heci_init.c new file mode 100644 index 000000000000..a8a0da910cfb --- /dev/null +++ b/drivers/staging/heci/heci_init.c @@ -0,0 +1,1077 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2008 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "heci_data_structures.h" +#include "heci_interface.h" +#include "heci.h" + + +const __u8 heci_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; +const __u8 heci_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; + +const __u8 heci_wd_state_independence_msg[3][4] = { + {0x05, 0x02, 0x51, 0x10}, + {0x05, 0x02, 0x52, 0x10}, + {0x07, 0x02, 0x01, 0x10} +}; + +static const struct guid heci_asf_guid = { + 0x75B30CD6, 0xA29E, 0x4AF7, + {0xA7, 0x12, 0xE6, 0x17, 0x43, 0x93, 0xC8, 0xA6} +}; +const struct guid heci_wd_guid = { + 0x05B79A6F, 0x4628, 0x4D7F, + {0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB} +}; +const struct guid heci_pthi_guid = { + 0x12f80028, 0xb4b7, 0x4b2d, + {0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c} +}; + + +/* + * heci init function prototypes + */ +static void heci_check_asf_mode(struct iamt_heci_device *dev); +static int host_start_message(struct iamt_heci_device *dev); +static int host_enum_clients_message(struct iamt_heci_device *dev); +static int allocate_me_clients_storage(struct iamt_heci_device *dev); +static void host_init_wd(struct iamt_heci_device *dev); +static void host_init_iamthif(struct iamt_heci_device *dev); +static int heci_wait_event_int_timeout(struct iamt_heci_device *dev, + long timeout); + + +/** + * heci_initialize_list - Sets up a queue list. + * + * @list: An instance of our list structure + * @dev: Device object for our driver + */ +void heci_initialize_list(struct io_heci_list *list, + struct iamt_heci_device *dev) +{ + /* initialize our queue list */ + INIT_LIST_HEAD(&list->heci_cb.cb_list); + list->status = 0; + list->device_extension = dev; +} + +/** + * heci_flush_queues - flush our queues list belong to file_ext. + * + * @dev: Device object for our driver + * @file_ext: private data of the file object + */ +void heci_flush_queues(struct iamt_heci_device *dev, + struct heci_file_private *file_ext) +{ + int i; + + if (!dev || !file_ext) + return; + + /* flush our queue list belong to file_ext */ + for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) { + DBG("remove list entry belong to file_ext\n"); + heci_flush_list(dev->io_list_array[i], file_ext); + } +} + + +/** + * heci_flush_list - remove list entry belong to file_ext. + * + * @list: An instance of our list structure + * @file_ext: private data of the file object + */ +void heci_flush_list(struct io_heci_list *list, + struct heci_file_private *file_ext) +{ + struct heci_file_private *file_ext_tmp; + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; + + if (!list || !file_ext) + return; + + if (list->status != 0) + return; + + if (list_empty(&list->heci_cb.cb_list)) + return; + + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &list->heci_cb.cb_list, cb_list) { + if (priv_cb_pos) { + file_ext_tmp = (struct heci_file_private *) + priv_cb_pos->file_private; + if (file_ext_tmp) { + if (heci_fe_same_id(file_ext, file_ext_tmp)) + list_del(&priv_cb_pos->cb_list); + } + } + } +} + +/** + * heci_reset_iamthif_params - initializes heci device iamthif + * + * @dev: The heci device structure + */ +static void heci_reset_iamthif_params(struct iamt_heci_device *dev) +{ + /* reset iamthif parameters. */ + dev->iamthif_current_cb = NULL; + dev->iamthif_msg_buf_size = 0; + dev->iamthif_msg_buf_index = 0; + dev->iamthif_canceled = 0; + dev->iamthif_file_ext.file = NULL; + dev->iamthif_ioctl = 0; + dev->iamthif_state = HECI_IAMTHIF_IDLE; + dev->iamthif_timer = 0; +} + +/** + * init_heci_device - allocates and initializes the heci device structure + * + * @pdev: The pci device structure + * + * returns The heci_device_device pointer on success, NULL on failure. + */ +struct iamt_heci_device *init_heci_device(struct pci_dev *pdev) +{ + int i; + struct iamt_heci_device *dev; + + dev = kzalloc(sizeof(struct iamt_heci_device), GFP_KERNEL); + if (!dev) + return NULL; + + /* setup our list array */ + dev->io_list_array[0] = &dev->read_list; + dev->io_list_array[1] = &dev->write_list; + dev->io_list_array[2] = &dev->write_waiting_list; + dev->io_list_array[3] = &dev->ctrl_wr_list; + dev->io_list_array[4] = &dev->ctrl_rd_list; + dev->io_list_array[5] = &dev->pthi_cmd_list; + dev->io_list_array[6] = &dev->pthi_read_complete_list; + INIT_LIST_HEAD(&dev->file_list); + INIT_LIST_HEAD(&dev->wd_file_ext.link); + INIT_LIST_HEAD(&dev->iamthif_file_ext.link); + spin_lock_init(&dev->device_lock); + init_waitqueue_head(&dev->wait_recvd_msg); + init_waitqueue_head(&dev->wait_stop_wd); + dev->heci_state = HECI_INITIALIZING; + dev->iamthif_state = HECI_IAMTHIF_IDLE; + + /* init work for schedule work */ + INIT_WORK(&dev->work, NULL); + for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) + heci_initialize_list(dev->io_list_array[i], dev); + dev->pdev = pdev; + return dev; +} + + + + +static int heci_wait_event_int_timeout(struct iamt_heci_device *dev, + long timeout) +{ + return wait_event_interruptible_timeout(dev->wait_recvd_msg, + (dev->recvd_msg), timeout); +} + +/** + * heci_hw_init - init host and fw to start work. + * + * @dev: Device object for our driver + * + * returns 0 on success, <0 on failure. + */ +int heci_hw_init(struct iamt_heci_device *dev) +{ + int err = 0; + + dev->host_hw_state = read_heci_register(dev, H_CSR); + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); + DBG("host_hw_state = 0x%08x, mestate = 0x%08x.\n", + dev->host_hw_state, dev->me_hw_state); + + if ((dev->host_hw_state & H_IS) == H_IS) { + /* acknowledge interrupt and stop interupts */ + heci_set_csr_register(dev); + } + dev->recvd_msg = 0; + DBG("reset in start the heci device.\n"); + + heci_reset(dev, 1); + + DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", + dev->host_hw_state, dev->me_hw_state); + + /* wait for ME to turn on ME_RDY */ + if (!dev->recvd_msg) + err = heci_wait_event_int_timeout(dev, HECI_INTEROP_TIMEOUT); + + if (!err && !dev->recvd_msg) { + dev->heci_state = HECI_DISABLED; + DBG("wait_event_interruptible_timeout failed" + "on wait for ME to turn on ME_RDY.\n"); + return -ENODEV; + } else { + if (!(((dev->host_hw_state & H_RDY) == H_RDY) + && ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { + dev->heci_state = HECI_DISABLED; + DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", + dev->host_hw_state, + dev->me_hw_state); + + if (!(dev->host_hw_state & H_RDY) != H_RDY) + DBG("host turn off H_RDY.\n"); + + if (!(dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) + DBG("ME turn off ME_RDY.\n"); + + printk(KERN_ERR + "heci: link layer initialization failed.\n"); + return -ENODEV; + } + } + dev->recvd_msg = 0; + DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", + dev->host_hw_state, dev->me_hw_state); + DBG("ME turn on ME_RDY and host turn on H_RDY.\n"); + printk(KERN_INFO "heci: link layer has been established.\n"); + return 0; +} + +/** + * heci_hw_reset - reset fw via heci csr register. + * + * @dev: Device object for our driver + * @interrupts: if interrupt should be enable after reset. + */ +static void heci_hw_reset(struct iamt_heci_device *dev, int interrupts) +{ + dev->host_hw_state |= (H_RST | H_IG); + + if (interrupts) + heci_csr_enable_interrupts(dev); + else + heci_csr_disable_interrupts(dev); + + BUG_ON((dev->host_hw_state & H_RST) != H_RST); + BUG_ON((dev->host_hw_state & H_RDY) != 0); +} + +/** + * heci_reset - reset host and fw. + * + * @dev: Device object for our driver + * @interrupts: if interrupt should be enable after reset. + */ +void heci_reset(struct iamt_heci_device *dev, int interrupts) +{ + struct heci_file_private *file_pos = NULL; + struct heci_file_private *file_next = NULL; + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; + int unexpected = 0; + + if (dev->heci_state == HECI_RECOVERING_FROM_RESET) { + dev->need_reset = 1; + return; + } + + if (dev->heci_state != HECI_INITIALIZING && + dev->heci_state != HECI_DISABLED && + dev->heci_state != HECI_POWER_DOWN && + dev->heci_state != HECI_POWER_UP) + unexpected = 1; + + if (dev->reinit_tsk != NULL) { + kthread_stop(dev->reinit_tsk); + dev->reinit_tsk = NULL; + } + + dev->host_hw_state = read_heci_register(dev, H_CSR); + + DBG("before reset host_hw_state = 0x%08x.\n", + dev->host_hw_state); + + heci_hw_reset(dev, interrupts); + + dev->host_hw_state &= ~H_RST; + dev->host_hw_state |= H_IG; + + write_heci_register(dev, H_CSR, dev->host_hw_state); + + DBG("currently saved host_hw_state = 0x%08x.\n", + dev->host_hw_state); + + dev->need_reset = 0; + + if (dev->heci_state != HECI_INITIALIZING) { + if ((dev->heci_state != HECI_DISABLED) && + (dev->heci_state != HECI_POWER_DOWN)) + dev->heci_state = HECI_RESETING; + + list_for_each_entry_safe(file_pos, + file_next, &dev->file_list, link) { + file_pos->state = HECI_FILE_DISCONNECTED; + file_pos->flow_ctrl_creds = 0; + file_pos->read_cb = NULL; + file_pos->timer_count = 0; + } + /* remove entry if already in list */ + DBG("list del iamthif and wd file list.\n"); + heci_remove_client_from_file_list(dev, + dev->wd_file_ext.host_client_id); + + heci_remove_client_from_file_list(dev, + dev->iamthif_file_ext.host_client_id); + + heci_reset_iamthif_params(dev); + dev->wd_due_counter = 0; + dev->extra_write_index = 0; + } + + dev->num_heci_me_clients = 0; + dev->rd_msg_hdr = 0; + dev->stop = 0; + dev->wd_pending = 0; + + /* update the state of the registers after reset */ + dev->host_hw_state = read_heci_register(dev, H_CSR); + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); + + DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", + dev->host_hw_state, dev->me_hw_state); + + if (unexpected) + printk(KERN_WARNING "heci: unexpected reset.\n"); + + /* Wake up all readings so they can be interrupted */ + list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) { + if (&file_pos->rx_wait && + waitqueue_active(&file_pos->rx_wait)) { + printk(KERN_INFO "heci: Waking up client!\n"); + wake_up_interruptible(&file_pos->rx_wait); + } + } + /* remove all waiting requests */ + if (dev->write_list.status == 0 && + !list_empty(&dev->write_list.heci_cb.cb_list)) { + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &dev->write_list.heci_cb.cb_list, cb_list) { + if (priv_cb_pos) { + list_del(&priv_cb_pos->cb_list); + heci_free_cb_private(priv_cb_pos); + } + } + } +} + +/** + * heci_initialize_clients - heci communication initialization. + * + * @dev: Device object for our driver + */ +int heci_initialize_clients(struct iamt_heci_device *dev) +{ + int status; + + msleep(100); /* FW needs time to be ready to talk with us */ + DBG("link is established start sending messages.\n"); + /* link is established start sending messages. */ + status = host_start_message(dev); + if (status != 0) { + spin_lock_bh(&dev->device_lock); + dev->heci_state = HECI_DISABLED; + spin_unlock_bh(&dev->device_lock); + DBG("start sending messages failed.\n"); + return status; + } + + /* enumerate clients */ + status = host_enum_clients_message(dev); + if (status != 0) { + spin_lock_bh(&dev->device_lock); + dev->heci_state = HECI_DISABLED; + spin_unlock_bh(&dev->device_lock); + DBG("enum clients failed.\n"); + return status; + } + /* allocate storage for ME clients representation */ + status = allocate_me_clients_storage(dev); + if (status != 0) { + spin_lock_bh(&dev->device_lock); + dev->num_heci_me_clients = 0; + dev->heci_state = HECI_DISABLED; + spin_unlock_bh(&dev->device_lock); + DBG("allocate clients failed.\n"); + return status; + } + + heci_check_asf_mode(dev); + /*heci initialization wd */ + host_init_wd(dev); + /*heci initialization iamthif client */ + host_init_iamthif(dev); + + spin_lock_bh(&dev->device_lock); + if (dev->need_reset) { + dev->need_reset = 0; + dev->heci_state = HECI_DISABLED; + spin_unlock_bh(&dev->device_lock); + return -ENODEV; + } + + memset(dev->heci_host_clients, 0, sizeof(dev->heci_host_clients)); + dev->open_handle_count = 0; + dev->heci_host_clients[0] |= 7; + dev->current_host_client_id = 3; + dev->heci_state = HECI_ENABLED; + spin_unlock_bh(&dev->device_lock); + DBG("initialization heci clients successful.\n"); + return 0; +} + +/** + * heci_task_initialize_clients - heci reinitialization task + * + * @data: Device object for our driver + */ +int heci_task_initialize_clients(void *data) +{ + int ret; + struct iamt_heci_device *dev = (struct iamt_heci_device *) data; + + spin_lock_bh(&dev->device_lock); + if (dev->reinit_tsk != NULL) { + spin_unlock_bh(&dev->device_lock); + DBG("reinit task already started.\n"); + return 0; + } + dev->reinit_tsk = current; + current->flags |= PF_NOFREEZE; + spin_unlock_bh(&dev->device_lock); + + ret = heci_initialize_clients(dev); + + spin_lock_bh(&dev->device_lock); + dev->reinit_tsk = NULL; + spin_unlock_bh(&dev->device_lock); + + return ret; +} + +/** + * host_start_message - heci host send start message. + * + * @dev: Device object for our driver + * + * returns 0 on success, <0 on failure. + */ +static int host_start_message(struct iamt_heci_device *dev) +{ + long timeout = 60; /* 60 second */ + + struct heci_msg_hdr *heci_hdr; + struct hbm_host_version_request *host_start_req; + struct hbm_host_stop_request *host_stop_req; + int err = 0; + + /* host start message */ + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_host_version_request); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + host_start_req = + (struct hbm_host_version_request *) &dev->wr_msg_buf[1]; + memset(host_start_req, 0, sizeof(struct hbm_host_version_request)); + host_start_req->cmd.cmd = HOST_START_REQ_CMD; + host_start_req->host_version.major_version = HBM_MAJOR_VERSION; + host_start_req->host_version.minor_version = HBM_MINOR_VERSION; + dev->recvd_msg = 0; + if (!heci_write_message(dev, heci_hdr, + (unsigned char *) (host_start_req), + heci_hdr->length)) { + DBG("send version to fw fail.\n"); + return -ENODEV; + } + DBG("call wait_event_interruptible_timeout for response message.\n"); + /* wait for response */ + err = heci_wait_event_int_timeout(dev, timeout * HZ); + if (!err && !dev->recvd_msg) { + DBG("wait_timeout failed on host start response message.\n"); + return -ENODEV; + } + dev->recvd_msg = 0; + DBG("wait_timeout successful on host start response message.\n"); + if ((dev->version.major_version != HBM_MAJOR_VERSION) || + (dev->version.minor_version != HBM_MINOR_VERSION)) { + /* send stop message */ + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_host_stop_request); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + host_stop_req = + (struct hbm_host_stop_request *) &dev->wr_msg_buf[1]; + + memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request)); + host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD; + host_stop_req->reason = DRIVER_STOP_REQUEST; + heci_write_message(dev, heci_hdr, + (unsigned char *) (host_stop_req), + heci_hdr->length); + DBG("version mismatch.\n"); + return -ENODEV; + } + + return 0; +} + +/** + * host_enum_clients_message - host send enumeration client request message. + * + * @dev: Device object for our driver + * + * returns 0 on success, <0 on failure. + */ +static int host_enum_clients_message(struct iamt_heci_device *dev) +{ + long timeout = 5; /*5 second */ + struct heci_msg_hdr *heci_hdr; + struct hbm_host_enum_request *host_enum_req; + int err = 0; + int i, j; + + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + /* enumerate clients */ + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_host_enum_request); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1]; + memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request)); + host_enum_req->cmd.cmd = HOST_ENUM_REQ_CMD; + if (!heci_write_message(dev, heci_hdr, + (unsigned char *) (host_enum_req), + heci_hdr->length)) { + DBG("send enumeration request failed.\n"); + return -ENODEV; + } + /* wait for response */ + dev->recvd_msg = 0; + err = heci_wait_event_int_timeout(dev, timeout * HZ); + if (!err && !dev->recvd_msg) { + DBG("wait_event_interruptible_timeout failed " + "on enumeration clients response message.\n"); + return -ENODEV; + } + dev->recvd_msg = 0; + + spin_lock_bh(&dev->device_lock); + /* count how many ME clients we have */ + for (i = 0; i < sizeof(dev->heci_me_clients); i++) { + for (j = 0; j < 8; j++) { + if ((dev->heci_me_clients[i] & (1 << j)) != 0) + dev->num_heci_me_clients++; + + } + } + spin_unlock_bh(&dev->device_lock); + + return 0; +} + +/** + * host_client_properties - reads properties for client + * + * @dev: Device object for our driver + * @idx: client index in me client array + * @client_id: id of the client + * + * returns 0 on success, <0 on failure. + */ +static int host_client_properties(struct iamt_heci_device *dev, + struct heci_me_client *client) +{ + struct heci_msg_hdr *heci_hdr; + struct hbm_props_request *host_cli_req; + int err; + + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_props_request); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + host_cli_req = (struct hbm_props_request *) &dev->wr_msg_buf[1]; + memset(host_cli_req, 0, sizeof(struct hbm_props_request)); + host_cli_req->cmd.cmd = HOST_CLIENT_PROPERTEIS_REQ_CMD; + host_cli_req->address = client->client_id; + if (!heci_write_message(dev, heci_hdr, + (unsigned char *) (host_cli_req), + heci_hdr->length)) { + DBG("send props request failed.\n"); + return -ENODEV; + } + /* wait for response */ + dev->recvd_msg = 0; + err = heci_wait_event_int_timeout(dev, 10 * HZ); + if (!err && !dev->recvd_msg) { + DBG("wait failed on props resp msg.\n"); + return -ENODEV; + } + dev->recvd_msg = 0; + return 0; +} + +/** + * allocate_me_clients_storage - allocate storage for me clients + * + * @dev: Device object for our driver + * + * returns 0 on success, <0 on failure. + */ +static int allocate_me_clients_storage(struct iamt_heci_device *dev) +{ + struct heci_me_client *clients; + struct heci_me_client *client; + __u8 num, i, j; + int err; + + if (dev->num_heci_me_clients <= 0) + return 0; + + spin_lock_bh(&dev->device_lock); + kfree(dev->me_clients); + dev->me_clients = NULL; + spin_unlock_bh(&dev->device_lock); + + /* allocate storage for ME clients representation */ + clients = kcalloc(dev->num_heci_me_clients, + sizeof(struct heci_me_client), GFP_KERNEL); + if (!clients) { + DBG("memory allocation for ME clients failed.\n"); + return -ENOMEM; + } + + spin_lock_bh(&dev->device_lock); + dev->me_clients = clients; + spin_unlock_bh(&dev->device_lock); + + num = 0; + for (i = 0; i < sizeof(dev->heci_me_clients); i++) { + for (j = 0; j < 8; j++) { + if ((dev->heci_me_clients[i] & (1 << j)) != 0) { + client = &dev->me_clients[num]; + client->client_id = (i * 8) + j; + client->flow_ctrl_creds = 0; + err = host_client_properties(dev, client); + if (err != 0) { + spin_lock_bh(&dev->device_lock); + kfree(dev->me_clients); + dev->me_clients = NULL; + spin_unlock_bh(&dev->device_lock); + return err; + } + num++; + } + } + } + + return 0; +} + +/** + * heci_init_file_private - initializes private file structure. + * + * @priv: private file structure to be initialized + * @file: the file structure + */ +static void heci_init_file_private(struct heci_file_private *priv, + struct file *file) +{ + memset(priv, 0, sizeof(struct heci_file_private)); + spin_lock_init(&priv->file_lock); + spin_lock_init(&priv->read_io_lock); + spin_lock_init(&priv->write_io_lock); + init_waitqueue_head(&priv->wait); + init_waitqueue_head(&priv->rx_wait); + DBG("priv->rx_wait =%p\n", &priv->rx_wait); + init_waitqueue_head(&priv->tx_wait); + INIT_LIST_HEAD(&priv->link); + priv->reading_state = HECI_IDLE; + priv->writing_state = HECI_IDLE; +} + +/** + * heci_find_me_client - search for ME client guid + * sets client_id in heci_file_private if found + * @dev: Device object for our driver + * @priv: private file structure to set client_id in + * @cguid: searched guid of ME client + * @client_id: id of host client to be set in file private structure + * + * returns ME client index + */ +static __u8 heci_find_me_client(struct iamt_heci_device *dev, + struct heci_file_private *priv, + const struct guid *cguid, __u8 client_id) +{ + __u8 i; + + if ((dev == NULL) || (priv == NULL) || (cguid == NULL)) + return 0; + + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (memcmp(cguid, + &dev->me_clients[i].props.protocol_name, + sizeof(struct guid)) == 0) { + priv->me_client_id = dev->me_clients[i].client_id; + priv->state = HECI_FILE_CONNECTING; + priv->host_client_id = client_id; + + list_add_tail(&priv->link, &dev->file_list); + return i; + } + } + return 0; +} + +/** + * heci_check_asf_mode - check for ASF client + * + * @dev: Device object for our driver + */ +static void heci_check_asf_mode(struct iamt_heci_device *dev) +{ + __u8 i; + + spin_lock_bh(&dev->device_lock); + dev->asf_mode = 0; + /* find ME ASF client - otherwise assume AMT mode */ + DBG("find ME ASF client - otherwise assume AMT mode.\n"); + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (memcmp(&heci_asf_guid, + &dev->me_clients[i].props.protocol_name, + sizeof(struct guid)) == 0) { + dev->asf_mode = 1; + spin_unlock_bh(&dev->device_lock); + DBG("found ME ASF client.\n"); + return; + } + } + spin_unlock_bh(&dev->device_lock); + DBG("assume AMT mode.\n"); +} + +/** + * heci_connect_me_client - connect ME client + * @dev: Device object for our driver + * @priv: private file structure + * @timeout: connect timeout in seconds + * + * returns 1 - if connected, 0 - if not + */ +static __u8 heci_connect_me_client(struct iamt_heci_device *dev, + struct heci_file_private *priv, + long timeout) +{ + int err = 0; + + if ((dev == NULL) || (priv == NULL)) + return 0; + + if (!heci_connect(dev, priv)) { + DBG("failed to call heci_connect for client_id=%d.\n", + priv->host_client_id); + spin_lock_bh(&dev->device_lock); + heci_remove_client_from_file_list(dev, priv->host_client_id); + priv->state = HECI_FILE_DISCONNECTED; + spin_unlock_bh(&dev->device_lock); + return 0; + } + + err = wait_event_timeout(dev->wait_recvd_msg, + (HECI_FILE_CONNECTED == priv->state || + HECI_FILE_DISCONNECTED == priv->state), + timeout * HZ); + if (HECI_FILE_CONNECTED != priv->state) { + spin_lock_bh(&dev->device_lock); + heci_remove_client_from_file_list(dev, priv->host_client_id); + DBG("failed to connect client_id=%d state=%d.\n", + priv->host_client_id, priv->state); + if (err) + DBG("failed connect err=%08x\n", err); + priv->state = HECI_FILE_DISCONNECTED; + spin_unlock_bh(&dev->device_lock); + return 0; + } + DBG("successfully connected client_id=%d.\n", + priv->host_client_id); + return 1; +} + +/** + * host_init_wd - heci initialization wd. + * + * @dev: Device object for our driver + */ +static void host_init_wd(struct iamt_heci_device *dev) +{ + spin_lock_bh(&dev->device_lock); + + heci_init_file_private(&dev->wd_file_ext, NULL); + + /* look for WD client and connect to it */ + dev->wd_file_ext.state = HECI_FILE_DISCONNECTED; + dev->wd_timeout = 0; + + if (dev->asf_mode) { + memcpy(dev->wd_data, heci_stop_wd_params, HECI_WD_PARAMS_SIZE); + } else { + /* AMT mode */ + dev->wd_timeout = AMT_WD_VALUE; + DBG("dev->wd_timeout=%d.\n", dev->wd_timeout); + memcpy(dev->wd_data, heci_start_wd_params, HECI_WD_PARAMS_SIZE); + memcpy(dev->wd_data + HECI_WD_PARAMS_SIZE, + &dev->wd_timeout, sizeof(__u16)); + } + + /* find ME WD client */ + heci_find_me_client(dev, &dev->wd_file_ext, + &heci_wd_guid, HECI_WD_HOST_CLIENT_ID); + spin_unlock_bh(&dev->device_lock); + + DBG("check wd_file_ext\n"); + if (HECI_FILE_CONNECTING == dev->wd_file_ext.state) { + if (heci_connect_me_client(dev, &dev->wd_file_ext, 15) == 1) { + DBG("dev->wd_timeout=%d.\n", dev->wd_timeout); + if (dev->wd_timeout != 0) + dev->wd_due_counter = 1; + else + dev->wd_due_counter = 0; + DBG("successfully connected to WD client.\n"); + } + } else + DBG("failed to find WD client.\n"); + + + spin_lock_bh(&dev->device_lock); + dev->wd_timer.function = &heci_wd_timer; + dev->wd_timer.data = (unsigned long) dev; + spin_unlock_bh(&dev->device_lock); +} + + +/** + * host_init_iamthif - heci initialization iamthif client. + * + * @dev: Device object for our driver + * + */ +static void host_init_iamthif(struct iamt_heci_device *dev) +{ + __u8 i; + + spin_lock_bh(&dev->device_lock); + + heci_init_file_private(&dev->iamthif_file_ext, NULL); + dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTED; + + /* find ME PTHI client */ + i = heci_find_me_client(dev, &dev->iamthif_file_ext, + &heci_pthi_guid, HECI_IAMTHIF_HOST_CLIENT_ID); + if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTING) { + DBG("failed to find iamthif client.\n"); + spin_unlock_bh(&dev->device_lock); + return; + } + + BUG_ON(dev->me_clients[i].props.max_msg_length != IAMTHIF_MTU); + + spin_unlock_bh(&dev->device_lock); + if (heci_connect_me_client(dev, &dev->iamthif_file_ext, 15) == 1) { + DBG("connected to iamthif client.\n"); + dev->iamthif_state = HECI_IAMTHIF_IDLE; + } +} + +/** + * heci_alloc_file_private - allocates a private file structure and set it up. + * @file: the file structure + * + * returns The allocated file or NULL on failure + */ +struct heci_file_private *heci_alloc_file_private(struct file *file) +{ + struct heci_file_private *priv; + + priv = kmalloc(sizeof(struct heci_file_private), GFP_KERNEL); + if (!priv) + return NULL; + + heci_init_file_private(priv, file); + + return priv; +} + + + +/** + * heci_disconnect_host_client - send disconnect message to fw from host client. + * + * @dev: Device object for our driver + * @file_ext: private data of the file object + * + * returns 0 on success, <0 on failure. + */ +int heci_disconnect_host_client(struct iamt_heci_device *dev, + struct heci_file_private *file_ext) +{ + int rets, err; + long timeout = 15; /* 15 seconds */ + struct heci_cb_private *priv_cb; + + if ((!dev) || (!file_ext)) + return -ENODEV; + + if (file_ext->state != HECI_FILE_DISCONNECTING) + return 0; + + priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL); + if (!priv_cb) + return -ENOMEM; + + INIT_LIST_HEAD(&priv_cb->cb_list); + priv_cb->file_private = file_ext; + priv_cb->major_file_operations = HECI_CLOSE; + spin_lock_bh(&dev->device_lock); + if (dev->host_buffer_is_empty) { + dev->host_buffer_is_empty = 0; + if (heci_disconnect(dev, file_ext)) { + list_add_tail(&priv_cb->cb_list, + &dev->ctrl_rd_list.heci_cb.cb_list); + } else { + spin_unlock_bh(&dev->device_lock); + rets = -ENODEV; + DBG("failed to call heci_disconnect.\n"); + goto free; + } + } else { + DBG("add disconnect cb to control write list\n"); + list_add_tail(&priv_cb->cb_list, + &dev->ctrl_wr_list.heci_cb.cb_list); + } + spin_unlock_bh(&dev->device_lock); + + err = wait_event_timeout(dev->wait_recvd_msg, + (HECI_FILE_DISCONNECTED == file_ext->state), + timeout * HZ); + if (HECI_FILE_DISCONNECTED == file_ext->state) { + rets = 0; + DBG("successfully disconnected from fw client.\n"); + } else { + rets = -ENODEV; + if (HECI_FILE_DISCONNECTED != file_ext->state) + DBG("wrong status client disconnect.\n"); + + if (err) + DBG("wait failed disconnect err=%08x\n", err); + + DBG("failed to disconnect from fw client.\n"); + } + + spin_lock_bh(&dev->device_lock); + heci_flush_list(&dev->ctrl_rd_list, file_ext); + heci_flush_list(&dev->ctrl_wr_list, file_ext); + spin_unlock_bh(&dev->device_lock); +free: + heci_free_cb_private(priv_cb); + return rets; +} + +/** + * heci_remove_client_from_file_list - + * remove file private data from device file list + * + * @dev: Device object for our driver + * @host_client_id: host client id to be removed + */ +void heci_remove_client_from_file_list(struct iamt_heci_device *dev, + __u8 host_client_id) +{ + struct heci_file_private *file_pos = NULL; + struct heci_file_private *file_next = NULL; + list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) { + if (host_client_id == file_pos->host_client_id) { + DBG("remove host client = %d, ME client = %d\n", + file_pos->host_client_id, + file_pos->me_client_id); + list_del_init(&file_pos->link); + break; + } + } +} diff --git a/drivers/staging/heci/heci_interface.c b/drivers/staging/heci/heci_interface.c new file mode 100644 index 000000000000..c5f51a7ddf2c --- /dev/null +++ b/drivers/staging/heci/heci_interface.c @@ -0,0 +1,485 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2008 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + + +#include "heci.h" +#include "heci_interface.h" + + +/** + * heci_set_csr_register - write H_CSR register to the heci device + * + * @dev: device object for our driver + */ +void heci_set_csr_register(struct iamt_heci_device *dev) +{ + write_heci_register(dev, H_CSR, dev->host_hw_state); + dev->host_hw_state = read_heci_register(dev, H_CSR); +} + +/** + * heci_csr_enable_interrupts - enable heci device interrupts + * + * @dev: device object for our driver + */ +void heci_csr_enable_interrupts(struct iamt_heci_device *dev) +{ + dev->host_hw_state |= H_IE; + heci_set_csr_register(dev); +} + +/** + * heci_csr_disable_interrupts - disable heci device interrupts + * + * @dev: device object for our driver + */ +void heci_csr_disable_interrupts(struct iamt_heci_device *dev) +{ + dev->host_hw_state &= ~H_IE; + heci_set_csr_register(dev); +} + + +/** + * _host_get_filled_slots - get number of device filled buffer slots + * + * @device: the device structure + * + * returns numer of filled slots + */ +static unsigned char _host_get_filled_slots(const struct iamt_heci_device *dev) +{ + char read_ptr, write_ptr; + + read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8); + write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16); + + return (unsigned char) (write_ptr - read_ptr); +} + +/** + * host_buffer_is_empty - check if host buffer is empty. + * + * @dev: device object for our driver + * + * returns 1 if empty, 0 - otherwise. + */ +int host_buffer_is_empty(struct iamt_heci_device *dev) +{ + unsigned char filled_slots; + + dev->host_hw_state = read_heci_register(dev, H_CSR); + filled_slots = _host_get_filled_slots(dev); + + if (filled_slots > 0) + return 0; + + return 1; +} + +/** + * count_empty_write_slots - count write empty slots. + * + * @dev: device object for our driver + * + * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count + */ +__s32 count_empty_write_slots(const struct iamt_heci_device *dev) +{ + unsigned char buffer_depth, filled_slots, empty_slots; + + buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24); + filled_slots = _host_get_filled_slots(dev); + empty_slots = buffer_depth - filled_slots; + + if (filled_slots > buffer_depth) { + /* overflow */ + return -ESLOTS_OVERFLOW; + } + + return (__s32) empty_slots; +} + +/** + * heci_write_message - write a message to heci device. + * + * @dev: device object for our driver + * @heci_hdr: header of message + * @write_buffer: message buffer will be write + * @write_length: message size will be write + * + * returns 1 if success, 0 - otherwise. + */ +int heci_write_message(struct iamt_heci_device *dev, + struct heci_msg_hdr *header, + unsigned char *write_buffer, + unsigned long write_length) +{ + __u32 temp_msg = 0; + unsigned long bytes_written = 0; + unsigned char buffer_depth, filled_slots, empty_slots; + unsigned long dw_to_write; + + dev->host_hw_state = read_heci_register(dev, H_CSR); + DBG("host_hw_state = 0x%08x.\n", dev->host_hw_state); + DBG("heci_write_message header=%08x.\n", *((__u32 *) header)); + buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24); + filled_slots = _host_get_filled_slots(dev); + empty_slots = buffer_depth - filled_slots; + DBG("filled = %hu, empty = %hu.\n", filled_slots, empty_slots); + + dw_to_write = ((write_length + 3) / 4); + + if (dw_to_write > empty_slots) + return 0; + + write_heci_register(dev, H_CB_WW, *((__u32 *) header)); + + while (write_length >= 4) { + write_heci_register(dev, H_CB_WW, + *(__u32 *) (write_buffer + bytes_written)); + bytes_written += 4; + write_length -= 4; + } + + if (write_length > 0) { + memcpy(&temp_msg, &write_buffer[bytes_written], write_length); + write_heci_register(dev, H_CB_WW, temp_msg); + } + + dev->host_hw_state |= H_IG; + write_heci_register(dev, H_CSR, dev->host_hw_state); + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); + if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA) + return 0; + + dev->write_hang = 0; + return 1; +} + +/** + * count_full_read_slots - count read full slots. + * + * @dev: device object for our driver + * + * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count + */ +__s32 count_full_read_slots(struct iamt_heci_device *dev) +{ + char read_ptr, write_ptr; + unsigned char buffer_depth, filled_slots; + + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); + buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24); + read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8); + write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16); + filled_slots = (unsigned char) (write_ptr - read_ptr); + + if (filled_slots > buffer_depth) { + /* overflow */ + return -ESLOTS_OVERFLOW; + } + + DBG("filled_slots =%08x \n", filled_slots); + return (__s32) filled_slots; +} + +/** + * heci_read_slots - read a message from heci device. + * + * @dev: device object for our driver + * @buffer: message buffer will be write + * @buffer_length: message size will be read + */ +void heci_read_slots(struct iamt_heci_device *dev, + unsigned char *buffer, unsigned long buffer_length) +{ + __u32 i = 0; + unsigned char temp_buf[sizeof(__u32)]; + + while (buffer_length >= sizeof(__u32)) { + ((__u32 *) buffer)[i] = read_heci_register(dev, ME_CB_RW); + DBG("buffer[%d]= %d\n", i, ((__u32 *) buffer)[i]); + i++; + buffer_length -= sizeof(__u32); + } + + if (buffer_length > 0) { + *((__u32 *) &temp_buf) = read_heci_register(dev, ME_CB_RW); + memcpy(&buffer[i * 4], temp_buf, buffer_length); + } + + dev->host_hw_state |= H_IG; + heci_set_csr_register(dev); +} + +/** + * flow_ctrl_creds - check flow_control credentials. + * + * @dev: device object for our driver + * @file_ext: private data of the file object + * + * returns 1 if flow_ctrl_creds >0, 0 - otherwise. + */ +int flow_ctrl_creds(struct iamt_heci_device *dev, + struct heci_file_private *file_ext) +{ + __u8 i; + + if (!dev->num_heci_me_clients) + return 0; + + if (file_ext == NULL) + return 0; + + if (file_ext->flow_ctrl_creds > 0) + return 1; + + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (dev->me_clients[i].client_id == file_ext->me_client_id) { + if (dev->me_clients[i].flow_ctrl_creds > 0) { + BUG_ON(dev->me_clients[i].props.single_recv_buf + == 0); + return 1; + } + return 0; + } + } + BUG(); + return 0; +} + +/** + * flow_ctrl_reduce - reduce flow_control. + * + * @dev: device object for our driver + * @file_ext: private data of the file object + */ +void flow_ctrl_reduce(struct iamt_heci_device *dev, + struct heci_file_private *file_ext) +{ + __u8 i; + + if (!dev->num_heci_me_clients) + return; + + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (dev->me_clients[i].client_id == file_ext->me_client_id) { + if (dev->me_clients[i].props.single_recv_buf != 0) { + BUG_ON(dev->me_clients[i].flow_ctrl_creds <= 0); + dev->me_clients[i].flow_ctrl_creds--; + } else { + BUG_ON(file_ext->flow_ctrl_creds <= 0); + file_ext->flow_ctrl_creds--; + } + return; + } + } + BUG(); +} + +/** + * heci_send_flow_control - send flow control to fw. + * + * @dev: device object for our driver + * @file_ext: private data of the file object + * + * returns 1 if success, 0 - otherwise. + */ +int heci_send_flow_control(struct iamt_heci_device *dev, + struct heci_file_private *file_ext) +{ + struct heci_msg_hdr *heci_hdr; + struct hbm_flow_control *heci_flow_control; + + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_flow_control); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + heci_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1]; + memset(heci_flow_control, 0, sizeof(heci_flow_control)); + heci_flow_control->host_addr = file_ext->host_client_id; + heci_flow_control->me_addr = file_ext->me_client_id; + heci_flow_control->cmd.cmd = HECI_FLOW_CONTROL_CMD; + memset(heci_flow_control->reserved, 0, + sizeof(heci_flow_control->reserved)); + DBG("sending flow control host client = %d, me client = %d\n", + file_ext->host_client_id, file_ext->me_client_id); + if (!heci_write_message(dev, heci_hdr, + (unsigned char *) heci_flow_control, + sizeof(struct hbm_flow_control))) + return 0; + + return 1; + +} + +/** + * other_client_is_connecting - check if other + * client with the same client id is connected. + * + * @dev: device object for our driver + * @file_ext: private data of the file object + * + * returns 1 if other client is connected, 0 - otherwise. + */ +int other_client_is_connecting(struct iamt_heci_device *dev, + struct heci_file_private *file_ext) +{ + struct heci_file_private *file_pos = NULL; + struct heci_file_private *file_next = NULL; + + list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) { + if ((file_pos->state == HECI_FILE_CONNECTING) + && (file_pos != file_ext) + && file_ext->me_client_id == file_pos->me_client_id) + return 1; + + } + return 0; +} + +/** + * heci_send_wd - send watch dog message to fw. + * + * @dev: device object for our driver + * + * returns 1 if success, 0 - otherwise. + */ +int heci_send_wd(struct iamt_heci_device *dev) +{ + struct heci_msg_hdr *heci_hdr; + + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = dev->wd_file_ext.host_client_id; + heci_hdr->me_addr = dev->wd_file_ext.me_client_id; + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + if (!memcmp(dev->wd_data, heci_start_wd_params, + HECI_WD_PARAMS_SIZE)) { + heci_hdr->length = HECI_START_WD_DATA_SIZE; + } else { + BUG_ON(memcmp(dev->wd_data, heci_stop_wd_params, + HECI_WD_PARAMS_SIZE)); + heci_hdr->length = HECI_WD_PARAMS_SIZE; + } + + if (!heci_write_message(dev, heci_hdr, dev->wd_data, heci_hdr->length)) + return 0; + + return 1; +} + +/** + * heci_disconnect - send disconnect message to fw. + * + * @dev: device object for our driver + * @file_ext: private data of the file object + * + * returns 1 if success, 0 - otherwise. + */ +int heci_disconnect(struct iamt_heci_device *dev, + struct heci_file_private *file_ext) +{ + struct heci_msg_hdr *heci_hdr; + struct hbm_client_disconnect_request *heci_cli_disconnect; + + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_client_disconnect_request); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + heci_cli_disconnect = + (struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1]; + memset(heci_cli_disconnect, 0, sizeof(heci_cli_disconnect)); + heci_cli_disconnect->host_addr = file_ext->host_client_id; + heci_cli_disconnect->me_addr = file_ext->me_client_id; + heci_cli_disconnect->cmd.cmd = CLIENT_DISCONNECT_REQ_CMD; + heci_cli_disconnect->reserved[0] = 0; + + if (!heci_write_message(dev, heci_hdr, + (unsigned char *) heci_cli_disconnect, + sizeof(struct hbm_client_disconnect_request))) + return 0; + + return 1; +} + +/** + * heci_connect - send connect message to fw. + * + * @dev: device object for our driver + * @file_ext: private data of the file object + * + * returns 1 if success, 0 - otherwise. + */ +int heci_connect(struct iamt_heci_device *dev, + struct heci_file_private *file_ext) +{ + struct heci_msg_hdr *heci_hdr; + struct hbm_client_connect_request *heci_cli_connect; + + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_client_connect_request); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + heci_cli_connect = + (struct hbm_client_connect_request *) &dev->wr_msg_buf[1]; + heci_cli_connect->host_addr = file_ext->host_client_id; + heci_cli_connect->me_addr = file_ext->me_client_id; + heci_cli_connect->cmd.cmd = CLIENT_CONNECT_REQ_CMD; + heci_cli_connect->reserved = 0; + + if (!heci_write_message(dev, heci_hdr, + (unsigned char *) heci_cli_connect, + sizeof(struct hbm_client_connect_request))) + return 0; + + return 1; +} diff --git a/drivers/staging/heci/heci_interface.h b/drivers/staging/heci/heci_interface.h new file mode 100644 index 000000000000..37336ebc0a5b --- /dev/null +++ b/drivers/staging/heci/heci_interface.h @@ -0,0 +1,170 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2008 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + + +#ifndef _HECI_INTERFACE_H_ +#define _HECI_INTERFACE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "heci_data_structures.h" + + +#define HBM_MINOR_VERSION 0 +#define HBM_MAJOR_VERSION 1 +#define HBM_TIMEOUT 1 /* 1 second */ + + +#define HOST_START_REQ_CMD 0x01 +#define HOST_START_RES_CMD 0x81 + +#define HOST_STOP_REQ_CMD 0x02 +#define HOST_STOP_RES_CMD 0x82 + +#define ME_STOP_REQ_CMD 0x03 + +#define HOST_ENUM_REQ_CMD 0x04 +#define HOST_ENUM_RES_CMD 0x84 + +#define HOST_CLIENT_PROPERTEIS_REQ_CMD 0x05 +#define HOST_CLIENT_PROPERTEIS_RES_CMD 0x85 + +#define CLIENT_CONNECT_REQ_CMD 0x06 +#define CLIENT_CONNECT_RES_CMD 0x86 + +#define CLIENT_DISCONNECT_REQ_CMD 0x07 +#define CLIENT_DISCONNECT_RES_CMD 0x87 + +#define HECI_FLOW_CONTROL_CMD 0x08 + + +#define AMT_WD_VALUE 120 /* seconds */ + +#define HECI_WATCHDOG_DATA_SIZE 16 +#define HECI_START_WD_DATA_SIZE 20 +#define HECI_WD_PARAMS_SIZE 4 + +/* IOCTL commands */ +#define IOCTL_HECI_GET_VERSION \ + _IOWR('H' , 0x0, struct heci_message_data) +#define IOCTL_HECI_CONNECT_CLIENT \ + _IOWR('H' , 0x01, struct heci_message_data) +#define IOCTL_HECI_WD \ + _IOWR('H' , 0x02, struct heci_message_data) +#define IOCTL_HECI_BYPASS_WD \ + _IOWR('H' , 0x10, struct heci_message_data) + +enum heci_stop_reason_types{ + DRIVER_STOP_REQUEST = 0x00, + DEVICE_D1_ENTRY = 0x01, + DEVICE_D2_ENTRY = 0x02, + DEVICE_D3_ENTRY = 0x03, + SYSTEM_S1_ENTRY = 0x04, + SYSTEM_S2_ENTRY = 0x05, + SYSTEM_S3_ENTRY = 0x06, + SYSTEM_S4_ENTRY = 0x07, + SYSTEM_S5_ENTRY = 0x08 +}; + +enum me_stop_reason_types{ + FW_UPDATE = 0x00 +}; + +enum client_connect_status_types{ + CCS_SUCCESS = 0x00, + CCS_NOT_FOUND = 0x01, + CCS_ALREADY_STARTED = 0x02, + CCS_OUT_OF_RESOURCES = 0x03, + CCS_MESSAGE_SMALL = 0x04 +}; + +enum client_disconnect_status_types{ + CDS_SUCCESS = 0x00 +}; + + +/* + * heci interface function prototypes + */ +void heci_set_csr_register(struct iamt_heci_device *dev); +void heci_csr_enable_interrupts(struct iamt_heci_device *dev); +void heci_csr_disable_interrupts(struct iamt_heci_device *dev); + +void heci_read_slots(struct iamt_heci_device *dev, + unsigned char *buffer, unsigned long buffer_length); + +int heci_write_message(struct iamt_heci_device *dev, + struct heci_msg_hdr *header, + unsigned char *write_buffer, + unsigned long write_length); + +int host_buffer_is_empty(struct iamt_heci_device *dev); + +__s32 count_full_read_slots(struct iamt_heci_device *dev); + +__s32 count_empty_write_slots(const struct iamt_heci_device *dev); + +int flow_ctrl_creds(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); + +int heci_send_wd(struct iamt_heci_device *dev); + +void flow_ctrl_reduce(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); + +int heci_send_flow_control(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); + +int heci_disconnect(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); +int other_client_is_connecting(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); +int heci_connect(struct iamt_heci_device *dev, + struct heci_file_private *file_ext); + +#endif /* _HECI_INTERFACE_H_ */ diff --git a/drivers/staging/heci/heci_main.c b/drivers/staging/heci/heci_main.c new file mode 100644 index 000000000000..00e44c781428 --- /dev/null +++ b/drivers/staging/heci/heci_main.c @@ -0,0 +1,1564 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2008 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "heci.h" +#include "heci_interface.h" +#include "heci_version.h" + + +#define HECI_READ_TIMEOUT 45 + +#define HECI_DRIVER_NAME "heci" + +/* + * heci driver strings + */ +static char heci_driver_name[] = HECI_DRIVER_NAME; +static char heci_driver_string[] = "Intel(R) Management Engine Interface"; +static char heci_driver_version[] = HECI_DRIVER_VERSION; +static char heci_copyright[] = "Copyright (c) 2003 - 2008 Intel Corporation."; + + +#ifdef HECI_DEBUG +int heci_debug = 1; +#else +int heci_debug; +#endif +MODULE_PARM_DESC(heci_debug, "Debug enabled or not"); +module_param(heci_debug, int, 0644); + + +#define HECI_DEV_NAME "heci" + +/* heci char device for registration */ +static struct cdev heci_cdev; + +/* major number for device */ +static int heci_major; +/* The device pointer */ +static struct pci_dev *heci_device; + +static struct class *heci_class; + + +/* heci_pci_tbl - PCI Device ID Table */ +static struct pci_device_id heci_pci_tbl[] = { + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82946GZ)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82G35)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82Q965)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82G965)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82GM965)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82GME965)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82Q35)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82G33)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82Q33)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82X38)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_3200)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_6)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_7)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_8)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_9)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_10)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_1)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_2)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_3)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_4)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_1)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_2)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_3)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_4)}, + /* required last entry */ + {0, } +}; + +MODULE_DEVICE_TABLE(pci, heci_pci_tbl); + +/* + * Local Function Prototypes + */ +static int __init heci_init_module(void); +static void __exit heci_exit_module(void); +static int __devinit heci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void __devexit heci_remove(struct pci_dev *pdev); +static int heci_open(struct inode *inode, struct file *file); +static int heci_release(struct inode *inode, struct file *file); +static ssize_t heci_read(struct file *file, char __user *ubuf, + size_t length, loff_t *offset); +static int heci_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long data); +static ssize_t heci_write(struct file *file, const char __user *ubuf, + size_t length, loff_t *offset); +static unsigned int heci_poll(struct file *file, poll_table *wait); +static struct heci_cb_private *find_read_list_entry( + struct iamt_heci_device *dev, + struct heci_file_private *file_ext); +#ifdef CONFIG_PM +static int heci_suspend(struct pci_dev *pdev, pm_message_t state); +static int heci_resume(struct pci_dev *pdev); +static __u16 g_sus_wd_timeout; +#else +#define heci_suspend NULL +#define heci_resume NULL +#endif +/* + * PCI driver structure + */ +static struct pci_driver heci_driver = { + .name = heci_driver_name, + .id_table = heci_pci_tbl, + .probe = heci_probe, + .remove = __devexit_p(heci_remove), + .shutdown = __devexit_p(heci_remove), + .suspend = heci_suspend, + .resume = heci_resume +}; + +/* + * file operations structure will be use heci char device. + */ +static const struct file_operations heci_fops = { + .owner = THIS_MODULE, + .read = heci_read, + .ioctl = heci_ioctl, + .open = heci_open, + .release = heci_release, + .write = heci_write, + .poll = heci_poll, +}; + +/** + * heci_registration_cdev - set up the cdev structure for heci device. + * + * @dev: char device struct + * @hminor: minor number for registration char device + * @fops: file operations structure + * + * returns 0 on success, <0 on failure. + */ +static int heci_registration_cdev(struct cdev *dev, int hminor, + const struct file_operations *fops) +{ + int ret, devno = MKDEV(heci_major, hminor); + + cdev_init(dev, fops); + dev->owner = THIS_MODULE; + ret = cdev_add(dev, devno, 1); + /* Fail gracefully if need be */ + if (ret) { + printk(KERN_ERR "heci: Error %d registering heci device %d\n", + ret, hminor); + } + return ret; +} + +/* Display the version of heci driver. */ +static ssize_t version_show(struct class *dev, char *buf) +{ + return sprintf(buf, "%s %s.\n", + heci_driver_string, heci_driver_version); +} + +static CLASS_ATTR(version, S_IRUGO, version_show, NULL); + +/** + * heci_register_cdev - registers heci char device + * + * returns 0 on success, <0 on failure. + */ +static int heci_register_cdev(void) +{ + int ret; + dev_t dev; + + /* registration of char devices */ + ret = alloc_chrdev_region(&dev, HECI_MINORS_BASE, HECI_MINORS_COUNT, + HECI_DRIVER_NAME); + if (ret) { + printk(KERN_ERR "heci: Error allocating char device region.\n"); + return ret; + } + + heci_major = MAJOR(dev); + + ret = heci_registration_cdev(&heci_cdev, HECI_MINOR_NUMBER, + &heci_fops); + if (ret) + unregister_chrdev_region(MKDEV(heci_major, HECI_MINORS_BASE), + HECI_MINORS_COUNT); + + return ret; +} + +/** + * heci_unregister_cdev - unregisters heci char device + */ +static void heci_unregister_cdev(void) +{ + cdev_del(&heci_cdev); + unregister_chrdev_region(MKDEV(heci_major, HECI_MINORS_BASE), + HECI_MINORS_COUNT); +} + +#ifndef HECI_DEVICE_CREATE +#define HECI_DEVICE_CREATE device_create +#endif +/** + * heci_sysfs_device_create - adds device entry to sysfs + * + * returns 0 on success, <0 on failure. + */ +static int heci_sysfs_device_create(void) +{ + struct class *class; + void *tmphdev; + int err = 0; + + class = class_create(THIS_MODULE, HECI_DRIVER_NAME); + if (IS_ERR(class)) { + err = PTR_ERR(class); + printk(KERN_ERR "heci: Error creating heci class.\n"); + goto err_out; + } + + err = class_create_file(class, &class_attr_version); + if (err) { + class_destroy(class); + printk(KERN_ERR "heci: Error creating heci class file.\n"); + goto err_out; + } + + tmphdev = HECI_DEVICE_CREATE(class, NULL, heci_cdev.dev, NULL, + HECI_DEV_NAME); + if (IS_ERR(tmphdev)) { + err = PTR_ERR(tmphdev); + class_remove_file(class, &class_attr_version); + class_destroy(class); + goto err_out; + } + + heci_class = class; +err_out: + return err; +} + +/** + * heci_sysfs_device_remove - unregisters the device entry on sysfs + */ +static void heci_sysfs_device_remove(void) +{ + if ((heci_class == NULL) || (IS_ERR(heci_class))) + return; + + device_destroy(heci_class, heci_cdev.dev); + class_remove_file(heci_class, &class_attr_version); + class_destroy(heci_class); +} + +/** + * heci_init_module - Driver Registration Routine + * + * heci_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + * + * returns 0 on success, <0 on failure. + */ +static int __init heci_init_module(void) +{ + int ret = 0; + + printk(KERN_INFO "heci: %s - version %s\n", heci_driver_string, + heci_driver_version); + printk(KERN_INFO "heci: %s\n", heci_copyright); + + /* init pci module */ + ret = pci_register_driver(&heci_driver); + if (ret < 0) { + printk(KERN_ERR "heci: Error registering driver.\n"); + goto end; + } + + ret = heci_register_cdev(); + if (ret) + goto unregister_pci; + + ret = heci_sysfs_device_create(); + if (ret) + goto unregister_cdev; + + return ret; + +unregister_cdev: + heci_unregister_cdev(); +unregister_pci: + pci_unregister_driver(&heci_driver); +end: + return ret; +} + +module_init(heci_init_module); + + +/** + * heci_exit_module - Driver Exit Cleanup Routine + * + * heci_exit_module is called just before the driver is removed + * from memory. + */ +static void __exit heci_exit_module(void) +{ + pci_unregister_driver(&heci_driver); + heci_sysfs_device_remove(); + heci_unregister_cdev(); +} + +module_exit(heci_exit_module); + + +/** + * heci_probe - Device Initialization Routine + * + * @pdev: PCI device information struct + * @ent: entry in kcs_pci_tbl + * + * returns 0 on success, <0 on failure. + */ +static int __devinit heci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct iamt_heci_device *dev = NULL; + int i, err = 0; + + if (heci_device) { + err = -EEXIST; + goto end; + } + /* enable pci dev */ + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "heci: Failed to enable pci device.\n"); + goto end; + } + /* set PCI host mastering */ + pci_set_master(pdev); + /* pci request regions for heci driver */ + err = pci_request_regions(pdev, heci_driver_name); + if (err) { + printk(KERN_ERR "heci: Failed to get pci regions.\n"); + goto disable_device; + } + /* allocates and initializes the heci dev structure */ + dev = init_heci_device(pdev); + if (!dev) { + err = -ENOMEM; + goto release_regions; + } + /* mapping IO device memory */ + for (i = 0; i <= 5; i++) { + if (pci_resource_len(pdev, i) == 0) + continue; + if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { + printk(KERN_ERR "heci: heci has IO ports.\n"); + goto free_device; + } else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) { + if (dev->mem_base) { + printk(KERN_ERR + "heci: Too many mem addresses.\n"); + goto free_device; + } + dev->mem_base = pci_resource_start(pdev, i); + dev->mem_length = pci_resource_len(pdev, i); + } + } + if (!dev->mem_base) { + printk(KERN_ERR "heci: No address to use.\n"); + err = -ENODEV; + goto free_device; + } + dev->mem_addr = ioremap_nocache(dev->mem_base, + dev->mem_length); + if (!dev->mem_addr) { + printk(KERN_ERR "heci: Remap IO device memory failure.\n"); + err = -ENOMEM; + goto free_device; + } + /* request and enable interrupt */ + err = request_irq(pdev->irq, heci_isr_interrupt, IRQF_SHARED, + heci_driver_name, dev); + if (err) { + printk(KERN_ERR "heci: Request_irq failure. irq = %d \n", + pdev->irq); + goto unmap_memory; + } + + if (heci_hw_init(dev)) { + printk(KERN_ERR "heci: Init hw failure.\n"); + err = -ENODEV; + goto release_irq; + } + init_timer(&dev->wd_timer); + + heci_initialize_clients(dev); + if (dev->heci_state != HECI_ENABLED) { + err = -ENODEV; + goto release_hw; + } + + spin_lock_bh(&dev->device_lock); + heci_device = pdev; + pci_set_drvdata(pdev, dev); + spin_unlock_bh(&dev->device_lock); + + if (dev->wd_timeout) + mod_timer(&dev->wd_timer, jiffies); + +#ifdef CONFIG_PM + g_sus_wd_timeout = 0; +#endif + printk(KERN_INFO "heci driver initialization successful.\n"); + return 0; + +release_hw: + /* disable interrupts */ + dev->host_hw_state = read_heci_register(dev, H_CSR); + heci_csr_disable_interrupts(dev); + + del_timer_sync(&dev->wd_timer); + + flush_scheduled_work(); + +release_irq: + free_irq(pdev->irq, dev); +unmap_memory: + if (dev->mem_addr) + iounmap(dev->mem_addr); +free_device: + kfree(dev); +release_regions: + pci_release_regions(pdev); +disable_device: + pci_disable_device(pdev); +end: + printk(KERN_ERR "heci driver initialization failed.\n"); + return err; +} + +/** + * heci_remove - Device Removal Routine + * + * @pdev: PCI device information struct + * + * heci_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. + */ +static void __devexit heci_remove(struct pci_dev *pdev) +{ + struct iamt_heci_device *dev = pci_get_drvdata(pdev); + + if (heci_device != pdev) + return; + + if (dev == NULL) + return; + + spin_lock_bh(&dev->device_lock); + if (heci_device != pdev) { + spin_unlock_bh(&dev->device_lock); + return; + } + + if (dev->reinit_tsk != NULL) { + kthread_stop(dev->reinit_tsk); + dev->reinit_tsk = NULL; + } + + del_timer_sync(&dev->wd_timer); + if (dev->wd_file_ext.state == HECI_FILE_CONNECTED + && dev->wd_timeout) { + dev->wd_timeout = 0; + dev->wd_due_counter = 0; + memcpy(dev->wd_data, heci_stop_wd_params, HECI_WD_PARAMS_SIZE); + dev->stop = 1; + if (dev->host_buffer_is_empty && + flow_ctrl_creds(dev, &dev->wd_file_ext)) { + dev->host_buffer_is_empty = 0; + + if (!heci_send_wd(dev)) + DBG("send stop WD failed\n"); + else + flow_ctrl_reduce(dev, &dev->wd_file_ext); + + dev->wd_pending = 0; + } else { + dev->wd_pending = 1; + } + dev->wd_stoped = 0; + spin_unlock_bh(&dev->device_lock); + + wait_event_interruptible_timeout(dev->wait_stop_wd, + (dev->wd_stoped), 10 * HZ); + spin_lock_bh(&dev->device_lock); + if (!dev->wd_stoped) + DBG("stop wd failed to complete.\n"); + else + DBG("stop wd complete.\n"); + + } + + heci_device = NULL; + spin_unlock_bh(&dev->device_lock); + + if (dev->iamthif_file_ext.state == HECI_FILE_CONNECTED) { + dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTING; + heci_disconnect_host_client(dev, + &dev->iamthif_file_ext); + } + if (dev->wd_file_ext.state == HECI_FILE_CONNECTED) { + dev->wd_file_ext.state = HECI_FILE_DISCONNECTING; + heci_disconnect_host_client(dev, + &dev->wd_file_ext); + } + + spin_lock_bh(&dev->device_lock); + + /* remove entry if already in list */ + DBG("list del iamthif and wd file list.\n"); + heci_remove_client_from_file_list(dev, dev->wd_file_ext. + host_client_id); + heci_remove_client_from_file_list(dev, + dev->iamthif_file_ext.host_client_id); + + dev->iamthif_current_cb = NULL; + dev->iamthif_file_ext.file = NULL; + dev->num_heci_me_clients = 0; + + spin_unlock_bh(&dev->device_lock); + + flush_scheduled_work(); + + /* disable interrupts */ + heci_csr_disable_interrupts(dev); + + free_irq(pdev->irq, dev); + pci_set_drvdata(pdev, NULL); + + if (dev->mem_addr) + iounmap(dev->mem_addr); + + kfree(dev); + + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +/** + * heci_clear_list - remove all callbacks associated with file + * from heci_cb_list + * + * @file: file information struct + * @heci_cb_list: callbacks list + * + * heci_clear_list is called to clear resources associated with file + * when application calls close function or Ctrl-C was pressed + * + * returns 1 if callback removed from the list, 0 otherwise + */ +static int heci_clear_list(struct iamt_heci_device *dev, + struct file *file, struct list_head *heci_cb_list) +{ + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; + struct file *file_temp; + int rets = 0; + + /* list all list member */ + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + heci_cb_list, cb_list) { + file_temp = (struct file *)priv_cb_pos->file_object; + /* check if list member associated with a file */ + if (file_temp == file) { + /* remove member from the list */ + list_del(&priv_cb_pos->cb_list); + /* check if cb equal to current iamthif cb */ + if (dev->iamthif_current_cb == priv_cb_pos) { + dev->iamthif_current_cb = NULL; + /* send flow control to iamthif client */ + heci_send_flow_control(dev, + &dev->iamthif_file_ext); + } + /* free all allocated buffers */ + heci_free_cb_private(priv_cb_pos); + rets = 1; + } + } + return rets; +} + +/** + * heci_clear_lists - remove all callbacks associated with file + * + * @dev: device information struct + * @file: file information struct + * + * heci_clear_lists is called to clear resources associated with file + * when application calls close function or Ctrl-C was pressed + * + * returns 1 if callback removed from the list, 0 otherwise + */ +static int heci_clear_lists(struct iamt_heci_device *dev, struct file *file) +{ + int rets = 0; + + /* remove callbacks associated with a file */ + heci_clear_list(dev, file, &dev->pthi_cmd_list.heci_cb.cb_list); + if (heci_clear_list(dev, file, + &dev->pthi_read_complete_list.heci_cb.cb_list)) + rets = 1; + + heci_clear_list(dev, file, &dev->ctrl_rd_list.heci_cb.cb_list); + + if (heci_clear_list(dev, file, &dev->ctrl_wr_list.heci_cb.cb_list)) + rets = 1; + + if (heci_clear_list(dev, file, + &dev->write_waiting_list.heci_cb.cb_list)) + rets = 1; + + if (heci_clear_list(dev, file, &dev->write_list.heci_cb.cb_list)) + rets = 1; + + /* check if iamthif_current_cb not NULL */ + if (dev->iamthif_current_cb && (!rets)) { + /* check file and iamthif current cb association */ + if (dev->iamthif_current_cb->file_object == file) { + /* remove cb */ + heci_free_cb_private(dev->iamthif_current_cb); + dev->iamthif_current_cb = NULL; + rets = 1; + } + } + return rets; +} + +/** + * heci_open - the open function + * + * @inode: pointer to inode structure + * @file: pointer to file structure + * + * returns 0 on success, <0 on error + */ +static int heci_open(struct inode *inode, struct file *file) +{ + struct heci_file_private *file_ext; + int if_num = iminor(inode); + struct iamt_heci_device *dev; + + if (!heci_device) + return -ENODEV; + + dev = pci_get_drvdata(heci_device); + if ((if_num != HECI_MINOR_NUMBER) || (!dev)) + return -ENODEV; + + file_ext = heci_alloc_file_private(file); + if (file_ext == NULL) + return -ENOMEM; + + spin_lock_bh(&dev->device_lock); + if (dev->heci_state != HECI_ENABLED) { + spin_unlock_bh(&dev->device_lock); + kfree(file_ext); + return -ENODEV; + } + if (dev->open_handle_count >= HECI_MAX_OPEN_HANDLE_COUNT) { + spin_unlock_bh(&dev->device_lock); + kfree(file_ext); + return -ENFILE; + }; + dev->open_handle_count++; + list_add_tail(&file_ext->link, &dev->file_list); + while ((dev->heci_host_clients[dev->current_host_client_id / 8] + & (1 << (dev->current_host_client_id % 8))) != 0) { + + dev->current_host_client_id++; /* allow overflow */ + DBG("current_host_client_id = %d\n", + dev->current_host_client_id); + DBG("dev->open_handle_count = %lu\n", + dev->open_handle_count); + } + DBG("current_host_client_id = %d\n", dev->current_host_client_id); + file_ext->host_client_id = dev->current_host_client_id; + dev->heci_host_clients[file_ext->host_client_id / 8] |= + (1 << (file_ext->host_client_id % 8)); + spin_unlock_bh(&dev->device_lock); + spin_lock(&file_ext->file_lock); + file_ext->state = HECI_FILE_INITIALIZING; + file_ext->sm_state = 0; + + file->private_data = file_ext; + spin_unlock(&file_ext->file_lock); + + return 0; +} + +/** + * heci_release - the release function + * + * @inode: pointer to inode structure + * @file: pointer to file structure + * + * returns 0 on success, <0 on error + */ +static int heci_release(struct inode *inode, struct file *file) +{ + int rets = 0; + int if_num = iminor(inode); + struct heci_file_private *file_ext = file->private_data; + struct heci_cb_private *priv_cb = NULL; + struct iamt_heci_device *dev; + + if (!heci_device) + return -ENODEV; + + dev = pci_get_drvdata(heci_device); + if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) + return -ENODEV; + + if (file_ext != &dev->iamthif_file_ext) { + spin_lock(&file_ext->file_lock); + if (file_ext->state == HECI_FILE_CONNECTED) { + file_ext->state = HECI_FILE_DISCONNECTING; + spin_unlock(&file_ext->file_lock); + DBG("disconnecting client host client = %d, " + "ME client = %d\n", + file_ext->host_client_id, + file_ext->me_client_id); + rets = heci_disconnect_host_client(dev, file_ext); + spin_lock(&file_ext->file_lock); + } + spin_lock_bh(&dev->device_lock); + heci_flush_queues(dev, file_ext); + DBG("remove client host client = %d, ME client = %d\n", + file_ext->host_client_id, + file_ext->me_client_id); + + if (dev->open_handle_count > 0) { + dev->heci_host_clients[file_ext->host_client_id / 8] &= + ~(1 << (file_ext->host_client_id % 8)); + dev->open_handle_count--; + } + heci_remove_client_from_file_list(dev, + file_ext->host_client_id); + + /* free read cb */ + if (file_ext->read_cb != NULL) { + priv_cb = find_read_list_entry(dev, file_ext); + /* Remove entry from read list */ + if (priv_cb != NULL) + list_del(&priv_cb->cb_list); + + priv_cb = file_ext->read_cb; + file_ext->read_cb = NULL; + } + + spin_unlock_bh(&dev->device_lock); + file->private_data = NULL; + spin_unlock(&file_ext->file_lock); + + if (priv_cb != NULL) + heci_free_cb_private(priv_cb); + + kfree(file_ext); + } else { + spin_lock_bh(&dev->device_lock); + + if (dev->open_handle_count > 0) + dev->open_handle_count--; + + if (dev->iamthif_file_object == file + && dev->iamthif_state != HECI_IAMTHIF_IDLE) { + DBG("pthi canceled iamthif state %d\n", + dev->iamthif_state); + dev->iamthif_canceled = 1; + if (dev->iamthif_state == HECI_IAMTHIF_READ_COMPLETE) { + DBG("run next pthi iamthif cb\n"); + run_next_iamthif_cmd(dev); + } + } + + if (heci_clear_lists(dev, file)) + dev->iamthif_state = HECI_IAMTHIF_IDLE; + + spin_unlock_bh(&dev->device_lock); + } + return rets; +} + +static struct heci_cb_private *find_read_list_entry( + struct iamt_heci_device *dev, + struct heci_file_private *file_ext) +{ + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; + struct heci_file_private *file_ext_list_temp; + + if (dev->read_list.status == 0 + && !list_empty(&dev->read_list.heci_cb.cb_list)) { + DBG("remove read_list CB \n"); + list_for_each_entry_safe(priv_cb_pos, + priv_cb_next, + &dev->read_list.heci_cb.cb_list, cb_list) { + + file_ext_list_temp = (struct heci_file_private *) + priv_cb_pos->file_private; + + if ((file_ext_list_temp != NULL) && + heci_fe_same_id(file_ext, file_ext_list_temp)) + return priv_cb_pos; + + } + } + return NULL; +} + +/** + * heci_read - the read client message function. + * + * @file: pointer to file structure + * @ubuf: pointer to user buffer + * @length: buffer length + * @offset: data offset in buffer + * + * returns >=0 data length on success , <0 on error + */ +static ssize_t heci_read(struct file *file, char __user *ubuf, + size_t length, loff_t *offset) +{ + int i; + int rets = 0, err = 0; + int if_num = iminor(file->f_dentry->d_inode); + struct heci_file_private *file_ext = file->private_data; + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb = NULL; + struct iamt_heci_device *dev; + + if (!heci_device) + return -ENODEV; + + dev = pci_get_drvdata(heci_device); + if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) + return -ENODEV; + + spin_lock_bh(&dev->device_lock); + if (dev->heci_state != HECI_ENABLED) { + spin_unlock_bh(&dev->device_lock); + return -ENODEV; + } + spin_unlock_bh(&dev->device_lock); + + spin_lock(&file_ext->file_lock); + if ((file_ext->sm_state & HECI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) { + spin_unlock(&file_ext->file_lock); + /* Do not allow to read watchdog client */ + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (memcmp(&heci_wd_guid, + &dev->me_clients[i].props.protocol_name, + sizeof(struct guid)) == 0) { + if (file_ext->me_client_id == + dev->me_clients[i].client_id) + return -EBADF; + } + } + } else { + file_ext->sm_state &= ~HECI_WD_STATE_INDEPENDENCE_MSG_SENT; + spin_unlock(&file_ext->file_lock); + } + + if (file_ext == &dev->iamthif_file_ext) { + rets = pthi_read(dev, if_num, file, ubuf, length, offset); + goto out; + } + + if (file_ext->read_cb && file_ext->read_cb->information > *offset) { + priv_cb = file_ext->read_cb; + goto copy_buffer; + } else if (file_ext->read_cb && file_ext->read_cb->information > 0 && + file_ext->read_cb->information <= *offset) { + priv_cb = file_ext->read_cb; + rets = 0; + goto free; + } else if ((!file_ext->read_cb || file_ext->read_cb->information == 0) + && *offset > 0) { + /*Offset needs to be cleaned for contingous reads*/ + *offset = 0; + rets = 0; + goto out; + } + + spin_lock(&file_ext->read_io_lock); + err = heci_start_read(dev, if_num, file_ext); + if (err != 0 && err != -EBUSY) { + DBG("heci start read failure with status = %d\n", err); + spin_unlock(&file_ext->read_io_lock); + rets = err; + goto out; + } + if (HECI_READ_COMPLETE != file_ext->reading_state + && !waitqueue_active(&file_ext->rx_wait)) { + if (file->f_flags & O_NONBLOCK) { + rets = -EAGAIN; + spin_unlock(&file_ext->read_io_lock); + goto out; + } + spin_unlock(&file_ext->read_io_lock); + + if (wait_event_interruptible(file_ext->rx_wait, + (HECI_READ_COMPLETE == file_ext->reading_state + || HECI_FILE_INITIALIZING == file_ext->state + || HECI_FILE_DISCONNECTED == file_ext->state + || HECI_FILE_DISCONNECTING == file_ext->state))) { + if (signal_pending(current)) { + rets = -EINTR; + goto out; + } + return -ERESTARTSYS; + } + + if (HECI_FILE_INITIALIZING == file_ext->state || + HECI_FILE_DISCONNECTED == file_ext->state || + HECI_FILE_DISCONNECTING == file_ext->state) { + rets = -EBUSY; + goto out; + } + spin_lock(&file_ext->read_io_lock); + } + + priv_cb = file_ext->read_cb; + + if (!priv_cb) { + spin_unlock(&file_ext->read_io_lock); + return -ENODEV; + } + if (file_ext->reading_state != HECI_READ_COMPLETE) { + spin_unlock(&file_ext->read_io_lock); + return 0; + } + spin_unlock(&file_ext->read_io_lock); + /* now copy the data to user space */ +copy_buffer: + DBG("priv_cb->response_buffer size - %d\n", + priv_cb->response_buffer.size); + DBG("priv_cb->information - %lu\n", + priv_cb->information); + if (length == 0 || ubuf == NULL || + *offset > priv_cb->information) { + rets = -EMSGSIZE; + goto free; + } + + /* length is being turncated to PAGE_SIZE, however, */ + /* information size may be longer */ + length = (length < (priv_cb->information - *offset) ? + length : (priv_cb->information - *offset)); + + if (copy_to_user(ubuf, + priv_cb->response_buffer.data + *offset, + length)) { + rets = -EFAULT; + goto free; + } + + rets = length; + *offset += length; + if ((unsigned long)*offset < priv_cb->information) + goto out; + +free: + spin_lock_bh(&dev->device_lock); + priv_cb_pos = find_read_list_entry(dev, file_ext); + /* Remove entry from read list */ + if (priv_cb_pos != NULL) + list_del(&priv_cb_pos->cb_list); + spin_unlock_bh(&dev->device_lock); + heci_free_cb_private(priv_cb); + spin_lock(&file_ext->read_io_lock); + file_ext->reading_state = HECI_IDLE; + file_ext->read_cb = NULL; + file_ext->read_pending = 0; + spin_unlock(&file_ext->read_io_lock); +out: DBG("end heci read rets= %d\n", rets); + return rets; +} + +/** + * heci_write - the write function. + * + * @file: pointer to file structure + * @ubuf: pointer to user buffer + * @length: buffer length + * @offset: data offset in buffer + * + * returns >=0 data length on success , <0 on error + */ +static ssize_t heci_write(struct file *file, const char __user *ubuf, + size_t length, loff_t *offset) +{ + int rets = 0; + __u8 i; + int if_num = iminor(file->f_dentry->d_inode); + struct heci_file_private *file_ext = file->private_data; + struct heci_cb_private *priv_write_cb = NULL; + struct heci_msg_hdr heci_hdr; + struct iamt_heci_device *dev; + unsigned long currtime = get_seconds(); + + if (!heci_device) + return -ENODEV; + + dev = pci_get_drvdata(heci_device); + + if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) + return -ENODEV; + + spin_lock_bh(&dev->device_lock); + + if (dev->heci_state != HECI_ENABLED) { + spin_unlock_bh(&dev->device_lock); + return -ENODEV; + } + if (file_ext == &dev->iamthif_file_ext) { + priv_write_cb = find_pthi_read_list_entry(dev, file); + if ((priv_write_cb != NULL) && + (((currtime - priv_write_cb->read_time) > + IAMTHIF_READ_TIMER) || + (file_ext->reading_state == HECI_READ_COMPLETE))) { + (*offset) = 0; + list_del(&priv_write_cb->cb_list); + heci_free_cb_private(priv_write_cb); + priv_write_cb = NULL; + } + } + + /* free entry used in read */ + if (file_ext->reading_state == HECI_READ_COMPLETE) { + *offset = 0; + priv_write_cb = find_read_list_entry(dev, file_ext); + if (priv_write_cb != NULL) { + list_del(&priv_write_cb->cb_list); + heci_free_cb_private(priv_write_cb); + priv_write_cb = NULL; + spin_lock(&file_ext->read_io_lock); + file_ext->reading_state = HECI_IDLE; + file_ext->read_cb = NULL; + file_ext->read_pending = 0; + spin_unlock(&file_ext->read_io_lock); + } + } else if (file_ext->reading_state == HECI_IDLE && + file_ext->read_pending == 0) + (*offset) = 0; + + spin_unlock_bh(&dev->device_lock); + + priv_write_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL); + if (!priv_write_cb) + return -ENOMEM; + + priv_write_cb->file_object = file; + priv_write_cb->file_private = file_ext; + priv_write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL); + if (!priv_write_cb->request_buffer.data) { + kfree(priv_write_cb); + return -ENOMEM; + } + DBG("length =%d\n", (int) length); + + if (copy_from_user(priv_write_cb->request_buffer.data, + ubuf, length)) { + rets = -EFAULT; + goto fail; + } + + spin_lock(&file_ext->file_lock); + file_ext->sm_state = 0; + if ((length == 4) && + ((memcmp(heci_wd_state_independence_msg[0], ubuf, 4) == 0) || + (memcmp(heci_wd_state_independence_msg[1], ubuf, 4) == 0) || + (memcmp(heci_wd_state_independence_msg[2], ubuf, 4) == 0))) + file_ext->sm_state |= HECI_WD_STATE_INDEPENDENCE_MSG_SENT; + spin_unlock(&file_ext->file_lock); + + INIT_LIST_HEAD(&priv_write_cb->cb_list); + if (file_ext == &dev->iamthif_file_ext) { + priv_write_cb->response_buffer.data = + kmalloc(IAMTHIF_MTU, GFP_KERNEL); + if (!priv_write_cb->response_buffer.data) { + rets = -ENOMEM; + goto fail; + } + spin_lock_bh(&dev->device_lock); + if (dev->heci_state != HECI_ENABLED) { + spin_unlock_bh(&dev->device_lock); + rets = -ENODEV; + goto fail; + } + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (dev->me_clients[i].client_id == + dev->iamthif_file_ext.me_client_id) + break; + } + + BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id); + if ((i == dev->num_heci_me_clients) || + (dev->me_clients[i].client_id != + dev->iamthif_file_ext.me_client_id)) { + + spin_unlock_bh(&dev->device_lock); + rets = -ENODEV; + goto fail; + } else if ((length > dev->me_clients[i].props.max_msg_length) + || (length <= 0)) { + spin_unlock_bh(&dev->device_lock); + rets = -EMSGSIZE; + goto fail; + } + + + priv_write_cb->response_buffer.size = IAMTHIF_MTU; + priv_write_cb->major_file_operations = HECI_IOCTL; + priv_write_cb->information = 0; + priv_write_cb->request_buffer.size = length; + if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) { + spin_unlock_bh(&dev->device_lock); + rets = -ENODEV; + goto fail; + } + + if (!list_empty(&dev->pthi_cmd_list.heci_cb.cb_list) + || dev->iamthif_state != HECI_IAMTHIF_IDLE) { + DBG("pthi_state = %d\n", (int) dev->iamthif_state); + DBG("add PTHI cb to pthi cmd waiting list\n"); + list_add_tail(&priv_write_cb->cb_list, + &dev->pthi_cmd_list.heci_cb.cb_list); + rets = length; + } else { + DBG("call pthi write\n"); + rets = pthi_write(dev, priv_write_cb); + + if (rets != 0) { + DBG("pthi write failed with status = %d\n", + rets); + spin_unlock_bh(&dev->device_lock); + goto fail; + } + rets = length; + } + spin_unlock_bh(&dev->device_lock); + return rets; + } + + priv_write_cb->major_file_operations = HECI_WRITE; + /* make sure information is zero before we start */ + + priv_write_cb->information = 0; + priv_write_cb->request_buffer.size = length; + + spin_lock(&file_ext->write_io_lock); + DBG("host client = %d, ME client = %d\n", + file_ext->host_client_id, file_ext->me_client_id); + if (file_ext->state != HECI_FILE_CONNECTED) { + rets = -ENODEV; + DBG("host client = %d, is not connected to ME client = %d", + file_ext->host_client_id, + file_ext->me_client_id); + + goto unlock; + } + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (dev->me_clients[i].client_id == + file_ext->me_client_id) + break; + } + BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id); + if (i == dev->num_heci_me_clients) { + rets = -ENODEV; + goto unlock; + } + if (length > dev->me_clients[i].props.max_msg_length || length <= 0) { + rets = -EINVAL; + goto unlock; + } + priv_write_cb->file_private = file_ext; + + spin_lock_bh(&dev->device_lock); + if (flow_ctrl_creds(dev, file_ext) && + dev->host_buffer_is_empty) { + spin_unlock_bh(&dev->device_lock); + dev->host_buffer_is_empty = 0; + if (length > ((((dev->host_hw_state & H_CBD) >> 24) * + sizeof(__u32)) - sizeof(struct heci_msg_hdr))) { + + heci_hdr.length = + (((dev->host_hw_state & H_CBD) >> 24) * + sizeof(__u32)) - + sizeof(struct heci_msg_hdr); + heci_hdr.msg_complete = 0; + } else { + heci_hdr.length = length; + heci_hdr.msg_complete = 1; + } + heci_hdr.host_addr = file_ext->host_client_id; + heci_hdr.me_addr = file_ext->me_client_id; + heci_hdr.reserved = 0; + DBG("call heci_write_message header=%08x.\n", + *((__u32 *) &heci_hdr)); + spin_unlock(&file_ext->write_io_lock); + /* protect heci low level write */ + spin_lock_bh(&dev->device_lock); + if (!heci_write_message(dev, &heci_hdr, + (unsigned char *) (priv_write_cb->request_buffer.data), + heci_hdr.length)) { + + spin_unlock_bh(&dev->device_lock); + heci_free_cb_private(priv_write_cb); + rets = -ENODEV; + priv_write_cb->information = 0; + return rets; + } + file_ext->writing_state = HECI_WRITING; + priv_write_cb->information = heci_hdr.length; + if (heci_hdr.msg_complete) { + flow_ctrl_reduce(dev, file_ext); + list_add_tail(&priv_write_cb->cb_list, + &dev->write_waiting_list.heci_cb.cb_list); + } else { + list_add_tail(&priv_write_cb->cb_list, + &dev->write_list.heci_cb.cb_list); + } + spin_unlock_bh(&dev->device_lock); + + } else { + + spin_unlock_bh(&dev->device_lock); + priv_write_cb->information = 0; + file_ext->writing_state = HECI_WRITING; + spin_unlock(&file_ext->write_io_lock); + list_add_tail(&priv_write_cb->cb_list, + &dev->write_list.heci_cb.cb_list); + } + return length; + +unlock: + spin_unlock(&file_ext->write_io_lock); +fail: + heci_free_cb_private(priv_write_cb); + return rets; + +} + +/** + * heci_ioctl - the IOCTL function + * + * @inode: pointer to inode structure + * @file: pointer to file structure + * @cmd: ioctl command + * @data: pointer to heci message structure + * + * returns 0 on success , <0 on error + */ +static int heci_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long data) +{ + int rets = 0; + int if_num = iminor(inode); + struct heci_file_private *file_ext = file->private_data; + /* in user space */ + struct heci_message_data __user *u_msg; + struct heci_message_data k_msg; /* all in kernel on the stack */ + struct iamt_heci_device *dev; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (!heci_device) + return -ENODEV; + + dev = pci_get_drvdata(heci_device); + if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) + return -ENODEV; + + spin_lock_bh(&dev->device_lock); + if (dev->heci_state != HECI_ENABLED) { + spin_unlock_bh(&dev->device_lock); + return -ENODEV; + } + spin_unlock_bh(&dev->device_lock); + + /* first copy from user all data needed */ + u_msg = (struct heci_message_data __user *)data; + if (copy_from_user(&k_msg, u_msg, sizeof(k_msg))) { + DBG("first copy from user all data needed filled\n"); + return -EFAULT; + } + DBG("user message size is %d\n", k_msg.size); + + switch (cmd) { + case IOCTL_HECI_GET_VERSION: + DBG(": IOCTL_HECI_GET_VERSION\n"); + rets = heci_ioctl_get_version(dev, if_num, u_msg, k_msg, + file_ext); + break; + + case IOCTL_HECI_CONNECT_CLIENT: + DBG(": IOCTL_HECI_CONNECT_CLIENT.\n"); + rets = heci_ioctl_connect_client(dev, if_num, u_msg, k_msg, + file); + break; + + case IOCTL_HECI_WD: + DBG(": IOCTL_HECI_WD.\n"); + rets = heci_ioctl_wd(dev, if_num, k_msg, file_ext); + break; + + case IOCTL_HECI_BYPASS_WD: + DBG(": IOCTL_HECI_BYPASS_WD.\n"); + rets = heci_ioctl_bypass_wd(dev, if_num, k_msg, file_ext); + break; + + default: + rets = -EINVAL; + break; + } + return rets; +} + +/** + * heci_poll - the poll function + * + * @file: pointer to file structure + * @wait: pointer to poll_table structure + * + * returns poll mask + */ +static unsigned int heci_poll(struct file *file, poll_table *wait) +{ + int if_num = iminor(file->f_dentry->d_inode); + unsigned int mask = 0; + struct heci_file_private *file_ext = file->private_data; + struct iamt_heci_device *dev; + + if (!heci_device) + return mask; + + dev = pci_get_drvdata(heci_device); + + if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) + return mask; + + spin_lock_bh(&dev->device_lock); + if (dev->heci_state != HECI_ENABLED) { + spin_unlock_bh(&dev->device_lock); + return mask; + } + spin_unlock_bh(&dev->device_lock); + + if (file_ext == &dev->iamthif_file_ext) { + poll_wait(file, &dev->iamthif_file_ext.wait, wait); + spin_lock(&dev->iamthif_file_ext.file_lock); + if (dev->iamthif_state == HECI_IAMTHIF_READ_COMPLETE + && dev->iamthif_file_object == file) { + mask |= (POLLIN | POLLRDNORM); + spin_lock_bh(&dev->device_lock); + DBG("run next pthi cb\n"); + run_next_iamthif_cmd(dev); + spin_unlock_bh(&dev->device_lock); + } + spin_unlock(&dev->iamthif_file_ext.file_lock); + + } else{ + poll_wait(file, &file_ext->tx_wait, wait); + spin_lock(&file_ext->write_io_lock); + if (HECI_WRITE_COMPLETE == file_ext->writing_state) + mask |= (POLLIN | POLLRDNORM); + + spin_unlock(&file_ext->write_io_lock); + } + + return mask; +} + +#ifdef CONFIG_PM +static int heci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct iamt_heci_device *dev = pci_get_drvdata(pdev); + int err = 0; + + spin_lock_bh(&dev->device_lock); + if (dev->reinit_tsk != NULL) { + kthread_stop(dev->reinit_tsk); + dev->reinit_tsk = NULL; + } + spin_unlock_bh(&dev->device_lock); + + /* Stop watchdog if exists */ + del_timer_sync(&dev->wd_timer); + if (dev->wd_file_ext.state == HECI_FILE_CONNECTED + && dev->wd_timeout) { + spin_lock_bh(&dev->device_lock); + g_sus_wd_timeout = dev->wd_timeout; + dev->wd_timeout = 0; + dev->wd_due_counter = 0; + memcpy(dev->wd_data, heci_stop_wd_params, + HECI_WD_PARAMS_SIZE); + dev->stop = 1; + if (dev->host_buffer_is_empty && + flow_ctrl_creds(dev, &dev->wd_file_ext)) { + dev->host_buffer_is_empty = 0; + if (!heci_send_wd(dev)) + DBG("send stop WD failed\n"); + else + flow_ctrl_reduce(dev, &dev->wd_file_ext); + + dev->wd_pending = 0; + } else { + dev->wd_pending = 1; + } + spin_unlock_bh(&dev->device_lock); + dev->wd_stoped = 0; + + err = wait_event_interruptible_timeout(dev->wait_stop_wd, + (dev->wd_stoped), + 10 * HZ); + if (!dev->wd_stoped) + DBG("stop wd failed to complete.\n"); + else { + DBG("stop wd complete %d.\n", err); + err = 0; + } + } + /* Set new heci state */ + spin_lock_bh(&dev->device_lock); + if (dev->heci_state == HECI_ENABLED || + dev->heci_state == HECI_RECOVERING_FROM_RESET) { + dev->heci_state = HECI_POWER_DOWN; + heci_reset(dev, 0); + } + spin_unlock_bh(&dev->device_lock); + + pci_save_state(pdev); + + pci_disable_device(pdev); + free_irq(pdev->irq, dev); + + pci_set_power_state(pdev, PCI_D3hot); + + return err; +} + +static int heci_resume(struct pci_dev *pdev) +{ + struct iamt_heci_device *dev; + int err = 0; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + dev = pci_get_drvdata(pdev); + if (!dev) + return -ENODEV; + + /* request and enable interrupt */ + err = request_irq(pdev->irq, heci_isr_interrupt, IRQF_SHARED, + heci_driver_name, dev); + if (err) { + printk(KERN_ERR "heci: Request_irq failure. irq = %d \n", + pdev->irq); + return err; + } + + spin_lock_bh(&dev->device_lock); + dev->heci_state = HECI_POWER_UP; + heci_reset(dev, 1); + spin_unlock_bh(&dev->device_lock); + + /* Start watchdog if stopped in suspend */ + if (g_sus_wd_timeout != 0) { + dev->wd_timeout = g_sus_wd_timeout; + + memcpy(dev->wd_data, heci_start_wd_params, + HECI_WD_PARAMS_SIZE); + memcpy(dev->wd_data + HECI_WD_PARAMS_SIZE, + &dev->wd_timeout, sizeof(__u16)); + dev->wd_due_counter = 1; + + if (dev->wd_timeout) + mod_timer(&dev->wd_timer, jiffies); + + g_sus_wd_timeout = 0; + } + return err; +} +#endif + +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Intel(R) Management Engine Interface"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(HECI_DRIVER_VERSION); diff --git a/drivers/staging/heci/heci_version.h b/drivers/staging/heci/heci_version.h new file mode 100644 index 000000000000..3007aa6e17d4 --- /dev/null +++ b/drivers/staging/heci/heci_version.h @@ -0,0 +1,54 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2008 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifndef HECI_VERSION_H +#define HECI_VERSION_H + +#define MAJOR_VERSION 5 +#define MINOR_VERSION 0 +#define QUICK_FIX_NUMBER 0 +#define VER_BUILD 31 + +#define HECI_DRV_VER1 __stringify(MAJOR_VERSION) "." __stringify(MINOR_VERSION) +#define HECI_DRV_VER2 __stringify(QUICK_FIX_NUMBER) "." __stringify(VER_BUILD) + +#define HECI_DRIVER_VERSION HECI_DRV_VER1 "." HECI_DRV_VER2 + +#endif diff --git a/drivers/staging/heci/interrupt.c b/drivers/staging/heci/interrupt.c new file mode 100644 index 000000000000..aacd26243988 --- /dev/null +++ b/drivers/staging/heci/interrupt.c @@ -0,0 +1,1553 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2008 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include + +#include "heci.h" +#include "heci_interface.h" + +/* + * interrupt function prototypes + */ +static void heci_bh_handler(struct work_struct *work); +static int heci_bh_read_handler(struct io_heci_list *complete_list, + struct iamt_heci_device *dev, + __s32 *slots); +static int heci_bh_write_handler(struct io_heci_list *complete_list, + struct iamt_heci_device *dev, + __s32 *slots); +static void heci_bh_read_bus_message(struct iamt_heci_device *dev, + struct heci_msg_hdr *heci_hdr); +static int heci_bh_read_pthi_message(struct io_heci_list *complete_list, + struct iamt_heci_device *dev, + struct heci_msg_hdr *heci_hdr); +static int heci_bh_read_client_message(struct io_heci_list *complete_list, + struct iamt_heci_device *dev, + struct heci_msg_hdr *heci_hdr); +static void heci_client_connect_response(struct iamt_heci_device *dev, + struct hbm_client_connect_response *connect_res); +static void heci_client_disconnect_response(struct iamt_heci_device *dev, + struct hbm_client_connect_response *disconnect_res); +static void heci_client_flow_control_response(struct iamt_heci_device *dev, + struct hbm_flow_control *flow_control); +static void heci_client_disconnect_request(struct iamt_heci_device *dev, + struct hbm_client_disconnect_request *disconnect_req); + + +/** + * heci_isr_interrupt - The ISR of the HECI device + * + * @irq: The irq number + * @dev_id: pointer to the device structure + * + * returns irqreturn_t + */ +irqreturn_t heci_isr_interrupt(int irq, void *dev_id) +{ + int err; + struct iamt_heci_device *dev = (struct iamt_heci_device *) dev_id; + + dev->host_hw_state = read_heci_register(dev, H_CSR); + + if ((dev->host_hw_state & H_IS) != H_IS) + return IRQ_NONE; + + /* disable interrupts */ + heci_csr_disable_interrupts(dev); + + /* + * Our device interrupted, schedule work the heci_bh_handler + * to handle the interrupt processing. This needs to be a + * workqueue item since the handler can sleep. + */ + PREPARE_WORK(&dev->work, heci_bh_handler); + DBG("schedule work the heci_bh_handler.\n"); + err = schedule_work(&dev->work); + if (!err) { + printk(KERN_ERR "heci: schedule the heci_bh_handler" + " failed error=%x\n", err); + } + return IRQ_HANDLED; +} + +/** + * _heci_cmpl - process completed operation. + * + * @file_ext: private data of the file object. + * @priv_cb_pos: callback block. + */ +static void _heci_cmpl(struct heci_file_private *file_ext, + struct heci_cb_private *priv_cb_pos) +{ + if (priv_cb_pos->major_file_operations == HECI_WRITE) { + heci_free_cb_private(priv_cb_pos); + DBG("completing write call back.\n"); + file_ext->writing_state = HECI_WRITE_COMPLETE; + if ((&file_ext->tx_wait) && + waitqueue_active(&file_ext->tx_wait)) + wake_up_interruptible(&file_ext->tx_wait); + + } else if (priv_cb_pos->major_file_operations == HECI_READ + && HECI_READING == file_ext->reading_state) { + DBG("completing read call back information= %lu\n", + priv_cb_pos->information); + file_ext->reading_state = HECI_READ_COMPLETE; + if ((&file_ext->rx_wait) && + waitqueue_active(&file_ext->rx_wait)) + wake_up_interruptible(&file_ext->rx_wait); + + } +} + +/** + * _heci_cmpl_iamthif - process completed iamthif operation. + * + * @dev: Device object for our driver. + * @priv_cb_pos: callback block. + */ +static void _heci_cmpl_iamthif(struct iamt_heci_device *dev, + struct heci_cb_private *priv_cb_pos) +{ + if (dev->iamthif_canceled != 1) { + dev->iamthif_state = HECI_IAMTHIF_READ_COMPLETE; + dev->iamthif_stall_timer = 0; + memcpy(priv_cb_pos->response_buffer.data, + dev->iamthif_msg_buf, + dev->iamthif_msg_buf_index); + list_add_tail(&priv_cb_pos->cb_list, + &dev->pthi_read_complete_list.heci_cb.cb_list); + DBG("pthi read completed.\n"); + } else { + run_next_iamthif_cmd(dev); + } + if (&dev->iamthif_file_ext.wait) { + DBG("completing pthi call back.\n"); + wake_up_interruptible(&dev->iamthif_file_ext.wait); + } +} +/** + * heci_bh_handler - function called after ISR to handle the interrupt + * processing. + * + * @work: pointer to the work structure + * + * NOTE: This function is called by schedule work + */ +static void heci_bh_handler(struct work_struct *work) +{ + struct iamt_heci_device *dev = + container_of(work, struct iamt_heci_device, work); + struct io_heci_list complete_list; + __s32 slots; + int rets; + struct heci_cb_private *cb_pos = NULL, *cb_next = NULL; + struct heci_file_private *file_ext; + int bus_message_received = 0; + struct task_struct *tsk; + + DBG("function called after ISR to handle the interrupt processing.\n"); + /* initialize our complete list */ + spin_lock_bh(&dev->device_lock); + heci_initialize_list(&complete_list, dev); + dev->host_hw_state = read_heci_register(dev, H_CSR); + dev->me_hw_state = read_heci_register(dev, ME_CSR_HA); + + /* check if ME wants a reset */ + if (((dev->me_hw_state & ME_RDY_HRA) == 0) + && (dev->heci_state != HECI_RESETING) + && (dev->heci_state != HECI_INITIALIZING)) { + DBG("FW not ready.\n"); + heci_reset(dev, 1); + spin_unlock_bh(&dev->device_lock); + return; + } + + /* check if we need to start the dev */ + if ((dev->host_hw_state & H_RDY) == 0) { + if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) { + DBG("we need to start the dev.\n"); + dev->host_hw_state |= (H_IE | H_IG | H_RDY); + heci_set_csr_register(dev); + if (dev->heci_state == HECI_INITIALIZING) { + dev->recvd_msg = 1; + spin_unlock_bh(&dev->device_lock); + wake_up_interruptible(&dev->wait_recvd_msg); + return; + + } else { + spin_unlock_bh(&dev->device_lock); + tsk = kthread_run(heci_task_initialize_clients, + dev, "heci_reinit"); + if (IS_ERR(tsk)) { + int rc = PTR_ERR(tsk); + printk(KERN_WARNING "heci: Unable to" + "start the heci thread: %d\n", rc); + } + return; + } + } else { + DBG("enable interrupt FW not ready.\n"); + heci_csr_enable_interrupts(dev); + spin_unlock_bh(&dev->device_lock); + return; + } + } + /* check slots avalable for reading */ + slots = count_full_read_slots(dev); + DBG("slots =%08x extra_write_index =%08x.\n", + slots, dev->extra_write_index); + while ((slots > 0) && (!dev->extra_write_index)) { + DBG("slots =%08x extra_write_index =%08x.\n", slots, + dev->extra_write_index); + DBG("call heci_bh_read_handler.\n"); + rets = heci_bh_read_handler(&complete_list, dev, &slots); + if (rets != 0) + goto end; + } + rets = heci_bh_write_handler(&complete_list, dev, &slots); +end: + DBG("end of bottom half function.\n"); + dev->host_hw_state = read_heci_register(dev, H_CSR); + dev->host_buffer_is_empty = host_buffer_is_empty(dev); + + if ((dev->host_hw_state & H_IS) == H_IS) { + /* acknowledge interrupt and disable interrupts */ + heci_csr_disable_interrupts(dev); + + PREPARE_WORK(&dev->work, heci_bh_handler); + DBG("schedule work the heci_bh_handler.\n"); + rets = schedule_work(&dev->work); + if (!rets) { + printk(KERN_ERR "heci: schedule the heci_bh_handler" + " failed error=%x\n", rets); + } + } else { + heci_csr_enable_interrupts(dev); + } + + if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { + DBG("received waiting bus message\n"); + bus_message_received = 1; + } + spin_unlock_bh(&dev->device_lock); + if (bus_message_received) { + DBG("wake up dev->wait_recvd_msg\n"); + wake_up_interruptible(&dev->wait_recvd_msg); + bus_message_received = 0; + } + if ((complete_list.status != 0) + || list_empty(&complete_list.heci_cb.cb_list)) + return; + + + list_for_each_entry_safe(cb_pos, cb_next, + &complete_list.heci_cb.cb_list, cb_list) { + file_ext = (struct heci_file_private *)cb_pos->file_private; + list_del(&cb_pos->cb_list); + if (file_ext != NULL) { + if (file_ext != &dev->iamthif_file_ext) { + DBG("completing call back.\n"); + _heci_cmpl(file_ext, cb_pos); + cb_pos = NULL; + } else if (file_ext == &dev->iamthif_file_ext) { + _heci_cmpl_iamthif(dev, cb_pos); + } + } + } +} + + +/** + * heci_bh_read_handler - bottom half read routine after ISR to + * handle the read processing. + * + * @cmpl_list: An instance of our list structure + * @dev: Device object for our driver + * @slots: slots to read. + * + * returns 0 on success, <0 on failure. + */ +static int heci_bh_read_handler(struct io_heci_list *cmpl_list, + struct iamt_heci_device *dev, + __s32 *slots) +{ + struct heci_msg_hdr *heci_hdr; + int ret = 0; + struct heci_file_private *file_pos = NULL; + struct heci_file_private *file_next = NULL; + + if (!dev->rd_msg_hdr) { + dev->rd_msg_hdr = read_heci_register(dev, ME_CB_RW); + DBG("slots=%08x.\n", *slots); + (*slots)--; + DBG("slots=%08x.\n", *slots); + } + heci_hdr = (struct heci_msg_hdr *) &dev->rd_msg_hdr; + DBG("heci_hdr->length =%d\n", heci_hdr->length); + + if ((heci_hdr->reserved) || !(dev->rd_msg_hdr)) { + DBG("corrupted message header.\n"); + ret = -ECORRUPTED_MESSAGE_HEADER; + goto end; + } + + if ((heci_hdr->host_addr) || (heci_hdr->me_addr)) { + list_for_each_entry_safe(file_pos, file_next, + &dev->file_list, link) { + DBG("list_for_each_entry_safe read host" + " client = %d, ME client = %d\n", + file_pos->host_client_id, + file_pos->me_client_id); + if ((file_pos->host_client_id == heci_hdr->host_addr) + && (file_pos->me_client_id == heci_hdr->me_addr)) + break; + } + + if (&file_pos->link == &dev->file_list) { + DBG("corrupted message header\n"); + ret = -ECORRUPTED_MESSAGE_HEADER; + goto end; + } + } + if (((*slots) * sizeof(__u32)) < heci_hdr->length) { + DBG("we can't read the message slots=%08x.\n", *slots); + /* we can't read the message */ + ret = -ERANGE; + goto end; + } + + /* decide where to read the message too */ + if (!heci_hdr->host_addr) { + DBG("call heci_bh_read_bus_message.\n"); + heci_bh_read_bus_message(dev, heci_hdr); + DBG("end heci_bh_read_bus_message.\n"); + } else if ((heci_hdr->host_addr == dev->iamthif_file_ext.host_client_id) + && (HECI_FILE_CONNECTED == dev->iamthif_file_ext.state) + && (dev->iamthif_state == HECI_IAMTHIF_READING)) { + DBG("call heci_bh_read_iamthif_message.\n"); + DBG("heci_hdr->length =%d\n", heci_hdr->length); + ret = heci_bh_read_pthi_message(cmpl_list, dev, heci_hdr); + if (ret != 0) + goto end; + + } else { + DBG("call heci_bh_read_client_message.\n"); + ret = heci_bh_read_client_message(cmpl_list, dev, heci_hdr); + if (ret != 0) + goto end; + + } + + /* reset the number of slots and header */ + *slots = count_full_read_slots(dev); + dev->rd_msg_hdr = 0; + + if (*slots == -ESLOTS_OVERFLOW) { + /* overflow - reset */ + DBG("reseting due to slots overflow.\n"); + /* set the event since message has been read */ + ret = -ERANGE; + goto end; + } +end: + return ret; +} + + +/** + * heci_bh_read_bus_message - bottom half read routine after ISR to + * handle the read bus message cmd processing. + * + * @dev: Device object for our driver + * @heci_hdr: header of bus message + */ +static void heci_bh_read_bus_message(struct iamt_heci_device *dev, + struct heci_msg_hdr *heci_hdr) +{ + struct heci_bus_message *heci_msg; + struct hbm_host_version_response *version_res; + struct hbm_client_connect_response *connect_res; + struct hbm_client_connect_response *disconnect_res; + struct hbm_flow_control *flow_control; + struct hbm_props_response *props_res; + struct hbm_host_enum_response *enum_res; + struct hbm_client_disconnect_request *disconnect_req; + struct hbm_host_stop_request *h_stop_req; + int i; + unsigned char *buffer; + + /* read the message to our buffer */ + buffer = (unsigned char *) dev->rd_msg_buf; + BUG_ON(heci_hdr->length >= sizeof(dev->rd_msg_buf)); + heci_read_slots(dev, buffer, heci_hdr->length); + heci_msg = (struct heci_bus_message *) buffer; + + switch (*(__u8 *) heci_msg) { + case HOST_START_RES_CMD: + version_res = (struct hbm_host_version_response *) heci_msg; + if (version_res->host_version_supported) { + dev->version.major_version = HBM_MAJOR_VERSION; + dev->version.minor_version = HBM_MINOR_VERSION; + } else { + dev->version = version_res->me_max_version; + } + dev->recvd_msg = 1; + DBG("host start response message received.\n"); + break; + + case CLIENT_CONNECT_RES_CMD: + connect_res = + (struct hbm_client_connect_response *) heci_msg; + heci_client_connect_response(dev, connect_res); + DBG("client connect response message received.\n"); + wake_up(&dev->wait_recvd_msg); + break; + + case CLIENT_DISCONNECT_RES_CMD: + disconnect_res = + (struct hbm_client_connect_response *) heci_msg; + heci_client_disconnect_response(dev, disconnect_res); + DBG("client disconnect response message received.\n"); + wake_up(&dev->wait_recvd_msg); + break; + + case HECI_FLOW_CONTROL_CMD: + flow_control = (struct hbm_flow_control *) heci_msg; + heci_client_flow_control_response(dev, flow_control); + DBG("client flow control response message received.\n"); + break; + + case HOST_CLIENT_PROPERTEIS_RES_CMD: + props_res = (struct hbm_props_response *) heci_msg; + if (props_res->status != 0) { + BUG(); + break; + } + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (dev->me_clients[i].client_id == + props_res->address) { + dev->me_clients[i].props = + props_res->client_properties; + break; + } + + } + dev->recvd_msg = 1; + break; + + case HOST_ENUM_RES_CMD: + enum_res = (struct hbm_host_enum_response *) heci_msg; + memcpy(dev->heci_me_clients, enum_res->valid_addresses, 32); + dev->recvd_msg = 1; + break; + + case HOST_STOP_RES_CMD: + dev->heci_state = HECI_DISABLED; + DBG("reseting because of FW stop response.\n"); + heci_reset(dev, 1); + break; + + case CLIENT_DISCONNECT_REQ_CMD: + /* search for client */ + disconnect_req = + (struct hbm_client_disconnect_request *) heci_msg; + heci_client_disconnect_request(dev, disconnect_req); + break; + + case ME_STOP_REQ_CMD: + /* prepare stop request */ + heci_hdr = (struct heci_msg_hdr *) &dev->ext_msg_buf[0]; + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = sizeof(struct hbm_host_stop_request); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + h_stop_req = + (struct hbm_host_stop_request *) &dev->ext_msg_buf[1]; + memset(h_stop_req, 0, sizeof(struct hbm_host_stop_request)); + h_stop_req->cmd.cmd = HOST_STOP_REQ_CMD; + h_stop_req->reason = DRIVER_STOP_REQUEST; + h_stop_req->reserved[0] = 0; + h_stop_req->reserved[1] = 0; + dev->extra_write_index = 2; + break; + + default: + BUG(); + break; + + } +} + +/** + * heci_bh_read_pthi_message - bottom half read routine after ISR to + * handle the read pthi message data processing. + * + * @complete_list: An instance of our list structure + * @dev: Device object for our driver + * @heci_hdr: header of pthi message + * + * returns 0 on success, <0 on failure. + */ +static int heci_bh_read_pthi_message(struct io_heci_list *complete_list, + struct iamt_heci_device *dev, + struct heci_msg_hdr *heci_hdr) +{ + struct heci_file_private *file_ext; + struct heci_cb_private *priv_cb; + unsigned char *buffer; + + BUG_ON(heci_hdr->me_addr != dev->iamthif_file_ext.me_client_id); + BUG_ON(dev->iamthif_state != HECI_IAMTHIF_READING); + + buffer = (unsigned char *) (dev->iamthif_msg_buf + + dev->iamthif_msg_buf_index); + BUG_ON(sizeof(dev->iamthif_msg_buf) < + (dev->iamthif_msg_buf_index + heci_hdr->length)); + + heci_read_slots(dev, buffer, heci_hdr->length); + + dev->iamthif_msg_buf_index += heci_hdr->length; + + if (!(heci_hdr->msg_complete)) + return 0; + + DBG("pthi_message_buffer_index=%d\n", heci_hdr->length); + DBG("completed pthi read.\n "); + if (!dev->iamthif_current_cb) + return -ENODEV; + + priv_cb = dev->iamthif_current_cb; + dev->iamthif_current_cb = NULL; + + file_ext = (struct heci_file_private *)priv_cb->file_private; + if (!file_ext) + return -ENODEV; + + dev->iamthif_stall_timer = 0; + priv_cb->information = dev->iamthif_msg_buf_index; + priv_cb->read_time = get_seconds(); + if ((dev->iamthif_ioctl) && (file_ext == &dev->iamthif_file_ext)) { + /* found the iamthif cb */ + DBG("complete the pthi read cb.\n "); + if (&dev->iamthif_file_ext) { + DBG("add the pthi read cb to complete.\n "); + list_add_tail(&priv_cb->cb_list, + &complete_list->heci_cb.cb_list); + } + } + return 0; +} + +/** + * _heci_bh_state_ok - check if heci header matches file private data + * + * @file_ext: private data of the file object + * @heci_hdr: header of heci client message + * + * returns !=0 if matches, 0 if no match. + */ +static int _heci_bh_state_ok(struct heci_file_private *file_ext, + struct heci_msg_hdr *heci_hdr) +{ + return ((file_ext->host_client_id == heci_hdr->host_addr) + && (file_ext->me_client_id == heci_hdr->me_addr) + && (file_ext->state == HECI_FILE_CONNECTED) + && (HECI_READ_COMPLETE != file_ext->reading_state)); +} + +/** + * heci_bh_read_client_message - bottom half read routine after ISR to + * handle the read heci client message data processing. + * + * @complete_list: An instance of our list structure + * @dev: Device object for our driver + * @heci_hdr: header of heci client message + * + * returns 0 on success, <0 on failure. + */ +static int heci_bh_read_client_message(struct io_heci_list *complete_list, + struct iamt_heci_device *dev, + struct heci_msg_hdr *heci_hdr) +{ + struct heci_file_private *file_ext; + struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL; + unsigned char *buffer = NULL; + + DBG("start client msg\n"); + if (!((dev->read_list.status == 0) && + !list_empty(&dev->read_list.heci_cb.cb_list))) + goto quit; + + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &dev->read_list.heci_cb.cb_list, cb_list) { + file_ext = (struct heci_file_private *) + priv_cb_pos->file_private; + if ((file_ext != NULL) && + (_heci_bh_state_ok(file_ext, heci_hdr))) { + spin_lock(&file_ext->read_io_lock); + file_ext->reading_state = HECI_READING; + buffer = (unsigned char *) + (priv_cb_pos->response_buffer.data + + priv_cb_pos->information); + BUG_ON(priv_cb_pos->response_buffer.size < + heci_hdr->length + + priv_cb_pos->information); + + if (priv_cb_pos->response_buffer.size < + heci_hdr->length + + priv_cb_pos->information) { + DBG("message overflow.\n"); + list_del(&priv_cb_pos->cb_list); + spin_unlock(&file_ext->read_io_lock); + return -ENOMEM; + } + if (buffer) { + heci_read_slots(dev, buffer, + heci_hdr->length); + } + priv_cb_pos->information += heci_hdr->length; + if (heci_hdr->msg_complete) { + file_ext->status = 0; + list_del(&priv_cb_pos->cb_list); + spin_unlock(&file_ext->read_io_lock); + DBG("completed read host client = %d," + "ME client = %d, " + "data length = %lu\n", + file_ext->host_client_id, + file_ext->me_client_id, + priv_cb_pos->information); + + *(priv_cb_pos->response_buffer.data + + priv_cb_pos->information) = '\0'; + DBG("priv_cb_pos->res_buffer - %s\n", + priv_cb_pos->response_buffer.data); + list_add_tail(&priv_cb_pos->cb_list, + &complete_list->heci_cb.cb_list); + } else { + spin_unlock(&file_ext->read_io_lock); + } + + break; + } + + } + +quit: + DBG("message read\n"); + if (!buffer) { + heci_read_slots(dev, (unsigned char *) dev->rd_msg_buf, + heci_hdr->length); + DBG("discarding message, header=%08x.\n", + *(__u32 *) dev->rd_msg_buf); + } + + return 0; +} + +/** + * _heci_bh_iamthif_read - prepare to read iamthif data. + * + * @dev: Device object for our driver. + * @slots: free slots. + * + * returns 0, OK; otherwise, error. + */ +static int _heci_bh_iamthif_read(struct iamt_heci_device *dev, __s32 *slots) +{ + + if (((*slots) * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) + + sizeof(struct hbm_flow_control))) { + *slots -= (sizeof(struct heci_msg_hdr) + + sizeof(struct hbm_flow_control) + 3) / 4; + if (!heci_send_flow_control(dev, &dev->iamthif_file_ext)) { + DBG("iamthif flow control failed\n"); + } else { + DBG("iamthif flow control success\n"); + dev->iamthif_state = HECI_IAMTHIF_READING; + dev->iamthif_flow_control_pending = 0; + dev->iamthif_msg_buf_index = 0; + dev->iamthif_msg_buf_size = 0; + dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER; + dev->host_buffer_is_empty = host_buffer_is_empty(dev); + } + return 0; + } else { + return -ECOMPLETE_MESSAGE; + } +} + +/** + * _heci_bh_close - process close related operation. + * + * @dev: Device object for our driver. + * @slots: free slots. + * @priv_cb_pos: callback block. + * @file_ext: private data of the file object. + * @cmpl_list: complete list. + * + * returns 0, OK; otherwise, error. + */ +static int _heci_bh_close(struct iamt_heci_device *dev, __s32 *slots, + struct heci_cb_private *priv_cb_pos, + struct heci_file_private *file_ext, + struct io_heci_list *cmpl_list) +{ + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) + + sizeof(struct hbm_client_disconnect_request))) { + *slots -= (sizeof(struct heci_msg_hdr) + + sizeof(struct hbm_client_disconnect_request) + 3) / 4; + + if (!heci_disconnect(dev, file_ext)) { + file_ext->status = 0; + priv_cb_pos->information = 0; + list_move_tail(&priv_cb_pos->cb_list, + &cmpl_list->heci_cb.cb_list); + return -ECOMPLETE_MESSAGE; + } else { + file_ext->state = HECI_FILE_DISCONNECTING; + file_ext->status = 0; + priv_cb_pos->information = 0; + list_move_tail(&priv_cb_pos->cb_list, + &dev->ctrl_rd_list.heci_cb.cb_list); + file_ext->timer_count = HECI_CONNECT_TIMEOUT; + } + } else { + /* return the cancel routine */ + return -ECORRUPTED_MESSAGE_HEADER; + } + + return 0; +} + +/** + * _heci_hb_close - process read related operation. + * + * @dev: Device object for our driver. + * @slots: free slots. + * @priv_cb_pos: callback block. + * @file_ext: private data of the file object. + * @cmpl_list: complete list. + * + * returns 0, OK; otherwise, error. + */ +static int _heci_bh_read(struct iamt_heci_device *dev, __s32 *slots, + struct heci_cb_private *priv_cb_pos, + struct heci_file_private *file_ext, + struct io_heci_list *cmpl_list) +{ + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) + + sizeof(struct hbm_flow_control))) { + *slots -= (sizeof(struct heci_msg_hdr) + + sizeof(struct hbm_flow_control) + 3) / 4; + if (!heci_send_flow_control(dev, file_ext)) { + file_ext->status = -ENODEV; + priv_cb_pos->information = 0; + list_move_tail(&priv_cb_pos->cb_list, + &cmpl_list->heci_cb.cb_list); + return -ENODEV; + } else { + list_move_tail(&priv_cb_pos->cb_list, + &dev->read_list.heci_cb.cb_list); + } + } else { + /* return the cancel routine */ + list_del(&priv_cb_pos->cb_list); + return -ECORRUPTED_MESSAGE_HEADER; + } + + return 0; +} + + +/** + * _heci_bh_ioctl - process ioctl related operation. + * + * @dev: Device object for our driver. + * @slots: free slots. + * @priv_cb_pos: callback block. + * @file_ext: private data of the file object. + * @cmpl_list: complete list. + * + * returns 0, OK; otherwise, error. + */ +static int _heci_bh_ioctl(struct iamt_heci_device *dev, __s32 *slots, + struct heci_cb_private *priv_cb_pos, + struct heci_file_private *file_ext, + struct io_heci_list *cmpl_list) +{ + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) + + sizeof(struct hbm_client_connect_request))) { + file_ext->state = HECI_FILE_CONNECTING; + *slots -= (sizeof(struct heci_msg_hdr) + + sizeof(struct hbm_client_connect_request) + 3) / 4; + if (!heci_connect(dev, file_ext)) { + file_ext->status = -ENODEV; + priv_cb_pos->information = 0; + list_del(&priv_cb_pos->cb_list); + return -ENODEV; + } else { + list_move_tail(&priv_cb_pos->cb_list, + &dev->ctrl_rd_list.heci_cb.cb_list); + file_ext->timer_count = HECI_CONNECT_TIMEOUT; + } + } else { + /* return the cancel routine */ + list_del(&priv_cb_pos->cb_list); + return -ECORRUPTED_MESSAGE_HEADER; + } + + return 0; +} + +/** + * _heci_bh_cmpl - process completed and no-iamthif operation. + * + * @dev: Device object for our driver. + * @slots: free slots. + * @priv_cb_pos: callback block. + * @file_ext: private data of the file object. + * @cmpl_list: complete list. + * + * returns 0, OK; otherwise, error. + */ +static int _heci_bh_cmpl(struct iamt_heci_device *dev, __s32 *slots, + struct heci_cb_private *priv_cb_pos, + struct heci_file_private *file_ext, + struct io_heci_list *cmpl_list) +{ + struct heci_msg_hdr *heci_hdr; + + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) + + (priv_cb_pos->request_buffer.size - + priv_cb_pos->information))) { + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = file_ext->host_client_id; + heci_hdr->me_addr = file_ext->me_client_id; + heci_hdr->length = ((priv_cb_pos->request_buffer.size) - + (priv_cb_pos->information)); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + DBG("priv_cb_pos->request_buffer.size =%d" + "heci_hdr->msg_complete= %d\n", + priv_cb_pos->request_buffer.size, + heci_hdr->msg_complete); + DBG("priv_cb_pos->information =%lu\n", + priv_cb_pos->information); + DBG("heci_hdr->length =%d\n", + heci_hdr->length); + *slots -= (sizeof(struct heci_msg_hdr) + + heci_hdr->length + 3) / 4; + if (!heci_write_message(dev, heci_hdr, + (unsigned char *) + (priv_cb_pos->request_buffer.data + + priv_cb_pos->information), + heci_hdr->length)) { + file_ext->status = -ENODEV; + list_move_tail(&priv_cb_pos->cb_list, + &cmpl_list->heci_cb.cb_list); + return -ENODEV; + } else { + flow_ctrl_reduce(dev, file_ext); + file_ext->status = 0; + priv_cb_pos->information += heci_hdr->length; + list_move_tail(&priv_cb_pos->cb_list, + &dev->write_waiting_list.heci_cb.cb_list); + } + } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) { + /* buffer is still empty */ + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = file_ext->host_client_id; + heci_hdr->me_addr = file_ext->me_client_id; + heci_hdr->length = + (*slots * sizeof(__u32)) - sizeof(struct heci_msg_hdr); + heci_hdr->msg_complete = 0; + heci_hdr->reserved = 0; + + (*slots) -= (sizeof(struct heci_msg_hdr) + + heci_hdr->length + 3) / 4; + if (!heci_write_message(dev, heci_hdr, + (unsigned char *) + (priv_cb_pos->request_buffer.data + + priv_cb_pos->information), + heci_hdr->length)) { + file_ext->status = -ENODEV; + list_move_tail(&priv_cb_pos->cb_list, + &cmpl_list->heci_cb.cb_list); + return -ENODEV; + } else { + priv_cb_pos->information += heci_hdr->length; + DBG("priv_cb_pos->request_buffer.size =%d" + " heci_hdr->msg_complete= %d\n", + priv_cb_pos->request_buffer.size, + heci_hdr->msg_complete); + DBG("priv_cb_pos->information =%lu\n", + priv_cb_pos->information); + DBG("heci_hdr->length =%d\n", heci_hdr->length); + } + return -ECOMPLETE_MESSAGE; + } else { + return -ECORRUPTED_MESSAGE_HEADER; + } + + return 0; +} + +/** + * _heci_bh_cmpl_iamthif - process completed iamthif operation. + * + * @dev: Device object for our driver. + * @slots: free slots. + * @priv_cb_pos: callback block. + * @file_ext: private data of the file object. + * @cmpl_list: complete list. + * + * returns 0, OK; otherwise, error. + */ +static int _heci_bh_cmpl_iamthif(struct iamt_heci_device *dev, __s32 *slots, + struct heci_cb_private *priv_cb_pos, + struct heci_file_private *file_ext, + struct io_heci_list *cmpl_list) +{ + struct heci_msg_hdr *heci_hdr; + + if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) + + dev->iamthif_msg_buf_size - + dev->iamthif_msg_buf_index)) { + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = file_ext->host_client_id; + heci_hdr->me_addr = file_ext->me_client_id; + heci_hdr->length = dev->iamthif_msg_buf_size - + dev->iamthif_msg_buf_index; + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + *slots -= (sizeof(struct heci_msg_hdr) + + heci_hdr->length + 3) / 4; + + if (!heci_write_message(dev, heci_hdr, + (dev->iamthif_msg_buf + + dev->iamthif_msg_buf_index), + heci_hdr->length)) { + dev->iamthif_state = HECI_IAMTHIF_IDLE; + file_ext->status = -ENODEV; + list_del(&priv_cb_pos->cb_list); + return -ENODEV; + } else { + flow_ctrl_reduce(dev, file_ext); + dev->iamthif_msg_buf_index += heci_hdr->length; + priv_cb_pos->information = dev->iamthif_msg_buf_index; + file_ext->status = 0; + dev->iamthif_state = HECI_IAMTHIF_FLOW_CONTROL; + dev->iamthif_flow_control_pending = 1; + /* save iamthif cb sent to pthi client */ + dev->iamthif_current_cb = priv_cb_pos; + list_move_tail(&priv_cb_pos->cb_list, + &dev->write_waiting_list.heci_cb.cb_list); + + } + } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) { + /* buffer is still empty */ + heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0]; + heci_hdr->host_addr = file_ext->host_client_id; + heci_hdr->me_addr = file_ext->me_client_id; + heci_hdr->length = + (*slots * sizeof(__u32)) - sizeof(struct heci_msg_hdr); + heci_hdr->msg_complete = 0; + heci_hdr->reserved = 0; + + *slots -= (sizeof(struct heci_msg_hdr) + + heci_hdr->length + 3) / 4; + + if (!heci_write_message(dev, heci_hdr, + (dev->iamthif_msg_buf + + dev->iamthif_msg_buf_index), + heci_hdr->length)) { + file_ext->status = -ENODEV; + list_del(&priv_cb_pos->cb_list); + } else { + dev->iamthif_msg_buf_index += heci_hdr->length; + } + return -ECOMPLETE_MESSAGE; + } else { + return -ECORRUPTED_MESSAGE_HEADER; + } + + return 0; +} + +/** + * heci_bh_write_handler - bottom half write routine after + * ISR to handle the write processing. + * + * @cmpl_list: An instance of our list structure + * @dev: Device object for our driver + * @slots: slots to write. + * + * returns 0 on success, <0 on failure. + */ +static int heci_bh_write_handler(struct io_heci_list *cmpl_list, + struct iamt_heci_device *dev, + __s32 *slots) +{ + + struct heci_file_private *file_ext; + struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL; + struct io_heci_list *list; + int ret; + + if (!host_buffer_is_empty(dev)) { + DBG("host buffer is not empty.\n"); + return 0; + } + dev->write_hang = -1; + *slots = count_empty_write_slots(dev); + /* complete all waiting for write CB */ + DBG("complete all waiting for write cb.\n"); + + list = &dev->write_waiting_list; + if ((list->status == 0) + && !list_empty(&list->heci_cb.cb_list)) { + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &list->heci_cb.cb_list, cb_list) { + file_ext = (struct heci_file_private *) + priv_cb_pos->file_private; + if (file_ext != NULL) { + file_ext->status = 0; + list_del(&priv_cb_pos->cb_list); + if ((HECI_WRITING == file_ext->writing_state) && + (priv_cb_pos->major_file_operations == + HECI_WRITING) && + (file_ext != &dev->iamthif_file_ext)) { + DBG("HECI WRITE COMPLETE\n"); + file_ext->writing_state = + HECI_WRITE_COMPLETE; + list_add_tail(&priv_cb_pos->cb_list, + &cmpl_list->heci_cb.cb_list); + } + if (file_ext == &dev->iamthif_file_ext) { + DBG("check iamthif flow control.\n"); + if (dev->iamthif_flow_control_pending) { + ret = _heci_bh_iamthif_read(dev, + slots); + if (ret != 0) + return ret; + } + } + } + + } + } + + if ((dev->stop) && (!dev->wd_pending)) { + dev->wd_stoped = 1; + wake_up_interruptible(&dev->wait_stop_wd); + return 0; + } + + if (dev->extra_write_index != 0) { + DBG("extra_write_index =%d.\n", dev->extra_write_index); + heci_write_message(dev, + (struct heci_msg_hdr *) &dev->ext_msg_buf[0], + (unsigned char *) &dev->ext_msg_buf[1], + (dev->extra_write_index - 1) * sizeof(__u32)); + *slots -= dev->extra_write_index; + dev->extra_write_index = 0; + } + if (dev->heci_state == HECI_ENABLED) { + if ((dev->wd_pending) + && flow_ctrl_creds(dev, &dev->wd_file_ext)) { + if (!heci_send_wd(dev)) + DBG("wd send failed.\n"); + else + flow_ctrl_reduce(dev, &dev->wd_file_ext); + + dev->wd_pending = 0; + + if (dev->wd_timeout != 0) { + *slots -= (sizeof(struct heci_msg_hdr) + + HECI_START_WD_DATA_SIZE + 3) / 4; + dev->wd_due_counter = 2; + } else { + *slots -= (sizeof(struct heci_msg_hdr) + + HECI_WD_PARAMS_SIZE + 3) / 4; + dev->wd_due_counter = 0; + } + + } + } + if (dev->stop) + return ~ENODEV; + + /* complete control write list CB */ + if (dev->ctrl_wr_list.status == 0) { + /* complete control write list CB */ + DBG("complete control write list cb.\n"); + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &dev->ctrl_wr_list.heci_cb.cb_list, cb_list) { + file_ext = (struct heci_file_private *) + priv_cb_pos->file_private; + if (file_ext == NULL) { + list_del(&priv_cb_pos->cb_list); + return -ENODEV; + } + switch (priv_cb_pos->major_file_operations) { + case HECI_CLOSE: + /* send disconnect message */ + ret = _heci_bh_close(dev, slots, + priv_cb_pos, + file_ext, cmpl_list); + if (ret != 0) + return ret; + + break; + case HECI_READ: + /* send flow control message */ + ret = _heci_bh_read(dev, slots, + priv_cb_pos, + file_ext, cmpl_list); + if (ret != 0) + return ret; + + break; + case HECI_IOCTL: + /* connect message */ + if (!other_client_is_connecting(dev, file_ext)) + continue; + ret = _heci_bh_ioctl(dev, slots, + priv_cb_pos, + file_ext, cmpl_list); + if (ret != 0) + return ret; + + break; + + default: + BUG(); + } + + } + } + /* complete write list CB */ + if ((dev->write_list.status == 0) + && !list_empty(&dev->write_list.heci_cb.cb_list)) { + DBG("complete write list cb.\n"); + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &dev->write_list.heci_cb.cb_list, cb_list) { + file_ext = (struct heci_file_private *) + priv_cb_pos->file_private; + + if (file_ext != NULL) { + if (file_ext != &dev->iamthif_file_ext) { + if (!flow_ctrl_creds(dev, file_ext)) { + DBG("No flow control" + " credentials for client" + " %d, not sending.\n", + file_ext->host_client_id); + continue; + } + ret = _heci_bh_cmpl(dev, slots, + priv_cb_pos, + file_ext, + cmpl_list); + if (ret != 0) + return ret; + + } else if (file_ext == &dev->iamthif_file_ext) { + /* IAMTHIF IOCTL */ + DBG("complete pthi write cb.\n"); + if (!flow_ctrl_creds(dev, file_ext)) { + DBG("No flow control" + " credentials for pthi" + " client %d.\n", + file_ext->host_client_id); + continue; + } + ret = _heci_bh_cmpl_iamthif(dev, slots, + priv_cb_pos, + file_ext, + cmpl_list); + if (ret != 0) + return ret; + + } + } + + } + } + return 0; +} + + +/** + * is_treat_specially_client - check if the message belong + * to the file private data. + * + * @file_ext: private data of the file object + * @rs: connect response bus message + * @dev: Device object for our driver + * + * returns 0 on success, <0 on failure. + */ +static int is_treat_specially_client(struct heci_file_private *file_ext, + struct hbm_client_connect_response *rs) +{ + int ret = 0; + + if ((file_ext->host_client_id == rs->host_addr) && + (file_ext->me_client_id == rs->me_addr)) { + if (rs->status == 0) { + DBG("client connect status = 0x%08x.\n", rs->status); + file_ext->state = HECI_FILE_CONNECTED; + file_ext->status = 0; + } else { + DBG("client connect status = 0x%08x.\n", rs->status); + file_ext->state = HECI_FILE_DISCONNECTED; + file_ext->status = -ENODEV; + } + ret = 1; + } + DBG("client state = %d.\n", file_ext->state); + return ret; +} + +/** + * heci_client_connect_response - connect response bh routine + * + * @dev: Device object for our driver + * @rs: connect response bus message + */ +static void heci_client_connect_response(struct iamt_heci_device *dev, + struct hbm_client_connect_response *rs) +{ + + struct heci_file_private *file_ext; + struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL; + + /* if WD or iamthif client treat specially */ + + if ((is_treat_specially_client(&(dev->wd_file_ext), rs)) || + (is_treat_specially_client(&(dev->iamthif_file_ext), rs))) + return; + + if (dev->ctrl_rd_list.status == 0 + && !list_empty(&dev->ctrl_rd_list.heci_cb.cb_list)) { + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &dev->ctrl_rd_list.heci_cb.cb_list, cb_list) { + file_ext = (struct heci_file_private *) + priv_cb_pos->file_private; + if (file_ext == NULL) { + list_del(&priv_cb_pos->cb_list); + return; + } + if (HECI_IOCTL == priv_cb_pos->major_file_operations) { + if (is_treat_specially_client(file_ext, rs)) { + list_del(&priv_cb_pos->cb_list); + file_ext->status = 0; + file_ext->timer_count = 0; + break; + } + } + } + } +} + +/** + * heci_client_disconnect_response - disconnect response bh routine + * + * @dev: Device object for our driver + * @rs: disconnect response bus message + */ +static void heci_client_disconnect_response(struct iamt_heci_device *dev, + struct hbm_client_connect_response *rs) +{ + struct heci_file_private *file_ext; + struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL; + + if (dev->ctrl_rd_list.status == 0 + && !list_empty(&dev->ctrl_rd_list.heci_cb.cb_list)) { + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &dev->ctrl_rd_list.heci_cb.cb_list, cb_list) { + file_ext = (struct heci_file_private *) + priv_cb_pos->file_private; + + if (file_ext == NULL) { + list_del(&priv_cb_pos->cb_list); + return; + } + + DBG("list_for_each_entry_safe in ctrl_rd_list.\n"); + if ((file_ext->host_client_id == rs->host_addr) && + (file_ext->me_client_id == rs->me_addr)) { + + list_del(&priv_cb_pos->cb_list); + if (rs->status == 0) { + file_ext->state = + HECI_FILE_DISCONNECTED; + } + + file_ext->status = 0; + file_ext->timer_count = 0; + break; + } + } + } +} + +/** + * same_flow_addr - tell they have same address. + * + * @file: private data of the file object. + * @flow: flow control. + * + * returns !=0, same; 0,not. + */ +static int same_flow_addr(struct heci_file_private *file, + struct hbm_flow_control *flow) +{ + return ((file->host_client_id == flow->host_addr) + && (file->me_client_id == flow->me_addr)); +} + +/** + * add_single_flow_creds - add single buffer credentials. + * + * @file: private data ot the file object. + * @flow: flow control. + */ +static void add_single_flow_creds(struct iamt_heci_device *dev, + struct hbm_flow_control *flow) +{ + struct heci_me_client *client; + int i; + + for (i = 0; i < dev->num_heci_me_clients; i++) { + client = &dev->me_clients[i]; + if ((client != NULL) && + (flow->me_addr == client->client_id)) { + if (client->props.single_recv_buf != 0) { + client->flow_ctrl_creds++; + DBG("recv flow ctrl msg ME %d (single).\n", + flow->me_addr); + DBG("flow control credentials=%d.\n", + client->flow_ctrl_creds); + } else { + BUG(); /* error in flow control */ + } + } + } +} + +/** + * heci_client_flow_control_response - flow control response bh routine + * + * @dev: Device object for our driver + * @flow_control: flow control response bus message + */ +static void heci_client_flow_control_response(struct iamt_heci_device *dev, + struct hbm_flow_control *flow_control) +{ + struct heci_file_private *file_pos = NULL; + struct heci_file_private *file_next = NULL; + + if (flow_control->host_addr == 0) { + /* single receive buffer */ + add_single_flow_creds(dev, flow_control); + } else { + /* normal connection */ + list_for_each_entry_safe(file_pos, file_next, + &dev->file_list, link) { + DBG("list_for_each_entry_safe in file_list\n"); + + DBG("file_ext of host client %d ME client %d.\n", + file_pos->host_client_id, + file_pos->me_client_id); + DBG("flow ctrl msg for host %d ME %d.\n", + flow_control->host_addr, + flow_control->me_addr); + if (same_flow_addr(file_pos, flow_control)) { + DBG("recv ctrl msg for host %d ME %d.\n", + flow_control->host_addr, + flow_control->me_addr); + file_pos->flow_ctrl_creds++; + DBG("flow control credentials=%d.\n", + file_pos->flow_ctrl_creds); + break; + } + } + } +} + +/** + * same_disconn_addr - tell they have same address + * + * @file: private data of the file object. + * @disconn: disconnection request. + * + * returns !=0, same; 0,not. + */ +static int same_disconn_addr(struct heci_file_private *file, + struct hbm_client_disconnect_request *disconn) +{ + return ((file->host_client_id == disconn->host_addr) + && (file->me_client_id == disconn->me_addr)); +} + +/** + * heci_client_disconnect_request - disconnect request bh routine + * + * @dev: Device object for our driver. + * @disconnect_req: disconnect request bus message. + */ +static void heci_client_disconnect_request(struct iamt_heci_device *dev, + struct hbm_client_disconnect_request *disconnect_req) +{ + struct heci_msg_hdr *heci_hdr; + struct hbm_client_connect_response *disconnect_res; + struct heci_file_private *file_pos = NULL; + struct heci_file_private *file_next = NULL; + + list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) { + if (same_disconn_addr(file_pos, disconnect_req)) { + DBG("disconnect request host client %d ME client %d.\n", + disconnect_req->host_addr, + disconnect_req->me_addr); + file_pos->state = HECI_FILE_DISCONNECTED; + file_pos->timer_count = 0; + if (file_pos == &dev->wd_file_ext) { + dev->wd_due_counter = 0; + dev->wd_pending = 0; + } else if (file_pos == &dev->iamthif_file_ext) + dev->iamthif_timer = 0; + + /* prepare disconnect response */ + heci_hdr = + (struct heci_msg_hdr *) &dev->ext_msg_buf[0]; + heci_hdr->host_addr = 0; + heci_hdr->me_addr = 0; + heci_hdr->length = + sizeof(struct hbm_client_connect_response); + heci_hdr->msg_complete = 1; + heci_hdr->reserved = 0; + + disconnect_res = + (struct hbm_client_connect_response *) + &dev->ext_msg_buf[1]; + disconnect_res->host_addr = file_pos->host_client_id; + disconnect_res->me_addr = file_pos->me_client_id; + *(__u8 *) (&disconnect_res->cmd) = + CLIENT_DISCONNECT_RES_CMD; + disconnect_res->status = 0; + dev->extra_write_index = 2; + break; + } + } +} + +/** + * heci_timer - timer function. + * + * @data: pointer to the device structure + * + * NOTE: This function is called by timer interrupt work + */ +void heci_wd_timer(unsigned long data) +{ + struct iamt_heci_device *dev = (struct iamt_heci_device *) data; + + DBG("send watchdog.\n"); + spin_lock_bh(&dev->device_lock); + if (dev->heci_state != HECI_ENABLED) { + mod_timer(&dev->wd_timer, round_jiffies(jiffies + 2 * HZ)); + spin_unlock_bh(&dev->device_lock); + return; + } + if (dev->wd_file_ext.state != HECI_FILE_CONNECTED) { + mod_timer(&dev->wd_timer, round_jiffies(jiffies + 2 * HZ)); + spin_unlock_bh(&dev->device_lock); + return; + } + /* Watchdog */ + if ((dev->wd_due_counter != 0) && (dev->wd_bypass == 0)) { + if (--dev->wd_due_counter == 0) { + if (dev->host_buffer_is_empty && + flow_ctrl_creds(dev, &dev->wd_file_ext)) { + dev->host_buffer_is_empty = 0; + if (!heci_send_wd(dev)) { + DBG("wd send failed.\n"); + } else { + flow_ctrl_reduce(dev, + &dev->wd_file_ext); + } + + if (dev->wd_timeout != 0) + dev->wd_due_counter = 2; + else + dev->wd_due_counter = 0; + + } else + dev->wd_pending = 1; + + } + } + if (dev->iamthif_stall_timer != 0) { + if (--dev->iamthif_stall_timer == 0) { + DBG("reseting because of hang to PTHI.\n"); + heci_reset(dev, 1); + dev->iamthif_msg_buf_size = 0; + dev->iamthif_msg_buf_index = 0; + dev->iamthif_canceled = 0; + dev->iamthif_ioctl = 1; + dev->iamthif_state = HECI_IAMTHIF_IDLE; + dev->iamthif_timer = 0; + spin_unlock_bh(&dev->device_lock); + + if (dev->iamthif_current_cb) + heci_free_cb_private(dev->iamthif_current_cb); + + spin_lock_bh(&dev->device_lock); + dev->iamthif_file_object = NULL; + dev->iamthif_current_cb = NULL; + run_next_iamthif_cmd(dev); + } + } + mod_timer(&dev->wd_timer, round_jiffies(jiffies + 2 * HZ)); + spin_unlock_bh(&dev->device_lock); +} diff --git a/drivers/staging/heci/io_heci.c b/drivers/staging/heci/io_heci.c new file mode 100644 index 000000000000..f7544a7bbbe0 --- /dev/null +++ b/drivers/staging/heci/io_heci.c @@ -0,0 +1,847 @@ +/* + * Part of Intel(R) Manageability Engine Interface Linux driver + * + * Copyright (c) 2003 - 2008 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "heci_data_structures.h" +#include "heci.h" +#include "heci_interface.h" +#include "heci_version.h" + + +/** + * heci_ioctl_get_version - the get driver version IOCTL function + * + * @dev: Device object for our driver + * @if_num: minor number + * @*u_msg: pointer to user data struct in user space + * @k_msg: data in kernel on the stack + * @file_ext: private data of the file object + * + * returns 0 on success, <0 on failure. + */ +int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num, + struct heci_message_data __user *u_msg, + struct heci_message_data k_msg, + struct heci_file_private *file_ext) +{ + int rets = 0; + struct heci_driver_version *version; + struct heci_message_data res_msg; + + if ((if_num != HECI_MINOR_NUMBER) || (!dev) + || (!file_ext)) + return -ENODEV; + + if (k_msg.size < (sizeof(struct heci_driver_version) - 2)) { + DBG("user buffer less than heci_driver_version.\n"); + return -EMSGSIZE; + } + + res_msg.data = kmalloc(sizeof(struct heci_driver_version), GFP_KERNEL); + if (!res_msg.data) { + DBG("failed allocation response buffer size = %d.\n", + (int) sizeof(struct heci_driver_version)); + return -ENOMEM; + } + + version = (struct heci_driver_version *) res_msg.data; + version->major = MAJOR_VERSION; + version->minor = MINOR_VERSION; + version->hotfix = QUICK_FIX_NUMBER; + version->build = VER_BUILD; + res_msg.size = sizeof(struct heci_driver_version); + if (k_msg.size < sizeof(struct heci_driver_version)) + res_msg.size -= 2; + + rets = file_ext->status; + /* now copy the data to user space */ + if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) { + rets = -EFAULT; + goto end; + } + if (put_user(res_msg.size, &u_msg->size)) { + rets = -EFAULT; + goto end; + } +end: + kfree(res_msg.data); + return rets; +} + +/** + * heci_ioctl_connect_client - the connect to fw client IOCTL function + * + * @dev: Device object for our driver + * @if_num: minor number + * @*u_msg: pointer to user data struct in user space + * @k_msg: data in kernel on the stack + * @file_ext: private data of the file object + * + * returns 0 on success, <0 on failure. + */ +int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num, + struct heci_message_data __user *u_msg, + struct heci_message_data k_msg, + struct file *file) +{ + int rets = 0; + struct heci_message_data req_msg, res_msg; + struct heci_cb_private *priv_cb = NULL; + struct heci_client *client; + struct heci_file_private *file_ext; + struct heci_file_private *file_pos = NULL; + struct heci_file_private *file_next = NULL; + long timeout = 15; /*15 second */ + __u8 i; + int err = 0; + + if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file)) + return -ENODEV; + + file_ext = file->private_data; + if (!file_ext) + return -ENODEV; + + if (k_msg.size != sizeof(struct guid)) { + DBG("user buffer size is not equal to size of struct " + "guid(16).\n"); + return -EMSGSIZE; + } + + if (!k_msg.data) + return -EIO; + + req_msg.data = kmalloc(sizeof(struct guid), GFP_KERNEL); + res_msg.data = kmalloc(sizeof(struct heci_client), GFP_KERNEL); + + if (!res_msg.data) { + DBG("failed allocation response buffer size = %d.\n", + (int) sizeof(struct heci_client)); + kfree(req_msg.data); + return -ENOMEM; + } + if (!req_msg.data) { + DBG("failed allocation request buffer size = %d.\n", + (int) sizeof(struct guid)); + kfree(res_msg.data); + return -ENOMEM; + } + req_msg.size = sizeof(struct guid); + res_msg.size = sizeof(struct heci_client); + + /* copy the message to kernel space - + * use a pointer already copied into kernel space + */ + if (copy_from_user(req_msg.data, k_msg.data, k_msg.size)) { + rets = -EFAULT; + goto end; + } + /* buffered ioctl cb */ + priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL); + if (!priv_cb) { + rets = -ENOMEM; + goto end; + } + INIT_LIST_HEAD(&priv_cb->cb_list); + priv_cb->response_buffer.data = res_msg.data; + priv_cb->response_buffer.size = res_msg.size; + priv_cb->request_buffer.data = req_msg.data; + priv_cb->request_buffer.size = req_msg.size; + priv_cb->major_file_operations = HECI_IOCTL; + spin_lock_bh(&dev->device_lock); + if (dev->heci_state != HECI_ENABLED) { + rets = -ENODEV; + spin_unlock_bh(&dev->device_lock); + goto end; + } + if ((file_ext->state != HECI_FILE_INITIALIZING) && + (file_ext->state != HECI_FILE_DISCONNECTED)) { + rets = -EBUSY; + spin_unlock_bh(&dev->device_lock); + goto end; + } + + /* find ME client we're trying to connect to */ + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (memcmp((struct guid *)req_msg.data, + &dev->me_clients[i].props.protocol_name, + sizeof(struct guid)) == 0) { + if (dev->me_clients[i].props.fixed_address == 0) { + file_ext->me_client_id = + dev->me_clients[i].client_id; + file_ext->state = HECI_FILE_CONNECTING; + } + break; + } + } + /* if we're connecting to PTHI client so we will use the exist + * connection + */ + if (memcmp((struct guid *)req_msg.data, &heci_pthi_guid, + sizeof(struct guid)) == 0) { + if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) { + rets = -ENODEV; + spin_unlock_bh(&dev->device_lock); + goto end; + } + dev->heci_host_clients[file_ext->host_client_id / 8] &= + ~(1 << (file_ext->host_client_id % 8)); + list_for_each_entry_safe(file_pos, + file_next, &dev->file_list, link) { + if (heci_fe_same_id(file_ext, file_pos)) { + DBG("remove file private data node host" + " client = %d, ME client = %d.\n", + file_pos->host_client_id, + file_pos->me_client_id); + list_del(&file_pos->link); + } + + } + DBG("free file private data memory.\n"); + kfree(file_ext); + file_ext = NULL; + file->private_data = &dev->iamthif_file_ext; + client = (struct heci_client *) res_msg.data; + client->max_msg_length = + dev->me_clients[i].props.max_msg_length; + client->protocol_version = + dev->me_clients[i].props.protocol_version; + rets = dev->iamthif_file_ext.status; + spin_unlock_bh(&dev->device_lock); + + /* now copy the data to user space */ + if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) { + rets = -EFAULT; + goto end; + } + if (put_user(res_msg.size, &u_msg->size)) { + rets = -EFAULT; + goto end; + } + goto end; + } + spin_lock(&file_ext->file_lock); + if (file_ext->state != HECI_FILE_CONNECTING) { + rets = -ENODEV; + spin_unlock(&file_ext->file_lock); + spin_unlock_bh(&dev->device_lock); + goto end; + } + spin_unlock(&file_ext->file_lock); + /* prepare the output buffer */ + client = (struct heci_client *) res_msg.data; + client->max_msg_length = dev->me_clients[i].props.max_msg_length; + client->protocol_version = dev->me_clients[i].props.protocol_version; + if (dev->host_buffer_is_empty + && !other_client_is_connecting(dev, file_ext)) { + dev->host_buffer_is_empty = 0; + if (!heci_connect(dev, file_ext)) { + rets = -ENODEV; + spin_unlock_bh(&dev->device_lock); + goto end; + } else { + file_ext->timer_count = HECI_CONNECT_TIMEOUT; + priv_cb->file_private = file_ext; + list_add_tail(&priv_cb->cb_list, + &dev->ctrl_rd_list.heci_cb. + cb_list); + } + + + } else { + priv_cb->file_private = file_ext; + DBG("add connect cb to control write list.\n"); + list_add_tail(&priv_cb->cb_list, + &dev->ctrl_wr_list.heci_cb.cb_list); + } + spin_unlock_bh(&dev->device_lock); + err = wait_event_timeout(dev->wait_recvd_msg, + (HECI_FILE_CONNECTED == file_ext->state + || HECI_FILE_DISCONNECTED == file_ext->state), + timeout * HZ); + + if (HECI_FILE_CONNECTED == file_ext->state) { + DBG("successfully connected to FW client.\n"); + rets = file_ext->status; + /* now copy the data to user space */ + if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) { + rets = -EFAULT; + goto end; + } + if (put_user(res_msg.size, &u_msg->size)) { + rets = -EFAULT; + goto end; + } + goto end; + } else { + DBG("failed to connect to FW client.file_ext->state = %d.\n", + file_ext->state); + if (!err) { + DBG("wait_event_interruptible_timeout failed on client" + " connect message fw response message.\n"); + } + rets = -EFAULT; + goto remove_list; + } + +remove_list: + if (priv_cb) { + spin_lock_bh(&dev->device_lock); + heci_flush_list(&dev->ctrl_rd_list, file_ext); + heci_flush_list(&dev->ctrl_wr_list, file_ext); + spin_unlock_bh(&dev->device_lock); + } +end: + DBG("free connect cb memory."); + kfree(req_msg.data); + kfree(res_msg.data); + kfree(priv_cb); + return rets; +} + +/** + * heci_ioctl_wd - the wd IOCTL function + * + * @dev: Device object for our driver + * @if_num: minor number + * @k_msg: data in kernel on the stack + * @file_ext: private data of the file object + * + * returns 0 on success, <0 on failure. + */ +int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num, + struct heci_message_data k_msg, + struct heci_file_private *file_ext) +{ + int rets = 0; + struct heci_message_data req_msg; /*in kernel on the stack */ + + if (if_num != HECI_MINOR_NUMBER) + return -ENODEV; + + spin_lock(&file_ext->file_lock); + if (k_msg.size != HECI_WATCHDOG_DATA_SIZE) { + DBG("user buffer has invalid size.\n"); + spin_unlock(&file_ext->file_lock); + return -EMSGSIZE; + } + spin_unlock(&file_ext->file_lock); + + req_msg.data = kmalloc(HECI_WATCHDOG_DATA_SIZE, GFP_KERNEL); + if (!req_msg.data) { + DBG("failed allocation request buffer size = %d.\n", + HECI_WATCHDOG_DATA_SIZE); + return -ENOMEM; + } + req_msg.size = HECI_WATCHDOG_DATA_SIZE; + + /* copy the message to kernel space - use a pointer already + * copied into kernel space + */ + if (copy_from_user(req_msg.data, k_msg.data, req_msg.size)) { + rets = -EFAULT; + goto end; + } + spin_lock_bh(&dev->device_lock); + if (dev->heci_state != HECI_ENABLED) { + rets = -ENODEV; + spin_unlock_bh(&dev->device_lock); + goto end; + } + + if (dev->wd_file_ext.state != HECI_FILE_CONNECTED) { + rets = -ENODEV; + spin_unlock_bh(&dev->device_lock); + goto end; + } + if (!dev->asf_mode) { + rets = -EIO; + spin_unlock_bh(&dev->device_lock); + goto end; + } + + memcpy(&dev->wd_data[HECI_WD_PARAMS_SIZE], req_msg.data, + HECI_WATCHDOG_DATA_SIZE); + + dev->wd_timeout = (req_msg.data[1] << 8) + req_msg.data[0]; + dev->wd_pending = 0; + dev->wd_due_counter = 1; /* next timer */ + if (dev->wd_timeout == 0) { + memcpy(dev->wd_data, heci_stop_wd_params, + HECI_WD_PARAMS_SIZE); + } else { + memcpy(dev->wd_data, heci_start_wd_params, + HECI_WD_PARAMS_SIZE); + mod_timer(&dev->wd_timer, jiffies); + } + spin_unlock_bh(&dev->device_lock); +end: + kfree(req_msg.data); + return rets; +} + + +/** + * heci_ioctl_bypass_wd - the bypass_wd IOCTL function + * + * @dev: Device object for our driver + * @if_num: minor number + * @k_msg: data in kernel on the stack + * @file_ext: private data of the file object + * + * returns 0 on success, <0 on failure. + */ +int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num, + struct heci_message_data k_msg, + struct heci_file_private *file_ext) +{ + __u8 flag = 0; + int rets = 0; + + if (if_num != HECI_MINOR_NUMBER) + return -ENODEV; + + spin_lock(&file_ext->file_lock); + if (k_msg.size < 1) { + DBG("user buffer less than HECI_WATCHDOG_DATA_SIZE.\n"); + spin_unlock(&file_ext->file_lock); + return -EMSGSIZE; + } + spin_unlock(&file_ext->file_lock); + if (copy_from_user(&flag, k_msg.data, 1)) { + rets = -EFAULT; + goto end; + } + + spin_lock_bh(&dev->device_lock); + flag = flag ? (1) : (0); + dev->wd_bypass = flag; + spin_unlock_bh(&dev->device_lock); +end: + return rets; +} + +/** + * find_pthi_read_list_entry - finds a PTHIlist entry for current file + * + * @dev: Device object for our driver + * @file: pointer to file object + * + * returns returned a list entry on success, NULL on failure. + */ +struct heci_cb_private *find_pthi_read_list_entry( + struct iamt_heci_device *dev, + struct file *file) +{ + struct heci_file_private *file_ext_temp; + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; + + if ((dev->pthi_read_complete_list.status == 0) && + !list_empty(&dev->pthi_read_complete_list.heci_cb.cb_list)) { + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &dev->pthi_read_complete_list.heci_cb.cb_list, cb_list) { + file_ext_temp = (struct heci_file_private *) + priv_cb_pos->file_private; + if ((file_ext_temp != NULL) && + (file_ext_temp == &dev->iamthif_file_ext) && + (priv_cb_pos->file_object == file)) + return priv_cb_pos; + } + } + return NULL; +} + +/** + * pthi_read - read data from pthi client + * + * @dev: Device object for our driver + * @if_num: minor number + * @file: pointer to file object + * @*ubuf: pointer to user data in user space + * @length: data length to read + * @offset: data read offset + * + * returns + * returned data length on success, + * zero if no data to read, + * negative on failure. + */ +int pthi_read(struct iamt_heci_device *dev, int if_num, struct file *file, + char __user *ubuf, size_t length, loff_t *offset) +{ + int rets = 0; + struct heci_cb_private *priv_cb = NULL; + struct heci_file_private *file_ext = file->private_data; + __u8 i; + unsigned long currtime = get_seconds(); + + if ((if_num != HECI_MINOR_NUMBER) || (!dev)) + return -ENODEV; + + if ((file_ext == NULL) || (file_ext != &dev->iamthif_file_ext)) + return -ENODEV; + + spin_lock_bh(&dev->device_lock); + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (dev->me_clients[i].client_id == + dev->iamthif_file_ext.me_client_id) + break; + } + BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id); + if ((i == dev->num_heci_me_clients) + || (dev->me_clients[i].client_id != + dev->iamthif_file_ext.me_client_id)) { + DBG("PTHI client not found.\n"); + spin_unlock_bh(&dev->device_lock); + return -ENODEV; + } + priv_cb = find_pthi_read_list_entry(dev, file); + if (!priv_cb) { + spin_unlock_bh(&dev->device_lock); + return 0; /* No more data to read */ + } else { + if (priv_cb && + (currtime - priv_cb->read_time > IAMTHIF_READ_TIMER)) { + /* 15 sec for the message has expired */ + list_del(&priv_cb->cb_list); + spin_unlock_bh(&dev->device_lock); + rets = -ETIMEDOUT; + goto free; + } + /* if the whole message will fit remove it from the list */ + if ((priv_cb->information >= *offset) && + (length >= (priv_cb->information - *offset))) + list_del(&priv_cb->cb_list); + else if ((priv_cb->information > 0) && + (priv_cb->information <= *offset)) { + /* end of the message has been reached */ + list_del(&priv_cb->cb_list); + rets = 0; + spin_unlock_bh(&dev->device_lock); + goto free; + } + /* else means that not full buffer will be read and do not + * remove message from deletion list + */ + } + DBG("pthi priv_cb->response_buffer size - %d\n", + priv_cb->response_buffer.size); + DBG("pthi priv_cb->information - %lu\n", + priv_cb->information); + spin_unlock_bh(&dev->device_lock); + + /* length is being turncated to PAGE_SIZE, however, + * the information may be longer */ + length = length < (priv_cb->information - *offset) ? + length : (priv_cb->information - *offset); + + if (copy_to_user(ubuf, + priv_cb->response_buffer.data + *offset, + length)) + rets = -EFAULT; + else { + rets = length; + if ((*offset + length) < priv_cb->information) { + *offset += length; + goto out; + } + } +free: + DBG("free pthi cb memory.\n"); + *offset = 0; + heci_free_cb_private(priv_cb); +out: + return rets; +} + +/** + * heci_start_read - the start read client message function. + * + * @dev: Device object for our driver + * @if_num: minor number + * @file_ext: private data of the file object + * + * returns 0 on success, <0 on failure. + */ +int heci_start_read(struct iamt_heci_device *dev, int if_num, + struct heci_file_private *file_ext) +{ + int rets = 0; + __u8 i; + struct heci_cb_private *priv_cb = NULL; + + if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) { + DBG("received wrong function input param.\n"); + return -ENODEV; + } + if (file_ext->state != HECI_FILE_CONNECTED) + return -ENODEV; + + spin_lock_bh(&dev->device_lock); + if (dev->heci_state != HECI_ENABLED) { + spin_unlock_bh(&dev->device_lock); + return -ENODEV; + } + spin_unlock_bh(&dev->device_lock); + DBG("check if read is pending.\n"); + if ((file_ext->read_pending) || (file_ext->read_cb != NULL)) { + DBG("read is pending.\n"); + return -EBUSY; + } + priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL); + if (!priv_cb) + return -ENOMEM; + + DBG("allocation call back success\n" + "host client = %d, ME client = %d\n", + file_ext->host_client_id, file_ext->me_client_id); + spin_lock_bh(&dev->device_lock); + for (i = 0; i < dev->num_heci_me_clients; i++) { + if (dev->me_clients[i].client_id == file_ext->me_client_id) + break; + + } + + BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id); + if (i == dev->num_heci_me_clients) { + rets = -ENODEV; + goto unlock; + } + + priv_cb->response_buffer.size = dev->me_clients[i].props.max_msg_length; + spin_unlock_bh(&dev->device_lock); + priv_cb->response_buffer.data = + kmalloc(priv_cb->response_buffer.size, GFP_KERNEL); + if (!priv_cb->response_buffer.data) { + rets = -ENOMEM; + goto fail; + } + DBG("allocation call back data success.\n"); + priv_cb->major_file_operations = HECI_READ; + /* make sure information is zero before we start */ + priv_cb->information = 0; + priv_cb->file_private = (void *) file_ext; + file_ext->read_cb = priv_cb; + spin_lock_bh(&dev->device_lock); + if (dev->host_buffer_is_empty) { + dev->host_buffer_is_empty = 0; + if (!heci_send_flow_control(dev, file_ext)) { + rets = -ENODEV; + goto unlock; + } else { + list_add_tail(&priv_cb->cb_list, + &dev->read_list.heci_cb.cb_list); + } + } else { + list_add_tail(&priv_cb->cb_list, + &dev->ctrl_wr_list.heci_cb.cb_list); + } + spin_unlock_bh(&dev->device_lock); + return rets; +unlock: + spin_unlock_bh(&dev->device_lock); +fail: + heci_free_cb_private(priv_cb); + return rets; +} + +/** + * pthi_write - write iamthif data to pthi client + * + * @dev: Device object for our driver + * @priv_cb: heci call back struct + * + * returns 0 on success, <0 on failure. + */ +int pthi_write(struct iamt_heci_device *dev, + struct heci_cb_private *priv_cb) +{ + int rets = 0; + struct heci_msg_hdr heci_hdr; + + if ((!dev) || (!priv_cb)) + return -ENODEV; + + DBG("write data to pthi client.\n"); + + dev->iamthif_state = HECI_IAMTHIF_WRITING; + dev->iamthif_current_cb = priv_cb; + dev->iamthif_file_object = priv_cb->file_object; + dev->iamthif_canceled = 0; + dev->iamthif_ioctl = 1; + dev->iamthif_msg_buf_size = priv_cb->request_buffer.size; + memcpy(dev->iamthif_msg_buf, priv_cb->request_buffer.data, + priv_cb->request_buffer.size); + + if (flow_ctrl_creds(dev, &dev->iamthif_file_ext) && + dev->host_buffer_is_empty) { + dev->host_buffer_is_empty = 0; + if (priv_cb->request_buffer.size > + (((dev->host_hw_state & H_CBD) >> 24) * + sizeof(__u32)) - sizeof(struct heci_msg_hdr)) { + heci_hdr.length = + (((dev->host_hw_state & H_CBD) >> 24) * + sizeof(__u32)) - sizeof(struct heci_msg_hdr); + heci_hdr.msg_complete = 0; + } else { + heci_hdr.length = priv_cb->request_buffer.size; + heci_hdr.msg_complete = 1; + } + + heci_hdr.host_addr = dev->iamthif_file_ext.host_client_id; + heci_hdr.me_addr = dev->iamthif_file_ext.me_client_id; + heci_hdr.reserved = 0; + dev->iamthif_msg_buf_index += heci_hdr.length; + if (!heci_write_message(dev, &heci_hdr, + (unsigned char *)(dev->iamthif_msg_buf), + heci_hdr.length)) + return -ENODEV; + + if (heci_hdr.msg_complete) { + flow_ctrl_reduce(dev, &dev->iamthif_file_ext); + dev->iamthif_flow_control_pending = 1; + dev->iamthif_state = HECI_IAMTHIF_FLOW_CONTROL; + DBG("add pthi cb to write waiting list\n"); + dev->iamthif_current_cb = priv_cb; + dev->iamthif_file_object = priv_cb->file_object; + list_add_tail(&priv_cb->cb_list, + &dev->write_waiting_list.heci_cb.cb_list); + } else { + DBG("message does not complete, " + "so add pthi cb to write list.\n"); + list_add_tail(&priv_cb->cb_list, + &dev->write_list.heci_cb.cb_list); + } + } else { + if (!(dev->host_buffer_is_empty)) + DBG("host buffer is not empty"); + + DBG("No flow control credentials, " + "so add iamthif cb to write list.\n"); + list_add_tail(&priv_cb->cb_list, + &dev->write_list.heci_cb.cb_list); + } + return rets; +} + +/** + * iamthif_ioctl_send_msg - send cmd data to pthi client + * + * @dev: Device object for our driver + * + * returns 0 on success, <0 on failure. + */ +void run_next_iamthif_cmd(struct iamt_heci_device *dev) +{ + struct heci_file_private *file_ext_tmp; + struct heci_cb_private *priv_cb_pos = NULL; + struct heci_cb_private *priv_cb_next = NULL; + int status = 0; + + if (!dev) + return; + + dev->iamthif_msg_buf_size = 0; + dev->iamthif_msg_buf_index = 0; + dev->iamthif_canceled = 0; + dev->iamthif_ioctl = 1; + dev->iamthif_state = HECI_IAMTHIF_IDLE; + dev->iamthif_timer = 0; + dev->iamthif_file_object = NULL; + + if (dev->pthi_cmd_list.status == 0 && + !list_empty(&dev->pthi_cmd_list.heci_cb.cb_list)) { + DBG("complete pthi cmd_list cb.\n"); + + list_for_each_entry_safe(priv_cb_pos, priv_cb_next, + &dev->pthi_cmd_list.heci_cb.cb_list, cb_list) { + list_del(&priv_cb_pos->cb_list); + file_ext_tmp = (struct heci_file_private *) + priv_cb_pos->file_private; + + if ((file_ext_tmp != NULL) && + (file_ext_tmp == &dev->iamthif_file_ext)) { + status = pthi_write(dev, priv_cb_pos); + if (status != 0) { + DBG("pthi write failed status = %d\n", + status); + return; + } + break; + } + } + } +} + +/** + * heci_free_cb_private - free heci_cb_private related memory + * + * @priv_cb: heci callback struct + */ +void heci_free_cb_private(struct heci_cb_private *priv_cb) +{ + if (priv_cb == NULL) + return; + + kfree(priv_cb->request_buffer.data); + kfree(priv_cb->response_buffer.data); + kfree(priv_cb); +} + diff --git a/drivers/staging/line6/Kconfig b/drivers/staging/line6/Kconfig new file mode 100644 index 000000000000..7852d4a960c5 --- /dev/null +++ b/drivers/staging/line6/Kconfig @@ -0,0 +1,21 @@ +config LINE6_USB + tristate "Line6 USB support" + depends on USB && SND + select SND_RAWMIDI + help + This is a driver for the guitar amp, cab, and effects modeller + PODxt Pro by Line6 (and similar devices), supporting the + following features: + * Reading/writing individual parameters + * Reading/writing complete channel, effects setup, and amp + setup data + * Channel switching + * Virtual MIDI interface + * Tuner access + * Playback/capture/mixer device for any ALSA-compatible PCM + audio application + * Signal routing (record clean/processed guitar signal, + re-amping) + + Preliminary support for the Variax Workbench is included. + diff --git a/drivers/staging/line6/Makefile b/drivers/staging/line6/Makefile new file mode 100644 index 000000000000..a1c93edc6b1d --- /dev/null +++ b/drivers/staging/line6/Makefile @@ -0,0 +1,15 @@ +obj-$(CONFIG_LINE6_USB) += line6usb.o + +line6usb-objs := \ + audio.o \ + capture.o \ + control.o \ + driver.o \ + dumprequest.o \ + midi.o \ + midibuf.o \ + pcm.o \ + playback.o \ + pod.o \ + toneport.o \ + variax.o diff --git a/drivers/staging/line6/audio.c b/drivers/staging/line6/audio.c new file mode 100644 index 000000000000..3aa946899ced --- /dev/null +++ b/drivers/staging/line6/audio.c @@ -0,0 +1,72 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" +#include "audio.h" + +#include +#include + + +static int line6_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +static char *line6_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; + + +/* + Initialize the Line6 USB audio system. +*/ +int line6_init_audio(struct usb_line6 *line6) +{ + static int dev; + struct snd_card *card; + + card = snd_card_new(line6_index[dev], line6_id[dev], THIS_MODULE, 0); + + if (card == NULL) + return -ENOMEM; + + line6->card = card; + + strcpy(card->driver, DRIVER_NAME); + strcpy(card->shortname, "Line6-USB"); + sprintf(card->longname, "Line6 %s at USB %s", line6->properties->name, + dev_name(line6->ifcdev)); /* 80 chars - see asound.h */ + return 0; +} + +/* + Register the Line6 USB audio system. +*/ +int line6_register_audio(struct usb_line6 *line6) +{ + int err; + + err = snd_card_register(line6->card); + if (err < 0) + return err; + + return 0; +} + +/* + Cleanup the Line6 USB audio system. +*/ +void line6_cleanup_audio(struct usb_line6 *line6) +{ + struct snd_card *card = line6->card; + + if (card == NULL) + return; + + snd_card_disconnect(card); + snd_card_free(card); + line6->card = NULL; +} diff --git a/drivers/staging/line6/audio.h b/drivers/staging/line6/audio.h new file mode 100644 index 000000000000..cc0245adbcd9 --- /dev/null +++ b/drivers/staging/line6/audio.h @@ -0,0 +1,24 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef AUDIO_H +#define AUDIO_H + + +#include "driver.h" + + +extern void line6_cleanup_audio(struct usb_line6 *); +extern int line6_init_audio(struct usb_line6 *); +extern int line6_register_audio(struct usb_line6 *); + + +#endif diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c new file mode 100644 index 000000000000..8393e25a10b1 --- /dev/null +++ b/drivers/staging/line6/capture.c @@ -0,0 +1,372 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" + +#include +#include +#include + +#include "audio.h" +#include "pcm.h" +#include "pod.h" +#include "capture.h" + + +/* + Find a free URB and submit it. +*/ +static int submit_audio_in_urb(struct snd_pcm_substream *substream) +{ + int index; + unsigned long flags; + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + int i, urb_size; + struct urb *urb_in; + + spin_lock_irqsave(&line6pcm->lock_audio_in, flags); + index = find_first_zero_bit(&line6pcm->active_urb_in, LINE6_ISO_BUFFERS); + + if (index < 0 || index >= LINE6_ISO_BUFFERS) { + spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags); + dev_err(s2m(substream), "no free URB found\n"); + return -EINVAL; + } + + urb_in = line6pcm->urb_audio_in[index]; + urb_size = 0; + + for (i = 0; i < LINE6_ISO_PACKETS; ++i) { + struct usb_iso_packet_descriptor *fin = &urb_in->iso_frame_desc[i]; + fin->offset = urb_size; + fin->length = line6pcm->max_packet_size; + urb_size += line6pcm->max_packet_size; + } + + urb_in->transfer_buffer = line6pcm->buffer_in + index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; + urb_in->transfer_buffer_length = urb_size; + urb_in->context = substream; + + if (usb_submit_urb(urb_in, GFP_ATOMIC) == 0) + set_bit(index, &line6pcm->active_urb_in); + else + dev_err(s2m(substream), "URB in #%d submission failed\n", index); + + spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags); + return 0; +} + +/* + Submit all currently available capture URBs. +*/ +static int submit_audio_in_all_urbs(struct snd_pcm_substream *substream) +{ + int ret, i; + + for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + ret = submit_audio_in_urb(substream); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + Unlink all currently active capture URBs. +*/ +static void unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm) +{ + unsigned int i; + + for (i = LINE6_ISO_BUFFERS; i--;) { + if (test_bit(i, &line6pcm->active_urb_in)) { + if (!test_and_set_bit(i, &line6pcm->unlink_urb_in)) { + struct urb *u = line6pcm->urb_audio_in[i]; + usb_unlink_urb(u); + } + } + } +} + +/* + Wait until unlinking of all currently active capture URBs has been + finished. +*/ +static void wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) +{ + int timeout = HZ; + unsigned int i; + int alive; + + do { + alive = 0; + for (i = LINE6_ISO_BUFFERS; i--;) { + if (test_bit(i, &line6pcm->active_urb_in)) + alive++; + } + if (!alive) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } while (--timeout > 0); + if (alive) + snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); + + line6pcm->active_urb_in = 0; + line6pcm->unlink_urb_in = 0; +} + +/* + Unlink all currently active capture URBs, and wait for finishing. +*/ +void unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) +{ + unlink_audio_in_urbs(line6pcm); + wait_clear_audio_in_urbs(line6pcm); +} + +/* + Callback for completed capture URB. +*/ +static void audio_in_callback(struct urb *urb) +{ + int i, index, length = 0, shutdown = 0; + int frames; + unsigned long flags; + + struct snd_pcm_substream *substream = (struct snd_pcm_substream *)urb->context; + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + const int bytes_per_frame = line6pcm->properties->bytes_per_frame; + struct snd_pcm_runtime *runtime = substream->runtime; + + /* find index of URB */ + for (index = 0; index < LINE6_ISO_BUFFERS; ++index) + if (urb == line6pcm->urb_audio_in[index]) + break; + +#if DO_DUMP_PCM_RECEIVE + for (i = 0; i < LINE6_ISO_PACKETS; ++i) { + struct usb_iso_packet_descriptor *fout = &urb->iso_frame_desc[i]; + line6_write_hexdump(line6pcm->line6, 'C', urb->transfer_buffer + fout->offset, fout->length); + } +#endif + + spin_lock_irqsave(&line6pcm->lock_audio_in, flags); + + for (i = 0; i < LINE6_ISO_PACKETS; ++i) { + char *fbuf; + int fsize; + struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i]; + + if (fin->status == -18) { + shutdown = 1; + break; + } + + fbuf = urb->transfer_buffer + fin->offset; + fsize = fin->actual_length; + length += fsize; + + if (fsize > 0) { + frames = fsize / bytes_per_frame; + + if (line6pcm->pos_in_done + frames > runtime->buffer_size) { + /* + The transferred area goes over buffer boundary, + copy two separate chunks. + */ + int len; + len = runtime->buffer_size - line6pcm->pos_in_done; + + if (len > 0) { + memcpy(runtime->dma_area + line6pcm->pos_in_done * bytes_per_frame, fbuf, len * bytes_per_frame); + memcpy(runtime->dma_area, fbuf + len * bytes_per_frame, (frames - len) * bytes_per_frame); + } else + dev_err(s2m(substream), "driver bug: len = %d\n", len); /* this is somewhat paranoid */ + } else { + /* copy single chunk */ + memcpy(runtime->dma_area + line6pcm->pos_in_done * bytes_per_frame, fbuf, fsize * bytes_per_frame); + } + + if ((line6pcm->pos_in_done += frames) >= runtime->buffer_size) + line6pcm->pos_in_done -= runtime->buffer_size; + } + } + + clear_bit(index, &line6pcm->active_urb_in); + + if (test_bit(index, &line6pcm->unlink_urb_in)) + shutdown = 1; + + spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags); + + if (!shutdown) { + submit_audio_in_urb(substream); + + if ((line6pcm->bytes_in += length) >= line6pcm->period_in) { + line6pcm->bytes_in -= line6pcm->period_in; + snd_pcm_period_elapsed(substream); + } + } +} + +/* open capture callback */ +static int snd_line6_capture_open(struct snd_pcm_substream *substream) +{ + int err; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + err = snd_pcm_hw_constraint_ratdens(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + (&line6pcm->properties->snd_line6_rates)); + if (err < 0) + return err; + + runtime->hw = line6pcm->properties->snd_line6_capture_hw; + return 0; +} + +/* close capture callback */ +static int snd_line6_capture_close(struct snd_pcm_substream *substream) +{ + return 0; +} + +/* hw_params capture callback */ +static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + int ret; + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + /* -- Florian Demski [FD] */ + /* don't ask me why, but this fixes the bug on my machine */ + if (line6pcm == NULL) { + if (substream->pcm == NULL) + return -ENOMEM; + if (substream->pcm->private_data == NULL) + return -ENOMEM; + substream->private_data = substream->pcm->private_data; + line6pcm = snd_pcm_substream_chip(substream); + } + /* -- [FD] end */ + + ret = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (ret < 0) + return ret; + + line6pcm->period_in = params_period_bytes(hw_params); + line6pcm->buffer_in = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * LINE6_ISO_PACKET_SIZE_MAX, GFP_KERNEL); + + if (!line6pcm->buffer_in) { + dev_err(s2m(substream), "cannot malloc buffer_in\n"); + return -ENOMEM; + } + + return 0; +} + +/* hw_free capture callback */ +static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + unlink_wait_clear_audio_in_urbs(line6pcm); + + kfree(line6pcm->buffer_in); + line6pcm->buffer_in = NULL; + + return snd_pcm_lib_free_pages(substream); +} + +/* trigger callback */ +int snd_line6_capture_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + int err; + line6pcm->count_in = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (!test_and_set_bit(BIT_RUNNING_CAPTURE, &line6pcm->flags)) { + err = submit_audio_in_all_urbs(substream); + + if (err < 0) { + clear_bit(BIT_RUNNING_CAPTURE, &line6pcm->flags); + return err; + } + } + + break; + + case SNDRV_PCM_TRIGGER_STOP: + if (test_and_clear_bit(BIT_RUNNING_CAPTURE, &line6pcm->flags)) + unlink_audio_in_urbs(line6pcm); + + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* capture pointer callback */ +static snd_pcm_uframes_t +snd_line6_capture_pointer(struct snd_pcm_substream *substream) +{ + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + return line6pcm->pos_in_done; +} + +/* capture operators */ +struct snd_pcm_ops snd_line6_capture_ops = { + .open = snd_line6_capture_open, + .close = snd_line6_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_line6_capture_hw_params, + .hw_free = snd_line6_capture_hw_free, + .prepare = snd_line6_prepare, + .trigger = snd_line6_trigger, + .pointer = snd_line6_capture_pointer, +}; + +int create_audio_in_urbs(struct snd_line6_pcm *line6pcm) +{ + int i; + + /* create audio URBs and fill in constant values: */ + for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + struct urb *urb; + + /* URB for audio in: */ + urb = line6pcm->urb_audio_in[i] = usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); + + if (urb == NULL) { + dev_err(line6pcm->line6->ifcdev, "Out of memory\n"); + return -ENOMEM; + } + + urb->dev = line6pcm->line6->usbdev; + urb->pipe = usb_rcvisocpipe(line6pcm->line6->usbdev, line6pcm->ep_audio_read & USB_ENDPOINT_NUMBER_MASK); + urb->transfer_flags = URB_ISO_ASAP; + urb->start_frame = -1; + urb->number_of_packets = LINE6_ISO_PACKETS; + urb->interval = LINE6_ISO_INTERVAL; + urb->error_count = 0; + urb->complete = audio_in_callback; + } + + return 0; +} diff --git a/drivers/staging/line6/capture.h b/drivers/staging/line6/capture.h new file mode 100644 index 000000000000..5c44464d29d4 --- /dev/null +++ b/drivers/staging/line6/capture.h @@ -0,0 +1,32 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef CAPTURE_H +#define CAPTURE_H + + +#include "driver.h" + +#include + +#include "pcm.h" + + +extern struct snd_pcm_ops snd_line6_capture_ops; + + +extern int create_audio_in_urbs(struct snd_line6_pcm *line6pcm); +extern int snd_line6_capture_trigger(struct snd_pcm_substream *substream, + int cmd); +extern void unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm); + + +#endif diff --git a/drivers/staging/line6/config.h b/drivers/staging/line6/config.h new file mode 100644 index 000000000000..adad130c5dc2 --- /dev/null +++ b/drivers/staging/line6/config.h @@ -0,0 +1,48 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef CONFIG_H +#define CONFIG_H + + +#ifdef CONFIG_USB_DEBUG +#define DEBUG 1 +#endif + + +/** + Development tools. +*/ +#define DO_DEBUG_MESSAGES 0 +#define DO_DUMP_URB_SEND DO_DEBUG_MESSAGES +#define DO_DUMP_URB_RECEIVE DO_DEBUG_MESSAGES +#define DO_DUMP_PCM_SEND 0 +#define DO_DUMP_PCM_RECEIVE 0 +#define DO_DUMP_MIDI_SEND DO_DEBUG_MESSAGES +#define DO_DUMP_MIDI_RECEIVE DO_DEBUG_MESSAGES +#define DO_DUMP_ANY (DO_DUMP_URB_SEND || DO_DUMP_URB_RECEIVE || \ + DO_DUMP_PCM_SEND || DO_DUMP_PCM_RECEIVE || \ + DO_DUMP_MIDI_SEND || DO_DUMP_MIDI_RECEIVE) +#define CREATE_RAW_FILE 0 + +#if DO_DEBUG_MESSAGES +#define CHECKPOINT printk(KERN_INFO "line6usb: %s (%s:%d)\n", \ + __func__, __FILE__, __LINE__) +#endif + +#if DO_DEBUG_MESSAGES +#define DEBUG_MESSAGES(x) (x) +#else +#define DEBUG_MESSAGES(x) +#endif + + +#endif diff --git a/drivers/staging/line6/control.c b/drivers/staging/line6/control.c new file mode 100644 index 000000000000..23ad08e17f84 --- /dev/null +++ b/drivers/staging/line6/control.c @@ -0,0 +1,840 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" + +#include + +#include "control.h" +#include "pod.h" +#include "usbdefs.h" +#include "variax.h" + +#define DEVICE_ATTR2(_name1, _name2, _mode, _show, _store) \ +struct device_attribute dev_attr_##_name1 = __ATTR(_name2, _mode, _show, _store) + +#define LINE6_PARAM_R(PREFIX, prefix, type, param) \ +static ssize_t prefix ## _get_ ## param(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + return prefix ## _get_param_ ## type(dev, buf, PREFIX ## _ ## param); \ +} + +#define LINE6_PARAM_RW(PREFIX, prefix, type, param) \ +LINE6_PARAM_R(PREFIX, prefix, type, param); \ +static ssize_t prefix ## _set_ ## param(struct device *dev, \ + struct device_attribute *attr, const char *buf, size_t count) \ +{ \ + return prefix ## _set_param_ ## type(dev, buf, count, PREFIX ## _ ## param); \ +} + +#define POD_PARAM_R(type, param) LINE6_PARAM_R(POD, pod, type, param) +#define POD_PARAM_RW(type, param) LINE6_PARAM_RW(POD, pod, type, param) +#define VARIAX_PARAM_R(type, param) LINE6_PARAM_R(VARIAX, variax, type, param) +#define VARIAX_PARAM_RW(type, param) LINE6_PARAM_RW(VARIAX, variax, type, param) + + +static ssize_t pod_get_param_int(struct device *dev, char *buf, int param) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + int retval = line6_wait_dump(&pod->dumpreq, 0); + if (retval < 0) + return retval; + return sprintf(buf, "%d\n", pod->prog_data.control[param]); +} + +static ssize_t pod_set_param_int(struct device *dev, const char *buf, size_t count, int param) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + int value = simple_strtoul(buf, NULL, 10); + pod_transmit_parameter(pod, param, value); + return count; +} + +static ssize_t variax_get_param_int(struct device *dev, char *buf, int param) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_variax *variax = usb_get_intfdata(interface); + int retval = line6_wait_dump(&variax->dumpreq, 0); + if (retval < 0) + return retval; + return sprintf(buf, "%d\n", variax->model_data.control[param]); +} + +static ssize_t variax_get_param_float(struct device *dev, char *buf, int param) +{ + /* + We do our own floating point handling here since floats in the + kernel are problematic for at least two reasons: - many distros + are still shipped with binary kernels optimized for the ancient + 80386 without FPU + - there isn't a printf("%f") + (see http://www.kernelthread.com/publications/faq/335.html) + */ + + static const int BIAS = 0x7f; + static const int OFFSET = 0xf; + static const int PRECISION = 1000; + + int len = 0; + unsigned part_int, part_frac; + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_variax *variax = usb_get_intfdata(interface); + const unsigned char *p = variax->model_data.control + param; + int retval = line6_wait_dump(&variax->dumpreq, 0); + if (retval < 0) + return retval; + + if ((p[0] == 0) && (p[1] == 0) && (p[2] == 0)) + part_int = part_frac = 0; + else { + int exponent = (((p[0] & 0x7f) << 1) | (p[1] >> 7)) - BIAS; + unsigned mantissa = (p[1] << 8) | p[2] | 0x8000; + exponent -= OFFSET; + + if (exponent >= 0) { + part_int = mantissa << exponent; + part_frac = 0; + } else { + part_int = mantissa >> -exponent; + part_frac = (mantissa << (32 + exponent)) & 0xffffffff; + } + + part_frac = (part_frac / ((1UL << 31) / (PRECISION / 2 * 10)) + 5) / 10; + } + + len += sprintf(buf + len, "%s%d.%03d\n", ((p[0] & 0x80) ? "-" : ""), part_int, part_frac); + return len; +} + +POD_PARAM_RW(int, tweak); +POD_PARAM_RW(int, wah_position); +POD_PARAM_RW(int, compression_gain); +POD_PARAM_RW(int, vol_pedal_position); +POD_PARAM_RW(int, compression_threshold); +POD_PARAM_RW(int, pan); +POD_PARAM_RW(int, amp_model_setup); +POD_PARAM_RW(int, amp_model); +POD_PARAM_RW(int, drive); +POD_PARAM_RW(int, bass); +POD_PARAM_RW(int, mid); +POD_PARAM_RW(int, lowmid); +POD_PARAM_RW(int, treble); +POD_PARAM_RW(int, highmid); +POD_PARAM_RW(int, chan_vol); +POD_PARAM_RW(int, reverb_mix); +POD_PARAM_RW(int, effect_setup); +POD_PARAM_RW(int, band_1_frequency); +POD_PARAM_RW(int, presence); +POD_PARAM_RW(int, treble__bass); +POD_PARAM_RW(int, noise_gate_enable); +POD_PARAM_RW(int, gate_threshold); +POD_PARAM_RW(int, gate_decay_time); +POD_PARAM_RW(int, stomp_enable); +POD_PARAM_RW(int, comp_enable); +POD_PARAM_RW(int, stomp_time); +POD_PARAM_RW(int, delay_enable); +POD_PARAM_RW(int, mod_param_1); +POD_PARAM_RW(int, delay_param_1); +POD_PARAM_RW(int, delay_param_1_note_value); +POD_PARAM_RW(int, band_2_frequency__bass); +POD_PARAM_RW(int, delay_param_2); +POD_PARAM_RW(int, delay_volume_mix); +POD_PARAM_RW(int, delay_param_3); +POD_PARAM_RW(int, reverb_enable); +POD_PARAM_RW(int, reverb_type); +POD_PARAM_RW(int, reverb_decay); +POD_PARAM_RW(int, reverb_tone); +POD_PARAM_RW(int, reverb_pre_delay); +POD_PARAM_RW(int, reverb_pre_post); +POD_PARAM_RW(int, band_2_frequency); +POD_PARAM_RW(int, band_3_frequency__bass); +POD_PARAM_RW(int, wah_enable); +POD_PARAM_RW(int, modulation_lo_cut); +POD_PARAM_RW(int, delay_reverb_lo_cut); +POD_PARAM_RW(int, volume_pedal_minimum); +POD_PARAM_RW(int, eq_pre_post); +POD_PARAM_RW(int, volume_pre_post); +POD_PARAM_RW(int, di_model); +POD_PARAM_RW(int, di_delay); +POD_PARAM_RW(int, mod_enable); +POD_PARAM_RW(int, mod_param_1_note_value); +POD_PARAM_RW(int, mod_param_2); +POD_PARAM_RW(int, mod_param_3); +POD_PARAM_RW(int, mod_param_4); +POD_PARAM_RW(int, mod_param_5); +POD_PARAM_RW(int, mod_volume_mix); +POD_PARAM_RW(int, mod_pre_post); +POD_PARAM_RW(int, modulation_model); +POD_PARAM_RW(int, band_3_frequency); +POD_PARAM_RW(int, band_4_frequency__bass); +POD_PARAM_RW(int, mod_param_1_double_precision); +POD_PARAM_RW(int, delay_param_1_double_precision); +POD_PARAM_RW(int, eq_enable); +POD_PARAM_RW(int, tap); +POD_PARAM_RW(int, volume_tweak_pedal_assign); +POD_PARAM_RW(int, band_5_frequency); +POD_PARAM_RW(int, tuner); +POD_PARAM_RW(int, mic_selection); +POD_PARAM_RW(int, cabinet_model); +POD_PARAM_RW(int, stomp_model); +POD_PARAM_RW(int, roomlevel); +POD_PARAM_RW(int, band_4_frequency); +POD_PARAM_RW(int, band_6_frequency); +POD_PARAM_RW(int, stomp_param_1_note_value); +POD_PARAM_RW(int, stomp_param_2); +POD_PARAM_RW(int, stomp_param_3); +POD_PARAM_RW(int, stomp_param_4); +POD_PARAM_RW(int, stomp_param_5); +POD_PARAM_RW(int, stomp_param_6); +POD_PARAM_RW(int, amp_switch_select); +POD_PARAM_RW(int, delay_param_4); +POD_PARAM_RW(int, delay_param_5); +POD_PARAM_RW(int, delay_pre_post); +POD_PARAM_RW(int, delay_model); +POD_PARAM_RW(int, delay_verb_model); +POD_PARAM_RW(int, tempo_msb); +POD_PARAM_RW(int, tempo_lsb); +POD_PARAM_RW(int, wah_model); +POD_PARAM_RW(int, bypass_volume); +POD_PARAM_RW(int, fx_loop_on_off); +POD_PARAM_RW(int, tweak_param_select); +POD_PARAM_RW(int, amp1_engage); +POD_PARAM_RW(int, band_1_gain); +POD_PARAM_RW(int, band_2_gain__bass); +POD_PARAM_RW(int, band_2_gain); +POD_PARAM_RW(int, band_3_gain__bass); +POD_PARAM_RW(int, band_3_gain); +POD_PARAM_RW(int, band_4_gain__bass); +POD_PARAM_RW(int, band_5_gain__bass); +POD_PARAM_RW(int, band_4_gain); +POD_PARAM_RW(int, band_6_gain__bass); +VARIAX_PARAM_R(int, body); +VARIAX_PARAM_R(int, pickup1_enable); +VARIAX_PARAM_R(int, pickup1_type); +VARIAX_PARAM_R(float, pickup1_position); +VARIAX_PARAM_R(float, pickup1_angle); +VARIAX_PARAM_R(float, pickup1_level); +VARIAX_PARAM_R(int, pickup2_enable); +VARIAX_PARAM_R(int, pickup2_type); +VARIAX_PARAM_R(float, pickup2_position); +VARIAX_PARAM_R(float, pickup2_angle); +VARIAX_PARAM_R(float, pickup2_level); +VARIAX_PARAM_R(int, pickup_phase); +VARIAX_PARAM_R(float, capacitance); +VARIAX_PARAM_R(float, tone_resistance); +VARIAX_PARAM_R(float, volume_resistance); +VARIAX_PARAM_R(int, taper); +VARIAX_PARAM_R(float, tone_dump); +VARIAX_PARAM_R(int, save_tone); +VARIAX_PARAM_R(float, volume_dump); +VARIAX_PARAM_R(int, tuning_enable); +VARIAX_PARAM_R(int, tuning6); +VARIAX_PARAM_R(int, tuning5); +VARIAX_PARAM_R(int, tuning4); +VARIAX_PARAM_R(int, tuning3); +VARIAX_PARAM_R(int, tuning2); +VARIAX_PARAM_R(int, tuning1); +VARIAX_PARAM_R(float, detune6); +VARIAX_PARAM_R(float, detune5); +VARIAX_PARAM_R(float, detune4); +VARIAX_PARAM_R(float, detune3); +VARIAX_PARAM_R(float, detune2); +VARIAX_PARAM_R(float, detune1); +VARIAX_PARAM_R(float, mix6); +VARIAX_PARAM_R(float, mix5); +VARIAX_PARAM_R(float, mix4); +VARIAX_PARAM_R(float, mix3); +VARIAX_PARAM_R(float, mix2); +VARIAX_PARAM_R(float, mix1); +VARIAX_PARAM_R(int, pickup_wiring); + +static DEVICE_ATTR(tweak, S_IWUGO | S_IRUGO, pod_get_tweak, pod_set_tweak); +static DEVICE_ATTR(wah_position, S_IWUGO | S_IRUGO, pod_get_wah_position, pod_set_wah_position); +static DEVICE_ATTR(compression_gain, S_IWUGO | S_IRUGO, pod_get_compression_gain, pod_set_compression_gain); +static DEVICE_ATTR(vol_pedal_position, S_IWUGO | S_IRUGO, pod_get_vol_pedal_position, pod_set_vol_pedal_position); +static DEVICE_ATTR(compression_threshold, S_IWUGO | S_IRUGO, pod_get_compression_threshold, pod_set_compression_threshold); +static DEVICE_ATTR(pan, S_IWUGO | S_IRUGO, pod_get_pan, pod_set_pan); +static DEVICE_ATTR(amp_model_setup, S_IWUGO | S_IRUGO, pod_get_amp_model_setup, pod_set_amp_model_setup); +static DEVICE_ATTR(amp_model, S_IWUGO | S_IRUGO, pod_get_amp_model, pod_set_amp_model); +static DEVICE_ATTR(drive, S_IWUGO | S_IRUGO, pod_get_drive, pod_set_drive); +static DEVICE_ATTR(bass, S_IWUGO | S_IRUGO, pod_get_bass, pod_set_bass); +static DEVICE_ATTR(mid, S_IWUGO | S_IRUGO, pod_get_mid, pod_set_mid); +static DEVICE_ATTR(lowmid, S_IWUGO | S_IRUGO, pod_get_lowmid, pod_set_lowmid); +static DEVICE_ATTR(treble, S_IWUGO | S_IRUGO, pod_get_treble, pod_set_treble); +static DEVICE_ATTR(highmid, S_IWUGO | S_IRUGO, pod_get_highmid, pod_set_highmid); +static DEVICE_ATTR(chan_vol, S_IWUGO | S_IRUGO, pod_get_chan_vol, pod_set_chan_vol); +static DEVICE_ATTR(reverb_mix, S_IWUGO | S_IRUGO, pod_get_reverb_mix, pod_set_reverb_mix); +static DEVICE_ATTR(effect_setup, S_IWUGO | S_IRUGO, pod_get_effect_setup, pod_set_effect_setup); +static DEVICE_ATTR(band_1_frequency, S_IWUGO | S_IRUGO, pod_get_band_1_frequency, pod_set_band_1_frequency); +static DEVICE_ATTR(presence, S_IWUGO | S_IRUGO, pod_get_presence, pod_set_presence); +static DEVICE_ATTR2(treble__bass, treble, S_IWUGO | S_IRUGO, pod_get_treble__bass, pod_set_treble__bass); +static DEVICE_ATTR(noise_gate_enable, S_IWUGO | S_IRUGO, pod_get_noise_gate_enable, pod_set_noise_gate_enable); +static DEVICE_ATTR(gate_threshold, S_IWUGO | S_IRUGO, pod_get_gate_threshold, pod_set_gate_threshold); +static DEVICE_ATTR(gate_decay_time, S_IWUGO | S_IRUGO, pod_get_gate_decay_time, pod_set_gate_decay_time); +static DEVICE_ATTR(stomp_enable, S_IWUGO | S_IRUGO, pod_get_stomp_enable, pod_set_stomp_enable); +static DEVICE_ATTR(comp_enable, S_IWUGO | S_IRUGO, pod_get_comp_enable, pod_set_comp_enable); +static DEVICE_ATTR(stomp_time, S_IWUGO | S_IRUGO, pod_get_stomp_time, pod_set_stomp_time); +static DEVICE_ATTR(delay_enable, S_IWUGO | S_IRUGO, pod_get_delay_enable, pod_set_delay_enable); +static DEVICE_ATTR(mod_param_1, S_IWUGO | S_IRUGO, pod_get_mod_param_1, pod_set_mod_param_1); +static DEVICE_ATTR(delay_param_1, S_IWUGO | S_IRUGO, pod_get_delay_param_1, pod_set_delay_param_1); +static DEVICE_ATTR(delay_param_1_note_value, S_IWUGO | S_IRUGO, pod_get_delay_param_1_note_value, pod_set_delay_param_1_note_value); +static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUGO | S_IRUGO, pod_get_band_2_frequency__bass, pod_set_band_2_frequency__bass); +static DEVICE_ATTR(delay_param_2, S_IWUGO | S_IRUGO, pod_get_delay_param_2, pod_set_delay_param_2); +static DEVICE_ATTR(delay_volume_mix, S_IWUGO | S_IRUGO, pod_get_delay_volume_mix, pod_set_delay_volume_mix); +static DEVICE_ATTR(delay_param_3, S_IWUGO | S_IRUGO, pod_get_delay_param_3, pod_set_delay_param_3); +static DEVICE_ATTR(reverb_enable, S_IWUGO | S_IRUGO, pod_get_reverb_enable, pod_set_reverb_enable); +static DEVICE_ATTR(reverb_type, S_IWUGO | S_IRUGO, pod_get_reverb_type, pod_set_reverb_type); +static DEVICE_ATTR(reverb_decay, S_IWUGO | S_IRUGO, pod_get_reverb_decay, pod_set_reverb_decay); +static DEVICE_ATTR(reverb_tone, S_IWUGO | S_IRUGO, pod_get_reverb_tone, pod_set_reverb_tone); +static DEVICE_ATTR(reverb_pre_delay, S_IWUGO | S_IRUGO, pod_get_reverb_pre_delay, pod_set_reverb_pre_delay); +static DEVICE_ATTR(reverb_pre_post, S_IWUGO | S_IRUGO, pod_get_reverb_pre_post, pod_set_reverb_pre_post); +static DEVICE_ATTR(band_2_frequency, S_IWUGO | S_IRUGO, pod_get_band_2_frequency, pod_set_band_2_frequency); +static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUGO | S_IRUGO, pod_get_band_3_frequency__bass, pod_set_band_3_frequency__bass); +static DEVICE_ATTR(wah_enable, S_IWUGO | S_IRUGO, pod_get_wah_enable, pod_set_wah_enable); +static DEVICE_ATTR(modulation_lo_cut, S_IWUGO | S_IRUGO, pod_get_modulation_lo_cut, pod_set_modulation_lo_cut); +static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUGO | S_IRUGO, pod_get_delay_reverb_lo_cut, pod_set_delay_reverb_lo_cut); +static DEVICE_ATTR(volume_pedal_minimum, S_IWUGO | S_IRUGO, pod_get_volume_pedal_minimum, pod_set_volume_pedal_minimum); +static DEVICE_ATTR(eq_pre_post, S_IWUGO | S_IRUGO, pod_get_eq_pre_post, pod_set_eq_pre_post); +static DEVICE_ATTR(volume_pre_post, S_IWUGO | S_IRUGO, pod_get_volume_pre_post, pod_set_volume_pre_post); +static DEVICE_ATTR(di_model, S_IWUGO | S_IRUGO, pod_get_di_model, pod_set_di_model); +static DEVICE_ATTR(di_delay, S_IWUGO | S_IRUGO, pod_get_di_delay, pod_set_di_delay); +static DEVICE_ATTR(mod_enable, S_IWUGO | S_IRUGO, pod_get_mod_enable, pod_set_mod_enable); +static DEVICE_ATTR(mod_param_1_note_value, S_IWUGO | S_IRUGO, pod_get_mod_param_1_note_value, pod_set_mod_param_1_note_value); +static DEVICE_ATTR(mod_param_2, S_IWUGO | S_IRUGO, pod_get_mod_param_2, pod_set_mod_param_2); +static DEVICE_ATTR(mod_param_3, S_IWUGO | S_IRUGO, pod_get_mod_param_3, pod_set_mod_param_3); +static DEVICE_ATTR(mod_param_4, S_IWUGO | S_IRUGO, pod_get_mod_param_4, pod_set_mod_param_4); +static DEVICE_ATTR(mod_param_5, S_IWUGO | S_IRUGO, pod_get_mod_param_5, pod_set_mod_param_5); +static DEVICE_ATTR(mod_volume_mix, S_IWUGO | S_IRUGO, pod_get_mod_volume_mix, pod_set_mod_volume_mix); +static DEVICE_ATTR(mod_pre_post, S_IWUGO | S_IRUGO, pod_get_mod_pre_post, pod_set_mod_pre_post); +static DEVICE_ATTR(modulation_model, S_IWUGO | S_IRUGO, pod_get_modulation_model, pod_set_modulation_model); +static DEVICE_ATTR(band_3_frequency, S_IWUGO | S_IRUGO, pod_get_band_3_frequency, pod_set_band_3_frequency); +static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUGO | S_IRUGO, pod_get_band_4_frequency__bass, pod_set_band_4_frequency__bass); +static DEVICE_ATTR(mod_param_1_double_precision, S_IWUGO | S_IRUGO, pod_get_mod_param_1_double_precision, pod_set_mod_param_1_double_precision); +static DEVICE_ATTR(delay_param_1_double_precision, S_IWUGO | S_IRUGO, pod_get_delay_param_1_double_precision, pod_set_delay_param_1_double_precision); +static DEVICE_ATTR(eq_enable, S_IWUGO | S_IRUGO, pod_get_eq_enable, pod_set_eq_enable); +static DEVICE_ATTR(tap, S_IWUGO | S_IRUGO, pod_get_tap, pod_set_tap); +static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUGO | S_IRUGO, pod_get_volume_tweak_pedal_assign, pod_set_volume_tweak_pedal_assign); +static DEVICE_ATTR(band_5_frequency, S_IWUGO | S_IRUGO, pod_get_band_5_frequency, pod_set_band_5_frequency); +static DEVICE_ATTR(tuner, S_IWUGO | S_IRUGO, pod_get_tuner, pod_set_tuner); +static DEVICE_ATTR(mic_selection, S_IWUGO | S_IRUGO, pod_get_mic_selection, pod_set_mic_selection); +static DEVICE_ATTR(cabinet_model, S_IWUGO | S_IRUGO, pod_get_cabinet_model, pod_set_cabinet_model); +static DEVICE_ATTR(stomp_model, S_IWUGO | S_IRUGO, pod_get_stomp_model, pod_set_stomp_model); +static DEVICE_ATTR(roomlevel, S_IWUGO | S_IRUGO, pod_get_roomlevel, pod_set_roomlevel); +static DEVICE_ATTR(band_4_frequency, S_IWUGO | S_IRUGO, pod_get_band_4_frequency, pod_set_band_4_frequency); +static DEVICE_ATTR(band_6_frequency, S_IWUGO | S_IRUGO, pod_get_band_6_frequency, pod_set_band_6_frequency); +static DEVICE_ATTR(stomp_param_1_note_value, S_IWUGO | S_IRUGO, pod_get_stomp_param_1_note_value, pod_set_stomp_param_1_note_value); +static DEVICE_ATTR(stomp_param_2, S_IWUGO | S_IRUGO, pod_get_stomp_param_2, pod_set_stomp_param_2); +static DEVICE_ATTR(stomp_param_3, S_IWUGO | S_IRUGO, pod_get_stomp_param_3, pod_set_stomp_param_3); +static DEVICE_ATTR(stomp_param_4, S_IWUGO | S_IRUGO, pod_get_stomp_param_4, pod_set_stomp_param_4); +static DEVICE_ATTR(stomp_param_5, S_IWUGO | S_IRUGO, pod_get_stomp_param_5, pod_set_stomp_param_5); +static DEVICE_ATTR(stomp_param_6, S_IWUGO | S_IRUGO, pod_get_stomp_param_6, pod_set_stomp_param_6); +static DEVICE_ATTR(amp_switch_select, S_IWUGO | S_IRUGO, pod_get_amp_switch_select, pod_set_amp_switch_select); +static DEVICE_ATTR(delay_param_4, S_IWUGO | S_IRUGO, pod_get_delay_param_4, pod_set_delay_param_4); +static DEVICE_ATTR(delay_param_5, S_IWUGO | S_IRUGO, pod_get_delay_param_5, pod_set_delay_param_5); +static DEVICE_ATTR(delay_pre_post, S_IWUGO | S_IRUGO, pod_get_delay_pre_post, pod_set_delay_pre_post); +static DEVICE_ATTR(delay_model, S_IWUGO | S_IRUGO, pod_get_delay_model, pod_set_delay_model); +static DEVICE_ATTR(delay_verb_model, S_IWUGO | S_IRUGO, pod_get_delay_verb_model, pod_set_delay_verb_model); +static DEVICE_ATTR(tempo_msb, S_IWUGO | S_IRUGO, pod_get_tempo_msb, pod_set_tempo_msb); +static DEVICE_ATTR(tempo_lsb, S_IWUGO | S_IRUGO, pod_get_tempo_lsb, pod_set_tempo_lsb); +static DEVICE_ATTR(wah_model, S_IWUGO | S_IRUGO, pod_get_wah_model, pod_set_wah_model); +static DEVICE_ATTR(bypass_volume, S_IWUGO | S_IRUGO, pod_get_bypass_volume, pod_set_bypass_volume); +static DEVICE_ATTR(fx_loop_on_off, S_IWUGO | S_IRUGO, pod_get_fx_loop_on_off, pod_set_fx_loop_on_off); +static DEVICE_ATTR(tweak_param_select, S_IWUGO | S_IRUGO, pod_get_tweak_param_select, pod_set_tweak_param_select); +static DEVICE_ATTR(amp1_engage, S_IWUGO | S_IRUGO, pod_get_amp1_engage, pod_set_amp1_engage); +static DEVICE_ATTR(band_1_gain, S_IWUGO | S_IRUGO, pod_get_band_1_gain, pod_set_band_1_gain); +static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUGO | S_IRUGO, pod_get_band_2_gain__bass, pod_set_band_2_gain__bass); +static DEVICE_ATTR(band_2_gain, S_IWUGO | S_IRUGO, pod_get_band_2_gain, pod_set_band_2_gain); +static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUGO | S_IRUGO, pod_get_band_3_gain__bass, pod_set_band_3_gain__bass); +static DEVICE_ATTR(band_3_gain, S_IWUGO | S_IRUGO, pod_get_band_3_gain, pod_set_band_3_gain); +static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUGO | S_IRUGO, pod_get_band_4_gain__bass, pod_set_band_4_gain__bass); +static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUGO | S_IRUGO, pod_get_band_5_gain__bass, pod_set_band_5_gain__bass); +static DEVICE_ATTR(band_4_gain, S_IWUGO | S_IRUGO, pod_get_band_4_gain, pod_set_band_4_gain); +static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUGO | S_IRUGO, pod_get_band_6_gain__bass, pod_set_band_6_gain__bass); +static DEVICE_ATTR(body, S_IRUGO, variax_get_body, line6_nop_write); +static DEVICE_ATTR(pickup1_enable, S_IRUGO, variax_get_pickup1_enable, line6_nop_write); +static DEVICE_ATTR(pickup1_type, S_IRUGO, variax_get_pickup1_type, line6_nop_write); +static DEVICE_ATTR(pickup1_position, S_IRUGO, variax_get_pickup1_position, line6_nop_write); +static DEVICE_ATTR(pickup1_angle, S_IRUGO, variax_get_pickup1_angle, line6_nop_write); +static DEVICE_ATTR(pickup1_level, S_IRUGO, variax_get_pickup1_level, line6_nop_write); +static DEVICE_ATTR(pickup2_enable, S_IRUGO, variax_get_pickup2_enable, line6_nop_write); +static DEVICE_ATTR(pickup2_type, S_IRUGO, variax_get_pickup2_type, line6_nop_write); +static DEVICE_ATTR(pickup2_position, S_IRUGO, variax_get_pickup2_position, line6_nop_write); +static DEVICE_ATTR(pickup2_angle, S_IRUGO, variax_get_pickup2_angle, line6_nop_write); +static DEVICE_ATTR(pickup2_level, S_IRUGO, variax_get_pickup2_level, line6_nop_write); +static DEVICE_ATTR(pickup_phase, S_IRUGO, variax_get_pickup_phase, line6_nop_write); +static DEVICE_ATTR(capacitance, S_IRUGO, variax_get_capacitance, line6_nop_write); +static DEVICE_ATTR(tone_resistance, S_IRUGO, variax_get_tone_resistance, line6_nop_write); +static DEVICE_ATTR(volume_resistance, S_IRUGO, variax_get_volume_resistance, line6_nop_write); +static DEVICE_ATTR(taper, S_IRUGO, variax_get_taper, line6_nop_write); +static DEVICE_ATTR(tone_dump, S_IRUGO, variax_get_tone_dump, line6_nop_write); +static DEVICE_ATTR(save_tone, S_IRUGO, variax_get_save_tone, line6_nop_write); +static DEVICE_ATTR(volume_dump, S_IRUGO, variax_get_volume_dump, line6_nop_write); +static DEVICE_ATTR(tuning_enable, S_IRUGO, variax_get_tuning_enable, line6_nop_write); +static DEVICE_ATTR(tuning6, S_IRUGO, variax_get_tuning6, line6_nop_write); +static DEVICE_ATTR(tuning5, S_IRUGO, variax_get_tuning5, line6_nop_write); +static DEVICE_ATTR(tuning4, S_IRUGO, variax_get_tuning4, line6_nop_write); +static DEVICE_ATTR(tuning3, S_IRUGO, variax_get_tuning3, line6_nop_write); +static DEVICE_ATTR(tuning2, S_IRUGO, variax_get_tuning2, line6_nop_write); +static DEVICE_ATTR(tuning1, S_IRUGO, variax_get_tuning1, line6_nop_write); +static DEVICE_ATTR(detune6, S_IRUGO, variax_get_detune6, line6_nop_write); +static DEVICE_ATTR(detune5, S_IRUGO, variax_get_detune5, line6_nop_write); +static DEVICE_ATTR(detune4, S_IRUGO, variax_get_detune4, line6_nop_write); +static DEVICE_ATTR(detune3, S_IRUGO, variax_get_detune3, line6_nop_write); +static DEVICE_ATTR(detune2, S_IRUGO, variax_get_detune2, line6_nop_write); +static DEVICE_ATTR(detune1, S_IRUGO, variax_get_detune1, line6_nop_write); +static DEVICE_ATTR(mix6, S_IRUGO, variax_get_mix6, line6_nop_write); +static DEVICE_ATTR(mix5, S_IRUGO, variax_get_mix5, line6_nop_write); +static DEVICE_ATTR(mix4, S_IRUGO, variax_get_mix4, line6_nop_write); +static DEVICE_ATTR(mix3, S_IRUGO, variax_get_mix3, line6_nop_write); +static DEVICE_ATTR(mix2, S_IRUGO, variax_get_mix2, line6_nop_write); +static DEVICE_ATTR(mix1, S_IRUGO, variax_get_mix1, line6_nop_write); +static DEVICE_ATTR(pickup_wiring, S_IRUGO, variax_get_pickup_wiring, line6_nop_write); + +int pod_create_files(int firmware, int type, struct device *dev) +{ + int err; + CHECK_RETURN(device_create_file(dev, &dev_attr_tweak)); + CHECK_RETURN(device_create_file(dev, &dev_attr_wah_position)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_compression_gain)); + CHECK_RETURN(device_create_file(dev, &dev_attr_vol_pedal_position)); + CHECK_RETURN(device_create_file(dev, &dev_attr_compression_threshold)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pan)); + CHECK_RETURN(device_create_file(dev, &dev_attr_amp_model_setup)); + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_amp_model)); + CHECK_RETURN(device_create_file(dev, &dev_attr_drive)); + CHECK_RETURN(device_create_file(dev, &dev_attr_bass)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_mid)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_lowmid)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_treble)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_highmid)); + CHECK_RETURN(device_create_file(dev, &dev_attr_chan_vol)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_mix)); + CHECK_RETURN(device_create_file(dev, &dev_attr_effect_setup)); + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_1_frequency)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_presence)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_treble__bass)); + CHECK_RETURN(device_create_file(dev, &dev_attr_noise_gate_enable)); + CHECK_RETURN(device_create_file(dev, &dev_attr_gate_threshold)); + CHECK_RETURN(device_create_file(dev, &dev_attr_gate_decay_time)); + CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_enable)); + CHECK_RETURN(device_create_file(dev, &dev_attr_comp_enable)); + CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_time)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_enable)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_1)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_1)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_1_note_value)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_2_frequency__bass)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_2)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_volume_mix)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_3)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_enable)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_type)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_decay)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_tone)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_pre_delay)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_reverb_pre_post)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_2_frequency)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_3_frequency__bass)); + CHECK_RETURN(device_create_file(dev, &dev_attr_wah_enable)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_modulation_lo_cut)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_reverb_lo_cut)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_volume_pedal_minimum)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_eq_pre_post)); + CHECK_RETURN(device_create_file(dev, &dev_attr_volume_pre_post)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_di_model)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_di_delay)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_enable)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_1_note_value)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_2)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_3)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_4)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_5)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_volume_mix)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_pre_post)); + CHECK_RETURN(device_create_file(dev, &dev_attr_modulation_model)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_3_frequency)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_4_frequency__bass)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mod_param_1_double_precision)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_1_double_precision)); + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_eq_enable)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tap)); + CHECK_RETURN(device_create_file(dev, &dev_attr_volume_tweak_pedal_assign)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_5_frequency)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuner)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mic_selection)); + CHECK_RETURN(device_create_file(dev, &dev_attr_cabinet_model)); + CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_model)); + CHECK_RETURN(device_create_file(dev, &dev_attr_roomlevel)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_4_frequency)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_6_frequency)); + CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_1_note_value)); + CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_2)); + CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_3)); + CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_4)); + CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_5)); + CHECK_RETURN(device_create_file(dev, &dev_attr_stomp_param_6)); + if ((type & (LINE6_BITS_LIVE)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_amp_switch_select)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_4)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_param_5)); + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_pre_post)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_model)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_delay_verb_model)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tempo_msb)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tempo_lsb)); + if (firmware >= 300) + CHECK_RETURN(device_create_file(dev, &dev_attr_wah_model)); + if (firmware >= 214) + CHECK_RETURN(device_create_file(dev, &dev_attr_bypass_volume)); + if ((type & (LINE6_BITS_PRO)) != 0) + CHECK_RETURN(device_create_file(dev, &dev_attr_fx_loop_on_off)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tweak_param_select)); + CHECK_RETURN(device_create_file(dev, &dev_attr_amp1_engage)); + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_1_gain)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_2_gain__bass)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_2_gain)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_3_gain__bass)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_3_gain)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_4_gain__bass)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_5_gain__bass)); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_4_gain)); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + CHECK_RETURN(device_create_file(dev, &dev_attr_band_6_gain__bass)); + return 0; +} + +void pod_remove_files(int firmware, int type, struct device *dev) +{ + device_remove_file(dev, &dev_attr_tweak); + device_remove_file(dev, &dev_attr_wah_position); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_compression_gain); + device_remove_file(dev, &dev_attr_vol_pedal_position); + device_remove_file(dev, &dev_attr_compression_threshold); + device_remove_file(dev, &dev_attr_pan); + device_remove_file(dev, &dev_attr_amp_model_setup); + if (firmware >= 200) + device_remove_file(dev, &dev_attr_amp_model); + device_remove_file(dev, &dev_attr_drive); + device_remove_file(dev, &dev_attr_bass); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_mid); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + device_remove_file(dev, &dev_attr_lowmid); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_treble); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + device_remove_file(dev, &dev_attr_highmid); + device_remove_file(dev, &dev_attr_chan_vol); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_reverb_mix); + device_remove_file(dev, &dev_attr_effect_setup); + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_1_frequency); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_presence); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + device_remove_file(dev, &dev_attr_treble__bass); + device_remove_file(dev, &dev_attr_noise_gate_enable); + device_remove_file(dev, &dev_attr_gate_threshold); + device_remove_file(dev, &dev_attr_gate_decay_time); + device_remove_file(dev, &dev_attr_stomp_enable); + device_remove_file(dev, &dev_attr_comp_enable); + device_remove_file(dev, &dev_attr_stomp_time); + device_remove_file(dev, &dev_attr_delay_enable); + device_remove_file(dev, &dev_attr_mod_param_1); + device_remove_file(dev, &dev_attr_delay_param_1); + device_remove_file(dev, &dev_attr_delay_param_1_note_value); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_2_frequency__bass); + device_remove_file(dev, &dev_attr_delay_param_2); + device_remove_file(dev, &dev_attr_delay_volume_mix); + device_remove_file(dev, &dev_attr_delay_param_3); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_reverb_enable); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_reverb_type); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_reverb_decay); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_reverb_tone); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_reverb_pre_delay); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_reverb_pre_post); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_2_frequency); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_3_frequency__bass); + device_remove_file(dev, &dev_attr_wah_enable); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + device_remove_file(dev, &dev_attr_modulation_lo_cut); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + device_remove_file(dev, &dev_attr_delay_reverb_lo_cut); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_volume_pedal_minimum); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_eq_pre_post); + device_remove_file(dev, &dev_attr_volume_pre_post); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + device_remove_file(dev, &dev_attr_di_model); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + device_remove_file(dev, &dev_attr_di_delay); + device_remove_file(dev, &dev_attr_mod_enable); + device_remove_file(dev, &dev_attr_mod_param_1_note_value); + device_remove_file(dev, &dev_attr_mod_param_2); + device_remove_file(dev, &dev_attr_mod_param_3); + device_remove_file(dev, &dev_attr_mod_param_4); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + device_remove_file(dev, &dev_attr_mod_param_5); + device_remove_file(dev, &dev_attr_mod_volume_mix); + device_remove_file(dev, &dev_attr_mod_pre_post); + device_remove_file(dev, &dev_attr_modulation_model); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_3_frequency); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_4_frequency__bass); + device_remove_file(dev, &dev_attr_mod_param_1_double_precision); + device_remove_file(dev, &dev_attr_delay_param_1_double_precision); + if (firmware >= 200) + device_remove_file(dev, &dev_attr_eq_enable); + device_remove_file(dev, &dev_attr_tap); + device_remove_file(dev, &dev_attr_volume_tweak_pedal_assign); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_5_frequency); + device_remove_file(dev, &dev_attr_tuner); + device_remove_file(dev, &dev_attr_mic_selection); + device_remove_file(dev, &dev_attr_cabinet_model); + device_remove_file(dev, &dev_attr_stomp_model); + device_remove_file(dev, &dev_attr_roomlevel); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_4_frequency); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_6_frequency); + device_remove_file(dev, &dev_attr_stomp_param_1_note_value); + device_remove_file(dev, &dev_attr_stomp_param_2); + device_remove_file(dev, &dev_attr_stomp_param_3); + device_remove_file(dev, &dev_attr_stomp_param_4); + device_remove_file(dev, &dev_attr_stomp_param_5); + device_remove_file(dev, &dev_attr_stomp_param_6); + if ((type & (LINE6_BITS_LIVE)) != 0) + device_remove_file(dev, &dev_attr_amp_switch_select); + device_remove_file(dev, &dev_attr_delay_param_4); + device_remove_file(dev, &dev_attr_delay_param_5); + device_remove_file(dev, &dev_attr_delay_pre_post); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + device_remove_file(dev, &dev_attr_delay_model); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + device_remove_file(dev, &dev_attr_delay_verb_model); + device_remove_file(dev, &dev_attr_tempo_msb); + device_remove_file(dev, &dev_attr_tempo_lsb); + if (firmware >= 300) + device_remove_file(dev, &dev_attr_wah_model); + if (firmware >= 214) + device_remove_file(dev, &dev_attr_bypass_volume); + if ((type & (LINE6_BITS_PRO)) != 0) + device_remove_file(dev, &dev_attr_fx_loop_on_off); + device_remove_file(dev, &dev_attr_tweak_param_select); + device_remove_file(dev, &dev_attr_amp1_engage); + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_1_gain); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_2_gain__bass); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_2_gain); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_3_gain__bass); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_3_gain); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_4_gain__bass); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_5_gain__bass); + if ((type & (LINE6_BITS_PODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_4_gain); + if ((type & (LINE6_BITS_BASSPODXTALL)) != 0) + if (firmware >= 200) + device_remove_file(dev, &dev_attr_band_6_gain__bass); +} + +EXPORT_SYMBOL(pod_create_files); +EXPORT_SYMBOL(pod_remove_files); + +int variax_create_files(int firmware, int type, struct device *dev) +{ + int err; + CHECK_RETURN(device_create_file(dev, &dev_attr_body)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_enable)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_type)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_position)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_angle)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup1_level)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_enable)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_type)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_position)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_angle)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup2_level)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup_phase)); + CHECK_RETURN(device_create_file(dev, &dev_attr_capacitance)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tone_resistance)); + CHECK_RETURN(device_create_file(dev, &dev_attr_volume_resistance)); + CHECK_RETURN(device_create_file(dev, &dev_attr_taper)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tone_dump)); + CHECK_RETURN(device_create_file(dev, &dev_attr_save_tone)); + CHECK_RETURN(device_create_file(dev, &dev_attr_volume_dump)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuning_enable)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuning6)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuning5)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuning4)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuning3)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuning2)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuning1)); + CHECK_RETURN(device_create_file(dev, &dev_attr_detune6)); + CHECK_RETURN(device_create_file(dev, &dev_attr_detune5)); + CHECK_RETURN(device_create_file(dev, &dev_attr_detune4)); + CHECK_RETURN(device_create_file(dev, &dev_attr_detune3)); + CHECK_RETURN(device_create_file(dev, &dev_attr_detune2)); + CHECK_RETURN(device_create_file(dev, &dev_attr_detune1)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mix6)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mix5)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mix4)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mix3)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mix2)); + CHECK_RETURN(device_create_file(dev, &dev_attr_mix1)); + CHECK_RETURN(device_create_file(dev, &dev_attr_pickup_wiring)); + return 0; +} + +void variax_remove_files(int firmware, int type, struct device *dev) +{ + device_remove_file(dev, &dev_attr_body); + device_remove_file(dev, &dev_attr_pickup1_enable); + device_remove_file(dev, &dev_attr_pickup1_type); + device_remove_file(dev, &dev_attr_pickup1_position); + device_remove_file(dev, &dev_attr_pickup1_angle); + device_remove_file(dev, &dev_attr_pickup1_level); + device_remove_file(dev, &dev_attr_pickup2_enable); + device_remove_file(dev, &dev_attr_pickup2_type); + device_remove_file(dev, &dev_attr_pickup2_position); + device_remove_file(dev, &dev_attr_pickup2_angle); + device_remove_file(dev, &dev_attr_pickup2_level); + device_remove_file(dev, &dev_attr_pickup_phase); + device_remove_file(dev, &dev_attr_capacitance); + device_remove_file(dev, &dev_attr_tone_resistance); + device_remove_file(dev, &dev_attr_volume_resistance); + device_remove_file(dev, &dev_attr_taper); + device_remove_file(dev, &dev_attr_tone_dump); + device_remove_file(dev, &dev_attr_save_tone); + device_remove_file(dev, &dev_attr_volume_dump); + device_remove_file(dev, &dev_attr_tuning_enable); + device_remove_file(dev, &dev_attr_tuning6); + device_remove_file(dev, &dev_attr_tuning5); + device_remove_file(dev, &dev_attr_tuning4); + device_remove_file(dev, &dev_attr_tuning3); + device_remove_file(dev, &dev_attr_tuning2); + device_remove_file(dev, &dev_attr_tuning1); + device_remove_file(dev, &dev_attr_detune6); + device_remove_file(dev, &dev_attr_detune5); + device_remove_file(dev, &dev_attr_detune4); + device_remove_file(dev, &dev_attr_detune3); + device_remove_file(dev, &dev_attr_detune2); + device_remove_file(dev, &dev_attr_detune1); + device_remove_file(dev, &dev_attr_mix6); + device_remove_file(dev, &dev_attr_mix5); + device_remove_file(dev, &dev_attr_mix4); + device_remove_file(dev, &dev_attr_mix3); + device_remove_file(dev, &dev_attr_mix2); + device_remove_file(dev, &dev_attr_mix1); + device_remove_file(dev, &dev_attr_pickup_wiring); +} + +EXPORT_SYMBOL(variax_create_files); +EXPORT_SYMBOL(variax_remove_files); diff --git a/drivers/staging/line6/control.h b/drivers/staging/line6/control.h new file mode 100644 index 000000000000..2f19665d95a9 --- /dev/null +++ b/drivers/staging/line6/control.h @@ -0,0 +1,187 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef LINE6_CONTROL_H +#define LINE6_CONTROL_H + + +/** + List of PODxt Pro controls. + See Appendix C of the "PODxt (Pro) Pilot's Handbook" by Line6. + Comments after the number refer to the PODxt Pro firmware version required + for this feature. +*/ +enum { + POD_tweak = 1, + POD_wah_position = 4, + POD_compression_gain = 5, /* device: LINE6_BITS_PODXTALL */ + POD_vol_pedal_position = 7, + POD_compression_threshold = 9, + POD_pan = 10, + POD_amp_model_setup = 11, + POD_amp_model = 12, /* firmware: 2.0 */ + POD_drive = 13, + POD_bass = 14, + POD_mid = 15, /* device: LINE6_BITS_PODXTALL */ + POD_lowmid = 15, /* device: LINE6_BITS_BASSPODXTALL */ + POD_treble = 16, /* device: LINE6_BITS_PODXTALL */ + POD_highmid = 16, /* device: LINE6_BITS_BASSPODXTALL */ + POD_chan_vol = 17, + POD_reverb_mix = 18, /* device: LINE6_BITS_PODXTALL */ + POD_effect_setup = 19, + POD_band_1_frequency = 20, /* firmware: 2.0 */ + POD_presence = 21, /* device: LINE6_BITS_PODXTALL */ + POD_treble__bass = 21, /* device: LINE6_BITS_BASSPODXTALL */ + POD_noise_gate_enable = 22, + POD_gate_threshold = 23, + POD_gate_decay_time = 24, + POD_stomp_enable = 25, + POD_comp_enable = 26, + POD_stomp_time = 27, + POD_delay_enable = 28, + POD_mod_param_1 = 29, + POD_delay_param_1 = 30, + POD_delay_param_1_note_value = 31, + POD_band_2_frequency__bass = 32, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_delay_param_2 = 33, + POD_delay_volume_mix = 34, + POD_delay_param_3 = 35, + POD_reverb_enable = 36, /* device: LINE6_BITS_PODXTALL */ + POD_reverb_type = 37, /* device: LINE6_BITS_PODXTALL */ + POD_reverb_decay = 38, /* device: LINE6_BITS_PODXTALL */ + POD_reverb_tone = 39, /* device: LINE6_BITS_PODXTALL */ + POD_reverb_pre_delay = 40, /* device: LINE6_BITS_PODXTALL */ + POD_reverb_pre_post = 41, /* device: LINE6_BITS_PODXTALL */ + POD_band_2_frequency = 42, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ + POD_band_3_frequency__bass = 42, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_wah_enable = 43, + POD_modulation_lo_cut = 44, /* device: LINE6_BITS_BASSPODXTALL */ + POD_delay_reverb_lo_cut = 45, /* device: LINE6_BITS_BASSPODXTALL */ + POD_volume_pedal_minimum = 46, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ + POD_eq_pre_post = 46, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_volume_pre_post = 47, + POD_di_model = 48, /* device: LINE6_BITS_BASSPODXTALL */ + POD_di_delay = 49, /* device: LINE6_BITS_BASSPODXTALL */ + POD_mod_enable = 50, + POD_mod_param_1_note_value = 51, + POD_mod_param_2 = 52, + POD_mod_param_3 = 53, + POD_mod_param_4 = 54, + POD_mod_param_5 = 55, /* device: LINE6_BITS_BASSPODXTALL */ + POD_mod_volume_mix = 56, + POD_mod_pre_post = 57, + POD_modulation_model = 58, + POD_band_3_frequency = 60, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ + POD_band_4_frequency__bass = 60, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_mod_param_1_double_precision = 61, + POD_delay_param_1_double_precision = 62, + POD_eq_enable = 63, /* firmware: 2.0 */ + POD_tap = 64, + POD_volume_tweak_pedal_assign = 65, + POD_band_5_frequency = 68, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_tuner = 69, + POD_mic_selection = 70, + POD_cabinet_model = 71, + POD_stomp_model = 75, + POD_roomlevel = 76, + POD_band_4_frequency = 77, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ + POD_band_6_frequency = 77, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_stomp_param_1_note_value = 78, + POD_stomp_param_2 = 79, + POD_stomp_param_3 = 80, + POD_stomp_param_4 = 81, + POD_stomp_param_5 = 82, + POD_stomp_param_6 = 83, + POD_amp_switch_select = 84, /* device: LINE6_BITS_LIVE */ + POD_delay_param_4 = 85, + POD_delay_param_5 = 86, + POD_delay_pre_post = 87, + POD_delay_model = 88, /* device: LINE6_BITS_PODXTALL */ + POD_delay_verb_model = 88, /* device: LINE6_BITS_BASSPODXTALL */ + POD_tempo_msb = 89, + POD_tempo_lsb = 90, + POD_wah_model = 91, /* firmware: 3.0 */ + POD_bypass_volume = 105, /* firmware: 2.14 */ + POD_fx_loop_on_off = 107, /* device: LINE6_BITS_PRO */ + POD_tweak_param_select = 108, + POD_amp1_engage = 111, + POD_band_1_gain = 114, /* firmware: 2.0 */ + POD_band_2_gain__bass = 115, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_band_2_gain = 116, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ + POD_band_3_gain__bass = 116, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_band_3_gain = 117, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ + POD_band_4_gain__bass = 117, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_band_5_gain__bass = 118, /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ + POD_band_4_gain = 119, /* device: LINE6_BITS_PODXTALL */ /* firmware: 2.0 */ + POD_band_6_gain__bass = 119 /* device: LINE6_BITS_BASSPODXTALL */ /* firmware: 2.0 */ +}; + +/** + List of Variax workbench controls (dump). +*/ +enum { + VARIAX_body = 3, + VARIAX_pickup1_enable = 4, /* 0: enabled, 1: disabled */ + VARIAX_pickup1_type = 8, + VARIAX_pickup1_position = 9, /* type: 24 bit float */ + VARIAX_pickup1_angle = 12, /* type: 24 bit float */ + VARIAX_pickup1_level = 15, /* type: 24 bit float */ + VARIAX_pickup2_enable = 18, /* 0: enabled, 1: disabled */ + VARIAX_pickup2_type = 22, + VARIAX_pickup2_position = 23, /* type: 24 bit float */ + VARIAX_pickup2_angle = 26, /* type: 24 bit float */ + VARIAX_pickup2_level = 29, /* type: 24 bit float */ + VARIAX_pickup_phase = 32, /* 0: in phase, 1: out of phase */ + VARIAX_capacitance = 33, /* type: 24 bit float */ + VARIAX_tone_resistance = 36, /* type: 24 bit float */ + VARIAX_volume_resistance = 39, /* type: 24 bit float */ + VARIAX_taper = 42, /* 0: Linear, 1: Audio */ + VARIAX_tone_dump = 43, /* type: 24 bit float */ + VARIAX_save_tone = 46, + VARIAX_volume_dump = 47, /* type: 24 bit float */ + VARIAX_tuning_enable = 50, + VARIAX_tuning6 = 51, + VARIAX_tuning5 = 52, + VARIAX_tuning4 = 53, + VARIAX_tuning3 = 54, + VARIAX_tuning2 = 55, + VARIAX_tuning1 = 56, + VARIAX_detune6 = 57, /* type: 24 bit float */ + VARIAX_detune5 = 60, /* type: 24 bit float */ + VARIAX_detune4 = 63, /* type: 24 bit float */ + VARIAX_detune3 = 66, /* type: 24 bit float */ + VARIAX_detune2 = 69, /* type: 24 bit float */ + VARIAX_detune1 = 72, /* type: 24 bit float */ + VARIAX_mix6 = 75, /* type: 24 bit float */ + VARIAX_mix5 = 78, /* type: 24 bit float */ + VARIAX_mix4 = 81, /* type: 24 bit float */ + VARIAX_mix3 = 84, /* type: 24 bit float */ + VARIAX_mix2 = 87, /* type: 24 bit float */ + VARIAX_mix1 = 90, /* type: 24 bit float */ + VARIAX_pickup_wiring = 96 /* 0: parallel, 1: series */ +}; + +/** + List of Variax workbench controls (MIDI). +*/ +enum { + VARIAXMIDI_volume = 7, + VARIAXMIDI_tone = 79, +}; + + +extern int pod_create_files(int firmware, int type, struct device *dev); +extern void pod_remove_files(int firmware, int type, struct device *dev); +extern int variax_create_files(int firmware, int type, struct device *dev); +extern void variax_remove_files(int firmware, int type, struct device *dev); + + +#endif diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c new file mode 100644 index 000000000000..85a20d0002c0 --- /dev/null +++ b/drivers/staging/line6/driver.c @@ -0,0 +1,1102 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" + +#include +#include +#include + +#include "audio.h" +#include "capture.h" +#include "control.h" +#include "midi.h" +#include "playback.h" +#include "pod.h" +#include "revision.h" +#include "toneport.h" +#include "usbdefs.h" +#include "variax.h" + + +#define DRIVER_AUTHOR "Markus Grabner " +#define DRIVER_DESC "Line6 USB Driver" +#define DRIVER_VERSION "0.8.0" + + +/* table of devices that work with this driver */ +static struct usb_device_id line6_id_table[] = { + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXT) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTLIVE) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_GUITARPORT) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_POCKETPOD) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3LIVE) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXT) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTLIVE) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTPRO) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_GX) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX1) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX2) }, + { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_VARIAX) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, line6_id_table); + +static struct line6_properties line6_properties_table[] = { + { "BassPODxt", LINE6_BIT_BASSPODXT, LINE6_BIT_CONTROL_PCM }, + { "BassPODxt Live", LINE6_BIT_BASSPODXTLIVE, LINE6_BIT_CONTROL_PCM }, + { "BassPODxt Pro", LINE6_BIT_BASSPODXTPRO, LINE6_BIT_CONTROL_PCM }, + { "GuitarPort", LINE6_BIT_GUITARPORT, LINE6_BIT_PCM }, + { "Pocket POD", LINE6_BIT_POCKETPOD, LINE6_BIT_CONTROL_PCM }, + { "POD X3", LINE6_BIT_PODX3, LINE6_BIT_PCM }, + { "POD X3 Live", LINE6_BIT_PODX3LIVE, LINE6_BIT_PCM }, + { "PODxt", LINE6_BIT_PODXT, LINE6_BIT_CONTROL_PCM }, + { "PODxt Live", LINE6_BIT_PODXTLIVE, LINE6_BIT_CONTROL_PCM }, + { "PODxt Pro", LINE6_BIT_PODXTPRO, LINE6_BIT_CONTROL_PCM }, + { "TonePort GX", LINE6_BIT_TONEPORT_GX, LINE6_BIT_PCM }, + { "TonePort UX1", LINE6_BIT_TONEPORT_UX1, LINE6_BIT_PCM }, + { "TonePort UX2", LINE6_BIT_TONEPORT_UX2, LINE6_BIT_PCM }, + { "Variax Workbench", LINE6_BIT_VARIAX, LINE6_BIT_CONTROL } +}; + + +/* + This is Line6's MIDI manufacturer ID. +*/ +const unsigned char line6_midi_id[] = { 0x00, 0x01, 0x0c }; + +struct usb_line6 *line6_devices[LINE6_MAX_DEVICES]; +struct workqueue_struct *line6_workqueue; + + +/** + Class for asynchronous messages. +*/ +struct message { + struct usb_line6 *line6; + const char *buffer; + int size; + int done; +}; + + +/* + Forward declarations. +*/ +static void line6_data_received(struct urb *urb); +static int line6_send_raw_message_async_part(struct message *msg, + struct urb *urb); + + +/* + Start to listen on endpoint. +*/ +static int line6_start_listen(struct usb_line6 *line6) +{ + usb_fill_int_urb(line6->urb_listen, line6->usbdev, + usb_rcvintpipe(line6->usbdev, line6->ep_control_read), + line6->buffer_listen, LINE6_BUFSIZE_LISTEN, + line6_data_received, line6, line6->interval); + line6->urb_listen->actual_length = 0; + return usb_submit_urb(line6->urb_listen, GFP_KERNEL); +} + +#if DO_DUMP_ANY +/* + Write hexdump to syslog. +*/ +void line6_write_hexdump(struct usb_line6 *line6, char dir, + const unsigned char *buffer, int size) +{ + static const int BYTES_PER_LINE = 8; + char hexdump[100]; + char asc[BYTES_PER_LINE + 1]; + int i, j; + + for (i = 0; i < size; i += BYTES_PER_LINE) { + int hexdumpsize = sizeof(hexdump); + char *p = hexdump; + int n = min(size - i, BYTES_PER_LINE); + asc[n] = 0; + + for (j = 0; j < BYTES_PER_LINE; ++j) { + int bytes; + + if (j < n) { + unsigned char val = buffer[i + j]; + bytes = snprintf(p, hexdumpsize, " %02X", val); + asc[j] = ((val >= 0x20) && (val < 0x7f)) ? val : '.'; + } else + bytes = snprintf(p, hexdumpsize, " "); + + if (bytes > hexdumpsize) + break; /* buffer overflow */ + + p += bytes; + hexdumpsize -= bytes; + } + + dev_info(line6->ifcdev, "%c%04X:%s %s\n", dir, i, hexdump, asc); + } +} +#endif + +#if DO_DUMP_URB_RECEIVE +/* + Dump URB data to syslog. +*/ +static void line6_dump_urb(struct urb *urb) +{ + struct usb_line6 *line6 = (struct usb_line6 *)urb->context; + + if (urb->status < 0) + return; + + line6_write_hexdump(line6, 'R', (unsigned char *)urb->transfer_buffer, + urb->actual_length); +} +#endif + +/* + Send raw message in pieces of wMaxPacketSize bytes. +*/ +int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, + int size) +{ + int i, done = 0; + +#if DO_DUMP_URB_SEND + line6_write_hexdump(line6, 'S', buffer, size); +#endif + + for (i = 0; i < size; i += line6->max_packet_size) { + int partial; + const char *frag_buf = buffer + i; + int frag_size = min(line6->max_packet_size, size - i); + int retval; + + retval = usb_interrupt_msg(line6->usbdev, + usb_sndintpipe(line6->usbdev, + line6->ep_control_write), + (char *)frag_buf, frag_size, + &partial, LINE6_TIMEOUT * HZ); + + if (retval) { + dev_err(line6->ifcdev, + "usb_interrupt_msg failed (%d)\n", retval); + break; + } + + done += frag_size; + } + + return done; +} + +/* + Notification of completion of asynchronous request transmission. +*/ +static void line6_async_request_sent(struct urb *urb) +{ + struct message *msg = (struct message *)urb->context; + + if (msg->done >= msg->size) { + usb_free_urb(urb); + kfree(msg); + } else + line6_send_raw_message_async_part(msg, urb); +} + +/* + Asynchronously send part of a raw message. +*/ +static int line6_send_raw_message_async_part(struct message *msg, + struct urb *urb) +{ + int retval; + struct usb_line6 *line6 = msg->line6; + int done = msg->done; + int bytes = min(msg->size - done, line6->max_packet_size); + + usb_fill_int_urb(urb, line6->usbdev, + usb_sndintpipe(line6->usbdev, line6->ep_control_write), + (char *)msg->buffer + done, bytes, + line6_async_request_sent, msg, line6->interval); + +#if DO_DUMP_URB_SEND + line6_write_hexdump(line6, 'S', (char *)msg->buffer + done, bytes); +#endif + + msg->done += bytes; + retval = usb_submit_urb(urb, GFP_ATOMIC); + + if (retval < 0) { + dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n", + __func__, retval); + usb_free_urb(urb); + kfree(msg); + return -EINVAL; + } + + return 0; +} + +/* + Asynchronously send raw message. +*/ +int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer, + int size) +{ + struct message *msg; + struct urb *urb; + + /* create message: */ + msg = kmalloc(sizeof(struct message), GFP_ATOMIC); + + if (msg == NULL) { + dev_err(line6->ifcdev, "Out of memory\n"); + return -ENOMEM; + } + + /* create URB: */ + urb = usb_alloc_urb(0, GFP_ATOMIC); + + if (urb == NULL) { + kfree(msg); + dev_err(line6->ifcdev, "Out of memory\n"); + return -ENOMEM; + } + + /* set message data: */ + msg->line6 = line6; + msg->buffer = buffer; + msg->size = size; + msg->done = 0; + + /* start sending: */ + return line6_send_raw_message_async_part(msg, urb); +} + +/* + Send sysex message in pieces of wMaxPacketSize bytes. +*/ +int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer, + int size) +{ + return line6_send_raw_message(line6, buffer, size + SYSEX_EXTRA_SIZE) - SYSEX_EXTRA_SIZE; +} + +/* + Allocate buffer for sysex message and prepare header. + @param code sysex message code + @param size number of bytes between code and sysex end +*/ +char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, int code2, + int size) +{ + char *buffer = kmalloc(size + SYSEX_EXTRA_SIZE, GFP_KERNEL); + + if (!buffer) { + dev_err(line6->ifcdev, "out of memory\n"); + return NULL; + } + + buffer[0] = LINE6_SYSEX_BEGIN; + memcpy(buffer + 1, line6_midi_id, sizeof(line6_midi_id)); + buffer[sizeof(line6_midi_id) + 1] = code1; + buffer[sizeof(line6_midi_id) + 2] = code2; + buffer[sizeof(line6_midi_id) + 3 + size] = LINE6_SYSEX_END; + return buffer; +} + +/* + Notification of data received from the Line6 device. +*/ +static void line6_data_received(struct urb *urb) +{ + struct usb_line6 *line6 = (struct usb_line6 *)urb->context; + struct MidiBuffer *mb = &line6->line6midi->midibuf_in; + int done; + + if (urb->status == -ESHUTDOWN) + return; + +#if DO_DUMP_URB_RECEIVE + line6_dump_urb(urb); +#endif + + done = midibuf_write(mb, urb->transfer_buffer, urb->actual_length); + + if (done < urb->actual_length) { + midibuf_ignore(mb, done); + DEBUG_MESSAGES(dev_err(line6->ifcdev, "%d %d buffer overflow - message skipped\n", done, urb->actual_length)); + } + + for (;;) { + done = midibuf_read(mb, line6->buffer_message, LINE6_MESSAGE_MAXLEN); + + if (done == 0) + break; + + /* MIDI input filter */ + if (midibuf_skip_message(mb, line6->line6midi->midi_mask_receive)) + continue; + + line6->message_length = done; +#if DO_DUMP_MIDI_RECEIVE + line6_write_hexdump(line6, 'r', line6->buffer_message, done); +#endif + line6_midi_receive(line6, line6->buffer_message, done); + + switch (line6->usbdev->descriptor.idProduct) { + case LINE6_DEVID_BASSPODXT: + case LINE6_DEVID_BASSPODXTLIVE: + case LINE6_DEVID_BASSPODXTPRO: + case LINE6_DEVID_PODXT: + case LINE6_DEVID_PODXTPRO: + case LINE6_DEVID_POCKETPOD: + pod_process_message((struct usb_line6_pod *)line6); + break; + + case LINE6_DEVID_PODXTLIVE: + switch (line6->interface_number) { + case PODXTLIVE_INTERFACE_POD: + pod_process_message((struct usb_line6_pod *)line6); + break; + + case PODXTLIVE_INTERFACE_VARIAX: + variax_process_message((struct usb_line6_variax *)line6); + break; + + default: + dev_err(line6->ifcdev, "PODxt Live interface %d not supported\n", line6->interface_number); + } + break; + + case LINE6_DEVID_VARIAX: + variax_process_message((struct usb_line6_variax *)line6); + break; + + default: + MISSING_CASE; + } + } + + line6_start_listen(line6); +} + +/* + Send channel number (i.e., switch to a different sound). +*/ +int line6_send_program(struct usb_line6 *line6, int value) +{ + int retval; + unsigned char *buffer; + unsigned int partial; + + buffer = kmalloc(2, GFP_KERNEL); + + if (!buffer) { + dev_err(line6->ifcdev, "out of memory\n"); + return -ENOMEM; + } + + buffer[0] = LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST; + buffer[1] = value; + +#if DO_DUMP_URB_SEND + line6_write_hexdump(line6, 'S', buffer, 2); +#endif + + retval = usb_interrupt_msg(line6->usbdev, + usb_sndintpipe(line6->usbdev, + line6->ep_control_write), + buffer, 2, &partial, LINE6_TIMEOUT * HZ); + + if (retval) + dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", retval); + + kfree(buffer); + return retval; +} + +/* + Transmit Line6 control parameter. +*/ +int line6_transmit_parameter(struct usb_line6 *line6, int param, int value) +{ + int retval; + unsigned char *buffer; + unsigned int partial; + + buffer = kmalloc(3, GFP_KERNEL); + + if (!buffer) { + dev_err(line6->ifcdev, "out of memory\n"); + return -ENOMEM; + } + + buffer[0] = LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST; + buffer[1] = param; + buffer[2] = value; + +#if DO_DUMP_URB_SEND + line6_write_hexdump(line6, 'S', buffer, 3); +#endif + + retval = usb_interrupt_msg(line6->usbdev, + usb_sndintpipe(line6->usbdev, line6->ep_control_write), + buffer, 3, &partial, LINE6_TIMEOUT * HZ); + + if (retval) + dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", retval); + + kfree(buffer); + return retval; +} + +/* + Read data from device. +*/ +int line6_read_data(struct usb_line6 *line6, int address, void *data, size_t datalen) +{ + struct usb_device *usbdev = line6->usbdev; + int ret; + unsigned char len; + + /* query the serial number: */ + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + (datalen << 8) | 0x21, address, NULL, 0, LINE6_TIMEOUT * HZ); + + if (ret < 0) { + dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); + return ret; + } + + /* Wait for data length. We'll get a couple of 0xff until length arrives. */ + do { + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_IN, + 0x0012, 0x0000, &len, 1, + LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(line6->ifcdev, + "receive length failed (error %d)\n", ret); + return ret; + } + } + while (len == 0xff) + ; + + if (len != datalen) { + /* should be equal or something went wrong */ + dev_err(line6->ifcdev, + "length mismatch (expected %d, got %d)\n", + (int)datalen, (int)len); + return -EINVAL; + } + + /* receive the result: */ + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x0013, 0x0000, data, datalen, + LINE6_TIMEOUT * HZ); + + if (ret < 0) { + dev_err(line6->ifcdev, "read failed (error %d)\n", ret); + return ret; + } + + return 0; +} + +/* + Write data to device. +*/ +int line6_write_data(struct usb_line6 *line6, int address, void *data, + size_t datalen) +{ + struct usb_device *usbdev = line6->usbdev; + int ret; + unsigned char status; + + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + 0x0022, address, data, datalen, + LINE6_TIMEOUT * HZ); + + if (ret < 0) { + dev_err(line6->ifcdev, + "write request failed (error %d)\n", ret); + return ret; + } + + do { + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), + 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_IN, + 0x0012, 0x0000, + &status, 1, LINE6_TIMEOUT * HZ); + + if (ret < 0) { + dev_err(line6->ifcdev, + "receiving status failed (error %d)\n", ret); + return ret; + } + } + while (status == 0xff) + ; + + if (status != 0) { + dev_err(line6->ifcdev, "write failed (error %d)\n", ret); + return -EINVAL; + } + + return 0; +} + +/* + Read Line6 device serial number. + (POD, TonePort, GuitarPort) +*/ +int line6_read_serial_number(struct usb_line6 *line6, int *serial_number) +{ + return line6_read_data(line6, 0x80d0, serial_number, sizeof(*serial_number)); +} + +/* + No operation (i.e., unsupported). +*/ +ssize_t line6_nop_read(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return 0; +} + +/* + No operation (i.e., unsupported). +*/ +ssize_t line6_nop_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return count; +} + +/* + "write" request on "raw" special file. +*/ +#if CREATE_RAW_FILE +ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6 *line6 = usb_get_intfdata(interface); + line6_send_raw_message(line6, buf, count); + return count; +} +#endif + +/* + Generic destructor. +*/ +static void line6_destruct(struct usb_interface *interface) +{ + struct usb_line6 *line6; + + if (interface == NULL) + return; + line6 = usb_get_intfdata(interface); + if (line6 == NULL) + return; + + /* free buffer memory first: */ + kfree(line6->buffer_message); + kfree(line6->buffer_listen); + + /* then free URBs: */ + usb_free_urb(line6->urb_listen); + + /* make sure the device isn't destructed twice: */ + usb_set_intfdata(interface, NULL); + + /* free interface data: */ + kfree(line6); +} + +static void line6_list_devices(void) +{ + int i; + + for (i = 0; i < LINE6_MAX_DEVICES; ++i) { + struct usb_line6 *dev = line6_devices[i]; + printk(KERN_INFO "Line6 device %d: ", i); + + if (dev == NULL) + printk("(not used)\n"); + else + printk("%s:%d\n", dev->properties->name, dev->interface_number); + } +} + +/* + Probe USB device. +*/ +static int line6_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + int devtype; + struct usb_device *usbdev = NULL; + struct usb_line6 *line6 = NULL; + const struct line6_properties *properties; + int devnum; + int interface_number, alternate = 0; + int product; + int size = 0; + int ep_read = 0, ep_write = 0; + int ret; + + if (interface == NULL) + return -ENODEV; + usbdev = interface_to_usbdev(interface); + if (usbdev == NULL) + return -ENODEV; + + /* increment reference counters: */ + usb_get_intf(interface); + usb_get_dev(usbdev); + + /* we don't handle multiple configurations */ + if (usbdev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + /* check vendor and product id */ + for (devtype = sizeof(line6_id_table) / sizeof(line6_id_table[0]) - 1; devtype--;) + if ((le16_to_cpu(usbdev->descriptor.idVendor) == line6_id_table[devtype].idVendor) && + (le16_to_cpu(usbdev->descriptor.idProduct) == line6_id_table[devtype].idProduct)) + break; + + if (devtype < 0) + return -ENODEV; + + /* find free slot in device table: */ + for (devnum = 0; devnum < LINE6_MAX_DEVICES; ++devnum) + if (line6_devices[devnum] == NULL) + break; + + if (devnum == LINE6_MAX_DEVICES) + return -ENODEV; + + /* initialize device info: */ + properties = &line6_properties_table[devtype]; + dev_info(&interface->dev, "Line6 %s found\n", properties->name); + product = le16_to_cpu(usbdev->descriptor.idProduct); + + /* query interface number */ + interface_number = interface->cur_altsetting->desc.bInterfaceNumber; + + switch (product) { + case LINE6_DEVID_BASSPODXTLIVE: + case LINE6_DEVID_POCKETPOD: + case LINE6_DEVID_PODXTLIVE: + case LINE6_DEVID_VARIAX: + alternate = 1; + break; + + case LINE6_DEVID_PODX3: + case LINE6_DEVID_PODX3LIVE: + switch (interface_number) { + case 0: + alternate = 1; + break; + case 1: + alternate = 0; + break; + default: + MISSING_CASE; + } + break; + + case LINE6_DEVID_BASSPODXT: + case LINE6_DEVID_BASSPODXTPRO: + case LINE6_DEVID_PODXT: + case LINE6_DEVID_PODXTPRO: + alternate = 5; + break; + + case LINE6_DEVID_TONEPORT_GX: + case LINE6_DEVID_GUITARPORT: + alternate = 2; /* 1..4 seem to be ok */ + break; + + case LINE6_DEVID_TONEPORT_UX1: + case LINE6_DEVID_TONEPORT_UX2: + switch (interface_number) { + case 0: + /* defaults to 44.1kHz, 16-bit */ + alternate = 2; + break; + case 1: + alternate = 0; + break; + default: + MISSING_CASE; + } + break; + + default: + MISSING_CASE; + return -ENODEV; + } + + ret = usb_set_interface(usbdev, interface_number, alternate); + if (ret < 0) { + dev_err(&interface->dev, "set_interface failed\n"); + return ret; + } + + /* initialize device data based on product id: */ + switch (product) { + case LINE6_DEVID_BASSPODXT: + case LINE6_DEVID_BASSPODXTLIVE: + case LINE6_DEVID_BASSPODXTPRO: + case LINE6_DEVID_POCKETPOD: + case LINE6_DEVID_PODXT: + case LINE6_DEVID_PODXTPRO: + size = sizeof(struct usb_line6_pod); + ep_read = 0x84; + ep_write = 0x03; + break; + + case LINE6_DEVID_PODX3: + case LINE6_DEVID_PODX3LIVE: + /* currently unused! */ + size = sizeof(struct usb_line6_pod); + ep_read = 0x81; + ep_write = 0x01; + break; + + case LINE6_DEVID_TONEPORT_GX: + case LINE6_DEVID_TONEPORT_UX1: + case LINE6_DEVID_TONEPORT_UX2: + case LINE6_DEVID_GUITARPORT: + size = sizeof(struct usb_line6_toneport); + /* these don't have a control channel */ + break; + + case LINE6_DEVID_PODXTLIVE: + switch (interface_number) { + case PODXTLIVE_INTERFACE_POD: + size = sizeof(struct usb_line6_pod); + ep_read = 0x84; + ep_write = 0x03; + break; + + case PODXTLIVE_INTERFACE_VARIAX: + size = sizeof(struct usb_line6_variax); + ep_read = 0x86; + ep_write = 0x05; + break; + + default: + return -ENODEV; + } + break; + + case LINE6_DEVID_VARIAX: + size = sizeof(struct usb_line6_variax); + ep_read = 0x82; + ep_write = 0x01; + break; + + default: + MISSING_CASE; + return -ENODEV; + } + + if (size == 0) { + dev_err(line6->ifcdev, "driver bug: interface data size not set\n"); + return -ENODEV; + } + + line6 = kzalloc(size, GFP_KERNEL); + + if (line6 == NULL) { + dev_err(&interface->dev, "Out of memory\n"); + return -ENOMEM; + } + + /* store basic data: */ + line6->interface_number = interface_number; + line6->properties = properties; + line6->usbdev = usbdev; + line6->ifcdev = &interface->dev; + line6->ep_control_read = ep_read; + line6->ep_control_write = ep_write; + line6->product = product; + + /* get data from endpoint descriptor (see usb_maxpacket): */ + { + struct usb_host_endpoint *ep; + unsigned epnum = usb_pipeendpoint(usb_rcvintpipe(usbdev, ep_read)); + ep = usbdev->ep_in[epnum]; + + if (ep != NULL) { + line6->interval = ep->desc.bInterval; + line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); + } else { + line6->interval = LINE6_FALLBACK_INTERVAL; + line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE; + dev_err(line6->ifcdev, "endpoint not available, using fallback values"); + } + } + + usb_set_intfdata(interface, line6); + + if (properties->capabilities & LINE6_BIT_CONTROL) { + /* initialize USB buffers: */ + line6->buffer_listen = kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL); + + if (line6->buffer_listen == NULL) { + dev_err(&interface->dev, "Out of memory\n"); + line6_destruct(interface); + return -ENOMEM; + } + + line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL); + + if (line6->buffer_message == NULL) { + dev_err(&interface->dev, "Out of memory\n"); + line6_destruct(interface); + return -ENOMEM; + } + + line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL); + + if (line6->urb_listen == NULL) { + dev_err(&interface->dev, "Out of memory\n"); + line6_destruct(interface); + return -ENOMEM; + } + + ret = line6_start_listen(line6); + if (ret < 0) { + dev_err(&interface->dev, "%s: usb_submit_urb failed\n", + __func__); + line6_destruct(interface); + return ret; + } + } + + /* initialize device data based on product id: */ + switch (product) { + case LINE6_DEVID_BASSPODXT: + case LINE6_DEVID_BASSPODXTLIVE: + case LINE6_DEVID_BASSPODXTPRO: + case LINE6_DEVID_POCKETPOD: + case LINE6_DEVID_PODX3: + case LINE6_DEVID_PODX3LIVE: + case LINE6_DEVID_PODXT: + case LINE6_DEVID_PODXTPRO: + ret = pod_init(interface, (struct usb_line6_pod *)line6); + break; + + case LINE6_DEVID_PODXTLIVE: + switch (interface_number) { + case PODXTLIVE_INTERFACE_POD: + ret = pod_init(interface, (struct usb_line6_pod *)line6); + break; + + case PODXTLIVE_INTERFACE_VARIAX: + ret = variax_init(interface, (struct usb_line6_variax *)line6); + break; + + default: + dev_err(&interface->dev, + "PODxt Live interface %d not supported\n", + interface_number); + ret = -ENODEV; + } + + break; + + case LINE6_DEVID_VARIAX: + ret = variax_init(interface, (struct usb_line6_variax *)line6); + break; + + case LINE6_DEVID_TONEPORT_GX: + case LINE6_DEVID_TONEPORT_UX1: + case LINE6_DEVID_TONEPORT_UX2: + case LINE6_DEVID_GUITARPORT: + ret = toneport_init(interface, (struct usb_line6_toneport *)line6); + break; + + default: + MISSING_CASE; + ret = -ENODEV; + } + + if (ret < 0) { + line6_destruct(interface); + return ret; + } + + ret = sysfs_create_link(&interface->dev.kobj, &usbdev->dev.kobj, + "usb_device"); + if (ret < 0) { + line6_destruct(interface); + return ret; + } + + dev_info(&interface->dev, "Line6 %s now attached\n", + line6->properties->name); + line6_devices[devnum] = line6; + line6_list_devices(); + return ret; +} + +/* + Line6 device disconnected. +*/ +static void line6_disconnect(struct usb_interface *interface) +{ + struct usb_line6 *line6; + struct usb_device *usbdev; + int interface_number, i; + + if (interface == NULL) + return; + usbdev = interface_to_usbdev(interface); + if (usbdev == NULL) + return; + + sysfs_remove_link(&interface->dev.kobj, "usb_device"); + + interface_number = interface->cur_altsetting->desc.bInterfaceNumber; + line6 = usb_get_intfdata(interface); + + if (line6 != NULL) { + if (line6->urb_listen != NULL) + usb_kill_urb(line6->urb_listen); + + if (usbdev != line6->usbdev) + dev_err(line6->ifcdev, + "driver bug: inconsistent usb device\n"); + + switch (line6->usbdev->descriptor.idProduct) { + case LINE6_DEVID_BASSPODXT: + case LINE6_DEVID_BASSPODXTLIVE: + case LINE6_DEVID_BASSPODXTPRO: + case LINE6_DEVID_POCKETPOD: + case LINE6_DEVID_PODX3: + case LINE6_DEVID_PODX3LIVE: + case LINE6_DEVID_PODXT: + case LINE6_DEVID_PODXTPRO: + pod_disconnect(interface); + break; + + case LINE6_DEVID_PODXTLIVE: + switch (interface_number) { + case PODXTLIVE_INTERFACE_POD: + pod_disconnect(interface); + break; + + case PODXTLIVE_INTERFACE_VARIAX: + variax_disconnect(interface); + break; + } + + break; + + case LINE6_DEVID_VARIAX: + variax_disconnect(interface); + break; + + case LINE6_DEVID_TONEPORT_GX: + case LINE6_DEVID_TONEPORT_UX1: + case LINE6_DEVID_TONEPORT_UX2: + case LINE6_DEVID_GUITARPORT: + toneport_disconnect(interface); + break; + + default: + MISSING_CASE; + } + + dev_info(&interface->dev, "Line6 %s now disconnected\n", line6->properties->name); + + for (i = LINE6_MAX_DEVICES; i--;) + if (line6_devices[i] == line6) + line6_devices[i] = NULL; + } + + line6_destruct(interface); + + /* decrement reference counters: */ + usb_put_intf(interface); + usb_put_dev(usbdev); + + line6_list_devices(); +} + +static struct usb_driver line6_driver = { + .name = DRIVER_NAME, + .probe = line6_probe, + .disconnect = line6_disconnect, + .id_table = line6_id_table, +}; + +/* + Module initialization. +*/ +static int __init line6_init(void) +{ + int i, retval; + + printk(KERN_INFO "%s driver version %s%s\n", + DRIVER_NAME, DRIVER_VERSION, DRIVER_REVISION); + line6_workqueue = create_workqueue(DRIVER_NAME); + + if (line6_workqueue == NULL) { + err("couldn't create workqueue"); + return -EINVAL; + } + + for (i = LINE6_MAX_DEVICES; i--;) + line6_devices[i] = NULL; + + retval = usb_register(&line6_driver); + + if (retval) + err("usb_register failed. Error number %d", retval); + + return retval; +} + +/* + Module cleanup. +*/ +static void __exit line6_exit(void) +{ + destroy_workqueue(line6_workqueue); + usb_deregister(&line6_driver); +} + +module_init(line6_init); +module_exit(line6_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRIVER_VERSION); diff --git a/drivers/staging/line6/driver.h b/drivers/staging/line6/driver.h new file mode 100644 index 000000000000..9908bfa6afaf --- /dev/null +++ b/drivers/staging/line6/driver.h @@ -0,0 +1,204 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef DRIVER_H +#define DRIVER_H + + +#include "config.h" + +#include +#include +#include +#include + +#include "midi.h" + +#define DRIVER_NAME "line6usb" + +#define LINE6_TIMEOUT 1 +#define LINE6_MAX_DEVICES 8 +#define LINE6_BUFSIZE_LISTEN 32 +#define LINE6_MESSAGE_MAXLEN 256 + + +/* + Line6 MIDI control commands +*/ +#define LINE6_PARAM_CHANGE 0xb0 +#define LINE6_PROGRAM_CHANGE 0xc0 +#define LINE6_SYSEX_BEGIN 0xf0 +#define LINE6_SYSEX_END 0xf7 +#define LINE6_RESET 0xff + +/* + MIDI channel for messages initiated by the host + (and eventually echoed back by the device) +*/ +#define LINE6_CHANNEL_HOST 0x00 + +/* + MIDI channel for messages initiated by the device +*/ +#define LINE6_CHANNEL_DEVICE 0x02 + +#define LINE6_CHANNEL_UNKNOWN 5 /* don't know yet what this is good for */ + +#define LINE6_CHANNEL_MASK 0x0f + + +#define MISSING_CASE \ + printk(KERN_ERR "line6usb driver bug: missing case in %s:%d\n", \ + __FILE__, __LINE__) + + +#define CHECK_RETURN(x) \ +do { \ + err = x; \ + if (err < 0) \ + return err; \ +} while (0) + + +extern const unsigned char line6_midi_id[3]; +extern struct usb_line6 *line6_devices[LINE6_MAX_DEVICES]; +extern struct workqueue_struct *line6_workqueue; + +static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3; +static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4; + + +/** + Common properties of Line6 devices. +*/ +struct line6_properties { + const char *name; + int device_bit; + int capabilities; +}; + +/** + Common data shared by all Line6 devices. + Corresponds to a pair of USB endpoints. +*/ +struct usb_line6 { + /** + USB device. + */ + struct usb_device *usbdev; + + /** + Product id. + */ + int product; + + /** + Properties. + */ + const struct line6_properties *properties; + + /** + Interface number. + */ + int interface_number; + + /** + Interval (ms). + */ + int interval; + + /** + Maximum size of USB packet. + */ + int max_packet_size; + + /** + Device representing the USB interface. + */ + struct device *ifcdev; + + /** + Line6 sound card data structure. + Each device has at least MIDI or PCM. + */ + struct snd_card *card; + + /** + Line6 PCM device data structure. + */ + struct snd_line6_pcm *line6pcm; + + /** + Line6 MIDI device data structure. + */ + struct snd_line6_midi *line6midi; + + /** + USB endpoint for listening to control commands. + */ + int ep_control_read; + + /** + USB endpoint for writing control commands. + */ + int ep_control_write; + + /** + URB for listening to PODxt Pro control endpoint. + */ + struct urb *urb_listen; + + /** + Buffer for listening to PODxt Pro control endpoint. + */ + unsigned char *buffer_listen; + + /** + Buffer for message to be processed. + */ + unsigned char *buffer_message; + + /** + Length of message to be processed. + */ + int message_length; +}; + + +extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, + int code2, int size); +extern ssize_t line6_nop_read(struct device *dev, + struct device_attribute *attr, char *buf); +extern ssize_t line6_nop_write(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +extern int line6_read_data(struct usb_line6 *line6, int address, void *data, + size_t datalen); +extern int line6_read_serial_number(struct usb_line6 *line6, + int *serial_number); +extern int line6_send_program(struct usb_line6 *line6, int value); +extern int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, + int size); +extern int line6_send_raw_message_async(struct usb_line6 *line6, + const char *buffer, int size); +extern int line6_send_sysex_message(struct usb_line6 *line6, + const char *buffer, int size); +extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); +extern int line6_transmit_parameter(struct usb_line6 *line6, int param, + int value); +extern int line6_write_data(struct usb_line6 *line6, int address, void *data, + size_t datalen); +extern void line6_write_hexdump(struct usb_line6 *line6, char dir, + const unsigned char *buffer, int size); + + +#endif diff --git a/drivers/staging/line6/dumprequest.c b/drivers/staging/line6/dumprequest.c new file mode 100644 index 000000000000..decbaa971b68 --- /dev/null +++ b/drivers/staging/line6/dumprequest.c @@ -0,0 +1,151 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" +#include "dumprequest.h" + + +/* + Set "dump in progress" flag. +*/ +void line6_dump_started(struct line6_dump_request *l6dr, int dest) +{ + l6dr->in_progress = dest; +} + +/* + Invalidate current channel, i.e., set "dump in progress" flag. + Reading from the "dump" special file blocks until dump is completed. +*/ +void line6_invalidate_current(struct line6_dump_request *l6dr) +{ + line6_dump_started(l6dr, LINE6_DUMP_CURRENT); +} + +/* + Clear "dump in progress" flag and notify waiting processes. +*/ +void line6_dump_finished(struct line6_dump_request *l6dr) +{ + l6dr->in_progress = LINE6_DUMP_NONE; + wake_up_interruptible(&l6dr->wait); +} + +/* + Send an asynchronous channel dump request. +*/ +int line6_dump_request_async(struct line6_dump_request *l6dr, + struct usb_line6 *line6, int num) +{ + int ret; + line6_invalidate_current(l6dr); + ret = line6_send_raw_message_async(line6, l6dr->reqbufs[num].buffer, + l6dr->reqbufs[num].length); + + if (ret < 0) + line6_dump_finished(l6dr); + + return ret; +} + +/* + Send an asynchronous dump request after a given interval. +*/ +void line6_startup_delayed(struct line6_dump_request *l6dr, int seconds, + void (*function)(unsigned long), void *data) +{ + l6dr->timer.expires = jiffies + seconds * HZ; + l6dr->timer.function = function; + l6dr->timer.data = (unsigned long)data; + add_timer(&l6dr->timer); +} + +/* + Wait for completion. +*/ +int line6_wait_dump(struct line6_dump_request *l6dr, int nonblock) +{ + int retval = 0; + DECLARE_WAITQUEUE(wait, current); + add_wait_queue(&l6dr->wait, &wait); + current->state = TASK_INTERRUPTIBLE; + + while (l6dr->in_progress) { + if (nonblock) { + retval = -EAGAIN; + break; + } + + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } else + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue(&l6dr->wait, &wait); + return retval; +} + +/* + Initialize dump request buffer. +*/ +int line6_dumpreq_initbuf(struct line6_dump_request *l6dr, const void *buf, + size_t len, int num) +{ + l6dr->reqbufs[num].buffer = kmalloc(len, GFP_KERNEL); + if (l6dr->reqbufs[num].buffer == NULL) + return -ENOMEM; + memcpy(l6dr->reqbufs[num].buffer, buf, len); + l6dr->reqbufs[num].length = len; + return 0; +} + +/* + Initialize dump request data structure (including one buffer). +*/ +int line6_dumpreq_init(struct line6_dump_request *l6dr, const void *buf, + size_t len) +{ + int ret; + ret = line6_dumpreq_initbuf(l6dr, buf, len, 0); + if (ret < 0) + return ret; + init_waitqueue_head(&l6dr->wait); + init_timer(&l6dr->timer); + return 0; +} + +/* + Destruct dump request data structure. +*/ +void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num) +{ + if (l6dr == NULL) + return; + if (l6dr->reqbufs[num].buffer == NULL) + return; + kfree(l6dr->reqbufs[num].buffer); + l6dr->reqbufs[num].buffer = NULL; +} + +/* + Destruct dump request data structure. +*/ +void line6_dumpreq_destruct(struct line6_dump_request *l6dr) +{ + if (l6dr->reqbufs[0].buffer == NULL) + return; + line6_dumpreq_destructbuf(l6dr, 0); + l6dr->ok = 1; + del_timer_sync(&l6dr->timer); +} diff --git a/drivers/staging/line6/dumprequest.h b/drivers/staging/line6/dumprequest.h new file mode 100644 index 000000000000..1975d54b3c20 --- /dev/null +++ b/drivers/staging/line6/dumprequest.h @@ -0,0 +1,90 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef DUMPREQUEST_H +#define DUMPREQUEST_H + + +#include +#include + +#include + + +enum { + LINE6_DUMP_NONE, + LINE6_DUMP_CURRENT +}; + + +struct line6_dump_reqbuf { + /** + Buffer for dump requests. + */ + unsigned char *buffer; + + /** + Size of dump request. + */ + size_t length; +}; + +/** + Provides the functionality to request channel/model/... dump data from a + Line6 device. +*/ +struct line6_dump_request { + /** + Wait queue for access to program dump data. + */ + wait_queue_head_t wait; + + /** + Indicates an unfinished program dump request. + 0: no dump + 1: dump current settings + Other device-specific values are also allowed. + */ + int in_progress; + + /** + Timer for delayed dump request. + */ + struct timer_list timer; + + /** + Flag if initial dump request has been successful. + */ + char ok; + + /** + Dump request buffers + */ + struct line6_dump_reqbuf reqbufs[1]; +}; + +extern void line6_dump_finished(struct line6_dump_request *l6dr); +extern int line6_dump_request_async(struct line6_dump_request *l6dr, + struct usb_line6 *line6, int num); +extern void line6_dump_started(struct line6_dump_request *l6dr, int dest); +extern void line6_dumpreq_destruct(struct line6_dump_request *l6dr); +extern void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num); +extern int line6_dumpreq_init(struct line6_dump_request *l6dr, const void *buf, + size_t len); +extern int line6_dumpreq_initbuf(struct line6_dump_request *l6dr, + const void *buf, size_t len, int num); +extern void line6_invalidate_current(struct line6_dump_request *l6dr); +extern void line6_startup_delayed(struct line6_dump_request *l6dr, int seconds, + void (*function)(unsigned long), void *data); +extern int line6_wait_dump(struct line6_dump_request *l6dr, int nonblock); + + +#endif diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c new file mode 100644 index 000000000000..89a2b17e9caf --- /dev/null +++ b/drivers/staging/line6/midi.c @@ -0,0 +1,422 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" + +#include + +#include +#include + +#include "audio.h" +#include "midi.h" +#include "pod.h" +#include "usbdefs.h" + + +#define USE_MIDIBUF 1 +#define OUTPUT_DUMP_ONLY 0 + + +#define line6_rawmidi_substream_midi(substream) \ + ((struct snd_line6_midi *)((substream)->rmidi->private_data)) + + +static int send_midi_async(struct usb_line6 *line6, unsigned char *data, + int length); + + +/* + Pass data received via USB to MIDI. +*/ +void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, + int length) +{ + if (line6->line6midi->substream_receive) + snd_rawmidi_receive(line6->line6midi->substream_receive, + data, length); +} + +/* + Read data from MIDI buffer and transmit them via USB. +*/ +static void line6_midi_transmit(struct snd_rawmidi_substream *substream) +{ + struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6; + struct snd_line6_midi *line6midi = line6->line6midi; + struct MidiBuffer *mb = &line6midi->midibuf_out; + unsigned long flags; + unsigned char chunk[line6->max_packet_size]; + int req, done; + + spin_lock_irqsave(&line6->line6midi->midi_transmit_lock, flags); + + for (;;) { + req = min(midibuf_bytes_free(mb), line6->max_packet_size); + done = snd_rawmidi_transmit_peek(substream, chunk, req); + + if (done == 0) + break; + +#if DO_DUMP_MIDI_SEND + line6_write_hexdump(line6, 's', chunk, done); +#endif + midibuf_write(mb, chunk, done); + snd_rawmidi_transmit_ack(substream, done); + } + + for (;;) { + done = midibuf_read(mb, chunk, line6->max_packet_size); + + if (done == 0) + break; + + if (midibuf_skip_message(mb, line6midi->midi_mask_transmit)) + continue; + + send_midi_async(line6, chunk, done); + } + + spin_unlock_irqrestore(&line6->line6midi->midi_transmit_lock, flags); +} + +/* + Notification of completion of MIDI transmission. +*/ +static void midi_sent(struct urb *urb) +{ + unsigned long flags; + int status; + int num; + struct usb_line6 *line6 = (struct usb_line6 *)urb->context; + + status = urb->status; + kfree(urb->transfer_buffer); + usb_free_urb(urb); + + if (status == -ESHUTDOWN) + return; + + spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags); + num = --line6->line6midi->num_active_send_urbs; + + if (num == 0) { + line6_midi_transmit(line6->line6midi->substream_transmit); + num = line6->line6midi->num_active_send_urbs; + } + + if (num == 0) + wake_up_interruptible(&line6->line6midi->send_wait); + + spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags); +} + +/* + Send an asynchronous MIDI message. + Assumes that line6->line6midi->send_urb_lock is held + (i.e., this function is serialized). +*/ +static int send_midi_async(struct usb_line6 *line6, unsigned char *data, + int length) +{ + struct urb *urb; + int retval; + unsigned char *transfer_buffer; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + + if (urb == 0) { + dev_err(line6->ifcdev, "Out of memory\n"); + return -ENOMEM; + } + +#if DO_DUMP_URB_SEND + line6_write_hexdump(line6, 'S', data, length); +#endif + + transfer_buffer = kmalloc(length, GFP_ATOMIC); + + if (transfer_buffer == 0) { + usb_free_urb(urb); + dev_err(line6->ifcdev, "Out of memory\n"); + return -ENOMEM; + } + + memcpy(transfer_buffer, data, length); + usb_fill_int_urb(urb, line6->usbdev, + usb_sndbulkpipe(line6->usbdev, + line6->ep_control_write), + transfer_buffer, length, midi_sent, line6, + line6->interval); + urb->actual_length = 0; + retval = usb_submit_urb(urb, GFP_ATOMIC); + + if (retval < 0) { + dev_err(line6->ifcdev, "usb_submit_urb failed\n"); + usb_free_urb(urb); + return -EINVAL; + } + + ++line6->line6midi->num_active_send_urbs; + + switch (line6->usbdev->descriptor.idProduct) { + case LINE6_DEVID_BASSPODXT: + case LINE6_DEVID_BASSPODXTLIVE: + case LINE6_DEVID_BASSPODXTPRO: + case LINE6_DEVID_PODXT: + case LINE6_DEVID_PODXTLIVE: + case LINE6_DEVID_PODXTPRO: + case LINE6_DEVID_POCKETPOD: + pod_midi_postprocess((struct usb_line6_pod *)line6, data, + length); + break; + + default: + MISSING_CASE; + } + + return 0; +} + +static int line6_midi_output_open(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static int line6_midi_output_close(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, + int up) +{ + unsigned long flags; + struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6; + + line6->line6midi->substream_transmit = substream; + spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags); + + if (line6->line6midi->num_active_send_urbs == 0) + line6_midi_transmit(substream); + + spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags); +} + +static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) +{ + struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6; + wait_queue_head_t *head = &line6->line6midi->send_wait; + DECLARE_WAITQUEUE(wait, current); + add_wait_queue(head, &wait); + current->state = TASK_INTERRUPTIBLE; + + while (line6->line6midi->num_active_send_urbs > 0) + if (signal_pending(current)) + break; + else + schedule(); + + current->state = TASK_RUNNING; + remove_wait_queue(head, &wait); +} + +static int line6_midi_input_open(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static int line6_midi_input_close(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, + int up) +{ + struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6; + + if (up) + line6->line6midi->substream_receive = substream; + else + line6->line6midi->substream_receive = 0; +} + +static struct snd_rawmidi_ops line6_midi_output_ops = { + .open = line6_midi_output_open, + .close = line6_midi_output_close, + .trigger = line6_midi_output_trigger, + .drain = line6_midi_output_drain, +}; + +static struct snd_rawmidi_ops line6_midi_input_ops = { + .open = line6_midi_input_open, + .close = line6_midi_input_close, + .trigger = line6_midi_input_trigger, +}; + +/* + Cleanup the Line6 MIDI device. +*/ +static void line6_cleanup_midi(struct snd_rawmidi *rmidi) +{ +} + +/* Create a MIDI device */ +static int snd_line6_new_midi(struct snd_line6_midi *line6midi) +{ + struct snd_rawmidi *rmidi; + int err; + + err = snd_rawmidi_new(line6midi->line6->card, "Line6 MIDI", 0, 1, 1, + &rmidi); + if (err < 0) + return err; + + rmidi->private_data = line6midi; + rmidi->private_free = line6_cleanup_midi; + strcpy(rmidi->name, line6midi->line6->properties->name); + + rmidi->info_flags = + SNDRV_RAWMIDI_INFO_OUTPUT | + SNDRV_RAWMIDI_INFO_INPUT | + SNDRV_RAWMIDI_INFO_DUPLEX; + + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, + &line6_midi_output_ops); + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, + &line6_midi_input_ops); + return 0; +} + +/* + "read" request on "midi_mask_transmit" special file. +*/ +static ssize_t midi_get_midi_mask_transmit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6 *line6 = usb_get_intfdata(interface); + return sprintf(buf, "%d\n", line6->line6midi->midi_mask_transmit); +} + +/* + "write" request on "midi_mask" special file. +*/ +static ssize_t midi_set_midi_mask_transmit(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6 *line6 = usb_get_intfdata(interface); + int value = simple_strtoul(buf, NULL, 10); + line6->line6midi->midi_mask_transmit = value; + return count; +} + +/* + "read" request on "midi_mask_receive" special file. +*/ +static ssize_t midi_get_midi_mask_receive(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6 *line6 = usb_get_intfdata(interface); + return sprintf(buf, "%d\n", line6->line6midi->midi_mask_receive); +} + +/* + "write" request on "midi_mask" special file. +*/ +static ssize_t midi_set_midi_mask_receive(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6 *line6 = usb_get_intfdata(interface); + int value = simple_strtoul(buf, NULL, 10); + line6->line6midi->midi_mask_receive = value; + return count; +} + +static DEVICE_ATTR(midi_mask_transmit, S_IWUGO | S_IRUGO, midi_get_midi_mask_transmit, midi_set_midi_mask_transmit); +static DEVICE_ATTR(midi_mask_receive, S_IWUGO | S_IRUGO, midi_get_midi_mask_receive, midi_set_midi_mask_receive); + +/* MIDI device destructor */ +static int snd_line6_midi_free(struct snd_device *device) +{ + struct snd_line6_midi *line6midi = device->device_data; + device_remove_file(line6midi->line6->ifcdev, &dev_attr_midi_mask_transmit); + device_remove_file(line6midi->line6->ifcdev, &dev_attr_midi_mask_receive); + midibuf_destroy(&line6midi->midibuf_in); + midibuf_destroy(&line6midi->midibuf_out); + return 0; +} + +/* + Initialize the Line6 MIDI subsystem. +*/ +int line6_init_midi(struct usb_line6 *line6) +{ + static struct snd_device_ops midi_ops = { + .dev_free = snd_line6_midi_free, + }; + + int err; + struct snd_line6_midi *line6midi; + + if (!(line6->properties->capabilities & LINE6_BIT_CONTROL)) + return 0; /* skip MIDI initialization and report success */ + + line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL); + + if (line6midi == NULL) + return -ENOMEM; + + err = midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); + if (err < 0) + return err; + + err = midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); + if (err < 0) + return err; + + line6midi->line6 = line6; + line6midi->midi_mask_transmit = 1; + line6midi->midi_mask_receive = 4; + line6->line6midi = line6midi; + + err = snd_device_new(line6->card, SNDRV_DEV_RAWMIDI, line6midi, + &midi_ops); + if (err < 0) + return err; + + snd_card_set_dev(line6->card, line6->ifcdev); + + err = snd_line6_new_midi(line6midi); + if (err < 0) + return err; + + err = device_create_file(line6->ifcdev, &dev_attr_midi_mask_transmit); + if (err < 0) + return err; + + err = device_create_file(line6->ifcdev, &dev_attr_midi_mask_receive); + if (err < 0) + return err; + + init_waitqueue_head(&line6midi->send_wait); + spin_lock_init(&line6midi->send_urb_lock); + spin_lock_init(&line6midi->midi_transmit_lock); + return 0; +} diff --git a/drivers/staging/line6/midi.h b/drivers/staging/line6/midi.h new file mode 100644 index 000000000000..c69fd118957b --- /dev/null +++ b/drivers/staging/line6/midi.h @@ -0,0 +1,87 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef MIDI_H +#define MIDI_H + + +#include + +#include "midibuf.h" + + +#define MIDI_BUFFER_SIZE 1024 + + +struct snd_line6_midi { + /** + Pointer back to the Line6 driver data structure. + */ + struct usb_line6 *line6; + + /** + MIDI substream for receiving (or NULL if not active). + */ + struct snd_rawmidi_substream *substream_receive; + + /** + MIDI substream for transmitting (or NULL if not active). + */ + struct snd_rawmidi_substream *substream_transmit; + + /** + Number of currently active MIDI send URBs. + */ + int num_active_send_urbs; + + /** + Spin lock to protect updates of send_urb. + */ + spinlock_t send_urb_lock; + + /** + Spin lock to protect MIDI buffer handling. + */ + spinlock_t midi_transmit_lock; + + /** + Wait queue for MIDI transmission. + */ + wait_queue_head_t send_wait; + + /** + Bit mask for output MIDI channels. + */ + int midi_mask_transmit; + + /** + Bit mask for input MIDI channels. + */ + int midi_mask_receive; + + /** + Buffer for incoming MIDI stream. + */ + struct MidiBuffer midibuf_in; + + /** + Buffer for outgoing MIDI stream. + */ + struct MidiBuffer midibuf_out; +}; + + +extern int line6_init_midi(struct usb_line6 *line6); +extern void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, + int length); + + +#endif diff --git a/drivers/staging/line6/midibuf.c b/drivers/staging/line6/midibuf.c new file mode 100644 index 000000000000..ab0a5f30fbca --- /dev/null +++ b/drivers/staging/line6/midibuf.c @@ -0,0 +1,262 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "config.h" + +#include + +#include "midibuf.h" + + +static int midibuf_message_length(unsigned char code) +{ + if (code < 0x80) + return -1; + else if (code < 0xf0) { + static const int length[] = { 3, 3, 3, 3, 2, 2, 3 }; + return length[(code >> 4) - 8]; + } else { + /* + Note that according to the MIDI specification 0xf2 is + the "Song Position Pointer", but this is used by Line6 + to send sysex messages to the host. + */ + static const int length[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1, + 1, 1, 1, -1, 1, 1 }; + return length[code & 0x0f]; + } +} + +void midibuf_reset(struct MidiBuffer *this) +{ + this->pos_read = this->pos_write = this->full = 0; + this->command_prev = -1; +} + +int midibuf_init(struct MidiBuffer *this, int size, int split) +{ + this->buf = kmalloc(size, GFP_KERNEL); + + if (this->buf == NULL) + return -ENOMEM; + + this->size = size; + this->split = split; + midibuf_reset(this); + return 0; +} + +void midibuf_status(struct MidiBuffer *this) +{ + printk(KERN_DEBUG "midibuf size=%d split=%d pos_read=%d pos_write=%d " + "full=%d command_prev=%02x\n", this->size, this->split, + this->pos_read, this->pos_write, this->full, this->command_prev); +} + +static int midibuf_is_empty(struct MidiBuffer *this) +{ + return (this->pos_read == this->pos_write) && !this->full; +} + +static int midibuf_is_full(struct MidiBuffer *this) +{ + return this->full; +} + +int midibuf_bytes_free(struct MidiBuffer *this) +{ + return + midibuf_is_full(this) ? + 0 : + (this->pos_read - this->pos_write + this->size - 1) % this->size + 1; +} + +int midibuf_bytes_used(struct MidiBuffer *this) +{ + return + midibuf_is_empty(this) ? + 0 : + (this->pos_write - this->pos_read + this->size - 1) % this->size + 1; +} + +int midibuf_write(struct MidiBuffer *this, unsigned char *data, int length) +{ + int bytes_free; + int length1, length2; + int skip_active_sense = 0; + + if (midibuf_is_full(this) || (length <= 0)) + return 0; + + /* skip trailing active sense */ + if (data[length - 1] == 0xfe) { + --length; + skip_active_sense = 1; + } + + bytes_free = midibuf_bytes_free(this); + + if (length > bytes_free) + length = bytes_free; + + if (length > 0) { + length1 = this->size - this->pos_write; + + if (length < length1) { + /* no buffer wraparound */ + memcpy(this->buf + this->pos_write, data, length); + this->pos_write += length; + } else { + /* buffer wraparound */ + length2 = length - length1; + memcpy(this->buf + this->pos_write, data, length1); + memcpy(this->buf, data + length1, length2); + this->pos_write = length2; + } + + if (this->pos_write == this->pos_read) + this->full = 1; + } + + return length + skip_active_sense; +} + +int midibuf_read(struct MidiBuffer *this, unsigned char *data, int length) +{ + int bytes_used; + int length1, length2; + int command; + int midi_length; + int repeat = 0; + int i; + + /* we need to be able to store at least a 3 byte MIDI message */ + if (length < 3) + return -EINVAL; + + if (midibuf_is_empty(this)) + return 0; + + bytes_used = midibuf_bytes_used(this); + + if (length > bytes_used) + length = bytes_used; + + length1 = this->size - this->pos_read; + + /* check MIDI command length */ + command = this->buf[this->pos_read]; + + if (command & 0x80) { + midi_length = midibuf_message_length(command); + this->command_prev = command; + } else { + if (this->command_prev > 0) { + int midi_length_prev = midibuf_message_length(this->command_prev); + + if (midi_length_prev > 0) { + midi_length = midi_length_prev - 1; + repeat = 1; + } else + midi_length = -1; + } else + midi_length = -1; + } + + if (midi_length < 0) { + /* search for end of message */ + if (length < length1) { + /* no buffer wraparound */ + for (i = 1; i < length; ++i) + if (this->buf[this->pos_read + i] & 0x80) + break; + + midi_length = i; + } else { + /* buffer wraparound */ + length2 = length - length1; + + for (i = 1; i < length1; ++i) + if (this->buf[this->pos_read + i] & 0x80) + break; + + if (i < length1) + midi_length = i; + else { + for (i = 0; i < length2; ++i) + if (this->buf[i] & 0x80) + break; + + midi_length = length1 + i; + } + } + + if (midi_length == length) + midi_length = -1; /* end of message not found */ + } + + if (midi_length < 0) { + if (!this->split) + return 0; /* command is not yet complete */ + } else { + if (length < midi_length) + return 0; /* command is not yet complete */ + + length = midi_length; + } + + if (length < length1) { + /* no buffer wraparound */ + memcpy(data + repeat, this->buf + this->pos_read, length); + this->pos_read += length; + } else { + /* buffer wraparound */ + length2 = length - length1; + memcpy(data + repeat, this->buf + this->pos_read, length1); + memcpy(data + repeat + length1, this->buf, length2); + this->pos_read = length2; + } + + if (repeat) + data[0] = this->command_prev; + + this->full = 0; + return length + repeat; +} + +int midibuf_ignore(struct MidiBuffer *this, int length) +{ + int bytes_used = midibuf_bytes_used(this); + + if (length > bytes_used) + length = bytes_used; + + this->pos_read = (this->pos_read + length) % this->size; + this->full = 0; + return length; +} + +int midibuf_skip_message(struct MidiBuffer *this, unsigned short mask) +{ + int cmd = this->command_prev; + + if ((cmd >= 0x80) && (cmd < 0xf0)) + if ((mask & (1 << (cmd & 0x0f))) == 0) + return 1; + + return 0; +} + +void midibuf_destroy(struct MidiBuffer *this) +{ + kfree(this->buf); + this->buf = NULL; +} diff --git a/drivers/staging/line6/midibuf.h b/drivers/staging/line6/midibuf.h new file mode 100644 index 000000000000..9877581bcd9a --- /dev/null +++ b/drivers/staging/line6/midibuf.h @@ -0,0 +1,39 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef MIDIBUF_H +#define MIDIBUF_H + + +struct MidiBuffer { + unsigned char *buf; + int size; + int split; + int pos_read, pos_write; + int full; + int command_prev; +}; + + +extern int midibuf_bytes_used(struct MidiBuffer *mb); +extern int midibuf_bytes_free(struct MidiBuffer *mb); +extern void midibuf_destroy(struct MidiBuffer *mb); +extern int midibuf_ignore(struct MidiBuffer *mb, int length); +extern int midibuf_init(struct MidiBuffer *mb, int size, int split); +extern int midibuf_read(struct MidiBuffer *mb, unsigned char *data, int length); +extern void midibuf_reset(struct MidiBuffer *mb); +extern int midibuf_skip_message(struct MidiBuffer *mb, unsigned short mask); +extern void midibuf_status(struct MidiBuffer *mb); +extern int midibuf_write(struct MidiBuffer *mb, unsigned char *data, + int length); + + +#endif diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c new file mode 100644 index 000000000000..fc4113f33159 --- /dev/null +++ b/drivers/staging/line6/pcm.c @@ -0,0 +1,301 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" + +#include +#include +#include +#include + +#include "audio.h" +#include "capture.h" +#include "playback.h" +#include "pod.h" + + +/* trigger callback */ +int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + struct snd_pcm_substream *s; + int err; + unsigned long flags; + + spin_lock_irqsave(&line6pcm->lock_trigger, flags); + clear_bit(BIT_PREPARED, &line6pcm->flags); + + snd_pcm_group_for_each_entry(s, substream) { + switch (s->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + err = snd_line6_playback_trigger(s, cmd); + + if (err < 0) { + spin_unlock_irqrestore(&line6pcm->lock_trigger, + flags); + return err; + } + + break; + + case SNDRV_PCM_STREAM_CAPTURE: + err = snd_line6_capture_trigger(s, cmd); + + if (err < 0) { + spin_unlock_irqrestore(&line6pcm->lock_trigger, + flags); + return err; + } + + break; + + default: + dev_err(s2m(substream), "Unknown stream direction %d\n", + s->stream); + } + } + + spin_unlock_irqrestore(&line6pcm->lock_trigger, flags); + return 0; +} + +/* control info callback */ +static int snd_line6_control_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 256; + return 0; +} + +/* control get callback */ +static int snd_line6_control_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int i; + struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); + + for (i = 2; i--;) + ucontrol->value.integer.value[i] = line6pcm->volume[i]; + + return 0; +} + +/* control put callback */ +static int snd_line6_control_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int i, changed = 0; + struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); + + for (i = 2; i--;) + if (line6pcm->volume[i] != ucontrol->value.integer.value[i]) { + line6pcm->volume[i] = ucontrol->value.integer.value[i]; + changed = 1; + } + + return changed; +} + +/* control definition */ +static struct snd_kcontrol_new line6_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "PCM Playback Volume", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_line6_control_info, + .get = snd_line6_control_get, + .put = snd_line6_control_put +}; + +/* + Cleanup the PCM device. +*/ +static void line6_cleanup_pcm(struct snd_pcm *pcm) +{ + int i; + struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); + + for (i = LINE6_ISO_BUFFERS; i--;) { + if (line6pcm->urb_audio_out[i]) { + usb_kill_urb(line6pcm->urb_audio_out[i]); + usb_free_urb(line6pcm->urb_audio_out[i]); + } + if (line6pcm->urb_audio_in[i]) { + usb_kill_urb(line6pcm->urb_audio_in[i]); + usb_free_urb(line6pcm->urb_audio_in[i]); + } + } +} + +/* create a PCM device */ +static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm) +{ + struct snd_pcm *pcm; + int err; + + err = snd_pcm_new(line6pcm->line6->card, + (char *)line6pcm->line6->properties->name, + 0, 1, 1, &pcm); + if (err < 0) + return err; + + pcm->private_data = line6pcm; + pcm->private_free = line6_cleanup_pcm; + line6pcm->pcm = pcm; + strcpy(pcm->name, line6pcm->line6->properties->name); + + /* set operators */ + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_line6_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops); + + /* pre-allocation of buffers */ + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, + snd_dma_continuous_data(GFP_KERNEL), + 64 * 1024, 128 * 1024); + + return 0; +} + +/* PCM device destructor */ +static int snd_line6_pcm_free(struct snd_device *device) +{ + return 0; +} + +/* + Create and register the PCM device and mixer entries. + Create URBs for playback and capture. +*/ +int line6_init_pcm(struct usb_line6 *line6, + struct line6_pcm_properties *properties) +{ + static struct snd_device_ops pcm_ops = { + .dev_free = snd_line6_pcm_free, + }; + + int err; + int ep_read = 0, ep_write = 0; + struct snd_line6_pcm *line6pcm; + + if (!(line6->properties->capabilities & LINE6_BIT_PCM)) + return 0; /* skip PCM initialization and report success */ + + /* initialize PCM subsystem based on product id: */ + switch (line6->product) { + case LINE6_DEVID_BASSPODXT: + case LINE6_DEVID_BASSPODXTLIVE: + case LINE6_DEVID_BASSPODXTPRO: + case LINE6_DEVID_PODXT: + case LINE6_DEVID_PODXTLIVE: + case LINE6_DEVID_PODXTPRO: + ep_read = 0x82; + ep_write = 0x01; + break; + + case LINE6_DEVID_PODX3: + case LINE6_DEVID_PODX3LIVE: + ep_read = 0x86; + ep_write = 0x02; + break; + + case LINE6_DEVID_POCKETPOD: + ep_read = 0x82; + ep_write = 0x02; + break; + + case LINE6_DEVID_GUITARPORT: + case LINE6_DEVID_TONEPORT_GX: + ep_read = 0x82; + ep_write = 0x01; + break; + + case LINE6_DEVID_TONEPORT_UX1: + ep_read = 0x00; + ep_write = 0x00; + break; + + case LINE6_DEVID_TONEPORT_UX2: + ep_read = 0x87; + ep_write = 0x00; + break; + + default: + MISSING_CASE; + } + + line6pcm = kzalloc(sizeof(struct snd_line6_pcm), GFP_KERNEL); + + if (line6pcm == NULL) + return -ENOMEM; + + line6pcm->volume[0] = line6pcm->volume[1] = 128; + line6pcm->line6 = line6; + line6pcm->ep_audio_read = ep_read; + line6pcm->ep_audio_write = ep_write; + line6pcm->max_packet_size = usb_maxpacket(line6->usbdev, + usb_rcvintpipe(line6->usbdev, + ep_read), + 0); + line6pcm->properties = properties; + line6->line6pcm = line6pcm; + + /* PCM device: */ + err = snd_device_new(line6->card, SNDRV_DEV_PCM, line6, &pcm_ops); + if (err < 0) + return err; + + snd_card_set_dev(line6->card, line6->ifcdev); + + err = snd_line6_new_pcm(line6pcm); + if (err < 0) + return err; + + spin_lock_init(&line6pcm->lock_audio_out); + spin_lock_init(&line6pcm->lock_audio_in); + spin_lock_init(&line6pcm->lock_trigger); + + err = create_audio_out_urbs(line6pcm); + if (err < 0) + return err; + + err = create_audio_in_urbs(line6pcm); + if (err < 0) + return err; + + /* mixer: */ + err = snd_ctl_add(line6->card, snd_ctl_new1(&line6_control, line6pcm)); + if (err < 0) + return err; + + return 0; +} + +/* prepare pcm callback */ +int snd_line6_prepare(struct snd_pcm_substream *substream) +{ + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + if (!test_and_set_bit(BIT_PREPARED, &line6pcm->flags)) { + unlink_wait_clear_audio_out_urbs(line6pcm); + line6pcm->pos_out = 0; + line6pcm->pos_out_done = 0; + + unlink_wait_clear_audio_in_urbs(line6pcm); + line6pcm->bytes_out = 0; + line6pcm->pos_in_done = 0; + line6pcm->bytes_in = 0; + } + + return 0; +} diff --git a/drivers/staging/line6/pcm.h b/drivers/staging/line6/pcm.h new file mode 100644 index 000000000000..53db217cd42d --- /dev/null +++ b/drivers/staging/line6/pcm.h @@ -0,0 +1,222 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +/* + PCM interface to POD series devices. +*/ + +#ifndef PCM_H +#define PCM_H + + +#include + +#include "driver.h" +#include "usbdefs.h" + + +/* number of URBs */ +#define LINE6_ISO_BUFFERS 8 + +/* number of USB frames per URB */ +#define LINE6_ISO_PACKETS 2 + +/* in a "full speed" device (such as the PODxt Pro) this means 1ms */ +#define LINE6_ISO_INTERVAL 1 + +/* this should be queried dynamically from the USB interface! */ +#define LINE6_ISO_PACKET_SIZE_MAX 252 + + +/* + Extract the messaging device from the substream instance +*/ +#define s2m(s) (((struct snd_line6_pcm *) \ + snd_pcm_substream_chip(s))->line6->ifcdev) + + +enum { + BIT_RUNNING_PLAYBACK, + BIT_RUNNING_CAPTURE, + BIT_PAUSE_PLAYBACK, + BIT_PREPARED +}; + +struct line6_pcm_properties { + struct snd_pcm_hardware snd_line6_playback_hw, snd_line6_capture_hw; + struct snd_pcm_hw_constraint_ratdens snd_line6_rates; + int bytes_per_frame; +}; + +struct snd_line6_pcm { + /** + Pointer back to the Line6 driver data structure. + */ + struct usb_line6 *line6; + + /** + Properties. + */ + struct line6_pcm_properties *properties; + + /** + ALSA pcm stream + */ + struct snd_pcm *pcm; + + /** + URBs for audio playback. + */ + struct urb *urb_audio_out[LINE6_ISO_BUFFERS]; + + /** + URBs for audio capture. + */ + struct urb *urb_audio_in[LINE6_ISO_BUFFERS]; + + /** + Temporary buffer to hold data when playback buffer wraps. + */ + unsigned char *wrap_out; + + /** + Temporary buffer for capture. + Since the packet size is not known in advance, this buffer is + large enough to store maximum size packets. + */ + unsigned char *buffer_in; + + /** + Free frame position in the playback buffer. + */ + snd_pcm_uframes_t pos_out; + + /** + Count processed bytes for playback. + This is modulo period size (to determine when a period is + finished). + */ + unsigned bytes_out; + + /** + Counter to create desired playback sample rate. + */ + unsigned count_out; + + /** + Playback period size in bytes + */ + unsigned period_out; + + /** + Processed frame position in the playback buffer. + The contents of the output ring buffer have been consumed by + the USB subsystem (i.e., sent to the USB device) up to this + position. + */ + snd_pcm_uframes_t pos_out_done; + + /** + Count processed bytes for capture. + This is modulo period size (to determine when a period is + finished). + */ + unsigned bytes_in; + + /** + Counter to create desired capture sample rate. + */ + unsigned count_in; + + /** + Capture period size in bytes + */ + unsigned period_in; + + /** + Processed frame position in the capture buffer. + The contents of the output ring buffer have been consumed by + the USB subsystem (i.e., sent to the USB device) up to this + position. + */ + snd_pcm_uframes_t pos_in_done; + + /** + Bit mask of active playback URBs. + */ + unsigned long active_urb_out; + + /** + Maximum size of USB packet. + */ + int max_packet_size; + + /** + USB endpoint for listening to audio data. + */ + int ep_audio_read; + + /** + USB endpoint for writing audio data. + */ + int ep_audio_write; + + /** + Bit mask of active capture URBs. + */ + unsigned long active_urb_in; + + /** + Bit mask of playback URBs currently being unlinked. + */ + unsigned long unlink_urb_out; + + /** + Bit mask of capture URBs currently being unlinked. + */ + unsigned long unlink_urb_in; + + /** + Spin lock to protect updates of the playback buffer positions (not + contents!) + */ + spinlock_t lock_audio_out; + + /** + Spin lock to protect updates of the capture buffer positions (not + contents!) + */ + spinlock_t lock_audio_in; + + /** + Spin lock to protect trigger. + */ + spinlock_t lock_trigger; + + /** + PCM playback volume (left and right). + */ + int volume[2]; + + /** + Several status bits (see BIT_*). + */ + unsigned long flags; +}; + + +extern int line6_init_pcm(struct usb_line6 *line6, + struct line6_pcm_properties *properties); +extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd); +extern int snd_line6_prepare(struct snd_pcm_substream *substream); + + +#endif diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c new file mode 100644 index 000000000000..acb06126a6a5 --- /dev/null +++ b/drivers/staging/line6/playback.c @@ -0,0 +1,427 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" + +#include +#include +#include + +#include "audio.h" +#include "pcm.h" +#include "pod.h" +#include "playback.h" + + +/* + Software stereo volume control. +*/ +static void change_volume(struct urb *urb_out, int volume[], + int bytes_per_frame) +{ + int chn = 0; + + if (volume[0] == 256 && volume[1] == 256) + return; /* maximum volume - no change */ + + if (bytes_per_frame == 4) { + short *p, *buf_end; + p = (short *)urb_out->transfer_buffer; + buf_end = p + urb_out->transfer_buffer_length / sizeof(*p); + + for (; p < buf_end; ++p) { + *p = (*p * volume[chn & 1]) >> 8; + ++chn; + } + } else if (bytes_per_frame == 6) { + unsigned char *p, *buf_end; + p = (unsigned char *)urb_out->transfer_buffer; + buf_end = p + urb_out->transfer_buffer_length; + + for (; p < buf_end; p += 3) { + int val; + val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16); + val = (val * volume[chn & 1]) >> 8; + p[0] = val; + p[1] = val >> 8; + p[2] = val >> 16; + ++chn; + } + } +} + +/* + Find a free URB, prepare audio data, and submit URB. +*/ +static int submit_audio_out_urb(struct snd_pcm_substream *substream) +{ + int index; + unsigned long flags; + int i, urb_size, urb_frames; + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + const int bytes_per_frame = line6pcm->properties->bytes_per_frame; + const int frame_increment = line6pcm->properties->snd_line6_rates.rats[0].num_min; + const int frame_factor = line6pcm->properties->snd_line6_rates.rats[0].den * (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL); + struct snd_pcm_runtime *runtime = substream->runtime; + struct urb *urb_out; + + spin_lock_irqsave(&line6pcm->lock_audio_out, flags); + index = find_first_zero_bit(&line6pcm->active_urb_out, LINE6_ISO_BUFFERS); + + if (index < 0 || index >= LINE6_ISO_BUFFERS) { + spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); + dev_err(s2m(substream), "no free URB found\n"); + return -EINVAL; + } + + urb_out = line6pcm->urb_audio_out[index]; + urb_size = 0; + + for (i = 0; i < LINE6_ISO_PACKETS; ++i) { + /* compute frame size for given sampling rate */ + int n, fs; + struct usb_iso_packet_descriptor *fout = &urb_out->iso_frame_desc[i]; + line6pcm->count_out += frame_increment; + n = line6pcm->count_out / frame_factor; + line6pcm->count_out -= n * frame_factor; + fs = n * bytes_per_frame; + fout->offset = urb_size; + fout->length = fs; + urb_size += fs; + } + + urb_frames = urb_size / bytes_per_frame; + + if (test_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags)) { + urb_out->transfer_buffer = line6pcm->wrap_out; + memset(line6pcm->wrap_out, 0, urb_size); + } else { + if (line6pcm->pos_out + urb_frames > runtime->buffer_size) { + /* + The transferred area goes over buffer boundary, + copy the data to the temp buffer. + */ + int len; + len = runtime->buffer_size - line6pcm->pos_out; + urb_out->transfer_buffer = line6pcm->wrap_out; + + if (len > 0) { + memcpy(line6pcm->wrap_out, runtime->dma_area + line6pcm->pos_out * bytes_per_frame, len * bytes_per_frame); + memcpy(line6pcm->wrap_out + len * bytes_per_frame, runtime->dma_area, (urb_frames - len) * bytes_per_frame); + } else + dev_err(s2m(substream), "driver bug: len = %d\n", len); /* this is somewhat paranoid */ + } else { + /* set the buffer pointer */ + urb_out->transfer_buffer = runtime->dma_area + line6pcm->pos_out * bytes_per_frame; + } + } + + if ((line6pcm->pos_out += urb_frames) >= runtime->buffer_size) + line6pcm->pos_out -= runtime->buffer_size; + + urb_out->transfer_buffer_length = urb_size; + urb_out->context = substream; + change_volume(urb_out, line6pcm->volume, bytes_per_frame); + +#if DO_DUMP_PCM_SEND + for (i = 0; i < LINE6_ISO_PACKETS; ++i) { + struct usb_iso_packet_descriptor *fout = &urb_out->iso_frame_desc[i]; + line6_write_hexdump(line6pcm->line6, 'P', urb_out->transfer_buffer + fout->offset, fout->length); + } +#endif + + if (usb_submit_urb(urb_out, GFP_ATOMIC) == 0) + set_bit(index, &line6pcm->active_urb_out); + else + dev_err(s2m(substream), "URB out #%d submission failed\n", index); + + spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); + return 0; +} + +/* + Submit all currently available playback URBs. +*/ +static int submit_audio_out_all_urbs(struct snd_pcm_substream *substream) +{ + int ret, i; + + for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + ret = submit_audio_out_urb(substream); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + Unlink all currently active playback URBs. +*/ +static void unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm) +{ + unsigned int i; + + for (i = LINE6_ISO_BUFFERS; i--;) { + if (test_bit(i, &line6pcm->active_urb_out)) { + if (!test_and_set_bit(i, &line6pcm->unlink_urb_out)) { + struct urb *u = line6pcm->urb_audio_out[i]; + usb_unlink_urb(u); + } + } + } +} + +/* + Wait until unlinking of all currently active playback URBs has been finished. +*/ +static void wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) +{ + int timeout = HZ; + unsigned int i; + int alive; + + do { + alive = 0; + for (i = LINE6_ISO_BUFFERS; i--;) { + if (test_bit(i, &line6pcm->active_urb_out)) + alive++; + } + if (!alive) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } while (--timeout > 0); + if (alive) + snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); + + line6pcm->active_urb_out = 0; + line6pcm->unlink_urb_out = 0; +} + +/* + Unlink all currently active playback URBs, and wait for finishing. +*/ +void unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) +{ + unlink_audio_out_urbs(line6pcm); + wait_clear_audio_out_urbs(line6pcm); +} + +/* + Callback for completed playback URB. +*/ +static void audio_out_callback(struct urb *urb) +{ + int i, index, length = 0, shutdown = 0; + unsigned long flags; + + struct snd_pcm_substream *substream = (struct snd_pcm_substream *)urb->context; + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + + /* find index of URB */ + for (index = LINE6_ISO_BUFFERS; index--;) + if (urb == line6pcm->urb_audio_out[index]) + break; + + if (index < 0) + return; /* URB has been unlinked asynchronously */ + + for (i = LINE6_ISO_PACKETS; i--;) + length += urb->iso_frame_desc[i].length; + + spin_lock_irqsave(&line6pcm->lock_audio_out, flags); + line6pcm->pos_out_done += length / line6pcm->properties->bytes_per_frame; + + if (line6pcm->pos_out_done >= runtime->buffer_size) + line6pcm->pos_out_done -= runtime->buffer_size; + + clear_bit(index, &line6pcm->active_urb_out); + + for (i = LINE6_ISO_PACKETS; i--;) + if (urb->iso_frame_desc[i].status == -ESHUTDOWN) { + shutdown = 1; + break; + } + + if (test_bit(index, &line6pcm->unlink_urb_out)) + shutdown = 1; + + spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); + + if (!shutdown) { + submit_audio_out_urb(substream); + + if ((line6pcm->bytes_out += length) >= line6pcm->period_out) { + line6pcm->bytes_out -= line6pcm->period_out; + snd_pcm_period_elapsed(substream); + } + } +} + +/* open playback callback */ +static int snd_line6_playback_open(struct snd_pcm_substream *substream) +{ + int err; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + (&line6pcm->properties->snd_line6_rates)); + if (err < 0) + return err; + + runtime->hw = line6pcm->properties->snd_line6_playback_hw; + return 0; +} + +/* close playback callback */ +static int snd_line6_playback_close(struct snd_pcm_substream *substream) +{ + return 0; +} + +/* hw_params playback callback */ +static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) +{ + int ret; + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + /* -- Florian Demski [FD] */ + /* don't ask me why, but this fixes the bug on my machine */ + if (line6pcm == NULL) { + if (substream->pcm == NULL) + return -ENOMEM; + if (substream->pcm->private_data == NULL) + return -ENOMEM; + substream->private_data = substream->pcm->private_data; + line6pcm = snd_pcm_substream_chip(substream); + } + /* -- [FD] end */ + + ret = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (ret < 0) + return ret; + + line6pcm->period_out = params_period_bytes(hw_params); + line6pcm->wrap_out = kmalloc(2 * LINE6_ISO_PACKET_SIZE_MAX, GFP_KERNEL); + + if (!line6pcm->wrap_out) { + dev_err(s2m(substream), "cannot malloc wrap_out\n"); + return -ENOMEM; + } + + return 0; +} + +/* hw_free playback callback */ +static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + unlink_wait_clear_audio_out_urbs(line6pcm); + + kfree(line6pcm->wrap_out); + line6pcm->wrap_out = NULL; + + return snd_pcm_lib_free_pages(substream); +} + +/* trigger playback callback */ +int snd_line6_playback_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + int err; + line6pcm->count_out = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + if (!test_and_set_bit(BIT_RUNNING_PLAYBACK, &line6pcm->flags)) { + err = submit_audio_out_all_urbs(substream); + + if (err < 0) { + clear_bit(BIT_RUNNING_PLAYBACK, &line6pcm->flags); + return err; + } + } + + break; + + case SNDRV_PCM_TRIGGER_STOP: + if (test_and_clear_bit(BIT_RUNNING_PLAYBACK, &line6pcm->flags)) + unlink_audio_out_urbs(line6pcm); + + break; + + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + set_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags); + break; + + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + clear_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags); + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* playback pointer callback */ +static snd_pcm_uframes_t +snd_line6_playback_pointer(struct snd_pcm_substream *substream) +{ + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + return line6pcm->pos_out_done; +} + +/* playback operators */ +struct snd_pcm_ops snd_line6_playback_ops = { + .open = snd_line6_playback_open, + .close = snd_line6_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_line6_playback_hw_params, + .hw_free = snd_line6_playback_hw_free, + .prepare = snd_line6_prepare, + .trigger = snd_line6_trigger, + .pointer = snd_line6_playback_pointer, +}; + +int create_audio_out_urbs(struct snd_line6_pcm *line6pcm) +{ + int i; + + /* create audio URBs and fill in constant values: */ + for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + struct urb *urb; + + /* URB for audio out: */ + urb = line6pcm->urb_audio_out[i] = usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); + + if (urb == NULL) { + dev_err(line6pcm->line6->ifcdev, "Out of memory\n"); + return -ENOMEM; + } + + urb->dev = line6pcm->line6->usbdev; + urb->pipe = usb_sndisocpipe(line6pcm->line6->usbdev, line6pcm->ep_audio_write & USB_ENDPOINT_NUMBER_MASK); + urb->transfer_flags = URB_ISO_ASAP; + urb->start_frame = -1; + urb->number_of_packets = LINE6_ISO_PACKETS; + urb->interval = LINE6_ISO_INTERVAL; + urb->error_count = 0; + urb->complete = audio_out_callback; + } + + return 0; +} diff --git a/drivers/staging/line6/playback.h b/drivers/staging/line6/playback.h new file mode 100644 index 000000000000..db1e48b3596e --- /dev/null +++ b/drivers/staging/line6/playback.h @@ -0,0 +1,30 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef PLAYBACK_H +#define PLAYBACK_H + + +#include "driver.h" + +#include + + +extern struct snd_pcm_ops snd_line6_playback_ops; + + +extern int create_audio_out_urbs(struct snd_line6_pcm *line6pcm); +extern int snd_line6_playback_trigger(struct snd_pcm_substream *substream, + int cmd); +extern void unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm); + + +#endif diff --git a/drivers/staging/line6/pod.c b/drivers/staging/line6/pod.c new file mode 100644 index 000000000000..fa5caa245d85 --- /dev/null +++ b/drivers/staging/line6/pod.c @@ -0,0 +1,1151 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" + +#include "audio.h" +#include "capture.h" +#include "control.h" +#include "playback.h" +#include "pod.h" + + +#define POD_SYSEX_CODE 3 +#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ + + +enum { + POD_SYSEX_CLIP = 0x0f, + POD_SYSEX_SAVE = 0x24, + POD_SYSEX_SYSTEM = 0x56, + POD_SYSEX_SYSTEMREQ = 0x57, + /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */ + POD_SYSEX_STORE = 0x71, + POD_SYSEX_FINISH = 0x72, + POD_SYSEX_DUMPMEM = 0x73, + POD_SYSEX_DUMP = 0x74, + POD_SYSEX_DUMPREQ = 0x75 + /* POD_SYSEX_DUMPMEM2 = 0x76 */ /* dumps entire internal memory of PODxt Pro */ +}; + +enum { + POD_monitor_level = 0x04, + POD_routing = 0x05, + POD_tuner_mute = 0x13, + POD_tuner_freq = 0x15, + POD_tuner_note = 0x16, + POD_tuner_pitch = 0x17, + POD_system_invalid = 0x7fff +}; + +enum { + POD_DUMP_MEMORY = 2 +}; + +enum { + POD_BUSY_READ, + POD_BUSY_WRITE, + POD_CHANNEL_DIRTY, + POD_SAVE_PRESSED, + POD_BUSY_MIDISEND +}; + + +static struct snd_ratden pod_ratden = { + .num_min = 78125, + .num_max = 78125, + .num_step = 1, + .den = 2 +}; + +static struct line6_pcm_properties pod_pcm_properties = { + .snd_line6_playback_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = 39062, + .rate_max = 39063, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = LINE6_ISO_PACKET_SIZE_MAX * POD_BYTES_PER_FRAME, /* at least one URB must fit into one period */ + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024 + }, + .snd_line6_capture_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = 39062, + .rate_max = 39063, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = LINE6_ISO_PACKET_SIZE_MAX * POD_BYTES_PER_FRAME, /* at least one URB must fit into one period */ + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024 + }, + .snd_line6_rates = { + .nrats = 1, + .rats = &pod_ratden + }, + .bytes_per_frame = POD_BYTES_PER_FRAME +}; + +static const char pod_request_version[] = { 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7 }; +static const char pod_request_channel[] = { 0xf0, 0x00, 0x01, 0x0c, 0x03, 0x75, 0xf7 }; +static const char pod_version_header[] = { 0xf2, 0x7e, 0x7f, 0x06, 0x02 }; + + +/* + Mark all parameters as dirty and notify waiting processes. +*/ +static void pod_mark_batch_all_dirty(struct usb_line6_pod *pod) +{ + int i; + + for (i = POD_CONTROL_SIZE; i--;) + set_bit(i, pod->param_dirty); +} + +/* + Send an asynchronous request for the POD firmware version and device ID. +*/ +static int pod_version_request_async(struct usb_line6_pod *pod) +{ + return line6_send_raw_message_async(&pod->line6, pod->buffer_versionreq, sizeof(pod_request_version)); +} + +static void pod_create_files_work(struct work_struct *work) +{ + struct usb_line6_pod *pod = container_of(work, struct usb_line6_pod, create_files_work); + + pod_create_files(pod->firmware_version, pod->line6.properties->device_bit, pod->line6.ifcdev); +} + +static void pod_startup_timeout(unsigned long arg) +{ + enum { + REQUEST_NONE, + REQUEST_DUMP, + REQUEST_VERSION + }; + + int request = REQUEST_NONE; + struct usb_line6_pod *pod = (struct usb_line6_pod *)arg; + + if (pod->dumpreq.ok) { + if (!pod->versionreq_ok) + request = REQUEST_VERSION; + } else { + if (pod->versionreq_ok) + request = REQUEST_DUMP; + else if (pod->startup_count++ & 1) + request = REQUEST_DUMP; + else + request = REQUEST_VERSION; + } + + switch (request) { + case REQUEST_DUMP: + line6_dump_request_async(&pod->dumpreq, &pod->line6, 0); + break; + + case REQUEST_VERSION: + pod_version_request_async(pod); + break; + + default: + return; + } + + line6_startup_delayed(&pod->dumpreq, 1, pod_startup_timeout, pod); +} + +static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, int size) +{ + return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code, size); +} + +/* + Send channel dump data to the PODxt Pro. +*/ +static void pod_dump(struct usb_line6_pod *pod, const unsigned char *data) +{ + int size = 1 + sizeof(pod->prog_data); + char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMP, size); + if (!sysex) + return; + /* Don't know what this is good for, but PODxt Pro transmits it, so we + * also do... */ + sysex[SYSEX_DATA_OFS] = 5; + memcpy(sysex + SYSEX_DATA_OFS + 1, data, sizeof(pod->prog_data)); + line6_send_sysex_message(&pod->line6, sysex, size); + memcpy(&pod->prog_data, data, sizeof(pod->prog_data)); + pod_mark_batch_all_dirty(pod); + kfree(sysex); +} + +/* + Store parameter value in driver memory and mark it as dirty. +*/ +static void pod_store_parameter(struct usb_line6_pod *pod, int param, int value) +{ + pod->prog_data.control[param] = value; + set_bit(param, pod->param_dirty); + pod->dirty = 1; +} + +/* + Handle SAVE button +*/ +static void pod_save_button_pressed(struct usb_line6_pod *pod, int type, int index) +{ + pod->dirty = 0; + set_bit(POD_SAVE_PRESSED, &pod->atomic_flags); +} + +/* + Process a completely received message. +*/ +void pod_process_message(struct usb_line6_pod *pod) +{ + const unsigned char *buf = pod->line6.buffer_message; + + /* filter messages by type */ + switch (buf[0] & 0xf0) { + case LINE6_PARAM_CHANGE: + case LINE6_PROGRAM_CHANGE: + case LINE6_SYSEX_BEGIN: + break; /* handle these further down */ + + default: + return; /* ignore all others */ + } + + /* process all remaining messages */ + switch (buf[0]) { + case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE: + pod_store_parameter(pod, buf[1], buf[2]); + /* intentionally no break here! */ + + case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST: + if ((buf[1] == POD_amp_model_setup) || + (buf[1] == POD_effect_setup)) + /* these also affect other settings */ + line6_dump_request_async(&pod->dumpreq, &pod->line6, 0); + + break; + + case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE: + case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST: + pod->channel_num = buf[1]; + pod->dirty = 0; + set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags); + line6_dump_request_async(&pod->dumpreq, &pod->line6, 0); + break; + + case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE: + case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN: + if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) { + switch (buf[5]) { + case POD_SYSEX_DUMP: + if (pod->line6.message_length == sizeof(pod->prog_data) + 7) { + switch (pod->dumpreq.in_progress) { + case LINE6_DUMP_CURRENT: + memcpy(&pod->prog_data, buf + 7, sizeof(pod->prog_data)); + pod_mark_batch_all_dirty(pod); + pod->dumpreq.ok = 1; + break; + + case POD_DUMP_MEMORY: + memcpy(&pod->prog_data_buf, buf + 7, sizeof(pod->prog_data_buf)); + break; + + default: + DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown dump code %02X\n", pod->dumpreq.in_progress)); + } + + line6_dump_finished(&pod->dumpreq); + } else + DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "wrong size of channel dump message (%d instead of %d)\n", + pod->line6.message_length, (int)sizeof(pod->prog_data) + 7)); + + break; + + case POD_SYSEX_SYSTEM: { + short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) | ((int)buf[9] << 4) | (int)buf[10]; + +#define PROCESS_SYSTEM_PARAM(x) \ + case POD_ ## x: \ + pod->x.value = value; \ + wake_up_interruptible(&pod->x.wait); \ + break; + + switch (buf[6]) { + PROCESS_SYSTEM_PARAM(monitor_level); + PROCESS_SYSTEM_PARAM(routing); + PROCESS_SYSTEM_PARAM(tuner_mute); + PROCESS_SYSTEM_PARAM(tuner_freq); + PROCESS_SYSTEM_PARAM(tuner_note); + PROCESS_SYSTEM_PARAM(tuner_pitch); + +#undef PROCESS_SYSTEM_PARAM + + default: + DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown tuner/system response %02X\n", buf[6])); + } + + break; + } + + case POD_SYSEX_FINISH: + /* do we need to respond to this? */ + break; + + case POD_SYSEX_SAVE: + pod_save_button_pressed(pod, buf[6], buf[7]); + break; + + case POD_SYSEX_CLIP: + DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "audio clipped\n")); + pod->clipping.value = 1; + wake_up_interruptible(&pod->clipping.wait); + break; + + case POD_SYSEX_STORE: + DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "message %02X not yet implemented\n", buf[5])); + break; + + default: + DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex message %02X\n", buf[5])); + } + } else if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) { + if (pod->versionreq_ok == 0) { + pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15]; + pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)buf[10]; + pod->versionreq_ok = 1; + + /* Now we know the firmware version, so we schedule a bottom half + handler to create the special files: */ + INIT_WORK(&pod->create_files_work, pod_create_files_work); + queue_work(line6_workqueue, &pod->create_files_work); + } else + DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "multiple firmware version message\n")); + } else + DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex header\n")); + + break; + + case LINE6_SYSEX_END: + break; + + default: + DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "POD: unknown message %02X\n", buf[0])); + } +} + +/* + Detect some cases that require a channel dump after sending a command to the + device. Important notes: + *) The actual dump request can not be sent here since we are not allowed to + wait for the completion of the first message in this context, and sending + the dump request before completion of the previous message leaves the POD + in an undefined state. The dump request will be sent when the echoed + commands are received. + *) This method fails if a param change message is "chopped" after the first + byte. +*/ +void pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, int length) +{ + int i; + + if (!pod->midi_postprocess) + return; + + for (i = 0; i < length; ++i) { + if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) { + line6_invalidate_current(&pod->dumpreq); + break; + } else if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST)) && (i < length - 1)) + if ((data[i + 1] == POD_amp_model_setup) || (data[i + 1] == POD_effect_setup)) { + line6_invalidate_current(&pod->dumpreq); + break; + } + } +} + +/* + Send channel number (i.e., switch to a different sound). +*/ +static void pod_send_channel(struct usb_line6_pod *pod, int value) +{ + line6_invalidate_current(&pod->dumpreq); + + if (line6_send_program(&pod->line6, value) == 0) + pod->channel_num = value; + else + line6_dump_finished(&pod->dumpreq); +} + +/* + Transmit PODxt Pro control parameter. +*/ +void pod_transmit_parameter(struct usb_line6_pod *pod, int param, int value) +{ + if (line6_transmit_parameter(&pod->line6, param, value) == 0) + pod_store_parameter(pod, param, value); + + if ((param == POD_amp_model_setup) || (param == POD_effect_setup)) /* these also affect other settings */ + line6_invalidate_current(&pod->dumpreq); +} + +/* + Resolve value to memory location. +*/ +static void pod_resolve(const char *buf, short block0, short block1, unsigned char *location) +{ + int value = simple_strtoul(buf, NULL, 10); + short block = (value < 0x40) ? block0 : block1; + value &= 0x3f; + location[0] = block >> 7; + location[1] = value | (block & 0x7f); +} + +/* + Send command to store channel/effects setup/amp setup to PODxt Pro. +*/ +static ssize_t pod_send_store_command(struct device *dev, const char *buf, size_t count, short block0, short block1) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + + int size = 3 + sizeof(pod->prog_data_buf); + char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_STORE, size); + if (!sysex) + return 0; + + sysex[SYSEX_DATA_OFS] = 5; /* see pod_dump() */ + pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS + 1); + memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf, sizeof(pod->prog_data_buf)); + + line6_send_sysex_message(&pod->line6, sysex, size); + kfree(sysex); + /* needs some delay here on AMD64 platform */ + return count; +} + +/* + Send command to retrieve channel/effects setup/amp setup to PODxt Pro. +*/ +static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf, size_t count, short block0, short block1) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + int size = 4; + char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMPMEM, size); + + if (!sysex) + return 0; + + pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS); + sysex[SYSEX_DATA_OFS + 2] = 0; + sysex[SYSEX_DATA_OFS + 3] = 0; + line6_dump_started(&pod->dumpreq, POD_DUMP_MEMORY); + + if (line6_send_sysex_message(&pod->line6, sysex, size) < size) + line6_dump_finished(&pod->dumpreq); + + kfree(sysex); + /* needs some delay here on AMD64 platform */ + return count; +} + +/* + Generic get name function. +*/ +static ssize_t get_name_generic(struct usb_line6_pod *pod, const char *str, char *buf) +{ + int length = 0; + const char *p1; + char *p2; + char *last_non_space = buf; + + int retval = line6_wait_dump(&pod->dumpreq, 0); + if (retval < 0) + return retval; + + for (p1 = str, p2 = buf; *p1; ++p1, ++p2) { + *p2 = *p1; + if (*p2 != ' ') + last_non_space = p2; + if (++length == POD_NAME_LENGTH) + break; + } + + *(last_non_space + 1) = '\n'; + return last_non_space - buf + 2; +} + +/* + "read" request on "channel" special file. +*/ +static ssize_t pod_get_channel(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + return sprintf(buf, "%d\n", pod->channel_num); +} + +/* + "write" request on "channel" special file. +*/ +static ssize_t pod_set_channel(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + int value = simple_strtoul(buf, NULL, 10); + pod_send_channel(pod, value); + return count; +} + +/* + "read" request on "name" special file. +*/ +static ssize_t pod_get_name(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + return get_name_generic(pod, pod->prog_data.header + POD_NAME_OFFSET, buf); +} + +/* + "read" request on "name" special file. +*/ +static ssize_t pod_get_name_buf(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + return get_name_generic(pod, pod->prog_data_buf.header + POD_NAME_OFFSET, buf); +} + +/* + "read" request on "dump" special file. +*/ +static ssize_t pod_get_dump(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + int retval = line6_wait_dump(&pod->dumpreq, 0); + if (retval < 0) + return retval; + memcpy(buf, &pod->prog_data, sizeof(pod->prog_data)); + return sizeof(pod->prog_data); +} + +/* + "write" request on "dump" special file. +*/ +static ssize_t pod_set_dump(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + + if (count != sizeof(pod->prog_data)) { + dev_err(pod->line6.ifcdev, + "data block must be exactly %d bytes\n", + (int)sizeof(pod->prog_data)); + return -EINVAL; + } + + pod_dump(pod, buf); + return sizeof(pod->prog_data); +} + +/* + Request system parameter. + @param tuner non-zero, if code refers to a tuner parameter +*/ +static ssize_t pod_get_system_param(struct usb_line6_pod *pod, char *buf, int code, struct ValueWait *param, int tuner, int sign) +{ + char *sysex; + int value; + static const int size = 1; + int retval = 0; + DECLARE_WAITQUEUE(wait, current); + + if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && tuner) + return -ENODEV; + + /* send value request to tuner: */ + param->value = POD_system_invalid; + sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEMREQ, size); + if (!sysex) + return 0; + sysex[SYSEX_DATA_OFS] = code; + line6_send_sysex_message(&pod->line6, sysex, size); + kfree(sysex); + + /* wait for tuner to respond: */ + add_wait_queue(¶m->wait, &wait); + current->state = TASK_INTERRUPTIBLE; + + while (param->value == POD_system_invalid) { + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } else + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue(¶m->wait, &wait); + + if (retval < 0) + return retval; + + value = sign ? (int)(signed short)param->value : (int)(unsigned short)param->value; + return sprintf(buf, "%d\n", value); +} + +/* + Send system parameter. + @param tuner non-zero, if code refers to a tuner parameter +*/ +static ssize_t pod_set_system_param(struct usb_line6_pod *pod, const char *buf, + int count, int code, unsigned short mask, + int tuner) +{ + char *sysex; + static const int size = 5; + unsigned short value; + + if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && tuner) + return -EINVAL; + + /* send value to tuner: */ + sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size); + if (!sysex) + return 0; + value = simple_strtoul(buf, NULL, 10) & mask; + sysex[SYSEX_DATA_OFS] = code; + sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f; + sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f; + sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f; + sysex[SYSEX_DATA_OFS + 4] = (value ) & 0x0f; + line6_send_sysex_message(&pod->line6, sysex, size); + kfree(sysex); + return count; +} + +/* + "read" request on "dump_buf" special file. +*/ +static ssize_t pod_get_dump_buf(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + int retval = line6_wait_dump(&pod->dumpreq, 0); + if (retval < 0) + return retval; + memcpy(buf, &pod->prog_data_buf, sizeof(pod->prog_data_buf)); + return sizeof(pod->prog_data_buf); +} + +/* + "write" request on "dump_buf" special file. +*/ +static ssize_t pod_set_dump_buf(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + + if (count != sizeof(pod->prog_data)) { + dev_err(pod->line6.ifcdev, + "data block must be exactly %d bytes\n", + (int)sizeof(pod->prog_data)); + return -EINVAL; + } + + memcpy(&pod->prog_data_buf, buf, sizeof(pod->prog_data)); + return sizeof(pod->prog_data); +} + +/* + "write" request on "finish" special file. +*/ +static ssize_t pod_set_finish(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + int size = 0; + char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_FINISH, size); + if (!sysex) + return 0; + line6_send_sysex_message(&pod->line6, sysex, size); + kfree(sysex); + return count; +} + +/* + "write" request on "store_channel" special file. +*/ +static ssize_t pod_set_store_channel(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return pod_send_store_command(dev, buf, count, 0x0000, 0x00c0); +} + +/* + "write" request on "store_effects_setup" special file. +*/ +static ssize_t pod_set_store_effects_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return pod_send_store_command(dev, buf, count, 0x0080, 0x0080); +} + +/* + "write" request on "store_amp_setup" special file. +*/ +static ssize_t pod_set_store_amp_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return pod_send_store_command(dev, buf, count, 0x0040, 0x0100); +} + +/* + "write" request on "retrieve_channel" special file. +*/ +static ssize_t pod_set_retrieve_channel(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return pod_send_retrieve_command(dev, buf, count, 0x0000, 0x00c0); +} + +/* + "write" request on "retrieve_effects_setup" special file. +*/ +static ssize_t pod_set_retrieve_effects_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return pod_send_retrieve_command(dev, buf, count, 0x0080, 0x0080); +} + +/* + "write" request on "retrieve_amp_setup" special file. +*/ +static ssize_t pod_set_retrieve_amp_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return pod_send_retrieve_command(dev, buf, count, 0x0040, 0x0100); +} + +/* + "read" request on "dirty" special file. +*/ +static ssize_t pod_get_dirty(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + buf[0] = pod->dirty ? '1' : '0'; + buf[1] = '\n'; + return 2; +} + +/* + "read" request on "midi_postprocess" special file. +*/ +static ssize_t pod_get_midi_postprocess(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + return sprintf(buf, "%d\n", pod->midi_postprocess); +} + +/* + "write" request on "midi_postprocess" special file. +*/ +static ssize_t pod_set_midi_postprocess(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + int value = simple_strtoul(buf, NULL, 10); + pod->midi_postprocess = value ? 1 : 0; + return count; +} + +/* + "read" request on "serial_number" special file. +*/ +static ssize_t pod_get_serial_number(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + return sprintf(buf, "%d\n", pod->serial_number); +} + +/* + "read" request on "firmware_version" special file. +*/ +static ssize_t pod_get_firmware_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100, + pod->firmware_version % 100); +} + +/* + "read" request on "device_id" special file. +*/ +static ssize_t pod_get_device_id(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + return sprintf(buf, "%d\n", pod->device_id); +} + +/* + "read" request on "clip" special file. +*/ +static ssize_t pod_wait_for_clip(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_pod *pod = usb_get_intfdata(interface); + int err = 0; + DECLARE_WAITQUEUE(wait, current); + pod->clipping.value = 0; + add_wait_queue(&pod->clipping.wait, &wait); + current->state = TASK_INTERRUPTIBLE; + + while (pod->clipping.value == 0) { + if (signal_pending(current)) { + err = -ERESTARTSYS; + break; + } else + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue(&pod->clipping.wait, &wait); + return err; +} + +#define POD_GET_SYSTEM_PARAM(code, tuner, sign) \ +static ssize_t pod_get_ ## code(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct usb_interface *interface = to_usb_interface(dev); \ + struct usb_line6_pod *pod = usb_get_intfdata(interface); \ + return pod_get_system_param(pod, buf, POD_ ## code, &pod->code, \ + tuner, sign); \ +} + +#define POD_GET_SET_SYSTEM_PARAM(code, mask, tuner, sign) \ +POD_GET_SYSTEM_PARAM(code, tuner, sign) \ +static ssize_t pod_set_ ## code(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct usb_interface *interface = to_usb_interface(dev); \ + struct usb_line6_pod *pod = usb_get_intfdata(interface); \ + return pod_set_system_param(pod, buf, count, POD_ ## code, mask, \ + tuner); \ +} + +POD_GET_SET_SYSTEM_PARAM(monitor_level, 0xffff, 0, 0); +POD_GET_SET_SYSTEM_PARAM(routing, 0x0003, 0, 0); +POD_GET_SET_SYSTEM_PARAM(tuner_mute, 0x0001, 1, 0); +POD_GET_SET_SYSTEM_PARAM(tuner_freq, 0xffff, 1, 0); +POD_GET_SYSTEM_PARAM(tuner_note, 1, 1); +POD_GET_SYSTEM_PARAM(tuner_pitch, 1, 1); + +#undef GET_SET_SYSTEM_PARAM +#undef GET_SYSTEM_PARAM + +/* POD special files: */ +static DEVICE_ATTR(channel, S_IWUGO | S_IRUGO, pod_get_channel, pod_set_channel); +static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write); +static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write); +static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write); +static DEVICE_ATTR(dump, S_IWUGO | S_IRUGO, pod_get_dump, pod_set_dump); +static DEVICE_ATTR(dump_buf, S_IWUGO | S_IRUGO, pod_get_dump_buf, pod_set_dump_buf); +static DEVICE_ATTR(finish, S_IWUGO, line6_nop_read, pod_set_finish); +static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version, line6_nop_write); +static DEVICE_ATTR(midi_postprocess, S_IWUGO | S_IRUGO, pod_get_midi_postprocess, pod_set_midi_postprocess); +static DEVICE_ATTR(monitor_level, S_IWUGO | S_IRUGO, pod_get_monitor_level, pod_set_monitor_level); +static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write); +static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write); +static DEVICE_ATTR(retrieve_amp_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_amp_setup); +static DEVICE_ATTR(retrieve_channel, S_IWUGO, line6_nop_read, pod_set_retrieve_channel); +static DEVICE_ATTR(retrieve_effects_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_effects_setup); +static DEVICE_ATTR(routing, S_IWUGO | S_IRUGO, pod_get_routing, pod_set_routing); +static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number, line6_nop_write); +static DEVICE_ATTR(store_amp_setup, S_IWUGO, line6_nop_read, pod_set_store_amp_setup); +static DEVICE_ATTR(store_channel, S_IWUGO, line6_nop_read, pod_set_store_channel); +static DEVICE_ATTR(store_effects_setup, S_IWUGO, line6_nop_read, pod_set_store_effects_setup); +static DEVICE_ATTR(tuner_freq, S_IWUGO | S_IRUGO, pod_get_tuner_freq, pod_set_tuner_freq); +static DEVICE_ATTR(tuner_mute, S_IWUGO | S_IRUGO, pod_get_tuner_mute, pod_set_tuner_mute); +static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write); +static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write); + +#if CREATE_RAW_FILE +static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw); +#endif + +/* + POD destructor. +*/ +static void pod_destruct(struct usb_interface *interface) +{ + struct usb_line6_pod *pod = usb_get_intfdata(interface); + struct usb_line6 *line6; + + if (pod == NULL) + return; + line6 = &pod->line6; + if (line6 == NULL) + return; + line6_cleanup_audio(line6); + + /* free dump request data: */ + line6_dumpreq_destruct(&pod->dumpreq); + + kfree(pod->buffer_versionreq); +} + +/* + Create sysfs entries. +*/ +static int pod_create_files2(struct device *dev) +{ + int err; + + CHECK_RETURN(device_create_file(dev, &dev_attr_channel)); + CHECK_RETURN(device_create_file(dev, &dev_attr_clip)); + CHECK_RETURN(device_create_file(dev, &dev_attr_device_id)); + CHECK_RETURN(device_create_file(dev, &dev_attr_dirty)); + CHECK_RETURN(device_create_file(dev, &dev_attr_dump)); + CHECK_RETURN(device_create_file(dev, &dev_attr_dump_buf)); + CHECK_RETURN(device_create_file(dev, &dev_attr_finish)); + CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version)); + CHECK_RETURN(device_create_file(dev, &dev_attr_midi_postprocess)); + CHECK_RETURN(device_create_file(dev, &dev_attr_monitor_level)); + CHECK_RETURN(device_create_file(dev, &dev_attr_name)); + CHECK_RETURN(device_create_file(dev, &dev_attr_name_buf)); + CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_amp_setup)); + CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_channel)); + CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_effects_setup)); + CHECK_RETURN(device_create_file(dev, &dev_attr_routing)); + CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number)); + CHECK_RETURN(device_create_file(dev, &dev_attr_store_amp_setup)); + CHECK_RETURN(device_create_file(dev, &dev_attr_store_channel)); + CHECK_RETURN(device_create_file(dev, &dev_attr_store_effects_setup)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_freq)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_mute)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_note)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_pitch)); + +#if CREATE_RAW_FILE + CHECK_RETURN(device_create_file(dev, &dev_attr_raw)); +#endif + + return 0; +} + +/* + Init POD device. +*/ +int pod_init(struct usb_interface *interface, struct usb_line6_pod *pod) +{ + int err; + struct usb_line6 *line6 = &pod->line6; + + if ((interface == NULL) || (pod == NULL)) + return -ENODEV; + + pod->channel_num = 255; + + /* initialize wait queues: */ + init_waitqueue_head(&pod->monitor_level.wait); + init_waitqueue_head(&pod->routing.wait); + init_waitqueue_head(&pod->tuner_mute.wait); + init_waitqueue_head(&pod->tuner_freq.wait); + init_waitqueue_head(&pod->tuner_note.wait); + init_waitqueue_head(&pod->tuner_pitch.wait); + init_waitqueue_head(&pod->clipping.wait); + + memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty)); + + /* initialize USB buffers: */ + err = line6_dumpreq_init(&pod->dumpreq, pod_request_channel, + sizeof(pod_request_channel)); + if (err < 0) { + dev_err(&interface->dev, "Out of memory\n"); + pod_destruct(interface); + return -ENOMEM; + } + + pod->buffer_versionreq = kmalloc(sizeof(pod_request_version), + GFP_KERNEL); + + if (pod->buffer_versionreq == NULL) { + dev_err(&interface->dev, "Out of memory\n"); + pod_destruct(interface); + return -ENOMEM; + } + + memcpy(pod->buffer_versionreq, pod_request_version, + sizeof(pod_request_version)); + + /* create sysfs entries: */ + err = pod_create_files2(&interface->dev); + if (err < 0) { + pod_destruct(interface); + return err; + } + + /* initialize audio system: */ + err = line6_init_audio(line6); + if (err < 0) { + pod_destruct(interface); + return err; + } + + /* initialize MIDI subsystem: */ + err = line6_init_midi(line6); + if (err < 0) { + pod_destruct(interface); + return err; + } + + /* initialize PCM subsystem: */ + err = line6_init_pcm(line6, &pod_pcm_properties); + if (err < 0) { + pod_destruct(interface); + return err; + } + + /* register audio system: */ + err = line6_register_audio(line6); + if (err < 0) { + pod_destruct(interface); + return err; + } + + if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) { + /* query some data: */ + line6_startup_delayed(&pod->dumpreq, POD_STARTUP_DELAY, + pod_startup_timeout, pod); + line6_read_serial_number(&pod->line6, &pod->serial_number); + } + + return 0; +} + +/* + POD device disconnected. +*/ +void pod_disconnect(struct usb_interface *interface) +{ + struct usb_line6_pod *pod; + + if (interface == NULL) + return; + pod = usb_get_intfdata(interface); + + if (pod != NULL) { + struct snd_line6_pcm *line6pcm = pod->line6.line6pcm; + struct device *dev = &interface->dev; + + if (line6pcm != NULL) { + unlink_wait_clear_audio_out_urbs(line6pcm); + unlink_wait_clear_audio_in_urbs(line6pcm); + } + + if (dev != NULL) { + /* remove sysfs entries: */ + if (pod->versionreq_ok) + pod_remove_files(pod->firmware_version, pod->line6.properties->device_bit, dev); + + device_remove_file(dev, &dev_attr_channel); + device_remove_file(dev, &dev_attr_clip); + device_remove_file(dev, &dev_attr_device_id); + device_remove_file(dev, &dev_attr_dirty); + device_remove_file(dev, &dev_attr_dump); + device_remove_file(dev, &dev_attr_dump_buf); + device_remove_file(dev, &dev_attr_finish); + device_remove_file(dev, &dev_attr_firmware_version); + device_remove_file(dev, &dev_attr_midi_postprocess); + device_remove_file(dev, &dev_attr_monitor_level); + device_remove_file(dev, &dev_attr_name); + device_remove_file(dev, &dev_attr_name_buf); + device_remove_file(dev, &dev_attr_retrieve_amp_setup); + device_remove_file(dev, &dev_attr_retrieve_channel); + device_remove_file(dev, &dev_attr_retrieve_effects_setup); + device_remove_file(dev, &dev_attr_routing); + device_remove_file(dev, &dev_attr_serial_number); + device_remove_file(dev, &dev_attr_store_amp_setup); + device_remove_file(dev, &dev_attr_store_channel); + device_remove_file(dev, &dev_attr_store_effects_setup); + device_remove_file(dev, &dev_attr_tuner_freq); + device_remove_file(dev, &dev_attr_tuner_mute); + device_remove_file(dev, &dev_attr_tuner_note); + device_remove_file(dev, &dev_attr_tuner_pitch); + +#if CREATE_RAW_FILE + device_remove_file(dev, &dev_attr_raw); +#endif + } + } + + pod_destruct(interface); +} diff --git a/drivers/staging/line6/pod.h b/drivers/staging/line6/pod.h new file mode 100644 index 000000000000..7051ca613819 --- /dev/null +++ b/drivers/staging/line6/pod.h @@ -0,0 +1,204 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef POD_H +#define POD_H + + +#include "driver.h" + +#include +#include +#include +#include + +#include + +#include "dumprequest.h" + + +/* + PODxt Live interfaces +*/ +#define PODXTLIVE_INTERFACE_POD 0 +#define PODXTLIVE_INTERFACE_VARIAX 1 + +/* + Locate name in binary program dump +*/ +#define POD_NAME_OFFSET 0 +#define POD_NAME_LENGTH 16 + +/* + Other constants +*/ +#define POD_CONTROL_SIZE 0x80 +#define POD_BUFSIZE_DUMPREQ 7 +#define POD_STARTUP_DELAY 3 + + +/** + Data structure for values that need to be requested explicitly. + This is the case for system and tuner settings. +*/ +struct ValueWait { + unsigned short value; + wait_queue_head_t wait; +}; + +/** + Binary PodXT Pro program dump +*/ +struct pod_program { + /** + Header information (including program name). + */ + unsigned char header[0x20]; + + /** + Program parameters. + */ + unsigned char control[POD_CONTROL_SIZE]; +}; + +struct usb_line6_pod { + /** + Generic Line6 USB data. + */ + struct usb_line6 line6; + + /** + Dump request structure. + */ + struct line6_dump_request dumpreq; + + /** + Current program number. + */ + unsigned char channel_num; + + /** + Current program settings. + */ + struct pod_program prog_data; + + /** + Buffer for data retrieved from or to be stored on PODxt Pro. + */ + struct pod_program prog_data_buf; + + /** + Buffer for requesting version number. + */ + unsigned char *buffer_versionreq; + + /** + Tuner mute mode. + */ + struct ValueWait tuner_mute; + + /** + Tuner base frequency (typically 440Hz). + */ + struct ValueWait tuner_freq; + + /** + Note received from tuner. + */ + struct ValueWait tuner_note; + + /** + Pitch value received from tuner. + */ + struct ValueWait tuner_pitch; + + /** + Instrument monitor level. + */ + struct ValueWait monitor_level; + + /** + Audio routing mode. + 0: send processed guitar + 1: send clean guitar + 2: send clean guitar re-amp playback + 3: send re-amp playback + */ + struct ValueWait routing; + + /** + Wait for audio clipping event. + */ + struct ValueWait clipping; + + /** + Bottom-half for creation of sysfs special files. + */ + struct work_struct create_files_work; + + /** + Dirty flags for access to parameter data. + */ + unsigned long param_dirty[POD_CONTROL_SIZE / sizeof(unsigned long)]; + + /** + Some atomic flags. + */ + unsigned long atomic_flags; + + /** + Counter for startup process. + */ + int startup_count; + + /** + Serial number of device. + */ + int serial_number; + + /** + Firmware version (x 100). + */ + int firmware_version; + + /** + Device ID. + */ + int device_id; + + /** + Flag to indicate modification of current program settings. + */ + char dirty; + + /** + Flag if initial firmware version request has been successful. + */ + char versionreq_ok; + + /** + Flag to enable MIDI postprocessing. + */ + char midi_postprocess; +}; + + +extern void pod_disconnect(struct usb_interface *interface); +extern int pod_init(struct usb_interface *interface, struct usb_line6_pod *pod); +extern void pod_midi_postprocess(struct usb_line6_pod *pod, + unsigned char *data, int length); +extern void pod_process_message(struct usb_line6_pod *pod); +extern void pod_receive_parameter(struct usb_line6_pod *pod, int param); +extern void pod_transmit_parameter(struct usb_line6_pod *pod, int param, + int value); + + +#endif diff --git a/drivers/staging/line6/revision.h b/drivers/staging/line6/revision.h new file mode 100644 index 000000000000..b2a0a85efe69 --- /dev/null +++ b/drivers/staging/line6/revision.h @@ -0,0 +1,4 @@ +#ifndef DRIVER_REVISION +/* current subversion revision */ +#define DRIVER_REVISION " (revision 529)" +#endif diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c new file mode 100644 index 000000000000..eaa1229002aa --- /dev/null +++ b/drivers/staging/line6/toneport.c @@ -0,0 +1,241 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * Emil Myhrman (emil.myhrman@gmail.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, version 2. + * + */ + +#include "driver.h" + +#include "audio.h" +#include "capture.h" +#include "playback.h" +#include "toneport.h" + + +static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); + + +static struct snd_ratden toneport_ratden = { + .num_min = 44100, + .num_max = 44100, + .num_step = 1, + .den = 1 +}; + +static struct line6_pcm_properties toneport_pcm_properties = { + .snd_line6_playback_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = 44100, + .rate_max = 44100, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = 180 * 4, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024 + }, + .snd_line6_capture_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_KNOT, + .rate_min = 44100, + .rate_max = 44100, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = 188 * 4, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024 + }, + .snd_line6_rates = { + .nrats = 1, + .rats = &toneport_ratden + }, + .bytes_per_frame = 4 +}; + +/* + For the led on Guitarport. + Brightness goes from 0x00 to 0x26. Set a value above this to have led + blink. + (void cmd_0x02(byte red, byte green) +*/ +static int led_red = 0x00; +static int led_green = 0x26; + +static void toneport_update_led(struct device *dev) +{ + struct usb_interface *interface = to_usb_interface(dev); + struct usb_line6_toneport *tp = usb_get_intfdata(interface); + struct usb_line6 *line6; + + if (!tp) + return; + + line6 = &tp->line6; + if (line6) + toneport_send_cmd(line6->usbdev, (led_red << 8) | 0x0002, + led_green); +} + +static ssize_t toneport_set_led_red(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + char *c; + led_red = simple_strtol(buf, &c, 10); + toneport_update_led(dev); + return count; +} + +static ssize_t toneport_set_led_green(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + char *c; + led_green = simple_strtol(buf, &c, 10); + toneport_update_led(dev); + return count; +} + +static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read, toneport_set_led_red); +static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read, toneport_set_led_green); + + +static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) +{ + int ret; + + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ); + + if (ret < 0) { + err("send failed (error %d)\n", ret); + return ret; + } + + return 0; +} + +/* + Toneport destructor. +*/ +static void toneport_destruct(struct usb_interface *interface) +{ + struct usb_line6_toneport *toneport = usb_get_intfdata(interface); + struct usb_line6 *line6; + + if (toneport == NULL) + return; + line6 = &toneport->line6; + if (line6 == NULL) + return; + line6_cleanup_audio(line6); +} + +/* + Init Toneport device. +*/ +int toneport_init(struct usb_interface *interface, + struct usb_line6_toneport *toneport) +{ + int err, ticks; + struct usb_line6 *line6 = &toneport->line6; + struct usb_device *usbdev; + + if ((interface == NULL) || (toneport == NULL)) + return -ENODEV; + + /* initialize audio system: */ + err = line6_init_audio(line6); + if (err < 0) { + toneport_destruct(interface); + return err; + } + + /* initialize PCM subsystem: */ + err = line6_init_pcm(line6, &toneport_pcm_properties); + if (err < 0) { + toneport_destruct(interface); + return err; + } + + /* register audio system: */ + err = line6_register_audio(line6); + if (err < 0) { + toneport_destruct(interface); + return err; + } + + usbdev = line6->usbdev; + line6_read_serial_number(line6, &toneport->serial_number); + line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); + + /* sync time on device with host: */ + ticks = (int)get_seconds(); + line6_write_data(line6, 0x80c6, &ticks, 4); + + /* + seems to work without the first two... + */ + /* toneport_send_cmd(usbdev, 0x0201, 0x0002); */ + /* toneport_send_cmd(usbdev, 0x0801, 0x0000); */ + /* only one that works for me; on GP, TP might be different? */ + toneport_send_cmd(usbdev, 0x0301, 0x0000); + + if (usbdev->descriptor.idProduct != LINE6_DEVID_GUITARPORT) { + CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_red)); + CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_green)); + toneport_update_led(&usbdev->dev); + } + + return 0; +} + +/* + Toneport device disconnected. +*/ +void toneport_disconnect(struct usb_interface *interface) +{ + struct usb_line6_toneport *toneport; + + if (interface == NULL) + return; + toneport = usb_get_intfdata(interface); + + if (toneport->line6.usbdev->descriptor.idProduct != LINE6_DEVID_GUITARPORT) { + device_remove_file(&interface->dev, &dev_attr_led_red); + device_remove_file(&interface->dev, &dev_attr_led_green); + } + + if (toneport != NULL) { + struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm; + + if (line6pcm != NULL) { + unlink_wait_clear_audio_out_urbs(line6pcm); + unlink_wait_clear_audio_in_urbs(line6pcm); + } + } + + toneport_destruct(interface); +} diff --git a/drivers/staging/line6/toneport.h b/drivers/staging/line6/toneport.h new file mode 100644 index 000000000000..bddc58dd7e3a --- /dev/null +++ b/drivers/staging/line6/toneport.h @@ -0,0 +1,45 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef TONEPORT_H +#define TONEPORT_H + + +#include "driver.h" + +#include +#include + + +struct usb_line6_toneport { + /** + Generic Line6 USB data. + */ + struct usb_line6 line6; + + /** + Serial number of device. + */ + int serial_number; + + /** + Firmware version (x 100). + */ + int firmware_version; +}; + + +extern void toneport_disconnect(struct usb_interface *interface); +extern int toneport_init(struct usb_interface *interface, + struct usb_line6_toneport *toneport); + + +#endif diff --git a/drivers/staging/line6/usbdefs.h b/drivers/staging/line6/usbdefs.h new file mode 100644 index 000000000000..c38f31f2f421 --- /dev/null +++ b/drivers/staging/line6/usbdefs.h @@ -0,0 +1,74 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2005-2008 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef USBDEFS_H +#define USBDEFS_H + + +#define LINE6_VENDOR_ID 0x0e41 + +#define USB_INTERVALS_PER_SECOND 1000 + +/* + Device ids. +*/ +#define LINE6_DEVID_BASSPODXT 0x4250 +#define LINE6_DEVID_BASSPODXTLIVE 0x4642 +#define LINE6_DEVID_BASSPODXTPRO 0x4252 +#define LINE6_DEVID_GUITARPORT 0x4750 +#define LINE6_DEVID_POCKETPOD 0x5051 +#define LINE6_DEVID_PODX3 0x414a +#define LINE6_DEVID_PODX3LIVE 0x414b +#define LINE6_DEVID_PODXT 0x5044 +#define LINE6_DEVID_PODXTLIVE 0x4650 +#define LINE6_DEVID_PODXTPRO 0x5050 +#define LINE6_DEVID_TONEPORT_GX 0x4147 +#define LINE6_DEVID_TONEPORT_UX1 0x4141 +#define LINE6_DEVID_TONEPORT_UX2 0x4142 +#define LINE6_DEVID_VARIAX 0x534d + +#define LINE6_BIT_BASSPODXT (1 << 0) +#define LINE6_BIT_BASSPODXTLIVE (1 << 1) +#define LINE6_BIT_BASSPODXTPRO (1 << 2) +#define LINE6_BIT_GUITARPORT (1 << 3) +#define LINE6_BIT_POCKETPOD (1 << 4) +#define LINE6_BIT_PODX3 (1 << 5) +#define LINE6_BIT_PODX3LIVE (1 << 6) +#define LINE6_BIT_PODXT (1 << 7) +#define LINE6_BIT_PODXTLIVE (1 << 8) +#define LINE6_BIT_PODXTPRO (1 << 9) +#define LINE6_BIT_TONEPORT_GX (1 << 10) +#define LINE6_BIT_TONEPORT_UX1 (1 << 11) +#define LINE6_BIT_TONEPORT_UX2 (1 << 12) +#define LINE6_BIT_VARIAX (1 << 13) + +#define LINE6_BITS_PRO (LINE6_BIT_BASSPODXTPRO | \ + LINE6_BIT_PODXTPRO) +#define LINE6_BITS_LIVE (LINE6_BIT_BASSPODXTLIVE | \ + LINE6_BIT_PODXTLIVE | \ + LINE6_BIT_PODX3LIVE) +#define LINE6_BITS_PODXTALL (LINE6_BIT_PODXT | \ + LINE6_BIT_PODXTLIVE | \ + LINE6_BIT_PODXTPRO) +#define LINE6_BITS_BASSPODXTALL (LINE6_BIT_BASSPODXT | \ + LINE6_BIT_BASSPODXTLIVE | \ + LINE6_BIT_BASSPODXTPRO) + +/* device supports settings parameter via USB */ +#define LINE6_BIT_CONTROL (1 << 0) +/* device supports PCM input/output via USB */ +#define LINE6_BIT_PCM (1 << 1) +#define LINE6_BIT_CONTROL_PCM (LINE6_BIT_CONTROL | LINE6_BIT_PCM) + +#define LINE6_FALLBACK_INTERVAL 10 +#define LINE6_FALLBACK_MAXPACKETSIZE 16 + +#endif diff --git a/drivers/staging/line6/variax.c b/drivers/staging/line6/variax.c new file mode 100644 index 000000000000..f9d96984733a --- /dev/null +++ b/drivers/staging/line6/variax.c @@ -0,0 +1,546 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#include "driver.h" + +#include "audio.h" +#include "control.h" +#include "variax.h" + + +#define VARIAX_SYSEX_CODE 7 +#define VARIAX_SYSEX_PARAM 0x3b +#define VARIAX_SYSEX_ACTIVATE 0x2a +#define VARIAX_MODEL_HEADER_LENGTH 7 +#define VARIAX_MODEL_MESSAGE_LENGTH 199 +#define VARIAX_OFFSET_ACTIVATE 7 + + +static const char variax_activate[] = { + 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01, + 0xf7 +}; +static const char variax_request_bank[] = { + 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6d, 0xf7 +}; +static const char variax_request_model1[] = { + 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x03, + 0x00, 0x00, 0x00, 0xf7 +}; +static const char variax_request_model2[] = { + 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x03, + 0x00, 0x00, 0x00, 0xf7 +}; + + +/* + Decode data transmitted by workbench. +*/ +static void variax_decode(const unsigned char *raw_data, unsigned char *data, + int raw_size) +{ + for (; raw_size > 0; raw_size -= 6) { + data[2] = raw_data[0] | (raw_data[1] << 4); + data[1] = raw_data[2] | (raw_data[3] << 4); + data[0] = raw_data[4] | (raw_data[5] << 4); + raw_data += 6; + data += 3; + } +} + +static void variax_activate_timeout(unsigned long arg) +{ + struct usb_line6_variax *variax = (struct usb_line6_variax *)arg; + variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = 1; + line6_send_raw_message_async(&variax->line6, variax->buffer_activate, + sizeof(variax_activate)); +} + +/* + Send an asynchronous activation request after a given interval. +*/ +static void variax_activate_delayed(struct usb_line6_variax *variax, + int seconds) +{ + variax->activate_timer.expires = jiffies + seconds * HZ; + variax->activate_timer.function = variax_activate_timeout; + variax->activate_timer.data = (unsigned long)variax; + add_timer(&variax->activate_timer); +} + +static void variax_startup_timeout(unsigned long arg) +{ + struct usb_line6_variax *variax = (struct usb_line6_variax *)arg; + + if (variax->dumpreq.ok) + return; + + line6_dump_request_async(&variax->dumpreq, &variax->line6, 0); + line6_startup_delayed(&variax->dumpreq, 1, variax_startup_timeout, + variax); +} + +/* + Process a completely received message. +*/ +void variax_process_message(struct usb_line6_variax *variax) +{ + const unsigned char *buf = variax->line6.buffer_message; + + switch (buf[0]) { + case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST: + switch (buf[1]) { + case VARIAXMIDI_volume: + variax->volume = buf[2]; + break; + + case VARIAXMIDI_tone: + variax->tone = buf[2]; + } + + break; + + case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE: + case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST: + variax->model = buf[1]; + line6_dump_request_async(&variax->dumpreq, &variax->line6, 0); + break; + + case LINE6_RESET: + dev_info(variax->line6.ifcdev, "VARIAX reset\n"); + variax_activate_delayed(variax, VARIAX_ACTIVATE_DELAY); + break; + + case LINE6_SYSEX_BEGIN: + if (memcmp(buf + 1, variax_request_model1 + 1, + VARIAX_MODEL_HEADER_LENGTH - 1) == 0) { + if (variax->line6.message_length == + VARIAX_MODEL_MESSAGE_LENGTH) { + switch (variax->dumpreq.in_progress) { + case VARIAX_DUMP_PASS1: + variax_decode(buf + VARIAX_MODEL_HEADER_LENGTH, (unsigned char *)&variax->model_data, + (sizeof(variax->model_data.name) + sizeof(variax->model_data.control) / 2) * 2); + line6_dump_request_async(&variax->dumpreq, &variax->line6, 1); + line6_dump_started(&variax->dumpreq, VARIAX_DUMP_PASS2); + break; + + case VARIAX_DUMP_PASS2: + /* model name is transmitted twice, so skip it here: */ + variax_decode(buf + VARIAX_MODEL_HEADER_LENGTH, + (unsigned char *)&variax->model_data.control + sizeof(variax->model_data.control) / 2, + sizeof(variax->model_data.control) / 2 * 2); + variax->dumpreq.ok = 1; + line6_dump_request_async(&variax->dumpreq, &variax->line6, 2); + line6_dump_started(&variax->dumpreq, VARIAX_DUMP_PASS3); + } + } else { + DEBUG_MESSAGES(dev_err(variax->line6.ifcdev, "illegal length %d of model data\n", variax->line6.message_length)); + line6_dump_finished(&variax->dumpreq); + } + } else if (memcmp(buf + 1, variax_request_bank + 1, + sizeof(variax_request_bank) - 2) == 0) { + memcpy(variax->bank, + buf + sizeof(variax_request_bank) - 1, + sizeof(variax->bank)); + variax->dumpreq.ok = 1; + line6_dump_finished(&variax->dumpreq); + } + + break; + + case LINE6_SYSEX_END: + break; + + default: + DEBUG_MESSAGES(dev_err(variax->line6.ifcdev, "Variax: unknown message %02X\n", buf[0])); + } +} + +/* + "read" request on "volume" special file. +*/ +static ssize_t variax_get_volume(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + return sprintf(buf, "%d\n", variax->volume); +} + +/* + "write" request on "volume" special file. +*/ +static ssize_t variax_set_volume(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + int value = simple_strtoul(buf, NULL, 10); + + if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_volume, + value) == 0) + variax->volume = value; + + return count; +} + +/* + "read" request on "model" special file. +*/ +static ssize_t variax_get_model(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + return sprintf(buf, "%d\n", variax->model); +} + +/* + "write" request on "model" special file. +*/ +static ssize_t variax_set_model(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + int value = simple_strtoul(buf, NULL, 10); + + if (line6_send_program(&variax->line6, value) == 0) + variax->model = value; + + return count; +} + +/* + "read" request on "active" special file. +*/ +static ssize_t variax_get_active(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + return sprintf(buf, "%d\n", variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]); +} + +/* + "write" request on "active" special file. +*/ +static ssize_t variax_set_active(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + int value = simple_strtoul(buf, NULL, 10) ? 1 : 0; + variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = value; + line6_send_raw_message_async(&variax->line6, variax->buffer_activate, + sizeof(variax_activate)); + return count; +} + +/* + "read" request on "tone" special file. +*/ +static ssize_t variax_get_tone(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + return sprintf(buf, "%d\n", variax->tone); +} + +/* + "write" request on "tone" special file. +*/ +static ssize_t variax_set_tone(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + int value = simple_strtoul(buf, NULL, 10); + + if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone, + value) == 0) + variax->tone = value; + + return count; +} + +static ssize_t get_string(char *buf, const char *data, int length) +{ + int i; + memcpy(buf, data, length); + + for (i = length; i--;) { + char c = buf[i]; + + if ((c != 0) && (c != ' ')) + break; + } + + buf[i + 1] = '\n'; + return i + 2; +} + +/* + "read" request on "name" special file. +*/ +static ssize_t variax_get_name(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + line6_wait_dump(&variax->dumpreq, 0); + return get_string(buf, variax->model_data.name, + sizeof(variax->model_data.name)); +} + +/* + "read" request on "bank" special file. +*/ +static ssize_t variax_get_bank(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + line6_wait_dump(&variax->dumpreq, 0); + return get_string(buf, variax->bank, sizeof(variax->bank)); +} + +/* + "read" request on "dump" special file. +*/ +static ssize_t variax_get_dump(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + int retval; + retval = line6_wait_dump(&variax->dumpreq, 0); + if (retval < 0) + return retval; + memcpy(buf, &variax->model_data.control, + sizeof(variax->model_data.control)); + return sizeof(variax->model_data.control); +} + +#if CREATE_RAW_FILE + +/* + "write" request on "raw" special file. +*/ +static ssize_t variax_set_raw2(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); + int size; + int i; + char *sysex; + + count -= count % 3; + size = count * 2; + sysex = variax_alloc_sysex_buffer(variax, VARIAX_SYSEX_PARAM, size); + + if (!sysex) + return 0; + + for (i = 0; i < count; i += 3) { + const unsigned char *p1 = buf + i; + char *p2 = sysex + SYSEX_DATA_OFS + i * 2; + p2[0] = p1[2] & 0x0f; + p2[1] = p1[2] >> 4; + p2[2] = p1[1] & 0x0f; + p2[3] = p1[1] >> 4; + p2[4] = p1[0] & 0x0f; + p2[5] = p1[0] >> 4; + } + + line6_send_sysex_message(&variax->line6, sysex, size); + kfree(sysex); + return count; +} + +#endif + +/* Variax workbench special files: */ +static DEVICE_ATTR(model, S_IWUGO | S_IRUGO, variax_get_model, variax_set_model); +static DEVICE_ATTR(volume, S_IWUGO | S_IRUGO, variax_get_volume, variax_set_volume); +static DEVICE_ATTR(tone, S_IWUGO | S_IRUGO, variax_get_tone, variax_set_tone); +static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write); +static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write); +static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write); +static DEVICE_ATTR(active, S_IWUGO | S_IRUGO, variax_get_active, variax_set_active); + +#if CREATE_RAW_FILE +static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw); +static DEVICE_ATTR(raw2, S_IWUGO, line6_nop_read, variax_set_raw2); +#endif + + +/* + Variax destructor. +*/ +static void variax_destruct(struct usb_interface *interface) +{ + struct usb_line6_variax *variax = usb_get_intfdata(interface); + struct usb_line6 *line6; + + if (variax == NULL) + return; + line6 = &variax->line6; + if (line6 == NULL) + return; + line6_cleanup_audio(line6); + + /* free dump request data: */ + line6_dumpreq_destructbuf(&variax->dumpreq, 2); + line6_dumpreq_destructbuf(&variax->dumpreq, 1); + line6_dumpreq_destruct(&variax->dumpreq); + + kfree(variax->buffer_activate); + del_timer_sync(&variax->activate_timer); +} + +/* + Create sysfs entries. +*/ +static int variax_create_files2(struct device *dev) +{ + int err; + CHECK_RETURN(device_create_file(dev, &dev_attr_model)); + CHECK_RETURN(device_create_file(dev, &dev_attr_volume)); + CHECK_RETURN(device_create_file(dev, &dev_attr_tone)); + CHECK_RETURN(device_create_file(dev, &dev_attr_name)); + CHECK_RETURN(device_create_file(dev, &dev_attr_bank)); + CHECK_RETURN(device_create_file(dev, &dev_attr_dump)); + CHECK_RETURN(device_create_file(dev, &dev_attr_active)); +#if CREATE_RAW_FILE + CHECK_RETURN(device_create_file(dev, &dev_attr_raw)); + CHECK_RETURN(device_create_file(dev, &dev_attr_raw2)); +#endif + return 0; +} + +/* + Init workbench device. +*/ +int variax_init(struct usb_interface *interface, + struct usb_line6_variax *variax) +{ + int err; + + if ((interface == NULL) || (variax == NULL)) + return -ENODEV; + + /* initialize USB buffers: */ + err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1, + sizeof(variax_request_model1)); + + if (err < 0) { + dev_err(&interface->dev, "Out of memory\n"); + variax_destruct(interface); + return err; + } + + err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2, + sizeof(variax_request_model2), 1); + + if (err < 0) { + dev_err(&interface->dev, "Out of memory\n"); + variax_destruct(interface); + return err; + } + + err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank, + sizeof(variax_request_bank), 2); + + if (err < 0) { + dev_err(&interface->dev, "Out of memory\n"); + variax_destruct(interface); + return err; + } + + variax->buffer_activate = kmalloc(sizeof(variax_activate), GFP_KERNEL); + + if (variax->buffer_activate == NULL) { + dev_err(&interface->dev, "Out of memory\n"); + variax_destruct(interface); + return -ENOMEM; + } + + memcpy(variax->buffer_activate, variax_activate, + sizeof(variax_activate)); + init_timer(&variax->activate_timer); + + /* create sysfs entries: */ + err = variax_create_files(0, 0, &interface->dev); + if (err < 0) { + variax_destruct(interface); + return err; + } + + err = variax_create_files2(&interface->dev); + if (err < 0) { + variax_destruct(interface); + return err; + } + + /* initialize audio system: */ + err = line6_init_audio(&variax->line6); + if (err < 0) { + variax_destruct(interface); + return err; + } + + /* initialize MIDI subsystem: */ + err = line6_init_midi(&variax->line6); + if (err < 0) { + variax_destruct(interface); + return err; + } + + /* register audio system: */ + err = line6_register_audio(&variax->line6); + if (err < 0) { + variax_destruct(interface); + return err; + } + + variax_activate_delayed(variax, VARIAX_ACTIVATE_DELAY); + line6_startup_delayed(&variax->dumpreq, VARIAX_STARTUP_DELAY, + variax_startup_timeout, variax); + return 0; +} + +/* + Workbench device disconnected. +*/ +void variax_disconnect(struct usb_interface *interface) +{ + struct device *dev; + + if (interface == NULL) + return; + dev = &interface->dev; + + if (dev != NULL) { + /* remove sysfs entries: */ + variax_remove_files(0, 0, dev); + device_remove_file(dev, &dev_attr_model); + device_remove_file(dev, &dev_attr_volume); + device_remove_file(dev, &dev_attr_tone); + device_remove_file(dev, &dev_attr_name); + device_remove_file(dev, &dev_attr_bank); + device_remove_file(dev, &dev_attr_dump); + device_remove_file(dev, &dev_attr_active); +#if CREATE_RAW_FILE + device_remove_file(dev, &dev_attr_raw); + device_remove_file(dev, &dev_attr_raw2); +#endif + } + + variax_destruct(interface); +} diff --git a/drivers/staging/line6/variax.h b/drivers/staging/line6/variax.h new file mode 100644 index 000000000000..ee330ba30898 --- /dev/null +++ b/drivers/staging/line6/variax.h @@ -0,0 +1,108 @@ +/* + * Line6 Linux USB driver - 0.8.0 + * + * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) + * + * 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, version 2. + * + */ + +#ifndef VARIAX_H +#define VARIAX_H + + +#include "driver.h" + +#include +#include +#include + +#include + +#include "dumprequest.h" + + +#define VARIAX_ACTIVATE_DELAY 10 +#define VARIAX_STARTUP_DELAY 3 + + +enum { + VARIAX_DUMP_PASS1 = LINE6_DUMP_CURRENT, + VARIAX_DUMP_PASS2, + VARIAX_DUMP_PASS3 +}; + + +/** + Binary Variax model dump +*/ +struct variax_model { + /** + Header information (including program name). + */ + unsigned char name[18]; + + /** + Model parameters. + */ + unsigned char control[78 * 2]; +}; + +struct usb_line6_variax { + /** + Generic Line6 USB data. + */ + struct usb_line6 line6; + + /** + Dump request structure. + Append two extra buffers for 3-pass data query. + */ + struct line6_dump_request dumpreq; struct line6_dump_reqbuf extrabuf[2]; + + /** + Buffer for activation code. + */ + unsigned char *buffer_activate; + + /** + Model number. + */ + int model; + + /** + Current model settings. + */ + struct variax_model model_data; + + /** + Name of current model bank. + */ + unsigned char bank[18]; + + /** + Position of volume dial. + */ + int volume; + + /** + Position of tone control dial. + */ + int tone; + + /** + Timer for delayed activation request. + */ + struct timer_list activate_timer; +}; + + +extern void variax_disconnect(struct usb_interface *interface); +extern int variax_init(struct usb_interface *interface, + struct usb_line6_variax *variax); +extern void variax_process_message(struct usb_line6_variax *variax); + + +#endif diff --git a/drivers/staging/me4000/me4000.c b/drivers/staging/me4000/me4000.c index e1c4a8078901..01017b731d0b 100644 --- a/drivers/staging/me4000/me4000.c +++ b/drivers/staging/me4000/me4000.c @@ -36,8 +36,8 @@ #include #include #include -#include -#include +#include +#include #include /* Include-File for the Meilhaus ME-4000 I/O board */ @@ -246,17 +246,17 @@ static irqreturn_t me4000_ext_int_isr(int, void *); Inline functions ---------------------------------------------------------------------------*/ -static int inline me4000_buf_count(struct me4000_circ_buf buf, int size) +static inline int me4000_buf_count(struct me4000_circ_buf buf, int size) { - return ((buf.head - buf.tail) & (size - 1)); + return (buf.head - buf.tail) & (size - 1); } -static int inline me4000_buf_space(struct me4000_circ_buf buf, int size) +static inline int me4000_buf_space(struct me4000_circ_buf buf, int size) { - return ((buf.tail - (buf.head + 1)) & (size - 1)); + return (buf.tail - (buf.head + 1)) & (size - 1); } -static int inline me4000_values_to_end(struct me4000_circ_buf buf, int size) +static inline int me4000_values_to_end(struct me4000_circ_buf buf, int size) { int end; int n; @@ -265,7 +265,7 @@ static int inline me4000_values_to_end(struct me4000_circ_buf buf, int size) return (n < end) ? n : end; } -static int inline me4000_space_to_end(struct me4000_circ_buf buf, int size) +static inline int me4000_space_to_end(struct me4000_circ_buf buf, int size) { int end; int n; @@ -275,19 +275,19 @@ static int inline me4000_space_to_end(struct me4000_circ_buf buf, int size) return (n <= end) ? n : (end + 1); } -static void inline me4000_outb(unsigned char value, unsigned long port) +static inline void me4000_outb(unsigned char value, unsigned long port) { PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port); outb(value, port); } -static void inline me4000_outl(unsigned long value, unsigned long port) +static inline void me4000_outl(unsigned long value, unsigned long port) { PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port); outl(value, port); } -static unsigned long inline me4000_inl(unsigned long port) +static inline unsigned long me4000_inl(unsigned long port) { unsigned long value; value = inl(port); @@ -295,7 +295,7 @@ static unsigned long inline me4000_inl(unsigned long port) return value; } -static unsigned char inline me4000_inb(unsigned long port) +static inline unsigned char me4000_inb(unsigned long port) { unsigned char value; value = inb(port); @@ -309,7 +309,7 @@ static struct pci_driver me4000_driver = { .probe = me4000_probe }; -static struct file_operations me4000_ao_fops_sing = { +static const struct file_operations me4000_ao_fops_sing = { .owner = THIS_MODULE, .write = me4000_ao_write_sing, .ioctl = me4000_ao_ioctl_sing, @@ -317,7 +317,7 @@ static struct file_operations me4000_ao_fops_sing = { .release = me4000_release, }; -static struct file_operations me4000_ao_fops_wrap = { +static const struct file_operations me4000_ao_fops_wrap = { .owner = THIS_MODULE, .write = me4000_ao_write_wrap, .ioctl = me4000_ao_ioctl_wrap, @@ -325,7 +325,7 @@ static struct file_operations me4000_ao_fops_wrap = { .release = me4000_release, }; -static struct file_operations me4000_ao_fops_cont = { +static const struct file_operations me4000_ao_fops_cont = { .owner = THIS_MODULE, .write = me4000_ao_write_cont, .poll = me4000_ao_poll_cont, @@ -335,14 +335,14 @@ static struct file_operations me4000_ao_fops_cont = { .fsync = me4000_ao_fsync_cont, }; -static struct file_operations me4000_ai_fops_sing = { +static const struct file_operations me4000_ai_fops_sing = { .owner = THIS_MODULE, .ioctl = me4000_ai_ioctl_sing, .open = me4000_open, .release = me4000_release, }; -static struct file_operations me4000_ai_fops_cont_sw = { +static const struct file_operations me4000_ai_fops_cont_sw = { .owner = THIS_MODULE, .read = me4000_ai_read, .poll = me4000_ai_poll, @@ -352,7 +352,7 @@ static struct file_operations me4000_ai_fops_cont_sw = { .fasync = me4000_ai_fasync, }; -static struct file_operations me4000_ai_fops_cont_et = { +static const struct file_operations me4000_ai_fops_cont_et = { .owner = THIS_MODULE, .read = me4000_ai_read, .poll = me4000_ai_poll, @@ -361,7 +361,7 @@ static struct file_operations me4000_ai_fops_cont_et = { .release = me4000_release, }; -static struct file_operations me4000_ai_fops_cont_et_value = { +static const struct file_operations me4000_ai_fops_cont_et_value = { .owner = THIS_MODULE, .read = me4000_ai_read, .poll = me4000_ai_poll, @@ -370,7 +370,7 @@ static struct file_operations me4000_ai_fops_cont_et_value = { .release = me4000_release, }; -static struct file_operations me4000_ai_fops_cont_et_chanlist = { +static const struct file_operations me4000_ai_fops_cont_et_chanlist = { .owner = THIS_MODULE, .read = me4000_ai_read, .poll = me4000_ai_poll, @@ -379,21 +379,21 @@ static struct file_operations me4000_ai_fops_cont_et_chanlist = { .release = me4000_release, }; -static struct file_operations me4000_dio_fops = { +static const struct file_operations me4000_dio_fops = { .owner = THIS_MODULE, .ioctl = me4000_dio_ioctl, .open = me4000_open, .release = me4000_release, }; -static struct file_operations me4000_cnt_fops = { +static const struct file_operations me4000_cnt_fops = { .owner = THIS_MODULE, .ioctl = me4000_cnt_ioctl, .open = me4000_open, .release = me4000_release, }; -static struct file_operations me4000_ext_int_fops = { +static const struct file_operations me4000_ext_int_fops = { .owner = THIS_MODULE, .ioctl = me4000_ext_int_ioctl, .open = me4000_open, @@ -401,18 +401,26 @@ static struct file_operations me4000_ext_int_fops = { .fasync = me4000_ext_int_fasync, }; -static struct file_operations *me4000_ao_fops_array[] = { - &me4000_ao_fops_sing, // single operations - &me4000_ao_fops_wrap, // wraparound operations - &me4000_ao_fops_cont, // continous operations +static const struct file_operations *me4000_ao_fops_array[] = { + /* single operations */ + &me4000_ao_fops_sing, + /* wraparound operations */ + &me4000_ao_fops_wrap, + /* continuous operations */ + &me4000_ao_fops_cont, }; -static struct file_operations *me4000_ai_fops_array[] = { - &me4000_ai_fops_sing, // single operations - &me4000_ai_fops_cont_sw, // continuous operations with software start - &me4000_ai_fops_cont_et, // continous operations with external trigger - &me4000_ai_fops_cont_et_value, // sample values by external trigger - &me4000_ai_fops_cont_et_chanlist, // work through one channel list by external trigger +static const struct file_operations *me4000_ai_fops_array[] = { + /* single operations */ + &me4000_ai_fops_sing, + /* continuous operations with software start */ + &me4000_ai_fops_cont_sw, + /* continuous operations with external trigger */ + &me4000_ai_fops_cont_et, + /* sample values by external trigger */ + &me4000_ai_fops_cont_et_value, + /* work through one channel list by external trigger */ + &me4000_ai_fops_cont_et_chanlist, }; static int __init me4000_init_module(void) @@ -546,15 +554,13 @@ static void clear_board_info_list(void) &board_info->ao_context_list, list) { me4000_ao_reset(ao_context); free_irq(ao_context->irq, ao_context); - if (ao_context->circ_buf.buf) - kfree(ao_context->circ_buf.buf); + kfree(ao_context->circ_buf.buf); list_del(&ao_context->list); kfree(ao_context); } /* Clear analog input context */ - if (board_info->ai_context->circ_buf.buf) - kfree(board_info->ai_context->circ_buf.buf); + kfree(board_info->ai_context->circ_buf.buf); kfree(board_info->ai_context); /* Clear digital I/O context */ @@ -1263,9 +1269,8 @@ static int me4000_reset_board(struct me4000_info *info) info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG); /* Set digital I/O direction for port 0 to output on isolated versions */ - if (!(me4000_inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) { + if (!(me4000_inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) me4000_outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG); - } return 0; } @@ -1463,7 +1468,7 @@ static int me4000_open(struct inode *inode_p, struct file *file_p) /* Set file operations pointer to single functions */ file_p->f_op = &me4000_dio_fops; - //me4000_dio_reset(dio_context); + /* me4000_dio_reset(dio_context); */ } /* Counters */ else if (MAJOR(inode_p->i_rdev) == me4000_cnt_major_driver_no) { @@ -2058,7 +2063,7 @@ static ssize_t me4000_ao_write_cont(struct file *filep, const char *buff, ME4000_AO_BUFFER_COUNT); if (c == 0) - return (2 * ret); + return 2 * ret; /* Only able to write size of free buffer or size of count */ if (count < c) @@ -2104,9 +2109,8 @@ static ssize_t me4000_ao_write_cont(struct file *filep, const char *buff, } } - if (filep->f_flags & O_NONBLOCK) { + if (filep->f_flags & O_NONBLOCK) return (ret == 0) ? -EAGAIN : 2 * ret; - } return 2 * ret; } @@ -2201,7 +2205,7 @@ static int me4000_ao_ioctl_sing(struct inode *inode_p, struct file *file_p, case ME4000_AO_SIMULTANEOUS_UPDATE: return me4000_ao_simultaneous_update( - (struct me4000_ao_channel_list *)arg, + (struct me4000_ao_channel_list *)arg, ao_context); case ME4000_AO_EX_TRIG_TIMEOUT: return me4000_ao_ex_trig_timeout((unsigned long *)arg, @@ -2361,7 +2365,9 @@ static int me4000_ao_start(unsigned long *arg, "ME4000:me4000_ao_start():Wait on start of state machine interrupted\n"); return -EINTR; } - if (((jiffies - ref) > (timeout * HZ / USER_HZ))) { // 2.6 has diffrent definitions for HZ in user and kernel space + /* kernel 2.6 has different definitions for HZ + * in user and kernel space */ + if ((jiffies - ref) > (timeout * HZ / USER_HZ)) { printk(KERN_ERR "ME4000:me4000_ao_start():Timeout reached\n"); return -EIO; @@ -2402,8 +2408,8 @@ static int me4000_ao_stop(struct me4000_ao_context *ao_context) } /* Clear the stop bit */ - //tmp &= ~ME4000_AO_CTRL_BIT_STOP; - //me4000_outl(tmp, ao_context->ctrl_reg); + /* tmp &= ~ME4000_AO_CTRL_BIT_STOP; */ + /* me4000_outl(tmp, ao_context->ctrl_reg); */ return 0; } @@ -2434,8 +2440,8 @@ static int me4000_ao_immediate_stop(struct me4000_ao_context *ao_context) } /* Clear the stop bits */ - //tmp &= ~(ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP); - //me4000_outl(tmp, ao_context->ctrl_reg); + /* tmp &= ~(ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP); */ + /* me4000_outl(tmp, ao_context->ctrl_reg); */ return 0; } @@ -2598,8 +2604,10 @@ static int me4000_ao_simultaneous_disable(struct me4000_ao_context *ao_context) spin_lock(&ao_context->board_info->preload_lock); tmp = me4000_inl(ao_context->preload_reg); - tmp &= ~(0x1 << ao_context->index); // Disable preload bit - tmp &= ~(0x1 << (ao_context->index + 16)); // Disable hw simultaneous bit + /* Disable preload bit */ + tmp &= ~(0x1 << ao_context->index); + /* Disable hw simultaneous bit */ + tmp &= ~(0x1 << (ao_context->index + 16)); me4000_outl(tmp, ao_context->preload_reg); spin_unlock(&ao_context->board_info->preload_lock); @@ -2614,8 +2622,10 @@ static int me4000_ao_simultaneous_ex_trig(struct me4000_ao_context *ao_context) spin_lock(&ao_context->board_info->preload_lock); tmp = me4000_inl(ao_context->preload_reg); - tmp |= (0x1 << ao_context->index); // Enable preload bit - tmp |= (0x1 << (ao_context->index + 16)); // Enable hw simultaneous bit + /* Enable preload bit */ + tmp |= (0x1 << ao_context->index); + /* Enable hw simulatenous bit */ + tmp |= (0x1 << (ao_context->index + 16)); me4000_outl(tmp, ao_context->preload_reg); spin_unlock(&ao_context->board_info->preload_lock); @@ -2630,8 +2640,10 @@ static int me4000_ao_simultaneous_sw(struct me4000_ao_context *ao_context) spin_lock(&ao_context->board_info->preload_lock); tmp = me4000_inl(ao_context->preload_reg); - tmp |= (0x1 << ao_context->index); // Enable preload bit - tmp &= ~(0x1 << (ao_context->index + 16)); // Disable hw simultaneous bit + /* Enable preload bit */ + tmp |= (0x1 << ao_context->index); + /* Enable hw simulatenous bit */ + tmp &= ~(0x1 << (ao_context->index + 16)); me4000_outl(tmp, ao_context->preload_reg); spin_unlock(&ao_context->board_info->preload_lock); @@ -2669,11 +2681,11 @@ static int me4000_ao_preload_update(struct me4000_ao_context *ao_context) (tmp & (0x1 << (((struct me4000_ao_context *)entry)->index - + 16)))) { + + 16)))) { tmp &= ~(0x1 << (((struct me4000_ao_context *)entry)-> - index)); + index)); } } } @@ -2732,8 +2744,10 @@ static int me4000_ao_simultaneous_update(struct me4000_ao_channel_list *arg, "ME4000:me4000_ao_simultaneous_update():Invalid board number specified\n"); return -EFAULT; } - tmp &= ~(0x1 << channels.list[i]); // Clear the preload bit - tmp &= ~(0x1 << (channels.list[i] + 16)); // Clear the hw simultaneous bit + /* Clear the preload bit */ + tmp &= ~(0x1 << channels.list[i]); + /* Clear the hw simultaneous bit */ + tmp &= ~(0x1 << (channels.list[i] + 16)); } me4000_outl(tmp, ao_context->preload_reg); spin_unlock(&ao_context->board_info->preload_lock); @@ -2759,8 +2773,10 @@ static int me4000_ao_synchronous_ex_trig(struct me4000_ao_context *ao_context) spin_lock(&ao_context->board_info->preload_lock); tmp = me4000_inl(ao_context->preload_reg); - tmp &= ~(0x1 << ao_context->index); // Disable synchronous sw bit - tmp |= 0x1 << (ao_context->index + 16); // Enable synchronous hw bit + /* Disable synchronous sw bit */ + tmp &= ~(0x1 << ao_context->index); + /* Enable synchronous hw bit */ + tmp |= 0x1 << (ao_context->index + 16); me4000_outl(tmp, ao_context->preload_reg); spin_unlock(&ao_context->board_info->preload_lock); @@ -2794,8 +2810,10 @@ static int me4000_ao_synchronous_sw(struct me4000_ao_context *ao_context) spin_lock(&ao_context->board_info->preload_lock); tmp = me4000_inl(ao_context->preload_reg); - tmp |= 0x1 << ao_context->index; // Enable synchronous sw bit - tmp &= ~(0x1 << (ao_context->index + 16)); // Disable synchronous hw bit + /* Enable synchronous sw bit */ + tmp |= 0x1 << ao_context->index; + /* Disable synchronous hw bit */ + tmp &= ~(0x1 << (ao_context->index + 16)); me4000_outl(tmp, ao_context->preload_reg); spin_unlock(&ao_context->board_info->preload_lock); @@ -2867,7 +2885,9 @@ static int me4000_ao_ex_trig_timeout(unsigned long *arg, "ME4000:me4000_ao_ex_trig_timeout():Wait on start of state machine interrupted\n"); return -EINTR; } - if (((jiffies - ref) > (timeout * HZ / USER_HZ))) { // 2.6 has diffrent definitions for HZ in user and kernel space + /* kernel 2.6 has different definitions for HZ + * in user and kernel space */ + if ((jiffies - ref) > (timeout * HZ / USER_HZ)) { printk(KERN_ERR "ME4000:me4000_ao_ex_trig_timeout():Timeout reached\n"); return -EIO; @@ -3243,7 +3263,8 @@ static int me4000_ai_single(struct me4000_ai_single *arg, "ME4000:me4000_ai_single():Wait on start of state machine interrupted\n"); return -EINTR; } - if (((jiffies - jiffy) > (cmd.timeout * HZ / USER_HZ)) && cmd.timeout) { // 2.6 has diffrent definitions for HZ in user and kernel space + /* 2.6 has different definitions for HZ in user and kernel space */ + if (((jiffies - jiffy) > (cmd.timeout * HZ / USER_HZ)) && cmd.timeout) { printk(KERN_ERR "ME4000:me4000_ai_single():Timeout reached\n"); return -EIO; @@ -3622,9 +3643,8 @@ static int me4000_ai_config(struct me4000_ai_config *arg, me4000_outl(tmp, ai_context->ctrl_reg); /* Write the channel list */ - for (i = 0; i < cmd.channel_list.count; i++) { + for (i = 0; i < cmd.channel_list.count; i++) me4000_outl(list[i], ai_context->channel_list_reg); - } /* Setup sample and hold */ if (cmd.sh) { @@ -3663,8 +3683,7 @@ AI_CONFIG_ERR: tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_SAMPLE_HOLD); - if (list) - kfree(list); + kfree(list); return err; @@ -3774,25 +3793,22 @@ static int me4000_ai_start_ex(unsigned long *arg, if (timeout) { ref = jiffies; - while (! - (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) - { + while (!(inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) { interruptible_sleep_on_timeout(&queue, 1); if (signal_pending(current)) { printk(KERN_ERR "ME4000:me4000_ai_start_ex():Wait on start of state machine interrupted\n"); return -EINTR; } - if (((jiffies - ref) > (timeout * HZ / USER_HZ))) { // 2.6 has diffrent definitions for HZ in user and kernel space + /* 2.6 has different definitions for HZ in user and kernel space */ + if ((jiffies - ref) > (timeout * HZ / USER_HZ)) { printk(KERN_ERR "ME4000:me4000_ai_start_ex():Timeout reached\n"); return -EIO; } } } else { - while (! - (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) - { + while (!(inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) { interruptible_sleep_on_timeout(&queue, 1); if (signal_pending(current)) { printk(KERN_ERR @@ -4113,9 +4129,8 @@ static ssize_t me4000_ai_read(struct file *filep, char *buff, size_t cnt, return -EPIPE; } - if (filep->f_flags & O_NONBLOCK) { + if (filep->f_flags & O_NONBLOCK) return (k == 0) ? -EAGAIN : 2 * ret; - } CALL_PDEBUG("me4000_ai_read() is leaved\n"); return ret * 2; @@ -4254,11 +4269,10 @@ static int eeprom_write_cmd(struct me4000_ai_context *ai_context, unsigned long udelay(EEPROM_DELAY); for (i = 0; i < length; i++) { - if (cmd & ((0x1 << (length - 1)) >> i)) { + if (cmd & ((0x1 << (length - 1)) >> i)) value |= PLX_ICR_BIT_EEPROM_WRITE; - } else { + else value &= ~PLX_ICR_BIT_EEPROM_WRITE; - } /* Write to EEPROM */ me4000_outl(value, @@ -4314,11 +4328,11 @@ static unsigned short eeprom_read_cmd(struct me4000_ai_context *ai_context, /* Write the read command to the eeprom */ for (i = 0; i < length; i++) { - if (cmd & ((0x1 << (length - 1)) >> i)) { + if (cmd & ((0x1 << (length - 1)) >> i)) value |= PLX_ICR_BIT_EEPROM_WRITE; - } else { + else value &= ~PLX_ICR_BIT_EEPROM_WRITE; - } + me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR); udelay(EEPROM_DELAY); @@ -5440,8 +5454,6 @@ static irqreturn_t me4000_ao_isr(int irq, void *dev_id) int i; int c = 0; int c1 = 0; - //unsigned long before; - //unsigned long after; ISR_PDEBUG("me4000_ao_isr() is executed\n"); @@ -5493,7 +5505,6 @@ static irqreturn_t me4000_ao_isr(int irq, void *dev_id) ("me4000_ao_isr():Work done or buffer empty\n"); break; } - //rdtscl(before); if (((ao_context->fifo_reg & 0xFF) == ME4000_AO_01_FIFO_REG) || ((ao_context->fifo_reg & 0xFF) == ME4000_AO_03_FIFO_REG)) { for (i = 0; i < c1; i++) { @@ -5509,8 +5520,6 @@ static irqreturn_t me4000_ao_isr(int irq, void *dev_id) ao_context->circ_buf.buf + ao_context->circ_buf.tail, c1); - //rdtscl(after); - //printk(KERN_ERR"ME4000:me4000_ao_isr():Time lapse = %lu\n", after - before); ao_context->circ_buf.tail = (ao_context->circ_buf.tail + c1) & (ME4000_AO_BUFFER_COUNT - @@ -5542,8 +5551,10 @@ static irqreturn_t me4000_ao_isr(int irq, void *dev_id) /* If state machine is stopped, flow was interrupted */ if (!(me4000_inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM)) { printk(KERN_ERR "ME4000:me4000_ao_isr():Broken pipe\n"); - ao_context->pipe_flag = 1; // Set flag in order to inform write routine - tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_IRQ; // Disable interrupt + /* Set flag in order to inform write routine */ + ao_context->pipe_flag = 1; + /* Disable interrupt */ + tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_IRQ; } me4000_outl(tmp, ao_context->ctrl_reg); spin_unlock(&ao_context->int_lock); diff --git a/drivers/staging/meilhaus/me0600_device.c b/drivers/staging/meilhaus/me0600_device.c index 8950e47e0e86..bae17d264168 100644 --- a/drivers/staging/meilhaus/me0600_device.c +++ b/drivers/staging/meilhaus/me0600_device.c @@ -186,6 +186,7 @@ me_device_t *me0600_pci_constructor(struct pci_dev *pci_device) return (me_device_t *) me0600_device; } +EXPORT_SYMBOL(me0600_pci_constructor); // Init and exit of module. @@ -210,6 +211,3 @@ MODULE_AUTHOR MODULE_DESCRIPTION("Device Driver Module for ME-6xx Device"); MODULE_SUPPORTED_DEVICE("Meilhaus ME-6xx Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(me0600_pci_constructor); diff --git a/drivers/staging/meilhaus/me0600_dio.c b/drivers/staging/meilhaus/me0600_dio.c index 3a2775749a2c..d29303518bed 100644 --- a/drivers/staging/meilhaus/me0600_dio.c +++ b/drivers/staging/meilhaus/me0600_dio.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -91,7 +91,7 @@ static int me0600_dio_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_dio_io_single_config(me_subdevice_t * subdevice, +static int me0600_dio_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -162,7 +162,7 @@ static int me0600_dio_io_single_config(me_subdevice_t * subdevice, return err; } -static int me0600_dio_io_single_read(me_subdevice_t * subdevice, +static int me0600_dio_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -242,7 +242,7 @@ static int me0600_dio_io_single_read(me_subdevice_t * subdevice, return err; } -static int me0600_dio_io_single_write(me_subdevice_t * subdevice, +static int me0600_dio_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -329,7 +329,7 @@ static int me0600_dio_io_single_write(me_subdevice_t * subdevice, return err; } -static int me0600_dio_query_number_channels(me_subdevice_t * subdevice, +static int me0600_dio_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -337,7 +337,7 @@ static int me0600_dio_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_dio_query_subdevice_type(me_subdevice_t * subdevice, +static int me0600_dio_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -346,7 +346,7 @@ static int me0600_dio_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_dio_query_subdevice_caps(me_subdevice_t * subdevice, +static int me0600_dio_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); @@ -356,7 +356,7 @@ static int me0600_dio_query_subdevice_caps(me_subdevice_t * subdevice, me0600_dio_subdevice_t *me0600_dio_constructor(uint32_t reg_base, unsigned int dio_idx, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me0600_dio_subdevice_t *subdevice; int err; @@ -381,7 +381,7 @@ me0600_dio_subdevice_t *me0600_dio_constructor(uint32_t reg_base, kfree(subdevice); return NULL; } - // Initialize spin locks. + /* Initialize spin locks. */ spin_lock_init(&subdevice->subdevice_lock); subdevice->ctrl_reg_lock = ctrl_reg_lock; diff --git a/drivers/staging/meilhaus/me0600_ext_irq.c b/drivers/staging/meilhaus/me0600_ext_irq.c index eba18adecb72..2f6fedca3223 100644 --- a/drivers/staging/meilhaus/me0600_ext_irq.c +++ b/drivers/staging/meilhaus/me0600_ext_irq.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include @@ -337,11 +337,7 @@ static void me0600_ext_irq_destructor(struct me_subdevice *subdevice) kfree(instance); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me0600_isr(int irq, void *dev_id) -#else -static irqreturn_t me0600_isr(int irq, void *dev_id, struct pt_regs *regs) -#endif { me0600_ext_irq_subdevice_t *instance; uint32_t status; @@ -397,7 +393,7 @@ static irqreturn_t me0600_isr(int irq, void *dev_id, struct pt_regs *regs) me0600_ext_irq_subdevice_t *me0600_ext_irq_constructor(uint32_t plx_reg_base, uint32_t me0600_reg_base, - spinlock_t * intcsr_lock, + spinlock_t *intcsr_lock, unsigned ext_irq_idx, int irq) { diff --git a/drivers/staging/meilhaus/me0600_optoi.c b/drivers/staging/meilhaus/me0600_optoi.c index b6d977f228ca..43f710ffd278 100644 --- a/drivers/staging/meilhaus/me0600_optoi.c +++ b/drivers/staging/meilhaus/me0600_optoi.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -68,7 +68,7 @@ static int me0600_optoi_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_optoi_io_single_config(me_subdevice_t * subdevice, +static int me0600_optoi_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -118,7 +118,7 @@ static int me0600_optoi_io_single_config(me_subdevice_t * subdevice, return err; } -static int me0600_optoi_io_single_read(me_subdevice_t * subdevice, +static int me0600_optoi_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -169,7 +169,7 @@ static int me0600_optoi_io_single_read(me_subdevice_t * subdevice, return err; } -static int me0600_optoi_query_number_channels(me_subdevice_t * subdevice, +static int me0600_optoi_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -177,7 +177,7 @@ static int me0600_optoi_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_optoi_query_subdevice_type(me_subdevice_t * subdevice, +static int me0600_optoi_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -186,7 +186,7 @@ static int me0600_optoi_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_optoi_query_subdevice_caps(me_subdevice_t * subdevice, +static int me0600_optoi_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); @@ -219,7 +219,7 @@ me0600_optoi_subdevice_t *me0600_optoi_constructor(uint32_t reg_base) kfree(subdevice); return NULL; } - // Initialize spin locks. + /* Initialize spin locks. */ spin_lock_init(&subdevice->subdevice_lock); /* Save the subdevice index */ diff --git a/drivers/staging/meilhaus/me0600_relay.c b/drivers/staging/meilhaus/me0600_relay.c index 2665c69addd2..03835e3df254 100644 --- a/drivers/staging/meilhaus/me0600_relay.c +++ b/drivers/staging/meilhaus/me0600_relay.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -85,7 +85,7 @@ static int me0600_relay_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_relay_io_single_config(me_subdevice_t * subdevice, +static int me0600_relay_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -135,7 +135,7 @@ static int me0600_relay_io_single_config(me_subdevice_t * subdevice, return err; } -static int me0600_relay_io_single_read(me_subdevice_t * subdevice, +static int me0600_relay_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -203,7 +203,7 @@ static int me0600_relay_io_single_read(me_subdevice_t * subdevice, return err; } -static int me0600_relay_io_single_write(me_subdevice_t * subdevice, +static int me0600_relay_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -279,7 +279,7 @@ static int me0600_relay_io_single_write(me_subdevice_t * subdevice, return err; } -static int me0600_relay_query_number_channels(me_subdevice_t * subdevice, +static int me0600_relay_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -287,7 +287,7 @@ static int me0600_relay_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_relay_query_subdevice_type(me_subdevice_t * subdevice, +static int me0600_relay_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -296,7 +296,7 @@ static int me0600_relay_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_relay_query_subdevice_caps(me_subdevice_t * subdevice, +static int me0600_relay_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); diff --git a/drivers/staging/meilhaus/me0600_ttli.c b/drivers/staging/meilhaus/me0600_ttli.c index ab8e13b6f329..7d970f584cc7 100644 --- a/drivers/staging/meilhaus/me0600_ttli.c +++ b/drivers/staging/meilhaus/me0600_ttli.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -67,7 +67,7 @@ static int me0600_ttli_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_ttli_io_single_config(me_subdevice_t * subdevice, +static int me0600_ttli_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -116,7 +116,7 @@ static int me0600_ttli_io_single_config(me_subdevice_t * subdevice, return err; } -static int me0600_ttli_io_single_read(me_subdevice_t * subdevice, +static int me0600_ttli_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -164,7 +164,7 @@ static int me0600_ttli_io_single_read(me_subdevice_t * subdevice, return err; } -static int me0600_ttli_query_number_channels(me_subdevice_t * subdevice, +static int me0600_ttli_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -172,7 +172,7 @@ static int me0600_ttli_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_ttli_query_subdevice_type(me_subdevice_t * subdevice, +static int me0600_ttli_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -181,7 +181,7 @@ static int me0600_ttli_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0600_ttli_query_subdevice_caps(me_subdevice_t * subdevice, +static int me0600_ttli_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); diff --git a/drivers/staging/meilhaus/me0900_device.c b/drivers/staging/meilhaus/me0900_device.c index 764d5d307c44..e9c6884b5d23 100644 --- a/drivers/staging/meilhaus/me0900_device.c +++ b/drivers/staging/meilhaus/me0900_device.c @@ -152,6 +152,7 @@ me_device_t *me0900_pci_constructor(struct pci_dev *pci_device) return (me_device_t *) me0900_device; } +EXPORT_SYMBOL(me0900_pci_constructor); // Init and exit of module. @@ -175,6 +176,3 @@ MODULE_AUTHOR MODULE_DESCRIPTION("Device Driver Module for ME-9x Device"); MODULE_SUPPORTED_DEVICE("Meilhaus ME-9x Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(me0900_pci_constructor); diff --git a/drivers/staging/meilhaus/me0900_di.c b/drivers/staging/meilhaus/me0900_di.c index d7d7394f800a..4665b2acbea4 100644 --- a/drivers/staging/meilhaus/me0900_di.c +++ b/drivers/staging/meilhaus/me0900_di.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include #include @@ -71,7 +71,7 @@ static int me0900_di_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me0900_di_io_single_config(me_subdevice_t * subdevice, +static int me0900_di_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -115,7 +115,7 @@ static int me0900_di_io_single_config(me_subdevice_t * subdevice, return err; } -static int me0900_di_io_single_read(me_subdevice_t * subdevice, +static int me0900_di_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -161,7 +161,7 @@ static int me0900_di_io_single_read(me_subdevice_t * subdevice, return err; } -static int me0900_di_query_number_channels(me_subdevice_t * subdevice, +static int me0900_di_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -169,7 +169,7 @@ static int me0900_di_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0900_di_query_subdevice_type(me_subdevice_t * subdevice, +static int me0900_di_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -178,7 +178,7 @@ static int me0900_di_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0900_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me0900_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); *caps = 0; diff --git a/drivers/staging/meilhaus/me0900_do.c b/drivers/staging/meilhaus/me0900_do.c index b5b9c3a98c94..a2275faf1a0c 100644 --- a/drivers/staging/meilhaus/me0900_do.c +++ b/drivers/staging/meilhaus/me0900_do.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -81,7 +81,7 @@ static int me0900_do_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me0900_do_io_single_config(me_subdevice_t * subdevice, +static int me0900_do_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -125,7 +125,7 @@ static int me0900_do_io_single_config(me_subdevice_t * subdevice, return err; } -static int me0900_do_io_single_read(me_subdevice_t * subdevice, +static int me0900_do_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -171,7 +171,7 @@ static int me0900_do_io_single_read(me_subdevice_t * subdevice, return err; } -static int me0900_do_io_single_write(me_subdevice_t * subdevice, +static int me0900_do_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -223,7 +223,7 @@ static int me0900_do_io_single_write(me_subdevice_t * subdevice, return err; } -static int me0900_do_query_number_channels(me_subdevice_t * subdevice, +static int me0900_do_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -231,7 +231,7 @@ static int me0900_do_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0900_do_query_subdevice_type(me_subdevice_t * subdevice, +static int me0900_do_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -240,7 +240,7 @@ static int me0900_do_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me0900_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me0900_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); *caps = 0; diff --git a/drivers/staging/meilhaus/me1000_device.c b/drivers/staging/meilhaus/me1000_device.c index c44e214af26c..cf0fb92f24c6 100644 --- a/drivers/staging/meilhaus/me1000_device.c +++ b/drivers/staging/meilhaus/me1000_device.c @@ -49,8 +49,8 @@ #include "mesubdevice.h" #include "me1000_dio.h" -static int me1000_config_load(me_device_t * me_device, struct file *filep, - me_cfg_device_entry_t * config) +static int me1000_config_load(me_device_t *me_device, struct file *filep, + me_cfg_device_entry_t *config) { me1000_device_t *me1000_device; me1000_dio_subdevice_t *dio; @@ -181,6 +181,7 @@ me_device_t *me1000_pci_constructor(struct pci_dev * pci_device) return (me_device_t *) me1000_device; } +EXPORT_SYMBOL(me1000_pci_constructor); // Init and exit of module. static int __init me1000_init(void) @@ -203,6 +204,3 @@ MODULE_AUTHOR MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-1000 Devices"); MODULE_SUPPORTED_DEVICE("Meilhaus ME-1000 Digital I/O Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(me1000_pci_constructor); diff --git a/drivers/staging/meilhaus/me1000_dio.c b/drivers/staging/meilhaus/me1000_dio.c index 87605a9108ae..2d7ed07d1f39 100644 --- a/drivers/staging/meilhaus/me1000_dio.c +++ b/drivers/staging/meilhaus/me1000_dio.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -371,7 +371,7 @@ static int me1000_dio_query_subdevice_caps(struct me_subdevice *subdevice, me1000_dio_subdevice_t *me1000_dio_constructor(uint32_t reg_base, unsigned int dio_idx, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me1000_dio_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me1400_device.c b/drivers/staging/meilhaus/me1400_device.c index b95bb4fce6ab..ca7498b9056c 100644 --- a/drivers/staging/meilhaus/me1400_device.c +++ b/drivers/staging/meilhaus/me1400_device.c @@ -228,6 +228,7 @@ me_device_t *me1400_pci_constructor(struct pci_dev *pci_device) return (me_device_t *) me1400_device; } +EXPORT_SYMBOL(me1400_pci_constructor); // Init and exit of module. @@ -251,6 +252,3 @@ MODULE_AUTHOR MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-14xx devices"); MODULE_SUPPORTED_DEVICE("Meilhaus ME-14xx MIO devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(me1400_pci_constructor); diff --git a/drivers/staging/meilhaus/me1400_ext_irq.c b/drivers/staging/meilhaus/me1400_ext_irq.c index b4df7cc58ab7..0dc6b4519b5b 100644 --- a/drivers/staging/meilhaus/me1400_ext_irq.c +++ b/drivers/staging/meilhaus/me1400_ext_irq.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include @@ -323,12 +323,7 @@ static int me1400_ext_irq_query_subdevice_caps_args(struct me_subdevice return ME_ERRNO_NOT_SUPPORTED; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me1400_ext_irq_isr(int irq, void *dev_id) -#else -static irqreturn_t me1400_ext_irq_isr(int irq, void *dev_id, - struct pt_regs *regs) -#endif { me1400_ext_irq_subdevice_t *instance; uint32_t status; diff --git a/drivers/staging/meilhaus/me1600_ao.c b/drivers/staging/meilhaus/me1600_ao.c index d127c6b00307..12e3c70e982a 100644 --- a/drivers/staging/meilhaus/me1600_ao.c +++ b/drivers/staging/meilhaus/me1600_ao.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include @@ -55,36 +55,32 @@ static void me1600_ao_destructor(struct me_subdevice *subdevice); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void me1600_ao_work_control_task(void *subdevice); -#else static void me1600_ao_work_control_task(struct work_struct *work); -#endif -static int me1600_ao_io_reset_subdevice(me_subdevice_t * subdevice, +static int me1600_ao_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags); -static int me1600_ao_io_single_config(me_subdevice_t * subdevice, +static int me1600_ao_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, int ref, int trig_chan, int trig_type, int trig_edge, int flags); -static int me1600_ao_io_single_read(me_subdevice_t * subdevice, +static int me1600_ao_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags); -static int me1600_ao_io_single_write(me_subdevice_t * subdevice, +static int me1600_ao_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags); -static int me1600_ao_query_number_channels(me_subdevice_t * subdevice, +static int me1600_ao_query_number_channels(me_subdevice_t *subdevice, int *number); -static int me1600_ao_query_subdevice_type(me_subdevice_t * subdevice, int *type, +static int me1600_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype); -static int me1600_ao_query_subdevice_caps(me_subdevice_t * subdevice, +static int me1600_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps); -static int me1600_ao_query_range_by_min_max(me_subdevice_t * subdevice, +static int me1600_ao_query_range_by_min_max(me_subdevice_t *subdevice, int unit, int *min, int *max, int *maxdata, int *range); -static int me1600_ao_query_number_ranges(me_subdevice_t * subdevice, int unit, +static int me1600_ao_query_number_ranges(me_subdevice_t *subdevice, int unit, int *count); -static int me1600_ao_query_range_info(me_subdevice_t * subdevice, int range, +static int me1600_ao_query_range_info(me_subdevice_t *subdevice, int range, int *unit, int *min, int *max, int *maxdata); @@ -94,10 +90,9 @@ static int me1600_ao_query_range_info(me_subdevice_t * subdevice, int range, me1600_ao_subdevice_t *me1600_ao_constructor(uint32_t reg_base, unsigned int ao_idx, int curr, - spinlock_t * config_regs_lock, - spinlock_t * ao_shadows_lock, - me1600_ao_shadow_t * - ao_regs_shadows, + spinlock_t *config_regs_lock, + spinlock_t *ao_shadows_lock, + me1600_ao_shadow_t *ao_regs_shadows, struct workqueue_struct *me1600_wq) { me1600_ao_subdevice_t *subdevice; @@ -200,13 +195,8 @@ me1600_ao_subdevice_t *me1600_ao_constructor(uint32_t reg_base, subdevice->me1600_workqueue = me1600_wq; /* workqueue API changed in kernel 2.6.20 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) - INIT_WORK(&subdevice->ao_control_task, me1600_ao_work_control_task, - (void *)subdevice); -#else INIT_DELAYED_WORK(&subdevice->ao_control_task, me1600_ao_work_control_task); -#endif return subdevice; } @@ -231,7 +221,7 @@ static void me1600_ao_destructor(struct me_subdevice *subdevice) } } -static int me1600_ao_io_reset_subdevice(me_subdevice_t * subdevice, +static int me1600_ao_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags) { me1600_ao_subdevice_t *instance; @@ -313,7 +303,7 @@ static int me1600_ao_io_reset_subdevice(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me1600_ao_io_single_config(me_subdevice_t * subdevice, +static int me1600_ao_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -545,7 +535,7 @@ static int me1600_ao_io_single_config(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me1600_ao_io_single_read(me_subdevice_t * subdevice, +static int me1600_ao_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -612,7 +602,7 @@ static int me1600_ao_io_single_read(me_subdevice_t * subdevice, return err; } -static int me1600_ao_io_single_write(me_subdevice_t * subdevice, +static int me1600_ao_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -756,7 +746,9 @@ static int me1600_ao_io_single_write(me_subdevice_t * subdevice, queue_delayed_work(instance->me1600_workqueue, &instance->ao_control_task, 1); - if ((!flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING) && ((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { //Blocking mode. Wait for software trigger. + if ((!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) && + ((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { + /* Blocking mode. Wait for software trigger. */ if (time_out) { delay = (time_out * HZ) / 1000; if (delay == 0) @@ -793,7 +785,7 @@ static int me1600_ao_io_single_write(me_subdevice_t * subdevice, return err; } -static int me1600_ao_query_number_channels(me_subdevice_t * subdevice, +static int me1600_ao_query_number_channels(me_subdevice_t *subdevice, int *number) { me1600_ao_subdevice_t *instance; @@ -805,7 +797,7 @@ static int me1600_ao_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me1600_ao_query_subdevice_type(me_subdevice_t * subdevice, int *type, +static int me1600_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { me1600_ao_subdevice_t *instance; @@ -818,14 +810,14 @@ static int me1600_ao_query_subdevice_type(me_subdevice_t * subdevice, int *type, return ME_ERRNO_SUCCESS; } -static int me1600_ao_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me1600_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); *caps = ME_CAPS_AO_TRIG_SYNCHRONOUS; return ME_ERRNO_SUCCESS; } -static int me1600_ao_query_range_by_min_max(me_subdevice_t * subdevice, +static int me1600_ao_query_range_by_min_max(me_subdevice_t *subdevice, int unit, int *min, int *max, int *maxdata, int *range) @@ -903,7 +895,7 @@ static int me1600_ao_query_range_by_min_max(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me1600_ao_query_number_ranges(me_subdevice_t * subdevice, +static int me1600_ao_query_number_ranges(me_subdevice_t *subdevice, int unit, int *count) { me1600_ao_subdevice_t *instance; @@ -928,7 +920,7 @@ static int me1600_ao_query_number_ranges(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me1600_ao_query_range_info(me_subdevice_t * subdevice, +static int me1600_ao_query_range_info(me_subdevice_t *subdevice, int range, int *unit, int *min, int *max, int *maxdata) @@ -960,22 +952,14 @@ static int me1600_ao_query_range_info(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void me1600_ao_work_control_task(void *subdevice) -#else static void me1600_ao_work_control_task(struct work_struct *work) -#endif { me1600_ao_subdevice_t *instance; int reschedule = 1; int signaling = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - instance = (me1600_ao_subdevice_t *) subdevice; -#else instance = container_of((void *)work, me1600_ao_subdevice_t, ao_control_task); -#endif PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies, instance->ao_idx); diff --git a/drivers/staging/meilhaus/me1600_ao.h b/drivers/staging/meilhaus/me1600_ao.h index b82bf5a1676e..4827dcb4bf44 100644 --- a/drivers/staging/meilhaus/me1600_ao.h +++ b/drivers/staging/meilhaus/me1600_ao.h @@ -98,11 +98,7 @@ typedef struct me1600_ao_subdevice { wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ me1600_ao_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */ struct workqueue_struct *me1600_workqueue; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct ao_control_task; -#else struct delayed_work ao_control_task; -#endif volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */ } me1600_ao_subdevice_t; diff --git a/drivers/staging/meilhaus/me1600_device.c b/drivers/staging/meilhaus/me1600_device.c index 3bc2cb1dc869..c244e984049e 100644 --- a/drivers/staging/meilhaus/me1600_device.c +++ b/drivers/staging/meilhaus/me1600_device.c @@ -48,7 +48,7 @@ #include "mesubdevice.h" #include "me1600_device.h" -static void me1600_set_registry(me1600_device_t * subdevice, uint32_t reg_base); +static void me1600_set_registry(me1600_device_t *subdevice, uint32_t reg_base); static void me1600_destructor(struct me_device *device); /** @@ -142,6 +142,7 @@ me_device_t *me1600_pci_constructor(struct pci_dev *pci_device) return (me_device_t *) me1600_device; } +EXPORT_SYMBOL(me1600_pci_constructor); static void me1600_destructor(struct me_device *device) { @@ -157,7 +158,7 @@ static void me1600_destructor(struct me_device *device) kfree(me1600_device); } -static void me1600_set_registry(me1600_device_t * subdevice, uint32_t reg_base) +static void me1600_set_registry(me1600_device_t *subdevice, uint32_t reg_base) { // Create shadow structure. if (subdevice->ao_regs_shadows.count >= 1) { subdevice->ao_regs_shadows.registry[0] = @@ -256,6 +257,3 @@ MODULE_AUTHOR MODULE_DESCRIPTION("Device Driver Module for ME-1600 Device"); MODULE_SUPPORTED_DEVICE("Meilhaus ME-1600 Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(me1600_pci_constructor); diff --git a/drivers/staging/meilhaus/me4600_ai.c b/drivers/staging/meilhaus/me4600_ai.c index 0a8c9d737e90..a3cfef09a4de 100644 --- a/drivers/staging/meilhaus/me4600_ai.c +++ b/drivers/staging/meilhaus/me4600_ai.c @@ -36,8 +36,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -57,10 +57,10 @@ */ static void me4600_ai_destructor(struct me_subdevice *subdevice); -static int me4600_ai_io_reset_subdevice(me_subdevice_t * subdevice, +static int me4600_ai_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags); -static int me4600_ai_io_single_config(me_subdevice_t * subdevice, +static int me4600_ai_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -68,120 +68,112 @@ static int me4600_ai_io_single_config(me_subdevice_t * subdevice, int trig_chan, int trig_type, int trig_edge, int flags); -static int me4600_ai_io_single_read(me_subdevice_t * subdevice, +static int me4600_ai_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags); -static int me4600_ai_io_stream_config(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_config(me_subdevice_t *subdevice, struct file *filep, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags); -static int me4600_ai_io_stream_read(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_read(me_subdevice_t *subdevice, struct file *filep, int read_mode, int *values, int *count, int flags); -static int me4600_ai_io_stream_new_values(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_new_values(me_subdevice_t *subdevice, struct file *filep, int time_out, int *count, int flags); -static int inline me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * +static inline int me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * instance, int *values, const int count, const int flags); -static int me4600_ai_io_stream_start(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_start(me_subdevice_t *subdevice, struct file *filep, int start_mode, int time_out, int flags); -static int me4600_ai_io_stream_stop(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_stop(me_subdevice_t *subdevice, struct file *filep, int stop_mode, int flags); -static int me4600_ai_io_stream_status(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_status(me_subdevice_t *subdevice, struct file *filep, int wait, int *status, int *values, int flags); -static int me4600_ai_query_range_by_min_max(me_subdevice_t * subdevice, +static int me4600_ai_query_range_by_min_max(me_subdevice_t *subdevice, int unit, int *min, int *max, int *maxdata, int *range); -static int me4600_ai_query_number_ranges(me_subdevice_t * subdevice, +static int me4600_ai_query_number_ranges(me_subdevice_t *subdevice, int unit, int *count); -static int me4600_ai_query_range_info(me_subdevice_t * subdevice, +static int me4600_ai_query_range_info(me_subdevice_t *subdevice, int range, int *unit, int *min, int *max, int *maxdata); -static int me4600_ai_query_timer(me_subdevice_t * subdevice, +static int me4600_ai_query_timer(me_subdevice_t *subdevice, int timer, int *base_frequency, long long *min_ticks, long long *max_ticks); -static int me4600_ai_query_number_channels(me_subdevice_t * subdevice, +static int me4600_ai_query_number_channels(me_subdevice_t *subdevice, int *number); -static int me4600_ai_query_subdevice_type(me_subdevice_t * subdevice, +static int me4600_ai_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype); -static int me4600_ai_query_subdevice_caps(me_subdevice_t * subdevice, +static int me4600_ai_query_subdevice_caps(me_subdevice_t *subdevice, int *caps); static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice, int cap, int *args, int count); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me4600_ai_isr(int irq, void *dev_id); -#else -static irqreturn_t me4600_ai_isr(int irq, void *dev_id, struct pt_regs *regs); -#endif -static int ai_mux_toggler(me4600_ai_subdevice_t * subdevice); +static int ai_mux_toggler(me4600_ai_subdevice_t *subdevice); /** Immidiate stop. * Reset all IRQ's sources. (block laches) * Preserve FIFO */ -static int ai_stop_immediately(me4600_ai_subdevice_t * instance); +static int ai_stop_immediately(me4600_ai_subdevice_t *instance); /** Immidiate stop. * Reset all IRQ's sources. (block laches) * Reset data FIFO */ -void inline ai_stop_isr(me4600_ai_subdevice_t * instance); +inline void ai_stop_isr(me4600_ai_subdevice_t *instance); /** Interrupt logics. * Read datas * Reset latches */ -void ai_limited_isr(me4600_ai_subdevice_t * instance, const uint32_t irq_status, +void ai_limited_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, const uint32_t ctrl_status); -void ai_infinite_isr(me4600_ai_subdevice_t * instance, +void ai_infinite_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, const uint32_t ctrl_status); /** Last chunck of datas. We must reschedule sample counter. * Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts. * When threshold is wrongly set some IRQ are lost.(!!!) */ -void inline ai_reschedule_SC(me4600_ai_subdevice_t * instance); +inline void ai_reschedule_SC(me4600_ai_subdevice_t *instance); /** Read datas from FIFO and copy them to buffer */ -static int inline ai_read_data(me4600_ai_subdevice_t * instance, +static inline int ai_read_data(me4600_ai_subdevice_t *instance, const int count); /** Copy rest of data from fifo to circular buffer.*/ -static int inline ai_read_data_pooling(me4600_ai_subdevice_t * instance); +static inline int ai_read_data_pooling(me4600_ai_subdevice_t *instance); /** Set ISM to next state for infinite data aqusation mode*/ -void inline ai_infinite_ISM(me4600_ai_subdevice_t * instance); +inline void ai_infinite_ISM(me4600_ai_subdevice_t *instance); /** Set ISM to next state for define amount of data aqusation mode*/ -void inline ai_limited_ISM(me4600_ai_subdevice_t * instance, +inline void ai_limited_ISM(me4600_ai_subdevice_t *instance, uint32_t irq_status); /** Set ISM to next stage for limited mode */ -void inline ai_data_acquisition_logic(me4600_ai_subdevice_t * instance); +inline void ai_data_acquisition_logic(me4600_ai_subdevice_t *instance); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void me4600_ai_work_control_task(void *subdevice); -#else static void me4600_ai_work_control_task(struct work_struct *work); -#endif /* Definitions */ @@ -192,7 +184,7 @@ me4600_ai_subdevice_t *me4600_ai_constructor(uint32_t reg_base, int isolated, int sh, int irq, - spinlock_t * ctrl_reg_lock, + spinlock_t *ctrl_reg_lock, struct workqueue_struct *me4600_wq) { me4600_ai_subdevice_t *subdevice; @@ -360,13 +352,8 @@ me4600_ai_subdevice_t *me4600_ai_constructor(uint32_t reg_base, subdevice->me4600_workqueue = me4600_wq; /* workqueue API changed in kernel 2.6.20 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) - INIT_WORK(&subdevice->ai_control_task, me4600_ai_work_control_task, - (void *)subdevice); -#else INIT_DELAYED_WORK(&subdevice->ai_control_task, me4600_ai_work_control_task); -#endif return subdevice; } @@ -397,7 +384,7 @@ static void me4600_ai_destructor(struct me_subdevice *subdevice) kfree(instance); } -static int me4600_ai_io_reset_subdevice(me_subdevice_t * subdevice, +static int me4600_ai_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags) { me4600_ai_subdevice_t *instance; @@ -519,7 +506,7 @@ static int me4600_ai_io_reset_subdevice(me_subdevice_t * subdevice, return err; } -static int me4600_ai_io_single_config(me_subdevice_t * subdevice, +static int me4600_ai_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -709,7 +696,7 @@ static int me4600_ai_io_single_config(me_subdevice_t * subdevice, return err; } -static int me4600_ai_io_single_read(me_subdevice_t * subdevice, +static int me4600_ai_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -915,11 +902,11 @@ static int me4600_ai_io_single_read(me_subdevice_t * subdevice, return err; } -static int me4600_ai_io_stream_config(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_config(me_subdevice_t *subdevice, struct file *filep, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags) { me4600_ai_subdevice_t *instance; @@ -1586,15 +1573,15 @@ static int me4600_ai_io_stream_config(me_subdevice_t * subdevice, ME_SINGLE_CHANNEL_NOT_CONFIGURED; } - VERIFY_ERROR: // Error in code. Wrong setting check. This should never ever happend! +VERIFY_ERROR: // Error in code. Wrong setting check. This should never ever happend! spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - ERROR: // Error in settings. +ERROR: // Error in settings. ME_SUBDEVICE_EXIT; return err; } -static int me4600_ai_io_stream_new_values(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_new_values(me_subdevice_t *subdevice, struct file *filep, int time_out, int *count, int flags) { @@ -1677,7 +1664,7 @@ static int me4600_ai_io_stream_new_values(me_subdevice_t * subdevice, return err; } -static int inline me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * +static inline int me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * instance, int *values, const int count, const int flags) @@ -1712,7 +1699,7 @@ static int inline me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * return n; } -static int me4600_ai_io_stream_read(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_read(me_subdevice_t *subdevice, struct file *filep, int read_mode, int *values, int *count, int flags) @@ -1838,7 +1825,7 @@ static int me4600_ai_io_stream_read(me_subdevice_t * subdevice, * @param instance The subdevice instance (pointer). */ -static int ai_stop_immediately(me4600_ai_subdevice_t * instance) +static int ai_stop_immediately(me4600_ai_subdevice_t *instance) { unsigned long cpu_flags = 0; volatile uint32_t ctrl; @@ -1877,7 +1864,7 @@ static int ai_stop_immediately(me4600_ai_subdevice_t * instance) return ME_ERRNO_SUCCESS; } -static int me4600_ai_io_stream_start(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_start(me_subdevice_t *subdevice, struct file *filep, int start_mode, int time_out, int flags) { @@ -2055,13 +2042,13 @@ static int me4600_ai_io_stream_start(me_subdevice_t * subdevice, (tmp & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : "work"); #endif - ERROR: +ERROR: ME_SUBDEVICE_EXIT; return err; } -static int me4600_ai_io_stream_status(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_status(me_subdevice_t *subdevice, struct file *filep, int wait, int *status, int *values, int flags) @@ -2139,7 +2126,7 @@ static int me4600_ai_io_stream_status(me_subdevice_t * subdevice, return err; } -static int me4600_ai_io_stream_stop(me_subdevice_t * subdevice, +static int me4600_ai_io_stream_stop(me_subdevice_t *subdevice, struct file *filep, int stop_mode, int flags) { @@ -2236,7 +2223,7 @@ static int me4600_ai_io_stream_stop(me_subdevice_t * subdevice, return ret; } -static int me4600_ai_query_range_by_min_max(me_subdevice_t * subdevice, +static int me4600_ai_query_range_by_min_max(me_subdevice_t *subdevice, int unit, int *min, int *max, int *maxdata, int *range) @@ -2288,7 +2275,7 @@ static int me4600_ai_query_range_by_min_max(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ai_query_number_ranges(me_subdevice_t * subdevice, +static int me4600_ai_query_number_ranges(me_subdevice_t *subdevice, int unit, int *count) { me4600_ai_subdevice_t *instance; @@ -2306,7 +2293,7 @@ static int me4600_ai_query_number_ranges(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ai_query_range_info(me_subdevice_t * subdevice, +static int me4600_ai_query_range_info(me_subdevice_t *subdevice, int range, int *unit, int *min, int *max, int *maxdata) @@ -2330,7 +2317,7 @@ static int me4600_ai_query_range_info(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ai_query_timer(me_subdevice_t * subdevice, +static int me4600_ai_query_timer(me_subdevice_t *subdevice, int timer, int *base_frequency, long long *min_ticks, long long *max_ticks) @@ -2370,7 +2357,7 @@ static int me4600_ai_query_timer(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ai_query_number_channels(me_subdevice_t * subdevice, +static int me4600_ai_query_number_channels(me_subdevice_t *subdevice, int *number) { me4600_ai_subdevice_t *instance; @@ -2383,7 +2370,7 @@ static int me4600_ai_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ai_query_subdevice_type(me_subdevice_t * subdevice, +static int me4600_ai_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed. idx=0\n"); @@ -2394,7 +2381,7 @@ static int me4600_ai_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ai_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me4600_ai_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed. idx=0\n"); @@ -2439,7 +2426,7 @@ static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice, return err; } -void ai_limited_isr(me4600_ai_subdevice_t * instance, const uint32_t irq_status, +void ai_limited_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, const uint32_t ctrl_status) { int to_read; @@ -2547,7 +2534,7 @@ void ai_limited_isr(me4600_ai_subdevice_t * instance, const uint32_t irq_status, } } -void ai_infinite_isr(me4600_ai_subdevice_t * instance, +void ai_infinite_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, const uint32_t ctrl_status) { int to_read; @@ -2603,11 +2590,7 @@ void ai_infinite_isr(me4600_ai_subdevice_t * instance, } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me4600_ai_isr(int irq, void *dev_id) -#else -static irqreturn_t me4600_ai_isr(int irq, void *dev_id, struct pt_regs *regs) -#endif { /// @note This is time critical function! uint32_t irq_status; uint32_t ctrl_status; @@ -2803,7 +2786,7 @@ static irqreturn_t me4600_ai_isr(int irq, void *dev_id, struct pt_regs *regs) * * @param instance The subdevice instance (pointer). */ -void inline ai_stop_isr(me4600_ai_subdevice_t * instance) +inline void ai_stop_isr(me4600_ai_subdevice_t *instance) { /// @note This is soft time critical function! register uint32_t tmp; @@ -2829,7 +2812,7 @@ void inline ai_stop_isr(me4600_ai_subdevice_t * instance) * @return On success: Number of copied values. * @return On error: -ME_ERRNO_RING_BUFFER_OVERFLOW. */ -static int inline ai_read_data(me4600_ai_subdevice_t * instance, +static inline int ai_read_data(me4600_ai_subdevice_t *instance, const int count) { /// @note This is time critical function! int c = count; @@ -2875,7 +2858,7 @@ static int inline ai_read_data(me4600_ai_subdevice_t * instance, return copied; } -void inline ai_infinite_ISM(me4600_ai_subdevice_t * instance) +inline void ai_infinite_ISM(me4600_ai_subdevice_t *instance) { /// @note This is time critical function! register volatile uint32_t ctrl_set, ctrl_reset, tmp; @@ -2925,7 +2908,7 @@ void inline ai_infinite_ISM(me4600_ai_subdevice_t * instance) } -void inline ai_limited_ISM(me4600_ai_subdevice_t * instance, +inline void ai_limited_ISM(me4600_ai_subdevice_t *instance, uint32_t irq_status) { /// @note This is time critical function! register volatile uint32_t ctrl_set, ctrl_reset = 0xFFFFFFFF, tmp; @@ -2986,7 +2969,7 @@ void inline ai_limited_ISM(me4600_ai_subdevice_t * instance, * Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts. * @warning When threshold is wrongly set some IRQ are lost.(!!!) */ -void inline ai_reschedule_SC(me4600_ai_subdevice_t * instance) +inline void ai_reschedule_SC(me4600_ai_subdevice_t *instance) { register uint32_t rest; @@ -3018,7 +3001,7 @@ void inline ai_reschedule_SC(me4600_ai_subdevice_t * instance) } /** Start the ISM. All must be reseted before enter to this function. */ -void inline ai_data_acquisition_logic(me4600_ai_subdevice_t * instance) +inline void ai_data_acquisition_logic(me4600_ai_subdevice_t *instance) { register uint32_t tmp; @@ -3166,7 +3149,7 @@ void inline ai_data_acquisition_logic(me4600_ai_subdevice_t * instance) } } -static int ai_mux_toggler(me4600_ai_subdevice_t * instance) +static int ai_mux_toggler(me4600_ai_subdevice_t *instance) { uint32_t tmp; @@ -3276,7 +3259,7 @@ static int ai_mux_toggler(me4600_ai_subdevice_t * instance) * @return On success: Number of copied values. * @return On error: Negative error code -ME_ERRNO_RING_BUFFER_OVERFLOW. */ -static int inline ai_read_data_pooling(me4600_ai_subdevice_t * instance) +static inline int ai_read_data_pooling(me4600_ai_subdevice_t *instance) { /// @note This is time critical function! int empty_space; int copied = 0; @@ -3310,11 +3293,7 @@ static int inline ai_read_data_pooling(me4600_ai_subdevice_t * instance) return (!status) ? copied : -ME_ERRNO_RING_BUFFER_OVERFLOW; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void me4600_ai_work_control_task(void *subdevice) -#else static void me4600_ai_work_control_task(struct work_struct *work) -#endif { me4600_ai_subdevice_t *instance; uint32_t status; @@ -3323,12 +3302,8 @@ static void me4600_ai_work_control_task(struct work_struct *work) int reschedule = 0; int signaling = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - instance = (me4600_ai_subdevice_t *) subdevice; -#else instance = container_of((void *)work, me4600_ai_subdevice_t, ai_control_task); -#endif PINFO("<%s: %ld> executed.\n", __func__, jiffies); status = inl(instance->status_reg); diff --git a/drivers/staging/meilhaus/me4600_ai.h b/drivers/staging/meilhaus/me4600_ai.h index 1d5a1b9c6f91..106e1959f9f1 100644 --- a/drivers/staging/meilhaus/me4600_ai.h +++ b/drivers/staging/meilhaus/me4600_ai.h @@ -139,11 +139,7 @@ typedef struct me4600_ai_subdevice { wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ struct workqueue_struct *me4600_workqueue; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct ai_control_task; -#else struct delayed_work ai_control_task; -#endif volatile int ai_control_task_flag; /**< Flag controling reexecuting of control task */ diff --git a/drivers/staging/meilhaus/me4600_ao.c b/drivers/staging/meilhaus/me4600_ao.c index e2bec8229abd..eb472692a7c5 100644 --- a/drivers/staging/meilhaus/me4600_ao.c +++ b/drivers/staging/meilhaus/me4600_ao.c @@ -38,8 +38,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -58,31 +58,31 @@ /* Defines */ -static int me4600_ao_query_range_by_min_max(me_subdevice_t * subdevice, +static int me4600_ao_query_range_by_min_max(me_subdevice_t *subdevice, int unit, int *min, int *max, int *maxdata, int *range); -static int me4600_ao_query_number_ranges(me_subdevice_t * subdevice, +static int me4600_ao_query_number_ranges(me_subdevice_t *subdevice, int unit, int *count); -static int me4600_ao_query_range_info(me_subdevice_t * subdevice, +static int me4600_ao_query_range_info(me_subdevice_t *subdevice, int range, int *unit, int *min, int *max, int *maxdata); -static int me4600_ao_query_timer(me_subdevice_t * subdevice, +static int me4600_ao_query_timer(me_subdevice_t *subdevice, int timer, int *base_frequency, long long *min_ticks, long long *max_ticks); -static int me4600_ao_query_number_channels(me_subdevice_t * subdevice, +static int me4600_ao_query_number_channels(me_subdevice_t *subdevice, int *number); -static int me4600_ao_query_subdevice_type(me_subdevice_t * subdevice, +static int me4600_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype); -static int me4600_ao_query_subdevice_caps(me_subdevice_t * subdevice, +static int me4600_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps); static int me4600_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, @@ -105,12 +105,12 @@ static void me4600_ao_destructor(struct me_subdevice *subdevice); /** Reset subdevice. Stop all actions. Reset registry. Disable FIFO. Set output to 0V and status to 'none'. */ -static int me4600_ao_io_reset_subdevice(me_subdevice_t * subdevice, +static int me4600_ao_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags); /** Set output as single */ -static int me4600_ao_io_single_config(me_subdevice_t * subdevice, +static int me4600_ao_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -120,103 +120,93 @@ static int me4600_ao_io_single_config(me_subdevice_t * subdevice, /** Pass to user actual value of output. */ -static int me4600_ao_io_single_read(me_subdevice_t * subdevice, +static int me4600_ao_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags); /** Write to output requed value. */ -static int me4600_ao_io_single_write(me_subdevice_t * subdevice, +static int me4600_ao_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags); /** Set output as streamed device. */ -static int me4600_ao_io_stream_config(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_config(me_subdevice_t *subdevice, struct file *filep, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags); /** Wait for / Check empty space in buffer. */ -static int me4600_ao_io_stream_new_values(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_new_values(me_subdevice_t *subdevice, struct file *filep, int time_out, int *count, int flags); /** Start streaming. */ -static int me4600_ao_io_stream_start(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_start(me_subdevice_t *subdevice, struct file *filep, int start_mode, int time_out, int flags); /** Check actual state. / Wait for end. */ -static int me4600_ao_io_stream_status(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_status(me_subdevice_t *subdevice, struct file *filep, int wait, int *status, int *values, int flags); /** Stop streaming. */ -static int me4600_ao_io_stream_stop(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_stop(me_subdevice_t *subdevice, struct file *filep, int stop_mode, int flags); /** Write datas to buffor. */ -static int me4600_ao_io_stream_write(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_write(me_subdevice_t *subdevice, struct file *filep, int write_mode, int *values, int *count, int flags); /** Interrupt handler. Copy from buffer to FIFO. */ -static irqreturn_t me4600_ao_isr(int irq, void *dev_id -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - , struct pt_regs *regs -#endif - ); +static irqreturn_t me4600_ao_isr(int irq, void *dev_id); /** Copy data from circular buffer to fifo (fast) in wraparound mode. */ -int inline ao_write_data_wraparound(me4600_ao_subdevice_t * instance, int count, +inline int ao_write_data_wraparound(me4600_ao_subdevice_t *instance, int count, int start_pos); /** Copy data from circular buffer to fifo (fast). */ -int inline ao_write_data(me4600_ao_subdevice_t * instance, int count, +inline int ao_write_data(me4600_ao_subdevice_t *instance, int count, int start_pos); /** Copy data from circular buffer to fifo (slow). */ -int inline ao_write_data_pooling(me4600_ao_subdevice_t * instance, int count, +inline int ao_write_data_pooling(me4600_ao_subdevice_t *instance, int count, int start_pos); /** Copy data from user space to circular buffer. */ -int inline ao_get_data_from_user(me4600_ao_subdevice_t * instance, int count, +inline int ao_get_data_from_user(me4600_ao_subdevice_t *instance, int count, int *user_values); /** Stop presentation. Preserve FIFOs. */ -int inline ao_stop_immediately(me4600_ao_subdevice_t * instance); +inline int ao_stop_immediately(me4600_ao_subdevice_t *instance); /** Task for asynchronical state verifying. */ -static void me4600_ao_work_control_task( -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - void *subdevice -#else - struct work_struct *work -#endif - ); +static void me4600_ao_work_control_task(struct work_struct *work); /* Functions */ -static int me4600_ao_io_reset_subdevice(me_subdevice_t * subdevice, +static int me4600_ao_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags) { me4600_ao_subdevice_t *instance; @@ -290,7 +280,7 @@ static int me4600_ao_io_reset_subdevice(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_single_config(me_subdevice_t * subdevice, +static int me4600_ao_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -463,7 +453,7 @@ static int me4600_ao_io_single_config(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_single_read(me_subdevice_t * subdevice, +static int me4600_ao_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -547,7 +537,7 @@ static int me4600_ao_io_single_read(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_single_write(me_subdevice_t * subdevice, +static int me4600_ao_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -989,11 +979,11 @@ static int me4600_ao_io_single_write(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_stream_config(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_config(me_subdevice_t *subdevice, struct file *filep, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags) { me4600_ao_subdevice_t *instance; @@ -1025,7 +1015,7 @@ static int me4600_ao_io_stream_config(me_subdevice_t * subdevice, } if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { - if (!flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { + if (!(flags & ME_IO_STREAM_CONFIG_WRAPAROUND)) { PERROR ("Hardware ME_IO_STREAM_CONFIG_HARDWARE_ONLY has to be with ME_IO_STREAM_CONFIG_WRAPAROUND.\n"); return ME_ERRNO_INVALID_FLAGS; @@ -1327,7 +1317,7 @@ static int me4600_ao_io_stream_config(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_stream_new_values(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_new_values(me_subdevice_t *subdevice, struct file *filep, int time_out, int *count, int flags) { @@ -1408,7 +1398,7 @@ static int me4600_ao_io_stream_new_values(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_stream_start(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_start(me_subdevice_t *subdevice, struct file *filep, int start_mode, int time_out, int flags) { @@ -1845,7 +1835,7 @@ static int me4600_ao_io_stream_start(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_stream_status(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_status(me_subdevice_t *subdevice, struct file *filep, int wait, int *status, int *values, int flags) @@ -1943,7 +1933,7 @@ static int me4600_ao_io_stream_status(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_stream_stop(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_stop(me_subdevice_t *subdevice, struct file *filep, int stop_mode, int flags) { // Stop work and empty buffer and FIFO @@ -2048,7 +2038,7 @@ static int me4600_ao_io_stream_stop(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_stream_write(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_write(me_subdevice_t *subdevice, struct file *filep, int write_mode, int *values, int *count, int flags) @@ -2272,11 +2262,7 @@ static int me4600_ao_io_stream_write(me_subdevice_t * subdevice, return err; } -static irqreturn_t me4600_ao_isr(int irq, void *dev_id -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) - , struct pt_regs *regs -#endif - ) +static irqreturn_t me4600_ao_isr(int irq, void *dev_id) { me4600_ao_subdevice_t *instance = dev_id; uint32_t irq_status; @@ -2498,8 +2484,8 @@ static void me4600_ao_destructor(struct me_subdevice *subdevice) } me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, - spinlock_t * preload_reg_lock, - uint32_t * preload_flags, + spinlock_t *preload_reg_lock, + uint32_t *preload_flags, int ao_idx, int fifo, int irq, @@ -2689,13 +2675,8 @@ me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, subdevice->me4600_workqueue = me4600_wq; /* workqueue API changed in kernel 2.6.20 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) - INIT_WORK(&subdevice->ao_control_task, me4600_ao_work_control_task, - (void *)subdevice); -#else INIT_DELAYED_WORK(&subdevice->ao_control_task, me4600_ao_work_control_task); -#endif if (subdevice->fifo) { // Set speed for single operations. outl(ME4600_AO_MIN_CHAN_TICKS - 1, subdevice->timer_reg); @@ -2709,7 +2690,7 @@ me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, * * @param instance The subdevice instance (pointer). */ -int inline ao_stop_immediately(me4600_ao_subdevice_t * instance) +inline int ao_stop_immediately(me4600_ao_subdevice_t *instance) { unsigned long cpu_flags; uint32_t ctrl; @@ -2762,7 +2743,7 @@ int inline ao_stop_immediately(me4600_ao_subdevice_t * instance) * @return On error/success: 0. No datas were copied => no data in buffer. * @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. */ -int inline ao_write_data_wraparound(me4600_ao_subdevice_t * instance, int count, +inline int ao_write_data_wraparound(me4600_ao_subdevice_t *instance, int count, int start_pos) { /// @note This is time critical function! uint32_t status; @@ -2827,7 +2808,7 @@ int inline ao_write_data_wraparound(me4600_ao_subdevice_t * instance, int count, * @return On error/success: 0. No datas were copied => no data in buffer. * @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. */ -int inline ao_write_data(me4600_ao_subdevice_t * instance, int count, +inline int ao_write_data(me4600_ao_subdevice_t *instance, int count, int start_pos) { /// @note This is time critical function! uint32_t status; @@ -2897,7 +2878,7 @@ int inline ao_write_data(me4600_ao_subdevice_t * instance, int count, * @return On error/success: 0. FIFO was full at begining. * @return On error: -ME_ERRNO_RING_BUFFER_UNDEFFLOW. */ -int inline ao_write_data_pooling(me4600_ao_subdevice_t * instance, int count, +inline int ao_write_data_pooling(me4600_ao_subdevice_t *instance, int count, int start_pos) { /// @note This is slow function! uint32_t status; @@ -2955,7 +2936,7 @@ int inline ao_write_data_pooling(me4600_ao_subdevice_t * instance, int count, * @return On success: Number of copied values. * @return On error: -ME_ERRNO_INTERNAL. */ -int inline ao_get_data_from_user(me4600_ao_subdevice_t * instance, int count, +inline int ao_get_data_from_user(me4600_ao_subdevice_t *instance, int count, int *user_values) { int i, err; @@ -2987,13 +2968,7 @@ int inline ao_get_data_from_user(me4600_ao_subdevice_t * instance, int count, /** @brief Checking actual hardware and logical state. * @param instance The subdevice instance (pointer). */ -static void me4600_ao_work_control_task( -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - void *subdevice -#else - struct work_struct *work -#endif - ) +static void me4600_ao_work_control_task(struct work_struct *work) { me4600_ao_subdevice_t *instance; unsigned long cpu_flags = 0; @@ -3003,12 +2978,8 @@ static void me4600_ao_work_control_task( int reschedule = 0; int signaling = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - instance = (me4600_ao_subdevice_t *) subdevice; -#else instance = container_of((void *)work, me4600_ao_subdevice_t, ao_control_task); -#endif PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies, instance->ao_idx); @@ -3323,7 +3294,7 @@ static void me4600_ao_work_control_task( #else /// @note SPECIAL BUILD FOR BOSCH /// @author Guenter Gebhardt -static int me4600_ao_io_reset_subdevice(me_subdevice_t * subdevice, +static int me4600_ao_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags) { me4600_ao_subdevice_t *instance; @@ -3365,7 +3336,7 @@ static int me4600_ao_io_reset_subdevice(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_single_config(me_subdevice_t * subdevice, +static int me4600_ao_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -3636,7 +3607,7 @@ static int me4600_ao_io_single_config(me_subdevice_t * subdevice, goto ERROR; } - ERROR: +ERROR: spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); @@ -3645,7 +3616,7 @@ static int me4600_ao_io_single_config(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_single_read(me_subdevice_t * subdevice, +static int me4600_ao_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -3682,7 +3653,7 @@ static int me4600_ao_io_single_read(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_single_write(me_subdevice_t * subdevice, +static int me4600_ao_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -3830,18 +3801,18 @@ static int me4600_ao_io_single_write(me_subdevice_t * subdevice, spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); } - ERROR: +ERROR: ME_SUBDEVICE_EXIT; return err; } -static int me4600_ao_io_stream_config(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_config(me_subdevice_t *subdevice, struct file *filep, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags) { me4600_ao_subdevice_t *instance; @@ -4150,7 +4121,7 @@ static int me4600_ao_io_stream_config(me_subdevice_t * subdevice, PDEBUG("Ctrl word = 0x%lX.\n", ctrl); outl(ctrl, instance->ctrl_reg); // Write the control word - ERROR: +ERROR: spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); @@ -4159,7 +4130,7 @@ static int me4600_ao_io_stream_config(me_subdevice_t * subdevice, return err; } -static int me4600_ao_io_stream_new_values(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_new_values(me_subdevice_t *subdevice, struct file *filep, int time_out, int *count, int flags) { @@ -4238,7 +4209,7 @@ static int me4600_ao_io_stream_new_values(me_subdevice_t * subdevice, return err; } -static void stop_immediately(me4600_ao_subdevice_t * instance) +static void stop_immediately(me4600_ao_subdevice_t *instance) { unsigned long cpu_flags; uint32_t tmp; @@ -4253,7 +4224,7 @@ static void stop_immediately(me4600_ao_subdevice_t * instance) spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); } -static int me4600_ao_io_stream_start(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_start(me_subdevice_t *subdevice, struct file *filep, int start_mode, int time_out, int flags) { @@ -4778,14 +4749,14 @@ static int me4600_ao_io_stream_start(me_subdevice_t * subdevice, goto ERROR; } - ERROR: +ERROR: ME_SUBDEVICE_EXIT; return err; } -static int me4600_ao_io_stream_status(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_status(me_subdevice_t *subdevice, struct file *filep, int wait, int *status, int *values, int flags) @@ -4842,14 +4813,14 @@ static int me4600_ao_io_stream_status(me_subdevice_t * subdevice, goto ERROR; } - ERROR: +ERROR: ME_SUBDEVICE_EXIT; return err; } -static int me4600_ao_io_stream_stop(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_stop(me_subdevice_t *subdevice, struct file *filep, int stop_mode, int flags) { @@ -4891,14 +4862,14 @@ static int me4600_ao_io_stream_stop(me_subdevice_t * subdevice, goto ERROR; } - ERROR: +ERROR: ME_SUBDEVICE_EXIT; return err; } -static int me4600_ao_io_stream_write(me_subdevice_t * subdevice, +static int me4600_ao_io_stream_write(me_subdevice_t *subdevice, struct file *filep, int write_mode, int *values, int *count, int flags) @@ -5432,18 +5403,14 @@ static int me4600_ao_io_stream_write(me_subdevice_t * subdevice, goto ERROR; } - ERROR: +ERROR: ME_SUBDEVICE_EXIT; return err; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me4600_ao_isr(int irq, void *dev_id) -#else -static irqreturn_t me4600_ao_isr(int irq, void *dev_id, struct pt_regs *regs) -#endif { unsigned long tmp; int value; @@ -5660,8 +5627,8 @@ static void me4600_ao_destructor(struct me_subdevice *subdevice) } me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, - spinlock_t * preload_reg_lock, - uint32_t * preload_flags, + spinlock_t *preload_reg_lock, + uint32_t *preload_flags, int ao_idx, int fifo, int irq) { me4600_ao_subdevice_t *subdevice; @@ -5823,7 +5790,7 @@ me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, /* Common functions */ -static int me4600_ao_query_range_by_min_max(me_subdevice_t * subdevice, +static int me4600_ao_query_range_by_min_max(me_subdevice_t *subdevice, int unit, int *min, int *max, int *maxdata, int *range) @@ -5858,7 +5825,7 @@ static int me4600_ao_query_range_by_min_max(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ao_query_number_ranges(me_subdevice_t * subdevice, +static int me4600_ao_query_number_ranges(me_subdevice_t *subdevice, int unit, int *count) { me4600_ao_subdevice_t *instance; @@ -5876,7 +5843,7 @@ static int me4600_ao_query_number_ranges(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ao_query_range_info(me_subdevice_t * subdevice, +static int me4600_ao_query_range_info(me_subdevice_t *subdevice, int range, int *unit, int *min, int *max, int *maxdata) @@ -5900,7 +5867,7 @@ static int me4600_ao_query_range_info(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ao_query_timer(me_subdevice_t * subdevice, +static int me4600_ao_query_timer(me_subdevice_t *subdevice, int timer, int *base_frequency, long long *min_ticks, long long *max_ticks) @@ -5934,7 +5901,7 @@ static int me4600_ao_query_timer(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ao_query_number_channels(me_subdevice_t * subdevice, +static int me4600_ao_query_number_channels(me_subdevice_t *subdevice, int *number) { me4600_ao_subdevice_t *instance; @@ -5947,7 +5914,7 @@ static int me4600_ao_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ao_query_subdevice_type(me_subdevice_t * subdevice, +static int me4600_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { me4600_ao_subdevice_t *instance; @@ -5962,7 +5929,7 @@ static int me4600_ao_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ao_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me4600_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { me4600_ao_subdevice_t *instance; instance = (me4600_ao_subdevice_t *) subdevice; diff --git a/drivers/staging/meilhaus/me4600_ao.h b/drivers/staging/meilhaus/me4600_ao.h index 6fbc4a2dd9dd..7579435adc67 100644 --- a/drivers/staging/meilhaus/me4600_ao.h +++ b/drivers/staging/meilhaus/me4600_ao.h @@ -225,11 +225,7 @@ typedef struct me4600_ao_subdevice { wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ struct workqueue_struct *me4600_workqueue; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct ao_control_task; -#else struct delayed_work ao_control_task; -#endif volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */ diff --git a/drivers/staging/meilhaus/me4600_device.c b/drivers/staging/meilhaus/me4600_device.c index fa455844f4e3..457666ef61a5 100644 --- a/drivers/staging/meilhaus/me4600_device.c +++ b/drivers/staging/meilhaus/me4600_device.c @@ -336,6 +336,7 @@ me_device_t *me4600_pci_constructor(struct pci_dev *pci_device) return (me_device_t *) me4600_device; } +EXPORT_SYMBOL(me4600_pci_constructor); // Init and exit of module. @@ -368,6 +369,3 @@ MODULE_AUTHOR MODULE_DESCRIPTION("Device Driver Module for ME-46xx Devices"); MODULE_SUPPORTED_DEVICE("Meilhaus ME-46xx Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(me4600_pci_constructor); diff --git a/drivers/staging/meilhaus/me4600_di.c b/drivers/staging/meilhaus/me4600_di.c index 7e3c9f4d2df2..e107e5061388 100644 --- a/drivers/staging/meilhaus/me4600_di.c +++ b/drivers/staging/meilhaus/me4600_di.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -91,7 +91,7 @@ static int me4600_di_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_di_io_single_config(me_subdevice_t * subdevice, +static int me4600_di_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -133,7 +133,7 @@ static int me4600_di_io_single_config(me_subdevice_t * subdevice, return err; } -static int me4600_di_io_single_read(me_subdevice_t * subdevice, +static int me4600_di_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -177,7 +177,7 @@ static int me4600_di_io_single_read(me_subdevice_t * subdevice, return err; } -static int me4600_di_query_number_channels(me_subdevice_t * subdevice, +static int me4600_di_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -185,7 +185,7 @@ static int me4600_di_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_di_query_subdevice_type(me_subdevice_t * subdevice, +static int me4600_di_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -194,7 +194,7 @@ static int me4600_di_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me4600_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); *caps = 0; @@ -202,7 +202,7 @@ static int me4600_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) } me4600_di_subdevice_t *me4600_di_constructor(uint32_t reg_base, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me4600_di_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me4600_dio.c b/drivers/staging/meilhaus/me4600_dio.c index 0af95d1a8f5d..baa28ff6b6bd 100644 --- a/drivers/staging/meilhaus/me4600_dio.c +++ b/drivers/staging/meilhaus/me4600_dio.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -94,7 +94,7 @@ static int me4600_dio_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_dio_io_single_config(me_subdevice_t * subdevice, +static int me4600_dio_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -268,7 +268,7 @@ static int me4600_dio_io_single_config(me_subdevice_t * subdevice, return err; } -static int me4600_dio_io_single_read(me_subdevice_t * subdevice, +static int me4600_dio_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -342,7 +342,7 @@ static int me4600_dio_io_single_read(me_subdevice_t * subdevice, return err; } -static int me4600_dio_io_single_write(me_subdevice_t * subdevice, +static int me4600_dio_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -425,7 +425,7 @@ static int me4600_dio_io_single_write(me_subdevice_t * subdevice, return err; } -static int me4600_dio_query_number_channels(me_subdevice_t * subdevice, +static int me4600_dio_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -433,7 +433,7 @@ static int me4600_dio_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_dio_query_subdevice_type(me_subdevice_t * subdevice, +static int me4600_dio_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -442,7 +442,7 @@ static int me4600_dio_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_dio_query_subdevice_caps(me_subdevice_t * subdevice, +static int me4600_dio_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); @@ -452,7 +452,7 @@ static int me4600_dio_query_subdevice_caps(me_subdevice_t * subdevice, me4600_dio_subdevice_t *me4600_dio_constructor(uint32_t reg_base, unsigned int dio_idx, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me4600_dio_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me4600_do.c b/drivers/staging/meilhaus/me4600_do.c index ee591bc1185e..39510f3e6e67 100644 --- a/drivers/staging/meilhaus/me4600_do.c +++ b/drivers/staging/meilhaus/me4600_do.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -93,7 +93,7 @@ static int me4600_do_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_do_io_single_config(me_subdevice_t * subdevice, +static int me4600_do_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -224,7 +224,7 @@ static int me4600_do_io_single_config(me_subdevice_t * subdevice, return err; } -static int me4600_do_io_single_read(me_subdevice_t * subdevice, +static int me4600_do_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -284,7 +284,7 @@ static int me4600_do_io_single_read(me_subdevice_t * subdevice, return err; } -static int me4600_do_io_single_write(me_subdevice_t * subdevice, +static int me4600_do_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -352,7 +352,7 @@ static int me4600_do_io_single_write(me_subdevice_t * subdevice, return err; } -static int me4600_do_query_number_channels(me_subdevice_t * subdevice, +static int me4600_do_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -360,7 +360,7 @@ static int me4600_do_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_do_query_subdevice_type(me_subdevice_t * subdevice, +static int me4600_do_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -369,7 +369,7 @@ static int me4600_do_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me4600_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); *caps = 0; @@ -377,7 +377,7 @@ static int me4600_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) } me4600_do_subdevice_t *me4600_do_constructor(uint32_t reg_base, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me4600_do_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me4600_ext_irq.c b/drivers/staging/meilhaus/me4600_ext_irq.c index adc1e1babf40..6b33cba3da8b 100644 --- a/drivers/staging/meilhaus/me4600_ext_irq.c +++ b/drivers/staging/meilhaus/me4600_ext_irq.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include @@ -60,7 +60,7 @@ * Functions */ -static int me4600_ext_irq_io_irq_start(me_subdevice_t * subdevice, +static int me4600_ext_irq_io_irq_start(me_subdevice_t *subdevice, struct file *filep, int channel, int irq_source, @@ -135,7 +135,7 @@ static int me4600_ext_irq_io_irq_start(me_subdevice_t * subdevice, return err; } -static int me4600_ext_irq_io_irq_wait(me_subdevice_t * subdevice, +static int me4600_ext_irq_io_irq_wait(me_subdevice_t *subdevice, struct file *filep, int channel, int *irq_count, @@ -214,7 +214,7 @@ static int me4600_ext_irq_io_irq_wait(me_subdevice_t * subdevice, return err; } -static int me4600_ext_irq_io_irq_stop(me_subdevice_t * subdevice, +static int me4600_ext_irq_io_irq_stop(me_subdevice_t *subdevice, struct file *filep, int channel, int flags) { @@ -256,7 +256,7 @@ static int me4600_ext_irq_io_irq_stop(me_subdevice_t * subdevice, return err; } -static int me4600_ext_irq_io_reset_subdevice(me_subdevice_t * subdevice, +static int me4600_ext_irq_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags) { me4600_ext_irq_subdevice_t *instance; @@ -308,7 +308,7 @@ static void me4600_ext_irq_destructor(struct me_subdevice *subdevice) kfree(instance); } -static int me4600_ext_irq_query_number_channels(me_subdevice_t * subdevice, +static int me4600_ext_irq_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -316,7 +316,7 @@ static int me4600_ext_irq_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ext_irq_query_subdevice_type(me_subdevice_t * subdevice, +static int me4600_ext_irq_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -325,7 +325,7 @@ static int me4600_ext_irq_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me4600_ext_irq_query_subdevice_caps(me_subdevice_t * subdevice, +static int me4600_ext_irq_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); @@ -335,12 +335,7 @@ static int me4600_ext_irq_query_subdevice_caps(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me4600_ext_irq_isr(int irq, void *dev_id) -#else -static irqreturn_t me4600_ext_irq_isr(int irq, void *dev_id, - struct pt_regs *regs) -#endif { me4600_ext_irq_subdevice_t *instance; uint32_t ctrl; diff --git a/drivers/staging/meilhaus/me6000_ao.c b/drivers/staging/meilhaus/me6000_ao.c index 94f01231f79a..f7abdbd485e4 100644 --- a/drivers/staging/meilhaus/me6000_ao.c +++ b/drivers/staging/meilhaus/me6000_ao.c @@ -36,8 +36,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -57,31 +57,31 @@ /* Defines */ -static int me6000_ao_query_range_by_min_max(me_subdevice_t * subdevice, +static int me6000_ao_query_range_by_min_max(me_subdevice_t *subdevice, int unit, int *min, int *max, int *maxdata, int *range); -static int me6000_ao_query_number_ranges(me_subdevice_t * subdevice, +static int me6000_ao_query_number_ranges(me_subdevice_t *subdevice, int unit, int *count); -static int me6000_ao_query_range_info(me_subdevice_t * subdevice, +static int me6000_ao_query_range_info(me_subdevice_t *subdevice, int range, int *unit, int *min, int *max, int *maxdata); -static int me6000_ao_query_timer(me_subdevice_t * subdevice, +static int me6000_ao_query_timer(me_subdevice_t *subdevice, int timer, int *base_frequency, long long *min_ticks, long long *max_ticks); -static int me6000_ao_query_number_channels(me_subdevice_t * subdevice, +static int me6000_ao_query_number_channels(me_subdevice_t *subdevice, int *number); -static int me6000_ao_query_subdevice_type(me_subdevice_t * subdevice, +static int me6000_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype); -static int me6000_ao_query_subdevice_caps(me_subdevice_t * subdevice, +static int me6000_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps); static int me6000_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, @@ -91,11 +91,11 @@ static int me6000_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, static void me6000_ao_destructor(struct me_subdevice *subdevice); /** Reset subdevice. Stop all actions. Reset registry. Disable FIFO. Set output to 0V and status to 'none'. */ -static int me6000_ao_io_reset_subdevice(me_subdevice_t * subdevice, +static int me6000_ao_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags); /** Set output as single */ -static int me6000_ao_io_single_config(me_subdevice_t * subdevice, +static int me6000_ao_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -104,89 +104,81 @@ static int me6000_ao_io_single_config(me_subdevice_t * subdevice, int trig_type, int trig_edge, int flags); /** Pass to user actual value of output. */ -static int me6000_ao_io_single_read(me_subdevice_t * subdevice, +static int me6000_ao_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags); /** Write to output requed value. */ -static int me6000_ao_io_single_write(me_subdevice_t * subdevice, +static int me6000_ao_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags); /** Set output as streamed device. */ -static int me6000_ao_io_stream_config(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_config(me_subdevice_t *subdevice, struct file *filep, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags); /** Wait for / Check empty space in buffer. */ -static int me6000_ao_io_stream_new_values(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_new_values(me_subdevice_t *subdevice, struct file *filep, int time_out, int *count, int flags); /** Start streaming. */ -static int me6000_ao_io_stream_start(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_start(me_subdevice_t *subdevice, struct file *filep, int start_mode, int time_out, int flags); /** Check actual state. / Wait for end. */ -static int me6000_ao_io_stream_status(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_status(me_subdevice_t *subdevice, struct file *filep, int wait, int *status, int *values, int flags); /** Stop streaming. */ -static int me6000_ao_io_stream_stop(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_stop(me_subdevice_t *subdevice, struct file *filep, int stop_mode, int flags); /** Write datas to buffor. */ -static int me6000_ao_io_stream_write(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_write(me_subdevice_t *subdevice, struct file *filep, int write_mode, int *values, int *count, int flags); /** Interrupt handler. Copy from buffer to FIFO. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me6000_ao_isr(int irq, void *dev_id); -#else -static irqreturn_t me6000_ao_isr(int irq, void *dev_id, struct pt_regs *regs); -#endif /** Copy data from circular buffer to fifo (fast) in wraparound mode. */ -int inline ao_write_data_wraparound(me6000_ao_subdevice_t * instance, int count, +inline int ao_write_data_wraparound(me6000_ao_subdevice_t *instance, int count, int start_pos); /** Copy data from circular buffer to fifo (fast).*/ -int inline ao_write_data(me6000_ao_subdevice_t * instance, int count, +inline int ao_write_data(me6000_ao_subdevice_t *instance, int count, int start_pos); /** Copy data from circular buffer to fifo (slow).*/ -int inline ao_write_data_pooling(me6000_ao_subdevice_t * instance, int count, +inline int ao_write_data_pooling(me6000_ao_subdevice_t *instance, int count, int start_pos); /** Copy data from user space to circular buffer. */ -int inline ao_get_data_from_user(me6000_ao_subdevice_t * instance, int count, +inline int ao_get_data_from_user(me6000_ao_subdevice_t *instance, int count, int *user_values); /** Stop presentation. Preserve FIFOs. */ -int inline ao_stop_immediately(me6000_ao_subdevice_t * instance); +inline int ao_stop_immediately(me6000_ao_subdevice_t *instance); /** Function for checking timeout in non-blocking mode. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void me6000_ao_work_control_task(void *subdevice); -#else static void me6000_ao_work_control_task(struct work_struct *work); -#endif /* Functions */ -static int me6000_ao_io_reset_subdevice(me_subdevice_t * subdevice, +static int me6000_ao_io_reset_subdevice(me_subdevice_t *subdevice, struct file *filep, int flags) { me6000_ao_subdevice_t *instance; @@ -274,7 +266,7 @@ static int me6000_ao_io_reset_subdevice(me_subdevice_t * subdevice, return err; } -static int me6000_ao_io_single_config(me_subdevice_t * subdevice, +static int me6000_ao_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -473,7 +465,7 @@ static int me6000_ao_io_single_config(me_subdevice_t * subdevice, return err; } -static int me6000_ao_io_single_read(me_subdevice_t * subdevice, +static int me6000_ao_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -555,7 +547,7 @@ static int me6000_ao_io_single_read(me_subdevice_t * subdevice, return err; } -static int me6000_ao_io_single_write(me_subdevice_t * subdevice, +static int me6000_ao_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -1027,11 +1019,11 @@ static int me6000_ao_io_single_write(me_subdevice_t * subdevice, return err; } -static int me6000_ao_io_stream_config(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_config(me_subdevice_t *subdevice, struct file *filep, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags) { me6000_ao_subdevice_t *instance; @@ -1063,7 +1055,7 @@ static int me6000_ao_io_stream_config(me_subdevice_t * subdevice, } if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { - if (!flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { + if (!(flags & ME_IO_STREAM_CONFIG_WRAPAROUND)) { PERROR ("Hardware ME_IO_STREAM_CONFIG_HARDWARE_ONLY has to be with ME_IO_STREAM_CONFIG_WRAPAROUND.\n"); return ME_ERRNO_INVALID_FLAGS; @@ -1359,7 +1351,7 @@ static int me6000_ao_io_stream_config(me_subdevice_t * subdevice, return err; } -static int me6000_ao_io_stream_new_values(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_new_values(me_subdevice_t *subdevice, struct file *filep, int time_out, int *count, int flags) { @@ -1440,7 +1432,7 @@ static int me6000_ao_io_stream_new_values(me_subdevice_t * subdevice, return err; } -static int me6000_ao_io_stream_start(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_start(me_subdevice_t *subdevice, struct file *filep, int start_mode, int time_out, int flags) { @@ -1889,7 +1881,7 @@ static int me6000_ao_io_stream_start(me_subdevice_t * subdevice, return err; } -static int me6000_ao_io_stream_status(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_status(me_subdevice_t *subdevice, struct file *filep, int wait, int *status, int *values, int flags) @@ -1987,7 +1979,7 @@ static int me6000_ao_io_stream_status(me_subdevice_t * subdevice, return err; } -static int me6000_ao_io_stream_stop(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_stop(me_subdevice_t *subdevice, struct file *filep, int stop_mode, int flags) { /// @note Stop work and empty buffer and FIFO @@ -2094,7 +2086,7 @@ static int me6000_ao_io_stream_stop(me_subdevice_t * subdevice, return err; } -static int me6000_ao_io_stream_write(me_subdevice_t * subdevice, +static int me6000_ao_io_stream_write(me_subdevice_t *subdevice, struct file *filep, int write_mode, int *values, int *count, int flags) @@ -2324,11 +2316,7 @@ static int me6000_ao_io_stream_write(me_subdevice_t * subdevice, return err; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me6000_ao_isr(int irq, void *dev_id) -#else -static irqreturn_t me6000_ao_isr(int irq, void *dev_id, struct pt_regs *regs) -#endif { me6000_ao_subdevice_t *instance = dev_id; uint32_t irq_status; @@ -2544,9 +2532,9 @@ static void me6000_ao_destructor(struct me_subdevice *subdevice) } me6000_ao_subdevice_t *me6000_ao_constructor(uint32_t reg_base, - spinlock_t * preload_reg_lock, - uint32_t * preload_flags, - uint32_t * triggering_flags, + spinlock_t *preload_reg_lock, + uint32_t *preload_flags, + uint32_t *triggering_flags, int ao_idx, int fifo, int irq, @@ -2797,13 +2785,8 @@ me6000_ao_subdevice_t *me6000_ao_constructor(uint32_t reg_base, subdevice->me6000_workqueue = me6000_wq; /* workqueue API changed in kernel 2.6.20 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) - INIT_WORK(&subdevice->ao_control_task, me6000_ao_work_control_task, - (void *)subdevice); -#else INIT_DELAYED_WORK(&subdevice->ao_control_task, me6000_ao_work_control_task); -#endif if (subdevice->fifo) { //Set speed outl(ME6000_AO_MIN_CHAN_TICKS - 1, subdevice->timer_reg); @@ -2817,7 +2800,7 @@ me6000_ao_subdevice_t *me6000_ao_constructor(uint32_t reg_base, * * @param instance The subdevice instance (pointer). */ -int inline ao_stop_immediately(me6000_ao_subdevice_t * instance) +inline int ao_stop_immediately(me6000_ao_subdevice_t *instance) { unsigned long cpu_flags; uint32_t ctrl; @@ -2825,10 +2808,11 @@ int inline ao_stop_immediately(me6000_ao_subdevice_t * instance) int i; uint32_t single_mask; - single_mask = - (instance->ao_idx - ME6000_AO_SINGLE_STATUS_OFFSET < - 0) ? 0x0000 : (0x0001 << (instance->ao_idx - - ME6000_AO_SINGLE_STATUS_OFFSET)); + if (instance->ao_idx < ME6000_AO_SINGLE_STATUS_OFFSET) + single_mask = 0x0000; + else + single_mask = 0x0001 << (instance->ao_idx - + ME6000_AO_SINGLE_STATUS_OFFSET); timeout = (instance->hardware_stop_delay > @@ -2887,7 +2871,7 @@ int inline ao_stop_immediately(me6000_ao_subdevice_t * instance) * @return On error/success: 0. No datas were copied => no data in buffer. * @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. */ -int inline ao_write_data_wraparound(me6000_ao_subdevice_t * instance, int count, +inline int ao_write_data_wraparound(me6000_ao_subdevice_t *instance, int count, int start_pos) { /// @note This is time critical function! uint32_t status; @@ -2952,7 +2936,7 @@ int inline ao_write_data_wraparound(me6000_ao_subdevice_t * instance, int count, * @return On error/success: 0. No datas were copied => no data in buffer. * @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. */ -int inline ao_write_data(me6000_ao_subdevice_t * instance, int count, +inline int ao_write_data(me6000_ao_subdevice_t *instance, int count, int start_pos) { /// @note This is time critical function! uint32_t status; @@ -3022,7 +3006,7 @@ int inline ao_write_data(me6000_ao_subdevice_t * instance, int count, * @return On error/success: 0. FIFO was full at begining. * @return On error: -ME_ERRNO_RING_BUFFER_UNDEFFLOW. */ -int inline ao_write_data_pooling(me6000_ao_subdevice_t * instance, int count, +inline int ao_write_data_pooling(me6000_ao_subdevice_t *instance, int count, int start_pos) { /// @note This is slow function! uint32_t status; @@ -3080,7 +3064,7 @@ int inline ao_write_data_pooling(me6000_ao_subdevice_t * instance, int count, * @return On success: Number of copied values. * @return On error: -ME_ERRNO_INTERNAL. */ -int inline ao_get_data_from_user(me6000_ao_subdevice_t * instance, int count, +inline int ao_get_data_from_user(me6000_ao_subdevice_t *instance, int count, int *user_values) { int i, err; @@ -3109,13 +3093,7 @@ int inline ao_get_data_from_user(me6000_ao_subdevice_t * instance, int count, return copied; } -static void me6000_ao_work_control_task( -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - void *subdevice -#else - struct work_struct *work -#endif - ) +static void me6000_ao_work_control_task(struct work_struct *work) { me6000_ao_subdevice_t *instance; unsigned long cpu_flags = 0; @@ -3126,12 +3104,8 @@ static void me6000_ao_work_control_task( int signaling = 0; uint32_t single_mask; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - instance = (me6000_ao_subdevice_t *) subdevice; -#else instance = container_of((void *)work, me6000_ao_subdevice_t, ao_control_task); -#endif PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies, instance->ao_idx); @@ -3555,7 +3529,7 @@ static void me6000_ao_work_control_task( } -static int me6000_ao_query_range_by_min_max(me_subdevice_t * subdevice, +static int me6000_ao_query_range_by_min_max(me_subdevice_t *subdevice, int unit, int *min, int *max, int *maxdata, int *range) @@ -3589,7 +3563,7 @@ static int me6000_ao_query_range_by_min_max(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me6000_ao_query_number_ranges(me_subdevice_t * subdevice, +static int me6000_ao_query_number_ranges(me_subdevice_t *subdevice, int unit, int *count) { me6000_ao_subdevice_t *instance; @@ -3607,7 +3581,7 @@ static int me6000_ao_query_number_ranges(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me6000_ao_query_range_info(me_subdevice_t * subdevice, +static int me6000_ao_query_range_info(me_subdevice_t *subdevice, int range, int *unit, int *min, int *max, int *maxdata) @@ -3631,7 +3605,7 @@ static int me6000_ao_query_range_info(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me6000_ao_query_timer(me_subdevice_t * subdevice, +static int me6000_ao_query_timer(me_subdevice_t *subdevice, int timer, int *base_frequency, long long *min_ticks, long long *max_ticks) @@ -3660,7 +3634,7 @@ static int me6000_ao_query_timer(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me6000_ao_query_number_channels(me_subdevice_t * subdevice, +static int me6000_ao_query_number_channels(me_subdevice_t *subdevice, int *number) { me6000_ao_subdevice_t *instance; @@ -3672,7 +3646,7 @@ static int me6000_ao_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me6000_ao_query_subdevice_type(me_subdevice_t * subdevice, +static int me6000_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { me6000_ao_subdevice_t *instance; @@ -3690,7 +3664,7 @@ static int me6000_ao_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me6000_ao_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me6000_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { me6000_ao_subdevice_t *instance; instance = (me6000_ao_subdevice_t *) subdevice; diff --git a/drivers/staging/meilhaus/me6000_ao.h b/drivers/staging/meilhaus/me6000_ao.h index 9629649cd410..ef4d0189bdea 100644 --- a/drivers/staging/meilhaus/me6000_ao.h +++ b/drivers/staging/meilhaus/me6000_ao.h @@ -160,11 +160,7 @@ typedef struct me6000_ao_subdevice { wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ struct workqueue_struct *me6000_workqueue; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct ao_control_task; -#else struct delayed_work ao_control_task; -#endif volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */ diff --git a/drivers/staging/meilhaus/me6000_device.c b/drivers/staging/meilhaus/me6000_device.c index fee4c58b8464..1a6cf7f43251 100644 --- a/drivers/staging/meilhaus/me6000_device.c +++ b/drivers/staging/meilhaus/me6000_device.c @@ -178,6 +178,7 @@ me_device_t *me6000_pci_constructor(struct pci_dev *pci_device) return (me_device_t *) me6000_device; } +EXPORT_SYMBOL(me6000_pci_constructor); // Init and exit of module. @@ -206,6 +207,3 @@ MODULE_AUTHOR MODULE_DESCRIPTION("Device Driver Module for ME-6000 Device"); MODULE_SUPPORTED_DEVICE("Meilhaus ME-6000 Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(me6000_pci_constructor); diff --git a/drivers/staging/meilhaus/me6000_dio.c b/drivers/staging/meilhaus/me6000_dio.c index 07f1069f9ac6..c90686efc380 100644 --- a/drivers/staging/meilhaus/me6000_dio.c +++ b/drivers/staging/meilhaus/me6000_dio.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -91,7 +91,7 @@ static int me6000_dio_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me6000_dio_io_single_config(me_subdevice_t * subdevice, +static int me6000_dio_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -161,7 +161,7 @@ static int me6000_dio_io_single_config(me_subdevice_t * subdevice, return err; } -static int me6000_dio_io_single_read(me_subdevice_t * subdevice, +static int me6000_dio_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -233,7 +233,7 @@ static int me6000_dio_io_single_read(me_subdevice_t * subdevice, return err; } -static int me6000_dio_io_single_write(me_subdevice_t * subdevice, +static int me6000_dio_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -314,7 +314,7 @@ static int me6000_dio_io_single_write(me_subdevice_t * subdevice, return err; } -static int me6000_dio_query_number_channels(me_subdevice_t * subdevice, +static int me6000_dio_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -322,7 +322,7 @@ static int me6000_dio_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me6000_dio_query_subdevice_type(me_subdevice_t * subdevice, +static int me6000_dio_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -331,7 +331,7 @@ static int me6000_dio_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me6000_dio_query_subdevice_caps(me_subdevice_t * subdevice, +static int me6000_dio_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); @@ -341,7 +341,7 @@ static int me6000_dio_query_subdevice_caps(me_subdevice_t * subdevice, me6000_dio_subdevice_t *me6000_dio_constructor(uint32_t reg_base, unsigned int dio_idx, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me6000_dio_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me8100_device.c b/drivers/staging/meilhaus/me8100_device.c index 1fb79e490261..41a9345cee5d 100644 --- a/drivers/staging/meilhaus/me8100_device.c +++ b/drivers/staging/meilhaus/me8100_device.c @@ -159,6 +159,7 @@ me_device_t *me8100_pci_constructor(struct pci_dev *pci_device) return (me_device_t *) me8100_device; } +EXPORT_SYMBOL(me8100_pci_constructor); // Init and exit of module. @@ -182,6 +183,3 @@ MODULE_AUTHOR("Guenter Gebhardt "); MODULE_DESCRIPTION("Device Driver Module for Template Device"); MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(me8100_pci_constructor); diff --git a/drivers/staging/meilhaus/me8100_di.c b/drivers/staging/meilhaus/me8100_di.c index 971727c9e305..301dbd8f96a1 100644 --- a/drivers/staging/meilhaus/me8100_di.c +++ b/drivers/staging/meilhaus/me8100_di.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include #include @@ -114,7 +114,7 @@ static int me8100_di_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me8100_di_io_irq_start(me_subdevice_t * subdevice, +static int me8100_di_io_irq_start(me_subdevice_t *subdevice, struct file *filep, int channel, int irq_source, @@ -208,7 +208,7 @@ static int me8100_di_io_irq_start(me_subdevice_t * subdevice, return err; } -static int me8100_di_io_irq_wait(me_subdevice_t * subdevice, +static int me8100_di_io_irq_wait(me_subdevice_t *subdevice, struct file *filep, int channel, int *irq_count, @@ -315,7 +315,7 @@ static int me8100_di_io_irq_wait(me_subdevice_t * subdevice, return err; } -static int me8100_di_io_irq_stop(me_subdevice_t * subdevice, +static int me8100_di_io_irq_stop(me_subdevice_t *subdevice, struct file *filep, int channel, int flags) { me8100_di_subdevice_t *instance; @@ -358,7 +358,7 @@ static int me8100_di_io_irq_stop(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8100_di_io_single_config(me_subdevice_t * subdevice, +static int me8100_di_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -405,7 +405,7 @@ static int me8100_di_io_single_config(me_subdevice_t * subdevice, return err; } -static int me8100_di_io_single_read(me_subdevice_t * subdevice, +static int me8100_di_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -466,7 +466,7 @@ static int me8100_di_io_single_read(me_subdevice_t * subdevice, return err; } -static int me8100_di_query_number_channels(me_subdevice_t * subdevice, +static int me8100_di_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -474,7 +474,7 @@ static int me8100_di_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8100_di_query_subdevice_type(me_subdevice_t * subdevice, +static int me8100_di_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -483,7 +483,7 @@ static int me8100_di_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8100_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me8100_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); *caps = ME_CAPS_DIO_BIT_PATTERN_IRQ | ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY; @@ -503,11 +503,7 @@ static void me8100_di_destructor(struct me_subdevice *subdevice) kfree(instance); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me8100_isr(int irq, void *dev_id) -#else -static irqreturn_t me8100_isr(int irq, void *dev_id, struct pt_regs *regs) -#endif { me8100_di_subdevice_t *instance; uint32_t icsr; @@ -598,7 +594,7 @@ me8100_di_subdevice_t *me8100_di_constructor(uint32_t me8100_reg_base, uint32_t plx_reg_base, unsigned int di_idx, int irq, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me8100_di_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me8100_do.c b/drivers/staging/meilhaus/me8100_do.c index 957b9f92f760..81651a90cc05 100644 --- a/drivers/staging/meilhaus/me8100_do.c +++ b/drivers/staging/meilhaus/me8100_do.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -92,7 +92,7 @@ static int me8100_do_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me8100_do_io_single_config(me_subdevice_t * subdevice, +static int me8100_do_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -158,7 +158,7 @@ static int me8100_do_io_single_config(me_subdevice_t * subdevice, return err; } -static int me8100_do_io_single_read(me_subdevice_t * subdevice, +static int me8100_do_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -215,7 +215,7 @@ static int me8100_do_io_single_read(me_subdevice_t * subdevice, return err; } -static int me8100_do_io_single_write(me_subdevice_t * subdevice, +static int me8100_do_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -297,7 +297,7 @@ static int me8100_do_io_single_write(me_subdevice_t * subdevice, return err; } -static int me8100_do_query_number_channels(me_subdevice_t * subdevice, +static int me8100_do_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -305,7 +305,7 @@ static int me8100_do_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8100_do_query_subdevice_type(me_subdevice_t * subdevice, +static int me8100_do_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -314,7 +314,7 @@ static int me8100_do_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8100_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me8100_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); *caps = ME_CAPS_DIO_SINK_SOURCE; @@ -323,7 +323,7 @@ static int me8100_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) me8100_do_subdevice_t *me8100_do_constructor(uint32_t reg_base, unsigned int do_idx, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me8100_do_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me8200_device.c b/drivers/staging/meilhaus/me8200_device.c index 261c0cbd9d0a..b313679fc5c3 100644 --- a/drivers/staging/meilhaus/me8200_device.c +++ b/drivers/staging/meilhaus/me8200_device.c @@ -166,6 +166,7 @@ me_device_t *me8200_pci_constructor(struct pci_dev *pci_device) return (me_device_t *) me8200_device; } +EXPORT_SYMBOL(me8200_pci_constructor); // Init and exit of module. @@ -189,6 +190,3 @@ MODULE_AUTHOR("Guenter Gebhardt "); MODULE_DESCRIPTION("Device Driver Module for Template Device"); MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(me8200_pci_constructor); diff --git a/drivers/staging/meilhaus/me8200_di.c b/drivers/staging/meilhaus/me8200_di.c index 27525bc067b6..a931fb817c7d 100644 --- a/drivers/staging/meilhaus/me8200_di.c +++ b/drivers/staging/meilhaus/me8200_di.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include #include @@ -50,52 +50,44 @@ /// Defines static void me8200_di_destructor(struct me_subdevice *subdevice); -static int me8200_di_io_irq_start(me_subdevice_t * subdevice, +static int me8200_di_io_irq_start(me_subdevice_t *subdevice, struct file *filep, int channel, int irq_source, int irq_edge, int irq_arg, int flags); -static int me8200_di_io_irq_wait(me_subdevice_t * subdevice, +static int me8200_di_io_irq_wait(me_subdevice_t *subdevice, struct file *filep, int channel, int *irq_count, int *value, int time_out, int flags); -static int me8200_di_io_irq_stop(me_subdevice_t * subdevice, +static int me8200_di_io_irq_stop(me_subdevice_t *subdevice, struct file *filep, int channel, int flags); -static int me8200_di_io_single_config(me_subdevice_t * subdevice, +static int me8200_di_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, int ref, int trig_chan, int trig_type, int trig_edge, int flags); -static int me8200_di_io_single_read(me_subdevice_t * subdevice, +static int me8200_di_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags); static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice, struct file *filep, int flags); -static int me8200_di_query_number_channels(me_subdevice_t * subdevice, +static int me8200_di_query_number_channels(me_subdevice_t *subdevice, int *number); -static int me8200_di_query_subdevice_type(me_subdevice_t * subdevice, +static int me8200_di_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype); -static int me8200_di_query_subdevice_caps(me_subdevice_t * subdevice, +static int me8200_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me8200_isr(int irq, void *dev_id); -#else -static irqreturn_t me8200_isr(int irq, void *dev_id, struct pt_regs *regs); -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me8200_isr_EX(int irq, void *dev_id); -#else -static irqreturn_t me8200_isr_EX(int irq, void *dev_id, struct pt_regs *regs); -#endif -static void me8200_di_check_version(me8200_di_subdevice_t * instance, +static void me8200_di_check_version(me8200_di_subdevice_t *instance, unsigned long addr); ///Functions -static int me8200_di_io_irq_start(me_subdevice_t * subdevice, +static int me8200_di_io_irq_start(me_subdevice_t *subdevice, struct file *filep, int channel, int irq_source, @@ -246,7 +238,7 @@ static int me8200_di_io_irq_start(me_subdevice_t * subdevice, return err; } -static int me8200_di_io_irq_wait(me_subdevice_t * subdevice, +static int me8200_di_io_irq_wait(me_subdevice_t *subdevice, struct file *filep, int channel, int *irq_count, @@ -352,7 +344,7 @@ static int me8200_di_io_irq_wait(me_subdevice_t * subdevice, return err; } -static int me8200_di_io_irq_stop(me_subdevice_t * subdevice, +static int me8200_di_io_irq_stop(me_subdevice_t *subdevice, struct file *filep, int channel, int flags) { me8200_di_subdevice_t *instance; @@ -406,7 +398,7 @@ static int me8200_di_io_irq_stop(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8200_di_io_single_config(me_subdevice_t * subdevice, +static int me8200_di_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -453,7 +445,7 @@ static int me8200_di_io_single_config(me_subdevice_t * subdevice, return err; } -static int me8200_di_io_single_read(me_subdevice_t * subdevice, +static int me8200_di_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -518,7 +510,7 @@ static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice, return me8200_di_io_irq_stop(subdevice, filep, 0, 0); } -static int me8200_di_query_number_channels(me_subdevice_t * subdevice, +static int me8200_di_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -526,7 +518,7 @@ static int me8200_di_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8200_di_query_subdevice_type(me_subdevice_t * subdevice, +static int me8200_di_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -535,7 +527,7 @@ static int me8200_di_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8200_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me8200_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); *caps = @@ -546,11 +538,7 @@ static int me8200_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) return ME_ERRNO_SUCCESS; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me8200_isr(int irq, void *dev_id) -#else -static irqreturn_t me8200_isr(int irq, void *dev_id, struct pt_regs *regs) -#endif { me8200_di_subdevice_t *instance; uint8_t ctrl; @@ -629,11 +617,7 @@ static irqreturn_t me8200_isr(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me8200_isr_EX(int irq, void *dev_id) -#else -static irqreturn_t me8200_isr_EX(int irq, void *dev_id, struct pt_regs *regs) -#endif { me8200_di_subdevice_t *instance; uint8_t irq_status = 0; @@ -715,8 +699,8 @@ static void me8200_di_destructor(struct me_subdevice *subdevice) me8200_di_subdevice_t *me8200_di_constructor(uint32_t me8200_regbase, unsigned int di_idx, int irq, - spinlock_t * irq_ctrl_lock, - spinlock_t * irq_mode_lock) + spinlock_t *irq_ctrl_lock, + spinlock_t *irq_mode_lock) { me8200_di_subdevice_t *subdevice; int err; @@ -843,7 +827,7 @@ me8200_di_subdevice_t *me8200_di_constructor(uint32_t me8200_regbase, return subdevice; } -static void me8200_di_check_version(me8200_di_subdevice_t * instance, +static void me8200_di_check_version(me8200_di_subdevice_t *instance, unsigned long addr) { diff --git a/drivers/staging/meilhaus/me8200_dio.c b/drivers/staging/meilhaus/me8200_dio.c index ff8ca1b8b7f3..c7f43f011f3c 100644 --- a/drivers/staging/meilhaus/me8200_dio.c +++ b/drivers/staging/meilhaus/me8200_dio.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -90,7 +90,7 @@ static int me8200_dio_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me8200_dio_io_single_config(me_subdevice_t * subdevice, +static int me8200_dio_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -164,7 +164,7 @@ static int me8200_dio_io_single_config(me_subdevice_t * subdevice, return err; } -static int me8200_dio_io_single_read(me_subdevice_t * subdevice, +static int me8200_dio_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -241,7 +241,7 @@ static int me8200_dio_io_single_read(me_subdevice_t * subdevice, return err; } -static int me8200_dio_io_single_write(me_subdevice_t * subdevice, +static int me8200_dio_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -332,7 +332,7 @@ static int me8200_dio_io_single_write(me_subdevice_t * subdevice, return err; } -static int me8200_dio_query_number_channels(me_subdevice_t * subdevice, +static int me8200_dio_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -340,7 +340,7 @@ static int me8200_dio_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8200_dio_query_subdevice_type(me_subdevice_t * subdevice, +static int me8200_dio_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -349,7 +349,7 @@ static int me8200_dio_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8200_dio_query_subdevice_caps(me_subdevice_t * subdevice, +static int me8200_dio_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); @@ -359,7 +359,7 @@ static int me8200_dio_query_subdevice_caps(me_subdevice_t * subdevice, me8200_dio_subdevice_t *me8200_dio_constructor(uint32_t reg_base, unsigned int dio_idx, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me8200_dio_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me8200_do.c b/drivers/staging/meilhaus/me8200_do.c index d2bebd16ff41..40d536c71d50 100644 --- a/drivers/staging/meilhaus/me8200_do.c +++ b/drivers/staging/meilhaus/me8200_do.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include @@ -59,7 +59,7 @@ * Functions */ -static int me8200_do_io_irq_start(me_subdevice_t * subdevice, +static int me8200_do_io_irq_start(me_subdevice_t *subdevice, struct file *filep, int channel, int irq_source, @@ -109,7 +109,7 @@ static int me8200_do_io_irq_start(me_subdevice_t * subdevice, return err; } -static int me8200_do_io_irq_wait(me_subdevice_t * subdevice, +static int me8200_do_io_irq_wait(me_subdevice_t *subdevice, struct file *filep, int channel, int *irq_count, @@ -184,7 +184,7 @@ static int me8200_do_io_irq_wait(me_subdevice_t * subdevice, return err; } -static int me8200_do_io_irq_stop(me_subdevice_t * subdevice, +static int me8200_do_io_irq_stop(me_subdevice_t *subdevice, struct file *filep, int channel, int flags) { me8200_do_subdevice_t *instance; @@ -262,7 +262,7 @@ static int me8200_do_io_reset_subdevice(struct me_subdevice *subdevice, return ME_ERRNO_SUCCESS; } -static int me8200_do_io_single_config(me_subdevice_t * subdevice, +static int me8200_do_io_single_config(me_subdevice_t *subdevice, struct file *filep, int channel, int single_config, @@ -307,7 +307,7 @@ static int me8200_do_io_single_config(me_subdevice_t * subdevice, return err; } -static int me8200_do_io_single_read(me_subdevice_t * subdevice, +static int me8200_do_io_single_read(me_subdevice_t *subdevice, struct file *filep, int channel, int *value, int time_out, int flags) @@ -354,7 +354,7 @@ static int me8200_do_io_single_read(me_subdevice_t * subdevice, return err; } -static int me8200_do_io_single_write(me_subdevice_t * subdevice, +static int me8200_do_io_single_write(me_subdevice_t *subdevice, struct file *filep, int channel, int value, int time_out, int flags) @@ -415,7 +415,7 @@ static int me8200_do_io_single_write(me_subdevice_t * subdevice, return err; } -static int me8200_do_query_number_channels(me_subdevice_t * subdevice, +static int me8200_do_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -423,7 +423,7 @@ static int me8200_do_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8200_do_query_subdevice_type(me_subdevice_t * subdevice, +static int me8200_do_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -432,7 +432,7 @@ static int me8200_do_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int me8200_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps) +static int me8200_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); *caps = ME_CAPS_DIO_OVER_TEMP_IRQ; @@ -452,11 +452,7 @@ static void me8200_do_destructor(struct me_subdevice *subdevice) kfree(instance); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) static irqreturn_t me8200_do_isr(int irq, void *dev_id) -#else -static irqreturn_t me8200_do_isr(int irq, void *dev_id, struct pt_regs *regs) -#endif { me8200_do_subdevice_t *instance; uint16_t ctrl; @@ -505,7 +501,7 @@ static irqreturn_t me8200_do_isr(int irq, void *dev_id, struct pt_regs *regs) me8200_do_subdevice_t *me8200_do_constructor(uint32_t reg_base, unsigned int do_idx, int irq, - spinlock_t * irq_mode_lock) + spinlock_t *irq_mode_lock) { me8200_do_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me8254.c b/drivers/staging/meilhaus/me8254.c index 6e44c3d7a0c7..d8f742a8ca99 100644 --- a/drivers/staging/meilhaus/me8254.c +++ b/drivers/staging/meilhaus/me8254.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -183,7 +183,7 @@ static int me8254_io_reset_subdevice(struct me_subdevice *subdevice, return err; } -static int me1400_ab_ref_config(me8254_subdevice_t * instance, int ref) +static int me1400_ab_ref_config(me8254_subdevice_t *instance, int ref) { uint8_t clk_src; @@ -291,7 +291,7 @@ static int me1400_ab_ref_config(me8254_subdevice_t * instance, int ref) return ME_ERRNO_SUCCESS; } -static int me1400_cd_ref_config(me8254_subdevice_t * instance, int ref) +static int me1400_cd_ref_config(me8254_subdevice_t *instance, int ref) { uint8_t clk_src; @@ -436,7 +436,7 @@ static int me1400_cd_ref_config(me8254_subdevice_t * instance, int ref) return ME_ERRNO_SUCCESS; } -static int me4600_ref_config(me8254_subdevice_t * instance, int ref) +static int me4600_ref_config(me8254_subdevice_t *instance, int ref) { switch (ref) { @@ -453,7 +453,7 @@ static int me4600_ref_config(me8254_subdevice_t * instance, int ref) return ME_ERRNO_SUCCESS; } -static int me8100_ref_config(me8254_subdevice_t * instance, int ref) +static int me8100_ref_config(me8254_subdevice_t *instance, int ref) { switch (ref) { @@ -962,8 +962,8 @@ me8254_subdevice_t *me8254_constructor(uint32_t device_id, uint32_t reg_base, unsigned int me8254_idx, unsigned int ctr_idx, - spinlock_t * ctrl_reg_lock, - spinlock_t * clk_src_reg_lock) + spinlock_t *ctrl_reg_lock, + spinlock_t *clk_src_reg_lock) { me8254_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/me8255.c b/drivers/staging/meilhaus/me8255.c index 180e7f8d2146..ec9c6389752f 100644 --- a/drivers/staging/meilhaus/me8255.c +++ b/drivers/staging/meilhaus/me8255.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -318,7 +318,7 @@ me8255_subdevice_t *me8255_constructor(uint32_t device_id, unsigned int me8255_idx, unsigned int dio_idx, int *ctrl_reg_mirror, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { me8255_subdevice_t *subdevice; int err; diff --git a/drivers/staging/meilhaus/mecirc_buf.h b/drivers/staging/meilhaus/mecirc_buf.h index e9b591eaa349..516658522ef1 100644 --- a/drivers/staging/meilhaus/mecirc_buf.h +++ b/drivers/staging/meilhaus/mecirc_buf.h @@ -40,19 +40,19 @@ typedef struct me_circ_buf { int volatile tail; } me_circ_buf_t; -static int inline me_circ_buf_values(me_circ_buf_t * buf) +static inline int me_circ_buf_values(me_circ_buf_t * buf) { // return ((buf->head - buf->tail) & (buf->count - 1)); return ((buf->head - buf->tail) & (buf->mask)); } -static int inline me_circ_buf_space(me_circ_buf_t * buf) +static inline int me_circ_buf_space(me_circ_buf_t * buf) { // return ((buf->tail - (buf->head + 1)) & (buf->count - 1)); return ((buf->tail - (buf->head + 1)) & (buf->mask)); } -static int inline me_circ_buf_values_to_end(me_circ_buf_t * buf) +static inline int me_circ_buf_values_to_end(me_circ_buf_t * buf) { int end; int n; @@ -63,7 +63,7 @@ static int inline me_circ_buf_values_to_end(me_circ_buf_t * buf) return (n < end) ? n : end; } -static int inline me_circ_buf_space_to_end(me_circ_buf_t * buf) +static inline int me_circ_buf_space_to_end(me_circ_buf_t * buf) { int end; int n; @@ -99,19 +99,19 @@ typedef struct me_circ_buf_16b { # endif //_CBUFF_32b_t /** How many values is in buffer */ -static int inline me_circ_buf_values(me_circ_buf_t * buf) +static inline int me_circ_buf_values(me_circ_buf_t * buf) { return ((buf->head - buf->tail) & (buf->mask)); } /** How many space left */ -static int inline me_circ_buf_space(me_circ_buf_t * buf) +static inline int me_circ_buf_space(me_circ_buf_t * buf) { return ((buf->tail - (buf->head + 1)) & (buf->mask)); } /** How many values can be read from buffor in one chunck. */ -static int inline me_circ_buf_values_to_end(me_circ_buf_t * buf) +static inline int me_circ_buf_values_to_end(me_circ_buf_t * buf) { return (buf->tail <= buf->head) ? (buf->head - buf->tail) : (buf->mask - buf->tail + @@ -119,7 +119,7 @@ static int inline me_circ_buf_values_to_end(me_circ_buf_t * buf) } /** How many values can be write to buffer in one chunck. */ -static int inline me_circ_buf_space_to_end(me_circ_buf_t * buf) +static inline int me_circ_buf_space_to_end(me_circ_buf_t * buf) { return (buf->tail <= buf->head) ? (buf->mask - buf->head + 1) : (buf->tail - diff --git a/drivers/staging/meilhaus/medevice.c b/drivers/staging/meilhaus/medevice.c index 8f62e16c7a37..75aaec0f681b 100644 --- a/drivers/staging/meilhaus/medevice.c +++ b/drivers/staging/meilhaus/medevice.c @@ -390,9 +390,9 @@ static int me_device_io_single_write(struct me_device *device, static int me_device_io_stream_config(struct me_device *device, struct file *filep, int subdevice, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags) { int err = ME_ERRNO_SUCCESS; @@ -1040,7 +1040,7 @@ static int me_device_query_timer(struct me_device *device, int subdevice, int timer, int *base_frequency, - uint64_t * min_ticks, uint64_t * max_ticks) + uint64_t *min_ticks, uint64_t *max_ticks) { int err = ME_ERRNO_SUCCESS; me_subdevice_t *s; @@ -1082,14 +1082,14 @@ static int me_device_query_version_device_driver(struct me_device *device, } static int me_device_config_load(struct me_device *device, struct file *filep, - me_cfg_device_entry_t * config) + me_cfg_device_entry_t *config) { PDEBUG("executed.\n"); return ME_ERRNO_SUCCESS; //If no need for config return success. // return ME_ERRNO_NOT_SUPPORTED; } -static void me_device_destructor(me_device_t * me_device) +static void me_device_destructor(me_device_t *me_device) { PDEBUG("executed.\n"); me_device_deinit(me_device); @@ -1581,7 +1581,7 @@ static int get_device_descriptions(uint16_t device_id, return 0; } -int me_device_pci_init(me_device_t * me_device, struct pci_dev *pci_device) +int me_device_pci_init(me_device_t *me_device, struct pci_dev *pci_device) { int err; int i; @@ -1720,7 +1720,7 @@ int me_device_pci_init(me_device_t * me_device, struct pci_dev *pci_device) return 1; } -void me_device_deinit(me_device_t * me_device) +void me_device_deinit(me_device_t *me_device) { PDEBUG("executed.\n"); diff --git a/drivers/staging/meilhaus/medlist.c b/drivers/staging/meilhaus/medlist.c index ef4e36955dc8..b6a4065d2da1 100644 --- a/drivers/staging/meilhaus/medlist.c +++ b/drivers/staging/meilhaus/medlist.c @@ -69,7 +69,7 @@ me_device_t *me_dlist_get_device(struct me_dlist * dlist, unsigned int index) return device; } -void me_dlist_add_device_tail(struct me_dlist *dlist, me_device_t * device) +void me_dlist_add_device_tail(struct me_dlist *dlist, me_device_t *device) { PDEBUG_LOCKS("called.\n"); @@ -99,7 +99,7 @@ me_device_t *me_dlist_del_device_tail(struct me_dlist *dlist) return device; } -int me_dlist_init(me_dlist_t * dlist) +int me_dlist_init(me_dlist_t *dlist) { PDEBUG_LOCKS("called.\n"); @@ -108,7 +108,7 @@ int me_dlist_init(me_dlist_t * dlist) return 0; } -void me_dlist_deinit(me_dlist_t * dlist) +void me_dlist_deinit(me_dlist_t *dlist) { struct list_head *s; diff --git a/drivers/staging/meilhaus/medlock.c b/drivers/staging/meilhaus/medlock.c index f649e3da4f05..8ded397214f8 100644 --- a/drivers/staging/meilhaus/medlock.c +++ b/drivers/staging/meilhaus/medlock.c @@ -65,7 +65,7 @@ int me_dlock_exit(struct me_dlock *dlock, struct file *filep) } int me_dlock_lock(struct me_dlock *dlock, - struct file *filep, int lock, int flags, me_slist_t * slist) + struct file *filep, int lock, int flags, me_slist_t *slist) { int err = ME_ERRNO_SUCCESS; int i; @@ -183,7 +183,7 @@ void me_dlock_deinit(struct me_dlock *dlock) PDEBUG_LOCKS("executed.\n"); } -int me_dlock_init(me_dlock_t * dlock) +int me_dlock_init(me_dlock_t *dlock) { PDEBUG_LOCKS("executed.\n"); diff --git a/drivers/staging/meilhaus/medummy.c b/drivers/staging/meilhaus/medummy.c index 6a9f08d50bb1..2423745f9575 100644 --- a/drivers/staging/meilhaus/medummy.c +++ b/drivers/staging/meilhaus/medummy.c @@ -47,7 +47,7 @@ #include "medummy.h" -static int medummy_io_irq_start(me_device_t * device, +static int medummy_io_irq_start(me_device_t *device, struct file *filep, int subdevice, int channel, @@ -58,7 +58,7 @@ static int medummy_io_irq_start(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_irq_wait(me_device_t * device, +static int medummy_io_irq_wait(me_device_t *device, struct file *filep, int subdevice, int channel, @@ -69,7 +69,7 @@ static int medummy_io_irq_wait(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_irq_stop(me_device_t * device, +static int medummy_io_irq_stop(me_device_t *device, struct file *filep, int subdevice, int channel, int flags) { @@ -77,14 +77,14 @@ static int medummy_io_irq_stop(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_reset_device(me_device_t * device, +static int medummy_io_reset_device(me_device_t *device, struct file *filep, int flags) { PDEBUG("executed.\n"); return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_reset_subdevice(me_device_t * device, +static int medummy_io_reset_subdevice(me_device_t *device, struct file *filep, int subdevice, int flags) { @@ -92,7 +92,7 @@ static int medummy_io_reset_subdevice(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_single_config(me_device_t * device, +static int medummy_io_single_config(me_device_t *device, struct file *filep, int subdevice, int channel, @@ -105,7 +105,7 @@ static int medummy_io_single_config(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_single_read(me_device_t * device, +static int medummy_io_single_read(me_device_t *device, struct file *filep, int subdevice, int channel, @@ -115,7 +115,7 @@ static int medummy_io_single_read(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_single_write(me_device_t * device, +static int medummy_io_single_write(me_device_t *device, struct file *filep, int subdevice, int channel, @@ -125,19 +125,19 @@ static int medummy_io_single_write(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_stream_config(me_device_t * device, +static int medummy_io_stream_config(me_device_t *device, struct file *filep, int subdevice, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags) { PDEBUG("executed.\n"); return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_stream_new_values(me_device_t * device, +static int medummy_io_stream_new_values(me_device_t *device, struct file *filep, int subdevice, int timeout, int *count, int flags) @@ -146,7 +146,7 @@ static int medummy_io_stream_new_values(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_stream_read(me_device_t * device, +static int medummy_io_stream_read(me_device_t *device, struct file *filep, int subdevice, int read_mode, @@ -156,7 +156,7 @@ static int medummy_io_stream_read(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_stream_start(me_device_t * device, +static int medummy_io_stream_start(me_device_t *device, struct file *filep, int subdevice, int start_mode, int time_out, int flags) @@ -165,7 +165,7 @@ static int medummy_io_stream_start(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_stream_status(me_device_t * device, +static int medummy_io_stream_status(me_device_t *device, struct file *filep, int subdevice, int wait, @@ -175,7 +175,7 @@ static int medummy_io_stream_status(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_stream_stop(me_device_t * device, +static int medummy_io_stream_stop(me_device_t *device, struct file *filep, int subdevice, int stop_mode, int flags) { @@ -183,7 +183,7 @@ static int medummy_io_stream_stop(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_io_stream_write(me_device_t * device, +static int medummy_io_stream_write(me_device_t *device, struct file *filep, int subdevice, int write_mode, @@ -193,14 +193,14 @@ static int medummy_io_stream_write(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_lock_device(me_device_t * device, +static int medummy_lock_device(me_device_t *device, struct file *filep, int lock, int flags) { PDEBUG("executed.\n"); return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_lock_subdevice(me_device_t * device, +static int medummy_lock_subdevice(me_device_t *device, struct file *filep, int subdevice, int lock, int flags) { @@ -208,7 +208,7 @@ static int medummy_lock_subdevice(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_description_device(me_device_t * device, +static int medummy_query_description_device(me_device_t *device, char **description) { medummy_device_t *instance = (medummy_device_t *) device; @@ -602,7 +602,7 @@ static int medummy_query_description_device(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_info_device(me_device_t * device, +static int medummy_query_info_device(me_device_t *device, int *vendor_id, int *device_id, int *serial_no, @@ -632,14 +632,14 @@ static int medummy_query_info_device(me_device_t * device, return ME_ERRNO_SUCCESS; } -static int medummy_query_name_device_driver(me_device_t * device, char **name) +static int medummy_query_name_device_driver(me_device_t *device, char **name) { PDEBUG("executed.\n"); *name = MEDUMMY_NAME_DRIVER; return ME_ERRNO_SUCCESS; } -static int medummy_query_name_device(me_device_t * device, char **name) +static int medummy_query_name_device(me_device_t *device, char **name) { medummy_device_t *instance = (medummy_device_t *) device; @@ -1012,41 +1012,41 @@ static int medummy_query_name_device(me_device_t * device, char **name) return ME_ERRNO_SUCCESS; } -static int medummy_query_number_subdevices(me_device_t * device, int *number) +static int medummy_query_number_subdevices(me_device_t *device, int *number) { PDEBUG("executed.\n"); return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_number_channels(me_device_t * device, +static int medummy_query_number_channels(me_device_t *device, int subdevice, int *number) { PDEBUG("executed.\n"); return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_number_ranges(me_device_t * device, +static int medummy_query_number_ranges(me_device_t *device, int subdevice, int unit, int *count) { PDEBUG("executed.\n"); return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_subdevice_type(me_device_t * device, +static int medummy_query_subdevice_type(me_device_t *device, int subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_subdevice_caps(me_device_t * device, +static int medummy_query_subdevice_caps(me_device_t *device, int subdevice, int *caps) { PDEBUG("executed.\n"); return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_subdevice_caps_args(me_device_t * device, +static int medummy_query_subdevice_caps_args(me_device_t *device, int subdevice, int cap, int *args, int count) { @@ -1054,7 +1054,7 @@ static int medummy_query_subdevice_caps_args(me_device_t * device, return ME_ERRNO_NOT_SUPPORTED; } -static int medummy_query_subdevice_by_type(me_device_t * device, +static int medummy_query_subdevice_by_type(me_device_t *device, int start_subdevice, int type, int subtype, int *subdevice) @@ -1063,7 +1063,7 @@ static int medummy_query_subdevice_by_type(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_range_by_min_max(me_device_t * device, +static int medummy_query_range_by_min_max(me_device_t *device, int subdevice, int unit, int *min, @@ -1073,7 +1073,7 @@ static int medummy_query_range_by_min_max(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_range_info(me_device_t * device, +static int medummy_query_range_info(me_device_t *device, int subdevice, int range, int *unit, int *min, int *max, int *maxdata) @@ -1082,17 +1082,17 @@ static int medummy_query_range_info(me_device_t * device, return ME_ERRNO_DEVICE_UNPLUGGED; } -int medummy_query_timer(me_device_t * device, +int medummy_query_timer(me_device_t *device, int subdevice, int timer, int *base_frequency, - uint64_t * min_ticks, uint64_t * max_ticks) + uint64_t *min_ticks, uint64_t *max_ticks) { PDEBUG("executed.\n"); return ME_ERRNO_DEVICE_UNPLUGGED; } -static int medummy_query_version_device_driver(me_device_t * device, +static int medummy_query_version_device_driver(me_device_t *device, int *version) { PDEBUG("executed.\n"); @@ -1101,7 +1101,7 @@ static int medummy_query_version_device_driver(me_device_t * device, return ME_ERRNO_SUCCESS; } -static void medummy_destructor(me_device_t * device) +static void medummy_destructor(me_device_t *device) { PDEBUG("executed.\n"); kfree(device); @@ -1113,7 +1113,7 @@ static int init_device_info(unsigned short vendor_id, int bus_type, int bus_no, int dev_no, - int func_no, medummy_device_t * instance) + int func_no, medummy_device_t *instance) { PDEBUG("executed.\n"); @@ -1129,14 +1129,14 @@ static int init_device_info(unsigned short vendor_id, return 0; } -static int medummy_config_load(me_device_t * device, struct file *filep, - me_cfg_device_entry_t * config) +static int medummy_config_load(me_device_t *device, struct file *filep, + me_cfg_device_entry_t *config) { PDEBUG("executed.\n"); return ME_ERRNO_SUCCESS; } -static int init_device_instance(me_device_t * device) +static int init_device_instance(me_device_t *device) { PDEBUG("executed.\n"); @@ -1238,6 +1238,7 @@ me_device_t *medummy_constructor(unsigned short vendor_id, return (me_device_t *) instance; } +EXPORT_SYMBOL(medummy_constructor); // Init and exit of module. @@ -1261,6 +1262,3 @@ MODULE_AUTHOR("Guenter Gebhardt "); MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-DUMMY Devices"); MODULE_SUPPORTED_DEVICE("Meilhaus ME-DUMMY Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(medummy_constructor); diff --git a/drivers/staging/meilhaus/memain.c b/drivers/staging/meilhaus/memain.c index b09d1a6c766c..fd9f079b0ed1 100644 --- a/drivers/staging/meilhaus/memain.c +++ b/drivers/staging/meilhaus/memain.c @@ -37,7 +37,7 @@ #include //#include #include -#include +#include #include #include @@ -56,6 +56,7 @@ #ifdef BOSCH static unsigned int me_bosch_fw = 0; +EXPORT_SYMBOL(me_bosch_fw); # ifdef module_param module_param(me_bosch_fw, int, S_IRUGO); @@ -79,7 +80,7 @@ MODULE_PARM(major, "i"); static struct file *me_filep = NULL; static int me_count = 0; -static spinlock_t me_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(me_lock); static DECLARE_RWSEM(me_rwsem); /* Board instances are kept in a global list */ @@ -90,7 +91,7 @@ LIST_HEAD(me_device_list); static int me_probe_pci(struct pci_dev *dev, const struct pci_device_id *id); static void me_remove_pci(struct pci_dev *dev); -static int insert_to_device_list(me_device_t * n_device); +static int insert_to_device_list(me_device_t *n_device); static int replace_with_dummy(int vendor_id, int device_id, int serial_no); static void clear_device_list(void); static int me_open(struct inode *inode_ptr, struct file *filep); @@ -472,7 +473,7 @@ static int me_probe_pci(struct pci_dev *dev, const struct pci_device_id *id) return ME_ERRNO_SUCCESS; } -static void release_instance(me_device_t * device) +static void release_instance(me_device_t *device) { int vendor_id; int device_id; @@ -517,7 +518,7 @@ static void release_instance(me_device_t * device) } } -static int insert_to_device_list(me_device_t * n_device) +static int insert_to_device_list(me_device_t *n_device) { me_device_t *o_device = NULL; @@ -762,7 +763,7 @@ static int lock_driver(struct file *filep, int lock, int flags) return err; } -static int me_lock_driver(struct file *filep, me_lock_driver_t * arg) +static int me_lock_driver(struct file *filep, me_lock_driver_t *arg) { int err = 0; @@ -807,7 +808,7 @@ static int me_release(struct inode *inode_ptr, struct file *filep) } static int me_query_version_main_driver(struct file *filep, - me_query_version_main_driver_t * arg) + me_query_version_main_driver_t *arg) { int err; me_query_version_main_driver_t karg; @@ -828,7 +829,7 @@ static int me_query_version_main_driver(struct file *filep, } static int me_config_load_device(struct file *filep, - me_cfg_device_entry_t * karg, int device_no) + me_cfg_device_entry_t *karg, int device_no) { int err = ME_ERRNO_SUCCESS; @@ -874,7 +875,7 @@ static int me_config_load_device(struct file *filep, return err; } -static int me_config_load(struct file *filep, me_config_load_t * arg) +static int me_config_load(struct file *filep, me_config_load_t *arg) { int err; int i; @@ -1170,7 +1171,7 @@ static int me_config_load(struct file *filep, me_config_load_t * arg) return 0; } -static int me_io_stream_start(struct file *filep, me_io_stream_start_t * arg) +static int me_io_stream_start(struct file *filep, me_io_stream_start_t *arg) { int err; int i, k; @@ -1292,7 +1293,7 @@ static int me_io_stream_start(struct file *filep, me_io_stream_start_t * arg) return err; } -static int me_io_single(struct file *filep, me_io_single_t * arg) +static int me_io_single(struct file *filep, me_io_single_t *arg) { int err; int i, k; @@ -1448,7 +1449,7 @@ static int me_io_single(struct file *filep, me_io_single_t * arg) return err; } -static int me_io_stream_config(struct file *filep, me_io_stream_config_t * arg) +static int me_io_stream_config(struct file *filep, me_io_stream_config_t *arg) { int err; int k = 0; @@ -1540,7 +1541,7 @@ static int me_io_stream_config(struct file *filep, me_io_stream_config_t * arg) } static int me_query_number_devices(struct file *filep, - me_query_number_devices_t * arg) + me_query_number_devices_t *arg) { int err; me_query_number_devices_t karg; @@ -1569,7 +1570,7 @@ static int me_query_number_devices(struct file *filep, return 0; } -static int me_io_stream_stop(struct file *filep, me_io_stream_stop_t * arg) +static int me_io_stream_stop(struct file *filep, me_io_stream_stop_t *arg) { int err; int i, k; @@ -2015,8 +2016,3 @@ MODULE_AUTHOR MODULE_DESCRIPTION("Central module for Meilhaus Driver System."); MODULE_SUPPORTED_DEVICE("Meilhaus PCI/cPCI boards."); MODULE_LICENSE("GPL"); - -#ifdef BOSCH -// Export the flag for the BOSCH firmware. -EXPORT_SYMBOL(me_bosch_fw); -#endif // BOSCH diff --git a/drivers/staging/meilhaus/meslist.c b/drivers/staging/meilhaus/meslist.c index 7e8b66c05f7e..ce49114df55f 100644 --- a/drivers/staging/meilhaus/meslist.c +++ b/drivers/staging/meilhaus/meslist.c @@ -115,7 +115,7 @@ int me_slist_get_subdevice_by_type(struct me_slist *slist, } void me_slist_add_subdevice_tail(struct me_slist *slist, - me_subdevice_t * subdevice) + me_subdevice_t *subdevice) { PDEBUG_LOCKS("called.\n"); @@ -145,7 +145,7 @@ me_subdevice_t *me_slist_del_subdevice_tail(struct me_slist *slist) return subdevice; } -int me_slist_init(me_slist_t * slist) +int me_slist_init(me_slist_t *slist) { PDEBUG_LOCKS("called.\n"); @@ -154,7 +154,7 @@ int me_slist_init(me_slist_t * slist) return 0; } -void me_slist_deinit(me_slist_t * slist) +void me_slist_deinit(me_slist_t *slist) { struct list_head *s; diff --git a/drivers/staging/meilhaus/meslock.c b/drivers/staging/meilhaus/meslock.c index 5230b89b45b5..abcdb4a2eba6 100644 --- a/drivers/staging/meilhaus/meslock.c +++ b/drivers/staging/meilhaus/meslock.c @@ -124,7 +124,7 @@ void me_slock_deinit(struct me_slock *slock) PDEBUG_LOCKS("executed.\n"); } -int me_slock_init(me_slock_t * slock) +int me_slock_init(me_slock_t *slock) { PDEBUG_LOCKS("executed.\n"); diff --git a/drivers/staging/meilhaus/mesubdevice.c b/drivers/staging/meilhaus/mesubdevice.c index 98d4f1f7a824..b2e956726b5f 100644 --- a/drivers/staging/meilhaus/mesubdevice.c +++ b/drivers/staging/meilhaus/mesubdevice.c @@ -101,9 +101,9 @@ static int me_subdevice_io_single_write(struct me_subdevice *subdevice, static int me_subdevice_io_stream_config(struct me_subdevice *subdevice, struct file *filep, - meIOStreamConfig_t * config_list, + meIOStreamConfig_t *config_list, int count, - meIOStreamTrigger_t * trigger, + meIOStreamTrigger_t *trigger, int fifo_irq_threshold, int flags) { PDEBUG("executed.\n"); @@ -162,7 +162,7 @@ static int me_subdevice_io_stream_write(struct me_subdevice *subdevice, return ME_ERRNO_NOT_SUPPORTED; } -static int me_subdevice_lock_subdevice(me_subdevice_t * subdevice, +static int me_subdevice_lock_subdevice(me_subdevice_t *subdevice, struct file *filep, int lock, int flags) { PDEBUG("executed.\n"); @@ -235,7 +235,7 @@ static int me_subdevice_query_timer(struct me_subdevice *subdevice, } static int me_subdevice_config_load(struct me_subdevice *subdevice, - me_cfg_device_entry_t * config) + me_cfg_device_entry_t *config) { PDEBUG("executed.\n"); return ME_ERRNO_SUCCESS; @@ -248,7 +248,7 @@ static void me_subdevice_destructor(struct me_subdevice *subdevice) kfree(subdevice); } -int me_subdevice_init(me_subdevice_t * subdevice) +int me_subdevice_init(me_subdevice_t *subdevice) { int err; @@ -308,7 +308,7 @@ int me_subdevice_init(me_subdevice_t * subdevice) return 0; } -void me_subdevice_deinit(me_subdevice_t * subdevice) +void me_subdevice_deinit(me_subdevice_t *subdevice) { PDEBUG("executed.\n"); me_subdevice_io_reset_subdevice(subdevice, NULL, diff --git a/drivers/staging/meilhaus/metempl_device.c b/drivers/staging/meilhaus/metempl_device.c index e48632ddc1aa..bdaf6df72771 100644 --- a/drivers/staging/meilhaus/metempl_device.c +++ b/drivers/staging/meilhaus/metempl_device.c @@ -109,6 +109,7 @@ me_device_t *metempl_pci_constructor(struct pci_dev *pci_device) return (me_device_t *) metempl_device; } +EXPORT_SYMBOL(metempl_pci_constructor); // Init and exit of module. @@ -132,6 +133,3 @@ MODULE_AUTHOR("Guenter Gebhardt "); MODULE_DESCRIPTION("Device Driver Module for Template Device"); MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices"); MODULE_LICENSE("GPL"); - -// Export the constructor. -EXPORT_SYMBOL(metempl_pci_constructor); diff --git a/drivers/staging/meilhaus/metempl_sub.c b/drivers/staging/meilhaus/metempl_sub.c index f1d65d889e23..b5a6a978b509 100644 --- a/drivers/staging/meilhaus/metempl_sub.c +++ b/drivers/staging/meilhaus/metempl_sub.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include "medefines.h" @@ -68,7 +68,7 @@ static void metempl_sub_destructor(struct me_subdevice *subdevice) kfree(instance); } -static int metempl_sub_query_number_channels(me_subdevice_t * subdevice, +static int metempl_sub_query_number_channels(me_subdevice_t *subdevice, int *number) { PDEBUG("executed.\n"); @@ -76,7 +76,7 @@ static int metempl_sub_query_number_channels(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int metempl_sub_query_subdevice_type(me_subdevice_t * subdevice, +static int metempl_sub_query_subdevice_type(me_subdevice_t *subdevice, int *type, int *subtype) { PDEBUG("executed.\n"); @@ -85,7 +85,7 @@ static int metempl_sub_query_subdevice_type(me_subdevice_t * subdevice, return ME_ERRNO_SUCCESS; } -static int metempl_sub_query_subdevice_caps(me_subdevice_t * subdevice, +static int metempl_sub_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) { PDEBUG("executed.\n"); @@ -95,7 +95,7 @@ static int metempl_sub_query_subdevice_caps(me_subdevice_t * subdevice, metempl_sub_subdevice_t *metempl_sub_constructor(uint32_t reg_base, unsigned int sub_idx, - spinlock_t * ctrl_reg_lock) + spinlock_t *ctrl_reg_lock) { metempl_sub_subdevice_t *subdevice; int err; diff --git a/drivers/staging/mimio/Kconfig b/drivers/staging/mimio/Kconfig index c0ba4c800dff..505dcb275796 100644 --- a/drivers/staging/mimio/Kconfig +++ b/drivers/staging/mimio/Kconfig @@ -1,6 +1,6 @@ config INPUT_MIMIO tristate "Mimio Xi interactive whiteboard support" - depends on USB + depends on USB && INPUT default N help Say Y here if you want to use a Mimio Xi interactive diff --git a/drivers/staging/otus/80211core/amsdu.c b/drivers/staging/otus/80211core/amsdu.c index c9123d58b82f..0321288d107e 100644 --- a/drivers/staging/otus/80211core/amsdu.c +++ b/drivers/staging/otus/80211core/amsdu.c @@ -34,53 +34,53 @@ /* Stephen Chen Atheros Communications, INC. 2007.2 */ /* */ /************************************************************************/ -zbuf_t* zfGetAmsduSubFrame(zdev_t* dev, zbuf_t* buf, u16_t* offset) +zbuf_t *zfGetAmsduSubFrame(zdev_t *dev, zbuf_t *buf, u16_t *offset) { - u16_t subframeLen; - u16_t amsduLen = zfwBufGetSize(dev, buf); - zbuf_t* newBuf; + u16_t subframeLen; + u16_t amsduLen = zfwBufGetSize(dev, buf); + zbuf_t *newBuf; - ZM_PERFORMANCE_RX_AMSDU(dev, buf, amsduLen); + ZM_PERFORMANCE_RX_AMSDU(dev, buf, amsduLen); - /* Verify A-MSDU length */ - if (amsduLen < (*offset + 14)) - { - return NULL; - } + /* Verify A-MSDU length */ + if (amsduLen < (*offset + 14)) + return NULL; - /* Locate A-MSDU subframe by offset and verify subframe length */ - subframeLen = (zmw_buf_readb(dev, buf, *offset + 12) << 8) + - zmw_buf_readb(dev, buf, *offset + 13); - if (subframeLen == 0) - { - return NULL; - } + /* Locate A-MSDU subframe by offset and verify subframe length */ + subframeLen = (zmw_buf_readb(dev, buf, *offset + 12) << 8) + + zmw_buf_readb(dev, buf, *offset + 13); - /* Verify A-MSDU subframe length */ - if ((*offset+14+subframeLen) <= amsduLen) - { - /* Allocate a new buffer */ - if ((newBuf = zfwBufAllocate(dev, 24+2+subframeLen)) != NULL) - { -#ifdef ZM_ENABLE_NATIVE_WIFI - /* Copy and convert subframe to wlan frame format */ - /* SHALL NOT INCLUDE QOS and AMSDU header. Ray 20070807 For Vista */ - zfRxBufferCopy(dev, newBuf, buf, 0, 0, 24); - zfRxBufferCopy(dev, newBuf, buf, 24, *offset+14, subframeLen); - zfwBufSetSize(dev, newBuf, 24+subframeLen); -#else - /* Copy subframe to new buffer */ - zfRxBufferCopy(dev, newBuf, buf, 0, *offset, 14+subframeLen); - zfwBufSetSize(dev, newBuf, 14+subframeLen); -#endif - /* Update offset */ - *offset += (((14+subframeLen)+3) & 0xfffc); + if (subframeLen == 0) + return NULL; - /* Return buffer pointer */ - return newBuf; - } - } - return NULL; + /* Verify A-MSDU subframe length */ + if ((*offset+14+subframeLen) <= amsduLen) { + /* Allocate a new buffer */ + newBuf = zfwBufAllocate(dev, 24+2+subframeLen); + if (newBuf != NULL) { + #ifdef ZM_ENABLE_NATIVE_WIFI + /* Copy and convert subframe to wlan frame format + * SHALL NOT INCLUDE QOS and AMSDU header. + * Ray 20070807 For Vista + */ + zfRxBufferCopy(dev, newBuf, buf, 0, 0, 24); + zfRxBufferCopy(dev, newBuf, buf, 24, *offset+14, + subframeLen); + zfwBufSetSize(dev, newBuf, 24+subframeLen); + #else + /* Copy subframe to new buffer */ + zfRxBufferCopy(dev, newBuf, buf, 0, *offset, + 14+subframeLen); + zfwBufSetSize(dev, newBuf, 14+subframeLen); + #endif + /* Update offset */ + *offset += (((14+subframeLen)+3) & 0xfffc); + + /* Return buffer pointer */ + return newBuf; + } + } + return NULL; } @@ -101,34 +101,29 @@ zbuf_t* zfGetAmsduSubFrame(zdev_t* dev, zbuf_t* buf, u16_t* offset) /* Stephen Chen Atheros Communications, INC. 2007.2 */ /* */ /************************************************************************/ -void zfDeAmsdu(zdev_t* dev, zbuf_t* buf, u16_t vap, u8_t encryMode) +void zfDeAmsdu(zdev_t *dev, zbuf_t *buf, u16_t vap, u8_t encryMode) { - u16_t offset = ZM_SIZE_OF_WLAN_DATA_HEADER+ZM_SIZE_OF_QOS_CTRL; - zbuf_t* subframeBuf; - zmw_get_wlan_dev(dev); + u16_t offset = ZM_SIZE_OF_WLAN_DATA_HEADER+ZM_SIZE_OF_QOS_CTRL; + zbuf_t *subframeBuf; + zmw_get_wlan_dev(dev); - ZM_BUFFER_TRACE(dev, buf) + ZM_BUFFER_TRACE(dev, buf) - if (encryMode == ZM_AES || encryMode == ZM_TKIP) - { - offset += (ZM_SIZE_OF_IV + ZM_SIZE_OF_EXT_IV); - } - else if (encryMode == ZM_WEP64 || encryMode == ZM_WEP128) - { - offset += ZM_SIZE_OF_IV; - } + if (encryMode == ZM_AES || encryMode == ZM_TKIP) + offset += (ZM_SIZE_OF_IV + ZM_SIZE_OF_EXT_IV); + else if (encryMode == ZM_WEP64 || encryMode == ZM_WEP128) + offset += ZM_SIZE_OF_IV; - /* Repeatly calling zfGetAmsduSubFrame() until NULL returned */ - while ((subframeBuf = zfGetAmsduSubFrame(dev, buf, &offset)) != NULL) - { - wd->commTally.NotifyNDISRxFrmCnt++; - if (wd->zfcbRecvEth != NULL) - { - wd->zfcbRecvEth(dev, subframeBuf, (u8_t)vap); - ZM_PERFORMANCE_RX_MSDU(dev, wd->tick); - } - } - zfwBufFree(dev, buf, 0); - return; + /* Repeatly calling zfGetAmsduSubFrame() until NULL returned */ + while ((subframeBuf = zfGetAmsduSubFrame(dev, buf, &offset)) != NULL) { + wd->commTally.NotifyNDISRxFrmCnt++; + if (wd->zfcbRecvEth != NULL) { + wd->zfcbRecvEth(dev, subframeBuf, (u8_t)vap); + ZM_PERFORMANCE_RX_MSDU(dev, wd->tick); + } + } + zfwBufFree(dev, buf, 0); + + return; } diff --git a/drivers/staging/otus/80211core/cmmsta.c b/drivers/staging/otus/80211core/cmmsta.c index c75ba11ee43d..b28a4e25e107 100644 --- a/drivers/staging/otus/80211core/cmmsta.c +++ b/drivers/staging/otus/80211core/cmmsta.c @@ -724,6 +724,9 @@ void zfStaUpdateWmeParameter(zdev_t* dev, zbuf_t* buf) /* process 802.11h Dynamic Frequency Selection */ void zfStaUpdateDot11HDFS(zdev_t* dev, zbuf_t* buf) { + //u8_t length, channel, is5G; + u16_t offset; + zmw_get_wlan_dev(dev); /* @@ -736,8 +739,6 @@ void zfStaUpdateDot11HDFS(zdev_t* dev, zbuf_t* buf) |Value | 37 | 3 | 0 or 1 |unsigned integer |unsigned integer | +------+----------+------+-------------------+------------------+--------------------+ */ - //u8_t length, channel, is5G; - u16_t offset; /* get EID(Channel Switch Announcement) */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CHANNEL_SWITCH_ANNOUNCE)) == 0xffff ) diff --git a/drivers/staging/otus/80211core/coid.c b/drivers/staging/otus/80211core/coid.c index 6007f3131f8f..88f8d3491a80 100644 --- a/drivers/staging/otus/80211core/coid.c +++ b/drivers/staging/otus/80211core/coid.c @@ -214,10 +214,10 @@ u32_t zfiWlanQuerySupportMode(zdev_t* dev) u32_t zfiWlanQueryTransmitPower(zdev_t* dev) { - zmw_get_wlan_dev(dev); - u32_t ret = 0; + zmw_get_wlan_dev(dev); + if (zfStaIsConnected(dev)) { ret = wd->sta.connPowerInHalfDbm; } else { @@ -1432,12 +1432,12 @@ u32_t zfiWlanQueryCurrentFrequency(zdev_t* dev, u8_t qmode) u32_t zfiWlanQueryFrequencyAttribute(zdev_t* dev, u32_t freq) { - zmw_get_wlan_dev(dev); - u8_t i; u16_t frequency = (u16_t) (freq/1000); u32_t ret = 0; + zmw_get_wlan_dev(dev); + for (i = 0; i < wd->regulationTable.allowChannelCnt; i++) { if ( wd->regulationTable.allowChannel[i].channel == frequency ) diff --git a/drivers/staging/otus/80211core/cwm.c b/drivers/staging/otus/80211core/cwm.c index 80f1141bf910..1bd0b1ff12dc 100644 --- a/drivers/staging/otus/80211core/cwm.c +++ b/drivers/staging/otus/80211core/cwm.c @@ -75,9 +75,9 @@ void zfCoreCwmBusy(zdev_t* dev, u16_t busy) if((wd->wlanMode == ZM_MODE_INFRASTRUCTURE || wd->wlanMode == ZM_MODE_PSEUDO || wd->wlanMode == ZM_MODE_IBSS)) { - if (wd->sta.ie.HtCap.HtCapInfo && HTCAP_SupChannelWidthSet != 0 && - wd->sta.ie.HtInfo.ChannelInfo && ExtHtCap_RecomTxWidthSet != 0 && - (wd->sta.ie.HtInfo.ChannelInfo && ExtHtCap_ExtChannelOffsetAbove) == 1) { + if ((wd->sta.ie.HtCap.HtCapInfo & HTCAP_SupChannelWidthSet) && + (wd->sta.ie.HtInfo.ChannelInfo & ExtHtCap_RecomTxWidthSet) && + (wd->sta.ie.HtInfo.ChannelInfo & ExtHtCap_ExtChannelOffsetAbove)) { wd->cwm.cw_width = CWM_WIDTH40; } diff --git a/drivers/staging/otus/TODO b/drivers/staging/otus/TODO index e912293ed1ed..4caf026a4915 100644 --- a/drivers/staging/otus/TODO +++ b/drivers/staging/otus/TODO @@ -1,8 +1,15 @@ +I'm hesitant to add a TODO file here, as the wireless developers would +really have people help them out on the "clean" ar9170 driver that can +be found at the linux-wireless developer site. + +But, if you wish to clean up this driver instead, here's a short list of +things that need to be done to get it into a more mergable shape: + TODO: - checkpatch.pl cleanups - sparse cleanups - port to in-kernel 80211 stack - - proper network developer maintainer + - review by the wireless developer community Please send any patches to Greg Kroah-Hartman and Luis Rodriguez and the diff --git a/drivers/staging/otus/hal/hpani.c b/drivers/staging/otus/hal/hpani.c index ba95b5d012a4..0afecd8c2de4 100644 --- a/drivers/staging/otus/hal/hpani.c +++ b/drivers/staging/otus/hal/hpani.c @@ -55,10 +55,10 @@ extern u16_t zfFlushDelayWrite(zdev_t* dev); s32_t BEACON_RSSI(zdev_t* dev) { s32_t rssi; + struct zsHpPriv *HpPriv; zmw_get_wlan_dev(dev); - - struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate; + HpPriv = (struct zsHpPriv*)wd->hpPrivate; rssi = ZM_HAL_EP_RND(HpPriv->stats.ast_nodestats.ns_avgbrssi, ZM_HAL_RSSI_EP_MULTIPLIER); @@ -74,16 +74,16 @@ void zfHpAniAttach(zdev_t* dev) { #define N(a) (sizeof(a) / sizeof(a[0])) u32_t i; - - zmw_get_wlan_dev(dev); - - struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate; + struct zsHpPriv *HpPriv; const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; const int coarseHigh[] = { -14, -14, -14, -14, -12 }; const int coarseLow[] = { -64, -64, -64, -64, -70 }; const int firpwr[] = { -78, -78, -78, -78, -80 }; + zmw_get_wlan_dev(dev); + HpPriv = (struct zsHpPriv*)wd->hpPrivate; + for (i = 0; i < 5; i++) { HpPriv->totalSizeDesired[i] = totalSizeDesired[i]; @@ -139,12 +139,12 @@ u8_t zfHpAniControl(zdev_t* dev, ZM_HAL_ANI_CMD cmd, int param) { #define N(a) (sizeof(a)/sizeof(a[0])) typedef s32_t TABLE[]; + struct zsHpPriv *HpPriv; + struct zsAniState *aniState; zmw_get_wlan_dev(dev); - - struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate; - - struct zsAniState *aniState = HpPriv->curani; + HpPriv = (struct zsHpPriv*)wd->hpPrivate; + aniState = HpPriv->curani; switch (cmd) { @@ -346,11 +346,10 @@ u8_t zfHpAniControl(zdev_t* dev, ZM_HAL_ANI_CMD cmd, int param) void zfHpAniRestart(zdev_t* dev) { struct zsAniState *aniState; + struct zsHpPriv *HpPriv; zmw_get_wlan_dev(dev); - - struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate; - + HpPriv = (struct zsHpPriv*)wd->hpPrivate; aniState = HpPriv->curani; aniState->listenTime = 0; @@ -387,10 +386,10 @@ void zfHpAniOfdmErrTrigger(zdev_t* dev) { struct zsAniState *aniState; s32_t rssi; + struct zsHpPriv *HpPriv; zmw_get_wlan_dev(dev); - - struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate; + HpPriv = (struct zsHpPriv*)wd->hpPrivate; //HALASSERT(chan != NULL); @@ -466,10 +465,10 @@ void zfHpAniCckErrTrigger(zdev_t* dev) { struct zsAniState *aniState; s32_t rssi; + struct zsHpPriv *HpPriv; zmw_get_wlan_dev(dev); - - struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate; + HpPriv = (struct zsHpPriv*)wd->hpPrivate; //HALASSERT(chan != NULL); @@ -511,11 +510,10 @@ void zfHpAniLowerImmunity(zdev_t* dev) { struct zsAniState *aniState; s32_t rssi; + struct zsHpPriv *HpPriv; zmw_get_wlan_dev(dev); - - struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate; - + HpPriv = (struct zsHpPriv*)wd->hpPrivate; aniState = HpPriv->curani; rssi = BEACON_RSSI(dev); @@ -586,10 +584,10 @@ s32_t zfHpAniGetListenTime(zdev_t* dev) struct zsAniState *aniState; u32_t txFrameCount, rxFrameCount, cycleCount; s32_t listenTime; + struct zsHpPriv *HpPriv; zmw_get_wlan_dev(dev); - - struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate; + HpPriv = (struct zsHpPriv*)wd->hpPrivate; txFrameCount = 0;//OS_REG_READ(ah, AR_TFCNT); rxFrameCount = 0;//OS_REG_READ(ah, AR_RFCNT); @@ -627,10 +625,10 @@ void zfHpAniArPoll(zdev_t* dev, u32_t listenTime, u32_t phyCnt1, u32_t phyCnt2) { struct zsAniState *aniState; //s32_t listenTime; + struct zsHpPriv *HpPriv; zmw_get_wlan_dev(dev); - - struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate; + HpPriv = (struct zsHpPriv*)wd->hpPrivate; /* * Since we're called from end of rx tasklet, we also check for diff --git a/drivers/staging/otus/hal/hpmain.c b/drivers/staging/otus/hal/hpmain.c index dab278326931..322585be2c88 100644 --- a/drivers/staging/otus/hal/hpmain.c +++ b/drivers/staging/otus/hal/hpmain.c @@ -328,8 +328,8 @@ void zfInitPhy(zdev_t* dev, u32_t frequency, u8_t bw40) u16_t modesIndex = 0; u16_t freqIndex = 0; u32_t tmp, tmp1; - zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + struct zsHpPriv* hpPriv; + u32_t eepromBoardData[15][6] = { /* Register A-20 A-20/40 G-20/40 G-20 G-Turbo */ {0x9964, 0, 0, 0, 0, 0}, @@ -349,6 +349,9 @@ void zfInitPhy(zdev_t* dev, u32_t frequency, u8_t bw40) {0xa258, 0, 0, 0, 0, 0}, }; + zmw_get_wlan_dev(dev); + hpPriv=wd->hpPrivate; + /* #1 Save the initial value of the related RIFS register settings */ //((struct zsHpPriv*)wd->hpPrivate)->isInitialPhy++; @@ -1324,9 +1327,10 @@ void zfHpSetFrequencyEx(zdev_t* dev, u32_t frequency, u8_t bw40, int delta_slope_coeff_man; int delta_slope_coeff_exp_shgi; int delta_slope_coeff_man_shgi; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv = wd->hpPrivate; + hpPriv = wd->hpPrivate; zm_msg1_scan(ZM_LV_1, "Frequency = ", frequency); zm_msg1_scan(ZM_LV_1, "bw40 = ", bw40); @@ -1560,9 +1564,10 @@ u16_t zfHpResetKeyCache(zdev_t* dev) { u8_t i; u32_t key[4] = {0, 0, 0, 0}; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; for(i=0;i<4;i++) { @@ -1601,9 +1606,10 @@ u32_t zfHpSetKey(zdev_t* dev, u8_t user, u8_t keyId, u8_t type, u32_t cmd[(ZM_MAX_CMD_SIZE/4)]; u16_t ret; u16_t i; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; #if 0 /* remove to zfCoreSetKey() */ zmw_declare_for_critical_section(); @@ -1670,8 +1676,10 @@ u32_t zfHpSetDefaultKey(zdev_t* dev, u8_t keyId, u8_t type, u32_t* key, u32_t* m u16_t macAddr[3] = {0, 0, 0}; #ifdef ZM_ENABLE_IBSS_WPA2PSK + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv = wd->hpPrivate; + hpPriv = wd->hpPrivate; if ( hpPriv->dot11Mode == ZM_HAL_80211_MODE_IBSS_WPA2PSK ) { /* If not wpa2psk , use traditional */ @@ -1702,8 +1710,10 @@ u32_t zfHpSetDefaultKey(zdev_t* dev, u8_t keyId, u8_t type, u32_t* key, u32_t* m u32_t zfHpSetPerUserKey(zdev_t* dev, u8_t user, u8_t keyId, u8_t* mac, u8_t type, u32_t* key, u32_t* micKey) { #ifdef ZM_ENABLE_IBSS_WPA2PSK + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv = wd->hpPrivate; + hpPriv = wd->hpPrivate; if ( hpPriv->dot11Mode == ZM_HAL_80211_MODE_IBSS_WPA2PSK ) { /* If not wpa2psk , use traditional */ @@ -1918,9 +1928,10 @@ u16_t zfHpSetSnifferMode(zdev_t* dev, u16_t on) u16_t zfHpSetApStaMode(zdev_t* dev, u8_t mode) { - zmw_get_wlan_dev(dev); + struct zsHpPriv* hpPriv; - struct zsHpPriv* hpPriv = wd->hpPrivate; + zmw_get_wlan_dev(dev); + hpPriv = wd->hpPrivate; hpPriv->dot11Mode = mode; switch(mode) @@ -1993,8 +2004,10 @@ u16_t zfHpSetBssid(zdev_t* dev, u8_t* bssidSrc) u8_t zfHpUpdateQosParameter(zdev_t* dev, u16_t* cwminTbl, u16_t* cwmaxTbl, u16_t* aifsTbl, u16_t* txopTbl) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv = wd->hpPrivate; + hpPriv = wd->hpPrivate; zm_msg0_mm(ZM_LV_0, "zfHalUpdateQosParameter()"); @@ -2259,9 +2272,11 @@ u32_t zfHpCwmUpdate(zdev_t* dev) // //ret = zfIssueCmd(dev, cmd, 12, ZM_CWM_READ, 0); //return ret; - zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + struct zsHpPriv* hpPriv; + + zmw_get_wlan_dev(dev); + hpPriv=wd->hpPrivate; zfCoreCwmBusy(dev, zfCwmIsExtChanBusy(hpPriv->ctlBusy, hpPriv->extBusy)); @@ -2291,9 +2306,10 @@ u32_t zfHpAniUpdate(zdev_t* dev) */ u32_t zfHpAniUpdateRssi(zdev_t* dev, u8_t rssi) { - zmw_get_wlan_dev(dev); + struct zsHpPriv* hpPriv; - struct zsHpPriv* hpPriv=wd->hpPrivate; + zmw_get_wlan_dev(dev); + hpPriv=wd->hpPrivate; hpPriv->stats.ast_nodestats.ns_avgbrssi = rssi; @@ -2325,11 +2341,12 @@ u32_t zfHpGetMacAddress(zdev_t* dev) u32_t zfHpGetTransmitPower(zdev_t* dev) { - zmw_get_wlan_dev(dev); - - struct zsHpPriv* hpPriv = wd->hpPrivate; + struct zsHpPriv* hpPriv; u16_t tpc = 0; + zmw_get_wlan_dev(dev); + hpPriv = wd->hpPrivate; + if (hpPriv->hwFrequency < 3000) { tpc = hpPriv->tPow2x2g[0] & 0x3f; wd->maxTxPower2 &= 0x3f; @@ -2345,11 +2362,12 @@ u32_t zfHpGetTransmitPower(zdev_t* dev) u8_t zfHpGetMinTxPower(zdev_t* dev) { - zmw_get_wlan_dev(dev); - - struct zsHpPriv* hpPriv = wd->hpPrivate; + struct zsHpPriv* hpPriv; u8_t tpc = 0; + zmw_get_wlan_dev(dev); + hpPriv = wd->hpPrivate; + if (hpPriv->hwFrequency < 3000) { if(wd->BandWidth40) @@ -2382,11 +2400,12 @@ u8_t zfHpGetMinTxPower(zdev_t* dev) u8_t zfHpGetMaxTxPower(zdev_t* dev) { - zmw_get_wlan_dev(dev); - - struct zsHpPriv* hpPriv = wd->hpPrivate; + struct zsHpPriv* hpPriv; u8_t tpc = 0; + zmw_get_wlan_dev(dev); + hpPriv = wd->hpPrivate; + if (hpPriv->hwFrequency < 3000) { tpc = (hpPriv->tPow2xCck[0]&0x3f); @@ -2421,11 +2440,13 @@ u32_t zfHpLoadEEPROMFromFW(zdev_t* dev) void zfHpHeartBeat(zdev_t* dev) { - zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + struct zsHpPriv* hpPriv; u8_t polluted = 0; u8_t ackTpc; + zmw_get_wlan_dev(dev); + hpPriv=wd->hpPrivate; + /* Workaround : Make OTUS fire more beacon in ad hoc mode in 2.4GHz */ if (hpPriv->ibssBcnEnabled != 0) { @@ -4219,8 +4240,10 @@ void zfHpPowerSaveSetMode(zdev_t* dev, u8_t staMode, u8_t psMode, u16_t bcnInter void zfHpPowerSaveSetState(zdev_t* dev, u8_t psState) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv = wd->hpPrivate; + hpPriv = wd->hpPrivate; //DbgPrint("INTO zfHpPowerSaveSetState"); @@ -4279,8 +4302,10 @@ void zfHpPowerSaveSetState(zdev_t* dev, u8_t psState) void zfHpSetAggPktNum(zdev_t* dev, u32_t num) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv = wd->hpPrivate; + hpPriv = wd->hpPrivate; num = (num << 16) | (0xa); @@ -4310,8 +4335,10 @@ void zfHpSetMPDUDensity(zdev_t* dev, u8_t density) void zfHpSetSlotTime(zdev_t* dev, u8_t type) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv = wd->hpPrivate; + hpPriv = wd->hpPrivate; if (type == 0) { @@ -4376,8 +4403,10 @@ void zfHpSetRifs(zdev_t* dev, u8_t ht_enable, u8_t ht2040, u8_t g_mode) void zfHpBeginSiteSurvey(zdev_t* dev, u8_t status) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; if ( status == 1 ) { // Connected @@ -4421,8 +4450,10 @@ void zfHpBeginSiteSurvey(zdev_t* dev, u8_t status) void zfHpFinishSiteSurvey(zdev_t* dev, u8_t status) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; zmw_declare_for_critical_section(); @@ -4527,16 +4558,20 @@ void zfHpSWEncrypt(zdev_t* dev, u8_t enable) u32_t zfHpCapability(zdev_t* dev) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; return hpPriv->halCapability; } void zfHpSetRollCallTable(zdev_t* dev) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; if (hpPriv->camRollCallTable != (u64_t) 0) { diff --git a/drivers/staging/otus/hal/hpreg.c b/drivers/staging/otus/hal/hpreg.c index 3cfeba8620f6..d9894fe5f4ec 100644 --- a/drivers/staging/otus/hal/hpreg.c +++ b/drivers/staging/otus/hal/hpreg.c @@ -1770,8 +1770,10 @@ void zfHpGetRegulationTable(zdev_t* dev, u16_t regionCode, u16_t c_lo, u16_t c_h REG_DOMAIN rd5GHz, rd2GHz; const struct cmode *cm; s16_t next=0,b; + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; zmw_declare_for_critical_section(); @@ -2473,9 +2475,10 @@ u8_t zfHpGetRegulatoryDomain(zdev_t* dev) void zfHpDisableDfsChannel(zdev_t* dev, u8_t disableFlag) { - zmw_get_wlan_dev(dev); + struct zsHpPriv* hpPriv; - struct zsHpPriv* hpPriv=wd->hpPrivate; + zmw_get_wlan_dev(dev); + hpPriv=wd->hpPrivate; hpPriv->disableDfsCh = disableFlag; return; } diff --git a/drivers/staging/otus/hal/hprw.c b/drivers/staging/otus/hal/hprw.c index db7d49576456..d9fad47d5d59 100644 --- a/drivers/staging/otus/hal/hprw.c +++ b/drivers/staging/otus/hal/hprw.c @@ -29,8 +29,10 @@ u16_t zfFlushDelayWrite(zdev_t* dev); void zfInitCmdQueue(zdev_t* dev) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv = (struct zsHpPriv*)(wd->hpPrivate); + hpPriv = (struct zsHpPriv*)(wd->hpPrivate); zmw_declare_for_critical_section(); @@ -48,9 +50,10 @@ void zfInitCmdQueue(zdev_t* dev) u16_t zfPutCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen, u16_t src, u8_t* buf) { u16_t i; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; /* Make sure command length < ZM_MAX_CMD_SIZE */ zm_assert(cmdLen <= ZM_MAX_CMD_SIZE); @@ -77,9 +80,10 @@ u16_t zfPutCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen, u16_t src, u8_t* buf) u16_t zfGetCmd(zdev_t* dev, u32_t* cmd, u16_t* cmdLen, u16_t* src, u8_t** buf) { u16_t i; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; if (hpPriv->cmdTail == hpPriv->cmdHead) { @@ -106,9 +110,10 @@ void zfSendCmdEx(zdev_t* dev) u16_t ncmdLen = 0; u16_t cmdFlag = 0; u16_t i; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; zmw_declare_for_critical_section(); @@ -141,8 +146,10 @@ void zfSendCmdEx(zdev_t* dev) void zfiSendCmdComp(zdev_t* dev) { + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; zmw_declare_for_critical_section(); @@ -158,9 +165,10 @@ u16_t zfIssueCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen, u16_t src, u8_t* buf) { u16_t cmdFlag = 0; u16_t ret; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; zmw_declare_for_critical_section(); @@ -214,9 +222,10 @@ void zfIdlRsp(zdev_t* dev, u32_t* rsp, u16_t rspLen) u16_t i; s32_t nf; s32_t noisefloor[4]; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; zmw_declare_for_critical_section(); @@ -826,9 +835,10 @@ u16_t zfDelayWriteInternalReg(zdev_t* dev, u32_t addr, u32_t val) u32_t cmd[(ZM_MAX_CMD_SIZE/4)]; u16_t i; u16_t ret; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; zmw_declare_for_critical_section(); @@ -892,8 +902,10 @@ u16_t zfFlushDelayWrite(zdev_t* dev) u32_t cmd[(ZM_MAX_CMD_SIZE/4)]; u16_t i; u16_t ret; + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; zmw_declare_for_critical_section(); diff --git a/drivers/staging/otus/hal/hpusb.c b/drivers/staging/otus/hal/hpusb.c index 4b76de93fff0..ee939005be7d 100644 --- a/drivers/staging/otus/hal/hpusb.c +++ b/drivers/staging/otus/hal/hpusb.c @@ -64,9 +64,10 @@ void zfAdjustCtrlSetting(zdev_t* dev, u16_t* header, zbuf_t* buf) u32_t oldPhyCtrl; u16_t tpc = 0; + struct zsHpPriv* hpPriv; zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; /* mm */ if (header == NULL) @@ -330,8 +331,10 @@ u16_t zfHpSend(zdev_t* dev, u16_t* header, u16_t headerLen, u16_t i; u16_t swlpOffset; #endif /* #if ZM_SW_LOOP_BACK == 1 */ + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; zm_msg1_tx(ZM_LV_1, "zfHpSend(), len = ", 12 + headerLen-8 + snapLen + zfwBufGetSize(dev, buf) + 4 + 8); @@ -576,8 +579,10 @@ void zfiUsbRecv(zdev_t *dev, zbuf_t *buf) u32_t rxMCS; u32_t rxBW; u32_t rxSG; + struct zsHpPriv* hpPriv; + zmw_get_wlan_dev(dev); - struct zsHpPriv* hpPriv=wd->hpPrivate; + hpPriv=wd->hpPrivate; //zm_msg0_rx(ZM_LV_0, "zfiUsbRecv()"); diff --git a/drivers/staging/otus/ioctl.c b/drivers/staging/otus/ioctl.c index 7a5c1e876b01..ce04218253dd 100644 --- a/drivers/staging/otus/ioctl.c +++ b/drivers/staging/otus/ioctl.c @@ -25,7 +25,7 @@ /************************************************************************/ #include #include -#include +#include #include "usbdrv.h" @@ -34,7 +34,7 @@ #define ZD_IOCTL_GETWPAIE (SIOCDEVPRIVATE + 3) #ifdef ZM_ENABLE_CENC #define ZM_IOCTL_CENC (SIOCDEVPRIVATE + 4) -#endif //ZM_ENABLE_CENC +#endif /* ZM_ENABLE_CENC */ #define ZD_PARAM_ROAMING 0x0001 #define ZD_PARAM_PRIVACY 0x0002 #define ZD_PARAM_WPA 0x0003 @@ -45,7 +45,7 @@ #ifdef ZM_ENABLE_CENC #define P80211_PACKET_CENCFLAG 0x0001 -#endif //ZM_ENABLE_CENC +#endif /* ZM_ENABLE_CENC */ #define P80211_PACKET_SETKEY 0x0003 #define ZD_CMD_SET_ENCRYPT_KEY 0x0001 @@ -62,204 +62,190 @@ #include #endif -extern u16_t zfLnxGetVapId(zdev_t* dev); +extern u16_t zfLnxGetVapId(zdev_t *dev); static const u32_t channel_frequency_11A[] = { -//Even element for Channel Number, Odd for Frequency - 36,5180, - 40,5200, - 44,5220, - 48,5240, - 52,5260, - 56,5280, - 60,5300, - 64,5320, - 100,5500, - 104,5520, - 108,5540, - 112,5560, - 116,5580, - 120,5600, - 124,5620, - 128,5640, - 132,5660, - 136,5680, - 140,5700, -// - 184,4920, - 188,4940, - 192,4960, - 196,4980, - 8,5040, - 12,5060, - 16,5080, - 34,5170, - 38,5190, - 42,5210, - 46,5230, -// - 149,5745, - 153,5765, - 157,5785, - 161,5805, - 165,5825 -// + /* Even element for Channel Number, Odd for Frequency */ + 36, 5180, + 40, 5200, + 44, 5220, + 48, 5240, + 52, 5260, + 56, 5280, + 60, 5300, + 64, 5320, + 100, 5500, + 104, 5520, + 108, 5540, + 112, 5560, + 116, 5580, + 120, 5600, + 124, 5620, + 128, 5640, + 132, 5660, + 136, 5680, + 140, 5700, + /**/ + 184, 4920, + 188, 4940, + 192, 4960, + 196, 4980, + 8, 5040, + 12, 5060, + 16, 5080, + 34, 5170, + 38, 5190, + 42, 5210, + 46, 5230, + /**/ + 149, 5745, + 153, 5765, + 157, 5785, + 161, 5805, + 165, 5825 + /**/ }; int usbdrv_freq2chan(u32_t freq) { - /* 2.4G Hz */ - if (freq > 2400 && freq < 3000) - { - return ((freq-2412)/5) + 1; - } - else - { - u16_t ii; - u16_t num_chan = sizeof(channel_frequency_11A)/sizeof(u32_t); + /* 2.4G Hz */ + if (freq > 2400 && freq < 3000) { + return ((freq-2412)/5) + 1; + } else { + u16_t ii; + u16_t num_chan = sizeof(channel_frequency_11A)/sizeof(u32_t); - for(ii = 1; ii < num_chan; ii += 2) - { - if (channel_frequency_11A[ii] == freq) - return channel_frequency_11A[ii-1]; - } - } + for (ii = 1; ii < num_chan; ii += 2) { + if (channel_frequency_11A[ii] == freq) + return channel_frequency_11A[ii-1]; + } + } - return 0; + return 0; } int usbdrv_chan2freq(int chan) { - int freq; + int freq; - /* If channel number is out of range */ - if (chan > 165 || chan <= 0) - return -1; + /* If channel number is out of range */ + if (chan > 165 || chan <= 0) + return -1; - /* 2.4G band */ - if (chan >= 1 && chan <= 13) - { - freq = (2412 + (chan - 1) * 5); - return freq; - } - else if (chan >= 36 && chan <= 165) - { - u16_t ii; - u16_t num_chan = sizeof(channel_frequency_11A)/sizeof(u32_t); + /* 2.4G band */ + if (chan >= 1 && chan <= 13) { + freq = (2412 + (chan - 1) * 5); + return freq; + } else if (chan >= 36 && chan <= 165) { + u16_t ii; + u16_t num_chan = sizeof(channel_frequency_11A)/sizeof(u32_t); - for(ii = 0; ii < num_chan; ii += 2) - { - if (channel_frequency_11A[ii] == chan) - return channel_frequency_11A[ii+1]; - } + for (ii = 0; ii < num_chan; ii += 2) { + if (channel_frequency_11A[ii] == chan) + return channel_frequency_11A[ii+1]; + } - /* Can't find desired frequency */ - if (ii == num_chan) - return -1; - } + /* Can't find desired frequency */ + if (ii == num_chan) + return -1; + } - /* Can't find deisred frequency */ - return -1; + /* Can't find deisred frequency */ + return -1; } int usbdrv_ioctl_setessid(struct net_device *dev, struct iw_point *erq) { -#ifdef ZM_HOSTAPD_SUPPORT - //struct usbdrv_private *macp = dev->ml_priv; - char essidbuf[IW_ESSID_MAX_SIZE+1]; - int i; + #ifdef ZM_HOSTAPD_SUPPORT + /* struct usbdrv_private *macp = dev->ml_priv; */ + char essidbuf[IW_ESSID_MAX_SIZE+1]; + int i; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - memset(essidbuf, 0, sizeof(essidbuf)); + memset(essidbuf, 0, sizeof(essidbuf)); - printk(KERN_ERR "usbdrv_ioctl_setessid\n"); + printk(KERN_ERR "usbdrv_ioctl_setessid\n"); - //printk("ssidlen=%d\n", erq->length); //for any, it is 1. - if (erq->flags) { - if (erq->length > (IW_ESSID_MAX_SIZE+1)) - return -E2BIG; + /* printk("ssidlen=%d\n", erq->length); //for any, it is 1. */ + if (erq->flags) { + if (erq->length > (IW_ESSID_MAX_SIZE+1)) + return -E2BIG; - if (copy_from_user(essidbuf, erq->pointer, erq->length)) - return -EFAULT; - } + if (copy_from_user(essidbuf, erq->pointer, erq->length)) + return -EFAULT; + } - //zd_DisasocAll(2); - //wait_ms(100); + /* zd_DisasocAll(2); */ + /* wait_ms(100); */ - printk(KERN_ERR "essidbuf: "); + printk(KERN_ERR "essidbuf: "); - for(i = 0; i < erq->length; i++) - { - printk(KERN_ERR "%02x ", essidbuf[i]); - } + for (i = 0; i < erq->length; i++) + printk(KERN_ERR "%02x ", essidbuf[i]); - printk(KERN_ERR "\n"); + printk(KERN_ERR "\n"); - essidbuf[erq->length] = '\0'; - //memcpy(macp->wd.ws.ssid, essidbuf, erq->length); - //macp->wd.ws.ssidLen = strlen(essidbuf)+2; - //macp->wd.ws.ssid[1] = strlen(essidbuf); // Update ssid length + essidbuf[erq->length] = '\0'; + /* memcpy(macp->wd.ws.ssid, essidbuf, erq->length); */ + /* macp->wd.ws.ssidLen = strlen(essidbuf)+2; */ + /* macp->wd.ws.ssid[1] = strlen(essidbuf); Update ssid length */ - zfiWlanSetSSID(dev, essidbuf, erq->length); -#if 0 - printk(KERN_ERR "macp->wd.ws.ssid: "); + zfiWlanSetSSID(dev, essidbuf, erq->length); + #if 0 + printk(KERN_ERR "macp->wd.ws.ssid: "); - for(i = 0; i < macp->wd.ws.ssidLen; i++) - { - printk(KERN_ERR "%02x ", macp->wd.ws.ssid[i]); - } + for (i = 0; i < macp->wd.ws.ssidLen; i++) + printk(KERN_ERR "%02x ", macp->wd.ws.ssid[i]); - printk(KERN_ERR "\n"); -#endif - zfiWlanDisable(dev, 0); - zfiWlanEnable(dev); + printk(KERN_ERR "\n"); + #endif -#endif + zfiWlanDisable(dev, 0); + zfiWlanEnable(dev); - return 0; + #endif + + return 0; } int usbdrv_ioctl_getessid(struct net_device *dev, struct iw_point *erq) { - //struct usbdrv_private *macp = dev->ml_priv; - u8_t essidbuf[IW_ESSID_MAX_SIZE+1]; - u8_t len; - u8_t i; + /* struct usbdrv_private *macp = dev->ml_priv; */ + u8_t essidbuf[IW_ESSID_MAX_SIZE+1]; + u8_t len; + u8_t i; - //len = macp->wd.ws.ssidLen; - //memcpy(essidbuf, macp->wd.ws.ssid, macp->wd.ws.ssidLen); - zfiWlanQuerySSID(dev, essidbuf, &len); + /* len = macp->wd.ws.ssidLen; */ + /* memcpy(essidbuf, macp->wd.ws.ssid, macp->wd.ws.ssidLen); */ + zfiWlanQuerySSID(dev, essidbuf, &len); - essidbuf[len] = 0; + essidbuf[len] = 0; - printk(KERN_ERR "ESSID: "); + printk(KERN_ERR "ESSID: "); - for(i = 0; i < len; i++) - { - printk(KERN_ERR "%c", essidbuf[i]); - } + for (i = 0; i < len; i++) + printk(KERN_ERR "%c", essidbuf[i]); - printk(KERN_ERR "\n"); + printk(KERN_ERR "\n"); - erq->flags= 1; - erq->length = strlen(essidbuf) + 1; + erq->flags = 1; + erq->length = strlen(essidbuf) + 1; - if (erq->pointer) - if (copy_to_user(erq->pointer, essidbuf, erq->length)) - return -EFAULT; + if (erq->pointer) { + if (copy_to_user(erq->pointer, essidbuf, erq->length)) + return -EFAULT; + } - return 0; + return 0; } - int usbdrv_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) { - - return 0; + return 0; } #if WIRELESS_EXT > 14 @@ -267,462 +253,418 @@ int usbdrv_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) * Encode a WPA or RSN information element as a custom * element using the hostap format. */ -u32 encode_ie(void *buf, u32 bufsize, const u8 *ie, u32 ielen, const u8 *leader, u32 leader_len) +u32 encode_ie(void *buf, u32 bufsize, const u8 *ie, u32 ielen, + const u8 *leader, u32 leader_len) { - u8 *p; - u32 i; + u8 *p; + u32 i; - if (bufsize < leader_len) - return 0; - p = buf; - memcpy(p, leader, leader_len); - bufsize -= leader_len; - p += leader_len; - for (i = 0; i < ielen && bufsize > 2; i++) - p += sprintf(p, "%02x", ie[i]); - return (i == ielen ? p - (u8 *)buf : 0); + if (bufsize < leader_len) + return 0; + p = buf; + memcpy(p, leader, leader_len); + bufsize -= leader_len; + p += leader_len; + for (i = 0; i < ielen && bufsize > 2; i++) + p += sprintf(p, "%02x", ie[i]); + return (i == ielen ? p - (u8 *)buf:0); } -#endif /* WIRELESS_EXT > 14 */ +#endif /* WIRELESS_EXT > 14 */ -/*------------------------------------------------------------------*/ /* * Translate scan data returned from the card to a card independent * format that the Wireless Tools will understand */ char *usbdrv_translate_scan(struct net_device *dev, struct iw_request_info *info, char *current_ev, - char *end_buf, struct zsBssInfo *list) + char *end_buf, struct zsBssInfo *list) { - struct iw_event iwe; /* Temporary buffer */ - u16_t capabilities; - char *current_val; /* For rates */ - char *last_ev; - int i; -#if WIRELESS_EXT > 14 - char buf[64*2 + 30]; -#endif + struct iw_event iwe; /* Temporary buffer */ + u16_t capabilities; + char *current_val; /* For rates */ + char *last_ev; + int i; + #if WIRELESS_EXT > 14 + char buf[64*2 + 30]; + #endif - last_ev = current_ev; + last_ev = current_ev; -/* First entry *MUST* be the AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN); - current_ev = iwe_stream_add_event( - info, - current_ev, - end_buf, &iwe, IW_EV_ADDR_LEN); + /* First entry *MUST* be the AP MAC address */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN); + current_ev = iwe_stream_add_event(info, current_ev, + end_buf, &iwe, IW_EV_ADDR_LEN); - /* Ran out of buffer */ - if (last_ev == current_ev) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_ev) + return end_buf; - last_ev = current_ev; + last_ev = current_ev; -/* Other entries will be displayed in the order we give them */ + /* Other entries will be displayed in the order we give them */ -/* Add the ESSID */ - iwe.u.data.length = list->ssid[1]; - if(iwe.u.data.length > 32) - iwe.u.data.length = 32; - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point( - info, - current_ev, end_buf, &iwe, &list->ssid[2]); + /* Add the ESSID */ + iwe.u.data.length = list->ssid[1]; + if (iwe.u.data.length > 32) + iwe.u.data.length = 32; + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, &iwe, &list->ssid[2]); - /* Ran out of buffer */ - if (last_ev == current_ev) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_ev) + return end_buf; - last_ev = current_ev; + last_ev = current_ev; -/* Add mode */ - iwe.cmd = SIOCGIWMODE; - capabilities = (list->capability[1] << 8) + list->capability[0]; - if(capabilities & (0x01 | 0x02)) - { - if(capabilities & 0x01) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event( - info, - current_ev, end_buf, &iwe, IW_EV_UINT_LEN); - } + /* Add mode */ + iwe.cmd = SIOCGIWMODE; + capabilities = (list->capability[1] << 8) + list->capability[0]; + if (capabilities & (0x01 | 0x02)) { + if (capabilities & 0x01) + iwe.u.mode = IW_MODE_MASTER; + else + iwe.u.mode = IW_MODE_ADHOC; + current_ev = iwe_stream_add_event(info, current_ev, + end_buf, &iwe, IW_EV_UINT_LEN); + } - /* Ran out of buffer */ - if (last_ev == current_ev) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_ev) + return end_buf; - last_ev = current_ev; + last_ev = current_ev; -/* Add frequency */ - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = list->channel; -/* Channel frequency in KHz */ - if (iwe.u.freq.m > 14) - { - if ((184 <= iwe.u.freq.m) && (iwe.u.freq.m<=196)) - iwe.u.freq.m = 4000 + iwe.u.freq.m * 5; - else - iwe.u.freq.m = 5000 + iwe.u.freq.m * 5; - } - else - { - if (iwe.u.freq.m == 14) - iwe.u.freq.m = 2484; - else - iwe.u.freq.m = 2412 + (iwe.u.freq.m - 1) * 5; - } - iwe.u.freq.e = 6; - current_ev = iwe_stream_add_event( - info, - current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); + /* Add frequency */ + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = list->channel; + /* Channel frequency in KHz */ + if (iwe.u.freq.m > 14) { + if ((184 <= iwe.u.freq.m) && (iwe.u.freq.m <= 196)) + iwe.u.freq.m = 4000 + iwe.u.freq.m * 5; + else + iwe.u.freq.m = 5000 + iwe.u.freq.m * 5; + } else { + if (iwe.u.freq.m == 14) + iwe.u.freq.m = 2484; + else + iwe.u.freq.m = 2412 + (iwe.u.freq.m - 1) * 5; + } + iwe.u.freq.e = 6; + current_ev = iwe_stream_add_event(info, current_ev, + end_buf, &iwe, IW_EV_FREQ_LEN); - /* Ran out of buffer */ - if (last_ev == current_ev) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_ev) + return end_buf; - last_ev = current_ev; + last_ev = current_ev; -/* Add quality statistics */ - iwe.cmd = IWEVQUAL; -#if WIRELESS_EXT > 18 - iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED - |IW_QUAL_NOISE_UPDATED; -#endif - iwe.u.qual.level = list->signalStrength; - iwe.u.qual.noise = 0; - iwe.u.qual.qual = list->signalQuality; - current_ev = iwe_stream_add_event( - info, - current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + /* Add quality statistics */ + iwe.cmd = IWEVQUAL; + #if WIRELESS_EXT > 18 + iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED + | IW_QUAL_NOISE_UPDATED; + #endif + iwe.u.qual.level = list->signalStrength; + iwe.u.qual.noise = 0; + iwe.u.qual.qual = list->signalQuality; + current_ev = iwe_stream_add_event(info, current_ev, + end_buf, &iwe, IW_EV_QUAL_LEN); - /* Ran out of buffer */ - if (last_ev == current_ev) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_ev) + return end_buf; - last_ev = current_ev; + last_ev = current_ev; -/* Add encryption capability */ + /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if(capabilities & 0x10) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.cmd = SIOCGIWENCODE; + if (capabilities & 0x10) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point( - info, - current_ev, end_buf, &iwe, list->ssid); + iwe.u.data.length = 0; + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, &iwe, list->ssid); - /* Ran out of buffer */ - if (last_ev == current_ev) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_ev) + return end_buf; - last_ev = current_ev; + last_ev = current_ev; -/* Rate : stuffing multiple values in a single event require a bit - * more of magic */ - current_val = current_ev + IW_EV_LCP_LEN; + /* Rate : stuffing multiple values in a single event require a bit + * more of magic + */ + current_val = current_ev + IW_EV_LCP_LEN; - iwe.cmd = SIOCGIWRATE; -/* Those two flags are ignored... */ - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + iwe.cmd = SIOCGIWRATE; + /* Those two flags are ignored... */ + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - for(i = 0 ; i < list->supportedRates[1] ; i++) - { -/* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((list->supportedRates[i+2] & 0x7f) * 500000); -/* Add new value to event */ - current_val = iwe_stream_add_value( - info, - current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + for (i = 0 ; i < list->supportedRates[1] ; i++) { + /* Bit rate given in 500 kb/s units (+ 0x80) */ + iwe.u.bitrate.value = ((list->supportedRates[i+2] & 0x7f) + * 500000); + /* Add new value to event */ + current_val = iwe_stream_add_value(info, current_ev, + current_val, end_buf, &iwe, IW_EV_PARAM_LEN); - /* Ran out of buffer */ - if (last_ev == current_val) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_val) + return end_buf; - last_ev = current_val; - } + last_ev = current_val; + } - for (i = 0 ; i < list->extSupportedRates[1] ; i++) - { -/* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((list->extSupportedRates[i+2] & 0x7f) * 500000); -/* Add new value to event */ - current_val = iwe_stream_add_value( - info, - current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + for (i = 0 ; i < list->extSupportedRates[1] ; i++) { + /* Bit rate given in 500 kb/s units (+ 0x80) */ + iwe.u.bitrate.value = ((list->extSupportedRates[i+2] & 0x7f) + * 500000); + /* Add new value to event */ + current_val = iwe_stream_add_value(info, current_ev, + current_val, end_buf, &iwe, IW_EV_PARAM_LEN); - /* Ran out of buffer */ - if (last_ev == current_val) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_val) + return end_buf; - last_ev = current_ev; - } + last_ev = current_ev; + } -/* Check if we added any event */ - if((current_val - current_ev) > IW_EV_LCP_LEN) - current_ev = current_val; -#if WIRELESS_EXT > 14 -#define IEEE80211_ELEMID_RSN 0x30 - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - snprintf(buf, sizeof(buf), "bcn_int=%d", (list->beaconInterval[1] << 8) + list->beaconInterval[0]); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point( - info, - current_ev, end_buf, &iwe, buf); + /* Check if we added any event */ + if ((current_val - current_ev) > IW_EV_LCP_LEN) + current_ev = current_val; + #if WIRELESS_EXT > 14 + #define IEEE80211_ELEMID_RSN 0x30 + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + snprintf(buf, sizeof(buf), "bcn_int=%d", (list->beaconInterval[1] << 8) + + list->beaconInterval[0]); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, &iwe, buf); - /* Ran out of buffer */ - if (last_ev == current_ev) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_ev) + return end_buf; - last_ev = current_ev; + last_ev = current_ev; - if (list->wpaIe[1] != 0) - { - static const char rsn_leader[] = "rsn_ie="; - static const char wpa_leader[] = "wpa_ie="; + if (list->wpaIe[1] != 0) { + static const char rsn_leader[] = "rsn_ie="; + static const char wpa_leader[] = "wpa_ie="; - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - if (list->wpaIe[0] == IEEE80211_ELEMID_RSN) - iwe.u.data.length = encode_ie(buf, sizeof(buf), - list->wpaIe, list->wpaIe[1]+2, - rsn_leader, sizeof(rsn_leader)-1); - else - iwe.u.data.length = encode_ie(buf, sizeof(buf), - list->wpaIe, list->wpaIe[1]+2, - wpa_leader, sizeof(wpa_leader)-1); + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + if (list->wpaIe[0] == IEEE80211_ELEMID_RSN) + iwe.u.data.length = encode_ie(buf, sizeof(buf), + list->wpaIe, list->wpaIe[1]+2, + rsn_leader, sizeof(rsn_leader)-1); + else + iwe.u.data.length = encode_ie(buf, sizeof(buf), + list->wpaIe, list->wpaIe[1]+2, + wpa_leader, sizeof(wpa_leader)-1); - if (iwe.u.data.length != 0) - current_ev = iwe_stream_add_point( - info, - current_ev, end_buf, &iwe, buf); + if (iwe.u.data.length != 0) + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, &iwe, buf); - /* Ran out of buffer */ - if (last_ev == current_ev) - { - return end_buf; - } + /* Ran out of buffer */ + if (last_ev == current_ev) + return end_buf; - last_ev = current_ev; - } - if (list->rsnIe[1] != 0) - { - static const char rsn_leader[] = "rsn_ie="; - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; + last_ev = current_ev; + } - if (list->rsnIe[0] == IEEE80211_ELEMID_RSN) - { - iwe.u.data.length = encode_ie(buf, sizeof(buf), - list->rsnIe, list->rsnIe[1]+2, - rsn_leader, sizeof(rsn_leader)-1); - if (iwe.u.data.length != 0) - current_ev = iwe_stream_add_point( - info, - current_ev, end_buf, &iwe, buf); + if (list->rsnIe[1] != 0) { + static const char rsn_leader[] = "rsn_ie="; + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; - /* Ran out of buffer */ - if (last_ev == current_ev) - { - return end_buf; - } + if (list->rsnIe[0] == IEEE80211_ELEMID_RSN) { + iwe.u.data.length = encode_ie(buf, sizeof(buf), + list->rsnIe, list->rsnIe[1]+2, + rsn_leader, sizeof(rsn_leader)-1); + if (iwe.u.data.length != 0) + current_ev = iwe_stream_add_point(info, + current_ev, end_buf, &iwe, buf); - last_ev = current_ev; - } - } -#endif -/* The other data in the scan result are not really - * interesting, so for now drop it */ - return current_ev; + /* Ran out of buffer */ + if (last_ev == current_ev) + return end_buf; + + last_ev = current_ev; + } + } + #endif + /* The other data in the scan result are not really + * interesting, so for now drop it + */ + return current_ev; } int usbdrvwext_giwname(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrq, char *extra) + struct iw_request_info *info, + union iwreq_data *wrq, char *extra) { - //struct usbdrv_private *macp = dev->ml_priv; + /* struct usbdrv_private *macp = dev->ml_priv; */ - strcpy(wrq->name, "IEEE 802.11-MIMO"); + strcpy(wrq->name, "IEEE 802.11-MIMO"); - return 0; + return 0; } int usbdrvwext_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) + struct iw_request_info *info, + struct iw_freq *freq, char *extra) { - u32_t FreqKHz; - struct usbdrv_private *macp = dev->ml_priv; + u32_t FreqKHz; + struct usbdrv_private *macp = dev->ml_priv; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if (freq->e > 1) - return -EINVAL; + if (freq->e > 1) + return -EINVAL; - if (freq->e == 1) - { - FreqKHz = (freq->m / 100000); + if (freq->e == 1) { + FreqKHz = (freq->m / 100000); - if (FreqKHz > 4000000) - { - if (FreqKHz > 5825000) - FreqKHz = 5825000; - else if (FreqKHz < 4920000) - FreqKHz = 4920000; - else if (FreqKHz < 5000000) - FreqKHz = (((FreqKHz - 4000000) / 5000) * 5000) + 4000000; - else - FreqKHz = (((FreqKHz - 5000000) / 5000) * 5000) + 5000000; - } - else - { - if (FreqKHz > 2484000) - FreqKHz = 2484000; - else if (FreqKHz < 2412000) - FreqKHz = 2412000; - else - FreqKHz = (((FreqKHz - 2412000) / 5000) * 5000) + 2412000; - } + if (FreqKHz > 4000000) { + if (FreqKHz > 5825000) + FreqKHz = 5825000; + else if (FreqKHz < 4920000) + FreqKHz = 4920000; + else if (FreqKHz < 5000000) + FreqKHz = (((FreqKHz - 4000000) / 5000) * 5000) + + 4000000; + else + FreqKHz = (((FreqKHz - 5000000) / 5000) * 5000) + + 5000000; + } else { + if (FreqKHz > 2484000) + FreqKHz = 2484000; + else if (FreqKHz < 2412000) + FreqKHz = 2412000; + else + FreqKHz = (((FreqKHz - 2412000) / 5000) * 5000) + + 2412000; + } + } else { + FreqKHz = usbdrv_chan2freq(freq->m); - } - else - { - FreqKHz = usbdrv_chan2freq(freq->m); + if (FreqKHz != -1) + FreqKHz *= 1000; + else + FreqKHz = 2412000; + } - if (FreqKHz != -1) - FreqKHz *= 1000; - else - FreqKHz = 2412000; - } + /* printk("freq->m: %d, freq->e: %d\n", freq->m, freq->e); */ + /* printk("FreqKHz: %d\n", FreqKHz); */ - //printk("freq->m: %d, freq->e: %d\n", freq->m, freq->e); - //printk("FreqKHz: %d\n", FreqKHz); + if (macp->DeviceOpened == 1) { + zfiWlanSetFrequency(dev, FreqKHz, 0); /* Immediate */ + /* u8_t wpaieLen,wpaie[50]; */ + /* zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen); */ + zfiWlanDisable(dev, 0); + zfiWlanEnable(dev); + /* if (wpaieLen > 2) */ + /* zfiWlanSetWpaIe(dev, wpaie, wpaieLen); */ + } - if (macp->DeviceOpened == 1) - { - zfiWlanSetFrequency(dev, FreqKHz, 0); // Immediate - //u8_t wpaieLen,wpaie[50]; - //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen); - zfiWlanDisable(dev, 0); - zfiWlanEnable(dev); - //if (wpaieLen > 2) - // zfiWlanSetWpaIe(dev, wpaie, wpaieLen); - } - - return 0; + return 0; } int usbdrvwext_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) + struct iw_request_info *info, + struct iw_freq *freq, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; + struct usbdrv_private *macp = dev->ml_priv; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - freq->m = zfiWlanQueryFrequency(dev); - freq->e = 3; + freq->m = zfiWlanQueryFrequency(dev); + freq->e = 3; - return 0; + return 0; } int usbdrvwext_siwmode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrq, char *extra) + struct iw_request_info *info, + union iwreq_data *wrq, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; - u8_t WlanMode; + struct usbdrv_private *macp = dev->ml_priv; + u8_t WlanMode; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - switch(wrq->mode) - { - case IW_MODE_MASTER: - WlanMode = ZM_MODE_AP; - break; - case IW_MODE_INFRA: - WlanMode = ZM_MODE_INFRASTRUCTURE; - break; - case IW_MODE_ADHOC: - WlanMode = ZM_MODE_IBSS; - break; - default: - WlanMode = ZM_MODE_IBSS; - break; - } + switch (wrq->mode) { + case IW_MODE_MASTER: + WlanMode = ZM_MODE_AP; + break; + case IW_MODE_INFRA: + WlanMode = ZM_MODE_INFRASTRUCTURE; + break; + case IW_MODE_ADHOC: + WlanMode = ZM_MODE_IBSS; + break; + default: + WlanMode = ZM_MODE_IBSS; + break; + } - zfiWlanSetWlanMode(dev,WlanMode); - zfiWlanDisable(dev, 1); - zfiWlanEnable(dev); + zfiWlanSetWlanMode(dev, WlanMode); + zfiWlanDisable(dev, 1); + zfiWlanEnable(dev); - return 0; + return 0; } int usbdrvwext_giwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) + struct iw_request_info *info, + __u32 *mode, char *extra) { - unsigned long irqFlag; - struct usbdrv_private *macp = dev->ml_priv; + unsigned long irqFlag; + struct usbdrv_private *macp = dev->ml_priv; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - spin_lock_irqsave(&macp->cs_lock, irqFlag); + spin_lock_irqsave(&macp->cs_lock, irqFlag); - switch(zfiWlanQueryWlanMode(dev)) - { - case ZM_MODE_AP: - *mode = IW_MODE_MASTER; - break; - case ZM_MODE_INFRASTRUCTURE: - *mode = IW_MODE_INFRA; - break; - case ZM_MODE_IBSS: - *mode = IW_MODE_ADHOC; - break; - default: - *mode = IW_MODE_ADHOC; - break; - } + switch (zfiWlanQueryWlanMode(dev)) { + case ZM_MODE_AP: + *mode = IW_MODE_MASTER; + break; + case ZM_MODE_INFRASTRUCTURE: + *mode = IW_MODE_INFRA; + break; + case ZM_MODE_IBSS: + *mode = IW_MODE_ADHOC; + break; + default: + *mode = IW_MODE_ADHOC; + break; + } - spin_unlock_irqrestore(&macp->cs_lock, irqFlag); + spin_unlock_irqrestore(&macp->cs_lock, irqFlag); - return 0; + return 0; } int usbdrvwext_siwsens(struct net_device *dev, @@ -743,338 +685,341 @@ int usbdrvwext_giwsens(struct net_device *dev, } int usbdrvwext_giwrange(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_request_info *info, + struct iw_point *data, char *extra) { - struct iw_range *range = (struct iw_range *) extra; - int i, val; - //int num_band_a; - u16_t channels[60]; - u16_t channel_num; + struct iw_range *range = (struct iw_range *) extra; + int i, val; + /* int num_band_a; */ + u16_t channels[60]; + u16_t channel_num; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; -#if WIRELESS_EXT > 9 - range->txpower_capa = IW_TXPOW_DBM; -// XXX what about min/max_pmp, min/max_pmt, etc. -#endif + #if WIRELESS_EXT > 9 + range->txpower_capa = IW_TXPOW_DBM; + /* XXX what about min/max_pmp, min/max_pmt, etc. */ + #endif -#if WIRELESS_EXT > 10 - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 13; + #if WIRELESS_EXT > 10 + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 13; - range->retry_capa = IW_RETRY_LIMIT; - range->retry_flags = IW_RETRY_LIMIT; - range->min_retry = 0; - range->max_retry = 255; -#endif /* WIRELESS_EXT > 10 */ + range->retry_capa = IW_RETRY_LIMIT; + range->retry_flags = IW_RETRY_LIMIT; + range->min_retry = 0; + range->max_retry = 255; + #endif /* WIRELESS_EXT > 10 */ - channel_num = zfiWlanQueryAllowChannels(dev, channels); + channel_num = zfiWlanQueryAllowChannels(dev, channels); - /* Gurantee reported channel numbers is less or equal to IW_MAX_FREQUENCIES */ - if (channel_num > IW_MAX_FREQUENCIES) - channel_num = IW_MAX_FREQUENCIES; + /* Gurantee reported channel numbers is less + * or equal to IW_MAX_FREQUENCIES + */ + if (channel_num > IW_MAX_FREQUENCIES) + channel_num = IW_MAX_FREQUENCIES; - val = 0; + val = 0; - for (i = 0; i < channel_num; i++) - { - range->freq[val].i = usbdrv_freq2chan(channels[i]); - range->freq[val].m = channels[i]; - range->freq[val].e = 6; - val++; - } + for (i = 0; i < channel_num; i++) { + range->freq[val].i = usbdrv_freq2chan(channels[i]); + range->freq[val].m = channels[i]; + range->freq[val].e = 6; + val++; + } - range->num_channels = channel_num; - range->num_frequency = channel_num; + range->num_channels = channel_num; + range->num_frequency = channel_num; -#if 0 - range->num_channels = 14; // Only 2.4G + #if 0 + range->num_channels = 14; /* Only 2.4G */ -/* XXX need to filter against the regulatory domain &| active set */ - val = 0; - for (i = 1; i <= 14; i++) // B,G Bands - { - range->freq[val].i = i; - if (i == 14) - range->freq[val].m = 2484000; - else - range->freq[val].m = (2412+(i-1)*5)*1000; - range->freq[val].e = 3; - val++; - } + /* XXX need to filter against the regulatory domain &| active set */ + val = 0; + /* B,G Bands */ + for (i = 1; i <= 14; i++) { + range->freq[val].i = i; + if (i == 14) + range->freq[val].m = 2484000; + else + range->freq[val].m = (2412+(i-1)*5)*1000; + range->freq[val].e = 3; + val++; + } - num_band_a = (IW_MAX_FREQUENCIES - val); + num_band_a = (IW_MAX_FREQUENCIES - val); + /* A Bands */ + for (i = 0; i < num_band_a; i++) { + range->freq[val].i = channel_frequency_11A[2 * i]; + range->freq[val].m = channel_frequency_11A[2 * i + 1] * 1000; + range->freq[val].e = 3; + val++; + } + /* MIMO Rate Not Defined Now + * For 802.11a, there are too more frequency. + * We can't return them all. + */ + range->num_frequency = val; + #endif - for (i = 0; i < num_band_a; i++) // A Bands - { - range->freq[val].i = channel_frequency_11A[2 * i]; - range->freq[val].m = channel_frequency_11A[2 * i + 1] * 1000; - range->freq[val].e = 3; - val++; - } - // MIMO Rate Not Defined Now - //For 802.11a, there are too more frequency. We can't return them all - range->num_frequency = val; -#endif + /* Max of /proc/net/wireless */ + range->max_qual.qual = 100; /* ?? 92; */ + range->max_qual.level = 154; /* ?? */ + range->max_qual.noise = 154; /* ?? */ + range->sensitivity = 3; /* ?? */ -/* Max of /proc/net/wireless */ - range->max_qual.qual = 100; //?? //92; - range->max_qual.level = 154; //?? - range->max_qual.noise = 154; //?? - range->sensitivity = 3; //?? + /* XXX these need to be nsd-specific! */ + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + range->max_encoding_tokens = 4 /* NUM_WEPKEYS ?? */; + range->num_encoding_sizes = 2; /* ?? */ -// XXX these need to be nsd-specific! - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - range->max_encoding_tokens = 4/*NUM_WEPKEYS*/; //?? - range->num_encoding_sizes = 2; //?? + range->encoding_size[0] = 5; /* ?? WEP Key Encoding Size */ + range->encoding_size[1] = 13; /* ?? */ - range->encoding_size[0] = 5; //?? //WEP Key Encoding Size - range->encoding_size[1] = 13;//?? + /* XXX what about num_bitrates/throughput? */ + range->num_bitrates = 0; /* ?? */ -// XXX what about num_bitrates/throughput? - range->num_bitrates = 0; //?? + /* estimated max throughput + * XXX need to cap it if we're running at ~2Mbps.. + */ -/* estimated max throughput */ -// XXX need to cap it if we're running at ~2Mbps.. + range->throughput = 300000000; - range->throughput = 300000000; - - return 0; + return 0; } int usbdrvwext_siwap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *MacAddr, char *extra) + struct sockaddr *MacAddr, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; + struct usbdrv_private *macp = dev->ml_priv; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode - zfiWlanSetMacAddress(dev,(u16_t *)&MacAddr->sa_data[0]); - else //STA Mode - zfiWlanSetBssid(dev,&MacAddr->sa_data[0]); + if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) { + /* AP Mode */ + zfiWlanSetMacAddress(dev, (u16_t *)&MacAddr->sa_data[0]); + } else { + /* STA Mode */ + zfiWlanSetBssid(dev, &MacAddr->sa_data[0]); + } - if (macp->DeviceOpened == 1) - { - //u8_t wpaieLen,wpaie[80]; - //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen); - zfiWlanDisable(dev, 0); - zfiWlanEnable(dev); - //if (wpaieLen > 2) - // zfiWlanSetWpaIe(dev, wpaie, wpaieLen); - } + if (macp->DeviceOpened == 1) { + /* u8_t wpaieLen,wpaie[80]; */ + /* zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen); */ + zfiWlanDisable(dev, 0); + zfiWlanEnable(dev); + /* if (wpaieLen > 2) */ + /* zfiWlanSetWpaIe(dev, wpaie, wpaieLen); */ + } - return 0; + return 0; } int usbdrvwext_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *MacAddr, char *extra) + struct iw_request_info *info, + struct sockaddr *MacAddr, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; + struct usbdrv_private *macp = dev->ml_priv; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode - zfiWlanQueryMacAddress(dev, &MacAddr->sa_data[0]); - else //STA Mode - { - if (macp->adapterState == ZM_STATUS_MEDIA_CONNECT) - { - zfiWlanQueryBssid(dev, &MacAddr->sa_data[0]); - } - else - { - u8_t zero_addr[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - memcpy(&MacAddr->sa_data[0], zero_addr, sizeof(zero_addr)); - } - } + if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) { + /* AP Mode */ + zfiWlanQueryMacAddress(dev, &MacAddr->sa_data[0]); + } else { + /* STA Mode */ + if (macp->adapterState == ZM_STATUS_MEDIA_CONNECT) { + zfiWlanQueryBssid(dev, &MacAddr->sa_data[0]); + } else { + u8_t zero_addr[6] = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; + memcpy(&MacAddr->sa_data[0], zero_addr, + sizeof(zero_addr)); + } + } - return 0; + return 0; } int usbdrvwext_iwaplist(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra) { - //Don't know how to do yet--CWYang(+) - return 0; + /* Don't know how to do yet--CWYang(+) */ + return 0; } int usbdrvwext_siwscan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_point *data, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; + struct usbdrv_private *macp = dev->ml_priv; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - printk("CWY - usbdrvwext_siwscan\n"); + printk(KERN_WARNING "CWY - usbdrvwext_siwscan\n"); - zfiWlanScan(dev); + zfiWlanScan(dev); - return 0; + return 0; } int usbdrvwext_giwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_request_info *info, + struct iw_point *data, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; - //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev); - char *current_ev = extra; - char *end_buf; - int i; - //struct zsBssList BssList; - struct zsBssListV1 *pBssList = kmalloc(sizeof(struct zsBssListV1), GFP_KERNEL); - //BssList = wd->sta.pBssList; - //zmw_get_wlan_dev(dev); + struct usbdrv_private *macp = dev->ml_priv; + /* struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev); */ + char *current_ev = extra; + char *end_buf; + int i; + /* struct zsBssList BssList; */ + struct zsBssListV1 *pBssList = kmalloc(sizeof(struct zsBssListV1), + GFP_KERNEL); + /* BssList = wd->sta.pBssList; */ + /* zmw_get_wlan_dev(dev); */ - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - if (data->length == 0) - { - end_buf = extra + IW_SCAN_MAX_DATA; - } - else - { - end_buf = extra + data->length; - } + if (data->length == 0) + end_buf = extra + IW_SCAN_MAX_DATA; + else + end_buf = extra + data->length; - printk("giwscan - Report Scan Results\n"); - //printk("giwscan - BssList Sreucture Len : %d\n", sizeof(BssList)); - //printk("giwscan - BssList Count : %d\n", wd->sta.pBssList->bssCount); - //printk("giwscan - UpdateBssList Count : %d\n", wd->sta.pUpdateBssList->bssCount); - zfiWlanQueryBssListV1(dev, pBssList); - //zfiWlanQueryBssList(dev, &BssList); + printk(KERN_WARNING "giwscan - Report Scan Results\n"); + /* printk("giwscan - BssList Sreucture Len : %d\n", sizeof(BssList)); + * printk("giwscan - BssList Count : %d\n", + * wd->sta.pBssList->bssCount); + * printk("giwscan - UpdateBssList Count : %d\n", + * wd->sta.pUpdateBssList->bssCount); + */ + zfiWlanQueryBssListV1(dev, pBssList); + /* zfiWlanQueryBssList(dev, &BssList); */ -/* Read and parse all entries */ - printk("giwscan - pBssList->bssCount : %d\n", pBssList->bssCount); - //printk("giwscan - BssList.bssCount : %d\n", BssList.bssCount); + /* Read and parse all entries */ + printk(KERN_WARNING "giwscan - pBssList->bssCount : %d\n", + pBssList->bssCount); + /* printk("giwscan - BssList.bssCount : %d\n", BssList.bssCount); */ - for (i = 0; i < pBssList->bssCount; i++) - { -/* Translate to WE format this entry */ - //current_ev = usbdrv_translate_scan(dev, info, current_ev, - // extra + IW_SCAN_MAX_DATA, &pBssList->bssInfo[i]); - current_ev = usbdrv_translate_scan(dev, info, current_ev, - end_buf, &pBssList->bssInfo[i]); + for (i = 0; i < pBssList->bssCount; i++) { + /* Translate to WE format this entry + * current_ev = usbdrv_translate_scan(dev, info, current_ev, + * extra + IW_SCAN_MAX_DATA, &pBssList->bssInfo[i]); + */ + current_ev = usbdrv_translate_scan(dev, info, current_ev, + end_buf, &pBssList->bssInfo[i]); -#if WIRELESS_EXT > 16 - if (current_ev == end_buf) - { - kfree(pBssList); - data->length = current_ev - extra; - return -E2BIG; - } -#endif - } + #if WIRELESS_EXT > 16 + if (current_ev == end_buf) { + kfree(pBssList); + data->length = current_ev - extra; + return -E2BIG; + } + #endif + } -/* Length of data */ - data->length = (current_ev - extra); - data->flags = 0; /* todo */ + /* Length of data */ + data->length = (current_ev - extra); + data->flags = 0; /* todo */ - kfree(pBssList); + kfree(pBssList); - return 0; + return 0; } int usbdrvwext_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *essid, char *extra) + struct iw_request_info *info, + struct iw_point *essid, char *extra) { - char EssidBuf[IW_ESSID_MAX_SIZE+1]; - struct usbdrv_private *macp = dev->ml_priv; + char EssidBuf[IW_ESSID_MAX_SIZE + 1]; + struct usbdrv_private *macp = dev->ml_priv; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if (essid->flags == 1) - { - if (essid->length > (IW_ESSID_MAX_SIZE+1)) - return -E2BIG; + if (essid->flags == 1) { + if (essid->length > (IW_ESSID_MAX_SIZE + 1)) + return -E2BIG; - if (copy_from_user(&EssidBuf, essid->pointer, essid->length)) - return -EFAULT; + if (copy_from_user(&EssidBuf, essid->pointer, essid->length)) + return -EFAULT; - EssidBuf[essid->length] = '\0'; - //printk("siwessid - Set Essid : %s\n",EssidBuf); - //printk("siwessid - Essid Len : %d\n",essid->length); - //printk("siwessid - Essid Flag : %x\n",essid->flags); - if (macp->DeviceOpened == 1) - { - zfiWlanSetSSID(dev, EssidBuf, strlen(EssidBuf)); - zfiWlanSetFrequency(dev, zfiWlanQueryFrequency(dev), FALSE); - zfiWlanSetEncryMode(dev, zfiWlanQueryEncryMode(dev)); - //u8_t wpaieLen,wpaie[50]; - //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen); - zfiWlanDisable(dev, 0); - zfiWlanEnable(dev); - //if (wpaieLen > 2) - // zfiWlanSetWpaIe(dev, wpaie, wpaieLen); - } - } + EssidBuf[essid->length] = '\0'; + /* printk("siwessid - Set Essid : %s\n",EssidBuf); */ + /* printk("siwessid - Essid Len : %d\n",essid->length); */ + /* printk("siwessid - Essid Flag : %x\n",essid->flags); */ + if (macp->DeviceOpened == 1) { + zfiWlanSetSSID(dev, EssidBuf, strlen(EssidBuf)); + zfiWlanSetFrequency(dev, zfiWlanQueryFrequency(dev), + FALSE); + zfiWlanSetEncryMode(dev, zfiWlanQueryEncryMode(dev)); + /* u8_t wpaieLen,wpaie[50]; */ + /* zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen); */ + zfiWlanDisable(dev, 0); + zfiWlanEnable(dev); + /* if (wpaieLen > 2) */ + /* zfiWlanSetWpaIe(dev, wpaie, wpaieLen); */ + } + } - return 0; + return 0; } int usbdrvwext_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *essid, char *extra) + struct iw_request_info *info, + struct iw_point *essid, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; - u8_t EssidLen; - char EssidBuf[IW_ESSID_MAX_SIZE+1]; - int ssid_len; + struct usbdrv_private *macp = dev->ml_priv; + u8_t EssidLen; + char EssidBuf[IW_ESSID_MAX_SIZE + 1]; + int ssid_len; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - zfiWlanQuerySSID(dev, &EssidBuf[0], &EssidLen); + zfiWlanQuerySSID(dev, &EssidBuf[0], &EssidLen); - /* Convert type from unsigned char to char */ - ssid_len = (int)EssidLen; + /* Convert type from unsigned char to char */ + ssid_len = (int)EssidLen; - /* Make sure the essid length is not greater than IW_ESSID_MAX_SIZE */ - if (ssid_len > IW_ESSID_MAX_SIZE) - ssid_len = IW_ESSID_MAX_SIZE; + /* Make sure the essid length is not greater than IW_ESSID_MAX_SIZE */ + if (ssid_len > IW_ESSID_MAX_SIZE) + ssid_len = IW_ESSID_MAX_SIZE; - EssidBuf[ssid_len] = '\0'; + EssidBuf[ssid_len] = '\0'; - essid->flags = 1; - essid->length = strlen(EssidBuf); + essid->flags = 1; + essid->length = strlen(EssidBuf); - memcpy(extra, EssidBuf, essid->length); - // wireless.c in Kernel would handle copy_to_user -- line 679 - /*if (essid->pointer) - { - if ( copy_to_user(essid->pointer, EssidBuf, essid->length) ) - { - printk("giwessid - copy_to_user Fail\n"); - return -EFAULT; - } - }*/ + memcpy(extra, EssidBuf, essid->length); + /* wireless.c in Kernel would handle copy_to_user -- line 679 */ + /* if (essid->pointer) { + * if (copy_to_user(essid->pointer, EssidBuf, essid->length)) { + * printk("giwessid - copy_to_user Fail\n"); + * return -EFAULT; + * } + * } + */ - return 0; + return 0; } int usbdrvwext_siwnickn(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname) { - //Exist but junk--CWYang(+) + /* Exist but junk--CWYang(+) */ return 0; } @@ -1082,182 +1027,180 @@ int usbdrvwext_giwnickn(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname) { - struct usbdrv_private *macp = dev->ml_priv; - u8_t EssidLen; - char EssidBuf[IW_ESSID_MAX_SIZE+1]; + struct usbdrv_private *macp = dev->ml_priv; + u8_t EssidLen; + char EssidBuf[IW_ESSID_MAX_SIZE + 1]; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - zfiWlanQuerySSID(dev, &EssidBuf[0], &EssidLen); - EssidBuf[EssidLen] = 0; + zfiWlanQuerySSID(dev, &EssidBuf[0], &EssidLen); + EssidBuf[EssidLen] = 0; - data->flags = 1; - data->length = strlen(EssidBuf); + data->flags = 1; + data->length = strlen(EssidBuf); - memcpy(nickname, EssidBuf, data->length); + memcpy(nickname, EssidBuf, data->length); return 0; } int usbdrvwext_siwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, char *extra) + struct iw_request_info *info, + struct iw_param *frq, char *extra) { struct usbdrv_private *macp = dev->ml_priv; - //Array to Define Rate Number that Send to Driver - u16_t zcIndextoRateBG[16] = {1000, 2000, 5500, 11000, 0, 0, 0, 0, 48000, - 24000, 12000, 6000, 54000, 36000, 18000, 9000}; - u16_t zcRateToMCS[] = {0xff, 0, 1, 2, 3, 0xb, 0xf, 0xa, 0xe, 0x9, 0xd, - 0x8, 0xc}; - u8_t i,RateIndex = 4; - u16_t RateKbps; + /* Array to Define Rate Number that Send to Driver */ + u16_t zcIndextoRateBG[16] = {1000, 2000, 5500, 11000, 0, 0, 0, 0, + 48000, 24000, 12000, 6000, 54000, 36000, 18000, 9000}; + u16_t zcRateToMCS[] = {0xff, 0, 1, 2, 3, 0xb, 0xf, 0xa, 0xe, 0x9, 0xd, + 0x8, 0xc}; + u8_t i, RateIndex = 4; + u16_t RateKbps; - //printk("frq->disabled : 0x%x\n",frq->disabled); - //printk("frq->value : 0x%x\n",frq->value); + /* printk("frq->disabled : 0x%x\n",frq->disabled); */ + /* printk("frq->value : 0x%x\n",frq->value); */ - RateKbps = frq->value / 1000; - //printk("RateKbps : %d\n", RateKbps); - for (i = 0; i < 16; i++) - { - if (RateKbps == zcIndextoRateBG[i]) - RateIndex = i; - } - if (zcIndextoRateBG[RateIndex] == 0) - RateIndex = 0xff; - //printk("RateIndex : %x\n", RateIndex); - for (i = 0; i < 13; i++) - if (RateIndex == zcRateToMCS[i]) - break; - //printk("Index : %x\n", i); - if (RateKbps == 65000) - { - RateIndex = 20; - printk("RateIndex : %d\n", RateIndex); - } - if (macp->DeviceOpened == 1) - { - zfiWlanSetTxRate(dev, i); - //zfiWlanDisable(dev); - //zfiWlanEnable(dev); - } + RateKbps = frq->value / 1000; + /* printk("RateKbps : %d\n", RateKbps); */ + for (i = 0; i < 16; i++) { + if (RateKbps == zcIndextoRateBG[i]) + RateIndex = i; + } - return 0; + if (zcIndextoRateBG[RateIndex] == 0) + RateIndex = 0xff; + /* printk("RateIndex : %x\n", RateIndex); */ + for (i = 0; i < 13; i++) + if (RateIndex == zcRateToMCS[i]) + break; + /* printk("Index : %x\n", i); */ + if (RateKbps == 65000) { + RateIndex = 20; + printk(KERN_WARNING "RateIndex : %d\n", RateIndex); + } + + if (macp->DeviceOpened == 1) { + zfiWlanSetTxRate(dev, i); + /* zfiWlanDisable(dev); */ + /* zfiWlanEnable(dev); */ + } + + return 0; } int usbdrvwext_giwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, char *extra) + struct iw_request_info *info, + struct iw_param *frq, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; + struct usbdrv_private *macp = dev->ml_priv; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - frq->fixed = 0; - frq->disabled = 0; - frq->value = zfiWlanQueryRxRate(dev) * 1000; + frq->fixed = 0; + frq->disabled = 0; + frq->value = zfiWlanQueryRxRate(dev) * 1000; - return 0; + return 0; } int usbdrvwext_siwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) + struct iw_request_info *info, + struct iw_param *rts, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; - int val = rts->value; + struct usbdrv_private *macp = dev->ml_priv; + int val = rts->value; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - if (rts->disabled) - val = 2347; + if (rts->disabled) + val = 2347; - if ((val < 0) || (val > 2347)) - return -EINVAL; + if ((val < 0) || (val > 2347)) + return -EINVAL; - zfiWlanSetRtsThreshold(dev,val); + zfiWlanSetRtsThreshold(dev, val); - return 0; + return 0; } int usbdrvwext_giwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) + struct iw_request_info *info, + struct iw_param *rts, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; + struct usbdrv_private *macp = dev->ml_priv; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - rts->value = zfiWlanQueryRtsThreshold(dev); - rts->disabled = (rts->value >= 2347); - rts->fixed = 1; - - return 0; + rts->value = zfiWlanQueryRtsThreshold(dev); + rts->disabled = (rts->value >= 2347); + rts->fixed = 1; + return 0; } int usbdrvwext_siwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) + struct iw_request_info *info, + struct iw_param *frag, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; - u16_t fragThreshold; + struct usbdrv_private *macp = dev->ml_priv; + u16_t fragThreshold; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - if (frag->disabled) - fragThreshold = 0; - else - fragThreshold = frag->value; + if (frag->disabled) + fragThreshold = 0; + else + fragThreshold = frag->value; - zfiWlanSetFragThreshold(dev,fragThreshold); + zfiWlanSetFragThreshold(dev, fragThreshold); - return 0; + return 0; } int usbdrvwext_giwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frag, char *extra) + struct iw_request_info *info, + struct iw_param *frag, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; - u16 val; - unsigned long irqFlag; + struct usbdrv_private *macp = dev->ml_priv; + u16 val; + unsigned long irqFlag; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - spin_lock_irqsave(&macp->cs_lock, irqFlag); + spin_lock_irqsave(&macp->cs_lock, irqFlag); - val = zfiWlanQueryFragThreshold(dev); + val = zfiWlanQueryFragThreshold(dev); - frag->value = val; + frag->value = val; - frag->disabled = (val >= 2346); - frag->fixed = 1; + frag->disabled = (val >= 2346); + frag->fixed = 1; - spin_unlock_irqrestore(&macp->cs_lock, irqFlag); + spin_unlock_irqrestore(&macp->cs_lock, irqFlag); - return 0; + return 0; } int usbdrvwext_siwtxpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) { - //Not support yet--CWYng(+) + /* Not support yet--CWYng(+) */ return 0; } @@ -1265,7 +1208,7 @@ int usbdrvwext_giwtxpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) { - //Not support yet--CWYng(+) + /* Not support yet--CWYng(+) */ return 0; } @@ -1273,7 +1216,7 @@ int usbdrvwext_siwretry(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) { - //Do nothing--CWYang(+) + /* Do nothing--CWYang(+) */ return 0; } @@ -1281,665 +1224,662 @@ int usbdrvwext_giwretry(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) { - //Do nothing--CWYang(+) + /* Do nothing--CWYang(+) */ return 0; } int usbdrvwext_siwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) + struct iw_request_info *info, + struct iw_point *erq, char *key) { - struct zsKeyInfo keyInfo; - int i, WepState = ZM_ENCRYPTION_WEP_DISABLED; - struct usbdrv_private *macp = dev->ml_priv; + struct zsKeyInfo keyInfo; + int i; + int WepState = ZM_ENCRYPTION_WEP_DISABLED; + struct usbdrv_private *macp = dev->ml_priv; - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - if ((erq->flags & IW_ENCODE_DISABLED) == 0) - { - keyInfo.key = key; - keyInfo.keyLength = erq->length; - keyInfo.keyIndex = (erq->flags & IW_ENCODE_INDEX) - 1; - if (keyInfo.keyIndex >= 4) - keyInfo.keyIndex = 0; - keyInfo.flag = ZM_KEY_FLAG_DEFAULT_KEY; + if ((erq->flags & IW_ENCODE_DISABLED) == 0) { + keyInfo.key = key; + keyInfo.keyLength = erq->length; + keyInfo.keyIndex = (erq->flags & IW_ENCODE_INDEX) - 1; + if (keyInfo.keyIndex >= 4) + keyInfo.keyIndex = 0; + keyInfo.flag = ZM_KEY_FLAG_DEFAULT_KEY; - zfiWlanSetKey(dev, keyInfo); - WepState = ZM_ENCRYPTION_WEP_ENABLED; - } - else - { - for (i = 1; i < 4; i++) - zfiWlanRemoveKey(dev, 0, i); - WepState = ZM_ENCRYPTION_WEP_DISABLED; - //zfiWlanSetEncryMode(dev, ZM_NO_WEP); - } + zfiWlanSetKey(dev, keyInfo); + WepState = ZM_ENCRYPTION_WEP_ENABLED; + } else { + for (i = 1; i < 4; i++) + zfiWlanRemoveKey(dev, 0, i); + WepState = ZM_ENCRYPTION_WEP_DISABLED; + /* zfiWlanSetEncryMode(dev, ZM_NO_WEP); */ + } - if (macp->DeviceOpened == 1) - { - zfiWlanSetWepStatus(dev, WepState); - zfiWlanSetFrequency(dev, zfiWlanQueryFrequency(dev), FALSE); - //zfiWlanSetEncryMode(dev, zfiWlanQueryEncryMode(dev)); - //u8_t wpaieLen,wpaie[50]; - //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen); - zfiWlanDisable(dev, 0); - zfiWlanEnable(dev); - //if (wpaieLen > 2) - // zfiWlanSetWpaIe(dev, wpaie, wpaieLen); - } + if (macp->DeviceOpened == 1) { + zfiWlanSetWepStatus(dev, WepState); + zfiWlanSetFrequency(dev, zfiWlanQueryFrequency(dev), FALSE); + /* zfiWlanSetEncryMode(dev, zfiWlanQueryEncryMode(dev)); */ + /* u8_t wpaieLen,wpaie[50]; */ + /* zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen); */ + zfiWlanDisable(dev, 0); + zfiWlanEnable(dev); + /* if (wpaieLen > 2) */ + /* zfiWlanSetWpaIe(dev, wpaie, wpaieLen); */ + } - return 0; + return 0; } int usbdrvwext_giwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) + struct iw_request_info *info, + struct iw_point *erq, char *key) { - struct usbdrv_private *macp = dev->ml_priv; - u8_t EncryptionMode; - u8_t keyLen = 0; + struct usbdrv_private *macp = dev->ml_priv; + u8_t EncryptionMode; + u8_t keyLen = 0; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - EncryptionMode = zfiWlanQueryEncryMode(dev); + EncryptionMode = zfiWlanQueryEncryMode(dev); - if (EncryptionMode) - { - erq->flags = IW_ENCODE_ENABLED; - } - else - { - erq->flags = IW_ENCODE_DISABLED; - } + if (EncryptionMode) + erq->flags = IW_ENCODE_ENABLED; + else + erq->flags = IW_ENCODE_DISABLED; -/* We can't return the key, so set the proper flag and return zero */ - erq->flags |= IW_ENCODE_NOKEY; - memset(key, 0, 16); + /* We can't return the key, so set the proper flag and return zero */ + erq->flags |= IW_ENCODE_NOKEY; + memset(key, 0, 16); -/* Copy the key to the user buffer */ - switch(EncryptionMode) - { - case ZM_WEP64: - keyLen = 5; - break; - case ZM_WEP128: - keyLen = 13; - break; - case ZM_WEP256: - keyLen = 29; - break; - case ZM_AES: - keyLen = 16; - break; - case ZM_TKIP: - keyLen = 32; - break; -#ifdef ZM_ENABLE_CENC - case ZM_CENC: - keyLen = 32; - break; -#endif //ZM_ENABLE_CENC - case ZM_NO_WEP: - keyLen = 0; - break; - default : - keyLen = 0; - printk("Unknown EncryMode\n"); - break; + /* Copy the key to the user buffer */ + switch (EncryptionMode) { + case ZM_WEP64: + keyLen = 5; + break; + case ZM_WEP128: + keyLen = 13; + break; + case ZM_WEP256: + keyLen = 29; + break; + case ZM_AES: + keyLen = 16; + break; + case ZM_TKIP: + keyLen = 32; + break; + #ifdef ZM_ENABLE_CENC + case ZM_CENC: + /* ZM_ENABLE_CENC */ + keyLen = 32; + break; + #endif + case ZM_NO_WEP: + keyLen = 0; + break; + default: + keyLen = 0; + printk(KERN_ERR "Unknown EncryMode\n"); + break; + } + erq->length = keyLen; - } - erq->length = keyLen; - - return 0; + return 0; } int usbdrvwext_siwpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, char *extra) + struct iw_request_info *info, + struct iw_param *frq, char *extra) { - struct usbdrv_private *macp = dev->ml_priv; - u8_t PSMode; + struct usbdrv_private *macp = dev->ml_priv; + u8_t PSMode; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - if (frq->disabled) - PSMode = ZM_STA_PS_NONE; - else - PSMode = ZM_STA_PS_MAX; + if (frq->disabled) + PSMode = ZM_STA_PS_NONE; + else + PSMode = ZM_STA_PS_MAX; - zfiWlanSetPowerSaveMode(dev,PSMode); + zfiWlanSetPowerSaveMode(dev, PSMode); - return 0; + return 0; } int usbdrvwext_giwpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, char *extra) + struct iw_request_info *info, + struct iw_param *frq, char *extra) { - unsigned long irqFlag; - struct usbdrv_private *macp = dev->ml_priv; + unsigned long irqFlag; + struct usbdrv_private *macp = dev->ml_priv; - if (macp->DeviceOpened != 1) - return 0; + if (macp->DeviceOpened != 1) + return 0; - spin_lock_irqsave(&macp->cs_lock, irqFlag); + spin_lock_irqsave(&macp->cs_lock, irqFlag); - if (zfiWlanQueryPowerSaveMode(dev) == ZM_STA_PS_NONE) - frq->disabled = 1; - else - frq->disabled = 0; + if (zfiWlanQueryPowerSaveMode(dev) == ZM_STA_PS_NONE) + frq->disabled = 1; + else + frq->disabled = 0; - spin_unlock_irqrestore(&macp->cs_lock, irqFlag); + spin_unlock_irqrestore(&macp->cs_lock, irqFlag); - return 0; + return 0; } -//int usbdrvwext_setparam(struct net_device *dev, struct iw_request_info *info, -// void *w, char *extra) -//{ -// struct ieee80211vap *vap = dev->ml_priv; -// struct ieee80211com *ic = vap->iv_ic; -// struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn; -// int *i = (int *) extra; -// int param = i[0]; /* parameter id is 1st */ -// int value = i[1]; /* NB: most values are TYPE_INT */ -// int retv = 0; -// int j, caps; -// const struct ieee80211_authenticator *auth; -// const struct ieee80211_aclator *acl; -// -// switch (param) { -// case IEEE80211_PARAM_AUTHMODE: -// switch (value) { -// case IEEE80211_AUTH_WPA: /* WPA */ -// case IEEE80211_AUTH_8021X: /* 802.1x */ -// case IEEE80211_AUTH_OPEN: /* open */ -// case IEEE80211_AUTH_SHARED: /* shared-key */ -// case IEEE80211_AUTH_AUTO: /* auto */ -// auth = ieee80211_authenticator_get(value); -// if (auth == NULL) -// return -EINVAL; -// break; -// default: -// return -EINVAL; -// } -// switch (value) { -// case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ -// vap->iv_flags |= IEEE80211_F_PRIVACY; -// value = IEEE80211_AUTH_8021X; -// break; -// case IEEE80211_AUTH_OPEN: /* open */ -// vap->iv_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY); -// break; -// case IEEE80211_AUTH_SHARED: /* shared-key */ -// case IEEE80211_AUTH_AUTO: /* auto */ -// case IEEE80211_AUTH_8021X: /* 802.1x */ -// vap->iv_flags &= ~IEEE80211_F_WPA; -// /* both require a key so mark the PRIVACY capability */ -// vap->iv_flags |= IEEE80211_F_PRIVACY; -// break; -// } -// /* NB: authenticator attach/detach happens on state change */ -// vap->iv_bss->ni_authmode = value; -// /* XXX mixed/mode/usage? */ -// vap->iv_auth = auth; -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_PROTMODE: -// if (value > IEEE80211_PROT_RTSCTS) -// return -EINVAL; -// ic->ic_protmode = value; -// /* NB: if not operating in 11g this can wait */ -// if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && -// IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_MCASTCIPHER: -// if ((vap->iv_caps & cipher2cap(value)) == 0 && -// !ieee80211_crypto_available(value)) -// return -EINVAL; -// rsn->rsn_mcastcipher = value; -// if (vap->iv_flags & IEEE80211_F_WPA) -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_MCASTKEYLEN: -// if (!(0 < value && value < IEEE80211_KEYBUF_SIZE)) -// return -EINVAL; -// /* XXX no way to verify driver capability */ -// rsn->rsn_mcastkeylen = value; -// if (vap->iv_flags & IEEE80211_F_WPA) -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_UCASTCIPHERS: -// /* -// * Convert cipher set to equivalent capabilities. -// * NB: this logic intentionally ignores unknown and -// * unsupported ciphers so folks can specify 0xff or -// * similar and get all available ciphers. -// */ -// caps = 0; -// for (j = 1; j < 32; j++) /* NB: skip WEP */ -// if ((value & (1<iv_caps & cipher2cap(j)) || -// ieee80211_crypto_available(j))) -// caps |= 1<rsn_ucastcipherset = caps; -// if (vap->iv_flags & IEEE80211_F_WPA) -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_UCASTCIPHER: -// if ((rsn->rsn_ucastcipherset & cipher2cap(value)) == 0) -// return -EINVAL; -// rsn->rsn_ucastcipher = value; -// break; -// case IEEE80211_PARAM_UCASTKEYLEN: -// if (!(0 < value && value < IEEE80211_KEYBUF_SIZE)) -// return -EINVAL; -// /* XXX no way to verify driver capability */ -// rsn->rsn_ucastkeylen = value; -// break; -// case IEEE80211_PARAM_KEYMGTALGS: -// /* XXX check */ -// rsn->rsn_keymgmtset = value; -// if (vap->iv_flags & IEEE80211_F_WPA) -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_RSNCAPS: -// /* XXX check */ -// rsn->rsn_caps = value; -// if (vap->iv_flags & IEEE80211_F_WPA) -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_WPA: -// if (value > 3) -// return -EINVAL; -// /* XXX verify ciphers available */ -// vap->iv_flags &= ~IEEE80211_F_WPA; -// switch (value) { -// case 1: -// vap->iv_flags |= IEEE80211_F_WPA1; -// break; -// case 2: -// vap->iv_flags |= IEEE80211_F_WPA2; -// break; -// case 3: -// vap->iv_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; -// break; -// } -// retv = ENETRESET; /* XXX? */ -// break; -// case IEEE80211_PARAM_ROAMING: -// if (!(IEEE80211_ROAMING_DEVICE <= value && -// value <= IEEE80211_ROAMING_MANUAL)) -// return -EINVAL; -// ic->ic_roaming = value; -// break; -// case IEEE80211_PARAM_PRIVACY: -// if (value) { -// /* XXX check for key state? */ -// vap->iv_flags |= IEEE80211_F_PRIVACY; -// } else -// vap->iv_flags &= ~IEEE80211_F_PRIVACY; -// break; -// case IEEE80211_PARAM_DROPUNENCRYPTED: -// if (value) -// vap->iv_flags |= IEEE80211_F_DROPUNENC; -// else -// vap->iv_flags &= ~IEEE80211_F_DROPUNENC; -// break; -// case IEEE80211_PARAM_COUNTERMEASURES: -// if (value) { -// if ((vap->iv_flags & IEEE80211_F_WPA) == 0) -// return -EINVAL; -// vap->iv_flags |= IEEE80211_F_COUNTERM; -// } else -// vap->iv_flags &= ~IEEE80211_F_COUNTERM; -// break; -// case IEEE80211_PARAM_DRIVER_CAPS: -// vap->iv_caps = value; /* NB: for testing */ -// break; -// case IEEE80211_PARAM_MACCMD: -// acl = vap->iv_acl; -// switch (value) { -// case IEEE80211_MACCMD_POLICY_OPEN: -// case IEEE80211_MACCMD_POLICY_ALLOW: -// case IEEE80211_MACCMD_POLICY_DENY: -// if (acl == NULL) { -// acl = ieee80211_aclator_get("mac"); -// if (acl == NULL || !acl->iac_attach(vap)) -// return -EINVAL; -// vap->iv_acl = acl; -// } -// acl->iac_setpolicy(vap, value); -// break; -// case IEEE80211_MACCMD_FLUSH: -// if (acl != NULL) -// acl->iac_flush(vap); -// /* NB: silently ignore when not in use */ -// break; -// case IEEE80211_MACCMD_DETACH: -// if (acl != NULL) { -// vap->iv_acl = NULL; -// acl->iac_detach(vap); -// } -// break; -// } -// break; -// case IEEE80211_PARAM_WMM: -// if (ic->ic_caps & IEEE80211_C_WME){ -// if (value) { -// vap->iv_flags |= IEEE80211_F_WME; -// vap->iv_ic->ic_flags |= IEEE80211_F_WME; /* XXX needed by ic_reset */ -// } -// else { -// vap->iv_flags &= ~IEEE80211_F_WME; -// vap->iv_ic->ic_flags &= ~IEEE80211_F_WME; /* XXX needed by ic_reset */ -// } -// retv = ENETRESET; /* Renegotiate for capabilities */ -// } -// break; -// case IEEE80211_PARAM_HIDESSID: -// if (value) -// vap->iv_flags |= IEEE80211_F_HIDESSID; -// else -// vap->iv_flags &= ~IEEE80211_F_HIDESSID; -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_APBRIDGE: -// if (value == 0) -// vap->iv_flags |= IEEE80211_F_NOBRIDGE; -// else -// vap->iv_flags &= ~IEEE80211_F_NOBRIDGE; -// break; -// case IEEE80211_PARAM_INACT: -// vap->iv_inact_run = value / IEEE80211_INACT_WAIT; -// break; -// case IEEE80211_PARAM_INACT_AUTH: -// vap->iv_inact_auth = value / IEEE80211_INACT_WAIT; -// break; -// case IEEE80211_PARAM_INACT_INIT: -// vap->iv_inact_init = value / IEEE80211_INACT_WAIT; -// break; -// case IEEE80211_PARAM_ABOLT: -// caps = 0; -// /* -// * Map abolt settings to capability bits; -// * this also strips unknown/unwanted bits. -// */ -// if (value & IEEE80211_ABOLT_TURBO_PRIME) -// caps |= IEEE80211_ATHC_TURBOP; -// if (value & IEEE80211_ABOLT_COMPRESSION) -// caps |= IEEE80211_ATHC_COMP; -// if (value & IEEE80211_ABOLT_FAST_FRAME) -// caps |= IEEE80211_ATHC_FF; -// if (value & IEEE80211_ABOLT_XR) -// caps |= IEEE80211_ATHC_XR; -// if (value & IEEE80211_ABOLT_AR) -// caps |= IEEE80211_ATHC_AR; -// if (value & IEEE80211_ABOLT_BURST) -// caps |= IEEE80211_ATHC_BURST; -// if (value & IEEE80211_ABOLT_WME_ELE) -// caps |= IEEE80211_ATHC_WME; -// /* verify requested capabilities are supported */ -// if ((caps & ic->ic_ath_cap) != caps) -// return -EINVAL; -// if (vap->iv_ath_cap != caps) { -// if ((vap->iv_ath_cap ^ caps) & IEEE80211_ATHC_TURBOP) { -// if (ieee80211_set_turbo(dev, caps & IEEE80211_ATHC_TURBOP)) -// return -EINVAL; -// ieee80211_scan_flush(ic); -// } -// vap->iv_ath_cap = caps; -// ic->ic_athcapsetup(vap->iv_ic, vap->iv_ath_cap); -// retv = ENETRESET; -// } -// break; -// case IEEE80211_PARAM_DTIM_PERIOD: -// if (vap->iv_opmode != IEEE80211_M_HOSTAP && -// vap->iv_opmode != IEEE80211_M_IBSS) -// return -EINVAL; -// if (IEEE80211_DTIM_MIN <= value && -// value <= IEEE80211_DTIM_MAX) { -// vap->iv_dtim_period = value; -// retv = ENETRESET; /* requires restart */ -// } else -// retv = EINVAL; -// break; -// case IEEE80211_PARAM_BEACON_INTERVAL: -// if (vap->iv_opmode != IEEE80211_M_HOSTAP && -// vap->iv_opmode != IEEE80211_M_IBSS) -// return -EINVAL; -// if (IEEE80211_BINTVAL_MIN <= value && -// value <= IEEE80211_BINTVAL_MAX) { -// ic->ic_lintval = value; /* XXX multi-bss */ -// retv = ENETRESET; /* requires restart */ -// } else -// retv = EINVAL; -// break; -// case IEEE80211_PARAM_DOTH: -// if (value) { -// ic->ic_flags |= IEEE80211_F_DOTH; -// } -// else -// ic->ic_flags &= ~IEEE80211_F_DOTH; -// retv = ENETRESET; /* XXX: need something this drastic? */ -// break; -// case IEEE80211_PARAM_PWRTARGET: -// ic->ic_curchanmaxpwr = value; -// break; -// case IEEE80211_PARAM_GENREASSOC: -// IEEE80211_SEND_MGMT(vap->iv_bss, IEEE80211_FC0_SUBTYPE_REASSOC_REQ, 0); -// break; -// case IEEE80211_PARAM_COMPRESSION: -// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_COMP, value); -// break; -// case IEEE80211_PARAM_WMM_AGGRMODE: -// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_WME, value); -// break; -// case IEEE80211_PARAM_FF: -// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_FF, value); -// break; -// case IEEE80211_PARAM_TURBO: -// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_TURBOP, value); -// if (retv == ENETRESET) { -// if(ieee80211_set_turbo(dev,value)) -// return -EINVAL; -// ieee80211_scan_flush(ic); -// } -// break; -// case IEEE80211_PARAM_XR: -// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_XR, value); -// break; -// case IEEE80211_PARAM_BURST: -// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_BURST, value); -// break; -// case IEEE80211_PARAM_AR: -// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_AR, value); -// break; -// case IEEE80211_PARAM_PUREG: -// if (value) -// vap->iv_flags |= IEEE80211_F_PUREG; -// else -// vap->iv_flags &= ~IEEE80211_F_PUREG; -// /* NB: reset only if we're operating on an 11g channel */ -// if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && -// IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_WDS: -// if (value) -// vap->iv_flags_ext |= IEEE80211_FEXT_WDS; -// else -// vap->iv_flags_ext &= ~IEEE80211_FEXT_WDS; -// break; -// case IEEE80211_PARAM_BGSCAN: -// if (value) { -// if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0) -// return -EINVAL; -// vap->iv_flags |= IEEE80211_F_BGSCAN; -// } else { -// /* XXX racey? */ -// vap->iv_flags &= ~IEEE80211_F_BGSCAN; -// ieee80211_cancel_scan(vap); /* anything current */ -// } -// break; -// case IEEE80211_PARAM_BGSCAN_IDLE: -// if (value >= IEEE80211_BGSCAN_IDLE_MIN) -// vap->iv_bgscanidle = value*HZ/1000; -// else -// retv = EINVAL; -// break; -// case IEEE80211_PARAM_BGSCAN_INTERVAL: -// if (value >= IEEE80211_BGSCAN_INTVAL_MIN) -// vap->iv_bgscanintvl = value*HZ; -// else -// retv = EINVAL; -// break; -// case IEEE80211_PARAM_MCAST_RATE: -// /* units are in KILObits per second */ -// if (value >= 256 && value <= 54000) -// vap->iv_mcast_rate = value; -// else -// retv = EINVAL; -// break; -// case IEEE80211_PARAM_COVERAGE_CLASS: -// if (value >= 0 && value <= IEEE80211_COVERAGE_CLASS_MAX) { -// ic->ic_coverageclass = value; -// if (IS_UP_AUTO(vap)) -// ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); -// retv = 0; -// } -// else -// retv = EINVAL; -// break; -// case IEEE80211_PARAM_COUNTRY_IE: -// if (value) -// ic->ic_flags_ext |= IEEE80211_FEXT_COUNTRYIE; -// else -// ic->ic_flags_ext &= ~IEEE80211_FEXT_COUNTRYIE; -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_REGCLASS: -// if (value) -// ic->ic_flags_ext |= IEEE80211_FEXT_REGCLASS; -// else -// ic->ic_flags_ext &= ~IEEE80211_FEXT_REGCLASS; -// retv = ENETRESET; -// break; -// case IEEE80211_PARAM_SCANVALID: -// vap->iv_scanvalid = value*HZ; -// break; -// case IEEE80211_PARAM_ROAM_RSSI_11A: -// vap->iv_roam.rssi11a = value; -// break; -// case IEEE80211_PARAM_ROAM_RSSI_11B: -// vap->iv_roam.rssi11bOnly = value; -// break; -// case IEEE80211_PARAM_ROAM_RSSI_11G: -// vap->iv_roam.rssi11b = value; -// break; -// case IEEE80211_PARAM_ROAM_RATE_11A: -// vap->iv_roam.rate11a = value; -// break; -// case IEEE80211_PARAM_ROAM_RATE_11B: -// vap->iv_roam.rate11bOnly = value; -// break; -// case IEEE80211_PARAM_ROAM_RATE_11G: -// vap->iv_roam.rate11b = value; -// break; -// case IEEE80211_PARAM_UAPSDINFO: -// if (vap->iv_opmode == IEEE80211_M_HOSTAP) { -// if (ic->ic_caps & IEEE80211_C_UAPSD) { -// if (value) -// IEEE80211_VAP_UAPSD_ENABLE(vap); -// else -// IEEE80211_VAP_UAPSD_DISABLE(vap); -// retv = ENETRESET; -// } -// } -// else if (vap->iv_opmode == IEEE80211_M_STA) { -// vap->iv_uapsdinfo = value; -// IEEE80211_VAP_UAPSD_ENABLE(vap); -// retv = ENETRESET; -// } -// break; -// case IEEE80211_PARAM_SLEEP: -// /* XXX: Forced sleep for testing. Does not actually place the -// * HW in sleep mode yet. this only makes sense for STAs. -// */ -// if (value) { -// /* goto sleep */ -// IEEE80211_VAP_GOTOSLEEP(vap); -// } -// else { -// /* wakeup */ -// IEEE80211_VAP_WAKEUP(vap); -// } -// ieee80211_send_nulldata(ieee80211_ref_node(vap->iv_bss)); -// break; -// case IEEE80211_PARAM_QOSNULL: -// /* Force a QoS Null for testing. */ -// ieee80211_send_qosnulldata(vap->iv_bss, value); -// break; -// case IEEE80211_PARAM_PSPOLL: -// /* Force a PS-POLL for testing. */ -// ieee80211_send_pspoll(vap->iv_bss); -// break; -// case IEEE80211_PARAM_EOSPDROP: -// if (vap->iv_opmode == IEEE80211_M_HOSTAP) { -// if (value) IEEE80211_VAP_EOSPDROP_ENABLE(vap); -// else IEEE80211_VAP_EOSPDROP_DISABLE(vap); -// } -// break; -// case IEEE80211_PARAM_MARKDFS: -// if (value) -// ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS; -// else -// ic->ic_flags_ext &= ~IEEE80211_FEXT_MARKDFS; -// break; -// case IEEE80211_PARAM_CHANBW: -// switch (value) { -// case 0: -// ic->ic_chanbwflag = 0; -// break; -// case 1: -// ic->ic_chanbwflag = IEEE80211_CHAN_HALF; -// break; -// case 2: -// ic->ic_chanbwflag = IEEE80211_CHAN_QUARTER; -// break; -// default: -// retv = EINVAL; -// break; -// } -// break; -// case IEEE80211_PARAM_SHORTPREAMBLE: -// if (value) { -// ic->ic_caps |= IEEE80211_C_SHPREAMBLE; -// } else { -// ic->ic_caps &= ~IEEE80211_C_SHPREAMBLE; -// } -// retv = ENETRESET; -// break; -// default: -// retv = EOPNOTSUPP; -// break; -// } -// /* XXX should any of these cause a rescan? */ -// if (retv == ENETRESET) -// retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0; -// return -retv; -//} +/*int usbdrvwext_setparam(struct net_device *dev, struct iw_request_info *info, +* void *w, char *extra) +*{ +* struct ieee80211vap *vap = dev->ml_priv; +* struct ieee80211com *ic = vap->iv_ic; +* struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn; +* int *i = (int *) extra; +* int param = i[0]; // parameter id is 1st +* int value = i[1]; // NB: most values are TYPE_INT +* int retv = 0; +* int j, caps; +* const struct ieee80211_authenticator *auth; +* const struct ieee80211_aclator *acl; +* +* switch (param) { +* case IEEE80211_PARAM_AUTHMODE: +* switch (value) { +* case IEEE80211_AUTH_WPA: // WPA +* case IEEE80211_AUTH_8021X: // 802.1x +* case IEEE80211_AUTH_OPEN: // open +* case IEEE80211_AUTH_SHARED: // shared-key +* case IEEE80211_AUTH_AUTO: // auto +* auth = ieee80211_authenticator_get(value); +* if (auth == NULL) +* return -EINVAL; +* break; +* default: +* return -EINVAL; +* } +* switch (value) { +* case IEEE80211_AUTH_WPA: // WPA w/ 802.1x +* vap->iv_flags |= IEEE80211_F_PRIVACY; +* value = IEEE80211_AUTH_8021X; +* break; +* case IEEE80211_AUTH_OPEN: // open +* vap->iv_flags &= ~(IEEE80211_F_WPA | IEEE80211_F_PRIVACY); +* break; +* case IEEE80211_AUTH_SHARED: // shared-key +* case IEEE80211_AUTH_AUTO: // auto +* case IEEE80211_AUTH_8021X: // 802.1x +* vap->iv_flags &= ~IEEE80211_F_WPA; +* // both require a key so mark the PRIVACY capability +* vap->iv_flags |= IEEE80211_F_PRIVACY; +* break; +* } +* // NB: authenticator attach/detach happens on state change +* vap->iv_bss->ni_authmode = value; +* // XXX mixed/mode/usage? +* vap->iv_auth = auth; +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_PROTMODE: +* if (value > IEEE80211_PROT_RTSCTS) +* return -EINVAL; +* ic->ic_protmode = value; +* // NB: if not operating in 11g this can wait +* if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && +* IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_MCASTCIPHER: +* if ((vap->iv_caps & cipher2cap(value)) == 0 && +* !ieee80211_crypto_available(value)) +* return -EINVAL; +* rsn->rsn_mcastcipher = value; +* if (vap->iv_flags & IEEE80211_F_WPA) +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_MCASTKEYLEN: +* if (!(0 < value && value < IEEE80211_KEYBUF_SIZE)) +* return -EINVAL; +* // XXX no way to verify driver capability +* rsn->rsn_mcastkeylen = value; +* if (vap->iv_flags & IEEE80211_F_WPA) +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_UCASTCIPHERS: +* +* // Convert cipher set to equivalent capabilities. +* // NB: this logic intentionally ignores unknown and +* // unsupported ciphers so folks can specify 0xff or +* // similar and get all available ciphers. +* +* caps = 0; +* for (j = 1; j < 32; j++) // NB: skip WEP +* if ((value & (1<iv_caps & cipher2cap(j)) || +* ieee80211_crypto_available(j))) +* caps |= 1<rsn_ucastcipherset = caps; +* if (vap->iv_flags & IEEE80211_F_WPA) +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_UCASTCIPHER: +* if ((rsn->rsn_ucastcipherset & cipher2cap(value)) == 0) +* return -EINVAL; +* rsn->rsn_ucastcipher = value; +* break; +* case IEEE80211_PARAM_UCASTKEYLEN: +* if (!(0 < value && value < IEEE80211_KEYBUF_SIZE)) +* return -EINVAL; +* // XXX no way to verify driver capability +* rsn->rsn_ucastkeylen = value; +* break; +* case IEEE80211_PARAM_KEYMGTALGS: +* // XXX check +* rsn->rsn_keymgmtset = value; +* if (vap->iv_flags & IEEE80211_F_WPA) +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_RSNCAPS: +* // XXX check +* rsn->rsn_caps = value; +* if (vap->iv_flags & IEEE80211_F_WPA) +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_WPA: +* if (value > 3) +* return -EINVAL; +* // XXX verify ciphers available +* vap->iv_flags &= ~IEEE80211_F_WPA; +* switch (value) { +* case 1: +* vap->iv_flags |= IEEE80211_F_WPA1; +* break; +* case 2: +* vap->iv_flags |= IEEE80211_F_WPA2; +* break; +* case 3: +* vap->iv_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; +* break; +* } +* retv = ENETRESET; // XXX? +* break; +* case IEEE80211_PARAM_ROAMING: +* if (!(IEEE80211_ROAMING_DEVICE <= value && +* value <= IEEE80211_ROAMING_MANUAL)) +* return -EINVAL; +* ic->ic_roaming = value; +* break; +* case IEEE80211_PARAM_PRIVACY: +* if (value) { +* // XXX check for key state? +* vap->iv_flags |= IEEE80211_F_PRIVACY; +* } else +* vap->iv_flags &= ~IEEE80211_F_PRIVACY; +* break; +* case IEEE80211_PARAM_DROPUNENCRYPTED: +* if (value) +* vap->iv_flags |= IEEE80211_F_DROPUNENC; +* else +* vap->iv_flags &= ~IEEE80211_F_DROPUNENC; +* break; +* case IEEE80211_PARAM_COUNTERMEASURES: +* if (value) { +* if ((vap->iv_flags & IEEE80211_F_WPA) == 0) +* return -EINVAL; +* vap->iv_flags |= IEEE80211_F_COUNTERM; +* } else +* vap->iv_flags &= ~IEEE80211_F_COUNTERM; +* break; +* case IEEE80211_PARAM_DRIVER_CAPS: +* vap->iv_caps = value; // NB: for testing +* break; +* case IEEE80211_PARAM_MACCMD: +* acl = vap->iv_acl; +* switch (value) { +* case IEEE80211_MACCMD_POLICY_OPEN: +* case IEEE80211_MACCMD_POLICY_ALLOW: +* case IEEE80211_MACCMD_POLICY_DENY: +* if (acl == NULL) { +* acl = ieee80211_aclator_get("mac"); +* if (acl == NULL || !acl->iac_attach(vap)) +* return -EINVAL; +* vap->iv_acl = acl; +* } +* acl->iac_setpolicy(vap, value); +* break; +* case IEEE80211_MACCMD_FLUSH: +* if (acl != NULL) +* acl->iac_flush(vap); +* // NB: silently ignore when not in use +* break; +* case IEEE80211_MACCMD_DETACH: +* if (acl != NULL) { +* vap->iv_acl = NULL; +* acl->iac_detach(vap); +* } +* break; +* } +* break; +* case IEEE80211_PARAM_WMM: +* if (ic->ic_caps & IEEE80211_C_WME){ +* if (value) { +* vap->iv_flags |= IEEE80211_F_WME; +* *//* XXX needed by ic_reset *//* +* vap->iv_ic->ic_flags |= IEEE80211_F_WME; +* } +* else { +* *//* XXX needed by ic_reset *//* +* vap->iv_flags &= ~IEEE80211_F_WME; +* vap->iv_ic->ic_flags &= ~IEEE80211_F_WME; +* } +* retv = ENETRESET; // Renegotiate for capabilities +* } +* break; +* case IEEE80211_PARAM_HIDESSID: +* if (value) +* vap->iv_flags |= IEEE80211_F_HIDESSID; +* else +* vap->iv_flags &= ~IEEE80211_F_HIDESSID; +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_APBRIDGE: +* if (value == 0) +* vap->iv_flags |= IEEE80211_F_NOBRIDGE; +* else +* vap->iv_flags &= ~IEEE80211_F_NOBRIDGE; +* break; +* case IEEE80211_PARAM_INACT: +* vap->iv_inact_run = value / IEEE80211_INACT_WAIT; +* break; +* case IEEE80211_PARAM_INACT_AUTH: +* vap->iv_inact_auth = value / IEEE80211_INACT_WAIT; +* break; +* case IEEE80211_PARAM_INACT_INIT: +* vap->iv_inact_init = value / IEEE80211_INACT_WAIT; +* break; +* case IEEE80211_PARAM_ABOLT: +* caps = 0; +* +* // Map abolt settings to capability bits; +* // this also strips unknown/unwanted bits. +* +* if (value & IEEE80211_ABOLT_TURBO_PRIME) +* caps |= IEEE80211_ATHC_TURBOP; +* if (value & IEEE80211_ABOLT_COMPRESSION) +* caps |= IEEE80211_ATHC_COMP; +* if (value & IEEE80211_ABOLT_FAST_FRAME) +* caps |= IEEE80211_ATHC_FF; +* if (value & IEEE80211_ABOLT_XR) +* caps |= IEEE80211_ATHC_XR; +* if (value & IEEE80211_ABOLT_AR) +* caps |= IEEE80211_ATHC_AR; +* if (value & IEEE80211_ABOLT_BURST) +* caps |= IEEE80211_ATHC_BURST; +* if (value & IEEE80211_ABOLT_WME_ELE) +* caps |= IEEE80211_ATHC_WME; +* // verify requested capabilities are supported +* if ((caps & ic->ic_ath_cap) != caps) +* return -EINVAL; +* if (vap->iv_ath_cap != caps) { +* if ((vap->iv_ath_cap ^ caps) & IEEE80211_ATHC_TURBOP) { +* if (ieee80211_set_turbo(dev, +* caps & IEEE80211_ATHC_TURBOP)) +* return -EINVAL; +* ieee80211_scan_flush(ic); +* } +* vap->iv_ath_cap = caps; +* ic->ic_athcapsetup(vap->iv_ic, vap->iv_ath_cap); +* retv = ENETRESET; +* } +* break; +* case IEEE80211_PARAM_DTIM_PERIOD: +* if (vap->iv_opmode != IEEE80211_M_HOSTAP && +* vap->iv_opmode != IEEE80211_M_IBSS) +* return -EINVAL; +* if (IEEE80211_DTIM_MIN <= value && +* value <= IEEE80211_DTIM_MAX) { +* vap->iv_dtim_period = value; +* retv = ENETRESET; // requires restart +* } else +* retv = EINVAL; +* break; +* case IEEE80211_PARAM_BEACON_INTERVAL: +* if (vap->iv_opmode != IEEE80211_M_HOSTAP && +* vap->iv_opmode != IEEE80211_M_IBSS) +* return -EINVAL; +* if (IEEE80211_BINTVAL_MIN <= value && +* value <= IEEE80211_BINTVAL_MAX) { +* ic->ic_lintval = value; // XXX multi-bss +* retv = ENETRESET; // requires restart +* } else +* retv = EINVAL; +* break; +* case IEEE80211_PARAM_DOTH: +* if (value) { +* ic->ic_flags |= IEEE80211_F_DOTH; +* } +* else +* ic->ic_flags &= ~IEEE80211_F_DOTH; +* retv = ENETRESET; // XXX: need something this drastic? +* break; +* case IEEE80211_PARAM_PWRTARGET: +* ic->ic_curchanmaxpwr = value; +* break; +* case IEEE80211_PARAM_GENREASSOC: +* IEEE80211_SEND_MGMT(vap->iv_bss, +* IEEE80211_FC0_SUBTYPE_REASSOC_REQ, 0); +* break; +* case IEEE80211_PARAM_COMPRESSION: +* retv = ieee80211_setathcap(vap, IEEE80211_ATHC_COMP, value); +* break; +* case IEEE80211_PARAM_WMM_AGGRMODE: +* retv = ieee80211_setathcap(vap, IEEE80211_ATHC_WME, value); +* break; +* case IEEE80211_PARAM_FF: +* retv = ieee80211_setathcap(vap, IEEE80211_ATHC_FF, value); +* break; +* case IEEE80211_PARAM_TURBO: +* retv = ieee80211_setathcap(vap, IEEE80211_ATHC_TURBOP, value); +* if (retv == ENETRESET) { +* if(ieee80211_set_turbo(dev,value)) +* return -EINVAL; +* ieee80211_scan_flush(ic); +* } +* break; +* case IEEE80211_PARAM_XR: +* retv = ieee80211_setathcap(vap, IEEE80211_ATHC_XR, value); +* break; +* case IEEE80211_PARAM_BURST: +* retv = ieee80211_setathcap(vap, IEEE80211_ATHC_BURST, value); +* break; +* case IEEE80211_PARAM_AR: +* retv = ieee80211_setathcap(vap, IEEE80211_ATHC_AR, value); +* break; +* case IEEE80211_PARAM_PUREG: +* if (value) +* vap->iv_flags |= IEEE80211_F_PUREG; +* else +* vap->iv_flags &= ~IEEE80211_F_PUREG; +* // NB: reset only if we're operating on an 11g channel +* if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && +* IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_WDS: +* if (value) +* vap->iv_flags_ext |= IEEE80211_FEXT_WDS; +* else +* vap->iv_flags_ext &= ~IEEE80211_FEXT_WDS; +* break; +* case IEEE80211_PARAM_BGSCAN: +* if (value) { +* if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0) +* return -EINVAL; +* vap->iv_flags |= IEEE80211_F_BGSCAN; +* } else { +* // XXX racey? +* vap->iv_flags &= ~IEEE80211_F_BGSCAN; +* ieee80211_cancel_scan(vap); // anything current +* } +* break; +* case IEEE80211_PARAM_BGSCAN_IDLE: +* if (value >= IEEE80211_BGSCAN_IDLE_MIN) +* vap->iv_bgscanidle = value*HZ/1000; +* else +* retv = EINVAL; +* break; +* case IEEE80211_PARAM_BGSCAN_INTERVAL: +* if (value >= IEEE80211_BGSCAN_INTVAL_MIN) +* vap->iv_bgscanintvl = value*HZ; +* else +* retv = EINVAL; +* break; +* case IEEE80211_PARAM_MCAST_RATE: +* // units are in KILObits per second +* if (value >= 256 && value <= 54000) +* vap->iv_mcast_rate = value; +* else +* retv = EINVAL; +* break; +* case IEEE80211_PARAM_COVERAGE_CLASS: +* if (value >= 0 && value <= IEEE80211_COVERAGE_CLASS_MAX) { +* ic->ic_coverageclass = value; +* if (IS_UP_AUTO(vap)) +* ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); +* retv = 0; +* } +* else +* retv = EINVAL; +* break; +* case IEEE80211_PARAM_COUNTRY_IE: +* if (value) +* ic->ic_flags_ext |= IEEE80211_FEXT_COUNTRYIE; +* else +* ic->ic_flags_ext &= ~IEEE80211_FEXT_COUNTRYIE; +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_REGCLASS: +* if (value) +* ic->ic_flags_ext |= IEEE80211_FEXT_REGCLASS; +* else +* ic->ic_flags_ext &= ~IEEE80211_FEXT_REGCLASS; +* retv = ENETRESET; +* break; +* case IEEE80211_PARAM_SCANVALID: +* vap->iv_scanvalid = value*HZ; +* break; +* case IEEE80211_PARAM_ROAM_RSSI_11A: +* vap->iv_roam.rssi11a = value; +* break; +* case IEEE80211_PARAM_ROAM_RSSI_11B: +* vap->iv_roam.rssi11bOnly = value; +* break; +* case IEEE80211_PARAM_ROAM_RSSI_11G: +* vap->iv_roam.rssi11b = value; +* break; +* case IEEE80211_PARAM_ROAM_RATE_11A: +* vap->iv_roam.rate11a = value; +* break; +* case IEEE80211_PARAM_ROAM_RATE_11B: +* vap->iv_roam.rate11bOnly = value; +* break; +* case IEEE80211_PARAM_ROAM_RATE_11G: +* vap->iv_roam.rate11b = value; +* break; +* case IEEE80211_PARAM_UAPSDINFO: +* if (vap->iv_opmode == IEEE80211_M_HOSTAP) { +* if (ic->ic_caps & IEEE80211_C_UAPSD) { +* if (value) +* IEEE80211_VAP_UAPSD_ENABLE(vap); +* else +* IEEE80211_VAP_UAPSD_DISABLE(vap); +* retv = ENETRESET; +* } +* } +* else if (vap->iv_opmode == IEEE80211_M_STA) { +* vap->iv_uapsdinfo = value; +* IEEE80211_VAP_UAPSD_ENABLE(vap); +* retv = ENETRESET; +* } +* break; +* case IEEE80211_PARAM_SLEEP: +* // XXX: Forced sleep for testing. Does not actually place the +* // HW in sleep mode yet. this only makes sense for STAs. +* +* if (value) { +* // goto sleep +* IEEE80211_VAP_GOTOSLEEP(vap); +* } +* else { +* // wakeup +* IEEE80211_VAP_WAKEUP(vap); +* } +* ieee80211_send_nulldata(ieee80211_ref_node(vap->iv_bss)); +* break; +* case IEEE80211_PARAM_QOSNULL: +* // Force a QoS Null for testing. +* ieee80211_send_qosnulldata(vap->iv_bss, value); +* break; +* case IEEE80211_PARAM_PSPOLL: +* // Force a PS-POLL for testing. +* ieee80211_send_pspoll(vap->iv_bss); +* break; +* case IEEE80211_PARAM_EOSPDROP: +* if (vap->iv_opmode == IEEE80211_M_HOSTAP) { +* if (value) IEEE80211_VAP_EOSPDROP_ENABLE(vap); +* else IEEE80211_VAP_EOSPDROP_DISABLE(vap); +* } +* break; +* case IEEE80211_PARAM_MARKDFS: +* if (value) +* ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS; +* else +* ic->ic_flags_ext &= ~IEEE80211_FEXT_MARKDFS; +* break; +* case IEEE80211_PARAM_CHANBW: +* switch (value) { +* case 0: +* ic->ic_chanbwflag = 0; +* break; +* case 1: +* ic->ic_chanbwflag = IEEE80211_CHAN_HALF; +* break; +* case 2: +* ic->ic_chanbwflag = IEEE80211_CHAN_QUARTER; +* break; +* default: +* retv = EINVAL; +* break; +* } +* break; +* case IEEE80211_PARAM_SHORTPREAMBLE: +* if (value) { +* ic->ic_caps |= IEEE80211_C_SHPREAMBLE; +* } else { +* ic->ic_caps &= ~IEEE80211_C_SHPREAMBLE; +* } +* retv = ENETRESET; +* break; +* default: +* retv = EOPNOTSUPP; +* break; +* } +* // XXX should any of these cause a rescan? +* if (retv == ENETRESET) +* retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0; +* return -retv; +*} +*/ int usbdrvwext_setmode(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) + void *w, char *extra) { return 0; } @@ -1947,158 +1887,138 @@ int usbdrvwext_setmode(struct net_device *dev, struct iw_request_info *info, int usbdrvwext_getmode(struct net_device *dev, struct iw_request_info *info, void *w, char *extra) { - //struct usbdrv_private *macp = dev->ml_priv; + /* struct usbdrv_private *macp = dev->ml_priv; */ struct iw_point *wri = (struct iw_point *)extra; char mode[8]; - strcpy(mode,"11g"); - return (copy_to_user(wri->pointer, mode, 6) ? -EFAULT : 0); + strcpy(mode, "11g"); + return copy_to_user(wri->pointer, mode, 6) ? -EFAULT : 0; } int zfLnxPrivateIoctl(struct net_device *dev, struct zdap_ioctl* zdreq) { - //void* regp = macp->regp; + /* void* regp = macp->regp; */ u16_t cmd; - //u32_t temp; - u32_t* p; + /* u32_t temp; */ + u32_t *p; u32_t i; cmd = zdreq->cmd; - switch(cmd) - { + switch (cmd) { case ZM_IOCTL_REG_READ: zfiDbgReadReg(dev, zdreq->addr); break; - case ZM_IOCTL_REG_WRITE: zfiDbgWriteReg(dev, zdreq->addr, zdreq->value); break; - case ZM_IOCTL_MEM_READ: p = (u32_t *) bus_to_virt(zdreq->addr); - printk(KERN_DEBUG "usbdrv: read memory addr: 0x%08x value: 0x%08x\n", zdreq->addr, *p); + printk(KERN_WARNING + "usbdrv: read memory addr: 0x%08x value:" + " 0x%08x\n", zdreq->addr, *p); break; - case ZM_IOCTL_MEM_WRITE: p = (u32_t *) bus_to_virt(zdreq->addr); *p = zdreq->value; - printk(KERN_DEBUG "usbdrv: write value: 0x%08x to memory addr: 0x%08x\n", zdreq->value, zdreq->addr); + printk(KERN_WARNING + "usbdrv : write value : 0x%08x to memory addr :" + " 0x%08x\n", zdreq->value, zdreq->addr); break; - - case ZM_IOCTL_TALLY : + case ZM_IOCTL_TALLY: zfiWlanShowTally(dev); if (zdreq->addr) zfiWlanResetTally(dev); break; + case ZM_IOCTL_TEST: + printk(KERN_WARNING + "ZM_IOCTL_TEST:len=%d\n", zdreq->addr); + /* zfiWlanReadReg(dev, 0x10f400); */ + /* zfiWlanReadReg(dev, 0x10f404); */ + printk(KERN_WARNING "IOCTL TEST\n"); + #if 1 + /* print packet */ + for (i = 0; i < zdreq->addr; i++) { + if ((i&0x7) == 0) + printk(KERN_WARNING "\n"); + printk(KERN_WARNING "%02X ", + (unsigned char)zdreq->data[i]); + } + printk(KERN_WARNING "\n"); + #endif - case ZM_IOCTL_TEST : - printk(KERN_DEBUG "ZM_IOCTL_TEST:len=%d\n", zdreq->addr); - //zfiWlanReadReg(dev, 0x10f400); - //zfiWlanReadReg(dev, 0x10f404); - printk("IOCTL TEST\n"); - #if 1 - //print packet - for (i=0; iaddr; i++) - { - if ((i&0x7) == 0) - { - printk("\n"); - } - printk("%02X ", (unsigned char)zdreq->data[i]); - } - printk("\n"); - #endif + /* For Test?? 1 to 0 by CWYang(-) */ + #if 0 + struct sk_buff *s; + /* Allocate a skb */ + s = alloc_skb(2000, GFP_ATOMIC); - #if 0 //For Test?? 1 to 0 by CWYang(-) - { - struct sk_buff* s; + /* Copy data to skb */ + for (i = 0; i < zdreq->addr; i++) + s->data[i] = zdreq->data[i]; + s->len = zdreq->addr; - /* Allocate a skb */ - s = alloc_skb(2000, GFP_ATOMIC); + /* Call zfIdlRecv() */ + zfiRecv80211(dev, s, NULL); + #endif + break; + /************************* ZDCONFIG ***************************/ + case ZM_IOCTL_FRAG: + zfiWlanSetFragThreshold(dev, zdreq->addr); + break; + case ZM_IOCTL_RTS: + zfiWlanSetRtsThreshold(dev, zdreq->addr); + break; + case ZM_IOCTL_SCAN: + zfiWlanScan(dev); + break; + case ZM_IOCTL_KEY: { + u8_t key[29]; + struct zsKeyInfo keyInfo; + u32_t i; - /* Copy data to skb */ - for (i=0; iaddr; i++) - { - s->data[i] = zdreq->data[i]; - } - s->len = zdreq->addr; + for (i = 0; i < 29; i++) + key[i] = 0; - /* Call zfIdlRecv() */ - zfiRecv80211(dev, s, NULL); - } - #endif + for (i = 0; i < zdreq->addr; i++) + key[i] = zdreq->data[i]; - break; + printk(KERN_WARNING + "key len=%d, key=%02x%02x%02x%02x%02x...\n", + zdreq->addr, key[0], key[1], key[2], key[3], key[4]); + keyInfo.keyLength = zdreq->addr; + keyInfo.keyIndex = 0; + keyInfo.flag = 0; + keyInfo.key = key; + zfiWlanSetKey(dev, keyInfo); + } + break; + case ZM_IOCTL_RATE: + zfiWlanSetTxRate(dev, zdreq->addr); + break; + case ZM_IOCTL_ENCRYPTION_MODE: + zfiWlanSetEncryMode(dev, zdreq->addr); -/****************************** ZDCONFIG ******************************/ - case ZM_IOCTL_FRAG : - zfiWlanSetFragThreshold(dev, zdreq->addr); - break; - - case ZM_IOCTL_RTS : - zfiWlanSetRtsThreshold(dev, zdreq->addr); - break; - - case ZM_IOCTL_SCAN : - zfiWlanScan(dev); - break; - - case ZM_IOCTL_KEY : - { - u8_t key[29]; - struct zsKeyInfo keyInfo; - u32_t i; - - for (i=0; i<29; i++) - { - key[i] = 0; - } - - for (i=0; iaddr; i++) - { - key[i] = zdreq->data[i]; - } - - printk("key len=%d, key=%02x%02x%02x%02x%02x...\n", - zdreq->addr, key[0], key[1], key[2], key[3], key[4]); - - keyInfo.keyLength = zdreq->addr; - keyInfo.keyIndex = 0; - keyInfo.flag = 0; - keyInfo.key = key; - zfiWlanSetKey(dev, keyInfo); - } - break; - - case ZM_IOCTL_RATE : - zfiWlanSetTxRate(dev, zdreq->addr); - break; - - case ZM_IOCTL_ENCRYPTION_MODE : - zfiWlanSetEncryMode(dev, zdreq->addr); - - zfiWlanDisable(dev, 0); - zfiWlanEnable(dev); - break; - //CWYang(+) - case ZM_IOCTL_SIGNAL_STRENGTH : - { - u8_t buffer[2]; - zfiWlanQuerySignalInfo(dev, &buffer[0]); - printk("Current Signal Strength : %02d\n", buffer[0]); - } - break; - //CWYang(+) - case ZM_IOCTL_SIGNAL_QUALITY : - { - u8_t buffer[2]; - zfiWlanQuerySignalInfo(dev, &buffer[0]); - printk("Current Signal Quality : %02d\n", buffer[1]); - } - break; - + zfiWlanDisable(dev, 0); + zfiWlanEnable(dev); + break; + /* CWYang(+) */ + case ZM_IOCTL_SIGNAL_STRENGTH: { + u8_t buffer[2]; + zfiWlanQuerySignalInfo(dev, &buffer[0]); + printk(KERN_WARNING + "Current Signal Strength : %02d\n", buffer[0]); + } + break; + /* CWYang(+) */ + case ZM_IOCTL_SIGNAL_QUALITY: { + u8_t buffer[2]; + zfiWlanQuerySignalInfo(dev, &buffer[0]); + printk(KERN_WARNING + "Current Signal Quality : %02d\n", buffer[1]); + } + break; case ZM_IOCTL_SET_PIBSS_MODE: if (zdreq->addr == 1) zfiWlanSetWlanMode(dev, ZM_MODE_PSEUDO); @@ -2107,11 +2027,9 @@ int zfLnxPrivateIoctl(struct net_device *dev, struct zdap_ioctl* zdreq) zfiWlanDisable(dev, 0); zfiWlanEnable(dev); - break; -/****************************** ZDCONFIG ******************************/ - - default : + /********************* ZDCONFIG ***********************/ + default: printk(KERN_ERR "usbdrv: error command = %x\n", cmd); break; } @@ -2121,793 +2039,736 @@ int zfLnxPrivateIoctl(struct net_device *dev, struct zdap_ioctl* zdreq) int usbdrv_wpa_ioctl(struct net_device *dev, struct athr_wlan_param *zdparm) { - int ret = 0; - u8_t bc_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - u8_t mac_addr[80]; - struct zsKeyInfo keyInfo; - struct usbdrv_private *macp = dev->ml_priv; - u16_t vapId = 0; + int ret = 0; + u8_t bc_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + u8_t mac_addr[80]; + struct zsKeyInfo keyInfo; + struct usbdrv_private *macp = dev->ml_priv; + u16_t vapId = 0; - //zmw_get_wlan_dev(dev); + /* zmw_get_wlan_dev(dev); */ - switch(zdparm->cmd) - { - case ZD_CMD_SET_ENCRYPT_KEY: + switch (zdparm->cmd) { + case ZD_CMD_SET_ENCRYPT_KEY: + /* Set up key information */ + keyInfo.keyLength = zdparm->u.crypt.key_len; + keyInfo.keyIndex = zdparm->u.crypt.idx; + if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) { + /* AP Mode */ + keyInfo.flag = ZM_KEY_FLAG_AUTHENTICATOR; + } else + keyInfo.flag = 0; + keyInfo.key = zdparm->u.crypt.key; + keyInfo.initIv = zdparm->u.crypt.seq; + keyInfo.macAddr = (u16_t *)zdparm->sta_addr; - /* Set up key information */ - keyInfo.keyLength = zdparm->u.crypt.key_len; - keyInfo.keyIndex = zdparm->u.crypt.idx; - if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode - keyInfo.flag = ZM_KEY_FLAG_AUTHENTICATOR; - else - keyInfo.flag = 0; - keyInfo.key = zdparm->u.crypt.key; - keyInfo.initIv = zdparm->u.crypt.seq; - keyInfo.macAddr = (u16_t *)zdparm->sta_addr; + /* Identify the MAC address information */ + if (memcmp(zdparm->sta_addr, bc_addr, sizeof(bc_addr)) == 0) + keyInfo.flag |= ZM_KEY_FLAG_GK; + else + keyInfo.flag |= ZM_KEY_FLAG_PK; - /* Identify the MAC address information */ - if (memcmp(zdparm->sta_addr, bc_addr, sizeof(bc_addr)) == 0) - { - keyInfo.flag |= ZM_KEY_FLAG_GK; - } - else - { - keyInfo.flag |= ZM_KEY_FLAG_PK; - } + if (!strcmp(zdparm->u.crypt.alg, "NONE")) { + /* u8_t zero_mac[]={0,0,0,0,0,0}; */ - if (!strcmp(zdparm->u.crypt.alg, "NONE")) - { - //u8_t zero_mac[]={0,0,0,0,0,0}; + /* Set key length to zero */ + keyInfo.keyLength = 0; - /* Set key length to zero */ - keyInfo.keyLength = 0; + /* del group key */ + if (zdparm->sta_addr[0] & 1) { + /* if (macp->cardSetting.WPAIeLen==0) + * { 802.1x dynamic WEP + * mDynKeyMode = 0; + * mKeyFormat[0] = 0; + * mPrivacyInvoked[0]=FALSE; + * mCap[0] &= ~CAP_PRIVACY; + * macp->cardSetting.EncryOnOff[0]=0; + * } + * mWpaBcKeyLen = mGkInstalled = 0; + */ + } else { + /* if (memcmp(zero_mac,zdparm->sta_addr, 6)==0) + * { + * mDynKeyMode=0; + * mKeyFormat[0]=0; + * pSetting->DynKeyMode=0; + * pSetting->EncryMode[0]=0; + * mDynKeyMode=0; + * } + */ + } - if (zdparm->sta_addr[0] & 1)//del group key - { - //if (macp->cardSetting.WPAIeLen==0) - //{//802.1x dynamic WEP - // mDynKeyMode = 0; - // mKeyFormat[0] = 0; - // mPrivacyInvoked[0]=FALSE; - // mCap[0] &= ~CAP_PRIVACY; - // macp->cardSetting.EncryOnOff[0]=0; - //} - //mWpaBcKeyLen = mGkInstalled = 0; - } - else - { - //if (memcmp(zero_mac,zdparm->sta_addr, 6)==0) - //{ - // mDynKeyMode=0; - // mKeyFormat[0]=0; - // pSetting->DynKeyMode=0; - // pSetting->EncryMode[0]=0; - // mDynKeyMode=0; - //} - } + printk(KERN_ERR "Set Encryption Type NONE\n"); + return ret; + } else if (!strcmp(zdparm->u.crypt.alg, "TKIP")) { + zfiWlanSetEncryMode(dev, ZM_TKIP); + /* //Linux Supplicant will inverse Tx/Rx key + * //So we inverse it back, CWYang(+) + * zfMemoryCopy(&temp[0], &keyInfo.key[16], 8); + * zfMemoryCopy(&keyInfo.key[16], keyInfo.key[24], 8); + * zfMemoryCopy(&keyInfo.key[24], &temp[0], 8); + * u8_t temp; + * int k; + * for (k = 0; k < 8; k++) + * { + * temp = keyInfo.key[16 + k]; + * keyInfo.key[16 + k] = keyInfo.key[24 + k]; + * keyInfo.key[24 + k] = temp; + * } + * CamEncryType = ZM_TKIP; + * if (idx == 0) + * { // Pairwise key + * mKeyFormat[0] = CamEncryType; + * mDynKeyMode = pSetting->DynKeyMode = DYN_KEY_TKIP; + * } + */ + } else if (!strcmp(zdparm->u.crypt.alg, "CCMP")) { + zfiWlanSetEncryMode(dev, ZM_AES); + /* CamEncryType = ZM_AES; + * if (idx == 0) + * { // Pairwise key + * mKeyFormat[0] = CamEncryType; + * mDynKeyMode = pSetting->DynKeyMode = DYN_KEY_AES; + * } + */ + } else if (!strcmp(zdparm->u.crypt.alg, "WEP")) { + if (keyInfo.keyLength == 5) { + /* WEP 64 */ + zfiWlanSetEncryMode(dev, ZM_WEP64); + /* CamEncryType = ZM_WEP64; */ + /* tmpDynKeyMode=DYN_KEY_WEP64; */ + } else if (keyInfo.keyLength == 13) { + /* keylen=13, WEP 128 */ + zfiWlanSetEncryMode(dev, ZM_WEP128); + /* CamEncryType = ZM_WEP128; */ + /* tmpDynKeyMode=DYN_KEY_WEP128; */ + } else { + zfiWlanSetEncryMode(dev, ZM_WEP256); + } - printk(KERN_ERR "Set Encryption Type NONE\n"); - return ret; - } - else if (!strcmp(zdparm->u.crypt.alg, "TKIP")) - { - zfiWlanSetEncryMode(dev, ZM_TKIP); - //Linux Supplicant will inverse Tx/Rx key - //So we inverse it back //CWYang(+) - //zfMemoryCopy(&temp[0], &keyInfo.key[16], 8); - //zfMemoryCopy(&keyInfo.key[16], keyInfo.key[24], 8); - //zfMemoryCopy(&keyInfo.key[24], &temp[0], 8); - //u8_t temp; - //int k; - //for (k = 0; k < 8; k++) - //{ - // temp = keyInfo.key[16 + k]; - // keyInfo.key[16 + k] = keyInfo.key[24 + k]; - // keyInfo.key[24 + k] = temp; - //} - //CamEncryType = ZM_TKIP; - ////if (idx == 0) - //{// Pairwise key - // mKeyFormat[0] = CamEncryType; - // mDynKeyMode = pSetting->DynKeyMode = DYN_KEY_TKIP; - //} - } - else if (!strcmp(zdparm->u.crypt.alg, "CCMP")) - { - zfiWlanSetEncryMode(dev, ZM_AES); - //CamEncryType = ZM_AES; - ////if (idx == 0) - //{// Pairwise key - // mKeyFormat[0] = CamEncryType; - // mDynKeyMode = pSetting->DynKeyMode = DYN_KEY_AES; - //} - } - else if (!strcmp(zdparm->u.crypt.alg, "WEP")) - { - if (keyInfo.keyLength == 5) - { // WEP 64 - zfiWlanSetEncryMode(dev, ZM_WEP64); - // CamEncryType = ZM_WEP64; - // tmpDynKeyMode=DYN_KEY_WEP64; - } - else if (keyInfo.keyLength == 13) - {//keylen=13, WEP 128 - zfiWlanSetEncryMode(dev, ZM_WEP128); - // CamEncryType = ZM_WEP128; - // tmpDynKeyMode=DYN_KEY_WEP128; - } - else - { - zfiWlanSetEncryMode(dev, ZM_WEP256); - } + /* For Dynamic WEP key (Non-WPA Radius), the key ID range: 0-3 + * In WPA/RSN mode, the key ID range: 1-3, usually, a broadcast key. + * For WEP key setting: we set mDynKeyMode and mKeyFormat in following + * case: + * 1. For 802.1x dynamically generated WEP key method. + * 2. For WPA/RSN mode, but key id == 0. + * (But this is an impossible case) + * So, only check case 1. + * if (macp->cardSetting.WPAIeLen==0) + * { + * mKeyFormat[0] = CamEncryType; + * mDynKeyMode = pSetting->DynKeyMode = tmpDynKeyMode; + * mPrivacyInvoked[0]=TRUE; + * mCap[0] |= CAP_PRIVACY; + * macp->cardSetting.EncryOnOff[0]=1; + * } + */ + } - // For Dynamic WEP key (Non-WPA Radius), the key ID range: 0-3 - // In WPA/RSN mode, the key ID range: 1-3, usually, a broadcast key. - // For WEP key setting: we set mDynKeyMode and mKeyFormat in following case: - // 1. For 802.1x dynamically generated WEP key method. - // 2. For WPA/RSN mode, but key id == 0. (But this is an impossible case) - // So, only check case 1. - //if (macp->cardSetting.WPAIeLen==0) - //{ - // mKeyFormat[0] = CamEncryType; - // mDynKeyMode = pSetting->DynKeyMode = tmpDynKeyMode; - // mPrivacyInvoked[0]=TRUE; - // mCap[0] |= CAP_PRIVACY; - // macp->cardSetting.EncryOnOff[0]=1; - //} - } + /* DUMP key context */ + /* #ifdef WPA_DEBUG */ + if (keyInfo.keyLength > 0) { + int ii; + printk(KERN_WARNING + "Otus: Key Context:\n"); + for (ii = 0; ii < keyInfo.keyLength; ) { + printk(KERN_WARNING + "0x%02x ", keyInfo.key[ii]); + if ((++ii % 16) == 0) + printk(KERN_WARNING "\n"); + } + printk(KERN_WARNING "\n"); + } + /* #endif */ - /* DUMP key context */ -//#ifdef WPA_DEBUG - if (keyInfo.keyLength > 0) - { - int ii; - printk("Otus: Key Context:\n"); - for(ii = 0; ii < keyInfo.keyLength;) - { - printk("0x%02x ", keyInfo.key[ii]); - if((++ii % 16) == 0) - printk("\n"); - } - printk("\n"); - } -//#endif + /* Set encrypt mode */ + /* zfiWlanSetEncryMode(dev, CamEncryType); */ + vapId = zfLnxGetVapId(dev); + if (vapId == 0xffff) + keyInfo.vapId = 0; + else + keyInfo.vapId = vapId + 1; + keyInfo.vapAddr[0] = keyInfo.macAddr[0]; + keyInfo.vapAddr[1] = keyInfo.macAddr[1]; + keyInfo.vapAddr[2] = keyInfo.macAddr[2]; - /* Set encrypt mode */ - //zfiWlanSetEncryMode(dev, CamEncryType); - vapId = zfLnxGetVapId(dev); - if (vapId == 0xffff) - keyInfo.vapId = 0; - else - keyInfo.vapId = vapId + 1; - keyInfo.vapAddr[0] = keyInfo.macAddr[0]; - keyInfo.vapAddr[1] = keyInfo.macAddr[1]; - keyInfo.vapAddr[2] = keyInfo.macAddr[2]; + zfiWlanSetKey(dev, keyInfo); - zfiWlanSetKey(dev, keyInfo); + /* zfiWlanDisable(dev); */ + /* zfiWlanEnable(dev); */ + break; + case ZD_CMD_SET_MLME: + printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SET_MLME\n"); - //zfiWlanDisable(dev); - //zfiWlanEnable(dev); - break; + /* Translate STA's address */ + sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", + zdparm->sta_addr[0], zdparm->sta_addr[1], + zdparm->sta_addr[2], zdparm->sta_addr[3], + zdparm->sta_addr[4], zdparm->sta_addr[5]); - case ZD_CMD_SET_MLME: - printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SET_MLME\n"); + switch (zdparm->u.mlme.cmd) { + case MLME_STA_DEAUTH: + printk(KERN_WARNING + " -------Call zfiWlanDeauth, reason:%d\n", + zdparm->u.mlme.reason_code); + if (zfiWlanDeauth(dev, (u16_t *) zdparm->sta_addr, + zdparm->u.mlme.reason_code) != 0) + printk(KERN_ERR "Can't deauthencate STA: %s\n", + mac_addr); + else + printk(KERN_ERR "Deauthenticate STA: %s" + "with reason code: %d\n", + mac_addr, zdparm->u.mlme.reason_code); + break; + case MLME_STA_DISASSOC: + printk(KERN_WARNING + " -------Call zfiWlanDeauth, reason:%d\n", + zdparm->u.mlme.reason_code); + if (zfiWlanDeauth(dev, (u16_t *) zdparm->sta_addr, + zdparm->u.mlme.reason_code) != 0) + printk(KERN_ERR "Can't disassociate STA: %s\n", + mac_addr); + else + printk(KERN_ERR "Disassociate STA: %s" + "with reason code: %d\n", + mac_addr, zdparm->u.mlme.reason_code); + break; + default: + printk(KERN_ERR "MLME command: 0x%04x not support\n", + zdparm->u.mlme.cmd); + break; + } - /* Translate STA's address */ - sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", zdparm->sta_addr[0], zdparm->sta_addr[1], - zdparm->sta_addr[2], zdparm->sta_addr[3], zdparm->sta_addr[4], zdparm->sta_addr[5]); + break; + case ZD_CMD_SCAN_REQ: + printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SCAN_REQ\n"); + break; + case ZD_CMD_SET_GENERIC_ELEMENT: + printk(KERN_ERR "usbdrv_wpa_ioctl:" + " ZD_CMD_SET_GENERIC_ELEMENT\n"); - switch(zdparm->u.mlme.cmd) - { - case MLME_STA_DEAUTH: - printk(" -------Call zfiWlanDeauth, reason:%d\n",zdparm->u.mlme.reason_code); - if(zfiWlanDeauth(dev, (u16_t*) zdparm->sta_addr, zdparm->u.mlme.reason_code) != 0) - printk(KERN_ERR "Can't deauthencate STA: %s\n", mac_addr); - else - printk(KERN_ERR "Deauthenticate STA: %s with reason code: %d\n", mac_addr, zdparm->u.mlme.reason_code); - break; + /* Copy the WPA IE + * zm_msg1_mm(ZM_LV_0, "CWY - wpaie Length : ", + * zdparm->u.generic_elem.len); + */ + printk(KERN_ERR "wpaie Length : % d\n", + zdparm->u.generic_elem.len); + if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) { + /* AP Mode */ + zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data, + zdparm->u.generic_elem.len); + } else { + macp->supLen = zdparm->u.generic_elem.len; + memcpy(macp->supIe, zdparm->u.generic_elem.data, + zdparm->u.generic_elem.len); + } + zfiWlanSetWpaSupport(dev, 1); + /* zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data, + * zdparm->u.generic_elem.len); + */ + int ii; + u8_t len = zdparm->u.generic_elem.len; + u8_t *wpaie = (u8_t *)zdparm->u.generic_elem.data; - case MLME_STA_DISASSOC: - printk(" -------Call zfiWlanDeauth, reason:%d\n",zdparm->u.mlme.reason_code); - if(zfiWlanDeauth(dev, (u16_t*) zdparm->sta_addr, zdparm->u.mlme.reason_code) != 0) - printk(KERN_ERR "Can't disassociate STA: %s\n", mac_addr); - else - printk(KERN_ERR "Disassociate STA: %s with reason code: %d\n", mac_addr, zdparm->u.mlme.reason_code); - break; + printk(KERN_ERR "wd->ap.wpaLen : % d\n", len); - default: - printk(KERN_ERR "MLME command: 0x%04x not support\n", zdparm->u.mlme.cmd); - break; - } + /* DUMP WPA IE */ + for(ii = 0; ii < len;) { + printk(KERN_ERR "0x%02x ", wpaie[ii]); - break; + if((++ii % 16) == 0) + printk(KERN_ERR "\n"); + } + printk(KERN_ERR "\n"); - case ZD_CMD_SCAN_REQ: - printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SCAN_REQ\n"); - break; + /* #ifdef ZM_HOSTAPD_SUPPORT + * if (wd->wlanMode == ZM_MODE_AP) + * {// Update Beacon FIFO in the next TBTT. + * memcpy(&mWPAIe, pSetting->WPAIe, pSetting->WPAIeLen); + * printk(KERN_ERR "Copy WPA IE into mWPAIe\n"); + * } + * #endif + */ + break; - case ZD_CMD_SET_GENERIC_ELEMENT: - printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SET_GENERIC_ELEMENT\n"); + /* #ifdef ZM_HOSTAPD_SUPPORT */ + case ZD_CMD_GET_TSC: + printk(KERN_ERR "usbdrv_wpa_ioctl : ZD_CMD_GET_TSC\n"); + break; + /* #endif */ - /* Copy the WPA IE */ - //zm_msg1_mm(ZM_LV_0, "CWY - wpaie Length : ", zdparm->u.generic_elem.len); - printk(KERN_ERR "wpaie Length : %d\n", zdparm->u.generic_elem.len); - if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode - { - zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data, zdparm->u.generic_elem.len); - } - else - { - macp->supLen = zdparm->u.generic_elem.len; - memcpy(macp->supIe, zdparm->u.generic_elem.data, zdparm->u.generic_elem.len); - } - zfiWlanSetWpaSupport(dev, 1); - //zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data, zdparm->u.generic_elem.len); - { - int ii; - u8_t len = zdparm->u.generic_elem.len; - u8_t *wpaie = (u8_t *)zdparm->u.generic_elem.data; + default: + printk(KERN_ERR "usbdrv_wpa_ioctl default : 0x%04x\n", + zdparm->cmd); + ret = -EINVAL; + break; + } - printk(KERN_ERR "wd->ap.wpaLen: %d\n", len); - - /* DUMP WPA IE */ - for(ii = 0; ii < len;) - { - printk(KERN_ERR "0x%02x ", wpaie[ii]); - - if((++ii % 16) == 0) - printk(KERN_ERR "\n"); - } - printk(KERN_ERR "\n"); - } - -// #ifdef ZM_HOSTAPD_SUPPORT - //if (wd->wlanMode == ZM_MODE_AP) - //{// Update Beacon FIFO in the next TBTT. - // memcpy(&mWPAIe, pSetting->WPAIe, pSetting->WPAIeLen); - // printk(KERN_ERR "Copy WPA IE into mWPAIe\n"); - //} -// #endif - break; - -// #ifdef ZM_HOSTAPD_SUPPORT - case ZD_CMD_GET_TSC: - printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_GET_TSC\n"); - break; -// #endif - - default: - printk(KERN_ERR "usbdrv_wpa_ioctl default: 0x%04x\n", zdparm->cmd); - ret = -EINVAL; - break; - } - - return ret; + return ret; } #ifdef ZM_ENABLE_CENC int usbdrv_cenc_ioctl(struct net_device *dev, struct zydas_cenc_param *zdparm) { - //struct usbdrv_private *macp = dev->ml_priv; - struct zsKeyInfo keyInfo; - u16_t apId; - u8_t bc_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - int ret = 0; - int ii; + /* struct usbdrv_private *macp = dev->ml_priv; */ + struct zsKeyInfo keyInfo; + u16_t apId; + u8_t bc_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + int ret = 0; + int ii; - /* Get the AP Id */ - apId = zfLnxGetVapId(dev); + /* Get the AP Id */ + apId = zfLnxGetVapId(dev); - if (apId == 0xffff) - { - apId = 0; - } - else - { - apId = apId+1; - } + if (apId == 0xffff) { + apId = 0; + } else { + apId = apId + 1; + } - switch (zdparm->cmd) - { - case ZM_CMD_CENC_SETCENC: - printk(KERN_ERR "ZM_CMD_CENC_SETCENC\n"); - printk(KERN_ERR "length: %d\n", zdparm->len); - printk(KERN_ERR "policy: %d\n", zdparm->u.info.cenc_policy); - break; - case ZM_CMD_CENC_SETKEY: - //ret = wai_ioctl_setkey(vap, ioctl_msg); - printk(KERN_ERR "ZM_CMD_CENC_SETKEY\n"); + switch (zdparm->cmd) { + case ZM_CMD_CENC_SETCENC: + printk(KERN_ERR "ZM_CMD_CENC_SETCENC\n"); + printk(KERN_ERR "length : % d\n", zdparm->len); + printk(KERN_ERR "policy : % d\n", zdparm->u.info.cenc_policy); + break; + case ZM_CMD_CENC_SETKEY: + /* ret = wai_ioctl_setkey(vap, ioctl_msg); */ + printk(KERN_ERR "ZM_CMD_CENC_SETKEY\n"); - printk(KERN_ERR "MAC address= "); - for(ii = 0; ii < 6; ii++) - { - printk(KERN_ERR "0x%02x ", zdparm->u.crypt.sta_addr[ii]); - } - printk(KERN_ERR "\n"); + printk(KERN_ERR "MAC address = "); + for (ii = 0; ii < 6; ii++) { + printk(KERN_ERR "0x%02x ", + zdparm->u.crypt.sta_addr[ii]); + } + printk(KERN_ERR "\n"); - printk(KERN_ERR "Key Index: %d\n", zdparm->u.crypt.keyid); - printk(KERN_ERR "Encryption key= "); - for(ii = 0; ii < 16; ii++) - { - printk(KERN_ERR "0x%02x ", zdparm->u.crypt.key[ii]); - } - printk(KERN_ERR "\n"); + printk(KERN_ERR "Key Index : % d\n", zdparm->u.crypt.keyid); + printk(KERN_ERR "Encryption key = "); + for (ii = 0; ii < 16; ii++) { + printk(KERN_ERR "0x%02x ", zdparm->u.crypt.key[ii]); + } + printk(KERN_ERR "\n"); - printk(KERN_ERR "MIC key= "); - for(ii = 16; ii < ZM_CENC_KEY_SIZE; ii++) - { - printk(KERN_ERR "0x%02x ", zdparm->u.crypt.key[ii]); - } - printk(KERN_ERR "\n"); + printk(KERN_ERR "MIC key = "); + for(ii = 16; ii < ZM_CENC_KEY_SIZE; ii++) { + printk(KERN_ERR "0x%02x ", zdparm->u.crypt.key[ii]); + } + printk(KERN_ERR "\n"); - /* Set up key information */ - keyInfo.keyLength = ZM_CENC_KEY_SIZE; - keyInfo.keyIndex = zdparm->u.crypt.keyid; - keyInfo.flag = ZM_KEY_FLAG_AUTHENTICATOR | ZM_KEY_FLAG_CENC; - keyInfo.key = zdparm->u.crypt.key; - keyInfo.macAddr = (u16_t *)zdparm->u.crypt.sta_addr; + /* Set up key information */ + keyInfo.keyLength = ZM_CENC_KEY_SIZE; + keyInfo.keyIndex = zdparm->u.crypt.keyid; + keyInfo.flag = ZM_KEY_FLAG_AUTHENTICATOR | ZM_KEY_FLAG_CENC; + keyInfo.key = zdparm->u.crypt.key; + keyInfo.macAddr = (u16_t *)zdparm->u.crypt.sta_addr; - /* Identify the MAC address information */ - if (memcmp(zdparm->u.crypt.sta_addr, bc_addr, sizeof(bc_addr)) == 0) - { - keyInfo.flag |= ZM_KEY_FLAG_GK; - keyInfo.vapId = apId; - memcpy(keyInfo.vapAddr, dev->dev_addr, ETH_ALEN); - } - else - { - keyInfo.flag |= ZM_KEY_FLAG_PK; - } + /* Identify the MAC address information */ + if (memcmp(zdparm->u.crypt.sta_addr, bc_addr, + sizeof(bc_addr)) == 0) { + keyInfo.flag |= ZM_KEY_FLAG_GK; + keyInfo.vapId = apId; + memcpy(keyInfo.vapAddr, dev->dev_addr, ETH_ALEN); + } else { + keyInfo.flag |= ZM_KEY_FLAG_PK; + } - zfiWlanSetKey(dev, keyInfo); + zfiWlanSetKey(dev, keyInfo); - break; - case ZM_CMD_CENC_REKEY: - //ret = wai_ioctl_rekey(vap, ioctl_msg); - printk(KERN_ERR "ZM_CMD_CENC_REKEY\n"); - break; - default: - ret = -EOPNOTSUPP; - break; + break; + case ZM_CMD_CENC_REKEY: + /* ret = wai_ioctl_rekey(vap, ioctl_msg); */ + printk(KERN_ERR "ZM_CMD_CENC_REKEY\n"); + break; + default: + ret = -EOPNOTSUPP; + break; + } - } + /* if (retv == ENETRESET) */ + /* retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0; */ - //if (retv == ENETRESET) - // retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0; - - return ret; + return ret; } -#endif //ZM_ENABLE_CENC -///////////////////////////////////////// +#endif /* ZM_ENABLE_CENC */ + int usbdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { -// struct usbdrv_private *macp; -// void *regp; - struct zdap_ioctl zdreq; - struct iwreq *wrq = (struct iwreq *)ifr; - struct athr_wlan_param zdparm; - struct usbdrv_private *macp = dev->ml_priv; + /* struct usbdrv_private *macp; */ + /* void *regp; */ + struct zdap_ioctl zdreq; + struct iwreq *wrq = (struct iwreq *)ifr; + struct athr_wlan_param zdparm; + struct usbdrv_private *macp = dev->ml_priv; - int err = 0; - int changed = 0; + int err = 0; + int changed = 0; -// regp = macp->regp; + /* regp = macp->regp; */ - if(!netif_running(dev)) - return -EINVAL; + if (!netif_running(dev)) + return -EINVAL; - switch (cmd) - { - case SIOCGIWNAME: - strcpy(wrq->u.name, "IEEE 802.11-DS"); - break; + switch (cmd) { + case SIOCGIWNAME: + strcpy(wrq->u.name, "IEEE 802.11-DS"); + break; + case SIOCGIWAP: + err = usbdrvwext_giwap(dev, NULL, &wrq->u.ap_addr, NULL); + break; + case SIOCSIWAP: + err = usbdrvwext_siwap(dev, NULL, &wrq->u.ap_addr, NULL); + break; + case SIOCGIWMODE: + err = usbdrvwext_giwmode(dev, NULL, &wrq->u.mode, NULL); + break; + case SIOCSIWESSID: + printk(KERN_ERR "CWY - usbdrvwext_siwessid\n"); + /* err = usbdrv_ioctl_setessid(dev, &wrq->u.essid); */ + err = usbdrvwext_siwessid(dev, NULL, &wrq->u.essid, NULL); - case SIOCGIWAP: - err = usbdrvwext_giwap(dev, NULL, &wrq->u.ap_addr, NULL); - break; + if (!err) + changed = 1; + break; + case SIOCGIWESSID: + err = usbdrvwext_giwessid(dev, NULL, &wrq->u.essid, NULL); + break; + case SIOCSIWRTS: + err = usbdrv_ioctl_setrts(dev, &wrq->u.rts); + if (! err) + changed = 1; + break; + /* set_auth */ + case SIOCIWFIRSTPRIV + 0x2: { + /* printk("CWY - SIOCIWFIRSTPRIV + 0x2(set_auth)\n"); */ + if (!capable(CAP_NET_ADMIN)) { + err = -EPERM; + break; + } + int val = *((int *) wrq->u.name); + if ((val < 0) || (val > 2)) { + err = -EINVAL; + break; + } else { + zfiWlanSetAuthenticationMode(dev, val); + if (macp->DeviceOpened == 1) { + zfiWlanDisable(dev, 0); + zfiWlanEnable(dev); + } - case SIOCSIWAP: - err = usbdrvwext_siwap(dev, NULL, &wrq->u.ap_addr, NULL); - break; + err = 0; + changed = 1; + } + } + break; + /* get_auth */ + case SIOCIWFIRSTPRIV + 0x3: { + int AuthMode = ZM_AUTH_MODE_OPEN; + /* printk("CWY - SIOCIWFIRSTPRIV + 0x3(get_auth)\n"); */ - case SIOCGIWMODE: - err = usbdrvwext_giwmode(dev, NULL, &wrq->u.mode, NULL); - break; + if (wrq->u.data.pointer) { + wrq->u.data.flags = 1; + AuthMode = zfiWlanQueryAuthenticationMode(dev, 0); + if (AuthMode == ZM_AUTH_MODE_OPEN) { + wrq->u.data.length = 12; - case SIOCSIWESSID: - printk(KERN_ERR "CWY - usbdrvwext_siwessid\n"); - //err = usbdrv_ioctl_setessid(dev, &wrq->u.essid); - err = usbdrvwext_siwessid(dev, NULL, &wrq->u.essid, NULL); + if (copy_to_user(wrq->u.data.pointer, + "open system", 12)) { + return -EFAULT; + } + } else if (AuthMode == ZM_AUTH_MODE_SHARED_KEY) { + wrq->u.data.length = 11; - if (! err) - changed = 1; - break; + if (copy_to_user(wrq->u.data.pointer, + "shared key", 11)) { + return -EFAULT; + } + } else if (AuthMode == ZM_AUTH_MODE_AUTO) { + wrq->u.data.length = 10; + if (copy_to_user(wrq->u.data.pointer, + "auto mode", 10)) { + return -EFAULT; + } + } else { + return -EFAULT; + } + } + } + break; + /* debug command */ + case ZDAPIOCTL: + if (copy_from_user(&zdreq, ifr->ifr_data, sizeof(zdreq))) { + printk(KERN_ERR "usbdrv : copy_from_user error\n"); + return -EFAULT; + } - case SIOCGIWESSID: - err = usbdrvwext_giwessid(dev, NULL, &wrq->u.essid, NULL); - break; + /* printk(KERN_WARNING + * "usbdrv : cmd = % 2x, reg = 0x%04lx, + *value = 0x%08lx\n", + * zdreq.cmd, zdreq.addr, zdreq.value); + */ + zfLnxPrivateIoctl(dev, &zdreq); + err = 0; + break; + case ZD_IOCTL_WPA: + if (copy_from_user(&zdparm, ifr->ifr_data, + sizeof(struct athr_wlan_param))) { + printk(KERN_ERR "usbdrv : copy_from_user error\n"); + return -EFAULT; + } - case SIOCSIWRTS: + usbdrv_wpa_ioctl(dev, &zdparm); + err = 0; + break; + case ZD_IOCTL_PARAM: { + int *p; + int op; + int arg; - err = usbdrv_ioctl_setrts(dev, &wrq->u.rts); - if (! err) - changed = 1; - break; + /* Point to the name field and retrieve the + * op and arg elements. + */ + p = (int *)wrq->u.name; + op = *p++; + arg = *p; + if (op == ZD_PARAM_ROAMING) { + printk(KERN_ERR + "*************ZD_PARAM_ROAMING : % d\n", arg); + /* macp->cardSetting.ap_scan=(U8)arg; */ + } + if (op == ZD_PARAM_PRIVACY) { + printk(KERN_ERR "ZD_IOCTL_PRIVACY : "); - case SIOCIWFIRSTPRIV + 0x2: /* set_auth */ - { - //printk("CWY - SIOCIWFIRSTPRIV + 0x2 (set_auth)\n"); - if (! capable(CAP_NET_ADMIN)) - { - err = -EPERM; + /* Turn on the privacy invoke flag */ + if (arg) { + /* mCap[0] |= CAP_PRIVACY; */ + /* macp->cardSetting.EncryOnOff[0] = 1; */ + printk(KERN_ERR "enable\n"); + + } else { + /* mCap[0] &= ~CAP_PRIVACY; */ + /* macp->cardSetting.EncryOnOff[0] = 0; */ + printk(KERN_ERR "disable\n"); + } + /* changed=1; */ + } + if (op == ZD_PARAM_WPA) { + + printk(KERN_ERR "ZD_PARAM_WPA : "); + + if (arg) { + printk(KERN_ERR "enable\n"); + + if (zfiWlanQueryWlanMode(dev) != ZM_MODE_AP) { + printk(KERN_ERR "Station Mode\n"); + /* zfiWlanQueryWpaIe(dev, (u8_t *) + &wpaIe, &wpalen); */ + /* printk("wpaIe : % 2x, % 2x, % 2x\n", + wpaIe[21], wpaIe[22], wpaIe[23]); */ + /* printk("rsnIe : % 2x, % 2x, % 2x\n", + wpaIe[17], wpaIe[18], wpaIe[19]); */ + if ((macp->supIe[21] == 0x50) && + (macp->supIe[22] == 0xf2) && + (macp->supIe[23] == 0x2)) { + printk(KERN_ERR + "wd->sta.authMode = ZM_AUTH_MODE_WPAPSK\n"); + /* wd->sta.authMode = ZM_AUTH_MODE_WPAPSK; */ + /* wd->ws.authMode = ZM_AUTH_MODE_WPAPSK; */ + zfiWlanSetAuthenticationMode(dev, + ZM_AUTH_MODE_WPAPSK); + } else if ((macp->supIe[21] == 0x50) && + (macp->supIe[22] == 0xf2) && + (macp->supIe[23] == 0x1)) { + printk(KERN_ERR + "wd->sta.authMode = ZM_AUTH_MODE_WPA\n"); + /* wd->sta.authMode = ZM_AUTH_MODE_WPA; */ + /* wd->ws.authMode = ZM_AUTH_MODE_WPA; */ + zfiWlanSetAuthenticationMode(dev, + ZM_AUTH_MODE_WPA); + } else if ((macp->supIe[17] == 0xf) && + (macp->supIe[18] == 0xac) && + (macp->supIe[19] == 0x2)) + { + printk(KERN_ERR + "wd->sta.authMode = ZM_AUTH_MODE_WPA2PSK\n"); + /* wd->sta.authMode = ZM_AUTH_MODE_WPA2PSK; */ + /* wd->ws.authMode = ZM_AUTH_MODE_WPA2PSK; */ + zfiWlanSetAuthenticationMode(dev, + ZM_AUTH_MODE_WPA2PSK); + } else if ((macp->supIe[17] == 0xf) && + (macp->supIe[18] == 0xac) && + (macp->supIe[19] == 0x1)) + { + printk(KERN_ERR + "wd->sta.authMode = ZM_AUTH_MODE_WPA2\n"); + /* wd->sta.authMode = ZM_AUTH_MODE_WPA2; */ + /* wd->ws.authMode = ZM_AUTH_MODE_WPA2; */ + zfiWlanSetAuthenticationMode(dev, + ZM_AUTH_MODE_WPA2); + } + /* WPA or WPAPSK */ + if ((macp->supIe[21] == 0x50) || + (macp->supIe[22] == 0xf2)) { + if (macp->supIe[11] == 0x2) { + printk(KERN_ERR + "wd->sta.wepStatus = ZM_ENCRYPTION_TKIP\n"); + /* wd->sta.wepStatus = ZM_ENCRYPTION_TKIP; */ + /* wd->ws.wepStatus = ZM_ENCRYPTION_TKIP; */ + zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_TKIP); + } else { + printk(KERN_ERR + "wd->sta.wepStatus = ZM_ENCRYPTION_AES\n"); + /* wd->sta.wepStatus = ZM_ENCRYPTION_AES; */ + /* wd->ws.wepStatus = ZM_ENCRYPTION_AES; */ + zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_AES); + } + } + //WPA2 or WPA2PSK + if ((macp->supIe[17] == 0xf) || + (macp->supIe[18] == 0xac)) { + if (macp->supIe[13] == 0x2) { + printk(KERN_ERR + "wd->sta.wepStatus = ZM_ENCRYPTION_TKIP\n"); + /* wd->sta.wepStatus = ZM_ENCRYPTION_TKIP; */ + /* wd->ws.wepStatus = ZM_ENCRYPTION_TKIP; */ + zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_TKIP); + } else { + printk(KERN_ERR + "wd->sta.wepStatus = ZM_ENCRYPTION_AES\n"); + /* wd->sta.wepStatus = ZM_ENCRYPTION_AES; */ + /* wd->ws.wepStatus = ZM_ENCRYPTION_AES; */ + zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_AES); + } + } + } + zfiWlanSetWpaSupport(dev, 1); + } else { + /* Reset the WPA related variables */ + printk(KERN_ERR "disable\n"); + + zfiWlanSetWpaSupport(dev, 0); + zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_OPEN); + zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_WEP_DISABLED); + + /* Now we only set the length in the WPA IE + * field to zero. + *macp->cardSetting.WPAIe[1] = 0; + */ + } + } + + if (op == ZD_PARAM_COUNTERMEASURES) { + printk(KERN_ERR + "****************ZD_PARAM_COUNTERMEASURES : "); + + if(arg) { + /* mCounterMeasureState=1; */ + printk(KERN_ERR "enable\n"); + } else { + /* mCounterMeasureState=0; */ + printk(KERN_ERR "disable\n"); + } + } + if (op == ZD_PARAM_DROPUNENCRYPTED) { + printk(KERN_ERR "ZD_PARAM_DROPUNENCRYPTED : "); + + if(arg) { + printk(KERN_ERR "enable\n"); + } else { + printk(KERN_ERR "disable\n"); + } + } + if (op == ZD_PARAM_AUTH_ALGS) { + printk(KERN_ERR "ZD_PARAM_AUTH_ALGS : "); + + if (arg == 0) { + printk(KERN_ERR "OPEN_SYSTEM\n"); + } else { + printk(KERN_ERR "SHARED_KEY\n"); + } + } + if (op == ZD_PARAM_WPS_FILTER) { + printk(KERN_ERR "ZD_PARAM_WPS_FILTER : "); + + if (arg) { + /* mCounterMeasureState=1; */ + macp->forwardMgmt = 1; + printk(KERN_ERR "enable\n"); + } else { + /* mCounterMeasureState=0; */ + macp->forwardMgmt = 0; + printk(KERN_ERR "disable\n"); + } + } + } + err = 0; + break; + case ZD_IOCTL_GETWPAIE: { + struct ieee80211req_wpaie req_wpaie; + u16_t apId, i, j; + + /* Get the AP Id */ + apId = zfLnxGetVapId(dev); + + if (apId == 0xffff) { + apId = 0; + } else { + apId = apId + 1; + } + + if (copy_from_user(&req_wpaie, ifr->ifr_data, + sizeof(struct ieee80211req_wpaie))) { + printk(KERN_ERR "usbdrv : copy_from_user error\n"); + return -EFAULT; + } + + for (i = 0; i < ZM_OAL_MAX_STA_SUPPORT; i++) { + for (j = 0; j < IEEE80211_ADDR_LEN; j++) { + if (macp->stawpaie[i].wpa_macaddr[j] != + req_wpaie.wpa_macaddr[j]) break; } - { - int val = *( (int *) wrq->u.name ); - if ((val < 0) || (val > 2)) - { - err = -EINVAL; - break; - } - else - { - zfiWlanSetAuthenticationMode(dev, val); - - if (macp->DeviceOpened == 1) - { - zfiWlanDisable(dev, 0); - zfiWlanEnable(dev); - } - - err = 0; - changed = 1; - } - } - } + if (j == 6) break; - - case SIOCIWFIRSTPRIV + 0x3: /* get_auth */ - { - int AuthMode = ZM_AUTH_MODE_OPEN; - - //printk("CWY - SIOCIWFIRSTPRIV + 0x3 (get_auth)\n"); - - if (wrq->u.data.pointer) - { - wrq->u.data.flags = 1; - - AuthMode = zfiWlanQueryAuthenticationMode(dev, 0); - if (AuthMode == ZM_AUTH_MODE_OPEN) - { - wrq->u.data.length = 12; - - if (copy_to_user(wrq->u.data.pointer, "open system", 12)) - { - return -EFAULT; - } - } - else if (AuthMode == ZM_AUTH_MODE_SHARED_KEY) - { - wrq->u.data.length = 11; - - if (copy_to_user(wrq->u.data.pointer, "shared key", 11)) - { - return -EFAULT; - } - } - else if (AuthMode == ZM_AUTH_MODE_AUTO) - { - wrq->u.data.length = 10; - - if (copy_to_user(wrq->u.data.pointer, "auto mode", 10)) - { - return -EFAULT; - } - } - else - { - return -EFAULT; - } - } } - break; + if (i < ZM_OAL_MAX_STA_SUPPORT) { + /* printk("ZD_IOCTL_GETWPAIE - sta index = % d\n", i); */ + memcpy(req_wpaie.wpa_ie, macp->stawpaie[i].wpa_ie, + IEEE80211_MAX_IE_SIZE); + } - case ZDAPIOCTL: //debug command - if (copy_from_user(&zdreq, ifr->ifr_data, sizeof (zdreq))) - { - printk(KERN_ERR "usbdrv: copy_from_user error\n"); - return -EFAULT; - } + if (copy_to_user(wrq->u.data.pointer, &req_wpaie, + sizeof(struct ieee80211req_wpaie))) { + return -EFAULT; + } + } - //printk(KERN_DEBUG "usbdrv: cmd=%2x, reg=0x%04lx, value=0x%08lx\n", - // zdreq.cmd, zdreq.addr, zdreq.value); + err = 0; + break; + #ifdef ZM_ENABLE_CENC + case ZM_IOCTL_CENC: + if (copy_from_user(&macp->zd_wpa_req, ifr->ifr_data, + sizeof(struct athr_wlan_param))) { + printk(KERN_ERR "usbdrv : copy_from_user error\n"); + return -EFAULT; + } - zfLnxPrivateIoctl(dev, &zdreq); + usbdrv_cenc_ioctl(dev, + (struct zydas_cenc_param *)&macp->zd_wpa_req); + err = 0; + break; + #endif /* ZM_ENABLE_CENC */ + default: + err = -EOPNOTSUPP; + break; + } - err = 0; - break; - - case ZD_IOCTL_WPA: - if (copy_from_user(&zdparm, ifr->ifr_data, sizeof(struct athr_wlan_param))) - { - printk(KERN_ERR "usbdrv: copy_from_user error\n"); - return -EFAULT; - } - - usbdrv_wpa_ioctl(dev, &zdparm); - err = 0; - break; - - case ZD_IOCTL_PARAM: - { - int *p; - int op; - int arg; - - /* Point to the name field and retrieve the - * op and arg elements. */ - p = (int *)wrq->u.name; - op = *p++; - arg = *p; - - if(op == ZD_PARAM_ROAMING) - { - printk(KERN_ERR "************* ZD_PARAM_ROAMING: %d\n", arg); - //macp->cardSetting.ap_scan=(U8)arg; - } - if(op == ZD_PARAM_PRIVACY) - { - printk(KERN_ERR "ZD_IOCTL_PRIVACY: "); - - /* Turn on the privacy invoke flag */ - if(arg) - { - // mCap[0] |= CAP_PRIVACY; - // macp->cardSetting.EncryOnOff[0] = 1; - printk(KERN_ERR "enable\n"); - - } - else - { - // mCap[0] &= ~CAP_PRIVACY; - // macp->cardSetting.EncryOnOff[0] = 0; - printk(KERN_ERR "disable\n"); - } - //changed=1; - } - if(op == ZD_PARAM_WPA) - { - printk(KERN_ERR "ZD_PARAM_WPA: "); - - if(arg) - { - printk(KERN_ERR "enable\n"); - - if (zfiWlanQueryWlanMode(dev) != ZM_MODE_AP) - { - printk(KERN_ERR "Station Mode\n"); - //zfiWlanQueryWpaIe(dev, (u8_t *)&wpaIe, &wpalen); - //printk("wpaIe : %2x,%2x,%2x\n", wpaIe[21], wpaIe[22], wpaIe[23]); - //printk("rsnIe : %2x,%2x,%2x\n", wpaIe[17], wpaIe[18], wpaIe[19]); - if ((macp->supIe[21] == 0x50) && - (macp->supIe[22] == 0xf2) && - (macp->supIe[23] == 0x2)) - { - printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPAPSK\n"); - //wd->sta.authMode = ZM_AUTH_MODE_WPAPSK; - //wd->ws.authMode = ZM_AUTH_MODE_WPAPSK; - zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPAPSK); - } - else if ((macp->supIe[21] == 0x50) && - (macp->supIe[22] == 0xf2) && - (macp->supIe[23] == 0x1)) - { - printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPA\n"); - //wd->sta.authMode = ZM_AUTH_MODE_WPA; - //wd->ws.authMode = ZM_AUTH_MODE_WPA; - zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPA); - } - else if ((macp->supIe[17] == 0xf) && - (macp->supIe[18] == 0xac) && - (macp->supIe[19] == 0x2)) - { - printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPA2PSK\n"); - //wd->sta.authMode = ZM_AUTH_MODE_WPA2PSK; - //wd->ws.authMode = ZM_AUTH_MODE_WPA2PSK; - zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPA2PSK); - } - else if ((macp->supIe[17] == 0xf) && - (macp->supIe[18] == 0xac) && - (macp->supIe[19] == 0x1)) - { - printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPA2\n"); - //wd->sta.authMode = ZM_AUTH_MODE_WPA2; - //wd->ws.authMode = ZM_AUTH_MODE_WPA2; - zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPA2); - } - if ((macp->supIe[21] == 0x50) || (macp->supIe[22] == 0xf2))//WPA or WPAPSK - { - if (macp->supIe[11] == 0x2) - { - printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_TKIP\n"); - //wd->sta.wepStatus = ZM_ENCRYPTION_TKIP; - //wd->ws.wepStatus = ZM_ENCRYPTION_TKIP; - zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_TKIP); - } - else - { - printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_AES\n"); - //wd->sta.wepStatus = ZM_ENCRYPTION_AES; - //wd->ws.wepStatus = ZM_ENCRYPTION_AES; - zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_AES); - } - } - if ((macp->supIe[17] == 0xf) || (macp->supIe[18] == 0xac)) //WPA2 or WPA2PSK - { - if (macp->supIe[13] == 0x2) - { - printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_TKIP\n"); - //wd->sta.wepStatus = ZM_ENCRYPTION_TKIP; - //wd->ws.wepStatus = ZM_ENCRYPTION_TKIP; - zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_TKIP); - } - else - { - printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_AES\n"); - //wd->sta.wepStatus = ZM_ENCRYPTION_AES; - //wd->ws.wepStatus = ZM_ENCRYPTION_AES; - zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_AES); - } - } - } - zfiWlanSetWpaSupport(dev, 1); - } - else - { - /* Reset the WPA related variables */ - printk(KERN_ERR "disable\n"); - - zfiWlanSetWpaSupport(dev, 0); - zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_OPEN); - zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_WEP_DISABLED); - - /* Now we only set the length in the WPA IE - * field to zero. */ - //macp->cardSetting.WPAIe[1] = 0; - } - } - if(op == ZD_PARAM_COUNTERMEASURES) - { - printk(KERN_ERR "================ZD_PARAM_COUNTERMEASURES: "); - - if(arg) - { - // mCounterMeasureState=1; - printk(KERN_ERR "enable\n"); - } - else - { - // mCounterMeasureState=0; - printk(KERN_ERR "disable\n"); - } - } - if(op == ZD_PARAM_DROPUNENCRYPTED) - { - printk(KERN_ERR "ZD_PARAM_DROPUNENCRYPTED: "); - - if(arg) - { - printk(KERN_ERR "enable\n"); - } - else - { - printk(KERN_ERR "disable\n"); - } - } - if(op == ZD_PARAM_AUTH_ALGS) - { - printk(KERN_ERR "ZD_PARAM_AUTH_ALGS: "); - - if(arg == 0) - { - printk(KERN_ERR "OPEN_SYSTEM\n"); - } - else - { - printk(KERN_ERR "SHARED_KEY\n"); - } - } - if(op == ZD_PARAM_WPS_FILTER) - { - printk(KERN_ERR "ZD_PARAM_WPS_FILTER: "); - - if(arg) - { - // mCounterMeasureState=1; - macp->forwardMgmt = 1; - printk(KERN_ERR "enable\n"); - } - else - { - // mCounterMeasureState=0; - macp->forwardMgmt = 0; - printk(KERN_ERR "disable\n"); - } - } - } - err = 0; - break; - - case ZD_IOCTL_GETWPAIE: - { - struct ieee80211req_wpaie req_wpaie; - u16_t apId, i, j; - - /* Get the AP Id */ - apId = zfLnxGetVapId(dev); - - if (apId == 0xffff) - { - apId = 0; - } - else - { - apId = apId+1; - } - - if (copy_from_user(&req_wpaie, ifr->ifr_data, sizeof(struct ieee80211req_wpaie))){ - printk(KERN_ERR "usbdrv: copy_from_user error\n"); - return -EFAULT; - } - - for(i = 0; i < ZM_OAL_MAX_STA_SUPPORT; i++) - { - for(j = 0; j < IEEE80211_ADDR_LEN; j++) - { - if (macp->stawpaie[i].wpa_macaddr[j] != req_wpaie.wpa_macaddr[j]) - break; - } - if (j == 6) - break; - } - if (i < ZM_OAL_MAX_STA_SUPPORT) - { - //printk("ZD_IOCTL_GETWPAIE - sta index = %d\n", i); - memcpy(req_wpaie.wpa_ie, macp->stawpaie[i].wpa_ie, IEEE80211_MAX_IE_SIZE); - } - - if (copy_to_user(wrq->u.data.pointer, &req_wpaie, sizeof(struct ieee80211req_wpaie))) - { - return -EFAULT; - } - } - - err = 0; - break; -#ifdef ZM_ENABLE_CENC - case ZM_IOCTL_CENC: - if (copy_from_user(&macp->zd_wpa_req, ifr->ifr_data, sizeof(struct athr_wlan_param))) - { - printk(KERN_ERR "usbdrv: copy_from_user error\n"); - return -EFAULT; - } - - usbdrv_cenc_ioctl(dev, (struct zydas_cenc_param *)&macp->zd_wpa_req); - err = 0; - break; -#endif //ZM_ENABLE_CENC - default: - err = -EOPNOTSUPP; - break; - } - - - return err; + return err; } diff --git a/drivers/staging/otus/usbdrv.c b/drivers/staging/otus/usbdrv.c index dfe07072011f..565a839589f5 100644 --- a/drivers/staging/otus/usbdrv.c +++ b/drivers/staging/otus/usbdrv.c @@ -936,30 +936,26 @@ int zfLnxAllocAllUrbs(struct usbdrv_private *macp) for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x02)) + if (usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ printk(KERN_ERR "bulk in: wMaxPacketSize = %x\n", le16_to_cpu(endpoint->wMaxPacketSize)); } - if (((endpoint->bEndpointAddress & 0x80) == 0x00) && - ((endpoint->bmAttributes & 3) == 0x02)) + if (usb_endpoint_is_bulk_out(endpoint)) { /* we found a bulk out endpoint */ printk(KERN_ERR "bulk out: wMaxPacketSize = %x\n", le16_to_cpu(endpoint->wMaxPacketSize)); } - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x03)) + if (usb_endpoint_is_int_in(endpoint)) { /* we found a interrupt in endpoint */ printk(KERN_ERR "interrupt in: wMaxPacketSize = %x\n", le16_to_cpu(endpoint->wMaxPacketSize)); printk(KERN_ERR "interrupt in: int_interval = %d\n", endpoint->bInterval); } - if (((endpoint->bEndpointAddress & 0x80) == 0x00) && - ((endpoint->bmAttributes & 3) == 0x03)) + if (usb_endpoint_is_int_out(endpoint)) { /* we found a interrupt out endpoint */ printk(KERN_ERR "interrupt out: wMaxPacketSize = %x\n", le16_to_cpu(endpoint->wMaxPacketSize)); diff --git a/drivers/staging/otus/wwrap.c b/drivers/staging/otus/wwrap.c index 1bb5f596d6c3..4db8f6e75ad8 100644 --- a/drivers/staging/otus/wwrap.c +++ b/drivers/staging/otus/wwrap.c @@ -350,8 +350,7 @@ void zfLnxUsbDataIn_callback(urb_t *urb) buf->len = 0; #endif - if ((buf->tail + urb->actual_length) > buf->end) - BUG(); + BUG_ON((buf->tail + urb->actual_length) > buf->end); skb_put(buf, urb->actual_length); @@ -971,8 +970,7 @@ int zfLnxCencSendMsg(struct sock *netlink_sk, u_int8_t *msg, int len) out: return ret; nlmsg_failure: /*NLMSG_PUT ʧ°Ü£¬Ôò³·ÏúÌ×½Ó×Ö»º´æ*/ - if(skb) - kfree_skb(skb); + kfree_skb(skb); goto out; #undef COMMTYPE_GROUP diff --git a/drivers/staging/otus/zdcompat.h b/drivers/staging/otus/zdcompat.h index 8acf400fbc0b..d9a3b2d5ba1e 100644 --- a/drivers/staging/otus/zdcompat.h +++ b/drivers/staging/otus/zdcompat.h @@ -45,13 +45,6 @@ struct iw_request_info #endif #endif -#ifndef IRQ_NONE -typedef void irqreturn_t; -#define IRQ_NONE -#define IRQ_HANDLED -#define IRQ_RETVAL(x) -#endif - #ifndef in_atomic #define in_atomic() 0 #endif diff --git a/drivers/staging/p9auth/Kconfig b/drivers/staging/p9auth/Kconfig new file mode 100644 index 000000000000..d1c66d262020 --- /dev/null +++ b/drivers/staging/p9auth/Kconfig @@ -0,0 +1,9 @@ +config PLAN9AUTH + tristate "Plan 9 style capability device implementation" + default n + depends on CRYPTO + help + This module implements the Plan 9 style capability device. + + To compile this driver as a module, choose + M here: the module will be called p9auth. diff --git a/drivers/staging/p9auth/Makefile b/drivers/staging/p9auth/Makefile new file mode 100644 index 000000000000..3ebf6ff0eef2 --- /dev/null +++ b/drivers/staging/p9auth/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_PLAN9AUTH) += p9auth.o diff --git a/drivers/staging/p9auth/p9auth.c b/drivers/staging/p9auth/p9auth.c new file mode 100644 index 000000000000..3cac89b26faf --- /dev/null +++ b/drivers/staging/p9auth/p9auth.c @@ -0,0 +1,383 @@ +/* + * Plan 9 style capability device implementation for the Linux Kernel + * + * Copyright 2008, 2009 Ashwin Ganti + * + * Released under the GPLv2 + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CAP_MAJOR +#define CAP_MAJOR 0 +#endif + +#ifndef CAP_NR_DEVS +#define CAP_NR_DEVS 2 /* caphash and capuse */ +#endif + +#ifndef CAP_NODE_SIZE +#define CAP_NODE_SIZE 20 +#endif + +#define MAX_DIGEST_SIZE 20 + +struct cap_node { + char data[CAP_NODE_SIZE]; + struct list_head list; +}; + +struct cap_dev { + struct cap_node *head; + int node_size; + unsigned long size; + struct semaphore sem; + struct cdev cdev; +}; + +static int cap_major = CAP_MAJOR; +static int cap_minor; +static int cap_nr_devs = CAP_NR_DEVS; +static int cap_node_size = CAP_NODE_SIZE; + +module_param(cap_major, int, S_IRUGO); +module_param(cap_minor, int, S_IRUGO); +module_param(cap_nr_devs, int, S_IRUGO); + +MODULE_AUTHOR("Ashwin Ganti"); +MODULE_LICENSE("GPL"); + +static struct cap_dev *cap_devices; + +static void hexdump(unsigned char *buf, unsigned int len) +{ + while (len--) + printk("%02x", *buf++); + printk("\n"); +} + +static char *cap_hash(char *plain_text, unsigned int plain_text_size, + char *key, unsigned int key_size) +{ + struct scatterlist sg; + char *result; + struct crypto_hash *tfm; + struct hash_desc desc; + int ret; + + tfm = crypto_alloc_hash("hmac(sha1)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { + printk(KERN_ERR + "failed to load transform for hmac(sha1): %ld\n", + PTR_ERR(tfm)); + return NULL; + } + + desc.tfm = tfm; + desc.flags = 0; + + result = kzalloc(MAX_DIGEST_SIZE, GFP_KERNEL); + if (!result) { + printk(KERN_ERR "out of memory!\n"); + goto out; + } + + sg_set_buf(&sg, plain_text, plain_text_size); + + ret = crypto_hash_setkey(tfm, key, key_size); + if (ret) { + printk(KERN_ERR "setkey() failed ret=%d\n", ret); + kfree(result); + result = NULL; + goto out; + } + + ret = crypto_hash_digest(&desc, &sg, plain_text_size, result); + if (ret) { + printk(KERN_ERR "digest () failed ret=%d\n", ret); + kfree(result); + result = NULL; + goto out; + } + + printk(KERN_DEBUG "crypto hash digest size %d\n", + crypto_hash_digestsize(tfm)); + hexdump(result, MAX_DIGEST_SIZE); + +out: + crypto_free_hash(tfm); + return result; +} + +static int cap_trim(struct cap_dev *dev) +{ + struct cap_node *tmp; + struct list_head *pos, *q; + if (dev->head != NULL) { + list_for_each_safe(pos, q, &(dev->head->list)) { + tmp = list_entry(pos, struct cap_node, list); + list_del(pos); + kfree(tmp); + } + } + return 0; +} + +static int cap_open(struct inode *inode, struct file *filp) +{ + struct cap_dev *dev; + dev = container_of(inode->i_cdev, struct cap_dev, cdev); + filp->private_data = dev; + + /* trim to 0 the length of the device if open was write-only */ + if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; + cap_trim(dev); + up(&dev->sem); + } + /* initialise the head if it is NULL */ + if (dev->head == NULL) { + dev->head = kmalloc(sizeof(struct cap_node), GFP_KERNEL); + INIT_LIST_HEAD(&(dev->head->list)); + } + return 0; +} + +static int cap_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +static ssize_t cap_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + struct cap_node *node_ptr, *tmp; + struct list_head *pos; + struct cap_dev *dev = filp->private_data; + ssize_t retval = -ENOMEM; + struct cred *new; + int len, target_int, source_int, flag = 0; + char *user_buf, *user_buf_running, *source_user, *target_user, + *rand_str, *hash_str, *result; + + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; + + node_ptr = kmalloc(sizeof(struct cap_node), GFP_KERNEL); + user_buf = kzalloc(count, GFP_KERNEL); + + if (copy_from_user(user_buf, buf, count)) { + retval = -EFAULT; + goto out; + } + + /* + * If the minor number is 0 ( /dev/caphash ) then simply add the + * hashed capability supplied by the user to the list of hashes + */ + if (0 == iminor(filp->f_dentry->d_inode)) { + printk(KERN_INFO "Capability being written to /dev/caphash : \n"); + hexdump(user_buf, count); + memcpy(node_ptr->data, user_buf, count); + list_add(&(node_ptr->list), &(dev->head->list)); + } else { + /* + * break the supplied string into tokens with @ as the + * delimiter If the string is "user1@user2@randomstring" we + * need to split it and hash 'user1@user2' using 'randomstring' + * as the key. + */ + user_buf_running = kstrdup(user_buf, GFP_KERNEL); + source_user = strsep(&user_buf_running, "@"); + target_user = strsep(&user_buf_running, "@"); + rand_str = strsep(&user_buf_running, "@"); + + /* hash the string user1@user2 with rand_str as the key */ + len = strlen(source_user) + strlen(target_user) + 1; + hash_str = kzalloc(len, GFP_KERNEL); + strcat(hash_str, source_user); + strcat(hash_str, "@"); + strcat(hash_str, target_user); + + printk(KERN_ALERT "the source user is %s \n", source_user); + printk(KERN_ALERT "the target user is %s \n", target_user); + + result = cap_hash(hash_str, len, rand_str, strlen(rand_str)); + if (NULL == result) { + retval = -EFAULT; + goto out; + } + memcpy(node_ptr->data, result, CAP_NODE_SIZE); + /* Change the process's uid if the hash is present in the + * list of hashes + */ + list_for_each(pos, &(cap_devices->head->list)) { + /* + * Change the user id of the process if the hashes + * match + */ + if (0 == + memcmp(result, + list_entry(pos, struct cap_node, + list)->data, + CAP_NODE_SIZE)) { + target_int = (unsigned int) + simple_strtol(target_user, NULL, 0); + source_int = (unsigned int) + simple_strtol(source_user, NULL, 0); + flag = 1; + + /* + * Check whether the process writing to capuse + * is actually owned by the source owner + */ + if (source_int != current_uid()) { + printk(KERN_ALERT + "Process is not owned by the source user of the capability.\n"); + retval = -EFAULT; + goto out; + } + /* + * What all id's need to be changed here? uid, + * euid, fsid, savedids ?? Currently I am + * changing the effective user id since most of + * the authorisation decisions are based on it + */ + new = prepare_creds(); + if (!new) { + retval = -ENOMEM; + goto out; + } + new->uid = (uid_t) target_int; + new->euid = (uid_t) target_int; + retval = commit_creds(new); + if (retval) + goto out; + + /* + * Remove the capability from the list and + * break + */ + tmp = list_entry(pos, struct cap_node, list); + list_del(pos); + kfree(tmp); + break; + } + } + if (0 == flag) { + /* + * The capability is not present in the list of the + * hashes stored, hence return failure + */ + printk(KERN_ALERT + "Invalid capabiliy written to /dev/capuse \n"); + retval = -EFAULT; + goto out; + } + } + *f_pos += count; + retval = count; + /* update the size */ + if (dev->size < *f_pos) + dev->size = *f_pos; + +out: + up(&dev->sem); + return retval; +} + +static const struct file_operations cap_fops = { + .owner = THIS_MODULE, + .write = cap_write, + .open = cap_open, + .release = cap_release, +}; + +static void cap_cleanup_module(void) +{ + int i; + dev_t devno = MKDEV(cap_major, cap_minor); + if (cap_devices) { + for (i = 0; i < cap_nr_devs; i++) { + cap_trim(cap_devices + i); + cdev_del(&cap_devices[i].cdev); + } + kfree(cap_devices); + } + unregister_chrdev_region(devno, cap_nr_devs); + +} + +static void cap_setup_cdev(struct cap_dev *dev, int index) +{ + int err, devno = MKDEV(cap_major, cap_minor + index); + cdev_init(&dev->cdev, &cap_fops); + dev->cdev.owner = THIS_MODULE; + dev->cdev.ops = &cap_fops; + err = cdev_add(&dev->cdev, devno, 1); + if (err) + printk(KERN_NOTICE "Error %d adding cap%d", err, index); +} + +static int cap_init_module(void) +{ + int result, i; + dev_t dev = 0; + + if (cap_major) { + dev = MKDEV(cap_major, cap_minor); + result = register_chrdev_region(dev, cap_nr_devs, "cap"); + } else { + result = alloc_chrdev_region(&dev, cap_minor, cap_nr_devs, + "cap"); + cap_major = MAJOR(dev); + } + + if (result < 0) { + printk(KERN_WARNING "cap: can't get major %d\n", + cap_major); + return result; + } + + cap_devices = kzalloc(cap_nr_devs * sizeof(struct cap_dev), + GFP_KERNEL); + if (!cap_devices) { + result = -ENOMEM; + goto fail; + } + + /* Initialize each device. */ + for (i = 0; i < cap_nr_devs; i++) { + cap_devices[i].node_size = cap_node_size; + init_MUTEX(&cap_devices[i].sem); + cap_setup_cdev(&cap_devices[i], i); + } + + return 0; + +fail: + cap_cleanup_module(); + return result; +} + +module_init(cap_init_module); +module_exit(cap_cleanup_module); + + diff --git a/drivers/staging/phison/Kconfig b/drivers/staging/phison/Kconfig new file mode 100644 index 000000000000..d3c65d315a2e --- /dev/null +++ b/drivers/staging/phison/Kconfig @@ -0,0 +1,5 @@ +config IDE_PHISON + tristate "PCIE ATA PS5000 IDE support" + depends on PCI && ATA && ATA_SFF + ---help--- + This is an experimental driver for PS5000 IDE driver. diff --git a/drivers/staging/phison/Makefile b/drivers/staging/phison/Makefile new file mode 100644 index 000000000000..7642a2190e91 --- /dev/null +++ b/drivers/staging/phison/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_IDE_PHISON) += phison.o diff --git a/drivers/staging/phison/phison.c b/drivers/staging/phison/phison.c new file mode 100644 index 000000000000..270ebcb681a2 --- /dev/null +++ b/drivers/staging/phison/phison.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2006 Red Hat + * + * May be copied or modified under the terms of the GNU General Public License + * + * [Modify History] + * #0001, Evan, 2008.10.22, V0.00, New release. + * #0002, Evan, 2008.11.01, V0.90, Test Work In Ubuntu Linux 8.04. + * #0003, Evan, 2008.01.08, V0.91, Change Name "PCIE-SSD" to "E-BOX". + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PHISON_DEBUG + +#define DRV_NAME "phison_e-box" /* #0003 */ +#define DRV_VERSION "0.91" /* #0003 */ + +#define PCI_VENDOR_ID_PHISON 0x1987 +#define PCI_DEVICE_ID_PS5000 0x5000 + +static int phison_pre_reset(struct ata_link *link, unsigned long deadline) +{ + int ret; + struct ata_port *ap = link->ap; + + ap->cbl = ATA_CBL_NONE; + ret = ata_std_prereset(link, deadline); + dev_dbg(ap->dev, "phison_pre_reset(), ret = %x\n", ret); + return ret; +} + +static struct scsi_host_template phison_sht = { + ATA_BMDMA_SHT(DRV_NAME), +}; + +static struct ata_port_operations phison_ops = { + .inherits = &ata_bmdma_port_ops, + .prereset = phison_pre_reset, +}; + +static int phison_init_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int ret; + struct ata_port_info info = { + .flags = ATA_FLAG_NO_ATAPI, + + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = ATA_UDMA5, + + .port_ops = &phison_ops, + }; + const struct ata_port_info *ppi[] = { &info, NULL }; + + ret = ata_pci_sff_init_one(pdev, ppi, &phison_sht, NULL); + + dev_dbg(&pdev->dev, "phison_init_one(), ret = %x\n", ret); + + return ret; +} + +static struct pci_device_id phison_pci_tbl[] = { + { PCI_VENDOR_ID_PHISON, PCI_DEVICE_ID_PS5000, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, phison_pci_tbl); + +static struct pci_driver phison_pci_driver = { + .name = DRV_NAME, + .id_table = phison_pci_tbl, + .probe = phison_init_one, + .remove = ata_pci_remove_one, +#ifdef CONFIG_PM /* haven't tested it. */ + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, +#endif +}; + +static int phison_ide_init(void) +{ + return pci_register_driver(&phison_pci_driver); +} + +static void phison_ide_exit(void) +{ + pci_unregister_driver(&phison_pci_driver); +} + +module_init(phison_ide_init); +module_exit(phison_ide_exit); + +MODULE_AUTHOR("Evan Ko"); +MODULE_DESCRIPTION("PCIE driver module for PHISON PS5000 E-BOX"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/staging/pohmelfs/Kconfig b/drivers/staging/pohmelfs/Kconfig new file mode 100644 index 000000000000..58158b8780f4 --- /dev/null +++ b/drivers/staging/pohmelfs/Kconfig @@ -0,0 +1,28 @@ +config POHMELFS + tristate "POHMELFS filesystem support" + depends on NET + select CONNECTOR + select CRYPTO + select CRYPTO_BLKCIPHER + select CRYPTO_HMAC + help + POHMELFS stands for Parallel Optimized Host Message Exchange Layered + File System. This is a network filesystem which supports coherent + caching of data and metadata on clients. + +config POHMELFS_DEBUG + bool "POHMELFS debugging" + depends on POHMELFS + default n + help + Turns on excessive POHMELFS debugging facilities. + You usually do not want to slow things down noticeably and get really + lots of kernel messages in syslog. + +config POHMELFS_CRYPTO + bool "POHMELFS crypto support" + depends on POHMELFS + help + This option allows to encrypt and/or protect with strong + cryptographic hash all dataflow between server and clients. + Each config group can have its own keys. diff --git a/drivers/staging/pohmelfs/Makefile b/drivers/staging/pohmelfs/Makefile new file mode 100644 index 000000000000..196561ca26bc --- /dev/null +++ b/drivers/staging/pohmelfs/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_POHMELFS) += pohmelfs.o + +pohmelfs-y := inode.o config.o dir.o net.o path_entry.o trans.o crypto.o lock.o mcache.o diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c new file mode 100644 index 000000000000..3e67da9ea381 --- /dev/null +++ b/drivers/staging/pohmelfs/config.c @@ -0,0 +1,478 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "netfs.h" + +/* + * Global configuration list. + * Each client can be asked to get one of them. + * + * Allows to provide remote server address (ipv4/v6/whatever), port + * and so on via kernel connector. + */ + +static struct cb_id pohmelfs_cn_id = {.idx = POHMELFS_CN_IDX, .val = POHMELFS_CN_VAL}; +static LIST_HEAD(pohmelfs_config_list); +static DEFINE_MUTEX(pohmelfs_config_lock); + +static inline int pohmelfs_config_eql(struct pohmelfs_ctl *sc, struct pohmelfs_ctl *ctl) +{ + if (sc->idx == ctl->idx && sc->type == ctl->type && + sc->proto == ctl->proto && + sc->addrlen == ctl->addrlen && + !memcmp(&sc->addr, &ctl->addr, ctl->addrlen)) + return 1; + + return 0; +} + +static struct pohmelfs_config_group *pohmelfs_find_config_group(unsigned int idx) +{ + struct pohmelfs_config_group *g, *group = NULL; + + list_for_each_entry(g, &pohmelfs_config_list, group_entry) { + if (g->idx == idx) { + group = g; + break; + } + } + + return group; +} + +static struct pohmelfs_config_group *pohmelfs_find_create_config_group(unsigned int idx) +{ + struct pohmelfs_config_group *g; + + g = pohmelfs_find_config_group(idx); + if (g) + return g; + + g = kzalloc(sizeof(struct pohmelfs_config_group), GFP_KERNEL); + if (!g) + return NULL; + + INIT_LIST_HEAD(&g->config_list); + g->idx = idx; + g->num_entry = 0; + + list_add_tail(&g->group_entry, &pohmelfs_config_list); + + return g; +} + +int pohmelfs_copy_config(struct pohmelfs_sb *psb) +{ + struct pohmelfs_config_group *g; + struct pohmelfs_config *c, *dst; + int err = -ENODEV; + + mutex_lock(&pohmelfs_config_lock); + + g = pohmelfs_find_config_group(psb->idx); + if (!g) + goto out_unlock; + + /* + * Run over all entries in given config group and try to crate and + * initialize those, which do not exist in superblock list. + * Skip all existing entries. + */ + + list_for_each_entry(c, &g->config_list, config_entry) { + err = 0; + list_for_each_entry(dst, &psb->state_list, config_entry) { + if (pohmelfs_config_eql(&dst->state.ctl, &c->state.ctl)) { + err = -EEXIST; + break; + } + } + + if (err) + continue; + + dst = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL); + if (!dst) { + err = -ENOMEM; + break; + } + + memcpy(&dst->state.ctl, &c->state.ctl, sizeof(struct pohmelfs_ctl)); + + list_add_tail(&dst->config_entry, &psb->state_list); + + err = pohmelfs_state_init_one(psb, dst); + if (err) { + list_del(&dst->config_entry); + kfree(dst); + } + + err = 0; + } + +out_unlock: + mutex_unlock(&pohmelfs_config_lock); + + return err; +} + +int pohmelfs_copy_crypto(struct pohmelfs_sb *psb) +{ + struct pohmelfs_config_group *g; + int err = -ENOENT; + + mutex_lock(&pohmelfs_config_lock); + g = pohmelfs_find_config_group(psb->idx); + if (!g) + goto err_out_exit; + + if (g->hash_string) { + err = -ENOMEM; + psb->hash_string = kstrdup(g->hash_string, GFP_KERNEL); + if (!psb->hash_string) + goto err_out_exit; + psb->hash_strlen = g->hash_strlen; + } + + if (g->cipher_string) { + psb->cipher_string = kstrdup(g->cipher_string, GFP_KERNEL); + if (!psb->cipher_string) + goto err_out_free_hash_string; + psb->cipher_strlen = g->cipher_strlen; + } + + if (g->hash_keysize) { + psb->hash_key = kmalloc(g->hash_keysize, GFP_KERNEL); + if (!psb->hash_key) + goto err_out_free_cipher_string; + memcpy(psb->hash_key, g->hash_key, g->hash_keysize); + psb->hash_keysize = g->hash_keysize; + } + + if (g->cipher_keysize) { + psb->cipher_key = kmalloc(g->cipher_keysize, GFP_KERNEL); + if (!psb->cipher_key) + goto err_out_free_hash; + memcpy(psb->cipher_key, g->cipher_key, g->cipher_keysize); + psb->cipher_keysize = g->cipher_keysize; + } + + mutex_unlock(&pohmelfs_config_lock); + + return 0; + +err_out_free_hash: + kfree(psb->hash_key); +err_out_free_cipher_string: + kfree(psb->cipher_string); +err_out_free_hash_string: + kfree(psb->hash_string); +err_out_exit: + mutex_unlock(&pohmelfs_config_lock); + return err; +} + +static int pohmelfs_send_reply(int err, int msg_num, int action, struct cn_msg *msg, struct pohmelfs_ctl *ctl) +{ + struct pohmelfs_cn_ack *ack; + + ack = kmalloc(sizeof(struct pohmelfs_cn_ack), GFP_KERNEL); + if (!ack) + return -ENOMEM; + + memset(ack, 0, sizeof(struct pohmelfs_cn_ack)); + memcpy(&ack->msg, msg, sizeof(struct cn_msg)); + + if (action == POHMELFS_CTLINFO_ACK) + memcpy(&ack->ctl, ctl, sizeof(struct pohmelfs_ctl)); + + ack->msg.len = sizeof(struct pohmelfs_cn_ack) - sizeof(struct cn_msg); + ack->msg.ack = msg->ack + 1; + ack->error = err; + ack->msg_num = msg_num; + + cn_netlink_send(&ack->msg, 0, GFP_KERNEL); + kfree(ack); + return 0; +} + +static int pohmelfs_cn_disp(struct cn_msg *msg) +{ + struct pohmelfs_config_group *g; + struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data; + struct pohmelfs_config *c, *tmp; + int err = 0, i = 1; + + if (msg->len != sizeof(struct pohmelfs_ctl)) + return -EBADMSG; + + mutex_lock(&pohmelfs_config_lock); + + g = pohmelfs_find_config_group(ctl->idx); + if (!g) { + pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL); + goto out_unlock; + } + + list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) { + struct pohmelfs_ctl *sc = &c->state.ctl; + if (pohmelfs_send_reply(err, g->num_entry - i, POHMELFS_CTLINFO_ACK, msg, sc)) { + err = -ENOMEM; + goto out_unlock; + } + i += 1; + } + +out_unlock: + mutex_unlock(&pohmelfs_config_lock); + return err; +} + +static int pohmelfs_cn_ctl(struct cn_msg *msg, int action) +{ + struct pohmelfs_config_group *g; + struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data; + struct pohmelfs_config *c, *tmp; + int err = 0; + + if (msg->len != sizeof(struct pohmelfs_ctl)) + return -EBADMSG; + + mutex_lock(&pohmelfs_config_lock); + + g = pohmelfs_find_create_config_group(ctl->idx); + if (!g) { + err = -ENOMEM; + goto out_unlock; + } + + list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) { + struct pohmelfs_ctl *sc = &c->state.ctl; + + if (pohmelfs_config_eql(sc, ctl)) { + if (action == POHMELFS_FLAGS_ADD) { + err = -EEXIST; + goto out_unlock; + } else if (action == POHMELFS_FLAGS_DEL) { + list_del(&c->config_entry); + g->num_entry--; + kfree(c); + goto out_unlock; + } else { + err = -EEXIST; + goto out_unlock; + } + } + } + if (action == POHMELFS_FLAGS_DEL) { + err = -EBADMSG; + goto out_unlock; + } + + c = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL); + if (!c) { + err = -ENOMEM; + goto out_unlock; + } + memcpy(&c->state.ctl, ctl, sizeof(struct pohmelfs_ctl)); + g->num_entry++; + list_add_tail(&c->config_entry, &g->config_list); + +out_unlock: + mutex_unlock(&pohmelfs_config_lock); + if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL)) + err = -ENOMEM; + + return err; +} + +static int pohmelfs_crypto_hash_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c) +{ + char *algo = (char *)c->data; + u8 *key = (u8 *)(algo + c->strlen); + + if (g->hash_string) + return -EEXIST; + + g->hash_string = kstrdup(algo, GFP_KERNEL); + if (!g->hash_string) + return -ENOMEM; + g->hash_strlen = c->strlen; + g->hash_keysize = c->keysize; + + g->hash_key = kmalloc(c->keysize, GFP_KERNEL); + if (!g->hash_key) { + kfree(g->hash_string); + return -ENOMEM; + } + + memcpy(g->hash_key, key, c->keysize); + + return 0; +} + +static int pohmelfs_crypto_cipher_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c) +{ + char *algo = (char *)c->data; + u8 *key = (u8 *)(algo + c->strlen); + + if (g->cipher_string) + return -EEXIST; + + g->cipher_string = kstrdup(algo, GFP_KERNEL); + if (!g->cipher_string) + return -ENOMEM; + g->cipher_strlen = c->strlen; + g->cipher_keysize = c->keysize; + + g->cipher_key = kmalloc(c->keysize, GFP_KERNEL); + if (!g->cipher_key) { + kfree(g->cipher_string); + return -ENOMEM; + } + + memcpy(g->cipher_key, key, c->keysize); + + return 0; +} + + +static int pohmelfs_cn_crypto(struct cn_msg *msg) +{ + struct pohmelfs_crypto *crypto = (struct pohmelfs_crypto *)msg->data; + struct pohmelfs_config_group *g; + int err = 0; + + dprintk("%s: idx: %u, strlen: %u, type: %u, keysize: %u, algo: %s.\n", + __func__, crypto->idx, crypto->strlen, crypto->type, + crypto->keysize, (char *)crypto->data); + + mutex_lock(&pohmelfs_config_lock); + g = pohmelfs_find_create_config_group(crypto->idx); + if (!g) { + err = -ENOMEM; + goto out_unlock; + } + + switch (crypto->type) { + case POHMELFS_CRYPTO_HASH: + err = pohmelfs_crypto_hash_init(g, crypto); + break; + case POHMELFS_CRYPTO_CIPHER: + err = pohmelfs_crypto_cipher_init(g, crypto); + break; + default: + err = -ENOTSUPP; + break; + } + +out_unlock: + mutex_unlock(&pohmelfs_config_lock); + if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL)) + err = -ENOMEM; + + return err; +} + +static void pohmelfs_cn_callback(void *data) +{ + struct cn_msg *msg = data; + int err; + + switch (msg->flags) { + case POHMELFS_FLAGS_ADD: + err = pohmelfs_cn_ctl(msg, POHMELFS_FLAGS_ADD); + break; + case POHMELFS_FLAGS_DEL: + err = pohmelfs_cn_ctl(msg, POHMELFS_FLAGS_DEL); + break; + case POHMELFS_FLAGS_SHOW: + err = pohmelfs_cn_disp(msg); + break; + case POHMELFS_FLAGS_CRYPTO: + err = pohmelfs_cn_crypto(msg); + break; + default: + err = -ENOSYS; + break; + } +} + +int pohmelfs_config_check(struct pohmelfs_config *config, int idx) +{ + struct pohmelfs_ctl *ctl = &config->state.ctl; + struct pohmelfs_config *tmp; + int err = -ENOENT; + struct pohmelfs_ctl *sc; + struct pohmelfs_config_group *g; + + mutex_lock(&pohmelfs_config_lock); + + g = pohmelfs_find_config_group(ctl->idx); + if (g) { + list_for_each_entry(tmp, &g->config_list, config_entry) { + sc = &tmp->state.ctl; + + if (pohmelfs_config_eql(sc, ctl)) { + err = 0; + break; + } + } + } + + mutex_unlock(&pohmelfs_config_lock); + + return err; +} + +int __init pohmelfs_config_init(void) +{ + return cn_add_callback(&pohmelfs_cn_id, "pohmelfs", pohmelfs_cn_callback); +} + +void pohmelfs_config_exit(void) +{ + struct pohmelfs_config *c, *tmp; + struct pohmelfs_config_group *g, *gtmp; + + cn_del_callback(&pohmelfs_cn_id); + + mutex_lock(&pohmelfs_config_lock); + list_for_each_entry_safe(g, gtmp, &pohmelfs_config_list, group_entry) { + list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) { + list_del(&c->config_entry); + kfree(c); + } + + list_del(&g->group_entry); + + if (g->hash_string) + kfree(g->hash_string); + + if (g->cipher_string) + kfree(g->cipher_string); + + kfree(g); + } + mutex_unlock(&pohmelfs_config_lock); +} diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c new file mode 100644 index 000000000000..31d765de92ce --- /dev/null +++ b/drivers/staging/pohmelfs/crypto.c @@ -0,0 +1,880 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include "netfs.h" + +static struct crypto_hash *pohmelfs_init_hash(struct pohmelfs_sb *psb) +{ + int err; + struct crypto_hash *hash; + + hash = crypto_alloc_hash(psb->hash_string, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(hash)) { + err = PTR_ERR(hash); + dprintk("%s: idx: %u: failed to allocate hash '%s', err: %d.\n", + __func__, psb->idx, psb->hash_string, err); + goto err_out_exit; + } + + psb->crypto_attached_size = crypto_hash_digestsize(hash); + + if (!psb->hash_keysize) + return hash; + + err = crypto_hash_setkey(hash, psb->hash_key, psb->hash_keysize); + if (err) { + dprintk("%s: idx: %u: failed to set key for hash '%s', err: %d.\n", + __func__, psb->idx, psb->hash_string, err); + goto err_out_free; + } + + return hash; + +err_out_free: + crypto_free_hash(hash); +err_out_exit: + return ERR_PTR(err); +} + +static struct crypto_ablkcipher *pohmelfs_init_cipher(struct pohmelfs_sb *psb) +{ + int err = -EINVAL; + struct crypto_ablkcipher *cipher; + + if (!psb->cipher_keysize) + goto err_out_exit; + + cipher = crypto_alloc_ablkcipher(psb->cipher_string, 0, 0); + if (IS_ERR(cipher)) { + err = PTR_ERR(cipher); + dprintk("%s: idx: %u: failed to allocate cipher '%s', err: %d.\n", + __func__, psb->idx, psb->cipher_string, err); + goto err_out_exit; + } + + crypto_ablkcipher_clear_flags(cipher, ~0); + + err = crypto_ablkcipher_setkey(cipher, psb->cipher_key, psb->cipher_keysize); + if (err) { + dprintk("%s: idx: %u: failed to set key for cipher '%s', err: %d.\n", + __func__, psb->idx, psb->cipher_string, err); + goto err_out_free; + } + + return cipher; + +err_out_free: + crypto_free_ablkcipher(cipher); +err_out_exit: + return ERR_PTR(err); +} + +int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb) +{ + int err; + + e->page_num = 0; + + e->size = PAGE_SIZE; + e->data = kmalloc(e->size, GFP_KERNEL); + if (!e->data) { + err = -ENOMEM; + goto err_out_exit; + } + + if (psb->hash_string) { + e->hash = pohmelfs_init_hash(psb); + if (IS_ERR(e->hash)) { + err = PTR_ERR(e->hash); + e->hash = NULL; + goto err_out_free; + } + } + + if (psb->cipher_string) { + e->cipher = pohmelfs_init_cipher(psb); + if (IS_ERR(e->cipher)) { + err = PTR_ERR(e->cipher); + e->cipher = NULL; + goto err_out_free_hash; + } + } + + return 0; + +err_out_free_hash: + crypto_free_hash(e->hash); +err_out_free: + kfree(e->data); +err_out_exit: + return err; +} + +void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e) +{ + if (e->hash) + crypto_free_hash(e->hash); + if (e->cipher) + crypto_free_ablkcipher(e->cipher); + kfree(e->data); +} + +static void pohmelfs_crypto_complete(struct crypto_async_request *req, int err) +{ + struct pohmelfs_crypto_completion *c = req->data; + + if (err == -EINPROGRESS) + return; + + dprintk("%s: req: %p, err: %d.\n", __func__, req, err); + c->error = err; + complete(&c->complete); +} + +static int pohmelfs_crypto_process(struct ablkcipher_request *req, + struct scatterlist *sg_dst, struct scatterlist *sg_src, + void *iv, int enc, unsigned long timeout) +{ + struct pohmelfs_crypto_completion complete; + int err; + + init_completion(&complete.complete); + complete.error = -EINPROGRESS; + + ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + pohmelfs_crypto_complete, &complete); + + ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv); + + if (enc) + err = crypto_ablkcipher_encrypt(req); + else + err = crypto_ablkcipher_decrypt(req); + + switch (err) { + case -EINPROGRESS: + case -EBUSY: + err = wait_for_completion_interruptible_timeout(&complete.complete, + timeout); + if (!err) + err = -ETIMEDOUT; + else + err = complete.error; + break; + default: + break; + } + + return err; +} + +int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 cmd_iv, + void *data, struct page *page, unsigned int size) +{ + int err; + struct scatterlist sg; + + if (!e->cipher && !e->hash) + return 0; + + dprintk("%s: eng: %p, iv: %llx, data: %p, page: %p/%lu, size: %u.\n", + __func__, e, cmd_iv, data, page, (page)?page->index:0, size); + + if (data) { + sg_init_one(&sg, data, size); + } else { + sg_init_table(&sg, 1); + sg_set_page(&sg, page, size, 0); + } + + if (e->cipher) { + struct ablkcipher_request *req = e->data + crypto_hash_digestsize(e->hash); + u8 iv[32]; + + memset(iv, 0, sizeof(iv)); + memcpy(iv, &cmd_iv, sizeof(cmd_iv)); + + ablkcipher_request_set_tfm(req, e->cipher); + + err = pohmelfs_crypto_process(req, &sg, &sg, iv, 0, e->timeout); + if (err) + goto err_out_exit; + } + + if (e->hash) { + struct hash_desc desc; + void *dst = e->data + e->size/2; + + desc.tfm = e->hash; + desc.flags = 0; + + err = crypto_hash_init(&desc); + if (err) + goto err_out_exit; + + err = crypto_hash_update(&desc, &sg, size); + if (err) + goto err_out_exit; + + err = crypto_hash_final(&desc, dst); + if (err) + goto err_out_exit; + + err = !!memcmp(dst, e->data, crypto_hash_digestsize(e->hash)); + + if (err) { +#ifdef CONFIG_POHMELFS_DEBUG + unsigned int i; + unsigned char *recv = e->data, *calc = dst; + + dprintk("%s: eng: %p, hash: %p, cipher: %p: iv : %llx, hash mismatch (recv/calc): ", + __func__, e, e->hash, e->cipher, cmd_iv); + for (i=0; ihash); ++i) { +#if 0 + dprintka("%02x ", recv[i]); + if (recv[i] != calc[i]) { + dprintka("| calc byte: %02x.\n", calc[i]); + break; + } +#else + dprintka("%02x/%02x ", recv[i], calc[i]); +#endif + } + dprintk("\n"); +#endif + goto err_out_exit; + } else { + dprintk("%s: eng: %p, hash: %p, cipher: %p: hashes matched.\n", + __func__, e, e->hash, e->cipher); + } + } + + dprintk("%s: eng: %p, size: %u, hash: %p, cipher: %p: completed.\n", + __func__, e, e->size, e->hash, e->cipher); + + return 0; + +err_out_exit: + dprintk("%s: eng: %p, hash: %p, cipher: %p: err: %d.\n", + __func__, e, e->hash, e->cipher, err); + return err; +} + +static int pohmelfs_trans_iter(struct netfs_trans *t, struct pohmelfs_crypto_engine *e, + int (* iterator) (struct pohmelfs_crypto_engine *e, + struct scatterlist *dst, + struct scatterlist *src)) +{ + void *data = t->iovec.iov_base + sizeof(struct netfs_cmd) + t->psb->crypto_attached_size; + unsigned int size = t->iovec.iov_len - sizeof(struct netfs_cmd) - t->psb->crypto_attached_size; + struct netfs_cmd *cmd = data; + unsigned int sz, pages = t->attached_pages, i, csize, cmd_cmd, dpage_idx; + struct scatterlist sg_src, sg_dst; + int err; + + while (size) { + cmd = data; + cmd_cmd = __be16_to_cpu(cmd->cmd); + csize = __be32_to_cpu(cmd->size); + cmd->iv = __cpu_to_be64(e->iv); + + if (cmd_cmd == NETFS_READ_PAGES || cmd_cmd == NETFS_READ_PAGE) + csize = __be16_to_cpu(cmd->ext); + + sz = csize + __be16_to_cpu(cmd->cpad) + sizeof(struct netfs_cmd); + + dprintk("%s: size: %u, sz: %u, cmd_size: %u, cmd_cpad: %u.\n", + __func__, size, sz, __be32_to_cpu(cmd->size), __be16_to_cpu(cmd->cpad)); + + data += sz; + size -= sz; + + sg_init_one(&sg_src, cmd->data, sz - sizeof(struct netfs_cmd)); + sg_init_one(&sg_dst, cmd->data, sz - sizeof(struct netfs_cmd)); + + err = iterator(e, &sg_dst, &sg_src); + if (err) + return err; + } + + if (!pages) + return 0; + + dpage_idx = 0; + for (i=0; ipage_num; ++i) { + struct page *page = t->pages[i]; + struct page *dpage = e->pages[dpage_idx]; + + if (!page) + continue; + + sg_init_table(&sg_src, 1); + sg_init_table(&sg_dst, 1); + sg_set_page(&sg_src, page, page_private(page), 0); + sg_set_page(&sg_dst, dpage, page_private(page), 0); + + err = iterator(e, &sg_dst, &sg_src); + if (err) + return err; + + pages--; + if (!pages) + break; + dpage_idx++; + } + + return 0; +} + +static int pohmelfs_encrypt_iterator(struct pohmelfs_crypto_engine *e, + struct scatterlist *sg_dst, struct scatterlist *sg_src) +{ + struct ablkcipher_request *req = e->data; + u8 iv[32]; + + memset(iv, 0, sizeof(iv)); + + memcpy(iv, &e->iv, sizeof(e->iv)); + + return pohmelfs_crypto_process(req, sg_dst, sg_src, iv, 1, e->timeout); +} + +static int pohmelfs_encrypt(struct pohmelfs_crypto_thread *tc) +{ + struct netfs_trans *t = tc->trans; + struct pohmelfs_crypto_engine *e = &tc->eng; + struct ablkcipher_request *req = e->data; + + memset(req, 0, sizeof(struct ablkcipher_request)); + ablkcipher_request_set_tfm(req, e->cipher); + + e->iv = pohmelfs_gen_iv(t); + + return pohmelfs_trans_iter(t, e, pohmelfs_encrypt_iterator); +} + +static int pohmelfs_hash_iterator(struct pohmelfs_crypto_engine *e, + struct scatterlist *sg_dst, struct scatterlist *sg_src) +{ + return crypto_hash_update(e->data, sg_src, sg_src->length); +} + +static int pohmelfs_hash(struct pohmelfs_crypto_thread *tc) +{ + struct pohmelfs_crypto_engine *e = &tc->eng; + struct hash_desc *desc = e->data; + unsigned char *dst = tc->trans->iovec.iov_base + sizeof(struct netfs_cmd); + int err; + + desc->tfm = e->hash; + desc->flags = 0; + + err = crypto_hash_init(desc); + if (err) + return err; + + err = pohmelfs_trans_iter(tc->trans, e, pohmelfs_hash_iterator); + if (err) + return err; + + err = crypto_hash_final(desc, dst); + if (err) + return err; + + { + unsigned int i; + dprintk("%s: ", __func__); + for (i=0; ipsb->crypto_attached_size; ++i) + dprintka("%02x ", dst[i]); + dprintka("\n"); + } + + return 0; +} + +static void pohmelfs_crypto_pages_free(struct pohmelfs_crypto_engine *e) +{ + unsigned int i; + + for (i=0; ipage_num; ++i) + __free_page(e->pages[i]); + kfree(e->pages); +} + +static int pohmelfs_crypto_pages_alloc(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb) +{ + unsigned int i; + + e->pages = kmalloc(psb->trans_max_pages * sizeof(struct page *), GFP_KERNEL); + if (!e->pages) + return -ENOMEM; + + for (i=0; itrans_max_pages; ++i) { + e->pages[i] = alloc_page(GFP_KERNEL); + if (!e->pages[i]) + break; + } + + e->page_num = i; + if (!e->page_num) + goto err_out_free; + + return 0; + +err_out_free: + kfree(e->pages); + return -ENOMEM; +} + +static void pohmelfs_sys_crypto_exit_one(struct pohmelfs_crypto_thread *t) +{ + struct pohmelfs_sb *psb = t->psb; + + if (t->thread) + kthread_stop(t->thread); + + mutex_lock(&psb->crypto_thread_lock); + list_del(&t->thread_entry); + psb->crypto_thread_num--; + mutex_unlock(&psb->crypto_thread_lock); + + pohmelfs_crypto_engine_exit(&t->eng); + pohmelfs_crypto_pages_free(&t->eng); + kfree(t); +} + +static int pohmelfs_crypto_finish(struct netfs_trans *t, struct pohmelfs_sb *psb, int err) +{ + struct netfs_cmd *cmd = t->iovec.iov_base; + netfs_convert_cmd(cmd); + + if (likely(!err)) + err = netfs_trans_finish_send(t, psb); + + t->result = err; + netfs_trans_put(t); + + return err; +} + +void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th) +{ + struct pohmelfs_sb *psb = th->psb; + + th->page = NULL; + th->trans = NULL; + + mutex_lock(&psb->crypto_thread_lock); + list_move_tail(&th->thread_entry, &psb->crypto_ready_list); + mutex_unlock(&psb->crypto_thread_lock); + wake_up(&psb->wait); +} + +static int pohmelfs_crypto_thread_trans(struct pohmelfs_crypto_thread *t) +{ + struct netfs_trans *trans; + int err = 0; + + trans = t->trans; + trans->eng = NULL; + + if (t->eng.hash) { + err = pohmelfs_hash(t); + if (err) + goto out_complete; + } + + if (t->eng.cipher) { + err = pohmelfs_encrypt(t); + if (err) + goto out_complete; + trans->eng = &t->eng; + } + +out_complete: + t->page = NULL; + t->trans = NULL; + + if (!trans->eng) + pohmelfs_crypto_thread_make_ready(t); + + pohmelfs_crypto_finish(trans, t->psb, err); + return err; +} + +static int pohmelfs_crypto_thread_page(struct pohmelfs_crypto_thread *t) +{ + struct pohmelfs_crypto_engine *e = &t->eng; + struct page *page = t->page; + int err; + + WARN_ON(!PageChecked(page)); + + err = pohmelfs_crypto_process_input_data(e, e->iv, NULL, page, t->size); + if (!err) + SetPageUptodate(page); + else + SetPageError(page); + unlock_page(page); + page_cache_release(page); + + pohmelfs_crypto_thread_make_ready(t); + + return err; +} + +static int pohmelfs_crypto_thread_func(void *data) +{ + struct pohmelfs_crypto_thread *t = data; + + while (!kthread_should_stop()) { + wait_event_interruptible(t->wait, kthread_should_stop() || + t->trans || t->page); + + if (kthread_should_stop()) + break; + + if (!t->trans && !t->page) + continue; + + dprintk("%s: thread: %p, trans: %p, page: %p.\n", + __func__, t, t->trans, t->page); + + if (t->trans) + pohmelfs_crypto_thread_trans(t); + else if (t->page) + pohmelfs_crypto_thread_page(t); + } + + return 0; +} + +static void pohmelfs_crypto_flush(struct pohmelfs_sb *psb, struct list_head *head) +{ + while (!list_empty(head)) { + struct pohmelfs_crypto_thread *t = NULL; + + mutex_lock(&psb->crypto_thread_lock); + if (!list_empty(head)) { + t = list_first_entry(head, struct pohmelfs_crypto_thread, thread_entry); + list_del_init(&t->thread_entry); + } + mutex_unlock(&psb->crypto_thread_lock); + + if (t) + pohmelfs_sys_crypto_exit_one(t); + } +} + +static void pohmelfs_sys_crypto_exit(struct pohmelfs_sb *psb) +{ + while (!list_empty(&psb->crypto_active_list) || !list_empty(&psb->crypto_ready_list)) { + dprintk("%s: crypto_thread_num: %u.\n", __func__, psb->crypto_thread_num); + pohmelfs_crypto_flush(psb, &psb->crypto_active_list); + pohmelfs_crypto_flush(psb, &psb->crypto_ready_list); + } +} + +static int pohmelfs_sys_crypto_init(struct pohmelfs_sb *psb) +{ + unsigned int i; + struct pohmelfs_crypto_thread *t; + struct pohmelfs_config *c; + struct netfs_state *st; + int err; + + list_for_each_entry(c, &psb->state_list, config_entry) { + st = &c->state; + + err = pohmelfs_crypto_engine_init(&st->eng, psb); + if (err) + goto err_out_exit; + + dprintk("%s: st: %p, eng: %p, hash: %p, cipher: %p.\n", + __func__, st, &st->eng, &st->eng.hash, &st->eng.cipher); + } + + for (i=0; icrypto_thread_num; ++i) { + err = -ENOMEM; + t = kzalloc(sizeof(struct pohmelfs_crypto_thread), GFP_KERNEL); + if (!t) + goto err_out_free_state_engines; + + init_waitqueue_head(&t->wait); + + t->psb = psb; + t->trans = NULL; + t->eng.thread = t; + + err = pohmelfs_crypto_engine_init(&t->eng, psb); + if (err) + goto err_out_free_state_engines; + + err = pohmelfs_crypto_pages_alloc(&t->eng, psb); + if (err) + goto err_out_free; + + t->thread = kthread_run(pohmelfs_crypto_thread_func, t, + "pohmelfs-crypto-%d-%d", psb->idx, i); + if (IS_ERR(t->thread)) { + err = PTR_ERR(t->thread); + t->thread = NULL; + goto err_out_free; + } + + if (t->eng.cipher) + psb->crypto_align_size = crypto_ablkcipher_blocksize(t->eng.cipher); + + mutex_lock(&psb->crypto_thread_lock); + list_add_tail(&t->thread_entry, &psb->crypto_ready_list); + mutex_unlock(&psb->crypto_thread_lock); + } + + psb->crypto_thread_num = i; + return 0; + +err_out_free: + pohmelfs_sys_crypto_exit_one(t); +err_out_free_state_engines: + list_for_each_entry(c, &psb->state_list, config_entry) { + st = &c->state; + pohmelfs_crypto_engine_exit(&st->eng); + } +err_out_exit: + pohmelfs_sys_crypto_exit(psb); + return err; +} + +void pohmelfs_crypto_exit(struct pohmelfs_sb *psb) +{ + pohmelfs_sys_crypto_exit(psb); + + kfree(psb->hash_string); + kfree(psb->cipher_string); +} + +static int pohmelfs_crypt_init_complete(struct page **pages, unsigned int page_num, + void *private, int err) +{ + struct pohmelfs_sb *psb = private; + + psb->flags = -err; + dprintk("%s: err: %d.\n", __func__, err); + + wake_up(&psb->wait); + + return err; +} + +static int pohmelfs_crypto_init_handshake(struct pohmelfs_sb *psb) +{ + struct netfs_trans *t; + struct netfs_crypto_capabilities *cap; + struct netfs_cmd *cmd; + char *str; + int err = -ENOMEM, size; + + size = sizeof(struct netfs_crypto_capabilities) + + psb->cipher_strlen + psb->hash_strlen + 2; /* 0 bytes */ + + t = netfs_trans_alloc(psb, size, 0, 0); + if (!t) + goto err_out_exit; + + t->complete = pohmelfs_crypt_init_complete; + t->private = psb; + + cmd = netfs_trans_current(t); + cap = (struct netfs_crypto_capabilities *)(cmd + 1); + str = (char *)(cap + 1); + + cmd->cmd = NETFS_CAPABILITIES; + cmd->id = POHMELFS_CRYPTO_CAPABILITIES; + cmd->size = size; + cmd->start = 0; + cmd->ext = 0; + cmd->csize = 0; + + netfs_convert_cmd(cmd); + netfs_trans_update(cmd, t, size); + + cap->hash_strlen = psb->hash_strlen; + if (cap->hash_strlen) { + sprintf(str, "%s", psb->hash_string); + str += cap->hash_strlen; + } + + cap->cipher_strlen = psb->cipher_strlen; + cap->cipher_keysize = psb->cipher_keysize; + if (cap->cipher_strlen) + sprintf(str, "%s", psb->cipher_string); + + netfs_convert_crypto_capabilities(cap); + + psb->flags = ~0; + err = netfs_trans_finish(t, psb); + if (err) + goto err_out_exit; + + err = wait_event_interruptible_timeout(psb->wait, (psb->flags != ~0), + psb->wait_on_page_timeout); + if (!err) + err = -ETIMEDOUT; + else + err = -psb->flags; + + if (!err) + psb->perform_crypto = 1; + psb->flags = 0; + + /* + * At this point NETFS_CAPABILITIES response command + * should setup superblock in a way, which is acceptible + * for both client and server, so if server refuses connection, + * it will send error in transaction response. + */ + + if (err) + goto err_out_exit; + + return 0; + +err_out_exit: + return err; +} + +int pohmelfs_crypto_init(struct pohmelfs_sb *psb) +{ + int err; + + if (!psb->cipher_string && !psb->hash_string) + return 0; + + err = pohmelfs_crypto_init_handshake(psb); + if (err) + return err; + + err = pohmelfs_sys_crypto_init(psb); + if (err) + return err; + + return 0; +} + +static int pohmelfs_crypto_thread_get(struct pohmelfs_sb *psb, + int (* action)(struct pohmelfs_crypto_thread *t, void *data), void *data) +{ + struct pohmelfs_crypto_thread *t = NULL; + int err; + + while (!t) { + err = wait_event_interruptible_timeout(psb->wait, + !list_empty(&psb->crypto_ready_list), + psb->wait_on_page_timeout); + + t = NULL; + err = 0; + mutex_lock(&psb->crypto_thread_lock); + if (!list_empty(&psb->crypto_ready_list)) { + t = list_entry(psb->crypto_ready_list.prev, + struct pohmelfs_crypto_thread, + thread_entry); + + list_move_tail(&t->thread_entry, + &psb->crypto_active_list); + + action(t, data); + wake_up(&t->wait); + + } + mutex_unlock(&psb->crypto_thread_lock); + } + + return err; +} + +static int pohmelfs_trans_crypt_action(struct pohmelfs_crypto_thread *t, void *data) +{ + struct netfs_trans *trans = data; + + netfs_trans_get(trans); + t->trans = trans; + + dprintk("%s: t: %p, gen: %u, thread: %p.\n", __func__, trans, trans->gen, t); + return 0; +} + +int pohmelfs_trans_crypt(struct netfs_trans *trans, struct pohmelfs_sb *psb) +{ + if ((!psb->hash_string && !psb->cipher_string) || !psb->perform_crypto) { + netfs_trans_get(trans); + return pohmelfs_crypto_finish(trans, psb, 0); + } + + return pohmelfs_crypto_thread_get(psb, pohmelfs_trans_crypt_action, trans); +} + +struct pohmelfs_crypto_input_action_data +{ + struct page *page; + struct pohmelfs_crypto_engine *e; + u64 iv; + unsigned int size; +}; + +static int pohmelfs_crypt_input_page_action(struct pohmelfs_crypto_thread *t, void *data) +{ + struct pohmelfs_crypto_input_action_data *act = data; + + memcpy(t->eng.data, act->e->data, t->psb->crypto_attached_size); + + t->size = act->size; + t->eng.iv = act->iv; + + t->page = act->page; + return 0; +} + +int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e, + struct page *page, unsigned int size, u64 iv) +{ + struct inode *inode = page->mapping->host; + struct pohmelfs_crypto_input_action_data act; + int err = -ENOENT; + + act.page = page; + act.e = e; + act.size = size; + act.iv = iv; + + err = pohmelfs_crypto_thread_get(POHMELFS_SB(inode->i_sb), + pohmelfs_crypt_input_page_action, &act); + if (err) + goto err_out_exit; + + return 0; + +err_out_exit: + SetPageUptodate(page); + page_cache_release(page); + + return err; +} diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c new file mode 100644 index 000000000000..7a41183a32e1 --- /dev/null +++ b/drivers/staging/pohmelfs/dir.c @@ -0,0 +1,1093 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include "netfs.h" + +static int pohmelfs_cmp_hash(struct pohmelfs_name *n, u32 hash) +{ + if (n->hash > hash) + return -1; + if (n->hash < hash) + return 1; + + return 0; +} + +static struct pohmelfs_name *pohmelfs_search_hash_unprecise(struct pohmelfs_inode *pi, u32 hash) +{ + struct rb_node *n = pi->hash_root.rb_node; + struct pohmelfs_name *tmp = NULL; + int cmp; + + while (n) { + tmp = rb_entry(n, struct pohmelfs_name, hash_node); + + cmp = pohmelfs_cmp_hash(tmp, hash); + if (cmp < 0) + n = n->rb_left; + else if (cmp > 0) + n = n->rb_right; + else + break; + + } + + return tmp; +} + +struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash) +{ + struct pohmelfs_name *tmp; + + tmp = pohmelfs_search_hash_unprecise(pi, hash); + if (tmp && (tmp->hash == hash)) + return tmp; + + return NULL; +} + +static void __pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node) +{ + rb_erase(&node->hash_node, &parent->hash_root); +} + +/* + * Remove name cache entry from its caches and free it. + */ +static void pohmelfs_name_free(struct pohmelfs_inode *parent, struct pohmelfs_name *node) +{ + __pohmelfs_name_del(parent, node); + list_del(&node->sync_create_entry); + kfree(node); +} + +static struct pohmelfs_name *pohmelfs_insert_hash(struct pohmelfs_inode *pi, + struct pohmelfs_name *new) +{ + struct rb_node **n = &pi->hash_root.rb_node, *parent = NULL; + struct pohmelfs_name *ret = NULL, *tmp; + int cmp; + + while (*n) { + parent = *n; + + tmp = rb_entry(parent, struct pohmelfs_name, hash_node); + + cmp = pohmelfs_cmp_hash(tmp, new->hash); + if (cmp < 0) + n = &parent->rb_left; + else if (cmp > 0) + n = &parent->rb_right; + else { + ret = tmp; + break; + } + } + + if (ret) { + printk("%s: exist: parent: %llu, ino: %llu, hash: %x, len: %u, data: '%s', " + "new: ino: %llu, hash: %x, len: %u, data: '%s'.\n", + __func__, pi->ino, + ret->ino, ret->hash, ret->len, ret->data, + new->ino, new->hash, new->len, new->data); + ret->ino = new->ino; + return ret; + } + + rb_link_node(&new->hash_node, parent, n); + rb_insert_color(&new->hash_node, &pi->hash_root); + + return NULL; +} + +/* + * Free name cache for given inode. + */ +void pohmelfs_free_names(struct pohmelfs_inode *parent) +{ + struct rb_node *rb_node; + struct pohmelfs_name *n; + + for (rb_node = rb_first(&parent->hash_root); rb_node;) { + n = rb_entry(rb_node, struct pohmelfs_name, hash_node); + rb_node = rb_next(rb_node); + + pohmelfs_name_free(parent, n); + } +} + +static void pohmelfs_fix_offset(struct pohmelfs_inode *parent, struct pohmelfs_name *node) +{ + parent->total_len -= node->len; +} + +/* + * Free name cache entry helper. + */ +void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node) +{ + pohmelfs_fix_offset(parent, node); + pohmelfs_name_free(parent, node); +} + +/* + * Insert new name cache entry into all hash cache. + */ +static int pohmelfs_insert_name(struct pohmelfs_inode *parent, struct pohmelfs_name *n) +{ + struct pohmelfs_name *name; + + name = pohmelfs_insert_hash(parent, n); + if (name) + return -EEXIST; + + parent->total_len += n->len; + list_add_tail(&n->sync_create_entry, &parent->sync_create_list); + + return 0; +} + +/* + * Allocate new name cache entry. + */ +static struct pohmelfs_name *pohmelfs_name_alloc(unsigned int len) +{ + struct pohmelfs_name *n; + + n = kzalloc(sizeof(struct pohmelfs_name) + len, GFP_KERNEL); + if (!n) + return NULL; + + INIT_LIST_HEAD(&n->sync_create_entry); + + n->data = (char *)(n+1); + + return n; +} + +/* + * Add new name entry into directory's cache. + */ +static int pohmelfs_add_dir(struct pohmelfs_sb *psb, struct pohmelfs_inode *parent, + struct pohmelfs_inode *npi, struct qstr *str, unsigned int mode, int link) +{ + int err = -ENOMEM; + struct pohmelfs_name *n; + + n = pohmelfs_name_alloc(str->len + 1); + if (!n) + goto err_out_exit; + + n->ino = npi->ino; + n->mode = mode; + n->len = str->len; + n->hash = str->hash; + sprintf(n->data, "%s", str->name); + + mutex_lock(&parent->offset_lock); + err = pohmelfs_insert_name(parent, n); + mutex_unlock(&parent->offset_lock); + + if (err) { + if (err != -EEXIST) + goto err_out_free; + kfree(n); + } + + return 0; + +err_out_free: + kfree(n); +err_out_exit: + return err; +} + +/* + * Create new inode for given parameters (name, inode info, parent). + * This does not create object on the server, it will be synced there during writeback. + */ +struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb, + struct pohmelfs_inode *parent, struct qstr *str, + struct netfs_inode_info *info, int link) +{ + struct inode *new = NULL; + struct pohmelfs_inode *npi; + int err = -EEXIST; + + dprintk("%s: creating inode: parent: %llu, ino: %llu, str: %p.\n", + __func__, (parent)?parent->ino:0, info->ino, str); + + err = -ENOMEM; + new = iget_locked(psb->sb, info->ino); + if (!new) + goto err_out_exit; + + npi = POHMELFS_I(new); + npi->ino = info->ino; + err = 0; + + if (new->i_state & I_NEW) { + dprintk("%s: filling VFS inode: %lu/%llu.\n", + __func__, new->i_ino, info->ino); + pohmelfs_fill_inode(new, info); + + if (S_ISDIR(info->mode)) { + struct qstr s; + + s.name = "."; + s.len = 1; + s.hash = jhash(s.name, s.len, 0); + + err = pohmelfs_add_dir(psb, npi, npi, &s, info->mode, 0); + if (err) + goto err_out_put; + + s.name = ".."; + s.len = 2; + s.hash = jhash(s.name, s.len, 0); + + err = pohmelfs_add_dir(psb, npi, (parent)?parent:npi, &s, + (parent)?parent->vfs_inode.i_mode:npi->vfs_inode.i_mode, 0); + if (err) + goto err_out_put; + } + } + + if (str) { + if (parent) { + err = pohmelfs_add_dir(psb, parent, npi, str, info->mode, link); + + dprintk("%s: %s inserted name: '%s', new_offset: %llu, ino: %llu, parent: %llu.\n", + __func__, (err)?"unsuccessfully":"successfully", + str->name, parent->total_len, info->ino, parent->ino); + + if (err && err != -EEXIST) + goto err_out_put; + } + } + + if (new->i_state & I_NEW) { + if (parent) + mark_inode_dirty(&parent->vfs_inode); + mark_inode_dirty(new); + } + + set_bit(NETFS_INODE_OWNED, &npi->state); + npi->lock_type = POHMELFS_WRITE_LOCK; + unlock_new_inode(new); + + return npi; + +err_out_put: + printk("%s: putting inode: %p, npi: %p, error: %d.\n", __func__, new, npi, err); + iput(new); +err_out_exit: + return ERR_PTR(err); +} + +static int pohmelfs_remote_sync_complete(struct page **pages, unsigned int page_num, + void *private, int err) +{ + struct pohmelfs_inode *pi = private; + struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); + + dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err); + + if (err) + pi->error = err; + wake_up(&psb->wait); + pohmelfs_put_inode(pi); + + return err; +} + +/* + * Receive directory content from the server. + * This should be only done for objects, which were not created locally, + * and which were not synced previously. + */ +static int pohmelfs_sync_remote_dir(struct pohmelfs_inode *pi) +{ + struct inode *inode = &pi->vfs_inode; + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + long ret = msecs_to_jiffies(25000); + int err; + + dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n", + __func__, pi->ino, pi->state, test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state)); + + if (test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state)) + return 0; + + if (!igrab(inode)) { + err = -ENOENT; + goto err_out_exit; + } + + err = pohmelfs_meta_command(pi, NETFS_READDIR, NETFS_TRANS_SINGLE_DST, + pohmelfs_remote_sync_complete, pi, 0); + if (err) + goto err_out_exit; + + pi->error = 0; + ret = wait_event_interruptible_timeout(psb->wait, + test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state) || pi->error, ret); + dprintk("%s: awake dir: %llu, ret: %ld, err: %d.\n", __func__, pi->ino, ret, pi->error); + if (ret <= 0) { + err = -ETIMEDOUT; + goto err_out_exit; + } + + if (pi->error) + return pi->error; + + return 0; + +err_out_exit: + clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); + + return err; +} + +static int pohmelfs_dir_open(struct inode *inode, struct file *file) +{ + file->private_data = NULL; + return 0; +} + +/* + * VFS readdir callback. Syncs directory content from server if needed, + * and provides direntry info to the userspace. + */ +static int pohmelfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *inode = file->f_path.dentry->d_inode; + struct pohmelfs_inode *pi = POHMELFS_I(inode); + struct pohmelfs_name *n; + struct rb_node *rb_node; + int err = 0, mode; + u64 len; + + dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n", + __func__, pi->ino, (u64)file->f_pos, + (unsigned long)file->private_data); + + err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK); + if (err) + return err; + + err = pohmelfs_sync_remote_dir(pi); + if (err) + return err; + + if (file->private_data && (file->private_data == (void *)(unsigned long)file->f_pos)) + return 0; + + mutex_lock(&pi->offset_lock); + n = pohmelfs_search_hash_unprecise(pi, (unsigned long)file->private_data); + + while (n) { + mode = (n->mode >> 12) & 15; + + dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, " + "mode: %o/%o, fpos: %llu, hash: %08x.\n", + __func__, file->f_pos, pi->ino, n->data, n->len, + n->ino, n->mode, mode, file->f_pos, n->hash); + + file->private_data = (void *)n->hash; + + len = n->len; + err = filldir(dirent, n->data, n->len, file->f_pos, n->ino, mode); + + if (err < 0) { + dprintk("%s: err: %d.\n", __func__, err); + err = 0; + break; + } + + file->f_pos += len; + + rb_node = rb_next(&n->hash_node); + + if (!rb_node || (rb_node == &n->hash_node)) { + file->private_data = (void *)(unsigned long)file->f_pos; + break; + } + + n = rb_entry(rb_node, struct pohmelfs_name, hash_node); + } + mutex_unlock(&pi->offset_lock); + + return err; +} + +static loff_t pohmelfs_dir_lseek(struct file *file, loff_t offset, int origin) +{ + file->f_pos = offset; + file->private_data = NULL; + return offset; +} + +const struct file_operations pohmelfs_dir_fops = { + .open = pohmelfs_dir_open, + .read = generic_read_dir, + .llseek = pohmelfs_dir_lseek, + .readdir = pohmelfs_readdir, +}; + +/* + * Lookup single object on server. + */ +static int pohmelfs_lookup_single(struct pohmelfs_inode *parent, + struct qstr *str, u64 ino) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(parent->vfs_inode.i_sb); + long ret = msecs_to_jiffies(5000); + int err; + + set_bit(NETFS_COMMAND_PENDING, &parent->state); + err = pohmelfs_meta_command_data(parent, parent->ino, NETFS_LOOKUP, + (char *)str->name, NETFS_TRANS_SINGLE_DST, NULL, NULL, ino); + if (err) + goto err_out_exit; + + err = 0; + ret = wait_event_interruptible_timeout(psb->wait, + !test_bit(NETFS_COMMAND_PENDING, &parent->state), ret); + if (ret == 0) + err = -ETIMEDOUT; + else if (signal_pending(current)) + err = -EINTR; + + if (err) + goto err_out_exit; + + return 0; + +err_out_exit: + clear_bit(NETFS_COMMAND_PENDING, &parent->state); + + printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n", + __func__, parent->ino, ino, str->name, err); + + return err; +} + +/* + * VFS lookup callback. + * We first try to get inode number from local name cache, if we have one, + * then inode can be found in inode cache. If there is no inode or no object in + * local cache, try to lookup it on server. This only should be done for directories, + * which were not created locally, otherwise remote server does not know about dir at all, + * so no need to try to know that. + */ +struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) +{ + struct pohmelfs_inode *parent = POHMELFS_I(dir); + struct pohmelfs_name *n; + struct inode *inode = NULL; + unsigned long ino = 0; + int err, lock_type = POHMELFS_READ_LOCK, need_lock; + struct qstr str = dentry->d_name; + + if ((nd->intent.open.flags & O_ACCMODE) > 1) + lock_type = POHMELFS_WRITE_LOCK; + + need_lock = pohmelfs_need_lock(parent, lock_type); + + err = pohmelfs_data_lock(parent, 0, ~0, lock_type); + if (err) + goto out; + + str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); + + mutex_lock(&parent->offset_lock); + n = pohmelfs_search_hash(parent, str.hash); + if (n) + ino = n->ino; + mutex_unlock(&parent->offset_lock); + + dprintk("%s: 1 ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx.\n", + __func__, ino, inode, str.name, str.hash, parent->state); + + if (ino) { + inode = ilookup(dir->i_sb, ino); + if (inode) + goto out; + } + + dprintk("%s: dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n", + __func__, dir, parent->ino, + str.name, str.len, parent->state, ino); + + if (!ino) { + if (!need_lock) + goto out; + } + + err = pohmelfs_lookup_single(parent, &str, ino); + if (err) + goto out; + + if (!ino) { + mutex_lock(&parent->offset_lock); + n = pohmelfs_search_hash(parent, str.hash); + if (n) + ino = n->ino; + mutex_unlock(&parent->offset_lock); + } + + if (ino) { + inode = ilookup(dir->i_sb, ino); + printk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n", + __func__, ino, inode, str.name, str.hash); + if (!inode) { + printk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n", + __func__, ino, str.name, str.hash); + //return NULL; + return ERR_PTR(-EACCES); + } + } else { + printk("%s: No inode number : name: '%s', hash: %x.\n", + __func__, str.name, str.hash); + } +out: + return d_splice_alias(inode, dentry); +} + +/* + * Create new object in local cache. Object will be synced to server + * during writeback for given inode. + */ +struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb, + struct pohmelfs_inode *parent, struct qstr *str, u64 start, int mode) +{ + struct pohmelfs_inode *npi; + int err = -ENOMEM; + struct netfs_inode_info info; + + dprintk("%s: name: '%s', mode: %o, start: %llu.\n", + __func__, str->name, mode, start); + + info.mode = mode; + info.ino = start; + + if (!start) + info.ino = pohmelfs_new_ino(psb); + + info.nlink = S_ISDIR(mode)?2:1; + info.uid = current_fsuid(); + info.gid = current_fsgid(); + info.size = 0; + info.blocksize = 512; + info.blocks = 0; + info.rdev = 0; + info.version = 0; + + npi = pohmelfs_new_inode(psb, parent, str, &info, !!start); + if (IS_ERR(npi)) { + err = PTR_ERR(npi); + goto err_out_unlock; + } + + return npi; + +err_out_unlock: + dprintk("%s: err: %d.\n", __func__, err); + return ERR_PTR(err); +} + +/* + * Create local object and bind it to dentry. + */ +static int pohmelfs_create_entry(struct inode *dir, struct dentry *dentry, u64 start, int mode) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb); + struct pohmelfs_inode *npi, *parent; + struct qstr str = dentry->d_name; + int err; + + parent = POHMELFS_I(dir); + + err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK); + if (err) + return err; + + str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); + + npi = pohmelfs_create_entry_local(psb, parent, &str, start, mode); + if (IS_ERR(npi)) + return PTR_ERR(npi); + + d_instantiate(dentry, &npi->vfs_inode); + + dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n", + __func__, parent->ino, npi->ino, dentry->d_name.name, + (signed)dir->i_nlink, (signed)npi->vfs_inode.i_nlink); + + return 0; +} + +/* + * VFS create and mkdir callbacks. + */ +static int pohmelfs_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + return pohmelfs_create_entry(dir, dentry, 0, mode); +} + +static int pohmelfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + int err; + + inode_inc_link_count(dir); + err = pohmelfs_create_entry(dir, dentry, 0, mode | S_IFDIR); + if (err) + inode_dec_link_count(dir); + + return err; +} + +static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb); + struct inode *inode = dentry->d_inode; + struct pohmelfs_inode *parent = POHMELFS_I(dir), *pi = POHMELFS_I(inode); + struct pohmelfs_name *n; + int err = -ENOENT; + struct qstr str = dentry->d_name; + + err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK); + if (err) + return err; + + str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); + + dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n", + __func__, parent->ino, pi->ino, + str.name, (signed)inode->i_nlink); + + BUG_ON(!inode); + + mutex_lock(&parent->offset_lock); + n = pohmelfs_search_hash(parent, str.hash); + if (n) { + pohmelfs_fix_offset(parent, n); + if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state)) { + pohmelfs_remove_child(pi, n); + } + pohmelfs_name_free(parent, n); + err = 0; + } + mutex_unlock(&parent->offset_lock); + + if (!err) { + psb->avail_size += inode->i_size; + + pohmelfs_inode_del_inode(psb, pi); + + mark_inode_dirty(dir); + + inode->i_ctime = dir->i_ctime; + if (inode->i_nlink) + inode_dec_link_count(inode); + } + dprintk("%s: inode: %p, lock: %ld, unhashed: %d.\n", + __func__, pi, inode->i_state & I_LOCK, hlist_unhashed(&inode->i_hash)); + + return err; +} + +/* + * Unlink and rmdir VFS callbacks. + */ +static int pohmelfs_unlink(struct inode *dir, struct dentry *dentry) +{ + return pohmelfs_remove_entry(dir, dentry); +} + +static int pohmelfs_rmdir(struct inode *dir, struct dentry *dentry) +{ + int err; + struct inode *inode = dentry->d_inode; + + dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n", + __func__, POHMELFS_I(dir)->ino, POHMELFS_I(inode)->ino, + dentry->d_name.name, (signed)dir->i_nlink, (signed)inode->i_nlink); + + err = pohmelfs_remove_entry(dir, dentry); + if (!err) { + inode_dec_link_count(dir); + inode_dec_link_count(inode); + } + + return err; +} + +/* + * Link creation is synchronous. + * I'm lazy. + * Earth is somewhat round. + */ +static int pohmelfs_create_link(struct pohmelfs_inode *parent, struct qstr *obj, + struct pohmelfs_inode *target, struct qstr *tstr) +{ + struct super_block *sb = parent->vfs_inode.i_sb; + struct pohmelfs_sb *psb = POHMELFS_SB(sb); + struct netfs_cmd *cmd; + struct netfs_trans *t; + void *data; + int err, parent_len, target_len = 0, cur_len, path_size = 0; + + err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK); + if (err) + return err; + + err = sb->s_op->write_inode(&parent->vfs_inode, 0); + if (err) + goto err_out_exit; + + if (tstr) + target_len = tstr->len; + + parent_len = pohmelfs_path_length(parent); + if (target) + target_len += pohmelfs_path_length(target); + + if (parent_len < 0) { + err = parent_len; + goto err_out_exit; + } + + if (target_len < 0) { + err = target_len; + goto err_out_exit; + } + + t = netfs_trans_alloc(psb, parent_len + target_len + obj->len + 2, 0, 0); + if (!t) { + err = -ENOMEM; + goto err_out_exit; + } + cur_len = netfs_trans_cur_len(t); + + cmd = netfs_trans_current(t); + if (IS_ERR(cmd)) { + err = PTR_ERR(cmd); + goto err_out_free; + } + + data = (void *)(cmd + 1); + cur_len -= sizeof(struct netfs_cmd); + + err = pohmelfs_construct_path_string(parent, data, parent_len); + if (err > 0) { + /* Do not place null-byte before the slash */ + path_size = err - 1; + cur_len -= path_size; + + err = snprintf(data + path_size, cur_len, "/%s|", obj->name); + + path_size += err; + cur_len -= err; + + cmd->ext = path_size - 1; /* No | symbol */ + + if (target) { + err = pohmelfs_construct_path_string(target, data + path_size, target_len); + if (err > 0) { + path_size += err; + cur_len -= err; + } + } + } + + if (err < 0) + goto err_out_free; + + cmd->start = 0; + + if (!target && tstr) { + if (tstr->len > cur_len - 1) { + err = -ENAMETOOLONG; + goto err_out_free; + } + + err = snprintf(data + path_size, cur_len, "%s", tstr->name) + 1; /* 0-byte */ + path_size += err; + cur_len -= err; + cmd->start = 1; + } + + dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n", + __func__, parent->ino, obj->name, (target)?target->ino:0, (tstr)?tstr->name:NULL, + (char *)data); + + cmd->cmd = NETFS_LINK; + cmd->size = path_size; + cmd->id = parent->ino; + + netfs_convert_cmd(cmd); + + netfs_trans_update(cmd, t, path_size); + + err = netfs_trans_finish(t, psb); + if (err) + goto err_out_exit; + + return 0; + +err_out_free: + t->result = err; + netfs_trans_put(t); +err_out_exit: + return err; +} + +/* + * VFS hard and soft link callbacks. + */ +static int pohmelfs_link(struct dentry *old_dentry, struct inode *dir, + struct dentry *dentry) +{ + struct inode *inode = old_dentry->d_inode; + struct pohmelfs_inode *pi = POHMELFS_I(inode); + int err; + struct qstr str = dentry->d_name; + + str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); + + err = inode->i_sb->s_op->write_inode(inode, 0); + if (err) + return err; + + err = pohmelfs_create_link(POHMELFS_I(dir), &str, pi, NULL); + if (err) + return err; + + return pohmelfs_create_entry(dir, dentry, pi->ino, inode->i_mode); +} + +static int pohmelfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) +{ + struct qstr sym_str; + struct qstr str = dentry->d_name; + struct inode *inode; + int err; + + str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); + + sym_str.name = symname; + sym_str.len = strlen(symname); + + err = pohmelfs_create_link(POHMELFS_I(dir), &str, NULL, &sym_str); + if (err) + goto err_out_exit; + + err = pohmelfs_create_entry(dir, dentry, 0, S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO); + if (err) + goto err_out_exit; + + inode = dentry->d_inode; + + err = page_symlink(inode, symname, sym_str.len + 1); + if (err) + goto err_out_put; + + return 0; + +err_out_put: + iput(inode); +err_out_exit: + return err; +} + +static int pohmelfs_send_rename(struct pohmelfs_inode *pi, struct pohmelfs_inode *parent, + struct qstr *str) +{ + int path_len, err, total_len = 0, inode_len, parent_len; + char *path; + struct netfs_trans *t; + struct netfs_cmd *cmd; + struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); + + parent_len = pohmelfs_path_length(parent); + inode_len = pohmelfs_path_length(pi); + + if (parent_len < 0 || inode_len < 0) + return -EINVAL; + + path_len = parent_len + inode_len + str->len + 3; + + t = netfs_trans_alloc(psb, path_len, 0, 0); + if (!t) + return -ENOMEM; + + cmd = netfs_trans_current(t); + path = (char *)(cmd + 1); + + err = pohmelfs_construct_path_string(pi, path, inode_len); + if (err < 0) + goto err_out_unlock; + + cmd->ext = err; + + path += err; + total_len += err; + path_len -= err; + + *path = '|'; + path++; + total_len++; + path_len--; + + err = pohmelfs_construct_path_string(parent, path, parent_len); + if (err < 0) + goto err_out_unlock; + + /* + * Do not place a null-byte before the final slash and the name. + */ + err--; + path += err; + total_len += err; + path_len -= err; + + err = snprintf(path, path_len - 1, "/%s", str->name); + + total_len += err + 1; /* 0 symbol */ + path_len -= err + 1; + + cmd->cmd = NETFS_RENAME; + cmd->id = pi->ino; + cmd->start = parent->ino; + cmd->size = total_len; + + netfs_convert_cmd(cmd); + + netfs_trans_update(cmd, t, total_len); + + return netfs_trans_finish(t, psb); + +err_out_unlock: + netfs_trans_free(t); + return err; +} + +static int pohmelfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + struct inode *inode = old_dentry->d_inode; + struct pohmelfs_inode *old_parent, *pi, *new_parent; + struct qstr str = new_dentry->d_name; + struct pohmelfs_name *n; + unsigned int old_hash; + int err = -ENOENT; + + pi = POHMELFS_I(inode); + old_parent = POHMELFS_I(old_dir); + + if (new_dir) { + new_dir->i_sb->s_op->write_inode(new_dir, 0); + } + + old_hash = jhash(old_dentry->d_name.name, old_dentry->d_name.len, 0); + str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0); + + str.len = new_dentry->d_name.len; + str.name = new_dentry->d_name.name; + str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0); + + if (new_dir) { + new_parent = POHMELFS_I(new_dir); + err = -ENOTEMPTY; + + if (S_ISDIR(inode->i_mode) && + new_parent->total_len <= 3) + goto err_out_exit; + } else { + new_parent = old_parent; + } + + dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n", + __func__, pi->ino, old_parent->ino, old_dentry->d_name.name, + new_parent->ino, new_dentry->d_name.name, inode->i_size); + + if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state) && + test_bit(NETFS_INODE_OWNED, &pi->state)) { + err = pohmelfs_send_rename(pi, new_parent, &str); + if (err) + goto err_out_exit; + } + + n = pohmelfs_name_alloc(str.len + 1); + if (!n) + goto err_out_exit; + + mutex_lock(&new_parent->offset_lock); + n->ino = pi->ino; + n->mode = inode->i_mode; + n->len = str.len; + n->hash = str.hash; + sprintf(n->data, "%s", str.name); + + err = pohmelfs_insert_name(new_parent, n); + mutex_unlock(&new_parent->offset_lock); + + if (err) + goto err_out_exit; + + mutex_lock(&old_parent->offset_lock); + n = pohmelfs_search_hash(old_parent, old_hash); + if (n) + pohmelfs_name_del(old_parent, n); + mutex_unlock(&old_parent->offset_lock); + + mark_inode_dirty(inode); + mark_inode_dirty(&new_parent->vfs_inode); + + WARN_ON_ONCE(list_empty(&inode->i_dentry)); + + return 0; + +err_out_exit: + + clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); + + mutex_unlock(&inode->i_mutex); + return err; +} + +/* + * POHMELFS directory inode operations. + */ +const struct inode_operations pohmelfs_dir_inode_ops = { + .link = pohmelfs_link, + .symlink = pohmelfs_symlink, + .unlink = pohmelfs_unlink, + .mkdir = pohmelfs_mkdir, + .rmdir = pohmelfs_rmdir, + .create = pohmelfs_create, + .lookup = pohmelfs_lookup, + .setattr = pohmelfs_setattr, + .rename = pohmelfs_rename, +}; diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c new file mode 100644 index 000000000000..5bf16504cd6f --- /dev/null +++ b/drivers/staging/pohmelfs/inode.c @@ -0,0 +1,1976 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netfs.h" + +#define POHMELFS_MAGIC_NUM 0x504f482e + +static struct kmem_cache *pohmelfs_inode_cache; + +/* + * Removes inode from all trees, drops local name cache and removes all queued + * requests for object removal. + */ +void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi) +{ + mutex_lock(&pi->offset_lock); + pohmelfs_free_names(pi); + mutex_unlock(&pi->offset_lock); + + dprintk("%s: deleted stuff in ino: %llu.\n", __func__, pi->ino); +} + +/* + * Sync inode to server. + * Returns zero in success and negative error value otherwise. + * It will gather path to root directory into structures containing + * creation mode, permissions and names, so that the whole path + * to given inode could be created using only single network command. + */ +int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans) +{ + struct pohmelfs_inode *pi = POHMELFS_I(inode); + int err = -ENOMEM, size; + struct netfs_cmd *cmd; + void *data; + int cur_len = netfs_trans_cur_len(trans); + + if (unlikely(cur_len < 0)) + return -ETOOSMALL; + + cmd = netfs_trans_current(trans); + cur_len -= sizeof(struct netfs_cmd); + + data = (void *)(cmd + 1); + + err = pohmelfs_construct_path_string(pi, data, cur_len); + if (err < 0) + goto err_out_exit; + + size = err; + + cmd->start = i_size_read(inode); + cmd->cmd = NETFS_CREATE; + cmd->size = size; + cmd->id = pi->ino; + cmd->ext = inode->i_mode; + + netfs_convert_cmd(cmd); + + netfs_trans_update(cmd, trans, size); + + return 0; + +err_out_exit: + printk("%s: completed ino: %llu, err: %d.\n", __func__, pi->ino, err); + return err; +} + +static int pohmelfs_write_trans_complete(struct page **pages, unsigned int page_num, + void *private, int err) +{ + unsigned i; + + dprintk("%s: pages: %lu-%lu, page_num: %u, err: %d.\n", + __func__, pages[0]->index, pages[page_num-1]->index, + page_num, err); + + for (i = 0; i < page_num; i++) { + struct page *page = pages[i]; + + if (!page) + continue; + + end_page_writeback(page); + + if (err < 0) { + SetPageError(page); + set_page_dirty(page); + } + + unlock_page(page); + page_cache_release(page); + + /* dprintk("%s: %3u/%u: page: %p.\n", __func__, i, page_num, page); */ + } + return err; +} + +static int pohmelfs_inode_has_dirty_pages(struct address_space *mapping, pgoff_t index) +{ + int ret; + struct page *page; + + rcu_read_lock(); + ret = radix_tree_gang_lookup_tag(&mapping->page_tree, + (void **)&page, index, 1, PAGECACHE_TAG_DIRTY); + rcu_read_unlock(); + return ret; +} + +static int pohmelfs_writepages(struct address_space *mapping, struct writeback_control *wbc) +{ + struct inode *inode = mapping->host; + struct pohmelfs_inode *pi = POHMELFS_I(inode); + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + struct backing_dev_info *bdi = mapping->backing_dev_info; + int err = 0; + int done = 0; + int nr_pages; + pgoff_t index; + pgoff_t end; /* Inclusive */ + int scanned = 0; + int range_whole = 0; + + if (wbc->nonblocking && bdi_write_congested(bdi)) { + wbc->encountered_congestion = 1; + return 0; + } + + if (wbc->range_cyclic) { + index = mapping->writeback_index; /* Start from prev offset */ + end = -1; + } else { + index = wbc->range_start >> PAGE_CACHE_SHIFT; + end = wbc->range_end >> PAGE_CACHE_SHIFT; + if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) + range_whole = 1; + scanned = 1; + } +retry: + while (!done && (index <= end)) { + unsigned int i = min(end - index, (pgoff_t)psb->trans_max_pages); + int path_len; + struct netfs_trans *trans; + + err = pohmelfs_inode_has_dirty_pages(mapping, index); + if (!err) + break; + + err = pohmelfs_path_length(pi); + if (err < 0) + break; + + path_len = err; + + if (path_len <= 2) { + err = -ENOENT; + break; + } + + trans = netfs_trans_alloc(psb, path_len, 0, i); + if (!trans) { + err = -ENOMEM; + break; + } + trans->complete = &pohmelfs_write_trans_complete; + + trans->page_num = nr_pages = find_get_pages_tag(mapping, &index, + PAGECACHE_TAG_DIRTY, trans->page_num, + trans->pages); + + dprintk("%s: t: %p, nr_pages: %u, end: %lu, index: %lu, max: %u.\n", + __func__, trans, nr_pages, end, index, trans->page_num); + + if (!nr_pages) + goto err_out_reset; + + err = pohmelfs_write_inode_create(inode, trans); + if (err) + goto err_out_reset; + + err = 0; + scanned = 1; + + for (i = 0; i < trans->page_num; i++) { + struct page *page = trans->pages[i]; + + lock_page(page); + + if (unlikely(page->mapping != mapping)) + goto out_continue; + + if (!wbc->range_cyclic && page->index > end) { + done = 1; + goto out_continue; + } + + if (wbc->sync_mode != WB_SYNC_NONE) + wait_on_page_writeback(page); + + if (PageWriteback(page) || + !clear_page_dirty_for_io(page)) { + dprintk("%s: not clear for io page: %p, writeback: %d.\n", + __func__, page, PageWriteback(page)); + goto out_continue; + } + + set_page_writeback(page); + + trans->attached_size += page_private(page); + trans->attached_pages++; +#if 0 + dprintk("%s: %u/%u added trans: %p, gen: %u, page: %p, [High: %d], size: %lu, idx: %lu.\n", + __func__, i, trans->page_num, trans, trans->gen, page, + !!PageHighMem(page), page_private(page), page->index); +#endif + wbc->nr_to_write--; + + if (wbc->nr_to_write <= 0) + done = 1; + if (wbc->nonblocking && bdi_write_congested(bdi)) { + wbc->encountered_congestion = 1; + done = 1; + } + + continue; +out_continue: + unlock_page(page); + trans->pages[i] = NULL; + } + + err = netfs_trans_finish(trans, psb); + if (err) + break; + + continue; + +err_out_reset: + trans->result = err; + netfs_trans_reset(trans); + netfs_trans_put(trans); + break; + } + + if (!scanned && !done) { + /* + * We hit the last page and there is more work to be done: wrap + * back to the start of the file + */ + scanned = 1; + index = 0; + goto retry; + } + + if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) + mapping->writeback_index = index; + + return err; +} + +/* + * Inode writeback creation completion callback. + * Only invoked for just created inodes, which do not have pages attached, + * like dirs and empty files. + */ +static int pohmelfs_write_inode_complete(struct page **pages, unsigned int page_num, + void *private, int err) +{ + struct inode *inode = private; + struct pohmelfs_inode *pi = POHMELFS_I(inode); + + if (inode) { + if (err) { + mark_inode_dirty(inode); + clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); + } else { + set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); + } + + pohmelfs_put_inode(pi); + } + + return err; +} + +int pohmelfs_write_create_inode(struct pohmelfs_inode *pi) +{ + struct netfs_trans *t; + struct inode *inode = &pi->vfs_inode; + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + int err; + + if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state)) + return 0; + + dprintk("%s: started ino: %llu.\n", __func__, pi->ino); + + err = pohmelfs_path_length(pi); + if (err < 0) + goto err_out_exit; + + t = netfs_trans_alloc(psb, err + 1, 0, 0); + if (!t) { + err = -ENOMEM; + goto err_out_put; + } + t->complete = pohmelfs_write_inode_complete; + t->private = igrab(inode); + if (!t->private) { + err = -ENOENT; + goto err_out_put; + } + + err = pohmelfs_write_inode_create(inode, t); + if (err) + goto err_out_put; + + netfs_trans_finish(t, POHMELFS_SB(inode->i_sb)); + + return 0; + +err_out_put: + t->result = err; + netfs_trans_put(t); +err_out_exit: + return err; +} + +/* + * Sync all not-yet-created children in given directory to the server. + */ +static int pohmelfs_write_inode_create_children(struct inode *inode) +{ + struct pohmelfs_inode *parent = POHMELFS_I(inode); + struct super_block *sb = inode->i_sb; + struct pohmelfs_name *n; + + while (!list_empty(&parent->sync_create_list)) { + n = NULL; + mutex_lock(&parent->offset_lock); + if (!list_empty(&parent->sync_create_list)) { + n = list_first_entry(&parent->sync_create_list, + struct pohmelfs_name, sync_create_entry); + list_del_init(&n->sync_create_entry); + } + mutex_unlock(&parent->offset_lock); + + if (!n) + break; + + inode = ilookup(sb, n->ino); + + dprintk("%s: parent: %llu, ino: %llu, inode: %p.\n", + __func__, parent->ino, n->ino, inode); + + if (inode && (inode->i_state & I_DIRTY)) { + struct pohmelfs_inode *pi = POHMELFS_I(inode); + pohmelfs_write_create_inode(pi); + //pohmelfs_meta_command(pi, NETFS_INODE_INFO, 0, NULL, NULL, 0); + iput(inode); + } + } + + return 0; +} + +/* + * Removes given child from given inode on server. + */ +int pohmelfs_remove_child(struct pohmelfs_inode *pi, struct pohmelfs_name *n) +{ + return pohmelfs_meta_command_data(pi, pi->ino, NETFS_REMOVE, NULL, 0, NULL, NULL, 0); +} + +/* + * Writeback for given inode. + */ +static int pohmelfs_write_inode(struct inode *inode, int sync) +{ + struct pohmelfs_inode *pi = POHMELFS_I(inode); + + pohmelfs_write_create_inode(pi); + pohmelfs_write_inode_create_children(inode); + + return 0; +} + +/* + * It is not exported, sorry... + */ +static inline wait_queue_head_t *page_waitqueue(struct page *page) +{ + const struct zone *zone = page_zone(page); + + return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)]; +} + +static int pohmelfs_wait_on_page_locked(struct page *page) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(page->mapping->host->i_sb); + long ret = psb->wait_on_page_timeout; + DEFINE_WAIT_BIT(wait, &page->flags, PG_locked); + int err = 0; + + if (!PageLocked(page)) + return 0; + + for (;;) { + prepare_to_wait(page_waitqueue(page), + &wait.wait, TASK_INTERRUPTIBLE); + + dprintk("%s: page: %p, locked: %d, uptodate: %d, error: %d, flags: %lx.\n", + __func__, page, PageLocked(page), PageUptodate(page), + PageError(page), page->flags); + + if (!PageLocked(page)) + break; + + if (!signal_pending(current)) { + ret = schedule_timeout(ret); + if (!ret) + break; + continue; + } + ret = -ERESTARTSYS; + break; + } + finish_wait(page_waitqueue(page), &wait.wait); + + if (!ret) + err = -ETIMEDOUT; + + + if (!err) + SetPageUptodate(page); + + if (err) + printk("%s: page: %p, uptodate: %d, locked: %d, err: %d.\n", + __func__, page, PageUptodate(page), PageLocked(page), err); + + return err; +} + +static int pohmelfs_read_page_complete(struct page **pages, unsigned int page_num, + void *private, int err) +{ + struct page *page = private; + + if (PageChecked(page)) + return err; + + if (err < 0) { + dprintk("%s: page: %p, err: %d.\n", __func__, page, err); + SetPageError(page); + } + + unlock_page(page); + + return err; +} + +/* + * Read a page from remote server. + * Function will wait until page is unlocked. + */ +static int pohmelfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + struct pohmelfs_inode *pi = POHMELFS_I(inode); + struct netfs_trans *t; + struct netfs_cmd *cmd; + int err, path_len; + void *data; + u64 isize; + + err = pohmelfs_data_lock(pi, page->index << PAGE_CACHE_SHIFT, + PAGE_SIZE, POHMELFS_READ_LOCK); + if (err) + goto err_out_exit; + + isize = i_size_read(inode); + if (isize <= page->index << PAGE_CACHE_SHIFT) { + SetPageUptodate(page); + unlock_page(page); + return 0; + } + + path_len = pohmelfs_path_length(pi); + if (path_len < 0) { + err = path_len; + goto err_out_exit; + } + + t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0); + if (!t) { + err = -ENOMEM; + goto err_out_exit; + } + + t->complete = pohmelfs_read_page_complete; + t->private = page; + + cmd = netfs_trans_current(t); + data = (void *)(cmd + 1); + + err = pohmelfs_construct_path_string(pi, data, path_len); + if (err < 0) + goto err_out_free; + + path_len = err; + + cmd->id = pi->ino; + cmd->start = page->index; + cmd->start <<= PAGE_CACHE_SHIFT; + cmd->size = PAGE_CACHE_SIZE + path_len; + cmd->cmd = NETFS_READ_PAGE; + cmd->ext = path_len; + + dprintk("%s: path: '%s', page: %p, ino: %llu, start: %llu, size: %lu.\n", + __func__, (char *)data, page, pi->ino, cmd->start, PAGE_CACHE_SIZE); + + netfs_convert_cmd(cmd); + netfs_trans_update(cmd, t, path_len); + + err = netfs_trans_finish(t, psb); + if (err) + goto err_out_return; + + return pohmelfs_wait_on_page_locked(page); + +err_out_free: + t->result = err; + netfs_trans_put(t); +err_out_exit: + SetPageError(page); + if (PageLocked(page)) + unlock_page(page); +err_out_return: + printk("%s: page: %p, start: %lu, size: %lu, err: %d.\n", + __func__, page, page->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE, err); + + return err; +} + +/* + * Write begin/end magic. + * Allocates a page and writes inode if it was not synced to server before. + */ +static int pohmelfs_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) +{ + struct inode *inode = mapping->host; + struct page *page; + pgoff_t index; + unsigned start, end; + int err; + + *pagep = NULL; + + index = pos >> PAGE_CACHE_SHIFT; + start = pos & (PAGE_CACHE_SIZE - 1); + end = start + len; + + page = grab_cache_page(mapping, index); +#if 0 + dprintk("%s: page: %p pos: %llu, len: %u, index: %lu, start: %u, end: %u, uptodate: %d.\n", + __func__, page, pos, len, index, start, end, PageUptodate(page)); +#endif + if (!page) { + err = -ENOMEM; + goto err_out_exit; + } + + while (!PageUptodate(page)) { + if (start && test_bit(NETFS_INODE_REMOTE_SYNCED, &POHMELFS_I(inode)->state)) { + err = pohmelfs_readpage(file, page); + if (err) + goto err_out_exit; + + lock_page(page); + continue; + } + + if (len != PAGE_CACHE_SIZE) { + void *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr + start, 0, PAGE_CACHE_SIZE - start); + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); + } + SetPageUptodate(page); + } + + set_page_private(page, end); + + *pagep = page; + + return 0; + +err_out_exit: + page_cache_release(page); + *pagep = NULL; + + return err; +} + +static int pohmelfs_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *page, void *fsdata) +{ + struct inode *inode = mapping->host; + + if (copied != len) { + unsigned from = pos & (PAGE_CACHE_SIZE - 1); + void *kaddr = kmap_atomic(page, KM_USER0); + + memset(kaddr + from + copied, 0, len - copied); + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); + } + + SetPageUptodate(page); + set_page_dirty(page); +#if 0 + dprintk("%s: page: %p [U: %d, D: %d, L: %d], pos: %llu, len: %u, copied: %u.\n", + __func__, page, + PageUptodate(page), PageDirty(page), PageLocked(page), + pos, len, copied); +#endif + flush_dcache_page(page); + + unlock_page(page); + page_cache_release(page); + + if (pos + copied > inode->i_size) { + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + + psb->avail_size -= pos + copied - inode->i_size; + + i_size_write(inode, pos + copied); + } + + return copied; +} + +static int pohmelfs_readpages_trans_complete(struct page **__pages, unsigned int page_num, + void *private, int err) +{ + struct pohmelfs_inode *pi = private; + unsigned int i, num; + struct page **pages, *page = (struct page *)__pages; + loff_t index = page->index; + + pages = kzalloc(sizeof(void *) * page_num, GFP_NOIO); + if (!pages) + return -ENOMEM; + + num = find_get_pages_contig(pi->vfs_inode.i_mapping, index, page_num, pages); + if (num <= 0) { + err = num; + goto err_out_free; + } + + for (i=0; iindex, + PageUptodate(page), PageLocked(page), err); + + if (!PageChecked(page)) { + if (err < 0) + SetPageError(page); + unlock_page(page); + } + page_cache_release(page); + page_cache_release(page); + } + +err_out_free: + kfree(pages); + return err; +} + +static int pohmelfs_send_readpages(struct pohmelfs_inode *pi, struct page *first, unsigned int num) +{ + struct netfs_trans *t; + struct netfs_cmd *cmd; + struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); + int err, path_len; + void *data; + + err = pohmelfs_data_lock(pi, first->index << PAGE_CACHE_SHIFT, + num * PAGE_SIZE, POHMELFS_READ_LOCK); + if (err) + goto err_out_exit; + + path_len = pohmelfs_path_length(pi); + if (path_len < 0) { + err = path_len; + goto err_out_exit; + } + + t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0); + if (!t) { + err = -ENOMEM; + goto err_out_exit; + } + + cmd = netfs_trans_current(t); + data = (void *)(cmd + 1); + + t->complete = pohmelfs_readpages_trans_complete; + t->private = pi; + t->page_num = num; + t->pages = (struct page **)first; + + err = pohmelfs_construct_path_string(pi, data, path_len); + if (err < 0) + goto err_out_put; + + path_len = err; + + cmd->cmd = NETFS_READ_PAGES; + cmd->start = first->index; + cmd->start <<= PAGE_CACHE_SHIFT; + cmd->size = (num << 8 | PAGE_CACHE_SHIFT); + cmd->id = pi->ino; + cmd->ext = path_len; + + dprintk("%s: t: %p, gen: %u, path: '%s', path_len: %u, " + "start: %lu, num: %u.\n", + __func__, t, t->gen, (char *)data, path_len, + first->index, num); + + netfs_convert_cmd(cmd); + netfs_trans_update(cmd, t, path_len); + + return netfs_trans_finish(t, psb); + +err_out_put: + netfs_trans_free(t); +err_out_exit: + pohmelfs_readpages_trans_complete((struct page **)first, num, pi, err); + return err; +} + +#define list_to_page(head) (list_entry((head)->prev, struct page, lru)) + +static int pohmelfs_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned nr_pages) +{ + unsigned int page_idx, num = 0; + struct page *page = NULL, *first = NULL; + + for (page_idx = 0; page_idx < nr_pages; page_idx++) { + page = list_to_page(pages); + + prefetchw(&page->flags); + list_del(&page->lru); + + if (!add_to_page_cache_lru(page, mapping, + page->index, GFP_KERNEL)) { + + if (!num) { + num = 1; + first = page; + continue; + } + + dprintk("%s: added to lru page: %p, page_index: %lu, first_index: %lu.\n", + __func__, page, page->index, first->index); + + if (unlikely(first->index + num != page->index) || (num > 500)) { + pohmelfs_send_readpages(POHMELFS_I(mapping->host), + first, num); + first = page; + num = 0; + } + + num++; + } + } + pohmelfs_send_readpages(POHMELFS_I(mapping->host), first, num); + + /* + * This will be sync read, so when last page is processed, + * all previous are alerady unlocked and ready to be used. + */ + return 0; +} + +/* + * Small addres space operations for POHMELFS. + */ +const struct address_space_operations pohmelfs_aops = { + .readpage = pohmelfs_readpage, + .readpages = pohmelfs_readpages, + .writepages = pohmelfs_writepages, + .write_begin = pohmelfs_write_begin, + .write_end = pohmelfs_write_end, + .set_page_dirty = __set_page_dirty_nobuffers, +}; + +/* + * ->detroy_inode() callback. Deletes inode from the caches + * and frees private data. + */ +static void pohmelfs_destroy_inode(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + struct pohmelfs_sb *psb = POHMELFS_SB(sb); + struct pohmelfs_inode *pi = POHMELFS_I(inode); + + //pohmelfs_data_unlock(pi, 0, inode->i_size, POHMELFS_READ_LOCK); + + pohmelfs_inode_del_inode(psb, pi); + + dprintk("%s: pi: %p, inode: %p, ino: %llu.\n", + __func__, pi, &pi->vfs_inode, pi->ino); + kmem_cache_free(pohmelfs_inode_cache, pi); + atomic_long_dec(&psb->total_inodes); +} + +/* + * ->alloc_inode() callback. Allocates inode and initilizes private data. + */ +static struct inode *pohmelfs_alloc_inode(struct super_block *sb) +{ + struct pohmelfs_inode *pi; + + pi = kmem_cache_alloc(pohmelfs_inode_cache, GFP_NOIO); + if (!pi) + return NULL; + + pi->hash_root = RB_ROOT; + mutex_init(&pi->offset_lock); + + INIT_LIST_HEAD(&pi->sync_create_list); + + INIT_LIST_HEAD(&pi->inode_entry); + + pi->lock_type = 0; + pi->state = 0; + pi->total_len = 0; + pi->drop_count = 0; + + dprintk("%s: pi: %p, inode: %p.\n", __func__, pi, &pi->vfs_inode); + + atomic_long_inc(&POHMELFS_SB(sb)->total_inodes); + + return &pi->vfs_inode; +} + +/* + * We want fsync() to work on POHMELFS. + */ +static int pohmelfs_fsync(struct file *file, struct dentry *dentry, int datasync) +{ + struct inode *inode = file->f_mapping->host; + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = 0, /* sys_fsync did this */ + }; + + return sync_inode(inode, &wbc); +} + +ssize_t pohmelfs_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + struct address_space *mapping = file->f_mapping; + struct inode *inode = mapping->host; + struct pohmelfs_inode *pi = POHMELFS_I(inode); + struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len }; + struct kiocb kiocb; + ssize_t ret; + loff_t pos = *ppos; + + init_sync_kiocb(&kiocb, file); + kiocb.ki_pos = pos; + kiocb.ki_left = len; + + dprintk("%s: len: %zu, pos: %llu.\n", __func__, len, pos); + + mutex_lock(&inode->i_mutex); + ret = pohmelfs_data_lock(pi, pos, len, POHMELFS_WRITE_LOCK); + if (ret) + goto err_out_unlock; + + ret = generic_file_aio_write_nolock(&kiocb, &iov, 1, pos); + *ppos = kiocb.ki_pos; + + mutex_unlock(&inode->i_mutex); + WARN_ON(ret < 0); + + if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { + ssize_t err; + + err = sync_page_range(inode, mapping, pos, ret); + if (err < 0) + ret = err; + WARN_ON(ret < 0); + } + + return ret; + +err_out_unlock: + mutex_unlock(&inode->i_mutex); + return ret; +} + +const static struct file_operations pohmelfs_file_ops = { + .open = generic_file_open, + .fsync = pohmelfs_fsync, + + .llseek = generic_file_llseek, + + .read = do_sync_read, + .aio_read = generic_file_aio_read, + + .mmap = generic_file_mmap, + + .splice_read = generic_file_splice_read, + .splice_write = generic_file_splice_write, + + .write = pohmelfs_write, + .aio_write = generic_file_aio_write, +}; + +const struct inode_operations pohmelfs_symlink_inode_operations = { + .readlink = generic_readlink, + .follow_link = page_follow_link_light, + .put_link = page_put_link, +}; + +int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr) +{ + int err; + + err = inode_change_ok(inode, attr); + if (err) { + dprintk("%s: ino: %llu, inode changes are not allowed.\n", __func__, POHMELFS_I(inode)->ino); + goto err_out_exit; + } + + if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || + (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { + err = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0; + if (err) + goto err_out_exit; + } + + err = inode_setattr(inode, attr); + if (err) { + dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); + goto err_out_exit; + } + + dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n", + __func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode, + inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size); + + return 0; + +err_out_exit: + return err; +} + +int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + struct pohmelfs_inode *pi = POHMELFS_I(inode); + int err; + + err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_WRITE_LOCK); + if (err) + goto err_out_exit; + + err = security_inode_setattr(dentry, attr); + if (err) + goto err_out_exit; + + err = pohmelfs_setattr_raw(inode, attr); + if (err) + goto err_out_exit; + + return 0; + +err_out_exit: + return err; +} + +static int pohmelfs_send_xattr_req(struct pohmelfs_inode *pi, u64 id, u64 start, + const char *name, const void *value, size_t attrsize, int command) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); + int err, path_len, namelen = strlen(name) + 1; /* 0-byte */ + struct netfs_trans *t; + struct netfs_cmd *cmd; + void *data; + + dprintk("%s: id: %llu, start: %llu, name: '%s', attrsize: %zu, cmd: %d.\n", + __func__, id, start, name, attrsize, command); + + path_len = pohmelfs_path_length(pi); + if (path_len < 0) { + err = path_len; + goto err_out_exit; + } + + t = netfs_trans_alloc(psb, namelen + path_len + attrsize, 0, 0); + if (!t) { + err = -ENOMEM; + goto err_out_exit; + } + + cmd = netfs_trans_current(t); + data = cmd + 1; + + path_len = pohmelfs_construct_path_string(pi, data, path_len); + if (path_len < 0) { + err = path_len; + goto err_out_put; + } + data += path_len; + + /* + * 'name' is a NUL-terminated string already and + * 'namelen' includes 0-byte. + */ + memcpy(data, name, namelen); + data += namelen; + + memcpy(data, value, attrsize); + + cmd->cmd = command; + cmd->id = id; + cmd->start = start; + cmd->size = attrsize + namelen + path_len; + cmd->ext = path_len; + cmd->csize = 0; + cmd->cpad = 0; + + netfs_convert_cmd(cmd); + netfs_trans_update(cmd, t, namelen + path_len + attrsize); + + return netfs_trans_finish(t, psb); + +err_out_put: + t->result = err; + netfs_trans_put(t); +err_out_exit: + return err; +} + +static int pohmelfs_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t attrsize, int flags) +{ + struct inode *inode = dentry->d_inode; + struct pohmelfs_inode *pi = POHMELFS_I(inode); + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + + if (!(psb->state_flags & POHMELFS_FLAGS_XATTR)) + return -EOPNOTSUPP; + + return pohmelfs_send_xattr_req(pi, flags, attrsize, name, + value, attrsize, NETFS_XATTR_SET); +} + +static ssize_t pohmelfs_getxattr(struct dentry *dentry, const char *name, + void *value, size_t attrsize) +{ + struct inode *inode = dentry->d_inode; + struct pohmelfs_inode *pi = POHMELFS_I(inode); + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + struct pohmelfs_mcache *m; + int err; + long timeout = psb->mcache_timeout; + + if (!(psb->state_flags & POHMELFS_FLAGS_XATTR)) + return -EOPNOTSUPP; + + m = pohmelfs_mcache_alloc(psb, 0, attrsize, value); + if (IS_ERR(m)) + return PTR_ERR(m); + + dprintk("%s: ino: %llu, name: '%s', size: %zu.\n", + __func__, pi->ino, name, attrsize); + + err = pohmelfs_send_xattr_req(pi, m->gen, attrsize, name, value, 0, NETFS_XATTR_GET); + if (err) + goto err_out_put; + + do { + err = wait_for_completion_timeout(&m->complete, timeout); + if (err) { + err = m->err; + break; + } + + /* + * This loop is a bit ugly, since it waits until reference counter + * hits 1 and then put object here. Main goal is to prevent race with + * network thread, when it can start processing given request, i.e. + * increase its reference counter but yet not complete it, while + * we will exit from ->getxattr() with timeout, and although request + * will not be freed (its reference counter was increased by network + * thread), data pointer provided by user may be released, so we will + * overwrite already freed area in network thread. + * + * Now after timeout we remove request from the cache, so it can not be + * found by network thread, and wait for its reference counter to hit 1, + * i.e. if network thread already started to process this request, we wait + * it to finish, and then free object locally. If reference counter is + * already 1, i.e. request is not used by anyone else, we can free it without + * problem. + */ + err = -ETIMEDOUT; + timeout = HZ; + + pohmelfs_mcache_remove_locked(psb, m); + } while (atomic_read(&m->refcnt) != 1); + + pohmelfs_mcache_put(psb, m); + + dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err); + + return err; + +err_out_put: + pohmelfs_mcache_put(psb, m); + return err; +} + +static int pohmelfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + struct pohmelfs_inode *pi = POHMELFS_I(inode); + int err; + + err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK); + if (err) + return err; + + dprintk("%s: ino: %llu, mode: %o, uid: %u, gid: %u, size: %llu.\n", + __func__, pi->ino, inode->i_mode, inode->i_uid, + inode->i_gid, inode->i_size); + + generic_fillattr(inode, stat); + return 0; +} + +const struct inode_operations pohmelfs_file_inode_operations = { + .setattr = pohmelfs_setattr, + .getattr = pohmelfs_getattr, + .setxattr = pohmelfs_setxattr, + .getxattr = pohmelfs_getxattr, +}; + +/* + * Fill inode data: mode, size, operation callbacks and so on... + */ +void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info) +{ + inode->i_mode = info->mode; + inode->i_nlink = info->nlink; + inode->i_uid = info->uid; + inode->i_gid = info->gid; + inode->i_blocks = info->blocks; + inode->i_rdev = info->rdev; + inode->i_size = info->size; + inode->i_version = info->version; + inode->i_blkbits = ffs(info->blocksize); + + dprintk("%s: inode: %p, num: %lu/%llu inode is regular: %d, dir: %d, link: %d, mode: %o, size: %llu.\n", + __func__, inode, inode->i_ino, info->ino, + S_ISREG(inode->i_mode), S_ISDIR(inode->i_mode), + S_ISLNK(inode->i_mode), inode->i_mode, inode->i_size); + + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; + + /* + * i_mapping is a pointer to i_data during inode initialization. + */ + inode->i_data.a_ops = &pohmelfs_aops; + + if (S_ISREG(inode->i_mode)) { + inode->i_fop = &pohmelfs_file_ops; + inode->i_op = &pohmelfs_file_inode_operations; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_fop = &pohmelfs_dir_fops; + inode->i_op = &pohmelfs_dir_inode_ops; + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &pohmelfs_symlink_inode_operations; + inode->i_fop = &pohmelfs_file_ops; + } else { + inode->i_fop = &generic_ro_fops; + } +} + +static void pohmelfs_drop_inode(struct inode *inode) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + struct pohmelfs_inode *pi = POHMELFS_I(inode); + + spin_lock(&psb->ino_lock); + list_del_init(&pi->inode_entry); + spin_unlock(&psb->ino_lock); + + generic_drop_inode(inode); +} + +static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb, + struct list_head *head, unsigned int *count) +{ + struct pohmelfs_inode *pi = NULL; + + spin_lock(&psb->ino_lock); + if (!list_empty(head)) { + pi = list_entry(head->next, struct pohmelfs_inode, + inode_entry); + list_del_init(&pi->inode_entry); + *count = pi->drop_count; + pi->drop_count = 0; + } + spin_unlock(&psb->ino_lock); + + return pi; +} + +static void pohmelfs_flush_transactions(struct pohmelfs_sb *psb) +{ + struct pohmelfs_config *c; + + mutex_lock(&psb->state_lock); + list_for_each_entry(c, &psb->state_list, config_entry) { + pohmelfs_state_flush_transactions(&c->state); + } + mutex_unlock(&psb->state_lock); +} + +/* + * ->put_super() callback. Invoked before superblock is destroyed, + * so it has to clean all private data. + */ +static void pohmelfs_put_super(struct super_block *sb) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(sb); + struct pohmelfs_inode *pi; + unsigned int count; + unsigned int in_drop_list = 0; + struct inode *inode, *tmp; + + dprintk("%s.\n", __func__); + + /* + * Kill pending transactions, which could affect inodes in-flight. + */ + pohmelfs_flush_transactions(psb); + + while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count))) { + inode = &pi->vfs_inode; + + dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n", + __func__, pi->ino, pi, inode, count); + + if (atomic_read(&inode->i_count) != count) { + printk("%s: ino: %llu, pi: %p, inode: %p, count: %u, i_count: %d.\n", + __func__, pi->ino, pi, inode, count, + atomic_read(&inode->i_count)); + count = atomic_read(&inode->i_count); + in_drop_list++; + } + + while (count--) + iput(&pi->vfs_inode); + } + + list_for_each_entry_safe(inode, tmp, &sb->s_inodes, i_sb_list) { + pi = POHMELFS_I(inode); + + dprintk("%s: ino: %llu, pi: %p, inode: %p, i_count: %u.\n", + __func__, pi->ino, pi, inode, atomic_read(&inode->i_count)); + + /* + * These are special inodes, they were created during + * directory reading or lookup, and were not bound to dentry, + * so they live here with reference counter being 1 and prevent + * umount from succeed since it believes that they are busy. + */ + count = atomic_read(&inode->i_count); + if (count) { + list_del_init(&inode->i_sb_list); + while (count--) + iput(&pi->vfs_inode); + } + } + + psb->trans_scan_timeout = psb->drop_scan_timeout = 0; + cancel_rearming_delayed_work(&psb->dwork); + cancel_rearming_delayed_work(&psb->drop_dwork); + flush_scheduled_work(); + + dprintk("%s: stopped workqueues.\n", __func__); + + pohmelfs_crypto_exit(psb); + pohmelfs_state_exit(psb); + + kfree(psb); + sb->s_fs_info = NULL; + + pohmelfs_ftrans_exit(); +} + +static int pohmelfs_remount(struct super_block *sb, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + +static int pohmelfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + struct pohmelfs_sb *psb = POHMELFS_SB(sb); + + /* + * There are no filesystem size limits yet. + */ + memset(buf, 0, sizeof(struct kstatfs)); + + buf->f_type = POHMELFS_MAGIC_NUM; /* 'POH.' */ + buf->f_bsize = sb->s_blocksize; + buf->f_files = psb->ino; + buf->f_namelen = 255; + buf->f_files = atomic_long_read(&psb->total_inodes); + buf->f_bfree = buf->f_bavail = psb->avail_size >> PAGE_SHIFT; + buf->f_blocks = psb->total_size >> PAGE_SHIFT; + + dprintk("%s: total: %llu, avail: %llu, inodes: %llu, bsize: %lu.\n", + __func__, psb->total_size, psb->avail_size, buf->f_files, sb->s_blocksize); + + return 0; +} + +static int pohmelfs_show_options(struct seq_file *seq, struct vfsmount *vfs) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(vfs->mnt_sb); + + seq_printf(seq, ",idx=%u", psb->idx); + seq_printf(seq, ",trans_scan_timeout=%u", jiffies_to_msecs(psb->trans_scan_timeout)); + seq_printf(seq, ",drop_scan_timeout=%u", jiffies_to_msecs(psb->drop_scan_timeout)); + seq_printf(seq, ",wait_on_page_timeout=%u", jiffies_to_msecs(psb->wait_on_page_timeout)); + seq_printf(seq, ",trans_retries=%u", psb->trans_retries); + seq_printf(seq, ",crypto_thread_num=%u", psb->crypto_thread_num); + seq_printf(seq, ",trans_max_pages=%u", psb->trans_max_pages); + seq_printf(seq, ",mcache_timeout=%u", jiffies_to_msecs(psb->mcache_timeout)); + if (psb->crypto_fail_unsupported) + seq_printf(seq, ",crypto_fail_unsupported"); + + return 0; +} + +static const struct super_operations pohmelfs_sb_ops = { + .alloc_inode = pohmelfs_alloc_inode, + .destroy_inode = pohmelfs_destroy_inode, + .drop_inode = pohmelfs_drop_inode, + .write_inode = pohmelfs_write_inode, + .put_super = pohmelfs_put_super, + .remount_fs = pohmelfs_remount, + .statfs = pohmelfs_statfs, + .show_options = pohmelfs_show_options, +}; + +enum { + pohmelfs_opt_idx, + pohmelfs_opt_trans_scan_timeout, + pohmelfs_opt_drop_scan_timeout, + pohmelfs_opt_wait_on_page_timeout, + pohmelfs_opt_trans_retries, + pohmelfs_opt_crypto_thread_num, + pohmelfs_opt_trans_max_pages, + pohmelfs_opt_crypto_fail_unsupported, + pohmelfs_opt_mcache_timeout, +}; + +static struct match_token pohmelfs_tokens[] = { + {pohmelfs_opt_idx, "idx=%u"}, + {pohmelfs_opt_trans_scan_timeout, "trans_scan_timeout=%u"}, + {pohmelfs_opt_drop_scan_timeout, "drop_scan_timeout=%u"}, + {pohmelfs_opt_wait_on_page_timeout, "wait_on_page_timeout=%u"}, + {pohmelfs_opt_trans_retries, "trans_retries=%u"}, + {pohmelfs_opt_crypto_thread_num, "crypto_thread_num=%u"}, + {pohmelfs_opt_trans_max_pages, "trans_max_pages=%u"}, + {pohmelfs_opt_crypto_fail_unsupported, "crypto_fail_unsupported"}, + {pohmelfs_opt_mcache_timeout, "mcache_timeout=%u"}, +}; + +static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int option, err; + + if (!options) + return 0; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + if (!*p) + continue; + + token = match_token(p, pohmelfs_tokens, args); + + err = match_int(&args[0], &option); + if (err) + return err; + + switch (token) { + case pohmelfs_opt_idx: + psb->idx = option; + break; + case pohmelfs_opt_trans_scan_timeout: + psb->trans_scan_timeout = msecs_to_jiffies(option); + break; + case pohmelfs_opt_drop_scan_timeout: + psb->drop_scan_timeout = msecs_to_jiffies(option); + break; + case pohmelfs_opt_wait_on_page_timeout: + psb->wait_on_page_timeout = msecs_to_jiffies(option); + break; + case pohmelfs_opt_mcache_timeout: + psb->mcache_timeout = msecs_to_jiffies(option); + break; + case pohmelfs_opt_trans_retries: + psb->trans_retries = option; + break; + case pohmelfs_opt_crypto_thread_num: + psb->crypto_thread_num = option; + break; + case pohmelfs_opt_trans_max_pages: + psb->trans_max_pages = option; + break; + case pohmelfs_opt_crypto_fail_unsupported: + psb->crypto_fail_unsupported = 1; + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static void pohmelfs_flush_inode(struct pohmelfs_inode *pi, unsigned int count) +{ + struct inode *inode = &pi->vfs_inode; + + dprintk("%s: %p: ino: %llu, owned: %d.\n", + __func__, inode, pi->ino, test_bit(NETFS_INODE_OWNED, &pi->state)); + + mutex_lock(&inode->i_mutex); + if (test_and_clear_bit(NETFS_INODE_OWNED, &pi->state)) { + filemap_fdatawrite(inode->i_mapping); + inode->i_sb->s_op->write_inode(inode, 0); + } + + truncate_inode_pages(inode->i_mapping, 0); + + pohmelfs_data_unlock(pi, 0, ~0, POHMELFS_WRITE_LOCK); + mutex_unlock(&inode->i_mutex); +} + +static void pohmelfs_put_inode_count(struct pohmelfs_inode *pi, unsigned int count) +{ + dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n", + __func__, pi->ino, pi, &pi->vfs_inode, count); + + if (test_and_clear_bit(NETFS_INODE_NEED_FLUSH, &pi->state)) + pohmelfs_flush_inode(pi, count); + + while (count--) + iput(&pi->vfs_inode); +} + +static void pohmelfs_drop_scan(struct work_struct *work) +{ + struct pohmelfs_sb *psb = + container_of(work, struct pohmelfs_sb, drop_dwork.work); + struct pohmelfs_inode *pi; + unsigned int count = 0; + + while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count))) { + pohmelfs_put_inode_count(pi, count); + } + pohmelfs_check_states(psb); + + if (psb->drop_scan_timeout) + schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout); +} + +/* + * Run through all transactions starting from the oldest, + * drop transaction from current state and try to send it + * to all remote nodes, which are currently installed. + */ +static void pohmelfs_trans_scan_state(struct netfs_state *st) +{ + struct rb_node *rb_node; + struct netfs_trans_dst *dst; + struct pohmelfs_sb *psb = st->psb; + unsigned int timeout = psb->trans_scan_timeout; + struct netfs_trans *t; + int err; + + mutex_lock(&st->trans_lock); + for (rb_node = rb_first(&st->trans_root); rb_node; ) { + dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry); + t = dst->trans; + + if (timeout && time_after(dst->send_time + timeout, jiffies) + && dst->retries == 0) + break; + + dprintk("%s: t: %p, gen: %u, st: %p, retries: %u, max: %u.\n", + __func__, t, t->gen, st, dst->retries, psb->trans_retries); + netfs_trans_get(t); + + rb_node = rb_next(rb_node); + + err = -ETIMEDOUT; + if (timeout && (++dst->retries < psb->trans_retries)) { + err = netfs_trans_resend(t, psb); + } + + if (err || (t->flags & NETFS_TRANS_SINGLE_DST)) { + if (netfs_trans_remove_nolock(dst, st)) + netfs_trans_drop_dst_nostate(dst); + } + + t->result = err; + netfs_trans_put(t); + } + mutex_unlock(&st->trans_lock); +} + +/* + * Walk through all installed network states and resend all + * transactions, which are old enough. + */ +static void pohmelfs_trans_scan(struct work_struct *work) +{ + struct pohmelfs_sb *psb = + container_of(work, struct pohmelfs_sb, dwork.work); + struct netfs_state *st; + struct pohmelfs_config *c; + + mutex_lock(&psb->state_lock); + list_for_each_entry(c, &psb->state_list, config_entry) { + st = &c->state; + + pohmelfs_trans_scan_state(st); + } + mutex_unlock(&psb->state_lock); + + /* + * If no timeout specified then system is in the middle of umount process, + * so no need to reschedule scanning process again. + */ + if (psb->trans_scan_timeout) + schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout); +} + +int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon, + unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start) +{ + struct inode *inode = &pi->vfs_inode; + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + int err = 0, sz; + struct netfs_trans *t; + int path_len, addon_len = 0; + void *data; + struct netfs_inode_info *info; + struct netfs_cmd *cmd; + + dprintk("%s: ino: %llu, cmd: %u, addon: %p.\n", __func__, pi->ino, cmd_op, addon); + + path_len = pohmelfs_path_length(pi); + if (path_len < 0) { + err = path_len; + goto err_out_exit; + } + + if (addon) + addon_len = strlen(addon) + 1; /* 0-byte */ + sz = addon_len; + + if (cmd_op == NETFS_INODE_INFO) + sz += sizeof(struct netfs_inode_info); + + t = netfs_trans_alloc(psb, sz + path_len, flags, 0); + if (!t) { + err = -ENOMEM; + goto err_out_exit; + } + t->complete = complete; + t->private = priv; + + cmd = netfs_trans_current(t); + data = (void *)(cmd + 1); + + if (cmd_op == NETFS_INODE_INFO) { + info = (struct netfs_inode_info *)(cmd + 1); + data = (void *)(info + 1); + + /* + * We are under i_mutex, can read and change whatever we want... + */ + info->mode = inode->i_mode; + info->nlink = inode->i_nlink; + info->uid = inode->i_uid; + info->gid = inode->i_gid; + info->blocks = inode->i_blocks; + info->rdev = inode->i_rdev; + info->size = inode->i_size; + info->version = inode->i_version; + + netfs_convert_inode_info(info); + } + + path_len = pohmelfs_construct_path_string(pi, data, path_len); + if (path_len < 0) + goto err_out_free; + + dprintk("%s: path_len: %d.\n", __func__, path_len); + + if (addon) { + path_len--; /* Do not place null-byte before the addon */ + path_len += sprintf(data + path_len, "/%s", addon) + 1; /* 0 - byte */ + } + + sz += path_len; + + cmd->cmd = cmd_op; + cmd->ext = path_len; + cmd->size = sz; + cmd->id = id; + cmd->start = start; + + netfs_convert_cmd(cmd); + netfs_trans_update(cmd, t, sz); + + /* + * Note, that it is possible to leak error here: transaction callback will not + * be invoked for allocation path failure. + */ + return netfs_trans_finish(t, psb); + +err_out_free: + netfs_trans_free(t); +err_out_exit: + if (complete) + complete(NULL, 0, priv, err); + return err; +} + +int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags, + netfs_trans_complete_t complete, void *priv, u64 start) +{ + return pohmelfs_meta_command_data(pi, pi->ino, cmd_op, NULL, flags, complete, priv, start); +} + +/* + * Send request and wait for POHMELFS root capabilities response, + * which will update server's informaion about size of the export, + * permissions, number of objects, available size and so on. + */ +static int pohmelfs_root_handshake(struct pohmelfs_sb *psb) +{ + struct netfs_trans *t; + struct netfs_cmd *cmd; + int err = -ENOMEM; + + t = netfs_trans_alloc(psb, 0, 0, 0); + if (!t) + goto err_out_exit; + + cmd = netfs_trans_current(t); + + cmd->cmd = NETFS_CAPABILITIES; + cmd->id = POHMELFS_ROOT_CAPABILITIES; + cmd->size = 0; + cmd->start = 0; + cmd->ext = 0; + cmd->csize = 0; + + netfs_convert_cmd(cmd); + netfs_trans_update(cmd, t, 0); + + err = netfs_trans_finish(t, psb); + if (err) + goto err_out_exit; + + psb->flags = ~0; + err = wait_event_interruptible_timeout(psb->wait, + (psb->flags != ~0), + psb->wait_on_page_timeout); + if (!err) { + err = -ETIMEDOUT; + } else { + err = -psb->flags; + } + + if (err) + goto err_out_exit; + + return 0; + +err_out_exit: + return err; +} + +/* + * Allocate private superblock and create root dir. + */ +static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent) +{ + struct pohmelfs_sb *psb; + int err = -ENOMEM; + struct inode *root; + struct pohmelfs_inode *npi; + struct qstr str; + + pohmelfs_ftrans_init(); + + psb = kzalloc(sizeof(struct pohmelfs_sb), GFP_KERNEL); + if (!psb) + goto err_out_exit; + + sb->s_fs_info = psb; + sb->s_op = &pohmelfs_sb_ops; + sb->s_magic = POHMELFS_MAGIC_NUM; + sb->s_maxbytes = MAX_LFS_FILESIZE; + sb->s_blocksize = PAGE_SIZE; + + psb->sb = sb; + + psb->ino = 2; + psb->idx = 0; + psb->active_state = NULL; + psb->trans_retries = 5; + psb->trans_data_size = PAGE_SIZE; + psb->drop_scan_timeout = msecs_to_jiffies(1000); + psb->trans_scan_timeout = msecs_to_jiffies(5000); + psb->wait_on_page_timeout = msecs_to_jiffies(5000); + init_waitqueue_head(&psb->wait); + + spin_lock_init(&psb->ino_lock); + + INIT_LIST_HEAD(&psb->drop_list); + + mutex_init(&psb->mcache_lock); + psb->mcache_root = RB_ROOT; + psb->mcache_timeout = msecs_to_jiffies(5000); + atomic_long_set(&psb->mcache_gen, 0); + + psb->trans_max_pages = 100; + + psb->crypto_align_size = 16; + psb->crypto_attached_size = 0; + psb->hash_strlen = 0; + psb->cipher_strlen = 0; + psb->perform_crypto = 0; + psb->crypto_thread_num = 2; + psb->crypto_fail_unsupported = 0; + mutex_init(&psb->crypto_thread_lock); + INIT_LIST_HEAD(&psb->crypto_ready_list); + INIT_LIST_HEAD(&psb->crypto_active_list); + + atomic_set(&psb->trans_gen, 1); + atomic_set(&psb->total_inodes, 0); + + mutex_init(&psb->state_lock); + INIT_LIST_HEAD(&psb->state_list); + + err = pohmelfs_parse_options((char *) data, psb); + if (err) + goto err_out_free_sb; + + err = pohmelfs_copy_crypto(psb); + if (err) + goto err_out_free_sb; + + err = pohmelfs_state_init(psb); + if (err) + goto err_out_free_strings; + + err = pohmelfs_crypto_init(psb); + if (err) + goto err_out_state_exit; + + err = pohmelfs_root_handshake(psb); + if (err) + goto err_out_crypto_exit; + + str.name = "/"; + str.hash = jhash("/", 1, 0); + str.len = 1; + + npi = pohmelfs_create_entry_local(psb, NULL, &str, 0, 0755|S_IFDIR); + if (IS_ERR(npi)) { + err = PTR_ERR(npi); + goto err_out_crypto_exit; + } + + root = &npi->vfs_inode; + + sb->s_root = d_alloc_root(root); + if (!sb->s_root) + goto err_out_put_root; + + INIT_DELAYED_WORK(&psb->drop_dwork, pohmelfs_drop_scan); + schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout); + + INIT_DELAYED_WORK(&psb->dwork, pohmelfs_trans_scan); + schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout); + + return 0; + +err_out_put_root: + iput(root); +err_out_crypto_exit: + pohmelfs_crypto_exit(psb); +err_out_state_exit: + pohmelfs_state_exit(psb); +err_out_free_strings: + kfree(psb->cipher_string); + kfree(psb->hash_string); +err_out_free_sb: + kfree(psb); +err_out_exit: + + dprintk("%s: err: %d.\n", __func__, err); + return err; +} + +/* + * Some VFS magic here... + */ +static int pohmelfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_nodev(fs_type, flags, data, pohmelfs_fill_super, + mnt); +} + +static struct file_system_type pohmel_fs_type = { + .owner = THIS_MODULE, + .name = "pohmel", + .get_sb = pohmelfs_get_sb, + .kill_sb = kill_anon_super, +}; + +/* + * Cache and module initializations and freeing routings. + */ +static void pohmelfs_init_once(void *data) +{ + struct pohmelfs_inode *pi = data; + + inode_init_once(&pi->vfs_inode); +} + +static int __init pohmelfs_init_inodecache(void) +{ + pohmelfs_inode_cache = kmem_cache_create("pohmelfs_inode_cache", + sizeof(struct pohmelfs_inode), + 0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), + pohmelfs_init_once); + if (!pohmelfs_inode_cache) + return -ENOMEM; + + return 0; +} + +static void pohmelfs_destroy_inodecache(void) +{ + kmem_cache_destroy(pohmelfs_inode_cache); +} + +static int __init init_pohmel_fs(void) +{ + int err; + + err = pohmelfs_config_init(); + if (err) + goto err_out_exit; + + err = pohmelfs_init_inodecache(); + if (err) + goto err_out_config_exit; + + err = pohmelfs_mcache_init(); + if (err) + goto err_out_destroy; + + err = netfs_trans_init(); + if (err) + goto err_out_mcache_exit; + + err = register_filesystem(&pohmel_fs_type); + if (err) + goto err_out_trans; + + return 0; + +err_out_trans: + netfs_trans_exit(); +err_out_mcache_exit: + pohmelfs_mcache_exit(); +err_out_destroy: + pohmelfs_destroy_inodecache(); +err_out_config_exit: + pohmelfs_config_exit(); +err_out_exit: + return err; +} + +static void __exit exit_pohmel_fs(void) +{ + unregister_filesystem(&pohmel_fs_type); + pohmelfs_destroy_inodecache(); + pohmelfs_mcache_exit(); + pohmelfs_config_exit(); + netfs_trans_exit(); +} + +module_init(init_pohmel_fs); +module_exit(exit_pohmel_fs); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Evgeniy Polyakov "); +MODULE_DESCRIPTION("Pohmel filesystem"); diff --git a/drivers/staging/pohmelfs/lock.c b/drivers/staging/pohmelfs/lock.c new file mode 100644 index 000000000000..ad4a18559bdd --- /dev/null +++ b/drivers/staging/pohmelfs/lock.c @@ -0,0 +1,182 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#include "netfs.h" + +static int pohmelfs_send_lock_trans(struct pohmelfs_inode *pi, + u64 id, u64 start, u32 size, int type) +{ + struct inode *inode = &pi->vfs_inode; + struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); + struct netfs_trans *t; + struct netfs_cmd *cmd; + int path_len, err; + void *data; + struct netfs_lock *l; + int isize = (type & POHMELFS_LOCK_GRAB) ? 0 : sizeof(struct netfs_inode_info); + + err = pohmelfs_path_length(pi); + if (err < 0) + goto err_out_exit; + + path_len = err; + + err = -ENOMEM; + t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize, 0, 0); + if (!t) + goto err_out_exit; + + cmd = netfs_trans_current(t); + data = cmd + 1; + + err = pohmelfs_construct_path_string(pi, data, path_len); + if (err < 0) + goto err_out_free; + path_len = err; + + l = data + path_len; + + l->start = start; + l->size = size; + l->type = type; + l->ino = pi->ino; + + cmd->cmd = NETFS_LOCK; + cmd->start = 0; + cmd->id = id; + cmd->size = sizeof(struct netfs_lock) + path_len + isize; + cmd->ext = path_len; + cmd->csize = 0; + + netfs_convert_cmd(cmd); + netfs_convert_lock(l); + + if (isize) { + struct netfs_inode_info *info = (struct netfs_inode_info *)(l + 1); + + info->mode = inode->i_mode; + info->nlink = inode->i_nlink; + info->uid = inode->i_uid; + info->gid = inode->i_gid; + info->blocks = inode->i_blocks; + info->rdev = inode->i_rdev; + info->size = inode->i_size; + info->version = inode->i_version; + + netfs_convert_inode_info(info); + } + + netfs_trans_update(cmd, t, path_len + sizeof(struct netfs_lock) + isize); + + return netfs_trans_finish(t, psb); + +err_out_free: + netfs_trans_free(t); +err_out_exit: + printk("%s: err: %d.\n", __func__, err); + return err; +} + +int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); + struct pohmelfs_mcache *m; + int err = -ENOMEM; + struct iattr iattr; + struct inode *inode = &pi->vfs_inode; + + dprintk("%s: %p: ino: %llu, start: %llu, size: %u, " + "type: %d, locked as: %d, owned: %d.\n", + __func__, &pi->vfs_inode, pi->ino, + start, size, type, pi->lock_type, + !!test_bit(NETFS_INODE_OWNED, &pi->state)); + + if (!pohmelfs_need_lock(pi, type)) + return 0; + + m = pohmelfs_mcache_alloc(psb, start, size, NULL); + if (IS_ERR(m)) + return PTR_ERR(m); + + err = pohmelfs_send_lock_trans(pi, m->gen, start, size, + type | POHMELFS_LOCK_GRAB); + if (err) + goto err_out_put; + + err = wait_for_completion_timeout(&m->complete, psb->mcache_timeout); + if (err) + err = m->err; + else + err = -ETIMEDOUT; + + if (err) { + printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n", + __func__, &pi->vfs_inode, pi->ino, m->gen, start, size, err); + } + + if (err && (err != -ENOENT)) + goto err_out_put; + + if (!err) { + netfs_convert_inode_info(&m->info); + + iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | ATTR_ATIME; + iattr.ia_mode = m->info.mode; + iattr.ia_uid = m->info.uid; + iattr.ia_gid = m->info.gid; + iattr.ia_size = m->info.size; + iattr.ia_atime = CURRENT_TIME; + + dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n", + __func__, &pi->vfs_inode, pi->ino, m->gen, start, inode->i_size, m->info.size); + + err = pohmelfs_setattr_raw(inode, &iattr); + if (!err) { + struct dentry *dentry = d_find_alias(inode); + if (dentry) { + fsnotify_change(dentry, iattr.ia_valid); + dput(dentry); + } + } + } + + pi->lock_type = type; + set_bit(NETFS_INODE_OWNED, &pi->state); + + pohmelfs_mcache_put(psb, m); + + return 0; + +err_out_put: + pohmelfs_mcache_put(psb, m); + return err; +} + +int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type) +{ + dprintk("%s: %p: ino: %llu, start: %llu, size: %u, type: %d.\n", + __func__, &pi->vfs_inode, pi->ino, start, size, type); + pi->lock_type = 0; + clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state); + clear_bit(NETFS_INODE_OWNED, &pi->state); + return pohmelfs_send_lock_trans(pi, pi->ino, start, size, type); +} diff --git a/drivers/staging/pohmelfs/mcache.c b/drivers/staging/pohmelfs/mcache.c new file mode 100644 index 000000000000..e22665cdd16c --- /dev/null +++ b/drivers/staging/pohmelfs/mcache.c @@ -0,0 +1,171 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include + +#include "netfs.h" + +static struct kmem_cache *pohmelfs_mcache_cache; +static mempool_t *pohmelfs_mcache_pool; + +static inline int pohmelfs_mcache_cmp(u64 gen, u64 new) +{ + if (gen < new) + return 1; + if (gen > new) + return -1; + return 0; +} + +struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen) +{ + struct rb_root *root = &psb->mcache_root; + struct rb_node *n = root->rb_node; + struct pohmelfs_mcache *tmp, *ret = NULL; + int cmp; + + while (n) { + tmp = rb_entry(n, struct pohmelfs_mcache, mcache_entry); + + cmp = pohmelfs_mcache_cmp(tmp->gen, gen); + if (cmp < 0) + n = n->rb_left; + else if (cmp > 0) + n = n->rb_right; + else { + ret = tmp; + pohmelfs_mcache_get(ret); + break; + } + } + + return ret; +} + +static int pohmelfs_mcache_insert(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m) +{ + struct rb_root *root = &psb->mcache_root; + struct rb_node **n = &root->rb_node, *parent = NULL; + struct pohmelfs_mcache *ret = NULL, *tmp; + int cmp; + + while (*n) { + parent = *n; + + tmp = rb_entry(parent, struct pohmelfs_mcache, mcache_entry); + + cmp = pohmelfs_mcache_cmp(tmp->gen, m->gen); + if (cmp < 0) + n = &parent->rb_left; + else if (cmp > 0) + n = &parent->rb_right; + else { + ret = tmp; + break; + } + } + + if (ret) + return -EEXIST; + + rb_link_node(&m->mcache_entry, parent, n); + rb_insert_color(&m->mcache_entry, root); + + return 0; +} + +static int pohmelfs_mcache_remove(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m) +{ + if (m && m->mcache_entry.rb_parent_color) { + rb_erase(&m->mcache_entry, &psb->mcache_root); + m->mcache_entry.rb_parent_color = 0; + return 1; + } + return 0; +} + +void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m) +{ + mutex_lock(&psb->mcache_lock); + pohmelfs_mcache_remove(psb, m); + mutex_unlock(&psb->mcache_lock); +} + +struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start, + unsigned int size, void *data) +{ + struct pohmelfs_mcache *m; + int err = -ENOMEM; + + m = mempool_alloc(pohmelfs_mcache_pool, GFP_KERNEL); + if (!m) + goto err_out_exit; + + init_completion(&m->complete); + m->err = 0; + atomic_set(&m->refcnt, 1); + m->data = data; + m->start = start; + m->size = size; + m->gen = atomic_long_inc_return(&psb->mcache_gen); + + mutex_lock(&psb->mcache_lock); + err = pohmelfs_mcache_insert(psb, m); + mutex_unlock(&psb->mcache_lock); + if (err) + goto err_out_free; + + return m; + +err_out_free: + mempool_free(m, pohmelfs_mcache_pool); +err_out_exit: + return ERR_PTR(err); +} + +void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m) +{ + pohmelfs_mcache_remove_locked(psb, m); + + mempool_free(m, pohmelfs_mcache_pool); +} + +int __init pohmelfs_mcache_init(void) +{ + pohmelfs_mcache_cache = kmem_cache_create("pohmelfs_mcache_cache", + sizeof(struct pohmelfs_mcache), + 0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), NULL); + if (!pohmelfs_mcache_cache) + goto err_out_exit; + + pohmelfs_mcache_pool = mempool_create_slab_pool(256, pohmelfs_mcache_cache); + if (!pohmelfs_mcache_pool) + goto err_out_free; + + return 0; + +err_out_free: + kmem_cache_destroy(pohmelfs_mcache_cache); +err_out_exit: + return -ENOMEM; +} + +void pohmelfs_mcache_exit(void) +{ + mempool_destroy(pohmelfs_mcache_pool); + kmem_cache_destroy(pohmelfs_mcache_cache); +} diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c new file mode 100644 index 000000000000..c9b8540c1efe --- /dev/null +++ b/drivers/staging/pohmelfs/net.c @@ -0,0 +1,1247 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netfs.h" + +static int pohmelfs_ftrans_size = 10240; +static u32 *pohmelfs_ftrans; + +int pohmelfs_ftrans_init(void) +{ + pohmelfs_ftrans = vmalloc(pohmelfs_ftrans_size * 4); + if (!pohmelfs_ftrans) + return -ENOMEM; + + return 0; +} + +void pohmelfs_ftrans_exit(void) +{ + vfree(pohmelfs_ftrans); +} + +void pohmelfs_ftrans_clean(u64 id) +{ + if (pohmelfs_ftrans) { + u32 i = id & 0xffffffff; + int idx = i % pohmelfs_ftrans_size; + + pohmelfs_ftrans[idx] = 0; + } +} + +void pohmelfs_ftrans_update(u64 id) +{ + if (pohmelfs_ftrans) { + u32 i = id & 0xffffffff; + int idx = i % pohmelfs_ftrans_size; + + pohmelfs_ftrans[idx] = i; + } +} + +int pohmelfs_ftrans_check(u64 id) +{ + if (pohmelfs_ftrans) { + u32 i = id & 0xffffffff; + int idx = i % pohmelfs_ftrans_size; + + return (pohmelfs_ftrans[idx] == i); + } + + return -1; +} + +/* + * Async machinery lives here. + * All commands being sent to server do _not_ require sync reply, + * instead, if it is really needed, like readdir or readpage, caller + * sleeps waiting for data, which will be placed into provided buffer + * and caller will be awakened. + * + * Every command response can come without some listener. For example + * readdir response will add new objects into cache without appropriate + * request from userspace. This is used in cache coherency. + * + * If object is not found for given data, it is discarded. + * + * All requests are received by dedicated kernel thread. + */ + +/* + * Basic network sending/receiving functions. + * Blocked mode is used. + */ +static int netfs_data_recv(struct netfs_state *st, void *buf, u64 size) +{ + struct msghdr msg; + struct kvec iov; + int err; + + BUG_ON(!size); + + iov.iov_base = buf; + iov.iov_len = size; + + msg.msg_iov = (struct iovec *)&iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = MSG_DONTWAIT; + + err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len, + msg.msg_flags); + if (err <= 0) { + printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__, size, err); + if (err == 0) + err = -ECONNRESET; + } + + return err; +} + +static int pohmelfs_data_recv(struct netfs_state *st, void *data, unsigned int size) +{ + unsigned int revents = 0; + unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; + unsigned int mask = err_mask | POLLIN; + int err = 0; + + while (size && !err) { + revents = netfs_state_poll(st); + + if (!(revents & mask)) { + DEFINE_WAIT(wait); + + for (;;) { + prepare_to_wait(&st->thread_wait, &wait, TASK_INTERRUPTIBLE); + if (kthread_should_stop()) + break; + + revents = netfs_state_poll(st); + + if (revents & mask) + break; + + if (signal_pending(current)) + break; + + schedule(); + continue; + } + finish_wait(&st->thread_wait, &wait); + } + + err = 0; + netfs_state_lock(st); + if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) { + err = netfs_data_recv(st, data, size); + if (err > 0) { + data += err; + size -= err; + err = 0; + } else if (err == 0) + err = -ECONNRESET; + } + + if (revents & err_mask) { + printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n", + __func__, revents, st->socket, size, err); + err = -ECONNRESET; + } + netfs_state_unlock(st); + + if (err < 0) { + if (netfs_state_trylock_send(st)) { + netfs_state_exit(st); + err = netfs_state_init(st); + if (!err) + err = -EAGAIN; + netfs_state_unlock_send(st); + } else { + st->need_reset = 1; + } + } + + if (kthread_should_stop()) + err = -ENODEV; + + if (err) + printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, " + "should_stop: %d, size: %u, err: %d.\n", + __func__, st->socket, st->read_socket, + revents, revents & err_mask, kthread_should_stop(), size, err); + } + + return err; +} + +int pohmelfs_data_recv_and_check(struct netfs_state *st, void *data, unsigned int size) +{ + struct netfs_cmd *cmd = &st->cmd; + int err; + + err = pohmelfs_data_recv(st, data, size); + if (err) + return err; + + return pohmelfs_crypto_process_input_data(&st->eng, cmd->iv, data, NULL, size); +} + +/* + * Polling machinery. + */ + +struct netfs_poll_helper +{ + poll_table pt; + struct netfs_state *st; +}; + +static int netfs_queue_wake(wait_queue_t *wait, unsigned mode, int sync, void *key) +{ + struct netfs_state *st = container_of(wait, struct netfs_state, wait); + + wake_up(&st->thread_wait); + return 1; +} + +static void netfs_queue_func(struct file *file, wait_queue_head_t *whead, + poll_table *pt) +{ + struct netfs_state *st = container_of(pt, struct netfs_poll_helper, pt)->st; + + st->whead = whead; + init_waitqueue_func_entry(&st->wait, netfs_queue_wake); + add_wait_queue(whead, &st->wait); +} + +static void netfs_poll_exit(struct netfs_state *st) +{ + if (st->whead) { + remove_wait_queue(st->whead, &st->wait); + st->whead = NULL; + } +} + +static int netfs_poll_init(struct netfs_state *st) +{ + struct netfs_poll_helper ph; + + ph.st = st; + init_poll_funcptr(&ph.pt, &netfs_queue_func); + + st->socket->ops->poll(NULL, st->socket, &ph.pt); + return 0; +} + +/* + * Get response for readpage command. We search inode and page in its mapping + * and copy data into. If it was async request, then we queue page into shared + * data and wakeup listener, who will copy it to userspace. + * + * There is a work in progress of allowing to call copy_to_user() directly from + * async receiving kernel thread. + */ +static int pohmelfs_read_page_response(struct netfs_state *st) +{ + struct pohmelfs_sb *psb = st->psb; + struct netfs_cmd *cmd = &st->cmd; + struct inode *inode; + struct page *page; + int err = 0; + + if (cmd->size > PAGE_CACHE_SIZE) { + err = -EINVAL; + goto err_out_exit; + } + + inode = ilookup(st->psb->sb, cmd->id); + if (!inode) { + printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id); + err = -ENOENT; + goto err_out_exit; + } + + page = find_get_page(inode->i_mapping, cmd->start >> PAGE_CACHE_SHIFT); + if (!page || !PageLocked(page)) { + printk("%s: failed to find/lock page: page: %p, id: %llu, start: %llu, index: %llu.\n", + __func__, page, cmd->id, cmd->start, cmd->start >> PAGE_CACHE_SHIFT); + + while (cmd->size) { + unsigned int sz = min(cmd->size, st->size); + + err = pohmelfs_data_recv(st, st->data, sz); + if (err) + break; + + cmd->size -= sz; + } + + err = -ENODEV; + if (page) + goto err_out_page_put; + goto err_out_put; + } + + if (cmd->size) { + void *addr; + + addr = kmap(page); + err = pohmelfs_data_recv(st, addr, cmd->size); + kunmap(page); + + if (err) + goto err_out_page_unlock; + } + + dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n", + __func__, page, cmd->start, cmd->size, PageLocked(page)); + + SetPageChecked(page); + if ((psb->hash_string || psb->cipher_string) && psb->perform_crypto && cmd->size) { + err = pohmelfs_crypto_process_input_page(&st->eng, page, cmd->size, cmd->iv); + if (err < 0) + goto err_out_page_unlock; + } else { + SetPageUptodate(page); + unlock_page(page); + page_cache_release(page); + } + + pohmelfs_put_inode(POHMELFS_I(inode)); + wake_up(&st->psb->wait); + + return 0; + +err_out_page_unlock: + SetPageError(page); + unlock_page(page); +err_out_page_put: + page_cache_release(page); +err_out_put: + pohmelfs_put_inode(POHMELFS_I(inode)); +err_out_exit: + wake_up(&st->psb->wait); + return err; +} + +static int pohmelfs_check_name(struct pohmelfs_inode *parent, struct qstr *str, + struct netfs_inode_info *info) +{ + struct inode *inode; + struct pohmelfs_name *n; + int err = 0; + u64 ino = 0; + + mutex_lock(&parent->offset_lock); + n = pohmelfs_search_hash(parent, str->hash); + if (n) + ino = n->ino; + mutex_unlock(&parent->offset_lock); + + if (!ino) + goto out; + + inode = ilookup(parent->vfs_inode.i_sb, ino); + if (!inode) + goto out; + + dprintk("%s: parent: %llu, inode: %llu.\n", __func__, parent->ino, ino); + + pohmelfs_fill_inode(inode, info); + pohmelfs_put_inode(POHMELFS_I(inode)); + err = -EEXIST; +out: + return err; +} + +/* + * Readdir response from server. If special field is set, we wakeup + * listener (readdir() call), which will copy data to userspace. + */ +static int pohmelfs_readdir_response(struct netfs_state *st) +{ + struct inode *inode; + struct netfs_cmd *cmd = &st->cmd; + struct netfs_inode_info *info; + struct pohmelfs_inode *parent = NULL, *npi; + int err = 0, last = cmd->ext; + struct qstr str; + + if (cmd->size > st->size) + return -EINVAL; + + inode = ilookup(st->psb->sb, cmd->id); + if (!inode) { + printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id); + return -ENOENT; + } + parent = POHMELFS_I(inode); + + if (!cmd->size && cmd->start) { + err = -cmd->start; + goto out; + } + + if (cmd->size) { + char *name; + + err = pohmelfs_data_recv_and_check(st, st->data, cmd->size); + if (err) + goto err_out_put; + + info = (struct netfs_inode_info *)(st->data); + + name = (char *)(info + 1); + str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad; + name[str.len] = 0; + str.name = name; + str.hash = jhash(str.name, str.len, 0); + + netfs_convert_inode_info(info); + + if (parent) { + err = pohmelfs_check_name(parent, &str, info); + if (err) { + if (err == -EEXIST) + err = 0; + goto out; + } + } + + info->ino = cmd->start; + if (!info->ino) + info->ino = pohmelfs_new_ino(st->psb); + + dprintk("%s: parent: %llu, ino: %llu, name: '%s', hash: %x, len: %u, mode: %o.\n", + __func__, parent->ino, info->ino, str.name, str.hash, str.len, + info->mode); + + npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0); + if (IS_ERR(npi)) { + err = PTR_ERR(npi); + + if (err != -EEXIST) + goto err_out_put; + } else { + set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state); + clear_bit(NETFS_INODE_OWNED, &npi->state); + } + } +out: + if (last) { + set_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state); + set_bit(NETFS_INODE_REMOTE_SYNCED, &parent->state); + wake_up(&st->psb->wait); + } + pohmelfs_put_inode(parent); + + return err; + +err_out_put: + clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state); + printk("%s: parent: %llu, ino: %llu, cmd_id: %llu.\n", __func__, parent->ino, cmd->start, cmd->id); + pohmelfs_put_inode(parent); + wake_up(&st->psb->wait); + return err; +} + +/* + * Lookup command response. + * It searches for inode to be looked at (if it exists) and substitutes + * its inode information (size, permission, mode and so on), if inode does + * not exist, new one will be created and inserted into caches. + */ +static int pohmelfs_lookup_response(struct netfs_state *st) +{ + struct inode *inode = NULL; + struct netfs_cmd *cmd = &st->cmd; + struct netfs_inode_info *info; + struct pohmelfs_inode *parent = NULL, *npi; + int err = -EINVAL; + char *name; + + inode = ilookup(st->psb->sb, cmd->id); + if (!inode) { + printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n", + __func__, cmd->id, cmd->start, cmd->size); + err = -ENOENT; + goto err_out_exit; + } + parent = POHMELFS_I(inode); + + if (!cmd->size) { + err = -cmd->start; + goto err_out_put; + } + + if (cmd->size < sizeof(struct netfs_inode_info)) { + printk("%s: broken lookup response: id: %llu, start: %llu, size: %u.\n", + __func__, cmd->id, cmd->start, cmd->size); + err = -EINVAL; + goto err_out_put; + } + + err = pohmelfs_data_recv_and_check(st, st->data, cmd->size); + if (err) + goto err_out_put; + + info = (struct netfs_inode_info *)(st->data); + name = (char *)(info + 1); + + netfs_convert_inode_info(info); + + info->ino = cmd->start; + if (!info->ino) + info->ino = pohmelfs_new_ino(st->psb); + + dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n", + __func__, parent->ino, info->ino, name, cmd->start); + + if (cmd->start) + npi = pohmelfs_new_inode(st->psb, parent, NULL, info, 0); + else { + struct qstr str; + + str.name = name; + str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad; + str.hash = jhash(name, str.len, 0); + + npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0); + } + if (IS_ERR(npi)) { + err = PTR_ERR(npi); + + if (err != -EEXIST) + goto err_out_put; + } else { + set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state); + clear_bit(NETFS_INODE_OWNED, &npi->state); + } + + clear_bit(NETFS_COMMAND_PENDING, &parent->state); + pohmelfs_put_inode(parent); + + wake_up(&st->psb->wait); + + return 0; + +err_out_put: + pohmelfs_put_inode(parent); +err_out_exit: + clear_bit(NETFS_COMMAND_PENDING, &parent->state); + wake_up(&st->psb->wait); + printk("%s: inode: %p, id: %llu, start: %llu, size: %u, err: %d.\n", + __func__, inode, cmd->id, cmd->start, cmd->size, err); + return err; +} + +/* + * Create response, just marks local inode as 'created', so that writeback + * for any of its children (or own) would not try to sync it again. + */ +static int pohmelfs_create_response(struct netfs_state *st) +{ + struct inode *inode; + struct netfs_cmd *cmd = &st->cmd; + struct pohmelfs_inode *pi; + + inode = ilookup(st->psb->sb, cmd->id); + if (!inode) { + printk("%s: failed to find inode: id: %llu, start: %llu.\n", + __func__, cmd->id, cmd->start); + goto err_out_exit; + } + + pi = POHMELFS_I(inode); + + /* + * To lock or not to lock? + * We actually do not care if it races... + */ + if (cmd->start) + make_bad_inode(inode); + set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); + + pohmelfs_put_inode(pi); + + wake_up(&st->psb->wait); + return 0; + +err_out_exit: + wake_up(&st->psb->wait); + return -ENOENT; +} + +/* + * Object remove response. Just says that remove request has been received. + * Used in cache coherency protocol. + */ +static int pohmelfs_remove_response(struct netfs_state *st) +{ + struct netfs_cmd *cmd = &st->cmd; + int err; + + err = pohmelfs_data_recv_and_check(st, st->data, cmd->size); + if (err) + return err; + + dprintk("%s: parent: %llu, path: '%s'.\n", __func__, cmd->id, (char *)st->data); + + return 0; +} + +/* + * Transaction reply processing. + * + * Find transaction based on its generation number, bump its reference counter, + * so that none could free it under us, drop from the trees and lists and + * drop reference counter. When it hits zero (when all destinations replied + * and all timeout handled by async scanning code), completion will be called + * and transaction will be freed. + */ +static int pohmelfs_transaction_response(struct netfs_state *st) +{ + struct netfs_trans_dst *dst; + struct netfs_trans *t = NULL; + struct netfs_cmd *cmd = &st->cmd; + short err = (signed)cmd->ext; + + mutex_lock(&st->trans_lock); + dst = netfs_trans_search(st, cmd->start); + if (dst) { + netfs_trans_remove_nolock(dst, st); + t = dst->trans; + + pohmelfs_ftrans_update(cmd->start); + } + mutex_unlock(&st->trans_lock); + + if (!t) { + int check = pohmelfs_ftrans_check(cmd->start); + printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u, double: %d.\n", + __func__, cmd->start, cmd->id, cmd->size, cmd->ext, check); + err = -EINVAL; + goto out; + } + + t->result = err; + netfs_trans_drop_dst_nostate(dst); + +out: + wake_up(&st->psb->wait); + return err; +} + +/* + * Inode metadata cache coherency message. + */ +static int pohmelfs_page_cache_response(struct netfs_state *st) +{ + struct netfs_cmd *cmd = &st->cmd; + struct inode *inode; + + dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__, st, cmd->id, cmd->start, cmd->size); + + inode = ilookup(st->psb->sb, cmd->id); + if (!inode) { + printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id); + return -ENOENT; + } + + set_bit(NETFS_INODE_NEED_FLUSH, &POHMELFS_I(inode)->state); + pohmelfs_put_inode(POHMELFS_I(inode)); + + return 0; +} + +/* + * Root capabilities response: export statistics + * like used and available size, number of files and dirs, + * permissions. + */ +static int pohmelfs_root_cap_response(struct netfs_state *st) +{ + struct netfs_cmd *cmd = &st->cmd; + struct netfs_root_capabilities *cap; + struct pohmelfs_sb *psb = st->psb; + + if (cmd->size != sizeof(struct netfs_root_capabilities)) { + psb->flags = EPROTO; + wake_up(&psb->wait); + return -EPROTO; + } + + cap = st->data; + + netfs_convert_root_capabilities(cap); + + if (psb->total_size < cap->used + cap->avail) + psb->total_size = cap->used + cap->avail; + if (cap->avail) + psb->avail_size = cap->avail; + psb->state_flags = cap->flags; + + if (psb->state_flags & POHMELFS_FLAGS_RO) { + psb->sb->s_flags |= MS_RDONLY; + printk(KERN_INFO "Mounting POHMELFS (%d) read-only.\n", psb->idx); + } + + if (psb->state_flags & POHMELFS_FLAGS_XATTR) + printk(KERN_INFO "Mounting POHMELFS (%d) " + "with extended attributes support.\n", psb->idx); + + if (atomic_read(&psb->total_inodes) <= 1) + atomic_long_set(&psb->total_inodes, cap->nr_files); + + dprintk("%s: total: %llu, avail: %llu, flags: %llx, inodes: %llu.\n", + __func__, psb->total_size, psb->avail_size, psb->state_flags, cap->nr_files); + + psb->flags = 0; + wake_up(&psb->wait); + return 0; +} + +/* + * Crypto capabilities of the server, where it says that + * it supports or does not requested hash/cipher algorithms. + */ +static int pohmelfs_crypto_cap_response(struct netfs_state *st) +{ + struct netfs_cmd *cmd = &st->cmd; + struct netfs_crypto_capabilities *cap; + struct pohmelfs_sb *psb = st->psb; + int err = 0; + + if (cmd->size != sizeof(struct netfs_crypto_capabilities)) { + psb->flags = EPROTO; + wake_up(&psb->wait); + return -EPROTO; + } + + cap = st->data; + + dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n", + __func__, + psb->cipher_string, (cap->cipher_strlen)?"SUPPORTED":"NOT SUPPORTED", + psb->hash_string, (cap->hash_strlen)?"SUPPORTED":"NOT SUPPORTED"); + + if (!cap->hash_strlen) { + if (psb->hash_strlen && psb->crypto_fail_unsupported) + err = -ENOTSUPP; + psb->hash_strlen = 0; + kfree(psb->hash_string); + psb->hash_string = NULL; + } + + if (!cap->cipher_strlen) { + if (psb->cipher_strlen && psb->crypto_fail_unsupported) + err = -ENOTSUPP; + psb->cipher_strlen = 0; + kfree(psb->cipher_string); + psb->cipher_string = NULL; + } + + return err; +} + +/* + * Capabilities handshake response. + */ +static int pohmelfs_capabilities_response(struct netfs_state *st) +{ + struct netfs_cmd *cmd = &st->cmd; + int err = 0; + + err = pohmelfs_data_recv(st, st->data, cmd->size); + if (err) + return err; + + switch (cmd->id) { + case POHMELFS_CRYPTO_CAPABILITIES: + return pohmelfs_crypto_cap_response(st); + case POHMELFS_ROOT_CAPABILITIES: + return pohmelfs_root_cap_response(st); + default: + break; + } + return -EINVAL; +} + +/* + * Receiving extended attribute. + * Does not work properly if received size is more than requested one, + * it should not happen with current request/reply model though. + */ +static int pohmelfs_getxattr_response(struct netfs_state *st) +{ + struct pohmelfs_sb *psb = st->psb; + struct netfs_cmd *cmd = &st->cmd; + struct pohmelfs_mcache *m; + short error = (signed short)cmd->ext, err; + unsigned int sz, total_size; + + m = pohmelfs_mcache_search(psb, cmd->id); + + dprintk("%s: id: %llu, gen: %llu, err: %d.\n", + __func__, cmd->id, (m)?m->gen:0, error); + + if (!m) { + printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__, cmd->id); + return -ENOENT; + } + + if (cmd->size) { + sz = min_t(unsigned int, cmd->size, m->size); + err = pohmelfs_data_recv_and_check(st, m->data, sz); + if (err) { + error = err; + goto out; + } + + m->size = sz; + total_size = cmd->size - sz; + + while (total_size) { + sz = min(total_size, st->size); + + err = pohmelfs_data_recv_and_check(st, st->data, sz); + if (err) { + error = err; + break; + } + + total_size -= sz; + } + } + +out: + m->err = error; + complete(&m->complete); + pohmelfs_mcache_put(psb, m); + + return error; +} + +int pohmelfs_data_lock_response(struct netfs_state *st) +{ + struct pohmelfs_sb *psb = st->psb; + struct netfs_cmd *cmd = &st->cmd; + struct pohmelfs_mcache *m; + short err = (signed short)cmd->ext; + u64 id = cmd->id; + + m = pohmelfs_mcache_search(psb, id); + + dprintk("%s: id: %llu, gen: %llu, err: %d.\n", + __func__, cmd->id, (m)?m->gen:0, err); + + if (!m) { + pohmelfs_data_recv(st, st->data, cmd->size); + printk("%s: failed to find data lock response: id: %llu.\n", __func__, cmd->id); + return -ENOENT; + } + + if (cmd->size) + err = pohmelfs_data_recv_and_check(st, &m->info, cmd->size); + + m->err = err; + complete(&m->complete); + pohmelfs_mcache_put(psb, m); + + return err; +} + +static void __inline__ netfs_state_reset(struct netfs_state *st) +{ + netfs_state_lock_send(st); + netfs_state_exit(st); + netfs_state_init(st); + netfs_state_unlock_send(st); +} + +/* + * Main receiving function, called from dedicated kernel thread. + */ +static int pohmelfs_recv(void *data) +{ + int err = -EINTR; + struct netfs_state *st = data; + struct netfs_cmd *cmd = &st->cmd; + + while (!kthread_should_stop()) { + /* + * If socket will be reset after this statement, then + * pohmelfs_data_recv() will just fail and loop will + * start again, so it can be done without any locks. + * + * st->read_socket is needed to prevents state machine + * breaking between this data reading and subsequent one + * in protocol specific functions during connection reset. + * In case of reset we have to read next command and do + * not expect data for old command to magically appear in + * new connection. + */ + st->read_socket = st->socket; + err = pohmelfs_data_recv(st, cmd, sizeof(struct netfs_cmd)); + if (err) { + msleep(1000); + continue; + } + + netfs_convert_cmd(cmd); + + dprintk("%s: cmd: %u, id: %llu, start: %llu, size: %u, " + "ext: %u, csize: %u, cpad: %u.\n", + __func__, cmd->cmd, cmd->id, cmd->start, + cmd->size, cmd->ext, cmd->csize, cmd->cpad); + + if (cmd->csize) { + struct pohmelfs_crypto_engine *e = &st->eng; + + if (unlikely(cmd->csize > e->size/2)) { + netfs_state_reset(st); + continue; + } + + if (e->hash && unlikely(cmd->csize != st->psb->crypto_attached_size)) { + dprintk("%s: cmd: cmd: %u, id: %llu, start: %llu, size: %u, " + "csize: %u != digest size %u.\n", + __func__, cmd->cmd, cmd->id, cmd->start, cmd->size, + cmd->csize, st->psb->crypto_attached_size); + netfs_state_reset(st); + continue; + } + + err = pohmelfs_data_recv(st, e->data, cmd->csize); + if (err) { + netfs_state_reset(st); + continue; + } + +#ifdef CONFIG_POHMELFS_DEBUG + { + unsigned int i; + unsigned char *hash = e->data; + + dprintk("%s: received hash: ", __func__); + for (i=0; icsize; ++i) { + printk("%02x ", hash[i]); + } + printk("\n"); + } +#endif + cmd->size -= cmd->csize; + } + + /* + * This should catch protocol breakage and random garbage instead of commands. + */ + if (unlikely((cmd->size > st->size) && (cmd->cmd != NETFS_XATTR_GET))) { + netfs_state_reset(st); + continue; + } + + switch (cmd->cmd) { + case NETFS_READ_PAGE: + err = pohmelfs_read_page_response(st); + break; + case NETFS_READDIR: + err = pohmelfs_readdir_response(st); + break; + case NETFS_LOOKUP: + err = pohmelfs_lookup_response(st); + break; + case NETFS_CREATE: + err = pohmelfs_create_response(st); + break; + case NETFS_REMOVE: + err = pohmelfs_remove_response(st); + break; + case NETFS_TRANS: + err = pohmelfs_transaction_response(st); + break; + case NETFS_PAGE_CACHE: + err = pohmelfs_page_cache_response(st); + break; + case NETFS_CAPABILITIES: + err = pohmelfs_capabilities_response(st); + break; + case NETFS_LOCK: + err = pohmelfs_data_lock_response(st); + break; + case NETFS_XATTR_GET: + err = pohmelfs_getxattr_response(st); + break; + default: + printk("%s: wrong cmd: %u, id: %llu, start: %llu, size: %u, ext: %u.\n", + __func__, cmd->cmd, cmd->id, cmd->start, cmd->size, cmd->ext); + netfs_state_reset(st); + break; + } + } + + while (!kthread_should_stop()) + schedule_timeout_uninterruptible(msecs_to_jiffies(10)); + + return err; +} + +int netfs_state_init(struct netfs_state *st) +{ + int err; + struct pohmelfs_ctl *ctl = &st->ctl; + + err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &st->socket); + if (err) { + printk("%s: failed to create a socket: family: %d, type: %d, proto: %d, err: %d.\n", + __func__, ctl->addr.sa_family, ctl->type, ctl->proto, err); + goto err_out_exit; + } + + st->socket->sk->sk_allocation = GFP_NOIO; + st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000); + + err = kernel_connect(st->socket, (struct sockaddr *)&ctl->addr, ctl->addrlen, 0); + if (err) { + printk("%s: failed to connect to server: idx: %u, err: %d.\n", + __func__, st->psb->idx, err); + goto err_out_release; + } + st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000); + + err = netfs_poll_init(st); + if (err) + goto err_out_release; + + if (st->socket->ops->family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)&ctl->addr; + printk(KERN_INFO "%s: (re)connected to peer %u.%u.%u.%u:%d.\n", __func__, + NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); + } else if (st->socket->ops->family == AF_INET6) { + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&ctl->addr; + printk(KERN_INFO "%s: (re)connected to peer " + "%pi6:%d", + __func__, &sin->sin6_addr, ntohs(sin->sin6_port)); + } + + return 0; + +err_out_release: + sock_release(st->socket); +err_out_exit: + st->socket = NULL; + return err; +} + +void netfs_state_exit(struct netfs_state *st) +{ + if (st->socket) { + netfs_poll_exit(st); + st->socket->ops->shutdown(st->socket, 2); + + if (st->socket->ops->family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr; + printk("%s: disconnected from peer %u.%u.%u.%u:%d.\n", __func__, + NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); + } else if (st->socket->ops->family == AF_INET6) { + struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr; + printk("%s: disconnected from peer " + "%pi6:%d", + __func__, &sin->sin6_addr, ntohs(sin->sin6_port)); + } + + sock_release(st->socket); + st->socket = NULL; + st->read_socket = NULL; + st->need_reset = 0; + } +} + +int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf) +{ + struct netfs_state *st = &conf->state; + int err = -ENOMEM; + + mutex_init(&st->__state_lock); + mutex_init(&st->__state_send_lock); + init_waitqueue_head(&st->thread_wait); + + st->psb = psb; + st->trans_root = RB_ROOT; + mutex_init(&st->trans_lock); + + st->size = psb->trans_data_size; + st->data = kmalloc(st->size, GFP_KERNEL); + if (!st->data) + goto err_out_exit; + + if (psb->perform_crypto) { + err = pohmelfs_crypto_engine_init(&st->eng, psb); + if (err) + goto err_out_free_data; + } + + err = netfs_state_init(st); + if (err) + goto err_out_free_engine; + + st->thread = kthread_run(pohmelfs_recv, st, "pohmelfs/%u", psb->idx); + if (IS_ERR(st->thread)) { + err = PTR_ERR(st->thread); + goto err_out_netfs_exit; + } + + if (!psb->active_state) + psb->active_state = conf; + + dprintk("%s: conf: %p, st: %p, socket: %p.\n", + __func__, conf, st, st->socket); + return 0; + +err_out_netfs_exit: + netfs_state_exit(st); +err_out_free_engine: + pohmelfs_crypto_engine_exit(&st->eng); +err_out_free_data: + kfree(st->data); +err_out_exit: + return err; + +} + +void pohmelfs_state_flush_transactions(struct netfs_state *st) +{ + struct rb_node *rb_node; + struct netfs_trans_dst *dst; + + mutex_lock(&st->trans_lock); + for (rb_node = rb_first(&st->trans_root); rb_node; ) { + dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry); + rb_node = rb_next(rb_node); + + dst->trans->result = -EINVAL; + netfs_trans_remove_nolock(dst, st); + netfs_trans_drop_dst_nostate(dst); + } + mutex_unlock(&st->trans_lock); +} + +static void pohmelfs_state_exit_one(struct pohmelfs_config *c) +{ + struct netfs_state *st = &c->state; + + dprintk("%s: exiting, st: %p.\n", __func__, st); + if (st->thread) { + kthread_stop(st->thread); + st->thread = NULL; + } + + netfs_state_lock_send(st); + netfs_state_exit(st); + netfs_state_unlock_send(st); + + pohmelfs_state_flush_transactions(st); + + pohmelfs_crypto_engine_exit(&st->eng); + kfree(st->data); + + kfree(c); +} + +/* + * Initialize network stack. It searches for given ID in global + * configuration table, this contains information of the remote server + * (address (any supported by socket interface) and port, protocol and so on). + */ +int pohmelfs_state_init(struct pohmelfs_sb *psb) +{ + int err = -ENOMEM; + + err = pohmelfs_copy_config(psb); + if (err) { + pohmelfs_state_exit(psb); + return err; + } + + return 0; +} + +void pohmelfs_state_exit(struct pohmelfs_sb *psb) +{ + struct pohmelfs_config *c, *tmp; + + list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) { + list_del(&c->config_entry); + pohmelfs_state_exit_one(c); + } +} + +void pohmelfs_switch_active(struct pohmelfs_sb *psb) +{ + struct pohmelfs_config *c = psb->active_state; + + if (!list_empty(&psb->state_list)) { + if (c->config_entry.next != &psb->state_list) { + psb->active_state = list_entry(c->config_entry.next, + struct pohmelfs_config, config_entry); + } else { + psb->active_state = list_entry(psb->state_list.next, + struct pohmelfs_config, config_entry); + } + + dprintk("%s: empty: %d, active %p -> %p.\n", + __func__, list_empty(&psb->state_list), c, + psb->active_state); + } else + psb->active_state = NULL; +} + +void pohmelfs_check_states(struct pohmelfs_sb *psb) +{ + struct pohmelfs_config *c, *tmp; + LIST_HEAD(delete_list); + + mutex_lock(&psb->state_lock); + list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) { + if (pohmelfs_config_check(c, psb->idx)) { + + if (psb->active_state == c) + pohmelfs_switch_active(psb); + list_move(&c->config_entry, &delete_list); + } + } + pohmelfs_copy_config(psb); + mutex_unlock(&psb->state_lock); + + list_for_each_entry_safe(c, tmp, &delete_list, config_entry) { + list_del(&c->config_entry); + pohmelfs_state_exit_one(c); + } +} diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h new file mode 100644 index 000000000000..2ff21ae5bb12 --- /dev/null +++ b/drivers/staging/pohmelfs/netfs.h @@ -0,0 +1,932 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#ifndef __NETFS_H +#define __NETFS_H + +#include +#include + +#define POHMELFS_CN_IDX 5 +#define POHMELFS_CN_VAL 0 + +#define POHMELFS_CTLINFO_ACK 1 +#define POHMELFS_NOINFO_ACK 2 + + +/* + * Network command structure. + * Will be extended. + */ +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]; +}; + +static inline void netfs_convert_cmd(struct netfs_cmd *cmd) +{ + cmd->id = __be64_to_cpu(cmd->id); + cmd->start = __be64_to_cpu(cmd->start); + cmd->iv = __be64_to_cpu(cmd->iv); + cmd->cmd = __be16_to_cpu(cmd->cmd); + cmd->ext = __be16_to_cpu(cmd->ext); + cmd->csize = __be16_to_cpu(cmd->csize); + cmd->cpad = __be16_to_cpu(cmd->cpad); + cmd->size = __be32_to_cpu(cmd->size); +} + +#define NETFS_TRANS_SINGLE_DST (1<<0) + +enum { + 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 */ + NETFS_CMD_MAX +}; + +enum { + POHMELFS_FLAGS_ADD = 0, /* Network state control message for ADD */ + POHMELFS_FLAGS_DEL, /* Network state control message for DEL */ + POHMELFS_FLAGS_SHOW, /* Network state control message for SHOW */ + POHMELFS_FLAGS_CRYPTO, /* Crypto data control message */ +}; + +/* + * Always wanted to copy it from socket headers into public one, + * since they are __KERNEL__ protected there. + */ +#define _K_SS_MAXSIZE 128 + +struct saddr +{ + unsigned short sa_family; + char addr[_K_SS_MAXSIZE]; +}; + +enum { + POHMELFS_CRYPTO_HASH = 0, + POHMELFS_CRYPTO_CIPHER, +}; + +struct pohmelfs_crypto +{ + unsigned int idx; /* Config index */ + unsigned short strlen; /* Size of the attached crypto string including 0-byte + * "cbc(aes)" for example */ + unsigned short type; /* HMAC, cipher, both */ + unsigned int keysize; /* Key size */ + unsigned char data[0]; /* Algorithm string, key and IV */ +}; + +/* + * Configuration command used to create table of different remote servers. + */ +struct pohmelfs_ctl +{ + unsigned int idx; /* Config index */ + unsigned int type; /* Socket type */ + unsigned int proto; /* Socket protocol */ + unsigned int addrlen; /* Size of the address */ + unsigned short unused; /* Align structure by 4 bytes */ + struct saddr addr; /* Remote server address */ +}; + +/* + * Ack for userspace about requested command. + */ +struct pohmelfs_cn_ack +{ + struct cn_msg msg; + int error; + int msg_num; + int unused[3]; + struct pohmelfs_ctl ctl; +}; + +/* + * Inode info structure used to sync with server. + * Check what stat() returns. + */ +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; +}; + +static inline void netfs_convert_inode_info(struct netfs_inode_info *info) +{ + info->mode = __cpu_to_be32(info->mode); + info->nlink = __cpu_to_be32(info->nlink); + info->uid = __cpu_to_be32(info->uid); + info->gid = __cpu_to_be32(info->gid); + info->blocksize = __cpu_to_be32(info->blocksize); + info->blocks = __cpu_to_be64(info->blocks); + info->rdev = __cpu_to_be64(info->rdev); + info->size = __cpu_to_be64(info->size); + info->version = __cpu_to_be64(info->version); + info->ino = __cpu_to_be64(info->ino); +} + +/* + * Cache state machine. + */ +enum { + NETFS_COMMAND_PENDING = 0, /* Command is being executed */ + NETFS_INODE_REMOTE_SYNCED, /* Inode was synced to server */ + NETFS_INODE_REMOTE_DIR_SYNCED, /* Inode (directory) was synced from the server */ + NETFS_INODE_OWNED, /* Inode is owned by given host */ + NETFS_INODE_NEED_FLUSH, /* Inode has to be flushed to the server */ +}; + +/* + * POHMELFS capabilities: information about supported + * crypto operations (hash/cipher, modes, key sizes and so on), + * root informaion (used/available size, number of objects, permissions) + */ +enum pohmelfs_capabilities { + POHMELFS_CRYPTO_CAPABILITIES = 0, + POHMELFS_ROOT_CAPABILITIES, +}; + +/* Read-only mount */ +#define POHMELFS_FLAGS_RO (1<<0) +/* Extended attributes support on/off */ +#define POHMELFS_FLAGS_XATTR (1<<1) + +struct netfs_root_capabilities +{ + __u64 nr_files; + __u64 used, avail; + __u64 flags; +}; + +static inline void netfs_convert_root_capabilities(struct netfs_root_capabilities *cap) +{ + cap->nr_files = __cpu_to_be64(cap->nr_files); + cap->used = __cpu_to_be64(cap->used); + cap->avail = __cpu_to_be64(cap->avail); + cap->flags = __cpu_to_be64(cap->flags); +} + +struct netfs_crypto_capabilities +{ + unsigned short hash_strlen; /* Hash string length, like "hmac(sha1) including 0 byte "*/ + unsigned short cipher_strlen; /* Cipher string length with the same format */ + unsigned int cipher_keysize; /* Cipher key size */ +}; + +static inline void netfs_convert_crypto_capabilities(struct netfs_crypto_capabilities *cap) +{ + cap->hash_strlen = __cpu_to_be16(cap->hash_strlen); + cap->cipher_strlen = __cpu_to_be16(cap->cipher_strlen); + cap->cipher_keysize = __cpu_to_be32(cap->cipher_keysize); +} + +enum pohmelfs_lock_type { + POHMELFS_LOCK_GRAB = (1<<15), + + POHMELFS_READ_LOCK = 0, + POHMELFS_WRITE_LOCK, +}; + +struct netfs_lock +{ + __u64 start; + __u64 ino; + __u32 size; + __u32 type; +}; + +static inline void netfs_convert_lock(struct netfs_lock *lock) +{ + lock->start = __cpu_to_be64(lock->start); + lock->ino = __cpu_to_be64(lock->ino); + lock->size = __cpu_to_be32(lock->size); + lock->type = __cpu_to_be32(lock->type); +} + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +/* + * Private POHMELFS cache of objects in directory. + */ +struct pohmelfs_name +{ + struct rb_node hash_node; + + struct list_head sync_create_entry; + + u64 ino; + + u32 hash; + u32 mode; + u32 len; + + char *data; +}; + +/* + * POHMELFS inode. Main object. + */ +struct pohmelfs_inode +{ + struct list_head inode_entry; /* Entry in superblock list. + * Objects which are not bound to dentry require to be dropped + * in ->put_super() + */ + struct rb_root hash_root; /* The same, but indexed by name hash and len */ + struct mutex offset_lock; /* Protect both above trees */ + + struct list_head sync_create_list; /* List of created but not yet synced to the server children */ + + unsigned int drop_count; + + int lock_type; /* How this inode is locked: read or write */ + + int error; /* Transaction error for given inode */ + + long state; /* State machine above */ + + u64 ino; /* Inode number */ + u64 total_len; /* Total length of all children names, used to create offsets */ + + struct inode vfs_inode; +}; + +struct netfs_trans; +typedef int (* netfs_trans_complete_t)(struct page **pages, unsigned int page_num, + void *private, int err); + +struct netfs_state; +struct pohmelfs_sb; + +struct netfs_trans +{ + /* + * Transaction header and attached contiguous data live here. + */ + struct iovec iovec; + + /* + * Pages attached to transaction. + */ + struct page **pages; + + /* + * List and protecting lock for transaction destination + * network states. + */ + spinlock_t dst_lock; + struct list_head dst_list; + + /* + * Number of users for given transaction. + * For example each network state attached to transaction + * via dst_list increases it. + */ + atomic_t refcnt; + + /* + * Number of pages attached to given transaction. + * Some slots in above page array can be NULL, since + * for example page can be under writeback already, + * so we skip it in this transaction. + */ + unsigned int page_num; + + /* + * Transaction flags: single dst or broadcast and so on. + */ + unsigned int flags; + + /* + * Size of the data, which can be placed into + * iovec.iov_base area. + */ + unsigned int total_size; + + /* + * Number of pages to be sent to remote server. + * Usually equal to above page_num, but in case of partial + * writeback it can accumulate only pages already completed + * previous writeback. + */ + unsigned int attached_pages; + + /* + * Attached number of bytes in all above pages. + */ + unsigned int attached_size; + + /* + * Unique transacton generation number. + * Used as identity in the network state tree of transactions. + */ + unsigned int gen; + + /* + * Transaction completion status. + */ + int result; + + /* + * Superblock this transaction belongs to + */ + struct pohmelfs_sb *psb; + + /* + * Crypto engine, which processed this transaction. + * Can be not NULL only if crypto engine holds encrypted pages. + */ + struct pohmelfs_crypto_engine *eng; + + /* Private data */ + void *private; + + /* Completion callback, invoked just before transaction is destroyed */ + netfs_trans_complete_t complete; +}; + +static inline int netfs_trans_cur_len(struct netfs_trans *t) +{ + return (signed)(t->total_size - t->iovec.iov_len); +} + +static inline void *netfs_trans_current(struct netfs_trans *t) +{ + return t->iovec.iov_base + t->iovec.iov_len; +} + +struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size, + unsigned int flags, unsigned int nr); +void netfs_trans_free(struct netfs_trans *t); +int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb); +int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb); + +static inline void netfs_trans_reset(struct netfs_trans *t) +{ + t->complete = NULL; +} + +struct netfs_trans_dst +{ + struct list_head trans_entry; + struct rb_node state_entry; + + unsigned long send_time; + + /* + * Times this transaction was resent to its old or new, + * depending on flags, destinations. When it reaches maximum + * allowed number, specified in superblock->trans_retries, + * transaction will be freed with ETIMEDOUT error. + */ + unsigned int retries; + + struct netfs_trans *trans; + struct netfs_state *state; +}; + +struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen); +void netfs_trans_drop_dst(struct netfs_trans_dst *dst); +void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst); +void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st); +void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st); +int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb); +int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st); + +int netfs_trans_init(void); +void netfs_trans_exit(void); + +struct pohmelfs_crypto_engine +{ + u64 iv; /* Crypto IV for current operation */ + unsigned long timeout; /* Crypto waiting timeout */ + unsigned int size; /* Size of crypto scratchpad */ + void *data; /* Temporal crypto scratchpad */ + /* + * Crypto operations performed on objects. + */ + struct crypto_hash *hash; + struct crypto_ablkcipher *cipher; + + struct pohmelfs_crypto_thread *thread; /* Crypto thread which hosts this engine */ + + struct page **pages; + unsigned int page_num; +}; + +struct pohmelfs_crypto_thread +{ + struct list_head thread_entry; + + struct task_struct *thread; + struct pohmelfs_sb *psb; + + struct pohmelfs_crypto_engine eng; + + struct netfs_trans *trans; + + wait_queue_head_t wait; + int error; + + unsigned int size; + struct page *page; +}; + +void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th); + +/* + * Network state, attached to one server. + */ +struct netfs_state +{ + struct mutex __state_lock; /* Can not allow to use the same socket simultaneously */ + struct mutex __state_send_lock; + struct netfs_cmd cmd; /* Cached command */ + struct netfs_inode_info info; /* Cached inode info */ + + void *data; /* Cached some data */ + unsigned int size; /* Size of that data */ + + struct pohmelfs_sb *psb; /* Superblock */ + + struct task_struct *thread; /* Async receiving thread */ + + /* Waiting/polling machinery */ + wait_queue_t wait; + wait_queue_head_t *whead; + wait_queue_head_t thread_wait; + + struct mutex trans_lock; + struct rb_root trans_root; + + struct pohmelfs_ctl ctl; /* Remote peer */ + + struct socket *socket; /* Socket object */ + struct socket *read_socket; /* Cached pointer to socket object. + * Used to determine if between lock drops socket was changed. + * Never used to read data or any kind of access. + */ + /* + * Crypto engines to process incoming data. + */ + struct pohmelfs_crypto_engine eng; + + int need_reset; +}; + +int netfs_state_init(struct netfs_state *st); +void netfs_state_exit(struct netfs_state *st); + +static inline void netfs_state_lock_send(struct netfs_state *st) +{ + mutex_lock(&st->__state_send_lock); +} + +static inline int netfs_state_trylock_send(struct netfs_state *st) +{ + return mutex_trylock(&st->__state_send_lock); +} + +static inline void netfs_state_unlock_send(struct netfs_state *st) +{ + BUG_ON(!mutex_is_locked(&st->__state_send_lock)); + + mutex_unlock(&st->__state_send_lock); +} + +static inline void netfs_state_lock(struct netfs_state *st) +{ + mutex_lock(&st->__state_lock); +} + +static inline void netfs_state_unlock(struct netfs_state *st) +{ + BUG_ON(!mutex_is_locked(&st->__state_lock)); + + mutex_unlock(&st->__state_lock); +} + +static inline unsigned int netfs_state_poll(struct netfs_state *st) +{ + unsigned int revents = POLLHUP | POLLERR; + + netfs_state_lock(st); + if (st->socket) + revents = st->socket->ops->poll(NULL, st->socket, NULL); + netfs_state_unlock(st); + + return revents; +} + +struct pohmelfs_config; + +struct pohmelfs_sb +{ + struct rb_root mcache_root; + struct mutex mcache_lock; + atomic_long_t mcache_gen; + unsigned long mcache_timeout; + + unsigned int idx; + + unsigned int trans_retries; + + atomic_t trans_gen; + + unsigned int crypto_attached_size; + unsigned int crypto_align_size; + + unsigned int crypto_fail_unsupported; + + unsigned int crypto_thread_num; + struct list_head crypto_active_list, crypto_ready_list; + struct mutex crypto_thread_lock; + + unsigned int trans_max_pages; + unsigned long trans_data_size; + unsigned long trans_timeout; + + unsigned long drop_scan_timeout; + unsigned long trans_scan_timeout; + + unsigned long wait_on_page_timeout; + + struct list_head flush_list; + struct list_head drop_list; + spinlock_t ino_lock; + u64 ino; + + /* + * Remote nodes POHMELFS connected to. + */ + struct list_head state_list; + struct mutex state_lock; + + /* + * Currently active state to request data from. + */ + struct pohmelfs_config *active_state; + + + wait_queue_head_t wait; + + /* + * Timed checks: stale transactions, inodes to be freed and so on. + */ + struct delayed_work dwork; + struct delayed_work drop_dwork; + + struct super_block *sb; + + /* + * Algorithm strings. + */ + char *hash_string; + char *cipher_string; + + u8 *hash_key; + u8 *cipher_key; + + /* + * Algorithm string lengths. + */ + unsigned int hash_strlen; + unsigned int cipher_strlen; + unsigned int hash_keysize; + unsigned int cipher_keysize; + + /* + * Controls whether to perfrom crypto processing or not. + */ + int perform_crypto; + + /* + * POHMELFS statistics. + */ + u64 total_size; + u64 avail_size; + atomic_long_t total_inodes; + + /* + * Xattr support, read-only and so on. + */ + u64 state_flags; + + /* + * Temporary storage to detect changes in the wait queue. + */ + long flags; +}; + +static inline void netfs_trans_update(struct netfs_cmd *cmd, + struct netfs_trans *t, unsigned int size) +{ + unsigned int sz = ALIGN(size, t->psb->crypto_align_size); + + t->iovec.iov_len += sizeof(struct netfs_cmd) + sz; + cmd->cpad = __cpu_to_be16(sz - size); +} + +static inline struct pohmelfs_sb *POHMELFS_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} + +static inline struct pohmelfs_inode *POHMELFS_I(struct inode *inode) +{ + return container_of(inode, struct pohmelfs_inode, vfs_inode); +} + +static inline u64 pohmelfs_new_ino(struct pohmelfs_sb *psb) +{ + u64 ino; + + spin_lock(&psb->ino_lock); + ino = psb->ino++; + spin_unlock(&psb->ino_lock); + + return ino; +} + +static inline void pohmelfs_put_inode(struct pohmelfs_inode *pi) +{ + struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); + + spin_lock(&psb->ino_lock); + list_move_tail(&pi->inode_entry, &psb->drop_list); + pi->drop_count++; + spin_unlock(&psb->ino_lock); +} + +struct pohmelfs_config +{ + struct list_head config_entry; + + struct netfs_state state; +}; + +struct pohmelfs_config_group +{ + /* + * Entry in the global config group list. + */ + struct list_head group_entry; + + /* + * Index of the current group. + */ + unsigned int idx; + /* + * Number of config_list entries in this group entry. + */ + unsigned int num_entry; + /* + * Algorithm strings. + */ + char *hash_string; + char *cipher_string; + + /* + * Algorithm string lengths. + */ + unsigned int hash_strlen; + unsigned int cipher_strlen; + + /* + * Key and its size. + */ + unsigned int hash_keysize; + unsigned int cipher_keysize; + u8 *hash_key; + u8 *cipher_key; + + /* + * List of config entries (network state info) for given idx. + */ + struct list_head config_list; +}; + +int __init pohmelfs_config_init(void); +void pohmelfs_config_exit(void); +int pohmelfs_copy_config(struct pohmelfs_sb *psb); +int pohmelfs_copy_crypto(struct pohmelfs_sb *psb); +int pohmelfs_config_check(struct pohmelfs_config *config, int idx); +int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf); + +extern const struct file_operations pohmelfs_dir_fops; +extern const struct inode_operations pohmelfs_dir_inode_ops; + +int pohmelfs_state_init(struct pohmelfs_sb *psb); +void pohmelfs_state_exit(struct pohmelfs_sb *psb); +void pohmelfs_state_flush_transactions(struct netfs_state *st); + +void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info); + +void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *n); +void pohmelfs_free_names(struct pohmelfs_inode *parent); +struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash); + +void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi); + +struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb, + struct pohmelfs_inode *parent, struct qstr *str, u64 start, int mode); + +int pohmelfs_write_create_inode(struct pohmelfs_inode *pi); + +int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans); +int pohmelfs_remove_child(struct pohmelfs_inode *parent, struct pohmelfs_name *n); + +struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb, + struct pohmelfs_inode *parent, struct qstr *str, + struct netfs_inode_info *info, int link); + +int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr); +int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr); + +int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags, + netfs_trans_complete_t complete, void *priv, u64 start); +int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon, + unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start); + +void pohmelfs_check_states(struct pohmelfs_sb *psb); +void pohmelfs_switch_active(struct pohmelfs_sb *psb); + +int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len); +int pohmelfs_path_length(struct pohmelfs_inode *pi); + +struct pohmelfs_crypto_completion +{ + struct completion complete; + int error; +}; + +int pohmelfs_trans_crypt(struct netfs_trans *t, struct pohmelfs_sb *psb); +void pohmelfs_crypto_exit(struct pohmelfs_sb *psb); +int pohmelfs_crypto_init(struct pohmelfs_sb *psb); + +int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb); +void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e); + +int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 iv, + void *data, struct page *page, unsigned int size); +int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e, + struct page *page, unsigned int size, u64 iv); + +static inline u64 pohmelfs_gen_iv(struct netfs_trans *t) +{ + u64 iv = t->gen; + + iv <<= 32; + iv |= ((unsigned long)t) & 0xffffffff; + + return iv; +} + +int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type); +int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type); +int pohmelfs_data_lock_response(struct netfs_state *st); + +static inline int pohmelfs_need_lock(struct pohmelfs_inode *pi, int type) +{ + if (test_bit(NETFS_INODE_OWNED, &pi->state)) { + if (type == pi->lock_type) + return 0; + if ((type == POHMELFS_READ_LOCK) && (pi->lock_type == POHMELFS_WRITE_LOCK)) + return 0; + } + + if (!test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state)) + return 0; + + return 1; +} + +int __init pohmelfs_mcache_init(void); +void pohmelfs_mcache_exit(void); + +//#define CONFIG_POHMELFS_DEBUG + +#ifdef CONFIG_POHMELFS_DEBUG +#define dprintka(f, a...) printk(f, ##a) +#define dprintk(f, a...) printk("%d: " f, task_pid_vnr(current), ##a) +#else +#define dprintka(f, a...) do {} while (0) +#define dprintk(f, a...) do {} while (0) +#endif + +static inline void netfs_trans_get(struct netfs_trans *t) +{ + atomic_inc(&t->refcnt); +} + +static inline void netfs_trans_put(struct netfs_trans *t) +{ + if (atomic_dec_and_test(&t->refcnt)) { + dprintk("%s: t: %p, gen: %u, err: %d.\n", + __func__, t, t->gen, t->result); + if (t->complete) + t->complete(t->pages, t->page_num, + t->private, t->result); + netfs_trans_free(t); + } +} + +struct pohmelfs_mcache +{ + struct rb_node mcache_entry; + struct completion complete; + + atomic_t refcnt; + + u64 gen; + + void *data; + u64 start; + u32 size; + int err; + + struct netfs_inode_info info; +}; + +struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start, + unsigned int size, void *data); +void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m); +struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen); +void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m); + +static inline void pohmelfs_mcache_get(struct pohmelfs_mcache *m) +{ + atomic_inc(&m->refcnt); +} + +static inline void pohmelfs_mcache_put(struct pohmelfs_sb *psb, + struct pohmelfs_mcache *m) +{ + if (atomic_dec_and_test(&m->refcnt)) + pohmelfs_mcache_free(psb, m); +} + +int pohmelfs_ftrans_init(void); +void pohmelfs_ftrans_exit(void); +void pohmelfs_ftrans_update(u64 id); +int pohmelfs_ftrans_check(u64 id); +void pohmelfs_ftrans_clean(u64 id); + +#endif /* __KERNEL__*/ + +#endif /* __NETFS_H */ diff --git a/drivers/staging/pohmelfs/path_entry.c b/drivers/staging/pohmelfs/path_entry.c new file mode 100644 index 000000000000..3bad888ced13 --- /dev/null +++ b/drivers/staging/pohmelfs/path_entry.c @@ -0,0 +1,114 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netfs.h" + +#define UNHASHED_OBSCURE_STRING_SIZE sizeof(" (deleted)") + +/* + * Create path from root for given inode. + * Path is formed as set of stuctures, containing name of the object + * and its inode data (mode, permissions and so on). + */ +int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len) +{ + struct path path; + struct dentry *d; + char *ptr; + int err = 0, strlen, reduce = 0; + + d = d_find_alias(&pi->vfs_inode); + if (!d) { + printk("%s: no alias, list_empty: %d.\n", __func__, list_empty(&pi->vfs_inode.i_dentry)); + return -ENOENT; + } + + read_lock(¤t->fs->lock); + path.mnt = mntget(current->fs->root.mnt); + read_unlock(¤t->fs->lock); + + path.dentry = d; + + if (!IS_ROOT(d) && d_unhashed(d)) + reduce = 1; + + ptr = d_path(&path, data, len); + if (IS_ERR(ptr)) { + err = PTR_ERR(ptr); + goto out; + } + + if (reduce && len >= UNHASHED_OBSCURE_STRING_SIZE) { + char *end = data + len - UNHASHED_OBSCURE_STRING_SIZE; + *end = '\0'; + } + + strlen = len - (ptr - (char *)data); + memmove(data, ptr, strlen); + ptr = data; + + err = strlen; + + dprintk("%s: dname: '%s', len: %u, maxlen: %u, name: '%s', strlen: %d.\n", + __func__, d->d_name.name, d->d_name.len, len, ptr, strlen); + +out: + dput(d); + mntput(path.mnt); + + return err; +} + +int pohmelfs_path_length(struct pohmelfs_inode *pi) +{ + struct dentry *d, *root, *first; + int len = 1; /* Root slash */ + + first = d = d_find_alias(&pi->vfs_inode); + if (!d) { + dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode); + return -ENOENT; + } + + read_lock(¤t->fs->lock); + root = dget(current->fs->root.dentry); + read_unlock(¤t->fs->lock); + + spin_lock(&dcache_lock); + + if (!IS_ROOT(d) && d_unhashed(d)) + len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */ + + while (d && d != root && !IS_ROOT(d)) { + len += d->d_name.len + 1; /* Plus slash */ + d = d->d_parent; + } + spin_unlock(&dcache_lock); + + dput(root); + dput(first); + + return len + 1; /* Including zero-byte */ +} diff --git a/drivers/staging/pohmelfs/trans.c b/drivers/staging/pohmelfs/trans.c new file mode 100644 index 000000000000..bcb59425a21c --- /dev/null +++ b/drivers/staging/pohmelfs/trans.c @@ -0,0 +1,715 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netfs.h" + +static struct kmem_cache *netfs_trans_dst; +static mempool_t *netfs_trans_dst_pool; + +static void netfs_trans_init_static(struct netfs_trans *t, int num, int size) +{ + t->page_num = num; + t->total_size = size; + atomic_set(&t->refcnt, 1); + + spin_lock_init(&t->dst_lock); + INIT_LIST_HEAD(&t->dst_list); +} + +static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st) +{ + int err = 0; + unsigned int i, attached_pages = t->attached_pages, ci; + struct msghdr msg; + struct page **pages = (t->eng)?t->eng->pages:t->pages; + struct page *p; + unsigned int size; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = MSG_WAITALL | MSG_MORE; + + ci = 0; + for (i=0; ipage_num; ++i) { + struct page *page = pages[ci]; + struct netfs_cmd cmd; + struct iovec io; + + p = t->pages[i]; + + if (!p) + continue; + + size = page_private(p); + + io.iov_base = &cmd; + io.iov_len = sizeof(struct netfs_cmd); + + cmd.cmd = NETFS_WRITE_PAGE; + cmd.ext = 0; + cmd.id = 0; + cmd.size = size; + cmd.start = p->index; + cmd.start <<= PAGE_CACHE_SHIFT; + cmd.csize = 0; + cmd.cpad = 0; + cmd.iv = pohmelfs_gen_iv(t); + + netfs_convert_cmd(&cmd); + + msg.msg_iov = &io; + msg.msg_iovlen = 1; + msg.msg_flags = MSG_WAITALL | MSG_MORE; + + err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, sizeof(struct netfs_cmd)); + if (err <= 0) { + printk("%s: %d/%d failed to send transaction header: t: %p, gen: %u, err: %d.\n", + __func__, i, t->page_num, t, t->gen, err); + if (err == 0) + err = -ECONNRESET; + goto err_out; + } + + msg.msg_flags = MSG_WAITALL|(attached_pages == 1)?0:MSG_MORE; + + err = kernel_sendpage(st->socket, page, 0, size, msg.msg_flags); + if (err <= 0) { + printk("%s: %d/%d failed to send transaction page: t: %p, gen: %u, size: %u, err: %d.\n", + __func__, i, t->page_num, t, t->gen, size, err); + if (err == 0) + err = -ECONNRESET; + goto err_out; + } + + dprintk("%s: %d/%d sent t: %p, gen: %u, page: %p/%p, size: %u.\n", + __func__, i, t->page_num, t, t->gen, page, p, size); + + err = 0; + attached_pages--; + if (!attached_pages) + break; + ci++; + + continue; + +err_out: + printk("%s: t: %p, gen: %u, err: %d.\n", __func__, t, t->gen, err); + netfs_state_exit(st); + break; + } + + return err; +} + +int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st) +{ + int err; + struct msghdr msg; + + BUG_ON(!t->iovec.iov_len); + BUG_ON(t->iovec.iov_len > 1024*1024*1024); + + netfs_state_lock_send(st); + if (!st->socket) { + err = netfs_state_init(st); + if (err) + goto err_out_unlock_return; + } + + msg.msg_iov = &t->iovec; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = MSG_WAITALL; + + if (t->attached_pages) + msg.msg_flags |= MSG_MORE; + + err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, t->iovec.iov_len); + if (err <= 0) { + printk("%s: failed to send contig transaction: t: %p, gen: %u, size: %zu, err: %d.\n", + __func__, t, t->gen, t->iovec.iov_len, err); + if (err == 0) + err = -ECONNRESET; + goto err_out_unlock_return; + } + + dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n", + __func__, (t->page_num)?"partial":"full", + t, t->gen, t->iovec.iov_len, t->page_num); + + err = 0; + if (t->attached_pages) + err = netfs_trans_send_pages(t, st); + +err_out_unlock_return: + + if (st->need_reset) { + netfs_state_exit(st); + } + netfs_state_unlock_send(st); + + dprintk("%s: t: %p, gen: %u, err: %d.\n", + __func__, t, t->gen, err); + + t->result = err; + return err; +} + +static inline int netfs_trans_cmp(unsigned int gen, unsigned int new) +{ + if (gen < new) + return 1; + if (gen > new) + return -1; + return 0; +} + +struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen) +{ + struct rb_root *root = &st->trans_root; + struct rb_node *n = root->rb_node; + struct netfs_trans_dst *tmp, *ret = NULL; + struct netfs_trans *t; + int cmp; + + while (n) { + tmp = rb_entry(n, struct netfs_trans_dst, state_entry); + t = tmp->trans; + + cmp = netfs_trans_cmp(t->gen, gen); + if (cmp < 0) + n = n->rb_left; + else if (cmp > 0) + n = n->rb_right; + else { + ret = tmp; + break; + } + } + + return ret; +} + +static int netfs_trans_insert(struct netfs_trans_dst *ndst, struct netfs_state *st) +{ + struct rb_root *root = &st->trans_root; + struct rb_node **n = &root->rb_node, *parent = NULL; + struct netfs_trans_dst *ret = NULL, *tmp; + struct netfs_trans *t = NULL, *new = ndst->trans; + int cmp; + + while (*n) { + parent = *n; + + tmp = rb_entry(parent, struct netfs_trans_dst, state_entry); + t = tmp->trans; + + cmp = netfs_trans_cmp(t->gen, new->gen); + if (cmp < 0) + n = &parent->rb_left; + else if (cmp > 0) + n = &parent->rb_right; + else { + ret = tmp; + break; + } + } + + if (ret) { + printk("%s: exist: old: gen: %u, flags: %x, send_time: %lu, " + "new: gen: %u, flags: %x, send_time: %lu.\n", + __func__, t->gen, t->flags, ret->send_time, + new->gen, new->flags, ndst->send_time); + return -EEXIST; + } + + rb_link_node(&ndst->state_entry, parent, n); + rb_insert_color(&ndst->state_entry, root); + ndst->send_time = jiffies; + + return 0; +} + +int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st) +{ + if (dst && dst->state_entry.rb_parent_color) { + rb_erase(&dst->state_entry, &st->trans_root); + dst->state_entry.rb_parent_color = 0; + return 1; + } + return 0; +} + +static int netfs_trans_remove_state(struct netfs_trans_dst *dst) +{ + int ret; + struct netfs_state *st = dst->state; + + mutex_lock(&st->trans_lock); + ret = netfs_trans_remove_nolock(dst, st); + mutex_unlock(&st->trans_lock); + + return ret; +} + +/* + * Create new destination for given transaction associated with given network state. + * Transaction's reference counter is bumped and will be dropped when either + * reply is received or when async timeout detection task will fail resending + * and drop transaction. + */ +static int netfs_trans_push_dst(struct netfs_trans *t, struct netfs_state *st) +{ + struct netfs_trans_dst *dst; + int err; + + dst = mempool_alloc(netfs_trans_dst_pool, GFP_KERNEL); + if (!dst) + return -ENOMEM; + + dst->retries = 0; + dst->send_time = 0; + dst->state = st; + dst->trans = t; + netfs_trans_get(t); + + mutex_lock(&st->trans_lock); + err = netfs_trans_insert(dst, st); + mutex_unlock(&st->trans_lock); + + if (err) + goto err_out_free; + + spin_lock(&t->dst_lock); + list_add_tail(&dst->trans_entry, &t->dst_list); + spin_unlock(&t->dst_lock); + + return 0; + +err_out_free: + t->result = err; + netfs_trans_put(t); + mempool_free(dst, netfs_trans_dst_pool); + return err; +} + +static void netfs_trans_free_dst(struct netfs_trans_dst *dst) +{ + netfs_trans_put(dst->trans); + mempool_free(dst, netfs_trans_dst_pool); +} + +static void netfs_trans_remove_dst(struct netfs_trans_dst *dst) +{ + if (netfs_trans_remove_state(dst)) + netfs_trans_free_dst(dst); +} + +/* + * Drop destination transaction entry when we know it. + */ +void netfs_trans_drop_dst(struct netfs_trans_dst *dst) +{ + struct netfs_trans *t = dst->trans; + + spin_lock(&t->dst_lock); + list_del_init(&dst->trans_entry); + spin_unlock(&t->dst_lock); + + netfs_trans_remove_dst(dst); +} + +/* + * Drop destination transaction entry when we know it and when we + * already removed dst from state tree. + */ +void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst) +{ + struct netfs_trans *t = dst->trans; + + spin_lock(&t->dst_lock); + list_del_init(&dst->trans_entry); + spin_unlock(&t->dst_lock); + + netfs_trans_free_dst(dst); +} + +/* + * This drops destination transaction entry from appropriate network state + * tree and drops related reference counter. It is possible that transaction + * will be freed here if its reference counter hits zero. + * Destination transaction entry will be freed. + */ +void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st) +{ + struct netfs_trans_dst *dst, *tmp, *ret = NULL; + + spin_lock(&t->dst_lock); + list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) { + if (dst->state == st) { + ret = dst; + list_del(&dst->trans_entry); + break; + } + } + spin_unlock(&t->dst_lock); + + if (ret) + netfs_trans_remove_dst(ret); +} + +/* + * This drops destination transaction entry from appropriate network state + * tree and drops related reference counter. It is possible that transaction + * will be freed here if its reference counter hits zero. + * Destination transaction entry will be freed. + */ +void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st) +{ + struct netfs_trans_dst *dst, *tmp, *ret; + + spin_lock(&t->dst_lock); + ret = list_entry(t->dst_list.prev, struct netfs_trans_dst, trans_entry); + if (ret->state != st) { + ret = NULL; + list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) { + if (dst->state == st) { + ret = dst; + list_del_init(&dst->trans_entry); + break; + } + } + } else { + list_del(&ret->trans_entry); + } + spin_unlock(&t->dst_lock); + + if (ret) + netfs_trans_remove_dst(ret); +} + +static int netfs_trans_push(struct netfs_trans *t, struct netfs_state *st) +{ + int err; + + err = netfs_trans_push_dst(t, st); + if (err) + return err; + + err = netfs_trans_send(t, st); + if (err) + goto err_out_free; + + if (t->flags & NETFS_TRANS_SINGLE_DST) + pohmelfs_switch_active(st->psb); + + return 0; + +err_out_free: + t->result = err; + netfs_trans_drop_last(t, st); + + return err; +} + +int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb) +{ + struct pohmelfs_config *c; + int err = -ENODEV; + struct netfs_state *st; +#if 0 + dprintk("%s: t: %p, gen: %u, size: %u, page_num: %u, active: %p.\n", + __func__, t, t->gen, t->iovec.iov_len, t->page_num, psb->active_state); +#endif + mutex_lock(&psb->state_lock); + + if ((t->flags & NETFS_TRANS_SINGLE_DST) && psb->active_state) { + st = &psb->active_state->state; + + err = -EPIPE; + if (netfs_state_poll(st) & POLLOUT) { + err = netfs_trans_push_dst(t, st); + if (!err) { + err = netfs_trans_send(t, st); + if (err) { + netfs_trans_drop_last(t, st); + } else { + pohmelfs_switch_active(psb); + goto out; + } + } + } + pohmelfs_switch_active(psb); + } + + list_for_each_entry(c, &psb->state_list, config_entry) { + st = &c->state; + + err = netfs_trans_push(t, st); + if (!err && (t->flags & NETFS_TRANS_SINGLE_DST)) + break; + } +out: + mutex_unlock(&psb->state_lock); +#if 0 + dprintk("%s: fully sent t: %p, gen: %u, size: %u, page_num: %u, err: %d.\n", + __func__, t, t->gen, t->iovec.iov_len, t->page_num, err); +#endif + if (err) + t->result = err; + return err; +} + +int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb) +{ + int err; + struct netfs_cmd *cmd = t->iovec.iov_base; + + t->gen = atomic_inc_return(&psb->trans_gen); + + pohmelfs_ftrans_clean(t->gen); + + cmd->size = t->iovec.iov_len - sizeof(struct netfs_cmd) + + t->attached_size + t->attached_pages * sizeof(struct netfs_cmd); + cmd->cmd = NETFS_TRANS; + cmd->start = t->gen; + cmd->id = 0; + + if (psb->perform_crypto) { + cmd->ext = psb->crypto_attached_size; + cmd->csize = psb->crypto_attached_size; + } + + dprintk("%s: t: %u, size: %u, iov_len: %zu, attached_size: %u, attached_pages: %u.\n", + __func__, t->gen, cmd->size, t->iovec.iov_len, t->attached_size, t->attached_pages); + err = pohmelfs_trans_crypt(t, psb); + if (err) { + t->result = err; + netfs_convert_cmd(cmd); + dprintk("%s: trans: %llu, crypto_attached_size: %u, attached_size: %u, attached_pages: %d, trans_size: %u, err: %d.\n", + __func__, cmd->start, psb->crypto_attached_size, t->attached_size, t->attached_pages, cmd->size, err); + } + netfs_trans_put(t); + return err; +} + +/* + * Resend transaction to remote server(s). + * If new servers were added into superblock, we can try to send data + * to them too. + * + * It is called under superblock's state_lock, so we can safely + * dereference psb->state_list. Also, transaction's reference counter is + * bumped, so it can not go away under us, thus we can safely access all + * its members. State is locked. + * + * This function returns 0 if transaction was successfully sent to at + * least one destination target. + */ +int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb) +{ + struct netfs_trans_dst *dst; + struct netfs_state *st; + struct pohmelfs_config *c; + int err, exist, error = -ENODEV; + + list_for_each_entry(c, &psb->state_list, config_entry) { + st = &c->state; + + exist = 0; + spin_lock(&t->dst_lock); + list_for_each_entry(dst, &t->dst_list, trans_entry) { + if (st == dst->state) { + exist = 1; + break; + } + } + spin_unlock(&t->dst_lock); + + if (exist) { + if (!(t->flags & NETFS_TRANS_SINGLE_DST) || + (c->config_entry.next == &psb->state_list)) { + dprintk("%s: resending st: %p, t: %p, gen: %u.\n", + __func__, st, t, t->gen); + err = netfs_trans_send(t, st); + if (!err) + error = 0; + } + continue; + } + + dprintk("%s: pushing/resending st: %p, t: %p, gen: %u.\n", + __func__, st, t, t->gen); + err = netfs_trans_push(t, st); + if (err) + continue; + error = 0; + if (t->flags & NETFS_TRANS_SINGLE_DST) + break; + } + + t->result = error; + return error; +} + +void *netfs_trans_add(struct netfs_trans *t, unsigned int size) +{ + struct iovec *io = &t->iovec; + void *ptr; + + if (size > t->total_size) { + ptr = ERR_PTR(-EINVAL); + goto out; + } + + if (io->iov_len + size > t->total_size) { + dprintk("%s: too big size t: %p, gen: %u, iov_len: %zu, size: %u, total: %u.\n", + __func__, t, t->gen, io->iov_len, size, t->total_size); + ptr = ERR_PTR(-E2BIG); + goto out; + } + + ptr = io->iov_base + io->iov_len; + io->iov_len += size; + +out: + dprintk("%s: t: %p, gen: %u, size: %u, total: %zu.\n", + __func__, t, t->gen, size, io->iov_len); + return ptr; +} + +void netfs_trans_free(struct netfs_trans *t) +{ + if (t->eng) + pohmelfs_crypto_thread_make_ready(t->eng->thread); + kfree(t); +} + +struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size, + unsigned int flags, unsigned int nr) +{ + struct netfs_trans *t; + unsigned int num, cont, pad, size_no_trans; + unsigned int crypto_added = 0; + struct netfs_cmd *cmd; + + if (psb->perform_crypto) + crypto_added = psb->crypto_attached_size; + + /* + * |sizeof(struct netfs_trans)| + * |sizeof(struct netfs_cmd)| - transaction header + * |size| - buffer with requested size + * |padding| - crypto padding, zero bytes + * |nr * sizeof(struct page *)| - array of page pointers + * + * Overall size should be less than PAGE_SIZE for guaranteed allocation. + */ + + cont = size; + size = ALIGN(size, psb->crypto_align_size); + pad = size - cont; + + size_no_trans = size + sizeof(struct netfs_cmd) * 2 + crypto_added; + + cont = sizeof(struct netfs_trans) + size_no_trans; + + num = (PAGE_SIZE - cont)/sizeof(struct page *); + + if (nr > num) + nr = num; + + t = kzalloc(cont + nr*sizeof(struct page *), GFP_NOIO); + if (!t) + goto err_out_exit; + + t->iovec.iov_base = (void *)(t + 1); + t->pages = (struct page **)(t->iovec.iov_base + size_no_trans); + + /* + * Reserving space for transaction header. + */ + t->iovec.iov_len = sizeof(struct netfs_cmd) + crypto_added; + + netfs_trans_init_static(t, nr, size_no_trans); + + t->flags = flags; + t->psb = psb; + + cmd = (struct netfs_cmd *)t->iovec.iov_base; + + cmd->size = size; + cmd->cpad = pad; + cmd->csize = crypto_added; + + dprintk("%s: t: %p, gen: %u, size: %u, padding: %u, align_size: %u, flags: %x, " + "page_num: %u, base: %p, pages: %p.\n", + __func__, t, t->gen, size, pad, psb->crypto_align_size, flags, nr, + t->iovec.iov_base, t->pages); + + return t; + +err_out_exit: + return NULL; +} + +int netfs_trans_init(void) +{ + int err = -ENOMEM; + + netfs_trans_dst = kmem_cache_create("netfs_trans_dst", sizeof(struct netfs_trans_dst), + 0, 0, NULL); + if (!netfs_trans_dst) + goto err_out_exit; + + netfs_trans_dst_pool = mempool_create_slab_pool(256, netfs_trans_dst); + if (!netfs_trans_dst_pool) + goto err_out_free; + + return 0; + +err_out_free: + kmem_cache_destroy(netfs_trans_dst); +err_out_exit: + return err; +} + +void netfs_trans_exit(void) +{ + mempool_destroy(netfs_trans_dst_pool); + kmem_cache_destroy(netfs_trans_dst); +} diff --git a/drivers/staging/rspiusb/rspiusb.c b/drivers/staging/rspiusb/rspiusb.c index ca281d6cbd7a..ecaffb503111 100644 --- a/drivers/staging/rspiusb/rspiusb.c +++ b/drivers/staging/rspiusb/rspiusb.c @@ -781,9 +781,8 @@ static int piusb_probe(struct usb_interface *interface, dbg("Endpoint[%d]->MaxPacketSize = %d\n", i, endpoint->wMaxPacketSize); } - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_BULK) { - if (endpoint->bEndpointAddress & USB_DIR_IN) + if (usb_endpoint_xfer_bulk(endpoint)) { + if (usb_endpoint_dir_in(endpoint)) pdx->hEP[i] = usb_rcvbulkpipe(pdx->udev, endpoint->bEndpointAddress); diff --git a/drivers/staging/rt2860/2860_main_dev.c b/drivers/staging/rt2860/2860_main_dev.c index 08ca81f43cc8..ff7f83380736 100644 --- a/drivers/staging/rt2860/2860_main_dev.c +++ b/drivers/staging/rt2860/2860_main_dev.c @@ -90,12 +90,10 @@ void init_thread_task(PRTMP_ADAPTER pAd); static void __exit rt2860_cleanup_module(void); static int __init rt2860_init_module(void); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #ifdef CONFIG_PM static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state); static int rt2860_resume(struct pci_dev *pci_dev); #endif // CONFIG_PM // -#endif // @@ -128,22 +126,15 @@ static struct pci_driver rt2860_driver = name: "rt2860", id_table: rt2860_pci_tbl, probe: rt2860_init_one, -#if LINUX_VERSION_CODE >= 0x20412 remove: __devexit_p(rt2860_remove_one), -#else - remove: __devexit(rt2860_remove_one), -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #ifdef CONFIG_PM suspend: rt2860_suspend, resume: rt2860_resume, #endif -#endif }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #ifdef CONFIG_PM VOID RT2860RejectPendingPackets( @@ -284,16 +275,11 @@ static int rt2860_resume( return 0; } #endif // CONFIG_PM // -#endif static INT __init rt2860_init_module(VOID) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) return pci_register_driver(&rt2860_driver); -#else - return pci_module_init(&rt2860_driver); -#endif } @@ -374,11 +360,7 @@ static VOID __devexit rt2860_remove_one( } // Free pre-allocated net_device memory -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) free_netdev(net_dev); -#else - kfree(net_dev); -#endif } // @@ -758,16 +740,13 @@ static void ac0_dma_done_tasklet(unsigned long data) int print_int_count; IRQ_HANDLE_TYPE -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) rt2860_interrupt(int irq, void *dev_instance) -#else -rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -#endif { struct net_device *net_dev = (struct net_device *) dev_instance; PRTMP_ADAPTER pAd = net_dev->ml_priv; INT_SOURCE_CSR_STRUC IntSource; POS_COOKIE pObj; + BOOLEAN bOldValue; pObj = (POS_COOKIE) pAd->OS_Cookie; @@ -800,20 +779,19 @@ rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs) // RT2661 => when ASIC is sleeping, MAC register cannot be read and written. // RT2860 => when ASIC is sleeping, MAC register can be read and written. + bOldValue = pAd->bPCIclkOff; + pAd->bPCIclkOff = FALSE; { RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word); RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); // write 1 to clear } + pAd->bPCIclkOff = bOldValue; // Do nothing if Reset in progress if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return IRQ_HANDLED; -#else - return; -#endif + return IRQ_HANDLED; } // @@ -822,8 +800,6 @@ rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs) // The priority can be adjust by altering processing if statement // - pAd->bPCIclkOff = FALSE; - // If required spinlock, each interrupt service routine has to acquire // and release itself. // @@ -832,11 +808,8 @@ rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs) if (IntSource.word == 0xffffffff) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - return IRQ_HANDLED; -#else - return; -#endif + printk("snowpin - IntSource.word == 0xffffffff\n"); + return IRQ_HANDLED; } if (IntSource.word & TxCoherent) @@ -970,10 +943,7 @@ rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs) } #endif // CONFIG_STA_SUPPORT // -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) return IRQ_HANDLED; -#endif - } /* @@ -1026,11 +996,7 @@ BOOLEAN RT28XXNetDevInit( ULONG csr_addr; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - print_name = pci_dev ? pci_name(pci_dev) : "rt2860"; -#else - print_name = pci_dev ? pci_dev->slot_name : "rt2860"; -#endif // LINUX_VERSION_CODE // + print_name = pci_dev ? pci_name(pci_dev) : "rt2860"; net_dev->base_addr = 0; net_dev->irq = 0; diff --git a/drivers/staging/rt2860/Makefile b/drivers/staging/rt2860/Makefile index 6162212b588c..b95636478464 100644 --- a/drivers/staging/rt2860/Makefile +++ b/drivers/staging/rt2860/Makefile @@ -2,7 +2,6 @@ obj-$(CONFIG_RT2860) += rt2860sta.o # TODO: all of these should be removed EXTRA_CFLAGS += -DLINUX -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -EXTRA_CFLAGS += -DRT2860 EXTRA_CFLAGS += -DCONFIG_STA_SUPPORT EXTRA_CFLAGS += -DDBG EXTRA_CFLAGS += -DDOT11_N_SUPPORT diff --git a/drivers/staging/rt2860/TODO b/drivers/staging/rt2860/TODO index 2f70b0faca3d..6158dc2a4b66 100644 --- a/drivers/staging/rt2860/TODO +++ b/drivers/staging/rt2860/TODO @@ -1,6 +1,6 @@ I'm hesitant to add a TODO file here, as the wireless developers would really have people help them out on the "clean" rt2860 driver that can -be found at the rt2860.sf.net site. +be found at the http://rt2x00.serialmonkey.com/ site. But, if you wish to clean up this driver instead, here's a short list of things that need to be done to get it into a more mergable shape: @@ -8,7 +8,7 @@ things that need to be done to get it into a more mergable shape: TODO: - checkpatch.pl clean - sparse clean - - port to in-kernel 80211 stack + - port to in-kernel 80211 stack and common rt2x00 infrastructure - remove reading from /etc/ config files - review by the wireless developer community diff --git a/drivers/staging/rt2860/common/cmm_data.c b/drivers/staging/rt2860/common/cmm_data.c index b67b9eba7229..b3f88f52af7c 100644 --- a/drivers/staging/rt2860/common/cmm_data.c +++ b/drivers/staging/rt2860/common/cmm_data.c @@ -105,9 +105,7 @@ NDIS_STATUS MiniportMMRequest( PNDIS_PACKET pPacket; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; ULONG FreeNum; -#ifdef RT2860 unsigned long IrqFlags = 0; -#endif // RT2860 // UCHAR IrqState; UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; @@ -118,10 +116,9 @@ NDIS_STATUS MiniportMMRequest( // 2860C use Tx Ring IrqState = pAd->irq_disabled; -#ifdef RT2860 + if ((pAd->MACVersion == 0x28600100) && (!IrqState)) RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); -#endif // RT2860 // do { @@ -175,17 +172,14 @@ NDIS_STATUS MiniportMMRequest( } while (FALSE); -#ifdef RT2860 // 2860C use Tx Ring if ((pAd->MACVersion == 0x28600100) && (!IrqState)) RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); -#endif // RT2860 // return Status; } -#ifdef RT2860 NDIS_STATUS MiniportMMRequestUnlock( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx, @@ -253,7 +247,6 @@ NDIS_STATUS MiniportMMRequestUnlock( return Status; } -#endif // RT2860 // /* @@ -290,17 +283,14 @@ NDIS_STATUS MlmeHardTransmit( return NDIS_STATUS_FAILURE; } -#ifdef RT2860 if ( pAd->MACVersion == 0x28600100 ) return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket); else -#endif // RT2860 // return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); } -#ifdef RT2860 NDIS_STATUS MlmeHardTransmitTxRing( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx, @@ -366,7 +356,7 @@ NDIS_STATUS MlmeHardTransmitTxRing( { // outgoing frame always wakeup PHY to prevent frame lost if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - AsicForceWakeup(pAd, TRUE); + AsicForceWakeup(pAd, FROM_TX); } #endif // CONFIG_STA_SUPPORT // pFirstTxWI =(PTXWI_STRUC)pSrcBufVA; @@ -509,7 +499,6 @@ NDIS_STATUS MlmeHardTransmitTxRing( return NDIS_STATUS_SUCCESS; } -#endif // RT2860 // NDIS_STATUS MlmeHardTransmitMgmtRing( @@ -541,7 +530,7 @@ NDIS_STATUS MlmeHardTransmitMgmtRing( { // outgoing frame always wakeup PHY to prevent frame lost if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - AsicForceWakeup(pAd, TRUE); + AsicForceWakeup(pAd, FROM_TX); } #endif // CONFIG_STA_SUPPORT // @@ -1076,7 +1065,6 @@ VOID RTMPDeQueuePacket( break; } -#ifdef RT2860 FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); #ifdef DBG_DIAGNOSE @@ -1101,7 +1089,6 @@ VOID RTMPDeQueuePacket( RTMPFreeTXDUponTxDmaDone(pAd, QueIdx); FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); } -#endif // RT2860 // // probe the Queue Head pQueue = &pAd->TxSwQueue[QueIdx]; @@ -1180,12 +1167,10 @@ VOID RTMPDeQueuePacket( Status = STAHardTransmit(pAd, pTxBlk, QueIdx); #endif // CONFIG_STA_SUPPORT // -#ifdef RT2860 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); // static rate also need NICUpdateFifoStaCounters() function. //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) NICUpdateFifoStaCounters(pAd); -#endif // RT2860 // } RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); @@ -1764,7 +1749,6 @@ PQUEUE_HEADER RTMPCheckTxSwQueue( } -#ifdef RT2860 BOOLEAN RTMPFreeTXDUponTxDmaDone( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx) @@ -2309,7 +2293,6 @@ VOID DBGPRINT_RX_RING( DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx)); DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount)); } -#endif // RT2860 // /* ======================================================================== @@ -2634,9 +2617,7 @@ MAC_TABLE_ENTRY *MacTableInsertEntry( pEntry->AuthMode = pAd->StaCfg.AuthMode; pEntry->WepStatus = pAd->StaCfg.WepStatus; pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; -#ifdef RT2860 AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i); -#endif // RT2860 // } #endif // CONFIG_STA_SUPPORT // } @@ -2823,9 +2804,7 @@ VOID MacTableReset( for (i=1; iMacTab.Content[i].ValidAsCLI == TRUE) { diff --git a/drivers/staging/rt2860/common/cmm_data_2860.c b/drivers/staging/rt2860/common/cmm_data_2860.c index 419e50c3fc4c..fae741e4beeb 100644 --- a/drivers/staging/rt2860/common/cmm_data_2860.c +++ b/drivers/staging/rt2860/common/cmm_data_2860.c @@ -634,7 +634,7 @@ VOID RT28xxPciAsicRadioOff( } // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops. - pAd->bPCIclkOffDisableTx = TRUE; + RTMP_SET_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { @@ -651,7 +651,7 @@ VOID RT28xxPciAsicRadioOff( { DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime)); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - pAd->bPCIclkOffDisableTx = FALSE; + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); return; } else @@ -688,18 +688,25 @@ VOID RT28xxPciAsicRadioOff( if (i >= 50) { DBGPRINT(RT_DEBUG_TRACE, ("DMA keeps busy. return on RT28xxPciAsicRadioOff ()\n")); - pAd->bPCIclkOffDisableTx = FALSE; RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); DmaCfg.field.EnableTxDMA = 1; RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); + pAd->CheckDmaBusyCount++; return; } + else + { + pAd->CheckDmaBusyCount = 0; + } RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); // Set to 1R. - tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); - RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); + if (pAd->Antenna.field.RxPath > 1) + { + tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3); + } // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) @@ -714,8 +721,15 @@ VOID RT28xxPciAsicRadioOff( AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); } - // When PCI clock is off, don't want to service interrupt. - RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); + if (Level != RTMP_HALT) + { + // Change Interrupt bitmask. + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); + } + else + { + NICDisableInterrupt(pAd); + } RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); // Disable MAC Rx @@ -726,7 +740,8 @@ VOID RT28xxPciAsicRadioOff( // 2. Send Sleep command RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); - AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout unit:40us. + // send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power + AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x1); // 2-1. Wait command success // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task. brc = AsicCheckCommanOk(pAd, PowerSafeCID); @@ -734,7 +749,7 @@ VOID RT28xxPciAsicRadioOff( if (brc == FALSE) { // try again - AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout unit:40us. + AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x01); // send POWER-SAVE command to MCU. Timeout unit:40us. //RTMPusecDelay(200); brc = AsicCheckCommanOk(pAd, PowerSafeCID); } @@ -759,7 +774,7 @@ VOID RT28xxPciAsicRadioOff( do { RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - if (DmaCfg.field.RxDMABusy == 0) + if ((DmaCfg.field.RxDMABusy == 0) && (DmaCfg.field.TxDMABusy == 0)) break; RTMPusecDelay(20); i++; @@ -767,13 +782,12 @@ VOID RT28xxPciAsicRadioOff( if (i >= 50) { + pAd->CheckDmaBusyCount++; DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. on RT28xxPciAsicRadioOff ()\n")); } - // disable DMA Rx. + else { - RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word); - DmaCfg.field.EnableRxDMA = 0; - RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word); + pAd->CheckDmaBusyCount = 0; } if (Level == DOT11POWERSAVE) @@ -799,7 +813,7 @@ VOID RT28xxPciAsicRadioOff( if (Level == RTMP_HALT) { if ((brc == TRUE) && (i < 50)) - RTMPPCIeLinkCtrlSetting(pAd, 1); + RTMPPCIeLinkCtrlSetting(pAd, 0); } // 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function else @@ -808,7 +822,7 @@ VOID RT28xxPciAsicRadioOff( RTMPPCIeLinkCtrlSetting(pAd, 3); } - pAd->bPCIclkOffDisableTx = FALSE; + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_DISABLE_TX); } @@ -835,7 +849,8 @@ BOOLEAN RT28xxPciAsicRadioOn( { pAd->Mlme.bPsPollTimerRunning = FALSE; RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); - if ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE)) + if ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE) + || (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))) { DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n")); // 1. Set PCI Link Control in Configuration Space. @@ -845,15 +860,14 @@ BOOLEAN RT28xxPciAsicRadioOn( } pAd->bPCIclkOff = FALSE; - + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x3a80); // 2. Send wake up command. - AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00); + AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02); // 2-1. wait command ok. brv = AsicCheckCommanOk(pAd, PowerWakeCID); if (brv) { - //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT)); NICEnableInterrupt(pAd); // 3. Enable Tx DMA. @@ -893,13 +907,10 @@ BOOLEAN RT28xxPciAsicRadioOn( VOID RT28xxPciStaAsicForceWakeup( IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx) + IN UCHAR Level) { AUTO_WAKEUP_STRUC AutoWakeupCfg; - if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - return; - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW)) { DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n")); @@ -907,38 +918,48 @@ VOID RT28xxPciStaAsicForceWakeup( } OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { // Support PCIe Advance Power Save - if (bFromTx == TRUE) + if (((Level == FROM_TX) && (pAd->Mlme.bPsPollTimerRunning == TRUE)) || + (Level == RTMP_HALT)) { pAd->Mlme.bPsPollTimerRunning = FALSE; RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP); - RTMPusecDelay(3000); + RTMPusecDelay(5000); DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n")); } AutoWakeupCfg.word = 0; RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE)) - { - // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. - if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) - && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) - { - // Must using 40MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); - } - else - { - // Must using 20MHz. - AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); - AsicLockChannel(pAd, pAd->CommonCfg.Channel); - } - } + // If this is called from Halt. ALWAYS force wakeup!!! + if (Level == RTMP_HALT) + { + RT28xxPciAsicRadioOn(pAd, RTMP_HALT); + } + else + { + if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE)) + { + // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again. + if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel) + && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + // Must using 20MHz. + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + } + } } else { @@ -1122,6 +1143,7 @@ VOID RT28xxPciMlmeRadioOn( { NICResetFromError(pAd); + /* RTMPRingCleanUp(pAd, QID_AC_BK); RTMPRingCleanUp(pAd, QID_AC_BE); RTMPRingCleanUp(pAd, QID_AC_VI); @@ -1129,6 +1151,7 @@ VOID RT28xxPciMlmeRadioOn( RTMPRingCleanUp(pAd, QID_HCCA); RTMPRingCleanUp(pAd, QID_MGMT); RTMPRingCleanUp(pAd, QID_RX); + */ // Enable Tx/Rx RTMPEnableRxTx(pAd); @@ -1162,6 +1185,12 @@ VOID RT28xxPciMlmeRadioOFF( WPDMA_GLO_CFG_STRUC GloCfg; UINT32 i; + if (pAd->StaCfg.bRadio == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE,("-->MlmeRadioOff() return on bRadio == TRUE; \n")); + return; + } + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) return; @@ -1169,13 +1198,12 @@ VOID RT28xxPciMlmeRadioOFF( // Set LED RTMPSetLED(pAd, LED_RADIO_OFF); - // Set Radio off flag - RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { BOOLEAN Cancelled; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); @@ -1185,6 +1213,15 @@ VOID RT28xxPciMlmeRadioOFF( if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { BOOLEAN Cancelled; + + // Always radio on since the NIC needs to set the MCU command (LED_RADIO_OFF). + if ((pAd->OpMode == OPMODE_STA) && + (IDLE_ON(pAd)) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); + } + pAd->Mlme.bPsPollTimerRunning = FALSE; RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); @@ -1197,9 +1234,26 @@ VOID RT28xxPciMlmeRadioOFF( //========================================== // Clean up old bss table BssTableInit(&pAd->ScanTab); + + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_HCCA); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) + { + RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 500); + return; + } } #endif // CONFIG_STA_SUPPORT // + // Set Radio off flag + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + // Disable Tx/Rx DMA RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA GloCfg.field.EnableTxDMA = 0; diff --git a/drivers/staging/rt2860/common/cmm_info.c b/drivers/staging/rt2860/common/cmm_info.c index dd92ac6eaed2..c3e13195e121 100644 --- a/drivers/staging/rt2860/common/cmm_info.c +++ b/drivers/staging/rt2860/common/cmm_info.c @@ -814,7 +814,6 @@ INT Show_DescInfo_Proc( IN PRTMP_ADAPTER pAd, IN PUCHAR arg) { -#ifdef RT2860 INT i, QueIdx=0; PRT28XX_RXD_STRUC pRxD; PTXD_STRUC pTxD; @@ -845,7 +844,6 @@ INT Show_DescInfo_Proc( hex_dump("Rx Descriptor", (char *)pRxD, 16); printk("pRxD->DDONE = %x\n", pRxD->DDONE); } -#endif // RT2860 // return TRUE; } @@ -1803,9 +1801,7 @@ VOID RTMPAddWcidAttributeEntry( } // For key index and ext IV bit, so only need to update the position(offset+3). -#ifdef RT2860 RTMP_IO_WRITE8(pAd, offset+3, IVEIV); -#endif // RT2860 // DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg])); DBGPRINT(RT_DEBUG_TRACE,(" WCIDAttri = 0x%x \n", WCIDAttri)); @@ -2827,9 +2823,7 @@ INT Set_OpMode_Proc( Value = simple_strtol(arg, 0, 10); -#ifdef RT2860 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) -#endif // RT2860 // { DBGPRINT(RT_DEBUG_ERROR, ("Can not switch operate mode on interface up !! \n")); return FALSE; diff --git a/drivers/staging/rt2860/common/cmm_sync.c b/drivers/staging/rt2860/common/cmm_sync.c index 40e4109118e0..d29e0b630e2e 100644 --- a/drivers/staging/rt2860/common/cmm_sync.c +++ b/drivers/staging/rt2860/common/cmm_sync.c @@ -470,7 +470,7 @@ VOID ScanNextChannel( { // BBP and RF are not accessible in PS mode, we has to wake them up first if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) - AsicForceWakeup(pAd, TRUE); + AsicForceWakeup(pAd, FROM_TX); // leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON if (pAd->StaCfg.Psm == PWR_SAVE) diff --git a/drivers/staging/rt2860/common/cmm_wpa.c b/drivers/staging/rt2860/common/cmm_wpa.c index 81c332ac2524..69baf522fa01 100644 --- a/drivers/staging/rt2860/common/cmm_wpa.c +++ b/drivers/staging/rt2860/common/cmm_wpa.c @@ -39,8 +39,10 @@ // WPA OUI UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00}; UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01}; UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02}; UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04}; +UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05}; UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01}; UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02}; // WPA2 OUI @@ -49,6 +51,7 @@ UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02}; UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04}; UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01}; UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02}; +UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05}; // MSA OUI UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06 UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06 @@ -367,6 +370,24 @@ static VOID RTMPInsertRsnIeCipher( break; } +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) + { + UINT GroupCipher = pAd->StaCfg.GroupCipher; + switch(GroupCipher) + { + case Ndis802_11GroupWEP40Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4); + break; + case Ndis802_11GroupWEP104Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4); + break; + } + } +#endif // CONFIG_STA_SUPPORT // + // swap for big-endian platform pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); @@ -427,11 +448,28 @@ static VOID RTMPInsertRsnIeCipher( break; } +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) + { + UINT GroupCipher = pAd->StaCfg.GroupCipher; + switch(GroupCipher) + { + case Ndis802_11GroupWEP40Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4); + break; + case Ndis802_11GroupWEP104Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4); + break; + } + } +#endif // CONFIG_STA_SUPPORT // + // swap for big-endian platform pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); } - } /* diff --git a/drivers/staging/rt2860/common/mlme.c b/drivers/staging/rt2860/common/mlme.c index 229747095aec..c00f9ab9c46c 100644 --- a/drivers/staging/rt2860/common/mlme.c +++ b/drivers/staging/rt2860/common/mlme.c @@ -527,7 +527,6 @@ NDIS_STATUS MlmeInit( #ifdef CONFIG_STA_SUPPORT -#ifdef RT2860 IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) @@ -537,7 +536,6 @@ NDIS_STATUS MlmeInit( RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE); } } -#endif // RT2860 // #endif // CONFIG_STA_SUPPORT // } while (FALSE); @@ -711,13 +709,11 @@ VOID MlmeHalt( RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); -#ifdef RT2860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled); } -#endif // RT2860 // #ifdef QOS_DLS_SUPPORT for (i=0; iStaCfg.WepStatus)); + //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0. + //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1. + if(pAd->StaCfg.WepStatus<2) + { + pAd->StaCfg.WpaSupplicantUP = 0; + } + else + { + pAd->StaCfg.WpaSupplicantUP = 1; + } + #ifdef CONFIG_STA_SUPPORT -#ifdef RT2860 IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. // Move code to here, because following code will return when radio is off - if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && (pAd->StaCfg.bHardwareRadio == TRUE) && + if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && + (pAd->StaCfg.bHardwareRadio == TRUE) && + (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && - (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && - (pAd->bPCIclkOff == FALSE)) + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { UINT32 data = 0; // Read GPIO pin2 as Hardware controlled radio state - RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); + RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data); if (data & 0x04) { pAd->StaCfg.bHwRadio = TRUE; @@ -849,7 +858,6 @@ VOID MlmePeriodicExec( } } } -#endif // RT2860 // #endif // CONFIG_STA_SUPPORT // // Do nothing if the driver is starting halt state. @@ -860,6 +868,45 @@ VOID MlmePeriodicExec( fRTMP_ADAPTER_RESET_IN_PROGRESS)))) return; + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE)) + { + // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1. + pAd->SameRxByteCount++; + } + else + pAd->SameRxByteCount = 0; + + // If after BBP, still not work...need to check to reset PBF&MAC. + if (pAd->SameRxByteCount == 702) + { + pAd->SameRxByteCount = 0; + AsicResetPBF(pAd); + AsicResetMAC(pAd); + } + + // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode. + if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600))) + { + if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700)) + { + DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount)); + pAd->SameRxByteCount = 700; + AsicResetBBP(pAd); + } + } + + // Update lastReceiveByteCount. + pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount; + + if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd))) + { + pAd->CheckDmaBusyCount = 0; + AsicResetFromDMABusy(pAd); + } + } + RT28XX_MLME_PRE_SANITY_CHECK(pAd); #ifdef RALINK_ATE @@ -1022,9 +1069,7 @@ VOID MlmePeriodicExec( #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { -#ifdef RT2860 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE)) -#endif // RT2860 // { // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock // and sending CTS-to-self over and over. @@ -1081,6 +1126,19 @@ VOID STAMlmePeriodicExec( pAd->StaCfg.bBlockAssoc = FALSE; } + //Baron 2008/07/10 + //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus)); + //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0. + //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1. + if(pAd->StaCfg.WepStatus<2) + { + pAd->StaCfg.WpaSupplicantUP = 0; + } + else + { + pAd->StaCfg.WpaSupplicantUP = 1; + } + if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent)) { if (pAd->IndicateMediaState == NdisMediaStateConnected) @@ -1090,6 +1148,15 @@ VOID STAMlmePeriodicExec( pAd->PreMediaState = pAd->IndicateMediaState; } + if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) && + (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && + (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) && + (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && + (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0); + } @@ -2781,7 +2848,7 @@ VOID MlmeCheckPsmChange( if (INFRA_ON(pAd) && (PowerMode != Ndis802_11PowerModeCAM) && (pAd->StaCfg.Psm == PWR_ACTIVE) && - (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) + RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)) { NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime); pAd->RalinkCounters.RxCountSinceLastNULL = 0; @@ -4065,7 +4132,9 @@ VOID BssTableSsidSort( continue; // check group cipher - if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) + if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) && + (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) && + (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled)) continue; // check pairwise cipher, skip if none matched @@ -4084,7 +4153,9 @@ VOID BssTableSsidSort( continue; // check group cipher - if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher) + if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) && + (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) && + (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled)) continue; // check pairwise cipher, skip if none matched @@ -4371,8 +4442,10 @@ VOID BssCipherParse( switch (*pTmp) { case 1: - case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway - pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; + pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled; + break; + case 5: + pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled; break; case 2: pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled; @@ -4489,8 +4562,10 @@ VOID BssCipherParse( switch (pCipher->Type) { case 1: - case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway - pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled; + pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled; + break; + case 5: + pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled; break; case 2: pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled; @@ -4953,16 +5028,13 @@ BOOLEAN MlmeDequeue( VOID MlmeRestartStateMachine( IN PRTMP_ADAPTER pAd) { -#ifdef RT2860 MLME_QUEUE_ELEM *Elem = NULL; -#endif // RT2860 // #ifdef CONFIG_STA_SUPPORT BOOLEAN Cancelled; #endif // CONFIG_STA_SUPPORT // DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); -#ifdef RT2860 NdisAcquireSpinLock(&pAd->Mlme.TaskLock); if(pAd->Mlme.bRunning) { @@ -4990,7 +5062,6 @@ VOID MlmeRestartStateMachine( DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n")); } } -#endif // RT2860 // #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) @@ -5039,12 +5110,10 @@ VOID MlmeRestartStateMachine( } #endif // CONFIG_STA_SUPPORT // -#ifdef RT2860 // Remove running state NdisAcquireSpinLock(&pAd->Mlme.TaskLock); pAd->Mlme.bRunning = FALSE; NdisReleaseSpinLock(&pAd->Mlme.TaskLock); -#endif // RT2860 // } /*! \brief test if the MLME Queue is empty @@ -6149,6 +6218,12 @@ VOID AsicAdjustTxPower( ULONG TxPwr[5]; CHAR Value; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) + || (pAd->bPCIclkOff == TRUE) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + return; + if (pAd->CommonCfg.BBPCurrentBW == BW_40) { if (pAd->CommonCfg.CentralChannel > 14) @@ -6493,10 +6568,10 @@ VOID AsicForceSleep( */ VOID AsicForceWakeup( IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx) + IN UCHAR Level) { DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n")); - RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx); + RT28XX_STA_FORCE_WAKEUP(pAd, Level); } #endif // CONFIG_STA_SUPPORT // /* @@ -6710,7 +6785,6 @@ VOID AsicEnableIbssSync( csr9.field.bTsfTicking = 0; RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); -#ifdef RT2860 // move BEACON TXD and frame content to on-chip memory ptr = (PUCHAR)&pAd->BeaconTxWI; for (i=0; iCommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU @@ -7097,9 +7170,7 @@ VOID AsicAddSharedKeyEntry( { ULONG offset; //, csr0; SHAREDKEY_MODE_STRUC csr1; -#ifdef RT2860 INT i; -#endif // RT2860 // DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx)); //============================================================================================ @@ -7121,7 +7192,6 @@ VOID AsicAddSharedKeyEntry( // // fill key material - key + TX MIC + RX MIC // -#ifdef RT2860 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE; for (i=0; iTxTsc; UCHAR CipherAlg = pCipherKey->CipherAlg; SHAREDKEY_MODE_STRUC csr1; -#ifdef RT2860 UCHAR i; -#endif // RT2860 // DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n")); // @@ -7337,7 +7404,6 @@ VOID AsicAddKeyEntry( // 2.) Set Key to Asic // //for (i = 0; i < KeyLen; i++) -#ifdef RT2860 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++) { RTMP_IO_WRITE8(pAd, offset + i, pKey[i]); @@ -7363,7 +7429,6 @@ VOID AsicAddKeyEntry( RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]); } } -#endif // RT2860 // // @@ -7372,7 +7437,6 @@ VOID AsicAddKeyEntry( // if (bTxKey) { -#ifdef RT2860 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); // // Write IV @@ -7395,7 +7459,6 @@ VOID AsicAddKeyEntry( { RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]); } -#endif // RT2860 // AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable); } @@ -7461,12 +7524,10 @@ VOID AsicAddPairwiseKeyEntry( // EKEY offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); -#ifdef RT2860 for (i=0; i= 100) { -#ifdef RT2860 #ifdef RALINK_ATE if (pAd->ate.bFWLoading == TRUE) { @@ -7583,14 +7637,33 @@ BOOLEAN AsicSendCommandToMcu( } else #endif // RALINK_ATE // -#endif // RT2860 // { + UINT32 Data; + + // Reset DMA + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); + Data |= 0x2; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); + + // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too. + // Reset DMA/CPU ring index + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_HCCA); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + // Clear Reset + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); + Data &= 0xfffffffd; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); } - return FALSE; + //return FALSE; } -#ifdef RT2860 #ifdef RALINK_ATE else if (pAd->ate.bFWLoading == TRUE) { @@ -7600,7 +7673,6 @@ BOOLEAN AsicSendCommandToMcu( j = 0; } #endif // RALINK_ATE // -#endif // RT2860 // H2MMailbox.field.Owner = 1; // pass ownership to MCU H2MMailbox.field.CmdToken = Token; @@ -7619,7 +7691,6 @@ BOOLEAN AsicSendCommandToMcu( return TRUE; } -#ifdef RT2860 BOOLEAN AsicCheckCommanOk( IN PRTMP_ADAPTER pAd, IN UCHAR Command) @@ -7684,7 +7755,6 @@ BOOLEAN AsicCheckCommanOk( return FALSE; } -#endif // RT2860 // /* ======================================================================== @@ -8096,10 +8166,8 @@ VOID AsicEvaluateRxAnt( } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); #ifdef CONFIG_STA_SUPPORT -#ifdef RT2860 IF_DEV_CONFIG_OPMODE_ON_STA(pAd) pAd->StaCfg.BBPR3 = BBPR3; -#endif // RT2860 // #endif // CONFIG_STA_SUPPORT // if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) ) @@ -8211,9 +8279,7 @@ VOID AsicRxAntEvalTimeout( BBPR3 |= (0x0); } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); -#ifdef RT2860 - pAd->StaCfg.BBPR3 = BBPR3; -#endif // RT2860 // + pAd->StaCfg.BBPR3 = BBPR3; } #endif // CONFIG_STA_SUPPORT // @@ -8439,10 +8505,7 @@ VOID AsicStaBbpTuning( && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) ) && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) -#ifdef RT2860 - && (pAd->bPCIclkOff == FALSE) -#endif // RT2860 // - ) + && (pAd->bPCIclkOff == FALSE)) { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value); R66 = OrigR66Value; @@ -8518,6 +8581,106 @@ VOID AsicStaBbpTuning( } } + +VOID AsicResetFromDMABusy( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Data; + BOOLEAN bCtrl = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n")); + + // Be sure restore link control value so we can write register. + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); + if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) + { + DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n")); + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT); + RTMPusecDelay(6000); + pAd->bPCIclkOff = FALSE; + bCtrl = TRUE; + } + // Reset DMA + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); + Data |= 0x2; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); + + // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too. + // Reset DMA/CPU ring index + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_HCCA); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + // Clear Reset + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); + Data &= 0xfffffffd; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); + + // If in Radio off, should call RTMPPCIePowerLinkCtrl again. + if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE)) + RTMPPCIeLinkCtrlSetting(pAd, 3); + + RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS); + DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n")); +} + +VOID AsicResetBBP( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n")); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); + + // After hard-reset BBP, initialize all BBP values. + NICRestoreBBPValue(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n")); +} + +VOID AsicResetMAC( + IN PRTMP_ADAPTER pAd) +{ + ULONG Data; + + DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n")); + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); + Data |= 0x4; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); + Data &= 0xfffffffb; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n")); +} + +VOID AsicResetPBF( + IN PRTMP_ADAPTER pAd) +{ + ULONG Value1, Value2; + ULONG Data; + + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1); + RTMP_IO_READ32(pAd, PBF_DBG, &Value2); + + Value2 &= 0xff; + // sum should be equals to 0xff, which is the total buffer size. + if ((Value1 + Value2) < 0xff) + { + DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n")); + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data); + Data |= 0x8; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); + Data &= 0xfffffff7; + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n")); + } +} #endif // CONFIG_STA_SUPPORT // VOID RTMPSetAGCInitValue( diff --git a/drivers/staging/rt2860/common/rtmp_init.c b/drivers/staging/rt2860/common/rtmp_init.c index 563f2c5bb856..8a00cee3ee91 100644 --- a/drivers/staging/rt2860/common/rtmp_init.c +++ b/drivers/staging/rt2860/common/rtmp_init.c @@ -149,9 +149,7 @@ RTMP_REG_PAIR MACRegTable[] = { {GF20_PROT_CFG, 0x01744004}, // set 19:18 --> Short NAV for MIMO PS {GF40_PROT_CFG, 0x03F44084}, {MM20_PROT_CFG, 0x01744004}, -#ifdef RT2860 {MM40_PROT_CFG, 0x03F54084}, -#endif // RT2860 // {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, //Extension channel backoff. {TX_RTS_CFG, 0x00092b20}, {EXP_ACK_TIME, 0x002400ca}, // default value @@ -188,9 +186,7 @@ RTMP_REG_PAIR STAMACRegTable[] = { #define FIRMWAREIMAGEV1_LENGTH 0x1000 #define FIRMWAREIMAGEV2_LENGTH 0x1000 -#ifdef RT2860 #define FIRMWARE_MINOR_VERSION 2 -#endif // RT2860 // /* @@ -248,9 +244,7 @@ NDIS_STATUS RTMPAllocAdapterBlock( // Init spin locks NdisAllocateSpinLock(&pAd->MgmtRingLock); -#ifdef RT2860 NdisAllocateSpinLock(&pAd->RxRingLock); -#endif // RT2860 // for (index =0 ; index < NUM_OF_TX_RING; index++) { @@ -1555,10 +1549,7 @@ VOID NICInitAsicFromEEPROM( pAd->LedCntl.word = 0x01; pAd->Led1 = 0x5555; pAd->Led2 = 0x2221; - -#ifdef RT2860 pAd->Led3 = 0xA9F8; -#endif // RT2860 // } AsicSendCommandToMcu(pAd, 0x52, 0xff, (UCHAR)pAd->Led1, (UCHAR)(pAd->Led1 >> 8)); @@ -1594,12 +1585,10 @@ VOID NICInitAsicFromEEPROM( else { RTMPSetLED(pAd, LED_RADIO_ON); -#ifdef RT2860 AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00); // 2-1. wait command ok. AsicCheckCommanOk(pAd, PowerWakeCID); -#endif // RT2860 // } } #endif // CONFIG_STA_SUPPORT // @@ -1677,10 +1666,8 @@ NDIS_STATUS NICInitializeAdapter( { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; WPDMA_GLO_CFG_STRUC GloCfg; -#ifdef RT2860 UINT32 Value; DELAY_INT_CFG_STRUC IntCfg; -#endif // RT2860 // ULONG i =0, j=0; AC_TXOP_CSR0_STRUC csr0; @@ -1719,11 +1706,9 @@ retry: // asic simulation sequence put this ahead before loading firmware. // pbf hardware reset -#ifdef RT2860 RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f); // 0x10000 for reset rx, 0x3f resets all 6 tx rings. RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f); RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00); -#endif // RT2860 // // Initialze ASIC for TX & Rx operation if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS) @@ -1737,7 +1722,6 @@ retry: } -#ifdef RT2860 // Write AC_BK base address register Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa); RTMP_IO_WRITE32(pAd, TX_BASE_PTR1, Value); @@ -1810,7 +1794,6 @@ retry: // Write RX_RING_CSR register Value = RX_RING_SIZE; RTMP_IO_WRITE32(pAd, RX_MAX_CNT, Value); -#endif // RT2860 // // WMM parameter @@ -1829,7 +1812,6 @@ retry: RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word); -#ifdef RT2860 // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: i = 0; do @@ -1848,7 +1830,6 @@ retry: IntCfg.word = 0; RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word); -#endif // RT2860 // // reset action @@ -1889,7 +1870,6 @@ NDIS_STATUS NICInitializeAsic( DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n")); -#ifdef RT2860 if (bHardReset == TRUE) { RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3); @@ -1914,7 +1894,6 @@ NDIS_STATUS NICInitializeAsic( } } #endif // CONFIG_STA_SUPPORT // -#endif // RT2860 // // @@ -2041,6 +2020,131 @@ NDIS_STATUS NICInitializeAsic( return NDIS_STATUS_SUCCESS; } + +VOID NICRestoreBBPValue( + IN PRTMP_ADAPTER pAd) +{ + UCHAR index; + UCHAR Value = 0; + ULONG Data; + + DBGPRINT(RT_DEBUG_TRACE, ("---> NICRestoreBBPValue !!!!!!!!!!!!!!!!!!!!!!! \n")); + // Initialize BBP register to default value (rtmp_init.c) + for (index = 0; index < NUM_BBP_REG_PARMS; index++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[index].Register, BBPRegTable[index].Value); + } + // copy from (rtmp_init.c) + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12); + } + + // copy from (connect.c LinkUp function) + if (INFRA_ON(pAd)) + { + // Change to AP channel + if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + // RX : control channel at lower + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + // Record BBPR3 setting, But don't keep R Antenna # information. + pAd->StaCfg.BBPR3 = Value; + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); + } + else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + // Record BBPR3 setting, But don't keep R Antenna # information. + pAd->StaCfg.BBPR3 = Value; + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); + } + else + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + // Record BBPR3 setting, But don't keep R Antenna # information. + pAd->StaCfg.BBPR3 = Value; + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz LINK UP !!! \n" )); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<--- NICRestoreBBPValue !!!!!!!!!!!!!!!!!!!!!!! \n")); +} + /* ======================================================================== @@ -3028,11 +3132,10 @@ VOID UserCfgInit( pAd->CommonCfg.BBPCurrentBW = BW_20; pAd->LedCntl.word = 0; -#ifdef RT2860 pAd->LedIndicatorStregth = 0; pAd->RLnkCtrlOffset = 0; pAd->HostLnkCtrlOffset = 0; -#endif // RT2860 // + pAd->CheckDmaBusyCount = 0; pAd->bAutoTxAgcA = FALSE; // Default is OFF pAd->bAutoTxAgcG = FALSE; // Default is OFF @@ -3292,9 +3395,7 @@ VOID UserCfgInit( pAd->ate.bRxFer = 0; pAd->ate.bQATxStart = FALSE; pAd->ate.bQARxStart = FALSE; -#ifdef RT2860 pAd->ate.bFWLoading = FALSE; -#endif // RT2860 // #ifdef RALINK_28xx_QA //pAd->ate.Repeat = 0; pAd->ate.TxStatus = 0; @@ -3304,11 +3405,9 @@ VOID UserCfgInit( pAd->CommonCfg.bWiFiTest = FALSE; -#ifdef RT2860 - pAd->bPCIclkOff = FALSE; -#endif // RT2860 // - + pAd->bPCIclkOff = FALSE; + RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n")); } diff --git a/drivers/staging/rt2860/common/spectrum.c b/drivers/staging/rt2860/common/spectrum.c index 0265a6d1df1a..b3650ec46563 100644 --- a/drivers/staging/rt2860/common/spectrum.c +++ b/drivers/staging/rt2860/common/spectrum.c @@ -1596,7 +1596,7 @@ static VOID PeerMeasureReportAction( if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL) { - DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __func__, sizeof(MEASURE_RPI_REPORT))); + DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%zu).\n", __func__, sizeof(MEASURE_RPI_REPORT))); return; } diff --git a/drivers/staging/rt2860/config.mk b/drivers/staging/rt2860/config.mk index f57d7bbffb24..25bd55a7aab3 100644 --- a/drivers/staging/rt2860/config.mk +++ b/drivers/staging/rt2860/config.mk @@ -108,10 +108,6 @@ ifeq ($(HAS_EXT_BUILD_CHANNEL_LIST),y) WFLAGS += -DEXT_BUILD_CHANNEL_LIST endif -ifeq ($(CHIPSET),2860) -WFLAGS +=-DRT2860 -endif - ifeq ($(CHIPSET),2870) WFLAGS +=-DRT2870 endif diff --git a/drivers/staging/rt2860/oid.h b/drivers/staging/rt2860/oid.h index f2f91b607c47..5e6ed9f62f9d 100644 --- a/drivers/staging/rt2860/oid.h +++ b/drivers/staging/rt2860/oid.h @@ -544,6 +544,8 @@ typedef enum _NDIS_802_11_WEP_STATUS Ndis802_11Encryption3KeyAbsent, Ndis802_11Encryption4Enabled, // TKIP or AES mix Ndis802_11Encryption4KeyAbsent, + Ndis802_11GroupWEP40Enabled, + Ndis802_11GroupWEP104Enabled, } NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; diff --git a/drivers/staging/rt2860/rt2860.h b/drivers/staging/rt2860/rt2860.h index 017201906628..4fbec906e106 100644 --- a/drivers/staging/rt2860/rt2860.h +++ b/drivers/staging/rt2860/rt2860.h @@ -46,18 +46,10 @@ Status = NDIS_STATUS_SUCCESS; /* function declarations */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #define IRQ_HANDLE_TYPE irqreturn_t -#else -#define IRQ_HANDLE_TYPE void -#endif IRQ_HANDLE_TYPE -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) rt2860_interrupt(int irq, void *dev_instance); -#else -rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -#endif /* ----------------- Frimware Related MACRO ----------------- */ #define RT28XX_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ @@ -237,9 +229,7 @@ rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); #define RTMP_MSI_DISABLE(_pAd) #endif // PCI_MSI_SUPPORT // -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) #define SA_SHIRQ IRQF_SHARED -#endif #define RT28XX_IRQ_REQUEST(net_dev) \ { PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->ml_priv); \ @@ -251,20 +241,12 @@ rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); printk("RT2860: request_irq ERROR(%d)\n", retval); \ return retval; } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #define RT28XX_IRQ_RELEASE(net_dev) \ { PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->ml_priv); \ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ synchronize_irq(_pObj->pci_dev->irq); \ free_irq(_pObj->pci_dev->irq, (net_dev)); \ RTMP_MSI_DISABLE(_pAd); } -#else -#define RT28XX_IRQ_RELEASE(net_dev) \ -{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->priv); \ - POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \ - free_irq(_pObj->pci_dev->irq, (net_dev)); \ - RTMP_MSI_DISABLE(_pAd); } -#endif #define RT28XX_IRQ_INIT(pAd) \ { pAd->int_enable_reg = ((DELAYINTMASK) | \ @@ -333,8 +315,8 @@ rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); reg16 = cpu2le16(Configuration); \ pci_write_config_word(pci_dev, offset, reg16); \ -#define RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx) \ - RT28xxPciStaAsicForceWakeup(pAd, bFromTx); +#define RT28XX_STA_FORCE_WAKEUP(pAd, Level) \ + RT28xxPciStaAsicForceWakeup(pAd, Level); #define RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp) \ RT28xxPciStaAsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); diff --git a/drivers/staging/rt2860/rt28xx.h b/drivers/staging/rt2860/rt28xx.h index ff23043e560e..e5e6f0a8de63 100644 --- a/drivers/staging/rt2860/rt28xx.h +++ b/drivers/staging/rt2860/rt28xx.h @@ -1670,11 +1670,9 @@ typedef struct _HW_WCID_ENTRY { // 8-byte per entry #define E2PROM_CSR 0x0004 #define IO_CNTL_CSR 0x77d0 -#ifdef RT2860 // 8051 firmware image for RT2860 - base address = 0x4000 #define FIRMWARE_IMAGE_BASE 0x2000 #define MAX_FIRMWARE_IMAGE_SIZE 0x2000 // 8kbyte -#endif // RT2860 // // ================================================================ @@ -2029,7 +2027,6 @@ typedef struct PACKED _TXWI_STRUC { // // Rx descriptor format, Rx Ring // -#ifdef RT2860 #ifdef RT_BIG_ENDIAN typedef struct PACKED _RXD_STRUC { // Word 0 @@ -2098,7 +2095,6 @@ typedef struct PACKED _RXD_STRUC { UINT32 Rsv1:13; } RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; #endif -#endif // RT2860 // // // RXWI wireless information format, in PBF. invisible in driver. // diff --git a/drivers/staging/rt2860/rt_ate.c b/drivers/staging/rt2860/rt_ate.c index f3316ec0b156..1ed73c9e6b60 100644 --- a/drivers/staging/rt2860/rt_ate.c +++ b/drivers/staging/rt2860/rt_ate.c @@ -68,7 +68,6 @@ static int CheckMCSValid( IN UCHAR Mode, IN UCHAR Mcs); -#ifdef RT2860 static VOID ATEWriteTxWI( IN PRTMP_ADAPTER pAd, IN PTXWI_STRUC pOutTxWI, @@ -87,7 +86,6 @@ static VOID ATEWriteTxWI( IN UCHAR Txopmode, IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING *pTransmit); -#endif // RT2860 // static VOID SetJapanFilter( @@ -95,7 +93,6 @@ static VOID SetJapanFilter( /*=========================end of prototype=========================*/ -#ifdef RT2860 static INT TxDmaBusy( IN PRTMP_ADAPTER pAd) { @@ -153,7 +150,6 @@ static VOID RtmpDmaEnable( return; } -#endif // RT2860 // static VOID BbpSoftReset( @@ -488,7 +484,6 @@ static INT ATETxPwrHandler( TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ -#ifdef RT2860 static INT ATECmdHandler( IN PRTMP_ADAPTER pAd, IN PUCHAR arg) @@ -1297,7 +1292,6 @@ static INT ATECmdHandler( return TRUE; } -#endif // RT2860 // /* */ /* */ /*=======================End of RT2860=======================*/ @@ -2907,7 +2901,6 @@ VOID ATEAsicAdjustTxPower( None ======================================================================== */ -#ifdef RT2860 static VOID ATEWriteTxWI( IN PRTMP_ADAPTER pAd, IN PTXWI_STRUC pOutTxWI, @@ -2972,7 +2965,6 @@ static VOID ATEWriteTxWI( return; } -#endif // RT2860 // /* ======================================================================== @@ -3249,13 +3241,11 @@ VOID RTMPStationStart( IN PRTMP_ADAPTER pAd) { ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStart\n")); -#ifdef RT2860 - pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +epAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; // // We did not cancel this timer when entering ATE mode. // // RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); -#endif // RT2860 // ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStart\n")); } #endif // CONFIG_STA_SUPPORT // @@ -3268,7 +3258,6 @@ VOID RTMPStationStart( This routine should only be used in ATE mode. ========================================================================== */ -#ifdef RT2860 static INT ATESetUpFrame( IN PRTMP_ADAPTER pAd, IN UINT32 TxIdx) @@ -3455,7 +3444,6 @@ static INT ATESetUpFrame( /* */ /* */ /*=======================End of RT2860=======================*/ -#endif // RT2860 // VOID rt_ee_read_all(PRTMP_ADAPTER pAd, USHORT *Data) @@ -4578,9 +4566,7 @@ VOID RtmpDoAte( { if (pAdapter->ate.TxCount == 0) { -#ifdef RT2860 pAdapter->ate.TxCount = 0xFFFFFFFF; -#endif // RT2860 // } ATEDBGPRINT(RT_DEBUG_TRACE,("START TXFRAME\n")); pAdapter->ate.bQATxStart = TRUE; @@ -5375,7 +5361,6 @@ TX_START_ERROR: memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); value = ntohs(value); -#ifdef RT2860 /* TX_FRAME_COUNT == 0 means tx infinitely */ if (value == 0) { @@ -5387,7 +5372,6 @@ TX_START_ERROR: } else -#endif // RT2860 // { sprintf((PCHAR)str, "%d", value); Set_ATE_TX_COUNT_Proc(pAdapter, str); diff --git a/drivers/staging/rt2860/rt_ate.h b/drivers/staging/rt2860/rt_ate.h index 48aa70d2f010..38f5c4af5462 100644 --- a/drivers/staging/rt2860/rt_ate.h +++ b/drivers/staging/rt2860/rt_ate.h @@ -31,12 +31,10 @@ #ifndef UCOS #define ate_print printk #define ATEDBGPRINT DBGPRINT -#ifdef RT2860 #define EEPROM_SIZE 0x200 #ifdef CONFIG_STA_SUPPORT #define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860STA/e2p.bin" #endif // CONFIG_STA_SUPPORT // -#endif // RT2860 // #else // !UCOS // #define fATE_LOAD_EEPROM 0x0C43 @@ -69,7 +67,6 @@ do{ int (*org_remote_display)(char *) = NULL; \ #define ATE_ON(_p) (((_p)->ate.Mode) != ATE_STOP) /* RT2880_iNIC will define "RT2860". */ -#ifdef RT2860 #define ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ { \ BBP_CSR_CFG_STRUC BbpCsr; \ @@ -131,10 +128,8 @@ do{ int (*org_remote_display)(char *) = NULL; \ ATEDBGPRINT(RT_DEBUG_ERROR, ("BBP write R%d fail\n", _I)); \ } \ } -#endif // RT2860 // /* RT2880_iNIC will define RT2860. */ -#ifdef RT2860 #define EEPROM_SIZE 0x200 /* iNIC has its own EEPROM_BIN_FILE_NAME */ #ifndef UCOS @@ -142,7 +137,6 @@ do{ int (*org_remote_display)(char *) = NULL; \ #define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860STA/e2p.bin" #endif // CONFIG_STA_SUPPORT // #endif // !UCOS // -#endif // RT2860 // diff --git a/drivers/staging/rt2860/rt_config.h b/drivers/staging/rt2860/rt_config.h index 7ee7a405b026..a67024fb4373 100644 --- a/drivers/staging/rt2860/rt_config.h +++ b/drivers/staging/rt2860/rt_config.h @@ -53,9 +53,7 @@ #include "rtmp_def.h" #include "rt28xx.h" -#ifdef RT2860 #include "rt2860.h" -#endif // RT2860 // #include "oid.h" diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c index f14500931efb..f3c128c72a21 100644 --- a/drivers/staging/rt2860/rt_linux.c +++ b/drivers/staging/rt2860/rt_linux.c @@ -48,10 +48,8 @@ BUILD_TIMER_FUNCTION(LeapAuthTimeout); #endif BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec); BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); -#ifdef RT2860 BUILD_TIMER_FUNCTION(PsPollWakeExec); BUILD_TIMER_FUNCTION(RadioOnExec); -#endif // RT2860 // #ifdef QOS_DLS_SUPPORT BUILD_TIMER_FUNCTION(DlsTimeoutAction); #endif // QOS_DLS_SUPPORT // @@ -293,9 +291,7 @@ VOID RTMPFreeAdapter( NdisFreeSpinLock(&pAd->MgmtRingLock); -#ifdef RT2860 NdisFreeSpinLock(&pAd->RxRingLock); -#endif // RT2860 // for (index =0 ; index < NUM_OF_TX_RING; index++) { @@ -854,7 +850,7 @@ void send_monitor_packets( if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE) { - DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); + DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%zu)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); goto err_free_sk_buff; } @@ -1005,35 +1001,14 @@ err_free_sk_buff: void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify) { - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) daemonize(pThreadName /*"%s",pAd->net_dev->name*/); allow_signal(SIGTERM); allow_signal(SIGKILL); current->flags |= PF_NOFREEZE; -#else - unsigned long flags; - daemonize(); - reparent_to_init(); - strcpy(current->comm, pThreadName); - - siginitsetinv(¤t->blocked, sigmask(SIGTERM) | sigmask(SIGKILL)); - - /* Allow interception of SIGKILL only - * Don't allow other signals to interrupt the transmission */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - spin_lock_irqsave(¤t->sigmask_lock, flags); - flush_signals(current); - recalc_sigpending(current); - spin_unlock_irqrestore(¤t->sigmask_lock, flags); -#endif -#endif - - /* signal that we've started the thread */ + /* signal that we've started the thread */ complete(pNotify); - } void RTMP_IndicateMediaState( diff --git a/drivers/staging/rt2860/rt_linux.h b/drivers/staging/rt2860/rt_linux.h index 0fd58f5109f2..708923cecaa2 100644 --- a/drivers/staging/rt2860/rt_linux.h +++ b/drivers/staging/rt2860/rt_linux.h @@ -65,7 +65,6 @@ #include -#include #include // load firmware @@ -90,28 +89,22 @@ typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_ // add by kathy #ifdef CONFIG_STA_SUPPORT -#ifdef RT2860 #define STA_PROFILE_PATH "/etc/Wireless/RT2860STA/RT2860STA.dat" #define STA_RTMP_FIRMWARE_FILE_NAME "/etc/Wireless/RT2860STA/RT2860STA.bin" #define STA_NIC_DEVICE_NAME "RT2860STA" -#define STA_DRIVER_VERSION "1.8.0.0" +#define STA_DRIVER_VERSION "1.8.1.1" #ifdef MULTIPLE_CARD_SUPPORT #define CARD_INFO_PATH "/etc/Wireless/RT2860STA/RT2860STACard.dat" #endif // MULTIPLE_CARD_SUPPORT // -#endif // RT2860 // #endif // CONFIG_STA_SUPPORT // -#ifdef RT2860 #ifndef PCI_DEVICE #define PCI_DEVICE(vend,dev) \ .vendor = (vend), .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID #endif // PCI_DEVICE // -#endif // RT2860 // - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #define RTMP_TIME_AFTER(a,b) \ (typecheck(unsigned long, (unsigned long)a) && \ @@ -123,11 +116,7 @@ typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_ typecheck(unsigned long, (unsigned long)b) && \ ((long)(a) - (long)(b) >= 0)) #define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) -#else -#define RTMP_TIME_AFTER(a,b) time_after(a, b) -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #define RT_MOD_INC_USE_COUNT() \ if (!try_module_get(THIS_MODULE)) \ { \ @@ -136,10 +125,6 @@ typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_ } #define RT_MOD_DEC_USE_COUNT() module_put(THIS_MODULE); -#else -#define RT_MOD_INC_USE_COUNT() MOD_INC_USE_COUNT; -#define RT_MOD_DEC_USE_COUNT() MOD_DEC_USE_COUNT; -#endif #define OS_HZ HZ @@ -171,21 +156,12 @@ typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_ #define NDIS_PACKET_TYPE_ALL_MULTICAST 3 #endif // CONFIG_STA_SUPPORT // -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) typedef struct pid * THREAD_PID; #define THREAD_PID_INIT_VALUE NULL #define GET_PID(_v) find_get_pid(_v) #define GET_PID_NUMBER(_v) pid_nr(_v) #define CHECK_PID_LEGALITY(_pid) if (pid_nr(_pid) >= 0) #define KILL_THREAD_PID(_A, _B, _C) kill_pid(_A, _B, _C) -#else -typedef pid_t THREAD_PID; -#define THREAD_PID_INIT_VALUE -1 -#define GET_PID(_v) _v -#define GET_PID_NUMBER(_v) _v -#define CHECK_PID_LEGALITY(_pid) if (_pid >= 0) -#define KILL_THREAD_PID(_A, _B, _C) kill_proc(_A, _B, _C) -#endif struct os_lock { spinlock_t lock; @@ -194,11 +170,9 @@ struct os_lock { struct os_cookie { -#ifdef RT2860 struct pci_dev *pci_dev; struct pci_dev *parent_pci_dev; dma_addr_t pAd_pa; -#endif // RT2860 // struct tasklet_struct rx_done_task; @@ -209,9 +183,7 @@ struct os_cookie { struct tasklet_struct ac3_dma_done_task; struct tasklet_struct hcca_dma_done_task; struct tasklet_struct tbtt_task; -#ifdef RT2860 struct tasklet_struct fifo_statistic_full_task; -#endif // RT2860 // unsigned long apd_pid; //802.1x daemon pid @@ -266,7 +238,6 @@ void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int #define RT2860_PCI_DEVICE_ID 0x0601 -#ifdef RT2860 #define PCI_MAP_SINGLE(_handle, _ptr, _size, _sd_idx, _dir) \ linux_pci_map_single(_handle, _ptr, _size, _sd_idx, _dir) @@ -281,7 +252,6 @@ void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int #define DEV_ALLOC_SKB(_length) \ dev_alloc_skb(_length) -#endif // RT2860 // @@ -401,7 +371,6 @@ extern ULONG RTDebugLevel; spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag)); \ } -#ifdef RT2860 #if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(IKANOS_VX_1X0) //Patch for ASIC turst read/write bug, needs to remove after metel fix #define RTMP_IO_READ32(_A, _R, _pV) \ @@ -413,6 +382,12 @@ extern ULONG RTDebugLevel; (*_pV = SWAP32(*((UINT32 *)(_pV)))); \ } \ } +#define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ +{ \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*_pV = SWAP32(*((UINT32 *)(_pV)))); \ +} #define RTMP_IO_READ8(_A, _R, _pV) \ { \ (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ @@ -452,6 +427,11 @@ extern ULONG RTDebugLevel; else \ *_pV = 0; \ } +#define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ +{ \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ +} #define RTMP_IO_READ8(_A, _R, _pV) \ { \ (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \ @@ -492,7 +472,6 @@ extern ULONG RTDebugLevel; writew((_V), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ } #endif -#endif // RT2860 // #ifndef wait_event_interruptible_timeout @@ -544,7 +523,6 @@ typedef void (*TIMER_FUNCTION)(unsigned long); #define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE) #define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA) -#ifdef RT2860 #define BUILD_TIMER_FUNCTION(_func) \ void linux_##_func(unsigned long data) \ { \ @@ -554,7 +532,6 @@ void linux_##_func(unsigned long data) \ if (pTimer->Repeat) \ RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); \ } -#endif // RT2860 // @@ -907,7 +884,6 @@ int rt28xx_packet_xmit(struct sk_buff *skb); void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify); -#ifdef RT2860 #if !defined(PCI_CAP_ID_EXP) #define PCI_CAP_ID_EXP 0x10 #endif @@ -921,6 +897,5 @@ void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify); #endif #define PCIBUS_INTEL_VENDOR 0x8086 -#endif // RT2860 // diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c index 3873c478f4ec..cf17bcdd7333 100644 --- a/drivers/staging/rt2860/rt_main_dev.c +++ b/drivers/staging/rt2860/rt_main_dev.c @@ -58,11 +58,7 @@ UINT32 CW_MAX_IN_BITS; char *mac = ""; // default 00:00:00:00:00:00 char *hostname = ""; // default CMPC -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) -MODULE_PARM (mac, "s"); -#else module_param (mac, charp, 0); -#endif MODULE_PARM_DESC (mac, "rt28xx: wireless mac addr"); @@ -75,9 +71,7 @@ extern void ba_reordering_resource_release(PRTMP_ADAPTER pAd); #endif // DOT11_N_SUPPORT // extern NDIS_STATUS NICLoadRateSwitchingParams(IN PRTMP_ADAPTER pAd); -#ifdef RT2860 extern void init_thread_task(PRTMP_ADAPTER pAd); -#endif // RT2860 // // public function prototype INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p, @@ -87,13 +81,6 @@ INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p, static int rt28xx_init(IN struct net_device *net_dev); INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev); -#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 -struct net_device *alloc_netdev( - int sizeof_priv, - const char *mask, - void (*setup)(struct net_device *)); -#endif // LINUX_VERSION_CODE // - static void CfgInitHook(PRTMP_ADAPTER pAd); #ifdef CONFIG_STA_SUPPORT @@ -235,15 +222,13 @@ int rt28xx_close(IN PNET_DEV dev) #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { -#ifdef RT2860 - RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE); -#endif // RT2860 // - // If dirver doesn't wake up firmware here, // NICLoadFirmware will hang forever when interface is up again. - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || + RTMP_SET_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) { - AsicForceWakeup(pAd, TRUE); + AsicForceWakeup(pAd, RTMP_HALT); } #ifdef QOS_DLS_SUPPORT @@ -323,9 +308,7 @@ int rt28xx_close(IN PNET_DEV dev) #endif // WPA_SUPPLICANT_SUPPORT // MlmeRadioOff(pAd); -#ifdef RT2860 pAd->bPCIclkOff = FALSE; -#endif // RT2860 // } #endif // CONFIG_STA_SUPPORT // @@ -359,7 +342,6 @@ int rt28xx_close(IN PNET_DEV dev) TpcReqTabExit(pAd); -#ifdef RT2860 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) { NICDisableInterrupt(pAd); @@ -375,7 +357,6 @@ int rt28xx_close(IN PNET_DEV dev) RT28XX_IRQ_RELEASE(net_dev) RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); } -#endif // RT2860 // // Free Ring or USB buffers @@ -439,12 +420,10 @@ static int rt28xx_init(IN struct net_device *net_dev) // Disable interrupts here which is as soon as possible // This statement should never be true. We might consider to remove it later -#ifdef RT2860 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) { NICDisableInterrupt(pAd); } -#endif // RT2860 // Status = RTMPAllocTxRxRingMemory(pAd); if (Status != NDIS_STATUS_SUCCESS) @@ -667,26 +646,6 @@ int rt28xx_open(IN PNET_DEV dev) #endif // WIRELESS_EXT >= 12 // #endif // CONFIG_APSTA_MIXED_SUPPORT // -#ifdef CONFIG_STA_SUPPORT -#ifdef RT2860 - IF_DEV_CONFIG_OPMODE_ON_STA(pAd) - { - // If dirver doesn't wake up firmware here, - // NICLoadFirmware will hang forever when interface is up again. - // RT2860 PCI - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) && - OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) - { - AUTO_WAKEUP_STRUC AutoWakeupCfg; - AsicForceWakeup(pAd, TRUE); - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); - OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); - } - } -#endif // RT2860 // -#endif // CONFIG_STA_SUPPORT // - // Init pObj = (POS_COOKIE)pAd->OS_Cookie; @@ -753,10 +712,8 @@ int rt28xx_open(IN PNET_DEV dev) } #ifdef CONFIG_STA_SUPPORT -#ifdef RT2860 IF_DEV_CONFIG_OPMODE_ON_STA(pAd) RTMPInitPCIeLinkCtrlValue(pAd); -#endif // RT2860 // #endif // CONFIG_STA_SUPPORT // return (retval); @@ -808,9 +765,7 @@ static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER p dev->stop = MainVirtualIF_close; //rt28xx_close; dev->priv_flags = INT_MAIN; dev->do_ioctl = rt28xx_ioctl; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - dev->validate_addr = NULL; -#endif + dev->validate_addr = NULL; // find available device name for (i = 0; i < 8; i++) { @@ -821,25 +776,11 @@ static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER p #endif // MULTIPLE_CARD_SUPPORT // sprintf(slot_name, "ra%d", i); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - device = dev_get_by_name(dev_net(dev), slot_name); -#else - device = dev_get_by_name(dev->nd_net, slot_name); -#endif -#else - device = dev_get_by_name(slot_name); -#endif - if (device != NULL) dev_put(device); -#else - for (device = dev_base; device != NULL; device = device->next) - { - if (strncmp(device->name, slot_name, 4) == 0) - break; - } -#endif - if(device == NULL) + device = dev_get_by_name(dev_net(dev), slot_name); + if (device != NULL) + dev_put(device); + + if (device == NULL) break; } @@ -1252,47 +1193,28 @@ INT __devinit rt28xx_probe( PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL; INT status; PVOID handle; -#ifdef RT2860 struct pci_dev *dev_p = (struct pci_dev *)_dev_p; -#endif // RT2860 // #ifdef CONFIG_STA_SUPPORT DBGPRINT(RT_DEBUG_TRACE, ("STA Driver version-%s\n", STA_DRIVER_VERSION)); #endif // CONFIG_STA_SUPPORT // -#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 - net_dev = alloc_netdev(sizeof(PRTMP_ADAPTER), "eth%d", ether_setup); -#else net_dev = alloc_etherdev(sizeof(PRTMP_ADAPTER)); -#endif if (net_dev == NULL) { printk("alloc_netdev failed\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - module_put(THIS_MODULE); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -#else - MOD_DEC_USE_COUNT; -#endif goto err_out; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - SET_MODULE_OWNER(net_dev); -#endif - netif_stop_queue(net_dev); #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT /* for supporting Network Manager */ /* Set the sysfs physical device reference for the network logical device * if set prior to registration will cause a symlink during initialization. */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) SET_NETDEV_DEV(net_dev, &(dev_p->dev)); -#endif #endif // NATIVE_WPA_SUPPLICANT_SUPPORT // // Allocate RTMP_ADAPTER miniport adapter structure @@ -1313,13 +1235,8 @@ INT __devinit rt28xx_probe( #endif // CONFIG_STA_SUPPORT // // Post config -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - if (RT28XXProbePostConfig(_dev_p, pAd, argc) == FALSE) - goto err_out_unmap; -#else if (RT28XXProbePostConfig(_dev_p, pAd, 0) == FALSE) goto err_out_unmap; -#endif // LINUX_VERSION_CODE // #ifdef CONFIG_STA_SUPPORT pAd->OpMode = OPMODE_STA; @@ -1362,20 +1279,12 @@ err_out_unmap: RT28XX_UNMAP(); err_out_free_netdev: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - free_netdev(net_dev); -#else - kfree(net_dev); -#endif + free_netdev(net_dev); err_out: RT28XX_PUT_DEVICE(dev_p); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - return (LONG)NULL; -#else - return -ENODEV; /* probe fail */ -#endif // LINUX_VERSION_CODE // + return -ENODEV; /* probe fail */ } /* End of rt28xx_probe */ @@ -1495,40 +1404,6 @@ INT rt28xx_send_packets( -#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 -struct net_device *alloc_netdev( - int sizeof_priv, - const char *mask, - void (*setup)(struct net_device *)) -{ - struct net_device *dev; - INT alloc_size; - - - /* ensure 32-byte alignment of the private area */ - alloc_size = sizeof (*dev) + sizeof_priv + 31; - - dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL); - if (dev == NULL) - { - DBGPRINT(RT_DEBUG_ERROR, - ("alloc_netdev: Unable to allocate device memory.\n")); - return NULL; - } - - memset(dev, 0, alloc_size); - - if (sizeof_priv) - dev->priv = (void *) (((long)(dev + 1) + 31) & ~31); - - setup(dev); - strcpy(dev->name, mask); - - return dev; -} -#endif // LINUX_VERSION_CODE // - - void CfgInitHook(PRTMP_ADAPTER pAd) { pAd->bBroadComHT = TRUE; diff --git a/drivers/staging/rt2860/rt_profile.c b/drivers/staging/rt2860/rt_profile.c index 326a3cb52b9c..62141f376972 100644 --- a/drivers/staging/rt2860/rt_profile.c +++ b/drivers/staging/rt2860/rt_profile.c @@ -1451,7 +1451,7 @@ NDIS_STATUS RTMPReadParametersHook( IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { //PSMode - if (RTMPGetKeyParameter("PSMode", tmpbuf, 10, buffer)) + if (RTMPGetKeyParameter("PSMode", tmpbuf, 32, buffer)) { if (pAd->StaCfg.BssType == BSS_INFRA) { diff --git a/drivers/staging/rt2860/rtmp.h b/drivers/staging/rt2860/rtmp.h index 411954206c28..b904b7886c28 100644 --- a/drivers/staging/rt2860/rtmp.h +++ b/drivers/staging/rt2860/rtmp.h @@ -203,9 +203,7 @@ typedef struct _ATE_INFO { BOOLEAN bRxFer; BOOLEAN bQATxStart; // Have compiled QA in and use it to ATE tx. BOOLEAN bQARxStart; // Have compiled QA in and use it to ATE rx. -#ifdef RT2860 BOOLEAN bFWLoading; // Reload firmware when ATE is done. -#endif // RT2860 // UINT32 RxTotalCnt; UINT32 RxCntPerSec; @@ -366,6 +364,13 @@ typedef struct _QUEUE_HEADER { #define RTMP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0) #define RTMP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F)) +// Macro for power save flag. +#define RTMP_SET_PSFLAG(_M, _F) ((_M)->PSFlags |= (_F)) +#define RTMP_CLEAR_PSFLAG(_M, _F) ((_M)->PSFlags &= ~(_F)) +#define RTMP_CLEAR_PSFLAGS(_M) ((_M)->PSFlags = 0) +#define RTMP_TEST_PSFLAG(_M, _F) (((_M)->PSFlags & (_F)) != 0) +#define RTMP_TEST_PSFLAGS(_M, _F) (((_M)->PSFlags & (_F)) == (_F)) + #define OPSTATUS_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags |= (_F)) #define OPSTATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags &= ~(_F)) #define OPSTATUS_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.OpStatusFlags & (_F)) != 0) @@ -478,7 +483,6 @@ typedef struct _QUEUE_HEADER { // #define MAX_BUSY_COUNT 100 // Number of retry before failing access BBP & RF indirect register // -#ifdef RT2860 #define RTMP_RF_IO_WRITE32(_A, _V) \ { \ PHY_CSR4_STRUC Value; \ @@ -642,7 +646,6 @@ typedef struct _QUEUE_HEADER { } \ } \ } -#endif // RT2860 // #define MAP_CHANNEL_ID_TO_KHZ(ch, khz) { \ @@ -894,7 +897,6 @@ typedef struct _RTMP_SCATTER_GATHER_LIST { // Enqueue this frame to MLME engine // We need to enqueue the whole frame because MLME need to pass data type // information from 802.11 header -#ifdef RT2860 #define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _PlcpSignal) \ { \ UINT32 High32TSF, Low32TSF; \ @@ -902,7 +904,6 @@ typedef struct _RTMP_SCATTER_GATHER_LIST { RTMP_IO_READ32(_pAd, TSF_TIMER_DW0, &Low32TSF); \ MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2,_FrameSize, _pFrame, (UCHAR)_PlcpSignal); \ } -#endif // RT2860 // #define NDIS_QUERY_BUFFER(_NdisBuf, _ppVA, _pBufLen) \ NdisQueryBuffer(_NdisBuf, _ppVA, _pBufLen) @@ -919,9 +920,10 @@ typedef struct _RTMP_SCATTER_GATHER_LIST { #define STA_PORT_SECURED(_pAd) \ { \ _pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \ - NdisAcquireSpinLock(&_pAd->MacTabLock); \ + RTMP_SET_PSFLAG(_pAd, fRTMP_PS_CAN_GO_SLEEP); \ + NdisAcquireSpinLock(&(_pAd)->MacTabLock); \ _pAd->MacTab.Content[BSSID_WCID].PortSecured = _pAd->StaCfg.PortSecured; \ - NdisReleaseSpinLock(&_pAd->MacTabLock); \ + NdisReleaseSpinLock(&(_pAd)->MacTabLock); \ } #endif // CONFIG_STA_SUPPORT // @@ -1000,9 +1002,7 @@ typedef struct _RTMP_REORDERBUF UCHAR DataOffset; USHORT Datasize; ULONG AllocSize; -#ifdef RT2860 NDIS_PHYSICAL_ADDRESS AllocPa; // TxBuf physical address -#endif // RT2860 // } RTMP_REORDERBUF, *PRTMP_REORDERBUF; // @@ -1101,6 +1101,7 @@ typedef struct _COUNTER_802_11 { typedef struct _COUNTER_RALINK { ULONG TransmittedByteCount; // both successful and failure, used to calculate TX throughput + ULONG LastReceivedByteCount; ULONG ReceivedByteCount; // both CRC okay and CRC error, used to calculate RX throughput ULONG BeenDisassociatedCount; ULONG BadCQIAutoRecoveryCount; @@ -1436,11 +1437,9 @@ typedef struct _MLME_STRUCT { RALINK_TIMER_STRUCT APSDPeriodicTimer; RALINK_TIMER_STRUCT LinkDownTimer; RALINK_TIMER_STRUCT LinkUpTimer; -#ifdef RT2860 UCHAR bPsPollTimerRunning; RALINK_TIMER_STRUCT PsPollTimer; RALINK_TIMER_STRUCT RadioOnOffTimer; -#endif // RT2860 // ULONG PeriodicRound; ULONG OneSecPeriodicRound; @@ -2228,9 +2227,7 @@ typedef struct _STA_ADMIN_CONFIG { RT_HT_PHY_INFO DesiredHtPhyInfo; BOOLEAN bAutoTxRateSwitch; -#ifdef RT2860 UCHAR BBPR3; -#endif // RT2860 // #ifdef EXT_BUILD_CHANNEL_LIST UCHAR IEEE80211dClientMode; @@ -2663,7 +2660,6 @@ typedef struct _RTMP_ADAPTER PNET_DEV net_dev; ULONG VirtualIfCnt; -#ifdef RT2860 USHORT LnkCtrlBitMask; USHORT RLnkCtrlConfiguration; USHORT RLnkCtrlOffset; @@ -2671,7 +2667,9 @@ typedef struct _RTMP_ADAPTER USHORT HostLnkCtrlOffset; USHORT PCIePowerSaveLevel; BOOLEAN bPCIclkOff; // flag that indicate if the PICE power status in Configuration SPace.. - BOOLEAN bPCIclkOffDisableTx; // + ULONG CheckDmaBusyCount; // Check Interrupt Status Register Count. + USHORT ThisTbttNumToNextWakeUp; + ULONG SameRxByteCount; /*****************************************************************************************/ @@ -2688,7 +2686,6 @@ typedef struct _RTMP_ADAPTER RTMP_DMABUF RxDescRing; // Shared memory for RX descriptors RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; // Shared memory for Tx descriptors RTMP_TX_RING TxRing[NUM_OF_TX_RING]; // AC0~4 + HCCA -#endif // RT2860 // NDIS_SPIN_LOCK irq_lock; @@ -2721,10 +2718,8 @@ typedef struct _RTMP_ADAPTER /* Rx related parameters */ /*****************************************************************************************/ -#ifdef RT2860 RTMP_RX_RING RxRing; NDIS_SPIN_LOCK RxRingLock; // Rx Ring spinlock -#endif // RT2860 // @@ -2895,6 +2890,7 @@ typedef struct _RTMP_ADAPTER // flags, see fRTMP_ADAPTER_xxx flags ULONG Flags; // Represent current device status + ULONG PSFlags; // Power Save operation flag. // current TX sequence # USHORT Sequence; @@ -3181,7 +3177,6 @@ typedef struct _TX_BLK_ //------------------------------------------------------------------------------------------ -#ifdef RT2860 // // Enable & Disable NIC interrupt via writing interrupt mask register // Since it use ADAPTER structure, it have to be put after structure definition. @@ -3214,7 +3209,6 @@ __inline VOID NICEnableInterrupt( //RTMP_IO_WRITE32(pAd, PBF_INT_ENA, 0x00000030); // 1 : enable RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE); } -#endif // RT2860 // #ifdef RT_BIG_ENDIAN static inline VOID WriteBackToDescriptor( @@ -3291,7 +3285,6 @@ static inline VOID RTMPWIEndianChange( Call this function when read or update descriptor ======================================================================== */ -#ifdef RT2860 static inline VOID RTMPDescriptorEndianChange( IN PUCHAR pData, IN ULONG DescriptorType) @@ -3301,7 +3294,6 @@ static inline VOID RTMPDescriptorEndianChange( *((UINT32 *)(pData +12)) = SWAP32(*((UINT32 *)(pData + 12))); // Byte 12~15 *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData + 4))); // Byte 4~7, this must be swapped last } -#endif // RT2860 // /* ======================================================================== @@ -3550,6 +3542,9 @@ NDIS_STATUS NICInitializeAsic( IN PRTMP_ADAPTER pAd, IN BOOLEAN bHardReset); +VOID NICRestoreBBPValue( + IN PRTMP_ADAPTER pAd); + VOID NICIssueReset( IN PRTMP_ADAPTER pAd); @@ -4208,7 +4203,7 @@ VOID AsicForceSleep( VOID AsicForceWakeup( IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx); + IN UCHAR Level); #endif // CONFIG_STA_SUPPORT // VOID AsicSetBssid( @@ -4304,11 +4299,9 @@ BOOLEAN AsicSendCommandToMcu( IN UCHAR Arg0, IN UCHAR Arg1); -#ifdef RT2860 BOOLEAN AsicCheckCommanOk( IN PRTMP_ADAPTER pAd, IN UCHAR Command); -#endif // RT2860 // VOID MacAddrRandomBssid( IN PRTMP_ADAPTER pAd, @@ -6978,7 +6971,6 @@ void kill_thread_task(PRTMP_ADAPTER pAd); void tbtt_tasklet(unsigned long data); -#ifdef RT2860 // // Function Prototype in cmm_data_2860.c // @@ -7069,7 +7061,7 @@ BOOLEAN RT28xxPciAsicRadioOn( VOID RT28xxPciStaAsicForceWakeup( IN PRTMP_ADAPTER pAd, - IN BOOLEAN bFromTx); + IN UCHAR Level); VOID RT28xxPciStaAsicSleepThenAutoWakeup( IN PRTMP_ADAPTER pAd, @@ -7093,7 +7085,6 @@ VOID RT28xxPciMlmeRadioOn( VOID RT28xxPciMlmeRadioOFF( IN PRTMP_ADAPTER pAd); -#endif // RT2860 // VOID AsicTurnOffRFClk( IN PRTMP_ADAPTER pAd, @@ -7132,6 +7123,18 @@ PCHAR RTMPGetRalinkEncryModeStr( #ifdef CONFIG_STA_SUPPORT VOID AsicStaBbpTuning( IN PRTMP_ADAPTER pAd); + +VOID AsicResetFromDMABusy( + IN PRTMP_ADAPTER pAd); + +VOID AsicResetBBP( + IN PRTMP_ADAPTER pAd); + +VOID AsicResetMAC( + IN PRTMP_ADAPTER pAd); + +VOID AsicResetPBF( + IN PRTMP_ADAPTER pAd); #endif // CONFIG_STA_SUPPORT // void RTMP_IndicateMediaState( diff --git a/drivers/staging/rt2860/rtmp_def.h b/drivers/staging/rt2860/rtmp_def.h index be982147883f..25a53d83a0d7 100644 --- a/drivers/staging/rt2860/rtmp_def.h +++ b/drivers/staging/rt2860/rtmp_def.h @@ -111,7 +111,6 @@ // Entry number for each DMA descriptor ring // -#ifdef RT2860 #define TX_RING_SIZE 64 //64 #define MGMT_RING_SIZE 128 #define RX_RING_SIZE 128 //64 @@ -119,7 +118,6 @@ #define MAX_DMA_DONE_PROCESS TX_RING_SIZE #define MAX_TX_DONE_PROCESS TX_RING_SIZE //8 #define LOCAL_TXBUF_SIZE 2 -#endif // RT2860 // #ifdef MULTIPLE_CARD_SUPPORT @@ -212,6 +210,19 @@ #define fOP_STATUS_WAKEUP_NOW 0x00008000 #define fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE 0x00020000 +// +// RTMP_ADAPTER PSFlags : related to advanced power save. +// +// Indicate whether driver can go to sleep mode from now. This flag is useful AFTER link up +#define fRTMP_PS_CAN_GO_SLEEP 0x00000001 +// Indicate whether driver has issue a LinkControl command to PCIe L1 +#define fRTMP_PS_SET_PCI_CLK_OFF_COMMAND 0x00000002 +// Indicate driver should disable kick off hardware to send packets from now. +#define fRTMP_PS_DISABLE_TX 0x00000004 +// Indicate driver should IMMEDIATELY fo to sleep after receiving AP's beacon in which doesn't indicate unicate nor multicast packets for me +//. This flag is used ONLY in RTMPHandleRxDoneInterrupt routine. +#define fRTMP_PS_GO_TO_SLEEP_NOW 0x00000008 + #ifdef DOT11N_DRAFT3 #define fOP_STATUS_SCAN_2040 0x00040000 #endif // DOT11N_DRAFT3 // @@ -1514,12 +1525,14 @@ #define MCAST_HTMIX 3 #endif // MCAST_RATE_SPECIFIC // -// For AsicRadioOff/AsicRadioOn function -#define DOT11POWERSAVE 0 -#define GUIRADIO_OFF 1 -#define RTMP_HALT 2 -#define GUI_IDLE_POWER_SAVE 3 -// -- +// For AsicRadioOff/AsicRadioOn/AsicForceWakeup function +// This is to indicate from where to call this function. +#define DOT11POWERSAVE 0 // TO do .11 power save sleep +#define GUIRADIO_OFF 1 // To perform Radio OFf command from GUI +#define RTMP_HALT 2 // Called from Halt handler. +#define GUI_IDLE_POWER_SAVE 3 // Call to sleep before link up with AP +#define FROM_TX 4 // Force wake up from Tx packet. + // definition for WpaSupport flag diff --git a/drivers/staging/rt2860/sta/assoc.c b/drivers/staging/rt2860/sta/assoc.c index 42db753eed70..34f1c1490f44 100644 --- a/drivers/staging/rt2860/sta/assoc.c +++ b/drivers/staging/rt2860/sta/assoc.c @@ -473,12 +473,7 @@ VOID MlmeAssocReqAction( RSNIe = IE_WPA2; } -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -#ifdef SIOCSIWGENIE - if (pAd->StaCfg.WpaSupplicantUP != 1) -#endif // SIOCSIWGENIE // -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // - RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); // Check for WPA PMK cache list if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) @@ -504,17 +499,6 @@ VOID MlmeAssocReqAction( } } -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -#ifdef SIOCSIWGENIE - if (pAd->StaCfg.WpaSupplicantUP == 1) - { - MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, - pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, - END_OF_ARGS); - } - else -#endif -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // { MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1, &RSNIe, @@ -525,11 +509,6 @@ VOID MlmeAssocReqAction( FrameLen += tmp; -#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT -#ifdef SIOCSIWGENIE - if (pAd->StaCfg.WpaSupplicantUP != 1) -#endif -#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // { // Append Variable IE NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1); diff --git a/drivers/staging/rt2860/sta/connect.c b/drivers/staging/rt2860/sta/connect.c index 36f28f8b4aa4..d8bcc76688a6 100644 --- a/drivers/staging/rt2860/sta/connect.c +++ b/drivers/staging/rt2860/sta/connect.c @@ -337,6 +337,10 @@ VOID CntlOidSsidProc( MLME_DISASSOC_REQ_STRUCT DisassocReq; ULONG Now; + // BBP and RF are not accessible in PS mode, we has to wake them up first + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, RTMP_HALT); + // Step 1. record the desired user settings to MlmeAux NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength); @@ -1240,6 +1244,13 @@ VOID LinkUp( UCHAR Value = 0, idx; MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; + if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) + { + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT); + RTMPusecDelay(6000); + pAd->bPCIclkOff = FALSE; + } + pEntry = &pAd->MacTab.Content[BSSID_WCID]; // @@ -1264,7 +1275,6 @@ VOID LinkUp( //rt2860b. Don't know why need this SwitchBetweenWepAndCkip(pAd); -#ifdef RT2860 // Before power save before link up function, We will force use 1R. // So after link up, check Rx antenna # again. RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); @@ -1282,7 +1292,6 @@ VOID LinkUp( } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); pAd->StaCfg.BBPR3 = Value; -#endif // RT2860 // if (BssType == BSS_ADHOC) { @@ -1330,9 +1339,7 @@ VOID LinkUp( RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); Value &= (~0x20); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); -#ifdef RT2860 pAd->StaCfg.BBPR3 = Value; -#endif // RT2860 // RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); Data &= 0xfffffffe; @@ -1367,9 +1374,7 @@ VOID LinkUp( RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); Value |= (0x20); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); -#ifdef RT2860 pAd->StaCfg.BBPR3 = Value; -#endif // RT2860 // if (pAd->MACVersion == 0x28600100) { @@ -1400,9 +1405,7 @@ VOID LinkUp( RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); Value &= (~0x20); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); -#ifdef RT2860 pAd->StaCfg.BBPR3 = Value; -#endif // RT2860 // if (pAd->MACVersion == 0x28600100) { @@ -1598,6 +1601,8 @@ VOID LinkUp( IV = 0; IV |= (pAd->StaCfg.DefaultKeyId << 30); AsicUpdateWCIDIVEIV(pAd, BSSID_WCID, IV, 0); + + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); } // NOTE: // the decision of using "short slot time" or not may change dynamically due to @@ -1919,6 +1924,7 @@ VOID LinkUp( } RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 @@ -1961,6 +1967,7 @@ VOID LinkDown( IN BOOLEAN IsReqFromAP) { UCHAR i, ByteValue = 0; + BOOLEAN Cancelled; // Do nothing if monitor mode is on if (MONITOR_ON(pAd)) @@ -1972,6 +1979,12 @@ VOID LinkDown( return; #endif // RALINK_ATE // + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); + RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); + + // Not allow go to sleep within linkdown function. + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); + if (pAd->CommonCfg.bWirelessEvent) { RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); @@ -1980,7 +1993,6 @@ VOID LinkDown( DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN !!!\n")); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); -#ifdef RT2860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { BOOLEAN Cancelled; @@ -1988,17 +2000,15 @@ VOID LinkDown( RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled); } - if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) || + RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)) { - AUTO_WAKEUP_STRUC AutoWakeupCfg; - AsicForceWakeup(pAd, TRUE); - AutoWakeupCfg.word = 0; - RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + AsicForceWakeup(pAd, RTMP_HALT); OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); } pAd->bPCIclkOff = FALSE; -#endif // RT2860 // if (ADHOC_ON(pAd)) // Adhoc mode link down { DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 1!!!\n")); @@ -2266,6 +2276,9 @@ VOID LinkDown( RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff); RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + // Allow go to sleep after linkdown steps. + RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); + #ifdef WPA_SUPPLICANT_SUPPORT #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT if (pAd->StaCfg.WpaSupplicantUP) { @@ -2510,7 +2523,6 @@ VOID AuthParmFill( ========================================================================== */ -#ifdef RT2860 VOID ComposePsPoll( IN PRTMP_ADAPTER pAd) { @@ -2534,7 +2546,6 @@ VOID ComposeNullFrame( COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress); COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid); } -#endif // RT2860 // diff --git a/drivers/staging/rt2860/sta/dls.c b/drivers/staging/rt2860/sta/dls.c index 78fb28976fd7..873cf7f1de93 100644 --- a/drivers/staging/rt2860/sta/dls.c +++ b/drivers/staging/rt2860/sta/dls.c @@ -1419,7 +1419,6 @@ BOOLEAN RTMPRcvFrameDLSCheck( //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); // Add Pair-wise key to Asic -#ifdef RT2860 AsicAddPairwiseKeyEntry(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, @@ -1431,7 +1430,6 @@ BOOLEAN RTMPRcvFrameDLSCheck( PairwiseKey.CipherAlg, pEntry); -#endif // RT2860 // NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n")); @@ -1477,7 +1475,6 @@ BOOLEAN RTMPRcvFrameDLSCheck( //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); // Add Pair-wise key to Asic -#ifdef RT2860 AsicAddPairwiseKeyEntry(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, @@ -1488,7 +1485,6 @@ BOOLEAN RTMPRcvFrameDLSCheck( 0, PairwiseKey.CipherAlg, pEntry); -#endif // RT2860 // NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n")); diff --git a/drivers/staging/rt2860/sta/rtmp_data.c b/drivers/staging/rt2860/sta/rtmp_data.c index 36aff247cd95..c5e76a2da56d 100644 --- a/drivers/staging/rt2860/sta/rtmp_data.c +++ b/drivers/staging/rt2860/sta/rtmp_data.c @@ -75,7 +75,6 @@ VOID STARxEAPOLFrameIndicate( if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0) { -#ifdef RT2860 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; // Set key material and cipherAlg to Asic @@ -89,7 +88,6 @@ VOID STARxEAPOLFrameIndicate( pAd->IndicateMediaState = NdisMediaStateConnected; pAd->ExtraInfo = GENERAL_LINK_UP; -#endif // RT2860 // // For Preventing ShardKey Table is cleared by remove key procedure. pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg; pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen; @@ -693,14 +691,12 @@ BOOLEAN STARxDoneInterruptHandle( break; } -#ifdef RT2860 if (RxProcessed++ > MAX_RX_PROCESS_CNT) { // need to reschedule rx handle bReschedule = TRUE; break; } -#endif // RT2860 // RxProcessed ++; // test @@ -811,6 +807,13 @@ BOOLEAN STARxDoneInterruptHandle( } } + // fRTMP_PS_GO_TO_SLEEP_NOW is set if receiving beacon. + if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW) && (INFRA_ON(pAd))) + { + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); + AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp); + bReschedule = FALSE; + } return bReschedule; } @@ -828,7 +831,7 @@ BOOLEAN STARxDoneInterruptHandle( VOID RTMPHandleTwakeupInterrupt( IN PRTMP_ADAPTER pAd) { - AsicForceWakeup(pAd, FALSE); + AsicForceWakeup(pAd, DOT11POWERSAVE); } /* @@ -1220,7 +1223,6 @@ NDIS_STATUS STASendPacket( ======================================================================== */ -#ifdef RT2860 NDIS_STATUS RTMPFreeTXDRequest( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx, @@ -1264,7 +1266,6 @@ NDIS_STATUS RTMPFreeTXDRequest( return (Status); } -#endif // RT2860 // @@ -1889,7 +1890,8 @@ VOID STA_AMPDU_Frame_Tx( // // Kick out Tx // - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); pAd->RalinkCounters.KickTxCount++; pAd->RalinkCounters.OneSecTxDoneCount++; @@ -2019,7 +2021,8 @@ VOID STA_AMSDU_Frame_Tx( // // Kick out Tx // - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); } #endif // DOT11_N_SUPPORT // @@ -2139,7 +2142,8 @@ VOID STA_Legacy_Frame_Tx( // // Kick out Tx // - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); } @@ -2249,7 +2253,8 @@ VOID STA_ARalink_Frame_Tx( // // Kick out Tx // - HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX)) + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); } @@ -2526,7 +2531,7 @@ NDIS_STATUS STAHardTransmit( if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n")); - AsicForceWakeup(pAd, TRUE); + AsicForceWakeup(pAd, FROM_TX); } // It should not change PSM bit, when APSD turn on. diff --git a/drivers/staging/rt2860/sta/sync.c b/drivers/staging/rt2860/sta/sync.c index d196f85395ce..148037a79d51 100644 --- a/drivers/staging/rt2860/sta/sync.c +++ b/drivers/staging/rt2860/sta/sync.c @@ -228,7 +228,6 @@ VOID MlmeScanReqAction( // Increase the scan retry counters. pAd->StaCfg.ScanCnt++; -#ifdef RT2860 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && (IDLE_ON(pAd)) && (pAd->StaCfg.bRadio == TRUE) && @@ -236,7 +235,6 @@ VOID MlmeScanReqAction( { RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); } -#endif // RT2860 // // first check the parameter sanity if (MlmeScanReqSanity(pAd, @@ -349,7 +347,6 @@ VOID MlmeJoinReqAction( DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); -#ifdef RT2860 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) && (IDLE_ON(pAd)) && (pAd->StaCfg.bRadio == TRUE) && @@ -357,7 +354,6 @@ VOID MlmeJoinReqAction( { RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE); } -#endif // RT2860 // // reset all the timers RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); @@ -1532,13 +1528,10 @@ VOID PeerBeacon( // 5. otherwise, put PHY back to sleep to save battery. if (MessageToMe) { -#ifdef RT2860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); - // Turn clk to 80Mhz. } -#endif // RT2860 // if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO) { @@ -1549,12 +1542,10 @@ VOID PeerBeacon( } else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM)) { -#ifdef RT2860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); } -#endif // RT2860 // } else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) || (pAd->TxSwQueue[QID_AC_BE].Number != 0) || @@ -1568,12 +1559,10 @@ VOID PeerBeacon( { // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme // can we cheat here (i.e. just check MGMT & AC_BE) for better performance? -#ifdef RT2860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) { RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); } -#endif // RT2860 // } else { @@ -1588,7 +1577,10 @@ VOID PeerBeacon( if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { - AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + // Set a flag to go to sleep . Then after parse this RxDoneInterrupt, will go to sleep mode. + RTMP_SET_PSFLAG(pAd, fRTMP_PS_GO_TO_SLEEP_NOW); + pAd->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp; + //AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); } } } diff --git a/drivers/staging/rt2860/sta/wpa.c b/drivers/staging/rt2860/sta/wpa.c index 774c6567ae53..2609d845fd5c 100644 --- a/drivers/staging/rt2860/sta/wpa.c +++ b/drivers/staging/rt2860/sta/wpa.c @@ -1384,6 +1384,10 @@ VOID WpaGroupMsg1Action( pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; + else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64; + else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128; //hex_dump("Group Key :", pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, LEN_TKIP_EK); } @@ -1760,7 +1764,7 @@ BOOLEAN ParseKeyData( // Get GTK length - refer to IEEE 802.11i-2004 p.82 GTKLEN = pKDE->Len -6; - if (GTKLEN < LEN_AES_KEY) + if (GTKLEN < MIN_LEN_OF_GTK) { DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); return FALSE; @@ -1786,6 +1790,10 @@ BOOLEAN ParseKeyData( pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; + else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64; + else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128; return TRUE; diff --git a/drivers/staging/rt2860/sta_ioctl.c b/drivers/staging/rt2860/sta_ioctl.c index 3ea2b2c4ab0e..c5452f152a21 100644 --- a/drivers/staging/rt2860/sta_ioctl.c +++ b/drivers/staging/rt2860/sta_ioctl.c @@ -49,15 +49,9 @@ extern ULONG RTDebugLevel; #define GROUP_KEY_NO 4 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) #define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_A, _B, _C, _D, _E) #define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_A, _B, _C, _D, _E) #define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_A, _B, _C, _D, _E, _F) -#else -#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_B, _C, _D, _E) -#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_B, _C, _D, _E) -#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_B, _C, _D, _E, _F) -#endif extern UCHAR CipherWpa2Template[]; extern UCHAR CipherWpaPskTkip[]; @@ -358,6 +352,20 @@ VOID RTMPAddKey( DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n")); + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); + if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) + { + if (pAd->StaCfg.bRadio == FALSE) + { + RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); + return; + } + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPAAddKeyProc1==>\n")); + RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT); + RTMPusecDelay(6000); + pAd->bPCIclkOff = FALSE; + } + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) { if (pKey->KeyIndex & 0x80000000) @@ -551,6 +559,8 @@ VOID RTMPAddKey( } } end: + RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP); + DBGPRINT(RT_DEBUG_INFO, ("<------ RTMPAddKey\n")); return; } @@ -573,9 +583,7 @@ rt_ioctl_giwname(struct net_device *dev, { // PRTMP_ADAPTER pAdapter = dev->ml_priv; -#ifdef RT2860 strncpy(name, "RT2860 Wireless", IFNAMSIZ); -#endif // RT2860 // return 0; } @@ -670,11 +678,9 @@ int rt_ioctl_siwmode(struct net_device *dev, case IW_MODE_INFRA: Set_NetworkType_Proc(pAdapter, "Infra"); break; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) case IW_MODE_MONITOR: Set_NetworkType_Proc(pAdapter, "Monitor"); break; -#endif default: DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", *mode)); return -EINVAL; @@ -715,12 +721,10 @@ int rt_ioctl_giwmode(struct net_device *dev, *mode = IW_MODE_ADHOC; else if (INFRA_ON(pAdapter)) *mode = IW_MODE_INFRA; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) else if (MONITOR_ON(pAdapter)) { *mode = IW_MODE_MONITOR; } -#endif else *mode = IW_MODE_AUTO; @@ -1038,6 +1042,15 @@ int rt_ioctl_siwscan(struct net_device *dev, return -EINVAL; } + if ((pAdapter->OpMode == OPMODE_STA) && (IDLE_ON(pAdapter)) + && (pAdapter->StaCfg.bRadio == TRUE) + && (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_IDLE_RADIO_OFF))) + { + RT28xxPciAsicRadioOn(pAdapter, GUI_IDLE_POWER_SAVE); + } + // Check if still radio off. + else if (pAdapter->bPCIclkOff == TRUE) + return 0; #ifdef WPA_SUPPLICANT_SUPPORT if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) @@ -1756,7 +1769,7 @@ int rt_ioctl_siwencode(struct net_device *dev, } else /* Don't complain if only change the mode */ - if(!erq->flags & IW_ENCODE_MODE) { + if (!(erq->flags & IW_ENCODE_MODE)) { return -EINVAL; } } @@ -2161,12 +2174,6 @@ rt_private_show(struct net_device *dev, struct iw_request_info *info, wrq->length = strlen(extra) + 1; // 1: size of '\0' break; case RAIO_ON: - if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) - { - sprintf(extra, "Scanning\n"); - wrq->length = strlen(extra) + 1; // 1: size of '\0' - break; - } pAd->StaCfg.bSwRadio = TRUE; //if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) { @@ -2450,6 +2457,20 @@ void fnSetCipherKey( IN BOOLEAN bGTK, IN struct iw_encode_ext *ext) { + RTMP_CLEAR_PSFLAG(pAdapter, fRTMP_PS_CAN_GO_SLEEP); + if (RTMP_TEST_PSFLAG(pAdapter, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND)) + { + if (pAdapter->StaCfg.bRadio == FALSE) + { + RTMP_SET_PSFLAG(pAdapter, fRTMP_PS_CAN_GO_SLEEP); + return; + } + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPAAddKeyProc1==>\n")); + RTMPPCIeLinkCtrlValueRestore(pAdapter, RESTORE_HALT); + RTMPusecDelay(6000); + pAdapter->bPCIclkOff = FALSE; + } + NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); pAdapter->SharedKey[BSS0][keyIdx].KeyLen = LEN_TKIP_EK; NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, LEN_TKIP_EK); @@ -2480,6 +2501,8 @@ void fnSetCipherKey( keyIdx, pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, &pAdapter->MacTab.Content[BSSID_WCID]); + + RTMP_SET_PSFLAG(pAdapter, fRTMP_PS_CAN_GO_SLEEP); } int rt_ioctl_siwencodeext(struct net_device *dev, @@ -2544,6 +2567,21 @@ int rt_ioctl_siwencodeext(struct net_device *dev, NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, ext->key_len); + + if (pAdapter->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled || + pAdapter->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled) + { + // Set Group key material to Asic + AsicAddSharedKeyEntry(pAdapter, BSS0, keyIdx, pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, pAdapter->SharedKey[BSS0][keyIdx].Key, NULL, NULL); + + // Update WCID attribute table and IVEIV table for this group key table + RTMPAddWcidAttributeEntry(pAdapter, BSS0, keyIdx, pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, NULL); + + STA_PORT_SECURED(pAdapter); + + // Indicate Connected for GUI + pAdapter->IndicateMediaState = NdisMediaStateConnected; + } break; case IW_ENCODE_ALG_TKIP: DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", __func__, keyIdx, ext->key_len)); @@ -4259,7 +4297,23 @@ INT RTMPSetInformation( } #ifdef WPA_SUPPLICANT_SUPPORT - if (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) + if ((pAdapter->StaCfg.WpaSupplicantUP != 0) && + (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) + { + Key = pWepKey->KeyMaterial; + + // Set Group key material to Asic + AsicAddSharedKeyEntry(pAdapter, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL); + + // Update WCID attribute table and IVEIV table for this group key table + RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, NULL); + + STA_PORT_SECURED(pAdapter); + + // Indicate Connected for GUI + pAdapter->IndicateMediaState = NdisMediaStateConnected; + } + else if (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) #endif // WPA_SUPPLICANT_SUPPORT { Key = pAdapter->SharedKey[BSS0][KeyIdx].Key; @@ -5265,7 +5319,6 @@ INT RTMPQueryInformation( case RT_OID_802_11_PRODUCTID: DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n")); -#ifdef RT2860 { USHORT device_id; @@ -5275,7 +5328,6 @@ INT RTMPQueryInformation( DBGPRINT(RT_DEBUG_TRACE, (" pci_dev = NULL\n")); sprintf(tmp, "%04x %04x\n", NIC_PCI_VENDOR_ID, device_id); } -#endif // RT2860 // wrq->u.data.length = strlen(tmp); Status = copy_to_user(wrq->u.data.pointer, tmp, wrq->u.data.length); break; diff --git a/drivers/staging/rt2860/wpa.h b/drivers/staging/rt2860/wpa.h index 88c7c8bf3fcd..0134ae6097cf 100644 --- a/drivers/staging/rt2860/wpa.h +++ b/drivers/staging/rt2860/wpa.h @@ -90,6 +90,7 @@ #define TKIP_AP_RXMICK_OFFSET (TKIP_AP_TXMICK_OFFSET+LEN_TKIP_TXMICK) #define TKIP_GTK_LENGTH ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK)) #define LEN_PTK ((LEN_EAP_KEY)+(LEN_TKIP_KEY)) +#define MIN_LEN_OF_GTK 5 // RSN IE Length definition #define MAX_LEN_OF_RSNIE 90 diff --git a/drivers/staging/rt2870/2870_main_dev.c b/drivers/staging/rt2870/2870_main_dev.c index 04c764d95d77..9d59e3167fe4 100644 --- a/drivers/staging/rt2870/2870_main_dev.c +++ b/drivers/staging/rt2870/2870_main_dev.c @@ -265,7 +265,7 @@ INT MlmeThread( */ DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__)); - pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE; + pObj->MLMEThr_task = NULL; complete_and_exit (&pAd->mlmeComplete, 0); return 0; @@ -373,7 +373,7 @@ INT RTUSBCmdThread( */ DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n")); - pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE; + pObj->RTUSBCmdThr_task = NULL; complete_and_exit (&pAd->CmdQComplete, 0); return 0; @@ -467,7 +467,7 @@ INT TimerQThread( */ DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__)); - pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE; + pObj->TimerQThr_task = NULL; complete_and_exit(&pAd->TimerQComplete, 0); return 0; @@ -944,69 +944,46 @@ VOID RT28xxThreadTerminate( RTUSBCancelPendingIRPs(pAd); // Terminate Threads - CHECK_PID_LEGALITY(pObj->TimerQThr_pid) + BUG_ON(pObj->TimerQThr_task == NULL); + CHECK_PID_LEGALITY(task_pid(pObj->TimerQThr_task)) { POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; - printk("Terminate the TimerQThr_pid=%d!\n", GET_PID_NUMBER(pObj->TimerQThr_pid)); + printk(KERN_DEBUG "Terminate the TimerQThr pid=%d!\n", + pid_nr(task_pid(pObj->TimerQThr_task))); mb(); pAd->TimerFunc_kill = 1; mb(); - ret = KILL_THREAD_PID(pObj->TimerQThr_pid, SIGTERM, 1); - if (ret) - { - printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n", - pAd->net_dev->name, GET_PID_NUMBER(pObj->TimerQThr_pid), ret); - } - else - { - wait_for_completion(&pAd->TimerQComplete); - pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE; - } + kthread_stop(pObj->TimerQThr_task); + pObj->TimerQThr_task = NULL; } - CHECK_PID_LEGALITY(pObj->MLMEThr_pid) + BUG_ON(pObj->MLMEThr_task == NULL); + CHECK_PID_LEGALITY(task_pid(pObj->MLMEThr_task)) { - printk("Terminate the MLMEThr_pid=%d!\n", GET_PID_NUMBER(pObj->MLMEThr_pid)); + printk(KERN_DEBUG "Terminate the MLMEThr pid=%d!\n", + pid_nr(task_pid(pObj->MLMEThr_task))); mb(); pAd->mlme_kill = 1; //RT28XX_MLME_HANDLER(pAd); mb(); - ret = KILL_THREAD_PID(pObj->MLMEThr_pid, SIGTERM, 1); - if (ret) - { - printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n", - pAd->net_dev->name, GET_PID_NUMBER(pObj->MLMEThr_pid), ret); - } - else - { - //wait_for_completion (&pAd->notify); - wait_for_completion (&pAd->mlmeComplete); - pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE; - } + kthread_stop(pObj->MLMEThr_task); + pObj->MLMEThr_task = NULL; } - CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid) + BUG_ON(pObj->RTUSBCmdThr_task == NULL); + CHECK_PID_LEGALITY(task_pid(pObj->RTUSBCmdThr_task)) { - printk("Terminate the RTUSBCmdThr_pid=%d!\n", GET_PID_NUMBER(pObj->RTUSBCmdThr_pid)); + printk(KERN_DEBUG "Terminate the RTUSBCmdThr pid=%d!\n", + pid_nr(task_pid(pObj->RTUSBCmdThr_task))); mb(); NdisAcquireSpinLock(&pAd->CmdQLock); pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED; NdisReleaseSpinLock(&pAd->CmdQLock); mb(); //RTUSBCMDUp(pAd); - ret = KILL_THREAD_PID(pObj->RTUSBCmdThr_pid, SIGTERM, 1); - if (ret) - { - printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n", - pAd->net_dev->name, GET_PID_NUMBER(pObj->RTUSBCmdThr_pid), ret); - } - else - { - //wait_for_completion (&pAd->notify); - wait_for_completion (&pAd->CmdQComplete); - pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE; - } + kthread_stop(pObj->RTUSBCmdThr_task); + pObj->RTUSBCmdThr_task = NULL; } @@ -1067,7 +1044,7 @@ BOOLEAN RT28XXChipsetCheck( if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor && dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct) { - printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n", + printk(KERN_DEBUG "rt2870: idVendor = 0x%x, idProduct = 0x%x\n", dev_p->descriptor.idVendor, dev_p->descriptor.idProduct); break; } diff --git a/drivers/staging/rt2870/TODO b/drivers/staging/rt2870/TODO index eae1ac47d3f9..2df1bfed9a58 100644 --- a/drivers/staging/rt2870/TODO +++ b/drivers/staging/rt2870/TODO @@ -1,7 +1,14 @@ +I'm hesitant to add a TODO file here, as the wireless developers would +really have people help them out on the "clean" rt2870 driver that can +be found at the http://rt2x00.serialmonkey.com/ site. + +But, if you wish to clean up this driver instead, here's a short list of +things that need to be done to get it into a more mergable shape: + TODO: - checkpatch.pl clean - sparse clean - - port to in-kernel 80211 stack + - port to in-kernel 80211 stack and common rt2x00 infrastructure - remove reading from /etc/ config files - review by the wireless developer community diff --git a/drivers/staging/rt2870/common/2870_rtmp_init.c b/drivers/staging/rt2870/common/2870_rtmp_init.c index 9f5143b3922e..cb16d2fcf60a 100644 --- a/drivers/staging/rt2870/common/2870_rtmp_init.c +++ b/drivers/staging/rt2870/common/2870_rtmp_init.c @@ -727,8 +727,8 @@ NDIS_STATUS AdapterBlockAllocateMemory( usb_dev = pObj->pUsb_Dev; - pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE; - pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE; + pObj->MLMEThr_task = NULL; + pObj->RTUSBCmdThr_task = NULL; *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); @@ -765,7 +765,7 @@ NDIS_STATUS CreateThreads( { PRTMP_ADAPTER pAd = net_dev->ml_priv; POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; - pid_t pid_number = -1; + struct task_struct *tsk; //init_MUTEX(&(pAd->usbdev_semaphore)); @@ -779,36 +779,39 @@ NDIS_STATUS CreateThreads( init_completion (&pAd->TimerQComplete); // Creat MLME Thread - pObj->MLMEThr_pid= THREAD_PID_INIT_VALUE; - pid_number = kernel_thread(MlmeThread, pAd, CLONE_VM); - if (pid_number < 0) - { + pObj->MLMEThr_task = NULL; + tsk = kthread_run(MlmeThread, pAd, pAd->net_dev->name); + + if (IS_ERR(tsk)) { printk (KERN_WARNING "%s: unable to start Mlme thread\n",pAd->net_dev->name); return NDIS_STATUS_FAILURE; } - pObj->MLMEThr_pid = GET_PID(pid_number); + + pObj->MLMEThr_task = tsk; // Wait for the thread to start wait_for_completion(&(pAd->mlmeComplete)); // Creat Command Thread - pObj->RTUSBCmdThr_pid= THREAD_PID_INIT_VALUE; - pid_number = kernel_thread(RTUSBCmdThread, pAd, CLONE_VM); - if (pid_number < 0) + pObj->RTUSBCmdThr_task = NULL; + tsk = kthread_run(RTUSBCmdThread, pAd, pAd->net_dev->name); + + if (IS_ERR(tsk) < 0) { printk (KERN_WARNING "%s: unable to start RTUSBCmd thread\n",pAd->net_dev->name); return NDIS_STATUS_FAILURE; } - pObj->RTUSBCmdThr_pid = GET_PID(pid_number); + + pObj->RTUSBCmdThr_task = tsk; wait_for_completion(&(pAd->CmdQComplete)); - pObj->TimerQThr_pid= THREAD_PID_INIT_VALUE; - pid_number = kernel_thread(TimerQThread, pAd, CLONE_VM); - if (pid_number < 0) + pObj->TimerQThr_task = NULL; + tsk = kthread_run(TimerQThread, pAd, pAd->net_dev->name); + if (IS_ERR(tsk) < 0) { printk (KERN_WARNING "%s: unable to start TimerQThread\n",pAd->net_dev->name); return NDIS_STATUS_FAILURE; } - pObj->TimerQThr_pid = GET_PID(pid_number); + pObj->TimerQThr_task = tsk; // Wait for the thread to start wait_for_completion(&(pAd->TimerQComplete)); diff --git a/drivers/staging/rt2870/common/cmm_data.c b/drivers/staging/rt2870/common/cmm_data.c index fd809abf6df0..f8e0ebd7bca9 100644 --- a/drivers/staging/rt2870/common/cmm_data.c +++ b/drivers/staging/rt2870/common/cmm_data.c @@ -709,9 +709,6 @@ BOOLEAN RTMP_FillTxBlkInfo( } return TRUE; - -FillTxBlkErr: - return FALSE; } diff --git a/drivers/staging/rt2870/common/rtmp_init.c b/drivers/staging/rt2870/common/rtmp_init.c index 870a00da3dac..099b6a806f86 100644 --- a/drivers/staging/rt2870/common/rtmp_init.c +++ b/drivers/staging/rt2870/common/rtmp_init.c @@ -3655,7 +3655,7 @@ VOID UserCfgInit( #ifdef RALINK_28xx_QA //pAd->ate.Repeat = 0; pAd->ate.TxStatus = 0; - pAd->ate.AtePid = THREAD_PID_INIT_VALUE; + pAd->ate.AtePid = NULL; #endif // RALINK_28xx_QA // #endif // RALINK_ATE // diff --git a/drivers/staging/rt2870/common/rtusb_io.c b/drivers/staging/rt2870/common/rtusb_io.c index 6db443e9268c..afde136a9a0c 100644 --- a/drivers/staging/rt2870/common/rtusb_io.c +++ b/drivers/staging/rt2870/common/rtusb_io.c @@ -958,7 +958,8 @@ NDIS_STATUS RTUSBEnqueueCmdFromNdis( POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; - CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid) + BUG_ON(pObj->RTUSBCmdThr_task == NULL); + CHECK_PID_LEGALITY(task_pid(pObj->RTUSBCmdThr_task)) return (NDIS_STATUS_RESOURCES); status = RTMPAllocateMemory((PVOID *)&cmdqelmt, sizeof(CmdQElmt)); diff --git a/drivers/staging/rt2870/common/spectrum.c b/drivers/staging/rt2870/common/spectrum.c index 43782ce9288f..74380958eb70 100644 --- a/drivers/staging/rt2870/common/spectrum.c +++ b/drivers/staging/rt2870/common/spectrum.c @@ -1595,7 +1595,7 @@ static VOID PeerMeasureReportAction( if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL) { - DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __func__, sizeof(MEASURE_RPI_REPORT))); + DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%zu).\n", __func__, sizeof(MEASURE_RPI_REPORT))); return; } diff --git a/drivers/staging/rt2870/rt2870.h b/drivers/staging/rt2870/rt2870.h index 30af4b57c3d8..5dd15aac9ce7 100644 --- a/drivers/staging/rt2870/rt2870.h +++ b/drivers/staging/rt2870/rt2870.h @@ -86,6 +86,7 @@ #define RT2870_USB_DEVICES \ { \ {USB_DEVICE(0x148F,0x2770)}, /* Ralink */ \ + {USB_DEVICE(0x1737,0x0071)}, /* Linksys WUSB600N */ \ {USB_DEVICE(0x148F,0x2870)}, /* Ralink */ \ {USB_DEVICE(0x148F,0x3070)}, /* Ralink */ \ {USB_DEVICE(0x0B05,0x1731)}, /* Asus */ \ @@ -576,14 +577,16 @@ VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs); #define RTUSBMlmeUp(pAd) \ { \ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; \ - CHECK_PID_LEGALITY(pObj->MLMEThr_pid) \ + BUG_ON(pObj->MLMEThr_task == NULL); \ + CHECK_PID_LEGALITY(task_pid(pObj->MLMEThr_task)) \ up(&(pAd->mlme_semaphore)); \ } #define RTUSBCMDUp(pAd) \ { \ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; \ - CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid) \ + BUG_ON(pObj->RTUSBCmdThr_task == NULL); \ + CHECK_PID_LEGALITY(task_pid(pObj->RTUSBCmdThr_task)) \ up(&(pAd->RTUSBCmd_semaphore)); \ } diff --git a/drivers/staging/rt2870/rt_linux.c b/drivers/staging/rt2870/rt_linux.c index 992e3d16f9b4..e38552c5ccb1 100644 --- a/drivers/staging/rt2870/rt_linux.c +++ b/drivers/staging/rt2870/rt_linux.c @@ -895,7 +895,7 @@ void send_monitor_packets( if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE) { - DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); + DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%zu)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); goto err_free_sk_buff; } diff --git a/drivers/staging/rt2870/rt_linux.h b/drivers/staging/rt2870/rt_linux.h index 859f9cef0a19..5a6ee6ad0e52 100644 --- a/drivers/staging/rt2870/rt_linux.h +++ b/drivers/staging/rt2870/rt_linux.h @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,6 @@ #include -#include #include // load firmware @@ -166,14 +166,12 @@ typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) typedef struct pid * THREAD_PID; -#define THREAD_PID_INIT_VALUE NULL #define GET_PID(_v) find_get_pid(_v) #define GET_PID_NUMBER(_v) pid_nr(_v) #define CHECK_PID_LEGALITY(_pid) if (pid_nr(_pid) >= 0) #define KILL_THREAD_PID(_A, _B, _C) kill_pid(_A, _B, _C) #else typedef pid_t THREAD_PID; -#define THREAD_PID_INIT_VALUE -1 #define GET_PID(_v) _v #define GET_PID_NUMBER(_v) _v #define CHECK_PID_LEGALITY(_pid) if (_pid >= 0) @@ -189,11 +187,11 @@ struct os_lock { struct os_cookie { #ifdef RT2870 - struct usb_device *pUsb_Dev; + struct usb_device *pUsb_Dev; - THREAD_PID MLMEThr_pid; - THREAD_PID RTUSBCmdThr_pid; - THREAD_PID TimerQThr_pid; + struct task_struct *MLMEThr_task; + struct task_struct *RTUSBCmdThr_task; + struct task_struct *TimerQThr_task; #endif // RT2870 // struct tasklet_struct rx_done_task; diff --git a/drivers/staging/rt2870/sta_ioctl.c b/drivers/staging/rt2870/sta_ioctl.c index 91f0fab11313..4b432ce4442e 100644 --- a/drivers/staging/rt2870/sta_ioctl.c +++ b/drivers/staging/rt2870/sta_ioctl.c @@ -1776,7 +1776,7 @@ int rt_ioctl_siwencode(struct net_device *dev, } else /* Don't complain if only change the mode */ - if(!erq->flags & IW_ENCODE_MODE) { + if (!(erq->flags & IW_ENCODE_MODE)) { return -EINVAL; } } diff --git a/drivers/staging/rt3070/2870_main_dev.c b/drivers/staging/rt3070/2870_main_dev.c new file mode 100644 index 000000000000..401ddb012131 --- /dev/null +++ b/drivers/staging/rt3070/2870_main_dev.c @@ -0,0 +1,1627 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtmp_main.c + + Abstract: + main initialization routines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Jan Lee 01-10-2005 modified + Sample Jun/01/07 Merge RT2870 and RT2860 drivers. +*/ + +#include "rt_config.h" + + +// Following information will be show when you run 'modinfo' +// *** If you have a solution for the bug in current version of driver, please mail to me. +// Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. *** +MODULE_AUTHOR("Paul Lin "); +MODULE_DESCRIPTION("RT2870 Wireless Lan Linux Driver"); +#ifdef CONFIG_STA_SUPPORT +MODULE_LICENSE("GPL"); +#ifdef MODULE_VERSION +MODULE_VERSION(STA_DRIVER_VERSION); +#endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef MULTIPLE_CARD_SUPPORT +// record whether the card in the card list is used in the card file +extern UINT8 MC_CardUsed[]; +#endif // MULTIPLE_CARD_SUPPORT // + +/* Kernel thread and vars, which handles packets that are completed. Only + * packets that have a "complete" function are sent here. This way, the + * completion is run out of kernel context, and doesn't block the rest of + * the stack. */ +//static int mlme_kill = 0; // Mlme kernel thread +//static int RTUSBCmd_kill = 0; // Command kernel thread +//static int TimerFunc_kill = 0; // TimerQ kernel thread + +//static wait_queue_head_t timerWaitQ; +//static wait_queue_t waitQ; + +extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p, + IN UINT argc, OUT PRTMP_ADAPTER *ppAd); + + +/* module table */ +struct usb_device_id rtusb_usb_id[] = RT2870_USB_DEVICES; +INT const rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id); +MODULE_DEVICE_TABLE(usb, rtusb_usb_id); + +#ifndef PF_NOFREEZE +#define PF_NOFREEZE 0 +#endif + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + +/**************************************************************************/ +/**************************************************************************/ +//tested for kernel 2.4 series +/**************************************************************************/ +/**************************************************************************/ +static void *rtusb_probe(struct usb_device *dev, UINT interface, + const struct usb_device_id *id_table); +static void rtusb_disconnect(struct usb_device *dev, void *ptr); + +struct usb_driver rtusb_driver = { + name:"rt2870", + probe:rtusb_probe, + disconnect:rtusb_disconnect, + id_table:rtusb_usb_id, + }; + +#else + +#ifdef CONFIG_PM +static int rt2870_suspend(struct usb_interface *intf, pm_message_t state); +static int rt2870_resume(struct usb_interface *intf); +#endif // CONFIG_PM // + +/**************************************************************************/ +/**************************************************************************/ +//tested for kernel 2.6series +/**************************************************************************/ +/**************************************************************************/ +static int rtusb_probe (struct usb_interface *intf, + const struct usb_device_id *id); +static void rtusb_disconnect(struct usb_interface *intf); + +struct usb_driver rtusb_driver = { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) + .owner = THIS_MODULE, +#endif + .name="rt2870", + .probe=rtusb_probe, + .disconnect=rtusb_disconnect, + .id_table=rtusb_usb_id, + +#ifdef CONFIG_PM + suspend: rt2870_suspend, + resume: rt2870_resume, +#endif + }; + +#ifdef CONFIG_PM + +VOID RT2860RejectPendingPackets( + IN PRTMP_ADAPTER pAd) +{ + // clear PS packets + // clear TxSw packets +} + +static int rt2870_suspend( + struct usb_interface *intf, + pm_message_t state) +{ + struct net_device *net_dev; + PRTMP_ADAPTER pAd = usb_get_intfdata(intf); + + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n")); + net_dev = pAd->net_dev; + netif_device_detach(net_dev); + + pAd->PM_FlgSuspend = 1; + if (netif_running(net_dev)) { + RTUSBCancelPendingBulkInIRP(pAd); + RTUSBCancelPendingBulkOutIRP(pAd); + } + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n")); + return 0; +} + +static int rt2870_resume( + struct usb_interface *intf) +{ + struct net_device *net_dev; + PRTMP_ADAPTER pAd = usb_get_intfdata(intf); + + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n")); + + pAd->PM_FlgSuspend = 0; + net_dev = pAd->net_dev; + netif_device_attach(net_dev); + netif_start_queue(net_dev); + netif_carrier_on(net_dev); + netif_wake_queue(net_dev); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n")); + return 0; +} +#endif // CONFIG_PM // +#endif // LINUX_VERSION_CODE // + + +// Init driver module +INT __init rtusb_init(void) +{ + printk("rtusb init --->\n"); + return usb_register(&rtusb_driver); +} + +// Deinit driver module +VOID __exit rtusb_exit(void) +{ + usb_deregister(&rtusb_driver); + printk("<--- rtusb exit\n"); +} + +module_init(rtusb_init); +module_exit(rtusb_exit); + + + + +/*--------------------------------------------------------------------- */ +/* function declarations */ +/*--------------------------------------------------------------------- */ + +/* +======================================================================== +Routine Description: + MLME kernel thread. + +Arguments: + *Context the pAd, driver control block pointer + +Return Value: + 0 close the thread + +Note: +======================================================================== +*/ +INT MlmeThread( + IN void *Context) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context; + POS_COOKIE pObj; + int status; + + pObj = (POS_COOKIE)pAd->OS_Cookie; + + rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete)); + + while (pAd->mlme_kill == 0) + { + /* lock the device pointers */ + //down(&(pAd->mlme_semaphore)); + status = down_interruptible(&(pAd->mlme_semaphore)); + + /* lock the device pointers , need to check if required*/ + //down(&(pAd->usbdev_semaphore)); + + if (!pAd->PM_FlgSuspend) + MlmeHandler(pAd); + + /* unlock the device pointers */ + //up(&(pAd->usbdev_semaphore)); + if (status != 0) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + } + + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ + DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); + + pObj->MLMEThr_pid = NULL; + + complete_and_exit (&pAd->mlmeComplete, 0); + return 0; + +} + + +/* +======================================================================== +Routine Description: + USB command kernel thread. + +Arguments: + *Context the pAd, driver control block pointer + +Return Value: + 0 close the thread + +Note: +======================================================================== +*/ +INT RTUSBCmdThread( + IN void * Context) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context; + POS_COOKIE pObj; + int status; + + pObj = (POS_COOKIE)pAd->OS_Cookie; + + rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete)); + + NdisAcquireSpinLock(&pAd->CmdQLock); + pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING; + NdisReleaseSpinLock(&pAd->CmdQLock); + + while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING) + { + /* lock the device pointers */ + //down(&(pAd->RTUSBCmd_semaphore)); + status = down_interruptible(&(pAd->RTUSBCmd_semaphore)); + + if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED) + break; + + if (status != 0) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + /* lock the device pointers , need to check if required*/ + //down(&(pAd->usbdev_semaphore)); + + if (!pAd->PM_FlgSuspend) + CMDHandler(pAd); + + /* unlock the device pointers */ + //up(&(pAd->usbdev_semaphore)); + } + + if (!pAd->PM_FlgSuspend) + { // Clear the CmdQElements. + CmdQElmt *pCmdQElmt = NULL; + + NdisAcquireSpinLock(&pAd->CmdQLock); + pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED; + while(pAd->CmdQ.size) + { + RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt); + if (pCmdQElmt) + { + if (pCmdQElmt->CmdFromNdis == TRUE) + { + if (pCmdQElmt->buffer != NULL) + NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0); + + NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0); + } + else + { + if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0)) + NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0); + { + NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0); + } + } + } + } + + NdisReleaseSpinLock(&pAd->CmdQLock); + } + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ + DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n")); + + pObj->RTUSBCmdThr_pid = NULL; + + complete_and_exit (&pAd->CmdQComplete, 0); + return 0; + +} + + +static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd) +{ + int status; + RALINK_TIMER_STRUCT *pTimer; + RT2870_TIMER_ENTRY *pEntry; + unsigned long irqFlag; + + while(!pAd->TimerFunc_kill) + { +// printk("waiting for event!\n"); + pTimer = NULL; + + status = down_interruptible(&(pAd->RTUSBTimer_semaphore)); + + if (pAd->TimerQ.status == RT2870_THREAD_STOPED) + break; + + // event happened. + while(pAd->TimerQ.pQHead) + { + RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag); + pEntry = pAd->TimerQ.pQHead; + if (pEntry) + { + pTimer = pEntry->pRaTimer; + + // update pQHead + pAd->TimerQ.pQHead = pEntry->pNext; + if (pEntry == pAd->TimerQ.pQTail) + pAd->TimerQ.pQTail = NULL; + + // return this queue entry to timerQFreeList. + pEntry->pNext = pAd->TimerQ.pQPollFreeList; + pAd->TimerQ.pQPollFreeList = pEntry; + } + RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag); + + if (pTimer) + { + if (pTimer->handle != NULL) + if (!pAd->PM_FlgSuspend) + pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer); + if ((pTimer->Repeat) && (pTimer->State == FALSE)) + RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); + } + } + + if (status != 0) + { + pAd->TimerQ.status = RT2870_THREAD_STOPED; + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + } +} + + +INT TimerQThread( + IN OUT PVOID Context) +{ + PRTMP_ADAPTER pAd; + POS_COOKIE pObj; + + pAd = (PRTMP_ADAPTER)Context; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete)); + + RT2870_TimerQ_Handle(pAd); + + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ + DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); + + pObj->TimerQThr_pid = NULL; + + complete_and_exit(&pAd->TimerQComplete, 0); + return 0; + +} + + +RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer) +{ + RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail; + unsigned long irqFlags; + + + RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags); + if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT) + { + if(pAd->TimerQ.pQPollFreeList) + { + pQNode = pAd->TimerQ.pQPollFreeList; + pAd->TimerQ.pQPollFreeList = pQNode->pNext; + + pQNode->pRaTimer = pTimer; + pQNode->pNext = NULL; + + pQTail = pAd->TimerQ.pQTail; + if (pAd->TimerQ.pQTail != NULL) + pQTail->pNext = pQNode; + pAd->TimerQ.pQTail = pQNode; + if (pAd->TimerQ.pQHead == NULL) + pAd->TimerQ.pQHead = pQNode; + } + RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); + + if (pQNode) + up(&pAd->RTUSBTimer_semaphore); + //wake_up(&timerWaitQ); + } + else + { + RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); + } + return pQNode; +} + + +BOOLEAN RT2870_TimerQ_Remove( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer) +{ + RT2870_TIMER_ENTRY *pNode, *pPrev = NULL; + unsigned long irqFlags; + + RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags); + if (pAd->TimerQ.status >= RT2870_THREAD_INITED) + { + pNode = pAd->TimerQ.pQHead; + while (pNode) + { + if (pNode->pRaTimer == pTimer) + break; + pPrev = pNode; + pNode = pNode->pNext; + } + + // Now move it to freeList queue. + if (pNode) + { + if (pNode == pAd->TimerQ.pQHead) + pAd->TimerQ.pQHead = pNode->pNext; + if (pNode == pAd->TimerQ.pQTail) + pAd->TimerQ.pQTail = pPrev; + if (pPrev != NULL) + pPrev->pNext = pNode->pNext; + + // return this queue entry to timerQFreeList. + pNode->pNext = pAd->TimerQ.pQPollFreeList; + pAd->TimerQ.pQPollFreeList = pNode; + } + } + RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); + + return TRUE; +} + + +void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd) +{ + RT2870_TIMER_ENTRY *pTimerQ; + unsigned long irqFlags; + + RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags); + while (pAd->TimerQ.pQHead) + { + pTimerQ = pAd->TimerQ.pQHead; + pAd->TimerQ.pQHead = pTimerQ->pNext; + // remove the timeQ + } + pAd->TimerQ.pQPollFreeList = NULL; + os_free_mem(pAd, pAd->TimerQ.pTimerQPoll); + pAd->TimerQ.pQTail = NULL; + pAd->TimerQ.pQHead = NULL; + pAd->TimerQ.status = RT2870_THREAD_STOPED; + RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); + +} + + +void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd) +{ + int i; + RT2870_TIMER_ENTRY *pQNode, *pEntry; + unsigned long irqFlags; + + NdisAllocateSpinLock(&pAd->TimerQLock); + + RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags); + NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ)); + //InterlockedExchange(&pAd->TimerQ.count, 0); + + /* Initialise the wait q head */ + //init_waitqueue_head(&timerWaitQ); + + os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX); + if (pAd->TimerQ.pTimerQPoll) + { + pEntry = NULL; + pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll; + for (i = 0 ;i pNext = pEntry; + pEntry = pQNode; + pQNode++; + } + pAd->TimerQ.pQPollFreeList = pEntry; + pAd->TimerQ.pQHead = NULL; + pAd->TimerQ.pQTail = NULL; + pAd->TimerQ.status = RT2870_THREAD_INITED; + } + RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags); +} + + +VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd) +{ + PHT_TX_CONTEXT pHTTXContext; + int idx; + ULONG irqFlags; + PURB pUrb; + BOOLEAN needDumpSeq = FALSE; + UINT32 MACValue; + + + idx = 0; + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); + if ((MACValue & 0xff) !=0 ) + { + DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue)); + RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012); + while((MACValue &0xff) != 0 && (idx++ < 10)) + { + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); + NdisMSleep(1); + } + RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006); + } + +//PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + idx = 0; + if ((MACValue & 0xff00) !=0 ) + { + DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue)); + RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a); + while((MACValue &0xff00) != 0 && (idx++ < 10)) + { + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); + NdisMSleep(1); + } + RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006); + } + } +#endif // CONFIG_STA_SUPPORT // + + if (pAd->watchDogRxOverFlowCnt >= 2) + { + DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n")); + if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_BULKIN_RESET | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n")); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0); + needDumpSeq = TRUE; + } + pAd->watchDogRxOverFlowCnt = 0; + } + + + for (idx = 0; idx < NUM_OF_TX_RING; idx++) + { + pUrb = NULL; + + RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags); + if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt) + { + pAd->watchDogTxPendingCnt[idx]++; + + if ((pAd->watchDogTxPendingCnt[idx] > 2) && + (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET))) + ) + { + // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it! + pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]); + if (pHTTXContext->IRPPending) + { // Check TxContext. + pUrb = pHTTXContext->pUrb; + } + else if (idx == MGMTPIPEIDX) + { + PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext; + + //Check MgmtContext. + pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa); + pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext); + pNULLContext = (PTX_CONTEXT)(&pAd->NullContext); + + if (pMLMEContext->IRPPending) + { + ASSERT(pMLMEContext->IRPPending); + pUrb = pMLMEContext->pUrb; + } + else if (pNULLContext->IRPPending) + { + ASSERT(pNULLContext->IRPPending); + pUrb = pNULLContext->pUrb; + } + else if (pPsPollContext->IRPPending) + { + ASSERT(pPsPollContext->IRPPending); + pUrb = pPsPollContext->pUrb; + } + } + + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags); + + DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx)); + if (pUrb) + { + DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n")); + // unlink it now + RTUSB_UNLINK_URB(pUrb); + // Sleep 200 microseconds to give cancellation time to work + RTMPusecDelay(200); + needDumpSeq = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n")); + } + } + else + { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags); + } + } + else + { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags); + } + } + +#ifdef DOT11_N_SUPPORT + // For Sigma debug, dump the ba_reordering sequence. + if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0)) + { + USHORT Idx; + PBA_REC_ENTRY pBAEntry = NULL; + UCHAR count = 0; + struct reordering_mpdu *mpdu_blk; + + Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0]; + + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL)) + { + DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n")); + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + mpdu_blk = pBAEntry->list.next; + while (mpdu_blk) + { + DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU)); + mpdu_blk = mpdu_blk->next; + count++; + } + + DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq)); + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + } + } +#endif // DOT11_N_SUPPORT // +} + +/* +======================================================================== +Routine Description: + Release allocated resources. + +Arguments: + *dev Point to the PCI or USB device + pAd driver control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd) +{ + struct net_device *net_dev = NULL; + + + DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n", + dev->bus->bus_name, dev->devpath)); + if (!pAd) + { +#ifdef MULTIPLE_CARD_SUPPORT + if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD)) + MC_CardUsed[pAd->MC_RowID] = 0; // not clear MAC address +#endif // MULTIPLE_CARD_SUPPORT // + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */ + while(MOD_IN_USE > 0) + { + MOD_DEC_USE_COUNT; + } +#else + usb_put_dev(dev); +#endif // LINUX_VERSION_CODE // + + printk("rtusb_disconnect: pAd == NULL!\n"); + return; + } + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + + + + // for debug, wait to show some messages to /proc system + udelay(1); + + + + + net_dev = pAd->net_dev; + if (pAd->net_dev != NULL) + { + printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name); + unregister_netdev (pAd->net_dev); + } + udelay(1); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */ +#else + flush_scheduled_work(); +#endif // LINUX_VERSION_CODE // + udelay(1); + + // free net_device memory +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */ + kfree(net_dev); +#else + free_netdev(net_dev); +#endif // LINUX_VERSION_CODE // + + // free adapter memory + RTMPFreeAdapter(pAd); + + // release a use of the usb device structure +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */ + while(MOD_IN_USE > 0) + { + MOD_DEC_USE_COUNT; + } +#else + usb_put_dev(dev); +#endif // LINUX_VERSION_CODE // + udelay(1); + + DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n")); +} + + +/* +======================================================================== +Routine Description: + Probe RT28XX chipset. + +Arguments: + *dev Point to the PCI or USB device + interface + *id_table Point to the PCI or USB device ID + +Return Value: + None + +Note: +======================================================================== +*/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */ +static void *rtusb_probe(struct usb_device *dev, UINT interface, + const struct usb_device_id *id) +{ + PRTMP_ADAPTER pAd; + rt28xx_probe((void *)dev, (void *)id, interface, &pAd); + return (void *)pAd; +} + +//Disconnect function is called within exit routine +static void rtusb_disconnect(struct usb_device *dev, void *ptr) +{ + _rtusb_disconnect(dev, ((PRTMP_ADAPTER)ptr)); +} + +#else /* kernel 2.6 series */ +static int rtusb_probe (struct usb_interface *intf, + const struct usb_device_id *id) +{ + PRTMP_ADAPTER pAd; + return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd); +} + + +static void rtusb_disconnect(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + PRTMP_ADAPTER pAd; + + + pAd = usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); + + _rtusb_disconnect(dev, pAd); +} +#endif // LINUX_VERSION_CODE // + + +/* +======================================================================== +Routine Description: + Close kernel threads. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID RT28xxThreadTerminate( + IN RTMP_ADAPTER *pAd) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + INT ret; + + + // Sleep 50 milliseconds so pending io might finish normally + RTMPusecDelay(50000); + + // We want to wait until all pending receives and sends to the + // device object. We cancel any + // irps. Wait until sends and receives have stopped. + RTUSBCancelPendingIRPs(pAd); + + // Terminate Threads + if (pObj->MLMEThr_pid) + { + printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj->MLMEThr_pid)); + mb(); + pAd->mlme_kill = 1; + //RT28XX_MLME_HANDLER(pAd); + mb(); + ret = kill_pid(pObj->MLMEThr_pid, SIGTERM, 1); + if (ret) + { + printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n", + pAd->net_dev->name, pid_nr(pObj->MLMEThr_pid), ret); + } + else + { + //wait_for_completion (&pAd->notify); + wait_for_completion (&pAd->mlmeComplete); + pObj->MLMEThr_pid = NULL; + } + } + + if (pObj->RTUSBCmdThr_pid >= 0) + { + printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj->RTUSBCmdThr_pid)); + mb(); + NdisAcquireSpinLock(&pAd->CmdQLock); + pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED; + NdisReleaseSpinLock(&pAd->CmdQLock); + mb(); + //RTUSBCMDUp(pAd); + ret = kill_pid(pObj->RTUSBCmdThr_pid, SIGTERM, 1); + if (ret) + { + printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n", + pAd->net_dev->name, pid_nr(pObj->RTUSBCmdThr_pid), ret); + } + else + { + //wait_for_completion (&pAd->notify); + wait_for_completion (&pAd->CmdQComplete); + pObj->RTUSBCmdThr_pid = NULL; + } + } + if (pObj->TimerQThr_pid >= 0) + { + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + + printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj->TimerQThr_pid)); + mb(); + pAd->TimerFunc_kill = 1; + mb(); + ret = kill_pid(pObj->TimerQThr_pid, SIGTERM, 1); + if (ret) + { + printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n", + pAd->net_dev->name, pid_nr(pObj->TimerQThr_pid), ret); + } + else + { + printk("wait_for_completion TimerQThr\n"); + wait_for_completion(&pAd->TimerQComplete); + pObj->TimerQThr_pid = NULL; + } + } + // Kill tasklets + pAd->mlme_kill = 0; + pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN; + pAd->TimerFunc_kill = 0; +} + + +void kill_thread_task(IN PRTMP_ADAPTER pAd) +{ + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + tasklet_kill(&pObj->rx_done_task); + tasklet_kill(&pObj->mgmt_dma_done_task); + tasklet_kill(&pObj->ac0_dma_done_task); + tasklet_kill(&pObj->ac1_dma_done_task); + tasklet_kill(&pObj->ac2_dma_done_task); + tasklet_kill(&pObj->ac3_dma_done_task); + tasklet_kill(&pObj->hcca_dma_done_task); + tasklet_kill(&pObj->tbtt_task); + +} + + +/* +======================================================================== +Routine Description: + Check the chipset vendor/product ID. + +Arguments: + _dev_p Point to the PCI or USB device + +Return Value: + TRUE Check ok + FALSE Check fail + +Note: +======================================================================== +*/ +BOOLEAN RT28XXChipsetCheck( + IN void *_dev_p) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */ + struct usb_device *dev_p = (struct usb_device *)_dev_p; +#else + struct usb_interface *intf = (struct usb_interface *)_dev_p; + struct usb_device *dev_p = interface_to_usbdev(intf); +#endif // LINUX_VERSION_CODE // + UINT32 i; + + + for(i=0; idescriptor.idVendor == rtusb_usb_id[i].idVendor && + dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct) + { + printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n", + dev_p->descriptor.idVendor, dev_p->descriptor.idProduct); + break; + } + } + + if (i == rtusb_usb_id_len) + { + printk("rt2870: Error! Device Descriptor not matching!\n"); + return FALSE; + } + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Init net device structure. + +Arguments: + _dev_p Point to the PCI or USB device + *net_dev Point to the net device + *pAd the raxx interface data pointer + +Return Value: + TRUE Init ok + FALSE Init fail + +Note: +======================================================================== +*/ +BOOLEAN RT28XXNetDevInit( + IN void *_dev_p, + IN struct net_device *net_dev, + IN RTMP_ADAPTER *pAd) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */ + struct usb_device *dev_p = (struct usb_device *)_dev_p; +#else + struct usb_interface *intf = (struct usb_interface *)_dev_p; + struct usb_device *dev_p = interface_to_usbdev(intf); +#endif // LINUX_VERSION_CODE // + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */ + pAd->config = dev_p->config; +#else + pAd->config = &dev_p->config->desc; +#endif // LINUX_VERSION_CODE // + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Init net device structure. + +Arguments: + _dev_p Point to the PCI or USB device + *pAd the raxx interface data pointer + +Return Value: + TRUE Config ok + FALSE Config fail + +Note: +======================================================================== +*/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +BOOLEAN RT28XXProbePostConfig( + IN void *_dev_p, + IN RTMP_ADAPTER *pAd, + IN INT32 interface) +{ + struct usb_device *dev_p = (struct usb_device *)_dev_p; + struct usb_interface *intf; + struct usb_interface_descriptor *iface_desc; + struct usb_endpoint_descriptor *endpoint; + ULONG BulkOutIdx; + UINT32 i; + + + /* get the active interface descriptor */ + intf = &dev_p->actconfig->interface[interface]; + iface_desc = &intf->altsetting[0]; + + /* get # of enpoints */ + pAd->NumberOfPipes = iface_desc->bNumEndpoints; + DBGPRINT(RT_DEBUG_TRACE, ("NumEndpoints=%d\n", iface_desc->bNumEndpoints)); + + /* Configure Pipes */ + endpoint = &iface_desc->endpoint[0]; + BulkOutIdx = 0; + + for(i=0; iNumberOfPipes; i++) + { + if ((endpoint[i].bmAttributes == USB_ENDPOINT_XFER_BULK) && + ((endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)) + { + pAd->BulkInEpAddr = endpoint[i].bEndpointAddress; + pAd->BulkInMaxPacketSize = endpoint[i].wMaxPacketSize; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize)); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("EP address = 0x%2x \n", endpoint[i].bEndpointAddress)); + } + else if ((endpoint[i].bmAttributes == USB_ENDPOINT_XFER_BULK) && + ((endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)) + { + // There are 6 bulk out EP. EP6 highest priority. + // EP1-4 is EDCA. EP5 is HCCA. + pAd->BulkOutEpAddr[BulkOutIdx++] = endpoint[i].bEndpointAddress; + pAd->BulkOutMaxPacketSize = endpoint[i].wMaxPacketSize; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize)); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("EP address = 0x%2x \n", endpoint[i].bEndpointAddress)); + } + } + + if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0])) + { + printk("Could not find both bulk-in and bulk-out endpoints\n"); + return FALSE; + } + + return TRUE; +} + +#else +BOOLEAN RT28XXProbePostConfig( + IN void *_dev_p, + IN RTMP_ADAPTER *pAd, + IN INT32 interface) +{ + struct usb_interface *intf = (struct usb_interface *)_dev_p; + struct usb_host_interface *iface_desc; + ULONG BulkOutIdx; + UINT32 i; + + + /* get the active interface descriptor */ + iface_desc = intf->cur_altsetting; + + /* get # of enpoints */ + pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints; + DBGPRINT(RT_DEBUG_TRACE, + ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints)); + + /* Configure Pipes */ + BulkOutIdx = 0; + + for(i=0; iNumberOfPipes; i++) + { + if ((iface_desc->endpoint[i].desc.bmAttributes == + USB_ENDPOINT_XFER_BULK) && + ((iface_desc->endpoint[i].desc.bEndpointAddress & + USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)) + { + pAd->BulkInEpAddr = iface_desc->endpoint[i].desc.bEndpointAddress; + pAd->BulkInMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize)); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("EP address = 0x%2x\n", iface_desc->endpoint[i].desc.bEndpointAddress)); + } + else if ((iface_desc->endpoint[i].desc.bmAttributes == + USB_ENDPOINT_XFER_BULK) && + ((iface_desc->endpoint[i].desc.bEndpointAddress & + USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)) + { + // there are 6 bulk out EP. EP6 highest priority. + // EP1-4 is EDCA. EP5 is HCCA. + pAd->BulkOutEpAddr[BulkOutIdx++] = iface_desc->endpoint[i].desc.bEndpointAddress; + pAd->BulkOutMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize; + + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize)); + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("EP address = 0x%2x \n", iface_desc->endpoint[i].desc.bEndpointAddress)); + } + } + + if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0])) + { + printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __FUNCTION__); + return FALSE; + } + + return TRUE; +} +#endif // LINUX_VERSION_CODE // + + +/* +======================================================================== +Routine Description: + Disable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28XXDMADisable( + IN RTMP_ADAPTER *pAd) +{ + // no use +} + + + +/* +======================================================================== +Routine Description: + Enable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28XXDMAEnable( + IN RTMP_ADAPTER *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + USB_DMA_CFG_STRUC UsbCfg; + int i = 0; + + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); + RTMPusecDelay(1000); + i++; + }while ( i <200); + + + RTMPusecDelay(50); + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnableTxDMA = 1; + DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + UsbCfg.word = 0; + UsbCfg.field.phyclear = 0; + /* usb version is 1.1,do not use bulk in aggregation */ + if (pAd->BulkInMaxPacketSize == 512) + UsbCfg.field.RxBulkAggEn = 1; + /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */ + UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3; + UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */ + UsbCfg.field.RxBulkEn = 1; + UsbCfg.field.TxBulkEn = 1; + + RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word); + +} + +/* +======================================================================== +Routine Description: + Write Beacon buffer to Asic. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28xx_UpdateBeaconToAsic( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN ULONG FrameLen, + IN ULONG UpdatePos) +{ + PUCHAR pBeaconFrame = NULL; + UCHAR *ptr; + UINT i, padding; + BEACON_SYNC_STRUCT *pBeaconSync = pAd->CommonCfg.pBeaconSync; + UINT32 longValue; +// USHORT shortValue; + BOOLEAN bBcnReq = FALSE; + UCHAR bcn_idx = 0; + + + if (pBeaconFrame == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n")); + return; + } + + if (pBeaconSync == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n")); + return; + } + + //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) || + // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) + // ) + if (bBcnReq == FALSE) + { + /* when the ra interface is down, do not send its beacon frame */ + /* clear all zero */ + for(i=0; iBeaconOffset[bcn_idx] + i, 0x00); + } + pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); + NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE); + } + else + { + ptr = (PUCHAR)&pAd->BeaconTxWI; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(ptr, TYPE_TXWI); +#endif + if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE) + { // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames. + pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); + NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE); + } + + if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx)) + { + for (i=0; iBeaconOffset[bcn_idx] + i, longValue); + ptr += 4; + } + } + + ptr = pBeaconSync->BeaconBuf[bcn_idx]; + padding = (FrameLen & 0x01); + NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding); + FrameLen += padding; + for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2) + { + if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE) + { + NdisMoveMemory(ptr, pBeaconFrame, 2); + //shortValue = *ptr + (*(ptr+1)<<8); + //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue); + RTUSBMultiWrite(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, ptr, 2); + } + ptr +=2; + pBeaconFrame += 2; + } + + pBeaconSync->BeaconBitMap |= (1 << bcn_idx); + + // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame. + } + +} + + +VOID RT2870_BssBeaconStop( + IN RTMP_ADAPTER *pAd) +{ + BEACON_SYNC_STRUCT *pBeaconSync; + int i, offset; + BOOLEAN Cancelled = TRUE; + + pBeaconSync = pAd->CommonCfg.pBeaconSync; + if (pBeaconSync && pBeaconSync->EnableBeacon) + { + INT NumOfBcn; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + NumOfBcn = MAX_MESH_NUM; + } +#endif // CONFIG_STA_SUPPORT // + + RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); + + for(i=0; iBeaconBuf[i], HW_BEACON_OFFSET); + NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); + + for (offset=0; offsetBeaconOffset[i] + offset, 0x00); + + pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; + pBeaconSync->TimIELocationInBeacon[i] = 0; + } + pBeaconSync->BeaconBitMap = 0; + pBeaconSync->DtimBitOn = 0; + } +} + + +VOID RT2870_BssBeaconStart( + IN RTMP_ADAPTER *pAd) +{ + int apidx; + BEACON_SYNC_STRUCT *pBeaconSync; +// LARGE_INTEGER tsfTime, deltaTime; + + pBeaconSync = pAd->CommonCfg.pBeaconSync; + if (pBeaconSync && pBeaconSync->EnableBeacon) + { + INT NumOfBcn; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + NumOfBcn = MAX_MESH_NUM; + } +#endif // CONFIG_STA_SUPPORT // + + for(apidx=0; apidxBeaconBuf[apidx], HW_BEACON_OFFSET); + pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon; + pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon; + NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWI_SIZE); + } + pBeaconSync->BeaconBitMap = 0; + pBeaconSync->DtimBitOn = 0; + pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE; + + pAd->CommonCfg.BeaconAdjust = 0; + pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10); + pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1; + printk("RT2870_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain); + RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, pAd->CommonCfg.BeaconPeriod); + + } +} + + +VOID RT2870_BssBeaconInit( + IN RTMP_ADAPTER *pAd) +{ + BEACON_SYNC_STRUCT *pBeaconSync; + int i; + + NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(BEACON_SYNC_STRUCT), MEM_ALLOC_FLAG); + if (pAd->CommonCfg.pBeaconSync) + { + pBeaconSync = pAd->CommonCfg.pBeaconSync; + NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT)); + for(i=0; i < HW_BEACON_MAX_COUNT; i++) + { + NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET); + pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; + pBeaconSync->TimIELocationInBeacon[i] = 0; + NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); + } + pBeaconSync->BeaconBitMap = 0; + + //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE); + pBeaconSync->EnableBeacon = TRUE; + } +} + + +VOID RT2870_BssBeaconExit( + IN RTMP_ADAPTER *pAd) +{ + BEACON_SYNC_STRUCT *pBeaconSync; + BOOLEAN Cancelled = TRUE; + int i; + + if (pAd->CommonCfg.pBeaconSync) + { + pBeaconSync = pAd->CommonCfg.pBeaconSync; + pBeaconSync->EnableBeacon = FALSE; + RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); + pBeaconSync->BeaconBitMap = 0; + + for(i=0; iBeaconBuf[i], HW_BEACON_OFFSET); + pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; + pBeaconSync->TimIELocationInBeacon[i] = 0; + NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); + } + + NdisFreeMemory(pAd->CommonCfg.pBeaconSync, HW_BEACON_OFFSET * HW_BEACON_MAX_COUNT, 0); + pAd->CommonCfg.pBeaconSync = NULL; + } +} + +VOID BeaconUpdateExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + LARGE_INTEGER tsfTime_a;//, tsfTime_b, deltaTime_exp, deltaTime_ab; + UINT32 delta, remain, remain_low, remain_high; +// BOOLEAN positive; + + ReSyncBeaconTime(pAd); + + + + RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart); + RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart); + + + //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp); + remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart; + remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10); + remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10); + delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain; + + pAd->CommonCfg.BeaconUpdateTimer.TimerValue = (delta >> 10) + 10; + +} + diff --git a/drivers/staging/rt3070/Kconfig b/drivers/staging/rt3070/Kconfig new file mode 100644 index 000000000000..b37fb5d13a4f --- /dev/null +++ b/drivers/staging/rt3070/Kconfig @@ -0,0 +1,6 @@ +config RT3070 + tristate "Ralink 3070 wireless support" + depends on USB && X86 && WLAN_80211 + ---help--- + This is an experimental driver for the Ralink 3070 wireless chip. + diff --git a/drivers/staging/rt3070/Makefile b/drivers/staging/rt3070/Makefile new file mode 100644 index 000000000000..55980c929254 --- /dev/null +++ b/drivers/staging/rt3070/Makefile @@ -0,0 +1,47 @@ +obj-$(CONFIG_RT3070) += rt3070sta.o + +# TODO: all of these should be removed +EXTRA_CFLAGS += -DLINUX -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT +EXTRA_CFLAGS += -DRT2870 -DRT30xx -DRT3070 +EXTRA_CFLAGS += -DCONFIG_STA_SUPPORT +EXTRA_CFLAGS += -DDBG +EXTRA_CFLAGS += -DDOT11_N_SUPPORT +EXTRA_CFLAGS += -DWPA_SUPPLICANT_SUPPORT +EXTRA_CFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT + +rt3070sta-objs := \ + common/md5.o \ + common/mlme.o \ + common/rtmp_wep.o \ + common/action.o \ + common/cmm_data.o \ + common/rtmp_init.o \ + common/rtmp_tkip.o \ + common/cmm_sync.o \ + common/eeprom.o \ + common/cmm_sanity.o \ + common/cmm_info.o \ + common/cmm_wpa.o \ + common/dfs.o \ + common/spectrum.o \ + sta/assoc.o \ + sta/aironet.o \ + sta/auth.o \ + sta/auth_rsp.o \ + sta/sync.o \ + sta/sanity.o \ + sta/rtmp_data.o \ + sta/connect.o \ + sta/wpa.o \ + rt_linux.o \ + rt_profile.o \ + rt_main_dev.o \ + sta_ioctl.o \ + common/ba_action.o \ + 2870_main_dev.o \ + common/2870_rtmp_init.o \ + common/rtusb_io.o \ + common/rtusb_bulk.o \ + common/rtusb_data.o \ + common/cmm_data_2870.o + diff --git a/drivers/staging/rt3070/action.h b/drivers/staging/rt3070/action.h new file mode 100644 index 000000000000..ce3877dce81b --- /dev/null +++ b/drivers/staging/rt3070/action.h @@ -0,0 +1,68 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + aironet.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 04-06-15 Initial +*/ + +#ifndef __ACTION_H__ +#define __ACTION_H__ + +typedef struct PACKED __HT_INFO_OCTET +{ +#ifdef RT_BIG_ENDIAN + UCHAR Reserved:5; + UCHAR STA_Channel_Width:1; + UCHAR Forty_MHz_Intolerant:1; + UCHAR Request:1; +#else + UCHAR Request:1; + UCHAR Forty_MHz_Intolerant:1; + UCHAR STA_Channel_Width:1; + UCHAR Reserved:5; +#endif +} HT_INFORMATION_OCTET; + + +typedef struct PACKED __FRAME_HT_INFO +{ + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + HT_INFORMATION_OCTET HT_Info; +} FRAME_HT_INFO, *PFRAME_HT_INFO; + +#endif /* __ACTION_H__ */ + + diff --git a/drivers/staging/rt3070/aironet.h b/drivers/staging/rt3070/aironet.h new file mode 100644 index 000000000000..1e07b19b8cdc --- /dev/null +++ b/drivers/staging/rt3070/aironet.h @@ -0,0 +1,210 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + aironet.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 04-06-15 Initial +*/ + +#ifndef __AIRONET_H__ +#define __AIRONET_H__ + +// Measurement Type definition +#define MSRN_TYPE_UNUSED 0 +#define MSRN_TYPE_CHANNEL_LOAD_REQ 1 +#define MSRN_TYPE_NOISE_HIST_REQ 2 +#define MSRN_TYPE_BEACON_REQ 3 +#define MSRN_TYPE_FRAME_REQ 4 + +// Scan Mode in Beacon Request +#define MSRN_SCAN_MODE_PASSIVE 0 +#define MSRN_SCAN_MODE_ACTIVE 1 +#define MSRN_SCAN_MODE_BEACON_TABLE 2 + +// PHY type definition for Aironet beacon report, CCX 2 table 36-9 +#define PHY_FH 1 +#define PHY_DSS 2 +#define PHY_UNUSED 3 +#define PHY_OFDM 4 +#define PHY_HR_DSS 5 +#define PHY_ERP 6 + +// RPI table in dBm +#define RPI_0 0 // Power <= -87 +#define RPI_1 1 // -87 < Power <= -82 +#define RPI_2 2 // -82 < Power <= -77 +#define RPI_3 3 // -77 < Power <= -72 +#define RPI_4 4 // -72 < Power <= -67 +#define RPI_5 5 // -67 < Power <= -62 +#define RPI_6 6 // -62 < Power <= -57 +#define RPI_7 7 // -57 < Power + +// Cisco Aironet IAPP definetions +#define AIRONET_IAPP_TYPE 0x32 +#define AIRONET_IAPP_SUBTYPE_REQUEST 0x01 +#define AIRONET_IAPP_SUBTYPE_REPORT 0x81 + +// Measurement Request detail format +typedef struct _MEASUREMENT_REQUEST { + UCHAR Channel; + UCHAR ScanMode; // Use only in beacon request, other requests did not use this field + USHORT Duration; +} MEASUREMENT_REQUEST, *PMEASUREMENT_REQUEST; + +// Beacon Measurement Report +// All these field might change to UCHAR, because we didn't do anything to these report. +// We copy all these beacons and report to CCX 2 AP. +typedef struct _BEACON_REPORT { + UCHAR Channel; + UCHAR Spare; + USHORT Duration; + UCHAR PhyType; // Definiation is listed above table 36-9 + UCHAR RxPower; + UCHAR BSSID[6]; + UCHAR ParentTSF[4]; + UCHAR TargetTSF[8]; + USHORT BeaconInterval; + USHORT CapabilityInfo; +} BEACON_REPORT, *PBEACON_REPORT; + +// Frame Measurement Report (Optional) +typedef struct _FRAME_REPORT { + UCHAR Channel; + UCHAR Spare; + USHORT Duration; + UCHAR TA; + UCHAR BSSID[6]; + UCHAR RSSI; + UCHAR Count; +} FRAME_REPORT, *PFRAME_REPORT; + +#pragma pack(1) +// Channel Load Report +typedef struct _CHANNEL_LOAD_REPORT { + UCHAR Channel; + UCHAR Spare; + USHORT Duration; + UCHAR CCABusy; +} CHANNEL_LOAD_REPORT, *PCHANNEL_LOAD_REPORT; +#pragma pack() + +// Nosie Histogram Report +typedef struct _NOISE_HIST_REPORT { + UCHAR Channel; + UCHAR Spare; + USHORT Duration; + UCHAR Density[8]; +} NOISE_HIST_REPORT, *PNOISE_HIST_REPORT; + +// Radio Management Capability element +typedef struct _RADIO_MANAGEMENT_CAPABILITY { + UCHAR Eid; // TODO: Why the Eid is 1 byte, not normal 2 bytes??? + UCHAR Length; + UCHAR AironetOui[3]; // AIronet OUI (00 40 96) + UCHAR Type; // Type / Version + USHORT Status; // swap16 required +} RADIO_MANAGEMENT_CAPABILITY, *PRADIO_MANAGEMENT_CAPABILITY; + +// Measurement Mode Bit definition +typedef struct _MEASUREMENT_MODE { + UCHAR Rsvd:4; + UCHAR Report:1; + UCHAR NotUsed:1; + UCHAR Enable:1; + UCHAR Parallel:1; +} MEASUREMENT_MODE, *PMEASUREMENT_MODE; + +// Measurement Request element, This is little endian mode +typedef struct _MEASUREMENT_REQUEST_ELEMENT { + USHORT Eid; + USHORT Length; // swap16 required + USHORT Token; // non-zero unique token + UCHAR Mode; // Measurement Mode + UCHAR Type; // Measurement type +} MEASUREMENT_REQUEST_ELEMENT, *PMEASUREMENT_REQUEST_ELEMENT; + +// Measurement Report element, This is little endian mode +typedef struct _MEASUREMENT_REPORT_ELEMENT { + USHORT Eid; + USHORT Length; // swap16 required + USHORT Token; // non-zero unique token + UCHAR Mode; // Measurement Mode + UCHAR Type; // Measurement type +} MEASUREMENT_REPORT_ELEMENT, *PMEASUREMENT_REPORT_ELEMENT; + +// Cisco Aironet IAPP Frame Header, Network byte order used +typedef struct _AIRONET_IAPP_HEADER { + UCHAR CiscoSnapHeader[8]; // 8 bytes Cisco snap header + USHORT Length; // IAPP ID & length, remember to swap16 in LE system + UCHAR Type; // IAPP type + UCHAR SubType; // IAPP subtype + UCHAR DA[6]; // Destination MAC address + UCHAR SA[6]; // Source MAC address + USHORT Token; // Dialog token, no need to swap16 since it is for yoken usage only +} AIRONET_IAPP_HEADER, *PAIRONET_IAPP_HEADER; + +// Radio Measurement Request frame +typedef struct _AIRONET_RM_REQUEST_FRAME { + AIRONET_IAPP_HEADER IAPP; // Common header + UCHAR Delay; // Activation Delay + UCHAR Offset; // Measurement offset +} AIRONET_RM_REQUEST_FRAME, *PAIRONET_RM_REQUEST_FRAME; + +// Radio Measurement Report frame +typedef struct _AIRONET_RM_REPORT_FRAME { + AIRONET_IAPP_HEADER IAPP; // Common header +} AIRONET_RM_REPORT_FRAME, *PAIRONET_RM_REPORT_FRAME; + +// Saved element request actions which will saved in StaCfg. +typedef struct _RM_REQUEST_ACTION { + MEASUREMENT_REQUEST_ELEMENT ReqElem; // Saved request element + MEASUREMENT_REQUEST Measurement; // Saved measurement within the request element +} RM_REQUEST_ACTION, *PRM_REQUEST_ACTION; + +// CCX administration control +typedef union _CCX_CONTROL { + struct { + UINT32 Enable:1; // Enable CCX2 + UINT32 LeapEnable:1; // Enable LEAP at CCX2 + UINT32 RMEnable:1; // Radio Measurement Enable + UINT32 DCRMEnable:1; // Non serving channel Radio Measurement enable + UINT32 QOSEnable:1; // Enable QOS for CCX 2.0 support + UINT32 FastRoamEnable:1; // Enable fast roaming + UINT32 Rsvd:2; // Not used + UINT32 dBmToRoam:8; // the condition to roam when receiving Rssi less than this value. It's negative value. + UINT32 TuLimit:16; // Limit for different channel scan + } field; + UINT32 word; +} CCX_CONTROL, *PCCX_CONTROL; + +#endif // __AIRONET_H__ diff --git a/drivers/staging/rt3070/ap.h b/drivers/staging/rt3070/ap.h new file mode 100644 index 000000000000..f5ba042e52ba --- /dev/null +++ b/drivers/staging/rt3070/ap.h @@ -0,0 +1,557 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + ap.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + James Tan 09-06-2002 modified (Revise NTCRegTable) + John Chang 12-22-2004 modified for RT2561/2661. merge with STA driver +*/ +#ifndef __AP_H__ +#define __AP_H__ + + + +// ========================= AP RTMP.h ================================ + + + +// ============================================================= +// Function Prototypes +// ============================================================= + +// ap_data.c + +BOOLEAN APBridgeToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN ULONG fromwdsidx); + +BOOLEAN APHandleRxDoneInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID APSendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets); + +NDIS_STATUS APSendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +NDIS_STATUS APHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx); + +VOID APRxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +NDIS_STATUS APCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PRT28XX_RXD_STRUC pRxD, + IN UCHAR Wcid); + +BOOLEAN APCheckClass2Class3Error( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader); + +VOID APHandleRxPsPoll( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Aid, + IN BOOLEAN isActive); + +VOID RTMPDescriptorEndianChange( + IN PUCHAR pData, + IN ULONG DescriptorType); + +VOID RTMPFrameEndianChange( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG Dir, + IN BOOLEAN FromRxDoneInt); + +// ap_assoc.c + +VOID APAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APPeerAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerReassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MbssKickOutStas( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN USHORT Reason); + +VOID APMlmeKickOutSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pStaAddr, + IN UCHAR Wcid, + IN USHORT Reason); + +VOID APMlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APCls3errAction( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader); + + +USHORT APBuildAssociation( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN USHORT CapabilityInfo, + IN UCHAR MaxSupportedRateIn500Kbps, + IN UCHAR *RSN, + IN UCHAR *pRSNLen, + IN BOOLEAN bWmmCapable, + IN ULONG RalinkIe, +#ifdef DOT11N_DRAFT3 + IN EXT_CAP_INFO_ELEMENT ExtCapInfo, +#endif // DOT11N_DRAFT3 // + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + OUT USHORT *pAid); + +/* +VOID RTMPAddClientSec( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN PUCHAR pKey, + IN PUCHAR pTxMic, + IN PUCHAR pRxMic, + IN MAC_TABLE_ENTRY *pEntry); +*/ + +// ap_auth.c + +void APAuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APMlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APCls2errAction( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN PHEADER_802_11 pHeader); + +// ap_authrsp.c + +VOID APAuthRspStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]); + +VOID APPeerAuthAtAuthRspIdleAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerAuthSimpleRspGenAndSend( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHdr80211, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT StatusCode); + +// ap_connect.c + +BOOLEAN BeaconTransmitRequired( + IN PRTMP_ADAPTER pAd, + IN INT apidx); + +VOID APMakeBssBeacon( + IN PRTMP_ADAPTER pAd, + IN INT apidx); + +VOID APUpdateBeaconFrame( + IN PRTMP_ADAPTER pAd, + IN INT apidx); + +VOID APMakeAllBssBeacon( + IN PRTMP_ADAPTER pAd); + +VOID APUpdateAllBeaconFrame( + IN PRTMP_ADAPTER pAd); + + +// ap_sync.c + +VOID APSyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APInvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APScanTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerBeaconAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APMlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APScanCnclAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ApSiteSurvey( + IN PRTMP_ADAPTER pAd); + +VOID SupportRate( + IN PUCHAR SupRate, + IN UCHAR SupRateLen, + IN PUCHAR ExtRate, + IN UCHAR ExtRateLen, + OUT PUCHAR *Rates, + OUT PUCHAR RatesLen, + OUT PUCHAR pMaxSupportRate); + + +BOOLEAN ApScanRunning( + IN PRTMP_ADAPTER pAd); + +#ifdef DOT11N_DRAFT3 +VOID APOverlappingBSSScan( + IN RTMP_ADAPTER *pAd); +#endif // DOT11N_DRAFT3 // + +// ap_wpa.c + +VOID APWpaStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +// ap_mlme.c + +VOID APMlmePeriodicExec( + IN PRTMP_ADAPTER pAd); + +VOID APMlmeSelectTxRateTable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR *ppTable, + IN PUCHAR pTableSize, + IN PUCHAR pInitTxRateIdx); + +VOID APMlmeSetTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH pTxRate); + +VOID APMlmeDynamicTxRateSwitching( + IN PRTMP_ADAPTER pAd); + +VOID APQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN APMsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +VOID APQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef RT2870 +VOID BeaconUpdateExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif // RT2870 // + +VOID RTMPSetPiggyBack( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bPiggyBack); + +VOID APAsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd); + +VOID APAsicRxAntEvalTimeout( + IN PRTMP_ADAPTER pAd); + +// ap.c + +VOID APSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN INT Channel); + +NDIS_STATUS APInitialize( + IN PRTMP_ADAPTER pAd); + +VOID APShutdown( + IN PRTMP_ADAPTER pAd); + +VOID APStartUp( + IN PRTMP_ADAPTER pAd); + +VOID APStop( + IN PRTMP_ADAPTER pAd); + +VOID APCleanupPsQueue( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_HEADER pQueue); + +VOID MacTableReset( + IN PRTMP_ADAPTER pAd); + +MAC_TABLE_ENTRY *MacTableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR apidx, + IN BOOLEAN CleanAll); + +BOOLEAN MacTableDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *MacTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID MacTableMaintenance( + IN PRTMP_ADAPTER pAd); + +UINT32 MacTableAssocStaNumGet( + IN PRTMP_ADAPTER pAd); + +MAC_TABLE_ENTRY *APSsPsInquiry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + OUT SST *Sst, + OUT USHORT *Aid, + OUT UCHAR *PsMode, + OUT UCHAR *Rate); + +BOOLEAN APPsIndicate( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN ULONG Wcid, + IN UCHAR Psm); + +VOID ApLogEvent( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Event); + +#ifdef DOT11_N_SUPPORT +VOID APUpdateOperationMode( + IN PRTMP_ADAPTER pAd); +#endif // DOT11_N_SUPPORT // + +VOID APUpdateCapabilityAndErpIe( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ApCheckAccessControlList( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR Apidx); + +VOID ApUpdateAccessControlList( + IN PRTMP_ADAPTER pAd, + IN UCHAR Apidx); + +VOID ApEnqueueNullFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR PID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP); + +VOID ApSendFrame( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuffer, + IN ULONG Length, + IN UCHAR TxRate, + IN UCHAR PID); + +VOID ApEnqueueAckFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR apidx); + +UCHAR APAutoSelectChannel( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN Optimal); + +// ap_sanity.c + + +BOOLEAN PeerAssocReqCmmSanity( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isRessoc, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pListenInterval, + OUT PUCHAR pApAddr, + OUT UCHAR *pSsidLen, + OUT char *Ssid, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *RSN, + OUT UCHAR *pRSNLen, + OUT BOOLEAN *pbWmmCapable, + OUT ULONG *pRalinkIe, +#ifdef DOT11N_DRAFT3 + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, +#endif // DOT11N_DRAFT3 // + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability); + + +BOOLEAN PeerDisassocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN PeerDeauthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN APPeerAuthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr1, + OUT PUCHAR pAddr2, + OUT USHORT *Alg, + OUT USHORT *Seq, + OUT USHORT *Status, + CHAR *ChlgText); + +BOOLEAN APPeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *SsidLen); + +BOOLEAN APPeerBeaconAndProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *SsidLen, + OUT UCHAR *BssType, + OUT USHORT *BeaconPeriod, + OUT UCHAR *Channel, + OUT LARGE_INTEGER *Timestamp, + OUT USHORT *CapabilityInfo, + OUT UCHAR Rate[], + OUT UCHAR *RateLen, + OUT BOOLEAN *ExtendedRateIeExist, + OUT UCHAR *Erp); + + +// ================== end of AP RTMP.h ======================== + + +#endif // __AP_H__ + diff --git a/drivers/staging/rt3070/chlist.h b/drivers/staging/rt3070/chlist.h new file mode 100644 index 000000000000..7151e8668cb5 --- /dev/null +++ b/drivers/staging/rt3070/chlist.h @@ -0,0 +1,1253 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + chlist.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi Wu 2007-12-19 created +*/ + +#ifndef __CHLIST_H__ +#define __CHLIST_H__ + +#include "rtmp_type.h" +#include "rtmp_def.h" + + +#define ODOR 0 +#define IDOR 1 +#define BOTH 2 + +#define BAND_5G 0 +#define BAND_24G 1 +#define BAND_BOTH 2 + +typedef struct _CH_DESP { + UCHAR FirstChannel; + UCHAR NumOfCh; + CHAR MaxTxPwr; // dBm + UCHAR Geography; // 0:out door, 1:in door, 2:both + BOOLEAN DfsReq; // Dfs require, 0: No, 1: yes. +} CH_DESP, *PCH_DESP; + +typedef struct _CH_REGION { + UCHAR CountReg[3]; + UCHAR DfsType; // 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56 + CH_DESP ChDesp[10]; +} CH_REGION, *PCH_REGION; + +static CH_REGION ChRegion[] = +{ + { // Antigua and Berbuda + "AG", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Argentina + "AR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Aruba + "AW", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Australia + "AU", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Austria + "AT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Bahamas + "BS", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Barbados + "BB", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Bermuda + "BM", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Brazil + "BR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 24, BOTH, FALSE}, // 5G, ch 100~140 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Belgium + "BE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 18, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 18, IDOR, FALSE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Bulgaria + "BG", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Canada + "CA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Cayman IsLands + "KY", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Chile + "CL", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // China + "CN", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Colombia + "CO", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Costa Rica + "CR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Cyprus + "CY", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Czech_Republic + "CZ", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Denmark + "DK", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Dominican Republic + "DO", + CE, + { + { 1, 0, 20, BOTH, FALSE}, // 2.4 G, ch 0 + { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Equador + "EC", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 100, 11, 27, BOTH, FALSE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // El Salvador + "SV", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 30, BOTH, TRUE}, // 5G, ch 52~64 + { 149, 4, 36, BOTH, TRUE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Finland + "FI", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // France + "FR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Germany + "DE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Greece + "GR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Guam + "GU", + CE, + { + { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Guatemala + "GT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Haiti + "HT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Honduras + "HN", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Hong Kong + "HK", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Hungary + "HU", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Iceland + "IS", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // India + "IN", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 24, IDOR, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Indonesia + "ID", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Ireland + "IE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Israel + "IL", + CE, + { + { 1, 3, 20, IDOR, FALSE}, // 2.4 G, ch 1~3 + { 4, 6, 20, BOTH, FALSE}, // 2.4 G, ch 4~9 + { 10, 4, 20, IDOR, FALSE}, // 2.4 G, ch 10~13 + { 0}, // end + } + }, + + { // Italy + "IT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Japan + "JP", + JAP, + { + { 1, 14, 20, BOTH, FALSE}, // 2.4 G, ch 1~14 + { 34, 4, 23, IDOR, FALSE}, // 5G, ch 34~46 + { 0}, // end + } + }, + + { // Jordan + "JO", + CE, + { + { 1, 13, 20, IDOR, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 149, 4, 23, IDOR, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Latvia + "LV", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Liechtenstein + "LI", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Lithuania + "LT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Luxemburg + "LU", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Malaysia + "MY", + CE, + { + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Malta + "MT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Marocco + "MA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48 + { 0}, // end + } + }, + + { // Mexico + "MX", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 5, 30, IDOR, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Netherlands + "NL", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // New Zealand + "NZ", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 24, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Norway + "NO", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Peru + "PE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Portugal + "PT", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Poland + "PL", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Romania + "RO", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Russia + "RU", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 149, 4, 20, IDOR, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Saudi Arabia + "SA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 23, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Serbia_and_Montenegro + "CS", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 0}, // end + } + }, + + { // Singapore + "SG", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Slovakia + "SK", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Slovenia + "SI", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // South Africa + "ZA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // South Korea + "KR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 8, 20, BOTH, FALSE}, // 5G, ch 100~128 + { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Spain + "ES", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 17, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Sweden + "SE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Switzerland + "CH", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13 + { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Taiwan + "TW", + CE, + { + { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // Turkey + "TR", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48 + { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64 + { 0}, // end + } + }, + + { // UK + "GB", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 23, IDOR, FALSE}, // 5G, ch 52~64 + { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 0}, // end + } + }, + + { // Ukraine + "UA", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 0}, // end + } + }, + + { // United_Arab_Emirates + "AE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 0}, // end + } + }, + + { // United_States + "US", + CE, + { + { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 17, IDOR, FALSE}, // 5G, ch 52~64 + { 52, 4, 24, BOTH, TRUE}, // 5G, ch 52~64 + { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140 + { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, + + { // Venezuela + "VE", + CE, + { + { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161 + { 0}, // end + } + }, + + { // Default + "", + CE, + { + { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11 + { 36, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 + { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64 + { 100, 11, 20, BOTH, FALSE}, // 5G, ch 100~140 + { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165 + { 0}, // end + } + }, +}; + +static inline PCH_REGION GetChRegion( + IN PUCHAR CntryCode) +{ + INT loop = 0; + PCH_REGION pChRegion = NULL; + + while (strcmp(ChRegion[loop].CountReg, "") != 0) + { + if (strncmp(ChRegion[loop].CountReg, CntryCode, 2) == 0) + { + pChRegion = &ChRegion[loop]; + break; + } + loop++; + } + + if (pChRegion == NULL) + pChRegion = &ChRegion[loop]; + return pChRegion; +} + +static inline VOID ChBandCheck( + IN UCHAR PhyMode, + OUT PUCHAR pChType) +{ + switch(PhyMode) + { + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11AN_MIXED: +#endif // DOT11_N_SUPPORT // + *pChType = BAND_5G; + break; + case PHY_11ABG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11AGN_MIXED: + case PHY_11ABGN_MIXED: +#endif // DOT11_N_SUPPORT // + *pChType = BAND_BOTH; + break; + + default: + *pChType = BAND_24G; + break; + } +} + +static inline UCHAR FillChList( + IN PRTMP_ADAPTER pAd, + IN PCH_DESP pChDesp, + IN UCHAR Offset, + IN UCHAR increment) +{ + INT i, j, l; + UCHAR channel; + + j = Offset; + for (i = 0; i < pChDesp->NumOfCh; i++) + { + channel = pChDesp->FirstChannel + i * increment; + for (l=0; lTxPower[l].Channel) + { + pAd->ChannelList[j].Power = pAd->TxPower[l].Power; + pAd->ChannelList[j].Power2 = pAd->TxPower[l].Power2; + break; + } + } + if (l == MAX_NUM_OF_CHANNELS) + continue; + + pAd->ChannelList[j].Channel = pChDesp->FirstChannel + i * increment; + pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr; + pAd->ChannelList[j].DfsReq = pChDesp->DfsReq; + j++; + } + pAd->ChannelListNum = j; + + return j; +} + +static inline VOID CreateChList( + IN PRTMP_ADAPTER pAd, + IN PCH_REGION pChRegion, + IN UCHAR Geography) +{ + INT i; + UCHAR offset = 0; + PCH_DESP pChDesp; + UCHAR ChType; + UCHAR increment; + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + + for (i=0; i<10; i++) + { + pChDesp = &pChRegion->ChDesp[i]; + if (pChDesp->FirstChannel == 0) + break; + + if (ChType == BAND_5G) + { + if (pChDesp->FirstChannel <= 14) + continue; + } + else if (ChType == BAND_24G) + { + if (pChDesp->FirstChannel > 14) + continue; + } + + if ((pChDesp->Geography == BOTH) + || (pChDesp->Geography == Geography)) + { + if (pChDesp->FirstChannel > 14) + increment = 4; + else + increment = 1; + offset = FillChList(pAd, pChDesp, offset, increment); + } + } +} + +static inline VOID BuildChannelListEx( + IN PRTMP_ADAPTER pAd) +{ + PCH_REGION pChReg; + + pChReg = GetChRegion(pAd->CommonCfg.CountryCode); + CreateChList(pAd, pChReg, pAd->CommonCfg.Geography); +} + +static inline VOID BuildBeaconChList( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf, + OUT PULONG pBufLen) +{ + INT i; + ULONG TmpLen; + PCH_REGION pChRegion; + PCH_DESP pChDesp; + UCHAR ChType; + + pChRegion = GetChRegion(pAd->CommonCfg.CountryCode); + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + *pBufLen = 0; + + for (i=0; i<10; i++) + { + pChDesp = &pChRegion->ChDesp[i]; + if (pChDesp->FirstChannel == 0) + break; + + if (ChType == BAND_5G) + { + if (pChDesp->FirstChannel <= 14) + continue; + } + else if (ChType == BAND_24G) + { + if (pChDesp->FirstChannel > 14) + continue; + } + + if ((pChDesp->Geography == BOTH) + || (pChDesp->Geography == pAd->CommonCfg.Geography)) + { + MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, + 1, &pChDesp->FirstChannel, + 1, &pChDesp->NumOfCh, + 1, &pChDesp->MaxTxPwr, + END_OF_ARGS); + *pBufLen += TmpLen; + } + } +} + + +#ifdef DOT11_N_SUPPORT +static inline BOOLEAN IsValidChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) + +{ + INT i; + + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return FALSE; + else + return TRUE; +} + + +static inline UCHAR GetExtCh( + IN UCHAR Channel, + IN UCHAR Direction) +{ + CHAR ExtCh; + + if (Direction == EXTCHA_ABOVE) + ExtCh = Channel + 4; + else + ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0; + + return ExtCh; +} + + +static inline VOID N_ChannelCheck( + IN PRTMP_ADAPTER pAd) +{ + //UCHAR ChannelNum = pAd->ChannelListNum; + UCHAR Channel = pAd->CommonCfg.Channel; + + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) + { + if (Channel > 14) + { + if ((Channel == 36) || (Channel == 44) || (Channel == 52) || (Channel == 60) || (Channel == 100) || (Channel == 108) || + (Channel == 116) || (Channel == 124) || (Channel == 132) || (Channel == 149) || (Channel == 157)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + } + else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || (Channel == 64) || (Channel == 104) || (Channel == 112) || + (Channel == 120) || (Channel == 128) || (Channel == 136) || (Channel == 153) || (Channel == 161)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } + } + else + { + do + { + UCHAR ExtCh; + UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) + break; + + Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir; + break; + } + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } while(FALSE); + + if (Channel == 14) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + //pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; // We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT() + } + } + } + + +} + + +static inline VOID N_SetCenCh( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + } + else + { + if (pAd->CommonCfg.Channel == 14) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 1; + else + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + } + } + else + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } +} +#endif // DOT11_N_SUPPORT // + + +static inline UINT8 GetCuntryMaxTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 channel) +{ + int i; + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return 0xff; + else + return pAd->ChannelList[i].MaxTxPwr; +} +#endif // __CHLIST_H__ + diff --git a/drivers/staging/rt3070/common/2870_rtmp_init.c b/drivers/staging/rt3070/common/2870_rtmp_init.c new file mode 100644 index 000000000000..fdf8dc176a67 --- /dev/null +++ b/drivers/staging/rt3070/common/2870_rtmp_init.c @@ -0,0 +1,1762 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + 2870_rtmp_init.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 2002-08-01 created + John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme + Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT. + Sample Lin 2007-05-31 Merge RT2860 and RT2870 drivers. +*/ + +#include "../rt_config.h" + + +static void rx_done_tasklet(unsigned long data); +static void rt2870_hcca_dma_done_tasklet(unsigned long data); +static void rt2870_ac3_dma_done_tasklet(unsigned long data); +static void rt2870_ac2_dma_done_tasklet(unsigned long data); +static void rt2870_ac1_dma_done_tasklet(unsigned long data); +static void rt2870_ac0_dma_done_tasklet(unsigned long data); +static void rt2870_mgmt_dma_done_tasklet(unsigned long data); +static void rt2870_null_frame_complete_tasklet(unsigned long data); +static void rt2870_rts_frame_complete_tasklet(unsigned long data); +static void rt2870_pspoll_frame_complete_tasklet(unsigned long data); +static void rt2870_dataout_complete_tasklet(unsigned long data); + + +/* +======================================================================== +Routine Description: + Initialize receive data structures. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_RESOURCES + +Note: + Initialize all receive releated private buffer, include those define + in RTMP_ADAPTER structure and all private data structures. The mahor + work is to allocate buffer for each packet and chain buffer to + NDIS packet descriptor. +======================================================================== +*/ +NDIS_STATUS NICInitRecv( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitRecv\n")); + pObj = pObj; + + //InterlockedExchange(&pAd->PendingRx, 0); + pAd->PendingRx = 0; + pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index + pAd->NextRxBulkInIndex = 0 ; //RX_RING_SIZE -1; // Rx Bulk pointer + pAd->NextRxBulkInPosition = 0; + + for (i = 0; i < (RX_RING_SIZE); i++) + { + PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + + //Allocate URB + pRxContext->pUrb = RTUSB_ALLOC_URB(0); + if (pRxContext->pUrb == NULL) + { + Status = NDIS_STATUS_RESOURCES; + goto out1; + } + + // Allocate transfer buffer + pRxContext->TransferBuffer = RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, &pRxContext->data_dma); + if (pRxContext->TransferBuffer == NULL) + { + Status = NDIS_STATUS_RESOURCES; + goto out1; + } + + NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE); + + pRxContext->pAd = pAd; + pRxContext->pIrp = NULL; + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; + //pRxContext->ReorderInUse = FALSE; + pRxContext->bRxHandling = FALSE; + pRxContext->BulkInOffset = 0; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitRecv\n")); + return Status; + +out1: + for (i = 0; i < (RX_RING_SIZE); i++) + { + PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + + if (NULL != pRxContext->TransferBuffer) + { + RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, + pRxContext->TransferBuffer, pRxContext->data_dma); + pRxContext->TransferBuffer = NULL; + } + + if (NULL != pRxContext->pUrb) + { + RTUSB_UNLINK_URB(pRxContext->pUrb); + RTUSB_FREE_URB(pRxContext->pUrb); + pRxContext->pUrb = NULL; + } + } + + return Status; +} + + +/* +======================================================================== +Routine Description: + Initialize transmit data structures. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_RESOURCES + +Note: +======================================================================== +*/ +NDIS_STATUS NICInitTransmit( + IN PRTMP_ADAPTER pAd) +{ +#define LM_USB_ALLOC(pObj, Context, TB_Type, BufferSize, Status, msg1, err1, msg2, err2) \ + Context->pUrb = RTUSB_ALLOC_URB(0); \ + if (Context->pUrb == NULL) { \ + DBGPRINT(RT_DEBUG_ERROR, msg1); \ + Status = NDIS_STATUS_RESOURCES; \ + goto err1; } \ + \ + Context->TransferBuffer = \ + (TB_Type)RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, BufferSize, &Context->data_dma); \ + if (Context->TransferBuffer == NULL) { \ + DBGPRINT(RT_DEBUG_ERROR, msg2); \ + Status = NDIS_STATUS_RESOURCES; \ + goto err2; } + +#define LM_URB_FREE(pObj, Context, BufferSize) \ + if (NULL != Context->pUrb) { \ + RTUSB_UNLINK_URB(Context->pUrb); \ + RTUSB_FREE_URB(Context->pUrb); \ + Context->pUrb = NULL; } \ + if (NULL != Context->TransferBuffer) { \ + RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ + Context->TransferBuffer, \ + Context->data_dma); \ + Context->TransferBuffer = NULL; } + + UCHAR i, acidx; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PTX_CONTEXT pNullContext = &(pAd->NullContext); + PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext); + PTX_CONTEXT pRTSContext = &(pAd->RTSContext); + PTX_CONTEXT pMLMEContext = NULL; +// PHT_TX_CONTEXT pHTTXContext = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PVOID RingBaseVa; +// RTMP_TX_RING *pTxRing; + RTMP_MGMT_RING *pMgmtRing; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTransmit\n")); + pObj = pObj; + + // Init 4 set of Tx parameters + for(acidx = 0; acidx < NUM_OF_TX_RING; acidx++) + { + // Initialize all Transmit releated queues + InitializeQueueHeader(&pAd->TxSwQueue[acidx]); + + // Next Local tx ring pointer waiting for buck out + pAd->NextBulkOutIndex[acidx] = acidx; + pAd->BulkOutPending[acidx] = FALSE; // Buck Out control flag + //pAd->DataBulkDoneIdx[acidx] = 0; + } + + //pAd->NextMLMEIndex = 0; + //pAd->PushMgmtIndex = 0; + //pAd->PopMgmtIndex = 0; + //InterlockedExchange(&pAd->MgmtQueueSize, 0); + //InterlockedExchange(&pAd->TxCount, 0); + + //pAd->PrioRingFirstIndex = 0; + //pAd->PrioRingTxCnt = 0; + + do + { + // + // TX_RING_SIZE, 4 ACs + // +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + for(acidx=0; acidx<4; acidx++) +#endif // CONFIG_STA_SUPPORT // + { +#if 1 //def DOT11_N_SUPPORT + PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]); + + NdisZeroMemory(pHTTXContext, sizeof(HT_TX_CONTEXT)); + //Allocate URB + LM_USB_ALLOC(pObj, pHTTXContext, PHTTX_BUFFER, sizeof(HTTX_BUFFER), Status, + ("<-- ERROR in Alloc TX TxContext[%d] urb!! \n", acidx), + done, + ("<-- ERROR in Alloc TX TxContext[%d] HTTX_BUFFER !! \n", acidx), + out1); + + NdisZeroMemory(pHTTXContext->TransferBuffer->Aggregation, 4); + pHTTXContext->pAd = pAd; + pHTTXContext->pIrp = NULL; + pHTTXContext->IRPPending = FALSE; + pHTTXContext->NextBulkOutPosition = 0; + pHTTXContext->ENextBulkOutPosition = 0; + pHTTXContext->CurWritePosition = 0; + pHTTXContext->CurWriteRealPos = 0; + pHTTXContext->BulkOutSize = 0; + pHTTXContext->BulkOutPipeId = acidx; + pHTTXContext->bRingEmpty = TRUE; + pHTTXContext->bCopySavePad = FALSE; +#endif // DOT11_N_SUPPORT // + pAd->BulkOutPending[acidx] = FALSE; + } + + + // + // MGMT_RING_SIZE + // + // Allocate MGMT ring descriptor's memory + pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * sizeof(TX_CONTEXT); + RTMPAllocateMemory(&pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); + if (pAd->MgmtDescRing.AllocVa == NULL) + { + DBGPRINT_ERR(("Failed to allocate a big buffer for MgmtDescRing!\n")); + Status = NDIS_STATUS_RESOURCES; + goto out1; + } + NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); + RingBaseVa = pAd->MgmtDescRing.AllocVa; + + // Initialize MGMT Ring and associated buffer memory + pMgmtRing = &pAd->MgmtRing; + for (i = 0; i < MGMT_RING_SIZE; i++) + { + // link the pre-allocated Mgmt buffer to MgmtRing.Cell + pMgmtRing->Cell[i].AllocSize = sizeof(TX_CONTEXT); + pMgmtRing->Cell[i].AllocVa = RingBaseVa; + pMgmtRing->Cell[i].pNdisPacket = NULL; + pMgmtRing->Cell[i].pNextNdisPacket = NULL; + + //Allocate URB for MLMEContext + pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa; + pMLMEContext->pUrb = RTUSB_ALLOC_URB(0); + if (pMLMEContext->pUrb == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("<-- ERROR in Alloc TX MLMEContext[%d] urb!! \n", i)); + Status = NDIS_STATUS_RESOURCES; + goto out2; + } + pMLMEContext->pAd = pAd; + pMLMEContext->pIrp = NULL; + pMLMEContext->TransferBuffer = NULL; + pMLMEContext->InUse = FALSE; + pMLMEContext->IRPPending = FALSE; + pMLMEContext->bWaitingBulkOut = FALSE; + pMLMEContext->BulkOutSize = 0; + pMLMEContext->SelfIdx = i; + + // Offset to next ring descriptor address + RingBaseVa = (PUCHAR) RingBaseVa + sizeof(TX_CONTEXT); + } + DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", i)); + + //pAd->MgmtRing.TxSwFreeIdx = (MGMT_RING_SIZE - 1); + pAd->MgmtRing.TxSwFreeIdx = MGMT_RING_SIZE; + pAd->MgmtRing.TxCpuIdx = 0; + pAd->MgmtRing.TxDmaIdx = 0; + + // + // BEACON_RING_SIZE + // + for(i=0; iBeaconContext[i]); + + + NdisZeroMemory(pBeaconContext, sizeof(TX_CONTEXT)); + + //Allocate URB + LM_USB_ALLOC(pObj, pBeaconContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, + ("<-- ERROR in Alloc TX BeaconContext[%d] urb!! \n", i), + out2, + ("<-- ERROR in Alloc TX BeaconContext[%d] TX_BUFFER !! \n", i), + out3); + + pBeaconContext->pAd = pAd; + pBeaconContext->pIrp = NULL; + pBeaconContext->InUse = FALSE; + pBeaconContext->IRPPending = FALSE; + } + + // + // NullContext + // + NdisZeroMemory(pNullContext, sizeof(TX_CONTEXT)); + + //Allocate URB + LM_USB_ALLOC(pObj, pNullContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, + ("<-- ERROR in Alloc TX NullContext urb!! \n"), + out3, + ("<-- ERROR in Alloc TX NullContext TX_BUFFER !! \n"), + out4); + + pNullContext->pAd = pAd; + pNullContext->pIrp = NULL; + pNullContext->InUse = FALSE; + pNullContext->IRPPending = FALSE; + + // + // RTSContext + // + NdisZeroMemory(pRTSContext, sizeof(TX_CONTEXT)); + + //Allocate URB + LM_USB_ALLOC(pObj, pRTSContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, + ("<-- ERROR in Alloc TX RTSContext urb!! \n"), + out4, + ("<-- ERROR in Alloc TX RTSContext TX_BUFFER !! \n"), + out5); + + pRTSContext->pAd = pAd; + pRTSContext->pIrp = NULL; + pRTSContext->InUse = FALSE; + pRTSContext->IRPPending = FALSE; + + // + // PsPollContext + // + //NdisZeroMemory(pPsPollContext, sizeof(TX_CONTEXT)); + //Allocate URB + LM_USB_ALLOC(pObj, pPsPollContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, + ("<-- ERROR in Alloc TX PsPollContext urb!! \n"), + out5, + ("<-- ERROR in Alloc TX PsPollContext TX_BUFFER !! \n"), + out6); + + pPsPollContext->pAd = pAd; + pPsPollContext->pIrp = NULL; + pPsPollContext->InUse = FALSE; + pPsPollContext->IRPPending = FALSE; + pPsPollContext->bAggregatible = FALSE; + pPsPollContext->LastOne = TRUE; + + } while (FALSE); + + +done: + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit\n")); + + return Status; + + /* --------------------------- ERROR HANDLE --------------------------- */ +out6: + LM_URB_FREE(pObj, pPsPollContext, sizeof(TX_BUFFER)); + +out5: + LM_URB_FREE(pObj, pRTSContext, sizeof(TX_BUFFER)); + +out4: + LM_URB_FREE(pObj, pNullContext, sizeof(TX_BUFFER)); + +out3: + for(i=0; iBeaconContext[i]); + if (pBeaconContext) + LM_URB_FREE(pObj, pBeaconContext, sizeof(TX_BUFFER)); + } + +out2: + if (pAd->MgmtDescRing.AllocVa) + { + pMgmtRing = &pAd->MgmtRing; + for(i=0; iMgmtRing.Cell[i].AllocVa; + if (pMLMEContext) + LM_URB_FREE(pObj, pMLMEContext, sizeof(TX_BUFFER)); + } + NdisFreeMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize, 0); + pAd->MgmtDescRing.AllocVa = NULL; + } + +out1: +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + for(acidx=0; acidx<4; acidx++) +#endif // CONFIG_STA_SUPPORT // + { + PHT_TX_CONTEXT pTxContext = &(pAd->TxContext[acidx]); + if (pTxContext) + LM_URB_FREE(pObj, pTxContext, sizeof(HTTX_BUFFER)); + } + + // Here we didn't have any pre-allocated memory need to free. + + return Status; +} + + +/* +======================================================================== +Routine Description: + Allocate DMA memory blocks for send, receive. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + +Note: +======================================================================== +*/ +NDIS_STATUS RTMPAllocTxRxRingMemory( + IN PRTMP_ADAPTER pAd) +{ +// COUNTER_802_11 pCounter = &pAd->WlanCounters; + NDIS_STATUS Status; + INT num; + + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); + + + do + { + // Init the CmdQ and CmdQLock + NdisAllocateSpinLock(&pAd->CmdQLock); + NdisAcquireSpinLock(&pAd->CmdQLock); + RTUSBInitializeCmdQ(&pAd->CmdQ); + NdisReleaseSpinLock(&pAd->CmdQLock); + + + NdisAllocateSpinLock(&pAd->MLMEBulkOutLock); + //NdisAllocateSpinLock(&pAd->MLMEWaitQueueLock); + NdisAllocateSpinLock(&pAd->BulkOutLock[0]); + NdisAllocateSpinLock(&pAd->BulkOutLock[1]); + NdisAllocateSpinLock(&pAd->BulkOutLock[2]); + NdisAllocateSpinLock(&pAd->BulkOutLock[3]); + NdisAllocateSpinLock(&pAd->BulkOutLock[4]); + NdisAllocateSpinLock(&pAd->BulkOutLock[5]); + NdisAllocateSpinLock(&pAd->BulkInLock); + + for (num = 0; num < NUM_OF_TX_RING; num++) + { + NdisAllocateSpinLock(&pAd->TxContextQueueLock[num]); + } + +#ifdef RALINK_ATE + NdisAllocateSpinLock(&pAd->GenericLock); +#endif // RALINK_ATE // + +// NdisAllocateSpinLock(&pAd->MemLock); // Not used in RT28XX + +// NdisAllocateSpinLock(&pAd->MacTabLock); // init it in UserCfgInit() +// NdisAllocateSpinLock(&pAd->BATabLock); // init it in BATableInit() + +// for(num=0; numBATable.BARecEntry[num].RxReRingLock); +// } + + // + // Init Mac Table + // +// MacTableInitialize(pAd); + + // + // Init send data structures and related parameters + // + Status = NICInitTransmit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + break; + + // + // Init receive data structures and related parameters + // + Status = NICInitRecv(pAd); + if (Status != NDIS_STATUS_SUCCESS) + break; + + pAd->PendingIoCount = 1; + + } while (FALSE); + + NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); + pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + + if (pAd->FragFrame.pFragPacket == NULL) + { + Status = NDIS_STATUS_RESOURCES; + } + + DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); + return Status; +} + + +/* +======================================================================== +Routine Description: + Calls USB_InterfaceStop and frees memory allocated for the URBs + calls NdisMDeregisterDevice and frees the memory + allocated in VNetInitialize for the Adapter Object + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMPFreeTxRxRingMemory( + IN PRTMP_ADAPTER pAd) +{ +#define LM_URB_FREE(pObj, Context, BufferSize) \ + if (NULL != Context->pUrb) { \ + RTUSB_UNLINK_URB(Context->pUrb); \ + RTUSB_FREE_URB(Context->pUrb); \ + Context->pUrb = NULL; } \ + if (NULL != Context->TransferBuffer) { \ + RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ + Context->TransferBuffer, \ + Context->data_dma); \ + Context->TransferBuffer = NULL; } + + + UINT i, acidx; + PTX_CONTEXT pNullContext = &pAd->NullContext; + PTX_CONTEXT pPsPollContext = &pAd->PsPollContext; + PTX_CONTEXT pRTSContext = &pAd->RTSContext; +// PHT_TX_CONTEXT pHTTXContext; + //PRTMP_REORDERBUF pReorderBuf; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +// RTMP_TX_RING *pTxRing; + + DBGPRINT(RT_DEBUG_ERROR, ("---> RTMPFreeTxRxRingMemory\n")); + pObj = pObj; + + // Free all resources for the RECEIVE buffer queue. + for(i=0; i<(RX_RING_SIZE); i++) + { + PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + if (pRxContext) + LM_URB_FREE(pObj, pRxContext, MAX_RXBULK_SIZE); + } + + // Free PsPoll frame resource + LM_URB_FREE(pObj, pPsPollContext, sizeof(TX_BUFFER)); + + // Free NULL frame resource + LM_URB_FREE(pObj, pNullContext, sizeof(TX_BUFFER)); + + // Free RTS frame resource + LM_URB_FREE(pObj, pRTSContext, sizeof(TX_BUFFER)); + + + // Free beacon frame resource + for(i=0; iBeaconContext[i]); + if (pBeaconContext) + LM_URB_FREE(pObj, pBeaconContext, sizeof(TX_BUFFER)); + } + + + // Free mgmt frame resource + for(i = 0; i < MGMT_RING_SIZE; i++) + { + PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa; + //LM_URB_FREE(pObj, pMLMEContext, sizeof(TX_BUFFER)); + if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket) + { + RTMPFreeNdisPacket(pAd, pAd->MgmtRing.Cell[i].pNdisPacket); + pAd->MgmtRing.Cell[i].pNdisPacket = NULL; + pMLMEContext->TransferBuffer = NULL; + } + + if (pMLMEContext) + { + if (NULL != pMLMEContext->pUrb) + { + RTUSB_UNLINK_URB(pMLMEContext->pUrb); + RTUSB_FREE_URB(pMLMEContext->pUrb); + pMLMEContext->pUrb = NULL; + } + } + } + if (pAd->MgmtDescRing.AllocVa) + NdisFreeMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize, 0); + + + // Free Tx frame resource +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + for(acidx=0; acidx<4; acidx++) +#endif // CONFIG_STA_SUPPORT // + { + PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]); + if (pHTTXContext) + LM_URB_FREE(pObj, pHTTXContext, sizeof(HTTX_BUFFER)); + } + + if (pAd->FragFrame.pFragPacket) + RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); + + for(i=0; i<6; i++) + { + NdisFreeSpinLock(&pAd->BulkOutLock[i]); + } + + NdisFreeSpinLock(&pAd->BulkInLock); + NdisFreeSpinLock(&pAd->MLMEBulkOutLock); + + NdisFreeSpinLock(&pAd->CmdQLock); +#ifdef RALINK_ATE + NdisFreeSpinLock(&pAd->GenericLock); +#endif // RALINK_ATE // + // Clear all pending bulk-out request flags. + RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff); + +// NdisFreeSpinLock(&pAd->MacTabLock); + +// for(i=0; iBATable.BARecEntry[i].RxReRingLock); +// } + + DBGPRINT(RT_DEBUG_ERROR, ("<--- ReleaseAdapter\n")); +} + + +/* +======================================================================== +Routine Description: + Allocate memory for adapter control block. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + +Note: +======================================================================== +*/ +NDIS_STATUS AdapterBlockAllocateMemory( + IN PVOID handle, + OUT PVOID *ppAd) +{ + PUSB_DEV usb_dev; + POS_COOKIE pObj = (POS_COOKIE) handle; + + + usb_dev = pObj->pUsb_Dev; + + pObj->MLMEThr_pid = NULL; + pObj->RTUSBCmdThr_pid = NULL; + + *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); + + if (*ppAd) + { + NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER)); + ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle; + return (NDIS_STATUS_SUCCESS); + } + else + { + return (NDIS_STATUS_FAILURE); + } +} + + +/* +======================================================================== +Routine Description: + Create kernel threads & tasklets. + +Arguments: + *net_dev Pointer to wireless net device interface + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +NDIS_STATUS CreateThreads( + IN struct net_device *net_dev) +{ + PRTMP_ADAPTER pAd = net_dev->ml_priv; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + pid_t pid_number; + + //init_MUTEX(&(pAd->usbdev_semaphore)); + + init_MUTEX_LOCKED(&(pAd->mlme_semaphore)); + init_completion (&pAd->mlmeComplete); + + init_MUTEX_LOCKED(&(pAd->RTUSBCmd_semaphore)); + init_completion (&pAd->CmdQComplete); + + init_MUTEX_LOCKED(&(pAd->RTUSBTimer_semaphore)); + init_completion (&pAd->TimerQComplete); + + // Creat MLME Thread + pObj->MLMEThr_pid = NULL; + pid_number = kernel_thread(MlmeThread, pAd, CLONE_VM); + if (pid_number < 0) + { + printk (KERN_WARNING "%s: unable to start Mlme thread\n",pAd->net_dev->name); + return NDIS_STATUS_FAILURE; + } + pObj->MLMEThr_pid = find_get_pid(pid_number); + // Wait for the thread to start + wait_for_completion(&(pAd->mlmeComplete)); + + // Creat Command Thread + pObj->RTUSBCmdThr_pid = NULL; + pid_number = kernel_thread(RTUSBCmdThread, pAd, CLONE_VM); + if (pid_number < 0) + { + printk (KERN_WARNING "%s: unable to start RTUSBCmd thread\n",pAd->net_dev->name); + return NDIS_STATUS_FAILURE; + } + pObj->RTUSBCmdThr_pid = find_get_pid(pid_number); + wait_for_completion(&(pAd->CmdQComplete)); + + pObj->TimerQThr_pid = NULL; + pid_number = kernel_thread(TimerQThread, pAd, CLONE_VM); + if (pid_number < 0) + { + printk (KERN_WARNING "%s: unable to start TimerQThread\n",pAd->net_dev->name); + return NDIS_STATUS_FAILURE; + } + pObj->TimerQThr_pid = find_get_pid(pid_number); + // Wait for the thread to start + wait_for_completion(&(pAd->TimerQComplete)); + + // Create receive tasklet + tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (ULONG)pAd); + tasklet_init(&pObj->mgmt_dma_done_task, rt2870_mgmt_dma_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->ac0_dma_done_task, rt2870_ac0_dma_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->ac1_dma_done_task, rt2870_ac1_dma_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->ac2_dma_done_task, rt2870_ac2_dma_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->ac3_dma_done_task, rt2870_ac3_dma_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->hcca_dma_done_task, rt2870_hcca_dma_done_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->null_frame_complete_task, rt2870_null_frame_complete_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->rts_frame_complete_task, rt2870_rts_frame_complete_tasklet, (unsigned long)pAd); + tasklet_init(&pObj->pspoll_frame_complete_task, rt2870_pspoll_frame_complete_tasklet, (unsigned long)pAd); + + return NDIS_STATUS_SUCCESS; +} + + +#ifdef CONFIG_STA_SUPPORT +/* +======================================================================== +Routine Description: + As STA's BSSID is a WC too, it uses shared key table. + This function write correct unicast TX key to ASIC WCID. + And we still make a copy in our MacTab.Content[BSSID_WCID].PairwiseKey. + Caller guarantee TKIP/AES always has keyidx = 0. (pairwise key) + Caller guarantee WEP calls this function when set Txkey, default key index=0~3. + +Arguments: + pAd Pointer to our adapter + pKey Pointer to the where the key stored + +Return Value: + NDIS_SUCCESS Add key successfully + +Note: +======================================================================== +*/ +VOID RTMPAddBSSIDCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR Aid, + IN PNDIS_802_11_KEY pKey, + IN UCHAR CipherAlg) +{ + PUCHAR pTxMic, pRxMic; + BOOLEAN bKeyRSC, bAuthenticator; // indicate the receive SC set by KeyRSC value +// UCHAR CipherAlg; + UCHAR i; + ULONG WCIDAttri; + USHORT offset; + UCHAR KeyIdx, IVEIV[8]; + UINT32 Value; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddBSSIDCipher==> Aid = %d\n",Aid)); + + // Bit 29 of Add-key KeyRSC + bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE; + + // Bit 28 of Add-key Authenticator + bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE; + KeyIdx = (UCHAR)pKey->KeyIndex&0xff; + + if (KeyIdx > 4) + return; + + + if (pAd->MacTab.Content[Aid].PairwiseKey.CipherAlg == CIPHER_TKIP) + { if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + // for WPA-None Tx, Rx MIC is the same + pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16; + pRxMic = pTxMic; + } + else if (bAuthenticator == TRUE) + { + pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16; + pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 24; + } + else + { + pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 16; + pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 24; + } + + offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE) + 0x10; + for (i=0; i<8; ) + { + Value = *(pTxMic+i); + Value += (*(pTxMic+i+1)<<8); + Value += (*(pTxMic+i+2)<<16); + Value += (*(pTxMic+i+3)<<24); + RTUSBWriteMACRegister(pAd, offset+i, Value); + i+=4; + } + + offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE) + 0x18; + for (i=0; i<8; ) + { + Value = *(pRxMic+i); + Value += (*(pRxMic+i+1)<<8); + Value += (*(pRxMic+i+2)<<16); + Value += (*(pRxMic+i+3)<<24); + RTUSBWriteMACRegister(pAd, offset+i, Value); + i+=4; + } + + // Only Key lenth equal to TKIP key have these + NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxMic, pRxMic, 8); + NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.TxMic, pTxMic, 8); + + DBGPRINT(RT_DEBUG_TRACE, + (" TxMIC = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", + pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3], + pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); + DBGPRINT(RT_DEBUG_TRACE, + (" RxMIC = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", + pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3], + pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); + } + + // 2. Record Security Key. + pAd->MacTab.Content[BSSID_WCID].PairwiseKey.KeyLen= (UCHAR)pKey->KeyLength; + NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); + + // 3. Check RxTsc. And used to init to ASIC IV. + if (bKeyRSC == TRUE) + NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxTsc, &pKey->KeyRSC, 6); + else + NdisZeroMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxTsc, 6); + + // 4. Init TxTsc to one based on WiFi WPA specs + pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[0] = 1; + pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[1] = 0; + pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[2] = 0; + pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[3] = 0; + pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[4] = 0; + pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[5] = 0; + + CipherAlg = pAd->MacTab.Content[Aid].PairwiseKey.CipherAlg; + + offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE); + RTUSBMultiWrite(pAd, (USHORT) offset, pKey->KeyMaterial, + ((pKey->KeyLength == LEN_TKIP_KEY) ? 16 : (USHORT)pKey->KeyLength)); + + offset = SHARED_KEY_TABLE_BASE + (KeyIdx * HW_KEY_ENTRY_SIZE); + RTUSBMultiWrite(pAd, (USHORT) offset, pKey->KeyMaterial, (USHORT)pKey->KeyLength); + + offset = PAIRWISE_IVEIV_TABLE_BASE + (Aid * HW_IVEIV_ENTRY_SIZE); + NdisZeroMemory(IVEIV, 8); + + // IV/EIV + if ((CipherAlg == CIPHER_TKIP) || + (CipherAlg == CIPHER_TKIP_NO_MIC) || + (CipherAlg == CIPHER_AES)) + { + IVEIV[3] = 0x20; // Eiv bit on. keyid always 0 for pairwise key + } + // default key idx needs to set. + // in TKIP/AES KeyIdx = 0 , WEP KeyIdx is default tx key. + else + { + IVEIV[3] |= (KeyIdx<< 6); + } + RTUSBMultiWrite(pAd, (USHORT) offset, IVEIV, 8); + + // WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:1=PAIRWISE KEY, BSSIdx is 0 + if ((CipherAlg == CIPHER_TKIP) || + (CipherAlg == CIPHER_TKIP_NO_MIC) || + (CipherAlg == CIPHER_AES)) + { + WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE; + } + else + WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE; + + offset = MAC_WCID_ATTRIBUTE_BASE + (Aid* HW_WCID_ATTRI_SIZE); + RTUSBWriteMACRegister(pAd, offset, WCIDAttri); + RTUSBReadMACRegister(pAd, offset, &Value); + + DBGPRINT(RT_DEBUG_TRACE, ("BSSID_WCID : offset = %x, WCIDAttri = %lx\n", + offset, WCIDAttri)); + + // pAddr + // Add Bssid mac address at linkup. not here. check! + /*offset = MAC_WCID_BASE + (BSSID_WCID * HW_WCID_ENTRY_SIZE); + *for (i=0; iBSSID[i]); + } + */ + + DBGPRINT(RT_DEBUG_ERROR, ("AddBSSIDasWCIDEntry: Alg=%s, KeyLength = %d\n", + CipherName[CipherAlg], pKey->KeyLength)); + DBGPRINT(RT_DEBUG_TRACE, ("Key [idx=%x] [KeyLen = %d]\n", + pKey->KeyIndex, pKey->KeyLength)); + for(i=0; iKeyLength; i++) + DBGPRINT_RAW(RT_DEBUG_TRACE,(" %x:", pKey->KeyMaterial[i])); + DBGPRINT(RT_DEBUG_TRACE,(" \n")); +} +#endif // CONFIG_STA_SUPPORT // + +/* +======================================================================== +Routine Description: + Get a received packet. + +Arguments: + pAd device control block + pSaveRxD receive descriptor information + *pbReschedule need reschedule flag + *pRxPending pending received packet flag + +Return Value: + the recieved packet + +Note: +======================================================================== +*/ +#define RT2870_RXDMALEN_FIELD_SIZE 4 +PNDIS_PACKET GetPacketFromRxRing( + IN PRTMP_ADAPTER pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN *pbReschedule, + IN OUT UINT32 *pRxPending) +{ + PRX_CONTEXT pRxContext; + PNDIS_PACKET pSkb; + PUCHAR pData; + ULONG ThisFrameLen; + ULONG RxBufferLength; + PRXWI_STRUC pRxWI; + + pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex]; + if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE)) + return NULL; + + RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition; + if (RxBufferLength < (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXWI_STRUC) + sizeof(RXINFO_STRUC))) + { + goto label_null; + } + + pData = &pRxContext->TransferBuffer[pAd->ReadPosition]; /* 4KB */ + // The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding) + ThisFrameLen = *pData + (*(pData+1)<<8); + if (ThisFrameLen == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n", + pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); + goto label_null; + } + if ((ThisFrameLen&0x3) != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n", + pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); + goto label_null; + } + + if ((ThisFrameLen + 8)> RxBufferLength) // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC)) + { + DBGPRINT(RT_DEBUG_TRACE,("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n", + pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset, RxBufferLength, pAd->ReadPosition)); + + // error frame. finish this loop + goto label_null; + } + + // skip USB frame length field + pData += RT2870_RXDMALEN_FIELD_SIZE; + pRxWI = (PRXWI_STRUC)pData; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pData, TYPE_RXWI); +#endif // RT_BIG_ENDIAN // + if (pRxWI->MPDUtotalByteCount > ThisFrameLen) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n", + __FUNCTION__, pRxWI->MPDUtotalByteCount, ThisFrameLen)); + goto label_null; + } +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pData, TYPE_RXWI); +#endif // RT_BIG_ENDIAN // + + // allocate a rx packet + pSkb = dev_alloc_skb(ThisFrameLen); + if (pSkb == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", __FUNCTION__)); + goto label_null; + } + + // copy the rx packet + memcpy(skb_put(pSkb, ThisFrameLen), pData, ThisFrameLen); + RTPKT_TO_OSPKT(pSkb)->dev = get_netdev_from_bssid(pAd, BSS0); + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb), PKTSRC_NDIS); + + // copy RxD + *pSaveRxD = *(PRXINFO_STRUC)(pData + ThisFrameLen); +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pSaveRxD, TYPE_RXINFO); +#endif // RT_BIG_ENDIAN // + + // update next packet read position. + pAd->ReadPosition += (ThisFrameLen + RT2870_RXDMALEN_FIELD_SIZE + RXINFO_SIZE); // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC)) + + return pSkb; + +label_null: + + return NULL; +} + + +/* +======================================================================== +Routine Description: + Handle received packets. + +Arguments: + data - URB information pointer + +Return Value: + None + +Note: +======================================================================== +*/ +static void rx_done_tasklet(unsigned long data) +{ + purbb_t pUrb; + PRX_CONTEXT pRxContext; + PRTMP_ADAPTER pAd; + NTSTATUS Status; + unsigned int IrqFlags; + + pUrb = (purbb_t)data; + pRxContext = (PRX_CONTEXT)pUrb->context; + pAd = pRxContext->pAd; + Status = pUrb->status; + + + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->BulkInOffset += pUrb->actual_length; + //NdisInterlockedDecrement(&pAd->PendingRx); + pAd->PendingRx--; + + if (Status == USB_ST_NOERROR) + { + pAd->BulkInComplete++; + pAd->NextRxBulkInPosition = 0; + if (pRxContext->BulkInOffset) // As jan's comment, it may bulk-in success but size is zero. + { + pRxContext->Readable = TRUE; + INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE); + } + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + } + else // STATUS_OTHER + { + pAd->BulkInCompleteFail++; + // Still read this packet although it may comtain wrong bytes. + pRxContext->Readable = FALSE; + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + + // Parsing all packets. because after reset, the index will reset to all zero. + if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_BULKIN_RESET | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk In Failed. Status=%d, BIIdx=0x%x, BIRIdx=0x%x, actual_length= 0x%x\n", + Status, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pRxContext->pUrb->actual_length)); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0); + } + } + + ASSERT((pRxContext->InUse == pRxContext->IRPPending)); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + // If the driver is in ATE mode and Rx frame is set into here. + if (pAd->ContinBulkIn == TRUE) + { + RTUSBBulkReceive(pAd); + } + } + else +#endif // RALINK_ATE // + RTUSBBulkReceive(pAd); + + return; + +} + + +static void rt2870_mgmt_dma_done_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + PTX_CONTEXT pMLMEContext; + int index; + PNDIS_PACKET pPacket; + purbb_t pUrb; + NTSTATUS Status; + unsigned long IrqFlags; + + + pUrb = (purbb_t)data; + pMLMEContext = (PTX_CONTEXT)pUrb->context; + pAd = pMLMEContext->pAd; + Status = pUrb->status; + index = pMLMEContext->SelfIdx; + + ASSERT((pAd->MgmtRing.TxDmaIdx == index)); + + RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); + + + if (Status != USB_ST_NOERROR) + { + //Bulk-Out fail status handle + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out MLME Failed, Status=%d!\n", Status)); + // TODO: How to handle about the MLMEBulkOut failed issue. Need to resend the mgmt pkt? + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); + } + } + + pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); + + RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); + // Reset MLME context flags + pMLMEContext->IRPPending = FALSE; + pMLMEContext->InUse = FALSE; + pMLMEContext->bWaitingBulkOut = FALSE; + pMLMEContext->BulkOutSize = 0; + + pPacket = pAd->MgmtRing.Cell[index].pNdisPacket; + pAd->MgmtRing.Cell[index].pNdisPacket = NULL; + + // Increase MgmtRing Index + INC_RING_INDEX(pAd->MgmtRing.TxDmaIdx, MGMT_RING_SIZE); + pAd->MgmtRing.TxSwFreeIdx++; + RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); + + // No-matter success or fail, we free the mgmt packet. + if (pPacket) + RTMPFreeNdisPacket(pAd, pPacket); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + // do nothing and return directly. + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET) && + ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG)) + { // For Mgmt Bulk-Out failed, ignore it now. + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + } + else + { + + // Always call Bulk routine, even reset bulk. + // The protectioon of rest bulk should be in BulkOut routine + if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) + { + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); + } + RTUSBKickBulkOut(pAd); + } + } + +} + + +static void rt2870_hcca_dma_done_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + PHT_TX_CONTEXT pHTTXContext; + UCHAR BulkOutPipeId = 4; + purbb_t pUrb; + + + pUrb = (purbb_t)data; + pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; + pAd = pHTTXContext->pAd; + + rt2870_dataout_complete_tasklet((unsigned long)pUrb); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + // do nothing and return directly. + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) + { + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + } + else + { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && + /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ + (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && + (pHTTXContext->bCurWriting == FALSE)) + { + RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); + } + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<4); + RTUSBKickBulkOut(pAd); + } + } + + + return; +} + + +static void rt2870_ac3_dma_done_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + PHT_TX_CONTEXT pHTTXContext; + UCHAR BulkOutPipeId = 3; + purbb_t pUrb; + + + pUrb = (purbb_t)data; + pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; + pAd = pHTTXContext->pAd; + + rt2870_dataout_complete_tasklet((unsigned long)pUrb); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + // do nothing and return directly. + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) + { + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + } + else + { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && + /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ + (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && + (pHTTXContext->bCurWriting == FALSE)) + { + RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); + } + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<3); + RTUSBKickBulkOut(pAd); + } + } + + + return; +} + + +static void rt2870_ac2_dma_done_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + PHT_TX_CONTEXT pHTTXContext; + UCHAR BulkOutPipeId = 2; + purbb_t pUrb; + + + pUrb = (purbb_t)data; + pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; + pAd = pHTTXContext->pAd; + + rt2870_dataout_complete_tasklet((unsigned long)pUrb); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + // do nothing and return directly. + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) + { + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + } + else + { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && + /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ + (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && + (pHTTXContext->bCurWriting == FALSE)) + { + RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); + } + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<2); + RTUSBKickBulkOut(pAd); + } + } + + return; +} + + +static void rt2870_ac1_dma_done_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + PHT_TX_CONTEXT pHTTXContext; + UCHAR BulkOutPipeId = 1; + purbb_t pUrb; + + + pUrb = (purbb_t)data; + pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; + pAd = pHTTXContext->pAd; + + rt2870_dataout_complete_tasklet((unsigned long)pUrb); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + // do nothing and return directly. + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) + { + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + } + else + { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && + /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ + (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && + (pHTTXContext->bCurWriting == FALSE)) + { + RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); + } + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<1); + RTUSBKickBulkOut(pAd); + } + } + + + return; +} + + +static void rt2870_ac0_dma_done_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + PHT_TX_CONTEXT pHTTXContext; + UCHAR BulkOutPipeId = 0; + purbb_t pUrb; + + + pUrb = (purbb_t)data; + pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; + pAd = pHTTXContext->pAd; + + rt2870_dataout_complete_tasklet((unsigned long)pUrb); + + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + // do nothing and return directly. + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) + { + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + } + else + { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && + /* ((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ + (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && + (pHTTXContext->bCurWriting == FALSE)) + { + RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); + } + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL); + RTUSBKickBulkOut(pAd); + } + } + + + return; + +} + + +static void rt2870_null_frame_complete_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + PTX_CONTEXT pNullContext; + purbb_t pUrb; + NTSTATUS Status; + unsigned long irqFlag; + + + pUrb = (purbb_t)data; + pNullContext = (PTX_CONTEXT)pUrb->context; + pAd = pNullContext->pAd; + Status = pUrb->status; + + // Reset Null frame context flags + RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); + pNullContext->IRPPending = FALSE; + pNullContext->InUse = FALSE; + pAd->BulkOutPending[0] = FALSE; + pAd->watchDogTxPendingCnt[0] = 0; + + if (Status == USB_ST_NOERROR) + { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + else // STATUS_OTHER + { + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out Null Frame Failed, ReasonCode=%d!\n", Status)); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + } + else + { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + } + } + + // Always call Bulk routine, even reset bulk. + // The protectioon of rest bulk should be in BulkOut routine + RTUSBKickBulkOut(pAd); + +} + + +static void rt2870_rts_frame_complete_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + PTX_CONTEXT pRTSContext; + purbb_t pUrb; + NTSTATUS Status; + unsigned long irqFlag; + + + pUrb = (purbb_t)data; + pRTSContext = (PTX_CONTEXT)pUrb->context; + pAd = pRTSContext->pAd; + Status = pUrb->status; + + // Reset RTS frame context flags + RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); + pRTSContext->IRPPending = FALSE; + pRTSContext->InUse = FALSE; + + if (Status == USB_ST_NOERROR) + { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + else // STATUS_OTHER + { + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out RTS Frame Failed\n")); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + } + else + { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); + } + } + + RTMP_SEM_LOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); + pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE; + RTMP_SEM_UNLOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); + + // Always call Bulk routine, even reset bulk. + // The protectioon of rest bulk should be in BulkOut routine + RTUSBKickBulkOut(pAd); + +} + + +static void rt2870_pspoll_frame_complete_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + PTX_CONTEXT pPsPollContext; + purbb_t pUrb; + NTSTATUS Status; + + + pUrb = (purbb_t)data; + pPsPollContext = (PTX_CONTEXT)pUrb->context; + pAd = pPsPollContext->pAd; + Status = pUrb->status; + + // Reset PsPoll context flags + pPsPollContext->IRPPending = FALSE; + pPsPollContext->InUse = FALSE; + pAd->watchDogTxPendingCnt[0] = 0; + + if (Status == USB_ST_NOERROR) + { + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + else // STATUS_OTHER + { + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out PSPoll Failed\n")); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + } + } + + RTMP_SEM_LOCK(&pAd->BulkOutLock[0]); + pAd->BulkOutPending[0] = FALSE; + RTMP_SEM_UNLOCK(&pAd->BulkOutLock[0]); + + // Always call Bulk routine, even reset bulk. + // The protectioon of rest bulk should be in BulkOut routine + RTUSBKickBulkOut(pAd); + +} + + +static void rt2870_dataout_complete_tasklet(unsigned long data) +{ + PRTMP_ADAPTER pAd; + purbb_t pUrb; + POS_COOKIE pObj; + PHT_TX_CONTEXT pHTTXContext; + UCHAR BulkOutPipeId; + NTSTATUS Status; + unsigned long IrqFlags; + + + pUrb = (purbb_t)data; + pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; + pAd = pHTTXContext->pAd; + pObj = (POS_COOKIE) pAd->OS_Cookie; + Status = pUrb->status; + + // Store BulkOut PipeId + BulkOutPipeId = pHTTXContext->BulkOutPipeId; + pAd->BulkOutDataOneSecCount++; + + //DBGPRINT(RT_DEBUG_LOUD, ("Done-B(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", BulkOutPipeId, in_interrupt(), pHTTXContext->CurWritePosition, + // pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); + + RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + pHTTXContext->IRPPending = FALSE; + pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; + + if (Status == USB_ST_NOERROR) + { + pAd->BulkOutComplete++; + + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + pAd->Counters8023.GoodTransmits++; + //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext); + //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + + + } + else // STATUS_OTHER + { + PUCHAR pBuf; + + pAd->BulkOutCompleteOther++; + + pBuf = &pHTTXContext->TransferBuffer->field.WirelessPacket[pHTTXContext->NextBulkOutPosition]; + + if (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_BULKOUT_RESET))) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + pAd->bulkResetPipeid = BulkOutPipeId; + pAd->bulkResetReq[BulkOutPipeId] = pAd->BulkOutReq; + } + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkOutDataPacket failed: ReasonCode=%d!\n", Status)); + DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); + DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Header:%x %x %x %x %x %x %x %x\n", pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7])); + //DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOutCompleteCancel=0x%x, BulkOutCompleteOther=0x%x\n", pAd->BulkOutCompleteCancel, pAd->BulkOutCompleteOther)); + + } + + // + // bInUse = TRUE, means some process are filling TX data, after that must turn on bWaitingBulkOut + // bWaitingBulkOut = TRUE, means the TX data are waiting for bulk out. + // + //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + if ((pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition) && + (pHTTXContext->ENextBulkOutPosition != (pHTTXContext->CurWritePosition+8)) && + !RTUSB_TEST_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId))) + { + // Indicate There is data avaliable + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); + } + //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + + // Always call Bulk routine, even reset bulk. + // The protection of rest bulk should be in BulkOut routine + RTUSBKickBulkOut(pAd); +} + +/* End of 2870_rtmp_init.c */ diff --git a/drivers/staging/rt3070/common/action.c b/drivers/staging/rt3070/common/action.c new file mode 100644 index 000000000000..b8ae53633661 --- /dev/null +++ b/drivers/staging/rt3070/common/action.c @@ -0,0 +1,1038 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + action.c + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 2006 created for rt2860 + */ + +#include "../rt_config.h" +#include "../action.h" + + +static VOID ReservedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following + + ASSOC_IDLE + MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action + MT2_PEER_DISASSOC_REQ peer_disassoc_action + MT2_PEER_ASSOC_REQ drop + MT2_PEER_REASSOC_REQ drop + MT2_CLS3ERR cls3err_action + ========================================================================== + */ +VOID ActionStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction); +#ifdef QOS_DLS_SUPPORT + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)PeerDLSAction); +#endif // QOS_DLS_SUPPORT // + +#ifdef DOT11_N_SUPPORT + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); +#endif // DOT11_N_SUPPORT // + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction); +} + +#ifdef DOT11_N_SUPPORT +VOID MlmeADDBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + MLME_ADDBA_REQ_STRUCT *pInfo; + UCHAR Addr[6]; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG Idx; + FRAME_ADDBA_REQ Frame; + ULONG FrameLen; + BA_ORI_ENTRY *pBAEntry = NULL; + + pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; + NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); + + if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr)) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + // 1. find entry + Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; + if (Idx == 0) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); + return; + } + else + { + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr); + + } +#endif // CONFIG_STA_SUPPORT // + + Frame.Category = CATEGORY_BA; + Frame.Action = ADDBA_REQ; + Frame.BaParm.AMSDUSupported = 0; + Frame.BaParm.BAPolicy = IMMED_BA; + Frame.BaParm.TID = pInfo->TID; + Frame.BaParm.BufSize = pInfo->BaBufSize; + Frame.Token = pInfo->Token; + Frame.TimeOutValue = pInfo->TimeOutValue; + Frame.BaStartSeq.field.FragNum = 0; + Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; + + *(USHORT *)(&Frame.BaParm) = cpu2le16(*(USHORT *)(&Frame.BaParm)); + Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); + Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ADDBA_REQ), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + //MiniportDataMMRequest(pAd, MapUserPriorityToAccessCategory[pInfo->TID], pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); + } +} + +/* + ========================================================================== + Description: + send DELBA and delete BaEntry if any + Parametrs: + Elem - MLME message MLME_DELBA_REQ_STRUCT + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDELBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_DELBA_REQ_STRUCT *pInfo; + PUCHAR pOutBuffer = NULL; + PUCHAR pOutBuffer2 = NULL; + NDIS_STATUS NStatus; + ULONG Idx; + FRAME_DELBA_REQ Frame; + ULONG FrameLen; + FRAME_BAR FrameBar; + + pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg; + // must send back DELBA + NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ)); + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); + + if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen)) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n")); + return; + } + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); + return; + } + + // SEND BAR (Send BAR to refresh peer reordering buffer.) + Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress); +#endif // CONFIG_STA_SUPPORT // + + FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL funciton. + FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.TID = pInfo->TID; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.ACKPolicy = IMMED_BA; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.Compressed = 1; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.MTID = 0; // make sure sequence not clear in DEL funciton. + + MakeOutgoingFrame(pOutBuffer2, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer2); + DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); + + // SEND DELBA FRAME + FrameLen = 0; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); + } +#endif // CONFIG_STA_SUPPORT // + Frame.Category = CATEGORY_BA; + Frame.Action = DELBA; + Frame.DelbaParm.Initiator = pInfo->Initiator; + Frame.DelbaParm.TID = pInfo->TID; + Frame.ReasonCode = 39; // Time Out + *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm)); + Frame.ReasonCode = cpu2le16(Frame.ReasonCode); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_DELBA_REQ), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator)); + } +} +#endif // DOT11_N_SUPPORT // + +VOID MlmeQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +VOID MlmeDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +VOID MlmeInvalidAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + //PUCHAR pOutBuffer = NULL; + //Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11 +} + +VOID PeerQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +#ifdef QOS_DLS_SUPPORT +VOID PeerDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { + case ACTION_DLS_REQUEST: +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + PeerDlsReqAction(pAd, Elem); +#endif // CONFIG_STA_SUPPORT // + break; + + case ACTION_DLS_RESPONSE: +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + PeerDlsRspAction(pAd, Elem); +#endif // CONFIG_STA_SUPPORT // + break; + + case ACTION_DLS_TEARDOWN: +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + PeerDlsTearDownAction(pAd, Elem); +#endif // CONFIG_STA_SUPPORT // + break; + } +} +#endif // QOS_DLS_SUPPORT // + +#ifdef DOT11_N_SUPPORT +VOID PeerBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { + case ADDBA_REQ: + PeerAddBAReqAction(pAd,Elem); + break; + case ADDBA_RESP: + PeerAddBARspAction(pAd,Elem); + break; + case DELBA: + PeerDelBAAction(pAd,Elem); + break; + } +} + + +#ifdef DOT11N_DRAFT3 + +#ifdef CONFIG_STA_SUPPORT +VOID StaPublicAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Bss2040Coexist) +{ + BSS_2040_COEXIST_IE BssCoexist; + MLME_SCAN_REQ_STRUCT ScanReq; + + BssCoexist.word = Bss2040Coexist; + // AP asks Station to return a 20/40 BSS Coexistence mgmt frame. So we first starts a scan, then send back 20/40 BSS Coexistence mgmt frame + if ((BssCoexist.field.InfoReq == 1) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))) + { + // Clear record first. After scan , will update those bit and send back to transmiter. + pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1; + pAd->CommonCfg.BSSCoexist2040.field.Intolerant40 = 0; + pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 0; + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + } +} + + +/* +Description : Build Intolerant Channel Rerpot from Trigger event table. +return : how many bytes copied. +*/ +ULONG BuildIntolerantChannelRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDest) +{ + ULONG FrameLen = 0; + ULONG ReadOffset = 0; + UCHAR i; + UCHAR LastRegClass = 0xff; + PUCHAR pLen; + + for ( i = 0;i < MAX_TRIGGER_EVENT;i++) + { + if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid == TRUE) + { + if (pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass == LastRegClass) + { + *(pDest + ReadOffset) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel; + *pLen++; + ReadOffset++; + FrameLen++; + } + else + { + *(pDest + ReadOffset) = IE_2040_BSS_INTOLERANT_REPORT; // IE + *(pDest + ReadOffset + 1) = 2; // Len = RegClass byte + channel byte. + pLen = pDest + ReadOffset + 1; + LastRegClass = pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass; + *(pDest + ReadOffset + 2) = LastRegClass; // Len = RegClass byte + channel byte. + *(pDest + ReadOffset + 3) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel; + FrameLen += 4; + ReadOffset += 4; + } + + } + } + return FrameLen; +} + + +/* +Description : Send 20/40 BSS Coexistence Action frame If one trigger event is triggered. +*/ +VOID Send2040CoexistAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + ULONG IntolerantChaRepLen; + + IntolerantChaRepLen = 0; + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction() allocate memory failed \n")); + return; + } + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CommonCfg.Bssid); + Frame.Category = CATEGORY_PUBLIC; + Frame.Action = ACTION_BSS_2040_COEXIST; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + END_OF_ARGS); + + *(pOutBuffer + FrameLen) = pAd->CommonCfg.BSSCoexist2040.word; + FrameLen++; + + if (bAddIntolerantCha == TRUE) + IntolerantChaRepLen = BuildIntolerantChannelRep(pAd, pOutBuffer + FrameLen); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen + IntolerantChaRepLen); + DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction( BSSCoexist2040 = 0x%x ) \n", pAd->CommonCfg.BSSCoexist2040.word)); + +} + + +/* + ========================================================================== + Description: + After scan, Update 20/40 BSS Coexistence IE and send out. + According to 802.11n D3.03 11.14.10 + + Parameters: + ========================================================================== + */ +VOID Update2040CoexistFrameAndNotify( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha) +{ + BSS_2040_COEXIST_IE OldValue; + + OldValue.word = pAd->CommonCfg.BSSCoexist2040.word; + if ((pAd->CommonCfg.TriggerEventTab.EventANo > 0) || (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)) + pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 1; + + // Need to check !!!! + // How STA will set Intolerant40 if implementation dependent. Now we don't set this bit first.!!!!! + // So Only check BSS20WidthReq change. + if (OldValue.field.BSS20WidthReq != pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq) + { + Send2040CoexistAction(pAd, Wcid, bAddIntolerantCha); + } +} +#endif // CONFIG_STA_SUPPORT // + + +BOOLEAN ChannelSwitchSanityCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary) +{ + UCHAR i; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + if ((NewChannel > 7) && (Secondary == 1)) + return FALSE; + + if ((NewChannel < 5) && (Secondary == 3)) + return FALSE; + + // 0. Check if new channel is in the channellist. + for (i = 0;i < pAd->ChannelListNum;i++) + { + if (pAd->ChannelList[i].Channel == NewChannel) + { + break; + } + } + + if (i == pAd->ChannelListNum) + return FALSE; + + return TRUE; +} + + +VOID ChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary) +{ + UCHAR BBPValue = 0; + ULONG MACValue; + + DBGPRINT(RT_DEBUG_TRACE,("SPECTRUM - ChannelSwitchAction(NewChannel = %d , Secondary = %d) \n", NewChannel, Secondary)); + + if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE) + return; + + // 1. Switches to BW = 20. + if (Secondary == 0) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + pAd->CommonCfg.BBPCurrentBW = BW_20; + pAd->CommonCfg.Channel = NewChannel; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel,FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0; + DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz !!! \n" )); + } + // 1. Switches to BW = 40 And Station supports BW = 40. + else if (((Secondary == 1) || (Secondary == 3)) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) + { + pAd->CommonCfg.Channel = NewChannel; + + if (Secondary == 1) + { + // Secondary above. + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue); + MACValue &= 0xfe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + BBPValue|= (0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue); + BBPValue&= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); + } + else + { + // Secondary below. + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue); + MACValue &= 0xfe; + MACValue |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + BBPValue|= (0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue); + BBPValue&= (~0x20); + BBPValue|= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); + } + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1; + } +} +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +VOID PeerPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +#ifdef DOT11N_DRAFT3 + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; +#endif // DOT11N_DRAFT3 // + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + +#ifdef DOT11N_DRAFT3 + switch(Action) + { + case ACTION_BSS_2040_COEXIST: // Format defined in IEEE 7.4.7a.1 in 11n Draf3.03 + { + //UCHAR BssCoexist; + BSS_2040_COEXIST_ELEMENT *pCoexistInfo; + BSS_2040_COEXIST_IE *pBssCoexistIe; + BSS_2040_INTOLERANT_CH_REPORT *pIntolerantReport = NULL; + + if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen)); + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n")); + hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen); + + + pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2]; + //hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT)); + if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT))) + { + pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT)); + } + //hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT)); + + pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (INFRA_ON(pAd)) + { + StaPublicAction(pAd, pCoexistInfo); + } + } +#endif // CONFIG_STA_SUPPORT // + + } + break; + } + +#endif // DOT11N_DRAFT3 // + +} + + +static VOID ReservedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Category; + + if (Elem->MsgLen <= LENGTH_802_11) + { + return; + } + + Category = Elem->Msg[LENGTH_802_11]; + DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category)); + hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen); +} + +VOID PeerRMAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + return; +} + +#ifdef DOT11_N_SUPPORT +static VOID respond_ht_information_exchange_action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + FRAME_HT_INFO HTINFOframe, *pFrame; + UCHAR *pAddr; + + + // 2. Always send back ADDBA Response + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n")); + return; + } + + // get RA + pFrame = (FRAME_HT_INFO *) &Elem->Msg[0]; + pAddr = pFrame->Hdr.Addr2; + + NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO)); + // 2-1. Prepare ADDBA Response frame. +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); + } +#endif // CONFIG_STA_SUPPORT // + + HTINFOframe.Category = CATEGORY_HT; + HTINFOframe.Action = HT_INFO_EXCHANGE; + HTINFOframe.HT_Info.Request = 0; + HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant; + HTINFOframe.HT_Info.STA_Channel_Width = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_HT_INFO), &HTINFOframe, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + + +#ifdef DOT11N_DRAFT3 +VOID SendNotifyBWActionFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + PUCHAR pAddr1; + + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n")); + return; + } + + if (Wcid == MCAST_WCID) + pAddr1 = &BROADCAST_ADDR[0]; + else + pAddr1 = pAd->MacTab.Content[Wcid].Addr; + ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); + + Frame.Category = CATEGORY_HT; + Frame.Action = NOTIFY_BW_ACTION; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + END_OF_ARGS); + + *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + FrameLen++; + + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth)); + +} +#endif // DOT11N_DRAFT3 // + + +VOID PeerHTAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + switch(Action) + { + case NOTIFY_BW_ACTION: + DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n")); +#ifdef CONFIG_STA_SUPPORT + if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + { + // Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps + // sending BW_Notify Action frame, and cause us to linkup and linkdown. + // In legacy mode, don't need to parse HT action frame. + DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n", + Elem->Msg[LENGTH_802_11+2] )); + break; + } +#endif // CONFIG_STA_SUPPORT // + + if (Elem->Msg[LENGTH_802_11+2] == 0) // 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. + pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0; + + break; + + case SMPS_ACTION: + // 7.3.1.25 + DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n")); + if (((Elem->Msg[LENGTH_802_11+2]&0x1) == 0)) + { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE; + } + else if (((Elem->Msg[LENGTH_802_11+2]&0x2) == 0)) + { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC; + } + else + { + pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC; + } + + DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pAd->MacTab.Content[Elem->Wcid].MmpsMode)); + // rt2860c : add something for smps change. + break; + + case SETPCO_ACTION: + break; + + case MIMO_CHA_MEASURE_ACTION: + break; + + case HT_INFO_EXCHANGE: + { + HT_INFORMATION_OCTET *pHT_info; + + pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2]; + // 7.4.8.10 + DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n")); + if (pHT_info->Request) + { + respond_ht_information_exchange_action(pAd, Elem); + } + } + break; + } +} + + +/* + ========================================================================== + Description: + Retry sending ADDBA Reqest. + + IRQL = DISPATCH_LEVEL + + Parametrs: + p8023Header: if this is already 802.3 format, p8023Header is NULL + + Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. + FALSE , then continue indicaterx at this moment. + ========================================================================== + */ +VOID ORIBATimerTimeout( + IN PRTMP_ADAPTER pAd) +{ + MAC_TABLE_ENTRY *pEntry; + INT i, total; +// FRAME_BAR FrameBar; +// ULONG FrameLen; +// NDIS_STATUS NStatus; +// PUCHAR pOutBuffer = NULL; +// USHORT Sequence; + UCHAR TID; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + total = pAd->MacTab.Size * NUM_OF_TID; + + for (i = 1; ((i 0)) ; i++) + { + if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done) + { + pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid]; + TID = pAd->BATable.BAOriEntry[i].TID; + + ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE); + } + total --; + } +} + + +VOID SendRefreshBAR( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + FRAME_BAR FrameBar; + ULONG FrameLen; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + USHORT Sequence; + UCHAR i, TID; + USHORT idx; + BA_ORI_ENTRY *pBAEntry; + + for (i = 0; i BAOriWcidArray[i]; + if (idx == 0) + { + continue; + } + pBAEntry = &pAd->BATable.BAOriEntry[idx]; + + if (pBAEntry->ORI_BA_Status == Originator_Done) + { + TID = pBAEntry->TID; + + ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + + Sequence = pEntry->TxSeq[TID]; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress); +#endif // CONFIG_STA_SUPPORT // + + FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function. + FrameBar.StartingSeq.field.StartSeq = Sequence; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.TID = TID; // make sure sequence not clear in DEL funciton. + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + //if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET))) + if (1) // Now we always send BAR. + { + //MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + //MiniportDataMMRequest(pAd, MapUserPriorityToAccessCategory[TID], pOutBuffer, FrameLen); + } + MlmeFreeMemory(pAd, pOutBuffer); + } + } +} +#endif // DOT11_N_SUPPORT // + +VOID ActHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN PUCHAR Addr1, + IN PUCHAR Addr2, + IN PUCHAR Addr3) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SUBTYPE_ACTION; + + COPY_MAC_ADDR(pHdr80211->Addr1, Addr1); + COPY_MAC_ADDR(pHdr80211->Addr2, Addr2); + COPY_MAC_ADDR(pHdr80211->Addr3, Addr3); +} + +VOID BarHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PFRAME_BAR pCntlBar, + IN PUCHAR pDA, + IN PUCHAR pSA) +{ +// USHORT Duration; + + NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR)); + pCntlBar->FC.Type = BTYPE_CNTL; + pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ; + pCntlBar->BarControl.MTID = 0; + pCntlBar->BarControl.Compressed = 1; + pCntlBar->BarControl.ACKPolicy = 0; + + + pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA)); + + COPY_MAC_ADDR(pCntlBar->Addr1, pDA); + COPY_MAC_ADDR(pCntlBar->Addr2, pSA); +} + + +/* + ========================================================================== + Description: + Insert Category and action code into the action frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. category code of the frame. + 4. action code of the frame. + + Return : None. + ========================================================================== + */ +VOID InsertActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode) +{ + ULONG TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &Category, + 1, &ActCode, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} diff --git a/drivers/staging/rt3070/common/ba_action.c b/drivers/staging/rt3070/common/ba_action.c new file mode 100644 index 000000000000..17e1f87d98db --- /dev/null +++ b/drivers/staging/rt3070/common/ba_action.c @@ -0,0 +1,1810 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + */ + + +#ifdef DOT11_N_SUPPORT + +#include "../rt_config.h" + + + +#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session + +#define ORI_SESSION_MAX_RETRY 8 +#define ORI_BA_SESSION_TIMEOUT (2000) // ms +#define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms + +#define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms +#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * HZ)/1000) // system ticks -- 100 ms + +#define RESET_RCV_SEQ (0xFFFF) + +static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk); + + +BA_ORI_ENTRY *BATableAllocOriEntry( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Idx); + +BA_REC_ENTRY *BATableAllocRecEntry( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Idx); + +VOID BAOriSessionSetupTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID BARecSessionIdleTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout); +BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout); + +#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \ + Announce_Reordering_Packet(_pAd, _mpdu_blk); + +VOID BA_MaxWinSizeReasign( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntryPeer, + OUT UCHAR *pWinSize) +{ + UCHAR MaxSize; + + + if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3 + { + if (pAd->MACVersion >= RALINK_3070_VERSION) + { + if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) + MaxSize = 7; // for non-open mode + else + MaxSize = 13; + } + else + MaxSize = 31; + } + else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e + { + if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) + MaxSize = 7; // for non-open mode + else + MaxSize = 13; + } + else + MaxSize = 7; + + DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n", + *pWinSize, MaxSize)); + + if ((*pWinSize) > MaxSize) + { + DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n", + *pWinSize, MaxSize)); + + *pWinSize = MaxSize; + } +} + +void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd, + IN struct reordering_mpdu *mpdu) +{ + PNDIS_PACKET pPacket; + + pPacket = mpdu->pPacket; + + if (mpdu->bAMSDU) + { + ASSERT(0); + BA_Reorder_AMSDU_Annnounce(pAd, pPacket); + } + else + { + // + // pass this 802.3 packet to upper layer or forward this packet to WM directly + // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket)); +#endif // CONFIG_STA_SUPPORT // + } +} + +/* + * Insert a reordering mpdu into sorted linked list by sequence no. + */ +BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu) +{ + + struct reordering_mpdu **ppScan = &list->next; + + while (*ppScan != NULL) + { + if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) + { + ppScan = &(*ppScan)->next; + } + else if ((*ppScan)->Sequence == mpdu->Sequence) + { + /* give up this duplicated frame */ + return(FALSE); + } + else + { + /* find position */ + break; + } + } + + mpdu->next = *ppScan; + *ppScan = mpdu; + list->qlen++; + return TRUE; +} + + +/* + * caller lock critical section if necessary + */ +static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk) +{ + list->qlen++; + mpdu_blk->next = list->next; + list->next = mpdu_blk; +} + +/* + * caller lock critical section if necessary + */ +static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list) +{ + struct reordering_mpdu *mpdu_blk = NULL; + + ASSERT(list); + + if (list->qlen) + { + list->qlen--; + mpdu_blk = list->next; + if (mpdu_blk) + { + list->next = mpdu_blk->next; + mpdu_blk->next = NULL; + } + } + return mpdu_blk; +} + + +static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list) +{ + return(ba_dequeue(list)); +} + + +static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list) + { + ASSERT(list); + + return(list->next); + } + + +/* + * free all resource for reordering mechanism + */ +void ba_reordering_resource_release(PRTMP_ADAPTER pAd) +{ + BA_TABLE *Tab; + PBA_REC_ENTRY pBAEntry; + struct reordering_mpdu *mpdu_blk; + int i; + + Tab = &pAd->BATable; + + /* I. release all pending reordering packet */ + NdisAcquireSpinLock(&pAd->BATabLock); + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + pBAEntry = &Tab->BARecEntry[i]; + if (pBAEntry->REC_BA_Status != Recipient_NONE) + { + while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) + { + ASSERT(mpdu_blk->pPacket); + RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE); + ba_mpdu_blk_free(pAd, mpdu_blk); + } + } + } + NdisReleaseSpinLock(&pAd->BATabLock); + + ASSERT(pBAEntry->list.qlen == 0); + /* II. free memory of reordering mpdu table */ + NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); + os_free_mem(pAd, pAd->mpdu_blk_pool.mem); + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); +} + + + +/* + * Allocate all resource for reordering mechanism + */ +BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num) +{ + int i; + PUCHAR mem; + struct reordering_mpdu *mpdu_blk; + struct reordering_list *freelist; + + /* allocate spinlock */ + NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock); + + /* initialize freelist */ + freelist = &pAd->mpdu_blk_pool.freelist; + freelist->next = NULL; + freelist->qlen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu)))); + + /* allocate number of mpdu_blk memory */ + os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu))); + + pAd->mpdu_blk_pool.mem = mem; + + if (mem == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n")); + return(FALSE); + } + + /* build mpdu_blk free list */ + for (i=0; impdu_blk_pool.lock); + mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist); + if (mpdu_blk) + { +// blk_count++; + /* reset mpdu_blk */ + NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); + } + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); + return mpdu_blk; +} + +static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk) +{ + ASSERT(mpdu_blk); + + NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); +// blk_count--; + ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk); + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); +} + + +static USHORT ba_indicate_reordering_mpdus_in_order( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN USHORT StartSeq) +{ + struct reordering_mpdu *mpdu_blk; + USHORT LastIndSeq = RESET_RCV_SEQ; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) + { + /* find in-order frame */ + if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) + { + break; + } + /* dequeue in-order frame from reodering list */ + mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + /* move to next sequence */ + StartSeq = mpdu_blk->Sequence; + LastIndSeq = StartSeq; + /* free mpdu_blk */ + ba_mpdu_blk_free(pAd, mpdu_blk); + } + + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + + /* update last indicated sequence */ + return LastIndSeq; +} + +static void ba_indicate_reordering_mpdus_le_seq( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN USHORT Sequence) +{ + struct reordering_mpdu *mpdu_blk; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) + { + /* find in-order frame */ + if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) + { + /* dequeue in-order frame from reodering list */ + mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + /* free mpdu_blk */ + ba_mpdu_blk_free(pAd, mpdu_blk); + } + else + { + break; + } + } + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); +} + + +static void ba_refresh_reordering_mpdus( + IN PRTMP_ADAPTER pAd, + PBA_REC_ENTRY pBAEntry) +{ + struct reordering_mpdu *mpdu_blk; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + /* dequeue in-order frame from reodering list */ + while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) + { + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + + pBAEntry->LastIndSeq = mpdu_blk->Sequence; + ba_mpdu_blk_free(pAd, mpdu_blk); + + /* update last indicated sequence */ + } + ASSERT(pBAEntry->list.qlen == 0); + pBAEntry->LastIndSeq = RESET_RCV_SEQ; + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); +} + + +//static +void ba_flush_reordering_timeout_mpdus( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN ULONG Now32) + +{ + USHORT Sequence; + +// if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && +// (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| +// (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && +// (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6))) + &&(pBAEntry->list.qlen > 1) + ) + { + DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), + (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT, + pBAEntry->LastIndSeq)); + ba_refresh_reordering_mpdus(pAd, pBAEntry); + pBAEntry->LastIndSeqAtTimer = Now32; + } + else + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) + && (pBAEntry->list.qlen > 0) + ) + { +// printk("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer), +// (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT, +// pBAEntry->LastIndSeq); + // + // force LastIndSeq to shift to LastIndSeq+1 + // + Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ; + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); + pBAEntry->LastIndSeqAtTimer = Now32; + pBAEntry->LastIndSeq = Sequence; + // + // indicate in-order mpdus + // + Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence); + if (Sequence != RESET_RCV_SEQ) + { + pBAEntry->LastIndSeq = Sequence; + } + + //printk("%x, flush one!\n", pBAEntry->LastIndSeq); + + } +} + + +/* + * generate ADDBA request to + * set up BA agreement + */ +VOID BAOriSessionSetUp( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced) + +{ + //MLME_ADDBA_REQ_STRUCT AddbaReq; + BA_ORI_ENTRY *pBAEntry = NULL; + USHORT Idx; + BOOLEAN Cancelled; + + if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE)) + return; + + // if this entry is limited to use legacy tx mode, it doesn't generate BA. + if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT) + return; + + if ((pEntry->BADeclineBitmap & (1<BAOriWcidArray[TID]; + if (Idx == 0) + { + // allocate a BA session + pBAEntry = BATableAllocOriEntry(pAd, &Idx); + if (pBAEntry == NULL) + { + DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n")); + return; + } + } + else + { + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } + + if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) + { + return; + } + + pEntry->BAOriWcidArray[TID] = Idx; + + // Initialize BA session + pBAEntry->ORI_BA_Status = Originator_WaitRes; + pBAEntry->Wcid = pEntry->Aid; + pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + pBAEntry->Sequence = BA_ORI_INIT_SEQ; + pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0 + pBAEntry->TID = TID; + pBAEntry->TimeOutValue = TimeOut; + pBAEntry->pAdapter = pAd; + + DBGPRINT(RT_DEBUG_TRACE,("Send AddBA to %02x:%02x:%02x:%02x:%02x:%02x Tid:%d isForced:%d Wcid:%d\n" + ,pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2] + ,pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5] + ,TID,isForced,pEntry->Aid)); + + if (!(pEntry->TXBAbitmap & (1<ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE); + } + else + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); + + // set timer to send ADDBA request + RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime); +} + +VOID BAOriSessionAdd( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PFRAME_ADDBA_RSP pFrame) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + BOOLEAN Cancelled; + UCHAR TID; + USHORT Idx; + PUCHAR pOutBuffer2 = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + FRAME_BAR FrameBar; + + TID = pFrame->BaParm.TID; + Idx = pEntry->BAOriWcidArray[TID]; + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + + // Start fill in parameters. + if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) + { + pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize)); + BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize); + + pBAEntry->TimeOutValue = pFrame->TimeOutValue; + pBAEntry->ORI_BA_Status = Originator_Done; + // reset sequence number + pBAEntry->Sequence = BA_ORI_INIT_SEQ; + // Set Bitmap flag. + pEntry->TXBAbitmap |= (1<ORIBATimer, &Cancelled); + + pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue; + + DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap, + pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue)); + + // SEND BAR ; + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n")); + return; + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress); +#endif // CONFIG_STA_SUPPORT // + + FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function. + FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton. + FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton. + MakeOutgoingFrame(pOutBuffer2, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer2); + + + if (pBAEntry->ORIBATimer.TimerValue) + RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec + } +} + +BOOLEAN BARecSessionAdd( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PFRAME_ADDBA_REQ pFrame) +{ + BA_REC_ENTRY *pBAEntry = NULL; + BOOLEAN Status = TRUE; + BOOLEAN Cancelled; + USHORT Idx; + UCHAR TID; + UCHAR BAWinSize; + //UINT32 Value; + //UINT offset; + + + ASSERT(pEntry); + + // find TID + TID = pFrame->BaParm.TID; + + BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + + // Intel patch + if (BAWinSize == 0) + { + BAWinSize = 64; + } + + Idx = pEntry->BARecWcidArray[TID]; + + + if (Idx == 0) + { + pBAEntry = BATableAllocRecEntry(pAd, &Idx); + } + else + { + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + // flush all pending reordering mpdus + ba_refresh_reordering_mpdus(pAd, pBAEntry); + } + + DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx, + pFrame->BaParm.BufSize, BAWinSize)); + + // Start fill in parameters. + if (pBAEntry != NULL) + { + ASSERT(pBAEntry->list.qlen == 0); + + pBAEntry->REC_BA_Status = Recipient_HandleRes; + pBAEntry->BAWinSize = BAWinSize; + pBAEntry->Wcid = pEntry->Aid; + pBAEntry->TID = TID; + pBAEntry->TimeOutValue = pFrame->TimeOutValue; + pBAEntry->REC_BA_Status = Recipient_Accept; + // initial sequence number + pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq; + + printk("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq); + + if (pEntry->RXBAbitmap & (1<RECBATimer, &Cancelled); + } + else + { + RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE); + } + + // Set Bitmap flag. + pEntry->RXBAbitmap |= (1<BARecWcidArray[TID] = Idx; + + pEntry->BADeclineBitmap &= ~(1<Aid, TID); + + DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", + pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID])); + } + else + { + Status = FALSE; + DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n", + PRINT_MAC(pEntry->Addr), TID)); + } + return(Status); +} + + +BA_REC_ENTRY *BATableAllocRecEntry( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Idx) +{ + int i; + BA_REC_ENTRY *pBAEntry = NULL; + + + NdisAcquireSpinLock(&pAd->BATabLock); + + if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) + { + printk("BA Recipeint Session (%ld) > %d\n", pAd->BATable.numAsRecipient, + MAX_BARECI_SESSION); + goto done; + } + + // reserve idx 0 to identify BAWcidArray[TID] as empty + for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + pBAEntry =&pAd->BATable.BARecEntry[i]; + if ((pBAEntry->REC_BA_Status == Recipient_NONE)) + { + // get one + pAd->BATable.numAsRecipient++; + pBAEntry->REC_BA_Status = Recipient_USED; + *Idx = i; + break; + } + } + +done: + NdisReleaseSpinLock(&pAd->BATabLock); + return pBAEntry; +} + +BA_ORI_ENTRY *BATableAllocOriEntry( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Idx) +{ + int i; + BA_ORI_ENTRY *pBAEntry = NULL; + + NdisAcquireSpinLock(&pAd->BATabLock); + + if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) + { + goto done; + } + + // reserve idx 0 to identify BAWcidArray[TID] as empty + for (i=1; iBATable.BAOriEntry[i]; + if ((pBAEntry->ORI_BA_Status == Originator_NONE)) + { + // get one + pAd->BATable.numAsOriginator++; + pBAEntry->ORI_BA_Status = Originator_USED; + pBAEntry->pAdapter = pAd; + *Idx = i; + break; + } + } + +done: + NdisReleaseSpinLock(&pAd->BATabLock); + return pBAEntry; +} + + +VOID BATableFreeOriEntry( + IN PRTMP_ADAPTER pAd, + IN ULONG Idx) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + MAC_TABLE_ENTRY *pEntry; + + + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) + return; + + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + + if (pBAEntry->ORI_BA_Status != Originator_NONE) + { + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + pEntry->BAOriWcidArray[pBAEntry->TID] = 0; + + + NdisAcquireSpinLock(&pAd->BATabLock); + if (pBAEntry->ORI_BA_Status == Originator_Done) + { + pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) )); + DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); + // Erase Bitmap flag. + } + + ASSERT(pAd->BATable.numAsOriginator != 0); + + pAd->BATable.numAsOriginator -= 1; + + pBAEntry->ORI_BA_Status = Originator_NONE; + pBAEntry->Token = 0; + NdisReleaseSpinLock(&pAd->BATabLock); + } +} + + +VOID BATableFreeRecEntry( + IN PRTMP_ADAPTER pAd, + IN ULONG Idx) +{ + BA_REC_ENTRY *pBAEntry = NULL; + MAC_TABLE_ENTRY *pEntry; + + + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE)) + return; + + pBAEntry =&pAd->BATable.BARecEntry[Idx]; + + if (pBAEntry->REC_BA_Status != Recipient_NONE) + { + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + pEntry->BARecWcidArray[pBAEntry->TID] = 0; + + NdisAcquireSpinLock(&pAd->BATabLock); + + ASSERT(pAd->BATable.numAsRecipient != 0); + + pAd->BATable.numAsRecipient -= 1; + + pBAEntry->REC_BA_Status = Recipient_NONE; + NdisReleaseSpinLock(&pAd->BATabLock); + } +} + + +VOID BAOriSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend) +{ + ULONG Idx = 0; + BA_ORI_ENTRY *pBAEntry; + BOOLEAN Cancelled; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + { + return; + } + + // + // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). + // + Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID]; + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) + { + if (bForceSend == TRUE) + { + // force send specified TID DelBA + MLME_DELBA_REQ_STRUCT DelbaReq; + MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = ORIGINATOR; +#if 1 + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + kfree(Elem); +#else + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq); + RT28XX_MLME_HANDLER(pAd); +#endif + } + + return; + } + + DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); + + pBAEntry = &pAd->BATable.BAOriEntry[Idx]; + DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status)); + // + // Prepare DelBA action frame and send to the peer. + // + if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done)) + { + MLME_DELBA_REQ_STRUCT DelbaReq; + MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = pBAEntry->TID; + DelbaReq.Initiator = ORIGINATOR; +#if 1 + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + kfree(Elem); +#else + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq); + RT28XX_MLME_HANDLER(pAd); +#endif + } + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); + BATableFreeOriEntry(pAd, Idx); + + if (bPassive) + { + //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); + } +} + +VOID BARecSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive) +{ + ULONG Idx = 0; + BA_REC_ENTRY *pBAEntry; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + { + return; + } + + // + // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). + // + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + if (Idx == 0) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); + + + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status)); + // + // Prepare DelBA action frame and send to the peer. + // + if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept)) + { + MLME_DELBA_REQ_STRUCT DelbaReq; + BOOLEAN Cancelled; + MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + //ULONG offset; + //UINT32 VALUE; + + RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); + + // + // 1. Send DELBA Action Frame + // + if (bPassive == FALSE) + { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = RECIPIENT; +#if 1 + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + kfree(Elem); +#else + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq); + RT28XX_MLME_HANDLER(pAd); +#endif + } + + + // + // 2. Free resource of BA session + // + // flush all pending reordering mpdus + ba_refresh_reordering_mpdus(pAd, pBAEntry); + + NdisAcquireSpinLock(&pAd->BATabLock); + + // Erase Bitmap flag. + pBAEntry->LastIndSeq = RESET_RCV_SEQ; + pBAEntry->BAWinSize = 0; + // Erase Bitmap flag at software mactable + pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID))); + pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0; + + RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID); + + NdisReleaseSpinLock(&pAd->BATabLock); + + } + + BATableFreeRecEntry(pAd, Idx); +} + +VOID BASessionTearDownALL( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid) +{ + int i; + + for (i=0; ipAdapter; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Do nothing if monitor mode is on + if (MONITOR_ON(pAd)) + return; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef RALINK_ATE + // Nothing to do in ATE mode. + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + + if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) + { + MLME_ADDBA_REQ_STRUCT AddbaReq; + + NdisZeroMemory(&AddbaReq, sizeof(AddbaReq)); + COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr); + AddbaReq.Wcid = (UCHAR)(pEntry->Aid); + AddbaReq.TID = pBAEntry->TID; + AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + AddbaReq.TimeOutValue = 0; + AddbaReq.Token = pBAEntry->Token; + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq); + RT28XX_MLME_HANDLER(pAd); + //DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token)); + + DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) to %02x:%02x:%02x:%02x:%02x:%02x Tid:%d Wcid:%d\n" + ,pBAEntry->Token + ,pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2] + ,pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5] + ,pBAEntry->TID,pEntry->Aid)); + + pBAEntry->Token++; + RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); + } + else + { + BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]); + } +} + +/* + ========================================================================== + Description: + Retry sending ADDBA Reqest. + + IRQL = DISPATCH_LEVEL + + Parametrs: + p8023Header: if this is already 802.3 format, p8023Header is NULL + + Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. + FALSE , then continue indicaterx at this moment. + ========================================================================== + */ +VOID BARecSessionIdleTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + + BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + ULONG Now32; + + if (pBAEntry == NULL) + return; + + if ((pBAEntry->REC_BA_Status == Recipient_Accept)) + { + NdisGetSystemUpTime(&Now32); + + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT))) + { + pAd = pBAEntry->pAdapter; + // flush all pending reordering mpdus + ba_refresh_reordering_mpdus(pAd, pBAEntry); + printk("%ld: REC BA session Timeout\n", Now32); + } + } +} + + +VOID PeerAddBAReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + // 7.4.4.1 + //ULONG Idx; + UCHAR Status = 1; + UCHAR pAddr[6]; + FRAME_ADDBA_RSP ADDframe; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PFRAME_ADDBA_REQ pAddreqFrame = NULL; + //UCHAR BufSize; + ULONG FrameLen; + PULONG ptemp; + PMAC_TABLE_ENTRY pMacEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid)); + + //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); + + //ADDBA Request from unknown peer, ignore this. + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n")); + ptemp = (PULONG)Elem->Msg; + //DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8))); + + if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) + { + + if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry)) + { + pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); + printk("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid); + if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame)) + Status = 0; + else + Status = 38; // more parameters have invalid values + } + else + { + Status = 37; // the request has been declined. + } + } + + if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI) + ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC); + + pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); + // 2. Always send back ADDBA Response + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n")); + return; + } + + NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP)); + // 2-1. Prepare ADDBA Response frame. +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ADHOC_ON(pAd)) + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + else + ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); + } +#endif // CONFIG_STA_SUPPORT // + ADDframe.Category = CATEGORY_BA; + ADDframe.Action = ADDBA_RESP; + ADDframe.Token = pAddreqFrame->Token; + // What is the Status code?? need to check. + ADDframe.StatusCode = Status; + ADDframe.BaParm.BAPolicy = IMMED_BA; + ADDframe.BaParm.AMSDUSupported = 0; + ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; + ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + if (ADDframe.BaParm.BufSize == 0) + { + ADDframe.BaParm.BufSize = 64; + } + ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue; + + *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm)); + ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); + ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ADDBA_RSP), &ADDframe, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID, + ADDframe.BaParm.BufSize)); +} + + +VOID PeerAddBARspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + //UCHAR Idx, i; + //PUCHAR pOutBuffer = NULL; + PFRAME_ADDBA_RSP pFrame = NULL; + //PBA_ORI_ENTRY pBAEntry; + + //ADDBA Response from unknown peer, ignore this. + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid)); + + //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); + + if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) + { + pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]); + + DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode)); + switch (pFrame->StatusCode) + { + case 0: + // I want a BAsession with this peer as an originator. + BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame); + break; + default: + // check status == USED ??? + BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE); + break; + } + // Rcv Decline StatusCode + if ((pFrame->StatusCode == 37) +#ifdef CONFIG_STA_SUPPORT + || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0)) +#endif // CONFIG_STA_SUPPORT // + ) + { + pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<BaParm.TID; + } + } +} + +VOID PeerDelBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + //UCHAR Idx; + //PUCHAR pOutBuffer = NULL; + PFRAME_DELBA_REQ pDelFrame = NULL; + + DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__)); + //DELBA Request from unknown peer, ignore this. + if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) + { + pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]); + if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n")); + BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode)); + //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); + BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE); + } + } +} + + +BOOLEAN CntlEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg) +{ + PFRAME_BA_REQ pFrame = pMsg; + //PRTMP_REORDERBUF pBuffer; + //PRTMP_REORDERBUF pDmaBuf; + PBA_REC_ENTRY pBAEntry; + //BOOLEAN Result; + ULONG Idx; + //UCHAR NumRxPkt; + UCHAR TID;//, i; + + TID = (UCHAR)pFrame->BARControl.TID; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID)); + //hex_dump("BAR", (PCHAR) pFrame, MsgLen); + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + // First check the size, it MUST not exceed the mlme queue size + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); + return FALSE; + } + else if (MsgLen != sizeof(FRAME_BA_REQ)) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + else if (MsgLen != sizeof(FRAME_BA_REQ)) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + + if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) + { + // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + } + else + { + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq )); + + if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ)) + { + //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq); + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq); + pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1); + } + //ba_refresh_reordering_mpdus(pAd, pBAEntry); + return TRUE; +} + +/* +Description : Send PSMP Action frame If PSMP mode switches. +*/ +VOID SendPSMPAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR Psmp) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + //ULONG Idx; + FRAME_PSMP_ACTION Frame; + ULONG FrameLen; +#ifdef RT30xx + UCHAR bbpdata=0; + UINT32 macdata; +#endif // RT30xx // + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr); +#endif // CONFIG_STA_SUPPORT // + + Frame.Category = CATEGORY_HT; + Frame.Action = SMPS_ACTION; + switch (Psmp) + { + case MMPS_ENABLE: +#ifdef RT30xx + if (IS_RT3090(pAd)) + { + // disable MMPS BBP control register + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata); + bbpdata &= ~(0x04); //bit 2 + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata); + + // disable MMPS MAC control register + RTMP_IO_READ32(pAd, 0x1210, &macdata); + macdata &= ~(0x09); //bit 0, 3 + RTMP_IO_WRITE32(pAd, 0x1210, macdata); + } +#endif // RT30xx // + Frame.Psmp = 0; + break; + case MMPS_DYNAMIC: +#ifdef RT30xx + if (IS_RT3090(pAd)) + { + // enable MMPS BBP control register + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata); + bbpdata |= 0x04; //bit 2 + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata); + + // enable MMPS MAC control register + RTMP_IO_READ32(pAd, 0x1210, &macdata); + macdata |= 0x09; //bit 0, 3 + RTMP_IO_WRITE32(pAd, 0x1210, macdata); + } +#endif // RT30xx // + Frame.Psmp = 3; + break; + case MMPS_STATIC: +#ifdef RT30xx + if (IS_RT3090(pAd)) + { + // enable MMPS BBP control register + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata); + bbpdata |= 0x04; //bit 2 + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata); + + // enable MMPS MAC control register + RTMP_IO_READ32(pAd, 0x1210, &macdata); + macdata |= 0x09; //bit 0, 3 + RTMP_IO_WRITE32(pAd, 0x1210, macdata); + } +#endif // RT30xx // + Frame.Psmp = 1; + break; + } + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_PSMP_ACTION), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp)); +} + + +#define RADIO_MEASUREMENT_REQUEST_ACTION 0 + +typedef struct PACKED +{ + UCHAR RegulatoryClass; + UCHAR ChannelNumber; + USHORT RandomInterval; + USHORT MeasurementDuration; + UCHAR MeasurementMode; + UCHAR BSSID[MAC_ADDR_LEN]; + UCHAR ReportingCondition; + UCHAR Threshold; + UCHAR SSIDIE[2]; // 2 byte +} BEACON_REQUEST; + +typedef struct PACKED +{ + UCHAR ID; + UCHAR Length; + UCHAR Token; + UCHAR RequestMode; + UCHAR Type; +} MEASUREMENT_REQ; + + + + +void convert_reordering_packet_to_preAMSDU_or_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + PNDIS_PACKET pRxPkt; + UCHAR Header802_3[LENGTH_802_3]; + + // 1. get 802.3 Header + // 2. remove LLC + // a. pointer pRxBlk->pData to payload + // b. modify pRxBlk->DataSize + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif // CONFIG_STA_SUPPORT // + + ASSERT(pRxBlk->pRxPacket); + pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + + RTPKT_TO_OSPKT(pRxPkt)->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + RTPKT_TO_OSPKT(pRxPkt)->data = pRxBlk->pData; + RTPKT_TO_OSPKT(pRxPkt)->len = pRxBlk->DataSize; + RTPKT_TO_OSPKT(pRxPkt)->tail = RTPKT_TO_OSPKT(pRxPkt)->data + RTPKT_TO_OSPKT(pRxPkt)->len; + + // + // copy 802.3 header, if necessary + // + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef LINUX + NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3); +#endif +#ifdef UCOS + NdisMoveMemory(net_pkt_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3); +#endif + } +#endif // CONFIG_STA_SUPPORT // + } +} + + +#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \ + do \ + { \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ + { \ + Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \ + { \ + Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + else \ + { \ + Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ + } \ + } while (0); + + + +static VOID ba_enqueue_reordering_packet( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + struct reordering_mpdu *mpdu_blk; + UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence; + + mpdu_blk = ba_mpdu_blk_alloc(pAd); + if (mpdu_blk != NULL) + { + // Write RxD buffer address & allocated buffer length + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + mpdu_blk->Sequence = Sequence; + + mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); + + convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID); + + STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); + + // + // it is necessary for reordering packet to record + // which BSS it come from + // + RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); + + mpdu_blk->pPacket = pRxBlk->pRxPacket; + + if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE) + { + // had been already within reordering list + // don't indicate + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS); + ba_mpdu_blk_free(pAd, mpdu_blk); + } + + ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n", + pBAEntry->list.qlen)); + /* + * flush all pending reordering mpdus + * and receving mpdu to upper layer + * make tcp/ip to take care reordering mechanism + */ + //ba_refresh_reordering_mpdus(pAd, pBAEntry); + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); + + pBAEntry->LastIndSeq = Sequence; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + } +} + + +/* + ========================================================================== + Description: + Indicate this packet to upper layer or put it into reordering buffer + + Parametrs: + pRxBlk : carry necessary packet info 802.11 format + FromWhichBSSID : the packet received from which BSS + + Return : + none + + Note : + the packet queued into reordering buffer need to cover to 802.3 format + or pre_AMSDU format + ========================================================================== + */ + +VOID Indicate_AMPDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + USHORT Idx; + PBA_REC_ENTRY pBAEntry = NULL; + UINT16 Sequence = pRxBlk->pHeader->Sequence; + ULONG Now32; + UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; + UCHAR TID = pRxBlk->pRxWI->TID; + + + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + { + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + if (Idx == 0) + { + /* Rec BA Session had been torn down */ + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + return; + } + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + } + else + { + // impossible !!! + ASSERT(0); + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + ASSERT(pBAEntry); + + // update last rx time + NdisGetSystemUpTime(&Now32); + + pBAEntry->rcvSeq = Sequence; + + + ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); + pBAEntry->LastIndSeqAtTimer = Now32; + + // + // Reset Last Indicate Sequence + // + if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) + { + ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL)); + + // reset rcv sequence of BA session + pBAEntry->LastIndSeq = Sequence; + pBAEntry->LastIndSeqAtTimer = Now32; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + return; + } + + + // + // I. Check if in order. + // + if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { + USHORT LastIndSeq; + + pBAEntry->LastIndSeq = Sequence; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); + LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + if (LastIndSeq != RESET_RCV_SEQ) + { + pBAEntry->LastIndSeq = LastIndSeq; + } + pBAEntry->LastIndSeqAtTimer = Now32; + } + // + // II. Drop Duplicated Packet + // + else if (Sequence == pBAEntry->LastIndSeq) + { + + // drop and release packet + pBAEntry->nDropPacket++; + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } + // + // III. Drop Old Received Packet + // + else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { + + // drop and release packet + pBAEntry->nDropPacket++; + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } + // + // IV. Receive Sequence within Window Size + // + else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ)) + { + ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); + } + // + // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer + // + else + { + LONG WinStartSeq, TmpSeq; + + + TmpSeq = Sequence - (pBAEntry->BAWinSize) -1; + if (TmpSeq < 0) + { + TmpSeq = (MAXSEQ+1) + TmpSeq; + } + WinStartSeq = (TmpSeq+1) & MAXSEQ; + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); + pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq; + + pBAEntry->LastIndSeqAtTimer = Now32; + + ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); + + TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + if (TmpSeq != RESET_RCV_SEQ) + { + pBAEntry->LastIndSeq = TmpSeq; + } + } +} + +#endif // DOT11_N_SUPPORT // + diff --git a/drivers/staging/rt3070/common/cmm_data.c b/drivers/staging/rt3070/common/cmm_data.c new file mode 100644 index 000000000000..85f92b9f83da --- /dev/null +++ b/drivers/staging/rt3070/common/cmm_data.c @@ -0,0 +1,2827 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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 "../rt_config.h" + +#define MAX_TX_IN_TBTT (16) + + +UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; +UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8}; +// Add Cisco Aironet SNAP heade for CCX2 support +UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00}; +UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02}; +UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e}; +UCHAR EAPOL[] = {0x88, 0x8e}; +UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */ + +UCHAR IPX[] = {0x81, 0x37}; +UCHAR APPLE_TALK[] = {0x80, 0xf3}; +UCHAR RateIdToPlcpSignal[12] = { + 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec + 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14 + 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14 + +UCHAR OfdmSignalToRateId[16] = { + RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively + RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively + RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively + RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively +}; + +UCHAR OfdmRateToRxwiMCS[12] = { + 0, 0, 0, 0, + 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 + 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 +}; +UCHAR RxwiMCSToOfdmRate[12] = { + RATE_6, RATE_9, RATE_12, RATE_18, + RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 + 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 +}; + +char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"}; + +UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2}; +//UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; +UCHAR default_sta_aifsn[]={3,7,2,2}; + +UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO}; + + +/* + ======================================================================== + + Routine Description: + API for MLME to transmit management frame to AP (BSS Mode) + or station (IBSS Mode) + + Arguments: + pAd Pointer to our adapter + pData Pointer to the outgoing 802.11 frame + Length Size of outgoing management frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS MiniportMMRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PUCHAR pData, + IN UINT Length) +{ + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG FreeNum; + UCHAR IrqState; + UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; + + ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); + + QueIdx=3; + + // 2860C use Tx Ring + + IrqState = pAd->irq_disabled; + + do + { + // Reset is in progress, stop immediately + if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + Status = NDIS_STATUS_FAILURE; + break; + } + + // Check Free priority queue + // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. + + // 2860C use Tx Ring + if (pAd->MACVersion == 0x28600100) + { + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + } + else + { + FreeNum = GET_MGMTRING_FREENO(pAd); + } + + if ((FreeNum > 0)) + { + // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 + NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); + Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); + break; + } + + //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + //pAd->CommonCfg.MlmeRate = RATE_2; + + + Status = MlmeHardTransmit(pAd, QueIdx, pPacket); + if (Status != NDIS_STATUS_SUCCESS) + RTMPFreeNdisPacket(pAd, pPacket); + } + else + { + pAd->RalinkCounters.MgmtRingFullCount++; + DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n", + QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); + } + + } while (FALSE); + + + return Status; +} + + + +NDIS_STATUS MlmeDataHardTransmit( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +#define MAX_DATAMM_RETRY 3 +/* + ======================================================================== + + Routine Description: + API for MLME to transmit management frame to AP (BSS Mode) + or station (IBSS Mode) + + Arguments: + pAd Pointer to our adapter + pData Pointer to the outgoing 802.11 frame + Length Size of outgoing management frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS MiniportDataMMRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PUCHAR pData, + IN UINT Length) +{ + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG FreeNum; + int retry = 0; + UCHAR IrqState; + UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN]; + + ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); + + // 2860C use Tx Ring + IrqState = pAd->irq_disabled; + + do + { + // Reset is in progress, stop immediately + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)|| + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + Status = NDIS_STATUS_FAILURE; + break; + } + + // Check Free priority queue + // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. + + // 2860C use Tx Ring + + // free Tx(QueIdx) resources + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + + if ((FreeNum > 0)) + { + // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 + NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE)); + Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); + break; + } + + //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + //pAd->CommonCfg.MlmeRate = RATE_2; + + + Status = MlmeDataHardTransmit(pAd, QueIdx, pPacket); + if (Status != NDIS_STATUS_SUCCESS) + RTMPFreeNdisPacket(pAd, pPacket); + retry = MAX_DATAMM_RETRY; + } + else + { + retry ++; + + printk("retry %d\n", retry); + pAd->RalinkCounters.MgmtRingFullCount++; + + if (retry >= MAX_DATAMM_RETRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n", + QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); + } + } + + } while (retry < MAX_DATAMM_RETRY); + + + return Status; +} + + + + + + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware transmit function + + Arguments: + pAd Pointer to our adapter + pBuffer Pointer to memory of outgoing frame + Length Size of outgoing management frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS MlmeHardTransmit( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) +#ifdef CARRIER_DETECTION_SUPPORT +#endif // CARRIER_DETECTION_SUPPORT // + ) + { + return NDIS_STATUS_FAILURE; + } + + return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); + +} + +NDIS_STATUS MlmeDataHardTransmit( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) +#ifdef CARRIER_DETECTION_SUPPORT +#endif // CARRIER_DETECTION_SUPPORT // + ) + { + return NDIS_STATUS_FAILURE; + } + +#ifdef RT2870 + return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); +#endif // RT2870 // +} + + + + + +NDIS_STATUS MlmeHardTransmitMgmtRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + PHEADER_802_11 pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; + UCHAR MlmeRate; + PTXWI_STRUC pFirstTxWI; + MAC_TABLE_ENTRY *pMacEntry = NULL; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + // Make sure MGMT ring resource won't be used by other threads +// sample, for IRQ LOCK -> SEM LOCK +// IrqState = pAd->irq_disabled; +// if (!IrqState) + RTMP_SEM_LOCK(&pAd->MgmtRingLock); + + + if (pSrcBufVA == NULL) + { + // The buffer shouldn't be NULL +// if (!IrqState) + RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); + return NDIS_STATUS_FAILURE; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // outgoing frame always wakeup PHY to prevent frame lost + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + } +#endif // CONFIG_STA_SUPPORT // + + pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE); + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE); + + if (pHeader_802_11->Addr1[0] & 0x01) + { + MlmeRate = pAd->CommonCfg.BasicMlmeRate; + } + else + { + MlmeRate = pAd->CommonCfg.MlmeRate; + } + + // Verify Mlme rate for a / g bands. + if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band + MlmeRate = RATE_6; + + if ((pHeader_802_11->FC.Type == BTYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) + { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. + if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED +#ifdef DOT11_N_SUPPORT + || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED +#endif // DOT11_N_SUPPORT // + ) + { + if (pAd->LatchRfRegs.Channel > 14) + pAd->CommonCfg.MlmeTransmit.field.MODE = 1; + else + pAd->CommonCfg.MlmeTransmit.field.MODE = 0; + } + } +#endif // CONFIG_STA_SUPPORT // + + // + // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) + // Snice it's been set to 0 while on MgtMacHeaderInit + // By the way this will cause frame to be send on PWR_SAVE failed. + // + // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE); + // + // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame +#ifdef CONFIG_STA_SUPPORT + // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD + if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) + { + if ((pAd->StaCfg.Psm == PWR_SAVE) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + else + pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; + } +#endif // CONFIG_STA_SUPPORT // + + bInsertTimestamp = FALSE; + if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL + { +#ifdef CONFIG_STA_SUPPORT + //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. + if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) + { + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + } +#endif // CONFIG_STA_SUPPORT // + bAckRequired = FALSE; + } + else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame) + { + //pAd->Sequence++; + //pHeader_802_11->Sequence = pAd->Sequence; + + if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } + else + { + bAckRequired = TRUE; + pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); + if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) + { + bInsertTimestamp = TRUE; + } + } + } + + pHeader_802_11->Sequence = pAd->Sequence++; + if (pAd->Sequence >0xfff) + pAd->Sequence = 0; + + // Before radar detection done, mgmt frame can not be sent but probe req + // Because we need to use probe req to trigger driver to send probe req in passive scan + if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) + { + DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); +// if (!IrqState) + RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); + return (NDIS_STATUS_FAILURE); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); +#endif + + // + // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET + // should always has only one ohysical buffer, and the whole frame size equals + // to the first scatter buffer size + // + + // Initialize TX Descriptor + // For inter-frame gap, the number is for this frame and next frame + // For MLME rate, we will fix as 2Mb to match other vendor's implement +// pAd->CommonCfg.MlmeTransmit.field.MODE = 1; + +// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. + if (pMacEntry == NULL) + { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + } + else + { + RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, + bInsertTimestamp, FALSE, bAckRequired, FALSE, + 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), + pMacEntry->MaxHTPhyMode.field.MCS, 0, + (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS, + IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode); + } + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI); +#endif + + // Now do hardware-depened kick out. + HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen); + + // Make sure to release MGMT ring resource +// if (!IrqState) + RTMP_SEM_UNLOCK(&pAd->MgmtRingLock); + return NDIS_STATUS_SUCCESS; +} + + +/******************************************************************************** + + New DeQueue Procedures. + + ********************************************************************************/ + +#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \ + do{ \ + if (bIntContext == FALSE) \ + RTMP_IRQ_LOCK((lock), IrqFlags); \ + }while(0) + +#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \ + do{ \ + if (bIntContext == FALSE) \ + RTMP_IRQ_UNLOCK((lock), IrqFlags); \ + }while(0) + + +/* + ======================================================================== + Tx Path design algorithm: + Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal), + Specific Packet Type. Following show the classification rule and policy for each kinds of packets. + Classification Rule=> + Multicast: (*addr1 & 0x01) == 0x01 + Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc. + 11N Rate : If peer support HT + (1).AMPDU -- If TXBA is negotiated. + (2).AMSDU -- If AMSDU is capable for both peer and ourself. + *). AMSDU can embedded in a AMPDU, but now we didn't support it. + (3).Normal -- Other packets which send as 11n rate. + + B/G Rate : If peer is b/g only. + (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6 + (2).Normal -- Other packets which send as b/g rate. + Fragment: + The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment. + + Classified Packet Handle Rule=> + Multicast: + No ACK, //pTxBlk->bAckRequired = FALSE; + No WMM, //pTxBlk->bWMM = FALSE; + No piggyback, //pTxBlk->bPiggyBack = FALSE; + Force LowRate, //pTxBlk->bForceLowRate = TRUE; + Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use + the same policy to handle it. + Force LowRate, //pTxBlk->bForceLowRate = TRUE; + + 11N Rate : + No piggyback, //pTxBlk->bPiggyBack = FALSE; + + (1).AMSDU + pTxBlk->bWMM = TRUE; + (2).AMPDU + pTxBlk->bWMM = TRUE; + (3).Normal + + B/G Rate : + (1).ARALINK + + (2).Normal + ======================================================================== +*/ +static UCHAR TxPktClassification( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket) +{ + UCHAR TxFrameType = TX_UNKOWN_FRAME; + UCHAR Wcid; + MAC_TABLE_ENTRY *pMacEntry = NULL; +#ifdef DOT11_N_SUPPORT + BOOLEAN bHTRate = FALSE; +#endif // DOT11_N_SUPPORT // + + Wcid = RTMP_GET_PACKET_WCID(pPacket); + if (Wcid == MCAST_WCID) + { // Handle for RA is Broadcast/Multicast Address. + return TX_MCAST_FRAME; + } + + // Handle for unicast packets + pMacEntry = &pAd->MacTab.Content[Wcid]; + if (RTMP_GET_PACKET_LOWRATE(pPacket)) + { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame + TxFrameType = TX_LEGACY_FRAME; + } +#ifdef DOT11_N_SUPPORT + else if (IS_HT_RATE(pMacEntry)) + { // it's a 11n capable packet + + // Depends on HTPhyMode to check if the peer support the HTRate transmission. + // Currently didn't support A-MSDU embedded in A-MPDU + bHTRate = TRUE; + if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE)) + TxFrameType = TX_LEGACY_FRAME; +#ifdef UAPSD_AP_SUPPORT + else if (RTMP_GET_PACKET_EOSP(pPacket)) + TxFrameType = TX_LEGACY_FRAME; +#endif // UAPSD_AP_SUPPORT // + else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0) + return TX_AMPDU_FRAME; + else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)) + return TX_AMSDU_FRAME; + else + TxFrameType = TX_LEGACY_FRAME; + } +#endif // DOT11_N_SUPPORT // + else + { // it's a legacy b/g packet. + if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && + (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && + (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) + { // if peer support Ralink Aggregation, we use it. + TxFrameType = TX_RALINK_FRAME; + } + else + { + TxFrameType = TX_LEGACY_FRAME; + } + } + + // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. + if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME)) + TxFrameType = TX_FRAG_FRAME; + + return TxFrameType; +} + + +BOOLEAN RTMP_FillTxBlkInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PACKET_INFO PacketInfo; + PNDIS_PACKET pPacket; + PMAC_TABLE_ENTRY pMacEntry = NULL; + + pPacket = pTxBlk->pPacket; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + + pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); + pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket); + pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); + pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap + + if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame); + else + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame); + + // Default to clear this flag + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS); + + + if (pTxBlk->Wcid == MCAST_WCID) + { + pTxBlk->pMacEntry = NULL; + { +#ifdef MCAST_RATE_SPECIFIC + PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket); + if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff)) + pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode; + else +#endif // MCAST_RATE_SPECIFIC // + pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; + } + + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode. + //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag); + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); + if (RTMP_GET_PACKET_MOREDATA(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); + } + + } + else + { + pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; + pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode; + + pMacEntry = pTxBlk->pMacEntry; + + + // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. + if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK) + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); + else + TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired); + + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + + // If support WMM, enable it. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && + CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); + +// if (pAd->StaCfg.bAutoTxRateSwitch) +// TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); + } +#endif // CONFIG_STA_SUPPORT // + } + + if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) + { + if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) || + ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) + { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. + pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; +#ifdef DOT11_N_SUPPORT + // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? + if (IS_HT_STA(pTxBlk->pMacEntry) && + (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) && + ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))) + { + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM); + TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS); + } +#endif // DOT11_N_SUPPORT // + } + +#ifdef DOT11_N_SUPPORT + if ( (IS_HT_RATE(pMacEntry) == FALSE) && + (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) + { // Currently piggy-back only support when peer is operate in b/g mode. + TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack); + } +#endif // DOT11_N_SUPPORT // + + if (RTMP_GET_PACKET_MOREDATA(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); + } +#ifdef UAPSD_AP_SUPPORT + if (RTMP_GET_PACKET_EOSP(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP); + } +#endif // UAPSD_AP_SUPPORT // + } + else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag); + } + + pMacEntry->DebugTxCount++; + } + + return TRUE; + +FillTxBlkErr: + return FALSE; +} + + +BOOLEAN CanDoAggregateTransmit( + IN RTMP_ADAPTER *pAd, + IN NDIS_PACKET *pPacket, + IN TX_BLK *pTxBlk) +{ + + //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType); + + if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID) + return FALSE; + + if (RTMP_GET_PACKET_DHCP(pPacket) || + RTMP_GET_PACKET_EAPOL(pPacket) || + RTMP_GET_PACKET_WAI(pPacket)) + return FALSE; + + if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && + ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100))) + { // For AMSDU, allow the packets with total length < max-amsdu size + return FALSE; + } + + if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && + (pTxBlk->TxPacketList.Number == 2)) + { // For RALINK-Aggregation, allow two frames in one batch. + return FALSE; + } + +#ifdef CONFIG_STA_SUPPORT + if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP + return TRUE; + else +#endif // CONFIG_STA_SUPPORT // + return FALSE; + +} + + +/* + ======================================================================== + + Routine Description: + To do the enqueue operation and extract the first item of waiting + list. If a number of available shared memory segments could meet + the request of extracted item, the extracted item will be fragmented + into shared memory segments. + + Arguments: + pAd Pointer to our adapter + pQueue Pointer to Waiting Queue + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPDeQueuePacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bIntContext, + IN UCHAR QIdx, /* BulkOutPipeId */ + IN UCHAR Max_Tx_Packets) +{ + PQUEUE_ENTRY pEntry = NULL; + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + UCHAR Count=0; + PQUEUE_HEADER pQueue; + ULONG FreeNumber[NUM_OF_TX_RING]; + UCHAR QueIdx, sQIdx, eQIdx; + unsigned long IrqFlags = 0; + BOOLEAN hasTxDesc = FALSE; + TX_BLK TxBlk; + TX_BLK *pTxBlk; + +#ifdef DBG_DIAGNOSE + BOOLEAN firstRound; + RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct; +#endif + + + if (QIdx == NUM_OF_TX_RING) + { + sQIdx = 0; +//PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + eQIdx = 3; // 4 ACs, start from 0. +#endif // CONFIG_STA_SUPPORT // + } + else + { + sQIdx = eQIdx = QIdx; + } + + for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++) + { + Count=0; + + RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags); + +#ifdef DBG_DIAGNOSE + firstRound = ((QueIdx == 0) ? TRUE : FALSE); +#endif // DBG_DIAGNOSE // + + while (1) + { + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST)))) + { + RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + return; + } + + if (Count >= Max_Tx_Packets) + break; + + DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags); + if (&pAd->TxSwQueue[QueIdx] == NULL) + { +#ifdef DBG_DIAGNOSE + if (firstRound == TRUE) + pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++; +#endif // DBG_DIAGNOSE // + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + + + // probe the Queue Head + pQueue = &pAd->TxSwQueue[QueIdx]; + if ((pEntry = pQueue->Head) == NULL) + { + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + + pTxBlk = &TxBlk; + NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK)); + //InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. + pTxBlk->QueIdx = QueIdx; + + pPacket = QUEUE_ENTRY_TO_PKT(pEntry); + + // Early check to make sure we have enoguh Tx Resource. + hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); + if (!hasTxDesc) + { + pAd->PrivateInfo.TxRingFullCnt++; + + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + + break; + } + + pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket); + pEntry = RemoveHeadQueue(pQueue); + pTxBlk->TotalFrameNum++; + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary + pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); + pTxBlk->pPacket = pPacket; + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + + if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME) + { + // Enhance SW Aggregation Mechanism + if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType)) + { + InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); + break; + } + + do{ + if((pEntry = pQueue->Head) == NULL) + break; + + // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. + pPacket = QUEUE_ENTRY_TO_PKT(pEntry); + FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx); + hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket); + if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE)) + break; + + //Remove the packet from the TxSwQueue and insert into pTxBlk + pEntry = RemoveHeadQueue(pQueue); + ASSERT(pEntry); + pPacket = QUEUE_ENTRY_TO_PKT(pEntry); + pTxBlk->TotalFrameNum++; + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary + pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + }while(1); + + if (pTxBlk->TxPacketList.Number == 1) + pTxBlk->TxFrameType = TX_LEGACY_FRAME; + } + +#ifdef RT2870 + DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags); +#endif // RT2870 // + + Count += pTxBlk->TxPacketList.Number; + + // Do HardTransmit now. +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + Status = STAHardTransmit(pAd, pTxBlk, QueIdx); +#endif // CONFIG_STA_SUPPORT // + } + + RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + +#ifdef RT2870 + if (!hasTxDesc) + RTUSBKickBulkOut(pAd); +#endif // RT2870 // + +#ifdef BLOCK_NET_IF + if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE) + && (pAd->TxSwQueue[QueIdx].Number < 1)) + { + releaseNetIf(&pAd->blockQueueTab[QueIdx]); + } +#endif // BLOCK_NET_IF // + + } + +} + + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pAd Pointer to our adapter + Rate Transmit rate + Size Frame size in units of byte + + Return Value: + Duration number in units of usec + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +USHORT RTMPCalcDuration( + IN PRTMP_ADAPTER pAd, + IN UCHAR Rate, + IN ULONG Size) +{ + ULONG Duration = 0; + + if (Rate < RATE_FIRST_OFDM_RATE) // CCK + { + if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + Duration = 96; // 72+24 preamble+plcp + else + Duration = 192; // 144+48 preamble+plcp + + Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]); + if ((Size << 4) % RateIdTo500Kbps[Rate]) + Duration ++; + } + else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates + { + Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension + Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]); + if ((11 + Size * 4) % RateIdTo500Kbps[Rate]) + Duration += 4; + } + else //mimo rate + { + Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension + } + + return (USHORT)Duration; +} + + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pTxWI Pointer to head of each MPDU to HW. + Ack Setting for Ack requirement bit + Fragment Setting for Fragment bit + RetryMode Setting for retry mode + Ifs Setting for IFS gap + Rate Setting for transmit rate + Service Setting for service + Length Frame length + TxPreamble Short or Long preamble when using CCK rates + QueIdx - 0-3, according to 802.11e/d4.4 June/2003 + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + See also : BASmartHardTransmit() !!! + + ======================================================================== +*/ +VOID RTMPWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pOutTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN CFACK, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR TID, + IN UCHAR TxRate, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit) +{ + PMAC_TABLE_ENTRY pMac = NULL; + TXWI_STRUC TxWI; + PTXWI_STRUC pTxWI; + + if (WCID < MAX_LEN_OF_MAC_TABLE) + pMac = &pAd->MacTab.Content[WCID]; + + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(&TxWI, TXWI_SIZE); + pTxWI = &TxWI; + + pTxWI->FRAG= FRAG; + + pTxWI->CFACK = CFACK; + pTxWI->TS= InsTimestamp; + pTxWI->AMPDU = AMPDU; + pTxWI->ACK = Ack; + pTxWI->txop= Txopmode; + + pTxWI->NSEQ = NSeq; + // John tune the performace with Intel Client in 20 MHz performance +#ifdef DOT11_N_SUPPORT + BASize = pAd->CommonCfg.TxBASize; + + if( BASize >7 ) + BASize =7; + pTxWI->BAWinSize = BASize; + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; +#endif // DOT11_N_SUPPORT // + + pTxWI->WirelessCliID = WCID; + pTxWI->MPDUtotalByteCount = Length; + pTxWI->PacketId = PID; + + // If CCK or OFDM, BW must be 20 + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); +#ifdef DOT11N_DRAFT3 + if (pTxWI->BW) + pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif // DOT11N_DRAFT3 // + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + pTxWI->CFACK = CfAck; + +#ifdef DOT11_N_SUPPORT + if (pMac) + { + if (pAd->CommonCfg.bMIMOPSEnable) + { + if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + // Dynamic MIMO Power Save Mode + pTxWI->MIMOps = 1; + } + else if (pMac->MmpsMode == MMPS_STATIC) + { + // Static MIMO Power Save Mode + if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) + { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + } + //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; + if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled)) + { + pTxWI->MpduDensity = 7; + } + else + { + pTxWI->MpduDensity = pMac->MpduDensity; + } + } +#endif // DOT11_N_SUPPORT // + + pTxWI->PacketId = pTxWI->MCS; + NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC)); +} + + +VOID RTMPWriteTxWI_Data( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk) +{ + HTTRANSMIT_SETTING *pTransmit; + PMAC_TABLE_ENTRY pMacEntry; +#ifdef DOT11_N_SUPPORT + UCHAR BASize; +#endif // DOT11_N_SUPPORT // + + + ASSERT(pTxWI); + + pTransmit = pTxBlk->pTransmit; + pMacEntry = pTxBlk->pMacEntry; + + + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(pTxWI, TXWI_SIZE); + + pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); + pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); + pTxWI->txop = pTxBlk->FrameGap; + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + if (pMacEntry && + (pAd->StaCfg.BssType == BSS_INFRA) && + (pMacEntry->ValidAsDls == TRUE)) + pTxWI->WirelessCliID = BSSID_WCID; + else +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + pTxWI->WirelessCliID = pTxBlk->Wcid; + + pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); + + // If CCK or OFDM, BW must be 20 + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pTxWI->BW) + pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif // DOT11N_DRAFT3 // + pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); + + // John tune the performace with Intel Client in 20 MHz performance + BASize = pAd->CommonCfg.TxBASize; + if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) + { + UCHAR RABAOriIdx = 0; //The RA's BA Originator table index. + + RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; + BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; + } + + pTxWI->TxBF = pTransmit->field.TxBF; + pTxWI->BAWinSize = BASize; + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; +#endif // DOT11_N_SUPPORT // + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + +#ifdef DOT11_N_SUPPORT + if (pMacEntry) + { + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + // Dynamic MIMO Power Save Mode + pTxWI->MIMOps = 1; + } + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + // Static MIMO Power Save Mode + if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) + { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + + if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) + { + pTxWI->MpduDensity = 7; + } + else + { + pTxWI->MpduDensity = pMacEntry->MpduDensity; + } + } +#endif // DOT11_N_SUPPORT // + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; + pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; + } +#endif // DBG_DIAGNOSE // + + // for rate adapation + pTxWI->PacketId = pTxWI->MCS; +#ifdef INF_AMAZON_SE +/*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ + if( RTMP_GET_PACKET_NOBULKOUT(pTxBlk->pPacket)) + { + if(pTxWI->PHYMODE == MODE_CCK) + { + pTxWI->PacketId = 6; + } + } +#endif // INF_AMAZON_SE // +} + + +VOID RTMPWriteTxWI_Cache( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk) +{ + PHTTRANSMIT_SETTING /*pTxHTPhyMode,*/ pTransmit; + PMAC_TABLE_ENTRY pMacEntry; + + // + // update TXWI + // + pMacEntry = pTxBlk->pMacEntry; + pTransmit = pTxBlk->pTransmit; + + //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) + //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) + //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) + if (pMacEntry->bAutoTxRateSwitch) + { + pTxWI->txop = IFS_HTTXOP; + + // If CCK or OFDM, BW must be 20 + pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + pTxWI->ShortGI = pTransmit->field.ShortGI; + pTxWI->STBC = pTransmit->field.STBC; + + pTxWI->MCS = pTransmit->field.MCS; + pTxWI->PHYMODE = pTransmit->field.MODE; + + // set PID for TxRateSwitching + pTxWI->PacketId = pTransmit->field.MCS; + } + +#ifdef DOT11_N_SUPPORT + pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE); + pTxWI->MIMOps = 0; + +#ifdef DOT11N_DRAFT3 + if (pTxWI->BW) + pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif // DOT11N_DRAFT3 // + + if (pAd->CommonCfg.bMIMOPSEnable) + { + // MIMO Power Save Mode + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + // Dynamic MIMO Power Save Mode + pTxWI->MIMOps = 1; + } + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + // Static MIMO Power Save Mode + if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7)) + { + pTxWI->MCS = 7; + pTxWI->MIMOps = 0; + } + } + } +#endif // DOT11_N_SUPPORT // + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++; + pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++; + } +#endif // DBG_DIAGNOSE // + + pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + +} + + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pTxD Pointer to transmit descriptor + Ack Setting for Ack requirement bit + Fragment Setting for Fragment bit + RetryMode Setting for retry mode + Ifs Setting for IFS gap + Rate Setting for transmit rate + Service Setting for service + Length Frame length + TxPreamble Short or Long preamble when using CCK rates + QueIdx - 0-3, according to 802.11e/d4.4 June/2003 + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPWriteTxDescriptor( + IN PRTMP_ADAPTER pAd, + IN PTXD_STRUC pTxD, + IN BOOLEAN bWIV, + IN UCHAR QueueSEL) +{ + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + + pTxD->WIV = (bWIV) ? 1: 0; + pTxD->QSEL= (QueueSEL); + if (pAd->bGenOneHCCA == TRUE) + pTxD->QSEL= FIFO_HCCA; + pTxD->DMADONE = 0; +} + + +// should be called only when - +// 1. MEADIA_CONNECTED +// 2. AGGREGATION_IN_USED +// 3. Fragmentation not in used +// 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible +BOOLEAN TxFrameIsAggregatible( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPrevAddr1, + IN PUCHAR p8023hdr) +{ + + // can't aggregate EAPOL (802.1x) frame + if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e)) + return FALSE; + + // can't aggregate multicast/broadcast frame + if (p8023hdr[0] & 0x01) + return FALSE; + + if (INFRA_ON(pAd)) // must be unicast to AP + return TRUE; + else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA + return TRUE; + else + return FALSE; +} + + +/* + ======================================================================== + + Routine Description: + Check the MSDU Aggregation policy + 1.HT aggregation is A-MSDU + 2.legaacy rate aggregation is software aggregation by Ralink. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN PeerIsAggreOn( + IN PRTMP_ADAPTER pAd, + IN ULONG TxRate, + IN PMAC_TABLE_ENTRY pMacEntry) +{ + ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE); + + if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) + { +#ifdef DOT11_N_SUPPORT + if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + { + return TRUE; + } +#endif // DOT11_N_SUPPORT // + +#ifdef AGGREGATION_SUPPORT + if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) + { // legacy Ralink Aggregation support + return TRUE; + } +#endif // AGGREGATION_SUPPORT // + } + + return FALSE; + +} + + +/* + ======================================================================== + + Routine Description: + Check and fine the packet waiting in SW queue with highest priority + + Arguments: + pAd Pointer to our adapter + + Return Value: + pQueue Pointer to Waiting Queue + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +PQUEUE_HEADER RTMPCheckTxSwQueue( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pQueIdx) +{ + + ULONG Number; + // 2004-11-15 to be removed. test aggregation only +// if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) +// return NULL; + + Number = pAd->TxSwQueue[QID_AC_BK].Number + + pAd->TxSwQueue[QID_AC_BE].Number + + pAd->TxSwQueue[QID_AC_VI].Number + + pAd->TxSwQueue[QID_AC_VO].Number + + pAd->TxSwQueue[QID_HCCA].Number; + + if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) + { + *pQueIdx = QID_AC_VO; + return (&pAd->TxSwQueue[QID_AC_VO]); + } + else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) + { + *pQueIdx = QID_AC_VI; + return (&pAd->TxSwQueue[QID_AC_VI]); + } + else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) + { + *pQueIdx = QID_AC_BE; + return (&pAd->TxSwQueue[QID_AC_BE]); + } + else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) + { + *pQueIdx = QID_AC_BK; + return (&pAd->TxSwQueue[QID_AC_BK]); + } + else if (pAd->TxSwQueue[QID_HCCA].Head != NULL) + { + *pQueIdx = QID_HCCA; + return (&pAd->TxSwQueue[QID_HCCA]); + } + + // No packet pending in Tx Sw queue + *pQueIdx = QID_AC_BK; + + return (NULL); +} + + + +/* + ======================================================================== + + Routine Description: + Suspend MSDU transmission + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPSuspendMsduTransmission( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n")); + + + // + // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and + // use Lowbound as R66 value on ScanNextChannel(...) + // + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); + + // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) + //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); + RTMPSetAGCInitValue(pAd, BW_20); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings +} + + +/* + ======================================================================== + + Routine Description: + Resume MSDU transmission + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPResumeMsduTransmission( + IN PRTMP_ADAPTER pAd) +{ +// UCHAR IrqState; + + DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n")); + + + // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value + // R66 should not be 0 + if (pAd->BbpTuning.R66CurrentValue == 0) + { + pAd->BbpTuning.R66CurrentValue = 0x38; + DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n")); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); +// sample, for IRQ LOCK to SEM LOCK +// IrqState = pAd->irq_disabled; +// if (IrqState) +// RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); +// else + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); +} + + +UINT deaggregate_AMSDU_announce( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize) +{ + USHORT PayloadSize; + USHORT SubFrameSize; + PHEADER_802_3 pAMSDUsubheader; + UINT nMSDU; + UCHAR Header802_3[14]; + + PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP; + PNDIS_PACKET pClonePacket; + + + + nMSDU = 0; + + while (DataSize > LENGTH_802_3) + { + + nMSDU++; + + //hex_dump("subheader", pData, 64); + pAMSDUsubheader = (PHEADER_802_3)pData; + //pData += LENGTH_802_3; + PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8); + SubFrameSize = PayloadSize + LENGTH_802_3; + + + if ((DataSize < SubFrameSize) || (PayloadSize > 1518 )) + { + break; + } + + //printk("%d subframe: Size = %d\n", nMSDU, PayloadSize); + + pPayload = pData + LENGTH_802_3; + pDA = pData; + pSA = pData + MAC_ADDR_LEN; + + // convert to 802.3 header + CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP); + +#ifdef CONFIG_STA_SUPPORT + if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) ) + { + // avoid local heap overflow, use dyanamic allocation + MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize); + Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize; + WpaEAPOLKeyAction(pAd, Elem); + kfree(Elem); + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pRemovedLLCSNAP) + { + pPayload -= LENGTH_802_3; + PayloadSize += LENGTH_802_3; + NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3); + } + } +#endif // CONFIG_STA_SUPPORT // + + pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize); + if (pClonePacket) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket)); +#endif // CONFIG_STA_SUPPORT // + } + + + // A-MSDU has padding to multiple of 4 including subframe header. + // align SubFrameSize up to multiple of 4 + SubFrameSize = (SubFrameSize+3)&(~0x3); + + + if (SubFrameSize > 1528 || SubFrameSize < 32) + { + break; + } + + if (DataSize > SubFrameSize) + { + pData += SubFrameSize; + DataSize -= SubFrameSize; + } + else + { + // end of A-MSDU + DataSize = 0; + } + } + + // finally release original rx packet + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + + return nMSDU; +} + + +UINT BA_Reorder_AMSDU_Annnounce( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + PUCHAR pData; + USHORT DataSize; + UINT nMSDU = 0; + + pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); + DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); + + nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); + + return nMSDU; +} + + +/* + ========================================================================== + Description: + Look up the MAC address in the MAC table. Return NULL if not found. + Return: + pEntry - pointer to the MAC entry; NULL is not found + ========================================================================== +*/ +MAC_TABLE_ENTRY *MacTableLookup( + IN PRTMP_ADAPTER pAd, + PUCHAR pAddr) +{ + ULONG HashIdx; + MAC_TABLE_ENTRY *pEntry = NULL; + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) + { + if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + break; + } + else + pEntry = pEntry->pNext; + } + + return pEntry; +} + +MAC_TABLE_ENTRY *MacTableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR apidx, + IN BOOLEAN CleanAll) +{ + UCHAR HashIdx; + int i, FirstWcid; + MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; +// USHORT offset; +// ULONG addr; + + // if FULL, return + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + FirstWcid = 1; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + if (pAd->StaCfg.BssType == BSS_INFRA) + FirstWcid = 2; +#endif // CONFIG_STA_SUPPORT // + + // allocate one MAC entry + NdisAcquireSpinLock(&pAd->MacTabLock); + for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup + { + // pick up the first available vacancy + if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) && + (pAd->MacTab.Content[i].ValidAsWDS == FALSE) && + (pAd->MacTab.Content[i].ValidAsApCli== FALSE) && + (pAd->MacTab.Content[i].ValidAsMesh == FALSE) +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + && (pAd->MacTab.Content[i].ValidAsDls == FALSE) +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + ) + { + pEntry = &pAd->MacTab.Content[i]; + if (CleanAll == TRUE) + { + pEntry->MaxSupportedRate = RATE_11; + pEntry->CurrTxRate = RATE_11; + NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + pEntry->PairwiseKey.KeyLen = 0; + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; + } +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_DLS) + { + pEntry->ValidAsCLI = FALSE; + pEntry->ValidAsWDS = FALSE; + pEntry->ValidAsApCli = FALSE; + pEntry->ValidAsMesh = FALSE; + pEntry->ValidAsDls = TRUE; + pEntry->isCached = FALSE; + } + else +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEntry->ValidAsCLI = TRUE; + pEntry->ValidAsWDS = FALSE; + pEntry->ValidAsApCli = FALSE; + pEntry->ValidAsMesh = FALSE; + pEntry->ValidAsDls = FALSE; + } +#endif // CONFIG_STA_SUPPORT // + } + + pEntry->bIAmBadAtheros = FALSE; + pEntry->pAd = pAd; + pEntry->CMTimerRunning = FALSE; + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + pEntry->RSNIE_Len = 0; + NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + + if (pEntry->ValidAsMesh) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH); + else if (pEntry->ValidAsApCli) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI); + else if (pEntry->ValidAsWDS) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS); +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + else if (pEntry->ValidAsDls) + pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + else + pEntry->apidx = apidx; + + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEntry->AuthMode = pAd->StaCfg.AuthMode; + pEntry->WepStatus = pAd->StaCfg.WepStatus; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } +#endif // CONFIG_STA_SUPPORT // + } + + pEntry->GTKState = REKEY_NEGOTIATING; + pEntry->PairwiseKey.KeyLen = 0; + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + if (pEntry->ValidAsDls == TRUE) + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + else +#endif //QOS_DLS_SUPPORT +#endif // CONFIG_STA_SUPPORT // + pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; + COPY_MAC_ADDR(pEntry->Addr, pAddr); + pEntry->Sst = SST_NOT_AUTH; + pEntry->AuthState = AS_NOT_AUTH; + pEntry->Aid = (USHORT)i; //0; + pEntry->CapabilityInfo = 0; + pEntry->PsMode = PWR_ACTIVE; + pEntry->PsQIdleCount = 0; + pEntry->NoDataIdleCount = 0; + pEntry->ContinueTxFailCnt = 0; + InitializeQueueHeader(&pEntry->PsQueue); + + + pAd->MacTab.Size ++; + + // Add this entry into ASIC RX WCID search table + RT28XX_STA_ENTRY_ADD(pAd, pEntry); + + + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size)); + break; + } + } + + // add this MAC entry into HASH table + if (pEntry) + { + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + if (pAd->MacTab.Hash[HashIdx] == NULL) + { + pAd->MacTab.Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pAd->MacTab.Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + return pEntry; +} + +/* + ========================================================================== + Description: + Delete a specified client from MAC table + ========================================================================== + */ +BOOLEAN MacTableDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr) +{ + USHORT HashIdx; + MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; + BOOLEAN Cancelled; + //USHORT offset; // unused variable + //UCHAR j; // unused variable + + if (wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + NdisAcquireSpinLock(&pAd->MacTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + //pEntry = pAd->MacTab.Hash[HashIdx]; + pEntry = &pAd->MacTab.Content[wcid]; + + if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + || pEntry->ValidAsDls +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + )) + { + if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + + // Delete this entry from ASIC on-chip WCID Table + RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid); + +#ifdef DOT11_N_SUPPORT + // free resources of BA + BASessionTearDownALL(pAd, pEntry->Aid); +#endif // DOT11_N_SUPPORT // + + + pPrevEntry = NULL; + pProbeEntry = pAd->MacTab.Hash[HashIdx]; + ASSERT(pProbeEntry); + + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pAd->MacTab.Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + // not found !!! + ASSERT(pProbeEntry != NULL); + + RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid); + + + if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) + { + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + } + + + NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); + pAd->MacTab.Size --; + DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size)); + } + else + { + printk("\n%s: Impossible Wcid = %d !!!!!\n", __FUNCTION__, wcid); + } + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + + //Reset operating mode when no Sta. + if (pAd->MacTab.Size == 0) + { +#ifdef DOT11_N_SUPPORT + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; +#endif // DOT11_N_SUPPORT // + //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/); + RT28XX_UPDATE_PROTECT(pAd); // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet + } + + return TRUE; +} + + +/* + ========================================================================== + Description: + This routine reset the entire MAC table. All packets pending in + the power-saving queues are freed here. + ========================================================================== + */ +VOID MacTableReset( + IN PRTMP_ADAPTER pAd) +{ + int i; + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n")); + //NdisAcquireSpinLock(&pAd->MacTabLock); + + for (i=1; iMacTab.Content[i].ValidAsCLI == TRUE) + { + +#ifdef DOT11_N_SUPPORT + // free resources of BA + BASessionTearDownALL(pAd, i); +#endif // DOT11_N_SUPPORT // + + pAd->MacTab.Content[i].ValidAsCLI = FALSE; + + + +#ifdef RT2870 + NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6); + RT28XX_STA_ENTRY_MAC_RESET(pAd, i); +#endif // RT2870 // + + //AsicDelWcidTab(pAd, i); + } + } + + return; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID AssocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, + IN PUCHAR pAddr, + IN USHORT CapabilityInfo, + IN ULONG Timeout, + IN USHORT ListenIntv) +{ + COPY_MAC_ADDR(AssocReq->Addr, pAddr); + // Add mask to support 802.11b mode only + AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request + AssocReq->Timeout = Timeout; + AssocReq->ListenIntv = ListenIntv; +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID DisassocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, + IN PUCHAR pAddr, + IN USHORT Reason) +{ + COPY_MAC_ADDR(DisassocReq->Addr, pAddr); + DisassocReq->Reason = Reason; +} + + +/* + ======================================================================== + + Routine Description: + Check the out going frame, if this is an DHCP or ARP datagram + will be duplicate another frame at low data rate transmit. + + Arguments: + pAd Pointer to our adapter + pPacket Pointer to outgoing Ndis frame + + Return Value: + TRUE To be duplicate at Low data rate transmit. (1mb) + FALSE Do nothing. + + IRQL = DISPATCH_LEVEL + + Note: + + MAC header + IP Header + UDP Header + 14 Bytes 20 Bytes + + UDP Header + 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| + Source Port + 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31| + Destination Port + + port 0x43 means Bootstrap Protocol, server. + Port 0x44 means Bootstrap Protocol, client. + + ======================================================================== +*/ + +BOOLEAN RTMPCheckDHCPFrame( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + ULONG NumberOfBytesRead = 0; + ULONG CurrentOffset = 0; + PVOID pVirtualAddress = NULL; + UINT NdisBufferLength; + PUCHAR pSrc; + USHORT Protocol; + UCHAR ByteOffset36 = 0; + UCHAR ByteOffset38 = 0; + BOOLEAN ReadFirstParm = TRUE; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength); + + NumberOfBytesRead += NdisBufferLength; + pSrc = (PUCHAR) pVirtualAddress; + Protocol = *(pSrc + 12) * 256 + *(pSrc + 13); + + // + // Check DHCP & BOOTP protocol + // + while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) + { + if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) + { + CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength); + ByteOffset36 = *(pSrc + CurrentOffset); + ReadFirstParm = FALSE; + } + + if (NumberOfBytesRead >= 37) + { + CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength); + ByteOffset38 = *(pSrc + CurrentOffset); + //End of Read + break; + } + return FALSE; + } + + // Check for DHCP & BOOTP protocol + if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) + { + // + // 2054 (hex 0806) for ARP datagrams + // if this packet is not ARP datagrams, then do nothing + // ARP datagrams will also be duplicate at 1mb broadcast frames + // + if (Protocol != 0x0806 ) + return FALSE; + } + + return TRUE; +} + + +BOOLEAN RTMPCheckEtherType( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + USHORT TypeLen; + UCHAR Byte0, Byte1; + PUCHAR pSrcBuf; + UINT32 pktLen; + UINT16 srcPort, dstPort; + BOOLEAN status = TRUE; + + + pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); + pktLen = GET_OS_PKT_LEN(pPacket); + + ASSERT(pSrcBuf); + + RTMP_SET_PACKET_SPECIFIC(pPacket, 0); + + // get Ethernet protocol field + TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13]; + + pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header. + + if (TypeLen <= 1500) + { // 802.3, 802.3 LLC + /* + DestMAC(6) + SrcMAC(6) + Lenght(2) + + DSAP(1) + SSAP(1) + Control(1) + + if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. + => + SNAP (5, OriginationID(3) + etherType(2)) + */ + if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) + { + Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1); + RTMP_SET_PACKET_LLCSNAP(pPacket, 1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + pSrcBuf += 8; // Skip this LLC/SNAP header + } + else + { + //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. + } + } + + // If it's a VLAN packet, get the real Type/Length field. + if (TypeLen == 0x8100) + { + /* 0x8100 means VLAN packets */ + + /* Dest. MAC Address (6-bytes) + + Source MAC Address (6-bytes) + + Length/Type = 802.1Q Tag Type (2-byte) + + Tag Control Information (2-bytes) + + Length / Type (2-bytes) + + data payload (0-n bytes) + + Pad (0-p bytes) + + Frame Check Sequence (4-bytes) */ + + RTMP_SET_PACKET_VLAN(pPacket, 1); + Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + + pSrcBuf += 4; // Skip the VLAN Header. + } + + switch (TypeLen) + { + case 0x0800: + { + ASSERT((pktLen > 34)); + if (*(pSrcBuf + 9) == 0x11) + { // udp packet + ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header + + pSrcBuf += 20; // Skip the IP header + srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf)); + dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2))); + + if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44)) + { //It's a BOOTP/DHCP packet + RTMP_SET_PACKET_DHCP(pPacket, 1); + } + } + } + break; + case 0x0806: + { + //ARP Packet. + RTMP_SET_PACKET_DHCP(pPacket, 1); + } + break; + case 0x888e: + { + // EAPOL Packet. + RTMP_SET_PACKET_EAPOL(pPacket, 1); + } + break; + default: + status = FALSE; + break; + } + + return status; + +} + + + +VOID Update_Rssi_Sample( + IN PRTMP_ADAPTER pAd, + IN RSSI_SAMPLE *pRssi, + IN PRXWI_STRUC pRxWI) + { + CHAR rssi0 = pRxWI->RSSI0; + CHAR rssi1 = pRxWI->RSSI1; + CHAR rssi2 = pRxWI->RSSI2; + + if (rssi0 != 0) + { + pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0); + pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0; + pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3; + } + + if (rssi1 != 0) + { + pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1); + pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1; + pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3; + } + + if (rssi2 != 0) + { + pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2); + pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2; + pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3; + } +} + + + +// Normal legacy Rx packet indication +VOID Indicate_Legacy_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + UCHAR Header802_3[LENGTH_802_3]; + + // 1. get 802.3 Header + // 2. remove LLC + // a. pointer pRxBlk->pData to payload + // b. modify pRxBlk->DataSize +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif // CONFIG_STA_SUPPORT // + + if (pRxBlk->DataSize > MAX_RX_PKT_LEN) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + + STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); + +#ifdef RT2870 +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.bDisableReordering == 0) + { + PBA_REC_ENTRY pBAEntry; + ULONG Now32; + UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; + UCHAR TID = pRxBlk->pRxWI->TID; + USHORT Idx; + +#define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + { + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + if (Idx != 0) + { + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + // update last rx time + NdisGetSystemUpTime(&Now32); + if ((pBAEntry->list.qlen > 0) && + RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) + ) + { + printk("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n", pRxBlk->Flags, pRxBlk->pRxWI->TID, pRxBlk->RxD.AMPDU); + hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64); + ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); + } + } + } + } +#endif // DOT11_N_SUPPORT // +#endif // RT2870 // + + wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); + + // + // pass this 802.3 packet to upper layer or forward this packet to WM directly + // +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID); +#endif // CONFIG_STA_SUPPORT // + +} + + +// Normal, AMPDU or AMSDU +VOID CmmRxnonRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) + { + Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif // DOT11_N_SUPPORT // + { +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) + { + // handle A-MSDU + Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif // DOT11_N_SUPPORT // + { + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + } + } +} + + +VOID CmmRxRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + UCHAR Header802_3[LENGTH_802_3]; + UINT16 Msdu2Size; + UINT16 Payload1Size, Payload2Size; + PUCHAR pData2; + PNDIS_PACKET pPacket2 = NULL; + + + + Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8); + + if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) + { + /* skip two byte MSDU2 len */ + pRxBlk->pData += 2; + pRxBlk->DataSize -= 2; + } + else + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // get 802.3 Header and remove LLC +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); +#endif // CONFIG_STA_SUPPORT // + + + ASSERT(pRxBlk->pRxPacket); + + // Ralink Aggregation frame + pAd->RalinkCounters.OneSecRxAggregationCount ++; + Payload1Size = pRxBlk->DataSize - Msdu2Size; + Payload2Size = Msdu2Size - LENGTH_802_3; + + pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID); +#endif // CONFIG_STA_SUPPORT // + + if (!pPacket2) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // update payload size of 1st packet + pRxBlk->DataSize = Payload1Size; + wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID); +#endif // CONFIG_STA_SUPPORT // + + if (pPacket2) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID); +#endif // CONFIG_STA_SUPPORT // + } +} + + +#define RESET_FRAGFRAME(_fragFrame) \ + { \ + _fragFrame.RxSize = 0; \ + _fragFrame.Sequence = 0; \ + _fragFrame.LastFrag = 0; \ + _fragFrame.Flags = 0; \ + } + + +PNDIS_PACKET RTMPDeFragmentDataFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + UCHAR *pData = pRxBlk->pData; + USHORT DataSize = pRxBlk->DataSize; + PNDIS_PACKET pRetPacket = NULL; + UCHAR *pFragBuffer = NULL; + BOOLEAN bReassDone = FALSE; + UCHAR HeaderRoom = 0; + + + ASSERT(pHeader); + + HeaderRoom = pData - (UCHAR *)pHeader; + + // Re-assemble the fragmented packets + if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt + { + // the first pkt of fragment, record it. + if (pHeader->FC.MoreFrag) + { + ASSERT(pAd->FragFrame.pFragPacket); + pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); + pAd->FragFrame.RxSize = DataSize + HeaderRoom; + NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize); + pAd->FragFrame.Sequence = pHeader->Sequence; + pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0 + ASSERT(pAd->FragFrame.LastFrag == 0); + goto done; // end of processing this frame + } + } + else //Middle & End of fragment + { + if ((pHeader->Sequence != pAd->FragFrame.Sequence) || + (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) + { + // Fragment is not the same sequence or out of fragment number order + // Reset Fragment control blk + RESET_FRAGFRAME(pAd->FragFrame); + DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n")); + goto done; // give up this frame + } + else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) + { + // Fragment frame is too large, it exeeds the maximum frame size. + // Reset Fragment control blk + RESET_FRAGFRAME(pAd->FragFrame); + DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n")); + goto done; // give up this frame + } + + // + // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. + // In this case, we will dropt it. + // + if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag)); + goto done; // give up this frame + } + + pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket); + + // concatenate this fragment into the re-assembly buffer + NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize); + pAd->FragFrame.RxSize += DataSize; + pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number + + // Last fragment + if (pHeader->FC.MoreFrag == FALSE) + { + bReassDone = TRUE; + } + } + +done: + // always release rx fragmented packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + + // return defragmented packet if packet is reassembled completely + // otherwise return NULL + if (bReassDone) + { + PNDIS_PACKET pNewFragPacket; + + // allocate a new packet buffer for fragment + pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + if (pNewFragPacket) + { + // update RxBlk + pRetPacket = pAd->FragFrame.pFragPacket; + pAd->FragFrame.pFragPacket = pNewFragPacket; + pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket); + pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom; + pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom; + pRxBlk->pRxPacket = pRetPacket; + } + else + { + RESET_FRAGFRAME(pAd->FragFrame); + } + } + + return pRetPacket; +} + + +VOID Indicate_AMSDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + UINT nMSDU; + + update_os_packet_info(pAd, pRxBlk, FromWhichBSSID); + RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); + nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize); +} + +VOID Indicate_EAPOL_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } +#endif // CONFIG_STA_SUPPORT // + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n")); + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } +} + +#define BCN_TBTT_OFFSET 64 //defer 64 us +VOID ReSyncBeaconTime( + IN PRTMP_ADAPTER pAd) +{ + + UINT32 Offset; + + + Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); + + pAd->TbttTickCount++; + + // + // The updated BeaconInterval Value will affect Beacon Interval after two TBTT + // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER + // + if (Offset == (BCN_TBTT_OFFSET-2)) + { + BCN_TIME_CFG_STRUC csr; + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } + else + { + if (Offset == (BCN_TBTT_OFFSET-1)) + { + BCN_TIME_CFG_STRUC csr; + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } + } +} + diff --git a/drivers/staging/rt3070/common/cmm_data_2870.c b/drivers/staging/rt3070/common/cmm_data_2870.c new file mode 100644 index 000000000000..b1066aa2bb23 --- /dev/null +++ b/drivers/staging/rt3070/common/cmm_data_2870.c @@ -0,0 +1,980 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* +*/ +/* + All functions in this file must be USB-depended, or you should out your function + in other files. + +*/ +#include "../rt_config.h" + + +/* + We can do copy the frame into pTxContext when match following conditions. + => + => + => +*/ +static inline NDIS_STATUS RtmpUSBCanDoWrite( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN HT_TX_CONTEXT *pHTTXContext) +{ + NDIS_STATUS canWrite = NDIS_STATUS_RESOURCES; + + if (((pHTTXContext->CurWritePosition) < pHTTXContext->NextBulkOutPosition) && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition) + { + DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c1!\n")); + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); + } + else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE)) + { + DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c2!\n")); + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); + } + else if (pHTTXContext->bCurWriting == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c3!\n")); + } + else + { + canWrite = NDIS_STATUS_SUCCESS; + } + + + return canWrite; +} + + +USHORT RtmpUSB_WriteSubTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber) +{ + + // Dummy function. Should be removed in the future. + return 0; + +} + +USHORT RtmpUSB_WriteFragTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber) +{ + HT_TX_CONTEXT *pHTTXContext; + USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length. + UINT32 fillOffset; + TXINFO_STRUC *pTxInfo; + TXWI_STRUC *pTxWI; + PUCHAR pWirelessPacket = NULL; + UCHAR QueIdx; + NDIS_STATUS Status; + unsigned long IrqFlags; + UINT32 USBDMApktLen = 0, DMAHdrLen, padding; + BOOLEAN TxQLastRound = FALSE; + + // + // get Tx Ring Resource & Dma Buffer address + // + QueIdx = pTxBlk->QueIdx; + pHTTXContext = &pAd->TxContext[QueIdx]; + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + pHTTXContext = &pAd->TxContext[QueIdx]; + fillOffset = pHTTXContext->CurWritePosition; + + if(fragNum == 0) + { + // Check if we have enough space for this bulk-out batch. + Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); + if (Status == NDIS_STATUS_SUCCESS) + { + pHTTXContext->bCurWriting = TRUE; + + // Reserve space for 8 bytes padding. + if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) + { + pHTTXContext->ENextBulkOutPosition += 8; + pHTTXContext->CurWritePosition += 8; + fillOffset += 8; + } + pTxBlk->Priv = 0; + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + } + else + { + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return(Status); + } + } + else + { + // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. + Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); + if (Status == NDIS_STATUS_SUCCESS) + { + fillOffset += pTxBlk->Priv; + } + else + { + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return(Status); + } + } + + NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); + pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); + pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); + + pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; + + // copy TXWI + WLAN Header + LLC into DMA Header Buffer + //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + // Build our URB for USBD + DMAHdrLen = TXWI_SIZE + hwHdrLen; + USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; + padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment + USBDMApktLen += padding; + + pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); + + // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload + RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); + + if (fragNum == pTxBlk->TotalFragNum) + { + pTxInfo->USBDMATxburst = 0; + if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT) + { + pTxInfo->SwUseLastRound = 1; + TxQLastRound = TRUE; + } + } + else + { + pTxInfo->USBDMATxburst = 1; + } + + NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); +#endif // RT_BIG_ENDIAN // + pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + + // Zero the last padding. + pWirelessPacket += pTxBlk->SrcBufLen; + NdisZeroMemory(pWirelessPacket, padding + 8); + + if (fragNum == pTxBlk->TotalFragNum) + { + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + // Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. + pHTTXContext->CurWritePosition += pTxBlk->Priv; + if (TxQLastRound == TRUE) + pHTTXContext->CurWritePosition = 8; + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + + + // Finally, set bCurWriting as FALSE + pHTTXContext->bCurWriting = FALSE; + + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + // succeed and release the skb buffer + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); + } + + + return(Status); + +} + + +USHORT RtmpUSB_WriteSingleTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber) +{ + HT_TX_CONTEXT *pHTTXContext; + USHORT hwHdrLen; + UINT32 fillOffset; + TXINFO_STRUC *pTxInfo; + TXWI_STRUC *pTxWI; + PUCHAR pWirelessPacket; + UCHAR QueIdx; + unsigned long IrqFlags; + NDIS_STATUS Status; + UINT32 USBDMApktLen = 0, DMAHdrLen, padding; + BOOLEAN bTxQLastRound = FALSE; + + // For USB, didn't need PCI_MAP_SINGLE() + //SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); + + + // + // get Tx Ring Resource & Dma Buffer address + // + QueIdx = pTxBlk->QueIdx; + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + pHTTXContext = &pAd->TxContext[QueIdx]; + fillOffset = pHTTXContext->CurWritePosition; + + + + // Check ring full. + Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); + if(Status == NDIS_STATUS_SUCCESS) + { + pHTTXContext->bCurWriting = TRUE; + + pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); + pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); + + // Reserve space for 8 bytes padding. + if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) + { + pHTTXContext->ENextBulkOutPosition += 8; + pHTTXContext->CurWritePosition += 8; + fillOffset += 8; + } + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + + pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; + + // copy TXWI + WLAN Header + LLC into DMA Header Buffer + //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + // Build our URB for USBD + DMAHdrLen = TXWI_SIZE + hwHdrLen; + USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; + padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment + USBDMApktLen += padding; + + pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen); + + // For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload + //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); +#endif // CONFIG_STA_SUPPORT // + + if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT) + { + pTxInfo->SwUseLastRound = 1; + bTxQLastRound = TRUE; + } + NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); +#endif // RT_BIG_ENDIAN // + pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + + // We unlock it here to prevent the first 8 bytes maybe over-writed issue. + // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. + // 2. An interrupt break our routine and handle bulk-out complete. + // 3. In the bulk-out compllete, it need to do another bulk-out, + // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, + // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. + // 4. Interrupt complete. + // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. + // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. + // and the packet will wrong. + pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + pWirelessPacket += pTxBlk->SrcBufLen; + NdisZeroMemory(pWirelessPacket, padding + 8); + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + pHTTXContext->CurWritePosition += pTxBlk->Priv; + if (bTxQLastRound) + pHTTXContext->CurWritePosition = 8; + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + + pHTTXContext->bCurWriting = FALSE; + } + + + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + + // succeed and release the skb buffer + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); + + return(Status); + +} + + +USHORT RtmpUSB_WriteMultiTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber) +{ + HT_TX_CONTEXT *pHTTXContext; + USHORT hwHdrLen; // The hwHdrLen consist of 802.11 header length plus the header padding length. + UINT32 fillOffset; + TXINFO_STRUC *pTxInfo; + TXWI_STRUC *pTxWI; + PUCHAR pWirelessPacket = NULL; + UCHAR QueIdx; + NDIS_STATUS Status; + unsigned long IrqFlags; + //UINT32 USBDMApktLen = 0, DMAHdrLen, padding; + + // + // get Tx Ring Resource & Dma Buffer address + // + QueIdx = pTxBlk->QueIdx; + pHTTXContext = &pAd->TxContext[QueIdx]; + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + if(frameNum == 0) + { + // Check if we have enough space for this bulk-out batch. + Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); + if (Status == NDIS_STATUS_SUCCESS) + { + pHTTXContext->bCurWriting = TRUE; + + pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); + pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); + + + // Reserve space for 8 bytes padding. + if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) + { + + pHTTXContext->CurWritePosition += 8; + pHTTXContext->ENextBulkOutPosition += 8; + } + fillOffset = pHTTXContext->CurWritePosition; + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + + pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; + + // + // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer + // + if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) + //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; + hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; + else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) + //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; + hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; + else + //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + // Update the pTxBlk->Priv. + pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; + + // pTxInfo->USBDMApktLen now just a temp value and will to correct latter. + RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE); + + // Copy it. + NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv); +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE); +#endif // RT_BIG_ENDIAN // + pHTTXContext->CurWriteRealPos += pTxBlk->Priv; + pWirelessPacket += pTxBlk->Priv; + } + } + else + { // For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. + + Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); + if (Status == NDIS_STATUS_SUCCESS) + { + fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv); + pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; + + //hwHdrLen = pTxBlk->MpduHeaderLen; + NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen); + pWirelessPacket += (pTxBlk->MpduHeaderLen); + pTxBlk->Priv += pTxBlk->MpduHeaderLen; + } + else + { // It should not happened now unless we are going to shutdown. + DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); + Status = NDIS_STATUS_FAILURE; + } + } + + + // We unlock it here to prevent the first 8 bytes maybe over-write issue. + // 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. + // 2. An interrupt break our routine and handle bulk-out complete. + // 3. In the bulk-out compllete, it need to do another bulk-out, + // if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, + // but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. + // 4. Interrupt complete. + // 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. + // 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. + // and the packet will wrong. + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); + goto done; + } + + // Copy the frame content into DMA buffer and update the pTxBlk->Priv + NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + pWirelessPacket += pTxBlk->SrcBufLen; + pTxBlk->Priv += pTxBlk->SrcBufLen; + +done: + // Release the skb buffer here + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); + + return(Status); + +} + + +VOID RtmpUSB_FinalWriteTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN USHORT totalMPDUSize, + IN USHORT TxIdx) +{ + UCHAR QueIdx; + HT_TX_CONTEXT *pHTTXContext; + UINT32 fillOffset; + TXINFO_STRUC *pTxInfo; + TXWI_STRUC *pTxWI; + UINT32 USBDMApktLen, padding; + unsigned long IrqFlags; + PUCHAR pWirelessPacket; + + QueIdx = pTxBlk->QueIdx; + pHTTXContext = &pAd->TxContext[QueIdx]; + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + + if (pHTTXContext->bCurWriting == TRUE) + { + fillOffset = pHTTXContext->CurWritePosition; + if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition)) + && (pHTTXContext->bCopySavePad == TRUE)) + pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]); + else + pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]); + + // + // Update TxInfo->USBDMApktLen , + // the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding + // + pTxInfo = (PTXINFO_STRUC)(pWirelessPacket); + + // Calculate the bulk-out padding + USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE; + padding = (4 - (USBDMApktLen % 4)) & 0x03; // round up to 4 byte alignment + USBDMApktLen += padding; + + pTxInfo->USBDMATxPktLen = USBDMApktLen; + + // + // Update TXWI->MPDUtotalByteCount , + // the length = 802.11 header + payload_of_all_batch_frames + pTxWI= (PTXWI_STRUC)(pWirelessPacket + TXINFO_SIZE); + pTxWI->MPDUtotalByteCount = totalMPDUSize; + + // + // Update the pHTTXContext->CurWritePosition + // + pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen); + if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT) + { // Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame. + pHTTXContext->CurWritePosition = 8; + pTxInfo->SwUseLastRound = 1; + } + pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; + + + // + // Zero the last padding. + // + pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]); + NdisZeroMemory(pWirelessPacket, padding + 8); + + // Finally, set bCurWriting as FALSE + pHTTXContext->bCurWriting = FALSE; + + } + else + { // It should not happened now unless we are going to shutdown. + DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n")); + } + + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + +} + + +VOID RtmpUSBDataLastTxIdx( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN USHORT TxIdx) +{ + // DO nothing for USB. +} + + +/* + When can do bulk-out: + 1. TxSwFreeIdx < TX_RING_SIZE; + It means has at least one Ring entity is ready for bulk-out, kick it out. + 2. If TxSwFreeIdx == TX_RING_SIZE + Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out. + +*/ +VOID RtmpUSBDataKickOut( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx) +{ + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); + RTUSBKickBulkOut(pAd); + +} + + +/* + Must be run in Interrupt context + This function handle RT2870 specific TxDesc and cpu index update and kick the packet out. + */ +int RtmpUSBMgmtKickOut( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN PUCHAR pSrcBufVA, + IN UINT SrcBufLen) +{ + PTXINFO_STRUC pTxInfo; + ULONG BulkOutSize; + UCHAR padLen; + PUCHAR pDest; + ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; + PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa; + unsigned long IrqFlags; + + + pTxInfo = (PTXINFO_STRUC)(pSrcBufVA); + + // Build our URB for USBD + BulkOutSize = SrcBufLen; + BulkOutSize = (BulkOutSize + 3) & (~3); + RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + + BulkOutSize += 4; // Always add 4 extra bytes at every packet. + + // If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again. + if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0) + BulkOutSize += 4; + + padLen = BulkOutSize - SrcBufLen; + ASSERT((padLen <= RTMP_PKT_TAIL_PADDING)); + + // Now memzero all extra padding bytes. + pDest = (PUCHAR)(pSrcBufVA + SrcBufLen); + skb_put(GET_OS_PKT_TYPE(pPacket), padLen); + NdisZeroMemory(pDest, padLen); + + RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); + + pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket; + pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket)); + + // Length in TxInfo should be 8 less than bulkout size. + pMLMEContext->BulkOutSize = BulkOutSize; + pMLMEContext->InUse = TRUE; + pMLMEContext->bWaitingBulkOut = TRUE; + + + //for debug + //hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize)); + + //pAd->RalinkCounters.KickTxCount++; + //pAd->RalinkCounters.OneSecTxDoneCount++; + + //if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE) + // needKickOut = TRUE; + + // Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX + pAd->MgmtRing.TxSwFreeIdx--; + INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); + + RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); + //if (needKickOut) + RTUSBKickBulkOut(pAd); + + return 0; +} + + +VOID RtmpUSBNullFrameKickOut( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN UCHAR *pNullFrame, + IN UINT32 frameLen) +{ + if (pAd->NullContext.InUse == FALSE) + { + PTX_CONTEXT pNullContext; + PTXINFO_STRUC pTxInfo; + PTXWI_STRUC pTxWI; + PUCHAR pWirelessPkt; + + pNullContext = &(pAd->NullContext); + + // Set the in use bit + pNullContext->InUse = TRUE; + pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0]; + + RTMPZeroMemory(&pWirelessPkt[0], 100); + pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[0]; + RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + pTxInfo->QSEL = FIFO_EDCA; + pTxWI = (PTXWI_STRUC)&pWirelessPkt[TXINFO_SIZE]; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)), + 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); +#endif // RT_BIG_ENDIAN // + + RTMPMoveMemory(&pWirelessPkt[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11)); +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)&pWirelessPkt[TXINFO_SIZE + TXWI_SIZE], DIR_WRITE, FALSE); +#endif // RT_BIG_ENDIAN // + pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4; + + // Fill out frame length information for global Bulk out arbitor + //pNullContext->BulkOutSize = TransferBufferLength; + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - send NULL Frame @%d Mbps...\n", RateIdToMbps[pAd->CommonCfg.TxRate])); + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); + + // Kick bulk out + RTUSBKickBulkOut(pAd); + } + +} + +#ifdef CONFIG_STA_SUPPORT +/* + ======================================================================== + + Routine Description: + Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound + + Arguments: + pRxD Pointer to the Rx descriptor + + Return Value: + NDIS_STATUS_SUCCESS No err + NDIS_STATUS_FAILURE Error + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxINFO) +{ + PCIPHER_KEY pWpaKey; + INT dBm; + + if (pAd->bPromiscuous == TRUE) + return(NDIS_STATUS_SUCCESS); + if(pRxINFO == NULL) + return(NDIS_STATUS_FAILURE); + + // Phy errors & CRC errors + if (pRxINFO->Crc) + { + // Check RSSI for Noise Hist statistic collection. + dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta; + if (dBm <= -87) + pAd->StaCfg.RPIDensity[0] += 1; + else if (dBm <= -82) + pAd->StaCfg.RPIDensity[1] += 1; + else if (dBm <= -77) + pAd->StaCfg.RPIDensity[2] += 1; + else if (dBm <= -72) + pAd->StaCfg.RPIDensity[3] += 1; + else if (dBm <= -67) + pAd->StaCfg.RPIDensity[4] += 1; + else if (dBm <= -62) + pAd->StaCfg.RPIDensity[5] += 1; + else if (dBm <= -57) + pAd->StaCfg.RPIDensity[6] += 1; + else if (dBm > -57) + pAd->StaCfg.RPIDensity[7] += 1; + + return(NDIS_STATUS_FAILURE); + } + + // Add Rx size to channel load counter, we should ignore error counts + pAd->StaCfg.CLBusyBytes += (pRxWI->MPDUtotalByteCount+ 14); + + // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics + if (pHeader->FC.ToDs) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Err;FC.ToDs\n")); + return NDIS_STATUS_FAILURE; + } + + // Paul 04-03 for OFDM Rx length issue + if (pRxWI->MPDUtotalByteCount > MAX_AGGREGATION_SIZE) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n")); + return NDIS_STATUS_FAILURE; + } + + // Drop not U2M frames, cant's drop here because we will drop beacon in this case + // I am kind of doubting the U2M bit operation + // if (pRxD->U2M == 0) + // return(NDIS_STATUS_FAILURE); + + // drop decyption fail frame + if (pRxINFO->Decrypted && pRxINFO->CipherErr) + { + + // + // MIC Error + // + if ((pRxINFO->CipherErr == 2) && pRxINFO->MyBss) + { + pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex]; + RTMPReportMicError(pAd, pWpaKey); + DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n")); + } + + if (pRxINFO->Decrypted && + (pAd->SharedKey[BSS0][pRxWI->KeyIndex].CipherAlg == CIPHER_AES) && + (pHeader->Sequence == pAd->FragFrame.Sequence)) + { + // + // Acceptable since the First FragFrame no CipherErr problem. + // + return(NDIS_STATUS_SUCCESS); + } + + return(NDIS_STATUS_FAILURE); + } + + return(NDIS_STATUS_SUCCESS); +} + +VOID RT28xxUsbStaAsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx) +{ + AUTO_WAKEUP_STRUC AutoWakeupCfg; + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + + AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); +} + +VOID RT28xxUsbStaAsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp) +{ + AUTO_WAKEUP_STRUC AutoWakeupCfg; + + // we have decided to SLEEP, so at least do it for a BEACON period. + if (TbttNumToNextWakeUp == 0) + TbttNumToNextWakeUp = 1; + + AutoWakeupCfg.word = 0; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + + AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1; + AutoWakeupCfg.field.EnableAutoWakeup = 1; + AutoWakeupCfg.field.AutoLeadTime = 5; + RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word); + + AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); // send POWER-SAVE command to MCU. Timeout 40us. + + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE); + +} +#endif // CONFIG_STA_SUPPORT // + +VOID RT28xxUsbMlmeRadioOn( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n")); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); + RTMPusecDelay(10000); + } +#endif // CONFIG_STA_SUPPORT // + NICResetFromError(pAd); + + // Enable Tx/Rx + RTMPEnableRxTx(pAd); + +#ifdef RT3070 + if (IS_RT3071(pAd)) + { + RT30xxReverseRFSleepModeSetup(pAd); + } +#endif // RT3070 // + + // Clear Radio off flag + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + RTUSBBulkReceive(pAd); +#endif // CONFIG_STA_SUPPORT // + + // Set LED + RTMPSetLED(pAd, LED_RADIO_ON); +} + +VOID RT28xxUsbMlmeRadioOFF( + IN PRTMP_ADAPTER pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + UINT32 Value, i; + + DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n")); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + // Set LED + RTMPSetLED(pAd, LED_RADIO_OFF); + // Set Radio off flag + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Link down first if any association exists + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + LinkDown(pAd, FALSE); + RTMPusecDelay(10000); + + //========================================== + // Clean up old bss table + BssTableInit(&pAd->ScanTab); + } +#endif // CONFIG_STA_SUPPORT // + + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + // Must using 40MHz. + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + } + else + { + // Must using 20MHz. + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + } + + // Disable Tx/Rx DMA + RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.EnableRxDMA = 0; + RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings + + // Waiting for DMA idle + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + RTMPusecDelay(1000); + }while (i++ < 100); + + // Disable MAC Tx/Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= (0xfffffff3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // MAC_SYS_CTRL => value = 0x0 => 40mA + //RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0); + + // PWR_PIN_CFG => value = 0x0 => 40mA + //RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0); + + // TX_PIN_CFG => value = 0x0 => 20mA + //RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); +#endif // CONFIG_STA_SUPPORT // +} + diff --git a/drivers/staging/rt3070/common/cmm_info.c b/drivers/staging/rt3070/common/cmm_info.c new file mode 100644 index 000000000000..54cb1a35f7bf --- /dev/null +++ b/drivers/staging/rt3070/common/cmm_info.c @@ -0,0 +1,3395 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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 "../rt_config.h" + +INT Show_SSID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Channel_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +#ifdef DOT11_N_SUPPORT +INT Show_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); +#endif // DOT11_N_SUPPORT // + +INT Show_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_CountryCode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +#ifdef AGGREGATION_SUPPORT +INT Show_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); +#endif // AGGREGATION_SUPPORT // + +#ifdef WMM_SUPPORT +INT Show_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); +#endif // WMM_SUPPORT // + +INT Show_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +#ifdef CONFIG_STA_SUPPORT +INT Show_NetworkType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); +#endif // CONFIG_STA_SUPPORT // + +INT Show_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Key1_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Key2_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Key3_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_Key4_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +INT Show_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf); + +static struct { + CHAR *name; + INT (*show_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg); +} *PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC, RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC[] = { + {"SSID", Show_SSID_Proc}, + {"WirelessMode", Show_WirelessMode_Proc}, + {"TxBurst", Show_TxBurst_Proc}, + {"TxPreamble", Show_TxPreamble_Proc}, + {"TxPower", Show_TxPower_Proc}, + {"Channel", Show_Channel_Proc}, + {"BGProtection", Show_BGProtection_Proc}, + {"RTSThreshold", Show_RTSThreshold_Proc}, + {"FragThreshold", Show_FragThreshold_Proc}, +#ifdef DOT11_N_SUPPORT + {"HtBw", Show_HtBw_Proc}, + {"HtMcs", Show_HtMcs_Proc}, + {"HtGi", Show_HtGi_Proc}, + {"HtOpMode", Show_HtOpMode_Proc}, + {"HtExtcha", Show_HtExtcha_Proc}, + {"HtMpduDensity", Show_HtMpduDensity_Proc}, + {"HtBaWinSize", Show_HtBaWinSize_Proc}, + {"HtRdg", Show_HtRdg_Proc}, + {"HtAmsdu", Show_HtAmsdu_Proc}, + {"HtAutoBa", Show_HtAutoBa_Proc}, +#endif // DOT11_N_SUPPORT // + {"CountryRegion", Show_CountryRegion_Proc}, + {"CountryRegionABand", Show_CountryRegionABand_Proc}, + {"CountryCode", Show_CountryCode_Proc}, +#ifdef AGGREGATION_SUPPORT + {"PktAggregate", Show_PktAggregate_Proc}, +#endif + +#ifdef WMM_SUPPORT + {"WmmCapable", Show_WmmCapable_Proc}, +#endif + {"IEEE80211H", Show_IEEE80211H_Proc}, +#ifdef CONFIG_STA_SUPPORT + {"NetworkType", Show_NetworkType_Proc}, +#endif // CONFIG_STA_SUPPORT // + {"AuthMode", Show_AuthMode_Proc}, + {"EncrypType", Show_EncrypType_Proc}, + {"DefaultKeyID", Show_DefaultKeyID_Proc}, + {"Key1", Show_Key1_Proc}, + {"Key2", Show_Key2_Proc}, + {"Key3", Show_Key3_Proc}, + {"Key4", Show_Key4_Proc}, + {"WPAPSK", Show_WPAPSK_Proc}, + {NULL, NULL} +}; + +/* + ========================================================================== + Description: + Get Driver version. + + Return: + ========================================================================== +*/ +INT Set_DriverVersion_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", STA_DRIVER_VERSION)); +#endif // CONFIG_STA_SUPPORT // + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Country Region. + This command will not work, if the field of CountryRegion in eeprom is programmed. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG region; + + region = simple_strtol(arg, 0, 10); + +#ifdef EXT_BUILD_CHANNEL_LIST + return -EOPNOTSUPP; +#endif // EXT_BUILD_CHANNEL_LIST // + + // Country can be set only when EEPROM not programmed + if (pAd->CommonCfg.CountryRegion & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameter of CountryRegion in eeprom is programmed \n")); + return FALSE; + } + + if((region >= 0) && (region <= REGION_MAXIMUM_BG_BAND)) + { + pAd->CommonCfg.CountryRegion = (UCHAR) region; + } + else if (region == REGION_31_BG_BAND) + { + pAd->CommonCfg.CountryRegion = (UCHAR) region; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameters out of range\n")); + return FALSE; + } + + // if set country region, driver needs to be reset + BuildChannelList(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegion)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Country Region for A band. + This command will not work, if the field of CountryRegion in eeprom is programmed. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG region; + + region = simple_strtol(arg, 0, 10); + +#ifdef EXT_BUILD_CHANNEL_LIST + return -EOPNOTSUPP; +#endif // EXT_BUILD_CHANNEL_LIST // + + // Country can be set only when EEPROM not programmed + if (pAd->CommonCfg.CountryRegionForABand & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameter of CountryRegion in eeprom is programmed \n")); + return FALSE; + } + + if((region >= 0) && (region <= REGION_MAXIMUM_A_BAND)) + { + pAd->CommonCfg.CountryRegionForABand = (UCHAR) region; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameters out of range\n")); + return FALSE; + } + + // if set country region, driver needs to be reset + BuildChannelList(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegionABand_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegionForABand)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Wireless Mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG WirelessMode; + INT success = TRUE; + + WirelessMode = simple_strtol(arg, 0, 10); + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + INT MaxPhyMode = PHY_11G; + +#ifdef DOT11_N_SUPPORT + MaxPhyMode = PHY_11N_5G; +#endif // DOT11_N_SUPPORT // + + if (WirelessMode <= MaxPhyMode) + { + RTMPSetPhyMode(pAd, WirelessMode); +#ifdef DOT11_N_SUPPORT + if (WirelessMode >= PHY_11ABGN_MIXED) + { + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + pAd->CommonCfg.REGBACapability.field.AutoBA = TRUE; + } + else + { + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + pAd->CommonCfg.REGBACapability.field.AutoBA = FALSE; + } +#endif // DOT11_N_SUPPORT // + // Set AdhocMode rates + if (pAd->StaCfg.BssType == BSS_ADHOC) + { + MlmeUpdateTxRates(pAd, FALSE, 0); + MakeIbssBeacon(pAd); // re-build BEACON frame + AsicEnableIbssSync(pAd); // copy to on-chip memory + } + } + else + { + success = FALSE; + } + } +#endif // CONFIG_STA_SUPPORT // + + // it is needed to set SSID to take effect + if (success == TRUE) + { +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("Set_WirelessMode_Proc::(=%ld)\n", WirelessMode)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_WirelessMode_Proc::parameters out of range\n")); + } + + return success; +} + +/* + ========================================================================== + Description: + Set Channel + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Channel_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + INT success = TRUE; + UCHAR Channel; + + Channel = (UCHAR) simple_strtol(arg, 0, 10); + + // check if this channel is valid + if (ChannelSanity(pAd, Channel) == TRUE) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->CommonCfg.Channel = Channel; + + if (MONITOR_ON(pAd)) + { +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + N_SetCenCh(pAd); + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n", + pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + } + else +#endif // DOT11_N_SUPPORT // + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel)); + } + } + } +#endif // CONFIG_STA_SUPPORT // + success = TRUE; + } + else + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + success = FALSE; +#endif // CONFIG_STA_SUPPORT // + } + + + if (success == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel)); + + return success; +} + +/* + ========================================================================== + Description: + Set Short Slot Time Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ShortSlot_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG ShortSlot; + + ShortSlot = simple_strtol(arg, 0, 10); + + if (ShortSlot == 1) + pAd->CommonCfg.bUseShortSlotTime = TRUE; + else if (ShortSlot == 0) + pAd->CommonCfg.bUseShortSlotTime = FALSE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ShortSlot_Proc::(ShortSlot=%d)\n", pAd->CommonCfg.bUseShortSlotTime)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Tx power + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG TxPower; + INT success = FALSE; + + TxPower = (ULONG) simple_strtol(arg, 0, 10); + if (TxPower <= 100) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->CommonCfg.TxPowerDefault = TxPower; + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + } +#endif // CONFIG_STA_SUPPORT // + success = TRUE; + } + else + success = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPower_Proc::(TxPowerPercentage=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); + + return success; +} + +/* + ========================================================================== + Description: + Set 11B/11G Protection + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + switch (simple_strtol(arg, 0, 10)) + { + case 0: //AUTO + pAd->CommonCfg.UseBGProtection = 0; + break; + case 1: //Always On + pAd->CommonCfg.UseBGProtection = 1; + break; + case 2: //Always OFF + pAd->CommonCfg.UseBGProtection = 2; + break; + default: //Invalid argument + return FALSE; + } + + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BGProtection_Proc::(BGProtection=%ld)\n", pAd->CommonCfg.UseBGProtection)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set TxPreamble + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + RT_802_11_PREAMBLE Preamble; + + Preamble = simple_strtol(arg, 0, 10); + + + switch (Preamble) + { + case Rt802_11PreambleShort: + pAd->CommonCfg.TxPreamble = Preamble; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); +#endif // CONFIG_STA_SUPPORT // + break; + case Rt802_11PreambleLong: +#ifdef CONFIG_STA_SUPPORT + case Rt802_11PreambleAuto: + // if user wants AUTO, initialize to LONG here, then change according to AP's + // capability upon association. +#endif // CONFIG_STA_SUPPORT // + pAd->CommonCfg.TxPreamble = Preamble; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); +#endif // CONFIG_STA_SUPPORT // + break; + default: //Invalid argument + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPreamble_Proc::(TxPreamble=%ld)\n", pAd->CommonCfg.TxPreamble)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set RTS Threshold + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + NDIS_802_11_RTS_THRESHOLD RtsThresh; + + RtsThresh = simple_strtol(arg, 0, 10); + + if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD)) + pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; +#ifdef CONFIG_STA_SUPPORT + else if (RtsThresh == 0) + pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; +#endif // CONFIG_STA_SUPPORT // + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_RTSThreshold_Proc::(RTSThreshold=%d)\n", pAd->CommonCfg.RtsThreshold)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Fragment Threshold + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + + FragThresh = simple_strtol(arg, 0, 10); + + if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) + { + //Illegal FragThresh so we set it to default + pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + } + else if (FragThresh % 2 == 1) + { + // The length of each fragment shall always be an even number of octets, except for the last fragment + // of an MSDU or MMPDU, which may be either an even or an odd number of octets. + pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); + } + else + { + pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->CommonCfg.FragmentThreshold == MAX_FRAG_THRESHOLD) + pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; + else + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + } +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("Set_FragThreshold_Proc::(FragThreshold=%d)\n", pAd->CommonCfg.FragmentThreshold)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set TxBurst + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG TxBurst; + + TxBurst = simple_strtol(arg, 0, 10); + if (TxBurst == 1) + pAd->CommonCfg.bEnableTxBurst = TRUE; + else if (TxBurst == 0) + pAd->CommonCfg.bEnableTxBurst = FALSE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxBurst_Proc::(TxBurst=%d)\n", pAd->CommonCfg.bEnableTxBurst)); + + return TRUE; +} + +#ifdef AGGREGATION_SUPPORT +/* + ========================================================================== + Description: + Set TxBurst + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG aggre; + + aggre = simple_strtol(arg, 0, 10); + + if (aggre == 1) + pAd->CommonCfg.bAggregationCapable = TRUE; + else if (aggre == 0) + pAd->CommonCfg.bAggregationCapable = FALSE; + else + return FALSE; //Invalid argument + + + DBGPRINT(RT_DEBUG_TRACE, ("Set_PktAggregate_Proc::(AGGRE=%d)\n", pAd->CommonCfg.bAggregationCapable)); + + return TRUE; +} +#endif + +/* + ========================================================================== + Description: + Set IEEE80211H. + This parameter is 1 when needs radar detection, otherwise 0 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG ieee80211h; + + ieee80211h = simple_strtol(arg, 0, 10); + + if (ieee80211h == 1) + pAd->CommonCfg.bIEEE80211H = TRUE; + else if (ieee80211h == 0) + pAd->CommonCfg.bIEEE80211H = FALSE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_IEEE80211H_Proc::(IEEE80211H=%d)\n", pAd->CommonCfg.bIEEE80211H)); + + return TRUE; +} + + +#ifdef DBG +/* + ========================================================================== + Description: + For Debug information + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Debug_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==> Set_Debug_Proc *******************\n")); + + if(simple_strtol(arg, 0, 10) <= RT_DEBUG_LOUD) + RTDebugLevel = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Debug_Proc(RTDebugLevel = %ld)\n", RTDebugLevel)); + + return TRUE; +} +#endif + +INT Show_DescInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + return TRUE; +} + +/* + ========================================================================== + Description: + Reset statistics counter + + Arguments: + pAdapter Pointer to our adapter + arg + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ResetStatCounter_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + //UCHAR i; + //MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("==>Set_ResetStatCounter_Proc\n")); + + // add the most up-to-date h/w raw counters into software counters + NICUpdateRawCounters(pAd); + + NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11)); + NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3)); + NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK)); + + return TRUE; +} + +BOOLEAN RTMPCheckStrPrintAble( + IN CHAR *pInPutStr, + IN UCHAR strLen) +{ + UCHAR i=0; + + for (i=0; i 0x7E)) + return FALSE; + } + + return TRUE; +} + +/* + ======================================================================== + + Routine Description: + Remove WPA Key process + + Arguments: + pAd Pointer to our adapter + pBuf Pointer to the where the key stored + + Return Value: + NDIS_SUCCESS Add key successfully + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +#ifdef CONFIG_STA_SUPPORT +VOID RTMPSetDesiredRates( + IN PRTMP_ADAPTER pAdapter, + IN LONG Rates) +{ + NDIS_802_11_RATES aryRates; + + memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES)); + switch (pAdapter->CommonCfg.PhyMode) + { + case PHY_11A: // A only + switch (Rates) + { + case 6000000: //6M + aryRates[0] = 0x0c; // 6M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 9000000: //9M + aryRates[0] = 0x12; // 9M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 12000000: //12M + aryRates[0] = 0x18; // 12M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 18000000: //18M + aryRates[0] = 0x24; // 18M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 24000000: //24M + aryRates[0] = 0x30; // 24M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; + break; + case 36000000: //36M + aryRates[0] = 0x48; // 36M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; + break; + case 48000000: //48M + aryRates[0] = 0x60; // 48M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; + break; + case 54000000: //54M + aryRates[0] = 0x6c; // 54M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7; + break; + case -1: //Auto + default: + aryRates[0] = 0x6c; // 54Mbps + aryRates[1] = 0x60; // 48Mbps + aryRates[2] = 0x48; // 36Mbps + aryRates[3] = 0x30; // 24Mbps + aryRates[4] = 0x24; // 18M + aryRates[5] = 0x18; // 12M + aryRates[6] = 0x12; // 9M + aryRates[7] = 0x0c; // 6M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + break; + } + break; + case PHY_11BG_MIXED: // B/G Mixed + case PHY_11B: // B only + case PHY_11ABG_MIXED: // A/B/G Mixed + default: + switch (Rates) + { + case 1000000: //1M + aryRates[0] = 0x02; + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 2000000: //2M + aryRates[0] = 0x04; + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 5000000: //5.5M + aryRates[0] = 0x0b; // 5.5M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 11000000: //11M + aryRates[0] = 0x16; // 11M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 6000000: //6M + aryRates[0] = 0x0c; // 6M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0; + break; + case 9000000: //9M + aryRates[0] = 0x12; // 9M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1; + break; + case 12000000: //12M + aryRates[0] = 0x18; // 12M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2; + break; + case 18000000: //18M + aryRates[0] = 0x24; // 18M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3; + break; + case 24000000: //24M + aryRates[0] = 0x30; // 24M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4; + break; + case 36000000: //36M + aryRates[0] = 0x48; // 36M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5; + break; + case 48000000: //48M + aryRates[0] = 0x60; // 48M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6; + break; + case 54000000: //54M + aryRates[0] = 0x6c; // 54M + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7; + break; + case -1: //Auto + default: + if (pAdapter->CommonCfg.PhyMode == PHY_11B) + { //B Only + aryRates[0] = 0x16; // 11Mbps + aryRates[1] = 0x0b; // 5.5Mbps + aryRates[2] = 0x04; // 2Mbps + aryRates[3] = 0x02; // 1Mbps + } + else + { //(B/G) Mixed or (A/B/G) Mixed + aryRates[0] = 0x6c; // 54Mbps + aryRates[1] = 0x60; // 48Mbps + aryRates[2] = 0x48; // 36Mbps + aryRates[3] = 0x30; // 24Mbps + aryRates[4] = 0x16; // 11Mbps + aryRates[5] = 0x0b; // 5.5Mbps + aryRates[6] = 0x04; // 2Mbps + aryRates[7] = 0x02; // 1Mbps + } + pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + break; + } + break; + } + + NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); + DBGPRINT(RT_DEBUG_TRACE, (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", + pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1], + pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3], + pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5], + pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] )); + // Changing DesiredRate may affect the MAX TX rate we used to TX frames out + MlmeUpdateTxRates(pAdapter, FALSE, 0); +} + +NDIS_STATUS RTMPWPARemoveKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf) +{ + PNDIS_802_11_REMOVE_KEY pKey; + ULONG KeyIdx; + NDIS_STATUS Status = NDIS_STATUS_FAILURE; + BOOLEAN bTxKey; // Set the key as transmit key + BOOLEAN bPairwise; // Indicate the key is pairwise key + BOOLEAN bKeyRSC; // indicate the receive SC set by KeyRSC value. + // Otherwise, it will set by the NIC. + BOOLEAN bAuthenticator; // indicate key is set by authenticator. + INT i; + + DBGPRINT(RT_DEBUG_TRACE,("---> RTMPWPARemoveKeyProc\n")); + + pKey = (PNDIS_802_11_REMOVE_KEY) pBuf; + KeyIdx = pKey->KeyIndex & 0xff; + // Bit 31 of Add-key, Tx Key + bTxKey = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE; + // Bit 30 of Add-key PairwiseKey + bPairwise = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE; + // Bit 29 of Add-key KeyRSC + bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE; + // Bit 28 of Add-key Authenticator + bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE; + + // 1. If bTx is TRUE, return failure information + if (bTxKey == TRUE) + return(NDIS_STATUS_INVALID_DATA); + + // 2. Check Pairwise Key + if (bPairwise) + { + // a. If BSSID is broadcast, remove all pairwise keys. + // b. If not broadcast, remove the pairwise specified by BSSID + for (i = 0; i < SHARE_KEY_NUM; i++) + { + if (MAC_ADDR_EQUAL(pAd->SharedKey[BSS0][i].BssId, pKey->BSSID)) + { + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%d)\n", i)); + pAd->SharedKey[BSS0][i].KeyLen = 0; + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)i); + Status = NDIS_STATUS_SUCCESS; + break; + } + } + } + // 3. Group Key + else + { + // a. If BSSID is broadcast, remove all group keys indexed + // b. If BSSID matched, delete the group key indexed. + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%ld)\n", KeyIdx)); + pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0; + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx); + Status = NDIS_STATUS_SUCCESS; + } + + return (Status); +} +#endif // CONFIG_STA_SUPPORT // + + +#ifdef CONFIG_STA_SUPPORT +/* + ======================================================================== + + Routine Description: + Remove All WPA Keys + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPWPARemoveAllKeys( + IN PRTMP_ADAPTER pAd) +{ + + UCHAR i; + + DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus)); + + // For WEP/CKIP, there is no need to remove it, since WinXP won't set it again after + // Link up. And it will be replaced if user changed it. + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return; + + // For WPA-None, there is no need to remove it, since WinXP won't set it again after + // Link up. And it will be replaced if user changed it. + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + return; + + // set BSSID wcid entry of the Pair-wise Key table as no-security mode + AsicRemovePairwiseKeyEntry(pAd, BSS0, BSSID_WCID); + + // set all shared key mode as no-security. + for (i = 0; i < SHARE_KEY_NUM; i++) + { + DBGPRINT(RT_DEBUG_TRACE,("remove %s key #%d\n", CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i)); + NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(CIPHER_KEY)); + + AsicRemoveSharedKeyEntry(pAd, BSS0, i); + } + +} +#endif // CONFIG_STA_SUPPORT // + +/* + ======================================================================== + Routine Description: + Change NIC PHY mode. Re-association may be necessary. possible settings + include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED + + Arguments: + pAd - Pointer to our adapter + phymode - + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPSetPhyMode( + IN PRTMP_ADAPTER pAd, + IN ULONG phymode) +{ + INT i; + // the selected phymode must be supported by the RF IC encoded in E2PROM + + pAd->CommonCfg.PhyMode = (UCHAR)phymode; + + DBGPRINT(RT_DEBUG_TRACE,("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel)); +#ifdef EXT_BUILD_CHANNEL_LIST + BuildChannelListEx(pAd); +#else + BuildChannelList(pAd); +#endif // EXT_BUILD_CHANNEL_LIST // + + // sanity check user setting + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) + break; + } + + if (i == pAd->ChannelListNum) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->CommonCfg.Channel = FirstChannel(pAd); +#endif // CONFIG_STA_SUPPORT // + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", pAd->CommonCfg.Channel)); + } + + NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + switch (phymode) { + case PHY_11B: + pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRateLen = 4; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps + //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; // This MODE is only FYI. not use + break; + + case PHY_11G: + case PHY_11BG_MIXED: + case PHY_11ABG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: + case PHY_11GN_MIXED: +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[4] = 0x12; // 9 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[5] = 0x24; // 18 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[6] = 0x48; // 36 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps + pAd->CommonCfg.ExtRate[1] = 0x18; // 12 mbps, in units of 0.5 Mbps + pAd->CommonCfg.ExtRate[2] = 0x30; // 24 mbps, in units of 0.5 Mbps + pAd->CommonCfg.ExtRate[3] = 0x60; // 48 mbps, in units of 0.5 Mbps + pAd->CommonCfg.ExtRateLen = 4; + pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[4] = 12; // 6 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[5] = 18; // 9 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[6] = 24; // 12 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[7] = 36; // 18 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[8] = 48; // 24 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[9] = 72; // 36 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[10] = 96; // 48 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[11] = 108; // 54 mbps, in units of 0.5 Mbps + break; + + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11AN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11N_5G: +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate + pAd->CommonCfg.SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 12; // 6 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[1] = 18; // 9 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[2] = 24; // 12 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[3] = 36; // 18 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[4] = 48; // 24 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[5] = 72; // 36 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[6] = 96; // 48 mbps, in units of 0.5 Mbps + pAd->CommonCfg.DesireRate[7] = 108; // 54 mbps, in units of 0.5 Mbps + //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; // This MODE is only FYI. not use + break; + + default: + break; + } + + + pAd->CommonCfg.BandState = UNKNOWN_BAND; +} + + +#ifdef DOT11_N_SUPPORT +/* + ======================================================================== + Routine Description: + Caller ensures we has 802.11n support. + Calls at setting HT from AP/STASetinformation + + Arguments: + pAd - Pointer to our adapter + phymode - + + ======================================================================== +*/ +VOID RTMPSetHT( + IN PRTMP_ADAPTER pAd, + IN OID_SET_HT_PHYMODE *pHTPhyMode) +{ + //ULONG *pmcs; + UINT32 Value = 0; + UCHAR BBPValue = 0; + UCHAR BBP3Value = 0; + UCHAR RxStream = pAd->CommonCfg.RxStream; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->ExtOffset, + pHTPhyMode->MCS, pHTPhyMode->BW, + pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); + + // Don't zero supportedHyPhy structure. + RTMPZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); + RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, sizeof(pAd->CommonCfg.NewExtChanOffset)); + RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy, sizeof(pAd->CommonCfg.DesiredHtPhy)); + + if (pAd->CommonCfg.bRdg) + { + pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1; + pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1; + } + else + { + pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0; + pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0; + } + + pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3; + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : RxBAWinLimit = %d\n", pAd->CommonCfg.BACapability.field.RxBAWinLimit)); + + // Mimo power save, A-MSDU size, + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize = (UCHAR)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = (UCHAR)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n", + pAd->CommonCfg.DesiredHtPhy.AmsduSize, + pAd->CommonCfg.DesiredHtPhy.MimoPs, + pAd->CommonCfg.DesiredHtPhy.MpduDensity, + pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor)); + + if(pHTPhyMode->HtMode == HTMODE_GF) + { + pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1; + pAd->CommonCfg.DesiredHtPhy.GF = 1; + } + else + pAd->CommonCfg.DesiredHtPhy.GF = 0; + + // Decide Rx MCSSet + switch (RxStream) + { + case 1: + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0x00; + break; + + case 2: + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; + break; + + case 3: // 3*3 + pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff; + pAd->CommonCfg.HtCapability.MCSSet[2] = 0xff; + break; + } + + if (pAd->CommonCfg.bForty_Mhz_Intolerant && (pAd->CommonCfg.Channel <= 14) && (pHTPhyMode->BW == BW_40) ) + { + pHTPhyMode->BW = BW_20; + pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1; + } + + if(pHTPhyMode->BW == BW_40) + { + pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; // MCS 32 + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1; + if (pAd->CommonCfg.Channel <= 14) + pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1; + + pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = (pHTPhyMode->ExtOffset == EXTCHA_BELOW)? (EXTCHA_BELOW): EXTCHA_ABOVE; + // Set Regsiter for extension channel position. + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value); + if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW)) + { + Value |= 0x1; + BBP3Value |= (0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } + else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE)) + { + Value &= 0xfe; + BBP3Value &= (~0x20); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + } + + // Turn on BBP 40MHz mode now only as AP . + // Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection. + if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd) + ) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value); + pAd->CommonCfg.BBPCurrentBW = BW_40; + } + } + else + { + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0; + pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + // Turn on BBP 20MHz mode by request here. + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + pAd->CommonCfg.BBPCurrentBW = BW_20; + } + } + + if(pHTPhyMode->STBC == STBC_USE) + { + pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1; + pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1; + pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1; + pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1; + } + else + { + pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0; + pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0; + } + + if(pHTPhyMode->SHORTGI == GI_400) + { + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1; + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1; + } + else + { + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0; + pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0; + pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0; + } + + // We support link adaptation for unsolicit MCS feedback, set to 2. + pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; //MCSFBK_UNSOLICIT; + pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel; + // 1, the extension channel above the control channel. + + // EDCA parameters used for AP's own transmission + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) + { + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; + pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; + pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; + pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; + + pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; + pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; + + pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; + pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; + pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; + pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; + + pAd->CommonCfg.APEdcaParm.Txop[0] = 0; + pAd->CommonCfg.APEdcaParm.Txop[1] = 0; + pAd->CommonCfg.APEdcaParm.Txop[2] = 94; + pAd->CommonCfg.APEdcaParm.Txop[3] = 47; + } + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RTMPSetIndividualHT(pAd, 0); + } +#endif // CONFIG_STA_SUPPORT // + +} + +/* + ======================================================================== + Routine Description: + Caller ensures we has 802.11n support. + Calls at setting HT from AP/STASetinformation + + Arguments: + pAd - Pointer to our adapter + phymode - + + ======================================================================== +*/ +VOID RTMPSetIndividualHT( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx) +{ + PRT_HT_PHY_INFO pDesired_ht_phy = NULL; + UCHAR TxStream = pAd->CommonCfg.TxStream; + UCHAR DesiredMcs = MCS_AUTO; + + do + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo; + DesiredMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; + //pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; + break; + } +#endif // CONFIG_STA_SUPPORT // + } while (FALSE); + + if (pDesired_ht_phy == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); + return; + } + RTMPZeroMemory(pDesired_ht_phy, sizeof(RT_HT_PHY_INFO)); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs)); + // Check the validity of MCS + if ((TxStream == 1) && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", DesiredMcs)); + DesiredMcs = MCS_7; + } + + if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) && (DesiredMcs == MCS_32)) + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n")); + DesiredMcs = MCS_0; + } + + pDesired_ht_phy->bHtEnable = TRUE; + + // Decide desired Tx MCS + switch (TxStream) + { + case 1: + if (DesiredMcs == MCS_AUTO) + { + pDesired_ht_phy->MCSSet[0]= 0xff; + pDesired_ht_phy->MCSSet[1]= 0x00; + } + else if (DesiredMcs <= MCS_7) + { + pDesired_ht_phy->MCSSet[0]= 1<MCSSet[1]= 0x00; + } + break; + + case 2: + if (DesiredMcs == MCS_AUTO) + { + pDesired_ht_phy->MCSSet[0]= 0xff; + pDesired_ht_phy->MCSSet[1]= 0xff; + } + else if (DesiredMcs <= MCS_15) + { + ULONG mode; + + mode = DesiredMcs / 8; + if (mode < 2) + pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); + } + break; + + case 3: // 3*3 + if (DesiredMcs == MCS_AUTO) + { + /* MCS0 ~ MCS23, 3 bytes */ + pDesired_ht_phy->MCSSet[0]= 0xff; + pDesired_ht_phy->MCSSet[1]= 0xff; + pDesired_ht_phy->MCSSet[2]= 0xff; + } + else if (DesiredMcs <= MCS_23) + { + ULONG mode; + + mode = DesiredMcs / 8; + if (mode < 3) + pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); + } + break; + } + + if(pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) + { + if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32) + pDesired_ht_phy->MCSSet[4] = 0x1; + } + + // update HT Rate setting + if (pAd->OpMode == OPMODE_STA) + MlmeUpdateHtTxRates(pAd, BSS0); + else + MlmeUpdateHtTxRates(pAd, apidx); +} + + +/* + ======================================================================== + Routine Description: + Update HT IE from our capability. + + Arguments: + Send all HT IE in beacon/probe rsp/assoc rsp/action frame. + + + ======================================================================== +*/ +VOID RTMPUpdateHTIE( + IN RT_HT_CAPABILITY *pRtHt, + IN UCHAR *pMcsSet, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo) +{ + RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE)); + RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE)); + + pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth; + pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs; + pHtCapability->HtCapInfo.GF = pRtHt->GF; + pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20; + pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40; + pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC; + pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC; + pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize; + pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor; + pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity; + + pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset ; + pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth; + pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode; + pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent; + RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet*/pMcsSet, 4); // rt2860 only support MCS max=32, no need to copy all 16 uchar. + + DBGPRINT(RT_DEBUG_TRACE,("RTMPUpdateHTIE <== \n")); +} +#endif // DOT11_N_SUPPORT // + +/* + ======================================================================== + Description: + Add Client security information into ASIC WCID table and IVEIV table. + Return: + ======================================================================== +*/ +VOID RTMPAddWcidAttributeEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN MAC_TABLE_ENTRY *pEntry) +{ + UINT32 WCIDAttri = 0; + USHORT offset; + UCHAR IVEIV = 0; + USHORT Wcid = 0; + + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (BssIdx > BSS0) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n", BssIdx)); + return; + } + + // 1. In ADHOC mode, the AID is wcid number. And NO mesh link exists. + // 2. In Infra mode, the AID:1 MUST be wcid of infra STA. + // the AID:2~ assign to mesh link entry. + if (pEntry && ADHOC_ON(pAd)) + Wcid = pEntry->Aid; + else if (pEntry && INFRA_ON(pAd)) + { +#ifdef QOS_DLS_SUPPORT + if (pEntry->ValidAsDls == TRUE) + Wcid = pEntry->Aid; + else +#endif // QOS_DLS_SUPPORT // + Wcid = BSSID_WCID; + } + else + Wcid = MCAST_WCID; + } +#endif // CONFIG_STA_SUPPORT // + } + + // Update WCID attribute table + offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pEntry && pEntry->ValidAsMesh) + WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE; +#ifdef QOS_DLS_SUPPORT + else if ((pEntry) && (pEntry->ValidAsDls) && + ((CipherAlg == CIPHER_TKIP) || + (CipherAlg == CIPHER_TKIP_NO_MIC) || + (CipherAlg == CIPHER_AES) || + (CipherAlg == CIPHER_NONE))) + WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE; +#endif // QOS_DLS_SUPPORT // + else + WCIDAttri = (CipherAlg<<1) | SHAREDKEYTABLE; + } +#endif // CONFIG_STA_SUPPORT // + + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); + + + // Update IV/EIV table + offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE); + + // WPA mode + if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) || (CipherAlg == CIPHER_AES)) + { + // Eiv bit on. keyid always is 0 for pairwise key + IVEIV = (KeyIdx <<6) | 0x20; + } + else + { + // WEP KeyIdx is default tx key. + IVEIV = (KeyIdx << 6); + } + + // For key index and ext IV bit, so only need to update the position(offset+3). +#ifdef RT2870 + RTUSBMultiWrite_OneByte(pAd, offset+3, &IVEIV); +#endif // RT2870 // + + DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE,(" WCIDAttri = 0x%x \n", WCIDAttri)); + +} + +/* + ========================================================================== + Description: + Parse encryption type +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + ========================================================================== +*/ +CHAR *GetEncryptType(CHAR enc) +{ + if(enc == Ndis802_11WEPDisabled) + return "NONE"; + if(enc == Ndis802_11WEPEnabled) + return "WEP"; + if(enc == Ndis802_11Encryption2Enabled) + return "TKIP"; + if(enc == Ndis802_11Encryption3Enabled) + return "AES"; + if(enc == Ndis802_11Encryption4Enabled) + return "TKIPAES"; + else + return "UNKNOW"; +} + +CHAR *GetAuthMode(CHAR auth) +{ + if(auth == Ndis802_11AuthModeOpen) + return "OPEN"; + if(auth == Ndis802_11AuthModeShared) + return "SHARED"; + if(auth == Ndis802_11AuthModeAutoSwitch) + return "AUTOWEP"; + if(auth == Ndis802_11AuthModeWPA) + return "WPA"; + if(auth == Ndis802_11AuthModeWPAPSK) + return "WPAPSK"; + if(auth == Ndis802_11AuthModeWPANone) + return "WPANONE"; + if(auth == Ndis802_11AuthModeWPA2) + return "WPA2"; + if(auth == Ndis802_11AuthModeWPA2PSK) + return "WPA2PSK"; + if(auth == Ndis802_11AuthModeWPA1WPA2) + return "WPA1WPA2"; + if(auth == Ndis802_11AuthModeWPA1PSKWPA2PSK) + return "WPA1PSKWPA2PSK"; + + return "UNKNOW"; +} + +#if 1 //#ifndef UCOS +/* + ========================================================================== + Description: + Get site survey results + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) UI needs to wait 4 seconds after issue a site survey command + 2.) iwpriv ra0 get_site_survey + 3.) UI needs to prepare at least 4096bytes to get the results + ========================================================================== +*/ +#define LINE_LEN (4+33+20+8+10+9+7+3) // Channel+SSID+Bssid+WepStatus+AuthMode+Signal+WiressMode+NetworkType +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // +VOID RTMPIoctlGetSiteSurvey( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + CHAR *msg; + INT i=0; + INT WaitCnt; + INT Status=0; + CHAR Ssid[MAX_LEN_OF_SSID +1]; + INT Rssi = 0, max_len = LINE_LEN; + UINT Rssi_Quality = 0; + NDIS_802_11_NETWORK_TYPE wireless_mode; + + os_alloc_mem(NULL, (PUCHAR *)&msg, sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len)); + + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - msg memory alloc fail.\n")); + return; + } + + memset(msg, 0 ,(MAX_LEN_OF_BSS_TABLE)*max_len ); + memset(Ssid, 0 ,(MAX_LEN_OF_SSID +1)); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"%-4s%-33s%-20s%-8s%-10s%-9s%-7s%-3s\n", + "Ch", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode", " NT"); + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + + WaitCnt = 0; +#ifdef CONFIG_STA_SUPPORT + pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; + while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200)) + OS_WAIT(500); +#endif // CONFIG_STA_SUPPORT // + + for(i=0; iScanTab.BssNr ;i++) + { + if( pAdapter->ScanTab.BssEntry[i].Channel==0) + break; + + if((strlen(msg)+max_len ) >= IW_SCAN_MAX_DATA) + break; + + //Channel + sprintf(msg+strlen(msg),"%-4d", pAdapter->ScanTab.BssEntry[i].Channel); + //SSID + memcpy(Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen); + Ssid[pAdapter->ScanTab.BssEntry[i].SsidLen] = '\0'; + sprintf(msg+strlen(msg),"%-33s", Ssid); + //BSSID + sprintf(msg+strlen(msg),"%02x:%02x:%02x:%02x:%02x:%02x ", + pAdapter->ScanTab.BssEntry[i].Bssid[0], + pAdapter->ScanTab.BssEntry[i].Bssid[1], + pAdapter->ScanTab.BssEntry[i].Bssid[2], + pAdapter->ScanTab.BssEntry[i].Bssid[3], + pAdapter->ScanTab.BssEntry[i].Bssid[4], + pAdapter->ScanTab.BssEntry[i].Bssid[5]); + //Encryption Type + sprintf(msg+strlen(msg),"%-8s",GetEncryptType(pAdapter->ScanTab.BssEntry[i].WepStatus)); + //Authentication Mode + if (pAdapter->ScanTab.BssEntry[i].WepStatus == Ndis802_11WEPEnabled) + sprintf(msg+strlen(msg),"%-10s", "UNKNOW"); + else + sprintf(msg+strlen(msg),"%-10s",GetAuthMode(pAdapter->ScanTab.BssEntry[i].AuthMode)); + // Rssi + Rssi = (INT)pAdapter->ScanTab.BssEntry[i].Rssi; + if (Rssi >= -50) + Rssi_Quality = 100; + else if (Rssi >= -80) // between -50 ~ -80dbm + Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10); + else if (Rssi >= -90) // between -80 ~ -90dbm + Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10); + else // < -84 dbm + Rssi_Quality = 0; + sprintf(msg+strlen(msg),"%-9d", Rssi_Quality); + // Wireless Mode + wireless_mode = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]); + if (wireless_mode == Ndis802_11FH || + wireless_mode == Ndis802_11DS) + sprintf(msg+strlen(msg),"%-7s", "11b"); + else if (wireless_mode == Ndis802_11OFDM5) + sprintf(msg+strlen(msg),"%-7s", "11a"); + else if (wireless_mode == Ndis802_11OFDM5_N) + sprintf(msg+strlen(msg),"%-7s", "11a/n"); + else if (wireless_mode == Ndis802_11OFDM24) + sprintf(msg+strlen(msg),"%-7s", "11b/g"); + else if (wireless_mode == Ndis802_11OFDM24_N) + sprintf(msg+strlen(msg),"%-7s", "11b/g/n"); + else + sprintf(msg+strlen(msg),"%-7s", "unknow"); + //Network Type + if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_ADHOC) + sprintf(msg+strlen(msg),"%-3s", " Ad"); + else + sprintf(msg+strlen(msg),"%-3s", " In"); + + sprintf(msg+strlen(msg),"\n"); +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + } + +#ifdef CONFIG_STA_SUPPORT + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; +#endif // CONFIG_STA_SUPPORT // + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", wrq->u.data.length)); + os_free_mem(NULL, (PUCHAR)msg); +} + + +#define MAC_LINE_LEN (14+4+4+10+10+10+6+6) // Addr+aid+psm+datatime+rxbyte+txbyte+current tx rate+last tx rate +VOID RTMPIoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN struct iwreq *wrq) +{ + INT i; + RT_802_11_MAC_TABLE MacTab; + char *msg; + + MacTab.Num = 0; + for (i=0; iMacTab.Content[i].ValidAsCLI && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) + { + COPY_MAC_ADDR(MacTab.Entry[MacTab.Num].Addr, &pAd->MacTab.Content[i].Addr); + MacTab.Entry[MacTab.Num].Aid = (UCHAR)pAd->MacTab.Content[i].Aid; + MacTab.Entry[MacTab.Num].Psm = pAd->MacTab.Content[i].PsMode; +#ifdef DOT11_N_SUPPORT + MacTab.Entry[MacTab.Num].MimoPs = pAd->MacTab.Content[i].MmpsMode; +#endif // DOT11_N_SUPPORT // + + // Fill in RSSI per entry + MacTab.Entry[MacTab.Num].AvgRssi0 = pAd->MacTab.Content[i].RssiSample.AvgRssi0; + MacTab.Entry[MacTab.Num].AvgRssi1 = pAd->MacTab.Content[i].RssiSample.AvgRssi1; + MacTab.Entry[MacTab.Num].AvgRssi2 = pAd->MacTab.Content[i].RssiSample.AvgRssi2; + + // the connected time per entry + MacTab.Entry[MacTab.Num].ConnectedTime = pAd->MacTab.Content[i].StaConnectTime; + MacTab.Entry[MacTab.Num].TxRate.field.MCS = pAd->MacTab.Content[i].HTPhyMode.field.MCS; + MacTab.Entry[MacTab.Num].TxRate.field.BW = pAd->MacTab.Content[i].HTPhyMode.field.BW; + MacTab.Entry[MacTab.Num].TxRate.field.ShortGI = pAd->MacTab.Content[i].HTPhyMode.field.ShortGI; + MacTab.Entry[MacTab.Num].TxRate.field.STBC = pAd->MacTab.Content[i].HTPhyMode.field.STBC; + MacTab.Entry[MacTab.Num].TxRate.field.rsv = pAd->MacTab.Content[i].HTPhyMode.field.rsv; + MacTab.Entry[MacTab.Num].TxRate.field.MODE = pAd->MacTab.Content[i].HTPhyMode.field.MODE; + MacTab.Entry[MacTab.Num].TxRate.word = pAd->MacTab.Content[i].HTPhyMode.word; + + MacTab.Num += 1; + } + } + wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE); + if (copy_to_user(wrq->u.data.pointer, &MacTab, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + msg = (CHAR *) kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG); + memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN ); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-10s%-10s%-10s%-6s%-6s\n", + "MAC", "AID", "PSM", "LDT", "RxB", "TxB","CTxR", "LTxR"); + + for (i=0; iMacTab.Content[i]; + if (pEntry->ValidAsCLI && (pEntry->Sst == SST_ASSOC)) + { + if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) ) + break; + sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode); + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); // ToDo + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); // ToDo + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); // ToDo + sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]); + sprintf(msg+strlen(msg),"%-6d\n",0/*RateIdToMbps[pAd->MacTab.Content[i].LastTxRate]*/); // ToDo + } + } + // for compatible with old API just do the printk to console + //wrq->u.data.length = strlen(msg); + //if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); + } + + kfree(msg); +} +#endif // UCOS // + +#ifdef DOT11_N_SUPPORT +INT Set_BASetup_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[6], tid; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + +/* + The BASetup inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + //printk("\n%s\n", arg); + + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + if (tid > 15) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], tid); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + printk("\nSetup BA Session: Tid = %d\n", tid); + BAOriSessionSetUp(pAd, pEntry, tid, 0, 100, TRUE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_BADecline_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG bBADecline; + + bBADecline = simple_strtol(arg, 0, 10); + + if (bBADecline == 0) + { + pAd->CommonCfg.bBADecline = FALSE; + } + else if (bBADecline == 1) + { + pAd->CommonCfg.bBADecline = TRUE; + } + else + { + return FALSE; //Invalid argument + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BADecline_Proc::(BADecline=%d)\n", pAd->CommonCfg.bBADecline)); + + return TRUE; +} + +INT Set_BAOriTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[6], tid; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + //printk("\n%s\n", arg); +/* + The BAOriTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + if (tid > NUM_OF_TID) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], tid); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + printk("\nTear down Ori BA Session: Tid = %d\n", tid); + BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, TRUE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_BARecTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[6], tid; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + //printk("\n%s\n", arg); +/* + The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + if (tid > NUM_OF_TID) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], tid); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + printk("\nTear down Rec BA Session: Tid = %d\n", tid); + BARecSessionTearDown(pAd, pEntry->Aid, tid, FALSE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG HtBw; + + HtBw = simple_strtol(arg, 0, 10); + if (HtBw == BW_40) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + else if (HtBw == BW_20) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBw_Proc::(HtBw=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.BW)); + + return TRUE; +} + +INT Set_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG HtMcs, Mcs_tmp; +#ifdef CONFIG_STA_SUPPORT + BOOLEAN bAutoRate = FALSE; +#endif // CONFIG_STA_SUPPORT // + + Mcs_tmp = simple_strtol(arg, 0, 10); + + if (Mcs_tmp <= 15 || Mcs_tmp == 32) + HtMcs = Mcs_tmp; + else + HtMcs = MCS_AUTO; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = HtMcs; + pAd->StaCfg.bAutoTxRateSwitch = (HtMcs == MCS_AUTO) ? TRUE:FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d, bAutoTxRateSwitch = %d)\n", + pAd->StaCfg.DesiredTransmitSetting.field.MCS, pAd->StaCfg.bAutoTxRateSwitch)); + + if ((pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE < MODE_HTMIX)) + { + if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && + (HtMcs >= 0 && HtMcs <= 3) && + (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_CCK)) + { + RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs] * 1000000)); + } + else if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) && + (HtMcs >= 0 && HtMcs <= 7) && + (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_OFDM)) + { + RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs+4] * 1000000)); + } + else + bAutoRate = TRUE; + + if (bAutoRate) + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + RTMPSetDesiredRates(pAd, -1); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(FixedTxMode=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode)); + } + if (ADHOC_ON(pAd)) + return TRUE; + } +#endif // CONFIG_STA_SUPPORT // + + SetCommonHT(pAd); + + return TRUE; +} + +INT Set_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG HtGi; + + HtGi = simple_strtol(arg, 0, 10); + + if ( HtGi == GI_400) + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; + else if ( HtGi == GI_800 ) + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtGi_Proc::(ShortGI=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.ShortGI)); + + return TRUE; +} + + +INT Set_HtTxBASize_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR Size; + + Size = simple_strtol(arg, 0, 10); + + if (Size <=0 || Size >=64) + { + Size = 8; + } + pAd->CommonCfg.TxBASize = Size-1; + DBGPRINT(RT_DEBUG_ERROR, ("Set_HtTxBASize ::(TxBASize= %d)\n", Size)); + + return TRUE; +} + + +INT Set_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == HTMODE_GF) + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; + else if ( Value == HTMODE_MM ) + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtOpMode_Proc::(HtOpMode=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.HTMODE)); + + return TRUE; + +} + +INT Set_HtStbc_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == STBC_USE) + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; + else if ( Value == STBC_NONE ) + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Stbc_Proc::(HtStbc=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.STBC)); + + return TRUE; +} + +INT Set_HtHtc_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->HTCEnable = FALSE; + else if ( Value ==1 ) + pAd->HTCEnable = TRUE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtHtc_Proc::(HtHtc=%d)\n",pAd->HTCEnable)); + + return TRUE; +} + +INT Set_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 0) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + else if ( Value ==1 ) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtExtcha_Proc::(HtExtcha=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)); + + return TRUE; +} + +INT Set_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value <=7 && Value >= 0) + pAd->CommonCfg.BACapability.field.MpduDensity = Value; + else + pAd->CommonCfg.BACapability.field.MpduDensity = 4; + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMpduDensity_Proc::(HtMpduDensity=%d)\n",pAd->CommonCfg.BACapability.field.MpduDensity)); + + return TRUE; +} + +INT Set_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + + if (Value >=1 && Value <= 64) + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; + } + else + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; + } + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBaWinSize_Proc::(HtBaWinSize=%d)\n",pAd->CommonCfg.BACapability.field.RxBAWinLimit)); + + return TRUE; +} + +INT Set_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 0) + pAd->CommonCfg.bRdg = FALSE; + else if ( Value ==1 ) + { + pAd->HTCEnable = TRUE; + pAd->CommonCfg.bRdg = TRUE; + } + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRdg_Proc::(HtRdg=%d)\n",pAd->CommonCfg.bRdg)); + + return TRUE; +} + +INT Set_HtLinkAdapt_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->bLinkAdapt = FALSE; + else if ( Value ==1 ) + { + pAd->HTCEnable = TRUE; + pAd->bLinkAdapt = TRUE; + } + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtLinkAdapt_Proc::(HtLinkAdapt=%d)\n",pAd->bLinkAdapt)); + + return TRUE; +} + +INT Set_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; + else if ( Value == 1 ) + pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAmsdu_Proc::(HtAmsdu=%d)\n",pAd->CommonCfg.BACapability.field.AmsduEnable)); + + return TRUE; +} + +INT Set_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; + } + else if (Value == 1) + { + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; + } + else + return FALSE; //Invalid argument + + pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; + pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy; + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAutoBa_Proc::(HtAutoBa=%d)\n",pAd->CommonCfg.BACapability.field.AutoBA)); + + return TRUE; + +} + +INT Set_HtProtect_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.bHTProtect = FALSE; + else if (Value == 1) + pAd->CommonCfg.bHTProtect = TRUE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtProtect_Proc::(HtProtect=%d)\n",pAd->CommonCfg.bHTProtect)); + + return TRUE; +} + +INT Set_SendPSMPAction_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[6], mode; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + //printk("\n%s\n", arg); +/* + The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the mode value. +*/ + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and mode value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + mode = simple_strtol((token+1), 0, 10); + if (mode > MMPS_ENABLE) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], mode); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + printk("\nSendPSMPAction MIPS mode = %d\n", mode); + SendPSMPAction(pAd, pEntry->Aid, mode); + } + + return TRUE; + } + + return FALSE; + + +} + +INT Set_HtMIMOPSmode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value <=3 && Value >= 0) + pAd->CommonCfg.BACapability.field.MMPSmode = Value; + else + pAd->CommonCfg.BACapability.field.MMPSmode = 3; + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMIMOPSmode_Proc::(MIMOPS mode=%d)\n",pAd->CommonCfg.BACapability.field.MMPSmode)); + + return TRUE; +} + + +INT Set_ForceShortGI_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->WIFItestbed.bShortGI = FALSE; + else if (Value == 1) + pAd->WIFItestbed.bShortGI = TRUE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceShortGI_Proc::(ForceShortGI=%d)\n", pAd->WIFItestbed.bShortGI)); + + return TRUE; +} + + + +INT Set_ForceGF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->WIFItestbed.bGreenField = FALSE; + else if (Value == 1) + pAd->WIFItestbed.bGreenField = TRUE; + else + return FALSE; //Invalid argument + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceGF_Proc::(ForceGF=%d)\n", pAd->WIFItestbed.bGreenField)); + + return TRUE; +} + +INT Set_HtMimoPs_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.bMIMOPSEnable = FALSE; + else if (Value == 1) + pAd->CommonCfg.bMIMOPSEnable = TRUE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMimoPs_Proc::(HtMimoPs=%d)\n",pAd->CommonCfg.bMIMOPSEnable)); + + return TRUE; +} +#endif // DOT11_N_SUPPORT // + + +#ifdef DOT11_N_SUPPORT +INT SetCommonHT( + IN PRTMP_ADAPTER pAd) +{ + OID_SET_HT_PHYMODE SetHT; + + if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) + return FALSE; + + SetHT.PhyMode = pAd->CommonCfg.PhyMode; + SetHT.TransmitNo = ((UCHAR)pAd->Antenna.field.TxPath); + SetHT.HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE; + SetHT.ExtOffset = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + SetHT.MCS = MCS_AUTO; + SetHT.BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW; + SetHT.STBC = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.STBC; + SetHT.SHORTGI = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.ShortGI; + + RTMPSetHT(pAd, &SetHT); + + return TRUE; +} +#endif // DOT11_N_SUPPORT // + +INT Set_FixedTxMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR fix_tx_mode = FIXED_TXMODE_HT; + + if (strcmp(arg, "OFDM") == 0 || strcmp(arg, "ofdm") == 0) + { + fix_tx_mode = FIXED_TXMODE_OFDM; + } + else if (strcmp(arg, "CCK") == 0 || strcmp(arg, "cck") == 0) + { + fix_tx_mode = FIXED_TXMODE_CCK; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("Set_FixedTxMode_Proc::(FixedTxMode=%d)\n", fix_tx_mode)); + + return TRUE; +} + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + +#ifdef RT2870 + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) +#endif // RT2870 // + { + DBGPRINT(RT_DEBUG_ERROR, ("Can not switch operate mode on interface up !! \n")); + return FALSE; + } + + if (Value == 0) + pAd->OpMode = OPMODE_STA; + else if (Value == 1) + pAd->OpMode = OPMODE_AP; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_OpMode_Proc::(OpMode=%s)\n", pAd->OpMode == 1 ? "AP Mode" : "STA Mode")); + + return TRUE; +} +#endif // CONFIG_APSTA_MIXED_SUPPORT // + + +///////////////////////////////////////////////////////////////////////// +PCHAR RTMPGetRalinkAuthModeStr( + IN NDIS_802_11_AUTHENTICATION_MODE authMode) +{ + switch(authMode) + { + case Ndis802_11AuthModeOpen: + return "OPEN"; + default: + case Ndis802_11AuthModeWPAPSK: + return "WPAPSK"; + case Ndis802_11AuthModeShared: + return "SHARED"; + case Ndis802_11AuthModeWPA: + return "WPA"; + case Ndis802_11AuthModeWPA2: + return "WPA2"; + case Ndis802_11AuthModeWPA2PSK: + return "WPA2PSK"; + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + return "WPAPSKWPA2PSK"; + case Ndis802_11AuthModeWPA1WPA2: + return "WPA1WPA2"; + } +} + +PCHAR RTMPGetRalinkEncryModeStr( + IN USHORT encryMode) +{ + switch(encryMode) + { + default: + case Ndis802_11WEPDisabled: + return "NONE"; + case Ndis802_11WEPEnabled: + return "WEP"; + case Ndis802_11Encryption2Enabled: + return "TKIP"; + case Ndis802_11Encryption3Enabled: + return "AES"; + case Ndis802_11Encryption4Enabled: + return "TKIPAES"; + } +} + +INT RTMPShowCfgValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pName, + IN PUCHAR pBuf) +{ + INT Status = 0; + + for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) + { + if (!strcmp(pName, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name)) + { + if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->show_proc(pAd, pBuf)) + Status = -EINVAL; + break; //Exit for loop. + } + } + + if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name == NULL) + { + sprintf(pBuf, "\n"); + for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++) + sprintf(pBuf, "%s%s\n", pBuf, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name); + } + + return Status; +} + +INT Show_SSID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + sprintf(pBuf, "\t%s", pAd->CommonCfg.Ssid); +#endif // CONFIG_STA_SUPPORT // + return 0; +} + +INT Show_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.PhyMode) + { + case PHY_11BG_MIXED: + sprintf(pBuf, "\t11B/G"); + break; + case PHY_11B: + sprintf(pBuf, "\t11B"); + break; + case PHY_11A: + sprintf(pBuf, "\t11A"); + break; + case PHY_11ABG_MIXED: + sprintf(pBuf, "\t11A/B/G"); + break; + case PHY_11G: + sprintf(pBuf, "\t11G"); + break; +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: + sprintf(pBuf, "\t11A/B/G/N"); + break; + case PHY_11N_2_4G: + sprintf(pBuf, "\t11N only with 2.4G"); + break; + case PHY_11GN_MIXED: + sprintf(pBuf, "\t11G/N"); + break; + case PHY_11AN_MIXED: + sprintf(pBuf, "\t11A/N"); + break; + case PHY_11BGN_MIXED: + sprintf(pBuf, "\t11B/G/N"); + break; + case PHY_11AGN_MIXED: + sprintf(pBuf, "\t11A/G/N"); + break; + case PHY_11N_5G: + sprintf(pBuf, "\t11N only with 5G"); + break; +#endif // DOT11_N_SUPPORT // + default: + sprintf(pBuf, "\tUnknow Value(%d)", pAd->CommonCfg.PhyMode); + break; + } + return 0; +} + + +INT Show_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.bEnableTxBurst ? "TRUE":"FALSE"); + return 0; +} + +INT Show_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.TxPreamble) + { + case Rt802_11PreambleShort: + sprintf(pBuf, "\tShort"); + break; + case Rt802_11PreambleLong: + sprintf(pBuf, "\tLong"); + break; + case Rt802_11PreambleAuto: + sprintf(pBuf, "\tAuto"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.TxPreamble); + break; + } + + return 0; +} + +INT Show_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%lu", pAd->CommonCfg.TxPowerPercentage); + return 0; +} + +INT Show_Channel_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%d", pAd->CommonCfg.Channel); + return 0; +} + +INT Show_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.UseBGProtection) + { + case 1: //Always On + sprintf(pBuf, "\tON"); + break; + case 2: //Always OFF + sprintf(pBuf, "\tOFF"); + break; + case 0: //AUTO + sprintf(pBuf, "\tAuto"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.UseBGProtection); + break; + } + return 0; +} + +INT Show_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%u", pAd->CommonCfg.RtsThreshold); + return 0; +} + +INT Show_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%u", pAd->CommonCfg.FragmentThreshold); + return 0; +} + +#ifdef DOT11_N_SUPPORT +INT Show_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + sprintf(pBuf, "\t40 MHz"); + } + else + { + sprintf(pBuf, "\t20 MHz"); + } + return 0; +} + +INT Show_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + sprintf(pBuf, "\t%u", pAd->StaCfg.DesiredTransmitSetting.field.MCS); +#endif // CONFIG_STA_SUPPORT // + return 0; +} + +INT Show_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.RegTransmitSetting.field.ShortGI) + { + case GI_400: + sprintf(pBuf, "\tGI_400"); + break; + case GI_800: + sprintf(pBuf, "\tGI_800"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.ShortGI); + break; + } + return 0; +} + +INT Show_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.RegTransmitSetting.field.HTMODE) + { + case HTMODE_GF: + sprintf(pBuf, "\tGF"); + break; + case HTMODE_MM: + sprintf(pBuf, "\tMM"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.HTMODE); + break; + } + return 0; +} + +INT Show_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA) + { + case EXTCHA_BELOW: + sprintf(pBuf, "\tBelow"); + break; + case EXTCHA_ABOVE: + sprintf(pBuf, "\tAbove"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.EXTCHA); + break; + } + return 0; +} + + +INT Show_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.MpduDensity); + return 0; +} + +INT Show_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.RxBAWinLimit); + return 0; +} + +INT Show_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.bRdg ? "TRUE":"FALSE"); + return 0; +} + +INT Show_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AmsduEnable ? "TRUE":"FALSE"); + return 0; +} + +INT Show_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AutoBA ? "TRUE":"FALSE"); + return 0; +} +#endif // DOT11_N_SUPPORT // + +INT Show_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegion); + return 0; +} + +INT Show_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegionForABand); + return 0; +} + +INT Show_CountryCode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.CountryCode); + return 0; +} + +#ifdef AGGREGATION_SUPPORT +INT Show_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.bAggregationCapable ? "TRUE":"FALSE"); + return 0; +} +#endif // AGGREGATION_SUPPORT // + +#ifdef WMM_SUPPORT +INT Show_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + sprintf(pBuf, "\t%s", pAd->CommonCfg.bWmmCapable ? "TRUE":"FALSE"); +#endif // CONFIG_STA_SUPPORT // + + return 0; +} +#endif // WMM_SUPPORT // + +INT Show_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + sprintf(pBuf, "\t%s", pAd->CommonCfg.bIEEE80211H ? "TRUE":"FALSE"); + return 0; +} + +#ifdef CONFIG_STA_SUPPORT +INT Show_NetworkType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + switch(pAd->StaCfg.BssType) + { + case BSS_ADHOC: + sprintf(pBuf, "\tAdhoc"); + break; + case BSS_INFRA: + sprintf(pBuf, "\tInfra"); + break; + case BSS_ANY: + sprintf(pBuf, "\tAny"); + break; + case BSS_MONITOR: + sprintf(pBuf, "\tMonitor"); + break; + default: + sprintf(pBuf, "\tUnknow Value(%d)", pAd->StaCfg.BssType); + break; + } + return 0; +} +#endif // CONFIG_STA_SUPPORT // + +INT Show_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeOpen; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + AuthMode = pAd->StaCfg.AuthMode; +#endif // CONFIG_STA_SUPPORT // + + if ((AuthMode >= Ndis802_11AuthModeOpen) && + (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + sprintf(pBuf, "\t%s", RTMPGetRalinkAuthModeStr(AuthMode)); + else + sprintf(pBuf, "\tUnknow Value(%d)", AuthMode); + + return 0; +} + +INT Show_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + NDIS_802_11_WEP_STATUS WepStatus = Ndis802_11WEPDisabled; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + WepStatus = pAd->StaCfg.WepStatus; +#endif // CONFIG_STA_SUPPORT // + + if ((WepStatus >= Ndis802_11WEPEnabled) && + (WepStatus <= Ndis802_11Encryption4KeyAbsent)) + sprintf(pBuf, "\t%s", RTMPGetRalinkEncryModeStr(WepStatus)); + else + sprintf(pBuf, "\tUnknow Value(%d)", WepStatus); + + return 0; +} + +INT Show_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + UCHAR DefaultKeyId = 0; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + DefaultKeyId = pAd->StaCfg.DefaultKeyId; +#endif // CONFIG_STA_SUPPORT // + + sprintf(pBuf, "\t%d", DefaultKeyId); + + return 0; +} + +INT Show_WepKey_Proc( + IN PRTMP_ADAPTER pAd, + IN INT KeyIdx, + OUT PUCHAR pBuf) +{ + UCHAR Key[16] = {0}, KeyLength = 0; + INT index = BSS0; + + KeyLength = pAd->SharedKey[index][KeyIdx].KeyLen; + NdisMoveMemory(Key, pAd->SharedKey[index][KeyIdx].Key, KeyLength); + + //check key string is ASCII or not + if (RTMPCheckStrPrintAble(Key, KeyLength)) + sprintf(pBuf, "\t%s", Key); + else + { + int idx; + sprintf(pBuf, "\t"); + for (idx = 0; idx < KeyLength; idx++) + sprintf(pBuf+strlen(pBuf), "%02X", Key[idx]); + } + return 0; +} + +INT Show_Key1_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + Show_WepKey_Proc(pAd, 0, pBuf); + return 0; +} + +INT Show_Key2_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + Show_WepKey_Proc(pAd, 1, pBuf); + return 0; +} + +INT Show_Key3_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + Show_WepKey_Proc(pAd, 2, pBuf); + return 0; +} + +INT Show_Key4_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + Show_WepKey_Proc(pAd, 3, pBuf); + return 0; +} + +INT Show_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf) +{ + INT idx; + UCHAR PMK[32] = {0}; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisMoveMemory(PMK, pAd->StaCfg.PMK, 32); +#endif // CONFIG_STA_SUPPORT // + + sprintf(pBuf, "\tPMK = "); + for (idx = 0; idx < 32; idx++) + sprintf(pBuf+strlen(pBuf), "%02X", PMK[idx]); + + return 0; +} + diff --git a/drivers/staging/rt3070/common/cmm_sanity.c b/drivers/staging/rt3070/common/cmm_sanity.c new file mode 100644 index 000000000000..6118df8de7bb --- /dev/null +++ b/drivers/staging/rt3070/common/cmm_sanity.c @@ -0,0 +1,1669 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + sanity.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 add WMM support +*/ +#include "../rt_config.h" + + +extern UCHAR CISCO_OUI[]; + +extern UCHAR WPA_OUI[]; +extern UCHAR RSN_OUI[]; +extern UCHAR WME_INFO_ELEM[]; +extern UCHAR WME_PARM_ELEM[]; +extern UCHAR Ccx2QosInfo[]; +extern UCHAR RALINK_OUI[]; +extern UCHAR BROADCOM_OUI[]; +extern UCHAR WPS_OUI[]; + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeAddBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2) +{ + PMLME_ADDBA_REQ_STRUCT pInfo; + + pInfo = (MLME_ADDBA_REQ_STRUCT *)Msg; + + if ((MsgLen != sizeof(MLME_ADDBA_REQ_STRUCT))) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } + + /* + if ((pInfo->BaBufSize > MAX_RX_REORDERBUF) || (pInfo->BaBufSize < 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - Rx Reordering buffer too big or too small\n")); + return FALSE; + } + */ + + if ((pInfo->pAddr[0]&0x01) == 0x01) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - broadcast address not support BA\n")); + return FALSE; + } + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeDelBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen) +{ + MLME_DELBA_REQ_STRUCT *pInfo; + pInfo = (MLME_DELBA_REQ_STRUCT *)Msg; + + if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT))) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } + + if ((pInfo->TID & 0xf0)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n")); + return FALSE; + } + + if (NdisEqualMemory(pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, MAC_ADDR_LEN) == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n")); + return FALSE; + } + + return TRUE; +} + +BOOLEAN PeerAddBAReqActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PFRAME_ADDBA_REQ pAddFrame; + pAddFrame = (PFRAME_ADDBA_REQ)(pMsg); + if (MsgLen < (sizeof(FRAME_ADDBA_REQ))) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + // we support immediate BA. + *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); + pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); + pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word); + + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); + DBGPRINT(RT_DEBUG_ERROR,("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, pAddFrame->BaParm.AMSDUSupported)); + return FALSE; + } + + // we support immediate BA. + if (pAddFrame->BaParm.TID &0xfff0) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request incorrect TID = %d\n", pAddFrame->BaParm.TID)); + return FALSE; + } + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + return TRUE; +} + +BOOLEAN PeerAddBARspActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen) +{ + //PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PFRAME_ADDBA_RSP pAddFrame; + + pAddFrame = (PFRAME_ADDBA_RSP)(pMsg); + if (MsgLen < (sizeof(FRAME_ADDBA_RSP))) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + // we support immediate BA. + *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); + pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode); + pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); + + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); + return FALSE; + } + + // we support immediate BA. + if (pAddFrame->BaParm.TID &0xfff0) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response incorrect TID = %d\n", pAddFrame->BaParm.TID)); + return FALSE; + } + return TRUE; + +} + +BOOLEAN PeerDelBAActionSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen ) +{ + //PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PFRAME_DELBA_REQ pDelFrame; + if (MsgLen != (sizeof(FRAME_DELBA_REQ))) + return FALSE; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + pDelFrame = (PFRAME_DELBA_REQ)(pMsg); + + *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm)); + pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode); + + if (pDelFrame->DelbaParm.TID &0xfff0) + return FALSE; + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerBeaconAndProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pBssType, + OUT USHORT *pBeaconPeriod, + OUT UCHAR *pChannel, + OUT UCHAR *pNewChannel, + OUT LARGE_INTEGER *pTimestamp, + OUT CF_PARM *pCfParm, + OUT USHORT *pAtimWin, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pErp, + OUT UCHAR *pDtimCount, + OUT UCHAR *pDtimPeriod, + OUT UCHAR *pBcastFlag, + OUT UCHAR *pMessageToMe, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR *pCkipFlag, + OUT UCHAR *pAironetCellPowerLimit, + OUT PEDCA_PARM pEdcaParm, + OUT PQBSS_LOAD_PARM pQbssLoad, + OUT PQOS_CAPABILITY_PARM pQosCapability, + OUT ULONG *pRalinkIe, + OUT UCHAR *pHtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + OUT UCHAR *pPreNHtCapabilityLen, +#endif // CONFIG_STA_SUPPORT // + OUT HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *AddHtInfoLen, + OUT ADD_HT_INFO_IE *AddHtInfo, + OUT UCHAR *NewExtChannelOffset, // Ht extension channel offset(above or below) + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE) +{ + CHAR *Ptr; +#ifdef CONFIG_STA_SUPPORT + CHAR TimLen; +#endif // CONFIG_STA_SUPPORT // + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + UCHAR SubType; + UCHAR Sanity; + //UCHAR ECWMin, ECWMax; + //MAC_CSR9_STRUC Csr9; + ULONG Length = 0; + + // For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel + // 1. If the AP is 11n enabled, then check the control channel. + // 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!!) + UCHAR CtrlChannel = 0; + + // Add for 3 necessary EID field check + Sanity = 0; + + *pAtimWin = 0; + *pErp = 0; + *pDtimCount = 0; + *pDtimPeriod = 0; + *pBcastFlag = 0; + *pMessageToMe = 0; + *pExtRateLen = 0; + *pCkipFlag = 0; // Default of CkipFlag is 0 + *pAironetCellPowerLimit = 0xFF; // Default of AironetCellPowerLimit is 0xFF + *LengthVIE = 0; // Set the length of VIE to init value 0 + *pHtCapabilityLen = 0; // Set the length of VIE to init value 0 +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + *pPreNHtCapabilityLen = 0; // Set the length of VIE to init value 0 +#endif // CONFIG_STA_SUPPORT // + *AddHtInfoLen = 0; // Set the length of VIE to init value 0 + *pRalinkIe = 0; + *pNewChannel = 0; + *NewExtChannelOffset = 0xff; //Default 0xff means no such IE + pCfParm->bValid = FALSE; // default: no IE_CF found + pQbssLoad->bValid = FALSE; // default: no IE_QBSS_LOAD found + pEdcaParm->bValid = FALSE; // default: no IE_EDCA_PARAMETER found + pQosCapability->bValid = FALSE; // default: no IE_QOS_CAPABILITY found + + pFrame = (PFRAME_802_11)Msg; + + // get subtype from header + SubType = (UCHAR)pFrame->Hdr.FC.SubType; + + // get Addr2 and BSSID from header + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); + +// hex_dump("Beacon", Msg, MsgLen); + + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + // get timestamp from payload and advance the pointer + NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); + + pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); + pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); + + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + // get beacon interval from payload and advance the pointer + NdisMoveMemory(pBeaconPeriod, Ptr, 2); + Ptr += 2; + Length += 2; + + // get capability info from payload and advance the pointer + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + Length += 2; + + if (CAP_IS_ESS_ON(*pCapabilityInfo)) + *pBssType = BSS_INFRA; + else + *pBssType = BSS_ADHOC; + + pEid = (PEID_STRUCT) Ptr; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= MsgLen) + { + // + // Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow. + // + if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", + (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); + break; + } + + switch(pEid->Eid) + { + case IE_SSID: + // Already has one SSID EID in this beacon, ignore the second one + if (Sanity & 0x1) + break; + if(pEid->Len <= MAX_LEN_OF_SSID) + { + NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); + *pSsidLen = pEid->Len; + Sanity |= 0x1; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); + return FALSE; + } + break; + + case IE_SUPP_RATES: + if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + Sanity |= 0x2; + NdisMoveMemory(SupRate, pEid->Octet, pEid->Len); + *pSupRateLen = pEid->Len; + + // TODO: 2004-09-14 not a good design here, cause it exclude extra rates + // from ScanTab. We should report as is. And filter out unsupported + // rates in MlmeAux. + // Check against the supported rates + // RTMPCheckRates(pAd, SupRate, pSupRateLen); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",pEid->Len)); + return FALSE; + } + break; + + case IE_HT_CAP: + if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! + { + NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); + *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + *pPreNHtCapabilityLen = 0; // Nnow we only support 26 bytes. + + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#endif // CONFIG_STA_SUPPORT // + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", pEid->Len)); + } + + break; + case IE_ADD_HT: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only + // copy first sizeof(ADD_HT_INFO_IE) + NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + + CtrlChannel = AddHtInfo->ControlChan; + + *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2)); + *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3)); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } +#endif // CONFIG_STA_SUPPORT // + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n")); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *NewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } + + break; + case IE_FH_PARM: + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n")); + break; + + case IE_DS_PARM: + if(pEid->Len == 1) + { + *pChannel = *pEid->Octet; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (ChannelSanity(pAd, *pChannel) == 0) + { + + return FALSE; + } + } +#endif // CONFIG_STA_SUPPORT // + Sanity |= 0x4; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n",pEid->Len)); + return FALSE; + } + break; + + case IE_CF_PARM: + if(pEid->Len == 6) + { + pCfParm->bValid = TRUE; + pCfParm->CfpCount = pEid->Octet[0]; + pCfParm->CfpPeriod = pEid->Octet[1]; + pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3]; + pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5]; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n")); + return FALSE; + } + break; + + case IE_IBSS_PARM: + if(pEid->Len == 2) + { + NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n")); + return FALSE; + } + break; + +#ifdef CONFIG_STA_SUPPORT + case IE_TIM: + if(INFRA_ON(pAd) && SubType == SUBTYPE_BEACON) + { + GetTimBit((PUCHAR)pEid, pAd->StaActive.Aid, &TimLen, pBcastFlag, pDtimCount, pDtimPeriod, pMessageToMe); + } + break; +#endif // CONFIG_STA_SUPPORT // + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + if(pEid->Len == 3) + { + *pNewChannel = pEid->Octet[1]; //extract new channel number + } + break; + + // New for WPA + // CCX v2 has the same IE, we need to parse that too + // Wifi WMM use the same IE vale, need to parse that too + // case IE_WPA: + case IE_VENDOR_SPECIFIC: + // Check Broadcom/Atheros 802.11n OUI version, for HT Capability IE. + // This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. + /*if (NdisEqualMemory(pEid->Octet, BROADCOM_OUI, 3) && (pEid->Len >= 4)) + { + if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 30)) + { + { + NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE)); + *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes. + } + } + if ((pEid->Octet[3] == OUI_BROADCOM_HT) && (pEid->Len >= 26)) + { + { + NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; // Nnow we only support 26 bytes. + } + } + } + */ + // Check the OUI version, filter out non-standard usage + if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7)) + { + //*pRalinkIe = pEid->Octet[3]; + if (pEid->Octet[3] != 0) + *pRalinkIe = pEid->Octet[3]; + else + *pRalinkIe = 0xf0000000; // Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. + } +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT + // This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan. + + // Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP, + // Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE + else if ((*pHtCapabilityLen == 0) && NdisEqualMemory(pEid->Octet, PRE_N_HT_OUI, 3) && (pEid->Len >= 4) && (pAd->OpMode == OPMODE_STA)) + { + if ((pEid->Octet[3] == OUI_PREN_HT_CAP) && (pEid->Len >= 30) && (*pHtCapabilityLen == 0)) + { + NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE)); + *pPreNHtCapabilityLen = SIZE_HT_CAP_IE; + } + + if ((pEid->Octet[3] == OUI_PREN_ADD_HT) && (pEid->Len >= 26)) + { + NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } + } +#endif // DOT11_N_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + { + // Copy to pVIE which will report to microsoft bssid list. + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + // parsing EDCA parameters + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; + pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; + pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN + pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin + pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax + pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us + ptr += 4; // point to next AC + } + } + else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) + { + // parsing EDCA parameters + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; + pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; + pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + + // use default EDCA parameter + pEdcaParm->bACM[QID_AC_BE] = 0; + pEdcaParm->Aifsn[QID_AC_BE] = 3; + pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS; + pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_BE] = 0; + + pEdcaParm->bACM[QID_AC_BK] = 0; + pEdcaParm->Aifsn[QID_AC_BK] = 7; + pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS; + pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_BK] = 0; + + pEdcaParm->bACM[QID_AC_VI] = 0; + pEdcaParm->Aifsn[QID_AC_VI] = 2; + pEdcaParm->Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1; + pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS; + pEdcaParm->Txop[QID_AC_VI] = 96; // AC_VI: 96*32us ~= 3ms + + pEdcaParm->bACM[QID_AC_VO] = 0; + pEdcaParm->Aifsn[QID_AC_VO] = 2; + pEdcaParm->Cwmin[QID_AC_VO] = CW_MIN_IN_BITS-2; + pEdcaParm->Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-1; + pEdcaParm->Txop[QID_AC_VO] = 48; // AC_VO: 48*32us ~= 1.5ms + } +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + else + { + } + + break; + + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + + // TODO: 2004-09-14 not a good design here, cause it exclude extra rates + // from ScanTab. We should report as is. And filter out unsupported + // rates in MlmeAux. + // Check against the supported rates + // RTMPCheckRates(pAd, ExtRate, pExtRateLen); + } + break; + + case IE_ERP: + if (pEid->Len == 1) + { + *pErp = (UCHAR)pEid->Octet[0]; + } + break; + + case IE_AIRONET_CKIP: + // 0. Check Aironet IE length, it must be larger or equal to 28 + // Cisco AP350 used length as 28 + // Cisco AP12XX used length as 30 + if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) + break; + + // 1. Copy CKIP flag byte to buffer for process + *pCkipFlag = *(pEid->Octet + 8); + break; + + case IE_AP_TX_POWER: + // AP Control of Client Transmit Power + //0. Check Aironet IE length, it must be 6 + if (pEid->Len != 0x06) + break; + + // Get cell power limit in dBm + if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) + *pAironetCellPowerLimit = *(pEid->Octet + 4); + break; + + // WPA2 & 802.11i RSN + case IE_RSN: + // There is no OUI for version anymore, check the group cipher OUI before copying + if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + { + // Copy to pVIE which will report to microsoft bssid list. + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; +#ifdef CONFIG_STA_SUPPORT +#ifdef EXT_BUILD_CHANNEL_LIST + case IE_COUNTRY: + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + break; +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // + default: + break; + } + + Length = Length + 2 + pEid->Len; // Eid[1] + Len[1]+ content[Len] + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + // For some 11a AP. it did not have the channel EID, patch here +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + UCHAR LatchRfChannel = MsgChannel; + if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) + { + if (CtrlChannel != 0) + *pChannel = CtrlChannel; + else + *pChannel = LatchRfChannel; + Sanity |= 0x4; + } + } +#endif // CONFIG_STA_SUPPORT // + + if (Sanity != 0x7) + { + DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", Sanity)); + return FALSE; + } + else + { + return TRUE; + } + +} + +#ifdef DOT11N_DRAFT3 +/* + ========================================================================== + Description: + MLME message sanity check for some IE addressed in 802.11n d3.03. + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerBeaconAndProbeRspSanity2( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *RegClass) +{ + CHAR *Ptr; + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + ULONG Length = 0; + + pFrame = (PFRAME_802_11)Msg; + + *RegClass = 0; + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + // get timestamp from payload and advance the pointer + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + // get beacon interval from payload and advance the pointer + Ptr += 2; + Length += 2; + + // get capability info from payload and advance the pointer + Ptr += 2; + Length += 2; + + pEid = (PEID_STRUCT) Ptr; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch(pEid->Eid) + { + case IE_SUPP_REG_CLASS: + if(pEid->Len > 0) + { + *RegClass = *pEid->Octet; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len)); + return FALSE; + } + break; + } + + Length = Length + 2 + pEid->Len; // Eid[1] + Len[1]+ content[Len] + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return TRUE; + +} +#endif // DOT11N_DRAFT3 // + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeScanReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pBssType, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pScanType) +{ + MLME_SCAN_REQ_STRUCT *Info; + + Info = (MLME_SCAN_REQ_STRUCT *)(Msg); + *pBssType = Info->BssType; + *pSsidLen = Info->SsidLen; + NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); + *pScanType = Info->ScanType; + + if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY) + && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE +#ifdef CONFIG_STA_SUPPORT + || *pScanType == SCAN_CISCO_PASSIVE || *pScanType == SCAN_CISCO_ACTIVE + || *pScanType == SCAN_CISCO_CHANNEL_LOAD || *pScanType == SCAN_CISCO_NOISE +#endif // CONFIG_STA_SUPPORT // + )) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqSanity fail - wrong BssType or ScanType\n")); + return FALSE; + } +} + +// IRQL = DISPATCH_LEVEL +UCHAR ChannelSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + int i; + + for (i = 0; i < pAd->ChannelListNum; i ++) + { + if (channel == pAd->ChannelList[i].Channel) + return 1; + } + return 0; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerDeauthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pReason) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + NdisMoveMemory(pReason, &pFrame->Octet[0], 2); + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerAuthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT USHORT *pAlg, + OUT USHORT *pSeq, + OUT USHORT *pStatus, + CHAR *pChlgText) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2); + NdisMoveMemory(pAlg, &pFrame->Octet[0], 2); + NdisMoveMemory(pSeq, &pFrame->Octet[2], 2); + NdisMoveMemory(pStatus, &pFrame->Octet[4], 2); + + if ((*pAlg == Ndis802_11AuthModeOpen) +#ifdef LEAP_SUPPORT + || (*pAlg == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) + { + if (*pSeq == 1 || *pSeq == 2) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } + else if (*pAlg == Ndis802_11AuthModeShared) + { + if (*pSeq == 1 || *pSeq == 4) + { + return TRUE; + } + else if (*pSeq == 2 || *pSeq == 3) + { + NdisMoveMemory(pChlgText, &pFrame->Octet[8], CIPHER_TEXT_LEN); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong algorithm\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeAuthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT ULONG *pTimeout, + OUT USHORT *pAlg) +{ + MLME_AUTH_REQ_STRUCT *pInfo; + + pInfo = (MLME_AUTH_REQ_STRUCT *)Msg; + COPY_MAC_ADDR(pAddr, pInfo->Addr); + *pTimeout = pInfo->Timeout; + *pAlg = pInfo->Alg; + + if (((*pAlg == Ndis802_11AuthModeShared) ||(*pAlg == Ndis802_11AuthModeOpen) +#ifdef LEAP_SUPPORT + || (*pAlg == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) && + ((*pAddr & 0x01) == 0)) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAuthReqSanity fail - wrong algorithm\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeAssocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pApAddr, + OUT USHORT *pCapabilityInfo, + OUT ULONG *pTimeout, + OUT USHORT *pListenIntv) +{ + MLME_ASSOC_REQ_STRUCT *pInfo; + + pInfo = (MLME_ASSOC_REQ_STRUCT *)Msg; + *pTimeout = pInfo->Timeout; // timeout + COPY_MAC_ADDR(pApAddr, pInfo->Addr); // AP address + *pCapabilityInfo = pInfo->CapabilityInfo; // capability info + *pListenIntv = pInfo->ListenIntv; + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerDisassocSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pReason) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + NdisMoveMemory(pReason, &pFrame->Octet[0], 2); + + return TRUE; +} + +/* + ======================================================================== + Routine Description: + Sanity check NetworkType (11b, 11g or 11a) + + Arguments: + pBss - Pointer to BSS table. + + Return Value: + Ndis802_11DS .......(11b) + Ndis802_11OFDM24....(11g) + Ndis802_11OFDM5.....(11a) + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( + IN PBSS_ENTRY pBss) +{ + NDIS_802_11_NETWORK_TYPE NetWorkType; + UCHAR rate, i; + + NetWorkType = Ndis802_11DS; + + if (pBss->Channel <= 14) + { + // + // First check support Rate. + // + for (i = 0; i < pBss->SupRateLen; i++) + { + rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit + if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) + { + continue; + } + else + { + // + // Otherwise (even rate > 108) means Ndis802_11OFDM24 + // + NetWorkType = Ndis802_11OFDM24; + break; + } + } + + // + // Second check Extend Rate. + // + if (NetWorkType != Ndis802_11OFDM24) + { + for (i = 0; i < pBss->ExtRateLen; i++) + { + rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit + if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) + { + continue; + } + else + { + // + // Otherwise (even rate > 108) means Ndis802_11OFDM24 + // + NetWorkType = Ndis802_11OFDM24; + break; + } + } + } + } + else + { + NetWorkType = Ndis802_11OFDM5; + } + + if (pBss->HtCapabilityLen != 0) + { + if (NetWorkType == Ndis802_11OFDM5) + NetWorkType = Ndis802_11OFDM5_N; + else + NetWorkType = Ndis802_11OFDM24_N; + } + + return NetWorkType; +} + +/* + ========================================================================== + Description: + WPA message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN PeerWpaMessageSanity( + IN PRTMP_ADAPTER pAd, + IN PEAPOL_PACKET pMsg, + IN ULONG MsgLen, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE]; + BOOLEAN bReplayDiff = FALSE; + BOOLEAN bWPA2 = FALSE; + KEY_INFO EapolKeyInfo; + UCHAR GroupKeyIndex = 0; + + + NdisZeroMemory(mic, sizeof(mic)); + NdisZeroMemory(digest, sizeof(digest)); + NdisZeroMemory(KEYDATA, sizeof(KEYDATA)); + NdisZeroMemory((PUCHAR)&EapolKeyInfo, sizeof(EapolKeyInfo)); + + NdisMoveMemory((PUCHAR)&EapolKeyInfo, (PUCHAR)&pMsg->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT *)&EapolKeyInfo) = cpu2le16(*((USHORT *)&EapolKeyInfo)); + + // Choose WPA2 or not + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; + + // 0. Check MsgType + if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1)) + { + DBGPRINT(RT_DEBUG_ERROR, ("The message type is invalid(%d)! \n", MsgType)); + return FALSE; + } + + // 1. Replay counter check + if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) // For supplicant + { + // First validate replay counter, only accept message with larger replay counter. + // Let equal pass, some AP start with all zero replay counter + UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; + + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + if ((RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY) != 1) && + (RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) + { + bReplayDiff = TRUE; + } + } + else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) // For authenticator + { + // check Replay Counter coresponds to MSG from authenticator, otherwise discard + if (!NdisEqualMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY)) + { + bReplayDiff = TRUE; + } + } + + // Replay Counter different condition + if (bReplayDiff) + { + // send wireless event - for replay counter different + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) + { + DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", MsgType)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + hex_dump("Current replay counter ", pEntry->R_Counter, LEN_KEY_DESC_REPLAY); + return FALSE; + } + + // 2. Verify MIC except Pairwise Msg1 + if (MsgType != EAPOL_PAIR_MSG_1) + { + UCHAR rcvd_mic[LEN_KEY_DESC_MIC]; + + // Record the received MIC for check later + NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) // TKIP + { + hmac_md5(pEntry->PTK, LEN_EAP_MICK, (PUCHAR)pMsg, MsgLen, mic); + } + else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled) // AES + { + HMAC_SHA1((PUCHAR)pMsg, MsgLen, pEntry->PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } + + if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC)) + { + // send wireless event - for MIC different + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_MIC_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + if (MsgType < EAPOL_GROUP_MSG_1) + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in pairwise msg %d of 4-way handshake!\n", MsgType)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4))); + } + + hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC); + hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC); + + return FALSE; + } + } + + // Extract the context of the Key Data field if it exist + // The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is un-encrypted. + // The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted. + if (pMsg->KeyDesc.KeyDataLen[1] > 0) + { + // Decrypt this field + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) + { + if(pEntry->WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + AES_GTK_KEY_UNWRAP(&pEntry->PTK[16], KEYDATA, pMsg->KeyDesc.KeyDataLen[1],pMsg->KeyDesc.KeyData); + } + else + { + INT i; + UCHAR Key[32]; + // Decrypt TKIP GTK + // Construct 32 bytes RC4 Key + NdisMoveMemory(Key, pMsg->KeyDesc.KeyIv, 16); + NdisMoveMemory(&Key[16], &pEntry->PTK[16], 16); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32); + //discard first 256 bytes + for(i = 0; i < 256; i++) + ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT); + // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg->KeyDesc.KeyData, pMsg->KeyDesc.KeyDataLen[1]); + } + + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + GroupKeyIndex = EapolKeyInfo.KeyIndex; + + } + else if ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2)) + { + NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, pMsg->KeyDesc.KeyDataLen[1]); + } + else + { + + return TRUE; + } + + // Parse Key Data field to + // 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2) + // 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2 + // 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2) + if (!RTMPParseEapolKeyData(pAd, KEYDATA, pMsg->KeyDesc.KeyDataLen[1], GroupKeyIndex, MsgType, bWPA2, pEntry)) + { + return FALSE; + } + } + + return TRUE; + +} + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +BOOLEAN MlmeDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_DLS *pDLS, + OUT PUSHORT pReason) +{ + MLME_DLS_REQ_STRUCT *pInfo; + + pInfo = (MLME_DLS_REQ_STRUCT *)Msg; + + *pDLS = pInfo->pDLS; + *pReason = pInfo->Reason; + + return TRUE; +} +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +#ifdef QOS_DLS_SUPPORT +BOOLEAN PeerDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pDlsTimeout, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability) +{ + CHAR *Ptr; + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + PEID_STRUCT eid_ptr; + + // to prevent caller from using garbage output value + *pCapabilityInfo = 0; + *pDlsTimeout = 0; + *pHtCapabilityLen = 0; + + Ptr = Fr->Octet; + + // offset to destination MAC address (Category and Action field) + Ptr += 2; + + // get DA from payload and advance the pointer + NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get SA from payload and advance the pointer + NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get capability info from payload and advance the pointer + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + + // get capability info from payload and advance the pointer + NdisMoveMemory(pDlsTimeout, Ptr, 2); + Ptr += 2; + + // Category and Action field + DA + SA + capability + Timeout + eid_ptr = (PEID_STRUCT) &Fr->Octet[18]; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_SUPP_RATES: + if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) + { + NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len); + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0])); + DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7])); + *pRatesLen = eid_ptr->Len; + } + else + { + *pRatesLen = 8; + Rates[0] = 0x82; + Rates[1] = 0x84; + Rates[2] = 0x8b; + Rates[3] = 0x96; + Rates[4] = 0x12; + Rates[5] = 0x24; + Rates[6] = 0x48; + Rates[7] = 0x6c; + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len)); + } + break; + + case IE_EXT_SUPP_RATES: + if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len); + *pRatesLen = (*pRatesLen) + eid_ptr->Len; + } + else + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen)); + *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES; + } + break; + + case IE_HT_CAP: + if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) + { + NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE)); + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE); + + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_HT_CAP\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); + } + break; + + default: + break; + } + + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN PeerDlsRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability) +{ + CHAR *Ptr; + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + PEID_STRUCT eid_ptr; + + // to prevent caller from using garbage output value + *pStatus = 0; + *pCapabilityInfo = 0; + *pHtCapabilityLen = 0; + + Ptr = Fr->Octet; + + // offset to destination MAC address (Category and Action field) + Ptr += 2; + + // get status code from payload and advance the pointer + NdisMoveMemory(pStatus, Ptr, 2); + Ptr += 2; + + // get DA from payload and advance the pointer + NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get SA from payload and advance the pointer + NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + if (pStatus == 0) + { + // get capability info from payload and advance the pointer + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + } + + // Category and Action field + status code + DA + SA + capability + eid_ptr = (PEID_STRUCT) &Fr->Octet[18]; + + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_SUPP_RATES: + if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0)) + { + NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len); + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0])); + DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7])); + *pRatesLen = eid_ptr->Len; + } + else + { + *pRatesLen = 8; + Rates[0] = 0x82; + Rates[1] = 0x84; + Rates[2] = 0x8b; + Rates[3] = 0x96; + Rates[4] = 0x12; + Rates[5] = 0x24; + Rates[6] = 0x48; + Rates[7] = 0x6c; + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len)); + } + break; + + case IE_EXT_SUPP_RATES: + if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len); + *pRatesLen = (*pRatesLen) + eid_ptr->Len; + } + else + { + NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen)); + *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES; + } + break; + + case IE_HT_CAP: + if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) + { + NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE)); + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE); + + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_HT_CAP\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); + } + break; + + default: + break; + } + + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return TRUE; +} + +BOOLEAN PeerDlsTearDownSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pReason) +{ + CHAR *Ptr; + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + + // to prevent caller from using garbage output value + *pReason = 0; + + Ptr = Fr->Octet; + + // offset to destination MAC address (Category and Action field) + Ptr += 2; + + // get DA from payload and advance the pointer + NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get SA from payload and advance the pointer + NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN); + Ptr += MAC_ADDR_LEN; + + // get reason code from payload and advance the pointer + NdisMoveMemory(pReason, Ptr, 2); + Ptr += 2; + + return TRUE; +} +#endif // QOS_DLS_SUPPORT // + diff --git a/drivers/staging/rt3070/common/cmm_sync.c b/drivers/staging/rt3070/common/cmm_sync.c new file mode 100644 index 000000000000..2be7c77a384e --- /dev/null +++ b/drivers/staging/rt3070/common/cmm_sync.c @@ -0,0 +1,711 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + sync.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 modified for rt2561/2661 +*/ +#include "../rt_config.h" + +// 2.4 Ghz channel plan index in the TxPower arrays. +#define BG_BAND_REGION_0_START 0 // 1,2,3,4,5,6,7,8,9,10,11 +#define BG_BAND_REGION_0_SIZE 11 +#define BG_BAND_REGION_1_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13 +#define BG_BAND_REGION_1_SIZE 13 +#define BG_BAND_REGION_2_START 9 // 10,11 +#define BG_BAND_REGION_2_SIZE 2 +#define BG_BAND_REGION_3_START 9 // 10,11,12,13 +#define BG_BAND_REGION_3_SIZE 4 +#define BG_BAND_REGION_4_START 13 // 14 +#define BG_BAND_REGION_4_SIZE 1 +#define BG_BAND_REGION_5_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14 +#define BG_BAND_REGION_5_SIZE 14 +#define BG_BAND_REGION_6_START 2 // 3,4,5,6,7,8,9 +#define BG_BAND_REGION_6_SIZE 7 +#define BG_BAND_REGION_7_START 4 // 5,6,7,8,9,10,11,12,13 +#define BG_BAND_REGION_7_SIZE 9 +#define BG_BAND_REGION_31_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14 +#define BG_BAND_REGION_31_SIZE 14 + +// 5 Ghz channel plan index in the TxPower arrays. +UCHAR A_BAND_REGION_0_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_1_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; +UCHAR A_BAND_REGION_2_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64}; +UCHAR A_BAND_REGION_3_CHANNEL_LIST[]={52, 56, 60, 64, 149, 153, 157, 161}; +UCHAR A_BAND_REGION_4_CHANNEL_LIST[]={149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_5_CHANNEL_LIST[]={149, 153, 157, 161}; +UCHAR A_BAND_REGION_6_CHANNEL_LIST[]={36, 40, 44, 48}; +UCHAR A_BAND_REGION_7_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_8_CHANNEL_LIST[]={52, 56, 60, 64}; +UCHAR A_BAND_REGION_9_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_10_CHANNEL_LIST[]={36, 40, 44, 48, 149, 153, 157, 161, 165}; +UCHAR A_BAND_REGION_11_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161}; + +//BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8. +UCHAR BaSizeArray[4] = {8,16,32,64}; + +/* + ========================================================================== + Description: + Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type, + and 3) PHY-mode user selected. + The outcome is used by driver when doing site survey. + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID BuildChannelList( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i, j, index=0, num=0; + PUCHAR pChannelList = NULL; + + NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); + + // if not 11a-only mode, channel list starts from 2.4Ghz band + if ((pAd->CommonCfg.PhyMode != PHY_11A) +#ifdef DOT11_N_SUPPORT + && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G) +#endif // DOT11_N_SUPPORT // + ) + { + switch (pAd->CommonCfg.CountryRegion & 0x7f) + { + case REGION_0_BG_BAND: // 1 -11 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_0_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_0_SIZE); + index += BG_BAND_REGION_0_SIZE; + break; + case REGION_1_BG_BAND: // 1 - 13 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_1_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_1_SIZE); + index += BG_BAND_REGION_1_SIZE; + break; + case REGION_2_BG_BAND: // 10 - 11 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_2_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_2_SIZE); + index += BG_BAND_REGION_2_SIZE; + break; + case REGION_3_BG_BAND: // 10 - 13 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_3_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_3_SIZE); + index += BG_BAND_REGION_3_SIZE; + break; + case REGION_4_BG_BAND: // 14 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_4_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_4_SIZE); + index += BG_BAND_REGION_4_SIZE; + break; + case REGION_5_BG_BAND: // 1 - 14 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_5_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_5_SIZE); + index += BG_BAND_REGION_5_SIZE; + break; + case REGION_6_BG_BAND: // 3 - 9 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_6_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_6_SIZE); + index += BG_BAND_REGION_6_SIZE; + break; + case REGION_7_BG_BAND: // 5 - 13 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_7_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_7_SIZE); + index += BG_BAND_REGION_7_SIZE; + break; + case REGION_31_BG_BAND: // 1 - 14 + NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_31_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_31_SIZE); + index += BG_BAND_REGION_31_SIZE; + break; + default: // Error. should never happen + break; + } + for (i=0; iChannelList[i].MaxTxPwr = 20; + } + + if ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) + || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G) +#endif // DOT11_N_SUPPORT // + ) + { + switch (pAd->CommonCfg.CountryRegionForABand & 0x7f) + { + case REGION_0_A_BAND: + num = sizeof(A_BAND_REGION_0_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_0_CHANNEL_LIST; + break; + case REGION_1_A_BAND: + num = sizeof(A_BAND_REGION_1_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_1_CHANNEL_LIST; + break; + case REGION_2_A_BAND: + num = sizeof(A_BAND_REGION_2_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_2_CHANNEL_LIST; + break; + case REGION_3_A_BAND: + num = sizeof(A_BAND_REGION_3_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_3_CHANNEL_LIST; + break; + case REGION_4_A_BAND: + num = sizeof(A_BAND_REGION_4_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_4_CHANNEL_LIST; + break; + case REGION_5_A_BAND: + num = sizeof(A_BAND_REGION_5_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_5_CHANNEL_LIST; + break; + case REGION_6_A_BAND: + num = sizeof(A_BAND_REGION_6_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_6_CHANNEL_LIST; + break; + case REGION_7_A_BAND: + num = sizeof(A_BAND_REGION_7_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_7_CHANNEL_LIST; + break; + case REGION_8_A_BAND: + num = sizeof(A_BAND_REGION_8_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_8_CHANNEL_LIST; + break; + case REGION_9_A_BAND: + num = sizeof(A_BAND_REGION_9_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_9_CHANNEL_LIST; + break; + + case REGION_10_A_BAND: + num = sizeof(A_BAND_REGION_10_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_10_CHANNEL_LIST; + break; + + case REGION_11_A_BAND: + num = sizeof(A_BAND_REGION_11_CHANNEL_LIST)/sizeof(UCHAR); + pChannelList = A_BAND_REGION_11_CHANNEL_LIST; + break; + + default: // Error. should never happen + DBGPRINT(RT_DEBUG_WARN,("countryregion=%d not support", pAd->CommonCfg.CountryRegionForABand)); + break; + } + + if (num != 0) + { + UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; + for (i=0; iTxPower[j].Channel) + NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); + } + for (j=0; j<15; j++) + { + if (pChannelList[i] == RadarCh[j]) + pAd->ChannelList[index+i].DfsReq = TRUE; + } + pAd->ChannelList[index+i].MaxTxPwr = 20; + } + index += num; + } + } + + pAd->ChannelListNum = index; + DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n", + pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum)); +#ifdef DBG + for (i=0;iChannelListNum;i++) + { + DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ", pAd->ChannelList[i].Channel, pAd->ChannelList[i].Power, pAd->ChannelList[i].Power2)); + } +#endif +} + +/* + ========================================================================== + Description: + This routine return the first channel number according to the country + code selection and RF IC selection (signal band or dual band). It is called + whenever driver need to start a site survey of all supported channels. + Return: + ch - the first channel number of current country code setting + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +UCHAR FirstChannel( + IN PRTMP_ADAPTER pAd) +{ + return pAd->ChannelList[0].Channel; +} + +/* + ========================================================================== + Description: + This routine returns the next channel number. This routine is called + during driver need to start a site survey of all supported channels. + Return: + next_channel - the next channel number valid in current country code setting. + Note: + return 0 if no more next channel + ========================================================================== + */ +UCHAR NextChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + int i; + UCHAR next_channel = 0; + + for (i = 0; i < (pAd->ChannelListNum - 1); i++) + if (channel == pAd->ChannelList[i].Channel) + { + next_channel = pAd->ChannelList[i+1].Channel; + break; + } + return next_channel; +} + +/* + ========================================================================== + Description: + This routine is for Cisco Compatible Extensions 2.X + Spec31. AP Control of Client Transmit Power + Return: + None + Note: + Required by Aironet dBm(mW) + 0dBm(1mW), 1dBm(5mW), 13dBm(20mW), 15dBm(30mW), + 17dBm(50mw), 20dBm(100mW) + + We supported + 3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%), + 14dBm(75%), 15dBm(100%) + + The client station's actual transmit power shall be within +/- 5dB of + the minimum value or next lower value. + ========================================================================== + */ +VOID ChangeToCellPowerLimit( + IN PRTMP_ADAPTER pAd, + IN UCHAR AironetCellPowerLimit) +{ + //valud 0xFF means that hasn't found power limit information + //from the AP's Beacon/Probe response. + if (AironetCellPowerLimit == 0xFF) + return; + + if (AironetCellPowerLimit < 6) //Used Lowest Power Percentage. + pAd->CommonCfg.TxPowerPercentage = 6; + else if (AironetCellPowerLimit < 9) + pAd->CommonCfg.TxPowerPercentage = 10; + else if (AironetCellPowerLimit < 12) + pAd->CommonCfg.TxPowerPercentage = 25; + else if (AironetCellPowerLimit < 14) + pAd->CommonCfg.TxPowerPercentage = 50; + else if (AironetCellPowerLimit < 15) + pAd->CommonCfg.TxPowerPercentage = 75; + else + pAd->CommonCfg.TxPowerPercentage = 100; //else used maximum + + if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault) + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + +} + +CHAR ConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + + // Rssi equals to zero should be an invalid value + if (Rssi == 0) + return -99; + + LNAGain = GET_LNA_GAIN(pAd); + if (pAd->LatchRfRegs.Channel > 14) + { + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + return (-12 - RssiOffset - LNAGain - Rssi); +} + +/* + ========================================================================== + Description: + Scan next channel + ========================================================================== + */ +VOID ScanNextChannel( + IN PRTMP_ADAPTER pAd) +{ + HEADER_802_11 Hdr80211; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + UCHAR SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0; +#ifdef CONFIG_STA_SUPPORT + USHORT Status; + PHEADER_802_11 pHdr80211; +#endif // CONFIG_STA_SUPPORT // + UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (MONITOR_ON(pAd)) + return; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef RALINK_ATE + // Nothing to do in ATE mode. + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + if (pAd->MlmeAux.Channel == 0) + { + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) +#ifdef CONFIG_STA_SUPPORT + && (INFRA_ON(pAd) + || (pAd->OpMode == OPMODE_AP)) +#endif // CONFIG_STA_SUPPORT // + ) + { + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); + } + else + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr)); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // + // To prevent data lost. + // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. + // Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done + // + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) + { + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) + { + pHdr80211 = (PHEADER_802_11) pOutBuffer; + MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pHdr80211->Duration = 0; + pHdr80211->FC.Type = BTYPE_DATA; + pHdr80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame\n")); + MlmeFreeMemory(pAd, pOutBuffer); + RTMPusecDelay(5000); + } + } + + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); + } +#endif // CONFIG_STA_SUPPORT // + + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + } +#ifdef RT2870 +#ifdef CONFIG_STA_SUPPORT + else if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->OpMode == OPMODE_STA)) + { + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + MlmeCntlConfirm(pAd, MT2_SCAN_CONF, MLME_FAIL_NO_RESOURCE); + } +#endif // CONFIG_STA_SUPPORT // +#endif // RT2870 // + else + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // BBP and RF are not accessible in PS mode, we has to wake them up first + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + AsicForceWakeup(pAd, TRUE); + + // leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON + if (pAd->StaCfg.Psm == PWR_SAVE) + MlmeSetPsmBit(pAd, PWR_ACTIVE); + } +#endif // CONFIG_STA_SUPPORT // + + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->MlmeAux.Channel > 14) + { + if ((pAd->CommonCfg.bIEEE80211H == 1) && RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) + { + ScanType = SCAN_PASSIVE; + ScanTimeIn5gChannel = MIN_CHANNEL_TIME; + } + } + +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + // carrier detection + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + ScanType = SCAN_PASSIVE; + ScanTimeIn5gChannel = MIN_CHANNEL_TIME; + } +#endif // CARRIER_DETECTION_SUPPORT // + } + +#endif // CONFIG_STA_SUPPORT // + + //Global country domain(ch1-11:active scan, ch12-14 passive scan) + if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12) && ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_31_BG_BAND)) + { + ScanType = SCAN_PASSIVE; + } + + // We need to shorten active scan time in order for WZC connect issue + // Chnage the channel scan time for CISCO stuff based on its IAPP announcement + if (ScanType == FAST_SCAN_ACTIVE) + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, FAST_ACTIVE_SCAN_TIME); +#ifdef CONFIG_STA_SUPPORT + else if (((ScanType == SCAN_CISCO_ACTIVE) || + (ScanType == SCAN_CISCO_PASSIVE) || + (ScanType == SCAN_CISCO_CHANNEL_LOAD) || + (ScanType == SCAN_CISCO_NOISE)) && (pAd->OpMode == OPMODE_STA)) + { + if (pAd->StaCfg.CCXScanTime < 25) + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime * 2); + else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime); + } +#endif // CONFIG_STA_SUPPORT // + else // must be SCAN_PASSIVE or SCAN_ACTIVE + { + if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) +#endif // DOT11_N_SUPPORT // + ) + { + if (pAd->MlmeAux.Channel > 14) + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, ScanTimeIn5gChannel); + else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MIN_CHANNEL_TIME); + } + else + RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MAX_CHANNEL_TIME); + } + + if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) || + (ScanType == SCAN_CISCO_ACTIVE)) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); + } +#endif // CONFIG_STA_SUPPORT // + + return; + } + + // There is no need to send broadcast probe request if active scan is in effect. + if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) + ) + SsidLen = pAd->MlmeAux.SsidLen; + else + SsidLen = 0; + + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, + END_OF_ARGS); + + if (pAd->CommonCfg.ExtRateLen) + { + ULONG Tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } + +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + ULONG Tmp; + UCHAR HtLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + if (pAd->bBroadComHT == TRUE) + { + HtLen = pAd->MlmeAux.HtCapabilityLen + 4; +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); +#endif // RT_BIG_ENDIAN // + } + else + { + HtLen = pAd->MlmeAux.HtCapabilityLen; +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#endif // RT_BIG_ENDIAN // + } + FrameLen += Tmp; + +#ifdef DOT11N_DRAFT3 + if (pAd->CommonCfg.BACapability.field.b2040CoexistScanSup == 1) + { + ULONG Tmp; + HtLen = 1; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtHtCapIe, + 1, &HtLen, + 1, &pAd->CommonCfg.BSSCoexist2040.word, + END_OF_ARGS); + + FrameLen += Tmp; + } +#endif // DOT11N_DRAFT3 // + } +#endif // DOT11_N_SUPPORT // + + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + + // For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN; +#endif // CONFIG_STA_SUPPORT // + + } +} + +VOID MgtProbReqMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SubType; + if (SubType == SUBTYPE_ACK) + pHdr80211->FC.Type = BTYPE_CNTL; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); +} + + diff --git a/drivers/staging/rt3070/common/cmm_wpa.c b/drivers/staging/rt3070/common/cmm_wpa.c new file mode 100644 index 000000000000..81c332ac2524 --- /dev/null +++ b/drivers/staging/rt3070/common/cmm_wpa.c @@ -0,0 +1,1606 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + wpa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 03-07-22 Initial + Paul Lin 03-11-28 Modify for supplicant +*/ +#include "../rt_config.h" +// WPA OUI +UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00}; +UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02}; +UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04}; +UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02}; +// WPA2 OUI +UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01}; +UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02}; +UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04}; +UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01}; +UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02}; +// MSA OUI +UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06 +UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06 + +/* + ======================================================================== + + Routine Description: + The pseudo-random function(PRF) that hashes various inputs to + derive a pseudo-random value. To add liveness to the pseudo-random + value, a nonce should be one of the inputs. + + It is used to generate PTK, GTK or some specific random value. + + Arguments: + UCHAR *key, - the key material for HMAC_SHA1 use + INT key_len - the length of key + UCHAR *prefix - a prefix label + INT prefix_len - the length of the label + UCHAR *data - a specific data with variable length + INT data_len - the length of a specific data + INT len - the output lenght + + Return Value: + UCHAR *output - the calculated result + + Note: + 802.11i-2004 Annex H.3 + + ======================================================================== +*/ +VOID PRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *prefix, + IN INT prefix_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len) +{ + INT i; + UCHAR *input; + INT currentindex = 0; + INT total_len; + + // Allocate memory for input + os_alloc_mem(NULL, (PUCHAR *)&input, 1024); + + if (input == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n")); + return; + } + + // Generate concatenation input + NdisMoveMemory(input, prefix, prefix_len); + + // Concatenate a single octet containing 0 + input[prefix_len] = 0; + + // Concatenate specific data + NdisMoveMemory(&input[prefix_len + 1], data, data_len); + total_len = prefix_len + 1 + data_len; + + // Concatenate a single octet containing 0 + // This octet shall be update later + input[total_len] = 0; + total_len++; + + // Iterate to calculate the result by hmac-sha-1 + // Then concatenate to last result + for (i = 0; i < (len + 19) / 20; i++) + { + HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]); + currentindex += 20; + + // update the last octet + input[total_len - 1]++; + } + os_free_mem(NULL, input); +} + +/* + ======================================================================== + + Routine Description: + It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK. + It shall be called by 4-way handshake processing. + + Arguments: + pAd - pointer to our pAdapter context + PMK - pointer to PMK + ANonce - pointer to ANonce + AA - pointer to Authenticator Address + SNonce - pointer to SNonce + SA - pointer to Supplicant Address + len - indicate the length of PTK (octet) + + Return Value: + Output pointer to the PTK + + Note: + Refer to IEEE 802.11i-2004 8.5.1.2 + + ======================================================================== +*/ +VOID WpaCountPTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len) +{ + UCHAR concatenation[76]; + UINT CurrPos = 0; + UCHAR temp[32]; + UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', + 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; + + // initiate the concatenation input + NdisZeroMemory(temp, sizeof(temp)); + NdisZeroMemory(concatenation, 76); + + // Get smaller address + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(concatenation, AA, 6); + else + NdisMoveMemory(concatenation, SA, 6); + CurrPos += 6; + + // Get larger address + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(&concatenation[CurrPos], SA, 6); + else + NdisMoveMemory(&concatenation[CurrPos], AA, 6); + + // store the larger mac address for backward compatible of + // ralink proprietary STA-key issue + NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); + CurrPos += 6; + + // Get smaller Nonce + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + CurrPos += 32; + + // Get larger Nonce + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + CurrPos += 32; + + hex_dump("concatenation=", concatenation, 76); + + // Use PRF to generate PTK + PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len); + +} + +/* + ======================================================================== + + Routine Description: + Generate random number by software. + + Arguments: + pAd - pointer to our pAdapter context + macAddr - pointer to local MAC address + + Return Value: + + Note: + 802.1ii-2004 Annex H.5 + + ======================================================================== +*/ +VOID GenRandom( + IN PRTMP_ADAPTER pAd, + IN UCHAR *macAddr, + OUT UCHAR *random) +{ + INT i, curr; + UCHAR local[80], KeyCounter[32]; + UCHAR result[80]; + ULONG CurrentTime; + UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'}; + + // Zero the related information + NdisZeroMemory(result, 80); + NdisZeroMemory(local, 80); + NdisZeroMemory(KeyCounter, 32); + + for (i = 0; i < 32; i++) + { + // copy the local MAC address + COPY_MAC_ADDR(local, macAddr); + curr = MAC_ADDR_LEN; + + // concatenate the current time + NdisGetSystemUpTime(&CurrentTime); + NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime)); + curr += sizeof(CurrentTime); + + // concatenate the last result + NdisMoveMemory(&local[curr], result, 32); + curr += 32; + + // concatenate a variable + NdisMoveMemory(&local[curr], &i, 2); + curr += 2; + + // calculate the result + PRF(KeyCounter, 32, prefix,12, local, curr, result, 32); + } + + NdisMoveMemory(random, result, 32); +} + +/* + ======================================================================== + + Routine Description: + Build cipher suite in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + WepStatus - indicate the encryption type + bMixCipher - a boolean to indicate the pairwise cipher and group + cipher are the same or not + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPInsertRsnIeCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UINT WepStatus, + IN BOOLEAN bMixCipher, + IN UCHAR FlexibleCipher, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + UCHAR PairwiseCnt; + + *rsn_len = 0; + + // decide WPA2 or WPA1 + if (ElementID == Wpa2Ie) + { + RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe; + + // Assign the verson as 1 + pRsnie_cipher->version = 1; + + switch (WepStatus) + { + // TKIP mode + case Ndis802_11Encryption2Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); + *rsn_len = sizeof(RSNIE2); + break; + + // AES mode + case Ndis802_11Encryption3Enabled: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); + *rsn_len = sizeof(RSNIE2); + break; + + // TKIP-AES mix mode + case Ndis802_11Encryption4Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + + PairwiseCnt = 1; + // Insert WPA2 TKIP as the first pairwise cipher + if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); + // Insert WPA2 AES as the secondary pairwise cipher + if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4); + PairwiseCnt = 2; + } + } + else + { + // Insert WPA2 AES as the first pairwise cipher + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); + } + + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1)); + break; + } + + // swap for big-endian platform + pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + } + else + { + RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe; + + // Assign OUI and version + NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); + pRsnie_cipher->version = 1; + + switch (WepStatus) + { + // TKIP mode + case Ndis802_11Encryption2Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); + *rsn_len = sizeof(RSNIE); + break; + + // AES mode + case Ndis802_11Encryption3Enabled: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); + *rsn_len = sizeof(RSNIE); + break; + + // TKIP-AES mix mode + case Ndis802_11Encryption4Enabled: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + + PairwiseCnt = 1; + // Insert WPA TKIP as the first pairwise cipher + if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); + // Insert WPA AES as the secondary pairwise cipher + if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4); + PairwiseCnt = 2; + } + } + else + { + // Insert WPA AES as the first pairwise cipher + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); + } + + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1)); + break; + } + + // swap for big-endian platform + pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + } + +} + +/* + ======================================================================== + + Routine Description: + Build AKM suite in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + AuthMode - indicate the authentication mode + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPInsertRsnIeAKM( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UINT AuthMode, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + RSNIE_AUTH *pRsnie_auth; + + pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len)); + + // decide WPA2 or WPA1 + if (ElementID == Wpa2Ie) + { + switch (AuthMode) + { + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA1WPA2: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4); + break; + + case Ndis802_11AuthModeWPA2PSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4); + break; + } + } + else + { + switch (AuthMode) + { + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPA1WPA2: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4); + break; + + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4); + break; + + case Ndis802_11AuthModeWPANone: + pRsnie_auth->acount = 1; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4); + break; + } + } + + pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount); + + (*rsn_len) += sizeof(RSNIE_AUTH); // update current RSNIE length + +} + +/* + ======================================================================== + + Routine Description: + Build capability in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPInsertRsnIeCap( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + RSN_CAPABILITIES *pRSN_Cap; + + // it could be ignored in WPA1 mode + if (ElementID == WpaIe) + return; + + pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len)); + + + pRSN_Cap->word = cpu2le16(pRSN_Cap->word); + + (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length + +} + + +/* + ======================================================================== + + Routine Description: + Build RSN IE context. It is not included element-ID and length. + + Arguments: + pAd - pointer to our pAdapter context + AuthMode - indicate the authentication mode + WepStatus - indicate the encryption type + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMPMakeRSNIE( + IN PRTMP_ADAPTER pAd, + IN UINT AuthMode, + IN UINT WepStatus, + IN UCHAR apidx) +{ + PUCHAR pRsnIe = NULL; // primary RSNIE + UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE + UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE + UCHAR PrimaryRsnie; + BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different + UCHAR p_offset; + WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode + + rsnielen_cur_p = NULL; + rsnielen_ex_cur_p = NULL; + + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + if (AuthMode < Ndis802_11AuthModeWPA) + return; + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + // Support WPAPSK or WPA2PSK in STA-Infra mode + // Support WPANone in STA-Adhoc mode + if ((AuthMode != Ndis802_11AuthModeWPAPSK) && + (AuthMode != Ndis802_11AuthModeWPA2PSK) && + (AuthMode != Ndis802_11AuthModeWPANone) + ) + return; + } + + DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n")); + + // Zero RSNIE context + pAd->StaCfg.RSNIE_Len = 0; + NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE); + + // Pointer to RSNIE + rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len; + pRsnIe = pAd->StaCfg.RSN_IE; + + bMixCipher = pAd->StaCfg.bMixCipher; + } +#endif // CONFIG_STA_SUPPORT // + } + + // indicate primary RSNIE as WPA or WPA2 + if ((AuthMode == Ndis802_11AuthModeWPA) || + (AuthMode == Ndis802_11AuthModeWPAPSK) || + (AuthMode == Ndis802_11AuthModeWPANone) || + (AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + PrimaryRsnie = WpaIe; + else + PrimaryRsnie = Wpa2Ie; + + { + // Build the primary RSNIE + // 1. insert cipher suite + RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset); + + // 2. insert AKM + RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset); + + // 3. insert capability + RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); + } + + // 4. update the RSNIE length + *rsnielen_cur_p = p_offset; + + hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); + + +} + +/* + ========================================================================== + Description: + Check whether the received frame is EAP frame. + + Arguments: + pAd - pointer to our pAdapter context + pEntry - pointer to active entry + pData - the received frame + DataByteCount - the received frame's length + FromWhichBSSID - indicate the interface index + + Return: + TRUE - This frame is EAP frame + FALSE - otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckWPAframe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pData, + IN ULONG DataByteCount, + IN UCHAR FromWhichBSSID) +{ + ULONG Body_len; + BOOLEAN Cancelled; + + + if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H)) + return FALSE; + + + // Skip LLC header + if (NdisEqualMemory(SNAP_802_1H, pData, 6) || + // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) + { + pData += 6; + } + // Skip 2-bytes EAPoL type + if (NdisEqualMemory(EAPOL, pData, 2)) + { + pData += 2; + } + else + return FALSE; + + switch (*(pData+1)) + { + case EAPPacket: + Body_len = (*(pData+2)<<8) | (*(pData+3)); + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len)); + break; + case EAPOLStart: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n")); + if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n")); + RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + } + break; + case EAPOLLogoff: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n")); + break; + case EAPOLKey: + Body_len = (*(pData+2)<<8) | (*(pData+3)); + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len)); + break; + case EAPOLASFAlert: + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n")); + break; + default: + return FALSE; + + } + return TRUE; +} + + +/* + ========================================================================== + Description: + ENCRYPT AES GTK before sending in EAPOL frame. + AES GTK length = 128 bit, so fix blocks for aes-key-wrap as 2 in this function. + This function references to RFC 3394 for aes key wrap algorithm. + Return: + ========================================================================== +*/ +VOID AES_GTK_KEY_WRAP( + IN UCHAR *key, + IN UCHAR *plaintext, + IN UCHAR p_len, + OUT UCHAR *ciphertext) +{ + UCHAR A[8], BIN[16], BOUT[16]; + UCHAR R[512]; + INT num_blocks = p_len/8; // unit:64bits + INT i, j; + aes_context aesctx; + UCHAR xor; + + rtmp_aes_set_key(&aesctx, key, 128); + + // Init IA + for (i = 0; i < 8; i++) + A[i] = 0xa6; + + //Input plaintext + for (i = 0; i < num_blocks; i++) + { + for (j = 0 ; j < 8; j++) + R[8 * (i + 1) + j] = plaintext[8 * i + j]; + } + + // Key Mix + for (j = 0; j < 6; j++) + { + for(i = 1; i <= num_blocks; i++) + { + //phase 1 + NdisMoveMemory(BIN, A, 8); + NdisMoveMemory(&BIN[8], &R[8 * i], 8); + rtmp_aes_encrypt(&aesctx, BIN, BOUT); + + NdisMoveMemory(A, &BOUT[0], 8); + xor = num_blocks * j + i; + A[7] = BOUT[7] ^ xor; + NdisMoveMemory(&R[8 * i], &BOUT[8], 8); + } + } + + // Output ciphertext + NdisMoveMemory(ciphertext, A, 8); + + for (i = 1; i <= num_blocks; i++) + { + for (j = 0 ; j < 8; j++) + ciphertext[8 * i + j] = R[8 * i + j]; + } +} + + +/* + ======================================================================== + + Routine Description: + Misc function to decrypt AES body + + Arguments: + + Return Value: + + Note: + This function references to RFC 3394 for aes key unwrap algorithm. + + ======================================================================== +*/ +VOID AES_GTK_KEY_UNWRAP( + IN UCHAR *key, + OUT UCHAR *plaintext, + IN UCHAR c_len, + IN UCHAR *ciphertext) + +{ + UCHAR A[8], BIN[16], BOUT[16]; + UCHAR xor; + INT i, j; + aes_context aesctx; + UCHAR *R; + INT num_blocks = c_len/8; // unit:64bits + + + os_alloc_mem(NULL, (PUCHAR *)&R, 512); + + if (R == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n")); + return; + } /* End of if */ + + // Initialize + NdisMoveMemory(A, ciphertext, 8); + //Input plaintext + for(i = 0; i < (c_len-8); i++) + { + R[ i] = ciphertext[i + 8]; + } + + rtmp_aes_set_key(&aesctx, key, 128); + + for(j = 5; j >= 0; j--) + { + for(i = (num_blocks-1); i > 0; i--) + { + xor = (num_blocks -1 )* j + i; + NdisMoveMemory(BIN, A, 8); + BIN[7] = A[7] ^ xor; + NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8); + rtmp_aes_decrypt(&aesctx, BIN, BOUT); + NdisMoveMemory(A, &BOUT[0], 8); + NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8); + } + } + + // OUTPUT + for(i = 0; i < c_len; i++) + { + plaintext[i] = R[i]; + } + + + os_free_mem(NULL, R); +} + +/* + ========================================================================== + Description: + Report the EAP message type + + Arguments: + msg - EAPOL_PAIR_MSG_1 + EAPOL_PAIR_MSG_2 + EAPOL_PAIR_MSG_3 + EAPOL_PAIR_MSG_4 + EAPOL_GROUP_MSG_1 + EAPOL_GROUP_MSG_2 + + Return: + message type string + + ========================================================================== +*/ +CHAR *GetEapolMsgType(CHAR msg) +{ + if(msg == EAPOL_PAIR_MSG_1) + return "Pairwise Message 1"; + else if(msg == EAPOL_PAIR_MSG_2) + return "Pairwise Message 2"; + else if(msg == EAPOL_PAIR_MSG_3) + return "Pairwise Message 3"; + else if(msg == EAPOL_PAIR_MSG_4) + return "Pairwise Message 4"; + else if(msg == EAPOL_GROUP_MSG_1) + return "Group Message 1"; + else if(msg == EAPOL_GROUP_MSG_2) + return "Group Message 2"; + else + return "Invalid Message"; +} + + +/* + ======================================================================== + + Routine Description: + Check Sanity RSN IE of EAPoL message + + Arguments: + + Return Value: + + + ======================================================================== +*/ +BOOLEAN RTMPCheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + IN MAC_TABLE_ENTRY *pEntry, + OUT UCHAR *Offset) +{ + PUCHAR pVIE; + UCHAR len; + PEID_STRUCT pEid; + BOOLEAN result = FALSE; + + pVIE = pData; + len = DataLen; + *Offset = 0; + + while (len > sizeof(RSNIE2)) + { + pEid = (PEID_STRUCT) pVIE; + // WPA RSN IE + if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) + { + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) && + (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) && + (pEntry->RSNIE_Len == (pEid->Len + 2))) + { + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + // WPA2 RSN IE + else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) + { + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) && + (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) && + (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/) + { + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + else + { + break; + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + + + return result; + +} + + +/* + ======================================================================== + + Routine Description: + Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. + GTK is encaptulated in KDE format at p.83 802.11i D10 + + Arguments: + + Return Value: + + Note: + 802.11i D10 + + ======================================================================== +*/ +BOOLEAN RTMPParseEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR GroupKeyIndex, + IN UCHAR MsgType, + IN BOOLEAN bWPA2, + IN MAC_TABLE_ENTRY *pEntry) +{ + PKDE_ENCAP pKDE = NULL; + PUCHAR pMyKeyData = pKeyData; + UCHAR KeyDataLength = KeyDataLen; + UCHAR GTKLEN = 0; + UCHAR DefaultIdx = 0; + UCHAR skip_offset; + + // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it + if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) + { + // Check RSN IE whether it is WPA2/WPA2PSK + if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) + { + // send wireless event - for RSN IE different + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); + + DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType)); + hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen); + hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len); + + return FALSE; + } + else + { + if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) + { + // skip RSN IE + pMyKeyData += skip_offset; + KeyDataLength -= skip_offset; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); + } + else + return TRUE; + } + } + + DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); + + // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 + if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) + { + if (KeyDataLength >= 8) // KDE format exclude GTK length + { + pKDE = (PKDE_ENCAP) pMyKeyData; + + + DefaultIdx = pKDE->GTKEncap.Kid; + + // Sanity check - KED length + if (KeyDataLength < (pKDE->Len + 2)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n")); + return FALSE; + } + + // Get GTK length - refer to IEEE 802.11i-2004 p.82 + GTKLEN = pKDE->Len -6; + if (GTKLEN < LEN_AES_KEY) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); + return FALSE; + } + + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n")); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN)); + // skip it + pMyKeyData += 8; + KeyDataLength -= 8; + + } + else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) + { + DefaultIdx = GroupKeyIndex; + DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx)); + } + + // Sanity check - shared key index must be 1 ~ 3 + if (DefaultIdx < 1 || DefaultIdx > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + return FALSE; + } + + +#ifdef CONFIG_STA_SUPPORT + // Todo +#endif // CONFIG_STA_SUPPORT // + + return TRUE; + +} + + +/* + ======================================================================== + + Routine Description: + Construct EAPoL message for WPA handshaking + Its format is below, + + +--------------------+ + | Protocol Version | 1 octet + +--------------------+ + | Protocol Type | 1 octet + +--------------------+ + | Body Length | 2 octets + +--------------------+ + | Descriptor Type | 1 octet + +--------------------+ + | Key Information | 2 octets + +--------------------+ + | Key Length | 1 octet + +--------------------+ + | Key Repaly Counter | 8 octets + +--------------------+ + | Key Nonce | 32 octets + +--------------------+ + | Key IV | 16 octets + +--------------------+ + | Key RSC | 8 octets + +--------------------+ + | Key ID or Reserved | 8 octets + +--------------------+ + | Key MIC | 16 octets + +--------------------+ + | Key Data Length | 2 octets + +--------------------+ + | Key Data | n octets + +--------------------+ + + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ConstructEapolMsg( + IN PRTMP_ADAPTER pAd, + IN UCHAR AuthMode, + IN UCHAR WepStatus, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *ReplayCounter, + IN UCHAR *KeyNonce, + IN UCHAR *TxRSC, + IN UCHAR *PTK, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_Len, + OUT PEAPOL_PACKET pMsg) +{ + BOOLEAN bWPA2 = FALSE; + + // Choose WPA2 or not + if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK)) + bWPA2 = TRUE; + + // Init Packet and Fill header + pMsg->ProVer = EAPOL_VER; + pMsg->ProType = EAPOLKey; + + // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field + pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG; + + // Fill in EAPoL descriptor + if (bWPA2) + pMsg->KeyDesc.Type = WPA2_KEY_DESC; + else + pMsg->KeyDesc.Type = WPA1_KEY_DESC; + + // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 + // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. + pMsg->KeyDesc.KeyInfo.KeyDescVer = + (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); + + // Specify Key Type as Group(0) or Pairwise(1) + if (MsgType >= EAPOL_GROUP_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; + else + pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // Specify Key Index, only group_msg1_WPA1 + if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; + + if (MsgType == EAPOL_PAIR_MSG_3) + pMsg->KeyDesc.KeyInfo.Install = 1; + + if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyAck = 1; + + if (MsgType != EAPOL_PAIR_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyMic = 1; + + if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) + { + pMsg->KeyDesc.KeyInfo.Secure = 1; + } + + if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) + { + pMsg->KeyDesc.KeyInfo.EKD_DL = 1; + } + + // key Information element has done. + *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo)); + + // Fill in Key Length + { + if (MsgType >= EAPOL_GROUP_MSG_1) + { + // the length of group key cipher + pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY); + } + else + { + // the length of pairwise key cipher + pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY); + } + } + + // Fill in replay counter + NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Fill Key Nonce field + // ANonce : pairwise_msg1 & pairwise_msg3 + // SNonce : pairwise_msg2 + // GNonce : group_msg1_wpa1 + if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) + NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE); + + // Fill key IV - WPA2 as 0, WPA1 as random + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + { + // Suggest IV be random number plus some number, + NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV); + pMsg->KeyDesc.KeyIv[15] += 2; + } + + // Fill Key RSC field + // It contains the RSC for the GTK being installed. + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) + { + NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); + } + + // Clear Key MIC field for MIC calculation later + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + ConstructEapolKeyData(pAd, + AuthMode, + WepStatus, + GroupKeyWepStatus, + MsgType, + DefaultKeyIdx, + bWPA2, + PTK, + GTK, + RSNIE, + RSNIE_Len, + pMsg); + + // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. + if (MsgType != EAPOL_PAIR_MSG_1) + { + CalculateMIC(pAd, WepStatus, PTK, pMsg); + } + + DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", pMsg->Body_Len[1])); + DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", pMsg->KeyDesc.KeyLength[1])); + + +} + +/* + ======================================================================== + + Routine Description: + Construct the Key Data field of EAPoL message + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ConstructEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN UCHAR AuthMode, + IN UCHAR WepStatus, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN BOOLEAN bWPA2Capable, + IN UCHAR *PTK, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_LEN, + OUT PEAPOL_PACKET pMsg) +{ + UCHAR *mpool, *Key_Data, *Rc4GTK; + UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)]; + UCHAR data_offset; + + + if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) + return; + + // allocate memory pool + os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500); + + if (mpool == NULL) + return; + + /* Rc4GTK Len = 512 */ + Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4); + /* Key_Data Len = 512 */ + Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4); + + NdisZeroMemory(Key_Data, 512); + pMsg->KeyDesc.KeyDataLen[1] = 0; + data_offset = 0; + + // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 + if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) + { + if (bWPA2Capable) + Key_Data[data_offset + 0] = IE_WPA2; + else + Key_Data[data_offset + 0] = IE_WPA; + + Key_Data[data_offset + 1] = RSNIE_LEN; + NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN); + data_offset += (2 + RSNIE_LEN); + } + + // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 + if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))) + { + // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h + Key_Data[data_offset + 0] = 0xDD; + + if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + { + Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField) + } + else + { + Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField) + } + + Key_Data[data_offset + 2] = 0x00; + Key_Data[data_offset + 3] = 0x0F; + Key_Data[data_offset + 4] = 0xAC; + Key_Data[data_offset + 5] = 0x01; + + // GTK KDE format - 802.11i-2004 Figure-43x + Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03); + Key_Data[data_offset + 7] = 0x00; // Reserved Byte + + data_offset += 8; + } + + + // Encapsulate GTK and encrypt the key-data field with KEK. + // Only for pairwise_msg3_WPA2 and group_msg1 + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1)) + { + // Fill in GTK + if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + { + NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY); + data_offset += LEN_AES_KEY; + } + else + { + NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH); + data_offset += TKIP_GTK_LENGTH; + } + + // Still dont know why, but if not append will occur "GTK not include in MSG3" + // Patch for compatibility between zero config and funk + if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) + { + if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) + { + Key_Data[data_offset + 0] = 0xDD; + Key_Data[data_offset + 1] = 0; + data_offset += 2; + } + else + { + Key_Data[data_offset + 0] = 0xDD; + Key_Data[data_offset + 1] = 0; + Key_Data[data_offset + 2] = 0; + Key_Data[data_offset + 3] = 0; + Key_Data[data_offset + 4] = 0; + Key_Data[data_offset + 5] = 0; + data_offset += 6; + } + } + + // Encrypt the data material in key data field + if (WepStatus == Ndis802_11Encryption3Enabled) + { + AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK); + // AES wrap function will grow 8 bytes in length + data_offset += 8; + } + else + { + // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) + // put TxTsc in Key RSC field + pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32. + + // ekey is the contanetion of IV-field, and PTK[16]->PTK[31] + NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV); + NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV) + pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset); + WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset); + } + + NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset); + } + else + { + NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset); + } + + // set key data length field and total length + pMsg->KeyDesc.KeyDataLen[1] = data_offset; + pMsg->Body_Len[1] += data_offset; + + os_free_mem(pAd, mpool); + +} + +/* + ======================================================================== + + Routine Description: + Calcaulate MIC. It is used during 4-ways handsharking. + + Arguments: + pAd - pointer to our pAdapter context + PeerWepStatus - indicate the encryption type + + Return Value: + + Note: + + ======================================================================== +*/ +VOID CalculateMIC( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerWepStatus, + IN UCHAR *PTK, + OUT PEAPOL_PACKET pMsg) +{ + UCHAR *OutBuffer; + ULONG FrameLen = 0; + UCHAR mic[LEN_KEY_DESC_MIC]; + UCHAR digest[80]; + + // allocate memory for MIC calculation + os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512); + + if (OutBuffer == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n")); + return; + } + + // make a frame for calculating MIC. + MakeOutgoingFrame(OutBuffer, &FrameLen, + pMsg->Body_Len[1] + 4, pMsg, + END_OF_ARGS); + + NdisZeroMemory(mic, sizeof(mic)); + + // Calculate MIC + if (PeerWepStatus == Ndis802_11Encryption3Enabled) + { + HMAC_SHA1(OutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic); + } + + // store the calculated MIC + NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); + + os_free_mem(pAd, OutBuffer); +} + +/* + ======================================================================== + + Routine Description: + Some received frames can't decrypt by Asic, so decrypt them by software. + + Arguments: + pAd - pointer to our pAdapter context + PeerWepStatus - indicate the encryption type + + Return Value: + NDIS_STATUS_SUCCESS - decryption successful + NDIS_STATUS_FAILURE - decryption failure + + ======================================================================== +*/ +NDIS_STATUS RTMPSoftDecryptBroadCastData( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher, + IN PCIPHER_KEY pShard_key) +{ + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + + + + // handle WEP decryption + if (GroupCipher == Ndis802_11Encryption1Enabled) + { + if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key)) + { + + //Minus IV[4] & ICV[4] + pRxWI->MPDUtotalByteCount -= 8; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n")); + // give up this frame + return NDIS_STATUS_FAILURE; + } + } + // handle TKIP decryption + else if (GroupCipher == Ndis802_11Encryption2Enabled) + { + if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key)) + { + + //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV + pRxWI->MPDUtotalByteCount -= 20; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n")); + // give up this frame + return NDIS_STATUS_FAILURE; + } + } + // handle AES decryption + else if (GroupCipher == Ndis802_11Encryption3Enabled) + { + if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key)) + { + + //8 bytes MIC, 8 bytes IV/EIV (CCMP Header) + pRxWI->MPDUtotalByteCount -= 16; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n")); + // give up this frame + return NDIS_STATUS_FAILURE; + } + } + else + { + // give up this frame + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; + +} + diff --git a/drivers/staging/rt3070/common/dfs.c b/drivers/staging/rt3070/common/dfs.c new file mode 100644 index 000000000000..28d60145791c --- /dev/null +++ b/drivers/staging/rt3070/common/dfs.c @@ -0,0 +1,441 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + ap_dfs.c + + Abstract: + Support DFS function. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 03-12-2007 created +*/ + +#include "../rt_config.h" + +typedef struct _RADAR_DURATION_TABLE +{ + ULONG RDDurRegion; + ULONG RadarSignalDuration; + ULONG Tolerance; +} RADAR_DURATION_TABLE, *PRADAR_DURATION_TABLE; + + +static UCHAR RdIdleTimeTable[MAX_RD_REGION][4] = +{ + {9, 250, 250, 250}, // CE + {4, 250, 250, 250}, // FCC + {4, 250, 250, 250}, // JAP + {15, 250, 250, 250}, // JAP_W53 + {4, 250, 250, 250} // JAP_W56 +}; + +/* + ======================================================================== + + Routine Description: + Bbp Radar detection routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + + ======================================================================== +*/ +VOID BbpRadarDetectionStart( + IN PRTMP_ADAPTER pAd) +{ + UINT8 RadarPeriod; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 114, 0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 121, 0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 122, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 123, 0x08/*0x80*/); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 124, 0x28); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 125, 0xff); + + RadarPeriod = ((UINT)RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + (UINT)pAd->CommonCfg.RadarDetect.DfsSessionTime) < 250 ? + (RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + pAd->CommonCfg.RadarDetect.DfsSessionTime) : 250; + + RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); + RTMP_IO_WRITE8(pAd, 0x7021, 0x40); + + RadarDetectionStart(pAd, 0, RadarPeriod); + return; +} + +/* + ======================================================================== + + Routine Description: + Bbp Radar detection routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + + ======================================================================== +*/ +VOID BbpRadarDetectionStop( + IN PRTMP_ADAPTER pAd) +{ + RTMP_IO_WRITE8(pAd, 0x7020, 0x1d); + RTMP_IO_WRITE8(pAd, 0x7021, 0x60); + + RadarDetectionStop(pAd); + return; +} + +/* + ======================================================================== + + Routine Description: + Radar detection routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + + ======================================================================== +*/ +VOID RadarDetectionStart( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN CTSProtect, + IN UINT8 CTSPeriod) +{ + UINT8 DfsActiveTime = (pAd->CommonCfg.RadarDetect.DfsSessionTime & 0x1f); + UINT8 CtsProtect = (CTSProtect == 1) ? 0x02 : 0x01; // CTS protect. + + if (CTSProtect != 0) + { + switch(pAd->CommonCfg.RadarDetect.RDDurRegion) + { + case FCC: + case JAP_W56: + CtsProtect = 0x03; + break; + + case CE: + case JAP_W53: + default: + CtsProtect = 0x02; + break; + } + } + else + CtsProtect = 0x01; + + + // send start-RD with CTS protection command to MCU + // highbyte [7] reserve + // highbyte [6:5] 0x: stop Carrier/Radar detection + // highbyte [10]: Start Carrier/Radar detection without CTS protection, 11: Start Carrier/Radar detection with CTS protection + // highbyte [4:0] Radar/carrier detection duration. In 1ms. + + // lowbyte [7:0] Radar/carrier detection period, in 1ms. + AsicSendCommandToMcu(pAd, 0x60, 0xff, CTSPeriod, DfsActiveTime | (CtsProtect << 5)); + //AsicSendCommandToMcu(pAd, 0x63, 0xff, 10, 0); + + return; +} + +/* + ======================================================================== + + Routine Description: + Radar detection routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + TRUE Found radar signal + FALSE Not found radar signal + + ======================================================================== +*/ +VOID RadarDetectionStop( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("RadarDetectionStop.\n")); + AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00); // send start-RD with CTS protection command to MCU + + return; +} + +/* + ======================================================================== + + Routine Description: + Radar channel check routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + TRUE need to do radar detect + FALSE need not to do radar detect + + ======================================================================== +*/ +BOOLEAN RadarChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ch) +{ +#if 1 + INT i; + BOOLEAN result = FALSE; + + for (i=0; iChannelListNum; i++) + { + if (Ch == pAd->ChannelList[i].Channel) + { + result = pAd->ChannelList[i].DfsReq; + break; + } + } + + return result; +#else + INT i; + UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; + + for (i=0; i<15; i++) + { + if (Ch == Channel[i]) + { + break; + } + } + + if (i != 15) + return TRUE; + else + return FALSE; +#endif +} + +ULONG JapRadarType( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + const UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; + + if (pAd->CommonCfg.RadarDetect.RDDurRegion != JAP) + { + return pAd->CommonCfg.RadarDetect.RDDurRegion; + } + + for (i=0; i<15; i++) + { + if (pAd->CommonCfg.Channel == Channel[i]) + { + break; + } + } + + if (i < 4) + return JAP_W53; + else if (i < 15) + return JAP_W56; + else + return JAP; // W52 + +} + +ULONG RTMPBbpReadRadarDuration( + IN PRTMP_ADAPTER pAd) +{ + UINT8 byteValue = 0; + ULONG result; + + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R115, &byteValue); + + result = 0; + switch (byteValue) + { + case 1: // radar signal detected by pulse mode. + case 2: // radar signal detected by width mode. + result = RTMPReadRadarDuration(pAd); + break; + + case 0: // No radar signal. + default: + + result = 0; + break; + } + + return result; +} + +ULONG RTMPReadRadarDuration( + IN PRTMP_ADAPTER pAd) +{ + ULONG result = 0; + +#ifdef DFS_SUPPORT + UINT8 duration1 = 0, duration2 = 0, duration3 = 0; + + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R116, &duration1); + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R117, &duration2); + BBP_IO_READ8_BY_REG_ID(pAd, BBP_R118, &duration3); + result = (duration1 << 16) + (duration2 << 8) + duration3; +#endif // DFS_SUPPORT // + + return result; + +} + +VOID RTMPCleanRadarDuration( + IN PRTMP_ADAPTER pAd) +{ + return; +} + +/* + ======================================================================== + Routine Description: + Radar wave detection. The API should be invoke each second. + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID ApRadarDetectPeriodic( + IN PRTMP_ADAPTER pAd) +{ + INT i; + + pAd->CommonCfg.RadarDetect.InServiceMonitorCount++; + + for (i=0; iChannelListNum; i++) + { + if (pAd->ChannelList[i].RemainingTimeForUse > 0) + { + pAd->ChannelList[i].RemainingTimeForUse --; + if ((pAd->Mlme.PeriodicRound%5) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse)); + } + } + } + + //radar detect + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + RadarDetectPeriodic(pAd); + } + + return; +} + +// Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt() +// Before switch channel, driver needs doing channel switch announcement. +VOID RadarDetectPeriodic( + IN PRTMP_ADAPTER pAd) +{ + // need to check channel availability, after switch channel + if (pAd->CommonCfg.RadarDetect.RDMode != RD_SILENCE_MODE) + return; + + // channel availability check time is 60sec, use 65 for assurance + if (pAd->CommonCfg.RadarDetect.RDCount++ > pAd->CommonCfg.RadarDetect.ChMovingTime) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n")); + BbpRadarDetectionStop(pAd); + AsicEnableBssSync(pAd); + pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; + + + return; + } + + return; +} + + +/* + ========================================================================== + Description: + change channel moving time for DFS testing. + + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 set ChMovTime=[value] + ========================================================================== +*/ +INT Set_ChMovingTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT8 Value; + + Value = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.RadarDetect.ChMovingTime = Value; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__, + pAd->CommonCfg.RadarDetect.ChMovingTime)); + + return TRUE; +} + +INT Set_LongPulseRadarTh_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT8 Value; + + Value = simple_strtol(arg, 0, 10) > 10 ? 10 : simple_strtol(arg, 0, 10); + + pAd->CommonCfg.RadarDetect.LongPulseRadarTh = Value; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __FUNCTION__, + pAd->CommonCfg.RadarDetect.LongPulseRadarTh)); + + return TRUE; +} + + diff --git a/drivers/staging/rt3070/common/eeprom.c b/drivers/staging/rt3070/common/eeprom.c new file mode 100644 index 000000000000..63e1dc14d151 --- /dev/null +++ b/drivers/staging/rt3070/common/eeprom.c @@ -0,0 +1,1498 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + eeprom.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#include "../rt_config.h" + +// IRQL = PASSIVE_LEVEL +VOID RaiseClock( + IN PRTMP_ADAPTER pAd, + IN UINT32 *x) +{ + *x = *x | EESK; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); + RTMPusecDelay(1); // Max frequency = 1MHz in Spec. definition +} + +// IRQL = PASSIVE_LEVEL +VOID LowerClock( + IN PRTMP_ADAPTER pAd, + IN UINT32 *x) +{ + *x = *x & ~EESK; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); + RTMPusecDelay(1); +} + +// IRQL = PASSIVE_LEVEL +USHORT ShiftInBits( + IN PRTMP_ADAPTER pAd) +{ + UINT32 x,i; + USHORT data=0; + + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~( EEDO | EEDI); + + for(i=0; i<16; i++) + { + data = data << 1; + RaiseClock(pAd, &x); + + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + LowerClock(pAd, &x); //prevent read failed + + x &= ~(EEDI); + if(x & EEDO) + data |= 1; + } + + return data; +} + +// IRQL = PASSIVE_LEVEL +VOID ShiftOutBits( + IN PRTMP_ADAPTER pAd, + IN USHORT data, + IN USHORT count) +{ + UINT32 x,mask; + + mask = 0x01 << (count - 1); + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~(EEDO | EEDI); + + do + { + x &= ~EEDI; + if(data & mask) x |= EEDI; + + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + mask = mask >> 1; + } while(mask); + + x &= ~EEDI; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); +} + +// IRQL = PASSIVE_LEVEL +VOID EEpromCleanup( + IN PRTMP_ADAPTER pAd) +{ + UINT32 x; + + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + x &= ~(EECS | EEDI); + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + RaiseClock(pAd, &x); + LowerClock(pAd, &x); +} + +VOID EWEN( + IN PRTMP_ADAPTER pAd) +{ + UINT32 x; + + // reset bits and set EECS + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + // kick a pulse + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + // output the read_opcode and six pulse in that order + ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5); + ShiftOutBits(pAd, 0, 6); + + EEpromCleanup(pAd); +} + +VOID EWDS( + IN PRTMP_ADAPTER pAd) +{ + UINT32 x; + + // reset bits and set EECS + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + // kick a pulse + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + + // output the read_opcode and six pulse in that order + ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5); + ShiftOutBits(pAd, 0, 6); + + EEpromCleanup(pAd); +} + +// IRQL = PASSIVE_LEVEL +USHORT RTMP_EEPROM_READ16( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset) +{ + UINT32 x; + USHORT data; + + if (pAd->NicConfig2.field.AntDiversity) + { + pAd->EepromAccess = TRUE; + } +//2008/09/11:KH add to support efuse<-- +//2008/09/11:KH add to support efuse--> +{ + Offset /= 2; + // reset bits and set EECS + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + // patch can not access e-Fuse issue + if (!IS_RT3090(pAd)) + { + // kick a pulse + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + } + + // output the read_opcode and register number in that order + ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3); + ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); + + // Now read the data (16 bits) in from the selected EEPROM word + data = ShiftInBits(pAd); + + EEpromCleanup(pAd); + + // Antenna and EEPROM access are both using EESK pin, + // Therefor we should avoid accessing EESK at the same time + // Then restore antenna after EEPROM access + if ((pAd->NicConfig2.field.AntDiversity) || (pAd->RfIcType == RFIC_3020)) + { + pAd->EepromAccess = FALSE; + AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); + } +} + return data; +} //ReadEEprom + +VOID RTMP_EEPROM_WRITE16( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Data) +{ + UINT32 x; + + if (pAd->NicConfig2.field.AntDiversity) + { + pAd->EepromAccess = TRUE; + } + //2008/09/11:KH add to support efuse<-- +//2008/09/11:KH add to support efuse--> + { + Offset /= 2; + + EWEN(pAd); + + // reset bits and set EECS + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + // patch can not access e-Fuse issue + if (!IS_RT3090(pAd)) + { + // kick a pulse + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + } + + // output the read_opcode ,register number and data in that order + ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3); + ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); + ShiftOutBits(pAd, Data, 16); // 16-bit access + + // read DO status + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + EEpromCleanup(pAd); + + RTMPusecDelay(10000); //delay for twp(MAX)=10ms + + EWDS(pAd); + + EEpromCleanup(pAd); + + // Antenna and EEPROM access are both using EESK pin, + // Therefor we should avoid accessing EESK at the same time + // Then restore antenna after EEPROM access + if ((pAd->NicConfig2.field.AntDiversity) || (pAd->RfIcType == RFIC_3020)) + { + pAd->EepromAccess = FALSE; + AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); + } +} +} + +//2008/09/11:KH add to support efuse<-- +#ifdef RT30xx +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +UCHAR eFuseReadRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData) +{ + EFUSE_CTRL_STRUC eFuseCtrlStruc; + int i; + USHORT efuseDataOffset; + UINT32 data; + + RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); + + //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. + //Use the eeprom logical address and covert to address to block number + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0. + eFuseCtrlStruc.field.EFSROM_MODE = 0; + + //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); + + //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. + i = 0; + while(i < 100) + { + //rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4); + RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + { + break; + } + RTMPusecDelay(2); + i++; + } + + //if EFSROM_AOUT is not found in physical address, write 0xffff + if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) + { + for(i=0; i> (8*(Offset & 0x3)); +#endif + + NdisMoveMemory(pData, &data, Length); + } + + return (UCHAR) eFuseCtrlStruc.field.EFSROM_AOUT; + +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +VOID eFusePhysicalReadRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData) +{ + EFUSE_CTRL_STRUC eFuseCtrlStruc; + int i; + USHORT efuseDataOffset; + UINT32 data; + + RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); + + //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. + //Read in physical view + eFuseCtrlStruc.field.EFSROM_MODE = 1; + + //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); + + //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. + i = 0; + while(i < 100) + { + RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + break; + RTMPusecDelay(2); + i++; + } + + //Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) + //Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits. + //The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes + //Decide which EFUSE_DATA to read + //590:F E D C + //594:B A 9 8 + //598:7 6 5 4 + //59C:3 2 1 0 + efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC) ; + + RTMP_IO_READ32(pAd, efuseDataOffset, &data); + +#ifdef RT_BIG_ENDIAN + data = data << (8*((Offset & 0x3)^0x2)); +#else + data = data >> (8*(Offset & 0x3)); +#endif + + NdisMoveMemory(pData, &data, Length); + +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +VOID eFuseReadPhysical( + IN PRTMP_ADAPTER pAd, + IN PUSHORT lpInBuffer, + IN ULONG nInBufferSize, + OUT PUSHORT lpOutBuffer, + IN ULONG nOutBufferSize +) +{ + USHORT* pInBuf = (USHORT*)lpInBuffer; + USHORT* pOutBuf = (USHORT*)lpOutBuffer; + + USHORT Offset = pInBuf[0]; //addr + USHORT Length = pInBuf[1]; //length + int i; + + for(i=0; i> 2; + data = pData[0] & 0xffff; + //The offset should be 0x***10 or 0x***00 + if((Offset % 4) != 0) + { + eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff) | (data << 16); + } + else + { + eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff0000) | data; + } + + efuseDataOffset = EFUSE_DATA3; + for(i=0; i< 4; i++) + { + RTMP_IO_WRITE32(pAd, efuseDataOffset, eFuseDataBuffer[i]); + efuseDataOffset -= 4; + } + ///////////////////////////////////////////////////////////////// + + //Step1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + //Step2. Write EFSROM_MODE (0x580, bit7:bit6) to 3. + eFuseCtrlStruc.field.EFSROM_MODE = 3; + + //Step3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure. + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); + + //Step4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It¡¦s done. + i = 0; + while(i < 100) + { + RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); + + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + break; + + RTMPusecDelay(2); + i++; + } +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS eFuseWriteRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + IN USHORT* pData) +{ + USHORT i; + USHORT eFuseData; + USHORT LogicalAddress, BlkNum = 0xffff; + UCHAR EFSROM_AOUT; + + USHORT addr,tmpaddr, InBuf[3], tmpOffset; + USHORT buffer[8]; + BOOLEAN bWriteSuccess = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters Offset=%x, pData=%x\n", Offset, *pData)); + + //Step 0. find the entry in the mapping table + //The address of EEPROM is 2-bytes alignment. + //The last bit is used for alignment, so it must be 0. + tmpOffset = Offset & 0xfffe; + EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData); + + if( EFSROM_AOUT == 0x3f) + { //find available logical address pointer + //the logical address does not exist, find an empty one + //from the first address of block 45=16*45=0x2d0 to the last address of block 47 + //==>48*16-3(reserved)=2FC + for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) + { + //Retrive the logical block nubmer form each logical address pointer + //It will access two logical address pointer each time. + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + if( (LogicalAddress & 0xff) == 0) + {//Not used logical address pointer + BlkNum = i-EFUSE_USAGE_MAP_START; + break; + } + else if(( (LogicalAddress >> 8) & 0xff) == 0) + {//Not used logical address pointer + if (i != EFUSE_USAGE_MAP_END) + { + BlkNum = i-EFUSE_USAGE_MAP_START+1; + } + break; + } + } + } + else + { + BlkNum = EFSROM_AOUT; + } + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum)); + + if(BlkNum == 0xffff) + { + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); + return FALSE; + } + + //Step 1. Save data of this block which is pointed by the avaible logical address pointer + // read and save the original block data + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + buffer[i] = InBuf[2]; + } + + //Step 2. Update the data in buffer, and write the data to Efuse + buffer[ (Offset >> 1) % 8] = pData[0]; + + do + { + //Step 3. Write the data to Efuse + if(!bWriteSuccess) + { + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = buffer[i]; + + eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); + } + } + else + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+(Offset % 16); + InBuf[1] = 2; + InBuf[2] = pData[0]; + + eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); + } + + //Step 4. Write mapping table + addr = EFUSE_USAGE_MAP_START+BlkNum; + + tmpaddr = addr; + + if(addr % 2 != 0) + addr = addr -1; + InBuf[0] = addr; + InBuf[1] = 2; + + //convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry + tmpOffset = Offset; + tmpOffset >>= 4; + tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40; + tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80; + + // write the logical address + if(tmpaddr%2 != 0) + InBuf[2] = tmpOffset<<8; + else + InBuf[2] = tmpOffset; + + eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0); + + //Step 5. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted + bWriteSuccess = TRUE; + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + if(buffer[i] != InBuf[2]) + { + bWriteSuccess = FALSE; + break; + } + } + + //Step 6. invlidate mapping entry and find a free mapping entry if not succeed + if (!bWriteSuccess) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess BlkNum = %d\n", BlkNum)); + + // the offset of current mapping entry + addr = EFUSE_USAGE_MAP_START+BlkNum; + + //find a new mapping entry + BlkNum = 0xffff; + for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) + { + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + if( (LogicalAddress & 0xff) == 0) + { + BlkNum = i-EFUSE_USAGE_MAP_START; + break; + } + else if(( (LogicalAddress >> 8) & 0xff) == 0) + { + if (i != EFUSE_USAGE_MAP_END) + { + BlkNum = i+1-EFUSE_USAGE_MAP_START; + } + break; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess new BlkNum = %d\n", BlkNum)); + if(BlkNum == 0xffff) + { + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); + return FALSE; + } + + //invalidate the original mapping entry if new entry is not found + tmpaddr = addr; + + if(addr % 2 != 0) + addr = addr -1; + InBuf[0] = addr; + InBuf[1] = 2; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + // write the logical address + if(tmpaddr%2 != 0) + { + // Invalidate the high byte + for (i=8; i<15; i++) + { + if( ( (InBuf[2] >> i) & 0x01) == 0) + { + InBuf[2] |= (0x1 <> i) & 0x01) == 0) + { + InBuf[2] |= (0x1 <bUseEfuse) + return FALSE; + for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i+=2) + { + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + if( (LogicalAddress & 0xff) == 0) + { + efusefreenum= (UCHAR) (EFUSE_USAGE_MAP_END-i+1); + break; + } + else if(( (LogicalAddress >> 8) & 0xff) == 0) + { + efusefreenum = (UCHAR) (EFUSE_USAGE_MAP_END-i); + break; + } + + if(i == EFUSE_USAGE_MAP_END) + efusefreenum = 0; + } + printk("efuseFreeNumber is %d\n",efusefreenum); + return TRUE; +} +INT set_eFusedump_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +USHORT InBuf[3]; + INT i=0; + if(!pAd->bUseEfuse) + return FALSE; + for(i =0; i0) + { + + NdisMoveMemory(src, arg, strlen(arg)); + } + + else + { + + NdisMoveMemory(src, "RT30xxEEPROM.bin", BinFileSize); + } + + DBGPRINT(RT_DEBUG_TRACE, ("FileName=%s\n",src)); + buffer = kmalloc(MAX_EEPROM_BIN_FILE_SIZE, MEM_ALLOC_FLAG); + + if(buffer == NULL) + { + kfree(src); + return FALSE; +} + PDATA=kmalloc(sizeof(USHORT)*8,MEM_ALLOC_FLAG); + + if(PDATA==NULL) + { + kfree(src); + + kfree(buffer); + return FALSE; + } + /* Don't change to uid 0, let the file be opened as the "normal" user */ +#if 0 + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + current->fsuid=current->fsgid = 0; +#endif + orgfs = get_fs(); + set_fs(KERNEL_DS); + + if (src && *src) + { + srcf = filp_open(src, O_RDONLY, 0); + if (IS_ERR(srcf)) + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src)); + return FALSE; + } + else + { + // The object must have a read method + if (srcf->f_op && srcf->f_op->read) + { + memset(buffer, 0x00, MAX_EEPROM_BIN_FILE_SIZE); + while(srcf->f_op->read(srcf, &buffer[i], 1, &srcf->f_pos)==1) + { + DBGPRINT(RT_DEBUG_TRACE, ("%02X ",buffer[i])); + if((i+1)%8==0) + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + i++; + if(i>=MAX_EEPROM_BIN_FILE_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld reading %s, The file is too large[1024]\n", -PTR_ERR(srcf),src)); + kfree(PDATA); + kfree(buffer); + kfree(src); + return FALSE; + } + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error!! System doest not support read function\n")); + kfree(PDATA); + kfree(buffer); + kfree(src); + return FALSE; + } + } + + + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error src or srcf is null\n")); + kfree(PDATA); + kfree(buffer); + return FALSE; + + } + + + retval=filp_close(srcf,NULL); + + if (retval) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); + } + set_fs(orgfs); +#if 0 + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; +#endif + for(j=0;j48*16-3(reserved)=2FC + bAllocateNewBlk=TRUE; + for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) + { + //Retrive the logical block nubmer form each logical address pointer + //It will access two logical address pointer each time. + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + if( (LogicalAddress & 0xff) == 0) + {//Not used logical address pointer + BlkNum = i-EFUSE_USAGE_MAP_START; + break; + } + else if(( (LogicalAddress >> 8) & 0xff) == 0) + {//Not used logical address pointer + if (i != EFUSE_USAGE_MAP_END) + { + BlkNum = i-EFUSE_USAGE_MAP_START+1; + } + break; + } + } + } + else + { + bAllocateNewBlk=FALSE; + BlkNum = EFSROM_AOUT; + } + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum)); + + if(BlkNum == 0xffff) + { + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); + return FALSE; + } + //Step 1.1.0 + //If the block is not existing in mapping table, create one + //and write down the 16-bytes data to the new block + if(bAllocateNewBlk) + { + DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk\n")); + efuseDataOffset = EFUSE_DATA3; + for(i=0; i< 4; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk, Data%d=%04x%04x\n",3-i,pData[2*i+1],pData[2*i])); + tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i]; + + + RTMP_IO_WRITE32(pAd, efuseDataOffset,tempbuffer); + efuseDataOffset -= 4; + + } + ///////////////////////////////////////////////////////////////// + + //Step1.1.1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. + eFuseCtrlStruc.field.EFSROM_AIN = BlkNum* 0x10 ; + + //Step1.1.2. Write EFSROM_MODE (0x580, bit7:bit6) to 3. + eFuseCtrlStruc.field.EFSROM_MODE = 3; + + //Step1.1.3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure. + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + + RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); + + //Step1.1.4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It¡¦s done. + i = 0; + while(i < 100) + { + RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); + + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + break; + + RTMPusecDelay(2); + i++; + } + + } + else + { //Step1.2. + //If the same logical number is existing, check if the writting data and the data + //saving in this block are the same. + ///////////////////////////////////////////////////////////////// + //read current values of 16-byte block + RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); + + //Step1.2.0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + //Step1.2.1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. + eFuseCtrlStruc.field.EFSROM_MODE = 0; + + //Step1.2.2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); + + //Step1.2.3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. + i = 0; + while(i < 100) + { + RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); + + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + break; + RTMPusecDelay(2); + i++; + } + + //Step1.2.4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) + efuseDataOffset = EFUSE_DATA3; + for(i=0; i< 4; i++) + { + RTMP_IO_READ32(pAd, efuseDataOffset, (PUINT32) &buffer[i]); + efuseDataOffset -= 4; + } + //Step1.2.5. Check if the data of efuse and the writing data are the same. + for(i =0; i<4; i++) + { + tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i]; + DBGPRINT(RT_DEBUG_TRACE, ("buffer[%d]=%x,pData[%d]=%x,pData[%d]=%x,tempbuffer=%x\n",i,buffer[i],2*i,pData[2*i],2*i+1,pData[2*i+1],tempbuffer)); + + if(((buffer[i]&0xffff0000)==(pData[2*i+1]<<16))&&((buffer[i]&0xffff)==pData[2*i])) + bNotWrite&=TRUE; + else + { + bNotWrite&=FALSE; + break; + } + } + if(!bNotWrite) + { + printk("The data is not the same\n"); + + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = pData[i]; + + eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); + } + + } + else + return TRUE; + } + + + + //Step 2. Write mapping table + addr = EFUSE_USAGE_MAP_START+BlkNum; + + tmpaddr = addr; + + if(addr % 2 != 0) + addr = addr -1; + InBuf[0] = addr; + InBuf[1] = 2; + + //convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry + tmpOffset = Offset; + tmpOffset >>= 4; + tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40; + tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80; + + // write the logical address + if(tmpaddr%2 != 0) + InBuf[2] = tmpOffset<<8; + else + InBuf[2] = tmpOffset; + + eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0); + + //Step 3. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted + bWriteSuccess = TRUE; + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + DBGPRINT(RT_DEBUG_TRACE, ("addr=%x, buffer[i]=%x,InBuf[2]=%x\n",InBuf[0],pData[i],InBuf[2])); + if(pData[i] != InBuf[2]) + { + bWriteSuccess = FALSE; + break; + } + } + + //Step 4. invlidate mapping entry and find a free mapping entry if not succeed + + if (!bWriteSuccess&&Loop<2) + { + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess BlkNum = %d\n", BlkNum)); + + // the offset of current mapping entry + addr = EFUSE_USAGE_MAP_START+BlkNum; + + //find a new mapping entry + BlkNum = 0xffff; + for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) + { + eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + if( (LogicalAddress & 0xff) == 0) + { + BlkNum = i-EFUSE_USAGE_MAP_START; + break; + } + else if(( (LogicalAddress >> 8) & 0xff) == 0) + { + if (i != EFUSE_USAGE_MAP_END) + { + BlkNum = i+1-EFUSE_USAGE_MAP_START; + } + break; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess new BlkNum = %d\n", BlkNum)); + if(BlkNum == 0xffff) + { + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin: out of free E-fuse space!!!\n")); + return FALSE; + } + + //invalidate the original mapping entry if new entry is not found + tmpaddr = addr; + + if(addr % 2 != 0) + addr = addr -1; + InBuf[0] = addr; + InBuf[1] = 2; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + // write the logical address + if(tmpaddr%2 != 0) + { + // Invalidate the high byte + for (i=8; i<15; i++) + { + if( ( (InBuf[2] >> i) & 0x01) == 0) + { + InBuf[2] |= (0x1 <> i) & 0x01) == 0) + { + InBuf[2] |= (0x1 < + diff --git a/drivers/staging/rt3070/common/md5.c b/drivers/staging/rt3070/common/md5.c new file mode 100644 index 000000000000..774776b4b8c3 --- /dev/null +++ b/drivers/staging/rt3070/common/md5.c @@ -0,0 +1,1427 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + md5.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + jan 10-28-03 Initial + Rita 11-23-04 Modify MD5 and SHA-1 + Rita 10-14-05 Modify SHA-1 in big-endian platform + */ +#include "../rt_config.h" + +/** + * md5_mac: + * @key: pointer to the key used for MAC generation + * @key_len: length of the key in bytes + * @data: pointer to the data area for which the MAC is generated + * @data_len: length of the data in bytes + * @mac: pointer to the buffer holding space for the MAC; the buffer should + * have space for 128-bit (16 bytes) MD5 hash value + * + * md5_mac() determines the message authentication code by using secure hash + * MD5(key | data | key). + */ +void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac) +{ + MD5_CTX context; + + MD5Init(&context); + MD5Update(&context, key, key_len); + MD5Update(&context, data, data_len); + MD5Update(&context, key, key_len); + MD5Final(mac, &context); +} + +/** + * hmac_md5: + * @key: pointer to the key used for MAC generation + * @key_len: length of the key in bytes + * @data: pointer to the data area for which the MAC is generated + * @data_len: length of the data in bytes + * @mac: pointer to the buffer holding space for the MAC; the buffer should + * have space for 128-bit (16 bytes) MD5 hash value + * + * hmac_md5() determines the message authentication code using HMAC-MD5. + * This implementation is based on the sample code presented in RFC 2104. + */ +void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac) +{ + MD5_CTX context; + u8 k_ipad[65]; /* inner padding - key XORd with ipad */ + u8 k_opad[65]; /* outer padding - key XORd with opad */ + u8 tk[16]; + int i; + + //assert(key != NULL && data != NULL && mac != NULL); + + /* if key is longer than 64 bytes reset it to key = MD5(key) */ + if (key_len > 64) { + MD5_CTX ttcontext; + + MD5Init(&ttcontext); + MD5Update(&ttcontext, key, key_len); + MD5Final(tk, &ttcontext); + //key=(PUCHAR)ttcontext.buf; + key = tk; + key_len = 16; + } + + /* the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected */ + + /* start out by storing key in pads */ + NdisZeroMemory(k_ipad, sizeof(k_ipad)); + NdisZeroMemory(k_opad, sizeof(k_opad)); + //assert(key_len < sizeof(k_ipad)); + NdisMoveMemory(k_ipad, key, key_len); + NdisMoveMemory(k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i = 0; i < 64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + /* perform inner MD5 */ + MD5Init(&context); /* init context for 1st pass */ + MD5Update(&context, k_ipad, 64); /* start with inner pad */ + MD5Update(&context, data, data_len); /* then text of datagram */ + MD5Final(mac, &context); /* finish up 1st pass */ + + /* perform outer MD5 */ + MD5Init(&context); /* init context for 2nd pass */ + MD5Update(&context, k_opad, 64); /* start with outer pad */ + MD5Update(&context, mac, 16); /* then results of 1st hash */ + MD5Final(mac, &context); /* finish up 2nd pass */ +} + +#ifndef RT_BIG_ENDIAN +#define byteReverse(buf, len) /* Nothing */ +#else +void byteReverse(unsigned char *buf, unsigned longs); +void byteReverse(unsigned char *buf, unsigned longs) +{ + do { + *(UINT32 *)buf = SWAP32(*(UINT32 *)buf); + buf += 4; + } while (--longs); +} +#endif + + +/* ========================== MD5 implementation =========================== */ +// four base functions for MD5 +#define MD5_F1(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define MD5_F2(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define MD5_F3(x, y, z) ((x) ^ (y) ^ (z)) +#define MD5_F4(x, y, z) ((y) ^ ((x) | (~z))) +#define CYCLIC_LEFT_SHIFT(w, s) (((w) << (s)) | ((w) >> (32-(s)))) + +#define MD5Step(f, w, x, y, z, data, t, s) \ + ( w += f(x, y, z) + data + t, w = (CYCLIC_LEFT_SHIFT(w, s)) & 0xffffffff, w += x ) + + +/* + * Function Description: + * Initiate MD5 Context satisfied in RFC 1321 + * + * Arguments: + * pCtx Pointer to MD5 context + * + * Return Value: + * None + */ +VOID MD5Init(MD5_CTX *pCtx) +{ + pCtx->Buf[0]=0x67452301; + pCtx->Buf[1]=0xefcdab89; + pCtx->Buf[2]=0x98badcfe; + pCtx->Buf[3]=0x10325476; + + pCtx->LenInBitCount[0]=0; + pCtx->LenInBitCount[1]=0; +} + + +/* + * Function Description: + * Update MD5 Context, allow of an arrary of octets as the next portion + * of the message + * + * Arguments: + * pCtx Pointer to MD5 context + * pData Pointer to input data + * LenInBytes The length of input data (unit: byte) + * + * Return Value: + * None + * + * Note: + * Called after MD5Init or MD5Update(itself) + */ +VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes) +{ + + UINT32 TfTimes; + UINT32 temp; + unsigned int i; + + temp = pCtx->LenInBitCount[0]; + + pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3)); + + if (pCtx->LenInBitCount[0] < temp) + pCtx->LenInBitCount[1]++; //carry in + + pCtx->LenInBitCount[1] += LenInBytes >> 29; + + // mod 64 bytes + temp = (temp >> 3) & 0x3f; + + // process lacks of 64-byte data + if (temp) + { + UCHAR *pAds = (UCHAR *) pCtx->Input + temp; + + if ((temp+LenInBytes) < 64) + { + NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes); + return; + } + + NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp); + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + + pData += 64-temp; + LenInBytes -= 64-temp; + } // end of if (temp) + + + TfTimes = (LenInBytes >> 6); + + for (i=TfTimes; i>0; i--) + { + NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64); + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + pData += 64; + LenInBytes -= 64; + } // end of for + + // buffering lacks of 64-byte data + if(LenInBytes) + NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes); + +} + + +/* + * Function Description: + * Append padding bits and length of original message in the tail + * The message digest has to be completed in the end + * + * Arguments: + * Digest Output of Digest-Message for MD5 + * pCtx Pointer to MD5 context + * + * Return Value: + * None + * + * Note: + * Called after MD5Update + */ +VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx) +{ + UCHAR Remainder; + UCHAR PadLenInBytes; + UCHAR *pAppend=0; + unsigned int i; + + Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f); + + PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder); + + pAppend = (UCHAR *)pCtx->Input + Remainder; + + // padding bits without crossing block(64-byte based) boundary + if (Remainder < 56) + { + *pAppend = 0x80; + PadLenInBytes --; + + NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes); + + // add data-length field, from low to high + for (i=0; i<4; i++) + { + pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff); + pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff); + } + + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + } // end of if + + // padding bits with crossing block(64-byte based) boundary + else + { + // the first block === + *pAppend = 0x80; + PadLenInBytes --; + + NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1)); + PadLenInBytes -= (64 - Remainder - 1); + + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + + + // the second block === + NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes); + + // add data-length field + for (i=0; i<4; i++) + { + pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff); + pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff); + } + + byteReverse(pCtx->Input, 16); + MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input); + } // end of else + + + NdisMoveMemory((UCHAR *)Digest, (UINT32 *)pCtx->Buf, 16); // output + byteReverse((UCHAR *)Digest, 4); + NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free +} + + +/* + * Function Description: + * The central algorithm of MD5, consists of four rounds and sixteen + * steps per round + * + * Arguments: + * Buf Buffers of four states (output: 16 bytes) + * Mes Input data (input: 64 bytes) + * + * Return Value: + * None + * + * Note: + * Called by MD5Update or MD5Final + */ +VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16]) +{ + UINT32 Reg[4], Temp; + unsigned int i; + + static UCHAR LShiftVal[16] = + { + 7, 12, 17, 22, + 5, 9 , 14, 20, + 4, 11, 16, 23, + 6, 10, 15, 21, + }; + + + // [equal to 4294967296*abs(sin(index))] + static UINT32 MD5Table[64] = + { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + + + for (i=0; i<4; i++) + Reg[i]=Buf[i]; + + + // 64 steps in MD5 algorithm + for (i=0; i<16; i++) + { + MD5Step(MD5_F1, Reg[0], Reg[1], Reg[2], Reg[3], Mes[i], + MD5Table[i], LShiftVal[i & 0x3]); + + // one-word right shift + Temp = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + } + for (i=16; i<32; i++) + { + MD5Step(MD5_F2, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(5*(i & 0xf)+1) & 0xf], + MD5Table[i], LShiftVal[(0x1 << 2)+(i & 0x3)]); + + // one-word right shift + Temp = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + } + for (i=32; i<48; i++) + { + MD5Step(MD5_F3, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(3*(i & 0xf)+5) & 0xf], + MD5Table[i], LShiftVal[(0x1 << 3)+(i & 0x3)]); + + // one-word right shift + Temp = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + } + for (i=48; i<64; i++) + { + MD5Step(MD5_F4, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(7*(i & 0xf)) & 0xf], + MD5Table[i], LShiftVal[(0x3 << 2)+(i & 0x3)]); + + // one-word right shift + Temp = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + } + + + // (temporary)output + for (i=0; i<4; i++) + Buf[i] += Reg[i]; + +} + + + +/* ========================= SHA-1 implementation ========================== */ +// four base functions for SHA-1 +#define SHA1_F1(b, c, d) (((b) & (c)) | ((~b) & (d))) +#define SHA1_F2(b, c, d) ((b) ^ (c) ^ (d)) +#define SHA1_F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) + + +#define SHA1Step(f, a, b, c, d, e, w, k) \ + ( e += ( f(b, c, d) + w + k + CYCLIC_LEFT_SHIFT(a, 5)) & 0xffffffff, \ + b = CYCLIC_LEFT_SHIFT(b, 30) ) + +//Initiate SHA-1 Context satisfied in RFC 3174 +VOID SHAInit(SHA_CTX *pCtx) +{ + pCtx->Buf[0]=0x67452301; + pCtx->Buf[1]=0xefcdab89; + pCtx->Buf[2]=0x98badcfe; + pCtx->Buf[3]=0x10325476; + pCtx->Buf[4]=0xc3d2e1f0; + + pCtx->LenInBitCount[0]=0; + pCtx->LenInBitCount[1]=0; +} + +/* + * Function Description: + * Update SHA-1 Context, allow of an arrary of octets as the next + * portion of the message + * + * Arguments: + * pCtx Pointer to SHA-1 context + * pData Pointer to input data + * LenInBytes The length of input data (unit: byte) + * + * Return Value: + * error indicate more than pow(2,64) bits of data + * + * Note: + * Called after SHAInit or SHAUpdate(itself) + */ +UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes) +{ + UINT32 TfTimes; + UINT32 temp1,temp2; + unsigned int i; + UCHAR err=1; + + temp1 = pCtx->LenInBitCount[0]; + temp2 = pCtx->LenInBitCount[1]; + + pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3)); + if (pCtx->LenInBitCount[0] < temp1) + pCtx->LenInBitCount[1]++; //carry in + + + pCtx->LenInBitCount[1] = (UINT32) (pCtx->LenInBitCount[1] +(LenInBytes >> 29)); + if (pCtx->LenInBitCount[1] < temp2) + return (err); //check total length of original data + + + // mod 64 bytes + temp1 = (temp1 >> 3) & 0x3f; + + // process lacks of 64-byte data + if (temp1) + { + UCHAR *pAds = (UCHAR *) pCtx->Input + temp1; + + if ((temp1+LenInBytes) < 64) + { + NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes); + return (0); + } + + NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp1); + byteReverse((UCHAR *)pCtx->Input, 16); + + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + + pData += 64-temp1; + LenInBytes -= 64-temp1; + } // end of if (temp1) + + + TfTimes = (LenInBytes >> 6); + + for (i=TfTimes; i>0; i--) + { + NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64); + byteReverse((UCHAR *)pCtx->Input, 16); + + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + pData += 64; + LenInBytes -= 64; + } // end of for + + // buffering lacks of 64-byte data + if(LenInBytes) + NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes); + + return (0); + +} + +// Append padding bits and length of original message in the tail +// The message digest has to be completed in the end +VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20]) +{ + UCHAR Remainder; + UCHAR PadLenInBytes; + UCHAR *pAppend=0; + unsigned int i; + + Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f); + + pAppend = (UCHAR *)pCtx->Input + Remainder; + + PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder); + + // padding bits without crossing block(64-byte based) boundary + if (Remainder < 56) + { + *pAppend = 0x80; + PadLenInBytes --; + + NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes); + + // add data-length field, from high to low + for (i=0; i<4; i++) + { + pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff); + pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff); + } + + byteReverse((UCHAR *)pCtx->Input, 16); + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 14); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + } // end of if + + // padding bits with crossing block(64-byte based) boundary + else + { + // the first block === + *pAppend = 0x80; + PadLenInBytes --; + + NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1)); + PadLenInBytes -= (64 - Remainder - 1); + + byteReverse((UCHAR *)pCtx->Input, 16); + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + + + // the second block === + NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes); + + // add data-length field + for (i=0; i<4; i++) + { + pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff); + pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff); + } + + byteReverse((UCHAR *)pCtx->Input, 16); + NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16); + SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input); + } // end of else + + + //Output, bytereverse + for (i=0; i<20; i++) + { + Digest [i] = (UCHAR)(pCtx->Buf[i>>2] >> 8*(3-(i & 0x3))); + } + + NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free +} + + +// The central algorithm of SHA-1, consists of four rounds and +// twenty steps per round +VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20]) +{ + UINT32 Reg[5],Temp; + unsigned int i; + UINT32 W[80]; + + static UINT32 SHA1Table[4] = { 0x5a827999, 0x6ed9eba1, + 0x8f1bbcdc, 0xca62c1d6 }; + + Reg[0]=Buf[0]; + Reg[1]=Buf[1]; + Reg[2]=Buf[2]; + Reg[3]=Buf[3]; + Reg[4]=Buf[4]; + + //the first octet of a word is stored in the 0th element, bytereverse + for(i = 0; i < 16; i++) + { + W[i] = (Mes[i] >> 24) & 0xff; + W[i] |= (Mes[i] >> 8 ) & 0xff00; + W[i] |= (Mes[i] << 8 ) & 0xff0000; + W[i] |= (Mes[i] << 24) & 0xff000000; + } + + + for (i = 0; i < 64; i++) + W[16+i] = CYCLIC_LEFT_SHIFT(W[i] ^ W[2+i] ^ W[8+i] ^ W[13+i], 1); + + + // 80 steps in SHA-1 algorithm + for (i=0; i<80; i++) + { + if (i<20) + SHA1Step(SHA1_F1, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], + W[i], SHA1Table[0]); + + else if (i>=20 && i<40) + SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], + W[i], SHA1Table[1]); + + else if (i>=40 && i<60) + SHA1Step(SHA1_F3, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], + W[i], SHA1Table[2]); + + else + SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4], + W[i], SHA1Table[3]); + + + // one-word right shift + Temp = Reg[4]; + Reg[4] = Reg[3]; + Reg[3] = Reg[2]; + Reg[2] = Reg[1]; + Reg[1] = Reg[0]; + Reg[0] = Temp; + + } // end of for-loop + + + // (temporary)output + for (i=0; i<5; i++) + Buf[i] += Reg[i]; + +} + + +/* ========================= AES En/Decryption ========================== */ + +/* forward S-box */ +static uint32 FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* forward table */ +#define FT \ +\ + V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \ + V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \ + V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \ + V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \ + V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \ + V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \ + V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \ + V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \ + V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \ + V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \ + V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \ + V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \ + V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \ + V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \ + V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \ + V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \ + V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \ + V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \ + V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \ + V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \ + V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \ + V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \ + V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \ + V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \ + V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \ + V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \ + V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \ + V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \ + V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \ + V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \ + V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \ + V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \ + V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \ + V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \ + V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \ + V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \ + V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \ + V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \ + V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \ + V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \ + V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \ + V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \ + V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \ + V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \ + V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \ + V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \ + V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \ + V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \ + V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \ + V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \ + V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \ + V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \ + V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \ + V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \ + V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \ + V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \ + V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \ + V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \ + V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \ + V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \ + V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \ + V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \ + V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \ + V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A) + +#define V(a,b,c,d) 0x##a##b##c##d +static uint32 FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static uint32 FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static uint32 FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static uint32 FT3[256] = { FT }; +#undef V + +#undef FT + +/* reverse S-box */ + +static uint32 RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* reverse table */ + +#define RT \ +\ + V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \ + V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \ + V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \ + V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \ + V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \ + V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \ + V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \ + V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \ + V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \ + V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \ + V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \ + V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \ + V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \ + V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \ + V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \ + V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \ + V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \ + V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \ + V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \ + V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \ + V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \ + V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \ + V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \ + V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \ + V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \ + V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \ + V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \ + V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \ + V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \ + V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \ + V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \ + V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \ + V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \ + V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \ + V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \ + V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \ + V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \ + V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \ + V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \ + V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \ + V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \ + V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \ + V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \ + V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \ + V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \ + V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \ + V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \ + V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \ + V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \ + V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \ + V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \ + V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \ + V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \ + V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \ + V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \ + V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \ + V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \ + V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \ + V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \ + V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \ + V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \ + V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \ + V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \ + V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42) + +#define V(a,b,c,d) 0x##a##b##c##d +static uint32 RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static uint32 RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static uint32 RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static uint32 RT3[256] = { RT }; +#undef V + +#undef RT + +/* round constants */ + +static uint32 RCON[10] = +{ + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000 +}; + +/* key schedule tables */ + +static int KT_init = 1; + +static uint32 KT0[256]; +static uint32 KT1[256]; +static uint32 KT2[256]; +static uint32 KT3[256]; + +/* platform-independant 32-bit integer manipulation macros */ + +#define GET_UINT32(n,b,i) \ +{ \ + (n) = ( (uint32) (b)[(i) ] << 24 ) \ + | ( (uint32) (b)[(i) + 1] << 16 ) \ + | ( (uint32) (b)[(i) + 2] << 8 ) \ + | ( (uint32) (b)[(i) + 3] ); \ +} + +#define PUT_UINT32(n,b,i) \ +{ \ + (b)[(i) ] = (uint8) ( (n) >> 24 ); \ + (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \ + (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \ + (b)[(i) + 3] = (uint8) ( (n) ); \ +} + +/* AES key scheduling routine */ + +int rtmp_aes_set_key( aes_context *ctx, uint8 *key, int nbits ) +{ + int i; + uint32 *RK, *SK; + + switch( nbits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( 1 ); + } + + RK = ctx->erk; + + for( i = 0; i < (nbits >> 5); i++ ) + { + GET_UINT32( RK[i], key, i * 4 ); + } + + /* setup encryption round keys */ + + switch( nbits ) + { + case 128: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( FSb[ (uint8) ( RK[3] >> 16 ) ] << 24 ) ^ + ( FSb[ (uint8) ( RK[3] >> 8 ) ] << 16 ) ^ + ( FSb[ (uint8) ( RK[3] ) ] << 8 ) ^ + ( FSb[ (uint8) ( RK[3] >> 24 ) ] ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 192: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( FSb[ (uint8) ( RK[5] >> 16 ) ] << 24 ) ^ + ( FSb[ (uint8) ( RK[5] >> 8 ) ] << 16 ) ^ + ( FSb[ (uint8) ( RK[5] ) ] << 8 ) ^ + ( FSb[ (uint8) ( RK[5] >> 24 ) ] ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 256: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( FSb[ (uint8) ( RK[7] >> 16 ) ] << 24 ) ^ + ( FSb[ (uint8) ( RK[7] >> 8 ) ] << 16 ) ^ + ( FSb[ (uint8) ( RK[7] ) ] << 8 ) ^ + ( FSb[ (uint8) ( RK[7] >> 24 ) ] ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( RK[11] >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( RK[11] ) ] ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + /* setup decryption round keys */ + + if( KT_init ) + { + for( i = 0; i < 256; i++ ) + { + KT0[i] = RT0[ FSb[i] ]; + KT1[i] = RT1[ FSb[i] ]; + KT2[i] = RT2[ FSb[i] ]; + KT3[i] = RT3[ FSb[i] ]; + } + + KT_init = 0; + } + + SK = ctx->drk; + + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + + for( i = 1; i < ctx->nr; i++ ) + { + RK -= 8; + + *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ + KT1[ (uint8) ( *RK >> 16 ) ] ^ + KT2[ (uint8) ( *RK >> 8 ) ] ^ + KT3[ (uint8) ( *RK ) ]; RK++; + + *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ + KT1[ (uint8) ( *RK >> 16 ) ] ^ + KT2[ (uint8) ( *RK >> 8 ) ] ^ + KT3[ (uint8) ( *RK ) ]; RK++; + + *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ + KT1[ (uint8) ( *RK >> 16 ) ] ^ + KT2[ (uint8) ( *RK >> 8 ) ] ^ + KT3[ (uint8) ( *RK ) ]; RK++; + + *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^ + KT1[ (uint8) ( *RK >> 16 ) ] ^ + KT2[ (uint8) ( *RK >> 8 ) ] ^ + KT3[ (uint8) ( *RK ) ]; RK++; + } + + RK -= 8; + + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + *SK++ = *RK++; + + return( 0 ); +} + +/* AES 128-bit block encryption routine */ + +void rtmp_aes_encrypt(aes_context *ctx, uint8 input[16], uint8 output[16] ) +{ + uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->erk; + GET_UINT32( X0, input, 0 ); X0 ^= RK[0]; + GET_UINT32( X1, input, 4 ); X1 ^= RK[1]; + GET_UINT32( X2, input, 8 ); X2 ^= RK[2]; + GET_UINT32( X3, input, 12 ); X3 ^= RK[3]; + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + RK += 4; \ + \ + X0 = RK[0] ^ FT0[ (uint8) ( Y0 >> 24 ) ] ^ \ + FT1[ (uint8) ( Y1 >> 16 ) ] ^ \ + FT2[ (uint8) ( Y2 >> 8 ) ] ^ \ + FT3[ (uint8) ( Y3 ) ]; \ + \ + X1 = RK[1] ^ FT0[ (uint8) ( Y1 >> 24 ) ] ^ \ + FT1[ (uint8) ( Y2 >> 16 ) ] ^ \ + FT2[ (uint8) ( Y3 >> 8 ) ] ^ \ + FT3[ (uint8) ( Y0 ) ]; \ + \ + X2 = RK[2] ^ FT0[ (uint8) ( Y2 >> 24 ) ] ^ \ + FT1[ (uint8) ( Y3 >> 16 ) ] ^ \ + FT2[ (uint8) ( Y0 >> 8 ) ] ^ \ + FT3[ (uint8) ( Y1 ) ]; \ + \ + X3 = RK[3] ^ FT0[ (uint8) ( Y3 >> 24 ) ] ^ \ + FT1[ (uint8) ( Y0 >> 16 ) ] ^ \ + FT2[ (uint8) ( Y1 >> 8 ) ] ^ \ + FT3[ (uint8) ( Y2 ) ]; \ +} + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ + + if( ctx->nr > 10 ) + { + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ + } + + if( ctx->nr > 12 ) + { + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ + } + + /* last round */ + + RK += 4; + + X0 = RK[0] ^ ( FSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( Y3 ) ] ); + + X1 = RK[1] ^ ( FSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( Y0 ) ] ); + + X2 = RK[2] ^ ( FSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( Y1 ) ] ); + + X3 = RK[3] ^ ( FSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ + ( FSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ + ( FSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ + ( FSb[ (uint8) ( Y2 ) ] ); + + PUT_UINT32( X0, output, 0 ); + PUT_UINT32( X1, output, 4 ); + PUT_UINT32( X2, output, 8 ); + PUT_UINT32( X3, output, 12 ); +} + +/* AES 128-bit block decryption routine */ + +void rtmp_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ) +{ + uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->drk; + + GET_UINT32( X0, input, 0 ); X0 ^= RK[0]; + GET_UINT32( X1, input, 4 ); X1 ^= RK[1]; + GET_UINT32( X2, input, 8 ); X2 ^= RK[2]; + GET_UINT32( X3, input, 12 ); X3 ^= RK[3]; + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + RK += 4; \ + \ + X0 = RK[0] ^ RT0[ (uint8) ( Y0 >> 24 ) ] ^ \ + RT1[ (uint8) ( Y3 >> 16 ) ] ^ \ + RT2[ (uint8) ( Y2 >> 8 ) ] ^ \ + RT3[ (uint8) ( Y1 ) ]; \ + \ + X1 = RK[1] ^ RT0[ (uint8) ( Y1 >> 24 ) ] ^ \ + RT1[ (uint8) ( Y0 >> 16 ) ] ^ \ + RT2[ (uint8) ( Y3 >> 8 ) ] ^ \ + RT3[ (uint8) ( Y2 ) ]; \ + \ + X2 = RK[2] ^ RT0[ (uint8) ( Y2 >> 24 ) ] ^ \ + RT1[ (uint8) ( Y1 >> 16 ) ] ^ \ + RT2[ (uint8) ( Y0 >> 8 ) ] ^ \ + RT3[ (uint8) ( Y3 ) ]; \ + \ + X3 = RK[3] ^ RT0[ (uint8) ( Y3 >> 24 ) ] ^ \ + RT1[ (uint8) ( Y2 >> 16 ) ] ^ \ + RT2[ (uint8) ( Y1 >> 8 ) ] ^ \ + RT3[ (uint8) ( Y0 ) ]; \ +} + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */ + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */ + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */ + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */ + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */ + + if( ctx->nr > 10 ) + { + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */ + } + + if( ctx->nr > 12 ) + { + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */ + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */ + } + + /* last round */ + + RK += 4; + + X0 = RK[0] ^ ( RSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^ + ( RSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^ + ( RSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^ + ( RSb[ (uint8) ( Y1 ) ] ); + + X1 = RK[1] ^ ( RSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^ + ( RSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^ + ( RSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^ + ( RSb[ (uint8) ( Y2 ) ] ); + + X2 = RK[2] ^ ( RSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^ + ( RSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^ + ( RSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^ + ( RSb[ (uint8) ( Y3 ) ] ); + + X3 = RK[3] ^ ( RSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^ + ( RSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^ + ( RSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^ + ( RSb[ (uint8) ( Y0 ) ] ); + + PUT_UINT32( X0, output, 0 ); + PUT_UINT32( X1, output, 4 ); + PUT_UINT32( X2, output, 8 ); + PUT_UINT32( X3, output, 12 ); +} + +/* + ======================================================================== + + Routine Description: + SHA1 function + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID HMAC_SHA1( + IN UCHAR *text, + IN UINT text_len, + IN UCHAR *key, + IN UINT key_len, + IN UCHAR *digest) +{ + SHA_CTX context; + UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */ + UCHAR k_opad[65]; /* outer padding - key XORd with opad */ + INT i; + + // if key is longer than 64 bytes reset it to key=SHA1(key) + if (key_len > 64) + { + SHA_CTX tctx; + SHAInit(&tctx); + SHAUpdate(&tctx, key, key_len); + SHAFinal(&tctx, key); + key_len = 20; + } + NdisZeroMemory(k_ipad, sizeof(k_ipad)); + NdisZeroMemory(k_opad, sizeof(k_opad)); + NdisMoveMemory(k_ipad, key, key_len); + NdisMoveMemory(k_opad, key, key_len); + + // XOR key with ipad and opad values + for (i = 0; i < 64; i++) + { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + // perform inner SHA1 + SHAInit(&context); /* init context for 1st pass */ + SHAUpdate(&context, k_ipad, 64); /* start with inner pad */ + SHAUpdate(&context, text, text_len); /* then text of datagram */ + SHAFinal(&context, digest); /* finish up 1st pass */ + + //perform outer SHA1 + SHAInit(&context); /* init context for 2nd pass */ + SHAUpdate(&context, k_opad, 64); /* start with outer pad */ + SHAUpdate(&context, digest, 20); /* then results of 1st hash */ + SHAFinal(&context, digest); /* finish up 2nd pass */ + +} + +/* +* F(P, S, c, i) = U1 xor U2 xor ... Uc +* U1 = PRF(P, S || Int(i)) +* U2 = PRF(P, U1) +* Uc = PRF(P, Uc-1) +*/ + +void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output) +{ + unsigned char digest[36], digest1[SHA_DIGEST_LEN]; + int i, j; + + /* U1 = PRF(P, S || int(i)) */ + memcpy(digest, ssid, ssidlength); + digest[ssidlength] = (unsigned char)((count>>24) & 0xff); + digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff); + digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff); + digest[ssidlength+3] = (unsigned char)(count & 0xff); + HMAC_SHA1(digest, ssidlength+4, (unsigned char*) password, (int) strlen(password), digest1); // for WPA update + + /* output = U1 */ + memcpy(output, digest1, SHA_DIGEST_LEN); + + for (i = 1; i < iterations; i++) + { + /* Un = PRF(P, Un-1) */ + HMAC_SHA1(digest1, SHA_DIGEST_LEN, (unsigned char*) password, (int) strlen(password), digest); // for WPA update + memcpy(digest1, digest, SHA_DIGEST_LEN); + + /* output = output xor Un */ + for (j = 0; j < SHA_DIGEST_LEN; j++) + { + output[j] ^= digest[j]; + } + } +} +/* +* password - ascii string up to 63 characters in length +* ssid - octet string up to 32 octets +* ssidlength - length of ssid in octets +* output must be 40 octets in length and outputs 256 bits of key +*/ +int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output) +{ + if ((strlen(password) > 63) || (ssidlength > 32)) + return 0; + + F(password, ssid, ssidlength, 4096, 1, output); + F(password, ssid, ssidlength, 4096, 2, &output[SHA_DIGEST_LEN]); + return 1; +} + + diff --git a/drivers/staging/rt3070/common/mlme.c b/drivers/staging/rt3070/common/mlme.c new file mode 100644 index 000000000000..0ffbfa36699e --- /dev/null +++ b/drivers/staging/rt3070/common/mlme.c @@ -0,0 +1,9136 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + mlme.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-08-25 Modify from RT2500 code base + John Chang 2004-09-06 modified for RT2600 +*/ + +#include "../rt_config.h" +#include + +UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96}; + +UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; +UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac}; +UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72}; +UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; +UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; +UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04}; +UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43}; +UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c}; +UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT +UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c}; +#endif // DOT11_N_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +UCHAR RateSwitchTable[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x11, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, + 0x04, 0x21, 0, 30, 50, + 0x05, 0x21, 1, 20, 50, + 0x06, 0x21, 2, 20, 50, + 0x07, 0x21, 3, 15, 50, + 0x08, 0x21, 4, 15, 30, + 0x09, 0x21, 5, 10, 25, + 0x0a, 0x21, 6, 8, 25, + 0x0b, 0x21, 7, 8, 25, + 0x0c, 0x20, 12, 15, 30, + 0x0d, 0x20, 13, 8, 20, + 0x0e, 0x20, 14, 8, 20, + 0x0f, 0x20, 15, 8, 25, + 0x10, 0x22, 15, 8, 25, + 0x11, 0x00, 0, 0, 0, + 0x12, 0x00, 0, 0, 0, + 0x13, 0x00, 0, 0, 0, + 0x14, 0x00, 0, 0, 0, + 0x15, 0x00, 0, 0, 0, + 0x16, 0x00, 0, 0, 0, + 0x17, 0x00, 0, 0, 0, + 0x18, 0x00, 0, 0, 0, + 0x19, 0x00, 0, 0, 0, + 0x1a, 0x00, 0, 0, 0, + 0x1b, 0x00, 0, 0, 0, + 0x1c, 0x00, 0, 0, 0, + 0x1d, 0x00, 0, 0, 0, + 0x1e, 0x00, 0, 0, 0, + 0x1f, 0x00, 0, 0, 0, +}; + +UCHAR RateSwitchTable11B[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x04, 0x03, 0, 0, 0, // Initial used item after association + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, +}; + +UCHAR RateSwitchTable11BG[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, + 0x04, 0x10, 2, 20, 35, + 0x05, 0x10, 3, 16, 35, + 0x06, 0x10, 4, 10, 25, + 0x07, 0x10, 5, 16, 25, + 0x08, 0x10, 6, 10, 25, + 0x09, 0x10, 7, 10, 13, +}; + +UCHAR RateSwitchTable11G[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x08, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x10, 0, 20, 101, + 0x01, 0x10, 1, 20, 35, + 0x02, 0x10, 2, 20, 35, + 0x03, 0x10, 3, 16, 35, + 0x04, 0x10, 4, 10, 25, + 0x05, 0x10, 5, 16, 25, + 0x06, 0x10, 6, 10, 25, + 0x07, 0x10, 7, 10, 13, +}; + +#ifdef DOT11_N_SUPPORT +UCHAR RateSwitchTable11N1S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x09, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 10, 25, + 0x06, 0x21, 6, 8, 14, + 0x07, 0x21, 7, 8, 14, + 0x08, 0x23, 7, 8, 14, +}; + +UCHAR RateSwitchTable11N2S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x20, 12, 15, 30, + 0x06, 0x20, 13, 8, 20, + 0x07, 0x20, 14, 8, 20, + 0x08, 0x20, 15, 8, 25, + 0x09, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11N3S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x20, 12, 15, 30, + 0x06, 0x20, 13, 8, 20, + 0x07, 0x20, 14, 8, 20, + 0x08, 0x20, 15, 8, 25, + 0x09, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11N2SForABand[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0b, 0x09, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11N3SForABand[] = { // 3*3 +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0b, 0x09, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30, 101, + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11BGN1S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0d, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x00, 0, 40, 101, + 0x01, 0x00, 1, 40, 50, + 0x02, 0x00, 2, 35, 45, + 0x03, 0x00, 3, 20, 45, + 0x04, 0x21, 0, 30,101, //50 + 0x05, 0x21, 1, 20, 50, + 0x06, 0x21, 2, 20, 50, + 0x07, 0x21, 3, 15, 50, + 0x08, 0x21, 4, 15, 30, + 0x09, 0x21, 5, 10, 25, + 0x0a, 0x21, 6, 8, 14, + 0x0b, 0x21, 7, 8, 14, + 0x0c, 0x23, 7, 8, 14, +}; + +UCHAR RateSwitchTable11BGN2S[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30,101, //50 + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x20, 12, 15, 30, + 0x06, 0x20, 13, 8, 20, + 0x07, 0x20, 14, 8, 20, + 0x08, 0x20, 15, 8, 25, + 0x09, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11BGN3S[] = { // 3*3 +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0a, 0x00, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30,101, //50 + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 20, 50, + 0x04, 0x21, 4, 15, 50, +#if 1 + 0x05, 0x20, 20, 15, 30, + 0x06, 0x20, 21, 8, 20, + 0x07, 0x20, 22, 8, 20, + 0x08, 0x20, 23, 8, 25, + 0x09, 0x22, 23, 8, 25, +#else // for RT2860 2*3 test + 0x05, 0x20, 12, 15, 30, + 0x06, 0x20, 13, 8, 20, + 0x07, 0x20, 14, 8, 20, + 0x08, 0x20, 15, 8, 25, + 0x09, 0x22, 15, 8, 25, +#endif +}; + +UCHAR RateSwitchTable11BGN2SForABand[] = { +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0b, 0x09, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30,101, //50 + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x20, 12, 15, 30, + 0x07, 0x20, 13, 8, 20, + 0x08, 0x20, 14, 8, 20, + 0x09, 0x20, 15, 8, 25, + 0x0a, 0x22, 15, 8, 25, +}; + +UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3 +// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) + 0x0c, 0x09, 0, 0, 0, // Initial used item after association + 0x00, 0x21, 0, 30,101, //50 + 0x01, 0x21, 1, 20, 50, + 0x02, 0x21, 2, 20, 50, + 0x03, 0x21, 3, 15, 50, + 0x04, 0x21, 4, 15, 30, + 0x05, 0x21, 5, 15, 30, + 0x06, 0x21, 12, 15, 30, + 0x07, 0x20, 20, 15, 30, + 0x08, 0x20, 21, 8, 20, + 0x09, 0x20, 22, 8, 20, + 0x0a, 0x20, 23, 8, 25, + 0x0b, 0x22, 23, 8, 25, +}; +#endif // DOT11_N_SUPPORT // + +PUCHAR ReasonString[] = { + /* 0 */ "Reserved", + /* 1 */ "Unspecified Reason", + /* 2 */ "Previous Auth no longer valid", + /* 3 */ "STA is leaving / has left", + /* 4 */ "DIS-ASSOC due to inactivity", + /* 5 */ "AP unable to hanle all associations", + /* 6 */ "class 2 error", + /* 7 */ "class 3 error", + /* 8 */ "STA is leaving / has left", + /* 9 */ "require auth before assoc/re-assoc", + /* 10 */ "Reserved", + /* 11 */ "Reserved", + /* 12 */ "Reserved", + /* 13 */ "invalid IE", + /* 14 */ "MIC error", + /* 15 */ "4-way handshake timeout", + /* 16 */ "2-way (group key) handshake timeout", + /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon", + /* 18 */ +}; + +extern UCHAR OfdmRateToRxwiMCS[]; +// since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. +// otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate +ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */, + 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */, + 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */}; + +UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00}; +UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than +// this value, then it's quaranteed capable of operating in 36 mbps TX rate in +// clean environment. +// TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 +CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 }; + +UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100}; +USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200}; + +UCHAR SsidIe = IE_SSID; +UCHAR SupRateIe = IE_SUPP_RATES; +UCHAR ExtRateIe = IE_EXT_SUPP_RATES; +#ifdef DOT11_N_SUPPORT +UCHAR HtCapIe = IE_HT_CAP; +UCHAR AddHtInfoIe = IE_ADD_HT; +UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET; +#ifdef DOT11N_DRAFT3 +UCHAR ExtHtCapIe = IE_EXT_CAPABILITY; +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // +UCHAR ErpIe = IE_ERP; +UCHAR DsIe = IE_DS_PARM; +UCHAR TimIe = IE_TIM; +UCHAR WpaIe = IE_WPA; +UCHAR Wpa2Ie = IE_WPA2; +UCHAR IbssIe = IE_IBSS_PARM; +UCHAR Ccx2Ie = IE_CCX_V2; +UCHAR WapiIe = IE_WAPI; + +extern UCHAR WPA_OUI[]; + +UCHAR SES_OUI[] = {0x00, 0x90, 0x4c}; + +UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + +// Reset the RFIC setting to new series +RTMP_RF_REGS RF2850RegTable[] = { +// ch R1 R2 R3(TX0~4=0) R4 + {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b}, + {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f}, + {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b}, + {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f}, + {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b}, + {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f}, + {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b}, + {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f}, + {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b}, + {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f}, + {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b}, + {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f}, + {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b}, + {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193}, + + // 802.11 UNI / HyperLan 2 + {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3}, + {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193}, + {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183}, + {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3}, + {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b}, + {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b}, + {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193}, + {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3}, + {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b}, + {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183}, + {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193}, + {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5. + + // 802.11 HyperLan 2 + {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783}, + + // 2008.04.30 modified + // The system team has AN to improve the EVM value + // for channel 102 to 108 for the RT2850/RT2750 dual band solution. + {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793}, + {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3}, + {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193}, + + {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183}, + {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b}, + {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3}, + {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193}, + {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183}, + {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193}, + {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927 + {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3}, + {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b}, + {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193}, + {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b}, + {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183}, + + // 802.11 UNII + {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7}, + {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187}, + {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f}, + {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f}, + {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7}, + {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187}, + {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197}, + + // Japan + {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b}, + {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13}, + {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b}, + {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23}, + {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13}, + {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b}, + {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23}, + + // still lack of MMAC(Japan) ch 34,38,42,46 +}; +UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS)); + +FREQUENCY_ITEM FreqItems3020[] = +{ + /**************************************************/ + // ISM : 2.4 to 2.483 GHz // + /**************************************************/ + // 11g + /**************************************************/ + //-CH---N-------R---K----------- + {1, 241, 2, 2}, + {2, 241, 2, 7}, + {3, 242, 2, 2}, + {4, 242, 2, 7}, + {5, 243, 2, 2}, + {6, 243, 2, 7}, + {7, 244, 2, 2}, + {8, 244, 2, 7}, + {9, 245, 2, 2}, + {10, 245, 2, 7}, + {11, 246, 2, 2}, + {12, 246, 2, 7}, + {13, 247, 2, 2}, + {14, 248, 2, 4}, +}; +//2008/07/10:KH Modified to share this variable +UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM)); + +/* + ========================================================================== + Description: + initialize the MLME task and its data structure (queue, spinlock, + timer, state machines). + + IRQL = PASSIVE_LEVEL + + Return: + always return NDIS_STATUS_SUCCESS + + ========================================================================== +*/ +NDIS_STATUS MlmeInit( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n")); + + do + { + Status = MlmeQueueInit(&pAd->Mlme.Queue); + if(Status != NDIS_STATUS_SUCCESS) + break; + + pAd->Mlme.bRunning = FALSE; + NdisAllocateSpinLock(&pAd->Mlme.TaskLock); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + BssTableInit(&pAd->ScanTab); + + // init STA state machines + AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc); + AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc); + AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc); + SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc); + WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc); + AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc); + +#ifdef QOS_DLS_SUPPORT + DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc); +#endif // QOS_DLS_SUPPORT // + + + // Since we are using switch/case to implement it, the init is different from the above + // state machine init + MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL); + } +#endif // CONFIG_STA_SUPPORT // + + + + ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc); + + // Init mlme periodic timer + RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE); + + // Set mlme periodic timer + RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); + + // software-based RX Antenna diversity + RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE); + + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n")); + + return Status; +} + +/* + ========================================================================== + Description: + main loop of the MLME + Pre: + Mlme has to be initialized, and there are something inside the queue + Note: + This function is invoked from MPSetInformation and MPReceive; + This task guarantee only one MlmeHandler will run. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeHandler( + IN PRTMP_ADAPTER pAd) +{ + MLME_QUEUE_ELEM *Elem = NULL; + + // Only accept MLME and Frame from peer side, no other (control/data) frame should + // get into this state machine + + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + if(pAd->Mlme.bRunning) + { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + return; + } + else + { + pAd->Mlme.bRunning = TRUE; + } + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + + while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num)); + break; + } + +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n")); + break; + } +#endif // RALINK_ATE // + + //From message type, determine which state machine I should drive + if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) + { +#ifdef RT2870 + if (Elem->MsgType == MT2_RESET_CONF) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n")); + MlmeRestartStateMachine(pAd); + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + continue; + } +#endif // RT2870 // + + // if dequeue success + switch (Elem->Machine) + { + // STA state machines +#ifdef CONFIG_STA_SUPPORT + case ASSOC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem); + break; + case AUTH_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem); + break; + case AUTH_RSP_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem); + break; + case SYNC_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem); + break; + case MLME_CNTL_STATE_MACHINE: + MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem); + break; + case WPA_PSK_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem); + break; +#ifdef LEAP_SUPPORT + case LEAP_STATE_MACHINE: + LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem); + break; +#endif + case AIRONET_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem); + break; + +#ifdef QOS_DLS_SUPPORT + case DLS_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem); + break; +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + + case ACTION_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem); + break; + + + + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine)); + break; + } // end of switch + + // free MLME element + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n")); + } + } + + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + pAd->Mlme.bRunning = FALSE; + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +} + +/* + ========================================================================== + Description: + Destructor of MLME (Destroy queue, state machine, spin lock and timer) + Parameters: + Adapter - NIC Adapter pointer + Post: + The MLME task will no longer work properly + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID MlmeHalt( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; +#ifdef RT3070 + UINT32 TxPinCfg = 0x00050F0F; +#endif // RT3070 // + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n")); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + // disable BEACON generation and other BEACON related hardware timers + AsicDisableSync(pAd); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef QOS_DLS_SUPPORT + UCHAR i; +#endif // QOS_DLS_SUPPORT // + // Cancel pending timers + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + +#ifdef QOS_DLS_SUPPORT + for (i=0; iStaCfg.DLSEntry[i].Timer, &Cancelled); + } +#endif // QOS_DLS_SUPPORT // + } +#endif // CONFIG_STA_SUPPORT // + + RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled); + + + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + // Set LED + RTMPSetLED(pAd, LED_HALT); + RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it. +#ifdef RT2870 + { + LED_CFG_STRUC LedCfg; + RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word); + LedCfg.field.LedPolar = 0; + LedCfg.field.RLedMode = 0; + LedCfg.field.GLedMode = 0; + LedCfg.field.YLedMode = 0; + RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word); + } +#endif // RT2870 // +#ifdef RT3070 + // + // Turn off LNA_PE + // + if (IS_RT3070(pAd) || IS_RT3071(pAd)) + { + TxPinCfg &= 0xFFFFF0F0; + RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg); + } +#endif // RT3070 // + } + + RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled + + MlmeQueueDestroy(&pAd->Mlme.Queue); + NdisFreeSpinLock(&pAd->Mlme.TaskLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n")); +} + +VOID MlmeResetRalinkCounters( + IN PRTMP_ADAPTER pAd) +{ + pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt; + // clear all OneSecxxx counters. + pAd->RalinkCounters.OneSecBeaconSentCnt = 0; + pAd->RalinkCounters.OneSecFalseCCACnt = 0; + pAd->RalinkCounters.OneSecRxFcsErrCnt = 0; + pAd->RalinkCounters.OneSecRxOkCnt = 0; + pAd->RalinkCounters.OneSecTxFailCount = 0; + pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0; + pAd->RalinkCounters.OneSecTxRetryOkCount = 0; + pAd->RalinkCounters.OneSecRxOkDataCnt = 0; + + // TODO: for debug only. to be removed + pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0; + pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0; + pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0; + pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0; + pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0; + pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0; + pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0; + pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0; + pAd->RalinkCounters.OneSecTxDoneCount = 0; + pAd->RalinkCounters.OneSecRxCount = 0; + pAd->RalinkCounters.OneSecTxAggregationCount = 0; + pAd->RalinkCounters.OneSecRxAggregationCount = 0; + + return; +} + +unsigned long rx_AMSDU; +unsigned long rx_Total; + +/* + ========================================================================== + Description: + This routine is executed periodically to - + 1. Decide if it's a right time to turn on PwrMgmt bit of all + outgoiing frames + 2. Calculate ChannelQuality based on statistics of the last + period, so that TX rate won't toggling very frequently between a + successful TX and a failed TX. + 3. If the calculated ChannelQuality indicated current connection not + healthy, then a ROAMing attempt is tried here. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec +VOID MlmePeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + ULONG TxTotalCnt; + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RADIO_MEASUREMENT | + fRTMP_ADAPTER_RESET_IN_PROGRESS)))) + return; + + RT28XX_MLME_PRE_SANITY_CHECK(pAd); + +#ifdef RALINK_ATE + /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */ + if (ATE_ON(pAd)) + { + if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1)) + { + pAd->Mlme.PeriodicRound ++; + return; + } + } +#endif // RALINK_ATE // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Do nothing if monitor mode is on + if (MONITOR_ON(pAd)) + return; + + if (pAd->Mlme.PeriodicRound & 0x1) + { + // This is the fix for wifi 11n extension channel overlapping test case. for 2860D + if (((pAd->MACVersion & 0xffff) == 0x0101) && + (STA_TGN_WIFI_ON(pAd)) && + (pAd->CommonCfg.IOTestParm.bToggle == FALSE)) + + { + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf); + pAd->CommonCfg.IOTestParm.bToggle = TRUE; + } + else if ((STA_TGN_WIFI_ON(pAd)) && + ((pAd->MACVersion & 0xffff) == 0x0101)) + { + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f); + pAd->CommonCfg.IOTestParm.bToggle = FALSE; + } + } + } +#endif // CONFIG_STA_SUPPORT // + + pAd->bUpdateBcnCntDone = FALSE; + +// RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); + pAd->Mlme.PeriodicRound ++; + +#ifdef RT2870 + // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. + NICUpdateFifoStaCounters(pAd); +#endif // RT2870 // + // execute every 500ms + if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/) + { +#ifdef CONFIG_STA_SUPPORT + // perform dynamic tx rate switching based on past TX history + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))) + MlmeDynamicTxRateSwitching(pAd); + } +#endif // CONFIG_STA_SUPPORT // + } + + // Normal 1 second Mlme PeriodicExec. + if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0) + { + pAd->Mlme.OneSecPeriodicRound ++; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + /* request from Baron : move this routine from later to here */ + /* for showing Rx error count in ATE RXFRAME */ + NICUpdateRawCounters(pAd); + if (pAd->ate.bRxFer == 1) + { + pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec; + ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt); + pAd->ate.RxCntPerSec = 0; + + if (pAd->ate.RxAntennaSel == 0) + ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n", + pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2); + else + ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0); + } + MlmeResetRalinkCounters(pAd); + return; + } +#endif // RALINK_ATE // + + + if (rx_Total) + { + + // reset counters + rx_AMSDU = 0; + rx_Total = 0; + } + + //ORIBATimerTimeout(pAd); + + // Media status changed, report to NDIS + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + pAd->IndicateMediaState = NdisMediaStateConnected; + RTMP_IndicateMediaState(pAd); + + } + else + { + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + } + } + + NdisGetSystemUpTime(&pAd->Mlme.Now32); + + // add the most up-to-date h/w raw counters into software variable, so that + // the dynamic tuning mechanism below are based on most up-to-date information + NICUpdateRawCounters(pAd); + +#ifdef RT2870 + RT2870_WatchDog(pAd); +#endif // RT2870 // + +#ifdef DOT11_N_SUPPORT + // Need statistics after read counter. So put after NICUpdateRawCounters + ORIBATimerTimeout(pAd); +#endif // DOT11_N_SUPPORT // + + // The time period for checking antenna is according to traffic + { + if (pAd->Mlme.bEnableAutoAntennaCheck) + { + TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + // dynamic adjust antenna evaluation period according to the traffic + if (TxTotalCnt > 50) + { + if (pAd->Mlme.OneSecPeriodicRound % 10 == 0) + { + AsicEvaluateRxAnt(pAd); + } + } + else + { + if (pAd->Mlme.OneSecPeriodicRound % 3 == 0) + { + AsicEvaluateRxAnt(pAd); + } + } + } + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + STAMlmePeriodicExec(pAd); +#endif // CONFIG_STA_SUPPORT // + + MlmeResetRalinkCounters(pAd); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + { + // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock + // and sending CTS-to-self over and over. + // Software Patch Solution: + // 1. Polling debug state register 0x10F4 every one second. + // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. + // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. + + UINT32 MacReg = 0; + + RTMP_IO_READ32(pAd, 0x10F4, &MacReg); + if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20))) + { + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + RTMPusecDelay(1); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC); + + DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n")); + } + } + } +#endif // CONFIG_STA_SUPPORT // + + RT28XX_MLME_HANDLER(pAd); + } + + + pAd->bUpdateBcnCntDone = FALSE; +} + +#ifdef CONFIG_STA_SUPPORT +VOID STAMlmePeriodicExec( + PRTMP_ADAPTER pAd) +{ + ULONG TxTotalCnt; + int i; + +// +// We return here in ATE mode, because the statistics +// that ATE needs are not collected via this routine. +// +#ifdef RALINK_ATE + // It is supposed that we will never reach here in ATE mode. + ASSERT(!(ATE_ON(pAd))); + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) +#endif // WPA_SUPPLICANT_SUPPORT // + { + // WPA MIC error should block association attempt for 60 seconds + if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32)) + pAd->StaCfg.bBlockAssoc = FALSE; + } + + if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent)) + { + if (pAd->IndicateMediaState == NdisMediaStateConnected) + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + pAd->PreMediaState = pAd->IndicateMediaState; + } + + + + + AsicStaBbpTuning(pAd); + + TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + // update channel quality for Roaming and UI LinkQuality display + MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32); + } + + // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if + // Radio is currently in noisy environment + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + AsicAdjustTxPower(pAd); + + if (INFRA_ON(pAd)) + { +#ifdef QOS_DLS_SUPPORT + // Check DLS time out, then tear down those session + RTMPCheckDLSTimeOut(pAd); +#endif // QOS_DLS_SUPPORT // + + // Is PSM bit consistent with user power management policy? + // This is the only place that will set PSM bit ON. + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + MlmeCheckPsmChange(pAd, pAd->Mlme.Now32); + + pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt; + + if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600))) + { + RTMPSetAGCInitValue(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd)))); + } + + //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && + // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) + { + if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) + { + // When APSD is enabled, the period changes as 20 sec + if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8) + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + } + else + { + // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) + if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) + { + if (pAd->CommonCfg.bWmmCapable) + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + else + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); + } + } + } + + if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); + pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE; + pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime; + + // Lost AP, send disconnect & link down event + LinkDown(pAd, FALSE); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + { + union iwreq_data wrqu; + //send disassociate event to wpa_supplicant + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + // RTMPPatchMacBbpBug(pAd); + MlmeAutoReconnectLastSSID(pAd); + } + else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) + { + pAd->RalinkCounters.BadCQIAutoRecoveryCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount)); + MlmeAutoReconnectLastSSID(pAd); + } + + // Add auto seamless roaming + if (pAd->StaCfg.bFastRoaming) + { + SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam; + + DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam)); + + if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam) + { + MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32); + } + } + } + else if (ADHOC_ON(pAd)) + { + //radar detect + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + RadarDetectPeriodic(pAd); + } + + // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState + // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can + // join later. + if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + MLME_START_REQ_STRUCT StartReq; + + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n")); + LinkDown(pAd, FALSE); + + StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + + if (pEntry->ValidAsCLI == FALSE) + continue; + + if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) + MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr); + } + } + else // no INFRA nor ADHOC connection + { + + if (pAd->StaCfg.bScanReqIsFromWebUI && + ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32)) + goto SKIP_AUTO_SCAN_CONN; + else + pAd->StaCfg.bScanReqIsFromWebUI = FALSE; + + if ((pAd->StaCfg.bAutoReconnect == TRUE) + && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) + && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) + { + if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) + { + MLME_SCAN_REQ_STRUCT ScanReq; + + if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32) + { + DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid)); + ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + // Reset Missed scan number + pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; + } + else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room + MlmeAutoReconnectLastSSID(pAd); + } + else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) + { + MlmeAutoScan(pAd); + pAd->StaCfg.LastScanTime = pAd->Mlme.Now32; + } + else + { +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1) + MlmeAutoReconnectLastSSID(pAd); + } + else +#endif // CARRIER_DETECTION_SUPPORT // + MlmeAutoReconnectLastSSID(pAd); + } + } + } + } + +SKIP_AUTO_SCAN_CONN: + +#ifdef DOT11_N_SUPPORT + if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE)) + { + pAd->MacTab.fAnyBASession = TRUE; + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE); + } + else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE)) + { + pAd->MacTab.fAnyBASession = FALSE; + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); + } +#endif // DOT11_N_SUPPORT // + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)) + TriEventCounterMaintenance(pAd); +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + + return; +} + +// Link down report +VOID LinkDownExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; +} + +// IRQL = DISPATCH_LEVEL +VOID MlmeAutoScan( + IN PRTMP_ADAPTER pAd) +{ + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n")); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + 0, + NULL); + RT28XX_MLME_HANDLER(pAd); + } +} + +// IRQL = DISPATCH_LEVEL +VOID MlmeAutoReconnectLastSSID( + IN PRTMP_ADAPTER pAd) +{ + + + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && + (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) + { + NDIS_802_11_SSID OidSsid; + OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen; + NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen)); + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + &OidSsid); + RT28XX_MLME_HANDLER(pAd); + } +} +#endif // CONFIG_STA_SUPPORT // + +/* + ========================================================================== + Validate SSID for connection try and rescan purpose + Valid SSID will have visible chars only. + The valid length is from 0 to 32. + IRQL = DISPATCH_LEVEL + ========================================================================== + */ +BOOLEAN MlmeValidateSSID( + IN PUCHAR pSsid, + IN UCHAR SsidLen) +{ + int index; + + if (SsidLen > MAX_LEN_OF_SSID) + return (FALSE); + + // Check each character value + for (index = 0; index < SsidLen; index++) + { + if (pSsid[index] < 0x20) + return (FALSE); + } + + // All checked + return (TRUE); +} + +VOID MlmeSelectTxRateTable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR *ppTable, + IN PUCHAR pTableSize, + IN PUCHAR pInitTxRateIdx) +{ + do + { + // decide the rate table for tuning + if (pAd->CommonCfg.TxRateTableSize > 0) + { + *ppTable = RateSwitchTable; + *pTableSize = RateSwitchTable[0]; + *pInitTxRateIdx = RateSwitchTable[1]; + + break; + } + +#ifdef CONFIG_STA_SUPPORT + if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) + { +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && + (pEntry->HTCapability.MCSSet[0] == 0xff) && + ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) + {// 11N 1S Adhoc + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; + + } + else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && + (pEntry->HTCapability.MCSSet[0] == 0xff) && + (pEntry->HTCapability.MCSSet[1] == 0xff) && + (pAd->Antenna.field.TxPath == 2)) + {// 11N 2S Adhoc + if (pAd->LatchRfRegs.Channel <= 14) + { + *ppTable = RateSwitchTable11N2S; + *pTableSize = RateSwitchTable11N2S[0]; + *pInitTxRateIdx = RateSwitchTable11N2S[1]; + } + else + { + *ppTable = RateSwitchTable11N2SForABand; + *pTableSize = RateSwitchTable11N2SForABand[0]; + *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; + } + + } + else +#endif // DOT11_N_SUPPORT // + if ((pEntry->RateLen == 4) +#ifdef DOT11_N_SUPPORT + && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif // DOT11_N_SUPPORT // + ) + { + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; + + } + else if (pAd->LatchRfRegs.Channel <= 14) + { + *ppTable = RateSwitchTable11BG; + *pTableSize = RateSwitchTable11BG[0]; + *pInitTxRateIdx = RateSwitchTable11BG[1]; + + } + else + { + *ppTable = RateSwitchTable11G; + *pTableSize = RateSwitchTable11G[0]; + *pInitTxRateIdx = RateSwitchTable11G[1]; + + } + break; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef DOT11_N_SUPPORT + //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && + // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) + if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) && + ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) + {// 11BGN 1S AP + *ppTable = RateSwitchTable11BGN1S; + *pTableSize = RateSwitchTable11BGN1S[0]; + *pInitTxRateIdx = RateSwitchTable11BGN1S[1]; + + break; + } + + //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && + // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) + if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) && + (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) + {// 11BGN 2S AP + if (pAd->LatchRfRegs.Channel <= 14) + { + *ppTable = RateSwitchTable11BGN2S; + *pTableSize = RateSwitchTable11BGN2S[0]; + *pInitTxRateIdx = RateSwitchTable11BGN2S[1]; + + } + else + { + *ppTable = RateSwitchTable11BGN2SForABand; + *pTableSize = RateSwitchTable11BGN2SForABand[0]; + *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1]; + + } + break; + } + + //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) + if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) + {// 11N 1S AP + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; + + break; + } + + //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) + if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) + {// 11N 2S AP + if (pAd->LatchRfRegs.Channel <= 14) + { + *ppTable = RateSwitchTable11N2S; + *pTableSize = RateSwitchTable11N2S[0]; + *pInitTxRateIdx = RateSwitchTable11N2S[1]; + } + else + { + *ppTable = RateSwitchTable11N2SForABand; + *pTableSize = RateSwitchTable11N2SForABand[0]; + *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; + } + + break; + } +#endif // DOT11_N_SUPPORT // + //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) + if ((pEntry->RateLen == 4) +#ifdef DOT11_N_SUPPORT +//Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode +// && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif // DOT11_N_SUPPORT // + ) + {// B only AP + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; + + break; + } + + //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) + if ((pEntry->RateLen > 8) +#ifdef DOT11_N_SUPPORT + && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif // DOT11_N_SUPPORT // + ) + {// B/G mixed AP + *ppTable = RateSwitchTable11BG; + *pTableSize = RateSwitchTable11BG[0]; + *pInitTxRateIdx = RateSwitchTable11BG[1]; + + break; + } + + //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) + if ((pEntry->RateLen == 8) +#ifdef DOT11_N_SUPPORT + && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) +#endif // DOT11_N_SUPPORT // + ) + {// G only AP + *ppTable = RateSwitchTable11G; + *pTableSize = RateSwitchTable11G[0]; + *pInitTxRateIdx = RateSwitchTable11G[1]; + + break; + } +#ifdef DOT11_N_SUPPORT +#endif // DOT11_N_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef DOT11_N_SUPPORT + //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) + if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) +#endif // DOT11_N_SUPPORT // + { // Legacy mode + if (pAd->CommonCfg.MaxTxRate <= RATE_11) + { + *ppTable = RateSwitchTable11B; + *pTableSize = RateSwitchTable11B[0]; + *pInitTxRateIdx = RateSwitchTable11B[1]; + } + else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11)) + { + *ppTable = RateSwitchTable11G; + *pTableSize = RateSwitchTable11G[0]; + *pInitTxRateIdx = RateSwitchTable11G[1]; + + } + else + { + *ppTable = RateSwitchTable11BG; + *pTableSize = RateSwitchTable11BG[0]; + *pInitTxRateIdx = RateSwitchTable11BG[1]; + } + break; + } +#ifdef DOT11_N_SUPPORT + if (pAd->LatchRfRegs.Channel <= 14) + { + if (pAd->CommonCfg.TxStream == 1) + { + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); + } + else + { + *ppTable = RateSwitchTable11N2S; + *pTableSize = RateSwitchTable11N2S[0]; + *pInitTxRateIdx = RateSwitchTable11N2S[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); + } + } + else + { + if (pAd->CommonCfg.TxStream == 1) + { + *ppTable = RateSwitchTable11N1S; + *pTableSize = RateSwitchTable11N1S[0]; + *pInitTxRateIdx = RateSwitchTable11N1S[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n")); + } + else + { + *ppTable = RateSwitchTable11N2SForABand; + *pTableSize = RateSwitchTable11N2SForABand[0]; + *pInitTxRateIdx = RateSwitchTable11N2SForABand[1]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n")); + } + } +#endif // DOT11_N_SUPPORT // + DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n", + pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1])); + } +#endif // CONFIG_STA_SUPPORT // + } while(FALSE); +} + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + This routine checks if there're other APs out there capable for + roaming. Caller should call this routine only when Link up in INFRA mode + and channel quality is below CQI_GOOD_THRESHOLD. + + IRQL = DISPATCH_LEVEL + + Output: + ========================================================================== + */ +VOID MlmeCheckForRoaming( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32) +{ + USHORT i; + BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; + BSS_ENTRY *pBss; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n")); + // put all roaming candidates into RoamTab, and sort in RSSI order + BssTableInit(pRoamTab); + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + + if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32) + continue; // AP disappear + if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) + continue; // RSSI too weak. forget it. + if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) + continue; // skip current AP + if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA)) + continue; // only AP with stronger RSSI is eligible for roaming + + // AP passing all above rules is put into roaming candidate table + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); + pRoamTab->BssNr += 1; + } + + if (pRoamTab->BssNr > 0) + { + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + pAd->RalinkCounters.PoorCQIRoamingCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); + RT28XX_MLME_HANDLER(pAd); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr)); +} + +/* + ========================================================================== + Description: + This routine checks if there're other APs out there capable for + roaming. Caller should call this routine only when link up in INFRA mode + and channel quality is below CQI_GOOD_THRESHOLD. + + IRQL = DISPATCH_LEVEL + + Output: + ========================================================================== + */ +VOID MlmeCheckForFastRoaming( + IN PRTMP_ADAPTER pAd, + IN ULONG Now) +{ + USHORT i; + BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; + BSS_ENTRY *pBss; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n")); + // put all roaming candidates into RoamTab, and sort in RSSI order + BssTableInit(pRoamTab); + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + pBss = &pAd->ScanTab.BssEntry[i]; + + if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel)) + continue; // RSSI too weak. forget it. + if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) + continue; // skip current AP + if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) + continue; // skip different SSID + if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA)) + continue; // skip AP without better RSSI + + DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi)); + // AP passing all above rules is put into roaming candidate table + NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); + pRoamTab->BssNr += 1; + } + + if (pRoamTab->BssNr > 0) + { + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) + { + pAd->RalinkCounters.PoorCQIRoamingCount ++; + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); + RT28XX_MLME_HANDLER(pAd); + } + } + // Maybe site survey required + else + { + if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now) + { + // check CntlMachine.CurrState to avoid collision with NDIS SetOID request + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n")); + pAd->StaCfg.ScanCnt = 2; + pAd->StaCfg.LastScanTime = Now; + MlmeAutoScan(pAd); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr)); +} + +/* + ========================================================================== + Description: + This routine calculates TxPER, RxPER of the past N-sec period. And + according to the calculation result, ChannelQuality is calculated here + to decide if current AP is still doing the job. + + If ChannelQuality is not good, a ROAMing attempt may be tried later. + Output: + StaCfg.ChannelQuality - 0..100 + + IRQL = DISPATCH_LEVEL + + NOTE: This routine decide channle quality based on RX CRC error ratio. + Caller should make sure a function call to NICUpdateRawCounters(pAd) + is performed right before this routine, so that this routine can decide + channel quality based on the most up-to-date information + ========================================================================== + */ +VOID MlmeCalculateChannelQuality( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32) +{ + ULONG TxOkCnt, TxCnt, TxPER, TxPRR; + ULONG RxCnt, RxPER; + UCHAR NorRssi; + CHAR MaxRssi; + ULONG BeaconLostTime = BEACON_LOST_TIME; + +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + // longer beacon lost time when carrier detection enabled + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2; + } +#endif // CARRIER_DETECTION_SUPPORT // + + MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2); + + // + // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics + // + TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount; + TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount; + if (TxCnt < 5) + { + TxPER = 0; + TxPRR = 0; + } + else + { + TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt; + TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt; + } + + // + // calculate RX PER - don't take RxPER into consideration if too few sample + // + RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt; + if (RxCnt < 5) + RxPER = 0; + else + RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt; + + // + // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER + // + if (INFRA_ON(pAd) && + (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic + (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt)); + pAd->Mlme.ChannelQuality = 0; + } + else + { + // Normalize Rssi + if (MaxRssi > -40) + NorRssi = 100; + else if (MaxRssi < -90) + NorRssi = 0; + else + NorRssi = (MaxRssi + 90) * 2; + + // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) + pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi + + TX_WEIGHTING * (100 - TxPRR) + + RX_WEIGHTING* (100 - RxPER)) / 100; + if (pAd->Mlme.ChannelQuality >= 100) + pAd->Mlme.ChannelQuality = 100; + } + +} + +VOID MlmeSetTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH pTxRate) +{ + UCHAR MaxMode = MODE_OFDM; + +#ifdef DOT11_N_SUPPORT + MaxMode = MODE_HTGREENFIELD; + + if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2)) + pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE; + else +#endif // DOT11_N_SUPPORT // + pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; + + if (pTxRate->CurrMCS < MCS_AUTO) + pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS; + + if (pAd->StaCfg.HTPhyMode.field.MCS > 7) + pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE; + + if (ADHOC_ON(pAd)) + { + // If peer adhoc is b-only mode, we can't send 11g rate. + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + pEntry->HTPhyMode.field.STBC = STBC_NONE; + + // + // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary + // + pEntry->HTPhyMode.field.MODE = pTxRate->Mode; + pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + + // Patch speed error in status page + pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE; + } + else + { + if (pTxRate->Mode <= MaxMode) + pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode; + +#ifdef DOT11_N_SUPPORT + if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI)) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400; + else +#endif // DOT11_N_SUPPORT // + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + +#ifdef DOT11_N_SUPPORT + // Reexam each bandwidth's SGI support. + if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) + { + if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE))) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE))) + pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800; + } + + // Turn RTS/CTS rate to 6Mbps. + if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) + { + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + if (pAd->MacTab.fAnyBASession) + { + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + else + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + } + else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) + { + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + if (pAd->MacTab.fAnyBASession) + { + AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + else + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } + } + else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) + { + AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + + } + else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) + { + AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent); + } +#endif // DOT11_N_SUPPORT // + + pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC; + pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; +#ifdef DOT11_N_SUPPORT + if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) && + pAd->WIFItestbed.bGreenField) + pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD; +#endif // DOT11_N_SUPPORT // + } + + pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); +} + +/* + ========================================================================== + Description: + This routine calculates the acumulated TxPER of eaxh TxRate. And + according to the calculation result, change CommonCfg.TxRate which + is the stable TX Rate we expect the Radio situation could sustained. + + CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} + Output: + CommonCfg.TxRate - + + IRQL = DISPATCH_LEVEL + + NOTE: + call this routine every second + ========================================================================== + */ +VOID MlmeDynamicTxRateSwitching( + IN PRTMP_ADAPTER pAd) +{ + UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx; + ULONG i, AccuTxTotalCnt = 0, TxTotalCnt; + ULONG TxErrorRatio = 0; + BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE; + PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; + CHAR Rssi, RssiOffset = 0; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; + MAC_TABLE_ENTRY *pEntry; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif // RALINK_ATE // + + // + // walk through MAC table, see if need to change AP's TX rate toward each entry + // + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + + // check if this entry need to switch rate automatically + if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) + continue; + + if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) + { + Rssi = RTMPMaxRssi(pAd, + pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2); + + // Update statistic counter + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); + pAd->bUpdateBcnCntDone = TRUE; + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; + + // if no traffic in the past 1-sec period, don't change TX rate, + // but clear all bad history. because the bad history may affect the next + // Chariot throughput test + AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + if (INFRA_ON(pAd) && (i == 1)) + Rssi = RTMPMaxRssi(pAd, + pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2); + else + Rssi = RTMPMaxRssi(pAd, + pEntry->RssiSample.AvgRssi0, + pEntry->RssiSample.AvgRssi1, + pEntry->RssiSample.AvgRssi2); + + TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + + pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; + } + + CurrRateIdx = pEntry->CurrTxRateIndex; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + + if (CurrRateIdx >= TableSize) + { + CurrRateIdx = TableSize - 1; + } + + // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. + // So need to sync here. + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; + if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS) + //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) + ) + { + + // Need to sync Real Tx rate and our record. + // Then return for next DRS. + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5]; + pEntry->CurrTxRateIndex = InitTxRateIdx; + MlmeSetTxRate(pAd, pEntry, pCurrTxRate); + + // reset all OneSecTx counters + RESET_ONE_SEC_TX_CNT(pEntry); + continue; + } + + // decide the next upgrade rate and downgrade rate, if any + if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) + { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx -1; + } + else if (CurrRateIdx == 0) + { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx; + } + else if (CurrRateIdx == (TableSize - 1)) + { + UpRateIdx = CurrRateIdx; + DownRateIdx = CurrRateIdx - 1; + } + + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; + +#ifdef DOT11_N_SUPPORT + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif // DOT11_N_SUPPORT // + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; + + // + // Keep the last time TxRateChangeAction status. + // + pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction; + + + + // + // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI + // (criteria copied from RT2500 for Netopia case) + // + if (TxTotalCnt <= 15) + { + CHAR idx = 0; + UCHAR TxRateIdx; + //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; + UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0; + UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0; + UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3 + + // check the existence and index of each needed MCS + while (idx < pTable[0]) + { + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5]; + + if (pCurrTxRate->CurrMCS == MCS_0) + { + MCS0 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_1) + { + MCS1 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_2) + { + MCS2 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_3) + { + MCS3 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_4) + { + MCS4 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_5) + { + MCS5 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_6) + { + MCS6 = idx; + } + //else if (pCurrTxRate->CurrMCS == MCS_7) + else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput + { + MCS7 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_12) + { + MCS12 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_13) + { + MCS13 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_14) + { + MCS14 = idx; + } + else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) + { + MCS15 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3 + { + MCS20 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_21) + { + MCS21 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_22) + { + MCS22 = idx; + } + else if (pCurrTxRate->CurrMCS == MCS_23) + { + MCS23 = idx; + } + idx ++; + } + + if (pAd->LatchRfRegs.Channel <= 14) + { + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RssiOffset = 2; + } + else + { + RssiOffset = 5; + } + } + else + { + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RssiOffset = 5; + } + else + { + RssiOffset = 8; + } + } +#ifdef DOT11_N_SUPPORT + /*if (MCS15)*/ + if ((pTable == RateSwitchTable11BGN3S) || + (pTable == RateSwitchTable11N3S) || + (pTable == RateSwitchTable)) + {// N mode with 3 stream // 3*3 + if (MCS23 && (Rssi >= -70)) + TxRateIdx = MCS15; + else if (MCS22 && (Rssi >= -72)) + TxRateIdx = MCS14; + else if (MCS21 && (Rssi >= -76)) + TxRateIdx = MCS13; + else if (MCS20 && (Rssi >= -78)) + TxRateIdx = MCS12; + else if (MCS4 && (Rssi >= -82)) + TxRateIdx = MCS4; + else if (MCS3 && (Rssi >= -84)) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi >= -86)) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi >= -88)) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } +// else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) + else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3 + {// N mode with 2 stream + if (MCS15 && (Rssi >= (-70+RssiOffset))) + TxRateIdx = MCS15; + else if (MCS14 && (Rssi >= (-72+RssiOffset))) + TxRateIdx = MCS14; + else if (MCS13 && (Rssi >= (-76+RssiOffset))) + TxRateIdx = MCS13; + else if (MCS12 && (Rssi >= (-78+RssiOffset))) + TxRateIdx = MCS12; + else if (MCS4 && (Rssi >= (-82+RssiOffset))) + TxRateIdx = MCS4; + else if (MCS3 && (Rssi >= (-84+RssiOffset))) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi >= (-86+RssiOffset))) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi >= (-88+RssiOffset))) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } + else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) + {// N mode with 1 stream + if (MCS7 && (Rssi > (-72+RssiOffset))) + TxRateIdx = MCS7; + else if (MCS6 && (Rssi > (-74+RssiOffset))) + TxRateIdx = MCS6; + else if (MCS5 && (Rssi > (-77+RssiOffset))) + TxRateIdx = MCS5; + else if (MCS4 && (Rssi > (-79+RssiOffset))) + TxRateIdx = MCS4; + else if (MCS3 && (Rssi > (-81+RssiOffset))) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi > (-83+RssiOffset))) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi > (-86+RssiOffset))) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } + else +#endif // DOT11_N_SUPPORT // + {// Legacy mode + if (MCS7 && (Rssi > -70)) + TxRateIdx = MCS7; + else if (MCS6 && (Rssi > -74)) + TxRateIdx = MCS6; + else if (MCS5 && (Rssi > -78)) + TxRateIdx = MCS5; + else if (MCS4 && (Rssi > -82)) + TxRateIdx = MCS4; + else if (MCS4 == 0) // for B-only mode + TxRateIdx = MCS3; + else if (MCS3 && (Rssi > -85)) + TxRateIdx = MCS3; + else if (MCS2 && (Rssi > -87)) + TxRateIdx = MCS2; + else if (MCS1 && (Rssi > -90)) + TxRateIdx = MCS1; + else + TxRateIdx = MCS0; + } + + // if (TxRateIdx != pAd->CommonCfg.TxRateIndex) + { + pEntry->CurrTxRateIndex = TxRateIdx; + pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5]; + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + + NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); + pEntry->fLastSecAccordingRSSI = TRUE; + // reset all OneSecTx counters + RESET_ONE_SEC_TX_CNT(pEntry); + + continue; + } + + if (pEntry->fLastSecAccordingRSSI == TRUE) + { + pEntry->fLastSecAccordingRSSI = FALSE; + pEntry->LastSecTxRateChangeAction = 0; + // reset all OneSecTx counters + RESET_ONE_SEC_TX_CNT(pEntry); + + continue; + } + + do + { + BOOLEAN bTrainUpDown = FALSE; + + pEntry->CurrTxRateStableTime ++; + + // downgrade TX quality if PER >= Rate-Down threshold + if (TxErrorRatio >= TrainDown) + { + bTrainUpDown = TRUE; + pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; + } + // upgrade TX quality if PER <= Rate-Up threshold + else if (TxErrorRatio <= TrainUp) + { + bTrainUpDown = TRUE; + bUpgradeQuality = TRUE; + if (pEntry->TxQuality[CurrRateIdx]) + pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate + + if (pEntry->TxRateUpPenalty) + pEntry->TxRateUpPenalty --; + else if (pEntry->TxQuality[UpRateIdx]) + pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality + } + + pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + if (bTrainUpDown) + { + // perform DRS - consider TxRate Down first, then rate up. + if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND)) + { + pEntry->CurrTxRateIndex = DownRateIdx; + } + else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0)) + { + pEntry->CurrTxRateIndex = UpRateIdx; + } + } + } while (FALSE); + + // if rate-up happen, clear all bad history of all TX rates + if (pEntry->CurrTxRateIndex > CurrRateIdx) + { + pEntry->CurrTxRateStableTime = 0; + pEntry->TxRateUpPenalty = 0; + pEntry->LastSecTxRateChangeAction = 1; // rate UP + NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); + + // + // For TxRate fast train up + // + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + bTxRateChanged = TRUE; + } + // if rate-down happen, only clear DownRate's bad history + else if (pEntry->CurrTxRateIndex < CurrRateIdx) + { + pEntry->CurrTxRateStableTime = 0; + pEntry->TxRateUpPenalty = 0; // no penalty + pEntry->LastSecTxRateChangeAction = 2; // rate DOWN + pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0; + pEntry->PER[pEntry->CurrTxRateIndex] = 0; + + // + // For TxRate fast train down + // + if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) + { + RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100); + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE; + } + bTxRateChanged = TRUE; + } + else + { + pEntry->LastSecTxRateChangeAction = 0; // rate no change + bTxRateChanged = FALSE; + } + + pEntry->LastTxOkCount = TxSuccess; + + // reset all OneSecTx counters + RESET_ONE_SEC_TX_CNT(pEntry); + + pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5]; + if (bTxRateChanged && pNextTxRate) + { + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + } +} + +/* + ======================================================================== + Routine Description: + Station side, Auto TxRate faster train up timer call back function. + + Arguments: + SystemSpecific1 - Not used. + FunctionContext - Pointer to our Adapter context. + SystemSpecific2 - Not used. + SystemSpecific3 - Not used. + + Return Value: + None + + ======================================================================== +*/ +VOID StaQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0; + ULONG TxTotalCnt; + ULONG TxErrorRatio = 0; + BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE; + PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; + PUCHAR pTable; + UCHAR TableSize = 0; + UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT0_STRUC TxStaCnt0; + CHAR Rssi, ratio; + ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0; + MAC_TABLE_ENTRY *pEntry; + ULONG i; + + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; + + // + // walk through MAC table, see if need to change AP's TX rate toward each entry + // + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + + // check if this entry need to switch rate automatically + if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE) + continue; + + if (INFRA_ON(pAd) && (i == 1)) + Rssi = RTMPMaxRssi(pAd, + pAd->StaCfg.RssiSample.AvgRssi0, + pAd->StaCfg.RssiSample.AvgRssi1, + pAd->StaCfg.RssiSample.AvgRssi2); + else + Rssi = RTMPMaxRssi(pAd, + pEntry->RssiSample.AvgRssi0, + pEntry->RssiSample.AvgRssi1, + pEntry->RssiSample.AvgRssi2); + + CurrRateIdx = pAd->CommonCfg.TxRateIndex; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx); + + // decide the next upgrade rate and downgrade rate, if any + if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) + { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx -1; + } + else if (CurrRateIdx == 0) + { + UpRateIdx = CurrRateIdx + 1; + DownRateIdx = CurrRateIdx; + } + else if (CurrRateIdx == (TableSize - 1)) + { + UpRateIdx = CurrRateIdx; + DownRateIdx = CurrRateIdx - 1; + } + + pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; + +#ifdef DOT11_N_SUPPORT + if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) + { + TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); + TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); + } + else +#endif // DOT11_N_SUPPORT // + { + TrainUp = pCurrTxRate->TrainUp; + TrainDown = pCurrTxRate->TrainDown; + } + + if (pAd->MacTab.Size == 1) + { + // Update statistic counter + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); + + TxRetransmit = StaTx1.field.TxRetransmit; + TxSuccess = StaTx1.field.TxSuccess; + TxFailCount = TxStaCnt0.field.TxFailCount; + TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount; + + pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt; + } + else + { + TxTotalCnt = pEntry->OneSecTxNoRetryOkCount + + pEntry->OneSecTxRetryOkCount + + pEntry->OneSecTxFailCount; + + if (TxTotalCnt) + TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt; + } + + + // + // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI + // (criteria copied from RT2500 for Netopia case) + // + if (TxTotalCnt <= 12) + { + NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); + + if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) + { + pAd->CommonCfg.TxRateIndex = DownRateIdx; + pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; + } + else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) + { + pAd->CommonCfg.TxRateIndex = UpRateIdx; + } + + DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n")); + return; + } + + do + { + ULONG OneSecTxNoRetryOKRationCount; + + if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0) + ratio = 5; + else + ratio = 4; + + // downgrade TX quality if PER >= Rate-Down threshold + if (TxErrorRatio >= TrainDown) + { + pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; + } + + pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio; + + OneSecTxNoRetryOKRationCount = (TxSuccess * ratio); + + // perform DRS - consider TxRate Down first, then rate up. + if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx)) + { + if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) + { + pAd->CommonCfg.TxRateIndex = DownRateIdx; + pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND; + + } + + } + else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx)) + { + if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown)) + { + + } + else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount) + { + pAd->CommonCfg.TxRateIndex = UpRateIdx; + } + } + }while (FALSE); + + // if rate-up happen, clear all bad history of all TX rates + if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) + { + pAd->DrsCounters.TxRateUpPenalty = 0; + NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH); + NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH); + bTxRateChanged = TRUE; + } + // if rate-down happen, only clear DownRate's bad history + else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) + { + DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex)); + + pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty + pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0; + pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0; + bTxRateChanged = TRUE; + } + else + { + bTxRateChanged = FALSE; + } + + pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5]; + if (bTxRateChanged && pNextTxRate) + { + MlmeSetTxRate(pAd, pEntry, pNextTxRate); + } + } +} + +/* + ========================================================================== + Description: + This routine is executed periodically inside MlmePeriodicExec() after + association with an AP. + It checks if StaCfg.Psm is consistent with user policy (recorded in + StaCfg.WindowsPowerMode). If not, enforce user policy. However, + there're some conditions to consider: + 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all + the time when Mibss==TRUE + 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE + if outgoing traffic available in TxRing or MgmtRing. + Output: + 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeCheckPsmChange( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32) +{ + ULONG PowerMode; + + // condition - + // 1. Psm maybe ON only happen in INFRASTRUCTURE mode + // 2. user wants either MAX_PSP or FAST_PSP + // 3. but current psm is not in PWR_SAVE + // 4. CNTL state machine is not doing SCANning + // 5. no TX SUCCESS event for the past 1-sec period +#ifdef NDIS51_MINIPORT + if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery) + PowerMode = pAd->StaCfg.WindowsBatteryPowerMode; + else +#endif + PowerMode = pAd->StaCfg.WindowsPowerMode; + + if (INFRA_ON(pAd) && + (PowerMode != Ndis802_11PowerModeCAM) && + (pAd->StaCfg.Psm == PWR_ACTIVE) && +// (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&& + (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && + (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/) + { + // add by johnli, use Rx OK data count per second to calculate throughput + // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria + // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps + if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) && +/* Iverson mark + (pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) && +*/ + (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) || + ((pAd->StaCfg.HTPhyMode.field.MCS > 3) && +/* Iverson mark + (pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) && +*/ + (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400))) + { + // Get this time + NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime); + pAd->RalinkCounters.RxCountSinceLastNULL = 0; + MlmeSetPsmBit(pAd, PWR_SAVE); + if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) + { + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE); + } + else + { + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + } + } + } +} + +// IRQL = PASSIVE_LEVEL +// IRQL = DISPATCH_LEVEL +VOID MlmeSetPsmBit( + IN PRTMP_ADAPTER pAd, + IN USHORT psm) +{ + AUTO_RSP_CFG_STRUC csr4; + + pAd->StaCfg.Psm = psm; + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); + csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0; + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); +} +#endif // CONFIG_STA_SUPPORT // + + +// IRQL = DISPATCH_LEVEL +VOID MlmeSetTxPreamble( + IN PRTMP_ADAPTER pAd, + IN USHORT TxPreamble) +{ + AUTO_RSP_CFG_STRUC csr4; + + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + //TxPreamble = Rt802_11PreambleLong; + + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); + if (TxPreamble == Rt802_11PreambleLong) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + csr4.field.AutoResponderPreamble = 0; + } + else + { + // NOTE: 1Mbps should always use long preamble + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n")); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + csr4.field.AutoResponderPreamble = 1; + } + + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); +} + +/* + ========================================================================== + Description: + Update basic rate bitmap + ========================================================================== + */ + +VOID UpdateBasicRateBitmap( + IN PRTMP_ADAPTER pAdapter) +{ + INT i, j; + /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ + UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; + UCHAR *sup_p = pAdapter->CommonCfg.SupRate; + UCHAR *ext_p = pAdapter->CommonCfg.ExtRate; + ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap; + + + /* if A mode, always use fix BasicRateBitMap */ + //if (pAdapter->CommonCfg.Channel == PHY_11A) + if (pAdapter->CommonCfg.Channel > 14) + pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */ + /* End of if */ + + if (pAdapter->CommonCfg.BasicRateBitmap > 4095) + { + /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ + return; + } /* End of if */ + + for(i=0; iCommonCfg.DesireRate[i] & 0x7f) + { + case 2: Rate = RATE_1; num++; break; + case 4: Rate = RATE_2; num++; break; + case 11: Rate = RATE_5_5; num++; break; + case 22: Rate = RATE_11; num++; break; + case 12: Rate = RATE_6; num++; break; + case 18: Rate = RATE_9; num++; break; + case 24: Rate = RATE_12; num++; break; + case 36: Rate = RATE_18; num++; break; + case 48: Rate = RATE_24; num++; break; + case 72: Rate = RATE_36; num++; break; + case 96: Rate = RATE_48; num++; break; + case 108: Rate = RATE_54; num++; break; + //default: Rate = RATE_1; break; + } + if (MaxDesire < Rate) MaxDesire = Rate; + } + +//=========================================================================== +//=========================================================================== + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pHtPhy = &pAd->StaCfg.HTPhyMode; + pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; + pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; + + auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; + HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS; + + if ((pAd->StaCfg.BssType == BSS_ADHOC) && + (pAd->CommonCfg.PhyMode == PHY_11B) && + (MaxDesire > RATE_11)) + { + MaxDesire = RATE_11; + } + } +#endif // CONFIG_STA_SUPPORT // + + pAd->CommonCfg.MaxDesiredRate = MaxDesire; + pMinHtPhy->word = 0; + pMaxHtPhy->word = 0; + pHtPhy->word = 0; + + // Auto rate switching is enabled only if more than one DESIRED RATES are + // specified; otherwise disabled + if (num <= 1) + { + //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); + //pAd->CommonCfg.bAutoTxRateSwitch = FALSE; + *auto_rate_cur_p = FALSE; + } + else + { + //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); + //pAd->CommonCfg.bAutoTxRateSwitch = TRUE; + *auto_rate_cur_p = TRUE; + } + +#if 1 + if (HtMcs != MCS_AUTO) + { + //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); + //pAd->CommonCfg.bAutoTxRateSwitch = FALSE; + *auto_rate_cur_p = FALSE; + } + else + { + //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); + //pAd->CommonCfg.bAutoTxRateSwitch = TRUE; + *auto_rate_cur_p = TRUE; + } +#endif + +#ifdef CONFIG_STA_SUPPORT + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) + { + pSupRate = &pAd->StaActive.SupRate[0]; + pExtRate = &pAd->StaActive.ExtRate[0]; + SupRateLen = pAd->StaActive.SupRateLen; + ExtRateLen = pAd->StaActive.ExtRateLen; + } + else +#endif // CONFIG_STA_SUPPORT // + { + pSupRate = &pAd->CommonCfg.SupRate[0]; + pExtRate = &pAd->CommonCfg.ExtRate[0]; + SupRateLen = pAd->CommonCfg.SupRateLen; + ExtRateLen = pAd->CommonCfg.ExtRateLen; + } + + // find max supported rate + for (i=0; i Rate) MinSupport = Rate; + } + + for (i=0; i Rate) MinSupport = Rate; + } + + RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap); + + // calculate the exptected ACK rate for each TX rate. This info is used to caculate + // the DURATION field of outgoing uniicast DATA/MGMT frame + for (i=0; iCommonCfg.ExpectedACKRate[i] = CurrBasicRate; + } + + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire])); + // max tx rate = min {max desire rate, max supported rate} + if (MaxSupport < MaxDesire) + pAd->CommonCfg.MaxTxRate = MaxSupport; + else + pAd->CommonCfg.MaxTxRate = MaxDesire; + + pAd->CommonCfg.MinTxRate = MinSupport; + // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success + // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending + // on average RSSI + // 1. RSSI >= -70db, start at 54 Mbps (short distance) + // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) + // 3. -75 > RSSI, start at 11 Mbps (long distance) + //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* && + // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/) + if (*auto_rate_cur_p) + { + short dbm = 0; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta; +#endif // CONFIG_STA_SUPPORT // + if (bLinkUp == TRUE) + pAd->CommonCfg.TxRate = RATE_24; + else + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + if (dbm < -75) + pAd->CommonCfg.TxRate = RATE_11; + else if (dbm < -70) + pAd->CommonCfg.TxRate = RATE_24; + + // should never exceed MaxTxRate (consider 11B-only mode) + if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate) + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + pAd->CommonCfg.TxRateIndex = 0; + } + else + { + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate; + pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK; + + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE; + } + + if (pAd->CommonCfg.TxRate <= RATE_11) + { + pMaxHtPhy->field.MODE = MODE_CCK; + pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate; + pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate; + } + else + { + pMaxHtPhy->field.MODE = MODE_OFDM; + pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate]; + if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54)) + {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];} + else + {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;} + } + + pHtPhy->word = (pMaxHtPhy->word); + if (bLinkUp && (pAd->OpMode == OPMODE_STA)) + { + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word; + } + else + { + switch (pAd->CommonCfg.PhyMode) + { + case PHY_11BG_MIXED: + case PHY_11B: +#ifdef DOT11_N_SUPPORT + case PHY_11BGN_MIXED: +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + +//#ifdef WIFI_TEST + pAd->CommonCfg.RtsRate = RATE_11; +//#else +// pAd->CommonCfg.RtsRate = RATE_1; +//#endif + break; + case PHY_11G: + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11AGN_MIXED: + case PHY_11GN_MIXED: + case PHY_11N_2_4G: + case PHY_11AN_MIXED: + case PHY_11N_5G: +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + break; + case PHY_11ABG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: +#endif // DOT11_N_SUPPORT // + if (pAd->CommonCfg.Channel <= 14) + { + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.RtsRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + } + else + { + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + break; + default: // error + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->CommonCfg.RtsRate = RATE_1; + break; + } + // + // Keep Basic Mlme Rate. + // + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word; + if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24]; + else + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1; + pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate; + } + + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", + RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate], + /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p)); + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", + RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", + pAd->CommonCfg.MlmeTransmit.word, pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word )); +} + +#ifdef DOT11_N_SUPPORT +/* + ========================================================================== + Description: + This function update HT Rate setting. + Input Wcid value is valid for 2 case : + 1. it's used for Station in infra mode that copy AP rate to Mactable. + 2. OR Station in adhoc mode to copy peer's HT rate to Mactable. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeUpdateHtTxRates( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx) +{ + UCHAR StbcMcs; //j, StbcMcs, bitmask; + CHAR i; // 3*3 + RT_HT_CAPABILITY *pRtHtCap = NULL; + RT_HT_PHY_INFO *pActiveHtPhy = NULL; + ULONG BasicMCS; + UCHAR j, bitmask; + PRT_HT_PHY_INFO pDesireHtPhy = NULL; + PHTTRANSMIT_SETTING pHtPhy = NULL; + PHTTRANSMIT_SETTING pMaxHtPhy = NULL; + PHTTRANSMIT_SETTING pMinHtPhy = NULL; + BOOLEAN *auto_rate_cur_p; + + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n")); + + auto_rate_cur_p = NULL; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; + pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo; + pHtPhy = &pAd->StaCfg.HTPhyMode; + pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode; + pMinHtPhy = &pAd->StaCfg.MinHTPhyMode; + + auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch; + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) + { + if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + return; + + pRtHtCap = &pAd->StaActive.SupportedHtPhy; + pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo; + StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs; + BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16); + if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) + pMaxHtPhy->field.STBC = STBC_USE; + else + pMaxHtPhy->field.STBC = STBC_NONE; + } + else +#endif // CONFIG_STA_SUPPORT // + { + if (pDesireHtPhy->bHtEnable == FALSE) + return; + + pRtHtCap = &pAd->CommonCfg.DesiredHtPhy; + StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs; + BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16); + if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2)) + pMaxHtPhy->field.STBC = STBC_USE; + else + pMaxHtPhy->field.STBC = STBC_NONE; + } + + // Decide MAX ht rate. + if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + pMaxHtPhy->field.MODE = MODE_HTGREENFIELD; + else + pMaxHtPhy->field.MODE = MODE_HTMIX; + + if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth)) + pMaxHtPhy->field.BW = BW_40; + else + pMaxHtPhy->field.BW = BW_20; + + if (pMaxHtPhy->field.BW == BW_20) + pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20); + else + pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40); + + for (i=23; i>=0; i--) // 3*3 + { + j = i/8; + bitmask = (1<<(i-(j*8))); + + if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask)) + { + pMaxHtPhy->field.MCS = i; + break; + } + + if (i==0) + break; + } + + // Copy MIN ht rate. rt2860??? + pMinHtPhy->field.BW = BW_20; + pMinHtPhy->field.MCS = 0; + pMinHtPhy->field.STBC = 0; + pMinHtPhy->field.ShortGI = 0; + //If STA assigns fixed rate. update to fixed here. +#ifdef CONFIG_STA_SUPPORT + if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) + { + if (pDesireHtPhy->MCSSet[4] != 0) + { + pMaxHtPhy->field.MCS = 32; + pMinHtPhy->field.MCS = 32; + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS)); + } + + for (i=23; (CHAR)i >= 0; i--) // 3*3 + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask)) + { + pMaxHtPhy->field.MCS = i; + pMinHtPhy->field.MCS = i; + break; + } + if (i==0) + break; + } + } +#endif // CONFIG_STA_SUPPORT // + + + // Decide ht rate + pHtPhy->field.STBC = pMaxHtPhy->field.STBC; + pHtPhy->field.BW = pMaxHtPhy->field.BW; + pHtPhy->field.MODE = pMaxHtPhy->field.MODE; + pHtPhy->field.MCS = pMaxHtPhy->field.MCS; + pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI; + + // use default now. rt2860 + if (pDesireHtPhy->MCSSet[0] != 0xff) + *auto_rate_cur_p = FALSE; + else + *auto_rate_cur_p = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize )); + DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS, + pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE)); + DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n")); +} +#endif // DOT11_N_SUPPORT // + +// IRQL = DISPATCH_LEVEL +VOID MlmeRadioOff( + IN PRTMP_ADAPTER pAd) +{ + RT28XX_MLME_RADIO_OFF(pAd); +} + +// IRQL = DISPATCH_LEVEL +VOID MlmeRadioOn( + IN PRTMP_ADAPTER pAd) +{ + RT28XX_MLME_RADIO_ON(pAd); +} + +// =========================================================================================== +// bss_table.c +// =========================================================================================== + + +/*! \brief initialize BSS table + * \param p_tab pointer to the table + * \return none + * \pre + * \post + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +VOID BssTableInit( + IN BSS_TABLE *Tab) +{ + int i; + + Tab->BssNr = 0; + Tab->BssOverlapNr = 0; + for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) + { + NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY)); + Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value + } +} + +#ifdef DOT11_N_SUPPORT +VOID BATableInit( + IN PRTMP_ADAPTER pAd, + IN BA_TABLE *Tab) +{ + int i; + + Tab->numAsOriginator = 0; + Tab->numAsRecipient = 0; + NdisAllocateSpinLock(&pAd->BATabLock); + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE; + NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock)); + } + for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) + { + Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE; + } +} +#endif // DOT11_N_SUPPORT // + +/*! \brief search the BSS table by SSID + * \param p_tab pointer to the bss table + * \param ssid SSID string + * \return index of the table, BSS_NOT_FOUND if not in the table + * \pre + * \post + * \note search by sequential search + + IRQL = DISPATCH_LEVEL + + */ +ULONG BssTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + // + // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. + // We should distinguish this case. + // + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +ULONG BssSsidTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + // + // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. + // We should distinguish this case. + // + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) && + SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +ULONG BssTableSearchWithSSID( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) && + (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) || + (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) || + (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen)))) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +// IRQL = DISPATCH_LEVEL +VOID BssTableDeleteEntry( + IN OUT BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN UCHAR Channel) +{ + UCHAR i, j; + + for (i = 0; i < Tab->BssNr; i++) + { + if ((Tab->BssEntry[i].Channel == Channel) && + (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) + { + for (j = i; j < Tab->BssNr - 1; j++) + { + NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY)); + } + NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY)); + Tab->BssNr -= 1; + return; + } + } +} + +#ifdef DOT11_N_SUPPORT +/* + ======================================================================== + Routine Description: + Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed. + + Arguments: + // IRQL = DISPATCH_LEVEL + ======================================================================== +*/ +VOID BATableDeleteORIEntry( + IN OUT PRTMP_ADAPTER pAd, + IN BA_ORI_ENTRY *pBAORIEntry) +{ + + if (pBAORIEntry->ORI_BA_Status != Originator_NONE) + { + NdisAcquireSpinLock(&pAd->BATabLock); + if (pBAORIEntry->ORI_BA_Status == Originator_Done) + { + pAd->BATable.numAsOriginator -= 1; + DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); + // Erase Bitmap flag. + } + pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here + pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here + pBAORIEntry->ORI_BA_Status = Originator_NONE; + pBAORIEntry->Token = 1; + // Not clear Sequence here. + NdisReleaseSpinLock(&pAd->BATabLock); + } +} +#endif // DOT11_N_SUPPORT // + +/*! \brief + * \param + * \return + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +VOID BssEntrySet( + IN PRTMP_ADAPTER pAd, + OUT BSS_ENTRY *pBss, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN PCF_PARM pCfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR Channel, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE) +{ + COPY_MAC_ADDR(pBss->Bssid, pBssid); + // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID + pBss->Hidden = 1; + if (SsidLen > 0) + { + // For hidden SSID AP, it might send beacon with SSID len equal to 0 + // Or send beacon /probe response with SSID len matching real SSID length, + // but SSID is all zero. such as "00-00-00-00" with length 4. + // We have to prevent this case overwrite correct table + if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) + { + NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pBss->Ssid, Ssid, SsidLen); + pBss->SsidLen = SsidLen; + pBss->Hidden = 0; + } + } + else + pBss->SsidLen = 0; + pBss->BssType = BssType; + pBss->BeaconPeriod = BeaconPeriod; + if (BssType == BSS_INFRA) + { + if (pCfParm->bValid) + { + pBss->CfpCount = pCfParm->CfpCount; + pBss->CfpPeriod = pCfParm->CfpPeriod; + pBss->CfpMaxDuration = pCfParm->CfpMaxDuration; + pBss->CfpDurRemaining = pCfParm->CfpDurRemaining; + } + } + else + { + pBss->AtimWin = AtimWin; + } + + pBss->CapabilityInfo = CapabilityInfo; + // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES + // Combine with AuthMode, they will decide the connection methods. + pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo); + ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) + NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen); + else + NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES); + pBss->SupRateLen = SupRateLen; + ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen); + NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); + NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); + pBss->NewExtChanOffset = NewExtChanOffset; + pBss->ExtRateLen = ExtRateLen; + pBss->Channel = Channel; + pBss->CentralChannel = Channel; + pBss->Rssi = Rssi; + // Update CkipFlag. if not exists, the value is 0x0 + pBss->CkipFlag = CkipFlag; + + // New for microsoft Fixed IEs + NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8); + pBss->FixIEs.BeaconInterval = BeaconPeriod; + pBss->FixIEs.Capabilities = CapabilityInfo; + + // New for microsoft Variable IEs + if (LengthVIE != 0) + { + pBss->VarIELen = LengthVIE; + NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen); + } + else + { + pBss->VarIELen = 0; + } + + pBss->AddHtInfoLen = 0; + pBss->HtCapabilityLen = 0; +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen> 0) + { + pBss->HtCapabilityLen = HtCapabilityLen; + NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen); + if (AddHtInfoLen > 0) + { + pBss->AddHtInfoLen = AddHtInfoLen; + NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen); + + if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + pBss->CentralChannel = pAddHtInfo->ControlChan - 2; + } + else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40)) + { + pBss->CentralChannel = pAddHtInfo->ControlChan + 2; + } + } + } +#endif // DOT11_N_SUPPORT // + + BssCipherParse(pBss); + + // new for QOS + if (pEdcaParm) + NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + else + pBss->EdcaParm.bValid = FALSE; + if (pQosCapability) + NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM)); + else + pBss->QosCapability.bValid = FALSE; + if (pQbssLoad) + NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM)); + else + pBss->QbssLoad.bValid = FALSE; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + PEID_STRUCT pEid; + USHORT Length = 0; + + + NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN); + NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN); +#ifdef EXT_BUILD_CHANNEL_LIST + NdisZeroMemory(&pBss->CountryString[0], 3); + pBss->bHasCountryIE = FALSE; +#endif // EXT_BUILD_CHANNEL_LIST // + pEid = (PEID_STRUCT) pVIE; + while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE) + { + switch(pEid->Eid) + { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + { + if ((pEid->Len + 2) > MAX_CUSTOM_LEN) + { + pBss->WpaIE.IELen = 0; + break; + } + pBss->WpaIE.IELen = pEid->Len + 2; + NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen); + } + break; + case IE_RSN: + if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + { + if ((pEid->Len + 2) > MAX_CUSTOM_LEN) + { + pBss->RsnIE.IELen = 0; + break; + } + pBss->RsnIE.IELen = pEid->Len + 2; + NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen); + } + break; +#ifdef EXT_BUILD_CHANNEL_LIST + case IE_COUNTRY: + NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3); + pBss->bHasCountryIE = TRUE; + break; +#endif // EXT_BUILD_CHANNEL_LIST // + } + Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len] + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + } +#endif // CONFIG_STA_SUPPORT // +} + +/*! + * \brief insert an entry into the bss table + * \param p_tab The BSS table + * \param Bssid BSSID + * \param ssid SSID + * \param ssid_len Length of SSID + * \param bss_type + * \param beacon_period + * \param timestamp + * \param p_cf + * \param atim_win + * \param cap + * \param rates + * \param rates_len + * \param channel_idx + * \return none + * \pre + * \post + * \note If SSID is identical, the old entry will be replaced by the new one + + IRQL = DISPATCH_LEVEL + + */ +ULONG BssTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN CF_PARM *CfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR ChannelNo, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE) +{ + ULONG Idx; + + Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo); + if (Idx == BSS_NOT_FOUND) + { + if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) + { + // + // It may happen when BSS Table was full. + // The desired AP will not be added into BSS Table + // In this case, if we found the desired AP then overwrite BSS Table. + // + if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) || + SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen)) + { + Idx = Tab->BssOverlapNr; + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, + NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); + Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE; + } + return Idx; + } + else + { + return BSS_NOT_FOUND; + } + } + Idx = Tab->BssNr; + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, + NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); + Tab->BssNr++; + } + else + { + /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */ + if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) || + (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen))) + { + BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin, + CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen, + NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE); + } + } + + return Idx; +} + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID TriEventInit( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i; + + for (i = 0;i < MAX_TRIGGER_EVENT;i++) + pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE; + + pAd->CommonCfg.TriggerEventTab.EventANo = 0; + pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0; +} + +ULONG TriEventTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT TRIGGER_EVENT_TAB *Tab, + IN PUCHAR pBssid, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN UCHAR RegClass, + IN UCHAR ChannelNo) +{ + // Event A + if (HtCapabilityLen == 0) + { + if (Tab->EventANo < MAX_TRIGGER_EVENT) + { + RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6); + Tab->EventA[Tab->EventANo].bValid = TRUE; + Tab->EventA[Tab->EventANo].Channel = ChannelNo; + Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay; + if (RegClass != 0) + { + // Beacon has Regulatory class IE. So use beacon's + Tab->EventA[Tab->EventANo].RegClass = RegClass; + } + else + { + // Use Station's Regulatory class instead. + if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE) + { + if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + { + Tab->EventA[Tab->EventANo].RegClass = 32; + } + else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + Tab->EventA[Tab->EventANo].RegClass = 33; + } + else + Tab->EventA[Tab->EventANo].RegClass = ??; + + } + + Tab->EventANo ++; + } + } + else if (pHtCapability->HtCapInfo.Intolerant40) + { + Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay; + } + +} + +/* + ======================================================================== + Routine Description: + Trigger Event table Maintainence called once every second. + + Arguments: + // IRQL = DISPATCH_LEVEL + ======================================================================== +*/ +VOID TriEventCounterMaintenance( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i; + BOOLEAN bNotify = FALSE; + for (i = 0;i < MAX_TRIGGER_EVENT;i++) + { + if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0)) + { + pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--; + if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0) + { + pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE; + pAd->CommonCfg.TriggerEventTab.EventANo --; + // Need to send 20/40 Coexistence Notify frame if has status change. + bNotify = TRUE; + } + } + } + if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0) + { + pAd->CommonCfg.TriggerEventTab.EventBCountDown--; + if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0) + bNotify = TRUE; + } + + if (bNotify == TRUE) + Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE); +} +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +// IRQL = DISPATCH_LEVEL +VOID BssTableSsidSort( + IN PRTMP_ADAPTER pAd, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen) +{ + INT i; + BssTableInit(OutTab); + + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i]; + BOOLEAN bIsHiddenApIncluded = FALSE; + + if (((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->MlmeAux.Channel > 14) && + RadarChannelCheck(pAd, pInBss->Channel)) +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) +#endif // CARRIER_DETECTION_SUPPORT // + ) + { + if (pInBss->Hidden) + bIsHiddenApIncluded = TRUE; + } + + if ((pInBss->BssType == pAd->StaCfg.BssType) && + (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + + +#ifdef EXT_BUILD_CHANNEL_LIST + // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict. + if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) && + (pInBss->bHasCountryIE == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n")); + continue; + } +#endif // EXT_BUILD_CHANNEL_LIST // + +#ifdef DOT11_N_SUPPORT + // 2.4G/5G N only mode + if ((pInBss->HtCapabilityLen == 0) && + ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; + } +#endif // DOT11_N_SUPPORT // + + // New for WPA2 + // Check the Authmode first + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode + if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) + // None matched + continue; + + // Check cipher suite, AP must have more secured cipher than station setting + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + // If it's not mixed mode, we should only let BSS pass with the same encryption + if (pInBss->WPA.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) + continue; + + // check group cipher + if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) + continue; + + // check pairwise cipher, skip if none matched + // If profile set to AES, let it pass without question. + // If profile set to TKIP, we must find one mateched + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + // If it's not mixed mode, we should only let BSS pass with the same encryption + if (pInBss->WPA2.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) + continue; + + // check group cipher + if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher) + continue; + + // check pairwise cipher, skip if none matched + // If profile set to AES, let it pass without question. + // If profile set to TKIP, we must find one mateched + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } + } + // Bss Type matched, SSID matched. + // We will check wepstatus for qualification Bss + else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) + { + DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus)); + // + // For the SESv2 case, we will not qualify WepStatus. + // + if (!pInBss->bSES) + continue; + } + + // Since the AP is using hidden SSID, and we are trying to connect to ANY + // It definitely will fail. So, skip it. + // CCX also require not even try to connect it!! + if (SsidLen == 0) + continue; + +#ifdef DOT11_N_SUPPORT + // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region + // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, + if ((pInBss->CentralChannel != pInBss->Channel) && + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) + { + if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + SetCommonHT(pAd); + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + } + else + { + if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20) + { + SetCommonHT(pAd); + } + } + } +#endif // DOT11_N_SUPPORT // + + // copy matching BSS from InTab to OutTab + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + OutTab->BssNr++; + } + else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + + +#ifdef DOT11_N_SUPPORT + // 2.4G/5G N only mode + if ((pInBss->HtCapabilityLen == 0) && + ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; + } +#endif // DOT11_N_SUPPORT // + + // New for WPA2 + // Check the Authmode first + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode + if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux)) + // None matched + continue; + + // Check cipher suite, AP must have more secured cipher than station setting + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + // If it's not mixed mode, we should only let BSS pass with the same encryption + if (pInBss->WPA.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher) + continue; + + // check group cipher + if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) + continue; + + // check pairwise cipher, skip if none matched + // If profile set to AES, let it pass without question. + // If profile set to TKIP, we must find one mateched + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + // If it's not mixed mode, we should only let BSS pass with the same encryption + if (pInBss->WPA2.bMixMode == FALSE) + if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher) + continue; + + // check group cipher + if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher) + continue; + + // check pairwise cipher, skip if none matched + // If profile set to AES, let it pass without question. + // If profile set to TKIP, we must find one mateched + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) && + (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } + } + // Bss Type matched, SSID matched. + // We will check wepstatus for qualification Bss + else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) + continue; + +#ifdef DOT11_N_SUPPORT + // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region + // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, + if ((pInBss->CentralChannel != pInBss->Channel) && + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) + { + if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + SetCommonHT(pAd); + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + } + } +#endif // DOT11_N_SUPPORT // + + // copy matching BSS from InTab to OutTab + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + OutTab->BssNr++; + } + + if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE) + break; + } + + BssTableSortByRssi(OutTab); +} + + +// IRQL = DISPATCH_LEVEL +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab) +{ + INT i, j; + BSS_ENTRY TmpBss; + + for (i = 0; i < OutTab->BssNr - 1; i++) + { + for (j = i+1; j < OutTab->BssNr; j++) + { + if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) + { + NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY)); + NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY)); + NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY)); + } + } + } +} +#endif // CONFIG_STA_SUPPORT // + + +VOID BssCipherParse( + IN OUT PBSS_ENTRY pBss) +{ + PEID_STRUCT pEid; + PUCHAR pTmp; + PRSN_IE_HEADER_STRUCT pRsnHeader; + PCIPHER_SUITE_STRUCT pCipher; + PAKM_SUITE_STRUCT pAKM; + USHORT Count; + INT Length; + NDIS_802_11_ENCRYPTION_STATUS TmpCipher; + + // + // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. + // + if (pBss->Privacy) + { + pBss->WepStatus = Ndis802_11WEPEnabled; + } + else + { + pBss->WepStatus = Ndis802_11WEPDisabled; + } + // Set default to disable & open authentication before parsing variable IE + pBss->AuthMode = Ndis802_11AuthModeOpen; + pBss->AuthModeAux = Ndis802_11AuthModeOpen; + + // Init WPA setting + pBss->WPA.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA.RsnCapability = 0; + pBss->WPA.bMixMode = FALSE; + + // Init WPA2 setting + pBss->WPA2.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA2.RsnCapability = 0; + pBss->WPA2.bMixMode = FALSE; + + + Length = (INT) pBss->VarIELen; + + while (Length > 0) + { + // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently + pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length; + pEid = (PEID_STRUCT) pTmp; + switch (pEid->Eid) + { + case IE_WPA: + //Parse Cisco IE_WPA (LEAP, CCKM, etc.) + if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3)) + { + pTmp += 11; + switch (*pTmp) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + pBss->WepStatus = Ndis802_11Encryption1Enabled; + pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; + pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + pBss->WepStatus = Ndis802_11Encryption2Enabled; + pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; + pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; + break; + case 4: + pBss->WepStatus = Ndis802_11Encryption3Enabled; + pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled; + pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; + break; + default: + break; + } + + // if Cisco IE_WPA, break + break; + } + else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7)) + { + pBss->bSES = TRUE; + break; + } + else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) + { + // if unsupported vendor specific IE + break; + } + // Skip OUI, version, and multicast suite + // This part should be improved in the future when AP supported multiple cipher suite. + // For now, it's OK since almost all APs have fixed cipher suite supported. + // pTmp = (PUCHAR) pEid->Octet; + pTmp += 11; + + // Cipher Suite Selectors from Spec P802.11i/D3.2 P26. + // Value Meaning + // 0 None + // 1 WEP-40 + // 2 Tkip + // 3 WRAP + // 4 AES + // 5 WEP-104 + // Parse group cipher + switch (*pTmp) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled; + break; + default: + break; + } + // number of unicast suite + pTmp += 1; + + // skip all unicast cipher suites + //Count = *(PUSHORT) pTmp; + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + // Parsing all unicast cipher suite + while (Count > 0) + { + // Skip OUI + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + TmpCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + break; + default: + break; + } + if (TmpCipher > pBss->WPA.PairCipher) + { + // Move the lower cipher suite to PairCipherAux + pBss->WPA.PairCipherAux = pBss->WPA.PairCipher; + pBss->WPA.PairCipher = TmpCipher; + } + else + { + pBss->WPA.PairCipherAux = TmpCipher; + } + pTmp++; + Count--; + } + + // 4. get AKM suite counts + //Count = *(PUSHORT) pTmp; + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + pTmp += 3; + + switch (*pTmp) + { + case 1: + // Set AP support WPA mode + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA; + break; + case 2: + // Set AP support WPA mode + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPAPSK; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK; + break; + default: + break; + } + pTmp += 1; + + // Fixed for WPA-None + if (pBss->BssType == BSS_ADHOC) + { + pBss->AuthMode = Ndis802_11AuthModeWPANone; + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + pBss->WepStatus = pBss->WPA.GroupCipher; + if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) + pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; + } + else + pBss->WepStatus = pBss->WPA.PairCipher; + + // Check the Pair & Group, if different, turn on mixed mode flag + if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher) + pBss->WPA.bMixMode = TRUE; + + break; + + case IE_RSN: + pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; + + // 0. Version must be 1 + if (le2cpu16(pRsnHeader->Version) != 1) + break; + pTmp += sizeof(RSN_IE_HEADER_STRUCT); + + // 1. Check group cipher + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; + + // Parse group cipher + switch (pCipher->Type) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled; + break; + default: + break; + } + // set to correct offset for next parsing + pTmp += sizeof(CIPHER_SUITE_STRUCT); + + // 2. Get pairwise cipher counts + //Count = *(PUSHORT) pTmp; + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + // 3. Get pairwise cipher + // Parsing all unicast cipher suite + while (Count > 0) + { + // Skip OUI + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + TmpCipher = Ndis802_11WEPDisabled; + switch (pCipher->Type) + { + case 1: + case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway + TmpCipher = Ndis802_11Encryption1Enabled; + break; + case 2: + TmpCipher = Ndis802_11Encryption2Enabled; + break; + case 4: + TmpCipher = Ndis802_11Encryption3Enabled; + break; + default: + break; + } + if (TmpCipher > pBss->WPA2.PairCipher) + { + // Move the lower cipher suite to PairCipherAux + pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher; + pBss->WPA2.PairCipher = TmpCipher; + } + else + { + pBss->WPA2.PairCipherAux = TmpCipher; + } + pTmp += sizeof(CIPHER_SUITE_STRUCT); + Count--; + } + + // 4. get AKM suite counts + //Count = *(PUSHORT) pTmp; + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + // 5. Get AKM ciphers + pAKM = (PAKM_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; + + switch (pAKM->Type) + { + case 1: + // Set AP support WPA mode + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2; + break; + case 2: + // Set AP support WPA mode + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2PSK; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK; + break; + default: + break; + } + pTmp += (Count * sizeof(AKM_SUITE_STRUCT)); + + // Fixed for WPA-None + if (pBss->BssType == BSS_ADHOC) + { + pBss->AuthMode = Ndis802_11AuthModeWPANone; + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux; + pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher; + pBss->WepStatus = pBss->WPA.GroupCipher; + if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) + pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; + } + pBss->WepStatus = pBss->WPA2.PairCipher; + + // 6. Get RSN capability + //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp; + pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + // Check the Pair & Group, if different, turn on mixed mode flag + if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher) + pBss->WPA2.bMixMode = TRUE; + + break; + default: + break; + } + Length -= (pEid->Len + 2); + } +} + +// =========================================================================================== +// mac_table.c +// =========================================================================================== + +/*! \brief generates a random mac address value for IBSS BSSID + * \param Addr the bssid location + * \return none + * \pre + * \post + */ +VOID MacAddrRandomBssid( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pAddr) +{ + INT i; + + for (i = 0; i < MAC_ADDR_LEN; i++) + { + pAddr[i] = RandomByte(pAd); + } + + pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx +} + +/*! \brief init the management mac frame header + * \param p_hdr mac header + * \param subtype subtype of the frame + * \param p_ds destination address, don't care if it is a broadcast address + * \return none + * \pre the station has the following information in the pAd->StaCfg + * - bssid + * - station address + * \post + * \note this function initializes the following field + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +VOID MgtMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = BTYPE_MGMT; + pHdr80211->FC.SubType = SubType; +// if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type +// pHdr80211->FC.Type = BTYPE_CNTL; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); +#endif // CONFIG_STA_SUPPORT // + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); +} + +// =========================================================================================== +// mem_mgmt.c +// =========================================================================================== + +/*!*************************************************************************** + * This routine build an outgoing frame, and fill all information specified + * in argument list to the frame body. The actual frame size is the summation + * of all arguments. + * input params: + * Buffer - pointer to a pre-allocated memory segment + * args - a list of pairs. + * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this + * function will FAIL!!! + * return: + * Size of the buffer + * usage: + * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS); + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ****************************************************************************/ +ULONG MakeOutgoingFrame( + OUT CHAR *Buffer, + OUT ULONG *FrameLen, ...) +{ + CHAR *p; + int leng; + ULONG TotLeng; + va_list Args; + + // calculates the total length + TotLeng = 0; + va_start(Args, FrameLen); + do + { + leng = va_arg(Args, int); + if (leng == END_OF_ARGS) + { + break; + } + p = va_arg(Args, PVOID); + NdisMoveMemory(&Buffer[TotLeng], p, leng); + TotLeng = TotLeng + leng; + } while(TRUE); + + va_end(Args); /* clean up */ + *FrameLen = TotLeng; + return TotLeng; +} + +// =========================================================================================== +// mlme_queue.c +// =========================================================================================== + +/*! \brief Initialize The MLME Queue, used by MLME Functions + * \param *Queue The MLME Queue + * \return Always Return NDIS_STATE_SUCCESS in this implementation + * \pre + * \post + * \note Because this is done only once (at the init stage), no need to be locked + + IRQL = PASSIVE_LEVEL + + */ +NDIS_STATUS MlmeQueueInit( + IN MLME_QUEUE *Queue) +{ + INT i; + + NdisAllocateSpinLock(&Queue->Lock); + + Queue->Num = 0; + Queue->Head = 0; + Queue->Tail = 0; + + for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) + { + Queue->Entry[i].Occupied = FALSE; + Queue->Entry[i].MsgLen = 0; + NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); + } + + return NDIS_STATUS_SUCCESS; +} + +/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread + * \param *Queue The MLME Queue + * \param Machine The State Machine Id + * \param MsgType The Message Type + * \param MsgLen The Message length + * \param *Msg The message pointer + * \return TRUE if enqueue is successful, FALSE if the queue is full + * \pre + * \post + * \note The message has to be initialized + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeEnqueue( + IN PRTMP_ADAPTER pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg) +{ + INT Tail; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + // First check the size, it MUST not exceed the mlme queue size + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue)) + { + return FALSE; + } + + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Tail = 0; + } + + Queue->Entry[Tail].Wcid = RESERVED_WCID; + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + + if (Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} + +/*! \brief This function is used when Recv gets a MLME message + * \param *Queue The MLME Queue + * \param TimeStampHigh The upper 32 bit of timestamp + * \param TimeStampLow The lower 32 bit of timestamp + * \param Rssi The receiving RSSI strength + * \param MsgLen The length of the message + * \param *Msg The message pointer + * \return TRUE if everything ok, FALSE otherwise (like Queue Full) + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG TimeStampHigh, + IN ULONG TimeStampLow, + IN UCHAR Rssi0, + IN UCHAR Rssi1, + IN UCHAR Rssi2, + IN ULONG MsgLen, + IN VOID *Msg, + IN UCHAR Signal) +{ + INT Tail, Machine; + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + INT MsgType; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode */ + if(ATE_ON(pAd)) + return FALSE; +#endif // RALINK_ATE // + + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n")); + return FALSE; + } + + // First check the size, it MUST not exceed the mlme queue size + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue)) + { + return FALSE; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + { + DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType)); + return FALSE; + } + } +#endif // CONFIG_STA_SUPPORT // + + // OK, we got all the informations, it is time to put things into queue + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Tail = 0; + } + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; + Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; + Queue->Entry[Tail].Rssi0 = Rssi0; + Queue->Entry[Tail].Rssi1 = Rssi1; + Queue->Entry[Tail].Rssi2 = Rssi2; + Queue->Entry[Tail].Signal = Signal; + Queue->Entry[Tail].Wcid = (UCHAR)Wcid; + + Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel; + + if (Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + + RT28XX_MLME_HANDLER(pAd); + + return TRUE; +} + + +/*! \brief Dequeue a message from the MLME Queue + * \param *Queue The MLME Queue + * \param *Elem The message dequeued from MLME Queue + * \return TRUE if the Elem contains something, FALSE otherwise + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeDequeue( + IN MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem) +{ + NdisAcquireSpinLock(&(Queue->Lock)); + *Elem = &(Queue->Entry[Queue->Head]); + Queue->Num--; + Queue->Head++; + if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Head = 0; + } + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} + +// IRQL = DISPATCH_LEVEL +VOID MlmeRestartStateMachine( + IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_STA_SUPPORT + BOOLEAN Cancelled; +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef QOS_DLS_SUPPORT + UCHAR i; +#endif // QOS_DLS_SUPPORT // + // Cancel all timer events + // Be careful to cancel new added timer + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); + +#ifdef QOS_DLS_SUPPORT + for (i=0; iStaCfg.DLSEntry[i].Timer, &Cancelled); + } +#endif // QOS_DLS_SUPPORT // + } +#endif // CONFIG_STA_SUPPORT // + + // Change back to original channel in case of doing scan + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + // Resume MSDU which is turned off durning scan + RTMPResumeMsduTransmission(pAd); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Set all state machines back IDLE + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + pAd->Mlme.ActMachine.CurrState = ACT_IDLE; +#ifdef QOS_DLS_SUPPORT + pAd->Mlme.DlsMachine.CurrState = DLS_IDLE; +#endif // QOS_DLS_SUPPORT // + } +#endif // CONFIG_STA_SUPPORT // + +} + +/*! \brief test if the MLME Queue is empty + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeQueueEmpty( + IN MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == 0); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +/*! \brief test if the MLME Queue is full + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeQueueFull( + IN MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +/*! \brief The destructor of MLME Queue + * \param + * \return + * \pre + * \post + * \note Clear Mlme Queue, Set Queue->Num to Zero. + + IRQL = PASSIVE_LEVEL + + */ +VOID MlmeQueueDestroy( + IN MLME_QUEUE *pQueue) +{ + NdisAcquireSpinLock(&(pQueue->Lock)); + pQueue->Num = 0; + pQueue->Head = 0; + pQueue->Tail = 0; + NdisReleaseSpinLock(&(pQueue->Lock)); + NdisFreeSpinLock(&(pQueue->Lock)); +} + +/*! \brief To substitute the message type if the message is coming from external + * \param pFrame The frame received + * \param *Machine The state machine + * \param *MsgType the message type for the state machine + * \return TRUE if the substitution is successful, FALSE otherwise + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +#ifdef CONFIG_STA_SUPPORT +BOOLEAN MsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType) +{ + USHORT Seq; + UCHAR EAPType; + PUCHAR pData; + + // Pointer to start of data frames including SNAP header + pData = (PUCHAR) pFrame + LENGTH_802_11; + + // The only data type will pass to this function is EAPOL frame + if (pFrame->Hdr.FC.Type == BTYPE_DATA) + { + if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H)) + { + // Cisco Aironet SNAP header + *Machine = AIRONET_STATE_MACHINE; + *MsgType = MT2_AIRONET_MSG; + return (TRUE); + } +#ifdef LEAP_SUPPORT + if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP + { + // LEAP frames + *Machine = LEAP_STATE_MACHINE; + EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); + return (LeapMsgTypeSubst(EAPType, MsgType)); + } + else +#endif // LEAP_SUPPORT // + { + *Machine = WPA_PSK_STATE_MACHINE; + EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1); + return(WpaMsgTypeSubst(EAPType, MsgType)); + } + } + + switch (pFrame->Hdr.FC.SubType) + { + case SUBTYPE_ASSOC_REQ: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_ASSOC_REQ; + break; + case SUBTYPE_ASSOC_RSP: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_ASSOC_RSP; + break; + case SUBTYPE_REASSOC_REQ: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_REASSOC_REQ; + break; + case SUBTYPE_REASSOC_RSP: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_REASSOC_RSP; + break; + case SUBTYPE_PROBE_REQ: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_PROBE_REQ; + break; + case SUBTYPE_PROBE_RSP: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_PROBE_RSP; + break; + case SUBTYPE_BEACON: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_BEACON; + break; + case SUBTYPE_ATIM: + *Machine = SYNC_STATE_MACHINE; + *MsgType = MT2_PEER_ATIM; + break; + case SUBTYPE_DISASSOC: + *Machine = ASSOC_STATE_MACHINE; + *MsgType = MT2_PEER_DISASSOC_REQ; + break; + case SUBTYPE_AUTH: + // get the sequence number from payload 24 Mac Header + 2 bytes algorithm + NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); + if (Seq == 1 || Seq == 3) + { + *Machine = AUTH_RSP_STATE_MACHINE; + *MsgType = MT2_PEER_AUTH_ODD; + } + else if (Seq == 2 || Seq == 4) + { + *Machine = AUTH_STATE_MACHINE; + *MsgType = MT2_PEER_AUTH_EVEN; + } + else + { + return FALSE; + } + break; + case SUBTYPE_DEAUTH: + *Machine = AUTH_RSP_STATE_MACHINE; + *MsgType = MT2_PEER_DEAUTH; + break; + case SUBTYPE_ACTION: + *Machine = ACTION_STATE_MACHINE; + // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support + if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG) + { + *MsgType = MT2_ACT_INVALID; + } + else + { + *MsgType = (pFrame->Octet[0]&0x7F); + } + break; + default: + return FALSE; + break; + } + + return TRUE; +} +#endif // CONFIG_STA_SUPPORT // + +// =========================================================================================== +// state_machine.c +// =========================================================================================== + +/*! \brief Initialize the state machine. + * \param *S pointer to the state machine + * \param Trans State machine transition function + * \param StNr number of states + * \param MsgNr number of messages + * \param DefFunc default function, when there is invalid state/message combination + * \param InitState initial state of the state machine + * \param Base StateMachine base, internal use only + * \pre p_sm should be a legal pointer + * \post + + IRQL = PASSIVE_LEVEL + + */ +VOID StateMachineInit( + IN STATE_MACHINE *S, + IN STATE_MACHINE_FUNC Trans[], + IN ULONG StNr, + IN ULONG MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + IN ULONG InitState, + IN ULONG Base) +{ + ULONG i, j; + + // set number of states and messages + S->NrState = StNr; + S->NrMsg = MsgNr; + S->Base = Base; + + S->TransFunc = Trans; + + // init all state transition to default function + for (i = 0; i < StNr; i++) + { + for (j = 0; j < MsgNr; j++) + { + S->TransFunc[i * MsgNr + j] = DefFunc; + } + } + + // set the starting state + S->CurrState = InitState; +} + +/*! \brief This function fills in the function pointer into the cell in the state machine + * \param *S pointer to the state machine + * \param St state + * \param Msg incoming message + * \param f the function to be executed when (state, message) combination occurs at the state machine + * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state + * \post + + IRQL = PASSIVE_LEVEL + + */ +VOID StateMachineSetAction( + IN STATE_MACHINE *S, + IN ULONG St, + IN ULONG Msg, + IN STATE_MACHINE_FUNC Func) +{ + ULONG MsgIdx; + + MsgIdx = Msg - S->Base; + + if (St < S->NrState && MsgIdx < S->NrMsg) + { + // boundary checking before setting the action + S->TransFunc[St * S->NrMsg + MsgIdx] = Func; + } +} + +/*! \brief This function does the state transition + * \param *Adapter the NIC adapter pointer + * \param *S the state machine + * \param *Elem the message to be executed + * \return None + + IRQL = DISPATCH_LEVEL + + */ +VOID StateMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem) +{ + (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem); +} + +/* + ========================================================================== + Description: + The drop function, when machine executes this, the message is simply + ignored. This function does nothing, the message is freed in + StateMachinePerformAction() + ========================================================================== + */ +VOID Drop( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ +} + +// =========================================================================================== +// lfsr.c +// =========================================================================================== + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID LfsrInit( + IN PRTMP_ADAPTER pAd, + IN ULONG Seed) +{ + if (Seed == 0) + pAd->Mlme.ShiftReg = 1; + else + pAd->Mlme.ShiftReg = Seed; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +UCHAR RandomByte( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + UCHAR R, Result; + + R = 0; + + if (pAd->Mlme.ShiftReg == 0) + NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg); + + for (i = 0; i < 8; i++) + { + if (pAd->Mlme.ShiftReg & 0x00000001) + { + pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; + Result = 1; + } + else + { + pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1; + Result = 0; + } + R = (R << 1) | Result; + } + + return R; +} + +VOID AsicUpdateAutoFallBackTable( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRateTable) +{ + UCHAR i; + HT_FBK_CFG0_STRUC HtCfg0; + HT_FBK_CFG1_STRUC HtCfg1; + LG_FBK_CFG0_STRUC LgCfg0; + LG_FBK_CFG1_STRUC LgCfg1; + PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate; + + // set to initial value + HtCfg0.word = 0x65432100; + HtCfg1.word = 0xedcba988; + LgCfg0.word = 0xedcba988; + LgCfg1.word = 0x00002100; + + pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1; + for (i = 1; i < *((PUCHAR) pRateTable); i++) + { + pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i; + switch (pCurrTxRate->Mode) + { + case 0: //CCK + break; + case 1: //OFDM + { + switch(pCurrTxRate->CurrMCS) + { + case 0: + LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 1: + LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 2: + LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 3: + LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 4: + LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 5: + LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 6: + LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + case 7: + LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS; + break; + } + } + break; +#ifdef DOT11_N_SUPPORT + case 2: //HT-MIX + case 3: //HT-GF + { + if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS)) + { + switch(pCurrTxRate->CurrMCS) + { + case 0: + HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS; + break; + case 1: + HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS; + break; + case 2: + HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS; + break; + case 3: + HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS; + break; + case 4: + HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS; + break; + case 5: + HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS; + break; + case 6: + HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS; + break; + case 7: + HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS; + break; + case 8: + HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS; + break; + case 9: + HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS; + break; + case 10: + HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS; + break; + case 11: + HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS; + break; + case 12: + HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS; + break; + case 13: + HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS; + break; + case 14: + HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS; + break; + case 15: + HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS)); + } + } + } + break; +#endif // DOT11_N_SUPPORT // + } + + pNextTxRate = pCurrTxRate; + } + + RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word); + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word); + RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word); + RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word); +} + +/* + ======================================================================== + + Routine Description: + Set MAC register value according operation mode. + OperationMode AND bNonGFExist are for MM and GF Proteciton. + If MM or GF mask is not set, those passing argument doesn't not take effect. + + Operation mode meaning: + = 0 : Pure HT, no preotection. + = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. + = 0x10: No Transmission in 40M is protected. + = 0x11: Transmission in both 40M and 20M shall be protected + if (bNonGFExist) + we should choose not to use GF. But still set correct ASIC registers. + ======================================================================== +*/ +VOID AsicUpdateProtect( + IN PRTMP_ADAPTER pAd, + IN USHORT OperationMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist) +{ + PROT_CFG_STRUC ProtCfg, ProtCfg4; + UINT32 Protect[6]; + USHORT offset; + UCHAR i; + UINT32 MacReg = 0; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + +#ifdef DOT11_N_SUPPORT + if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) + { + return; + } + + if (pAd->BATable.numAsOriginator) + { + // + // enable the RTS/CTS to avoid channel collision + // + SetMask = ALLN_SETPROTECT; + OperationMode = 8; + } +#endif // DOT11_N_SUPPORT // + + // Config ASIC RTS threshold register + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFF0000FF; + + // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096 + if (( +#ifdef DOT11_N_SUPPORT + (pAd->CommonCfg.BACapability.field.AmsduEnable) || +#endif // DOT11_N_SUPPORT // + (pAd->CommonCfg.bAggregationCapable == TRUE)) + && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) + { + MacReg |= (0x1000 << 8); + } + else + { + MacReg |= (pAd->CommonCfg.RtsThreshold << 8); + } + + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + + // Initial common protection settings + RTMPZeroMemory(Protect, sizeof(Protect)); + ProtCfg4.word = 0; + ProtCfg.word = 0; + ProtCfg.field.TxopAllowGF40 = 1; + ProtCfg.field.TxopAllowGF20 = 1; + ProtCfg.field.TxopAllowMM40 = 1; + ProtCfg.field.TxopAllowMM20 = 1; + ProtCfg.field.TxopAllowOfdm = 1; + ProtCfg.field.TxopAllowCck = 1; + ProtCfg.field.RTSThEn = 1; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + + // update PHY mode and rate + if (pAd->CommonCfg.Channel > 14) + ProtCfg.field.ProtectRate = 0x4000; + ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; + + // Handle legacy(B/G) protection + if (bDisableBGProtect) + { + //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; + ProtCfg.field.ProtectCtrl = 0; + Protect[0] = ProtCfg.word; + Protect[1] = ProtCfg.word; + } + else + { + //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; + ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected + Protect[0] = ProtCfg.word; + ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect + Protect[1] = ProtCfg.word; + } + +#ifdef DOT11_N_SUPPORT + // Decide HT frame protection. + if ((SetMask & ALLN_SETPROTECT) != 0) + { + switch(OperationMode) + { + case 0x0: + // NO PROTECT + // 1.All STAs in the BSS are 20/40 MHz HT + // 2. in ai 20/40MHz BSS + // 3. all STAs are 20MHz in a 20MHz BSS + // Pure HT. no protection. + + // MM20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[2] = 0x01744004; + + // MM40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[3] = 0x03f44084; + + // CF20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[4] = 0x01744004; + + // CF40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[5] = 0x03f44084; + + if (bNonGFExist) + { + // PROT_NAV(19:18) -- 01 (Short NAV protectiion) + // PROT_CTRL(17:16) -- 01 (RTS/CTS) + Protect[4] = 0x01754004; + Protect[5] = 0x03f54084; + } + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + break; + + case 1: + // This is "HT non-member protection mode." + // If there may be non-HT STAs my BSS + ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) + ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. + ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083; + } + //Assign Protection method for 20&40 MHz packets + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + + case 2: + // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets + ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None) + ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1. + + //Assign Protection method for 40MHz packets + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + if (bNonGFExist) + { + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + } + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + break; + + case 3: + // HT mixed mode. PROTECT ALL! + // Assign Rate + ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1. + ProtCfg4.word = 0x03f44084; + // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18.. + ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083 + } + //Assign Protection method for 20&40 MHz packets + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[2] = ProtCfg.word; + Protect[3] = ProtCfg4.word; + Protect[4] = ProtCfg.word; + Protect[5] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + + case 8: + Protect[2] = 0x01754004; + Protect[3] = 0x03f54084; + Protect[4] = 0x01754004; + Protect[5] = 0x03f54084; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + } + } +#endif // DOT11_N_SUPPORT // + + offset = CCK_PROT_CFG; + for (i = 0;i < 6;i++) + { + if ((SetMask & (1<< i))) + { + RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); + } + } +} + + +#ifdef RT30xx +/* + ======================================================================== + + Routine Description: Write RT30xx RF register through MAC + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RT30xxWriteRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR RegID, + IN UCHAR Value) +{ + RF_CSR_CFG_STRUC rfcsr; + UINT i = 0; + + do + { + RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word); + + if (!rfcsr.field.RF_CSR_KICK) + break; + i++; + } + while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + return STATUS_UNSUCCESSFUL; + } + + rfcsr.field.RF_CSR_WR = 1; + rfcsr.field.RF_CSR_KICK = 1; + rfcsr.field.TESTCSR_RFACC_REGNUM = RegID; + rfcsr.field.RF_CSR_DATA = Value; + + RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word); + + return STATUS_SUCCESS; +} + + +/* + ======================================================================== + + Routine Description: Read RT30xx RF register through MAC + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RT30xxReadRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR RegID, + IN PUCHAR pValue) +{ + RF_CSR_CFG_STRUC rfcsr; + UINT i=0, k=0; + + for (i=0; iMACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0)) + { + RFValue |= 0x20; + } + RT30xxWriteRFRegister(pAd, RF_R17, RFValue); + + // RX_LO1_en, RF R20 register Bit 3 to 0 + RT30xxReadRFRegister(pAd, RF_R20, &RFValue); + RFValue &= (~0x08); + RT30xxWriteRFRegister(pAd, RF_R20, RFValue); + + // RX_LO2_en, RF R21 register Bit 3 to 0 + RT30xxReadRFRegister(pAd, RF_R21, &RFValue); + RFValue &= (~0x08); + RT30xxWriteRFRegister(pAd, RF_R21, RFValue); + + // LDORF_VC, RF R27 register Bit 2 to 0 + RT30xxReadRFRegister(pAd, RF_R27, &RFValue); + if ((pAd->MACVersion & 0xffff) < 0x0211) + RFValue = (RFValue & (~0x77)) | 0x3; + else + RFValue = (RFValue & (~0x77)); + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); + /* end johnli */ +} + +/* + ========================================================================== + Description: + + Load RF sleep-mode setup + + ========================================================================== + */ +VOID RT30xxLoadRFSleepModeSetup( + IN PRTMP_ADAPTER pAd) +{ + UCHAR RFValue; + UINT32 MACValue; + + // RF_BLOCK_en. RF R1 register Bit 0 to 0 + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + RFValue &= (~0x01); + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); + + // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0 + RT30xxReadRFRegister(pAd, RF_R07, &RFValue); + RFValue &= (~0x30); + RT30xxWriteRFRegister(pAd, RF_R07, RFValue); + + // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0 + RT30xxReadRFRegister(pAd, RF_R09, &RFValue); + RFValue &= (~0x0E); + RT30xxWriteRFRegister(pAd, RF_R09, RFValue); + + // RX_CTB_en, RF R21 register Bit 7 to 0 + RT30xxReadRFRegister(pAd, RF_R21, &RFValue); + RFValue &= (~0x80); + RT30xxWriteRFRegister(pAd, RF_R21, RFValue); + + // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1 + RT30xxReadRFRegister(pAd, RF_R27, &RFValue); + RFValue |= 0x77; + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); + + RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); + MACValue |= 0x1D000000; + RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); +} + +/* + ========================================================================== + Description: + + Reverse RF sleep-mode setup + + ========================================================================== + */ +VOID RT30xxReverseRFSleepModeSetup( + IN PRTMP_ADAPTER pAd) +{ + UCHAR RFValue; + UINT32 MACValue; + + // RF_BLOCK_en, RF R1 register Bit 0 to 1 + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + RFValue |= 0x01; + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); + + // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1 + RT30xxReadRFRegister(pAd, RF_R07, &RFValue); + RFValue |= 0x30; + RT30xxWriteRFRegister(pAd, RF_R07, RFValue); + + // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1 + RT30xxReadRFRegister(pAd, RF_R09, &RFValue); + RFValue |= 0x0E; + RT30xxWriteRFRegister(pAd, RF_R09, RFValue); + + // RX_CTB_en, RF R21 register Bit 7 to 1 + RT30xxReadRFRegister(pAd, RF_R21, &RFValue); + RFValue |= 0x80; + RT30xxWriteRFRegister(pAd, RF_R21, RFValue); + + // LDORF_VC, RF R27 register Bit 2 to 0 + RT30xxReadRFRegister(pAd, RF_R27, &RFValue); + if ((pAd->MACVersion & 0xffff) < 0x0211) + RFValue = (RFValue & (~0x77)) | 0x3; + else + RFValue = (RFValue & (~0x77)); + RT30xxWriteRFRegister(pAd, RF_R27, RFValue); + + // RT3071 version E has fixed this issue + if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211)) + { + // patch tx EVM issue temporarily + RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); + MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000); + RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); + } + else + { + RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue); + MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000); + RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue); + } +} +// end johnli +#endif // RT30xx // + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan) +{ + ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; + CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER; + UCHAR index; + UINT32 Value = 0; //BbpReg, Value; + RTMP_RF_REGS *RFRegTable; + + // Search Tx power value +#if 1 + // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list + // in ChannelList, so use TxPower array instead. + // + for (index = 0; index < MAX_NUM_OF_CHANNELS; index++) + { + if (Channel == pAd->TxPower[index].Channel) + { + TxPwer = pAd->TxPower[index].Power; + TxPwer2 = pAd->TxPower[index].Power2; + break; + } + } +#else + for (index = 0; index < pAd->ChannelListNum; index++) + { + if (Channel == pAd->ChannelList[index].Channel) + { + TxPwer = pAd->ChannelList[index].Power; + TxPwer2 = pAd->ChannelList[index].Power2; + break; + } + } +#endif + + if (index == MAX_NUM_OF_CHANNELS) + { + DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel)); + } + +#ifdef RT30xx + // The RF programming sequence is difference between 3xxx and 2xxx + if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) || + (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022))) + { + /* modify by WY for Read RF Reg. error */ + UCHAR RFValue; + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + if (Channel == FreqItems3020[index].Channel) + { + // Programming channel parameters + RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N); + RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K); + RT30xxReadRFRegister(pAd, RF_R06, &RFValue); + RFValue = (RFValue & 0xFC) | FreqItems3020[index].R; + RT30xxWriteRFRegister(pAd, RF_R06, RFValue); + + // Set Tx0 Power + RT30xxReadRFRegister(pAd, RF_R12, &RFValue); + RFValue = (RFValue & 0xE0) | TxPwer; + RT30xxWriteRFRegister(pAd, RF_R12, RFValue); + + // Set Tx1 Power + RT30xxReadRFRegister(pAd, RF_R13, &RFValue); + RFValue = (RFValue & 0xE0) | TxPwer2; + RT30xxWriteRFRegister(pAd, RF_R13, RFValue); + + // Tx/Rx Stream setting + RT30xxReadRFRegister(pAd, RF_R01, &RFValue); + //if (IS_RT3090(pAd)) + // RFValue |= 0x01; // Enable RF block. + RFValue &= 0x03; //clear bit[7~2] + if (pAd->Antenna.field.TxPath == 1) + RFValue |= 0xA0; + else if (pAd->Antenna.field.TxPath == 2) + RFValue |= 0x80; + if (pAd->Antenna.field.RxPath == 1) + RFValue |= 0x50; + else if (pAd->Antenna.field.RxPath == 2) + RFValue |= 0x40; + RT30xxWriteRFRegister(pAd, RF_R01, RFValue); + + // Set RF offset + RT30xxReadRFRegister(pAd, RF_R23, &RFValue); + RFValue = (RFValue & 0x80) | pAd->RfFreqOffset; + RT30xxWriteRFRegister(pAd, RF_R23, RFValue); + + // Set BW + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40)) + { + RFValue = pAd->Mlme.CaliBW40RfR24; + //DISABLE_11N_CHECK(pAd); + } + else + { + RFValue = pAd->Mlme.CaliBW20RfR24; + } + RT30xxWriteRFRegister(pAd, RF_R24, RFValue); + RT30xxWriteRFRegister(pAd, RF_R31, RFValue); + + // Enable RF tuning + RT30xxReadRFRegister(pAd, RF_R07, &RFValue); + RFValue = RFValue | 0x1; + RT30xxWriteRFRegister(pAd, RF_R07, RFValue); + + // latch channel for future usage. + pAd->LatchRfRegs.Channel = Channel; + + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems3020[index].N, + FreqItems3020[index].K, + FreqItems3020[index].R)); + + break; + } + } + } + else +#endif // RT30xx // + + { + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; + } + + if (pAd->Antenna.field.RxPath == 2) + { + R2 |= 0x40; // write 1 to off Rxpath. + } + else if (pAd->Antenna.field.RxPath == 1) + { + R2 |= 0x20040; // write 1 to off RxPath + } + + if (Channel > 14) + { + // initialize R3, R4 + R3 = (RFRegTable[index].R3 & 0xffffc1ff); + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15); + + // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB + // R3 + if ((TxPwer >= -7) && (TxPwer < 0)) + { + TxPwer = (7+TxPwer); + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10); + DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer)); + } + else + { + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10) | (1 << 9); + } + + // R4 + if ((TxPwer2 >= -7) && (TxPwer2 < 0)) + { + TxPwer2 = (7+TxPwer2); + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7); + DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); + } + else + { + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7) | (1 << 6); + } + } + else + { + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0 + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1 + } + + // Based on BBP current mode before changing RF channel. + if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40)) + { + R4 |=0x200000; + } + + // Update variables + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + // Set RF value 1's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 2's set R3[bit2] = [1] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 3's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + break; + } + } + break; + + default: + break; + } + } + + // Change BBP setting during siwtch from a->g, g->a + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. + //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + + // Rx High power VGA offset for LNA select + if (pAd->NicConfig2.field.ExternalLNAForG) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + else + { + ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505 + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue. + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + // Rx High power VGA offset for LNA select + if (pAd->NicConfig2.field.ExternalLNAForA) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50); + } + + // 5G band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + + // R66 should be set according to Channel and use 20MHz when scanning + //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd))); + if (bScan) + RTMPSetAGCInitValue(pAd, BW_20); + else + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + + // + // On 11A, We should delay and wait RF/BBP to be stable + // and the appropriate time should be 1000 micro seconds + // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. + // + RTMPusecDelay(1000); + + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", + Channel, + pAd->RfIcType, + (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); +} + +/* + ========================================================================== + Description: + This function is required for 2421 only, and should not be used during + site survey. It's only required after NIC decided to stay at a channel + for a longer period. + When this function is called, it's always after AsicSwitchChannel(). + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicLockChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicAntennaSelect( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + if (pAd->Mlme.OneSecPeriodicRound % 2 == 1) + { + // patch for AsicSetRxAnt failed + pAd->RxAnt.EvaluatePeriod = 0; + + // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a + // valid indication of the distance between this AP and its clients. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + SHORT realavgrssi1; + + // if no traffic then reset average rssi to trigger evaluation +#ifdef CONFIG_STA_SUPPORT + if (pAd->StaCfg.NumOfAvgRssiSample < 5) + { + pAd->RxAnt.Pair1LastAvgRssi = (-99); + pAd->RxAnt.Pair2LastAvgRssi = (-99); + DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n")); + } + + pAd->StaCfg.NumOfAvgRssiSample = 0; +#endif // CONFIG_STA_SUPPORT // + realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3); + + DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt)); + + // if the difference between two rssi is larger or less than 5, then evaluate the other antenna + if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5))) + { + pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1; + AsicEvaluateRxAnt(pAd); + } + } + else + { + // if not connected, always switch antenna to try to connect + UCHAR temp; + + temp = pAd->RxAnt.Pair1PrimaryRxAnt; + pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt; + pAd->RxAnt.Pair1SecondaryRxAnt = temp; + + DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n")); + + AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); + } + } +} + +/* + ======================================================================== + + Routine Description: + Antenna miscellaneous setting. + + Arguments: + pAd Pointer to our adapter + BandState Indicate current Band State. + + Return Value: + None + + IRQL <= DISPATCH_LEVEL + + Note: + 1.) Frame End type control + only valid for G only (RF_2527 & RF_2529) + 0: means DPDT, set BBP R4 bit 5 to 1 + 1: means SPDT, set BBP R4 bit 5 to 0 + + + ======================================================================== +*/ +VOID AsicAntennaSetting( + IN PRTMP_ADAPTER pAd, + IN ABGBAND_STATE BandState) +{ +} + +VOID AsicRfTuningExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ +} + +/* + ========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in LINK UP in INFRASTRUCTURE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) + 1. TxPowerPercentage + 2. auto calibration based on TSSI feedback + 3. extra 2 db for CCK + 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + + NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), + it should be called AFTER MlmeDynamicTxRatSwitching() + ========================================================================== + */ +VOID AsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + INT i, j; + CHAR DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + UCHAR BbpR1 = 0, BbpR49 = 0, idx; + PCHAR pTxAgcCompensate; + ULONG TxPwr[5]; + CHAR Value; + + + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + if (pAd->CommonCfg.CentralChannel > 14) + { + TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; + } + } + else + { + if (pAd->CommonCfg.Channel > 14) + { + TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + } + } + + // TX power compensation for temperature variation based on TSSI. try every 4 second + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { + if (pAd->CommonCfg.Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + /* BbpR1 is unsigned char */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ + /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ + /* step value is defined in pAd->TxAgcStepG for tx power value */ + + /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ + /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + above value are examined in mass factory production */ + /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ + + /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > pTssiMinusBoundary[1]) + { + // Reading is larger than the reference value + // check for how large we need to decrease the Tx power + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range + break; + } + // The index is the step we should decrease, idx = 0 means there is nothing to compensate +// if (R3 > (ULONG) (TxAgcStep * (idx-1))) + *pTxAgcCompensate = -(TxAgcStep * (idx-1)); +// else +// *pTxAgcCompensate = -((UCHAR)R3); + + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 < pTssiPlusBoundary[1]) + { + // Reading is smaller than the reference value + // check for how large we need to increase the Tx power + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range + break; + } + // The index is the step we should increase, idx = 0 means there is nothing to compensate + *pTxAgcCompensate = TxAgcStep * (idx-1); + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pAd->CommonCfg.Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); + BbpR1 &= 0xFC; + +#ifdef SINGLE_SKU + // Handle regulatory max tx power constrain + do + { + UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion; + UCHAR AdjustMaxTxPwr[40]; + + if (pAd->CommonCfg.Channel > 14) // 5G band + TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8); + else // 2.4G band + TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF); + CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + + // error handling, range check + if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50)) + { + DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr)); + break; + } + + criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion + + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr)); + + // Adjust max tx power according to the relationship of tx power in E2PROM + for (i=0; i<5; i++) + { + // CCK will have 4dBm larger than OFDM + // Therefore, we should separate to parse the tx power field + if (i == 0) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); + + if (j < 4) + { + // CCK will have 4dBm larger than OFDM + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4; + } + else + { + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); + } + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); + } + } + else + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); + + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); + } + } + } + + // Adjust tx power according to the relationship + for (i=0; i<5; i++) + { + if (TxPwr[i] != 0xffffffff) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); + + // The system tx power is larger than the regulatory, the power should be restrain + if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr) + { + // decrease to zero and don't need to take care BBPR1 + if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0) + Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr); + else + Value = 0; + + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); + } + else + DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j])); + + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } + } + } + } while (FALSE); +#endif // SINGLE_SKU // + + /* calculate delta power based on the percentage specified from UI */ + // E2PROM setting is calibrated for maximum TX power (i.e. 100%) + // We lower TX power here according to the percentage specified from UI + if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control + ; + else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1; + { + DeltaPwr -= 1; + } + else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3; + { + DeltaPwr -= 3; + } + else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6; + { + BbpR1 |= 0x01; + } + else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9; + { + BbpR1 |= 0x01; + DeltaPwr -= 3; + } + else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12; + { + BbpR1 |= 0x02; + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + /* reset different new tx power for different TX rate */ + for(i=0; i<5; i++) + { + if (TxPwr[i] != 0xffffffff) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ + + if ((Value + DeltaPwr) < 0) + { + Value = 0; /* min */ + } + else if ((Value + DeltaPwr) > 0xF) + { + Value = 0xF; /* max */ + } + else + { + Value += DeltaPwr; /* temperature compensation */ + } + + /* fill new value to CSR offset */ + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); + } + } + + +} + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup + automatically. Instead, MCU will issue a TwakeUpInterrupt to host after + the wakeup timer timeout. Driver has to issue a separate command to wake + PHY up. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp) +{ + RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp); +} + +/* + ========================================================================== + Description: + AsicForceWakeup() is used whenever manual wakeup is required + AsicForceSleep() should only be used when not in INFRA BSS. When + in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead. + ========================================================================== + */ +VOID AsicForceSleep( + IN PRTMP_ADAPTER pAd) +{ + +} + +/* + ========================================================================== + Description: + AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup) + expired. + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + ========================================================================== + */ +VOID AsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx) +{ + DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n")); + RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx); +} +#endif // CONFIG_STA_SUPPORT // +/* + ========================================================================== + Description: + Set My BSSID + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetBssid( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid) +{ + ULONG Addr4; + DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n", + pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5])); + + Addr4 = (ULONG)(pBssid[0]) | + (ULONG)(pBssid[1] << 8) | + (ULONG)(pBssid[2] << 16) | + (ULONG)(pBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + + Addr4 = 0; + // always one BSSID in STA mode + Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8); + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); +} + +VOID AsicSetMcastWC( + IN PRTMP_ADAPTER pAd) +{ + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID]; + USHORT offset; + + pEntry->Sst = SST_ASSOC; + pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index + pEntry->PsMode = PWR_ACTIVE; + pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate; + offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDelWcidTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid) +{ + ULONG Addr0 = 0x0, Addr1 = 0x0; + ULONG offset; + + DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid)); + offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE; + RTMP_IO_WRITE32(pAd, offset, Addr0); + offset += 4; + RTMP_IO_WRITE32(pAd, offset, Addr1); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableRDG( + IN PRTMP_ADAPTER pAd) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + UINT32 Data = 0; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 1; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + Data |= 0x80; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDisableRDG( + IN PRTMP_ADAPTER pAd) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + UINT32 Data = 0; + + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 0; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + + Data &= 0xFFFFFF00; + //Data |= 0x20; +#ifndef WIFI_TEST + //if ( pAd->CommonCfg.bEnableTxBurst ) + // Data |= 0x60; // for performance issue not set the TXOP to 0 +#endif + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) +#ifdef DOT11_N_SUPPORT + && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) +#endif // DOT11_N_SUPPORT // + ) + { + // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode + if (pAd->CommonCfg.bEnableTxBurst) + Data |= 0x20; + } + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDisableSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); + + // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect + // that NIC will never wakes up because TSF stops and no more + // TBTT interrupts + pAd->TbttTickCount = 0; + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.bBeaconGen = 0; + csr.field.bTBTTEnable = 0; + csr.field.TsfSyncMode = 0; + csr.field.bTsfTicking = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableBssSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n")); + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); +// RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU + csr.field.bTsfTicking = 1; + csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode + csr.field.bBeaconGen = 0; // do NOT generate BEACON + csr.field.bTBTTEnable = 1; + } +#endif // CONFIG_STA_SUPPORT // + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); +} + +/* + ========================================================================== + Description: + Note: + BEACON frame in shared memory should be built ok before this routine + can be called. Otherwise, a garbage frame maybe transmitted out every + Beacon period. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableIbssSync( + IN PRTMP_ADAPTER pAd) +{ + BCN_TIME_CFG_STRUC csr9; + PUCHAR ptr; + UINT i; + + DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount)); + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); + csr9.field.bBeaconGen = 0; + csr9.field.bTBTTEnable = 0; + csr9.field.bTsfTicking = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); + + +#ifdef RT2870 + // move BEACON TXD and frame content to on-chip memory + ptr = (PUCHAR)&pAd->BeaconTxWI; + for (i=0; iBeaconBuf; + for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2) + { + //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr); + RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2); + ptr +=2; + } +#endif // RT2870 // + + // + // For Wi-Fi faily generated beacons between participating stations. + // Set TBTT phase adaptive adjustment step to 8us (default 16us) + // don't change settings 2006-5- by Jerry + //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010); + + // start sending BEACON + csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU + csr9.field.bTsfTicking = 1; + csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode + csr9.field.bTBTTEnable = 1; + csr9.field.bBeaconGen = 1; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetEdcaParm( + IN PRTMP_ADAPTER pAd, + IN PEDCA_PARM pEdcaParm) +{ + EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; + AC_TXOP_CSR0_STRUC csr0; + AC_TXOP_CSR1_STRUC csr1; + AIFSN_CSR_STRUC AifsnCsr; + CWMIN_CSR_STRUC CwminCsr; + CWMAX_CSR_STRUC CwmaxCsr; + int i; + + Ac0Cfg.word = 0; + Ac1Cfg.word = 0; + Ac2Cfg.word = 0; + Ac3Cfg.word = 0; + if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); + for (i=0; iMacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli) + CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE); + } + + //======================================================== + // MAC Register has a copy . + //======================================================== +//#ifndef WIFI_TEST + if( pAd->CommonCfg.bEnableTxBurst ) + { + // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode + Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode + } + else + Ac0Cfg.field.AcTxop = 0; // QID_AC_BE +//#else +// Ac0Cfg.field.AcTxop = 0; // QID_AC_BE +//#endif + Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac0Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + + Ac1Cfg.field.AcTxop = 0; // QID_AC_BK + Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac1Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + + if (pAd->CommonCfg.PhyMode == PHY_11B) + { + Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms + Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms + } + else + { + Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms + Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms + } + Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac2Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS; + Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS; + Ac3Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); + + //======================================================== + // DMA Register has a copy too. + //======================================================== + csr0.field.Ac0Txop = 0; // QID_AC_BE + csr0.field.Ac1Txop = 0; // QID_AC_BK + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + if (pAd->CommonCfg.PhyMode == PHY_11B) + { + csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms + csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms + } + else + { + csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms + csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms + } + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); + + CwminCsr.word = 0; + CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS; + CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS; + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS; + CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS; + RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + + RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); + + NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM)); + } + else + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); + //======================================================== + // MAC Register has a copy. + //======================================================== + // + // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27 + // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue. + // + //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this + + Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; + Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE]; + Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1; + + Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2; + Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; + Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1; + + Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; + Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI]; + Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI]; + Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI]; +#ifdef INF_AMAZON_SE +#endif // INF_AMAZON_SE // + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Tuning for Wi-Fi WMM S06 + if (pAd->CommonCfg.bWiFiTest && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + Ac2Cfg.field.Aifsn -= 1; + + // Tuning for TGn Wi-Fi 5.2.32 + // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta + if (STA_TGN_WIFI_ON(pAd) && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + { + Ac0Cfg.field.Aifsn = 3; + Ac2Cfg.field.AcTxop = 5; + } + +#ifdef RT30xx + if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020) + { + // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta. + Ac2Cfg.field.Aifsn = 5; + } +#endif // RT30xx // + } +#endif // CONFIG_STA_SUPPORT // + + Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; + Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; + Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; + Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; + +//#ifdef WIFI_TEST + if (pAd->CommonCfg.bWiFiTest) + { + if (Ac3Cfg.field.AcTxop == 102) + { + Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */ + Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; + Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI]; + } /* End of if */ + } +//#endif // WIFI_TEST // + + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); + + + //======================================================== + // DMA Register has a copy too. + //======================================================== + csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop; + csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop; + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + + csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop; + csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop; + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); + + CwminCsr.word = 0; + CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE]; + CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK]; + CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI]; +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test +#endif // CONFIG_STA_SUPPORT // + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE]; + CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK]; + CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI]; + CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO]; + RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + + AifsnCsr.word = 0; + AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE]; + AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK]; + AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI]; +#ifdef INF_AMAZON_SE +#endif // INF_AMAZON_SE // + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Tuning for Wi-Fi WMM S06 + if (pAd->CommonCfg.bWiFiTest && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4; + + // Tuning for TGn Wi-Fi 5.2.32 + // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta + if (STA_TGN_WIFI_ON(pAd) && + pEdcaParm->Aifsn[QID_AC_VI] == 10) + { + AifsnCsr.field.Aifsn0 = 3; + AifsnCsr.field.Aifsn2 = 7; + } + + if (INFRA_ON(pAd)) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE); + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test +#ifdef RT30xx + if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020) + { + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04. + } +#endif // RT30xx // +#endif // CONFIG_STA_SUPPORT // + RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word); + + NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + if (!ADHOC_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount)); + DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[0], + pEdcaParm->Cwmin[0], + pEdcaParm->Cwmax[0], + pEdcaParm->Txop[0]<<5, + pEdcaParm->bACM[0])); + DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[1], + pEdcaParm->Cwmin[1], + pEdcaParm->Cwmax[1], + pEdcaParm->Txop[1]<<5, + pEdcaParm->bACM[1])); + DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[2], + pEdcaParm->Cwmin[2], + pEdcaParm->Cwmax[2], + pEdcaParm->Txop[2]<<5, + pEdcaParm->bACM[2])); + DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n", + pEdcaParm->Aifsn[3], + pEdcaParm->Cwmin[3], + pEdcaParm->Cwmax[3], + pEdcaParm->Txop[3]<<5, + pEdcaParm->bACM[3])); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetSlotTime( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUseShortSlotTime) +{ + ULONG SlotTime; + UINT32 RegValue = 0; + +#ifdef CONFIG_STA_SUPPORT + if (pAd->CommonCfg.Channel > 14) + bUseShortSlotTime = TRUE; +#endif // CONFIG_STA_SUPPORT // + + if (bUseShortSlotTime) + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + else + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED); + + SlotTime = (bUseShortSlotTime)? 9 : 20; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // force using short SLOT time for FAE to demo performance when TxBurst is ON + if (pAd->CommonCfg.bEnableTxBurst) + SlotTime = 9; + } +#endif // CONFIG_STA_SUPPORT // + + // + // For some reasons, always set it to short slot time. + // + // ToDo: Should consider capability with 11B + // +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.BssType == BSS_ADHOC) + SlotTime = 20; + } +#endif // CONFIG_STA_SUPPORT // + + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + RegValue = RegValue & 0xFFFFFF00; + + RegValue |= SlotTime; + + RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); +} + +/* + ======================================================================== + Description: + Add Shared key information into ASIC. + Update shared key, TxMic and RxMic to Asic Shared key table + Update its cipherAlg to Asic Shared key Mode. + + Return: + ======================================================================== +*/ +VOID AsicAddSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN PUCHAR pKey, + IN PUCHAR pTxMic, + IN PUCHAR pRxMic) +{ + ULONG offset; //, csr0; + SHAREDKEY_MODE_STRUC csr1; + + DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx)); +//============================================================================================ + + DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx)); + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); + if (pRxMic) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); + } + if (pTxMic) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); + } +//============================================================================================ + // + // fill key material - key + TX MIC + RX MIC + // + +#ifdef RT2870 +{ + offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE; + RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY); + + offset += MAX_LEN_OF_SHARE_KEY; + if (pTxMic) + { + RTUSBMultiWrite(pAd, offset, pTxMic, 8); + } + + offset += 8; + if (pRxMic) + { + RTUSBMultiWrite(pAd, offset, pRxMic, 8); + } +} +#endif // RT2870 // + + // + // Update cipher algorithm. WSTA always use BSS0 + // + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word); + DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word)); + if ((BssIndex%2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = CipherAlg; + else + csr1.field.Bss0Key3CipherAlg = CipherAlg; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = CipherAlg; + else + csr1.field.Bss1Key3CipherAlg = CipherAlg; + } + DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word); + +} + +// IRQL = DISPATCH_LEVEL +VOID AsicRemoveSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx) +{ + //ULONG SecCsr0; + SHAREDKEY_MODE_STRUC csr1; + + DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx)); + + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word); + if ((BssIndex%2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = 0; + else + csr1.field.Bss0Key3CipherAlg = 0; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = 0; + else + csr1.field.Bss1Key3CipherAlg = 0; + } + DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word); + ASSERT(BssIndex < 4); + ASSERT(KeyIdx < 4); + +} + + +VOID AsicUpdateWCIDAttribute( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN UCHAR BssIndex, + IN UCHAR CipherAlg, + IN BOOLEAN bUsePairewiseKeyTable) +{ + ULONG WCIDAttri = 0, offset; + + // + // Update WCID attribute. + // Only TxKey could update WCID attribute. + // + offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE); + WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable); + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); +} + +VOID AsicUpdateWCIDIVEIV( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV) +{ + ULONG offset; + + offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE); + + RTMP_IO_WRITE32(pAd, offset, uIV); + RTMP_IO_WRITE32(pAd, offset + 4, uEIV); +} + +VOID AsicUpdateRxWCIDTable( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN PUCHAR pAddr) +{ + ULONG offset; + ULONG Addr; + + offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE); + Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24); + RTMP_IO_WRITE32(pAd, offset, Addr); + Addr = pAddr[4] + (pAddr[5] << 8); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); +} + + +/* + ======================================================================== + + Routine Description: + Set Cipher Key, Cipher algorithm, IV/EIV to Asic + + Arguments: + pAd Pointer to our adapter + WCID WCID Entry number. + BssIndex BSSID index, station or none multiple BSSID support + this value should be 0. + KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled + pCipherKey Pointer to Cipher Key. + bUsePairewiseKeyTable TRUE means saved the key in SharedKey table, + otherwise PairewiseKey table + bTxKey This is the transmit key if enabled. + + Return Value: + None + + Note: + This routine will set the relative key stuff to Asic including WCID attribute, + Cipher Key, Cipher algorithm and IV/EIV. + + IV/EIV will be update if this CipherKey is the transmission key because + ASIC will base on IV's KeyID value to select Cipher Key. + + If bTxKey sets to FALSE, this is not the TX key, but it could be + RX key + + For AP mode bTxKey must be always set to TRUE. + ======================================================================== +*/ +VOID AsicAddKeyEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey, + IN BOOLEAN bUsePairewiseKeyTable, + IN BOOLEAN bTxKey) +{ + ULONG offset; +// ULONG WCIDAttri = 0; + UCHAR IV4 = 0; + PUCHAR pKey = pCipherKey->Key; +// ULONG KeyLen = pCipherKey->KeyLen; + PUCHAR pTxMic = pCipherKey->TxMic; + PUCHAR pRxMic = pCipherKey->RxMic; + PUCHAR pTxtsc = pCipherKey->TxTsc; + UCHAR CipherAlg = pCipherKey->CipherAlg; + SHAREDKEY_MODE_STRUC csr1; + +// ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY); + + DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n")); + // + // 1.) decide key table offset + // + if (bUsePairewiseKeyTable) + offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); + else + offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE; + + // + // 2.) Set Key to Asic + // + //for (i = 0; i < KeyLen; i++) + +#ifdef RT2870 + RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY); + offset += MAX_LEN_OF_PEER_KEY; + + // + // 3.) Set MIC key if available + // + if (pTxMic) + { + RTUSBMultiWrite(pAd, offset, pTxMic, 8); + } + offset += LEN_TKIP_TXMICK; + + if (pRxMic) + { + RTUSBMultiWrite(pAd, offset, pRxMic, 8); + } +#endif // RT2870 // + + // + // 4.) Modify IV/EIV if needs + // This will force Asic to use this key ID by setting IV. + // + if (bTxKey) + { + +#ifdef RT2870 + UINT32 tmpVal; + + // + // Write IV + // + IV4 = (KeyIdx << 6); + if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES)) + IV4 |= 0x20; // turn on extension bit means EIV existence + + tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24); + RTMP_IO_WRITE32(pAd, offset, tmpVal); + + // + // Write EIV + // + offset += 4; + RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]); +#endif // RT2870 // + AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable); + } + + if (!bUsePairewiseKeyTable) + { + // + // Only update the shared key security mode + // + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word); + if ((BssIndex % 2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = CipherAlg; + else + csr1.field.Bss0Key3CipherAlg = CipherAlg; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = CipherAlg; + else + csr1.field.Bss1Key3CipherAlg = CipherAlg; + } + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n")); +} + + +/* + ======================================================================== + Description: + Add Pair-wise key material into ASIC. + Update pairwise key, TxMic and RxMic to Asic Pair-wise key table + + Return: + ======================================================================== +*/ +VOID AsicAddPairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR WCID, + IN CIPHER_KEY *pCipherKey) +{ + INT i; + ULONG offset; + PUCHAR pKey = pCipherKey->Key; + PUCHAR pTxMic = pCipherKey->TxMic; + PUCHAR pRxMic = pCipherKey->RxMic; +#ifdef DBG + UCHAR CipherAlg = pCipherKey->CipherAlg; +#endif // DBG // + + // EKEY + offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE); +#ifdef RT2870 + RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY); +#endif // RT2870 // + for (i=0; iTxMic[0], 8); +#endif // RT2870 // + } + offset += 8; + if (pRxMic) + { +#ifdef RT2870 + RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8); +#endif // RT2870 // + } + + DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); + if (pRxMic) + { + DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); + } + if (pTxMic) + { + DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); + } +} +/* + ======================================================================== + Description: + Remove Pair-wise key material from ASIC. + + Return: + ======================================================================== +*/ +VOID AsicRemovePairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR Wcid) +{ + ULONG WCIDAttri; + USHORT offset; + + // re-set the entry's WCID attribute as OPEN-NONE. + offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE); + WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE; + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); +} + +BOOLEAN AsicSendCommandToMcu( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1) +{ + HOST_CMD_CSR_STRUC H2MCmd; + H2M_MAILBOX_STRUC H2MMailbox; + ULONG i = 0; + do + { + RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word); + if (H2MMailbox.field.Owner == 0) + break; + + RTMPusecDelay(2); + } while(i++ < 100); + + if (i >= 100) + { + { + DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n")); + } + return FALSE; + } + + + H2MMailbox.field.Owner = 1; // pass ownership to MCU + H2MMailbox.field.CmdToken = Token; + H2MMailbox.field.HighByte = Arg1; + H2MMailbox.field.LowByte = Arg0; + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word); + + H2MCmd.word = 0; + H2MCmd.field.HostCommand = Command; + RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word); + + if (Command != 0x80) + { + } + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID RTMPCheckRates( + IN PRTMP_ADAPTER pAd, + IN OUT UCHAR SupRate[], + IN OUT UCHAR *SupRateLen) +{ + UCHAR RateIdx, i, j; + UCHAR NewRate[12], NewRateLen; + + NewRateLen = 0; + + if (pAd->CommonCfg.PhyMode == PHY_11B) + RateIdx = 4; + else + RateIdx = 12; + + // Check for support rates exclude basic rate bit + for (i = 0; i < *SupRateLen; i++) + for (j = 0; j < RateIdx; j++) + if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + NewRate[NewRateLen++] = SupRate[i]; + + *SupRateLen = NewRateLen; + NdisMoveMemory(SupRate, NewRate, NewRateLen); +} + +#ifdef CONFIG_STA_SUPPORT +#ifdef DOT11_N_SUPPORT +BOOLEAN RTMPCheckChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR CentralChannel, + IN UCHAR Channel) +{ + UCHAR k; + UCHAR UpperChannel = 0, LowerChannel = 0; + UCHAR NoEffectChannelinList = 0; + + // Find upper and lower channel according to 40MHz current operation. + if (CentralChannel < Channel) + { + UpperChannel = Channel; + if (CentralChannel > 2) + LowerChannel = CentralChannel - 2; + else + return FALSE; + } + else if (CentralChannel > Channel) + { + UpperChannel = CentralChannel + 2; + LowerChannel = Channel; + } + + for (k = 0;k < pAd->ChannelListNum;k++) + { + if (pAd->ChannelList[k].Channel == UpperChannel) + { + NoEffectChannelinList ++; + } + if (pAd->ChannelList[k].Channel == LowerChannel) + { + NoEffectChannelinList ++; + } + } + + DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList)); + if (NoEffectChannelinList == 2) + return TRUE; + else + return FALSE; +} + +/* + ======================================================================== + + Routine Description: + Verify the support rate for HT phy type + + Arguments: + pAd Pointer to our adapter + + Return Value: + FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +BOOLEAN RTMPCheckHt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo) +{ + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + // If use AMSDU, set flag. + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED); + // Save Peer Capability + if (pHtCapability->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCapability->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCapability->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCapability->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) + { + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE); + } + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + { + pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity; + } + + // Will check ChannelWidth for MCSSet[4] below + pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1; + switch (pAd->CommonCfg.RxStream) + { + case 1: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 2: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + case 3: + pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff; + pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00; + break; + } + + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n", + pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth, + pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode)); + + pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF; + + // Send Assoc Req with my HT capability. + pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize; + pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs; + pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20); + pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); + pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); + pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); + pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; + pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity; + pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + if (pAd->CommonCfg.bRdg) + { + pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; + pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1; + } + + if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20) + pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32 + + COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); + return TRUE; +} +#endif // DOT11_N_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID RTMPUpdateMlmeRate( + IN PRTMP_ADAPTER pAd) +{ + UCHAR MinimumRate; + UCHAR ProperMlmeRate; //= RATE_54; + UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 + BOOLEAN bMatch = FALSE; + + switch (pAd->CommonCfg.PhyMode) + { + case PHY_11B: + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + break; + case PHY_11BG_MIXED: +#ifdef DOT11_N_SUPPORT + case PHY_11ABGN_MIXED: + case PHY_11BGN_MIXED: +#endif // DOT11_N_SUPPORT // + if ((pAd->MlmeAux.SupRateLen == 4) && + (pAd->MlmeAux.ExtRateLen == 0)) + // B only AP + ProperMlmeRate = RATE_11; + else + ProperMlmeRate = RATE_24; + + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + case PHY_11A: +#ifdef DOT11_N_SUPPORT + case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n + case PHY_11GN_MIXED: + case PHY_11AGN_MIXED: + case PHY_11AN_MIXED: + case PHY_11N_5G: +#endif // DOT11_N_SUPPORT // + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + break; + case PHY_11ABG_MIXED: + ProperMlmeRate = RATE_24; + if (pAd->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + default: // error + ProperMlmeRate = RATE_1; + MinimumRate = RATE_1; + break; + } + + for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + + if (bMatch == FALSE) + { + for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + } + + if (bMatch == FALSE) + { + ProperMlmeRate = MinimumRate; + } + + pAd->CommonCfg.MlmeRate = MinimumRate; + pAd->CommonCfg.RtsRate = ProperMlmeRate; + if (pAd->CommonCfg.MlmeRate >= RATE_6) + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + else + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate; + } + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word)); +} + +CHAR RTMPMaxRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2) +{ + CHAR larger = -127; + + if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) + { + larger = Rssi0; + } + + if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) + { + larger = max(Rssi0, Rssi1); + } + + if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) + { + larger = max(larger, Rssi2); + } + + if (larger == -127) + larger = 0; + + return larger; +} + + +// Antenna divesity use GPIO3 and EESK pin for control +// Antenna and EEPROM access are both using EESK pin, +// Therefor we should avoid accessing EESK at the same time +// Then restore antenna after EEPROM access +VOID AsicSetRxAnt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ant) +{ +#ifdef RT30xx + UINT32 Value; + UINT32 x; + + if ((pAd->EepromAccess) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + return; + } + + // the antenna selection is through firmware and MAC register(GPIO3) + if (Ant == 0) + { + // Main antenna + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x |= (EESK); + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value); + Value &= ~(0x0808); + RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n")); + } + else + { + // Aux antenna + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EESK); + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value); + Value &= ~(0x0808); + Value |= 0x08; + RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n")); + } +#endif // RT30xx // +} + + +/* + ======================================================================== + Routine Description: + Periodic evaluate antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID AsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BBPR3 = 0; + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) || + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) +#ifdef RT30xx + || (pAd->EepromAccess) +#endif // RT30xx // + ) + return; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + //if (pAd->StaCfg.Psm == PWR_SAVE) + // return; + } +#endif // CONFIG_STA_SUPPORT // + + // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove + // one is antenna diversity:there is only one antenna can rx and tx + // the other is failed antenna remove:two physical antenna can rx and tx + if (pAd->NicConfig2.field.AntDiversity) + { + DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n", + pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt)); + + AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt); + + pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt + pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE; + pAd->RxAnt.RcvPktNumWhenEvaluate = 0; + + // a one-shot timer to end the evalution + // dynamic adjust antenna evaluation period according to the traffic + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100); + else + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); + } + else + { + +#ifdef CONFIG_STA_SUPPORT + if (pAd->StaCfg.Psm == PWR_SAVE) + return; +#endif // CONFIG_STA_SUPPORT // + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + { + ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + // dynamic adjust antenna evaluation period according to the traffic + if (TxTotalCnt > 50) + { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20); + pAd->Mlme.bLowThroughput = FALSE; + } + else + { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); + pAd->Mlme.bLowThroughput = TRUE; + } + } + } +} + +/* + ======================================================================== + Routine Description: + After evaluation, check antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID AsicRxAntEvalTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; +#ifdef CONFIG_STA_SUPPORT + UCHAR BBPR3 = 0; + CHAR larger = -127, rssi0, rssi1, rssi2; +#endif // CONFIG_STA_SUPPORT // + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_NIC_NOT_EXIST) || + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) +#ifdef RT30xx + || (pAd->EepromAccess) +#endif // RT30xx // + ) + return; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + //if (pAd->StaCfg.Psm == PWR_SAVE) + // return; + + if (pAd->NicConfig2.field.AntDiversity) + { + if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt])) + { + UCHAR temp; + + // + // select PrimaryRxAntPair + // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair. + // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt + // + temp = pAd->RxAnt.Pair1PrimaryRxAnt; + pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt; + pAd->RxAnt.Pair1SecondaryRxAnt = temp; + + pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3); + pAd->RxAnt.EvaluateStableCnt = 0; + } + else + { + // if the evaluated antenna is not better than original, switch back to original antenna + AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); + pAd->RxAnt.EvaluateStableCnt ++; + } + + pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt + + DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n", + pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate)); + } + else + { + if (pAd->StaCfg.Psm == PWR_SAVE) + return; + + // if the traffic is low, use average rssi as the criteria + if (pAd->Mlme.bLowThroughput == TRUE) + { + rssi0 = pAd->StaCfg.RssiSample.LastRssi0; + rssi1 = pAd->StaCfg.RssiSample.LastRssi1; + rssi2 = pAd->StaCfg.RssiSample.LastRssi2; + } + else + { + rssi0 = pAd->StaCfg.RssiSample.AvgRssi0; + rssi1 = pAd->StaCfg.RssiSample.AvgRssi1; + rssi2 = pAd->StaCfg.RssiSample.AvgRssi2; + } + + if(pAd->Antenna.field.RxPath == 3) + { + larger = max(rssi0, rssi1); + + if (larger > (rssi2 + 20)) + pAd->Mlme.RealRxPath = 2; + else + pAd->Mlme.RealRxPath = 3; + } + else if(pAd->Antenna.field.RxPath == 2) + { + if (rssi0 > (rssi1 + 20)) + pAd->Mlme.RealRxPath = 1; + else + pAd->Mlme.RealRxPath = 2; + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Mlme.RealRxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Mlme.RealRxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Mlme.RealRxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + } + } + +#endif // CONFIG_STA_SUPPORT // + +} + + + +VOID APSDPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + return; + + pAd->CommonCfg.TriggerTimerCount++; + +// Driver should not send trigger frame, it should be send by application layer +/* + if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable + && (pAd->CommonCfg.bNeedSendTriggerFrame || + (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO)))) + { + DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n")); + RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); + pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; + pAd->CommonCfg.TriggerTimerCount = 0; + pAd->CommonCfg.bInServicePeriod = TRUE; + }*/ +} + +/* + ======================================================================== + Routine Description: + Set/reset MAC registers according to bPiggyBack parameter + + Arguments: + pAd - Adapter pointer + bPiggyBack - Enable / Disable Piggy-Back + + Return Value: + None + + ======================================================================== +*/ +VOID RTMPSetPiggyBack( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bPiggyBack) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + + TxLinkCfg.field.TxCFAckEn = bPiggyBack; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); +} + +/* + ======================================================================== + Routine Description: + check if this entry need to switch rate automatically + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + BOOLEAN result = TRUE; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // only associated STA counts + if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC)) + { + result = pAd->StaCfg.bAutoTxRateSwitch; + } + else + result = FALSE; + } +#endif // CONFIG_STA_SUPPORT // + + + + return result; +} + + +BOOLEAN RTMPAutoRateSwitchCheck( + IN PRTMP_ADAPTER pAd) +{ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.bAutoTxRateSwitch) + return TRUE; + } +#endif // CONFIG_STA_SUPPORT // + return FALSE; +} + + +/* + ======================================================================== + Routine Description: + check if this entry need to fix tx legacy rate + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +UCHAR RTMPStaFixedTxMode( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + UCHAR tx_mode = FIXED_TXMODE_HT; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode; + } +#endif // CONFIG_STA_SUPPORT // + + return tx_mode; +} + +/* + ======================================================================== + Routine Description: + Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified. + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +VOID RTMPUpdateLegacyTxSetting( + UCHAR fixed_tx_mode, + PMAC_TABLE_ENTRY pEntry) +{ + HTTRANSMIT_SETTING TransmitSetting; + + if (fixed_tx_mode == FIXED_TXMODE_HT) + return; + + TransmitSetting.word = 0; + + TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE; + TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS; + + if (fixed_tx_mode == FIXED_TXMODE_CCK) + { + TransmitSetting.field.MODE = MODE_CCK; + // CCK mode allow MCS 0~3 + if (TransmitSetting.field.MCS > MCS_3) + TransmitSetting.field.MCS = MCS_3; + } + else + { + TransmitSetting.field.MODE = MODE_OFDM; + // OFDM mode allow MCS 0~7 + if (TransmitSetting.field.MCS > MCS_7) + TransmitSetting.field.MCS = MCS_7; + } + + if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) + { + pEntry->HTPhyMode.word = TransmitSetting.word; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n", + pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS)); + } +} + +#ifdef CONFIG_STA_SUPPORT +/* + ========================================================================== + Description: + dynamic tune BBP R66 to find a balance between sensibility and + noise isolation + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicStaBbpTuning( + IN PRTMP_ADAPTER pAd) +{ + UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30; + CHAR Rssi; + + // 2860C did not support Fase CCA, therefore can't tune + if (pAd->MACVersion == 0x28600100) + return; + + // + // work as a STA + // + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING + return; + + if ((pAd->OpMode == OPMODE_STA) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + ) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value); + R66 = OrigR66Value; + + if (pAd->Antenna.field.RxPath > 1) + Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; + else + Rssi = pAd->StaCfg.RssiSample.AvgRssi0; + + if (pAd->LatchRfRegs.Channel <= 14) + { //BG band +#ifdef RT30xx + // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control + // Otherwise, it will have some throughput side effect when low RSSI + if (IS_RT30xx(pAd)) + { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + { + R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + else + { + R66 = 0x1C + 2*GET_LNA_GAIN(pAd); + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + } + else +#endif // RT30xx // + { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + { + R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + else + { + R66 = 0x2E + GET_LNA_GAIN(pAd); + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + } + + } + else + { //A band + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + { + R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + else + { + R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + } + else + { + if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) + { + R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + else + { + R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3; + if (OrigR66Value != R66) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + } + } + + + } +} +#endif // CONFIG_STA_SUPPORT // + +VOID RTMPSetAGCInitValue( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth) +{ + UCHAR R66 = 0x30; + + if (pAd->LatchRfRegs.Channel <= 14) + { // BG band + R66 = 0x2E + GET_LNA_GAIN(pAd); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { //A band + if (BandWidth == BW_20) + { + R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } +#ifdef DOT11_N_SUPPORT + else + { + R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } +#endif // DOT11_N_SUPPORT // + } + +} + +VOID AsicTurnOffRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + // RF R2 bit 18 = 0 + UINT32 R1 = 0, R2 = 0, R3 = 0; + UCHAR index; + RTMP_RF_REGS *RFRegTable; + +#ifdef RT30xx + // The RF programming sequence is difference between 3xxx and 2xxx + if (IS_RT3090(pAd)) + { + RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup + } + else + { +#endif // RT30xx // + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R1 = RFRegTable[index].R1 & 0xffffdfff; + R2 = RFRegTable[index].R2 & 0xfffbffff; + R3 = RFRegTable[index].R3 & 0xfff3ffff; + + RTMP_RF_IO_WRITE32(pAd, R1); + RTMP_RF_IO_WRITE32(pAd, R2); + + // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. + // Set RF R2 bit18=0, R3 bit[18:19]=0 + //if (pAd->StaCfg.bRadio == FALSE) + if (1) + { + RTMP_RF_IO_WRITE32(pAd, R3); + + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", + Channel, pAd->RfIcType, R2, R3)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", + Channel, pAd->RfIcType, R2)); + break; + } + } + break; + + default: + break; + } +#ifdef RT30xx + } +#endif // RT30xx // + +} + + +VOID AsicTurnOnRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ + // RF R2 bit 18 = 0 + UINT32 R1 = 0, R2 = 0, R3 = 0; + UCHAR index; + RTMP_RF_REGS *RFRegTable; + +#ifdef RT30xx + // The RF programming sequence is difference between 3xxx and 2xxx + if (IS_RT3090(pAd)) + { + } + else + { +#endif // RT30xx // + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R3 = pAd->LatchRfRegs.R3; + R3 &= 0xfff3ffff; + R3 |= 0x00080000; + RTMP_RF_IO_WRITE32(pAd, R3); + + R1 = RFRegTable[index].R1; + RTMP_RF_IO_WRITE32(pAd, R1); + + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; + } + + if (pAd->Antenna.field.RxPath == 2) + { + R2 |= 0x40; // write 1 to off Rxpath. + } + else if (pAd->Antenna.field.RxPath == 1) + { + R2 |= 0x20040; // write 1 to off RxPath + } + RTMP_RF_IO_WRITE32(pAd, R2); + + break; + } + } + break; + + default: + break; + } + +#ifdef RT30xx + } +#endif // RT30xx // + +} + diff --git a/drivers/staging/rt3070/common/netif_block.c b/drivers/staging/rt3070/common/netif_block.c new file mode 100644 index 000000000000..4773c11bedd0 --- /dev/null +++ b/drivers/staging/rt3070/common/netif_block.c @@ -0,0 +1,136 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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 "../rt_config.h" +#include "netif_block.h" + +static NETIF_ENTRY freeNetIfEntryPool[FREE_NETIF_POOL_SIZE]; +static LIST_HEADER freeNetIfEntryList; + +void initblockQueueTab( + IN PRTMP_ADAPTER pAd) +{ + int i; + + initList(&freeNetIfEntryList); + for (i = 0; i < FREE_NETIF_POOL_SIZE; i++) + insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)&freeNetIfEntryPool[i]); + + for (i=0; i < NUM_OF_TX_RING; i++) + initList(&pAd->blockQueueTab[i].NetIfList); + + return; +} + +BOOLEAN blockNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry, + IN PNET_DEV pNetDev) +{ + PNETIF_ENTRY pNetIfEntry = NULL; + + if ((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(&freeNetIfEntryList)) != NULL) + { + netif_stop_queue(pNetDev); + pNetIfEntry->pNetDev = pNetDev; + insertTailList(&pBlockQueueEntry->NetIfList, (PLIST_ENTRY)pNetIfEntry); + + pBlockQueueEntry->SwTxQueueBlockFlag = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("netif_stop_queue(%s)\n", pNetDev->name)); + } + else + return FALSE; + + return TRUE; +} + +VOID releaseNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry) +{ + PNETIF_ENTRY pNetIfEntry = NULL; + PLIST_HEADER pNetIfList = &pBlockQueueEntry->NetIfList; + + while((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(pNetIfList)) != NULL) + { + PNET_DEV pNetDev = pNetIfEntry->pNetDev; + netif_wake_queue(pNetDev); + insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)pNetIfEntry); + + DBGPRINT(RT_DEBUG_TRACE, ("netif_wake_queue(%s)\n", pNetDev->name)); + } + pBlockQueueEntry->SwTxQueueBlockFlag = FALSE; + return; +} + + +VOID StopNetIfQueue( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket) +{ + PNET_DEV NetDev = NULL; + UCHAR IfIdx = 0; + BOOLEAN valid = FALSE; + +#ifdef WDS_SUPPORT + if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_WDS) + { + IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS) % MAX_WDS_ENTRY; + NetDev = pAd->WdsTab.WdsEntry[IfIdx].dev; + } + else +#endif // WDS_SUPPORT // + { +#ifdef MBSS_SUPPORT + if (pAd->OpMode == OPMODE_AP) + { + IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_MBSSID) % MAX_MBSSID_NUM; + NetDev = pAd->ApCfg.MBSSID[IfIdx].MSSIDDev; + } + else + { + IfIdx = MAIN_MBSSID; + NetDev = pAd->net_dev; + } +#else + IfIdx = MAIN_MBSSID; + NetDev = pAd->net_dev; +#endif + } + + // WMM support 4 software queues. + // One software queue full doesn't mean device have no capbility to transmit packet. + // So disable block Net-If queue function while WMM enable. +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + valid = (pAd->CommonCfg.bWmmCapable == TRUE) ? FALSE : TRUE; +#endif // CONFIG_STA_SUPPORT // + + if (valid) + blockNetIf(&pAd->blockQueueTab[QueIdx], NetDev); + return; +} + diff --git a/drivers/staging/rt3070/common/rtmp_init.c b/drivers/staging/rt3070/common/rtmp_init.c new file mode 100644 index 000000000000..4503f6c6d954 --- /dev/null +++ b/drivers/staging/rt3070/common/rtmp_init.c @@ -0,0 +1,4197 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtmp_init.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 2002-08-01 created + John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme + Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT. +*/ +#include "../rt_config.h" +#include "../firmware.h" + +//#define BIN_IN_FILE /* use *.bin firmware */ + +UCHAR BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; +ULONG BIT32[] = {0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, + 0x00001000, 0x00002000, 0x00004000, 0x00008000, + 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000}; + +char* CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128"}; + +const unsigned short ccitt_16Table[] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; +#define ByteCRC16(v, crc) \ + (unsigned short)((crc << 8) ^ ccitt_16Table[((crc >> 8) ^ (v)) & 255]) + +unsigned char BitReverse(unsigned char x) +{ + int i; + unsigned char Temp=0; + for(i=0; ; i++) + { + if(x & 0x80) Temp |= 0x80; + if(i==7) break; + x <<= 1; + Temp >>= 1; + } + return Temp; +} + +// +// BBP register initialization set +// +REG_PAIR BBPRegTable[] = { + {BBP_R65, 0x2C}, // fix rssi issue + {BBP_R66, 0x38}, // Also set this default value to pAd->BbpTuning.R66CurrentValue at initial + {BBP_R69, 0x12}, + {BBP_R70, 0xa}, // BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa + {BBP_R73, 0x10}, + {BBP_R81, 0x37}, + {BBP_R82, 0x62}, + {BBP_R83, 0x6A}, + {BBP_R84, 0x99}, // 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before + {BBP_R86, 0x00}, // middle range issue, Rory @2008-01-28 + {BBP_R91, 0x04}, // middle range issue, Rory @2008-01-28 + {BBP_R92, 0x00}, // middle range issue, Rory @2008-01-28 + {BBP_R103, 0x00}, // near range high-power issue, requested from Gary @2008-0528 + {BBP_R105, 0x05}, // 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before. +}; +#define NUM_BBP_REG_PARMS (sizeof(BBPRegTable) / sizeof(REG_PAIR)) + +// +// RF register initialization set +// +#ifdef RT30xx +REG_PAIR RT30xx_RFRegTable[] = { + {RF_R04, 0x40}, + {RF_R05, 0x03}, + {RF_R06, 0x02}, + {RF_R07, 0x70}, + {RF_R09, 0x0F}, + {RF_R10, 0x41}, + {RF_R11, 0x21}, + {RF_R12, 0x7B}, + {RF_R14, 0x90}, + {RF_R15, 0x58}, + {RF_R16, 0xB3}, + {RF_R17, 0x92}, + {RF_R18, 0x2C}, + {RF_R19, 0x02}, + {RF_R20, 0xBA}, + {RF_R21, 0xDB}, + {RF_R24, 0x16}, + {RF_R25, 0x01}, + {RF_R29, 0x1F}, +}; +#define NUM_RF_REG_PARMS (sizeof(RT30xx_RFRegTable) / sizeof(REG_PAIR)) +#endif // RT30xx // + +// +// ASIC register initialization sets +// + +RTMP_REG_PAIR MACRegTable[] = { +#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200) + {BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */ + {BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */ +#elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100) + {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ + {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ +#else + #error You must re-calculate new value for BCN_OFFSET0 & BCN_OFFSET1 in MACRegTable[]!!! +#endif // HW_BEACON_OFFSET // + + {LEGACY_BASIC_RATE, 0x0000013f}, // Basic rate set bitmap + {HT_BASIC_RATE, 0x00008003}, // Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI. + {MAC_SYS_CTRL, 0x00}, // 0x1004, , default Disable RX + {RX_FILTR_CFG, 0x17f97}, //0x1400 , RX filter control, + {BKOFF_SLOT_CFG, 0x209}, // default set short slot time, CC_DELAY_TIME should be 2 + //{TX_SW_CFG0, 0x40a06}, // Gary,2006-08-23 + {TX_SW_CFG0, 0x0}, // Gary,2008-05-21 for CWC test + {TX_SW_CFG1, 0x80606}, // Gary,2006-08-23 + {TX_LINK_CFG, 0x1020}, // Gary,2006-08-23 + {TX_TIMEOUT_CFG, 0x000a2090}, + {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, // 0x3018, MAX frame length. Max PSDU = 16kbytes. + {LED_CFG, 0x7f031e46}, // Gary, 2006-08-23 + +//#ifdef CONFIG_STA_SUPPORT +// {WMM_AIFSN_CFG, 0x00002273}, +// {WMM_CWMIN_CFG, 0x00002344}, +// {WMM_CWMAX_CFG, 0x000034aa}, +//#endif // CONFIG_STA_SUPPORT // +#ifdef INF_AMAZON_SE + {PBF_MAX_PCNT, 0x1F3F6F6F}, //iverson modify for usb issue, 2008/09/19 + // 6F + 6F < total page count FE + // so that RX doesn't occupy TX's buffer space when WMM congestion. +#else + {PBF_MAX_PCNT, 0x1F3FBF9F}, //0x1F3f7f9f}, //Jan, 2006/04/20 +#endif // INF_AMAZON_SE // + //{TX_RTY_CFG, 0x6bb80408}, // Jan, 2006/11/16 + {TX_RTY_CFG, 0x47d01f0f}, // Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03 + {AUTO_RSP_CFG, 0x00000013}, // Initial Auto_Responder, because QA will turn off Auto-Responder + {CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. + {OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. +//PS packets use Tx1Q (for HCCA) when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) +#ifdef RT2870 +#ifdef CONFIG_STA_SUPPORT + {PBF_CFG, 0xf40006}, // Only enable Queue 2 +#endif // CONFIG_STA_SUPPORT // + {MM40_PROT_CFG, 0x3F44084}, // Initial Auto_Responder, because QA will turn off Auto-Responder + {WPDMA_GLO_CFG, 0x00000030}, +#endif // RT2870 // + {GF20_PROT_CFG, 0x01744004}, // set 19:18 --> Short NAV for MIMO PS + {GF40_PROT_CFG, 0x03F44084}, + {MM20_PROT_CFG, 0x01744004}, + {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, //Extension channel backoff. + {TX_RTS_CFG, 0x00092b20}, +//#ifdef WIFI_TEST + {EXP_ACK_TIME, 0x002400ca}, // default value +//#else +// {EXP_ACK_TIME, 0x005400ca}, // suggested by Gray @ 20070323 for 11n intel-sta throughput +//#endif // end - WIFI_TEST // + {TXOP_HLDR_ET, 0x00000002}, + + /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us + is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0 + and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping + will always lost. So we change the SIFS of CCK from 10us to 16us. */ + {XIFS_TIME_CFG, 0x33a41010}, + {PWR_PIN_CFG, 0x00000003}, // patch for 2880-E +}; + + +#ifdef CONFIG_STA_SUPPORT +RTMP_REG_PAIR STAMACRegTable[] = { + {WMM_AIFSN_CFG, 0x00002273}, + {WMM_CWMIN_CFG, 0x00002344}, + {WMM_CWMAX_CFG, 0x000034aa}, +}; +#endif // CONFIG_STA_SUPPORT // + +#define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR)) +#ifdef CONFIG_STA_SUPPORT +#define NUM_STA_MAC_REG_PARMS (sizeof(STAMACRegTable) / sizeof(RTMP_REG_PAIR)) +#endif // CONFIG_STA_SUPPORT // + +#ifdef RT2870 +// +// RT2870 Firmware Spec only used 1 oct for version expression +// +#define FIRMWARE_MINOR_VERSION 7 + +#endif // RT2870 // + +// New 8k byte firmware size for RT3071/RT3072 +#define FIRMWAREIMAGE_MAX_LENGTH 0x2000 +#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(UCHAR)) +#define FIRMWARE_MAJOR_VERSION 0 + +#define FIRMWAREIMAGEV1_LENGTH 0x1000 +#define FIRMWAREIMAGEV2_LENGTH 0x1000 + + + +/* + ======================================================================== + + Routine Description: + Allocate RTMP_ADAPTER data block and do some initialization + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPAllocAdapterBlock( + IN PVOID handle, + OUT PRTMP_ADAPTER *ppAdapter) +{ + PRTMP_ADAPTER pAd; + NDIS_STATUS Status; + INT index; + UCHAR *pBeaconBuf = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n")); + + *ppAdapter = NULL; + + do + { + // Allocate RTMP_ADAPTER memory block + pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG); + if (pBeaconBuf == NULL) + { + Status = NDIS_STATUS_FAILURE; + DBGPRINT_ERR(("Failed to allocate memory - BeaconBuf!\n")); + break; + } + + Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n")); + break; + } + pAd->BeaconBuf = pBeaconBuf; + printk("\n\n=== pAd = %p, size = %d ===\n\n", pAd, (UINT32)sizeof(RTMP_ADAPTER)); + + + // Init spin locks + NdisAllocateSpinLock(&pAd->MgmtRingLock); + + for (index =0 ; index < NUM_OF_TX_RING; index++) + { + NdisAllocateSpinLock(&pAd->TxSwQueueLock[index]); + NdisAllocateSpinLock(&pAd->DeQueueLock[index]); + pAd->DeQueueRunning[index] = FALSE; + } + + NdisAllocateSpinLock(&pAd->irq_lock); + + } while (FALSE); + + if ((Status != NDIS_STATUS_SUCCESS) && (pBeaconBuf)) + kfree(pBeaconBuf); + + *ppAdapter = pAd; + + DBGPRINT_S(Status, ("<-- RTMPAllocAdapterBlock, Status=%x\n", Status)); + return Status; +} + +/* + ======================================================================== + + Routine Description: + Read initial Tx power per MCS and BW from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReadTxPwrPerRate( + IN PRTMP_ADAPTER pAd) +{ + ULONG data, Adata, Gdata; + USHORT i, value, value2; + INT Apwrdelta, Gpwrdelta; + UCHAR t1,t2,t3,t4; + BOOLEAN bValid, bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE; + + // + // Get power delta for 20MHz and 40MHz. + // + DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2); + Apwrdelta = 0; + Gpwrdelta = 0; + + if ((value2 & 0xff) != 0xff) + { + if ((value2 & 0x80)) + Gpwrdelta = (value2&0xf); + + if ((value2 & 0x40)) + bGpwrdeltaMinus = FALSE; + else + bGpwrdeltaMinus = TRUE; + } + if ((value2 & 0xff00) != 0xff00) + { + if ((value2 & 0x8000)) + Apwrdelta = ((value2&0xf00)>>8); + + if ((value2 & 0x4000)) + bApwrdeltaMinus = FALSE; + else + bApwrdeltaMinus = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta)); + + // + // Get Txpower per MCS for 20MHz in 2.4G. + // + for (i=0; i<5; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value); + data = value; + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + if (bGpwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Gpwrdelta) + t1 = (value&0xf)-(Gpwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Gpwrdelta) + t2 = ((value&0xf0)>>4)-(Gpwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Gpwrdelta) + t3 = ((value&0xf00)>>8)-(Gpwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Gpwrdelta) + t4 = ((value&0xf000)>>12)-(Gpwrdelta); + else + t4 = 0; + } + Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + if (bGpwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Gpwrdelta) + t1 = (value&0xf)-(Gpwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Gpwrdelta) + t2 = ((value&0xf0)>>4)-(Gpwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Gpwrdelta) + t3 = ((value&0xf00)>>8)-(Gpwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Gpwrdelta) + t4 = ((value&0xf000)>>12)-(Gpwrdelta); + else + t4 = 0; + } + Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + data |= (value<<16); + + pAd->Tx20MPwrCfgABand[i] = pAd->Tx40MPwrCfgABand[i] = Adata; + pAd->Tx20MPwrCfgGBand[i] = pAd->Tx40MPwrCfgGBand[i] = Gdata; + + if (data != 0xffffffff) + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", data, Adata, Gdata)); + } + + // + // Check this block is valid for 40MHz in 2.4G. If invalid, use parameter for 20MHz in 2.4G + // + bValid = TRUE; + for (i=0; i<6; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 2 + i*2, value); + if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00)) + { + bValid = FALSE; + break; + } + } + + // + // Get Txpower per MCS for 40MHz in 2.4G. + // + if (bValid) + { + for (i=0; i<4; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4, value); + if (bGpwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Gpwrdelta) + t1 = (value&0xf)-(Gpwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Gpwrdelta) + t2 = ((value&0xf0)>>4)-(Gpwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Gpwrdelta) + t3 = ((value&0xf00)>>8)-(Gpwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Gpwrdelta) + t4 = ((value&0xf000)>>12)-(Gpwrdelta); + else + t4 = 0; + } + Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4 + 2, value); + if (bGpwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Gpwrdelta) + t1 = (value&0xf)-(Gpwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Gpwrdelta) + t2 = ((value&0xf0)>>4)-(Gpwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Gpwrdelta) + t3 = ((value&0xf00)>>8)-(Gpwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Gpwrdelta) + t4 = ((value&0xf000)>>12)-(Gpwrdelta); + else + t4 = 0; + } + Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + + if (i == 0) + pAd->Tx40MPwrCfgGBand[i+1] = (pAd->Tx40MPwrCfgGBand[i+1] & 0x0000FFFF) | (Gdata & 0xFFFF0000); + else + pAd->Tx40MPwrCfgGBand[i+1] = Gdata; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 2.4G band, Gdata = %lx \n", Gdata)); + } + } + + // + // Check this block is valid for 20MHz in 5G. If invalid, use parameter for 20MHz in 2.4G + // + bValid = TRUE; + for (i=0; i<8; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 2 + i*2, value); + if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00)) + { + bValid = FALSE; + break; + } + } + + // + // Get Txpower per MCS for 20MHz in 5G. + // + if (bValid) + { + for (i=0; i<5; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4 + 2, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + + if (i == 0) + pAd->Tx20MPwrCfgABand[i] = (pAd->Tx20MPwrCfgABand[i] & 0x0000FFFF) | (Adata & 0xFFFF0000); + else + pAd->Tx20MPwrCfgABand[i] = Adata; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 5GHz band, Adata = %lx \n", Adata)); + } + } + + // + // Check this block is valid for 40MHz in 5G. If invalid, use parameter for 20MHz in 2.4G + // + bValid = TRUE; + for (i=0; i<6; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 2 + i*2, value); + if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00)) + { + bValid = FALSE; + break; + } + } + + // + // Get Txpower per MCS for 40MHz in 5G. + // + if (bValid) + { + for (i=0; i<4; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4 + 2, value); + if (bApwrdeltaMinus == FALSE) + { + t1 = (value&0xf)+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = ((value&0xf0)>>4)+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = ((value&0xf00)>>8)+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = ((value&0xf000)>>12)+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if ((value&0xf) > Apwrdelta) + t1 = (value&0xf)-(Apwrdelta); + else + t1 = 0; + if (((value&0xf0)>>4) > Apwrdelta) + t2 = ((value&0xf0)>>4)-(Apwrdelta); + else + t2 = 0; + if (((value&0xf00)>>8) > Apwrdelta) + t3 = ((value&0xf00)>>8)-(Apwrdelta); + else + t3 = 0; + if (((value&0xf000)>>12) > Apwrdelta) + t4 = ((value&0xf000)>>12)-(Apwrdelta); + else + t4 = 0; + } + Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + + if (i == 0) + pAd->Tx40MPwrCfgABand[i+1] = (pAd->Tx40MPwrCfgABand[i+1] & 0x0000FFFF) | (Adata & 0xFFFF0000); + else + pAd->Tx40MPwrCfgABand[i+1] = Adata; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 5GHz band, Adata = %lx \n", Adata)); + } + } +} + + +/* + ======================================================================== + + Routine Description: + Read initial channel power parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReadChannelPwr( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i, choffset; + EEPROM_TX_PWR_STRUC Power; + EEPROM_TX_PWR_STRUC Power2; + + // Read Tx power value for all channels + // Value from 1 - 0x7f. Default value is 24. + // Power value : 2.4G 0x00 (0) ~ 0x1F (31) + // : 5.5G 0xF9 (-7) ~ 0x0F (15) + + // 0. 11b/g, ch1 - ch 14 + for (i = 0; i < 7; i++) + { +// Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2); +// Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2); + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word); + pAd->TxPower[i * 2].Channel = i * 2 + 1; + pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; + + if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2].Power = Power.field.Byte0; + + if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1; + } + + // 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz) + // 1.1 Fill up channel + choffset = 14; + for (i = 0; i < 4; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + + // 1.2 Fill up power + for (i = 0; i < 6; i++) + { +// Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2); +// Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + // 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz) + // 2.1 Fill up channel + choffset = 14 + 12; + for (i = 0; i < 5; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 5 + choffset + 0].Channel = 140; + pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + // 2.2 Fill up power + for (i = 0; i < 8; i++) + { +// Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2); +// Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + // 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165 (including central frequency in BW 40MHz) + // 3.1 Fill up channel + choffset = 14 + 12 + 16; + for (i = 0; i < 2; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 2 + choffset + 0].Channel = 165; + pAd->TxPower[3 * 2 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 2 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + // 3.2 Fill up power + for (i = 0; i < 4; i++) + { +// Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2); +// Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + // 4. Print and Debug + choffset = 14 + 12 + 16 + 7; + +} + +/* + ======================================================================== + + Routine Description: + Read the following from the registry + 1. All the parameters + 2. NetworkAddres + + Arguments: + Adapter Pointer to our adapter + WrapperConfigurationContext For use by NdisOpenConfiguration + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICReadRegParameters( + IN PRTMP_ADAPTER pAd, + IN NDIS_HANDLE WrapperConfigurationContext + ) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status)); + return Status; +} + + +#ifdef RT30xx +/* + ======================================================================== + + Routine Description: + For RF filter calibration purpose + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID RTMPFilterCalibration( + IN PRTMP_ADAPTER pAd) +{ + UCHAR R55x = 0, value, FilterTarget = 0x1E, BBPValue=0; + UINT loop = 0, count = 0, loopcnt = 0, ReTry = 0; + UCHAR RF_R24_Value = 0; + + // Give bbp filter initial value + pAd->Mlme.CaliBW20RfR24 = 0x1F; + pAd->Mlme.CaliBW40RfR24 = 0x2F; //Bit[5] must be 1 for BW 40 + + do + { + if (loop == 1) //BandWidth = 40 MHz + { + // Write 0x27 to RF_R24 to program filter + RF_R24_Value = 0x27; + RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); + if (IS_RT3090(pAd)) + FilterTarget = 0x15; + else + FilterTarget = 0x19; + + // when calibrate BW40, BBP mask must set to BW40. + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + BBPValue|= (0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + // set to BW40 + RT30xxReadRFRegister(pAd, RF_R31, &value); + value |= 0x20; + RT30xxWriteRFRegister(pAd, RF_R31, value); + } + else //BandWidth = 20 MHz + { + // Write 0x07 to RF_R24 to program filter + RF_R24_Value = 0x07; + RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); + if (IS_RT3090(pAd)) + FilterTarget = 0x13; + else + FilterTarget = 0x16; + + // set to BW20 + RT30xxReadRFRegister(pAd, RF_R31, &value); + value &= (~0x20); + RT30xxWriteRFRegister(pAd, RF_R31, value); + } + + // Write 0x01 to RF_R22 to enable baseband loopback mode + RT30xxReadRFRegister(pAd, RF_R22, &value); + value |= 0x01; + RT30xxWriteRFRegister(pAd, RF_R22, value); + + // Write 0x00 to BBP_R24 to set power & frequency of passband test tone + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0); + + do + { + // Write 0x90 to BBP_R25 to transmit test tone + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90); + + RTMPusecDelay(1000); + // Read BBP_R55[6:0] for received power, set R55x = BBP_R55[6:0] + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value); + R55x = value & 0xFF; + + } while ((ReTry++ < 100) && (R55x == 0)); + + // Write 0x06 to BBP_R24 to set power & frequency of stopband test tone + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x06); + + while(TRUE) + { + // Write 0x90 to BBP_R25 to transmit test tone + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R25, 0x90); + + //We need to wait for calibration + RTMPusecDelay(1000); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R55, &value); + value &= 0xFF; + if ((R55x - value) < FilterTarget) + { + RF_R24_Value ++; + } + else if ((R55x - value) == FilterTarget) + { + RF_R24_Value ++; + count ++; + } + else + { + break; + } + + // prevent infinite loop cause driver hang. + if (loopcnt++ > 100) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPFilterCalibration - can't find a valid value, loopcnt=%d stop calibrating", loopcnt)); + break; + } + + // Write RF_R24 to program filter + RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); + } + + if (count > 0) + { + RF_R24_Value = RF_R24_Value - ((count) ? (1) : (0)); + } + + // Store for future usage + if (loopcnt < 100) + { + if (loop++ == 0) + { + //BandWidth = 20 MHz + pAd->Mlme.CaliBW20RfR24 = (UCHAR)RF_R24_Value; + } + else + { + //BandWidth = 40 MHz + pAd->Mlme.CaliBW40RfR24 = (UCHAR)RF_R24_Value; + break; + } + } + else + break; + + RT30xxWriteRFRegister(pAd, RF_R24, RF_R24_Value); + + // reset count + count = 0; + } while(TRUE); + + // + // Set back to initial state + // + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0); + + RT30xxReadRFRegister(pAd, RF_R22, &value); + value &= ~(0x01); + RT30xxWriteRFRegister(pAd, RF_R22, value); + + // set BBP back to BW20 + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue&= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPFilterCalibration - CaliBW20RfR24=0x%x, CaliBW40RfR24=0x%x\n", pAd->Mlme.CaliBW20RfR24, pAd->Mlme.CaliBW40RfR24)); +} +#endif // RT30xx // + + +#ifdef RT3070 +VOID NICInitRT30xxRFRegisters(IN PRTMP_ADAPTER pAd) +{ + INT i; + // Driver must read EEPROM to get RfIcType before initial RF registers + // Initialize RF register to default value + if (IS_RT3070(pAd) || IS_RT3071(pAd)) + { + // Init RF calibration + // Driver should toggle RF R30 bit7 before init RF registers + UINT32 RfReg = 0; + UINT32 data; + + RT30xxReadRFRegister(pAd, RF_R30, (PUCHAR)&RfReg); + RfReg |= 0x80; + RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); + RTMPusecDelay(1000); + RfReg &= 0x7F; + RT30xxWriteRFRegister(pAd, RF_R30, (UCHAR)RfReg); + + // Initialize RF register to default value + for (i = 0; i < NUM_RF_REG_PARMS; i++) + { + RT30xxWriteRFRegister(pAd, RT30xx_RFRegTable[i].Register, RT30xx_RFRegTable[i].Value); + } + + // add by johnli + if (IS_RT3070(pAd)) + { + // Update MAC 0x05D4 from 01xxxxxx to 0Dxxxxxx (voltage 1.2V to 1.35V) for RT3070 to improve yield rate + RTUSBReadMACRegister(pAd, LDO_CFG0, &data); + data = ((data & 0xF0FFFFFF) | 0x0D000000); + RTUSBWriteMACRegister(pAd, LDO_CFG0, data); + } + else if (IS_RT3071(pAd)) + { + // Driver should set RF R6 bit6 on before init RF registers + RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RfReg); + RfReg |= 0x40; + RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RfReg); + + // init R31 + RT30xxWriteRFRegister(pAd, RF_R31, 0x14); + + // RT3071 version E has fixed this issue + if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211)) + { + // patch tx EVM issue temporarily + RTUSBReadMACRegister(pAd, LDO_CFG0, &data); + data = ((data & 0xE0FFFFFF) | 0x0D000000); + RTUSBWriteMACRegister(pAd, LDO_CFG0, data); + } + else + { + RTMP_IO_READ32(pAd, LDO_CFG0, &data); + data = ((data & 0xE0FFFFFF) | 0x01000000); + RTMP_IO_WRITE32(pAd, LDO_CFG0, data); + } + + // patch LNA_PE_G1 failed issue + RTUSBReadMACRegister(pAd, GPIO_SWITCH, &data); + data &= ~(0x20); + RTUSBWriteMACRegister(pAd, GPIO_SWITCH, data); + } + + //For RF filter Calibration + RTMPFilterCalibration(pAd); + + // Initialize RF R27 register, set RF R27 must be behind RTMPFilterCalibration() + if ((pAd->MACVersion & 0xffff) < 0x0211) + RT30xxWriteRFRegister(pAd, RF_R27, 0x3); + + // set led open drain enable + RTUSBReadMACRegister(pAd, OPT_14, &data); + data |= 0x01; + RTUSBWriteMACRegister(pAd, OPT_14, data); + + if (IS_RT3071(pAd)) + { + // add by johnli, RF power sequence setup, load RF normal operation-mode setup + RT30xxLoadRFNormalModeSetup(pAd); + } + } + +} +#endif // RT3070 // + + +/* + ======================================================================== + + Routine Description: + Read initial parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID NICReadEEPROMParameters( + IN PRTMP_ADAPTER pAd, + IN PUCHAR mac_addr) +{ + UINT32 data = 0; + USHORT i, value, value2; + UCHAR TmpPhy; + EEPROM_TX_PWR_STRUC Power; + EEPROM_VERSION_STRUC Version; + EEPROM_ANTENNA_STRUC Antenna; + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n")); + + // Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8 + RTMP_IO_READ32(pAd, E2PROM_CSR, &data); + DBGPRINT(RT_DEBUG_TRACE, ("--> E2PROM_CSR = 0x%x\n", data)); + + if((data & 0x30) == 0) + pAd->EEPROMAddressNum = 6; // 93C46 + else if((data & 0x30) == 0x10) + pAd->EEPROMAddressNum = 8; // 93C66 + else + pAd->EEPROMAddressNum = 8; // 93C86 + DBGPRINT(RT_DEBUG_TRACE, ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum )); + + // RT2860 MAC no longer auto load MAC address from E2PROM. Driver has to intialize + // MAC address registers according to E2PROM setting + if (mac_addr == NULL || + strlen(mac_addr) != 17 || + mac_addr[2] != ':' || mac_addr[5] != ':' || mac_addr[8] != ':' || + mac_addr[11] != ':' || mac_addr[14] != ':') + { + USHORT Addr01,Addr23,Addr45 ; + + RT28xx_EEPROM_READ16(pAd, 0x04, Addr01); + RT28xx_EEPROM_READ16(pAd, 0x06, Addr23); + RT28xx_EEPROM_READ16(pAd, 0x08, Addr45); + + pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff); + pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8); + pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff); + pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8); + pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff); + pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8); + + DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from E2PROM \n")); + } + else + { + INT j; + PUCHAR macptr; + + macptr = mac_addr; + + for (j=0; jPermanentAddress[j], 1); + macptr=macptr+3; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from module parameter \n")); + } + + + { + //more conveninet to test mbssid, so ap's bssid &0xf1 + if (pAd->PermanentAddress[0] == 0xff) + pAd->PermanentAddress[0] = RandomByte(pAd)&0xf8; + + //if (pAd->PermanentAddress[5] == 0xff) + // pAd->PermanentAddress[5] = RandomByte(pAd)&0xf8; + + DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->PermanentAddress[0], pAd->PermanentAddress[1], + pAd->PermanentAddress[2], pAd->PermanentAddress[3], + pAd->PermanentAddress[4], pAd->PermanentAddress[5])); + if (pAd->bLocalAdminMAC == FALSE) + { + MAC_DW0_STRUC csr2; + MAC_DW1_STRUC csr3; + COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress); + csr2.field.Byte0 = pAd->CurrentAddress[0]; + csr2.field.Byte1 = pAd->CurrentAddress[1]; + csr2.field.Byte2 = pAd->CurrentAddress[2]; + csr2.field.Byte3 = pAd->CurrentAddress[3]; + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word); + csr3.word = 0; + csr3.field.Byte4 = pAd->CurrentAddress[4]; + csr3.field.Byte5 = pAd->CurrentAddress[5]; + csr3.field.U2MeMask = 0xff; + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word); + DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->PermanentAddress[0], pAd->PermanentAddress[1], + pAd->PermanentAddress[2], pAd->PermanentAddress[3], + pAd->PermanentAddress[4], pAd->PermanentAddress[5])); + } + } + + // if not return early. cause fail at emulation. + // Init the channel number for TX channel power + RTMPReadChannelPwr(pAd); + + // if E2PROM version mismatch with driver's expectation, then skip + // all subsequent E2RPOM retieval and set a system error bit to notify GUI + RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word); + pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256; + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber)); + + if (Version.field.Version > VALID_EEPROM_VERSION) + { + DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, VALID_EEPROM_VERSION)); + /*pAd->SystemErrorBitmap |= 0x00000001; + + // hard-code default value when no proper E2PROM installed + pAd->bAutoTxAgcA = FALSE; + pAd->bAutoTxAgcG = FALSE; + + // Default the channel power + for (i = 0; i < MAX_NUM_OF_CHANNELS; i++) + pAd->TxPower[i].Power = DEFAULT_RF_TX_POWER; + + // Default the channel power + for (i = 0; i < MAX_NUM_OF_11JCHANNELS; i++) + pAd->TxPower11J[i].Power = DEFAULT_RF_TX_POWER; + + for(i = 0; i < NUM_EEPROM_BBP_PARMS; i++) + pAd->EEPROMDefaultValue[i] = 0xffff; + return; */ + } + + // Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value); + pAd->EEPROMDefaultValue[0] = value; + + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); + pAd->EEPROMDefaultValue[1] = value; + + RT28xx_EEPROM_READ16(pAd, 0x38, value); // Country Region + pAd->EEPROMDefaultValue[2] = value; + + for(i = 0; i < 8; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i*2, value); + pAd->EEPROMDefaultValue[i+3] = value; + } + + // We have to parse NIC configuration 0 at here. + // If TSSI did not have preloaded value, it should reset the TxAutoAgc to false + // Therefore, we have to read TxAutoAgc control beforehand. + // Read Tx AGC control bit + Antenna.word = pAd->EEPROMDefaultValue[0]; + if (Antenna.word == 0xFFFF) + { +#ifdef RT30xx + if(IS_RT3090(pAd)) + { + Antenna.word = 0; + Antenna.field.RfIcType = RFIC_3020; + Antenna.field.TxPath = 1; + Antenna.field.RxPath = 1; + } + else + { +#endif // RT30xx // + Antenna.word = 0; + Antenna.field.RfIcType = RFIC_2820; + Antenna.field.TxPath = 1; + Antenna.field.RxPath = 2; + DBGPRINT(RT_DEBUG_WARN, ("E2PROM error, hard code as 0x%04x\n", Antenna.word)); +#ifdef RT30xx + } +#endif // RT30xx // + } + + // Choose the desired Tx&Rx stream. + if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath)) + pAd->CommonCfg.TxStream = Antenna.field.TxPath; + + if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath)) + { + pAd->CommonCfg.RxStream = Antenna.field.RxPath; + + if ((pAd->MACVersion < RALINK_2883_VERSION) && + (pAd->CommonCfg.RxStream > 2)) + { + // only 2 Rx streams for RT2860 series + pAd->CommonCfg.RxStream = 2; + } + } + + // 3*3 + // read value from EEPROM and set them to CSR174 ~ 177 in chain0 ~ chain2 + // yet implement + for(i=0; i<3; i++) + { + } + + NicConfig2.word = pAd->EEPROMDefaultValue[1]; + + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((NicConfig2.word & 0x00ff) == 0xff) + { + NicConfig2.word &= 0xff00; + } + + if ((NicConfig2.word >> 8) == 0xff) + { + NicConfig2.word &= 0x00ff; + } + } +#endif // CONFIG_STA_SUPPORT // + + if (NicConfig2.field.DynamicTxAgcControl == 1) + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; + else + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", Antenna.field.RxPath, Antenna.field.TxPath)); + + // Save the antenna for future use + pAd->Antenna.word = Antenna.word; + + // + // Reset PhyMode if we don't support 802.11a + // Only RFIC_2850 & RFIC_2750 support 802.11a + // + if ((Antenna.field.RfIcType != RFIC_2850) && (Antenna.field.RfIcType != RFIC_2750)) + { + if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11A)) + pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; +#ifdef DOT11_N_SUPPORT + else if ((pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || + (pAd->CommonCfg.PhyMode == PHY_11N_5G)) + pAd->CommonCfg.PhyMode = PHY_11BGN_MIXED; +#endif // DOT11_N_SUPPORT // + } + + // Read TSSI reference and TSSI boundary for temperature compensation. This is ugly + // 0. 11b/g + { + /* these are tempature reference value (0x00 ~ 0xFE) + ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) + + TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */ + RT28xx_EEPROM_READ16(pAd, 0x6E, Power.word); + pAd->TssiMinusBoundaryG[4] = Power.field.Byte0; + pAd->TssiMinusBoundaryG[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0x70, Power.word); + pAd->TssiMinusBoundaryG[2] = Power.field.Byte0; + pAd->TssiMinusBoundaryG[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0x72, Power.word); + pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */ + pAd->TssiPlusBoundaryG[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0x74, Power.word); + pAd->TssiPlusBoundaryG[2] = Power.field.Byte0; + pAd->TssiPlusBoundaryG[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0x76, Power.word); + pAd->TssiPlusBoundaryG[4] = Power.field.Byte0; + pAd->TxAgcStepG = Power.field.Byte1; + pAd->TxAgcCompensateG = 0; + pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG; + pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG; + + // Disable TxAgc if the based value is not right + if (pAd->TssiRefG == 0xff) + pAd->bAutoTxAgcG = FALSE; + + DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1], + pAd->TssiRefG, + pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], + pAd->TxAgcStepG, pAd->bAutoTxAgcG)); + } + // 1. 11a + { + RT28xx_EEPROM_READ16(pAd, 0xD4, Power.word); + pAd->TssiMinusBoundaryA[4] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0xD6, Power.word); + pAd->TssiMinusBoundaryA[2] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0xD8, Power.word); + pAd->TssiRefA = Power.field.Byte0; + pAd->TssiPlusBoundaryA[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0xDA, Power.word); + pAd->TssiPlusBoundaryA[2] = Power.field.Byte0; + pAd->TssiPlusBoundaryA[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, 0xDC, Power.word); + pAd->TssiPlusBoundaryA[4] = Power.field.Byte0; + pAd->TxAgcStepA = Power.field.Byte1; + pAd->TxAgcCompensateA = 0; + pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA; + pAd->TssiPlusBoundaryA[0] = pAd->TssiRefA; + + // Disable TxAgc if the based value is not right + if (pAd->TssiRefA == 0xff) + pAd->bAutoTxAgcA = FALSE; + + DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryA[4], pAd->TssiMinusBoundaryA[3], pAd->TssiMinusBoundaryA[2], pAd->TssiMinusBoundaryA[1], + pAd->TssiRefA, + pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4], + pAd->TxAgcStepA, pAd->bAutoTxAgcA)); + } + pAd->BbpRssiToDbmDelta = 0x0; + + // Read frequency offset setting for RF + RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value); + if ((value & 0x00FF) != 0x00FF) + pAd->RfFreqOffset = (ULONG) (value & 0x00FF); + else + pAd->RfFreqOffset = 0; + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset)); + + //CountryRegion byte offset (38h) + value = pAd->EEPROMDefaultValue[2] >> 8; // 2.4G band + value2 = pAd->EEPROMDefaultValue[2] & 0x00FF; // 5G band + + if ((value <= REGION_MAXIMUM_BG_BAND) && (value2 <= REGION_MAXIMUM_A_BAND)) + { + pAd->CommonCfg.CountryRegion = ((UCHAR) value) | 0x80; + pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | 0x80; + TmpPhy = pAd->CommonCfg.PhyMode; + pAd->CommonCfg.PhyMode = 0xff; + RTMPSetPhyMode(pAd, TmpPhy); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + } + + // + // Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch. + // The valid value are (-10 ~ 10) + // + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value); + pAd->BGRssiOffset0 = value & 0x00ff; + pAd->BGRssiOffset1 = (value >> 8); + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value); + pAd->BGRssiOffset2 = value & 0x00ff; + pAd->ALNAGain1 = (value >> 8); + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value); + pAd->BLNAGain = value & 0x00ff; + pAd->ALNAGain0 = (value >> 8); + + // Validate 11b/g RSSI_0 offset. + if ((pAd->BGRssiOffset0 < -10) || (pAd->BGRssiOffset0 > 10)) + pAd->BGRssiOffset0 = 0; + + // Validate 11b/g RSSI_1 offset. + if ((pAd->BGRssiOffset1 < -10) || (pAd->BGRssiOffset1 > 10)) + pAd->BGRssiOffset1 = 0; + + // Validate 11b/g RSSI_2 offset. + if ((pAd->BGRssiOffset2 < -10) || (pAd->BGRssiOffset2 > 10)) + pAd->BGRssiOffset2 = 0; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value); + pAd->ARssiOffset0 = value & 0x00ff; + pAd->ARssiOffset1 = (value >> 8); + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value); + pAd->ARssiOffset2 = value & 0x00ff; + pAd->ALNAGain2 = (value >> 8); + + if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00)) + pAd->ALNAGain1 = pAd->ALNAGain0; + if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00)) + pAd->ALNAGain2 = pAd->ALNAGain0; + + // Validate 11a RSSI_0 offset. + if ((pAd->ARssiOffset0 < -10) || (pAd->ARssiOffset0 > 10)) + pAd->ARssiOffset0 = 0; + + // Validate 11a RSSI_1 offset. + if ((pAd->ARssiOffset1 < -10) || (pAd->ARssiOffset1 > 10)) + pAd->ARssiOffset1 = 0; + + //Validate 11a RSSI_2 offset. + if ((pAd->ARssiOffset2 < -10) || (pAd->ARssiOffset2 > 10)) + pAd->ARssiOffset2 = 0; + + // + // Get LED Setting. + // + RT28xx_EEPROM_READ16(pAd, 0x3a, value); + pAd->LedCntl.word = (value&0xff00) >> 8; + RT28xx_EEPROM_READ16(pAd, EEPROM_LED1_OFFSET, value); + pAd->Led1 = value; + RT28xx_EEPROM_READ16(pAd, EEPROM_LED2_OFFSET, value); + pAd->Led2 = value; + RT28xx_EEPROM_READ16(pAd, EEPROM_LED3_OFFSET, value); + pAd->Led3 = value; + + RTMPReadTxPwrPerRate(pAd); + +#ifdef SINGLE_SKU + //pAd->CommonCfg.DefineMaxTxPwr = RTMP_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR); + RT28xx_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR, pAd->CommonCfg.DefineMaxTxPwr); +#endif // SINGLE_SKU // +#ifdef RT30xx + if (IS_RT30xx(pAd)) + { + eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value); + pAd->EFuseTag = (value & 0xff); + } +#endif // RT30xx // + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n")); +} + +/* + ======================================================================== + + Routine Description: + Set default value from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID NICInitAsicFromEEPROM( + IN PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_STA_SUPPORT + UINT32 data = 0; + UCHAR BBPR1 = 0; +#endif // CONFIG_STA_SUPPORT // + USHORT i; + EEPROM_ANTENNA_STRUC Antenna; + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + UCHAR BBPR3 = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n")); + for(i = 3; i < NUM_EEPROM_BBP_PARMS; i++) + { + UCHAR BbpRegIdx, BbpValue; + + if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) && (pAd->EEPROMDefaultValue[i] != 0)) + { + BbpRegIdx = (UCHAR)(pAd->EEPROMDefaultValue[i] >> 8); + BbpValue = (UCHAR)(pAd->EEPROMDefaultValue[i] & 0xff); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue); + } + } + + Antenna.word = pAd->EEPROMDefaultValue[0]; + if (Antenna.word == 0xFFFF) + { + DBGPRINT(RT_DEBUG_ERROR, ("E2PROM error, hard code as 0x%04x\n", Antenna.word)); + BUG_ON(Antenna.word == 0xFFFF); + } + pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath; + pAd->RfIcType = (UCHAR) Antenna.field.RfIcType; + + DBGPRINT(RT_DEBUG_WARN, ("pAd->RfIcType = %d, RealRxPath=%d, TxPath = %d\n", pAd->RfIcType, pAd->Mlme.RealRxPath,Antenna.field.TxPath)); + + // Save the antenna for future use + pAd->Antenna.word = Antenna.word; + + NicConfig2.word = pAd->EEPROMDefaultValue[1]; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((NicConfig2.word & 0x00ff) == 0xff) + { + NicConfig2.word &= 0xff00; + } + + if ((NicConfig2.word >> 8) == 0xff) + { + NicConfig2.word &= 0x00ff; + } + } +#endif // CONFIG_STA_SUPPORT // + + // Save the antenna for future use + pAd->NicConfig2.word = NicConfig2.word; + + // set default antenna as main + if (pAd->RfIcType == RFIC_3020) + AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt); + + // + // Send LED Setting to MCU. + // + if (pAd->LedCntl.word == 0xFF) + { + pAd->LedCntl.word = 0x01; + pAd->Led1 = 0x5555; + pAd->Led2 = 0x2221; + +#ifdef RT2870 + pAd->Led3 = 0x5627; +#endif // RT2870 // + } + + AsicSendCommandToMcu(pAd, 0x52, 0xff, (UCHAR)pAd->Led1, (UCHAR)(pAd->Led1 >> 8)); + AsicSendCommandToMcu(pAd, 0x53, 0xff, (UCHAR)pAd->Led2, (UCHAR)(pAd->Led2 >> 8)); + AsicSendCommandToMcu(pAd, 0x54, 0xff, (UCHAR)pAd->Led3, (UCHAR)(pAd->Led3 >> 8)); + pAd->LedIndicatorStregth = 0xFF; + RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, before link up + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Read Hardware controlled Radio state enable bit + if (NicConfig2.field.HardwareRadioControl == 1) + { + pAd->StaCfg.bHardwareRadio = TRUE; + + // Read GPIO pin2 as Hardware controlled radio state + RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); + if ((data & 0x04) == 0) + { + pAd->StaCfg.bHwRadio = FALSE; + pAd->StaCfg.bRadio = FALSE; +// RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + } + } + else + pAd->StaCfg.bHardwareRadio = FALSE; + + if (pAd->StaCfg.bRadio == FALSE) + { + RTMPSetLED(pAd, LED_RADIO_OFF); + } + else + { + RTMPSetLED(pAd, LED_RADIO_ON); + } + } +#endif // CONFIG_STA_SUPPORT // + + // Turn off patching for cardbus controller + if (NicConfig2.field.CardbusAcceleration == 1) + { +// pAd->bTest1 = TRUE; + } + + if (NicConfig2.field.DynamicTxAgcControl == 1) + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; + else + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; + // + // Since BBP has been progamed, to make sure BBP setting will be + // upate inside of AsicAntennaSelect, so reset to UNKNOWN_BAND!! + // + pAd->CommonCfg.BandState = UNKNOWN_BAND; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); + BBPR3 &= (~0x18); + if(pAd->Antenna.field.RxPath == 3) + { + BBPR3 |= (0x10); + } + else if(pAd->Antenna.field.RxPath == 2) + { + BBPR3 |= (0x8); + } + else if(pAd->Antenna.field.RxPath == 1) + { + BBPR3 |= (0x0); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Handle the difference when 1T + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); + if(pAd->Antenna.field.TxPath == 1) + { + BBPR1 &= (~0x18); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); + + DBGPRINT(RT_DEBUG_TRACE, ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", pAd->CommonCfg.bHardwareRadio, pAd->CommonCfg.bHardwareRadio)); + } +#endif // CONFIG_STA_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("TxPath = %d, RxPath = %d, RFIC=%d, Polar+LED mode=%x\n", pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, pAd->RfIcType, pAd->LedCntl.word)); + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n")); +} + +/* + ======================================================================== + + Routine Description: + Initialize NIC hardware + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICInitializeAdapter( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + WPDMA_GLO_CFG_STRUC GloCfg; +// INT_MASK_CSR_STRUC IntMask; + ULONG i =0, j=0; + AC_TXOP_CSR0_STRUC csr0; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n")); + + // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits: +retry: + i = 0; + do + { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) + break; + + RTMPusecDelay(1000); + i++; + }while ( i<100); + DBGPRINT(RT_DEBUG_TRACE, ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word)); + GloCfg.word &= 0xff0; + GloCfg.field.EnTXWriteBackDDONE =1; + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + // Record HW Beacon offset + pAd->BeaconOffset[0] = HW_BEACON_BASE0; + pAd->BeaconOffset[1] = HW_BEACON_BASE1; + pAd->BeaconOffset[2] = HW_BEACON_BASE2; + pAd->BeaconOffset[3] = HW_BEACON_BASE3; + pAd->BeaconOffset[4] = HW_BEACON_BASE4; + pAd->BeaconOffset[5] = HW_BEACON_BASE5; + pAd->BeaconOffset[6] = HW_BEACON_BASE6; + pAd->BeaconOffset[7] = HW_BEACON_BASE7; + + // + // write all shared Ring's base address into ASIC + // + + // asic simulation sequence put this ahead before loading firmware. + // pbf hardware reset + + // Initialze ASIC for TX & Rx operation + if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS) + { + if (j++ == 0) + { + NICLoadFirmware(pAd); + goto retry; + } + return NDIS_STATUS_FAILURE; + } + + + + + // WMM parameter + csr0.word = 0; + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + if (pAd->CommonCfg.PhyMode == PHY_11B) + { + csr0.field.Ac0Txop = 192; // AC_VI: 192*32us ~= 6ms + csr0.field.Ac1Txop = 96; // AC_VO: 96*32us ~= 3ms + } + else + { + csr0.field.Ac0Txop = 96; // AC_VI: 96*32us ~= 3ms + csr0.field.Ac1Txop = 48; // AC_VO: 48*32us ~= 1.5ms + } + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word); + + + + + // reset action + // Load firmware + // Status = NICLoadFirmware(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n")); + return Status; +} + +/* + ======================================================================== + + Routine Description: + Initialize ASIC + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICInitializeAsic( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset) +{ + ULONG Index = 0; + UCHAR R0 = 0xff; + UINT32 MacCsr12 = 0, Counter = 0; +#ifdef RT2870 + UINT32 MacCsr0 = 0; + NTSTATUS Status; + UCHAR Value = 0xff; +#endif // RT2870 // +#ifdef RT30xx + UINT32 eFuseCtrl; +#endif // RT30xx // + USHORT KeyIdx; + INT i,apidx; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n")); + + +#ifdef RT2870 + // + // Make sure MAC gets ready after NICLoadFirmware(). + // + Index = 0; + + //To avoid hang-on issue when interface up in kernel 2.4, + //we use a local variable "MacCsr0" instead of using "pAd->MACVersion" directly. + do + { + RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); + + if ((MacCsr0 != 0x00) && (MacCsr0 != 0xFFFFFFFF)) + break; + + RTMPusecDelay(10); + } while (Index++ < 100); + + pAd->MACVersion = MacCsr0; + DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); + // turn on bit13 (set to zero) after rt2860D. This is to solve high-current issue. + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacCsr12); + MacCsr12 &= (~0x2000); + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, MacCsr12); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3); + RTMP_IO_WRITE32(pAd, USB_DMA_CFG, 0x0); + Status = RTUSBVenderReset(pAd); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + + // Initialize MAC register to default value + for(Index=0; IndexMACVersion & 0xffff) < 0x0211) + { + if (pAd->NicConfig2.field.DACTestBit == 1) + { + RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x1F); // To fix throughput drop drastically + } + else + { + RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0F); // To fix throughput drop drastically + } + } + else + { + RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x0); + } + } + else if (IS_RT3070(pAd)) + { + RTMP_IO_WRITE32(pAd, TX_SW_CFG1, 0); + RTMP_IO_WRITE32(pAd, TX_SW_CFG2, 0x1F); // To fix throughput drop drastically + } +#endif // RT30xx // + + // + // Before program BBP, we need to wait BBP/RF get wake up. + // + Index = 0; + do + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12); + + if ((MacCsr12 & 0x03) == 0) // if BB.RF is stable + break; + + DBGPRINT(RT_DEBUG_TRACE, ("Check MAC_STATUS_CFG = Busy = %x\n", MacCsr12)); + RTMPusecDelay(1000); + } while (Index++ < 100); + + // The commands to firmware should be after these commands, these commands will init firmware + // PCI and USB are not the same because PCI driver needs to wait for PCI bus ready + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); // initialize BBP R/W access agent + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0); + RTMPusecDelay(1000); + + // Read BBP register, make sure BBP is up and running before write new data + Index = 0; + do + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &R0); + DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", R0)); + } while ((++Index < 20) && ((R0 == 0xff) || (R0 == 0x00))); + //ASSERT(Index < 20); //this will cause BSOD on Check-build driver + + if ((R0 == 0xff) || (R0 == 0x00)) + return NDIS_STATUS_FAILURE; + + // Initialize BBP register to default value + for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, BBPRegTable[Index].Value); + } + + // for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT. + // RT3090 should not program BBP R84 to 0x19, otherwise TX will block. + if (((pAd->MACVersion&0xffff) != 0x0101) && (!IS_RT30xx(pAd))) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19); + +// add by johnli, RF power sequence setup +#ifdef RT30xx + if (IS_RT30xx(pAd)) + { //update for RT3070/71/72/90/91/92. + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R79, 0x13); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R80, 0x05); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R81, 0x33); + } + + if (IS_RT3090(pAd)) + { + UCHAR bbpreg=0; + + // enable DC filter + if ((pAd->MACVersion & 0xffff) >= 0x0211) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R103, 0xc0); + } + + // improve power consumption + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R138, &bbpreg); + if (pAd->Antenna.field.TxPath == 1) + { + // turn off tx DAC_1 + bbpreg = (bbpreg | 0x20); + } + + if (pAd->Antenna.field.RxPath == 1) + { + // turn off tx ADC_1 + bbpreg &= (~0x2); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R138, bbpreg); + + // improve power consumption in RT3071 Ver.E + if ((pAd->MACVersion & 0xffff) >= 0x0211) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R31, &bbpreg); + bbpreg &= (~0x3); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R31, bbpreg); + } + } +#endif // RT30xx // +// end johnli + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12); + } + + if (pAd->MACVersion >= RALINK_2880E_VERSION && pAd->MACVersion < RALINK_3070_VERSION) // 3*3 + { + // enlarge MAX_LEN_CFG + UINT32 csr; + RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr); + csr &= 0xFFF; + csr |= 0x2000; + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr); + } + +#ifdef RT2870 +{ + UCHAR MAC_Value[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0,0}; + + //Initialize WCID table + Value = 0xff; + for(Index =0 ;Index < 254;Index++) + { + RTUSBMultiWrite(pAd, (USHORT)(MAC_WCID_BASE + Index * 8), MAC_Value, 8); + } +} +#endif // RT2870 // + + // Add radio off control +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pAd->StaCfg.bRadio == FALSE) + { +// RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + DBGPRINT(RT_DEBUG_TRACE, ("Set Radio Off\n")); + } + } +#endif // CONFIG_STA_SUPPORT // + + // Clear raw counters + RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter); + RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter); + + // ASIC will keep garbage value after boot + // Clear all seared key table when initial + // This routine can be ignored in radio-ON/OFF operation. + if (bHardReset) + { + for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4*KeyIdx, 0); + } + + // Clear all pairwise key table when initial + for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, MAC_WCID_ATTRIBUTE_BASE + (KeyIdx * HW_WCID_ATTRI_SIZE), 1); + } + } + + // assert HOST ready bit +// RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x0); // 2004-09-14 asked by Mark +// RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x4); + + // It isn't necessary to clear this space when not hard reset. + if (bHardReset == TRUE) + { + // clear all on-chip BEACON frame space + for (apidx = 0; apidx < HW_BEACON_MAX_COUNT; apidx++) + { + for (i = 0; i < HW_BEACON_OFFSET>>2; i+=4) + RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[apidx] + i, 0x00); + } + } +#ifdef RT2870 + AsicDisableSync(pAd); + // Clear raw counters + RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter); + RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter); + RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter); + // Default PCI clock cycle per ms is different as default setting, which is based on PCI. + RTMP_IO_READ32(pAd, USB_CYC_CFG, &Counter); + Counter&=0xffffff00; + Counter|=0x000001e; + RTMP_IO_WRITE32(pAd, USB_CYC_CFG, Counter); +#endif // RT2870 // +#ifdef RT30xx + pAd->bUseEfuse=FALSE; + RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrl); + pAd->bUseEfuse = ( (eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0; + if(pAd->bUseEfuse) + { + DBGPRINT(RT_DEBUG_TRACE, ("NVM is Efuse\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("NVM is EEPROM\n")); + + } +#endif // RT30xx // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT. + if ((pAd->MACVersion&0xffff) != 0x0101) + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x583f); + } +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n")); + return NDIS_STATUS_SUCCESS; +} + +/* + ======================================================================== + + Routine Description: + Reset NIC Asics + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +VOID NICIssueReset( + IN PRTMP_ADAPTER pAd) +{ + UINT32 Value = 0; + DBGPRINT(RT_DEBUG_TRACE, ("--> NICIssueReset\n")); + + // Abort Tx, prevent ASIC from writing to Host memory + //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x001f0000); + + // Disable Rx, register value supposed will remain after reset + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= (0xfffffff3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Issue reset and clear from reset state + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x03); // 2004-09-17 change from 0x01 + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICIssueReset\n")); +} + +/* + ======================================================================== + + Routine Description: + Check ASIC registers and find any reason the system might hang + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +BOOLEAN NICCheckForHang( + IN PRTMP_ADAPTER pAd) +{ + return (FALSE); +} + +VOID NICUpdateFifoStaCounters( + IN PRTMP_ADAPTER pAd) +{ + TX_STA_FIFO_STRUC StaFifo; + MAC_TABLE_ENTRY *pEntry; + UCHAR i = 0; + UCHAR pid = 0, wcid = 0; + CHAR reTry; + UCHAR succMCS; + +#ifdef RALINK_ATE + /* Nothing to do in ATE mode */ + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + do + { + RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word); + + if (StaFifo.field.bValid == 0) + break; + + wcid = (UCHAR)StaFifo.field.wcid; + + + /* ignore NoACK and MGMT frame use 0xFF as WCID */ + if ((StaFifo.field.TxAckRequired == 0) || (wcid >= MAX_LEN_OF_MAC_TABLE)) + { + i++; + continue; + } + + /* PID store Tx MCS Rate */ + pid = (UCHAR)StaFifo.field.PidType; + + pEntry = &pAd->MacTab.Content[wcid]; + + pEntry->DebugFIFOCount++; + +#ifdef DOT11_N_SUPPORT + if (StaFifo.field.TxBF) // 3*3 + pEntry->TxBFCount++; +#endif // DOT11_N_SUPPORT // + +#ifdef UAPSD_AP_SUPPORT + UAPSD_SP_AUE_Handle(pAd, pEntry, StaFifo.field.TxSuccess); +#endif // UAPSD_AP_SUPPORT // + + if (!StaFifo.field.TxSuccess) + { + pEntry->FIFOCount++; + pEntry->OneSecTxFailCount++; + + if (pEntry->FIFOCount >= 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("#")); +#ifdef DOT11_N_SUPPORT + pEntry->NoBADataCountDown = 64; +#endif // DOT11_N_SUPPORT // + + if(pEntry->PsMode == PWR_ACTIVE) + { +#ifdef DOT11_N_SUPPORT + int tid; + for (tid=0; tidAid, tid, FALSE, FALSE); + } +#endif // DOT11_N_SUPPORT // + + // Update the continuous transmission counter except PS mode + pEntry->ContinueTxFailCnt++; + } + else + { + // Clear the FIFOCount when sta in Power Save mode. Basically we assume + // this tx error happened due to sta just go to sleep. + pEntry->FIFOCount = 0; + pEntry->ContinueTxFailCnt = 0; + } + //pEntry->FIFOCount = 0; + } + //pEntry->bSendBAR = TRUE; + } + else + { +#ifdef DOT11_N_SUPPORT + if ((pEntry->PsMode != PWR_SAVE) && (pEntry->NoBADataCountDown > 0)) + { + pEntry->NoBADataCountDown--; + if (pEntry->NoBADataCountDown==0) + { + DBGPRINT(RT_DEBUG_TRACE, ("@\n")); + } + } +#endif // DOT11_N_SUPPORT // + pEntry->FIFOCount = 0; + pEntry->OneSecTxNoRetryOkCount++; + // update NoDataIdleCount when sucessful send packet to STA. + pEntry->NoDataIdleCount = 0; + pEntry->ContinueTxFailCnt = 0; + } + + succMCS = StaFifo.field.SuccessRate & 0x7F; + + reTry = pid - succMCS; + + if (StaFifo.field.TxSuccess) + { + pEntry->TXMCSExpected[pid]++; + if (pid == succMCS) + { + pEntry->TXMCSSuccessful[pid]++; + } + else + { + pEntry->TXMCSAutoFallBack[pid][succMCS]++; + } + } + else + { + pEntry->TXMCSFailed[pid]++; + } + + if (reTry > 0) + { + if ((pid >= 12) && succMCS <=7) + { + reTry -= 4; + } + pEntry->OneSecTxRetryOkCount += reTry; + } + + i++; + // ASIC store 16 stack + } while ( i < (2*TX_RING_SIZE) ); + +} + +/* + ======================================================================== + + Routine Description: + Read statistical counters from hardware registers and record them + in software variables for later on query + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID NICUpdateRawCounters( + IN PRTMP_ADAPTER pAd) +{ + UINT32 OldValue;//, Value2; + //ULONG PageSum, OneSecTransmitCount; + //ULONG TxErrorRatio, Retry, Fail; + RX_STA_CNT0_STRUC RxStaCnt0; + RX_STA_CNT1_STRUC RxStaCnt1; + RX_STA_CNT2_STRUC RxStaCnt2; + TX_STA_CNT0_STRUC TxStaCnt0; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT2_STRUC StaTx2; + TX_AGG_CNT_STRUC TxAggCnt; + TX_AGG_CNT0_STRUC TxAggCnt0; + TX_AGG_CNT1_STRUC TxAggCnt1; + TX_AGG_CNT2_STRUC TxAggCnt2; + TX_AGG_CNT3_STRUC TxAggCnt3; + TX_AGG_CNT4_STRUC TxAggCnt4; + TX_AGG_CNT5_STRUC TxAggCnt5; + TX_AGG_CNT6_STRUC TxAggCnt6; + TX_AGG_CNT7_STRUC TxAggCnt7; + + RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word); + + { + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + // Update RX PLCP error counter + pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr; + // Update False CCA counter + pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca; + } + + // Update FCS counters + OldValue= pAd->WlanCounters.FCSErrorCount.u.LowPart; + pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); // >> 7); + if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue) + pAd->WlanCounters.FCSErrorCount.u.HighPart++; + + // Add FCS error count to private counters + pAd->RalinkCounters.OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr; + OldValue = pAd->RalinkCounters.RealFcsErrCount.u.LowPart; + pAd->RalinkCounters.RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr; + if (pAd->RalinkCounters.RealFcsErrCount.u.LowPart < OldValue) + pAd->RalinkCounters.RealFcsErrCount.u.HighPart++; + + // Update Duplicate Rcv check + pAd->RalinkCounters.DuplicateRcv += RxStaCnt2.field.RxDupliCount; + pAd->WlanCounters.FrameDuplicateCount.u.LowPart += RxStaCnt2.field.RxDupliCount; + // Update RX Overflow counter + pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount); + + //pAd->RalinkCounters.RxCount = 0; +#ifdef RT2870 + if (pAd->RalinkCounters.RxCount != pAd->watchDogRxCnt) + { + pAd->watchDogRxCnt = pAd->RalinkCounters.RxCount; + pAd->watchDogRxOverFlowCnt = 0; + } + else + { + if (RxStaCnt2.field.RxFifoOverflowCount) + pAd->watchDogRxOverFlowCnt++; + else + pAd->watchDogRxOverFlowCnt = 0; + } +#endif // RT2870 // + + + //if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) || + // (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) && (pAd->MacTab.Size != 1))) + if (!pAd->bUpdateBcnCntDone) + { + // Update BEACON sent count + RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word); + RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word); + pAd->RalinkCounters.OneSecBeaconSentCnt += TxStaCnt0.field.TxBeaconCount; + pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount; + } + + //if (pAd->bStaFifoTest == TRUE) + { + RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT1, &TxAggCnt1.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT2, &TxAggCnt2.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT3, &TxAggCnt3.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT4, &TxAggCnt4.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word); + pAd->RalinkCounters.TxAggCount += TxAggCnt.field.AggTxCount; + pAd->RalinkCounters.TxNonAggCount += TxAggCnt.field.NonAggTxCount; + pAd->RalinkCounters.TxAgg1MPDUCount += TxAggCnt0.field.AggSize1Count; + pAd->RalinkCounters.TxAgg2MPDUCount += TxAggCnt0.field.AggSize2Count; + + pAd->RalinkCounters.TxAgg3MPDUCount += TxAggCnt1.field.AggSize3Count; + pAd->RalinkCounters.TxAgg4MPDUCount += TxAggCnt1.field.AggSize4Count; + pAd->RalinkCounters.TxAgg5MPDUCount += TxAggCnt2.field.AggSize5Count; + pAd->RalinkCounters.TxAgg6MPDUCount += TxAggCnt2.field.AggSize6Count; + + pAd->RalinkCounters.TxAgg7MPDUCount += TxAggCnt3.field.AggSize7Count; + pAd->RalinkCounters.TxAgg8MPDUCount += TxAggCnt3.field.AggSize8Count; + pAd->RalinkCounters.TxAgg9MPDUCount += TxAggCnt4.field.AggSize9Count; + pAd->RalinkCounters.TxAgg10MPDUCount += TxAggCnt4.field.AggSize10Count; + + pAd->RalinkCounters.TxAgg11MPDUCount += TxAggCnt5.field.AggSize11Count; + pAd->RalinkCounters.TxAgg12MPDUCount += TxAggCnt5.field.AggSize12Count; + pAd->RalinkCounters.TxAgg13MPDUCount += TxAggCnt6.field.AggSize13Count; + pAd->RalinkCounters.TxAgg14MPDUCount += TxAggCnt6.field.AggSize14Count; + + pAd->RalinkCounters.TxAgg15MPDUCount += TxAggCnt7.field.AggSize15Count; + pAd->RalinkCounters.TxAgg16MPDUCount += TxAggCnt7.field.AggSize16Count; + + // Calculate the transmitted A-MPDU count + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += TxAggCnt0.field.AggSize1Count; + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt0.field.AggSize2Count / 2); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize3Count / 3); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize4Count / 4); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize5Count / 5); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize6Count / 6); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize7Count / 7); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize8Count / 8); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize9Count / 9); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize10Count / 10); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize11Count / 11); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize12Count / 12); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize13Count / 13); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize14Count / 14); + + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize15Count / 15); + pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize16Count / 16); + } + +#ifdef DBG_DIAGNOSE + { + RtmpDiagStruct *pDiag; + COUNTER_RALINK *pRalinkCounters; + UCHAR ArrayCurIdx, i; + + pDiag = &pAd->DiagStruct; + pRalinkCounters = &pAd->RalinkCounters; + ArrayCurIdx = pDiag->ArrayCurIdx; + + if (pDiag->inited == 0) + { + NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_)); + pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0; + pDiag->inited = 1; + } + else + { + // Tx + pDiag->TxFailCnt[ArrayCurIdx] = TxStaCnt0.field.TxFailCount; + pDiag->TxAggCnt[ArrayCurIdx] = TxAggCnt.field.AggTxCount; + pDiag->TxNonAggCnt[ArrayCurIdx] = TxAggCnt.field.NonAggTxCount; + pDiag->TxAMPDUCnt[ArrayCurIdx][0] = TxAggCnt0.field.AggSize1Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][1] = TxAggCnt0.field.AggSize2Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][2] = TxAggCnt1.field.AggSize3Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][3] = TxAggCnt1.field.AggSize4Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][4] = TxAggCnt2.field.AggSize5Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][5] = TxAggCnt2.field.AggSize6Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][6] = TxAggCnt3.field.AggSize7Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][7] = TxAggCnt3.field.AggSize8Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][8] = TxAggCnt4.field.AggSize9Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][9] = TxAggCnt4.field.AggSize10Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][10] = TxAggCnt5.field.AggSize11Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][11] = TxAggCnt5.field.AggSize12Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][12] = TxAggCnt6.field.AggSize13Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][13] = TxAggCnt6.field.AggSize14Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][14] = TxAggCnt7.field.AggSize15Count; + pDiag->TxAMPDUCnt[ArrayCurIdx][15] = TxAggCnt7.field.AggSize16Count; + + pDiag->RxCrcErrCnt[ArrayCurIdx] = RxStaCnt0.field.CrcErr; + + INC_RING_INDEX(pDiag->ArrayCurIdx, DIAGNOSE_TIME); + ArrayCurIdx = pDiag->ArrayCurIdx; + for (i =0; i < 9; i++) + { + pDiag->TxDescCnt[ArrayCurIdx][i]= 0; + pDiag->TxSWQueCnt[ArrayCurIdx][i] =0; + pDiag->TxMcsCnt[ArrayCurIdx][i] = 0; + pDiag->RxMcsCnt[ArrayCurIdx][i] = 0; + } + pDiag->TxDataCnt[ArrayCurIdx] = 0; + pDiag->TxFailCnt[ArrayCurIdx] = 0; + pDiag->RxDataCnt[ArrayCurIdx] = 0; + pDiag->RxCrcErrCnt[ArrayCurIdx] = 0; +// for (i = 9; i < 16; i++) + for (i = 9; i < 24; i++) // 3*3 + { + pDiag->TxDescCnt[ArrayCurIdx][i] = 0; + pDiag->TxMcsCnt[ArrayCurIdx][i] = 0; + pDiag->RxMcsCnt[ArrayCurIdx][i] = 0; +} + + if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx) + INC_RING_INDEX(pDiag->ArrayStartIdx, DIAGNOSE_TIME); + } + + } +#endif // DBG_DIAGNOSE // + + +} + + +/* + ======================================================================== + + Routine Description: + Reset NIC from error + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Reset NIC from error state + + ======================================================================== +*/ +VOID NICResetFromError( + IN PRTMP_ADAPTER pAd) +{ + // Reset BBP (according to alex, reset ASIC will force reset BBP + // Therefore, skip the reset BBP + // RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + // Remove ASIC from reset state + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + + NICInitializeAdapter(pAd, FALSE); + NICInitAsicFromEEPROM(pAd); + + // Switch to current channel, since during reset process, the connection should remains on. + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); +} + +/* + ======================================================================== + + Routine Description: + erase 8051 firmware image in MAC ASIC + + Arguments: + Adapter Pointer to our adapter + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID NICEraseFirmware( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + + for(i=0; i %s\n", __FUNCTION__)); + + /* init */ + pFirmwareImage = NULL; + src = RTMP_FIRMWARE_FILE_NAME; + + /* save uid and gid used for filesystem access. + set user and group to 0 (root) */ + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + current->fsuid = current->fsgid = 0; + orgfs = get_fs(); + set_fs(KERNEL_DS); + + pAd->FirmwareVersion = (FIRMWARE_MAJOR_VERSION << 8) + \ + FIRMWARE_MINOR_VERSION; + + + /* allocate firmware buffer */ + pFirmwareImage = kmalloc(MAX_FIRMWARE_IMAGE_SIZE, MEM_ALLOC_FLAG); + if (pFirmwareImage == NULL) + { + /* allocate fail, use default firmware array in firmware.h */ + printk("%s - Allocate memory fail!\n", __FUNCTION__); + NICLF_DEFAULT_USE(); + } + else + { + /* allocate ok! zero the firmware buffer */ + memset(pFirmwareImage, 0x00, MAX_FIRMWARE_IMAGE_SIZE); + } /* End of if */ + + + /* if ok, read firmware file from *.bin file */ + if (flg_default_firm_use == FALSE) + { + do + { + /* open the bin file */ + srcf = filp_open(src, O_RDONLY, 0); + + if (IS_ERR(srcf)) + { + printk("%s - Error %ld opening %s\n", + __FUNCTION__, -PTR_ERR(srcf), src); + NICLF_DEFAULT_USE(); + break; + } /* End of if */ + + /* the object must have a read method */ + if ((srcf->f_op == NULL) || (srcf->f_op->read == NULL)) + { + printk("%s - %s does not have a write method\n", __FUNCTION__, src); + NICLF_DEFAULT_USE(); + break; + } /* End of if */ + + /* read the firmware from the file *.bin */ + FileLength = srcf->f_op->read(srcf, + pFirmwareImage, + MAX_FIRMWARE_IMAGE_SIZE, + &srcf->f_pos); + + if (FileLength != MAX_FIRMWARE_IMAGE_SIZE) + { + printk("%s: error file length (=%d) in RT2860AP.BIN\n", + __FUNCTION__, FileLength); + NICLF_DEFAULT_USE(); + break; + } + else + { + PUCHAR ptr = pFirmwareImage; + USHORT crc = 0xffff; + + + /* calculate firmware CRC */ + for(i=0; i<(MAX_FIRMWARE_IMAGE_SIZE-2); i++, ptr++) + crc = ByteCRC16(BitReverse(*ptr), crc); + /* End of for */ + + if ((pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2] != \ + (UCHAR)BitReverse((UCHAR)(crc>>8))) || + (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1] != \ + (UCHAR)BitReverse((UCHAR)crc))) + { + /* CRC fail */ + printk("%s: CRC = 0x%02x 0x%02x " + "error, should be 0x%02x 0x%02x\n", + __FUNCTION__, + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2], + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1], + (UCHAR)(crc>>8), (UCHAR)(crc)); + NICLF_DEFAULT_USE(); + break; + } + else + { + /* firmware is ok */ + pAd->FirmwareVersion = \ + (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4] << 8) + + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3]; + + /* check if firmware version of the file is too old */ + if ((pAd->FirmwareVersion) < \ + ((FIRMWARE_MAJOR_VERSION << 8) + + FIRMWARE_MINOR_VERSION)) + { + printk("%s: firmware version too old!\n", __FUNCTION__); + NICLF_DEFAULT_USE(); + break; + } /* End of if */ + } /* End of if */ + + DBGPRINT(RT_DEBUG_TRACE, + ("NICLoadFirmware: CRC ok, ver=%d.%d\n", + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4], + pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3])); + } /* End of if (FileLength == MAX_FIRMWARE_IMAGE_SIZE) */ + break; + } while(TRUE); + + /* close firmware file */ + if (IS_ERR(srcf)) + ; + else + { + retval = filp_close(srcf, NULL); + if (retval) + { + DBGPRINT(RT_DEBUG_ERROR, + ("--> Error %d closing %s\n", -retval, src)); + } /* End of if */ + } /* End of if */ + } /* End of if */ + + + /* write firmware to ASIC */ + if (flg_default_firm_use == TRUE) + { + /* use default fimeware, free allocated buffer */ + if (pFirmwareImage != NULL) + kfree(pFirmwareImage); + /* End of if */ + + /* use default *.bin array */ + pFirmwareImage = FirmwareImage; + FileLength = sizeof(FirmwareImage); + } /* End of if */ + + /* enable Host program ram write selection */ + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x10000); + + for(i=0; ifsuid = orgfsuid; + current->fsgid = orgfsgid; +#else + + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PUCHAR pFirmwareImage; + ULONG FileLength, Index; + //ULONG firm; + UINT32 MacReg = 0; + UINT32 Version = (pAd->MACVersion >> 16); + + pFirmwareImage = FirmwareImage; + FileLength = sizeof(FirmwareImage); + + // New 8k byte firmware size for RT3071/RT3072 + //printk("Usb Chip\n"); + if (FIRMWAREIMAGE_LENGTH == FIRMWAREIMAGE_MAX_LENGTH) + //The firmware image consists of two parts. One is the origianl and the other is the new. + //Use Second Part + { +#ifdef RT2870 + if ((Version != 0x2860) && (Version != 0x2872) && (Version != 0x3070)) + { // Use Firmware V2. + //printk("KH:Use New Version,part2\n"); + pFirmwareImage = (PUCHAR)&FirmwareImage[FIRMWAREIMAGEV1_LENGTH]; + FileLength = FIRMWAREIMAGEV2_LENGTH; + } + else + { + //printk("KH:Use New Version,part1\n"); + pFirmwareImage = FirmwareImage; + FileLength = FIRMWAREIMAGEV1_LENGTH; + } +#endif // RT2870 // + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("KH: bin file should be 8KB.\n")); + Status = NDIS_STATUS_FAILURE; + } + + RT28XX_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength); + +#endif + + /* check if MCU is ready */ + Index = 0; + do + { + RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg); + + if (MacReg & 0x80) + break; + + RTMPusecDelay(1000); + } while (Index++ < 1000); + + if (Index >= 1000) + { + Status = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware: MCU is not ready\n\n\n")); + } /* End of if */ + + DBGPRINT(RT_DEBUG_TRACE, + ("<=== %s (status=%d)\n", __FUNCTION__, Status)); + return Status; +} /* End of NICLoadFirmware */ + + +/* + ======================================================================== + + Routine Description: + Load Tx rate switching parameters + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS firmware image load ok + NDIS_STATUS_FAILURE image not found + + IRQL = PASSIVE_LEVEL + + Rate Table Format: + 1. (B0: Valid Item number) (B1:Initial item from zero) + 2. Item Number(Dec) Mode(Hex) Current MCS(Dec) TrainUp(Dec) TrainDown(Dec) + + ======================================================================== +*/ +NDIS_STATUS NICLoadRateSwitchingParams( + IN PRTMP_ADAPTER pAd) +{ + return NDIS_STATUS_SUCCESS; +} + +/* + ======================================================================== + + Routine Description: + if pSrc1 all zero with length Length, return 0. + If not all zero, return 1 + + Arguments: + pSrc1 + + Return Value: + 1: not all zero + 0: all zero + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +ULONG RTMPNotAllZero( + IN PVOID pSrc1, + IN ULONG Length) +{ + PUCHAR pMem1; + ULONG Index = 0; + + pMem1 = (PUCHAR) pSrc1; + + for (Index = 0; Index < Length; Index++) + { + if (pMem1[Index] != 0x0) + { + break; + } + } + + if (Index == Length) + { + return (0); + } + else + { + return (1); + } +} + +/* + ======================================================================== + + Routine Description: + Compare two memory block + + Arguments: + pSrc1 Pointer to first memory address + pSrc2 Pointer to second memory address + + Return Value: + 0: memory is equal + 1: pSrc1 memory is larger + 2: pSrc2 memory is larger + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +ULONG RTMPCompareMemory( + IN PVOID pSrc1, + IN PVOID pSrc2, + IN ULONG Length) +{ + PUCHAR pMem1; + PUCHAR pMem2; + ULONG Index = 0; + + pMem1 = (PUCHAR) pSrc1; + pMem2 = (PUCHAR) pSrc2; + + for (Index = 0; Index < Length; Index++) + { + if (pMem1[Index] > pMem2[Index]) + return (1); + else if (pMem1[Index] < pMem2[Index]) + return (2); + } + + // Equal + return (0); +} + +/* + ======================================================================== + + Routine Description: + Zero out memory block + + Arguments: + pSrc1 Pointer to memory address + Length Size + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPZeroMemory( + IN PVOID pSrc, + IN ULONG Length) +{ + PUCHAR pMem; + ULONG Index = 0; + + pMem = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem[Index] = 0x00; + } +} + +VOID RTMPFillMemory( + IN PVOID pSrc, + IN ULONG Length, + IN UCHAR Fill) +{ + PUCHAR pMem; + ULONG Index = 0; + + pMem = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem[Index] = Fill; + } +} + +/* + ======================================================================== + + Routine Description: + Copy data from memory block 1 to memory block 2 + + Arguments: + pDest Pointer to destination memory address + pSrc Pointer to source memory address + Length Copy size + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPMoveMemory( + OUT PVOID pDest, + IN PVOID pSrc, + IN ULONG Length) +{ + PUCHAR pMem1; + PUCHAR pMem2; + UINT Index; + + ASSERT((Length==0) || (pDest && pSrc)); + + pMem1 = (PUCHAR) pDest; + pMem2 = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem1[Index] = pMem2[Index]; + } +} + +/* + ======================================================================== + + Routine Description: + Initialize port configuration structure + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID UserCfgInit( + IN PRTMP_ADAPTER pAd) +{ +// EDCA_PARM DefaultEdcaParm; + UINT key_index, bss_index; + + DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit\n")); + + // + // part I. intialize common configuration + // +#ifdef RT2870 + pAd->BulkOutReq = 0; + + pAd->BulkOutComplete = 0; + pAd->BulkOutCompleteOther = 0; + pAd->BulkOutCompleteCancel = 0; + pAd->BulkInReq = 0; + pAd->BulkInComplete = 0; + pAd->BulkInCompleteFail = 0; + + //pAd->QuickTimerP = 100; + //pAd->TurnAggrBulkInCount = 0; + pAd->bUsbTxBulkAggre = 0; + + // init as unsed value to ensure driver will set to MCU once. + pAd->LedIndicatorStregth = 0xFF; + + pAd->CommonCfg.MaxPktOneTxBulk = 2; + pAd->CommonCfg.TxBulkFactor = 1; + pAd->CommonCfg.RxBulkFactor =1; + + pAd->CommonCfg.TxPower = 100; //mW + + NdisZeroMemory(&pAd->CommonCfg.IOTestParm, sizeof(pAd->CommonCfg.IOTestParm)); +#endif // RT2870 // + + for(key_index=0; key_indexSharedKey[bss_index][key_index].KeyLen = 0; + pAd->SharedKey[bss_index][key_index].CipherAlg = CIPHER_NONE; + } /* End of for */ + } /* End of for */ + + pAd->EepromAccess = FALSE; + + pAd->Antenna.word = 0; + pAd->CommonCfg.BBPCurrentBW = BW_20; + + pAd->LedCntl.word = 0; + + pAd->bAutoTxAgcA = FALSE; // Default is OFF + pAd->bAutoTxAgcG = FALSE; // Default is OFF + pAd->RfIcType = RFIC_2820; + + // Init timer for reset complete event + pAd->CommonCfg.CentralChannel = 1; + pAd->bForcePrintTX = FALSE; + pAd->bForcePrintRX = FALSE; + pAd->bStaFifoTest = FALSE; + pAd->bProtectionTest = FALSE; + pAd->bHCCATest = FALSE; + pAd->bGenOneHCCA = FALSE; + pAd->CommonCfg.Dsifs = 10; // in units of usec + pAd->CommonCfg.TxPower = 100; //mW + pAd->CommonCfg.TxPowerPercentage = 0xffffffff; // AUTO + pAd->CommonCfg.TxPowerDefault = 0xffffffff; // AUTO + pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; // use Long preamble on TX by defaut + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + pAd->CommonCfg.RtsThreshold = 2347; + pAd->CommonCfg.FragmentThreshold = 2346; + pAd->CommonCfg.UseBGProtection = 0; // 0: AUTO + pAd->CommonCfg.bEnableTxBurst = TRUE; //0; + pAd->CommonCfg.PhyMode = 0xff; // unknown + pAd->CommonCfg.BandState = UNKNOWN_BAND; + pAd->CommonCfg.RadarDetect.CSPeriod = 10; + pAd->CommonCfg.RadarDetect.CSCount = 0; + pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; + pAd->CommonCfg.RadarDetect.ChMovingTime = 65; + pAd->CommonCfg.RadarDetect.LongPulseRadarTh = 3; + pAd->CommonCfg.bAPSDCapable = FALSE; + pAd->CommonCfg.bNeedSendTriggerFrame = FALSE; + pAd->CommonCfg.TriggerTimerCount = 0; + pAd->CommonCfg.bAPSDForcePowerSave = FALSE; + pAd->CommonCfg.bCountryFlag = FALSE; + pAd->CommonCfg.TxStream = 0; + pAd->CommonCfg.RxStream = 0; + + NdisZeroMemory(&pAd->BeaconTxWI, sizeof(pAd->BeaconTxWI)); + +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); + pAd->HTCEnable = FALSE; + pAd->bBroadComHT = FALSE; + pAd->CommonCfg.bRdg = FALSE; + +#ifdef DOT11N_DRAFT3 + pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; // Unit : TU. 5~1000 + pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; // Unit : TU. 10~1000 + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; // Unit : Second + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; // Unit : TU. 200~10000 + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; // Unit : TU. 20~10000 + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor; + pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; // Unit : percentage + pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); +#endif // DOT11N_DRAFT3 // + + NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; + pAd->CommonCfg.BACapability.field.MpduDensity = 0; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; //32; + pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; //32; + DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit. BACapability = 0x%x\n", pAd->CommonCfg.BACapability.word)); + + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + BATableInit(pAd, &pAd->BATable); + + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; + pAd->CommonCfg.bHTProtect = 1; + pAd->CommonCfg.bMIMOPSEnable = TRUE; + pAd->CommonCfg.bBADecline = FALSE; + pAd->CommonCfg.bDisableReordering = FALSE; + + pAd->CommonCfg.TxBASize = 7; + + pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word; +#endif // DOT11_N_SUPPORT // + + //pAd->CommonCfg.HTPhyMode.field.BW = BW_20; + //pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO; + //pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800; + //pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE; + pAd->CommonCfg.TxRate = RATE_6; + + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; + pAd->CommonCfg.MlmeTransmit.field.BW = BW_20; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + + pAd->CommonCfg.BeaconPeriod = 100; // in mSec + + // + // part II. intialize STA specific configuration + // +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_DIRECT); + RX_FILTER_CLEAR_FLAG(pAd, fRX_FILTER_ACCEPT_MULTICAST); + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_BROADCAST); + RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_ALL_MULTICAST); + + pAd->StaCfg.Psm = PWR_ACTIVE; + + pAd->StaCfg.OrigWepStatus = Ndis802_11EncryptionDisabled; + pAd->StaCfg.PairCipher = Ndis802_11EncryptionDisabled; + pAd->StaCfg.GroupCipher = Ndis802_11EncryptionDisabled; + pAd->StaCfg.bMixCipher = FALSE; + pAd->StaCfg.DefaultKeyId = 0; + + // 802.1x port control + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.LastMicErrorTime = 0; + pAd->StaCfg.MicErrCnt = 0; + pAd->StaCfg.bBlockAssoc = FALSE; + pAd->StaCfg.WpaState = SS_NOTUSE; + + pAd->CommonCfg.NdisRadioStateOff = FALSE; // New to support microsoft disable radio with OID command + + pAd->StaCfg.RssiTrigger = 0; + NdisZeroMemory(&pAd->StaCfg.RssiSample, sizeof(RSSI_SAMPLE)); + pAd->StaCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_BELOW_THRESHOLD; + pAd->StaCfg.AtimWin = 0; + pAd->StaCfg.DefaultListenCount = 3;//default listen count; + pAd->StaCfg.BssType = BSS_INFRA; // BSS_INFRA or BSS_ADHOC or BSS_MONITOR + pAd->StaCfg.bScanReqIsFromWebUI = FALSE; + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW); + + pAd->StaCfg.bAutoTxRateSwitch = TRUE; + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + } + +#ifdef EXT_BUILD_CHANNEL_LIST + pAd->StaCfg.IEEE80211dClientMode = Rt802_11_D_None; +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // + + // global variables mXXXX used in MAC protocol state machines + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + + // PHY specification + pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; // default PHY mode + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); // CCK use LONG preamble + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // user desired power mode + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; + pAd->StaCfg.bWindowsACCAMEnable = FALSE; + +#ifdef LEAP_SUPPORT + // CCX v1.0 releated init value + RTMPInitTimer(pAd, &pAd->StaCfg.LeapAuthTimer, GET_TIMER_FUNCTION(LeapAuthTimeout), pAd, FALSE); + pAd->StaCfg.LeapAuthMode = CISCO_AuthModeLEAPNone; + pAd->StaCfg.bCkipOn = FALSE; +#endif // LEAP_SUPPORT // + + RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), pAd, FALSE); + pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE; + + // Patch for Ndtest + pAd->StaCfg.ScanCnt = 0; + + // CCX 2.0 control flag init + pAd->StaCfg.CCXEnable = FALSE; + pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED; + pAd->StaCfg.CCXQosECWMin = 4; + pAd->StaCfg.CCXQosECWMax = 10; + + pAd->StaCfg.bHwRadio = TRUE; // Default Hardware Radio status is On + pAd->StaCfg.bSwRadio = TRUE; // Default Software Radio status is On + pAd->StaCfg.bRadio = TRUE; // bHwRadio && bSwRadio + pAd->StaCfg.bHardwareRadio = FALSE; // Default is OFF + pAd->StaCfg.bShowHiddenSSID = FALSE; // Default no show + + // Nitro mode control + pAd->StaCfg.bAutoReconnect = TRUE; + + // Save the init time as last scan time, the system should do scan after 2 seconds. + // This patch is for driver wake up from standby mode, system will do scan right away. + pAd->StaCfg.LastScanTime = 0; + NdisZeroMemory(pAd->nickname, IW_ESSID_MAX_SIZE+1); + sprintf(pAd->nickname, "%s", STA_NIC_DEVICE_NAME); + RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), pAd, FALSE); +#ifdef WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.IEEE8021X = FALSE; + pAd->StaCfg.IEEE8021x_required_keys = FALSE; + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + + } +#endif // CONFIG_STA_SUPPORT // + + // Default for extra information is not valid + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + + // Default Config change flag + pAd->bConfigChanged = FALSE; + + // + // part III. AP configurations + // + + + // + // part IV. others + // + // dynamic BBP R66:sensibity tuning to overcome background noise + pAd->BbpTuning.bEnable = TRUE; + pAd->BbpTuning.FalseCcaLowerThreshold = 100; + pAd->BbpTuning.FalseCcaUpperThreshold = 512; + pAd->BbpTuning.R66Delta = 4; + pAd->Mlme.bEnableAutoAntennaCheck = TRUE; + + // + // Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value. + // if not initial this value, the default value will be 0. + // + pAd->BbpTuning.R66CurrentValue = 0x38; + + pAd->Bbp94 = BBPR94_DEFAULT; + pAd->BbpForCCK = FALSE; + + // Default is FALSE for test bit 1 + //pAd->bTest1 = FALSE; + + // initialize MAC table and allocate spin lock + NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); + InitializeQueueHeader(&pAd->MacTab.McastPsQueue); + NdisAllocateSpinLock(&pAd->MacTabLock); + + //RTMPInitTimer(pAd, &pAd->RECBATimer, RECBATimerTimeout, pAd, TRUE); + //RTMPSetTimer(&pAd->RECBATimer, REORDER_EXEC_INTV); + +#ifdef RALINK_ATE + NdisZeroMemory(&pAd->ate, sizeof(ATE_INFO)); + pAd->ate.Mode = ATE_STOP; + pAd->ate.TxCount = 200;/* to exceed TX_RING_SIZE ... */ + pAd->ate.TxLength = 1024; + pAd->ate.TxWI.ShortGI = 0;// LONG GI : 800 ns + pAd->ate.TxWI.PHYMODE = MODE_CCK; + pAd->ate.TxWI.MCS = 3; + pAd->ate.TxWI.BW = BW_20; + pAd->ate.Channel = 1; + pAd->ate.QID = QID_AC_BE; + pAd->ate.Addr1[0] = 0x00; + pAd->ate.Addr1[1] = 0x11; + pAd->ate.Addr1[2] = 0x22; + pAd->ate.Addr1[3] = 0xAA; + pAd->ate.Addr1[4] = 0xBB; + pAd->ate.Addr1[5] = 0xCC; + NdisMoveMemory(pAd->ate.Addr2, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS); + NdisMoveMemory(pAd->ate.Addr3, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS); + pAd->ate.bRxFer = 0; + pAd->ate.bQATxStart = FALSE; + pAd->ate.bQARxStart = FALSE; +#ifdef RALINK_28xx_QA + //pAd->ate.Repeat = 0; + pAd->ate.TxStatus = 0; + pAd->ate.AtePid = 0; +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + + + pAd->CommonCfg.bWiFiTest = FALSE; + + + DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n")); +} + +// IRQL = PASSIVE_LEVEL +UCHAR BtoH(char ch) +{ + if (ch >= '0' && ch <= '9') return (ch - '0'); // Handle numerals + if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA); // Handle capitol hex digits + if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA); // Handle small hex digits + return(255); +} + +// +// FUNCTION: AtoH(char *, UCHAR *, int) +// +// PURPOSE: Converts ascii string to network order hex +// +// PARAMETERS: +// src - pointer to input ascii string +// dest - pointer to output hex +// destlen - size of dest +// +// COMMENTS: +// +// 2 ascii bytes make a hex byte so must put 1st ascii byte of pair +// into upper nibble and 2nd ascii byte of pair into lower nibble. +// +// IRQL = PASSIVE_LEVEL + +void AtoH(char * src, UCHAR * dest, int destlen) +{ + char * srcptr; + PUCHAR destTemp; + + srcptr = src; + destTemp = (PUCHAR) dest; + + while(destlen--) + { + *destTemp = BtoH(*srcptr++) << 4; // Put 1st ascii byte in upper nibble. + *destTemp += BtoH(*srcptr++); // Add 2nd ascii byte to above. + destTemp++; + } +} + +VOID RTMPPatchMacBbpBug( + IN PRTMP_ADAPTER pAd) +{ + ULONG Index; + + // Initialize BBP register to default value + for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, (UCHAR)BBPRegTable[Index].Value); + } + + // Initialize RF register to default value + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + // Re-init BBP register from EEPROM value + NICInitAsicFromEEPROM(pAd); +} + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pAd Pointer to our adapter + pTimer Timer structure + pTimerFunc Function to execute when timer expired + Repeat Ture for period timer + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPInitTimer( + IN PRTMP_ADAPTER pAd, + IN PRALINK_TIMER_STRUCT pTimer, + IN PVOID pTimerFunc, + IN PVOID pData, + IN BOOLEAN Repeat) +{ + // + // Set Valid to TRUE for later used. + // It will crash if we cancel a timer or set a timer + // that we haven't initialize before. + // + pTimer->Valid = TRUE; + + pTimer->PeriodicType = Repeat; + pTimer->State = FALSE; + pTimer->cookie = (ULONG) pData; + +#ifdef RT2870 + pTimer->pAd = pAd; +#endif // RT2870 // + + RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (PVOID) pTimer); +} + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pTimer Timer structure + Value Timer value in milliseconds + + Return Value: + None + + Note: + To use this routine, must call RTMPInitTimer before. + + ======================================================================== +*/ +VOID RTMPSetTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value) +{ + if (pTimer->Valid) + { + pTimer->TimerValue = Value; + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) + { + pTimer->Repeat = TRUE; + RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value); + } + else + { + pTimer->Repeat = FALSE; + RTMP_OS_Add_Timer(&pTimer->TimerObj, Value); + } + } + else + { + DBGPRINT_ERR(("RTMPSetTimer failed, Timer hasn't been initialize!\n")); + } +} + + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pTimer Timer structure + Value Timer value in milliseconds + + Return Value: + None + + Note: + To use this routine, must call RTMPInitTimer before. + + ======================================================================== +*/ +VOID RTMPModTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value) +{ + BOOLEAN Cancel; + + if (pTimer->Valid) + { + pTimer->TimerValue = Value; + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) + { + RTMPCancelTimer(pTimer, &Cancel); + RTMPSetTimer(pTimer, Value); + } + else + { + RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value); + } + } + else + { + DBGPRINT_ERR(("RTMPModTimer failed, Timer hasn't been initialize!\n")); + } +} + +/* + ======================================================================== + + Routine Description: + Cancel timer objects + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + 1.) To use this routine, must call RTMPInitTimer before. + 2.) Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +VOID RTMPCancelTimer( + IN PRALINK_TIMER_STRUCT pTimer, + OUT BOOLEAN *pCancelled) +{ + if (pTimer->Valid) + { + if (pTimer->State == FALSE) + pTimer->Repeat = FALSE; + RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); + + if (*pCancelled == TRUE) + pTimer->State = TRUE; + +#ifdef RT2870 + // We need to go-through the TimerQ to findout this timer handler and remove it if + // it's still waiting for execution. + + RT2870_TimerQ_Remove(pTimer->pAd, pTimer); +#endif // RT2870 // + } + else + { + // + // NdisMCancelTimer just canced the timer and not mean release the timer. + // And don't set the "Valid" to False. So that we can use this timer again. + // + DBGPRINT_ERR(("RTMPCancelTimer failed, Timer hasn't been initialize!\n")); + } +} + +/* + ======================================================================== + + Routine Description: + Set LED Status + + Arguments: + pAd Pointer to our adapter + Status LED Status + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPSetLED( + IN PRTMP_ADAPTER pAd, + IN UCHAR Status) +{ + //ULONG data; + UCHAR HighByte = 0; + UCHAR LowByte; + +// In ATE mode of RT2860 AP/STA, we have erased 8051 firmware. +// So LED mode is not supported when ATE is running. +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + LowByte = pAd->LedCntl.field.LedMode&0x7f; + switch (Status) + { + case LED_LINK_DOWN: + HighByte = 0x20; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + pAd->LedIndicatorStregth = 0; + break; + case LED_LINK_UP: + if (pAd->CommonCfg.Channel > 14) + HighByte = 0xa0; + else + HighByte = 0x60; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_RADIO_ON: + HighByte = 0x20; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_HALT: + LowByte = 0; // Driver sets MAC register and MAC controls LED + case LED_RADIO_OFF: + HighByte = 0; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_WPS: + HighByte = 0x10; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_ON_SITE_SURVEY: + HighByte = 0x08; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + case LED_POWER_UP: + HighByte = 0x04; + AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte); + break; + default: + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetLED::Unknown Status %d\n", Status)); + break; + } + + // + // Keep LED status for LED SiteSurvey mode. + // After SiteSurvey, we will set the LED mode to previous status. + // + if ((Status != LED_ON_SITE_SURVEY) && (Status != LED_POWER_UP)) + pAd->LedStatus = Status; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetLED::Mode=%d,HighByte=0x%02x,LowByte=0x%02x\n", pAd->LedCntl.field.LedMode, HighByte, LowByte)); +} + +/* + ======================================================================== + + Routine Description: + Set LED Signal Stregth + + Arguments: + pAd Pointer to our adapter + Dbm Signal Stregth + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Can be run on any IRQL level. + + According to Microsoft Zero Config Wireless Signal Stregth definition as belows. + <= -90 No Signal + <= -81 Very Low + <= -71 Low + <= -67 Good + <= -57 Very Good + > -57 Excellent + ======================================================================== +*/ +VOID RTMPSetSignalLED( + IN PRTMP_ADAPTER pAd, + IN NDIS_802_11_RSSI Dbm) +{ + UCHAR nLed = 0; + + // + // if not Signal Stregth, then do nothing. + // + if (pAd->LedCntl.field.LedMode != LED_MODE_SIGNAL_STREGTH) + { + return; + } + + if (Dbm <= -90) + nLed = 0; + else if (Dbm <= -81) + nLed = 1; + else if (Dbm <= -71) + nLed = 3; + else if (Dbm <= -67) + nLed = 7; + else if (Dbm <= -57) + nLed = 15; + else + nLed = 31; + + // + // Update Signal Stregth to firmware if changed. + // + if (pAd->LedIndicatorStregth != nLed) + { + AsicSendCommandToMcu(pAd, 0x51, 0xff, nLed, pAd->LedCntl.field.Polarity); + pAd->LedIndicatorStregth = nLed; + } +} + +/* + ======================================================================== + + Routine Description: + Enable RX + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL <= DISPATCH_LEVEL + + Note: + Before Enable RX, make sure you have enabled Interrupt. + ======================================================================== +*/ +VOID RTMPEnableRxTx( + IN PRTMP_ADAPTER pAd) +{ +// WPDMA_GLO_CFG_STRUC GloCfg; +// ULONG i = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n")); + + // Enable Rx DMA. + RT28XXDMAEnable(pAd); + + // enable RX of MAC block + if (pAd->OpMode == OPMODE_AP) + { + UINT32 rx_filter_flag = APNORMAL; + + + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); // enable RX of DMA block + } + else + { + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. + } + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc); + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n")); +} + + diff --git a/drivers/staging/rt3070/common/rtmp_tkip.c b/drivers/staging/rt3070/common/rtmp_tkip.c new file mode 100644 index 000000000000..bf8986e83679 --- /dev/null +++ b/drivers/staging/rt3070/common/rtmp_tkip.c @@ -0,0 +1,1613 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtmp_tkip.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Wu 02-25-02 Initial +*/ + +#include "../rt_config.h" + +// Rotation functions on 32 bit values +#define ROL32( A, n ) \ + ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) +#define ROR32( A, n ) ROL32( (A), 32-(n) ) + +UINT Tkip_Sbox_Lower[256] = +{ + 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54, + 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A, + 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B, + 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B, + 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F, + 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F, + 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5, + 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F, + 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB, + 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97, + 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED, + 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A, + 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94, + 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3, + 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04, + 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D, + 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39, + 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95, + 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83, + 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76, + 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4, + 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B, + 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0, + 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18, + 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51, + 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85, + 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12, + 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9, + 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7, + 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A, + 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8, + 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A +}; + +UINT Tkip_Sbox_Upper[256] = +{ + 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91, + 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC, + 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB, + 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B, + 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83, + 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A, + 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F, + 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA, + 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B, + 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13, + 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6, + 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85, + 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11, + 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B, + 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1, + 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF, + 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E, + 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6, + 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B, + 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD, + 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8, + 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2, + 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49, + 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10, + 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97, + 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F, + 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C, + 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27, + 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33, + 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5, + 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0, + 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C +}; + +/*****************************/ +/******** SBOX Table *********/ +/*****************************/ + +UCHAR SboxTable[256] = +{ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +VOID xor_32( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out); + +VOID xor_128( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out); + +VOID next_key( + IN PUCHAR key, + IN INT round); + +VOID byte_sub( + IN PUCHAR in, + OUT PUCHAR out); + +VOID shift_row( + IN PUCHAR in, + OUT PUCHAR out); + +VOID mix_column( + IN PUCHAR in, + OUT PUCHAR out); + +UCHAR RTMPCkipSbox( + IN UCHAR a); +// +// Expanded IV for TKIP function. +// +typedef struct PACKED _IV_CONTROL_ +{ + union PACKED + { + struct PACKED + { + UCHAR rc0; + UCHAR rc1; + UCHAR rc2; + + union PACKED + { + struct PACKED + { +#ifdef RT_BIG_ENDIAN + UCHAR KeyID:2; + UCHAR ExtIV:1; + UCHAR Rsvd:5; +#else + UCHAR Rsvd:5; + UCHAR ExtIV:1; + UCHAR KeyID:2; +#endif + } field; + UCHAR Byte; + } CONTROL; + } field; + + ULONG word; + } IV16; + + ULONG IV32; +} TKIP_IV, *PTKIP_IV; + + +/* + ======================================================================== + + Routine Description: + Convert from UCHAR[] to ULONG in a portable way + + Arguments: + pMICKey pointer to MIC Key + + Return Value: + None + + Note: + + ======================================================================== +*/ +ULONG RTMPTkipGetUInt32( + IN PUCHAR pMICKey) +{ + ULONG res = 0; + INT i; + + for (i = 0; i < 4; i++) + { + res |= (*pMICKey++) << (8 * i); + } + + return res; +} + +/* + ======================================================================== + + Routine Description: + Convert from ULONG to UCHAR[] in a portable way + + Arguments: + pDst pointer to destination for convert ULONG to UCHAR[] + val the value for convert + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipPutUInt32( + IN OUT PUCHAR pDst, + IN ULONG val) +{ + INT i; + + for(i = 0; i < 4; i++) + { + *pDst++ = (UCHAR) (val & 0xff); + val >>= 8; + } +} + +/* + ======================================================================== + + Routine Description: + Set the MIC Key. + + Arguments: + pAd Pointer to our adapter + pMICKey pointer to MIC Key + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipSetMICKey( + IN PTKIP_KEY_INFO pTkip, + IN PUCHAR pMICKey) +{ + // Set the key + pTkip->K0 = RTMPTkipGetUInt32(pMICKey); + pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4); + // and reset the message + pTkip->L = pTkip->K0; + pTkip->R = pTkip->K1; + pTkip->nBytesInM = 0; + pTkip->M = 0; +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC Value. + + Arguments: + pAd Pointer to our adapter + uChar Append this uChar + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipAppendByte( + IN PTKIP_KEY_INFO pTkip, + IN UCHAR uChar) +{ + // Append the byte to our word-sized buffer + pTkip->M |= (uChar << (8* pTkip->nBytesInM)); + pTkip->nBytesInM++; + // Process the word if it is full. + if( pTkip->nBytesInM >= 4 ) + { + pTkip->L ^= pTkip->M; + pTkip->R ^= ROL32( pTkip->L, 17 ); + pTkip->L += pTkip->R; + pTkip->R ^= ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip->L & 0x00ff00ff) << 8); + pTkip->L += pTkip->R; + pTkip->R ^= ROL32( pTkip->L, 3 ); + pTkip->L += pTkip->R; + pTkip->R ^= ROR32( pTkip->L, 2 ); + pTkip->L += pTkip->R; + // Clear the buffer + pTkip->M = 0; + pTkip->nBytesInM = 0; + } +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC Value. + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to source data for Calculate MIC Value + Len Indicate the length of the source data + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipAppend( + IN PTKIP_KEY_INFO pTkip, + IN PUCHAR pSrc, + IN UINT nBytes) +{ + // This is simple + while(nBytes > 0) + { + RTMPTkipAppendByte(pTkip, *pSrc++); + nBytes--; + } +} + +/* + ======================================================================== + + Routine Description: + Get the MIC Value. + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + the MIC Value is store in pAd->PrivateInfo.MIC + ======================================================================== +*/ +VOID RTMPTkipGetMIC( + IN PTKIP_KEY_INFO pTkip) +{ + // Append the minimum padding + RTMPTkipAppendByte(pTkip, 0x5a ); + RTMPTkipAppendByte(pTkip, 0 ); + RTMPTkipAppendByte(pTkip, 0 ); + RTMPTkipAppendByte(pTkip, 0 ); + RTMPTkipAppendByte(pTkip, 0 ); + // and then zeroes until the length is a multiple of 4 + while( pTkip->nBytesInM != 0 ) + { + RTMPTkipAppendByte(pTkip, 0 ); + } + // The appendByte function has already computed the result. + RTMPTkipPutUInt32(pTkip->MIC, pTkip->L); + RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R); +} + +/* + ======================================================================== + + Routine Description: + Init Tkip function. + + Arguments: + pAd Pointer to our adapter + pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. + KeyId TK Key ID + pTA Pointer to transmitter address + pMICKey pointer to MIC Key + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPInitTkipEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyId, + IN PUCHAR pTA, + IN PUCHAR pMICKey, + IN PUCHAR pTSC, + OUT PULONG pIV16, + OUT PULONG pIV32) +{ + TKIP_IV tkipIv; + + // Prepare 8 bytes TKIP encapsulation for MPDU + NdisZeroMemory(&tkipIv, sizeof(TKIP_IV)); + tkipIv.IV16.field.rc0 = *(pTSC + 1); + tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f; + tkipIv.IV16.field.rc2 = *pTSC; + tkipIv.IV16.field.CONTROL.field.ExtIV = 1; // 0: non-extended IV, 1: an extended IV + tkipIv.IV16.field.CONTROL.field.KeyID = KeyId; +// tkipIv.IV32 = *(PULONG)(pTSC + 2); + NdisMoveMemory(&tkipIv.IV32, (pTSC + 2), 4); // Copy IV + + *pIV16 = tkipIv.IV16.word; + *pIV32 = tkipIv.IV32; +} + +/* + ======================================================================== + + Routine Description: + Init MIC Value calculation function which include set MIC key & + calculate first 16 bytes (DA + SA + priority + 0) + + Arguments: + pAd Pointer to our adapter + pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPInitMICEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UCHAR UserPriority, + IN PUCHAR pMICKey) +{ + ULONG Priority = UserPriority; + + // Init MIC value calculation + RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey); + // DA + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN); + // SA + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN); + // Priority + 3 bytes of 0 + RTMPTkipAppend(&pAd->PrivateInfo.Tx, (PUCHAR)&Priority, 4); +} + +/* + ======================================================================== + + Routine Description: + Compare MIC value of received MSDU + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to the received Plain text data + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + Len the length of the received plain text data exclude MIC value + + Return Value: + TRUE MIC value matched + FALSE MIC value mismatched + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPTkipCompareMICValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UCHAR UserPriority, + IN UINT Len) +{ + UCHAR OldMic[8]; + ULONG Priority = UserPriority; + + // Init MIC value calculation + RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); + // DA + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); + // SA + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); + // Priority + 3 bytes of 0 + RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4); + + // Calculate MIC value from plain text data + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); + + // Get MIC valude from received frame + NdisMoveMemory(OldMic, pSrc + Len, 8); + + // Get MIC value from decrypted plain data + RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); + + // Move MIC value from MSDU, this steps should move to data path. + // Since the MIC value might cross MPDUs. + if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); //MIC error. + + + return (FALSE); + } + return (TRUE); +} + +/* + ======================================================================== + + Routine Description: + Compare MIC value of received MSDU + + Arguments: + pAd Pointer to our adapter + pLLC LLC header + pSrc Pointer to the received Plain text data + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + Len the length of the received plain text data exclude MIC value + + Return Value: + TRUE MIC value matched + FALSE MIC value mismatched + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPTkipCompareMICValueWithLLC( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pLLC, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UINT Len) +{ + UCHAR OldMic[8]; + ULONG Priority = 0; + + // Init MIC value calculation + RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); + // DA + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); + // SA + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); + // Priority + 3 bytes of 0 + RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4); + + // Start with LLC header + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pLLC, 8); + + // Calculate MIC value from plain text data + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); + + // Get MIC valude from received frame + NdisMoveMemory(OldMic, pSrc + Len, 8); + + // Get MIC value from decrypted plain data + RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); + + // Move MIC value from MSDU, this steps should move to data path. + // Since the MIC value might cross MPDUs. + if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValueWithLLC(): TKIP MIC Error !\n")); //MIC error. + + + return (FALSE); + } + return (TRUE); +} +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware transmit function + + Arguments: + pAd Pointer to our adapter + PNDIS_PACKET Pointer to Ndis Packet for MIC calculation + pEncap Pointer to LLC encap data + LenEncap Total encap length, might be 0 which indicates no encap + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPCalculateMICValue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pEncap, + IN PCIPHER_KEY pKey, + IN UCHAR apidx) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + PUCHAR pSrc; + UCHAR UserPriority; + UCHAR vlan_offset = 0; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + UserPriority = RTMP_GET_PACKET_UP(pPacket); + pSrc = pSrcBufVA; + + // determine if this is a vlan packet + if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100) + vlan_offset = 4; + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + { + RTMPInitMICEngine( + pAd, + pKey->Key, + pSrc, + pSrc + 6, + UserPriority, + pKey->TxMic); + } + + + if (pEncap != NULL) + { + // LLC encapsulation + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6); + // Protocol Type + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, 2); + } + SrcBufLen -= (14 + vlan_offset); + pSrc += (14 + vlan_offset); + do + { + if (SrcBufLen > 0) + { + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen); + } + + break; // No need handle next packet + + } while (TRUE); // End of copying payload + + // Compute the final MIC Value + RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); +} + + +/************************************************************/ +/* tkip_sbox() */ +/* Returns a 16 bit value from a 64K entry table. The Table */ +/* is synthesized from two 256 entry byte wide tables. */ +/************************************************************/ + +UINT tkip_sbox(UINT index) +{ + UINT index_low; + UINT index_high; + UINT left, right; + + index_low = (index % 256); + index_high = ((index >> 8) % 256); + + left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256); + right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256); + + return (left ^ right); +} + +UINT rotr1(UINT a) +{ + unsigned int b; + + if ((a & 0x01) == 0x01) + { + b = (a >> 1) | 0x8000; + } + else + { + b = (a >> 1) & 0x7fff; + } + b = b % 65536; + return b; +} + +VOID RTMPTkipMixKey( + UCHAR *key, + UCHAR *ta, + ULONG pnl, /* Least significant 16 bits of PN */ + ULONG pnh, /* Most significant 32 bits of PN */ + UCHAR *rc4key, + UINT *p1k) +{ + + UINT tsc0; + UINT tsc1; + UINT tsc2; + + UINT ppk0; + UINT ppk1; + UINT ppk2; + UINT ppk3; + UINT ppk4; + UINT ppk5; + + INT i; + INT j; + + tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ + tsc1 = (unsigned int)(pnh % 65536); + tsc2 = (unsigned int)(pnl % 65536); /* lsb */ + + /* Phase 1, step 1 */ + p1k[0] = tsc1; + p1k[1] = tsc0; + p1k[2] = (UINT)(ta[0] + (ta[1]*256)); + p1k[3] = (UINT)(ta[2] + (ta[3]*256)); + p1k[4] = (UINT)(ta[4] + (ta[5]*256)); + + /* Phase 1, step 2 */ + for (i=0; i<8; i++) + { + j = 2*(i & 1); + p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*key[1+j]) + key[j])) % 65536 )) % 65536; + p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*key[5+j]) + key[4+j])) % 65536 )) % 65536; + p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*key[9+j]) + key[8+j])) % 65536 )) % 65536; + p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*key[13+j]) + key[12+j])) % 65536 )) % 65536; + p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*key[1+j]) + key[j]))) % 65536 )) % 65536; + p1k[4] = (p1k[4] + i) % 65536; + } + + /* Phase 2, Step 1 */ + ppk0 = p1k[0]; + ppk1 = p1k[1]; + ppk2 = p1k[2]; + ppk3 = p1k[3]; + ppk4 = p1k[4]; + ppk5 = (p1k[4] + tsc2) % 65536; + + /* Phase2, Step 2 */ + ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*key[1]) + key[0])) % 65536); + ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*key[3]) + key[2])) % 65536); + ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*key[5]) + key[4])) % 65536); + ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*key[7]) + key[6])) % 65536); + ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*key[9]) + key[8])) % 65536); + ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*key[11]) + key[10])) % 65536); + + ppk0 = ppk0 + rotr1(ppk5 ^ ((256*key[13]) + key[12])); + ppk1 = ppk1 + rotr1(ppk0 ^ ((256*key[15]) + key[14])); + ppk2 = ppk2 + rotr1(ppk1); + ppk3 = ppk3 + rotr1(ppk2); + ppk4 = ppk4 + rotr1(ppk3); + ppk5 = ppk5 + rotr1(ppk4); + + /* Phase 2, Step 3 */ + /* Phase 2, Step 3 */ + + tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ + tsc1 = (unsigned int)(pnh % 65536); + tsc2 = (unsigned int)(pnl % 65536); /* lsb */ + + rc4key[0] = (tsc2 >> 8) % 256; + rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f; + rc4key[2] = tsc2 % 256; + rc4key[3] = ((ppk5 ^ ((256*key[1]) + key[0])) >> 1) % 256; + + rc4key[4] = ppk0 % 256; + rc4key[5] = (ppk0 >> 8) % 256; + + rc4key[6] = ppk1 % 256; + rc4key[7] = (ppk1 >> 8) % 256; + + rc4key[8] = ppk2 % 256; + rc4key[9] = (ppk2 >> 8) % 256; + + rc4key[10] = ppk3 % 256; + rc4key[11] = (ppk3 >> 8) % 256; + + rc4key[12] = ppk4 % 256; + rc4key[13] = (ppk4 >> 8) % 256; + + rc4key[14] = ppk5 % 256; + rc4key[15] = (ppk5 >> 8) % 256; +} + + +/************************************************/ +/* construct_mic_header1() */ +/* Builds the first MIC header block from */ +/* header fields. */ +/************************************************/ + +void construct_mic_header1( + unsigned char *mic_header1, + int header_length, + unsigned char *mpdu) +{ + mic_header1[0] = (unsigned char)((header_length - 2) / 256); + mic_header1[1] = (unsigned char)((header_length - 2) % 256); + mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ + mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ + mic_header1[4] = mpdu[4]; /* A1 */ + mic_header1[5] = mpdu[5]; + mic_header1[6] = mpdu[6]; + mic_header1[7] = mpdu[7]; + mic_header1[8] = mpdu[8]; + mic_header1[9] = mpdu[9]; + mic_header1[10] = mpdu[10]; /* A2 */ + mic_header1[11] = mpdu[11]; + mic_header1[12] = mpdu[12]; + mic_header1[13] = mpdu[13]; + mic_header1[14] = mpdu[14]; + mic_header1[15] = mpdu[15]; +} + +/************************************************/ +/* construct_mic_header2() */ +/* Builds the last MIC header block from */ +/* header fields. */ +/************************************************/ + +void construct_mic_header2( + unsigned char *mic_header2, + unsigned char *mpdu, + int a4_exists, + int qc_exists) +{ + int i; + + for (i = 0; i<16; i++) mic_header2[i]=0x00; + + mic_header2[0] = mpdu[16]; /* A3 */ + mic_header2[1] = mpdu[17]; + mic_header2[2] = mpdu[18]; + mic_header2[3] = mpdu[19]; + mic_header2[4] = mpdu[20]; + mic_header2[5] = mpdu[21]; + + // In Sequence Control field, mute sequence numer bits (12-bit) + mic_header2[6] = mpdu[22] & 0x0f; /* SC */ + mic_header2[7] = 0x00; /* mpdu[23]; */ + + if ((!qc_exists) & a4_exists) + { + for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + + } + + if (qc_exists && (!a4_exists)) + { + mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ + mic_header2[9] = mpdu[25] & 0x00; + } + + if (qc_exists && a4_exists) + { + for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + + mic_header2[14] = mpdu[30] & 0x0f; + mic_header2[15] = mpdu[31] & 0x00; + } +} + + +/************************************************/ +/* construct_mic_iv() */ +/* Builds the MIC IV from header fields and PN */ +/************************************************/ + +void construct_mic_iv( + unsigned char *mic_iv, + int qc_exists, + int a4_exists, + unsigned char *mpdu, + unsigned int payload_length, + unsigned char *pn_vector) +{ + int i; + + mic_iv[0] = 0x59; + if (qc_exists && a4_exists) + mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ + if (qc_exists && !a4_exists) + mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ + if (!qc_exists) + mic_iv[1] = 0x00; + for (i = 2; i < 8; i++) + mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ +#ifdef CONSISTENT_PN_ORDER + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */ +#else + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ +#endif + i = (payload_length / 256); + i = (payload_length % 256); + mic_iv[14] = (unsigned char) (payload_length / 256); + mic_iv[15] = (unsigned char) (payload_length % 256); + +} + + + +/************************************/ +/* bitwise_xor() */ +/* A 128 bit, bitwise exclusive or */ +/************************************/ + +void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out) +{ + int i; + for (i=0; i<16; i++) + { + out[i] = ina[i] ^ inb[i]; + } +} + + +void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext) +{ + int round; + int i; + unsigned char intermediatea[16]; + unsigned char intermediateb[16]; + unsigned char round_key[16]; + + for(i=0; i<16; i++) round_key[i] = key[i]; + + for (round = 0; round < 11; round++) + { + if (round == 0) + { + xor_128(round_key, data, ciphertext); + next_key(round_key, round); + } + else if (round == 10) + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + xor_128(intermediateb, round_key, ciphertext); + } + else /* 1 - 9 */ + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + mix_column(&intermediateb[0], &intermediatea[0]); + mix_column(&intermediateb[4], &intermediatea[4]); + mix_column(&intermediateb[8], &intermediatea[8]); + mix_column(&intermediateb[12], &intermediatea[12]); + xor_128(intermediatea, round_key, ciphertext); + next_key(round_key, round); + } + } + +} + +void construct_ctr_preload( + unsigned char *ctr_preload, + int a4_exists, + int qc_exists, + unsigned char *mpdu, + unsigned char *pn_vector, + int c) +{ + + int i = 0; + for (i=0; i<16; i++) ctr_preload[i] = 0x00; + i = 0; + + ctr_preload[0] = 0x01; /* flag */ + if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ + if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f; + + for (i = 2; i < 8; i++) + ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ +#ifdef CONSISTENT_PN_ORDER + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */ +#else + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ +#endif + ctr_preload[14] = (unsigned char) (c / 256); // Ctr + ctr_preload[15] = (unsigned char) (c % 256); + +} + + +// +// TRUE: Success! +// FALSE: Decrypt Error! +// +BOOLEAN RTMPSoftDecryptTKIP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN UCHAR UserPriority, + IN PCIPHER_KEY pWpaKey) +{ + UCHAR KeyID; + UINT HeaderLen; + UCHAR fc0; + UCHAR fc1; + USHORT fc; + UINT frame_type; + UINT frame_subtype; + UINT from_ds; + UINT to_ds; + INT a4_exists; + INT qc_exists; + USHORT duration; + USHORT seq_control; + USHORT qos_control; + UCHAR TA[MAC_ADDR_LEN]; + UCHAR DA[MAC_ADDR_LEN]; + UCHAR SA[MAC_ADDR_LEN]; + UCHAR RC4Key[16]; + UINT p1k[5]; //for mix_key; + ULONG pnl;/* Least significant 16 bits of PN */ + ULONG pnh;/* Most significant 32 bits of PN */ + UINT num_blocks; + UINT payload_remainder; + ARCFOURCONTEXT ArcFourContext; + UINT crc32 = 0; + UINT trailfcs = 0; + UCHAR MIC[8]; + UCHAR TrailMIC[8]; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + + fc0 = *pData; + fc1 = *(pData + 1); + + fc = *((PUSHORT)pData); + + frame_type = ((fc0 >> 2) & 0x03); + frame_subtype = ((fc0 >> 4) & 0x0f); + + from_ds = (fc1 & 0x2) >> 1; + to_ds = (fc1 & 0x1); + + a4_exists = (from_ds & to_ds); + qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ + (frame_subtype == 0x09) || /* Likely to change. */ + (frame_subtype == 0x0a) || + (frame_subtype == 0x0b) + ); + + HeaderLen = 24; + if (a4_exists) + HeaderLen += 6; + + KeyID = *((PUCHAR)(pData+ HeaderLen + 3)); + KeyID = KeyID >> 6; + + if (pWpaKey[KeyID].KeyLen == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP failed!(KeyID[%d] Length can not be 0)\n", KeyID)); + return FALSE; + } + + duration = *((PUSHORT)(pData+2)); + + seq_control = *((PUSHORT)(pData+22)); + + if (qc_exists) + { + if (a4_exists) + { + qos_control = *((PUSHORT)(pData+30)); + } + else + { + qos_control = *((PUSHORT)(pData+24)); + } + } + + if (to_ds == 0 && from_ds == 1) + { + NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN); + NdisMoveMemory(SA, pData+16, MAC_ADDR_LEN); + NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); //BSSID + } + else if (to_ds == 0 && from_ds == 0 ) + { + NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); + NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN); + NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN); + } + else if (to_ds == 1 && from_ds == 0) + { + NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN); + NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); + NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN); + } + else if (to_ds == 1 && from_ds == 1) + { + NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); + NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN); + NdisMoveMemory(SA, pData+22, MAC_ADDR_LEN); + } + + num_blocks = (DataByteCnt - 16) / 16; + payload_remainder = (DataByteCnt - 16) % 16; + + pnl = (*(pData + HeaderLen)) * 256 + *(pData + HeaderLen + 2); + pnh = *((PULONG)(pData + HeaderLen + 4)); + pnh = cpu2le32(pnh); + RTMPTkipMixKey(pWpaKey[KeyID].Key, TA, pnl, pnh, RC4Key, p1k); + + ARCFOUR_INIT(&ArcFourContext, RC4Key, 16); + + ARCFOUR_DECRYPT(&ArcFourContext, pData + HeaderLen, pData + HeaderLen + 8, DataByteCnt - HeaderLen - 8); + NdisMoveMemory(&trailfcs, pData + DataByteCnt - 8 - 4, 4); + crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 4); //Skip IV+EIV 8 bytes & Skip last 4 bytes(FCS). + crc32 ^= 0xffffffff; /* complement */ + + if(crc32 != cpu2le32(trailfcs)) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP, WEP Data ICV Error !\n")); //ICV error. + + return (FALSE); + } + + NdisMoveMemory(TrailMIC, pData + DataByteCnt - 8 - 8 - 4, 8); + RTMPInitMICEngine(pAd, pWpaKey[KeyID].Key, DA, SA, UserPriority, pWpaKey[KeyID].RxMic); + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 12); + RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); + NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, 8); + + if (!NdisEqualMemory(MIC, TrailMIC, 8)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptTKIP, WEP Data MIC Error !\n")); //MIC error. + //RTMPReportMicError(pAd, &pWpaKey[KeyID]); // marked by AlbertY @ 20060630 + return (FALSE); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + //DBGPRINT(RT_DEBUG_TRACE, "RTMPSoftDecryptTKIP Decript done!!\n"); + return TRUE; +} + + + + +BOOLEAN RTMPSoftDecryptAES( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pWpaKey) +{ + UCHAR KeyID; + UINT HeaderLen; + UCHAR PN[6]; + UINT payload_len; + UINT num_blocks; + UINT payload_remainder; + USHORT fc; + UCHAR fc0; + UCHAR fc1; + UINT frame_type; + UINT frame_subtype; + UINT from_ds; + UINT to_ds; + INT a4_exists; + INT qc_exists; + UCHAR aes_out[16]; + int payload_index; + UINT i; + UCHAR ctr_preload[16]; + UCHAR chain_buffer[16]; + UCHAR padded_buffer[16]; + UCHAR mic_iv[16]; + UCHAR mic_header1[16]; + UCHAR mic_header2[16]; + UCHAR MIC[8]; + UCHAR TrailMIC[8]; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + + fc0 = *pData; + fc1 = *(pData + 1); + + fc = *((PUSHORT)pData); + + frame_type = ((fc0 >> 2) & 0x03); + frame_subtype = ((fc0 >> 4) & 0x0f); + + from_ds = (fc1 & 0x2) >> 1; + to_ds = (fc1 & 0x1); + + a4_exists = (from_ds & to_ds); + qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */ + (frame_subtype == 0x09) || /* Likely to change. */ + (frame_subtype == 0x0a) || + (frame_subtype == 0x0b) + ); + + HeaderLen = 24; + if (a4_exists) + HeaderLen += 6; + + KeyID = *((PUCHAR)(pData+ HeaderLen + 3)); + KeyID = KeyID >> 6; + + if (pWpaKey[KeyID].KeyLen == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptAES failed!(KeyID[%d] Length can not be 0)\n", KeyID)); + return FALSE; + } + + PN[0] = *(pData+ HeaderLen); + PN[1] = *(pData+ HeaderLen + 1); + PN[2] = *(pData+ HeaderLen + 4); + PN[3] = *(pData+ HeaderLen + 5); + PN[4] = *(pData+ HeaderLen + 6); + PN[5] = *(pData+ HeaderLen + 7); + + payload_len = DataByteCnt - HeaderLen - 8 - 8; // 8 bytes for CCMP header , 8 bytes for MIC + payload_remainder = (payload_len) % 16; + num_blocks = (payload_len) / 16; + + + + // Find start of payload + payload_index = HeaderLen + 8; //IV+EIV + + for (i=0; i< num_blocks; i++) + { + construct_ctr_preload(ctr_preload, + a4_exists, + qc_exists, + pData, + PN, + i+1 ); + + aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); + + bitwise_xor(aes_out, pData + payload_index, chain_buffer); + NdisMoveMemory(pData + payload_index - 8, chain_buffer, 16); + payload_index += 16; + } + + // + // If there is a short final block, then pad it + // encrypt it and copy the unpadded part back + // + if (payload_remainder > 0) + { + construct_ctr_preload(ctr_preload, + a4_exists, + qc_exists, + pData, + PN, + num_blocks + 1); + + NdisZeroMemory(padded_buffer, 16); + NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); + + aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); + + bitwise_xor(aes_out, padded_buffer, chain_buffer); + NdisMoveMemory(pData + payload_index - 8, chain_buffer, payload_remainder); + payload_index += payload_remainder; + } + + // + // Descrypt the MIC + // + construct_ctr_preload(ctr_preload, + a4_exists, + qc_exists, + pData, + PN, + 0); + NdisZeroMemory(padded_buffer, 16); + NdisMoveMemory(padded_buffer, pData + payload_index, 8); + + aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out); + + bitwise_xor(aes_out, padded_buffer, chain_buffer); + + NdisMoveMemory(TrailMIC, chain_buffer, 8); + + // + // Calculate MIC + // + + //Force the protected frame bit on + *(pData + 1) = *(pData + 1) | 0x40; + + // Find start of payload + // Because the CCMP header has been removed + payload_index = HeaderLen; + + construct_mic_iv( + mic_iv, + qc_exists, + a4_exists, + pData, + payload_len, + PN); + + construct_mic_header1( + mic_header1, + HeaderLen, + pData); + + construct_mic_header2( + mic_header2, + pData, + a4_exists, + qc_exists); + + aes128k128d(pWpaKey[KeyID].Key, mic_iv, aes_out); + bitwise_xor(aes_out, mic_header1, chain_buffer); + aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); + bitwise_xor(aes_out, mic_header2, chain_buffer); + aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); + + // iterate through each 16 byte payload block + for (i = 0; i < num_blocks; i++) + { + bitwise_xor(aes_out, pData + payload_index, chain_buffer); + payload_index += 16; + aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); + } + + // Add on the final payload block if it needs padding + if (payload_remainder > 0) + { + NdisZeroMemory(padded_buffer, 16); + NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder); + + bitwise_xor(aes_out, padded_buffer, chain_buffer); + aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out); + } + + // aes_out contains padded mic, discard most significant + // 8 bytes to generate 64 bit MIC + for (i = 0 ; i < 8; i++) MIC[i] = aes_out[i]; + + if (!NdisEqualMemory(MIC, TrailMIC, 8)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n")); //MIC error. + return FALSE; + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE); +#endif + + return TRUE; +} + +/****************************************/ +/* aes128k128d() */ +/* Performs a 128 bit AES encrypt with */ +/* 128 bit data. */ +/****************************************/ +VOID xor_128( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out) +{ + INT i; + + for (i=0;i<16; i++) + { + out[i] = a[i] ^ b[i]; + } +} + +VOID next_key( + IN PUCHAR key, + IN INT round) +{ + UCHAR rcon; + UCHAR sbox_key[4]; + UCHAR rcon_table[12] = + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x36, 0x36 + }; + + sbox_key[0] = RTMPCkipSbox(key[13]); + sbox_key[1] = RTMPCkipSbox(key[14]); + sbox_key[2] = RTMPCkipSbox(key[15]); + sbox_key[3] = RTMPCkipSbox(key[12]); + + rcon = rcon_table[round]; + + xor_32(&key[0], sbox_key, &key[0]); + key[0] = key[0] ^ rcon; + + xor_32(&key[4], &key[0], &key[4]); + xor_32(&key[8], &key[4], &key[8]); + xor_32(&key[12], &key[8], &key[12]); +} + +VOID xor_32( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out) +{ + INT i; + + for (i=0;i<4; i++) + { + out[i] = a[i] ^ b[i]; + } +} + +VOID byte_sub( + IN PUCHAR in, + OUT PUCHAR out) +{ + INT i; + + for (i=0; i< 16; i++) + { + out[i] = RTMPCkipSbox(in[i]); + } +} + +UCHAR RTMPCkipSbox( + IN UCHAR a) +{ + return SboxTable[(int)a]; +} + +VOID shift_row( + IN PUCHAR in, + OUT PUCHAR out) +{ + out[0] = in[0]; + out[1] = in[5]; + out[2] = in[10]; + out[3] = in[15]; + out[4] = in[4]; + out[5] = in[9]; + out[6] = in[14]; + out[7] = in[3]; + out[8] = in[8]; + out[9] = in[13]; + out[10] = in[2]; + out[11] = in[7]; + out[12] = in[12]; + out[13] = in[1]; + out[14] = in[6]; + out[15] = in[11]; +} + +VOID mix_column( + IN PUCHAR in, + OUT PUCHAR out) +{ + INT i; + UCHAR add1b[4]; + UCHAR add1bf7[4]; + UCHAR rotl[4]; + UCHAR swap_halfs[4]; + UCHAR andf7[4]; + UCHAR rotr[4]; + UCHAR temp[4]; + UCHAR tempb[4]; + + for (i=0 ; i<4; i++) + { + if ((in[i] & 0x80)== 0x80) + add1b[i] = 0x1b; + else + add1b[i] = 0x00; + } + + swap_halfs[0] = in[2]; /* Swap halfs */ + swap_halfs[1] = in[3]; + swap_halfs[2] = in[0]; + swap_halfs[3] = in[1]; + + rotl[0] = in[3]; /* Rotate left 8 bits */ + rotl[1] = in[0]; + rotl[2] = in[1]; + rotl[3] = in[2]; + + andf7[0] = in[0] & 0x7f; + andf7[1] = in[1] & 0x7f; + andf7[2] = in[2] & 0x7f; + andf7[3] = in[3] & 0x7f; + + for (i = 3; i>0; i--) /* logical shift left 1 bit */ + { + andf7[i] = andf7[i] << 1; + if ((andf7[i-1] & 0x80) == 0x80) + { + andf7[i] = (andf7[i] | 0x01); + } + } + andf7[0] = andf7[0] << 1; + andf7[0] = andf7[0] & 0xfe; + + xor_32(add1b, andf7, add1bf7); + + xor_32(in, add1bf7, rotr); + + temp[0] = rotr[0]; /* Rotate right 8 bits */ + rotr[0] = rotr[1]; + rotr[1] = rotr[2]; + rotr[2] = rotr[3]; + rotr[3] = temp[0]; + + xor_32(add1bf7, rotr, temp); + xor_32(swap_halfs, rotl,tempb); + xor_32(temp, tempb, out); +} + diff --git a/drivers/staging/rt3070/common/rtmp_wep.c b/drivers/staging/rt3070/common/rtmp_wep.c new file mode 100644 index 000000000000..f5f0a3bb17eb --- /dev/null +++ b/drivers/staging/rt3070/common/rtmp_wep.c @@ -0,0 +1,508 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtmp_wep.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Wu 10-28-02 Initial +*/ + +#include "../rt_config.h" + +UINT FCSTAB_32[256] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +/* +UCHAR WEPKEY[] = { + //IV + 0x00, 0x11, 0x22, + //WEP KEY + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC + }; + */ + +/* + ======================================================================== + + Routine Description: + Init WEP function. + + Arguments: + pAd Pointer to our adapter + pKey Pointer to the WEP KEY + KeyId WEP Key ID + KeyLen the length of WEP KEY + pDest Pointer to the destination which Encryption data will store in. + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPInitWepEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyId, + IN UCHAR KeyLen, + IN OUT PUCHAR pDest) +{ + UINT i; + UCHAR WEPKEY[] = { + //IV + 0x00, 0x11, 0x22, + //WEP KEY + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC + }; + + pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32. + +#ifdef CONFIG_STA_SUPPORT + if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10) && (pAd->OpMode == OPMODE_STA)) + { + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, pKey, KeyLen); //INIT SBOX, KEYLEN+3(IV) + NdisMoveMemory(pDest, pKey, 3); //Append Init Vector + } + else +#endif // CONFIG_STA_SUPPORT // + { + NdisMoveMemory(WEPKEY + 3, pKey, KeyLen); + + for(i = 0; i < 3; i++) + WEPKEY[i] = RandomByte(pAd); //Call mlme RandomByte() function. + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, KeyLen + 3); //INIT SBOX, KEYLEN+3(IV) + + NdisMoveMemory(pDest, WEPKEY, 3); //Append Init Vector + } + *(pDest+3) = (KeyId << 6); //Append KEYID + +} + +/* + ======================================================================== + + Routine Description: + Encrypt transimitted data + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to the transimitted source data that will be encrypt + pDest Pointer to the destination where entryption data will be store in. + Len Indicate the length of the source data + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPEncryptData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDest, + IN UINT Len) +{ + pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, pSrc, Len); + ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, pSrc, Len); +} + + +/* + ======================================================================== + + Routine Description: + Decrypt received WEP data + + Arguments: + pAdapter Pointer to our adapter + pSrc Pointer to the received data + Len the length of the received data + + Return Value: + TRUE Decrypt WEP data success + FALSE Decrypt WEP data failed + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPSoftDecryptWEP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pGroupKey) +{ + UINT trailfcs; + UINT crc32; + UCHAR KeyIdx; + UCHAR WEPKEY[] = { + //IV + 0x00, 0x11, 0x22, + //WEP KEY + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC + }; + UCHAR *pPayload = (UCHAR *)pData + LENGTH_802_11; + ULONG payload_len = DataByteCnt - LENGTH_802_11; + + NdisMoveMemory(WEPKEY, pPayload, 3); //Get WEP IV + + KeyIdx = (*(pPayload + 3) & 0xc0) >> 6; + if (pGroupKey[KeyIdx].KeyLen == 0) + return (FALSE); + + NdisMoveMemory(WEPKEY + 3, pGroupKey[KeyIdx].Key, pGroupKey[KeyIdx].KeyLen); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, pGroupKey[KeyIdx].KeyLen + 3); + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, pPayload, pPayload + 4, payload_len - 4); + NdisMoveMemory(&trailfcs, pPayload + payload_len - 8, 4); + crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pPayload, payload_len - 8); //Skip last 4 bytes(FCS). + crc32 ^= 0xffffffff; /* complement */ + + if(crc32 != cpu2le32(trailfcs)) + { + DBGPRINT(RT_DEBUG_TRACE, ("! WEP Data CRC Error !\n")); //CRC error. + return (FALSE); + } + return (TRUE); +} + +/* + ======================================================================== + + Routine Description: + The Stream Cipher Encryption Algorithm "ARCFOUR" initialize + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + pKey Pointer to the WEP KEY + KeyLen Indicate the length fo the WEP KEY + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID ARCFOUR_INIT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pKey, + IN UINT KeyLen) +{ + UCHAR t, u; + UINT keyindex; + UINT stateindex; + PUCHAR state; + UINT counter; + + state = Ctx->STATE; + Ctx->X = 0; + Ctx->Y = 0; + for (counter = 0; counter < 256; counter++) + state[counter] = (UCHAR)counter; + keyindex = 0; + stateindex = 0; + for (counter = 0; counter < 256; counter++) + { + t = state[counter]; + stateindex = (stateindex + pKey[keyindex] + t) & 0xff; + u = state[stateindex]; + state[stateindex] = t; + state[counter] = u; + if (++keyindex >= KeyLen) + keyindex = 0; + } +} + +/* + ======================================================================== + + Routine Description: + Get bytes from ARCFOUR CONTEXT (S-BOX) + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + + Return Value: + UCHAR - the value of the ARCFOUR CONTEXT (S-BOX) + + Note: + + ======================================================================== +*/ +UCHAR ARCFOUR_BYTE( + IN PARCFOURCONTEXT Ctx) +{ + UINT x; + UINT y; + UCHAR sx, sy; + PUCHAR state; + + state = Ctx->STATE; + x = (Ctx->X + 1) & 0xff; + sx = state[x]; + y = (sx + Ctx->Y) & 0xff; + sy = state[y]; + Ctx->X = x; + Ctx->Y = y; + state[y] = sx; + state[x] = sy; + + return(state[(sx + sy) & 0xff]); + +} + +/* + ======================================================================== + + Routine Description: + The Stream Cipher Decryption Algorithm + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + pDest Pointer to the Destination + pSrc Pointer to the Source data + Len Indicate the length of the Source data + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ARCFOUR_DECRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len) +{ + UINT i; + + for (i = 0; i < Len; i++) + pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); +} + +/* + ======================================================================== + + Routine Description: + The Stream Cipher Encryption Algorithm + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + pDest Pointer to the Destination + pSrc Pointer to the Source data + Len Indicate the length of the Source dta + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID ARCFOUR_ENCRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len) +{ + UINT i; + + for (i = 0; i < Len; i++) + pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); +} + +/* + ======================================================================== + + Routine Description: + The Stream Cipher Encryption Algorithm which conform to the special requirement to encrypt GTK. + + Arguments: + Ctx Pointer to ARCFOUR CONTEXT (SBOX) + pDest Pointer to the Destination + pSrc Pointer to the Source data + Len Indicate the length of the Source dta + + + ======================================================================== +*/ + +VOID WPAARCFOUR_ENCRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len) +{ + UINT i; + //discard first 256 bytes + for (i = 0; i < 256; i++) + ARCFOUR_BYTE(Ctx); + + for (i = 0; i < Len; i++) + pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx); +} + + +/* + ======================================================================== + + Routine Description: + Calculate a new FCS given the current FCS and the new data. + + Arguments: + Fcs the original FCS value + Cp pointer to the data which will be calculate the FCS + Len the length of the data + + Return Value: + UINT - FCS 32 bits + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +UINT RTMP_CALC_FCS32( + IN UINT Fcs, + IN PUCHAR Cp, + IN INT Len) +{ + while (Len--) + Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]); + + return (Fcs); +} + + +/* + ======================================================================== + + Routine Description: + Get last FCS and encrypt it to the destination + + Arguments: + pDest Pointer to the Destination + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPSetICV( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDest) +{ + pAd->PrivateInfo.FCSCRC32 ^= 0xffffffff; /* complement */ + pAd->PrivateInfo.FCSCRC32 = cpu2le32(pAd->PrivateInfo.FCSCRC32); + + ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, (PUCHAR) &pAd->PrivateInfo.FCSCRC32, 4); +} + diff --git a/drivers/staging/rt3070/common/rtusb_bulk.c b/drivers/staging/rt3070/common/rtusb_bulk.c new file mode 100644 index 000000000000..1a05703520fc --- /dev/null +++ b/drivers/staging/rt3070/common/rtusb_bulk.c @@ -0,0 +1,1382 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtusb_bulk.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 06-25-2004 created + +*/ + +#include "../rt_config.h" +// Match total 6 bulkout endpoint to corresponding queue. +UCHAR EpToQueue[6]={FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_MGMT}; + +//static BOOLEAN SingleBulkOut = FALSE; + +void RTUSB_FILL_BULK_URB (struct urb *pUrb, + struct usb_device *pUsb_Dev, + unsigned int bulkpipe, + void *pTransferBuf, + int BufSize, + usb_complete_t Complete, + void *pContext) +{ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + usb_fill_bulk_urb(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, (usb_complete_t)Complete, pContext); +#else + FILL_BULK_URB(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, Complete, pContext); +#endif + +} + +VOID RTUSBInitTxDesc( + IN PRTMP_ADAPTER pAd, + IN PTX_CONTEXT pTxContext, + IN UCHAR BulkOutPipeId, + IN usb_complete_t Func) +{ + PURB pUrb; + PUCHAR pSrc = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pUrb = pTxContext->pUrb; + ASSERT(pUrb); + + // Store BulkOut PipeId + pTxContext->BulkOutPipeId = BulkOutPipeId; + + if (pTxContext->bAggregatible) + { + pSrc = &pTxContext->TransferBuffer->Aggregation[2]; + } + else + { + pSrc = (PUCHAR) pTxContext->TransferBuffer->field.WirelessPacket; + } + + + //Initialize a tx bulk urb + RTUSB_FILL_BULK_URB(pUrb, + pObj->pUsb_Dev, + usb_sndbulkpipe(pObj->pUsb_Dev, pAd->BulkOutEpAddr[BulkOutPipeId]), + pSrc, + pTxContext->BulkOutSize, + Func, + pTxContext); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + if (pTxContext->bAggregatible) + pUrb->transfer_dma = (pTxContext->data_dma + TX_BUFFER_NORMSIZE + 2); + else + pUrb->transfer_dma = pTxContext->data_dma; + + pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + +} + +VOID RTUSBInitHTTxDesc( + IN PRTMP_ADAPTER pAd, + IN PHT_TX_CONTEXT pTxContext, + IN UCHAR BulkOutPipeId, + IN ULONG BulkOutSize, + IN usb_complete_t Func) +{ + PURB pUrb; + PUCHAR pSrc = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pUrb = pTxContext->pUrb; + ASSERT(pUrb); + + // Store BulkOut PipeId + pTxContext->BulkOutPipeId = BulkOutPipeId; + + pSrc = &pTxContext->TransferBuffer->field.WirelessPacket[pTxContext->NextBulkOutPosition]; + + + //Initialize a tx bulk urb + RTUSB_FILL_BULK_URB(pUrb, + pObj->pUsb_Dev, + usb_sndbulkpipe(pObj->pUsb_Dev, pAd->BulkOutEpAddr[BulkOutPipeId]), + pSrc, + BulkOutSize, + Func, + pTxContext); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + pUrb->transfer_dma = (pTxContext->data_dma + pTxContext->NextBulkOutPosition); + pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + +} + +VOID RTUSBInitRxDesc( + IN PRTMP_ADAPTER pAd, + IN PRX_CONTEXT pRxContext) +{ + PURB pUrb; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + ULONG RX_bulk_size; + + + pUrb = pRxContext->pUrb; + ASSERT(pUrb); + + if ( pAd->BulkInMaxPacketSize == 64) + RX_bulk_size = 4096; + else + RX_bulk_size = MAX_RXBULK_SIZE; + + //Initialize a rx bulk urb + RTUSB_FILL_BULK_URB(pUrb, + pObj->pUsb_Dev, + usb_rcvbulkpipe(pObj->pUsb_Dev, pAd->BulkInEpAddr), + &(pRxContext->TransferBuffer[pAd->NextRxBulkInPosition]), + RX_bulk_size - (pAd->NextRxBulkInPosition), + (usb_complete_t)RTUSBBulkRxComplete, + (void *)pRxContext); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + pUrb->transfer_dma = pRxContext->data_dma + pAd->NextRxBulkInPosition; + pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +#endif + + +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ + +#define BULK_OUT_LOCK(pLock, IrqFlags) \ + if(1 /*!(in_interrupt() & 0xffff0000)*/) \ + RTMP_IRQ_LOCK((pLock), IrqFlags); + +#define BULK_OUT_UNLOCK(pLock, IrqFlags) \ + if(1 /*!(in_interrupt() & 0xffff0000)*/) \ + RTMP_IRQ_UNLOCK((pLock), IrqFlags); + + +VOID RTUSBBulkOutDataPacket( + IN PRTMP_ADAPTER pAd, + IN UCHAR BulkOutPipeId, + IN UCHAR Index) +{ + + PHT_TX_CONTEXT pHTTXContext; + PURB pUrb; + int ret = 0; + PTXINFO_STRUC pTxInfo, pLastTxInfo = NULL; + PTXWI_STRUC pTxWI; + ULONG TmpBulkEndPos, ThisBulkSize; + unsigned long IrqFlags = 0, IrqFlags2 = 0; + PUCHAR pWirelessPkt, pAppendant; + BOOLEAN bTxQLastRound = FALSE; + UCHAR allzero[4]= {0x0,0x0,0x0,0x0}; + + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + if ((pAd->BulkOutPending[BulkOutPipeId] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) + { + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + return; + } + pAd->BulkOutPending[BulkOutPipeId] = TRUE; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) + ) + { + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + return; + } + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + + pHTTXContext = &(pAd->TxContext[BulkOutPipeId]); + + BULK_OUT_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); + if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) + || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition)) + { + BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); + + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + + // Clear Data flag + RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)); + RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); + + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + return; + } + + // Clear Data flag + RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)); + RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); + + //DBGPRINT(RT_DEBUG_TRACE,("BulkOut-B:I=0x%lx, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", in_interrupt(), + // pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, + // pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); + pHTTXContext->NextBulkOutPosition = pHTTXContext->ENextBulkOutPosition; + ThisBulkSize = 0; + TmpBulkEndPos = pHTTXContext->NextBulkOutPosition; + pWirelessPkt = &pHTTXContext->TransferBuffer->field.WirelessPacket[0]; + + if ((pHTTXContext->bCopySavePad == TRUE)) + { + if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR,("e1, allzero : %x %x %x %x %x %x %x %x \n", + pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3] + ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7])); + } + NdisMoveMemory(&pWirelessPkt[TmpBulkEndPos], pHTTXContext->SavedPad, 8); + pHTTXContext->bCopySavePad = FALSE; + if (pAd->bForcePrintTX == TRUE) + DBGPRINT(RT_DEBUG_TRACE,("RTUSBBulkOutDataPacket --> COPY PAD. CurWrite = %ld, NextBulk = %ld. ENextBulk = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition)); + } + + do + { + pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[TmpBulkEndPos]; + pTxWI = (PTXWI_STRUC)&pWirelessPkt[TmpBulkEndPos + TXINFO_SIZE]; + + if (pAd->bForcePrintTX == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkOutDataPacket AMPDU = %d.\n", pTxWI->AMPDU)); + + // add by Iverson, limit BulkOut size to 4k to pass WMM b mode 2T1R test items + //if ((ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) + if ((ThisBulkSize != 0) && (pTxWI->PHYMODE == MODE_CCK)) + { +#ifdef INF_AMAZON_SE + /*Iverson Add for AMAZON USB (RT2070 && RT3070) to pass WMM A2-T4 ~ A2-T10*/ + if(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) + { + /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate*/ + if(pTxWI->PacketId == 6) + { + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + else if (BulkOutPipeId == 1) + { + /*BK No Limit BulkOut size .*/ + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + else if (((ThisBulkSize&0xffff8000) != 0) || (((ThisBulkSize&0x1000) == 0x1000) && (BulkOutPipeId == 0) )) + { + /*BE Limit BulkOut size to about 4k bytes.*/ + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + else if (((ThisBulkSize&0xffff8000) != 0) || (((ThisBulkSize&0x1c00) == 0x1c00) && (BulkOutPipeId == 2) )) + { + /*VI Limit BulkOut size to about 7k bytes.*/ + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + else if (((ThisBulkSize&0xffff8000) != 0) || (((ThisBulkSize&0x2500) == 0x2500) && (BulkOutPipeId == 3) )) + { + /*VO Limit BulkOut size to about 9k bytes.*/ + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + } + else if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x1000) == 0x1000)) + { + /* Limit BulkOut size to about 4k bytes.*/ + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } +#else + if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x1000) == 0x1000)) + { + // Limit BulkOut size to about 4k bytes. + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } +#endif // INF_AMAZON_SE // + + else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0))*/) + { + // For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. + // For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + } + // end Iverson + else + { +#ifdef INF_AMAZON_SE +//#ifdef DOT11_N_SUPPORT +// if(((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000) || ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0))) +// { +// /* AMAZON_SE: BG mode Disable BulkOut Aggregate, N mode BulkOut Aggregaet size 24K */ +// pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; +// break; +// } +// else +//#endif // DOT11_N_SUPPORT // +// { + if(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && (pTxWI->AMPDU == 0)) + { + if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0)) || + (ThisBulkSize != 0)) + { + /* AMAZON_SE: RT2070 Disable BulkOut Aggregate when WMM for USB issue */ + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + } +/* + else if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000)) + { + // Limit BulkOut size to about 24k bytes. + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + } +*/ +#endif // INF_AMAZON_SE // + + if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000)) + { // Limit BulkOut size to about 24k bytes. + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + + else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0))*/) + { // For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. + // For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + } + + if (TmpBulkEndPos == pHTTXContext->CurWritePosition) + { + pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; + break; + } + //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (pTxInfo->QSEL != FIFO_EDCA) + { + printk("%s(): ====> pTxInfo->QueueSel(%d)!= FIFO_EDCA!!!!\n", __FUNCTION__, pTxInfo->QSEL); + printk("\tCWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad); + hex_dump("Wrong QSel Pkt:", (PUCHAR)&pWirelessPkt[TmpBulkEndPos], (pHTTXContext->CurWritePosition - pHTTXContext->NextBulkOutPosition)); + } + } +#endif // CONFIG_STA_SUPPORT // + + if (pTxInfo->USBDMATxPktLen <= 8) + { + BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); + DBGPRINT(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("e2, USBDMATxPktLen==0, Size=%ld, bCSPad=%d, CWPos=%ld, NBPos=%ld, CWRPos=%ld!\n", + pHTTXContext->BulkOutSize, pHTTXContext->bCopySavePad, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->CurWriteRealPos)); + { + DBGPRINT_RAW(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("%x %x %x %x %x %x %x %x \n", + pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3] + ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7])); + } + pAd->bForcePrintTX = TRUE; + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + //DBGPRINT(RT_DEBUG_LOUD,("Out:pTxInfo->USBDMATxPktLen=%d!\n", pTxInfo->USBDMATxPktLen)); + return; + } + + // Increase Total transmit byte counter + pAd->RalinkCounters.OneSecTransmittedByteCount += pTxWI->MPDUtotalByteCount; + pAd->RalinkCounters.TransmittedByteCount += pTxWI->MPDUtotalByteCount; + + pLastTxInfo = pTxInfo; + + // Make sure we use EDCA QUEUE. +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pTxInfo->QSEL = FIFO_EDCA; //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) +#endif // CONFIG_STA_SUPPORT // + ThisBulkSize += (pTxInfo->USBDMATxPktLen+4); + TmpBulkEndPos += (pTxInfo->USBDMATxPktLen+4); + + if (TmpBulkEndPos != pHTTXContext->CurWritePosition) + pTxInfo->USBDMANextVLD = 1; + + if (pTxInfo->SwUseLastRound == 1) + { + if (pHTTXContext->CurWritePosition == 8) + pTxInfo->USBDMANextVLD = 0; + pTxInfo->SwUseLastRound = 0; + + bTxQLastRound = TRUE; + pHTTXContext->ENextBulkOutPosition = 8; + + #ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO); + RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); + #endif // RT_BIG_ENDIAN // + + break; + } + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO); + RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); +#endif // RT_BIG_ENDIAN // + + }while (TRUE); + + // adjust the pTxInfo->USBDMANextVLD value of last pTxInfo. + if (pLastTxInfo) + { +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pLastTxInfo, TYPE_TXINFO); +#endif // RT_BIG_ENDIAN // + pLastTxInfo->USBDMANextVLD = 0; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pLastTxInfo, TYPE_TXINFO); +#endif // RT_BIG_ENDIAN // + } + + /* + We need to copy SavedPad when following condition matched! + 1. Not the last round of the TxQueue and + 2. any match of following cases: + (1). The End Position of this bulk out is reach to the Currenct Write position and + the TxInfo and related header already write to the CurWritePosition. + =>(ENextBulkOutPosition == CurWritePosition) && (CurWriteRealPos > CurWritePosition) + + (2). The EndPosition of the bulk out is not reach to the Current Write Position. + =>(ENextBulkOutPosition != CurWritePosition) + */ + if ((bTxQLastRound == FALSE) && + (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) && (pHTTXContext->CurWriteRealPos > pHTTXContext->CurWritePosition)) || + (pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition)) + ) + { + NdisMoveMemory(pHTTXContext->SavedPad, &pWirelessPkt[pHTTXContext->ENextBulkOutPosition], 8); + pHTTXContext->bCopySavePad = TRUE; + if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4)) + { + PUCHAR pBuf = &pHTTXContext->SavedPad[0]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("WARNING-Zero-3:%02x%02x%02x%02x%02x%02x%02x%02x,CWPos=%ld, CWRPos=%ld, bCW=%d, NBPos=%ld, TBPos=%ld, TBSize=%ld\n", + pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7], pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, + pHTTXContext->bCurWriting, pHTTXContext->NextBulkOutPosition, TmpBulkEndPos, ThisBulkSize)); + + pBuf = &pWirelessPkt[pHTTXContext->CurWritePosition]; + DBGPRINT_RAW(RT_DEBUG_ERROR,("\tCWPos=%02x%02x%02x%02x%02x%02x%02x%02x\n", pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7])); + } + //DBGPRINT(RT_DEBUG_LOUD,("ENPos==CWPos=%ld, CWRPos=%ld, bCSPad=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->bCopySavePad)); + } + + if (pAd->bForcePrintTX == TRUE) + DBGPRINT(RT_DEBUG_TRACE,("BulkOut-A:Size=%ld, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); + //DBGPRINT(RT_DEBUG_LOUD,("BulkOut-A:Size=%ld, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, bLRound=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, bTxQLastRound)); + + // USB DMA engine requires to pad extra 4 bytes. This pad doesn't count into real bulkoutsize. + pAppendant = &pWirelessPkt[TmpBulkEndPos]; + NdisZeroMemory(pAppendant, 8); + ThisBulkSize += 4; + pHTTXContext->LastOne = TRUE; + if ((ThisBulkSize % pAd->BulkOutMaxPacketSize) == 0) + ThisBulkSize += 4; + pHTTXContext->BulkOutSize = ThisBulkSize; + + pAd->watchDogTxPendingCnt[BulkOutPipeId] = 1; + BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); + + // Init Tx context descriptor + RTUSBInitHTTxDesc(pAd, pHTTXContext, BulkOutPipeId, ThisBulkSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete); + + pUrb = pHTTXContext->pUrb; + if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret)); + + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + return; + } + + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pHTTXContext->IRPPending = TRUE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutReq++; + +} + + +VOID RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) +{ + PHT_TX_CONTEXT pHTTXContext; + PRTMP_ADAPTER pAd; + POS_COOKIE pObj; + UCHAR BulkOutPipeId; + + + pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; + pAd = pHTTXContext->pAd; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + // Store BulkOut PipeId + BulkOutPipeId = pHTTXContext->BulkOutPipeId; + pAd->BulkOutDataOneSecCount++; + + switch (BulkOutPipeId) + { + case 0: + pObj->ac0_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->ac0_dma_done_task); + break; + case 1: + pObj->ac1_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->ac1_dma_done_task); + break; + case 2: + pObj->ac2_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->ac2_dma_done_task); + break; + case 3: + pObj->ac3_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->ac3_dma_done_task); + break; + case 4: + pObj->hcca_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->hcca_dma_done_task); + break; + } +} + + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: NULL frame use BulkOutPipeId = 0 + + ======================================================================== +*/ +VOID RTUSBBulkOutNullFrame( + IN PRTMP_ADAPTER pAd) +{ + PTX_CONTEXT pNullContext = &(pAd->NullContext); + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; + + RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); + if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) + { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); + return; + } + pAd->BulkOutPending[0] = TRUE; + pAd->watchDogTxPendingCnt[0] = 1; + pNullContext->IRPPending = TRUE; + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); + + // Increase Total transmit byte counter + pAd->RalinkCounters.TransmittedByteCount += pNullContext->BulkOutSize; + + + // Clear Null frame bulk flag + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pNullContext->TransferBuffer, TYPE_TXINFO); +#endif // RT_BIG_ENDIAN // + + // Init Tx context descriptor + RTUSBInitTxDesc(pAd, pNullContext, 0, (usb_complete_t)RTUSBBulkOutNullFrameComplete); + + pUrb = pNullContext->pUrb; + if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) + { + RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); + pAd->BulkOutPending[0] = FALSE; + pAd->watchDogTxPendingCnt[0] = 0; + pNullContext->IRPPending = FALSE; + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); + + DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutNullFrame: Submit Tx URB failed %d\n", ret)); + return; + } + +} + +// NULL frame use BulkOutPipeId = 0 +VOID RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs) +{ + PRTMP_ADAPTER pAd; + PTX_CONTEXT pNullContext; + NTSTATUS Status; + POS_COOKIE pObj; + + + pNullContext = (PTX_CONTEXT)pUrb->context; + pAd = pNullContext->pAd; + Status = pUrb->status; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + pObj->null_frame_complete_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->null_frame_complete_task); + +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: MLME use BulkOutPipeId = 0 + + ======================================================================== +*/ +VOID RTUSBBulkOutMLMEPacket( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PTX_CONTEXT pMLMEContext; + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; + + pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa; + pUrb = pMLMEContext->pUrb; + + if ((pAd->MgmtRing.TxSwFreeIdx >= MGMT_RING_SIZE) || + (pMLMEContext->InUse == FALSE) || + (pMLMEContext->bWaitingBulkOut == FALSE)) + { + + + // Clear MLME bulk flag + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); + + return; + } + + + RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); + if ((pAd->BulkOutPending[MGMTPIPEIDX] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) + { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); + return; + } + + pAd->BulkOutPending[MGMTPIPEIDX] = TRUE; + pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 1; + pMLMEContext->IRPPending = TRUE; + pMLMEContext->bWaitingBulkOut = FALSE; + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); + + // Increase Total transmit byte counter + pAd->RalinkCounters.TransmittedByteCount += pMLMEContext->BulkOutSize; + + // Clear MLME bulk flag + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pMLMEContext->TransferBuffer, TYPE_TXINFO); +#endif // RT_BIG_ENDIAN // + + // Init Tx context descriptor + RTUSBInitTxDesc(pAd, pMLMEContext, MGMTPIPEIDX, (usb_complete_t)RTUSBBulkOutMLMEPacketComplete); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + //For mgmt urb buffer, because we use sk_buff, so we need to notify the USB controller do dma mapping. + pUrb->transfer_dma = 0; + pUrb->transfer_flags &= (~URB_NO_TRANSFER_DMA_MAP); +#endif + + pUrb = pMLMEContext->pUrb; + if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutMLMEPacket: Submit MLME URB failed %d\n", ret)); + RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); + pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; + pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 0; + pMLMEContext->IRPPending = FALSE; + pMLMEContext->bWaitingBulkOut = TRUE; + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); + + return; + } + + //DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutMLMEPacket \n")); +// printk("<---RTUSBBulkOutMLMEPacket,Cpu=%d!, Dma=%d, SwIdx=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx); +} + + +VOID RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) +{ + PTX_CONTEXT pMLMEContext; + PRTMP_ADAPTER pAd; + NTSTATUS Status; + POS_COOKIE pObj; + int index; + + //DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutMLMEPacketComplete\n")); + pMLMEContext = (PTX_CONTEXT)pUrb->context; + pAd = pMLMEContext->pAd; + pObj = (POS_COOKIE)pAd->OS_Cookie; + Status = pUrb->status; + index = pMLMEContext->SelfIdx; + + pObj->mgmt_dma_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->mgmt_dma_done_task); +} + + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: PsPoll use BulkOutPipeId = 0 + + ======================================================================== +*/ +VOID RTUSBBulkOutPsPoll( + IN PRTMP_ADAPTER pAd) +{ + PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext); + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; + + RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); + if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) + { + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); + return; + } + pAd->BulkOutPending[0] = TRUE; + pAd->watchDogTxPendingCnt[0] = 1; + pPsPollContext->IRPPending = TRUE; + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); + + + // Clear PS-Poll bulk flag + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pPsPollContext->TransferBuffer, TYPE_TXINFO); +#endif // RT_BIG_ENDIAN // + + // Init Tx context descriptor + RTUSBInitTxDesc(pAd, pPsPollContext, MGMTPIPEIDX, (usb_complete_t)RTUSBBulkOutPsPollComplete); + + pUrb = pPsPollContext->pUrb; + if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) + { + RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); + pAd->BulkOutPending[0] = FALSE; + pAd->watchDogTxPendingCnt[0] = 0; + pPsPollContext->IRPPending = FALSE; + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); + + DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutPsPoll: Submit Tx URB failed %d\n", ret)); + return; + } + +} + +// PS-Poll frame use BulkOutPipeId = 0 +VOID RTUSBBulkOutPsPollComplete(purbb_t pUrb,struct pt_regs *pt_regs) +{ + PRTMP_ADAPTER pAd; + PTX_CONTEXT pPsPollContext; + NTSTATUS Status; + POS_COOKIE pObj; + + + pPsPollContext= (PTX_CONTEXT)pUrb->context; + pAd = pPsPollContext->pAd; + Status = pUrb->status; + pObj = (POS_COOKIE) pAd->OS_Cookie; + pObj->pspoll_frame_complete_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->pspoll_frame_complete_task); + +} + +VOID DoBulkIn(IN RTMP_ADAPTER *pAd) +{ + PRX_CONTEXT pRxContext; + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; + + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); + if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE)) + { + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + return; + } + pRxContext->InUse = TRUE; + pRxContext->IRPPending = TRUE; + pAd->PendingRx++; + pAd->BulkInReq++; + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + + // Init Rx context descriptor + NdisZeroMemory(pRxContext->TransferBuffer, pRxContext->BulkInOffset); + RTUSBInitRxDesc(pAd, pRxContext); + + pUrb = pRxContext->pUrb; + if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0) + { // fail + + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pAd->PendingRx--; + pAd->BulkInReq--; + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret)); + } + else + { // success + ASSERT((pRxContext->InUse == pRxContext->IRPPending)); + //printk("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex); + } +} + + +/* + ======================================================================== + + Routine Description: + USB_RxPacket initializes a URB and uses the Rx IRP to submit it + to USB. It checks if an Rx Descriptor is available and passes the + the coresponding buffer to be filled. If no descriptor is available + fails the request. When setting the completion routine we pass our + Adapter Object as Context. + + Arguments: + + Return Value: + TRUE found matched tuple cache + FALSE no matched found + + Note: + + ======================================================================== +*/ +#define fRTMP_ADAPTER_NEED_STOP_RX \ + (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ + fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \ + fRTMP_ADAPTER_REMOVE_IN_PROGRESS | fRTMP_ADAPTER_BULKIN_RESET) + +#define fRTMP_ADAPTER_NEED_STOP_HANDLE_RX \ + (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ + fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \ + fRTMP_ADAPTER_REMOVE_IN_PROGRESS) + +VOID RTUSBBulkReceive( + IN PRTMP_ADAPTER pAd) +{ + PRX_CONTEXT pRxContext; + unsigned long IrqFlags; + + + /* sanity check */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_HANDLE_RX)) + return; + + while(1) + { + + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext = &(pAd->RxContext[pAd->NextRxBulkInReadIndex]); + if (((pRxContext->InUse == FALSE) && (pRxContext->Readable == TRUE)) && + (pRxContext->bRxHandling == FALSE)) + { + pRxContext->bRxHandling = TRUE; + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + + // read RxContext, Since not +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + STARxDoneInterruptHandle(pAd, TRUE); +#endif // CONFIG_STA_SUPPORT // + + // Finish to handle this bulkIn buffer. + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext->BulkInOffset = 0; + pRxContext->Readable = FALSE; + pRxContext->bRxHandling = FALSE; + pAd->ReadPosition = 0; + pAd->TransferBufferLength = 0; + INC_RING_INDEX(pAd->NextRxBulkInReadIndex, RX_RING_SIZE); + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + + } + else + { + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + break; + } + } + + if (!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_RX))) + DoBulkIn(pAd); + +} + + +/* + ======================================================================== + + Routine Description: + This routine process Rx Irp and call rx complete function. + + Arguments: + DeviceObject Pointer to the device object for next lower + device. DeviceObject passed in here belongs to + the next lower driver in the stack because we + were invoked via IoCallDriver in USB_RxPacket + AND it is not OUR device object + Irp Ptr to completed IRP + Context Ptr to our Adapter object (context specified + in IoSetCompletionRoutine + + Return Value: + Always returns STATUS_MORE_PROCESSING_REQUIRED + + Note: + Always returns STATUS_MORE_PROCESSING_REQUIRED + ======================================================================== +*/ +VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs) +{ + // use a receive tasklet to handle received packets; + // or sometimes hardware IRQ will be disabled here, so we can not + // use spin_lock_bh()/spin_unlock_bh() after IRQ is disabled. :< + PRX_CONTEXT pRxContext; + PRTMP_ADAPTER pAd; + POS_COOKIE pObj; + + + pRxContext = (PRX_CONTEXT)pUrb->context; + pAd = pRxContext->pAd; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + pObj->rx_done_task.data = (unsigned long)pUrb; + tasklet_hi_schedule(&pObj->rx_done_task); + +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTUSBKickBulkOut( + IN PRTMP_ADAPTER pAd) +{ + // BulkIn Reset will reset whole USB PHY. So we need to make sure fRTMP_ADAPTER_BULKIN_RESET not flaged. + if (!RTMP_TEST_FLAG(pAd ,fRTMP_ADAPTER_NEED_STOP_TX) +#ifdef RALINK_ATE + && !(ATE_ON(pAd)) +#endif // RALINK_ATE // + ) + { + // 2. PS-Poll frame is next + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL)) + { + RTUSBBulkOutPsPoll(pAd); + } + + // 5. Mlme frame is next + else if ((RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME)) && + (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE)) + { + RTUSBBulkOutMLMEPacket(pAd, pAd->MgmtRing.TxDmaIdx); + } + + // 6. Data frame normal is next + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL)) + { + if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + )) + { + RTUSBBulkOutDataPacket(pAd, 0, pAd->NextBulkOutIndex[0]); + } + } + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_2)) + { + if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + )) + { + RTUSBBulkOutDataPacket(pAd, 1, pAd->NextBulkOutIndex[1]); + } + } + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_3)) + { + if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + )) + { + RTUSBBulkOutDataPacket(pAd, 2, pAd->NextBulkOutIndex[2]); + } + } + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_4)) + { + if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + )) + { + RTUSBBulkOutDataPacket(pAd, 3, pAd->NextBulkOutIndex[3]); + } + } + //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA) + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_5)) + { + if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || + (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + )) + { + } + } + + // 7. Null frame is the last + else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL)) + { + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + RTUSBBulkOutNullFrame(pAd); + } + } + + // 8. No data avaliable + else + { + + } + } +#ifdef RALINK_ATE + /* If the mode is in ATE mode. */ + else if((ATE_ON(pAd)) && + !RTMP_TEST_FLAG(pAd ,fRTMP_ADAPTER_NEED_STOP_TX))// PETER : watch out ! + { + if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE)) + { + ATE_RTUSBBulkOutDataPacket(pAd, 0); + } + } +#endif // RALINK_ATE // + +} + +/* + ======================================================================== + + Routine Description: + Call from Reset action after BulkOut failed. + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTUSBCleanUpDataBulkOutQueue( + IN PRTMP_ADAPTER pAd) +{ + UCHAR Idx; + PHT_TX_CONTEXT pTxContext; + + DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpDataBulkOutQueue\n")); + + for (Idx = 0; Idx < 4; Idx++) + { + pTxContext = &pAd->TxContext[Idx]; + + pTxContext->CurWritePosition = pTxContext->NextBulkOutPosition; + pTxContext->LastOne = FALSE; + NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]); + pAd->BulkOutPending[Idx] = FALSE; + NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpDataBulkOutQueue\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTUSBCleanUpMLMEBulkOutQueue( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpMLMEBulkOutQueue\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpMLMEBulkOutQueue\n")); +} + + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + + Note: + + ======================================================================== +*/ +VOID RTUSBCancelPendingIRPs( + IN PRTMP_ADAPTER pAd) +{ + RTUSBCancelPendingBulkInIRP(pAd); + RTUSBCancelPendingBulkOutIRP(pAd); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTUSBCancelPendingBulkInIRP( + IN PRTMP_ADAPTER pAd) +{ + PRX_CONTEXT pRxContext; + UINT i; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->RTUSBCancelPendingBulkInIRP\n")); + for ( i = 0; i < (RX_RING_SIZE); i++) + { + pRxContext = &(pAd->RxContext[i]); + if(pRxContext->IRPPending == TRUE) + { + RTUSB_UNLINK_URB(pRxContext->pUrb); + pRxContext->IRPPending = FALSE; + pRxContext->InUse = FALSE; + //NdisInterlockedDecrement(&pAd->PendingRx); + //pAd->PendingRx--; + } + } + DBGPRINT_RAW(RT_DEBUG_TRACE, ("<---RTUSBCancelPendingBulkInIRP\n")); +} + + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTUSBCancelPendingBulkOutIRP( + IN PRTMP_ADAPTER pAd) +{ + PHT_TX_CONTEXT pHTTXContext; + PTX_CONTEXT pMLMEContext; + PTX_CONTEXT pBeaconContext; + PTX_CONTEXT pNullContext; + PTX_CONTEXT pPsPollContext; + PTX_CONTEXT pRTSContext; + UINT i, Idx; +// unsigned int IrqFlags; +// NDIS_SPIN_LOCK *pLock; +// BOOLEAN *pPending; + + +// pLock = &pAd->BulkOutLock[MGMTPIPEIDX]; +// pPending = &pAd->BulkOutPending[MGMTPIPEIDX]; + + for (Idx = 0; Idx < 4; Idx++) + { + pHTTXContext = &(pAd->TxContext[Idx]); + + if (pHTTXContext->IRPPending == TRUE) + { + + // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself + // remove it from the HeadPendingSendList and NULL out HeadPendingSendList + // when the last IRP on the list has been cancelled; that's how we exit this loop + // + + RTUSB_UNLINK_URB(pHTTXContext->pUrb); + + // Sleep 200 microseconds to give cancellation time to work + RTMPusecDelay(200); + } + +#ifdef RALINK_ATE + pHTTXContext->bCopySavePad = 0; + pHTTXContext->CurWritePosition = 0; + pHTTXContext->CurWriteRealPos = 0; + pHTTXContext->bCurWriting = FALSE; + pHTTXContext->NextBulkOutPosition = 0; + pHTTXContext->ENextBulkOutPosition = 0; +#endif // RALINK_ATE // + pAd->BulkOutPending[Idx] = FALSE; + } + + //RTMP_IRQ_LOCK(pLock, IrqFlags); + for (i = 0; i < MGMT_RING_SIZE; i++) + { + pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa; + if(pMLMEContext && (pMLMEContext->IRPPending == TRUE)) + { + + // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself + // remove it from the HeadPendingSendList and NULL out HeadPendingSendList + // when the last IRP on the list has been cancelled; that's how we exit this loop + // + + RTUSB_UNLINK_URB(pMLMEContext->pUrb); + pMLMEContext->IRPPending = FALSE; + + // Sleep 200 microsecs to give cancellation time to work + RTMPusecDelay(200); + } + } + pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; + //RTMP_IRQ_UNLOCK(pLock, IrqFlags); + + + for (i = 0; i < BEACON_RING_SIZE; i++) + { + pBeaconContext = &(pAd->BeaconContext[i]); + + if(pBeaconContext->IRPPending == TRUE) + { + + // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself + // remove it from the HeadPendingSendList and NULL out HeadPendingSendList + // when the last IRP on the list has been cancelled; that's how we exit this loop + // + + RTUSB_UNLINK_URB(pBeaconContext->pUrb); + + // Sleep 200 microsecs to give cancellation time to work + RTMPusecDelay(200); + } + } + + pNullContext = &(pAd->NullContext); + if (pNullContext->IRPPending == TRUE) + RTUSB_UNLINK_URB(pNullContext->pUrb); + + pRTSContext = &(pAd->RTSContext); + if (pRTSContext->IRPPending == TRUE) + RTUSB_UNLINK_URB(pRTSContext->pUrb); + + pPsPollContext = &(pAd->PsPollContext); + if (pPsPollContext->IRPPending == TRUE) + RTUSB_UNLINK_URB(pPsPollContext->pUrb); + + for (Idx = 0; Idx < 4; Idx++) + { + NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]); + pAd->BulkOutPending[Idx] = FALSE; + NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]); + } +} + diff --git a/drivers/staging/rt3070/common/rtusb_data.c b/drivers/staging/rt3070/common/rtusb_data.c new file mode 100644 index 000000000000..521309a2ae53 --- /dev/null +++ b/drivers/staging/rt3070/common/rtusb_data.c @@ -0,0 +1,218 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtusb_data.c + + Abstract: + Ralink USB driver Tx/Rx functions. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan 03-25-2006 created + +*/ +#include "../rt_config.h" + +extern UCHAR Phy11BGNextRateUpward[]; // defined in mlme.c +extern UCHAR EpToQueue[]; + + +VOID REPORT_AMSDU_FRAMES_TO_LLC( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataSize) +{ + PNDIS_PACKET pPacket; + UINT nMSDU; + struct sk_buff *pSkb; + + nMSDU = 0; + /* allocate a rx packet */ + pSkb = dev_alloc_skb(RX_BUFFER_AGGRESIZE); + pPacket = (PNDIS_PACKET)OSPKT_TO_RTPKT(pSkb); + if (pSkb) + { + + /* convert 802.11 to 802.3 packet */ + pSkb->dev = get_netdev_from_bssid(pAd, BSS0); + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); + deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize); + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("Can't allocate skb\n")); + } +} + +NDIS_STATUS RTUSBFreeDescriptorRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR BulkOutPipeId, + IN UINT32 NumberRequired) +{ +// UCHAR FreeNumber = 0; +// UINT Index; + NDIS_STATUS Status = NDIS_STATUS_FAILURE; + unsigned long IrqFlags; + HT_TX_CONTEXT *pHTTXContext; + + + pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + if ((pHTTXContext->CurWritePosition < pHTTXContext->NextBulkOutPosition) && ((pHTTXContext->CurWritePosition + NumberRequired + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)) + { + + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); + } + else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < (NumberRequired + LOCAL_TXBUF_SIZE))) + { + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); + } + else if (pHTTXContext->bCurWriting == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE,("RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n", BulkOutPipeId, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); + } + else + { + Status = NDIS_STATUS_SUCCESS; + } + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + + + return (Status); +} + + +NDIS_STATUS RTUSBFreeDescriptorRelease( + IN RTMP_ADAPTER *pAd, + IN UCHAR BulkOutPipeId) +{ + unsigned long IrqFlags; + HT_TX_CONTEXT *pHTTXContext; + + pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + pHTTXContext->bCurWriting = FALSE; + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + + return (NDIS_STATUS_SUCCESS); +} + + +BOOLEAN RTUSBNeedQueueBackForAgg( + IN RTMP_ADAPTER *pAd, + IN UCHAR BulkOutPipeId) +{ + unsigned long IrqFlags; + HT_TX_CONTEXT *pHTTXContext; + BOOLEAN needQueBack = FALSE; + + pHTTXContext = &pAd->TxContext[BulkOutPipeId]; + + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + if ((pHTTXContext->IRPPending == TRUE) /*&& (pAd->TxSwQueue[BulkOutPipeId].Number == 0) */) + { + if ((pHTTXContext->CurWritePosition < pHTTXContext->ENextBulkOutPosition) && + (((pHTTXContext->ENextBulkOutPosition+MAX_AGGREGATION_SIZE) < MAX_TXBULK_LIMIT) || (pHTTXContext->CurWritePosition > MAX_AGGREGATION_SIZE))) + { + needQueBack = TRUE; + } + else if ((pHTTXContext->CurWritePosition > pHTTXContext->ENextBulkOutPosition) && + ((pHTTXContext->ENextBulkOutPosition + MAX_AGGREGATION_SIZE) < pHTTXContext->CurWritePosition)) + { + needQueBack = TRUE; + } + } + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); + + return needQueBack; + +} + + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +VOID RTUSBRejectPendingPackets( + IN PRTMP_ADAPTER pAd) +{ + UCHAR Index; + PQUEUE_ENTRY pEntry; + PNDIS_PACKET pPacket; + PQUEUE_HEADER pQueue; + + + for (Index = 0; Index < 4; Index++) + { + NdisAcquireSpinLock(&pAd->TxSwQueueLock[Index]); + while (pAd->TxSwQueue[Index].Head != NULL) + { + pQueue = (PQUEUE_HEADER) &(pAd->TxSwQueue[Index]); + pEntry = RemoveHeadQueue(pQueue); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + NdisReleaseSpinLock(&pAd->TxSwQueueLock[Index]); + + } + +} + +VOID RTMPWriteTxInfo( + IN PRTMP_ADAPTER pAd, + IN PTXINFO_STRUC pTxInfo, + IN USHORT USBDMApktLen, + IN BOOLEAN bWiv, + IN UCHAR QueueSel, + IN UCHAR NextValid, + IN UCHAR TxBurst) +{ + pTxInfo->USBDMATxPktLen = USBDMApktLen; + pTxInfo->QSEL = QueueSel; + if (QueueSel != FIFO_EDCA) + DBGPRINT(RT_DEBUG_TRACE, ("====> QueueSel != FIFO_EDCA<============\n")); + pTxInfo->USBDMANextVLD = FALSE; //NextValid; // Need to check with Jan about this. + pTxInfo->USBDMATxburst = TxBurst; + pTxInfo->WIV = bWiv; + pTxInfo->SwUseLastRound = 0; + pTxInfo->rsv = 0; + pTxInfo->rsv2 = 0; +} + diff --git a/drivers/staging/rt3070/common/rtusb_io.c b/drivers/staging/rt3070/common/rtusb_io.c new file mode 100644 index 000000000000..a6a52e3445f9 --- /dev/null +++ b/drivers/staging/rt3070/common/rtusb_io.c @@ -0,0 +1,1908 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtusb_io.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 06-25-2004 created +*/ + +#include "../rt_config.h" + + +/* + ======================================================================== + + Routine Description: NIC initialization complete + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ + +NTSTATUS RTUSBFirmwareRun( + IN PRTMP_ADAPTER pAd) +{ + NTSTATUS Status; + + Status = RTUSB_VendorRequest( + pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x01, + 0x8, + 0, + NULL, + 0); + + return Status; +} + + + +/* + ======================================================================== + + Routine Description: Write Firmware to NIC. + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBFirmwareWrite( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFwImage, + IN ULONG FwLen) +{ + UINT32 MacReg; + NTSTATUS Status; +// ULONG i; + USHORT writeLen; + + Status = RTUSBReadMACRegister(pAd, MAC_CSR0, &MacReg); + + + writeLen = FwLen; + RTUSBMultiWrite(pAd, FIRMWARE_IMAGE_BASE, pFwImage, writeLen); + + Status = RTUSBWriteMACRegister(pAd, 0x7014, 0xffffffff); + Status = RTUSBWriteMACRegister(pAd, 0x701c, 0xffffffff); + Status = RTUSBFirmwareRun(pAd); + + RTMPusecDelay(10000); + RTUSBWriteMACRegister(pAd,H2M_MAILBOX_CSR,0); + AsicSendCommandToMcu(pAd, 0x72, 0x00, 0x00, 0x00);//reset rf by MCU supported by new firmware + + return Status; +} + + +/* + ======================================================================== + + Routine Description: Get current firmware operation mode (Return Value) + + Arguments: + + Return Value: + 0 or 1 = Downloaded by host driver + others = Driver doesn't download firmware + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBFirmwareOpmode( + IN PRTMP_ADAPTER pAd, + OUT PUINT32 pValue) +{ + NTSTATUS Status; + + Status = RTUSB_VendorRequest( + pAd, + (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), + DEVICE_VENDOR_REQUEST_IN, + 0x1, + 0x11, + 0, + pValue, + 4); + return Status; +} +NTSTATUS RTUSBVenderReset( + IN PRTMP_ADAPTER pAd) +{ + NTSTATUS Status; + DBGPRINT_RAW(RT_DEBUG_ERROR, ("-->RTUSBVenderReset\n")); + Status = RTUSB_VendorRequest( + pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x01, + 0x1, + 0, + NULL, + 0); + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("<--RTUSBVenderReset\n")); + return Status; +} +/* + ======================================================================== + + Routine Description: Read various length data from RT2573 + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBMultiRead( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT PUCHAR pData, + IN USHORT length) +{ + NTSTATUS Status; + + Status = RTUSB_VendorRequest( + pAd, + (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), + DEVICE_VENDOR_REQUEST_IN, + 0x7, + 0, + Offset, + pData, + length); + + return Status; +} + +/* + ======================================================================== + + Routine Description: Write various length data to RT2573 + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBMultiWrite_OneByte( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN PUCHAR pData) +{ + NTSTATUS Status; + + // TODO: In 2870, use this funciton carefully cause it's not stable. + Status = RTUSB_VendorRequest( + pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x6, + 0, + Offset, + pData, + 1); + + return Status; +} + +NTSTATUS RTUSBMultiWrite( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN PUCHAR pData, + IN USHORT length) +{ + NTSTATUS Status; + + + USHORT index = 0,Value; + PUCHAR pSrc = pData; + USHORT resude = 0; + + resude = length % 2; + length += resude; + do + { + Value =(USHORT)( *pSrc | (*(pSrc + 1) << 8)); + Status = RTUSBSingleWrite(pAd,Offset + index,Value); + index +=2; + length -= 2; + pSrc = pSrc + 2; + }while(length > 0); + + return Status; +} + + +NTSTATUS RTUSBSingleWrite( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT Value) +{ + NTSTATUS Status; + + Status = RTUSB_VendorRequest( + pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x2, + Value, + Offset, + NULL, + 0); + + return Status; + +} + + +/* + ======================================================================== + + Routine Description: Read 32-bit MAC register + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBReadMACRegister( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT PUINT32 pValue) +{ + NTSTATUS Status; + UINT32 localVal; + + Status = RTUSB_VendorRequest( + pAd, + (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), + DEVICE_VENDOR_REQUEST_IN, + 0x7, + 0, + Offset, + &localVal, + 4); + + *pValue = le2cpu32(localVal); + + + if (Status < 0) + *pValue = 0xffffffff; + + return Status; +} + + +/* + ======================================================================== + + Routine Description: Write 32-bit MAC register + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBWriteMACRegister( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN UINT32 Value) +{ + NTSTATUS Status; + UINT32 localVal; + + localVal = Value; + + Status = RTUSBSingleWrite(pAd, Offset, (USHORT)(localVal & 0xffff)); + Status = RTUSBSingleWrite(pAd, Offset + 2, (USHORT)((localVal & 0xffff0000) >> 16)); + + return Status; +} + + + +#if 1 +/* + ======================================================================== + + Routine Description: Read 8-bit BBP register + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBReadBBPRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR Id, + IN PUCHAR pValue) +{ + BBP_CSR_CFG_STRUC BbpCsr; + UINT i = 0; + NTSTATUS status; + + // Verify the busy condition + do + { + status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word); + if(status >= 0) + { + if (!(BbpCsr.field.Busy == BUSY)) + break; + } + printk("RTUSBReadBBPRegister(BBP_CSR_CFG_1):retry count=%d!\n", i); + i++; + } + while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + // + // Read failed then Return Default value. + // + *pValue = pAd->BbpWriteLatch[Id]; + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + return STATUS_UNSUCCESSFUL; + } + + // Prepare for write material + BbpCsr.word = 0; + BbpCsr.field.fRead = 1; + BbpCsr.field.Busy = 1; + BbpCsr.field.RegNum = Id; + RTUSBWriteMACRegister(pAd, BBP_CSR_CFG, BbpCsr.word); + + i = 0; + // Verify the busy condition + do + { + status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word); + if (status >= 0) + { + if (!(BbpCsr.field.Busy == BUSY)) + { + *pValue = (UCHAR)BbpCsr.field.Value; + break; + } + } + printk("RTUSBReadBBPRegister(BBP_CSR_CFG_2):retry count=%d!\n", i); + i++; + } + while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + // + // Read failed then Return Default value. + // + *pValue = pAd->BbpWriteLatch[Id]; + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; +} +#else +/* + ======================================================================== + + Routine Description: Read 8-bit BBP register via firmware + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBReadBBPRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR Id, + IN PUCHAR pValue) +{ + BBP_CSR_CFG_STRUC BbpCsr; + int i, k; + for (i=0; iBbpWriteLatch[Id]; + return STATUS_UNSUCCESSFUL; + } + return STATUS_SUCCESS; +} +#endif + +#if 1 +/* + ======================================================================== + + Routine Description: Write 8-bit BBP register + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBWriteBBPRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR Id, + IN UCHAR Value) +{ + BBP_CSR_CFG_STRUC BbpCsr; + UINT i = 0; + NTSTATUS status; + // Verify the busy condition + do + { + status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word); + if (status >= 0) + { + if (!(BbpCsr.field.Busy == BUSY)) + break; + } + printk("RTUSBWriteBBPRegister(BBP_CSR_CFG):retry count=%d!\n", i); + i++; + } + while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + return STATUS_UNSUCCESSFUL; + } + + // Prepare for write material + BbpCsr.word = 0; + BbpCsr.field.fRead = 0; + BbpCsr.field.Value = Value; + BbpCsr.field.Busy = 1; + BbpCsr.field.RegNum = Id; + RTUSBWriteMACRegister(pAd, BBP_CSR_CFG, BbpCsr.word); + + pAd->BbpWriteLatch[Id] = Value; + + return STATUS_SUCCESS; +} +#else +/* + ======================================================================== + + Routine Description: Write 8-bit BBP register via firmware + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ + +NTSTATUS RTUSBWriteBBPRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR Id, + IN UCHAR Value) + +{ + BBP_CSR_CFG_STRUC BbpCsr; + int BusyCnt; + for (BusyCnt=0; BusyCntBbpWriteLatch[Id] = Value; + break; + } + if (BusyCnt == MAX_BUSY_COUNT) + { + DBGPRINT_ERR(("BBP write R%d=0x%x fail\n", Id, BbpCsr.word)); + return STATUS_UNSUCCESSFUL; + } + return STATUS_SUCCESS; +} +#endif +/* + ======================================================================== + + Routine Description: Write RF register through MAC + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBWriteRFRegister( + IN PRTMP_ADAPTER pAd, + IN UINT32 Value) +{ + PHY_CSR4_STRUC PhyCsr4; + UINT i = 0; + NTSTATUS status; + + NdisZeroMemory(&PhyCsr4, sizeof(PHY_CSR4_STRUC)); + do + { + status = RTUSBReadMACRegister(pAd, RF_CSR_CFG0, &PhyCsr4.word); + if (status >= 0) + { + if (!(PhyCsr4.field.Busy)) + break; + } + printk("RTUSBWriteRFRegister(RF_CSR_CFG0):retry count=%d!\n", i); + i++; + } + while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); + + if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); + return STATUS_UNSUCCESSFUL; + } + + RTUSBWriteMACRegister(pAd, RF_CSR_CFG0, Value); + + return STATUS_SUCCESS; +} + + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBReadEEPROM( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT PUCHAR pData, + IN USHORT length) +{ + NTSTATUS Status = STATUS_SUCCESS; + +#ifdef RT30xx + if(pAd->bUseEfuse) + { + Status =eFuseRead(pAd, Offset, pData, length); + } + else +#endif // RT30xx // + { + Status = RTUSB_VendorRequest( + pAd, + (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), + DEVICE_VENDOR_REQUEST_IN, + 0x9, + 0, + Offset, + pData, + length); + } + + return Status; +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBWriteEEPROM( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN PUCHAR pData, + IN USHORT length) +{ + NTSTATUS Status = STATUS_SUCCESS; + +#ifdef RT30xx + if(pAd->bUseEfuse) + { + Status = eFuseWrite(pAd, Offset, pData, length); + } + else +#endif // RT30xx // + { + Status = RTUSB_VendorRequest( + pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x8, + 0, + Offset, + pData, + length); + } + + return Status; +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +VOID RTUSBPutToSleep( + IN PRTMP_ADAPTER pAd) +{ + UINT32 value; + + // Timeout 0x40 x 50us + value = (SLEEPCID<<16)+(OWNERMCU<<24)+ (0x40<<8)+1; + RTUSBWriteMACRegister(pAd, 0x7010, value); + RTUSBWriteMACRegister(pAd, 0x404, 0x30); + //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Sleep Mailbox testvalue %x\n", value)); + +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSBWakeUp( + IN PRTMP_ADAPTER pAd) +{ + NTSTATUS Status; + + Status = RTUSB_VendorRequest( + pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x01, + 0x09, + 0, + NULL, + 0); + + return Status; +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +VOID RTUSBInitializeCmdQ( + IN PCmdQ cmdq) +{ + cmdq->head = NULL; + cmdq->tail = NULL; + cmdq->size = 0; + cmdq->CmdQState = RT2870_THREAD_INITED; +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTUSBEnqueueCmdFromNdis( + IN PRTMP_ADAPTER pAd, + IN NDIS_OID Oid, + IN BOOLEAN SetInformation, + IN PVOID pInformationBuffer, + IN UINT32 InformationBufferLength) +{ + NDIS_STATUS status; + PCmdQElmt cmdqelmt = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + + if (pObj->RTUSBCmdThr_pid < 0) + return (NDIS_STATUS_RESOURCES); + + status = RTMPAllocateMemory((PVOID *)&cmdqelmt, sizeof(CmdQElmt)); + if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL)) + return (NDIS_STATUS_RESOURCES); + + cmdqelmt->buffer = NULL; + if (pInformationBuffer != NULL) + { + status = RTMPAllocateMemory((PVOID *)&cmdqelmt->buffer, InformationBufferLength); + if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL)) + { + kfree(cmdqelmt); + return (NDIS_STATUS_RESOURCES); + } + else + { + NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength); + cmdqelmt->bufferlength = InformationBufferLength; + } + } + else + cmdqelmt->bufferlength = 0; + + cmdqelmt->command = Oid; + cmdqelmt->CmdFromNdis = TRUE; + if (SetInformation == TRUE) + cmdqelmt->SetOperation = TRUE; + else + cmdqelmt->SetOperation = FALSE; + + NdisAcquireSpinLock(&pAd->CmdQLock); + if (pAd->CmdQ.CmdQState & RT2870_THREAD_CAN_DO_INSERT) + { + EnqueueCmd((&pAd->CmdQ), cmdqelmt); + status = NDIS_STATUS_SUCCESS; + } + else + { + status = NDIS_STATUS_FAILURE; + } + NdisReleaseSpinLock(&pAd->CmdQLock); + + if (status == NDIS_STATUS_FAILURE) + { + if (cmdqelmt->buffer) + NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0); + NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); + } + else + RTUSBCMDUp(pAd); + + + return(NDIS_STATUS_SUCCESS); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTUSBEnqueueInternalCmd( + IN PRTMP_ADAPTER pAd, + IN NDIS_OID Oid, + IN PVOID pInformationBuffer, + IN UINT32 InformationBufferLength) +{ + NDIS_STATUS status; + PCmdQElmt cmdqelmt = NULL; + + + status = RTMPAllocateMemory((PVOID *)&cmdqelmt, sizeof(CmdQElmt)); + if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL)) + return (NDIS_STATUS_RESOURCES); + NdisZeroMemory(cmdqelmt, sizeof(CmdQElmt)); + + if(InformationBufferLength > 0) + { + status = RTMPAllocateMemory((PVOID *)&cmdqelmt->buffer, InformationBufferLength); + if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL)) + { + NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); + return (NDIS_STATUS_RESOURCES); + } + else + { + NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength); + cmdqelmt->bufferlength = InformationBufferLength; + } + } + else + { + cmdqelmt->buffer = NULL; + cmdqelmt->bufferlength = 0; + } + + cmdqelmt->command = Oid; + cmdqelmt->CmdFromNdis = FALSE; + + if (cmdqelmt != NULL) + { + NdisAcquireSpinLock(&pAd->CmdQLock); + if (pAd->CmdQ.CmdQState & RT2870_THREAD_CAN_DO_INSERT) + { + EnqueueCmd((&pAd->CmdQ), cmdqelmt); + status = NDIS_STATUS_SUCCESS; + } + else + { + status = NDIS_STATUS_FAILURE; + } + NdisReleaseSpinLock(&pAd->CmdQLock); + + if (status == NDIS_STATUS_FAILURE) + { + if (cmdqelmt->buffer) + NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0); + NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); + } + else + RTUSBCMDUp(pAd); + } + return(NDIS_STATUS_SUCCESS); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +VOID RTUSBDequeueCmd( + IN PCmdQ cmdq, + OUT PCmdQElmt *pcmdqelmt) +{ + *pcmdqelmt = cmdq->head; + + if (*pcmdqelmt != NULL) + { + cmdq->head = cmdq->head->next; + cmdq->size--; + if (cmdq->size == 0) + cmdq->tail = NULL; + } +} + +/* + ======================================================================== + usb_control_msg - Builds a control urb, sends it off and waits for completion + @dev: pointer to the usb device to send the message to + @pipe: endpoint "pipe" to send the message to + @request: USB message request value + @requesttype: USB message request type value + @value: USB message value + @index: USB message index value + @data: pointer to the data to send + @size: length in bytes of the data to send + @timeout: time in jiffies to wait for the message to complete before + timing out (if 0 the wait is forever) + Context: !in_interrupt () + + This function sends a simple control message to a specified endpoint + and waits for the message to complete, or timeout. + If successful, it returns the number of bytes transferred, otherwise a negative error number. + + Don't use this function from within an interrupt context, like a + bottom half handler. If you need an asynchronous message, or need to send + a message from within interrupt context, use usb_submit_urb() + If a thread in your driver uses this call, make sure your disconnect() + method can wait for it to complete. Since you don't have a handle on + the URB used, you can't cancel the request. + + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSB_VendorRequest( + IN PRTMP_ADAPTER pAd, + IN UINT32 TransferFlags, + IN UCHAR RequestType, + IN UCHAR Request, + IN USHORT Value, + IN USHORT Index, + IN PVOID TransferBuffer, + IN UINT32 TransferBufferLength) +{ + int ret; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT(RT_DEBUG_ERROR, ("device disconnected\n")); + return -1; + } + else if (in_interrupt()) + { + DBGPRINT(RT_DEBUG_ERROR, ("in_interrupt, RTUSB_VendorRequest Request%02x Value%04x Offset%04x\n",Request,Value,Index)); + + return -1; + } + else + { +#define MAX_RETRY_COUNT 10 + + int retryCount = 0; + void *tmpBuf = TransferBuffer; + + // Acquire Control token +#ifdef INF_AMAZON_SE + ret = down_interruptible(&(pAd->UsbVendorReq_semaphore)); + if (pAd->UsbVendorReqBuf) + { + ASSERT(TransferBufferLength UsbVendorReqBuf; + NdisZeroMemory(pAd->UsbVendorReqBuf, TransferBufferLength); + + if (RequestType == DEVICE_VENDOR_REQUEST_OUT) + NdisMoveMemory(tmpBuf, TransferBuffer, TransferBufferLength); + } +#endif // INF_AMAZON_SE // + do { + if( RequestType == DEVICE_VENDOR_REQUEST_OUT) + ret=usb_control_msg(pObj->pUsb_Dev, usb_sndctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES); + else if(RequestType == DEVICE_VENDOR_REQUEST_IN) + ret=usb_control_msg(pObj->pUsb_Dev, usb_rcvctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES); + else + { + DBGPRINT(RT_DEBUG_ERROR, ("vendor request direction is failed\n")); + ret = -1; + } + + retryCount++; + if (ret < 0) { + printk("#\n"); + RTMPusecDelay(5000); + } + } while((ret < 0) && (retryCount < MAX_RETRY_COUNT)); + +#ifdef INF_AMAZON_SE + if ((pAd->UsbVendorReqBuf) && (RequestType == DEVICE_VENDOR_REQUEST_IN)) + NdisMoveMemory(TransferBuffer, tmpBuf, TransferBufferLength); + up(&(pAd->UsbVendorReq_semaphore)); +#endif // INF_AMAZON_SE // + + if (ret < 0) { +// DBGPRINT(RT_DEBUG_ERROR, ("USBVendorRequest failed ret=%d \n",ret)); + DBGPRINT(RT_DEBUG_ERROR, ("RTUSB_VendorRequest failed(%d),TxFlags=0x%x, ReqType=%s, Req=0x%x, Index=0x%x\n", + ret, TransferFlags, (RequestType == DEVICE_VENDOR_REQUEST_OUT ? "OUT" : "IN"), Request, Index)); + if (Request == 0x2) + DBGPRINT(RT_DEBUG_ERROR, ("\tRequest Value=0x%04x!\n", Value)); + + if ((TransferBuffer!= NULL) && (TransferBufferLength > 0)) + hex_dump("Failed TransferBuffer value", TransferBuffer, TransferBufferLength); + } + } + return ret; +} + +/* + ======================================================================== + + Routine Description: + Creates an IRP to submite an IOCTL_INTERNAL_USB_RESET_PORT + synchronously. Callers of this function must be running at + PASSIVE LEVEL. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +NTSTATUS RTUSB_ResetDevice( + IN PRTMP_ADAPTER pAd) +{ + NTSTATUS Status = TRUE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->USB_ResetDevice\n")); + //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); + return Status; +} + +VOID CMDHandler( + IN PRTMP_ADAPTER pAd) +{ + PCmdQElmt cmdqelmt; + PUCHAR pData; + NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; +// ULONG Now = 0; + NTSTATUS ntStatus; +// unsigned long IrqFlags; + + while (pAd->CmdQ.size > 0) + { + NdisStatus = NDIS_STATUS_SUCCESS; + + NdisAcquireSpinLock(&pAd->CmdQLock); + RTUSBDequeueCmd(&pAd->CmdQ, &cmdqelmt); + NdisReleaseSpinLock(&pAd->CmdQLock); + + if (cmdqelmt == NULL) + break; + + pData = cmdqelmt->buffer; + + if(!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) + { + switch (cmdqelmt->command) + { + case CMDTHREAD_CHECK_GPIO: + { +#ifdef CONFIG_STA_SUPPORT + UINT32 data; +#endif // CONFIG_STA_SUPPORT // +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + break; + } +#endif // RALINK_ATE // + +#ifdef CONFIG_STA_SUPPORT + + + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Read GPIO pin2 as Hardware controlled radio state + + RTUSBReadMACRegister( pAd, GPIO_CTRL_CFG, &data); + + if (data & 0x04) + { + pAd->StaCfg.bHwRadio = TRUE; + } + else + { + pAd->StaCfg.bHwRadio = FALSE; + } + + if(pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if(pAd->StaCfg.bRadio == TRUE) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio On !!!\n")); + + MlmeRadioOn(pAd); + // Update extra information + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + } + else + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio Off !!!\n")); + + MlmeRadioOff(pAd); + // Update extra information + pAd->ExtraInfo = HW_RADIO_OFF; + } + } + } +#endif // CONFIG_STA_SUPPORT // + } + break; + +#ifdef CONFIG_STA_SUPPORT + case CMDTHREAD_QKERIODIC_EXECUT: + { + StaQuickResponeForRateUpExec(NULL, pAd, NULL, NULL); + } + break; +#endif // CONFIG_STA_SUPPORT // + + case CMDTHREAD_RESET_BULK_OUT: + { + UINT32 MACValue; + UCHAR Index; + int ret=0; + PHT_TX_CONTEXT pHTTXContext; +// RTMP_TX_RING *pTxRing; + unsigned long IrqFlags; +#ifdef RALINK_ATE + PTX_CONTEXT pNullContext = &(pAd->NullContext); +#endif // RALINK_ATE // + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", pAd->bulkResetPipeid)); + // All transfers must be aborted or cancelled before attempting to reset the pipe. + //RTUSBCancelPendingBulkOutIRP(pAd); + // Wait 10ms to let previous packet that are already in HW FIFO to clear. by MAXLEE 12-25-2007 + Index = 0; + do + { + RTUSBReadMACRegister(pAd, TXRXQ_PCNT, &MACValue); + if ((MACValue & 0xf00000/*0x800000*/) == 0) + break; + Index++; + RTMPusecDelay(10000); + }while(Index < 100); + MACValue = 0; + RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); + // To prevent Read Register error, we 2nd check the validity. + if ((MACValue & 0xc00000) == 0) + RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); + // To prevent Read Register error, we 3rd check the validity. + if ((MACValue & 0xc00000) == 0) + RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); + MACValue |= 0x80000; + RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); + + // Wait 1ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 + RTMPusecDelay(1000); + + MACValue &= (~0x80000); + RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tSet 0x2a0 bit19. Clear USB DMA TX path\n")); + + // Wait 5ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 + //RTMPusecDelay(5000); + + if ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG) + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) + { + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); + } + RTUSBKickBulkOut(pAd); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tTX MGMT RECOVER Done!\n")); + } + else + { + pHTTXContext = &(pAd->TxContext[pAd->bulkResetPipeid]); + //NdisAcquireSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); + RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + if ( pAd->BulkOutPending[pAd->bulkResetPipeid] == FALSE) + { + pAd->BulkOutPending[pAd->bulkResetPipeid] = TRUE; + pHTTXContext->IRPPending = TRUE; + pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 1; + + // no matter what, clean the flag + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + + //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); + RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); +/*-----------------------------------------------------------------------------------------------*/ +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + pNullContext->IRPPending = TRUE; + // + // If driver is still in ATE TXFRAME mode, + // keep on transmitting ATE frames. + // + DBGPRINT_RAW(RT_DEBUG_TRACE, ("pAd->ate.Mode == %d\npAd->ContinBulkOut == %d\npAd->BulkOutRemained == %d\n", pAd->ate.Mode, pAd->ContinBulkOut, atomic_read(&pAd->BulkOutRemained))); + if((pAd->ate.Mode == ATE_TXFRAME) && ((pAd->ContinBulkOut == TRUE) || (atomic_read(&pAd->BulkOutRemained) > 0))) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("After CMDTHREAD_RESET_BULK_OUT, continue to bulk out frames !\n")); + + // Init Tx context descriptor + RTUSBInitTxDesc(pAd, pNullContext, 0/* pAd->bulkResetPipeid */, (usb_complete_t)ATE_RTUSBBulkOutDataPacketComplete); + + if((ret = RTUSB_SUBMIT_URB(pNullContext->pUrb))!=0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ATE_RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret)); + } + + pAd->BulkOutReq++; + } + } + else +#endif // RALINK_ATE // +/*-----------------------------------------------------------------------------------------------*/ + { + RTUSBInitHTTxDesc(pAd, pHTTXContext, pAd->bulkResetPipeid, pHTTXContext->BulkOutSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete); + + if((ret = RTUSB_SUBMIT_URB(pHTTXContext->pUrb))!=0) + { + RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + pAd->BulkOutPending[pAd->bulkResetPipeid] = FALSE; + pHTTXContext->IRPPending = FALSE; + pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 0; + RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + + DBGPRINT(RT_DEBUG_ERROR, ("CmdThread : CMDTHREAD_RESET_BULK_OUT: Submit Tx URB failed %d\n", ret)); + } + else + { + RTMP_IRQ_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + DBGPRINT_RAW(RT_DEBUG_TRACE,("\tCMDTHREAD_RESET_BULK_OUT: TxContext[%d]:CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, pending=%d!\n", + pAd->bulkResetPipeid, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, + pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, pAd->BulkOutPending[pAd->bulkResetPipeid])); + DBGPRINT_RAW(RT_DEBUG_TRACE,("\t\tBulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", + pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); + RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tCMDTHREAD_RESET_BULK_OUT: Submit Tx DATA URB for failed BulkReq(0x%lx) Done, status=%d!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pHTTXContext->pUrb->status)); + + } + } + } + else + { + //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); + //RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("CmdThread : TX DATA RECOVER FAIL for BulkReq(0x%lx) because BulkOutPending[%d] is TRUE!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pAd->bulkResetPipeid)); + if (pAd->bulkResetPipeid == 0) + { + UCHAR pendingContext = 0; + PHT_TX_CONTEXT pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[pAd->bulkResetPipeid ]); + PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa); + PTX_CONTEXT pNULLContext = (PTX_CONTEXT)(&pAd->PsPollContext); + PTX_CONTEXT pPsPollContext = (PTX_CONTEXT)(&pAd->NullContext); + + if (pHTTXContext->IRPPending) + pendingContext |= 1; + else if (pMLMEContext->IRPPending) + pendingContext |= 2; + else if (pNULLContext->IRPPending) + pendingContext |= 4; + else if (pPsPollContext->IRPPending) + pendingContext |= 8; + else + pendingContext = 0; + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("\tTX Occupied by %d!\n", pendingContext)); + } + + // no matter what, clean the flag + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + + RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << pAd->bulkResetPipeid)); + } + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + //RTUSBKickBulkOut(pAd); + } + + } + /* + // Don't cancel BULKIN. + while ((atomic_read(&pAd->PendingRx) > 0) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + if (atomic_read(&pAd->PendingRx) > 0) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!cancel it!\n")); + RTUSBCancelPendingBulkInIRP(pAd); + } + RTMPusecDelay(100000); + } + + if ((atomic_read(&pAd->PendingRx) == 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) + { + UCHAR i; + RTUSBRxPacket(pAd); + pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index + pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer + for (i = 0; i < (RX_RING_SIZE); i++) + { + PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + + pRxContext->pAd = pAd; + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; + pRxContext->ReorderInUse = FALSE; + + } + RTUSBBulkReceive(pAd); + DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTUSBBulkReceive\n")); + }*/ + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT<===\n")); + break; + + case CMDTHREAD_RESET_BULK_IN: + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n")); + + // All transfers must be aborted or cancelled before attempting to reset the pipe. + { + UINT32 MACValue; +/*-----------------------------------------------------------------------------------------------*/ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + if((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("ATE : BulkIn IRP Pending!!!\n")); + ATE_RTUSBCancelPendingBulkInIRP(pAd); + RTMPusecDelay(100000); + pAd->PendingRx = 0; + } + } + else +#endif // RALINK_ATE // +/*-----------------------------------------------------------------------------------------------*/ + { + //while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + if((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!!\n")); + RTUSBCancelPendingBulkInIRP(pAd); + RTMPusecDelay(100000); + pAd->PendingRx = 0; + } + } + + // Wait 10ms before reading register. + RTMPusecDelay(10000); + ntStatus = RTUSBReadMACRegister(pAd, MAC_CSR0, &MACValue); + + if ((NT_SUCCESS(ntStatus) == TRUE) && + (!(RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))))) + { + UCHAR i; + + if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))) + break; + pAd->NextRxBulkInPosition = pAd->RxContext[pAd->NextRxBulkInIndex].BulkInOffset; + DBGPRINT(RT_DEBUG_TRACE, ("BULK_IN_RESET: NBIIdx=0x%x,NBIRIdx=0x%x, BIRPos=0x%lx. BIReq=x%lx, BIComplete=0x%lx, BICFail0x%lx\n", + pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pAd->NextRxBulkInPosition, pAd->BulkInReq, pAd->BulkInComplete, pAd->BulkInCompleteFail)); + for (i = 0; i < RX_RING_SIZE; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("\tRxContext[%d]: IRPPending=%d, InUse=%d, Readable=%d!\n" + , i, pAd->RxContext[i].IRPPending, pAd->RxContext[i].InUse, pAd->RxContext[i].Readable)); + } + /* + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("==========================================\n")); + + pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index + pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer + for (i = 0; i < (RX_RING_SIZE); i++) + { + PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + + pRxContext->pAd = pAd; + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; + pRxContext->ReorderInUse = FALSE; + + }*/ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); + for (i = 0; i < pAd->CommonCfg.NumOfBulkInIRP; i++) + { + //RTUSBBulkReceive(pAd); + PRX_CONTEXT pRxContext; + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; + + + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); + if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE)) + { + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + break; + } + pRxContext->InUse = TRUE; + pRxContext->IRPPending = TRUE; + pAd->PendingRx++; + pAd->BulkInReq++; + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + + // Init Rx context descriptor + RTUSBInitRxDesc(pAd, pRxContext); + pUrb = pRxContext->pUrb; + if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0) + { // fail + + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pAd->PendingRx--; + pAd->BulkInReq--; + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB failed(%d), status=%d\n", ret, pUrb->status)); + } + else + { // success + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB Done, status=%d!\n", pUrb->status)); + ASSERT((pRxContext->InUse == pRxContext->IRPPending)); + } + } + + } + else + { + // Card must be removed + if (NT_SUCCESS(ntStatus) != TRUE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Read Register Failed!Card must be removed!!\n\n")); + } + else + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Cannot do bulk in because flags(0x%lx) on !\n", pAd->Flags)); + } + } + } + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n")); + break; + + case CMDTHREAD_SET_ASIC_WCID: + { + RT_SET_ASIC_WCID SetAsicWcid; + USHORT offset; + UINT32 MACValue, MACRValue = 0; + SetAsicWcid = *((PRT_SET_ASIC_WCID)(pData)); + + if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE) + return; + + offset = MAC_WCID_BASE + ((UCHAR)SetAsicWcid.WCID)*HW_WCID_ENTRY_SIZE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, SetTid = %lx, DeleteTid = %lx.\n", SetAsicWcid.WCID, SetAsicWcid.SetTid, SetAsicWcid.DeleteTid)); + MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[3]<<24)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[2]<<16)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[1]<<8)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[0]); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("1-MACValue= %x,\n", MACValue)); + RTUSBWriteMACRegister(pAd, offset, MACValue); + // Read bitmask + RTUSBReadMACRegister(pAd, offset+4, &MACRValue); + if ( SetAsicWcid.DeleteTid != 0xffffffff) + MACRValue &= (~SetAsicWcid.DeleteTid); + if (SetAsicWcid.SetTid != 0xffffffff) + MACRValue |= (SetAsicWcid.SetTid); + MACRValue &= 0xffff0000; + + MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[5]<<8)+pAd->MacTab.Content[SetAsicWcid.WCID].Addr[4]; + MACValue |= MACRValue; + RTUSBWriteMACRegister(pAd, offset+4, MACValue); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-MACValue= %x,\n", MACValue)); + } + break; + + case CMDTHREAD_SET_ASIC_WCID_CIPHER: + { +#ifdef CONFIG_STA_SUPPORT + RT_SET_ASIC_WCID_ATTRI SetAsicWcidAttri; + USHORT offset; + UINT32 MACRValue = 0; + SHAREDKEY_MODE_STRUC csr1; + SetAsicWcidAttri = *((PRT_SET_ASIC_WCID_ATTRI)(pData)); + + if (SetAsicWcidAttri.WCID >= MAX_LEN_OF_MAC_TABLE) + return; + + offset = MAC_WCID_ATTRIBUTE_BASE + ((UCHAR)SetAsicWcidAttri.WCID)*HW_WCID_ATTRI_SIZE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("Cmd : CMDTHREAD_SET_ASIC_WCID_CIPHER : WCID = %ld, Cipher = %lx.\n", SetAsicWcidAttri.WCID, SetAsicWcidAttri.Cipher)); + // Read bitmask + RTUSBReadMACRegister(pAd, offset, &MACRValue); + MACRValue = 0; + MACRValue |= (((UCHAR)SetAsicWcidAttri.Cipher) << 1); + + RTUSBWriteMACRegister(pAd, offset, MACRValue); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-offset = %x , MACValue= %x,\n", offset, MACRValue)); + + offset = PAIRWISE_IVEIV_TABLE_BASE + ((UCHAR)SetAsicWcidAttri.WCID)*HW_IVEIV_ENTRY_SIZE; + MACRValue = 0; + if ( (SetAsicWcidAttri.Cipher <= CIPHER_WEP128)) + MACRValue |= ( pAd->StaCfg.DefaultKeyId << 30); + else + MACRValue |= (0x20000000); + RTUSBWriteMACRegister(pAd, offset, MACRValue); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-offset = %x , MACValue= %x,\n", offset, MACRValue)); + + // + // Update cipher algorithm. WSTA always use BSS0 + // + // for adhoc mode only ,because wep status slow than add key, when use zero config + if (pAd->StaCfg.BssType == BSS_ADHOC ) + { + offset = MAC_WCID_ATTRIBUTE_BASE; + + RTUSBReadMACRegister(pAd, offset, &MACRValue); + MACRValue &= (~0xe); + MACRValue |= (((UCHAR)SetAsicWcidAttri.Cipher) << 1); + + RTUSBWriteMACRegister(pAd, offset, MACRValue); + + //Update group key cipher,,because wep status slow than add key, when use zero config + RTUSBReadMACRegister(pAd, SHARED_KEY_MODE_BASE+4*(0/2), &csr1.word); + + csr1.field.Bss0Key0CipherAlg = SetAsicWcidAttri.Cipher; + csr1.field.Bss0Key1CipherAlg = SetAsicWcidAttri.Cipher; + + RTUSBWriteMACRegister(pAd, SHARED_KEY_MODE_BASE+4*(0/2), csr1.word); + } +#endif // CONFIG_STA_SUPPORT // + } + break; + +//Benson modified for USB interface, avoid in interrupt when write key, 20080724 --> + case RT_CMD_SET_KEY_TABLE: //General call for AsicAddPairwiseKeyEntry() + { + RT_ADD_PAIRWISE_KEY_ENTRY KeyInfo; + KeyInfo = *((PRT_ADD_PAIRWISE_KEY_ENTRY)(pData)); + AsicAddPairwiseKeyEntry(pAd, + KeyInfo.MacAddr, + (UCHAR)KeyInfo.MacTabMatchWCID, + &KeyInfo.CipherKey); + } + break; + case RT_CMD_SET_RX_WCID_TABLE: //General call for RTMPAddWcidAttributeEntry() + { + PMAC_TABLE_ENTRY pEntry; + UCHAR KeyIdx; + UCHAR CipherAlg; + UCHAR ApIdx; + + pEntry = (PMAC_TABLE_ENTRY)(pData); + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + KeyIdx = 0; + CipherAlg = pEntry->PairwiseKey.CipherAlg; + ApIdx = BSS0; +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + + + RTMPAddWcidAttributeEntry( + pAd, + ApIdx, + KeyIdx, + CipherAlg, + pEntry); + } + break; +//Benson modified for USB interface, avoid in interrupt when write key, 20080724 <-- + + case CMDTHREAD_SET_CLIENT_MAC_ENTRY: + { + MAC_TABLE_ENTRY *pEntry; + pEntry = (MAC_TABLE_ENTRY *)pData; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)pEntry->Aid); + if ((pEntry->AuthMode <= Ndis802_11AuthModeAutoSwitch) && (pEntry->WepStatus == Ndis802_11Encryption1Enabled)) + { + UINT32 uIV = 0; + PUCHAR ptr; + + ptr = (PUCHAR) &uIV; + *(ptr + 3) = (pAd->StaCfg.DefaultKeyId << 6); + AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, uIV, 0); + AsicUpdateWCIDAttribute(pAd, pEntry->Aid, BSS0, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, FALSE); + } + else if (pEntry->AuthMode == Ndis802_11AuthModeWPANone) + { + UINT32 uIV = 0; + PUCHAR ptr; + + ptr = (PUCHAR) &uIV; + *(ptr + 3) = (pAd->StaCfg.DefaultKeyId << 6); + AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, uIV, 0); + AsicUpdateWCIDAttribute(pAd, pEntry->Aid, BSS0, pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, FALSE); + } + else + { + // + // Other case, disable engine. + // Don't worry WPA key, we will add WPA Key after 4-Way handshaking. + // + USHORT offset; + offset = MAC_WCID_ATTRIBUTE_BASE + (pEntry->Aid * HW_WCID_ATTRI_SIZE); + // RX_PKEY_MODE:0 for no security; RX_KEY_TAB:0 for shared key table; BSS_IDX:0 + RTUSBWriteMACRegister(pAd, offset, 0); + } + } +#endif // CONFIG_STA_SUPPORT // + + AsicUpdateRxWCIDTable(pAd, pEntry->Aid, pEntry->Addr); + printk("UpdateRxWCIDTable(): Aid=%d, Addr=%02x:%02x:%02x:%02x:%02x:%02x!\n", pEntry->Aid, + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + } + break; + +// add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet + case CMDTHREAD_UPDATE_PROTECT: + { + AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT), TRUE, 0); + } + break; +// end johnli + + case OID_802_11_ADD_WEP: + { +#ifdef CONFIG_STA_SUPPORT + UINT i; + UINT32 KeyIdx; + PNDIS_802_11_WEP pWepKey; + + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::OID_802_11_ADD_WEP \n")); + + pWepKey = (PNDIS_802_11_WEP)pData; + KeyIdx = pWepKey->KeyIndex & 0x0fffffff; + + // it is a shared key + if ((KeyIdx >= 4) || ((pWepKey->KeyLength != 5) && (pWepKey->KeyLength != 13))) + { + NdisStatus = NDIS_STATUS_INVALID_DATA; + DBGPRINT(RT_DEBUG_ERROR, ("CmdThread::OID_802_11_ADD_WEP, INVALID_DATA!!\n")); + } + else + { + UCHAR CipherAlg; + pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); + CipherAlg = (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 5)? CIPHER_WEP64 : CIPHER_WEP128; + + // + // Change the WEP cipher to CKIP cipher if CKIP KP on. + // Funk UI or Meetinghouse UI will add ckip key from this path. + // + + if (pAd->OpMode == OPMODE_STA) + { + pAd->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + pAd->MacTab.Content[BSSID_WCID].PairwiseKey.KeyLen = pAd->SharedKey[BSS0][KeyIdx].KeyLen; + } + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg; + if (pWepKey->KeyIndex & 0x80000000) + { + // Default key for tx (shared key) + UCHAR IVEIV[8]; + UINT32 WCIDAttri, Value; + USHORT offset, offset2; + NdisZeroMemory(IVEIV, 8); + pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; + // Add BSSID to WCTable. because this is Tx wep key. + // WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:1=PAIRWISE KEY, BSSIdx is 0 + WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE; + + offset = MAC_WCID_ATTRIBUTE_BASE + (BSSID_WCID* HW_WCID_ATTRI_SIZE); + RTUSBWriteMACRegister(pAd, offset, WCIDAttri); + // 1. IV/EIV + // Specify key index to find shared key. + IVEIV[3] = (UCHAR)(KeyIdx<< 6); //WEP Eiv bit off. groupkey index is not 0 + offset = PAIRWISE_IVEIV_TABLE_BASE + (BSS0Mcast_WCID * HW_IVEIV_ENTRY_SIZE); + offset2 = PAIRWISE_IVEIV_TABLE_BASE + (BSSID_WCID* HW_IVEIV_ENTRY_SIZE); + for (i=0; i<8;) + { + Value = IVEIV[i]; + Value += (IVEIV[i+1]<<8); + Value += (IVEIV[i+2]<<16); + Value += (IVEIV[i+3]<<24); + RTUSBWriteMACRegister(pAd, offset+i, Value); + RTUSBWriteMACRegister(pAd, offset2+i, Value); + i+=4; + } + + // 2. WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:use share key, BSSIdx is 0 + WCIDAttri = (pAd->SharedKey[BSS0][KeyIdx].CipherAlg<<1)|SHAREDKEYTABLE; + offset = MAC_WCID_ATTRIBUTE_BASE + (BSS0Mcast_WCID* HW_WCID_ATTRI_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("BSS0Mcast_WCID : offset = %x, WCIDAttri = %x\n", offset, WCIDAttri)); + RTUSBWriteMACRegister(pAd, offset, WCIDAttri); + + } + AsicAddSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx, CipherAlg, pWepKey->KeyMaterial, NULL, NULL); + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::OID_802_11_ADD_WEP (KeyIdx=%d, Len=%d-byte)\n", KeyIdx, pWepKey->KeyLength)); + } +#endif // CONFIG_STA_SUPPORT // + } + break; + + case CMDTHREAD_802_11_COUNTER_MEASURE: + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, ("--> Control Thread !! ERROR !! Unknown(cmdqelmt->command=0x%x) !! \n", cmdqelmt->command)); + break; + } + } + + if (cmdqelmt->CmdFromNdis == TRUE) + { + if (cmdqelmt->buffer != NULL) + NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0); + + NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); + } + else + { + if ((cmdqelmt->buffer != NULL) && (cmdqelmt->bufferlength != 0)) + NdisFreeMemory(cmdqelmt->buffer, cmdqelmt->bufferlength, 0); + { + NdisFreeMemory(cmdqelmt, sizeof(CmdQElmt), 0); + } + } + } /* end of while */ +} + diff --git a/drivers/staging/rt3070/common/spectrum.c b/drivers/staging/rt3070/common/spectrum.c new file mode 100644 index 000000000000..da57b1202d64 --- /dev/null +++ b/drivers/staging/rt3070/common/spectrum.c @@ -0,0 +1,1876 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + action.c + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Fonchi Wu 2008 created for 802.11h + */ + +#include "../rt_config.h" +#include "../action.h" + +VOID MeasureReqTabInit( + IN PRTMP_ADAPTER pAd) +{ + NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock); + + pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC); + if (pAd->CommonCfg.pMeasureReqTab) + NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __FUNCTION__)); + + return; +} + +VOID MeasureReqTabExit( + IN PRTMP_ADAPTER pAd) +{ + NdisFreeSpinLock(pAd->CommonCfg.MeasureReqTabLock); + + if (pAd->CommonCfg.pMeasureReqTab) + kfree(pAd->CommonCfg.pMeasureReqTab); + pAd->CommonCfg.pMeasureReqTab = NULL; + + return; +} + +static PMEASURE_REQ_ENTRY MeasureReqLookUp( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + UINT HashIdx; + PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; + PMEASURE_REQ_ENTRY pEntry = NULL; + PMEASURE_REQ_ENTRY pPrevEntry = NULL; + + if (pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + + HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); + pEntry = pTab->Hash[HashIdx]; + + while (pEntry) + { + if (pEntry->DialogToken == DialogToken) + break; + else + { + pPrevEntry = pEntry; + pEntry = pEntry->pNext; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + + return pEntry; +} + +static PMEASURE_REQ_ENTRY MeasureReqInsert( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + INT i; + ULONG HashIdx; + PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; + PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry; + ULONG Now; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + pEntry = MeasureReqLookUp(pAd, DialogToken); + if (pEntry == NULL) + { + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) + { + NdisGetSystemUpTime(&Now); + pEntry = &pTab->Content[i]; + + if ((pEntry->Valid == TRUE) + && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT))) + { + PMEASURE_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); + pTab->Size--; + + break; + } + + if (pEntry->Valid == FALSE) + break; + } + + if (i < MAX_MEASURE_REQ_TAB_SIZE) + { + NdisGetSystemUpTime(&Now); + pEntry->lastTime = Now; + pEntry->Valid = TRUE; + pEntry->DialogToken = DialogToken; + pTab->Size++; + } + else + { + pEntry = NULL; + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __FUNCTION__)); + } + + // add this Neighbor entry into HASH table + if (pEntry) + { + HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken); + if (pTab->Hash[HashIdx] == NULL) + { + pTab->Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pTab->Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + } + + return pEntry; +} + +static VOID MeasureReqDelete( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab; + PMEASURE_REQ_ENTRY pEntry = NULL; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__)); + return; + } + + // if empty, return + if (pTab->Size == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n")); + return; + } + + pEntry = MeasureReqLookUp(pAd, DialogToken); + if (pEntry != NULL) + { + PMEASURE_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY)); + pTab->Size--; + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + } + + return; +} + +VOID TpcReqTabInit( + IN PRTMP_ADAPTER pAd) +{ + NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock); + + pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC); + if (pAd->CommonCfg.pTpcReqTab) + NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __FUNCTION__)); + + return; +} + +VOID TpcReqTabExit( + IN PRTMP_ADAPTER pAd) +{ + NdisFreeSpinLock(pAd->CommonCfg.TpcReqTabLock); + + if (pAd->CommonCfg.pTpcReqTab) + kfree(pAd->CommonCfg.pTpcReqTab); + pAd->CommonCfg.pTpcReqTab = NULL; + + return; +} + +static PTPC_REQ_ENTRY TpcReqLookUp( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + UINT HashIdx; + PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; + PTPC_REQ_ENTRY pEntry = NULL; + PTPC_REQ_ENTRY pPrevEntry = NULL; + + if (pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); + + HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); + pEntry = pTab->Hash[HashIdx]; + + while (pEntry) + { + if (pEntry->DialogToken == DialogToken) + break; + else + { + pPrevEntry = pEntry; + pEntry = pEntry->pNext; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); + + return pEntry; +} + + +static PTPC_REQ_ENTRY TpcReqInsert( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + INT i; + ULONG HashIdx; + PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; + PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry; + ULONG Now; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); + return NULL; + } + + pEntry = TpcReqLookUp(pAd, DialogToken); + if (pEntry == NULL) + { + RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); + for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) + { + NdisGetSystemUpTime(&Now); + pEntry = &pTab->Content[i]; + + if ((pEntry->Valid == TRUE) + && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT))) + { + PTPC_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); + pTab->Size--; + + break; + } + + if (pEntry->Valid == FALSE) + break; + } + + if (i < MAX_TPC_REQ_TAB_SIZE) + { + NdisGetSystemUpTime(&Now); + pEntry->lastTime = Now; + pEntry->Valid = TRUE; + pEntry->DialogToken = DialogToken; + pTab->Size++; + } + else + { + pEntry = NULL; + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __FUNCTION__)); + } + + // add this Neighbor entry into HASH table + if (pEntry) + { + HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken); + if (pTab->Hash[HashIdx] == NULL) + { + pTab->Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pTab->Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); + } + + return pEntry; +} + +static VOID TpcReqDelete( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken) +{ + PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab; + PTPC_REQ_ENTRY pEntry = NULL; + + if(pTab == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__)); + return; + } + + // if empty, return + if (pTab->Size == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n")); + return; + } + + pEntry = TpcReqLookUp(pAd, DialogToken); + if (pEntry != NULL) + { + PTPC_REQ_ENTRY pPrevEntry = NULL; + ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken); + PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx]; + + RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock); + // update Hash list + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pTab->Hash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + + NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY)); + pTab->Size--; + + RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock); + } + + return; +} + +/* + ========================================================================== + Description: + Get Current TimeS tamp. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +static UINT64 GetCurrentTimeStamp( + IN PRTMP_ADAPTER pAd) +{ + // get current time stamp. + return 0; +} + +/* + ========================================================================== + Description: + Get Current Transmit Power. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +static UINT8 GetCurTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 Wcid) +{ + return 16; /* 16 dBm */ +} + +/* + ========================================================================== + Description: + Insert Dialog Token into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Dialog token. + + Return : None. + ========================================================================== + */ +static VOID InsertDialogToken( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 DialogToken) +{ + ULONG TempLen; + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &DialogToken, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* + ========================================================================== + Description: + Insert TPC Request IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + + Return : None. + ========================================================================== + */ + static VOID InsertTpcReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + ULONG Len = 0; + UINT8 ElementID = IE_TPC_REQUEST; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* + ========================================================================== + Description: + Insert TPC Report IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Transmit Power. + 4. Link Margin. + + Return : None. + ========================================================================== + */ + static VOID InsertTpcReportIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 TxPwr, + IN UINT8 LinkMargin) +{ + ULONG TempLen; + ULONG Len = sizeof(TPC_REPORT_INFO); + UINT8 ElementID = IE_TPC_REPORT; + TPC_REPORT_INFO TpcReportIE; + + TpcReportIE.TxPwr = TxPwr; + TpcReportIE.LinkMargin = LinkMargin; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, &TpcReportIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + + return; +} + +/* + ========================================================================== + Description: + Insert Channel Switch Announcement IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. channel switch announcement mode. + 4. new selected channel. + 5. channel switch announcement count. + + Return : None. + ========================================================================== + */ +static VOID InsertChSwAnnIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ChSwMode, + IN UINT8 NewChannel, + IN UINT8 ChSwCnt) +{ + ULONG TempLen; + ULONG Len = sizeof(CH_SW_ANN_INFO); + UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT; + CH_SW_ANN_INFO ChSwAnnIE; + + ChSwAnnIE.ChSwMode = ChSwMode; + ChSwAnnIE.Channel = NewChannel; + ChSwAnnIE.ChSwCnt = ChSwCnt; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, &ChSwAnnIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + + return; +} + +/* + ========================================================================== + Description: + Insert Measure Request IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Measure Token. + 4. Measure Request Mode. + 5. Measure Request Type. + 6. Measure Channel. + 7. Measure Start time. + 8. Measure Duration. + + + Return : None. + ========================================================================== + */ +static VOID InsertMeasureReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PMEASURE_REQ_INFO pMeasureReqIE) +{ + ULONG TempLen; + UINT8 Len = sizeof(MEASURE_REQ_INFO); + UINT8 ElementID = IE_MEASUREMENT_REQUEST; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, pMeasureReqIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +/* + ========================================================================== + Description: + Insert Measure Report IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Measure Token. + 4. Measure Request Mode. + 5. Measure Request Type. + 6. Length of Report Infomation + 7. Pointer of Report Infomation Buffer. + + Return : None. + ========================================================================== + */ +static VOID InsertMeasureReportIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PMEASURE_REPORT_INFO pMeasureReportIE, + IN UINT8 ReportLnfoLen, + IN PUINT8 pReportInfo) +{ + ULONG TempLen; + ULONG Len; + UINT8 ElementID = IE_MEASUREMENT_REPORT; + + Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, pMeasureReportIE, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) + { + MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen, + ReportLnfoLen, pReportInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + return; +} + +/* + ========================================================================== + Description: + Prepare Measurement request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 MeasureCh, + IN UINT16 MeasureDuration) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + HEADER_802_11 ActHdr; + MEASURE_REQ_INFO MeasureReqIE; + UINT8 RmReqDailogToken = RandomByte(pAd); + UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd); + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRQ); + + // fill Dialog Token + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, MeasureToken); + + // prepare Measurement IE. + NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO)); + MeasureReqIE.Token = RmReqDailogToken; + MeasureReqIE.ReqMode.word = MeasureReqMode; + MeasureReqIE.ReqType = MeasureReqType; + MeasureReqIE.MeasureReq.ChNum = MeasureCh; + MeasureReqIE.MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime); + MeasureReqIE.MeasureReq.MeasureDuration = cpu2le16(MeasureDuration); + InsertMeasureReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureReqIE); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare Measurement report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 ReportInfoLen, + IN PUINT8 pReportInfo) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + HEADER_802_11 ActHdr; + MEASURE_REPORT_INFO MeasureRepIE; + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP); + + // fill Dialog Token + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + // prepare Measurement IE. + NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO)); + MeasureRepIE.Token = MeasureToken; + MeasureRepIE.ReportMode.word = MeasureReqMode; + MeasureRepIE.ReportType = MeasureReqType; + InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare TPC Request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UCHAR DialogToken) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ); + + // fill Dialog Token + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + // Insert TPC Request IE. + InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare TPC Report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 TxPwr, + IN UINT8 LinkMargin) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP); + + // fill Dialog Token + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + // Insert TPC Request IE. + InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +/* + ========================================================================== + Description: + Prepare Channel Switch Announcement action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + 2. Channel switch announcement mode. + 2. a New selected channel. + + Return : None. + ========================================================================== + */ +VOID EnqueueChSwAnn( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 ChSwMode, + IN UINT8 NewCh) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + // build action frame header. + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); + + InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +static BOOLEAN DfsRequirementCheck( + IN PRTMP_ADAPTER pAd, + IN UINT8 Channel) +{ + BOOLEAN Result = FALSE; + INT i; + + do + { + // check DFS procedure is running. + // make sure DFS procedure won't start twice. + if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) + { + Result = FALSE; + break; + } + + // check the new channel carried from Channel Switch Announcemnet is valid. + for (i=0; iChannelListNum; i++) + { + if ((Channel == pAd->ChannelList[i].Channel) + &&(pAd->ChannelList[i].RemainingTimeForUse == 0)) + { + // found radar signal in the channel. the channel can't use at least for 30 minutes. + pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec + Result = TRUE; + break; + } + } + } while(FALSE); + + return Result; +} + +VOID NotifyChSwAnnToPeerAPs( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRA, + IN PUCHAR pTA, + IN UINT8 ChSwMode, + IN UINT8 Channel) +{ +#ifdef WDS_SUPPORT + if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address. + { + INT i; + // info neighbor APs that Radar signal found throgh WDS link. + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + if (ValidWdsEntry(pAd, i)) + { + PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr; + + // DA equal to SA. have no necessary orignal AP which found Radar signal. + if (MAC_ADDR_EQUAL(pTA, pDA)) + continue; + + // send Channel Switch Action frame to info Neighbro APs. + EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel); + } + } + } +#endif // WDS_SUPPORT // +} + +static VOID StartDFSProcedure( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN UINT8 ChSwMode) +{ + // start DFS procedure + pAd->CommonCfg.Channel = Channel; +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); +#endif // DOT11_N_SUPPORT // + pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE; + pAd->CommonCfg.RadarDetect.CSCount = 0; +} + +/* + ========================================================================== + Description: + Channel Switch Announcement action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Channel switch announcement infomation buffer. + + + Return : None. + ========================================================================== + */ + +/* + Channel Switch Announcement IE. + +----+-----+-----------+------------+-----------+ + | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt | + +----+-----+-----------+------------+-----------+ + 1 1 1 1 1 +*/ +static BOOLEAN PeerChSwAnnSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PCH_SW_ANN_INFO pChSwAnnInfo) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + + // skip 802.11 header. + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pChSwAnnInfo == NULL) + return result; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1); + NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1); + + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + Measurement request action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Measurement request infomation buffer. + + Return : None. + ========================================================================== + */ +static BOOLEAN PeerMeasureReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PMEASURE_REQ_INFO pMeasureReqInfo) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + PUCHAR ptr; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + + // skip 802.11 header. + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pMeasureReqInfo == NULL) + return result; + + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MEASUREMENT_REQUEST: + NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1); + NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1); + ptr = eid_ptr->Octet + 3; + NdisMoveMemory(&pMeasureReqInfo->MeasureReq.ChNum, ptr, 1); + NdisMoveMemory(&MeasureStartTime, ptr + 1, 8); + pMeasureReqInfo->MeasureReq.MeasureStartTime = SWAP64(MeasureStartTime); + NdisMoveMemory(&MeasureDuration, ptr + 9, 2); + pMeasureReqInfo->MeasureReq.MeasureDuration = SWAP16(MeasureDuration); + + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + Measurement report action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Measurement report infomation buffer. + 4. basic report infomation buffer. + + Return : None. + ========================================================================== + */ + +/* + Measurement Report IE. + +----+-----+-------+-------------+--------------+----------------+ + | ID | Len | Token | Report Mode | Measure Type | Measure Report | + +----+-----+-------+-------------+--------------+----------------+ + 1 1 1 1 1 variable + + Basic Report. + +--------+------------+----------+-----+ + | Ch Num | Start Time | Duration | Map | + +--------+------------+----------+-----+ + 1 8 2 1 + + Map Field Bit Format. + +-----+---------------+---------------------+-------+------------+----------+ + | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved | + +-----+---------------+---------------------+-------+------------+----------+ + 0 1 2 3 4 5-7 +*/ +static BOOLEAN PeerMeasureReportSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PMEASURE_REPORT_INFO pMeasureReportInfo, + OUT PUINT8 pReportBuf) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + PUCHAR ptr; + + // skip 802.11 header. + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pMeasureReportInfo == NULL) + return result; + + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MEASUREMENT_REPORT: + NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1); + NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1); + if (pMeasureReportInfo->ReportType == RM_BASIC) + { + PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf; + ptr = eid_ptr->Octet + 3; + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); + NdisMoveMemory(&pReport->Map, ptr + 11, 1); + + } + else if (pMeasureReportInfo->ReportType == RM_CCA) + { + PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf; + ptr = eid_ptr->Octet + 3; + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); + NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1); + + } + else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM) + { + PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf; + ptr = eid_ptr->Octet + 3; + NdisMoveMemory(&pReport->ChNum, ptr, 1); + NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8); + NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2); + NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8); + } + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + TPC Request action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Dialog Token. + + Return : None. + ========================================================================== + */ +static BOOLEAN PeerTpcReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pDialogToken == NULL) + return result; + + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_TPC_REQUEST: + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + TPC Report action frame sanity check. + + Parametrs: + 1. MLME message containing the received frame + 2. message length. + 3. Dialog Token. + 4. TPC Report IE. + + Return : None. + ========================================================================== + */ +static BOOLEAN PeerTpcRepSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PTPC_REPORT_INFO pTpcRepInfo) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + + MsgLen -= sizeof(HEADER_802_11); + + // skip category and action code. + pFramePtr += 2; + MsgLen -= 2; + + if (pDialogToken == NULL) + return result; + + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_TPC_REPORT: + NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1); + NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1); + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +/* + ========================================================================== + Description: + Channel Switch Announcement action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerChSwAnnAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + CH_SW_ANN_INFO ChSwAnnInfo; + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; +#ifdef CONFIG_STA_SUPPORT + UCHAR index = 0, Channel = 0, NewChannel = 0; + ULONG Bssidx = 0; +#endif // CONFIG_STA_SUPPORT // + + NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO)); + if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n")); + return; + } + + +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + { + Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel); + if (Bssidx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel)); + hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6); + + Channel = pAd->CommonCfg.Channel; + NewChannel = ChSwAnnInfo.Channel; + + if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) + { + // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). + // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. + AsicSwitchChannel(pAd, 1, FALSE); + AsicLockChannel(pAd, 1); + LinkDown(pAd, FALSE); + MlmeQueueInit(&pAd->Mlme.Queue); + BssTableInit(&pAd->ScanTab); + RTMPusecDelay(1000000); // use delay to prevent STA do reassoc + + // channel sanity check + for (index = 0 ; index < pAd->ChannelListNum; index++) + { + if (pAd->ChannelList[index].Channel == NewChannel) + { + pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; + pAd->CommonCfg.Channel = NewChannel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); + break; + } + } + + if (index >= pAd->ChannelListNum) + { + DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); + } + } + } +#endif // CONFIG_STA_SUPPORT // + + return; +} + + +/* + ========================================================================== + Description: + Measurement Request action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerMeasureReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + UINT8 DialogToken; + MEASURE_REQ_INFO MeasureReqInfo; + MEASURE_REPORT_MODE ReportMode; + + if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo)) + { + ReportMode.word = 0; + ReportMode.field.Incapable = 1; + EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL); + } + + return; +} + +/* + ========================================================================== + Description: + Measurement Report action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerMeasureReportAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MEASURE_REPORT_INFO MeasureReportInfo; + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + UINT8 DialogToken; + PUINT8 pMeasureReportInfo; + +// if (pAd->CommonCfg.bIEEE80211H != TRUE) +// return; + + if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __FUNCTION__, sizeof(MEASURE_RPI_REPORT))); + return; + } + + NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO)); + NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT)); + if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo)) + { + do { + PMEASURE_REQ_ENTRY pEntry = NULL; + + // Not a autonomous measure report. + // check the dialog token field. drop it if the dialog token doesn't match. + if ((DialogToken != 0) + && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL)) + break; + + if (pEntry != NULL) + MeasureReqDelete(pAd, pEntry->DialogToken); + + if (MeasureReportInfo.ReportType == RM_BASIC) + { + PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo; + if ((pBasicReport->Map.field.Radar) + && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE)) + { + NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum); + StartDFSProcedure(pAd, pBasicReport->ChNum, 1); + } + } + } while (FALSE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n")); + + kfree(pMeasureReportInfo); + + return; +} + +/* + ========================================================================== + Description: + TPC Request action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerTpcReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + PUCHAR pFramePtr = pFr->Octet; + UINT8 DialogToken; + UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid); + UINT8 LinkMargin = 0; + CHAR RealRssi; + + // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The + // STA may incorporate rate information and channel conditions, including interference, into its computation + // of link margin. + + RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), + ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), + ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + // skip Category and action code. + pFramePtr += 2; + + // Dialog token. + NdisMoveMemory(&DialogToken, pFramePtr, 1); + + LinkMargin = (RealRssi / MIN_RCV_PWR); + if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken)) + EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin); + + return; +} + +/* + ========================================================================== + Description: + TPC Report action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerTpcRepAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UINT8 DialogToken; + TPC_REPORT_INFO TpcRepInfo; + PTPC_REQ_ENTRY pEntry = NULL; + + NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO)); + if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) + { + if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL) + { + TpcReqDelete(pAd, pEntry->DialogToken); + DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n", + __FUNCTION__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin)); + } + } + + return; +} + +/* + ========================================================================== + Description: + Spectrun action frames Handler such as channel switch annoucement, + measurement report, measurement request actions frames. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +VOID PeerSpectrumAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (pAd->CommonCfg.bIEEE80211H != TRUE) + return; + + switch(Action) + { + case SPEC_MRQ: + // current rt2860 unable do such measure specified in Measurement Request. + // reject all measurement request. + PeerMeasureReqAction(pAd, Elem); + break; + + case SPEC_MRP: + PeerMeasureReportAction(pAd, Elem); + break; + + case SPEC_TPCRQ: + PeerTpcReqAction(pAd, Elem); + break; + + case SPEC_TPCRP: + PeerTpcRepAction(pAd, Elem); + break; + + case SPEC_CHANNEL_SWITCH: +{ +#ifdef DOT11N_DRAFT3 + SEC_CHA_OFFSET_IE Secondary; + CHA_SWITCH_ANNOUNCE_IE ChannelSwitch; + + // 802.11h only has Channel Switch Announcement IE. + RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE)); + + // 802.11n D3.03 adds secondary channel offset element in the end. + if (Elem->MsgLen == (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE))) + { + RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE)); + } + else + { + Secondary.SecondaryChannelOffset = 0; + } + + if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3)) + { + ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset); + } +#endif // DOT11N_DRAFT3 // +} + PeerChSwAnnAction(pAd, Elem); + break; + } + + return; +} + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_MeasureReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT Aid = 1; + UINT ArgIdx; + PUCHAR thisChar; + + MEASURE_REQ_MODE MeasureReqMode; + UINT8 MeasureReqToken = RandomByte(pAd); + UINT8 MeasureReqType = RM_BASIC; + UINT8 MeasureCh = 1; + + ArgIdx = 1; + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + switch(ArgIdx) + { + case 1: // Aid. + Aid = simple_strtol(thisChar, 0, 16); + break; + + case 2: // Measurement Request Type. + MeasureReqType = simple_strtol(thisChar, 0, 16); + if (MeasureReqType > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __FUNCTION__, MeasureReqType)); + return TRUE; + } + break; + + case 3: // Measurement channel. + MeasureCh = simple_strtol(thisChar, 0, 16); + break; + } + ArgIdx++; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __FUNCTION__, Aid, MeasureReqType, MeasureCh)); + if (!VALID_WCID(Aid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); + return TRUE; + } + + MeasureReqMode.word = 0; + MeasureReqMode.field.Enable = 1; + + MeasureReqInsert(pAd, MeasureReqToken); + + EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr, + MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000); + + return TRUE; +} + +INT Set_TpcReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT Aid; + + UINT8 TpcReqToken = RandomByte(pAd); + + Aid = simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __FUNCTION__, Aid)); + if (!VALID_WCID(Aid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); + return TRUE; + } + + TpcReqInsert(pAd, TpcReqToken); + + EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken); + + return TRUE; +} + diff --git a/drivers/staging/rt3070/dfs.h b/drivers/staging/rt3070/dfs.h new file mode 100644 index 000000000000..752a6352d9dd --- /dev/null +++ b/drivers/staging/rt3070/dfs.h @@ -0,0 +1,100 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + dfs.h + + Abstract: + Support DFS function. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 03-12-2007 created +*/ + +#define RADAR_PULSE 1 +#define RADAR_WIDTH 2 + +#define WIDTH_RD_IDLE 0 +#define WIDTH_RD_CHECK 1 + + +VOID BbpRadarDetectionStart( + IN PRTMP_ADAPTER pAd); + +VOID BbpRadarDetectionStop( + IN PRTMP_ADAPTER pAd); + +VOID RadarDetectionStart( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN CTS_Protect, + IN UINT8 CTSPeriod); + +VOID RadarDetectionStop( + IN PRTMP_ADAPTER pAd); + +VOID RadarDetectPeriodic( + IN PRTMP_ADAPTER pAd); + + +BOOLEAN RadarChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ch); + +ULONG JapRadarType( + IN PRTMP_ADAPTER pAd); + +ULONG RTMPBbpReadRadarDuration( + IN PRTMP_ADAPTER pAd); + +ULONG RTMPReadRadarDuration( + IN PRTMP_ADAPTER pAd); + +VOID RTMPCleanRadarDuration( + IN PRTMP_ADAPTER pAd); + +VOID RTMPPrepareRDCTSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN ULONG Duration, + IN UCHAR RTSRate, + IN ULONG CTSBaseAddr, + IN UCHAR FrameGap); + +VOID RTMPPrepareRadarDetectParams( + IN PRTMP_ADAPTER pAd); + + +INT Set_ChMovingTime_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_LongPulseRadarTh_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + + diff --git a/drivers/staging/rt3070/firmware.h b/drivers/staging/rt3070/firmware.h new file mode 100644 index 000000000000..b07783ed8dd0 --- /dev/null +++ b/drivers/staging/rt3070/firmware.h @@ -0,0 +1,558 @@ +/* + Copyright (c) 2007, Ralink Technology Corporation + All rights reserved. + + Redistribution. Redistribution and use in binary form, without + modification, are permitted provided that the following conditions are + met: + + * Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Ralink Technology Corporation nor the names of its + suppliers may be used to endorse or promote products derived from this + software without specific prior written permission. + * No reverse engineering, decompilation, or disassembly of this software + is permitted. + + Limited patent license. Ralink Technology Corporation grants a world-wide, + royalty-free, non-exclusive license under patents it now or hereafter + owns or controls to make, have made, use, import, offer to sell and + sell ("Utilize") this software, but solely to the extent that any + such patent is necessary to Utilize the software alone, or in + combination with an operating system licensed under an approved Open + Source license as listed by the Open Source Initiative at + http://opensource.org/licenses. The patent license shall not apply to + any other combinations which include this software. No hardware per + se is licensed hereunder. + + DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. +*/ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR FirmwareImage [] = { +0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x12, 0x67, 0x02, +0x12, 0x68, 0x02, 0x12, 0x87, 0x02, 0x12, 0x8c, 0x12, 0x12, 0x88, 0x22, 0x02, 0x16, 0x49, 0x02, +0x17, 0x1f, 0x02, 0x13, 0x77, 0x02, 0x12, 0x8d, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x17, +0xc1, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40, +0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4, +0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4, +0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01, +0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xc8, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02, +0x12, 0x66, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0x9d, 0x10, +0xb7, 0x31, 0x10, 0xe0, 0x50, 0x11, 0x04, 0x51, 0x11, 0x0d, 0x52, 0x11, 0x0d, 0x53, 0x11, 0x0d, +0x54, 0x11, 0x4e, 0x55, 0x11, 0x7e, 0x70, 0x11, 0xa9, 0x71, 0x11, 0xd7, 0x72, 0x12, 0x1d, 0x73, +0x12, 0x3e, 0x80, 0x00, 0x00, 0x12, 0x66, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf, +0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, +0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22, +0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x12, 0x66, 0x90, 0x70, 0x11, +0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x12, 0x66, 0x75, 0x4e, 0x03, +0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04, +0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57, +0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef, +0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, +0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0xe5, 0x47, +0x64, 0x07, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0x90, +0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, +0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0xd2, 0x04, 0x22, 0x90, 0x70, +0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, +0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, +0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, +0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, +0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, +0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x10, 0x02, 0xe0, 0xb4, 0x70, 0x1e, 0xa3, 0xe0, +0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54, +0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5, +0x4f, 0x75, 0x3a, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, +0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10, +0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, +0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70, +0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, +0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, +0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, +0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, +0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, 0xc2, 0x42, 0xd3, 0x22, 0x22, 0xc2, 0x4b, 0xc2, +0x4c, 0xe5, 0x44, 0x12, 0x0a, 0x9d, 0x12, 0xaf, 0x00, 0x13, 0x42, 0x04, 0x13, 0x3e, 0x08, 0x13, +0x19, 0x10, 0x12, 0xc3, 0x20, 0x12, 0xe3, 0x60, 0x12, 0xf4, 0xa0, 0x00, 0x00, 0x13, 0x44, 0x85, +0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x13, +0x44, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, +0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x66, 0x53, 0x43, +0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, +0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, +0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x35, 0xe5, +0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04, 0x06, 0x53, 0x5e, +0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5, +0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b, +0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54, +0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3, 0xe5, 0x4a, 0xf0, +0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3, 0xe5, 0x42, 0xf0, +0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0, 0x70, 0x03, 0x12, +0x16, 0x29, 0x12, 0x13, 0x8c, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x90, 0x04, +0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, 0x24, 0xff, +0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e, 0xf0, 0xe5, +0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f, 0x20, 0xe5, +0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x25, 0x70, 0x05, +0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, 0x5f, 0x30, +0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, 0x64, 0x03, +0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, 0x70, 0x03, 0x30, +0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, 0x15, 0x25, 0xd2, +0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, 0x3a, 0x64, +0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5, +0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5, +0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c, +0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, +0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, +0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, +0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, +0x26, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, +0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, +0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, +0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, +0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, +0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, +0x90, 0x10, 0x2f, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92, +0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, +0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4c, 0x90, 0x02, 0x29, +0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe, 0x60, 0x23, +0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x18, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0f, 0x80, 0x07, +0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x06, 0x54, 0xfe, 0xf0, 0x02, 0x16, 0x18, 0x44, 0x01, 0xf0, +0x02, 0x16, 0x18, 0xe5, 0x46, 0x30, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02, +0x28, 0xe0, 0x54, 0xfe, 0x4f, 0xf0, 0x02, 0x16, 0x18, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5, +0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, 0x16, 0x18, 0xe4, 0xf5, +0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x2e, +0x14, 0x60, 0x36, 0x24, 0xfc, 0x60, 0x5f, 0x24, 0xf9, 0x60, 0x1f, 0x24, 0x0e, 0x70, 0x69, 0xe5, +0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, +0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x45, 0xa2, 0x47, 0x80, 0x41, 0xe5, 0x46, +0x30, 0xe2, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, +0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, +0x47, 0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, +0x47, 0xb3, 0x92, 0x39, 0x80, 0x19, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, +0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, +0x02, 0x28, 0xe0, 0x54, 0xfc, 0x45, 0x27, 0xf0, 0x90, 0x70, 0x9c, 0xe5, 0x3a, 0xf0, 0xa3, 0xe5, +0x47, 0xf0, 0x90, 0x70, 0x41, 0xe5, 0x3a, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, +0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, +0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x62, 0xc2, 0xaf, 0xe5, 0x51, +0x14, 0x60, 0x46, 0x14, 0x60, 0x62, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x03, 0xd2, 0x59, 0x75, +0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0, 0x20, 0xe7, 0x22, 0x90, 0x04, +0x34, 0xe0, 0xb4, 0x02, 0x1b, 0xa3, 0xe0, 0xb4, 0x02, 0x16, 0xa3, 0xe0, 0xb4, 0x02, 0x11, 0x7f, +0x20, 0x12, 0x16, 0x3f, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x80, 0x73, +0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, 0x03, 0x80, 0x6a, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, +0x11, 0x7f, 0x20, 0x12, 0x16, 0x3f, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, +0x80, 0x51, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x46, 0x90, 0x02, 0xa3, 0xe0, 0x20, 0xe6, 0x3b, 0x90, +0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x33, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, +0xf0, 0x90, 0x12, 0x04, 0x74, 0x0a, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, +0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, 0xf9, 0xf0, 0x75, +0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, +0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x62, +0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, +0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, +0x02, 0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70, 0x4c, 0x75, 0x52, +0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44, +0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, +0x03, 0xf0, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0, +0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x17, +0x8d, 0x80, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, +0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, +0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, +0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, +0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, +0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, +0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, +0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, +0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01, +0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x94, 0x3f, +0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x12, 0x67, 0x02, +0x12, 0x68, 0x02, 0x12, 0x87, 0x02, 0x12, 0x8c, 0x12, 0x12, 0x88, 0x22, 0x02, 0x16, 0x49, 0x02, +0x17, 0x1f, 0x02, 0x13, 0x77, 0x02, 0x12, 0x8d, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x17, +0xc1, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40, +0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4, +0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4, +0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01, +0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xdd, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02, +0x12, 0x66, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0xb6, 0x10, +0xb7, 0x31, 0x10, 0xe0, 0x50, 0x11, 0x04, 0x51, 0x11, 0x0d, 0x52, 0x11, 0x0d, 0x53, 0x11, 0x0d, +0x54, 0x11, 0x4e, 0x55, 0x11, 0x7e, 0x70, 0x11, 0xa9, 0x71, 0x11, 0xd7, 0x72, 0x12, 0x1d, 0x73, +0x12, 0x3e, 0x80, 0x00, 0x00, 0x12, 0x66, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf, +0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, +0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22, +0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x12, 0x66, 0x90, 0x70, 0x11, +0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x12, 0x66, 0x75, 0x4e, 0x03, +0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04, +0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57, +0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef, +0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, +0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0xe5, 0x47, +0x64, 0x07, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0x90, +0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, +0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0xd2, 0x04, 0x22, 0x90, 0x70, +0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, +0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, +0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, +0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, +0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, +0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x10, 0x02, 0xe0, 0xb4, 0x70, 0x1e, 0xa3, 0xe0, +0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54, +0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5, +0x4f, 0x75, 0x3a, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, +0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10, +0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, +0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70, +0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, +0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, +0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, +0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, +0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, 0xc2, 0x42, 0xd3, 0x22, 0x22, 0xc2, 0x4b, 0xc2, +0x4c, 0xe5, 0x44, 0x12, 0x0a, 0xb6, 0x12, 0xaf, 0x00, 0x13, 0x42, 0x04, 0x13, 0x3e, 0x08, 0x13, +0x19, 0x10, 0x12, 0xc3, 0x20, 0x12, 0xe3, 0x60, 0x12, 0xf4, 0xa0, 0x00, 0x00, 0x13, 0x44, 0x85, +0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x13, +0x44, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, +0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x66, 0x53, 0x43, +0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, +0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, +0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x35, 0xe5, +0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04, 0x06, 0x53, 0x5e, +0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5, +0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b, +0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54, +0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3, 0xe5, 0x4a, 0xf0, +0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3, 0xe5, 0x42, 0xf0, +0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0, 0x70, 0x03, 0x12, +0x16, 0x29, 0x12, 0x13, 0x8c, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x90, 0x04, +0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, 0x24, 0xff, +0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e, 0xf0, 0xe5, +0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f, 0x20, 0xe5, +0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x25, 0x70, 0x05, +0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, 0x5f, 0x30, +0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, 0x64, 0x03, +0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, 0x70, 0x03, 0x30, +0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, 0x15, 0x25, 0xd2, +0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, 0x3a, 0x64, +0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5, +0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5, +0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c, +0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, +0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, +0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, +0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, +0x26, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, +0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, +0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, +0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, +0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, +0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, +0x90, 0x10, 0x2f, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92, +0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, +0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4c, 0x90, 0x02, 0x29, +0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe, 0x60, 0x23, +0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x18, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0f, 0x80, 0x07, +0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x06, 0x54, 0xfe, 0xf0, 0x02, 0x16, 0x18, 0x44, 0x01, 0xf0, +0x02, 0x16, 0x18, 0xe5, 0x46, 0x30, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02, +0x28, 0xe0, 0x54, 0xfe, 0x4f, 0xf0, 0x02, 0x16, 0x18, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5, +0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, 0x16, 0x18, 0xe4, 0xf5, +0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x2e, +0x14, 0x60, 0x36, 0x24, 0xfc, 0x60, 0x5f, 0x24, 0xf9, 0x60, 0x1f, 0x24, 0x0e, 0x70, 0x69, 0xe5, +0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, +0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x45, 0xa2, 0x47, 0x80, 0x41, 0xe5, 0x46, +0x30, 0xe2, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, +0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, +0x47, 0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, +0x47, 0xb3, 0x92, 0x39, 0x80, 0x19, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, +0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, +0x02, 0x28, 0xe0, 0x54, 0xfc, 0x45, 0x27, 0xf0, 0x90, 0x70, 0x9c, 0xe5, 0x3a, 0xf0, 0xa3, 0xe5, +0x47, 0xf0, 0x90, 0x70, 0x41, 0xe5, 0x3a, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, +0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, +0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x62, 0xc2, 0xaf, 0xe5, 0x51, +0x14, 0x60, 0x46, 0x14, 0x60, 0x62, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x03, 0xd2, 0x59, 0x75, +0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0, 0x20, 0xe7, 0x22, 0x90, 0x04, +0x34, 0xe0, 0xb4, 0x02, 0x1b, 0xa3, 0xe0, 0xb4, 0x02, 0x16, 0xa3, 0xe0, 0xb4, 0x02, 0x11, 0x7f, +0x20, 0x12, 0x16, 0x3f, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x80, 0x73, +0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, 0x03, 0x80, 0x6a, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, +0x11, 0x7f, 0x20, 0x12, 0x16, 0x3f, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, +0x80, 0x51, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x46, 0x90, 0x02, 0xa3, 0xe0, 0x20, 0xe6, 0x3b, 0x90, +0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x33, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, +0xf0, 0x90, 0x12, 0x04, 0x74, 0x0a, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, +0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, 0xf9, 0xf0, 0x75, +0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, +0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x62, +0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, +0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, +0x02, 0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70, 0x4c, 0x75, 0x52, +0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44, +0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, +0x03, 0xf0, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0, +0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x17, +0x8d, 0x80, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, +0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, +0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, +0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, +0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, +0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, +0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, +0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, +0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01, +0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x9b, 0xc0, } ; diff --git a/drivers/staging/rt3070/leap.h b/drivers/staging/rt3070/leap.h new file mode 100644 index 000000000000..6818c1ff4d73 --- /dev/null +++ b/drivers/staging/rt3070/leap.h @@ -0,0 +1,215 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + leap.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#ifndef __LEAP_H__ +#define __LEAP_H__ + +// Messages for Associate state machine +#define LEAP_MACHINE_BASE 30 + +#define LEAP_MSG_REQUEST_IDENTITY 31 +#define LEAP_MSG_REQUEST_LEAP 32 +#define LEAP_MSG_SUCCESS 33 +#define LEAP_MSG_FAILED 34 +#define LEAP_MSG_RESPONSE_LEAP 35 +#define LEAP_MSG_EAPOLKEY 36 +#define LEAP_MSG_UNKNOWN 37 +#define LEAP_MSG 38 +//! assoc state-machine states +#define LEAP_IDLE 0 +#define LEAP_WAIT_IDENTITY_REQUEST 1 +#define LEAP_WAIT_CHANLLENGE_REQUEST 2 +#define LEAP_WAIT_SUCCESS 3 +#define LEAP_WAIT_CHANLLENGE_RESPONSE 4 +#define LEAP_WAIT_EAPOLKEY 5 + +#define LEAP_REASON_INVALID_AUTH 0x01 +#define LEAP_REASON_AUTH_TIMEOUT 0x02 +#define LEAP_REASON_CHALLENGE_FROM_AP_FAILED 0x03 +#define LEAP_REASON_CHALLENGE_TO_AP_FAILED 0x04 + +#define CISCO_AuthModeLEAP 0x80 +#define CISCO_AuthModeLEAPNone 0x00 +#define LEAP_AUTH_TIMEOUT 30000 +#define LEAP_CHALLENGE_RESPONSE_LENGTH 24 +#define LEAP_CHALLENGE_REQUEST_LENGTH 8 + +typedef struct _LEAP_EAPOL_HEADER_ { + UCHAR Version; + UCHAR Type; + UCHAR Length[2]; +} LEAP_EAPOL_HEADER, *PLEAP_EAPOL_HEADER; + +typedef struct _LEAP_EAPOL_PACKET_ { + UCHAR Code; + UCHAR Identifier; + UCHAR Length[2]; + UCHAR Type; +} LEAP_EAPOL_PACKET, *PLEAP_EAPOL_PACKET; + +typedef struct _LEAP_EAP_CONTENTS_ { + UCHAR Version; + UCHAR Reserved; + UCHAR Length; +} LEAP_EAP_CONTENTS, *PLEAP_EAP_CONTENTS; + +/*** EAPOL key ***/ +typedef struct _EAPOL_KEY_HEADER_ { + UCHAR Type; + UCHAR Length[2]; + UCHAR Counter[8]; + UCHAR IV[16]; + UCHAR Index; + UCHAR Signature[16]; +} EAPOL_KEY_HEADER, *PEAPOL_KEY_HEADER; + +BOOLEAN LeapMsgTypeSubst( + IN UCHAR EAPType, + OUT ULONG *MsgType); + +VOID LeapMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem); + +VOID LeapMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR wep, + IN PUCHAR pAddr3); + +VOID LeapStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID LeapIdentityAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID LeapPeerChallengeAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID HashPwd( + IN PUCHAR pwd, + IN INT pwdlen, + OUT PUCHAR hash); + +VOID PeerChallengeResponse( + IN PUCHAR szChallenge, + IN PUCHAR smbPasswd, + OUT PUCHAR szResponse); + +VOID ParityKey( + OUT PUCHAR szOut, + IN PUCHAR szIn); + +VOID DesKey( + OUT ULONG k[16][2], + IN PUCHAR key, + IN INT decrypt); + +VOID Des( + IN ULONG ks[16][2], + OUT UCHAR block[8]); + +VOID DesEncrypt( + IN PUCHAR szClear, + IN PUCHAR szKey, + OUT PUCHAR szOut); + +VOID LeapNetworkChallengeAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID LeapNetworkChallengeResponse( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID HashpwdHash( + IN PUCHAR hash, + IN PUCHAR hashhash); + +VOID ProcessSessionKey( + OUT PUCHAR SessionKey, + IN PUCHAR hash2, + IN PUCHAR ChallengeToRadius, + IN PUCHAR ChallengeResponseFromRadius, + IN PUCHAR ChallengeFromRadius, + IN PUCHAR ChallengeResponseToRadius); + +VOID LeapEapolKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID RogueApTableInit( + IN ROGUEAP_TABLE *Tab); + +ULONG RogueApTableSearch( + IN ROGUEAP_TABLE *Tab, + IN PUCHAR pAddr); + +VOID RogueApEntrySet( + IN PRTMP_ADAPTER pAd, + OUT ROGUEAP_ENTRY *pRogueAp, + IN PUCHAR pAddr, + IN UCHAR FaileCode); + +ULONG RogueApTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT ROGUEAP_TABLE *Tab, + IN PUCHAR pAddr, + IN UCHAR FaileCode); + +VOID RogueApTableDeleteEntry( + IN OUT ROGUEAP_TABLE *Tab, + IN PUCHAR pAddr); + +VOID LeapAuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID LeapSendRogueAPReport( + IN PRTMP_ADAPTER pAd); + +BOOLEAN CCKMAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen); + +#endif // __LEAP_H__ diff --git a/drivers/staging/rt3070/link_list.h b/drivers/staging/rt3070/link_list.h new file mode 100644 index 000000000000..f6521133fd5e --- /dev/null +++ b/drivers/staging/rt3070/link_list.h @@ -0,0 +1,134 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + */ + +#ifndef __LINK_LIST_H__ +#define __LINK_LIST_H__ + +typedef struct _LIST_ENTRY +{ + struct _LIST_ENTRY *pNext; +} LIST_ENTRY, *PLIST_ENTRY; + +typedef struct _LIST_HEADR +{ + PLIST_ENTRY pHead; + PLIST_ENTRY pTail; + UCHAR size; +} LIST_HEADER, *PLIST_HEADER; + +static inline VOID initList( + IN PLIST_HEADER pList) +{ + pList->pHead = pList->pTail = NULL; + pList->size = 0; + return; +} + +static inline VOID insertTailList( + IN PLIST_HEADER pList, + IN PLIST_ENTRY pEntry) +{ + pEntry->pNext = NULL; + if (pList->pTail) + pList->pTail->pNext = pEntry; + else + pList->pHead = pEntry; + pList->pTail = pEntry; + pList->size++; + + return; +} + +static inline PLIST_ENTRY removeHeadList( + IN PLIST_HEADER pList) +{ + PLIST_ENTRY pNext; + PLIST_ENTRY pEntry; + + pEntry = pList->pHead; + if (pList->pHead != NULL) + { + pNext = pList->pHead->pNext; + pList->pHead = pNext; + if (pNext == NULL) + pList->pTail = NULL; + pList->size--; + } + return pEntry; +} + +static inline int getListSize( + IN PLIST_HEADER pList) +{ + return pList->size; +} + +static inline PLIST_ENTRY delEntryList( + IN PLIST_HEADER pList, + IN PLIST_ENTRY pEntry) +{ + PLIST_ENTRY pCurEntry; + PLIST_ENTRY pPrvEntry; + + if(pList->pHead == NULL) + return NULL; + + if(pEntry == pList->pHead) + { + pCurEntry = pList->pHead; + pList->pHead = pCurEntry->pNext; + + if(pList->pHead == NULL) + pList->pTail = NULL; + + pList->size--; + return pCurEntry; + } + + pPrvEntry = pList->pHead; + pCurEntry = pPrvEntry->pNext; + while(pCurEntry != NULL) + { + if (pEntry == pCurEntry) + { + pPrvEntry->pNext = pCurEntry->pNext; + + if(pEntry == pList->pTail) + pList->pTail = pPrvEntry; + + pList->size--; + break; + } + pPrvEntry = pCurEntry; + pCurEntry = pPrvEntry->pNext; + } + + return pCurEntry; +} + +#endif // ___LINK_LIST_H__ // + diff --git a/drivers/staging/rt3070/md4.h b/drivers/staging/rt3070/md4.h new file mode 100644 index 000000000000..f1e5b526350a --- /dev/null +++ b/drivers/staging/rt3070/md4.h @@ -0,0 +1,42 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + */ + +#ifndef __MD4_H__ +#define __MD4_H__ + +/* MD4 context. */ +typedef struct _MD4_CTX_ { + ULONG state[4]; /* state (ABCD) */ + ULONG count[2]; /* number of bits, modulo 2^64 (lsb first) */ + UCHAR buffer[64]; /* input buffer */ +} MD4_CTX; + +VOID MD4Init (MD4_CTX *); +VOID MD4Update (MD4_CTX *, PUCHAR, UINT); +VOID MD4Final (UCHAR [16], MD4_CTX *); + +#endif //__MD4_H__ \ No newline at end of file diff --git a/drivers/staging/rt3070/md5.h b/drivers/staging/rt3070/md5.h new file mode 100644 index 000000000000..d85db12170d5 --- /dev/null +++ b/drivers/staging/rt3070/md5.h @@ -0,0 +1,107 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + md5.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + jan 10-28-03 Initial + Rita 11-23-04 Modify MD5 and SHA-1 +*/ + +#ifndef uint8 +#define uint8 unsigned char +#endif + +#ifndef uint32 +#define uint32 unsigned long int +#endif + + +#ifndef __MD5_H__ +#define __MD5_H__ + +#define MD5_MAC_LEN 16 + +typedef struct _MD5_CTX { + UINT32 Buf[4]; // buffers of four states + UCHAR Input[64]; // input message + UINT32 LenInBitCount[2]; // length counter for input message, 0 up to 64 bits +} MD5_CTX; + +VOID MD5Init(MD5_CTX *pCtx); +VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes); +VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx); +VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16]); + +void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac); +void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac); + +// +// SHA context +// +typedef struct _SHA_CTX +{ + UINT32 Buf[5]; // buffers of five states + UCHAR Input[80]; // input message + UINT32 LenInBitCount[2]; // length counter for input message, 0 up to 64 bits + +} SHA_CTX; + +VOID SHAInit(SHA_CTX *pCtx); +UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes); +VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20]); +VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20]); + +#define SHA_DIGEST_LEN 20 +#endif // __MD5_H__ + +/******************************************************************************/ +#ifndef _AES_H +#define _AES_H + +typedef struct +{ + uint32 erk[64]; /* encryption round keys */ + uint32 drk[64]; /* decryption round keys */ + int nr; /* number of rounds */ +} +aes_context; + +int rtmp_aes_set_key( aes_context *ctx, uint8 *key, int nbits ); +void rtmp_aes_encrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ); +void rtmp_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] ); + +void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output); +int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output); + +#endif /* aes.h */ + diff --git a/drivers/staging/rt3070/mlme.h b/drivers/staging/rt3070/mlme.h new file mode 100644 index 000000000000..b0035e1fa8ea --- /dev/null +++ b/drivers/staging/rt3070/mlme.h @@ -0,0 +1,1468 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + mlme.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2003-08-28 Created + John Chang 2004-09-06 modified for RT2600 + +*/ +#ifndef __MLME_H__ +#define __MLME_H__ + +//extern UCHAR BROADCAST_ADDR[]; + +// maximum supported capability information - +// ESS, IBSS, Privacy, Short Preamble, Spectrum mgmt, Short Slot +#define SUPPORTED_CAPABILITY_INFO 0x0533 + +#define END_OF_ARGS -1 +#define LFSR_MASK 0x80000057 +#define MLME_TASK_EXEC_INTV 100/*200*/ // +#define LEAD_TIME 5 +#define MLME_TASK_EXEC_MULTIPLE 10 /*5*/ // MLME_TASK_EXEC_MULTIPLE * MLME_TASK_EXEC_INTV = 1 sec +#define REORDER_EXEC_INTV 100 // 0.1 sec +//#define TBTT_PRELOAD_TIME 384 // usec. LomgPreamble + 24-byte at 1Mbps + +// The definition of Radar detection duration region +#define CE 0 +#define FCC 1 +#define JAP 2 +#define JAP_W53 3 +#define JAP_W56 4 +#define MAX_RD_REGION 5 + +#ifdef NDIS51_MINIPORT +#define BEACON_LOST_TIME 4000 // 2048 msec = 2 sec +#else +#define BEACON_LOST_TIME 4 * OS_HZ // 2048 msec = 2 sec +#endif + +#define DLS_TIMEOUT 1200 // unit: msec +#define AUTH_TIMEOUT 300 // unit: msec +#define ASSOC_TIMEOUT 300 // unit: msec +#define JOIN_TIMEOUT 2 * OS_HZ // unit: msec +#define SHORT_CHANNEL_TIME 90 // unit: msec +#define MIN_CHANNEL_TIME 110 // unit: msec, for dual band scan +#define MAX_CHANNEL_TIME 140 // unit: msec, for single band scan +#define FAST_ACTIVE_SCAN_TIME 30 // Active scan waiting for probe response time +#define CW_MIN_IN_BITS 4 // actual CwMin = 2^CW_MIN_IN_BITS - 1 + + +#ifdef CONFIG_STA_SUPPORT +#ifndef CONFIG_AP_SUPPORT +#define CW_MAX_IN_BITS 10 // actual CwMax = 2^CW_MAX_IN_BITS - 1 +#endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +extern UINT32 CW_MAX_IN_BITS; +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +// Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720). +// SHould not refer to this constant anymore +//#define RSSI_TO_DBM_OFFSET 120 // for RT2530 RSSI-115 = dBm +#define RSSI_FOR_MID_TX_POWER -55 // -55 db is considered mid-distance +#define RSSI_FOR_LOW_TX_POWER -45 // -45 db is considered very short distance and + // eligible to use a lower TX power +#define RSSI_FOR_LOWEST_TX_POWER -30 +//#define MID_TX_POWER_DELTA 0 // 0 db from full TX power upon mid-distance to AP +#define LOW_TX_POWER_DELTA 6 // -3 db from full TX power upon very short distance. 1 grade is 0.5 db +#define LOWEST_TX_POWER_DELTA 16 // -8 db from full TX power upon shortest distance. 1 grade is 0.5 db + +#define RSSI_TRIGGERED_UPON_BELOW_THRESHOLD 0 +#define RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD 1 +#define RSSI_THRESHOLD_FOR_ROAMING 25 +#define RSSI_DELTA 5 + +// Channel Quality Indication +#define CQI_IS_GOOD(cqi) ((cqi) >= 50) +//#define CQI_IS_FAIR(cqi) (((cqi) >= 20) && ((cqi) < 50)) +#define CQI_IS_POOR(cqi) (cqi < 50) //(((cqi) >= 5) && ((cqi) < 20)) +#define CQI_IS_BAD(cqi) (cqi < 5) +#define CQI_IS_DEAD(cqi) (cqi == 0) + +// weighting factor to calculate Channel quality, total should be 100% +#define RSSI_WEIGHTING 50 +#define TX_WEIGHTING 30 +#define RX_WEIGHTING 20 + +//#define PEER_KEY_NOT_USED 0 +//#define PEER_KEY_64_BIT 64 +//#define PEER_KEY_128_BIT 128 + +//#define PEER_KEY_64BIT_LEN 8 +//#define PEER_KEY_128BIT_LEN 16 + +#define BSS_NOT_FOUND 0xFFFFFFFF + + +#ifdef CONFIG_STA_SUPPORT +#define MAX_LEN_OF_MLME_QUEUE 40 //10 +#endif // CONFIG_STA_SUPPORT // + +#define SCAN_PASSIVE 18 // scan with no probe request, only wait beacon and probe response +#define SCAN_ACTIVE 19 // scan with probe request, and wait beacon and probe response +#define SCAN_CISCO_PASSIVE 20 // Single channel passive scan +#define SCAN_CISCO_ACTIVE 21 // Single channel active scan +#define SCAN_CISCO_NOISE 22 // Single channel passive scan for noise histogram collection +#define SCAN_CISCO_CHANNEL_LOAD 23 // Single channel passive scan for channel load collection +#define FAST_SCAN_ACTIVE 24 // scan with probe request, and wait beacon and probe response + +#ifdef DOT11N_DRAFT3 +#define SCAN_2040_BSS_COEXIST 26 +#endif // DOT11N_DRAFT3 // + +//#define BSS_TABLE_EMPTY(x) ((x).BssNr == 0) +#define MAC_ADDR_IS_GROUP(Addr) (((Addr[0]) & 0x01)) +#define MAC_ADDR_HASH(Addr) (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define MAC_ADDR_HASH_INDEX(Addr) (MAC_ADDR_HASH(Addr) % HASH_TABLE_SIZE) +#define TID_MAC_HASH(Addr,TID) (TID^Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define TID_MAC_HASH_INDEX(Addr,TID) (TID_MAC_HASH(Addr,TID) % HASH_TABLE_SIZE) + +// LED Control +// assoiation ON. one LED ON. another blinking when TX, OFF when idle +// no association, both LED off +#define ASIC_LED_ACT_ON(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00031e46) +#define ASIC_LED_ACT_OFF(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00001e46) + +// bit definition of the 2-byte pBEACON->Capability field +#define CAP_IS_ESS_ON(x) (((x) & 0x0001) != 0) +#define CAP_IS_IBSS_ON(x) (((x) & 0x0002) != 0) +#define CAP_IS_CF_POLLABLE_ON(x) (((x) & 0x0004) != 0) +#define CAP_IS_CF_POLL_REQ_ON(x) (((x) & 0x0008) != 0) +#define CAP_IS_PRIVACY_ON(x) (((x) & 0x0010) != 0) +#define CAP_IS_SHORT_PREAMBLE_ON(x) (((x) & 0x0020) != 0) +#define CAP_IS_PBCC_ON(x) (((x) & 0x0040) != 0) +#define CAP_IS_AGILITY_ON(x) (((x) & 0x0080) != 0) +#define CAP_IS_SPECTRUM_MGMT(x) (((x) & 0x0100) != 0) // 802.11e d9 +#define CAP_IS_QOS(x) (((x) & 0x0200) != 0) // 802.11e d9 +#define CAP_IS_SHORT_SLOT(x) (((x) & 0x0400) != 0) +#define CAP_IS_APSD(x) (((x) & 0x0800) != 0) // 802.11e d9 +#define CAP_IS_IMMED_BA(x) (((x) & 0x1000) != 0) // 802.11e d9 +#define CAP_IS_DSSS_OFDM(x) (((x) & 0x2000) != 0) +#define CAP_IS_DELAY_BA(x) (((x) & 0x4000) != 0) // 802.11e d9 + +#define CAP_GENERATE(ess,ibss,priv,s_pre,s_slot,spectrum) (((ess) ? 0x0001 : 0x0000) | ((ibss) ? 0x0002 : 0x0000) | ((priv) ? 0x0010 : 0x0000) | ((s_pre) ? 0x0020 : 0x0000) | ((s_slot) ? 0x0400 : 0x0000) | ((spectrum) ? 0x0100 : 0x0000)) + +//#define STA_QOS_CAPABILITY 0 // 1-byte. see 802.11e d9.0 for bit definition + +#define ERP_IS_NON_ERP_PRESENT(x) (((x) & 0x01) != 0) // 802.11g +#define ERP_IS_USE_PROTECTION(x) (((x) & 0x02) != 0) // 802.11g +#define ERP_IS_USE_BARKER_PREAMBLE(x) (((x) & 0x04) != 0) // 802.11g + +#define DRS_TX_QUALITY_WORST_BOUND 8// 3 // just test by gary +#define DRS_PENALTY 8 + +#define BA_NOTUSE 2 +//BA Policy subfiled value in ADDBA frame +#define IMMED_BA 1 +#define DELAY_BA 0 + +// BA Initiator subfield in DELBA frame +#define ORIGINATOR 1 +#define RECIPIENT 0 + +// ADDBA Status Code +#define ADDBA_RESULTCODE_SUCCESS 0 +#define ADDBA_RESULTCODE_REFUSED 37 +#define ADDBA_RESULTCODE_INVALID_PARAMETERS 38 + +// DELBA Reason Code +#define DELBA_REASONCODE_QSTA_LEAVING 36 +#define DELBA_REASONCODE_END_BA 37 +#define DELBA_REASONCODE_UNKNOWN_BA 38 +#define DELBA_REASONCODE_TIMEOUT 39 + +// reset all OneSecTx counters +#define RESET_ONE_SEC_TX_CNT(__pEntry) \ +if (((__pEntry)) != NULL) \ +{ \ + (__pEntry)->OneSecTxRetryOkCount = 0; \ + (__pEntry)->OneSecTxFailCount = 0; \ + (__pEntry)->OneSecTxNoRetryOkCount = 0; \ +} + +// +// 802.11 frame formats +// +// HT Capability INFO field in HT Cap IE . +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT LSIGTxopProSup:1; + USHORT Forty_Mhz_Intolerant:1; + USHORT PSMP:1; + USHORT CCKmodein40:1; + USHORT AMsduSize:1; + USHORT DelayedBA:1; //rt2860c not support + USHORT RxSTBC:2; + USHORT TxSTBC:1; + USHORT ShortGIfor40:1; //for40MHz + USHORT ShortGIfor20:1; + USHORT GF:1; //green field + USHORT MimoPs:2;//momi power safe + USHORT ChannelWidth:1; + USHORT AdvCoding:1; +#else + USHORT AdvCoding:1; + USHORT ChannelWidth:1; + USHORT MimoPs:2;//momi power safe + USHORT GF:1; //green field + USHORT ShortGIfor20:1; + USHORT ShortGIfor40:1; //for40MHz + USHORT TxSTBC:1; + USHORT RxSTBC:2; + USHORT DelayedBA:1; //rt2860c not support + USHORT AMsduSize:1; // only support as zero + USHORT CCKmodein40:1; + USHORT PSMP:1; + USHORT Forty_Mhz_Intolerant:1; + USHORT LSIGTxopProSup:1; +#endif /* !RT_BIG_ENDIAN */ +} HT_CAP_INFO, *PHT_CAP_INFO; + +// HT Capability INFO field in HT Cap IE . +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR rsv:3;//momi power safe + UCHAR MpduDensity:3; + UCHAR MaxRAmpduFactor:2; +#else + UCHAR MaxRAmpduFactor:2; + UCHAR MpduDensity:3; + UCHAR rsv:3;//momi power safe +#endif /* !RT_BIG_ENDIAN */ +} HT_CAP_PARM, *PHT_CAP_PARM; + +// HT Capability INFO field in HT Cap IE . +typedef struct PACKED { + UCHAR MCSSet[10]; + UCHAR SupRate[2]; // unit : 1Mbps +#ifdef RT_BIG_ENDIAN + UCHAR rsv:3; + UCHAR MpduDensity:1; + UCHAR TxStream:2; + UCHAR TxRxNotEqual:1; + UCHAR TxMCSSetDefined:1; +#else + UCHAR TxMCSSetDefined:1; + UCHAR TxRxNotEqual:1; + UCHAR TxStream:2; + UCHAR MpduDensity:1; + UCHAR rsv:3; +#endif // RT_BIG_ENDIAN // + UCHAR rsv3[3]; +} HT_MCS_SET, *PHT_MCS_SET; + +// HT Capability INFO field in HT Cap IE . +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT rsv2:4; + USHORT RDGSupport:1; //reverse Direction Grant support + USHORT PlusHTC:1; //+HTC control field support + USHORT MCSFeedback:2; //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. + USHORT rsv:5;//momi power safe + USHORT TranTime:2; + USHORT Pco:1; +#else + USHORT Pco:1; + USHORT TranTime:2; + USHORT rsv:5;//momi power safe + USHORT MCSFeedback:2; //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. + USHORT PlusHTC:1; //+HTC control field support + USHORT RDGSupport:1; //reverse Direction Grant support + USHORT rsv2:4; +#endif /* RT_BIG_ENDIAN */ +} EXT_HT_CAP_INFO, *PEXT_HT_CAP_INFO; + +// HT Beamforming field in HT Cap IE . +typedef struct PACKED _HT_BF_CAP{ +#ifdef RT_BIG_ENDIAN + ULONG rsv:3; + ULONG ChanEstimation:2; + ULONG CSIRowBFSup:2; + ULONG ComSteerBFAntSup:2; + ULONG NoComSteerBFAntSup:2; + ULONG CSIBFAntSup:2; + ULONG MinGrouping:2; + ULONG ExpComBF:2; + ULONG ExpNoComBF:2; + ULONG ExpCSIFbk:2; + ULONG ExpComSteerCapable:1; + ULONG ExpNoComSteerCapable:1; + ULONG ExpCSICapable:1; + ULONG Calibration:2; + ULONG ImpTxBFCapable:1; + ULONG TxNDPCapable:1; + ULONG RxNDPCapable:1; + ULONG TxSoundCapable:1; + ULONG RxSoundCapable:1; + ULONG TxBFRecCapable:1; +#else + ULONG TxBFRecCapable:1; + ULONG RxSoundCapable:1; + ULONG TxSoundCapable:1; + ULONG RxNDPCapable:1; + ULONG TxNDPCapable:1; + ULONG ImpTxBFCapable:1; + ULONG Calibration:2; + ULONG ExpCSICapable:1; + ULONG ExpNoComSteerCapable:1; + ULONG ExpComSteerCapable:1; + ULONG ExpCSIFbk:2; + ULONG ExpNoComBF:2; + ULONG ExpComBF:2; + ULONG MinGrouping:2; + ULONG CSIBFAntSup:2; + ULONG NoComSteerBFAntSup:2; + ULONG ComSteerBFAntSup:2; + ULONG CSIRowBFSup:2; + ULONG ChanEstimation:2; + ULONG rsv:3; +#endif // RT_BIG_ENDIAN // +} HT_BF_CAP, *PHT_BF_CAP; + +// HT antenna selection field in HT Cap IE . +typedef struct PACKED _HT_AS_CAP{ +#ifdef RT_BIG_ENDIAN + UCHAR rsv:1; + UCHAR TxSoundPPDU:1; + UCHAR RxASel:1; + UCHAR AntIndFbk:1; + UCHAR ExpCSIFbk:1; + UCHAR AntIndFbkTxASEL:1; + UCHAR ExpCSIFbkTxASEL:1; + UCHAR AntSelect:1; +#else + UCHAR AntSelect:1; + UCHAR ExpCSIFbkTxASEL:1; + UCHAR AntIndFbkTxASEL:1; + UCHAR ExpCSIFbk:1; + UCHAR AntIndFbk:1; + UCHAR RxASel:1; + UCHAR TxSoundPPDU:1; + UCHAR rsv:1; +#endif // RT_BIG_ENDIAN // +} HT_AS_CAP, *PHT_AS_CAP; + +// Draft 1.0 set IE length 26, but is extensible.. +#define SIZE_HT_CAP_IE 26 +// The structure for HT Capability IE. +typedef struct PACKED _HT_CAPABILITY_IE{ + HT_CAP_INFO HtCapInfo; + HT_CAP_PARM HtCapParm; +// HT_MCS_SET HtMCSSet; + UCHAR MCSSet[16]; + EXT_HT_CAP_INFO ExtHtCapInfo; + HT_BF_CAP TxBFCap; // beamforming cap. rt2860c not support beamforming. + HT_AS_CAP ASCap; //antenna selection. +} HT_CAPABILITY_IE, *PHT_CAPABILITY_IE; + + +// 802.11n draft3 related structure definitions. +// 7.3.2.60 +#define dot11OBSSScanPassiveDwell 20 // in TU. min amount of time that the STA continously scans each channel when performing an active OBSS scan. +#define dot11OBSSScanActiveDwell 10 // in TU.min amount of time that the STA continously scans each channel when performing an passive OBSS scan. +#define dot11BSSWidthTriggerScanInterval 300 // in sec. max interval between scan operations to be performed to detect BSS channel width trigger events. +#define dot11OBSSScanPassiveTotalPerChannel 200 // in TU. min total amount of time that the STA scans each channel when performing a passive OBSS scan. +#define dot11OBSSScanActiveTotalPerChannel 20 //in TU. min total amount of time that the STA scans each channel when performing a active OBSS scan +#define dot11BSSWidthChannelTransactionDelayFactor 5 // min ratio between the delay time in performing a switch from 20MHz BSS to 20/40 BSS operation and the maxima + // interval between overlapping BSS scan operations. +#define dot11BSSScanActivityThreshold 25 // in %%, max total time that a STA may be active on the medium during a period of + // (dot11BSSWidthChannelTransactionDelayFactor * dot11BSSWidthTriggerScanInterval) seconds without + // being obligated to perform OBSS Scan operations. default is 25(== 0.25%) + +typedef struct PACKED _OVERLAP_BSS_SCAN_IE{ + USHORT ScanPassiveDwell; + USHORT ScanActiveDwell; + USHORT TriggerScanInt; // Trigger scan interval + USHORT PassiveTalPerChannel; // passive total per channel + USHORT ActiveTalPerChannel; // active total per channel + USHORT DelayFactor; // BSS width channel transition delay factor + USHORT ScanActThre; // Scan Activity threshold +}OVERLAP_BSS_SCAN_IE, *POVERLAP_BSS_SCAN_IE; + + +// 7.3.2.56. 20/40 Coexistence element used in Element ID = 72 = IE_2040_BSS_COEXIST +typedef union PACKED _BSS_2040_COEXIST_IE{ + struct PACKED { + #ifdef RT_BIG_ENDIAN + UCHAR rsv:5; + UCHAR BSS20WidthReq:1; + UCHAR Intolerant40:1; + UCHAR InfoReq:1; + #else + UCHAR InfoReq:1; + UCHAR Intolerant40:1; // Inter-BSS. set 1 when prohibits a receiving BSS from operating as a 20/40 Mhz BSS. + UCHAR BSS20WidthReq:1; // Intra-BSS set 1 when prohibits a receiving AP from operating its BSS as a 20/40MHz BSS. + UCHAR rsv:5; +#endif // RT_BIG_ENDIAN // + } field; + UCHAR word; +} BSS_2040_COEXIST_IE, *PBSS_2040_COEXIST_IE; + + +typedef struct _TRIGGER_EVENTA{ + BOOLEAN bValid; + UCHAR BSSID[6]; + UCHAR RegClass; // Regulatory Class + USHORT Channel; + ULONG CDCounter; // Maintain a seperate count down counter for each Event A. +} TRIGGER_EVENTA, *PTRIGGER_EVENTA; + +// 20/40 trigger event table +// If one Event A delete or created, or if Event B is detected or not detected, STA should send 2040BSSCoexistence to AP. +#define MAX_TRIGGER_EVENT 64 +typedef struct _TRIGGER_EVENT_TAB{ + UCHAR EventANo; + TRIGGER_EVENTA EventA[MAX_TRIGGER_EVENT]; + ULONG EventBCountDown; // Count down counter for Event B. +} TRIGGER_EVENT_TAB, *PTRIGGER_EVENT_TAB; + +// 7.3.27 20/40 Bss Coexistence Mgmt capability used in extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY). +// This is the first octet and was defined in 802.11n D3.03 and 802.11yD9.0 +typedef struct PACKED _EXT_CAP_INFO_ELEMENT{ +#ifdef RT_BIG_ENDIAN + UCHAR rsv2:5; + UCHAR ExtendChannelSwitch:1; + UCHAR rsv:1; + UCHAR BssCoexistMgmtSupport:1; +#else + UCHAR BssCoexistMgmtSupport:1; + UCHAR rsv:1; + UCHAR ExtendChannelSwitch:1; + UCHAR rsv2:5; +#endif // RT_BIG_ENDIAN // +}EXT_CAP_INFO_ELEMENT, *PEXT_CAP_INFO_ELEMENT; + + +// 802.11n 7.3.2.61 +typedef struct PACKED _BSS_2040_COEXIST_ELEMENT{ + UCHAR ElementID; // ID = IE_2040_BSS_COEXIST = 72 + UCHAR Len; + BSS_2040_COEXIST_IE BssCoexistIe; +}BSS_2040_COEXIST_ELEMENT, *PBSS_2040_COEXIST_ELEMENT; + + +//802.11n 7.3.2.59 +typedef struct PACKED _BSS_2040_INTOLERANT_CH_REPORT{ + UCHAR ElementID; // ID = IE_2040_BSS_INTOLERANT_REPORT = 73 + UCHAR Len; + UCHAR RegulatoryClass; + UCHAR ChList[0]; +}BSS_2040_INTOLERANT_CH_REPORT, *PBSS_2040_INTOLERANT_CH_REPORT; + + +// The structure for channel switch annoucement IE. This is in 802.11n D3.03 +typedef struct PACKED _CHA_SWITCH_ANNOUNCE_IE{ + UCHAR SwitchMode; //channel switch mode + UCHAR NewChannel; // + UCHAR SwitchCount; // +} CHA_SWITCH_ANNOUNCE_IE, *PCHA_SWITCH_ANNOUNCE_IE; + + +// The structure for channel switch annoucement IE. This is in 802.11n D3.03 +typedef struct PACKED _SEC_CHA_OFFSET_IE{ + UCHAR SecondaryChannelOffset; // 1: Secondary above, 3: Secondary below, 0: no Secondary +} SEC_CHA_OFFSET_IE, *PSEC_CHA_OFFSET_IE; + + +// This structure is extracted from struct RT_HT_CAPABILITY +typedef struct { + BOOLEAN bHtEnable; // If we should use ht rate. + BOOLEAN bPreNHt; // If we should use ht rate. + //Substract from HT Capability IE + UCHAR MCSSet[16]; //only supoort MCS=0-15,32 , +} RT_HT_PHY_INFO, *PRT_HT_PHY_INFO; + +//This structure substracts ralink supports from all 802.11n-related features. +//Features not listed here but contained in 802.11n spec are not supported in rt2860. +typedef struct { +#ifdef RT_BIG_ENDIAN + USHORT rsv:5; + USHORT AmsduSize:1; // Max receiving A-MSDU size + USHORT AmsduEnable:1; // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n + USHORT RxSTBC:2; // 2 bits + USHORT TxSTBC:1; + USHORT ShortGIfor40:1; //for40MHz + USHORT ShortGIfor20:1; + USHORT GF:1; //green field + USHORT MimoPs:2;//mimo power safe MMPS_ + USHORT ChannelWidth:1; +#else + USHORT ChannelWidth:1; + USHORT MimoPs:2;//mimo power safe MMPS_ + USHORT GF:1; //green field + USHORT ShortGIfor20:1; + USHORT ShortGIfor40:1; //for40MHz + USHORT TxSTBC:1; + USHORT RxSTBC:2; // 2 bits + USHORT AmsduEnable:1; // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n + USHORT AmsduSize:1; // Max receiving A-MSDU size + USHORT rsv:5; +#endif + + //Substract from Addiont HT INFO IE +#ifdef RT_BIG_ENDIAN + UCHAR RecomWidth:1; + UCHAR ExtChanOffset:2; // Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n + UCHAR MpduDensity:3; + UCHAR MaxRAmpduFactor:2; +#else + UCHAR MaxRAmpduFactor:2; + UCHAR MpduDensity:3; + UCHAR ExtChanOffset:2; // Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n + UCHAR RecomWidth:1; +#endif + +#ifdef RT_BIG_ENDIAN + USHORT rsv2:11; + USHORT OBSS_NonHTExist:1; + USHORT rsv3:1; + USHORT NonGfPresent:1; + USHORT OperaionMode:2; +#else + USHORT OperaionMode:2; + USHORT NonGfPresent:1; + USHORT rsv3:1; + USHORT OBSS_NonHTExist:1; + USHORT rsv2:11; +#endif + + // New Extension Channel Offset IE + UCHAR NewExtChannelOffset; + // Extension Capability IE = 127 + UCHAR BSSCoexist2040; +} RT_HT_CAPABILITY, *PRT_HT_CAPABILITY; + +// field in Addtional HT Information IE . +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR SerInterGranu:3; + UCHAR S_PSMPSup:1; + UCHAR RifsMode:1; + UCHAR RecomWidth:1; + UCHAR ExtChanOffset:2; +#else + UCHAR ExtChanOffset:2; + UCHAR RecomWidth:1; + UCHAR RifsMode:1; + UCHAR S_PSMPSup:1; //Indicate support for scheduled PSMP + UCHAR SerInterGranu:3; //service interval granularity +#endif +} ADD_HTINFO, *PADD_HTINFO; + +typedef struct PACKED{ +#ifdef RT_BIG_ENDIAN + USHORT rsv2:11; + USHORT OBSS_NonHTExist:1; + USHORT rsv:1; + USHORT NonGfPresent:1; + USHORT OperaionMode:2; +#else + USHORT OperaionMode:2; + USHORT NonGfPresent:1; + USHORT rsv:1; + USHORT OBSS_NonHTExist:1; + USHORT rsv2:11; +#endif +} ADD_HTINFO2, *PADD_HTINFO2; + + +// TODO: Need sync with spec about the definition of StbcMcs. In Draft 3.03, it's reserved. +typedef struct PACKED{ +#ifdef RT_BIG_ENDIAN + USHORT rsv:4; + USHORT PcoPhase:1; + USHORT PcoActive:1; + USHORT LsigTxopProt:1; + USHORT STBCBeacon:1; + USHORT DualCTSProtect:1; + USHORT DualBeacon:1; + USHORT StbcMcs:6; +#else + USHORT StbcMcs:6; + USHORT DualBeacon:1; + USHORT DualCTSProtect:1; + USHORT STBCBeacon:1; + USHORT LsigTxopProt:1; // L-SIG TXOP protection full support + USHORT PcoActive:1; + USHORT PcoPhase:1; + USHORT rsv:4; +#endif // RT_BIG_ENDIAN // +} ADD_HTINFO3, *PADD_HTINFO3; + +#define SIZE_ADD_HT_INFO_IE 22 +typedef struct PACKED{ + UCHAR ControlChan; + ADD_HTINFO AddHtInfo; + ADD_HTINFO2 AddHtInfo2; + ADD_HTINFO3 AddHtInfo3; + UCHAR MCSSet[16]; // Basic MCS set +} ADD_HT_INFO_IE, *PADD_HT_INFO_IE; + +typedef struct PACKED{ + UCHAR NewExtChanOffset; +} NEW_EXT_CHAN_IE, *PNEW_EXT_CHAN_IE; + + +// 4-byte HTC field. maybe included in any frame except non-QOS data frame. The Order bit must set 1. +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UINT32 RDG:1; //RDG / More PPDU + UINT32 ACConstraint:1; //feedback request + UINT32 rsv:5; //calibration sequence + UINT32 ZLFAnnouce:1; // ZLF announcement + UINT32 CSISTEERING:2; //CSI/ STEERING + UINT32 FBKReq:2; //feedback request + UINT32 CalSeq:2; //calibration sequence + UINT32 CalPos:2; // calibration position + UINT32 MFBorASC:7; //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available + UINT32 MFS:3; //SET to the received value of MRS. 0x111 for unsolicited MFB. + UINT32 MRSorASI:3; // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110. + UINT32 MRQ:1; //MCS feedback. Request for a MCS feedback + UINT32 TRQ:1; //sounding request + UINT32 MA:1; //management action payload exist in (QoS Null+HTC) +#else + UINT32 MA:1; //management action payload exist in (QoS Null+HTC) + UINT32 TRQ:1; //sounding request + UINT32 MRQ:1; //MCS feedback. Request for a MCS feedback + UINT32 MRSorASI:3; // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110. + UINT32 MFS:3; //SET to the received value of MRS. 0x111 for unsolicited MFB. + UINT32 MFBorASC:7; //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available + UINT32 CalPos:2; // calibration position + UINT32 CalSeq:2; //calibration sequence + UINT32 FBKReq:2; //feedback request + UINT32 CSISTEERING:2; //CSI/ STEERING + UINT32 ZLFAnnouce:1; // ZLF announcement + UINT32 rsv:5; //calibration sequence + UINT32 ACConstraint:1; //feedback request + UINT32 RDG:1; //RDG / More PPDU +#endif /* !RT_BIG_ENDIAN */ +} HT_CONTROL, *PHT_CONTROL; + +// 2-byte QOS CONTROL field +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT Txop_QueueSize:8; + USHORT AMsduPresent:1; + USHORT AckPolicy:2; //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA + USHORT EOSP:1; + USHORT TID:4; +#else + USHORT TID:4; + USHORT EOSP:1; + USHORT AckPolicy:2; //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA + USHORT AMsduPresent:1; + USHORT Txop_QueueSize:8; +#endif /* !RT_BIG_ENDIAN */ +} QOS_CONTROL, *PQOS_CONTROL; + +// 2-byte Frame control field +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT Order:1; // Strict order expected + USHORT Wep:1; // Wep data + USHORT MoreData:1; // More data bit + USHORT PwrMgmt:1; // Power management bit + USHORT Retry:1; // Retry status bit + USHORT MoreFrag:1; // More fragment bit + USHORT FrDs:1; // From DS indication + USHORT ToDs:1; // To DS indication + USHORT SubType:4; // MSDU subtype + USHORT Type:2; // MSDU type + USHORT Ver:2; // Protocol version +#else + USHORT Ver:2; // Protocol version + USHORT Type:2; // MSDU type + USHORT SubType:4; // MSDU subtype + USHORT ToDs:1; // To DS indication + USHORT FrDs:1; // From DS indication + USHORT MoreFrag:1; // More fragment bit + USHORT Retry:1; // Retry status bit + USHORT PwrMgmt:1; // Power management bit + USHORT MoreData:1; // More data bit + USHORT Wep:1; // Wep data + USHORT Order:1; // Strict order expected +#endif /* !RT_BIG_ENDIAN */ +} FRAME_CONTROL, *PFRAME_CONTROL; + +typedef struct PACKED _HEADER_802_11 { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; +#ifdef RT_BIG_ENDIAN + USHORT Sequence:12; + USHORT Frag:4; +#else + USHORT Frag:4; + USHORT Sequence:12; +#endif /* !RT_BIG_ENDIAN */ + UCHAR Octet[0]; +} HEADER_802_11, *PHEADER_802_11; + +typedef struct PACKED _FRAME_802_11 { + HEADER_802_11 Hdr; + UCHAR Octet[1]; +} FRAME_802_11, *PFRAME_802_11; + +// QoSNull embedding of management action. When HT Control MA field set to 1. +typedef struct PACKED _MA_BODY { + UCHAR Category; + UCHAR Action; + UCHAR Octet[1]; +} MA_BODY, *PMA_BODY; + +typedef struct PACKED _HEADER_802_3 { + UCHAR DAAddr1[MAC_ADDR_LEN]; + UCHAR SAAddr2[MAC_ADDR_LEN]; + UCHAR Octet[2]; +} HEADER_802_3, *PHEADER_802_3; +////Block ACK related format +// 2-byte BA Parameter field in DELBA frames to terminate an already set up bA +typedef struct PACKED{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; // value of TC os TS + USHORT Initiator:1; // 1: originator 0:recipient + USHORT Rsv:11; // always set to 0 +#else + USHORT Rsv:11; // always set to 0 + USHORT Initiator:1; // 1: originator 0:recipient + USHORT TID:4; // value of TC os TS +#endif /* !RT_BIG_ENDIAN */ +} DELBA_PARM, *PDELBA_PARM; + +// 2-byte BA Parameter Set field in ADDBA frames to signal parm for setting up a BA +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT BufSize:10; // number of buffe of size 2304 octetsr + USHORT TID:4; // value of TC os TS + USHORT BAPolicy:1; // 1: immediately BA 0:delayed BA + USHORT AMSDUSupported:1; // 0: not permitted 1: permitted +#else + USHORT AMSDUSupported:1; // 0: not permitted 1: permitted + USHORT BAPolicy:1; // 1: immediately BA 0:delayed BA + USHORT TID:4; // value of TC os TS + USHORT BufSize:10; // number of buffe of size 2304 octetsr +#endif /* !RT_BIG_ENDIAN */ +} BA_PARM, *PBA_PARM; + +// 2-byte BA Starting Seq CONTROL field +typedef union PACKED { + struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT StartSeq:12; // sequence number of the 1st MSDU for which this BAR is sent + USHORT FragNum:4; // always set to 0 +#else + USHORT FragNum:4; // always set to 0 + USHORT StartSeq:12; // sequence number of the 1st MSDU for which this BAR is sent +#endif /* RT_BIG_ENDIAN */ + } field; + USHORT word; +} BASEQ_CONTROL, *PBASEQ_CONTROL; + +//BAControl and BARControl are the same +// 2-byte BA CONTROL field in BA frame +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv:9; + USHORT Compressed:1; + USHORT MTID:1; //EWC V1.24 + USHORT ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK +#else + USHORT ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK + USHORT MTID:1; //EWC V1.24 + USHORT Compressed:1; + USHORT Rsv:9; + USHORT TID:4; +#endif /* !RT_BIG_ENDIAN */ +} BA_CONTROL, *PBA_CONTROL; + +// 2-byte BAR CONTROL field in BAR frame +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv1:9; + USHORT Compressed:1; + USHORT MTID:1; //if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ + USHORT ACKPolicy:1; +#else + USHORT ACKPolicy:1; // 0:normal ack, 1:no ack. + USHORT MTID:1; //if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ + USHORT Compressed:1; + USHORT Rsv1:9; + USHORT TID:4; +#endif /* !RT_BIG_ENDIAN */ +} BAR_CONTROL, *PBAR_CONTROL; + +// BARControl in MTBAR frame +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT NumTID:4; + USHORT Rsv1:9; + USHORT Compressed:1; + USHORT MTID:1; + USHORT ACKPolicy:1; +#else + USHORT ACKPolicy:1; + USHORT MTID:1; + USHORT Compressed:1; + USHORT Rsv1:9; + USHORT NumTID:4; +#endif /* !RT_BIG_ENDIAN */ +} MTBAR_CONTROL, *PMTBAR_CONTROL; + +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv1:12; +#else + USHORT Rsv1:12; + USHORT TID:4; +#endif /* !RT_BIG_ENDIAN */ +} PER_TID_INFO, *PPER_TID_INFO; + +typedef struct { + PER_TID_INFO PerTID; + BASEQ_CONTROL BAStartingSeq; +} EACH_TID, *PEACH_TID; + + +typedef struct PACKED _PSPOLL_FRAME { + FRAME_CONTROL FC; + USHORT Aid; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Ta[MAC_ADDR_LEN]; +} PSPOLL_FRAME, *PPSPOLL_FRAME; + +typedef struct PACKED _RTS_FRAME { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; +}RTS_FRAME, *PRTS_FRAME; + +// BAREQ AND MTBAREQ have the same subtype BAR, 802.11n BAR use compressed bitmap. +typedef struct PACKED _FRAME_BA_REQ { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BARControl; + BASEQ_CONTROL BAStartingSeq; +} FRAME_BA_REQ, *PFRAME_BA_REQ; + +typedef struct PACKED _FRAME_MTBA_REQ { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + MTBAR_CONTROL MTBARControl; + PER_TID_INFO PerTIDInfo; + BASEQ_CONTROL BAStartingSeq; +} FRAME_MTBA_REQ, *PFRAME_MTBA_REQ; + +// Compressed format is mandantory in HT STA +typedef struct PACKED _FRAME_MTBA { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BA_CONTROL BAControl; + BASEQ_CONTROL BAStartingSeq; + UCHAR BitMap[8]; +} FRAME_MTBA, *PFRAME_MTBA; + +typedef struct PACKED _FRAME_PSMP_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Psmp; // 7.3.1.25 +} FRAME_PSMP_ACTION, *PFRAME_PSMP_ACTION; + +typedef struct PACKED _FRAME_ACTION_HDR { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; +} FRAME_ACTION_HDR, *PFRAME_ACTION_HDR; + +//Action Frame +//Action Frame Category:Spectrum, Action:Channel Switch. 7.3.2.20 +typedef struct PACKED _CHAN_SWITCH_ANNOUNCE { + UCHAR ElementID; // ID = IE_CHANNEL_SWITCH_ANNOUNCEMENT = 37 + UCHAR Len; + CHA_SWITCH_ANNOUNCE_IE CSAnnounceIe; +} CHAN_SWITCH_ANNOUNCE, *PCHAN_SWITCH_ANNOUNCE; + + +//802.11n : 7.3.2.20a +typedef struct PACKED _SECOND_CHAN_OFFSET { + UCHAR ElementID; // ID = IE_SECONDARY_CH_OFFSET = 62 + UCHAR Len; + SEC_CHA_OFFSET_IE SecChOffsetIe; +} SECOND_CHAN_OFFSET, *PSECOND_CHAN_OFFSET; + + +typedef struct PACKED _FRAME_SPETRUM_CS { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + CHAN_SWITCH_ANNOUNCE CSAnnounce; + SECOND_CHAN_OFFSET SecondChannel; +} FRAME_SPETRUM_CS, *PFRAME_SPETRUM_CS; + + +typedef struct PACKED _FRAME_ADDBA_REQ { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; // 1 + BA_PARM BaParm; // 2 - 10 + USHORT TimeOutValue; // 0 - 0 + BASEQ_CONTROL BaStartSeq; // 0-0 +} FRAME_ADDBA_REQ, *PFRAME_ADDBA_REQ; + +typedef struct PACKED _FRAME_ADDBA_RSP { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; + USHORT StatusCode; + BA_PARM BaParm; //0 - 2 + USHORT TimeOutValue; +} FRAME_ADDBA_RSP, *PFRAME_ADDBA_RSP; + +typedef struct PACKED _FRAME_DELBA_REQ { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + DELBA_PARM DelbaParm; + USHORT ReasonCode; +} FRAME_DELBA_REQ, *PFRAME_DELBA_REQ; + + +//7.2.1.7 +typedef struct PACKED _FRAME_BAR { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BarControl; + BASEQ_CONTROL StartingSeq; +} FRAME_BAR, *PFRAME_BAR; + +//7.2.1.7 +typedef struct PACKED _FRAME_BA { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BarControl; + BASEQ_CONTROL StartingSeq; + UCHAR bitmask[8]; +} FRAME_BA, *PFRAME_BA; + + +// Radio Measuement Request Frame Format +typedef struct PACKED _FRAME_RM_REQ_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; + USHORT Repetition; + UCHAR data[0]; +} FRAME_RM_REQ_ACTION, *PFRAME_RM_REQ_ACTION; + +typedef struct PACKED { + UCHAR ID; + UCHAR Length; + UCHAR ChannelSwitchMode; + UCHAR NewRegClass; + UCHAR NewChannelNum; + UCHAR ChannelSwitchCount; +} HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE, *PHT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE; + + +// +// _Limit must be the 2**n - 1 +// _SEQ1 , _SEQ2 must be within 0 ~ _Limit +// +#define SEQ_STEPONE(_SEQ1, _SEQ2, _Limit) ((_SEQ1 == ((_SEQ2+1) & _Limit))) +#define SEQ_SMALLER(_SEQ1, _SEQ2, _Limit) (((_SEQ1-_SEQ2) & ((_Limit+1)>>1))) +#define SEQ_LARGER(_SEQ1, _SEQ2, _Limit) ((_SEQ1 != _SEQ2) && !(((_SEQ1-_SEQ2) & ((_Limit+1)>>1)))) +#define SEQ_WITHIN_WIN(_SEQ1, _SEQ2, _WIN, _Limit) (SEQ_LARGER(_SEQ1, _SEQ2, _Limit) && \ + SEQ_SMALLER(_SEQ1, ((_SEQ2+_WIN+1)&_Limit), _Limit)) + +// +// Contention-free parameter (without ID and Length) +// +typedef struct PACKED { + BOOLEAN bValid; // 1: variable contains valid value + UCHAR CfpCount; + UCHAR CfpPeriod; + USHORT CfpMaxDuration; + USHORT CfpDurRemaining; +} CF_PARM, *PCF_PARM; + +typedef struct _CIPHER_SUITE { + NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher 1, this one has more secured cipher suite + NDIS_802_11_ENCRYPTION_STATUS PairCipherAux; // Unicast cipher 2 if AP announce two unicast cipher suite + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Group cipher + USHORT RsnCapability; // RSN capability from beacon + BOOLEAN bMixMode; // Indicate Pair & Group cipher might be different +} CIPHER_SUITE, *PCIPHER_SUITE; + +// EDCA configuration from AP's BEACON/ProbeRsp +typedef struct { + BOOLEAN bValid; // 1: variable contains valid value + BOOLEAN bAdd; // 1: variable contains valid value + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; + BOOLEAN bAPSDCapable; +// BOOLEAN bMoreDataAck; + UCHAR EdcaUpdateCount; + UCHAR Aifsn[4]; // 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO + UCHAR Cwmin[4]; + UCHAR Cwmax[4]; + USHORT Txop[4]; // in unit of 32-us + BOOLEAN bACM[4]; // 1: Admission Control of AC_BK is mandattory +} EDCA_PARM, *PEDCA_PARM; + +// QBSS LOAD information from QAP's BEACON/ProbeRsp +typedef struct { + BOOLEAN bValid; // 1: variable contains valid value + USHORT StaNum; + UCHAR ChannelUtilization; + USHORT RemainingAdmissionControl; // in unit of 32-us +} QBSS_LOAD_PARM, *PQBSS_LOAD_PARM; + +// QBSS Info field in QSTA's assoc req +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:1; + UCHAR MaxSPLength:2; + UCHAR Rsv1:1; + UCHAR UAPSD_AC_BE:1; + UCHAR UAPSD_AC_BK:1; + UCHAR UAPSD_AC_VI:1; + UCHAR UAPSD_AC_VO:1; +#else + UCHAR UAPSD_AC_VO:1; + UCHAR UAPSD_AC_VI:1; + UCHAR UAPSD_AC_BK:1; + UCHAR UAPSD_AC_BE:1; + UCHAR Rsv1:1; + UCHAR MaxSPLength:2; + UCHAR Rsv2:1; +#endif /* !RT_BIG_ENDIAN */ +} QBSS_STA_INFO_PARM, *PQBSS_STA_INFO_PARM; + +// QBSS Info field in QAP's Beacon/ProbeRsp +typedef struct PACKED { +#ifdef RT_BIG_ENDIAN + UCHAR UAPSD:1; + UCHAR Rsv:3; + UCHAR ParamSetCount:4; +#else + UCHAR ParamSetCount:4; + UCHAR Rsv:3; + UCHAR UAPSD:1; +#endif /* !RT_BIG_ENDIAN */ +} QBSS_AP_INFO_PARM, *PQBSS_AP_INFO_PARM; + +// QOS Capability reported in QAP's BEACON/ProbeRsp +// QOS Capability sent out in QSTA's AssociateReq/ReAssociateReq +typedef struct { + BOOLEAN bValid; // 1: variable contains valid value + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; +// BOOLEAN bMoreDataAck; + UCHAR EdcaUpdateCount; +} QOS_CAPABILITY_PARM, *PQOS_CAPABILITY_PARM; + +#ifdef CONFIG_STA_SUPPORT +typedef struct { + UCHAR IELen; + UCHAR IE[MAX_CUSTOM_LEN]; +} WPA_IE_; +#endif // CONFIG_STA_SUPPORT // + + +typedef struct { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Channel; + UCHAR CentralChannel; //Store the wide-band central channel for 40MHz. .used in 40MHz AP. Or this is the same as Channel. + UCHAR BssType; + USHORT AtimWin; + USHORT BeaconPeriod; + + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + HT_CAPABILITY_IE HtCapability; + UCHAR HtCapabilityLen; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR AddHtInfoLen; + UCHAR NewExtChanOffset; + CHAR Rssi; + UCHAR Privacy; // Indicate security function ON/OFF. Don't mess up with auth mode. + UCHAR Hidden; + + USHORT DtimPeriod; + USHORT CapabilityInfo; + + USHORT CfpCount; + USHORT CfpPeriod; + USHORT CfpMaxDuration; + USHORT CfpDurRemaining; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + + ULONG LastBeaconRxTime; // OS's timestamp + + BOOLEAN bSES; + + // New for WPA2 + CIPHER_SUITE WPA; // AP announced WPA cipher suite + CIPHER_SUITE WPA2; // AP announced WPA2 cipher suite + + // New for microsoft WPA support + NDIS_802_11_FIXED_IEs FixIEs; + NDIS_802_11_AUTHENTICATION_MODE AuthModeAux; // Addition mode for WPA2 / WPA capable AP + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; // Unicast Encryption Algorithm extract from VAR_IE + USHORT VarIELen; // Length of next VIE include EID & Length + UCHAR VarIEs[MAX_VIE_LEN]; + + // CCX Ckip information + UCHAR CkipFlag; + + // CCX 2 TSF + UCHAR PTSF[4]; // Parent TSF + UCHAR TTSF[8]; // Target TSF + + // 802.11e d9, and WMM + EDCA_PARM EdcaParm; + QOS_CAPABILITY_PARM QosCapability; + QBSS_LOAD_PARM QbssLoad; +#ifdef CONFIG_STA_SUPPORT + WPA_IE_ WpaIE; + WPA_IE_ RsnIE; +#ifdef EXT_BUILD_CHANNEL_LIST + UCHAR CountryString[3]; + BOOLEAN bHasCountryIE; +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // +} BSS_ENTRY, *PBSS_ENTRY; + +typedef struct { + UCHAR BssNr; + UCHAR BssOverlapNr; + BSS_ENTRY BssEntry[MAX_LEN_OF_BSS_TABLE]; +} BSS_TABLE, *PBSS_TABLE; + + +typedef struct _MLME_QUEUE_ELEM { + ULONG Machine; + ULONG MsgType; + ULONG MsgLen; + UCHAR Msg[MGMT_DMA_BUFFER_SIZE]; + LARGE_INTEGER TimeStamp; + UCHAR Rssi0; + UCHAR Rssi1; + UCHAR Rssi2; + UCHAR Signal; + UCHAR Channel; + UCHAR Wcid; + BOOLEAN Occupied; +#ifdef MLME_EX + USHORT Idx; +#endif // MLME_EX // +} MLME_QUEUE_ELEM, *PMLME_QUEUE_ELEM; + +typedef struct _MLME_QUEUE { + ULONG Num; + ULONG Head; + ULONG Tail; + NDIS_SPIN_LOCK Lock; + MLME_QUEUE_ELEM Entry[MAX_LEN_OF_MLME_QUEUE]; +} MLME_QUEUE, *PMLME_QUEUE; + +typedef VOID (*STATE_MACHINE_FUNC)(VOID *Adaptor, MLME_QUEUE_ELEM *Elem); + +typedef struct _STATE_MACHINE { + ULONG Base; + ULONG NrState; + ULONG NrMsg; + ULONG CurrState; + STATE_MACHINE_FUNC *TransFunc; +} STATE_MACHINE, *PSTATE_MACHINE; + + +// MLME AUX data structure that hold temporarliy settings during a connection attempt. +// Once this attemp succeeds, all settings will be copy to pAd->StaActive. +// A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of +// several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely +// separate this under-trial settings away from pAd->StaActive so that once +// this new attempt failed, driver can auto-recover back to the active settings. +typedef struct _MLME_AUX { + UCHAR BssType; + UCHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR AutoReconnectSsid[MAX_LEN_OF_SSID]; + UCHAR AutoReconnectSsidLen; + USHORT Alg; + UCHAR ScanType; + UCHAR Channel; + UCHAR CentralChannel; + USHORT Aid; + USHORT CapabilityInfo; + USHORT BeaconPeriod; + USHORT CfpMaxDuration; + USHORT CfpPeriod; + USHORT AtimWin; + + // Copy supported rate from desired AP's beacon. We are trying to match + // AP's supported and extended rate settings. + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRateLen; + HT_CAPABILITY_IE HtCapability; + UCHAR HtCapabilityLen; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR NewExtChannelOffset; + //RT_HT_CAPABILITY SupportedHtPhy; + + // new for QOS + QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP + EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP + QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP + + // new to keep Ralink specific feature + ULONG APRalinkIe; + + BSS_TABLE SsidBssTab; // AP list for the same SSID + BSS_TABLE RoamTab; // AP list eligible for roaming + ULONG BssIdx; + ULONG RoamIdx; + + BOOLEAN CurrReqIsFromNdis; + + RALINK_TIMER_STRUCT BeaconTimer, ScanTimer; + RALINK_TIMER_STRUCT AuthTimer; + RALINK_TIMER_STRUCT AssocTimer, ReassocTimer, DisassocTimer; +} MLME_AUX, *PMLME_AUX; + +typedef struct _MLME_ADDBA_REQ_STRUCT{ + UCHAR Wcid; // + UCHAR pAddr[MAC_ADDR_LEN]; + UCHAR BaBufSize; + USHORT TimeOutValue; + UCHAR TID; + UCHAR Token; + USHORT BaStartSeq; +} MLME_ADDBA_REQ_STRUCT, *PMLME_ADDBA_REQ_STRUCT; + + +typedef struct _MLME_DELBA_REQ_STRUCT{ + UCHAR Wcid; // + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR TID; + UCHAR Initiator; +} MLME_DELBA_REQ_STRUCT, *PMLME_DELBA_REQ_STRUCT; + +// assoc struct is equal to reassoc +typedef struct _MLME_ASSOC_REQ_STRUCT{ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + USHORT ListenIntv; + ULONG Timeout; +} MLME_ASSOC_REQ_STRUCT, *PMLME_ASSOC_REQ_STRUCT, MLME_REASSOC_REQ_STRUCT, *PMLME_REASSOC_REQ_STRUCT; + +typedef struct _MLME_DISASSOC_REQ_STRUCT{ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; +} MLME_DISASSOC_REQ_STRUCT, *PMLME_DISASSOC_REQ_STRUCT; + +typedef struct _MLME_AUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg; + ULONG Timeout; +} MLME_AUTH_REQ_STRUCT, *PMLME_AUTH_REQ_STRUCT; + +typedef struct _MLME_DEAUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; +} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT; + +typedef struct { + ULONG BssIdx; +} MLME_JOIN_REQ_STRUCT; + +typedef struct _MLME_SCAN_REQ_STRUCT { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR BssType; + UCHAR ScanType; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; +} MLME_SCAN_REQ_STRUCT, *PMLME_SCAN_REQ_STRUCT; + +typedef struct _MLME_START_REQ_STRUCT { + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; +} MLME_START_REQ_STRUCT, *PMLME_START_REQ_STRUCT; + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +// structure for DLS +typedef struct _RT_802_11_DLS { + USHORT TimeOut; // Use to time out while slience, unit: second , set by UI + USHORT CountDownTimer; // Use to time out while slience,unit: second , used by driver only + NDIS_802_11_MAC_ADDRESS MacAddr; // set by UI + UCHAR Status; // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only + BOOLEAN Valid; // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link + RALINK_TIMER_STRUCT Timer; // Use to time out while handshake + USHORT Sequence; + USHORT MacTabMatchWCID; // ASIC + BOOLEAN bHTCap; + PVOID pAd; +} RT_802_11_DLS, *PRT_802_11_DLS; + +typedef struct _MLME_DLS_REQ_STRUCT { + PRT_802_11_DLS pDLS; + USHORT Reason; +} MLME_DLS_REQ_STRUCT, *PMLME_DLS_REQ_STRUCT; +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +typedef struct PACKED { + UCHAR Eid; + UCHAR Len; + CHAR Octet[1]; +} EID_STRUCT,*PEID_STRUCT, BEACON_EID_STRUCT, *PBEACON_EID_STRUCT; + +typedef struct PACKED _RTMP_TX_RATE_SWITCH +{ + UCHAR ItemNo; +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:2; + UCHAR Mode:2; + UCHAR Rsv1:1; + UCHAR BW:1; + UCHAR ShortGI:1; + UCHAR STBC:1; +#else + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:1; + UCHAR Rsv1:1; + UCHAR Mode:2; + UCHAR Rsv2:2; +#endif + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; +} RRTMP_TX_RATE_SWITCH, *PRTMP_TX_RATE_SWITCH; + +// ========================== AP mlme.h =============================== +#define TBTT_PRELOAD_TIME 384 // usec. LomgPreamble + 24-byte at 1Mbps +#define DEFAULT_DTIM_PERIOD 1 + +// weighting factor to calculate Channel quality, total should be 100% +//#define RSSI_WEIGHTING 0 +//#define TX_WEIGHTING 40 +//#define RX_WEIGHTING 60 + +#define MAC_TABLE_AGEOUT_TIME 300 // unit: sec +#define MAC_TABLE_ASSOC_TIMEOUT 5 // unit: sec +#define MAC_TABLE_FULL(Tab) ((Tab).size == MAX_LEN_OF_MAC_TABLE) + +// AP shall drop the sta if contine Tx fail count reach it. +#define MAC_ENTRY_LIFE_CHECK_CNT 20 // packet cnt. + +// Value domain of pMacEntry->Sst +typedef enum _Sst { + SST_NOT_AUTH, // 0: equivalent to IEEE 802.11/1999 state 1 + SST_AUTH, // 1: equivalent to IEEE 802.11/1999 state 2 + SST_ASSOC // 2: equivalent to IEEE 802.11/1999 state 3 +} SST; + +// value domain of pMacEntry->AuthState +typedef enum _AuthState { + AS_NOT_AUTH, + AS_AUTH_OPEN, // STA has been authenticated using OPEN SYSTEM + AS_AUTH_KEY, // STA has been authenticated using SHARED KEY + AS_AUTHENTICATING // STA is waiting for AUTH seq#3 using SHARED KEY +} AUTH_STATE; + +//for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 +typedef enum _ApWpaState { + AS_NOTUSE, // 0 + AS_DISCONNECT, // 1 + AS_DISCONNECTED, // 2 + AS_INITIALIZE, // 3 + AS_AUTHENTICATION, // 4 + AS_AUTHENTICATION2, // 5 + AS_INITPMK, // 6 + AS_INITPSK, // 7 + AS_PTKSTART, // 8 + AS_PTKINIT_NEGOTIATING, // 9 + AS_PTKINITDONE, // 10 + AS_UPDATEKEYS, // 11 + AS_INTEGRITY_FAILURE, // 12 + AS_KEYUPDATE, // 13 +} AP_WPA_STATE; + +// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 +typedef enum _GTKState { + REKEY_NEGOTIATING, + REKEY_ESTABLISHED, + KEYERROR, +} GTK_STATE; + +// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114 +typedef enum _WpaGTKState { + SETKEYS, + SETKEYS_DONE, +} WPA_GTK_STATE; +// ====================== end of AP mlme.h ============================ + + +#endif // MLME_H__ diff --git a/drivers/staging/rt3070/netif_block.h b/drivers/staging/rt3070/netif_block.h new file mode 100644 index 000000000000..6e5151c41095 --- /dev/null +++ b/drivers/staging/rt3070/netif_block.h @@ -0,0 +1,58 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + */ + +#ifndef __NET_IF_BLOCK_H__ +#define __NET_IF_BLOCK_H__ + +//#include +#include "link_list.h" +#include "rtmp.h" + +#define FREE_NETIF_POOL_SIZE 32 + +typedef struct _NETIF_ENTRY +{ + struct _NETIF_ENTRY *pNext; + PNET_DEV pNetDev; +} NETIF_ENTRY, *PNETIF_ENTRY; + +void initblockQueueTab( + IN PRTMP_ADAPTER pAd); + +BOOLEAN blockNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry, + IN PNET_DEV pNetDev); + +VOID releaseNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry); + +VOID StopNetIfQueue( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); +#endif // __NET_IF_BLOCK_H__ + diff --git a/drivers/staging/rt3070/oid.h b/drivers/staging/rt3070/oid.h new file mode 100644 index 000000000000..f78bf0a5f140 --- /dev/null +++ b/drivers/staging/rt3070/oid.h @@ -0,0 +1,1142 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + oid.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#ifndef _OID_H_ +#define _OID_H_ + +//#include + + +#define TRUE 1 +#define FALSE 0 +// +// IEEE 802.11 Structures and definitions +// +#define MAX_TX_POWER_LEVEL 100 /* mW */ +#define MAX_RSSI_TRIGGER -10 /* dBm */ +#define MIN_RSSI_TRIGGER -200 /* dBm */ +#define MAX_FRAG_THRESHOLD 2346 /* byte count */ +#define MIN_FRAG_THRESHOLD 256 /* byte count */ +#define MAX_RTS_THRESHOLD 2347 /* byte count */ + +// new types for Media Specific Indications +// Extension channel offset +#define EXTCHA_NONE 0 +#define EXTCHA_ABOVE 0x1 +#define EXTCHA_BELOW 0x3 + +// BW +#define BAND_WIDTH_20 0 +#define BAND_WIDTH_40 1 +#define BAND_WIDTH_BOTH 2 +#define BAND_WIDTH_10 3 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. +// SHORTGI +#define GAP_INTERVAL_400 1 // only support in HT mode +#define GAP_INTERVAL_800 0 +#define GAP_INTERVAL_BOTH 2 + +#define NdisMediaStateConnected 1 +#define NdisMediaStateDisconnected 0 + +#define NDIS_802_11_LENGTH_SSID 32 +#define NDIS_802_11_LENGTH_RATES 8 +#define NDIS_802_11_LENGTH_RATES_EX 16 +#define MAC_ADDR_LENGTH 6 +#define MAX_NUM_OF_CHS 49 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL terminationc +#define MAX_NUMBER_OF_EVENT 10 // entry # in EVENT table +#define MAX_NUMBER_OF_MAC 32 // if MAX_MBSSID_NUM is 8, this value can't be larger than 211 +#define MAX_NUMBER_OF_ACL 64 +#define MAX_LENGTH_OF_SUPPORT_RATES 12 // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 +#define MAX_NUMBER_OF_DLS_ENTRY 4 + + + +#ifndef UNDER_CE +// OID definition, since NDIS 5.0 didn't define these, we need to define for our own +//#if _WIN32_WINNT<=0x0500 + +#define OID_GEN_MACHINE_NAME 0x0001021A + +#ifdef RALINK_ATE +#define RT_QUERY_ATE_TXDONE_COUNT 0x0401 +#endif // RALINK_ATE // +#define RT_QUERY_SIGNAL_CONTEXT 0x0402 +#define RT_SET_IAPP_PID 0x0404 +#define RT_SET_APD_PID 0x0405 +#define RT_SET_DEL_MAC_ENTRY 0x0406 + +// +// IEEE 802.11 OIDs +// +#define OID_GET_SET_TOGGLE 0x8000 + +#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0103 +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0104 +#define OID_802_11_RSSI_TRIGGER 0x0107 +#define RT_OID_802_11_RSSI 0x0108 //rt2860 only , kathy +#define RT_OID_802_11_RSSI_1 0x0109 //rt2860 only , kathy +#define RT_OID_802_11_RSSI_2 0x010A //rt2860 only , kathy +#define OID_802_11_NUMBER_OF_ANTENNAS 0x010B +#define OID_802_11_RX_ANTENNA_SELECTED 0x010C +#define OID_802_11_TX_ANTENNA_SELECTED 0x010D +#define OID_802_11_SUPPORTED_RATES 0x010E +#define OID_802_11_ADD_WEP 0x0112 +#define OID_802_11_REMOVE_WEP 0x0113 +#define OID_802_11_DISASSOCIATE 0x0114 +#define OID_802_11_PRIVACY_FILTER 0x0118 +#define OID_802_11_ASSOCIATION_INFORMATION 0x011E +#define OID_802_11_TEST 0x011F +#define RT_OID_802_11_COUNTRY_REGION 0x0507 +#define OID_802_11_BSSID_LIST_SCAN 0x0508 +#define OID_802_11_SSID 0x0509 +#define OID_802_11_BSSID 0x050A +#define RT_OID_802_11_RADIO 0x050B +#define RT_OID_802_11_PHY_MODE 0x050C +#define RT_OID_802_11_STA_CONFIG 0x050D +#define OID_802_11_DESIRED_RATES 0x050E +#define RT_OID_802_11_PREAMBLE 0x050F +#define OID_802_11_WEP_STATUS 0x0510 +#define OID_802_11_AUTHENTICATION_MODE 0x0511 +#define OID_802_11_INFRASTRUCTURE_MODE 0x0512 +#define RT_OID_802_11_RESET_COUNTERS 0x0513 +#define OID_802_11_RTS_THRESHOLD 0x0514 +#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0515 +#define OID_802_11_POWER_MODE 0x0516 +#define OID_802_11_TX_POWER_LEVEL 0x0517 +#define RT_OID_802_11_ADD_WPA 0x0518 +#define OID_802_11_REMOVE_KEY 0x0519 +#define OID_802_11_ADD_KEY 0x0520 +#define OID_802_11_CONFIGURATION 0x0521 +#define OID_802_11_TX_PACKET_BURST 0x0522 +#define RT_OID_802_11_QUERY_NOISE_LEVEL 0x0523 +#define RT_OID_802_11_EXTRA_INFO 0x0524 +#ifdef DBG +#define RT_OID_802_11_HARDWARE_REGISTER 0x0525 +#endif +#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS +#define OID_802_11_DEAUTHENTICATION 0x0526 +#define OID_802_11_DROP_UNENCRYPTED 0x0527 +#define OID_802_11_MIC_FAILURE_REPORT_FRAME 0x0528 + +// For 802.1x daemin using to require current driver configuration +#define OID_802_11_RADIUS_QUERY_SETTING 0x0540 + +#define RT_OID_DEVICE_NAME 0x0607 +#define RT_OID_VERSION_INFO 0x0608 +#define OID_802_11_BSSID_LIST 0x0609 +#define OID_802_3_CURRENT_ADDRESS 0x060A +#define OID_GEN_MEDIA_CONNECT_STATUS 0x060B +#define RT_OID_802_11_QUERY_LINK_STATUS 0x060C +#define OID_802_11_RSSI 0x060D +#define OID_802_11_STATISTICS 0x060E +#define OID_GEN_RCV_OK 0x060F +#define OID_GEN_RCV_NO_BUFFER 0x0610 +#define RT_OID_802_11_QUERY_EEPROM_VERSION 0x0611 +#define RT_OID_802_11_QUERY_FIRMWARE_VERSION 0x0612 +#define RT_OID_802_11_QUERY_LAST_RX_RATE 0x0613 +#define RT_OID_802_11_TX_POWER_LEVEL_1 0x0614 +#define RT_OID_802_11_QUERY_PIDVID 0x0615 +//for WPA_SUPPLICANT_SUPPORT +#define OID_SET_COUNTERMEASURES 0x0616 +#define OID_802_11_SET_IEEE8021X 0x0617 +#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618 +#define OID_802_11_PMKID 0x0620 +#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 +#define RT_OID_WE_VERSION_COMPILED 0x0622 +#define RT_OID_NEW_DRIVER 0x0623 + + +//rt2860 , kathy +#define RT_OID_802_11_SNR_0 0x0630 +#define RT_OID_802_11_SNR_1 0x0631 +#define RT_OID_802_11_QUERY_LAST_TX_RATE 0x0632 +#define RT_OID_802_11_QUERY_HT_PHYMODE 0x0633 +#define RT_OID_802_11_SET_HT_PHYMODE 0x0634 +#define OID_802_11_RELOAD_DEFAULTS 0x0635 +#define RT_OID_802_11_QUERY_APSD_SETTING 0x0636 +#define RT_OID_802_11_SET_APSD_SETTING 0x0637 +#define RT_OID_802_11_QUERY_APSD_PSM 0x0638 +#define RT_OID_802_11_SET_APSD_PSM 0x0639 +#define RT_OID_802_11_QUERY_DLS 0x063A +#define RT_OID_802_11_SET_DLS 0x063B +#define RT_OID_802_11_QUERY_DLS_PARAM 0x063C +#define RT_OID_802_11_SET_DLS_PARAM 0x063D +#define RT_OID_802_11_QUERY_WMM 0x063E +#define RT_OID_802_11_SET_WMM 0x063F +#define RT_OID_802_11_QUERY_IMME_BA_CAP 0x0640 +#define RT_OID_802_11_SET_IMME_BA_CAP 0x0641 +#define RT_OID_802_11_QUERY_BATABLE 0x0642 +#define RT_OID_802_11_ADD_IMME_BA 0x0643 +#define RT_OID_802_11_TEAR_IMME_BA 0x0644 +#define RT_OID_DRIVER_DEVICE_NAME 0x0645 +#define RT_OID_802_11_QUERY_DAT_HT_PHYMODE 0x0646 +#define RT_OID_QUERY_MULTIPLE_CARD_SUPPORT 0x0647 + +// Ralink defined OIDs +// Dennis Lee move to platform specific + +#define RT_OID_802_11_BSSID (OID_GET_SET_TOGGLE | OID_802_11_BSSID) +#define RT_OID_802_11_SSID (OID_GET_SET_TOGGLE | OID_802_11_SSID) +#define RT_OID_802_11_INFRASTRUCTURE_MODE (OID_GET_SET_TOGGLE | OID_802_11_INFRASTRUCTURE_MODE) +#define RT_OID_802_11_ADD_WEP (OID_GET_SET_TOGGLE | OID_802_11_ADD_WEP) +#define RT_OID_802_11_ADD_KEY (OID_GET_SET_TOGGLE | OID_802_11_ADD_KEY) +#define RT_OID_802_11_REMOVE_WEP (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_WEP) +#define RT_OID_802_11_REMOVE_KEY (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_KEY) +#define RT_OID_802_11_DISASSOCIATE (OID_GET_SET_TOGGLE | OID_802_11_DISASSOCIATE) +#define RT_OID_802_11_AUTHENTICATION_MODE (OID_GET_SET_TOGGLE | OID_802_11_AUTHENTICATION_MODE) +#define RT_OID_802_11_PRIVACY_FILTER (OID_GET_SET_TOGGLE | OID_802_11_PRIVACY_FILTER) +#define RT_OID_802_11_BSSID_LIST_SCAN (OID_GET_SET_TOGGLE | OID_802_11_BSSID_LIST_SCAN) +#define RT_OID_802_11_WEP_STATUS (OID_GET_SET_TOGGLE | OID_802_11_WEP_STATUS) +#define RT_OID_802_11_RELOAD_DEFAULTS (OID_GET_SET_TOGGLE | OID_802_11_RELOAD_DEFAULTS) +#define RT_OID_802_11_NETWORK_TYPE_IN_USE (OID_GET_SET_TOGGLE | OID_802_11_NETWORK_TYPE_IN_USE) +#define RT_OID_802_11_TX_POWER_LEVEL (OID_GET_SET_TOGGLE | OID_802_11_TX_POWER_LEVEL) +#define RT_OID_802_11_RSSI_TRIGGER (OID_GET_SET_TOGGLE | OID_802_11_RSSI_TRIGGER) +#define RT_OID_802_11_FRAGMENTATION_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_FRAGMENTATION_THRESHOLD) +#define RT_OID_802_11_RTS_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_RTS_THRESHOLD) +#define RT_OID_802_11_RX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_RX_ANTENNA_SELECTED) +#define RT_OID_802_11_TX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_TX_ANTENNA_SELECTED) +#define RT_OID_802_11_SUPPORTED_RATES (OID_GET_SET_TOGGLE | OID_802_11_SUPPORTED_RATES) +#define RT_OID_802_11_DESIRED_RATES (OID_GET_SET_TOGGLE | OID_802_11_DESIRED_RATES) +#define RT_OID_802_11_CONFIGURATION (OID_GET_SET_TOGGLE | OID_802_11_CONFIGURATION) +#define RT_OID_802_11_POWER_MODE (OID_GET_SET_TOGGLE | OID_802_11_POWER_MODE) + + + +typedef enum _NDIS_802_11_STATUS_TYPE +{ + Ndis802_11StatusType_Authentication, + Ndis802_11StatusType_MediaStreamMode, + Ndis802_11StatusType_PMKID_CandidateList, + Ndis802_11StatusTypeMax // not a real type, defined as an upper bound +} NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE; + +typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; + +typedef struct _NDIS_802_11_STATUS_INDICATION +{ + NDIS_802_11_STATUS_TYPE StatusType; +} NDIS_802_11_STATUS_INDICATION, *PNDIS_802_11_STATUS_INDICATION; + +// mask for authentication/integrity fields +#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f + +#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 +#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 +#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 +#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E + +typedef struct _NDIS_802_11_AUTHENTICATION_REQUEST +{ + ULONG Length; // Length of structure + NDIS_802_11_MAC_ADDRESS Bssid; + ULONG Flags; +} NDIS_802_11_AUTHENTICATION_REQUEST, *PNDIS_802_11_AUTHENTICATION_REQUEST; + +//Added new types for PMKID Candidate lists. +typedef struct _PMKID_CANDIDATE { + NDIS_802_11_MAC_ADDRESS BSSID; + ULONG Flags; +} PMKID_CANDIDATE, *PPMKID_CANDIDATE; + +typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST +{ + ULONG Version; // Version of the structure + ULONG NumCandidates; // No. of pmkid candidates + PMKID_CANDIDATE CandidateList[1]; +} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST; + +//Flags for PMKID Candidate list structure +#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 + +// Added new types for OFDM 5G and 2.4G +typedef enum _NDIS_802_11_NETWORK_TYPE +{ + Ndis802_11FH, + Ndis802_11DS, + Ndis802_11OFDM5, + Ndis802_11OFDM5_N, + Ndis802_11OFDM24, + Ndis802_11OFDM24_N, + Ndis802_11Automode, + Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound +} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; + +typedef struct _NDIS_802_11_NETWORK_TYPE_LIST +{ + UINT NumberOfItems; // in list below, at least 1 + NDIS_802_11_NETWORK_TYPE NetworkType [1]; +} NDIS_802_11_NETWORK_TYPE_LIST, *PNDIS_802_11_NETWORK_TYPE_LIST; + +typedef enum _NDIS_802_11_POWER_MODE +{ + Ndis802_11PowerModeCAM, + Ndis802_11PowerModeMAX_PSP, + Ndis802_11PowerModeFast_PSP, + Ndis802_11PowerModeLegacy_PSP, + Ndis802_11PowerModeMax // not a real mode, defined as an upper bound +} NDIS_802_11_POWER_MODE, *PNDIS_802_11_POWER_MODE; + +typedef ULONG NDIS_802_11_TX_POWER_LEVEL; // in milliwatts + +// +// Received Signal Strength Indication +// +typedef LONG NDIS_802_11_RSSI; // in dBm + +typedef struct _NDIS_802_11_CONFIGURATION_FH +{ + ULONG Length; // Length of structure + ULONG HopPattern; // As defined by 802.11, MSB set + ULONG HopSet; // to one if non-802.11 + ULONG DwellTime; // units are Kusec +} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH; + +typedef struct _NDIS_802_11_CONFIGURATION +{ + ULONG Length; // Length of structure + ULONG BeaconPeriod; // units are Kusec + ULONG ATIMWindow; // units are Kusec + ULONG DSConfig; // Frequency, units are kHz + NDIS_802_11_CONFIGURATION_FH FHConfig; +} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION; + +typedef struct _NDIS_802_11_STATISTICS +{ + ULONG Length; // Length of structure + LARGE_INTEGER TransmittedFragmentCount; + LARGE_INTEGER MulticastTransmittedFrameCount; + LARGE_INTEGER FailedCount; + LARGE_INTEGER RetryCount; + LARGE_INTEGER MultipleRetryCount; + LARGE_INTEGER RTSSuccessCount; + LARGE_INTEGER RTSFailureCount; + LARGE_INTEGER ACKFailureCount; + LARGE_INTEGER FrameDuplicateCount; + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER MulticastReceivedFrameCount; + LARGE_INTEGER FCSErrorCount; + LARGE_INTEGER TKIPLocalMICFailures; + LARGE_INTEGER TKIPRemoteMICErrors; + LARGE_INTEGER TKIPICVErrors; + LARGE_INTEGER TKIPCounterMeasuresInvoked; + LARGE_INTEGER TKIPReplays; + LARGE_INTEGER CCMPFormatErrors; + LARGE_INTEGER CCMPReplays; + LARGE_INTEGER CCMPDecryptErrors; + LARGE_INTEGER FourWayHandshakeFailures; +} NDIS_802_11_STATISTICS, *PNDIS_802_11_STATISTICS; + +typedef ULONG NDIS_802_11_KEY_INDEX; +typedef ULONGLONG NDIS_802_11_KEY_RSC; + +#define MAX_RADIUS_SRV_NUM 2 // 802.1x failover number + +typedef struct PACKED _RADIUS_SRV_INFO { + UINT32 radius_ip; + UINT32 radius_port; + UCHAR radius_key[64]; + UCHAR radius_key_len; +} RADIUS_SRV_INFO, *PRADIUS_SRV_INFO; + +typedef struct PACKED _RADIUS_KEY_INFO +{ + UCHAR radius_srv_num; + RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; + UCHAR ieee8021xWEP; // dynamic WEP + UCHAR key_index; + UCHAR key_length; // length of key in bytes + UCHAR key_material[13]; +} RADIUS_KEY_INFO, *PRADIUS_KEY_INFO; + +// It's used by 802.1x daemon to require relative configuration +typedef struct PACKED _RADIUS_CONF +{ + UINT32 Length; // Length of this structure + UCHAR mbss_num; // indicate multiple BSS number + UINT32 own_ip_addr; + UINT32 retry_interval; + UINT32 session_timeout_interval; + UCHAR EAPifname[IFNAMSIZ]; + UCHAR EAPifname_len; + UCHAR PreAuthifname[IFNAMSIZ]; + UCHAR PreAuthifname_len; + RADIUS_KEY_INFO RadiusInfo[8/*MAX_MBSSID_NUM*/]; +} RADIUS_CONF, *PRADIUS_CONF; + + + +#ifdef CONFIG_STA_SUPPORT +// Key mapping keys require a BSSID +typedef struct _NDIS_802_11_KEY +{ + UINT Length; // Length of this structure + UINT KeyIndex; + UINT KeyLength; // length of key in bytes + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_KEY_RSC KeyRSC; + UCHAR KeyMaterial[1]; // variable length depending on above field +} NDIS_802_11_KEY, *PNDIS_802_11_KEY; +#endif // CONFIG_STA_SUPPORT // + +typedef struct _NDIS_802_11_REMOVE_KEY +{ + UINT Length; // Length of this structure + UINT KeyIndex; + NDIS_802_11_MAC_ADDRESS BSSID; +} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY; + +typedef struct _NDIS_802_11_WEP +{ + UINT Length; // Length of this structure + UINT KeyIndex; // 0 is the per-client key, 1-N are the + // global keys + UINT KeyLength; // length of key in bytes + UCHAR KeyMaterial[1];// variable length depending on above field +} NDIS_802_11_WEP, *PNDIS_802_11_WEP; + + +typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE +{ + Ndis802_11IBSS, + Ndis802_11Infrastructure, + Ndis802_11AutoUnknown, + Ndis802_11Monitor, + Ndis802_11InfrastructureMax // Not a real value, defined as upper bound +} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE; + +// Add new authentication modes +typedef enum _NDIS_802_11_AUTHENTICATION_MODE +{ + Ndis802_11AuthModeOpen, + Ndis802_11AuthModeShared, + Ndis802_11AuthModeAutoSwitch, + Ndis802_11AuthModeWPA, + Ndis802_11AuthModeWPAPSK, + Ndis802_11AuthModeWPANone, + Ndis802_11AuthModeWPA2, + Ndis802_11AuthModeWPA2PSK, + Ndis802_11AuthModeWPA1WPA2, + Ndis802_11AuthModeWPA1PSKWPA2PSK, + Ndis802_11AuthModeMax // Not a real mode, defined as upper bound +} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE; + +typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; // Set of 8 data rates +typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; // Set of 16 data rates + +typedef struct PACKED _NDIS_802_11_SSID +{ + UINT SsidLength; // length of SSID field below, in bytes; + // this can be zero. + UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; // SSID information field +} NDIS_802_11_SSID, *PNDIS_802_11_SSID; + + +typedef struct PACKED _NDIS_WLAN_BSSID +{ + ULONG Length; // Length of this structure + NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID + UCHAR Reserved[2]; + NDIS_802_11_SSID Ssid; // SSID + ULONG Privacy; // WEP encryption requirement + NDIS_802_11_RSSI Rssi; // receive signal strength in dBm + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES SupportedRates; +} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; + +typedef struct PACKED _NDIS_802_11_BSSID_LIST +{ + UINT NumberOfItems; // in list below, at least 1 + NDIS_WLAN_BSSID Bssid[1]; +} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; + +// Added Capabilities, IELength and IEs for each BSSID +typedef struct PACKED _NDIS_WLAN_BSSID_EX +{ + ULONG Length; // Length of this structure + NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID + UCHAR Reserved[2]; + NDIS_802_11_SSID Ssid; // SSID + UINT Privacy; // WEP encryption requirement + NDIS_802_11_RSSI Rssi; // receive signal + // strength in dBm + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES_EX SupportedRates; + ULONG IELength; + UCHAR IEs[1]; +} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; + +typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX +{ + UINT NumberOfItems; // in list below, at least 1 + NDIS_WLAN_BSSID_EX Bssid[1]; +} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX; + +typedef struct PACKED _NDIS_802_11_FIXED_IEs +{ + UCHAR Timestamp[8]; + USHORT BeaconInterval; + USHORT Capabilities; +} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs; + +typedef struct _NDIS_802_11_VARIABLE_IEs +{ + UCHAR ElementID; + UCHAR Length; // Number of bytes in data field + UCHAR data[1]; +} NDIS_802_11_VARIABLE_IEs, *PNDIS_802_11_VARIABLE_IEs; + +typedef ULONG NDIS_802_11_FRAGMENTATION_THRESHOLD; + +typedef ULONG NDIS_802_11_RTS_THRESHOLD; + +typedef ULONG NDIS_802_11_ANTENNA; + +typedef enum _NDIS_802_11_PRIVACY_FILTER +{ + Ndis802_11PrivFilterAcceptAll, + Ndis802_11PrivFilter8021xWEP +} NDIS_802_11_PRIVACY_FILTER, *PNDIS_802_11_PRIVACY_FILTER; + +// Added new encryption types +// Also aliased typedef to new name +typedef enum _NDIS_802_11_WEP_STATUS +{ + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11Encryption2Enabled, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11Encryption4Enabled, // TKIP or AES mix + Ndis802_11Encryption4KeyAbsent, +} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, + NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; + +typedef enum _NDIS_802_11_RELOAD_DEFAULTS +{ + Ndis802_11ReloadWEPKeys +} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS; + +#define NDIS_802_11_AI_REQFI_CAPABILITIES 1 +#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2 +#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4 + +#define NDIS_802_11_AI_RESFI_CAPABILITIES 1 +#define NDIS_802_11_AI_RESFI_STATUSCODE 2 +#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 + +typedef struct _NDIS_802_11_AI_REQFI +{ + USHORT Capabilities; + USHORT ListenInterval; + NDIS_802_11_MAC_ADDRESS CurrentAPAddress; +} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; + +typedef struct _NDIS_802_11_AI_RESFI +{ + USHORT Capabilities; + USHORT StatusCode; + USHORT AssociationId; +} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; + +typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION +{ + ULONG Length; + USHORT AvailableRequestFixedIEs; + NDIS_802_11_AI_REQFI RequestFixedIEs; + ULONG RequestIELength; + ULONG OffsetRequestIEs; + USHORT AvailableResponseFixedIEs; + NDIS_802_11_AI_RESFI ResponseFixedIEs; + ULONG ResponseIELength; + ULONG OffsetResponseIEs; +} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; + +typedef struct _NDIS_802_11_AUTHENTICATION_EVENT +{ + NDIS_802_11_STATUS_INDICATION Status; + NDIS_802_11_AUTHENTICATION_REQUEST Request[1]; +} NDIS_802_11_AUTHENTICATION_EVENT, *PNDIS_802_11_AUTHENTICATION_EVENT; + +/* +typedef struct _NDIS_802_11_TEST +{ + ULONG Length; + ULONG Type; + union + { + NDIS_802_11_AUTHENTICATION_EVENT AuthenticationEvent; + NDIS_802_11_RSSI RssiTrigger; + }; +} NDIS_802_11_TEST, *PNDIS_802_11_TEST; + */ + +// 802.11 Media stream constraints, associated with OID_802_11_MEDIA_STREAM_MODE +typedef enum _NDIS_802_11_MEDIA_STREAM_MODE +{ + Ndis802_11MediaStreamOff, + Ndis802_11MediaStreamOn, +} NDIS_802_11_MEDIA_STREAM_MODE, *PNDIS_802_11_MEDIA_STREAM_MODE; + +// PMKID Structures +typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; + +#ifdef CONFIG_STA_SUPPORT +typedef struct _BSSID_INFO +{ + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_PMKID_VALUE PMKID; +} BSSID_INFO, *PBSSID_INFO; + +typedef struct _NDIS_802_11_PMKID +{ + UINT Length; + UINT BSSIDInfoCount; + BSSID_INFO BSSIDInfo[1]; +} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID; +#endif // CONFIG_STA_SUPPORT // + + +typedef struct _NDIS_802_11_AUTHENTICATION_ENCRYPTION +{ + NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; + NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; +} NDIS_802_11_AUTHENTICATION_ENCRYPTION, *PNDIS_802_11_AUTHENTICATION_ENCRYPTION; + +typedef struct _NDIS_802_11_CAPABILITY +{ + ULONG Length; + ULONG Version; + ULONG NoOfPMKIDs; + ULONG NoOfAuthEncryptPairsSupported; + NDIS_802_11_AUTHENTICATION_ENCRYPTION AuthenticationEncryptionSupported[1]; +} NDIS_802_11_CAPABILITY, *PNDIS_802_11_CAPABILITY; + +//#endif //of WIN 2k +#endif //UNDER_CE + +#if WIRELESS_EXT <= 11 +#ifndef SIOCDEVPRIVATE +#define SIOCDEVPRIVATE 0x8BE0 +#endif +#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE +#endif + +#ifdef CONFIG_STA_SUPPORT +#define RT_PRIV_IOCTL_EXT (SIOCIWFIRSTPRIV + 0x01) // Sync. with AP for wsc upnp daemon +#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02) + +#ifdef DBG +#define RTPRIV_IOCTL_BBP (SIOCIWFIRSTPRIV + 0x03) +#define RTPRIV_IOCTL_MAC (SIOCIWFIRSTPRIV + 0x05) +#define RTPRIV_IOCTL_RF (SIOCIWFIRSTPRIV + 0x13) +#define RTPRIV_IOCTL_E2P (SIOCIWFIRSTPRIV + 0x07) +#endif + +#ifdef RALINK_ATE +#ifdef RALINK_28xx_QA +#define RTPRIV_IOCTL_ATE (SIOCIWFIRSTPRIV + 0x08) +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +#define RTPRIV_IOCTL_STATISTICS (SIOCIWFIRSTPRIV + 0x09) +#define RTPRIV_IOCTL_ADD_PMKID_CACHE (SIOCIWFIRSTPRIV + 0x0A) +#define RTPRIV_IOCTL_RADIUS_DATA (SIOCIWFIRSTPRIV + 0x0C) +#define RTPRIV_IOCTL_GSITESURVEY (SIOCIWFIRSTPRIV + 0x0D) +#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x0E) // Sync. with RT61 (for wpa_supplicant) +#define RTPRIV_IOCTL_GET_MAC_TABLE (SIOCIWFIRSTPRIV + 0x0F) + +#define RTPRIV_IOCTL_SHOW (SIOCIWFIRSTPRIV + 0x11) +enum { + SHOW_CONN_STATUS = 4, + SHOW_DRVIER_VERION = 5, + SHOW_BA_INFO = 6, + SHOW_DESC_INFO = 7, +#ifdef RT2870 + SHOW_RXBULK_INFO = 8, + SHOW_TXBULK_INFO = 9, +#endif // RT2870 // + RAIO_OFF = 10, + RAIO_ON = 11, +#ifdef QOS_DLS_SUPPORT + SHOW_DLS_ENTRY_INFO = 19, +#endif // QOS_DLS_SUPPORT // + SHOW_CFG_VALUE = 20, +}; + + +#endif // CONFIG_STA_SUPPORT // + + + +#ifdef SNMP_SUPPORT +//SNMP ieee 802dot11, kathy , 2008_0220 +// dot11res(3) +#define RT_OID_802_11_MANUFACTUREROUI 0x0700 +#define RT_OID_802_11_MANUFACTURERNAME 0x0701 +#define RT_OID_802_11_RESOURCETYPEIDNAME 0x0702 + +// dot11smt(1) +#define RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED 0x0703 +#define RT_OID_802_11_POWERMANAGEMENTMODE 0x0704 +#define OID_802_11_WEPDEFAULTKEYVALUE 0x0705 // read , write +#define OID_802_11_WEPDEFAULTKEYID 0x0706 +#define RT_OID_802_11_WEPKEYMAPPINGLENGTH 0x0707 +#define OID_802_11_SHORTRETRYLIMIT 0x0708 +#define OID_802_11_LONGRETRYLIMIT 0x0709 +#define RT_OID_802_11_PRODUCTID 0x0710 +#define RT_OID_802_11_MANUFACTUREID 0x0711 + +// //dot11Phy(4) +#define OID_802_11_CURRENTCHANNEL 0x0712 + +//dot11mac +#define RT_OID_802_11_MAC_ADDRESS 0x0713 +#endif // SNMP_SUPPORT // + +#define OID_802_11_BUILD_CHANNEL_EX 0x0714 +#define OID_802_11_GET_CH_LIST 0x0715 +#define OID_802_11_GET_COUNTRY_CODE 0x0716 +#define OID_802_11_GET_CHANNEL_GEOGRAPHY 0x0717 + +//#define RT_OID_802_11_STATISTICS (OID_GET_SET_TOGGLE | OID_802_11_STATISTICS) + +#ifdef CONFIG_STA_SUPPORT +#define RT_OID_WSC_SET_PASSPHRASE 0x0740 // passphrase for wpa(2)-psk +#define RT_OID_WSC_DRIVER_AUTO_CONNECT 0x0741 +#define RT_OID_WSC_QUERY_DEFAULT_PROFILE 0x0742 +#define RT_OID_WSC_SET_CONN_BY_PROFILE_INDEX 0x0743 +#define RT_OID_WSC_SET_ACTION 0x0744 +#define RT_OID_WSC_SET_SSID 0x0745 +#define RT_OID_WSC_SET_PIN_CODE 0x0746 +#define RT_OID_WSC_SET_MODE 0x0747 // PIN or PBC +#define RT_OID_WSC_SET_CONF_MODE 0x0748 // Enrollee or Registrar +#define RT_OID_WSC_SET_PROFILE 0x0749 +#endif // CONFIG_STA_SUPPORT // +#define RT_OID_802_11_WSC_QUERY_PROFILE 0x0750 +// for consistency with RT61 +#define RT_OID_WSC_QUERY_STATUS 0x0751 +#define RT_OID_WSC_PIN_CODE 0x0752 +#define RT_OID_WSC_UUID 0x0753 +#define RT_OID_WSC_SET_SELECTED_REGISTRAR 0x0754 +#define RT_OID_WSC_EAPMSG 0x0755 +#define RT_OID_WSC_MANUFACTURER 0x0756 +#define RT_OID_WSC_MODEL_NAME 0x0757 +#define RT_OID_WSC_MODEL_NO 0x0758 +#define RT_OID_WSC_SERIAL_NO 0x0759 +#define RT_OID_WSC_MAC_ADDRESS 0x0760 + +#ifdef LLTD_SUPPORT +// for consistency with RT61 +#define RT_OID_GET_PHY_MODE 0x761 +#endif // LLTD_SUPPORT // + +#ifdef NINTENDO_AP +//#define RT_OID_NINTENDO 0x0D010770 +#define RT_OID_802_11_NINTENDO_GET_TABLE 0x0771 //((RT_OID_NINTENDO + 0x01) & 0xffff) +#define RT_OID_802_11_NINTENDO_SET_TABLE 0x0772 //((RT_OID_NINTENDO + 0x02) & 0xffff) +#define RT_OID_802_11_NINTENDO_CAPABLE 0x0773 //((RT_OID_NINTENDO + 0x03) & 0xffff) +#endif // NINTENDO_AP // + +//Add Paul Chen for Accton +//#define RT_OID_TX_POWER_LEVEL 0xFF020010 +//#define RT_OID_SET_TX_POWER_LEVEL (OID_GET_SET_TOGGLE | RT_OID_TX_POWER_LEVEL) + +// New for MeetingHouse Api support +#define OID_MH_802_1X_SUPPORTED 0xFFEDC100 + +// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! +typedef union _HTTRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + USHORT MODE:2; // Use definition MODE_xxx. +// USHORT rsv:3; + USHORT TxBF:1; + USHORT rsv:2; + USHORT STBC:2; //SPACE + USHORT ShortGI:1; + USHORT BW:1; //channel bandwidth 20MHz or 40 MHz + USHORT MCS:7; // MCS + } field; +#else + struct { + USHORT MCS:7; // MCS + USHORT BW:1; //channel bandwidth 20MHz or 40 MHz + USHORT ShortGI:1; + USHORT STBC:2; //SPACE +// USHORT rsv:3; + USHORT rsv:2; + USHORT TxBF:1; + USHORT MODE:2; // Use definition MODE_xxx. + } field; +#endif + USHORT word; + } HTTRANSMIT_SETTING, *PHTTRANSMIT_SETTING; + +typedef enum _RT_802_11_PREAMBLE { + Rt802_11PreambleLong, + Rt802_11PreambleShort, + Rt802_11PreambleAuto +} RT_802_11_PREAMBLE, *PRT_802_11_PREAMBLE; + +// Only for STA, need to sync with AP +// 2005-03-08 match current RaConfig. +typedef enum _RT_802_11_PHY_MODE { + PHY_11BG_MIXED = 0, + PHY_11B, + PHY_11A, + PHY_11ABG_MIXED, + PHY_11G, +#ifdef DOT11_N_SUPPORT + PHY_11ABGN_MIXED, // both band 5 + PHY_11N_2_4G, // 11n-only with 2.4G band 6 + PHY_11GN_MIXED, // 2.4G band 7 + PHY_11AN_MIXED, // 5G band 8 + PHY_11BGN_MIXED, // if check 802.11b. 9 + PHY_11AGN_MIXED, // if check 802.11b. 10 + PHY_11N_5G, // 11n-only with 5G band 11 +#endif // DOT11_N_SUPPORT // +} RT_802_11_PHY_MODE; + +// put all proprietery for-query objects here to reduce # of Query_OID +typedef struct _RT_802_11_LINK_STATUS { + ULONG CurrTxRate; // in units of 0.5Mbps + ULONG ChannelQuality; // 0..100 % + ULONG TxByteCount; // both ok and fail + ULONG RxByteCount; // both ok and fail + ULONG CentralChannel; // 40MHz central channel number +} RT_802_11_LINK_STATUS, *PRT_802_11_LINK_STATUS; + +typedef struct _RT_802_11_EVENT_LOG { + LARGE_INTEGER SystemTime; // timestammp via NdisGetCurrentSystemTime() + UCHAR Addr[MAC_ADDR_LENGTH]; + USHORT Event; // EVENT_xxx +} RT_802_11_EVENT_LOG, *PRT_802_11_EVENT_LOG; + +typedef struct _RT_802_11_EVENT_TABLE { + ULONG Num; + ULONG Rsv; // to align Log[] at LARGE_INEGER boundary + RT_802_11_EVENT_LOG Log[MAX_NUMBER_OF_EVENT]; +} RT_802_11_EVENT_TABLE, PRT_802_11_EVENT_TABLE; + +// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! +typedef union _MACHTTRANSMIT_SETTING { + struct { + USHORT MCS:7; // MCS + USHORT BW:1; //channel bandwidth 20MHz or 40 MHz + USHORT ShortGI:1; + USHORT STBC:2; //SPACE + USHORT rsv:3; + USHORT MODE:2; // Use definition MODE_xxx. + } field; + USHORT word; + } MACHTTRANSMIT_SETTING, *PMACHTTRANSMIT_SETTING; + +typedef struct _RT_802_11_MAC_ENTRY { + UCHAR Addr[MAC_ADDR_LENGTH]; + UCHAR Aid; + UCHAR Psm; // 0:PWR_ACTIVE, 1:PWR_SAVE + UCHAR MimoPs; // 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled + CHAR AvgRssi0; + CHAR AvgRssi1; + CHAR AvgRssi2; + UINT32 ConnectedTime; + MACHTTRANSMIT_SETTING TxRate; +} RT_802_11_MAC_ENTRY, *PRT_802_11_MAC_ENTRY; + +typedef struct _RT_802_11_MAC_TABLE { + ULONG Num; + RT_802_11_MAC_ENTRY Entry[MAX_NUMBER_OF_MAC]; +} RT_802_11_MAC_TABLE, *PRT_802_11_MAC_TABLE; + +// structure for query/set hardware register - MAC, BBP, RF register +typedef struct _RT_802_11_HARDWARE_REGISTER { + ULONG HardwareType; // 0:MAC, 1:BBP, 2:RF register, 3:EEPROM + ULONG Offset; // Q/S register offset addr + ULONG Data; // R/W data buffer +} RT_802_11_HARDWARE_REGISTER, *PRT_802_11_HARDWARE_REGISTER; + +// structure to tune BBP R17 "RX AGC VGC init" +//typedef struct _RT_802_11_RX_AGC_VGC_TUNING { +// UCHAR FalseCcaLowerThreshold; // 0-255, def 10 +// UCHAR FalseCcaUpperThreshold; // 0-255, def 100 +// UCHAR VgcDelta; // R17 +-= VgcDelta whenever flase CCA over UpprThreshold +// // or lower than LowerThresholdupper threshold +// UCHAR VgcUpperBound; // max value of R17 +//} RT_802_11_RX_AGC_VGC_TUNING, *PRT_802_11_RX_AGC_VGC_TUNING; + +typedef struct _RT_802_11_AP_CONFIG { + ULONG EnableTxBurst; // 0-disable, 1-enable + ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate + ULONG IsolateInterStaTraffic; // 0-disable, 1-enable isolation + ULONG HideSsid; // 0-disable, 1-enable hiding + ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF + ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time + ULONG Rsv1; // must be 0 + ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY +} RT_802_11_AP_CONFIG, *PRT_802_11_AP_CONFIG; + +// structure to query/set STA_CONFIG +typedef struct _RT_802_11_STA_CONFIG { + ULONG EnableTxBurst; // 0-disable, 1-enable + ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate + ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF + ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time when applicable + ULONG AdhocMode; // 0-11b rates only (WIFI spec), 1 - b/g mixed, 2 - g only + ULONG HwRadioStatus; // 0-OFF, 1-ON, default is 1, Read-Only + ULONG Rsv1; // must be 0 + ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY +} RT_802_11_STA_CONFIG, *PRT_802_11_STA_CONFIG; + +// +// For OID Query or Set about BA structure +// +typedef struct _OID_BACAP_STRUC { + UCHAR RxBAWinLimit; + UCHAR TxBAWinLimit; + UCHAR Policy; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid + UCHAR MpduDensity; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid + UCHAR AmsduEnable; //Enable AMSDU transmisstion + UCHAR AmsduSize; // 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935}; + UCHAR MMPSmode; // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable + BOOLEAN AutoBA; // Auto BA will automatically +} OID_BACAP_STRUC, *POID_BACAP_STRUC; + +typedef struct _RT_802_11_ACL_ENTRY { + UCHAR Addr[MAC_ADDR_LENGTH]; + USHORT Rsv; +} RT_802_11_ACL_ENTRY, *PRT_802_11_ACL_ENTRY; + +typedef struct PACKED _RT_802_11_ACL { + ULONG Policy; // 0-disable, 1-positive list, 2-negative list + ULONG Num; + RT_802_11_ACL_ENTRY Entry[MAX_NUMBER_OF_ACL]; +} RT_802_11_ACL, *PRT_802_11_ACL; + +typedef struct _RT_802_11_WDS { + ULONG Num; + NDIS_802_11_MAC_ADDRESS Entry[24/*MAX_NUM_OF_WDS_LINK*/]; + ULONG KeyLength; + UCHAR KeyMaterial[32]; +} RT_802_11_WDS, *PRT_802_11_WDS; + +typedef struct _RT_802_11_TX_RATES_ { + UCHAR SupRateLen; + UCHAR SupRate[MAX_LENGTH_OF_SUPPORT_RATES]; + UCHAR ExtRateLen; + UCHAR ExtRate[MAX_LENGTH_OF_SUPPORT_RATES]; +} RT_802_11_TX_RATES, *PRT_802_11_TX_RATES; + + +// Definition of extra information code +#define GENERAL_LINK_UP 0x0 // Link is Up +#define GENERAL_LINK_DOWN 0x1 // Link is Down +#define HW_RADIO_OFF 0x2 // Hardware radio off +#define SW_RADIO_OFF 0x3 // Software radio off +#define AUTH_FAIL 0x4 // Open authentication fail +#define AUTH_FAIL_KEYS 0x5 // Shared authentication fail +#define ASSOC_FAIL 0x6 // Association failed +#define EAP_MIC_FAILURE 0x7 // Deauthencation because MIC failure +#define EAP_4WAY_TIMEOUT 0x8 // Deauthencation on 4-way handshake timeout +#define EAP_GROUP_KEY_TIMEOUT 0x9 // Deauthencation on group key handshake timeout +#define EAP_SUCCESS 0xa // EAP succeed +#define DETECT_RADAR_SIGNAL 0xb // Radar signal occur in current channel +#define EXTRA_INFO_MAX 0xb // Indicate Last OID + +#define EXTRA_INFO_CLEAR 0xffffffff + +// This is OID setting structure. So only GF or MM as Mode. This is valid when our wirelss mode has 802.11n in use. +typedef struct { + RT_802_11_PHY_MODE PhyMode; // + UCHAR TransmitNo; + UCHAR HtMode; //HTMODE_GF or HTMODE_MM + UCHAR ExtOffset; //extension channel above or below + UCHAR MCS; + UCHAR BW; + UCHAR STBC; + UCHAR SHORTGI; + UCHAR rsv; +} OID_SET_HT_PHYMODE, *POID_SET_HT_PHYMODE; + +#ifdef NINTENDO_AP +#define NINTENDO_MAX_ENTRY 16 +#define NINTENDO_SSID_NAME_LN 8 +#define NINTENDO_SSID_NAME "NWCUSBAP" +#define NINTENDO_PROBE_REQ_FLAG_MASK 0x03 +#define NINTENDO_PROBE_REQ_ON 0x01 +#define NINTENDO_PROBE_REQ_SIGNAL 0x02 +#define NINTENDO_PROBE_RSP_ON 0x01 +#define NINTENDO_SSID_NICKNAME_LN 20 + +#define NINTENDO_WEPKEY_LN 13 + +typedef struct _NINTENDO_SSID +{ + UCHAR NINTENDOFixChar[NINTENDO_SSID_NAME_LN]; + UCHAR zero1; + UCHAR registe; + UCHAR ID; + UCHAR zero2; + UCHAR NICKname[NINTENDO_SSID_NICKNAME_LN]; +} RT_NINTENDO_SSID, *PRT_NINTENDO_SSID; + +typedef struct _NINTENDO_ENTRY +{ + UCHAR NICKname[NINTENDO_SSID_NICKNAME_LN]; + UCHAR DS_Addr[ETH_LENGTH_OF_ADDRESS]; + UCHAR registe; + UCHAR UserSpaceAck; +} RT_NINTENDO_ENTRY, *PRT_NINTENDO_ENTRY; + +//RTPRIV_IOCTL_NINTENDO_GET_TABLE +//RTPRIV_IOCTL_NINTENDO_SET_TABLE +typedef struct _NINTENDO_TABLE +{ + UINT number; + RT_NINTENDO_ENTRY entry[NINTENDO_MAX_ENTRY]; +} RT_NINTENDO_TABLE, *PRT_NINTENDO_TABLE; + +//RTPRIV_IOCTL_NINTENDO_SEED_WEPKEY +typedef struct _NINTENDO_SEED_WEPKEY +{ + UCHAR seed[NINTENDO_SSID_NICKNAME_LN]; + UCHAR wepkey[16];//use 13 for 104 bits wep key +} RT_NINTENDO_SEED_WEPKEY, *PRT_NINTENDO_SEED_WEPKEY; +#endif // NINTENDO_AP // + +#ifdef LLTD_SUPPORT +typedef struct _RT_LLTD_ASSOICATION_ENTRY { + UCHAR Addr[ETH_LENGTH_OF_ADDRESS]; + unsigned short MOR; // maximum operational rate + UCHAR phyMode; +} RT_LLTD_ASSOICATION_ENTRY, *PRT_LLTD_ASSOICATION_ENTRY; + +typedef struct _RT_LLTD_ASSOICATION_TABLE { + unsigned int Num; + RT_LLTD_ASSOICATION_ENTRY Entry[MAX_NUMBER_OF_MAC]; +} RT_LLTD_ASSOICATION_TABLE, *PRT_LLTD_ASSOICATION_TABLE; +#endif // LLTD_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +//rt2860, kathy 2007-0118 +// structure for DLS +typedef struct _RT_802_11_DLS_UI { + USHORT TimeOut; // unit: second , set by UI + USHORT CountDownTimer; // unit: second , used by driver only + NDIS_802_11_MAC_ADDRESS MacAddr; // set by UI + UCHAR Status; // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only + BOOLEAN Valid; // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link +} RT_802_11_DLS_UI, *PRT_802_11_DLS_UI; + +typedef struct _RT_802_11_DLS_INFO { + RT_802_11_DLS_UI Entry[MAX_NUMBER_OF_DLS_ENTRY]; + UCHAR num; +} RT_802_11_DLS_INFO, *PRT_802_11_DLS_INFO; + +typedef enum _RT_802_11_DLS_MODE { + DLS_NONE, + DLS_WAIT_KEY, + DLS_FINISH +} RT_802_11_DLS_MODE; +#endif // QOS_DLS_SUPPORT // + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT +#define RT_ASSOC_EVENT_FLAG 0x0101 +#define RT_DISASSOC_EVENT_FLAG 0x0102 +#define RT_REQIE_EVENT_FLAG 0x0103 +#define RT_RESPIE_EVENT_FLAG 0x0104 +#define RT_ASSOCINFO_EVENT_FLAG 0x0105 +#define RT_PMKIDCAND_FLAG 0x0106 +#define RT_INTERFACE_DOWN 0x0107 +#define RT_INTERFACE_UP 0x0108 +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + + +#define MAX_CUSTOM_LEN 128 + +#ifdef CONFIG_STA_SUPPORT +typedef enum _RT_802_11_D_CLIENT_MODE +{ + Rt802_11_D_None, + Rt802_11_D_Flexible, + Rt802_11_D_Strict, +} RT_802_11_D_CLIENT_MODE, *PRT_802_11_D_CLIENT_MODE; +#endif // CONFIG_STA_SUPPORT // + +typedef struct _RT_CHANNEL_LIST_INFO +{ + UCHAR ChannelList[MAX_NUM_OF_CHS]; // list all supported channels for site survey + UCHAR ChannelListNum; // number of channel in ChannelList[] +} RT_CHANNEL_LIST_INFO, *PRT_CHANNEL_LIST_INFO; + +// WSC configured credential +typedef struct _WSC_CREDENTIAL +{ + NDIS_802_11_SSID SSID; // mandatory + USHORT AuthType; // mandatory, 1: open, 2: wpa-psk, 4: shared, 8:wpa, 0x10: wpa2, 0x20: wpa2-psk + USHORT EncrType; // mandatory, 1: none, 2: wep, 4: tkip, 8: aes + UCHAR Key[64]; // mandatory, Maximum 64 byte + USHORT KeyLength; + UCHAR MacAddr[6]; // mandatory, AP MAC address + UCHAR KeyIndex; // optional, default is 1 + UCHAR Rsvd[3]; // Make alignment +} WSC_CREDENTIAL, *PWSC_CREDENTIAL; + +// WSC configured profiles +typedef struct _WSC_PROFILE +{ + UINT ProfileCnt; + WSC_CREDENTIAL Profile[8]; // Support up to 8 profiles +} WSC_PROFILE, *PWSC_PROFILE; + + + +#endif // _OID_H_ + diff --git a/drivers/staging/rt3070/rt2870.h b/drivers/staging/rt3070/rt2870.h new file mode 100644 index 000000000000..d32a2bf1d040 --- /dev/null +++ b/drivers/staging/rt3070/rt2870.h @@ -0,0 +1,756 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + */ + +#ifndef __RT2870_H__ +#define __RT2870_H__ + +//usb header files +#include + +/* rtmp_def.h */ +// +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define BULKAGGRE_ZISE 100 +#define RT28XX_DRVDATA_SET(_a) usb_set_intfdata(_a, pAd); +#define RT28XX_PUT_DEVICE usb_put_dev +#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso, GFP_ATOMIC) +#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb, GFP_ATOMIC) +#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) usb_buffer_alloc(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr) +#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) usb_buffer_free(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) +#else +#define BULKAGGRE_ZISE 60 +#define RT28XX_DRVDATA_SET(_a) +#define RT28XX_PUT_DEVICE(dev_p) +#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso) +#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb) +#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) kmalloc(BufSize, GFP_ATOMIC) +#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) kfree(pTransferBuf) +#endif + +#define RXBULKAGGRE_ZISE 12 +#define MAX_TXBULK_LIMIT (LOCAL_TXBUF_SIZE*(BULKAGGRE_ZISE-1)) +#define MAX_TXBULK_SIZE (LOCAL_TXBUF_SIZE*BULKAGGRE_ZISE) +#define MAX_RXBULK_SIZE (LOCAL_TXBUF_SIZE*RXBULKAGGRE_ZISE) +#define MAX_MLME_HANDLER_MEMORY 20 +#define BUFFER_SIZE 2400 //2048 +#define TX_RING 0xa +#define PRIO_RING 0xc + + +// Flags for Bulkflags control for bulk out data +// +#define fRTUSB_BULK_OUT_DATA_NULL 0x00000001 +#define fRTUSB_BULK_OUT_RTS 0x00000002 +#define fRTUSB_BULK_OUT_MLME 0x00000004 + +#define fRTUSB_BULK_OUT_DATA_NORMAL 0x00010000 +#define fRTUSB_BULK_OUT_DATA_NORMAL_2 0x00020000 +#define fRTUSB_BULK_OUT_DATA_NORMAL_3 0x00040000 +#define fRTUSB_BULK_OUT_DATA_NORMAL_4 0x00080000 +#define fRTUSB_BULK_OUT_DATA_NORMAL_5 0x00100000 + +#define fRTUSB_BULK_OUT_PSPOLL 0x00000020 +#define fRTUSB_BULK_OUT_DATA_FRAG 0x00000040 +#define fRTUSB_BULK_OUT_DATA_FRAG_2 0x00000080 +#define fRTUSB_BULK_OUT_DATA_FRAG_3 0x00000100 +#define fRTUSB_BULK_OUT_DATA_FRAG_4 0x00000200 + +#ifdef RALINK_ATE +#define fRTUSB_BULK_OUT_DATA_ATE 0x00100000 +#endif // RALINK_ATE // + +#define RT2870_USB_DEVICES \ +{ \ + {USB_DEVICE(0x148F,0x2770)}, /* Ralink */ \ + {USB_DEVICE(0x148F,0x2870)}, /* Ralink */ \ + {USB_DEVICE(0x148F,0x3070)}, /* Ralink 3070 */ \ + {USB_DEVICE(0x148F,0x3071)}, /* Ralink 3071 */ \ + {USB_DEVICE(0x148F,0x3072)}, /* Ralink 3072 */ \ + {USB_DEVICE(0x0B05,0x1731)}, /* Asus */ \ + {USB_DEVICE(0x0B05,0x1732)}, /* Asus */ \ + {USB_DEVICE(0x0B05,0x1742)}, /* Asus */ \ + {USB_DEVICE(0x0DF6,0x0017)}, /* Sitecom */ \ + {USB_DEVICE(0x0DF6,0x002B)}, /* Sitecom */ \ + {USB_DEVICE(0x0DF6,0x002C)}, /* Sitecom */ \ + {USB_DEVICE(0x0DF6,0x003E)}, /* Sitecom 3070 */ \ + {USB_DEVICE(0x0DF6,0x002D)}, /* Sitecom */ \ + {USB_DEVICE(0x0DF6,0x0039)}, /* Sitecom 2770 */ \ + {USB_DEVICE(0x14B2,0x3C06)}, /* Conceptronic */ \ + {USB_DEVICE(0x14B2,0x3C28)}, /* Conceptronic */ \ + {USB_DEVICE(0x2019,0xED06)}, /* Planex Communications, Inc. */ \ + {USB_DEVICE(0x2019,0xAB25)}, /* Planex Communications, Inc. RT3070 */ \ + {USB_DEVICE(0x07D1,0x3C09)}, /* D-Link */ \ + {USB_DEVICE(0x07D1,0x3C11)}, /* D-Link */ \ + {USB_DEVICE(0x2001,0x3C09)}, /* D-Link */ \ + {USB_DEVICE(0x2001,0x3C0A)}, /* D-Link 3072*/ \ + {USB_DEVICE(0x14B2,0x3C07)}, /* AL */ \ + {USB_DEVICE(0x14B2,0x3C12)}, /* AL 3070 */ \ + {USB_DEVICE(0x050D,0x8053)}, /* Belkin */ \ + {USB_DEVICE(0x14B2,0x3C23)}, /* Airlink */ \ + {USB_DEVICE(0x14B2,0x3C27)}, /* Airlink */ \ + {USB_DEVICE(0x07AA,0x002F)}, /* Corega */ \ + {USB_DEVICE(0x07AA,0x003C)}, /* Corega */ \ + {USB_DEVICE(0x07AA,0x003F)}, /* Corega */ \ + {USB_DEVICE(0x18C5,0x0012)}, /* Corega 3070 */ \ + {USB_DEVICE(0x1044,0x800B)}, /* Gigabyte */ \ + {USB_DEVICE(0x1044,0x800D)}, /* Gigabyte GN-WB32L 3070 */ \ + {USB_DEVICE(0x15A9,0x0006)}, /* Sparklan */ \ + {USB_DEVICE(0x083A,0xB522)}, /* SMC */ \ + {USB_DEVICE(0x083A,0xA618)}, /* SMC */ \ + {USB_DEVICE(0x083A,0x8522)}, /* Arcadyan */ \ + {USB_DEVICE(0x083A,0x7512)}, /* Arcadyan 2770 */ \ + {USB_DEVICE(0x083A,0x7522)}, /* Arcadyan */ \ + {USB_DEVICE(0x083A,0x7511)}, /* Arcadyan 3070 */ \ + {USB_DEVICE(0x0CDE,0x0022)}, /* ZCOM */ \ + {USB_DEVICE(0x0586,0x3416)}, /* Zyxel */ \ + {USB_DEVICE(0x0CDE,0x0025)}, /* Zyxel */ \ + {USB_DEVICE(0x1740,0x9701)}, /* EnGenius */ \ + {USB_DEVICE(0x1740,0x9702)}, /* EnGenius */ \ + {USB_DEVICE(0x1740,0x9703)}, /* EnGenius 3070 */ \ + {USB_DEVICE(0x0471,0x200f)}, /* Philips */ \ + {USB_DEVICE(0x14B2,0x3C25)}, /* Draytek */ \ + {USB_DEVICE(0x13D3,0x3247)}, /* AzureWave */ \ + {USB_DEVICE(0x13D3,0x3273)}, /* AzureWave 3070*/ \ + {USB_DEVICE(0x083A,0x6618)}, /* Accton */ \ + {USB_DEVICE(0x15c5,0x0008)}, /* Amit */ \ + {USB_DEVICE(0x0E66,0x0001)}, /* Hawking */ \ + {USB_DEVICE(0x0E66,0x0003)}, /* Hawking */ \ + {USB_DEVICE(0x129B,0x1828)}, /* Siemens */ \ + {USB_DEVICE(0x157E,0x300E)}, /* U-Media */ \ + {USB_DEVICE(0x050d,0x805c)}, \ + {USB_DEVICE(0x1482,0x3C09)}, /* Abocom*/ \ + {USB_DEVICE(0x14B2,0x3C09)}, /* Alpha */ \ + {USB_DEVICE(0x04E8,0x2018)}, /* samsung */ \ + {USB_DEVICE(0x07B8,0x3070)}, /* AboCom 3070 */ \ + {USB_DEVICE(0x07B8,0x3071)}, /* AboCom 3071 */ \ + {USB_DEVICE(0x07B8,0x3072)}, /* Abocom 3072 */ \ + {USB_DEVICE(0x7392,0x7711)}, /* Edimax 3070 */ \ + {USB_DEVICE(0x5A57,0x0280)}, /* Zinwell */ \ + {USB_DEVICE(0x5A57,0x0282)}, /* Zinwell */ \ + {USB_DEVICE(0x1A32,0x0304)}, /* Quanta 3070 */ \ + {USB_DEVICE(0x0789,0x0162)}, /* Logitec 2870 */ \ + {USB_DEVICE(0x0789,0x0163)}, /* Logitec 2870 */ \ + {USB_DEVICE(0x0789,0x0164)}, /* Logitec 2870 */ \ + {USB_DEVICE(0x1EDA,0x2310)}, /* AirTies 3070 */ \ + { }/* Terminating entry */ \ +} + +#define FREE_HTTX_RING(_p, _b, _t) \ +{ \ + if ((_t)->ENextBulkOutPosition == (_t)->CurWritePosition) \ + { \ + (_t)->bRingEmpty = TRUE; \ + } \ + /*NdisInterlockedDecrement(&(_p)->TxCount); */\ +} + +// +// RXINFO appends at the end of each rx packet. +// +#ifdef RT_BIG_ENDIAN +typedef struct PACKED _RXINFO_STRUC { + UINT32 PlcpSignal:12; + UINT32 LastAMSDU:1; + UINT32 CipherAlg:1; + UINT32 PlcpRssil:1; + UINT32 Decrypted:1; + UINT32 AMPDU:1; // To be moved + UINT32 L2PAD:1; + UINT32 RSSI:1; + UINT32 HTC:1; + UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header. + UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid + UINT32 Crc:1; // 1: CRC error + UINT32 MyBss:1; // 1: this frame belongs to the same BSSID + UINT32 Bcast:1; // 1: this is a broadcast frame + UINT32 Mcast:1; // 1: this is a multicast frame + UINT32 U2M:1; // 1: this RX frame is unicast to me + UINT32 FRAG:1; + UINT32 NULLDATA:1; + UINT32 DATA:1; + UINT32 BA:1; +} RXINFO_STRUC, *PRXINFO_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; +#else +typedef struct PACKED _RXINFO_STRUC { + UINT32 BA:1; + UINT32 DATA:1; + UINT32 NULLDATA:1; + UINT32 FRAG:1; + UINT32 U2M:1; // 1: this RX frame is unicast to me + UINT32 Mcast:1; // 1: this is a multicast frame + UINT32 Bcast:1; // 1: this is a broadcast frame + UINT32 MyBss:1; // 1: this frame belongs to the same BSSID + UINT32 Crc:1; // 1: CRC error + UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid + UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header. + UINT32 HTC:1; + UINT32 RSSI:1; + UINT32 L2PAD:1; + UINT32 AMPDU:1; // To be moved + UINT32 Decrypted:1; + UINT32 PlcpRssil:1; + UINT32 CipherAlg:1; + UINT32 LastAMSDU:1; + UINT32 PlcpSignal:12; +} RXINFO_STRUC, *PRXINFO_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC; +#endif + + +// +// TXINFO +// +#ifdef RT_BIG_ENDIAN +typedef struct _TXINFO_STRUC { + // Word 0 + UINT32 USBDMATxburst:1;//used ONLY in USB bulk Aggre. Force USB DMA transmit frame from current selected endpoint + UINT32 USBDMANextVLD:1; //used ONLY in USB bulk Aggregation, NextValid + UINT32 rsv2:2; // Software use. + UINT32 SwUseLastRound:1; // Software use. + UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA + UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition + UINT32 rsv:8; + UINT32 USBDMATxPktLen:16; //used ONLY in USB bulk Aggregation, Total byte counts of all sub-frame. +} TXINFO_STRUC, *PTXINFO_STRUC; +#else +typedef struct _TXINFO_STRUC { + // Word 0 + UINT32 USBDMATxPktLen:16; //used ONLY in USB bulk Aggregation, Total byte counts of all sub-frame. + UINT32 rsv:8; + UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition + UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA + UINT32 SwUseLastRound:1; // Software use. + UINT32 rsv2:2; // Software use. + UINT32 USBDMANextVLD:1; //used ONLY in USB bulk Aggregation, NextValid + UINT32 USBDMATxburst:1;//used ONLY in USB bulk Aggre. Force USB DMA transmit frame from current selected endpoint +} TXINFO_STRUC, *PTXINFO_STRUC; +#endif + +#define TXINFO_SIZE 4 +#define RXINFO_SIZE 4 +#define TXPADDING_SIZE 11 + +// +// Management ring buffer format +// +typedef struct _MGMT_STRUC { + BOOLEAN Valid; + PUCHAR pBuffer; + ULONG Length; +} MGMT_STRUC, *PMGMT_STRUC; + + +/* ----------------- EEPROM Related MACRO ----------------- */ +#ifdef RT30xx +#define RT28xx_EEPROM_READ16(pAd, offset, var) \ + do { \ + RTUSBReadEEPROM(pAd, offset, (PUCHAR)&(var), 2); \ + if(!pAd->bUseEfuse) \ + var = le2cpu16(var); \ + }while(0) + +#define RT28xx_EEPROM_WRITE16(pAd, offset, var) \ + do{ \ + USHORT _tmpVar=var; \ + if(!pAd->bUseEfuse) \ + _tmpVar = cpu2le16(var); \ + RTUSBWriteEEPROM(pAd, offset, (PUCHAR)&(_tmpVar), 2); \ + }while(0) +#endif // RT30xx // +#ifndef RT30xx +#define RT28xx_EEPROM_READ16(pAd, offset, var) \ + do { \ + RTUSBReadEEPROM(pAd, offset, (PUCHAR)&(var), 2); \ + var = le2cpu16(var); \ + }while(0) + +#define RT28xx_EEPROM_WRITE16(pAd, offset, var) \ + do{ \ + USHORT _tmpVar=var; \ + _tmpVar = cpu2le16(var); \ + RTUSBWriteEEPROM(pAd, offset, (PUCHAR)&(_tmpVar), 2); \ + }while(0) +#endif // RT30xx // + +/* ----------------- TASK/THREAD Related MACRO ----------------- */ +#define RT28XX_TASK_THREAD_INIT(pAd, Status) \ + Status = CreateThreads(net_dev); + + +/* ----------------- Frimware Related MACRO ----------------- */ +#define RT28XX_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ + RTUSBFirmwareWrite(_pAd, _pFwImage, _FwLen) + +/* ----------------- TX Related MACRO ----------------- */ +#define RT28XX_START_DEQUEUE(pAd, QueIdx, irqFlags) \ + { \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + if (pAd->DeQueueRunning[QueIdx]) \ + { \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + printk("DeQueueRunning[%d]= TRUE!\n", QueIdx); \ + continue; \ + } \ + else \ + { \ + pAd->DeQueueRunning[QueIdx] = TRUE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + } \ + } +#define RT28XX_STOP_DEQUEUE(pAd, QueIdx, irqFlags) \ + do{ \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + pAd->DeQueueRunning[QueIdx] = FALSE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + }while(0) + + +#define RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ + (RTUSBFreeDescriptorRequest(pAd, pTxBlk->QueIdx, (pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))) == NDIS_STATUS_SUCCESS) + +#define RT28XX_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ + do{}while(0) + +#define NEED_QUEUE_BACK_FOR_AGG(_pAd, _QueIdx, _freeNum, _TxFrameType) \ + ((_TxFrameType == TX_RALINK_FRAME) && (RTUSBNeedQueueBackForAgg(_pAd, _QueIdx))) + + + +#define fRTMP_ADAPTER_NEED_STOP_TX \ + (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ + fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_BULKOUT_RESET | \ + fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_REMOVE_IN_PROGRESS) + + +#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ + RtmpUSB_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ + RtmpUSB_WriteSingleTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) + +#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ + RtmpUSB_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) + +#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ + RtmpUSB_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) + +#define HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) \ + RtmpUSB_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) + +#define HAL_LastTxIdx(pAd, QueIdx,TxIdx) \ + /*RtmpUSBDataLastTxIdx(pAd, QueIdx,TxIdx)*/ + +#define HAL_KickOutTx(pAd, pTxBlk, QueIdx) \ + RtmpUSBDataKickOut(pAd, pTxBlk, QueIdx) + + +#define HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) \ + RtmpUSBMgmtKickOut(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) + +#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ + RtmpUSBNullFrameKickOut(_pAd, _QueIdx, _pNullFrame, _frameLen) + +#define RTMP_PKT_TAIL_PADDING 11 // 3(max 4 byte padding) + 4 (last packet padding) + 4 (MaxBulkOutsize align padding) + +extern UCHAR EpToQueue[6]; + + +#ifdef RT2870 +#define GET_TXRING_FREENO(_pAd, _QueIdx) (_QueIdx) //(_pAd->TxRing[_QueIdx].TxSwFreeIdx) +#define GET_MGMTRING_FREENO(_pAd) (_pAd->MgmtRing.TxSwFreeIdx) +#endif // RT2870 // + + +/* ----------------- RX Related MACRO ----------------- */ +//#define RT28XX_RX_ERROR_CHECK RTMPCheckRxWI + +#define RT28XX_RV_ALL_BUF_END(bBulkReceive) \ + /* We return STATUS_MORE_PROCESSING_REQUIRED so that the completion */ \ + /* routine (IofCompleteRequest) will stop working on the irp. */ \ + if (bBulkReceive == TRUE) RTUSBBulkReceive(pAd); + + +/* ----------------- ASIC Related MACRO ----------------- */ +// reset MAC of a station entry to 0xFFFFFFFFFFFF +#define RT28XX_STA_ENTRY_MAC_RESET(pAd, Wcid) \ + { RT_SET_ASIC_WCID SetAsicWcid; \ + SetAsicWcid.WCID = Wcid; \ + SetAsicWcid.SetTid = 0xffffffff; \ + SetAsicWcid.DeleteTid = 0xffffffff; \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_ASIC_WCID, \ + &SetAsicWcid, sizeof(RT_SET_ASIC_WCID)); } + +// add this entry into ASIC RX WCID search table +#define RT28XX_STA_ENTRY_ADD(pAd, pEntry) \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_CLIENT_MAC_ENTRY, \ + pEntry, sizeof(MAC_TABLE_ENTRY)); + +// add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet +// Set MAC register value according operation mode +#define RT28XX_UPDATE_PROTECT(pAd) \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_UPDATE_PROTECT, NULL, 0); +// end johnli + +// remove Pair-wise key material from ASIC +// yet implement +#define RT28XX_STA_ENTRY_KEY_DEL(pAd, BssIdx, Wcid) + +// add Client security information into ASIC WCID table and IVEIV table +#define RT28XX_STA_SECURITY_INFO_ADD(pAd, apidx, KeyID, pEntry) \ + { RT28XX_STA_ENTRY_MAC_RESET(pAd, pEntry->Aid); \ + if (pEntry->Aid >= 1) { \ + RT_SET_ASIC_WCID_ATTRI SetAsicWcidAttri; \ + SetAsicWcidAttri.WCID = pEntry->Aid; \ + if ((pEntry->AuthMode <= Ndis802_11AuthModeAutoSwitch) && \ + (pEntry->WepStatus == Ndis802_11Encryption1Enabled)) \ + { \ + SetAsicWcidAttri.Cipher = pAd->SharedKey[apidx][KeyID].CipherAlg; \ + } \ + else if (pEntry->AuthMode == Ndis802_11AuthModeWPANone) \ + { \ + SetAsicWcidAttri.Cipher = pAd->SharedKey[apidx][KeyID].CipherAlg; \ + } \ + else SetAsicWcidAttri.Cipher = 0; \ + DBGPRINT(RT_DEBUG_TRACE, ("aid cipher = %ld\n",SetAsicWcidAttri.Cipher)); \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_SET_ASIC_WCID_CIPHER, \ + &SetAsicWcidAttri, sizeof(RT_SET_ASIC_WCID_ATTRI)); } } + +// Insert the BA bitmap to ASIC for the Wcid entry +#define RT28XX_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID) \ + do{ \ + RT_SET_ASIC_WCID SetAsicWcid; \ + SetAsicWcid.WCID = (_Aid); \ + SetAsicWcid.SetTid = (0x10000<<(_TID)); \ + SetAsicWcid.DeleteTid = 0xffffffff; \ + RTUSBEnqueueInternalCmd((_pAd), CMDTHREAD_SET_ASIC_WCID, &SetAsicWcid, sizeof(RT_SET_ASIC_WCID)); \ + }while(0) + +// Remove the BA bitmap from ASIC for the Wcid entry +#define RT28XX_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID) \ + do{ \ + RT_SET_ASIC_WCID SetAsicWcid; \ + SetAsicWcid.WCID = (_Wcid); \ + SetAsicWcid.SetTid = (0xffffffff); \ + SetAsicWcid.DeleteTid = (0x10000<<(_TID) ); \ + RTUSBEnqueueInternalCmd((_pAd), CMDTHREAD_SET_ASIC_WCID, &SetAsicWcid, sizeof(RT_SET_ASIC_WCID)); \ + }while(0) + + +/* ----------------- PCI/USB Related MACRO ----------------- */ +#define RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p) \ + ((POS_COOKIE)handle)->pUsb_Dev = dev_p; + +// no use +#define RT28XX_UNMAP() +#define RT28XX_IRQ_REQUEST(net_dev) +#define RT28XX_IRQ_RELEASE(net_dev) +#define RT28XX_IRQ_INIT(pAd) +#define RT28XX_IRQ_ENABLE(pAd) + + +/* ----------------- MLME Related MACRO ----------------- */ +#define RT28XX_MLME_HANDLER(pAd) RTUSBMlmeUp(pAd) + +#define RT28XX_MLME_PRE_SANITY_CHECK(pAd) \ + { if ((pAd->CommonCfg.bHardwareRadio == TRUE) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { \ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_CHECK_GPIO, NULL, 0); } } + +#define RT28XX_MLME_STA_QUICK_RSP_WAKE_UP(pAd) \ + { RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_QKERIODIC_EXECUT, NULL, 0); \ + RTUSBMlmeUp(pAd); } + +#define RT28XX_MLME_RESET_STATE_MACHINE(pAd) \ + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_RESET_CONF, 0, NULL); \ + RTUSBMlmeUp(pAd); + +#define RT28XX_HANDLE_COUNTER_MEASURE(_pAd, _pEntry) \ + { RTUSBEnqueueInternalCmd(_pAd, CMDTHREAD_802_11_COUNTER_MEASURE, _pEntry, sizeof(MAC_TABLE_ENTRY)); \ + RTUSBMlmeUp(_pAd); \ + } + + +/* ----------------- Power Save Related MACRO ----------------- */ +#define RT28XX_PS_POLL_ENQUEUE(pAd) \ + { RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL); \ + RTUSBKickBulkOut(pAd); } + +#define RT28xx_CHIP_NAME "RT2870" +#define USB_CYC_CFG 0x02a4 +#define NT_SUCCESS(status) (((status) > 0) ? (1):(0)) +#define InterlockedIncrement atomic_inc +#define NdisInterlockedIncrement atomic_inc +#define InterlockedDecrement atomic_dec +#define NdisInterlockedDecrement atomic_dec +#define InterlockedExchange atomic_set +//#define NdisMSendComplete RTMP_SendComplete +#define NdisMCancelTimer RTMPCancelTimer +#define NdisAllocMemory(_ptr, _size, _flag) \ + do{_ptr = kmalloc((_size),(_flag));}while(0) +#define NdisFreeMemory(a, b, c) kfree((a)) +#define NdisMSleep RTMPusecDelay /* unit: microsecond */ + + +#define USBD_TRANSFER_DIRECTION_OUT 0 +#define USBD_TRANSFER_DIRECTION_IN 0 +#define USBD_SHORT_TRANSFER_OK 0 +#define PURB purbb_t + +#define RTUSB_FREE_URB(pUrb) usb_free_urb(pUrb) + +//#undef MlmeAllocateMemory +//#undef MlmeFreeMemory + +typedef struct usb_device * PUSB_DEV; + +/* MACRO for linux usb */ +typedef struct urb *purbb_t; +typedef struct usb_ctrlrequest devctrlrequest; +#define PIRP PVOID +#define PMDL PVOID +#define NDIS_OID UINT +#ifndef USB_ST_NOERROR +#define USB_ST_NOERROR 0 +#endif + +// vendor-specific control operations +#define CONTROL_TIMEOUT_JIFFIES ( (100 * HZ) / 1000) +#define UNLINK_TIMEOUT_MS 3 + +/* unlink urb */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) +#define RTUSB_UNLINK_URB(pUrb) usb_kill_urb(pUrb) +#else +#define RTUSB_UNLINK_URB(pUrb) usb_unlink_urb(pUrb) +#endif + +// Prototypes of completion funuc. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define RTUSBBulkOutDataPacketComplete(purb, pt_regs) RTUSBBulkOutDataPacketComplete(purb) +#define RTUSBBulkOutMLMEPacketComplete(pUrb, pt_regs) RTUSBBulkOutMLMEPacketComplete(pUrb) +#define RTUSBBulkOutNullFrameComplete(pUrb, pt_regs) RTUSBBulkOutNullFrameComplete(pUrb) +#define RTUSBBulkOutRTSFrameComplete(pUrb, pt_regs) RTUSBBulkOutRTSFrameComplete(pUrb) +#define RTUSBBulkOutPsPollComplete(pUrb, pt_regs) RTUSBBulkOutPsPollComplete(pUrb) +#define RTUSBBulkRxComplete(pUrb, pt_regs) RTUSBBulkRxComplete(pUrb) +#endif + + +VOID RTUSBBulkOutDataPacketComplete(purbb_t purb, struct pt_regs *pt_regs); +VOID RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs); +VOID RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs); +VOID RTUSBBulkOutRTSFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs); +VOID RTUSBBulkOutPsPollComplete(purbb_t pUrb, struct pt_regs *pt_regs); +VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs); + + +#define RTUSBMlmeUp(pAd) \ +{ \ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; \ + if(pObj->MLMEThr_pid>0) \ + up(&(pAd->mlme_semaphore)); \ +} + +#define RTUSBCMDUp(pAd) \ +{ \ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; \ + if(pObj->RTUSBCmdThr_pid>0) \ + up(&(pAd->RTUSBCmd_semaphore)); \ +} + + +static inline NDIS_STATUS RTMPAllocateMemory( + OUT PVOID *ptr, + IN size_t size) +{ + *ptr = kmalloc(size, GFP_ATOMIC); + if(*ptr) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_RESOURCES; +} + +/* rtmp.h */ +#define BEACON_RING_SIZE 2 +#define DEVICE_VENDOR_REQUEST_OUT 0x40 +#define DEVICE_VENDOR_REQUEST_IN 0xc0 +#define INTERFACE_VENDOR_REQUEST_OUT 0x41 +#define INTERFACE_VENDOR_REQUEST_IN 0xc1 +#define MGMTPIPEIDX 0 // EP6 is highest priority + +#define BULKOUT_MGMT_RESET_FLAG 0x80 + +#define RTUSB_SET_BULK_FLAG(_M, _F) ((_M)->BulkFlags |= (_F)) +#define RTUSB_CLEAR_BULK_FLAG(_M, _F) ((_M)->BulkFlags &= ~(_F)) +#define RTUSB_TEST_BULK_FLAG(_M, _F) (((_M)->BulkFlags & (_F)) != 0) + +#define EnqueueCmd(cmdq, cmdqelmt) \ +{ \ + if (cmdq->size == 0) \ + cmdq->head = cmdqelmt; \ + else \ + cmdq->tail->next = cmdqelmt; \ + cmdq->tail = cmdqelmt; \ + cmdqelmt->next = NULL; \ + cmdq->size++; \ +} + +typedef struct _RT_SET_ASIC_WCID { + ULONG WCID; // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based + ULONG SetTid; // time-based: seconds, packet-based: kilo-packets + ULONG DeleteTid; // time-based: seconds, packet-based: kilo-packets +} RT_SET_ASIC_WCID,*PRT_SET_ASIC_WCID; + +typedef struct _RT_SET_ASIC_WCID_ATTRI { + ULONG WCID; // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based + ULONG Cipher; // ASIC Cipher definition + UCHAR Addr[ETH_LENGTH_OF_ADDRESS]; +} RT_SET_ASIC_WCID_ATTRI,*PRT_SET_ASIC_WCID_ATTRI; + +typedef struct _MLME_MEMORY_STRUCT { + PVOID AllocVa; //Pointer to the base virtual address of the allocated memory + struct _MLME_MEMORY_STRUCT *Next; //Pointer to the next virtual address of the allocated memory +} MLME_MEMORY_STRUCT, *PMLME_MEMORY_STRUCT; + +typedef struct _MLME_MEMORY_HANDLER { + BOOLEAN MemRunning; //The flag of the Mlme memory handler's status + UINT MemoryCount; //Total nonpaged system-space memory not size + UINT InUseCount; //Nonpaged system-space memory in used counts + UINT UnUseCount; //Nonpaged system-space memory available counts + INT PendingCount; //Nonpaged system-space memory for free counts + PMLME_MEMORY_STRUCT pInUseHead; //Pointer to the first nonpaed memory not used + PMLME_MEMORY_STRUCT pInUseTail; //Pointer to the last nonpaged memory not used + PMLME_MEMORY_STRUCT pUnUseHead; //Pointer to the first nonpaged memory in used + PMLME_MEMORY_STRUCT pUnUseTail; //Pointer to the last nonpaged memory in used + PULONG MemFreePending[MAX_MLME_HANDLER_MEMORY]; //an array to keep pending free-memory's pointer (32bits) +} MLME_MEMORY_HANDLER, *PMLME_MEMORY_HANDLER; + +typedef struct _CmdQElmt { + UINT command; + PVOID buffer; + ULONG bufferlength; + BOOLEAN CmdFromNdis; + BOOLEAN SetOperation; + struct _CmdQElmt *next; +} CmdQElmt, *PCmdQElmt; + +typedef struct _CmdQ { + UINT size; + CmdQElmt *head; + CmdQElmt *tail; + UINT32 CmdQState; +}CmdQ, *PCmdQ; + +// +// For WPA SUPPLICANT: WIRELESS EXT support wireless events: v14 or newer +// +#if WIRELESS_EXT >= 14 +//#define WPA_SUPPLICANT_SUPPORT 1 +#endif + +/* oid.h */ +// Cipher suite type for mixed mode group cipher, P802.11i-2004 +typedef enum _RT_802_11_CIPHER_SUITE_TYPE { + Cipher_Type_NONE, + Cipher_Type_WEP40, + Cipher_Type_TKIP, + Cipher_Type_RSVD, + Cipher_Type_CCMP, + Cipher_Type_WEP104 +} RT_802_11_CIPHER_SUITE_TYPE, *PRT_802_11_CIPHER_SUITE_TYPE; + +//CMDTHREAD_MULTI_READ_MAC +//CMDTHREAD_MULTI_WRITE_MAC +//CMDTHREAD_VENDOR_EEPROM_READ +//CMDTHREAD_VENDOR_EEPROM_WRITE +typedef struct _CMDHandler_TLV { + USHORT Offset; + USHORT Length; + UCHAR DataFirst; +} CMDHandler_TLV, *PCMDHandler_TLV; + +// New for MeetingHouse Api support +#define CMDTHREAD_VENDOR_RESET 0x0D730101 // cmd +#define CMDTHREAD_VENDOR_UNPLUG 0x0D730102 // cmd +#define CMDTHREAD_VENDOR_SWITCH_FUNCTION 0x0D730103 // cmd +#define CMDTHREAD_MULTI_WRITE_MAC 0x0D730107 // cmd +#define CMDTHREAD_MULTI_READ_MAC 0x0D730108 // cmd +#define CMDTHREAD_VENDOR_EEPROM_WRITE 0x0D73010A // cmd +#define CMDTHREAD_VENDOR_EEPROM_READ 0x0D73010B // cmd +#define CMDTHREAD_VENDOR_ENTER_TESTMODE 0x0D73010C // cmd +#define CMDTHREAD_VENDOR_EXIT_TESTMODE 0x0D73010D // cmd +#define CMDTHREAD_VENDOR_WRITE_BBP 0x0D730119 // cmd +#define CMDTHREAD_VENDOR_READ_BBP 0x0D730118 // cmd +#define CMDTHREAD_VENDOR_WRITE_RF 0x0D73011A // cmd +#define CMDTHREAD_VENDOR_FLIP_IQ 0x0D73011D // cmd +#define CMDTHREAD_RESET_BULK_OUT 0x0D730210 // cmd +#define CMDTHREAD_RESET_BULK_IN 0x0D730211 // cmd +#define CMDTHREAD_SET_PSM_BIT_SAVE 0x0D730212 // cmd +#define CMDTHREAD_SET_RADIO 0x0D730214 // cmd +#define CMDTHREAD_UPDATE_TX_RATE 0x0D730216 // cmd +#define CMDTHREAD_802_11_ADD_KEY_WEP 0x0D730218 // cmd +#define CMDTHREAD_RESET_FROM_ERROR 0x0D73021A // cmd +#define CMDTHREAD_LINK_DOWN 0x0D73021B // cmd +#define CMDTHREAD_RESET_FROM_NDIS 0x0D73021C // cmd +#define CMDTHREAD_CHECK_GPIO 0x0D730215 // cmd +#define CMDTHREAD_FORCE_WAKE_UP 0x0D730222 // cmd +#define CMDTHREAD_SET_BW 0x0D730225 // cmd +#define CMDTHREAD_SET_ASIC_WCID 0x0D730226 // cmd +#define CMDTHREAD_SET_ASIC_WCID_CIPHER 0x0D730227 // cmd +#define CMDTHREAD_QKERIODIC_EXECUT 0x0D73023D // cmd +#define RT_CMD_SET_KEY_TABLE 0x0D730228 // cmd +#define RT_CMD_SET_RX_WCID_TABLE 0x0D730229 // cmd +#define CMDTHREAD_SET_CLIENT_MAC_ENTRY 0x0D73023E // cmd +#define CMDTHREAD_802_11_QUERY_HARDWARE_REGISTER 0x0D710105 // cmd +#define CMDTHREAD_802_11_SET_PHY_MODE 0x0D79010C // cmd +#define CMDTHREAD_802_11_SET_STA_CONFIG 0x0D790111 // cmd +#define CMDTHREAD_802_11_SET_PREAMBLE 0x0D790101 // cmd +#define CMDTHREAD_802_11_COUNTER_MEASURE 0x0D790102 // cmd +// add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet +#define CMDTHREAD_UPDATE_PROTECT 0x0D790103 // cmd +// end johnli + +#define WPA1AKMBIT 0x01 +#define WPA2AKMBIT 0x02 +#define WPA1PSKAKMBIT 0x04 +#define WPA2PSKAKMBIT 0x08 +#define TKIPBIT 0x01 +#define CCMPBIT 0x02 + + +#define RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx) \ + RT28xxUsbStaAsicForceWakeup(pAd, bFromTx); + +#define RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp) \ + RT28xxUsbStaAsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + +#define RT28XX_MLME_RADIO_ON(pAd) \ + RT28xxUsbMlmeRadioOn(pAd); + +#define RT28XX_MLME_RADIO_OFF(pAd) \ + RT28xxUsbMlmeRadioOFF(pAd); + +#endif //__RT2870_H__ diff --git a/drivers/staging/rt3070/rt28xx.h b/drivers/staging/rt3070/rt28xx.h new file mode 100644 index 000000000000..b637c4ee6096 --- /dev/null +++ b/drivers/staging/rt3070/rt28xx.h @@ -0,0 +1,2725 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rt28xx.h + + Abstract: + RT28xx ASIC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee Jan-3-2006 created for RT2860c +*/ + +#ifndef __RT28XX_H__ +#define __RT28XX_H__ + + +// +// PCI registers - base address 0x0000 +// +#define PCI_CFG 0x0000 +#define PCI_EECTRL 0x0004 +#define PCI_MCUCTRL 0x0008 + +#define OPT_14 0x114 + +typedef int NTSTATUS; +#define RETRY_LIMIT 10 +#define STATUS_SUCCESS 0x00 +#define STATUS_UNSUCCESSFUL 0x01 + +// +// SCH/DMA registers - base address 0x0200 +// +// INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit +// +#define DMA_CSR0 0x200 +#define INT_SOURCE_CSR 0x200 +#ifdef RT_BIG_ENDIAN +typedef union _INT_SOURCE_CSR_STRUC { + struct { + UINT32 :14; + UINT32 TxCoherent:1; + UINT32 RxCoherent:1; + UINT32 GPTimer:1; + UINT32 AutoWakeup:1;//bit14 + UINT32 TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c + UINT32 PreTBTT:1; + UINT32 TBTTInt:1; + UINT32 RxTxCoherent:1; + UINT32 MCUCommandINT:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 RxDone:1; + UINT32 TxDelayINT:1; //delayed interrupt, not interrupt until several int or time limit hit + UINT32 RxDelayINT:1; //dealyed interrupt + } field; + UINT32 word; +} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC; +#else +typedef union _INT_SOURCE_CSR_STRUC { + struct { + UINT32 RxDelayINT:1; + UINT32 TxDelayINT:1; + UINT32 RxDone:1; + UINT32 Ac0DmaDone:1;//4 + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; // bit7 + UINT32 MgmtDmaDone:1; + UINT32 MCUCommandINT:1;//bit 9 + UINT32 RxTxCoherent:1; + UINT32 TBTTInt:1; + UINT32 PreTBTT:1; + UINT32 TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c + UINT32 AutoWakeup:1;//bit14 + UINT32 GPTimer:1; + UINT32 RxCoherent:1;//bit16 + UINT32 TxCoherent:1; + UINT32 :14; + } field; + UINT32 word; +} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC; +#endif + +// +// INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF +// +#define INT_MASK_CSR 0x204 +#ifdef RT_BIG_ENDIAN +typedef union _INT_MASK_CSR_STRUC { + struct { + UINT32 TxCoherent:1; + UINT32 RxCoherent:1; + UINT32 :20; + UINT32 MCUCommandINT:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 RxDone:1; + UINT32 TxDelay:1; + UINT32 RXDelay_INT_MSK:1; + } field; + UINT32 word; +}INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC; +#else +typedef union _INT_MASK_CSR_STRUC { + struct { + UINT32 RXDelay_INT_MSK:1; + UINT32 TxDelay:1; + UINT32 RxDone:1; + UINT32 Ac0DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 MgmtDmaDone:1; + UINT32 MCUCommandINT:1; + UINT32 :20; + UINT32 RxCoherent:1; + UINT32 TxCoherent:1; + } field; + UINT32 word; +} INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC; +#endif +#define WPDMA_GLO_CFG 0x208 +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + UINT32 HDR_SEG_LEN:16; + UINT32 RXHdrScater:8; + UINT32 BigEndian:1; + UINT32 EnTXWriteBackDDONE:1; + UINT32 WPDMABurstSIZE:2; + UINT32 RxDMABusy:1; + UINT32 EnableRxDMA:1; + UINT32 TxDMABusy:1; + UINT32 EnableTxDMA:1; + } field; + UINT32 word; +}WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; +#else +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + UINT32 EnableTxDMA:1; + UINT32 TxDMABusy:1; + UINT32 EnableRxDMA:1; + UINT32 RxDMABusy:1; + UINT32 WPDMABurstSIZE:2; + UINT32 EnTXWriteBackDDONE:1; + UINT32 BigEndian:1; + UINT32 RXHdrScater:8; + UINT32 HDR_SEG_LEN:16; + } field; + UINT32 word; +} WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC; +#endif +#define WPDMA_RST_IDX 0x20c +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_RST_IDX_STRUC { + struct { + UINT32 :15; + UINT32 RST_DRX_IDX0:1; + UINT32 rsv:10; + UINT32 RST_DTX_IDX5:1; + UINT32 RST_DTX_IDX4:1; + UINT32 RST_DTX_IDX3:1; + UINT32 RST_DTX_IDX2:1; + UINT32 RST_DTX_IDX1:1; + UINT32 RST_DTX_IDX0:1; + } field; + UINT32 word; +}WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; +#else +typedef union _WPDMA_RST_IDX_STRUC { + struct { + UINT32 RST_DTX_IDX0:1; + UINT32 RST_DTX_IDX1:1; + UINT32 RST_DTX_IDX2:1; + UINT32 RST_DTX_IDX3:1; + UINT32 RST_DTX_IDX4:1; + UINT32 RST_DTX_IDX5:1; + UINT32 rsv:10; + UINT32 RST_DRX_IDX0:1; + UINT32 :15; + } field; + UINT32 word; +} WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC; +#endif +#define DELAY_INT_CFG 0x0210 +#ifdef RT_BIG_ENDIAN +typedef union _DELAY_INT_CFG_STRUC { + struct { + UINT32 TXDLY_INT_EN:1; + UINT32 TXMAX_PINT:7; + UINT32 TXMAX_PTIME:8; + UINT32 RXDLY_INT_EN:1; + UINT32 RXMAX_PINT:7; + UINT32 RXMAX_PTIME:8; + } field; + UINT32 word; +}DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; +#else +typedef union _DELAY_INT_CFG_STRUC { + struct { + UINT32 RXMAX_PTIME:8; + UINT32 RXMAX_PINT:7; + UINT32 RXDLY_INT_EN:1; + UINT32 TXMAX_PTIME:8; + UINT32 TXMAX_PINT:7; + UINT32 TXDLY_INT_EN:1; + } field; + UINT32 word; +} DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC; +#endif +#define WMM_AIFSN_CFG 0x0214 +#ifdef RT_BIG_ENDIAN +typedef union _AIFSN_CSR_STRUC { + struct { + UINT32 Rsv:16; + UINT32 Aifsn3:4; // for AC_VO + UINT32 Aifsn2:4; // for AC_VI + UINT32 Aifsn1:4; // for AC_BK + UINT32 Aifsn0:4; // for AC_BE + } field; + UINT32 word; +} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC; +#else +typedef union _AIFSN_CSR_STRUC { + struct { + UINT32 Aifsn0:4; // for AC_BE + UINT32 Aifsn1:4; // for AC_BK + UINT32 Aifsn2:4; // for AC_VI + UINT32 Aifsn3:4; // for AC_VO + UINT32 Rsv:16; + } field; + UINT32 word; +} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC; +#endif +// +// CWMIN_CSR: CWmin for each EDCA AC +// +#define WMM_CWMIN_CFG 0x0218 +#ifdef RT_BIG_ENDIAN +typedef union _CWMIN_CSR_STRUC { + struct { + UINT32 Rsv:16; + UINT32 Cwmin3:4; // for AC_VO + UINT32 Cwmin2:4; // for AC_VI + UINT32 Cwmin1:4; // for AC_BK + UINT32 Cwmin0:4; // for AC_BE + } field; + UINT32 word; +} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC; +#else +typedef union _CWMIN_CSR_STRUC { + struct { + UINT32 Cwmin0:4; // for AC_BE + UINT32 Cwmin1:4; // for AC_BK + UINT32 Cwmin2:4; // for AC_VI + UINT32 Cwmin3:4; // for AC_VO + UINT32 Rsv:16; + } field; + UINT32 word; +} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC; +#endif + +// +// CWMAX_CSR: CWmin for each EDCA AC +// +#define WMM_CWMAX_CFG 0x021c +#ifdef RT_BIG_ENDIAN +typedef union _CWMAX_CSR_STRUC { + struct { + UINT32 Rsv:16; + UINT32 Cwmax3:4; // for AC_VO + UINT32 Cwmax2:4; // for AC_VI + UINT32 Cwmax1:4; // for AC_BK + UINT32 Cwmax0:4; // for AC_BE + } field; + UINT32 word; +} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC; +#else +typedef union _CWMAX_CSR_STRUC { + struct { + UINT32 Cwmax0:4; // for AC_BE + UINT32 Cwmax1:4; // for AC_BK + UINT32 Cwmax2:4; // for AC_VI + UINT32 Cwmax3:4; // for AC_VO + UINT32 Rsv:16; + } field; + UINT32 word; +} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC; +#endif + + +// +// AC_TXOP_CSR0: AC_BK/AC_BE TXOP register +// +#define WMM_TXOP0_CFG 0x0220 +#ifdef RT_BIG_ENDIAN +typedef union _AC_TXOP_CSR0_STRUC { + struct { + USHORT Ac1Txop; // for AC_BE, in unit of 32us + USHORT Ac0Txop; // for AC_BK, in unit of 32us + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC; +#else +typedef union _AC_TXOP_CSR0_STRUC { + struct { + USHORT Ac0Txop; // for AC_BK, in unit of 32us + USHORT Ac1Txop; // for AC_BE, in unit of 32us + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC; +#endif + +// +// AC_TXOP_CSR1: AC_VO/AC_VI TXOP register +// +#define WMM_TXOP1_CFG 0x0224 +#ifdef RT_BIG_ENDIAN +typedef union _AC_TXOP_CSR1_STRUC { + struct { + USHORT Ac3Txop; // for AC_VO, in unit of 32us + USHORT Ac2Txop; // for AC_VI, in unit of 32us + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; +#else +typedef union _AC_TXOP_CSR1_STRUC { + struct { + USHORT Ac2Txop; // for AC_VI, in unit of 32us + USHORT Ac3Txop; // for AC_VO, in unit of 32us + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC; +#endif +#define RINGREG_DIFF 0x10 +#define GPIO_CTRL_CFG 0x0228 //MAC_CSR13 +#define MCU_CMD_CFG 0x022c +#define TX_BASE_PTR0 0x0230 //AC_BK base address +#define TX_MAX_CNT0 0x0234 +#define TX_CTX_IDX0 0x0238 +#define TX_DTX_IDX0 0x023c +#define TX_BASE_PTR1 0x0240 //AC_BE base address +#define TX_MAX_CNT1 0x0244 +#define TX_CTX_IDX1 0x0248 +#define TX_DTX_IDX1 0x024c +#define TX_BASE_PTR2 0x0250 //AC_VI base address +#define TX_MAX_CNT2 0x0254 +#define TX_CTX_IDX2 0x0258 +#define TX_DTX_IDX2 0x025c +#define TX_BASE_PTR3 0x0260 //AC_VO base address +#define TX_MAX_CNT3 0x0264 +#define TX_CTX_IDX3 0x0268 +#define TX_DTX_IDX3 0x026c +#define TX_BASE_PTR4 0x0270 //HCCA base address +#define TX_MAX_CNT4 0x0274 +#define TX_CTX_IDX4 0x0278 +#define TX_DTX_IDX4 0x027c +#define TX_BASE_PTR5 0x0280 //MGMT base address +#define TX_MAX_CNT5 0x0284 +#define TX_CTX_IDX5 0x0288 +#define TX_DTX_IDX5 0x028c +#define TX_MGMTMAX_CNT TX_MAX_CNT5 +#define TX_MGMTCTX_IDX TX_CTX_IDX5 +#define TX_MGMTDTX_IDX TX_DTX_IDX5 +#define RX_BASE_PTR 0x0290 //RX base address +#define RX_MAX_CNT 0x0294 +#define RX_CRX_IDX 0x0298 +#define RX_DRX_IDX 0x029c +#define USB_DMA_CFG 0x02a0 +#ifdef RT_BIG_ENDIAN +typedef union _USB_DMA_CFG_STRUC { + struct { + UINT32 TxBusy:1; //USB DMA TX FSM busy . debug only + UINT32 RxBusy:1; //USB DMA RX FSM busy . debug only + UINT32 EpoutValid:6; //OUT endpoint data valid. debug only + UINT32 TxBulkEn:1; //Enable USB DMA Tx + UINT32 RxBulkEn:1; //Enable USB DMA Rx + UINT32 RxBulkAggEn:1; //Enable Rx Bulk Aggregation + UINT32 TxopHalt:1; //Halt TXOP count down when TX buffer is full. + UINT32 TxClear:1; //Clear USB DMA TX path + UINT32 rsv:2; + UINT32 phyclear:1; //phy watch dog enable. write 1 + UINT32 RxBulkAggLmt:8; //Rx Bulk Aggregation Limit in unit of 1024 bytes + UINT32 RxBulkAggTOut:8; //Rx Bulk Aggregation TimeOut in unit of 33ns + } field; + UINT32 word; +} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; +#else +typedef union _USB_DMA_CFG_STRUC { + struct { + UINT32 RxBulkAggTOut:8; //Rx Bulk Aggregation TimeOut in unit of 33ns + UINT32 RxBulkAggLmt:8; //Rx Bulk Aggregation Limit in unit of 256 bytes + UINT32 phyclear:1; //phy watch dog enable. write 1 + UINT32 rsv:2; + UINT32 TxClear:1; //Clear USB DMA TX path + UINT32 TxopHalt:1; //Halt TXOP count down when TX buffer is full. + UINT32 RxBulkAggEn:1; //Enable Rx Bulk Aggregation + UINT32 RxBulkEn:1; //Enable USB DMA Rx + UINT32 TxBulkEn:1; //Enable USB DMA Tx + UINT32 EpoutValid:6; //OUT endpoint data valid + UINT32 RxBusy:1; //USB DMA RX FSM busy + UINT32 TxBusy:1; //USB DMA TX FSM busy + } field; + UINT32 word; +} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC; +#endif + +// +// 3 PBF registers +// +// +// Most are for debug. Driver doesn't touch PBF register. +#define PBF_SYS_CTRL 0x0400 +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040C +#define PBF_CTRL 0x0410 +#define PBF_INT_STA 0x0414 +#define PBF_INT_ENA 0x0418 +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c +#define PBF_CAP_CTRL 0x0440 + + +// eFuse registers +#define EFUSE_CTRL 0x0580 +#define EFUSE_DATA0 0x0590 +#define EFUSE_DATA1 0x0594 +#define EFUSE_DATA2 0x0598 +#define EFUSE_DATA3 0x059c +#define EFUSE_USAGE_MAP_START 0x2d0 +#define EFUSE_USAGE_MAP_END 0x2fc +#define EFUSE_TAG 0x2fe +#define EFUSE_USAGE_MAP_SIZE 45 + +#ifdef RT_BIG_ENDIAN +typedef union _EFUSE_CTRL_STRUC { + struct { + UINT32 SEL_EFUSE:1; + UINT32 EFSROM_KICK:1; + UINT32 RESERVED:4; + UINT32 EFSROM_AIN:10; + UINT32 EFSROM_LDO_ON_TIME:2; + UINT32 EFSROM_LDO_OFF_TIME:6; + UINT32 EFSROM_MODE:2; + UINT32 EFSROM_AOUT:6; + } field; + UINT32 word; +} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; +#else +typedef union _EFUSE_CTRL_STRUC { + struct { + UINT32 EFSROM_AOUT:6; + UINT32 EFSROM_MODE:2; + UINT32 EFSROM_LDO_OFF_TIME:6; + UINT32 EFSROM_LDO_ON_TIME:2; + UINT32 EFSROM_AIN:10; + UINT32 RESERVED:4; + UINT32 EFSROM_KICK:1; + UINT32 SEL_EFUSE:1; + } field; + UINT32 word; +} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; +#endif // RT_BIG_ENDIAN // + +#define LDO_CFG0 0x05d4 +#define GPIO_SWITCH 0x05dc + +// +// 4 MAC registers +// +// +// 4.1 MAC SYSTEM configuration registers (offset:0x1000) +// +#define MAC_CSR0 0x1000 +#ifdef RT_BIG_ENDIAN +typedef union _ASIC_VER_ID_STRUC { + struct { + USHORT ASICVer; // version : 2860 + USHORT ASICRev; // reversion : 0 + } field; + UINT32 word; +} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; +#else +typedef union _ASIC_VER_ID_STRUC { + struct { + USHORT ASICRev; // reversion : 0 + USHORT ASICVer; // version : 2860 + } field; + UINT32 word; +} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC; +#endif +#define MAC_SYS_CTRL 0x1004 //MAC_CSR1 +#define MAC_ADDR_DW0 0x1008 // MAC ADDR DW0 +#define MAC_ADDR_DW1 0x100c // MAC ADDR DW1 +// +// MAC_CSR2: STA MAC register 0 +// +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW0_STRUC { + struct { + UCHAR Byte3; // MAC address byte 3 + UCHAR Byte2; // MAC address byte 2 + UCHAR Byte1; // MAC address byte 1 + UCHAR Byte0; // MAC address byte 0 + } field; + UINT32 word; +} MAC_DW0_STRUC, *PMAC_DW0_STRUC; +#else +typedef union _MAC_DW0_STRUC { + struct { + UCHAR Byte0; // MAC address byte 0 + UCHAR Byte1; // MAC address byte 1 + UCHAR Byte2; // MAC address byte 2 + UCHAR Byte3; // MAC address byte 3 + } field; + UINT32 word; +} MAC_DW0_STRUC, *PMAC_DW0_STRUC; +#endif + +// +// MAC_CSR3: STA MAC register 1 +// +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW1_STRUC { + struct { + UCHAR Rsvd1; + UCHAR U2MeMask; + UCHAR Byte5; // MAC address byte 5 + UCHAR Byte4; // MAC address byte 4 + } field; + UINT32 word; +} MAC_DW1_STRUC, *PMAC_DW1_STRUC; +#else +typedef union _MAC_DW1_STRUC { + struct { + UCHAR Byte4; // MAC address byte 4 + UCHAR Byte5; // MAC address byte 5 + UCHAR U2MeMask; + UCHAR Rsvd1; + } field; + UINT32 word; +} MAC_DW1_STRUC, *PMAC_DW1_STRUC; +#endif + +#define MAC_BSSID_DW0 0x1010 // MAC BSSID DW0 +#define MAC_BSSID_DW1 0x1014 // MAC BSSID DW1 + +// +// MAC_CSR5: BSSID register 1 +// +#ifdef RT_BIG_ENDIAN +typedef union _MAC_CSR5_STRUC { + struct { + USHORT Rsvd:11; + USHORT MBssBcnNum:3; + USHORT BssIdMode:2; // 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID + UCHAR Byte5; // BSSID byte 5 + UCHAR Byte4; // BSSID byte 4 + } field; + UINT32 word; +} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; +#else +typedef union _MAC_CSR5_STRUC { + struct { + UCHAR Byte4; // BSSID byte 4 + UCHAR Byte5; // BSSID byte 5 + USHORT BssIdMask:2; // 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID + USHORT MBssBcnNum:3; + USHORT Rsvd:11; + } field; + UINT32 word; +} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC; +#endif + +#define MAX_LEN_CFG 0x1018 // rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 +#define BBP_CSR_CFG 0x101c // +// +// BBP_CSR_CFG: BBP serial control register +// +#ifdef RT_BIG_ENDIAN +typedef union _BBP_CSR_CFG_STRUC { + struct { + UINT32 :12; + UINT32 BBP_RW_MODE:1; // 0: use serial mode 1:parallel + UINT32 BBP_PAR_DUR:1; // 0: 4 MAC clock cycles 1: 8 MAC clock cycles + UINT32 Busy:1; // 1: ASIC is busy execute BBP programming. + UINT32 fRead:1; // 0: Write BBP, 1: Read BBP + UINT32 RegNum:8; // Selected BBP register + UINT32 Value:8; // Register value to program into BBP + } field; + UINT32 word; +} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC; +#else +typedef union _BBP_CSR_CFG_STRUC { + struct { + UINT32 Value:8; // Register value to program into BBP + UINT32 RegNum:8; // Selected BBP register + UINT32 fRead:1; // 0: Write BBP, 1: Read BBP + UINT32 Busy:1; // 1: ASIC is busy execute BBP programming. + UINT32 BBP_PAR_DUR:1; // 0: 4 MAC clock cycles 1: 8 MAC clock cycles + UINT32 BBP_RW_MODE:1; // 0: use serial mode 1:parallel + UINT32 :12; + } field; + UINT32 word; +} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC; +#endif +#define RF_CSR_CFG0 0x1020 +// +// RF_CSR_CFG: RF control register +// +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG0_STRUC { + struct { + UINT32 Busy:1; // 0: idle 1: 8busy + UINT32 Sel:1; // 0:RF_LE0 activate 1:RF_LE1 activate + UINT32 StandbyMode:1; // 0: high when stand by 1: low when standby + UINT32 bitwidth:5; // Selected BBP register + UINT32 RegIdAndContent:24; // Register value to program into BBP + } field; + UINT32 word; +} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC; +#else +typedef union _RF_CSR_CFG0_STRUC { + struct { + UINT32 RegIdAndContent:24; // Register value to program into BBP + UINT32 bitwidth:5; // Selected BBP register + UINT32 StandbyMode:1; // 0: high when stand by 1: low when standby + UINT32 Sel:1; // 0:RF_LE0 activate 1:RF_LE1 activate + UINT32 Busy:1; // 0: idle 1: 8busy + } field; + UINT32 word; +} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC; +#endif +#define RF_CSR_CFG1 0x1024 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG1_STRUC { + struct { + UINT32 rsv:7; // 0: idle 1: 8busy + UINT32 RFGap:5; // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) + UINT32 RegIdAndContent:24; // Register value to program into BBP + } field; + UINT32 word; +} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC; +#else +typedef union _RF_CSR_CFG1_STRUC { + struct { + UINT32 RegIdAndContent:24; // Register value to program into BBP + UINT32 RFGap:5; // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) + UINT32 rsv:7; // 0: idle 1: 8busy + } field; + UINT32 word; +} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC; +#endif +#define RF_CSR_CFG2 0x1028 // +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG2_STRUC { + struct { + UINT32 rsv:8; // 0: idle 1: 8busy + UINT32 RegIdAndContent:24; // Register value to program into BBP + } field; + UINT32 word; +} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC; +#else +typedef union _RF_CSR_CFG2_STRUC { + struct { + UINT32 RegIdAndContent:24; // Register value to program into BBP + UINT32 rsv:8; // 0: idle 1: 8busy + } field; + UINT32 word; +} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC; +#endif +#define LED_CFG 0x102c // MAC_CSR14 +#ifdef RT_BIG_ENDIAN +typedef union _LED_CFG_STRUC { + struct { + UINT32 :1; + UINT32 LedPolar:1; // Led Polarity. 0: active low1: active high + UINT32 YLedMode:2; // yellow Led Mode + UINT32 GLedMode:2; // green Led Mode + UINT32 RLedMode:2; // red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on + UINT32 rsv:2; + UINT32 SlowBlinkPeriod:6; // slow blinking period. unit:1ms + UINT32 OffPeriod:8; // blinking off period unit 1ms + UINT32 OnPeriod:8; // blinking on period unit 1ms + } field; + UINT32 word; +} LED_CFG_STRUC, *PLED_CFG_STRUC; +#else +typedef union _LED_CFG_STRUC { + struct { + UINT32 OnPeriod:8; // blinking on period unit 1ms + UINT32 OffPeriod:8; // blinking off period unit 1ms + UINT32 SlowBlinkPeriod:6; // slow blinking period. unit:1ms + UINT32 rsv:2; + UINT32 RLedMode:2; // red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on + UINT32 GLedMode:2; // green Led Mode + UINT32 YLedMode:2; // yellow Led Mode + UINT32 LedPolar:1; // Led Polarity. 0: active low1: active high + UINT32 :1; + } field; + UINT32 word; +} LED_CFG_STRUC, *PLED_CFG_STRUC; +#endif +// +// 4.2 MAC TIMING configuration registers (offset:0x1100) +// +#define XIFS_TIME_CFG 0x1100 // MAC_CSR8 MAC_CSR9 +#ifdef RT_BIG_ENDIAN +typedef union _IFS_SLOT_CFG_STRUC { + struct { + UINT32 rsv:2; + UINT32 BBRxendEnable:1; // reference RXEND signal to begin XIFS defer + UINT32 EIFS:9; // unit 1us + UINT32 OfdmXifsTime:4; //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND + UINT32 OfdmSifsTime:8; // unit 1us. Applied after OFDM RX/TX + UINT32 CckmSifsTime:8; // unit 1us. Applied after CCK RX/TX + } field; + UINT32 word; +} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC; +#else +typedef union _IFS_SLOT_CFG_STRUC { + struct { + UINT32 CckmSifsTime:8; // unit 1us. Applied after CCK RX/TX + UINT32 OfdmSifsTime:8; // unit 1us. Applied after OFDM RX/TX + UINT32 OfdmXifsTime:4; //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND + UINT32 EIFS:9; // unit 1us + UINT32 BBRxendEnable:1; // reference RXEND signal to begin XIFS defer + UINT32 rsv:2; + } field; + UINT32 word; +} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC; +#endif + +#define BKOFF_SLOT_CFG 0x1104 // mac_csr9 last 8 bits +#define NAV_TIME_CFG 0x1108 // NAV (MAC_CSR15) +#define CH_TIME_CFG 0x110C // Count as channel busy +#define PBF_LIFE_TIMER 0x1110 //TX/RX MPDU timestamp timer (free run)Unit: 1us +#define BCN_TIME_CFG 0x1114 // TXRX_CSR9 + +#define BCN_OFFSET0 0x042C +#define BCN_OFFSET1 0x0430 + +// +// BCN_TIME_CFG : Synchronization control register +// +#ifdef RT_BIG_ENDIAN +typedef union _BCN_TIME_CFG_STRUC { + struct { + UINT32 TxTimestampCompensate:8; + UINT32 :3; + UINT32 bBeaconGen:1; // Enable beacon generator + UINT32 bTBTTEnable:1; + UINT32 TsfSyncMode:2; // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode + UINT32 bTsfTicking:1; // Enable TSF auto counting + UINT32 BeaconInterval:16; // in unit of 1/16 TU + } field; + UINT32 word; +} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC; +#else +typedef union _BCN_TIME_CFG_STRUC { + struct { + UINT32 BeaconInterval:16; // in unit of 1/16 TU + UINT32 bTsfTicking:1; // Enable TSF auto counting + UINT32 TsfSyncMode:2; // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode + UINT32 bTBTTEnable:1; + UINT32 bBeaconGen:1; // Enable beacon generator + UINT32 :3; + UINT32 TxTimestampCompensate:8; + } field; + UINT32 word; +} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC; +#endif +#define TBTT_SYNC_CFG 0x1118 // txrx_csr10 +#define TSF_TIMER_DW0 0x111C // Local TSF timer lsb 32 bits. Read-only +#define TSF_TIMER_DW1 0x1120 // msb 32 bits. Read-only. +#define TBTT_TIMER 0x1124 // TImer remains till next TBTT. Read-only. TXRX_CSR14 +#define INT_TIMER_CFG 0x1128 // +#define INT_TIMER_EN 0x112c // GP-timer and pre-tbtt Int enable +#define CH_IDLE_STA 0x1130 // channel idle time +#define CH_BUSY_STA 0x1134 // channle busy time +// +// 4.2 MAC POWER configuration registers (offset:0x1200) +// +#define MAC_STATUS_CFG 0x1200 // old MAC_CSR12 +#define PWR_PIN_CFG 0x1204 // old MAC_CSR12 +#define AUTO_WAKEUP_CFG 0x1208 // old MAC_CSR10 +// +// AUTO_WAKEUP_CFG: Manual power control / status register +// +#ifdef RT_BIG_ENDIAN +typedef union _AUTO_WAKEUP_STRUC { + struct { + UINT32 :16; + UINT32 EnableAutoWakeup:1; // 0:sleep, 1:awake + UINT32 NumofSleepingTbtt:7; // ForceWake has high privilege than PutToSleep when both set + UINT32 AutoLeadTime:8; + } field; + UINT32 word; +} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC; +#else +typedef union _AUTO_WAKEUP_STRUC { + struct { + UINT32 AutoLeadTime:8; + UINT32 NumofSleepingTbtt:7; // ForceWake has high privilege than PutToSleep when both set + UINT32 EnableAutoWakeup:1; // 0:sleep, 1:awake + UINT32 :16; + } field; + UINT32 word; +} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC; +#endif +// +// 4.3 MAC TX configuration registers (offset:0x1300) +// + +#define EDCA_AC0_CFG 0x1300 //AC_TXOP_CSR0 0x3474 +#define EDCA_AC1_CFG 0x1304 +#define EDCA_AC2_CFG 0x1308 +#define EDCA_AC3_CFG 0x130c +#ifdef RT_BIG_ENDIAN +typedef union _EDCA_AC_CFG_STRUC { + struct { + UINT32 :12; // + UINT32 Cwmax:4; //unit power of 2 + UINT32 Cwmin:4; // + UINT32 Aifsn:4; // # of slot time + UINT32 AcTxop:8; // in unit of 32us + } field; + UINT32 word; +} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC; +#else +typedef union _EDCA_AC_CFG_STRUC { + struct { + UINT32 AcTxop:8; // in unit of 32us + UINT32 Aifsn:4; // # of slot time + UINT32 Cwmin:4; // + UINT32 Cwmax:4; //unit power of 2 + UINT32 :12; // + } field; + UINT32 word; +} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC; +#endif + +#define EDCA_TID_AC_MAP 0x1310 +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_CFG_2 0x131C +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_CFG_4 0x1324 +#define TX_PIN_CFG 0x1328 +#define TX_BAND_CFG 0x132c // 0x1 use upper 20MHz. 0 juse lower 20MHz +#define TX_SW_CFG0 0x1330 +#define TX_SW_CFG1 0x1334 +#define TX_SW_CFG2 0x1338 +#define TXOP_THRES_CFG 0x133c +#define TXOP_CTRL_CFG 0x1340 +#define TX_RTS_CFG 0x1344 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_RTS_CFG_STRUC { + struct { + UINT32 rsv:7; + UINT32 RtsFbkEn:1; // enable rts rate fallback + UINT32 RtsThres:16; // unit:byte + UINT32 AutoRtsRetryLimit:8; + } field; + UINT32 word; +} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC; +#else +typedef union _TX_RTS_CFG_STRUC { + struct { + UINT32 AutoRtsRetryLimit:8; + UINT32 RtsThres:16; // unit:byte + UINT32 RtsFbkEn:1; // enable rts rate fallback + UINT32 rsv:7; // 1: HT non-STBC control frame enable + } field; + UINT32 word; +} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC; +#endif +#define TX_TIMEOUT_CFG 0x1348 +#ifdef RT_BIG_ENDIAN +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + UINT32 rsv2:8; + UINT32 TxopTimeout:8; //TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) + UINT32 RxAckTimeout:8; // unit:slot. Used for TX precedure + UINT32 MpduLifeTime:4; // expiration time = 2^(9+MPDU LIFE TIME) us + UINT32 rsv:4; + } field; + UINT32 word; +} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC; +#else +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + UINT32 rsv:4; + UINT32 MpduLifeTime:4; // expiration time = 2^(9+MPDU LIFE TIME) us + UINT32 RxAckTimeout:8; // unit:slot. Used for TX precedure + UINT32 TxopTimeout:8; //TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) + UINT32 rsv2:8; // 1: HT non-STBC control frame enable + } field; + UINT32 word; +} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC; +#endif +#define TX_RTY_CFG 0x134c +#ifdef RT_BIG_ENDIAN +typedef union PACKED _TX_RTY_CFG_STRUC { + struct { + UINT32 rsv:1; + UINT32 TxautoFBEnable:1; // Tx retry PHY rate auto fallback enable + UINT32 AggRtyMode:1; // Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer + UINT32 NonAggRtyMode:1; // Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer + UINT32 LongRtyThre:12; // Long retry threshoold + UINT32 LongRtyLimit:8; //long retry limit + UINT32 ShortRtyLimit:8; // short retry limit + + } field; + UINT32 word; +} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC; +#else +typedef union PACKED _TX_RTY_CFG_STRUC { + struct { + UINT32 ShortRtyLimit:8; // short retry limit + UINT32 LongRtyLimit:8; //long retry limit + UINT32 LongRtyThre:12; // Long retry threshoold + UINT32 NonAggRtyMode:1; // Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer + UINT32 AggRtyMode:1; // Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer + UINT32 TxautoFBEnable:1; // Tx retry PHY rate auto fallback enable + UINT32 rsv:1; // 1: HT non-STBC control frame enable + } field; + UINT32 word; +} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC; +#endif +#define TX_LINK_CFG 0x1350 +#ifdef RT_BIG_ENDIAN +typedef union PACKED _TX_LINK_CFG_STRUC { + struct PACKED { + UINT32 RemotMFS:8; //remote MCS feedback sequence number + UINT32 RemotMFB:8; // remote MCS feedback + UINT32 rsv:3; // + UINT32 TxCFAckEn:1; // Piggyback CF-ACK enable + UINT32 TxRDGEn:1; // RDG TX enable + UINT32 TxMRQEn:1; // MCS request TX enable + UINT32 RemoteUMFSEnable:1; // remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) + UINT32 MFBEnable:1; // TX apply remote MFB 1:enable + UINT32 RemoteMFBLifeTime:8; //remote MFB life time. unit : 32us + } field; + UINT32 word; +} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC; +#else +typedef union PACKED _TX_LINK_CFG_STRUC { + struct PACKED { + UINT32 RemoteMFBLifeTime:8; //remote MFB life time. unit : 32us + UINT32 MFBEnable:1; // TX apply remote MFB 1:enable + UINT32 RemoteUMFSEnable:1; // remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) + UINT32 TxMRQEn:1; // MCS request TX enable + UINT32 TxRDGEn:1; // RDG TX enable + UINT32 TxCFAckEn:1; // Piggyback CF-ACK enable + UINT32 rsv:3; // + UINT32 RemotMFB:8; // remote MCS feedback + UINT32 RemotMFS:8; //remote MCS feedback sequence number + } field; + UINT32 word; +} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC; +#endif +#define HT_FBK_CFG0 0x1354 +#ifdef RT_BIG_ENDIAN +typedef union PACKED _HT_FBK_CFG0_STRUC { + struct { + UINT32 HTMCS7FBK:4; + UINT32 HTMCS6FBK:4; + UINT32 HTMCS5FBK:4; + UINT32 HTMCS4FBK:4; + UINT32 HTMCS3FBK:4; + UINT32 HTMCS2FBK:4; + UINT32 HTMCS1FBK:4; + UINT32 HTMCS0FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC; +#else +typedef union PACKED _HT_FBK_CFG0_STRUC { + struct { + UINT32 HTMCS0FBK:4; + UINT32 HTMCS1FBK:4; + UINT32 HTMCS2FBK:4; + UINT32 HTMCS3FBK:4; + UINT32 HTMCS4FBK:4; + UINT32 HTMCS5FBK:4; + UINT32 HTMCS6FBK:4; + UINT32 HTMCS7FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC; +#endif +#define HT_FBK_CFG1 0x1358 +#ifdef RT_BIG_ENDIAN +typedef union _HT_FBK_CFG1_STRUC { + struct { + UINT32 HTMCS15FBK:4; + UINT32 HTMCS14FBK:4; + UINT32 HTMCS13FBK:4; + UINT32 HTMCS12FBK:4; + UINT32 HTMCS11FBK:4; + UINT32 HTMCS10FBK:4; + UINT32 HTMCS9FBK:4; + UINT32 HTMCS8FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC; +#else +typedef union _HT_FBK_CFG1_STRUC { + struct { + UINT32 HTMCS8FBK:4; + UINT32 HTMCS9FBK:4; + UINT32 HTMCS10FBK:4; + UINT32 HTMCS11FBK:4; + UINT32 HTMCS12FBK:4; + UINT32 HTMCS13FBK:4; + UINT32 HTMCS14FBK:4; + UINT32 HTMCS15FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC; +#endif +#define LG_FBK_CFG0 0x135c +#ifdef RT_BIG_ENDIAN +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS7FBK:4; //initial value is 6 + UINT32 OFDMMCS6FBK:4; //initial value is 5 + UINT32 OFDMMCS5FBK:4; //initial value is 4 + UINT32 OFDMMCS4FBK:4; //initial value is 3 + UINT32 OFDMMCS3FBK:4; //initial value is 2 + UINT32 OFDMMCS2FBK:4; //initial value is 1 + UINT32 OFDMMCS1FBK:4; //initial value is 0 + UINT32 OFDMMCS0FBK:4; //initial value is 0 + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC; +#else +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS0FBK:4; //initial value is 0 + UINT32 OFDMMCS1FBK:4; //initial value is 0 + UINT32 OFDMMCS2FBK:4; //initial value is 1 + UINT32 OFDMMCS3FBK:4; //initial value is 2 + UINT32 OFDMMCS4FBK:4; //initial value is 3 + UINT32 OFDMMCS5FBK:4; //initial value is 4 + UINT32 OFDMMCS6FBK:4; //initial value is 5 + UINT32 OFDMMCS7FBK:4; //initial value is 6 + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC; +#endif +#define LG_FBK_CFG1 0x1360 +#ifdef RT_BIG_ENDIAN +typedef union _LG_FBK_CFG1_STRUC { + struct { + UINT32 rsv:16; + UINT32 CCKMCS3FBK:4; //initial value is 2 + UINT32 CCKMCS2FBK:4; //initial value is 1 + UINT32 CCKMCS1FBK:4; //initial value is 0 + UINT32 CCKMCS0FBK:4; //initial value is 0 + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; +#else +typedef union _LG_FBK_CFG1_STRUC { + struct { + UINT32 CCKMCS0FBK:4; //initial value is 0 + UINT32 CCKMCS1FBK:4; //initial value is 0 + UINT32 CCKMCS2FBK:4; //initial value is 1 + UINT32 CCKMCS3FBK:4; //initial value is 2 + UINT32 rsv:16; + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC; +#endif + +//======================================================= +//================ Protection Paramater================================ +//======================================================= +#define CCK_PROT_CFG 0x1364 //CCK Protection +#define ASIC_SHORTNAV 1 +#define ASIC_LONGNAV 2 +#define ASIC_RTS 1 +#define ASIC_CTS 2 +#ifdef RT_BIG_ENDIAN +typedef union _PROT_CFG_STRUC { + struct { + UINT32 rsv:5; + UINT32 RTSThEn:1; //RTS threshold enable on CCK TX + UINT32 TxopAllowGF40:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowGF20:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowMM40:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowMM20:1; //CCK TXOP allowance. 0:disallow. + UINT32 TxopAllowOfdm:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowCck:1; //CCK TXOP allowance.0:disallow. + UINT32 ProtectNav:2; //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv + UINT32 ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv + UINT32 ProtectRate:16; //Protection control frame rate for CCK TX(RTS/CTS/CFEnd). + } field; + UINT32 word; +} PROT_CFG_STRUC, *PPROT_CFG_STRUC; +#else +typedef union _PROT_CFG_STRUC { + struct { + UINT32 ProtectRate:16; //Protection control frame rate for CCK TX(RTS/CTS/CFEnd). + UINT32 ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv + UINT32 ProtectNav:2; //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv + UINT32 TxopAllowCck:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowOfdm:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowMM20:1; //CCK TXOP allowance. 0:disallow. + UINT32 TxopAllowMM40:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowGF20:1; //CCK TXOP allowance.0:disallow. + UINT32 TxopAllowGF40:1; //CCK TXOP allowance.0:disallow. + UINT32 RTSThEn:1; //RTS threshold enable on CCK TX + UINT32 rsv:5; + } field; + UINT32 word; +} PROT_CFG_STRUC, *PPROT_CFG_STRUC; +#endif + +#define OFDM_PROT_CFG 0x1368 //OFDM Protection +#define MM20_PROT_CFG 0x136C //MM20 Protection +#define MM40_PROT_CFG 0x1370 //MM40 Protection +#define GF20_PROT_CFG 0x1374 //GF20 Protection +#define GF40_PROT_CFG 0x1378 //GR40 Protection +#define EXP_CTS_TIME 0x137C // +#define EXP_ACK_TIME 0x1380 // + +// +// 4.4 MAC RX configuration registers (offset:0x1400) +// +#define RX_FILTR_CFG 0x1400 //TXRX_CSR0 +#define AUTO_RSP_CFG 0x1404 //TXRX_CSR4 +// +// TXRX_CSR4: Auto-Responder/ +// +#ifdef RT_BIG_ENDIAN +typedef union _AUTO_RSP_CFG_STRUC { + struct { + UINT32 :24; + UINT32 AckCtsPsmBit:1; // Power bit value in conrtrol frame + UINT32 DualCTSEn:1; // Power bit value in conrtrol frame + UINT32 rsv:1; // Power bit value in conrtrol frame + UINT32 AutoResponderPreamble:1; // 0:long, 1:short preamble + UINT32 CTS40MRef:1; // Response CTS 40MHz duplicate mode + UINT32 CTS40MMode:1; // Response CTS 40MHz duplicate mode + UINT32 BACAckPolicyEnable:1; // 0:long, 1:short preamble + UINT32 AutoResponderEnable:1; + } field; + UINT32 word; +} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC; +#else +typedef union _AUTO_RSP_CFG_STRUC { + struct { + UINT32 AutoResponderEnable:1; + UINT32 BACAckPolicyEnable:1; // 0:long, 1:short preamble + UINT32 CTS40MMode:1; // Response CTS 40MHz duplicate mode + UINT32 CTS40MRef:1; // Response CTS 40MHz duplicate mode + UINT32 AutoResponderPreamble:1; // 0:long, 1:short preamble + UINT32 rsv:1; // Power bit value in conrtrol frame + UINT32 DualCTSEn:1; // Power bit value in conrtrol frame + UINT32 AckCtsPsmBit:1; // Power bit value in conrtrol frame + UINT32 :24; + } field; + UINT32 word; +} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC; +#endif + +#define LEGACY_BASIC_RATE 0x1408 // TXRX_CSR5 0x3054 +#define HT_BASIC_RATE 0x140c +#define HT_CTRL_CFG 0x1410 +#define SIFS_COST_CFG 0x1414 +#define RX_PARSER_CFG 0x1418 //Set NAV for all received frames + +// +// 4.5 MAC Security configuration (offset:0x1500) +// +#define TX_SEC_CNT0 0x1500 // +#define RX_SEC_CNT0 0x1504 // +#define CCMP_FC_MUTE 0x1508 // +// +// 4.6 HCCA/PSMP (offset:0x1600) +// +#define TXOP_HLDR_ADDR0 0x1600 +#define TXOP_HLDR_ADDR1 0x1604 +#define TXOP_HLDR_ET 0x1608 +#define QOS_CFPOLL_RA_DW0 0x160c +#define QOS_CFPOLL_A1_DW1 0x1610 +#define QOS_CFPOLL_QC 0x1614 +// +// 4.7 MAC Statistis registers (offset:0x1700) +// +#define RX_STA_CNT0 0x1700 // +#define RX_STA_CNT1 0x1704 // +#define RX_STA_CNT2 0x1708 // + +// +// RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count +// +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT0_STRUC { + struct { + USHORT PhyErr; + USHORT CrcErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; +#else +typedef union _RX_STA_CNT0_STRUC { + struct { + USHORT CrcErr; + USHORT PhyErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC; +#endif + +// +// RX_STA_CNT1_STRUC: RX False CCA count & RX LONG frame count +// +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT1_STRUC { + struct { + USHORT PlcpErr; + USHORT FalseCca; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; +#else +typedef union _RX_STA_CNT1_STRUC { + struct { + USHORT FalseCca; + USHORT PlcpErr; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC; +#endif + +// +// RX_STA_CNT2_STRUC: +// +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT2_STRUC { + struct { + USHORT RxFifoOverflowCount; + USHORT RxDupliCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; +#else +typedef union _RX_STA_CNT2_STRUC { + struct { + USHORT RxDupliCount; + USHORT RxFifoOverflowCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC; +#endif +#define TX_STA_CNT0 0x170C // +// +// STA_CSR3: TX Beacon count +// +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT0_STRUC { + struct { + USHORT TxBeaconCount; + USHORT TxFailCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; +#else +typedef union _TX_STA_CNT0_STRUC { + struct { + USHORT TxFailCount; + USHORT TxBeaconCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC; +#endif +#define TX_STA_CNT1 0x1710 // +// +// TX_STA_CNT1: TX tx count +// +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT1_STRUC { + struct { + USHORT TxRetransmit; + USHORT TxSuccess; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; +#else +typedef union _TX_STA_CNT1_STRUC { + struct { + USHORT TxSuccess; + USHORT TxRetransmit; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC; +#endif +#define TX_STA_CNT2 0x1714 // +// +// TX_STA_CNT2: TX tx count +// +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT2_STRUC { + struct { + USHORT TxUnderFlowCount; + USHORT TxZeroLenCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; +#else +typedef union _TX_STA_CNT2_STRUC { + struct { + USHORT TxZeroLenCount; + USHORT TxUnderFlowCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC; +#endif +#define TX_STA_FIFO 0x1718 // +// +// TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register +// +#ifdef RT_BIG_ENDIAN +typedef union PACKED _TX_STA_FIFO_STRUC { + struct { + UINT32 Reserve:2; + UINT32 TxBF:1; // 3*3 + UINT32 SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. +// UINT32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. + UINT32 wcid:8; //wireless client index + UINT32 TxAckRequired:1; // ack required + UINT32 TxAggre:1; // Tx is aggregated + UINT32 TxSuccess:1; // Tx success. whether success or not + UINT32 PidType:4; + UINT32 bValid:1; // 1:This register contains a valid TX result + } field; + UINT32 word; +} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC; +#else +typedef union PACKED _TX_STA_FIFO_STRUC { + struct { + UINT32 bValid:1; // 1:This register contains a valid TX result + UINT32 PidType:4; + UINT32 TxSuccess:1; // Tx No retry success + UINT32 TxAggre:1; // Tx Retry Success + UINT32 TxAckRequired:1; // Tx fail + UINT32 wcid:8; //wireless client index +// UINT32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. + UINT32 SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16. + UINT32 TxBF:1; + UINT32 Reserve:2; + } field; + UINT32 word; +} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT 0x171c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT_STRUC { + struct { + USHORT AggTxCount; + USHORT NonAggTxCount; + } field; + UINT32 word; +} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; +#else +typedef union _TX_AGG_CNT_STRUC { + struct { + USHORT NonAggTxCount; + USHORT AggTxCount; + } field; + UINT32 word; +} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT0 0x1720 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT0_STRUC { + struct { + USHORT AggSize2Count; + USHORT AggSize1Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; +#else +typedef union _TX_AGG_CNT0_STRUC { + struct { + USHORT AggSize1Count; + USHORT AggSize2Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT1 0x1724 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT1_STRUC { + struct { + USHORT AggSize4Count; + USHORT AggSize3Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; +#else +typedef union _TX_AGG_CNT1_STRUC { + struct { + USHORT AggSize3Count; + USHORT AggSize4Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC; +#endif +#define TX_AGG_CNT2 0x1728 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT2_STRUC { + struct { + USHORT AggSize6Count; + USHORT AggSize5Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; +#else +typedef union _TX_AGG_CNT2_STRUC { + struct { + USHORT AggSize5Count; + USHORT AggSize6Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT3 0x172c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT3_STRUC { + struct { + USHORT AggSize8Count; + USHORT AggSize7Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; +#else +typedef union _TX_AGG_CNT3_STRUC { + struct { + USHORT AggSize7Count; + USHORT AggSize8Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC; +#endif +// Debug counter +#define TX_AGG_CNT4 0x1730 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT4_STRUC { + struct { + USHORT AggSize10Count; + USHORT AggSize9Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; +#else +typedef union _TX_AGG_CNT4_STRUC { + struct { + USHORT AggSize9Count; + USHORT AggSize10Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC; +#endif +#define TX_AGG_CNT5 0x1734 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT5_STRUC { + struct { + USHORT AggSize12Count; + USHORT AggSize11Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; +#else +typedef union _TX_AGG_CNT5_STRUC { + struct { + USHORT AggSize11Count; + USHORT AggSize12Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC; +#endif +#define TX_AGG_CNT6 0x1738 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT6_STRUC { + struct { + USHORT AggSize14Count; + USHORT AggSize13Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; +#else +typedef union _TX_AGG_CNT6_STRUC { + struct { + USHORT AggSize13Count; + USHORT AggSize14Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC; +#endif +#define TX_AGG_CNT7 0x173c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT7_STRUC { + struct { + USHORT AggSize16Count; + USHORT AggSize15Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; +#else +typedef union _TX_AGG_CNT7_STRUC { + struct { + USHORT AggSize15Count; + USHORT AggSize16Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC; +#endif +#define MPDU_DENSITY_CNT 0x1740 +#ifdef RT_BIG_ENDIAN +typedef union _MPDU_DEN_CNT_STRUC { + struct { + USHORT RXZeroDelCount; //RX zero length delimiter count + USHORT TXZeroDelCount; //TX zero length delimiter count + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; +#else +typedef union _MPDU_DEN_CNT_STRUC { + struct { + USHORT TXZeroDelCount; //TX zero length delimiter count + USHORT RXZeroDelCount; //RX zero length delimiter count + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC; +#endif +// +// TXRX control registers - base address 0x3000 +// +// rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. +#define TXRX_CSR1 0x77d0 + +// +// Security key table memory, base address = 0x1000 +// +#define MAC_WCID_BASE 0x1800 //8-bytes(use only 6-bytes) * 256 entry = +#define HW_WCID_ENTRY_SIZE 8 +#define PAIRWISE_KEY_TABLE_BASE 0x4000 // 32-byte * 256-entry = -byte +#define HW_KEY_ENTRY_SIZE 0x20 +#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte +#define MAC_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte +#define HW_IVEIV_ENTRY_SIZE 8 +#define MAC_WCID_ATTRIBUTE_BASE 0x6800 // 4-byte * 256-entry = -byte +#define HW_WCID_ATTRI_SIZE 4 +#define WCID_RESERVED 0x6bfc +#define SHARED_KEY_TABLE_BASE 0x6c00 // 32-byte * 16-entry = 512-byte +#define SHARED_KEY_MODE_BASE 0x7000 // 32-byte * 16-entry = 512-byte +#define HW_SHARED_KEY_MODE_SIZE 4 +#define SHAREDKEYTABLE 0 +#define PAIRWISEKEYTABLE 1 + + +#ifdef RT_BIG_ENDIAN +typedef union _SHAREDKEY_MODE_STRUC { + struct { + UINT32 :1; + UINT32 Bss1Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key0CipherAlg:3; + } field; + UINT32 word; +} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC; +#else +typedef union _SHAREDKEY_MODE_STRUC { + struct { + UINT32 Bss0Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss0Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss1Key3CipherAlg:3; + UINT32 :1; + } field; + UINT32 word; +} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC; +#endif +// 64-entry for pairwise key table +typedef struct _HW_WCID_ENTRY { // 8-byte per entry + UCHAR Address[6]; + UCHAR Rsv[2]; +} HW_WCID_ENTRY, PHW_WCID_ENTRY; + + + +// +// Other on-chip shared memory space, base = 0x2000 +// + +// CIS space - base address = 0x2000 +#define HW_CIS_BASE 0x2000 + +// Carrier-sense CTS frame base address. It's where mac stores carrier-sense frame for carrier-sense function. +#define HW_CS_CTS_BASE 0x7700 +// DFS CTS frame base address. It's where mac stores CTS frame for DFS. +#define HW_DFS_CTS_BASE 0x7780 +#define HW_CTS_FRAME_SIZE 0x80 + +// 2004-11-08 john - since NULL frame won't be that long (256 byte). We steal 16 tail bytes +// to save debugging settings +#define HW_DEBUG_SETTING_BASE 0x77f0 // 0x77f0~0x77ff total 16 bytes +#define HW_DEBUG_SETTING_BASE2 0x7770 // 0x77f0~0x77ff total 16 bytes + +// In order to support maximum 8 MBSS and its maximum length is 512 for each beacon +// Three section discontinue memory segments will be used. +// 1. The original region for BCN 0~3 +// 2. Extract memory from FCE table for BCN 4~5 +// 3. Extract memory from Pair-wise key table for BCN 6~7 +// It occupied those memory of wcid 238~253 for BCN 6 +// and wcid 222~237 for BCN 7 +#define HW_BEACON_MAX_SIZE 0x1000 /* unit: byte */ +#define HW_BEACON_BASE0 0x7800 +#define HW_BEACON_BASE1 0x7A00 +#define HW_BEACON_BASE2 0x7C00 +#define HW_BEACON_BASE3 0x7E00 +#define HW_BEACON_BASE4 0x7200 +#define HW_BEACON_BASE5 0x7400 +#define HW_BEACON_BASE6 0x5DC0 +#define HW_BEACON_BASE7 0x5BC0 + +#define HW_BEACON_MAX_COUNT 8 +#define HW_BEACON_OFFSET 0x0200 +#define HW_BEACON_CONTENT_LEN (HW_BEACON_OFFSET - TXWI_SIZE) + +// HOST-MCU shared memory - base address = 0x2100 +#define HOST_CMD_CSR 0x404 +#define H2M_MAILBOX_CSR 0x7010 +#define H2M_MAILBOX_CID 0x7014 +#define H2M_MAILBOX_STATUS 0x701c +#define H2M_INT_SRC 0x7024 +#define H2M_BBP_AGENT 0x7028 +#define M2H_CMD_DONE_CSR 0x000c +#define MCU_TXOP_ARRAY_BASE 0x000c // TODO: to be provided by Albert +#define MCU_TXOP_ENTRY_SIZE 32 // TODO: to be provided by Albert +#define MAX_NUM_OF_TXOP_ENTRY 16 // TODO: must be same with 8051 firmware +#define MCU_MBOX_VERSION 0x01 // TODO: to be confirmed by Albert +#define MCU_MBOX_VERSION_OFFSET 5 // TODO: to be provided by Albert + +// +// Host DMA registers - base address 0x200 . TX0-3=EDCAQid0-3, TX4=HCCA, TX5=MGMT, +// +// +// DMA RING DESCRIPTOR +// +#define E2PROM_CSR 0x0004 +#define IO_CNTL_CSR 0x77d0 + +#ifdef RT2870 +// 8051 firmware image for usb - use last-half base address = 0x3000 +#define FIRMWARE_IMAGE_BASE 0x3000 +#define MAX_FIRMWARE_IMAGE_SIZE 0x1000 // 4kbyte +#endif // RT2870 // + +// TODO: ????? old RT2560 registers. to keep them or remove them? +//#define MCAST0 0x0178 // multicast filter register 0 +//#define MCAST1 0x017c // multicast filter register 1 + + +// ================================================================ +// Tx / Rx / Mgmt ring descriptor definition +// ================================================================ + +// the following PID values are used to mark outgoing frame type in TXD->PID so that +// proper TX statistics can be collected based on these categories +// b3-2 of PID field - +#define PID_MGMT 0x05 +#define PID_BEACON 0x0c +#define PID_DATA_NORMALUCAST 0x02 +#define PID_DATA_AMPDU 0x04 +#define PID_DATA_NO_ACK 0x08 +#define PID_DATA_NOT_NORM_ACK 0x03 +// value domain of pTxD->HostQId (4-bit: 0~15) +#define QID_AC_BK 1 // meet ACI definition in 802.11e +#define QID_AC_BE 0 // meet ACI definition in 802.11e +#define QID_AC_VI 2 +#define QID_AC_VO 3 +#define QID_HCCA 4 +#define NUM_OF_TX_RING 5 +#define QID_MGMT 13 +#define QID_RX 14 +#define QID_OTHER 15 + + +// ------------------------------------------------------ +// BBP & RF definition +// ------------------------------------------------------ +#define BUSY 1 +#define IDLE 0 + +#define RF_R00 0 +#define RF_R01 1 +#define RF_R02 2 +#define RF_R03 3 +#define RF_R04 4 +#define RF_R05 5 +#define RF_R06 6 +#define RF_R07 7 +#define RF_R08 8 +#define RF_R09 9 +#define RF_R10 10 +#define RF_R11 11 +#define RF_R12 12 +#define RF_R13 13 +#define RF_R14 14 +#define RF_R15 15 +#define RF_R16 16 +#define RF_R17 17 +#define RF_R18 18 +#define RF_R19 19 +#define RF_R20 20 +#define RF_R21 21 +#define RF_R22 22 +#define RF_R23 23 +#define RF_R24 24 +#define RF_R25 25 +#define RF_R26 26 +#define RF_R27 27 +#define RF_R28 28 +#define RF_R29 29 +#define RF_R30 30 +#define RF_R31 31 + +#define BBP_R0 0 // version +#define BBP_R1 1 // TSSI +#define BBP_R2 2 // TX configure +#define BBP_R3 3 +#define BBP_R4 4 +#define BBP_R5 5 +#define BBP_R6 6 +#define BBP_R14 14 // RX configure +#define BBP_R16 16 +#define BBP_R17 17 // RX sensibility +#define BBP_R18 18 +#define BBP_R21 21 +#define BBP_R22 22 +#define BBP_R24 24 +#define BBP_R25 25 +#define BBP_R31 31 +#define BBP_R49 49 //TSSI +#define BBP_R50 50 +#define BBP_R51 51 +#define BBP_R52 52 +#define BBP_R55 55 +#define BBP_R62 62 // Rx SQ0 Threshold HIGH +#define BBP_R63 63 +#define BBP_R64 64 +#define BBP_R65 65 +#define BBP_R66 66 +#define BBP_R67 67 +#define BBP_R68 68 +#define BBP_R69 69 +#define BBP_R70 70 // Rx AGC SQ CCK Xcorr threshold +#define BBP_R73 73 +#define BBP_R75 75 +#define BBP_R77 77 +#define BBP_R79 79 +#define BBP_R80 80 +#define BBP_R81 81 +#define BBP_R82 82 +#define BBP_R83 83 +#define BBP_R84 84 +#define BBP_R86 86 +#define BBP_R91 91 +#define BBP_R92 92 +#define BBP_R94 94 // Tx Gain Control +#define BBP_R103 103 +#define BBP_R105 105 +#define BBP_R113 113 +#define BBP_R114 114 +#define BBP_R115 115 +#define BBP_R116 116 +#define BBP_R117 117 +#define BBP_R118 118 +#define BBP_R119 119 +#define BBP_R120 120 +#define BBP_R121 121 +#define BBP_R122 122 +#define BBP_R123 123 +#ifdef RT30xx +#define BBP_R138 138 // add by johnli, RF power sequence setup, ADC dynamic on/off control +#endif // RT30xx // + + +#define BBPR94_DEFAULT 0x06 // Add 1 value will gain 1db + +//#define PHY_TR_SWITCH_TIME 5 // usec + +//#define BBP_R17_LOW_SENSIBILITY 0x50 +//#define BBP_R17_MID_SENSIBILITY 0x41 +//#define BBP_R17_DYNAMIC_UP_BOUND 0x40 +#define RSSI_FOR_VERY_LOW_SENSIBILITY -35 +#define RSSI_FOR_LOW_SENSIBILITY -58 +#define RSSI_FOR_MID_LOW_SENSIBILITY -80 +#define RSSI_FOR_MID_SENSIBILITY -90 + +//------------------------------------------------------------------------- +// EEPROM definition +//------------------------------------------------------------------------- +#define EEDO 0x08 +#define EEDI 0x04 +#define EECS 0x02 +#define EESK 0x01 +#define EERL 0x80 + +#define EEPROM_WRITE_OPCODE 0x05 +#define EEPROM_READ_OPCODE 0x06 +#define EEPROM_EWDS_OPCODE 0x10 +#define EEPROM_EWEN_OPCODE 0x13 + +#define NUM_EEPROM_BBP_PARMS 19 // Include NIC Config 0, 1, CR, TX ALC step, BBPs +#define NUM_EEPROM_TX_G_PARMS 7 +#define EEPROM_NIC1_OFFSET 0x34 // The address is from NIC config 0, not BBP register ID +#define EEPROM_NIC2_OFFSET 0x36 // The address is from NIC config 0, not BBP register ID +#define EEPROM_BBP_BASE_OFFSET 0xf0 // The address is from NIC config 0, not BBP register ID +#define EEPROM_G_TX_PWR_OFFSET 0x52 +#define EEPROM_G_TX2_PWR_OFFSET 0x60 +#define EEPROM_LED1_OFFSET 0x3c +#define EEPROM_LED2_OFFSET 0x3e +#define EEPROM_LED3_OFFSET 0x40 +#define EEPROM_LNA_OFFSET 0x44 +#define EEPROM_RSSI_BG_OFFSET 0x46 +#define EEPROM_RSSI_A_OFFSET 0x4a +#define EEPROM_DEFINE_MAX_TXPWR 0x4e +#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0xde // 20MHZ 2.4G tx power. +#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0xee // 40MHZ 2.4G tx power. +#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0xfa // 20MHZ 5G tx power. +#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x10a // 40MHZ 5G tx power. +#define EEPROM_A_TX_PWR_OFFSET 0x78 +#define EEPROM_A_TX2_PWR_OFFSET 0xa6 +//#define EEPROM_Japan_TX_PWR_OFFSET 0x90 // 802.11j +//#define EEPROM_Japan_TX2_PWR_OFFSET 0xbe +//#define EEPROM_TSSI_REF_OFFSET 0x54 +//#define EEPROM_TSSI_DELTA_OFFSET 0x24 +//#define EEPROM_CCK_TX_PWR_OFFSET 0x62 +//#define EEPROM_CALIBRATE_OFFSET 0x7c +#define EEPROM_VERSION_OFFSET 0x02 +#define EEPROM_FREQ_OFFSET 0x3a +#define EEPROM_TXPOWER_BYRATE 0xde // 20MHZ power. +#define EEPROM_TXPOWER_DELTA 0x50 // 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ. +#define VALID_EEPROM_VERSION 1 + +// PairKeyMode definition +#define PKMODE_NONE 0 +#define PKMODE_WEP64 1 +#define PKMODE_WEP128 2 +#define PKMODE_TKIP 3 +#define PKMODE_AES 4 +#define PKMODE_CKIP64 5 +#define PKMODE_CKIP128 6 +#define PKMODE_TKIP_NO_MIC 7 // MIC appended by driver: not a valid value in hardware key table + +// ================================================================================= +// WCID format +// ================================================================================= +//7.1 WCID ENTRY format : 8bytes +typedef struct _WCID_ENTRY_STRUC { + UCHAR RXBABitmap7; // bit0 for TID8, bit7 for TID 15 + UCHAR RXBABitmap0; // bit0 for TID0, bit7 for TID 7 + UCHAR MAC[6]; // 0 for shared key table. 1 for pairwise key table +} WCID_ENTRY_STRUC, *PWCID_ENTRY_STRUC; + +//8.1.1 SECURITY KEY format : 8DW +// 32-byte per entry, total 16-entry for shared key table, 64-entry for pairwise key table +typedef struct _HW_KEY_ENTRY { // 32-byte per entry + UCHAR Key[16]; + UCHAR TxMic[8]; + UCHAR RxMic[8]; +} HW_KEY_ENTRY, *PHW_KEY_ENTRY; + +//8.1.2 IV/EIV format : 2DW + +//8.1.3 RX attribute entry format : 1DW +#ifdef RT_BIG_ENDIAN +typedef struct _MAC_ATTRIBUTE_STRUC { + UINT32 rsv:22; + UINT32 RXWIUDF:3; + UINT32 BSSIDIdx:3; //multipleBSS index for the WCID + UINT32 PairKeyMode:3; + UINT32 KeyTab:1; // 0 for shared key table. 1 for pairwise key table +} MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC; +#else +typedef struct _MAC_ATTRIBUTE_STRUC { + UINT32 KeyTab:1; // 0 for shared key table. 1 for pairwise key table + UINT32 PairKeyMode:3; + UINT32 BSSIDIdx:3; //multipleBSS index for the WCID + UINT32 RXWIUDF:3; + UINT32 rsv:22; +} MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC; +#endif + + +// ================================================================================= +// TX / RX ring descriptor format +// ================================================================================= + +// the first 24-byte in TXD is called TXINFO and will be DMAed to MAC block through TXFIFO. +// MAC block use this TXINFO to control the transmission behavior of this frame. +#define FIFO_MGMT 0 +#define FIFO_HCCA 1 +#define FIFO_EDCA 2 + +// +// TX descriptor format, Tx ring, Mgmt Ring +// +#ifdef RT_BIG_ENDIAN +typedef struct PACKED _TXD_STRUC { + // Word 0 + UINT32 SDPtr0; + // Word 1 + UINT32 DMADONE:1; + UINT32 LastSec0:1; + UINT32 SDLen0:14; + UINT32 Burst:1; + UINT32 LastSec1:1; + UINT32 SDLen1:14; + // Word 2 + UINT32 SDPtr1; + // Word 3 + UINT32 ICO:1; + UINT32 UCO:1; + UINT32 TCO:1; + UINT32 rsv:2; + UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA + UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition + UINT32 rsv2:24; +} TXD_STRUC, *PTXD_STRUC; +#else +typedef struct PACKED _TXD_STRUC { + // Word 0 + UINT32 SDPtr0; + // Word 1 + UINT32 SDLen1:14; + UINT32 LastSec1:1; + UINT32 Burst:1; + UINT32 SDLen0:14; + UINT32 LastSec0:1; + UINT32 DMADONE:1; + //Word2 + UINT32 SDPtr1; + //Word3 + UINT32 rsv2:24; + UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition + UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA + UINT32 rsv:2; + UINT32 TCO:1; // + UINT32 UCO:1; // + UINT32 ICO:1; // +} TXD_STRUC, *PTXD_STRUC; +#endif + + +// +// TXD Wireless Information format for Tx ring and Mgmt Ring +// +//txop : for txop mode +// 0:txop for the MPDU frame will be handles by ASIC by register +// 1/2/3:the MPDU frame is send after PIFS/backoff/SIFS +#ifdef RT_BIG_ENDIAN +typedef struct PACKED _TXWI_STRUC { + // Word 0 + UINT32 PHYMODE:2; + UINT32 TxBF:1; // 3*3 + UINT32 rsv2:1; +// UINT32 rsv2:2; + UINT32 Ifs:1; // + UINT32 STBC:2; //channel bandwidth 20MHz or 40 MHz + UINT32 ShortGI:1; + UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz + UINT32 MCS:7; + + UINT32 rsv:6; + UINT32 txop:2; //tx back off mode 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. + UINT32 MpduDensity:3; + UINT32 AMPDU:1; + + UINT32 TS:1; + UINT32 CFACK:1; + UINT32 MIMOps:1; // the remote peer is in dynamic MIMO-PS mode + UINT32 FRAG:1; // 1 to inform TKIP engine this is a fragment. + // Word 1 + UINT32 PacketId:4; + UINT32 MPDUtotalByteCount:12; + UINT32 WirelessCliID:8; + UINT32 BAWinSize:6; + UINT32 NSEQ:1; + UINT32 ACK:1; + // Word 2 + UINT32 IV; + // Word 3 + UINT32 EIV; +} TXWI_STRUC, *PTXWI_STRUC; +#else +typedef struct PACKED _TXWI_STRUC { + // Word 0 + UINT32 FRAG:1; // 1 to inform TKIP engine this is a fragment. + UINT32 MIMOps:1; // the remote peer is in dynamic MIMO-PS mode + UINT32 CFACK:1; + UINT32 TS:1; + + UINT32 AMPDU:1; + UINT32 MpduDensity:3; + UINT32 txop:2; //FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. + UINT32 rsv:6; + + UINT32 MCS:7; + UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz + UINT32 ShortGI:1; + UINT32 STBC:2; // 1: STBC support MCS =0-7, 2,3 : RESERVE + UINT32 Ifs:1; // +// UINT32 rsv2:2; //channel bandwidth 20MHz or 40 MHz + UINT32 rsv2:1; + UINT32 TxBF:1; // 3*3 + UINT32 PHYMODE:2; + // Word 1 + UINT32 ACK:1; + UINT32 NSEQ:1; + UINT32 BAWinSize:6; + UINT32 WirelessCliID:8; + UINT32 MPDUtotalByteCount:12; + UINT32 PacketId:4; + //Word2 + UINT32 IV; + //Word3 + UINT32 EIV; +} TXWI_STRUC, *PTXWI_STRUC; +#endif +// +// Rx descriptor format, Rx Ring +// +// +// RXWI wireless information format, in PBF. invisible in driver. +// +#ifdef RT_BIG_ENDIAN +typedef struct PACKED _RXWI_STRUC { + // Word 0 + UINT32 TID:4; + UINT32 MPDUtotalByteCount:12; + UINT32 UDF:3; + UINT32 BSSID:3; + UINT32 KeyIndex:2; + UINT32 WirelessCliID:8; + // Word 1 + UINT32 PHYMODE:2; // 1: this RX frame is unicast to me + UINT32 rsv:3; + UINT32 STBC:2; + UINT32 ShortGI:1; + UINT32 BW:1; + UINT32 MCS:7; + UINT32 SEQUENCE:12; + UINT32 FRAG:4; + // Word 2 + UINT32 rsv1:8; + UINT32 RSSI2:8; + UINT32 RSSI1:8; + UINT32 RSSI0:8; + // Word 3 + UINT32 rsv2:16; + UINT32 SNR1:8; + UINT32 SNR0:8; +} RXWI_STRUC, *PRXWI_STRUC; +#else +typedef struct PACKED _RXWI_STRUC { + // Word 0 + UINT32 WirelessCliID:8; + UINT32 KeyIndex:2; + UINT32 BSSID:3; + UINT32 UDF:3; + UINT32 MPDUtotalByteCount:12; + UINT32 TID:4; + // Word 1 + UINT32 FRAG:4; + UINT32 SEQUENCE:12; + UINT32 MCS:7; + UINT32 BW:1; + UINT32 ShortGI:1; + UINT32 STBC:2; + UINT32 rsv:3; + UINT32 PHYMODE:2; // 1: this RX frame is unicast to me + //Word2 + UINT32 RSSI0:8; + UINT32 RSSI1:8; + UINT32 RSSI2:8; + UINT32 rsv1:8; + //Word3 + UINT32 SNR0:8; + UINT32 SNR1:8; + UINT32 rsv2:16; +} RXWI_STRUC, *PRXWI_STRUC; +#endif + + +// ================================================================================= +// HOST-MCU communication data structure +// ================================================================================= + +// +// H2M_MAILBOX_CSR: Host-to-MCU Mailbox +// +#ifdef RT_BIG_ENDIAN +typedef union _H2M_MAILBOX_STRUC { + struct { + UINT32 Owner:8; + UINT32 CmdToken:8; // 0xff tells MCU not to report CmdDoneInt after excuting the command + UINT32 HighByte:8; + UINT32 LowByte:8; + } field; + UINT32 word; +} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC; +#else +typedef union _H2M_MAILBOX_STRUC { + struct { + UINT32 LowByte:8; + UINT32 HighByte:8; + UINT32 CmdToken:8; + UINT32 Owner:8; + } field; + UINT32 word; +} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC; +#endif + +// +// M2H_CMD_DONE_CSR: MCU-to-Host command complete indication +// +#ifdef RT_BIG_ENDIAN +typedef union _M2H_CMD_DONE_STRUC { + struct { + UINT32 CmdToken3; + UINT32 CmdToken2; + UINT32 CmdToken1; + UINT32 CmdToken0; + } field; + UINT32 word; +} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC; +#else +typedef union _M2H_CMD_DONE_STRUC { + struct { + UINT32 CmdToken0; + UINT32 CmdToken1; + UINT32 CmdToken2; + UINT32 CmdToken3; + } field; + UINT32 word; +} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC; +#endif + + + +// +// MCU_LEDCS: MCU LED Control Setting. +// +#ifdef RT_BIG_ENDIAN +typedef union _MCU_LEDCS_STRUC { + struct { + UCHAR Polarity:1; + UCHAR LedMode:7; + } field; + UCHAR word; +} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC; +#else +typedef union _MCU_LEDCS_STRUC { + struct { + UCHAR LedMode:7; + UCHAR Polarity:1; + } field; + UCHAR word; +} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC; +#endif +// ================================================================================= +// Register format +// ================================================================================= + + + +//NAV_TIME_CFG :NAV +#ifdef RT_BIG_ENDIAN +typedef union _NAV_TIME_CFG_STRUC { + struct { + USHORT rsv:6; + USHORT ZeroSifs:1; // Applied zero SIFS timer after OFDM RX 0: disable + USHORT Eifs:9; // in unit of 1-us + UCHAR SlotTime; // in unit of 1-us + UCHAR Sifs; // in unit of 1-us + } field; + UINT32 word; +} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; +#else +typedef union _NAV_TIME_CFG_STRUC { + struct { + UCHAR Sifs; // in unit of 1-us + UCHAR SlotTime; // in unit of 1-us + USHORT Eifs:9; // in unit of 1-us + USHORT ZeroSifs:1; // Applied zero SIFS timer after OFDM RX 0: disable + USHORT rsv:6; + } field; + UINT32 word; +} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC; +#endif + + + + + +// +// RX_FILTR_CFG: /RX configuration register +// +#ifdef RT_BIG_ENDIAN +typedef union RX_FILTR_CFG_STRUC { + struct { + UINT32 :15; + UINT32 DropRsvCntlType:1; + + UINT32 DropBAR:1; // + UINT32 DropBA:1; // + UINT32 DropPsPoll:1; // Drop Ps-Poll + UINT32 DropRts:1; // Drop Ps-Poll + + UINT32 DropCts:1; // Drop Ps-Poll + UINT32 DropAck:1; // Drop Ps-Poll + UINT32 DropCFEnd:1; // Drop Ps-Poll + UINT32 DropCFEndAck:1; // Drop Ps-Poll + + UINT32 DropDuplicate:1; // Drop duplicate frame + UINT32 DropBcast:1; // Drop broadcast frames + UINT32 DropMcast:1; // Drop multicast frames + UINT32 DropVerErr:1; // Drop version error frame + + UINT32 DropNotMyBSSID:1; // Drop fram ToDs bit is true + UINT32 DropNotToMe:1; // Drop not to me unicast frame + UINT32 DropPhyErr:1; // Drop physical error + UINT32 DropCRCErr:1; // Drop CRC error + } field; + UINT32 word; +} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC; +#else +typedef union _RX_FILTR_CFG_STRUC { + struct { + UINT32 DropCRCErr:1; // Drop CRC error + UINT32 DropPhyErr:1; // Drop physical error + UINT32 DropNotToMe:1; // Drop not to me unicast frame + UINT32 DropNotMyBSSID:1; // Drop fram ToDs bit is true + + UINT32 DropVerErr:1; // Drop version error frame + UINT32 DropMcast:1; // Drop multicast frames + UINT32 DropBcast:1; // Drop broadcast frames + UINT32 DropDuplicate:1; // Drop duplicate frame + + UINT32 DropCFEndAck:1; // Drop Ps-Poll + UINT32 DropCFEnd:1; // Drop Ps-Poll + UINT32 DropAck:1; // Drop Ps-Poll + UINT32 DropCts:1; // Drop Ps-Poll + + UINT32 DropRts:1; // Drop Ps-Poll + UINT32 DropPsPoll:1; // Drop Ps-Poll + UINT32 DropBA:1; // + UINT32 DropBAR:1; // + + UINT32 DropRsvCntlType:1; + UINT32 :15; + } field; + UINT32 word; +} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC; +#endif + + + + +// +// PHY_CSR4: RF serial control register +// +#ifdef RT_BIG_ENDIAN +typedef union _PHY_CSR4_STRUC { + struct { + UINT32 Busy:1; // 1: ASIC is busy execute RF programming. + UINT32 PLL_LD:1; // RF PLL_LD status + UINT32 IFSelect:1; // 1: select IF to program, 0: select RF to program + UINT32 NumberOfBits:5; // Number of bits used in RFRegValue (I:20, RFMD:22) + UINT32 RFRegValue:24; // Register value (include register id) serial out to RF/IF chip. + } field; + UINT32 word; +} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; +#else +typedef union _PHY_CSR4_STRUC { + struct { + UINT32 RFRegValue:24; // Register value (include register id) serial out to RF/IF chip. + UINT32 NumberOfBits:5; // Number of bits used in RFRegValue (I:20, RFMD:22) + UINT32 IFSelect:1; // 1: select IF to program, 0: select RF to program + UINT32 PLL_LD:1; // RF PLL_LD status + UINT32 Busy:1; // 1: ASIC is busy execute RF programming. + } field; + UINT32 word; +} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC; +#endif + + +// +// SEC_CSR5: shared key table security mode register +// +#ifdef RT_BIG_ENDIAN +typedef union _SEC_CSR5_STRUC { + struct { + UINT32 :1; + UINT32 Bss3Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key0CipherAlg:3; + } field; + UINT32 word; +} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC; +#else +typedef union _SEC_CSR5_STRUC { + struct { + UINT32 Bss2Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss2Key3CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key0CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key1CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key2CipherAlg:3; + UINT32 :1; + UINT32 Bss3Key3CipherAlg:3; + UINT32 :1; + } field; + UINT32 word; +} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC; +#endif + + +// +// HOST_CMD_CSR: For HOST to interrupt embedded processor +// +#ifdef RT_BIG_ENDIAN +typedef union _HOST_CMD_CSR_STRUC { + struct { + UINT32 Rsv:24; + UINT32 HostCommand:8; + } field; + UINT32 word; +} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC; +#else +typedef union _HOST_CMD_CSR_STRUC { + struct { + UINT32 HostCommand:8; + UINT32 Rsv:24; + } field; + UINT32 word; +} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC; +#endif + + +// +// AIFSN_CSR: AIFSN for each EDCA AC +// + + + +// +// E2PROM_CSR: EEPROM control register +// +#ifdef RT_BIG_ENDIAN +typedef union _E2PROM_CSR_STRUC { + struct { + UINT32 Rsvd:25; + UINT32 LoadStatus:1; // 1:loading, 0:done + UINT32 Type:1; // 1: 93C46, 0:93C66 + UINT32 EepromDO:1; + UINT32 EepromDI:1; + UINT32 EepromCS:1; + UINT32 EepromSK:1; + UINT32 Reload:1; // Reload EEPROM content, write one to reload, self-cleared. + } field; + UINT32 word; +} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC; +#else +typedef union _E2PROM_CSR_STRUC { + struct { + UINT32 Reload:1; // Reload EEPROM content, write one to reload, self-cleared. + UINT32 EepromSK:1; + UINT32 EepromCS:1; + UINT32 EepromDI:1; + UINT32 EepromDO:1; + UINT32 Type:1; // 1: 93C46, 0:93C66 + UINT32 LoadStatus:1; // 1:loading, 0:done + UINT32 Rsvd:25; + } field; + UINT32 word; +} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC; +#endif + + +// ------------------------------------------------------------------- +// E2PROM data layout +// ------------------------------------------------------------------- + +// +// EEPROM antenna select format +// +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_ANTENNA_STRUC { + struct { + USHORT Rsv:4; + USHORT RfIcType:4; // see E2PROM document + USHORT TxPath:4; // 1: 1T, 2: 2T + USHORT RxPath:4; // 1: 1R, 2: 2R, 3: 3R + } field; + USHORT word; +} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; +#else +typedef union _EEPROM_ANTENNA_STRUC { + struct { + USHORT RxPath:4; // 1: 1R, 2: 2R, 3: 3R + USHORT TxPath:4; // 1: 1T, 2: 2T + USHORT RfIcType:4; // see E2PROM document + USHORT Rsv:4; + } field; + USHORT word; +} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_NIC_CINFIG2_STRUC { + struct { + USHORT DACTestBit:1; // control if driver should patch the DAC issue + USHORT Rsv2:3; // must be 0 + USHORT AntDiversity:1; // Antenna diversity + USHORT Rsv1:1; // must be 0 + USHORT BW40MAvailForA:1; // 0:enable, 1:disable + USHORT BW40MAvailForG:1; // 0:enable, 1:disable + USHORT EnableWPSPBC:1; // WPS PBC Control bit + USHORT BW40MSidebandForA:1; + USHORT BW40MSidebandForG:1; + USHORT CardbusAcceleration:1; // !!! NOTE: 0 - enable, 1 - disable + USHORT ExternalLNAForA:1; // external LNA enable for 5G + USHORT ExternalLNAForG:1; // external LNA enable for 2.4G + USHORT DynamicTxAgcControl:1; // + USHORT HardwareRadioControl:1; // Whether RF is controlled by driver or HW. 1:enable hw control, 0:disable + } field; + USHORT word; +} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; +#else +typedef union _EEPROM_NIC_CINFIG2_STRUC { + struct { + USHORT HardwareRadioControl:1; // 1:enable, 0:disable + USHORT DynamicTxAgcControl:1; // + USHORT ExternalLNAForG:1; // + USHORT ExternalLNAForA:1; // external LNA enable for 2.4G + USHORT CardbusAcceleration:1; // !!! NOTE: 0 - enable, 1 - disable + USHORT BW40MSidebandForG:1; + USHORT BW40MSidebandForA:1; + USHORT EnableWPSPBC:1; // WPS PBC Control bit + USHORT BW40MAvailForG:1; // 0:enable, 1:disable + USHORT BW40MAvailForA:1; // 0:enable, 1:disable + USHORT Rsv1:1; // must be 0 + USHORT AntDiversity:1; // Antenna diversity + USHORT Rsv2:3; // must be 0 + USHORT DACTestBit:1; // control if driver should patch the DAC issue + } field; + USHORT word; +} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC; +#endif + +// +// TX_PWR Value valid range 0xFA(-6) ~ 0x24(36) +// +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_TX_PWR_STRUC { + struct { + CHAR Byte1; // High Byte + CHAR Byte0; // Low Byte + } field; + USHORT word; +} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; +#else +typedef union _EEPROM_TX_PWR_STRUC { + struct { + CHAR Byte0; // Low Byte + CHAR Byte1; // High Byte + } field; + USHORT word; +} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_VERSION_STRUC { + struct { + UCHAR Version; // High Byte + UCHAR FaeReleaseNumber; // Low Byte + } field; + USHORT word; +} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; +#else +typedef union _EEPROM_VERSION_STRUC { + struct { + UCHAR FaeReleaseNumber; // Low Byte + UCHAR Version; // High Byte + } field; + USHORT word; +} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_LED_STRUC { + struct { + USHORT Rsvd:3; // Reserved + USHORT LedMode:5; // Led mode. + USHORT PolarityGPIO_4:1; // Polarity GPIO#4 setting. + USHORT PolarityGPIO_3:1; // Polarity GPIO#3 setting. + USHORT PolarityGPIO_2:1; // Polarity GPIO#2 setting. + USHORT PolarityGPIO_1:1; // Polarity GPIO#1 setting. + USHORT PolarityGPIO_0:1; // Polarity GPIO#0 setting. + USHORT PolarityACT:1; // Polarity ACT setting. + USHORT PolarityRDY_A:1; // Polarity RDY_A setting. + USHORT PolarityRDY_G:1; // Polarity RDY_G setting. + } field; + USHORT word; +} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; +#else +typedef union _EEPROM_LED_STRUC { + struct { + USHORT PolarityRDY_G:1; // Polarity RDY_G setting. + USHORT PolarityRDY_A:1; // Polarity RDY_A setting. + USHORT PolarityACT:1; // Polarity ACT setting. + USHORT PolarityGPIO_0:1; // Polarity GPIO#0 setting. + USHORT PolarityGPIO_1:1; // Polarity GPIO#1 setting. + USHORT PolarityGPIO_2:1; // Polarity GPIO#2 setting. + USHORT PolarityGPIO_3:1; // Polarity GPIO#3 setting. + USHORT PolarityGPIO_4:1; // Polarity GPIO#4 setting. + USHORT LedMode:5; // Led mode. + USHORT Rsvd:3; // Reserved + } field; + USHORT word; +} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_TXPOWER_DELTA_STRUC { + struct { + UCHAR TxPowerEnable:1;// Enable + UCHAR Type:1; // 1: plus the delta value, 0: minus the delta value + UCHAR DeltaValue:6; // Tx Power dalta value (MAX=4) + } field; + UCHAR value; +} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; +#else +typedef union _EEPROM_TXPOWER_DELTA_STRUC { + struct { + UCHAR DeltaValue:6; // Tx Power dalta value (MAX=4) + UCHAR Type:1; // 1: plus the delta value, 0: minus the delta value + UCHAR TxPowerEnable:1;// Enable + } field; + UCHAR value; +} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC; +#endif + +// +// QOS_CSR0: TXOP holder address0 register +// +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR0_STRUC { + struct { + UCHAR Byte3; // MAC address byte 3 + UCHAR Byte2; // MAC address byte 2 + UCHAR Byte1; // MAC address byte 1 + UCHAR Byte0; // MAC address byte 0 + } field; + UINT32 word; +} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; +#else +typedef union _QOS_CSR0_STRUC { + struct { + UCHAR Byte0; // MAC address byte 0 + UCHAR Byte1; // MAC address byte 1 + UCHAR Byte2; // MAC address byte 2 + UCHAR Byte3; // MAC address byte 3 + } field; + UINT32 word; +} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC; +#endif + +// +// QOS_CSR1: TXOP holder address1 register +// +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR1_STRUC { + struct { + UCHAR Rsvd1; + UCHAR Rsvd0; + UCHAR Byte5; // MAC address byte 5 + UCHAR Byte4; // MAC address byte 4 + } field; + UINT32 word; +} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; +#else +typedef union _QOS_CSR1_STRUC { + struct { + UCHAR Byte4; // MAC address byte 4 + UCHAR Byte5; // MAC address byte 5 + UCHAR Rsvd0; + UCHAR Rsvd1; + } field; + UINT32 word; +} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC; +#endif + +#define RF_CSR_CFG 0x500 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG_STRUC { + struct { + UINT Rsvd1:14; // Reserved + UINT RF_CSR_KICK:1; // kick RF register read/write + UINT RF_CSR_WR:1; // 0: read 1: write + UINT Rsvd2:3; // Reserved + UINT TESTCSR_RFACC_REGNUM:5; // RF register ID + UINT RF_CSR_DATA:8; // DATA + } field; + UINT word; +} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; +#else +typedef union _RF_CSR_CFG_STRUC { + struct { + UINT RF_CSR_DATA:8; // DATA + UINT TESTCSR_RFACC_REGNUM:5; // RF register ID + UINT Rsvd2:3; // Reserved + UINT RF_CSR_WR:1; // 0: read 1: write + UINT RF_CSR_KICK:1; // kick RF register read/write + UINT Rsvd1:14; // Reserved + } field; + UINT word; +} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC; +#endif + +#endif // __RT28XX_H__ diff --git a/drivers/staging/rt3070/rt_ate.c b/drivers/staging/rt3070/rt_ate.c new file mode 100644 index 000000000000..9238d960121c --- /dev/null +++ b/drivers/staging/rt3070/rt_ate.c @@ -0,0 +1,6506 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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 "rt_config.h" + +#ifdef UCOS +INT IoctlResponse(PUCHAR payload, PUCHAR msg, INT len); +#endif // UCOS // + +#define ATE_BBP_REG_NUM 168 +UCHAR restore_BBP[ATE_BBP_REG_NUM]={0}; + +#ifdef RALINK_ATE +UCHAR TemplateFrame[24] = {0x08/* Data type */,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xAA,0xBB,0x12,0x34,0x56,0x00,0x11,0x22,0xAA,0xBB,0xCC,0x00,0x00}; // 802.11 MAC Header, Type:Data, Length:24bytes +extern RTMP_RF_REGS RF2850RegTable[]; +extern UCHAR NUM_OF_2850_CHNL; + +#ifdef RT2870 +extern UCHAR EpToQueue[]; +extern VOID RTUSBRejectPendingPackets( IN PRTMP_ADAPTER pAd); +#endif // RT2870 // + +#ifdef RT30xx +//2008/07/10:KH adds to support 3070 ATE<-- +extern FREQUENCY_ITEM FreqItems3020[]; +extern UCHAR NUM_OF_3020_CHNL; +//2008/07/10:KH adds to support 3070 ATE--> +#endif // RT30xx // + +#ifdef UCOS +extern INT ConsoleResponse(IN PUCHAR buff); +extern int (*remote_display)(char *); +#endif // UCOS // + +static CHAR CCKRateTable[] = {0, 1, 2, 3, 8, 9, 10, 11, -1}; /* CCK Mode. */ +static CHAR OFDMRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, -1}; /* OFDM Mode. */ +static CHAR HTMIXRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}; /* HT Mix Mode. */ + +static INT TxDmaBusy( + IN PRTMP_ADAPTER pAd); + +static INT RxDmaBusy( + IN PRTMP_ADAPTER pAd); + +static VOID RtmpDmaEnable( + IN PRTMP_ADAPTER pAd, + IN INT Enable); + +static VOID BbpSoftReset( + IN PRTMP_ADAPTER pAd); + +static VOID RtmpRfIoWrite( + IN PRTMP_ADAPTER pAd); + +static INT ATESetUpFrame( + IN PRTMP_ADAPTER pAd, + IN UINT32 TxIdx); + +static INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); + +static INT ATECmdHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +static int CheckMCSValid( + IN UCHAR Mode, + IN UCHAR Mcs); + + +#ifdef RT2870 +static VOID ATEWriteTxInfo( + IN PRTMP_ADAPTER pAd, + IN PTXINFO_STRUC pTxInfo, + IN USHORT USBDMApktLen, + IN BOOLEAN bWiv, + IN UCHAR QueueSel, + IN UCHAR NextValid, + IN UCHAR TxBurst); + +static VOID ATEWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR MIMOps, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING Transmit); + +#endif // RT2870 // + +static VOID SetJapanFilter( + IN PRTMP_ADAPTER pAd); + +/*=========================end of prototype=========================*/ + + +#ifdef RT2870 +static INT TxDmaBusy( + IN PRTMP_ADAPTER pAd) +{ + INT result; + USB_DMA_CFG_STRUC UsbCfg; + + RTMP_IO_READ32(pAd, USB_DMA_CFG, &UsbCfg.word); // disable DMA + if (UsbCfg.field.TxBusy) + result = 1; + else + result = 0; + + return result; +} + +static INT RxDmaBusy( + IN PRTMP_ADAPTER pAd) +{ + INT result; + USB_DMA_CFG_STRUC UsbCfg; + + RTMP_IO_READ32(pAd, USB_DMA_CFG, &UsbCfg.word); // disable DMA + if (UsbCfg.field.RxBusy) + result = 1; + else + result = 0; + + return result; +} + +static VOID RtmpDmaEnable( + IN PRTMP_ADAPTER pAd, + IN INT Enable) +{ + BOOLEAN value; + ULONG WaitCnt; + USB_DMA_CFG_STRUC UsbCfg; + + value = Enable > 0 ? 1 : 0; + + // check DMA is in busy mode. + WaitCnt = 0; + while (TxDmaBusy(pAd) || RxDmaBusy(pAd)) + { + RTMPusecDelay(10); + if (WaitCnt++ > 100) + break; + } + + //Why not to clear USB DMA TX path first ??? + RTMP_IO_READ32(pAd, USB_DMA_CFG, &UsbCfg.word); // disable DMA + UsbCfg.field.TxBulkEn = value; + UsbCfg.field.RxBulkEn = value; + RTMP_IO_WRITE32(pAd, USB_DMA_CFG, UsbCfg.word); // abort all TX rings + RTMPusecDelay(5000); + + return; +} +#endif // RT2870 // + +static VOID BbpSoftReset( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpData = 0; + + // Soft reset, set BBP R21 bit0=1->0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); + BbpData |= 0x00000001; //set bit0=1 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData); + BbpData &= ~(0x00000001); //set bit0=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData); + + return; +} + +static VOID RtmpRfIoWrite( + IN PRTMP_ADAPTER pAd) +{ + // Set RF value 1's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 2's set R3[bit2] = [1] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04)); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + RTMPusecDelay(200); + + // Set RF value 3's set R3[bit2] = [0] + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04))); + RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4); + + return; +} + +static int CheckMCSValid( + UCHAR Mode, + UCHAR Mcs) +{ + int i; + PCHAR pRateTab; + + switch(Mode) + { + case 0: + pRateTab = CCKRateTable; + break; + case 1: + pRateTab = OFDMRateTable; + break; + case 2: + case 3: + pRateTab = HTMIXRateTable; + break; + default: + ATEDBGPRINT(RT_DEBUG_ERROR, ("unrecognizable Tx Mode %d\n", Mode)); + return -1; + break; + } + + i = 0; + while(pRateTab[i] != -1) + { + if (pRateTab[i] == Mcs) + return 0; + i++; + } + + return -1; +} + +#if 1 +static INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + ULONG R; + CHAR TxPower; + UCHAR Bbp94 = 0; + BOOLEAN bPowerReduce = FALSE; +#ifdef RT30xx + UCHAR RFValue; +#endif // RT30xx // +#ifdef RALINK_28xx_QA + if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) + { + /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power + ** are not synchronized. + */ +/* + pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx; + pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx; +*/ + return 0; + } + else +#endif // RALINK_28xx_QA // + { + TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1; + + if (pAd->ate.Channel <= 14) + { + if (TxPower > 31) + { + // + // R3, R4 can't large than 31 (0x24), 31 ~ 36 used by BBP 94 + // + R = 31; + if (TxPower <= 36) + Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31); + } + else if (TxPower < 0) + { + // + // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94 + // + R = 0; + if (TxPower >= -6) + Bbp94 = BBPR94_DEFAULT + TxPower; + } + else + { + // 0 ~ 31 + R = (ULONG) TxPower; + Bbp94 = BBPR94_DEFAULT; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94)); + } + else// 5.5 GHz + { + if (TxPower > 15) + { + // + // R3, R4 can't large than 15 (0x0F) + // + R = 15; + } + else if (TxPower < 0) + { + // + // R3, R4 can't less than 0 + // + // -1 ~ -7 + ASSERT((TxPower >= -7)); + R = (ULONG)(TxPower + 7); + bPowerReduce = TRUE; + } + else + { + // 0 ~ 15 + R = (ULONG) TxPower; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%lu)\n", __FUNCTION__, TxPower, R)); + } +//2008/09/10:KH adds to support 3070 ATE TX Power tunning real time<-- +#ifdef RT30xx + if(IS_RT30xx(pAd)) + { + // Set Tx Power + + RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPower; + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue); + ATEDBGPRINT(RT_DEBUG_TRACE, ("3070 or 2070:%s (TxPower=%d, RFValue=%x)\n", __FUNCTION__, TxPower, RFValue)); + + } + else +#endif // RT30xx // + { + if (pAd->ate.Channel <= 14) + { + if (index == 0) + { + R = R << 9; // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = R << 6; // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else// 5.5GHz + { + if (bPowerReduce == FALSE) + { + if (index == 0) + { + R = (R << 10) | (1 << 9); // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = (R << 7) | (1 << 6); // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else + { + if (index == 0) + { + R = (R << 10); // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + + /* Clear bit 9 of R3 to reduce 7dB. */ + pAd->LatchRfRegs.R3 = (R & (~(1 << 9))); + } + else + { + R = (R << 7); // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + + /* Clear bit 6 of R4 to reduce 7dB. */ + pAd->LatchRfRegs.R4 = (R & (~(1 << 6))); + } + } + } + RtmpRfIoWrite(pAd); + } +//2008/09/10:KH adds to support 3070 ATE TX Power tunning real time--> + + return 0; + } +} +#else// 1 // +static INT ATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index) +{ + ULONG R; + CHAR TxPower; + UCHAR Bbp94 = 0; + +#ifdef RALINK_28xx_QA + if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) + { + // TODO: how to get current TxPower0/1 from pAd->LatchRfRegs ? + /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power + ** are not synchronized. + */ +/* + pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx; + pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx; +*/ + return 0; + } + else +#endif // RALINK_28xx_QA // + { + TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1; + + if (TxPower > 31) + { + // + // R3, R4 can't large than 36 (0x24), 31 ~ 36 used by BBP 94 + // + R = 31; + if (TxPower <= 36) + Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31); + } + else if (TxPower < 0) + { + // + // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94 + // + R = 0; + if (TxPower >= -6) + Bbp94 = BBPR94_DEFAULT + TxPower; + } + else + { + // 0 ~ 31 + R = (ULONG) TxPower; + Bbp94 = BBPR94_DEFAULT; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R3=%ld, BBP_R94=%d)\n", __FUNCTION__, TxPower, R, Bbp94)); + + if (pAd->ate.Channel <= 14) + { + if (index == 0) + { + R = R << 9; // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = R << 6; // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + else + { + if (index == 0) + { + R = (R << 10) | (1 << 9); // shift TX power control to correct RF(R3) register bit position + R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff); + pAd->LatchRfRegs.R3 = R; + } + else + { + R = (R << 7) | (1 << 6); // shift TX power control to correct RF(R4) register bit position + R |= (pAd->LatchRfRegs.R4 & 0xfffff83f); + pAd->LatchRfRegs.R4 = R; + } + } + + RtmpRfIoWrite(pAd); + + return 0; + } +} +#endif // 1 // +/* + ========================================================================== + Description: + Set ATE operation mode to + 0. ATESTART = Start ATE Mode + 1. ATESTOP = Stop ATE Mode + 2. TXCONT = Continuous Transmit + 3. TXCARR = Transmit Carrier + 4. TXFRAME = Transmit Frames + 5. RXFRAME = Receive Frames +#ifdef RALINK_28xx_QA + 6. TXSTOP = Stop Any Type of Transmition + 7. RXSTOP = Stop Receiving Frames +#endif // RALINK_28xx_QA // + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +/* */ +/* */ +/*=======================End of RT2860=======================*/ + + +/*======================Start of RT2870======================*/ +/* */ +/* */ + +#ifdef RT2870 +static INT ATECmdHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT32 Value; + UCHAR BbpData; + UINT32 MacData; + UINT i=0, atemode; + //NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + //PUCHAR pDest; + UINT32 temp; + ULONG IrqFlags; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("===> ATECmdHandler()\n")); + ATEAsicSwitchChannel(pAd); + /* AsicLockChannel() is empty function so far in fact */ + AsicLockChannel(pAd, pAd->ate.Channel); + + RTMPusecDelay(5000); + + // Default value in BBP R22 is 0x0. + BbpData = 0; + + /* Enter ATE mode and set Tx/Rx Idle */ + if (!strcmp(arg, "ATESTART")) + { +#ifdef CONFIG_STA_SUPPORT + BOOLEAN Cancelled; +#endif // CONFIG_STA_SUPPORT // + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: ATESTART\n")); + + netif_stop_queue(pAd->net_dev); + + atemode = pAd->ate.Mode; + pAd->ate.Mode = ATE_START; +// pAd->ate.TxDoneCount = pAd->ate.TxCount; + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Disable auto responder + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &temp); + temp = temp & 0xFFFFFFFE; + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, temp); + + // read MAC_SYS_CTRL and backup MAC_SYS_CTRL value. + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + // clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + // Stop continuous TX production test. + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);//disable or cancel pending irp first ??? + + if (atemode & ATE_TXCARR +#ifdef RT30xx + || atemode & ATE_TXCONT +#endif // RT30xx // +) + { +#ifdef RT30xx + //Hardware Reset BBP + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &temp); + temp = temp |0x00000002; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, temp); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &temp); + temp = temp & ~(0x00000002); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, temp); + //Restore All BBP Value + for(i=0;iMlmeAux.AssocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled); +#endif // CONFIG_STA_SUPPORT // + + //RTUSBCleanUpMLMEWaitQueue(pAd); /* not used in RT28xx */ + RTUSBCleanUpMLMEBulkOutQueue(pAd); + + // Sometimes kernel will hang on, so we avoid calling MlmeSuspend(). +// MlmeSuspend(pAd, TRUE); + //RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + // Disable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Make sure there are no pending bulk in/out IRPs before we go on. +/*=========================================================================*/ + /* pAd->PendingRx is not of type atomic_t anymore in 28xx */ +// while ((atomic_read(&pAd->PendingRx) > 0)) //pAd->BulkFlags != 0 wait bulk out finish + while ((pAd->PendingRx > 0)) //pAd->BulkFlags != 0 wait bulk out finish + { +#if 1 + ATE_RTUSBCancelPendingBulkInIRP(pAd); +#else + NdisInterlockedDecrement(&pAd->PendingRx); +#endif + /* delay 0.5 seconds */ + RTMPusecDelay(500000); + pAd->PendingRx = 0; + } + /* peter : why don't we have to get BulkOutLock first ? */ + while (((pAd->BulkOutPending[0] == TRUE) || + (pAd->BulkOutPending[1] == TRUE) || + (pAd->BulkOutPending[2] == TRUE) || + (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0)) //pAd->BulkFlags != 0 wait bulk out finish + { + do + { + /* pAd->BulkOutPending[y] will be set to FALSE in RTUSBCancelPendingBulkOutIRP(pAd) */ + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + + /* we have enough time delay in RTUSBCancelPendingBulkOutIRP(pAd) + ** so this is not necessary + */ +// RTMPusecDelay(500000); + } + + /* pAd->PendingRx is not of type atomic_t anymore in 28xx */ +// ASSERT(atomic_read(&pAd->PendingRx) == 0); + ASSERT(pAd->PendingRx == 0); +/*=========================================================================*/ + + // reset Rx statistics. + pAd->ate.LastSNR0 = 0; + pAd->ate.LastSNR1 = 0; + pAd->ate.LastRssi0 = 0; + pAd->ate.LastRssi1 = 0; + pAd->ate.LastRssi2 = 0; + pAd->ate.AvgRssi0 = 0; + pAd->ate.AvgRssi1 = 0; + pAd->ate.AvgRssi2 = 0; + pAd->ate.AvgRssi0X8 = 0; + pAd->ate.AvgRssi1X8 = 0; + pAd->ate.AvgRssi2X8 = 0; + pAd->ate.NumOfAvgRssiSample = 0; + +#ifdef RALINK_28xx_QA + // Tx frame + pAd->ate.bQATxStart = FALSE; + pAd->ate.bQARxStart = FALSE; + pAd->ate.seq = 0; + + // counters + pAd->ate.U2M = 0; + pAd->ate.OtherData = 0; + pAd->ate.Beacon = 0; + pAd->ate.OtherCount = 0; + pAd->ate.TxAc0 = 0; + pAd->ate.TxAc1 = 0; + pAd->ate.TxAc2 = 0; + pAd->ate.TxAc3 = 0; + pAd->ate.TxHCCA = 0; + pAd->ate.TxMgmt = 0; + pAd->ate.RSSI0 = 0; + pAd->ate.RSSI1 = 0; + pAd->ate.RSSI2 = 0; + pAd->ate.SNR0 = 0; + pAd->ate.SNR1 = 0; + + // control + pAd->ate.TxDoneCount = 0; + pAd->ate.TxStatus = 0; // task Tx status // 0 --> task is idle, 1 --> task is running +#endif // RALINK_28xx_QA // + + // Soft reset BBP. + BbpSoftReset(pAd); + + +#ifdef CONFIG_STA_SUPPORT + AsicDisableSync(pAd); + + /* + ** If we skip "LinkDown()", we should disable protection + ** to prevent from sending out RTS or CTS-to-self. + */ + ATEDisableAsicProtect(pAd); + RTMPStationStop(pAd); +#endif // CONFIG_STA_SUPPORT // + + // Default value in BBP R22 is 0x0. + BbpData = 0; + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + + // Clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + //Clean ATE Bulk in/out counter and continue setup + InterlockedExchange(&pAd->BulkOutRemained, 0); + + /* NdisAcquireSpinLock()/NdisReleaseSpinLock() need only one argument in RT28xx */ + NdisAcquireSpinLock(&pAd->GenericLock); + pAd->ContinBulkOut = FALSE; + pAd->ContinBulkIn = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + } + else if (!strcmp(arg, "ATESTOP")) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE : ATESTOP ===>\n")); + + // Default value in BBP R22 is 0x0. + BbpData = 0; + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);//0820 + // Clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); // recover the MAC_SYS_CTRL register back. + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + /* + ** Abort Tx, RX DMA. + ** Q : How to do the following I/O if Tx, Rx DMA is aborted ? + ** Ans : Bulk endpoints are aborted, while the control endpoint is not. + */ + RtmpDmaEnable(pAd, 0); + + // Disable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + /* Make sure there are no pending bulk in/out IRPs before we go on. */ +/*=========================================================================*/ +// while ((atomic_read(&pAd->PendingRx) > 0)) //pAd->BulkFlags != 0 wait bulk out finish + while (pAd->PendingRx > 0) + { +#if 1 + ATE_RTUSBCancelPendingBulkInIRP(pAd); +#else +// NdisInterlockedDecrement(&pAd->PendingRx); + pAd->PendingRx--; +#endif + RTMPusecDelay(500000); + } + + while (((pAd->BulkOutPending[0] == TRUE) || + (pAd->BulkOutPending[1] == TRUE) || + (pAd->BulkOutPending[2] == TRUE) || + (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0)) //pAd->BulkFlags != 0 wait bulk out finish + { + do + { + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + + RTMPusecDelay(500000); + } + +// ASSERT(atomic_read(&pAd->PendingRx) == 0); + ASSERT(pAd->PendingRx == 0); +/*=========================================================================*/ +/* Reset Rx RING */ +/*=========================================================================*/ +// InterlockedExchange(&pAd->PendingRx, 0); + pAd->PendingRx = 0; + pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index + pAd->NextRxBulkInIndex = RX_RING_SIZE - 1; // Rx Bulk pointer + pAd->NextRxBulkInPosition = 0; + for (i = 0; i < (RX_RING_SIZE); i++) + { + PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE); + /* peter : why don't we have to get BulkInLock first ? */ + pRxContext->pAd = pAd; + pRxContext->pIrp = NULL; + /* peter debug ++ */ + pRxContext->BulkInOffset = 0; + pRxContext->bRxHandling = FALSE; + /* peter debug -- */ + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; +// pRxContext->ReorderInUse = FALSE; +// pRxContext->ReadPosOffset = 0; + } + +/*=========================================================================*/ +/* Reset Tx RING */ +/*=========================================================================*/ + do + { + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + +/*=========================================================================*/ + // Enable auto responder. + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &temp); + temp = temp | (0x01); + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, temp); + +/*================================================*/ + AsicEnableBssSync(pAd); + + /* Soft reset BBP.*/ + /* In 2870 chipset, ATE_BBP_IO_READ8_BY_REG_ID() == RTMP_BBP_IO_READ8_BY_REG_ID() */ + /* Both rt2870ap and rt2870sta use BbpSoftReset(pAd) to do BBP soft reset */ + BbpSoftReset(pAd); +/*================================================*/ + { +#ifdef CONFIG_STA_SUPPORT + // Set all state machines back IDLE + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE; + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + pAd->Mlme.ActMachine.CurrState = ACT_IDLE; +#endif // CONFIG_STA_SUPPORT // + + // + // ===> refer to MlmeRestartStateMachine(). + // When we entered ATE_START mode, PeriodicTimer was not cancelled. + // So we don't have to set it here. + // + //RTMPSetTimer(pAd, &pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV); + + ASSERT(pAd->CommonCfg.Channel != 0); + + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + +#ifdef CONFIG_STA_SUPPORT + RTMPStationStart(pAd); +#endif // CONFIG_STA_SUPPORT // + } +// +// These two steps have been done when entering ATE_STOP mode. +// + // Clean ATE Bulk in/out counter and continue setup. + InterlockedExchange(&pAd->BulkOutRemained, 0); + NdisAcquireSpinLock(&pAd->GenericLock); + pAd->ContinBulkOut = FALSE; + pAd->ContinBulkIn = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + /* Wait 50ms to prevent next URB to bulkout during HW reset. */ + /* todo : remove this if not necessary */ + NdisMSleep(50000); + + pAd->ate.Mode = ATE_STOP; + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + +/*=========================================================================*/ + /* restore RX_FILTR_CFG */ +#ifdef CONFIG_STA_SUPPORT + /* restore RX_FILTR_CFG in order that QA maybe set it to 0x3 */ + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); +#endif // CONFIG_STA_SUPPORT // +/*=========================================================================*/ + + // Enable Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + // Enable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Wait 10ms to wait all of the bulk-in URBs to complete. + /* todo : remove this if not necessary */ + NdisMSleep(10000); + + // Everything is ready to start normal Tx/Rx. + RTUSBBulkReceive(pAd); + netif_start_queue(pAd->net_dev); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== ATE : ATESTOP \n")); + } + else if (!strcmp(arg, "TXCARR")) // Tx Carrier + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCARR\n")); + pAd->ate.Mode |= ATE_TXCARR; + +#ifdef RT30xx + for(i=0;iate.bQATxStart == FALSE) + { + // Soft reset BBP. + BbpSoftReset(pAd); + + // Carrier Test set BBP R22 bit7=1, bit6=1, bit[5~0]=0x01 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] + BbpData |= 0x000000C1; //set bit7=1, bit6=1, bit[5~0]=0x01 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + // set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1 + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value = Value | 0x00000010; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } + } + else if (!strcmp(arg, "TXCONT")) // Tx Continue + { + if (pAd->ate.bQATxStart == TRUE) + { + /* set MAC_SYS_CTRL(0x1004) bit4(Continuous Tx Production Test) + and bit2(MAC TX enable) back to zero. */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData &= 0xFFFFFFEB; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + // set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF7F; //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + + /* for TxCont mode. + ** Step 1: Send 50 packets first then wait for a moment. + ** Step 2: Send more 50 packet then start continue mode. + */ + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCONT\n")); + +#ifdef RT30xx + for(i=0;iate.Mode |= ATE_TXCONT; + pAd->ate.TxCount = 50; + pAd->ate.TxDoneCount = 0; + + // Soft reset BBP. + BbpSoftReset(pAd); + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + + /* Only needed if we have to send some normal frames. */ + SetJapanFilter(pAd); + + // Setup frame format. + ATESetUpFrame(pAd, 0); + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Start Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + InterlockedExchange(&pAd->BulkOutRemained, pAd->ate.TxCount); + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + pAd->ate.TxStatus = 1; + //pAd->ate.Repeat = 0; + } +#endif // RALINK_28xx_QA // + + NdisAcquireSpinLock(&pAd->GenericLock);//0820 + pAd->ContinBulkOut = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + + // Kick bulk out + RTUSBKickBulkOut(pAd); + + /* To make sure all the 50 frames have been bulk out before executing step 2 */ + while (atomic_read(&pAd->BulkOutRemained) > 0) + { + RTMPusecDelay(5000); + } + + // Step 2: send more 50 packets then start continue mode. + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + // Cont. TX set BBP R22 bit7=1 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData |= 0x00000080; //set bit7=1 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + pAd->ate.TxCount = 50; + pAd->ate.TxDoneCount = 0; + + SetJapanFilter(pAd); + + // Setup frame format. + ATESetUpFrame(pAd, 0); + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + + // Start Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + InterlockedExchange(&pAd->BulkOutRemained, pAd->ate.TxCount); + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + pAd->ate.TxStatus = 1; + //pAd->ate.Repeat = 0; + } +#endif // RALINK_28xx_QA // + + NdisAcquireSpinLock(&pAd->GenericLock);//0820 + pAd->ContinBulkOut = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + // Kick bulk out + RTUSBKickBulkOut(pAd); + +#if 1 + RTMPusecDelay(500); +#else + while (atomic_read(&pAd->BulkOutRemained) > 0) + { + RTMPusecDelay(5000); + } +#endif // 1 // + + // Set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1. + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData |= 0x00000010; + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + } + else if (!strcmp(arg, "TXFRAME")) // Tx Frames + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXFRAME(Count=0x%08x)\n", pAd->ate.TxCount)); + pAd->ate.Mode |= ATE_TXFRAME; + + // Soft reset BBP. + BbpSoftReset(pAd); + + // Default value in BBP R22 is 0x0. + BbpData = 0; + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + + // Clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + +#ifdef RALINK_28xx_QA + // add this for LoopBack mode + if (pAd->ate.bQARxStart == FALSE) + { + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + } + + if (pAd->ate.bQATxStart == TRUE) + { + pAd->ate.TxStatus = 1; + //pAd->ate.Repeat = 0; + } +#else + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); +#endif // RALINK_28xx_QA // + + // Enable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + SetJapanFilter(pAd); + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + pAd->ate.TxDoneCount = 0; + + // Setup frame format + ATESetUpFrame(pAd, 0); + + // Start Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + // Check count is continuous or not yet. + // + // Due to the type mismatch between "pAd->BulkOutRemained"(atomic_t) and "pAd->ate.TxCount"(UINT32) + // + if (pAd->ate.TxCount == 0) + { + InterlockedExchange(&pAd->BulkOutRemained, 0); + } + else + { + InterlockedExchange(&pAd->BulkOutRemained, pAd->ate.TxCount); + } + ATEDBGPRINT(RT_DEBUG_TRACE, ("bulk out count = %d\n", atomic_read(&pAd->BulkOutRemained))); + ASSERT((atomic_read(&pAd->BulkOutRemained) >= 0)); + + if (atomic_read(&pAd->BulkOutRemained) == 0) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Send packet countinuously\n")); + + /* In 28xx, NdisAcquireSpinLock() == spin_lock_bh() */ + /* NdisAcquireSpinLock only need one argument in 28xx. */ + NdisAcquireSpinLock(&pAd->GenericLock); + pAd->ContinBulkOut = TRUE; + NdisReleaseSpinLock(&pAd->GenericLock); + + /* In 28xx, BULK_OUT_LOCK() == spin_lock_irqsave() */ + BULK_OUT_LOCK(&pAd->BulkOutLock[0], IrqFlags);// peter : NdisAcquireSpinLock ==> BULK_OUT_LOCK + pAd->BulkOutPending[0] = FALSE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);// peter : NdisAcquireSpinLock ==> BULK_OUT_LOCK + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Send packets depend on counter\n")); + + NdisAcquireSpinLock(&pAd->GenericLock); + pAd->ContinBulkOut = FALSE; + NdisReleaseSpinLock(&pAd->GenericLock); + + BULK_OUT_LOCK(&pAd->BulkOutLock[0], IrqFlags); + pAd->BulkOutPending[0] = FALSE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); + } + + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + + // Kick bulk out + RTUSBKickBulkOut(pAd); + } +#ifdef RALINK_28xx_QA + else if (!strcmp(arg, "TXSTOP")) //Enter ATE mode and set Tx/Rx Idle + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXSTOP\n")); + + atemode = pAd->ate.Mode; + pAd->ate.Mode &= ATE_TXSTOP; + pAd->ate.bQATxStart = FALSE; +// pAd->ate.TxDoneCount = pAd->ate.TxCount; + +/*=========================================================================*/ + if (atemode & ATE_TXCARR) + { + // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0] + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + else if (atemode & ATE_TXCARRSUPP) + { + // No Cont. TX set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + + // No Carrier Suppression set BBP R24 bit0=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData); + BbpData &= 0xFFFFFFFE; //clear bit0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData); + } + else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP)) + { + if (atemode & ATE_TXCONT) + { + // No Cont. TX set BBP R22 bit7=0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData); + BbpData &= ~(1 << 7); //set bit7=0 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + } + } + +/*=========================================================================*/ + RTUSBRejectPendingPackets(pAd); + RTUSBCleanUpDataBulkOutQueue(pAd); + + /* not used in RT28xx */ + //RTUSBCleanUpMLMEWaitQueue(pAd); + /* empty function so far */ + RTUSBCleanUpMLMEBulkOutQueue(pAd); +/*=========================================================================*/ + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); +/*=========================================================================*/ + + /* In 28xx, pAd->PendingRx is not of type atomic_t anymore */ +// while ((atomic_read(&pAd->PendingRx) > 0)) //pAd->BulkFlags != 0 wait bulk out finish + /* peter todo : BulkInLock */ + while (pAd->PendingRx > 0) + { +#if 1 + ATE_RTUSBCancelPendingBulkInIRP(pAd); +#else +// NdisInterlockedDecrement(&pAd->PendingRx); + pAd->PendingRx--; +#endif + RTMPusecDelay(500000); + } + + while (((pAd->BulkOutPending[0] == TRUE) || + (pAd->BulkOutPending[1] == TRUE) || + (pAd->BulkOutPending[2] == TRUE) || + (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0)) //pAd->BulkFlags != 0 wait bulk out finish + { + do + { + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + + RTMPusecDelay(500000); + } + + ASSERT(pAd->PendingRx == 0); +/*=========================================================================*/ + // Enable Tx, Rx DMA. + RtmpDmaEnable(pAd, 1); + + /* task Tx status : 0 --> task is idle, 1 --> task is running */ + pAd->ate.TxStatus = 0; + + // Soft reset BBP. + BbpSoftReset(pAd); + + // Disable Tx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + MacData &= (0xfffffffb); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + //Clean ATE Bulk in/out counter and continue setup + InterlockedExchange(&pAd->BulkOutRemained, 0); + + pAd->ContinBulkOut = FALSE; + } + else if (!strcmp(arg, "RXSTOP")) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXSTOP\n")); + atemode = pAd->ate.Mode; + + // Disable Rx + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + pAd->ate.Mode &= ATE_RXSTOP; + pAd->ate.bQARxStart = FALSE; +// pAd->ate.TxDoneCount = pAd->ate.TxCount; + +/*=========================================================================*/ + RTUSBRejectPendingPackets(pAd); + RTUSBCleanUpDataBulkOutQueue(pAd); + + /* not used in RT28xx */ + //RTUSBCleanUpMLMEWaitQueue(pAd); + RTUSBCleanUpMLMEBulkOutQueue(pAd); +/*=========================================================================*/ + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); +/*=========================================================================*/ +// while ((atomic_read(&pAd->PendingRx) > 0)) + while (pAd->PendingRx > 0) + { +#if 1 + ATE_RTUSBCancelPendingBulkInIRP(pAd); +#else +// NdisInterlockedDecrement(&pAd->PendingRx); + pAd->PendingRx--; +#endif + RTMPusecDelay(500000); + } + + while (((pAd->BulkOutPending[0] == TRUE) || + (pAd->BulkOutPending[1] == TRUE) || + (pAd->BulkOutPending[2] == TRUE) || + (pAd->BulkOutPending[3] == TRUE)) && (pAd->BulkFlags != 0)) //pAd->BulkFlags != 0 wait bulk out finish + { + do + { + RTUSBCancelPendingBulkOutIRP(pAd); + } while (FALSE); + + RTMPusecDelay(500000); + } + + ASSERT(pAd->PendingRx == 0); +/*=========================================================================*/ + + // Soft reset BBP. + BbpSoftReset(pAd); + pAd->ContinBulkIn = FALSE; + } +#endif // RALINK_28xx_QA // + else if (!strcmp(arg, "RXFRAME")) // Rx Frames + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXFRAME\n")); + + // Disable Rx of MAC block + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Default value in BBP R22 is 0x0. + BbpData = 0; + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData); + // Clean bit4 to stop continuous Tx production test. + MacData &= 0xFFFFFFEF; + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); + + pAd->ate.Mode |= ATE_RXFRAME; + + // Abort Tx, RX DMA. + RtmpDmaEnable(pAd, 0); + + // Disable TX of MAC block + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Reset Rx RING. + for ( i = 0; i < (RX_RING_SIZE); i++) + { + PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); + + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pRxContext->Readable = FALSE; + + // + // Get the urb from kernel back to driver. + // + RTUSB_UNLINK_URB(pRxContext->pUrb); + + /* Sleep 200 microsecs to give cancellation time to work. */ + NdisMSleep(200); + pAd->BulkInReq = 0; + +// InterlockedExchange(&pAd->PendingRx, 0); + pAd->PendingRx = 0; + pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index + pAd->NextRxBulkInIndex = RX_RING_SIZE - 1; // Rx Bulk pointer + pAd->NextRxBulkInPosition = 0; + } + + // read to clear counters + RTUSBReadMACRegister(pAd, RX_STA_CNT0, &temp); //RX PHY & RX CRC count + RTUSBReadMACRegister(pAd, RX_STA_CNT1, &temp); //RX PLCP error count & CCA false alarm count + RTUSBReadMACRegister(pAd, RX_STA_CNT2, &temp); //RX FIFO overflow frame count & RX duplicated filtered frame count + + pAd->ContinBulkIn = TRUE; + + // Enable Tx, RX DMA. + RtmpDmaEnable(pAd, 1); + + // Enable RX of MAC block + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (1 << 3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + // Kick bulk in + RTUSBBulkReceive(pAd); + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: Invalid arg!\n")); + return FALSE; + } + RTMPusecDelay(5000); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== ATECmdHandler()\n")); + + return TRUE; +} +#endif // RT2870 // + +INT Set_ATE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + if (ATECmdHandler(pAd, arg)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Success\n")); + + + return TRUE; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Failed\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + Set ATE ADDR1=DA for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR3=DA for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_DA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *value; + INT i; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pAd->ate.Addr3[i++], 1); +#endif // CONFIG_STA_SUPPORT // + } + + if(i != 6) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_DA_Proc (DA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr3[0], + pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5])); +#endif // CONFIG_STA_SUPPORT // + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_DA_Proc Success\n")); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE ADDR3=SA for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR2=SA for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_SA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *value; + INT i; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pAd->ate.Addr2[i++], 1); +#endif // CONFIG_STA_SUPPORT // + } + + if(i != 6) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_SA_Proc (SA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr2[0], + pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5])); +#endif // CONFIG_STA_SUPPORT // + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_SA_Proc Success\n")); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE ADDR2=BSSID for TxFrame(AP : To DS = 0 ; From DS = 1) + or + Set ATE ADDR1=BSSID for TxFrame(STA : To DS = 1 ; From DS = 0) + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_BSSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *value; + INT i; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + AtoH(value, &pAd->ate.Addr1[i++], 1); +#endif // CONFIG_STA_SUPPORT // + } + + if(i != 6) + return FALSE; //Invalid + + +#ifdef CONFIG_STA_SUPPORT + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_BSSID_Proc (BSSID = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr1[0], + pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5])); +#endif // CONFIG_STA_SUPPORT // + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_BSSID_Proc Success\n")); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Channel + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_CHANNEL_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR channel; + + channel = simple_strtol(arg, 0, 10); + + if ((channel < 1) || (channel > 216))// to allow A band channel : ((channel < 1) || (channel > 14)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_CHANNEL_Proc::Out of range, it should be in range of 1~14.\n")); + return FALSE; + } + pAd->ate.Channel = channel; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_CHANNEL_Proc (ATE Channel = %d)\n", pAd->ate.Channel)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_CHANNEL_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Power0 + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_POWER0_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR TxPower; + + TxPower = simple_strtol(arg, 0, 10); + + if (pAd->ate.Channel <= 14) + { + if ((TxPower > 31) || (TxPower < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + else// 5.5GHz + { + if ((TxPower > 15) || (TxPower < -7)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + + pAd->ate.TxPower0 = TxPower; + ATETxPwrHandler(pAd, 0); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER0_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Power1 + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_POWER1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR TxPower; + + TxPower = simple_strtol(arg, 0, 10); + + if (pAd->ate.Channel <= 14) + { + if ((TxPower > 31) || (TxPower < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + else + { + if ((TxPower > 15) || (TxPower < -7)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower)); + return FALSE; + } + } + + pAd->ate.TxPower1 = TxPower; + ATETxPwrHandler(pAd, 1); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER1_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx Antenna + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR value; + + value = simple_strtol(arg, 0, 10); + + if ((value > 2) || (value < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_Antenna_Proc::Out of range (Value=%d)\n", value)); + return FALSE; + } + + pAd->ate.TxAntennaSel = value; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_Antenna_Proc (Antenna = %d)\n", pAd->ate.TxAntennaSel)); + ATEDBGPRINT(RT_DEBUG_TRACE,("Ralink: Set_ATE_TX_Antenna_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Rx Antenna + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_RX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR value; + + value = simple_strtol(arg, 0, 10); + + if ((value > 3) || (value < 0)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_RX_Antenna_Proc::Out of range (Value=%d)\n", value)); + return FALSE; + } + + pAd->ate.RxAntennaSel = value; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_Antenna_Proc (Antenna = %d)\n", pAd->ate.RxAntennaSel)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_Antenna_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE RF frequence offset + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_FREQOFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR RFFreqOffset; + ULONG R4; + + RFFreqOffset = simple_strtol(arg, 0, 10); +#ifndef RT30xx + if(RFFreqOffset >= 64) +#endif // RT30xx // +#ifdef RT30xx +//2008/08/06: KH modified the limit of offset value from 65 to 95(0x5F) + if(RFFreqOffset >= 95) +#endif // RT30xx // + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_FREQOFFSET_Proc::Out of range, it should be in range of 0~63.\n")); + return FALSE; + } + + pAd->ate.RFFreqOffset = RFFreqOffset; +#ifdef RT30xx + if(IS_RT30xx(pAd)) + { + // Set RF offset + UCHAR RFValue; + RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue); + //2008/08/06: KH modified "pAd->RFFreqOffset" to "pAd->ate.RFFreqOffset" + RFValue = (RFValue & 0x80) | pAd->ate.RFFreqOffset; + RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue); + } + else +#endif // RT30xx // + { + + R4 = pAd->ate.RFFreqOffset << 15; // shift TX power control to correct RF register bit position + R4 |= (pAd->LatchRfRegs.R4 & ((~0x001f8000))); + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + } + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_FREQOFFSET_Proc (RFFreqOffset = %d)\n", pAd->ate.RFFreqOffset)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_FREQOFFSET_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE RF BW + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + int i; + UCHAR value = 0; + UCHAR BBPCurrentBW; + + BBPCurrentBW = simple_strtol(arg, 0, 10); + + if(BBPCurrentBW == 0) + pAd->ate.TxWI.BW = BW_20; + else + pAd->ate.TxWI.BW = BW_40; + + if(pAd->ate.TxWI.BW == BW_20) + { + if(pAd->ate.Channel <= 14) + { + for (i=0; i<5; i++) + { + if (pAd->Tx20MPwrCfgGBand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgGBand[i]); + RTMPusecDelay(5000); + } + } + } + else + { + for (i=0; i<5; i++) + { + if (pAd->Tx20MPwrCfgABand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgABand[i]); + RTMPusecDelay(5000); + } + } + } + + //Set BBP R4 bit[4:3]=0:0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + //Set BBP R66=0x3C + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + //Set BBP R68=0x0B + //to improve Rx sensitivity. + value = 0x0B; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + //Set BBP R69=0x16 + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + //Set BBP R70=0x08 + value = 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + //Set BBP R73=0x11 + value = 0x11; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + // If Channel=14, Bandwidth=20M and Mode=CCK, Set BBP R4 bit5=1 + // (Japan filter coefficients) + // This segment of code will only works when ATETXMODE and ATECHANNEL + // were set to MODE_CCK and 14 respectively before ATETXBW is set to 0. + //===================================================================== + if (pAd->ate.Channel == 14) + { + int TxMode = pAd->ate.TxWI.PHYMODE; + if (TxMode == MODE_CCK) + { + // when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value |= 0x20; //set bit5=1 + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + } + } + + //===================================================================== + // If bandwidth != 40M, RF Reg4 bit 21 = 0. +#ifdef RT30xx + // Set BW + if(IS_RT30xx(pAd)) + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR) pAd->Mlme.CaliBW20RfR24); + else +#endif // RT30xx // + { + pAd->LatchRfRegs.R4 &= ~0x00200000; + RtmpRfIoWrite(pAd); + } + + } + else if(pAd->ate.TxWI.BW == BW_40) + { + if(pAd->ate.Channel <= 14) + { + for (i=0; i<5; i++) + { + if (pAd->Tx40MPwrCfgGBand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgGBand[i]); + RTMPusecDelay(5000); + } + } + } + else + { + for (i=0; i<5; i++) + { + if (pAd->Tx40MPwrCfgABand[i] != 0xffffffff) + { + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgABand[i]); + RTMPusecDelay(5000); + } + } +#ifdef DOT11_N_SUPPORT + if ((pAd->ate.TxWI.PHYMODE >= MODE_HTMIX) && (pAd->ate.TxWI.MCS == 7)) + { + value = 0x28; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value); + } +#endif // DOT11_N_SUPPORT // + } + + //Set BBP R4 bit[4:3]=1:0 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value); + value &= (~0x18); + value |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value); + + //Set BBP R66=0x3C + value = 0x3C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value); + //Set BBP R68=0x0C + //to improve Rx sensitivity. + value = 0x0C; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value); + //Set BBP R69=0x1A + value = 0x1A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value); + //Set BBP R70=0x0A + value = 0x0A; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value); + //Set BBP R73=0x16 + value = 0x16; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value); + + // If bandwidth = 40M, set RF Reg4 bit 21 = 1. +#ifdef RT30xx + // Set BW + if(IS_RT30xx(pAd)) + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR) pAd->Mlme.CaliBW40RfR24); + else +#endif // RT30xx // + { + pAd->LatchRfRegs.R4 |= 0x00200000; + RtmpRfIoWrite(pAd); + } + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_BW_Proc (BBPCurrentBW = %d)\n", pAd->ate.TxWI.BW)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_BW_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame length + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_LENGTH_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxLength = simple_strtol(arg, 0, 10); + + if((pAd->ate.TxLength < 24) || (pAd->ate.TxLength > (MAX_FRAME_SIZE - 34/* == 2312 */))) + { + pAd->ate.TxLength = (MAX_FRAME_SIZE - 34/* == 2312 */); + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_LENGTH_Proc::Out of range, it should be in range of 24~%d.\n", (MAX_FRAME_SIZE - 34/* == 2312 */))); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_LENGTH_Proc (TxLength = %d)\n", pAd->ate.TxLength)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_LENGTH_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame count + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_COUNT_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxCount = simple_strtol(arg, 0, 10); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pAd->ate.TxCount)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame MCS + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_MCS_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR MCS; + int result; + + MCS = simple_strtol(arg, 0, 10); + result = CheckMCSValid(pAd->ate.TxWI.PHYMODE, MCS); + + if (result != -1) + { + pAd->ate.TxWI.MCS = (UCHAR)MCS; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MCS_Proc::Out of range, refer to rate table.\n")); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MCS_Proc (MCS = %d)\n", pAd->ate.TxWI.MCS)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MCS_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame Mode + 0: MODE_CCK + 1: MODE_OFDM + 2: MODE_HTMIX + 3: MODE_HTGREENFIELD + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_MODE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxWI.PHYMODE = simple_strtol(arg, 0, 10); + + if(pAd->ate.TxWI.PHYMODE > 3) + { + pAd->ate.TxWI.PHYMODE = 0; + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MODE_Proc::Out of range. it should be in range of 0~3\n")); + ATEDBGPRINT(RT_DEBUG_ERROR, ("0: CCK, 1: OFDM, 2: HT_MIX, 3: HT_GREEN_FIELD.\n")); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MODE_Proc (TxMode = %d)\n", pAd->ate.TxWI.PHYMODE)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MODE_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set ATE Tx frame GI + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ATE_TX_GI_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.TxWI.ShortGI = simple_strtol(arg, 0, 10); + + if(pAd->ate.TxWI.ShortGI > 1) + { + pAd->ate.TxWI.ShortGI = 0; + ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_GI_Proc::Out of range\n")); + return FALSE; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_GI_Proc (GI = %d)\n", pAd->ate.TxWI.ShortGI)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_GI_Proc Success\n")); + + + return TRUE; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +INT Set_ATE_RX_FER_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + pAd->ate.bRxFer = simple_strtol(arg, 0, 10); + + if (pAd->ate.bRxFer == 1) + { + pAd->ate.RxCntPerSec = 0; + pAd->ate.RxTotalCnt = 0; + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_FER_Proc (bRxFer = %d)\n", pAd->ate.bRxFer)); + ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_FER_Proc Success\n")); + + + return TRUE; +} + +INT Set_ATE_Read_RF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support RT30xx ATE<-- + if(IS_RT30xx(pAd)) + { + /* modify by WY for Read RF Reg. error */ + UCHAR RFValue; + INT index=0; + for (index = 0; index < 32; index++) + { + RT30xxReadRFRegister(pAd, index, (PUCHAR)&RFValue); + printk("R%d=%d\n",index,RFValue); + } + } + else +//2008/07/10:KH add to support RT30xx ATE--> +#endif // RT30xx // + { + ate_print(KERN_EMERG "R1 = %lx\n", pAd->LatchRfRegs.R1); + ate_print(KERN_EMERG "R2 = %lx\n", pAd->LatchRfRegs.R2); + ate_print(KERN_EMERG "R3 = %lx\n", pAd->LatchRfRegs.R3); + ate_print(KERN_EMERG "R4 = %lx\n", pAd->LatchRfRegs.R4); + } + return TRUE; +} + +INT Set_ATE_Write_RF1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + if(IS_RT30xx(pAd)) + { + printk("Warning!! RT30xx Don't Support\n"); + return FALSE; + + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // + { + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R1 = value; + RtmpRfIoWrite(pAd); + } + return TRUE; + +} + +INT Set_ATE_Write_RF2_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + if(IS_RT30xx(pAd)) + { + printk("Warning!! RT30xx Don't Support\n"); + return FALSE; + + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // + { + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R2 = value; + RtmpRfIoWrite(pAd); + } + return TRUE; +} + +INT Set_ATE_Write_RF3_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + if(IS_RT30xx(pAd)) + { + printk("Warning!! RT30xx Don't Support\n"); + return FALSE; + + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // + { + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R3 = value; + RtmpRfIoWrite(pAd); + } + return TRUE; +} + +INT Set_ATE_Write_RF4_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + if(IS_RT30xx(pAd)) + { + printk("Warning!! RT30xx Don't Support\n"); + return FALSE; + + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // + { + UINT32 value = simple_strtol(arg, 0, 16); + + pAd->LatchRfRegs.R4 = value; + RtmpRfIoWrite(pAd); + } + return TRUE; +} +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- +INT SET_ATE_3070RF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + CHAR *this_char; + CHAR *value; + UINT32 Reg,RFValue; + if(IS_RT30xx(pAd)) + { + printk("SET_ATE_3070RF_Proc=%s\n",arg); + this_char =arg; + if ((value = strchr(this_char, ':')) != NULL) + *value++ = 0; + Reg= simple_strtol(this_char, 0, 16); + RFValue= simple_strtol(value, 0, 16); + printk("RF Reg[%d]=%d\n",Reg,RFValue); + RT30xxWriteRFRegister(pAd, Reg,RFValue); + } + else + printk("Warning!! Only 3070 Support\n"); + return TRUE; +} +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // +/* + ========================================================================== + Description: + Load and Write EEPROM from a binary file prepared in advance. + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +#ifndef UCOS +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + BOOLEAN ret = FALSE; + PUCHAR src = EEPROM_BIN_FILE_NAME; + struct file *srcf; + INT32 retval, orgfsuid, orgfsgid; + mm_segment_t orgfs; + USHORT WriteEEPROM[(EEPROM_SIZE/2)]; + UINT32 FileLength = 0; + UINT32 value = simple_strtol(arg, 0, 10); + + ATEDBGPRINT(RT_DEBUG_ERROR, ("===> %s (value=%d)\n\n", __FUNCTION__, value)); + + if (value > 0) + { + /* zero the e2p buffer */ + NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE); + + /* save uid and gid used for filesystem access. + ** set user and group to 0 (root) + */ + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + /* as root */ + current->fsuid = current->fsgid = 0; + orgfs = get_fs(); + set_fs(KERNEL_DS); + + do + { + /* open the bin file */ + srcf = filp_open(src, O_RDONLY, 0); + + if (IS_ERR(srcf)) + { + ate_print("%s - Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(srcf), src); + break; + } + + /* the object must have a read method */ + if ((srcf->f_op == NULL) || (srcf->f_op->read == NULL)) + { + ate_print("%s - %s does not have a read method\n", __FUNCTION__, src); + break; + } + + /* read the firmware from the file *.bin */ + FileLength = srcf->f_op->read(srcf, + (PUCHAR)WriteEEPROM, + EEPROM_SIZE, + &srcf->f_pos); + + if (FileLength != EEPROM_SIZE) + { + ate_print("%s: error file length (=%d) in e2p.bin\n", + __FUNCTION__, FileLength); + break; + } + else + { + /* write the content of .bin file to EEPROM */ + rt_ee_write_all(pAd, WriteEEPROM); + ret = TRUE; + } + break; + } while(TRUE); + + /* close firmware file */ + if (IS_ERR(srcf)) + { + ; + } + else + { + retval = filp_close(srcf, NULL); + if (retval) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("--> Error %d closing %s\n", -retval, src)); + + } + } + + /* restore */ + set_fs(orgfs); + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; + } + ATEDBGPRINT(RT_DEBUG_ERROR, ("<=== %s (ret=%d)\n", __FUNCTION__, ret)); + + return ret; + +} +#else +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + USHORT WriteEEPROM[(EEPROM_SIZE/2)]; + struct iwreq *wrq = (struct iwreq *)arg; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("===> %s (wrq->u.data.length = %d)\n\n", __FUNCTION__, wrq->u.data.length)); + + if (wrq->u.data.length != EEPROM_SIZE) + { + ate_print("%s: error length (=%d) from host\n", + __FUNCTION__, wrq->u.data.length); + return FALSE; + } + else/* (wrq->u.data.length == EEPROM_SIZE) */ + { + /* zero the e2p buffer */ + NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE); + + /* fill the local buffer */ + NdisMoveMemory((PUCHAR)WriteEEPROM, wrq->u.data.pointer, wrq->u.data.length); + + do + { + /* write the content of .bin file to EEPROM */ + rt_ee_write_all(pAd, WriteEEPROM); + + } while(FALSE); + } + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== %s\n", __FUNCTION__)); + + return TRUE; + +} +#endif // !UCOS // + +INT Set_ATE_Read_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + USHORT buffer[EEPROM_SIZE/2]; + USHORT *p; + int i; + + rt_ee_read_all(pAd, (USHORT *)buffer); + p = buffer; + for (i = 0; i < (EEPROM_SIZE/2); i++) + { + ate_print("%4.4x ", *p); + if (((i+1) % 16) == 0) + ate_print("\n"); + p++; + } + return TRUE; +} + +INT Set_ATE_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ate_print("Mode=%d\n", pAd->ate.Mode); + ate_print("TxPower0=%d\n", pAd->ate.TxPower0); + ate_print("TxPower1=%d\n", pAd->ate.TxPower1); + ate_print("TxAntennaSel=%d\n", pAd->ate.TxAntennaSel); + ate_print("RxAntennaSel=%d\n", pAd->ate.RxAntennaSel); + ate_print("BBPCurrentBW=%d\n", pAd->ate.TxWI.BW); + ate_print("GI=%d\n", pAd->ate.TxWI.ShortGI); + ate_print("MCS=%d\n", pAd->ate.TxWI.MCS); + ate_print("TxMode=%d\n", pAd->ate.TxWI.PHYMODE); + ate_print("Addr1=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->ate.Addr1[0], pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5]); + ate_print("Addr2=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->ate.Addr2[0], pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5]); + ate_print("Addr3=%02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->ate.Addr3[0], pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5]); + ate_print("Channel=%d\n", pAd->ate.Channel); + ate_print("TxLength=%d\n", pAd->ate.TxLength); + ate_print("TxCount=%u\n", pAd->ate.TxCount); + ate_print("RFFreqOffset=%d\n", pAd->ate.RFFreqOffset); + ate_print(KERN_EMERG "Set_ATE_Show_Proc Success\n"); + return TRUE; +} + +INT Set_ATE_Help_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ate_print("ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXFRAME, RXFRAME\n"); + ate_print("ATEDA\n"); + ate_print("ATESA\n"); + ate_print("ATEBSSID\n"); + ate_print("ATECHANNEL, range:0~14(unless A band !)\n"); + ate_print("ATETXPOW0, set power level of antenna 1.\n"); + ate_print("ATETXPOW1, set power level of antenna 2.\n"); + ate_print("ATETXANT, set TX antenna. 0:all, 1:antenna one, 2:antenna two.\n"); + ate_print("ATERXANT, set RX antenna.0:all, 1:antenna one, 2:antenna two, 3:antenna three.\n"); + ate_print("ATETXFREQOFFSET, set frequency offset, range 0~63\n"); + ate_print("ATETXBW, set BandWidth, 0:20MHz, 1:40MHz.\n"); + ate_print("ATETXLEN, set Frame length, range 24~%d\n", (MAX_FRAME_SIZE - 34/* == 2312 */)); + ate_print("ATETXCNT, set how many frame going to transmit.\n"); + ate_print("ATETXMCS, set MCS, reference to rate table.\n"); + ate_print("ATETXMODE, set Mode 0:CCK, 1:OFDM, 2:HT-Mix, 3:GreenField, reference to rate table.\n"); + ate_print("ATETXGI, set GI interval, 0:Long, 1:Short\n"); + ate_print("ATERXFER, 0:disable Rx Frame error rate. 1:enable Rx Frame error rate.\n"); + ate_print("ATERRF, show all RF registers.\n"); + ate_print("ATEWRF1, set RF1 register.\n"); + ate_print("ATEWRF2, set RF2 register.\n"); + ate_print("ATEWRF3, set RF3 register.\n"); + ate_print("ATEWRF4, set RF4 register.\n"); + ate_print("ATELDE2P, load EEPROM from .bin file.\n"); + ate_print("ATERE2P, display all EEPROM content.\n"); + ate_print("ATESHOW, display all parameters of ATE.\n"); + ate_print("ATEHELP, online help.\n"); + + return TRUE; +} + +/* + ========================================================================== + Description: + + AsicSwitchChannel() dedicated for ATE. + + ========================================================================== +*/ +VOID ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd) +{ + UINT32 R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0, Value = 0; + CHAR TxPwer = 0, TxPwer2 = 0; + UCHAR index, BbpValue = 0, R66 = 0x30; + RTMP_RF_REGS *RFRegTable; + UCHAR Channel; + +#ifdef RALINK_28xx_QA + if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE)) + { + if (pAd->ate.Channel != pAd->LatchRfRegs.Channel) + { + pAd->ate.Channel = pAd->LatchRfRegs.Channel; + } + return; + } + else +#endif // RALINK_28xx_QA // + Channel = pAd->ate.Channel; + + // Select antenna + AsicAntennaSelect(pAd, Channel); + + // fill Tx power value + TxPwer = pAd->ate.TxPower0; + TxPwer2 = pAd->ate.TxPower1; +#ifdef RT30xx +//2008/07/10:KH add to support 3070 ATE<-- + + // The RF programming sequence is difference between 3xxx and 2xxx + // The 3070 is 1T1R. Therefore, we don't need to set the number of Tx/Rx path and the only job is to set the parameters of channels. + if (IS_RT30xx(pAd) && ((pAd->RfIcType == RFIC_3020) || +(pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022) || +(pAd->RfIcType == RFIC_2020))) + { + /* modify by WY for Read RF Reg. error */ + UCHAR RFValue; + + for (index = 0; index < NUM_OF_3020_CHNL; index++) + { + if (Channel == FreqItems3020[index].Channel) + { + // Programming channel parameters + RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N); + RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K); + + RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xFC) | FreqItems3020[index].R; + RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue); + + // Set Tx Power + RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue); + RFValue = (RFValue & 0xE0) | TxPwer; + RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue); + + // Set RF offset + RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue); + //2008/08/06: KH modified "pAd->RFFreqOffset" to "pAd->ate.RFFreqOffset" + RFValue = (RFValue & 0x80) | pAd->ate.RFFreqOffset; + RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue); + + // Set BW + if (pAd->ate.TxWI.BW == BW_40) + { + RFValue = pAd->Mlme.CaliBW40RfR24; + //DISABLE_11N_CHECK(pAd); + } + else + { + RFValue = pAd->Mlme.CaliBW20RfR24; + } + RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue); + + // Enable RF tuning + RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue); + RFValue = RFValue | 0x1; + RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue); + + // latch channel for future usage. + pAd->LatchRfRegs.Channel = Channel; + + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n", + Channel, + pAd->RfIcType, + TxPwer, + TxPwer2, + pAd->Antenna.field.TxPath, + FreqItems3020[index].N, + FreqItems3020[index].K, + FreqItems3020[index].R)); + } + else +//2008/07/10:KH add to support 3070 ATE--> +#endif // RT30xx // +{ + RFRegTable = RF2850RegTable; + + switch (pAd->RfIcType) + { + /* But only 2850 and 2750 support 5.5GHz band... */ + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: + + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R2 = RFRegTable[index].R2; + if (pAd->Antenna.field.TxPath == 1) + { + R2 |= 0x4000; // If TXpath is 1, bit 14 = 1; + } + + if (pAd->Antenna.field.RxPath == 2) + { + switch (pAd->ate.RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + R2 |= 0x40; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + /* Only enable two Antenna to receive. */ + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + else if (pAd->Antenna.field.RxPath == 1) + { + R2 |= 0x20040; // write 1 to off RxPath + } + + if (pAd->Antenna.field.TxPath == 2) + { + if (pAd->ate.TxAntennaSel == 1) + { + R2 |= 0x4000; // If TX Antenna select is 1 , bit 14 = 1; Disable Ant 2 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; //11100111B + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else if (pAd->ate.TxAntennaSel == 2) + { + R2 |= 0x8000; // If TX Antenna select is 2 , bit 15 = 1; Disable Ant 1 + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x08; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue); + BbpValue &= 0xE7; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue); + } + } + if (pAd->Antenna.field.RxPath == 3) + { + switch (pAd->ate.RxAntennaSel) + { + case 1: + R2 |= 0x20040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x00; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 2: + R2 |= 0x10040; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x01; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + case 3: + R2 |= 0x30000; + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x02; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + default: + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue); + BbpValue &= 0xE4; + BbpValue |= 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue); + break; + } + } + + if (Channel > 14) + { + // initialize R3, R4 + R3 = (RFRegTable[index].R3 & 0xffffc1ff); + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15); + + // According the Rory's suggestion to solve the middle range issue. + // 5.5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB + // R3 + if ((TxPwer >= -7) && (TxPwer < 0)) + { + TxPwer = (7+TxPwer); + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10); + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer=%d \n", TxPwer)); + } + else + { + TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer); + R3 |= (TxPwer << 10) | (1 << 9); + } + + // R4 + if ((TxPwer2 >= -7) && (TxPwer2 < 0)) + { + TxPwer2 = (7+TxPwer2); + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7); + ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer2=%d \n", TxPwer2)); + } + else + { + TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2); + R4 |= (TxPwer2 << 7) | (1 << 6); + } + } + else + { + R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0 + R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15) | (TxPwer2 <<6);// Set freq offset & TxPwr1 + } + + // Based on BBP current mode before changing RF channel. + if (pAd->ate.TxWI.BW == BW_40) + { + R4 |=0x200000; + } + + // Update variables + pAd->LatchRfRegs.Channel = Channel; + pAd->LatchRfRegs.R1 = RFRegTable[index].R1; + pAd->LatchRfRegs.R2 = R2; + pAd->LatchRfRegs.R3 = R3; + pAd->LatchRfRegs.R4 = R4; + + RtmpRfIoWrite(pAd); + + break; + } + } + break; + + default: + break; + } +} + // Change BBP setting during switch from a->g, g->a + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A;// 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + + /* For 1T/2R chip only... */ + if (pAd->NicConfig2.field.ExternalLNAForG) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84); + } + + // According the Rory's suggestion to solve the middle range issue. + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue); + ASSERT((BbpValue == 0x00)); + if ((BbpValue != 0x00)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00); + } + + // 5.5GHz band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x04); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R. + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + else + { + ULONG TxPinCfg = 0x00050F05;//2007.10.09 by Brian : 0x00050505 ==> 0x00050F05 + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd))); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + // According the Rory's suggestion to solve the middle range issue. + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue); + ASSERT((BbpValue == 0x00)); + if ((BbpValue != 0x00)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00); + } + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue); + ASSERT((BbpValue == 0x04)); + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R92, &BbpValue); + ASSERT((BbpValue == 0x00)); + + // 5.5GHz band selection PIN, bit1 and bit2 are complement + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value); + Value &= (~0x6); + Value |= (0x02); + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value); + + // Turn off unused PA or LNA when only 1T or 1R. + if (pAd->Antenna.field.TxPath == 1) + { + TxPinCfg &= 0xFFFFFFF3; + } + if (pAd->Antenna.field.RxPath == 1) + { + TxPinCfg &= 0xFFFFF3FF; + } + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + } + + // R66 should be set according to Channel and use 20MHz when scanning + if (Channel <= 14) + { + // BG band + R66 = 0x2E + GET_LNA_GAIN(pAd); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { + // 5.5 GHz band + if (pAd->ate.TxWI.BW == BW_20) + { + R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else + { + R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + } + + // + // On 11A, We should delay and wait RF/BBP to be stable + // and the appropriate time should be 1000 micro seconds + // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL. + // + RTMPusecDelay(1000); + + if (Channel > 14) + { + // When 5.5GHz band the LSB of TxPwr will be used to reduced 7dB or not. + ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", + Channel, + pAd->RfIcType, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%u, Pwr1=%u, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n", + Channel, + pAd->RfIcType, + (R3 & 0x00003e00) >> 9, + (R4 & 0x000007c0) >> 6, + pAd->Antenna.field.TxPath, + pAd->LatchRfRegs.R1, + pAd->LatchRfRegs.R2, + pAd->LatchRfRegs.R3, + pAd->LatchRfRegs.R4)); + } +} + +// +// In fact, no one will call this routine so far ! +// +/* + ========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in ATE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) + 1. TxPowerPercentage + 2. auto calibration based on TSSI feedback + 3. extra 2 db for CCK + 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + + NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), + it should be called AFTER MlmeDynamicTxRateSwitching() + ========================================================================== + */ +VOID ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd) +{ + INT i, j; + CHAR DeltaPwr = 0; + BOOLEAN bAutoTxAgc = FALSE; + UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep; + UCHAR BbpR49 = 0, idx; + PCHAR pTxAgcCompensate; + ULONG TxPwr[5]; + CHAR Value; + + /* no one calls this procedure so far */ + if (pAd->ate.TxWI.BW == BW_40) + { + if (pAd->ate.Channel > 14) + { + TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; + } + } + else + { + if (pAd->ate.Channel > 14) + { + TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + } + } + + // TX power compensation for temperature variation based on TSSI. + // Do it per 4 seconds. + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { + if (pAd->ate.Channel <= 14) + { + /* bg channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + TssiRef = pAd->TssiRefG; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0]; + TxAgcStep = pAd->TxAgcStepG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + /* a channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + TssiRef = pAd->TssiRefA; + pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + /* BbpR49 is unsigned char */ + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49); + + /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ + /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ + /* step value is defined in pAd->TxAgcStepG for tx power value */ + + /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ + /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + above value are examined in mass factory production */ + /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ + + /* plus is 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49 > pTssiMinusBoundary[1]) + { + // Reading is larger than the reference value. + // Check for how large we need to decrease the Tx power. + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range + break; + } + // The index is the step we should decrease, idx = 0 means there is nothing to compensate +// if (R3 > (ULONG) (TxAgcStep * (idx-1))) + *pTxAgcCompensate = -(TxAgcStep * (idx-1)); +// else +// *pTxAgcCompensate = -((UCHAR)R3); + + DeltaPwr += (*pTxAgcCompensate); + ATEDBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49 < pTssiPlusBoundary[1]) + { + // Reading is smaller than the reference value + // check for how large we need to increase the Tx power + for (idx = 1; idx < 5; idx++) + { + if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range + break; + } + // The index is the step we should increase, idx = 0 means there is nothing to compensate + *pTxAgcCompensate = TxAgcStep * (idx-1); + DeltaPwr += (*pTxAgcCompensate); + ATEDBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + ATEDBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pAd->ate.Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + /* calculate delta power based on the percentage specified from UI */ + // E2PROM setting is calibrated for maximum TX power (i.e. 100%) + // We lower TX power here according to the percentage specified from UI + if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control + ; + else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW + { + DeltaPwr -= 1; + } + else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW + { + DeltaPwr -= 3; + } + else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW + { + DeltaPwr -= 6; + } + else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW + { + DeltaPwr -= 9; + } + else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW + { + DeltaPwr -= 12; + } + + /* reset different new tx power for different TX rate */ + for(i=0; i<5; i++) + { + if (TxPwr[i] != 0xffffffff) + { + for (j=0; j<8; j++) + { + Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */ + + if ((Value + DeltaPwr) < 0) + { + Value = 0; /* min */ + } + else if ((Value + DeltaPwr) > 0xF) + { + Value = 0xF; /* max */ + } + else + { + Value += DeltaPwr; /* temperature compensation */ + } + + /* fill new value to CSR offset */ + TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4); + } + + /* write tx power value to CSR */ + /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M + TX power for OFDM 6M/9M + TX power for CCK5.5M/11M + TX power for CCK1M/2M */ + /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]); + + + } + } + +} + +/* + ======================================================================== + Routine Description: + Write TxWI for ATE mode. + + Return Value: + None + ======================================================================== +*/ + +#ifdef RT2870 +static VOID ATEWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR MIMOps, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING Transmit) +{ + // + // Always use Long preamble before verifiation short preamble functionality works well. + // Todo: remove the following line if short preamble functionality works + // + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + pTxWI->FRAG= FRAG; + pTxWI->TS= InsTimestamp; + pTxWI->AMPDU = AMPDU; + + pTxWI->MIMOps = PWR_ACTIVE; + pTxWI->MpduDensity = 4; + pTxWI->ACK = Ack; + pTxWI->txop = Txopmode; + pTxWI->NSEQ = NSeq; + pTxWI->BAWinSize = BASize; + + pTxWI->WirelessCliID = WCID; + pTxWI->MPDUtotalByteCount = Length; + pTxWI->PacketId = PID; + + pTxWI->BW = Transmit.field.BW; + pTxWI->ShortGI = Transmit.field.ShortGI; + pTxWI->STBC= Transmit.field.STBC; + + pTxWI->MCS = Transmit.field.MCS; + pTxWI->PHYMODE= Transmit.field.MODE; + +#ifdef DOT11_N_SUPPORT + // + // MMPS is 802.11n features. Because TxWI->MCS > 7 must be HT mode, + // so need not check if it's HT rate. + // + if ((MIMOps == MMPS_STATIC) && (pTxWI->MCS > 7)) + pTxWI->MCS = 7; + + if ((MIMOps == MMPS_DYNAMIC) && (pTxWI->MCS > 7)) // SMPS protect 2 spatial. + pTxWI->MIMOps = 1; +#endif // DOT11_N_SUPPORT // + + pTxWI->CFACK = CfAck; + + return; +} +#endif // RT2870 // +/* + ======================================================================== + + Routine Description: + Disable protection for ATE. + ======================================================================== +*/ +VOID ATEDisableAsicProtect( + IN PRTMP_ADAPTER pAd) +{ + PROT_CFG_STRUC ProtCfg, ProtCfg4; + UINT32 Protect[6]; + USHORT offset; + UCHAR i; + UINT32 MacReg = 0; + + // Config ASIC RTS threshold register + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFF0000FF; + MacReg |= (pAd->CommonCfg.RtsThreshold << 8); + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + + // Initial common protection settings + RTMPZeroMemory(Protect, sizeof(Protect)); + ProtCfg4.word = 0; + ProtCfg.word = 0; + ProtCfg.field.TxopAllowGF40 = 1; + ProtCfg.field.TxopAllowGF20 = 1; + ProtCfg.field.TxopAllowMM40 = 1; + ProtCfg.field.TxopAllowMM20 = 1; + ProtCfg.field.TxopAllowOfdm = 1; + ProtCfg.field.TxopAllowCck = 1; + ProtCfg.field.RTSThEn = 1; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + + // Handle legacy(B/G) protection + ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate; + ProtCfg.field.ProtectCtrl = 0; + Protect[0] = ProtCfg.word; + Protect[1] = ProtCfg.word; + + // NO PROTECT + // 1.All STAs in the BSS are 20/40 MHz HT + // 2. in ai 20/40MHz BSS + // 3. all STAs are 20MHz in a 20MHz BSS + // Pure HT. no protection. + + // MM20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[2] = 0x01744004; + + // MM40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[3] = 0x03f44084; + + // CF20_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 010111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4004 (OFDM 24M) + Protect[4] = 0x01744004; + + // CF40_PROT_CFG + // Reserved (31:27) + // PROT_TXOP(25:20) -- 111111 + // PROT_NAV(19:18) -- 01 (Short NAV protection) + // PROT_CTRL(17:16) -- 00 (None) + // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M) + Protect[5] = 0x03f44084; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + + offset = CCK_PROT_CFG; + for (i = 0;i < 6;i++) + RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); + +} + +#ifdef RT2870 +/* + ======================================================================== + Routine Description: + Write TxInfo for ATE mode. + + Return Value: + None + ======================================================================== +*/ +static VOID ATEWriteTxInfo( + IN PRTMP_ADAPTER pAd, + IN PTXINFO_STRUC pTxInfo, + IN USHORT USBDMApktLen, + IN BOOLEAN bWiv, + IN UCHAR QueueSel, + IN UCHAR NextValid, + IN UCHAR TxBurst) +{ + pTxInfo->USBDMATxPktLen = USBDMApktLen; + pTxInfo->QSEL = QueueSel; + + if (QueueSel != FIFO_EDCA) + ATEDBGPRINT(RT_DEBUG_TRACE, ("=======> QueueSel != FIFO_EDCA<=======\n")); + + pTxInfo->USBDMANextVLD = NextValid; + pTxInfo->USBDMATxburst = TxBurst; + pTxInfo->WIV = bWiv; + pTxInfo->SwUseLastRound = 0; + pTxInfo->rsv = 0; + pTxInfo->rsv2 = 0; + + return; +} +#endif // RT2870 // + +/* There are two ways to convert Rssi */ +#if 1 +// +// The way used with GET_LNA_GAIN(). +// +CHAR ATEConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + + // Rssi equals to zero should be an invalid value + if (Rssi == 0) + return -99; + + LNAGain = GET_LNA_GAIN(pAd); + if (pAd->LatchRfRegs.Channel > 14) + { + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + return (-12 - RssiOffset - LNAGain - Rssi); +} +#else +// +// The way originally used in ATE of rt2860ap. +// +CHAR ATEConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber) +{ + UCHAR RssiOffset, LNAGain; + + // Rssi equals to zero should be an invalid value + if (Rssi == 0) + return -99; + + if (pAd->LatchRfRegs.Channel > 14) + { + LNAGain = pAd->ALNAGain; + if (RssiNumber == 0) + RssiOffset = pAd->ARssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->ARssiOffset1; + else + RssiOffset = pAd->ARssiOffset2; + } + else + { + LNAGain = pAd->BLNAGain; + if (RssiNumber == 0) + RssiOffset = pAd->BGRssiOffset0; + else if (RssiNumber == 1) + RssiOffset = pAd->BGRssiOffset1; + else + RssiOffset = pAd->BGRssiOffset2; + } + + return (-32 - RssiOffset + LNAGain - Rssi); +} +#endif /* end of #if 1 */ + +/* + ======================================================================== + + Routine Description: + Set Japan filter coefficients if needed. + Note: + This routine should only be called when + entering TXFRAME mode or TXCONT mode. + + ======================================================================== +*/ +static VOID SetJapanFilter( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpData = 0; + + // + // If Channel=14 and Bandwidth=20M and Mode=CCK, set BBP R4 bit5=1 + // (Japan Tx filter coefficients)when (TXFRAME or TXCONT). + // + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpData); + + if ((pAd->ate.TxWI.PHYMODE == MODE_CCK) && (pAd->ate.Channel == 14) && (pAd->ate.TxWI.BW == BW_20)) + { + BbpData |= 0x20; // turn on + ATEDBGPRINT(RT_DEBUG_TRACE, ("SetJapanFilter!!!\n")); + } + else + { + BbpData &= 0xdf; // turn off + ATEDBGPRINT(RT_DEBUG_TRACE, ("ClearJapanFilter!!!\n")); + } + + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpData); +} + +VOID ATESampleRssi( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI) +{ + /* There are two ways to collect RSSI. */ +#if 1 + //pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ; + if (pRxWI->RSSI0 != 0) + { + pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0); + pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0; + pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3; + } + if (pRxWI->RSSI1 != 0) + { + pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1); + pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1; + pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3; + } + if (pRxWI->RSSI2 != 0) + { + pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2); + pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2; + pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3; + } + + pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0);// CHAR ==> UCHAR ? + pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1);// CHAR ==> UCHAR ? + + pAd->ate.NumOfAvgRssiSample ++; +#else + pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0); + pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1); + pAd->ate.RxCntPerSec++; + pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0); + pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1); + pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2); + pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0; + pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3; + pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1; + pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3; + pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2; + pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3; + pAd->ate.NumOfAvgRssiSample ++; +#endif +} + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPStationStop( + IN PRTMP_ADAPTER pAd) +{ +// BOOLEAN Cancelled; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStop\n")); + + // For rx statistics, we need to keep this timer running. +// RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStop\n")); +} + +VOID RTMPStationStart( + IN PRTMP_ADAPTER pAd) +{ + ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStart\n")); + ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStart\n")); +} +#endif // CONFIG_STA_SUPPORT // + +/* + ========================================================================== + Description: + Setup Frame format. + NOTE: + This routine should only be used in ATE mode. + ========================================================================== + */ + +#ifdef RT2870 +/*======================Start of RT2870======================*/ +/* */ +/* */ +static INT ATESetUpFrame( + IN PRTMP_ADAPTER pAd, + IN UINT32 TxIdx) +{ + UINT j; + PTX_CONTEXT pNullContext; + PUCHAR pDest; + HTTRANSMIT_SETTING TxHTPhyMode; + PTXWI_STRUC pTxWI; + PTXINFO_STRUC pTxInfo; + UINT32 TransferBufferLength, OrgBufferLength = 0; + UCHAR padLen = 0; +#ifdef RALINK_28xx_QA + PHEADER_802_11 pHeader80211 = NULL; +#endif // RALINK_28xx_QA // + + if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + return -1; + } + + /* We always use QID_AC_BE and FIFO_EDCA in ATE mode. */ + + pNullContext = &(pAd->NullContext); + ASSERT(pNullContext != NULL); + + if (pNullContext->InUse == FALSE) + { + // Set the in use bit + pNullContext->InUse = TRUE; + NdisZeroMemory(&(pAd->NullFrame), sizeof(HEADER_802_11)); + + // Fill 802.11 header. +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + pHeader80211 = NdisMoveMemory(&(pAd->NullFrame), pAd->ate.Header, pAd->ate.HLen); +// pDest = NdisMoveMemory(&(pAd->NullFrame), pAd->ate.Header, pAd->ate.HLen); +// pHeader80211 = (PHEADER_802_11)pDest; + } + else +#endif // RALINK_28xx_QA // + { + // Fill 802.11 header. + NdisMoveMemory(&(pAd->NullFrame), TemplateFrame, sizeof(HEADER_802_11)); + } +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)&(pAd->NullFrame), DIR_READ, FALSE); +#endif // RT_BIG_ENDIAN // + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + /* modify sequence number.... */ + if (pAd->ate.TxDoneCount == 0) + { + pAd->ate.seq = pHeader80211->Sequence; + } + else + { + pHeader80211->Sequence = ++pAd->ate.seq; + } + /* We already got all the addr. fields from QA GUI. */ + } + else +#endif // RALINK_28xx_QA // + { + COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->ate.Addr1); + COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->ate.Addr2); + COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->ate.Addr3); + } + + RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[0], TX_BUFFER_NORMSIZE);//??? + pTxInfo = (PTXINFO_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[0]; + +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + // Avoid to exceed the range of WirelessPacket[]. + ASSERT(pAd->ate.TxInfo.USBDMATxPktLen <= (MAX_FRAME_SIZE - 34/* == 2312 */)); + NdisMoveMemory(pTxInfo, &(pAd->ate.TxInfo), sizeof(pAd->ate.TxInfo)); + } + else +#endif // RALINK_28xx_QA // + { + // Avoid to exceed the range of WirelessPacket[]. + ASSERT(pAd->ate.TxLength <= (MAX_FRAME_SIZE - 34/* == 2312 */)); + + // pTxInfo->USBDMATxPktLen will be updated to include padding later. + ATEWriteTxInfo(pAd, pTxInfo, (USHORT)(TXWI_SIZE + pAd->ate.TxLength), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + pTxInfo->QSEL = FIFO_EDCA; + } + + pTxWI = (PTXWI_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE]; + + // Fill TxWI. + if (pAd->ate.bQATxStart == TRUE) + { + TxHTPhyMode.field.BW = pAd->ate.TxWI.BW; + TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI; + TxHTPhyMode.field.STBC = pAd->ate.TxWI.STBC; + TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS; + TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE; + ATEWriteTxWI(pAd, pTxWI, pAd->ate.TxWI.FRAG, pAd->ate.TxWI.TS, pAd->ate.TxWI.AMPDU, pAd->ate.TxWI.ACK, pAd->ate.TxWI.NSEQ, + pAd->ate.TxWI.BAWinSize, BSSID_WCID, pAd->ate.TxWI.MPDUtotalByteCount/* include 802.11 header */, pAd->ate.TxWI.PacketId, 0, pAd->ate.TxWI.txop/*IFS_HTTXOP*/, pAd->ate.TxWI.CFACK/*FALSE*/, TxHTPhyMode); + } + else + { + TxHTPhyMode.field.BW = pAd->ate.TxWI.BW; + TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI; + TxHTPhyMode.field.STBC = 0; + TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS; + TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE; + + ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE/* No ack required. */, FALSE, 0, BSSID_WCID, pAd->ate.TxLength, + 0, 0, IFS_HTTXOP, FALSE, TxHTPhyMode);// "MMPS_STATIC" instead of "MMPS_DYNAMIC" ??? + } + + RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE+TXWI_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11)); + + pDest = &(pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE+TXWI_SIZE+sizeof(HEADER_802_11)]); + + // Prepare frame payload +#ifdef RALINK_28xx_QA + if (pAd->ate.bQATxStart == TRUE) + { + // copy pattern + if ((pAd->ate.PLen != 0)) + { + for (j = 0; j < pAd->ate.DLen; j+=pAd->ate.PLen) + { + RTMPMoveMemory(pDest, pAd->ate.Pattern, pAd->ate.PLen); + pDest += pAd->ate.PLen; + } + } + TransferBufferLength = TXINFO_SIZE + TXWI_SIZE + pAd->ate.TxWI.MPDUtotalByteCount; + } + else +#endif // RALINK_28xx_QA // + { + for (j = 0; j < (pAd->ate.TxLength - sizeof(HEADER_802_11)); j++) + { + *pDest = 0xA5; + pDest += 1; + } + TransferBufferLength = TXINFO_SIZE + TXWI_SIZE + pAd->ate.TxLength; + } + +#if 1 + OrgBufferLength = TransferBufferLength; + TransferBufferLength = (TransferBufferLength + 3) & (~3); + + // Always add 4 extra bytes at every packet. + padLen = TransferBufferLength - OrgBufferLength + 4;/* 4 == last packet padding */ + ASSERT((padLen <= (RTMP_PKT_TAIL_PADDING - 4/* 4 == MaxBulkOutsize alignment padding */))); + + /* Now memzero all extra padding bytes. */ + NdisZeroMemory(pDest, padLen); + pDest += padLen; +#else + if ((TransferBufferLength % 4) == 1) + { + NdisZeroMemory(pDest, 7); + pDest += 7; + TransferBufferLength += 3; + } + else if ((TransferBufferLength % 4) == 2) + { + NdisZeroMemory(pDest, 6); + pDest += 6; + TransferBufferLength += 2; + } + else if ((TransferBufferLength % 4) == 3) + { + NdisZeroMemory(pDest, 5); + pDest += 5; + TransferBufferLength += 1; + } +#endif // 1 // + + // Update pTxInfo->USBDMATxPktLen to include padding. + pTxInfo->USBDMATxPktLen = TransferBufferLength - TXINFO_SIZE; + + TransferBufferLength += 4; + + // If TransferBufferLength is multiple of 64, add extra 4 bytes again. + if ((TransferBufferLength % pAd->BulkOutMaxPacketSize) == 0) + { + NdisZeroMemory(pDest, 4); + TransferBufferLength += 4; + } + + // Fill out frame length information for global Bulk out arbitor + pAd->NullContext.BulkOutSize = TransferBufferLength; + } +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); + RTMPFrameEndianChange(pAd, (((PUCHAR)pTxInfo)+TXWI_SIZE+TXINFO_SIZE), DIR_WRITE, FALSE); + RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO); +#endif // RT_BIG_ENDIAN // + return 0; +} + +VOID ATE_RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) +{ + PRTMP_ADAPTER pAd; + PTX_CONTEXT pNullContext; + UCHAR BulkOutPipeId; + NTSTATUS Status; + unsigned long IrqFlags; + ULONG OldValue; + + pNullContext = (PTX_CONTEXT)pUrb->context; + pAd = pNullContext->pAd; + + + // Reset Null frame context flags + pNullContext->IRPPending = FALSE; + pNullContext->InUse = FALSE; + Status = pUrb->status; + + // Store BulkOut PipeId + BulkOutPipeId = pNullContext->BulkOutPipeId; + pAd->BulkOutDataOneSecCount++; + + if (Status == USB_ST_NOERROR) + { +#ifdef RALINK_28xx_QA + if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) + { + if (pAd->ate.QID == BulkOutPipeId) + { + // Let Rx can have a chance to break in during Tx process, + // especially for loopback mode in QA ATE. + // To trade off between tx performance and loopback mode integrity. + /* Q : Now Rx is handled by tasklet, do we still need this delay ? */ + /* Ans : Even tasklet is used, Rx/Tx < 1 if we do not delay for a while right here. */ + RTMPusecDelay(500); + pAd->ate.TxDoneCount++; + pAd->RalinkCounters.KickTxCount++; + ASSERT(pAd->ate.QID == 0); + pAd->ate.TxAc0++; + } + } +#endif // RALINK_28xx_QA // + pAd->BulkOutComplete++; + + pAd->Counters8023.GoodTransmits++; + + /* Don't worry about the queue is empty or not. This function will check itself. */ + RTMPDeQueuePacket(pAd, TRUE, BulkOutPipeId, MAX_TX_PROCESS); + + /* In 28xx, SendTxWaitQueue ==> TxSwQueue */ +/* + if (pAd->SendTxWaitQueue[BulkOutPipeId].Number > 0) + { + RTMPDeQueuePacket(pAd, BulkOutPipeId); + } +*/ + } + else // STATUS_OTHER + { + pAd->BulkOutCompleteOther++; + + ATEDBGPRINT(RT_DEBUG_ERROR, ("BulkOutDataPacket Failed STATUS_OTHER = 0x%x . \n", Status)); + ATEDBGPRINT(RT_DEBUG_ERROR, (">>BulkOutReq=0x%lx, BulkOutComplete=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete)); + + if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + /* In 28xx, RT_OID_USB_RESET_BULK_OUT ==> CMDTHREAD_RESET_BULK_OUT */ + RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); + // Check + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + pAd->bulkResetPipeid = BulkOutPipeId; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + return; + } + } + + + + if (atomic_read(&pAd->BulkOutRemained) > 0) + { + atomic_dec(&pAd->BulkOutRemained); + } + + // 1st - Transmit Success + OldValue = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart; + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart++; + + if (pAd->WlanCounters.TransmittedFragmentCount.u.LowPart < OldValue) + { + pAd->WlanCounters.TransmittedFragmentCount.u.HighPart++; + } + + if(((pAd->ContinBulkOut == TRUE ) ||(atomic_read(&pAd->BulkOutRemained) > 0)) && (pAd->ate.Mode & ATE_TXFRAME)) + { + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + } + else + { + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); +#ifdef RALINK_28xx_QA + pAd->ate.TxStatus = 0; +#endif // RALINK_28xx_QA // + } + + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + pAd->BulkOutPending[BulkOutPipeId] = FALSE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + // Always call Bulk routine, even reset bulk. + // The protection of rest bulk should be in BulkOut routine. + RTUSBKickBulkOut(pAd); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID ATE_RTUSBBulkOutDataPacket( + IN PRTMP_ADAPTER pAd, + IN UCHAR BulkOutPipeId) +{ + PTX_CONTEXT pNullContext = &(pAd->NullContext); + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; + + + ASSERT(BulkOutPipeId == 0); + + /* Build up the frame first. */ +// ATESetUpFrame(pAd, 0); + + BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + if (pAd->BulkOutPending[BulkOutPipeId] == TRUE) + { + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + return; + } + + pAd->BulkOutPending[BulkOutPipeId] = TRUE; + BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); + + // Increase Total transmit byte counter + pAd->RalinkCounters.OneSecTransmittedByteCount += pNullContext->BulkOutSize; + pAd->RalinkCounters.TransmittedByteCount += pNullContext->BulkOutSize; + + // Clear ATE frame bulk out flag + RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); + + // Init Tx context descriptor + pNullContext->IRPPending = TRUE; + RTUSBInitTxDesc(pAd, pNullContext, BulkOutPipeId, (usb_complete_t)ATE_RTUSBBulkOutDataPacketComplete); + pUrb = pNullContext->pUrb; + + if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("ATE_RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret)); + return; + } + + pAd->BulkOutReq++; + return; + +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID ATE_RTUSBCancelPendingBulkInIRP( + IN PRTMP_ADAPTER pAd) +{ + PRX_CONTEXT pRxContext; + UINT i; + + ATEDBGPRINT(RT_DEBUG_TRACE, ("--->ATE_RTUSBCancelPendingBulkInIRP\n")); +#if 1 + for ( i = 0; i < (RX_RING_SIZE); i++) + { + pRxContext = &(pAd->RxContext[i]); + if(pRxContext->IRPPending == TRUE) + { + RTUSB_UNLINK_URB(pRxContext->pUrb); + pRxContext->IRPPending = FALSE; + pRxContext->InUse = FALSE; + //NdisInterlockedDecrement(&pAd->PendingRx); + //pAd->PendingRx--; + } + } +#else + for ( i = 0; i < (RX_RING_SIZE); i++) + { + pRxContext = &(pAd->RxContext[i]); + if(atomic_read(&pRxContext->IrpLock) == IRPLOCK_CANCELABLE) + { + RTUSB_UNLINK_URB(pRxContext->pUrb); + } + InterlockedExchange(&pRxContext->IrpLock, IRPLOCK_CANCE_START); + } +#endif // 1 // + ATEDBGPRINT(RT_DEBUG_TRACE, ("<---ATE_RTUSBCancelPendingBulkInIRP\n")); + return; +} +#endif // RT2870 // + +VOID rt_ee_read_all(PRTMP_ADAPTER pAd, USHORT *Data) +{ + USHORT i; + USHORT value; + + for (i = 0 ; i < EEPROM_SIZE/2 ; ) + { + /* "value" is expecially for some compilers... */ + RT28xx_EEPROM_READ16(pAd, i*2, value); + Data[i] = value; + i++; + } +} + +VOID rt_ee_write_all(PRTMP_ADAPTER pAd, USHORT *Data) +{ + USHORT i; + USHORT value; + + for (i = 0 ; i < EEPROM_SIZE/2 ; ) + { + /* "value" is expecially for some compilers... */ + value = Data[i]; + RT28xx_EEPROM_WRITE16(pAd, i*2, value); + i ++; + } +} +#ifdef RALINK_28xx_QA +VOID ATE_QA_Statistics( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxD, + IN PHEADER_802_11 pHeader) +{ + // update counter first + if (pHeader != NULL) + { + if (pHeader->FC.Type == BTYPE_DATA) + { + if (pRxD->U2M) + pAd->ate.U2M++; + else + pAd->ate.OtherData++; + } + else if (pHeader->FC.Type == BTYPE_MGMT) + { + if (pHeader->FC.SubType == SUBTYPE_BEACON) + pAd->ate.Beacon++; + else + pAd->ate.OtherCount++; + } + else if (pHeader->FC.Type == BTYPE_CNTL) + { + pAd->ate.OtherCount++; + } + } + pAd->ate.RSSI0 = pRxWI->RSSI0; + pAd->ate.RSSI1 = pRxWI->RSSI1; + pAd->ate.RSSI2 = pRxWI->RSSI2; + pAd->ate.SNR0 = pRxWI->SNR0; + pAd->ate.SNR1 = pRxWI->SNR1; +} + +/* command id with Cmd Type == 0x0008(for 28xx)/0x0005(for iNIC) */ +#define RACFG_CMD_RF_WRITE_ALL 0x0000 +#define RACFG_CMD_E2PROM_READ16 0x0001 +#define RACFG_CMD_E2PROM_WRITE16 0x0002 +#define RACFG_CMD_E2PROM_READ_ALL 0x0003 +#define RACFG_CMD_E2PROM_WRITE_ALL 0x0004 +#define RACFG_CMD_IO_READ 0x0005 +#define RACFG_CMD_IO_WRITE 0x0006 +#define RACFG_CMD_IO_READ_BULK 0x0007 +#define RACFG_CMD_BBP_READ8 0x0008 +#define RACFG_CMD_BBP_WRITE8 0x0009 +#define RACFG_CMD_BBP_READ_ALL 0x000a +#define RACFG_CMD_GET_COUNTER 0x000b +#define RACFG_CMD_CLEAR_COUNTER 0x000c + +#define RACFG_CMD_RSV1 0x000d +#define RACFG_CMD_RSV2 0x000e +#define RACFG_CMD_RSV3 0x000f + +#define RACFG_CMD_TX_START 0x0010 +#define RACFG_CMD_GET_TX_STATUS 0x0011 +#define RACFG_CMD_TX_STOP 0x0012 +#define RACFG_CMD_RX_START 0x0013 +#define RACFG_CMD_RX_STOP 0x0014 +#define RACFG_CMD_GET_NOISE_LEVEL 0x0015 + +#define RACFG_CMD_ATE_START 0x0080 +#define RACFG_CMD_ATE_STOP 0x0081 + +#define RACFG_CMD_ATE_START_TX_CARRIER 0x0100 +#define RACFG_CMD_ATE_START_TX_CONT 0x0101 +#define RACFG_CMD_ATE_START_TX_FRAME 0x0102 +#define RACFG_CMD_ATE_SET_BW 0x0103 +#define RACFG_CMD_ATE_SET_TX_POWER0 0x0104 +#define RACFG_CMD_ATE_SET_TX_POWER1 0x0105 +#define RACFG_CMD_ATE_SET_FREQ_OFFSET 0x0106 +#define RACFG_CMD_ATE_GET_STATISTICS 0x0107 +#define RACFG_CMD_ATE_RESET_COUNTER 0x0108 +#define RACFG_CMD_ATE_SEL_TX_ANTENNA 0x0109 +#define RACFG_CMD_ATE_SEL_RX_ANTENNA 0x010a +#define RACFG_CMD_ATE_SET_PREAMBLE 0x010b +#define RACFG_CMD_ATE_SET_CHANNEL 0x010c +#define RACFG_CMD_ATE_SET_ADDR1 0x010d +#define RACFG_CMD_ATE_SET_ADDR2 0x010e +#define RACFG_CMD_ATE_SET_ADDR3 0x010f +#define RACFG_CMD_ATE_SET_RATE 0x0110 +#define RACFG_CMD_ATE_SET_TX_FRAME_LEN 0x0111 +#define RACFG_CMD_ATE_SET_TX_FRAME_COUNT 0x0112 +#define RACFG_CMD_ATE_START_RX_FRAME 0x0113 +#define RACFG_CMD_ATE_E2PROM_READ_BULK 0x0114 +#define RACFG_CMD_ATE_E2PROM_WRITE_BULK 0x0115 +#define RACFG_CMD_ATE_IO_WRITE_BULK 0x0116 +#define RACFG_CMD_ATE_BBP_READ_BULK 0x0117 +#define RACFG_CMD_ATE_BBP_WRITE_BULK 0x0118 +#define RACFG_CMD_ATE_RF_READ_BULK 0x0119 +#define RACFG_CMD_ATE_RF_WRITE_BULK 0x011a + + + +#define A2Hex(_X, _p) \ +{ \ + UCHAR *p; \ + _X = 0; \ + p = _p; \ + while (((*p >= 'a') && (*p <= 'f')) || ((*p >= 'A') && (*p <= 'F')) || ((*p >= '0') && (*p <= '9'))) \ + { \ + if ((*p >= 'a') && (*p <= 'f')) \ + _X = _X * 16 + *p - 87; \ + else if ((*p >= 'A') && (*p <= 'F')) \ + _X = _X * 16 + *p - 55; \ + else if ((*p >= '0') && (*p <= '9')) \ + _X = _X * 16 + *p - 48; \ + p++; \ + } \ +} + + +static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len); +static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len); +static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len); + +#ifdef UCOS +int ate_copy_to_user( + IN PUCHAR payload, + IN PUCHAR msg, + IN INT len) +{ + memmove(payload, msg, len); + return 0; +} + +#undef copy_to_user +#define copy_to_user(x,y,z) ate_copy_to_user((PUCHAR)x, (PUCHAR)y, z) +#endif // UCOS // + +#define LEN_OF_ARG 16 + +VOID RtmpDoAte( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + unsigned short Command_Id; + struct ate_racfghdr *pRaCfg; + INT Status = NDIS_STATUS_SUCCESS; + + + + if((pRaCfg = kmalloc(sizeof(struct ate_racfghdr), GFP_KERNEL)) == NULL) + { + Status = -EINVAL; + return; + } + + NdisZeroMemory(pRaCfg, sizeof(struct ate_racfghdr)); + + if (copy_from_user((PUCHAR)pRaCfg, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + kfree(pRaCfg); + return; + } + + + Command_Id = ntohs(pRaCfg->command_id); + + ATEDBGPRINT(RT_DEBUG_TRACE,("\n%s: Command_Id = 0x%04x !\n", __FUNCTION__, Command_Id)); + + switch (Command_Id) + { + // We will get this command when QA starts. + case RACFG_CMD_ATE_START: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START\n")); + + // prepare feedback as soon as we can to avoid QA timeout. + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_ATE_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START is done !\n")); + } + Set_ATE_Proc(pAdapter, "ATESTART"); + } + break; + + // We will get this command either QA is closed or ated is killed by user. + case RACFG_CMD_ATE_STOP: + { +#ifndef UCOS + INT32 ret; +#endif // !UCOS // + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_STOP\n")); + + // Distinguish this command came from QA(via ated) + // or ate daemon according to the existence of pid in payload. + // No need to prepare feedback if this cmd came directly from ate daemon. + pRaCfg->length = ntohs(pRaCfg->length); + + if (pRaCfg->length == sizeof(pAdapter->ate.AtePid)) + { + // This command came from QA. + // Get the pid of ATE daemon. + memcpy((UCHAR *)&pAdapter->ate.AtePid, + (&pRaCfg->data[0]) - 2/* == &(pRaCfg->status) */, + sizeof(pAdapter->ate.AtePid)); + + // prepare feedback as soon as we can to avoid QA timeout. + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_STOP\n")); + Status = -EFAULT; + } + + // + // kill ATE daemon when leaving ATE mode. + // We must kill ATE daemon first before setting ATESTOP, + // or Microsoft will report sth. wrong. +#ifndef UCOS + ret = kill_proc(pAdapter->ate.AtePid, SIGTERM, 1); + if (ret) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("%s: unable to signal thread\n", pAdapter->net_dev->name)); + } +#endif // !UCOS // + } + +#ifdef UCOS + // Roger add to avoid error message after close QA + if (pAdapter->CSRBaseAddress == RT2860_CSR_ADDR) + { + + // prepare feedback as soon as we can to avoid QA timeout. + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_AP_START\n")); + Status = -EFAULT; + } + } +#endif // UCOS // + + // AP might have in ATE_STOP mode due to cmd from QA. + if (ATE_ON(pAdapter)) + { + // Someone has killed ate daemon while QA GUI is still open. + Set_ATE_Proc(pAdapter, "ATESTOP"); + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_AP_START is done !\n")); + } + } + break; + + case RACFG_CMD_RF_WRITE_ALL: + { + UINT32 R1, R2, R3, R4; + USHORT channel; + + memcpy(&R1, pRaCfg->data-2, 4); + memcpy(&R2, pRaCfg->data+2, 4); + memcpy(&R3, pRaCfg->data+6, 4); + memcpy(&R4, pRaCfg->data+10, 4); + memcpy(&channel, pRaCfg->data+14, 2); + + pAdapter->LatchRfRegs.R1 = ntohl(R1); + pAdapter->LatchRfRegs.R2 = ntohl(R2); + pAdapter->LatchRfRegs.R3 = ntohl(R3); + pAdapter->LatchRfRegs.R4 = ntohl(R4); + pAdapter->LatchRfRegs.Channel = ntohs(channel); + + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R1); + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R2); + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R3); + RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R4); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RF_WRITE_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RF_WRITE_ALL is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_READ16: + { + USHORT offset, value, tmp; + + offset = ntohs(pRaCfg->status); + /* "tmp" is expecially for some compilers... */ + RT28xx_EEPROM_READ16(pAdapter, offset, tmp); + value = tmp; + value = htons(value); + + ATEDBGPRINT(RT_DEBUG_TRACE,("EEPROM Read offset = 0x%04x, value = 0x%04x\n", offset, value)); + + // prepare feedback + pRaCfg->length = htons(4); + pRaCfg->status = htons(0); + memcpy(pRaCfg->data, &value, 2); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("sizeof(struct ate_racfghdr) = %d\n", sizeof(struct ate_racfghdr))); + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ16\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ16 is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_WRITE16: + { + USHORT offset, value; + + offset = ntohs(pRaCfg->status); + memcpy(&value, pRaCfg->data, 2); + value = ntohs(value); + RT28xx_EEPROM_WRITE16(pAdapter, offset, value); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE16\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_WRITE16 is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_READ_ALL: + { + USHORT buffer[EEPROM_SIZE/2]; + + rt_ee_read_all(pAdapter,(USHORT *)buffer); + memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer, EEPROM_SIZE); + + // prepare feedback + pRaCfg->length = htons(2+EEPROM_SIZE); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ_ALL is done !\n")); + } + } + break; + + case RACFG_CMD_E2PROM_WRITE_ALL: + { + USHORT buffer[EEPROM_SIZE/2]; + + NdisZeroMemory((UCHAR *)buffer, EEPROM_SIZE); + memcpy_exs(pAdapter, (UCHAR *)buffer, (UCHAR *)&pRaCfg->status, EEPROM_SIZE); + rt_ee_write_all(pAdapter,(USHORT *)buffer); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_E2PROM_WRITE_ALL is done !\n")); + } + + } + break; + + case RACFG_CMD_IO_READ: + { + UINT32 offset; + UINT32 value; + + memcpy(&offset, &pRaCfg->status, 4); + offset = ntohl(offset); + + // We do not need the base address. + // So just extract the offset out. + offset &= 0x0000FFFF; + RTMP_IO_READ32(pAdapter, offset, &value); + value = htonl(value); + + // prepare feedback + pRaCfg->length = htons(6); + pRaCfg->status = htons(0); + memcpy(pRaCfg->data, &value, 4); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ is done !\n")); + } + } + break; + + case RACFG_CMD_IO_WRITE: + { + UINT32 offset, value; + + memcpy(&offset, pRaCfg->data-2, 4); + memcpy(&value, pRaCfg->data+2, 4); + + offset = ntohl(offset); + + // We do not need the base address. + // So just extract out the offset. + offset &= 0x0000FFFF; + value = ntohl(value); + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_IO_WRITE: offset = %x, value = %x\n", offset, value)); + RTMP_IO_WRITE32(pAdapter, offset, value); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_WRITE\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_WRITE is done !\n")); + } + } + break; + + case RACFG_CMD_IO_READ_BULK: + { + UINT32 offset; + USHORT len; + + memcpy(&offset, &pRaCfg->status, 4); + offset = ntohl(offset); + + // We do not need the base address. + // So just extract the offset. + offset &= 0x0000FFFF; + memcpy(&len, pRaCfg->data+2, 2); + len = ntohs(len); + + if (len > 371) + { + ATEDBGPRINT(RT_DEBUG_TRACE,("len is too large, make it smaller\n")); + pRaCfg->length = htons(2); + pRaCfg->status = htons(1); + break; + } + + RTMP_IO_READ_BULK(pAdapter, pRaCfg->data, (UCHAR *)offset, len*4);// unit in four bytes + + // prepare feedback + pRaCfg->length = htons(2+len*4);// unit in four bytes + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ_BULK is done !\n")); + } + } + break; + + case RACFG_CMD_BBP_READ8: + { + USHORT offset; + UCHAR value; + + value = 0; + offset = ntohs(pRaCfg->status); + + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value); + } + // prepare feedback + pRaCfg->length = htons(3); + pRaCfg->status = htons(0); + pRaCfg->data[0] = value; + + ATEDBGPRINT(RT_DEBUG_TRACE,("BBP value = %x\n", value)); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ8\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ8 is done !\n")); + } + } + break; + case RACFG_CMD_BBP_WRITE8: + { + USHORT offset; + UCHAR value; + + offset = ntohs(pRaCfg->status); + memcpy(&value, pRaCfg->data, 1); + + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value); + } + + if ((offset == BBP_R1) || (offset == BBP_R3)) + { + SyncTxRxConfig(pAdapter, offset, value); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_WRITE8\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_WRITE8 is done !\n")); + } + } + break; + + case RACFG_CMD_BBP_READ_ALL: + { + USHORT j; + + for (j = 0; j < 137; j++) + { + pRaCfg->data[j] = 0; + + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j]); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j]); + } + } + + // prepare feedback + pRaCfg->length = htons(2+137); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ_ALL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ_ALL is done !\n")); + } + } + + break; + + case RACFG_CMD_ATE_E2PROM_READ_BULK: + { + USHORT offset; + USHORT len; + USHORT buffer[EEPROM_SIZE/2]; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + rt_ee_read_all(pAdapter,(USHORT *)buffer); + if (offset + len <= EEPROM_SIZE) + memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer+offset, len); + else + ATEDBGPRINT(RT_DEBUG_ERROR, ("exceed EEPROM size\n")); + + // prepare feedback + pRaCfg->length = htons(2+len); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_E2PROM_READ_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_E2PROM_WRITE_BULK: + { + USHORT offset; + USHORT len; + USHORT buffer[EEPROM_SIZE/2]; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + rt_ee_read_all(pAdapter,(USHORT *)buffer); + memcpy_exs(pAdapter, (UCHAR *)buffer + offset, (UCHAR *)pRaCfg->data + 2, len); + rt_ee_write_all(pAdapter,(USHORT *)buffer); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_E2PROM_WRITE_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_IO_WRITE_BULK: + { + UINT32 offset, i, value; + USHORT len; + + memcpy(&offset, &pRaCfg->status, 4); + offset = ntohl(offset); + memcpy(&len, pRaCfg->data+2, 2); + len = ntohs(len); + + for (i = 0; i < len; i += 4) + { + memcpy_exl(pAdapter, (UCHAR *)&value, pRaCfg->data+4+i, 4); + printk("Write %x %x\n", offset + i, value); + RTMP_IO_WRITE32(pAdapter, (offset +i) & 0xffff, value); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_IO_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_IO_WRITE_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_BBP_READ_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + + for (j = offset; j < (offset+len); j++) + { + pRaCfg->data[j - offset] = 0; + + if (pAdapter->ate.Mode == ATE_STOP) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]); + } + else + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]); + } + } + + // prepare feedback + pRaCfg->length = htons(2+len); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_READ_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_BBP_WRITE_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + UCHAR *value; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + for (j = offset; j < (offset+len); j++) + { + value = pRaCfg->data + 2 + (j - offset); + if (pAdapter->ate.Mode == ATE_STOP) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value); + } + else + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value); + } + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_WRITE_BULK is done !\n")); + } + } + break; + +#ifdef CONFIG_RALINK_RT3052 + case RACFG_CMD_ATE_RF_READ_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + for (j = offset; j < (offset+len); j++) + { + pRaCfg->data[j - offset] = 0; + RT30xxReadRFRegister(pAdapter, j, &pRaCfg->data[j - offset]); + } + + // prepare feedback + pRaCfg->length = htons(2+len); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_READ_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_READ_BULK is done !\n")); + } + + } + break; + + case RACFG_CMD_ATE_RF_WRITE_BULK: + { + USHORT offset; + USHORT len; + USHORT j; + UCHAR *value; + + offset = ntohs(pRaCfg->status); + memcpy(&len, pRaCfg->data, 2); + len = ntohs(len); + + for (j = offset; j < (offset+len); j++) + { + value = pRaCfg->data + 2 + (j - offset); + RT30xxWriteRFRegister(pAdapter, j, *value); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_WRITE_BULK\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_WRITE_BULK is done !\n")); + } + + } + break; +#endif + + + case RACFG_CMD_GET_NOISE_LEVEL: + { + UCHAR channel; + INT32 buffer[3][10];/* 3 : RxPath ; 10 : no. of per rssi samples */ + + channel = (ntohs(pRaCfg->status) & 0x00FF); + CalNoiseLevel(pAdapter, channel, buffer); + memcpy_exl(pAdapter, (UCHAR *)pRaCfg->data, (UCHAR *)&(buffer[0][0]), (sizeof(INT32)*3*10)); + + // prepare feedback + pRaCfg->length = htons(2 + (sizeof(INT32)*3*10)); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_NOISE_LEVEL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_NOISE_LEVEL is done !\n")); + } + } + break; + + case RACFG_CMD_GET_COUNTER: + { + memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.U2M, 4); + memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->ate.OtherData, 4); + memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->ate.Beacon, 4); + memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->ate.OtherCount, 4); + memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->ate.TxAc0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->ate.TxAc1, 4); + memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->ate.TxAc2, 4); + memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->ate.TxAc3, 4); + memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->ate.TxHCCA, 4); + memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->ate.TxMgmt, 4); + memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&pAdapter->ate.RSSI0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&pAdapter->ate.RSSI1, 4); + memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&pAdapter->ate.RSSI2, 4); + memcpy_exl(pAdapter, &pRaCfg->data[52], (UCHAR *)&pAdapter->ate.SNR0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[56], (UCHAR *)&pAdapter->ate.SNR1, 4); + + pRaCfg->length = htons(2+60); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_COUNTER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_COUNTER is done !\n")); + } + } + break; + + case RACFG_CMD_CLEAR_COUNTER: + { + pAdapter->ate.U2M = 0; + pAdapter->ate.OtherData = 0; + pAdapter->ate.Beacon = 0; + pAdapter->ate.OtherCount = 0; + pAdapter->ate.TxAc0 = 0; + pAdapter->ate.TxAc1 = 0; + pAdapter->ate.TxAc2 = 0; + pAdapter->ate.TxAc3 = 0; + pAdapter->ate.TxHCCA = 0; + pAdapter->ate.TxMgmt = 0; + pAdapter->ate.TxDoneCount = 0; + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_CLEAR_COUNTER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_CLEAR_COUNTER is done !\n")); + } + } + + break; + + case RACFG_CMD_TX_START: + { + USHORT *p; + USHORT err = 1; + UCHAR Bbp22Value = 0, Bbp24Value = 0; + + if ((pAdapter->ate.TxStatus != 0) && (pAdapter->ate.Mode & ATE_TXFRAME)) + { + ATEDBGPRINT(RT_DEBUG_TRACE,("Ate Tx is already running, to run next Tx, you must stop it first\n")); + err = 2; + goto TX_START_ERROR; + } + else if ((pAdapter->ate.TxStatus != 0) && !(pAdapter->ate.Mode & ATE_TXFRAME)) + { + int i = 0; + + while ((i++ < 10) && (pAdapter->ate.TxStatus != 0)) + { + RTMPusecDelay(5000); + } + + // force it to stop + pAdapter->ate.TxStatus = 0; + pAdapter->ate.TxDoneCount = 0; + //pAdapter->ate.Repeat = 0; + pAdapter->ate.bQATxStart = FALSE; + } + + // If pRaCfg->length == 0, this "RACFG_CMD_TX_START" is for Carrier test or Carrier Suppression. + if (ntohs(pRaCfg->length) != 0) + { + // Get frame info +#ifdef RT2870 + NdisMoveMemory(&pAdapter->ate.TxInfo, pRaCfg->data - 2, 4); +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR) &pAdapter->ate.TxInfo, TYPE_TXINFO); +#endif // RT_BIG_ENDIAN // +#endif // RT2870 // + + NdisMoveMemory(&pAdapter->ate.TxWI, pRaCfg->data + 2, 16); +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange((PUCHAR)&pAdapter->ate.TxWI, TYPE_TXWI); +#endif // RT_BIG_ENDIAN // + + NdisMoveMemory(&pAdapter->ate.TxCount, pRaCfg->data + 18, 4); + pAdapter->ate.TxCount = ntohl(pAdapter->ate.TxCount); + + p = (USHORT *)(&pRaCfg->data[22]); + //p = pRaCfg->data + 22; + // always use QID_AC_BE + pAdapter->ate.QID = 0; + p = (USHORT *)(&pRaCfg->data[24]); + //p = pRaCfg->data + 24; + pAdapter->ate.HLen = ntohs(*p); + + if (pAdapter->ate.HLen > 32) + { + ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.HLen > 32\n")); + err = 3; + goto TX_START_ERROR; + } + + NdisMoveMemory(&pAdapter->ate.Header, pRaCfg->data + 26, pAdapter->ate.HLen); + + + pAdapter->ate.PLen = ntohs(pRaCfg->length) - (pAdapter->ate.HLen + 28); + + if (pAdapter->ate.PLen > 32) + { + ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.PLen > 32\n")); + err = 4; + goto TX_START_ERROR; + } + + NdisMoveMemory(&pAdapter->ate.Pattern, pRaCfg->data + 26 + pAdapter->ate.HLen, pAdapter->ate.PLen); + pAdapter->ate.DLen = pAdapter->ate.TxWI.MPDUtotalByteCount - pAdapter->ate.HLen; + } + + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R22, &Bbp22Value); + + switch (Bbp22Value) + { + case BBP22_TXFRAME: + { + if (pAdapter->ate.TxCount == 0) + { + } + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXFRAME\n")); + pAdapter->ate.bQATxStart = TRUE; + Set_ATE_Proc(pAdapter, "TXFRAME"); + } + break; + + case BBP22_TXCONT_OR_CARRSUPP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("BBP22_TXCONT_OR_CARRSUPP\n")); + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, 24, &Bbp24Value); + + switch (Bbp24Value) + { + case BBP24_TXCONT: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCONT\n")); + pAdapter->ate.bQATxStart = TRUE; + Set_ATE_Proc(pAdapter, "TXCONT"); + } + break; + + case BBP24_CARRSUPP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARRSUPP\n")); + pAdapter->ate.bQATxStart = TRUE; + pAdapter->ate.Mode |= ATE_TXCARRSUPP; + } + break; + + default: + { + ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !")); + } + break; + } + } + break; + + case BBP22_TXCARR: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARR\n")); + pAdapter->ate.bQATxStart = TRUE; + Set_ATE_Proc(pAdapter, "TXCARR"); + } + break; + + default: + { + ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !")); + } + break; + } + + if (pAdapter->ate.bQATxStart == TRUE) + { + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() was failed in case RACFG_CMD_TX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_START is done !\n")); + } + break; + } + +TX_START_ERROR: + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(err); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_TX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("feedback of TX_START_ERROR is done !\n")); + } + } + break; + + case RACFG_CMD_GET_TX_STATUS: + { + UINT32 count; + + // prepare feedback + pRaCfg->length = htons(6); + pRaCfg->status = htons(0); + count = htonl(pAdapter->ate.TxDoneCount); + NdisMoveMemory(pRaCfg->data, &count, 4); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_TX_STATUS\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_TX_STATUS is done !\n")); + } + } + break; + + case RACFG_CMD_TX_STOP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_TX_STOP\n")); + + Set_ATE_Proc(pAdapter, "TXSTOP"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_TX_STOP\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_STOP is done !\n")); + } + } + break; + + case RACFG_CMD_RX_START: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); + + pAdapter->ate.bQARxStart = TRUE; + Set_ATE_Proc(pAdapter, "RXFRAME"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n")); + } + } + break; + + case RACFG_CMD_RX_STOP: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_STOP\n")); + + Set_ATE_Proc(pAdapter, "RXSTOP"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_STOP\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_STOP is done !\n")); + } + } + break; + + /* The following cases are for new ATE GUI(not QA). */ + /*==================================================*/ + case RACFG_CMD_ATE_START_TX_CARRIER: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CARRIER\n")); + + Set_ATE_Proc(pAdapter, "TXCARR"); + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CARRIER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CARRIER is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_START_TX_CONT: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CONT\n")); + + Set_ATE_Proc(pAdapter, "TXCONT"); + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CONT\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CONT is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_START_TX_FRAME: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_FRAME\n")); + + Set_ATE_Proc(pAdapter, "TXFRAME"); + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length)); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_FRAME\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_FRAME is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_BW: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_BW\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + + Set_ATE_TX_BW_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_BW\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_BW is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_POWER0: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER0\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_POWER0_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER0\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER0 is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_POWER1: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER1\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_POWER1_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER1\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER1 is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_FREQ_OFFSET: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_FREQ_OFFSET\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_FREQOFFSET_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_FREQ_OFFSET\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_FREQ_OFFSET is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_GET_STATISTICS: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_GET_STATISTICS\n")); + + memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.TxDoneCount, 4); + memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->WlanCounters.RetryCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->WlanCounters.FailedCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->WlanCounters.RTSSuccessCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->WlanCounters.RTSFailureCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->WlanCounters.FCSErrorCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->Counters8023.RxNoBuffer, 4); + memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart, 4); + memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->RalinkCounters.OneSecFalseCCACnt, 4); + + if (pAdapter->ate.RxAntennaSel == 0) + { + INT32 RSSI0 = 0; + INT32 RSSI1 = 0; + INT32 RSSI2 = 0; + + RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta); + RSSI1 = (INT32)(pAdapter->ate.LastRssi1 - pAdapter->BbpRssiToDbmDelta); + RSSI2 = (INT32)(pAdapter->ate.LastRssi2 - pAdapter->BbpRssiToDbmDelta); + memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); + memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&RSSI1, 4); + memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&RSSI2, 4); + pRaCfg->length = htons(2+52); + } + else + { + INT32 RSSI0 = 0; + + RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta); + memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4); + pRaCfg->length = htons(2+44); + } + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_GET_STATISTICS\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_GET_STATISTICS is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_RESET_COUNTER: + { + SHORT value = 1; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_RESET_COUNTER\n")); + + sprintf((PCHAR)str, "%d", value); + Set_ResetStatCounter_Proc(pAdapter, str); + + pAdapter->ate.TxDoneCount = 0; + + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RESET_COUNTER\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RESET_COUNTER is done !\n")); + } + } + + break; + + case RACFG_CMD_ATE_SEL_TX_ANTENNA: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_TX_ANTENNA\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_Antenna_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_TX_ANTENNA\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_TX_ANTENNA is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SEL_RX_ANTENNA: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_RX_ANTENNA\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_RX_Antenna_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_RX_ANTENNA\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_RX_ANTENNA is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_PREAMBLE: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_PREAMBLE\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_MODE_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_PREAMBLE\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_PREAMBLE is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_CHANNEL: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_CHANNEL\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_CHANNEL_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_CHANNEL\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_CHANNEL is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_ADDR1: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR1\n")); + + // Addr is an array of UCHAR, + // so no need to perform endian swap. + memcpy(pAdapter->ate.Addr1, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR1\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR1 is done !\n (ADDR1 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr1[0], + pAdapter->ate.Addr1[1], pAdapter->ate.Addr1[2], pAdapter->ate.Addr1[3], pAdapter->ate.Addr1[4], pAdapter->ate.Addr1[5])); + } + } + break; + + case RACFG_CMD_ATE_SET_ADDR2: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR2\n")); + + // Addr is an array of UCHAR, + // so no need to perform endian swap. + memcpy(pAdapter->ate.Addr2, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR2\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR2 is done !\n (ADDR2 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr2[0], + pAdapter->ate.Addr2[1], pAdapter->ate.Addr2[2], pAdapter->ate.Addr2[3], pAdapter->ate.Addr2[4], pAdapter->ate.Addr2[5])); + } + } + break; + + case RACFG_CMD_ATE_SET_ADDR3: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR3\n")); + + // Addr is an array of UCHAR, + // so no need to perform endian swap. + memcpy(pAdapter->ate.Addr3, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR3\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR3 is done !\n (ADDR3 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr3[0], + pAdapter->ate.Addr3[1], pAdapter->ate.Addr3[2], pAdapter->ate.Addr3[3], pAdapter->ate.Addr3[4], pAdapter->ate.Addr3[5])); + } + } + break; + + case RACFG_CMD_ATE_SET_RATE: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_RATE\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_MCS_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_RATE\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_RATE is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_FRAME_LEN: + { + SHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_LEN\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_LENGTH_Proc(pAdapter, str); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_LEN\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_LEN is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_SET_TX_FRAME_COUNT: + { + USHORT value = 0; + UCHAR str[LEN_OF_ARG]; + + NdisZeroMemory(str, LEN_OF_ARG); + + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n")); + + memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2); + value = ntohs(value); + { + sprintf((PCHAR)str, "%d", value); + Set_ATE_TX_COUNT_Proc(pAdapter, str); + } + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_COUNT is done !\n")); + } + } + break; + + case RACFG_CMD_ATE_START_RX_FRAME: + { + ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n")); + + Set_ATE_Proc(pAdapter, "RXFRAME"); + + // prepare feedback + pRaCfg->length = htons(2); + pRaCfg->status = htons(0); + wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type) + + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length) + + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length); + + if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length)) + { + ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n")); + Status = -EFAULT; + } + else + { + ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n")); + } + } + break; + default: + break; + } + ASSERT(pRaCfg != NULL); + if (pRaCfg != NULL) + { + kfree(pRaCfg); + } + return; +} + +VOID BubbleSort(INT32 n, INT32 a[]) +{ + INT32 k, j, temp; + + for (k = n-1; k>0; k--) + { + for (j = 0; j a[j+1]) + { + temp = a[j]; + a[j]=a[j+1]; + a[j+1]=temp; + } + } + } +} + +VOID CalNoiseLevel(PRTMP_ADAPTER pAd, UCHAR channel, INT32 RSSI[3][10]) +{ + INT32 RSSI0, RSSI1, RSSI2; + CHAR Rssi0Offset, Rssi1Offset, Rssi2Offset; + UCHAR BbpR50Rssi0 = 0, BbpR51Rssi1 = 0, BbpR52Rssi2 = 0; + UCHAR Org_BBP66value = 0, Org_BBP69value = 0, Org_BBP70value = 0, data = 0; + USHORT LNA_Gain = 0; + INT32 j = 0; + UCHAR Org_Channel = pAd->ate.Channel; + USHORT GainValue = 0, OffsetValue = 0; + + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &Org_BBP66value); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R69, &Org_BBP69value); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R70, &Org_BBP70value); + + //********************************************************************** + // Read the value of LNA gain and Rssi offset + //********************************************************************** + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, GainValue); + + // for Noise Level + if (channel <= 14) + { + LNA_Gain = GainValue & 0x00FF; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, OffsetValue); + Rssi0Offset = OffsetValue & 0x00FF; + Rssi1Offset = (OffsetValue & 0xFF00) >> 8; + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_BG_OFFSET + 2)/* 0x48 */, OffsetValue); + Rssi2Offset = OffsetValue & 0x00FF; + } + else + { + LNA_Gain = (GainValue & 0xFF00) >> 8; + + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, OffsetValue); + Rssi0Offset = OffsetValue & 0x00FF; + Rssi1Offset = (OffsetValue & 0xFF00) >> 8; + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET + 2)/* 0x4C */, OffsetValue); + Rssi2Offset = OffsetValue & 0x00FF; + } + //********************************************************************** + { + pAd->ate.Channel = channel; + ATEAsicSwitchChannel(pAd); + mdelay(5); + + data = 0x10; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data); + data = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, data); + data = 0x40; + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, data); + mdelay(5); + + // Start Rx + pAd->ate.bQARxStart = TRUE; + Set_ATE_Proc(pAd, "RXFRAME"); + + mdelay(5); + + for (j = 0; j < 10; j++) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R50, &BbpR50Rssi0); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R51, &BbpR51Rssi1); + ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R52, &BbpR52Rssi2); + + mdelay(10); + + // Calculate RSSI 0 + if (BbpR50Rssi0 == 0) + { + RSSI0 = -100; + } + else + { + RSSI0 = (INT32)(-12 - BbpR50Rssi0 - LNA_Gain - Rssi0Offset); + } + RSSI[0][j] = RSSI0; + + if ( pAd->Antenna.field.RxPath >= 2 ) // 2R + { + // Calculate RSSI 1 + if (BbpR51Rssi1 == 0) + { + RSSI1 = -100; + } + else + { + RSSI1 = (INT32)(-12 - BbpR51Rssi1 - LNA_Gain - Rssi1Offset); + } + RSSI[1][j] = RSSI1; + } + + if ( pAd->Antenna.field.RxPath >= 3 ) // 3R + { + // Calculate RSSI 2 + if (BbpR52Rssi2 == 0) + RSSI2 = -100; + else + RSSI2 = (INT32)(-12 - BbpR52Rssi2 - LNA_Gain - Rssi2Offset); + + RSSI[2][j] = RSSI2; + } + } + + // Stop Rx + Set_ATE_Proc(pAd, "RXSTOP"); + + mdelay(5); + + BubbleSort(10, RSSI[0]); // 1R + + if ( pAd->Antenna.field.RxPath >= 2 ) // 2R + { + BubbleSort(10, RSSI[1]); + } + + if ( pAd->Antenna.field.RxPath >= 3 ) // 3R + { + BubbleSort(10, RSSI[2]); + } + + } + + pAd->ate.Channel = Org_Channel; + ATEAsicSwitchChannel(pAd); + + // Restore original value + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, Org_BBP69value); + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, Org_BBP70value); + + return; +} + +BOOLEAN SyncTxRxConfig(PRTMP_ADAPTER pAd, USHORT offset, UCHAR value) +{ + UCHAR tmp = 0, bbp_data = 0; + + if (ATE_ON(pAd)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data); + } + + /* confirm again */ + ASSERT(bbp_data == value); + + switch(offset) + { + case BBP_R1: + /* Need to sync. tx configuration with legacy ATE. */ + tmp = (bbp_data & ((1 << 4) | (1 << 3))/* 0x18 */) >> 3; + switch(tmp) + { + /* The BBP R1 bit[4:3] = 2 :: Both DACs will be used by QA. */ + case 2: + /* All */ + pAd->ate.TxAntennaSel = 0; + break; + /* The BBP R1 bit[4:3] = 0 :: DAC 0 will be used by QA. */ + case 0: + /* Antenna one */ + pAd->ate.TxAntennaSel = 1; + break; + /* The BBP R1 bit[4:3] = 1 :: DAC 1 will be used by QA. */ + case 1: + /* Antenna two */ + pAd->ate.TxAntennaSel = 2; + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); + return FALSE; + } + break;/* case BBP_R1 */ + + case BBP_R3: + /* Need to sync. rx configuration with legacy ATE. */ + tmp = (bbp_data & ((1 << 1) | (1 << 0))/* 0x03 */); + switch(tmp) + { + /* The BBP R3 bit[1:0] = 3 :: All ADCs will be used by QA. */ + case 3: + /* All */ + pAd->ate.RxAntennaSel = 0; + break; + /* The BBP R3 bit[1:0] = 0 :: ADC 0 will be used by QA, */ + /* unless the BBP R3 bit[4:3] = 2 */ + case 0: + /* Antenna one */ + pAd->ate.RxAntennaSel = 1; + tmp = ((bbp_data & ((1 << 4) | (1 << 3))/* 0x03 */) >> 3); + if (tmp == 2)// 3R + { + /* Default : All ADCs will be used by QA */ + pAd->ate.RxAntennaSel = 0; + } + break; + /* The BBP R3 bit[1:0] = 1 :: ADC 1 will be used by QA. */ + case 1: + /* Antenna two */ + pAd->ate.RxAntennaSel = 2; + break; + /* The BBP R3 bit[1:0] = 2 :: ADC 2 will be used by QA. */ + case 2: + /* Antenna three */ + pAd->ate.RxAntennaSel = 3; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s -- Impossible! : return FALSE; \n", __FUNCTION__)); + return FALSE; + } + break;/* case BBP_R3 */ + + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s -- Sth. wrong! : return FALSE; \n", __FUNCTION__)); + return FALSE; + + } + return TRUE; +} + +static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) +{ + ULONG i, Value = 0; + ULONG *pDst, *pSrc; + UCHAR *p8; + + p8 = src; + pDst = (ULONG *) dst; + pSrc = (ULONG *) src; + + for (i = 0 ; i < (len/4); i++) + { + /* For alignment issue, we need a variable "Value". */ + memmove(&Value, pSrc, 4); + Value = htonl(Value); + memmove(pDst, &Value, 4); + pDst++; + pSrc++; + } + if ((len % 4) != 0) + { + /* wish that it will never reach here */ + memmove(&Value, pSrc, (len % 4)); + Value = htonl(Value); + memmove(pDst, &Value, (len % 4)); + } +} + +static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) +{ + ULONG i; + UCHAR *pDst, *pSrc; + + pDst = dst; + pSrc = src; + + for (i = 0; i < (len/2); i++) + { + memmove(pDst, pSrc, 2); + *((USHORT *)pDst) = htons(*((USHORT *)pDst)); + pDst+=2; + pSrc+=2; + } + + if ((len % 2) != 0) + { + memmove(pDst, pSrc, 1); + } +} + +static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len) +{ + UINT32 i, Value; + UINT32 *pDst, *pSrc; + + pDst = (UINT32 *) dst; + pSrc = (UINT32 *) src; + + for (i = 0 ; i < (len/4); i++) + { + RTMP_IO_READ32(pAd, (ULONG)pSrc, &Value); + Value = htonl(Value); + memmove(pDst, &Value, 4); + pDst++; + pSrc++; + } + return; +} + +INT Set_TxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ATEDBGPRINT(RT_DEBUG_TRACE,("Set_TxStop_Proc\n")); + + if (Set_ATE_Proc(pAd, "TXSTOP")) + { + return TRUE; +} + else + { + return FALSE; + } +} + +INT Set_RxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + ATEDBGPRINT(RT_DEBUG_TRACE,("Set_RxStop_Proc\n")); + + if (Set_ATE_Proc(pAd, "RXSTOP")) + { + return TRUE; +} + else + { + return FALSE; + } +} +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + diff --git a/drivers/staging/rt3070/rt_ate.h b/drivers/staging/rt3070/rt_ate.h new file mode 100644 index 000000000000..829ebb5f7236 --- /dev/null +++ b/drivers/staging/rt3070/rt_ate.h @@ -0,0 +1,294 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + */ + +#ifndef __ATE_H__ +#define __ATE_H__ + +#ifndef UCOS +#define ate_print printk +#define ATEDBGPRINT DBGPRINT + +#ifdef RT2870 +#define EEPROM_SIZE 0x400 +#ifdef CONFIG_STA_SUPPORT +#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2870STA/e2p.bin" +#endif // CONFIG_STA_SUPPORT // +#endif // RT2870 // +#else // !UCOS // +#define fATE_LOAD_EEPROM 0x0C43 +#ifdef CONFIG_PRINTK +extern INT ConsoleResponse(IN PUCHAR buff); +extern int (*remote_display)(char *); +extern void puts (const char *s); + +/* specificly defined to redirect and show ate-related messages to host. */ +/* Try to define ate_print as a macro. */ +#define ate_print(fmt, args...) \ +do{ int (*org_remote_display)(char *) = NULL; \ + org_remote_display = remote_display;\ + /* Save original "remote_display" */\ + remote_display = (int (*)(char *))ConsoleResponse; \ + printk(fmt, ## args); \ + /* Restore the remote_display function pointer */ \ + remote_display = org_remote_display; }while(0) + +#define ATEDBGPRINT(Level, Fmt) \ +{ \ + if ((Level) <= RTDebugLevel) \ + { \ + ate_print Fmt; \ + } \ +} +#endif // CONFIG_PRINTK // +#endif // !UCOS // + +#define ATE_ON(_p) (((_p)->ate.Mode) != ATE_STOP) + +/* RT2880_iNIC will define "RT2860". */ + +/* RT2880_iNIC will define RT2860. */ + +#ifdef RT2870 +#define EEPROM_SIZE 0x400 +#ifdef CONFIG_STA_SUPPORT +#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2870STA/e2p.bin" +#endif // CONFIG_STA_SUPPORT // +#endif // RT2870 // + +#ifdef RT2870 +#define ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) +#define ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) + +#define BULK_OUT_LOCK(pLock, IrqFlags) \ + if(1 /*!(in_interrupt() & 0xffff0000)*/) \ + RTMP_IRQ_LOCK((pLock), IrqFlags); + +#define BULK_OUT_UNLOCK(pLock, IrqFlags) \ + if(1 /*!(in_interrupt() & 0xffff0000)*/) \ + RTMP_IRQ_UNLOCK((pLock), IrqFlags); + +// Prototypes of completion funuc. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define ATE_RTUSBBulkOutDataPacketComplete(purb, pt_regs) ATE_RTUSBBulkOutDataPacketComplete(purb) +#endif + +VOID ATE_RTUSBBulkOutDataPacketComplete( + IN purbb_t purb, + OUT struct pt_regs *pt_regs); + +VOID ATE_RTUSBBulkOutDataPacket( + IN PRTMP_ADAPTER pAd, + IN UCHAR BulkOutPipeId); + +VOID ATE_RTUSBCancelPendingBulkInIRP( + IN PRTMP_ADAPTER pAd); +#endif // RT2870 // + +#ifdef RT30xx +#define ATE_RF_IO_READ8_BY_REG_ID(_A, _I, _pV) RTMP_RF_IO_READ8_BY_REG_ID(_A, _I, _pV) +#define ATE_RF_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTMP_RF_IO_WRITE8_BY_REG_ID(_A, _I, _V) +#endif // RT30xx // + + +VOID rt_ee_read_all( + IN PRTMP_ADAPTER pAd, + OUT USHORT *Data); + + +VOID rt_ee_write_all( + IN PRTMP_ADAPTER pAd, + IN USHORT *Data); + +INT Set_ATE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_DA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_SA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_BSSID_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_CHANNEL_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_POWER0_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_POWER1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_RX_Antenna_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_FREQOFFSET_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_BW_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_LENGTH_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_COUNT_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_MCS_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_MODE_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_TX_GI_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + + +INT Set_ATE_RX_FER_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Read_RF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Write_RF1_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Write_RF2_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Write_RF3_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Write_RF4_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Load_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Read_E2P_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Show_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ATE_Help_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef RALINK_ATE +#ifdef RALINK_28xx_QA +VOID ATE_QA_Statistics( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC p28xxRxD, + IN PHEADER_802_11 pHeader); + +VOID RtmpDoAte( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); + +VOID BubbleSort( + IN INT32 n, + IN INT32 a[]); + +VOID CalNoiseLevel( + IN PRTMP_ADAPTER pAdapter, + IN UCHAR channel, + OUT INT32 buffer[3][10]); + +BOOLEAN SyncTxRxConfig( + IN PRTMP_ADAPTER pAdapter, + IN USHORT offset, + IN UCHAR value); + +INT Set_TxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_RxStop_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +VOID ATEAsicSwitchChannel( + IN PRTMP_ADAPTER pAd); + +VOID ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); + +VOID ATEDisableAsicProtect( + IN PRTMP_ADAPTER pAd); + +CHAR ATEConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber); + +VOID ATESampleRssi( + IN PRTMP_ADAPTER pAd, + IN PRXWI_STRUC pRxWI); + + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPStationStop( + IN PRTMP_ADAPTER pAd); + +VOID RTMPStationStart( + IN PRTMP_ADAPTER pAd); +#endif // CONFIG_STA_SUPPORT // +#endif // __ATE_H__ // diff --git a/drivers/staging/rt3070/rt_config.h b/drivers/staging/rt3070/rt_config.h new file mode 100644 index 000000000000..9e06417f63d3 --- /dev/null +++ b/drivers/staging/rt3070/rt_config.h @@ -0,0 +1,121 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rt_config.h + + Abstract: + Central header file to maintain all include files for all NDIS + miniport driver routines. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + +*/ +#ifndef __RT_CONFIG_H__ +#define __RT_CONFIG_H__ + +#include "rtmp_type.h" +#ifdef UCOS +#include "includes.h" +#include +#include "rt_ucos.h" +#endif + +#ifdef LINUX +#include "rt_linux.h" +#endif +#include "rtmp_def.h" +#include "rt28xx.h" + + +#ifdef RT2870 +#include "rt2870.h" +#endif // RT2870 // + +#include "oid.h" +#include "mlme.h" +#include "wpa.h" +#include "md5.h" +#include "rtmp.h" +#include "ap.h" +#include "dfs.h" +#include "chlist.h" +#include "spectrum.h" +#ifdef MLME_EX +#include "mlme_ex_def.h" +#include "mlme_ex.h" +#endif // MLME_EX // + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + + +#ifdef LEAP_SUPPORT +#include "leap.h" +#endif // LEAP_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + +#ifdef BLOCK_NET_IF +#include "netif_block.h" +#endif // BLOCK_NET_IF // + +#ifdef IGMP_SNOOP_SUPPORT +#include "igmp_snoop.h" +#endif // IGMP_SNOOP_SUPPORT // + +#ifdef RALINK_ATE +#include "rt_ate.h" +#endif // RALINK_ATE // + + + +#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) +#define WSC_INCLUDED +#endif + + +#ifdef CONFIG_STA_SUPPORT +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifndef WPA_SUPPLICANT_SUPPORT +#error "Build for being controlled by NetworkManager or wext, please set HAS_WPA_SUPPLICANT=y and HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y" +#endif // WPA_SUPPLICANT_SUPPORT // +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + +#endif // CONFIG_STA_SUPPORT // + + +#ifdef IKANOS_VX_1X0 +#include "vr_ikans.h" +#endif // IKANOS_VX_1X0 // + +#endif // __RT_CONFIG_H__ + diff --git a/drivers/staging/rt3070/rt_linux.c b/drivers/staging/rt3070/rt_linux.c new file mode 100644 index 000000000000..bf3385365da1 --- /dev/null +++ b/drivers/staging/rt3070/rt_linux.c @@ -0,0 +1,1063 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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 "rt_config.h" + +ULONG RTDebugLevel = RT_DEBUG_ERROR; + +BUILD_TIMER_FUNCTION(MlmePeriodicExec); +//BUILD_TIMER_FUNCTION(MlmeRssiReportExec); +BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout); +BUILD_TIMER_FUNCTION(APSDPeriodicExec); +BUILD_TIMER_FUNCTION(AsicRfTuningExec); +#ifdef RT2870 +BUILD_TIMER_FUNCTION(BeaconUpdateExec); +#endif // RT2870 // + + +#ifdef CONFIG_STA_SUPPORT +BUILD_TIMER_FUNCTION(BeaconTimeout); +BUILD_TIMER_FUNCTION(ScanTimeout); +BUILD_TIMER_FUNCTION(AuthTimeout); +BUILD_TIMER_FUNCTION(AssocTimeout); +BUILD_TIMER_FUNCTION(ReassocTimeout); +BUILD_TIMER_FUNCTION(DisassocTimeout); +BUILD_TIMER_FUNCTION(LinkDownExec); +#ifdef LEAP_SUPPORT +BUILD_TIMER_FUNCTION(LeapAuthTimeout); +#endif +BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec); +BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); +#ifdef QOS_DLS_SUPPORT +BUILD_TIMER_FUNCTION(DlsTimeoutAction); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + + + + +// for wireless system event message +char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = { + // system status event + "had associated successfully", /* IW_ASSOC_EVENT_FLAG */ + "had disassociated", /* IW_DISASSOC_EVENT_FLAG */ + "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */ + "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */ + "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */ + "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */ + "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */ + "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */ + "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */ + "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */ + "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */ + "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */ + "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */ + "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */ + "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */ + "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */ + "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */ + "scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */ + "scan terminate!! Busy!! Enqueue fail!!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */ + }; + +// for wireless IDS_spoof_attack event message +char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = { + "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */ + "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */ + "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */ + "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */ + "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */ + "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */ + "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */ + "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */ + "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */ + "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */ + }; + +// for wireless IDS_flooding_attack event message +char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = { + "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */ + "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */ + "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */ + "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */ + "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */ + "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */ + "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */ + }; + + +/* timeout -- ms */ +VOID RTMP_SetPeriodicTimer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout) +{ + timeout = ((timeout*HZ) / 1000); + pTimer->expires = jiffies + timeout; + add_timer(pTimer); +} + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +VOID RTMP_OS_Init_Timer( + IN PRTMP_ADAPTER pAd, + IN NDIS_MINIPORT_TIMER *pTimer, + IN TIMER_FUNCTION function, + IN PVOID data) +{ + init_timer(pTimer); + pTimer->data = (unsigned long)data; + pTimer->function = function; +} + + +VOID RTMP_OS_Add_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout) +{ + if (timer_pending(pTimer)) + return; + + timeout = ((timeout*HZ) / 1000); + pTimer->expires = jiffies + timeout; + add_timer(pTimer); +} + +VOID RTMP_OS_Mod_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout) +{ + timeout = ((timeout*HZ) / 1000); + mod_timer(pTimer, jiffies + timeout); +} + +VOID RTMP_OS_Del_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + OUT BOOLEAN *pCancelled) +{ + if (timer_pending(pTimer)) + { + *pCancelled = del_timer_sync(pTimer); + } + else + { + *pCancelled = TRUE; + } + +} + +VOID RTMP_OS_Release_Packet( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_ENTRY pEntry) +{ + //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); +} + +// Unify all delay routine by using udelay +VOID RTMPusecDelay( + IN ULONG usec) +{ + ULONG i; + + for (i = 0; i < (usec / 50); i++) + udelay(50); + + if (usec % 50) + udelay(usec % 50); +} + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time) +{ + time->u.LowPart = jiffies; +} + +// pAd MUST allow to be NULL +NDIS_STATUS os_alloc_mem( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR *mem, + IN ULONG size) +{ + *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC); + if (*mem) + return (NDIS_STATUS_SUCCESS); + else + return (NDIS_STATUS_FAILURE); +} + +// pAd MUST allow to be NULL +NDIS_STATUS os_free_mem( + IN PRTMP_ADAPTER pAd, + IN PUCHAR mem) +{ + + ASSERT(mem); + kfree(mem); + return (NDIS_STATUS_SUCCESS); +} + + +PNDIS_PACKET RTMP_AllocateFragPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length) +{ + struct sk_buff *pkt; + + pkt = dev_alloc_skb(Length); + + if (pkt == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length)); + } + + if (pkt) + { + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + } + + return (PNDIS_PACKET) pkt; +} + + +PNDIS_PACKET RTMP_AllocateTxPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress) +{ + struct sk_buff *pkt; + + pkt = dev_alloc_skb(Length); + + if (pkt == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length)); + } + + if (pkt) + { + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + *VirtualAddress = (PVOID) pkt->data; + } + else + { + *VirtualAddress = (PVOID) NULL; + } + + return (PNDIS_PACKET) pkt; +} + + +VOID build_tx_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pFrame, + IN ULONG FrameLen) +{ + + struct sk_buff *pTxPkt; + + ASSERT(pPacket); + pTxPkt = RTPKT_TO_OSPKT(pPacket); + + NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen); +} + +VOID RTMPFreeAdapter( + IN PRTMP_ADAPTER pAd) +{ + POS_COOKIE os_cookie; + int index; + + os_cookie=(POS_COOKIE)pAd->OS_Cookie; + + kfree(pAd->BeaconBuf); + + + NdisFreeSpinLock(&pAd->MgmtRingLock); + + + for (index =0 ; index < NUM_OF_TX_RING; index++) + { + NdisFreeSpinLock(&pAd->TxSwQueueLock[index]); + NdisFreeSpinLock(&pAd->DeQueueLock[index]); + pAd->DeQueueRunning[index] = FALSE; + } + + NdisFreeSpinLock(&pAd->irq_lock); + + + vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa); + kfree(os_cookie); +} + +BOOLEAN OS_Need_Clone_Packet(void) +{ + return (FALSE); +} + + + +/* + ======================================================================== + + Routine Description: + clone an input NDIS PACKET to another one. The new internally created NDIS PACKET + must have only one NDIS BUFFER + return - byte copied. 0 means can't create NDIS PACKET + NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket + + Arguments: + pAd Pointer to our adapter + pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU. + *pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet. + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPCloneNdisPacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN pInsAMSDUHdr, + IN PNDIS_PACKET pInPacket, + OUT PNDIS_PACKET *ppOutPacket) +{ + + struct sk_buff *pkt; + + ASSERT(pInPacket); + ASSERT(ppOutPacket); + + // 1. Allocate a packet + pkt = dev_alloc_skb(2048); + + if (pkt == NULL) + { + return NDIS_STATUS_FAILURE; + } + + skb_put(pkt, GET_OS_PKT_LEN(pInPacket)); + NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket)); + *ppOutPacket = OSPKT_TO_RTPKT(pkt); + + + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + + printk("###Clone###\n"); + + return NDIS_STATUS_SUCCESS; +} + + +// the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() +NDIS_STATUS RTMPAllocateNdisPacket( + IN PRTMP_ADAPTER pAd, + OUT PNDIS_PACKET *ppPacket, + IN PUCHAR pHeader, + IN UINT HeaderLen, + IN PUCHAR pData, + IN UINT DataLen) +{ + PNDIS_PACKET pPacket; + ASSERT(pData); + ASSERT(DataLen); + + // 1. Allocate a packet + pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + TXPADDING_SIZE); + if (pPacket == NULL) + { + *ppPacket = NULL; +#ifdef DEBUG + printk("RTMPAllocateNdisPacket Fail\n\n"); +#endif + return NDIS_STATUS_FAILURE; + } + + // 2. clone the frame content + if (HeaderLen > 0) + NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen); + if (DataLen > 0) + NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen); + + // 3. update length of packet + skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen); + + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); +// printk("%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket)); + *ppPacket = pPacket; + return NDIS_STATUS_SUCCESS; +} + +/* + ======================================================================== + Description: + This routine frees a miniport internally allocated NDIS_PACKET and its + corresponding NDIS_BUFFER and allocated memory. + ======================================================================== +*/ +VOID RTMPFreeNdisPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket)); +} + + +// IRQL = DISPATCH_LEVEL +// NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same +// scatter gather buffer +NDIS_STATUS Sniff2BytesFromNdisBuffer( + IN PNDIS_BUFFER pFirstBuffer, + IN UCHAR DesiredOffset, + OUT PUCHAR pByte0, + OUT PUCHAR pByte1) +{ + *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset); + *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1); + + return NDIS_STATUS_SUCCESS; +} + + +void RTMP_QueryPacketInfo( + IN PNDIS_PACKET pPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen) +{ + pPacketInfo->BufferCount = 1; + pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket); + pPacketInfo->PhysicalBufferCount = 1; + pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); + + *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + *pSrcBufLen = GET_OS_PKT_LEN(pPacket); +} + +void RTMP_QueryNextPacketInfo( + IN PNDIS_PACKET *ppPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen) +{ + PNDIS_PACKET pPacket = NULL; + + if (*ppPacket) + pPacket = GET_OS_PKT_NEXT(*ppPacket); + + if (pPacket) + { + pPacketInfo->BufferCount = 1; + pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket); + pPacketInfo->PhysicalBufferCount = 1; + pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); + + *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + *pSrcBufLen = GET_OS_PKT_LEN(pPacket); + *ppPacket = GET_OS_PKT_NEXT(pPacket); + } + else + { + pPacketInfo->BufferCount = 0; + pPacketInfo->pFirstBuffer = NULL; + pPacketInfo->PhysicalBufferCount = 0; + pPacketInfo->TotalPacketLength = 0; + + *pSrcBufVA = NULL; + *pSrcBufLen = 0; + *ppPacket = NULL; + } +} + +// not yet support MBSS +PNET_DEV get_netdev_from_bssid( + IN PRTMP_ADAPTER pAd, + IN UCHAR FromWhichBSSID) +{ + PNET_DEV dev_p = NULL; + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + dev_p = pAd->net_dev; + } +#endif // CONFIG_STA_SUPPORT // + + ASSERT(dev_p); + return dev_p; /* return one of MBSS */ +} + +PNDIS_PACKET DuplicatePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *skb; + PNDIS_PACKET pRetPacket = NULL; + USHORT DataSize; + UCHAR *pData; + + DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); + pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); + + + skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); + if (skb) + { + skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pRetPacket = OSPKT_TO_RTPKT(skb); + } + + return pRetPacket; + +} + +PNDIS_PACKET duplicate_pkt( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *skb; + PNDIS_PACKET pPacket = NULL; + + + if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) + { + skb_reserve(skb, 2); + NdisMoveMemory(skb->tail, pHeader802_3, HdrLen); + skb_put(skb, HdrLen); + NdisMoveMemory(skb->tail, pData, DataSize); + skb_put(skb, DataSize); + skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pPacket = OSPKT_TO_RTPKT(skb); + } + + return pPacket; +} + + +#define TKIP_TX_MIC_SIZE 8 +PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + struct sk_buff *skb, *newskb; + + + skb = RTPKT_TO_OSPKT(pPacket); + if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) + { + // alloc a new skb and copy the packet + newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC); + dev_kfree_skb_any(skb); + if (newskb == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n")); + return NULL; + } + skb = newskb; + } + + return OSPKT_TO_RTPKT(skb); +} + + + + +PNDIS_PACKET ClonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize) +{ + struct sk_buff *pRxPkt; + struct sk_buff *pClonedPkt; + + ASSERT(pPacket); + pRxPkt = RTPKT_TO_OSPKT(pPacket); + + // clone the packet + pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG); + + if (pClonedPkt) + { + // set the correct dataptr and data len + pClonedPkt->dev = pRxPkt->dev; + pClonedPkt->data = pData; + pClonedPkt->len = DataSize; + pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len; + ASSERT(DataSize < 1530); + } + return pClonedPkt; +} + +// +// change OS packet DataPtr and DataLen +// +void update_os_packet_info( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *pOSPkt; + + ASSERT(pRxBlk->pRxPacket); + pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + + pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pOSPkt->data = pRxBlk->pData; + pOSPkt->len = pRxBlk->DataSize; + pOSPkt->tail = pOSPkt->data + pOSPkt->len; +} + + +void wlan_802_11_to_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN PUCHAR pHeader802_3, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *pOSPkt; + + ASSERT(pRxBlk->pRxPacket); + ASSERT(pHeader802_3); + + pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + + pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pOSPkt->data = pRxBlk->pData; + pOSPkt->len = pRxBlk->DataSize; + pOSPkt->tail = pOSPkt->data + pOSPkt->len; + + // + // copy 802.3 header + // + // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3); +#endif // CONFIG_STA_SUPPORT // + } + + + +void announce_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + + struct sk_buff *pRxPkt; + + ASSERT(pPacket); + + pRxPkt = RTPKT_TO_OSPKT(pPacket); + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + + /* Push up the protocol stack */ +#ifdef IKANOS_VX_1X0 + IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len); +#else + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); + +//#ifdef CONFIG_5VT_ENHANCE +// *(int*)(pRxPkt->cb) = BRIDGE_TAG; +//#endif + netif_rx(pRxPkt); +#endif // IKANOS_VX_1X0 // +} + + +PRTMP_SCATTER_GATHER_LIST +rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg) +{ + sg->NumberOfElements = 1; + sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket); + sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket); + return (sg); +} + +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen) +{ + unsigned char *pt; + int x; + + if (RTDebugLevel < RT_DEBUG_TRACE) + return; + + pt = pSrcBufVA; + printk("%s: %p, len = %d\n",str, pSrcBufVA, SrcBufLen); + for (x=0; x= 15 + + union iwreq_data wrqu; + PUCHAR pBuf = NULL, pBufPtr = NULL; + USHORT event, type, BufLen; + UCHAR event_table_len = 0; + + type = Event_flag & 0xFF00; + event = Event_flag & 0x00FF; + + switch (type) + { + case IW_SYS_EVENT_FLAG_START: + event_table_len = IW_SYS_EVENT_TYPE_NUM; + break; + + case IW_SPOOF_EVENT_FLAG_START: + event_table_len = IW_SPOOF_EVENT_TYPE_NUM; + break; + + case IW_FLOOD_EVENT_FLAG_START: + event_table_len = IW_FLOOD_EVENT_TYPE_NUM; + break; + } + + if (event_table_len == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __FUNCTION__, type)); + return; + } + + if (event >= event_table_len) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __FUNCTION__, event)); + return; + } + + //Allocate memory and copy the msg. + if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL) + { + //Prepare the payload + memset(pBuf, 0, IW_CUSTOM_MAX_LEN); + + pBufPtr = pBuf; + + if (pAddr) + pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr)); + else if (BssIdx < MAX_MBSSID_NUM) + pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx); + else + pBufPtr += sprintf(pBufPtr, "(RT2860) "); + + if (type == IW_SYS_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]); + else if (type == IW_SPOOF_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi); + else if (type == IW_FLOOD_EVENT_FLAG_START) + pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]); + else + pBufPtr += sprintf(pBufPtr, "%s", "unknown event"); + + pBufPtr[pBufPtr - pBuf] = '\0'; + BufLen = pBufPtr - pBuf; + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = Event_flag; + wrqu.data.length = BufLen; + + //send wireless event + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, pBuf); + + //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf)); + + kfree(pBuf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__)); +#else + DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __FUNCTION__)); +#endif /* WIRELESS_EXT >= 15 */ +} + + +#ifdef CONFIG_STA_SUPPORT +void send_monitor_packets( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + struct sk_buff *pOSPkt; + wlan_ng_prism2_header *ph; + int rate_index = 0; + USHORT header_len = 0; + UCHAR temp_header[40] = {0}; + + u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96, 108, 109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38 + 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 0,1,2,3,4,5,6,7,8,9,10, + 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80}; + + + ASSERT(pRxBlk->pRxPacket); + if (pRxBlk->DataSize < 10) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __FUNCTION__, pRxBlk->DataSize)); + goto err_free_sk_buff; + } + + if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header))); + goto err_free_sk_buff; + } + + pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0); + if (pRxBlk->pHeader->FC.Type == BTYPE_DATA) + { + pRxBlk->DataSize -= LENGTH_802_11; + if ((pRxBlk->pHeader->FC.ToDs == 1) && + (pRxBlk->pHeader->FC.FrDs == 1)) + header_len = LENGTH_802_11_WITH_ADDR4; + else + header_len = LENGTH_802_11; + + // QOS + if (pRxBlk->pHeader->FC.SubType & 0x08) + { + header_len += 2; + // Data skip QOS contorl field + pRxBlk->DataSize -=2; + } + + // Order bit: A-Ralink or HTC+ + if (pRxBlk->pHeader->FC.Order) + { + header_len += 4; + // Data skip HTC contorl field + pRxBlk->DataSize -= 4; + } + + // Copy Header + if (header_len <= 40) + NdisMoveMemory(temp_header, pRxBlk->pData, header_len); + + // skip HW padding + if (pRxBlk->RxD.L2PAD) + pRxBlk->pData += (header_len + 2); + else + pRxBlk->pData += header_len; + } //end if + + + if (pRxBlk->DataSize < pOSPkt->len) { + skb_trim(pOSPkt,pRxBlk->DataSize); + } else { + skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len)); + } //end if + + if ((pRxBlk->pData - pOSPkt->data) > 0) { + skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data)); + skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data)); + } //end if + + if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) { + if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__)); + goto err_free_sk_buff; + } //end if + } //end if + + if (header_len > 0) + NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len); + + ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header)); + NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header)); + + ph->msgcode = DIDmsg_lnxind_wlansniffrm; + ph->msglen = sizeof(wlan_ng_prism2_header); + strcpy(ph->devname, pAd->net_dev->name); + + ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + ph->hosttime.status = 0; + ph->hosttime.len = 4; + ph->hosttime.data = jiffies; + + ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; + ph->mactime.status = 0; + ph->mactime.len = 0; + ph->mactime.data = 0; + + ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + ph->istx.status = 0; + ph->istx.len = 0; + ph->istx.data = 0; + + ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + ph->channel.status = 0; + ph->channel.len = 4; + + ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel; + + ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + ph->rssi.status = 0; + ph->rssi.len = 4; + ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));; + + ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; + ph->signal.status = 0; + ph->signal.len = 4; + ph->signal.data = 0; //rssi + noise; + + ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + ph->noise.status = 0; + ph->noise.len = 4; + ph->noise.data = 0; + +#ifdef DOT11_N_SUPPORT + if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX) + { + rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS); + } + else +#endif // DOT11_N_SUPPORT // + if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM) + rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4; + else + rate_index = (UCHAR)(pRxBlk->pRxWI->MCS); + if (rate_index < 0) + rate_index = 0; + if (rate_index > 255) + rate_index = 255; + + ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + ph->rate.status = 0; + ph->rate.len = 4; + ph->rate.data = ralinkrate[rate_index]; + + ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; + ph->frmlen.status = 0; + ph->frmlen.len = 4; + ph->frmlen.data = (u_int32_t)pRxBlk->DataSize; + + + pOSPkt->pkt_type = PACKET_OTHERHOST; + pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev); + pOSPkt->ip_summed = CHECKSUM_NONE; + netif_rx(pOSPkt); + + return; + +err_free_sk_buff: + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + +} +#endif // CONFIG_STA_SUPPORT // + + +void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify) +{ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + daemonize(pThreadName /*"%s",pAd->net_dev->name*/); + + allow_signal(SIGTERM); + allow_signal(SIGKILL); + current->flags |= PF_NOFREEZE; +#else + unsigned long flags; + + daemonize(); + reparent_to_init(); + strcpy(current->comm, pThreadName); + + siginitsetinv(¤t->blocked, sigmask(SIGTERM) | sigmask(SIGKILL)); + + /* Allow interception of SIGKILL only + * Don't allow other signals to interrupt the transmission */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + spin_lock_irqsave(¤t->sigmask_lock, flags); + flush_signals(current); + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); +#endif +#endif + + /* signal that we've started the thread */ + complete(pNotify); + +} + +void RTMP_IndicateMediaState( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->CommonCfg.bWirelessEvent) + { + if (pAd->IndicateMediaState == NdisMediaStateConnected) + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + else + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + } +} + diff --git a/drivers/staging/rt3070/rt_linux.h b/drivers/staging/rt3070/rt_linux.h new file mode 100644 index 000000000000..0540d02da79b --- /dev/null +++ b/drivers/staging/rt3070/rt_linux.h @@ -0,0 +1,887 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + */ + +/***********************************************************************/ +/* */ +/* Program: rt_linux.c */ +/* Created: 4/21/2006 1:17:38 PM */ +/* Author: Wu Xi-Kun */ +/* Comments: `description` */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* History: */ +/* Revision 1.1 4/21/2006 1:17:38 PM xsikun */ +/* Initial revision */ +/* */ +/***********************************************************************/ + +#include "rtmp_type.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + +// load firmware +#define __KERNEL_SYSCALLS__ +#include +#include + + +#define MEM_ALLOC_FLAG (GFP_ATOMIC) //(GFP_DMA | GFP_ATOMIC) + +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +//#define CONFIG_CKIP_SUPPORT + +#undef __inline +#define __inline static inline + +typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_dev); + +// add by kathy + +#ifdef CONFIG_STA_SUPPORT + +#ifdef RT2870 +#define STA_PROFILE_PATH "/etc/Wireless/RT2870STA/RT2870STA.dat" +#define STA_RT2870_IMAGE_FILE_NAME "/etc/Wireless/RT2870STA/rt2870.bin" +#define STA_NIC_DEVICE_NAME "RT2870STA" +#define STA_DRIVER_VERSION "2.0.1.0" +#ifdef MULTIPLE_CARD_SUPPORT +#define CARD_INFO_PATH "/etc/Wireless/RT2870STA/RT2870STACard.dat" +#endif // MULTIPLE_CARD_SUPPORT // +#endif // RT2870 // + +#endif // CONFIG_STA_SUPPORT // + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +#define RTMP_TIME_AFTER(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(b) - (long)(a) < 0)) + +#define RTMP_TIME_AFTER_EQ(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(a) - (long)(b) >= 0)) +#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) +#else +#define RTMP_TIME_AFTER(a,b) time_after(a, b) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RT_MOD_INC_USE_COUNT() \ + if (!try_module_get(THIS_MODULE)) \ + { \ + DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot reserve module\n", __FUNCTION__)); \ + return -1; \ + } + +#define RT_MOD_DEC_USE_COUNT() module_put(THIS_MODULE); +#else +#define RT_MOD_INC_USE_COUNT() MOD_INC_USE_COUNT; +#define RT_MOD_DEC_USE_COUNT() MOD_DEC_USE_COUNT; +#endif + +#define OS_HZ HZ + +#define ETH_LENGTH_OF_ADDRESS 6 + +#define IN +#define OUT + +#define NDIS_STATUS INT +#define NDIS_STATUS_SUCCESS 0x00 +#define NDIS_STATUS_FAILURE 0x01 +#define NDIS_STATUS_INVALID_DATA 0x02 +#define NDIS_STATUS_RESOURCES 0x03 + +#define MIN_NET_DEVICE_FOR_AID 0x00 //0x00~0x3f +#define MIN_NET_DEVICE_FOR_MBSSID 0x00 //0x00,0x10,0x20,0x30 +#define MIN_NET_DEVICE_FOR_WDS 0x10 //0x40,0x50,0x60,0x70 +#define MIN_NET_DEVICE_FOR_APCLI 0x20 +#define MIN_NET_DEVICE_FOR_MESH 0x30 +#ifdef CONFIG_STA_SUPPORT +#define MIN_NET_DEVICE_FOR_DLS 0x40 +#endif // CONFIG_STA_SUPPORT // + + +#ifdef CONFIG_STA_SUPPORT +#define NDIS_PACKET_TYPE_DIRECTED 0 +#define NDIS_PACKET_TYPE_MULTICAST 1 +#define NDIS_PACKET_TYPE_BROADCAST 2 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 3 +#endif // CONFIG_STA_SUPPORT // + +struct os_lock { + spinlock_t lock; + unsigned long flags; +}; + + +struct os_cookie { + +#ifdef RT2870 + struct usb_device *pUsb_Dev; + + struct pid * MLMEThr_pid; + struct pid * RTUSBCmdThr_pid; + struct pid * TimerQThr_pid; +#endif // RT2870 // + + struct tasklet_struct rx_done_task; + struct tasklet_struct mgmt_dma_done_task; + struct tasklet_struct ac0_dma_done_task; + struct tasklet_struct ac1_dma_done_task; + struct tasklet_struct ac2_dma_done_task; + struct tasklet_struct ac3_dma_done_task; + struct tasklet_struct hcca_dma_done_task; + struct tasklet_struct tbtt_task; +#ifdef RT2870 + struct tasklet_struct null_frame_complete_task; + struct tasklet_struct rts_frame_complete_task; + struct tasklet_struct pspoll_frame_complete_task; +#endif // RT2870 // + + + unsigned long apd_pid; //802.1x daemon pid + INT ioctl_if_type; + INT ioctl_if; +}; + +typedef struct _VIRTUAL_ADAPTER +{ + struct net_device *RtmpDev; + struct net_device *VirtualDev; +} VIRTUAL_ADAPTER, PVIRTUAL_ADAPTER; + +#undef ASSERT +#define ASSERT(x) \ +{ \ + if (!(x)) \ + { \ + printk(KERN_WARNING __FILE__ ":%d assert " #x "failed\n", __LINE__); \ + } \ +} + +typedef struct os_cookie * POS_COOKIE; +typedef struct pci_dev * PPCI_DEV; +typedef struct net_device * PNET_DEV; +typedef void * PNDIS_PACKET; +typedef char NDIS_PACKET; +typedef PNDIS_PACKET * PPNDIS_PACKET; +typedef dma_addr_t NDIS_PHYSICAL_ADDRESS; +typedef dma_addr_t * PNDIS_PHYSICAL_ADDRESS; +//typedef struct timer_list RALINK_TIMER_STRUCT; +//typedef struct timer_list * PRALINK_TIMER_STRUCT; +//typedef struct os_lock NDIS_SPIN_LOCK; +typedef spinlock_t NDIS_SPIN_LOCK; +typedef struct timer_list NDIS_MINIPORT_TIMER; +typedef void * NDIS_HANDLE; +typedef char * PNDIS_BUFFER; + + + +void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen); + +dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction); +void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction); + + +//////////////////////////////////////// +// MOVE TO rtmp.h ? +///////////////////////////////////////// +#define PKTSRC_NDIS 0x7f +#define PKTSRC_DRIVER 0x0f +#define PRINT_MAC(addr) \ + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] + + +#define RT2860_PCI_DEVICE_ID 0x0601 + +#ifdef RT2870 +#define PCI_MAP_SINGLE(_handle, _ptr, _size, _dir) (ULONG)0 + +#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) +#endif // RT2870 // + + +#define BEACON_FRAME_DMA_CACHE_WBACK(_ptr, _size) \ + dma_cache_wback(_ptr, _size) + + +////////////////////////////////////////// +// +////////////////////////////////////////// + + +#define NdisMIndicateStatus(_w, _x, _y, _z) + + +typedef struct timer_list RTMP_OS_TIMER; + +#ifdef RT2870 +/* ----------------- Timer Related MARCO ---------------*/ +// In RT2870, we have a lot of timer functions and will read/write register, it's +// not allowed in Linux USB sub-system to do it ( because of sleep issue when submit +// to ctrl pipe). So we need a wrapper function to take care it. + +typedef VOID (*RT2870_TIMER_HANDLE)( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif // RT2870 // + + +typedef struct _RALINK_TIMER_STRUCT { + RTMP_OS_TIMER TimerObj; // Ndis Timer object + BOOLEAN Valid; // Set to True when call RTMPInitTimer + BOOLEAN State; // True if timer cancelled + BOOLEAN PeriodicType; // True if timer is periodic timer + BOOLEAN Repeat; // True if periodic timer + ULONG TimerValue; // Timer value in milliseconds + ULONG cookie; // os specific object +#ifdef RT2870 + RT2870_TIMER_HANDLE handle; + void *pAd; +#endif // RT2870 // +} RALINK_TIMER_STRUCT, *PRALINK_TIMER_STRUCT; + + +#ifdef RT2870 + +typedef enum _RT2870_KERNEL_THREAD_STATUS_ +{ + RT2870_THREAD_UNKNOWN = 0, + RT2870_THREAD_INITED = 1, + RT2870_THREAD_RUNNING = 2, + RT2870_THREAD_STOPED = 4, +}RT2870_KERNEL_THREAD_STATUS; + +#define RT2870_THREAD_CAN_DO_INSERT (RT2870_THREAD_INITED |RT2870_THREAD_RUNNING) + +typedef struct _RT2870_TIMER_ENTRY_ +{ + RALINK_TIMER_STRUCT *pRaTimer; + struct _RT2870_TIMER_ENTRY_ *pNext; +}RT2870_TIMER_ENTRY; + + +#define TIMER_QUEUE_SIZE_MAX 128 +typedef struct _RT2870_TIMER_QUEUE_ +{ + unsigned int status; + //wait_queue_head_t timerWaitQ; + //atomic_t count; + UCHAR *pTimerQPoll; + RT2870_TIMER_ENTRY *pQPollFreeList; + RT2870_TIMER_ENTRY *pQHead; + RT2870_TIMER_ENTRY *pQTail; +}RT2870_TIMER_QUEUE; +#endif // RT2870 // + + +//#define DBG 1 + +// +// MACRO for debugging information +// + +#ifdef DBG +extern ULONG RTDebugLevel; + +#define DBGPRINT_RAW(Level, Fmt) \ +{ \ + if (Level <= RTDebugLevel) \ + { \ + printk Fmt; \ + } \ +} + +#define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt) + + +#define DBGPRINT_ERR(Fmt) \ +{ \ + printk("ERROR!!! "); \ + printk Fmt; \ +} + +#define DBGPRINT_S(Status, Fmt) \ +{ \ + printk Fmt; \ +} + + +#else +#define DBGPRINT(Level, Fmt) +#define DBGPRINT_RAW(Level, Fmt) +#define DBGPRINT_S(Status, Fmt) +#define DBGPRINT_ERR(Fmt) +#endif + + +// +// spin_lock enhanced for Nested spin lock +// +#define NdisAllocateSpinLock(__lock) \ +{ \ + spin_lock_init((spinlock_t *)(__lock)); \ +} + +#define NdisFreeSpinLock(lock) \ +{ \ +} + + +#define RTMP_SEM_LOCK(__lock) \ +{ \ + spin_lock_bh((spinlock_t *)(__lock)); \ +} + +#define RTMP_SEM_UNLOCK(__lock) \ +{ \ + spin_unlock_bh((spinlock_t *)(__lock)); \ +} + +// sample, use semaphore lock to replace IRQ lock, 2007/11/15 +#define RTMP_IRQ_LOCK(__lock, __irqflags) \ +{ \ + __irqflags = 0; \ + spin_lock_bh((spinlock_t *)(__lock)); \ + pAd->irq_disabled |= 1; \ +} + +#define RTMP_IRQ_UNLOCK(__lock, __irqflag) \ +{ \ + pAd->irq_disabled &= 0; \ + spin_unlock_bh((spinlock_t *)(__lock)); \ +} + +#define RTMP_INT_LOCK(__lock, __irqflags) \ +{ \ + spin_lock_irqsave((spinlock_t *)__lock, __irqflags); \ +} + +#define RTMP_INT_UNLOCK(__lock, __irqflag) \ +{ \ + spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag)); \ +} + +#ifdef RT2870 +#define RTMP_IO_READ32(_A, _R, _pV) \ + RTUSBReadMACRegister(_A, _R, _pV) + +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ +} + +#define RTMP_IO_WRITE32(_A, _R, _V) \ + RTUSBWriteMACRegister(_A, _R, _V) + + +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + USHORT _Val = _V; \ + RTUSBSingleWrite(_A, _R, _Val); \ +} + + +#define RTMP_IO_WRITE16(_A, _R, _V) \ +{ \ + RTUSBSingleWrite(_A, _R, _V); \ +} +#endif // RT2870 // + +#ifndef wait_event_interruptible_timeout +#define __wait_event_interruptible_timeout(wq, condition, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while (0) + +#define wait_event_interruptible_timeout(wq, condition, timeout) \ +({ \ + long __ret = timeout; \ + if (!(condition)) \ + __wait_event_interruptible_timeout(wq, condition, __ret); \ + __ret; \ +}) +#endif +#define ONE_TICK 1 +#define OS_WAIT(_time) \ +{ int _i; \ + long _loop = ((_time)/(1000/OS_HZ)) > 0 ? ((_time)/(1000/OS_HZ)) : 1;\ + wait_queue_head_t _wait; \ + init_waitqueue_head(&_wait); \ + for (_i=0; _i<(_loop); _i++) \ + wait_event_interruptible_timeout(_wait, 0, ONE_TICK); } + + +/* Modified by Wu Xi-Kun 4/21/2006 */ +typedef void (*TIMER_FUNCTION)(unsigned long); + +#define COPY_MAC_ADDR(Addr1, Addr2) memcpy((Addr1), (Addr2), MAC_ADDR_LEN) + +#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE) +#define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA) + + +#ifdef RT2870 +#define BUILD_TIMER_FUNCTION(_func) \ +void linux_##_func(unsigned long data) \ +{ \ + PRALINK_TIMER_STRUCT _pTimer = (PRALINK_TIMER_STRUCT)data; \ + RT2870_TIMER_ENTRY *_pQNode; \ + RTMP_ADAPTER *_pAd; \ + \ + _pTimer->handle = _func; \ + _pAd = (RTMP_ADAPTER *)_pTimer->pAd; \ + _pQNode = RT2870_TimerQ_Insert(_pAd, _pTimer); \ + if ((_pQNode == NULL) && (_pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)) \ + RTMP_OS_Add_Timer(&_pTimer->TimerObj, HZ); \ +} +#endif // RT2870 // + + +#define DECLARE_TIMER_FUNCTION(_func) \ +void linux_##_func(unsigned long data) + +#define GET_TIMER_FUNCTION(_func) \ + linux_##_func + +DECLARE_TIMER_FUNCTION(MlmePeriodicExec); +DECLARE_TIMER_FUNCTION(MlmeRssiReportExec); +DECLARE_TIMER_FUNCTION(AsicRxAntEvalTimeout); +DECLARE_TIMER_FUNCTION(APSDPeriodicExec); +DECLARE_TIMER_FUNCTION(AsicRfTuningExec); +#ifdef RT2870 +DECLARE_TIMER_FUNCTION(BeaconUpdateExec); +#endif // RT2870 // + + +#ifdef CONFIG_STA_SUPPORT +DECLARE_TIMER_FUNCTION(BeaconTimeout); +DECLARE_TIMER_FUNCTION(ScanTimeout); +DECLARE_TIMER_FUNCTION(AuthTimeout); +DECLARE_TIMER_FUNCTION(AssocTimeout); +DECLARE_TIMER_FUNCTION(ReassocTimeout); +DECLARE_TIMER_FUNCTION(DisassocTimeout); +DECLARE_TIMER_FUNCTION(LinkDownExec); +#ifdef LEAP_SUPPORT +DECLARE_TIMER_FUNCTION(LeapAuthTimeout); +#endif +DECLARE_TIMER_FUNCTION(StaQuickResponeForRateUpExec); +DECLARE_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc); +DECLARE_TIMER_FUNCTION(PsPollWakeExec); +DECLARE_TIMER_FUNCTION(RadioOnExec); + +#ifdef QOS_DLS_SUPPORT +DECLARE_TIMER_FUNCTION(DlsTimeoutAction); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + +#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) +#define WSC_INCLUDED +#endif + + + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); + + +/* + * packet helper + * - convert internal rt packet to os packet or + * os packet to rt packet + */ +#define RTPKT_TO_OSPKT(_p) ((struct sk_buff *)(_p)) +#define OSPKT_TO_RTPKT(_p) ((PNDIS_PACKET)(_p)) + +#define GET_OS_PKT_DATAPTR(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->data) + +#define GET_OS_PKT_LEN(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->len) + +#define GET_OS_PKT_DATATAIL(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->tail) + +#define GET_OS_PKT_HEAD(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->head) + +#define GET_OS_PKT_END(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->end) + +#define GET_OS_PKT_NETDEV(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->dev) + +#define GET_OS_PKT_TYPE(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)) + +#define GET_OS_PKT_NEXT(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->next) + + +#define OS_NTOHS(_Val) \ + (ntohs(_Val)) +#define OS_HTONS(_Val) \ + (htons(_Val)) +#define OS_NTOHL(_Val) \ + (ntohl(_Val)) +#define OS_HTONL(_Val) \ + (htonl(_Val)) + +/* statistics counter */ +#define STATS_INC_RX_PACKETS(_pAd, _dev) +#define STATS_INC_TX_PACKETS(_pAd, _dev) + +#define STATS_INC_RX_BYTESS(_pAd, _dev, len) +#define STATS_INC_TX_BYTESS(_pAd, _dev, len) + +#define STATS_INC_RX_ERRORS(_pAd, _dev) +#define STATS_INC_TX_ERRORS(_pAd, _dev) + +#define STATS_INC_RX_DROPPED(_pAd, _dev) +#define STATS_INC_TX_DROPPED(_pAd, _dev) + + +#define CB_OFF 10 + + +// check DDK NDIS_PACKET data structure and find out only MiniportReservedEx[0..7] can be used by our driver without +// ambiguity. Fields after pPacket->MiniportReservedEx[8] may be used by other wrapper layer thus crashes the driver +// +//#define RTMP_GET_PACKET_MR(_p) (RTPKT_TO_OSPKT(_p)) + +// User Priority +#define RTMP_SET_PACKET_UP(_p, _prio) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0] = _prio) +#define RTMP_GET_PACKET_UP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0]) + +// Fragment # +#define RTMP_SET_PACKET_FRAGMENTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1] = _num) +#define RTMP_GET_PACKET_FRAGMENTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1]) + +// 0x0 ~0x7f: TX to AP's own BSS which has the specified AID. if AID>127, set bit 7 in RTMP_SET_PACKET_EMACTAB too. +//(this value also as MAC(on-chip WCID) table index) +// 0x80~0xff: TX to a WDS link. b0~6: WDS index +#define RTMP_SET_PACKET_WCID(_p, _wdsidx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2] = _wdsidx) +#define RTMP_GET_PACKET_WCID(_p) ((UCHAR)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2])) + +// 0xff: PKTSRC_NDIS, others: local TX buffer index. This value affects how to a packet +#define RTMP_SET_PACKET_SOURCE(_p, _pktsrc) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3] = _pktsrc) +#define RTMP_GET_PACKET_SOURCE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3]) + +// RTS/CTS-to-self protection method +#define RTMP_SET_PACKET_RTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4] = _num) +#define RTMP_GET_PACKET_RTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4]) +// see RTMP_S(G)ET_PACKET_EMACTAB + +// TX rate index +#define RTMP_SET_PACKET_TXRATE(_p, _rate) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5] = _rate) +#define RTMP_GET_PACKET_TXRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5]) + +// From which Interface +#define RTMP_SET_PACKET_IF(_p, _ifdx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6] = _ifdx) +#define RTMP_GET_PACKET_IF(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6]) +#define RTMP_SET_PACKET_NET_DEVICE_MBSSID(_p, _bss) RTMP_SET_PACKET_IF((_p), (_bss)) +#define RTMP_SET_PACKET_NET_DEVICE_WDS(_p, _bss) RTMP_SET_PACKET_IF((_p), ((_bss) + MIN_NET_DEVICE_FOR_WDS)) +#define RTMP_SET_PACKET_NET_DEVICE_APCLI(_p, _idx) RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_APCLI)) +#define RTMP_SET_PACKET_NET_DEVICE_MESH(_p, _idx) RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_MESH)) +#define RTMP_GET_PACKET_NET_DEVICE_MBSSID(_p) RTMP_GET_PACKET_IF((_p)) +#define RTMP_GET_PACKET_NET_DEVICE(_p) RTMP_GET_PACKET_IF((_p)) + +#define RTMP_SET_PACKET_MOREDATA(_p, _morebit) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7] = _morebit) +#define RTMP_GET_PACKET_MOREDATA(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7]) + +//#define RTMP_SET_PACKET_NET_DEVICE_MBSSID(_p, _bss) (RTPKT_TO_OSPKT(_p)->cb[8] = _bss) +//#define RTMP_GET_PACKET_NET_DEVICE_MBSSID(_p) (RTPKT_TO_OSPKT(_p)->cb[8]) + +// +// Sepcific Pakcet Type definition +// +#define RTMP_PACKET_SPECIFIC_CB_OFFSET 11 + +#define RTMP_PACKET_SPECIFIC_DHCP 0x01 +#define RTMP_PACKET_SPECIFIC_EAPOL 0x02 +#define RTMP_PACKET_SPECIFIC_IPV4 0x04 +#define RTMP_PACKET_SPECIFIC_WAI 0x08 +#define RTMP_PACKET_SPECIFIC_VLAN 0x10 +#define RTMP_PACKET_SPECIFIC_LLCSNAP 0x20 + +//Specific +#define RTMP_SET_PACKET_SPECIFIC(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg) + +//DHCP +#define RTMP_SET_PACKET_DHCP(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_DHCP); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_DHCP); \ + }while(0) +#define RTMP_GET_PACKET_DHCP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_DHCP) + +//EAPOL +#define RTMP_SET_PACKET_EAPOL(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_EAPOL); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_EAPOL); \ + }while(0) +#define RTMP_GET_PACKET_EAPOL(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_EAPOL) + +//WAI +#define RTMP_SET_PACKET_WAI(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_WAI); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_WAI); \ + }while(0) +#define RTMP_GET_PACKET_WAI(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_WAI) + +#define RTMP_GET_PACKET_LOWRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & (RTMP_PACKET_SPECIFIC_EAPOL | RTMP_PACKET_SPECIFIC_DHCP | RTMP_PACKET_SPECIFIC_WAI)) + +//VLAN +#define RTMP_SET_PACKET_VLAN(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_VLAN); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_VLAN); \ + }while(0) +#define RTMP_GET_PACKET_VLAN(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_VLAN) + +//LLC/SNAP +#define RTMP_SET_PACKET_LLCSNAP(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_LLCSNAP); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_LLCSNAP); \ + }while(0) + +#define RTMP_GET_PACKET_LLCSNAP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_LLCSNAP) + +// IP +#define RTMP_SET_PACKET_IPV4(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_IPV4); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_IPV4); \ + }while(0) + +#define RTMP_GET_PACKET_IPV4(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_IPV4) + +// If this flag is set, it indicates that this EAPoL frame MUST be clear. +#define RTMP_SET_PACKET_CLEAR_EAP_FRAME(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12] = _flg) +#define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12]) + +#define RTMP_SET_PACKET_5VT(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22] = _flg) +#define RTMP_GET_PACKET_5VT(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22]) + + +#ifdef INF_AMAZON_SE +/*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ +#define RTMP_SET_PACKET_NOBULKOUT(_p, _morebit) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+23] = _morebit) +#define RTMP_GET_PACKET_NOBULKOUT(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+23]) +#endif // INF_AMAZON_SE // + + + +#ifdef CONFIG_5VT_ENHANCE +#define BRIDGE_TAG 0x35564252 // depends on 5VT define in br_input.c +#endif + + +#define NDIS_SET_PACKET_STATUS(_p, _status) + + +#define GET_SG_LIST_FROM_PACKET(_p, _sc) \ + rt_get_sg_list_from_packet(_p, _sc) + +#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) +#define NdisZeroMemory(Destination, Length) memset(Destination, 0, Length) +#define NdisFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) +#define NdisEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) +#define RTMPEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) + + +#define RTMP_INC_REF(_A) 0 +#define RTMP_DEC_REF(_A) 0 +#define RTMP_GET_REF(_A) 0 + + + +/* + * ULONG + * RTMP_GetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressLow(PhysicalAddress) (PhysicalAddress) + +/* + * ULONG + * RTMP_GetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressHigh(PhysicalAddress) (0) + +/* + * VOID + * RTMP_SetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressLow(PhysicalAddress, Value) \ + PhysicalAddress = Value; + +/* + * VOID + * RTMP_SetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressHigh(PhysicalAddress, Value) + + +//CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); +#define QUEUE_ENTRY_TO_PACKET(pEntry) \ + (PNDIS_PACKET)(pEntry) + +#define PACKET_TO_QUEUE_ENTRY(pPacket) \ + (PQUEUE_ENTRY)(pPacket) + + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) \ +((type *)((PCHAR)(address) - offsetof(type, field))) +#endif + + +#define RELEASE_NDIS_PACKET(_pAd, _pPacket, _Status) \ +{ \ + RTMPFreeNdisPacket(_pAd, _pPacket); \ +} + + +#define SWITCH_PhyAB(_pAA, _pBB) \ +{ \ + ULONG AABasePaHigh; \ + ULONG AABasePaLow; \ + ULONG BBBasePaHigh; \ + ULONG BBBasePaLow; \ + BBBasePaHigh = RTMP_GetPhysicalAddressHigh(_pBB); \ + BBBasePaLow = RTMP_GetPhysicalAddressLow(_pBB); \ + AABasePaHigh = RTMP_GetPhysicalAddressHigh(_pAA); \ + AABasePaLow = RTMP_GetPhysicalAddressLow(_pAA); \ + RTMP_SetPhysicalAddressHigh(_pAA, BBBasePaHigh); \ + RTMP_SetPhysicalAddressLow(_pAA, BBBasePaLow); \ + RTMP_SetPhysicalAddressHigh(_pBB, AABasePaHigh); \ + RTMP_SetPhysicalAddressLow(_pBB, AABasePaLow); \ +} + + +#define NdisWriteErrorLogEntry(_a, _b, _c, _d) +#define NdisMAllocateMapRegisters(_a, _b, _c, _d, _e) NDIS_STATUS_SUCCESS + + +#define NdisAcquireSpinLock RTMP_SEM_LOCK +#define NdisReleaseSpinLock RTMP_SEM_UNLOCK + +static inline void NdisGetSystemUpTime(ULONG *time) +{ + *time = jiffies; +} + +//pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); +#define QUEUE_ENTRY_TO_PKT(pEntry) \ + ((PNDIS_PACKET) (pEntry)) + +int rt28xx_packet_xmit(struct sk_buff *skb); + + + +void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify); + + + diff --git a/drivers/staging/rt3070/rt_main_dev.c b/drivers/staging/rt3070/rt_main_dev.c new file mode 100644 index 000000000000..c000646286e6 --- /dev/null +++ b/drivers/staging/rt3070/rt_main_dev.c @@ -0,0 +1,1800 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rt_main_dev.c + + Abstract: + Create and register network interface. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sample Mar/21/07 Merge RT2870 and RT2860 drivers. +*/ + +#include "rt_config.h" + +#define FORTY_MHZ_INTOLERANT_INTERVAL (60*1000) // 1 min + +#ifdef MULTIPLE_CARD_SUPPORT +// record whether the card in the card list is used in the card file +UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD]; +// record used card mac address in the card list +static UINT8 MC_CardMac[MAX_NUM_OF_MULTIPLE_CARD][6]; +#endif // MULTIPLE_CARD_SUPPORT // + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +UINT32 CW_MAX_IN_BITS; +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +/*---------------------------------------------------------------------*/ +/* Private Variables Used */ +/*---------------------------------------------------------------------*/ +//static RALINK_TIMER_STRUCT PeriodicTimer; + +char *mac = ""; // default 00:00:00:00:00:00 +char *hostname = ""; // default CMPC +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) +MODULE_PARM (mac, "s"); +#else +module_param (mac, charp, 0); +#endif +MODULE_PARM_DESC (mac, "rt28xx: wireless mac addr"); + + +/*---------------------------------------------------------------------*/ +/* Prototypes of Functions Used */ +/*---------------------------------------------------------------------*/ +#ifdef DOT11_N_SUPPORT +extern BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num); +extern void ba_reordering_resource_release(PRTMP_ADAPTER pAd); +#endif // DOT11_N_SUPPORT // +extern NDIS_STATUS NICLoadRateSwitchingParams(IN PRTMP_ADAPTER pAd); + + +// public function prototype +INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p, + IN UINT argc, OUT PRTMP_ADAPTER *ppAd); + +// private function prototype +static int rt28xx_init(IN struct net_device *net_dev); +INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev); + +#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 +struct net_device *alloc_netdev( + int sizeof_priv, + const char *mask, + void (*setup)(struct net_device *)); +#endif // LINUX_VERSION_CODE // + +static void CfgInitHook(PRTMP_ADAPTER pAd); +//static BOOLEAN RT28XXAvailRANameAssign(IN CHAR *name_p); + +#ifdef CONFIG_STA_SUPPORT +extern const struct iw_handler_def rt28xx_iw_handler_def; +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +extern const struct iw_handler_def rt28xx_ap_iw_handler_def; +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +#if WIRELESS_EXT >= 12 +// This function will be called when query /proc +struct iw_statistics *rt28xx_get_wireless_stats( + IN struct net_device *net_dev); +#endif + +struct net_device_stats *RT28xx_get_ether_stats( + IN struct net_device *net_dev); + +/* +======================================================================== +Routine Description: + Close raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: + 1. if open fail, kernel will not call the close function. + 2. Free memory for + (1) Mlme Memory Handler: MlmeHalt() + (2) TX & RX: RTMPFreeTxRxRingMemory() + (3) BA Reordering: ba_reordering_resource_release() +======================================================================== +*/ +int MainVirtualIF_close(IN struct net_device *net_dev) +{ + RTMP_ADAPTER *pAd = net_dev->ml_priv; + + // Sanity check for pAd + if (pAd == NULL) + return 0; // close ok + + netif_carrier_off(pAd->net_dev); + netif_stop_queue(pAd->net_dev); + + + + VIRTUAL_IF_DOWN(pAd); + + RT_MOD_DEC_USE_COUNT(); + + return 0; // close ok +} + +/* +======================================================================== +Routine Description: + Open raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: + 1. if open fail, kernel will not call the close function. + 2. Free memory for + (1) Mlme Memory Handler: MlmeHalt() + (2) TX & RX: RTMPFreeTxRxRingMemory() + (3) BA Reordering: ba_reordering_resource_release() +======================================================================== +*/ +int MainVirtualIF_open(IN struct net_device *net_dev) +{ + RTMP_ADAPTER *pAd = net_dev->ml_priv; + + // Sanity check for pAd + if (pAd == NULL) + return 0; // close ok + + if (VIRTUAL_IF_UP(pAd) != 0) + return -1; + + // increase MODULE use count + RT_MOD_INC_USE_COUNT(); + + netif_start_queue(net_dev); + netif_carrier_on(net_dev); + netif_wake_queue(net_dev); + + return 0; +} + +/* +======================================================================== +Routine Description: + Close raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: + 1. if open fail, kernel will not call the close function. + 2. Free memory for + (1) Mlme Memory Handler: MlmeHalt() + (2) TX & RX: RTMPFreeTxRxRingMemory() + (3) BA Reordering: ba_reordering_resource_release() +======================================================================== +*/ +int rt28xx_close(IN PNET_DEV dev) +{ + struct net_device * net_dev = (struct net_device *)dev; + RTMP_ADAPTER *pAd = net_dev->ml_priv; + BOOLEAN Cancelled = FALSE; + UINT32 i = 0; +#ifdef RT2870 + DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup); + DECLARE_WAITQUEUE(wait, current); + + //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); +#endif // RT2870 // + + + DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n")); + + // Sanity check for pAd + if (pAd == NULL) + return 0; // close ok + + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif // WDS_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + + // If dirver doesn't wake up firmware here, + // NICLoadFirmware will hang forever when interface is up again. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + AsicForceWakeup(pAd, TRUE); + } + +#ifdef QOS_DLS_SUPPORT + // send DLS-TEAR_DOWN message, + if (pAd->CommonCfg.bDLSCapable) + { + UCHAR i; + + // tear down local dls table entry + for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + + // tear down peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + RT28XX_MLME_HANDLER(pAd); + } +#endif // QOS_DLS_SUPPORT // + + if (INFRA_ON(pAd) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + MLME_DISASSOC_REQ_STRUCT DisReq; + MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + + COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid); + DisReq.Reason = REASON_DEAUTH_STA_LEAVING; + + MsgElem->Machine = ASSOC_STATE_MACHINE; + MsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); + NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); + + // Prevent to connect AP again in STAMlmePeriodicExec + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; + MlmeDisassocReqAction(pAd, MsgElem); + kfree(MsgElem); + + RTMPusecDelay(1000); + } + +#ifdef RT2870 + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); +#endif // RT2870 // + +#ifdef CCX_SUPPORT + RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &Cancelled); +#endif + + RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled); + RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + // send wireless event to wpa_supplicant for infroming interface down. + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_INTERFACE_DOWN; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + + MlmeRadioOff(pAd); + } +#endif // CONFIG_STA_SUPPORT // + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + for (i = 0 ; i < NUM_OF_TX_RING; i++) + { + while (pAd->DeQueueRunning[i] == TRUE) + { + printk("Waiting for TxQueue[%d] done..........\n", i); + RTMPusecDelay(1000); + } + } + +#ifdef RT2870 + // ensure there are no more active urbs. + add_wait_queue (&unlink_wakeup, &wait); + pAd->wait = &unlink_wakeup; + + // maybe wait for deletions to finish. + i = 0; + //while((i < 25) && atomic_read(&pAd->PendingRx) > 0) + while(i < 25) + { + unsigned long IrqFlags; + + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + if (pAd->PendingRx == 0) + { + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + break; + } + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) + msleep(UNLINK_TIMEOUT_MS); //Time in millisecond +#else + RTMPusecDelay(UNLINK_TIMEOUT_MS*1000); //Time in microsecond +#endif + i++; + } + pAd->wait = NULL; + remove_wait_queue (&unlink_wakeup, &wait); +#endif // RT2870 // + + //RTUSBCleanUpMLMEWaitQueue(pAd); /*not used in RT28xx*/ + + +#ifdef RT2870 + // We need clear timerQ related structure before exits of the timer thread. + RT2870_TimerQ_Exit(pAd); + // Close kernel threads or tasklets + RT28xxThreadTerminate(pAd); +#endif // RT2870 // + + // Stop Mlme state machine + MlmeHalt(pAd); + + // Close kernel threads or tasklets + kill_thread_task(pAd); + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + MacTableReset(pAd); + } +#endif // CONFIG_STA_SUPPORT // + + + MeasureReqTabExit(pAd); + TpcReqTabExit(pAd); + + + + + // Free Ring or USB buffers + RTMPFreeTxRxRingMemory(pAd); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + +#ifdef DOT11_N_SUPPORT + // Free BA reorder resource + ba_reordering_resource_release(pAd); +#endif // DOT11_N_SUPPORT // + +#ifdef RT2870 +#ifdef INF_AMAZON_SE + if (pAd->UsbVendorReqBuf) + os_free_mem(pAd, pAd->UsbVendorReqBuf); +#endif // INF_AMAZON_SE // +#endif // RT2870 // + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + return 0; // close ok +} /* End of rt28xx_close */ + +static int rt28xx_init(IN struct net_device *net_dev) +{ + PRTMP_ADAPTER pAd = net_dev->ml_priv; + UINT index; + UCHAR TmpPhy; +// ULONG Value=0; + NDIS_STATUS Status; +// OID_SET_HT_PHYMODE SetHT; +// WPDMA_GLO_CFG_STRUC GloCfg; + UINT32 MacCsr0 = 0; + UINT32 MacValue = 0; + +#ifdef RT2870 +#ifdef INF_AMAZON_SE + init_MUTEX(&(pAd->UsbVendorReq_semaphore)); + os_alloc_mem(pAd, (PUCHAR)&pAd->UsbVendorReqBuf, MAX_PARAM_BUFFER_SIZE - 1); + if (pAd->UsbVendorReqBuf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Allocate vendor request temp buffer failed!\n")); + goto err0; + } +#endif // INF_AMAZON_SE // +#endif // RT2870 // + +#ifdef DOT11_N_SUPPORT + // Allocate BA Reordering memory + ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM); +#endif // DOT11_N_SUPPORT // + + // Make sure MAC gets ready. + index = 0; + do + { + RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0); + pAd->MACVersion = MacCsr0; + + if ((pAd->MACVersion != 0x00) && (pAd->MACVersion != 0xFFFFFFFF)) + break; + + RTMPusecDelay(10); + } while (index++ < 100); + + DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion)); +/*Iverson patch PCIE L1 issue */ + + // Disable DMA + RT28XXDMADisable(pAd); + + + // Load 8051 firmware + Status = NICLoadFirmware(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status)); + goto err1; + } + + NICLoadRateSwitchingParams(pAd); + + // Disable interrupts here which is as soon as possible + // This statement should never be true. We might consider to remove it later + + Status = RTMPAllocTxRxRingMemory(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", Status)); + goto err1; + } + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + + // initialize MLME + // + + Status = MlmeInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status)); + goto err2; + } + + // Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default + // + UserCfgInit(pAd); + +#ifdef RT2870 + // We need init timerQ related structure before create the timer thread. + RT2870_TimerQ_Init(pAd); +#endif // RT2870 // + + RT28XX_TASK_THREAD_INIT(pAd, Status); + if (Status != NDIS_STATUS_SUCCESS) + goto err1; + +// COPY_MAC_ADDR(pAd->ApCfg.MBSSID[apidx].Bssid, netif->hwaddr); +// pAd->bForcePrintTX = TRUE; + + CfgInitHook(pAd); + + +#ifdef BLOCK_NET_IF + initblockQueueTab(pAd); +#endif // BLOCK_NET_IF // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisAllocateSpinLock(&pAd->MacTabLock); +#endif // CONFIG_STA_SUPPORT // + + MeasureReqTabInit(pAd); + TpcReqTabInit(pAd); + + // + // Init the hardware, we need to init asic before read registry, otherwise mac register will be reset + // + Status = NICInitializeAdapter(pAd, TRUE); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status)); + if (Status != NDIS_STATUS_SUCCESS) + goto err3; + } + + // Read parameters from Config File + Status = RTMPReadParametersHook(pAd); + + printk("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICReadRegParameters failed, Status[=0x%08x]\n",Status)); + goto err4; + } + +#ifdef RT2870 + pAd->CommonCfg.bMultipleIRP = FALSE; + + if (pAd->CommonCfg.bMultipleIRP) + pAd->CommonCfg.NumOfBulkInIRP = RX_RING_SIZE; + else + pAd->CommonCfg.NumOfBulkInIRP = 1; +#endif // RT2870 // + + + //Init Ba Capability parameters. +// RT28XX_BA_INIT(pAd); +#ifdef DOT11_N_SUPPORT + pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + // UPdata to HT IE + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; +#endif // DOT11_N_SUPPORT // + + // after reading Registry, we now know if in AP mode or STA mode + + // Load 8051 firmware; crash when FW image not existent + // Status = NICLoadFirmware(pAd); + // if (Status != NDIS_STATUS_SUCCESS) + // break; + + printk("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); + + // We should read EEPROM for all cases. rt2860b + NICReadEEPROMParameters(pAd, mac); +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + + printk("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode); + + NICInitAsicFromEEPROM(pAd); //rt2860b + + // Set PHY to appropriate mode + TmpPhy = pAd->CommonCfg.PhyMode; + pAd->CommonCfg.PhyMode = 0xff; + RTMPSetPhyMode(pAd, TmpPhy); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + + // No valid channels. + if (pAd->ChannelListNum == 0) + { + printk("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n"); + goto err4; + } + +#ifdef DOT11_N_SUPPORT + printk("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0], + pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2], + pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4]); +#endif // DOT11_N_SUPPORT // + +#ifdef RT30xx + //Init RT30xx RFRegisters after read RFIC type from EEPROM + NICInitRT30xxRFRegisters(pAd); +#endif // RT30xx // + +// APInitialize(pAd); + +#ifdef IKANOS_VX_1X0 + VR_IKANOS_FP_Init(pAd->ApCfg.BssidNum, pAd->PermanentAddress); +#endif // IKANOS_VX_1X0 // + + // + // Initialize RF register to default value + // + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + if (pAd && (Status != NDIS_STATUS_SUCCESS)) + { + // + // Undo everything if it failed + // + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { +// NdisMDeregisterInterrupt(&pAd->Interrupt); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + } +// RTMPFreeAdapter(pAd); // we will free it in disconnect() + } + else if (pAd) + { + // Microsoft HCT require driver send a disconnect event after driver initialization. + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); +// pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE); + + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n")); + + +#ifdef RT2870 + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS); + + // + // Support multiple BulkIn IRP, + // the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1. + // + for(index=0; indexCommonCfg.NumOfBulkInIRP; index++) + { + RTUSBBulkReceive(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkReceive!\n" )); + } +#endif // RT2870 // + }// end of else + + + DBGPRINT_S(Status, ("<==== RTMPInitialize, Status=%x\n", Status)); + + return TRUE; + + +err4: +err3: + MlmeHalt(pAd); +err2: + RTMPFreeTxRxRingMemory(pAd); +// RTMPFreeAdapter(pAd); +err1: + +#ifdef DOT11_N_SUPPORT + os_free_mem(pAd, pAd->mpdu_blk_pool.mem); // free BA pool +#endif // DOT11_N_SUPPORT // + RT28XX_IRQ_RELEASE(net_dev); + + // shall not set priv to NULL here because the priv didn't been free yet. + //net_dev->ml_priv = 0; +#ifdef INF_AMAZON_SE +err0: +#endif // INF_AMAZON_SE // + printk("!!! %s Initialized fail !!!\n", RT28xx_CHIP_NAME); + return FALSE; +} /* End of rt28xx_init */ + + +/* +======================================================================== +Routine Description: + Open raxx interface. + +Arguments: + *net_dev the raxx interface pointer + +Return Value: + 0 Open OK + otherwise Open Fail + +Note: +======================================================================== +*/ +int rt28xx_open(IN PNET_DEV dev) +{ + struct net_device * net_dev = (struct net_device *)dev; + PRTMP_ADAPTER pAd = net_dev->ml_priv; + int retval = 0; + POS_COOKIE pObj; + + + // Sanity check for pAd + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->ml_priv will be NULL in 2rd open */ + return -1; + } + +#ifdef CONFIG_APSTA_MIXED_SUPPORT + if (pAd->OpMode == OPMODE_AP) + { + CW_MAX_IN_BITS = 6; + } + else if (pAd->OpMode == OPMODE_STA) + { + CW_MAX_IN_BITS = 10; + } + +#if WIRELESS_EXT >= 12 + if (net_dev->ml_priv_flags == INT_MAIN) + { + if (pAd->OpMode == OPMODE_AP) + net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_ap_iw_handler_def; + else if (pAd->OpMode == OPMODE_STA) + net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_iw_handler_def; + } +#endif // WIRELESS_EXT >= 12 // +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + + // Init + pObj = (POS_COOKIE)pAd->OS_Cookie; + + // reset Adapter flags + RTMP_CLEAR_FLAGS(pAd); + + // Request interrupt service routine for PCI device + // register the interrupt routine with the os + RT28XX_IRQ_REQUEST(net_dev); + + + // Init BssTab & ChannelInfo tabbles for auto channel select. + + + // Chip & other init + if (rt28xx_init(net_dev) == FALSE) + goto err; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + NdisZeroMemory(pAd->StaCfg.dev_name, 16); + NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name)); + } +#endif // CONFIG_STA_SUPPORT // + + // Set up the Mac address + NdisMoveMemory(net_dev->dev_addr, (void *) pAd->CurrentAddress, 6); + + // Init IRQ parameters + RT28XX_IRQ_INIT(pAd); + + // Various AP function init + + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + // send wireless event to wpa_supplicant for infroming interface down. + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_INTERFACE_UP; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + + } +#endif // CONFIG_STA_SUPPORT // + + // Enable Interrupt + RT28XX_IRQ_ENABLE(pAd); + + // Now Enable RxTx + RTMPEnableRxTx(pAd); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + { + UINT32 reg = 0; + RTMP_IO_READ32(pAd, 0x1300, ®); // clear garbage interrupts + printk("0x1300 = %08x\n", reg); + } + + { +// u32 reg; +// u8 byte; +// u16 tmp; + +// RTMP_IO_READ32(pAd, XIFS_TIME_CFG, ®); + +// tmp = 0x0805; +// reg = (reg & 0xffff0000) | tmp; +// RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg); + + } + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + + return (retval); + +err: + return (-1); +} /* End of rt28xx_open */ + + +/* Must not be called for mdev and apdev */ +static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER pAd) +{ + NDIS_STATUS Status; + INT i=0; + CHAR slot_name[IFNAMSIZ]; + struct net_device *device; + + + //ether_setup(dev); + dev->hard_start_xmit = rt28xx_send_packets; + +#ifdef IKANOS_VX_1X0 + dev->hard_start_xmit = IKANOS_DataFramesTx; +#endif // IKANOS_VX_1X0 // + +// dev->set_multicast_list = ieee80211_set_multicast_list; +// dev->change_mtu = ieee80211_change_mtu; +#ifdef CONFIG_STA_SUPPORT +#if WIRELESS_EXT >= 12 + if (pAd->OpMode == OPMODE_STA) + { + dev->wireless_handlers = &rt28xx_iw_handler_def; + } +#endif //WIRELESS_EXT >= 12 +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +#if WIRELESS_EXT >= 12 + if (pAd->OpMode == OPMODE_AP) + { + dev->wireless_handlers = &rt28xx_ap_iw_handler_def; + } +#endif //WIRELESS_EXT >= 12 +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +#if WIRELESS_EXT < 21 + dev->get_wireless_stats = rt28xx_get_wireless_stats; +#endif + dev->get_stats = RT28xx_get_ether_stats; + dev->open = MainVirtualIF_open; //rt28xx_open; + dev->stop = MainVirtualIF_close; //rt28xx_close; +// dev->uninit = ieee80211_if_reinit; +// dev->destructor = ieee80211_if_free; + dev->priv_flags = INT_MAIN; + dev->do_ioctl = rt28xx_ioctl; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) + dev->validate_addr = NULL; +#endif + // find available device name + for (i = 0; i < 8; i++) + { +#ifdef MULTIPLE_CARD_SUPPORT + if (pAd->MC_RowID >= 0) + sprintf(slot_name, "ra%02d_%d", pAd->MC_RowID, i); + else +#endif // MULTIPLE_CARD_SUPPORT // + sprintf(slot_name, "ra%d", i); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + device = dev_get_by_name(dev_net(dev), slot_name); +#else + device = dev_get_by_name(dev->nd_net, slot_name); +#endif +#else + device = dev_get_by_name(slot_name); +#endif + if (device != NULL) dev_put(device); +#else + for (device = dev_base; device != NULL; device = device->next) + { + if (strncmp(device->name, slot_name, 4) == 0) + break; + } +#endif + if(device == NULL) + break; + } + + if(i == 8) + { + DBGPRINT(RT_DEBUG_ERROR, ("No available slot name\n")); + Status = NDIS_STATUS_FAILURE; + } + else + { +#ifdef MULTIPLE_CARD_SUPPORT + if (pAd->MC_RowID >= 0) + sprintf(dev->name, "ra%02d_%d", pAd->MC_RowID, i); + else +#endif // MULTIPLE_CARD_SUPPORT // + sprintf(dev->name, "ra%d", i); + Status = NDIS_STATUS_SUCCESS; + } + + return Status; + +} + + +#ifdef MULTIPLE_CARD_SUPPORT +/* +======================================================================== +Routine Description: + Get card profile path. + +Arguments: + pAd + +Return Value: + TRUE - Find a card profile + FALSE - use default profile + +Note: +======================================================================== +*/ +extern INT RTMPGetKeyParameter( + IN PCHAR key, + OUT PCHAR dest, + IN INT destsize, + IN PCHAR buffer); + +BOOLEAN RTMP_CardInfoRead( + IN PRTMP_ADAPTER pAd) +{ +#define MC_SELECT_CARDID 0 /* use CARD ID (0 ~ 31) to identify different cards */ +#define MC_SELECT_MAC 1 /* use CARD MAC to identify different cards */ +#define MC_SELECT_CARDTYPE 2 /* use CARD type (abgn or bgn) to identify different cards */ + +#define LETTER_CASE_TRANSLATE(txt_p, card_id) \ + { UINT32 _len; char _char; \ + for(_len=0; _lenfsuid; + orgfsgid = current->fsgid; + current->fsuid = current->fsgid = 0; + orgfs = get_fs(); + set_fs(KERNEL_DS); + + // get RF IC type + RTMP_IO_READ32(pAd, E2PROM_CSR, &data); + + if ((data & 0x30) == 0) + pAd->EEPROMAddressNum = 6; // 93C46 + else if ((data & 0x30) == 0x10) + pAd->EEPROMAddressNum = 8; // 93C66 + else + pAd->EEPROMAddressNum = 8; // 93C86 + + //antenna.word = RTMP_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET); + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, antenna.word); + + if ((antenna.field.RfIcType == RFIC_2850) || + (antenna.field.RfIcType == RFIC_2750)) + { + /* ABGN card */ + strcpy(RFIC_word, "abgn"); + } + else + { + /* BGN card */ + strcpy(RFIC_word, "bgn"); + } + + // get MAC address + //addr01 = RTMP_EEPROM_READ16(pAd, 0x04); + //addr23 = RTMP_EEPROM_READ16(pAd, 0x06); + //addr45 = RTMP_EEPROM_READ16(pAd, 0x08); + RT28xx_EEPROM_READ16(pAd, 0x04, addr01); + RT28xx_EEPROM_READ16(pAd, 0x06, addr23); + RT28xx_EEPROM_READ16(pAd, 0x08, addr45); + + mac[0] = (UCHAR)(addr01 & 0xff); + mac[1] = (UCHAR)(addr01 >> 8); + mac[2] = (UCHAR)(addr23 & 0xff); + mac[3] = (UCHAR)(addr23 >> 8); + mac[4] = (UCHAR)(addr45 & 0xff); + mac[5] = (UCHAR)(addr45 >> 8); + + // open card information file + srcf = filp_open(CARD_INFO_PATH, O_RDONLY, 0); + if (IS_ERR(srcf)) + { + /* card information file does not exist */ + DBGPRINT(RT_DEBUG_TRACE, + ("--> Error %ld opening %s\n", -PTR_ERR(srcf), CARD_INFO_PATH)); + return FALSE; + } + + if (srcf->f_op && srcf->f_op->read) + { + /* card information file exists so reading the card information */ + memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); + retval = srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos); + if (retval < 0) + { + /* read fail */ + DBGPRINT(RT_DEBUG_TRACE, + ("--> Read %s error %d\n", CARD_INFO_PATH, -retval)); + } + else + { + /* get card selection method */ + memset(tmpbuf, 0x00, MAX_PARAM_BUFFER_SIZE); + card_select_method = MC_SELECT_CARDTYPE; // default + + if (RTMPGetKeyParameter("SELECT", tmpbuf, 256, buffer)) + { + if (strcmp(tmpbuf, "CARDID") == 0) + card_select_method = MC_SELECT_CARDID; + else if (strcmp(tmpbuf, "MAC") == 0) + card_select_method = MC_SELECT_MAC; + else if (strcmp(tmpbuf, "CARDTYPE") == 0) + card_select_method = MC_SELECT_CARDTYPE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("MC> Card Selection = %d\n", card_select_method)); + + // init + card_free_id = -1; + card_nouse_id = -1; + card_same_mac_id = -1; + card_match_id = -1; + + // search current card information records + for(card_index=0; + card_index Free = %d, Same = %d, NOUSE = %d\n", + card_free_id, card_same_mac_id, card_nouse_id)); + + if ((card_same_mac_id >= 0) && + ((card_select_method == MC_SELECT_CARDID) || + (card_select_method == MC_SELECT_CARDTYPE))) + { + // same MAC entry is found + card_match_id = card_same_mac_id; + + if (card_select_method == MC_SELECT_CARDTYPE) + { + // for CARDTYPE + sprintf(card_id_buf, "%02dCARDTYPE%s", + card_match_id, RFIC_word); + + if ((start_ptr=rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + // we found the card ID + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + } + } + } + else + { + // the card is 1st plug-in, try to find the match card profile + switch(card_select_method) + { + case MC_SELECT_CARDID: // CARDID + default: + if (card_free_id >= 0) + card_match_id = card_free_id; + else + card_match_id = card_nouse_id; + break; + + case MC_SELECT_MAC: // MAC + sprintf(card_id_buf, "MAC%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + + /* try to find the key word in the card file */ + if ((start_ptr=rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + + /* get the row ID (2 ASCII characters) */ + start_ptr -= 2; + card_id_buf[0] = *(start_ptr); + card_id_buf[1] = *(start_ptr+1); + card_id_buf[2] = 0x00; + + card_match_id = simple_strtol(card_id_buf, 0, 10); + } + break; + + case MC_SELECT_CARDTYPE: // CARDTYPE + card_nouse_id = -1; + + for(card_index=0; + card_index= 0) + { + // make up search keyword + switch(card_select_method) + { + case MC_SELECT_CARDID: // CARDID + sprintf(card_id_buf, "%02dCARDID", card_match_id); + break; + + case MC_SELECT_MAC: // MAC + sprintf(card_id_buf, + "%02dmac%02x:%02x:%02x:%02x:%02x:%02x", + card_match_id, + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + break; + + case MC_SELECT_CARDTYPE: // CARDTYPE + default: + sprintf(card_id_buf, "%02dcardtype%s", + card_match_id, RFIC_word); + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Search Keyword = %s\n", card_id_buf)); + + // read card file path + if (RTMPGetKeyParameter(card_id_buf, tmpbuf, 256, buffer)) + { + if (strlen(tmpbuf) < sizeof(pAd->MC_FileName)) + { + // backup card information + pAd->MC_RowID = card_match_id; /* base 0 */ + MC_CardUsed[card_match_id] = 1; + memcpy(MC_CardMac[card_match_id], mac, sizeof(mac)); + + // backup card file path + NdisMoveMemory(pAd->MC_FileName, tmpbuf , strlen(tmpbuf)); + pAd->MC_FileName[strlen(tmpbuf)] = '\0'; + flg_match_ok = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, + ("Card Profile Name = %s\n", pAd->MC_FileName)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("Card Profile Name length too large!\n")); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("Can not find search key word in card.dat!\n")); + } + + if ((flg_match_ok != TRUE) && + (card_match_id < MAX_NUM_OF_MULTIPLE_CARD)) + { + MC_CardUsed[card_match_id] = 0; + memset(MC_CardMac[card_match_id], 0, sizeof(mac)); + } + } // if (card_match_id >= 0) + } + } + + // close file + retval = filp_close(srcf, NULL); + set_fs(orgfs); + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; + kfree(buffer); + kfree(tmpbuf); + return flg_match_ok; +} +#endif // MULTIPLE_CARD_SUPPORT // + + +/* +======================================================================== +Routine Description: + Probe RT28XX chipset. + +Arguments: + _dev_p Point to the PCI or USB device + _dev_id_p Point to the PCI or USB device ID + +Return Value: + 0 Probe OK + -ENODEV Probe Fail + +Note: +======================================================================== +*/ +INT __devinit rt28xx_probe( + IN void *_dev_p, + IN void *_dev_id_p, + IN UINT argc, + OUT PRTMP_ADAPTER *ppAd) +{ + struct net_device *net_dev; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL; + INT status; + PVOID handle; +#ifdef RT2870 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */ + struct usb_device *dev_p = (struct usb_device *)_dev_p; +#else + struct usb_interface *intf = (struct usb_interface *)_dev_p; + struct usb_device *dev_p = interface_to_usbdev(intf); + + dev_p = usb_get_dev(dev_p); +#endif // LINUX_VERSION_CODE // +#endif // RT2870 // + + +#ifdef CONFIG_STA_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("STA Driver version-%s\n", STA_DRIVER_VERSION)); +#endif // CONFIG_STA_SUPPORT // + + // Check chipset vendor/product ID +// if (RT28XXChipsetCheck(_dev_p) == FALSE) +// goto err_out; + +#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 + net_dev = alloc_netdev(sizeof(PRTMP_ADAPTER), "eth%d", ether_setup); +#else + net_dev = alloc_etherdev(sizeof(PRTMP_ADAPTER)); +#endif + if (net_dev == NULL) + { + printk("alloc_netdev failed\n"); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) + module_put(THIS_MODULE); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) +#else + MOD_DEC_USE_COUNT; +#endif + goto err_out; + } + +// sample +// if (rt_ieee80211_if_setup(net_dev) != NDIS_STATUS_SUCCESS) +// goto err_out; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + SET_MODULE_OWNER(net_dev); +#endif + + netif_stop_queue(net_dev); +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +/* for supporting Network Manager */ +/* Set the sysfs physical device reference for the network logical device + * if set prior to registration will cause a symlink during initialization. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + SET_NETDEV_DEV(net_dev, &(dev_p->dev)); +#endif +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + // Allocate RTMP_ADAPTER miniport adapter structure + handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL); + RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p); + + status = RTMPAllocAdapterBlock(handle, &pAd); + if (status != NDIS_STATUS_SUCCESS) + goto err_out_free_netdev; + + net_dev->ml_priv = (PVOID)pAd; + pAd->net_dev = net_dev; // must be before RT28XXNetDevInit() + + RT28XXNetDevInit(_dev_p, net_dev, pAd); + +#ifdef CONFIG_STA_SUPPORT + pAd->StaCfg.OriDevType = net_dev->type; +#endif // CONFIG_STA_SUPPORT // + + // Find and assign a free interface name, raxx +// RT28XXAvailRANameAssign(net_dev->name); + + // Post config +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + if (RT28XXProbePostConfig(_dev_p, pAd, argc) == FALSE) + goto err_out_unmap; +#else + if (RT28XXProbePostConfig(_dev_p, pAd, 0) == FALSE) + goto err_out_unmap; +#endif // LINUX_VERSION_CODE // + +#ifdef CONFIG_STA_SUPPORT + pAd->OpMode = OPMODE_STA; +#endif // CONFIG_STA_SUPPORT // + + +#ifdef MULTIPLE_CARD_SUPPORT + // find its profile path + pAd->MC_RowID = -1; // use default profile path + RTMP_CardInfoRead(pAd); + + if (pAd->MC_RowID == -1) +#ifdef CONFIG_STA_SUPPORT + strcpy(pAd->MC_FileName, STA_PROFILE_PATH); +#endif // CONFIG_STA_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, + ("MC> ROW = %d, PATH = %s\n", pAd->MC_RowID, pAd->MC_FileName)); +#endif // MULTIPLE_CARD_SUPPORT // + + // sample move + if (rt_ieee80211_if_setup(net_dev, pAd) != NDIS_STATUS_SUCCESS) + goto err_out_unmap; + + // Register this device + status = register_netdev(net_dev); + if (status) + goto err_out_unmap; + + // Set driver data + RT28XX_DRVDATA_SET(_dev_p); + + + + *ppAd = pAd; + return 0; // probe ok + + + /* --------------------------- ERROR HANDLE --------------------------- */ +err_out_unmap: + RTMPFreeAdapter(pAd); + RT28XX_UNMAP(); + +err_out_free_netdev: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + free_netdev(net_dev); +#else + kfree(net_dev); +#endif + +err_out: + RT28XX_PUT_DEVICE(dev_p); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + return (LONG)NULL; +#else + return -ENODEV; /* probe fail */ +#endif // LINUX_VERSION_CODE // +} /* End of rt28xx_probe */ + + +/* +======================================================================== +Routine Description: + The entry point for Linux kernel sent packet to our driver. + +Arguments: + sk_buff *skb the pointer refer to a sk_buffer. + +Return Value: + 0 + +Note: + This function is the entry point of Tx Path for Os delivery packet to + our driver. You only can put OS-depened & STA/AP common handle procedures + in here. +======================================================================== +*/ +int rt28xx_packet_xmit(struct sk_buff *skb) +{ + struct net_device *net_dev = skb->dev; + PRTMP_ADAPTER pAd = net_dev->ml_priv; + int status = 0; + PNDIS_PACKET pPacket = (PNDIS_PACKET) skb; + + /* RT2870STA does this in RTMPSendPackets() */ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES); + return 0; + } +#endif // RALINK_ATE // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + // Drop send request since we are in monitor mode + if (MONITOR_ON(pAd)) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + goto done; + } + } +#endif // CONFIG_STA_SUPPORT // + + // EapolStart size is 18 + if (skb->len < 14) + { + //printk("bad packet size: %d\n", pkt->len); + hex_dump("bad packet", skb->data, skb->len); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + goto done; + } + + RTMP_SET_PACKET_5VT(pPacket, 0); +// MiniportMMRequest(pAd, pkt->data, pkt->len); +#ifdef CONFIG_5VT_ENHANCE + if (*(int*)(skb->cb) == BRIDGE_TAG) { + RTMP_SET_PACKET_5VT(pPacket, 1); + } +#endif + + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + + STASendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1); + } + +#endif // CONFIG_STA_SUPPORT // + + status = 0; +done: + + return status; +} + + +/* +======================================================================== +Routine Description: + Send a packet to WLAN. + +Arguments: + skb_p points to our adapter + dev_p which WLAN network interface + +Return Value: + 0: transmit successfully + otherwise: transmit fail + +Note: +======================================================================== +*/ +INT rt28xx_send_packets( + IN struct sk_buff *skb_p, + IN struct net_device *net_dev) +{ + RTMP_ADAPTER *pAd = net_dev->ml_priv; + + if (!(net_dev->flags & IFF_UP)) + { + RELEASE_NDIS_PACKET(pAd, (PNDIS_PACKET)skb_p, NDIS_STATUS_FAILURE); + return 0; + } + + NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF], 15); + RTMP_SET_PACKET_NET_DEVICE_MBSSID(skb_p, MAIN_MBSSID); + + return rt28xx_packet_xmit(skb_p); +} /* End of MBSS_VirtualIF_PacketSend */ + + + + +#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1 +//static struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)) //sample +struct net_device *alloc_netdev( + int sizeof_priv, + const char *mask, + void (*setup)(struct net_device *)) +{ + struct net_device *dev; + INT alloc_size; + + + /* ensure 32-byte alignment of the private area */ + alloc_size = sizeof (*dev) + sizeof_priv + 31; + + dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL); + if (dev == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, + ("alloc_netdev: Unable to allocate device memory.\n")); + return NULL; + } + + memset(dev, 0, alloc_size); + + if (sizeof_priv) + dev->ml_priv = (void *) (((long)(dev + 1) + 31) & ~31); + + setup(dev); + strcpy(dev->name, mask); + + return dev; +} +#endif // LINUX_VERSION_CODE // + + +void CfgInitHook(PRTMP_ADAPTER pAd) +{ + pAd->bBroadComHT = TRUE; +} /* End of CfgInitHook */ + + +#if WIRELESS_EXT >= 12 +// This function will be called when query /proc +struct iw_statistics *rt28xx_get_wireless_stats( + IN struct net_device *net_dev) +{ + PRTMP_ADAPTER pAd = net_dev->ml_priv; + + + DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n")); + + pAd->iw_stats.status = 0; // Status - device dependent for now + + // link quality + pAd->iw_stats.qual.qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10); + if(pAd->iw_stats.qual.qual > 100) + pAd->iw_stats.qual.qual = 100; + +#ifdef CONFIG_STA_SUPPORT + if (pAd->OpMode == OPMODE_STA) + pAd->iw_stats.qual.level = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2); +#endif // CONFIG_STA_SUPPORT // + + pAd->iw_stats.qual.noise = pAd->BbpWriteLatch[66]; // noise level (dBm) + + pAd->iw_stats.qual.noise += 256 - 143; + pAd->iw_stats.qual.updated = 1; // Flags to know if updated +#ifdef IW_QUAL_DBM + pAd->iw_stats.qual.updated |= IW_QUAL_DBM; // Level + Noise are dBm +#endif // IW_QUAL_DBM // + + pAd->iw_stats.discard.nwid = 0; // Rx : Wrong nwid/essid + pAd->iw_stats.miss.beacon = 0; // Missed beacons/superframe + + DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n")); + return &pAd->iw_stats; +} /* End of rt28xx_get_wireless_stats */ +#endif // WIRELESS_EXT // + + + +void tbtt_tasklet(unsigned long data) +{ +#define MAX_TX_IN_TBTT (16) + +} + +INT rt28xx_ioctl( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN INT cmd) +{ + VIRTUAL_ADAPTER *pVirtualAd = NULL; + RTMP_ADAPTER *pAd = NULL; + INT ret = 0; + + if (net_dev->priv_flags == INT_MAIN) + { + pAd = net_dev->ml_priv; + } + else + { + pVirtualAd = net_dev->ml_priv; + pAd = pVirtualAd->RtmpDev->ml_priv; + } + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->ml_priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + ret = rt28xx_sta_ioctl(net_dev, rq, cmd); + } +#endif // CONFIG_STA_SUPPORT // + + return ret; +} + +/* + ======================================================================== + + Routine Description: + return ethernet statistics counter + + Arguments: + net_dev Pointer to net_device + + Return Value: + net_device_stats* + + Note: + + ======================================================================== +*/ +struct net_device_stats *RT28xx_get_ether_stats( + IN struct net_device *net_dev) +{ + RTMP_ADAPTER *pAd = NULL; + + if (net_dev) + pAd = net_dev->ml_priv; + + if (pAd) + { + + pAd->stats.rx_packets = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; + pAd->stats.tx_packets = pAd->WlanCounters.TransmittedFragmentCount.QuadPart; + + pAd->stats.rx_bytes = pAd->RalinkCounters.ReceivedByteCount; + pAd->stats.tx_bytes = pAd->RalinkCounters.TransmittedByteCount; + + pAd->stats.rx_errors = pAd->Counters8023.RxErrors; + pAd->stats.tx_errors = pAd->Counters8023.TxErrors; + + pAd->stats.rx_dropped = 0; + pAd->stats.tx_dropped = 0; + + pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; // multicast packets received + pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions; // Collision packets + + pAd->stats.rx_length_errors = 0; + pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer; // receiver ring buff overflow + pAd->stats.rx_crc_errors = 0;//pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error + pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors; // recv'd frame alignment error + pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer; // recv'r fifo overrun + pAd->stats.rx_missed_errors = 0; // receiver missed packet + + // detailed tx_errors + pAd->stats.tx_aborted_errors = 0; + pAd->stats.tx_carrier_errors = 0; + pAd->stats.tx_fifo_errors = 0; + pAd->stats.tx_heartbeat_errors = 0; + pAd->stats.tx_window_errors = 0; + + // for cslip etc + pAd->stats.rx_compressed = 0; + pAd->stats.tx_compressed = 0; + + return &pAd->stats; + } + else + return NULL; +} + diff --git a/drivers/staging/rt3070/rt_profile.c b/drivers/staging/rt3070/rt_profile.c new file mode 100644 index 000000000000..6eda27e6b8dc --- /dev/null +++ b/drivers/staging/rt3070/rt_profile.c @@ -0,0 +1,2041 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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 "rt_config.h" + +#ifdef DOT11_N_SUPPORT +static void HTParametersHook( + IN PRTMP_ADAPTER pAd, + IN CHAR *pValueStr, + IN CHAR *pInput); +#endif // DOT11_N_SUPPORT // + +#define ETH_MAC_ADDR_STR_LEN 17 // in format of xx:xx:xx:xx:xx:xx + +// We assume the s1 is a sting, s2 is a memory space with 6 bytes. and content of s1 will be changed. +BOOLEAN rtstrmactohex(char *s1, char *s2) +{ + int i = 0; + char *ptokS = s1, *ptokE = s1; + + if (strlen(s1) != ETH_MAC_ADDR_STR_LEN) + return FALSE; + + while((*ptokS) != '\0') + { + if((ptokE = strchr(ptokS, ':')) != NULL) + *ptokE++ = '\0'; + if ((strlen(ptokS) != 2) || (!isxdigit(*ptokS)) || (!isxdigit(*(ptokS+1)))) + break; // fail + AtoH(ptokS, &s2[i++], 1); + ptokS = ptokE; + if (i == 6) + break; // parsing finished + } + + return ( i == 6 ? TRUE : FALSE); + +} + + +// we assume the s1 and s2 both are strings. +BOOLEAN rtstrcasecmp(char *s1, char *s2) +{ + char *p1 = s1, *p2 = s2; + + if (strlen(s1) != strlen(s2)) + return FALSE; + + while(*p1 != '\0') + { + if((*p1 != *p2) && ((*p1 ^ *p2) != 0x20)) + return FALSE; + p1++; + p2++; + } + + return TRUE; +} + +// we assume the s1 (buffer) and s2 (key) both are strings. +char * rtstrstruncasecmp(char * s1, char * s2) +{ + INT l1, l2, i; + char temp1, temp2; + + l2 = strlen(s2); + if (!l2) + return (char *) s1; + + l1 = strlen(s1); + + while (l1 >= l2) + { + l1--; + + for(i=0; i= l2) + { + l1--; + if (!memcmp(s1,s2,l2)) + return (char *) s1; + s1++; + } + + return NULL; +} + +/** + * rstrtok - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * * WARNING: strtok is deprecated, use strsep instead. However strsep is not compatible with old architecture. + */ +char * __rstrtok; +char * rstrtok(char * s,const char * ct) +{ + char *sbegin, *send; + + sbegin = s ? s : __rstrtok; + if (!sbegin) + { + return NULL; + } + + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') + { + __rstrtok = NULL; + return( NULL ); + } + + send = strpbrk( sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + + __rstrtok = send; + + return (sbegin); +} + +/** + * delimitcnt - return the count of a given delimiter in a given string. + * @s: The string to be searched. + * @ct: The delimiter to search for. + * Notice : We suppose the delimiter is a single-char string(for example : ";"). + */ +INT delimitcnt(char * s,const char * ct) +{ + INT count = 0; + /* point to the beginning of the line */ + const char *token = s; + + for ( ;; ) + { + token = strpbrk(token, ct); /* search for delimiters */ + + if ( token == NULL ) + { + /* advanced to the terminating null character */ + break; + } + /* skip the delimiter */ + ++token; + + /* + * Print the found text: use len with %.*s to specify field width. + */ + + /* accumulate delimiter count */ + ++count; + } + return count; +} + +/* + * converts the Internet host address from the standard numbers-and-dots notation + * into binary data. + * returns nonzero if the address is valid, zero if not. + */ +int rtinet_aton(const char *cp, unsigned int *addr) +{ + unsigned int val; + int base, n; + char c; + unsigned int parts[4]; + unsigned int *pp = parts; + + for (;;) + { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, other=decimal. + */ + val = 0; + base = 10; + if (*cp == '0') + { + if (*++cp == 'x' || *cp == 'X') + base = 16, cp++; + else + base = 8; + } + while ((c = *cp) != '\0') + { + if (isdigit((unsigned char) c)) + { + val = (val * base) + (c - '0'); + cp++; + continue; + } + if (base == 16 && isxdigit((unsigned char) c)) + { + val = (val << 4) + + (c + 10 - (islower((unsigned char) c) ? 'a' : 'A')); + cp++; + continue; + } + break; + } + if (*cp == '.') + { + /* + * Internet format: a.b.c.d a.b.c (with c treated as 16-bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3 || val > 0xff) + return 0; + *pp++ = val, cp++; + } + else + break; + } + + /* + * Check for trailing junk. + */ + while (*cp) + if (!isspace((unsigned char) *cp++)) + return 0; + + /* + * Concoct the address according to the number of parts specified. + */ + n = pp - parts + 1; + switch (n) + { + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return 0; + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return 0; + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return 0; + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + + *addr = htonl(val); + return 1; + +} + +/* + ======================================================================== + + Routine Description: + Find key section for Get key parameter. + + Arguments: + buffer Pointer to the buffer to start find the key section + section the key of the secion to be find + + Return Value: + NULL Fail + Others Success + ======================================================================== +*/ +PUCHAR RTMPFindSection( + IN PCHAR buffer) +{ + CHAR temp_buf[32]; + PUCHAR ptr; + + strcpy(temp_buf, "Default"); + + if((ptr = rtstrstr(buffer, temp_buf)) != NULL) + return (ptr+strlen("\n")); + else + return NULL; +} + +/* + ======================================================================== + + Routine Description: + Get key parameter. + + Arguments: + key Pointer to key string + dest Pointer to destination + destsize The datasize of the destination + buffer Pointer to the buffer to start find the key + + Return Value: + TRUE Success + FALSE Fail + + Note: + This routine get the value with the matched key (case case-sensitive) + ======================================================================== +*/ +INT RTMPGetKeyParameter( + IN PCHAR key, + OUT PCHAR dest, + IN INT destsize, + IN PCHAR buffer) +{ + UCHAR *temp_buf1 = NULL; + UCHAR *temp_buf2 = NULL; + CHAR *start_ptr; + CHAR *end_ptr; + CHAR *ptr; + CHAR *offset = 0; + INT len; + + //temp_buf1 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); + os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE); + + if(temp_buf1 == NULL) + return (FALSE); + + //temp_buf2 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); + os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE); + if(temp_buf2 == NULL) + { + os_free_mem(NULL, temp_buf1); + return (FALSE); + } + + //find section + if((offset = RTMPFindSection(buffer)) == NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + strcpy(temp_buf1, "\n"); + strcat(temp_buf1, key); + strcat(temp_buf1, "="); + + //search key + if((start_ptr=rtstrstr(offset, temp_buf1))==NULL) + { + os_free_mem(NULL, temp_buf1); + os_free_mem(NULL, temp_buf2); + return (FALSE); + } + + start_ptr+=strlen("\n"); + if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL) + end_ptr=start_ptr+strlen(start_ptr); + + if (end_ptrSharedKey[i][idx].KeyLen = KeyLen / 2; + AtoH(keybuff, pAd->SharedKey[i][idx].Key, KeyLen / 2); + if (KeyLen == 10) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + pAd->SharedKey[i][idx].CipherAlg = CipherAlg; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Key%dStr=%s and type=%s\n", i, idx+1, keybuff, (KeyType == 0) ? "Hex":"Ascii")); + return 1; + } + else + {//Invalid key length + DBGPRINT(RT_DEBUG_ERROR, ("I/F(ra%d) Key%dStr is Invalid key length! KeyLen = %ld!\n", i, idx+1, KeyLen)); + return 0; + } + } +} +static void rtmp_read_key_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) +{ + char tok_str[16]; + PUCHAR macptr; + INT i = 0, idx; + ULONG KeyType[MAX_MBSSID_NUM]; + ULONG KeyIdx; + + NdisZeroMemory(KeyType, MAX_MBSSID_NUM); + + //DefaultKeyID + if(RTMPGetKeyParameter("DefaultKeyID", tmpbuf, 25, buffer)) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + KeyIdx = simple_strtol(tmpbuf, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAd->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1); + else + pAd->StaCfg.DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyID(0~3)=%d\n", pAd->StaCfg.DefaultKeyId)); + } +#endif // CONFIG_STA_SUPPORT // + } + + + for (idx = 0; idx < 4; idx++) + { + sprintf(tok_str, "Key%dType", idx + 1); + //Key1Type + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + KeyType[i] = simple_strtol(macptr, 0, 10); + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + sprintf(tok_str, "Key%dStr", idx + 1); + if (RTMPGetCriticalParameter(tok_str, tmpbuf, 128, buffer)) + { + rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx); + } + } +#endif // CONFIG_STA_SUPPORT // + } + } +} + + +#ifdef CONFIG_STA_SUPPORT +static void rtmp_read_sta_wmm_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer) +{ + PUCHAR macptr; + INT i=0; + BOOLEAN bWmmEnable = FALSE; + + //WmmCapable + if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + { + pAd->CommonCfg.bWmmCapable = TRUE; + bWmmEnable = TRUE; + } + else //Disable + { + pAd->CommonCfg.bWmmCapable = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("WmmCapable=%d\n", pAd->CommonCfg.bWmmCapable)); + } + +#ifdef QOS_DLS_SUPPORT + //DLSCapable + if(RTMPGetKeyParameter("DLSCapable", tmpbuf, 32, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + { + pAd->CommonCfg.bDLSCapable = TRUE; + } + else //Disable + { + pAd->CommonCfg.bDLSCapable = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("bDLSCapable=%d\n", pAd->CommonCfg.bDLSCapable)); + } +#endif // QOS_DLS_SUPPORT // + + //AckPolicy for AC_BK, AC_BE, AC_VI, AC_VO + if(RTMPGetKeyParameter("AckPolicy", tmpbuf, 32, buffer)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.AckPolicy[i] = (UCHAR)simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("AckPolicy[%d]=%d\n", i, pAd->CommonCfg.AckPolicy[i])); + } + } + + if (bWmmEnable) + { + //APSDCapable + if(RTMPGetKeyParameter("APSDCapable", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->CommonCfg.bAPSDCapable = TRUE; + else + pAd->CommonCfg.bAPSDCapable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("APSDCapable=%d\n", pAd->CommonCfg.bAPSDCapable)); + } + + //APSDAC for AC_BE, AC_BK, AC_VI, AC_VO + if(RTMPGetKeyParameter("APSDAC", tmpbuf, 32, buffer)) + { + BOOLEAN apsd_ac[4]; + + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + apsd_ac[i] = (BOOLEAN)simple_strtol(macptr, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("APSDAC%d %d\n", i, apsd_ac[i])); + } + + pAd->CommonCfg.bAPSDAC_BE = apsd_ac[0]; + pAd->CommonCfg.bAPSDAC_BK = apsd_ac[1]; + pAd->CommonCfg.bAPSDAC_VI = apsd_ac[2]; + pAd->CommonCfg.bAPSDAC_VO = apsd_ac[3]; + } + } + +} +#endif // CONFIG_STA_SUPPORT // + + +NDIS_STATUS RTMPReadParametersHook( + IN PRTMP_ADAPTER pAd) +{ + PUCHAR src = NULL; + struct file *srcf; + INT retval, orgfsuid, orgfsgid; + mm_segment_t orgfs; + CHAR *buffer; + CHAR *tmpbuf; + ULONG RtsThresh; + ULONG FragThresh; +#ifdef CONFIG_STA_SUPPORT + UCHAR keyMaterial[40]; +#endif // CONFIG_STA_SUPPORT // + + + PUCHAR macptr; + INT i = 0; + + buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG); + if(buffer == NULL) + return NDIS_STATUS_FAILURE; + + tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG); + if(tmpbuf == NULL) + { + kfree(buffer); + return NDIS_STATUS_FAILURE; + } + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + src = STA_PROFILE_PATH; +#endif // CONFIG_STA_SUPPORT // +#ifdef MULTIPLE_CARD_SUPPORT + src = pAd->MC_FileName; +#endif // MULTIPLE_CARD_SUPPORT // + + // Save uid and gid used for filesystem access. + // Set user and group to 0 (root) +#if 0 + orgfsuid = current->fsuid; + orgfsgid = current->fsgid; + current->fsuid=current->fsgid = 0; +#endif + orgfs = get_fs(); + set_fs(KERNEL_DS); + + if (src && *src) + { + srcf = filp_open(src, O_RDONLY, 0); + if (IS_ERR(srcf)) + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src)); + } + else + { + // The object must have a read method + if (srcf->f_op && srcf->f_op->read) + { + memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); + retval=srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos); + if (retval < 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Read %s error %d\n", src, -retval)); + } + else + { + // set file parameter to portcfg + //CountryRegion + if(RTMPGetKeyParameter("CountryRegion", tmpbuf, 25, buffer)) + { + pAd->CommonCfg.CountryRegion = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("CountryRegion=%d\n", pAd->CommonCfg.CountryRegion)); + } + //CountryRegionABand + if(RTMPGetKeyParameter("CountryRegionABand", tmpbuf, 25, buffer)) + { + pAd->CommonCfg.CountryRegionForABand= (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("CountryRegionABand=%d\n", pAd->CommonCfg.CountryRegionForABand)); + } + //CountryCode + if(RTMPGetKeyParameter("CountryCode", tmpbuf, 25, buffer)) + { + NdisMoveMemory(pAd->CommonCfg.CountryCode, tmpbuf , 2); +#ifdef CONFIG_STA_SUPPORT +#ifdef EXT_BUILD_CHANNEL_LIST + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + NdisMoveMemory(pAd->StaCfg.StaOriCountryCode, tmpbuf , 2); +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // + if (strlen(pAd->CommonCfg.CountryCode) != 0) + { + pAd->CommonCfg.bCountryFlag = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("CountryCode=%s\n", pAd->CommonCfg.CountryCode)); + } + //ChannelGeography + if(RTMPGetKeyParameter("ChannelGeography", tmpbuf, 25, buffer)) + { + UCHAR Geography = (UCHAR) simple_strtol(tmpbuf, 0, 10); + if (Geography <= BOTH) + { + pAd->CommonCfg.Geography = Geography; + pAd->CommonCfg.CountryCode[2] = + (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O'); +#ifdef CONFIG_STA_SUPPORT +#ifdef EXT_BUILD_CHANNEL_LIST + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->StaCfg.StaOriGeography = pAd->CommonCfg.Geography; +#endif // EXT_BUILD_CHANNEL_LIST // +#endif // CONFIG_STA_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("ChannelGeography=%d\n", pAd->CommonCfg.Geography)); + } + } + else + { + pAd->CommonCfg.Geography = BOTH; + pAd->CommonCfg.CountryCode[2] = ' '; + } + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + //SSID + if (RTMPGetCriticalParameter("SSID", tmpbuf, 256, buffer)) + { + if (strlen(tmpbuf) <= 32) + { + pAd->CommonCfg.SsidLen = (UCHAR) strlen(tmpbuf); + NdisZeroMemory(pAd->CommonCfg.Ssid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->CommonCfg.Ssid, tmpbuf, pAd->CommonCfg.SsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, tmpbuf, pAd->MlmeAux.AutoReconnectSsidLen); + pAd->MlmeAux.SsidLen = pAd->CommonCfg.SsidLen; + NdisZeroMemory(pAd->MlmeAux.Ssid, NDIS_802_11_LENGTH_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, tmpbuf, pAd->MlmeAux.SsidLen); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(SSID=%s)\n", __FUNCTION__, tmpbuf)); + } + } + } +#endif // CONFIG_STA_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + //NetworkType + if (RTMPGetKeyParameter("NetworkType", tmpbuf, 25, buffer)) + { + pAd->bConfigChanged = TRUE; + if (strcmp(tmpbuf, "Adhoc") == 0) + pAd->StaCfg.BssType = BSS_ADHOC; + else //Default Infrastructure mode + pAd->StaCfg.BssType = BSS_INFRA; + // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key + pAd->StaCfg.WpaState = SS_NOTUSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s::(NetworkType=%d)\n", __FUNCTION__, pAd->StaCfg.BssType)); + } + } +#endif // CONFIG_STA_SUPPORT // + //Channel + if(RTMPGetKeyParameter("Channel", tmpbuf, 10, buffer)) + { + pAd->CommonCfg.Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Channel=%d\n", pAd->CommonCfg.Channel)); + } + //WirelessMode + if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 10, buffer)) + { + int value = 0, maxPhyMode = PHY_11G; + +#ifdef DOT11_N_SUPPORT + maxPhyMode = PHY_11N_5G; +#endif // DOT11_N_SUPPORT // + + value = simple_strtol(tmpbuf, 0, 10); + + if (value <= maxPhyMode) + { + pAd->CommonCfg.PhyMode = value; + } + DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode)); + } + //BasicRate + if(RTMPGetKeyParameter("BasicRate", tmpbuf, 10, buffer)) + { + pAd->CommonCfg.BasicRateBitmap = (ULONG) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("BasicRate=%ld\n", pAd->CommonCfg.BasicRateBitmap)); + } + //BeaconPeriod + if(RTMPGetKeyParameter("BeaconPeriod", tmpbuf, 10, buffer)) + { + pAd->CommonCfg.BeaconPeriod = (USHORT) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("BeaconPeriod=%d\n", pAd->CommonCfg.BeaconPeriod)); + } + //TxPower + if(RTMPGetKeyParameter("TxPower", tmpbuf, 10, buffer)) + { + pAd->CommonCfg.TxPowerPercentage = (ULONG) simple_strtol(tmpbuf, 0, 10); +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + pAd->CommonCfg.TxPowerDefault = pAd->CommonCfg.TxPowerPercentage; +#endif // CONFIG_STA_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("TxPower=%ld\n", pAd->CommonCfg.TxPowerPercentage)); + } + //BGProtection + if(RTMPGetKeyParameter("BGProtection", tmpbuf, 10, buffer)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case 1: //Always On + pAd->CommonCfg.UseBGProtection = 1; + break; + case 2: //Always OFF + pAd->CommonCfg.UseBGProtection = 2; + break; + case 0: //AUTO + default: + pAd->CommonCfg.UseBGProtection = 0; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("BGProtection=%ld\n", pAd->CommonCfg.UseBGProtection)); + } + //OLBCDetection + if(RTMPGetKeyParameter("DisableOLBC", tmpbuf, 10, buffer)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case 1: //disable OLBC Detection + pAd->CommonCfg.DisableOLBCDetect = 1; + break; + case 0: //enable OLBC Detection + pAd->CommonCfg.DisableOLBCDetect = 0; + break; + default: + pAd->CommonCfg.DisableOLBCDetect= 0; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("OLBCDetection=%ld\n", pAd->CommonCfg.DisableOLBCDetect)); + } + //TxPreamble + if(RTMPGetKeyParameter("TxPreamble", tmpbuf, 10, buffer)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case Rt802_11PreambleShort: + pAd->CommonCfg.TxPreamble = Rt802_11PreambleShort; + break; + case Rt802_11PreambleLong: + default: + pAd->CommonCfg.TxPreamble = Rt802_11PreambleLong; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxPreamble=%ld\n", pAd->CommonCfg.TxPreamble)); + } + //RTSThreshold + if(RTMPGetKeyParameter("RTSThreshold", tmpbuf, 10, buffer)) + { + RtsThresh = simple_strtol(tmpbuf, 0, 10); + if( (RtsThresh >= 1) && (RtsThresh <= MAX_RTS_THRESHOLD) ) + pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh; + else + pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD; + + DBGPRINT(RT_DEBUG_TRACE, ("RTSThreshold=%d\n", pAd->CommonCfg.RtsThreshold)); + } + //FragThreshold + if(RTMPGetKeyParameter("FragThreshold", tmpbuf, 10, buffer)) + { + FragThresh = simple_strtol(tmpbuf, 0, 10); + pAd->CommonCfg.bUseZeroToDisableFragment = FALSE; + + if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) + { //illegal FragThresh so we set it to default + pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + pAd->CommonCfg.bUseZeroToDisableFragment = TRUE; + } + else if (FragThresh % 2 == 1) + { + // The length of each fragment shall always be an even number of octets, except for the last fragment + // of an MSDU or MMPDU, which may be either an even or an odd number of octets. + pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1); + } + else + { + pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + } + //pAd->CommonCfg.AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; + DBGPRINT(RT_DEBUG_TRACE, ("FragThreshold=%d\n", pAd->CommonCfg.FragmentThreshold)); + } + //TxBurst + if(RTMPGetKeyParameter("TxBurst", tmpbuf, 10, buffer)) + { +//#ifdef WIFI_TEST +// pAd->CommonCfg.bEnableTxBurst = FALSE; +//#else + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->CommonCfg.bEnableTxBurst = TRUE; + else //Disable + pAd->CommonCfg.bEnableTxBurst = FALSE; +//#endif + DBGPRINT(RT_DEBUG_TRACE, ("TxBurst=%d\n", pAd->CommonCfg.bEnableTxBurst)); + } + +#ifdef AGGREGATION_SUPPORT + //PktAggregate + if(RTMPGetKeyParameter("PktAggregate", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->CommonCfg.bAggregationCapable = TRUE; + else //Disable + pAd->CommonCfg.bAggregationCapable = FALSE; +#ifdef PIGGYBACK_SUPPORT + pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable; +#endif // PIGGYBACK_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("PktAggregate=%d\n", pAd->CommonCfg.bAggregationCapable)); + } +#else + pAd->CommonCfg.bAggregationCapable = FALSE; + pAd->CommonCfg.bPiggyBackCapable = FALSE; +#endif // AGGREGATION_SUPPORT // + + // WmmCapable + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + rtmp_read_sta_wmm_parms_from_file(pAd, tmpbuf, buffer); +#endif // CONFIG_STA_SUPPORT // + + //ShortSlot + if(RTMPGetKeyParameter("ShortSlot", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable + pAd->CommonCfg.bUseShortSlotTime = TRUE; + else //Disable + pAd->CommonCfg.bUseShortSlotTime = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("ShortSlot=%d\n", pAd->CommonCfg.bUseShortSlotTime)); + } + //IEEE80211H + if(RTMPGetKeyParameter("IEEE80211H", tmpbuf, 10, buffer)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if(simple_strtol(macptr, 0, 10) != 0) //Enable + pAd->CommonCfg.bIEEE80211H = TRUE; + else //Disable + pAd->CommonCfg.bIEEE80211H = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IEEE80211H=%d\n", pAd->CommonCfg.bIEEE80211H)); + } + } + //CSPeriod + if(RTMPGetKeyParameter("CSPeriod", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->CommonCfg.RadarDetect.CSPeriod = simple_strtol(tmpbuf, 0, 10); + else + pAd->CommonCfg.RadarDetect.CSPeriod = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("CSPeriod=%d\n", pAd->CommonCfg.RadarDetect.CSPeriod)); + } + + //RDRegion + if(RTMPGetKeyParameter("RDRegion", tmpbuf, 128, buffer)) + { + if ((strncmp(tmpbuf, "JAP_W53", 7) == 0) || (strncmp(tmpbuf, "jap_w53", 7) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W53; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 15; + } + else if ((strncmp(tmpbuf, "JAP_W56", 7) == 0) || (strncmp(tmpbuf, "jap_w56", 7) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W56; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; + } + else if ((strncmp(tmpbuf, "JAP", 3) == 0) || (strncmp(tmpbuf, "jap", 3) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = JAP; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 5; + } + else if ((strncmp(tmpbuf, "FCC", 3) == 0) || (strncmp(tmpbuf, "fcc", 3) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = FCC; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 5; + } + else if ((strncmp(tmpbuf, "CE", 2) == 0) || (strncmp(tmpbuf, "ce", 2) == 0)) + { + pAd->CommonCfg.RadarDetect.RDDurRegion = CE; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; + } + else + { + pAd->CommonCfg.RadarDetect.RDDurRegion = CE; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; + } + + DBGPRINT(RT_DEBUG_TRACE, ("RDRegion=%d\n", pAd->CommonCfg.RadarDetect.RDDurRegion)); + } + else + { + pAd->CommonCfg.RadarDetect.RDDurRegion = CE; + pAd->CommonCfg.RadarDetect.DfsSessionTime = 13; + } + + //WirelessEvent + if(RTMPGetKeyParameter("WirelessEvent", tmpbuf, 10, buffer)) + { +#if WIRELESS_EXT >= 15 + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->CommonCfg.bWirelessEvent = simple_strtol(tmpbuf, 0, 10); + else + pAd->CommonCfg.bWirelessEvent = 0; // disable +#else + pAd->CommonCfg.bWirelessEvent = 0; // disable +#endif + DBGPRINT(RT_DEBUG_TRACE, ("WirelessEvent=%d\n", pAd->CommonCfg.bWirelessEvent)); + } + if(RTMPGetKeyParameter("WiFiTest", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->CommonCfg.bWiFiTest= simple_strtol(tmpbuf, 0, 10); + else + pAd->CommonCfg.bWiFiTest = 0; // disable + + DBGPRINT(RT_DEBUG_TRACE, ("WiFiTest=%d\n", pAd->CommonCfg.bWiFiTest)); + } + //AuthMode + if(RTMPGetKeyParameter("AuthMode", tmpbuf, 128, buffer)) + { +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((strcmp(tmpbuf, "WEPAUTO") == 0) || (strcmp(tmpbuf, "wepauto") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(tmpbuf, "SHARED") == 0) || (strcmp(tmpbuf, "shared") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(tmpbuf, "WPAPSK") == 0) || (strcmp(tmpbuf, "wpapsk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(tmpbuf, "WPANONE") == 0) || (strcmp(tmpbuf, "wpanone") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + else if ((strcmp(tmpbuf, "WPA2PSK") == 0) || (strcmp(tmpbuf, "wpa2psk") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if ((strcmp(tmpbuf, "WPA") == 0) || (strcmp(tmpbuf, "wpa") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(tmpbuf, "WPA2") == 0) || (strcmp(tmpbuf, "wpa2") == 0)) + pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#endif // WPA_SUPPLICANT_SUPPORT // + else + pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, pAd->StaCfg.WepStatus)); + } +#endif // CONFIG_STA_SUPPORT // + } + //EncrypType + if(RTMPGetKeyParameter("EncrypType", tmpbuf, 128, buffer)) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if ((strcmp(tmpbuf, "WEP") == 0) || (strcmp(tmpbuf, "wep") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled; + else if ((strcmp(tmpbuf, "TKIP") == 0) || (strcmp(tmpbuf, "tkip") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + else if ((strcmp(tmpbuf, "AES") == 0) || (strcmp(tmpbuf, "aes") == 0)) + pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + else + pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled; + + // Update all wepstatus related + pAd->StaCfg.PairCipher = pAd->StaCfg.WepStatus; + pAd->StaCfg.GroupCipher = pAd->StaCfg.WepStatus; + pAd->StaCfg.OrigWepStatus = pAd->StaCfg.WepStatus; + pAd->StaCfg.bMixCipher = FALSE; + + //RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); + DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __FUNCTION__, pAd->StaCfg.WepStatus)); + } +#endif // CONFIG_STA_SUPPORT // + } + + + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(RTMPGetCriticalParameter("WPAPSK", tmpbuf, 512, buffer)) + { + int err=0; + + tmpbuf[strlen(tmpbuf)] = '\0'; // make STA can process .$^& for WPAPSK input + + if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && + (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) + ) + { + err = 1; + } + else if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) < 64)) + { + PasswordHash((char *)tmpbuf, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, keyMaterial); + NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32); + + } + else if (strlen(tmpbuf) == 64) + { + AtoH(tmpbuf, keyMaterial, 32); + NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32); + } + else + { + err = 1; + DBGPRINT(RT_DEBUG_ERROR, ("%s::(WPAPSK key-string required 8 ~ 64 characters!)\n", __FUNCTION__)); + } + + if (err == 0) + { + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + // Start STA supplicant state machine + pAd->StaCfg.WpaState = SS_START; + } + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + /* + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TKIP_EK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_TXMICK); + + // Decide its ChiperAlg + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; + */ + pAd->StaCfg.WpaState = SS_NOTUSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(WPAPSK=%s)\n", __FUNCTION__, tmpbuf)); + } + } + } +#endif // CONFIG_STA_SUPPORT // + + //DefaultKeyID, KeyType, KeyStr + rtmp_read_key_parms_from_file(pAd, tmpbuf, buffer); + + + //HSCounter + /*if(RTMPGetKeyParameter("HSCounter", tmpbuf, 10, buffer)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case 1: //Enable + pAd->CommonCfg.bEnableHSCounter = TRUE; + break; + case 0: //Disable + default: + pAd->CommonCfg.bEnableHSCounter = FALSE; + break; + } + DBGPRINT(RT_DEBUG_TRACE, "HSCounter=%d\n", pAd->CommonCfg.bEnableHSCounter); + }*/ + +#ifdef DOT11_N_SUPPORT + HTParametersHook(pAd, tmpbuf, buffer); +#endif // DOT11_N_SUPPORT // + + +#ifdef CARRIER_DETECTION_SUPPORT + //CarrierDetect + if(RTMPGetKeyParameter("CarrierDetect", tmpbuf, 128, buffer)) + { + if ((strncmp(tmpbuf, "0", 1) == 0)) + pAd->CommonCfg.CarrierDetect.Enable = FALSE; + else if ((strncmp(tmpbuf, "1", 1) == 0)) + pAd->CommonCfg.CarrierDetect.Enable = TRUE; + else + pAd->CommonCfg.CarrierDetect.Enable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetect.Enable=%d\n", pAd->CommonCfg.CarrierDetect.Enable)); + } + else + pAd->CommonCfg.CarrierDetect.Enable = FALSE; +#endif // CARRIER_DETECTION_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + //PSMode + if (RTMPGetKeyParameter("PSMode", tmpbuf, 10, buffer)) + { + if (pAd->StaCfg.BssType == BSS_INFRA) + { + if ((strcmp(tmpbuf, "MAX_PSP") == 0) || (strcmp(tmpbuf, "max_psp") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + // MlmeSetPsm(pAd, PWR_SAVE); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP; + pAd->StaCfg.DefaultListenCount = 5; + } + else if ((strcmp(tmpbuf, "Fast_PSP") == 0) || (strcmp(tmpbuf, "fast_psp") == 0) + || (strcmp(tmpbuf, "FAST_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + // MlmeSetPsmBit(pAd, PWR_SAVE); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP; + pAd->StaCfg.DefaultListenCount = 3; + } + else if ((strcmp(tmpbuf, "Legacy_PSP") == 0) || (strcmp(tmpbuf, "legacy_psp") == 0) + || (strcmp(tmpbuf, "LEGACY_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + // MlmeSetPsmBit(pAd, PWR_SAVE); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAd->StaCfg.DefaultListenCount = 3; + } + else + { //Default Ndis802_11PowerModeCAM + // clear PSM bit immediately + MlmeSetPsmBit(pAd, PWR_ACTIVE); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + if (pAd->StaCfg.bWindowsACCAMEnable == FALSE) + pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; + pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; + } + DBGPRINT(RT_DEBUG_TRACE, ("PSMode=%ld\n", pAd->StaCfg.WindowsPowerMode)); + } + } + // FastRoaming + if (RTMPGetKeyParameter("FastRoaming", tmpbuf, 32, buffer)) + { + if (simple_strtol(tmpbuf, 0, 10) == 0) + pAd->StaCfg.bFastRoaming = FALSE; + else + pAd->StaCfg.bFastRoaming = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("FastRoaming=%d\n", pAd->StaCfg.bFastRoaming)); + } + // RoamThreshold + if (RTMPGetKeyParameter("RoamThreshold", tmpbuf, 32, buffer)) + { + long lInfo = simple_strtol(tmpbuf, 0, 10); + + if (lInfo > 90 || lInfo < 60) + pAd->StaCfg.dBmToRoam = -70; + else + pAd->StaCfg.dBmToRoam = (CHAR)(-1)*lInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("RoamThreshold=%d dBm\n", pAd->StaCfg.dBmToRoam)); + } + + if(RTMPGetKeyParameter("TGnWifiTest", tmpbuf, 10, buffer)) + { + if(simple_strtol(tmpbuf, 0, 10) == 0) + pAd->StaCfg.bTGnWifiTest = FALSE; + else + pAd->StaCfg.bTGnWifiTest = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("TGnWifiTest=%d\n", pAd->StaCfg.bTGnWifiTest)); + } + } +#endif // CONFIG_STA_SUPPORT // + + +#ifdef RT30xx +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if(RTMPGetKeyParameter("AntDiversity", tmpbuf, 10, buffer)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if(simple_strtol(macptr, 0, 10) != 0) //Enable + pAd->CommonCfg.bRxAntDiversity = TRUE; + else //Disable + pAd->CommonCfg.bRxAntDiversity = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("AntDiversity=%d\n", pAd->CommonCfg.bRxAntDiversity)); + } + } + } +#endif // CONFIG_STA_SUPPORT // +#endif // RT30xx // + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("--> %s does not have a write method\n", src)); + } + + retval=filp_close(srcf,NULL); + + if (retval) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); + } + } + } + + set_fs(orgfs); +#if 0 + current->fsuid = orgfsuid; + current->fsgid = orgfsgid; +#endif + + kfree(buffer); + kfree(tmpbuf); + + return (NDIS_STATUS_SUCCESS); +} + +#ifdef DOT11_N_SUPPORT +static void HTParametersHook( + IN PRTMP_ADAPTER pAd, + IN CHAR *pValueStr, + IN CHAR *pInput) +{ + + INT Value; + + if (RTMPGetKeyParameter("HT_PROTECT", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bHTProtect = FALSE; + } + else + { + pAd->CommonCfg.bHTProtect = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Protection = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + if (RTMPGetKeyParameter("HT_MIMOPSEnable", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bMIMOPSEnable = FALSE; + } + else + { + pAd->CommonCfg.bMIMOPSEnable = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPSEnable = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + if (RTMPGetKeyParameter("HT_MIMOPSMode", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value > MMPS_ENABLE) + { + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; + } + else + { + //TODO: add mimo power saving mechanism + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE; + //pAd->CommonCfg.BACapability.field.MMPSmode = Value; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPS Mode = %d\n", Value)); + } + + if (RTMPGetKeyParameter("HT_BADecline", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bBADecline = FALSE; + } + else + { + pAd->CommonCfg.bBADecline = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Decline = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + if (RTMPGetKeyParameter("HT_DisableReordering", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bDisableReordering = FALSE; + } + else + { + pAd->CommonCfg.bDisableReordering = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: DisableReordering = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + if (RTMPGetKeyParameter("HT_AutoBA", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; + } + else + { + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; + } + pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; + pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy; + DBGPRINT(RT_DEBUG_TRACE, ("HT: Auto BA = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + // Tx_+HTC frame + if (RTMPGetKeyParameter("HT_HTC", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->HTCEnable = FALSE; + } + else + { + pAd->HTCEnable = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx +HTC frame = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + // Enable HT Link Adaptation Control + if (RTMPGetKeyParameter("HT_LinkAdapt", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->bLinkAdapt = FALSE; + } + else + { + pAd->HTCEnable = TRUE; + pAd->bLinkAdapt = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Link Adaptation Control = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); + } + + // Reverse Direction Mechanism + if (RTMPGetKeyParameter("HT_RDG", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bRdg = FALSE; + } + else + { + pAd->HTCEnable = TRUE; + pAd->CommonCfg.bRdg = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: RDG = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); + } + + + + + // Tx A-MSUD ? + if (RTMPGetKeyParameter("HT_AMSDU", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE; + } + else + { + pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + // MPDU Density + if (RTMPGetKeyParameter("HT_MpduDensity", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value <=7 && Value >= 0) + { + pAd->CommonCfg.BACapability.field.MpduDensity = Value; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d\n", Value)); + } + else + { + pAd->CommonCfg.BACapability.field.MpduDensity = 4; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d (Default)\n", 4)); + } + } + + // Max Rx BA Window Size + if (RTMPGetKeyParameter("HT_BAWinSize", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value >=1 && Value <= 64) + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value; + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", Value)); + } + else + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = 64 (Defualt)\n")); + } + + } + + // Guard Interval + if (RTMPGetKeyParameter("HT_GI", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == GI_400) + { + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Guard Interval = %s\n", (Value==GI_400) ? "400" : "800" )); + } + + // HT Operation Mode : Mixed Mode , Green Field + if (RTMPGetKeyParameter("HT_OpMode", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == HTMODE_GF) + { + + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Operate Mode = %s\n", (Value==HTMODE_GF) ? "Green Field" : "Mixed Mode" )); + } + + // Fixed Tx mode : CCK, OFDM + if (RTMPGetKeyParameter("FixedTxMode", pValueStr, 25, pInput)) + { + UCHAR fix_tx_mode; + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + fix_tx_mode = FIXED_TXMODE_HT; + + if (strcmp(pValueStr, "OFDM") == 0 || strcmp(pValueStr, "ofdm") == 0) + { + fix_tx_mode = FIXED_TXMODE_OFDM; + } + else if (strcmp(pValueStr, "CCK") == 0 || strcmp(pValueStr, "cck") == 0) + { + fix_tx_mode = FIXED_TXMODE_CCK; + } + else if (strcmp(pValueStr, "HT") == 0 || strcmp(pValueStr, "ht") == 0) + { + fix_tx_mode = FIXED_TXMODE_HT; + } + else + { + Value = simple_strtol(pValueStr, 0, 10); + // 1 : CCK + // 2 : OFDM + // otherwise : HT + if (Value == FIXED_TXMODE_CCK || Value == FIXED_TXMODE_OFDM) + fix_tx_mode = Value; + else + fix_tx_mode = FIXED_TXMODE_HT; + } + + pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; + DBGPRINT(RT_DEBUG_TRACE, ("Fixed Tx Mode = %d\n", fix_tx_mode)); + + } +#endif // CONFIG_STA_SUPPORT // + } + + + // Channel Width + if (RTMPGetKeyParameter("HT_BW", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == BW_40) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } + +#ifdef MCAST_RATE_SPECIFIC + pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW; +#endif // MCAST_RATE_SPECIFIC // + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Channel Width = %s\n", (Value==BW_40) ? "40 MHz" : "20 MHz" )); + } + + if (RTMPGetKeyParameter("HT_EXTCHA", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + { + + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", (Value==0) ? "BELOW" : "ABOVE" )); + } + + // MSC + if (RTMPGetKeyParameter("HT_MCS", pValueStr, 50, pInput)) + { + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + Value = simple_strtol(pValueStr, 0, 10); + +// if ((Value >= 0 && Value <= 15) || (Value == 32)) + if ((Value >= 0 && Value <= 23) || (Value == 32)) // 3*3 + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = Value; + pAd->StaCfg.bAutoTxRateSwitch = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = %d\n", pAd->StaCfg.DesiredTransmitSetting.field.MCS)); + } + else + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + pAd->StaCfg.bAutoTxRateSwitch = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = AUTO\n")); + } + } +#endif // CONFIG_STA_SUPPORT // + } + + // STBC + if (RTMPGetKeyParameter("HT_STBC", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == STBC_USE) + { + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: STBC = %d\n", pAd->CommonCfg.RegTransmitSetting.field.STBC)); + } + + // 40_Mhz_Intolerant + if (RTMPGetKeyParameter("HT_40MHZ_INTOLERANT", pValueStr, 25, pInput)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bForty_Mhz_Intolerant = FALSE; + } + else + { + pAd->CommonCfg.bForty_Mhz_Intolerant = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: 40MHZ INTOLERANT = %d\n", pAd->CommonCfg.bForty_Mhz_Intolerant)); + } + //HT_TxStream + if(RTMPGetKeyParameter("HT_TxStream", pValueStr, 10, pInput)) + { + switch (simple_strtol(pValueStr, 0, 10)) + { + case 1: + pAd->CommonCfg.TxStream = 1; + break; + case 2: + pAd->CommonCfg.TxStream = 2; + break; + case 3: // 3*3 + default: + pAd->CommonCfg.TxStream = 3; + + if (pAd->MACVersion < RALINK_2883_VERSION) + pAd->CommonCfg.TxStream = 2; // only 2 tx streams for RT2860 series + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx Stream = %d\n", pAd->CommonCfg.TxStream)); + } + //HT_RxStream + if(RTMPGetKeyParameter("HT_RxStream", pValueStr, 10, pInput)) + { + switch (simple_strtol(pValueStr, 0, 10)) + { + case 1: + pAd->CommonCfg.RxStream = 1; + break; + case 2: + pAd->CommonCfg.RxStream = 2; + break; + case 3: + default: + pAd->CommonCfg.RxStream = 3; + + if (pAd->MACVersion < RALINK_2883_VERSION) + pAd->CommonCfg.RxStream = 2; // only 2 rx streams for RT2860 series + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Rx Stream = %d\n", pAd->CommonCfg.RxStream)); + } + +} +#endif // DOT11_N_SUPPORT // + diff --git a/drivers/staging/rt3070/rtmp.h b/drivers/staging/rt3070/rtmp.h new file mode 100644 index 000000000000..d80d74ffbc89 --- /dev/null +++ b/drivers/staging/rt3070/rtmp.h @@ -0,0 +1,7728 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtmp.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 2002-08-01 created + James Tan 2002-09-06 modified (Revise NTCRegTable) + John Chang 2004-09-06 modified for RT2600 +*/ +#ifndef __RTMP_H__ +#define __RTMP_H__ + +#include "link_list.h" +#include "spectrum_def.h" + +#ifdef MLME_EX +#include "mlme_ex_def.h" +#endif // MLME_EX // + +#ifdef CONFIG_STA_SUPPORT +#include "aironet.h" +#endif // CONFIG_STA_SUPPORT // + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + +#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) +#define WSC_INCLUDED +#endif + + + + + +//#define DBG 1 + +//#define DBG_DIAGNOSE 1 + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) +#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) if(_pAd->OpMode == OPMODE_AP) +#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) if(_pAd->OpMode == OPMODE_STA) +#else +#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) +#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) +#endif + +#define VIRTUAL_IF_INC(__pAd) ((__pAd)->VirtualIfCnt++) +#define VIRTUAL_IF_DEC(__pAd) ((__pAd)->VirtualIfCnt--) +#define VIRTUAL_IF_NUM(__pAd) ((__pAd)->VirtualIfCnt) + +#ifdef RT2870 +//////////////////////////////////////////////////////////////////////////// +// The TX_BUFFER structure forms the transmitted USB packet to the device +//////////////////////////////////////////////////////////////////////////// +typedef struct __TX_BUFFER{ + union { + UCHAR WirelessPacket[TX_BUFFER_NORMSIZE]; + HEADER_802_11 NullFrame; + PSPOLL_FRAME PsPollPacket; + RTS_FRAME RTSFrame; + }field; + UCHAR Aggregation[4]; //Buffer for save Aggregation size. +} TX_BUFFER, *PTX_BUFFER; + +typedef struct __HTTX_BUFFER{ + union { + UCHAR WirelessPacket[MAX_TXBULK_SIZE]; + HEADER_802_11 NullFrame; + PSPOLL_FRAME PsPollPacket; + RTS_FRAME RTSFrame; + }field; + UCHAR Aggregation[4]; //Buffer for save Aggregation size. +} HTTX_BUFFER, *PHTTX_BUFFER; + + +// used to track driver-generated write irps +typedef struct _TX_CONTEXT +{ + PVOID pAd; //Initialized in MiniportInitialize + PURB pUrb; //Initialized in MiniportInitialize + PIRP pIrp; //used to cancel pending bulk out. + //Initialized in MiniportInitialize + PTX_BUFFER TransferBuffer; //Initialized in MiniportInitialize + ULONG BulkOutSize; + UCHAR BulkOutPipeId; + UCHAR SelfIdx; + BOOLEAN InUse; + BOOLEAN bWaitingBulkOut; // at least one packet is in this TxContext, ready for making IRP anytime. + BOOLEAN bFullForBulkOut; // all tx buffer are full , so waiting for tx bulkout. + BOOLEAN IRPPending; + BOOLEAN LastOne; + BOOLEAN bAggregatible; + UCHAR Header_802_3[LENGTH_802_3]; + UCHAR Rsv[2]; + ULONG DataOffset; + UINT TxRate; + dma_addr_t data_dma; // urb dma on linux + +} TX_CONTEXT, *PTX_CONTEXT, **PPTX_CONTEXT; + + +// used to track driver-generated write irps +typedef struct _HT_TX_CONTEXT +{ + PVOID pAd; //Initialized in MiniportInitialize + PURB pUrb; //Initialized in MiniportInitialize + PIRP pIrp; //used to cancel pending bulk out. + //Initialized in MiniportInitialize + PHTTX_BUFFER TransferBuffer; //Initialized in MiniportInitialize + ULONG BulkOutSize; // Indicate the total bulk-out size in bytes in one bulk-transmission + UCHAR BulkOutPipeId; + BOOLEAN IRPPending; + BOOLEAN LastOne; + BOOLEAN bCurWriting; + BOOLEAN bRingEmpty; + BOOLEAN bCopySavePad; + UCHAR SavedPad[8]; + UCHAR Header_802_3[LENGTH_802_3]; + ULONG CurWritePosition; // Indicate the buffer offset which packet will be inserted start from. + ULONG CurWriteRealPos; // Indicate the buffer offset which packet now are writing to. + ULONG NextBulkOutPosition; // Indicate the buffer start offset of a bulk-transmission + ULONG ENextBulkOutPosition; // Indicate the buffer end offset of a bulk-transmission + UINT TxRate; + dma_addr_t data_dma; // urb dma on linux +} HT_TX_CONTEXT, *PHT_TX_CONTEXT, **PPHT_TX_CONTEXT; + + +// +// Structure to keep track of receive packets and buffers to indicate +// receive data to the protocol. +// +typedef struct _RX_CONTEXT +{ + PUCHAR TransferBuffer; + PVOID pAd; + PIRP pIrp;//used to cancel pending bulk in. + PURB pUrb; + //These 2 Boolean shouldn't both be 1 at the same time. + ULONG BulkInOffset; // number of packets waiting for reordering . +// BOOLEAN ReorderInUse; // At least one packet in this buffer are in reordering buffer and wait for receive indication + BOOLEAN bRxHandling; // Notify this packet is being process now. + BOOLEAN InUse; // USB Hardware Occupied. Wait for USB HW to put packet. + BOOLEAN Readable; // Receive Complete back. OK for driver to indicate receiving packet. + BOOLEAN IRPPending; // TODO: To be removed + atomic_t IrpLock; + NDIS_SPIN_LOCK RxContextLock; + dma_addr_t data_dma; // urb dma on linux +} RX_CONTEXT, *PRX_CONTEXT; +#endif // RT2870 // + + +// +// NDIS Version definitions +// +#ifdef NDIS50_MINIPORT +#define RTMP_NDIS_MAJOR_VERSION 5 +#define RTMP_NDIS_MINOR_VERSION 0 +#endif + +#ifdef NDIS51_MINIPORT +#define RTMP_NDIS_MAJOR_VERSION 5 +#define RTMP_NDIS_MINOR_VERSION 1 +#endif + +extern char NIC_VENDOR_DESC[]; +extern int NIC_VENDOR_DESC_LEN; + +extern unsigned char SNAP_AIRONET[]; +extern unsigned char CipherSuiteCiscoCCKM[]; +extern unsigned char CipherSuiteCiscoCCKMLen; +extern unsigned char CipherSuiteCiscoCCKM24[]; +extern unsigned char CipherSuiteCiscoCCKM24Len; +extern unsigned char CipherSuiteCCXTkip[]; +extern unsigned char CipherSuiteCCXTkipLen; +extern unsigned char CISCO_OUI[]; +extern UCHAR BaSizeArray[4]; + +extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; +extern UCHAR MULTICAST_ADDR[MAC_ADDR_LEN]; +extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; +extern ULONG BIT32[32]; +extern UCHAR BIT8[8]; +extern char* CipherName[]; +extern char* MCSToMbps[]; +extern UCHAR RxwiMCSToOfdmRate[12]; +extern UCHAR SNAP_802_1H[6]; +extern UCHAR SNAP_BRIDGE_TUNNEL[6]; +extern UCHAR SNAP_AIRONET[8]; +extern UCHAR CKIP_LLC_SNAP[8]; +extern UCHAR EAPOL_LLC_SNAP[8]; +extern UCHAR EAPOL[2]; +extern UCHAR IPX[2]; +extern UCHAR APPLE_TALK[2]; +extern UCHAR RateIdToPlcpSignal[12]; // see IEEE802.11a-1999 p.14 +extern UCHAR OfdmRateToRxwiMCS[]; +extern UCHAR OfdmSignalToRateId[16] ; +extern UCHAR default_cwmin[4]; +extern UCHAR default_cwmax[4]; +extern UCHAR default_sta_aifsn[4]; +extern UCHAR MapUserPriorityToAccessCategory[8]; + +extern USHORT RateUpPER[]; +extern USHORT RateDownPER[]; +extern UCHAR Phy11BNextRateDownward[]; +extern UCHAR Phy11BNextRateUpward[]; +extern UCHAR Phy11BGNextRateDownward[]; +extern UCHAR Phy11BGNextRateUpward[]; +extern UCHAR Phy11ANextRateDownward[]; +extern UCHAR Phy11ANextRateUpward[]; +extern CHAR RssiSafeLevelForTxRate[]; +extern UCHAR RateIdToMbps[]; +extern USHORT RateIdTo500Kbps[]; + +extern UCHAR CipherSuiteWpaNoneTkip[]; +extern UCHAR CipherSuiteWpaNoneTkipLen; + +extern UCHAR CipherSuiteWpaNoneAes[]; +extern UCHAR CipherSuiteWpaNoneAesLen; + +extern UCHAR SsidIe; +extern UCHAR SupRateIe; +extern UCHAR ExtRateIe; + +#ifdef DOT11_N_SUPPORT +extern UCHAR HtCapIe; +extern UCHAR AddHtInfoIe; +extern UCHAR NewExtChanIe; +#ifdef DOT11N_DRAFT3 +extern UCHAR ExtHtCapIe; +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +extern UCHAR ErpIe; +extern UCHAR DsIe; +extern UCHAR TimIe; +extern UCHAR WpaIe; +extern UCHAR Wpa2Ie; +extern UCHAR IbssIe; +extern UCHAR Ccx2Ie; +extern UCHAR WapiIe; + +extern UCHAR WPA_OUI[]; +extern UCHAR RSN_OUI[]; +extern UCHAR WAPI_OUI[]; +extern UCHAR WME_INFO_ELEM[]; +extern UCHAR WME_PARM_ELEM[]; +extern UCHAR Ccx2QosInfo[]; +extern UCHAR Ccx2IeInfo[]; +extern UCHAR RALINK_OUI[]; +extern UCHAR PowerConstraintIE[]; + + +extern UCHAR RateSwitchTable[]; +extern UCHAR RateSwitchTable11B[]; +extern UCHAR RateSwitchTable11G[]; +extern UCHAR RateSwitchTable11BG[]; + +#ifdef DOT11_N_SUPPORT +extern UCHAR RateSwitchTable11BGN1S[]; +extern UCHAR RateSwitchTable11BGN2S[]; +extern UCHAR RateSwitchTable11BGN2SForABand[]; +extern UCHAR RateSwitchTable11N1S[]; +extern UCHAR RateSwitchTable11N2S[]; +extern UCHAR RateSwitchTable11N2SForABand[]; + +#ifdef CONFIG_STA_SUPPORT +extern UCHAR PRE_N_HT_OUI[]; +#endif // CONFIG_STA_SUPPORT // +#endif // DOT11_N_SUPPORT // + +#define MAXSEQ (0xFFF) + +#ifdef RALINK_ATE +typedef struct _ATE_INFO { + UCHAR Mode; + CHAR TxPower0; + CHAR TxPower1; + CHAR TxAntennaSel; + CHAR RxAntennaSel; + TXWI_STRUC TxWI; // TXWI + USHORT QID; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; + UCHAR Channel; + UINT32 TxLength; + UINT32 TxCount; + UINT32 TxDoneCount; // Tx DMA Done + UINT32 RFFreqOffset; + BOOLEAN bRxFer; + BOOLEAN bQATxStart; // Have compiled QA in and use it to ATE tx. + BOOLEAN bQARxStart; // Have compiled QA in and use it to ATE rx. + UINT32 RxTotalCnt; + UINT32 RxCntPerSec; + + CHAR LastSNR0; // last received SNR + CHAR LastSNR1; // last received SNR for 2nd antenna + CHAR LastRssi0; // last received RSSI + CHAR LastRssi1; // last received RSSI for 2nd antenna + CHAR LastRssi2; // last received RSSI for 3rd antenna + CHAR AvgRssi0; // last 8 frames' average RSSI + CHAR AvgRssi1; // last 8 frames' average RSSI + CHAR AvgRssi2; // last 8 frames' average RSSI + SHORT AvgRssi0X8; // sum of last 8 frames' RSSI + SHORT AvgRssi1X8; // sum of last 8 frames' RSSI + SHORT AvgRssi2X8; // sum of last 8 frames' RSSI + + UINT32 NumOfAvgRssiSample; + +#ifdef RALINK_28xx_QA + // Tx frame +#ifdef RT2870 + /* not used in RT2860 */ + TXINFO_STRUC TxInfo; // TxInfo +#endif // RT2870 // + USHORT HLen; // Header Length + USHORT PLen; // Pattern Length + UCHAR Header[32]; // Header buffer + UCHAR Pattern[32]; // Pattern buffer + USHORT DLen; // Data Length + USHORT seq; + UINT32 CID; + pid_t AtePid; + // counters + UINT32 U2M; + UINT32 OtherData; + UINT32 Beacon; + UINT32 OtherCount; + UINT32 TxAc0; + UINT32 TxAc1; + UINT32 TxAc2; + UINT32 TxAc3; + UINT32 TxHCCA; + UINT32 TxMgmt; + UINT32 RSSI0; + UINT32 RSSI1; + UINT32 RSSI2; + UINT32 SNR0; + UINT32 SNR1; + // control + //UINT32 Repeat; // Tx Cpu count + UCHAR TxStatus; // task Tx status // 0 --> task is idle, 1 --> task is running +#endif // RALINK_28xx_QA // +} ATE_INFO, *PATE_INFO; + +#ifdef RALINK_28xx_QA +struct ate_racfghdr { + UINT32 magic_no; + USHORT command_type; + USHORT command_id; + USHORT length; + USHORT sequence; + USHORT status; + UCHAR data[2046]; +} __attribute__((packed)); +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +#ifdef DOT11_N_SUPPORT +struct reordering_mpdu +{ + struct reordering_mpdu *next; + PNDIS_PACKET pPacket; /* coverted to 802.3 frame */ + int Sequence; /* sequence number of MPDU */ + BOOLEAN bAMSDU; +}; + +struct reordering_list +{ + struct reordering_mpdu *next; + int qlen; +}; + +struct reordering_mpdu_pool +{ + PVOID mem; + NDIS_SPIN_LOCK lock; + struct reordering_list freelist; +}; +#endif // DOT11_N_SUPPORT // + +typedef struct _RSSI_SAMPLE { + CHAR LastRssi0; // last received RSSI + CHAR LastRssi1; // last received RSSI + CHAR LastRssi2; // last received RSSI + CHAR AvgRssi0; + CHAR AvgRssi1; + CHAR AvgRssi2; + SHORT AvgRssi0X8; + SHORT AvgRssi1X8; + SHORT AvgRssi2X8; +} RSSI_SAMPLE; + +// +// Queue structure and macros +// +typedef struct _QUEUE_ENTRY { + struct _QUEUE_ENTRY *Next; +} QUEUE_ENTRY, *PQUEUE_ENTRY; + +// Queue structure +typedef struct _QUEUE_HEADER { + PQUEUE_ENTRY Head; + PQUEUE_ENTRY Tail; + ULONG Number; +} QUEUE_HEADER, *PQUEUE_HEADER; + +#define InitializeQueueHeader(QueueHeader) \ +{ \ + (QueueHeader)->Head = (QueueHeader)->Tail = NULL; \ + (QueueHeader)->Number = 0; \ +} + +#define RemoveHeadQueue(QueueHeader) \ +(QueueHeader)->Head; \ +{ \ + PQUEUE_ENTRY pNext; \ + if ((QueueHeader)->Head != NULL) \ + { \ + pNext = (QueueHeader)->Head->Next; \ + (QueueHeader)->Head = pNext; \ + if (pNext == NULL) \ + (QueueHeader)->Tail = NULL; \ + (QueueHeader)->Number--; \ + } \ +} + +#define InsertHeadQueue(QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = (QueueHeader)->Head; \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + if ((QueueHeader)->Tail == NULL) \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + +#define InsertTailQueue(QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \ + if ((QueueHeader)->Tail) \ + (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \ + else \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + +// +// Macros for flag and ref count operations +// +#define RTMP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F)) +#define RTMP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F)) +#define RTMP_CLEAR_FLAGS(_M) ((_M)->Flags = 0) +#define RTMP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0) +#define RTMP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F)) + +#define OPSTATUS_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags |= (_F)) +#define OPSTATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags &= ~(_F)) +#define OPSTATUS_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.OpStatusFlags & (_F)) != 0) + +#define CLIENT_STATUS_SET_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags |= (_F)) +#define CLIENT_STATUS_CLEAR_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags &= ~(_F)) +#define CLIENT_STATUS_TEST_FLAG(_pEntry,_F) (((_pEntry)->ClientStatusFlags & (_F)) != 0) + +#define RX_FILTER_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter |= (_F)) +#define RX_FILTER_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter &= ~(_F)) +#define RX_FILTER_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.PacketFilter & (_F)) != 0) + +#ifdef CONFIG_STA_SUPPORT +#define STA_NO_SECURITY_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11EncryptionDisabled) +#define STA_WEP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) +#define STA_TKIP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) +#define STA_AES_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + +#define STA_TGN_WIFI_ON(_p) (_p->StaCfg.bTGnWifiTest == TRUE) +#endif // CONFIG_STA_SUPPORT // + +#define CKIP_KP_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x10) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) +#define CKIP_CMIC_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x08) && ((_p)->StaCfg.bCkipCmicOn == TRUE)) + + +#define INC_RING_INDEX(_idx, _RingSize) \ +{ \ + (_idx) = (_idx+1) % (_RingSize); \ +} + +// We will have a cost down version which mac version is 0x3090xxxx +#define IS_RT3090(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30710000) || (((_pAd)->MACVersion & 0xffff0000) == 0x30900000)) + +#define IS_RT3070(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30700000) +#define IS_RT3071(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30710000) +#define IS_RT2070(_pAd) (((_pAd)->RfIcType == RFIC_2020) || ((_pAd)->EFuseTag == 0x27)) + +#define IS_RT30xx(_pAd) (((_pAd)->MACVersion & 0xfff00000) == 0x30700000) + +#define RING_PACKET_INIT(_TxRing, _idx) \ +{ \ + _TxRing->Cell[_idx].pNdisPacket = NULL; \ + _TxRing->Cell[_idx].pNextNdisPacket = NULL; \ +} + +#define TXDT_INIT(_TxD) \ +{ \ + NdisZeroMemory(_TxD, TXD_SIZE); \ + _TxD->DMADONE = 1; \ +} + +//Set last data segment +#define RING_SET_LASTDS(_TxD, _IsSD0) \ +{ \ + if (_IsSD0) {_TxD->LastSec0 = 1;} \ + else {_TxD->LastSec1 = 1;} \ +} + +// Increase TxTsc value for next transmission +// TODO: +// When i==6, means TSC has done one full cycle, do re-keying stuff follow specs +// Should send a special event microsoft defined to request re-key +#define INC_TX_TSC(_tsc) \ +{ \ + int i=0; \ + while (++_tsc[i] == 0x0) \ + { \ + i++; \ + if (i == 6) \ + break; \ + } \ +} + +#ifdef DOT11_N_SUPPORT +// StaActive.SupportedHtPhy.MCSSet is copied from AP beacon. Don't need to update here. +#define COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ +{ \ + _pAd->StaActive.SupportedHtPhy.ChannelWidth = _pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth; \ + _pAd->StaActive.SupportedHtPhy.MimoPs = _pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs; \ + _pAd->StaActive.SupportedHtPhy.GF = _pAd->MlmeAux.HtCapability.HtCapInfo.GF; \ + _pAd->StaActive.SupportedHtPhy.ShortGIfor20 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20; \ + _pAd->StaActive.SupportedHtPhy.ShortGIfor40 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40; \ + _pAd->StaActive.SupportedHtPhy.TxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC; \ + _pAd->StaActive.SupportedHtPhy.RxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC; \ + _pAd->StaActive.SupportedHtPhy.ExtChanOffset = _pAd->MlmeAux.AddHtInfo.AddHtInfo.ExtChanOffset; \ + _pAd->StaActive.SupportedHtPhy.RecomWidth = _pAd->MlmeAux.AddHtInfo.AddHtInfo.RecomWidth; \ + _pAd->StaActive.SupportedHtPhy.OperaionMode = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode; \ + _pAd->StaActive.SupportedHtPhy.NonGfPresent = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent; \ + NdisMoveMemory((_pAd)->MacTab.Content[BSSID_WCID].HTCapability.MCSSet, (_pAd)->StaActive.SupportedPhyInfo.MCSSet, sizeof(UCHAR) * 16);\ +} + +#define COPY_AP_HTSETTINGS_FROM_BEACON(_pAd, _pHtCapability) \ +{ \ + _pAd->MacTab.Content[BSSID_WCID].AMsduSize = (UCHAR)(_pHtCapability->HtCapInfo.AMsduSize); \ + _pAd->MacTab.Content[BSSID_WCID].MmpsMode= (UCHAR)(_pHtCapability->HtCapInfo.MimoPs); \ + _pAd->MacTab.Content[BSSID_WCID].MaxRAmpduFactor = (UCHAR)(_pHtCapability->HtCapParm.MaxRAmpduFactor); \ +} +#endif // DOT11_N_SUPPORT // + +// +// MACRO for 32-bit PCI register read / write +// +// Usage : RTMP_IO_READ32( +// PRTMP_ADAPTER pAd, +// ULONG Register_Offset, +// PULONG pValue) +// +// RTMP_IO_WRITE32( +// PRTMP_ADAPTER pAd, +// ULONG Register_Offset, +// ULONG Value) +// + +// +// BBP & RF are using indirect access. Before write any value into it. +// We have to make sure there is no outstanding command pending via checking busy bit. +// +#define MAX_BUSY_COUNT 100 // Number of retry before failing access BBP & RF indirect register +// + +#ifdef RT2870 +#define RTMP_RF_IO_WRITE32(_A, _V) RTUSBWriteRFRegister(_A, _V) +#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) RTUSBReadBBPRegister(_A, _I, _pV) +#define RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTUSBWriteBBPRegister(_A, _I, _V) + +#define BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) RTUSBWriteBBPRegister(_A, _I, _V) +#define BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) RTUSBReadBBPRegister(_A, _I, _pV) +#endif // RT2870 // + +#ifdef RT30xx +#define RTMP_RF_IO_READ8_BY_REG_ID(_A, _I, _pV) RT30xxReadRFRegister(_A, _I, _pV) +#define RTMP_RF_IO_WRITE8_BY_REG_ID(_A, _I, _V) RT30xxWriteRFRegister(_A, _I, _V) +#endif // RT30xx // + +#define MAP_CHANNEL_ID_TO_KHZ(ch, khz) { \ + switch (ch) \ + { \ + case 1: khz = 2412000; break; \ + case 2: khz = 2417000; break; \ + case 3: khz = 2422000; break; \ + case 4: khz = 2427000; break; \ + case 5: khz = 2432000; break; \ + case 6: khz = 2437000; break; \ + case 7: khz = 2442000; break; \ + case 8: khz = 2447000; break; \ + case 9: khz = 2452000; break; \ + case 10: khz = 2457000; break; \ + case 11: khz = 2462000; break; \ + case 12: khz = 2467000; break; \ + case 13: khz = 2472000; break; \ + case 14: khz = 2484000; break; \ + case 36: /* UNII */ khz = 5180000; break; \ + case 40: /* UNII */ khz = 5200000; break; \ + case 44: /* UNII */ khz = 5220000; break; \ + case 48: /* UNII */ khz = 5240000; break; \ + case 52: /* UNII */ khz = 5260000; break; \ + case 56: /* UNII */ khz = 5280000; break; \ + case 60: /* UNII */ khz = 5300000; break; \ + case 64: /* UNII */ khz = 5320000; break; \ + case 149: /* UNII */ khz = 5745000; break; \ + case 153: /* UNII */ khz = 5765000; break; \ + case 157: /* UNII */ khz = 5785000; break; \ + case 161: /* UNII */ khz = 5805000; break; \ + case 165: /* UNII */ khz = 5825000; break; \ + case 100: /* HiperLAN2 */ khz = 5500000; break; \ + case 104: /* HiperLAN2 */ khz = 5520000; break; \ + case 108: /* HiperLAN2 */ khz = 5540000; break; \ + case 112: /* HiperLAN2 */ khz = 5560000; break; \ + case 116: /* HiperLAN2 */ khz = 5580000; break; \ + case 120: /* HiperLAN2 */ khz = 5600000; break; \ + case 124: /* HiperLAN2 */ khz = 5620000; break; \ + case 128: /* HiperLAN2 */ khz = 5640000; break; \ + case 132: /* HiperLAN2 */ khz = 5660000; break; \ + case 136: /* HiperLAN2 */ khz = 5680000; break; \ + case 140: /* HiperLAN2 */ khz = 5700000; break; \ + case 34: /* Japan MMAC */ khz = 5170000; break; \ + case 38: /* Japan MMAC */ khz = 5190000; break; \ + case 42: /* Japan MMAC */ khz = 5210000; break; \ + case 46: /* Japan MMAC */ khz = 5230000; break; \ + case 184: /* Japan */ khz = 4920000; break; \ + case 188: /* Japan */ khz = 4940000; break; \ + case 192: /* Japan */ khz = 4960000; break; \ + case 196: /* Japan */ khz = 4980000; break; \ + case 208: /* Japan, means J08 */ khz = 5040000; break; \ + case 212: /* Japan, means J12 */ khz = 5060000; break; \ + case 216: /* Japan, means J16 */ khz = 5080000; break; \ + default: khz = 2412000; break; \ + } \ + } + +#define MAP_KHZ_TO_CHANNEL_ID(khz, ch) { \ + switch (khz) \ + { \ + case 2412000: ch = 1; break; \ + case 2417000: ch = 2; break; \ + case 2422000: ch = 3; break; \ + case 2427000: ch = 4; break; \ + case 2432000: ch = 5; break; \ + case 2437000: ch = 6; break; \ + case 2442000: ch = 7; break; \ + case 2447000: ch = 8; break; \ + case 2452000: ch = 9; break; \ + case 2457000: ch = 10; break; \ + case 2462000: ch = 11; break; \ + case 2467000: ch = 12; break; \ + case 2472000: ch = 13; break; \ + case 2484000: ch = 14; break; \ + case 5180000: ch = 36; /* UNII */ break; \ + case 5200000: ch = 40; /* UNII */ break; \ + case 5220000: ch = 44; /* UNII */ break; \ + case 5240000: ch = 48; /* UNII */ break; \ + case 5260000: ch = 52; /* UNII */ break; \ + case 5280000: ch = 56; /* UNII */ break; \ + case 5300000: ch = 60; /* UNII */ break; \ + case 5320000: ch = 64; /* UNII */ break; \ + case 5745000: ch = 149; /* UNII */ break; \ + case 5765000: ch = 153; /* UNII */ break; \ + case 5785000: ch = 157; /* UNII */ break; \ + case 5805000: ch = 161; /* UNII */ break; \ + case 5825000: ch = 165; /* UNII */ break; \ + case 5500000: ch = 100; /* HiperLAN2 */ break; \ + case 5520000: ch = 104; /* HiperLAN2 */ break; \ + case 5540000: ch = 108; /* HiperLAN2 */ break; \ + case 5560000: ch = 112; /* HiperLAN2 */ break; \ + case 5580000: ch = 116; /* HiperLAN2 */ break; \ + case 5600000: ch = 120; /* HiperLAN2 */ break; \ + case 5620000: ch = 124; /* HiperLAN2 */ break; \ + case 5640000: ch = 128; /* HiperLAN2 */ break; \ + case 5660000: ch = 132; /* HiperLAN2 */ break; \ + case 5680000: ch = 136; /* HiperLAN2 */ break; \ + case 5700000: ch = 140; /* HiperLAN2 */ break; \ + case 5170000: ch = 34; /* Japan MMAC */ break; \ + case 5190000: ch = 38; /* Japan MMAC */ break; \ + case 5210000: ch = 42; /* Japan MMAC */ break; \ + case 5230000: ch = 46; /* Japan MMAC */ break; \ + case 4920000: ch = 184; /* Japan */ break; \ + case 4940000: ch = 188; /* Japan */ break; \ + case 4960000: ch = 192; /* Japan */ break; \ + case 4980000: ch = 196; /* Japan */ break; \ + case 5040000: ch = 208; /* Japan, means J08 */ break; \ + case 5060000: ch = 212; /* Japan, means J12 */ break; \ + case 5080000: ch = 216; /* Japan, means J16 */ break; \ + default: ch = 1; break; \ + } \ + } + +// +// Common fragment list structure - Identical to the scatter gather frag list structure +// +//#define RTMP_SCATTER_GATHER_ELEMENT SCATTER_GATHER_ELEMENT +//#define PRTMP_SCATTER_GATHER_ELEMENT PSCATTER_GATHER_ELEMENT +#define NIC_MAX_PHYS_BUF_COUNT 8 + +typedef struct _RTMP_SCATTER_GATHER_ELEMENT { + PVOID Address; + ULONG Length; + PULONG Reserved; +} RTMP_SCATTER_GATHER_ELEMENT, *PRTMP_SCATTER_GATHER_ELEMENT; + + +typedef struct _RTMP_SCATTER_GATHER_LIST { + ULONG NumberOfElements; + PULONG Reserved; + RTMP_SCATTER_GATHER_ELEMENT Elements[NIC_MAX_PHYS_BUF_COUNT]; +} RTMP_SCATTER_GATHER_LIST, *PRTMP_SCATTER_GATHER_LIST; + +// +// Some utility macros +// +#ifndef min +#define min(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) +#endif + +#ifndef max +#define max(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) +#endif + +#define GET_LNA_GAIN(_pAd) ((_pAd->LatchRfRegs.Channel <= 14) ? (_pAd->BLNAGain) : ((_pAd->LatchRfRegs.Channel <= 64) ? (_pAd->ALNAGain0) : ((_pAd->LatchRfRegs.Channel <= 128) ? (_pAd->ALNAGain1) : (_pAd->ALNAGain2)))) + +#define INC_COUNTER64(Val) (Val.QuadPart++) + +#define INFRA_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_INFRA_ON)) +#define ADHOC_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_ADHOC_ON)) +#define MONITOR_ON(_p) (((_p)->StaCfg.BssType) == BSS_MONITOR) +#define IDLE_ON(_p) (!INFRA_ON(_p) && !ADHOC_ON(_p)) + +// Check LEAP & CCKM flags +#define LEAP_ON(_p) (((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) +#define LEAP_CCKM_ON(_p) ((((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) && ((_p)->StaCfg.LeapAuthInfo.CCKM == TRUE)) + +// if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required +#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(_pBufVA, _pExtraLlcSnapEncap) \ +{ \ + if (((*(_pBufVA + 12) << 8) + *(_pBufVA + 13)) > 1500) \ + { \ + _pExtraLlcSnapEncap = SNAP_802_1H; \ + if (NdisEqualMemory(IPX, _pBufVA + 12, 2) || \ + NdisEqualMemory(APPLE_TALK, _pBufVA + 12, 2)) \ + { \ + _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \ + } \ + } \ + else \ + { \ + _pExtraLlcSnapEncap = NULL; \ + } \ +} + +// New Define for new Tx Path. +#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(_pBufVA, _pExtraLlcSnapEncap) \ +{ \ + if (((*(_pBufVA) << 8) + *(_pBufVA + 1)) > 1500) \ + { \ + _pExtraLlcSnapEncap = SNAP_802_1H; \ + if (NdisEqualMemory(IPX, _pBufVA, 2) || \ + NdisEqualMemory(APPLE_TALK, _pBufVA, 2)) \ + { \ + _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \ + } \ + } \ + else \ + { \ + _pExtraLlcSnapEncap = NULL; \ + } \ +} + + +#define MAKE_802_3_HEADER(_p, _pMac1, _pMac2, _pType) \ +{ \ + NdisMoveMemory(_p, _pMac1, MAC_ADDR_LEN); \ + NdisMoveMemory((_p + MAC_ADDR_LEN), _pMac2, MAC_ADDR_LEN); \ + NdisMoveMemory((_p + MAC_ADDR_LEN * 2), _pType, LENGTH_802_3_TYPE); \ +} + +// if pData has no LLC/SNAP (neither RFC1042 nor Bridge tunnel), keep it that way. +// else if the received frame is LLC/SNAP-encaped IPX or APPLETALK, preserve the LLC/SNAP field +// else remove the LLC/SNAP field from the result Ethernet frame +// Patch for WHQL only, which did not turn on Netbios but use IPX within its payload +// Note: +// _pData & _DataSize may be altered (remove 8-byte LLC/SNAP) by this MACRO +// _pRemovedLLCSNAP: pointer to removed LLC/SNAP; NULL is not removed +#define CONVERT_TO_802_3(_p8023hdr, _pDA, _pSA, _pData, _DataSize, _pRemovedLLCSNAP) \ +{ \ + char LLC_Len[2]; \ + \ + _pRemovedLLCSNAP = NULL; \ + if (NdisEqualMemory(SNAP_802_1H, _pData, 6) || \ + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, _pData, 6)) \ + { \ + PUCHAR pProto = _pData + 6; \ + \ + if ((NdisEqualMemory(IPX, pProto, 2) || NdisEqualMemory(APPLE_TALK, pProto, 2)) && \ + NdisEqualMemory(SNAP_802_1H, _pData, 6)) \ + { \ + LLC_Len[0] = (UCHAR)(_DataSize / 256); \ + LLC_Len[1] = (UCHAR)(_DataSize % 256); \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ + } \ + else \ + { \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, pProto); \ + _pRemovedLLCSNAP = _pData; \ + _DataSize -= LENGTH_802_1_H; \ + _pData += LENGTH_802_1_H; \ + } \ + } \ + else \ + { \ + LLC_Len[0] = (UCHAR)(_DataSize / 256); \ + LLC_Len[1] = (UCHAR)(_DataSize % 256); \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ + } \ +} + +#define SWITCH_AB( _pAA, _pBB) \ +{ \ + PVOID pCC; \ + pCC = _pBB; \ + _pBB = _pAA; \ + _pAA = pCC; \ +} + +// Enqueue this frame to MLME engine +// We need to enqueue the whole frame because MLME need to pass data type +// information from 802.11 header +#ifdef RT2870 +#define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _PlcpSignal) \ +{ \ + UINT32 High32TSF=0, Low32TSF=0; \ + MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2,_FrameSize, _pFrame, (UCHAR)_PlcpSignal); \ +} +#endif // RT2870 // + +#ifdef RT30xx +//Need to collect each ant's rssi concurrently +//rssi1 is report to pair2 Ant and rss2 is reprot to pair1 Ant when 4 Ant +#define COLLECT_RX_ANTENNA_AVERAGE_RSSI(_pAd, _rssi1, _rssi2) \ +{ \ + SHORT AvgRssi; \ + UCHAR UsedAnt; \ + if (_pAd->RxAnt.EvaluatePeriod == 0) \ + { \ + UsedAnt = _pAd->RxAnt.Pair1PrimaryRxAnt; \ + AvgRssi = _pAd->RxAnt.Pair1AvgRssi[UsedAnt]; \ + if (AvgRssi < 0) \ + AvgRssi = AvgRssi - (AvgRssi >> 3) + _rssi1; \ + else \ + AvgRssi = _rssi1 << 3; \ + _pAd->RxAnt.Pair1AvgRssi[UsedAnt] = AvgRssi; \ + } \ + else \ + { \ + UsedAnt = _pAd->RxAnt.Pair1SecondaryRxAnt; \ + AvgRssi = _pAd->RxAnt.Pair1AvgRssi[UsedAnt]; \ + if ((AvgRssi < 0) && (_pAd->RxAnt.FirstPktArrivedWhenEvaluate)) \ + AvgRssi = AvgRssi - (AvgRssi >> 3) + _rssi1; \ + else \ + { \ + _pAd->RxAnt.FirstPktArrivedWhenEvaluate = TRUE; \ + AvgRssi = _rssi1 << 3; \ + } \ + _pAd->RxAnt.Pair1AvgRssi[UsedAnt] = AvgRssi; \ + _pAd->RxAnt.RcvPktNumWhenEvaluate++; \ + } \ +} +#endif // RT30xx // + + +#define NDIS_QUERY_BUFFER(_NdisBuf, _ppVA, _pBufLen) \ + NdisQueryBuffer(_NdisBuf, _ppVA, _pBufLen) + +#define MAC_ADDR_EQUAL(pAddr1,pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), MAC_ADDR_LEN) +#define SSID_EQUAL(ssid1, len1, ssid2, len2) ((len1==len2) && (RTMPEqualMemory(ssid1, ssid2, len1))) + +// +// Check if it is Japan W53(ch52,56,60,64) channel. +// +#define JapanChannelCheck(channel) ((channel == 52) || (channel == 56) || (channel == 60) || (channel == 64)) + +#ifdef CONFIG_STA_SUPPORT +#define STA_PORT_SECURED(_pAd) \ +{ \ + _pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \ + NdisAcquireSpinLock(&_pAd->MacTabLock); \ + _pAd->MacTab.Content[BSSID_WCID].PortSecured = _pAd->StaCfg.PortSecured; \ + NdisReleaseSpinLock(&_pAd->MacTabLock); \ +} +#endif // CONFIG_STA_SUPPORT // + + +// +// Register set pair for initialzation register set definition +// +typedef struct _RTMP_REG_PAIR +{ + ULONG Register; + ULONG Value; +} RTMP_REG_PAIR, *PRTMP_REG_PAIR; + +typedef struct _REG_PAIR +{ + UCHAR Register; + UCHAR Value; +} REG_PAIR, *PREG_PAIR; + +// +// Register set pair for initialzation register set definition +// +typedef struct _RTMP_RF_REGS +{ + UCHAR Channel; + ULONG R1; + ULONG R2; + ULONG R3; + ULONG R4; +} RTMP_RF_REGS, *PRTMP_RF_REGS; + +typedef struct _FREQUENCY_ITEM { + UCHAR Channel; + UCHAR N; + UCHAR R; + UCHAR K; +} FREQUENCY_ITEM, *PFREQUENCY_ITEM; + +// +// Data buffer for DMA operation, the buffer must be contiguous physical memory +// Both DMA to / from CPU use the same structure. +// +typedef struct _RTMP_DMABUF +{ + ULONG AllocSize; + PVOID AllocVa; // TxBuf virtual address + NDIS_PHYSICAL_ADDRESS AllocPa; // TxBuf physical address +} RTMP_DMABUF, *PRTMP_DMABUF; + + +typedef union _HEADER_802_11_SEQ{ +#ifdef RT_BIG_ENDIAN + struct { + USHORT Sequence:12; + USHORT Frag:4; + } field; +#else + struct { + USHORT Frag:4; + USHORT Sequence:12; + } field; +#endif + USHORT value; +} HEADER_802_11_SEQ, *PHEADER_802_11_SEQ; + +// +// Data buffer for DMA operation, the buffer must be contiguous physical memory +// Both DMA to / from CPU use the same structure. +// +typedef struct _RTMP_REORDERBUF +{ + BOOLEAN IsFull; + PVOID AllocVa; // TxBuf virtual address + UCHAR Header802_3[14]; + HEADER_802_11_SEQ Sequence; //support compressed bitmap BA, so no consider fragment in BA + UCHAR DataOffset; + USHORT Datasize; + ULONG AllocSize; +#ifdef RT2870 + PUCHAR AllocPa; +#endif // RT2870 // +} RTMP_REORDERBUF, *PRTMP_REORDERBUF; + +// +// Control block (Descriptor) for all ring descriptor DMA operation, buffer must be +// contiguous physical memory. NDIS_PACKET stored the binding Rx packet descriptor +// which won't be released, driver has to wait until upper layer return the packet +// before giveing up this rx ring descriptor to ASIC. NDIS_BUFFER is assocaited pair +// to describe the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor +// which driver should ACK upper layer when the tx is physically done or failed. +// +typedef struct _RTMP_DMACB +{ + ULONG AllocSize; // Control block size + PVOID AllocVa; // Control block virtual address + NDIS_PHYSICAL_ADDRESS AllocPa; // Control block physical address + PNDIS_PACKET pNdisPacket; + PNDIS_PACKET pNextNdisPacket; + + RTMP_DMABUF DmaBuf; // Associated DMA buffer structure +} RTMP_DMACB, *PRTMP_DMACB; + +typedef struct _RTMP_TX_BUF +{ + PQUEUE_ENTRY Next; + UCHAR Index; + ULONG AllocSize; // Control block size + PVOID AllocVa; // Control block virtual address + NDIS_PHYSICAL_ADDRESS AllocPa; // Control block physical address +} RTMP_TXBUF, *PRTMP_TXBUF; + +typedef struct _RTMP_RX_BUF +{ + BOOLEAN InUse; + ULONG ByBaRecIndex; + RTMP_REORDERBUF MAP_RXBuf[MAX_RX_REORDERBUF]; +} RTMP_RXBUF, *PRTMP_RXBUF; +typedef struct _RTMP_TX_RING +{ + RTMP_DMACB Cell[TX_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; // software next free tx index +} RTMP_TX_RING, *PRTMP_TX_RING; + +typedef struct _RTMP_RX_RING +{ + RTMP_DMACB Cell[RX_RING_SIZE]; + UINT32 RxCpuIdx; + UINT32 RxDmaIdx; + INT32 RxSwReadIdx; // software next read index +} RTMP_RX_RING, *PRTMP_RX_RING; + +typedef struct _RTMP_MGMT_RING +{ + RTMP_DMACB Cell[MGMT_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; // software next free tx index +} RTMP_MGMT_RING, *PRTMP_MGMT_RING; + +// +// Statistic counter structure +// +typedef struct _COUNTER_802_3 +{ + // General Stats + ULONG GoodTransmits; + ULONG GoodReceives; + ULONG TxErrors; + ULONG RxErrors; + ULONG RxNoBuffer; + + // Ethernet Stats + ULONG RcvAlignmentErrors; + ULONG OneCollision; + ULONG MoreCollisions; + +} COUNTER_802_3, *PCOUNTER_802_3; + +typedef struct _COUNTER_802_11 { + ULONG Length; + LARGE_INTEGER LastTransmittedFragmentCount; + LARGE_INTEGER TransmittedFragmentCount; + LARGE_INTEGER MulticastTransmittedFrameCount; + LARGE_INTEGER FailedCount; + LARGE_INTEGER RetryCount; + LARGE_INTEGER MultipleRetryCount; + LARGE_INTEGER RTSSuccessCount; + LARGE_INTEGER RTSFailureCount; + LARGE_INTEGER ACKFailureCount; + LARGE_INTEGER FrameDuplicateCount; + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER MulticastReceivedFrameCount; + LARGE_INTEGER FCSErrorCount; +} COUNTER_802_11, *PCOUNTER_802_11; + +typedef struct _COUNTER_RALINK { + ULONG TransmittedByteCount; // both successful and failure, used to calculate TX throughput + ULONG ReceivedByteCount; // both CRC okay and CRC error, used to calculate RX throughput + ULONG BeenDisassociatedCount; + ULONG BadCQIAutoRecoveryCount; + ULONG PoorCQIRoamingCount; + ULONG MgmtRingFullCount; + ULONG RxCountSinceLastNULL; + ULONG RxCount; + ULONG RxRingErrCount; + ULONG KickTxCount; + ULONG TxRingErrCount; + LARGE_INTEGER RealFcsErrCount; + ULONG PendingNdisPacketCount; + + ULONG OneSecOsTxCount[NUM_OF_TX_RING]; + ULONG OneSecDmaDoneCount[NUM_OF_TX_RING]; + UINT32 OneSecTxDoneCount; + ULONG OneSecRxCount; + UINT32 OneSecTxAggregationCount; + UINT32 OneSecRxAggregationCount; + + UINT32 OneSecFrameDuplicateCount; + +#ifdef RT2870 + ULONG OneSecTransmittedByteCount; // both successful and failure, used to calculate TX throughput +#endif // RT2870 // + + UINT32 OneSecTxNoRetryOkCount; + UINT32 OneSecTxRetryOkCount; + UINT32 OneSecTxFailCount; + UINT32 OneSecFalseCCACnt; // CCA error count, for debug purpose, might move to global counter + UINT32 OneSecRxOkCnt; // RX without error + UINT32 OneSecRxOkDataCnt; // unicast-to-me DATA frame count + UINT32 OneSecRxFcsErrCnt; // CRC error + UINT32 OneSecBeaconSentCnt; + UINT32 LastOneSecTotalTxCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount + UINT32 LastOneSecRxOkDataCnt; // OneSecRxOkDataCnt + ULONG DuplicateRcv; + ULONG TxAggCount; + ULONG TxNonAggCount; + ULONG TxAgg1MPDUCount; + ULONG TxAgg2MPDUCount; + ULONG TxAgg3MPDUCount; + ULONG TxAgg4MPDUCount; + ULONG TxAgg5MPDUCount; + ULONG TxAgg6MPDUCount; + ULONG TxAgg7MPDUCount; + ULONG TxAgg8MPDUCount; + ULONG TxAgg9MPDUCount; + ULONG TxAgg10MPDUCount; + ULONG TxAgg11MPDUCount; + ULONG TxAgg12MPDUCount; + ULONG TxAgg13MPDUCount; + ULONG TxAgg14MPDUCount; + ULONG TxAgg15MPDUCount; + ULONG TxAgg16MPDUCount; + + LARGE_INTEGER TransmittedOctetsInAMSDU; + LARGE_INTEGER TransmittedAMSDUCount; + LARGE_INTEGER ReceivedOctesInAMSDUCount; + LARGE_INTEGER ReceivedAMSDUCount; + LARGE_INTEGER TransmittedAMPDUCount; + LARGE_INTEGER TransmittedMPDUsInAMPDUCount; + LARGE_INTEGER TransmittedOctetsInAMPDUCount; + LARGE_INTEGER MPDUInReceivedAMPDUCount; +} COUNTER_RALINK, *PCOUNTER_RALINK; + +typedef struct _PID_COUNTER { + ULONG TxAckRequiredCount; // CRC error + ULONG TxAggreCount; + ULONG TxSuccessCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount + ULONG LastSuccessRate; +} PID_COUNTER, *PPID_COUNTER; + +typedef struct _COUNTER_DRS { + // to record the each TX rate's quality. 0 is best, the bigger the worse. + USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; + UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH]; + UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition + ULONG CurrTxRateStableTime; // # of second in current TX rate + BOOLEAN fNoisyEnvironment; + BOOLEAN fLastSecAccordingRSSI; + UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down + UCHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction + ULONG LastTxOkCount; +} COUNTER_DRS, *PCOUNTER_DRS; + +// +// Arcfour Structure Added by PaulWu +// +typedef struct _ARCFOUR +{ + UINT X; + UINT Y; + UCHAR STATE[256]; +} ARCFOURCONTEXT, *PARCFOURCONTEXT; + +// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI too. just copy to TXWI. +typedef struct _RECEIVE_SETTING { +#ifdef RT_BIG_ENDIAN + USHORT MIMO:1; + USHORT OFDM:1; + USHORT rsv:3; + USHORT STBC:2; //SPACE + USHORT ShortGI:1; + USHORT Mode:2; //channel bandwidth 20MHz or 40 MHz + USHORT NumOfRX:2; // MIMO. WE HAVE 3R +#else + USHORT NumOfRX:2; // MIMO. WE HAVE 3R + USHORT Mode:2; //channel bandwidth 20MHz or 40 MHz + USHORT ShortGI:1; + USHORT STBC:2; //SPACE + USHORT rsv:3; + USHORT OFDM:1; + USHORT MIMO:1; +#endif + } RECEIVE_SETTING, *PRECEIVE_SETTING; + +// Shared key data structure +typedef struct _WEP_KEY { + UCHAR KeyLen; // Key length for each key, 0: entry is invalid + UCHAR Key[MAX_LEN_OF_KEY]; // right now we implement 4 keys, 128 bits max +} WEP_KEY, *PWEP_KEY; + +typedef struct _CIPHER_KEY { + UCHAR Key[16]; // right now we implement 4 keys, 128 bits max + UCHAR RxMic[8]; // make alignment + UCHAR TxMic[8]; + UCHAR TxTsc[6]; // 48bit TSC value + UCHAR RxTsc[6]; // 48bit TSC value + UCHAR CipherAlg; // 0-none, 1:WEP64, 2:WEP128, 3:TKIP, 4:AES, 5:CKIP64, 6:CKIP128 + UCHAR KeyLen; +#ifdef CONFIG_STA_SUPPORT + UCHAR BssId[6]; +#endif // CONFIG_STA_SUPPORT // + // Key length for each key, 0: entry is invalid + UCHAR Type; // Indicate Pairwise/Group when reporting MIC error +} CIPHER_KEY, *PCIPHER_KEY; + +typedef struct _BBP_TUNING_STRUCT { + BOOLEAN Enable; + UCHAR FalseCcaCountUpperBound; // 100 per sec + UCHAR FalseCcaCountLowerBound; // 10 per sec + UCHAR R17LowerBound; // specified in E2PROM + UCHAR R17UpperBound; // 0x68 according to David Tung + UCHAR CurrentR17Value; +} BBP_TUNING, *PBBP_TUNING; + +typedef struct _SOFT_RX_ANT_DIVERSITY_STRUCT { + UCHAR EvaluatePeriod; // 0:not evalute status, 1: evaluate status, 2: switching status + UCHAR EvaluateStableCnt; + UCHAR Pair1PrimaryRxAnt; // 0:Ant-E1, 1:Ant-E2 + UCHAR Pair1SecondaryRxAnt; // 0:Ant-E1, 1:Ant-E2 + UCHAR Pair2PrimaryRxAnt; // 0:Ant-E3, 1:Ant-E4 + UCHAR Pair2SecondaryRxAnt; // 0:Ant-E3, 1:Ant-E4 + SHORT Pair1AvgRssi[2]; // AvgRssi[0]:E1, AvgRssi[1]:E2 + SHORT Pair2AvgRssi[2]; // AvgRssi[0]:E3, AvgRssi[1]:E4 + SHORT Pair1LastAvgRssi; // + SHORT Pair2LastAvgRssi; // + ULONG RcvPktNumWhenEvaluate; + BOOLEAN FirstPktArrivedWhenEvaluate; + RALINK_TIMER_STRUCT RxAntDiversityTimer; +} SOFT_RX_ANT_DIVERSITY, *PSOFT_RX_ANT_DIVERSITY; + +typedef struct _LEAP_AUTH_INFO { + BOOLEAN Enabled; //Ture: Enable LEAP Authentication + BOOLEAN CCKM; //Ture: Use Fast Reauthentication with CCKM + UCHAR Reserve[2]; + UCHAR UserName[256]; //LEAP, User name + ULONG UserNameLen; + UCHAR Password[256]; //LEAP, User Password + ULONG PasswordLen; +} LEAP_AUTH_INFO, *PLEAP_AUTH_INFO; + +typedef struct { + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR ErrorCode[2]; //00 01-Invalid authentication type + //00 02-Authentication timeout + //00 03-Challenge from AP failed + //00 04-Challenge to AP failed + BOOLEAN Reported; +} ROGUEAP_ENTRY, *PROGUEAP_ENTRY; + +typedef struct { + UCHAR RogueApNr; + ROGUEAP_ENTRY RogueApEntry[MAX_LEN_OF_BSS_TABLE]; +} ROGUEAP_TABLE, *PROGUEAP_TABLE; + +typedef struct { + BOOLEAN Enable; + UCHAR Delta; + BOOLEAN PlusSign; +} CCK_TX_POWER_CALIBRATE, *PCCK_TX_POWER_CALIBRATE; + +// +// Receive Tuple Cache Format +// +typedef struct _TUPLE_CACHE { + BOOLEAN Valid; + UCHAR MacAddress[MAC_ADDR_LEN]; + USHORT Sequence; + USHORT Frag; +} TUPLE_CACHE, *PTUPLE_CACHE; + +// +// Fragment Frame structure +// +typedef struct _FRAGMENT_FRAME { + PNDIS_PACKET pFragPacket; + ULONG RxSize; + USHORT Sequence; + USHORT LastFrag; + ULONG Flags; // Some extra frame information. bit 0: LLC presented +} FRAGMENT_FRAME, *PFRAGMENT_FRAME; + + +// +// Packet information for NdisQueryPacket +// +typedef struct _PACKET_INFO { + UINT PhysicalBufferCount; // Physical breaks of buffer descripor chained + UINT BufferCount ; // Number of Buffer descriptor chained + UINT TotalPacketLength ; // Self explained + PNDIS_BUFFER pFirstBuffer; // Pointer to first buffer descriptor +} PACKET_INFO, *PPACKET_INFO; + +// +// Tkip Key structure which RC4 key & MIC calculation +// +typedef struct _TKIP_KEY_INFO { + UINT nBytesInM; // # bytes in M for MICKEY + ULONG IV16; + ULONG IV32; + ULONG K0; // for MICKEY Low + ULONG K1; // for MICKEY Hig + ULONG L; // Current state for MICKEY + ULONG R; // Current state for MICKEY + ULONG M; // Message accumulator for MICKEY + UCHAR RC4KEY[16]; + UCHAR MIC[8]; +} TKIP_KEY_INFO, *PTKIP_KEY_INFO; + +// +// Private / Misc data, counters for driver internal use +// +typedef struct __PRIVATE_STRUC { + UINT SystemResetCnt; // System reset counter + UINT TxRingFullCnt; // Tx ring full occurrance number + UINT PhyRxErrCnt; // PHY Rx error count, for debug purpose, might move to global counter + // Variables for WEP encryption / decryption in rtmp_wep.c + UINT FCSCRC32; + ARCFOURCONTEXT WEPCONTEXT; + // Tkip stuff + TKIP_KEY_INFO Tx; + TKIP_KEY_INFO Rx; +} PRIVATE_STRUC, *PPRIVATE_STRUC; + +// structure to tune BBP R66 (BBP TUNING) +typedef struct _BBP_R66_TUNING { + BOOLEAN bEnable; + USHORT FalseCcaLowerThreshold; // default 100 + USHORT FalseCcaUpperThreshold; // default 512 + UCHAR R66Delta; + UCHAR R66CurrentValue; + BOOLEAN R66LowerUpperSelect; //Before LinkUp, Used LowerBound or UpperBound as R66 value. +} BBP_R66_TUNING, *PBBP_R66_TUNING; + +// structure to store channel TX power +typedef struct _CHANNEL_TX_POWER { + USHORT RemainingTimeForUse; //unit: sec + UCHAR Channel; +#ifdef DOT11N_DRAFT3 + BOOLEAN bEffectedChannel; // For BW 40 operating in 2.4GHz , the "effected channel" is the channel that is covered in 40Mhz. +#endif // DOT11N_DRAFT3 // + CHAR Power; + CHAR Power2; + UCHAR MaxTxPwr; + UCHAR DfsReq; +} CHANNEL_TX_POWER, *PCHANNEL_TX_POWER; + +// structure to store 802.11j channel TX power +typedef struct _CHANNEL_11J_TX_POWER { + UCHAR Channel; + UCHAR BW; // BW_10 or BW_20 + CHAR Power; + CHAR Power2; + USHORT RemainingTimeForUse; //unit: sec +} CHANNEL_11J_TX_POWER, *PCHANNEL_11J_TX_POWER; + +typedef enum _ABGBAND_STATE_ { + UNKNOWN_BAND, + BG_BAND, + A_BAND, +} ABGBAND_STATE; + +typedef struct _MLME_STRUCT { +#ifdef CONFIG_STA_SUPPORT + // STA state machines + STATE_MACHINE CntlMachine; + STATE_MACHINE AssocMachine; + STATE_MACHINE AuthMachine; + STATE_MACHINE AuthRspMachine; + STATE_MACHINE SyncMachine; + STATE_MACHINE WpaPskMachine; + STATE_MACHINE LeapMachine; + STATE_MACHINE AironetMachine; + STATE_MACHINE_FUNC AssocFunc[ASSOC_FUNC_SIZE]; + STATE_MACHINE_FUNC AuthFunc[AUTH_FUNC_SIZE]; + STATE_MACHINE_FUNC AuthRspFunc[AUTH_RSP_FUNC_SIZE]; + STATE_MACHINE_FUNC SyncFunc[SYNC_FUNC_SIZE]; + STATE_MACHINE_FUNC WpaPskFunc[WPA_PSK_FUNC_SIZE]; + STATE_MACHINE_FUNC AironetFunc[AIRONET_FUNC_SIZE]; +#endif // CONFIG_STA_SUPPORT // + STATE_MACHINE_FUNC ActFunc[ACT_FUNC_SIZE]; + // Action + STATE_MACHINE ActMachine; + + +#ifdef QOS_DLS_SUPPORT + STATE_MACHINE DlsMachine; + STATE_MACHINE_FUNC DlsFunc[DLS_FUNC_SIZE]; +#endif // QOS_DLS_SUPPORT // + + + + + ULONG ChannelQuality; // 0..100, Channel Quality Indication for Roaming + ULONG Now32; // latch the value of NdisGetSystemUpTime() + ULONG LastSendNULLpsmTime; + + BOOLEAN bRunning; + NDIS_SPIN_LOCK TaskLock; + MLME_QUEUE Queue; + + UINT ShiftReg; + + RALINK_TIMER_STRUCT PeriodicTimer; + RALINK_TIMER_STRUCT APSDPeriodicTimer; + RALINK_TIMER_STRUCT LinkDownTimer; + RALINK_TIMER_STRUCT LinkUpTimer; + ULONG PeriodicRound; + ULONG OneSecPeriodicRound; + + UCHAR RealRxPath; + BOOLEAN bLowThroughput; + BOOLEAN bEnableAutoAntennaCheck; + RALINK_TIMER_STRUCT RxAntEvalTimer; + +#ifdef RT30xx + UCHAR CaliBW40RfR24; + UCHAR CaliBW20RfR24; +#endif // RT30xx // + +} MLME_STRUCT, *PMLME_STRUCT; + +// structure for radar detection and channel switch +typedef struct _RADAR_DETECT_STRUCT { + //BOOLEAN IEEE80211H; // 0: disable, 1: enable IEEE802.11h + UCHAR CSCount; //Channel switch counter + UCHAR CSPeriod; //Channel switch period (beacon count) + UCHAR RDCount; //Radar detection counter + UCHAR RDMode; //Radar Detection mode + UCHAR RDDurRegion; //Radar detection duration region + UCHAR BBPR16; + UCHAR BBPR17; + UCHAR BBPR18; + UCHAR BBPR21; + UCHAR BBPR22; + UCHAR BBPR64; + ULONG InServiceMonitorCount; // unit: sec + UINT8 DfsSessionTime; + BOOLEAN bFastDfs; + UINT8 ChMovingTime; + UINT8 LongPulseRadarTh; +} RADAR_DETECT_STRUCT, *PRADAR_DETECT_STRUCT; + +#ifdef CARRIER_DETECTION_SUPPORT +typedef enum CD_STATE_n +{ + CD_NORMAL, + CD_SILENCE, + CD_MAX_STATE +} CD_STATE; + +typedef struct CARRIER_DETECTION_s +{ + BOOLEAN Enable; + UINT8 CDSessionTime; + UINT8 CDPeriod; + CD_STATE CD_State; +} CARRIER_DETECTION, *PCARRIER_DETECTION; +#endif // CARRIER_DETECTION_SUPPORT // + +typedef enum _REC_BLOCKACK_STATUS +{ + Recipient_NONE=0, + Recipient_USED, + Recipient_HandleRes, + Recipient_Accept +} REC_BLOCKACK_STATUS, *PREC_BLOCKACK_STATUS; + +typedef enum _ORI_BLOCKACK_STATUS +{ + Originator_NONE=0, + Originator_USED, + Originator_WaitRes, + Originator_Done +} ORI_BLOCKACK_STATUS, *PORI_BLOCKACK_STATUS; + +#ifdef DOT11_N_SUPPORT +typedef struct _BA_ORI_ENTRY{ + UCHAR Wcid; + UCHAR TID; + UCHAR BAWinSize; + UCHAR Token; +// Sequence is to fill every outgoing QoS DATA frame's sequence field in 802.11 header. + USHORT Sequence; + USHORT TimeOutValue; + ORI_BLOCKACK_STATUS ORI_BA_Status; + RALINK_TIMER_STRUCT ORIBATimer; + PVOID pAdapter; +} BA_ORI_ENTRY, *PBA_ORI_ENTRY; + +typedef struct _BA_REC_ENTRY { + UCHAR Wcid; + UCHAR TID; + UCHAR BAWinSize; // 7.3.1.14. each buffer is capable of holding a max AMSDU or MSDU. + //UCHAR NumOfRxPkt; + //UCHAR Curindidx; // the head in the RX reordering buffer + USHORT LastIndSeq; +// USHORT LastIndSeqAtTimer; + USHORT TimeOutValue; + RALINK_TIMER_STRUCT RECBATimer; + ULONG LastIndSeqAtTimer; + ULONG nDropPacket; + ULONG rcvSeq; + REC_BLOCKACK_STATUS REC_BA_Status; +// UCHAR RxBufIdxUsed; + // corresponding virtual address for RX reordering packet storage. + //RTMP_REORDERDMABUF MAP_RXBuf[MAX_RX_REORDERBUF]; + NDIS_SPIN_LOCK RxReRingLock; // Rx Ring spinlock +// struct _BA_REC_ENTRY *pNext; + PVOID pAdapter; + struct reordering_list list; +} BA_REC_ENTRY, *PBA_REC_ENTRY; + + +typedef struct { + ULONG numAsRecipient; // I am recipient of numAsRecipient clients. These client are in the BARecEntry[] + ULONG numAsOriginator; // I am originator of numAsOriginator clients. These clients are in the BAOriEntry[] + BA_ORI_ENTRY BAOriEntry[MAX_LEN_OF_BA_ORI_TABLE]; + BA_REC_ENTRY BARecEntry[MAX_LEN_OF_BA_REC_TABLE]; +} BA_TABLE, *PBA_TABLE; + +//For QureyBATableOID use; +typedef struct PACKED _OID_BA_REC_ENTRY{ + UCHAR MACAddr[MAC_ADDR_LEN]; + UCHAR BaBitmap; // if (BaBitmap&(1<> 3) + 1) /* /8 + 1 */ +#define WLAN_CT_TIM_BCMC_OFFSET 0 /* unit: 32B */ + +/* clear bcmc TIM bit */ +#define WLAN_MR_TIM_BCMC_CLEAR(apidx) \ + pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] &= ~BIT8[0]; + +/* set bcmc TIM bit */ +#define WLAN_MR_TIM_BCMC_SET(apidx) \ + pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] |= BIT8[0]; + +/* clear a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_CLEAR(ad_p, apidx, wcid) \ + { UCHAR tim_offset = wcid >> 3; \ + UCHAR bit_offset = wcid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] &= (~BIT8[bit_offset]); } + +/* set a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_SET(ad_p, apidx, wcid) \ + { UCHAR tim_offset = wcid >> 3; \ + UCHAR bit_offset = wcid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= BIT8[bit_offset]; } + +#ifdef RT2870 +#define BEACON_BITMAP_MASK 0xff +typedef struct _BEACON_SYNC_STRUCT_ +{ + UCHAR BeaconBuf[HW_BEACON_MAX_COUNT][HW_BEACON_OFFSET]; + UCHAR BeaconTxWI[HW_BEACON_MAX_COUNT][TXWI_SIZE]; + ULONG TimIELocationInBeacon[HW_BEACON_MAX_COUNT]; + ULONG CapabilityInfoLocationInBeacon[HW_BEACON_MAX_COUNT]; + BOOLEAN EnableBeacon; // trigger to enable beacon transmission. + UCHAR BeaconBitMap; // NOTE: If the MAX_MBSSID_NUM is larger than 8, this parameter need to change. + UCHAR DtimBitOn; // NOTE: If the MAX_MBSSID_NUM is larger than 8, this parameter need to change. +}BEACON_SYNC_STRUCT; +#endif // RT2870 // + +typedef struct _MULTISSID_STRUCT { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + USHORT CapabilityInfo; + + PNET_DEV MSSIDDev; + + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + WPA_MIX_PAIR_CIPHER WpaMixPairCipher; + + ULONG TxCount; + ULONG RxCount; + ULONG ReceivedByteCount; + ULONG TransmittedByteCount; + ULONG RxErrorCount; + ULONG RxDropCount; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. + RT_HT_PHY_INFO DesiredHtPhyInfo; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. this is for reading registry setting only. not useful. + BOOLEAN bAutoTxRateSwitch; + + //CIPHER_KEY SharedKey[SHARE_KEY_NUM]; // ref pAd->SharedKey[BSS][4] + UCHAR DefaultKeyId; + + UCHAR TxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11, ... + UCHAR DesiredRates[MAX_LEN_OF_SUPPORTED_RATES];// OID_802_11_DESIRED_RATES + UCHAR DesiredRatesIndex; + UCHAR MaxTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 + +// ULONG TimBitmap; // bit0 for broadcast, 1 for AID1, 2 for AID2, ...so on +// ULONG TimBitmap2; // b0 for AID32, b1 for AID33, ... and so on + UCHAR TimBitmaps[WLAN_MAX_NUM_OF_TIM]; + + // WPA + UCHAR GMK[32]; + UCHAR PMK[32]; + UCHAR GTK[32]; + BOOLEAN IEEE8021X; + BOOLEAN PreAuth; + UCHAR GNonce[32]; + UCHAR PortSecured; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; + UCHAR BANClass3Data; + ULONG IsolateInterStaTraffic; + + UCHAR RSNIE_Len[2]; + UCHAR RSN_IE[2][MAX_LEN_OF_RSNIE]; + + + UCHAR TimIELocationInBeacon; + UCHAR CapabilityInfoLocationInBeacon; + // outgoing BEACON frame buffer and corresponding TXWI + // PTXWI_STRUC BeaconTxWI; // + CHAR BeaconBuf[MAX_BEACON_SIZE]; // NOTE: BeaconBuf should be 4-byte aligned + + BOOLEAN bHideSsid; + UINT16 StationKeepAliveTime; // unit: second + + USHORT VLAN_VID; + USHORT VLAN_Priority; + + RT_802_11_ACL AccessControlList; + + // EDCA Qos + BOOLEAN bWmmCapable; // 0:disable WMM, 1:enable WMM + BOOLEAN bDLSCapable; // 0:disable DLS, 1:enable DLS + + UCHAR DlsPTK[64]; // Due to windows dirver count on meetinghouse to handle 4-way shake + + // For 802.1x daemon setting per BSS + UCHAR radius_srv_num; + RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; + +#ifdef RTL865X_SOC + unsigned int mylinkid; +#endif + + + UINT32 RcvdConflictSsidCount; + UINT32 RcvdSpoofedAssocRespCount; + UINT32 RcvdSpoofedReassocRespCount; + UINT32 RcvdSpoofedProbeRespCount; + UINT32 RcvdSpoofedBeaconCount; + UINT32 RcvdSpoofedDisassocCount; + UINT32 RcvdSpoofedAuthCount; + UINT32 RcvdSpoofedDeauthCount; + UINT32 RcvdSpoofedUnknownMgmtCount; + UINT32 RcvdReplayAttackCount; + + CHAR RssiOfRcvdConflictSsid; + CHAR RssiOfRcvdSpoofedAssocResp; + CHAR RssiOfRcvdSpoofedReassocResp; + CHAR RssiOfRcvdSpoofedProbeResp; + CHAR RssiOfRcvdSpoofedBeacon; + CHAR RssiOfRcvdSpoofedDisassoc; + CHAR RssiOfRcvdSpoofedAuth; + CHAR RssiOfRcvdSpoofedDeauth; + CHAR RssiOfRcvdSpoofedUnknownMgmt; + CHAR RssiOfRcvdReplayAttack; + + BOOLEAN bBcnSntReq; + UCHAR BcnBufIdx; +} MULTISSID_STRUCT, *PMULTISSID_STRUCT; + + + +#ifdef DOT11N_DRAFT3 +typedef enum _BSS2040COEXIST_FLAG{ + BSS_2040_COEXIST_DISABLE = 0, + BSS_2040_COEXIST_TIMER_FIRED = 1, + BSS_2040_COEXIST_INFO_SYNC = 2, + BSS_2040_COEXIST_INFO_NOTIFY = 4, +}BSS2040COEXIST_FLAG; +#endif // DOT11N_DRAFT3 // + +// configuration common to OPMODE_AP as well as OPMODE_STA +typedef struct _COMMON_CONFIG { + + BOOLEAN bCountryFlag; + UCHAR CountryCode[3]; + UCHAR Geography; + UCHAR CountryRegion; // Enum of country region, 0:FCC, 1:IC, 2:ETSI, 3:SPAIN, 4:France, 5:MKK, 6:MKK1, 7:Israel + UCHAR CountryRegionForABand; // Enum of country region for A band + UCHAR PhyMode; // PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED + USHORT Dsifs; // in units of usec + ULONG PacketFilter; // Packet filter for receiving + + CHAR Ssid[MAX_LEN_OF_SSID]; // NOT NULL-terminated + UCHAR SsidLen; // the actual ssid length in used + UCHAR LastSsidLen; // the actual ssid length in used + CHAR LastSsid[MAX_LEN_OF_SSID]; // NOT NULL-terminated + UCHAR LastBssid[MAC_ADDR_LEN]; + + UCHAR Bssid[MAC_ADDR_LEN]; + USHORT BeaconPeriod; + UCHAR Channel; + UCHAR CentralChannel; // Central Channel when using 40MHz is indicating. not real channel. + + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + UCHAR DesireRate[MAX_LEN_OF_SUPPORTED_RATES]; // OID_802_11_DESIRED_RATES + UCHAR MaxDesiredRate; + UCHAR ExpectedACKRate[MAX_LEN_OF_SUPPORTED_RATES]; + + ULONG BasicRateBitmap; // backup basic ratebitmap + + BOOLEAN bAPSDCapable; + BOOLEAN bInServicePeriod; + BOOLEAN bAPSDAC_BE; + BOOLEAN bAPSDAC_BK; + BOOLEAN bAPSDAC_VI; + BOOLEAN bAPSDAC_VO; + BOOLEAN bNeedSendTriggerFrame; + BOOLEAN bAPSDForcePowerSave; // Force power save mode, should only use in APSD-STAUT + ULONG TriggerTimerCount; + UCHAR MaxSPLength; + UCHAR BBPCurrentBW; // BW_10, BW_20, BW_40 + // move to MULTISSID_STRUCT for MBSS + //HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. + REG_TRANSMIT_SETTING RegTransmitSetting; //registry transmit setting. this is for reading registry setting only. not useful. + //UCHAR FixedTxMode; // Fixed Tx Mode (CCK, OFDM), for HT fixed tx mode (GF, MIX) , refer to RegTransmitSetting.field.HTMode + UCHAR TxRate; // Same value to fill in TXD. TxRate is 6-bit + UCHAR MaxTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 + UCHAR TxRateIndex; // Tx rate index in RateSwitchTable + UCHAR TxRateTableSize; // Valid Tx rate table size in RateSwitchTable + //BOOLEAN bAutoTxRateSwitch; + UCHAR MinTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11 + UCHAR RtsRate; // RATE_xxx + HTTRANSMIT_SETTING MlmeTransmit; // MGMT frame PHY rate setting when operatin at Ht rate. + UCHAR MlmeRate; // RATE_xxx, used to send MLME frames + UCHAR BasicMlmeRate; // Default Rate for sending MLME frames + + USHORT RtsThreshold; // in unit of BYTE + USHORT FragmentThreshold; // in unit of BYTE + + UCHAR TxPower; // in unit of mW + ULONG TxPowerPercentage; // 0~100 % + ULONG TxPowerDefault; // keep for TxPowerPercentage + +#ifdef DOT11_N_SUPPORT + BACAP_STRUC BACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 + BACAP_STRUC REGBACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 +#endif // DOT11_N_SUPPORT // + IOT_STRUC IOTestParm; // 802.11n InterOpbility Test Parameter; + ULONG TxPreamble; // Rt802_11PreambleLong, Rt802_11PreambleShort, Rt802_11PreambleAuto + BOOLEAN bUseZeroToDisableFragment; // Microsoft use 0 as disable + ULONG UseBGProtection; // 0: auto, 1: always use, 2: always not use + BOOLEAN bUseShortSlotTime; // 0: disable, 1 - use short slot (9us) + BOOLEAN bEnableTxBurst; // 1: enble TX PACKET BURST, 0: disable TX PACKET BURST + BOOLEAN bAggregationCapable; // 1: enable TX aggregation when the peer supports it + BOOLEAN bPiggyBackCapable; // 1: enable TX piggy-back according MAC's version + BOOLEAN bIEEE80211H; // 1: enable IEEE802.11h spec. + ULONG DisableOLBCDetect; // 0: enable OLBC detect; 1 disable OLBC detect + +#ifdef DOT11_N_SUPPORT + BOOLEAN bRdg; +#endif // DOT11_N_SUPPORT // + BOOLEAN bWmmCapable; // 0:disable WMM, 1:enable WMM + QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP + EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP + QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP + UCHAR AckPolicy[4]; // ACK policy of the specified AC. see ACK_xxx +#ifdef CONFIG_STA_SUPPORT + BOOLEAN bDLSCapable; // 0:disable DLS, 1:enable DLS +#endif // CONFIG_STA_SUPPORT // + // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular + // BOOLEAN control, either ON or OFF. These flags should always be accessed via + // OPSTATUS_TEST_FLAG(), OPSTATUS_SET_FLAG(), OP_STATUS_CLEAR_FLAG() macros. + // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition + ULONG OpStatusFlags; + + BOOLEAN NdisRadioStateOff; //For HCT 12.0, set this flag to TRUE instead of called MlmeRadioOff. + ABGBAND_STATE BandState; // For setting BBP used on B/G or A mode. + BOOLEAN bRxAntDiversity; // 0:disable, 1:enable Software Rx Antenna Diversity. + + // IEEE802.11H--DFS. + RADAR_DETECT_STRUCT RadarDetect; + +#ifdef CARRIER_DETECTION_SUPPORT + CARRIER_DETECTION CarrierDetect; +#endif // CARRIER_DETECTION_SUPPORT // + +#ifdef DOT11_N_SUPPORT + // HT + UCHAR BASize; // USer desired BAWindowSize. Should not exceed our max capability + //RT_HT_CAPABILITY SupportedHtPhy; + RT_HT_CAPABILITY DesiredHtPhy; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHTInfo; // Useful as AP. + //This IE is used with channel switch announcement element when changing to a new 40MHz. + //This IE is included in channel switch ammouncement frames 7.4.1.5, beacons, probe Rsp. + NEW_EXT_CHAN_IE NewExtChanOffset; //7.3.2.20A, 1 if extension channel is above the control channel, 3 if below, 0 if not present + +#ifdef DOT11N_DRAFT3 + UCHAR Bss2040CoexistFlag; // bit 0: bBssCoexistTimerRunning, bit 1: NeedSyncAddHtInfo. + RALINK_TIMER_STRUCT Bss2040CoexistTimer; + + //This IE is used for 20/40 BSS Coexistence. + BSS_2040_COEXIST_IE BSS2040CoexistInfo; + // ====== 11n D3.0 =======================> + USHORT Dot11OBssScanPassiveDwell; // Unit : TU. 5~1000 + USHORT Dot11OBssScanActiveDwell; // Unit : TU. 10~1000 + USHORT Dot11BssWidthTriggerScanInt; // Unit : Second + USHORT Dot11OBssScanPassiveTotalPerChannel; // Unit : TU. 200~10000 + USHORT Dot11OBssScanActiveTotalPerChannel; // Unit : TU. 20~10000 + USHORT Dot11BssWidthChanTranDelayFactor; + USHORT Dot11OBssScanActivityThre; // Unit : percentage + + ULONG Dot11BssWidthChanTranDelay; // multiple of (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) + ULONG CountDownCtr; // CountDown Counter from (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) + + NDIS_SPIN_LOCK TriggerEventTabLock; + BSS_2040_COEXIST_IE LastBSSCoexist2040; + BSS_2040_COEXIST_IE BSSCoexist2040; + TRIGGER_EVENT_TAB TriggerEventTab; + UCHAR ChannelListIdx; + // <====== 11n D3.0 ======================= + BOOLEAN bOverlapScanning; +#endif // DOT11N_DRAFT3 // + + BOOLEAN bHTProtect; + BOOLEAN bMIMOPSEnable; + BOOLEAN bBADecline; + BOOLEAN bDisableReordering; + BOOLEAN bForty_Mhz_Intolerant; + BOOLEAN bExtChannelSwitchAnnouncement; + BOOLEAN bRcvBSSWidthTriggerEvents; + ULONG LastRcvBSSWidthTriggerEventsTime; + + UCHAR TxBASize; +#endif // DOT11_N_SUPPORT // + + // Enable wireless event + BOOLEAN bWirelessEvent; + BOOLEAN bWiFiTest; // Enable this parameter for WiFi test + + // Tx & Rx Stream number selection + UCHAR TxStream; + UCHAR RxStream; + + // transmit phy mode, trasmit rate for Multicast. +#ifdef MCAST_RATE_SPECIFIC + UCHAR McastTransmitMcs; + UCHAR McastTransmitPhyMode; +#endif // MCAST_RATE_SPECIFIC // + + BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled + +#ifdef RT2870 + BOOLEAN bMultipleIRP; // Multiple Bulk IN flag + UCHAR NumOfBulkInIRP; // if bMultipleIRP == TRUE, NumOfBulkInIRP will be 4 otherwise be 1 + RT_HT_CAPABILITY SupportedHtPhy; + ULONG MaxPktOneTxBulk; + UCHAR TxBulkFactor; + UCHAR RxBulkFactor; + + BEACON_SYNC_STRUCT *pBeaconSync; + RALINK_TIMER_STRUCT BeaconUpdateTimer; + UINT32 BeaconAdjust; + UINT32 BeaconFactor; + UINT32 BeaconRemain; +#endif // RT2870 // + + + NDIS_SPIN_LOCK MeasureReqTabLock; + PMEASURE_REQ_TAB pMeasureReqTab; + + NDIS_SPIN_LOCK TpcReqTabLock; + PTPC_REQ_TAB pTpcReqTab; + + // transmit phy mode, trasmit rate for Multicast. +#ifdef MCAST_RATE_SPECIFIC + HTTRANSMIT_SETTING MCastPhyMode; +#endif // MCAST_RATE_SPECIFIC // + +#ifdef SINGLE_SKU + UINT16 DefineMaxTxPwr; +#endif // SINGLE_SKU // + + +} COMMON_CONFIG, *PCOMMON_CONFIG; + + +#ifdef CONFIG_STA_SUPPORT +/* Modified by Wu Xi-Kun 4/21/2006 */ +// STA configuration and status +typedef struct _STA_ADMIN_CONFIG { + // GROUP 1 - + // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe + // the user intended configuration, but not necessary fully equal to the final + // settings in ACTIVE BSS after negotiation/compromize with the BSS holder (either + // AP or IBSS holder). + // Once initialized, user configuration can only be changed via OID_xxx + UCHAR BssType; // BSS_INFRA or BSS_ADHOC + USHORT AtimWin; // used when starting a new IBSS + + // GROUP 2 - + // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe + // the user intended configuration, and should be always applied to the final + // settings in ACTIVE BSS without compromising with the BSS holder. + // Once initialized, user configuration can only be changed via OID_xxx + UCHAR RssiTrigger; + UCHAR RssiTriggerMode; // RSSI_TRIGGERED_UPON_BELOW_THRESHOLD or RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD + USHORT DefaultListenCount; // default listen count; + ULONG WindowsPowerMode; // Power mode for AC power + ULONG WindowsBatteryPowerMode; // Power mode for battery if exists + BOOLEAN bWindowsACCAMEnable; // Enable CAM power mode when AC on + BOOLEAN bAutoReconnect; // Set to TRUE when setting OID_802_11_SSID with no matching BSSID + ULONG WindowsPowerProfile; // Windows power profile, for NDIS5.1 PnP + + // MIB:ieee802dot11.dot11smt(1).dot11StationConfigTable(1) + USHORT Psm; // power management mode (PWR_ACTIVE|PWR_SAVE) + USHORT DisassocReason; + UCHAR DisassocSta[MAC_ADDR_LEN]; + USHORT DeauthReason; + UCHAR DeauthSta[MAC_ADDR_LEN]; + USHORT AuthFailReason; + UCHAR AuthFailSta[MAC_ADDR_LEN]; + + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X + NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS OrigWepStatus; // Original wep status set from OID + + // Add to support different cipher suite for WPA2/WPA mode + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Multicast cipher suite + NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher suite + BOOLEAN bMixCipher; // Indicate current Pair & Group use different cipher suites + USHORT RsnCapability; + + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + + UCHAR PMK[32]; // WPA PSK mode PMK + UCHAR PTK[64]; // WPA PSK mode PTK + UCHAR GTK[32]; // GTK from authenticator + BSSID_INFO SavedPMK[PMKID_NO]; + UINT SavedPMKNum; // Saved PMKID number + + UCHAR DefaultKeyId; + + + // WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED + UCHAR PortSecured; + + // For WPA countermeasures + ULONG LastMicErrorTime; // record last MIC error time + ULONG MicErrCnt; // Should be 0, 1, 2, then reset to zero (after disassoiciation). + BOOLEAN bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred. + // For WPA-PSK supplicant state + WPA_STATE WpaState; // Default is SS_NOTUSE and handled by microsoft 802.1x + UCHAR ReplayCounter[8]; + UCHAR ANonce[32]; // ANonce for WPA-PSK from aurhenticator + UCHAR SNonce[32]; // SNonce for WPA-PSK + + UCHAR LastSNR0; // last received BEACON's SNR + UCHAR LastSNR1; // last received BEACON's SNR for 2nd antenna + RSSI_SAMPLE RssiSample; + ULONG NumOfAvgRssiSample; + + ULONG LastBeaconRxTime; // OS's timestamp of the last BEACON RX time + ULONG Last11bBeaconRxTime; // OS's timestamp of the last 11B BEACON RX time + ULONG Last11gBeaconRxTime; // OS's timestamp of the last 11G BEACON RX time + ULONG Last20NBeaconRxTime; // OS's timestamp of the last 20MHz N BEACON RX time + + ULONG LastScanTime; // Record last scan time for issue BSSID_SCAN_LIST + ULONG ScanCnt; // Scan counts since most recent SSID, BSSID, SCAN OID request + BOOLEAN bSwRadio; // Software controlled Radio On/Off, TRUE: On + BOOLEAN bHwRadio; // Hardware controlled Radio On/Off, TRUE: On + BOOLEAN bRadio; // Radio state, And of Sw & Hw radio state + BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled + BOOLEAN bShowHiddenSSID; // Show all known SSID in SSID list get operation + + //BOOLEAN AdhocBOnlyJoined; // Indicate Adhoc B Join. + //BOOLEAN AdhocBGJoined; // Indicate Adhoc B/G Join. + //BOOLEAN Adhoc20NJoined; // Indicate Adhoc 20MHz N Join. + + // New for WPA, windows want us to to keep association information and + // Fixed IEs from last association response + NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo; + USHORT ReqVarIELen; // Length of next VIE include EID & Length + UCHAR ReqVarIEs[MAX_VIE_LEN]; // The content saved here should be little-endian format. + USHORT ResVarIELen; // Length of next VIE include EID & Length + UCHAR ResVarIEs[MAX_VIE_LEN]; + + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; // The content saved here should be little-endian format. + + // New variables used for CCX 1.0 + BOOLEAN bCkipOn; + BOOLEAN bCkipCmicOn; + UCHAR CkipFlag; + UCHAR GIV[3]; //for CCX iv + UCHAR RxSEQ[4]; + UCHAR TxSEQ[4]; + UCHAR CKIPMIC[4]; + UCHAR LeapAuthMode; + LEAP_AUTH_INFO LeapAuthInfo; + UCHAR HashPwd[16]; + UCHAR NetworkChallenge[8]; + UCHAR NetworkChallengeResponse[24]; + UCHAR PeerChallenge[8]; + + UCHAR PeerChallengeResponse[24]; + UCHAR SessionKey[16]; //Network session keys (NSK) + RALINK_TIMER_STRUCT LeapAuthTimer; + ROGUEAP_TABLE RogueApTab; //Cisco CCX1 Rogue AP Detection + + // New control flags for CCX + CCX_CONTROL CCXControl; // Master administration state + BOOLEAN CCXEnable; // Actual CCX state + UCHAR CCXScanChannel; // Selected channel for CCX beacon request + USHORT CCXScanTime; // Time out to wait for beacon and probe response + UCHAR CCXReqType; // Current processing CCX request type + BSS_TABLE CCXBssTab; // BSS Table + UCHAR FrameReportBuf[2048]; // Buffer for creating frame report + USHORT FrameReportLen; // Current Frame report length + ULONG CLBusyBytes; // Save the total bytes received durning channel load scan time + USHORT RPIDensity[8]; // Array for RPI density collection + // Start address of each BSS table within FrameReportBuf + // It's important to update the RxPower of the corresponding Bss + USHORT BssReportOffset[MAX_LEN_OF_BSS_TABLE]; + USHORT BeaconToken; // Token for beacon report + ULONG LastBssIndex; // Most current reported Bss index + RM_REQUEST_ACTION MeasurementRequest[16]; // Saved measurement request + UCHAR RMReqCnt; // Number of measurement request saved. + UCHAR CurrentRMReqIdx; // Number of measurement request saved. + BOOLEAN ParallelReq; // Parallel measurement, only one request performed, + // It must be the same channel with maximum duration + USHORT ParallelDuration; // Maximum duration for parallel measurement + UCHAR ParallelChannel; // Only one channel with parallel measurement + USHORT IAPPToken; // IAPP dialog token + UCHAR CCXQosECWMin; // Cisco QOS ECWMin for AC 0 + UCHAR CCXQosECWMax; // Cisco QOS ECWMax for AC 0 + // Hack for channel load and noise histogram parameters + UCHAR NHFactor; // Parameter for Noise histogram + UCHAR CLFactor; // Parameter for channel load + + UCHAR KRK[16]; //Key Refresh Key. + UCHAR BTK[32]; //Base Transient Key + BOOLEAN CCKMLinkUpFlag; + ULONG CCKMRN; //(Re)Association request number. + LARGE_INTEGER CCKMBeaconAtJoinTimeStamp; //TSF timer for Re-assocaite to the new AP + UCHAR AironetCellPowerLimit; //in dBm + UCHAR AironetIPAddress[4]; //eg. 192.168.1.1 + BOOLEAN CCXAdjacentAPReportFlag; //flag for determining report Assoc Lost time + CHAR CCXAdjacentAPSsid[MAX_LEN_OF_SSID]; //Adjacent AP's SSID report + UCHAR CCXAdjacentAPSsidLen; // the actual ssid length in used + UCHAR CCXAdjacentAPBssid[MAC_ADDR_LEN]; //Adjacent AP's BSSID report + USHORT CCXAdjacentAPChannel; + ULONG CCXAdjacentAPLinkDownTime; //for Spec S32. + + RALINK_TIMER_STRUCT StaQuickResponeForRateUpTimer; + BOOLEAN StaQuickResponeForRateUpTimerRunning; + + UCHAR DtimCount; // 0.. DtimPeriod-1 + UCHAR DtimPeriod; // default = 3 + +#ifdef QOS_DLS_SUPPORT + RT_802_11_DLS DLSEntry[MAX_NUM_OF_DLS_ENTRY]; + UCHAR DlsReplayCounter[8]; +#endif // QOS_DLS_SUPPORT // + //////////////////////////////////////////////////////////////////////////////////////// + // This is only for WHQL test. + BOOLEAN WhqlTest; + //////////////////////////////////////////////////////////////////////////////////////// + + RALINK_TIMER_STRUCT WpaDisassocAndBlockAssocTimer; + // Fast Roaming + BOOLEAN bFastRoaming; // 0:disable fast roaming, 1:enable fast roaming + CHAR dBmToRoam; // the condition to roam when receiving Rssi less than this value. It's negative value. + +#ifdef WPA_SUPPLICANT_SUPPORT + BOOLEAN IEEE8021X; + BOOLEAN IEEE8021x_required_keys; + CIPHER_KEY DesireSharedKey[4]; // Record user desired WEP keys + UCHAR DesireSharedKeyId; + + // 0: driver ignores wpa_supplicant + // 1: wpa_supplicant initiates scanning and AP selection + // 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters + UCHAR WpaSupplicantUP; + UCHAR WpaSupplicantScanCount; +#endif // WPA_SUPPLICANT_SUPPORT // + + CHAR dev_name[16]; + USHORT OriDevType; + + BOOLEAN bTGnWifiTest; + BOOLEAN bScanReqIsFromWebUI; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + + +#ifdef EXT_BUILD_CHANNEL_LIST + UCHAR IEEE80211dClientMode; + UCHAR StaOriCountryCode[3]; + UCHAR StaOriGeography; +#endif // EXT_BUILD_CHANNEL_LIST // +} STA_ADMIN_CONFIG, *PSTA_ADMIN_CONFIG; + +// This data structure keep the current active BSS/IBSS's configuration that this STA +// had agreed upon joining the network. Which means these parameters are usually decided +// by the BSS/IBSS creator instead of user configuration. Data in this data structurre +// is valid only when either ADHOC_ON(pAd) or INFRA_ON(pAd) is TRUE. +// Normally, after SCAN or failed roaming attempts, we need to recover back to +// the current active settings. +typedef struct _STA_ACTIVE_CONFIG { + USHORT Aid; + USHORT AtimWin; // in kusec; IBSS parameter set element + USHORT CapabilityInfo; + USHORT CfpMaxDuration; + USHORT CfpPeriod; + + // Copy supported rate from desired AP's beacon. We are trying to match + // AP's supported and extended rate settings. + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRateLen; + // Copy supported ht from desired AP's beacon. We are trying to match + RT_HT_PHY_INFO SupportedPhyInfo; + RT_HT_CAPABILITY SupportedHtPhy; +} STA_ACTIVE_CONFIG, *PSTA_ACTIVE_CONFIG; +#endif // CONFIG_STA_SUPPORT // + +#ifdef RT2870 +typedef struct RT_ADD_PAIRWISE_KEY_ENTRY { + NDIS_802_11_MAC_ADDRESS MacAddr; + USHORT MacTabMatchWCID; // ASIC + CIPHER_KEY CipherKey; +} RT_ADD_PAIRWISE_KEY_ENTRY,*PRT_ADD_PAIRWISE_KEY_ENTRY; +#endif // RT2870 // + +// ----------- start of AP -------------------------- +// AUTH-RSP State Machine Aux data structure +typedef struct _AP_MLME_AUX { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg; + CHAR Challenge[CIPHER_TEXT_LEN]; +} AP_MLME_AUX, *PAP_MLME_AUX; + +// structure to define WPA Group Key Rekey Interval +typedef struct PACKED _RT_802_11_WPA_REKEY { + ULONG ReKeyMethod; // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based + ULONG ReKeyInterval; // time-based: seconds, packet-based: kilo-packets +} RT_WPA_REKEY,*PRT_WPA_REKEY, RT_802_11_WPA_REKEY, *PRT_802_11_WPA_REKEY; + +typedef struct _MAC_TABLE_ENTRY { + //Choose 1 from ValidAsWDS and ValidAsCLI to validize. + BOOLEAN ValidAsCLI; // Sta mode, set this TRUE after Linkup,too. + BOOLEAN ValidAsWDS; // This is WDS Entry. only for AP mode. + BOOLEAN ValidAsApCli; //This is a AP-Client entry, only for AP mode which enable AP-Client functions. + BOOLEAN ValidAsMesh; + BOOLEAN ValidAsDls; // This is DLS Entry. only for STA mode. + BOOLEAN isCached; + BOOLEAN bIAmBadAtheros; + + UCHAR EnqueueEapolStartTimerRunning; // Enqueue EAPoL-Start for triggering EAP SM + //jan for wpa + // record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB + UCHAR CMTimerRunning; + UCHAR apidx; // MBSS number + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; + UCHAR ANonce[LEN_KEY_DESC_NONCE]; + UCHAR R_Counter[LEN_KEY_DESC_REPLAY]; + UCHAR PTK[64]; + UCHAR ReTryCounter; + RALINK_TIMER_STRUCT RetryTimer; + RALINK_TIMER_STRUCT EnqueueStartForPSKTimer; // A timer which enqueue EAPoL-Start for triggering PSK SM + NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined + NDIS_802_11_WEP_STATUS WepStatus; + AP_WPA_STATE WpaState; + GTK_STATE GTKState; + USHORT PortSecured; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X + CIPHER_KEY PairwiseKey; + PVOID pAd; + INT PMKID_CacheIdx; + UCHAR PMKID[LEN_PMKID]; + + + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR PsMode; + SST Sst; + AUTH_STATE AuthState; // for SHARED KEY authentication state machine used only + BOOLEAN IsReassocSta; // Indicate whether this is a reassociation procedure + USHORT Aid; + USHORT CapabilityInfo; + UCHAR LastRssi; + ULONG NoDataIdleCount; + UINT16 StationKeepAliveCount; // unit: second + ULONG PsQIdleCount; + QUEUE_HEADER PsQueue; + + UINT32 StaConnectTime; // the live time of this station since associated with AP + + +#ifdef DOT11_N_SUPPORT + BOOLEAN bSendBAR; + USHORT NoBADataCountDown; + + UINT32 CachedBuf[16]; // UINT (4 bytes) for alignment + UINT TxBFCount; // 3*3 +#endif // DOT11_N_SUPPORT // + UINT FIFOCount; + UINT DebugFIFOCount; + UINT DebugTxCount; + BOOLEAN bDlsInit; + + +//==================================================== +//WDS entry needs these +// rt2860 add this. if ValidAsWDS==TRUE, MatchWDSTabIdx is the index in WdsTab.MacTab + UINT MatchWDSTabIdx; + UCHAR MaxSupportedRate; + UCHAR CurrTxRate; + UCHAR CurrTxRateIndex; + // to record the each TX rate's quality. 0 is best, the bigger the worse. + USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH]; +// USHORT OneSecTxOkCount; + UINT32 OneSecTxNoRetryOkCount; + UINT32 OneSecTxRetryOkCount; + UINT32 OneSecTxFailCount; + UINT32 ContinueTxFailCnt; + UINT32 CurrTxRateStableTime; // # of second in current TX rate + UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition +//==================================================== + + + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT + UINT MatchDlsEntryIdx; // indicate the index in pAd->StaCfg.DLSEntry +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + + BOOLEAN fNoisyEnvironment; + BOOLEAN fLastSecAccordingRSSI; + UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down + CHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction + ULONG LastTxOkCount; + UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH]; + + // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular + // BOOLEAN control, either ON or OFF. These flags should always be accessed via + // CLIENT_STATUS_TEST_FLAG(), CLIENT_STATUS_SET_FLAG(), CLIENT_STATUS_CLEAR_FLAG() macros. + // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition. fCLIENT_STATUS_AMSDU_INUSED + ULONG ClientStatusFlags; + + // TODO: Shall we move that to DOT11_N_SUPPORT??? + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI. + +#ifdef DOT11_N_SUPPORT + // HT EWC MIMO-N used parameters + USHORT RXBAbitmap; // fill to on-chip RXWI_BA_BITMASK in 8.1.3RX attribute entry format + USHORT TXBAbitmap; // This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI + USHORT TXAutoBAbitmap; + USHORT BADeclineBitmap; + USHORT BARecWcidArray[NUM_OF_TID]; // The mapping wcid of recipient session. if RXBAbitmap bit is masked + USHORT BAOriWcidArray[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked + USHORT BAOriSequence[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked + + // 802.11n features. + UCHAR MpduDensity; + UCHAR MaxRAmpduFactor; + UCHAR AMsduSize; + UCHAR MmpsMode; // MIMO power save more. + + HT_CAPABILITY_IE HTCapability; + +#ifdef DOT11N_DRAFT3 + UCHAR BSS2040CoexistenceMgmtSupport; +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + + BOOLEAN bAutoTxRateSwitch; + + UCHAR RateLen; + struct _MAC_TABLE_ENTRY *pNext; + USHORT TxSeq[NUM_OF_TID]; + USHORT NonQosDataSeq; + + RSSI_SAMPLE RssiSample; + + UINT32 TXMCSExpected[16]; + UINT32 TXMCSSuccessful[16]; + UINT32 TXMCSFailed[16]; + UINT32 TXMCSAutoFallBack[16][16]; + +#ifdef CONFIG_STA_SUPPORT + ULONG LastBeaconRxTime; +#endif // CONFIG_STA_SUPPORT // +} MAC_TABLE_ENTRY, *PMAC_TABLE_ENTRY; + +typedef struct _MAC_TABLE { + USHORT Size; + MAC_TABLE_ENTRY *Hash[HASH_TABLE_SIZE]; + MAC_TABLE_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; + QUEUE_HEADER McastPsQueue; + ULONG PsQIdleCount; + BOOLEAN fAnyStationInPsm; + BOOLEAN fAnyStationBadAtheros; // Check if any Station is atheros 802.11n Chip. We need to use RTS/CTS with Atheros 802,.11n chip. + BOOLEAN fAnyTxOPForceDisable; // Check if it is necessary to disable BE TxOP + BOOLEAN fAllStationAsRalink; // Check if all stations are ralink-chipset +#ifdef DOT11_N_SUPPORT + BOOLEAN fAnyStationIsLegacy; // Check if I use legacy rate to transmit to my BSS Station/ + BOOLEAN fAnyStationNonGF; // Check if any Station can't support GF. + BOOLEAN fAnyStation20Only; // Check if any Station can't support GF. + BOOLEAN fAnyStationMIMOPSDynamic; // Check if any Station is MIMO Dynamic + BOOLEAN fAnyBASession; // Check if there is BA session. Force turn on RTS/CTS +#endif // DOT11_N_SUPPORT // +} MAC_TABLE, *PMAC_TABLE; + +#ifdef DOT11_N_SUPPORT +#define IS_HT_STA(_pMacEntry) \ + (_pMacEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX) + +#define IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + +#define PEER_IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) +#endif // DOT11_N_SUPPORT // + +typedef struct _WDS_ENTRY { + BOOLEAN Valid; + UCHAR Addr[MAC_ADDR_LEN]; + ULONG NoDataIdleCount; + struct _WDS_ENTRY *pNext; +} WDS_ENTRY, *PWDS_ENTRY; + +typedef struct _WDS_TABLE_ENTRY { + USHORT Size; + UCHAR WdsAddr[MAC_ADDR_LEN]; + WDS_ENTRY *Hash[HASH_TABLE_SIZE]; + WDS_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; + UCHAR MaxSupportedRate; + UCHAR CurrTxRate; + USHORT TxQuality[MAX_LEN_OF_SUPPORTED_RATES]; + USHORT OneSecTxOkCount; + USHORT OneSecTxRetryOkCount; + USHORT OneSecTxFailCount; + ULONG CurrTxRateStableTime; // # of second in current TX rate + UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition +} WDS_TABLE_ENTRY, *PWDS_TABLE_ENTRY; + +typedef struct _RT_802_11_WDS_ENTRY { + PNET_DEV dev; + UCHAR Valid; + UCHAR PhyMode; + UCHAR PeerWdsAddr[MAC_ADDR_LEN]; + UCHAR MacTabMatchWCID; // ASIC + NDIS_802_11_WEP_STATUS WepStatus; + UCHAR KeyIdx; + CIPHER_KEY WdsKey; + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. +} RT_802_11_WDS_ENTRY, *PRT_802_11_WDS_ENTRY; + +typedef struct _WDS_TABLE { + UCHAR Mode; + ULONG Size; + RT_802_11_WDS_ENTRY WdsEntry[MAX_WDS_ENTRY]; +} WDS_TABLE, *PWDS_TABLE; + +typedef struct _APCLI_STRUCT { + PNET_DEV dev; +#ifdef RTL865X_SOC + unsigned int mylinkid; +#endif + BOOLEAN Enable; // Set it as 1 if the apcli interface was configured to "1" or by iwpriv cmd "ApCliEnable" + BOOLEAN Valid; // Set it as 1 if the apcli interface associated success to remote AP. + UCHAR MacTabWCID; //WCID value, which point to the entry of ASIC Mac table. + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + + UCHAR CfgSsidLen; + CHAR CfgSsid[MAX_LEN_OF_SSID]; + UCHAR CfgApCliBssid[ETH_LENGTH_OF_ADDRESS]; + UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS]; + + ULONG ApCliRcvBeaconTime; + + ULONG CtrlCurrState; + ULONG SyncCurrState; + ULONG AuthCurrState; + ULONG AssocCurrState; + ULONG WpaPskCurrState; + + USHORT AuthReqCnt; + USHORT AssocReqCnt; + + ULONG ClientStatusFlags; + UCHAR MpduDensity; + + NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined + NDIS_802_11_WEP_STATUS WepStatus; + + // Add to support different cipher suite for WPA2/WPA mode + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Multicast cipher suite + NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher suite + BOOLEAN bMixCipher; // Indicate current Pair & Group use different cipher suites + USHORT RsnCapability; + + UCHAR PSK[100]; // reserve PSK key material + UCHAR PSKLen; + UCHAR PMK[32]; // WPA PSK mode PMK + //UCHAR PTK[64]; // WPA PSK mode PTK + UCHAR GTK[32]; // GTK from authenticator + + //CIPHER_KEY PairwiseKey; + CIPHER_KEY SharedKey[SHARE_KEY_NUM]; + UCHAR DefaultKeyId; + + // WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED + //UCHAR PortSecured; + + // store RSN_IE built by driver + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; // The content saved here should be convert to little-endian format. + UCHAR RSNIE_Len; + + // For WPA countermeasures + ULONG LastMicErrorTime; // record last MIC error time + //ULONG MicErrCnt; // Should be 0, 1, 2, then reset to zero (after disassoiciation). + BOOLEAN bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred. + + // For WPA-PSK supplicant state + //WPA_STATE WpaState; // Default is SS_NOTUSE + //UCHAR ReplayCounter[8]; + //UCHAR ANonce[32]; // ANonce for WPA-PSK from authenticator + UCHAR SNonce[32]; // SNonce for WPA-PSK + UCHAR GNonce[32]; // GNonce for WPA-PSK from authenticator + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; + RT_HT_PHY_INFO DesiredHtPhyInfo; + BOOLEAN bAutoTxRateSwitch; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. +} APCLI_STRUCT, *PAPCLI_STRUCT; + +// ----------- end of AP ---------------------------- + +#ifdef BLOCK_NET_IF +typedef struct _BLOCK_QUEUE_ENTRY +{ + BOOLEAN SwTxQueueBlockFlag; + LIST_HEADER NetIfList; +} BLOCK_QUEUE_ENTRY, *PBLOCK_QUEUE_ENTRY; +#endif // BLOCK_NET_IF // + + +struct wificonf +{ + BOOLEAN bShortGI; + BOOLEAN bGreenField; +}; + + + + +typedef struct _INF_PCI_CONFIG +{ + PUCHAR CSRBaseAddress; // PCI MMIO Base Address, all access will use +}INF_PCI_CONFIG; + +typedef struct _INF_USB_CONFIG +{ + UINT BulkInEpAddr; // bulk-in endpoint address + UINT BulkOutEpAddr[6]; // bulk-out endpoint address + +}INF_USB_CONFIG; + +#ifdef IKANOS_VX_1X0 + typedef void (*IkanosWlanTxCbFuncP)(void *, void *); + + struct IKANOS_TX_INFO + { + struct net_device *netdev; + IkanosWlanTxCbFuncP *fp; + }; +#endif // IKANOS_VX_1X0 // + +#ifdef NINTENDO_AP +typedef struct _NINDO_CTRL_BLOCK { + + RT_NINTENDO_TABLE DS_TABLE; + +#ifdef CHIP25XX + spinlock_t NINTENDO_TABLE_Lock; +#else + NDIS_SPIN_LOCK NINTENDO_TABLE_Lock; +#endif // CHIP25XX // + + UCHAR NINTENDO_UP_BUFFER[512]; + UCHAR Local_KeyIdx; + CIPHER_KEY Local_SharedKey; + UCHAR Local_bHideSsid; + UCHAR Local_AuthMode; + UCHAR Local_WepStatus; + USHORT Local_CapabilityInfo; +} NINDO_CTRL_BLOCK; +#endif // NINTENDO_AP // + + +#ifdef DBG_DIAGNOSE +#define DIAGNOSE_TIME 10 // 10 sec +typedef struct _RtmpDiagStrcut_ +{ // Diagnosis Related element + unsigned char inited; + unsigned char qIdx; + unsigned char ArrayStartIdx; + unsigned char ArrayCurIdx; + // Tx Related Count + USHORT TxDataCnt[DIAGNOSE_TIME]; + USHORT TxFailCnt[DIAGNOSE_TIME]; +// USHORT TxDescCnt[DIAGNOSE_TIME][16]; // TxDesc queue length in scale of 0~14, >=15 + USHORT TxDescCnt[DIAGNOSE_TIME][24]; // 3*3 // TxDesc queue length in scale of 0~14, >=15 +// USHORT TxMcsCnt[DIAGNOSE_TIME][16]; // TxDate MCS Count in range from 0 to 15, step in 1. + USHORT TxMcsCnt[DIAGNOSE_TIME][24]; // 3*3 + USHORT TxSWQueCnt[DIAGNOSE_TIME][9]; // TxSwQueue length in scale of 0, 1, 2, 3, 4, 5, 6, 7, >=8 + + USHORT TxAggCnt[DIAGNOSE_TIME]; + USHORT TxNonAggCnt[DIAGNOSE_TIME]; +// USHORT TxAMPDUCnt[DIAGNOSE_TIME][16]; // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1. + USHORT TxAMPDUCnt[DIAGNOSE_TIME][24]; // 3*3 // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1. + USHORT TxRalinkCnt[DIAGNOSE_TIME]; // TxRalink Aggregation Count in 1 sec scale. + USHORT TxAMSDUCnt[DIAGNOSE_TIME]; // TxAMSUD Aggregation Count in 1 sec scale. + + // Rx Related Count + USHORT RxDataCnt[DIAGNOSE_TIME]; // Rx Total Data count. + USHORT RxCrcErrCnt[DIAGNOSE_TIME]; +// USHORT RxMcsCnt[DIAGNOSE_TIME][16]; // Rx MCS Count in range from 0 to 15, step in 1. + USHORT RxMcsCnt[DIAGNOSE_TIME][24]; // 3*3 +}RtmpDiagStruct; +#endif // DBG_DIAGNOSE // + + +// +// The miniport adapter structure +// +typedef struct _RTMP_ADAPTER +{ + PVOID OS_Cookie; // save specific structure relative to OS + PNET_DEV net_dev; + ULONG VirtualIfCnt; + + + + NDIS_SPIN_LOCK irq_lock; + UCHAR irq_disabled; + +#ifdef RT2870 +/*****************************************************************************************/ +/* USB related parameters */ +/*****************************************************************************************/ + struct usb_config_descriptor *config; + UINT BulkInEpAddr; // bulk-in endpoint address + UINT BulkOutEpAddr[6]; // bulk-out endpoint address + + UINT NumberOfPipes; + USHORT BulkOutMaxPacketSize; + USHORT BulkInMaxPacketSize; + + //======Control Flags + LONG PendingIoCount; + ULONG BulkFlags; + BOOLEAN bUsbTxBulkAggre; // Flags for bulk out data priority + + + //======Timer Thread + RT2870_TIMER_QUEUE TimerQ; + NDIS_SPIN_LOCK TimerQLock; + + + //======Cmd Thread + CmdQ CmdQ; + NDIS_SPIN_LOCK CmdQLock; // CmdQLock spinlock + + BOOLEAN TimerFunc_kill; + BOOLEAN mlme_kill; + + + //======Semaphores (event) + struct semaphore mlme_semaphore; /* to sleep thread on */ + struct semaphore RTUSBCmd_semaphore; /* to sleep thread on */ + struct semaphore RTUSBTimer_semaphore; +#ifdef INF_AMAZON_SE + struct semaphore UsbVendorReq_semaphore; + PVOID UsbVendorReqBuf; +#endif // INF_AMAZON_SE // + struct completion TimerQComplete; + struct completion mlmeComplete; + struct completion CmdQComplete; + wait_queue_head_t *wait; + + //======Lock for 2870 ATE +#ifdef RALINK_ATE + NDIS_SPIN_LOCK GenericLock; // ATE Tx/Rx generic spinlock +#endif // RALINK_ATE // + +#endif // RT2870 // + + +/*****************************************************************************************/ + /* Both PCI/USB related parameters */ +/*****************************************************************************************/ + + +/*****************************************************************************************/ +/* Tx related parameters */ +/*****************************************************************************************/ + BOOLEAN DeQueueRunning[NUM_OF_TX_RING]; // for ensuring RTUSBDeQueuePacket get call once + NDIS_SPIN_LOCK DeQueueLock[NUM_OF_TX_RING]; + +#ifdef RT2870 + // Data related context and AC specified, 4 AC supported + NDIS_SPIN_LOCK BulkOutLock[6]; // BulkOut spinlock for 4 ACs + NDIS_SPIN_LOCK MLMEBulkOutLock; // MLME BulkOut lock + + HT_TX_CONTEXT TxContext[NUM_OF_TX_RING]; + NDIS_SPIN_LOCK TxContextQueueLock[NUM_OF_TX_RING]; // TxContextQueue spinlock + + // 4 sets of Bulk Out index and pending flag + UCHAR NextBulkOutIndex[4]; // only used for 4 EDCA bulkout pipe + + BOOLEAN BulkOutPending[6]; // used for total 6 bulkout pipe + UCHAR bulkResetPipeid; + BOOLEAN MgmtBulkPending; + ULONG bulkResetReq[6]; +#endif // RT2870 // + + // resource for software backlog queues + QUEUE_HEADER TxSwQueue[NUM_OF_TX_RING]; // 4 AC + 1 HCCA + NDIS_SPIN_LOCK TxSwQueueLock[NUM_OF_TX_RING]; // TxSwQueue spinlock + + RTMP_DMABUF MgmtDescRing; // Shared memory for MGMT descriptors + RTMP_MGMT_RING MgmtRing; + NDIS_SPIN_LOCK MgmtRingLock; // Prio Ring spinlock + + +/*****************************************************************************************/ +/* Rx related parameters */ +/*****************************************************************************************/ + + +#ifdef RT2870 + RX_CONTEXT RxContext[RX_RING_SIZE]; // 1 for redundant multiple IRP bulk in. + NDIS_SPIN_LOCK BulkInLock; // BulkIn spinlock for 4 ACs + UCHAR PendingRx; // The Maxima pending Rx value should be RX_RING_SIZE. + UCHAR NextRxBulkInIndex; // Indicate the current RxContext Index which hold by Host controller. + UCHAR NextRxBulkInReadIndex; // Indicate the current RxContext Index which driver can read & process it. + ULONG NextRxBulkInPosition; // Want to contatenate 2 URB buffer while 1st is bulkin failed URB. This Position is 1st URB TransferLength. + ULONG TransferBufferLength; // current length of the packet buffer + ULONG ReadPosition; // current read position in a packet buffer +#endif // RT2870 // + + +/*****************************************************************************************/ +/* ASIC related parameters */ +/*****************************************************************************************/ + UINT32 MACVersion; // MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101).. + + // --------------------------- + // E2PROM + // --------------------------- + ULONG EepromVersion; // byte 0: version, byte 1: revision, byte 2~3: unused + UCHAR EEPROMAddressNum; // 93c46=6 93c66=8 + USHORT EEPROMDefaultValue[NUM_EEPROM_BBP_PARMS]; + BOOLEAN EepromAccess; + UCHAR EFuseTag; + ULONG FirmwareVersion; // byte 0: Minor version, byte 1: Major version, otherwise unused. + + // --------------------------- + // BBP Control + // --------------------------- + UCHAR BbpWriteLatch[140]; // record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID + UCHAR BbpRssiToDbmDelta; + BBP_R66_TUNING BbpTuning; + + // ---------------------------- + // RFIC control + // ---------------------------- + UCHAR RfIcType; // RFIC_xxx + ULONG RfFreqOffset; // Frequency offset for channel switching + RTMP_RF_REGS LatchRfRegs; // latch th latest RF programming value since RF IC doesn't support READ + + EEPROM_ANTENNA_STRUC Antenna; // Since ANtenna definition is different for a & g. We need to save it for future reference. + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + + // This soft Rx Antenna Diversity mechanism is used only when user set + // RX Antenna = DIVERSITY ON + SOFT_RX_ANT_DIVERSITY RxAnt; + + UCHAR RFProgSeq; + CHANNEL_TX_POWER TxPower[MAX_NUM_OF_CHANNELS]; // Store Tx power value for all channels. + CHANNEL_TX_POWER ChannelList[MAX_NUM_OF_CHANNELS]; // list all supported channels for site survey + CHANNEL_11J_TX_POWER TxPower11J[MAX_NUM_OF_11JCHANNELS]; // 802.11j channel and bw + CHANNEL_11J_TX_POWER ChannelList11J[MAX_NUM_OF_11JCHANNELS]; // list all supported channels for site survey + + UCHAR ChannelListNum; // number of channel in ChannelList[] + UCHAR Bbp94; + BOOLEAN BbpForCCK; + ULONG Tx20MPwrCfgABand[5]; + ULONG Tx20MPwrCfgGBand[5]; + ULONG Tx40MPwrCfgABand[5]; + ULONG Tx40MPwrCfgGBand[5]; + + BOOLEAN bAutoTxAgcA; // Enable driver auto Tx Agc control + UCHAR TssiRefA; // Store Tssi reference value as 25 temperature. + UCHAR TssiPlusBoundaryA[5]; // Tssi boundary for increase Tx power to compensate. + UCHAR TssiMinusBoundaryA[5]; // Tssi boundary for decrease Tx power to compensate. + UCHAR TxAgcStepA; // Store Tx TSSI delta increment / decrement value + CHAR TxAgcCompensateA; // Store the compensation (TxAgcStep * (idx-1)) + + BOOLEAN bAutoTxAgcG; // Enable driver auto Tx Agc control + UCHAR TssiRefG; // Store Tssi reference value as 25 temperature. + UCHAR TssiPlusBoundaryG[5]; // Tssi boundary for increase Tx power to compensate. + UCHAR TssiMinusBoundaryG[5]; // Tssi boundary for decrease Tx power to compensate. + UCHAR TxAgcStepG; // Store Tx TSSI delta increment / decrement value + CHAR TxAgcCompensateG; // Store the compensation (TxAgcStep * (idx-1)) + + //+++For RT2870, the parameteres is start from BGRssiOffset1 ~ BGRssiOffset3 + CHAR BGRssiOffset0; // Store B/G RSSI#0 Offset value on EEPROM 0x46h + CHAR BGRssiOffset1; // Store B/G RSSI#1 Offset value + CHAR BGRssiOffset2; // Store B/G RSSI#2 Offset value + //--- + + //+++For RT2870, the parameteres is start from ARssiOffset1 ~ ARssiOffset3 + CHAR ARssiOffset0; // Store A RSSI#0 Offset value on EEPROM 0x4Ah + CHAR ARssiOffset1; // Store A RSSI#1 Offset value + CHAR ARssiOffset2; // Store A RSSI#2 Offset value + //--- + + CHAR BLNAGain; // Store B/G external LNA#0 value on EEPROM 0x44h + CHAR ALNAGain0; // Store A external LNA#0 value for ch36~64 + CHAR ALNAGain1; // Store A external LNA#1 value for ch100~128 + CHAR ALNAGain2; // Store A external LNA#2 value for ch132~165 + + // ---------------------------- + // LED control + // ---------------------------- + MCU_LEDCS_STRUC LedCntl; + USHORT Led1; // read from EEPROM 0x3c + USHORT Led2; // EEPROM 0x3e + USHORT Led3; // EEPROM 0x40 + UCHAR LedIndicatorStregth; + UCHAR RssiSingalstrengthOffet; + BOOLEAN bLedOnScanning; + UCHAR LedStatus; + +/*****************************************************************************************/ +/* 802.11 related parameters */ +/*****************************************************************************************/ + // outgoing BEACON frame buffer and corresponding TXD + TXWI_STRUC BeaconTxWI; + PUCHAR BeaconBuf; + USHORT BeaconOffset[HW_BEACON_MAX_COUNT]; + + // pre-build PS-POLL and NULL frame upon link up. for efficiency purpose. + PSPOLL_FRAME PsPollFrame; + HEADER_802_11 NullFrame; + +#ifdef RT2870 + TX_CONTEXT BeaconContext[BEACON_RING_SIZE]; + TX_CONTEXT NullContext; + TX_CONTEXT PsPollContext; + TX_CONTEXT RTSContext; +#endif // RT2870 // + + + +//=========AP=========== + + +//=======STA=========== +#ifdef CONFIG_STA_SUPPORT +/* Modified by Wu Xi-Kun 4/21/2006 */ + // ----------------------------------------------- + // STA specific configuration & operation status + // used only when pAd->OpMode == OPMODE_STA + // ----------------------------------------------- + STA_ADMIN_CONFIG StaCfg; // user desired settings + STA_ACTIVE_CONFIG StaActive; // valid only when ADHOC_ON(pAd) || INFRA_ON(pAd) + CHAR nickname[IW_ESSID_MAX_SIZE+1]; // nickname, only used in the iwconfig i/f + NDIS_MEDIA_STATE PreMediaState; +#endif // CONFIG_STA_SUPPORT // + +//=======Common=========== + // OP mode: either AP or STA + UCHAR OpMode; // OPMODE_STA, OPMODE_AP + + NDIS_MEDIA_STATE IndicateMediaState; // Base on Indication state, default is NdisMediaStateDisConnected + + + // MAT related parameters + + // configuration: read from Registry & E2PROM + BOOLEAN bLocalAdminMAC; // Use user changed MAC + UCHAR PermanentAddress[MAC_ADDR_LEN]; // Factory default MAC address + UCHAR CurrentAddress[MAC_ADDR_LEN]; // User changed MAC address + + // ------------------------------------------------------ + // common configuration to both OPMODE_STA and OPMODE_AP + // ------------------------------------------------------ + COMMON_CONFIG CommonCfg; + MLME_STRUCT Mlme; + + // AP needs those vaiables for site survey feature. + MLME_AUX MlmeAux; // temporary settings used during MLME state machine + BSS_TABLE ScanTab; // store the latest SCAN result + + //About MacTab, the sta driver will use #0 and #1 for multicast and AP. + MAC_TABLE MacTab; // ASIC on-chip WCID entry table. At TX, ASIC always use key according to this on-chip table. + NDIS_SPIN_LOCK MacTabLock; + +#ifdef DOT11_N_SUPPORT + BA_TABLE BATable; +#endif // DOT11_N_SUPPORT // + NDIS_SPIN_LOCK BATabLock; + RALINK_TIMER_STRUCT RECBATimer; + + // encryption/decryption KEY tables + CIPHER_KEY SharedKey[MAX_MBSSID_NUM][4]; // STA always use SharedKey[BSS0][0..3] + + // RX re-assembly buffer for fragmentation + FRAGMENT_FRAME FragFrame; // Frame storage for fragment frame + + // various Counters + COUNTER_802_3 Counters8023; // 802.3 counters + COUNTER_802_11 WlanCounters; // 802.11 MIB counters + COUNTER_RALINK RalinkCounters; // Ralink propriety counters + COUNTER_DRS DrsCounters; // counters for Dynamic TX Rate Switching + PRIVATE_STRUC PrivateInfo; // Private information & counters + + // flags, see fRTMP_ADAPTER_xxx flags + ULONG Flags; // Represent current device status + + // current TX sequence # + USHORT Sequence; + +#ifdef UNDER_CE + NDIS_HANDLE hGiISR; +#endif + + + // Control disconnect / connect event generation + //+++Didn't used anymore + ULONG LinkDownTime; + //--- + ULONG LastRxRate; + ULONG LastTxRate; + //+++Used only for Station + BOOLEAN bConfigChanged; // Config Change flag for the same SSID setting + //--- + + ULONG ExtraInfo; // Extra information for displaying status + ULONG SystemErrorBitmap; // b0: E2PROM version error + + //+++Didn't used anymore + ULONG MacIcVersion; // MAC/BBP serial interface issue solved after ver.D + //--- + + // --------------------------- + // System event log + // --------------------------- + RT_802_11_EVENT_TABLE EventTab; + + + BOOLEAN HTCEnable; + + /*****************************************************************************************/ + /* Statistic related parameters */ + /*****************************************************************************************/ +#ifdef RT2870 + ULONG BulkOutDataOneSecCount; + ULONG BulkInDataOneSecCount; + ULONG BulkLastOneSecCount; // BulkOutDataOneSecCount + BulkInDataOneSecCount + ULONG watchDogRxCnt; + ULONG watchDogRxOverFlowCnt; + ULONG watchDogTxPendingCnt[NUM_OF_TX_RING]; +#endif // RT2870 // + + BOOLEAN bUpdateBcnCntDone; + ULONG watchDogMacDeadlock; // prevent MAC/BBP into deadlock condition + // ---------------------------- + // DEBUG paramerts + // ---------------------------- + //ULONG DebugSetting[4]; + BOOLEAN bBanAllBaSetup; + BOOLEAN bPromiscuous; + + // ---------------------------- + // rt2860c emulation-use Parameters + // ---------------------------- + ULONG rtsaccu[30]; + ULONG ctsaccu[30]; + ULONG cfendaccu[30]; + ULONG bacontent[16]; + ULONG rxint[RX_RING_SIZE+1]; + UCHAR rcvba[60]; + BOOLEAN bLinkAdapt; + BOOLEAN bForcePrintTX; + BOOLEAN bForcePrintRX; + BOOLEAN bDisablescanning; //defined in RT2870 USB + BOOLEAN bStaFifoTest; + BOOLEAN bProtectionTest; + BOOLEAN bHCCATest; + BOOLEAN bGenOneHCCA; + BOOLEAN bBroadComHT; + //+++Following add from RT2870 USB. + ULONG BulkOutReq; + ULONG BulkOutComplete; + ULONG BulkOutCompleteOther; + ULONG BulkOutCompleteCancel; // seems not use now? + ULONG BulkInReq; + ULONG BulkInComplete; + ULONG BulkInCompleteFail; + //--- + + struct wificonf WIFItestbed; + +#ifdef RALINK_ATE + ATE_INFO ate; +#ifdef RT2870 + BOOLEAN ContinBulkOut; //ATE bulk out control + BOOLEAN ContinBulkIn; //ATE bulk in control + atomic_t BulkOutRemained; + atomic_t BulkInRemained; +#endif // RT2870 // +#endif // RALINK_ATE // + +#ifdef DOT11_N_SUPPORT + struct reordering_mpdu_pool mpdu_blk_pool; +#endif // DOT11_N_SUPPORT // + + ULONG OneSecondnonBEpackets; // record non BE packets per second + +#if WIRELESS_EXT >= 12 + struct iw_statistics iw_stats; +#endif + + struct net_device_stats stats; + +#ifdef BLOCK_NET_IF + BLOCK_QUEUE_ENTRY blockQueueTab[NUM_OF_TX_RING]; +#endif // BLOCK_NET_IF // + + + +#ifdef MULTIPLE_CARD_SUPPORT + INT32 MC_RowID; + UCHAR MC_FileName[256]; +#endif // MULTIPLE_CARD_SUPPORT // + + ULONG TbttTickCount; +#ifdef PCI_MSI_SUPPORT + BOOLEAN HaveMsi; +#endif // PCI_MSI_SUPPORT // + + + UCHAR is_on; + +#define TIME_BASE (1000000/OS_HZ) +#define TIME_ONE_SECOND (1000000/TIME_BASE) + UCHAR flg_be_adjust; + ULONG be_adjust_last_time; + +#ifdef NINTENDO_AP + NINDO_CTRL_BLOCK nindo_ctrl_block; +#endif // NINTENDO_AP // + + +#ifdef IKANOS_VX_1X0 + struct IKANOS_TX_INFO IkanosTxInfo; + struct IKANOS_TX_INFO IkanosRxInfo[MAX_MBSSID_NUM + MAX_WDS_ENTRY + MAX_APCLI_NUM + MAX_MESH_NUM]; +#endif // IKANOS_VX_1X0 // + + +#ifdef DBG_DIAGNOSE + RtmpDiagStruct DiagStruct; +#endif // DBG_DIAGNOSE // + + + UINT8 PM_FlgSuspend; + +#ifdef RT30xx +//======efuse + BOOLEAN bUseEfuse; + BOOLEAN bEEPROMFile; +#endif // RT30xx // + +} RTMP_ADAPTER, *PRTMP_ADAPTER; + +// +// Cisco IAPP format +// +typedef struct _CISCO_IAPP_CONTENT_ +{ + USHORT Length; //IAPP Length + UCHAR MessageType; //IAPP type + UCHAR FunctionCode; //IAPP function type + UCHAR DestinaionMAC[MAC_ADDR_LEN]; + UCHAR SourceMAC[MAC_ADDR_LEN]; + USHORT Tag; //Tag(element IE) - Adjacent AP report + USHORT TagLength; //Length of element not including 4 byte header + UCHAR OUI[4]; //0x00, 0x40, 0x96, 0x00 + UCHAR PreviousAP[MAC_ADDR_LEN]; //MAC Address of access point + USHORT Channel; + USHORT SsidLen; + UCHAR Ssid[MAX_LEN_OF_SSID]; + USHORT Seconds; //Seconds that the client has been disassociated. +} CISCO_IAPP_CONTENT, *PCISCO_IAPP_CONTENT; + +#define DELAYINTMASK 0x0003fffb +#define INTMASK 0x0003fffb +#define IndMask 0x0003fffc +#define RxINT 0x00000005 // Delayed Rx or indivi rx +#define TxDataInt 0x000000fa // Delayed Tx or indivi tx +#define TxMgmtInt 0x00000102 // Delayed Tx or indivi tx +#define TxCoherent 0x00020000 // tx coherent +#define RxCoherent 0x00010000 // rx coherent +#define McuCommand 0x00000200 // mcu +#define PreTBTTInt 0x00001000 // Pre-TBTT interrupt +#define TBTTInt 0x00000800 // TBTT interrupt +#define GPTimeOutInt 0x00008000 // GPtimeout interrupt +#define AutoWakeupInt 0x00004000 // AutoWakeupInt interrupt +#define FifoStaFullInt 0x00002000 // fifo statistics full interrupt + + +typedef struct _RX_BLK_ +{ +// RXD_STRUC RxD; // sample + RT28XX_RXD_STRUC RxD; + PRXWI_STRUC pRxWI; + PHEADER_802_11 pHeader; + PNDIS_PACKET pRxPacket; + UCHAR *pData; + USHORT DataSize; + USHORT Flags; + UCHAR UserPriority; // for calculate TKIP MIC using +} RX_BLK; + + +#define RX_BLK_SET_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags |= _flag) +#define RX_BLK_TEST_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags & _flag) +#define RX_BLK_CLEAR_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags &= ~(_flag)) + + +#define fRX_WDS 0x0001 +#define fRX_AMSDU 0x0002 +#define fRX_ARALINK 0x0004 +#define fRX_HTC 0x0008 +#define fRX_PAD 0x0010 +#define fRX_AMPDU 0x0020 +#define fRX_QOS 0x0040 +#define fRX_INFRA 0x0080 +#define fRX_EAP 0x0100 +#define fRX_MESH 0x0200 +#define fRX_APCLI 0x0400 +#define fRX_DLS 0x0800 +#define fRX_WPI 0x1000 + +#define LENGTH_AMSDU_SUBFRAMEHEAD 14 +#define LENGTH_ARALINK_SUBFRAMEHEAD 14 +#define LENGTH_ARALINK_HEADER_FIELD 2 + +#define TX_UNKOWN_FRAME 0x00 +#define TX_MCAST_FRAME 0x01 +#define TX_LEGACY_FRAME 0x02 +#define TX_AMPDU_FRAME 0x04 +#define TX_AMSDU_FRAME 0x08 +#define TX_RALINK_FRAME 0x10 +#define TX_FRAG_FRAME 0x20 + + +// Currently the sizeof(TX_BLK) is 148 bytes. +typedef struct _TX_BLK_ +{ + UCHAR QueIdx; + UCHAR TxFrameType; // Indicate the Transmission type of the all frames in one batch + UCHAR TotalFrameNum; // Total frame number want to send-out in one batch + USHORT TotalFragNum; // Total frame fragments required in one batch + USHORT TotalFrameLen; // Total length of all frames want to send-out in one batch + + QUEUE_HEADER TxPacketList; + MAC_TABLE_ENTRY *pMacEntry; // NULL: packet with 802.11 RA field is multicast/broadcast address + HTTRANSMIT_SETTING *pTransmit; + + // Following structure used for the characteristics of a specific packet. + PNDIS_PACKET pPacket; + PUCHAR pSrcBufHeader; // Reference to the head of sk_buff->data + PUCHAR pSrcBufData; // Reference to the sk_buff->data, will changed depends on hanlding progresss + UINT SrcBufLen; // Length of packet payload which not including Layer 2 header + PUCHAR pExtraLlcSnapEncap; // NULL means no extra LLC/SNAP is required + UCHAR HeaderBuf[80]; // TempBuffer for TX_INFO + TX_WI + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP + UCHAR MpduHeaderLen; // 802.11 header length NOT including the padding + UCHAR HdrPadLen; // recording Header Padding Length; + UCHAR apidx; // The interface associated to this packet + UCHAR Wcid; // The MAC entry associated to this packet + UCHAR UserPriority; // priority class of packet + UCHAR FrameGap; // what kind of IFS this packet use + UCHAR MpduReqNum; // number of fragments of this frame + UCHAR TxRate; // TODO: Obsoleted? Should change to MCS? + UCHAR CipherAlg; // cipher alogrithm + PCIPHER_KEY pKey; + + + + USHORT Flags; //See following definitions for detail. + + //YOU SHOULD NOT TOUCH IT! Following parameters are used for hardware-depended layer. + ULONG Priv; // Hardware specific value saved in here. +} TX_BLK, *PTX_BLK; + + +#define fTX_bRtsRequired 0x0001 // Indicate if need send RTS frame for protection. Not used in RT2860/RT2870. +#define fTX_bAckRequired 0x0002 // the packet need ack response +#define fTX_bPiggyBack 0x0004 // Legacy device use Piggback or not +#define fTX_bHTRate 0x0008 // allow to use HT rate +//#define fTX_bForceLowRate 0x0010 // force to use Low Rate +#define fTX_bForceNonQoS 0x0010 // force to transmit frame without WMM-QoS in HT mode +#define fTX_bAllowFrag 0x0020 // allow to fragment the packet, A-MPDU, A-MSDU, A-Ralink is not allowed to fragment +#define fTX_bMoreData 0x0040 // there are more data packets in PowerSave Queue +#define fTX_bWMM 0x0080 // QOS Data + +#define fTX_bClearEAPFrame 0x0100 + + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + + + +#define TX_BLK_ASSIGN_FLAG(_pTxBlk, _flag, value) \ + do { \ + if (value) \ + (_pTxBlk->Flags |= _flag) \ + else \ + (_pTxBlk->Flags &= ~(_flag)) \ + }while(0) + +#define TX_BLK_SET_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags |= _flag) +#define TX_BLK_TEST_FLAG(_pTxBlk, _flag) (((_pTxBlk->Flags & _flag) == _flag) ? 1 : 0) +#define TX_BLK_CLEAR_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags &= ~(_flag)) + + + + + +//------------------------------------------------------------------------------------------ + + + +#ifdef RT_BIG_ENDIAN +static inline VOID WriteBackToDescriptor( + IN PUCHAR Dest, + IN PUCHAR Src, + IN BOOLEAN DoEncrypt, + IN ULONG DescriptorType) +{ + UINT32 *p1, *p2; + + p1 = ((UINT32 *)Dest); + p2 = ((UINT32 *)Src); + + *p1 = *p2; + *(p1+2) = *(p2+2); + *(p1+3) = *(p2+3); + *(p1+1) = *(p2+1); // Word 1; this must be written back last +} + +/* + ======================================================================== + + Routine Description: + Endian conversion of Tx/Rx descriptor . + + Arguments: + pAd Pointer to our adapter + pData Pointer to Tx/Rx descriptor + DescriptorType Direction of the frame + + Return Value: + None + + Note: + Call this function when read or update descriptor + ======================================================================== +*/ +static inline VOID RTMPWIEndianChange( + IN PUCHAR pData, + IN ULONG DescriptorType) +{ + int size; + int i; + + size = ((DescriptorType == TYPE_TXWI) ? TXWI_SIZE : RXWI_SIZE); + + if(DescriptorType == TYPE_TXWI) + { + *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); // Byte 0~3 + *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData+4))); // Byte 4~7 + } + else + { + for(i=0; i < size/4 ; i++) + *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i)); + } +} + +/* + ======================================================================== + + Routine Description: + Endian conversion of Tx/Rx descriptor . + + Arguments: + pAd Pointer to our adapter + pData Pointer to Tx/Rx descriptor + DescriptorType Direction of the frame + + Return Value: + None + + Note: + Call this function when read or update descriptor + ======================================================================== +*/ + +#ifdef RT2870 +static inline VOID RTMPDescriptorEndianChange( + IN PUCHAR pData, + IN ULONG DescriptorType) +{ + *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); +} +#endif // RT2870 // +/* + ======================================================================== + + Routine Description: + Endian conversion of all kinds of 802.11 frames . + + Arguments: + pAd Pointer to our adapter + pData Pointer to the 802.11 frame structure + Dir Direction of the frame + FromRxDoneInt Caller is from RxDone interrupt + + Return Value: + None + + Note: + Call this function when read or update buffer data + ======================================================================== +*/ +static inline VOID RTMPFrameEndianChange( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG Dir, + IN BOOLEAN FromRxDoneInt) +{ + PHEADER_802_11 pFrame; + PUCHAR pMacHdr; + + // swab 16 bit fields - Frame Control field + if(Dir == DIR_READ) + { + *(USHORT *)pData = SWAP16(*(USHORT *)pData); + } + + pFrame = (PHEADER_802_11) pData; + pMacHdr = (PUCHAR) pFrame; + + // swab 16 bit fields - Duration/ID field + *(USHORT *)(pMacHdr + 2) = SWAP16(*(USHORT *)(pMacHdr + 2)); + + // swab 16 bit fields - Sequence Control field + *(USHORT *)(pMacHdr + 22) = SWAP16(*(USHORT *)(pMacHdr + 22)); + + if(pFrame->FC.Type == BTYPE_MGMT) + { + switch(pFrame->FC.SubType) + { + case SUBTYPE_ASSOC_REQ: + case SUBTYPE_REASSOC_REQ: + // swab 16 bit fields - CapabilityInfo field + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - Listen Interval field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_ASSOC_RSP: + case SUBTYPE_REASSOC_RSP: + // swab 16 bit fields - CapabilityInfo field + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - Status Code field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - AID field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_AUTH: + // If from APHandleRxDoneInterrupt routine, it is still a encrypt format. + // The convertion is delayed to RTMPHandleDecryptionDoneInterrupt. + if(!FromRxDoneInt && pFrame->FC.Wep == 1) + break; + else + { + // swab 16 bit fields - Auth Alg No. field + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - Auth Seq No. field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - Status Code field + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + } + break; + + case SUBTYPE_BEACON: + case SUBTYPE_PROBE_RSP: + // swab 16 bit fields - BeaconInterval field + pMacHdr += (sizeof(HEADER_802_11) + TIMESTAMP_LEN); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + // swab 16 bit fields - CapabilityInfo field + pMacHdr += sizeof(USHORT); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_DEAUTH: + case SUBTYPE_DISASSOC: + // swab 16 bit fields - Reason code field + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + } + } + else if( pFrame->FC.Type == BTYPE_DATA ) + { + } + else if(pFrame->FC.Type == BTYPE_CNTL) + { + switch(pFrame->FC.SubType) + { + case SUBTYPE_BLOCK_ACK_REQ: + { + PFRAME_BA_REQ pBAReq = (PFRAME_BA_REQ)pFrame; + *(USHORT *)(&pBAReq->BARControl) = SWAP16(*(USHORT *)(&pBAReq->BARControl)); + pBAReq->BAStartingSeq.word = SWAP16(pBAReq->BAStartingSeq.word); + } + break; + case SUBTYPE_BLOCK_ACK: + // For Block Ack packet, the HT_CONTROL field is in the same offset with Addr3 + *(UINT32 *)(&pFrame->Addr3[0]) = SWAP32(*(UINT32 *)(&pFrame->Addr3[0])); + break; + + case SUBTYPE_ACK: + //For ACK packet, the HT_CONTROL field is in the same offset with Addr2 + *(UINT32 *)(&pFrame->Addr2[0])= SWAP32(*(UINT32 *)(&pFrame->Addr2[0])); + break; + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("Invalid Frame Type!!!\n")); + } + + // swab 16 bit fields - Frame Control + if(Dir == DIR_WRITE) + { + *(USHORT *)pData = SWAP16(*(USHORT *)pData); + } +} +#endif // RT_BIG_ENDIAN // + + +static inline VOID ConvertMulticastIP2MAC( + IN PUCHAR pIpAddr, + IN PUCHAR *ppMacAddr, + IN UINT16 ProtoType) +{ + if (pIpAddr == NULL) + return; + + if (ppMacAddr == NULL || *ppMacAddr == NULL) + return; + + switch (ProtoType) + { + case ETH_P_IPV6: +// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); + *(*ppMacAddr) = 0x33; + *(*ppMacAddr + 1) = 0x33; + *(*ppMacAddr + 2) = pIpAddr[12]; + *(*ppMacAddr + 3) = pIpAddr[13]; + *(*ppMacAddr + 4) = pIpAddr[14]; + *(*ppMacAddr + 5) = pIpAddr[15]; + break; + + case ETH_P_IP: + default: +// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS); + *(*ppMacAddr) = 0x01; + *(*ppMacAddr + 1) = 0x00; + *(*ppMacAddr + 2) = 0x5e; + *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f; + *(*ppMacAddr + 4) = pIpAddr[2]; + *(*ppMacAddr + 5) = pIpAddr[3]; + break; + } + + return; +} + +BOOLEAN RTMPCheckForHang( + IN NDIS_HANDLE MiniportAdapterContext + ); + +VOID RTMPHalt( + IN NDIS_HANDLE MiniportAdapterContext + ); + +// +// Private routines in rtmp_init.c +// +NDIS_STATUS RTMPAllocAdapterBlock( + IN PVOID handle, + OUT PRTMP_ADAPTER *ppAdapter + ); + +NDIS_STATUS RTMPAllocTxRxRingMemory( + IN PRTMP_ADAPTER pAd + ); + +NDIS_STATUS RTMPFindAdapter( + IN PRTMP_ADAPTER pAd, + IN NDIS_HANDLE WrapperConfigurationContext + ); + +NDIS_STATUS RTMPReadParametersHook( + IN PRTMP_ADAPTER pAd + ); + +VOID RTMPFreeAdapter( + IN PRTMP_ADAPTER pAd + ); + +NDIS_STATUS NICReadRegParameters( + IN PRTMP_ADAPTER pAd, + IN NDIS_HANDLE WrapperConfigurationContext + ); + +#ifdef RT30xx +VOID NICInitRT30xxRFRegisters( + IN PRTMP_ADAPTER pAd); +#endif // RT30xx // + +VOID NICReadEEPROMParameters( + IN PRTMP_ADAPTER pAd, + IN PUCHAR mac_addr); + +VOID NICInitAsicFromEEPROM( + IN PRTMP_ADAPTER pAd); + +VOID NICInitTxRxRingAndBacklogQueue( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS NICInitializeAdapter( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset); + +NDIS_STATUS NICInitializeAsic( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bHardReset); + +VOID NICIssueReset( + IN PRTMP_ADAPTER pAd); + +VOID RTMPRingCleanUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR RingType); + +VOID RxTest( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS DbgSendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + +VOID UserCfgInit( + IN PRTMP_ADAPTER pAd); + +VOID NICResetFromError( + IN PRTMP_ADAPTER pAd); + +VOID NICEraseFirmware( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS NICLoadFirmware( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS NICLoadRateSwitchingParams( + IN PRTMP_ADAPTER pAd); + +BOOLEAN NICCheckForHang( + IN PRTMP_ADAPTER pAd); + +VOID NICUpdateFifoStaCounters( + IN PRTMP_ADAPTER pAd); + +VOID NICUpdateRawCounters( + IN PRTMP_ADAPTER pAd); + +ULONG RTMPNotAllZero( + IN PVOID pSrc1, + IN ULONG Length); + +VOID RTMPZeroMemory( + IN PVOID pSrc, + IN ULONG Length); + +ULONG RTMPCompareMemory( + IN PVOID pSrc1, + IN PVOID pSrc2, + IN ULONG Length); + +VOID RTMPMoveMemory( + OUT PVOID pDest, + IN PVOID pSrc, + IN ULONG Length); + +VOID AtoH( + char *src, + UCHAR *dest, + int destlen); + +UCHAR BtoH( + char ch); + +VOID RTMPPatchMacBbpBug( + IN PRTMP_ADAPTER pAd); + +VOID RTMPPatchCardBus( + IN PRTMP_ADAPTER pAdapter); + +VOID RTMPPatchRalinkCardBus( + IN PRTMP_ADAPTER pAdapter, + IN ULONG Bus); + +ULONG RTMPReadCBConfig( + IN ULONG Bus, + IN ULONG Slot, + IN ULONG Func, + IN ULONG Offset); + +VOID RTMPWriteCBConfig( + IN ULONG Bus, + IN ULONG Slot, + IN ULONG Func, + IN ULONG Offset, + IN ULONG Value); + +VOID RTMPInitTimer( + IN PRTMP_ADAPTER pAd, + IN PRALINK_TIMER_STRUCT pTimer, + IN PVOID pTimerFunc, + IN PVOID pData, + IN BOOLEAN Repeat); + +VOID RTMPSetTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value); + + +VOID RTMPModTimer( + IN PRALINK_TIMER_STRUCT pTimer, + IN ULONG Value); + +VOID RTMPCancelTimer( + IN PRALINK_TIMER_STRUCT pTimer, + OUT BOOLEAN *pCancelled); + +VOID RTMPSetLED( + IN PRTMP_ADAPTER pAd, + IN UCHAR Status); + +VOID RTMPSetSignalLED( + IN PRTMP_ADAPTER pAd, + IN NDIS_802_11_RSSI Dbm); + +VOID RTMPEnableRxTx( + IN PRTMP_ADAPTER pAd); + +// +// prototype in action.c +// +VOID ActionStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeADDBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDELBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeInvalidAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef DOT11_N_SUPPORT +VOID PeerAddBAReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAddBARspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDelBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif // DOT11_N_SUPPORT // + +VOID SendPSMPAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR Psmp); + + +#ifdef DOT11N_DRAFT3 +VOID SendBSS2040CoexistMgmtAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx, + IN UCHAR InfoReq); + +VOID SendNotifyBWActionFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR apidx); + +BOOLEAN ChannelSwitchSanityCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary); + +VOID ChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR Channel, + IN UCHAR Secondary); + +ULONG BuildIntolerantChannelRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDest); + +VOID Update2040CoexistFrameAndNotify( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); + +VOID Send2040CoexistAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); +#endif // DOT11N_DRAFT3 // + +VOID PeerRMAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef CONFIG_STA_SUPPORT +VOID StaPublicAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Bss2040Coexist); +#endif // CONFIG_STA_SUPPORT // + + +VOID PeerBSSTranAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef DOT11_N_SUPPORT +VOID PeerHTAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif // DOT11_N_SUPPORT // + +VOID PeerQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef QOS_DLS_SUPPORT +VOID PeerDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif // QOS_DLS_SUPPORT // + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +VOID DlsParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DLS_REQ_STRUCT *pDlsReq, + IN PRT_802_11_DLS pDls, + IN USHORT reason); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +#ifdef DOT11_N_SUPPORT +VOID RECBATimerTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ORIBATimerTimeout( + IN PRTMP_ADAPTER pAd); + +VOID SendRefreshBAR( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); +#endif // DOT11_N_SUPPORT // + +VOID ActHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN PUCHAR Addr1, + IN PUCHAR Addr2, + IN PUCHAR Addr3); + +VOID BarHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PFRAME_BAR pCntlBar, + IN PUCHAR pDA, + IN PUCHAR pSA); + +VOID InsertActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode); + +BOOLEAN QosBADataParse( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bAMSDU, + IN PUCHAR p8023Header, + IN UCHAR WCID, + IN UCHAR TID, + IN USHORT Sequence, + IN UCHAR DataOffset, + IN USHORT Datasize, + IN UINT CurRxIndex); + +#ifdef DOT11_N_SUPPORT +BOOLEAN CntlEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg); + +VOID BaAutoManSwitch( + IN PRTMP_ADAPTER pAd); +#endif // DOT11_N_SUPPORT // + +VOID HTIOTCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR BatRecIdx); + +// +// Private routines in rtmp_data.c +// +BOOLEAN RTMPHandleRxDoneInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandleTxDoneInterrupt( + IN PRTMP_ADAPTER pAd); + +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( + IN PRTMP_ADAPTER pAd, + IN INT_SOURCE_CSR_STRUC TxRingBitmap); + +VOID RTMPHandleMgmtRingDmaDoneInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandleTBTTInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandlePreTBTTInterrupt( + IN PRTMP_ADAPTER pAd); + +void RTMPHandleTwakeupInterrupt( + IN PRTMP_ADAPTER pAd); + +VOID RTMPHandleRxCoherentInterrupt( + IN PRTMP_ADAPTER pAd); + +BOOLEAN TxFrameIsAggregatible( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPrevAddr1, + IN PUCHAR p8023hdr); + +BOOLEAN PeerIsAggreOn( + IN PRTMP_ADAPTER pAd, + IN ULONG TxRate, + IN PMAC_TABLE_ENTRY pMacEntry); + +NDIS_STATUS Sniff2BytesFromNdisBuffer( + IN PNDIS_BUFFER pFirstBuffer, + IN UCHAR DesiredOffset, + OUT PUCHAR pByte0, + OUT PUCHAR pByte1); + +NDIS_STATUS STASendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + +VOID STASendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets); + +VOID RTMPDeQueuePacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bIntContext, + IN UCHAR QueIdx, + IN UCHAR Max_Tx_Packets); + +NDIS_STATUS RTMPHardTransmit( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR QueIdx, + OUT PULONG pFreeTXDLeft); + +NDIS_STATUS STAHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx); + +VOID STARxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +NDIS_STATUS RTMPFreeTXDRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR RingType, + IN UCHAR NumberRequired, + IN PUCHAR FreeNumberIs); + +NDIS_STATUS MlmeHardTransmit( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +NDIS_STATUS MlmeHardTransmitMgmtRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +NDIS_STATUS MlmeHardTransmitTxRing( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +USHORT RTMPCalcDuration( + IN PRTMP_ADAPTER pAd, + IN UCHAR Rate, + IN ULONG Size); + +VOID RTMPWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN PTXWI_STRUC pTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN CFACK, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, // HW new a sequence. + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR TID, + IN UCHAR TxRate, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit); + + +VOID RTMPWriteTxWI_Data( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk); + + +VOID RTMPWriteTxWI_Cache( + IN PRTMP_ADAPTER pAd, + IN OUT PTXWI_STRUC pTxWI, + IN TX_BLK *pTxBlk); + +VOID RTMPWriteTxDescriptor( + IN PRTMP_ADAPTER pAd, + IN PTXD_STRUC pTxD, + IN BOOLEAN bWIV, + IN UCHAR QSEL); + +VOID RTMPSuspendMsduTransmission( + IN PRTMP_ADAPTER pAd); + +VOID RTMPResumeMsduTransmission( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS MiniportMMRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PUCHAR pData, + IN UINT Length); + +NDIS_STATUS MiniportDataMMRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PUCHAR pData, + IN UINT Length); + +VOID RTMPSendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull); + +VOID RTMPSendDisassociationFrame( + IN PRTMP_ADAPTER pAd); + +VOID RTMPSendRTSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN unsigned int NextMpduSize, + IN UCHAR TxRate, + IN UCHAR RTSRate, + IN USHORT AckDuration, + IN UCHAR QueIdx, + IN UCHAR FrameGap); + + +NDIS_STATUS RTMPApplyPacketFilter( + IN PRTMP_ADAPTER pAd, + IN PRT28XX_RXD_STRUC pRxD, + IN PHEADER_802_11 pHeader); + +PQUEUE_HEADER RTMPCheckTxSwQueue( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *QueIdx); + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPReportMicError( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pWpaKey); + +VOID WpaMicFailureReportFrame( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaDisassocApAndBlockAssoc( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif // CONFIG_STA_SUPPORT // + +NDIS_STATUS RTMPCloneNdisPacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN pInsAMSDUHdr, + IN PNDIS_PACKET pInPacket, + OUT PNDIS_PACKET *ppOutPacket); + +NDIS_STATUS RTMPAllocateNdisPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET *pPacket, + IN PUCHAR pHeader, + IN UINT HeaderLen, + IN PUCHAR pData, + IN UINT DataLen); + +VOID RTMPFreeNdisPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + +BOOLEAN RTMPFreeTXDUponTxDmaDone( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx); + +BOOLEAN RTMPCheckDHCPFrame( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +BOOLEAN RTMPCheckEtherType( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +VOID RTMPCckBbpTuning( + IN PRTMP_ADAPTER pAd, + IN UINT TxRate); + +// +// Private routines in rtmp_wep.c +// +VOID RTMPInitWepEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyId, + IN UCHAR KeyLen, + IN PUCHAR pDest); + +VOID RTMPEncryptData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDest, + IN UINT Len); + +BOOLEAN RTMPDecryptData( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pSrc, + IN UINT Len, + IN UINT idx); + +BOOLEAN RTMPSoftDecryptWEP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pGroupKey); + +VOID RTMPSetICV( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDest); + +VOID ARCFOUR_INIT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pKey, + IN UINT KeyLen); + +UCHAR ARCFOUR_BYTE( + IN PARCFOURCONTEXT Ctx); + +VOID ARCFOUR_DECRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len); + +VOID ARCFOUR_ENCRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len); + +VOID WPAARCFOUR_ENCRYPT( + IN PARCFOURCONTEXT Ctx, + IN PUCHAR pDest, + IN PUCHAR pSrc, + IN UINT Len); + +UINT RTMP_CALC_FCS32( + IN UINT Fcs, + IN PUCHAR Cp, + IN INT Len); + +// +// MLME routines +// + +// Asic/RF/BBP related functions + +VOID AsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateProtect( + IN PRTMP_ADAPTER pAd, + IN USHORT OperaionMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist); + +VOID AsicSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan); + +VOID AsicLockChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) ; + +VOID AsicAntennaSelect( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +VOID AsicAntennaSetting( + IN PRTMP_ADAPTER pAd, + IN ABGBAND_STATE BandState); + +VOID AsicRfTuningExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef CONFIG_STA_SUPPORT +VOID AsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp); + +VOID AsicForceSleep( + IN PRTMP_ADAPTER pAd); + +VOID AsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx); +#endif // CONFIG_STA_SUPPORT // + +VOID AsicSetBssid( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid); + +VOID AsicSetMcastWC( + IN PRTMP_ADAPTER pAd); + +VOID AsicDelWcidTab( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid); + +VOID AsicEnableRDG( + IN PRTMP_ADAPTER pAd); + +VOID AsicDisableRDG( + IN PRTMP_ADAPTER pAd); + +VOID AsicDisableSync( + IN PRTMP_ADAPTER pAd); + +VOID AsicEnableBssSync( + IN PRTMP_ADAPTER pAd); + +VOID AsicEnableIbssSync( + IN PRTMP_ADAPTER pAd); + +VOID AsicSetEdcaParm( + IN PRTMP_ADAPTER pAd, + IN PEDCA_PARM pEdcaParm); + +VOID AsicSetSlotTime( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUseShortSlotTime); + +VOID AsicAddSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN PUCHAR pKey, + IN PUCHAR pTxMic, + IN PUCHAR pRxMic); + +VOID AsicRemoveSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx); + +VOID AsicUpdateWCIDAttribute( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN UCHAR BssIndex, + IN UCHAR CipherAlg, + IN BOOLEAN bUsePairewiseKeyTable); + +VOID AsicUpdateWCIDIVEIV( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV); + +VOID AsicUpdateRxWCIDTable( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN PUCHAR pAddr); + +VOID AsicAddKeyEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey, + IN BOOLEAN bUsePairewiseKeyTable, + IN BOOLEAN bTxKey); + +VOID AsicAddPairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR WCID, + IN CIPHER_KEY *pCipherKey); + +VOID AsicRemovePairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR Wcid); + +BOOLEAN AsicSendCommandToMcu( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1); + + +VOID MacAddrRandomBssid( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pAddr); + +VOID MgtMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid); + +VOID MlmeRadioOff( + IN PRTMP_ADAPTER pAd); + +VOID MlmeRadioOn( + IN PRTMP_ADAPTER pAd); + + +VOID BssTableInit( + IN BSS_TABLE *Tab); + +#ifdef DOT11_N_SUPPORT +VOID BATableInit( + IN PRTMP_ADAPTER pAd, + IN BA_TABLE *Tab); +#endif // DOT11_N_SUPPORT // + +ULONG BssTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN UCHAR Channel); + +ULONG BssSsidTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +ULONG BssTableSearchWithSSID( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +VOID BssTableDeleteEntry( + IN OUT PBSS_TABLE pTab, + IN PUCHAR pBssid, + IN UCHAR Channel); + +#ifdef DOT11_N_SUPPORT +VOID BATableDeleteORIEntry( + IN OUT PRTMP_ADAPTER pAd, + IN BA_ORI_ENTRY *pBAORIEntry); + +VOID BATableDeleteRECEntry( + IN OUT PRTMP_ADAPTER pAd, + IN BA_REC_ENTRY *pBARECEntry); + +VOID BATableTearORIEntry( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR TID, + IN UCHAR Wcid, + IN BOOLEAN bForceDelete, + IN BOOLEAN ALL); + +VOID BATableTearRECEntry( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR TID, + IN UCHAR WCID, + IN BOOLEAN ALL); +#endif // DOT11_N_SUPPORT // + +VOID BssEntrySet( + IN PRTMP_ADAPTER pAd, + OUT PBSS_ENTRY pBss, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN PCF_PARM CfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR Channel, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE); + +ULONG BssTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT PBSS_TABLE pTab, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN USHORT BeaconPeriod, + IN CF_PARM *CfParm, + IN USHORT AtimWin, + IN USHORT CapabilityInfo, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN HT_CAPABILITY_IE *pHtCapability, + IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + IN UCHAR HtCapabilityLen, + IN UCHAR AddHtInfoLen, + IN UCHAR NewExtChanOffset, + IN UCHAR Channel, + IN CHAR Rssi, + IN LARGE_INTEGER TimeStamp, + IN UCHAR CkipFlag, + IN PEDCA_PARM pEdcaParm, + IN PQOS_CAPABILITY_PARM pQosCapability, + IN PQBSS_LOAD_PARM pQbssLoad, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE); + +#ifdef DOT11_N_SUPPORT +VOID BATableInsertEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT Aid, + IN USHORT TimeOutValue, + IN USHORT StartingSeq, + IN UCHAR TID, + IN UCHAR BAWinSize, + IN UCHAR OriginatorStatus, + IN BOOLEAN IsRecipient); + +#ifdef DOT11N_DRAFT3 +VOID Bss2040CoexistTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +VOID TriEventInit( + IN PRTMP_ADAPTER pAd); + +ULONG TriEventTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT TRIGGER_EVENT_TAB *Tab, + IN PUCHAR pBssid, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN UCHAR RegClass, + IN UCHAR ChannelNo); + +VOID TriEventCounterMaintenance( + IN PRTMP_ADAPTER pAd); +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +VOID BssTableSsidSort( + IN PRTMP_ADAPTER pAd, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen); + +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab); + +VOID BssCipherParse( + IN OUT PBSS_ENTRY pBss); + +NDIS_STATUS MlmeQueueInit( + IN MLME_QUEUE *Queue); + +VOID MlmeQueueDestroy( + IN MLME_QUEUE *Queue); + +BOOLEAN MlmeEnqueue( + IN PRTMP_ADAPTER pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg); + +BOOLEAN MlmeEnqueueForRecv( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid, + IN ULONG TimeStampHigh, + IN ULONG TimeStampLow, + IN UCHAR Rssi0, + IN UCHAR Rssi1, + IN UCHAR Rssi2, + IN ULONG MsgLen, + IN PVOID Msg, + IN UCHAR Signal); + + +BOOLEAN MlmeDequeue( + IN MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem); + +VOID MlmeRestartStateMachine( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MlmeQueueEmpty( + IN MLME_QUEUE *Queue); + +BOOLEAN MlmeQueueFull( + IN MLME_QUEUE *Queue); + +BOOLEAN MsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +VOID StateMachineInit( + IN STATE_MACHINE *Sm, + IN STATE_MACHINE_FUNC Trans[], + IN ULONG StNr, + IN ULONG MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + IN ULONG InitState, + IN ULONG Base); + +VOID StateMachineSetAction( + IN STATE_MACHINE *S, + IN ULONG St, + ULONG Msg, + IN STATE_MACHINE_FUNC F); + +VOID StateMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem); + +VOID Drop( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ReassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID AssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID DisassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +//---------------------------------------------- +VOID MlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeReassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerReassocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDisassocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID DisassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ReassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls3errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID SwitchBetweenWepAndCkip( + IN PRTMP_ADAPTER pAd); + +VOID InvalidStateWhenAssoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenReassoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenDisassociate( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef RT2870 +VOID MlmeCntlConfirm( + IN PRTMP_ADAPTER pAd, + IN ULONG MsgType, + IN USHORT Msg); +#endif // RT2870 // + +VOID ComposePsPoll( + IN PRTMP_ADAPTER pAd); + +VOID ComposeNullFrame( + IN PRTMP_ADAPTER pAd); + +VOID AssocPostProc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT Aid, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo); + +VOID AuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID AuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID MlmeAuthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq2Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AuthTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls2errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID MlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenAuth( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +//============================================= + +VOID AuthRspStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]); + +VOID PeerDeauthAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthSimpleRspGenAndSend( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHdr80211, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT Reason, + IN USHORT Status); + +// +// Private routines in dls.c +// + +#ifdef CONFIG_STA_SUPPORT +#ifdef QOS_DLS_SUPPORT +void DlsStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID RTMPCheckDLSTimeOut( + IN PRTMP_ADAPTER pAd); + +BOOLEAN RTMPRcvFrameDLSCheck( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN ULONG Len, + IN PRT28XX_RXD_STRUC pRxD); + +INT RTMPCheckDLSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +VOID RTMPSendDLSTearDownFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +NDIS_STATUS RTMPSendSTAKeyRequest( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +NDIS_STATUS RTMPSendSTAKeyHandShake( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +VOID DlsTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN MlmeDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PRT_802_11_DLS *pDLS, + OUT PUSHORT pReason); + +INT Set_DlsEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +MAC_TABLE_ENTRY *MacTableInsertDlsEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT DlsEntryIdx); + +BOOLEAN MacTableDeleteDlsEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *DlsEntryTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +INT Set_DlsAddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_DlsTearDownEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // QOS_DLS_SUPPORT // +#endif // CONFIG_STA_SUPPORT // + +#ifdef QOS_DLS_SUPPORT +BOOLEAN PeerDlsReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pDlsTimeout, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability); + +BOOLEAN PeerDlsRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT UCHAR *pRatesLen, + OUT UCHAR Rates[], + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability); + +BOOLEAN PeerDlsTearDownSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pDA, + OUT PUCHAR pSA, + OUT USHORT *pReason); +#endif // QOS_DLS_SUPPORT // + +//======================================== + +VOID SyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID BeaconTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID MlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenJoin( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenStart( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID EnqueueProbeRequest( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ScanRunning( + IN PRTMP_ADAPTER pAd); +//========================================= + +VOID MlmeCntlInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeCntlMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlIdleProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidScanProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidSsidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlOidRTBssidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlMlmeRoamingProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlWaitDisassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitJoinProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitReassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitStartProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc2( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAssocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef QOS_DLS_SUPPORT +VOID CntlOidDLSSetupProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif // QOS_DLS_SUPPORT // + +VOID LinkUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssType); + +VOID LinkDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN IsReqFromAP); + +VOID IterateOnBssTab( + IN PRTMP_ADAPTER pAd); + +VOID IterateOnBssTab2( + IN PRTMP_ADAPTER pAd);; + +VOID JoinParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, + IN ULONG BssIdx); + +VOID AssocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, + IN PUCHAR pAddr, + IN USHORT CapabilityInfo, + IN ULONG Timeout, + IN USHORT ListenIntv); + +VOID ScanParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN UCHAR ScanType); + +VOID DisassocParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, + IN PUCHAR pAddr, + IN USHORT Reason); + +VOID StartParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_START_REQ_STRUCT *StartReq, + IN CHAR Ssid[], + IN UCHAR SsidLen); + +VOID AuthParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, + IN PUCHAR pAddr, + IN USHORT Alg); + +VOID EnqueuePsPoll( + IN PRTMP_ADAPTER pAd); + +VOID EnqueueBeaconFrame( + IN PRTMP_ADAPTER pAd); + +VOID MlmeJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeStartReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID BeaconTimeoutAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanNextChannel( + IN PRTMP_ADAPTER pAd); + +ULONG MakeIbssBeacon( + IN PRTMP_ADAPTER pAd); + +VOID CCXAdjacentAPReport( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MlmeScanReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *BssType, + OUT CHAR ssid[], + OUT UCHAR *SsidLen, + OUT UCHAR *ScanType); + +BOOLEAN PeerBeaconAndProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pBssType, + OUT USHORT *pBeaconPeriod, + OUT UCHAR *pChannel, + OUT UCHAR *pNewChannel, + OUT LARGE_INTEGER *pTimestamp, + OUT CF_PARM *pCfParm, + OUT USHORT *pAtimWin, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pErp, + OUT UCHAR *pDtimCount, + OUT UCHAR *pDtimPeriod, + OUT UCHAR *pBcastFlag, + OUT UCHAR *pMessageToMe, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR *pCkipFlag, + OUT UCHAR *pAironetCellPowerLimit, + OUT PEDCA_PARM pEdcaParm, + OUT PQBSS_LOAD_PARM pQbssLoad, + OUT PQOS_CAPABILITY_PARM pQosCapability, + OUT ULONG *pRalinkIe, + OUT UCHAR *pHtCapabilityLen, +#ifdef CONFIG_STA_SUPPORT + OUT UCHAR *pPreNHtCapabilityLen, +#endif // CONFIG_STA_SUPPORT // + OUT HT_CAPABILITY_IE *pHtCapability, + OUT UCHAR *AddHtInfoLen, + OUT ADD_HT_INFO_IE *AddHtInfo, + OUT UCHAR *NewExtChannel, + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE); + +BOOLEAN PeerAddBAReqActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +BOOLEAN PeerAddBARspActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN PeerDelBAActionSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN MlmeAssocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pApAddr, + OUT USHORT *CapabilityInfo, + OUT ULONG *Timeout, + OUT USHORT *ListenIntv); + +BOOLEAN MlmeAuthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT ULONG *Timeout, + OUT USHORT *Alg); + +BOOLEAN MlmeStartReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT CHAR Ssid[], + OUT UCHAR *Ssidlen); + +BOOLEAN PeerAuthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT USHORT *Alg, + OUT USHORT *Seq, + OUT USHORT *Status, + OUT CHAR ChlgText[]); + +BOOLEAN PeerAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT UCHAR *pCkipFlag); + +BOOLEAN PeerDisassocSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN PeerWpaMessageSanity( + IN PRTMP_ADAPTER pAd, + IN PEAPOL_PACKET pMsg, + IN ULONG MsgLen, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry); + +BOOLEAN PeerDeauthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN PeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen); + +BOOLEAN GetTimBit( + IN CHAR *Ptr, + IN USHORT Aid, + OUT UCHAR *TimLen, + OUT UCHAR *BcastFlag, + OUT UCHAR *DtimCount, + OUT UCHAR *DtimPeriod, + OUT UCHAR *MessageToMe); + +UCHAR ChannelSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel); + +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( + IN PBSS_ENTRY pBss); + +BOOLEAN MlmeDelBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen); + +BOOLEAN MlmeAddBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +ULONG MakeOutgoingFrame( + OUT CHAR *Buffer, + OUT ULONG *Length, ...); + +VOID LfsrInit( + IN PRTMP_ADAPTER pAd, + IN ULONG Seed); + +UCHAR RandomByte( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateAutoFallBackTable( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTxRate); + +VOID MlmePeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID LinkDownExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID LinkUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID STAMlmePeriodicExec( + PRTMP_ADAPTER pAd); + +VOID MlmeAutoScan( + IN PRTMP_ADAPTER pAd); + +VOID MlmeAutoReconnectLastSSID( + IN PRTMP_ADAPTER pAd); + +BOOLEAN MlmeValidateSSID( + IN PUCHAR pSsid, + IN UCHAR SsidLen); + +VOID MlmeCheckForRoaming( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32); + +VOID MlmeCheckForFastRoaming( + IN PRTMP_ADAPTER pAd, + IN ULONG Now); + +VOID MlmeDynamicTxRateSwitching( + IN PRTMP_ADAPTER pAd); + +VOID MlmeSetTxRate( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PRTMP_TX_RATE_SWITCH pTxRate); + +VOID MlmeSelectTxRateTable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR *ppTable, + IN PUCHAR pTableSize, + IN PUCHAR pInitTxRateIdx); + +VOID MlmeCalculateChannelQuality( + IN PRTMP_ADAPTER pAd, + IN ULONG Now); + +VOID MlmeCheckPsmChange( + IN PRTMP_ADAPTER pAd, + IN ULONG Now32); + +VOID MlmeSetPsmBit( + IN PRTMP_ADAPTER pAd, + IN USHORT psm); + +VOID MlmeSetTxPreamble( + IN PRTMP_ADAPTER pAd, + IN USHORT TxPreamble); + +VOID UpdateBasicRateBitmap( + IN PRTMP_ADAPTER pAd); + +VOID MlmeUpdateTxRates( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bLinkUp, + IN UCHAR apidx); + +#ifdef DOT11_N_SUPPORT +VOID MlmeUpdateHtTxRates( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); +#endif // DOT11_N_SUPPORT // + +VOID RTMPCheckRates( + IN PRTMP_ADAPTER pAd, + IN OUT UCHAR SupRate[], + IN OUT UCHAR *SupRateLen); + +#ifdef CONFIG_STA_SUPPORT +BOOLEAN RTMPCheckChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR CentralChannel, + IN UCHAR Channel); +#endif // CONFIG_STA_SUPPORT // + +BOOLEAN RTMPCheckHt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN OUT HT_CAPABILITY_IE *pHtCapability, + IN OUT ADD_HT_INFO_IE *pAddHtInfo); + +VOID StaQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID AsicBbpTuning1( + IN PRTMP_ADAPTER pAd); + +VOID AsicBbpTuning2( + IN PRTMP_ADAPTER pAd); + +VOID RTMPUpdateMlmeRate( + IN PRTMP_ADAPTER pAd); + +CHAR RTMPMaxRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +VOID AsicSetRxAnt( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ant); + +VOID AsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd); + +VOID AsicRxAntEvalTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APSDPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +UCHAR RTMPStaFixedTxMode( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPUpdateLegacyTxSetting( + UCHAR fixed_tx_mode, + PMAC_TABLE_ENTRY pEntry); + +BOOLEAN RTMPAutoRateSwitchCheck( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS MlmeInit( + IN PRTMP_ADAPTER pAd); + +VOID MlmeHandler( + IN PRTMP_ADAPTER pAd); + +VOID MlmeHalt( + IN PRTMP_ADAPTER pAd); + +VOID MlmeResetRalinkCounters( + IN PRTMP_ADAPTER pAd); + +VOID BuildChannelList( + IN PRTMP_ADAPTER pAd); + +UCHAR FirstChannel( + IN PRTMP_ADAPTER pAd); + +UCHAR NextChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel); + +VOID ChangeToCellPowerLimit( + IN PRTMP_ADAPTER pAd, + IN UCHAR AironetCellPowerLimit); + +VOID RaiseClock( + IN PRTMP_ADAPTER pAd, + IN UINT32 *x); + +VOID LowerClock( + IN PRTMP_ADAPTER pAd, + IN UINT32 *x); + +USHORT ShiftInBits( + IN PRTMP_ADAPTER pAd); + +VOID ShiftOutBits( + IN PRTMP_ADAPTER pAd, + IN USHORT data, + IN USHORT count); + +VOID EEpromCleanup( + IN PRTMP_ADAPTER pAd); + +VOID EWDS( + IN PRTMP_ADAPTER pAd); + +VOID EWEN( + IN PRTMP_ADAPTER pAd); + +USHORT RTMP_EEPROM_READ16( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset); + +VOID RTMP_EEPROM_WRITE16( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Data); + +// +// Prototypes of function definition in rtmp_tkip.c +// +VOID RTMPInitTkipEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTKey, + IN UCHAR KeyId, + IN PUCHAR pTA, + IN PUCHAR pMICKey, + IN PUCHAR pTSC, + OUT PULONG pIV16, + OUT PULONG pIV32); + +VOID RTMPInitMICEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UCHAR UserPriority, + IN PUCHAR pMICKey); + +BOOLEAN RTMPTkipCompareMICValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UCHAR UserPriority, + IN UINT Len); + +VOID RTMPCalculateMICValue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pEncap, + IN PCIPHER_KEY pKey, + IN UCHAR apidx); + +BOOLEAN RTMPTkipCompareMICValueWithLLC( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pLLC, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UINT Len); + +VOID RTMPTkipAppendByte( + IN PTKIP_KEY_INFO pTkip, + IN UCHAR uChar); + +VOID RTMPTkipAppend( + IN PTKIP_KEY_INFO pTkip, + IN PUCHAR pSrc, + IN UINT nBytes); + +VOID RTMPTkipGetMIC( + IN PTKIP_KEY_INFO pTkip); + +BOOLEAN RTMPSoftDecryptTKIP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN UCHAR UserPriority, + IN PCIPHER_KEY pWpaKey); + +BOOLEAN RTMPSoftDecryptAES( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataByteCnt, + IN PCIPHER_KEY pWpaKey); + +// +// Prototypes of function definition in cmm_info.c +// +NDIS_STATUS RTMPWPARemoveKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf); + +VOID RTMPWPARemoveAllKeys( + IN PRTMP_ADAPTER pAd); + +BOOLEAN RTMPCheckStrPrintAble( + IN CHAR *pInPutStr, + IN UCHAR strLen); + +VOID RTMPSetPhyMode( + IN PRTMP_ADAPTER pAd, + IN ULONG phymode); + +VOID RTMPUpdateHTIE( + IN RT_HT_CAPABILITY *pRtHt, + IN UCHAR *pMcsSet, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo); + +VOID RTMPAddWcidAttributeEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN MAC_TABLE_ENTRY *pEntry); + +CHAR *GetEncryptType( + CHAR enc); + +CHAR *GetAuthMode( + CHAR auth); + +VOID RTMPIoctlGetSiteSurvey( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); + +VOID RTMPIoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN struct iwreq *wrq); + +VOID RTMPIndicateWPA2Status( + IN PRTMP_ADAPTER pAdapter); + +VOID RTMPOPModeSwitching( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_STA_SUPPORT +VOID RTMPAddBSSIDCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR Aid, + IN PNDIS_802_11_KEY pKey, + IN UCHAR CipherAlg); +#endif // CONFIG_STA_SUPPORT // + +#ifdef DOT11_N_SUPPORT +VOID RTMPSetHT( + IN PRTMP_ADAPTER pAd, + IN OID_SET_HT_PHYMODE *pHTPhyMode); + +VOID RTMPSetIndividualHT( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); +#endif // DOT11_N_SUPPORT // + +VOID RTMPSendWirelessEvent( + IN PRTMP_ADAPTER pAd, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR BssIdx, + IN CHAR Rssi); + +VOID NICUpdateCntlCounters( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN UCHAR SubType, + IN PRXWI_STRUC pRxWI); +// +// prototype in wpa.c +// +BOOLEAN WpaMsgTypeSubst( + IN UCHAR EAPType, + OUT INT *MsgType); + +VOID WpaPskStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID WpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WpaMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR wep, + IN PUCHAR pAddr1); + +VOID Wpa2PairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Wpa2PairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +BOOLEAN ParseKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR bPairewise); + +VOID RTMPToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN BOOLEAN is4wayFrame); + +VOID HMAC_SHA1( + IN UCHAR *text, + IN UINT text_len, + IN UCHAR *key, + IN UINT key_len, + IN UCHAR *digest); + +VOID PRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *prefix, + IN INT prefix_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len); + +VOID CCKMPRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len); + +VOID WpaCountPTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len); + +VOID GenRandom( + IN PRTMP_ADAPTER pAd, + IN UCHAR *macAddr, + OUT UCHAR *random); + +// +// prototype in aironet.c +// +VOID AironetStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID AironetMsgAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AironetRequestAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ChannelLoadRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID NoiseHistRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID BeaconRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID AironetReportAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ChannelLoadReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID NoiseHistReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID AironetFinalReportAction( + IN PRTMP_ADAPTER pAd); + +VOID BeaconReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID AironetAddBeaconReport( + IN PRTMP_ADAPTER pAd, + IN ULONG Index, + IN PMLME_QUEUE_ELEM pElem); + +VOID AironetCreateBeaconReportFromBssTable( + IN PRTMP_ADAPTER pAd); + +VOID DBGPRINT_TX_RING( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx); + +VOID DBGPRINT_RX_RING( + IN PRTMP_ADAPTER pAd); + +CHAR ConvertToRssi( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + IN UCHAR RssiNumber); + + +#ifdef DOT11N_DRAFT3 +VOID BuildEffectedChannelList( + IN PRTMP_ADAPTER pAd); +#endif // DOT11N_DRAFT3 // + + +VOID APAsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd); + + +VOID APAsicRxAntEvalTimeout( + IN PRTMP_ADAPTER pAd); + +// +// function prototype in cmm_wpa.c +// +BOOLEAN RTMPCheckWPAframe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pData, + IN ULONG DataByteCount, + IN UCHAR FromWhichBSSID); + +VOID AES_GTK_KEY_UNWRAP( + IN UCHAR *key, + OUT UCHAR *plaintext, + IN UCHAR c_len, + IN UCHAR *ciphertext); + +BOOLEAN RTMPCheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + IN MAC_TABLE_ENTRY *pEntry, + OUT UCHAR *Offset); + +BOOLEAN RTMPParseEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR GroupKeyIndex, + IN UCHAR MsgType, + IN BOOLEAN bWPA2, + IN MAC_TABLE_ENTRY *pEntry); + +VOID ConstructEapolMsg( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerAuthMode, + IN UCHAR PeerWepStatus, + IN UCHAR MyGroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN UCHAR *ReplayCounter, + IN UCHAR *KeyNonce, + IN UCHAR *TxRSC, + IN UCHAR *PTK, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_Len, + OUT PEAPOL_PACKET pMsg); + +VOID CalculateMIC( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerWepStatus, + IN UCHAR *PTK, + OUT PEAPOL_PACKET pMsg); + +NDIS_STATUS RTMPSoftDecryptBroadCastData( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher, + IN PCIPHER_KEY pShard_key); + +VOID ConstructEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN UCHAR PeerAuthMode, + IN UCHAR PeerWepStatus, + IN UCHAR GroupKeyWepStatus, + IN UCHAR MsgType, + IN UCHAR DefaultKeyIdx, + IN BOOLEAN bWPA2Capable, + IN UCHAR *PTK, + IN UCHAR *GTK, + IN UCHAR *RSNIE, + IN UCHAR RSNIE_LEN, + OUT PEAPOL_PACKET pMsg); + +VOID RTMPMakeRSNIE( + IN PRTMP_ADAPTER pAd, + IN UINT AuthMode, + IN UINT WepStatus, + IN UCHAR apidx); + +// +// function prototype in ap_wpa.c +// + +BOOLEAN APWpaMsgTypeSubst( + IN UCHAR EAPType, + OUT INT *MsgType) ; + +MAC_TABLE_ENTRY *PACInquiry( + IN PRTMP_ADAPTER pAd, + IN ULONG Wcid); + +BOOLEAN RTMPCheckMcast( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry); + +BOOLEAN RTMPCheckUcast( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry); + +BOOLEAN RTMPCheckAUTH( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry); + +VOID WPAStart4WayHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval); + +VOID WPAStart2WayGroupHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID APWpaEAPPacketAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APWpaEAPOLStartAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APWpaEAPOLLogoffAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APWpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APWpaEAPOLASFAlertAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID HandleCounterMeasure( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID PeerPairMsg2Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg4Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID CMTimerExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WPARetryExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID EnqueueStartForPSKExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RTMPHandleSTAKey( + IN PRTMP_ADAPTER pAdapter, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerGroupMsg2Action( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN VOID *Msg, + IN UINT MsgLen); + +VOID PairDisAssocAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT Reason); + +VOID MlmeDeAuthAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT Reason); + +VOID GREKEYPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID CountGTK( + IN UCHAR *PMK, + IN UCHAR *GNonce, + IN UCHAR *AA, + OUT UCHAR *output, + IN UINT len); + +VOID GetSmall( + IN PVOID pSrc1, + IN PVOID pSrc2, + OUT PUCHAR out, + IN ULONG Length); + +VOID GetLarge( + IN PVOID pSrc1, + IN PVOID pSrc2, + OUT PUCHAR out, + IN ULONG Length); + +VOID APGenRandom( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *random); + +VOID AES_GTK_KEY_WRAP( + IN UCHAR *key, + IN UCHAR *plaintext, + IN UCHAR p_len, + OUT UCHAR *ciphertext); + +VOID WpaSend( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pPacket, + IN ULONG Len); + +VOID APToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN BOOLEAN bClearFrame); + +VOID RTMPAddPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr, + IN UCHAR *PMKID, + IN UCHAR *PMK); + +INT RTMPSearchPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr); + +VOID RTMPDeletePMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN INT idx); + +VOID RTMPMaintainPMKIDCache( + IN PRTMP_ADAPTER pAd); + +VOID RTMPSendTriggerFrame( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuffer, + IN ULONG Length, + IN UCHAR TxRate, + IN BOOLEAN bQosNull); + +#ifdef RT30xx +VOID RTMPFilterCalibration( + IN PRTMP_ADAPTER pAd); +#endif // RT30xx // + + +//typedef void (*TIMER_FUNCTION)(unsigned long); + + +/* timeout -- ms */ +VOID RTMP_SetPeriodicTimer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout); + +VOID RTMP_OS_Init_Timer( + IN PRTMP_ADAPTER pAd, + IN NDIS_MINIPORT_TIMER *pTimer, + IN TIMER_FUNCTION function, + IN PVOID data); + +VOID RTMP_OS_Add_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout); + +VOID RTMP_OS_Mod_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + IN unsigned long timeout); + + +VOID RTMP_OS_Del_Timer( + IN NDIS_MINIPORT_TIMER *pTimer, + OUT BOOLEAN *pCancelled); + + +VOID RTMP_OS_Release_Packet( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_ENTRY pEntry); + +VOID RTMPusecDelay( + IN ULONG usec); + +NDIS_STATUS os_alloc_mem( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR *mem, + IN ULONG size); + +NDIS_STATUS os_free_mem( + IN PRTMP_ADAPTER pAd, + IN PUCHAR mem); + + +void RTMP_AllocateSharedMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +VOID RTMPFreeTxRxRingMemory( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS AdapterBlockAllocateMemory( + IN PVOID handle, + OUT PVOID *ppAd); + +void RTMP_AllocateTxDescMemory( + IN PRTMP_ADAPTER pAd, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateFirstTxBuffer( + IN PRTMP_ADAPTER pAd, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateMgmtDescMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateRxDescMemory( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +PNDIS_PACKET RTMP_AllocateRxPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +PNDIS_PACKET RTMP_AllocateTxPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress); + +PNDIS_PACKET RTMP_AllocateFragPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length); + +void RTMP_QueryPacketInfo( + IN PNDIS_PACKET pPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen); + +void RTMP_QueryNextPacketInfo( + IN PNDIS_PACKET *ppPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen); + + +BOOLEAN RTMP_FillTxBlkInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk); + + +PRTMP_SCATTER_GATHER_LIST +rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg); + + + void announce_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +UINT BA_Reorder_AMSDU_Annnounce( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket); + + +UINT Handle_AMSDU_Packet( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID); + + +void convert_802_11_to_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR p8023hdr, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID); + + +PNET_DEV get_netdev_from_bssid( + IN PRTMP_ADAPTER pAd, + IN UCHAR FromWhichBSSID); + + +PNDIS_PACKET duplicate_pkt( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID); + + +PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pOldPkt); + +PNDIS_PACKET duplicate_pkt_with_VLAN( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID); + +PNDIS_PACKET duplicate_pkt_with_WPI( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UINT32 ext_head_len, + IN UINT32 ext_tail_len); + +UCHAR VLAN_8023_Header_Copy( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + OUT PUCHAR pData, + IN UCHAR FromWhichBSSID); + +#ifdef DOT11_N_SUPPORT +void ba_flush_reordering_timeout_mpdus( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN ULONG Now32); + + +VOID BAOriSessionSetUp( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced); + +VOID BASessionTearDownALL( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid); +#endif // DOT11_N_SUPPORT // + +BOOLEAN OS_Need_Clone_Packet(void); + + +VOID build_tx_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pFrame, + IN ULONG FrameLen); + + +VOID BAOriSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend); + +VOID BARecSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive); + +BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num); +void ba_reordering_resource_release(PRTMP_ADAPTER pAd); + +ULONG AutoChBssInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR ChannelNo, + IN CHAR Rssi); + +void AutoChBssTableInit( + IN PRTMP_ADAPTER pAd); + +void ChannelInfoInit( + IN PRTMP_ADAPTER pAd); + +void AutoChBssTableDestroy( + IN PRTMP_ADAPTER pAd); + +void ChannelInfoDestroy( + IN PRTMP_ADAPTER pAd); + +UCHAR New_ApAutoSelectChannel( + IN PRTMP_ADAPTER pAd); + + +#ifdef NINTENDO_AP +VOID InitNINTENDO_TABLE( + IN PRTMP_ADAPTER pAd); + +UCHAR CheckNINTENDO_TABLE( + IN PRTMP_ADAPTER pAd, + PCHAR pDS_Ssid, + UCHAR DS_SsidLen, + PUCHAR pDS_Addr); + +UCHAR DelNINTENDO_ENTRY( + IN PRTMP_ADAPTER pAd, + UCHAR * pDS_Addr); + +VOID RTMPIoctlNintendoCapable( + IN PRTMP_ADAPTER pAd, + IN struct iwreq *wrq); + +VOID RTMPIoctlNintendoGetTable( + IN PRTMP_ADAPTER pAd, + IN struct iwreq *wrq); + +VOID RTMPIoctlNintendoSetTable( + IN PRTMP_ADAPTER pAd, + IN struct iwreq *wrq); + +#endif // NINTENDO_AP // + +BOOLEAN rtstrmactohex( + IN char *s1, + IN char *s2); + +BOOLEAN rtstrcasecmp( + IN char *s1, + IN char *s2); + +char *rtstrstruncasecmp( + IN char *s1, + IN char *s2); + +char *rtstrstr( + IN const char * s1, + IN const char * s2); + +char *rstrtok( + IN char * s, + IN const char * ct); + +int rtinet_aton( + const char *cp, + unsigned int *addr); + +////////// common ioctl functions ////////// +INT Set_DriverVersion_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_CountryRegion_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_Channel_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ShortSlot_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_TxPower_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_TxPreamble_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_RTSThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef AGGREGATION_SUPPORT +INT Set_PktAggregate_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif + +INT Set_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef DBG +INT Set_Debug_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif + +INT Show_DescInfo_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ResetStatCounter_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef DOT11_N_SUPPORT +INT Set_BASetup_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BADecline_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BAOriTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_BARecTearDown_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtBw_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtOpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtStbc_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtHtc_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtExtcha_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtMpduDensity_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtBaWinSize_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtRdg_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtLinkAdapt_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtAmsdu_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtAutoBa_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtProtect_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtMimoPs_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + + +INT Set_ForceShortGI_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_ForceGF_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT SetCommonHT( + IN PRTMP_ADAPTER pAd); + +INT Set_SendPSMPAction_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_HtMIMOPSmode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + + +INT Set_HtTxBASize_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // DOT11_N_SUPPORT // + + + +#ifdef CONFIG_STA_SUPPORT +//Dls , kathy +VOID RTMPSendDLSTearDownFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA); + +#ifdef DOT11_N_SUPPORT +//Block ACK +VOID QueryBATABLE( + IN PRTMP_ADAPTER pAd, + OUT PQUERYBA_TABLE pBAT); +#endif // DOT11_N_SUPPORT // + +#ifdef WPA_SUPPLICANT_SUPPORT +INT WpaCheckEapCode( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrame, + IN USHORT FrameLen, + IN USHORT OffSet); + +VOID WpaSendMicFailureToWpaSupplicant( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUnicast); + +VOID SendAssocIEsToWpaSupplicant( + IN PRTMP_ADAPTER pAd); +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +int wext_notify_event_assoc( + IN RTMP_ADAPTER *pAd); +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + +#endif // CONFIG_STA_SUPPORT // + + + +#ifdef DOT11_N_SUPPORT +VOID Handle_BSS_Width_Trigger_Events( + IN PRTMP_ADAPTER pAd); + +void build_ext_channel_switch_ie( + IN PRTMP_ADAPTER pAd, + IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE); +#endif // DOT11_N_SUPPORT // + + +BOOLEAN APRxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd); + +BOOLEAN STARxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN argc); + +#ifdef DOT11_N_SUPPORT +// AMPDU packet indication +VOID Indicate_AMPDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +// AMSDU packet indication +VOID Indicate_AMSDU_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); +#endif // DOT11_N_SUPPORT // + +// Normal legacy Rx packet indication +VOID Indicate_Legacy_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID Indicate_EAPOL_Packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +void update_os_packet_info( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +void wlan_802_11_to_802_3_packet( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN PUCHAR pHeader802_3, + IN UCHAR FromWhichBSSID); + +UINT deaggregate_AMSDU_announce( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize); + + +#ifdef CONFIG_STA_SUPPORT +// remove LLC and get 802_3 Header +#define RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(_pRxBlk, _pHeader802_3) \ +{ \ + PUCHAR _pRemovedLLCSNAP = NULL, _pDA, _pSA; \ + \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_MESH)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr3; \ + _pSA = (PUCHAR)_pRxBlk->pHeader + sizeof(HEADER_802_11); \ + } \ + else \ + { \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_INFRA)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr1; \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_DLS)) \ + _pSA = _pRxBlk->pHeader->Addr2; \ + else \ + _pSA = _pRxBlk->pHeader->Addr3; \ + } \ + else \ + { \ + _pDA = _pRxBlk->pHeader->Addr1; \ + _pSA = _pRxBlk->pHeader->Addr2; \ + } \ + } \ + \ + CONVERT_TO_802_3(_pHeader802_3, _pDA, _pSA, _pRxBlk->pData, \ + _pRxBlk->DataSize, _pRemovedLLCSNAP); \ +} +#endif // CONFIG_STA_SUPPORT // + + +BOOLEAN APFowardWirelessStaToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN ULONG FromWhichBSSID); + +VOID Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID); + +VOID Sta_Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID); + + +#ifdef CONFIG_STA_SUPPORT +#define ANNOUNCE_OR_FORWARD_802_3_PACKET(_pAd, _pPacket, _FromWhichBSS)\ + Sta_Announce_or_Forward_802_3_Packet(_pAd, _pPacket, _FromWhichBSS); + //announce_802_3_packet(_pAd, _pPacket); +#endif // CONFIG_STA_SUPPORT // + + +PNDIS_PACKET DuplicatePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID); + + +PNDIS_PACKET ClonePacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize); + + +// Normal, AMPDU or AMSDU +VOID CmmRxnonRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID CmmRxRalinkFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID); + +VOID Update_Rssi_Sample( + IN PRTMP_ADAPTER pAd, + IN RSSI_SAMPLE *pRssi, + IN PRXWI_STRUC pRxWI); + +PNDIS_PACKET GetPacketFromRxRing( + IN PRTMP_ADAPTER pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN *pbReschedule, + IN OUT UINT32 *pRxPending); + +PNDIS_PACKET RTMPDeFragmentDataFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +//////////////////////////////////////// + + + + + +#ifdef SNMP_SUPPORT +//for snmp , kathy +typedef struct _DefaultKeyIdxValue +{ + UCHAR KeyIdx; + UCHAR Value[16]; +} DefaultKeyIdxValue, *PDefaultKeyIdxValue; +#endif + + +#ifdef CONFIG_STA_SUPPORT +enum { + DIDmsg_lnxind_wlansniffrm = 0x00000044, + DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044, + DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044, + DIDmsg_lnxind_wlansniffrm_channel = 0x00030044, + DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044, + DIDmsg_lnxind_wlansniffrm_sq = 0x00050044, + DIDmsg_lnxind_wlansniffrm_signal = 0x00060044, + DIDmsg_lnxind_wlansniffrm_noise = 0x00070044, + DIDmsg_lnxind_wlansniffrm_rate = 0x00080044, + DIDmsg_lnxind_wlansniffrm_istx = 0x00090044, + DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044 +}; +enum { + P80211ENUM_msgitem_status_no_value = 0x00 +}; +enum { + P80211ENUM_truth_false = 0x00, + P80211ENUM_truth_true = 0x01 +}; + +/* Definition from madwifi */ +typedef struct { + UINT32 did; + UINT16 status; + UINT16 len; + UINT32 data; +} p80211item_uint32_t; + +typedef struct { + UINT32 msgcode; + UINT32 msglen; +#define WLAN_DEVNAMELEN_MAX 16 + UINT8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t hosttime; + p80211item_uint32_t mactime; + p80211item_uint32_t channel; + p80211item_uint32_t rssi; + p80211item_uint32_t sq; + p80211item_uint32_t signal; + p80211item_uint32_t noise; + p80211item_uint32_t rate; + p80211item_uint32_t istx; + p80211item_uint32_t frmlen; +} wlan_ng_prism2_header; + +/* The radio capture header precedes the 802.11 header. */ +typedef struct PACKED _ieee80211_radiotap_header { + UINT8 it_version; /* Version 0. Only increases + * for drastic changes, + * introduction of compatible + * new fields does not count. + */ + UINT8 it_pad; + UINT16 it_len; /* length of the whole + * header in bytes, including + * it_version, it_pad, + * it_len, and data fields. + */ + UINT32 it_present; /* A bitmap telling which + * fields are present. Set bit 31 + * (0x80000000) to extend the + * bitmap by another 32 bits. + * Additional extensions are made + * by setting bit 31. + */ +}ieee80211_radiotap_header ; + +enum ieee80211_radiotap_type { + IEEE80211_RADIOTAP_TSFT = 0, + IEEE80211_RADIOTAP_FLAGS = 1, + IEEE80211_RADIOTAP_RATE = 2, + IEEE80211_RADIOTAP_CHANNEL = 3, + IEEE80211_RADIOTAP_FHSS = 4, + IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, + IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, + IEEE80211_RADIOTAP_LOCK_QUALITY = 7, + IEEE80211_RADIOTAP_TX_ATTENUATION = 8, + IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, + IEEE80211_RADIOTAP_DBM_TX_POWER = 10, + IEEE80211_RADIOTAP_ANTENNA = 11, + IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, + IEEE80211_RADIOTAP_DB_ANTNOISE = 13 +}; + +#define WLAN_RADIOTAP_PRESENT ( \ + (1 << IEEE80211_RADIOTAP_TSFT) | \ + (1 << IEEE80211_RADIOTAP_FLAGS) | \ + (1 << IEEE80211_RADIOTAP_RATE) | \ + 0) + +typedef struct _wlan_radiotap_header { + ieee80211_radiotap_header wt_ihdr; + INT64 wt_tsft; + UINT8 wt_flags; + UINT8 wt_rate; +} wlan_radiotap_header; +/* Definition from madwifi */ + +void send_monitor_packets( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +#if WIRELESS_EXT >= 12 +// This function will be called when query /proc +struct iw_statistics *rt28xx_get_wireless_stats( + IN struct net_device *net_dev); +#endif + +VOID RTMPSetDesiredRates( + IN PRTMP_ADAPTER pAdapter, + IN LONG Rates); +#endif // CONFIG_STA_SUPPORT // + +INT Set_FixedTxMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // CONFIG_APSTA_MIXED_SUPPORT // + +static inline char* GetPhyMode( + int Mode) +{ + switch(Mode) + { + case MODE_CCK: + return "CCK"; + + case MODE_OFDM: + return "OFDM"; +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + return "HTMIX"; + + case MODE_HTGREENFIELD: + return "GREEN"; +#endif // DOT11_N_SUPPORT // + default: + return "N/A"; + } +} + + +static inline char* GetBW( + int BW) +{ + switch(BW) + { + case BW_10: + return "10M"; + + case BW_20: + return "20M"; +#ifdef DOT11_N_SUPPORT + case BW_40: + return "40M"; +#endif // DOT11_N_SUPPORT // + default: + return "N/A"; + } +} + + +VOID RT28xxThreadTerminate( + IN RTMP_ADAPTER *pAd); + +BOOLEAN RT28XXChipsetCheck( + IN void *_dev_p); + +BOOLEAN RT28XXNetDevInit( + IN void *_dev_p, + IN struct net_device *net_dev, + IN RTMP_ADAPTER *pAd); + +BOOLEAN RT28XXProbePostConfig( + IN void *_dev_p, + IN RTMP_ADAPTER *pAd, + IN INT32 argc); + +VOID RT28XXDMADisable( + IN RTMP_ADAPTER *pAd); + +VOID RT28XXDMAEnable( + IN RTMP_ADAPTER *pAd); + +VOID RT28xx_UpdateBeaconToAsic( + IN RTMP_ADAPTER * pAd, + IN INT apidx, + IN ULONG BeaconLen, + IN ULONG UpdatePos); + +INT rt28xx_ioctl( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN INT cmd); + + +#ifdef CONFIG_STA_SUPPORT +INT rt28xx_sta_ioctl( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN INT cmd); +#endif // CONFIG_STA_SUPPORT // + +BOOLEAN RT28XXSecurityKeyAdd( + IN PRTMP_ADAPTER pAd, + IN ULONG apidx, + IN ULONG KeyIdx, + IN MAC_TABLE_ENTRY *pEntry); + +//////////////////////////////////////// +PNDIS_PACKET GetPacketFromRxRing( + IN PRTMP_ADAPTER pAd, + OUT PRT28XX_RXD_STRUC pSaveRxD, + OUT BOOLEAN *pbReschedule, + IN OUT UINT32 *pRxPending); + + +void kill_thread_task(PRTMP_ADAPTER pAd); + +void tbtt_tasklet(unsigned long data); + + +VOID AsicTurnOffRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +VOID AsicTurnOnRFClk( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel); + +#ifdef RT30xx +NTSTATUS RT30xxWriteRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR RegID, + IN UCHAR Value); + +NTSTATUS RT30xxReadRFRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR RegID, + IN PUCHAR pValue); + +//2008/09/11:KH add to support efuse<-- +UCHAR eFuseReadRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData); + +VOID eFuseReadPhysical( + IN PRTMP_ADAPTER pAd, + IN PUSHORT lpInBuffer, + IN ULONG nInBufferSize, + OUT PUSHORT lpOutBuffer, + IN ULONG nOutBufferSize +); + +NTSTATUS eFuseRead( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT PUCHAR pData, + IN USHORT Length); + +VOID eFusePhysicalWriteRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData); + +NTSTATUS eFuseWriteRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + IN USHORT* pData); + +VOID eFuseWritePhysical( + IN PRTMP_ADAPTER pAd, + PUSHORT lpInBuffer, + ULONG nInBufferSize, + PUCHAR lpOutBuffer, + ULONG nOutBufferSize +); + +NTSTATUS eFuseWrite( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN PUCHAR pData, + IN USHORT length); + +INT set_eFuseGetFreeBlockCount_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT set_eFusedump_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT set_eFuseLoadFromBin_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +NTSTATUS eFuseWriteRegistersFromBin( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + IN USHORT* pData); + +VOID eFusePhysicalReadRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData); + +NDIS_STATUS NICLoadEEPROM( + IN PRTMP_ADAPTER pAd); + +BOOLEAN bNeedLoadEEPROM( + IN PRTMP_ADAPTER pAd); +//2008/09/11:KH add to support efuse--> +#endif // RT30xx // + +#ifdef RT30xx +// add by johnli, RF power sequence setup +VOID RT30xxLoadRFNormalModeSetup( + IN PRTMP_ADAPTER pAd); + +VOID RT30xxLoadRFSleepModeSetup( + IN PRTMP_ADAPTER pAd); + +VOID RT30xxReverseRFSleepModeSetup( + IN PRTMP_ADAPTER pAd); +// end johnli +#endif // RT30xx // + +#ifdef RT2870 +// +// Function Prototype in rtusb_bulk.c +// +VOID RTUSBInitTxDesc( + IN PRTMP_ADAPTER pAd, + IN PTX_CONTEXT pTxContext, + IN UCHAR BulkOutPipeId, + IN usb_complete_t Func); + +VOID RTUSBInitHTTxDesc( + IN PRTMP_ADAPTER pAd, + IN PHT_TX_CONTEXT pTxContext, + IN UCHAR BulkOutPipeId, + IN ULONG BulkOutSize, + IN usb_complete_t Func); + +VOID RTUSBInitRxDesc( + IN PRTMP_ADAPTER pAd, + IN PRX_CONTEXT pRxContext); + +VOID RTUSBCleanUpDataBulkOutQueue( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBCancelPendingBulkOutIRP( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBBulkOutDataPacket( + IN PRTMP_ADAPTER pAd, + IN UCHAR BulkOutPipeId, + IN UCHAR Index); + +VOID RTUSBBulkOutNullFrame( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBBulkOutRTSFrame( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBCancelPendingBulkInIRP( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBCancelPendingIRPs( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBBulkOutMLMEPacket( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index); + +VOID RTUSBBulkOutPsPoll( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBCleanUpMLMEBulkOutQueue( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBKickBulkOut( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBBulkReceive( + IN PRTMP_ADAPTER pAd); + +VOID DoBulkIn( + IN RTMP_ADAPTER *pAd); + +VOID RTUSBInitRxDesc( + IN PRTMP_ADAPTER pAd, + IN PRX_CONTEXT pRxContext); + +VOID RTUSBBulkRxHandle( + IN unsigned long data); + +// +// Function Prototype in rtusb_io.c +// +NTSTATUS RTUSBMultiRead( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT PUCHAR pData, + IN USHORT length); + +NTSTATUS RTUSBMultiWrite( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN PUCHAR pData, + IN USHORT length); + +NTSTATUS RTUSBMultiWrite_OneByte( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN PUCHAR pData); + +NTSTATUS RTUSBReadBBPRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR Id, + IN PUCHAR pValue); + +NTSTATUS RTUSBWriteBBPRegister( + IN PRTMP_ADAPTER pAd, + IN UCHAR Id, + IN UCHAR Value); + +NTSTATUS RTUSBWriteRFRegister( + IN PRTMP_ADAPTER pAd, + IN UINT32 Value); + +NTSTATUS RTUSB_VendorRequest( + IN PRTMP_ADAPTER pAd, + IN UINT32 TransferFlags, + IN UCHAR ReservedBits, + IN UCHAR Request, + IN USHORT Value, + IN USHORT Index, + IN PVOID TransferBuffer, + IN UINT32 TransferBufferLength); + +NTSTATUS RTUSBReadEEPROM( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT PUCHAR pData, + IN USHORT length); + +NTSTATUS RTUSBWriteEEPROM( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN PUCHAR pData, + IN USHORT length); + +VOID RTUSBPutToSleep( + IN PRTMP_ADAPTER pAd); + +NTSTATUS RTUSBWakeUp( + IN PRTMP_ADAPTER pAd); + +VOID RTUSBInitializeCmdQ( + IN PCmdQ cmdq); + +NDIS_STATUS RTUSBEnqueueCmdFromNdis( + IN PRTMP_ADAPTER pAd, + IN NDIS_OID Oid, + IN BOOLEAN SetInformation, + IN PVOID pInformationBuffer, + IN UINT32 InformationBufferLength); + +NDIS_STATUS RTUSBEnqueueInternalCmd( + IN PRTMP_ADAPTER pAd, + IN NDIS_OID Oid, + IN PVOID pInformationBuffer, + IN UINT32 InformationBufferLength); + +VOID RTUSBDequeueCmd( + IN PCmdQ cmdq, + OUT PCmdQElmt *pcmdqelmt); + +INT RTUSBCmdThread( + IN OUT PVOID Context); + +INT TimerQThread( + IN OUT PVOID Context); + +RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer); + +BOOLEAN RT2870_TimerQ_Remove( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer); + +void RT2870_TimerQ_Exit( + IN RTMP_ADAPTER *pAd); + +void RT2870_TimerQ_Init( + IN RTMP_ADAPTER *pAd); + +VOID RT2870_BssBeaconExit( + IN RTMP_ADAPTER *pAd); + +VOID RT2870_BssBeaconStop( + IN RTMP_ADAPTER *pAd); + +VOID RT2870_BssBeaconStart( + IN RTMP_ADAPTER * pAd); + +VOID RT2870_BssBeaconInit( + IN RTMP_ADAPTER *pAd); + +VOID RT2870_WatchDog( + IN RTMP_ADAPTER *pAd); + +NTSTATUS RTUSBWriteMACRegister( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN UINT32 Value); + +NTSTATUS RTUSBReadMACRegister( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT PUINT32 pValue); + +NTSTATUS RTUSBSingleWrite( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT Value); + +NTSTATUS RTUSBFirmwareRun( + IN PRTMP_ADAPTER pAd); + +NTSTATUS RTUSBFirmwareWrite( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFwImage, + IN ULONG FwLen); + +NTSTATUS RTUSBFirmwareOpmode( + IN PRTMP_ADAPTER pAd, + OUT PUINT32 pValue); + +NTSTATUS RTUSBVenderReset( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS RTUSBSetHardWareRegister( + IN PRTMP_ADAPTER pAdapter, + IN PVOID pBuf); + +NDIS_STATUS RTUSBQueryHardWareRegister( + IN PRTMP_ADAPTER pAdapter, + IN PVOID pBuf); + +VOID CMDHandler( + IN PRTMP_ADAPTER pAd); + + +NDIS_STATUS CreateThreads( + IN struct net_device *net_dev ); + + +VOID MacTableInitialize( + IN PRTMP_ADAPTER pAd); + +VOID MlmeSetPsm( + IN PRTMP_ADAPTER pAd, + IN USHORT psm); + +NDIS_STATUS RTMPWPAAddKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf); + +VOID AsicRxAntEvalAction( + IN PRTMP_ADAPTER pAd); + +void append_pkt( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + OUT PNDIS_PACKET *ppPacket); + +UINT deaggregate_AMSDU_announce( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize); + +NDIS_STATUS RTMPCheckRxError( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN PRXWI_STRUC pRxWI, + IN PRT28XX_RXD_STRUC pRxINFO); + + +VOID RTUSBMlmeHardTransmit( + IN PRTMP_ADAPTER pAd, + IN PMGMT_STRUC pMgmt); + +INT MlmeThread( + IN PVOID Context); + +// +// Function Prototype in rtusb_data.c +// +NDIS_STATUS RTUSBFreeDescriptorRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR BulkOutPipeId, + IN UINT32 NumberRequired); + + +BOOLEAN RTUSBNeedQueueBackForAgg( + IN RTMP_ADAPTER *pAd, + IN UCHAR BulkOutPipeId); + + +VOID RTMPWriteTxInfo( + IN PRTMP_ADAPTER pAd, + IN PTXINFO_STRUC pTxInfo, + IN USHORT USBDMApktLen, + IN BOOLEAN bWiv, + IN UCHAR QueueSel, + IN UCHAR NextValid, + IN UCHAR TxBurst); + +// +// Function Prototype in cmm_data_2870.c +// +USHORT RtmpUSB_WriteSubTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber); + +USHORT RtmpUSB_WriteSingleTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber); + +USHORT RtmpUSB_WriteFragTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber); + +USHORT RtmpUSB_WriteMultiTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber); + +VOID RtmpUSB_FinalWriteTxResource( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN USHORT totalMPDUSize, + IN USHORT TxIdx); + +VOID RtmpUSBDataLastTxIdx( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN USHORT TxIdx); + +VOID RtmpUSBDataKickOut( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx); + + +int RtmpUSBMgmtKickOut( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN PUCHAR pSrcBufVA, + IN UINT SrcBufLen); + +VOID RtmpUSBNullFrameKickOut( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN UCHAR *pNullFrame, + IN UINT32 frameLen); + +VOID RT28xxUsbStaAsicForceWakeup( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromTx); + +VOID RT28xxUsbStaAsicSleepThenAutoWakeup( + IN PRTMP_ADAPTER pAd, + IN USHORT TbttNumToNextWakeUp); + +VOID RT28xxUsbMlmeRadioOn( + IN PRTMP_ADAPTER pAd); + +VOID RT28xxUsbMlmeRadioOFF( + IN PRTMP_ADAPTER pAd); +#endif // RT2870 // + +//////////////////////////////////////// + +VOID QBSS_LoadInit( + IN RTMP_ADAPTER *pAd); + +UINT32 QBSS_LoadElementAppend( + IN RTMP_ADAPTER *pAd, + OUT UINT8 *buf_p); + +VOID QBSS_LoadUpdate( + IN RTMP_ADAPTER *pAd); + +/////////////////////////////////////// +INT RTMPShowCfgValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pName, + IN PUCHAR pBuf); + +PCHAR RTMPGetRalinkAuthModeStr( + IN NDIS_802_11_AUTHENTICATION_MODE authMode); + +PCHAR RTMPGetRalinkEncryModeStr( + IN USHORT encryMode); +////////////////////////////////////// + +#ifdef CONFIG_STA_SUPPORT +VOID AsicStaBbpTuning( + IN PRTMP_ADAPTER pAd); + +BOOLEAN StaAddMacTableEntry( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR MaxSupportedRateIn500Kbps, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN USHORT CapabilityInfo); +#endif // CONFIG_STA_SUPPORT // + +void RTMP_IndicateMediaState( + IN PRTMP_ADAPTER pAd); + +VOID ReSyncBeaconTime( + IN PRTMP_ADAPTER pAd); + +VOID RTMPSetAGCInitValue( + IN PRTMP_ADAPTER pAd, + IN UCHAR BandWidth); + +int rt28xx_close(IN PNET_DEV dev); +int rt28xx_open(IN PNET_DEV dev); + +__inline INT VIRTUAL_IF_UP(PRTMP_ADAPTER pAd) +{ +extern VOID MeshMakeBeacon(IN PRTMP_ADAPTER pAd, IN UCHAR idx); +extern VOID MeshUpdateBeaconFrame(IN PRTMP_ADAPTER pAd, IN UCHAR idx); + + if (VIRTUAL_IF_NUM(pAd) == 0) + { + if (rt28xx_open(pAd->net_dev) != 0) + return -1; + } + else + { + } + VIRTUAL_IF_INC(pAd); + return 0; +} + +__inline VOID VIRTUAL_IF_DOWN(PRTMP_ADAPTER pAd) +{ + VIRTUAL_IF_DEC(pAd); + if (VIRTUAL_IF_NUM(pAd) == 0) + rt28xx_close(pAd->net_dev); + return; +} + + +#endif // __RTMP_H__ + diff --git a/drivers/staging/rt3070/rtmp_ckipmic.h b/drivers/staging/rt3070/rtmp_ckipmic.h new file mode 100644 index 000000000000..a3d949a39d39 --- /dev/null +++ b/drivers/staging/rt3070/rtmp_ckipmic.h @@ -0,0 +1,113 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtmp_ckipmic.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#ifndef __RTMP_CKIPMIC_H__ +#define __RTMP_CKIPMIC_H__ + +typedef struct _MIC_CONTEXT { + /* --- MMH context */ + UCHAR CK[16]; /* the key */ + UCHAR coefficient[16]; /* current aes counter mode coefficients */ + ULONGLONG accum; /* accumulated mic, reduced to u32 in final() */ + UINT position; /* current position (byte offset) in message */ + UCHAR part[4]; /* for conversion of message to u32 for mmh */ +} MIC_CONTEXT, *PMIC_CONTEXT; + +VOID CKIP_key_permute( + OUT UCHAR *PK, /* output permuted key */ + IN UCHAR *CK, /* input CKIP key */ + IN UCHAR toDsFromDs, /* input toDs/FromDs bits */ + IN UCHAR *piv); /* input pointer to IV */ + +VOID RTMPCkipMicInit( + IN PMIC_CONTEXT pContext, + IN PUCHAR CK); + +VOID RTMPMicUpdate( + IN PMIC_CONTEXT pContext, + IN PUCHAR pOctets, + IN INT len); + +ULONG RTMPMicGetCoefficient( + IN PMIC_CONTEXT pContext); + +VOID xor_128( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out); + +UCHAR RTMPCkipSbox( + IN UCHAR a); + +VOID xor_32( + IN PUCHAR a, + IN PUCHAR b, + OUT PUCHAR out); + +VOID next_key( + IN PUCHAR key, + IN INT round); + +VOID byte_sub( + IN PUCHAR in, + OUT PUCHAR out); + +VOID shift_row( + IN PUCHAR in, + OUT PUCHAR out); + +VOID mix_column( + IN PUCHAR in, + OUT PUCHAR out); + +VOID RTMPAesEncrypt( + IN PUCHAR key, + IN PUCHAR data, + IN PUCHAR ciphertext); + +VOID RTMPMicFinal( + IN PMIC_CONTEXT pContext, + OUT UCHAR digest[4]); + +VOID RTMPCkipInsertCMIC( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pMIC, + IN PUCHAR p80211hdr, + IN PNDIS_PACKET pPacket, + IN PCIPHER_KEY pKey, + IN PUCHAR mic_snap); + +#endif //__RTMP_CKIPMIC_H__ diff --git a/drivers/staging/rt3070/rtmp_def.h b/drivers/staging/rt3070/rtmp_def.h new file mode 100644 index 000000000000..2599f7c836e8 --- /dev/null +++ b/drivers/staging/rt3070/rtmp_def.h @@ -0,0 +1,1559 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtmp_def.h + + Abstract: + Miniport related definition header + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 08-01-2002 created + John Chang 08-05-2003 add definition for 11g & other drafts +*/ +#ifndef __RTMP_DEF_H__ +#define __RTMP_DEF_H__ + +#include "oid.h" + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + + +#ifdef CONFIG_STA_SUPPORT +#endif // CONFIG_STA_SUPPORT // + +#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) +#define WSC_INCLUDED +#endif +// +// Debug information verbosity: lower values indicate higher urgency +// +#define RT_DEBUG_OFF 0 +#define RT_DEBUG_ERROR 1 +#define RT_DEBUG_WARN 2 +#define RT_DEBUG_TRACE 3 +#define RT_DEBUG_INFO 4 +#define RT_DEBUG_LOUD 5 + +#define NIC_TAG ((ULONG)'0682') +#define NIC_DBG_STRING ("**RT28xx**") + +#ifdef SNMP_SUPPORT +// for snmp +// to get manufacturer OUI, kathy, 2008_0220 +#define ManufacturerOUI_LEN 3 +#define ManufacturerNAME ("Ralink Technology Company.") +#define ResourceTypeIdName ("Ralink_ID") +#endif + + +//#define PACKED + +#define RALINK_2883_VERSION ((UINT32)0x28830300) +#define RALINK_2880E_VERSION ((UINT32)0x28720200) +#define RALINK_3070_VERSION ((UINT32)0x30700200) + +// +// NDIS version in use by the NIC driver. +// The high byte is the major version. The low byte is the minor version. +// +#ifdef NDIS51_MINIPORT +#define NIC_DRIVER_VERSION 0x0501 +#else +#define NIC_DRIVER_VERSION 0x0500 +#endif + +// +// NDIS media type, current is ethernet, change if native wireless supported +// +#define NIC_MEDIA_TYPE NdisMedium802_3 +#define NIC_PCI_HDR_LENGTH 0xe2 +#define NIC_MAX_PACKET_SIZE 2304 +#define NIC_HEADER_SIZE 14 +#define MAX_MAP_REGISTERS_NEEDED 32 +#define MIN_MAP_REGISTERS_NEEDED 2 //Todo: should consider fragment issue. + +// +// interface type, we use PCI +// +#define NIC_INTERFACE_TYPE NdisInterfacePci +#define NIC_INTERRUPT_MODE NdisInterruptLevelSensitive + +// +// buffer size passed in NdisMQueryAdapterResources +// We should only need three adapter resources (IO, interrupt and memory), +// Some devices get extra resources, so have room for 10 resources +// UF_SIZE (sizeof(NDIS_RESOURCE_LIST) + (10*sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR))) + + +#define NIC_RESOURCE_B// +// IO space length +// +#define NIC_MAP_IOSPACE_LENGTH sizeof(CSR_STRUC) + +#define MAX_RX_PKT_LEN 1520 + +// +// Entry number for each DMA descriptor ring +// + + +#ifdef RT2870 +#define TX_RING_SIZE 8 // 1 +#define PRIO_RING_SIZE 8 +#define MGMT_RING_SIZE 32 // PRIO_RING_SIZE +#define RX_RING_SIZE 8 +#define MAX_TX_PROCESS 4 +#define LOCAL_TXBUF_SIZE 2048 +#endif // RT2870 // + +#ifdef MULTIPLE_CARD_SUPPORT +// MC: Multple Cards +#define MAX_NUM_OF_MULTIPLE_CARD 32 +#endif // MULTIPLE_CARD_SUPPORT // + +#define MAX_RX_PROCESS 128 //64 //32 +#define NUM_OF_LOCAL_TXBUF 2 +#define TXD_SIZE 16 +#define TXWI_SIZE 16 +#define RXD_SIZE 16 +#define RXWI_SIZE 16 +// TXINFO_SIZE + TXWI_SIZE + 802.11 Header Size + AMSDU sub frame header +#define TX_DMA_1ST_BUFFER_SIZE 96 // only the 1st physical buffer is pre-allocated +#define MGMT_DMA_BUFFER_SIZE 1536 //2048 +#define RX_BUFFER_AGGRESIZE 3840 //3904 //3968 //4096 //2048 //4096 +#define RX_BUFFER_NORMSIZE 3840 //3904 //3968 //4096 //2048 //4096 +#define TX_BUFFER_NORMSIZE RX_BUFFER_NORMSIZE +#define MAX_FRAME_SIZE 2346 // Maximum 802.11 frame size +#define MAX_AGGREGATION_SIZE 3840 //3904 //3968 //4096 +#define MAX_NUM_OF_TUPLE_CACHE 2 +#define MAX_MCAST_LIST_SIZE 32 +#define MAX_LEN_OF_VENDOR_DESC 64 +//#define MAX_SIZE_OF_MCAST_PSQ (NUM_OF_LOCAL_TXBUF >> 2) // AP won't spend more than 1/4 of total buffers on M/BCAST PSQ +#define MAX_SIZE_OF_MCAST_PSQ 32 + +#define MAX_RX_PROCESS_CNT (RX_RING_SIZE) + + +#define MAX_PACKETS_IN_QUEUE (512) //(512) // to pass WMM A5-WPAPSK +#define MAX_PACKETS_IN_MCAST_PS_QUEUE 32 +#define MAX_PACKETS_IN_PS_QUEUE 128 //32 +#define WMM_NUM_OF_AC 4 /* AC0, AC1, AC2, and AC3 */ + + +//2008/09/11:KH add to support efuse<-- +#define MAX_EEPROM_BIN_FILE_SIZE 1024 +//2008/09/11:KH add to support efuse--> + +// RxFilter +#define STANORMAL 0x17f97 +#define APNORMAL 0x15f97 +// +// RTMP_ADAPTER flags +// +#define fRTMP_ADAPTER_MAP_REGISTER 0x00000001 +#define fRTMP_ADAPTER_INTERRUPT_IN_USE 0x00000002 +#define fRTMP_ADAPTER_HARDWARE_ERROR 0x00000004 +#define fRTMP_ADAPTER_SCATTER_GATHER 0x00000008 +#define fRTMP_ADAPTER_SEND_PACKET_ERROR 0x00000010 +#define fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS 0x00000020 +#define fRTMP_ADAPTER_HALT_IN_PROGRESS 0x00000040 +#define fRTMP_ADAPTER_RESET_IN_PROGRESS 0x00000080 +#define fRTMP_ADAPTER_NIC_NOT_EXIST 0x00000100 +#define fRTMP_ADAPTER_TX_RING_ALLOCATED 0x00000200 +#define fRTMP_ADAPTER_REMOVE_IN_PROGRESS 0x00000400 +#define fRTMP_ADAPTER_MIMORATE_INUSED 0x00000800 +#define fRTMP_ADAPTER_RX_RING_ALLOCATED 0x00001000 +#define fRTMP_ADAPTER_INTERRUPT_ACTIVE 0x00002000 +#define fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS 0x00004000 +#define fRTMP_ADAPTER_REASSOC_IN_PROGRESS 0x00008000 +#define fRTMP_ADAPTER_MEDIA_STATE_PENDING 0x00010000 +#define fRTMP_ADAPTER_RADIO_OFF 0x00020000 +#define fRTMP_ADAPTER_BULKOUT_RESET 0x00040000 +#define fRTMP_ADAPTER_BULKIN_RESET 0x00080000 +#define fRTMP_ADAPTER_RDG_ACTIVE 0x00100000 +#define fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE 0x00200000 +#define fRTMP_ADAPTER_SCAN_2040 0x04000000 +#define fRTMP_ADAPTER_RADIO_MEASUREMENT 0x08000000 + +#define fRTMP_ADAPTER_START_UP 0x10000000 //Devive already initialized and enabled Tx/Rx. +#define fRTMP_ADAPTER_MEDIA_STATE_CHANGE 0x20000000 +#define fRTMP_ADAPTER_IDLE_RADIO_OFF 0x40000000 + +// Lock bit for accessing different ring buffers +//#define fRTMP_ADAPTER_TX_RING_BUSY 0x80000000 +//#define fRTMP_ADAPTER_MGMT_RING_BUSY 0x40000000 +//#define fRTMP_ADAPTER_ATIM_RING_BUSY 0x20000000 +//#define fRTMP_ADAPTER_RX_RING_BUSY 0x10000000 + +// Lock bit for accessing different queue +//#define fRTMP_ADAPTER_TX_QUEUE_BUSY 0x08000000 +//#define fRTMP_ADAPTER_MGMT_QUEUE_BUSY 0x04000000 + +// +// STA operation status flags +// +#define fOP_STATUS_INFRA_ON 0x00000001 +#define fOP_STATUS_ADHOC_ON 0x00000002 +#define fOP_STATUS_BG_PROTECTION_INUSED 0x00000004 +#define fOP_STATUS_SHORT_SLOT_INUSED 0x00000008 +#define fOP_STATUS_SHORT_PREAMBLE_INUSED 0x00000010 +#define fOP_STATUS_RECEIVE_DTIM 0x00000020 +//#define fOP_STATUS_TX_RATE_SWITCH_ENABLED 0x00000040 +#define fOP_STATUS_MEDIA_STATE_CONNECTED 0x00000080 +#define fOP_STATUS_WMM_INUSED 0x00000100 +#define fOP_STATUS_AGGREGATION_INUSED 0x00000200 +#define fOP_STATUS_DOZE 0x00000400 // debug purpose +#define fOP_STATUS_PIGGYBACK_INUSED 0x00000800 // piggy-back, and aggregation +#define fOP_STATUS_APSD_INUSED 0x00001000 +#define fOP_STATUS_TX_AMSDU_INUSED 0x00002000 +#define fOP_STATUS_MAX_RETRY_ENABLED 0x00004000 +#define fOP_STATUS_WAKEUP_NOW 0x00008000 +#define fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE 0x00020000 + +#ifdef DOT11N_DRAFT3 +#define fOP_STATUS_SCAN_2040 0x00040000 +#endif // DOT11N_DRAFT3 // + +#define CCKSETPROTECT 0x1 +#define OFDMSETPROTECT 0x2 +#define MM20SETPROTECT 0x4 +#define MM40SETPROTECT 0x8 +#define GF20SETPROTECT 0x10 +#define GR40SETPROTECT 0x20 +#define ALLN_SETPROTECT (GR40SETPROTECT | GF20SETPROTECT | MM40SETPROTECT | MM20SETPROTECT) + +// +// AP's client table operation status flags +// +#define fCLIENT_STATUS_WMM_CAPABLE 0x00000001 // CLIENT can parse QOS DATA frame +#define fCLIENT_STATUS_AGGREGATION_CAPABLE 0x00000002 // CLIENT can receive Ralink's proprietary TX aggregation frame +#define fCLIENT_STATUS_PIGGYBACK_CAPABLE 0x00000004 // CLIENT support piggy-back +#define fCLIENT_STATUS_AMSDU_INUSED 0x00000008 +#define fCLIENT_STATUS_SGI20_CAPABLE 0x00000010 +#define fCLIENT_STATUS_SGI40_CAPABLE 0x00000020 +#define fCLIENT_STATUS_TxSTBC_CAPABLE 0x00000040 +#define fCLIENT_STATUS_RxSTBC_CAPABLE 0x00000080 +#define fCLIENT_STATUS_HTC_CAPABLE 0x00000100 +#define fCLIENT_STATUS_RDG_CAPABLE 0x00000200 +#define fCLIENT_STATUS_MCSFEEDBACK_CAPABLE 0x00000400 +#define fCLIENT_STATUS_APSD_CAPABLE 0x00000800 /* UAPSD STATION */ + +#ifdef DOT11N_DRAFT3 +#define fCLIENT_STATUS_BSSCOEXIST_CAPABLE 0x00001000 +#endif // DOT11N_DRAFT3 // + +#define fCLIENT_STATUS_RALINK_CHIPSET 0x00100000 +// +// STA configuration flags +// +//#define fSTA_CFG_ENABLE_TX_BURST 0x00000001 + +// 802.11n Operating Mode Definition. 0-3 also used in ASICUPdateProtect switch case +#define HT_NO_PROTECT 0 +#define HT_LEGACY_PROTECT 1 +#define HT_40_PROTECT 2 +#define HT_2040_PROTECT 3 +#define HT_RTSCTS_6M 7 +//following is our own definition in order to turn on our ASIC protection register in INFRASTRUCTURE. +#define HT_ATHEROS 8 +#define HT_FORCERTSCTS 9 // Force turn on RTS/CTS first. then go to evaluate if this force RTS is necessary. + +// +// RX Packet Filter control flags. Apply on pAd->PacketFilter +// +#define fRX_FILTER_ACCEPT_DIRECT NDIS_PACKET_TYPE_DIRECTED +#define fRX_FILTER_ACCEPT_MULTICAST NDIS_PACKET_TYPE_MULTICAST +#define fRX_FILTER_ACCEPT_BROADCAST NDIS_PACKET_TYPE_BROADCAST +#define fRX_FILTER_ACCEPT_ALL_MULTICAST NDIS_PACKET_TYPE_ALL_MULTICAST + +// +// Error code section +// +// NDIS_ERROR_CODE_ADAPTER_NOT_FOUND +#define ERRLOG_READ_PCI_SLOT_FAILED 0x00000101L +#define ERRLOG_WRITE_PCI_SLOT_FAILED 0x00000102L +#define ERRLOG_VENDOR_DEVICE_NOMATCH 0x00000103L + +// NDIS_ERROR_CODE_ADAPTER_DISABLED +#define ERRLOG_BUS_MASTER_DISABLED 0x00000201L + +// NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION +#define ERRLOG_INVALID_SPEED_DUPLEX 0x00000301L +#define ERRLOG_SET_SECONDARY_FAILED 0x00000302L + +// NDIS_ERROR_CODE_OUT_OF_RESOURCES +#define ERRLOG_OUT_OF_MEMORY 0x00000401L +#define ERRLOG_OUT_OF_SHARED_MEMORY 0x00000402L +#define ERRLOG_OUT_OF_MAP_REGISTERS 0x00000403L +#define ERRLOG_OUT_OF_BUFFER_POOL 0x00000404L +#define ERRLOG_OUT_OF_NDIS_BUFFER 0x00000405L +#define ERRLOG_OUT_OF_PACKET_POOL 0x00000406L +#define ERRLOG_OUT_OF_NDIS_PACKET 0x00000407L +#define ERRLOG_OUT_OF_LOOKASIDE_MEMORY 0x00000408L + +// NDIS_ERROR_CODE_HARDWARE_FAILURE +#define ERRLOG_SELFTEST_FAILED 0x00000501L +#define ERRLOG_INITIALIZE_ADAPTER 0x00000502L +#define ERRLOG_REMOVE_MINIPORT 0x00000503L + +// NDIS_ERROR_CODE_RESOURCE_CONFLICT +#define ERRLOG_MAP_IO_SPACE 0x00000601L +#define ERRLOG_QUERY_ADAPTER_RESOURCES 0x00000602L +#define ERRLOG_NO_IO_RESOURCE 0x00000603L +#define ERRLOG_NO_INTERRUPT_RESOURCE 0x00000604L +#define ERRLOG_NO_MEMORY_RESOURCE 0x00000605L + + +// WDS definition +#define MAX_WDS_ENTRY 4 +#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table + +#define WDS_DISABLE_MODE 0 +#define WDS_RESTRICT_MODE 1 +#define WDS_BRIDGE_MODE 2 +#define WDS_REPEATER_MODE 3 +#define WDS_LAZY_MODE 4 + + +#define MAX_MESH_NUM 0 + +#define MAX_APCLI_NUM 0 + +#define MAX_MBSSID_NUM 1 +#ifdef MBSS_SUPPORT +#undef MAX_MBSSID_NUM +#define MAX_MBSSID_NUM (8 - MAX_MESH_NUM - MAX_APCLI_NUM) +#endif // MBSS_SUPPORT // + +/* sanity check for apidx */ +#define MBSS_MR_APIDX_SANITY_CHECK(apidx) \ + { if (apidx > MAX_MBSSID_NUM) { \ + printk("%s> Error! apidx = %d > MAX_MBSSID_NUM!\n", __FUNCTION__, apidx); \ + apidx = MAIN_MBSSID; } } + +#define VALID_WCID(_wcid) ((_wcid) > 0 && (_wcid) < MAX_LEN_OF_MAC_TABLE ) + +#define MAIN_MBSSID 0 +#define FIRST_MBSSID 1 + + +#define MAX_BEACON_SIZE 512 +// If the MAX_MBSSID_NUM is larger than 6, +// it shall reserve some WCID space(wcid 222~253) for beacon frames. +// - these wcid 238~253 are reserved for beacon#6(ra6). +// - these wcid 222~237 are reserved for beacon#7(ra7). +#if defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 8) +#define HW_RESERVED_WCID 222 +#elif defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 7) +#define HW_RESERVED_WCID 238 +#else +#define HW_RESERVED_WCID 255 +#endif + +// Then dedicate wcid of DFS and Carrier-Sense. +#define DFS_CTS_WCID (HW_RESERVED_WCID - 1) +#define CS_CTS_WCID (HW_RESERVED_WCID - 2) +#define LAST_SPECIFIC_WCID (HW_RESERVED_WCID - 2) + +// If MAX_MBSSID_NUM is 8, the maximum available wcid for the associated STA is 211. +// If MAX_MBSSID_NUM is 7, the maximum available wcid for the associated STA is 228. +#define MAX_AVAILABLE_CLIENT_WCID (LAST_SPECIFIC_WCID - MAX_MBSSID_NUM - 1) + +// TX need WCID to find Cipher Key +// these wcid 212 ~ 219 are reserved for bc/mc packets if MAX_MBSSID_NUM is 8. +#define GET_GroupKey_WCID(__wcid, __bssidx) \ + { \ + __wcid = LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM) + __bssidx; \ + } + +#define IsGroupKeyWCID(__wcid) (((__wcid) < LAST_SPECIFIC_WCID) && ((__wcid) >= (LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM)))) + + +// definition to support multiple BSSID +#define BSS0 0 +#define BSS1 1 +#define BSS2 2 +#define BSS3 3 +#define BSS4 4 +#define BSS5 5 +#define BSS6 6 +#define BSS7 7 + + +//============================================================ +// Length definitions +#define PEER_KEY_NO 2 +#define MAC_ADDR_LEN 6 +#define TIMESTAMP_LEN 8 +#define MAX_LEN_OF_SUPPORTED_RATES MAX_LENGTH_OF_SUPPORT_RATES // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 +#define MAX_LEN_OF_KEY 32 // 32 octets == 256 bits, Redefine for WPA +#define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination +#define MAX_NUM_OF_11JCHANNELS 20 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination +#define MAX_LEN_OF_SSID 32 +#define CIPHER_TEXT_LEN 128 +#define HASH_TABLE_SIZE 256 +#define MAX_VIE_LEN 1024 // New for WPA cipher suite variable IE sizes. +#define MAX_SUPPORT_MCS 32 + +//============================================================ +// ASIC WCID Table definition. +//============================================================ +#define BSSID_WCID 1 // in infra mode, always put bssid with this WCID +#define MCAST_WCID 0x0 +#define BSS0Mcast_WCID 0x0 +#define BSS1Mcast_WCID 0xf8 +#define BSS2Mcast_WCID 0xf9 +#define BSS3Mcast_WCID 0xfa +#define BSS4Mcast_WCID 0xfb +#define BSS5Mcast_WCID 0xfc +#define BSS6Mcast_WCID 0xfd +#define BSS7Mcast_WCID 0xfe +#define RESERVED_WCID 0xff + +#define MAX_NUM_OF_ACL_LIST MAX_NUMBER_OF_ACL + +#define MAX_LEN_OF_MAC_TABLE MAX_NUMBER_OF_MAC // if MAX_MBSSID_NUM is 8, this value can't be larger than 211 + +#if MAX_LEN_OF_MAC_TABLE>MAX_AVAILABLE_CLIENT_WCID +#error MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!! +#endif + +#define MAX_NUM_OF_WDS_LINK_PERBSSID 3 +#define MAX_NUM_OF_WDS_LINK (MAX_NUM_OF_WDS_LINK_PERBSSID*MAX_MBSSID_NUM) +#define MAX_NUM_OF_EVENT MAX_NUMBER_OF_EVENT +#define WDS_LINK_START_WCID (MAX_LEN_OF_MAC_TABLE-1) + +#define NUM_OF_TID 8 +#define MAX_AID_BA 4 +#define MAX_LEN_OF_BA_REC_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) //Block ACK recipient +#define MAX_LEN_OF_BA_ORI_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) // Block ACK originator +#define MAX_LEN_OF_BSS_TABLE 64 +#define MAX_REORDERING_MPDU_NUM 512 + +// key related definitions +#define SHARE_KEY_NUM 4 +#define MAX_LEN_OF_SHARE_KEY 16 // byte count +#define MAX_LEN_OF_PEER_KEY 16 // byte count +#define PAIRWISE_KEY_NUM 64 // in MAC ASIC pairwise key table +#define GROUP_KEY_NUM 4 +#define PMK_LEN 32 +#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table +#define PMKID_NO 4 // Number of PMKID saved supported +#define MAX_LEN_OF_MLME_BUFFER 2048 + +// power status related definitions +#define PWR_ACTIVE 0 +#define PWR_SAVE 1 +#define PWR_MMPS 2 //MIMO power save +//#define PWR_UNKNOWN 2 + +// Auth and Assoc mode related definitions +#define AUTH_MODE_OPEN 0x00 +#define AUTH_MODE_KEY 0x01 +//#define AUTH_MODE_AUTO_SWITCH 0x03 +//#define AUTH_MODE_DEAUTH 0x04 +//#define AUTH_MODE_UPLAYER 0x05 // reserved for 802.11i use + +// BSS Type definitions +#define BSS_ADHOC 0 // = Ndis802_11IBSS +#define BSS_INFRA 1 // = Ndis802_11Infrastructure +#define BSS_ANY 2 // = Ndis802_11AutoUnknown +#define BSS_MONITOR 3 // = Ndis802_11Monitor + + +// Reason code definitions +#define REASON_RESERVED 0 +#define REASON_UNSPECIFY 1 +#define REASON_NO_LONGER_VALID 2 +#define REASON_DEAUTH_STA_LEAVING 3 +#define REASON_DISASSOC_INACTIVE 4 +#define REASON_DISASSPC_AP_UNABLE 5 +#define REASON_CLS2ERR 6 +#define REASON_CLS3ERR 7 +#define REASON_DISASSOC_STA_LEAVING 8 +#define REASON_STA_REQ_ASSOC_NOT_AUTH 9 +#define REASON_INVALID_IE 13 +#define REASON_MIC_FAILURE 14 +#define REASON_4_WAY_TIMEOUT 15 +#define REASON_GROUP_KEY_HS_TIMEOUT 16 +#define REASON_IE_DIFFERENT 17 +#define REASON_MCIPHER_NOT_VALID 18 +#define REASON_UCIPHER_NOT_VALID 19 +#define REASON_AKMP_NOT_VALID 20 +#define REASON_UNSUPPORT_RSNE_VER 21 +#define REASON_INVALID_RSNE_CAP 22 +#define REASON_8021X_AUTH_FAIL 23 +#define REASON_CIPHER_SUITE_REJECTED 24 +#define REASON_DECLINED 37 + +#define REASON_QOS_UNSPECIFY 32 +#define REASON_QOS_LACK_BANDWIDTH 33 +#define REASON_POOR_CHANNEL_CONDITION 34 +#define REASON_QOS_OUTSIDE_TXOP_LIMITION 35 +#define REASON_QOS_QSTA_LEAVING_QBSS 36 +#define REASON_QOS_UNWANTED_MECHANISM 37 +#define REASON_QOS_MECH_SETUP_REQUIRED 38 +#define REASON_QOS_REQUEST_TIMEOUT 39 +#define REASON_QOS_CIPHER_NOT_SUPPORT 45 + +// Status code definitions +#define MLME_SUCCESS 0 +#define MLME_UNSPECIFY_FAIL 1 +#define MLME_CANNOT_SUPPORT_CAP 10 +#define MLME_REASSOC_DENY_ASSOC_EXIST 11 +#define MLME_ASSOC_DENY_OUT_SCOPE 12 +#define MLME_ALG_NOT_SUPPORT 13 +#define MLME_SEQ_NR_OUT_OF_SEQUENCE 14 +#define MLME_REJ_CHALLENGE_FAILURE 15 +#define MLME_REJ_TIMEOUT 16 +#define MLME_ASSOC_REJ_UNABLE_HANDLE_STA 17 +#define MLME_ASSOC_REJ_DATA_RATE 18 + +#define MLME_ASSOC_REJ_NO_EXT_RATE 22 +#define MLME_ASSOC_REJ_NO_EXT_RATE_PBCC 23 +#define MLME_ASSOC_REJ_NO_CCK_OFDM 24 + +#define MLME_QOS_UNSPECIFY 32 +#define MLME_REQUEST_DECLINED 37 +#define MLME_REQUEST_WITH_INVALID_PARAM 38 +#define MLME_DLS_NOT_ALLOW_IN_QBSS 48 +#define MLME_DEST_STA_NOT_IN_QBSS 49 +#define MLME_DEST_STA_IS_NOT_A_QSTA 50 + +#define MLME_INVALID_FORMAT 0x51 +#define MLME_FAIL_NO_RESOURCE 0x52 +#define MLME_STATE_MACHINE_REJECT 0x53 +#define MLME_MAC_TABLE_FAIL 0x54 + +// IE code +#define IE_SSID 0 +#define IE_SUPP_RATES 1 +#define IE_FH_PARM 2 +#define IE_DS_PARM 3 +#define IE_CF_PARM 4 +#define IE_TIM 5 +#define IE_IBSS_PARM 6 +#define IE_COUNTRY 7 // 802.11d +#define IE_802_11D_REQUEST 10 // 802.11d +#define IE_QBSS_LOAD 11 // 802.11e d9 +#define IE_EDCA_PARAMETER 12 // 802.11e d9 +#define IE_TSPEC 13 // 802.11e d9 +#define IE_TCLAS 14 // 802.11e d9 +#define IE_SCHEDULE 15 // 802.11e d9 +#define IE_CHALLENGE_TEXT 16 +#define IE_POWER_CONSTRAINT 32 // 802.11h d3.3 +#define IE_POWER_CAPABILITY 33 // 802.11h d3.3 +#define IE_TPC_REQUEST 34 // 802.11h d3.3 +#define IE_TPC_REPORT 35 // 802.11h d3.3 +#define IE_SUPP_CHANNELS 36 // 802.11h d3.3 +#define IE_CHANNEL_SWITCH_ANNOUNCEMENT 37 // 802.11h d3.3 +#define IE_MEASUREMENT_REQUEST 38 // 802.11h d3.3 +#define IE_MEASUREMENT_REPORT 39 // 802.11h d3.3 +#define IE_QUIET 40 // 802.11h d3.3 +#define IE_IBSS_DFS 41 // 802.11h d3.3 +#define IE_ERP 42 // 802.11g +#define IE_TS_DELAY 43 // 802.11e d9 +#define IE_TCLAS_PROCESSING 44 // 802.11e d9 +#define IE_QOS_CAPABILITY 46 // 802.11e d6 +#define IE_HT_CAP 45 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD +#define IE_AP_CHANNEL_REPORT 51 // 802.11k d6 +#define IE_HT_CAP2 52 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD +#define IE_RSN 48 // 802.11i d3.0 +#define IE_WPA2 48 // WPA2 +#define IE_EXT_SUPP_RATES 50 // 802.11g +#define IE_SUPP_REG_CLASS 59 // 802.11y. Supported regulatory classes. +#define IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT 60 // 802.11n +#define IE_ADD_HT 61 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD +#define IE_ADD_HT2 53 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD + + +// For 802.11n D3.03 +//#define IE_NEW_EXT_CHA_OFFSET 62 // 802.11n d1. New extension channel offset elemet +#define IE_SECONDARY_CH_OFFSET 62 // 802.11n D3.03 Secondary Channel Offset element +#define IE_WAPI 68 // WAPI information element +#define IE_2040_BSS_COEXIST 72 // 802.11n D3.0.3 +#define IE_2040_BSS_INTOLERANT_REPORT 73 // 802.11n D3.03 +#define IE_OVERLAPBSS_SCAN_PARM 74 // 802.11n D3.03 +#define IE_EXT_CAPABILITY 127 // 802.11n D3.03 + + +#define IE_WPA 221 // WPA +#define IE_VENDOR_SPECIFIC 221 // Wifi WMM (WME) + +#define OUI_BROADCOM_HT 51 // +#define OUI_BROADCOM_HTADD 52 // +#define OUI_PREN_HT_CAP 51 // +#define OUI_PREN_ADD_HT 52 // + +// CCX information +#define IE_AIRONET_CKIP 133 // CCX1.0 ID 85H for CKIP +#define IE_AP_TX_POWER 150 // CCX 2.0 for AP transmit power +#define IE_MEASUREMENT_CAPABILITY 221 // CCX 2.0 +#define IE_CCX_V2 221 +#define IE_AIRONET_IPADDRESS 149 // CCX ID 95H for IP Address +#define IE_AIRONET_CCKMREASSOC 156 // CCX ID 9CH for CCKM Reassociation Request element +#define CKIP_NEGOTIATION_LENGTH 30 +#define AIRONET_IPADDRESS_LENGTH 10 +#define AIRONET_CCKMREASSOC_LENGTH 24 + +// ======================================================== +// MLME state machine definition +// ======================================================== + +// STA MLME state mahcines +#define ASSOC_STATE_MACHINE 1 +#define AUTH_STATE_MACHINE 2 +#define AUTH_RSP_STATE_MACHINE 3 +#define SYNC_STATE_MACHINE 4 +#define MLME_CNTL_STATE_MACHINE 5 +#define WPA_PSK_STATE_MACHINE 6 +#define LEAP_STATE_MACHINE 7 +#define AIRONET_STATE_MACHINE 8 +#define ACTION_STATE_MACHINE 9 + +// AP MLME state machines +#define AP_ASSOC_STATE_MACHINE 11 +#define AP_AUTH_STATE_MACHINE 12 +#define AP_AUTH_RSP_STATE_MACHINE 13 +#define AP_SYNC_STATE_MACHINE 14 +#define AP_CNTL_STATE_MACHINE 15 +#define AP_WPA_STATE_MACHINE 16 + +#define WSC_STATE_MACHINE 17 +#define WSC_UPNP_STATE_MACHINE 18 + + + +#ifdef QOS_DLS_SUPPORT +#define DLS_STATE_MACHINE 26 +#endif // QOS_DLS_SUPPORT // + +// +// STA's CONTROL/CONNECT state machine: states, events, total function # +// +#define CNTL_IDLE 0 +#define CNTL_WAIT_DISASSOC 1 +#define CNTL_WAIT_JOIN 2 +#define CNTL_WAIT_REASSOC 3 +#define CNTL_WAIT_START 4 +#define CNTL_WAIT_AUTH 5 +#define CNTL_WAIT_ASSOC 6 +#define CNTL_WAIT_AUTH2 7 +#define CNTL_WAIT_OID_LIST_SCAN 8 +#define CNTL_WAIT_OID_DISASSOC 9 +#ifdef RT2870 +#define CNTL_WAIT_SCAN_FOR_CONNECT 10 +#endif // RT2870 // + +#define MT2_ASSOC_CONF 34 +#define MT2_AUTH_CONF 35 +#define MT2_DEAUTH_CONF 36 +#define MT2_DISASSOC_CONF 37 +#define MT2_REASSOC_CONF 38 +#define MT2_PWR_MGMT_CONF 39 +#define MT2_JOIN_CONF 40 +#define MT2_SCAN_CONF 41 +#define MT2_START_CONF 42 +#define MT2_GET_CONF 43 +#define MT2_SET_CONF 44 +#define MT2_RESET_CONF 45 +#define MT2_MLME_ROAMING_REQ 52 + +#define CNTL_FUNC_SIZE 1 + +// +// STA's ASSOC state machine: states, events, total function # +// +#define ASSOC_IDLE 0 +#define ASSOC_WAIT_RSP 1 +#define REASSOC_WAIT_RSP 2 +#define DISASSOC_WAIT_RSP 3 +#define MAX_ASSOC_STATE 4 + +#define ASSOC_MACHINE_BASE 0 +#define MT2_MLME_ASSOC_REQ 0 +#define MT2_MLME_REASSOC_REQ 1 +#define MT2_MLME_DISASSOC_REQ 2 +#define MT2_PEER_DISASSOC_REQ 3 +#define MT2_PEER_ASSOC_REQ 4 +#define MT2_PEER_ASSOC_RSP 5 +#define MT2_PEER_REASSOC_REQ 6 +#define MT2_PEER_REASSOC_RSP 7 +#define MT2_DISASSOC_TIMEOUT 8 +#define MT2_ASSOC_TIMEOUT 9 +#define MT2_REASSOC_TIMEOUT 10 +#define MAX_ASSOC_MSG 11 + +#define ASSOC_FUNC_SIZE (MAX_ASSOC_STATE * MAX_ASSOC_MSG) + +// +// ACT state machine: states, events, total function # +// +#define ACT_IDLE 0 +#define MAX_ACT_STATE 1 + +#define ACT_MACHINE_BASE 0 + +//Those PEER_xx_CATE number is based on real Categary value in IEEE spec. Please don'es modify it by your self. +//Category +#define MT2_PEER_SPECTRUM_CATE 0 +#define MT2_PEER_QOS_CATE 1 +#define MT2_PEER_DLS_CATE 2 +#define MT2_PEER_BA_CATE 3 +#define MT2_PEER_PUBLIC_CATE 4 +#define MT2_PEER_RM_CATE 5 +#define MT2_PEER_HT_CATE 7 // 7.4.7 +#define MAX_PEER_CATE_MSG 7 +#define MT2_MLME_ADD_BA_CATE 8 +#define MT2_MLME_ORI_DELBA_CATE 9 +#define MT2_MLME_REC_DELBA_CATE 10 +#define MT2_MLME_QOS_CATE 11 +#define MT2_MLME_DLS_CATE 12 +#define MT2_ACT_INVALID 13 +#define MAX_ACT_MSG 14 + +//Category field +#define CATEGORY_SPECTRUM 0 +#define CATEGORY_QOS 1 +#define CATEGORY_DLS 2 +#define CATEGORY_BA 3 +#define CATEGORY_PUBLIC 4 +#define CATEGORY_RM 5 +#define CATEGORY_HT 7 + + +// DLS Action frame definition +#define ACTION_DLS_REQUEST 0 +#define ACTION_DLS_RESPONSE 1 +#define ACTION_DLS_TEARDOWN 2 + +//Spectrum Action field value 802.11h 7.4.1 +#define SPEC_MRQ 0 // Request +#define SPEC_MRP 1 //Report +#define SPEC_TPCRQ 2 +#define SPEC_TPCRP 3 +#define SPEC_CHANNEL_SWITCH 4 + + +//BA Action field value +#define ADDBA_REQ 0 +#define ADDBA_RESP 1 +#define DELBA 2 + +//Public's Action field value in Public Category. Some in 802.11y and some in 11n +#define ACTION_BSS_2040_COEXIST 0 // 11n +#define ACTION_DSE_ENABLEMENT 1 // 11y D9.0 +#define ACTION_DSE_DEENABLEMENT 2 // 11y D9.0 +#define ACTION_DSE_REG_LOCATION_ANNOUNCE 3 // 11y D9.0 +#define ACTION_EXT_CH_SWITCH_ANNOUNCE 4 // 11y D9.0 +#define ACTION_DSE_MEASUREMENT_REQ 5 // 11y D9.0 +#define ACTION_DSE_MEASUREMENT_REPORT 6 // 11y D9.0 +#define ACTION_MEASUREMENT_PILOT_ACTION 7 // 11y D9.0 +#define ACTION_DSE_POWER_CONSTRAINT 8 // 11y D9.0 + + +//HT Action field value +#define NOTIFY_BW_ACTION 0 +#define SMPS_ACTION 1 +#define PSMP_ACTION 2 +#define SETPCO_ACTION 3 +#define MIMO_CHA_MEASURE_ACTION 4 +#define MIMO_N_BEACONFORM 5 +#define MIMO_BEACONFORM 6 +#define ANTENNA_SELECT 7 +#define HT_INFO_EXCHANGE 8 + +#define ACT_FUNC_SIZE (MAX_ACT_STATE * MAX_ACT_MSG) +// +// STA's AUTHENTICATION state machine: states, evvents, total function # +// +#define AUTH_REQ_IDLE 0 +#define AUTH_WAIT_SEQ2 1 +#define AUTH_WAIT_SEQ4 2 +#define MAX_AUTH_STATE 3 + +#define AUTH_MACHINE_BASE 0 +#define MT2_MLME_AUTH_REQ 0 +#define MT2_PEER_AUTH_EVEN 1 +#define MT2_AUTH_TIMEOUT 2 +#define MAX_AUTH_MSG 3 + +#define AUTH_FUNC_SIZE (MAX_AUTH_STATE * MAX_AUTH_MSG) + +// +// STA's AUTH_RSP state machine: states, events, total function # +// +#define AUTH_RSP_IDLE 0 +#define AUTH_RSP_WAIT_CHAL 1 +#define MAX_AUTH_RSP_STATE 2 + +#define AUTH_RSP_MACHINE_BASE 0 +#define MT2_AUTH_CHALLENGE_TIMEOUT 0 +#define MT2_PEER_AUTH_ODD 1 +#define MT2_PEER_DEAUTH 2 +#define MAX_AUTH_RSP_MSG 3 + +#define AUTH_RSP_FUNC_SIZE (MAX_AUTH_RSP_STATE * MAX_AUTH_RSP_MSG) + +// +// STA's SYNC state machine: states, events, total function # +// +#define SYNC_IDLE 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state +#define JOIN_WAIT_BEACON 1 +#define SCAN_LISTEN 2 +#define MAX_SYNC_STATE 3 + +#define SYNC_MACHINE_BASE 0 +#define MT2_MLME_SCAN_REQ 0 +#define MT2_MLME_JOIN_REQ 1 +#define MT2_MLME_START_REQ 2 +#define MT2_PEER_BEACON 3 +#define MT2_PEER_PROBE_RSP 4 +#define MT2_PEER_ATIM 5 +#define MT2_SCAN_TIMEOUT 6 +#define MT2_BEACON_TIMEOUT 7 +#define MT2_ATIM_TIMEOUT 8 +#define MT2_PEER_PROBE_REQ 9 +#define MAX_SYNC_MSG 10 + +#define SYNC_FUNC_SIZE (MAX_SYNC_STATE * MAX_SYNC_MSG) + +//Messages for the DLS state machine +#define DLS_IDLE 0 +#define MAX_DLS_STATE 1 + +#define DLS_MACHINE_BASE 0 +#define MT2_MLME_DLS_REQ 0 +#define MT2_PEER_DLS_REQ 1 +#define MT2_PEER_DLS_RSP 2 +#define MT2_MLME_DLS_TEAR_DOWN 3 +#define MT2_PEER_DLS_TEAR_DOWN 4 +#define MAX_DLS_MSG 5 + +#define DLS_FUNC_SIZE (MAX_DLS_STATE * MAX_DLS_MSG) + +// +// STA's WPA-PSK State machine: states, events, total function # +// +#define WPA_PSK_IDLE 0 +#define MAX_WPA_PSK_STATE 1 + +#define WPA_MACHINE_BASE 0 +#define MT2_EAPPacket 0 +#define MT2_EAPOLStart 1 +#define MT2_EAPOLLogoff 2 +#define MT2_EAPOLKey 3 +#define MT2_EAPOLASFAlert 4 +#define MAX_WPA_PSK_MSG 5 + +#define WPA_PSK_FUNC_SIZE (MAX_WPA_PSK_STATE * MAX_WPA_PSK_MSG) + +// +// STA's CISCO-AIRONET State machine: states, events, total function # +// +#define AIRONET_IDLE 0 +#define AIRONET_SCANNING 1 +#define MAX_AIRONET_STATE 2 + +#define AIRONET_MACHINE_BASE 0 +#define MT2_AIRONET_MSG 0 +#define MT2_AIRONET_SCAN_REQ 1 +#define MT2_AIRONET_SCAN_DONE 2 +#define MAX_AIRONET_MSG 3 + +#define AIRONET_FUNC_SIZE (MAX_AIRONET_STATE * MAX_AIRONET_MSG) + +// +// WSC State machine: states, events, total function # +// + +// +// AP's CONTROL/CONNECT state machine: states, events, total function # +// +#define AP_CNTL_FUNC_SIZE 1 + +// +// AP's ASSOC state machine: states, events, total function # +// +#define AP_ASSOC_IDLE 0 +#define AP_MAX_ASSOC_STATE 1 + +#define AP_ASSOC_MACHINE_BASE 0 +#define APMT2_MLME_DISASSOC_REQ 0 +#define APMT2_PEER_DISASSOC_REQ 1 +#define APMT2_PEER_ASSOC_REQ 2 +#define APMT2_PEER_REASSOC_REQ 3 +#define APMT2_CLS3ERR 4 +#define AP_MAX_ASSOC_MSG 5 + +#define AP_ASSOC_FUNC_SIZE (AP_MAX_ASSOC_STATE * AP_MAX_ASSOC_MSG) + +// +// AP's AUTHENTICATION state machine: states, events, total function # +// +#define AP_AUTH_REQ_IDLE 0 +#define AP_MAX_AUTH_STATE 1 + +#define AP_AUTH_MACHINE_BASE 0 +#define APMT2_MLME_DEAUTH_REQ 0 +#define APMT2_CLS2ERR 1 +#define AP_MAX_AUTH_MSG 2 + +#define AP_AUTH_FUNC_SIZE (AP_MAX_AUTH_STATE * AP_MAX_AUTH_MSG) + +// +// AP's AUTH-RSP state machine: states, events, total function # +// +#define AP_AUTH_RSP_IDLE 0 +#define AP_MAX_AUTH_RSP_STATE 1 + +#define AP_AUTH_RSP_MACHINE_BASE 0 +#define APMT2_AUTH_CHALLENGE_TIMEOUT 0 +#define APMT2_PEER_AUTH_ODD 1 +#define APMT2_PEER_DEAUTH 2 +#define AP_MAX_AUTH_RSP_MSG 3 + +#define AP_AUTH_RSP_FUNC_SIZE (AP_MAX_AUTH_RSP_STATE * AP_MAX_AUTH_RSP_MSG) + +// +// AP's SYNC state machine: states, events, total function # +// +#define AP_SYNC_IDLE 0 +#define AP_SCAN_LISTEN 1 +#define AP_MAX_SYNC_STATE 2 + +#define AP_SYNC_MACHINE_BASE 0 +#define APMT2_PEER_PROBE_REQ 0 +#define APMT2_PEER_BEACON 1 +#define APMT2_MLME_SCAN_REQ 2 +#define APMT2_PEER_PROBE_RSP 3 +#define APMT2_SCAN_TIMEOUT 4 +#define APMT2_MLME_SCAN_CNCL 5 +#define AP_MAX_SYNC_MSG 6 + +#define AP_SYNC_FUNC_SIZE (AP_MAX_SYNC_STATE * AP_MAX_SYNC_MSG) + +// +// AP's WPA state machine: states, events, total function # +// +#define AP_WPA_PTK 0 +#define AP_MAX_WPA_PTK_STATE 1 + +#define AP_WPA_MACHINE_BASE 0 +#define APMT2_EAPPacket 0 +#define APMT2_EAPOLStart 1 +#define APMT2_EAPOLLogoff 2 +#define APMT2_EAPOLKey 3 +#define APMT2_EAPOLASFAlert 4 +#define AP_MAX_WPA_MSG 5 + +#define AP_WPA_FUNC_SIZE (AP_MAX_WPA_PTK_STATE * AP_MAX_WPA_MSG) + + + +// ============================================================================= + +// value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header +#define BTYPE_MGMT 0 +#define BTYPE_CNTL 1 +#define BTYPE_DATA 2 + +// value domain of 802.11 MGMT frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header +#define SUBTYPE_ASSOC_REQ 0 +#define SUBTYPE_ASSOC_RSP 1 +#define SUBTYPE_REASSOC_REQ 2 +#define SUBTYPE_REASSOC_RSP 3 +#define SUBTYPE_PROBE_REQ 4 +#define SUBTYPE_PROBE_RSP 5 +#define SUBTYPE_BEACON 8 +#define SUBTYPE_ATIM 9 +#define SUBTYPE_DISASSOC 10 +#define SUBTYPE_AUTH 11 +#define SUBTYPE_DEAUTH 12 +#define SUBTYPE_ACTION 13 +#define SUBTYPE_ACTION_NO_ACK 14 + +// value domain of 802.11 CNTL frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header +#define SUBTYPE_WRAPPER 7 +#define SUBTYPE_BLOCK_ACK_REQ 8 +#define SUBTYPE_BLOCK_ACK 9 +#define SUBTYPE_PS_POLL 10 +#define SUBTYPE_RTS 11 +#define SUBTYPE_CTS 12 +#define SUBTYPE_ACK 13 +#define SUBTYPE_CFEND 14 +#define SUBTYPE_CFEND_CFACK 15 + +// value domain of 802.11 DATA frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header +#define SUBTYPE_DATA 0 +#define SUBTYPE_DATA_CFACK 1 +#define SUBTYPE_DATA_CFPOLL 2 +#define SUBTYPE_DATA_CFACK_CFPOLL 3 +#define SUBTYPE_NULL_FUNC 4 +#define SUBTYPE_CFACK 5 +#define SUBTYPE_CFPOLL 6 +#define SUBTYPE_CFACK_CFPOLL 7 +#define SUBTYPE_QDATA 8 +#define SUBTYPE_QDATA_CFACK 9 +#define SUBTYPE_QDATA_CFPOLL 10 +#define SUBTYPE_QDATA_CFACK_CFPOLL 11 +#define SUBTYPE_QOS_NULL 12 +#define SUBTYPE_QOS_CFACK 13 +#define SUBTYPE_QOS_CFPOLL 14 +#define SUBTYPE_QOS_CFACK_CFPOLL 15 + +// ACK policy of QOS Control field bit 6:5 +#define NORMAL_ACK 0x00 // b6:5 = 00 +#define NO_ACK 0x20 // b6:5 = 01 +#define NO_EXPLICIT_ACK 0x40 // b6:5 = 10 +#define BLOCK_ACK 0x60 // b6:5 = 11 + +// +// rtmp_data.c use these definition +// +#define LENGTH_802_11 24 +#define LENGTH_802_11_AND_H 30 +#define LENGTH_802_11_CRC_H 34 +#define LENGTH_802_11_CRC 28 +#define LENGTH_802_11_WITH_ADDR4 30 +#define LENGTH_802_3 14 +#define LENGTH_802_3_TYPE 2 +#define LENGTH_802_1_H 8 +#define LENGTH_EAPOL_H 4 +#define LENGTH_WMMQOS_H 2 +#define LENGTH_CRC 4 +#define MAX_SEQ_NUMBER 0x0fff +#define LENGTH_802_3_NO_TYPE 12 +#define LENGTH_802_1Q 4 /* VLAN related */ + +// STA_CSR4.field.TxResult +#define TX_RESULT_SUCCESS 0 +#define TX_RESULT_ZERO_LENGTH 1 +#define TX_RESULT_UNDER_RUN 2 +#define TX_RESULT_OHY_ERROR 4 +#define TX_RESULT_RETRY_FAIL 6 + +// All PHY rate summary in TXD +// Preamble MODE in TxD +#define MODE_CCK 0 +#define MODE_OFDM 1 +#ifdef DOT11_N_SUPPORT +#define MODE_HTMIX 2 +#define MODE_HTGREENFIELD 3 +#endif // DOT11_N_SUPPORT // +// MCS for CCK. BW.SGI.STBC are reserved +#define MCS_LONGP_RATE_1 0 // long preamble CCK 1Mbps +#define MCS_LONGP_RATE_2 1 // long preamble CCK 1Mbps +#define MCS_LONGP_RATE_5_5 2 +#define MCS_LONGP_RATE_11 3 +#define MCS_SHORTP_RATE_1 4 // long preamble CCK 1Mbps. short is forbidden in 1Mbps +#define MCS_SHORTP_RATE_2 5 // short preamble CCK 2Mbps +#define MCS_SHORTP_RATE_5_5 6 +#define MCS_SHORTP_RATE_11 7 +// To send duplicate legacy OFDM. set BW=BW_40. SGI.STBC are reserved +#define MCS_RATE_6 0 // legacy OFDM +#define MCS_RATE_9 1 // OFDM +#define MCS_RATE_12 2 // OFDM +#define MCS_RATE_18 3 // OFDM +#define MCS_RATE_24 4 // OFDM +#define MCS_RATE_36 5 // OFDM +#define MCS_RATE_48 6 // OFDM +#define MCS_RATE_54 7 // OFDM +// HT +#define MCS_0 0 // 1S +#define MCS_1 1 +#define MCS_2 2 +#define MCS_3 3 +#define MCS_4 4 +#define MCS_5 5 +#define MCS_6 6 +#define MCS_7 7 +#define MCS_8 8 // 2S +#define MCS_9 9 +#define MCS_10 10 +#define MCS_11 11 +#define MCS_12 12 +#define MCS_13 13 +#define MCS_14 14 +#define MCS_15 15 +#define MCS_16 16 // 3*3 +#define MCS_17 17 +#define MCS_18 18 +#define MCS_19 19 +#define MCS_20 20 +#define MCS_21 21 +#define MCS_22 22 +#define MCS_23 23 +#define MCS_32 32 +#define MCS_AUTO 33 + +#ifdef DOT11_N_SUPPORT +// OID_HTPHYMODE +// MODE +#define HTMODE_MM 0 +#define HTMODE_GF 1 +#endif // DOT11_N_SUPPORT // + +// Fixed Tx MODE - HT, CCK or OFDM +#define FIXED_TXMODE_HT 0 +#define FIXED_TXMODE_CCK 1 +#define FIXED_TXMODE_OFDM 2 +// BW +#define BW_20 BAND_WIDTH_20 +#define BW_40 BAND_WIDTH_40 +#define BW_BOTH BAND_WIDTH_BOTH +#define BW_10 BAND_WIDTH_10 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. + +#ifdef DOT11_N_SUPPORT +// SHORTGI +#define GI_400 GAP_INTERVAL_400 // only support in HT mode +#define GI_BOTH GAP_INTERVAL_BOTH +#endif // DOT11_N_SUPPORT // +#define GI_800 GAP_INTERVAL_800 +// STBC +#define STBC_NONE 0 +#ifdef DOT11_N_SUPPORT +#define STBC_USE 1 // limited use in rt2860b phy +#define RXSTBC_ONE 1 // rx support of one spatial stream +#define RXSTBC_TWO 2 // rx support of 1 and 2 spatial stream +#define RXSTBC_THR 3 // rx support of 1~3 spatial stream +// MCS FEEDBACK +#define MCSFBK_NONE 0 // not support mcs feedback / +#define MCSFBK_RSV 1 // reserved +#define MCSFBK_UNSOLICIT 2 // only support unsolict mcs feedback +#define MCSFBK_MRQ 3 // response to both MRQ and unsolict mcs feedback + +// MIMO power safe +#define MMPS_STATIC 0 +#define MMPS_DYNAMIC 1 +#define MMPS_RSV 2 +#define MMPS_ENABLE 3 + + +// A-MSDU size +#define AMSDU_0 0 +#define AMSDU_1 1 + +#endif // DOT11_N_SUPPORT // + +// MCS use 7 bits +#define TXRATEMIMO 0x80 +#define TXRATEMCS 0x7F +#define TXRATEOFDM 0x7F +#define RATE_1 0 +#define RATE_2 1 +#define RATE_5_5 2 +#define RATE_11 3 +#define RATE_6 4 // OFDM +#define RATE_9 5 // OFDM +#define RATE_12 6 // OFDM +#define RATE_18 7 // OFDM +#define RATE_24 8 // OFDM +#define RATE_36 9 // OFDM +#define RATE_48 10 // OFDM +#define RATE_54 11 // OFDM +#define RATE_FIRST_OFDM_RATE RATE_6 +#define RATE_LAST_OFDM_RATE RATE_54 +#define RATE_6_5 12 // HT mix +#define RATE_13 13 // HT mix +#define RATE_19_5 14 // HT mix +#define RATE_26 15 // HT mix +#define RATE_39 16 // HT mix +#define RATE_52 17 // HT mix +#define RATE_58_5 18 // HT mix +#define RATE_65 19 // HT mix +#define RATE_78 20 // HT mix +#define RATE_104 21 // HT mix +#define RATE_117 22 // HT mix +#define RATE_130 23 // HT mix +//#define RATE_AUTO_SWITCH 255 // for StaCfg.FixedTxRate only +#define HTRATE_0 12 +#define RATE_FIRST_MM_RATE HTRATE_0 +#define RATE_FIRST_HT_RATE HTRATE_0 +#define RATE_LAST_HT_RATE HTRATE_0 + +// pTxWI->txop +#define IFS_HTTXOP 0 // The txop will be handles by ASIC. +#define IFS_PIFS 1 +#define IFS_SIFS 2 +#define IFS_BACKOFF 3 + +// pTxD->RetryMode +#define LONG_RETRY 1 +#define SHORT_RETRY 0 + +// Country Region definition +#define REGION_MINIMUM_BG_BAND 0 +#define REGION_0_BG_BAND 0 // 1-11 +#define REGION_1_BG_BAND 1 // 1-13 +#define REGION_2_BG_BAND 2 // 10-11 +#define REGION_3_BG_BAND 3 // 10-13 +#define REGION_4_BG_BAND 4 // 14 +#define REGION_5_BG_BAND 5 // 1-14 +#define REGION_6_BG_BAND 6 // 3-9 +#define REGION_7_BG_BAND 7 // 5-13 +#define REGION_31_BG_BAND 31 // 5-13 +#define REGION_MAXIMUM_BG_BAND 7 + +#define REGION_MINIMUM_A_BAND 0 +#define REGION_0_A_BAND 0 // 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 +#define REGION_1_A_BAND 1 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 +#define REGION_2_A_BAND 2 // 36, 40, 44, 48, 52, 56, 60, 64 +#define REGION_3_A_BAND 3 // 52, 56, 60, 64, 149, 153, 157, 161 +#define REGION_4_A_BAND 4 // 149, 153, 157, 161, 165 +#define REGION_5_A_BAND 5 // 149, 153, 157, 161 +#define REGION_6_A_BAND 6 // 36, 40, 44, 48 +#define REGION_7_A_BAND 7 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 +#define REGION_8_A_BAND 8 // 52, 56, 60, 64 +#define REGION_9_A_BAND 9 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 +#define REGION_10_A_BAND 10 // 36, 40, 44, 48, 149, 153, 157, 161, 165 +#define REGION_11_A_BAND 11 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 +#define REGION_MAXIMUM_A_BAND 11 + +// pTxD->CipherAlg +#define CIPHER_NONE 0 +#define CIPHER_WEP64 1 +#define CIPHER_WEP128 2 +#define CIPHER_TKIP 3 +#define CIPHER_AES 4 +#define CIPHER_CKIP64 5 +#define CIPHER_CKIP128 6 +#define CIPHER_TKIP_NO_MIC 7 // MIC appended by driver: not a valid value in hardware key table +#define CIPHER_SMS4 8 + +// value domain of pAd->RfIcType +#define RFIC_2820 1 // 2.4G 2T3R +#define RFIC_2850 2 // 2.4G/5G 2T3R +#define RFIC_2720 3 // 2.4G 1T2R +#define RFIC_2750 4 // 2.4G/5G 1T2R +#define RFIC_3020 5 // 2.4G 1T1R +#define RFIC_2020 6 // 2.4G B/G +#define RFIC_3021 7 // 2.4G 1T2R +#define RFIC_3022 8 // 2.4G 2T2R + +// LED Status. +#define LED_LINK_DOWN 0 +#define LED_LINK_UP 1 +#define LED_RADIO_OFF 2 +#define LED_RADIO_ON 3 +#define LED_HALT 4 +#define LED_WPS 5 +#define LED_ON_SITE_SURVEY 6 +#define LED_POWER_UP 7 + +// value domain of pAd->LedCntl.LedMode and E2PROM +#define LED_MODE_DEFAULT 0 +#define LED_MODE_TWO_LED 1 +#define LED_MODE_SIGNAL_STREGTH 8 // EEPROM define =8 + +// RC4 init value, used fro WEP & TKIP +#define PPPINITFCS32 0xffffffff /* Initial FCS value */ + +// value domain of pAd->StaCfg.PortSecured. 802.1X controlled port definition +#define WPA_802_1X_PORT_SECURED 1 +#define WPA_802_1X_PORT_NOT_SECURED 2 + +#define PAIRWISE_KEY 1 +#define GROUP_KEY 2 + +//definition of DRS +#define MAX_STEP_OF_TX_RATE_SWITCH 32 + + +// pre-allocated free NDIS PACKET/BUFFER poll for internal usage +#define MAX_NUM_OF_FREE_NDIS_PACKET 128 + +//Block ACK +#define MAX_TX_REORDERBUF 64 +#define MAX_RX_REORDERBUF 64 +#define DEFAULT_TX_TIMEOUT 30 +#define DEFAULT_RX_TIMEOUT 30 + +// definition of Recipient or Originator +#define I_RECIPIENT TRUE +#define I_ORIGINATOR FALSE + +#define DEFAULT_BBP_TX_POWER 0 +#define DEFAULT_RF_TX_POWER 5 + +#define MAX_INI_BUFFER_SIZE 4096 +#define MAX_PARAM_BUFFER_SIZE (2048) // enough for ACL (18*64) + //18 : the length of Mac address acceptable format "01:02:03:04:05:06;") + //64 : MAX_NUM_OF_ACL_LIST +// definition of pAd->OpMode +#define OPMODE_STA 0 +#define OPMODE_AP 1 +//#define OPMODE_L3_BRG 2 // as AP and STA at the same time + +#ifdef RT_BIG_ENDIAN +#define DIR_READ 0 +#define DIR_WRITE 1 +#define TYPE_TXD 0 +#define TYPE_RXD 1 +#define TYPE_TXINFO 0 +#define TYPE_RXINFO 1 +#define TYPE_TXWI 0 +#define TYPE_RXWI 1 +#endif + +// ========================= AP rtmp_def.h =========================== +// value domain for pAd->EventTab.Log[].Event +#define EVENT_RESET_ACCESS_POINT 0 // Log = "hh:mm:ss Restart Access Point" +#define EVENT_ASSOCIATED 1 // Log = "hh:mm:ss STA 00:01:02:03:04:05 associated" +#define EVENT_DISASSOCIATED 2 // Log = "hh:mm:ss STA 00:01:02:03:04:05 left this BSS" +#define EVENT_AGED_OUT 3 // Log = "hh:mm:ss STA 00:01:02:03:04:05 was aged-out and removed from this BSS" +#define EVENT_COUNTER_M 4 +#define EVENT_INVALID_PSK 5 +#define EVENT_MAX_EVENT_TYPE 6 +// ==== end of AP rtmp_def.h ============ + +// definition RSSI Number +#define RSSI_0 0 +#define RSSI_1 1 +#define RSSI_2 2 + +// definition of radar detection +#define RD_NORMAL_MODE 0 // Not found radar signal +#define RD_SWITCHING_MODE 1 // Found radar signal, and doing channel switch +#define RD_SILENCE_MODE 2 // After channel switch, need to be silence a while to ensure radar not found + +//Driver defined cid for mapping status and command. +#define SLEEPCID 0x11 +#define WAKECID 0x22 +#define QUERYPOWERCID 0x33 +#define OWNERMCU 0x1 +#define OWNERCPU 0x0 + +// MBSSID definition +#define ENTRY_NOT_FOUND 0xFF + + +/* After Linux 2.6.9, + * VLAN module use Private (from user) interface flags (netdevice->priv_flags). + * #define IFF_802_1Q_VLAN 0x1 -- 802.1Q VLAN device. in if.h + * ref to ip_sabotage_out() [ out->priv_flags & IFF_802_1Q_VLAN ] in br_netfilter.c + * + * For this reason, we MUST use EVEN value in priv_flags + */ +#define INT_MAIN 0x0100 +#define INT_MBSSID 0x0200 +#define INT_WDS 0x0300 +#define INT_APCLI 0x0400 +#define INT_MESH 0x0500 + +// Use bitmap to allow coexist of ATE_TXFRAME and ATE_RXFRAME(i.e.,to support LoopBack mode) +#ifdef RALINK_ATE +#define ATE_START 0x00 // Start ATE +#define ATE_STOP 0x80 // Stop ATE +#define ATE_TXCONT 0x05 // Continuous Transmit +#define ATE_TXCARR 0x09 // Transmit Carrier +#define ATE_TXCARRSUPP 0x11 // Transmit Carrier Suppression +#define ATE_TXFRAME 0x01 // Transmit Frames +#define ATE_RXFRAME 0x02 // Receive Frames +#ifdef RALINK_28xx_QA +#define ATE_TXSTOP 0xe2 // Stop Transmition(i.e., TXCONT, TXCARR, TXCARRSUPP, and TXFRAME) +#define ATE_RXSTOP 0xfd // Stop receiving Frames +#define BBP22_TXFRAME 0x00 // Transmit Frames +#define BBP22_TXCONT_OR_CARRSUPP 0x80 // Continuous Transmit or Carrier Suppression +#define BBP22_TXCARR 0xc1 // Transmit Carrier +#define BBP24_TXCONT 0x00 // Continuous Transmit +#define BBP24_CARRSUPP 0x01 // Carrier Suppression +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +// WEP Key TYPE +#define WEP_HEXADECIMAL_TYPE 0 +#define WEP_ASCII_TYPE 1 + + + +// WIRELESS EVENTS definition +/* Max number of char in custom event, refer to wireless_tools.28/wireless.20.h */ +#define IW_CUSTOM_MAX_LEN 255 /* In bytes */ + +// For system event - start +#define IW_SYS_EVENT_FLAG_START 0x0200 +#define IW_ASSOC_EVENT_FLAG 0x0200 +#define IW_DISASSOC_EVENT_FLAG 0x0201 +#define IW_DEAUTH_EVENT_FLAG 0x0202 +#define IW_AGEOUT_EVENT_FLAG 0x0203 +#define IW_COUNTER_MEASURES_EVENT_FLAG 0x0204 +#define IW_REPLAY_COUNTER_DIFF_EVENT_FLAG 0x0205 +#define IW_RSNIE_DIFF_EVENT_FLAG 0x0206 +#define IW_MIC_DIFF_EVENT_FLAG 0x0207 +#define IW_ICV_ERROR_EVENT_FLAG 0x0208 +#define IW_MIC_ERROR_EVENT_FLAG 0x0209 +#define IW_GROUP_HS_TIMEOUT_EVENT_FLAG 0x020A +#define IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG 0x020B +#define IW_RSNIE_SANITY_FAIL_EVENT_FLAG 0x020C +#define IW_SET_KEY_DONE_WPA1_EVENT_FLAG 0x020D +#define IW_SET_KEY_DONE_WPA2_EVENT_FLAG 0x020E +#define IW_STA_LINKUP_EVENT_FLAG 0x020F +#define IW_STA_LINKDOWN_EVENT_FLAG 0x0210 +#define IW_SCAN_COMPLETED_EVENT_FLAG 0x0211 +#define IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG 0x0212 +// if add new system event flag, please upadte the IW_SYS_EVENT_FLAG_END +#define IW_SYS_EVENT_FLAG_END 0x0212 +#define IW_SYS_EVENT_TYPE_NUM (IW_SYS_EVENT_FLAG_END - IW_SYS_EVENT_FLAG_START + 1) +// For system event - end + +// For spoof attack event - start +#define IW_SPOOF_EVENT_FLAG_START 0x0300 +#define IW_CONFLICT_SSID_EVENT_FLAG 0x0300 +#define IW_SPOOF_ASSOC_RESP_EVENT_FLAG 0x0301 +#define IW_SPOOF_REASSOC_RESP_EVENT_FLAG 0x0302 +#define IW_SPOOF_PROBE_RESP_EVENT_FLAG 0x0303 +#define IW_SPOOF_BEACON_EVENT_FLAG 0x0304 +#define IW_SPOOF_DISASSOC_EVENT_FLAG 0x0305 +#define IW_SPOOF_AUTH_EVENT_FLAG 0x0306 +#define IW_SPOOF_DEAUTH_EVENT_FLAG 0x0307 +#define IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG 0x0308 +#define IW_REPLAY_ATTACK_EVENT_FLAG 0x0309 +// if add new spoof attack event flag, please upadte the IW_SPOOF_EVENT_FLAG_END +#define IW_SPOOF_EVENT_FLAG_END 0x0309 +#define IW_SPOOF_EVENT_TYPE_NUM (IW_SPOOF_EVENT_FLAG_END - IW_SPOOF_EVENT_FLAG_START + 1) +// For spoof attack event - end + +// For flooding attack event - start +#define IW_FLOOD_EVENT_FLAG_START 0x0400 +#define IW_FLOOD_AUTH_EVENT_FLAG 0x0400 +#define IW_FLOOD_ASSOC_REQ_EVENT_FLAG 0x0401 +#define IW_FLOOD_REASSOC_REQ_EVENT_FLAG 0x0402 +#define IW_FLOOD_PROBE_REQ_EVENT_FLAG 0x0403 +#define IW_FLOOD_DISASSOC_EVENT_FLAG 0x0404 +#define IW_FLOOD_DEAUTH_EVENT_FLAG 0x0405 +#define IW_FLOOD_EAP_REQ_EVENT_FLAG 0x0406 +// if add new flooding attack event flag, please upadte the IW_FLOOD_EVENT_FLAG_END +#define IW_FLOOD_EVENT_FLAG_END 0x0406 +#define IW_FLOOD_EVENT_TYPE_NUM (IW_FLOOD_EVENT_FLAG_END - IW_FLOOD_EVENT_FLAG_START + 1) +// For flooding attack - end + +// End - WIRELESS EVENTS definition + +#ifdef CONFIG_STA_SUPPORT +// definition for DLS, kathy +#define MAX_NUM_OF_INIT_DLS_ENTRY 1 +#define MAX_NUM_OF_DLS_ENTRY MAX_NUMBER_OF_DLS_ENTRY + +//Block ACK , rt2860, kathy +#define MAX_TX_REORDERBUF 64 +#define MAX_RX_REORDERBUF 64 +#define DEFAULT_TX_TIMEOUT 30 +#define DEFAULT_RX_TIMEOUT 30 +#ifndef CONFIG_AP_SUPPORT +#define MAX_BARECI_SESSION 8 +#endif + +#ifndef IW_ESSID_MAX_SIZE +/* Maximum size of the ESSID and pAd->nickname strings */ +#define IW_ESSID_MAX_SIZE 32 +#endif +#endif // CONFIG_STA_SUPPORT // + +#ifdef MCAST_RATE_SPECIFIC +#define MCAST_DISABLE 0 +#define MCAST_CCK 1 +#define MCAST_OFDM 2 +#define MCAST_HTMIX 3 +#endif // MCAST_RATE_SPECIFIC // + +// For AsicRadioOff/AsicRadioOn function +#define DOT11POWERSAVE 0 +#define GUIRADIO_OFF 1 +#define RTMP_HALT 2 +#define GUI_IDLE_POWER_SAVE 3 +// -- + + +// definition for WpaSupport flag +#define WPA_SUPPLICANT_DISABLE 0 +#define WPA_SUPPLICANT_ENABLE 1 +#define WPA_SUPPLICANT_ENABLE_WITH_WEB_UI 2 + +// Endian byte swapping codes +#define SWAP16(x) \ + ((UINT16)( \ + (((UINT16)(x) & (UINT16) 0x00ffU) << 8) | \ + (((UINT16)(x) & (UINT16) 0xff00U) >> 8) )) + +#define SWAP32(x) \ + ((UINT32)( \ + (((UINT32)(x) & (UINT32) 0x000000ffUL) << 24) | \ + (((UINT32)(x) & (UINT32) 0x0000ff00UL) << 8) | \ + (((UINT32)(x) & (UINT32) 0x00ff0000UL) >> 8) | \ + (((UINT32)(x) & (UINT32) 0xff000000UL) >> 24) )) + +#define SWAP64(x) \ + ((UINT64)( \ + (UINT64)(((UINT64)(x) & (UINT64) 0x00000000000000ffULL) << 56) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x000000000000ff00ULL) << 40) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x0000000000ff0000ULL) << 24) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x00000000ff000000ULL) << 8) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x000000ff00000000ULL) >> 8) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x0000ff0000000000ULL) >> 24) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0x00ff000000000000ULL) >> 40) | \ + (UINT64)(((UINT64)(x) & (UINT64) 0xff00000000000000ULL) >> 56) )) + +#ifdef RT_BIG_ENDIAN + +#define cpu2le64(x) SWAP64((x)) +#define le2cpu64(x) SWAP64((x)) +#define cpu2le32(x) SWAP32((x)) +#define le2cpu32(x) SWAP32((x)) +#define cpu2le16(x) SWAP16((x)) +#define le2cpu16(x) SWAP16((x)) +#define cpu2be64(x) ((UINT64)(x)) +#define be2cpu64(x) ((UINT64)(x)) +#define cpu2be32(x) ((UINT32)(x)) +#define be2cpu32(x) ((UINT32)(x)) +#define cpu2be16(x) ((UINT16)(x)) +#define be2cpu16(x) ((UINT16)(x)) + +#else // Little_Endian + +#define cpu2le64(x) ((UINT64)(x)) +#define le2cpu64(x) ((UINT64)(x)) +#define cpu2le32(x) ((UINT32)(x)) +#define le2cpu32(x) ((UINT32)(x)) +#define cpu2le16(x) ((UINT16)(x)) +#define le2cpu16(x) ((UINT16)(x)) +#define cpu2be64(x) SWAP64((x)) +#define be2cpu64(x) SWAP64((x)) +#define cpu2be32(x) SWAP32((x)) +#define be2cpu32(x) SWAP32((x)) +#define cpu2be16(x) SWAP16((x)) +#define be2cpu16(x) SWAP16((x)) + +#endif // RT_BIG_ENDIAN + +#endif // __RTMP_DEF_H__ + + diff --git a/drivers/staging/rt3070/rtmp_type.h b/drivers/staging/rt3070/rtmp_type.h new file mode 100644 index 000000000000..4e4b168b9e92 --- /dev/null +++ b/drivers/staging/rt3070/rtmp_type.h @@ -0,0 +1,95 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtmp_type.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs + Paul Lin 1-2-2004 +*/ +#ifndef __RTMP_TYPE_H__ +#define __RTMP_TYPE_H__ + + +#define PACKED __attribute__ ((packed)) + +// Put platform dependent declaration here +// For example, linux type definition +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; +typedef unsigned long long UINT64; +typedef int INT32; +typedef long long INT64; + +typedef unsigned char * PUINT8; +typedef unsigned short * PUINT16; +typedef unsigned int * PUINT32; +typedef unsigned long long * PUINT64; +typedef int * PINT32; +typedef long long * PINT64; + +typedef signed char CHAR; +typedef signed short SHORT; +typedef signed int INT; +typedef signed long LONG; +typedef signed long long LONGLONG; + + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned long ULONG; +typedef unsigned long long ULONGLONG; + +typedef unsigned char BOOLEAN; +typedef void VOID; + +typedef VOID * PVOID; +typedef CHAR * PCHAR; +typedef UCHAR * PUCHAR; +typedef USHORT * PUSHORT; +typedef LONG * PLONG; +typedef ULONG * PULONG; +typedef UINT * PUINT; + +typedef unsigned int NDIS_MEDIA_STATE; + +typedef union _LARGE_INTEGER { + struct { + UINT LowPart; + INT32 HighPart; + } u; + INT64 QuadPart; +} LARGE_INTEGER; + +#endif // __RTMP_TYPE_H__ + diff --git a/drivers/staging/rt3070/spectrum.h b/drivers/staging/rt3070/spectrum.h new file mode 100644 index 000000000000..94cfa5b174fc --- /dev/null +++ b/drivers/staging/rt3070/spectrum.h @@ -0,0 +1,322 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + */ + +#ifndef __SPECTRUM_H__ +#define __SPECTRUM_H__ + +#include "rtmp_type.h" +#include "spectrum_def.h" + +typedef struct PACKED _TPC_REPORT_INFO +{ + UINT8 TxPwr; + UINT8 LinkMargin; +} TPC_REPORT_INFO, *PTPC_REPORT_INFO; + +typedef struct PACKED _CH_SW_ANN_INFO +{ + UINT8 ChSwMode; + UINT8 Channel; + UINT8 ChSwCnt; +} CH_SW_ANN_INFO, *PCH_SW_ANN_INFO; + +typedef union PACKED _MEASURE_REQ_MODE +{ +#ifdef RT_BIG_ENDIAN + struct PACKED + { + UINT8 Rev1:4; + UINT8 Report:1; + UINT8 Request:1; + UINT8 Enable:1; + UINT8 Rev0:1; + } field; +#else + struct PACKED + { + UINT8 Rev0:1; + UINT8 Enable:1; + UINT8 Request:1; + UINT8 Report:1; + UINT8 Rev1:4; + } field; +#endif // RT_BIG_ENDIAN // + UINT8 word; +} MEASURE_REQ_MODE, *PMEASURE_REQ_MODE; + +typedef struct PACKED _MEASURE_REQ +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; +} MEASURE_REQ, *PMEASURE_REQ; + +typedef struct PACKED _MEASURE_REQ_INFO +{ + UINT8 Token; + MEASURE_REQ_MODE ReqMode; + UINT8 ReqType; + MEASURE_REQ MeasureReq; +} MEASURE_REQ_INFO, *PMEASURE_REQ_INFO; + +typedef union PACKED _MEASURE_BASIC_REPORT_MAP +{ +#ifdef RT_BIG_ENDIAN + struct PACKED + { + UINT8 Rev:3; + UINT8 Unmeasure:1; + UINT8 Radar:1; + UINT8 UnidentifiedSignal:1; + UINT8 OfdmPreamble:1; + UINT8 BSS:1; + } field; +#else + struct PACKED + { + UINT8 BSS:1; + UINT8 OfdmPreamble:1; + UINT8 UnidentifiedSignal:1; + UINT8 Radar:1; + UINT8 Unmeasure:1; + UINT8 Rev:3; + } field; +#endif // RT_BIG_ENDIAN // + UINT8 word; +} MEASURE_BASIC_REPORT_MAP, *PMEASURE_BASIC_REPORT_MAP; + +typedef struct PACKED _MEASURE_BASIC_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + MEASURE_BASIC_REPORT_MAP Map; +} MEASURE_BASIC_REPORT, *PMEASURE_BASIC_REPORT; + +typedef struct PACKED _MEASURE_CCA_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + UINT8 CCA_Busy_Fraction; +} MEASURE_CCA_REPORT, *PMEASURE_CCA_REPORT; + +typedef struct PACKED _MEASURE_RPI_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + UINT8 RPI_Density[8]; +} MEASURE_RPI_REPORT, *PMEASURE_RPI_REPORT; + +typedef union PACKED _MEASURE_REPORT_MODE +{ + struct PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 Rev:5; + UINT8 Refused:1; + UINT8 Incapable:1; + UINT8 Late:1; +#else + UINT8 Late:1; + UINT8 Incapable:1; + UINT8 Refused:1; + UINT8 Rev:5; +#endif // RT_BIG_ENDIAN // + } field; + UINT8 word; +} MEASURE_REPORT_MODE, *PMEASURE_REPORT_MODE; + +typedef struct PACKED _MEASURE_REPORT_INFO +{ + UINT8 Token; + MEASURE_REPORT_MODE ReportMode; + UINT8 ReportType; + UINT8 Octect[0]; +} MEASURE_REPORT_INFO, *PMEASURE_REPORT_INFO; + +typedef struct PACKED _QUIET_INFO +{ + UINT8 QuietCnt; + UINT8 QuietPeriod; + UINT8 QuietDuration; + UINT8 QuietOffset; +} QUIET_INFO, *PQUIET_INFO; + +/* + ========================================================================== + Description: + Prepare Measurement request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 MeasureCh, + IN UINT16 MeasureDuration); + +/* + ========================================================================== + Description: + Prepare Measurement report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueMeasurementRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 ReportInfoLen, + IN PUINT8 pReportInfo); + +/* + ========================================================================== + Description: + Prepare TPC Request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCReq( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UCHAR DialogToken); + +/* + ========================================================================== + Description: + Prepare TPC Report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCRep( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 TxPwr, + IN UINT8 LinkMargin); + +/* + ========================================================================== + Description: + Prepare Channel Switch Announcement action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + 2. Channel switch announcement mode. + 2. a New selected channel. + + Return : None. + ========================================================================== + */ +VOID EnqueueChSwAnn( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN UINT8 ChSwMode, + IN UINT8 NewCh); + +/* + ========================================================================== + Description: + Spectrun action frames Handler such as channel switch annoucement, + measurement report, measurement request actions frames. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +VOID PeerSpectrumAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_MeasureReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +INT Set_TpcReq_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); + +VOID MeasureReqTabInit( + IN PRTMP_ADAPTER pAd); + +VOID MeasureReqTabExit( + IN PRTMP_ADAPTER pAd); + +VOID TpcReqTabInit( + IN PRTMP_ADAPTER pAd); + +VOID TpcReqTabExit( + IN PRTMP_ADAPTER pAd); + +VOID NotifyChSwAnnToPeerAPs( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pRA, + IN PUCHAR pTA, + IN UINT8 ChSwMode, + IN UINT8 Channel); +#endif // __SPECTRUM_H__ // + diff --git a/drivers/staging/rt3070/spectrum_def.h b/drivers/staging/rt3070/spectrum_def.h new file mode 100644 index 000000000000..4ca4817bba05 --- /dev/null +++ b/drivers/staging/rt3070/spectrum_def.h @@ -0,0 +1,95 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + spectrum_def.h + + Abstract: + Handle association related requests either from WSTA or from local MLME + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Fonchi Wu 2008 created for 802.11h + */ + +#ifndef __SPECTRUM_DEF_H__ +#define __SPECTRUM_DEF_H__ + +#define MAX_MEASURE_REQ_TAB_SIZE 3 +#define MAX_HASH_MEASURE_REQ_TAB_SIZE MAX_MEASURE_REQ_TAB_SIZE + +#define MAX_TPC_REQ_TAB_SIZE 3 +#define MAX_HASH_TPC_REQ_TAB_SIZE MAX_TPC_REQ_TAB_SIZE + +#define MIN_RCV_PWR 100 /* Negative value ((dBm) */ + +#define RM_TPC_REQ 0 +#define RM_MEASURE_REQ 1 + +#define RM_BASIC 0 +#define RM_CCA 1 +#define RM_RPI_HISTOGRAM 2 + +#define TPC_REQ_AGE_OUT 500 /* ms */ +#define MQ_REQ_AGE_OUT 500 /* ms */ + +#define TPC_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_HASH_TPC_REQ_TAB_SIZE) +#define MQ_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_MEASURE_REQ_TAB_SIZE) + +typedef struct _MEASURE_REQ_ENTRY +{ + struct _MEASURE_REQ_ENTRY *pNext; + ULONG lastTime; + BOOLEAN Valid; + UINT8 DialogToken; + UINT8 MeasureDialogToken[3]; // 0:basic measure, 1: CCA measure, 2: RPI_Histogram measure. +} MEASURE_REQ_ENTRY, *PMEASURE_REQ_ENTRY; + +typedef struct _MEASURE_REQ_TAB +{ + UCHAR Size; + PMEASURE_REQ_ENTRY Hash[MAX_HASH_MEASURE_REQ_TAB_SIZE]; + MEASURE_REQ_ENTRY Content[MAX_MEASURE_REQ_TAB_SIZE]; +} MEASURE_REQ_TAB, *PMEASURE_REQ_TAB; + +typedef struct _TPC_REQ_ENTRY +{ + struct _TPC_REQ_ENTRY *pNext; + ULONG lastTime; + BOOLEAN Valid; + UINT8 DialogToken; +} TPC_REQ_ENTRY, *PTPC_REQ_ENTRY; + +typedef struct _TPC_REQ_TAB +{ + UCHAR Size; + PTPC_REQ_ENTRY Hash[MAX_HASH_TPC_REQ_TAB_SIZE]; + TPC_REQ_ENTRY Content[MAX_TPC_REQ_TAB_SIZE]; +} TPC_REQ_TAB, *PTPC_REQ_TAB; + +#endif // __SPECTRUM_DEF_H__ // + diff --git a/drivers/staging/rt3070/sta/aironet.c b/drivers/staging/rt3070/sta/aironet.c new file mode 100644 index 000000000000..4af4a1906181 --- /dev/null +++ b/drivers/staging/rt3070/sta/aironet.c @@ -0,0 +1,1312 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + aironet.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Lin 04-06-15 Initial +*/ +#include "../rt_config.h" + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + ========================================================================== + */ +VOID AironetStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, Trans, MAX_AIRONET_STATE, MAX_AIRONET_MSG, (STATE_MACHINE_FUNC)Drop, AIRONET_IDLE, AIRONET_MACHINE_BASE); + StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_MSG, (STATE_MACHINE_FUNC)AironetMsgAction); + StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_SCAN_REQ, (STATE_MACHINE_FUNC)AironetRequestAction); + StateMachineSetAction(S, AIRONET_SCANNING, MT2_AIRONET_SCAN_DONE, (STATE_MACHINE_FUNC)AironetReportAction); +} + +/* + ========================================================================== + Description: + This is state machine function. + When receiving EAPOL packets which is for 802.1x key management. + Use both in WPA, and WPAPSK case. + In this function, further dispatch to different functions according to the received packet. 3 categories are : + 1. normal 4-way pairwisekey and 2-way groupkey handshake + 2. MIC error (Countermeasures attack) report packet from STA. + 3. Request for pairwise/group key update from STA + Return: + ========================================================================== +*/ +VOID AironetMsgAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Length; + UCHAR Index, i; + PUCHAR pData; + PAIRONET_RM_REQUEST_FRAME pRMReq; + PRM_REQUEST_ACTION pReqElem; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> AironetMsgAction\n")); + + // 0. Get Aironet IAPP header first + pRMReq = (PAIRONET_RM_REQUEST_FRAME) &Elem->Msg[LENGTH_802_11]; + pData = (PUCHAR) &Elem->Msg[LENGTH_802_11]; + + // 1. Change endian format form network to little endian + Length = be2cpu16(pRMReq->IAPP.Length); + + // 2.0 Sanity check, this should only happen when CCX 2.0 support is enabled + if (pAd->StaCfg.CCXEnable != TRUE) + return; + + // 2.1 Radio measurement must be on + if (pAd->StaCfg.CCXControl.field.RMEnable != 1) + return; + + // 2.2. Debug print all bit information + DBGPRINT(RT_DEBUG_TRACE, ("IAPP ID & Length %d\n", Length)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP Type %x\n", pRMReq->IAPP.Type)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP SubType %x\n", pRMReq->IAPP.SubType)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP Dialog Token %x\n", pRMReq->IAPP.Token)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP Activation Delay %x\n", pRMReq->Delay)); + DBGPRINT(RT_DEBUG_TRACE, ("IAPP Measurement Offset %x\n", pRMReq->Offset)); + + // 3. Check IAPP frame type, it must be 0x32 for Cisco Aironet extension + if (pRMReq->IAPP.Type != AIRONET_IAPP_TYPE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP type for Cisco Aironet extension\n")); + return; + } + + // 4. Check IAPP frame subtype, it must be 0x01 for Cisco Aironet extension request. + // Since we are acting as client only, we will disregards reply subtype. + if (pRMReq->IAPP.SubType != AIRONET_IAPP_SUBTYPE_REQUEST) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP subtype for Cisco Aironet extension\n")); + return; + } + + // 5. Verify Destination MAC and Source MAC, both should be all zeros. + if (! MAC_ADDR_EQUAL(pRMReq->IAPP.DA, ZERO_MAC_ADDR)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP DA for Cisco Aironet extension, it's not Zero\n")); + return; + } + + if (! MAC_ADDR_EQUAL(pRMReq->IAPP.SA, ZERO_MAC_ADDR)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP SA for Cisco Aironet extension, it's not Zero\n")); + return; + } + + // 6. Reinit all report related fields + NdisZeroMemory(pAd->StaCfg.FrameReportBuf, 2048); + NdisZeroMemory(pAd->StaCfg.BssReportOffset, sizeof(USHORT) * MAX_LEN_OF_BSS_TABLE); + NdisZeroMemory(pAd->StaCfg.MeasurementRequest, sizeof(RM_REQUEST_ACTION) * 4); + + // 7. Point to the start of first element report element + pAd->StaCfg.FrameReportLen = LENGTH_802_11 + sizeof(AIRONET_IAPP_HEADER); + DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen)); + pAd->StaCfg.LastBssIndex = 0xff; + pAd->StaCfg.RMReqCnt = 0; + pAd->StaCfg.ParallelReq = FALSE; + pAd->StaCfg.ParallelDuration = 0; + pAd->StaCfg.ParallelChannel = 0; + pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token; + pAd->StaCfg.CurrentRMReqIdx = 0; + pAd->StaCfg.CLBusyBytes = 0; + // Reset the statistics + for (i = 0; i < 8; i++) + pAd->StaCfg.RPIDensity[i] = 0; + + Index = 0; + + // 8. Save dialog token for report + pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token; + + // Save Activation delay & measurement offset, Not really needed + + // 9. Point to the first request element + pData += sizeof(AIRONET_RM_REQUEST_FRAME); + // Length should exclude the CISCO Aironet SNAP header + Length -= (sizeof(AIRONET_RM_REQUEST_FRAME) - LENGTH_802_1_H); + + // 10. Start Parsing the Measurement elements. + // Be careful about multiple MR elements within one frames. + while (Length > 0) + { + pReqElem = (PRM_REQUEST_ACTION) pData; + switch (pReqElem->ReqElem.Eid) + { + case IE_MEASUREMENT_REQUEST: + // From the example, it seems we only need to support one request in one frame + // There is no multiple request in one frame. + // Besides, looks like we need to take care the measurement request only. + // The measurement request is always 4 bytes. + + // Start parsing this type of request. + // 0. Eid is IE_MEASUREMENT_REQUEST + // 1. Length didn't include Eid and Length field, it always be 8. + // 2. Measurement Token, we nned to save it for the corresponding report. + // 3. Measurement Mode, Although there are definitions, but we din't see value other than + // 0 from test specs examples. + // 4. Measurement Type, this is what we need to do. + switch (pReqElem->ReqElem.Type) + { + case MSRN_TYPE_CHANNEL_LOAD_REQ: + case MSRN_TYPE_NOISE_HIST_REQ: + case MSRN_TYPE_BEACON_REQ: + // Check the Enable non-serving channel measurement control + if (pAd->StaCfg.CCXControl.field.DCRMEnable == 0) + { + // Check channel before enqueue the action + if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel) + break; + } + else + { + // If off channel measurement, check the TU duration limit + if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel) + if (pReqElem->Measurement.Duration > pAd->StaCfg.CCXControl.field.TuLimit) + break; + } + + // Save requests and execute actions later + NdisMoveMemory(&pAd->StaCfg.MeasurementRequest[Index], pReqElem, sizeof(RM_REQUEST_ACTION)); + Index += 1; + break; + + case MSRN_TYPE_FRAME_REQ: + // Since it's option, we will support later + // FrameRequestAction(pAd, pData); + break; + + default: + break; + } + + // Point to next Measurement request + pData += sizeof(RM_REQUEST_ACTION); + Length -= sizeof(RM_REQUEST_ACTION); + break; + + // We accept request only, all others are dropped + case IE_MEASUREMENT_REPORT: + case IE_AP_TX_POWER: + case IE_MEASUREMENT_CAPABILITY: + default: + return; + } + } + + // 11. Update some flags and index + pAd->StaCfg.RMReqCnt = Index; + + if (Index) + { + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL); + RT28XX_MLME_HANDLER(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- AironetMsgAction\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID AironetRequestAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRM_REQUEST_ACTION pReq; + + // 1. Point to next request element + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; + + // 2. Parse measurement type and call appropriate functions + if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) + // Channel Load measurement request + ChannelLoadRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) + // Noise Histogram measurement request + NoiseHistRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ) + // Beacon measurement request + BeaconRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else + // Unknown. Do nothing and return, this should never happen + return; + + // 3. Peek into the next request, if it's parallel, we will update the scan time to the largest one + if ((pAd->StaCfg.CurrentRMReqIdx + 1) < pAd->StaCfg.RMReqCnt) + { + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx + 1]; + // Check for parallel bit + if ((pReq->ReqElem.Mode & 0x01) && (pReq->Measurement.Channel == pAd->StaCfg.CCXScanChannel)) + { + // Update parallel mode request information + pAd->StaCfg.ParallelReq = TRUE; + pAd->StaCfg.CCXScanTime = ((pReq->Measurement.Duration > pAd->StaCfg.CCXScanTime) ? + (pReq->Measurement.Duration) : (pAd->StaCfg.CCXScanTime)); + } + } + + // 4. Call RT28XX_MLME_HANDLER to execute the request mlme commands, Scan request is the only one used + RT28XX_MLME_HANDLER(pAd); + +} + + +/* + ======================================================================== + + Routine Description: + Prepare channel load report action, special scan operation added + to support + + Arguments: + pAd Pointer to our adapter + pData Start from element ID + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ChannelLoadRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PRM_REQUEST_ACTION pReq; + MLME_SCAN_REQ_STRUCT ScanReq; + UCHAR ZeroSsid[32]; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + PHEADER_802_11 pNullFrame; + + DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction ----->\n")); + + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; + NdisZeroMemory(ZeroSsid, 32); + + // Prepare for special scan request + // The scan definition is different with our Active, Passive scan definition. + // For CCX2, Active means send out probe request with broadcast BSSID. + // Passive means no probe request sent, only listen to the beacons. + // The channel scanned is fixed as specified, no need to scan all channels. + // The scan wait time is specified in the request too. + // Passive scan Mode + + // Control state machine is not idle, reject the request + if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) + return; + + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_CHANNEL_LOAD); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + + // Reset some internal control flags to make sure this scan works. + BssTableInit(&pAd->StaCfg.CCXBssTab); + pAd->StaCfg.ScanCnt = 0; + pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; + pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; + + DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel)); + + // If it's non serving channel scan, send out a null frame with PSM bit on. + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + { + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pNullFrame = (PHEADER_802_11) pOutBuffer;; + // Make the power save Null frame with PSM bit on + MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pNullFrame->Duration = 0; + pNullFrame->FC.Type = BTYPE_DATA; + pNullFrame->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); + RTMPusecDelay(5000); + } + + pAd->StaCfg.CCXReqType = MSRN_TYPE_CHANNEL_LOAD_REQ; + pAd->StaCfg.CLBusyBytes = 0; + // Enable Rx with promiscuous reception + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010); + + // Set channel load measurement flag + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); + + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + + DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + Prepare noise histogram report action, special scan operation added + to support + + Arguments: + pAd Pointer to our adapter + pData Start from element ID + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID NoiseHistRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PRM_REQUEST_ACTION pReq; + MLME_SCAN_REQ_STRUCT ScanReq; + UCHAR ZeroSsid[32], i; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + PHEADER_802_11 pNullFrame; + + DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction ----->\n")); + + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; + NdisZeroMemory(ZeroSsid, 32); + + // Prepare for special scan request + // The scan definition is different with our Active, Passive scan definition. + // For CCX2, Active means send out probe request with broadcast BSSID. + // Passive means no probe request sent, only listen to the beacons. + // The channel scanned is fixed as specified, no need to scan all channels. + // The scan wait time is specified in the request too. + // Passive scan Mode + + // Control state machine is not idle, reject the request + if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) + return; + + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_NOISE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + + // Reset some internal control flags to make sure this scan works. + BssTableInit(&pAd->StaCfg.CCXBssTab); + pAd->StaCfg.ScanCnt = 0; + pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; + pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; + pAd->StaCfg.CCXReqType = MSRN_TYPE_NOISE_HIST_REQ; + + DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel)); + + // If it's non serving channel scan, send out a null frame with PSM bit on. + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + { + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pNullFrame = (PHEADER_802_11) pOutBuffer; + // Make the power save Null frame with PSM bit on + MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pNullFrame->Duration = 0; + pNullFrame->FC.Type = BTYPE_DATA; + pNullFrame->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); + RTMPusecDelay(5000); + } + + // Reset the statistics + for (i = 0; i < 8; i++) + pAd->StaCfg.RPIDensity[i] = 0; + + // Enable Rx with promiscuous reception + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010); + + // Set channel load measurement flag + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); + + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + + DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + Prepare Beacon report action, special scan operation added + to support + + Arguments: + pAd Pointer to our adapter + pData Start from element ID + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID BeaconRequestAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PRM_REQUEST_ACTION pReq; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + PHEADER_802_11 pNullFrame; + MLME_SCAN_REQ_STRUCT ScanReq; + UCHAR ZeroSsid[32]; + + DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction ----->\n")); + + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; + NdisZeroMemory(ZeroSsid, 32); + + // Prepare for special scan request + // The scan definition is different with our Active, Passive scan definition. + // For CCX2, Active means send out probe request with broadcast BSSID. + // Passive means no probe request sent, only listen to the beacons. + // The channel scanned is fixed as specified, no need to scan all channels. + // The scan wait time is specified in the request too. + if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_PASSIVE) + { + // Passive scan Mode + DBGPRINT(RT_DEBUG_TRACE, ("Passive Scan Mode!\n")); + + // Control state machine is not idle, reject the request + if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) + return; + + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_PASSIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + + // Reset some internal control flags to make sure this scan works. + BssTableInit(&pAd->StaCfg.CCXBssTab); + pAd->StaCfg.ScanCnt = 0; + pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; + pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; + pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ; + DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration)); + + // If it's non serving channel scan, send out a null frame with PSM bit on. + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + { + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pNullFrame = (PHEADER_802_11) pOutBuffer; + // Make the power save Null frame with PSM bit on + MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pNullFrame->Duration = 0; + pNullFrame->FC.Type = BTYPE_DATA; + pNullFrame->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); + RTMPusecDelay(5000); + } + + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + } + else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE) + { + // Active scan Mode + DBGPRINT(RT_DEBUG_TRACE, ("Active Scan Mode!\n")); + + // Control state machine is not idle, reject the request + if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) + return; + + // Fill out stuff for scan request + ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + + // Reset some internal control flags to make sure this scan works. + BssTableInit(&pAd->StaCfg.CCXBssTab); + pAd->StaCfg.ScanCnt = 0; + pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; + pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; + pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ; + DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration)); + + // If it's non serving channel scan, send out a null frame with PSM bit on. + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + { + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + pNullFrame = (PHEADER_802_11) pOutBuffer; + // Make the power save Null frame with PSM bit on + MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pNullFrame->Duration = 0; + pNullFrame->FC.Type = BTYPE_DATA; + pNullFrame->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); + RTMPusecDelay(5000); + } + + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + } + else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_BEACON_TABLE) + { + // Beacon report Mode, report all the APS in current bss table + DBGPRINT(RT_DEBUG_TRACE, ("Beacon Report Mode!\n")); + + // Copy current BSS table to CCX table, we can omit this step later on. + NdisMoveMemory(&pAd->StaCfg.CCXBssTab, &pAd->ScanTab, sizeof(BSS_TABLE)); + + // Create beacon report from Bss table + AironetCreateBeaconReportFromBssTable(pAd); + + // Set state to scanning + pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; + + // Enqueue report request + // Cisco scan request is finished, prepare beacon report + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL); + } + else + { + // Wrong scan Mode + DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n")); + } + + DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID AironetReportAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRM_REQUEST_ACTION pReq; + ULONG Now32; + + NdisGetSystemUpTime(&Now32); + pAd->StaCfg.LastBeaconRxTime = Now32; + + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; + + DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction ----->\n")); + + // 1. Parse measurement type and call appropriate functions + if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) + // Channel Load measurement request + ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) + // Noise Histogram measurement request + NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ) + // Beacon measurement request + BeaconReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else + // Unknown. Do nothing and return + ; + + // 2. Point to the correct index of action element, start from 0 + pAd->StaCfg.CurrentRMReqIdx++; + + // 3. Check for parallel actions + if (pAd->StaCfg.ParallelReq == TRUE) + { + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; + + // Process next action right away + if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) + // Channel Load measurement request + ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) + // Noise Histogram measurement request + NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); + + pAd->StaCfg.ParallelReq = FALSE; + pAd->StaCfg.CurrentRMReqIdx++; + } + + if (pAd->StaCfg.CurrentRMReqIdx >= pAd->StaCfg.RMReqCnt) + { + // 4. There is no more unprocessed measurement request, go for transmit this report + AironetFinalReportAction(pAd); + pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; + } + else + { + pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; + + if (pReq->Measurement.Channel != pAd->CommonCfg.Channel) + { + RTMPusecDelay(100000); + } + + // 5. There are more requests to be measure + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL); + RT28XX_MLME_HANDLER(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID AironetFinalReportAction( + IN PRTMP_ADAPTER pAd) +{ + PUCHAR pDest; + PAIRONET_IAPP_HEADER pIAPP; + PHEADER_802_11 pHeader; + UCHAR AckRate = RATE_2; + USHORT AckDuration = 0; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction ----->\n")); + + // 0. Set up the frame pointer, Frame was inited at the end of message action + pDest = &pAd->StaCfg.FrameReportBuf[LENGTH_802_11]; + + // 1. Update report IAPP fields + pIAPP = (PAIRONET_IAPP_HEADER) pDest; + + // 2. Copy Cisco SNAP header + NdisMoveMemory(pIAPP->CiscoSnapHeader, SNAP_AIRONET, LENGTH_802_1_H); + + // 3. network order for this 16bit length + pIAPP->Length = cpu2be16(pAd->StaCfg.FrameReportLen - LENGTH_802_11 - LENGTH_802_1_H); + + // 3.1 sanity check the report length, ignore it if there is nothing to report + if (be2cpu16(pIAPP->Length) <= 18) + return; + + // 4. Type must be 0x32 + pIAPP->Type = AIRONET_IAPP_TYPE; + + // 5. SubType for report must be 0x81 + pIAPP->SubType = AIRONET_IAPP_SUBTYPE_REPORT; + + // 6. DA is not used and must be zero, although the whole frame was cleared at the start of function + // We will do it again here. We can use BSSID instead + COPY_MAC_ADDR(pIAPP->DA, pAd->CommonCfg.Bssid); + + // 7. SA is the client reporting which must be our MAC + COPY_MAC_ADDR(pIAPP->SA, pAd->CurrentAddress); + + // 8. Copy the saved dialog token + pIAPP->Token = pAd->StaCfg.IAPPToken; + + // 9. Make the Report frame 802.11 header + // Reuse function in wpa.c + pHeader = (PHEADER_802_11) pAd->StaCfg.FrameReportBuf; + pAd->Sequence ++; + WpaMacHeaderInit(pAd, pHeader, 0, pAd->CommonCfg.Bssid); + + // ACK size is 14 include CRC, and its rate is based on real time information + AckRate = pAd->CommonCfg.ExpectedACKRate[pAd->CommonCfg.MlmeRate]; + AckDuration = RTMPCalcDuration(pAd, AckRate, 14); + pHeader->Duration = pAd->CommonCfg.Dsifs + AckDuration; + + // Use MLME enqueue method + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + // 10. Prepare report frame with dynamic outbuffer. Just simply copy everything. + MakeOutgoingFrame(pOutBuffer, &FrameLen, + pAd->StaCfg.FrameReportLen, pAd->StaCfg.FrameReportBuf, + END_OF_ARGS); + + // 11. Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED; + + DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID ChannelLoadReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PMEASUREMENT_REPORT_ELEMENT pReport; + PCHANNEL_LOAD_REPORT pLoad; + PUCHAR pDest; + UCHAR CCABusyFraction; + + DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction ----->\n")); + + // Disable Rx with promiscuous reception, make it back to normal + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. + + // 0. Setup pointer for processing beacon & probe response + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; + pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; + + // 1. Fill Measurement report element field. + pReport->Eid = IE_MEASUREMENT_REPORT; + // Fixed Length at 9, not include Eid and length fields + pReport->Length = 9; + pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token; + pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode; + pReport->Type = MSRN_TYPE_CHANNEL_LOAD_REQ; + + // 2. Fill channel report measurement data + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + pLoad = (PCHANNEL_LOAD_REPORT) pDest; + pLoad->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel; + pLoad->Spare = 0; + pLoad->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration; + + // 3. Calculate the CCA Busy Fraction + // (Bytes + ACK size) * 8 / Tx speed * 255 / 1000 / measurement duration, use 24 us Tx speed + // = (Bytes + ACK) / 12 / duration + // 9 is the good value for pAd->StaCfg.CLFactor + // CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 9 / pLoad->Duration); + CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / pAd->StaCfg.CLFactor / pLoad->Duration); + if (CCABusyFraction < 10) + CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 3 / pLoad->Duration) + 1; + + pLoad->CCABusy = CCABusyFraction; + DBGPRINT(RT_DEBUG_TRACE, ("CLBusyByte %ld, Duration %d, Result, %d\n", pAd->StaCfg.CLBusyBytes, pLoad->Duration, CCABusyFraction)); + + DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen)); + pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(CHANNEL_LOAD_REPORT)); + DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen)); + + // 4. Clear channel load measurement flag + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); + + // 5. reset to idle state + pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; + + DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID NoiseHistReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + PMEASUREMENT_REPORT_ELEMENT pReport; + PNOISE_HIST_REPORT pNoise; + PUCHAR pDest; + UCHAR i,NoiseCnt; + USHORT TotalRPICnt, TotalRPISum; + + DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction ----->\n")); + + // 0. Disable Rx with promiscuous reception, make it back to normal + RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. + // 1. Setup pointer for processing beacon & probe response + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; + pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; + + // 2. Fill Measurement report element field. + pReport->Eid = IE_MEASUREMENT_REPORT; + // Fixed Length at 16, not include Eid and length fields + pReport->Length = 16; + pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token; + pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode; + pReport->Type = MSRN_TYPE_NOISE_HIST_REQ; + + // 3. Fill noise histogram report measurement data + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + pNoise = (PNOISE_HIST_REPORT) pDest; + pNoise->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel; + pNoise->Spare = 0; + pNoise->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration; + // 4. Fill Noise histogram, the total RPI counts should be 0.4 * TU + // We estimate 4000 normal packets received durning 10 seconds test. + // Adjust it if required. + // 3 is a good value for pAd->StaCfg.NHFactor + // TotalRPICnt = pNoise->Duration * 3 / 10; + TotalRPICnt = pNoise->Duration * pAd->StaCfg.NHFactor / 10; + TotalRPISum = 0; + + for (i = 0; i < 8; i++) + { + TotalRPISum += pAd->StaCfg.RPIDensity[i]; + DBGPRINT(RT_DEBUG_TRACE, ("RPI %d Conuts %d\n", i, pAd->StaCfg.RPIDensity[i])); + } + + // Double check if the counter is larger than our expectation. + // We will replace it with the total number plus a fraction. + if (TotalRPISum > TotalRPICnt) + TotalRPICnt = TotalRPISum + pNoise->Duration / 20; + + DBGPRINT(RT_DEBUG_TRACE, ("Total RPI Conuts %d\n", TotalRPICnt)); + + // 5. Initialize noise count for the total summation of 0xff + NoiseCnt = 0; + for (i = 1; i < 8; i++) + { + pNoise->Density[i] = (UCHAR) (pAd->StaCfg.RPIDensity[i] * 255 / TotalRPICnt); + if ((pNoise->Density[i] == 0) && (pAd->StaCfg.RPIDensity[i] != 0)) + pNoise->Density[i]++; + NoiseCnt += pNoise->Density[i]; + DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[%d] = 0x%02x\n", i, pNoise->Density[i])); + } + + // 6. RPI[0] represents the rest of counts + pNoise->Density[0] = 0xff - NoiseCnt; + DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[0] = 0x%02x\n", pNoise->Density[0])); + + pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(NOISE_HIST_REPORT)); + + // 7. Clear channel load measurement flag + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); + + // 8. reset to idle state + pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; + + DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + Prepare Beacon report action, + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID BeaconReportAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Index) +{ + DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction ----->\n")); + + // Looks like we don't have anything thing need to do here. + // All measurement report already finished in AddBeaconReport + // The length is in the FrameReportLen + + // reset Beacon index for next beacon request + pAd->StaCfg.LastBssIndex = 0xff; + + // reset to idle state + pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; + + DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + Index Current BSSID in CCXBsstab entry index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID AironetAddBeaconReport( + IN PRTMP_ADAPTER pAd, + IN ULONG Index, + IN PMLME_QUEUE_ELEM pElem) +{ + PVOID pMsg; + PUCHAR pSrc, pDest; + UCHAR ReqIdx; + ULONG MsgLen; + USHORT Length; + PFRAME_802_11 pFrame; + PMEASUREMENT_REPORT_ELEMENT pReport; + PEID_STRUCT pEid; + PBEACON_REPORT pBeaconReport; + PBSS_ENTRY pBss; + + // 0. Setup pointer for processing beacon & probe response + pMsg = pElem->Msg; + MsgLen = pElem->MsgLen; + pFrame = (PFRAME_802_11) pMsg; + pSrc = pFrame->Octet; // Start from AP TSF + pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index]; + ReqIdx = pAd->StaCfg.CurrentRMReqIdx; + + // 1 Check the Index, if we already create this entry, only update the average RSSI + if ((Index <= pAd->StaCfg.LastBssIndex) && (pAd->StaCfg.LastBssIndex != 0xff)) + { + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.BssReportOffset[Index]]; + // Point to bss report information + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + pBeaconReport = (PBEACON_REPORT) pDest; + + // Update Rx power, in dBm + // Get the original RSSI readback from BBP + pBeaconReport->RxPower += pAd->BbpRssiToDbmDelta; + // Average the Rssi reading + pBeaconReport->RxPower = (pBeaconReport->RxPower + pBss->Rssi) / 2; + // Get to dBm format + pBeaconReport->RxPower -= pAd->BbpRssiToDbmDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ", + pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], + pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); + DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld] Rssi %d, Avg Rssi %d\n", Index, (pBss->Rssi - pAd->BbpRssiToDbmDelta), pBeaconReport->RxPower - 256)); + DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.BssReportOffset[Index])); + + // Update other information here + + // Done + return; + } + + // 2. Update reported Index + pAd->StaCfg.LastBssIndex = Index; + + // 3. Setup the buffer address for copying this BSSID into reporting frame + // The offset should start after 802.11 header and report frame header. + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; + + // 4. Save the start offset of each Bss in report frame + pAd->StaCfg.BssReportOffset[Index] = pAd->StaCfg.FrameReportLen; + + // 5. Fill Measurement report fields + pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; + pReport->Eid = IE_MEASUREMENT_REPORT; + pReport->Length = 0; + pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token; + pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode; + pReport->Type = MSRN_TYPE_BEACON_REQ; + Length = sizeof(MEASUREMENT_REPORT_ELEMENT); + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + + // 6. Start thebeacon report format + pBeaconReport = (PBEACON_REPORT) pDest; + pDest += sizeof(BEACON_REPORT); + Length += sizeof(BEACON_REPORT); + + // 7. Copy Channel number + pBeaconReport->Channel = pBss->Channel; + pBeaconReport->Spare = 0; + pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration; + pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS); + // 8. Rx power, in dBm + pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta; + + DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ", + pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], + pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); + DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld], Rssi %d\n", Index, pBeaconReport->RxPower - 256)); + DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.FrameReportLen)); + + pBeaconReport->BeaconInterval = pBss->BeaconPeriod; + COPY_MAC_ADDR(pBeaconReport->BSSID, pFrame->Hdr.Addr3); + NdisMoveMemory(pBeaconReport->ParentTSF, pSrc, 4); + NdisMoveMemory(pBeaconReport->TargetTSF, &pElem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pBeaconReport->TargetTSF[4], &pElem->TimeStamp.u.HighPart, 4); + + // 9. Skip the beacon frame and offset to start of capabilityinfo since we already processed capabilityinfo + pSrc += (TIMESTAMP_LEN + 2); + pBeaconReport->CapabilityInfo = *(USHORT *)pSrc; + + // 10. Point to start of element ID + pSrc += 2; + pEid = (PEID_STRUCT) pSrc; + + // 11. Start process all variable Eid oayload and add the appropriate to the frame report + while (((PUCHAR) pEid + pEid->Len + 1) < ((PUCHAR) pFrame + MsgLen)) + { + // Only limited EID are required to report for CCX 2. It includes SSID, Supported rate, + // FH paramenter set, DS parameter set, CF parameter set, IBSS parameter set, + // TIM (report first 4 bytes only, radio measurement capability + switch (pEid->Eid) + { + case IE_SSID: + case IE_SUPP_RATES: + case IE_FH_PARM: + case IE_DS_PARM: + case IE_CF_PARM: + case IE_IBSS_PARM: + NdisMoveMemory(pDest, pEid, pEid->Len + 2); + pDest += (pEid->Len + 2); + Length += (pEid->Len + 2); + break; + + case IE_MEASUREMENT_CAPABILITY: + // Since this IE is duplicated with WPA security IE, we has to do sanity check before + // recognize it. + // 1. It also has fixed 6 bytes IE length. + if (pEid->Len != 6) + break; + // 2. Check the Cisco Aironet OUI + if (NdisEqualMemory(CISCO_OUI, (pSrc + 2), 3)) + { + // Matched, this is what we want + NdisMoveMemory(pDest, pEid, pEid->Len + 2); + pDest += (pEid->Len + 2); + Length += (pEid->Len + 2); + } + break; + + case IE_TIM: + if (pEid->Len > 4) + { + // May truncate and report the first 4 bytes only, with the eid & len, total should be 6 + NdisMoveMemory(pDest, pEid, 6); + pDest += 6; + Length += 6; + } + else + { + NdisMoveMemory(pDest, pEid, pEid->Len + 2); + pDest += (pEid->Len + 2); + Length += (pEid->Len + 2); + } + break; + + default: + break; + } + // 12. Move to next element ID + pSrc += (2 + pEid->Len); + pEid = (PEID_STRUCT) pSrc; + } + + // 13. Update the length in the header, not include EID and length + pReport->Length = Length - 4; + + // 14. Update the frame report buffer data length + pAd->StaCfg.FrameReportLen += Length; + DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen)); +} + +/* + ======================================================================== + + Routine Description: + + Arguments: + Index Current BSSID in CCXBsstab entry index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID AironetCreateBeaconReportFromBssTable( + IN PRTMP_ADAPTER pAd) +{ + PMEASUREMENT_REPORT_ELEMENT pReport; + PBEACON_REPORT pBeaconReport; + UCHAR Index, ReqIdx; + USHORT Length; + PUCHAR pDest; + PBSS_ENTRY pBss; + + // 0. setup base pointer + ReqIdx = pAd->StaCfg.CurrentRMReqIdx; + + for (Index = 0; Index < pAd->StaCfg.CCXBssTab.BssNr; Index++) + { + // 1. Setup the buffer address for copying this BSSID into reporting frame + // The offset should start after 802.11 header and report frame header. + pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; + pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index]; + Length = 0; + + // 2. Fill Measurement report fields + pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; + pReport->Eid = IE_MEASUREMENT_REPORT; + pReport->Length = 0; + pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token; + pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode; + pReport->Type = MSRN_TYPE_BEACON_REQ; + Length = sizeof(MEASUREMENT_REPORT_ELEMENT); + pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); + + // 3. Start the beacon report format + pBeaconReport = (PBEACON_REPORT) pDest; + pDest += sizeof(BEACON_REPORT); + Length += sizeof(BEACON_REPORT); + + // 4. Copy Channel number + pBeaconReport->Channel = pBss->Channel; + pBeaconReport->Spare = 0; + pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration; + pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS); + pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta; + pBeaconReport->BeaconInterval = pBss->BeaconPeriod; + pBeaconReport->CapabilityInfo = pBss->CapabilityInfo; + COPY_MAC_ADDR(pBeaconReport->BSSID, pBss->Bssid); + NdisMoveMemory(pBeaconReport->ParentTSF, pBss->PTSF, 4); + NdisMoveMemory(pBeaconReport->TargetTSF, pBss->TTSF, 8); + + // 5. Create SSID + *pDest++ = 0x00; + *pDest++ = pBss->SsidLen; + NdisMoveMemory(pDest, pBss->Ssid, pBss->SsidLen); + pDest += pBss->SsidLen; + Length += (2 + pBss->SsidLen); + + // 6. Create SupportRates + *pDest++ = 0x01; + *pDest++ = pBss->SupRateLen; + NdisMoveMemory(pDest, pBss->SupRate, pBss->SupRateLen); + pDest += pBss->SupRateLen; + Length += (2 + pBss->SupRateLen); + + // 7. DS Parameter + *pDest++ = 0x03; + *pDest++ = 1; + *pDest++ = pBss->Channel; + Length += 3; + + // 8. IBSS parameter if presents + if (pBss->BssType == BSS_ADHOC) + { + *pDest++ = 0x06; + *pDest++ = 2; + *(PUSHORT) pDest = pBss->AtimWin; + pDest += 2; + Length += 4; + } + + // 9. Update length field, not include EID and length + pReport->Length = Length - 4; + + // 10. Update total frame size + pAd->StaCfg.FrameReportLen += Length; + } +} diff --git a/drivers/staging/rt3070/sta/assoc.c b/drivers/staging/rt3070/sta/assoc.c new file mode 100644 index 000000000000..5c33a895bf7f --- /dev/null +++ b/drivers/staging/rt3070/sta/assoc.c @@ -0,0 +1,2060 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + assoc.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-9-3 porting from RT2500 +*/ +#include "../rt_config.h" + +UCHAR CipherWpaTemplate[] = { + 0xdd, // WPA IE + 0x16, // Length + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x02, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x01 // authentication + }; + +UCHAR CipherWpa2Template[] = { + 0x30, // RSN IE + 0x14, // Length + 0x01, 0x00, // Version + 0x00, 0x0f, 0xac, 0x02, // group cipher, TKIP + 0x01, 0x00, // number of pairwise + 0x00, 0x0f, 0xac, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x0f, 0xac, 0x02, // authentication + 0x00, 0x00, // RSN capability + }; + +UCHAR Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02}; + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID AssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, ASSOC_IDLE, ASSOC_MACHINE_BASE); + + // first column + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)MlmeAssocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)MlmeReassocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)MlmeDisassocReqAction); + StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); + + // second column + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction); + // + // Patch 3Com AP MOde:3CRWE454G72 + // We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp. + // + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction); + StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)AssocTimeoutAction); + + // third column + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction); + // + // Patch, AP doesn't send Reassociate Rsp frame to Station. + // + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction); + StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ReassocTimeoutAction); + + // fourth column + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction); + StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, (STATE_MACHINE_FUNC)DisassocTimeoutAction); + + // initialize the timer + RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE); +} + +/* + ========================================================================== + Description: + Association timeout procedure. After association timeout, this function + will be called and it will put a message into the MLME queue + Parameters: + Standard timer parameters + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AssocTimeout(IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Reassociation timeout procedure. After reassociation timeout, this + function will be called and put a message into the MLME queue + Parameters: + Standard timer parameters + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID ReassocTimeout(IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Disassociation timeout procedure. After disassociation timeout, this + function will be called and put a message into the MLME queue + Parameters: + Standard timer parameters + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID DisassocTimeout(IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + mlme assoc req handling procedure + Parameters: + Adapter - Adapter pointer + Elem - MLME Queue Element + Pre: + the station has been authenticated and the following information is stored in the config + -# SSID + -# supported rates and their length + -# listen interval (Adapter->StaCfg.default_listen_count) + -# Transmit power (Adapter->StaCfg.tx_power) + Post : + -# An association request frame is generated and sent to the air + -# Association timer starts + -# Association state -> ASSOC_WAIT_RSP + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR ApAddr[6]; + HEADER_802_11 AssocHdr; + UCHAR Ccx2Len = 5; + UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; + USHORT ListenIntv; + ULONG Timeout; + USHORT CapabilityInfo; + BOOLEAN TimerCancelled; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + ULONG tmp; + USHORT VarIesOffset; + UCHAR CkipFlag; + UCHAR CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH]; + UCHAR AironetCkipIe = IE_AIRONET_CKIP; + UCHAR AironetCkipLen = CKIP_NEGOTIATION_LENGTH; + UCHAR AironetIPAddressIE = IE_AIRONET_IPADDRESS; + UCHAR AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH; + UCHAR AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}; + USHORT Status; + + // Block all authentication request durning WPA block period + if (pAd->StaCfg.bBlockAssoc == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block Assoc request durning WPA block period!\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + } + // check sanity first + else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) + { + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); + + // Get an unused nonpaged memory + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() allocate memory failed \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + return; + } + + // Add by James 03/06/27 + pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + // Association don't need to report MAC address + pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs = + NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL; + pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo; + pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv; + // Only reassociate need this + //COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr); + pAd->StaCfg.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + + NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN); + // First add SSID + VarIesOffset = 0; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + VarIesOffset += pAd->MlmeAux.SsidLen; + + // Second add Supported rates + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen); + VarIesOffset += pAd->MlmeAux.SupRateLen; + // End Add by James + + if ((pAd->CommonCfg.Channel > 14) && + (pAd->CommonCfg.bIEEE80211H == TRUE)) + CapabilityInfo |= 0x0100; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n")); + MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr); + + // Build basic frame first + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AssocHdr, + 2, &CapabilityInfo, + 2, &ListenIntv, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + // HT + if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + ULONG TmpLen; + UCHAR HtLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; + if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) + { + HtLen = SIZE_HT_CAP_IE + 4; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } + else + { +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); +#else + NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, pAd->MlmeAux.HtCapabilityLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen,&HtCapabilityTmp, + END_OF_ARGS); +#endif + } + FrameLen += TmpLen; + } +#endif // DOT11_N_SUPPORT // + + // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION + // Case I: (Aggregation + Piggy-Back) + // 1. user enable aggregation, AND + // 2. Mac support piggy-back + // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON + // Case II: (Aggregation) + // 1. user enable aggregation, AND + // 2. AP annouces it's AGGREGATION-capable in BEACON + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + else if (pAd->MlmeAux.APRalinkIe & 0x00000001) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + else + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + + if (pAd->MlmeAux.APEdcaParm.bValid) + { + if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable) + { + QBSS_STA_INFO_PARM QosInfo; + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; + WmeIe[8] |= *(PUCHAR)&QosInfo; + } + else + { + // The Parameter Set Count is set to ¡§0¡¨ in the association request frames + // WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], + END_OF_ARGS); + FrameLen += tmp; + } + + // + // Let WPA(#221) Element ID on the end of this association frame. + // Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp. + // For example: Put Vendor Specific IE on the front of WPA IE. + // This happens on AP (Model No:Linksys WRK54G) + // + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + ) + ) + { + UCHAR RSNIe = IE_WPA; + + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) + { + RSNIe = IE_WPA2; + } + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifdef SIOCSIWGENIE + if (pAd->StaCfg.WpaSupplicantUP != 1) +#endif // SIOCSIWGENIE // +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); + + // Check for WPA PMK cache list + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) + { + INT idx; + BOOLEAN FoundPMK = FALSE; + // Search chched PMKID, append it if existed + for (idx = 0; idx < PMKID_NO; idx++) + { + if (NdisEqualMemory(ApAddr, &pAd->StaCfg.SavedPMK[idx].BSSID, 6)) + { + FoundPMK = TRUE; + break; + } + } + + if (FoundPMK) + { + // Set PMK number + *(PUSHORT) &pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len] = 1; + NdisMoveMemory(&pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len + 2], &pAd->StaCfg.SavedPMK[idx].PMKID, 16); + pAd->StaCfg.RSNIE_Len += 18; + } + } + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifdef SIOCSIWGENIE + if (pAd->StaCfg.WpaSupplicantUP == 1) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + } + else +#endif +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + } + + FrameLen += tmp; + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifdef SIOCSIWGENIE + if (pAd->StaCfg.WpaSupplicantUP != 1) +#endif +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + { + // Append Variable IE + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1); + VarIesOffset += 1; + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->StaCfg.RSNIE_Len, 1); + VarIesOffset += 1; + } + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); + VarIesOffset += pAd->StaCfg.RSNIE_Len; + + // Set Variable IEs Length + pAd->StaCfg.ReqVarIELen = VarIesOffset; + } + + // We have update that at PeerBeaconAtJoinRequest() + CkipFlag = pAd->StaCfg.CkipFlag; + if (CkipFlag != 0) + { + NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH); + CkipNegotiationBuffer[2] = 0x66; + // Make it try KP & MIC, since we have to follow the result from AssocRsp + CkipNegotiationBuffer[8] = 0x18; + CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22; + CkipFlag = 0x18; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetCkipIe, + 1, &AironetCkipLen, + AironetCkipLen, CkipNegotiationBuffer, + END_OF_ARGS); + FrameLen += tmp; + } + + // Add CCX v2 request if CCX2 admin state is on + if (pAd->StaCfg.CCXControl.field.Enable == 1) + { + + // + // Add AironetIPAddressIE for Cisco CCX 2.X + // Add CCX Version + // + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetIPAddressIE, + 1, &AironetIPAddressLen, + AironetIPAddressLen, AironetIPAddressBuffer, + 1, &Ccx2Ie, + 1, &Ccx2Len, + Ccx2Len, Ccx2IeInfo, + END_OF_ARGS); + FrameLen += tmp; + + // + // Add CipherSuite CCKM or LeapTkip if setting. + // +#ifdef LEAP_SUPPORT + if (LEAP_CCKM_ON(pAd)) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + CipherSuiteCiscoCCKMLen, CipherSuiteCiscoCCKM, + END_OF_ARGS); + FrameLen += tmp; + + // Third add RSN + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, CipherSuiteCiscoCCKM, CipherSuiteCiscoCCKMLen); //Save CipherSuite + VarIesOffset += CipherSuiteCiscoCCKMLen; + } + else if ((pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) && (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + CipherSuiteCCXTkipLen, CipherSuiteCCXTkip, + END_OF_ARGS); + FrameLen += tmp; + + // Third add RSN + NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, CipherSuiteCCXTkip, CipherSuiteCCXTkipLen); + VarIesOffset += CipherSuiteCCXTkipLen; + } +#endif // LEAP_SUPPORT // + + // Add by James 03/06/27 + // Set Variable IEs Length + pAd->StaCfg.ReqVarIELen = VarIesOffset; + pAd->StaCfg.AssocInfo.RequestIELength = VarIesOffset; + + // OffsetResponseIEs follow ReqVarIE + pAd->StaCfg.AssocInfo.OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAd->StaCfg.ReqVarIELen; + // End Add by James + } + + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout); + pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP; + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + } + +} + +/* + ========================================================================== + Description: + mlme reassoc req handling procedure + Parameters: + Elem - + Pre: + -# SSID (Adapter->StaCfg.ssid[]) + -# BSSID (AP address, Adapter->StaCfg.bssid) + -# Supported rates (Adapter->StaCfg.supported_rates[]) + -# Supported rates length (Adapter->StaCfg.supported_rates_len) + -# Tx power (Adapter->StaCfg.tx_power) + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeReassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR ApAddr[6]; + HEADER_802_11 ReassocHdr; + UCHAR Ccx2Len = 5; + UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; + USHORT CapabilityInfo, ListenIntv; + ULONG Timeout; + ULONG FrameLen = 0; + BOOLEAN TimerCancelled; + NDIS_STATUS NStatus; + ULONG tmp; + PUCHAR pOutBuffer = NULL; +//CCX 2.X +#ifdef LEAP_SUPPORT + UCHAR CkipFlag; + UCHAR CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH]; + UCHAR AironetCkipIe = IE_AIRONET_CKIP; + UCHAR AironetCkipLen = CKIP_NEGOTIATION_LENGTH; + UCHAR AironetIPAddressIE = IE_AIRONET_IPADDRESS; + UCHAR AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH; + UCHAR AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}; + UCHAR AironetCCKMReassocIE = IE_AIRONET_CCKMREASSOC; + UCHAR AironetCCKMReassocLen = AIRONET_CCKMREASSOC_LENGTH; + UCHAR AironetCCKMReassocBuffer[AIRONET_CCKMREASSOC_LENGTH]; + UCHAR AironetOUI[] = {0x00, 0x40, 0x96, 0x00}; + UCHAR MICMN[16]; + UCHAR CalcMicBuffer[80]; + ULONG CalcMicBufferLen = 0; +#endif // LEAP_SUPPORT // + USHORT Status; + + // Block all authentication request durning WPA block period + if (pAd->StaCfg.bBlockAssoc == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block ReAssoc request durning WPA block period!\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + } + // the parameters are the same as the association + else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) + { + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() allocate memory failed \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + return; + } + + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr); + + // make frame, use bssid as the AP address?? + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send RE-ASSOC request...\n")); + MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, ApAddr); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ReassocHdr, + 2, &CapabilityInfo, + 2, &ListenIntv, + MAC_ADDR_LEN, ApAddr, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + + if (pAd->MlmeAux.APEdcaParm.bValid) + { + if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable) + { + QBSS_STA_INFO_PARM QosInfo; + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; + WmeIe[8] |= *(PUCHAR)&QosInfo; + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + // HT + if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + ULONG TmpLen; + UCHAR HtLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; + if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE) + { + HtLen = SIZE_HT_CAP_IE + 4; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &HtLen, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } + else + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &pAd->MlmeAux.HtCapabilityLen, + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } + FrameLen += TmpLen; + } +#endif // DOT11_N_SUPPORT // + + // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION + // Case I: (Aggregation + Piggy-Back) + // 1. user enable aggregation, AND + // 2. Mac support piggy-back + // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON + // Case II: (Aggregation) + // 1. user enable aggregation, AND + // 2. AP annouces it's AGGREGATION-capable in BEACON + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + else if (pAd->MlmeAux.APRalinkIe & 0x00000001) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + else + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } +#ifdef LEAP_SUPPORT + if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE)) + { + CkipFlag = pAd->StaCfg.CkipFlag; // We have update that at PeerBeaconAtJoinRequest() + if (CkipFlag != 0) + { + NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH); + CkipNegotiationBuffer[2] = 0x66; + // Make it try KP & MIC, since we have to follow the result from AssocRsp + CkipNegotiationBuffer[8] = 0x18; + CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetCkipIe, + 1, &AironetCkipLen, + AironetCkipLen, CkipNegotiationBuffer, + END_OF_ARGS); + FrameLen += tmp; + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetIPAddressIE, + 1, &AironetIPAddressLen, + AironetIPAddressLen, AironetIPAddressBuffer, + END_OF_ARGS); + FrameLen += tmp; + + // + // The RN is incremented before each reassociation request. + // + pAd->StaCfg.CCKMRN++; + // + // Calculate MIC = hmac-md5(krk, STA-ID|BSSID|RSNIE|TSF|RN); + // + COPY_MAC_ADDR(CalcMicBuffer, pAd->CurrentAddress); + CalcMicBufferLen = MAC_ADDR_LEN; + COPY_MAC_ADDR(CalcMicBuffer + CalcMicBufferLen, pAd->MlmeAux.Bssid); + CalcMicBufferLen += MAC_ADDR_LEN; + NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, CipherSuiteCiscoCCKM, CipherSuiteCiscoCCKMLen); + CalcMicBufferLen += CipherSuiteCiscoCCKMLen; + NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, (PUCHAR) &pAd->StaCfg.CCKMBeaconAtJoinTimeStamp, sizeof(pAd->StaCfg.CCKMBeaconAtJoinTimeStamp)); + CalcMicBufferLen += sizeof(pAd->StaCfg.CCKMBeaconAtJoinTimeStamp); + NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, (PUCHAR)&pAd->StaCfg.CCKMRN, sizeof(pAd->StaCfg.CCKMRN)); + CalcMicBufferLen += sizeof(pAd->StaCfg.CCKMRN); + hmac_md5(pAd->StaCfg.KRK, LEN_EAP_MICK, CalcMicBuffer, CalcMicBufferLen, MICMN); + + // + // fill up CCKM reassociation request element + // + NdisMoveMemory(AironetCCKMReassocBuffer, AironetOUI, 4); + NdisMoveMemory(AironetCCKMReassocBuffer + 4, (PUCHAR)&pAd->StaCfg.CCKMBeaconAtJoinTimeStamp, 8); + NdisMoveMemory(AironetCCKMReassocBuffer + 12, (PUCHAR) &pAd->StaCfg.CCKMRN, 4); + NdisMoveMemory(AironetCCKMReassocBuffer +16, MICMN, 8); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &AironetCCKMReassocIE, + 1, &AironetCCKMReassocLen, + AironetCCKMReassocLen, AironetCCKMReassocBuffer, + END_OF_ARGS); + FrameLen += tmp; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + CipherSuiteCiscoCCKMLen,CipherSuiteCiscoCCKM, + END_OF_ARGS); + FrameLen += tmp; + } +#endif // LEAP_SUPPORT // + + // Add CCX v2 request if CCX2 admin state is on + if (pAd->StaCfg.CCXControl.field.Enable == 1) + { + // + // Add CCX Version + // + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &Ccx2Ie, + 1, &Ccx2Len, + Ccx2Len, Ccx2IeInfo, + END_OF_ARGS); + FrameLen += tmp; + } + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */ + pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP; + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + } +} + +/* + ========================================================================== + Description: + Upper layer issues disassoc request + Parameters: + Elem - + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID MlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_DISASSOC_REQ_STRUCT pDisassocReq; + HEADER_802_11 DisassocHdr; + PHEADER_802_11 pDisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + BOOLEAN TimerCancelled; + ULONG Timeout = 0; + USHORT Status; + +#ifdef QOS_DLS_SUPPORT + // send DLS-TEAR_DOWN message, + if (pAd->CommonCfg.bDLSCapable) + { + UCHAR i; + + // tear down local dls table entry + for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + + // tear down peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + } + } + } +#endif // QOS_DLS_SUPPORT // + + // skip sanity check + pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); + return; + } + + + + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled); + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n", + pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2], + pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5], pDisassocReq->Reason)); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr); // patch peap ttls switching issue + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DisassocHdr, + 2, &pDisassocReq->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + // To patch Instance and Buffalo(N) AP + // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine + // Therefore, we send both of them. + pDisassocHdr = (PHEADER_802_11)pOutBuffer; + pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING; + COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr); + + RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */ + pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP; + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + union iwreq_data wrqu; + //send disassociate event to wpa_supplicant + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + +} + +/* + ========================================================================== + Description: + peer sends assoc rsp back + Parameters: + Elme - MLME message containing the received frame + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT CapabilityInfo, Status, Aid; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + UCHAR Addr2[MAC_ADDR_LEN]; + BOOLEAN TimerCancelled; + UCHAR CkipFlag; + EDCA_PARM EdcaParm; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + + if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, + &HtCapability,&AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) + { + // The frame is for me ? + if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n",Elem->Wcid, pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); +#endif // DOT11_N_SUPPORT // + RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled); + if(Status == MLME_SUCCESS) + { + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR idx; + + // supported rates array may not be sorted. sort it and find the maximum rate + for (idx=0; idxMacTab.Content[BSSID_WCID], MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo); + + pAd->StaCfg.CkipFlag = CkipFlag; + if (CkipFlag & 0x18) + { + NdisZeroMemory(pAd->StaCfg.TxSEQ, 4); + NdisZeroMemory(pAd->StaCfg.RxSEQ, 4); + NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4); + pAd->StaCfg.GIV[0] = RandomByte(pAd); + pAd->StaCfg.GIV[1] = RandomByte(pAd); + pAd->StaCfg.GIV[2] = RandomByte(pAd); + pAd->StaCfg.bCkipOn = TRUE; + DBGPRINT(RT_DEBUG_TRACE, (" pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag)); + } + } + else + { + // Faile on Association, we need to check the status code + // Is that a Rogue AP? +#ifdef LEAP_SUPPORT + if ((pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) && (Status == MLME_ALG_NOT_SUPPORT)) + { //Possibly Rogue AP + RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, pAd->MlmeAux.Bssid, LEAP_REASON_INVALID_AUTH); + } +#endif // LEAP_SUPPORT // + } + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerAssocRspAction() sanity check fail\n")); + } +} + +/* + ========================================================================== + Description: + peer sends reassoc rsp + Parametrs: + Elem - MLME message cntaining the received frame + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerReassocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT CapabilityInfo; + USHORT Status; + USHORT Aid; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR CkipFlag; + BOOLEAN TimerCancelled; + EDCA_PARM EdcaParm; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + + if(PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, + &HtCapability, &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag)) + { + if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) // The frame is for me ? + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", Status)); + RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled); + + if(Status == MLME_SUCCESS) + { + // go to procedure listed on page 376 + AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen, + &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + union iwreq_data wrqu; + + SendAssocIEsToWpaSupplicant(pAd); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_ASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + wext_notify_event_assoc(pAd); + + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + } + + // + // Cisco Leap CCKM supported Re-association. + // +#ifdef LEAP_SUPPORT + if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE)) + { + if (CCKMAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen) == TRUE) + { + pAd->StaCfg.CkipFlag = CkipFlag; + if (CkipFlag & 0x18) + { + NdisZeroMemory(pAd->StaCfg.TxSEQ, 4); + NdisZeroMemory(pAd->StaCfg.RxSEQ, 4); + NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4); + pAd->StaCfg.GIV[0] = RandomByte(pAd); + pAd->StaCfg.GIV[1] = RandomByte(pAd); + pAd->StaCfg.GIV[2] = RandomByte(pAd); + pAd->StaCfg.bCkipOn = TRUE; + DBGPRINT(RT_DEBUG_TRACE, (" pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag)); + } + + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - CCKMAssocRspSanity() sanity check fail\n")); + } + } + else +#endif // LEAP_SUPPORT // + { + // CkipFlag is no use for reassociate + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerReassocRspAction() sanity check fail\n")); + } + +} + +/* + ========================================================================== + Description: + procedures on IEEE 802.11/1999 p.376 + Parametrs: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AssocPostProc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT Aid, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo) // AP might use this additional ht info IE +{ + ULONG Idx; + + pAd->MlmeAux.BssType = BSS_INFRA; + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2); + pAd->MlmeAux.Aid = Aid; + pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; +#ifdef DOT11_N_SUPPORT + // Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on. + if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE)) + { + pEdcaParm->bValid = TRUE; + pEdcaParm->Aifsn[0] = 3; + pEdcaParm->Aifsn[1] = 7; + pEdcaParm->Aifsn[2] = 2; + pEdcaParm->Aifsn[3] = 2; + + pEdcaParm->Cwmin[0] = 4; + pEdcaParm->Cwmin[1] = 4; + pEdcaParm->Cwmin[2] = 3; + pEdcaParm->Cwmin[3] = 2; + + pEdcaParm->Cwmax[0] = 10; + pEdcaParm->Cwmax[1] = 10; + pEdcaParm->Cwmax[2] = 4; + pEdcaParm->Cwmax[3] = 3; + + pEdcaParm->Txop[0] = 0; + pEdcaParm->Txop[1] = 0; + pEdcaParm->Txop[2] = 96; + pEdcaParm->Txop[3] = 48; + + } +#endif // DOT11_N_SUPPORT // + + NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + + // filter out un-supported rates + pAd->MlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + + // filter out un-supported rates + pAd->MlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); + +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen > 0) + { + RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo); + } + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); + + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> (Mmps=%d, AmsduSize=%d, )\n", + pAd->MacTab.Content[BSSID_WCID].MmpsMode, pAd->MacTab.Content[BSSID_WCID].AMsduSize)); +#endif // DOT11_N_SUPPORT // + + // Set New WPA information + Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel); + if (Idx == BSS_NOT_FOUND) + { + DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n")); + } + else + { + // Init variable + pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0; + NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, MAX_LEN_OF_RSNIE); + + // Store appropriate RSN_IE for WPA SM negotiation later + if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0)) + { + PUCHAR pVIE; + USHORT len; + PEID_STRUCT pEid; + + pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs; + len = pAd->ScanTab.BssEntry[Idx].VarIELen; + + while (len > 0) + { + pEid = (PEID_STRUCT) pVIE; + // For WPA/WPAPSK + if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2)); + pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n")); + } + // For WPA2/WPA2PSK + else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2)); + pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n")); + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + } + + if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> no RSN_IE \n")); + } + else + { + hex_dump("RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len); + } + } +} + +/* + ========================================================================== + Description: + left part of IEEE 802.11/1999 p.374 + Parameters: + Elem - MLME message containing the received frame + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDisassocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n")); + if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() Reason = %d\n", Reason)); + if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2)) + { + + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + + +#ifdef LEAP_SUPPORT + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + // Cisco_LEAP has start a timer + // We should cancel it if using LEAP + RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &TimerCancelled); + //Check is it mach the LEAP Authentication failed as possible a Rogue AP + //on it's PortSecured not equal to WPA_802_1X_PORT_SECURED while process the Association. + if ((pAd->Mlme.LeapMachine.CurrState != LEAP_IDLE) && (pAd->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED)) + { + RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_AUTH_TIMEOUT); + } + } +#endif // LEAP_SUPPORT // + // + // Get Current System time and Turn on AdjacentAPReport + // + NdisGetSystemUpTime(&pAd->StaCfg.CCXAdjacentAPLinkDownTime); + pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE; + LinkDown(pAd, TRUE); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + union iwreq_data wrqu; + //send disassociate event to wpa_supplicant + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() sanity check fail\n")); + } + +} + +/* + ========================================================================== + Description: + what the state machine will do after assoc timeout + Parameters: + Elme - + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AssocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + what the state machine will do after reassoc timeout + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID ReassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + what the state machine will do after disassoc timeout + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID DisassocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n")); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); +} + +VOID InvalidStateWhenAssoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status); +} + +VOID InvalidStateWhenReassoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status); +} + +VOID InvalidStateWhenDisassociate( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n", + pAd->Mlme.AssocMachine.CurrState)); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + right part of IEEE 802.11/1999 page 374 + Note: + This event should never cause ASSOC state machine perform state + transition, and has no relationship with CNTL machine. So we separate + this routine as a service outside of ASSOC state transition table. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID Cls3errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + HEADER_802_11 DisassocHdr; + PHEADER_802_11 pDisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + USHORT Reason = REASON_CLS3ERR; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame\n")); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid); // patch peap ttls switching issue + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DisassocHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + // To patch Instance and Buffalo(N) AP + // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine + // Therefore, we send both of them. + pDisassocHdr = (PHEADER_802_11)pOutBuffer; + pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH; + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DisassocReason = REASON_CLS3ERR; + COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr); +} + + /* + ========================================================================== + Description: + Switch between WEP and CKIP upon new association up. + Parameters: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID SwitchBetweenWepAndCkip( + IN PRTMP_ADAPTER pAd) +{ + int i; + SHAREDKEY_MODE_STRUC csr1; + + // if KP is required. change the CipherAlg in hardware shard key table from WEP + // to CKIP. else remain as WEP + if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10)) + { + // modify hardware key table so that MAC use correct algorithm to decrypt RX + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word); + if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP64) + csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP64; + else if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP128) + csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP128; + + if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP64) + csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP64; + else if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP128) + csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP128; + + if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP64) + csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP64; + else if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP128) + csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP128; + + if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP64) + csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP64; + else if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP128) + csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP128; + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word); + DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg])); + + // modify software key table so that driver can specify correct algorithm in TXD upon TX + for (i=0; iSharedKey[BSS0][i].CipherAlg == CIPHER_WEP64) + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP64; + else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP128) + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP128; + } + } + + // else if KP NOT inused. change the CipherAlg in hardware shard key table from CKIP + // to WEP. + else + { + // modify hardware key table so that MAC use correct algorithm to decrypt RX + RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word); + if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP64) + csr1.field.Bss0Key0CipherAlg = CIPHER_WEP64; + else if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP128) + csr1.field.Bss0Key0CipherAlg = CIPHER_WEP128; + + if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP64) + csr1.field.Bss0Key1CipherAlg = CIPHER_WEP64; + else if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP128) + csr1.field.Bss0Key1CipherAlg = CIPHER_WEP128; + + if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP64) + csr1.field.Bss0Key2CipherAlg = CIPHER_WEP64; + else if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP128) + csr1.field.Bss0Key2CipherAlg = CIPHER_WEP128; + + if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP64) + csr1.field.Bss0Key3CipherAlg = CIPHER_WEP64; + else if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP128) + csr1.field.Bss0Key3CipherAlg = CIPHER_WEP128; + + // modify software key table so that driver can specify correct algorithm in TXD upon TX + for (i=0; iSharedKey[BSS0][i].CipherAlg == CIPHER_CKIP64) + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP64; + else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP128) + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP128; + } + + // + // On WPA-NONE, must update CipherAlg. + // Because the OID_802_11_WEP_STATUS was been set after OID_802_11_ADD_KEY + // and CipherAlg will be CIPHER_NONE by Windows ZeroConfig. + // So we need to update CipherAlg after connect. + // + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + for (i = 0; i < SHARE_KEY_NUM; i++) + { + if (pAd->SharedKey[BSS0][i].KeyLen != 0) + { + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) + { + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_TKIP; + } + else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_AES; + } + } + else + { + pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE; + } + } + + csr1.field.Bss0Key0CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + csr1.field.Bss0Key1CipherAlg = pAd->SharedKey[BSS0][1].CipherAlg; + csr1.field.Bss0Key2CipherAlg = pAd->SharedKey[BSS0][2].CipherAlg; + csr1.field.Bss0Key3CipherAlg = pAd->SharedKey[BSS0][3].CipherAlg; + } + RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word); + DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg])); + } +} + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT +VOID SendAssocIEsToWpaSupplicant( + IN PRTMP_ADAPTER pAd) +{ + union iwreq_data wrqu; + unsigned char custom[IW_CUSTOM_MAX] = {0}; + + if ((pAd->StaCfg.ReqVarIELen + 17) <= IW_CUSTOM_MAX) + { + sprintf(custom, "ASSOCINFO_ReqIEs="); + NdisMoveMemory(custom+17, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = pAd->StaCfg.ReqVarIELen + 17; + wrqu.data.flags = RT_REQIE_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom); + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_ASSOCINFO_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen + 17 > MAX_CUSTOM_LEN\n")); + + return; +} +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +int wext_notify_event_assoc( + IN RTMP_ADAPTER *pAd) +{ + union iwreq_data wrqu; + char custom[IW_CUSTOM_MAX] = {0}; + +#if WIRELESS_EXT > 17 + if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX) + { + wrqu.data.length = pAd->StaCfg.ReqVarIELen; + memcpy(custom, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen); + wireless_send_event(pAd->net_dev, IWEVASSOCREQIE, &wrqu, custom); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n")); +#else + if (((pAd->StaCfg.ReqVarIELen*2) + 17) <= IW_CUSTOM_MAX) + { + UCHAR idx; + wrqu.data.length = (pAd->StaCfg.ReqVarIELen*2) + 17; + sprintf(custom, "ASSOCINFO(ReqIEs="); + for (idx=0; idxStaCfg.ReqVarIELen; idx++) + sprintf(custom, "%s%02x", custom, pAd->StaCfg.ReqVarIEs[idx]); + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("(pAd->StaCfg.ReqVarIELen*2) + 17 > MAX_CUSTOM_LEN\n")); +#endif + + return 0; + +} +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + +BOOLEAN StaAddMacTableEntry( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR MaxSupportedRateIn500Kbps, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN USHORT CapabilityInfo) +{ + UCHAR MaxSupportedRate = RATE_11; + + if (ADHOC_ON(pAd)) + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + if ((pAd->CommonCfg.PhyMode == PHY_11G) && (MaxSupportedRate < RATE_FIRST_OFDM_RATE)) + return FALSE; + +#ifdef DOT11_N_SUPPORT + // 11n only + if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))&& (HtCapabilityLen == 0)) + return FALSE; +#endif // DOT11_N_SUPPORT // + + if (!pEntry) + return FALSE; + + NdisAcquireSpinLock(&pAd->MacTabLock); + if (pEntry) + { + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + if ((MaxSupportedRate < RATE_FIRST_OFDM_RATE) || + (pAd->CommonCfg.PhyMode == PHY_11B)) + { + pEntry->RateLen = 4; + if (MaxSupportedRate >= RATE_FIRST_OFDM_RATE) + MaxSupportedRate = RATE_11; + } + else + pEntry->RateLen = 12; + + pEntry->MaxHTPhyMode.word = 0; + pEntry->MinHTPhyMode.word = 0; + pEntry->HTPhyMode.word = 0; + pEntry->MaxSupportedRate = MaxSupportedRate; + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + } + pEntry->CapabilityInfo = CapabilityInfo; + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); + } + +#ifdef DOT11_N_SUPPORT + // If this Entry supports 802.11n, upgrade to HT rate. + if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; //k,bitmask; + CHAR i; + + if (ADHOC_ON(pAd)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + if ((pHtCapability->HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((pHtCapability->HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40)); + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + // 3*3 + if (pAd->MACVersion >= RALINK_2883_VERSION && pAd->MACVersion < RALINK_3070_VERSION) + pEntry->MaxHTPhyMode.field.TxBF = pAd->CommonCfg.RegTransmitSetting.field.TxBF; + + // find max fixed rate + for (i=23; i>=0; i--) // 3*3 + { + j = i/8; + bitmask = (1<<(i-(j*8))); + if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = i; + break; + } + if (i==0) + break; + } + + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) + { + // Fix MCS as HT Duplicated Mode + pEntry->MaxHTPhyMode.field.BW = 1; + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pEntry->MaxHTPhyMode.field.STBC = 0; + pEntry->MaxHTPhyMode.field.ShortGI = 0; + pEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) + { + // STA supports fixed MCS + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + } + } + + pEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); + if (pHtCapability->HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (pHtCapability->HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (pHtCapability->HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (pHtCapability->HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (pHtCapability->ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + } + else + { + pAd->MacTab.fAnyStationIsLegacy = TRUE; + } + + NdisMoveMemory(&pEntry->HTCapability, pHtCapability, sizeof(HT_CAPABILITY_IE)); +#endif // DOT11_N_SUPPORT // + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + + // Set asic auto fall back + if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + // If the legacy mode is set, overwrite the transmit setting of this entry. + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + + pEntry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->Sst = SST_ASSOC; + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->AuthMode = pAd->StaCfg.AuthMode; + pEntry->WepStatus = pAd->StaCfg.WepStatus; + + NdisReleaseSpinLock(&pAd->MacTabLock); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + { + union iwreq_data wrqu; + + SendAssocIEsToWpaSupplicant(pAd); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_ASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + wext_notify_event_assoc(pAd); + + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + return TRUE; +} + + diff --git a/drivers/staging/rt3070/sta/auth.c b/drivers/staging/rt3070/sta/auth.c new file mode 100644 index 000000000000..032b5df058bc --- /dev/null +++ b/drivers/staging/rt3070/sta/auth.c @@ -0,0 +1,475 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + auth.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-9-3 porting from RT2500 +*/ +#include "../rt_config.h" + +/* + ========================================================================== + Description: + authenticate state machine init, including state transition and timer init + Parameters: + Sm - pointer to the auth state machine + Note: + The state machine looks like this + + AUTH_REQ_IDLE AUTH_WAIT_SEQ2 AUTH_WAIT_SEQ4 + MT2_MLME_AUTH_REQ mlme_auth_req_action invalid_state_when_auth invalid_state_when_auth + MT2_PEER_AUTH_EVEN drop peer_auth_even_at_seq2_action peer_auth_even_at_seq4_action + MT2_AUTH_TIMEOUT Drop auth_timeout_action auth_timeout_action + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ + +void AuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_REQ_IDLE, AUTH_MACHINE_BASE); + + // the first column + StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)MlmeAuthReqAction); + + // the second column + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq2Action); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction); + + // the third column + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq4Action); + StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction); + + RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE); +} + +/* + ========================================================================== + Description: + function to be executed at timer thread when auth timer expires + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE,("AUTH - AuthTimeout\n")); + + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + // send a de-auth to reset AP's state machine (Patch AP-Dir635) + if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2) + Cls2errAction(pAd, pAd->MlmeAux.Bssid); + + + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeAuthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr[6]; + USHORT Alg, Seq, Status; + ULONG Timeout; + HEADER_802_11 AuthHdr; + BOOLEAN TimerCancelled; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + + // Block all authentication request durning WPA block period + if (pAd->StaCfg.bBlockAssoc == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Block Auth request durning WPA block period!\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } + else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg)) + { + // reset timer + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr); + pAd->MlmeAux.Alg = Alg; + Seq = 1; + Status = MLME_SUCCESS; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", Alg)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg)); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&AuthHdr, + 2, &Alg, + 2, &Seq, + 2, &Status, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.AuthTimer, Timeout); + pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2; + } + else + { + DBGPRINT_ERR(("AUTH - MlmeAuthReqAction() sanity check failed\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerAuthRspAtSeq2Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Seq, Status, RemoteStatus, Alg; + UCHAR ChlgText[CIPHER_TEXT_LEN]; + UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; + UCHAR Element[2]; + HEADER_802_11 AuthHdr; + BOOLEAN TimerCancelled; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Status2; + + if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) + { + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); + + if (Status == MLME_SUCCESS) + { + // Authentication Mode "LEAP" has allow for CCX 1.X + if ((pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen) +#ifdef LEAP_SUPPORT + || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) + { + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; +#ifdef LEAP_SUPPORT + pAd->Mlme.LeapMachine.CurrState = LEAP_IDLE; +#endif // LEAP_SUPPORT // + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } + else + { + // 2. shared key, need to be challenged + Seq++; + RemoteStatus = MLME_SUCCESS; + + // Get an unused nonpaged memory + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status2 = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid); + AuthHdr.FC.Wep = 1; + // Encrypt challenge text & auth information + RTMPInitWepEngine( + pAd, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen, + CyperChlgText); + + Alg = cpu2le16(*(USHORT *)&Alg); + Seq = cpu2le16(*(USHORT *)&Seq); + RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus); + + RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2); + RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2); + RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2); + Element[0] = 16; + Element[1] = 128; + RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2); + RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128); + RTMPSetICV(pAd, CyperChlgText + 140); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AuthHdr, + CIPHER_TEXT_LEN + 16, CyperChlgText, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT); + pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4; + } + } + else + { +#ifdef LEAP_SUPPORT + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + //Invalid Authentication possible rogue AP + //Add this Ap to Rogue AP. + RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_INVALID_AUTH); + } +#endif // LEAP_SUPPORT // + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n")); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerAuthRspAtSeq4Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Alg, Seq, Status; + CHAR ChlgText[CIPHER_TEXT_LEN]; + BOOLEAN TimerCancelled; + + if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) + { + if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n")); + RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled); + + if (Status != MLME_SUCCESS) + { + pAd->StaCfg.AuthFailReason = Status; + COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2); + } + + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n")); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_DEAUTH_REQ_STRUCT *pInfo; + HEADER_802_11 DeauthHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Status; + + pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status); + return; + } + + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason)); + MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DeauthHdr, + 2, &pInfo->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DeauthReason = pInfo->Reason; + COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status); + + // send wireless event - for deauthentication + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AuthTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n")); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID InvalidStateWhenAuth( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState)); + pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + Some STA/AP + Note: + This action should never trigger AUTH state transition, therefore we + separate it from AUTH state machine, and make it as a standalone service + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID Cls2errAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + HEADER_802_11 DeauthHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Reason = REASON_CLS2ERR; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n")); + MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DeauthHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + pAd->StaCfg.DeauthReason = Reason; + COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr); +} + + diff --git a/drivers/staging/rt3070/sta/auth_rsp.c b/drivers/staging/rt3070/sta/auth_rsp.c new file mode 100644 index 000000000000..f7aa4b99cf56 --- /dev/null +++ b/drivers/staging/rt3070/sta/auth_rsp.c @@ -0,0 +1,167 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + auth_rsp.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-10-1 copy from RT2560 +*/ +#include "../rt_config.h" + +/* + ========================================================================== + Description: + authentication state machine init procedure + Parameters: + Sm - the state machine + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID AuthRspStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, MAX_AUTH_RSP_STATE, MAX_AUTH_RSP_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_RSP_IDLE, AUTH_RSP_MACHINE_BASE); + + // column 1 + StateMachineSetAction(Sm, AUTH_RSP_IDLE, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction); + + // column 2 + StateMachineSetAction(Sm, AUTH_RSP_WAIT_CHAL, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction); + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID PeerAuthSimpleRspGenAndSend( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHdr80211, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT Reason, + IN USHORT Status) +{ + HEADER_802_11 AuthHdr; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + + if (Reason != MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("Peer AUTH fail...\n")); + return; + } + + //Get an unused nonpaged memory + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("Send AUTH response (seq#2)...\n")); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr80211->Addr2, pAd->MlmeAux.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AuthHdr, + 2, &Alg, + 2, &Seq, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID PeerDeauthAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + + if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason)) + { + if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(Addr2, pAd->CommonCfg.Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - receive DE-AUTH from our AP (Reason=%d)\n", Reason)); + + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + + + // send wireless event - for deauthentication + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + LinkDown(pAd, TRUE); + + // Authentication Mode Cisco_LEAP has start a timer + // We should cancel it if using LEAP +#ifdef LEAP_SUPPORT + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &TimerCancelled); + //Check is it mach the LEAP Authentication failed as possible a Rogue AP + //on it's PortSecured not equal to WPA_802_1X_PORT_SECURED while process the Authenticaton. + if ((pAd->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED) && (pAd->Mlme.LeapMachine.CurrState != LEAP_IDLE)) + { + RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_AUTH_TIMEOUT); + } + } +#endif // LEAP_SUPPORT // + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - PeerDeauthAction() sanity check fail\n")); + } +} + diff --git a/drivers/staging/rt3070/sta/connect.c b/drivers/staging/rt3070/sta/connect.c new file mode 100644 index 000000000000..152c0bd0f822 --- /dev/null +++ b/drivers/staging/rt3070/sta/connect.c @@ -0,0 +1,2857 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + connect.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John 2004-08-08 Major modification from RT2560 +*/ +#include "../rt_config.h" + +UCHAR CipherSuiteWpaNoneTkip[] = { + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x02, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x00 // authentication + }; +UCHAR CipherSuiteWpaNoneTkipLen = (sizeof(CipherSuiteWpaNoneTkip) / sizeof(UCHAR)); + +UCHAR CipherSuiteWpaNoneAes[] = { + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x04, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x04, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x00 // authentication + }; +UCHAR CipherSuiteWpaNoneAesLen = (sizeof(CipherSuiteWpaNoneAes) / sizeof(UCHAR)); + +// The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS, +// or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS +// All settings successfuly negotiated furing MLME state machines become final settings +// and are copied to pAd->StaActive +#define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ +{ \ + (_pAd)->CommonCfg.SsidLen = (_pAd)->MlmeAux.SsidLen; \ + NdisMoveMemory((_pAd)->CommonCfg.Ssid, (_pAd)->MlmeAux.Ssid, (_pAd)->MlmeAux.SsidLen); \ + COPY_MAC_ADDR((_pAd)->CommonCfg.Bssid, (_pAd)->MlmeAux.Bssid); \ + (_pAd)->CommonCfg.Channel = (_pAd)->MlmeAux.Channel; \ + (_pAd)->CommonCfg.CentralChannel = (_pAd)->MlmeAux.CentralChannel; \ + (_pAd)->StaActive.Aid = (_pAd)->MlmeAux.Aid; \ + (_pAd)->StaActive.AtimWin = (_pAd)->MlmeAux.AtimWin; \ + (_pAd)->StaActive.CapabilityInfo = (_pAd)->MlmeAux.CapabilityInfo; \ + (_pAd)->CommonCfg.BeaconPeriod = (_pAd)->MlmeAux.BeaconPeriod; \ + (_pAd)->StaActive.CfpMaxDuration = (_pAd)->MlmeAux.CfpMaxDuration; \ + (_pAd)->StaActive.CfpPeriod = (_pAd)->MlmeAux.CfpPeriod; \ + (_pAd)->StaActive.SupRateLen = (_pAd)->MlmeAux.SupRateLen; \ + NdisMoveMemory((_pAd)->StaActive.SupRate, (_pAd)->MlmeAux.SupRate, (_pAd)->MlmeAux.SupRateLen);\ + (_pAd)->StaActive.ExtRateLen = (_pAd)->MlmeAux.ExtRateLen; \ + NdisMoveMemory((_pAd)->StaActive.ExtRate, (_pAd)->MlmeAux.ExtRate, (_pAd)->MlmeAux.ExtRateLen);\ + NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));\ + NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));\ + NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));\ + COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].Addr, (_pAd)->MlmeAux.Bssid); \ + (_pAd)->MacTab.Content[BSSID_WCID].Aid = (_pAd)->MlmeAux.Aid; \ + (_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = (_pAd)->StaCfg.PairCipher;\ + COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.BssId, (_pAd)->MlmeAux.Bssid);\ + (_pAd)->MacTab.Content[BSSID_WCID].RateLen = (_pAd)->StaActive.SupRateLen + (_pAd)->StaActive.ExtRateLen;\ +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + + ========================================================================== +*/ +VOID MlmeCntlInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + // Control state machine differs from other state machines, the interface + // follows the standard interface + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID MlmeCntlMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem) +{ + switch(pAd->Mlme.CntlMachine.CurrState) + { + case CNTL_IDLE: + { + CntlIdleProc(pAd, Elem); + } + break; + case CNTL_WAIT_DISASSOC: + CntlWaitDisassocProc(pAd, Elem); + break; + case CNTL_WAIT_JOIN: + CntlWaitJoinProc(pAd, Elem); + break; + + // CNTL_WAIT_REASSOC is the only state in CNTL machine that does + // not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)". + // Therefore not protected by NDIS's "only one outstanding OID request" + // rule. Which means NDIS may SET OID in the middle of ROAMing attempts. + // Current approach is to block new SET request at RTMPSetInformation() + // when CntlMachine.CurrState is not CNTL_IDLE + case CNTL_WAIT_REASSOC: + CntlWaitReassocProc(pAd, Elem); + break; + + case CNTL_WAIT_START: + CntlWaitStartProc(pAd, Elem); + break; + case CNTL_WAIT_AUTH: + CntlWaitAuthProc(pAd, Elem); + break; + case CNTL_WAIT_AUTH2: + CntlWaitAuthProc2(pAd, Elem); + break; + case CNTL_WAIT_ASSOC: + CntlWaitAssocProc(pAd, Elem); + break; + + case CNTL_WAIT_OID_LIST_SCAN: + if(Elem->MsgType == MT2_SCAN_CONF) + { + // Resume TxRing after SCANING complete. We hope the out-of-service time + // won't be too long to let upper layer time-out the waiting frames + RTMPResumeMsduTransmission(pAd); + if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) + { + // Cisco scan request is finished, prepare beacon report + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL); + } + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + + // + // Set LED status to previous status. + // + if (pAd->bLedOnScanning) + { + pAd->bLedOnScanning = FALSE; + RTMPSetLED(pAd, pAd->LedStatus); + } +#ifdef DOT11N_DRAFT3 + // AP sent a 2040Coexistence mgmt frame, then station perform a scan, and then send back the respone. + if (pAd->CommonCfg.BSSCoexist2040.field.InfoReq == 1) + { + Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE); + } +#endif // DOT11N_DRAFT3 // + } + break; + + case CNTL_WAIT_OID_DISASSOC: + if (Elem->MsgType == MT2_DISASSOC_CONF) + { + LinkDown(pAd, FALSE); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } + break; +#ifdef RT2870 + // + // This state is for that we want to connect to an AP but + // it didn't find on BSS List table. So we need to scan the air first, + // after that we can try to connect to the desired AP if available. + // + case CNTL_WAIT_SCAN_FOR_CONNECT: + if(Elem->MsgType == MT2_SCAN_CONF) + { + // Resume TxRing after SCANING complete. We hope the out-of-service time + // won't be too long to let upper layer time-out the waiting frames + RTMPResumeMsduTransmission(pAd); +#ifdef CCX_SUPPORT + if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) + { + // Cisco scan request is finished, prepare beacon report + MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL); + } +#endif // CCX_SUPPORT // + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + + // + // Check if we can connect to. + // + BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + if (pAd->MlmeAux.SsidBssTab.BssNr > 0) + { + MlmeAutoReconnectLastSSID(pAd); + } + } + break; +#endif // RT2870 // + default: + DBGPRINT_ERR(("!ERROR! CNTL - Illegal message type(=%ld)", Elem->MsgType)); + break; + } +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlIdleProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + switch(Elem->MsgType) + { + case OID_802_11_SSID: + CntlOidSsidProc(pAd, Elem); + break; + + case OID_802_11_BSSID: + CntlOidRTBssidProc(pAd,Elem); + break; + + case OID_802_11_BSSID_LIST_SCAN: + CntlOidScanProc(pAd,Elem); + break; + + case OID_802_11_DISASSOCIATE: +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + break; + } +#endif // RALINK_ATE // + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE_WITH_WEB_UI) +#endif // WPA_SUPPLICANT_SUPPORT // + { + // Set the AutoReconnectSsid to prevent it reconnect to old SSID + // Since calling this indicate user don't want to connect to that SSID anymore. + pAd->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); + } + break; + + case MT2_MLME_ROAMING_REQ: + CntlMlmeRoamingProc(pAd, Elem); + break; + + case OID_802_11_MIC_FAILURE_REPORT_FRAME: + WpaMicFailureReportFrame(pAd, Elem); + break; + +#ifdef QOS_DLS_SUPPORT + case RT_OID_802_11_SET_DLS_PARAM: + CntlOidDLSSetupProc(pAd, Elem); + break; +#endif // QOS_DLS_SUPPORT // + + default: + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n",Elem->MsgType)); + break; + } +} + +VOID CntlOidScanProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_SCAN_REQ_STRUCT ScanReq; + ULONG BssIdx = BSS_NOT_FOUND; + BSS_ENTRY CurrBss; + +#ifdef RALINK_ATE +/* Disable scanning when ATE is running. */ + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + + // record current BSS if network is connected. + // 2003-2-13 do not include current IBSS if this is the only STA in this IBSS. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + BssIdx = BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Channel); + if (BssIdx != BSS_NOT_FOUND) + { + NdisMoveMemory(&CurrBss, &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY)); + } + } + + // clean up previous SCAN result, add current BSS back to table if any + BssTableInit(&pAd->ScanTab); + if (BssIdx != BSS_NOT_FOUND) + { + // DDK Note: If the NIC is associated with a particular BSSID and SSID + // that are not contained in the list of BSSIDs generated by this scan, the + // BSSID description of the currently associated BSSID and SSID should be + // appended to the list of BSSIDs in the NIC's database. + // To ensure this, we append this BSS as the first entry in SCAN result + NdisMoveMemory(&pAd->ScanTab.BssEntry[0], &CurrBss, sizeof(BSS_ENTRY)); + pAd->ScanTab.BssNr = 1; + } + + ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, + sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; +} + +/* + ========================================================================== + Description: + Before calling this routine, user desired SSID should already been + recorded in CommonCfg.Ssid[] + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlOidSsidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + PNDIS_802_11_SSID pOidSsid = (NDIS_802_11_SSID *)Elem->Msg; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + ULONG Now; + + // Step 1. record the desired user settings to MlmeAux + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength); + pAd->MlmeAux.SsidLen = (UCHAR)pOidSsid->SsidLength; + NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->MlmeAux.BssType = pAd->StaCfg.BssType; + + + // + // Update Reconnect Ssid, that user desired to connect. + // + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; + + // step 2. find all matching BSS in the lastest SCAN result (inBssTab) + // & log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order + BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire (%d)SSID - %s\n", + pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid)); + NdisGetSystemUpTime(&Now); + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + (pAd->CommonCfg.SsidLen == pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen) && + NdisEqualMemory(pAd->CommonCfg.Ssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid, pAd->CommonCfg.SsidLen) && + MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid)) + { + // Case 1. already connected with an AP who has the desired SSID + // with highest RSSI + + // Add checking Mode "LEAP" for CCX 1.0 + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef LEAP_SUPPORT + || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + // case 1.1 For WPA, WPA-PSK, if the 1x port is not secured, we have to redo + // connection process + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } + else if (pAd->bConfigChanged == TRUE) + { + // case 1.2 Important Config has changed, we have to reconnect to the same AP + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } + else + { + // case 1.3. already connected to the SSID with highest RSSI. + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n")); + // + // (HCT 12.1) 1c_wlan_mediaevents required + // media connect events are indicated when associating with the same AP + // + if (INFRA_ON(pAd)) + { + // + // Since MediaState already is NdisMediaStateConnected + // We just indicate the connect event again to meet the WHQL required. + // + pAd->IndicateMediaState = NdisMediaStateConnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up + } + + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + } + } + else if (INFRA_ON(pAd)) + { + // + // For RT61 + // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) + // RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect + // But media status is connected, so the SSID not report correctly. + // + if (!SSID_EQUAL(pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen)) + { + // + // Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event. + // + pAd->MlmeAux.CurrReqIsFromNdis = TRUE; + } + // case 2. active INFRA association existent + // roaming is done within miniport driver, nothing to do with configuration + // utility. so upon a new SET(OID_802_11_SSID) is received, we just + // disassociate with the current associated AP, + // then perform a new association with this new SSID, no matter the + // new/old SSID are the same or not. + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } + else + { + if (ADHOC_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - drop current ADHOC\n")); + LinkDown(pAd, FALSE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); + } + + if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) && + (pAd->StaCfg.bAutoReconnect == TRUE) && + (pAd->MlmeAux.BssType == BSS_INFRA) && + (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen) == TRUE) + ) + { + MLME_SCAN_REQ_STRUCT ScanReq; + + DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n")); + ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; + // Reset Missed scan number + pAd->StaCfg.LastScanTime = Now; + } + else + { + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); + } + } +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlOidRTBssidProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + ULONG BssIdx; + PUCHAR pOidBssid = (PUCHAR)Elem->Msg; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + MLME_JOIN_REQ_STRUCT JoinReq; + +#ifdef RALINK_ATE +/* No need to perform this routine when ATE is running. */ + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + // record user desired settings + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pOidBssid); + pAd->MlmeAux.BssType = pAd->StaCfg.BssType; + + // + // Update Reconnect Ssid, that user desired to connect. + // + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + + // find the desired BSS in the latest SCAN result table + BssIdx = BssTableSearch(&pAd->ScanTab, pOidBssid, pAd->MlmeAux.Channel); + if (BssIdx == BSS_NOT_FOUND) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + return; + } + + // copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why? + // Because we need this entry to become the JOIN target in later on SYNC state machine + pAd->MlmeAux.BssIdx = 0; + pAd->MlmeAux.SsidBssTab.BssNr = 1; + NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY)); + + //pAd->MlmeAux.AutoReconnectSsidLen = pAd->ScanTab.BssEntry[BssIdx].SsidLen; + //NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->ScanTab.BssEntry[BssIdx].Ssid, pAd->ScanTab.BssEntry[BssIdx].SsidLen); + + // Add SSID into MlmeAux for site surey joining hidden SSID + //pAd->MlmeAux.SsidLen = pAd->ScanTab.BssEntry[BssIdx].SsidLen; + //NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->ScanTab.BssEntry[BssIdx].Ssid, pAd->MlmeAux.SsidLen); + + // 2002-11-26 skip the following checking. i.e. if user wants to re-connect to same AP + // we just follow normal procedure. The reason of user doing this may because he/she changed + // AP to another channel, but we still received BEACON from it thus don't claim Link Down. + // Since user knows he's changed AP channel, he'll re-connect again. By skipping the following + // checking, we'll disassociate then re-do normal association with this AP at the new channel. + // 2003-1-6 Re-enable this feature based on microsoft requirement which prefer not to re-do + // connection when setting the same BSSID. + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && + MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pOidBssid)) + { + // already connected to the same BSSID, go back to idle state directly + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - already in this BSSID. ignore this SET_BSSID request\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + } + else + { + if (INFRA_ON(pAd)) + { + // disassoc from current AP first + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - disassociate with current AP ...\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + } + else + { + if (ADHOC_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - drop current ADHOC\n")); + LinkDown(pAd, FALSE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n")); + } + + // Change the wepstatus to original wepstatus + pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus; + + // Check cipher suite, AP must have more secured cipher than station setting + // Set the Pairwise and Group cipher to match the intended AP setting + // We can only connect to AP with less secured cipher setting + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.GroupCipher; + + if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher) + pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher; + else if (pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux; + else // There is no PairCipher Aux, downgrade our capability to TKIP + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.GroupCipher; + + if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher) + pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher; + else if (pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux; + else // There is no PairCipher Aux, downgrade our capability to TKIP + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + + // RSN capability + pAd->StaCfg.RsnCapability = pAd->ScanTab.BssEntry[BssIdx].WPA2.RsnCapability; + } + + // Set Mix cipher flag + pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; + if (pAd->StaCfg.bMixCipher == TRUE) + { + // If mix cipher, re-build RSNIE + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); + } + // No active association, join the BSS immediately + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n", + pOidBssid[0],pOidBssid[1],pOidBssid[2],pOidBssid[3],pOidBssid[4],pOidBssid[5])); + + JoinParmFill(pAd, &JoinReq, pAd->MlmeAux.BssIdx); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), &JoinReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; + } + } +} + +// Roaming is the only external request triggering CNTL state machine +// despite of other "SET OID" operation. All "SET OID" related oerations +// happen in sequence, because no other SET OID will be sent to this device +// until the the previous SET operation is complete (successful o failed). +// So, how do we quarantee this ROAMING request won't corrupt other "SET OID"? +// or been corrupted by other "SET OID"? +// +// IRQL = DISPATCH_LEVEL +VOID CntlMlmeRoamingProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + // TODO: + // AP in different channel may show lower RSSI than actual value?? + // should we add a weighting factor to compensate it? + DBGPRINT(RT_DEBUG_TRACE,("CNTL - Roaming in MlmeAux.RoamTab...\n")); + + NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab, sizeof(pAd->MlmeAux.RoamTab)); + pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr; + + BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab); + pAd->MlmeAux.BssIdx = 0; + IterateOnBssTab(pAd); +} + +#ifdef QOS_DLS_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlOidDLSSetupProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PRT_802_11_DLS pDLS = (PRT_802_11_DLS)Elem->Msg; + MLME_DLS_REQ_STRUCT MlmeDlsReq; + INT i; + USHORT reason = REASON_UNSPECIFY; + + DBGPRINT(RT_DEBUG_TRACE,("CNTL - (OID set %02x:%02x:%02x:%02x:%02x:%02x with Valid=%d, Status=%d, TimeOut=%d, CountDownTimer=%d)\n", + pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5], + pDLS->Valid, pDLS->Status, pDLS->TimeOut, pDLS->CountDownTimer)); + + if (!pAd->CommonCfg.bDLSCapable) + return; + + // DLS will not be supported when Adhoc mode + if (INFRA_ON(pAd)) + { + for (i = 0; i < MAX_NUM_OF_DLS_ENTRY; i++) + { + if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && + (pDLS->TimeOut == pAd->StaCfg.DLSEntry[i].TimeOut) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + // 1. Same setting, just drop it + DBGPRINT(RT_DEBUG_TRACE,("CNTL - setting unchanged\n")); + break; + } + else if (!pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && + MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + // 2. Disable DLS link case, just tear down DLS link + reason = REASON_QOS_UNWANTED_MECHANISM; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - start tear down procedure\n")); + break; + } + else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && !pAd->StaCfg.DLSEntry[i].Valid) + { + // 3. Enable case, start DLS setup procedure + NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI)); + + //Update countdown timer + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS setup case\n")); + break; + } + else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && + (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && !MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + // 4. update mac case, tear down old DLS and setup new DLS + reason = REASON_QOS_UNWANTED_MECHANISM; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI)); + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS tear down and restart case\n")); + break; + } + else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && + MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr) && (pAd->StaCfg.DLSEntry[i].TimeOut != pDLS->TimeOut)) + { + // 5. update timeout case, start DLS setup procedure (no tear down) + pAd->StaCfg.DLSEntry[i].TimeOut = pDLS->TimeOut; + //Update countdown timer + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS update timeout case\n")); + break; + } + else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && + (pAd->StaCfg.DLSEntry[i].Status != DLS_FINISH) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + // 6. re-setup case, start DLS setup procedure (no tear down) + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS retry setup procedure\n")); + break; + } + else + { + DBGPRINT(RT_DEBUG_WARN,("CNTL - DLS not changed in entry - %d - Valid=%d, Status=%d, TimeOut=%d\n", + i, pAd->StaCfg.DLSEntry[i].Valid, pAd->StaCfg.DLSEntry[i].Status, pAd->StaCfg.DLSEntry[i].TimeOut)); + } + } + } +} +#endif // QOS_DLS_SUPPORT // + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitDisassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_START_REQ_STRUCT StartReq; + + if (Elem->MsgType == MT2_DISASSOC_CONF) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Dis-associate successful\n")); + + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + + LinkDown(pAd, FALSE); + + // case 1. no matching BSS, and user wants ADHOC, so we just start a new one + if ((pAd->MlmeAux.SsidBssTab.BssNr==0) && (pAd->StaCfg.BssType == BSS_ADHOC)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid)); + StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + // case 2. try each matched BSS + else + { + pAd->MlmeAux.BssIdx = 0; + + IterateOnBssTab(pAd); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitJoinProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + MLME_AUTH_REQ_STRUCT AuthReq; + + if (Elem->MsgType == MT2_JOIN_CONF) + { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); + if (Reason == MLME_SUCCESS) + { + // 1. joined an IBSS, we are pretty much done here + if (pAd->MlmeAux.BssType == BSS_ADHOC) + { + // + // 5G bands rules of Japan: + // Ad hoc must be disabled in W53(ch52,56,60,64) channels. + // + if ( (pAd->CommonCfg.bIEEE80211H == 1) && + RadarChannelCheck(pAd, pAd->CommonCfg.Channel) + ) + { + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel)); + return; + } + + LinkUp(pAd, BSS_ADHOC); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", + pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5])); + + pAd->IndicateMediaState = NdisMediaStateConnected; + pAd->ExtraInfo = GENERAL_LINK_UP; + } + // 2. joined a new INFRA network, start from authentication + else + { +#ifdef LEAP_SUPPORT + // Add AuthMode "LEAP" for CCX 1.X + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, CISCO_AuthModeLEAP); + } + else +#endif // LEAP_SUPPORT // + { + // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch)) + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared); + } + else + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); + } + } + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH; + } + } + else + { + // 3. failed, try next BSS + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + } +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitStartProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Result; + + if (Elem->MsgType == MT2_START_CONF) + { + NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT)); + if (Result == MLME_SUCCESS) + { + // + // 5G bands rules of Japan: + // Ad hoc must be disabled in W53(ch52,56,60,64) channels. + // + if ( (pAd->CommonCfg.bIEEE80211H == 1) && + RadarChannelCheck(pAd, pAd->CommonCfg.Channel) + ) + { + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel)); + return; + } +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + N_ChannelCheck(pAd); + SetCommonHT(pAd); + NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &pAd->CommonCfg.AddHTInfo, sizeof(ADD_HT_INFO_IE)); + RTMPCheckHt(pAd, BSSID_WCID, &pAd->CommonCfg.HtCapability, &pAd->CommonCfg.AddHTInfo); + pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; + NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16); + NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], &pAd->CommonCfg.HtCapability.MCSSet[0], 16); + COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); + + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE)) + { + pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel + 2; + } + else if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW)) + { + pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel - 2; + } + } + else +#endif // DOT11_N_SUPPORT // + { + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + } + LinkUp(pAd, BSS_ADHOC); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + // Before send beacon, driver need do radar detection + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + pAd->CommonCfg.RadarDetect.RDMode = RD_SILENCE_MODE; + pAd->CommonCfg.RadarDetect.RDCount = 0; +#ifdef DFS_SUPPORT + BbpRadarDetectionStart(pAd); +#endif // DFS_SUPPORT // + } + + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n", + pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5])); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Start IBSS fail. BUG!!!!!\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitAuthProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + MLME_ASSOC_REQ_STRUCT AssocReq; + MLME_AUTH_REQ_STRUCT AuthReq; + + if (Elem->MsgType == MT2_AUTH_CONF) + { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); + if (Reason == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); + AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); + +#ifdef LEAP_SUPPORT + // + // Cisco Leap CCKM supported Re-association. + // + if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE)) + { + //if CCKM is turn on , that's mean Fast Reauthentication + //Use CCKM Reassociation instead of normal association for Fast Roaming. + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; + } + else +#endif // LEAP_SUPPORT // + { + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; + } + } + else + { + // This fail may because of the AP already keep us in its MAC table without + // ageing-out. The previous authentication attempt must have let it remove us. + // so try Authentication again may help. For D-Link DWL-900AP+ compatibility. + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try again...\n")); +#ifdef LEAP_SUPPORT + //Add AuthMode "LEAP" for CCX 1.X + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, CISCO_AuthModeLEAP); + } + else +#endif // LEAP_SUPPORT // + { + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch)) + { + // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared); + } + else + { + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); + } + } + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitAuthProc2( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + MLME_ASSOC_REQ_STRUCT AssocReq; + MLME_AUTH_REQ_STRUCT AuthReq; + + if (Elem->MsgType == MT2_AUTH_CONF) + { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); + if (Reason == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n")); + AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC; + } + else + { +#ifdef LEAP_SUPPORT + // Process LEAP first, since it use different control variable + // We don't want to affect other poven operation + if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) + { + // LEAP Auth not success, try next BSS + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - *LEAP* AUTH FAIL, give up; try next BSS\n")); + DBGPRINT(RT_DEBUG_TRACE, ("Total match BSSID [=%d]\n", pAd->MlmeAux.SsidBssTab.BssNr)); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + else +#endif // LEAP_SUPPORT // + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch) && + (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared)) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try OPEN system...\n")); + AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen); + MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2; + } + else + { + // not success, try next BSS + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, give up; try next BSS\n")); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; //??????? + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitAssocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Reason; + + if (Elem->MsgType == MT2_ASSOC_CONF) + { + NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT)); + if (Reason == MLME_SUCCESS) + { + LinkUp(pAd, BSS_INFRA); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association successful on BSS #%ld\n",pAd->MlmeAux.BssIdx)); + + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + } + else + { + // not success, try next BSS + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association fails on BSS #%ld\n",pAd->MlmeAux.BssIdx)); + pAd->MlmeAux.BssIdx++; + IterateOnBssTab(pAd); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID CntlWaitReassocProc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Result; + + if (Elem->MsgType == MT2_REASSOC_CONF) + { + NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT)); + if (Result == MLME_SUCCESS) + { + // + // NDIS requires a new Link UP indication but no Link Down for RE-ASSOC + // + LinkUp(pAd, BSS_INFRA); + + // send wireless event - for association + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + +#ifdef LEAP_SUPPORT + if (LEAP_CCKM_ON(pAd)) + { + STA_PORT_SECURED(pAd); + pAd->StaCfg.WpaState = SS_FINISH; + } +#endif // LEAP_SUPPORT // + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition successful on BSS #%ld\n", pAd->MlmeAux.RoamIdx)); + } + else + { + // reassoc failed, try to pick next BSS in the BSS Table + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition fails on BSS #%ld\n", pAd->MlmeAux.RoamIdx)); + pAd->MlmeAux.RoamIdx++; + IterateOnBssTab2(pAd); + } + } +} + + +VOID AdhocTurnOnQos( + IN PRTMP_ADAPTER pAd) +{ +#define AC0_DEF_TXOP 0 +#define AC1_DEF_TXOP 0 +#define AC2_DEF_TXOP 94 +#define AC3_DEF_TXOP 47 + + // Turn on QOs if use HT rate. + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) + { + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; + pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; + pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; + pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; + + pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; + pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; + + pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10; + pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6; + pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; + pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; + + pAd->CommonCfg.APEdcaParm.Txop[0] = 0; + pAd->CommonCfg.APEdcaParm.Txop[1] = 0; + pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP; + pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP; + } + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID LinkUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssType) +{ + ULONG Now; + UINT32 Data; + BOOLEAN Cancelled; + UCHAR Value = 0, idx; + MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + // + // ASSOC - DisassocTimeoutAction + // CNTL - Dis-associate successful + // !!! LINK DOWN !!! + // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: ) + // + // To prevent DisassocTimeoutAction to call Link down after we link up, + // cancel the DisassocTimer no matter what it start or not. + // + RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled); + + COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); + +#ifdef DOT11_N_SUPPORT + COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd); +#endif // DOT11_N_SUPPORT // + // It's quite difficult to tell if a newly added KEY is WEP or CKIP until a new BSS + // is formed (either ASSOC/RE-ASSOC done or IBSS started. LinkUP should be a safe place + // to examine if cipher algorithm switching is required. + //rt2860b. Don't know why need this + SwitchBetweenWepAndCkip(pAd); + + + if (BssType == BSS_ADHOC) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE)) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + } + else if ((pAd->CommonCfg.Channel > 2) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW)) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + } +#endif // DOT11_N_SUPPORT // + +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + // No carrier detection when adhoc + // CarrierDetectionStop(pAd); + pAd->CommonCfg.CarrierDetect.CD_State = CD_NORMAL; +#endif // CARRIER_DETECTION_SUPPORT // + +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + AdhocTurnOnQos(pAd); +#endif // DOT11_N_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("!!!Adhoc LINK UP !!! \n" )); + } + else + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_INFRA_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + + DBGPRINT(RT_DEBUG_TRACE, ("!!!Infra LINK UP !!! \n" )); + } + + // 3*3 + // reset Tx beamforming bit + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x01); + Value |= pAd->CommonCfg.RegTransmitSetting.field.TxBF; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + +#ifdef DOT11_N_SUPPORT + // Change to AP channel + if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + // RX : control channel at lower + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel )); + } + else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + // Must using 40MHz. + pAd->CommonCfg.BBPCurrentBW = BW_40; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + Value |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data |= 0x1; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!! 40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel )); + } + else +#endif // DOT11_N_SUPPORT // + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value); + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data); + Data &= 0xfffffffe; + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value); + Value &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value); + + if (pAd->MACVersion == 0x28600100) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11); + DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" )); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!! 20MHz LINK UP !!! \n" )); + } + + RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW); + // + // Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission + // + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue); + + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n", + BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (Density =%d, )\n", pAd->MacTab.Content[BSSID_WCID].MpduDensity)); +#endif // DOT11_N_SUPPORT // + + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); + + AsicSetSlotTime(pAd, TRUE); + AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); + + // Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, but normally it will not hit + AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE, FALSE); + +#ifdef DOT11_N_SUPPORT + if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE)) + { + // Update HT protectionfor based on AP's operating mode. + if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); + } + else + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); + } +#endif // DOT11_N_SUPPORT // + + NdisZeroMemory(&pAd->DrsCounters, sizeof(COUNTER_DRS)); + + NdisGetSystemUpTime(&Now); + pAd->StaCfg.LastBeaconRxTime = Now; // last RX timestamp + + if ((pAd->CommonCfg.TxPreamble != Rt802_11PreambleLong) && + CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo)) + { + MlmeSetTxPreamble(pAd, Rt802_11PreambleShort); + } + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + + if (pAd->CommonCfg.RadarDetect.RDMode == RD_SILENCE_MODE) + { +#ifdef DFS_SUPPORT + RadarDetectionStop(pAd); +#endif // DFS_SUPPORT // + } + pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE; + + if (BssType == BSS_ADHOC) + { + MakeIbssBeacon(pAd); + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + ; //Do nothing + } + else + { + AsicEnableIbssSync(pAd); + } + + // In ad hoc mode, use MAC table from index 1. + // p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. + RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); + RTMP_IO_WRITE32(pAd, 0x1808, 0x00); + + // If WEP is enabled, add key material and cipherAlg into Asic + // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) + + if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) + { + PUCHAR Key; + UCHAR CipherAlg; + + for (idx=0; idx < SHARE_KEY_NUM; idx++) + { + CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; + Key = pAd->SharedKey[BSS0][idx].Key; + + if (pAd->SharedKey[BSS0][idx].KeyLen > 0) + { + // Set key material and cipherAlg to Asic + AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); + + if (idx == pAd->StaCfg.DefaultKeyId) + { + // Update WCID attribute table and IVEIV table for this group key table + RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); + } + } + + + } + } + // If WPANone is enabled, add key material and cipherAlg into Asic + // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000) + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + pAd->StaCfg.DefaultKeyId = 0; // always be zero + + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TKIP_EK); + + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_TXMICK); + } + + // Decide its ChiperAlg + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Unknow Cipher (=%d), set Cipher to AES\n", pAd->StaCfg.PairCipher)); + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + } + + // Set key material and cipherAlg to Asic + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + // Update WCID attribute table and IVEIV table for this group key table + RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pAd->SharedKey[BSS0][0].CipherAlg, NULL); + + } + + } + else // BSS_INFRA + { + // Check the new SSID with last SSID + while (Cancelled == TRUE) + { + if (pAd->CommonCfg.LastSsidLen == pAd->CommonCfg.SsidLen) + { + if (RTMPCompareMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen) == 0) + { + // Link to the old one no linkdown is required. + break; + } + } + // Send link down event before set to link up + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n")); + break; + } + + // + // On WPA mode, Remove All Keys if not connect to the last BSSID + // Key will be set after 4-way handshake. + // + if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) + { + ULONG IV; + + // Remove all WPA keys + RTMPWPARemoveAllKeys(pAd); + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + + // Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP + // If IV related values are too large in GroupMsg2, AP would ignore this message. + IV = 0; + IV |= (pAd->StaCfg.DefaultKeyId << 30); + AsicUpdateWCIDIVEIV(pAd, BSSID_WCID, IV, 0); + } + // NOTE: + // the decision of using "short slot time" or not may change dynamically due to + // new STA association to the AP. so we have to decide that upon parsing BEACON, not here + + // NOTE: + // the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically + // due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here + + ComposePsPoll(pAd); + ComposeNullFrame(pAd); + + AsicEnableBssSync(pAd); + + // Add BSSID to WCID search table + AsicUpdateRxWCIDTable(pAd, BSSID_WCID, pAd->CommonCfg.Bssid); + + NdisAcquireSpinLock(&pAd->MacTabLock); + // add this BSSID entry into HASH table + { + UCHAR HashIdx; + + //pEntry = &pAd->MacTab.Content[BSSID_WCID]; + HashIdx = MAC_ADDR_HASH_INDEX(pAd->CommonCfg.Bssid); + if (pAd->MacTab.Hash[HashIdx] == NULL) + { + pAd->MacTab.Hash[HashIdx] = pEntry; + } + else + { + pCurrEntry = pAd->MacTab.Hash[HashIdx]; + while (pCurrEntry->pNext != NULL) + pCurrEntry = pCurrEntry->pNext; + pCurrEntry->pNext = pEntry; + } + } + NdisReleaseSpinLock(&pAd->MacTabLock); + + + // If WEP is enabled, add paiewise and shared key +#ifdef WPA_SUPPLICANT_SUPPORT + if (((pAd->StaCfg.WpaSupplicantUP)&& + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)&& + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) || + ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)&& + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled))) +#else + if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) +#endif // WPA_SUPPLICANT_SUPPORT // + { + PUCHAR Key; + UCHAR CipherAlg; + + for (idx=0; idx < SHARE_KEY_NUM; idx++) + { + CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg; + Key = pAd->SharedKey[BSS0][idx].Key; + + if (pAd->SharedKey[BSS0][idx].KeyLen > 0) + { + // Set key material and cipherAlg to Asic + AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); + + if (idx == pAd->StaCfg.DefaultKeyId) + { + // Assign group key info + RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); + + // Assign pairwise key info + RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry); + } + } + } + } + + // only INFRASTRUCTURE mode need to indicate connectivity immediately; ADHOC mode + // should wait until at least 2 active nodes in this BSSID. + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + + // For GUI ++ + if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + { + pAd->IndicateMediaState = NdisMediaStateConnected; + pAd->ExtraInfo = GENERAL_LINK_UP; + RTMP_IndicateMediaState(pAd); + } + // -- + + // Add BSSID in my MAC Table. + NdisAcquireSpinLock(&pAd->MacTabLock); + RTMPMoveMemory(pAd->MacTab.Content[BSSID_WCID].Addr, pAd->CommonCfg.Bssid, MAC_ADDR_LEN); + pAd->MacTab.Content[BSSID_WCID].Aid = BSSID_WCID; + pAd->MacTab.Content[BSSID_WCID].pAd = pAd; + pAd->MacTab.Content[BSSID_WCID].ValidAsCLI = TRUE; //Although this is bssid..still set ValidAsCl + pAd->MacTab.Size = 1; // infra mode always set MACtab size =1. + pAd->MacTab.Content[BSSID_WCID].Sst = SST_ASSOC; + pAd->MacTab.Content[BSSID_WCID].AuthState = SST_ASSOC; + pAd->MacTab.Content[BSSID_WCID].AuthMode = pAd->StaCfg.AuthMode; + pAd->MacTab.Content[BSSID_WCID].WepStatus = pAd->StaCfg.WepStatus; + NdisReleaseSpinLock(&pAd->MacTabLock); + + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! ClientStatusFlags=%lx)\n", + pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); + + MlmeUpdateTxRates(pAd, TRUE, BSS0); +#ifdef DOT11_N_SUPPORT + MlmeUpdateHtTxRates(pAd, BSS0); + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !! (StaActive.bHtEnable =%d, )\n", pAd->StaActive.SupportedPhyInfo.bHtEnable)); +#endif // DOT11_N_SUPPORT // + + // + // Report Adjacent AP report. + // +#ifdef LEAP_SUPPORT + CCXAdjacentAPReport(pAd); +#endif // LEAP_SUPPORT // + + if (pAd->CommonCfg.bAggregationCapable) + { + if ((pAd->CommonCfg.bPiggyBackCapable) && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3) + { + + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + RTMPSetPiggyBack(pAd, TRUE); + DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n")); + } + else if (pAd->MlmeAux.APRalinkIe & 0x00000001) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + } + } + + if (pAd->MlmeAux.APRalinkIe != 0x0) + { +#ifdef DOT11_N_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RDG_CAPABLE)) + { + AsicEnableRDG(pAd); + } +#endif // DOT11_N_SUPPORT // + OPSTATUS_SET_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); + CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET); + } + else + { + OPSTATUS_CLEAR_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET); + CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET); + } + } + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n", pAd->CommonCfg.BACapability.word, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags)); +#endif // DOT11_N_SUPPORT // + + // Set LED + RTMPSetLED(pAd, LED_LINK_UP); + + pAd->Mlme.PeriodicRound = 0; + pAd->Mlme.OneSecPeriodicRound = 0; + pAd->bConfigChanged = FALSE; // Reset config flag + pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up + + // Set asic auto fall back + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, &pAd->MacTab.Content[BSSID_WCID], &pTable, &TableSize, &pAd->CommonCfg.TxRateIndex); + AsicUpdateAutoFallBackTable(pAd, pTable); + } + + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word; + pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word; + if (pAd->StaCfg.bAutoTxRateSwitch == FALSE) + { + pEntry->bAutoTxRateSwitch = FALSE; +#ifdef DOT11_N_SUPPORT + if (pEntry->HTPhyMode.field.MCS == 32) + pEntry->HTPhyMode.field.ShortGI = GI_800; + + if ((pEntry->HTPhyMode.field.MCS > MCS_7) || (pEntry->HTPhyMode.field.MCS == 32)) + pEntry->HTPhyMode.field.STBC = STBC_NONE; +#endif // DOT11_N_SUPPORT // + // If the legacy mode is set, overwrite the transmit setting of this entry. + if (pEntry->HTPhyMode.field.MODE <= MODE_OFDM) + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + else + pEntry->bAutoTxRateSwitch = TRUE; + NdisReleaseSpinLock(&pAd->MacTabLock); + + // Let Link Status Page display first initial rate. + pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); + // Select DAC according to HT or Legacy + if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); + Value &= (~0x18); + if (pAd->Antenna.field.TxPath == 2) + { + Value |= 0x10; + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); + } + else + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value); + Value &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value); + } + +#ifdef DOT11_N_SUPPORT + if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) + { + } + else if (pEntry->MaxRAmpduFactor == 0) + { + // If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0. + // Because our Init value is 1 at MACRegTable. + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x0fff); + } +#endif // DOT11_N_SUPPORT // + + // Patch for Marvel AP to gain high throughput + // Need to set as following, + // 1. Set txop in register-EDCA_AC0_CFG as 0x60 + // 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero + // 3. PBF_MAX_PCNT as 0x1F3FBF9F + // 4. kick per two packets when dequeue + // + // Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable + // + // if 1. Legacy AP WMM on, or 2. 11n AP, AMPDU disable. Force turn off burst no matter what bEnableTxBurst is. +#ifdef DOT11_N_SUPPORT +// if ((!IS_RT30xx(pAd)) && + if (!((pAd->CommonCfg.RxStream == 1)&&(pAd->CommonCfg.TxStream == 1)) && + (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) + || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)))) + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); + DBGPRINT(RT_DEBUG_TRACE, ("Txburst 1\n")); + } + else +#endif // DOT11_N_SUPPORT // + if (pAd->CommonCfg.bEnableTxBurst) + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + Data |= 0x60; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = TRUE; + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F); + DBGPRINT(RT_DEBUG_TRACE, ("Txburst 2\n")); + } + else + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F); + DBGPRINT(RT_DEBUG_TRACE, ("Txburst 3\n")); + } + +#ifdef DOT11_N_SUPPORT + // Re-check to turn on TX burst or not. + if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE) && ((STA_WEP_ON(pAd))||(STA_TKIP_ON(pAd)))) + { + pAd->CommonCfg.IOTestParm.bNextDisableRxBA = TRUE; + if (pAd->CommonCfg.bEnableTxBurst) + { + UINT32 MACValue = 0; + // Force disable TXOP value in this case. The same action in MLMEUpdateProtect too. + // I didn't change PBF_MAX_PCNT setting. + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue); + MACValue &= 0xFFFFFF00; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue); + pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; + } + } + else + { + pAd->CommonCfg.IOTestParm.bNextDisableRxBA = FALSE; + } +#endif // DOT11_N_SUPPORT // + + pAd->CommonCfg.IOTestParm.bLastAtheros = FALSE; + COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); + DBGPRINT(RT_DEBUG_TRACE, ("!!!pAd->bNextDisableRxBA= %d \n", pAd->CommonCfg.IOTestParm.bNextDisableRxBA)); + // BSSID add in one MAC entry too. Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap + // Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver. + // Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same. + + if (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled) + { + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + + NdisAcquireSpinLock(&pAd->MacTabLock); + pEntry->PortSecured = pAd->StaCfg.PortSecured; + NdisReleaseSpinLock(&pAd->MacTabLock); + + // + // Patch Atheros AP TX will breakdown issue. + // AP Model: DLink DWL-8200AP + // + if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && STA_TKIP_ON(pAd)) + { + RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x01); + } + else + { + RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x00); + } + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if ((pAd->CommonCfg.BACapability.field.b2040CoexistScanSup) && (pAd->CommonCfg.Channel <= 11)) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SCAN_2040); + BuildEffectedChannelList(pAd); + } +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // +} + +/* + ========================================================================== + + Routine Description: + Disconnect current BSSID + + Arguments: + pAd - Pointer to our adapter + IsReqFromAP - Request from AP + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + We need more information to know it's this requst from AP. + If yes! we need to do extra handling, for example, remove the WPA key. + Otherwise on 4-way handshaking will faied, since the WPA key didn't be + remove while auto reconnect. + Disconnect request from AP, it means we will start afresh 4-way handshaking + on WPA mode. + + ========================================================================== +*/ +VOID LinkDown( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN IsReqFromAP) +{ + UCHAR i, ByteValue = 0; + + // Do nothing if monitor mode is on + if (MONITOR_ON(pAd)) + return; + +#ifdef RALINK_ATE + // Nothing to do in ATE mode. + if (ATE_ON(pAd)) + return; +#endif // RALINK_ATE // + + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN !!!\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED); + + if (ADHOC_ON(pAd)) // Adhoc mode link down + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 1!!!\n")); + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MacTab.Size=%d !!!\n", pAd->MacTab.Size)); + } + else // Infra structure mode + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 2!!!\n")); + +#ifdef QOS_DLS_SUPPORT + // DLS tear down frame must be sent before link down + // send DLS-TEAR_DOWN message + if (pAd->CommonCfg.bDLSCapable) + { + // tear down local dls table entry + for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + // tear down peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + } +#endif // QOS_DLS_SUPPORT // + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + + // Saved last SSID for linkup comparison + pAd->CommonCfg.LastSsidLen = pAd->CommonCfg.SsidLen; + NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen); + COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid); + if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE) + { + pAd->IndicateMediaState = NdisMediaStateDisconnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_DOWN; + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n")); + pAd->MlmeAux.CurrReqIsFromNdis = FALSE; + } + else + { + // + // If disassociation request is from NDIS, then we don't need to delete BSSID from entry. + // Otherwise lost beacon or receive De-Authentication from AP, + // then we should delete BSSID from BssTable. + // If we don't delete from entry, roaming will fail. + // + BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel); + } + + // restore back to - + // 1. long slot (20 us) or short slot (9 us) time + // 2. turn on/off RTS/CTS and/or CTS-to-self protection + // 3. short preamble + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + + if (pAd->StaCfg.CCXAdjacentAPReportFlag == TRUE) + { + // + // Record current AP's information. + // for later used reporting Adjacent AP report. + // + pAd->StaCfg.CCXAdjacentAPChannel = pAd->CommonCfg.Channel; + pAd->StaCfg.CCXAdjacentAPSsidLen = pAd->CommonCfg.SsidLen; + NdisMoveMemory(pAd->StaCfg.CCXAdjacentAPSsid, pAd->CommonCfg.Ssid, pAd->StaCfg.CCXAdjacentAPSsidLen); + COPY_MAC_ADDR(pAd->StaCfg.CCXAdjacentAPBssid, pAd->CommonCfg.Bssid); + } + +#ifdef EXT_BUILD_CHANNEL_LIST + // Country IE of the AP will be evaluated and will be used. + if (pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) + { + NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pAd->StaCfg.StaOriCountryCode[0], 2); + pAd->CommonCfg.Geography = pAd->StaCfg.StaOriGeography; + BuildChannelListEx(pAd); + } +#endif // EXT_BUILD_CHANNEL_LIST // + + } + + for (i=1; iMacTab.Content[i].ValidAsCLI == TRUE) + MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, pAd->MacTab.Content[i].Addr); + } + + pAd->StaCfg.CCXQosECWMin = 4; + pAd->StaCfg.CCXQosECWMax = 10; + + AsicSetSlotTime(pAd, TRUE); //FALSE); + AsicSetEdcaParm(pAd, NULL); + + // Set LED + RTMPSetLED(pAd, LED_LINK_DOWN); + pAd->LedIndicatorStregth = 0xF0; + RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it. + + AsicDisableSync(pAd); + + pAd->Mlme.PeriodicRound = 0; + pAd->Mlme.OneSecPeriodicRound = 0; + + if (pAd->StaCfg.BssType == BSS_INFRA) + { + // Remove StaCfg Information after link down + NdisZeroMemory(pAd->CommonCfg.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID); + pAd->CommonCfg.SsidLen = 0; + } +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE)); + NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof(ADD_HT_INFO_IE)); + pAd->MlmeAux.HtCapabilityLen = 0; + pAd->MlmeAux.NewExtChannelOffset = 0xff; +#endif // DOT11_N_SUPPORT // + + // Reset WPA-PSK state. Only reset when supplicant enabled + if (pAd->StaCfg.WpaState != SS_NOTUSE) + { + pAd->StaCfg.WpaState = SS_START; + // Clear Replay counter + NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); + +#ifdef QOS_DLS_SUPPORT + if (pAd->CommonCfg.bDLSCapable) + NdisZeroMemory(pAd->StaCfg.DlsReplayCounter, 8); +#endif // QOS_DLS_SUPPORT // + } + + + // + // if link down come from AP, we need to remove all WPA keys on WPA mode. + // otherwise will cause 4-way handshaking failed, since the WPA key not empty. + // + if ((IsReqFromAP) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) + { + // Remove all WPA keys + RTMPWPARemoveAllKeys(pAd); + } + + // 802.1x port control +#ifdef WPA_SUPPLICANT_SUPPORT + // Prevent clear PortSecured here with static WEP + // NetworkManger set security policy first then set SSID to connect AP. + if (pAd->StaCfg.WpaSupplicantUP && + (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) && + (pAd->StaCfg.IEEE8021X == FALSE)) + { + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + } + + NdisAcquireSpinLock(&pAd->MacTabLock); + pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.PortSecured; + NdisReleaseSpinLock(&pAd->MacTabLock); + + pAd->StaCfg.MicErrCnt = 0; + + // Turn off Ckip control flag + pAd->StaCfg.bCkipOn = FALSE; + pAd->StaCfg.CCXEnable = FALSE; + + pAd->IndicateMediaState = NdisMediaStateDisconnected; + // Update extra information to link is up + pAd->ExtraInfo = GENERAL_LINK_DOWN; + + //pAd->StaCfg.AdhocBOnlyJoined = FALSE; + //pAd->StaCfg.AdhocBGJoined = FALSE; + //pAd->StaCfg.Adhoc20NJoined = FALSE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + + // Reset the Current AP's IP address + NdisZeroMemory(pAd->StaCfg.AironetIPAddress, 4); +#ifdef RT2870 + pAd->bUsbTxBulkAggre = FALSE; +#endif // RT2870 // + + // Clean association information + NdisZeroMemory(&pAd->StaCfg.AssocInfo, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION)); + pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); + pAd->StaCfg.ReqVarIELen = 0; + pAd->StaCfg.ResVarIELen = 0; + + // + // Reset RSSI value after link down + // + pAd->StaCfg.RssiSample.AvgRssi0 = 0; + pAd->StaCfg.RssiSample.AvgRssi0X8 = 0; + pAd->StaCfg.RssiSample.AvgRssi1 = 0; + pAd->StaCfg.RssiSample.AvgRssi1X8 = 0; + pAd->StaCfg.RssiSample.AvgRssi2 = 0; + pAd->StaCfg.RssiSample.AvgRssi2X8 = 0; + + // Restore MlmeRate + pAd->CommonCfg.MlmeRate = pAd->CommonCfg.BasicMlmeRate; + pAd->CommonCfg.RtsRate = pAd->CommonCfg.BasicMlmeRate; + +#ifdef DOT11_N_SUPPORT + // + // After Link down, reset piggy-back setting in ASIC. Disable RDG. + // + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + pAd->CommonCfg.BBPCurrentBW = BW_20; + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &ByteValue); + ByteValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, ByteValue); + } +#endif // DOT11_N_SUPPORT // + // Reset DAC + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &ByteValue); + ByteValue &= (~0x18); + if (pAd->Antenna.field.TxPath == 2) + { + ByteValue |= 0x10; + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, ByteValue); + + RTMPSetPiggyBack(pAd,FALSE); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED); + +#ifdef DOT11_N_SUPPORT + pAd->CommonCfg.BACapability.word = pAd->CommonCfg.REGBACapability.word; +#endif // DOT11_N_SUPPORT // + + // Restore all settings in the following. + AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); + AsicDisableRDG(pAd); + pAd->CommonCfg.IOTestParm.bCurrentAtheros = FALSE; + pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE; + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SCAN_2040); + pAd->CommonCfg.BSSCoexist2040.word = 0; + TriEventInit(pAd); + for (i = 0; i < (pAd->ChannelListNum - 1); i++) + { + pAd->ChannelList[i].bEffectedChannel = FALSE; + } +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + +#ifdef WPA_SUPPLICANT_SUPPORT +#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) { + union iwreq_data wrqu; + //send disassociate event to wpa_supplicant + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.flags = RT_DISASSOC_EVENT_FLAG; + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT + { + union iwreq_data wrqu; + memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN); + wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL); + } +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + +#ifdef RT30xx + if (IS_RT3090(pAd)) + { + UINT32 macdata; + // disable MMPS BBP control register + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &ByteValue); + ByteValue &= ~(0x04); //bit 2 + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, ByteValue); + + // disable MMPS MAC control register + RTMP_IO_READ32(pAd, 0x1210, &macdata); + macdata &= ~(0x09); //bit 0, 3 + RTMP_IO_WRITE32(pAd, 0x1210, macdata); + } +#endif // RT30xx // + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID IterateOnBssTab( + IN PRTMP_ADAPTER pAd) +{ + MLME_START_REQ_STRUCT StartReq; + MLME_JOIN_REQ_STRUCT JoinReq; + ULONG BssIdx; + + // Change the wepstatus to original wepstatus + pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus; + pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus; + + BssIdx = pAd->MlmeAux.BssIdx; + if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr) + { + // Check cipher suite, AP must have more secured cipher than station setting + // Set the Pairwise and Group cipher to match the intended AP setting + // We can only connect to AP with less secured cipher setting + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.GroupCipher; + + if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher) + pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher; + else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux; + else // There is no PairCipher Aux, downgrade our capability to TKIP + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.GroupCipher; + + if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher) + pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher; + else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled) + pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux; + else // There is no PairCipher Aux, downgrade our capability to TKIP + pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + + // RSN capability + pAd->StaCfg.RsnCapability = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.RsnCapability; + } + + // Set Mix cipher flag + pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE; + if (pAd->StaCfg.bMixCipher == TRUE) + { + // If mix cipher, re-build RSNIE + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0); + } + + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.SsidBssTab.BssNr)); + JoinParmFill(pAd, &JoinReq, BssIdx); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), + &JoinReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN; + } + else if (pAd->StaCfg.BssType == BSS_ADHOC) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid)); + StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq); + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START; + } + else // no more BSS + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All roaming failed, stay @ ch #%d\n", pAd->CommonCfg.Channel)); + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } +} + +// for re-association only +// IRQL = DISPATCH_LEVEL +VOID IterateOnBssTab2( + IN PRTMP_ADAPTER pAd) +{ + MLME_REASSOC_REQ_STRUCT ReassocReq; + ULONG BssIdx; + BSS_ENTRY *pBss; + + BssIdx = pAd->MlmeAux.RoamIdx; + pBss = &pAd->MlmeAux.RoamTab.BssEntry[BssIdx]; + + if (BssIdx < pAd->MlmeAux.RoamTab.BssNr) + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.RoamTab.BssNr)); + + AsicSwitchChannel(pAd, pBss->Channel, FALSE); + AsicLockChannel(pAd, pBss->Channel); + + // reassociate message has the same structure as associate message + AssocParmFill(pAd, &ReassocReq, pBss->Bssid, pBss->CapabilityInfo, + ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ, + sizeof(MLME_REASSOC_REQ_STRUCT), &ReassocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC; + } + else // no more BSS + { + DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All fast roaming failed, back to ch #%d\n",pAd->CommonCfg.Channel)); + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID JoinParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, + IN ULONG BssIdx) +{ + JoinReq->BssIdx = BssIdx; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID ScanParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN UCHAR ScanType) +{ + NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID); + ScanReq->SsidLen = SsidLen; + NdisMoveMemory(ScanReq->Ssid, Ssid, SsidLen); + ScanReq->BssType = BssType; + ScanReq->ScanType = ScanType; +} + +#ifdef QOS_DLS_SUPPORT +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID DlsParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_DLS_REQ_STRUCT *pDlsReq, + IN PRT_802_11_DLS pDls, + IN USHORT reason) +{ + pDlsReq->pDLS = pDls; + pDlsReq->Reason = reason; +} +#endif // QOS_DLS_SUPPORT // + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID StartParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_START_REQ_STRUCT *StartReq, + IN CHAR Ssid[], + IN UCHAR SsidLen) +{ + ASSERT(SsidLen <= MAX_LEN_OF_SSID); + NdisMoveMemory(StartReq->Ssid, Ssid, SsidLen); + StartReq->SsidLen = SsidLen; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +VOID AuthParmFill( + IN PRTMP_ADAPTER pAd, + IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, + IN PUCHAR pAddr, + IN USHORT Alg) +{ + COPY_MAC_ADDR(AuthReq->Addr, pAddr); + AuthReq->Alg = Alg; + AuthReq->Timeout = AUTH_TIMEOUT; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ + + +#ifdef RT2870 + +VOID MlmeCntlConfirm( + IN PRTMP_ADAPTER pAd, + IN ULONG MsgType, + IN USHORT Msg) +{ + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MsgType, sizeof(USHORT), &Msg); +} + +VOID ComposePsPoll( + IN PRTMP_ADAPTER pAd) +{ + PTXINFO_STRUC pTxInfo; + PTXWI_STRUC pTxWI; + + DBGPRINT(RT_DEBUG_TRACE, ("ComposePsPoll\n")); + NdisZeroMemory(&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); + + pAd->PsPollFrame.FC.PwrMgmt = 0; + pAd->PsPollFrame.FC.Type = BTYPE_CNTL; + pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL; + pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000; + COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress); + + RTMPZeroMemory(&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[0], 100); + pTxInfo = (PTXINFO_STRUC)&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[0]; + RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(PSPOLL_FRAME)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + pTxWI = (PTXWI_STRUC)&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE]; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(PSPOLL_FRAME)), + 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + RTMPMoveMemory(&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[TXWI_SIZE+TXINFO_SIZE], &pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); + // Append 4 extra zero bytes. + pAd->PsPollContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(PSPOLL_FRAME) + 4; +} + +// IRQL = DISPATCH_LEVEL +VOID ComposeNullFrame( + IN PRTMP_ADAPTER pAd) +{ + PTXINFO_STRUC pTxInfo; + PTXWI_STRUC pTxWI; + + NdisZeroMemory(&pAd->NullFrame, sizeof(HEADER_802_11)); + pAd->NullFrame.FC.Type = BTYPE_DATA; + pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC; + pAd->NullFrame.FC.ToDs = 1; + COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid); + RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[0], 100); + pTxInfo = (PTXINFO_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[0]; + RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); + pTxWI = (PTXWI_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE]; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)), + 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit); + RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11)); + pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4; +} +#endif // RT2870 // + + +/* + ========================================================================== + Description: + Pre-build a BEACON frame in the shared memory + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== +*/ +ULONG MakeIbssBeacon( + IN PRTMP_ADAPTER pAd) +{ + UCHAR DsLen = 1, IbssLen = 2; + UCHAR LocalErpIe[3] = {IE_ERP, 1, 0x04}; + HEADER_802_11 BcnHdr; + USHORT CapabilityInfo; + LARGE_INTEGER FakeTimestamp; + ULONG FrameLen = 0; + PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; + CHAR *pBeaconFrame = pAd->BeaconBuf; + BOOLEAN Privacy; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen = 0; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen = 0; + UCHAR RSNIe = IE_WPA; + + if ((pAd->CommonCfg.PhyMode == PHY_11B) && (pAd->CommonCfg.Channel <= 14)) + { + SupRate[0] = 0x82; // 1 mbps + SupRate[1] = 0x84; // 2 mbps + SupRate[2] = 0x8b; // 5.5 mbps + SupRate[3] = 0x96; // 11 mbps + SupRateLen = 4; + ExtRateLen = 0; + } + else if (pAd->CommonCfg.Channel > 14) + { + SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate + SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps + SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate + SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps + SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate + SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps + SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps + SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps + SupRateLen = 8; + ExtRateLen = 0; + + // + // Also Update MlmeRate & RtsRate for G only & A only + // + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + else + { + SupRate[0] = 0x82; // 1 mbps + SupRate[1] = 0x84; // 2 mbps + SupRate[2] = 0x8b; // 5.5 mbps + SupRate[3] = 0x96; // 11 mbps + SupRateLen = 4; + + ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps, + ExtRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps + ExtRate[2] = 0x18; // 12 mbps, in units of 0.5 Mbps, + ExtRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps + ExtRate[4] = 0x30; // 24 mbps, in units of 0.5 Mbps, + ExtRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps + ExtRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps + ExtRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps + ExtRateLen = 8; + } + + pAd->StaActive.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->StaActive.SupRate, SupRate, SupRateLen); + pAd->StaActive.ExtRateLen = ExtRateLen; + NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, ExtRateLen); + + // compose IBSS beacon frame + MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->CommonCfg.Bssid); + Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); + + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof(HEADER_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &CapabilityInfo, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + 1, &IbssIe, + 1, &IbssLen, + 2, &pAd->StaActive.AtimWin, + END_OF_ARGS); + + // add ERP_IE and EXT_RAE IE of in 802.11g + if (ExtRateLen) + { + ULONG tmp; + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, + 3, LocalErpIe, + 1, &ExtRateIe, + 1, &ExtRateLen, + ExtRateLen, ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + + // If adhoc secruity is set for WPA-None, append the cipher suite IE + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + ULONG tmp; + RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0); + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + ULONG TmpLen; + UCHAR HtLen, HtLen1; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; + USHORT b2lTmp, b2lTmp2; +#endif + + // add HT Capability IE + HtLen = sizeof(pAd->CommonCfg.HtCapability); + HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, HtLen1); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + } +#endif // DOT11_N_SUPPORT // + + //beacon use reserved WCID 0xff + if (pAd->CommonCfg.Channel > 14) + { + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, + PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit); + } + else + { + // Set to use 1Mbps for Adhoc beacon. + HTTRANSMIT_SETTING Transmit; + Transmit.word = 0; + RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, + PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &Transmit); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, pBeaconFrame, DIR_WRITE, FALSE); + RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n", + FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel, pAd->CommonCfg.PhyMode)); + return FrameLen; +} + + diff --git a/drivers/staging/rt3070/sta/dls.c b/drivers/staging/rt3070/sta/dls.c new file mode 100644 index 000000000000..8bcd41329343 --- /dev/null +++ b/drivers/staging/rt3070/sta/dls.c @@ -0,0 +1,2170 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + dls.c + + Abstract: + Handle WMM-DLS state machine + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Rory Chen 02-14-2006 + Arvin Tai 06-03-2008 Modified for RT28xx + */ + +#include "../rt_config.h" + +/* + ========================================================================== + Description: + dls state machine init, including state transition and timer init + Parameters: + Sm - pointer to the dls state machine + Note: + The state machine looks like this + + DLS_IDLE + MT2_MLME_DLS_REQUEST MlmeDlsReqAction + MT2_PEER_DLS_REQUEST PeerDlsReqAction + MT2_PEER_DLS_RESPONSE PeerDlsRspAction + MT2_MLME_DLS_TEARDOWN MlmeTearDownAction + MT2_PEER_DLS_TEARDOWN PeerTearDownAction + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +void DlsStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; + + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, MAX_DLS_STATE, MAX_DLS_MSG, (STATE_MACHINE_FUNC)Drop, DLS_IDLE, DLS_MACHINE_BASE); + + // the first column + StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_REQ, (STATE_MACHINE_FUNC)MlmeDlsReqAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_REQ, (STATE_MACHINE_FUNC)PeerDlsReqAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_RSP, (STATE_MACHINE_FUNC)PeerDlsRspAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)MlmeDlsTearDownAction); + StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)PeerDlsTearDownAction); + + for (i=0; iStaCfg.DLSEntry[i].pAd = pAd; + RTMPInitTimer(pAd, &pAd->StaCfg.DLSEntry[i].Timer, GET_TIMER_FUNCTION(DlsTimeoutAction), pAd, FALSE); + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DlsReqHdr; + PRT_802_11_DLS pDLS = NULL; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_REQUEST; + ULONG tmp; + USHORT reason; + ULONG Timeout; + BOOLEAN TimerCancelled; + + if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &reason)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsReqAction() \n")); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsReqAction() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &DlsReqHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + // Build basic frame first + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsReqHdr, + 1, &Category, + 1, &Action, + 6, &pDLS->MacAddr, + 6, pAd->CurrentAddress, + 2, &pAd->StaActive.CapabilityInfo, + 2, &pDLS->TimeOut, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR HtLen; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + + // add HT Capability IE + HtLen = sizeof(HT_CAPABILITY_IE); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif + FrameLen = FrameLen + tmp; + } +#endif // DOT11_N_SUPPORT // + + RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); + Timeout = DLS_TIMEOUT; + RTMPSetTimer(&pDLS->Timer, Timeout); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDlsReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT StatusCode = MLME_SUCCESS; + HEADER_802_11 DlsRspHdr; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_RESPONSE; + ULONG tmp; + USHORT CapabilityInfo; + UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; + USHORT DLSTimeOut; + SHORT i; + ULONG Timeout; + BOOLEAN TimerCancelled; + PRT_802_11_DLS pDLS = NULL; + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR SupportedRatesLen; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR HtCapabilityLen; + HT_CAPABILITY_IE HtCapability; + + if (!PeerDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeOut, + &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability)) + return; + + // supported rates array may not be sorted. sort it and find the maximum rate + for (i = 0; i < SupportedRatesLen; i++) + { + if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f)) + MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f; + } + + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() allocate memory failed \n")); + return; + } + + if (!INFRA_ON(pAd)) + { + StatusCode = MLME_REQUEST_DECLINED; + } + else if (!pAd->CommonCfg.bWmmCapable) + { + StatusCode = MLME_DEST_STA_IS_NOT_A_QSTA; + } + else if (!pAd->CommonCfg.bDLSCapable) + { + StatusCode = MLME_REQUEST_DECLINED; + } + else + { + // find table to update parameters + for (i = (MAX_NUM_OF_DLS_ENTRY-1); i >= 0; i--) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + else + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + } + + pAd->StaCfg.DLSEntry[i].Sequence = 0; + pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut; + pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut; + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + pDLS = &pAd->StaCfg.DLSEntry[i]; + break; + } + } + + // can not find in table, create a new one + if (i < 0) + { + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() can not find same entry \n")); + for (i=(MAX_NUM_OF_DLS_ENTRY - 1); i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--) + { + if (!pAd->StaCfg.DLSEntry[i].Valid) + { + MAC_TABLE_ENTRY *pEntry; + UCHAR MaxSupportedRate = RATE_11; + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + } + else + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + } + + pAd->StaCfg.DLSEntry[i].Sequence = 0; + pAd->StaCfg.DLSEntry[i].Valid = TRUE; + pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut; + pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut; + NdisMoveMemory(pAd->StaCfg.DLSEntry[i].MacAddr, SA, MAC_ADDR_LEN); + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + pDLS = &pAd->StaCfg.DLSEntry[i]; + pEntry = MacTableInsertDlsEntry(pAd, SA, i); + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + } + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + + // If this Entry supports 802.11n, upgrade to HT rate. + if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; //k,bitmask; + CHAR ii; + + if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40)); + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + // find max fixed rate + for (ii=15; ii>=0; ii--) + { + j = ii/8; + bitmask = (1<<(ii-(j*8))); + if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = ii; + break; + } + if (ii==0) + break; + } + + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + + printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", + pAd->StaCfg.DesiredTransmitSetting.field.MCS); + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) + { + // Fix MCS as HT Duplicated Mode + pEntry->MaxHTPhyMode.field.BW = 1; + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pEntry->MaxHTPhyMode.field.STBC = 0; + pEntry->MaxHTPhyMode.field.ShortGI = 0; + pEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) + { + // STA supports fixed MCS + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + } + } + + pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (HtCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (HtCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (HtCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (HtCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (HtCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE)); + } +#endif // DOT11_N_SUPPORT // + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + break; + } + } + } + StatusCode = MLME_SUCCESS; + + // can not find in table, create a new one + if (i < 0) + { + StatusCode = MLME_QOS_UNSPECIFY; + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() DLSEntry table full(only can support %d DLS session) \n", MAX_NUM_OF_DLS_ENTRY - MAX_NUM_OF_INIT_DLS_ENTRY)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() use entry(%d) %02x:%02x:%02x:%02x:%02x:%02x\n", + i, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + } + } + + ActHeaderInit(pAd, &DlsRspHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + // Build basic frame first + if (StatusCode == MLME_SUCCESS) + { + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsRspHdr, + 1, &Category, + 1, &Action, + 2, &StatusCode, + 6, SA, + 6, pAd->CurrentAddress, + 2, &pAd->StaActive.CapabilityInfo, + 1, &SupRateIe, + 1, &pAd->MlmeAux.SupRateLen, + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate, + END_OF_ARGS); + + if (pAd->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pAd->MlmeAux.ExtRateLen, + pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR HtLen; + +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + + // add HT Capability IE + HtLen = sizeof(HT_CAPABILITY_IE); +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif + FrameLen = FrameLen + tmp; + } +#endif // DOT11_N_SUPPORT // + + if (pDLS && (pDLS->Status != DLS_FINISH)) + { + RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); + Timeout = DLS_TIMEOUT; + RTMPSetTimer(&pDLS->Timer, Timeout); + } + } + else + { + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsRspHdr, + 1, &Category, + 1, &Action, + 2, &StatusCode, + 6, SA, + 6, pAd->CurrentAddress, + END_OF_ARGS); + } + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDlsRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT CapabilityInfo; + UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; + USHORT StatusCode; + SHORT i; + BOOLEAN TimerCancelled; + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR SupportedRatesLen; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR HtCapabilityLen; + HT_CAPABILITY_IE HtCapability; + + if (!pAd->CommonCfg.bDLSCapable) + return; + + if (!INFRA_ON(pAd)) + return; + + if (!PeerDlsRspSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode, + &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability)) + return; + + // supported rates array may not be sorted. sort it and find the maximum rate + for (i=0; iStaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (StatusCode == MLME_SUCCESS) + { + MAC_TABLE_ENTRY *pEntry; + UCHAR MaxSupportedRate = RATE_11; + + pEntry = MacTableInsertDlsEntry(pAd, SA, i); + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + } + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + + // If this Entry supports 802.11n, upgrade to HT rate. + if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; //k,bitmask; + CHAR ii; + + if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40)); + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + // find max fixed rate + for (ii=15; ii>=0; ii--) + { + j = ii/8; + bitmask = (1<<(ii-(j*8))); + if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = ii; + break; + } + if (ii==0) + break; + } + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) + { + // Fix MCS as HT Duplicated Mode + pEntry->MaxHTPhyMode.field.BW = 1; + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pEntry->MaxHTPhyMode.field.STBC = 0; + pEntry->MaxHTPhyMode.field.ShortGI = 0; + pEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) + { + // STA supports fixed MCS + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + } + } + + pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (HtCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (HtCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (HtCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (HtCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (HtCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE)); + } +#endif // DOT11_N_SUPPORT // + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + // If support WPA or WPA2, start STAKey hand shake, + // If failed hand shake, just tear down peer DLS + if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS) + { + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; + + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n")); + } + else + { + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n")); + } + } + else + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + } + + //initialize seq no for DLS frames. + pAd->StaCfg.DLSEntry[i].Sequence = 0; + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + } + else + { + // DLS setup procedure failed. + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode)); + } + } + } + + if (i >= MAX_NUM_OF_INIT_DLS_ENTRY) + { + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() update timeout value \n")); + for (i=(MAX_NUM_OF_DLS_ENTRY-1); i>=MAX_NUM_OF_INIT_DLS_ENTRY; i--) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (StatusCode == MLME_SUCCESS) + { + MAC_TABLE_ENTRY *pEntry; + UCHAR MaxSupportedRate = RATE_11; + + pEntry = MacTableInsertDlsEntry(pAd, SA, i); + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_CCK; + pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->MinHTPhyMode.field.MODE = MODE_CCK; + pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate; + pEntry->HTPhyMode.field.MODE = MODE_CCK; + pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->MinHTPhyMode.field.MODE = MODE_OFDM; + pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + pEntry->HTPhyMode.field.MODE = MODE_OFDM; + pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate]; + } + + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; + +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + + // If this Entry supports 802.11n, upgrade to HT rate. + if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + UCHAR j, bitmask; //k,bitmask; + CHAR ii; + + if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD; + } + else + { + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pAd->MacTab.fAnyStationNonGF = TRUE; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + } + + if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40)); + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20)); + pAd->MacTab.fAnyStation20Only = TRUE; + } + + // find max fixed rate + for (ii=15; ii>=0; ii--) + { + j = ii/8; + bitmask = (1<<(ii-(j*8))); + if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask)) + { + pEntry->MaxHTPhyMode.field.MCS = ii; + break; + } + if (ii==0) + break; + } + + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n", + pAd->StaCfg.DesiredTransmitSetting.field.MCS); + if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32) + { + // Fix MCS as HT Duplicated Mode + pEntry->MaxHTPhyMode.field.BW = 1; + pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX; + pEntry->MaxHTPhyMode.field.STBC = 0; + pEntry->MaxHTPhyMode.field.ShortGI = 0; + pEntry->MaxHTPhyMode.field.MCS = 32; + } + else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS) + { + // STA supports fixed MCS + pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + } + } + + pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + if (HtCapability.HtCapInfo.ShortGIfor20) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); + if (HtCapability.HtCapInfo.ShortGIfor40) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); + if (HtCapability.HtCapInfo.TxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); + if (HtCapability.HtCapInfo.RxSTBC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); + if (HtCapability.ExtHtCapInfo.PlusHTC) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); + if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); + if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); + + NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE)); + } +#endif // DOT11_N_SUPPORT // + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + if (pAd->StaCfg.bAutoTxRateSwitch == TRUE) + { + PUCHAR pTable; + UCHAR TableSize = 0; + + MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex); + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE; + pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + pEntry->RateLen = SupportedRatesLen; + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + // If support WPA or WPA2, start STAKey hand shake, + // If failed hand shake, just tear down peer DLS + if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS) + { + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; + + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n")); + } + else + { + pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY; + DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n")); + } + } + else + { + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5])); + } + pAd->StaCfg.DLSEntry[i].Sequence = 0; + if (HtCapabilityLen != 0) + pAd->StaCfg.DLSEntry[i].bHTCap = TRUE; + else + pAd->StaCfg.DLSEntry[i].bHTCap = FALSE; + } + else + { + // DLS setup procedure failed. + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode)); + } + } + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_TEARDOWN; + USHORT ReasonCode = REASON_QOS_UNSPECIFY; + HEADER_802_11 DlsTearDownHdr; + PRT_802_11_DLS pDLS; + BOOLEAN TimerCancelled; + UCHAR i; + + if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &ReasonCode)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsTearDownAction() with ReasonCode=%d \n", ReasonCode)); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsTearDownAction() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + + // Build basic frame first + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsTearDownHdr, + 1, &Category, + 1, &Action, + 6, &pDLS->MacAddr, + 6, pAd->CurrentAddress, + 2, &ReasonCode, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + RTMPCancelTimer(&pDLS->Timer, &TimerCancelled); + + // Remove key in local dls table entry + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + // clear peer dls table entry + for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++) + { + if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerDlsTearDownAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN]; + USHORT ReasonCode; + UINT i; + BOOLEAN TimerCancelled; + + if (!pAd->CommonCfg.bDLSCapable) + return; + + if (!INFRA_ON(pAd)) + return; + + if (!PeerDlsTearDownSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &ReasonCode)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode)); + + // clear local dls table entry + for (i=0; iStaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); + //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + // clear peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); + //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID); + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID RTMPCheckDLSTimeOut( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_UNSPECIFY; + + if (! pAd->CommonCfg.bDLSCapable) + return; + + if (! INFRA_ON(pAd)) + return; + + // If timeout value is equaled to zero, it means always not be timeout. + + // update local dls table entry + for (i=0; iStaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && (pAd->StaCfg.DLSEntry[i].TimeOut != 0)) + { + pAd->StaCfg.DLSEntry[i].CountDownTimer --; + + if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0) + { + reason = REASON_QOS_REQUEST_TIMEOUT; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + } + } + } + + // update peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && (pAd->StaCfg.DLSEntry[i].TimeOut != 0)) + { + pAd->StaCfg.DLSEntry[i].CountDownTimer --; + + if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0) + { + reason = REASON_QOS_REQUEST_TIMEOUT; + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + } + } + } +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN RTMPRcvFrameDLSCheck( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN ULONG Len, + IN PRT28XX_RXD_STRUC pRxD) +{ + ULONG i; + BOOLEAN bFindEntry = FALSE; + BOOLEAN bSTAKeyFrame = FALSE; + PEAPOL_PACKET pEap; + PUCHAR pProto, pAddr = NULL; + PUCHAR pSTAKey = NULL; + UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; + UCHAR Mic[16], OldMic[16]; + UCHAR digest[80]; + UCHAR DlsPTK[80]; + UCHAR temp[64]; + BOOLEAN TimerCancelled; + CIPHER_KEY PairwiseKey; + + + if (! pAd->CommonCfg.bDLSCapable) + return bSTAKeyFrame; + + if (! INFRA_ON(pAd)) + return bSTAKeyFrame; + + if (! (pHeader->FC.SubType & 0x08)) + return bSTAKeyFrame; + + if (Len < LENGTH_802_11 + 6 + 2 + 2) + return bSTAKeyFrame; + + pProto = (PUCHAR)pHeader + LENGTH_802_11 + 2 + 6; // QOS Control field , 0xAA 0xAA 0xAA 0x00 0x00 0x00 + pAddr = pHeader->Addr2; + + // L2PAD bit on will pad 2 bytes at LLC + if (pRxD->L2PAD) + { + pProto += 2; + } + + if (RTMPEqualMemory(EAPOL, pProto, 2) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)) + { + pEap = (PEAPOL_PACKET) (pProto + 2); + + DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff Len=%ld, DataLen=%d, KeyMic=%d, Install=%d, KeyAck=%d, Secure=%d, EKD_DL=%d, Error=%d, Request=%d\n", Len, + (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16), + pEap->KeyDesc.KeyInfo.KeyMic, + pEap->KeyDesc.KeyInfo.Install, + pEap->KeyDesc.KeyInfo.KeyAck, + pEap->KeyDesc.KeyInfo.Secure, + pEap->KeyDesc.KeyInfo.EKD_DL, + pEap->KeyDesc.KeyInfo.Error, + pEap->KeyDesc.KeyInfo.Request)); + + if ((Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16)) && pEap->KeyDesc.KeyInfo.KeyMic + && pEap->KeyDesc.KeyInfo.Install && pEap->KeyDesc.KeyInfo.KeyAck && pEap->KeyDesc.KeyInfo.Secure + && pEap->KeyDesc.KeyInfo.EKD_DL && !pEap->KeyDesc.KeyInfo.Error && !pEap->KeyDesc.KeyInfo.Request) + { + // First validate replay counter, only accept message with larger replay counter + // Let equal pass, some AP start with all zero replay counter + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + if ((RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) && + (RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) + return bSTAKeyFrame; + + //RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter (%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n", + pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2], + pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5], + pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1])); + + // put these code segment to get the replay counter + if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) + return bSTAKeyFrame; + + // Check MIC value + // Save the MIC and replace with zero + // use proprietary PTK + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); + + NdisMoveMemory(OldMic, pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1((PUCHAR) pEap, pEap->Body_Len[1] + 4, DlsPTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, Mic); + } + + if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in Msg1 of STAKey handshake! \n")); + return bSTAKeyFrame; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in Msg1 of STAKey handshake! \n")); +#if 1 + if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0C) + && (pEap->KeyDesc.KeyData[4] == 0x43) && (pEap->KeyDesc.KeyData[5] == 0x02)) + { + pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2) + pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6) + + DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%ld, KeyDataLen=%d\n", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1])); + + bSTAKeyFrame = TRUE; + } +#else + if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0F) + && (pEap->KeyDesc.KeyData[4] == 0xAC) && (pEap->KeyDesc.KeyData[5] == 0x02)) + { + pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2) + pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6) + + DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%d, KeyDataLen=%d\n", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1])); + + bSTAKeyFrame = TRUE; + } +#endif + + } + else if (Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE)) + { + RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter 2(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n", + pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2], + pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5], + pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1])); + + } + } + + // If timeout value is equaled to zero, it means always not be timeout. + // update local dls table entry + for (i= 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (bSTAKeyFrame) + { + PMAC_TABLE_ENTRY pEntry; + + // STAKey frame, add pairwise key table + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + + PairwiseKey.KeyLen = LEN_TKIP_EK; + NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK); + NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK); + NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK); + + PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg; + + pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); + //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast + //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); + // Add Pair-wise key to Asic +#ifdef RT2870 +//Benson modified for USB interface, avoid in interrupt when write key, 20080724 --> + { + RT_ADD_PAIRWISE_KEY_ENTRY KeyInfo; + COPY_MAC_ADDR(KeyInfo.MacAddr,pAd->StaCfg.DLSEntry[i].MacAddr); + KeyInfo.MacTabMatchWCID=pAd->StaCfg.DLSEntry[i].MacTabMatchWCID; + NdisMoveMemory(&KeyInfo.CipherKey, &PairwiseKey,sizeof(CIPHER_KEY)); + RTUSBEnqueueInternalCmd(pAd, RT_CMD_SET_KEY_TABLE, &KeyInfo, sizeof(RT_ADD_PAIRWISE_KEY_ENTRY)); + } + { + PMAC_TABLE_ENTRY pDLSEntry; + pDLSEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); + pDLSEntry->PairwiseKey.CipherAlg=PairwiseKey.CipherAlg; + RTUSBEnqueueInternalCmd(pAd, RT_CMD_SET_RX_WCID_TABLE, pDLSEntry, sizeof(MAC_TABLE_ENTRY)); + } +//Benson modified for USB interface, avoid in interrupt when write key, 20080724 <-- +#endif // RT2870 // + NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n")); + + RTMPSendSTAKeyHandShake(pAd, pAd->StaCfg.DLSEntry[i].MacAddr); + + DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Initiator side)\n")); + } + else + { + // Data frame, update timeout value + if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + { + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); + } + } + + bFindEntry = TRUE; + } + } + + // update peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + if (bSTAKeyFrame) + { + PMAC_TABLE_ENTRY pEntry = NULL; + + // STAKey frame, add pairwise key table, and send STAkey Msg-2 + pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH; + RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled); + + PairwiseKey.KeyLen = LEN_TKIP_EK; + NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK); + NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK); + NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK); + + PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg; + + pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); + //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast + //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr); + // Add Pair-wise key to Asic +#ifdef RT2870 +//Benson modified for USB interface, avoid in interrupt when write key, 20080724 --> + { + RT_ADD_PAIRWISE_KEY_ENTRY KeyInfo; + COPY_MAC_ADDR(KeyInfo.MacAddr,pAd->StaCfg.DLSEntry[i].MacAddr); + KeyInfo.MacTabMatchWCID=pAd->StaCfg.DLSEntry[i].MacTabMatchWCID; + NdisMoveMemory(&KeyInfo.CipherKey, &PairwiseKey,sizeof(CIPHER_KEY)); + RTUSBEnqueueInternalCmd(pAd, RT_CMD_SET_KEY_TABLE, &KeyInfo, sizeof(RT_ADD_PAIRWISE_KEY_ENTRY)); + } + { + PMAC_TABLE_ENTRY pDLSEntry; + pDLSEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE); + pDLSEntry->PairwiseKey.CipherAlg=PairwiseKey.CipherAlg; + RTUSBEnqueueInternalCmd(pAd, RT_CMD_SET_RX_WCID_TABLE, pDLSEntry, sizeof(MAC_TABLE_ENTRY)); + } +//Benson modified for USB interface, avoid in interrupt when write key, 20080724 <-- +#endif // RT2870 // + NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n")); + + // If support WPA or WPA2, start STAKey hand shake, + // If failed hand shake, just tear down peer DLS + if (RTMPSendSTAKeyHandShake(pAd, pAddr) != NDIS_STATUS_SUCCESS) + { + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT; + + pAd->StaCfg.DLSEntry[i].Valid = FALSE; + pAd->StaCfg.DLSEntry[i].Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Peer side)\n")); + } + } + else + { + // Data frame, update timeout value + if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + { + pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut; + } + } + + bFindEntry = TRUE; + } + } + + + return bSTAKeyFrame; +} + +/* + ======================================================================== + + Routine Description: + Check if the frame can be sent through DLS direct link interface + + Arguments: + pAd Pointer to adapter + + Return Value: + DLS entry index + + Note: + + ======================================================================== +*/ +INT RTMPCheckDLSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + INT rval = -1; + INT i; + + if (!pAd->CommonCfg.bDLSCapable) + return rval; + + if (!INFRA_ON(pAd)) + return rval; + + do{ + // check local dls table entry + for (i=0; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && + MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + rval = i; + break; + } + } + + // check peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && + MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + rval = i; + break; + } + } + } while (FALSE); + + return rval; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID RTMPSendDLSTearDownFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + HEADER_802_11 DlsTearDownHdr; + ULONG FrameLen = 0; + USHORT Reason = REASON_QOS_QSTA_LEAVING_QBSS; + UCHAR Category = CATEGORY_DLS; + UCHAR Action = ACTION_DLS_TEARDOWN; + UCHAR i = 0; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame \n")); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ASSOC - RTMPSendDLSTearDownFrame() allocate memory failed \n")); + return; + } + + ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DlsTearDownHdr, + 1, &Category, + 1, &Action, + 6, pDA, + 6, pAd->CurrentAddress, + 2, &Reason, + END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + // Remove key in local dls table entry + for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++) + { + if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + // Remove key in peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) + && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr)) + { + MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame and remove key in (i=%d) \n", i)); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +NDIS_STATUS RTMPSendSTAKeyRequest( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + UCHAR Header802_3[14]; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + UCHAR digest[80]; + PUCHAR pOutBuffer = NULL; + PNDIS_PACKET pNdisPacket; + UCHAR temp[64]; + UCHAR DlsPTK[80]; + + DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyRequest() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5])); + + pAd->Sequence ++; + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero message body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE andPeer MAC address + + // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE) + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + Packet.KeyDesc.Type = WPA1_KEY_DESC; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + Packet.KeyDesc.Type = WPA2_KEY_DESC; + } + + // Key descriptor version + Packet.KeyDesc.KeyInfo.KeyDescVer = + (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); + + Packet.KeyDesc.KeyInfo.KeyMic = 1; + Packet.KeyDesc.KeyInfo.Secure = 1; + Packet.KeyDesc.KeyInfo.Request = 1; + + Packet.KeyDesc.KeyDataLen[1] = 12; + + // use our own OUI to distinguish proprietary with standard. + Packet.KeyDesc.KeyData[0] = 0xDD; + Packet.KeyDesc.KeyData[1] = 0x0A; + Packet.KeyDesc.KeyData[2] = 0x00; + Packet.KeyDesc.KeyData[3] = 0x0C; + Packet.KeyDesc.KeyData[4] = 0x43; + Packet.KeyDesc.KeyData[5] = 0x03; + NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN); + + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY); + + // Allocate buffer for transmitting message + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return NStatus; + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // use proprietary PTK + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); + + // calculate MIC + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + NdisZeroMemory(digest, sizeof(digest)); + HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC); + } + else + { + NdisZeroMemory(Mic, sizeof(Mic)); + hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + } + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(Header802_3), Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen); + if (NStatus == NDIS_STATUS_SUCCESS) + { + RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID); + STASendPacket(pAd, pNdisPacket); + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyRequest- Send STAKey request (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen)); + + return NStatus; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +NDIS_STATUS RTMPSendSTAKeyHandShake( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA) +{ + UCHAR Header802_3[14]; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + UCHAR digest[80]; + PUCHAR pOutBuffer = NULL; + PNDIS_PACKET pNdisPacket; + UCHAR temp[64]; + UCHAR DlsPTK[80]; // Due to dirver can not get PTK, use proprietary PTK + + DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyHandShake() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5])); + + pAd->Sequence ++; + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero message body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE and Peer MAC address + + // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE) + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) + { + Packet.KeyDesc.Type = WPA1_KEY_DESC; + } + else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + Packet.KeyDesc.Type = WPA2_KEY_DESC; + } + + // Key descriptor version + Packet.KeyDesc.KeyInfo.KeyDescVer = + (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP)); + + Packet.KeyDesc.KeyInfo.KeyMic = 1; + Packet.KeyDesc.KeyInfo.Secure = 1; + + Packet.KeyDesc.KeyDataLen[1] = 12; + + // use our own OUI to distinguish proprietary with standard. + Packet.KeyDesc.KeyData[0] = 0xDD; + Packet.KeyDesc.KeyData[1] = 0x0A; + Packet.KeyDesc.KeyData[2] = 0x00; + Packet.KeyDesc.KeyData[3] = 0x0C; + Packet.KeyDesc.KeyData[4] = 0x43; + Packet.KeyDesc.KeyData[5] = 0x03; + NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN); + + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY); + + // Allocate buffer for transmitting message + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return NStatus; + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // use proprietary PTK + NdisZeroMemory(temp, 64); + NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32); + WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK); + + // calculate MIC + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + NdisZeroMemory(digest, sizeof(digest)); + HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC); + } + else + { + NdisZeroMemory(Mic, sizeof(Mic)); + hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + } + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(Header802_3), Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen); + if (NStatus == NDIS_STATUS_SUCCESS) + { + RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID); + STASendPacket(pAd, pNdisPacket); + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + } + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyHandShake- Send STAKey Message-2 (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen)); + + return NStatus; +} + +VOID DlsTimeoutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MLME_DLS_REQ_STRUCT MlmeDlsReq; + USHORT reason; + PRT_802_11_DLS pDLS = (PRT_802_11_DLS)FunctionContext; + PRTMP_ADAPTER pAd = pDLS->pAd; + + DBGPRINT(RT_DEBUG_TRACE, ("DlsTimeout - Tear down DLS links (%02x:%02x:%02x:%02x:%02x:%02x)\n", + pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5])); + + if ((pDLS) && (pDLS->Valid)) + { + reason = REASON_QOS_REQUEST_TIMEOUT; + pDLS->Valid = FALSE; + pDLS->Status = DLS_NONE; + DlsParmFill(pAd, &MlmeDlsReq, pDLS, reason); + MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq); + RT28XX_MLME_HANDLER(pAd); + } +} + +/* +================================================================ +Description : because DLS and CLI share the same WCID table in ASIC. +Mesh entry also insert to pAd->MacTab.content[]. Such is marked as ValidAsDls = TRUE. +Also fills the pairwise key. +Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert Dls +from index MAX_AID_BA. +================================================================ +*/ +MAC_TABLE_ENTRY *MacTableInsertDlsEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UINT DlsEntryIdx) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableInsertDlsEntry\n")); + // if FULL, return + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + do + { + if((pEntry = DlsEntryTableLookup(pAd, pAddr, TRUE)) != NULL) + break; + + // allocate one MAC entry + pEntry = MacTableInsertEntry(pAd, pAddr, DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, TRUE); + if (pEntry) + { + pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = pEntry->Aid; + pEntry->MatchDlsEntryIdx = DlsEntryIdx; + pEntry->AuthMode = pAd->StaCfg.AuthMode; + pEntry->WepStatus = pAd->StaCfg.WepStatus; + + DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n",pEntry->Aid, pAd->MacTab.Size)); + + // If legacy WEP is used, set pair-wise cipherAlg into WCID attribute table for this entry + if ((pEntry->ValidAsDls) && (pEntry->WepStatus == Ndis802_11WEPEnabled)) + { + UCHAR KeyIdx = 0; + UCHAR CipherAlg = 0; + + KeyIdx = pAd->StaCfg.DefaultKeyId; + + CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + pEntry); + } + + break; + } + } while(FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableInsertDlsEntry\n")); + + return pEntry; +} + + +/* + ========================================================================== + Description: + Delete all Mesh Entry in pAd->MacTab + ========================================================================== + */ +BOOLEAN MacTableDeleteDlsEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr) +{ + DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableDeleteDlsEntry\n")); + + if (!VALID_WCID(wcid)) + return FALSE; + + MacTableDeleteEntry(pAd, wcid, pAddr); + + DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableDeleteDlsEntry\n")); + + return TRUE; +} + +MAC_TABLE_ENTRY *DlsEntryTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + ULONG HashIdx; + MAC_TABLE_ENTRY *pEntry = NULL; + + RTMP_SEM_LOCK(&pAd->MacTabLock); + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + while (pEntry) + { + if ((pEntry->ValidAsDls == TRUE) + && MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) + { + if(bResetIdelCount) + pEntry->NoDataIdleCount = 0; + break; + } + else + pEntry = pEntry->pNext; + } + + RTMP_SEM_UNLOCK(&pAd->MacTabLock); + return pEntry; +} + +MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + ULONG DLsIndex; + PMAC_TABLE_ENTRY pCurEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (!VALID_WCID(wcid)) + return NULL; + + RTMP_SEM_LOCK(&pAd->MacTabLock); + + do + { + pCurEntry = &pAd->MacTab.Content[wcid]; + + DLsIndex = 0xff; + if ((pCurEntry) && (pCurEntry->ValidAsDls== TRUE)) + { + DLsIndex = pCurEntry->MatchDlsEntryIdx; + } + + if (DLsIndex == 0xff) + break; + + if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr)) + { + if(bResetIdelCount) + pCurEntry->NoDataIdleCount = 0; + pEntry = pCurEntry; + break; + } + } while(FALSE); + + RTMP_SEM_UNLOCK(&pAd->MacTabLock); + + return pEntry; +} + +INT Set_DlsEntryInfo_Display_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + INT i; + + printk("\n%-19s%-8s\n", "MAC", "TIMEOUT\n"); + for (i=0; iStaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + printk("%02x:%02x:%02x:%02x:%02x:%02x ", + pAd->StaCfg.DLSEntry[i].MacAddr[0], pAd->StaCfg.DLSEntry[i].MacAddr[1], pAd->StaCfg.DLSEntry[i].MacAddr[2], + pAd->StaCfg.DLSEntry[i].MacAddr[3], pAd->StaCfg.DLSEntry[i].MacAddr[4], pAd->StaCfg.DLSEntry[i].MacAddr[5]); + printk("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut); + } + } + + return TRUE; +} + +INT Set_DlsAddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR mac[MAC_ADDR_LEN]; + USHORT Timeout; + char *token, sepValue[] = ":", DASH = '-'; + INT i; + RT_802_11_DLS Dls; + + if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and timeout value in decimal format. + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + Timeout = simple_strtol((token+1), 0, 10); + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (PUCHAR)(&mac[i]), 1); + } + if(i != 6) + return FALSE; + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%d", mac[0], mac[1], + mac[2], mac[3], mac[4], mac[5], (int)Timeout); + + NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); + Dls.TimeOut = Timeout; + COPY_MAC_ADDR(Dls.MacAddr, mac); + Dls.Valid = 1; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_DLS_PARAM, + sizeof(RT_802_11_DLS), + &Dls); + + return TRUE; + } + + return FALSE; + +} + +INT Set_DlsTearDownEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + CHAR *value; + INT i; + RT_802_11_DLS Dls; + + if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17 + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; //Invalid + + AtoH(value, &macAddr[i++], 2); + } + + printk("\n%02x:%02x:%02x:%02x:%02x:%02x", macAddr[0], macAddr[1], + macAddr[2], macAddr[3], macAddr[4], macAddr[5]); + + NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); + COPY_MAC_ADDR(Dls.MacAddr, macAddr); + Dls.Valid = 0; + + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_DLS_PARAM, + sizeof(RT_802_11_DLS), + &Dls); + + return TRUE; +} + diff --git a/drivers/staging/rt3070/sta/rtmp_data.c b/drivers/staging/rt3070/sta/rtmp_data.c new file mode 100644 index 000000000000..b0f259b35c74 --- /dev/null +++ b/drivers/staging/rt3070/sta/rtmp_data.c @@ -0,0 +1,2637 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + rtmp_data.c + + Abstract: + Data path subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Aug/17/04 major modification for RT2561/2661 + Jan Lee Mar/17/06 major modification for RT2860 New Ring Design +*/ +#include "../rt_config.h" + + + +VOID STARxEAPOLFrameIndicate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + UCHAR *pTmpBuf; + + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + { + // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) + // TBD : process fragmented EAPol frames + { + // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable + if ( pAd->StaCfg.IEEE8021X == TRUE && + (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H))) + { + PUCHAR Key; + UCHAR CipherAlg; + int idx = 0; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n")); + //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAd); + + if (pAd->StaCfg.IEEE8021x_required_keys == FALSE) + { + idx = pAd->StaCfg.DesireSharedKeyId; + CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg; + Key = pAd->StaCfg.DesireSharedKey[idx].Key; + + if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0) + { +#ifdef RT2870 + union + { + char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1]; + NDIS_802_11_WEP keyinfo; + } WepKey; + int len; + + + NdisZeroMemory(&WepKey, sizeof(WepKey)); + len =pAd->StaCfg.DesireSharedKey[idx].KeyLen; + + NdisMoveMemory(WepKey.keyinfo.KeyMaterial, + pAd->StaCfg.DesireSharedKey[idx].Key, + pAd->StaCfg.DesireSharedKey[idx].KeyLen); + + WepKey.keyinfo.KeyIndex = 0x80000000 + idx; + WepKey.keyinfo.KeyLength = len; + pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13); + + pAd->IndicateMediaState = NdisMediaStateConnected; + pAd->ExtraInfo = GENERAL_LINK_UP; + // need to enqueue cmd to thread + RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1); +#endif // RT2870 // + // For Preventing ShardKey Table is cleared by remove key procedure. + pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg; + pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen; + NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key, + pAd->StaCfg.DesireSharedKey[idx].Key, + pAd->StaCfg.DesireSharedKey[idx].KeyLen); + } + } + } + + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + // Special DATA frame that has to pass to MLME + // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process + // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process + { + pTmpBuf = pRxBlk->pData - LENGTH_802_11; + NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); + DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize)); + } + } + + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + +} + +VOID STARxDataFrameAnnounce( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR FromWhichBSSID) +{ + + // non-EAP frame + if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) + { + + { + // drop all non-EAP DATA frame before + // this client's Port-Access-Control is secured + if (pRxBlk->pHeader->FC.Wep) + { + // unsupported cipher suite + if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + else + { + // encryption in-use but receive a non-EAPOL clear text frame, drop it + if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + } + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP); + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) + { + // Normal legacy, AMPDU or AMSDU + CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID); + + } + else + { + // ARALINK + CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } +#ifdef QOS_DLS_SUPPORT + RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS); +#endif // QOS_DLS_SUPPORT // + } + else + { + RX_BLK_SET_FLAG(pRxBlk, fRX_EAP); +#ifdef DOT11_N_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) + { + Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); + } + else +#endif // DOT11_N_SUPPORT // + { + // Determin the destination of the EAP frame + // to WPA state machine or upper layer + STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); + } + } +} + + +// For TKIP frame, calculate the MIC value +BOOLEAN STACheckTkipMICValue( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk) +{ + PHEADER_802_11 pHeader = pRxBlk->pHeader; + UCHAR *pData = pRxBlk->pData; + USHORT DataSize = pRxBlk->DataSize; + UCHAR UserPriority = pRxBlk->UserPriority; + PCIPHER_KEY pWpaKey; + UCHAR *pDA, *pSA; + + pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex]; + + pDA = pHeader->Addr1; + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) + { + pSA = pHeader->Addr3; + } + else + { + pSA = pHeader->Addr2; + } + + if (RTMPTkipCompareMICValue(pAd, + pData, + pDA, + pSA, + pWpaKey->RxMic, + UserPriority, + DataSize) == FALSE) + { + DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n")); + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.WpaSupplicantUP) + { + WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE); + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + RTMPReportMicError(pAd, pWpaKey); + } + + // release packet + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return FALSE; + } + + return TRUE; +} + + +// +// All Rx routines use RX_BLK structure to hande rx events +// It is very important to build pRxBlk attributes +// 1. pHeader pointer to 802.11 Header +// 2. pData pointer to payload including LLC (just skip Header) +// 3. set payload size including LLC to DataSize +// 4. set some flags with RX_BLK_SET_FLAG() +// +VOID STAHandleRxDataFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + BOOLEAN bFragment = FALSE; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR FromWhichBSSID = BSS0; + UCHAR UserPriority = 0; + + { + // before LINK UP, all DATA frames are rejected + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + +#ifdef QOS_DLS_SUPPORT + //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) + if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD)) + { + return; + } +#endif // QOS_DLS_SUPPORT // + + // Drop not my BSS frames + if (pRxD->MyBss == 0) + { + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + + pAd->RalinkCounters.RxCountSinceLastNULL++; + if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08)) + { + UCHAR *pData; + DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n")); + + // Qos bit 4 + pData = (PUCHAR)pHeader + LENGTH_802_11; + if ((*pData >> 4) & 0x01) + { + DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n")); + pAd->CommonCfg.bInServicePeriod = FALSE; + + // Force driver to fall into sleep mode when rcv EOSP frame + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + USHORT TbttNumToNextWakeUp; + USHORT NextDtim = pAd->StaCfg.DtimPeriod; + ULONG Now; + + NdisGetSystemUpTime(&Now); + NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod; + + TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) + TbttNumToNextWakeUp = NextDtim; + + MlmeSetPsmBit(pAd, PWR_SAVE); + // if WMM-APSD is failed, try to disable following line + AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + } + } + + if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod)) + { + DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n")); + } + } + + // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame + if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // Drop not my BSS frame (we can not only check the MyBss bit in RxD) +#ifdef QOS_DLS_SUPPORT + if (!pAd->CommonCfg.bDLSCapable) + { +#endif // QOS_DLS_SUPPORT // + if (INFRA_ON(pAd)) + { + // Infrastructure mode, check address 2 for BSSID + if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) + { + // Receive frame not my BSSID + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } + else // Ad-Hoc mode or Not associated + { + // Ad-Hoc mode, check address 3 for BSSID + if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) + { + // Receive frame not my BSSID + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + } +#ifdef QOS_DLS_SUPPORT + } +#endif // QOS_DLS_SUPPORT // + + // + // find pEntry + // + if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) + { + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + } + else + { + // 1. release packet if infra mode + // 2. new a pEntry if ad-hoc mode + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // infra or ad-hoc + if (INFRA_ON(pAd)) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA); +#ifdef QOS_DLS_SUPPORT + if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) + RX_BLK_SET_FLAG(pRxBlk, fRX_DLS); + else +#endif // QOS_DLS_SUPPORT // + ASSERT(pRxWI->WirelessCliID == BSSID_WCID); + } + + // check Atheros Client + if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry )) + { + pEntry->bIAmBadAtheros = TRUE; + pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE; + pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE; + if (!STA_AES_ON(pAd)) + { + AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE); + } + } + } + + pRxBlk->pData = (UCHAR *)pHeader; + + // + // update RxBlk->pData, DataSize + // 802.11 Header, QOS, HTC, Hw Padding + // + + // 1. skip 802.11 HEADER + { + pRxBlk->pData += LENGTH_802_11; + pRxBlk->DataSize -= LENGTH_802_11; + } + + // 2. QOS + if (pHeader->FC.SubType & 0x08) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_QOS); + UserPriority = *(pRxBlk->pData) & 0x0f; + // bit 7 in QoS Control field signals the HT A-MSDU format + if ((*pRxBlk->pData) & 0x80) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU); + } + + // skip QOS contorl field + pRxBlk->pData += 2; + pRxBlk->DataSize -=2; + } + pRxBlk->UserPriority = UserPriority; + + // 3. Order bit: A-Ralink or HTC+ + if (pHeader->FC.Order) + { +#ifdef AGGREGATION_SUPPORT + if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK); + } + else +#endif + { +#ifdef DOT11_N_SUPPORT + RX_BLK_SET_FLAG(pRxBlk, fRX_HTC); + // skip HTC contorl field + pRxBlk->pData += 4; + pRxBlk->DataSize -= 4; +#endif // DOT11_N_SUPPORT // + } + } + + // 4. skip HW padding + if (pRxD->L2PAD) + { + // just move pData pointer + // because DataSize excluding HW padding + RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); + pRxBlk->pData += 2; + } + +#ifdef DOT11_N_SUPPORT + if (pRxD->BA) + { + RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU); + } +#endif // DOT11_N_SUPPORT // + + + // + // Case I Process Broadcast & Multicast data frame + // + if (pRxD->Bcast || pRxD->Mcast) + { + INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); + + // Drop Mcast/Bcast frame with fragment bit on + if (pHeader->FC.MoreFrag) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + // Filter out Bcast frame which AP relayed for us + if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) + { + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); + return; + } + else if (pRxD->U2M) + { + pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ; + + +#ifdef QOS_DLS_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS)) + { + MAC_TABLE_ENTRY *pDlsEntry = NULL; + + pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE); + if(pDlsEntry) + Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI); + } + else +#endif // QOS_DLS_SUPPORT // + if (ADHOC_ON(pAd)) + { + pEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pEntry) + Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI); + } + + + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); + + pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); + pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); + + pAd->RalinkCounters.OneSecRxOkDataCnt++; + + + if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) + { + // re-assemble the fragmented packets + // return complete frame (pRxPacket) or NULL + bFragment = TRUE; + pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); + } + + if (pRxPacket) + { + pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; + + // process complete frame + if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled)) + { + // Minus MIC length + pRxBlk->DataSize -= 8; + + // For TKIP frame, calculate the MIC value + if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) + { + return; + } + } + + STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID); + return; + } + else + { + // just return + // because RTMPDeFragmentDataFrame() will release rx packet, + // if packet is fragmented + return; + } + } + + ASSERT(0); + // release packet + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); +} + +VOID STAHandleRxMgmtFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ + PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + + do + { + + // We should collect RSSI not only U2M data but also my beacon + if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)) + && (pAd->RxAnt.EvaluatePeriod == 0)) + { + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); + + pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); + pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); + } + +#ifdef RT30xx + // collect rssi information for antenna diversity + if (pAd->NicConfig2.field.AntDiversity) + { + if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))) + { + COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73 + pAd->StaCfg.NumOfAvgRssiSample ++; + } + } +#endif // RT30xx // + + // First check the size, it MUST not exceed the mlme queue size + if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount)); + break; + } + + REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount, + pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); + } while (FALSE); + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); +} + +VOID STAHandleRxControlFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk) +{ +#ifdef DOT11_N_SUPPORT + PRXWI_STRUC pRxWI = pRxBlk->pRxWI; +#endif // DOT11_N_SUPPORT // + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; + + switch (pHeader->FC.SubType) + { + case SUBTYPE_BLOCK_ACK_REQ: +#ifdef DOT11_N_SUPPORT + { + CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader); + } + break; +#endif // DOT11_N_SUPPORT // + case SUBTYPE_BLOCK_ACK: + case SUBTYPE_ACK: + default: + break; + } + + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); +} + + +/* + ======================================================================== + + Routine Description: + Process RxDone interrupt, running in DPC level + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + This routine has to maintain Rx ring read pointer. + Need to consider QOS DATA format when converting to 802.3 + ======================================================================== +*/ +BOOLEAN STARxDoneInterruptHandle( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN argc) +{ + NDIS_STATUS Status; + UINT32 RxProcessed, RxPending; + BOOLEAN bReschedule = FALSE; + RT28XX_RXD_STRUC *pRxD; + UCHAR *pData; + PRXWI_STRUC pRxWI; + PNDIS_PACKET pRxPacket; + PHEADER_802_11 pHeader; + RX_BLK RxCell; + + RxProcessed = RxPending = 0; + + // process whole rx ring + while (1) + { + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST) || + !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP)) + { + break; + } + + + RxProcessed ++; // test + + // 1. allocate a new data packet into rx ring to replace received packet + // then processing the received packet + // 2. the callee must take charge of release of packet + // 3. As far as driver is concerned , + // the rx packet must + // a. be indicated to upper layer or + // b. be released if it is discarded + pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending); + if (pRxPacket == NULL) + { + // no more packet to process + break; + } + + // get rx ring descriptor + pRxD = &(RxCell.RxD); + // get rx data buffer + pData = GET_OS_PKT_DATAPTR(pRxPacket); + pRxWI = (PRXWI_STRUC) pData; + pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE); + RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI); +#endif + + // build RxCell + RxCell.pRxWI = pRxWI; + RxCell.pHeader = pHeader; + RxCell.pRxPacket = pRxPacket; + RxCell.pData = (UCHAR *) pHeader; + RxCell.DataSize = pRxWI->MPDUtotalByteCount; + RxCell.Flags = 0; + + // Increase Total receive byte counter after real data received no mater any error or not + pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount; + pAd->RalinkCounters.RxCount ++; + + INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); + + if (pRxWI->MPDUtotalByteCount < 14) + Status = NDIS_STATUS_FAILURE; + + if (MONITOR_ON(pAd)) + { + send_monitor_packets(pAd, &RxCell); + break; + } + /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + pAd->ate.RxCntPerSec++; + ATESampleRssi(pAd, pRxWI); +#ifdef RALINK_28xx_QA + if (pAd->ate.bQARxStart == TRUE) + { + /* (*pRxD) has been swapped in GetPacketFromRxRing() */ + ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader); + } +#endif // RALINK_28xx_QA // + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } +#endif // RALINK_ATE // + + // Check for all RxD errors + Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD); + + // Handle the received frame + if (Status == NDIS_STATUS_SUCCESS) + { + switch (pHeader->FC.Type) + { + // CASE I, receive a DATA frame + case BTYPE_DATA: + { + // process DATA frame + STAHandleRxDataFrame(pAd, &RxCell); + } + break; + // CASE II, receive a MGMT frame + case BTYPE_MGMT: + { + STAHandleRxMgmtFrame(pAd, &RxCell); + } + break; + // CASE III. receive a CNTL frame + case BTYPE_CNTL: + { + STAHandleRxControlFrame(pAd, &RxCell); + } + break; + // discard other type + default: + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + break; + } + } + else + { + pAd->Counters8023.RxErrors++; + // discard this frame + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); + } + } + + return bReschedule; +} + +/* + ======================================================================== + + Routine Description: + Arguments: + pAd Pointer to our adapter + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandleTwakeupInterrupt( + IN PRTMP_ADAPTER pAd) +{ + AsicForceWakeup(pAd, FALSE); +} + +/* +======================================================================== +Routine Description: + Early checking and OS-depened parsing for Tx packet send to our STA driver. + +Arguments: + NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd. + PPNDIS_PACKET ppPacketArray The packet array need to do transmission. + UINT NumberOfPackets Number of packet in packet array. + +Return Value: + NONE + +Note: + This function do early checking and classification for send-out packet. + You only can put OS-depened & STA related code in here. +======================================================================== +*/ +VOID STASendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets) +{ + UINT Index; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext; + PNDIS_PACKET pPacket; + BOOLEAN allowToSend = FALSE; + + + for (Index = 0; Index < NumberOfPackets; Index++) + { + pPacket = ppPacketArray[Index]; + + do + { + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + { + // Drop send request since hardware is in reset state + break; + } + else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) + { + // Drop send request since there are no physical connection yet + break; + } + else + { + // Record that orignal packet source is from NDIS layer,so that + // later on driver knows how to release this NDIS PACKET +#ifdef QOS_DLS_SUPPORT + MAC_TABLE_ENTRY *pEntry; + PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + + pEntry = MacTableLookup(pAd, pSrcBufVA); + if (pEntry && (pEntry->ValidAsDls == TRUE)) + { + RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid); + } + else +#endif // QOS_DLS_SUPPORT // + RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); + NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING); + pAd->RalinkCounters.PendingNdisPacketCount++; + + allowToSend = TRUE; + } + } while(FALSE); + + if (allowToSend == TRUE) + STASendPacket(pAd, pPacket); + else + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + + // Dequeue outgoing frames from TxSwQueue[] and process it + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); + +} + + +/* +======================================================================== +Routine Description: + This routine is used to do packet parsing and classification for Tx packet + to STA device, and it will en-queue packets to our TxSwQueue depends on AC + class. + +Arguments: + pAd Pointer to our adapter + pPacket Pointer to send packet + +Return Value: + NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue. + NDIS_STATUS_FAILURE If failed to do en-queue. + +Note: + You only can put OS-indepened & STA related code in here. +======================================================================== +*/ +NDIS_STATUS STASendPacket( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + UINT AllowFragSize; + UCHAR NumberOfFrag; +// UCHAR RTSRequired; + UCHAR QueIdx, UserPriority; + MAC_TABLE_ENTRY *pEntry = NULL; + unsigned int IrqFlags; + UCHAR FlgIsIP = 0; + UCHAR Rate; + + // Prepare packet information structure for buffer descriptor + // chained within a single NDIS packet. + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen)); + // Resourece is low, system did not allocate virtual address + // return NDIS_STATUS_FAILURE directly to upper layer + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + + if (SrcBufLen < 14) + { + DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n")); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return (NDIS_STATUS_FAILURE); + } + + // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. + // Note multicast packets in adhoc also use BSSID_WCID index. + { + if(INFRA_ON(pAd)) + { +#ifdef QOS_DLS_SUPPORT + USHORT tmpWcid; + + tmpWcid = RTMP_GET_PACKET_WCID(pPacket); + if (VALID_WCID(tmpWcid) && + (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE)) + { + pEntry = &pAd->MacTab.Content[tmpWcid]; + Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate; + } + else +#endif // QOS_DLS_SUPPORT // + { + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); + Rate = pAd->CommonCfg.TxRate; + } + } + else if (ADHOC_ON(pAd)) + { + if (*pSrcBufVA & 0x01) + { + RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID); + pEntry = &pAd->MacTab.Content[MCAST_WCID]; + } + else + { + pEntry = MacTableLookup(pAd, pSrcBufVA); + } + Rate = pAd->CommonCfg.TxRate; + } + } + + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA))); + // Resourece is low, system did not allocate virtual address + // return NDIS_STATUS_FAILURE directly to upper layer + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + if (ADHOC_ON(pAd) + ) + { + RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid); + } + + // + // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. + // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). + RTMPCheckEtherType(pAd, pPacket); + + + + // + // WPA 802.1x secured port control - drop all non-802.1x frame before port secured + // + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.IEEE8021X == TRUE) +#endif // WPA_SUPPLICANT_SUPPORT // +#ifdef LEAP_SUPPORT + || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) +#endif // LEAP_SUPPORT // + ) + && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2)) + && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE) + ) + { + DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n")); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return (NDIS_STATUS_FAILURE); + } + + + // STEP 1. Decide number of fragments required to deliver this MSDU. + // The estimation here is not very accurate because difficult to + // take encryption overhead into consideration here. The result + // "NumberOfFrag" is then just used to pre-check if enough free + // TXD are available to hold this MSDU. + + + if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast + NumberOfFrag = 1; + else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) + NumberOfFrag = 1; // Aggregation overwhelms fragmentation + else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED)) + NumberOfFrag = 1; // Aggregation overwhelms fragmentation +#ifdef DOT11_N_SUPPORT + else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD)) + NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation +#endif // DOT11_N_SUPPORT // + else + { + // The calculated "NumberOfFrag" is a rough estimation because of various + // encryption/encapsulation overhead not taken into consideration. This number is just + // used to make sure enough free TXD are available before fragmentation takes place. + // In case the actual required number of fragments of an NDIS packet + // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the + // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of + // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should + // rarely happen and the penalty is just like a TX RETRY fail. Affordable. + + AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; + NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1; + // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size + if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0) + { + NumberOfFrag--; + } + } + + // Save fragment number to Ndis packet reserved field + RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); + + + // STEP 2. Check the requirement of RTS: + // If multiple fragment required, RTS is required only for the first fragment + // if the fragment size large than RTS threshold + // For RT28xx, Let ASIC send RTS/CTS + RTMP_SET_PACKET_RTS(pPacket, 0); + RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate); + + // + // STEP 3. Traffic classification. outcome = + // + UserPriority = 0; + QueIdx = QID_AC_BE; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) + { + USHORT Protocol; + UCHAR LlcSnapLen = 0, Byte0, Byte1; + do + { + // get Ethernet protocol field + Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]); + if (Protocol <= 1500) + { + // get Ethernet protocol field from LLC/SNAP + if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) + break; + + Protocol = (USHORT)((Byte0 << 8) + Byte1); + LlcSnapLen = 8; + } + + // always AC_BE for non-IP packet + if (Protocol != 0x0800) + break; + + // get IP header + if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) + break; + + // return AC_BE if packet is not IPv4 + if ((Byte0 & 0xf0) != 0x40) + break; + + FlgIsIP = 1; + UserPriority = (Byte1 & 0xe0) >> 5; + QueIdx = MapUserPriorityToAccessCategory[UserPriority]; + + // TODO: have to check ACM bit. apply TSPEC if ACM is ON + // TODO: downgrade UP & QueIdx before passing ACM + if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) + { + UserPriority = 0; + QueIdx = QID_AC_BE; + } + } while (FALSE); + } + + RTMP_SET_PACKET_UP(pPacket, UserPriority); + + + + // Make sure SendTxWait queue resource won't be used by other threads + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) + { + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#ifdef BLOCK_NET_IF + StopNetIfQueue(pAd, QueIdx, pPacket); +#endif // BLOCK_NET_IF // + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + return NDIS_STATUS_FAILURE; + } + else + { + InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket)); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&& + IS_HT_STA(pEntry)) + { + //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; + if (((pEntry->TXBAbitmap & (1<BADeclineBitmap & (1<PortSecured == WPA_802_1X_PORT_SECURED) + // For IOT compatibility, if + // 1. It is Ralink chip or + // 2. It is OPEN or AES mode, + // then BA session can be bulit. + && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) || + (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled)) + ) + { + BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE); + } + } +#endif // DOT11_N_SUPPORT // + + pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed + return NDIS_STATUS_SUCCESS; +} + + +/* + ======================================================================== + + Routine Description: + This subroutine will scan through releative ring descriptor to find + out avaliable free ring descriptor and compare with request size. + + Arguments: + pAd Pointer to our adapter + QueIdx Selected TX Ring + + Return Value: + NDIS_STATUS_FAILURE Not enough free descriptor + NDIS_STATUS_SUCCESS Enough free descriptor + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ + +#ifdef RT2870 +/* + Actually, this function used to check if the TxHardware Queue still has frame need to send. + If no frame need to send, go to sleep, else, still wake up. +*/ +NDIS_STATUS RTMPFreeTXDRequest( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN UCHAR NumberRequired, + IN PUCHAR FreeNumberIs) +{ + //ULONG FreeNumber = 0; + NDIS_STATUS Status = NDIS_STATUS_FAILURE; + unsigned long IrqFlags; + HT_TX_CONTEXT *pHTTXContext; + + switch (QueIdx) + { + case QID_AC_BK: + case QID_AC_BE: + case QID_AC_VI: + case QID_AC_VO: + case QID_HCCA: + { + pHTTXContext = &pAd->TxContext[QueIdx]; + RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) || + (pHTTXContext->IRPPending == TRUE)) + { + Status = NDIS_STATUS_FAILURE; + } + else + { + Status = NDIS_STATUS_SUCCESS; + } + RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); + } + break; + + case QID_MGMT: + if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE) + Status = NDIS_STATUS_FAILURE; + else + Status = NDIS_STATUS_SUCCESS; + break; + + default: + DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx)); + break; + } + + return (Status); + +} +#endif // RT2870 // + + +VOID RTMPSendDisassociationFrame( + IN PRTMP_ADAPTER pAd) +{ +} + +VOID RTMPSendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull) +{ + UCHAR NullFrame[48]; + ULONG Length; + PHEADER_802_11 pHeader_802_11; + + +#ifdef RALINK_ATE + if(ATE_ON(pAd)) + { + return; + } +#endif // RALINK_ATE // + + // WPA 802.1x secured port control + if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef WPA_SUPPLICANT_SUPPORT + || (pAd->StaCfg.IEEE8021X == TRUE) +#endif + ) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + return; + } + + NdisZeroMemory(NullFrame, 48); + Length = sizeof(HEADER_802_11); + + pHeader_802_11 = (PHEADER_802_11) NullFrame; + + pHeader_802_11->FC.Type = BTYPE_DATA; + pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC; + pHeader_802_11->FC.ToDs = 1; + COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + + if (pAd->CommonCfg.bAPSDForcePowerSave) + { + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + } + else + { + pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0; + } + pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); + + pAd->Sequence++; + pHeader_802_11->Sequence = pAd->Sequence; + + // Prepare QosNull function frame + if (bQosNull) + { + pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL; + + // copy QOS control bytes + NullFrame[Length] = 0; + NullFrame[Length+1] = 0; + Length += 2;// if pad with 2 bytes for alignment, APSD will fail + } + + HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length); + +} + +// IRQL = DISPATCH_LEVEL +VOID RTMPSendRTSFrame( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN unsigned int NextMpduSize, + IN UCHAR TxRate, + IN UCHAR RTSRate, + IN USHORT AckDuration, + IN UCHAR QueIdx, + IN UCHAR FrameGap) +{ +} + + + +// -------------------------------------------------------- +// FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM +// Find the WPA key, either Group or Pairwise Key +// LEAP + TKIP also use WPA key. +// -------------------------------------------------------- +// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst +// In Cisco CCX 2.0 Leap Authentication +// WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey +// Instead of the SharedKey, SharedKey Length may be Zero. +VOID STAFindCipherAlgorithm( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet + UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm + UCHAR KeyIdx = 0xff; + PUCHAR pSrcBufVA; + PCIPHER_KEY pKey = NULL; + + pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket); + + { + // Select Cipher + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) + Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast + else + Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast + + if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + { + ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128); + + // 4-way handshaking frame must be clear + if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) && + (pAd->SharedKey[BSS0][0].KeyLen)) + { + CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + KeyIdx = 0; + } + } + else if (Cipher == Ndis802_11Encryption1Enabled) + { +#ifdef LEAP_SUPPORT + if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on + { + if (LEAP_CCKM_ON(pAd)) + { + if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))) + KeyIdx = 1; + else + KeyIdx = 0; + } + else + KeyIdx = pAd->StaCfg.DefaultKeyId; + } + else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC + KeyIdx = pAd->StaCfg.DefaultKeyId; + else if (LEAP_CCKM_ON(pAd)) + { + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) + KeyIdx = 1; + else + KeyIdx = 0; + } + else // standard WEP64 or WEP128 +#endif // LEAP_SUPPORT // + KeyIdx = pAd->StaCfg.DefaultKeyId; + } + else if ((Cipher == Ndis802_11Encryption2Enabled) || + (Cipher == Ndis802_11Encryption3Enabled)) + { + if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast + KeyIdx = pAd->StaCfg.DefaultKeyId; + else if (pAd->SharedKey[BSS0][0].KeyLen) + KeyIdx = 0; + else + KeyIdx = pAd->StaCfg.DefaultKeyId; + } + + if (KeyIdx == 0xff) + CipherAlg = CIPHER_NONE; + else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0)) + CipherAlg = CIPHER_NONE; +#ifdef WPA_SUPPLICANT_SUPPORT + else if ( pAd->StaCfg.WpaSupplicantUP && + (Cipher == Ndis802_11Encryption1Enabled) && + (pAd->StaCfg.IEEE8021X == TRUE) && + (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + CipherAlg = CIPHER_NONE; +#endif // WPA_SUPPLICANT_SUPPORT // + else + { + //Header_802_11.FC.Wep = 1; + CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + pKey = &pAd->SharedKey[BSS0][KeyIdx]; + } + } + + pTxBlk->CipherAlg = CipherAlg; + pTxBlk->pKey = pKey; +} + + +VOID STABuildCommon802_11Header( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + + HEADER_802_11 *pHeader_802_11; +#ifdef QOS_DLS_SUPPORT + BOOLEAN bDLSFrame = FALSE; + INT DlsEntryIndex = 0; +#endif // QOS_DLS_SUPPORT // + + // + // MAKE A COMMON 802.11 HEADER + // + + // normal wlan header size : 24 octets + pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + + pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + + NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11)); + + pHeader_802_11->FC.FrDs = 0; + pHeader_802_11->FC.Type = BTYPE_DATA; + pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA); + +#ifdef QOS_DLS_SUPPORT + if (INFRA_ON(pAd)) + { + // Check if the frame can be sent through DLS direct link interface + // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) + DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); + if (DlsEntryIndex >= 0) + bDLSFrame = TRUE; + else + bDLSFrame = FALSE; + } +#endif // QOS_DLS_SUPPORT // + + if (pTxBlk->pMacEntry) + { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) + { + pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq; + pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ; + } + else + { +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) + { + pHeader_802_11->Sequence = pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence; + pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence = (pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence+1) & MAXSEQ; + } + else +#endif // QOS_DLS_SUPPORT // + { + pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]; + pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + } + } + } + else + { + pHeader_802_11->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence + } + + pHeader_802_11->Frag = 0; + + pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + { + if (INFRA_ON(pAd)) + { +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) + { + COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + pHeader_802_11->FC.ToDs = 0; + } + else +#endif // QOS_DLS_SUPPORT // + { + COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader); + pHeader_802_11->FC.ToDs = 1; + } + } + else if (ADHOC_ON(pAd)) + { + COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); + pHeader_802_11->FC.ToDs = 0; + } + } + + if (pTxBlk->CipherAlg != CIPHER_NONE) + pHeader_802_11->FC.Wep = 1; + + // ----------------------------------------------------------------- + // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. + // ----------------------------------------------------------------- + if (pAd->CommonCfg.bAPSDForcePowerSave) + pHeader_802_11->FC.PwrMgmt = PWR_SAVE; + else + pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); +} + +#ifdef DOT11_N_SUPPORT +VOID STABuildCache802_11Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR *pHeader) +{ + MAC_TABLE_ENTRY *pMacEntry; + PHEADER_802_11 pHeader80211; + + pHeader80211 = (PHEADER_802_11)pHeader; + pMacEntry = pTxBlk->pMacEntry; + + // + // Update the cached 802.11 HEADER + // + + // normal wlan header size : 24 octets + pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + + // More Bit + pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + // Sequence + pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority]; + pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + + { + // Check if the frame can be sent through DLS direct link interface + // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) +#ifdef QOS_DLS_SUPPORT + BOOLEAN bDLSFrame = FALSE; + INT DlsEntryIndex = 0; + + DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader); + if (DlsEntryIndex >= 0) + bDLSFrame = TRUE; + else + bDLSFrame = FALSE; +#endif // QOS_DLS_SUPPORT // + + // The addr3 of normal packet send from DS is Dest Mac address. +#ifdef QOS_DLS_SUPPORT + if (bDLSFrame) + { + COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid); + pHeader80211->FC.ToDs = 0; + } + else +#endif // QOS_DLS_SUPPORT // + if (ADHOC_ON(pAd)) + COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid); + else + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader); + } + + // ----------------------------------------------------------------- + // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. + // ----------------------------------------------------------------- + if (pAd->CommonCfg.bAPSDForcePowerSave) + pHeader80211->FC.PwrMgmt = PWR_SAVE; + else + pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE); +} +#endif // DOT11_N_SUPPORT // + +static inline PUCHAR STA_Build_ARalink_Frame_Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + HEADER_802_11 *pHeader_802_11; + PNDIS_PACKET pNextPacket; + UINT32 nextBufLen; + PQUEUE_ENTRY pQEntry; + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + // steal "order" bit to mark "aggregation" + pHeader_802_11->FC.Order = 1; + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + } + + // padding at front of LLC header. LLC header should at 4-bytes aligment. + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + // For RA Aggregation, + // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format + pQEntry = pTxBlk->TxPacketList.Head; + pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry); + nextBufLen = GET_OS_PKT_LEN(pNextPacket); + if (RTMP_GET_PACKET_VLAN(pNextPacket)) + nextBufLen -= LENGTH_802_1Q; + + *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff; + *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8); + + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + + return pHeaderBufPtr; + +} + +#ifdef DOT11_N_SUPPORT +static inline PUCHAR STA_Build_AMSDU_Frame_Header( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr;//, pSaveBufPtr; + HEADER_802_11 *pHeader_802_11; + + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + + // + // A-MSDU packet + // + *pHeaderBufPtr |= 0x80; + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + + //pSaveBufPtr = pHeaderBufPtr; + + // + // padding at front of LLC header + // LLC header should locate at 4-octets aligment + // + // @@@ MpduHeaderLen excluding padding @@@ + // + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + return pHeaderBufPtr; + +} + + +VOID STA_AMPDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + MAC_TABLE_ENTRY *pMacEntry; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + + ASSERT(pTxBlk); + + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + pMacEntry = pTxBlk->pMacEntry; + if (pMacEntry->isCached) + { + // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!! + NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11)); + pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]); + STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr); + } + else + { + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + } + + + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + + // + // build HTC+ + // HTC control filed following QoS field + // + if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)) + { + if (pMacEntry->isCached == FALSE) + { + // mark HTC bit + pHeader_802_11->FC.Order = 1; + + NdisZeroMemory(pHeaderBufPtr, 4); + *(pHeaderBufPtr+3) |= 0x80; + } + pHeaderBufPtr += 4; + pTxBlk->MpduHeaderLen += 4; + } + + //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; + ASSERT(pTxBlk->MpduHeaderLen >= 24); + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + // + // padding at front of LLC header + // LLC header should locate at 4-octets aligment + // + // @@@ MpduHeaderLen excluding padding @@@ + // + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + { + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) + { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + + } + + if (pMacEntry->isCached) + { + RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } + else + { + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf)); + NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]))); + pMacEntry->isCached = TRUE; + } + + // calculate Transmitted AMPDU count and ByteCount + { + pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++; + pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; + } + + //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + } + +} + + +VOID STA_AMSDU_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding. + USHORT totalMPDUSize=0; + UCHAR *subFrameHeader; + UCHAR padding = 0; + USHORT FirstTx = 0, LastTxIdx = 0; + BOOLEAN bVLANPkt; + int frameNum = 0; + PQUEUE_ENTRY pQEntry; + + + ASSERT(pTxBlk); + + ASSERT((pTxBlk->TxPacketList.Number > 1)); + + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + if (frameNum == 0) + { + pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk); + + // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled. + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + } + else + { + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; + padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen); + NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD); + pHeaderBufPtr += padding; + pTxBlk->MpduHeaderLen = padding; + } + + // + // A-MSDU subframe + // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap + // + subFrameHeader = pHeaderBufPtr; + subFramePayloadLen = pTxBlk->SrcBufLen; + + NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12); + + + pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD; + pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD; + + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + + subFramePayloadLen = pTxBlk->SrcBufLen; + + if (pTxBlk->pExtraLlcSnapEncap) + { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + subFramePayloadLen += LENGTH_802_1_H; + } + + // update subFrame Length field + subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8; + subFrameHeader[13] = subFramePayloadLen & 0xFF; + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + if (frameNum ==0) + FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + else + LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + + frameNum++; + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + // calculate Transmitted AMSDU Count and ByteCount + { + pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++; + pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize; + } + + } + + HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); + HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} +#endif // DOT11_N_SUPPORT // + +VOID STA_Legacy_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + + ASSERT(pTxBlk); + + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) + { + INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); + } + + if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired); + else + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired); + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate) + pTxBlk->TxRate = pAd->CommonCfg.MinTxRate; + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr; + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + } + + // The remaining content of MPDU header should locate at 4-octets aligment + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + { + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + // + // if original Ethernet frame contains no LLC/SNAP, + // then an extra LLC/SNAP encap is required + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) + { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // skip vlan tag + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + + } + + // + // prepare for TXWI + // use Wcid as Key Index + // + + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} + + +VOID STA_ARalink_Frame_Tx( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + USHORT totalMPDUSize=0; + USHORT FirstTx, LastTxIdx; + int frameNum = 0; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + + + ASSERT(pTxBlk); + + ASSERT((pTxBlk->TxPacketList.Number== 2)); + + + FirstTx = LastTxIdx = 0; // Is it ok init they as 0? + while(pTxBlk->TxPacketList.Head) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + continue; + } + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + if (frameNum == 0) + { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header + + pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk); + + // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount + // will be updated after final frame was handled. + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap); + + if (pTxBlk->pExtraLlcSnapEncap) + { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + else + { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. + + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; + pTxBlk->MpduHeaderLen = 0; + + // A-Ralink sub-sequent frame header is the same as 802.3 header. + // DA(6)+SA(6)+FrameType(2) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12); + pHeaderBufPtr += 12; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD; + } + + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + + //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); + if (frameNum ==0) + FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + else + LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber); + + frameNum++; + + pAd->RalinkCounters.OneSecTxAggregationCount++; + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + } + + HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); + HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx); + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + +} + + +VOID STA_Fragment_Frame_Tx( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + HEADER_802_11 *pHeader_802_11; + PUCHAR pHeaderBufPtr; + USHORT FreeNumber; + UCHAR fragNum = 0; + PACKET_INFO PacketInfo; + USHORT EncryptionOverhead = 0; + UINT32 FreeMpduSize, SrcRemainingBytes; + USHORT AckDuration; + UINT NextMpduSize; + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + + + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + + ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag)); + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + STAFindCipherAlgorithm(pAd, pTxBlk); + STABuildCommon802_11Header(pAd, pTxBlk); + + if (pTxBlk->CipherAlg == CIPHER_TKIP) + { + pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket); + if (pTxBlk->pPacket == NULL) + return; + RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + } + + // skip 802.3 header + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + + // skip vlan tag + if (bVLANPkt) + { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]; + pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr; + + + // skip common header + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + // + // build QOS Control bytes + // + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); + + *(pHeaderBufPtr+1) = 0; + pHeaderBufPtr +=2; + pTxBlk->MpduHeaderLen += 2; + } + + // + // padding at front of LLC header + // LLC header should locate at 4-octets aligment + // + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + + + + // + // Insert LLC-SNAP encapsulation - 8 octets + // + // + // if original Ethernet frame contains no LLC/SNAP, + // then an extra LLC/SNAP encap is required + // + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) + { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + // skip vlan tag + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + // get 2 octets (TypeofLen) + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + + + // If TKIP is used and fragmentation is required. Driver has to + // append TKIP MIC at tail of the scatter buffer + // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC + if (pTxBlk->CipherAlg == CIPHER_TKIP) + { + + // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust + // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. + NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8); + //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); + pTxBlk->SrcBufLen += 8; + pTxBlk->TotalFrameLen += 8; + pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC; + } + + // + // calcuate the overhead bytes that encryption algorithm may add. This + // affects the calculate of "duration" field + // + if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128)) + EncryptionOverhead = 8; //WEP: IV[4] + ICV[4]; + else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC) + EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength + else if (pTxBlk->CipherAlg == CIPHER_TKIP) + EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] + else if (pTxBlk->CipherAlg == CIPHER_AES) + EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8] + else + EncryptionOverhead = 0; + + // decide how much time an ACK/CTS frame will consume in the air + AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14); + + // Init the total payload length of this frame. + SrcRemainingBytes = pTxBlk->SrcBufLen; + + pTxBlk->TotalFragNum = 0xff; + + do { + + FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC; + + FreeMpduSize -= pTxBlk->MpduHeaderLen; + + if (SrcRemainingBytes <= FreeMpduSize) + { // this is the last or only fragment + + pTxBlk->SrcBufLen = SrcRemainingBytes; + + pHeader_802_11->FC.MoreFrag = 0; + pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration; + + // Indicate the lower layer that this's the last fragment. + pTxBlk->TotalFragNum = fragNum; + } + else + { // more fragment is required + + pTxBlk->SrcBufLen = FreeMpduSize; + + NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold)); + pHeader_802_11->FC.MoreFrag = 1; + pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead); + } + + if (fragNum == 0) + pTxBlk->FrameGap = IFS_HTTXOP; + else + pTxBlk->FrameGap = IFS_SIFS; + + RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk); + + HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + // Update the frame number, remaining size of the NDIS packet payload. + + // space for 802.11 header. + if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap) + pTxBlk->MpduHeaderLen -= LENGTH_802_1_H; + + fragNum++; + SrcRemainingBytes -= pTxBlk->SrcBufLen; + pTxBlk->pSrcBufData += pTxBlk->SrcBufLen; + + pHeader_802_11->Frag++; // increase Frag # + + }while(SrcRemainingBytes > 0); + + // + // Kick out Tx + // + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} + + +#define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \ + while(_pTxBlk->TxPacketList.Head) \ + { \ + _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \ + RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \ + } + + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware encryption before really + sent out to air. + + Arguments: + pAd Pointer to our adapter + PNDIS_PACKET Pointer to outgoing Ndis frame + NumberOfFrag Number of fragment required + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS STAHardTransmit( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk, + IN UCHAR QueIdx) +{ + NDIS_PACKET *pPacket; + PQUEUE_ENTRY pQEntry; + + // --------------------------------------------- + // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. + // --------------------------------------------- + // + ASSERT(pTxBlk->TxPacketList.Number); + if (pTxBlk->TxPacketList.Head == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number)); + return NDIS_STATUS_FAILURE; + } + + pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head); + + // ------------------------------------------------------------------ + // STEP 1. WAKE UP PHY + // outgoing frame always wakeup PHY to prevent frame lost and + // turn off PSM bit to improve performance + // ------------------------------------------------------------------ + // not to change PSM bit, just send this frame out? + if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n")); + AsicForceWakeup(pAd, TRUE); + } + + // It should not change PSM bit, when APSD turn on. + if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE)) + || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) + { + if ((pAd->StaCfg.Psm == PWR_SAVE) && + (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP)) + MlmeSetPsmBit(pAd, PWR_ACTIVE); + } + + switch (pTxBlk->TxFrameType) + { +#ifdef DOT11_N_SUPPORT + case TX_AMPDU_FRAME: + STA_AMPDU_Frame_Tx(pAd, pTxBlk); + break; + case TX_AMSDU_FRAME: + STA_AMSDU_Frame_Tx(pAd, pTxBlk); + break; +#endif // DOT11_N_SUPPORT // + case TX_LEGACY_FRAME: + STA_Legacy_Frame_Tx(pAd, pTxBlk); + break; + case TX_MCAST_FRAME: + STA_Legacy_Frame_Tx(pAd, pTxBlk); + break; + case TX_RALINK_FRAME: + STA_ARalink_Frame_Tx(pAd, pTxBlk); + break; + case TX_FRAG_FRAME: + STA_Fragment_Frame_Tx(pAd, pTxBlk); + break; + default: + { + // It should not happened! + DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n")); + while(pTxBlk->TxPacketList.Number) + { + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + } + break; + } + + return (NDIS_STATUS_SUCCESS); + +} + +ULONG HashBytesPolynomial(UCHAR *value, unsigned int len) +{ + unsigned char *word = value; + unsigned int ret = 0; + unsigned int i; + + for(i=0; i < len; i++) + { + int mod = i % 32; + ret ^=(unsigned int) (word[i]) << mod; + ret ^=(unsigned int) (word[i]) >> (32 - mod); + } + return ret; +} + +VOID Sta_Announce_or_Forward_802_3_Packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + if (TRUE + ) + { + announce_802_3_packet(pAd, pPacket); + } + else + { + // release packet + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } +} + diff --git a/drivers/staging/rt3070/sta/sanity.c b/drivers/staging/rt3070/sta/sanity.c new file mode 100644 index 000000000000..239872464bed --- /dev/null +++ b/drivers/staging/rt3070/sta/sanity.c @@ -0,0 +1,420 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + sanity.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 add WMM support +*/ +#include "../rt_config.h" + +extern UCHAR CISCO_OUI[]; + +extern UCHAR WPA_OUI[]; +extern UCHAR RSN_OUI[]; +extern UCHAR WME_INFO_ELEM[]; +extern UCHAR WME_PARM_ELEM[]; +extern UCHAR Ccx2QosInfo[]; +extern UCHAR RALINK_OUI[]; +extern UCHAR BROADCOM_OUI[]; + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeStartReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen) +{ + MLME_START_REQ_STRUCT *Info; + + Info = (MLME_START_REQ_STRUCT *)(Msg); + + if (Info->SsidLen > MAX_LEN_OF_SSID) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqSanity fail - wrong SSID length\n")); + return FALSE; + } + + *pSsidLen = Info->SsidLen; + NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT UCHAR *pCkipFlag) +{ + CHAR IeType, *Ptr; + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PEID_STRUCT pEid; + ULONG Length = 0; + + *pNewExtChannelOffset = 0xff; + *pHtCapabilityLen = 0; + *pAddHtInfoLen = 0; + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); + Length += 2; + NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); + Length += 2; + *pCkipFlag = 0; + *pExtRateLen = 0; + pEdcaParm->bValid = FALSE; + + if (*pStatus != MLME_SUCCESS) + return TRUE; + + NdisMoveMemory(pAid, &pFrame->Octet[4], 2); + Length += 2; + + // Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform + *pAid = (*pAid) & 0x3fff; // AID is low 14-bit + + // -- get supported rates from payload and advance the pointer + IeType = pFrame->Octet[6]; + *pSupRateLen = pFrame->Octet[7]; + if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n")); + return FALSE; + } + else + NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); + + Length = Length + 2 + *pSupRateLen; + + // many AP implement proprietary IEs in non-standard order, we'd better + // tolerate mis-ordered IEs to get best compatibility + pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)]; + + // get variable fields from payload and advance the pointer + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch (pEid->Eid) + { + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + } + break; + + case IE_HT_CAP: + case IE_HT_CAP2: + if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!! + { + NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE); + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + + *pHtCapabilityLen = SIZE_HT_CAP_IE; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n")); + } + + break; +#ifdef DOT11_N_SUPPORT + case IE_ADD_HT: + case IE_ADD_HT2: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only + // copy first sizeof(ADD_HT_INFO_IE) + NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + + *(USHORT *)(&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo2)); + *(USHORT *)(&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo3)); + + *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n")); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *pNewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n")); + } +#endif // DOT11_N_SUPPORT // + break; + case IE_AIRONET_CKIP: + // 0. Check Aironet IE length, it must be larger or equal to 28 + // Cisco's AP VxWork version(will not be supported) used this IE length as 28 + // Cisco's AP IOS version used this IE length as 30 + if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) + break; + + // 1. Copy CKIP flag byte to buffer for process + *pCkipFlag = *(pEid->Octet + 8); + break; + + case IE_AIRONET_IPADDRESS: + if (pEid->Len != 0x0A) + break; + + // Get Cisco Aironet IP information + if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) + NdisMoveMemory(pAd->StaCfg.AironetIPAddress, pEid->Octet + 4, 4); + break; + + // CCX2, WMM use the same IE value + // case IE_CCX_V2: + case IE_VENDOR_SPECIFIC: + // handle WME PARAMTER ELEMENT + if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + // parsing EDCA parameters + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10; + pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20; + pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40; + //pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80; + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN + pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin + pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax + pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us + ptr += 4; // point to next AC + } + } + + // handle CCX IE + else + { + // 0. Check the size and CCX admin control + if (pAd->StaCfg.CCXControl.field.Enable == 0) + break; + if (pEid->Len != 5) + break; + + // Turn CCX2 if matched + if (NdisEqualMemory(pEid->Octet, Ccx2IeInfo, 5) == 1) + pAd->StaCfg.CCXEnable = TRUE; + break; + } + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + // Force CCX2 enable to TRUE for those AP didn't replay CCX v2 IE, we still force it to be on + if (pAd->StaCfg.CCXControl.field.Enable == 1) + pAd->StaCfg.CCXEnable = TRUE; + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen) +{ + UCHAR Idx; + UCHAR RateLen; + CHAR IeType; + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + + if ((pFrame->Octet[0] != IE_SSID) || (pFrame->Octet[1] > MAX_LEN_OF_SSID)) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n",pFrame->Octet[0],pFrame->Octet[1])); + return FALSE; + } + + *pSsidLen = pFrame->Octet[1]; + NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen); + + Idx = *pSsidLen + 2; + + // -- get supported rates from payload and advance the pointer + IeType = pFrame->Octet[Idx]; + RateLen = pFrame->Octet[Idx + 1]; + if (IeType != IE_SUPP_RATES) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n",pFrame->Octet[Idx],pFrame->Octet[Idx+1])); + return FALSE; + } + else + { + if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8)) + return (FALSE); + } + + return TRUE; +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN GetTimBit( + IN CHAR *Ptr, + IN USHORT Aid, + OUT UCHAR *TimLen, + OUT UCHAR *BcastFlag, + OUT UCHAR *DtimCount, + OUT UCHAR *DtimPeriod, + OUT UCHAR *MessageToMe) +{ + UCHAR BitCntl, N1, N2, MyByte, MyBit; + CHAR *IdxPtr; + + IdxPtr = Ptr; + + IdxPtr ++; + *TimLen = *IdxPtr; + + // get DTIM Count from TIM element + IdxPtr ++; + *DtimCount = *IdxPtr; + + // get DTIM Period from TIM element + IdxPtr++; + *DtimPeriod = *IdxPtr; + + // get Bitmap Control from TIM element + IdxPtr++; + BitCntl = *IdxPtr; + + if ((*DtimCount == 0) && (BitCntl & 0x01)) + *BcastFlag = TRUE; + else + *BcastFlag = FALSE; + + // Parse Partial Virtual Bitmap from TIM element + N1 = BitCntl & 0xfe; // N1 is the first bitmap byte# + N2 = *TimLen - 4 + N1; // N2 is the last bitmap byte# + + if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3))) + *MessageToMe = FALSE; + else + { + MyByte = (Aid >> 3) - N1; // my byte position in the bitmap byte-stream + MyBit = Aid % 16 - ((MyByte & 0x01)? 8:0); + + IdxPtr += (MyByte + 1); + + //if (*IdxPtr) + // DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr)); + + if (*IdxPtr & (0x01 << MyBit)) + *MessageToMe = TRUE; + else + *MessageToMe = FALSE; + } + + return TRUE; +} + diff --git a/drivers/staging/rt3070/sta/sync.c b/drivers/staging/rt3070/sta/sync.c new file mode 100644 index 000000000000..2b5b3b07661d --- /dev/null +++ b/drivers/staging/rt3070/sta/sync.c @@ -0,0 +1,1755 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + sync.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 modified for rt2561/2661 + Jan Lee 2006-08-01 modified for rt2860 for 802.11n +*/ +#include "../rt_config.h" + +#define ADHOC_ENTRY_BEACON_LOST_TIME (2*OS_HZ) // 2 sec + +/* + ========================================================================== + Description: + The sync state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + + ========================================================================== + */ +VOID SyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE); + + // column 1 + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon); + StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction); + + //column 2 + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction); + StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction); + + // column 3 + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction); + StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction); + + // timer init + RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE); +} + +/* + ========================================================================== + Description: + Beacon timeout handler, executed in timer thread + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID BeaconTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n")); + + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return; + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.BBPCurrentBW == BW_40) + ) + { + UCHAR BBPValue = 0; + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + BBPValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr)); + } +#endif // DOT11_N_SUPPORT // + + MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL); + RT28XX_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Scan timeout handler, executed in timer thread + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID ScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + + // Do nothing if the driver is starting halt state. + // This might happen when timer already been fired before cancel timer with mlmehalt + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return; + + if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL)) + { + RT28XX_MLME_HANDLER(pAd); + } + else + { + // To prevent SyncMachine.CurrState is SCAN_LISTEN forever. + pAd->MlmeAux.Channel = 0; + ScanNextChannel(pAd); + if (pAd->CommonCfg.bWirelessEvent) + { + RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + } + } +} + +/* + ========================================================================== + Description: + MLME SCAN req state machine procedure + ========================================================================== + */ +VOID MlmeScanReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0; + BOOLEAN TimerCancelled; + ULONG Now; + USHORT Status; + PHEADER_802_11 pHdr80211; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + + // Check the total scan tries for one single OID command + // If this is the CCX 2.0 Case, skip that! + if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n")); + return; + } + + // Increase the scan retry counters. + pAd->StaCfg.ScanCnt++; + + + // first check the parameter sanity + if (MlmeScanReqSanity(pAd, + Elem->Msg, + Elem->MsgLen, + &BssType, + Ssid, + &SsidLen, + &ScanType)) + { + + // Check for channel load and noise hist request + // Suspend MSDU only at scan request, not the last two mentioned + if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD)) + { + if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) + RTMPSuspendMsduTransmission(pAd); // Suspend MSDU transmission here + } + else + { + // Suspend MSDU transmission here + RTMPSuspendMsduTransmission(pAd); + } + + // + // To prevent data lost. + // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress. + // And should send an NULL data with turned PSM bit off to AP, when scan progress done + // + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd))) + { + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) + { + pHdr80211 = (PHEADER_802_11) pOutBuffer; + MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); + pHdr80211->Duration = 0; + pHdr80211->FC.Type = BTYPE_DATA; + pHdr80211->FC.PwrMgmt = PWR_SAVE; + + // Send using priority queue + MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n")); + MlmeFreeMemory(pAd, pOutBuffer); + RTMPusecDelay(5000); + } + } + + NdisGetSystemUpTime(&Now); + pAd->StaCfg.LastScanTime = Now; + // reset all the timers + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + + // record desired BSS parameters + pAd->MlmeAux.BssType = BssType; + pAd->MlmeAux.ScanType = ScanType; + pAd->MlmeAux.SsidLen = SsidLen; + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + + // start from the first channel + pAd->MlmeAux.Channel = FirstChannel(pAd); + + // Change the scan channel when dealing with CCX beacon report + if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) || + (ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE)) + pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel; + + // Let BBP register at 20MHz to do scan + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + ScanNextChannel(pAd); + } + else + { + DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); + } +} + +/* + ========================================================================== + Description: + MLME JOIN req state machine procedure + ========================================================================== + */ +VOID MlmeJoinReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR BBPValue = 0; + BSS_ENTRY *pBss; + BOOLEAN TimerCancelled; + HEADER_802_11 Hdr80211; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + PUCHAR pSupRate = NULL; + UCHAR SupRateLen; + PUCHAR pExtRate = NULL; + UCHAR ExtRateLen; + UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C}; + UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR); + MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx)); + + + // reset all the timers + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx]; + + // record the desired SSID & BSSID we're waiting for + COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid); + + // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again. + if (pBss->Hidden == 0) + { + NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen); + pAd->MlmeAux.SsidLen = pBss->SsidLen; + } + + pAd->MlmeAux.BssType = pBss->BssType; + pAd->MlmeAux.Channel = pBss->Channel; + pAd->MlmeAux.CentralChannel = pBss->CentralChannel; + +#ifdef EXT_BUILD_CHANNEL_LIST + // Country IE of the AP will be evaluated and will be used. + if ((pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None) && + (pBss->bHasCountryIE == TRUE)) + { + NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pBss->CountryString[0], 2); + if (pBss->CountryString[2] == 'I') + pAd->CommonCfg.Geography = IDOR; + else if (pBss->CountryString[2] == 'O') + pAd->CommonCfg.Geography = ODOR; + else + pAd->CommonCfg.Geography = BOTH; + BuildChannelListEx(pAd); + } +#endif // EXT_BUILD_CHANNEL_LIST // + + // Let BBP register at 20MHz to do scan + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue); + BBPValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + + // switch channel and waiting for beacon timer + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT); + + do + { + if (((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->MlmeAux.Channel > 14) && + RadarChannelCheck(pAd, pAd->MlmeAux.Channel)) +#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier + || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) +#endif // CARRIER_DETECTION_SUPPORT // + ) + { + // + // We can't send any Probe request frame to meet 802.11h. + // + if (pBss->Hidden == 0) + break; + } + + // + // send probe request + // + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus == NDIS_STATUS_SUCCESS) + { + if (pAd->MlmeAux.Channel <= 14) + { + pSupRate = pAd->CommonCfg.SupRate; + SupRateLen = pAd->CommonCfg.SupRateLen; + pExtRate = pAd->CommonCfg.ExtRate; + ExtRateLen = pAd->CommonCfg.ExtRateLen; + } + else + { + // + // Overwrite Support Rate, CCK rate are not allowed + // + pSupRate = ASupRate; + SupRateLen = ASupRateLen; + ExtRateLen = 0; + } + + if (pAd->MlmeAux.BssType == BSS_INFRA) + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid); + else + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &pAd->MlmeAux.SsidLen, + pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &SupRateLen, + SupRateLen, pSupRate, + END_OF_ARGS); + + if (ExtRateLen) + { + ULONG Tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &ExtRateLen, + ExtRateLen, pExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } + + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + } while (FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n", + pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5])); + + pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON; +} + +/* + ========================================================================== + Description: + MLME START Request state machine procedure, starting an IBSS + ========================================================================== + */ +VOID MlmeStartReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen; + BOOLEAN TimerCancelled; + + // New for WPA security suites + UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + LARGE_INTEGER TimeStamp; + BOOLEAN Privacy; + USHORT Status; + + // Init Variable IE structure + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + TimeStamp.u.LowPart = 0; + TimeStamp.u.HighPart = 0; + + if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen)) + { + // reset all the timers + RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + // + // Start a new IBSS. All IBSS parameters are decided now.... + // + DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n")); + pAd->MlmeAux.BssType = BSS_ADHOC; + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + pAd->MlmeAux.SsidLen = SsidLen; + + // generate a radom number as BSSID + MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid); + DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n")); + + Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0); + pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod; + pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin; + pAd->MlmeAux.Channel = pAd->CommonCfg.Channel; + + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel; + + pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo); + pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE); + // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here. + DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n")); + } + else +#endif // DOT11_N_SUPPORT // + { + pAd->MlmeAux.HtCapabilityLen = 0; + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + } + // temporarily not support QOS in IBSS + NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + + AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE); + AsicLockChannel(pAd, pAd->MlmeAux.Channel); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n", + pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); + + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); + } + else + { + DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); + } +} + +/* + ========================================================================== + Description: + peer sends beacon back when scanning + ========================================================================== + */ +VOID PeerBeaconAtScanAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel, + SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe; + CF_PARM CfParm; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; + PFRAME_802_11 pFrame; + LARGE_INTEGER TimeStamp; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + USHORT LenVIE; + UCHAR CkipFlag; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; + UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + + + // NdisFillMemory(Ssid, MAX_LEN_OF_SSID, 0x00); + pFrame = (PFRAME_802_11) Elem->Msg; + // Init Variable IE structure + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; +#ifdef DOT11_N_SUPPORT + RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); + RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); +#endif // DOT11_N_SUPPORT // + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &CfParm, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + &HtCapability, + &AddHtInfoLen, + &AddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE)) + { + ULONG Idx; + CHAR Rssi = 0; + + Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); + if (Idx != BSS_NOT_FOUND) + Rssi = pAd->ScanTab.BssEntry[Idx].Rssi; + + Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + +#ifdef DOT11_N_SUPPORT + if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) + HtCapabilityLen = SIZE_HT_CAP_IE; +#endif // DOT11_N_SUPPORT // + if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel)) + { + Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability, + &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, + &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); + if (Idx != BSS_NOT_FOUND) + { + NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ) + AironetAddBeaconReport(pAd, Idx, Elem); + } + } + else + { + Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, + &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag, + &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pAd->ChannelList[pAd->CommonCfg.ChannelListIdx].bEffectedChannel == TRUE) + { + UCHAR RegClass; + PeerBeaconAndProbeRspSanity2(pAd, Elem->Msg, Elem->MsgLen, &RegClass); + TriEventTableSetEntry(pAd, &pAd->CommonCfg.TriggerEventTab, Bssid, &HtCapability, HtCapabilityLen, RegClass, Channel); + } +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + if (Idx != BSS_NOT_FOUND) + { + NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + } + } + } + // sanity check fail, ignored +} + +/* + ========================================================================== + Description: + When waiting joining the (I)BSS, beacon received from external + ========================================================================== + */ +VOID PeerBeaconAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe, + DtimCount, DtimPeriod, BcastFlag, NewChannel; + LARGE_INTEGER TimeStamp; + USHORT BeaconPeriod, AtimWin, CapabilityInfo; + CF_PARM Cf; + BOOLEAN TimerCancelled; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + USHORT LenVIE; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + USHORT Status; + UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + ULONG RalinkIe; + ULONG Idx; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; +#ifdef DOT11_N_SUPPORT + UCHAR CentralChannel; +#endif // DOT11_N_SUPPORT // + + // Init Variable IE structure + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); + RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); + + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &Cf, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + &HtCapability, + &AddHtInfoLen, + &AddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE)) + { + // Disqualify 11b only adhoc when we are in 11g only adhoc mode + if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12)) + return; + + // BEACON from desired BSS/IBSS found. We should be able to decide most + // BSS parameters here. + // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION? + // Do we need to receover back all parameters belonging to previous BSS? + // A. Should be not. There's no back-door recover to previous AP. It still need + // a new JOIN-AUTH-ASSOC sequence. + if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel)); + RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled); + + // Update RSSI to prevent No signal display when cards first initialized + pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0); + pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1); + pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2); + pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0; + pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3; + pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1; + pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3; + pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2; + pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3; + + // + // We need to check if SSID only set to any, then we can record the current SSID. + // Otherwise will cause hidden SSID association failed. + // + if (pAd->MlmeAux.SsidLen == 0) + { + NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen); + pAd->MlmeAux.SsidLen = SsidLen; + } + else + { + Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel); + + if (Idx != BSS_NOT_FOUND) + { + // + // Multiple SSID case, used correct CapabilityInfo + // + CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo; + } + } + NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN); + pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pAd->MlmeAux.BssType = BssType; + pAd->MlmeAux.BeaconPeriod = BeaconPeriod; + pAd->MlmeAux.Channel = Channel; + pAd->MlmeAux.AtimWin = AtimWin; + pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod; + pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration; + pAd->MlmeAux.APRalinkIe = RalinkIe; + + // Copy AP's supported rate to MlmeAux for creating assoication request + // Also filter out not supported rate + pAd->MlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen); + pAd->MlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen); + + NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16); +#ifdef DOT11_N_SUPPORT + pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; + pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen; + + // filter out un-supported ht rates + if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)) + { + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE); + + // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability + NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16); + pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset; + pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE; + pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE; + if (PreNHtCapabilityLen > 0) + pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE; + RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo); + // Copy AP Parameter to StaActive. This is also in LinkUp. + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n", + pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth)); + + if (AddHtInfoLen > 0) + { + CentralChannel = AddHtInfo.ControlChan; + // Check again the Bandwidth capability of this AP. + if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = AddHtInfo.ControlChan - 2; + } + else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + CentralChannel = AddHtInfo.ControlChan + 2; + } + + // Check Error . + if (pAd->MlmeAux.CentralChannel != CentralChannel) + DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel)); + + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan)); + + } + + } + else +#endif // DOT11_N_SUPPORT // + { + // To prevent error, let legacy AP must have same CentralChannel and Channel. + if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0)) + pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel; + + pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE; + RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); + } + + RTMPUpdateMlmeRate(pAd); + + // copy QOS related information + if ((pAd->CommonCfg.bWmmCapable) +#ifdef DOT11_N_SUPPORT + || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) +#endif // DOT11_N_SUPPORT // + ) + { + NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM)); + NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + else + { + NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", + pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen)); + +#ifdef LEAP_SUPPORT + // Update CkipFlag + pAd->StaCfg.CkipFlag = CkipFlag; + + // Keep TimeStamp for Re-Association used. + if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE)) + pAd->StaCfg.CCKMBeaconAtJoinTimeStamp = TimeStamp; +#endif // LEAP_SUPPORT // + + if (AironetCellPowerLimit != 0xFF) + { + //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power + ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); + } + else //Used the default TX Power Percentage. + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_SUCCESS; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); + } + // not to me BEACON, ignored + } + // sanity check fail, ignore this frame +} + +/* + ========================================================================== + Description: + receive BEACON from peer + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID PeerBeacon( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + CF_PARM CfParm; + UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0; + UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0; + USHORT CapabilityInfo, AtimWin, BeaconPeriod; + LARGE_INTEGER TimeStamp; + USHORT TbttNumToNextWakeUp; + UCHAR Erp; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen, ExtRateLen; + UCHAR CkipFlag; + USHORT LenVIE; + UCHAR AironetCellPowerLimit; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; + ULONG RalinkIe; + // New for WPA security suites + UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5 + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE + UCHAR HtCapabilityLen, PreNHtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif // RALINK_ATE // + + if (!(INFRA_ON(pAd) || ADHOC_ON(pAd) + )) + return; + + // Init Variable IE structure + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); + RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + Addr2, + Bssid, + Ssid, + &SsidLen, + &BssType, + &BeaconPeriod, + &Channel, + &NewChannel, + &TimeStamp, + &CfParm, + &AtimWin, + &CapabilityInfo, + &Erp, + &DtimCount, + &DtimPeriod, + &BcastFlag, + &MessageToMe, + SupRate, + &SupRateLen, + ExtRate, + &ExtRateLen, + &CkipFlag, + &AironetCellPowerLimit, + &EdcaParm, + &QbssLoad, + &QosCapability, + &RalinkIe, + &HtCapabilityLen, + &PreNHtCapabilityLen, + &HtCapability, + &AddHtInfoLen, + &AddHtInfo, + &NewExtChannelOffset, + &LenVIE, + pVIE)) + { + BOOLEAN is_my_bssid, is_my_ssid; + ULONG Bssidx, Now; + BSS_ENTRY *pBss; + CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); + + is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE; + is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE; + + + // ignore BEACON not for my SSID + if ((! is_my_ssid) && (! is_my_bssid)) + return; + + // It means STA waits disassoc completely from this AP, ignores this beacon. + if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC) + return; + +#ifdef DOT11_N_SUPPORT + // Copy Control channel for this BSSID. + if (AddHtInfoLen != 0) + Channel = AddHtInfo.ControlChan; + + if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) + HtCapabilityLen = SIZE_HT_CAP_IE; +#endif // DOT11_N_SUPPORT // + + // + // Housekeeping "SsidBssTab" table for later-on ROAMing usage. + // + Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); + if (Bssidx == BSS_NOT_FOUND) + { + // discover new AP of this network, create BSS entry + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, + &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel, + RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability, + &QbssLoad, LenVIE, pVIE); + if (Bssidx == BSS_NOT_FOUND) // return if BSS table full + return; + + NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + + + + } + + if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) + { + // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). + // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. + AsicSwitchChannel(pAd, 1, FALSE); + AsicLockChannel(pAd, 1); + LinkDown(pAd, FALSE); + MlmeQueueInit(&pAd->Mlme.Queue); + BssTableInit(&pAd->ScanTab); + RTMPusecDelay(1000000); // use delay to prevent STA do reassoc + + // channel sanity check + for (index = 0 ; index < pAd->ChannelListNum; index++) + { + if (pAd->ChannelList[index].Channel == NewChannel) + { + pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; + pAd->CommonCfg.Channel = NewChannel; + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); + break; + } + } + + if (index >= pAd->ChannelListNum) + { + DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); + } + } + + // if the ssid matched & bssid unmatched, we should select the bssid with large value. + // This might happened when two STA start at the same time + if ((! is_my_bssid) && ADHOC_ON(pAd)) + { + INT i; + + // Add the safeguard against the mismatch of adhoc wep status + if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Not matched wep status %d %d\n", pAd->StaCfg.WepStatus, pAd->ScanTab.BssEntry[Bssidx].WepStatus)); + DBGPRINT(RT_DEBUG_TRACE, ("bssid=%s\n", pAd->ScanTab.BssEntry[Bssidx].Bssid)); + return; + } + + // collapse into the ADHOC network which has bigger BSSID value. + for (i = 0; i < 6; i++) + { + if (Bssid[i] > pAd->CommonCfg.Bssid[i]) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + AsicDisableSync(pAd); + COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid); + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); + MakeIbssBeacon(pAd); // re-build BEACON frame + AsicEnableIbssSync(pAd); // copy BEACON frame to on-chip memory + is_my_bssid = TRUE; + break; + } + else if (Bssid[i] < pAd->CommonCfg.Bssid[i]) + break; + } + } + + + NdisGetSystemUpTime(&Now); + pBss = &pAd->ScanTab.BssEntry[Bssidx]; + pBss->Rssi = RealRssi; // lastest RSSI + pBss->LastBeaconRxTime = Now; // last RX timestamp + + // + // BEACON from my BSSID - either IBSS or INFRA network + // + if (is_my_bssid) + { + RXWI_STRUC RxWI; + + pAd->StaCfg.DtimCount = DtimCount; + pAd->StaCfg.DtimPeriod = DtimPeriod; + pAd->StaCfg.LastBeaconRxTime = Now; + + + RxWI.RSSI0 = Elem->Rssi0; + RxWI.RSSI1 = Elem->Rssi1; + RxWI.RSSI2 = Elem->Rssi2; + + Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI); + if (AironetCellPowerLimit != 0xFF) + { + // + // We get the Cisco (ccx) "TxPower Limit" required + // Changed to appropriate TxPower Limit for Ciso Compatible Extensions + // + ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); + } + else + { + // + // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist. + // Used the default TX Power Percentage, that set from UI. + // + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + } + + if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo))) + { + UCHAR MaxSupportedRateIn500Kbps = 0; + UCHAR idx; + MAC_TABLE_ENTRY *pEntry; + + // supported rates array may not be sorted. sort it and find the maximum rate + for (idx=0; idxWcid == RESERVED_WCID)) || + (pEntry && ((pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME) < Now))) + { + if (pEntry == NULL) + // Another adhoc joining, add to our MAC table. + pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE); + + if (StaAddMacTableEntry(pAd, pEntry, MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n")); + return; + } + + if (pEntry && + (Elem->Wcid == RESERVED_WCID)) + { + idx = pAd->StaCfg.DefaultKeyId; + RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry); + } + } + + if (pEntry && pEntry->ValidAsCLI) + pEntry->LastBeaconRxTime = Now; + + // At least another peer in this IBSS, declare MediaState as CONNECTED + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + + pAd->IndicateMediaState = NdisMediaStateConnected; + RTMP_IndicateMediaState(pAd); + pAd->ExtraInfo = GENERAL_LINK_UP; + AsicSetBssid(pAd, pAd->CommonCfg.Bssid); + + // 2003/03/12 - john + // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that + // "site survey" result should always include the current connected network. + // + Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); + if (Bssidx == BSS_NOT_FOUND) + { + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, + &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, + &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0, + &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); + } + DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); + } + } + + if (INFRA_ON(pAd)) + { + BOOLEAN bUseShortSlot, bUseBGProtection; + + // decide to use/change to - + // 1. long slot (20 us) or short slot (9 us) time + // 2. turn on/off RTS/CTS and/or CTS-to-self protection + // 3. short preamble + + //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo); + bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo); + if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) + AsicSetSlotTime(pAd, bUseShortSlot); + + bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use + ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp)); + + if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP + bUseBGProtection = FALSE; + + if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + if (bUseBGProtection) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); + } + else + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); + } + + DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection)); + } + +#ifdef DOT11_N_SUPPORT + // check Ht protection mode. and adhere to the Non-GF device indication by AP. + if ((AddHtInfoLen != 0) && + ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) || + (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent))) + { + pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent; + pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode; + if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) + { + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); + } + else + AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode)); + } +#endif // DOT11_N_SUPPORT // + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) && + ERP_IS_USE_BARKER_PREAMBLE(Erp)) + { + MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n")); + } + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && + (EdcaParm.bValid == TRUE) && + (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount)) + { + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n", + pAd->CommonCfg.APEdcaParm.EdcaUpdateCount, + EdcaParm.EdcaUpdateCount)); + AsicSetEdcaParm(pAd, &EdcaParm); + } + + // copy QOS related information + NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + + // only INFRASTRUCTURE mode support power-saving feature + if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave)) + { + UCHAR FreeNumber; + // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL + // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE + // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE + // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE + // 5. otherwise, put PHY back to sleep to save battery. + if (MessageToMe) + { + if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && + pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO) + { + pAd->CommonCfg.bNeedSendTriggerFrame = TRUE; + } + else + RT28XX_PS_POLL_ENQUEUE(pAd); + } + else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM)) + { + } + else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) || + (pAd->TxSwQueue[QID_AC_BE].Number != 0) || + (pAd->TxSwQueue[QID_AC_VI].Number != 0) || + (pAd->TxSwQueue[QID_AC_VO].Number != 0) || + (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || + (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)) + { + // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme + // can we cheat here (i.e. just check MGMT & AC_BE) for better performance? + } + else + { + USHORT NextDtim = DtimCount; + + if (NextDtim == 0) + NextDtim = DtimPeriod; + + TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) + TbttNumToNextWakeUp = NextDtim; + + if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); + } + } + } + } + // not my BSSID, ignore it + } + // sanity check fail, ignore this frame +} + +/* + ========================================================================== + Description: + Receive PROBE REQ from remote peer when operating in IBSS mode + ========================================================================== + */ +VOID PeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; +#ifdef DOT11_N_SUPPORT + UCHAR HtLen, AddHtLen, NewExtLen; +#endif // DOT11_N_SUPPORT // + HEADER_802_11 ProbeRspHdr; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + LARGE_INTEGER FakeTimestamp; + UCHAR DsLen = 1, IbssLen = 2; + UCHAR LocalErpIe[3] = {IE_ERP, 1, 0}; + BOOLEAN Privacy; + USHORT CapabilityInfo; + UCHAR RSNIe = IE_WPA; + + if (! ADHOC_ON(pAd)) + return; + + if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen)) + { + if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) + { + // allocate and send out ProbeRsp frame + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + //pAd->StaCfg.AtimWin = 0; // ?????? + + Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled); + CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ProbeRspHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &CapabilityInfo, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &pAd->StaActive.SupRateLen, + pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + 1, &IbssIe, + 1, &IbssLen, + 2, &pAd->StaActive.AtimWin, + END_OF_ARGS); + + if (pAd->StaActive.ExtRateLen) + { + ULONG tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 3, LocalErpIe, + 1, &ExtRateIe, + 1, &pAd->StaActive.ExtRateLen, + pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + + // If adhoc secruity is set for WPA-None, append the cipher suite IE + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + ULONG tmp; + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &pAd->StaCfg.RSNIE_Len, + pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE, + END_OF_ARGS); + FrameLen += tmp; + } +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + { + ULONG TmpLen; + UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; + HtLen = sizeof(pAd->CommonCfg.HtCapability); + AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); + NewExtLen = 1; + //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame + if (pAd->bBroadComHT == TRUE) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 4, &BROADCOM[0], + pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, + END_OF_ARGS); + } + else + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, + 1, &AddHtInfoIe, + 1, &AddHtLen, + sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, + 1, &NewExtChanIe, + 1, &NewExtLen, + sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset, + END_OF_ARGS); + } + FrameLen += TmpLen; + } +#endif // DOT11_N_SUPPORT // + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + } +} + +VOID BeaconTimeoutAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n")); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_REJ_TIMEOUT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + Scan timeout procedure. basically add channel index by 1 and rescan + ========================================================================== + */ +VOID ScanTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel); + + // Only one channel scanned for CISCO beacon request + if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) || + (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD)) + pAd->MlmeAux.Channel = 0; + + // this routine will stop if pAd->MlmeAux.Channel == 0 + ScanNextChannel(pAd); +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenScan( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenJoin( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID InvalidStateWhenStart( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT Status; + DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState)); + pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; + Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status); +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID EnqueuePsPoll( + IN PRTMP_ADAPTER pAd) +{ +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + return; + } +#endif // RALINK_ATE // + + + if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP) + pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE; + MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME)); +} + + +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID EnqueueProbeRequest( + IN PRTMP_ADAPTER pAd) +{ + NDIS_STATUS NState; + PUCHAR pOutBuffer; + ULONG FrameLen = 0; + HEADER_802_11 Hdr80211; + + DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); + + NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory + if (NState == NDIS_STATUS_SUCCESS) + { + MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR); + + // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &pAd->CommonCfg.SsidLen, + pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid, + 1, &SupRateIe, + 1, &pAd->StaActive.SupRateLen, + pAd->StaActive.SupRateLen, pAd->StaActive.SupRate, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + +} + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID BuildEffectedChannelList( + IN PRTMP_ADAPTER pAd) +{ + UCHAR EChannel[11]; + UCHAR i, j, k; + UCHAR UpperChannel = 0, LowerChannel = 0; + + RTMPZeroMemory(EChannel, 11); + i = 0; + // Find upper channel and lower channel. + if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) + { + UpperChannel = pAd->CommonCfg.Channel; + LowerChannel = pAd->CommonCfg.CentralChannel; + } + else if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) + { + UpperChannel = pAd->CommonCfg.CentralChannel; + LowerChannel = pAd->CommonCfg.Channel; + } + else + { + return; + } + + // Record channels that is below lower channel.. + if (LowerChannel > 1) + { + EChannel[0] = LowerChannel - 1; + i = 1; + if (LowerChannel > 2) + { + EChannel[1] = LowerChannel - 2; + i = 2; + if (LowerChannel > 3) + { + EChannel[2] = LowerChannel - 3; + i = 3; + } + } + } + // Record channels that is between lower channel and upper channel. + for (k = LowerChannel;k < UpperChannel;k++) + { + EChannel[i] = k; + i++; + } + // Record channels that is above upper channel.. + if (LowerChannel < 11) + { + EChannel[i] = UpperChannel + 1; + i++; + if (LowerChannel < 10) + { + EChannel[i] = LowerChannel + 2; + i++; + if (LowerChannel < 9) + { + EChannel[i] = LowerChannel + 3; + i++; + } + } + } + // + for (j = 0;j < i;j++) + { + for (k = 0;k < pAd->ChannelListNum;k++) + { + if (pAd->ChannelList[k].Channel == EChannel[j]) + { + pAd->ChannelList[k].bEffectedChannel = TRUE; + DBGPRINT(RT_DEBUG_TRACE,(" EffectedChannel( =%d)\n", EChannel[j])); + break; + } + } + } +} +#endif // DOT11N_DRAFT3 // +#endif // DOT11_N_SUPPORT // + +BOOLEAN ScanRunning( + IN PRTMP_ADAPTER pAd) +{ + return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE; +} + diff --git a/drivers/staging/rt3070/sta/wpa.c b/drivers/staging/rt3070/sta/wpa.c new file mode 100644 index 000000000000..63d08306bf6f --- /dev/null +++ b/drivers/staging/rt3070/sta/wpa.c @@ -0,0 +1,2099 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + wpa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 03-07-22 Initial + Paul Lin 03-11-28 Modify for supplicant +*/ +#include "../rt_config.h" + +#define WPARSNIE 0xdd +#define WPA2RSNIE 0x30 + +//extern UCHAR BIT8[]; +UCHAR CipherWpaPskTkip[] = { + 0xDD, 0x16, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x02, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x02 // authentication + }; +UCHAR CipherWpaPskTkipLen = (sizeof(CipherWpaPskTkip) / sizeof(UCHAR)); + +UCHAR CipherWpaPskAes[] = { + 0xDD, 0x16, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x04, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x04, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x02 // authentication + }; +UCHAR CipherWpaPskAesLen = (sizeof(CipherWpaPskAes) / sizeof(UCHAR)); + +UCHAR CipherSuiteCiscoCCKM[] = { + 0xDD, 0x16, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x40, 0x96, 0x01, // Multicast + 0x01, 0x00, // Number of uicast + 0x00, 0x40, 0x96, 0x01, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x40, 0x96, 0x00 // Authentication + }; +UCHAR CipherSuiteCiscoCCKMLen = (sizeof(CipherSuiteCiscoCCKM) / sizeof(UCHAR)); + +UCHAR CipherSuiteCiscoCCKM24[] = { + 0xDD, 0x18, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x40, 0x96, 0x01, // Multicast + 0x01, 0x00, // Number of uicast + 0x00, 0x40, 0x96, 0x01, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x40, 0x96, 0x00, + 0x28, 0x00// Authentication + }; + +UCHAR CipherSuiteCiscoCCKM24Len = (sizeof(CipherSuiteCiscoCCKM24) / sizeof(UCHAR)); + +UCHAR CipherSuiteCCXTkip[] = { + 0xDD, 0x16, // RSN IE + 0x00, 0x50, 0xf2, 0x01, // oui + 0x01, 0x00, // Version + 0x00, 0x50, 0xf2, 0x02, // Multicast + 0x01, 0x00, // Number of unicast + 0x00, 0x50, 0xf2, 0x02, // unicast + 0x01, 0x00, // number of authentication method + 0x00, 0x50, 0xf2, 0x01 // authentication + }; +UCHAR CipherSuiteCCXTkipLen = (sizeof(CipherSuiteCCXTkip) / sizeof(UCHAR)); + +UCHAR CCX_LLC_HDR[] = {0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02}; +UCHAR LLC_NORMAL[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}; + +UCHAR EAPOL_FRAME[] = {0x88, 0x8E}; + +BOOLEAN CheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + OUT UCHAR *Offset); + +void inc_byte_array(UCHAR *counter, int len); + +/* + ======================================================================== + + Routine Description: + Classify WPA EAP message type + + Arguments: + EAPType Value of EAP message type + MsgType Internal Message definition for MLME state machine + + Return Value: + TRUE Found appropriate message type + FALSE No appropriate message type + + IRQL = DISPATCH_LEVEL + + Note: + All these constants are defined in wpa.h + For supplicant, there is only EAPOL Key message avaliable + + ======================================================================== +*/ +BOOLEAN WpaMsgTypeSubst( + IN UCHAR EAPType, + OUT INT *MsgType) +{ + switch (EAPType) + { + case EAPPacket: + *MsgType = MT2_EAPPacket; + break; + case EAPOLStart: + *MsgType = MT2_EAPOLStart; + break; + case EAPOLLogoff: + *MsgType = MT2_EAPOLLogoff; + break; + case EAPOLKey: + *MsgType = MT2_EAPOLKey; + break; + case EAPOLASFAlert: + *MsgType = MT2_EAPOLASFAlert; + break; + default: + return FALSE; + } + return TRUE; +} + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + ========================================================================== + */ +VOID WpaPskStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, Trans, MAX_WPA_PSK_STATE, MAX_WPA_PSK_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PSK_IDLE, WPA_MACHINE_BASE); + StateMachineSetAction(S, WPA_PSK_IDLE, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction); +} + +/* + ========================================================================== + Description: + This is state machine function. + When receiving EAPOL packets which is for 802.1x key management. + Use both in WPA, and WPAPSK case. + In this function, further dispatch to different functions according to the received packet. 3 categories are : + 1. normal 4-way pairwisekey and 2-way groupkey handshake + 2. MIC error (Countermeasures attack) report packet from STA. + 3. Request for pairwise/group key update from STA + Return: + ========================================================================== +*/ +VOID WpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + INT MsgType = EAPOL_MSG_INVALID; + PKEY_DESCRIPTER pKeyDesc; + PHEADER_802_11 pHeader; //red + UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY]; + UCHAR EapolVr; + KEY_INFO peerKeyInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WpaEAPOLKeyAction\n")); + + // Get 802.11 header first + pHeader = (PHEADER_802_11) Elem->Msg; + + // Get EAPoL-Key Descriptor + pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)]; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pKeyDesc->KeyInfo, sizeof(KEY_INFO)); + + *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo)); + + + // 1. Check EAPOL frame version and type + EapolVr = (UCHAR) Elem->Msg[LENGTH_802_11+LENGTH_802_1_H]; + + if (((EapolVr != EAPOL_VER) && (EapolVr != EAPOL_VER2)) || ((pKeyDesc->Type != WPA1_KEY_DESC) && (pKeyDesc->Type != WPA2_KEY_DESC))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n")); + return; + } + + // First validate replay counter, only accept message with larger replay counter + // Let equal pass, some AP start with all zero replay counter + NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY); + + if((RTMPCompareMemory(pKeyDesc->ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) && + (RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0)) + { + DBGPRINT(RT_DEBUG_ERROR, (" ReplayCounter not match \n")); + return; + } + + // Process WPA2PSK frame + if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + { + if((peerKeyInfo.KeyType == PAIRWISEKEY) && + (peerKeyInfo.EKD_DL == 0) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 0) && + (peerKeyInfo.Secure == 0) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_PAIR_MSG_1; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n")); + } else if((peerKeyInfo.KeyType == PAIRWISEKEY) && + (peerKeyInfo.EKD_DL == 1) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Secure == 1) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_PAIR_MSG_3; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n")); + } else if((peerKeyInfo.KeyType == GROUPKEY) && + (peerKeyInfo.EKD_DL == 1) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Secure == 1) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_GROUP_MSG_1; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n")); + } + + // We will assume link is up (assoc suceess and port not secured). + // All state has to be able to process message from previous state + switch(pAd->StaCfg.WpaState) + { + case SS_START: + if(MsgType == EAPOL_PAIR_MSG_1) + { + Wpa2PairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + break; + + case SS_WAIT_MSG_3: + if(MsgType == EAPOL_PAIR_MSG_1) + { + Wpa2PairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + else if(MsgType == EAPOL_PAIR_MSG_3) + { + Wpa2PairMsg3Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_GROUP; + } + break; + + case SS_WAIT_GROUP: // When doing group key exchange + case SS_FINISH: // This happened when update group key + if(MsgType == EAPOL_PAIR_MSG_1) + { + // Reset port secured variable + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + Wpa2PairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + else if(MsgType == EAPOL_PAIR_MSG_3) + { + // Reset port secured variable + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + Wpa2PairMsg3Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_GROUP; + } + else if(MsgType == EAPOL_GROUP_MSG_1) + { + WpaGroupMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_FINISH; + } + break; + + default: + break; + } + } + // Process WPAPSK Frame + // Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant + else if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + { + if((peerKeyInfo.KeyType == PAIRWISEKEY) && + (peerKeyInfo.KeyIndex == 0) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 0) && + (peerKeyInfo.Secure == 0) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_PAIR_MSG_1; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n")); + } + else if((peerKeyInfo.KeyType == PAIRWISEKEY) && + (peerKeyInfo.KeyIndex == 0) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Secure == 0) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_PAIR_MSG_3; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n")); + } + else if((peerKeyInfo.KeyType == GROUPKEY) && + (peerKeyInfo.KeyIndex != 0) && + (peerKeyInfo.KeyAck == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Secure == 1) && + (peerKeyInfo.Error == 0) && + (peerKeyInfo.Request == 0)) + { + MsgType = EAPOL_GROUP_MSG_1; + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n")); + } + + // We will assume link is up (assoc suceess and port not secured). + // All state has to be able to process message from previous state + switch(pAd->StaCfg.WpaState) + { + case SS_START: + if(MsgType == EAPOL_PAIR_MSG_1) + { + WpaPairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + break; + + case SS_WAIT_MSG_3: + if(MsgType == EAPOL_PAIR_MSG_1) + { + WpaPairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + } + else if(MsgType == EAPOL_PAIR_MSG_3) + { + WpaPairMsg3Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_GROUP; + } + break; + + case SS_WAIT_GROUP: // When doing group key exchange + case SS_FINISH: // This happened when update group key + if(MsgType == EAPOL_PAIR_MSG_1) + { + WpaPairMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_MSG_3; + // Reset port secured variable + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + else if(MsgType == EAPOL_PAIR_MSG_3) + { + WpaPairMsg3Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_WAIT_GROUP; + // Reset port secured variable + pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + else if(MsgType == EAPOL_GROUP_MSG_1) + { + WpaGroupMsg1Action(pAd, Elem); + pAd->StaCfg.WpaState = SS_FINISH; + } + break; + + default: + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaEAPOLKeyAction\n")); +} + +/* + ======================================================================== + + Routine Description: + Process Pairwise key 4-way handshaking + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID WpaPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PHEADER_802_11 pHeader; + UCHAR *mpool, *PTK, *digest; + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + PEAPOL_PACKET pMsg1; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + + DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action ----->\n")); + + // allocate memory pool + os_alloc_mem(pAd, (PUCHAR *)&mpool, 256); + + if (mpool == NULL) + return; + + // PTK Len = 80. + PTK = (UCHAR *) ROUND_UP(mpool, 4); + // digest Len = 80. + digest = (UCHAR *) ROUND_UP(PTK + 80, 4); + + pHeader = (PHEADER_802_11) Elem->Msg; + + // Process message 1 from authenticator + pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + // 1. Save Replay counter, it will use to verify message 3 and construct message 2 + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 2. Save ANonce + NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + + // Generate random SNonce + GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce); + + // Calc PTK(ANonce, SNonce) + WpaCountPTK(pAd, + pAd->StaCfg.PMK, + pAd->StaCfg.ANonce, + pAd->CommonCfg.Bssid, + pAd->StaCfg.SNonce, + pAd->CurrentAddress, + PTK, + LEN_PTK); + + // Save key to PTK entry + NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK); + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero Message 2 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + // + // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE) + // + Packet.KeyDesc.Type = WPA1_KEY_DESC; + // 1. Key descriptor version and appropriate RSN IE + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 2; + } + else // TKIP + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 1; + } + + // fill in Data Material and its length + Packet.KeyDesc.KeyData[0] = IE_WPA; + Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len; + Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2; + NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); + + // Update packet length after decide Key data payload + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1]; + + // Update Key length + Packet.KeyDesc.KeyLength[0] = pMsg1->KeyDesc.KeyLength[0]; + Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1]; + // 2. Key Type PeerKey + Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // 3. KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + //Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + + // 4. Fill SNonce + NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE); + + // 5. Key Replay Count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Send EAPOL(0, 1, 0, 0, 0, P, 0, SNonce, MIC, RSN_IE) + // Out buffer for transmitting message 2 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + os_free_mem(pAd, mpool); + return; + } + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // 6. Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { // AES + + HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { // TKIP + hmac_md5(PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + //hex_dump("MIC", Mic, LEN_KEY_DESC_MIC); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // 5. Copy frame to Tx ring and send Msg 2 to authenticator + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + os_free_mem(pAd, (PUCHAR)mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action <-----\n")); +} + +VOID Wpa2PairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PHEADER_802_11 pHeader; + UCHAR *mpool, *PTK, *digest; + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + PEAPOL_PACKET pMsg1; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + + DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action ----->\n")); + + // allocate memory pool + os_alloc_mem(pAd, (PUCHAR *)&mpool, 256); + + if (mpool == NULL) + return; + + // PTK Len = 80. + PTK = (UCHAR *) ROUND_UP(mpool, 4); + // digest Len = 80. + digest = (UCHAR *) ROUND_UP(PTK + 80, 4); + + pHeader = (PHEADER_802_11) Elem->Msg; + + // Process message 1 from authenticator + pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + // 1. Save Replay counter, it will use to verify message 3 and construct message 2 + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 2. Save ANonce + NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + + // Generate random SNonce + GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce); + + if(pMsg1->KeyDesc.KeyDataLen[1] > 0 ) + { + // cached PMKID + } + + // Calc PTK(ANonce, SNonce) + WpaCountPTK(pAd, + pAd->StaCfg.PMK, + pAd->StaCfg.ANonce, + pAd->CommonCfg.Bssid, + pAd->StaCfg.SNonce, + pAd->CurrentAddress, + PTK, + LEN_PTK); + + // Save key to PTK entry + NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK); + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero message 2 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + // + // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE) + // + Packet.KeyDesc.Type = WPA2_KEY_DESC; + + // 1. Key descriptor version and appropriate RSN IE + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 2; + } + else // TKIP + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 1; + } + + // fill in Data Material and its length + Packet.KeyDesc.KeyData[0] = IE_WPA2; + Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len; + Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2; + NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len); + + // Update packet length after decide Key data payload + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1]; + + // 2. Key Type PeerKey + Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // 3. KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + // Update Key Length + Packet.KeyDesc.KeyLength[0] = 0; + Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1]; + + // 4. Fill SNonce + NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE); + + // 5. Key Replay Count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + // Send EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE) + // Out buffer for transmitting message 2 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + os_free_mem(pAd, mpool); + return; + } + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // 6. Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + + // Make Transmitting frame + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // 5. Copy frame to Tx ring + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); + + MlmeFreeMemory(pAd, pOutBuffer); + os_free_mem(pAd, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action <-----\n")); + +} + +/* + ======================================================================== + + Routine Description: + Process Pairwise key 4-way handshaking + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID WpaPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + PHEADER_802_11 pHeader; + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + PEAPOL_PACKET pMsg3; + UCHAR Mic[16], OldMic[16]; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR skip_offset; + KEY_INFO peerKeyInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action ----->\n")); + + // Record 802.11 header & the received EAPOL packet Msg3 + pHeader = (PHEADER_802_11) Elem->Msg; + pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo)); + + + // 1. Verify cipher type match + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2)) + { + return; + } + else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1)) + { + return; + } + + // Verify RSN IE + //if (!RTMPEqualMemory(pMsg3->KeyDesc.KeyData, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) + if (!CheckRSNIE(pAd, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1], &skip_offset)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in Msg 3 of WPA1 4-way handshake!! \n")); + hex_dump("The original RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len); + hex_dump("The received RSN_IE", pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("RSN_IE VALID in Msg 3 of WPA1 4-way handshake!! \n")); + + + // 2. Check MIC value + // Save the MIC and replace with zero + NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + UCHAR digest[80]; + + HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else // TKIP + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic); + } + + if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n")); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n")); + + // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger + if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) + return; + + // Update new replay counter + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 4. Double check ANonce + if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) + return; + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero Message 4 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field + + // + // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0) + // + Packet.KeyDesc.Type = WPA1_KEY_DESC; + + // Key descriptor version and appropriate RSN IE + Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer; + + // Update Key Length + Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0]; + Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1]; + + // Key Type PeerKey + Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + // In Msg3, KeyInfo.secure =0 if Group Key HS to come. 1 if no group key HS + // Station sends Msg4 KeyInfo.secure should be the same as that in Msg.3 + Packet.KeyDesc.KeyInfo.Secure= peerKeyInfo.Secure; + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + // Key Replay count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Out buffer for transmitting message 4 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + return; + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + UCHAR digest[80]; + + HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + // Update PTK + // Prepare pair-wise key information into shared key table + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + + // Decide its ChiperAlg + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; + + // Update these related information to MAC_TABLE_ENTRY + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + + // Update pairwise key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pEntry); + + // Make transmitting frame + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // Copy frame to Tx ring and Send Message 4 to authenticator + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action <-----\n")); +} + +VOID Wpa2PairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + PHEADER_802_11 pHeader; + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + PEAPOL_PACKET pMsg3; + UCHAR Mic[16], OldMic[16]; + UCHAR *mpool, *KEYDATA, *digest; + UCHAR Key[32]; + MAC_TABLE_ENTRY *pEntry = NULL; + KEY_INFO peerKeyInfo; + + // allocate memory + os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024); + + if(mpool == NULL) + return; + + // KEYDATA Len = 512. + KEYDATA = (UCHAR *) ROUND_UP(mpool, 4); + // digest Len = 80. + digest = (UCHAR *) ROUND_UP(KEYDATA + 512, 4); + + DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg3Action ----->\n")); + + pHeader = (PHEADER_802_11) Elem->Msg; + + // Process message 3 frame. + pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo)); + + // 1. Verify cipher type match + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer!= 2)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // 2. Check MIC value + // Save the MIC and replace with zero + NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic); + } + + if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n")); + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n")); + + // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger + if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Update new replay counter + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 4. Double check ANonce + if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Obtain GTK + // 5. Decrypt GTK from Key Data + DBGPRINT_RAW(RT_DEBUG_TRACE, ("EKD = %d\n", peerKeyInfo.EKD_DL)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // Decrypt AES GTK + AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pMsg3->KeyDesc.KeyDataLen[1],pMsg3->KeyDesc.KeyData); + } + else // TKIP + { + INT i; + // Decrypt TKIP GTK + // Construct 32 bytes RC4 Key + NdisMoveMemory(Key, pMsg3->KeyDesc.KeyIv, 16); + NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32); + //discard first 256 bytes + for(i = 0; i < 256; i++) + ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT); + // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]); + } + + if (!ParseKeyData(pAd, KEYDATA, pMsg3->KeyDesc.KeyDataLen[1], 1)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Update GTK to ASIC + // Update group key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + NULL); + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero message 4 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field + + // + // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0) + // + Packet.KeyDesc.Type = WPA2_KEY_DESC; + + // Key descriptor version and appropriate RSN IE + Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer; + + // Update Key Length + Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0]; + Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1]; + + // Key Type PeerKey + Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + // KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + Packet.KeyDesc.KeyInfo.Secure = 1; + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + // Key Replay count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Out buffer for transmitting message 4 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + // Update PTK + // Prepare pair-wise key information into shared key table + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + + // Decide its ChiperAlg + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; + + // Update these related information to MAC_TABLE_ENTRY + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(&pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK); + NdisMoveMemory(&pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK); + NdisMoveMemory(&pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + + // Update pairwise key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pEntry); + + // Make Transmitting frame + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // Copy frame to Tx ring and Send Message 4 to authenticator + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE); + + // set 802.1x port control + //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAd); + + // Indicate Connected for GUI + pAd->IndicateMediaState = NdisMediaStateConnected; + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + os_free_mem(pAd, (PUCHAR)mpool); + + + // send wireless event - for set key done WPA2 + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, BSS0, 0); + + DBGPRINT(RT_DEBUG_ERROR, ("Wpa2PairMsg3Action <-----\n")); + +} + +/* + ======================================================================== + + Routine Description: + Process Group key 2-way handshaking + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID WpaGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + PEAPOL_PACKET pGroup; + UCHAR *mpool, *digest, *KEYDATA; + UCHAR Mic[16], OldMic[16]; + UCHAR GTK[32], Key[32]; + KEY_INFO peerKeyInfo; + + // allocate memory + os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024); + + if(mpool == NULL) + return; + + // digest Len = 80. + digest = (UCHAR *) ROUND_UP(mpool, 4); + // KEYDATA Len = 512. + KEYDATA = (UCHAR *) ROUND_UP(digest + 80, 4); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action ----->\n")); + + // Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) + pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; + + NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo)); + NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pGroup->KeyDesc.KeyInfo, sizeof(KEY_INFO)); + + *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo)); + + // 0. Check cipher type match + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // 1. Verify Replay counter + // Check Replay Counter, it has to be larger than last one. No need to be exact one larger + if(RTMPCompareMemory(pGroup->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + + // Update new replay counter + NdisMoveMemory(pAd->StaCfg.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // 2. Verify MIC is valid + // Save the MIC and replace with zero + NdisMoveMemory(OldMic, pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + NdisZeroMemory(pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { // AES + HMAC_SHA1((PUCHAR) pGroup, pGroup->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { // TKIP + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pGroup, pGroup->Body_Len[1] + 4, Mic); + } + + if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in group msg 1 of 2-way handshake!!!!!!!!!! \n")); + MlmeFreeMemory(pAd, (PUCHAR)mpool); + return; + } + else + DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in group msg 1 of 2-way handshake!!!!!!!!!! \n")); + + + // 3. Decrypt GTK from Key Data + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // Decrypt AES GTK + AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pGroup->KeyDesc.KeyDataLen[1], pGroup->KeyDesc.KeyData); + } + else // TKIP + { + INT i; + + // Decrypt TKIP GTK + // Construct 32 bytes RC4 Key + NdisMoveMemory(Key, pGroup->KeyDesc.KeyIv, 16); + NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16); + ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32); + //discard first 256 bytes + for(i = 0; i < 256; i++) + ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT); + // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not + ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pGroup->KeyDesc.KeyData, pGroup->KeyDesc.KeyDataLen[1]); + } + + // Process decrypted key data material + // Parse keyData to handle KDE format for WPA2PSK + if (peerKeyInfo.EKD_DL) + { + if (!ParseKeyData(pAd, KEYDATA, pGroup->KeyDesc.KeyDataLen[1], 0)) + { + os_free_mem(pAd, (PUCHAR)mpool); + return; + } + } + else // WPAPSK + { + // set key material, TxMic and RxMic for WPAPSK + NdisMoveMemory(GTK, KEYDATA, 32); + NdisMoveMemory(pAd->StaCfg.GTK, GTK, 32); + pAd->StaCfg.DefaultKeyId = peerKeyInfo.KeyIndex; + + // Prepare pair-wise key information into shared key table + NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, GTK, LEN_TKIP_EK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, >K[16], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, >K[24], LEN_TKIP_TXMICK); + + // Update Shared Key CipherAlg + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; + + //hex_dump("Group Key :", pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, LEN_TKIP_EK); + } + + // Update group key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + NULL); + + // set 802.1x port control + //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAd); + + // Indicate Connected for GUI + pAd->IndicateMediaState = NdisMediaStateConnected; + + // init header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + // Zero Group message 1 body + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field + + // + // Group Message 2 as EAPOL-Key(1,0,0,0,G,0,0,MIC,0) + // + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + { + Packet.KeyDesc.Type = WPA2_KEY_DESC; + } + else + { + Packet.KeyDesc.Type = WPA1_KEY_DESC; + } + + // Key descriptor version and appropriate RSN IE + Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer; + + // Update Key Length + Packet.KeyDesc.KeyLength[0] = pGroup->KeyDesc.KeyLength[0]; + Packet.KeyDesc.KeyLength[1] = pGroup->KeyDesc.KeyLength[1]; + + // Key Index as G-Msg 1 + if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + Packet.KeyDesc.KeyInfo.KeyIndex = peerKeyInfo.KeyIndex; + + // Key Type Group key + Packet.KeyDesc.KeyInfo.KeyType = GROUPKEY; + + // KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + // Secure bit + Packet.KeyDesc.KeyInfo.Secure = 1; + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + // Key Replay count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + // Out buffer for transmitting group message 2 + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + MlmeFreeMemory(pAd, (PUCHAR)mpool); + return; + } + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + // AES + HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + + // 5. Copy frame to Tx ring and prepare for encryption + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE); + + // 6 Free allocated memory + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + os_free_mem(pAd, (PUCHAR)mpool); + + // send wireless event - for set key done WPA2 + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action <-----\n")); +} + +/* + ======================================================================== + + Routine Description: + Init WPA MAC header + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID WpaMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR wep, + IN PUCHAR pAddr1) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = BTYPE_DATA; + pHdr80211->FC.ToDs = 1; + if (wep == 1) + pHdr80211->FC.Wep = 1; + + // Addr1: BSSID, Addr2: SA, Addr3: DA + COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1); + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pHdr80211->Addr3, pAd->CommonCfg.Bssid); + pHdr80211->Sequence = pAd->Sequence; +} + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware encryption before really + sent out to air. + + Arguments: + pAd Pointer to our adapter + PNDIS_PACKET Pointer to outgoing Ndis frame + NumberOfFrag Number of fragment required + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN BOOLEAN is4wayFrame) + +{ + NDIS_STATUS Status; + PNDIS_PACKET pPacket; + UCHAR Index; + + do + { + // 1. build a NDIS packet and call RTMPSendPacket(); + // be careful about how/when to release this internal allocated NDIS PACKET buffer + Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen); + if (Status != NDIS_STATUS_SUCCESS) + break; + + if (is4wayFrame) + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1); + else + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0); + + // 2. send out the packet + Status = STASendPacket(pAd, pPacket); + if(Status == NDIS_STATUS_SUCCESS) + { + // Dequeue one frame from TxSwQueue0..3 queue and process it + // There are three place calling dequeue for TX ring. + // 1. Here, right after queueing the frame. + // 2. At the end of TxRingTxDone service routine. + // 3. Upon NDIS call RTMPSendPackets + if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) + { + for(Index = 0; Index < 5; Index ++) + if(pAd->TxSwQueue[Index].Number > 0) + RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS); + } + } + } while(FALSE); + +} + +/* + ======================================================================== + + Routine Description: + Check Sanity RSN IE form AP + + Arguments: + + Return Value: + + + ======================================================================== +*/ +BOOLEAN CheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + OUT UCHAR *Offset) +{ + PUCHAR pVIE; + UCHAR len; + PEID_STRUCT pEid; + BOOLEAN result = FALSE; + + pVIE = pData; + len = DataLen; + *Offset = 0; + + while (len > sizeof(RSNIE2)) + { + pEid = (PEID_STRUCT) pVIE; + // WPA RSN IE + if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) + { + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) && + (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) && + (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2))) + { + DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA/WPAPSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2))); + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + // WPA2 RSN IE + else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) + { + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) && + (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) && + (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2))) + { + DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2))); + result = TRUE; + } + + *Offset += (pEid->Len + 2); + } + else + { + break; + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + + DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> skip_offset(%d) \n", *Offset)); + + return result; + +} + + +/* + ======================================================================== + + Routine Description: + Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. + GTK is encaptulated in KDE format at p.83 802.11i D10 + + Arguments: + + Return Value: + + Note: + 802.11i D10 + + ======================================================================== +*/ +BOOLEAN ParseKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR bPairewise) +{ + PKDE_ENCAP pKDE = NULL; + PUCHAR pMyKeyData = pKeyData; + UCHAR KeyDataLength = KeyDataLen; + UCHAR GTKLEN; + UCHAR skip_offset; + + // Verify The RSN IE contained in Pairewise-Msg 3 and skip it + if (bPairewise) + { + // Check RSN IE whether it is WPA2/WPA2PSK + if (!CheckRSNIE(pAd, pKeyData, KeyDataLen, &skip_offset)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE mismatched \n")); + hex_dump("Get KEYDATA :", pKeyData, KeyDataLen); + return FALSE; + } + else + { + // skip RSN IE + pMyKeyData += skip_offset; + KeyDataLength -= skip_offset; + + //DBGPRINT(RT_DEBUG_TRACE, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); + } + } + + DBGPRINT(RT_DEBUG_TRACE,("ParseKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); + + // Parse EKD format + if (KeyDataLength >= 8) + { + pKDE = (PKDE_ENCAP) pMyKeyData; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KeyDataLength is too short \n")); + return FALSE; + } + + + // Sanity check - shared key index should not be 0 + if (pKDE->GTKEncap.Kid == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index zero \n")); + return FALSE; + } + + // Sanity check - KED length + if (KeyDataLength < (pKDE->Len + 2)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n")); + return FALSE; + } + + // Get GTK length - refer to IEEE 802.11i-2004 p.82 + GTKLEN = pKDE->Len -6; + + if (GTKLEN < LEN_AES_KEY) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); + return FALSE; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("GTK Key with KDE formet got index=%d, len=%d \n", pKDE->GTKEncap.Kid, GTKLEN)); + + // Update GTK + // set key material, TxMic and RxMic for WPAPSK + NdisMoveMemory(pAd->StaCfg.GTK, pKDE->GTKEncap.GTK, 32); + pAd->StaCfg.DefaultKeyId = pKDE->GTKEncap.Kid; + + // Update shared key table + NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKDE->GTKEncap.GTK, LEN_TKIP_EK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &pKDE->GTKEncap.GTK[16], LEN_TKIP_RXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &pKDE->GTKEncap.GTK[24], LEN_TKIP_TXMICK); + + // Update Shared Key CipherAlg + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; + + return TRUE; + +} + +/* + ======================================================================== + + Routine Description: + Cisco CCKM PRF function + + Arguments: + key Cisco Base Transient Key (BTK) + key_len The key length of the BTK + data Ruquest Number(RN) + BSSID + data_len The length of the data + output Store for PTK(Pairwise transient keys) + len The length of the output + Return Value: + None + + Note: + 802.1i Annex F.9 + + ======================================================================== +*/ +VOID CCKMPRF( + IN UCHAR *key, + IN INT key_len, + IN UCHAR *data, + IN INT data_len, + OUT UCHAR *output, + IN INT len) +{ + INT i; + UCHAR input[1024]; + INT currentindex = 0; + INT total_len; + + NdisMoveMemory(input, data, data_len); + total_len = data_len; + input[total_len] = 0; + total_len++; + for (i = 0; i < (len + 19) / 20; i++) + { + HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]); + currentindex += 20; + input[total_len - 1]++; + } +} + +/* + ======================================================================== + + Routine Description: + Process MIC error indication and record MIC error timer. + + Arguments: + pAd Pointer to our adapter + pWpaKey Pointer to the WPA key structure + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReportMicError( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pWpaKey) +{ + ULONG Now; + UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0); + + // Record Last MIC error time and count + Now = jiffies; + if (pAd->StaCfg.MicErrCnt == 0) + { + pAd->StaCfg.MicErrCnt++; + pAd->StaCfg.LastMicErrorTime = Now; + NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8); + } + else if (pAd->StaCfg.MicErrCnt == 1) + { + if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) + { + // Update Last MIC error time, this did not violate two MIC errors within 60 seconds + pAd->StaCfg.LastMicErrorTime = Now; + } + else + { + + if (pAd->CommonCfg.bWirelessEvent) + RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0); + + pAd->StaCfg.LastMicErrorTime = Now; + // Violate MIC error counts, MIC countermeasures kicks in + pAd->StaCfg.MicErrCnt++; + // We shall block all reception + // We shall clean all Tx ring and disassoicate from AP after next EAPOL frame + // + // No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets + // if pAd->StaCfg.MicErrCnt greater than 2. + // + // RTMPRingCleanUp(pAd, QID_AC_BK); + // RTMPRingCleanUp(pAd, QID_AC_BE); + // RTMPRingCleanUp(pAd, QID_AC_VI); + // RTMPRingCleanUp(pAd, QID_AC_VO); + // RTMPRingCleanUp(pAd, QID_HCCA); + } + } + else + { + // MIC error count >= 2 + // This should not happen + ; + } + MlmeEnqueue(pAd, + MLME_CNTL_STATE_MACHINE, + OID_802_11_MIC_FAILURE_REPORT_FRAME, + 1, + &unicastKey); + + if (pAd->StaCfg.MicErrCnt == 2) + { + RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100); + } +} + + +#ifdef WPA_SUPPLICANT_SUPPORT +#define LENGTH_EAP_H 4 +// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)). +INT WpaCheckEapCode( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrame, + IN USHORT FrameLen, + IN USHORT OffSet) +{ + + PUCHAR pData; + INT result = 0; + + if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H ) + return result; + + pData = pFrame + OffSet; // skip offset bytes + + if(*(pData+1) == EAPPacket) // 802.1x header - Packet Type + { + result = *(pData+4); // EAP header - Code + } + + return result; +} + +VOID WpaSendMicFailureToWpaSupplicant( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUnicast) +{ + union iwreq_data wrqu; + char custom[IW_CUSTOM_MAX] = {0}; + + sprintf(custom, "MLME-MICHAELMICFAILURE.indication"); + if (bUnicast) + sprintf(custom, "%s unicast", custom); + wrqu.data.length = strlen(custom); + wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom); + + return; +} +#endif // WPA_SUPPLICANT_SUPPORT // + +VOID WpaMicFailureReportFrame( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PUCHAR pOutBuffer = NULL; + UCHAR Header802_3[14]; + ULONG FrameLen = 0; + EAPOL_PACKET Packet; + UCHAR Mic[16]; + BOOLEAN bUnicast; + + DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n")); + + bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE); + pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); + + // init 802.3 header and Fill Packet + MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL); + + NdisZeroMemory(&Packet, sizeof(Packet)); + Packet.ProVer = EAPOL_VER; + Packet.ProType = EAPOLKey; + + Packet.KeyDesc.Type = WPA1_KEY_DESC; + + // Request field presented + Packet.KeyDesc.KeyInfo.Request = 1; + + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 2; + } + else // TKIP + { + Packet.KeyDesc.KeyInfo.KeyDescVer = 1; + } + + Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY); + + // KeyMic field presented + Packet.KeyDesc.KeyInfo.KeyMic = 1; + + // Error field presented + Packet.KeyDesc.KeyInfo.Error = 1; + + // Update packet length after decide Key data payload + Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; + + // Key Replay Count + NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY); + inc_byte_array(pAd->StaCfg.ReplayCounter, 8); + + // Convert to little-endian format. + *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo)); + + + MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory + if(pOutBuffer == NULL) + { + return; + } + + // Prepare EAPOL frame for MIC calculation + // Be careful, only EAPOL frame is counted for MIC calculation + MakeOutgoingFrame(pOutBuffer, &FrameLen, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // Prepare and Fill MIC value + NdisZeroMemory(Mic, sizeof(Mic)); + if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) + { // AES + UCHAR digest[20] = {0}; + HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest); + NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC); + } + else + { // TKIP + hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic); + } + NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + LENGTH_802_3, &Header802_3, + Packet.Body_Len[1] + 4, &Packet, + END_OF_ARGS); + + // opy frame to Tx ring and send MIC failure report frame to authenticator + RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE); + + MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n")); +} + +/** from wpa_supplicant + * inc_byte_array - Increment arbitrary length byte array by one + * @counter: Pointer to byte array + * @len: Length of the counter in bytes + * + * This function increments the last byte of the counter by one and continues + * rolling over to more significant bytes if the byte was incremented from + * 0xff to 0x00. + */ +void inc_byte_array(UCHAR *counter, int len) +{ + int pos = len - 1; + while (pos >= 0) { + counter[pos]++; + if (counter[pos] != 0) + break; + pos--; + } +} + +VOID WpaDisassocApAndBlockAssoc( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + // disassoc from current AP first + DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n")); + DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE); + MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC; + pAd->StaCfg.bBlockAssoc = TRUE; +} + diff --git a/drivers/staging/rt3070/sta_ioctl.c b/drivers/staging/rt3070/sta_ioctl.c new file mode 100644 index 000000000000..079454835a43 --- /dev/null +++ b/drivers/staging/rt3070/sta_ioctl.c @@ -0,0 +1,7203 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + sta_ioctl.c + + Abstract: + IOCTL related subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Rory Chen 01-03-2003 created + Rory Chen 02-14-2005 modify to support RT61 +*/ + +#include "rt_config.h" + +#ifdef DBG +extern ULONG RTDebugLevel; +#endif + +#define NR_WEP_KEYS 4 +#define WEP_SMALL_KEY_LEN (40/8) +#define WEP_LARGE_KEY_LEN (104/8) + +#define GROUP_KEY_NO 4 + +extern UCHAR CipherWpa2Template[]; +extern UCHAR CipherWpaPskTkip[]; +extern UCHAR CipherWpaPskTkipLen; + +typedef struct PACKED _RT_VERSION_INFO{ + UCHAR DriverVersionW; + UCHAR DriverVersionX; + UCHAR DriverVersionY; + UCHAR DriverVersionZ; + UINT DriverBuildYear; + UINT DriverBuildMonth; + UINT DriverBuildDay; +} RT_VERSION_INFO, *PRT_VERSION_INFO; + +struct iw_priv_args privtab[] = { +{ RTPRIV_IOCTL_SET, + IW_PRIV_TYPE_CHAR | 1024, 0, + "set"}, + +{ RTPRIV_IOCTL_SHOW, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + ""}, +{ RTPRIV_IOCTL_SHOW, IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + ""}, +/* --- sub-ioctls definitions --- */ + { SHOW_CONN_STATUS, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "connStatus" }, + { SHOW_DRVIER_VERION, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "driverVer" }, + { SHOW_BA_INFO, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "bainfo" }, + { SHOW_DESC_INFO, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "descinfo" }, + { RAIO_OFF, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_off" }, + { RAIO_ON, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "radio_on" }, +#ifdef QOS_DLS_SUPPORT + { SHOW_DLS_ENTRY_INFO, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "dlsentryinfo" }, +#endif // QOS_DLS_SUPPORT // + { SHOW_CFG_VALUE, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, "show" }, +/* --- sub-ioctls relations --- */ + +#ifdef DBG +{ RTPRIV_IOCTL_BBP, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + "bbp"}, +{ RTPRIV_IOCTL_MAC, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "mac"}, +#ifdef RT30xx +{ RTPRIV_IOCTL_RF, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + "rf"}, +#endif // RT30xx // +{ RTPRIV_IOCTL_E2P, + IW_PRIV_TYPE_CHAR | 1024, IW_PRIV_TYPE_CHAR | 1024, + "e2p"}, +#endif /* DBG */ + +{ RTPRIV_IOCTL_STATISTICS, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_MASK, + "stat"}, +{ RTPRIV_IOCTL_GSITESURVEY, + 0, IW_PRIV_TYPE_CHAR | 1024, + "get_site_survey"}, + + +}; + +INT Set_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +#ifdef WMM_SUPPORT +INT Set_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif + +INT Set_NetworkType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_AuthMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_EncrypType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_Key1_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_Key2_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_Key3_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_Key4_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_WPAPSK_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + + +INT Set_PSMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +#ifdef WPA_SUPPLICANT_SUPPORT +INT Set_Wpa_Support( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef DBG + +VOID RTMPIoctlMAC( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); + +VOID RTMPIoctlE2PROM( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); + +#ifdef RT30xx +VOID RTMPIoctlRF( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq); +#endif // RT30xx // +#endif // DBG // + + +NDIS_STATUS RTMPWPANoneAddKeyProc( + IN PRTMP_ADAPTER pAd, + IN PVOID pBuf); + +INT Set_FragTest_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +#ifdef DOT11_N_SUPPORT +INT Set_TGnWifiTest_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // DOT11_N_SUPPORT // + +INT Set_LongRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +INT Set_ShortRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_Ieee80211dClientMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg); +#endif // EXT_BUILD_CHANNEL_LIST // + +#ifdef CARRIER_DETECTION_SUPPORT +INT Set_CarrierDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg); +#endif // CARRIER_DETECTION_SUPPORT // + +static struct { + CHAR *name; + INT (*set_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg); +} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = { + {"DriverVersion", Set_DriverVersion_Proc}, + {"CountryRegion", Set_CountryRegion_Proc}, + {"CountryRegionABand", Set_CountryRegionABand_Proc}, + {"SSID", Set_SSID_Proc}, + {"WirelessMode", Set_WirelessMode_Proc}, + {"TxBurst", Set_TxBurst_Proc}, + {"TxPreamble", Set_TxPreamble_Proc}, + {"TxPower", Set_TxPower_Proc}, + {"Channel", Set_Channel_Proc}, + {"BGProtection", Set_BGProtection_Proc}, + {"RTSThreshold", Set_RTSThreshold_Proc}, + {"FragThreshold", Set_FragThreshold_Proc}, +#ifdef DOT11_N_SUPPORT + {"HtBw", Set_HtBw_Proc}, + {"HtMcs", Set_HtMcs_Proc}, + {"HtGi", Set_HtGi_Proc}, + {"HtOpMode", Set_HtOpMode_Proc}, + {"HtExtcha", Set_HtExtcha_Proc}, + {"HtMpduDensity", Set_HtMpduDensity_Proc}, + {"HtBaWinSize", Set_HtBaWinSize_Proc}, + {"HtRdg", Set_HtRdg_Proc}, + {"HtAmsdu", Set_HtAmsdu_Proc}, + {"HtAutoBa", Set_HtAutoBa_Proc}, + {"HtBaDecline", Set_BADecline_Proc}, + {"HtProtect", Set_HtProtect_Proc}, + {"HtMimoPs", Set_HtMimoPs_Proc}, +#endif // DOT11_N_SUPPORT // + +#ifdef AGGREGATION_SUPPORT + {"PktAggregate", Set_PktAggregate_Proc}, +#endif + +#ifdef WMM_SUPPORT + {"WmmCapable", Set_WmmCapable_Proc}, +#endif + {"IEEE80211H", Set_IEEE80211H_Proc}, + {"NetworkType", Set_NetworkType_Proc}, + {"AuthMode", Set_AuthMode_Proc}, + {"EncrypType", Set_EncrypType_Proc}, + {"DefaultKeyID", Set_DefaultKeyID_Proc}, + {"Key1", Set_Key1_Proc}, + {"Key2", Set_Key2_Proc}, + {"Key3", Set_Key3_Proc}, + {"Key4", Set_Key4_Proc}, + {"WPAPSK", Set_WPAPSK_Proc}, + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"PSMode", Set_PSMode_Proc}, +#ifdef DBG + {"Debug", Set_Debug_Proc}, +#endif + +#ifdef RALINK_ATE + {"ATE", Set_ATE_Proc}, + {"ATEDA", Set_ATE_DA_Proc}, + {"ATESA", Set_ATE_SA_Proc}, + {"ATEBSSID", Set_ATE_BSSID_Proc}, + {"ATECHANNEL", Set_ATE_CHANNEL_Proc}, + {"ATETXPOW0", Set_ATE_TX_POWER0_Proc}, + {"ATETXPOW1", Set_ATE_TX_POWER1_Proc}, + {"ATETXANT", Set_ATE_TX_Antenna_Proc}, + {"ATERXANT", Set_ATE_RX_Antenna_Proc}, + {"ATETXFREQOFFSET", Set_ATE_TX_FREQOFFSET_Proc}, + {"ATETXBW", Set_ATE_TX_BW_Proc}, + {"ATETXLEN", Set_ATE_TX_LENGTH_Proc}, + {"ATETXCNT", Set_ATE_TX_COUNT_Proc}, + {"ATETXMCS", Set_ATE_TX_MCS_Proc}, + {"ATETXMODE", Set_ATE_TX_MODE_Proc}, + {"ATETXGI", Set_ATE_TX_GI_Proc}, + {"ATERXFER", Set_ATE_RX_FER_Proc}, + {"ATERRF", Set_ATE_Read_RF_Proc}, + {"ATEWRF1", Set_ATE_Write_RF1_Proc}, + {"ATEWRF2", Set_ATE_Write_RF2_Proc}, + {"ATEWRF3", Set_ATE_Write_RF3_Proc}, + {"ATEWRF4", Set_ATE_Write_RF4_Proc}, + {"ATELDE2P", Set_ATE_Load_E2P_Proc}, + {"ATERE2P", Set_ATE_Read_E2P_Proc}, + {"ATESHOW", Set_ATE_Show_Proc}, + {"ATEHELP", Set_ATE_Help_Proc}, + +#ifdef RALINK_28xx_QA + {"TxStop", Set_TxStop_Proc}, + {"RxStop", Set_RxStop_Proc}, +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + +#ifdef WPA_SUPPLICANT_SUPPORT + {"WpaSupport", Set_Wpa_Support}, +#endif // WPA_SUPPLICANT_SUPPORT // + + + + {"FixedTxMode", Set_FixedTxMode_Proc}, +#ifdef CONFIG_APSTA_MIXED_SUPPORT + {"OpMode", Set_OpMode_Proc}, +#endif // CONFIG_APSTA_MIXED_SUPPORT // +#ifdef DOT11_N_SUPPORT + {"TGnWifiTest", Set_TGnWifiTest_Proc}, + {"ForceGF", Set_ForceGF_Proc}, +#endif // DOT11_N_SUPPORT // +#ifdef QOS_DLS_SUPPORT + {"DlsAddEntry", Set_DlsAddEntry_Proc}, + {"DlsTearDownEntry", Set_DlsTearDownEntry_Proc}, +#endif // QOS_DLS_SUPPORT // + {"LongRetry", Set_LongRetryLimit_Proc}, + {"ShortRetry", Set_ShortRetryLimit_Proc}, +#ifdef EXT_BUILD_CHANNEL_LIST + {"11dClientMode", Set_Ieee80211dClientMode_Proc}, +#endif // EXT_BUILD_CHANNEL_LIST // +#ifdef CARRIER_DETECTION_SUPPORT + {"CarrierDetect", Set_CarrierDetect_Proc}, +#endif // CARRIER_DETECTION_SUPPORT // +//2008/09/11:KH add to support efuse<-- +#ifdef RT30xx + {"efuseFreeNumber", set_eFuseGetFreeBlockCount_Proc}, + {"efuseDump", set_eFusedump_Proc}, + {"efuseLoadFromBin", set_eFuseLoadFromBin_Proc}, +#endif // RT30xx // +//2008/09/11:KH add to support efuse--> + {NULL,} +}; + + +VOID RTMPAddKey( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_KEY pKey) +{ + ULONG KeyIdx; + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey ------>\n")); + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + if (pKey->KeyIndex & 0x80000000) + { + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + NdisZeroMemory(pAd->StaCfg.PMK, 32); + NdisMoveMemory(pAd->StaCfg.PMK, pKey->KeyMaterial, pKey->KeyLength); + goto end; + } + // Update PTK + NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pKey->KeyMaterial, LEN_TKIP_EK); +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + } + + // Decide its ChiperAlg + if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES; + else + pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE; + + // Update these related information to MAC_TABLE_ENTRY + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[BSS0][0].Key, LEN_TKIP_EK); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, pAd->SharedKey[BSS0][0].RxMic, LEN_TKIP_RXMICK); + NdisMoveMemory(pEntry->PairwiseKey.TxMic, pAd->SharedKey[BSS0][0].TxMic, LEN_TKIP_TXMICK); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; + + // Update pairwise key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pAd->SharedKey[BSS0][0].Key, + pAd->SharedKey[BSS0][0].TxMic, + pAd->SharedKey[BSS0][0].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + 0, + pAd->SharedKey[BSS0][0].CipherAlg, + pEntry); + + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) + { + // set 802.1x port control + //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAd); + + // Indicate Connected for GUI + pAd->IndicateMediaState = NdisMediaStateConnected; + } + } + else + { + // Update GTK + pAd->StaCfg.DefaultKeyId = (pKey->KeyIndex & 0xFF); + NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY)); + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKey->KeyMaterial, LEN_TKIP_EK); +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + { + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + } + else +#endif // WPA_SUPPLICANT_SUPPORT // + { + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, pKey->KeyMaterial + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, pKey->KeyMaterial + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + } + + // Update Shared Key CipherAlg + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE; + if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled) + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES; + + // Update group key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic); + + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAd, + BSS0, + pAd->StaCfg.DefaultKeyId, + pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg, + NULL); + + // set 802.1x port control + //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAd); + + // Indicate Connected for GUI + pAd->IndicateMediaState = NdisMediaStateConnected; + } + } + else // dynamic WEP from wpa_supplicant + { + UCHAR CipherAlg; + PUCHAR Key; + + if(pKey->KeyLength == 32) + goto end; + + KeyIdx = pKey->KeyIndex & 0x0fffffff; + + if (KeyIdx < 4) + { + // it is a default shared key, for Pairwise key setting + if (pKey->KeyIndex & 0x80000000) + { + pEntry = MacTableLookup(pAd, pKey->BSSID); + + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddKey: Set Pair-wise Key\n")); + + // set key material and key length + pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); + + // set Cipher type + if (pKey->KeyLength == 5) + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64; + else + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128; + + // Add Pair-wise key to Asic + AsicAddPairwiseKeyEntry( + pAd, + pEntry->Addr, + (UCHAR)pEntry->Aid, + &pEntry->PairwiseKey); + + // update WCID attribute table and IVEIV table for this entry + RTMPAddWcidAttributeEntry( + pAd, + BSS0, + KeyIdx, // The value may be not zero + pEntry->PairwiseKey.CipherAlg, + pEntry); + + } + } + else + { + // Default key for tx (shared key) + pAd->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; + + // set key material and key length + pAd->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(pAd->SharedKey[BSS0][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength); + + // Set Ciper type + if (pKey->KeyLength == 5) + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP64; + else + pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_WEP128; + + CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; + Key = pAd->SharedKey[BSS0][KeyIdx].Key; + + // Set Group key material to Asic + AsicAddSharedKeyEntry(pAd, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL); + + // Update WCID attribute table and IVEIV table for this group key table + RTMPAddWcidAttributeEntry(pAd, BSS0, KeyIdx, CipherAlg, NULL); + + } + } + } +end: + return; +} + +char * rtstrchr(const char * s, int c) +{ + for(; *s != (char) c; ++s) + if (*s == '\0') + return NULL; + return (char *) s; +} + +/* +This is required for LinEX2004/kernel2.6.7 to provide iwlist scanning function +*/ + +int +rt_ioctl_giwname(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +{ +// PRTMP_ADAPTER pAdapter = dev->ml_priv; + +#ifdef RT2870 + strncpy(name, "RT2870 Wireless", IFNAMSIZ); +#endif // RT2870 // + return 0; +} + +int rt_ioctl_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + int chan = -1; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + + if (freq->e > 1) + return -EINVAL; + + if((freq->e == 0) && (freq->m <= 1000)) + chan = freq->m; // Setting by channel number + else + MAP_KHZ_TO_CHANNEL_ID( (freq->m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G, + + if (ChannelSanity(pAdapter, chan) == TRUE) + { + pAdapter->CommonCfg.Channel = chan; + DBGPRINT(RT_DEBUG_ERROR, ("==>rt_ioctl_siwfreq::SIOCSIWFREQ[cmd=0x%x] (Channel=%d)\n", SIOCSIWFREQ, pAdapter->CommonCfg.Channel)); + } + else + return -EINVAL; + + return 0; +} +int rt_ioctl_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + VIRTUAL_ADAPTER *pVirtualAd = NULL; + PRTMP_ADAPTER pAdapter; + UCHAR ch; + ULONG m; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->ml_priv; + } + else + { + pVirtualAd = dev->ml_priv; + pAdapter = pVirtualAd->RtmpDev->ml_priv; + } + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->ml_priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + ch = pAdapter->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE,("==>rt_ioctl_giwfreq %d\n", ch)); + + MAP_CHANNEL_ID_TO_KHZ(ch, m); + freq->m = m * 100; + freq->e = 1; + return 0; +} + +int rt_ioctl_siwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + switch (*mode) + { + case IW_MODE_ADHOC: + Set_NetworkType_Proc(pAdapter, "Adhoc"); + break; + case IW_MODE_INFRA: + Set_NetworkType_Proc(pAdapter, "Infra"); + break; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) + case IW_MODE_MONITOR: + Set_NetworkType_Proc(pAdapter, "Monitor"); + break; +#endif + default: + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_siwmode::SIOCSIWMODE (unknown %d)\n", *mode)); + return -EINVAL; + } + + // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key + pAdapter->StaCfg.WpaState = SS_NOTUSE; + + return 0; +} + +int rt_ioctl_giwmode(struct net_device *dev, + struct iw_request_info *info, + __u32 *mode, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + if (ADHOC_ON(pAdapter)) + *mode = IW_MODE_ADHOC; + else if (INFRA_ON(pAdapter)) + *mode = IW_MODE_INFRA; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) + else if (MONITOR_ON(pAdapter)) + { + *mode = IW_MODE_MONITOR; + } +#endif + else + *mode = IW_MODE_AUTO; + + DBGPRINT(RT_DEBUG_TRACE, ("==>rt_ioctl_giwmode(mode=%d)\n", *mode)); + return 0; +} + +int rt_ioctl_siwsens(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + return 0; +} + +int rt_ioctl_giwsens(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra) +{ + return 0; +} + +int rt_ioctl_giwrange(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + struct iw_range *range = (struct iw_range *) extra; + u16 val; + int i; + + DBGPRINT(RT_DEBUG_TRACE ,("===>rt_ioctl_giwrange\n")); + data->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + range->txpower_capa = IW_TXPOW_DBM; + + if (INFRA_ON(pAdapter)||ADHOC_ON(pAdapter)) + { + range->min_pmp = 1 * 1024; + range->max_pmp = 65535 * 1024; + range->min_pmt = 1 * 1024; + range->max_pmt = 1000 * 1024; + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | + IW_POWER_UNICAST_R | IW_POWER_ALL_R; + } + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 14; + + range->retry_capa = IW_RETRY_LIMIT; + range->retry_flags = IW_RETRY_LIMIT; + range->min_retry = 0; + range->max_retry = 255; + + range->num_channels = pAdapter->ChannelListNum; + + val = 0; + for (i = 1; i <= range->num_channels; i++) + { + u32 m; + range->freq[val].i = pAdapter->ChannelList[i-1].Channel; + MAP_CHANNEL_ID_TO_KHZ(pAdapter->ChannelList[i-1].Channel, m); + range->freq[val].m = m * 100; /* HZ */ + + range->freq[val].e = 1; + val++; + if (val == IW_MAX_FREQUENCIES) + break; + } + range->num_frequency = val; + + range->max_qual.qual = 100; /* what is correct max? This was not + * documented exactly. At least + * 69 has been observed. */ + range->max_qual.level = 0; /* dB */ + range->max_qual.noise = 0; /* dB */ + + /* What would be suitable values for "average/typical" qual? */ + range->avg_qual.qual = 20; + range->avg_qual.level = -60; + range->avg_qual.noise = -95; + range->sensitivity = 3; + + range->max_encoding_tokens = NR_WEP_KEYS; + range->num_encoding_sizes = 2; + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + +#if WIRELESS_EXT > 17 + /* IW_ENC_CAPA_* bit field */ + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; +#endif + + return 0; +} + +int rt_ioctl_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + NDIS_802_11_MAC_ADDRESS Bssid; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + // tell CNTL state machine to call NdisMSetInformationComplete() after completing + // this request, because this request is initiated by NDIS. + pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; + // Prevent to connect AP again in STAMlmePeriodicExec + pAdapter->MlmeAux.AutoReconnectSsidLen= 32; + + memset(Bssid, 0, MAC_ADDR_LEN); + memcpy(Bssid, ap_addr->sa_data, MAC_ADDR_LEN); + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + sizeof(NDIS_802_11_MAC_ADDRESS), + (VOID *)&Bssid); + + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCSIWAP %02x:%02x:%02x:%02x:%02x:%02x\n", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + + return 0; +} + +int rt_ioctl_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) + { + ap_addr->sa_family = ARPHRD_ETHER; + memcpy(ap_addr->sa_data, &pAdapter->CommonCfg.Bssid, ETH_ALEN); + } +#ifdef WPA_SUPPLICANT_SUPPORT + // Add for RT2870 + else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + ap_addr->sa_family = ARPHRD_ETHER; + memcpy(ap_addr->sa_data, &pAdapter->MlmeAux.Bssid, ETH_ALEN); + } +#endif // WPA_SUPPLICANT_SUPPORT // + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=EMPTY)\n")); + return -ENOTCONN; + } + + return 0; +} + +/* + * Units are in db above the noise floor. That means the + * rssi values reported in the tx/rx descriptors in the + * driver are the SNR expressed in db. + * + * If you assume that the noise floor is -95, which is an + * excellent assumption 99.5 % of the time, then you can + * derive the absolute signal level (i.e. -95 + rssi). + * There are some other slight factors to take into account + * depending on whether the rssi measurement is from 11b, + * 11g, or 11a. These differences are at most 2db and + * can be documented. + * + * NB: various calculations are based on the orinoco/wavelan + * drivers for compatibility + */ +static void set_quality(PRTMP_ADAPTER pAdapter, + struct iw_quality *iq, + signed char rssi) +{ + __u8 ChannelQuality; + + // Normalize Rssi + if (rssi >= -50) + ChannelQuality = 100; + else if (rssi >= -80) // between -50 ~ -80dbm + ChannelQuality = (__u8)(24 + ((rssi + 80) * 26)/10); + else if (rssi >= -90) // between -80 ~ -90dbm + ChannelQuality = (__u8)((rssi + 90) * 26)/10; + else + ChannelQuality = 0; + + iq->qual = (__u8)ChannelQuality; + + iq->level = (__u8)(rssi); + iq->noise = (pAdapter->BbpWriteLatch[66] > pAdapter->BbpTuning.FalseCcaUpperThreshold) ? ((__u8)pAdapter->BbpTuning.FalseCcaUpperThreshold) : ((__u8) pAdapter->BbpWriteLatch[66]); // noise level (dBm) + iq->noise += 256 - 143; + iq->updated = pAdapter->iw_stats.qual.updated; +} + +int rt_ioctl_iwaplist(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + struct sockaddr addr[IW_MAX_AP]; + struct iw_quality qual[IW_MAX_AP]; + int i; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + data->length = 0; + return 0; + //return -ENETDOWN; + } + + for (i = 0; i = pAdapter->ScanTab.BssNr) + break; + addr[i].sa_family = ARPHRD_ETHER; + memcpy(addr[i].sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN); + set_quality(pAdapter, &qual[i], pAdapter->ScanTab.BssEntry[i].Rssi); + } + data->length = i; + memcpy(extra, &addr, i*sizeof(addr[0])); + data->flags = 1; /* signal quality present (sort of) */ + memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i])); + + return 0; +} + +#ifdef SIOCGIWSCAN +int rt_ioctl_siwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + ULONG Now; + int Status = NDIS_STATUS_SUCCESS; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (MONITOR_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); + return -EINVAL; + } + + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) + { + pAdapter->StaCfg.WpaSupplicantScanCount++; + } +#endif // WPA_SUPPLICANT_SUPPORT // + + pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + return 0; + do{ + Now = jiffies; + +#ifdef WPA_SUPPLICANT_SUPPORT + if ((pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) && + (pAdapter->StaCfg.WpaSupplicantScanCount > 3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! WpaSupplicantScanCount > 3\n")); + Status = NDIS_STATUS_SUCCESS; + break; + } +#endif // WPA_SUPPLICANT_SUPPORT // + + if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) && + ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)) && + (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + break; + } + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + // tell CNTL state machine to call NdisMSetInformationComplete() after completing + // this request, because this request is initiated by NDIS. + pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; + // Reset allowed scan retries + pAdapter->StaCfg.ScanCnt = 0; + pAdapter->StaCfg.LastScanTime = Now; + + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + 0, + NULL); + + Status = NDIS_STATUS_SUCCESS; + RT28XX_MLME_HANDLER(pAdapter); + }while(0); + return 0; +} + +int rt_ioctl_giwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + + PRTMP_ADAPTER pAdapter = dev->ml_priv; + int i=0; + char *current_ev = extra, *previous_ev = extra; + char *end_buf; + char *current_val, custom[MAX_CUSTOM_LEN] = {0}; +#ifndef IWEVGENIE + char idx; +#endif // IWEVGENIE // + struct iw_event iwe; + + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, indicate the caller should try again. + */ + return -EAGAIN; + } + + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAdapter->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) + { + pAdapter->StaCfg.WpaSupplicantScanCount = 0; + } +#endif // WPA_SUPPLICANT_SUPPORT // + + if (pAdapter->ScanTab.BssNr == 0) + { + data->length = 0; + return 0; + } + +#if WIRELESS_EXT >= 17 + if (data->length > 0) + end_buf = extra + data->length; + else + end_buf = extra + IW_SCAN_MAX_DATA; +#else + end_buf = extra + IW_SCAN_MAX_DATA; +#endif + + for (i = 0; i < pAdapter->ScanTab.BssNr; i++) + { + if (current_ev >= end_buf) + { +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + //MAC address + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, &pAdapter->ScanTab.BssEntry[i].Bssid, ETH_ALEN); + + previous_ev = current_ev; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + /* + Protocol: + it will show scanned AP's WirelessMode . + it might be + 802.11a + 802.11a/n + 802.11g/n + 802.11b/g/n + 802.11g + 802.11b/g + */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWNAME; + + + { + PBSS_ENTRY pBssEntry=&pAdapter->ScanTab.BssEntry[i]; + BOOLEAN isGonly=FALSE; + int rateCnt=0; + + if (pBssEntry->Channel>14) + { + if (pBssEntry->HtCapabilityLen!=0) + strcpy(iwe.u.name,"802.11a/n"); + else + strcpy(iwe.u.name,"802.11a"); + } + else + { + /* + if one of non B mode rate is set supported rate . it mean G only. + */ + for (rateCnt=0;rateCntSupRateLen;rateCnt++) + { + /* + 6Mbps(140) 9Mbps(146) and >=12Mbps(152) are supported rate , it mean G only. + */ + if (pBssEntry->SupRate[rateCnt]==140 || pBssEntry->SupRate[rateCnt]==146 || pBssEntry->SupRate[rateCnt]>=152) + isGonly=TRUE; + } + + for (rateCnt=0;rateCntExtRateLen;rateCnt++) + { + if (pBssEntry->ExtRate[rateCnt]==140 || pBssEntry->ExtRate[rateCnt]==146 || pBssEntry->ExtRate[rateCnt]>=152) + isGonly=TRUE; + } + + + if (pBssEntry->HtCapabilityLen!=0) + { + if (isGonly==TRUE) + strcpy(iwe.u.name,"802.11g/n"); + else + strcpy(iwe.u.name,"802.11b/g/n"); + } + else + { + if (isGonly==TRUE) + strcpy(iwe.u.name,"802.11g"); + else + { + if (pBssEntry->SupRateLen==4 && pBssEntry->ExtRateLen==0) + strcpy(iwe.u.name,"802.11b"); + else + strcpy(iwe.u.name,"802.11b/g"); + } + } + } + } + + previous_ev = current_ev; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //ESSID + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].SsidLen; + iwe.u.data.flags = 1; + + previous_ev = current_ev; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pAdapter->ScanTab.BssEntry[i].Ssid); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Network Type + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11IBSS) + { + iwe.u.mode = IW_MODE_ADHOC; + } + else if (pAdapter->ScanTab.BssEntry[i].BssType == Ndis802_11Infrastructure) + { + iwe.u.mode = IW_MODE_INFRA; + } + else + { + iwe.u.mode = IW_MODE_AUTO; + } + iwe.len = IW_EV_UINT_LEN; + + previous_ev = current_ev; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Channel and Frequency + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) + iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel; + else + iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel; + iwe.u.freq.e = 0; + iwe.u.freq.i = 0; + + previous_ev = current_ev; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Add quality statistics + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + iwe.u.qual.level = 0; + iwe.u.qual.noise = 0; + set_quality(pAdapter, &iwe.u.qual, pAdapter->ScanTab.BssEntry[i].Rssi); + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Encyption key + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + if (CAP_IS_PRIVACY_ON (pAdapter->ScanTab.BssEntry[i].CapabilityInfo )) + iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + + previous_ev = current_ev; + current_ev = iwe_stream_add_point(info, current_ev, end_buf,&iwe, (char *)pAdapter->SharedKey[BSS0][(iwe.u.data.flags & IW_ENCODE_INDEX)-1].Key); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Bit Rate + //================================ + if (pAdapter->ScanTab.BssEntry[i].SupRateLen) + { + UCHAR tmpRate = pAdapter->ScanTab.BssEntry[i].SupRate[pAdapter->ScanTab.BssEntry[i].SupRateLen-1]; + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWRATE; + current_val = current_ev + IW_EV_LCP_LEN; + if (tmpRate == 0x82) + iwe.u.bitrate.value = 1 * 1000000; + else if (tmpRate == 0x84) + iwe.u.bitrate.value = 2 * 1000000; + else if (tmpRate == 0x8B) + iwe.u.bitrate.value = 5.5 * 1000000; + else if (tmpRate == 0x96) + iwe.u.bitrate.value = 11 * 1000000; + else + iwe.u.bitrate.value = (tmpRate/2) * 1000000; + + iwe.u.bitrate.disabled = 0; + current_val = iwe_stream_add_value(info, current_ev, + current_val, end_buf, &iwe, + IW_EV_PARAM_LEN); + + if((current_val-current_ev)>IW_EV_LCP_LEN) + current_ev = current_val; + else +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + +#ifdef IWEVGENIE + //WPA IE + if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0) + { + memset(&iwe, 0, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].WpaIE.IE[0]), + pAdapter->ScanTab.BssEntry[i].WpaIE.IELen); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + //WPA2 IE + if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0) + { + memset(&iwe, 0, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + memcpy(custom, &(pAdapter->ScanTab.BssEntry[i].RsnIE.IE[0]), + pAdapter->ScanTab.BssEntry[i].RsnIE.IELen); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } +#else + //WPA IE + //================================ + if (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen > 0) + { + NdisZeroMemory(&iwe, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].WpaIE.IELen * 2) + 7; + NdisMoveMemory(custom, "wpa_ie=", 7); + for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].WpaIE.IELen; idx++) + sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].WpaIE.IE[idx]); + previous_ev = current_ev; + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + //WPA2 IE + if (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen > 0) + { + NdisZeroMemory(&iwe, sizeof(iwe)); + memset(&custom[0], 0, MAX_CUSTOM_LEN); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = (pAdapter->ScanTab.BssEntry[i].RsnIE.IELen * 2) + 7; + NdisMoveMemory(custom, "rsn_ie=", 7); + for (idx = 0; idx < pAdapter->ScanTab.BssEntry[i].RsnIE.IELen; idx++) + sprintf(custom, "%s%02x", custom, pAdapter->ScanTab.BssEntry[i].RsnIE.IE[idx]); + previous_ev = current_ev; + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, custom); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } +#endif // IWEVGENIE // + } + + data->length = current_ev - extra; + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; + DBGPRINT(RT_DEBUG_ERROR ,("===>rt_ioctl_giwscan. %d(%d) BSS returned, data->length = %d\n",i , pAdapter->ScanTab.BssNr, data->length)); + return 0; +} +#endif + +int rt_ioctl_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (data->flags) + { + PCHAR pSsidString = NULL; + + // Includes null character. + if (data->length > (IW_ESSID_MAX_SIZE + 1)) + return -E2BIG; + + pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); + if (pSsidString) + { + NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); + NdisMoveMemory(pSsidString, essid, data->length); + if (Set_SSID_Proc(pAdapter, pSsidString) == FALSE) + return -EINVAL; + } + else + return -ENOMEM; + } + else + { + // ANY ssid + if (Set_SSID_Proc(pAdapter, "") == FALSE) + return -EINVAL; + } + return 0; +} + +int rt_ioctl_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *essid) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + data->flags = 1; + if (MONITOR_ON(pAdapter)) + { + data->length = 0; + return 0; + } + + if (OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) + { + DBGPRINT(RT_DEBUG_TRACE ,("MediaState is connected\n")); + data->length = pAdapter->CommonCfg.SsidLen; + memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen); + } +#ifdef RT2870 +#ifdef WPA_SUPPLICANT_SUPPORT + // Add for RT2870 + else if (pAdapter->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) + { + data->length = pAdapter->CommonCfg.SsidLen; + memcpy(essid, pAdapter->CommonCfg.Ssid, pAdapter->CommonCfg.SsidLen); + } +#endif // WPA_SUPPLICANT_SUPPORT // +#endif // RT2870 // + else + {//the ANY ssid was specified + data->length = 0; + DBGPRINT(RT_DEBUG_TRACE ,("MediaState is not connected, ess\n")); + } + + return 0; + +} + +int rt_ioctl_siwnickn(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *nickname) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE ,("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (data->length > IW_ESSID_MAX_SIZE) + return -EINVAL; + + memset(pAdapter->nickname, 0, IW_ESSID_MAX_SIZE + 1); + memcpy(pAdapter->nickname, nickname, data->length); + + + return 0; +} + +int rt_ioctl_giwnickn(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *nickname) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + if (data->length > strlen(pAdapter->nickname) + 1) + data->length = strlen(pAdapter->nickname) + 1; + if (data->length > 0) { + memcpy(nickname, pAdapter->nickname, data->length-1); + nickname[data->length-1] = '\0'; + } + return 0; +} + +int rt_ioctl_siwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + u16 val; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (rts->disabled) + val = MAX_RTS_THRESHOLD; + else if (rts->value < 0 || rts->value > MAX_RTS_THRESHOLD) + return -EINVAL; + else if (rts->value == 0) + val = MAX_RTS_THRESHOLD; + else + val = rts->value; + + if (val != pAdapter->CommonCfg.RtsThreshold) + pAdapter->CommonCfg.RtsThreshold = val; + + return 0; +} + +int rt_ioctl_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + rts->value = pAdapter->CommonCfg.RtsThreshold; + rts->disabled = (rts->value == MAX_RTS_THRESHOLD); + rts->fixed = 1; + + return 0; +} + +int rt_ioctl_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + u16 val; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (frag->disabled) + val = MAX_FRAG_THRESHOLD; + else if (frag->value >= MIN_FRAG_THRESHOLD || frag->value <= MAX_FRAG_THRESHOLD) + val = __cpu_to_le16(frag->value & ~0x1); /* even numbers only */ + else if (frag->value == 0) + val = MAX_FRAG_THRESHOLD; + else + return -EINVAL; + + pAdapter->CommonCfg.FragmentThreshold = val; + return 0; +} + +int rt_ioctl_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + frag->value = pAdapter->CommonCfg.FragmentThreshold; + frag->disabled = (frag->value == MAX_FRAG_THRESHOLD); + frag->fixed = 1; + + return 0; +} + +#define MAX_WEP_KEY_SIZE 13 +#define MIN_WEP_KEY_SIZE 5 +int rt_ioctl_siwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if ((erq->length == 0) && + (erq->flags & IW_ENCODE_DISABLED)) + { + pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + goto done; + } + else if (erq->flags & IW_ENCODE_RESTRICTED || erq->flags & IW_ENCODE_OPEN) + { + //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAdapter); + pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + if (erq->flags & IW_ENCODE_RESTRICTED) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + } + + if (erq->length > 0) + { + int keyIdx = (erq->flags & IW_ENCODE_INDEX) - 1; + /* Check the size of the key */ + if (erq->length > MAX_WEP_KEY_SIZE) + { + return -EINVAL; + } + /* Check key index */ + if ((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) + { + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::Wrong keyIdx=%d! Using default key instead (%d)\n", + keyIdx, pAdapter->StaCfg.DefaultKeyId)); + + //Using default key + keyIdx = pAdapter->StaCfg.DefaultKeyId; + } + else + { + pAdapter->StaCfg.DefaultKeyId=keyIdx; + } + + NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); + + if (erq->length == MAX_WEP_KEY_SIZE) + { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; + } + else if (erq->length == MIN_WEP_KEY_SIZE) + { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; + } + else + /* Disable the key */ + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0; + + /* Check if the key is not marked as invalid */ + if(!(erq->flags & IW_ENCODE_NOKEY)) + { + /* Copy the key in the driver */ + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, extra, erq->length); + } + } + else + { + /* Do we want to just set the transmit key index ? */ + int index = (erq->flags & IW_ENCODE_INDEX) - 1; + if ((index >= 0) && (index < 4)) + { + pAdapter->StaCfg.DefaultKeyId = index; + } + else + /* Don't complain if only change the mode */ + if(!erq->flags & IW_ENCODE_MODE) + { + return -EINVAL; + } + } + +done: + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::erq->flags=%x\n",erq->flags)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::AuthMode=%x\n",pAdapter->StaCfg.AuthMode)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::DefaultKeyId=%x, KeyLen = %d\n",pAdapter->StaCfg.DefaultKeyId , pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen)); + DBGPRINT(RT_DEBUG_TRACE ,("==>rt_ioctl_siwencode::WepStatus=%x\n",pAdapter->StaCfg.WepStatus)); + return 0; +} + +int +rt_ioctl_giwencode(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *key) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + int kid; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + kid = erq->flags & IW_ENCODE_INDEX; + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_giwencode %d\n", erq->flags & IW_ENCODE_INDEX)); + + if (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) + { + erq->length = 0; + erq->flags = IW_ENCODE_DISABLED; + } + else if ((kid > 0) && (kid <=4)) + { + // copy wep key + erq->flags = kid ; /* NB: base 1 */ + if (erq->length > pAdapter->SharedKey[BSS0][kid-1].KeyLen) + erq->length = pAdapter->SharedKey[BSS0][kid-1].KeyLen; + memcpy(key, pAdapter->SharedKey[BSS0][kid-1].Key, erq->length); + //if ((kid == pAdapter->PortCfg.DefaultKeyId)) + //erq->flags |= IW_ENCODE_ENABLED; /* XXX */ + if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + else + erq->flags |= IW_ENCODE_OPEN; /* XXX */ + + } + else if (kid == 0) + { + if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + else + erq->flags |= IW_ENCODE_OPEN; /* XXX */ + erq->length = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen; + memcpy(key, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, erq->length); + // copy default key ID + if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + else + erq->flags |= IW_ENCODE_OPEN; /* XXX */ + erq->flags = pAdapter->StaCfg.DefaultKeyId + 1; /* NB: base 1 */ + erq->flags |= IW_ENCODE_ENABLED; /* XXX */ + } + + return 0; + +} + +static int +rt_ioctl_setparam(struct net_device *dev, struct iw_request_info *info, + void *w, char *extra) +{ + VIRTUAL_ADAPTER *pVirtualAd = NULL; + PRTMP_ADAPTER pAdapter; + POS_COOKIE pObj; + char *this_char = extra; + char *value; + int Status=0; + + if (dev->priv_flags == INT_MAIN) + { + pAdapter = dev->ml_priv; + } + else + { + pVirtualAd = dev->ml_priv; + pAdapter = pVirtualAd->RtmpDev->ml_priv; + } + pObj = (POS_COOKIE) pAdapter->OS_Cookie; + + if (pAdapter == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->ml_priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + { + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (!*this_char) + return -EINVAL; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value) + return -EINVAL; + + // reject setting nothing besides ANY ssid(ssidLen=0) + if (!*value && (strcmp(this_char, "SSID") != 0)) + return -EINVAL; + + for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++) + { + if (strcmp(this_char, PRTMP_PRIVATE_SET_PROC->name) == 0) + { + if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAdapter, value)) + { //FALSE:Set private failed then return Invalid argument + Status = -EINVAL; + } + break; //Exit for loop. + } + } + + if(PRTMP_PRIVATE_SET_PROC->name == NULL) + { //Not found argument + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("===>rt_ioctl_setparam:: (iwpriv) Not Support Set Command [%s=%s]\n", this_char, value)); + } + + return Status; +} + + +static int +rt_private_get_statistics(struct net_device *dev, struct iw_request_info *info, + struct iw_point *wrq, char *extra) +{ + INT Status = 0; + PRTMP_ADAPTER pAd = dev->ml_priv; + + if (extra == NULL) + { + wrq->length = 0; + return -EIO; + } + + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + sprintf(extra, "\n\n"); + +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + sprintf(extra+strlen(extra), "Tx success = %ld\n", (ULONG)pAd->ate.TxDoneCount); + //sprintf(extra+strlen(extra), "Tx success without retry = %ld\n", (ULONG)pAd->ate.TxDoneCount); + } + else +#endif // RALINK_ATE // + { + sprintf(extra+strlen(extra), "Tx success = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart); + sprintf(extra+strlen(extra), "Tx success without retry = %ld\n", (ULONG)pAd->WlanCounters.TransmittedFragmentCount.QuadPart - (ULONG)pAd->WlanCounters.RetryCount.QuadPart); + } + sprintf(extra+strlen(extra), "Tx success after retry = %ld\n", (ULONG)pAd->WlanCounters.RetryCount.QuadPart); + sprintf(extra+strlen(extra), "Tx fail to Rcv ACK after retry = %ld\n", (ULONG)pAd->WlanCounters.FailedCount.QuadPart); + sprintf(extra+strlen(extra), "RTS Success Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSSuccessCount.QuadPart); + sprintf(extra+strlen(extra), "RTS Fail Rcv CTS = %ld\n", (ULONG)pAd->WlanCounters.RTSFailureCount.QuadPart); + + sprintf(extra+strlen(extra), "Rx success = %ld\n", (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart); + sprintf(extra+strlen(extra), "Rx with CRC = %ld\n", (ULONG)pAd->WlanCounters.FCSErrorCount.QuadPart); + sprintf(extra+strlen(extra), "Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); + sprintf(extra+strlen(extra), "Rx duplicate frame = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.QuadPart); + + sprintf(extra+strlen(extra), "False CCA (one second) = %ld\n", (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt); +#ifdef RALINK_ATE + if (ATE_ON(pAd)) + { + if (pAd->ate.RxAntennaSel == 0) + { + sprintf(extra+strlen(extra), "RSSI-A = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-B (if available) = %ld\n", (LONG)(pAd->ate.LastRssi1 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->ate.LastRssi2 - pAd->BbpRssiToDbmDelta)); + } + else + { + sprintf(extra+strlen(extra), "RSSI = %ld\n", (LONG)(pAd->ate.LastRssi0 - pAd->BbpRssiToDbmDelta)); + } + } + else +#endif // RALINK_ATE // + { + sprintf(extra+strlen(extra), "RSSI-A = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi0 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-B (if available) = %ld\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi1 - pAd->BbpRssiToDbmDelta)); + sprintf(extra+strlen(extra), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->StaCfg.RssiSample.LastRssi2 - pAd->BbpRssiToDbmDelta)); + } +#ifdef WPA_SUPPLICANT_SUPPORT + sprintf(extra+strlen(extra), "WpaSupplicantUP = %d\n\n", pAd->StaCfg.WpaSupplicantUP); +#endif // WPA_SUPPLICANT_SUPPORT // + + + wrq->length = strlen(extra) + 1; // 1: size of '\0' + DBGPRINT(RT_DEBUG_TRACE, ("<== rt_private_get_statistics, wrq->length = %d\n", wrq->length)); + + return Status; +} + +#ifdef DOT11_N_SUPPORT +void getBaInfo( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pOutBuf) +{ + INT i, j; + BA_ORI_ENTRY *pOriBAEntry; + BA_REC_ENTRY *pRecBAEntry; + + for (i=0; iMacTab.Content[i]; + if (((pEntry->ValidAsCLI || pEntry->ValidAsApCli) && (pEntry->Sst == SST_ASSOC)) + || (pEntry->ValidAsWDS) || (pEntry->ValidAsMesh)) + { + sprintf(pOutBuf, "%s\n%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (AP) -\n", + pOutBuf, + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5], pEntry->Aid); + + sprintf(pOutBuf, "%s[Recipient]\n", pOutBuf); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BARecWcidArray[j] != 0) + { + pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]]; + sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", pOutBuf, j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen); + } + } + sprintf(pOutBuf, "%s\n", pOutBuf); + + sprintf(pOutBuf, "%s[Originator]\n", pOutBuf); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BAOriWcidArray[j] != 0) + { + pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]]; + sprintf(pOutBuf, "%sTID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", pOutBuf, j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, pEntry->TxSeq[j]); + } + } + sprintf(pOutBuf, "%s\n\n", pOutBuf); + } + if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) + break; + } + + return; +} +#endif // DOT11_N_SUPPORT // + +static int +rt_private_show(struct net_device *dev, struct iw_request_info *info, + struct iw_point *wrq, char *extra) +{ + INT Status = 0; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + PRTMP_ADAPTER pAd; + POS_COOKIE pObj; + u32 subcmd = wrq->flags; + + if (dev->priv_flags == INT_MAIN) + pAd = dev->ml_priv; + else + { + pVirtualAd = dev->ml_priv; + pAd = pVirtualAd->RtmpDev->ml_priv; + } + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->ml_priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + if (extra == NULL) + { + wrq->length = 0; + return -EIO; + } + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + + { + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + + switch(subcmd) + { + + case SHOW_CONN_STATUS: + if (MONITOR_ON(pAd)) + { +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAd->CommonCfg.RegTransmitSetting.field.BW) + sprintf(extra, "Monitor Mode(CentralChannel %d)\n", pAd->CommonCfg.CentralChannel); + else +#endif // DOT11_N_SUPPORT // + sprintf(extra, "Monitor Mode(Channel %d)\n", pAd->CommonCfg.Channel); + } + else + { + if (pAd->IndicateMediaState == NdisMediaStateConnected) + { + if (INFRA_ON(pAd)) + { + sprintf(extra, "Connected(AP: %s[%02X:%02X:%02X:%02X:%02X:%02X])\n", + pAd->CommonCfg.Ssid, + pAd->CommonCfg.Bssid[0], + pAd->CommonCfg.Bssid[1], + pAd->CommonCfg.Bssid[2], + pAd->CommonCfg.Bssid[3], + pAd->CommonCfg.Bssid[4], + pAd->CommonCfg.Bssid[5]); + DBGPRINT(RT_DEBUG_TRACE ,("Ssid=%s ,Ssidlen = %d\n",pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)); + } + else if (ADHOC_ON(pAd)) + sprintf(extra, "Connected\n"); + } + else + { + sprintf(extra, "Disconnected\n"); + DBGPRINT(RT_DEBUG_TRACE ,("ConnStatus is not connected\n")); + } + } + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + case SHOW_DRVIER_VERION: + sprintf(extra, "Driver version-%s, %s %s\n", STA_DRIVER_VERSION, __DATE__, __TIME__ ); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; +#ifdef DOT11_N_SUPPORT + case SHOW_BA_INFO: + getBaInfo(pAd, extra); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; +#endif // DOT11_N_SUPPORT // + case SHOW_DESC_INFO: + { + Show_DescInfo_Proc(pAd, NULL); + wrq->length = 0; // 1: size of '\0' + } + break; + case RAIO_OFF: + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + sprintf(extra, "Scanning\n"); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + } + pAd->StaCfg.bSwRadio = FALSE; + if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == FALSE) + { + MlmeRadioOff(pAd); + // Update extra information + pAd->ExtraInfo = SW_RADIO_OFF; + } + } + sprintf(extra, "Radio Off\n"); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + case RAIO_ON: + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + sprintf(extra, "Scanning\n"); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + } + pAd->StaCfg.bSwRadio = TRUE; + //if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) + { + pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); + if (pAd->StaCfg.bRadio == TRUE) + { + MlmeRadioOn(pAd); + // Update extra information + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + } + } + sprintf(extra, "Radio On\n"); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + break; + + +#ifdef QOS_DLS_SUPPORT + case SHOW_DLS_ENTRY_INFO: + { + Set_DlsEntryInfo_Display_Proc(pAd, NULL); + wrq->length = 0; // 1: size of '\0' + } + break; +#endif // QOS_DLS_SUPPORT // + + case SHOW_CFG_VALUE: + { + Status = RTMPShowCfgValue(pAd, wrq->pointer, extra); + if (Status == 0) + wrq->length = strlen(extra) + 1; // 1: size of '\0' + } + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s - unknow subcmd = %d\n", __FUNCTION__, subcmd)); + break; + } + + return Status; +} + +#ifdef SIOCSIWMLME +int rt_ioctl_siwmlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + PRTMP_ADAPTER pAd = dev->ml_priv; + struct iw_mlme *pMlme = (struct iw_mlme *)wrqu->data.pointer; + MLME_QUEUE_ELEM MsgElem; + MLME_DISASSOC_REQ_STRUCT DisAssocReq; + MLME_DEAUTH_REQ_STRUCT DeAuthReq; + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + if (pMlme == NULL) + return -EINVAL; + + switch(pMlme->cmd) + { +#ifdef IW_MLME_DEAUTH + case IW_MLME_DEAUTH: + DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DEAUTH\n", __FUNCTION__)); + COPY_MAC_ADDR(DeAuthReq.Addr, pAd->CommonCfg.Bssid); + DeAuthReq.Reason = pMlme->reason_code; + MsgElem.MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT); + NdisMoveMemory(MsgElem.Msg, &DeAuthReq, sizeof(MLME_DEAUTH_REQ_STRUCT)); + MlmeDeauthReqAction(pAd, &MsgElem); + if (INFRA_ON(pAd)) + { + LinkDown(pAd, FALSE); + pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + } + break; +#endif // IW_MLME_DEAUTH // +#ifdef IW_MLME_DISASSOC + case IW_MLME_DISASSOC: + DBGPRINT(RT_DEBUG_TRACE, ("====> %s - IW_MLME_DISASSOC\n", __FUNCTION__)); + COPY_MAC_ADDR(DisAssocReq.Addr, pAd->CommonCfg.Bssid); + DisAssocReq.Reason = pMlme->reason_code; + + MsgElem.Machine = ASSOC_STATE_MACHINE; + MsgElem.MsgType = MT2_MLME_DISASSOC_REQ; + MsgElem.MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT); + NdisMoveMemory(MsgElem.Msg, &DisAssocReq, sizeof(MLME_DISASSOC_REQ_STRUCT)); + + pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC; + MlmeDisassocReqAction(pAd, &MsgElem); + break; +#endif // IW_MLME_DISASSOC // + default: + DBGPRINT(RT_DEBUG_TRACE, ("====> %s - Unknow Command\n", __FUNCTION__)); + break; + } + + return 0; +} +#endif // SIOCSIWMLME // + +#if WIRELESS_EXT > 17 +int rt_ioctl_siwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct iw_param *param = &wrqu->param; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + if (param->value == IW_AUTH_WPA_VERSION_WPA) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + } + else if (param->value == IW_AUTH_WPA_VERSION_WPA2) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_CIPHER_PAIRWISE: + if (param->value == IW_AUTH_CIPHER_NONE) + { + pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; + } + else if (param->value == IW_AUTH_CIPHER_WEP40 || + param->value == IW_AUTH_CIPHER_WEP104) + { + pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; +#ifdef WPA_SUPPLICANT_SUPPORT + pAdapter->StaCfg.IEEE8021X = FALSE; +#endif // WPA_SUPPLICANT_SUPPORT // + } + else if (param->value == IW_AUTH_CIPHER_TKIP) + { + pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + } + else if (param->value == IW_AUTH_CIPHER_CCMP) + { + pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_PAIRWISE - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_CIPHER_GROUP: + if (param->value == IW_AUTH_CIPHER_NONE) + { + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } + else if (param->value == IW_AUTH_CIPHER_WEP40 || + param->value == IW_AUTH_CIPHER_WEP104) + { + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + } + else if (param->value == IW_AUTH_CIPHER_TKIP) + { + pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; + } + else if (param->value == IW_AUTH_CIPHER_CCMP) + { + pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_CIPHER_GROUP - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_KEY_MGMT: + if (param->value == IW_AUTH_KEY_MGMT_802_1X) + { + if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA; +#ifdef WPA_SUPPLICANT_SUPPORT + pAdapter->StaCfg.IEEE8021X = FALSE; +#endif // WPA_SUPPLICANT_SUPPORT // + } + else if (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#ifdef WPA_SUPPLICANT_SUPPORT + pAdapter->StaCfg.IEEE8021X = FALSE; +#endif // WPA_SUPPLICANT_SUPPORT // + } +#ifdef WPA_SUPPLICANT_SUPPORT + else + // WEP 1x + pAdapter->StaCfg.IEEE8021X = TRUE; +#endif // WPA_SUPPLICANT_SUPPORT // + } + else if (param->value == 0) + { + //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAdapter); + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_KEY_MGMT - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + break; + case IW_AUTH_PRIVACY_INVOKED: + /*if (param->value == 0) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + }*/ + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_PRIVACY_INVOKED - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_DROP_UNENCRYPTED: + if (param->value != 0) + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + { + //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAdapter); + } + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_VERSION - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_80211_AUTH_ALG: + if (param->value & IW_AUTH_ALG_SHARED_KEY) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; + } + else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) + { + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + } + else + return -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_80211_AUTH_ALG - param->value = %d!\n", __FUNCTION__, param->value)); + break; + case IW_AUTH_WPA_ENABLED: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_AUTH_WPA_ENABLED - Driver supports WPA!(param->value = %d)\n", __FUNCTION__, param->value)); + break; + default: + return -EOPNOTSUPP; +} + + return 0; +} + +int rt_ioctl_giwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct iw_param *param = &wrqu->param; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + param->value = (pAdapter->StaCfg.WepStatus == Ndis802_11WEPDisabled) ? 0 : 1; + break; + + case IW_AUTH_80211_AUTH_ALG: + param->value = (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeShared) ? IW_AUTH_ALG_SHARED_KEY : IW_AUTH_ALG_OPEN_SYSTEM; + break; + + case IW_AUTH_WPA_ENABLED: + param->value = (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) ? 1 : 0; + break; + + default: + return -EOPNOTSUPP; + } + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_giwauth::param->value = %d!\n", param->value)); + return 0; +} + +void fnSetCipherKey( + IN PRTMP_ADAPTER pAdapter, + IN INT keyIdx, + IN UCHAR CipherAlg, + IN BOOLEAN bGTK, + IN struct iw_encode_ext *ext) +{ + NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = LEN_TKIP_EK; + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, LEN_TKIP_EK); + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].TxMic, ext->key + LEN_TKIP_EK, LEN_TKIP_TXMICK); + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].RxMic, ext->key + LEN_TKIP_EK + LEN_TKIP_TXMICK, LEN_TKIP_RXMICK); + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CipherAlg; + + // Update group key information to ASIC Shared Key Table + AsicAddSharedKeyEntry(pAdapter, + BSS0, + keyIdx, + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, + pAdapter->SharedKey[BSS0][keyIdx].Key, + pAdapter->SharedKey[BSS0][keyIdx].TxMic, + pAdapter->SharedKey[BSS0][keyIdx].RxMic); + + if (bGTK) + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAdapter, + BSS0, + keyIdx, + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, + NULL); + else + // Update ASIC WCID attribute table and IVEIV table + RTMPAddWcidAttributeEntry(pAdapter, + BSS0, + keyIdx, + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg, + &pAdapter->MacTab.Content[BSSID_WCID]); +} + +int rt_ioctl_siwencodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) + { + PRTMP_ADAPTER pAdapter = dev->ml_priv; + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int keyIdx, alg = ext->alg; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if (encoding->flags & IW_ENCODE_DISABLED) + { + keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; + // set BSSID wcid entry of the Pair-wise Key table as no-security mode + AsicRemovePairwiseKeyEntry(pAdapter, BSS0, BSSID_WCID); + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = 0; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)keyIdx); + NdisZeroMemory(&pAdapter->SharedKey[BSS0][keyIdx], sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE, ("%s::Remove all keys!(encoding->flags = %x)\n", __FUNCTION__, encoding->flags)); + } + else + { + // Get Key Index and convet to our own defined key index + keyIdx = (encoding->flags & IW_ENCODE_INDEX) - 1; + if((keyIdx < 0) || (keyIdx >= NR_WEP_KEYS)) + return -EINVAL; + + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + { + pAdapter->StaCfg.DefaultKeyId = keyIdx; + DBGPRINT(RT_DEBUG_TRACE, ("%s::DefaultKeyId = %d\n", __FUNCTION__, pAdapter->StaCfg.DefaultKeyId)); + } + + switch (alg) { + case IW_ENCODE_ALG_NONE: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_NONE\n", __FUNCTION__)); + break; + case IW_ENCODE_ALG_WEP: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_WEP - ext->key_len = %d, keyIdx = %d\n", __FUNCTION__, ext->key_len, keyIdx)); + if (ext->key_len == MAX_WEP_KEY_SIZE) + { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MAX_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP128; + } + else if (ext->key_len == MIN_WEP_KEY_SIZE) + { + pAdapter->SharedKey[BSS0][keyIdx].KeyLen = MIN_WEP_KEY_SIZE; + pAdapter->SharedKey[BSS0][keyIdx].CipherAlg = CIPHER_WEP64; + } + else + return -EINVAL; + + NdisZeroMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, 16); + NdisMoveMemory(pAdapter->SharedKey[BSS0][keyIdx].Key, ext->key, ext->key_len); + break; + case IW_ENCODE_ALG_TKIP: + DBGPRINT(RT_DEBUG_TRACE, ("%s::IW_ENCODE_ALG_TKIP - keyIdx = %d, ext->key_len = %d\n", __FUNCTION__, keyIdx, ext->key_len)); + if (ext->key_len == 32) + { + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, FALSE, ext); + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) + { + //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAdapter); + } + } + else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) + { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_TKIP, TRUE, ext); + + // set 802.1x port control + //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAdapter); + } + } + else + return -EINVAL; + break; + case IW_ENCODE_ALG_CCMP: + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, FALSE, ext); + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA2) + //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAdapter); + } + else if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) + { + fnSetCipherKey(pAdapter, keyIdx, CIPHER_AES, TRUE, ext); + + // set 802.1x port control + //pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + STA_PORT_SECURED(pAdapter); + } + break; + default: + return -EINVAL; + } + } + + return 0; +} + +int +rt_ioctl_giwencodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = dev->ml_priv; + PCHAR pKey = NULL; + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int idx, max_key_len; + + DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_giwencodeext\n")); + + max_key_len = encoding->length - sizeof(*ext); + if (max_key_len < 0) + return -EINVAL; + + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) + { + if (idx < 1 || idx > 4) + return -EINVAL; + idx--; + + if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || + (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)) + { + if (idx != pAd->StaCfg.DefaultKeyId) + { + ext->key_len = 0; + return 0; + } + } + } + else + idx = pAd->StaCfg.DefaultKeyId; + + encoding->flags = idx + 1; + memset(ext, 0, sizeof(*ext)); + + ext->key_len = 0; + switch(pAd->StaCfg.WepStatus) { + case Ndis802_11WEPDisabled: + ext->alg = IW_ENCODE_ALG_NONE; + encoding->flags |= IW_ENCODE_DISABLED; + break; + case Ndis802_11WEPEnabled: + ext->alg = IW_ENCODE_ALG_WEP; + if (pAd->SharedKey[BSS0][idx].KeyLen > max_key_len) + return -E2BIG; + else + { + ext->key_len = pAd->SharedKey[BSS0][idx].KeyLen; + pKey = &(pAd->SharedKey[BSS0][idx].Key[0]); + } + break; + case Ndis802_11Encryption2Enabled: + case Ndis802_11Encryption3Enabled: + if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) + ext->alg = IW_ENCODE_ALG_TKIP; + else + ext->alg = IW_ENCODE_ALG_CCMP; + + if (max_key_len < 32) + return -E2BIG; + else + { + ext->key_len = 32; + pKey = &pAd->StaCfg.PMK[0]; + } + break; + default: + return -EINVAL; + } + + if (ext->key_len && pKey) + { + encoding->flags |= IW_ENCODE_ENABLED; + memcpy(ext->key, pKey, ext->key_len); + } + + return 0; +} + +#ifdef SIOCSIWGENIE +int rt_ioctl_siwgenie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = dev->ml_priv; + + if (wrqu->data.length > MAX_LEN_OF_RSNIE || + (wrqu->data.length && extra == NULL)) + return -EINVAL; + + if (wrqu->data.length) + { + pAd->StaCfg.RSNIE_Len = wrqu->data.length; + NdisMoveMemory(&pAd->StaCfg.RSN_IE[0], extra, pAd->StaCfg.RSNIE_Len); + } + else + { + pAd->StaCfg.RSNIE_Len = 0; + NdisZeroMemory(&pAd->StaCfg.RSN_IE[0], MAX_LEN_OF_RSNIE); + } + + return 0; +} +#endif // SIOCSIWGENIE // + +int rt_ioctl_giwgenie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = dev->ml_priv; + + if ((pAd->StaCfg.RSNIE_Len == 0) || + (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)) + { + wrqu->data.length = 0; + return 0; + } + +#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT +#ifdef SIOCSIWGENIE + if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_ENABLE) + { + if (wrqu->data.length < pAd->StaCfg.RSNIE_Len) + return -E2BIG; + + wrqu->data.length = pAd->StaCfg.RSNIE_Len; + memcpy(extra, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); + } + else +#endif // SIOCSIWGENIE // +#endif // NATIVE_WPA_SUPPLICANT_SUPPORT // + { + UCHAR RSNIe = IE_WPA; + + if (wrqu->data.length < (pAd->StaCfg.RSNIE_Len + 2)) // ID, Len + return -E2BIG; + wrqu->data.length = pAd->StaCfg.RSNIE_Len + 2; + + if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)) + RSNIe = IE_RSN; + + extra[0] = (char)RSNIe; + extra[1] = pAd->StaCfg.RSNIE_Len; + memcpy(extra+2, &pAd->StaCfg.RSN_IE[0], pAd->StaCfg.RSNIE_Len); + } + + return 0; +} + +int rt_ioctl_siwpmksa(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + PRTMP_ADAPTER pAd = dev->ml_priv; + struct iw_pmksa *pPmksa = (struct iw_pmksa *)wrqu->data.pointer; + INT CachedIdx = 0, idx = 0; + + if (pPmksa == NULL) + return -EINVAL; + + DBGPRINT(RT_DEBUG_TRACE ,("===> rt_ioctl_siwpmksa\n")); + switch(pPmksa->cmd) + { + case IW_PMKSA_FLUSH: + NdisZeroMemory(pAd->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_FLUSH\n")); + break; + case IW_PMKSA_REMOVE: + for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) + { + // compare the BSSID + if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) + { + NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN); + NdisZeroMemory(pAd->StaCfg.SavedPMK[CachedIdx].PMKID, 16); + for (idx = CachedIdx; idx < (pAd->StaCfg.SavedPMKNum - 1); idx++) + { + NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].BSSID[0], &pAd->StaCfg.SavedPMK[idx+1].BSSID[0], MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[idx].PMKID[0], &pAd->StaCfg.SavedPMK[idx+1].PMKID[0], 16); + } + pAd->StaCfg.SavedPMKNum--; + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_REMOVE\n")); + break; + case IW_PMKSA_ADD: + for (CachedIdx = 0; CachedIdx < pAd->StaCfg.SavedPMKNum; CachedIdx++) + { + // compare the BSSID + if (NdisEqualMemory(pPmksa->bssid.sa_data, pAd->StaCfg.SavedPMK[CachedIdx].BSSID, MAC_ADDR_LEN)) + break; + } + + // Found, replace it + if (CachedIdx < PMKID_NO) + { + DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16); + pAd->StaCfg.SavedPMKNum++; + } + // Not found, replace the last one + else + { + // Randomly replace one + CachedIdx = (pPmksa->bssid.sa_data[5] % PMKID_NO); + DBGPRINT(RT_DEBUG_OFF, ("Update PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].BSSID[0], pPmksa->bssid.sa_data, MAC_ADDR_LEN); + NdisMoveMemory(&pAd->StaCfg.SavedPMK[CachedIdx].PMKID[0], pPmksa->pmkid, 16); + } + + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - IW_PMKSA_ADD\n")); + break; + default: + DBGPRINT(RT_DEBUG_TRACE ,("rt_ioctl_siwpmksa - Unknow Command!!\n")); + break; + } + + return 0; +} +#endif // #if WIRELESS_EXT > 17 + +#ifdef DBG +static int +rt_private_ioctl_bbp(struct net_device *dev, struct iw_request_info *info, + struct iw_point *wrq, char *extra) + { + CHAR *this_char; + CHAR *value = NULL; + UCHAR regBBP = 0; +// CHAR arg[255]={0}; + UINT32 bbpId; + UINT32 bbpValue; + BOOLEAN bIsPrintAllBBP = FALSE; + INT Status = 0; + PRTMP_ADAPTER pAdapter = dev->ml_priv; + + + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + + if (wrq->length > 1) //No parameters. + { + sprintf(extra, "\n"); + + //Parsing Read or Write + this_char = wrq->pointer; + DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s\n", this_char)); + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { //Read + DBGPRINT(RT_DEBUG_TRACE, ("this_char=%s, value=%s\n", this_char, value)); + if (sscanf(this_char, "%d", &(bbpId)) == 1) + { +#ifndef RT30xx + if (bbpId <= 136) +#endif // RT30xx // +#ifdef RT30xx + if (bbpId <= 138) // edit by johnli, RF power sequence setup, add BBP R138 for ADC dynamic on/off control +#endif // RT30xx // + { +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + else +#endif // RALINK_ATE // + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra)); + } + else + {//Invalid parametes, so default printk all bbp + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { //Invalid parametes, so default printk all bbp + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { //Write + if ((sscanf(this_char, "%d", &(bbpId)) == 1) && (sscanf(value, "%x", &(bbpValue)) == 1)) + { +#ifndef RT30xx + if (bbpId <= 136) +#endif // RT30xx // +#ifdef RT30xx + if (bbpId <= 138) // edit by johnli, RF power sequence setup, add BBP R138 for ADC dynamic on/off control +#endif // RT30xx // + { +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue); + //Read it back for showing + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + else +#endif // RALINK_ATE // + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, bbpId, bbpValue); + //Read it back for showing + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X\n", bbpId, bbpId*2, regBBP); + wrq->length = strlen(extra) + 1; // 1: size of '\0' + DBGPRINT(RT_DEBUG_TRACE, ("msg=%s\n", extra)); + } + else + {//Invalid parametes, so default printk all bbp + bIsPrintAllBBP = TRUE; + goto next; + } + } + else + { //Invalid parametes, so default printk all bbp + bIsPrintAllBBP = TRUE; + goto next; + } + } + } + else + bIsPrintAllBBP = TRUE; + +next: + if (bIsPrintAllBBP) + { + memset(extra, 0x00, IW_PRIV_SIZE_MASK); + sprintf(extra, "\n"); +#ifndef RT30xx + for (bbpId = 0; bbpId <= 136; bbpId++) +#endif // RT30xx // +#ifdef RT30xx + for (bbpId = 0; bbpId <= 138; bbpId++) // edit by johnli, RF power sequence setup, add BBP R138 for ADC dynamic on/off control +#endif // RT30xx // + { + if (strlen(extra) >= (IW_PRIV_SIZE_MASK - 10)) + break; +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + } + else +#endif // RALINK_ATE // + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); +/* + sprintf(extra+strlen(extra), "R%02d[0x%02X]:%02X ", bbpId, bbpId*2, regBBP); + if (bbpId%5 == 4) + sprintf(extra+strlen(extra), "\n"); +*/ + sprintf(extra+strlen(extra), "%03d = %02X\n", bbpId, regBBP); // edit by johnli, change display format + } + + wrq->length = strlen(extra) + 1; // 1: size of '\0' + DBGPRINT(RT_DEBUG_TRACE, ("wrq->length = %d\n", wrq->length)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<==rt_private_ioctl_bbp\n\n")); + + return Status; +} +#endif // DBG // + +int rt_ioctl_siwrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = dev->ml_priv; + UINT32 rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed; + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::Network is down!\n")); + return -ENETDOWN; + } + + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed)); + /* rate = -1 => auto rate + rate = X, fixed = 1 => (fixed rate X) + */ + if (rate == -1) + { + //Auto Rate + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; + pAd->StaCfg.bAutoTxRateSwitch = TRUE; + if ((pAd->CommonCfg.PhyMode <= PHY_11G) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + RTMPSetDesiredRates(pAd, -1); + +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + } + else + { + if (fixed) + { + pAd->StaCfg.bAutoTxRateSwitch = FALSE; + if ((pAd->CommonCfg.PhyMode <= PHY_11G) || + (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) + RTMPSetDesiredRates(pAd, rate); + else + { + pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO; +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif // DOT11_N_SUPPORT // + } + DBGPRINT(RT_DEBUG_TRACE, ("rt_ioctl_siwrate::(HtMcs=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.MCS)); + } + else + { + // TODO: rate = X, fixed = 0 => (rates <= X) + return -EOPNOTSUPP; + } + } + + return 0; +} + +int rt_ioctl_giwrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + PRTMP_ADAPTER pAd = dev->ml_priv; + int rate_index = 0, rate_count = 0; + HTTRANSMIT_SETTING ht_setting; + __s32 ralinkrate[] = + {2, 4, 11, 22, // CCK + 12, 18, 24, 36, 48, 72, 96, 108, // OFDM + 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, // 20MHz, 800ns GI, MCS: 0 ~ 15 + 39, 78, 117, 156, 234, 312, 351, 390, // 20MHz, 800ns GI, MCS: 16 ~ 23 + 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, // 40MHz, 800ns GI, MCS: 0 ~ 15 + 81, 162, 243, 324, 486, 648, 729, 810, // 40MHz, 800ns GI, MCS: 16 ~ 23 + 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, // 20MHz, 400ns GI, MCS: 0 ~ 15 + 43, 87, 130, 173, 260, 317, 390, 433, // 20MHz, 400ns GI, MCS: 16 ~ 23 + 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, // 40MHz, 400ns GI, MCS: 0 ~ 15 + 90, 180, 270, 360, 540, 720, 810, 900}; // 40MHz, 400ns GI, MCS: 16 ~ 23 + + rate_count = sizeof(ralinkrate)/sizeof(__s32); + //check if the interface is down + if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + + if ((pAd->StaCfg.bAutoTxRateSwitch == FALSE) && + (INFRA_ON(pAd)) && + ((pAd->CommonCfg.PhyMode <= PHY_11G) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM))) + ht_setting.word = pAd->StaCfg.HTPhyMode.word; + else + ht_setting.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; + +#ifdef DOT11_N_SUPPORT + if (ht_setting.field.MODE >= MODE_HTMIX) + { +// rate_index = 12 + ((UCHAR)ht_setting.field.BW *16) + ((UCHAR)ht_setting.field.ShortGI *32) + ((UCHAR)ht_setting.field.MCS); + rate_index = 12 + ((UCHAR)ht_setting.field.BW *24) + ((UCHAR)ht_setting.field.ShortGI *48) + ((UCHAR)ht_setting.field.MCS); + } + else +#endif // DOT11_N_SUPPORT // + if (ht_setting.field.MODE == MODE_OFDM) + rate_index = (UCHAR)(ht_setting.field.MCS) + 4; + else if (ht_setting.field.MODE == MODE_CCK) + rate_index = (UCHAR)(ht_setting.field.MCS); + + if (rate_index < 0) + rate_index = 0; + + if (rate_index > rate_count) + rate_index = rate_count; + + wrqu->bitrate.value = ralinkrate[rate_index] * 500000; + wrqu->bitrate.disabled = 0; + + return 0; +} + +static const iw_handler rt_handler[] = +{ + (iw_handler) NULL, /* SIOCSIWCOMMIT */ + (iw_handler) rt_ioctl_giwname, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) rt_ioctl_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) rt_ioctl_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) rt_ioctl_siwmode, /* SIOCSIWMODE */ + (iw_handler) rt_ioctl_giwmode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ + (iw_handler) rt_ioctl_giwrange, /* SIOCGIWRANGE */ + (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ + (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ + (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ + (iw_handler) rt28xx_get_wireless_stats /* kernel code */, /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* SIOCSIWTHRSPY */ + (iw_handler) NULL, /* SIOCGIWTHRSPY */ + (iw_handler) rt_ioctl_siwap, /* SIOCSIWAP */ + (iw_handler) rt_ioctl_giwap, /* SIOCGIWAP */ +#ifdef SIOCSIWMLME + (iw_handler) rt_ioctl_siwmlme, /* SIOCSIWMLME */ +#else + (iw_handler) NULL, /* SIOCSIWMLME */ +#endif // SIOCSIWMLME // + (iw_handler) rt_ioctl_iwaplist, /* SIOCGIWAPLIST */ +#ifdef SIOCGIWSCAN + (iw_handler) rt_ioctl_siwscan, /* SIOCSIWSCAN */ + (iw_handler) rt_ioctl_giwscan, /* SIOCGIWSCAN */ +#else + (iw_handler) NULL, /* SIOCSIWSCAN */ + (iw_handler) NULL, /* SIOCGIWSCAN */ +#endif /* SIOCGIWSCAN */ + (iw_handler) rt_ioctl_siwessid, /* SIOCSIWESSID */ + (iw_handler) rt_ioctl_giwessid, /* SIOCGIWESSID */ + (iw_handler) rt_ioctl_siwnickn, /* SIOCSIWNICKN */ + (iw_handler) rt_ioctl_giwnickn, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) rt_ioctl_siwrate, /* SIOCSIWRATE */ + (iw_handler) rt_ioctl_giwrate, /* SIOCGIWRATE */ + (iw_handler) rt_ioctl_siwrts, /* SIOCSIWRTS */ + (iw_handler) rt_ioctl_giwrts, /* SIOCGIWRTS */ + (iw_handler) rt_ioctl_siwfrag, /* SIOCSIWFRAG */ + (iw_handler) rt_ioctl_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) NULL, /* SIOCSIWRETRY */ + (iw_handler) NULL, /* SIOCGIWRETRY */ + (iw_handler) rt_ioctl_siwencode, /* SIOCSIWENCODE */ + (iw_handler) rt_ioctl_giwencode, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) NULL, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ +#if WIRELESS_EXT > 17 + (iw_handler) rt_ioctl_siwgenie, /* SIOCSIWGENIE */ + (iw_handler) rt_ioctl_giwgenie, /* SIOCGIWGENIE */ + (iw_handler) rt_ioctl_siwauth, /* SIOCSIWAUTH */ + (iw_handler) rt_ioctl_giwauth, /* SIOCGIWAUTH */ + (iw_handler) rt_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) rt_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) rt_ioctl_siwpmksa, /* SIOCSIWPMKSA */ +#endif +}; + +static const iw_handler rt_priv_handlers[] = { + (iw_handler) NULL, /* + 0x00 */ + (iw_handler) NULL, /* + 0x01 */ +#ifndef CONFIG_AP_SUPPORT + (iw_handler) rt_ioctl_setparam, /* + 0x02 */ +#else + (iw_handler) NULL, /* + 0x02 */ +#endif // CONFIG_AP_SUPPORT // +#ifdef DBG + (iw_handler) rt_private_ioctl_bbp, /* + 0x03 */ +#else + (iw_handler) NULL, /* + 0x03 */ +#endif + (iw_handler) NULL, /* + 0x04 */ + (iw_handler) NULL, /* + 0x05 */ + (iw_handler) NULL, /* + 0x06 */ + (iw_handler) NULL, /* + 0x07 */ + (iw_handler) NULL, /* + 0x08 */ + (iw_handler) rt_private_get_statistics, /* + 0x09 */ + (iw_handler) NULL, /* + 0x0A */ + (iw_handler) NULL, /* + 0x0B */ + (iw_handler) NULL, /* + 0x0C */ + (iw_handler) NULL, /* + 0x0D */ + (iw_handler) NULL, /* + 0x0E */ + (iw_handler) NULL, /* + 0x0F */ + (iw_handler) NULL, /* + 0x10 */ + (iw_handler) rt_private_show, /* + 0x11 */ + (iw_handler) NULL, /* + 0x12 */ + (iw_handler) NULL, /* + 0x13 */ + (iw_handler) NULL, /* + 0x15 */ + (iw_handler) NULL, /* + 0x17 */ + (iw_handler) NULL, /* + 0x18 */ +}; + +const struct iw_handler_def rt28xx_iw_handler_def = +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + .standard = (iw_handler *) rt_handler, + .num_standard = sizeof(rt_handler) / sizeof(iw_handler), + .private = (iw_handler *) rt_priv_handlers, + .num_private = N(rt_priv_handlers), + .private_args = (struct iw_priv_args *) privtab, + .num_private_args = N(privtab), +#if IW_HANDLER_VERSION >= 7 + .get_wireless_stats = rt28xx_get_wireless_stats, +#endif +}; + +INT RTMPSetInformation( + IN PRTMP_ADAPTER pAdapter, + IN OUT struct ifreq *rq, + IN INT cmd) +{ + struct iwreq *wrq = (struct iwreq *) rq; + NDIS_802_11_SSID Ssid; + NDIS_802_11_MAC_ADDRESS Bssid; + RT_802_11_PHY_MODE PhyMode; + RT_802_11_STA_CONFIG StaConfig; + NDIS_802_11_RATES aryRates; + RT_802_11_PREAMBLE Preamble; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; + NDIS_802_11_NETWORK_INFRASTRUCTURE BssType; + NDIS_802_11_RTS_THRESHOLD RtsThresh; + NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + NDIS_802_11_POWER_MODE PowerMode; + PNDIS_802_11_KEY pKey = NULL; + PNDIS_802_11_WEP pWepKey =NULL; + PNDIS_802_11_REMOVE_KEY pRemoveKey = NULL; + NDIS_802_11_CONFIGURATION Config, *pConfig = NULL; + NDIS_802_11_NETWORK_TYPE NetType; + ULONG Now; + UINT KeyIdx = 0; + INT Status = NDIS_STATUS_SUCCESS, MaxPhyMode = PHY_11G; + ULONG PowerTemp; + BOOLEAN RadioState; + BOOLEAN StateMachineTouched = FALSE; +#ifdef DOT11_N_SUPPORT + OID_SET_HT_PHYMODE HT_PhyMode; //11n ,kathy +#endif // DOT11_N_SUPPORT // +#ifdef WPA_SUPPLICANT_SUPPORT + PNDIS_802_11_PMKID pPmkId = NULL; + BOOLEAN IEEE8021xState = FALSE; + BOOLEAN IEEE8021x_required_keys = FALSE; + UCHAR wpa_supplicant_enable = 0; +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef SNMP_SUPPORT + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; + UCHAR ctmp; +#endif // SNMP_SUPPORT // + + +#ifdef DOT11_N_SUPPORT + MaxPhyMode = PHY_11N_5G; +#endif // DOT11_N_SUPPORT // + + + DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPSetInformation(), 0x%08x\n", cmd&0x7FFF)); + switch(cmd & 0x7FFF) { + case RT_OID_802_11_COUNTRY_REGION: + if (wrq->u.data.length < sizeof(UCHAR)) + Status = -EINVAL; + // Only avaliable when EEPROM not programming + else if (!(pAdapter->CommonCfg.CountryRegion & 0x80) && !(pAdapter->CommonCfg.CountryRegionForABand & 0x80)) + { + ULONG Country; + UCHAR TmpPhy; + + Status = copy_from_user(&Country, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->CommonCfg.CountryRegion = (UCHAR)(Country & 0x000000FF); + pAdapter->CommonCfg.CountryRegionForABand = (UCHAR)((Country >> 8) & 0x000000FF); + TmpPhy = pAdapter->CommonCfg.PhyMode; + pAdapter->CommonCfg.PhyMode = 0xff; + // Build all corresponding channel information + RTMPSetPhyMode(pAdapter, TmpPhy); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAdapter); +#endif // DOT11_N_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_COUNTRY_REGION (A:%d B/G:%d)\n", pAdapter->CommonCfg.CountryRegionForABand, + pAdapter->CommonCfg.CountryRegion)); + } + break; + case OID_802_11_BSSID_LIST_SCAN: + #ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + break; + } +#endif // RALINK_ATE // + Now = jiffies; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID_LIST_SCAN, TxCnt = %d \n", pAdapter->RalinkCounters.LastOneSecTotalTxCount)); + + if (MONITOR_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is in Monitor Mode now !!!\n")); + break; + } + + //Benson add 20080527, when radio off, sta don't need to scan + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF)) + break; + + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Driver is scanning now !!!\n")); + pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; + Status = NDIS_STATUS_SUCCESS; + break; + } + + if (pAdapter->RalinkCounters.LastOneSecTotalTxCount > 100) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + pAdapter->StaCfg.ScanCnt = 99; // Prevent auto scan triggered by this OID + break; + } + + if ((OPSTATUS_TEST_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED)) && + ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && + (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("!!! Link UP, Port Not Secured! ignore this set::OID_802_11_BSSID_LIST_SCAN\n")); + Status = NDIS_STATUS_SUCCESS; + pAdapter->StaCfg.ScanCnt = 99; // Prevent auto scan triggered by this OID + break; + } + + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + // tell CNTL state machine to call NdisMSetInformationComplete() after completing + // this request, because this request is initiated by NDIS. + pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; + // Reset allowed scan retries + pAdapter->StaCfg.ScanCnt = 0; + pAdapter->StaCfg.LastScanTime = Now; + + pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE; + RTMP_SET_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID_LIST_SCAN, + 0, + NULL); + + Status = NDIS_STATUS_SUCCESS; + StateMachineTouched = TRUE; + break; + case OID_802_11_SSID: + if (wrq->u.data.length != sizeof(NDIS_802_11_SSID)) + Status = -EINVAL; + else + { + PCHAR pSsidString = NULL; + Status = copy_from_user(&Ssid, wrq->u.data.pointer, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SSID (Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid)); + if (Ssid.SsidLength > MAX_LEN_OF_SSID) + Status = -EINVAL; + else + { + if (Ssid.SsidLength == 0) + { + Set_SSID_Proc(pAdapter, ""); + } + else + { + pSsidString = (CHAR *) kmalloc(MAX_LEN_OF_SSID+1, MEM_ALLOC_FLAG); + if (pSsidString) + { + NdisZeroMemory(pSsidString, MAX_LEN_OF_SSID+1); + NdisMoveMemory(pSsidString, Ssid.Ssid, Ssid.SsidLength); + Set_SSID_Proc(pAdapter, pSsidString); + kfree(pSsidString); + } + else + Status = -ENOMEM; + } + } + } + break; + case OID_802_11_BSSID: +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + break; + } +#endif // RALINK_ATE // + if (wrq->u.data.length != sizeof(NDIS_802_11_MAC_ADDRESS)) + Status = -EINVAL; + else + { + Status = copy_from_user(&Bssid, wrq->u.data.pointer, wrq->u.data.length); + + // tell CNTL state machine to call NdisMSetInformationComplete() after completing + // this request, because this request is initiated by NDIS. + pAdapter->MlmeAux.CurrReqIsFromNdis = FALSE; + + // Prevent to connect AP again in STAMlmePeriodicExec + pAdapter->MlmeAux.AutoReconnectSsidLen= 32; + + // Reset allowed scan retries + pAdapter->StaCfg.ScanCnt = 0; + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_BSSID, + sizeof(NDIS_802_11_MAC_ADDRESS), + (VOID *)&Bssid); + Status = NDIS_STATUS_SUCCESS; + StateMachineTouched = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); + } + break; + case RT_OID_802_11_RADIO: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&RadioState, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RADIO (=%d)\n", RadioState)); + if (pAdapter->StaCfg.bSwRadio != RadioState) + { + pAdapter->StaCfg.bSwRadio = RadioState; + if (pAdapter->StaCfg.bRadio != (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio)) + { + pAdapter->StaCfg.bRadio = (pAdapter->StaCfg.bHwRadio && pAdapter->StaCfg.bSwRadio); + if (pAdapter->StaCfg.bRadio == TRUE) + { + MlmeRadioOn(pAdapter); + // Update extra information + pAdapter->ExtraInfo = EXTRA_INFO_CLEAR; + } + else + { + MlmeRadioOff(pAdapter); + // Update extra information + pAdapter->ExtraInfo = SW_RADIO_OFF; + } + } + } + } + break; + case RT_OID_802_11_PHY_MODE: + if (wrq->u.data.length != sizeof(RT_802_11_PHY_MODE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&PhyMode, wrq->u.data.pointer, wrq->u.data.length); + if (PhyMode <= MaxPhyMode) + { + RTMPSetPhyMode(pAdapter, PhyMode); +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAdapter); +#endif // DOT11_N_SUPPORT // + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PHY_MODE (=%d)\n", PhyMode)); + } + break; + case RT_OID_802_11_STA_CONFIG: + if (wrq->u.data.length != sizeof(RT_802_11_STA_CONFIG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&StaConfig, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->CommonCfg.bEnableTxBurst = StaConfig.EnableTxBurst; + pAdapter->CommonCfg.UseBGProtection = StaConfig.UseBGProtection; + pAdapter->CommonCfg.bUseShortSlotTime = 1; // 2003-10-30 always SHORT SLOT capable + if ((pAdapter->CommonCfg.PhyMode != StaConfig.AdhocMode) && + (StaConfig.AdhocMode <= MaxPhyMode)) + { + // allow dynamic change of "USE OFDM rate or not" in ADHOC mode + // if setting changed, need to reset current TX rate as well as BEACON frame format + pAdapter->CommonCfg.PhyMode = StaConfig.AdhocMode; + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + { + RTMPSetPhyMode(pAdapter, PhyMode); + MlmeUpdateTxRates(pAdapter, FALSE, 0); + MakeIbssBeacon(pAdapter); // re-build BEACON frame + AsicEnableIbssSync(pAdapter); // copy to on-chip memory + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_STA_CONFIG (Burst=%d, Protection=%ld,ShortSlot=%d\n", + pAdapter->CommonCfg.bEnableTxBurst, + pAdapter->CommonCfg.UseBGProtection, + pAdapter->CommonCfg.bUseShortSlotTime)); + } + break; + case OID_802_11_DESIRED_RATES: + if (wrq->u.data.length != sizeof(NDIS_802_11_RATES)) + Status = -EINVAL; + else + { + Status = copy_from_user(&aryRates, wrq->u.data.pointer, wrq->u.data.length); + NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES)); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DESIRED_RATES (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n", + pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1], + pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3], + pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5], + pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] )); + // Changing DesiredRate may affect the MAX TX rate we used to TX frames out + MlmeUpdateTxRates(pAdapter, FALSE, 0); + } + break; + case RT_OID_802_11_PREAMBLE: + if (wrq->u.data.length != sizeof(RT_802_11_PREAMBLE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&Preamble, wrq->u.data.pointer, wrq->u.data.length); + if (Preamble == Rt802_11PreambleShort) + { + pAdapter->CommonCfg.TxPreamble = Preamble; + MlmeSetTxPreamble(pAdapter, Rt802_11PreambleShort); + } + else if ((Preamble == Rt802_11PreambleLong) || (Preamble == Rt802_11PreambleAuto)) + { + // if user wants AUTO, initialize to LONG here, then change according to AP's + // capability upon association. + pAdapter->CommonCfg.TxPreamble = Preamble; + MlmeSetTxPreamble(pAdapter, Rt802_11PreambleLong); + } + else + { + Status = -EINVAL; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_PREAMBLE (=%d)\n", Preamble)); + } + break; + case OID_802_11_WEP_STATUS: + if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS)) + Status = -EINVAL; + else + { + Status = copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length); + // Since TKIP, AES, WEP are all supported. It should not have any invalid setting + if (WepStatus <= Ndis802_11Encryption3KeyAbsent) + { + if (pAdapter->StaCfg.WepStatus != WepStatus) + { + // Config has changed + pAdapter->bConfigChanged = TRUE; + } + pAdapter->StaCfg.WepStatus = WepStatus; + pAdapter->StaCfg.OrigWepStatus = WepStatus; + pAdapter->StaCfg.PairCipher = WepStatus; + pAdapter->StaCfg.GroupCipher = WepStatus; + } + else + { + Status = -EINVAL; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus)); + } + break; + case OID_802_11_AUTHENTICATION_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_AUTHENTICATION_MODE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&AuthMode, wrq->u.data.pointer, wrq->u.data.length); + if (AuthMode > Ndis802_11AuthModeMax) + { + Status = -EINVAL; + break; + } + else + { + if (pAdapter->StaCfg.AuthMode != AuthMode) + { + // Config has changed + pAdapter->bConfigChanged = TRUE; + } + pAdapter->StaCfg.AuthMode = AuthMode; + } + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n",pAdapter->StaCfg.AuthMode)); + } + break; + case OID_802_11_INFRASTRUCTURE_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_INFRASTRUCTURE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&BssType, wrq->u.data.pointer, wrq->u.data.length); + + if (BssType == Ndis802_11IBSS) + Set_NetworkType_Proc(pAdapter, "Adhoc"); + else if (BssType == Ndis802_11Infrastructure) + Set_NetworkType_Proc(pAdapter, "Infra"); + else if (BssType == Ndis802_11Monitor) + Set_NetworkType_Proc(pAdapter, "Monitor"); + else + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_INFRASTRUCTURE_MODE (unknown)\n")); + } + } + break; + case OID_802_11_REMOVE_WEP: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_WEP\n")); + if (wrq->u.data.length != sizeof(NDIS_802_11_KEY_INDEX)) + { + Status = -EINVAL; + } + else + { + KeyIdx = *(NDIS_802_11_KEY_INDEX *) wrq->u.data.pointer; + + if (KeyIdx & 0x80000000) + { + // Should never set default bit when remove key + Status = -EINVAL; + } + else + { + KeyIdx = KeyIdx & 0x0fffffff; + if (KeyIdx >= 4){ + Status = -EINVAL; + } + else + { + pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0; + pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx); + } + } + } + break; + case RT_OID_802_11_RESET_COUNTERS: + NdisZeroMemory(&pAdapter->WlanCounters, sizeof(COUNTER_802_11)); + NdisZeroMemory(&pAdapter->Counters8023, sizeof(COUNTER_802_3)); + NdisZeroMemory(&pAdapter->RalinkCounters, sizeof(COUNTER_RALINK)); + pAdapter->Counters8023.RxNoBuffer = 0; + pAdapter->Counters8023.GoodReceives = 0; + pAdapter->Counters8023.RxNoBuffer = 0; +#ifdef RT2870 + pAdapter->BulkOutComplete = 0; + pAdapter->BulkOutCompleteOther= 0; + pAdapter->BulkOutCompleteCancel = 0; + pAdapter->BulkOutReq = 0; + pAdapter->BulkInReq= 0; + pAdapter->BulkInComplete = 0; + pAdapter->BulkInCompleteFail = 0; +#endif // RT2870 // + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_RESET_COUNTERS \n")); + break; + case OID_802_11_RTS_THRESHOLD: + if (wrq->u.data.length != sizeof(NDIS_802_11_RTS_THRESHOLD)) + Status = -EINVAL; + else + { + Status = copy_from_user(&RtsThresh, wrq->u.data.pointer, wrq->u.data.length); + if (RtsThresh > MAX_RTS_THRESHOLD) + Status = -EINVAL; + else + pAdapter->CommonCfg.RtsThreshold = (USHORT)RtsThresh; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_RTS_THRESHOLD (=%ld)\n",RtsThresh)); + break; + case OID_802_11_FRAGMENTATION_THRESHOLD: + if (wrq->u.data.length != sizeof(NDIS_802_11_FRAGMENTATION_THRESHOLD)) + Status = -EINVAL; + else + { + Status = copy_from_user(&FragThresh, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->CommonCfg.bUseZeroToDisableFragment = FALSE; + if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD) + { + if (FragThresh == 0) + { + pAdapter->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD; + pAdapter->CommonCfg.bUseZeroToDisableFragment = TRUE; + } + else + Status = -EINVAL; + } + else + pAdapter->CommonCfg.FragmentThreshold = (USHORT)FragThresh; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_FRAGMENTATION_THRESHOLD (=%ld) \n",FragThresh)); + break; + case OID_802_11_POWER_MODE: + if (wrq->u.data.length != sizeof(NDIS_802_11_POWER_MODE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&PowerMode, wrq->u.data.pointer, wrq->u.data.length); + if (PowerMode == Ndis802_11PowerModeCAM) + Set_PSMode_Proc(pAdapter, "CAM"); + else if (PowerMode == Ndis802_11PowerModeMAX_PSP) + Set_PSMode_Proc(pAdapter, "Max_PSP"); + else if (PowerMode == Ndis802_11PowerModeFast_PSP) + Set_PSMode_Proc(pAdapter, "Fast_PSP"); + else if (PowerMode == Ndis802_11PowerModeLegacy_PSP) + Set_PSMode_Proc(pAdapter, "Legacy_PSP"); + else + Status = -EINVAL; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_POWER_MODE (=%d)\n",PowerMode)); + break; + case RT_OID_802_11_TX_POWER_LEVEL_1: + if (wrq->u.data.length < sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&PowerTemp, wrq->u.data.pointer, wrq->u.data.length); + if (PowerTemp > 100) + PowerTemp = 0xffffffff; // AUTO + pAdapter->CommonCfg.TxPowerDefault = PowerTemp; //keep current setting. + pAdapter->CommonCfg.TxPowerPercentage = pAdapter->CommonCfg.TxPowerDefault; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage)); + } + break; + case OID_802_11_NETWORK_TYPE_IN_USE: + if (wrq->u.data.length != sizeof(NDIS_802_11_NETWORK_TYPE)) + Status = -EINVAL; + else + { + Status = copy_from_user(&NetType, wrq->u.data.pointer, wrq->u.data.length); + + if (NetType == Ndis802_11DS) + RTMPSetPhyMode(pAdapter, PHY_11B); + else if (NetType == Ndis802_11OFDM24) + RTMPSetPhyMode(pAdapter, PHY_11BG_MIXED); + else if (NetType == Ndis802_11OFDM5) + RTMPSetPhyMode(pAdapter, PHY_11A); + else + Status = -EINVAL; +#ifdef DOT11_N_SUPPORT + if (Status == NDIS_STATUS_SUCCESS) + SetCommonHT(pAdapter); +#endif // DOT11_N_SUPPORT // + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_NETWORK_TYPE_IN_USE (=%d)\n",NetType)); + } + break; + // For WPA PSK PMK key + case RT_OID_802_11_ADD_WPA: + pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + if(pKey == NULL) + { + Status = -ENOMEM; + break; + } + + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + if (pKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!!\n")); + } + else + { + if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && + (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) ) + { + Status = -EOPNOTSUPP; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA, Failed!! [AuthMode != WPAPSK/WPA2PSK/WPANONE]\n")); + } + else if ((pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) || + (pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) ) // Only for WPA PSK mode + { + NdisMoveMemory(pAdapter->StaCfg.PMK, &pKey->KeyMaterial, pKey->KeyLength); + // Use RaConfig as PSK agent. + // Start STA supplicant state machine + if (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) + pAdapter->StaCfg.WpaState = SS_START; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); + } + else + { + pAdapter->StaCfg.WpaState = SS_NOTUSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_WPA (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); + } + } + kfree(pKey); + break; + case OID_802_11_REMOVE_KEY: + pRemoveKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + if(pRemoveKey == NULL) + { + Status = -ENOMEM; + break; + } + + Status = copy_from_user(pRemoveKey, wrq->u.data.pointer, wrq->u.data.length); + if (pRemoveKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!\n")); + } + else + { + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + { + RTMPWPARemoveKeyProc(pAdapter, pRemoveKey); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Remove WPA Key!!\n")); + } + else + { + KeyIdx = pRemoveKey->KeyIndex; + + if (KeyIdx & 0x80000000) + { + // Should never set default bit when remove key + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(Should never set default bit when remove key)\n")); + } + else + { + KeyIdx = KeyIdx & 0x0fffffff; + if (KeyIdx > 3) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY, Failed!!(KeyId[%d] out of range)\n", KeyIdx)); + } + else + { + pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = 0; + pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE; + AsicRemoveSharedKeyEntry(pAdapter, 0, (UCHAR)KeyIdx); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_REMOVE_KEY (id=0x%x, Len=%d-byte)\n", pRemoveKey->KeyIndex, pRemoveKey->Length)); + } + } + } + } + kfree(pRemoveKey); + break; + // New for WPA + case OID_802_11_ADD_KEY: + pKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + if(pKey == NULL) + { + Status = -ENOMEM; + break; + } + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + if (pKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY, Failed!!\n")); + } + else + { + RTMPAddKey(pAdapter, pKey); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_KEY (id=0x%x, Len=%d-byte)\n", pKey->KeyIndex, pKey->KeyLength)); + } + kfree(pKey); + break; + case OID_802_11_CONFIGURATION: + if (wrq->u.data.length != sizeof(NDIS_802_11_CONFIGURATION)) + Status = -EINVAL; + else + { + Status = copy_from_user(&Config, wrq->u.data.pointer, wrq->u.data.length); + pConfig = &Config; + + if ((pConfig->BeaconPeriod >= 20) && (pConfig->BeaconPeriod <=400)) + pAdapter->CommonCfg.BeaconPeriod = (USHORT) pConfig->BeaconPeriod; + + pAdapter->StaActive.AtimWin = (USHORT) pConfig->ATIMWindow; + MAP_KHZ_TO_CHANNEL_ID(pConfig->DSConfig, pAdapter->CommonCfg.Channel); + // + // Save the channel on MlmeAux for CntlOidRTBssidProc used. + // + pAdapter->MlmeAux.Channel = pAdapter->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CONFIGURATION (BeacnPeriod=%ld,AtimW=%ld,Ch=%d)\n", + pConfig->BeaconPeriod, pConfig->ATIMWindow, pAdapter->CommonCfg.Channel)); + // Config has changed + pAdapter->bConfigChanged = TRUE; + } + break; +#ifdef DOT11_N_SUPPORT + case RT_OID_802_11_SET_HT_PHYMODE: + if (wrq->u.data.length != sizeof(OID_SET_HT_PHYMODE)) + Status = -EINVAL; + else + { + POID_SET_HT_PHYMODE pHTPhyMode = &HT_PhyMode; + + Status = copy_from_user(&HT_PhyMode, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::pHTPhyMode (PhyMode = %d,TransmitNo = %d, HtMode = %d, ExtOffset = %d , MCS = %d, BW = %d, STBC = %d, SHORTGI = %d) \n", + pHTPhyMode->PhyMode, pHTPhyMode->TransmitNo,pHTPhyMode->HtMode,pHTPhyMode->ExtOffset, + pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->SHORTGI)); + if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) + RTMPSetHT(pAdapter, pHTPhyMode); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_HT_PHYMODE(MCS=%d,BW=%d,SGI=%d,STBC=%d)\n", + pAdapter->StaCfg.HTPhyMode.field.MCS, pAdapter->StaCfg.HTPhyMode.field.BW, pAdapter->StaCfg.HTPhyMode.field.ShortGI, + pAdapter->StaCfg.HTPhyMode.field.STBC)); + break; +#endif // DOT11_N_SUPPORT // + case RT_OID_802_11_SET_APSD_SETTING: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + ULONG apsd ; + Status = copy_from_user(&apsd, wrq->u.data.pointer, wrq->u.data.length); + + /*------------------------------------------------------------------- + |B31~B7 | B6~B5 | B4 | B3 | B2 | B1 | B0 | + --------------------------------------------------------------------- + | Rsvd | Max SP Len | AC_VO | AC_VI | AC_BK | AC_BE | APSD Capable | + ---------------------------------------------------------------------*/ + pAdapter->CommonCfg.bAPSDCapable = (apsd & 0x00000001) ? TRUE : FALSE; + pAdapter->CommonCfg.bAPSDAC_BE = ((apsd & 0x00000002) >> 1) ? TRUE : FALSE; + pAdapter->CommonCfg.bAPSDAC_BK = ((apsd & 0x00000004) >> 2) ? TRUE : FALSE; + pAdapter->CommonCfg.bAPSDAC_VI = ((apsd & 0x00000008) >> 3) ? TRUE : FALSE; + pAdapter->CommonCfg.bAPSDAC_VO = ((apsd & 0x00000010) >> 4) ? TRUE : FALSE; + pAdapter->CommonCfg.MaxSPLength = (UCHAR)((apsd & 0x00000060) >> 5); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_SETTING (apsd=0x%lx, APSDCap=%d, [BE,BK,VI,VO]=[%d/%d/%d/%d], MaxSPLen=%d)\n", apsd, pAdapter->CommonCfg.bAPSDCapable, + pAdapter->CommonCfg.bAPSDAC_BE, pAdapter->CommonCfg.bAPSDAC_BK, pAdapter->CommonCfg.bAPSDAC_VI, pAdapter->CommonCfg.bAPSDAC_VO, pAdapter->CommonCfg.MaxSPLength)); + } + break; + + case RT_OID_802_11_SET_APSD_PSM: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + // Driver needs to notify AP when PSM changes + Status = copy_from_user(&pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.pointer, wrq->u.data.length); + if (pAdapter->CommonCfg.bAPSDForcePowerSave != pAdapter->StaCfg.Psm) + { + MlmeSetPsmBit(pAdapter, pAdapter->CommonCfg.bAPSDForcePowerSave); + RTMPSendNullFrame(pAdapter, pAdapter->CommonCfg.TxRate, TRUE); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_APSD_PSM (bAPSDForcePowerSave:%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave)); + } + break; +#ifdef QOS_DLS_SUPPORT + case RT_OID_802_11_SET_DLS: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + BOOLEAN oldvalue = pAdapter->CommonCfg.bDLSCapable; + Status = copy_from_user(&pAdapter->CommonCfg.bDLSCapable, wrq->u.data.pointer, wrq->u.data.length); + if (oldvalue && !pAdapter->CommonCfg.bDLSCapable) + { + int i; + // tear down local dls table entry + for (i=0; iStaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAdapter->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAdapter->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr); + } + } + + // tear down peer dls table entry + for (i=MAX_NUM_OF_INIT_DLS_ENTRY; iStaCfg.DLSEntry[i].Valid && (pAdapter->StaCfg.DLSEntry[i].Status == DLS_FINISH)) + { + pAdapter->StaCfg.DLSEntry[i].Status = DLS_NONE; + pAdapter->StaCfg.DLSEntry[i].Valid = FALSE; + RTMPSendDLSTearDownFrame(pAdapter, pAdapter->StaCfg.DLSEntry[i].MacAddr); + } + } + } + + DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS (=%d)\n", pAdapter->CommonCfg.bDLSCapable)); + } + break; + + case RT_OID_802_11_SET_DLS_PARAM: + if (wrq->u.data.length != sizeof(RT_802_11_DLS_UI)) + Status = -EINVAL; + else + { + RT_802_11_DLS Dls; + + NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS)); + RTMPMoveMemory(&Dls, wrq->u.data.pointer, sizeof(RT_802_11_DLS_UI)); + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + RT_OID_802_11_SET_DLS_PARAM, + sizeof(RT_802_11_DLS), + &Dls); + DBGPRINT(RT_DEBUG_TRACE,("Set::RT_OID_802_11_SET_DLS_PARAM \n")); + } + break; +#endif // QOS_DLS_SUPPORT // + case RT_OID_802_11_SET_WMM: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&pAdapter->CommonCfg.bWmmCapable, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_SET_WMM (=%d) \n", pAdapter->CommonCfg.bWmmCapable)); + } + break; + + case OID_802_11_DISASSOCIATE: +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + break; + } +#endif // RALINK_ATE // + // + // Set NdisRadioStateOff to TRUE, instead of called MlmeRadioOff. + // Later on, NDIS_802_11_BSSID_LIST_EX->NumberOfItems should be 0 + // when query OID_802_11_BSSID_LIST. + // + // TRUE: NumberOfItems will set to 0. + // FALSE: NumberOfItems no change. + // + pAdapter->CommonCfg.NdisRadioStateOff = TRUE; + // Set to immediately send the media disconnect event + pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DISASSOCIATE \n")); + + if (INFRA_ON(pAdapter)) + { + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_DISASSOCIATE, + 0, + NULL); + + StateMachineTouched = TRUE; + } + break; + +#ifdef DOT11_N_SUPPORT + case RT_OID_802_11_SET_IMME_BA_CAP: + if (wrq->u.data.length != sizeof(OID_BACAP_STRUC)) + Status = -EINVAL; + else + { + OID_BACAP_STRUC Orde ; + Status = copy_from_user(&Orde, wrq->u.data.pointer, wrq->u.data.length); + if (Orde.Policy > BA_NOTUSE) + { + Status = NDIS_STATUS_INVALID_DATA; + } + else if (Orde.Policy == BA_NOTUSE) + { + pAdapter->CommonCfg.BACapability.field.Policy = BA_NOTUSE; + pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity; + pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity; + pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable; + pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize; + pAdapter->CommonCfg.DesiredHtPhy.MimoPs= Orde.MMPSmode; + pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode; + // UPdata to HT IE + pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode; + pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize; + pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity; + } + else + { + pAdapter->CommonCfg.BACapability.field.AutoBA = Orde.AutoBA; + pAdapter->CommonCfg.BACapability.field.Policy = IMMED_BA; // we only support immediate BA. + pAdapter->CommonCfg.BACapability.field.MpduDensity = Orde.MpduDensity; + pAdapter->CommonCfg.DesiredHtPhy.MpduDensity = Orde.MpduDensity; + pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable = Orde.AmsduEnable; + pAdapter->CommonCfg.DesiredHtPhy.AmsduSize= Orde.AmsduSize; + pAdapter->CommonCfg.DesiredHtPhy.MimoPs = Orde.MMPSmode; + pAdapter->CommonCfg.BACapability.field.MMPSmode = Orde.MMPSmode; + + // UPdata to HT IE + pAdapter->CommonCfg.HtCapability.HtCapInfo.MimoPs = Orde.MMPSmode; + pAdapter->CommonCfg.HtCapability.HtCapInfo.AMsduSize = Orde.AmsduSize; + pAdapter->CommonCfg.HtCapability.HtCapParm.MpduDensity = Orde.MpduDensity; + + if (pAdapter->CommonCfg.BACapability.field.RxBAWinLimit > MAX_RX_REORDERBUF) + pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = MAX_RX_REORDERBUF; + + } + + pAdapter->CommonCfg.REGBACapability.word = pAdapter->CommonCfg.BACapability.word; + DBGPRINT(RT_DEBUG_TRACE, ("Set::(Orde.AutoBA = %d) (Policy=%d)(ReBAWinLimit=%d)(TxBAWinLimit=%d)(AutoMode=%d)\n",Orde.AutoBA, pAdapter->CommonCfg.BACapability.field.Policy, + pAdapter->CommonCfg.BACapability.field.RxBAWinLimit,pAdapter->CommonCfg.BACapability.field.TxBAWinLimit, pAdapter->CommonCfg.BACapability.field.AutoBA)); + DBGPRINT(RT_DEBUG_TRACE, ("Set::(MimoPs = %d)(AmsduEnable = %d) (AmsduSize=%d)(MpduDensity=%d)\n",pAdapter->CommonCfg.DesiredHtPhy.MimoPs, pAdapter->CommonCfg.DesiredHtPhy.AmsduEnable, + pAdapter->CommonCfg.DesiredHtPhy.AmsduSize, pAdapter->CommonCfg.DesiredHtPhy.MpduDensity)); + } + + break; + case RT_OID_802_11_ADD_IMME_BA: + DBGPRINT(RT_DEBUG_TRACE, (" Set :: RT_OID_802_11_ADD_IMME_BA \n")); + if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY)) + Status = -EINVAL; + else + { + UCHAR index; + OID_ADD_BA_ENTRY BA; + MAC_TABLE_ENTRY *pEntry; + + Status = copy_from_user(&BA, wrq->u.data.pointer, wrq->u.data.length); + if (BA.TID > 15) + { + Status = NDIS_STATUS_INVALID_DATA; + break; + } + else + { + //BATableInsertEntry + //As ad-hoc mode, BA pair is not limited to only BSSID. so add via OID. + index = BA.TID; + // in ad hoc mode, when adding BA pair, we should insert this entry into MACEntry too + pEntry = MacTableLookup(pAdapter, BA.MACAddr); + if (!pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_ADD_IMME_BA. break on no connection.----:%x:%x\n", BA.MACAddr[4], BA.MACAddr[5])); + break; + } + if (BA.IsRecipient == FALSE) + { + if (pEntry->bIAmBadAtheros == TRUE) + pAdapter->CommonCfg.BACapability.field.RxBAWinLimit = 0x10; + + BAOriSessionSetUp(pAdapter, pEntry, index, 0, 100, TRUE); + } + else + { + //BATableInsertEntry(pAdapter, pEntry->Aid, BA.MACAddr, 0, 0xffff, BA.TID, BA.nMSDU, BA.IsRecipient); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_802_11_ADD_IMME_BA. Rec = %d. Mac = %x:%x:%x:%x:%x:%x . \n", + BA.IsRecipient, BA.MACAddr[0], BA.MACAddr[1], BA.MACAddr[2], BA.MACAddr[2] + , BA.MACAddr[4], BA.MACAddr[5])); + } + } + break; + + case RT_OID_802_11_TEAR_IMME_BA: + DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA \n")); + if (wrq->u.data.length != sizeof(OID_ADD_BA_ENTRY)) + Status = -EINVAL; + else + { + POID_ADD_BA_ENTRY pBA; + MAC_TABLE_ENTRY *pEntry; + + pBA = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + + if (pBA == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA kmalloc() can't allocate enough memory\n")); + Status = NDIS_STATUS_FAILURE; + } + else + { + Status = copy_from_user(pBA, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Set :: RT_OID_802_11_TEAR_IMME_BA(TID=%d, bAllTid=%d)\n", pBA->TID, pBA->bAllTid)); + + if (!pBA->bAllTid && (pBA->TID > NUM_OF_TID)) + { + Status = NDIS_STATUS_INVALID_DATA; + break; + } + + if (pBA->IsRecipient == FALSE) + { + pEntry = MacTableLookup(pAdapter, pBA->MACAddr); + DBGPRINT(RT_DEBUG_TRACE, (" pBA->IsRecipient == FALSE\n")); + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, (" pBA->pEntry\n")); + BAOriSessionTearDown(pAdapter, pEntry->Aid, pBA->TID, FALSE, TRUE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n")); + } + else + { + pEntry = MacTableLookup(pAdapter, pBA->MACAddr); + if (pEntry) + { + BARecSessionTearDown( pAdapter, (UCHAR)pEntry->Aid, pBA->TID, TRUE); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Set :: Not found pEntry \n")); + } + kfree(pBA); + } + } + break; +#endif // DOT11_N_SUPPORT // + + // For WPA_SUPPLICANT to set static wep key + case OID_802_11_ADD_WEP: + pWepKey = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + + if(pWepKey == NULL) + { + Status = -ENOMEM; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed!!\n")); + break; + } + Status = copy_from_user(pWepKey, wrq->u.data.pointer, wrq->u.data.length); + if (Status) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (length mismatch)!!\n")); + } + else + { + KeyIdx = pWepKey->KeyIndex & 0x0fffffff; + // KeyIdx must be 0 ~ 3 + if (KeyIdx > 4) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, Failed (KeyIdx must be smaller than 4)!!\n")); + } + else + { + UCHAR CipherAlg = 0; + PUCHAR Key; + + // set key material and key length + NdisZeroMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, 16); + pAdapter->SharedKey[BSS0][KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAdapter->SharedKey[BSS0][KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); + + switch(pWepKey->KeyLength) + { + case 5: + CipherAlg = CIPHER_WEP64; + break; + case 13: + CipherAlg = CIPHER_WEP128; + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP, only support CIPHER_WEP64(len:5) & CIPHER_WEP128(len:13)!!\n")); + Status = -EINVAL; + break; + } + pAdapter->SharedKey[BSS0][KeyIdx].CipherAlg = CipherAlg; + + // Default key for tx (shared key) + if (pWepKey->KeyIndex & 0x80000000) + { +#ifdef WPA_SUPPLICANT_SUPPORT + // set key material and key length + NdisZeroMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, 16); + pAdapter->StaCfg.DesireSharedKey[KeyIdx].KeyLen = (UCHAR) pWepKey->KeyLength; + NdisMoveMemory(pAdapter->StaCfg.DesireSharedKey[KeyIdx].Key, &pWepKey->KeyMaterial, pWepKey->KeyLength); + pAdapter->StaCfg.DesireSharedKeyId = KeyIdx; + pAdapter->StaCfg.DesireSharedKey[KeyIdx].CipherAlg = CipherAlg; +#endif // WPA_SUPPLICANT_SUPPORT // + pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; + } + +#ifdef WPA_SUPPLICANT_SUPPORT + if (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) +#endif // WPA_SUPPLICANT_SUPPORT + { + Key = pAdapter->SharedKey[BSS0][KeyIdx].Key; + + // Set key material and cipherAlg to Asic + AsicAddSharedKeyEntry(pAdapter, BSS0, KeyIdx, CipherAlg, Key, NULL, NULL); + + if (pWepKey->KeyIndex & 0x80000000) + { + PMAC_TABLE_ENTRY pEntry = &pAdapter->MacTab.Content[BSSID_WCID]; + // Assign group key info + RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, NULL); + // Assign pairwise key info + RTMPAddWcidAttributeEntry(pAdapter, BSS0, KeyIdx, CipherAlg, pEntry); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_ADD_WEP (id=0x%x, Len=%d-byte), %s\n", pWepKey->KeyIndex, pWepKey->KeyLength, (pAdapter->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED) ? "Port Secured":"Port NOT Secured")); + } + } + kfree(pWepKey); + break; +#ifdef WPA_SUPPLICANT_SUPPORT + case OID_SET_COUNTERMEASURES: + if (wrq->u.data.length != sizeof(int)) + Status = -EINVAL; + else + { + int enabled = 0; + Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); + if (enabled == 1) + pAdapter->StaCfg.bBlockAssoc = TRUE; + else + // WPA MIC error should block association attempt for 60 seconds + pAdapter->StaCfg.bBlockAssoc = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_SET_COUNTERMEASURES bBlockAssoc=%s\n", pAdapter->StaCfg.bBlockAssoc ? "TRUE":"FALSE")); + } + break; + case RT_OID_WPA_SUPPLICANT_SUPPORT: + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + Status = copy_from_user(&wpa_supplicant_enable, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->StaCfg.WpaSupplicantUP = wpa_supplicant_enable; + DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP)); + } + break; + case OID_802_11_DEAUTHENTICATION: + if (wrq->u.data.length != sizeof(MLME_DEAUTH_REQ_STRUCT)) + Status = -EINVAL; + else + { + MLME_DEAUTH_REQ_STRUCT *pInfo; + MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); + + pInfo = (MLME_DEAUTH_REQ_STRUCT *) MsgElem->Msg; + Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length); + MlmeDeauthReqAction(pAdapter, MsgElem); + kfree(MsgElem); + + if (INFRA_ON(pAdapter)) + { + LinkDown(pAdapter, FALSE); + pAdapter->Mlme.AssocMachine.CurrState = ASSOC_IDLE; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason)); + } + break; + case OID_802_11_DROP_UNENCRYPTED: + if (wrq->u.data.length != sizeof(int)) + Status = -EINVAL; + else + { + int enabled = 0; + Status = copy_from_user(&enabled, wrq->u.data.pointer, wrq->u.data.length); + if (enabled == 1) + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; + NdisAcquireSpinLock(&pAdapter->MacTabLock); + pAdapter->MacTab.Content[BSSID_WCID].PortSecured = pAdapter->StaCfg.PortSecured; + NdisReleaseSpinLock(&pAdapter->MacTabLock); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DROP_UNENCRYPTED (=%d)\n", enabled)); + } + break; + case OID_802_11_SET_IEEE8021X: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&IEEE8021xState, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->StaCfg.IEEE8021X = IEEE8021xState; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X (=%d)\n", IEEE8021xState)); + } + break; + case OID_802_11_SET_IEEE8021X_REQUIRE_KEY: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + Status = copy_from_user(&IEEE8021x_required_keys, wrq->u.data.pointer, wrq->u.data.length); + pAdapter->StaCfg.IEEE8021x_required_keys = IEEE8021x_required_keys; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SET_IEEE8021X_REQUIRE_KEY (%d)\n", IEEE8021x_required_keys)); + } + break; + case OID_802_11_PMKID: + pPmkId = kmalloc(wrq->u.data.length, MEM_ALLOC_FLAG); + + if(pPmkId == NULL) { + Status = -ENOMEM; + break; + } + Status = copy_from_user(pPmkId, wrq->u.data.pointer, wrq->u.data.length); + + // check the PMKID information + if (pPmkId->BSSIDInfoCount == 0) + NdisZeroMemory(pAdapter->StaCfg.SavedPMK, sizeof(BSSID_INFO)*PMKID_NO); + else + { + PBSSID_INFO pBssIdInfo; + UINT BssIdx; + UINT CachedIdx; + + for (BssIdx = 0; BssIdx < pPmkId->BSSIDInfoCount; BssIdx++) + { + // point to the indexed BSSID_INFO structure + pBssIdInfo = (PBSSID_INFO) ((PUCHAR) pPmkId + 2 * sizeof(UINT) + BssIdx * sizeof(BSSID_INFO)); + // Find the entry in the saved data base. + for (CachedIdx = 0; CachedIdx < pAdapter->StaCfg.SavedPMKNum; CachedIdx++) + { + // compare the BSSID + if (NdisEqualMemory(pBssIdInfo->BSSID, pAdapter->StaCfg.SavedPMK[CachedIdx].BSSID, sizeof(NDIS_802_11_MAC_ADDRESS))) + break; + } + + // Found, replace it + if (CachedIdx < PMKID_NO) + { + DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); + pAdapter->StaCfg.SavedPMKNum++; + } + // Not found, replace the last one + else + { + // Randomly replace one + CachedIdx = (pBssIdInfo->BSSID[5] % PMKID_NO); + DBGPRINT(RT_DEBUG_OFF, ("Update OID_802_11_PMKID, idx = %d\n", CachedIdx)); + NdisMoveMemory(&pAdapter->StaCfg.SavedPMK[CachedIdx], pBssIdInfo, sizeof(BSSID_INFO)); + } + } + } + if(pPmkId) + kfree(pPmkId); + break; +#endif // WPA_SUPPLICANT_SUPPORT // + + + +#ifdef SNMP_SUPPORT + case OID_802_11_SHORTRETRYLIMIT: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&ShortRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; + RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SHORTRETRYLIMIT (tx_rty_cfg.field.ShortRetryLimit=%d, ShortRetryLimit=%ld)\n", tx_rty_cfg.field.ShortRtyLimit, ShortRetryLimit)); + } + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT \n")); + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&LongRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; + RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT (tx_rty_cfg.field.LongRetryLimit= %d,LongRetryLimit=%ld)\n", tx_rty_cfg.field.LongRtyLimit, LongRetryLimit)); + } + break; + + case OID_802_11_WEPDEFAULTKEYVALUE: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE\n")); + pKey = kmalloc(wrq->u.data.length, GFP_KERNEL); + Status = copy_from_user(pKey, wrq->u.data.pointer, wrq->u.data.length); + //pKey = &WepKey; + + if ( pKey->Length != wrq->u.data.length) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE, Failed!!\n")); + } + KeyIdx = pKey->KeyIndex & 0x0fffffff; + DBGPRINT(RT_DEBUG_TRACE,("pKey->KeyIndex =%d, pKey->KeyLength=%d\n", pKey->KeyIndex, pKey->KeyLength)); + + // it is a shared key + if (KeyIdx > 4) + Status = -EINVAL; + else + { + pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(&pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, &pKey->KeyMaterial, pKey->KeyLength); + if (pKey->KeyIndex & 0x80000000) + { + // Default key for tx (shared key) + pAdapter->StaCfg.DefaultKeyId = (UCHAR) KeyIdx; + } + //RestartAPIsRequired = TRUE; + } + break; + + + case OID_802_11_WEPDEFAULTKEYID: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYID \n")); + + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + Status = copy_from_user(&pAdapter->StaCfg.DefaultKeyId, wrq->u.data.pointer, wrq->u.data.length); + + break; + + + case OID_802_11_CURRENTCHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_CURRENTCHANNEL \n")); + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + Status = copy_from_user(&ctmp, wrq->u.data.pointer, wrq->u.data.length); + sprintf(&ctmp,"%d", ctmp); + Set_Channel_Proc(pAdapter, &ctmp); + } + break; +#endif + + + + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + + + return Status; +} + +INT RTMPQueryInformation( + IN PRTMP_ADAPTER pAdapter, + IN OUT struct ifreq *rq, + IN INT cmd) +{ + struct iwreq *wrq = (struct iwreq *) rq; + NDIS_802_11_BSSID_LIST_EX *pBssidList = NULL; + PNDIS_WLAN_BSSID_EX pBss; + NDIS_802_11_SSID Ssid; + NDIS_802_11_CONFIGURATION *pConfiguration = NULL; + RT_802_11_LINK_STATUS *pLinkStatus = NULL; + RT_802_11_STA_CONFIG *pStaConfig = NULL; + NDIS_802_11_STATISTICS *pStatistics = NULL; + NDIS_802_11_RTS_THRESHOLD RtsThresh; + NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh; + NDIS_802_11_POWER_MODE PowerMode; + NDIS_802_11_NETWORK_INFRASTRUCTURE BssType; + RT_802_11_PREAMBLE PreamType; + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_MEDIA_STATE MediaState; + ULONG BssBufSize, ulInfo=0, NetworkTypeList[4], apsd = 0; + USHORT BssLen = 0; + PUCHAR pBuf = NULL, pPtr; + INT Status = NDIS_STATUS_SUCCESS; + UINT we_version_compiled; + UCHAR i, Padding = 0; + BOOLEAN RadioState; + UCHAR driverVersion[8]; + OID_SET_HT_PHYMODE *pHTPhyMode = NULL; + + +#ifdef SNMP_SUPPORT + //for snmp, kathy + DefaultKeyIdxValue *pKeyIdxValue; + INT valueLen; + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; + UCHAR tmp[64]; +#endif //SNMP + + switch(cmd) + { + case RT_OID_DEVICE_NAME: + wrq->u.data.length = sizeof(STA_NIC_DEVICE_NAME); + Status = copy_to_user(wrq->u.data.pointer, STA_NIC_DEVICE_NAME, wrq->u.data.length); + break; + case RT_OID_VERSION_INFO: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_VERSION_INFO \n")); + wrq->u.data.length = 8*sizeof(UCHAR); + sprintf(&driverVersion[0], "%s", STA_DRIVER_VERSION); + driverVersion[7] = '\0'; + if (copy_to_user(wrq->u.data.pointer, &driverVersion, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#ifdef RALINK_ATE + case RT_QUERY_ATE_TXDONE_COUNT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_QUERY_ATE_TXDONE_COUNT \n")); + wrq->u.data.length = sizeof(UINT32); + if (copy_to_user(wrq->u.data.pointer, &pAdapter->ate.TxDoneCount, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#endif // RALINK_ATE // + case OID_802_11_BSSID_LIST: + if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + * Still scanning, indicate the caller should try again. + */ + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (Still scanning)\n")); + return -EAGAIN; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID_LIST (%d BSS returned)\n",pAdapter->ScanTab.BssNr)); + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; + // Claculate total buffer size required + BssBufSize = sizeof(ULONG); + + for (i = 0; i < pAdapter->ScanTab.BssNr; i++) + { + // Align pointer to 4 bytes boundary. + //Padding = 4 - (pAdapter->ScanTab.BssEntry[i].VarIELen & 0x0003); + //if (Padding == 4) + // Padding = 0; + BssBufSize += (sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding); + } + + // For safety issue, we add 256 bytes just in case + BssBufSize += 256; + // Allocate the same size as passed from higher layer + pBuf = kmalloc(BssBufSize, MEM_ALLOC_FLAG); + if(pBuf == NULL) + { + Status = -ENOMEM; + break; + } + // Init 802_11_BSSID_LIST_EX structure + NdisZeroMemory(pBuf, BssBufSize); + pBssidList = (PNDIS_802_11_BSSID_LIST_EX) pBuf; + pBssidList->NumberOfItems = pAdapter->ScanTab.BssNr; + + // Calculate total buffer length + BssLen = 4; // Consist of NumberOfItems + // Point to start of NDIS_WLAN_BSSID_EX + // pPtr = pBuf + sizeof(ULONG); + pPtr = (PUCHAR) &pBssidList->Bssid[0]; + for (i = 0; i < pAdapter->ScanTab.BssNr; i++) + { + pBss = (PNDIS_WLAN_BSSID_EX) pPtr; + NdisMoveMemory(&pBss->MacAddress, &pAdapter->ScanTab.BssEntry[i].Bssid, MAC_ADDR_LEN); + if ((pAdapter->ScanTab.BssEntry[i].Hidden == 1) && (pAdapter->StaCfg.bShowHiddenSSID == FALSE)) + { + // + // We must return this SSID during 4way handshaking, otherwise Aegis will failed to parse WPA infomation + // and then failed to send EAPOl farame. + // + if ((pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAdapter->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED)) + { + pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen; + NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen); + } + else + pBss->Ssid.SsidLength = 0; + } + else + { + pBss->Ssid.SsidLength = pAdapter->ScanTab.BssEntry[i].SsidLen; + NdisMoveMemory(pBss->Ssid.Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen); + } + pBss->Privacy = pAdapter->ScanTab.BssEntry[i].Privacy; + pBss->Rssi = pAdapter->ScanTab.BssEntry[i].Rssi - pAdapter->BbpRssiToDbmDelta; + pBss->NetworkTypeInUse = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]); + pBss->Configuration.Length = sizeof(NDIS_802_11_CONFIGURATION); + pBss->Configuration.BeaconPeriod = pAdapter->ScanTab.BssEntry[i].BeaconPeriod; + pBss->Configuration.ATIMWindow = pAdapter->ScanTab.BssEntry[i].AtimWin; + + MAP_CHANNEL_ID_TO_KHZ(pAdapter->ScanTab.BssEntry[i].Channel, pBss->Configuration.DSConfig); + + if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_INFRA) + pBss->InfrastructureMode = Ndis802_11Infrastructure; + else + pBss->InfrastructureMode = Ndis802_11IBSS; + + NdisMoveMemory(pBss->SupportedRates, pAdapter->ScanTab.BssEntry[i].SupRate, pAdapter->ScanTab.BssEntry[i].SupRateLen); + NdisMoveMemory(pBss->SupportedRates + pAdapter->ScanTab.BssEntry[i].SupRateLen, + pAdapter->ScanTab.BssEntry[i].ExtRate, + pAdapter->ScanTab.BssEntry[i].ExtRateLen); + + if (pAdapter->ScanTab.BssEntry[i].VarIELen == 0) + { + pBss->IELength = sizeof(NDIS_802_11_FIXED_IEs); + NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); + pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); + } + else + { + pBss->IELength = (ULONG)(sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen); + pPtr = pPtr + sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs); + NdisMoveMemory(pBss->IEs, &pAdapter->ScanTab.BssEntry[i].FixIEs, sizeof(NDIS_802_11_FIXED_IEs)); + NdisMoveMemory(pBss->IEs + sizeof(NDIS_802_11_FIXED_IEs), pAdapter->ScanTab.BssEntry[i].VarIEs, pAdapter->ScanTab.BssEntry[i].VarIELen); + pPtr += pAdapter->ScanTab.BssEntry[i].VarIELen; + } + pBss->Length = (ULONG)(sizeof(NDIS_WLAN_BSSID_EX) - 1 + sizeof(NDIS_802_11_FIXED_IEs) + pAdapter->ScanTab.BssEntry[i].VarIELen + Padding); + +#if WIRELESS_EXT < 17 + if ((BssLen + pBss->Length) < wrq->u.data.length) + BssLen += pBss->Length; + else + { + pBssidList->NumberOfItems = i; + break; + } +#else + BssLen += pBss->Length; +#endif + } + +#if WIRELESS_EXT < 17 + wrq->u.data.length = BssLen; +#else + if (BssLen > wrq->u.data.length) + { + kfree(pBssidList); + return -E2BIG; + } + else + wrq->u.data.length = BssLen; +#endif + Status = copy_to_user(wrq->u.data.pointer, pBssidList, BssLen); + kfree(pBssidList); + break; + case OID_802_3_CURRENT_ADDRESS: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length); + break; + case OID_GEN_MEDIA_CONNECT_STATUS: + if (pAdapter->IndicateMediaState == NdisMediaStateConnected) + MediaState = NdisMediaStateConnected; + else + MediaState = NdisMediaStateDisconnected; + + wrq->u.data.length = sizeof(NDIS_MEDIA_STATE); + Status = copy_to_user(wrq->u.data.pointer, &MediaState, wrq->u.data.length); + break; + case OID_802_11_BSSID: +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } +#endif // RALINK_ATE // + if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter)) + { + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Bssid, sizeof(NDIS_802_11_MAC_ADDRESS)); + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BSSID(=EMPTY)\n")); + Status = -ENOTCONN; + } + break; + case OID_802_11_SSID: + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + NdisZeroMemory(Ssid.Ssid, MAX_LEN_OF_SSID); + Ssid.SsidLength = pAdapter->CommonCfg.SsidLen; + memcpy(Ssid.Ssid, pAdapter->CommonCfg.Ssid, Ssid.SsidLength); + wrq->u.data.length = sizeof(NDIS_802_11_SSID); + Status = copy_to_user(wrq->u.data.pointer, &Ssid, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SSID (Len=%d, ssid=%s)\n", Ssid.SsidLength,Ssid.Ssid)); + break; + case RT_OID_802_11_QUERY_LINK_STATUS: + pLinkStatus = (RT_802_11_LINK_STATUS *) kmalloc(sizeof(RT_802_11_LINK_STATUS), MEM_ALLOC_FLAG); + if (pLinkStatus) + { + pLinkStatus->CurrTxRate = RateIdTo500Kbps[pAdapter->CommonCfg.TxRate]; // unit : 500 kbps + pLinkStatus->ChannelQuality = pAdapter->Mlme.ChannelQuality; + pLinkStatus->RxByteCount = pAdapter->RalinkCounters.ReceivedByteCount; + pLinkStatus->TxByteCount = pAdapter->RalinkCounters.TransmittedByteCount; + pLinkStatus->CentralChannel = pAdapter->CommonCfg.CentralChannel; + wrq->u.data.length = sizeof(RT_802_11_LINK_STATUS); + Status = copy_to_user(wrq->u.data.pointer, pLinkStatus, wrq->u.data.length); + kfree(pLinkStatus); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LINK_STATUS(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case OID_802_11_CONFIGURATION: + pConfiguration = (NDIS_802_11_CONFIGURATION *) kmalloc(sizeof(NDIS_802_11_CONFIGURATION), MEM_ALLOC_FLAG); + if (pConfiguration) + { + pConfiguration->Length = sizeof(NDIS_802_11_CONFIGURATION); + pConfiguration->BeaconPeriod = pAdapter->CommonCfg.BeaconPeriod; + pConfiguration->ATIMWindow = pAdapter->StaActive.AtimWin; + MAP_CHANNEL_ID_TO_KHZ(pAdapter->CommonCfg.Channel, pConfiguration->DSConfig); + wrq->u.data.length = sizeof(NDIS_802_11_CONFIGURATION); + Status = copy_to_user(wrq->u.data.pointer, pConfiguration, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(BeaconPeriod=%ld,AtimW=%ld,Channel=%d) \n", + pConfiguration->BeaconPeriod, pConfiguration->ATIMWindow, pAdapter->CommonCfg.Channel)); + kfree(pConfiguration); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CONFIGURATION(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case RT_OID_802_11_SNR_0: + if ((pAdapter->StaCfg.LastSNR0 > 0)) + { + ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR0) * 3) / 16 ; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_SNR_0(0x=%lx)\n", ulInfo)); + } + else + Status = -EFAULT; + break; + case RT_OID_802_11_SNR_1: + if ((pAdapter->Antenna.field.RxPath > 1) && + (pAdapter->StaCfg.LastSNR1 > 0)) + { + ulInfo = ((0xeb - pAdapter->StaCfg.LastSNR1) * 3) / 16 ; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(0x=%lx)\n",ulInfo)); + } + else + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE,("Query::RT_OID_802_11_SNR_1(pAdapter->StaCfg.LastSNR1=%d)\n",pAdapter->StaCfg.LastSNR1)); + break; + case OID_802_11_RSSI_TRIGGER: + ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0 - pAdapter->BbpRssiToDbmDelta; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RSSI_TRIGGER(=%ld)\n", ulInfo)); + break; + case OID_802_11_RSSI: + case RT_OID_802_11_RSSI: + ulInfo = pAdapter->StaCfg.RssiSample.LastRssi0; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_RSSI_1: + ulInfo = pAdapter->StaCfg.RssiSample.LastRssi1; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_RSSI_2: + ulInfo = pAdapter->StaCfg.RssiSample.LastRssi2; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case OID_802_11_STATISTICS: + pStatistics = (NDIS_802_11_STATISTICS *) kmalloc(sizeof(NDIS_802_11_STATISTICS), MEM_ALLOC_FLAG); + if (pStatistics) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS \n")); + // add the most up-to-date h/w raw counters into software counters + NICUpdateRawCounters(pAdapter); + + // Sanity check for calculation of sucessful count + if (pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart < pAdapter->WlanCounters.RetryCount.QuadPart) + pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart; + + pStatistics->TransmittedFragmentCount.QuadPart = pAdapter->WlanCounters.TransmittedFragmentCount.QuadPart; + pStatistics->MulticastTransmittedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastTransmittedFrameCount.QuadPart; + pStatistics->FailedCount.QuadPart = pAdapter->WlanCounters.FailedCount.QuadPart; + pStatistics->RetryCount.QuadPart = pAdapter->WlanCounters.RetryCount.QuadPart; + pStatistics->MultipleRetryCount.QuadPart = pAdapter->WlanCounters.MultipleRetryCount.QuadPart; + pStatistics->RTSSuccessCount.QuadPart = pAdapter->WlanCounters.RTSSuccessCount.QuadPart; + pStatistics->RTSFailureCount.QuadPart = pAdapter->WlanCounters.RTSFailureCount.QuadPart; + pStatistics->ACKFailureCount.QuadPart = pAdapter->WlanCounters.ACKFailureCount.QuadPart; + pStatistics->FrameDuplicateCount.QuadPart = pAdapter->WlanCounters.FrameDuplicateCount.QuadPart; + pStatistics->ReceivedFragmentCount.QuadPart = pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart; + pStatistics->MulticastReceivedFrameCount.QuadPart = pAdapter->WlanCounters.MulticastReceivedFrameCount.QuadPart; +#ifdef DBG + pStatistics->FCSErrorCount = pAdapter->RalinkCounters.RealFcsErrCount; +#else + pStatistics->FCSErrorCount.QuadPart = pAdapter->WlanCounters.FCSErrorCount.QuadPart; + pStatistics->FrameDuplicateCount.u.LowPart = pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart / 100; +#endif + wrq->u.data.length = sizeof(NDIS_802_11_STATISTICS); + Status = copy_to_user(wrq->u.data.pointer, pStatistics, wrq->u.data.length); + kfree(pStatistics); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case OID_GEN_RCV_OK: + ulInfo = pAdapter->Counters8023.GoodReceives; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case OID_GEN_RCV_NO_BUFFER: + ulInfo = pAdapter->Counters8023.RxNoBuffer; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_PHY_MODE: + ulInfo = (ULONG)pAdapter->CommonCfg.PhyMode; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PHY_MODE (=%ld)\n", ulInfo)); + break; + case RT_OID_802_11_STA_CONFIG: + pStaConfig = (RT_802_11_STA_CONFIG *) kmalloc(sizeof(RT_802_11_STA_CONFIG), MEM_ALLOC_FLAG); + if (pStaConfig) + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG\n")); + pStaConfig->EnableTxBurst = pAdapter->CommonCfg.bEnableTxBurst; + pStaConfig->EnableTurboRate = 0; + pStaConfig->UseBGProtection = pAdapter->CommonCfg.UseBGProtection; + pStaConfig->UseShortSlotTime = pAdapter->CommonCfg.bUseShortSlotTime; + //pStaConfig->AdhocMode = pAdapter->StaCfg.AdhocMode; + pStaConfig->HwRadioStatus = (pAdapter->StaCfg.bHwRadio == TRUE) ? 1 : 0; + pStaConfig->Rsv1 = 0; + pStaConfig->SystemErrorBitmap = pAdapter->SystemErrorBitmap; + wrq->u.data.length = sizeof(RT_802_11_STA_CONFIG); + Status = copy_to_user(wrq->u.data.pointer, pStaConfig, wrq->u.data.length); + kfree(pStaConfig); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case OID_802_11_RTS_THRESHOLD: + RtsThresh = pAdapter->CommonCfg.RtsThreshold; + wrq->u.data.length = sizeof(RtsThresh); + Status = copy_to_user(wrq->u.data.pointer, &RtsThresh, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_RTS_THRESHOLD(=%ld)\n", RtsThresh)); + break; + case OID_802_11_FRAGMENTATION_THRESHOLD: + FragThresh = pAdapter->CommonCfg.FragmentThreshold; + if (pAdapter->CommonCfg.bUseZeroToDisableFragment == TRUE) + FragThresh = 0; + wrq->u.data.length = sizeof(FragThresh); + Status = copy_to_user(wrq->u.data.pointer, &FragThresh, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_FRAGMENTATION_THRESHOLD(=%ld)\n", FragThresh)); + break; + case OID_802_11_POWER_MODE: + PowerMode = pAdapter->StaCfg.WindowsPowerMode; + wrq->u.data.length = sizeof(PowerMode); + Status = copy_to_user(wrq->u.data.pointer, &PowerMode, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_POWER_MODE(=%d)\n", PowerMode)); + break; + case RT_OID_802_11_RADIO: + RadioState = (BOOLEAN) pAdapter->StaCfg.bSwRadio; + wrq->u.data.length = sizeof(RadioState); + Status = copy_to_user(wrq->u.data.pointer, &RadioState, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_RADIO (=%d)\n", RadioState)); + break; + case OID_802_11_INFRASTRUCTURE_MODE: + if (pAdapter->StaCfg.BssType == BSS_ADHOC) + BssType = Ndis802_11IBSS; + else if (pAdapter->StaCfg.BssType == BSS_INFRA) + BssType = Ndis802_11Infrastructure; + else if (pAdapter->StaCfg.BssType == BSS_MONITOR) + BssType = Ndis802_11Monitor; + else + BssType = Ndis802_11AutoUnknown; + + wrq->u.data.length = sizeof(BssType); + Status = copy_to_user(wrq->u.data.pointer, &BssType, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_INFRASTRUCTURE_MODE(=%d)\n", BssType)); + break; + case RT_OID_802_11_PREAMBLE: + PreamType = pAdapter->CommonCfg.TxPreamble; + wrq->u.data.length = sizeof(PreamType); + Status = copy_to_user(wrq->u.data.pointer, &PreamType, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PREAMBLE(=%d)\n", PreamType)); + break; + case OID_802_11_AUTHENTICATION_MODE: + AuthMode = pAdapter->StaCfg.AuthMode; + wrq->u.data.length = sizeof(AuthMode); + Status = copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AUTHENTICATION_MODE(=%d)\n", AuthMode)); + break; + case OID_802_11_WEP_STATUS: + WepStatus = pAdapter->StaCfg.WepStatus; + wrq->u.data.length = sizeof(WepStatus); + Status = copy_to_user(wrq->u.data.pointer, &WepStatus, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEP_STATUS(=%d)\n", WepStatus)); + break; + case OID_802_11_TX_POWER_LEVEL: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPower, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_TX_POWER_LEVEL %x\n",pAdapter->CommonCfg.TxPower)); + break; + case RT_OID_802_11_TX_POWER_LEVEL_1: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.TxPowerPercentage, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_TX_POWER_LEVEL_1 (=%ld)\n", pAdapter->CommonCfg.TxPowerPercentage)); + break; + case OID_802_11_NETWORK_TYPES_SUPPORTED: + if ((pAdapter->RfIcType == RFIC_2850) || (pAdapter->RfIcType == RFIC_2750)) + { + NetworkTypeList[0] = 3; // NumberOfItems = 3 + NetworkTypeList[1] = Ndis802_11DS; // NetworkType[1] = 11b + NetworkTypeList[2] = Ndis802_11OFDM24; // NetworkType[2] = 11g + NetworkTypeList[3] = Ndis802_11OFDM5; // NetworkType[3] = 11a + wrq->u.data.length = 16; + Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length); + } + else + { + NetworkTypeList[0] = 2; // NumberOfItems = 2 + NetworkTypeList[1] = Ndis802_11DS; // NetworkType[1] = 11b + NetworkTypeList[2] = Ndis802_11OFDM24; // NetworkType[2] = 11g + wrq->u.data.length = 12; + Status = copy_to_user(wrq->u.data.pointer, &NetworkTypeList[0], wrq->u.data.length); + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_NETWORK_TYPES_SUPPORTED\n")); + break; + case OID_802_11_NETWORK_TYPE_IN_USE: + wrq->u.data.length = sizeof(ULONG); + if (pAdapter->CommonCfg.PhyMode == PHY_11A) + ulInfo = Ndis802_11OFDM5; + else if ((pAdapter->CommonCfg.PhyMode == PHY_11BG_MIXED) || (pAdapter->CommonCfg.PhyMode == PHY_11G)) + ulInfo = Ndis802_11OFDM24; + else + ulInfo = Ndis802_11DS; + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_LAST_RX_RATE: + ulInfo = (ULONG)pAdapter->LastRxRate; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_RX_RATE (=%ld)\n", ulInfo)); + break; + case RT_OID_802_11_QUERY_LAST_TX_RATE: + //ulInfo = (ULONG)pAdapter->LastTxRate; + ulInfo = (ULONG)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word; + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_LAST_TX_RATE (=%lx)\n", ulInfo)); + break; + case RT_OID_802_11_QUERY_EEPROM_VERSION: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->EepromVersion, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_FIRMWARE_VERSION: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->FirmwareVersion, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_NOISE_LEVEL: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->BbpWriteLatch[66], wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_NOISE_LEVEL (=%d)\n", pAdapter->BbpWriteLatch[66])); + break; + case RT_OID_802_11_EXTRA_INFO: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->ExtraInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_EXTRA_INFO (=%ld)\n", pAdapter->ExtraInfo)); + break; + case RT_OID_WE_VERSION_COMPILED: + wrq->u.data.length = sizeof(UINT); + we_version_compiled = WIRELESS_EXT; + Status = copy_to_user(wrq->u.data.pointer, &we_version_compiled, wrq->u.data.length); + break; + case RT_OID_802_11_QUERY_APSD_SETTING: + apsd = (pAdapter->CommonCfg.bAPSDCapable | (pAdapter->CommonCfg.bAPSDAC_BE << 1) | (pAdapter->CommonCfg.bAPSDAC_BK << 2) + | (pAdapter->CommonCfg.bAPSDAC_VI << 3) | (pAdapter->CommonCfg.bAPSDAC_VO << 4) | (pAdapter->CommonCfg.MaxSPLength << 5)); + + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &apsd, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_SETTING (=0x%lx,APSDCap=%d,AC_BE=%d,AC_BK=%d,AC_VI=%d,AC_VO=%d,MAXSPLen=%d)\n", + apsd,pAdapter->CommonCfg.bAPSDCapable,pAdapter->CommonCfg.bAPSDAC_BE,pAdapter->CommonCfg.bAPSDAC_BK,pAdapter->CommonCfg.bAPSDAC_VI,pAdapter->CommonCfg.bAPSDAC_VO,pAdapter->CommonCfg.MaxSPLength)); + break; + case RT_OID_802_11_QUERY_APSD_PSM: + wrq->u.data.length = sizeof(ULONG); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bAPSDForcePowerSave, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_APSD_PSM (=%d)\n", pAdapter->CommonCfg.bAPSDForcePowerSave)); + break; + case RT_OID_802_11_QUERY_WMM: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bWmmCapable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_WMM (=%d)\n", pAdapter->CommonCfg.bWmmCapable)); + break; +#ifdef WPA_SUPPLICANT_SUPPORT + case RT_OID_NEW_DRIVER: + { + UCHAR enabled = 1; + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &enabled, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_NEW_DRIVER (=%d)\n", enabled)); + } + break; + case RT_OID_WPA_SUPPLICANT_SUPPORT: + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.WpaSupplicantUP, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WPA_SUPPLICANT_SUPPORT (=%d)\n", pAdapter->StaCfg.WpaSupplicantUP)); + break; +#endif // WPA_SUPPLICANT_SUPPORT // + + case RT_OID_DRIVER_DEVICE_NAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_DRIVER_DEVICE_NAME \n")); + wrq->u.data.length = 16; + if (copy_to_user(wrq->u.data.pointer, pAdapter->StaCfg.dev_name, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_802_11_QUERY_HT_PHYMODE: + pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG); + if (pHTPhyMode) + { + pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode; + pHTPhyMode->HtMode = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE; + pHTPhyMode->BW = (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.BW; + pHTPhyMode->MCS= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS; + pHTPhyMode->SHORTGI= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI; + pHTPhyMode->STBC= (UCHAR)pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC; + + pHTPhyMode->ExtOffset = ((pAdapter->CommonCfg.CentralChannel < pAdapter->CommonCfg.Channel) ? (EXTCHA_BELOW) : (EXTCHA_ABOVE)); + wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE); + if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset)); + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case RT_OID_802_11_COUNTRY_REGION: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_COUNTRY_REGION \n")); + wrq->u.data.length = sizeof(ulInfo); + ulInfo = pAdapter->CommonCfg.CountryRegionForABand; + ulInfo = (ulInfo << 8)|(pAdapter->CommonCfg.CountryRegion); + if (copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_802_11_QUERY_DAT_HT_PHYMODE: + pHTPhyMode = (OID_SET_HT_PHYMODE *) kmalloc(sizeof(OID_SET_HT_PHYMODE), MEM_ALLOC_FLAG); + if (pHTPhyMode) + { + pHTPhyMode->PhyMode = pAdapter->CommonCfg.PhyMode; + pHTPhyMode->HtMode = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.HTMODE; + pHTPhyMode->BW = (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.BW; + pHTPhyMode->MCS= (UCHAR)pAdapter->StaCfg.DesiredTransmitSetting.field.MCS; + pHTPhyMode->SHORTGI= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.ShortGI; + pHTPhyMode->STBC= (UCHAR)pAdapter->CommonCfg.RegTransmitSetting.field.STBC; + + wrq->u.data.length = sizeof(OID_SET_HT_PHYMODE); + if (copy_to_user(wrq->u.data.pointer, pHTPhyMode, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_HT_PHYMODE (PhyMode = %d, MCS =%d, BW = %d, STBC = %d, ExtOffset=%d)\n", + pHTPhyMode->HtMode, pHTPhyMode->MCS, pHTPhyMode->BW, pHTPhyMode->STBC, pHTPhyMode->ExtOffset)); + DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (.word = %x )\n", pAdapter->MacTab.Content[BSSID_WCID].HTPhyMode.word)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_STA_CONFIG(kmalloc failed)\n")); + Status = -EFAULT; + } + break; + case RT_OID_QUERY_MULTIPLE_CARD_SUPPORT: + wrq->u.data.length = sizeof(UCHAR); + i = 0; +#ifdef MULTIPLE_CARD_SUPPORT + i = 1; +#endif // MULTIPLE_CARD_SUPPORT // + if (copy_to_user(wrq->u.data.pointer, &i, wrq->u.data.length)) + { + Status = -EFAULT; + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_QUERY_MULTIPLE_CARD_SUPPORT(=%d) \n", i)); + break; +#ifdef SNMP_SUPPORT + case RT_OID_802_11_MAC_ADDRESS: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTUREROUI: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREROUI \n")); + wrq->u.data.length = ManufacturerOUI_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CurrentAddress, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTURERNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTURERNAME \n")); + wrq->u.data.length = strlen(ManufacturerNAME); + Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); + break; + + case RT_OID_802_11_RESOURCETYPEIDNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_RESOURCETYPEIDNAME \n")); + wrq->u.data.length = strlen(ResourceTypeIdName); + Status = copy_to_user(wrq->u.data.pointer, ResourceTypeIdName, wrq->u.data.length); + break; + + case RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED \n")); + ulInfo = 1; // 1 is support wep else 2 is not support. + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + + case RT_OID_802_11_POWERMANAGEMENTMODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_POWERMANAGEMENTMODE \n")); + if (pAdapter->StaCfg.Psm == PSMP_ACTION) + ulInfo = 1; // 1 is power active else 2 is power save. + else + ulInfo = 2; + + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + + case OID_802_11_WEPDEFAULTKEYVALUE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEPDEFAULTKEYVALUE \n")); + //KeyIdxValue.KeyIdx = pAd->PortCfg.MBSSID[pAd->IoctlIF].DefaultKeyId; + pKeyIdxValue = wrq->u.data.pointer; + DBGPRINT(RT_DEBUG_TRACE,("KeyIdxValue.KeyIdx = %d, \n",pKeyIdxValue->KeyIdx)); + valueLen = pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen; + NdisMoveMemory(pKeyIdxValue->Value, + &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].Key, + valueLen); + pKeyIdxValue->Value[valueLen]='\0'; + + wrq->u.data.length = sizeof(DefaultKeyIdxValue); + + Status = copy_to_user(wrq->u.data.pointer, pKeyIdxValue, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("DefaultKeyId = %d, total len = %d, str len=%d, KeyValue= %02x %02x %02x %02x \n", pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length, pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen, + pAdapter->SharedKey[BSS0][0].Key[0], + pAdapter->SharedKey[BSS0][1].Key[0], + pAdapter->SharedKey[BSS0][2].Key[0], + pAdapter->SharedKey[BSS0][3].Key[0])); + break; + + case OID_802_11_WEPDEFAULTKEYID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPDEFAULTKEYID \n")); + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->StaCfg.DefaultKeyId, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyId =%d \n", pAdapter->StaCfg.DefaultKeyId)); + break; + + case RT_OID_802_11_WEPKEYMAPPINGLENGTH: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WEPKEYMAPPINGLENGTH \n")); + wrq->u.data.length = sizeof(UCHAR); + Status = copy_to_user(wrq->u.data.pointer, + &pAdapter->SharedKey[BSS0][pAdapter->StaCfg.DefaultKeyId].KeyLen, + wrq->u.data.length); + break; + + case OID_802_11_SHORTRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SHORTRETRYLIMIT \n")); + wrq->u.data.length = sizeof(ULONG); + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + ShortRetryLimit = tx_rty_cfg.field.ShortRtyLimit; + DBGPRINT(RT_DEBUG_TRACE, ("ShortRetryLimit =%ld, tx_rty_cfg.field.ShortRetryLimit=%d\n", ShortRetryLimit, tx_rty_cfg.field.ShortRtyLimit)); + Status = copy_to_user(wrq->u.data.pointer, &ShortRetryLimit, wrq->u.data.length); + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_LONGRETRYLIMIT \n")); + wrq->u.data.length = sizeof(ULONG); + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + LongRetryLimit = tx_rty_cfg.field.LongRtyLimit; + DBGPRINT(RT_DEBUG_TRACE, ("LongRetryLimit =%ld, tx_rty_cfg.field.LongRtyLimit=%d\n", LongRetryLimit, tx_rty_cfg.field.LongRtyLimit)); + Status = copy_to_user(wrq->u.data.pointer, &LongRetryLimit, wrq->u.data.length); + break; + + case RT_OID_802_11_PRODUCTID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n")); + +#ifdef RT2870 + sprintf(tmp, "%04x %04x\n", ((POS_COOKIE)pAdapter->OS_Cookie)->pUsb_Dev->descriptor.idVendor ,((POS_COOKIE)pAdapter->OS_Cookie)->pUsb_Dev->descriptor.idProduct); + +#endif // RT2870 // + wrq->u.data.length = strlen(tmp); + Status = copy_to_user(wrq->u.data.pointer, tmp, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTUREID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREID \n")); + wrq->u.data.length = strlen(ManufacturerNAME); + Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); + break; + + case OID_802_11_CURRENTCHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CURRENTCHANNEL \n")); + wrq->u.data.length = sizeof(UCHAR); + DBGPRINT(RT_DEBUG_TRACE, ("sizeof UCHAR=%d, channel=%d \n", sizeof(UCHAR), pAdapter->CommonCfg.Channel)); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Channel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; +#endif //SNMP_SUPPORT + + case OID_802_11_BUILD_CHANNEL_EX: + { + UCHAR value; + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_BUILD_CHANNEL_EX \n")); + wrq->u.data.length = sizeof(UCHAR); +#ifdef EXT_BUILD_CHANNEL_LIST + DBGPRINT(RT_DEBUG_TRACE, ("Support EXT_BUILD_CHANNEL_LIST.\n")); + value = 1; +#else + DBGPRINT(RT_DEBUG_TRACE, ("Doesn't support EXT_BUILD_CHANNEL_LIST.\n")); + value = 0; +#endif // EXT_BUILD_CHANNEL_LIST // + Status = copy_to_user(wrq->u.data.pointer, &value, 1); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + } + break; + + case OID_802_11_GET_CH_LIST: + { + PRT_CHANNEL_LIST_INFO pChListBuf; + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CH_LIST \n")); + if (pAdapter->ChannelListNum == 0) + { + wrq->u.data.length = 0; + break; + } + + pChListBuf = (RT_CHANNEL_LIST_INFO *) kmalloc(sizeof(RT_CHANNEL_LIST_INFO), MEM_ALLOC_FLAG); + if (pChListBuf == NULL) + { + wrq->u.data.length = 0; + break; + } + + pChListBuf->ChannelListNum = pAdapter->ChannelListNum; + for (i = 0; i < pChListBuf->ChannelListNum; i++) + pChListBuf->ChannelList[i] = pAdapter->ChannelList[i].Channel; + + wrq->u.data.length = sizeof(RT_CHANNEL_LIST_INFO); + Status = copy_to_user(wrq->u.data.pointer, pChListBuf, sizeof(RT_CHANNEL_LIST_INFO)); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + + if (pChListBuf) + kfree(pChListBuf); + } + break; + + case OID_802_11_GET_COUNTRY_CODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_COUNTRY_CODE \n")); + wrq->u.data.length = 2; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.CountryCode, 2); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; + + case OID_802_11_GET_CHANNEL_GEOGRAPHY: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_GET_CHANNEL_GEOGRAPHY \n")); + wrq->u.data.length = 1; + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.Geography, 1); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; + + +#ifdef QOS_DLS_SUPPORT + case RT_OID_802_11_QUERY_DLS: + wrq->u.data.length = sizeof(BOOLEAN); + Status = copy_to_user(wrq->u.data.pointer, &pAdapter->CommonCfg.bDLSCapable, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS(=%d)\n", pAdapter->CommonCfg.bDLSCapable)); + break; + + case RT_OID_802_11_QUERY_DLS_PARAM: + { + PRT_802_11_DLS_INFO pDlsInfo = kmalloc(sizeof(RT_802_11_DLS_INFO), GFP_ATOMIC); + if (pDlsInfo == NULL) + break; + + for (i=0; iEntry[i], &pAdapter->StaCfg.DLSEntry[i], sizeof(RT_802_11_DLS_UI)); + } + + pDlsInfo->num = MAX_NUM_OF_DLS_ENTRY; + wrq->u.data.length = sizeof(RT_802_11_DLS_INFO); + Status = copy_to_user(wrq->u.data.pointer, pDlsInfo, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_QUERY_DLS_PARAM\n")); + + if (pDlsInfo) + kfree(pDlsInfo); + } + break; +#endif // QOS_DLS_SUPPORT // + default: + DBGPRINT(RT_DEBUG_TRACE, ("Query::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + return Status; +} + +INT rt28xx_sta_ioctl( + IN struct net_device *net_dev, + IN OUT struct ifreq *rq, + IN INT cmd) +{ + POS_COOKIE pObj; + VIRTUAL_ADAPTER *pVirtualAd = NULL; + RTMP_ADAPTER *pAd = NULL; + struct iwreq *wrq = (struct iwreq *) rq; + BOOLEAN StateMachineTouched = FALSE; + INT Status = NDIS_STATUS_SUCCESS; + USHORT subcmd; + + if (net_dev->priv_flags == INT_MAIN) + { + pAd = net_dev->ml_priv; + } + else + { + pVirtualAd = net_dev->ml_priv; + pAd = pVirtualAd->RtmpDev->ml_priv; + } + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (pAd == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->ml_priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + //check if the interface is down + if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { +#ifdef CONFIG_APSTA_MIXED_SUPPORT + if (wrq->u.data.pointer == NULL) + { + return Status; + } + + if (strstr(wrq->u.data.pointer, "OpMode") == NULL) +#endif // CONFIG_APSTA_MIXED_SUPPORT // + { + DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n")); + return -ENETDOWN; + } + } + + { // determine this ioctl command is comming from which interface. + pObj->ioctl_if_type = INT_MAIN; + pObj->ioctl_if = MAIN_MBSSID; + } + + switch(cmd) + { +#ifdef RALINK_ATE +#ifdef RALINK_28xx_QA + case RTPRIV_IOCTL_ATE: + { + RtmpDoAte(pAd, wrq); + } + break; +#endif // RALINK_28xx_QA // +#endif // RALINK_ATE // + case SIOCGIFHWADDR: + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIFHWADDR\n")); + memcpy(wrq->u.name, pAd->CurrentAddress, ETH_ALEN); + break; + case SIOCGIWNAME: + { + char *name=&wrq->u.name[0]; + rt_ioctl_giwname(net_dev, NULL, name, NULL); + break; + } + case SIOCGIWESSID: //Get ESSID + { + struct iw_point *essid=&wrq->u.essid; + rt_ioctl_giwessid(net_dev, NULL, essid, essid->pointer); + break; + } + case SIOCSIWESSID: //Set ESSID + { + struct iw_point *essid=&wrq->u.essid; + rt_ioctl_siwessid(net_dev, NULL, essid, essid->pointer); + break; + } + case SIOCSIWNWID: // set network id (the cell) + case SIOCGIWNWID: // get network id + Status = -EOPNOTSUPP; + break; + case SIOCSIWFREQ: //set channel/frequency (Hz) + { + struct iw_freq *freq=&wrq->u.freq; + rt_ioctl_siwfreq(net_dev, NULL, freq, NULL); + break; + } + case SIOCGIWFREQ: // get channel/frequency (Hz) + { + struct iw_freq *freq=&wrq->u.freq; + rt_ioctl_giwfreq(net_dev, NULL, freq, NULL); + break; + } + case SIOCSIWNICKN: //set node name/nickname + { + struct iw_point *data=&wrq->u.data; + rt_ioctl_siwnickn(net_dev, NULL, data, NULL); + break; + } + case SIOCGIWNICKN: //get node name/nickname + { + struct iw_point *data=&wrq->u.data; + rt_ioctl_giwnickn(net_dev, NULL, data, NULL); + break; + } + case SIOCGIWRATE: //get default bit rate (bps) + rt_ioctl_giwrate(net_dev, NULL, &wrq->u, NULL); + break; + case SIOCSIWRATE: //set default bit rate (bps) + rt_ioctl_siwrate(net_dev, NULL, &wrq->u, NULL); + break; + case SIOCGIWRTS: // get RTS/CTS threshold (bytes) + { + struct iw_param *rts=&wrq->u.rts; + rt_ioctl_giwrts(net_dev, NULL, rts, NULL); + break; + } + case SIOCSIWRTS: //set RTS/CTS threshold (bytes) + { + struct iw_param *rts=&wrq->u.rts; + rt_ioctl_siwrts(net_dev, NULL, rts, NULL); + break; + } + case SIOCGIWFRAG: //get fragmentation thr (bytes) + { + struct iw_param *frag=&wrq->u.frag; + rt_ioctl_giwfrag(net_dev, NULL, frag, NULL); + break; + } + case SIOCSIWFRAG: //set fragmentation thr (bytes) + { + struct iw_param *frag=&wrq->u.frag; + rt_ioctl_siwfrag(net_dev, NULL, frag, NULL); + break; + } + case SIOCGIWENCODE: //get encoding token & mode + { + struct iw_point *erq=&wrq->u.encoding; + if(erq->pointer) + rt_ioctl_giwencode(net_dev, NULL, erq, erq->pointer); + break; + } + case SIOCSIWENCODE: //set encoding token & mode + { + struct iw_point *erq=&wrq->u.encoding; + if(erq->pointer) + rt_ioctl_siwencode(net_dev, NULL, erq, erq->pointer); + break; + } + case SIOCGIWAP: //get access point MAC addresses + { + struct sockaddr *ap_addr=&wrq->u.ap_addr; + rt_ioctl_giwap(net_dev, NULL, ap_addr, ap_addr->sa_data); + break; + } + case SIOCSIWAP: //set access point MAC addresses + { + struct sockaddr *ap_addr=&wrq->u.ap_addr; + rt_ioctl_siwap(net_dev, NULL, ap_addr, ap_addr->sa_data); + break; + } + case SIOCGIWMODE: //get operation mode + { + __u32 *mode=&wrq->u.mode; + rt_ioctl_giwmode(net_dev, NULL, mode, NULL); + break; + } + case SIOCSIWMODE: //set operation mode + { + __u32 *mode=&wrq->u.mode; + rt_ioctl_siwmode(net_dev, NULL, mode, NULL); + break; + } + case SIOCGIWSENS: //get sensitivity (dBm) + case SIOCSIWSENS: //set sensitivity (dBm) + case SIOCGIWPOWER: //get Power Management settings + case SIOCSIWPOWER: //set Power Management settings + case SIOCGIWTXPOW: //get transmit power (dBm) + case SIOCSIWTXPOW: //set transmit power (dBm) + case SIOCGIWRANGE: //Get range of parameters + case SIOCGIWRETRY: //get retry limits and lifetime + case SIOCSIWRETRY: //set retry limits and lifetime + Status = -EOPNOTSUPP; + break; + case RT_PRIV_IOCTL: + case RT_PRIV_IOCTL_EXT: + subcmd = wrq->u.data.flags; + if( subcmd & OID_GET_SET_TOGGLE) + Status = RTMPSetInformation(pAd, rq, subcmd); + else + Status = RTMPQueryInformation(pAd, rq, subcmd); + break; + case SIOCGIWPRIV: + if (wrq->u.data.pointer) + { + if ( access_ok(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab)) != TRUE) + break; + wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); + if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab))) + Status = -EFAULT; + } + break; + case RTPRIV_IOCTL_SET: + if(access_ok(VERIFY_READ, wrq->u.data.pointer, wrq->u.data.length) != TRUE) + break; + rt_ioctl_setparam(net_dev, NULL, NULL, wrq->u.data.pointer); + break; + case RTPRIV_IOCTL_GSITESURVEY: + RTMPIoctlGetSiteSurvey(pAd, wrq); + break; +#ifdef DBG + case RTPRIV_IOCTL_MAC: + RTMPIoctlMAC(pAd, wrq); + break; + case RTPRIV_IOCTL_E2P: + RTMPIoctlE2PROM(pAd, wrq); + break; +#ifdef RT30xx + case RTPRIV_IOCTL_RF: + RTMPIoctlRF(pAd, wrq); + break; +#endif // RT30xx // +#endif // DBG // + case SIOCETHTOOL: + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("IOCTL::unknown IOCTL's cmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + + if(StateMachineTouched) // Upper layer sent a MLME-related operations + RT28XX_MLME_HANDLER(pAd); + + return Status; +} + +/* + ========================================================================== + Description: + Set SSID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_SSID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + NDIS_802_11_SSID Ssid, *pSsid=NULL; + BOOLEAN StateMachineTouched = FALSE; + int success = TRUE; + + if( strlen(arg) <= MAX_LEN_OF_SSID) + { + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + if (strlen(arg) != 0) + { + NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); + Ssid.SsidLength = strlen(arg); + } + else //ANY ssid + { + Ssid.SsidLength = 0; + memcpy(Ssid.Ssid, "", 0); + pAdapter->StaCfg.BssType = BSS_INFRA; + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + pAdapter->StaCfg.WepStatus = Ndis802_11EncryptionDisabled; + } + pSsid = &Ssid; + + if (pAdapter->Mlme.CntlMachine.CurrState != CNTL_IDLE) + { + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n")); + } + + pAdapter->MlmeAux.CurrReqIsFromNdis = TRUE; + pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE; + pAdapter->bConfigChanged = TRUE; + + MlmeEnqueue(pAdapter, + MLME_CNTL_STATE_MACHINE, + OID_802_11_SSID, + sizeof(NDIS_802_11_SSID), + (VOID *)pSsid); + + StateMachineTouched = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Set_SSID_Proc::(Len=%d,Ssid=%s)\n", Ssid.SsidLength, Ssid.Ssid)); + } + else + success = FALSE; + + if (StateMachineTouched) // Upper layer sent a MLME-related operations + RT28XX_MLME_HANDLER(pAdapter); + + return success; +} + +#ifdef WMM_SUPPORT +/* + ========================================================================== + Description: + Set WmmCapable Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + BOOLEAN bWmmCapable; + + bWmmCapable = simple_strtol(arg, 0, 10); + + if ((bWmmCapable == 1) +#ifdef RT2870 + && (pAd->NumberOfPipes >= 5) +#endif // RT2870 // + ) + pAd->CommonCfg.bWmmCapable = TRUE; + else if (bWmmCapable == 0) + pAd->CommonCfg.bWmmCapable = FALSE; + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WmmCapable_Proc::(bWmmCapable=%d)\n", + pAd->CommonCfg.bWmmCapable)); + + return TRUE; +} +#endif // WMM_SUPPORT // + +/* + ========================================================================== + Description: + Set Network Type(Infrastructure/Adhoc mode) + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_NetworkType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + UINT32 Value = 0; + + if (strcmp(arg, "Adhoc") == 0) + { + if (pAdapter->StaCfg.BssType != BSS_ADHOC) + { + // Config has changed + pAdapter->bConfigChanged = TRUE; + if (MONITOR_ON(pAdapter)) + { + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL); + RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); + Value &= (~0x80); + RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); + OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAdapter->StaCfg.bAutoReconnect = TRUE; + LinkDown(pAdapter, FALSE); + } + if (INFRA_ON(pAdapter)) + { + //BOOLEAN Cancelled; + // Set the AutoReconnectSsid to prevent it reconnect to old SSID + // Since calling this indicate user don't want to connect to that SSID anymore. + pAdapter->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen); + + LinkDown(pAdapter, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event BB!\n")); + } + } + pAdapter->StaCfg.BssType = BSS_ADHOC; + pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; + DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(AD-HOC)\n")); + } + else if (strcmp(arg, "Infra") == 0) + { + if (pAdapter->StaCfg.BssType != BSS_INFRA) + { + // Config has changed + pAdapter->bConfigChanged = TRUE; + if (MONITOR_ON(pAdapter)) + { + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, STANORMAL); + RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); + Value &= (~0x80); + RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); + OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); + pAdapter->StaCfg.bAutoReconnect = TRUE; + LinkDown(pAdapter, FALSE); + } + if (ADHOC_ON(pAdapter)) + { + // Set the AutoReconnectSsid to prevent it reconnect to old SSID + // Since calling this indicate user don't want to connect to that SSID anymore. + pAdapter->MlmeAux.AutoReconnectSsidLen= 32; + NdisZeroMemory(pAdapter->MlmeAux.AutoReconnectSsid, pAdapter->MlmeAux.AutoReconnectSsidLen); + + LinkDown(pAdapter, FALSE); + } + } + pAdapter->StaCfg.BssType = BSS_INFRA; + pAdapter->net_dev->type = pAdapter->StaCfg.OriDevType; + DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(INFRA)\n")); + + pAdapter->StaCfg.BssType = BSS_INFRA; + } + else if (strcmp(arg, "Monitor") == 0) + { + UCHAR bbpValue = 0; + BCN_TIME_CFG_STRUC csr; + OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_INFRA_ON); + OPSTATUS_CLEAR_FLAG(pAdapter, fOP_STATUS_ADHOC_ON); + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_MEDIA_STATE_CONNECTED); + // disable all periodic state machine + pAdapter->StaCfg.bAutoReconnect = FALSE; + // reset all mlme state machine + RT28XX_MLME_RESET_STATE_MACHINE(pAdapter); + DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_MEDIA_STATE_CONNECTED \n")); + if (pAdapter->CommonCfg.CentralChannel == 0) + { +#ifdef DOT11_N_SUPPORT + if (pAdapter->CommonCfg.PhyMode == PHY_11AN_MIXED) + pAdapter->CommonCfg.CentralChannel = 36; + else +#endif // DOT11_N_SUPPORT // + pAdapter->CommonCfg.CentralChannel = 6; + } +#ifdef DOT11_N_SUPPORT + else + N_ChannelCheck(pAdapter); +#endif // DOT11_N_SUPPORT // + +#ifdef DOT11_N_SUPPORT + if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 && + pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + // 40MHz ,control channel at lower + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); + bbpValue &= (~0x18); + bbpValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); + pAdapter->CommonCfg.BBPCurrentBW = BW_40; + // RX : control channel at lower + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue); + bbpValue &= (~0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue); + + RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value); + Value &= 0xfffffffe; + RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value); + pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel + 2; + AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", + pAdapter->CommonCfg.Channel, + pAdapter->CommonCfg.CentralChannel)); + } + else if (pAdapter->CommonCfg.PhyMode >= PHY_11ABGN_MIXED && + pAdapter->CommonCfg.RegTransmitSetting.field.BW == BW_40 && + pAdapter->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW) + { + // 40MHz ,control channel at upper + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); + bbpValue &= (~0x18); + bbpValue |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); + pAdapter->CommonCfg.BBPCurrentBW = BW_40; + RTMP_IO_READ32(pAdapter, TX_BAND_CFG, &Value); + Value |= 0x1; + RTMP_IO_WRITE32(pAdapter, TX_BAND_CFG, Value); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R3, &bbpValue); + bbpValue |= (0x20); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R3, bbpValue); + pAdapter->CommonCfg.CentralChannel = pAdapter->CommonCfg.Channel - 2; + AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAdapter, pAdapter->CommonCfg.CentralChannel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_40 ,control_channel(%d), CentralChannel(%d) \n", + pAdapter->CommonCfg.Channel, + pAdapter->CommonCfg.CentralChannel)); + } + else +#endif // DOT11_N_SUPPORT // + { + // 20MHz + RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R4, &bbpValue); + bbpValue &= (~0x18); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R4, bbpValue); + pAdapter->CommonCfg.BBPCurrentBW = BW_20; + AsicSwitchChannel(pAdapter, pAdapter->CommonCfg.Channel, FALSE); + AsicLockChannel(pAdapter, pAdapter->CommonCfg.Channel); + DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAdapter->CommonCfg.Channel)); + } + // Enable Rx with promiscuous reception + RTMP_IO_WRITE32(pAdapter, RX_FILTR_CFG, 0x3); + // ASIC supporsts sniffer function with replacing RSSI with timestamp. + //RTMP_IO_READ32(pAdapter, MAC_SYS_CTRL, &Value); + //Value |= (0x80); + //RTMP_IO_WRITE32(pAdapter, MAC_SYS_CTRL, Value); + // disable sync + RTMP_IO_READ32(pAdapter, BCN_TIME_CFG, &csr.word); + csr.field.bBeaconGen = 0; + csr.field.bTBTTEnable = 0; + csr.field.TsfSyncMode = 0; + RTMP_IO_WRITE32(pAdapter, BCN_TIME_CFG, csr.word); + + pAdapter->StaCfg.BssType = BSS_MONITOR; + pAdapter->net_dev->type = ARPHRD_IEEE80211_PRISM; //ARPHRD_IEEE80211; // IEEE80211 + DBGPRINT(RT_DEBUG_TRACE, ("===>Set_NetworkType_Proc::(MONITOR)\n")); + } + + // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key + pAdapter->StaCfg.WpaState = SS_NOTUSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_NetworkType_Proc::(NetworkType=%d)\n", pAdapter->StaCfg.BssType)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Authentication mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AuthMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeOpen; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPANONE") == 0) || (strcmp(arg, "wpanone") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPANone; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef WPA_SUPPLICANT_SUPPORT + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + pAdapter->StaCfg.AuthMode = Ndis802_11AuthModeWPA2; +#endif // WPA_SUPPLICANT_SUPPORT // + else + return FALSE; + + pAdapter->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_AuthMode_Proc::(AuthMode=%d)\n", pAdapter->StaCfg.AuthMode)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_EncrypType_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) + { + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + pAdapter->StaCfg.WepStatus = Ndis802_11WEPDisabled; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPDisabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPDisabled; + } + else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + { + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + pAdapter->StaCfg.WepStatus = Ndis802_11WEPEnabled; + pAdapter->StaCfg.PairCipher = Ndis802_11WEPEnabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11WEPEnabled; + } + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + { + if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + pAdapter->StaCfg.WepStatus = Ndis802_11Encryption2Enabled; + pAdapter->StaCfg.PairCipher = Ndis802_11Encryption2Enabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption2Enabled; + } + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) + { + if (pAdapter->StaCfg.AuthMode < Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + pAdapter->StaCfg.WepStatus = Ndis802_11Encryption3Enabled; + pAdapter->StaCfg.PairCipher = Ndis802_11Encryption3Enabled; + pAdapter->StaCfg.GroupCipher = Ndis802_11Encryption3Enabled; + } + else + return FALSE; + + pAdapter->StaCfg.OrigWepStatus = pAdapter->StaCfg.WepStatus; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_EncrypType_Proc::(EncrypType=%d)\n", pAdapter->StaCfg.WepStatus)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Default Key ID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + ULONG KeyIdx; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAdapter->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; //Invalid argument + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DefaultKeyID_Proc::(DefaultKeyID=%d)\n", pAdapter->StaCfg.DefaultKeyId)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WEP KEY1 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key1_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: //wep 40 Ascii type + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); + break; + case 10: //wep 40 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); + break; + case 13: //wep 104 Ascii type + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][0].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Ascii")); + break; + case 26: //wep 104 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][0].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][0].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::(Key1=%s and type=%s)\n", arg, "Hex")); + break; + default: //Invalid argument + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key1_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + + pAdapter->SharedKey[BSS0][0].CipherAlg = CipherAlg; + + // Set keys (into ASIC) + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + ; // not support + else // Old WEP stuff + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 0, + pAdapter->SharedKey[BSS0][0].CipherAlg, + pAdapter->SharedKey[BSS0][0].Key, + NULL, + NULL); + } + + return TRUE; +} +/* + ========================================================================== + + Description: + Set WEP KEY2 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key2_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: //wep 40 Ascii type + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); + break; + case 10: //wep 40 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); + break; + case 13: //wep 104 Ascii type + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][1].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Ascii")); + break; + case 26: //wep 104 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][1].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][1].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::(Key2=%s and type=%s)\n", arg, "Hex")); + break; + default: //Invalid argument + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key2_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + pAdapter->SharedKey[BSS0][1].CipherAlg = CipherAlg; + + // Set keys (into ASIC) + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + ; // not support + else // Old WEP stuff + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 1, + pAdapter->SharedKey[BSS0][1].CipherAlg, + pAdapter->SharedKey[BSS0][1].Key, + NULL, + NULL); + } + + return TRUE; +} +/* + ========================================================================== + Description: + Set WEP KEY3 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key3_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: //wep 40 Ascii type + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); + break; + case 10: //wep 40 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); + break; + case 13: //wep 104 Ascii type + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][2].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Ascii)\n", arg)); + break; + case 26: //wep 104 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][2].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][2].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::(Key3=%s and type=Hex)\n", arg)); + break; + default: //Invalid argument + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key3_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + pAdapter->SharedKey[BSS0][2].CipherAlg = CipherAlg; + + // Set keys (into ASIC) + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + ; // not support + else // Old WEP stuff + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 2, + pAdapter->SharedKey[BSS0][2].CipherAlg, + pAdapter->SharedKey[BSS0][2].Key, + NULL, + NULL); + } + + return TRUE; +} +/* + ========================================================================== + Description: + Set WEP KEY4 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Key4_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + int KeyLen; + int i; + UCHAR CipherAlg=CIPHER_WEP64; + + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + return TRUE; // do nothing + + KeyLen = strlen(arg); + + switch (KeyLen) + { + case 5: //wep 40 Ascii type + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); + break; + case 10: //wep 40 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP64; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); + break; + case 13: //wep 104 Ascii type + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen; + memcpy(pAdapter->SharedKey[BSS0][3].Key, arg, KeyLen); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Ascii")); + break; + case 26: //wep 104 Hex type + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(arg+i)) ) + return FALSE; //Not Hex value; + } + pAdapter->SharedKey[BSS0][3].KeyLen = KeyLen / 2 ; + AtoH(arg, pAdapter->SharedKey[BSS0][3].Key, KeyLen / 2); + CipherAlg = CIPHER_WEP128; + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::(Key4=%s and type=%s)\n", arg, "Hex")); + break; + default: //Invalid argument + DBGPRINT(RT_DEBUG_TRACE, ("Set_Key4_Proc::Invalid argument (=%s)\n", arg)); + return FALSE; + } + pAdapter->SharedKey[BSS0][3].CipherAlg = CipherAlg; + + // Set keys (into ASIC) + if (pAdapter->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) + ; // not support + else // Old WEP stuff + { + AsicAddSharedKeyEntry(pAdapter, + 0, + 3, + pAdapter->SharedKey[BSS0][3].CipherAlg, + pAdapter->SharedKey[BSS0][3].Key, + NULL, + NULL); + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WPA PSK key + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WPAPSK_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + UCHAR keyMaterial[40]; + + if ((pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) && + (pAdapter->StaCfg.AuthMode != Ndis802_11AuthModeWPANone) + ) + return TRUE; // do nothing + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg)); + + NdisZeroMemory(keyMaterial, 40); + + if ((strlen(arg) < 8) || (strlen(arg) > 64)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set failed!!(WPAPSK=%s), WPAPSK key-string required 8 ~ 64 characters \n", arg)); + return FALSE; + } + + if (strlen(arg) == 64) + { + AtoH(arg, keyMaterial, 32); + NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32); + + } + else + { + PasswordHash((char *)arg, pAdapter->MlmeAux.Ssid, pAdapter->MlmeAux.SsidLen, keyMaterial); + NdisMoveMemory(pAdapter->StaCfg.PMK, keyMaterial, 32); + } + + + + if(pAdapter->StaCfg.BssType == BSS_ADHOC && + pAdapter->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) + { + pAdapter->StaCfg.WpaState = SS_NOTUSE; + } + else + { + // Start STA supplicant state machine + pAdapter->StaCfg.WpaState = SS_START; + } + + return TRUE; +} + +/* + ========================================================================== + Description: + Set Power Saving mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_PSMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + if (pAdapter->StaCfg.BssType == BSS_INFRA) + { + if ((strcmp(arg, "Max_PSP") == 0) || + (strcmp(arg, "max_psp") == 0) || + (strcmp(arg, "MAX_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP; + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + pAdapter->StaCfg.DefaultListenCount = 5; + + } + else if ((strcmp(arg, "Fast_PSP") == 0) || + (strcmp(arg, "fast_psp") == 0) || + (strcmp(arg, "FAST_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP; + pAdapter->StaCfg.DefaultListenCount = 3; + } + else if ((strcmp(arg, "Legacy_PSP") == 0) || + (strcmp(arg, "legacy_psp") == 0) || + (strcmp(arg, "LEGACY_PSP") == 0)) + { + // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange() + // to exclude certain situations. + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP; + pAdapter->StaCfg.DefaultListenCount = 3; + } + else + { + //Default Ndis802_11PowerModeCAM + // clear PSM bit immediately + MlmeSetPsmBit(pAdapter, PWR_ACTIVE); + OPSTATUS_SET_FLAG(pAdapter, fOP_STATUS_RECEIVE_DTIM); + if (pAdapter->StaCfg.bWindowsACCAMEnable == FALSE) + pAdapter->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM; + pAdapter->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_PSMode_Proc::(PSMode=%ld)\n", pAdapter->StaCfg.WindowsPowerMode)); + } + else + return FALSE; + + + return TRUE; +} + +#ifdef WPA_SUPPLICANT_SUPPORT +/* + ========================================================================== + Description: + Set WpaSupport flag. + Value: + 0: Driver ignore wpa_supplicant. + 1: wpa_supplicant initiates scanning and AP selection. + 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Wpa_Support( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + + if ( simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + else if ( simple_strtol(arg, 0, 10) == 1) + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE; + else if ( simple_strtol(arg, 0, 10) == 2) + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE_WITH_WEB_UI; + else + pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Wpa_Support::(WpaSupplicantUP=%d)\n", pAd->StaCfg.WpaSupplicantUP)); + + return TRUE; +} +#endif // WPA_SUPPLICANT_SUPPORT // + +#ifdef DBG +/* + ========================================================================== + Description: + Read / Write MAC + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 mac 0 ==> read MAC where Addr=0x0 + 2.) iwpriv ra0 mac 0=12 ==> write MAC where Addr=0x0, value=12 + ========================================================================== +*/ +VOID RTMPIoctlMAC( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + CHAR *this_char; + CHAR *value; + INT j = 0, k = 0; + CHAR msg[1024]; + CHAR arg[255]; + ULONG macAddr = 0; + UCHAR temp[16], temp2[16]; + UINT32 macValue = 0; + INT Status; + BOOLEAN bIsPrintAllMAC = FALSE; + + + memset(msg, 0x00, 1024); + if (wrq->u.data.length > 1) //No parameters. + { + Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + sprintf(msg, "\n"); + + //Parsing Read or Write + this_char = arg; + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { //Read + // Sanity check + if(strlen(this_char) > 4) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + return; + } + + // Mac Addr + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + if(strlen(this_char) == 4) + { + AtoH(this_char, temp, 2); + macAddr = *temp*256 + temp[1]; + if (macAddr < 0xFFFF) + { + RTMP_IO_READ32(pAdapter, macAddr, &macValue); + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%lx, MacValue=%x\n", macAddr, macValue)); + sprintf(msg+strlen(msg), "[0x%08lX]:%08X ", macAddr , macValue); + } + else + {//Invalid parametes, so default printk all mac + bIsPrintAllMAC = TRUE; + goto next; + } + } + } + else + { //Write + memcpy(&temp2, value, strlen(value)); + temp2[strlen(value)] = '\0'; + + // Sanity check + if((strlen(this_char) > 4) || strlen(temp2) > 8) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + return; + } + + j = strlen(temp2); + while(j-- > 0) + { + if(temp2[j] > 'f' || temp2[j] < '0') + return; + } + + //MAC Addr + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + //MAC value + k = j = strlen(temp2); + while(j-- > 0) + { + temp2[8-k+j] = temp2[j]; + } + + while(k < 8) + temp2[7-k++]='0'; + temp2[8]='\0'; + + { + AtoH(this_char, temp, 2); + macAddr = *temp*256 + temp[1]; + + AtoH(temp2, temp, 4); + macValue = *temp*256*256*256 + temp[1]*256*256 + temp[2]*256 + temp[3]; + + // debug mode + if (macAddr == (HW_DEBUG_SETTING_BASE + 4)) + { + // 0x2bf4: byte0 non-zero: enable R17 tuning, 0: disable R17 tuning + if (macValue & 0x000000ff) + { + pAdapter->BbpTuning.bEnable = TRUE; + DBGPRINT(RT_DEBUG_TRACE,("turn on R17 tuning\n")); + } + else + { + UCHAR R66; + pAdapter->BbpTuning.bEnable = FALSE; + R66 = 0x26 + GET_LNA_GAIN(pAdapter); +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter))); + } + else +#endif // RALINK_ATE // + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, BBP_R66, (0x26 + GET_LNA_GAIN(pAdapter))); + DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66)); + } + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=%02lx, MacValue=0x%x\n", macAddr, macValue)); + + RTMP_IO_WRITE32(pAdapter, macAddr, macValue); + sprintf(msg+strlen(msg), "[0x%08lX]:%08X ", macAddr, macValue); + } + } + } + else + bIsPrintAllMAC = TRUE; +next: + if (bIsPrintAllMAC) + { + struct file *file_w; + PCHAR fileName = "MacDump.txt"; + mm_segment_t orig_fs; + + orig_fs = get_fs(); + set_fs(KERNEL_DS); + + // open file + file_w = filp_open(fileName, O_WRONLY|O_CREAT, 0); + if (IS_ERR(file_w)) + { + DBGPRINT(RT_DEBUG_TRACE, ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(file_w), fileName)); + } + else + { + if (file_w->f_op && file_w->f_op->write) + { + file_w->f_pos = 0; + macAddr = 0x1000; + + while (macAddr <= 0x1800) + { + RTMP_IO_READ32(pAdapter, macAddr, &macValue); + sprintf(msg, "%08lx = %08X\n", macAddr, macValue); + + // write data to file + file_w->f_op->write(file_w, msg, strlen(msg), &file_w->f_pos); + + printk("%s", msg); + macAddr += 4; + } + sprintf(msg, "\nDump all MAC values to %s\n", fileName); + } + filp_close(file_w, NULL); + } + set_fs(orig_fs); + } + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + // Copy the information into the user buffer + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlMAC\n\n")); +} + +/* + ========================================================================== + Description: + Read / Write E2PROM + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 e2p 0 ==> read E2PROM where Addr=0x0 + 2.) iwpriv ra0 e2p 0=1234 ==> write E2PROM where Addr=0x0, value=1234 + ========================================================================== +*/ +VOID RTMPIoctlE2PROM( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + CHAR *this_char; + CHAR *value; + INT j = 0, k = 0; + CHAR msg[1024]; + CHAR arg[255]; + USHORT eepAddr = 0; + UCHAR temp[16], temp2[16]; + USHORT eepValue; + int Status; + BOOLEAN bIsPrintAllE2P = FALSE; + + + memset(msg, 0x00, 1024); + if (wrq->u.data.length > 1) //No parameters. + { + Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + sprintf(msg, "\n"); + + //Parsing Read or Write + this_char = arg; + + + if (!*this_char) + goto next; + + if ((value = rtstrchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { //Read + + // Sanity check + if(strlen(this_char) > 4) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + return; + } + + // E2PROM addr + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + if(strlen(this_char) == 4) + { + AtoH(this_char, temp, 2); + eepAddr = *temp*256 + temp[1]; + if (eepAddr < 0xFFFF) + { + RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue); + sprintf(msg+strlen(msg), "[0x%04X]:0x%04X ", eepAddr , eepValue); + } + else + {//Invalid parametes, so default printk all bbp + bIsPrintAllE2P = TRUE; + goto next; + } + } + } + else + { //Write + memcpy(&temp2, value, strlen(value)); + temp2[strlen(value)] = '\0'; + + // Sanity check + if((strlen(this_char) > 4) || strlen(temp2) > 8) + goto next; + + j = strlen(this_char); + while(j-- > 0) + { + if(this_char[j] > 'f' || this_char[j] < '0') + return; + } + j = strlen(temp2); + while(j-- > 0) + { + if(temp2[j] > 'f' || temp2[j] < '0') + return; + } + + //MAC Addr + k = j = strlen(this_char); + while(j-- > 0) + { + this_char[4-k+j] = this_char[j]; + } + + while(k < 4) + this_char[3-k++]='0'; + this_char[4]='\0'; + + //MAC value + k = j = strlen(temp2); + while(j-- > 0) + { + temp2[4-k+j] = temp2[j]; + } + + while(k < 4) + temp2[3-k++]='0'; + temp2[4]='\0'; + + AtoH(this_char, temp, 2); + eepAddr = *temp*256 + temp[1]; + + AtoH(temp2, temp, 2); + eepValue = *temp*256 + temp[1]; + + RT28xx_EEPROM_WRITE16(pAdapter, eepAddr, eepValue); + sprintf(msg+strlen(msg), "[0x%02X]:%02X ", eepAddr, eepValue); + } + } + else + bIsPrintAllE2P = TRUE; +next: + if (bIsPrintAllE2P) + { + struct file *file_w; + PCHAR fileName = "EEPROMDump.txt"; + mm_segment_t orig_fs; + + orig_fs = get_fs(); + set_fs(KERNEL_DS); + + // open file + file_w = filp_open(fileName, O_WRONLY|O_CREAT, 0); + if (IS_ERR(file_w)) + { + DBGPRINT(RT_DEBUG_TRACE, ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(file_w), fileName)); + } + else + { + if (file_w->f_op && file_w->f_op->write) + { + file_w->f_pos = 0; + eepAddr = 0x00; + + while (eepAddr <= 0xFE) + { + RT28xx_EEPROM_READ16(pAdapter, eepAddr, eepValue); + sprintf(msg, "%08x = %04x\n", eepAddr , eepValue); + + // write data to file + file_w->f_op->write(file_w, msg, strlen(msg), &file_w->f_pos); + + printk("%s", msg); + eepAddr += 2; + } + sprintf(msg, "\nDump all EEPROM values to %s\n", fileName); + } + filp_close(file_w, NULL); + } + set_fs(orig_fs); + } + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + + // Copy the information into the user buffer + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlE2PROM\n")); +} +#ifdef RT30xx +/* + ========================================================================== + Description: + Read / Write RF register +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 rf ==> read all RF registers + 2.) iwpriv ra0 rf 1 ==> read RF where RegID=1 + 3.) iwpriv ra0 rf 1=10 ==> write RF R1=0x10 + ========================================================================== +*/ +VOID RTMPIoctlRF( + IN PRTMP_ADAPTER pAdapter, + IN struct iwreq *wrq) +{ + CHAR *this_char; + CHAR *value; + UCHAR regRF = 0; + CHAR msg[2048]; + CHAR arg[255]; + INT rfId; + LONG rfValue; + int Status; + BOOLEAN bIsPrintAllRF = FALSE; + + + memset(msg, 0x00, 2048); + if (wrq->u.data.length > 1) //No parameters. + { + Status = copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); + sprintf(msg, "\n"); + + //Parsing Read or Write + this_char = arg; + if (!*this_char) + goto next; + + if ((value = strchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value || !*value) + { //Read + if (sscanf(this_char, "%d", &(rfId)) == 1) + { + if (rfId <= 31) + { + // In RT2860 ATE mode, we do not load 8051 firmware. + //We must access RF directly. + // For RT2870 ATE mode, ATE_RF_IO_WRITE8(/READ8)_BY_REG_ID are redefined. +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); + } + else +#endif // RALINK_ATE // + // according to Andy, Gary, David require. + // the command rf shall read rf register directly for dubug. + // BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + + sprintf(msg+strlen(msg), "R%02d[0x%02x]:%02X ", rfId, rfId*2, regRF); + } + else + {//Invalid parametes, so default printk all RF + bIsPrintAllRF = TRUE; + goto next; + } + } + else + { //Invalid parametes, so default printk all RF + bIsPrintAllRF = TRUE; + goto next; + } + } + else + { //Write + if ((sscanf(this_char, "%d", &(rfId)) == 1) && (sscanf(value, "%lx", &(rfValue)) == 1)) + { + if (rfId <= 31) + { + // In RT2860 ATE mode, we do not load 8051 firmware. + // We should access RF registers directly. + // For RT2870 ATE mode, ATE_RF_IO_WRITE8/READ8_BY_REG_ID are redefined. +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); + ATE_RF_IO_WRITE8_BY_REG_ID(pAdapter, (UCHAR)rfId,(UCHAR) rfValue); + //Read it back for showing + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); + sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X\n", rfId, rfId*2, regRF); + } + else +#endif // RALINK_ATE // + { + // according to Andy, Gary, David require. + // the command RF shall read/write RF register directly for dubug. + //BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + //BBP_IO_WRITE8_BY_REG_ID(pAdapter, (UCHAR)bbpId,(UCHAR) bbpValue); + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + RT30xxWriteRFRegister(pAdapter, (UCHAR)rfId,(UCHAR) rfValue); + //Read it back for showing + //BBP_IO_READ8_BY_REG_ID(pAdapter, bbpId, ®BBP); + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X\n", rfId, rfId*2, regRF); + } + } + else + {//Invalid parametes, so default printk all RF + bIsPrintAllRF = TRUE; + } + } + else + { //Invalid parametes, so default printk all RF + bIsPrintAllRF = TRUE; + } + } + } + else + bIsPrintAllRF = TRUE; +next: + if (bIsPrintAllRF) + { + memset(msg, 0x00, 2048); + sprintf(msg, "\n"); + for (rfId = 0; rfId <= 31; rfId++) + { + // In RT2860 ATE mode, we do not load 8051 firmware. + // We should access RF registers directly. + // For RT2870 ATE mode, ATE_RF_IO_WRITE8/READ8_BY_REG_ID are redefined. +#ifdef RALINK_ATE + if (ATE_ON(pAdapter)) + { + ATE_RF_IO_READ8_BY_REG_ID(pAdapter, rfId, ®RF); + } + else +#endif // RALINK_ATE // + + // according to Andy, Gary, David require. + // the command RF shall read/write RF register directly for dubug. + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + sprintf(msg+strlen(msg), "%03d = %02X\n", rfId, regRF); + } + // Copy the information into the user buffer + DBGPRINT(RT_DEBUG_TRACE, ("strlen(msg)=%d\n", (UINT32)strlen(msg))); + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + } + else + { + if(strlen(msg) == 1) + sprintf(msg+strlen(msg), "===>Error command format!"); + + DBGPRINT(RT_DEBUG_TRACE, ("copy to user [msg=%s]\n", msg)); + // Copy the information into the user buffer + DBGPRINT(RT_DEBUG_TRACE, ("strlen(msg) =%d\n", (UINT32)strlen(msg))); + + // Copy the information into the user buffer + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n\n")); +} +#endif // RT30xx // +#endif // DBG // + + + + +INT Set_TGnWifiTest_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->StaCfg.bTGnWifiTest = FALSE; + else + pAd->StaCfg.bTGnWifiTest = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_TGnWifiTest_Proc::(bTGnWifiTest=%d)\n", pAd->StaCfg.bTGnWifiTest)); + return TRUE; +} + +INT Set_LongRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + UCHAR LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.LongRtyLimit = LongRetryLimit; + RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); + return TRUE; +} + +INT Set_ShortRetryLimit_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + UCHAR ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + + RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit; + RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word); + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word)); + return TRUE; +} + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_Ieee80211dClientMode_Proc( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_None; + else if (simple_strtol(arg, 0, 10) == 1) + pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Flexible; + else if (simple_strtol(arg, 0, 10) == 2) + pAdapter->StaCfg.IEEE80211dClientMode = Rt802_11_D_Strict; + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_Ieee802dMode_Proc::(IEEEE0211dMode=%d)\n", pAdapter->StaCfg.IEEE80211dClientMode)); + return TRUE; +} +#endif // EXT_BUILD_CHANNEL_LIST // + +#ifdef CARRIER_DETECTION_SUPPORT +INT Set_CarrierDetect_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + if (simple_strtol(arg, 0, 10) == 0) + pAd->CommonCfg.CarrierDetect.Enable = FALSE; + else + pAd->CommonCfg.CarrierDetect.Enable = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_CarrierDetect_Proc::(CarrierDetect.Enable=%d)\n", pAd->CommonCfg.CarrierDetect.Enable)); + return TRUE; +} +#endif // CARRIER_DETECTION_SUPPORT // + diff --git a/drivers/staging/rt3070/wpa.h b/drivers/staging/rt3070/wpa.h new file mode 100644 index 000000000000..88c7c8bf3fcd --- /dev/null +++ b/drivers/staging/rt3070/wpa.h @@ -0,0 +1,356 @@ +/* + ************************************************************************* + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2007, Ralink Technology, Inc. + * + * 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. * + * * + ************************************************************************* + + Module Name: + wpa.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifndef __WPA_H__ +#define __WPA_H__ + +// EAPOL Key descripter frame format related length +#define LEN_KEY_DESC_NONCE 32 +#define LEN_KEY_DESC_IV 16 +#define LEN_KEY_DESC_RSC 8 +#define LEN_KEY_DESC_ID 8 +#define LEN_KEY_DESC_REPLAY 8 +#define LEN_KEY_DESC_MIC 16 + +// The length is the EAPoL-Key frame except key data field. +// Please refer to 802.11i-2004 ,Figure 43u in p.78 +#define LEN_EAPOL_KEY_MSG (sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE) + +// EAP Code Type. +#define EAP_CODE_REQUEST 1 +#define EAP_CODE_RESPONSE 2 +#define EAP_CODE_SUCCESS 3 +#define EAP_CODE_FAILURE 4 + +// EAPOL frame Protocol Version +#define EAPOL_VER 1 +#define EAPOL_VER2 2 + +// EAPOL-KEY Descriptor Type +#define WPA1_KEY_DESC 0xfe +#define WPA2_KEY_DESC 0x02 + +// Key Descriptor Version of Key Information +#define DESC_TYPE_TKIP 1 +#define DESC_TYPE_AES 2 +#define DESC_TYPE_MESH 3 + +#define LEN_MSG1_2WAY 0x7f +#define MAX_LEN_OF_EAP_HS 256 + +#define LEN_MASTER_KEY 32 + +// EAPOL EK, MK +#define LEN_EAP_EK 16 +#define LEN_EAP_MICK 16 +#define LEN_EAP_KEY ((LEN_EAP_EK)+(LEN_EAP_MICK)) +// TKIP key related +#define LEN_PMKID 16 +#define LEN_TKIP_EK 16 +#define LEN_TKIP_RXMICK 8 +#define LEN_TKIP_TXMICK 8 +#define LEN_AES_EK 16 +#define LEN_AES_KEY LEN_AES_EK +#define LEN_TKIP_KEY ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK)) +#define TKIP_AP_TXMICK_OFFSET ((LEN_EAP_KEY)+(LEN_TKIP_EK)) +#define TKIP_AP_RXMICK_OFFSET (TKIP_AP_TXMICK_OFFSET+LEN_TKIP_TXMICK) +#define TKIP_GTK_LENGTH ((LEN_TKIP_EK)+(LEN_TKIP_RXMICK)+(LEN_TKIP_TXMICK)) +#define LEN_PTK ((LEN_EAP_KEY)+(LEN_TKIP_KEY)) + +// RSN IE Length definition +#define MAX_LEN_OF_RSNIE 90 +#define MIN_LEN_OF_RSNIE 8 + +//EAP Packet Type +#define EAPPacket 0 +#define EAPOLStart 1 +#define EAPOLLogoff 2 +#define EAPOLKey 3 +#define EAPOLASFAlert 4 +#define EAPTtypeMax 5 + +#define EAPOL_MSG_INVALID 0 +#define EAPOL_PAIR_MSG_1 1 +#define EAPOL_PAIR_MSG_2 2 +#define EAPOL_PAIR_MSG_3 3 +#define EAPOL_PAIR_MSG_4 4 +#define EAPOL_GROUP_MSG_1 5 +#define EAPOL_GROUP_MSG_2 6 + +#define PAIRWISEKEY 1 +#define GROUPKEY 0 + +// Retry timer counter initial value +#define PEER_MSG1_RETRY_TIMER_CTR 0 +#define PEER_MSG3_RETRY_TIMER_CTR 10 +#define GROUP_MSG1_RETRY_TIMER_CTR 20 + + +#define EAPOL_START_DISABLE 0 +#define EAPOL_START_PSK 1 +#define EAPOL_START_1X 2 + +#define MIX_CIPHER_WPA_TKIP_ON(x) (((x) & 0x08) != 0) +#define MIX_CIPHER_WPA_AES_ON(x) (((x) & 0x04) != 0) +#define MIX_CIPHER_WPA2_TKIP_ON(x) (((x) & 0x02) != 0) +#define MIX_CIPHER_WPA2_AES_ON(x) (((x) & 0x01) != 0) + +#define ROUND_UP(__x, __y) \ + (((ULONG)((__x)+((__y)-1))) & ((ULONG)~((__y)-1))) + +#define ADD_ONE_To_64BIT_VAR(_V) \ +{ \ + UCHAR cnt = LEN_KEY_DESC_REPLAY; \ + do \ + { \ + cnt--; \ + _V[cnt]++; \ + if (cnt == 0) \ + break; \ + }while (_V[cnt] == 0); \ +} + +#define IS_WPA_CAPABILITY(a) (((a) >= Ndis802_11AuthModeWPA) && ((a) <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + +// EAPOL Key Information definition within Key descriptor format +typedef struct PACKED _KEY_INFO +{ +#ifdef RT_BIG_ENDIAN + UCHAR KeyAck:1; + UCHAR Install:1; + UCHAR KeyIndex:2; + UCHAR KeyType:1; + UCHAR KeyDescVer:3; + UCHAR Rsvd:3; + UCHAR EKD_DL:1; // EKD for AP; DL for STA + UCHAR Request:1; + UCHAR Error:1; + UCHAR Secure:1; + UCHAR KeyMic:1; +#else + UCHAR KeyMic:1; + UCHAR Secure:1; + UCHAR Error:1; + UCHAR Request:1; + UCHAR EKD_DL:1; // EKD for AP; DL for STA + UCHAR Rsvd:3; + UCHAR KeyDescVer:3; + UCHAR KeyType:1; + UCHAR KeyIndex:2; + UCHAR Install:1; + UCHAR KeyAck:1; +#endif +} KEY_INFO, *PKEY_INFO; + +// EAPOL Key descriptor format +typedef struct PACKED _KEY_DESCRIPTER +{ + UCHAR Type; + KEY_INFO KeyInfo; + UCHAR KeyLength[2]; + UCHAR ReplayCounter[LEN_KEY_DESC_REPLAY]; + UCHAR KeyNonce[LEN_KEY_DESC_NONCE]; + UCHAR KeyIv[LEN_KEY_DESC_IV]; + UCHAR KeyRsc[LEN_KEY_DESC_RSC]; + UCHAR KeyId[LEN_KEY_DESC_ID]; + UCHAR KeyMic[LEN_KEY_DESC_MIC]; + UCHAR KeyDataLen[2]; + UCHAR KeyData[MAX_LEN_OF_RSNIE]; +} KEY_DESCRIPTER, *PKEY_DESCRIPTER; + +typedef struct PACKED _EAPOL_PACKET +{ + UCHAR ProVer; + UCHAR ProType; + UCHAR Body_Len[2]; + KEY_DESCRIPTER KeyDesc; +} EAPOL_PACKET, *PEAPOL_PACKET; + +//802.11i D10 page 83 +typedef struct PACKED _GTK_ENCAP +{ +#ifndef RT_BIG_ENDIAN + UCHAR Kid:2; + UCHAR tx:1; + UCHAR rsv:5; + UCHAR rsv1; +#else + UCHAR rsv:5; + UCHAR tx:1; + UCHAR Kid:2; + UCHAR rsv1; +#endif + UCHAR GTK[TKIP_GTK_LENGTH]; +} GTK_ENCAP, *PGTK_ENCAP; + +typedef struct PACKED _KDE_ENCAP +{ + UCHAR Type; + UCHAR Len; + UCHAR OUI[3]; + UCHAR DataType; + GTK_ENCAP GTKEncap; +} KDE_ENCAP, *PKDE_ENCAP; + +// For WPA1 +typedef struct PACKED _RSNIE { + UCHAR oui[4]; + USHORT version; + UCHAR mcast[4]; + USHORT ucount; + struct PACKED { + UCHAR oui[4]; + }ucast[1]; +} RSNIE, *PRSNIE; + +// For WPA2 +typedef struct PACKED _RSNIE2 { + USHORT version; + UCHAR mcast[4]; + USHORT ucount; + struct PACKED { + UCHAR oui[4]; + }ucast[1]; +} RSNIE2, *PRSNIE2; + +// AKM Suite +typedef struct PACKED _RSNIE_AUTH { + USHORT acount; + struct PACKED { + UCHAR oui[4]; + }auth[1]; +} RSNIE_AUTH,*PRSNIE_AUTH; + +typedef union PACKED _RSN_CAPABILITIES { + struct PACKED { +#ifdef RT_BIG_ENDIAN + USHORT Rsvd:10; + USHORT GTKSA_R_Counter:2; + USHORT PTKSA_R_Counter:2; + USHORT No_Pairwise:1; + USHORT PreAuth:1; +#else + USHORT PreAuth:1; + USHORT No_Pairwise:1; + USHORT PTKSA_R_Counter:2; + USHORT GTKSA_R_Counter:2; + USHORT Rsvd:10; +#endif + } field; + USHORT word; +} RSN_CAPABILITIES, *PRSN_CAPABILITIES; + +typedef struct PACKED _EAP_HDR { + UCHAR ProVer; + UCHAR ProType; + UCHAR Body_Len[2]; + UCHAR code; + UCHAR identifier; + UCHAR length[2]; // including code and identifier, followed by length-2 octets of data +} EAP_HDR, *PEAP_HDR; + +// For supplicant state machine states. 802.11i Draft 4.1, p. 97 +// We simplified it +typedef enum _WpaState +{ + SS_NOTUSE, // 0 + SS_START, // 1 + SS_WAIT_MSG_3, // 2 + SS_WAIT_GROUP, // 3 + SS_FINISH, // 4 + SS_KEYUPDATE, // 5 +} WPA_STATE; + +// +// The definition of the cipher combination +// +// bit3 bit2 bit1 bit0 +// +------------+------------+ +// | WPA | WPA2 | +// +------+-----+------+-----+ +// | TKIP | AES | TKIP | AES | +// | 0 | 1 | 1 | 0 | -> 0x06 +// | 0 | 1 | 1 | 1 | -> 0x07 +// | 1 | 0 | 0 | 1 | -> 0x09 +// | 1 | 0 | 1 | 1 | -> 0x0B +// | 1 | 1 | 0 | 1 | -> 0x0D +// | 1 | 1 | 1 | 0 | -> 0x0E +// | 1 | 1 | 1 | 1 | -> 0x0F +// +------+-----+------+-----+ +// +typedef enum _WpaMixPairCipher +{ + MIX_CIPHER_NOTUSE = 0x00, + WPA_NONE_WPA2_TKIPAES = 0x03, // WPA2-TKIPAES + WPA_AES_WPA2_TKIP = 0x06, + WPA_AES_WPA2_TKIPAES = 0x07, + WPA_TKIP_WPA2_AES = 0x09, + WPA_TKIP_WPA2_TKIPAES = 0x0B, + WPA_TKIPAES_WPA2_NONE = 0x0C, // WPA-TKIPAES + WPA_TKIPAES_WPA2_AES = 0x0D, + WPA_TKIPAES_WPA2_TKIP = 0x0E, + WPA_TKIPAES_WPA2_TKIPAES = 0x0F, +} WPA_MIX_PAIR_CIPHER; + +typedef struct PACKED _RSN_IE_HEADER_STRUCT { + UCHAR Eid; + UCHAR Length; + USHORT Version; // Little endian format +} RSN_IE_HEADER_STRUCT, *PRSN_IE_HEADER_STRUCT; + +// Cipher suite selector types +typedef struct PACKED _CIPHER_SUITE_STRUCT { + UCHAR Oui[3]; + UCHAR Type; +} CIPHER_SUITE_STRUCT, *PCIPHER_SUITE_STRUCT; + +// Authentication and Key Management suite selector +typedef struct PACKED _AKM_SUITE_STRUCT { + UCHAR Oui[3]; + UCHAR Type; +} AKM_SUITE_STRUCT, *PAKM_SUITE_STRUCT; + +// RSN capability +typedef struct PACKED _RSN_CAPABILITY { + USHORT Rsv:10; + USHORT GTKSAReplayCnt:2; + USHORT PTKSAReplayCnt:2; + USHORT NoPairwise:1; + USHORT PreAuth:1; +} RSN_CAPABILITY, *PRSN_CAPABILITY; + +#endif diff --git a/drivers/staging/rtl8187se/dot11d.h b/drivers/staging/rtl8187se/dot11d.h index 49f53fe52af4..2417da99529f 100644 --- a/drivers/staging/rtl8187se/dot11d.h +++ b/drivers/staging/rtl8187se/dot11d.h @@ -1,101 +1,101 @@ -#ifndef __INC_DOT11D_H -#define __INC_DOT11D_H - -#include "ieee80211.h" - -//#define ENABLE_DOT11D - -//#define DOT11D_MAX_CHNL_NUM 83 - -typedef struct _CHNL_TXPOWER_TRIPLE { - u8 FirstChnl; - u8 NumChnls; - u8 MaxTxPowerInDbm; -}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; - -typedef enum _DOT11D_STATE { - DOT11D_STATE_NONE = 0, - DOT11D_STATE_LEARNED, - DOT11D_STATE_DONE, -}DOT11D_STATE; - -typedef struct _RT_DOT11D_INFO { - //DECLARE_RT_OBJECT(RT_DOT11D_INFO); - - bool bEnabled; // dot11MultiDomainCapabilityEnabled - - u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. - u8 CountryIeBuf[MAX_IE_LEN]; - u8 CountryIeSrcAddr[6]; // Source AP of the country IE. - u8 CountryIeWatchdog; - - u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) - //u8 ChnlListLen; // #Bytes valid in ChnlList[]. - //u8 ChnlList[DOT11D_MAX_CHNL_NUM]; - u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; - - DOT11D_STATE State; -}RT_DOT11D_INFO, *PRT_DOT11D_INFO; -#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) -#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5]) -#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) - -#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled -#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) - -#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) -#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) - -#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ - (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ - FALSE : \ - (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) - -#define CIE_WATCHDOG_TH 1 -#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog -#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 -#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) - -#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) - - -void -Dot11d_Init( - struct ieee80211_device *dev - ); - -void -Dot11d_Reset( - struct ieee80211_device *dev - ); - -void -Dot11d_UpdateCountryIe( - struct ieee80211_device *dev, - u8 * pTaddr, - u16 CoutryIeLen, - u8 * pCoutryIe - ); - -u8 -DOT11D_GetMaxTxPwrInDbm( - struct ieee80211_device *dev, - u8 Channel - ); - -void -DOT11D_ScanComplete( - struct ieee80211_device * dev - ); - -int IsLegalChannel( - struct ieee80211_device * dev, - u8 channel -); - -int ToLegalChannel( - struct ieee80211_device * dev, - u8 channel -); - -#endif // #ifndef __INC_DOT11D_H +#ifndef __INC_DOT11D_H +#define __INC_DOT11D_H + +#include "ieee80211.h" + +//#define ENABLE_DOT11D + +//#define DOT11D_MAX_CHNL_NUM 83 + +typedef struct _CHNL_TXPOWER_TRIPLE { + u8 FirstChnl; + u8 NumChnls; + u8 MaxTxPowerInDbm; +}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; + +typedef enum _DOT11D_STATE { + DOT11D_STATE_NONE = 0, + DOT11D_STATE_LEARNED, + DOT11D_STATE_DONE, +}DOT11D_STATE; + +typedef struct _RT_DOT11D_INFO { + //DECLARE_RT_OBJECT(RT_DOT11D_INFO); + + bool bEnabled; // dot11MultiDomainCapabilityEnabled + + u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. + u8 CountryIeBuf[MAX_IE_LEN]; + u8 CountryIeSrcAddr[6]; // Source AP of the country IE. + u8 CountryIeWatchdog; + + u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) + //u8 ChnlListLen; // #Bytes valid in ChnlList[]. + //u8 ChnlList[DOT11D_MAX_CHNL_NUM]; + u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; + + DOT11D_STATE State; +}RT_DOT11D_INFO, *PRT_DOT11D_INFO; +#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) +#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5]) +#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) + +#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled +#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) + +#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) +#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) + +#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ + (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ + FALSE : \ + (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) + +#define CIE_WATCHDOG_TH 1 +#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog +#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 +#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) + +#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) + + +void +Dot11d_Init( + struct ieee80211_device *dev + ); + +void +Dot11d_Reset( + struct ieee80211_device *dev + ); + +void +Dot11d_UpdateCountryIe( + struct ieee80211_device *dev, + u8 * pTaddr, + u16 CoutryIeLen, + u8 * pCoutryIe + ); + +u8 +DOT11D_GetMaxTxPwrInDbm( + struct ieee80211_device *dev, + u8 Channel + ); + +void +DOT11D_ScanComplete( + struct ieee80211_device * dev + ); + +int IsLegalChannel( + struct ieee80211_device * dev, + u8 channel +); + +int ToLegalChannel( + struct ieee80211_device * dev, + u8 channel +); + +#endif // #ifndef __INC_DOT11D_H diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c index 5d8b752fc0fb..54bcdcf1d330 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c @@ -1,246 +1,246 @@ -#ifdef ENABLE_DOT11D -//----------------------------------------------------------------------------- -// File: -// Dot11d.c -// -// Description: -// Implement 802.11d. -// -//----------------------------------------------------------------------------- - -#include "dot11d.h" - -void -Dot11d_Init(struct ieee80211_device *ieee) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); - - pDot11dInfo->bEnabled = 0; - - pDot11dInfo->State = DOT11D_STATE_NONE; - pDot11dInfo->CountryIeLen = 0; - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - RESET_CIE_WATCHDOG(ieee); - - printk("Dot11d_Init()\n"); -} - -// -// Description: -// Reset to the state as we are just entering a regulatory domain. -// -void -Dot11d_Reset(struct ieee80211_device *ieee) -{ - u32 i; - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); - - // Clear old channel map - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - // Set new channel map - for (i=1; i<=11; i++) { - (pDot11dInfo->channel_map)[i] = 1; - } - for (i=12; i<=14; i++) { - (pDot11dInfo->channel_map)[i] = 2; - } - - pDot11dInfo->State = DOT11D_STATE_NONE; - pDot11dInfo->CountryIeLen = 0; - RESET_CIE_WATCHDOG(ieee); - - //printk("Dot11d_Reset()\n"); -} - -// -// Description: -// Update country IE from Beacon or Probe Resopnse -// and configure PHY for operation in the regulatory domain. -// -// TODO: -// Configure Tx power. -// -// Assumption: -// 1. IS_DOT11D_ENABLE() is TRUE. -// 2. Input IE is an valid one. -// -void -Dot11d_UpdateCountryIe( - struct ieee80211_device *dev, - u8 * pTaddr, - u16 CoutryIeLen, - u8 * pCoutryIe - ) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - u8 i, j, NumTriples, MaxChnlNum; - PCHNL_TXPOWER_TRIPLE pTriple; - - if((CoutryIeLen - 3)%3 != 0) - { - printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); - Dot11d_Reset(dev); - return; - } - - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - MaxChnlNum = 0; - NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string. - pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); - for(i = 0; i < NumTriples; i++) - { - if(MaxChnlNum >= pTriple->FirstChnl) - { // It is not in a monotonically increasing order, so stop processing. - printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); - Dot11d_Reset(dev); - return; - } - if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) - { // It is not a valid set of channel id, so stop processing. - printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); - Dot11d_Reset(dev); - return; - } - - for(j = 0 ; j < pTriple->NumChnls; j++) - { - pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; - pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm; - MaxChnlNum = pTriple->FirstChnl + j; - } - - pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3); - } -#if 1 - //printk("Dot11d_UpdateCountryIe(): Channel List:\n"); - printk("Channel List:"); - for(i=1; i<= MAX_CHANNEL_NUMBER; i++) - if(pDot11dInfo->channel_map[i] > 0) - printk(" %d", i); - printk("\n"); -#endif - - UPDATE_CIE_SRC(dev, pTaddr); - - pDot11dInfo->CountryIeLen = CoutryIeLen; - memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen); - pDot11dInfo->State = DOT11D_STATE_LEARNED; -} - -void dump_chnl_map(u8 * channel_map) -{ - int i; - printk("Channel List:"); - for(i=1; i<= MAX_CHANNEL_NUMBER; i++) - if(channel_map[i] > 0) - printk(" %d(%d)", i, channel_map[i]); - printk("\n"); -} - -u8 -DOT11D_GetMaxTxPwrInDbm( - struct ieee80211_device *dev, - u8 Channel - ) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - u8 MaxTxPwrInDbm = 255; - - if(MAX_CHANNEL_NUMBER < Channel) - { - printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); - return MaxTxPwrInDbm; - } - if(pDot11dInfo->channel_map[Channel]) - { - MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; - } - - return MaxTxPwrInDbm; -} - - -void -DOT11D_ScanComplete( - struct ieee80211_device * dev - ) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - - switch(pDot11dInfo->State) - { - case DOT11D_STATE_LEARNED: - pDot11dInfo->State = DOT11D_STATE_DONE; - break; - - case DOT11D_STATE_DONE: - if( GET_CIE_WATCHDOG(dev) == 0 ) - { // Reset country IE if previous one is gone. - Dot11d_Reset(dev); - } - break; - case DOT11D_STATE_NONE: - break; - } -} - -int IsLegalChannel( - struct ieee80211_device * dev, - u8 channel -) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - - if(MAX_CHANNEL_NUMBER < channel) - { - printk("IsLegalChannel(): Invalid Channel\n"); - return 0; - } - if(pDot11dInfo->channel_map[channel] > 0) - return 1; - return 0; -} - -int ToLegalChannel( - struct ieee80211_device * dev, - u8 channel -) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - u8 default_chn = 0; - u32 i = 0; - - for (i=1; i<= MAX_CHANNEL_NUMBER; i++) - { - if(pDot11dInfo->channel_map[i] > 0) - { - default_chn = i; - break; - } - } - - if(MAX_CHANNEL_NUMBER < channel) - { - printk("IsLegalChannel(): Invalid Channel\n"); - return default_chn; - } - - if(pDot11dInfo->channel_map[channel] > 0) - return channel; - - return default_chn; -} - -#if 0 -EXPORT_SYMBOL(Dot11d_Init); -EXPORT_SYMBOL(Dot11d_Reset); -EXPORT_SYMBOL(Dot11d_UpdateCountryIe); -EXPORT_SYMBOL(DOT11D_GetMaxTxPwrInDbm); -EXPORT_SYMBOL(DOT11D_ScanComplete); -EXPORT_SYMBOL(IsLegalChannel); -EXPORT_SYMBOL(ToLegalChannel); -#endif -#endif +#ifdef ENABLE_DOT11D +//----------------------------------------------------------------------------- +// File: +// Dot11d.c +// +// Description: +// Implement 802.11d. +// +//----------------------------------------------------------------------------- + +#include "dot11d.h" + +void +Dot11d_Init(struct ieee80211_device *ieee) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); + + pDot11dInfo->bEnabled = 0; + + pDot11dInfo->State = DOT11D_STATE_NONE; + pDot11dInfo->CountryIeLen = 0; + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + RESET_CIE_WATCHDOG(ieee); + + printk("Dot11d_Init()\n"); +} + +// +// Description: +// Reset to the state as we are just entering a regulatory domain. +// +void +Dot11d_Reset(struct ieee80211_device *ieee) +{ + u32 i; + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); + + // Clear old channel map + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + // Set new channel map + for (i=1; i<=11; i++) { + (pDot11dInfo->channel_map)[i] = 1; + } + for (i=12; i<=14; i++) { + (pDot11dInfo->channel_map)[i] = 2; + } + + pDot11dInfo->State = DOT11D_STATE_NONE; + pDot11dInfo->CountryIeLen = 0; + RESET_CIE_WATCHDOG(ieee); + + //printk("Dot11d_Reset()\n"); +} + +// +// Description: +// Update country IE from Beacon or Probe Resopnse +// and configure PHY for operation in the regulatory domain. +// +// TODO: +// Configure Tx power. +// +// Assumption: +// 1. IS_DOT11D_ENABLE() is TRUE. +// 2. Input IE is an valid one. +// +void +Dot11d_UpdateCountryIe( + struct ieee80211_device *dev, + u8 * pTaddr, + u16 CoutryIeLen, + u8 * pCoutryIe + ) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + u8 i, j, NumTriples, MaxChnlNum; + PCHNL_TXPOWER_TRIPLE pTriple; + + if((CoutryIeLen - 3)%3 != 0) + { + printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); + Dot11d_Reset(dev); + return; + } + + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + MaxChnlNum = 0; + NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string. + pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); + for(i = 0; i < NumTriples; i++) + { + if(MaxChnlNum >= pTriple->FirstChnl) + { // It is not in a monotonically increasing order, so stop processing. + printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); + Dot11d_Reset(dev); + return; + } + if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) + { // It is not a valid set of channel id, so stop processing. + printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); + Dot11d_Reset(dev); + return; + } + + for(j = 0 ; j < pTriple->NumChnls; j++) + { + pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; + pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm; + MaxChnlNum = pTriple->FirstChnl + j; + } + + pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3); + } +#if 1 + //printk("Dot11d_UpdateCountryIe(): Channel List:\n"); + printk("Channel List:"); + for(i=1; i<= MAX_CHANNEL_NUMBER; i++) + if(pDot11dInfo->channel_map[i] > 0) + printk(" %d", i); + printk("\n"); +#endif + + UPDATE_CIE_SRC(dev, pTaddr); + + pDot11dInfo->CountryIeLen = CoutryIeLen; + memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen); + pDot11dInfo->State = DOT11D_STATE_LEARNED; +} + +void dump_chnl_map(u8 * channel_map) +{ + int i; + printk("Channel List:"); + for(i=1; i<= MAX_CHANNEL_NUMBER; i++) + if(channel_map[i] > 0) + printk(" %d(%d)", i, channel_map[i]); + printk("\n"); +} + +u8 +DOT11D_GetMaxTxPwrInDbm( + struct ieee80211_device *dev, + u8 Channel + ) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + u8 MaxTxPwrInDbm = 255; + + if(MAX_CHANNEL_NUMBER < Channel) + { + printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); + return MaxTxPwrInDbm; + } + if(pDot11dInfo->channel_map[Channel]) + { + MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; + } + + return MaxTxPwrInDbm; +} + + +void +DOT11D_ScanComplete( + struct ieee80211_device * dev + ) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + + switch(pDot11dInfo->State) + { + case DOT11D_STATE_LEARNED: + pDot11dInfo->State = DOT11D_STATE_DONE; + break; + + case DOT11D_STATE_DONE: + if( GET_CIE_WATCHDOG(dev) == 0 ) + { // Reset country IE if previous one is gone. + Dot11d_Reset(dev); + } + break; + case DOT11D_STATE_NONE: + break; + } +} + +int IsLegalChannel( + struct ieee80211_device * dev, + u8 channel +) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + + if(MAX_CHANNEL_NUMBER < channel) + { + printk("IsLegalChannel(): Invalid Channel\n"); + return 0; + } + if(pDot11dInfo->channel_map[channel] > 0) + return 1; + return 0; +} + +int ToLegalChannel( + struct ieee80211_device * dev, + u8 channel +) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + u8 default_chn = 0; + u32 i = 0; + + for (i=1; i<= MAX_CHANNEL_NUMBER; i++) + { + if(pDot11dInfo->channel_map[i] > 0) + { + default_chn = i; + break; + } + } + + if(MAX_CHANNEL_NUMBER < channel) + { + printk("IsLegalChannel(): Invalid Channel\n"); + return default_chn; + } + + if(pDot11dInfo->channel_map[channel] > 0) + return channel; + + return default_chn; +} + +#if 0 +EXPORT_SYMBOL(Dot11d_Init); +EXPORT_SYMBOL(Dot11d_Reset); +EXPORT_SYMBOL(Dot11d_UpdateCountryIe); +EXPORT_SYMBOL(DOT11D_GetMaxTxPwrInDbm); +EXPORT_SYMBOL(DOT11D_ScanComplete); +EXPORT_SYMBOL(IsLegalChannel); +EXPORT_SYMBOL(ToLegalChannel); +#endif +#endif diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.h b/drivers/staging/rtl8187se/ieee80211/dot11d.h index 64bcf15bd219..82576b519cc5 100644 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.h +++ b/drivers/staging/rtl8187se/ieee80211/dot11d.h @@ -1,102 +1,102 @@ -#ifndef __INC_DOT11D_H -#define __INC_DOT11D_H - -#include "ieee80211.h" - -//#define ENABLE_DOT11D - -//#define DOT11D_MAX_CHNL_NUM 83 - -typedef struct _CHNL_TXPOWER_TRIPLE { - u8 FirstChnl; - u8 NumChnls; - u8 MaxTxPowerInDbm; -}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; - -typedef enum _DOT11D_STATE { - DOT11D_STATE_NONE = 0, - DOT11D_STATE_LEARNED, - DOT11D_STATE_DONE, -}DOT11D_STATE; - -typedef struct _RT_DOT11D_INFO { - //DECLARE_RT_OBJECT(RT_DOT11D_INFO); - - bool bEnabled; // dot11MultiDomainCapabilityEnabled - - u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. - u8 CountryIeBuf[MAX_IE_LEN]; - u8 CountryIeSrcAddr[6]; // Source AP of the country IE. - u8 CountryIeWatchdog; - - u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) - //u8 ChnlListLen; // #Bytes valid in ChnlList[]. - //u8 ChnlList[DOT11D_MAX_CHNL_NUM]; - u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; - - DOT11D_STATE State; -}RT_DOT11D_INFO, *PRT_DOT11D_INFO; -#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) -#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5]) -#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) - -#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled -#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) - -#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) -#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) - -#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ - (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ - FALSE : \ - (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) - -#define CIE_WATCHDOG_TH 1 -#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog -#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 -#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) - -#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) - - -void -Dot11d_Init( - struct ieee80211_device *dev - ); - -void -Dot11d_Reset( - struct ieee80211_device *dev - ); - -void -Dot11d_UpdateCountryIe( - struct ieee80211_device *dev, - u8 * pTaddr, - u16 CoutryIeLen, - u8 * pCoutryIe - ); - -u8 -DOT11D_GetMaxTxPwrInDbm( - struct ieee80211_device *dev, - u8 Channel - ); - -void -DOT11D_ScanComplete( - struct ieee80211_device * dev - ); - -int IsLegalChannel( - struct ieee80211_device * dev, - u8 channel -); - -int ToLegalChannel( - struct ieee80211_device * dev, - u8 channel -); - -void dump_chnl_map(u8 * channel_map); -#endif // #ifndef __INC_DOT11D_H +#ifndef __INC_DOT11D_H +#define __INC_DOT11D_H + +#include "ieee80211.h" + +//#define ENABLE_DOT11D + +//#define DOT11D_MAX_CHNL_NUM 83 + +typedef struct _CHNL_TXPOWER_TRIPLE { + u8 FirstChnl; + u8 NumChnls; + u8 MaxTxPowerInDbm; +}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; + +typedef enum _DOT11D_STATE { + DOT11D_STATE_NONE = 0, + DOT11D_STATE_LEARNED, + DOT11D_STATE_DONE, +}DOT11D_STATE; + +typedef struct _RT_DOT11D_INFO { + //DECLARE_RT_OBJECT(RT_DOT11D_INFO); + + bool bEnabled; // dot11MultiDomainCapabilityEnabled + + u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. + u8 CountryIeBuf[MAX_IE_LEN]; + u8 CountryIeSrcAddr[6]; // Source AP of the country IE. + u8 CountryIeWatchdog; + + u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) + //u8 ChnlListLen; // #Bytes valid in ChnlList[]. + //u8 ChnlList[DOT11D_MAX_CHNL_NUM]; + u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; + + DOT11D_STATE State; +}RT_DOT11D_INFO, *PRT_DOT11D_INFO; +#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) +#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5]) +#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) + +#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled +#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) + +#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) +#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) + +#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ + (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ + FALSE : \ + (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) + +#define CIE_WATCHDOG_TH 1 +#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog +#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 +#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) + +#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) + + +void +Dot11d_Init( + struct ieee80211_device *dev + ); + +void +Dot11d_Reset( + struct ieee80211_device *dev + ); + +void +Dot11d_UpdateCountryIe( + struct ieee80211_device *dev, + u8 * pTaddr, + u16 CoutryIeLen, + u8 * pCoutryIe + ); + +u8 +DOT11D_GetMaxTxPwrInDbm( + struct ieee80211_device *dev, + u8 Channel + ); + +void +DOT11D_ScanComplete( + struct ieee80211_device * dev + ); + +int IsLegalChannel( + struct ieee80211_device * dev, + u8 channel +); + +int ToLegalChannel( + struct ieee80211_device * dev, + u8 channel +); + +void dump_chnl_map(u8 * channel_map); +#endif // #ifndef __INC_DOT11D_H diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c index 6aad61e78041..d1295e56fd42 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c @@ -842,14 +842,14 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) if (len>MAX_WPA_IE_LEN || (len && ie == NULL)) { - printk("return error out, len:%d\n", len); + printk("return error out, len:%zu\n", len); return -EINVAL; } if (len) { if (len != ie[1]+2){ - printk("len:%d, ie:%d\n", len, ie[1]); + printk("len:%zu, ie:%d\n", len, ie[1]); return -EINVAL; } buf = kmalloc(len, GFP_KERNEL); diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index ff1f23f99f27..6ecd12de4296 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -3161,7 +3161,7 @@ void rtl8180_prepare_beacon(struct net_device *dev) return ; } - //while(! *tail & (1<<31)){ + //while(! (*tail & (1<<31))){ *tail= 0; // zeroes header *tail = *tail| (1<<29) ; //fist segment of the packet diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c index 742dc11fcac9..93b5a7bb2559 100644 --- a/drivers/staging/rtl8187se/r8180_dm.c +++ b/drivers/staging/rtl8187se/r8180_dm.c @@ -1,1725 +1,1725 @@ -//#include "r8180.h" -#include "r8180_dm.h" -#include "r8180_hw.h" -#include "r8180_93cx6.h" -//{by amy 080312 - -// -// Description: -// Return TRUE if we shall perform High Power Mecahnism, FALSE otherwise. -// -//+by amy 080312 -#define RATE_ADAPTIVE_TIMER_PERIOD 300 - -bool CheckHighPower(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - - if(!priv->bRegHighPowerMechanism) - { - return false; - } - - if(ieee->state == IEEE80211_LINKED_SCANNING) - { - return false; - } - - return true; -} - -// -// Description: -// Update Tx power level if necessary. -// See also DoRxHighPower() and SetTxPowerLevel8185() for reference. -// -// Note: -// The reason why we udpate Tx power level here instead of DoRxHighPower() -// is the number of IO to change Tx power is much more than chane TR switch -// and they are related to OFDM and MAC registers. -// So, we don't want to update it so frequently in per-Rx packet base. -// -void -DoTxHighPower( - struct net_device *dev - ) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 HiPwrUpperTh = 0; - u16 HiPwrLowerTh = 0; - u8 RSSIHiPwrUpperTh; - u8 RSSIHiPwrLowerTh; - u8 u1bTmp; - char OfdmTxPwrIdx, CckTxPwrIdx; - - //printk("----> DoTxHighPower()\n"); - - HiPwrUpperTh = priv->RegHiPwrUpperTh; - HiPwrLowerTh = priv->RegHiPwrLowerTh; - - HiPwrUpperTh = HiPwrUpperTh * 10; - HiPwrLowerTh = HiPwrLowerTh * 10; - RSSIHiPwrUpperTh = priv->RegRSSIHiPwrUpperTh; - RSSIHiPwrLowerTh = priv->RegRSSIHiPwrLowerTh; - - //lzm add 080826 - OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel]; - CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel]; - - // printk("DoTxHighPower() - UndecoratedSmoothedSS:%d, CurCCKRSSI = %d , bCurCCKPkt= %d \n", priv->UndecoratedSmoothedSS, priv->CurCCKRSSI, priv->bCurCCKPkt ); - - if((priv->UndecoratedSmoothedSS > HiPwrUpperTh) || - (priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh))) - { - // Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah - - // printk("=====>DoTxHighPower() - High Power - UndecoratedSmoothedSS:%d, HiPwrUpperTh = %d \n", priv->UndecoratedSmoothedSS, HiPwrUpperTh ); - priv->bToUpdateTxPwr = true; - u1bTmp= read_nic_byte(dev, CCK_TXAGC); - - // If it never enter High Power. - if( CckTxPwrIdx == u1bTmp) - { - u1bTmp = (u1bTmp > 16) ? (u1bTmp -16): 0; // 8dbm - write_nic_byte(dev, CCK_TXAGC, u1bTmp); - - u1bTmp= read_nic_byte(dev, OFDM_TXAGC); - u1bTmp = (u1bTmp > 16) ? (u1bTmp -16): 0; // 8dbm - write_nic_byte(dev, OFDM_TXAGC, u1bTmp); - } - - } - else if((priv->UndecoratedSmoothedSS < HiPwrLowerTh) && - (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) - { - // printk("DoTxHighPower() - lower Power - UndecoratedSmoothedSS:%d, HiPwrUpperTh = %d \n", priv->UndecoratedSmoothedSS, HiPwrLowerTh ); - if(priv->bToUpdateTxPwr) - { - priv->bToUpdateTxPwr = false; - //SD3 required. - u1bTmp= read_nic_byte(dev, CCK_TXAGC); - if(u1bTmp < CckTxPwrIdx) - { - //u1bTmp = ((u1bTmp+16) > 35) ? 35: (u1bTmp+16); // 8dbm - //write_nic_byte(dev, CCK_TXAGC, u1bTmp); - write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx); - } - - u1bTmp= read_nic_byte(dev, OFDM_TXAGC); - if(u1bTmp < OfdmTxPwrIdx) - { - //u1bTmp = ((u1bTmp+16) > 35) ? 35: (u1bTmp+16); // 8dbm - //write_nic_byte(dev, OFDM_TXAGC, u1bTmp); - write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx); - } - } - } - - //printk("<---- DoTxHighPower()\n"); -} - - -// -// Description: -// Callback function of UpdateTxPowerWorkItem. -// Because of some event happend, e.g. CCX TPC, High Power Mechanism, -// We update Tx power of current channel again. -// -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) -void rtl8180_tx_pw_wq (struct work_struct *work) -{ -// struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq); -// struct ieee80211_device * ieee = (struct ieee80211_device*) -// container_of(work, struct ieee80211_device, watch_dog_wq); - struct delayed_work *dwork = container_of(work,struct delayed_work,work); - struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,tx_pw_wq); - struct net_device *dev = ieee->dev; -#else -void rtl8180_tx_pw_wq(struct net_device *dev) -{ - // struct r8180_priv *priv = ieee80211_priv(dev); -#endif - -// printk("----> UpdateTxPowerWorkItemCallback()\n"); - - DoTxHighPower(dev); - -// printk("<---- UpdateTxPowerWorkItemCallback()\n"); -} - - -// -// Description: -// Return TRUE if we shall perform DIG Mecahnism, FALSE otherwise. -// -bool -CheckDig( - struct net_device *dev - ) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - - if(!priv->bDigMechanism) - return false; - - if(ieee->state != IEEE80211_LINKED) - return false; - - //if(priv->CurrentOperaRate < 36) // Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. - if((priv->ieee80211->rate/5) < 36) // Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. - return false; - return true; -} -// -// Description: -// Implementation of DIG for Zebra and Zebra2. -// -void -DIG_Zebra( - struct net_device *dev - ) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 CCKFalseAlarm, OFDMFalseAlarm; - u16 OfdmFA1, OfdmFA2; - int InitialGainStep = 7; // The number of initial gain stages. - int LowestGainStage = 4; // The capable lowest stage of performing dig workitem. - u32 AwakePeriodIn2Sec=0; - - //printk("---------> DIG_Zebra()\n"); - - CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff); - OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff); - OfdmFA1 = 0x15; - OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8; - -// printk("DIG**********CCK False Alarm: %#X \n",CCKFalseAlarm); -// printk("DIG**********OFDM False Alarm: %#X \n",OFDMFalseAlarm); - - // The number of initial gain steps is different, by Bruce, 2007-04-13. - if (priv->InitialGain == 0 ) //autoDIG - { // Advised from SD3 DZ - priv->InitialGain = 4; // In 87B, m74dBm means State 4 (m82dBm) - } - //if(pHalData->VersionID != VERSION_8187B_B) - { // Advised from SD3 DZ - OfdmFA1 = 0x20; - } - -#if 1 //lzm reserved 080826 - AwakePeriodIn2Sec = (2000-priv ->DozePeriodInPast2Sec); - //printk("&&& DozePeriod=%d AwakePeriod=%d\n", priv->DozePeriodInPast2Sec, AwakePeriodIn2Sec); - priv ->DozePeriodInPast2Sec=0; - - if(AwakePeriodIn2Sec) - { - //RT_TRACE(COMP_DIG, DBG_TRACE, ("DIG: AwakePeriodIn2Sec(%d) - FATh(0x%X , 0x%X) ->",AwakePeriodIn2Sec, OfdmFA1, OfdmFA2)); - // adjuest DIG threshold. - OfdmFA1 = (u16)((OfdmFA1*AwakePeriodIn2Sec) / 2000) ; - OfdmFA2 = (u16)((OfdmFA2*AwakePeriodIn2Sec) / 2000) ; - //RT_TRACE(COMP_DIG, DBG_TRACE, ("( 0x%X , 0x%X)\n", OfdmFA1, OfdmFA2)); - } - else - { - ;//RT_TRACE(COMP_DIG, DBG_WARNING, ("ERROR!! AwakePeriodIn2Sec should not be ZERO!!\n")); - } -#endif - - InitialGainStep = 8; - LowestGainStage = priv->RegBModeGainStage; // Lowest gain stage. - - if (OFDMFalseAlarm > OfdmFA1) - { - if (OFDMFalseAlarm > OfdmFA2) - { - priv->DIG_NumberFallbackVote++; - if (priv->DIG_NumberFallbackVote >1) - { - //serious OFDM False Alarm, need fallback - if (priv->InitialGain < InitialGainStep) - { - priv->InitialGainBackUp= priv->InitialGain; - - priv->InitialGain = (priv->InitialGain + 1); -// printk("DIG**********OFDM False Alarm: %#X, OfdmFA1: %#X, OfdmFA2: %#X\n", OFDMFalseAlarm, OfdmFA1, OfdmFA2); -// printk("DIG+++++++ fallback OFDM:%d \n", priv->InitialGain); - UpdateInitialGain(dev); - } - priv->DIG_NumberFallbackVote = 0; - priv->DIG_NumberUpgradeVote=0; - } - } - else - { - if (priv->DIG_NumberFallbackVote) - priv->DIG_NumberFallbackVote--; - } - priv->DIG_NumberUpgradeVote=0; - } - else - { - if (priv->DIG_NumberFallbackVote) - priv->DIG_NumberFallbackVote--; - priv->DIG_NumberUpgradeVote++; - - if (priv->DIG_NumberUpgradeVote>9) - { - if (priv->InitialGain > LowestGainStage) // In 87B, m78dBm means State 4 (m864dBm) - { - priv->InitialGainBackUp= priv->InitialGain; - - priv->InitialGain = (priv->InitialGain - 1); -// printk("DIG**********OFDM False Alarm: %#X, OfdmFA1: %#X, OfdmFA2: %#X\n", OFDMFalseAlarm, OfdmFA1, OfdmFA2); -// printk("DIG--------- Upgrade OFDM:%d \n", priv->InitialGain); - UpdateInitialGain(dev); - } - priv->DIG_NumberFallbackVote = 0; - priv->DIG_NumberUpgradeVote=0; - } - } - -// printk("DIG+++++++ OFDM:%d\n", priv->InitialGain); - //printk("<--------- DIG_Zebra()\n"); -} - -// -// Description: -// Dispatch DIG implementation according to RF. -// -void -DynamicInitGain( - struct net_device *dev - ) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - switch(priv->rf_chip) - { - case RF_ZEBRA2: // [AnnieWorkaround] For Zebra2, 2005-08-01. - case RF_ZEBRA4: - DIG_Zebra( dev ); - break; - - default: - printk("DynamicInitGain(): unknown RFChipID(%d) !!!\n", priv->rf_chip); - break; - } -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) -void rtl8180_hw_dig_wq (struct work_struct *work) -{ -// struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq); -// struct ieee80211_device * ieee = (struct ieee80211_device*) -// container_of(work, struct ieee80211_device, watch_dog_wq); - struct delayed_work *dwork = container_of(work,struct delayed_work,work); - struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_dig_wq); - struct net_device *dev = ieee->dev; -#else -void rtl8180_hw_dig_wq(struct net_device *dev) -{ - -#endif - struct r8180_priv *priv = ieee80211_priv(dev); - - // Read CCK and OFDM False Alarm. - priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM); - - - // Adjust Initial Gain dynamically. - DynamicInitGain(dev); - -} - -int -IncludedInSupportedRates( - struct r8180_priv *priv, - u8 TxRate ) -{ - u8 rate_len; - u8 rate_ex_len; - u8 RateMask = 0x7F; - u8 idx; - unsigned short Found = 0; - u8 NaiveTxRate = TxRate&RateMask; - - rate_len = priv->ieee80211->current_network.rates_len; - rate_ex_len = priv->ieee80211->current_network.rates_ex_len; - for( idx=0; idx< rate_len; idx++ ) - { - if( (priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate ) - { - Found = 1; - goto found_rate; - } - } - for( idx=0; idx< rate_ex_len; idx++ ) - { - if( (priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate ) - { - Found = 1; - goto found_rate; - } - } - return Found; - found_rate: - return Found; -} - -// -// Description: -// Get the Tx rate one degree up form the input rate in the supported rates. -// Return the upgrade rate if it is successed, otherwise return the input rate. -// By Bruce, 2007-06-05. -// -u8 -GetUpgradeTxRate( - struct net_device *dev, - u8 rate - ) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 UpRate; - - // Upgrade 1 degree. - switch(rate) - { - case 108: // Up to 54Mbps. - UpRate = 108; - break; - - case 96: // Up to 54Mbps. - UpRate = 108; - break; - - case 72: // Up to 48Mbps. - UpRate = 96; - break; - - case 48: // Up to 36Mbps. - UpRate = 72; - break; - - case 36: // Up to 24Mbps. - UpRate = 48; - break; - - case 22: // Up to 18Mbps. - UpRate = 36; - break; - - case 11: // Up to 11Mbps. - UpRate = 22; - break; - - case 4: // Up to 5.5Mbps. - UpRate = 11; - break; - - case 2: // Up to 2Mbps. - UpRate = 4; - break; - - default: - printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); - return rate; - } - // Check if the rate is valid. - if(IncludedInSupportedRates(priv, UpRate)) - { -// printk("GetUpgradeTxRate(): GetUpgrade Tx rate(%d) from %d !\n", UpRate, priv->CurrentOperaRate); - return UpRate; - } - else - { - //printk("GetUpgradeTxRate(): Tx rate (%d) is not in supported rates\n", UpRate); - return rate; - } - return rate; -} -// -// Description: -// Get the Tx rate one degree down form the input rate in the supported rates. -// Return the degrade rate if it is successed, otherwise return the input rate. -// By Bruce, 2007-06-05. -// -u8 -GetDegradeTxRate( - struct net_device *dev, - u8 rate - ) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 DownRate; - - // Upgrade 1 degree. - switch(rate) - { - case 108: // Down to 48Mbps. - DownRate = 96; - break; - - case 96: // Down to 36Mbps. - DownRate = 72; - break; - - case 72: // Down to 24Mbps. - DownRate = 48; - break; - - case 48: // Down to 18Mbps. - DownRate = 36; - break; - - case 36: // Down to 11Mbps. - DownRate = 22; - break; - - case 22: // Down to 5.5Mbps. - DownRate = 11; - break; - - case 11: // Down to 2Mbps. - DownRate = 4; - break; - - case 4: // Down to 1Mbps. - DownRate = 2; - break; - - case 2: // Down to 1Mbps. - DownRate = 2; - break; - - default: - printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); - return rate; - } - // Check if the rate is valid. - if(IncludedInSupportedRates(priv, DownRate)) - { -// printk("GetDegradeTxRate(): GetDegrade Tx rate(%d) from %d!\n", DownRate, priv->CurrentOperaRate); - return DownRate; - } - else - { - //printk("GetDegradeTxRate(): Tx rate (%d) is not in supported rates\n", DownRate); - return rate; - } - return rate; -} -// -// Helper function to determine if specified data rate is -// CCK rate. -// 2005.01.25, by rcnjko. -// -bool -MgntIsCckRate( - u16 rate - ) -{ - bool bReturn = false; - - if((rate <= 22) && (rate != 12) && (rate != 18)) - { - bReturn = true; - } - - return bReturn; -} -#ifdef CONFIG_RTL818X_S -// -// Description: -// Tx Power tracking mechanism routine on 87SE. -// Created by Roger, 2007.12.11. -// -void -TxPwrTracking87SE( - struct net_device *dev -) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u8 tmpu1Byte, CurrentThermal, Idx; - char CckTxPwrIdx, OfdmTxPwrIdx; - //u32 u4bRfReg; - - tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL); - CurrentThermal = (tmpu1Byte & 0xf0)>>4; //[ 7:4]: thermal meter indication. - CurrentThermal = (CurrentThermal>0x0c)? 0x0c:CurrentThermal;//lzm add 080826 - - //printk("TxPwrTracking87SE(): CurrentThermal(%d)\n", CurrentThermal); - - if( CurrentThermal != priv->ThermalMeter) - { -// printk("TxPwrTracking87SE(): Thermal meter changed!!!\n"); - - // Update Tx Power level on each channel. - for(Idx = 1; Idx<15; Idx++) - { - CckTxPwrIdx = priv->chtxpwr[Idx]; - OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx]; - - if( CurrentThermal > priv->ThermalMeter ) - { // higher thermal meter. - CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter)*2; - OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter)*2; - - if(CckTxPwrIdx >35) - CckTxPwrIdx = 35; // Force TxPower to maximal index. - if(OfdmTxPwrIdx >35) - OfdmTxPwrIdx = 35; - } - else - { // lower thermal meter. - CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal)*2; - OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal)*2; - - if(CckTxPwrIdx <0) - CckTxPwrIdx = 0; - if(OfdmTxPwrIdx <0) - OfdmTxPwrIdx = 0; - } - - // Update TxPower level on CCK and OFDM resp. - priv->chtxpwr[Idx] = CckTxPwrIdx; - priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx; - } - - // Update TxPower level immediately. - rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel); - } - priv->ThermalMeter = CurrentThermal; -} -void -StaRateAdaptive87SE( - struct net_device *dev - ) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - unsigned long CurrTxokCnt; - u16 CurrRetryCnt; - u16 CurrRetryRate; - //u16 i,idx; - unsigned long CurrRxokCnt; - bool bTryUp = false; - bool bTryDown = false; - u8 TryUpTh = 1; - u8 TryDownTh = 2; - u32 TxThroughput; - long CurrSignalStrength; - bool bUpdateInitialGain = false; - u8 u1bOfdm=0, u1bCck = 0; - char OfdmTxPwrIdx, CckTxPwrIdx; - - priv->RateAdaptivePeriod= RATE_ADAPTIVE_TIMER_PERIOD; - - - CurrRetryCnt = priv->CurrRetryCnt; - CurrTxokCnt = priv->NumTxOkTotal - priv->LastTxokCnt; - CurrRxokCnt = priv->ieee80211->NumRxOkTotal - priv->LastRxokCnt; - CurrSignalStrength = priv->Stats_RecvSignalPower; - TxThroughput = (u32)(priv->NumTxOkBytesTotal - priv->LastTxOKBytes); - priv->LastTxOKBytes = priv->NumTxOkBytesTotal; - priv->CurrentOperaRate = priv->ieee80211->rate/5; - //printk("priv->CurrentOperaRate is %d\n",priv->CurrentOperaRate); - //2 Compute retry ratio. - if (CurrTxokCnt>0) - { - CurrRetryRate = (u16)(CurrRetryCnt*100/CurrTxokCnt); - } - else - { // It may be serious retry. To distinguish serious retry or no packets modified by Bruce - CurrRetryRate = (u16)(CurrRetryCnt*100/1); - } - - - // - // Added by Roger, 2007.01.02. - // For debug information. - // - //printk("\n(1) pHalData->LastRetryRate: %d \n",priv->LastRetryRate); - //printk("(2) RetryCnt = %d \n", CurrRetryCnt); - //printk("(3) TxokCnt = %d \n", CurrTxokCnt); - //printk("(4) CurrRetryRate = %d \n", CurrRetryRate); - //printk("(5) CurrSignalStrength = %d \n",CurrSignalStrength); - //printk("(6) TxThroughput is %d\n",TxThroughput); - //printk("priv->NumTxOkBytesTotal is %d\n",priv->NumTxOkBytesTotal); - - priv->LastRetryCnt = priv->CurrRetryCnt; - priv->LastTxokCnt = priv->NumTxOkTotal; - priv->LastRxokCnt = priv->ieee80211->NumRxOkTotal; - priv->CurrRetryCnt = 0; - - //2No Tx packets, return to init_rate or not? - if (CurrRetryRate==0 && CurrTxokCnt == 0) - { - // - //After 9 (30*300ms) seconds in this condition, we try to raise rate. - // - priv->TryupingCountNoData++; - -// printk("No Tx packets, TryupingCountNoData(%d)\n", priv->TryupingCountNoData); - //[TRC Dell Lab] Extend raised period from 4.5sec to 9sec, Isaiah 2008-02-15 18:00 - if (priv->TryupingCountNoData>30) - { - priv->TryupingCountNoData = 0; - priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); - // Reset Fail Record - priv->LastFailTxRate = 0; - priv->LastFailTxRateSS = -200; - priv->FailTxRateCount = 0; - } - goto SetInitialGain; - } - else - { - priv->TryupingCountNoData=0; //Reset trying up times. - } - - - // - // For Netgear case, I comment out the following signal strength estimation, - // which can results in lower rate to transmit when sample is NOT enough (e.g. PING request). - // 2007.04.09, by Roger. - // - - // - // Restructure rate adaptive as the following main stages: - // (1) Add retry threshold in 54M upgrading condition with signal strength. - // (2) Add the mechanism to degrade to CCK rate according to signal strength - // and retry rate. - // (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated - // situation, Initial Gain Update is upon on DIG mechanism except CCK rate. - // (4) Add the mehanism of trying to upgrade tx rate. - // (5) Record the information of upping tx rate to avoid trying upping tx rate constantly. - // By Bruce, 2007-06-05. - // - // - - // 11Mbps or 36Mbps - // Check more times in these rate(key rates). - // - if(priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72) - { - TryUpTh += 9; - } - // - // Let these rates down more difficult. - // - if(MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36) - { - TryDownTh += 1; - } - - //1 Adjust Rate. - if (priv->bTryuping == true) - { - //2 For Test Upgrading mechanism - // Note: - // Sometimes the throughput is upon on the capability bwtween the AP and NIC, - // thus the low data rate does not improve the performance. - // We randomly upgrade the data rate and check if the retry rate is improved. - - // Upgrading rate did not improve the retry rate, fallback to the original rate. - if ( (CurrRetryRate > 25) && TxThroughput < priv->LastTxThroughput) - { - //Not necessary raising rate, fall back rate. - bTryDown = true; - //printk("case1-1: Not necessary raising rate, fall back rate....\n"); - //printk("case1-1: pMgntInfo->CurrentOperaRate =%d, TxThroughput = %d, LastThroughput = %d\n", - // priv->CurrentOperaRate, TxThroughput, priv->LastTxThroughput); - } - else - { - priv->bTryuping = false; - } - } - else if (CurrSignalStrength > -47 && (CurrRetryRate < 50)) - { - //2For High Power - // - // Added by Roger, 2007.04.09. - // Return to highest data rate, if signal strength is good enough. - // SignalStrength threshold(-50dbm) is for RTL8186. - // Revise SignalStrength threshold to -51dbm. - // - // Also need to check retry rate for safety, by Bruce, 2007-06-05. - if(priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate ) - { - bTryUp = true; - // Upgrade Tx Rate directly. - priv->TryupingCount += TryUpTh; - } -// printk("case2: StaRateAdaptive87SE: Power(%d) is high enough!!. \n", CurrSignalStrength); - - } - else if(CurrTxokCnt > 9 && CurrTxokCnt< 100 && CurrRetryRate >= 600) - { - //2 For Serious Retry - // - // Traffic is not busy but our Tx retry is serious. - // - bTryDown = true; - // Let Rate Mechanism to degrade tx rate directly. - priv->TryDownCountLowData += TryDownTh; -// printk("case3: RA: Tx Retry is serious. Degrade Tx Rate to %d directly...\n", priv->CurrentOperaRate); - } - else if ( priv->CurrentOperaRate == 108 ) - { - //2For 54Mbps - // Air Link - if ( (CurrRetryRate>26)&&(priv->LastRetryRate>25)) -// if ( (CurrRetryRate>40)&&(priv->LastRetryRate>39)) - { - //Down to rate 48Mbps. - bTryDown = true; - } - // Cable Link - else if ( (CurrRetryRate>17)&&(priv->LastRetryRate>16) && (CurrSignalStrength > -72)) -// else if ( (CurrRetryRate>17)&&(priv->LastRetryRate>16) && (CurrSignalStrength > -72)) - { - //Down to rate 48Mbps. - bTryDown = true; - } - - if(bTryDown && (CurrSignalStrength < -75)) //cable link - { - priv->TryDownCountLowData += TryDownTh; - } - //printk("case4---54M \n"); - - } - else if ( priv->CurrentOperaRate == 96 ) - { - //2For 48Mbps - //Air Link - if ( ((CurrRetryRate>48) && (priv->LastRetryRate>47))) -// if ( ((CurrRetryRate>65) && (priv->LastRetryRate>64))) - - { - //Down to rate 36Mbps. - bTryDown = true; - } - //Cable Link - else if ( ((CurrRetryRate>21) && (priv->LastRetryRate>20)) && (CurrSignalStrength > -74)) - { - //Down to rate 36Mbps. - bTryDown = true; - } - else if((CurrRetryRate> (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 )) -// else if((CurrRetryRate> (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 )) - { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } - else if ( (CurrRetryRate<8) && (priv->LastRetryRate<8) ) //TO DO: need to consider (RSSI) -// else if ( (CurrRetryRate<28) && (priv->LastRetryRate<8) ) - { - bTryUp = true; - } - - if(bTryDown && (CurrSignalStrength < -75)) - { - priv->TryDownCountLowData += TryDownTh; - } - //printk("case5---48M \n"); - } - else if ( priv->CurrentOperaRate == 72 ) - { - //2For 36Mbps - if ( (CurrRetryRate>43) && (priv->LastRetryRate>41)) -// if ( (CurrRetryRate>60) && (priv->LastRetryRate>59)) - { - //Down to rate 24Mbps. - bTryDown = true; - } - else if((CurrRetryRate> (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 )) -// else if((CurrRetryRate> (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 )) - { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } - else if ( (CurrRetryRate<15) && (priv->LastRetryRate<16)) //TO DO: need to consider (RSSI) -// else if ( (CurrRetryRate<35) && (priv->LastRetryRate<36)) - { - bTryUp = true; - } - - if(bTryDown && (CurrSignalStrength < -80)) - { - priv->TryDownCountLowData += TryDownTh; - } - //printk("case6---36M \n"); - } - else if ( priv->CurrentOperaRate == 48 ) - { - //2For 24Mbps - // Air Link - if ( ((CurrRetryRate>63) && (priv->LastRetryRate>62))) -// if ( ((CurrRetryRate>83) && (priv->LastRetryRate>82))) - { - //Down to rate 18Mbps. - bTryDown = true; - } - //Cable Link - else if ( ((CurrRetryRate>33) && (priv->LastRetryRate>32)) && (CurrSignalStrength > -82) ) -// else if ( ((CurrRetryRate>50) && (priv->LastRetryRate>49)) && (CurrSignalStrength > -82) ) - { - //Down to rate 18Mbps. - bTryDown = true; - } - else if((CurrRetryRate> (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 )) -// else if((CurrRetryRate> (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 )) - - { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } - else if ( (CurrRetryRate<20) && (priv->LastRetryRate<21)) //TO DO: need to consider (RSSI) -// else if ( (CurrRetryRate<40) && (priv->LastRetryRate<41)) - { - bTryUp = true; - } - - if(bTryDown && (CurrSignalStrength < -82)) - { - priv->TryDownCountLowData += TryDownTh; - } - //printk("case7---24M \n"); - } - else if ( priv->CurrentOperaRate == 36 ) - { - //2For 18Mbps - // original (109, 109) - //[TRC Dell Lab] (90, 91), Isaiah 2008-02-18 23:24 - // (85, 86), Isaiah 2008-02-18 24:00 - if ( ((CurrRetryRate>85) && (priv->LastRetryRate>86))) -// if ( ((CurrRetryRate>115) && (priv->LastRetryRate>116))) - { - //Down to rate 11Mbps. - bTryDown = true; - } - //[TRC Dell Lab] Isaiah 2008-02-18 23:24 - else if((CurrRetryRate> (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 )) -// else if((CurrRetryRate> (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 )) - { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } - else if ( (CurrRetryRate<22) && (priv->LastRetryRate<23)) //TO DO: need to consider (RSSI) -// else if ( (CurrRetryRate<42) && (priv->LastRetryRate<43)) - { - bTryUp = true; - } - //printk("case8---18M \n"); - } - else if ( priv->CurrentOperaRate == 22 ) - { - //2For 11Mbps - if (CurrRetryRate>95) -// if (CurrRetryRate>155) - { - bTryDown = true; - } - else if ( (CurrRetryRate<29) && (priv->LastRetryRate <30) )//TO DO: need to consider (RSSI) -// else if ( (CurrRetryRate<49) && (priv->LastRetryRate <50) ) - { - bTryUp = true; - } - //printk("case9---11M \n"); - } - else if ( priv->CurrentOperaRate == 11 ) - { - //2For 5.5Mbps - if (CurrRetryRate>149) -// if (CurrRetryRate>189) - { - bTryDown = true; - } - else if ( (CurrRetryRate<60) && (priv->LastRetryRate < 65)) -// else if ( (CurrRetryRate<80) && (priv->LastRetryRate < 85)) - - { - bTryUp = true; - } - //printk("case10---5.5M \n"); - } - else if ( priv->CurrentOperaRate == 4 ) - { - //2For 2 Mbps - if((CurrRetryRate>99) && (priv->LastRetryRate>99)) -// if((CurrRetryRate>199) && (priv->LastRetryRate>199)) - { - bTryDown = true; - } - else if ( (CurrRetryRate < 65) && (priv->LastRetryRate < 70)) -// else if ( (CurrRetryRate < 85) && (priv->LastRetryRate < 90)) - { - bTryUp = true; - } - //printk("case11---2M \n"); - } - else if ( priv->CurrentOperaRate == 2 ) - { - //2For 1 Mbps - if( (CurrRetryRate<70) && (priv->LastRetryRate<75)) -// if( (CurrRetryRate<90) && (priv->LastRetryRate<95)) - { - bTryUp = true; - } - //printk("case12---1M \n"); - } - - if(bTryUp && bTryDown) - printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n"); - - //1 Test Upgrading Tx Rate - // Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC. - // To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate. - if(!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0) - && priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate && priv->FailTxRateCount < 2) - { - if(jiffies% (CurrRetryRate + 101) == 0) - { - bTryUp = true; - priv->bTryuping = true; - //printk("StaRateAdaptive87SE(): Randomly try upgrading...\n"); - } - } - - //1 Rate Mechanism - if(bTryUp) - { - priv->TryupingCount++; - priv->TryDownCountLowData = 0; - - { -// printk("UP: pHalData->TryupingCount = %d\n", priv->TryupingCount); -// printk("UP: TryUpTh(%d)+ (FailTxRateCount(%d))^2 =%d\n", -// TryUpTh, priv->FailTxRateCount, (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount) ); -// printk("UP: pHalData->bTryuping=%d\n", priv->bTryuping); - - } - - // - // Check more times if we need to upgrade indeed. - // Because the largest value of pHalData->TryupingCount is 0xFFFF and - // the largest value of pHalData->FailTxRateCount is 0x14, - // this condition will be satisfied at most every 2 min. - // - - if((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) || - (CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping) - { - priv->TryupingCount = 0; - // - // When transfering from CCK to OFDM, DIG is an important issue. - // - if(priv->CurrentOperaRate == 22) - bUpdateInitialGain = true; - - // The difference in throughput between 48Mbps and 36Mbps is 8M. - // So, we must be carefully in this rate scale. Isaiah 2008-02-15. - // - if( ((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) && - (priv->FailTxRateCount > 2) ) - priv->RateAdaptivePeriod= (RATE_ADAPTIVE_TIMER_PERIOD/2); - - // (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold. - // (2)If the signal strength is increased, it may be able to upgrade. - - priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); -// printk("StaRateAdaptive87SE(): Upgrade Tx Rate to %d\n", priv->CurrentOperaRate); - - //[TRC Dell Lab] Bypass 12/9/6, Isaiah 2008-02-18 20:00 - if(priv->CurrentOperaRate ==36) - { - priv->bUpdateARFR=true; - write_nic_word(dev, ARFR, 0x0F8F); //bypass 12/9/6 -// printk("UP: ARFR=0xF8F\n"); - } - else if(priv->bUpdateARFR) - { - priv->bUpdateARFR=false; - write_nic_word(dev, ARFR, 0x0FFF); //set 1M ~ 54Mbps. -// printk("UP: ARFR=0xFFF\n"); - } - - // Update Fail Tx rate and count. - if(priv->LastFailTxRate != priv->CurrentOperaRate) - { - priv->LastFailTxRate = priv->CurrentOperaRate; - priv->FailTxRateCount = 0; - priv->LastFailTxRateSS = -200; // Set lowest power. - } - } - } - else - { - if(priv->TryupingCount > 0) - priv->TryupingCount --; - } - - if(bTryDown) - { - priv->TryDownCountLowData++; - priv->TryupingCount = 0; - { -// printk("DN: pHalData->TryDownCountLowData = %d\n",priv->TryDownCountLowData); -// printk("DN: TryDownTh =%d\n", TryDownTh); -// printk("DN: pHalData->bTryuping=%d\n", priv->bTryuping); - } - - //Check if Tx rate can be degraded or Test trying upgrading should fallback. - if(priv->TryDownCountLowData > TryDownTh || priv->bTryuping) - { - priv->TryDownCountLowData = 0; - priv->bTryuping = false; - // Update fail information. - if(priv->LastFailTxRate == priv->CurrentOperaRate) - { - priv->FailTxRateCount ++; - // Record the Tx fail rate signal strength. - if(CurrSignalStrength > priv->LastFailTxRateSS) - { - priv->LastFailTxRateSS = CurrSignalStrength; - } - } - else - { - priv->LastFailTxRate = priv->CurrentOperaRate; - priv->FailTxRateCount = 1; - priv->LastFailTxRateSS = CurrSignalStrength; - } - priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate); - - // Reduce chariot training time at weak signal strength situation. SD3 ED demand. - //[TRC Dell Lab] Revise Signal Threshold from -75 to -80 , Isaiah 2008-02-18 20:00 - if( (CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72 )) - { - priv->CurrentOperaRate = 72; -// printk("DN: weak signal strength (%d), degrade to 36Mbps\n", CurrSignalStrength); - } - - //[TRC Dell Lab] Bypass 12/9/6, Isaiah 2008-02-18 20:00 - if(priv->CurrentOperaRate ==36) - { - priv->bUpdateARFR=true; - write_nic_word(dev, ARFR, 0x0F8F); //bypass 12/9/6 -// printk("DN: ARFR=0xF8F\n"); - } - else if(priv->bUpdateARFR) - { - priv->bUpdateARFR=false; - write_nic_word(dev, ARFR, 0x0FFF); //set 1M ~ 54Mbps. -// printk("DN: ARFR=0xFFF\n"); - } - - // - // When it is CCK rate, it may need to update initial gain to receive lower power packets. - // - if(MgntIsCckRate(priv->CurrentOperaRate)) - { - bUpdateInitialGain = true; - } -// printk("StaRateAdaptive87SE(): Degrade Tx Rate to %d\n", priv->CurrentOperaRate); - } - } - else - { - if(priv->TryDownCountLowData > 0) - priv->TryDownCountLowData --; - } - - // Keep the Tx fail rate count to equal to 0x15 at most. - // Reduce the fail count at least to 10 sec if tx rate is tending stable. - if(priv->FailTxRateCount >= 0x15 || - (!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6)) - { - priv->FailTxRateCount --; - } - - - OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel]; - CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel]; - - //[TRC Dell Lab] Mac0x9e increase 2 level in 36M~18M situation, Isaiah 2008-02-18 24:00 - if((priv->CurrentOperaRate < 96) &&(priv->CurrentOperaRate > 22)) - { - u1bCck = read_nic_byte(dev, CCK_TXAGC); - u1bOfdm = read_nic_byte(dev, OFDM_TXAGC); - - // case 1: Never enter High power - if(u1bCck == CckTxPwrIdx ) - { - if(u1bOfdm != (OfdmTxPwrIdx+2) ) - { - priv->bEnhanceTxPwr= true; - u1bOfdm = ((u1bOfdm+2) > 35) ? 35: (u1bOfdm+2); - write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); -// printk("Enhance OFDM_TXAGC : +++++ u1bOfdm= 0x%x\n", u1bOfdm); - } - } - // case 2: enter high power - else if(u1bCck < CckTxPwrIdx) - { - if(!priv->bEnhanceTxPwr) - { - priv->bEnhanceTxPwr= true; - u1bOfdm = ((u1bOfdm+2) > 35) ? 35: (u1bOfdm+2); - write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); - //RT_TRACE(COMP_RATE, DBG_TRACE, ("Enhance OFDM_TXAGC(2) : +++++ u1bOfdm= 0x%x\n", u1bOfdm)); - } - } - } - else if(priv->bEnhanceTxPwr) //54/48/11/5.5/2/1 - { - u1bCck = read_nic_byte(dev, CCK_TXAGC); - u1bOfdm = read_nic_byte(dev, OFDM_TXAGC); - - // case 1: Never enter High power - if(u1bCck == CckTxPwrIdx ) - { - priv->bEnhanceTxPwr= false; - write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx); - //printk("Recover OFDM_TXAGC : ===== u1bOfdm= 0x%x\n", OfdmTxPwrIdx); - } - // case 2: enter high power - else if(u1bCck < CckTxPwrIdx) - { - priv->bEnhanceTxPwr= false; - u1bOfdm = ((u1bOfdm-2) > 0) ? (u1bOfdm-2): 0; - write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); - //RT_TRACE(COMP_RATE, DBG_TRACE, ("Recover OFDM_TXAGC(2): ===== u1bOfdm= 0x%x\n", u1bOfdm)); - - } - } - - // - // We need update initial gain when we set tx rate "from OFDM to CCK" or - // "from CCK to OFDM". - // -SetInitialGain: - if(bUpdateInitialGain) - { - if(MgntIsCckRate(priv->CurrentOperaRate)) // CCK - { - if(priv->InitialGain > priv->RegBModeGainStage) - { - priv->InitialGainBackUp= priv->InitialGain; - - if(CurrSignalStrength < -85) // Low power, OFDM [0x17] = 26. - { - //SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. - priv->InitialGain = priv->RegBModeGainStage; - } - else if(priv->InitialGain > priv->RegBModeGainStage + 1) - { - priv->InitialGain -= 2; - } - else - { - priv->InitialGain --; - } - printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate); - UpdateInitialGain(dev); - } - } - else // OFDM - { - if(priv->InitialGain < 4) - { - priv->InitialGainBackUp= priv->InitialGain; - - priv->InitialGain ++; - printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate); - UpdateInitialGain(dev); - } - } - } - - //Record the related info - priv->LastRetryRate = CurrRetryRate; - priv->LastTxThroughput = TxThroughput; - priv->ieee80211->rate = priv->CurrentOperaRate * 5; -} - -#endif -#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) -void rtl8180_rate_adapter(struct work_struct * work) -{ - struct delayed_work *dwork = container_of(work,struct delayed_work,work); - struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,rate_adapter_wq); - struct net_device *dev = ieee->dev; -#else -void rtl8180_rate_adapter(struct net_device *dev) -{ - -#endif - //struct r8180_priv *priv = ieee80211_priv(dev); -// DMESG("---->rtl8180_rate_adapter"); - StaRateAdaptive87SE(dev); -// DMESG("<----rtl8180_rate_adapter"); -} -void timer_rate_adaptive(unsigned long data) -{ - struct r8180_priv* priv = ieee80211_priv((struct net_device *)data); - //DMESG("---->timer_rate_adaptive()\n"); - if(!priv->up) - { -// DMESG("<----timer_rate_adaptive():driver is not up!\n"); - return; - } - if((priv->ieee80211->iw_mode != IW_MODE_MASTER) - && (priv->ieee80211->state == IEEE80211_LINKED) && - (priv->ForcedDataRate == 0) ) - { -// DMESG("timer_rate_adaptive():schedule rate_adapter_wq\n"); -#ifdef CONFIG_RTL818X_S - queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->rate_adapter_wq); -// StaRateAdaptive87SE((struct net_device *)data); -#endif - } - priv->rateadapter_timer.expires = jiffies + MSECS(priv->RateAdaptivePeriod); - add_timer(&priv->rateadapter_timer); - //DMESG("<----timer_rate_adaptive()\n"); -} -//by amy 080312} -void -SwAntennaDiversityRxOk8185( - struct net_device *dev, - u8 SignalStrength - ) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - -// printk("+SwAntennaDiversityRxOk8185: RxSs: %d\n", SignalStrength); - - priv->AdRxOkCnt++; - - if( priv->AdRxSignalStrength != -1) - { - priv->AdRxSignalStrength = ((priv->AdRxSignalStrength*7) + (SignalStrength*3)) / 10; - } - else - { // Initialization case. - priv->AdRxSignalStrength = SignalStrength; - } -//{+by amy 080312 - if( priv->LastRxPktAntenna ) //Main antenna. - priv->AdMainAntennaRxOkCnt++; - else // Aux antenna. - priv->AdAuxAntennaRxOkCnt++; -//+by amy 080312 -// printk("-SwAntennaDiversityRxOk8185: AdRxOkCnt: %d AdRxSignalStrength: %d\n", priv->AdRxOkCnt, priv->AdRxSignalStrength); -} -// -// Description: -// Change Antenna Switch. -// -bool -SetAntenna8185( - struct net_device *dev, - u8 u1bAntennaIndex - ) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bAntennaSwitched = false; - -// printk("+SetAntenna8185(): Antenna is switching to: %d \n", u1bAntennaIndex); - - switch(u1bAntennaIndex) - { - case 0: - switch(priv->rf_chip) - { - case RF_ZEBRA2: - case RF_ZEBRA4: -#ifdef CONFIG_RTL8185B -#ifdef CONFIG_RTL818X_S - // Mac register, main antenna - write_nic_byte(dev, ANTSEL, 0x03); - //base band - write_phy_cck(dev,0x11, 0x9b); // Config CCK RX antenna. - write_phy_ofdm(dev, 0x0d, 0x5c); // Config OFDM RX antenna. - -#else - // Mac register, main antenna - write_nic_byte(dev, ANTSEL, 0x03); - //base band - write_phy_cck(dev, 0x10, 0x9b); // Config CCK RX antenna. - write_phy_ofdm(dev, 0x0d, 0x5c); // Config OFDM RX antenna. -#endif -#endif - - bAntennaSwitched = true; - break; - - default: - printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); - break; - } - break; - - case 1: - switch(priv->rf_chip) - { - case RF_ZEBRA2: - case RF_ZEBRA4: -#ifdef CONFIG_RTL8185B -#ifdef CONFIG_RTL818X_S - // Mac register, aux antenna - write_nic_byte(dev, ANTSEL, 0x00); - //base band - write_phy_cck(dev, 0x11, 0xbb); // Config CCK RX antenna. - write_phy_ofdm(dev, 0x0d, 0x54); // Config OFDM RX antenna. -#else - // Mac register, aux antenna - write_nic_byte(dev, ANTSEL, 0x00); - //base band - write_phy_cck(dev, 0x10, 0xbb); // Config CCK RX antenna. - write_phy_ofdm(dev, 0x0d, 0x54); // Config OFDM RX antenna. -#endif -#endif - - bAntennaSwitched = true; - break; - - default: - printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); - break; - } - break; - - default: - printk("SetAntenna8185: unkown u1bAntennaIndex(%d)\n", u1bAntennaIndex); - break; - } - - if(bAntennaSwitched) - { - priv->CurrAntennaIndex = u1bAntennaIndex; - } - -// printk("-SetAntenna8185(): return (%#X)\n", bAntennaSwitched); - - return bAntennaSwitched; -} -// -// Description: -// Toggle Antenna switch. -// -bool -SwitchAntenna( - struct net_device *dev - ) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - bool bResult; - - if(priv->CurrAntennaIndex == 0) - { -#if 0//lzm del 080826 -//by amy 080312 -#ifdef CONFIG_RTL818X_S - if(priv->bSwAntennaDiverity) - bResult = SetAntennaConfig87SE(dev, 1, true); - else -#endif -#endif - bResult = SetAntenna8185(dev, 1); -//by amy 080312 -// printk("SwitchAntenna(): switching to antenna 1 ......\n"); -// bResult = SetAntenna8185(dev, 1);//-by amy 080312 - } - else - { -#if 0//lzm del 080826 -//by amy 080312 -#ifdef CONFIG_RTL818X_S - if(priv->bSwAntennaDiverity) - bResult = SetAntennaConfig87SE(dev, 0, true); - else -#endif -#endif - bResult = SetAntenna8185(dev, 0); -//by amy 080312 -// printk("SwitchAntenna(): switching to antenna 0 ......\n"); -// bResult = SetAntenna8185(dev, 0);//-by amy 080312 - } - - return bResult; -} -// -// Description: -// Engine of SW Antenna Diversity mechanism. -// Since 8187 has no Tx part information, -// this implementation is only dependend on Rx part information. -// -// 2006.04.17, by rcnjko. -// -void -SwAntennaDiversity( - struct net_device *dev - ) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bSwCheckSS=false; -// printk("+SwAntennaDiversity(): CurrAntennaIndex: %d\n", priv->CurrAntennaIndex); -// printk("AdTickCount is %d\n",priv->AdTickCount); -//by amy 080312 - if(bSwCheckSS) - { - priv->AdTickCount++; - - printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n", - priv->AdTickCount, priv->AdCheckPeriod); - printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n", - priv->AdRxSignalStrength, priv->AdRxSsThreshold); - } -// priv->AdTickCount++;//-by amy 080312 - - // Case 1. No Link. - if(priv->ieee80211->state != IEEE80211_LINKED) - { - // printk("SwAntennaDiversity(): Case 1. No Link.\n"); - - priv->bAdSwitchedChecking = false; - // I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. - SwitchAntenna(dev); - } - // Case 2. Linked but no packet received. - else if(priv->AdRxOkCnt == 0) - { - // printk("SwAntennaDiversity(): Case 2. Linked but no packet received.\n"); - - priv->bAdSwitchedChecking = false; - SwitchAntenna(dev); - } - // Case 3. Evaluate last antenna switch action and undo it if necessary. - else if(priv->bAdSwitchedChecking == true) - { - // printk("SwAntennaDiversity(): Case 3. Evaluate last antenna switch action.\n"); - - priv->bAdSwitchedChecking = false; - - // Adjust Rx signal strength threashold. - priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2; - - priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? - priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold; - if(priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) - { // Rx signal strength is not improved after we swtiched antenna. => Swich back. -// printk("SwAntennaDiversity(): Rx Signal Strength is not improved, CurrRxSs: %d, LastRxSs: %d\n", -// priv->AdRxSignalStrength, priv->AdRxSsBeforeSwitched); -//by amy 080312 - // Increase Antenna Diversity checking period due to bad decision. - priv->AdCheckPeriod *= 2; -//by amy 080312 - // Increase Antenna Diversity checking period. - if(priv->AdCheckPeriod > priv->AdMaxCheckPeriod) - priv->AdCheckPeriod = priv->AdMaxCheckPeriod; - - // Wrong deceision => switch back. - SwitchAntenna(dev); - } - else - { // Rx Signal Strength is improved. -// printk("SwAntennaDiversity(): Rx Signal Strength is improved, CurrRxSs: %d, LastRxSs: %d\n", -// priv->AdRxSignalStrength, priv->AdRxSsBeforeSwitched); - - // Reset Antenna Diversity checking period to its min value. - priv->AdCheckPeriod = priv->AdMinCheckPeriod; - } - -// printk("SwAntennaDiversity(): AdRxSsThreshold: %d, AdCheckPeriod: %d\n", -// priv->AdRxSsThreshold, priv->AdCheckPeriod); - } - // Case 4. Evaluate if we shall switch antenna now. - // Cause Table Speed is very fast in TRC Dell Lab, we check it every time. - else// if(priv->AdTickCount >= priv->AdCheckPeriod)//-by amy 080312 - { -// printk("SwAntennaDiversity(): Case 4. Evaluate if we shall switch antenna now.\n"); - - priv->AdTickCount = 0; - - // - // We evaluate RxOk counts for each antenna first and than - // evaluate signal strength. - // The following operation can overcome the disability of CCA on both two antennas - // When signal strength was extremely low or high. - // 2008.01.30. - // - - // - // Evaluate RxOk count from each antenna if we shall switch default antenna now. - // Added by Roger, 2008.02.21. -//{by amy 080312 - if((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt) - && (priv->CurrAntennaIndex == 0)) - { // We set Main antenna as default but RxOk count was less than Aux ones. - - // printk("SwAntennaDiversity(): Main antenna RxOK is poor, AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n", - // priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt); - - // Switch to Aux antenna. - SwitchAntenna(dev); - priv->bHWAdSwitched = true; - } - else if((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt) - && (priv->CurrAntennaIndex == 1)) - { // We set Aux antenna as default but RxOk count was less than Main ones. - - // printk("SwAntennaDiversity(): Aux antenna RxOK is poor, AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n", - // priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt); - - // Switch to Main antenna. - SwitchAntenna(dev); - priv->bHWAdSwitched = true; - } - else - {// Default antenna is better. - - // printk("SwAntennaDiversity(): Default antenna is better., AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n", - // priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt); - - // Still need to check current signal strength. - priv->bHWAdSwitched = false; - } - // - // We evaluate Rx signal strength ONLY when default antenna - // didn't changed by HW evaluation. - // 2008.02.27. - // - // [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05 - // For example, Throughput of aux is better than main antenna(about 10M v.s 2M), - // but AdRxSignalStrength is less than main. - // Our guess is that main antenna have lower throughput and get many change - // to receive more CCK packets(ex.Beacon) which have stronger SignalStrength. - // - if( (!priv->bHWAdSwitched) && (bSwCheckSS)) - { -//by amy 080312} - // Evaluate Rx signal strength if we shall switch antenna now. - if(priv->AdRxSignalStrength < priv->AdRxSsThreshold) - { // Rx signal strength is weak => Switch Antenna. -// printk("SwAntennaDiversity(): Rx Signal Strength is weak, CurrRxSs: %d, RxSsThreshold: %d\n", -// priv->AdRxSignalStrength, priv->AdRxSsThreshold); - - priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength; - priv->bAdSwitchedChecking = true; - - SwitchAntenna(dev); - } - else - { // Rx signal strength is OK. -// printk("SwAntennaDiversity(): Rx Signal Strength is OK, CurrRxSs: %d, RxSsThreshold: %d\n", -// priv->AdRxSignalStrength, priv->AdRxSsThreshold); - - priv->bAdSwitchedChecking = false; - // Increase Rx signal strength threashold if necessary. - if( (priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && // Signal is much stronger than current threshold - priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) // Current threhold is not yet reach upper limit. - { - priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2; - priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? - priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold;//+by amy 080312 - } - - // Reduce Antenna Diversity checking period if possible. - if( priv->AdCheckPeriod > priv->AdMinCheckPeriod ) - { - priv->AdCheckPeriod /= 2; - } - } - } - } -//by amy 080312 - // Reset antenna diversity Rx related statistics. - priv->AdRxOkCnt = 0; - priv->AdMainAntennaRxOkCnt = 0; - priv->AdAuxAntennaRxOkCnt = 0; -//by amy 080312 - -// priv->AdRxOkCnt = 0;//-by amy 080312 - -// printk("-SwAntennaDiversity()\n"); -} - -// -// Description: -// Return TRUE if we shall perform Tx Power Tracking Mecahnism, FALSE otherwise. -// -bool -CheckTxPwrTracking( struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - if(!priv->bTxPowerTrack) - { - return false; - } - -//lzm reserved 080826 - //if(priv->bScanInProgress) - //{ - // return false; - //} - - //if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah - if(priv->bToUpdateTxPwr) - { - return false; - } - - return true; -} - - -// -// Description: -// Timer callback function of SW Antenna Diversity. -// -void -SwAntennaDiversityTimerCallback( - struct net_device *dev - ) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - RT_RF_POWER_STATE rtState; - - //printk("+SwAntennaDiversityTimerCallback()\n"); - - // - // We do NOT need to switch antenna while RF is off. - // 2007.05.09, added by Roger. - // - rtState = priv->eRFPowerState; - do{ - if (rtState == eRfOff) - { -// printk("SwAntennaDiversityTimer - RF is OFF.\n"); - break; - } - else if (rtState == eRfSleep) - { - // Don't access BB/RF under Disable PLL situation. - //RT_TRACE((COMP_RF|COMP_ANTENNA), DBG_LOUD, ("SwAntennaDiversityTimerCallback(): RF is Sleep => skip it\n")); - break; - } - SwAntennaDiversity(dev); - - }while(false); - - if(priv->up) - { - priv->SwAntennaDiversityTimer.expires = jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD); - add_timer(&priv->SwAntennaDiversityTimer); - } - - //printk("-SwAntennaDiversityTimerCallback()\n"); -} - +//#include "r8180.h" +#include "r8180_dm.h" +#include "r8180_hw.h" +#include "r8180_93cx6.h" +//{by amy 080312 + +// +// Description: +// Return TRUE if we shall perform High Power Mecahnism, FALSE otherwise. +// +//+by amy 080312 +#define RATE_ADAPTIVE_TIMER_PERIOD 300 + +bool CheckHighPower(struct net_device *dev) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee80211; + + if(!priv->bRegHighPowerMechanism) + { + return false; + } + + if(ieee->state == IEEE80211_LINKED_SCANNING) + { + return false; + } + + return true; +} + +// +// Description: +// Update Tx power level if necessary. +// See also DoRxHighPower() and SetTxPowerLevel8185() for reference. +// +// Note: +// The reason why we udpate Tx power level here instead of DoRxHighPower() +// is the number of IO to change Tx power is much more than chane TR switch +// and they are related to OFDM and MAC registers. +// So, we don't want to update it so frequently in per-Rx packet base. +// +void +DoTxHighPower( + struct net_device *dev + ) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + u16 HiPwrUpperTh = 0; + u16 HiPwrLowerTh = 0; + u8 RSSIHiPwrUpperTh; + u8 RSSIHiPwrLowerTh; + u8 u1bTmp; + char OfdmTxPwrIdx, CckTxPwrIdx; + + //printk("----> DoTxHighPower()\n"); + + HiPwrUpperTh = priv->RegHiPwrUpperTh; + HiPwrLowerTh = priv->RegHiPwrLowerTh; + + HiPwrUpperTh = HiPwrUpperTh * 10; + HiPwrLowerTh = HiPwrLowerTh * 10; + RSSIHiPwrUpperTh = priv->RegRSSIHiPwrUpperTh; + RSSIHiPwrLowerTh = priv->RegRSSIHiPwrLowerTh; + + //lzm add 080826 + OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel]; + CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel]; + + // printk("DoTxHighPower() - UndecoratedSmoothedSS:%d, CurCCKRSSI = %d , bCurCCKPkt= %d \n", priv->UndecoratedSmoothedSS, priv->CurCCKRSSI, priv->bCurCCKPkt ); + + if((priv->UndecoratedSmoothedSS > HiPwrUpperTh) || + (priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh))) + { + // Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah + + // printk("=====>DoTxHighPower() - High Power - UndecoratedSmoothedSS:%d, HiPwrUpperTh = %d \n", priv->UndecoratedSmoothedSS, HiPwrUpperTh ); + priv->bToUpdateTxPwr = true; + u1bTmp= read_nic_byte(dev, CCK_TXAGC); + + // If it never enter High Power. + if( CckTxPwrIdx == u1bTmp) + { + u1bTmp = (u1bTmp > 16) ? (u1bTmp -16): 0; // 8dbm + write_nic_byte(dev, CCK_TXAGC, u1bTmp); + + u1bTmp= read_nic_byte(dev, OFDM_TXAGC); + u1bTmp = (u1bTmp > 16) ? (u1bTmp -16): 0; // 8dbm + write_nic_byte(dev, OFDM_TXAGC, u1bTmp); + } + + } + else if((priv->UndecoratedSmoothedSS < HiPwrLowerTh) && + (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) + { + // printk("DoTxHighPower() - lower Power - UndecoratedSmoothedSS:%d, HiPwrUpperTh = %d \n", priv->UndecoratedSmoothedSS, HiPwrLowerTh ); + if(priv->bToUpdateTxPwr) + { + priv->bToUpdateTxPwr = false; + //SD3 required. + u1bTmp= read_nic_byte(dev, CCK_TXAGC); + if(u1bTmp < CckTxPwrIdx) + { + //u1bTmp = ((u1bTmp+16) > 35) ? 35: (u1bTmp+16); // 8dbm + //write_nic_byte(dev, CCK_TXAGC, u1bTmp); + write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx); + } + + u1bTmp= read_nic_byte(dev, OFDM_TXAGC); + if(u1bTmp < OfdmTxPwrIdx) + { + //u1bTmp = ((u1bTmp+16) > 35) ? 35: (u1bTmp+16); // 8dbm + //write_nic_byte(dev, OFDM_TXAGC, u1bTmp); + write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx); + } + } + } + + //printk("<---- DoTxHighPower()\n"); +} + + +// +// Description: +// Callback function of UpdateTxPowerWorkItem. +// Because of some event happend, e.g. CCX TPC, High Power Mechanism, +// We update Tx power of current channel again. +// +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) +void rtl8180_tx_pw_wq (struct work_struct *work) +{ +// struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq); +// struct ieee80211_device * ieee = (struct ieee80211_device*) +// container_of(work, struct ieee80211_device, watch_dog_wq); + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,tx_pw_wq); + struct net_device *dev = ieee->dev; +#else +void rtl8180_tx_pw_wq(struct net_device *dev) +{ + // struct r8180_priv *priv = ieee80211_priv(dev); +#endif + +// printk("----> UpdateTxPowerWorkItemCallback()\n"); + + DoTxHighPower(dev); + +// printk("<---- UpdateTxPowerWorkItemCallback()\n"); +} + + +// +// Description: +// Return TRUE if we shall perform DIG Mecahnism, FALSE otherwise. +// +bool +CheckDig( + struct net_device *dev + ) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + struct ieee80211_device *ieee = priv->ieee80211; + + if(!priv->bDigMechanism) + return false; + + if(ieee->state != IEEE80211_LINKED) + return false; + + //if(priv->CurrentOperaRate < 36) // Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. + if((priv->ieee80211->rate/5) < 36) // Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. + return false; + return true; +} +// +// Description: +// Implementation of DIG for Zebra and Zebra2. +// +void +DIG_Zebra( + struct net_device *dev + ) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + u16 CCKFalseAlarm, OFDMFalseAlarm; + u16 OfdmFA1, OfdmFA2; + int InitialGainStep = 7; // The number of initial gain stages. + int LowestGainStage = 4; // The capable lowest stage of performing dig workitem. + u32 AwakePeriodIn2Sec=0; + + //printk("---------> DIG_Zebra()\n"); + + CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff); + OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff); + OfdmFA1 = 0x15; + OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8; + +// printk("DIG**********CCK False Alarm: %#X \n",CCKFalseAlarm); +// printk("DIG**********OFDM False Alarm: %#X \n",OFDMFalseAlarm); + + // The number of initial gain steps is different, by Bruce, 2007-04-13. + if (priv->InitialGain == 0 ) //autoDIG + { // Advised from SD3 DZ + priv->InitialGain = 4; // In 87B, m74dBm means State 4 (m82dBm) + } + //if(pHalData->VersionID != VERSION_8187B_B) + { // Advised from SD3 DZ + OfdmFA1 = 0x20; + } + +#if 1 //lzm reserved 080826 + AwakePeriodIn2Sec = (2000-priv ->DozePeriodInPast2Sec); + //printk("&&& DozePeriod=%d AwakePeriod=%d\n", priv->DozePeriodInPast2Sec, AwakePeriodIn2Sec); + priv ->DozePeriodInPast2Sec=0; + + if(AwakePeriodIn2Sec) + { + //RT_TRACE(COMP_DIG, DBG_TRACE, ("DIG: AwakePeriodIn2Sec(%d) - FATh(0x%X , 0x%X) ->",AwakePeriodIn2Sec, OfdmFA1, OfdmFA2)); + // adjuest DIG threshold. + OfdmFA1 = (u16)((OfdmFA1*AwakePeriodIn2Sec) / 2000) ; + OfdmFA2 = (u16)((OfdmFA2*AwakePeriodIn2Sec) / 2000) ; + //RT_TRACE(COMP_DIG, DBG_TRACE, ("( 0x%X , 0x%X)\n", OfdmFA1, OfdmFA2)); + } + else + { + ;//RT_TRACE(COMP_DIG, DBG_WARNING, ("ERROR!! AwakePeriodIn2Sec should not be ZERO!!\n")); + } +#endif + + InitialGainStep = 8; + LowestGainStage = priv->RegBModeGainStage; // Lowest gain stage. + + if (OFDMFalseAlarm > OfdmFA1) + { + if (OFDMFalseAlarm > OfdmFA2) + { + priv->DIG_NumberFallbackVote++; + if (priv->DIG_NumberFallbackVote >1) + { + //serious OFDM False Alarm, need fallback + if (priv->InitialGain < InitialGainStep) + { + priv->InitialGainBackUp= priv->InitialGain; + + priv->InitialGain = (priv->InitialGain + 1); +// printk("DIG**********OFDM False Alarm: %#X, OfdmFA1: %#X, OfdmFA2: %#X\n", OFDMFalseAlarm, OfdmFA1, OfdmFA2); +// printk("DIG+++++++ fallback OFDM:%d \n", priv->InitialGain); + UpdateInitialGain(dev); + } + priv->DIG_NumberFallbackVote = 0; + priv->DIG_NumberUpgradeVote=0; + } + } + else + { + if (priv->DIG_NumberFallbackVote) + priv->DIG_NumberFallbackVote--; + } + priv->DIG_NumberUpgradeVote=0; + } + else + { + if (priv->DIG_NumberFallbackVote) + priv->DIG_NumberFallbackVote--; + priv->DIG_NumberUpgradeVote++; + + if (priv->DIG_NumberUpgradeVote>9) + { + if (priv->InitialGain > LowestGainStage) // In 87B, m78dBm means State 4 (m864dBm) + { + priv->InitialGainBackUp= priv->InitialGain; + + priv->InitialGain = (priv->InitialGain - 1); +// printk("DIG**********OFDM False Alarm: %#X, OfdmFA1: %#X, OfdmFA2: %#X\n", OFDMFalseAlarm, OfdmFA1, OfdmFA2); +// printk("DIG--------- Upgrade OFDM:%d \n", priv->InitialGain); + UpdateInitialGain(dev); + } + priv->DIG_NumberFallbackVote = 0; + priv->DIG_NumberUpgradeVote=0; + } + } + +// printk("DIG+++++++ OFDM:%d\n", priv->InitialGain); + //printk("<--------- DIG_Zebra()\n"); +} + +// +// Description: +// Dispatch DIG implementation according to RF. +// +void +DynamicInitGain( + struct net_device *dev + ) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + + switch(priv->rf_chip) + { + case RF_ZEBRA2: // [AnnieWorkaround] For Zebra2, 2005-08-01. + case RF_ZEBRA4: + DIG_Zebra( dev ); + break; + + default: + printk("DynamicInitGain(): unknown RFChipID(%d) !!!\n", priv->rf_chip); + break; + } +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) +void rtl8180_hw_dig_wq (struct work_struct *work) +{ +// struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq); +// struct ieee80211_device * ieee = (struct ieee80211_device*) +// container_of(work, struct ieee80211_device, watch_dog_wq); + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_dig_wq); + struct net_device *dev = ieee->dev; +#else +void rtl8180_hw_dig_wq(struct net_device *dev) +{ + +#endif + struct r8180_priv *priv = ieee80211_priv(dev); + + // Read CCK and OFDM False Alarm. + priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM); + + + // Adjust Initial Gain dynamically. + DynamicInitGain(dev); + +} + +int +IncludedInSupportedRates( + struct r8180_priv *priv, + u8 TxRate ) +{ + u8 rate_len; + u8 rate_ex_len; + u8 RateMask = 0x7F; + u8 idx; + unsigned short Found = 0; + u8 NaiveTxRate = TxRate&RateMask; + + rate_len = priv->ieee80211->current_network.rates_len; + rate_ex_len = priv->ieee80211->current_network.rates_ex_len; + for( idx=0; idx< rate_len; idx++ ) + { + if( (priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate ) + { + Found = 1; + goto found_rate; + } + } + for( idx=0; idx< rate_ex_len; idx++ ) + { + if( (priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate ) + { + Found = 1; + goto found_rate; + } + } + return Found; + found_rate: + return Found; +} + +// +// Description: +// Get the Tx rate one degree up form the input rate in the supported rates. +// Return the upgrade rate if it is successed, otherwise return the input rate. +// By Bruce, 2007-06-05. +// +u8 +GetUpgradeTxRate( + struct net_device *dev, + u8 rate + ) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + u8 UpRate; + + // Upgrade 1 degree. + switch(rate) + { + case 108: // Up to 54Mbps. + UpRate = 108; + break; + + case 96: // Up to 54Mbps. + UpRate = 108; + break; + + case 72: // Up to 48Mbps. + UpRate = 96; + break; + + case 48: // Up to 36Mbps. + UpRate = 72; + break; + + case 36: // Up to 24Mbps. + UpRate = 48; + break; + + case 22: // Up to 18Mbps. + UpRate = 36; + break; + + case 11: // Up to 11Mbps. + UpRate = 22; + break; + + case 4: // Up to 5.5Mbps. + UpRate = 11; + break; + + case 2: // Up to 2Mbps. + UpRate = 4; + break; + + default: + printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); + return rate; + } + // Check if the rate is valid. + if(IncludedInSupportedRates(priv, UpRate)) + { +// printk("GetUpgradeTxRate(): GetUpgrade Tx rate(%d) from %d !\n", UpRate, priv->CurrentOperaRate); + return UpRate; + } + else + { + //printk("GetUpgradeTxRate(): Tx rate (%d) is not in supported rates\n", UpRate); + return rate; + } + return rate; +} +// +// Description: +// Get the Tx rate one degree down form the input rate in the supported rates. +// Return the degrade rate if it is successed, otherwise return the input rate. +// By Bruce, 2007-06-05. +// +u8 +GetDegradeTxRate( + struct net_device *dev, + u8 rate + ) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + u8 DownRate; + + // Upgrade 1 degree. + switch(rate) + { + case 108: // Down to 48Mbps. + DownRate = 96; + break; + + case 96: // Down to 36Mbps. + DownRate = 72; + break; + + case 72: // Down to 24Mbps. + DownRate = 48; + break; + + case 48: // Down to 18Mbps. + DownRate = 36; + break; + + case 36: // Down to 11Mbps. + DownRate = 22; + break; + + case 22: // Down to 5.5Mbps. + DownRate = 11; + break; + + case 11: // Down to 2Mbps. + DownRate = 4; + break; + + case 4: // Down to 1Mbps. + DownRate = 2; + break; + + case 2: // Down to 1Mbps. + DownRate = 2; + break; + + default: + printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); + return rate; + } + // Check if the rate is valid. + if(IncludedInSupportedRates(priv, DownRate)) + { +// printk("GetDegradeTxRate(): GetDegrade Tx rate(%d) from %d!\n", DownRate, priv->CurrentOperaRate); + return DownRate; + } + else + { + //printk("GetDegradeTxRate(): Tx rate (%d) is not in supported rates\n", DownRate); + return rate; + } + return rate; +} +// +// Helper function to determine if specified data rate is +// CCK rate. +// 2005.01.25, by rcnjko. +// +bool +MgntIsCckRate( + u16 rate + ) +{ + bool bReturn = false; + + if((rate <= 22) && (rate != 12) && (rate != 18)) + { + bReturn = true; + } + + return bReturn; +} +#ifdef CONFIG_RTL818X_S +// +// Description: +// Tx Power tracking mechanism routine on 87SE. +// Created by Roger, 2007.12.11. +// +void +TxPwrTracking87SE( + struct net_device *dev +) +{ + struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); + u8 tmpu1Byte, CurrentThermal, Idx; + char CckTxPwrIdx, OfdmTxPwrIdx; + //u32 u4bRfReg; + + tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL); + CurrentThermal = (tmpu1Byte & 0xf0)>>4; //[ 7:4]: thermal meter indication. + CurrentThermal = (CurrentThermal>0x0c)? 0x0c:CurrentThermal;//lzm add 080826 + + //printk("TxPwrTracking87SE(): CurrentThermal(%d)\n", CurrentThermal); + + if( CurrentThermal != priv->ThermalMeter) + { +// printk("TxPwrTracking87SE(): Thermal meter changed!!!\n"); + + // Update Tx Power level on each channel. + for(Idx = 1; Idx<15; Idx++) + { + CckTxPwrIdx = priv->chtxpwr[Idx]; + OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx]; + + if( CurrentThermal > priv->ThermalMeter ) + { // higher thermal meter. + CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter)*2; + OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter)*2; + + if(CckTxPwrIdx >35) + CckTxPwrIdx = 35; // Force TxPower to maximal index. + if(OfdmTxPwrIdx >35) + OfdmTxPwrIdx = 35; + } + else + { // lower thermal meter. + CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal)*2; + OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal)*2; + + if(CckTxPwrIdx <0) + CckTxPwrIdx = 0; + if(OfdmTxPwrIdx <0) + OfdmTxPwrIdx = 0; + } + + // Update TxPower level on CCK and OFDM resp. + priv->chtxpwr[Idx] = CckTxPwrIdx; + priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx; + } + + // Update TxPower level immediately. + rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel); + } + priv->ThermalMeter = CurrentThermal; +} +void +StaRateAdaptive87SE( + struct net_device *dev + ) +{ + struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); + unsigned long CurrTxokCnt; + u16 CurrRetryCnt; + u16 CurrRetryRate; + //u16 i,idx; + unsigned long CurrRxokCnt; + bool bTryUp = false; + bool bTryDown = false; + u8 TryUpTh = 1; + u8 TryDownTh = 2; + u32 TxThroughput; + long CurrSignalStrength; + bool bUpdateInitialGain = false; + u8 u1bOfdm=0, u1bCck = 0; + char OfdmTxPwrIdx, CckTxPwrIdx; + + priv->RateAdaptivePeriod= RATE_ADAPTIVE_TIMER_PERIOD; + + + CurrRetryCnt = priv->CurrRetryCnt; + CurrTxokCnt = priv->NumTxOkTotal - priv->LastTxokCnt; + CurrRxokCnt = priv->ieee80211->NumRxOkTotal - priv->LastRxokCnt; + CurrSignalStrength = priv->Stats_RecvSignalPower; + TxThroughput = (u32)(priv->NumTxOkBytesTotal - priv->LastTxOKBytes); + priv->LastTxOKBytes = priv->NumTxOkBytesTotal; + priv->CurrentOperaRate = priv->ieee80211->rate/5; + //printk("priv->CurrentOperaRate is %d\n",priv->CurrentOperaRate); + //2 Compute retry ratio. + if (CurrTxokCnt>0) + { + CurrRetryRate = (u16)(CurrRetryCnt*100/CurrTxokCnt); + } + else + { // It may be serious retry. To distinguish serious retry or no packets modified by Bruce + CurrRetryRate = (u16)(CurrRetryCnt*100/1); + } + + + // + // Added by Roger, 2007.01.02. + // For debug information. + // + //printk("\n(1) pHalData->LastRetryRate: %d \n",priv->LastRetryRate); + //printk("(2) RetryCnt = %d \n", CurrRetryCnt); + //printk("(3) TxokCnt = %d \n", CurrTxokCnt); + //printk("(4) CurrRetryRate = %d \n", CurrRetryRate); + //printk("(5) CurrSignalStrength = %d \n",CurrSignalStrength); + //printk("(6) TxThroughput is %d\n",TxThroughput); + //printk("priv->NumTxOkBytesTotal is %d\n",priv->NumTxOkBytesTotal); + + priv->LastRetryCnt = priv->CurrRetryCnt; + priv->LastTxokCnt = priv->NumTxOkTotal; + priv->LastRxokCnt = priv->ieee80211->NumRxOkTotal; + priv->CurrRetryCnt = 0; + + //2No Tx packets, return to init_rate or not? + if (CurrRetryRate==0 && CurrTxokCnt == 0) + { + // + //After 9 (30*300ms) seconds in this condition, we try to raise rate. + // + priv->TryupingCountNoData++; + +// printk("No Tx packets, TryupingCountNoData(%d)\n", priv->TryupingCountNoData); + //[TRC Dell Lab] Extend raised period from 4.5sec to 9sec, Isaiah 2008-02-15 18:00 + if (priv->TryupingCountNoData>30) + { + priv->TryupingCountNoData = 0; + priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); + // Reset Fail Record + priv->LastFailTxRate = 0; + priv->LastFailTxRateSS = -200; + priv->FailTxRateCount = 0; + } + goto SetInitialGain; + } + else + { + priv->TryupingCountNoData=0; //Reset trying up times. + } + + + // + // For Netgear case, I comment out the following signal strength estimation, + // which can results in lower rate to transmit when sample is NOT enough (e.g. PING request). + // 2007.04.09, by Roger. + // + + // + // Restructure rate adaptive as the following main stages: + // (1) Add retry threshold in 54M upgrading condition with signal strength. + // (2) Add the mechanism to degrade to CCK rate according to signal strength + // and retry rate. + // (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated + // situation, Initial Gain Update is upon on DIG mechanism except CCK rate. + // (4) Add the mehanism of trying to upgrade tx rate. + // (5) Record the information of upping tx rate to avoid trying upping tx rate constantly. + // By Bruce, 2007-06-05. + // + // + + // 11Mbps or 36Mbps + // Check more times in these rate(key rates). + // + if(priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72) + { + TryUpTh += 9; + } + // + // Let these rates down more difficult. + // + if(MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36) + { + TryDownTh += 1; + } + + //1 Adjust Rate. + if (priv->bTryuping == true) + { + //2 For Test Upgrading mechanism + // Note: + // Sometimes the throughput is upon on the capability bwtween the AP and NIC, + // thus the low data rate does not improve the performance. + // We randomly upgrade the data rate and check if the retry rate is improved. + + // Upgrading rate did not improve the retry rate, fallback to the original rate. + if ( (CurrRetryRate > 25) && TxThroughput < priv->LastTxThroughput) + { + //Not necessary raising rate, fall back rate. + bTryDown = true; + //printk("case1-1: Not necessary raising rate, fall back rate....\n"); + //printk("case1-1: pMgntInfo->CurrentOperaRate =%d, TxThroughput = %d, LastThroughput = %d\n", + // priv->CurrentOperaRate, TxThroughput, priv->LastTxThroughput); + } + else + { + priv->bTryuping = false; + } + } + else if (CurrSignalStrength > -47 && (CurrRetryRate < 50)) + { + //2For High Power + // + // Added by Roger, 2007.04.09. + // Return to highest data rate, if signal strength is good enough. + // SignalStrength threshold(-50dbm) is for RTL8186. + // Revise SignalStrength threshold to -51dbm. + // + // Also need to check retry rate for safety, by Bruce, 2007-06-05. + if(priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate ) + { + bTryUp = true; + // Upgrade Tx Rate directly. + priv->TryupingCount += TryUpTh; + } +// printk("case2: StaRateAdaptive87SE: Power(%d) is high enough!!. \n", CurrSignalStrength); + + } + else if(CurrTxokCnt > 9 && CurrTxokCnt< 100 && CurrRetryRate >= 600) + { + //2 For Serious Retry + // + // Traffic is not busy but our Tx retry is serious. + // + bTryDown = true; + // Let Rate Mechanism to degrade tx rate directly. + priv->TryDownCountLowData += TryDownTh; +// printk("case3: RA: Tx Retry is serious. Degrade Tx Rate to %d directly...\n", priv->CurrentOperaRate); + } + else if ( priv->CurrentOperaRate == 108 ) + { + //2For 54Mbps + // Air Link + if ( (CurrRetryRate>26)&&(priv->LastRetryRate>25)) +// if ( (CurrRetryRate>40)&&(priv->LastRetryRate>39)) + { + //Down to rate 48Mbps. + bTryDown = true; + } + // Cable Link + else if ( (CurrRetryRate>17)&&(priv->LastRetryRate>16) && (CurrSignalStrength > -72)) +// else if ( (CurrRetryRate>17)&&(priv->LastRetryRate>16) && (CurrSignalStrength > -72)) + { + //Down to rate 48Mbps. + bTryDown = true; + } + + if(bTryDown && (CurrSignalStrength < -75)) //cable link + { + priv->TryDownCountLowData += TryDownTh; + } + //printk("case4---54M \n"); + + } + else if ( priv->CurrentOperaRate == 96 ) + { + //2For 48Mbps + //Air Link + if ( ((CurrRetryRate>48) && (priv->LastRetryRate>47))) +// if ( ((CurrRetryRate>65) && (priv->LastRetryRate>64))) + + { + //Down to rate 36Mbps. + bTryDown = true; + } + //Cable Link + else if ( ((CurrRetryRate>21) && (priv->LastRetryRate>20)) && (CurrSignalStrength > -74)) + { + //Down to rate 36Mbps. + bTryDown = true; + } + else if((CurrRetryRate> (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 )) +// else if((CurrRetryRate> (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 )) + { + bTryDown = true; + priv->TryDownCountLowData += TryDownTh; + } + else if ( (CurrRetryRate<8) && (priv->LastRetryRate<8) ) //TO DO: need to consider (RSSI) +// else if ( (CurrRetryRate<28) && (priv->LastRetryRate<8) ) + { + bTryUp = true; + } + + if(bTryDown && (CurrSignalStrength < -75)) + { + priv->TryDownCountLowData += TryDownTh; + } + //printk("case5---48M \n"); + } + else if ( priv->CurrentOperaRate == 72 ) + { + //2For 36Mbps + if ( (CurrRetryRate>43) && (priv->LastRetryRate>41)) +// if ( (CurrRetryRate>60) && (priv->LastRetryRate>59)) + { + //Down to rate 24Mbps. + bTryDown = true; + } + else if((CurrRetryRate> (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 )) +// else if((CurrRetryRate> (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 )) + { + bTryDown = true; + priv->TryDownCountLowData += TryDownTh; + } + else if ( (CurrRetryRate<15) && (priv->LastRetryRate<16)) //TO DO: need to consider (RSSI) +// else if ( (CurrRetryRate<35) && (priv->LastRetryRate<36)) + { + bTryUp = true; + } + + if(bTryDown && (CurrSignalStrength < -80)) + { + priv->TryDownCountLowData += TryDownTh; + } + //printk("case6---36M \n"); + } + else if ( priv->CurrentOperaRate == 48 ) + { + //2For 24Mbps + // Air Link + if ( ((CurrRetryRate>63) && (priv->LastRetryRate>62))) +// if ( ((CurrRetryRate>83) && (priv->LastRetryRate>82))) + { + //Down to rate 18Mbps. + bTryDown = true; + } + //Cable Link + else if ( ((CurrRetryRate>33) && (priv->LastRetryRate>32)) && (CurrSignalStrength > -82) ) +// else if ( ((CurrRetryRate>50) && (priv->LastRetryRate>49)) && (CurrSignalStrength > -82) ) + { + //Down to rate 18Mbps. + bTryDown = true; + } + else if((CurrRetryRate> (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 )) +// else if((CurrRetryRate> (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 )) + + { + bTryDown = true; + priv->TryDownCountLowData += TryDownTh; + } + else if ( (CurrRetryRate<20) && (priv->LastRetryRate<21)) //TO DO: need to consider (RSSI) +// else if ( (CurrRetryRate<40) && (priv->LastRetryRate<41)) + { + bTryUp = true; + } + + if(bTryDown && (CurrSignalStrength < -82)) + { + priv->TryDownCountLowData += TryDownTh; + } + //printk("case7---24M \n"); + } + else if ( priv->CurrentOperaRate == 36 ) + { + //2For 18Mbps + // original (109, 109) + //[TRC Dell Lab] (90, 91), Isaiah 2008-02-18 23:24 + // (85, 86), Isaiah 2008-02-18 24:00 + if ( ((CurrRetryRate>85) && (priv->LastRetryRate>86))) +// if ( ((CurrRetryRate>115) && (priv->LastRetryRate>116))) + { + //Down to rate 11Mbps. + bTryDown = true; + } + //[TRC Dell Lab] Isaiah 2008-02-18 23:24 + else if((CurrRetryRate> (priv->LastRetryRate + 50 )) && (priv->FailTxRateCount >2 )) +// else if((CurrRetryRate> (priv->LastRetryRate + 70 )) && (priv->FailTxRateCount >2 )) + { + bTryDown = true; + priv->TryDownCountLowData += TryDownTh; + } + else if ( (CurrRetryRate<22) && (priv->LastRetryRate<23)) //TO DO: need to consider (RSSI) +// else if ( (CurrRetryRate<42) && (priv->LastRetryRate<43)) + { + bTryUp = true; + } + //printk("case8---18M \n"); + } + else if ( priv->CurrentOperaRate == 22 ) + { + //2For 11Mbps + if (CurrRetryRate>95) +// if (CurrRetryRate>155) + { + bTryDown = true; + } + else if ( (CurrRetryRate<29) && (priv->LastRetryRate <30) )//TO DO: need to consider (RSSI) +// else if ( (CurrRetryRate<49) && (priv->LastRetryRate <50) ) + { + bTryUp = true; + } + //printk("case9---11M \n"); + } + else if ( priv->CurrentOperaRate == 11 ) + { + //2For 5.5Mbps + if (CurrRetryRate>149) +// if (CurrRetryRate>189) + { + bTryDown = true; + } + else if ( (CurrRetryRate<60) && (priv->LastRetryRate < 65)) +// else if ( (CurrRetryRate<80) && (priv->LastRetryRate < 85)) + + { + bTryUp = true; + } + //printk("case10---5.5M \n"); + } + else if ( priv->CurrentOperaRate == 4 ) + { + //2For 2 Mbps + if((CurrRetryRate>99) && (priv->LastRetryRate>99)) +// if((CurrRetryRate>199) && (priv->LastRetryRate>199)) + { + bTryDown = true; + } + else if ( (CurrRetryRate < 65) && (priv->LastRetryRate < 70)) +// else if ( (CurrRetryRate < 85) && (priv->LastRetryRate < 90)) + { + bTryUp = true; + } + //printk("case11---2M \n"); + } + else if ( priv->CurrentOperaRate == 2 ) + { + //2For 1 Mbps + if( (CurrRetryRate<70) && (priv->LastRetryRate<75)) +// if( (CurrRetryRate<90) && (priv->LastRetryRate<95)) + { + bTryUp = true; + } + //printk("case12---1M \n"); + } + + if(bTryUp && bTryDown) + printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n"); + + //1 Test Upgrading Tx Rate + // Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC. + // To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate. + if(!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0) + && priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate && priv->FailTxRateCount < 2) + { + if(jiffies% (CurrRetryRate + 101) == 0) + { + bTryUp = true; + priv->bTryuping = true; + //printk("StaRateAdaptive87SE(): Randomly try upgrading...\n"); + } + } + + //1 Rate Mechanism + if(bTryUp) + { + priv->TryupingCount++; + priv->TryDownCountLowData = 0; + + { +// printk("UP: pHalData->TryupingCount = %d\n", priv->TryupingCount); +// printk("UP: TryUpTh(%d)+ (FailTxRateCount(%d))^2 =%d\n", +// TryUpTh, priv->FailTxRateCount, (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount) ); +// printk("UP: pHalData->bTryuping=%d\n", priv->bTryuping); + + } + + // + // Check more times if we need to upgrade indeed. + // Because the largest value of pHalData->TryupingCount is 0xFFFF and + // the largest value of pHalData->FailTxRateCount is 0x14, + // this condition will be satisfied at most every 2 min. + // + + if((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) || + (CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping) + { + priv->TryupingCount = 0; + // + // When transfering from CCK to OFDM, DIG is an important issue. + // + if(priv->CurrentOperaRate == 22) + bUpdateInitialGain = true; + + // The difference in throughput between 48Mbps and 36Mbps is 8M. + // So, we must be carefully in this rate scale. Isaiah 2008-02-15. + // + if( ((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) && + (priv->FailTxRateCount > 2) ) + priv->RateAdaptivePeriod= (RATE_ADAPTIVE_TIMER_PERIOD/2); + + // (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold. + // (2)If the signal strength is increased, it may be able to upgrade. + + priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); +// printk("StaRateAdaptive87SE(): Upgrade Tx Rate to %d\n", priv->CurrentOperaRate); + + //[TRC Dell Lab] Bypass 12/9/6, Isaiah 2008-02-18 20:00 + if(priv->CurrentOperaRate ==36) + { + priv->bUpdateARFR=true; + write_nic_word(dev, ARFR, 0x0F8F); //bypass 12/9/6 +// printk("UP: ARFR=0xF8F\n"); + } + else if(priv->bUpdateARFR) + { + priv->bUpdateARFR=false; + write_nic_word(dev, ARFR, 0x0FFF); //set 1M ~ 54Mbps. +// printk("UP: ARFR=0xFFF\n"); + } + + // Update Fail Tx rate and count. + if(priv->LastFailTxRate != priv->CurrentOperaRate) + { + priv->LastFailTxRate = priv->CurrentOperaRate; + priv->FailTxRateCount = 0; + priv->LastFailTxRateSS = -200; // Set lowest power. + } + } + } + else + { + if(priv->TryupingCount > 0) + priv->TryupingCount --; + } + + if(bTryDown) + { + priv->TryDownCountLowData++; + priv->TryupingCount = 0; + { +// printk("DN: pHalData->TryDownCountLowData = %d\n",priv->TryDownCountLowData); +// printk("DN: TryDownTh =%d\n", TryDownTh); +// printk("DN: pHalData->bTryuping=%d\n", priv->bTryuping); + } + + //Check if Tx rate can be degraded or Test trying upgrading should fallback. + if(priv->TryDownCountLowData > TryDownTh || priv->bTryuping) + { + priv->TryDownCountLowData = 0; + priv->bTryuping = false; + // Update fail information. + if(priv->LastFailTxRate == priv->CurrentOperaRate) + { + priv->FailTxRateCount ++; + // Record the Tx fail rate signal strength. + if(CurrSignalStrength > priv->LastFailTxRateSS) + { + priv->LastFailTxRateSS = CurrSignalStrength; + } + } + else + { + priv->LastFailTxRate = priv->CurrentOperaRate; + priv->FailTxRateCount = 1; + priv->LastFailTxRateSS = CurrSignalStrength; + } + priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate); + + // Reduce chariot training time at weak signal strength situation. SD3 ED demand. + //[TRC Dell Lab] Revise Signal Threshold from -75 to -80 , Isaiah 2008-02-18 20:00 + if( (CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72 )) + { + priv->CurrentOperaRate = 72; +// printk("DN: weak signal strength (%d), degrade to 36Mbps\n", CurrSignalStrength); + } + + //[TRC Dell Lab] Bypass 12/9/6, Isaiah 2008-02-18 20:00 + if(priv->CurrentOperaRate ==36) + { + priv->bUpdateARFR=true; + write_nic_word(dev, ARFR, 0x0F8F); //bypass 12/9/6 +// printk("DN: ARFR=0xF8F\n"); + } + else if(priv->bUpdateARFR) + { + priv->bUpdateARFR=false; + write_nic_word(dev, ARFR, 0x0FFF); //set 1M ~ 54Mbps. +// printk("DN: ARFR=0xFFF\n"); + } + + // + // When it is CCK rate, it may need to update initial gain to receive lower power packets. + // + if(MgntIsCckRate(priv->CurrentOperaRate)) + { + bUpdateInitialGain = true; + } +// printk("StaRateAdaptive87SE(): Degrade Tx Rate to %d\n", priv->CurrentOperaRate); + } + } + else + { + if(priv->TryDownCountLowData > 0) + priv->TryDownCountLowData --; + } + + // Keep the Tx fail rate count to equal to 0x15 at most. + // Reduce the fail count at least to 10 sec if tx rate is tending stable. + if(priv->FailTxRateCount >= 0x15 || + (!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6)) + { + priv->FailTxRateCount --; + } + + + OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel]; + CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel]; + + //[TRC Dell Lab] Mac0x9e increase 2 level in 36M~18M situation, Isaiah 2008-02-18 24:00 + if((priv->CurrentOperaRate < 96) &&(priv->CurrentOperaRate > 22)) + { + u1bCck = read_nic_byte(dev, CCK_TXAGC); + u1bOfdm = read_nic_byte(dev, OFDM_TXAGC); + + // case 1: Never enter High power + if(u1bCck == CckTxPwrIdx ) + { + if(u1bOfdm != (OfdmTxPwrIdx+2) ) + { + priv->bEnhanceTxPwr= true; + u1bOfdm = ((u1bOfdm+2) > 35) ? 35: (u1bOfdm+2); + write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); +// printk("Enhance OFDM_TXAGC : +++++ u1bOfdm= 0x%x\n", u1bOfdm); + } + } + // case 2: enter high power + else if(u1bCck < CckTxPwrIdx) + { + if(!priv->bEnhanceTxPwr) + { + priv->bEnhanceTxPwr= true; + u1bOfdm = ((u1bOfdm+2) > 35) ? 35: (u1bOfdm+2); + write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); + //RT_TRACE(COMP_RATE, DBG_TRACE, ("Enhance OFDM_TXAGC(2) : +++++ u1bOfdm= 0x%x\n", u1bOfdm)); + } + } + } + else if(priv->bEnhanceTxPwr) //54/48/11/5.5/2/1 + { + u1bCck = read_nic_byte(dev, CCK_TXAGC); + u1bOfdm = read_nic_byte(dev, OFDM_TXAGC); + + // case 1: Never enter High power + if(u1bCck == CckTxPwrIdx ) + { + priv->bEnhanceTxPwr= false; + write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx); + //printk("Recover OFDM_TXAGC : ===== u1bOfdm= 0x%x\n", OfdmTxPwrIdx); + } + // case 2: enter high power + else if(u1bCck < CckTxPwrIdx) + { + priv->bEnhanceTxPwr= false; + u1bOfdm = ((u1bOfdm-2) > 0) ? (u1bOfdm-2): 0; + write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); + //RT_TRACE(COMP_RATE, DBG_TRACE, ("Recover OFDM_TXAGC(2): ===== u1bOfdm= 0x%x\n", u1bOfdm)); + + } + } + + // + // We need update initial gain when we set tx rate "from OFDM to CCK" or + // "from CCK to OFDM". + // +SetInitialGain: + if(bUpdateInitialGain) + { + if(MgntIsCckRate(priv->CurrentOperaRate)) // CCK + { + if(priv->InitialGain > priv->RegBModeGainStage) + { + priv->InitialGainBackUp= priv->InitialGain; + + if(CurrSignalStrength < -85) // Low power, OFDM [0x17] = 26. + { + //SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. + priv->InitialGain = priv->RegBModeGainStage; + } + else if(priv->InitialGain > priv->RegBModeGainStage + 1) + { + priv->InitialGain -= 2; + } + else + { + priv->InitialGain --; + } + printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate); + UpdateInitialGain(dev); + } + } + else // OFDM + { + if(priv->InitialGain < 4) + { + priv->InitialGainBackUp= priv->InitialGain; + + priv->InitialGain ++; + printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate); + UpdateInitialGain(dev); + } + } + } + + //Record the related info + priv->LastRetryRate = CurrRetryRate; + priv->LastTxThroughput = TxThroughput; + priv->ieee80211->rate = priv->CurrentOperaRate * 5; +} + +#endif +#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) +void rtl8180_rate_adapter(struct work_struct * work) +{ + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,rate_adapter_wq); + struct net_device *dev = ieee->dev; +#else +void rtl8180_rate_adapter(struct net_device *dev) +{ + +#endif + //struct r8180_priv *priv = ieee80211_priv(dev); +// DMESG("---->rtl8180_rate_adapter"); + StaRateAdaptive87SE(dev); +// DMESG("<----rtl8180_rate_adapter"); +} +void timer_rate_adaptive(unsigned long data) +{ + struct r8180_priv* priv = ieee80211_priv((struct net_device *)data); + //DMESG("---->timer_rate_adaptive()\n"); + if(!priv->up) + { +// DMESG("<----timer_rate_adaptive():driver is not up!\n"); + return; + } + if((priv->ieee80211->iw_mode != IW_MODE_MASTER) + && (priv->ieee80211->state == IEEE80211_LINKED) && + (priv->ForcedDataRate == 0) ) + { +// DMESG("timer_rate_adaptive():schedule rate_adapter_wq\n"); +#ifdef CONFIG_RTL818X_S + queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->rate_adapter_wq); +// StaRateAdaptive87SE((struct net_device *)data); +#endif + } + priv->rateadapter_timer.expires = jiffies + MSECS(priv->RateAdaptivePeriod); + add_timer(&priv->rateadapter_timer); + //DMESG("<----timer_rate_adaptive()\n"); +} +//by amy 080312} +void +SwAntennaDiversityRxOk8185( + struct net_device *dev, + u8 SignalStrength + ) +{ + struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); + +// printk("+SwAntennaDiversityRxOk8185: RxSs: %d\n", SignalStrength); + + priv->AdRxOkCnt++; + + if( priv->AdRxSignalStrength != -1) + { + priv->AdRxSignalStrength = ((priv->AdRxSignalStrength*7) + (SignalStrength*3)) / 10; + } + else + { // Initialization case. + priv->AdRxSignalStrength = SignalStrength; + } +//{+by amy 080312 + if( priv->LastRxPktAntenna ) //Main antenna. + priv->AdMainAntennaRxOkCnt++; + else // Aux antenna. + priv->AdAuxAntennaRxOkCnt++; +//+by amy 080312 +// printk("-SwAntennaDiversityRxOk8185: AdRxOkCnt: %d AdRxSignalStrength: %d\n", priv->AdRxOkCnt, priv->AdRxSignalStrength); +} +// +// Description: +// Change Antenna Switch. +// +bool +SetAntenna8185( + struct net_device *dev, + u8 u1bAntennaIndex + ) +{ + struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); + bool bAntennaSwitched = false; + +// printk("+SetAntenna8185(): Antenna is switching to: %d \n", u1bAntennaIndex); + + switch(u1bAntennaIndex) + { + case 0: + switch(priv->rf_chip) + { + case RF_ZEBRA2: + case RF_ZEBRA4: +#ifdef CONFIG_RTL8185B +#ifdef CONFIG_RTL818X_S + // Mac register, main antenna + write_nic_byte(dev, ANTSEL, 0x03); + //base band + write_phy_cck(dev,0x11, 0x9b); // Config CCK RX antenna. + write_phy_ofdm(dev, 0x0d, 0x5c); // Config OFDM RX antenna. + +#else + // Mac register, main antenna + write_nic_byte(dev, ANTSEL, 0x03); + //base band + write_phy_cck(dev, 0x10, 0x9b); // Config CCK RX antenna. + write_phy_ofdm(dev, 0x0d, 0x5c); // Config OFDM RX antenna. +#endif +#endif + + bAntennaSwitched = true; + break; + + default: + printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); + break; + } + break; + + case 1: + switch(priv->rf_chip) + { + case RF_ZEBRA2: + case RF_ZEBRA4: +#ifdef CONFIG_RTL8185B +#ifdef CONFIG_RTL818X_S + // Mac register, aux antenna + write_nic_byte(dev, ANTSEL, 0x00); + //base band + write_phy_cck(dev, 0x11, 0xbb); // Config CCK RX antenna. + write_phy_ofdm(dev, 0x0d, 0x54); // Config OFDM RX antenna. +#else + // Mac register, aux antenna + write_nic_byte(dev, ANTSEL, 0x00); + //base band + write_phy_cck(dev, 0x10, 0xbb); // Config CCK RX antenna. + write_phy_ofdm(dev, 0x0d, 0x54); // Config OFDM RX antenna. +#endif +#endif + + bAntennaSwitched = true; + break; + + default: + printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); + break; + } + break; + + default: + printk("SetAntenna8185: unkown u1bAntennaIndex(%d)\n", u1bAntennaIndex); + break; + } + + if(bAntennaSwitched) + { + priv->CurrAntennaIndex = u1bAntennaIndex; + } + +// printk("-SetAntenna8185(): return (%#X)\n", bAntennaSwitched); + + return bAntennaSwitched; +} +// +// Description: +// Toggle Antenna switch. +// +bool +SwitchAntenna( + struct net_device *dev + ) +{ + struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); + + bool bResult; + + if(priv->CurrAntennaIndex == 0) + { +#if 0//lzm del 080826 +//by amy 080312 +#ifdef CONFIG_RTL818X_S + if(priv->bSwAntennaDiverity) + bResult = SetAntennaConfig87SE(dev, 1, true); + else +#endif +#endif + bResult = SetAntenna8185(dev, 1); +//by amy 080312 +// printk("SwitchAntenna(): switching to antenna 1 ......\n"); +// bResult = SetAntenna8185(dev, 1);//-by amy 080312 + } + else + { +#if 0//lzm del 080826 +//by amy 080312 +#ifdef CONFIG_RTL818X_S + if(priv->bSwAntennaDiverity) + bResult = SetAntennaConfig87SE(dev, 0, true); + else +#endif +#endif + bResult = SetAntenna8185(dev, 0); +//by amy 080312 +// printk("SwitchAntenna(): switching to antenna 0 ......\n"); +// bResult = SetAntenna8185(dev, 0);//-by amy 080312 + } + + return bResult; +} +// +// Description: +// Engine of SW Antenna Diversity mechanism. +// Since 8187 has no Tx part information, +// this implementation is only dependend on Rx part information. +// +// 2006.04.17, by rcnjko. +// +void +SwAntennaDiversity( + struct net_device *dev + ) +{ + struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); + bool bSwCheckSS=false; +// printk("+SwAntennaDiversity(): CurrAntennaIndex: %d\n", priv->CurrAntennaIndex); +// printk("AdTickCount is %d\n",priv->AdTickCount); +//by amy 080312 + if(bSwCheckSS) + { + priv->AdTickCount++; + + printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n", + priv->AdTickCount, priv->AdCheckPeriod); + printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n", + priv->AdRxSignalStrength, priv->AdRxSsThreshold); + } +// priv->AdTickCount++;//-by amy 080312 + + // Case 1. No Link. + if(priv->ieee80211->state != IEEE80211_LINKED) + { + // printk("SwAntennaDiversity(): Case 1. No Link.\n"); + + priv->bAdSwitchedChecking = false; + // I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. + SwitchAntenna(dev); + } + // Case 2. Linked but no packet received. + else if(priv->AdRxOkCnt == 0) + { + // printk("SwAntennaDiversity(): Case 2. Linked but no packet received.\n"); + + priv->bAdSwitchedChecking = false; + SwitchAntenna(dev); + } + // Case 3. Evaluate last antenna switch action and undo it if necessary. + else if(priv->bAdSwitchedChecking == true) + { + // printk("SwAntennaDiversity(): Case 3. Evaluate last antenna switch action.\n"); + + priv->bAdSwitchedChecking = false; + + // Adjust Rx signal strength threashold. + priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2; + + priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? + priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold; + if(priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) + { // Rx signal strength is not improved after we swtiched antenna. => Swich back. +// printk("SwAntennaDiversity(): Rx Signal Strength is not improved, CurrRxSs: %d, LastRxSs: %d\n", +// priv->AdRxSignalStrength, priv->AdRxSsBeforeSwitched); +//by amy 080312 + // Increase Antenna Diversity checking period due to bad decision. + priv->AdCheckPeriod *= 2; +//by amy 080312 + // Increase Antenna Diversity checking period. + if(priv->AdCheckPeriod > priv->AdMaxCheckPeriod) + priv->AdCheckPeriod = priv->AdMaxCheckPeriod; + + // Wrong deceision => switch back. + SwitchAntenna(dev); + } + else + { // Rx Signal Strength is improved. +// printk("SwAntennaDiversity(): Rx Signal Strength is improved, CurrRxSs: %d, LastRxSs: %d\n", +// priv->AdRxSignalStrength, priv->AdRxSsBeforeSwitched); + + // Reset Antenna Diversity checking period to its min value. + priv->AdCheckPeriod = priv->AdMinCheckPeriod; + } + +// printk("SwAntennaDiversity(): AdRxSsThreshold: %d, AdCheckPeriod: %d\n", +// priv->AdRxSsThreshold, priv->AdCheckPeriod); + } + // Case 4. Evaluate if we shall switch antenna now. + // Cause Table Speed is very fast in TRC Dell Lab, we check it every time. + else// if(priv->AdTickCount >= priv->AdCheckPeriod)//-by amy 080312 + { +// printk("SwAntennaDiversity(): Case 4. Evaluate if we shall switch antenna now.\n"); + + priv->AdTickCount = 0; + + // + // We evaluate RxOk counts for each antenna first and than + // evaluate signal strength. + // The following operation can overcome the disability of CCA on both two antennas + // When signal strength was extremely low or high. + // 2008.01.30. + // + + // + // Evaluate RxOk count from each antenna if we shall switch default antenna now. + // Added by Roger, 2008.02.21. +//{by amy 080312 + if((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt) + && (priv->CurrAntennaIndex == 0)) + { // We set Main antenna as default but RxOk count was less than Aux ones. + + // printk("SwAntennaDiversity(): Main antenna RxOK is poor, AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n", + // priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt); + + // Switch to Aux antenna. + SwitchAntenna(dev); + priv->bHWAdSwitched = true; + } + else if((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt) + && (priv->CurrAntennaIndex == 1)) + { // We set Aux antenna as default but RxOk count was less than Main ones. + + // printk("SwAntennaDiversity(): Aux antenna RxOK is poor, AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n", + // priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt); + + // Switch to Main antenna. + SwitchAntenna(dev); + priv->bHWAdSwitched = true; + } + else + {// Default antenna is better. + + // printk("SwAntennaDiversity(): Default antenna is better., AdMainAntennaRxOkCnt: %d, AdAuxAntennaRxOkCnt: %d\n", + // priv->AdMainAntennaRxOkCnt, priv->AdAuxAntennaRxOkCnt); + + // Still need to check current signal strength. + priv->bHWAdSwitched = false; + } + // + // We evaluate Rx signal strength ONLY when default antenna + // didn't changed by HW evaluation. + // 2008.02.27. + // + // [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05 + // For example, Throughput of aux is better than main antenna(about 10M v.s 2M), + // but AdRxSignalStrength is less than main. + // Our guess is that main antenna have lower throughput and get many change + // to receive more CCK packets(ex.Beacon) which have stronger SignalStrength. + // + if( (!priv->bHWAdSwitched) && (bSwCheckSS)) + { +//by amy 080312} + // Evaluate Rx signal strength if we shall switch antenna now. + if(priv->AdRxSignalStrength < priv->AdRxSsThreshold) + { // Rx signal strength is weak => Switch Antenna. +// printk("SwAntennaDiversity(): Rx Signal Strength is weak, CurrRxSs: %d, RxSsThreshold: %d\n", +// priv->AdRxSignalStrength, priv->AdRxSsThreshold); + + priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength; + priv->bAdSwitchedChecking = true; + + SwitchAntenna(dev); + } + else + { // Rx signal strength is OK. +// printk("SwAntennaDiversity(): Rx Signal Strength is OK, CurrRxSs: %d, RxSsThreshold: %d\n", +// priv->AdRxSignalStrength, priv->AdRxSsThreshold); + + priv->bAdSwitchedChecking = false; + // Increase Rx signal strength threashold if necessary. + if( (priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && // Signal is much stronger than current threshold + priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) // Current threhold is not yet reach upper limit. + { + priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2; + priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? + priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold;//+by amy 080312 + } + + // Reduce Antenna Diversity checking period if possible. + if( priv->AdCheckPeriod > priv->AdMinCheckPeriod ) + { + priv->AdCheckPeriod /= 2; + } + } + } + } +//by amy 080312 + // Reset antenna diversity Rx related statistics. + priv->AdRxOkCnt = 0; + priv->AdMainAntennaRxOkCnt = 0; + priv->AdAuxAntennaRxOkCnt = 0; +//by amy 080312 + +// priv->AdRxOkCnt = 0;//-by amy 080312 + +// printk("-SwAntennaDiversity()\n"); +} + +// +// Description: +// Return TRUE if we shall perform Tx Power Tracking Mecahnism, FALSE otherwise. +// +bool +CheckTxPwrTracking( struct net_device *dev) +{ + struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); + + if(!priv->bTxPowerTrack) + { + return false; + } + +//lzm reserved 080826 + //if(priv->bScanInProgress) + //{ + // return false; + //} + + //if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah + if(priv->bToUpdateTxPwr) + { + return false; + } + + return true; +} + + +// +// Description: +// Timer callback function of SW Antenna Diversity. +// +void +SwAntennaDiversityTimerCallback( + struct net_device *dev + ) +{ + struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); + RT_RF_POWER_STATE rtState; + + //printk("+SwAntennaDiversityTimerCallback()\n"); + + // + // We do NOT need to switch antenna while RF is off. + // 2007.05.09, added by Roger. + // + rtState = priv->eRFPowerState; + do{ + if (rtState == eRfOff) + { +// printk("SwAntennaDiversityTimer - RF is OFF.\n"); + break; + } + else if (rtState == eRfSleep) + { + // Don't access BB/RF under Disable PLL situation. + //RT_TRACE((COMP_RF|COMP_ANTENNA), DBG_LOUD, ("SwAntennaDiversityTimerCallback(): RF is Sleep => skip it\n")); + break; + } + SwAntennaDiversity(dev); + + }while(false); + + if(priv->up) + { + priv->SwAntennaDiversityTimer.expires = jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD); + add_timer(&priv->SwAntennaDiversityTimer); + } + + //printk("-SwAntennaDiversityTimerCallback()\n"); +} + diff --git a/drivers/staging/rtl8187se/r8180_dm.h b/drivers/staging/rtl8187se/r8180_dm.h index 3de92f040f99..b2736c8e521d 100644 --- a/drivers/staging/rtl8187se/r8180_dm.h +++ b/drivers/staging/rtl8187se/r8180_dm.h @@ -1,41 +1,41 @@ -#ifndef R8180_DM_H -#define R8180_DM_H - -#include "r8180.h" -//#include "r8180_hw.h" -//#include "r8180_93cx6.h" -void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength); -bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex); -bool SwitchAntenna( struct net_device *dev); -void SwAntennaDiversity(struct net_device *dev ); -void SwAntennaDiversityTimerCallback(struct net_device *dev); -bool CheckDig(struct net_device *dev); -bool CheckHighPower(struct net_device *dev); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) -void rtl8180_hw_dig_wq (struct work_struct *work); -#else -void rtl8180_hw_dig_wq(struct net_device *dev); -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) -void rtl8180_tx_pw_wq (struct work_struct *work); -#else -void rtl8180_tx_pw_wq(struct net_device *dev); -#endif -#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) -void rtl8180_rate_adapter(struct work_struct * work); - -#else -void rtl8180_rate_adapter(struct net_device *dev); - -#endif -void TxPwrTracking87SE(struct net_device *dev); -bool CheckTxPwrTracking(struct net_device *dev); -#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) -void rtl8180_rate_adapter(struct work_struct * work); -#else -void rtl8180_rate_adapter(struct net_device *dev); -#endif -void timer_rate_adaptive(unsigned long data); - - -#endif +#ifndef R8180_DM_H +#define R8180_DM_H + +#include "r8180.h" +//#include "r8180_hw.h" +//#include "r8180_93cx6.h" +void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength); +bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex); +bool SwitchAntenna( struct net_device *dev); +void SwAntennaDiversity(struct net_device *dev ); +void SwAntennaDiversityTimerCallback(struct net_device *dev); +bool CheckDig(struct net_device *dev); +bool CheckHighPower(struct net_device *dev); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) +void rtl8180_hw_dig_wq (struct work_struct *work); +#else +void rtl8180_hw_dig_wq(struct net_device *dev); +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) +void rtl8180_tx_pw_wq (struct work_struct *work); +#else +void rtl8180_tx_pw_wq(struct net_device *dev); +#endif +#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) +void rtl8180_rate_adapter(struct work_struct * work); + +#else +void rtl8180_rate_adapter(struct net_device *dev); + +#endif +void TxPwrTracking87SE(struct net_device *dev); +bool CheckTxPwrTracking(struct net_device *dev); +#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) +void rtl8180_rate_adapter(struct work_struct * work); +#else +void rtl8180_rate_adapter(struct net_device *dev); +#endif +void timer_rate_adaptive(unsigned long data); + + +#endif diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c index 8b3901d87f87..979ba0b5f331 100644 --- a/drivers/staging/rtl8187se/r8180_wx.c +++ b/drivers/staging/rtl8187se/r8180_wx.c @@ -1274,8 +1274,8 @@ static int r8180_wx_set_enc_ext(struct net_device *dev, } static int r8180_wx_set_auth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *data, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { //printk("====>%s()\n", __func__); struct r8180_priv *priv = ieee80211_priv(dev); @@ -1285,7 +1285,7 @@ static int r8180_wx_set_auth(struct net_device *dev, return 0; down(&priv->wx_sem); - ret = ieee80211_wx_set_auth(priv->ieee80211, info, data, extra); + ret = ieee80211_wx_set_auth(priv->ieee80211, info, &wrqu->param, extra); up(&priv->wx_sem); return ret; } @@ -1312,8 +1312,8 @@ static int r8180_wx_set_mlme(struct net_device *dev, return ret; } static int r8180_wx_set_gen_ie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { // printk("====>%s(), len:%d\n", __func__, data->length); int ret=0; @@ -1325,7 +1325,7 @@ static int r8180_wx_set_gen_ie(struct net_device *dev, down(&priv->wx_sem); #if 1 - ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->length); + ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, wrqu->data.length); #endif up(&priv->wx_sem); //printk("<======%s(), ret:%d\n", __func__, ret); diff --git a/drivers/staging/serqt_usb/Kconfig b/drivers/staging/serqt_usb/Kconfig new file mode 100644 index 000000000000..cc1af5df40d7 --- /dev/null +++ b/drivers/staging/serqt_usb/Kconfig @@ -0,0 +1,9 @@ +config USB_SERIAL_QUATECH_ESU100 + tristate "USB Quatech ESU-100 8 Port Serial Driver" + depends on USB_SERIAL + help + Say Y here if you want to use the Quatech ESU-100 8 port usb to + serial adapter. + + To compile this driver as a module, choose M here: the + module will be called serqt_usb. diff --git a/drivers/staging/serqt_usb/Makefile b/drivers/staging/serqt_usb/Makefile new file mode 100644 index 000000000000..4fd1da275e8d --- /dev/null +++ b/drivers/staging/serqt_usb/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_USB_SERIAL_QUATECH_ESU100) += serqt_usb.o diff --git a/drivers/staging/serqt_usb/TODO b/drivers/staging/serqt_usb/TODO new file mode 100644 index 000000000000..34ecca8992d2 --- /dev/null +++ b/drivers/staging/serqt_usb/TODO @@ -0,0 +1,8 @@ +Things to do for this driver to get merged into the main portion of the +kernel: + - checkpatch cleanups + - sparse clean + - port to the usb-serial layer instead of doing it all on its + own. + +Send patches to Greg Kroah-Hartman diff --git a/drivers/staging/serqt_usb/serqt_usb.c b/drivers/staging/serqt_usb/serqt_usb.c new file mode 100644 index 000000000000..1781510c53fd --- /dev/null +++ b/drivers/staging/serqt_usb/serqt_usb.c @@ -0,0 +1,2779 @@ +/* + * This code was developed for the Quatech USB line for linux, it used + * much of the code developed by Greg Kroah-Hartman for USB serial devices + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Use our own dbg macro */ +/* #define DEBUG_ON */ +/* #undef dbg */ +#ifdef DEBUG_ON +#define mydbg(const...) printk(const) +#else +#define mydbg(const...) +#endif + +/* parity check flag */ +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + +#define SERIAL_TTY_MAJOR 0 /* Nice legal number now */ +#define SERIAL_TTY_MINORS 255 /* loads of devices :) */ +#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */ +#define PREFUFF_LEVEL_CONSERVATIVE 128 +#define ATC_DISABLED 0x00 + +#define RR_BITS 0x03 /* for clearing clock bits */ +#define DUPMODE_BITS 0xc0 + +#define RS232_MODE 0x00 +#define RTSCTS_TO_CONNECTOR 0x40 +#define CLKS_X4 0x02 + +#define LOOPMODE_BITS 0x41 /* LOOP1 = b6, LOOP0 = b0 (PORT B) */ +#define ALL_LOOPBACK 0x01 +#define MODEM_CTRL 0x40 + +#define THISCHAR data[i] +#define NEXTCHAR data[i + 1] +#define THIRDCHAR data[i + 2] +#define FOURTHCHAR data[i + 3] + +/* + * Useful defintions for port A, Port B and Port C + */ +#define FULLPWRBIT 0x00000080 +#define NEXT_BOARD_POWER_BIT 0x00000004 + +#define SERIAL_LSR_OE 0x02 +#define SERIAL_LSR_PE 0x04 +#define SERIAL_LSR_FE 0x08 +#define SERIAL_LSR_BI 0x10 + +#define SERIAL_LSR_TEMT 0x40 + +#define DIV_LATCH_LS 0x00 +#define XMT_HOLD_REGISTER 0x00 +#define XVR_BUFFER_REGISTER 0x00 +#define DIV_LATCH_MS 0x01 +#define FIFO_CONTROL_REGISTER 0x02 +#define LINE_CONTROL_REGISTER 0x03 +#define MODEM_CONTROL_REGISTER 0x04 +#define LINE_STATUS_REGISTER 0x05 +#define MODEM_STATUS_REGISTER 0x06 + +#define SERIAL_MCR_DTR 0x01 +#define SERIAL_MCR_RTS 0x02 +#define SERIAL_MCR_LOOP 0x10 + +#define SERIAL_MSR_CTS 0x10 +#define SERIAL_MSR_CD 0x80 +#define SERIAL_MSR_RI 0x40 +#define SERIAL_MSR_DSR 0x20 +#define SERIAL_MSR_MASK 0xf0 + +#define SERIAL_8_DATA 0x03 +#define SERIAL_7_DATA 0x02 +#define SERIAL_6_DATA 0x01 +#define SERIAL_5_DATA 0x00 + +#define SERIAL_ODD_PARITY 0X08 +#define SERIAL_EVEN_PARITY 0X18 +#define SERIAL_TWO_STOPB 0x04 +#define SERIAL_ONE_STOPB 0x00 + +#define MAX_BAUD_RATE 460800 +#define MAX_BAUD_REMAINDER 4608 + +#define QT_SET_GET_DEVICE 0xc2 +#define QT_OPEN_CLOSE_CHANNEL 0xca +#define QT_GET_SET_PREBUF_TRIG_LVL 0xcc +#define QT_SET_ATF 0xcd +#define QT_GET_SET_REGISTER 0xc0 +#define QT_GET_SET_UART 0xc1 +#define QT_HW_FLOW_CONTROL_MASK 0xc5 +#define QT_SW_FLOW_CONTROL_MASK 0xc6 +#define QT_SW_FLOW_CONTROL_DISABLE 0xc7 +#define QT_BREAK_CONTROL 0xc8 + +#define SERIALQT_PCI_IOC_MAGIC 'k' +#define SERIALQT_WRITE_QOPR _IOW(SERIALQT_PCI_IOC_MAGIC, 0, int) +#define SERIALQT_WRITE_QMCR _IOW(SERIALQT_PCI_IOC_MAGIC, 1, int) +#define SERIALQT_GET_NUMOF_UNITS _IOR(SERIALQT_PCI_IOC_MAGIC, 2, void *) +#define SERIALQT_GET_THIS_UNIT _IOR(SERIALQT_PCI_IOC_MAGIC, 3, void *) +#define SERIALQT_READ_QOPR _IOR(SERIALQT_PCI_IOC_MAGIC, 4, int) +#define SERIALQT_READ_QMCR _IOR(SERIALQT_PCI_IOC_MAGIC, 5, int) +#define SERIALQT_IS422_EXTENDED _IOR(SERIALQT_PCI_IOC_MAGIC, 6, int) /* returns successful if 422 extended */ + +#define USBD_TRANSFER_DIRECTION_IN 0xc0 +#define USBD_TRANSFER_DIRECTION_OUT 0x40 + +#define ATC_DISABLED 0x00 +#define ATC_RTS_ENABLED 0x02 +#define ATC_DTR_ENABLED 0x01 + +#define RR_BITS 0x03 /* for clearing clock bits */ +#define DUPMODE_BITS 0xc0 + +#define FULL_DUPLEX 0x00 +#define HALF_DUPLEX_RTS 0x40 +#define HALF_DUPLEX_DTR 0x80 + +#define QMCR_FULL_DUPLEX 0x00 +#define QMCR_HALF_DUPLEX_RTS 0x02 +#define QMCR_HALF_DUPLEX_DTR 0x01 +#define QMCR_HALF_DUPLEX_MASK 0x03 +#define QMCR_CONNECTOR_MASK 0x1C + +#define QMCR_RX_EN_MASK 0x20 + +#define QMCR_ALL_LOOPBACK 0x10 +#define QMCR_MODEM_CONTROL 0X00 + +#define SERIALQT_IOC_MAXNR 6 + +struct usb_serial_port { + struct usb_serial *serial; /* pointer back to the owner of this port */ + struct tty_struct *tty; /* the coresponding tty for this port */ + unsigned char number; + char active; /* someone has this device open */ + + unsigned char *interrupt_in_buffer; + struct urb *interrupt_in_urb; + __u8 interrupt_in_endpointAddress; + + unsigned char *bulk_in_buffer; + unsigned char *xfer_to_tty_buffer; + struct urb *read_urb; + __u8 bulk_in_endpointAddress; + + unsigned char *bulk_out_buffer; + int bulk_out_size; + struct urb *write_urb; + __u8 bulk_out_endpointAddress; + + wait_queue_head_t write_wait; + wait_queue_head_t wait; + struct work_struct work; + + int open_count; /* number of times this port has been opened */ + struct semaphore sem; /* locks this structure */ + + __u8 shadowLCR; /* last LCR value received */ + __u8 shadowMCR; /* last MCR value received */ + __u8 shadowMSR; /* last MSR value received */ + __u8 shadowLSR; /* last LSR value received */ + int RxHolding; + char closePending; + int ReadBulkStopped; + + void *private; /* data private to the specific port */ +}; + +struct identity { + int index; + int n_identity; +}; + +struct usb_serial { + struct usb_device *dev; + struct usb_interface *interface; /* the interface for this device */ + struct tty_driver *tty_driver; /* the tty_driver for this device */ + unsigned char minor; /* the starting minor number for this device */ + unsigned char num_ports; /* the number of ports this device has */ + char num_interrupt_in; /* number of interrupt in endpoints we have */ + char num_bulk_in; /* number of bulk in endpoints we have */ + char num_bulk_out; /* number of bulk out endpoints we have */ + unsigned char num_OpenCount; /* the number of ports this device has */ + + __u16 vendor; /* vendor id of this device */ + __u16 product; /* product id of this device */ + struct usb_serial_port port[MAX_NUM_PORTS]; + + void *private; /* data private to the specific driver */ +}; + +static inline int port_paranoia_check(struct usb_serial_port *port, + const char *function) +{ + if (!port) { + dbg("%s - port == NULL", function); + return -1; + } + if (!port->serial) { + dbg("%s - port->serial == NULL\n", function); + return -1; + } + if (!port->tty) { + dbg("%s - port->tty == NULL\n", function); + return -1; + } + + return 0; +} + +/* Inline functions to check the sanity of a pointer that is passed to us */ +static inline int serial_paranoia_check(struct usb_serial *serial, + const char *function) +{ + if (!serial) { + dbg("%s - serial == NULL\n", function); + return -1; + } + + return 0; +} + +static inline struct usb_serial *get_usb_serial(struct usb_serial_port *port, + const char *function) +{ + /* if no port was specified, or it fails a paranoia check */ + if (!port || + port_paranoia_check(port, function) || + serial_paranoia_check(port->serial, function)) { + /* then say that we dont have a valid usb_serial thing, which will + * end up genrating -ENODEV return values */ + return NULL; + } + + return port->serial; +} + +struct qt_get_device_data { + __u8 porta; + __u8 portb; + __u8 portc; +}; + +struct qt_open_channel_data { + __u8 line_status; + __u8 modem_status; +}; + +static void ProcessLineStatus(struct usb_serial_port *port, + unsigned char line_status); +static void ProcessModemStatus(struct usb_serial_port *port, + unsigned char modem_status); +static void ProcessRxChar(struct usb_serial_port *port, unsigned char Data); +static struct usb_serial *get_free_serial(int num_ports, int *minor); + +static int serqt_probe(struct usb_interface *interface, + const struct usb_device_id *id); + +static void serqt_usb_disconnect(struct usb_interface *interface); +static int box_set_device(struct usb_serial *serial, + struct qt_get_device_data *pDeviceData); +static int box_get_device(struct usb_serial *serial, + struct qt_get_device_data *pDeviceData); +static int serial_open(struct tty_struct *tty, struct file *filp); +static void serial_close(struct tty_struct *tty, struct file *filp); +static int serial_write_room(struct tty_struct *tty); +static int serial_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +static void serial_set_termios(struct tty_struct *tty, struct ktermios *old); +static int serial_write(struct tty_struct *tty, const unsigned char *buf, + int count); + +static void serial_throttle(struct tty_struct *tty); +static void serial_unthrottle(struct tty_struct *tty); +static int serial_break(struct tty_struct *tty, int break_state); +static int serial_chars_in_buffer(struct tty_struct *tty); + +static int qt_open(struct usb_serial_port *port, struct file *filp); +static int BoxSetPrebufferLevel(struct usb_serial *serial); + +static int BoxSetATC(struct usb_serial *serial, __u16 n_Mode); +static int BoxSetUart(struct usb_serial *serial, unsigned short Uart_Number, + unsigned short default_divisor, + unsigned char default_LCR); + +static int BoxOPenCloseChannel(struct usb_serial *serial, __u16 Uart_Number, + __u16 OpenClose, + struct qt_open_channel_data *pDeviceData); +static void qt_close(struct usb_serial_port *port, struct file *filp); +static int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number, + unsigned short Register_Num, __u8 *pValue); +static int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number, + unsigned short Register_Num, unsigned short Value); +static void qt_write_bulk_callback(struct urb *urb); +static int qt_write(struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count); +static void port_softint(struct work_struct *work); +static int qt_write_room(struct usb_serial_port *port); +static int qt_chars_in_buffer(struct usb_serial_port *port); +static int qt_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg); +static void qt_set_termios(struct usb_serial_port *port, + struct ktermios *old_termios); +static int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int UartNumber, + int bSet); +static int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 UartNumber); +static int EmulateWriteQMCR_Reg(int index, unsigned uc_value); +static int EmulateReadQMCR_Reg(int index, unsigned *uc_value); +static struct usb_serial *find_the_box(unsigned int index); +static int ioctl_serial_usb(struct inode *innod, struct file *filp, unsigned int cmd, + unsigned long arg); + +static int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 Uart, + unsigned char stop_char, unsigned char start_char); +static void qt_read_bulk_callback(struct urb *urb); + +static void port_sofrint(void *private); + +static void return_serial(struct usb_serial *serial); + +static int serial_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static int serial_tiocmget(struct tty_struct *tty, struct file *file); + +static int qt_tiocmset(struct usb_serial_port *port, struct file *file, + unsigned int value); + +static int qt_tiocmget(struct usb_serial_port *port, struct file *file); + +/* Version Information */ +#define DRIVER_VERSION "v2.14" +#define DRIVER_AUTHOR "Tim Gobeli, Quatech, Inc" +#define DRIVER_DESC "Quatech USB to Serial Driver" + +#define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */ +#define DEVICE_ID_QUATECH_RS232_SINGLE_PORT 0xC020 /* SSU100 */ +#define DEVICE_ID_QUATECH_RS422_SINGLE_PORT 0xC030 /* SSU200 */ +#define DEVICE_ID_QUATECH_RS232_DUAL_PORT 0xC040 /* DSU100 */ +#define DEVICE_ID_QUATECH_RS422_DUAL_PORT 0xC050 /* DSU200 */ +#define DEVICE_ID_QUATECH_RS232_FOUR_PORT 0xC060 /* QSU100 */ +#define DEVICE_ID_QUATECH_RS422_FOUR_PORT 0xC070 /* QSU200 */ +#define DEVICE_ID_QUATECH_RS232_EIGHT_PORT_A 0xC080 /* ESU100A */ +#define DEVICE_ID_QUATECH_RS232_EIGHT_PORT_B 0xC081 /* ESU100B */ +#define DEVICE_ID_QUATECH_RS422_EIGHT_PORT_A 0xC0A0 /* ESU200A */ +#define DEVICE_ID_QUATECH_RS422_EIGHT_PORT_B 0xC0A1 /* ESU200B */ +#define DEVICE_ID_QUATECH_RS232_16_PORT_A 0xC090 /* HSU100A */ +#define DEVICE_ID_QUATECH_RS232_16_PORT_B 0xC091 /* HSU100B */ +#define DEVICE_ID_QUATECH_RS232_16_PORT_C 0xC092 /* HSU100C */ +#define DEVICE_ID_QUATECH_RS232_16_PORT_D 0xC093 /* HSU100D */ +#define DEVICE_ID_QUATECH_RS422_16_PORT_A 0xC0B0 /* HSU200A */ +#define DEVICE_ID_QUATECH_RS422_16_PORT_B 0xC0B1 /* HSU200B */ +#define DEVICE_ID_QUATECH_RS422_16_PORT_C 0xC0B2 /* HSU200C */ +#define DEVICE_ID_QUATECH_RS422_16_PORT_D 0xC0B3 /* HSU200D */ + +/* table of Quatech devices */ +static struct usb_device_id serqt_table[] = { + {USB_DEVICE + (USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_SINGLE_PORT)}, + {USB_DEVICE + (USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_SINGLE_PORT)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_DUAL_PORT)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_DUAL_PORT)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_FOUR_PORT)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_FOUR_PORT)}, + {USB_DEVICE + (USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_EIGHT_PORT_A)}, + {USB_DEVICE + (USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_EIGHT_PORT_B)}, + {USB_DEVICE + (USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_EIGHT_PORT_A)}, + {USB_DEVICE + (USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_EIGHT_PORT_B)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_16_PORT_A)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_16_PORT_B)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_16_PORT_C)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_16_PORT_D)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_16_PORT_A)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_16_PORT_B)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_16_PORT_C)}, + {USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_16_PORT_D)}, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, serqt_table); + +static int major_number; +static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ + +/* table of Quatech 422devices */ +static unsigned int serqt_422_table[] = { + DEVICE_ID_QUATECH_RS422_SINGLE_PORT, + DEVICE_ID_QUATECH_RS422_DUAL_PORT, + DEVICE_ID_QUATECH_RS422_FOUR_PORT, + DEVICE_ID_QUATECH_RS422_EIGHT_PORT_A, + DEVICE_ID_QUATECH_RS422_EIGHT_PORT_B, + DEVICE_ID_QUATECH_RS422_16_PORT_A, + DEVICE_ID_QUATECH_RS422_16_PORT_B, + DEVICE_ID_QUATECH_RS422_16_PORT_C, + DEVICE_ID_QUATECH_RS422_16_PORT_D, + 0 /* terminate with zero */ +}; + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver serqt_usb_driver = { + .name = "quatech-usb-serial", + .probe = serqt_probe, + .disconnect = serqt_usb_disconnect, + .id_table = serqt_table, +}; + +static struct ktermios *serial_termios[SERIAL_TTY_MINORS]; +static struct ktermios *serial_termios_locked[SERIAL_TTY_MINORS]; + +static const struct tty_operations serial_ops = { + .open = serial_open, + .close = serial_close, + .write = serial_write, + .write_room = serial_write_room, + .ioctl = serial_ioctl, + .set_termios = serial_set_termios, + .throttle = serial_throttle, + .unthrottle = serial_unthrottle, + .break_ctl = serial_break, + .chars_in_buffer = serial_chars_in_buffer, + .tiocmset = serial_tiocmset, + .tiocmget = serial_tiocmget, +}; + +static struct tty_driver serial_tty_driver = { + .magic = TTY_DRIVER_MAGIC, + .driver_name = "Quatech usb-serial", + .name = "ttyQT_USB", + .major = SERIAL_TTY_MAJOR, + .minor_start = 0, + .num = SERIAL_TTY_MINORS, + .type = TTY_DRIVER_TYPE_SERIAL, + .subtype = SERIAL_TYPE_NORMAL, + .flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV, + + .termios = serial_termios, + .termios_locked = serial_termios_locked, + .init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL, + + .init_termios.c_iflag = ICRNL | IXON, + .init_termios.c_oflag = OPOST, + + .init_termios.c_lflag = + ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN, +}; + +/* fops for parent device */ +static const struct file_operations serialqt_usb_fops = { + .ioctl = ioctl_serial_usb, +}; + + /** + * serqt_probe + * + * Called by the usb core when a new device is connected that it thinks + * this driver might be interested in. + * + */ +static int serqt_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(interface); + struct usb_serial *serial = NULL; + struct usb_serial_port *port; + struct usb_endpoint_descriptor *endpoint; + struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS]; + struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; + struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; + int minor; + int buffer_size; + int i; + struct usb_host_interface *iface_desc; + int num_interrupt_in = 0; + int num_bulk_in = 0; + int num_bulk_out = 0; + int num_ports; + struct qt_get_device_data DeviceData; + int status; + + mydbg("In %s\n", __func__); + + /* let's find the endpoints needed */ + /* check out the endpoints */ + iface_desc = interface->cur_altsetting;; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk in endpoint */ + mydbg("found bulk in"); + bulk_in_endpoint[num_bulk_in] = endpoint; + ++num_bulk_in; + } + + if (((endpoint->bEndpointAddress & 0x80) == 0x00) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk out endpoint */ + mydbg("found bulk out\n"); + bulk_out_endpoint[num_bulk_out] = endpoint; + ++num_bulk_out; + } + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x03)) { + /* we found a interrupt in endpoint */ + mydbg("found interrupt in\n"); + interrupt_in_endpoint[num_interrupt_in] = endpoint; + ++num_interrupt_in; + } + } + + /* found all that we need */ + dev_info(&interface->dev, "Quatech converter detected\n"); + num_ports = num_bulk_out; + if (num_ports == 0) { + err("Quatech device with no bulk out, not allowed."); + return -ENODEV; + + } + + serial = get_free_serial(num_ports, &minor); + if (serial == NULL) { + err("No more free serial devices"); + return -ENODEV; + } + + serial->dev = dev; + serial->interface = interface; + serial->minor = minor; + serial->num_ports = num_ports; + serial->num_bulk_in = num_bulk_in; + serial->num_bulk_out = num_bulk_out; + serial->num_interrupt_in = num_interrupt_in; + serial->vendor = dev->descriptor.idVendor; + serial->product = dev->descriptor.idProduct; + + /* set up the endpoint information */ + for (i = 0; i < num_bulk_in; ++i) { + endpoint = bulk_in_endpoint[i]; + port = &serial->port[i]; + port->read_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port->read_urb) { + err("No free urbs available"); + goto probe_error; + } + buffer_size = endpoint->wMaxPacketSize; + port->bulk_in_endpointAddress = endpoint->bEndpointAddress; + port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); + port->xfer_to_tty_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!port->bulk_in_buffer) { + err("Couldn't allocate bulk_in_buffer"); + goto probe_error; + } + usb_fill_bulk_urb(port->read_urb, dev, + usb_rcvbulkpipe(dev, + endpoint->bEndpointAddress), + port->bulk_in_buffer, buffer_size, + qt_read_bulk_callback, port); + } + + for (i = 0; i < num_bulk_out; ++i) { + endpoint = bulk_out_endpoint[i]; + port = &serial->port[i]; + port->write_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port->write_urb) { + err("No free urbs available"); + goto probe_error; + } + buffer_size = endpoint->wMaxPacketSize; + port->bulk_out_size = buffer_size; + port->bulk_out_endpointAddress = endpoint->bEndpointAddress; + port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!port->bulk_out_buffer) { + err("Couldn't allocate bulk_out_buffer"); + goto probe_error; + } + usb_fill_bulk_urb(port->write_urb, dev, + usb_sndbulkpipe(dev, + endpoint->bEndpointAddress), + port->bulk_out_buffer, buffer_size, + qt_write_bulk_callback, port); + + } + + /* For us numb of bulkin or out = number of ports */ + mydbg("%s - setting up %d port structures for this device\n", + __func__, num_bulk_in); + for (i = 0; i < num_bulk_in; ++i) { + port = &serial->port[i]; + port->number = i + serial->minor; + port->serial = serial; + + INIT_WORK(&port->work, port_softint); + + init_MUTEX(&port->sem); + + } + status = box_get_device(serial, &DeviceData); + if (status < 0) { + mydbg(__FILE__ "box_get_device failed"); + goto probe_error; + } + + mydbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb); + + DeviceData.portb &= ~FULLPWRBIT; + mydbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb); + + status = box_set_device(serial, &DeviceData); + if (status < 0) { + mydbg(__FILE__ "box_set_device failed\n"); + goto probe_error; + } + + /* initialize the devfs nodes for this device and let the user know what ports we are bound to */ + for (i = 0; i < serial->num_ports; ++i) { + dev_info(&interface->dev, + "Converter now attached to ttyUSB%d (or usb/tts/%d for devfs)", + serial->port[i].number, serial->port[i].number); + } + + /* usb_serial_console_init (debug, minor); */ + + /***********TAG add start next board here ****/ + status = box_get_device(serial, &DeviceData); + if (status < 0) { + mydbg(__FILE__ "box_get_device failed"); + goto probe_error; + } + /* + * and before we power up lets initialiaze parnent device stuff here before + * we set thmem via any other method such as the property pages + */ + switch (serial->product) { + case DEVICE_ID_QUATECH_RS232_SINGLE_PORT: + case DEVICE_ID_QUATECH_RS232_DUAL_PORT: + case DEVICE_ID_QUATECH_RS232_FOUR_PORT: + case DEVICE_ID_QUATECH_RS232_EIGHT_PORT_A: + case DEVICE_ID_QUATECH_RS232_EIGHT_PORT_B: + case DEVICE_ID_QUATECH_RS232_16_PORT_A: + case DEVICE_ID_QUATECH_RS232_16_PORT_B: + case DEVICE_ID_QUATECH_RS232_16_PORT_C: + case DEVICE_ID_QUATECH_RS232_16_PORT_D: + DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); + DeviceData.porta |= CLKS_X4; + DeviceData.portb &= ~(LOOPMODE_BITS); + DeviceData.portb |= RS232_MODE; + break; + + case DEVICE_ID_QUATECH_RS422_SINGLE_PORT: + case DEVICE_ID_QUATECH_RS422_DUAL_PORT: + case DEVICE_ID_QUATECH_RS422_FOUR_PORT: + case DEVICE_ID_QUATECH_RS422_EIGHT_PORT_A: + case DEVICE_ID_QUATECH_RS422_EIGHT_PORT_B: + case DEVICE_ID_QUATECH_RS422_16_PORT_A: + case DEVICE_ID_QUATECH_RS422_16_PORT_B: + case DEVICE_ID_QUATECH_RS422_16_PORT_C: + case DEVICE_ID_QUATECH_RS422_16_PORT_D: + DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); + DeviceData.porta |= CLKS_X4; + DeviceData.portb &= ~(LOOPMODE_BITS); + DeviceData.portb |= ALL_LOOPBACK; + break; + default: + DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); + DeviceData.porta |= CLKS_X4; + DeviceData.portb &= ~(LOOPMODE_BITS); + DeviceData.portb |= RS232_MODE; + break; + + } + status = BoxSetPrebufferLevel(serial); /* sets to default vaue */ + if (status < 0) { + mydbg(__FILE__ "BoxSetPrebufferLevel failed\n"); + goto probe_error; + } + + status = BoxSetATC(serial, ATC_DISABLED); + if (status < 0) { + mydbg(__FILE__ "BoxSetATC failed\n"); + goto probe_error; + } + /**********************************************************/ + mydbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb); + + DeviceData.portb |= NEXT_BOARD_POWER_BIT; + mydbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb); + + status = box_set_device(serial, &DeviceData); + if (status < 0) { + mydbg(__FILE__ "box_set_device failed\n"); + goto probe_error; + } + + mydbg("Exit Success %s\n", __func__); + + usb_set_intfdata(interface, serial); + return 0; + +probe_error: + + for (i = 0; i < num_bulk_in; ++i) { + port = &serial->port[i]; + usb_free_urb(port->read_urb); + kfree(port->bulk_in_buffer); + } + for (i = 0; i < num_bulk_out; ++i) { + port = &serial->port[i]; + usb_free_urb(port->write_urb); + kfree(port->bulk_out_buffer); + kfree(port->xfer_to_tty_buffer); + } + for (i = 0; i < num_interrupt_in; ++i) { + port = &serial->port[i]; + usb_free_urb(port->interrupt_in_urb); + kfree(port->interrupt_in_buffer); + } + + /* return the minor range that this device had */ + return_serial(serial); + mydbg("Exit fail %s\n", __func__); + + /* free up any memory that we allocated */ + kfree(serial); + return -EIO; +} + +/* + * returns the serial_table array pointers that are taken + * up in consecutive positions for each port to a common usb_serial structure + * back to NULL + */ +static void return_serial(struct usb_serial *serial) +{ + int i; + + mydbg("%s\n", __func__); + + if (serial == NULL) + return; + + for (i = 0; i < serial->num_ports; ++i) + serial_table[serial->minor + i] = NULL; + + return; +} + +/* + * Finds the first locatio int the serial_table array where it can fit + * num_ports number of consecutive points to a common usb_serial + * structure,allocates a stucture points to it in all the structures, and + * returns the index to the first location in the array in the "minor" + * variable. + */ +static struct usb_serial *get_free_serial(int num_ports, int *minor) +{ + struct usb_serial *serial = NULL; + int i, j; + int good_spot; + + mydbg("%s %d\n", __func__, num_ports); + + *minor = 0; + for (i = 0; i < SERIAL_TTY_MINORS; ++i) { + if (serial_table[i]) + continue; + + good_spot = 1; + /* + * find a spot in the array where you can fit consecutive + * positions to put the pointers to the usb_serail allocated + * structure for all the minor numbers (ie. ports) + */ + for (j = 1; j <= num_ports - 1; ++j) + if (serial_table[i + j]) + good_spot = 0; + if (good_spot == 0) + continue; + + serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL); + if (!serial) { + err("%s - Out of memory", __func__); + return NULL; + } + memset(serial, 0, sizeof(struct usb_serial)); + serial_table[i] = serial; + *minor = i; + mydbg("%s - minor base = %d\n", __func__, *minor); + + /* + * copy in the pointer into the array starting a the *minor + * position minor is the index into the array. + */ + for (i = *minor + 1; + (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) + serial_table[i] = serial; + return serial; + } + return NULL; +} + +static int flip_that(struct tty_struct *tty, __u16 UartNumber, + struct usb_serial *serial) +{ + tty_flip_buffer_push(tty); + tty_schedule_flip(tty); + return 0; +} + +/* Handles processing and moving data to the tty layer */ +static void port_sofrint(void *private) +{ + struct usb_serial_port *port = (struct usb_serial_port *)private; + struct usb_serial *serial = get_usb_serial(port, __func__); + struct tty_struct *tty = port->tty; + unsigned char *data = port->read_urb->transfer_buffer; + unsigned int UartNumber; + struct urb *urb = port->read_urb; + unsigned int RxCount = urb->actual_length; + int i, result; + int flag, flag_data; + + /* UartNumber = MINOR(port->tty->device) - serial->minor; */ + UartNumber = tty->index - serial->minor; + + mydbg("%s - port %d\n", __func__, port->number); + mydbg("%s - port->RxHolding = %d\n", __func__, port->RxHolding); + + if (port_paranoia_check(port, __func__) != 0) { + mydbg("%s - port_paranoia_check, exiting\n", __func__); + port->ReadBulkStopped = 1; + return; + } + + if (!serial) { + mydbg("%s - bad serial pointer, exiting\n", __func__); + return; + } + if (port->closePending == 1) { + /* Were closing , stop reading */ + mydbg("%s - (port->closepending == 1\n", __func__); + port->ReadBulkStopped = 1; + return; + } + + /* + * RxHolding is asserted by throttle, if we assert it, we're not + * receiving any more characters and let the box handle the flow + * control + */ + if (port->RxHolding == 1) { + port->ReadBulkStopped = 1; + return; + } + + if (urb->status) { + port->ReadBulkStopped = 1; + + mydbg("%s - nonzero read bulk status received: %d\n", + __func__, urb->status); + return; + } + + tty = port->tty; + mydbg("%s - port %d, tty =0x%p\n", __func__, port->number, tty); + + if (tty && RxCount) { + flag_data = 0; + for (i = 0; i < RxCount; ++i) { + /* Look ahead code here */ + if ((i <= (RxCount - 3)) && (THISCHAR == 0x1b) + && (NEXTCHAR == 0x1b)) { + flag = 0; + switch (THIRDCHAR) { + case 0x00: + /* Line status change 4th byte must follow */ + if (i > (RxCount - 4)) { + mydbg("Illegal escape sequences in received data\n"); + break; + } + ProcessLineStatus(port, FOURTHCHAR); + i += 3; + flag = 1; + break; + + case 0x01: + /* Modem status status change 4th byte must follow */ + mydbg("Modem status status. \n"); + if (i > (RxCount - 4)) { + mydbg + ("Illegal escape sequences in received data\n"); + break; + } + ProcessModemStatus(port, FOURTHCHAR); + i += 3; + flag = 1; + break; + case 0xff: + mydbg("No status sequence. \n"); + + ProcessRxChar(port, THISCHAR); + ProcessRxChar(port, NEXTCHAR); + i += 2; + break; + } + if (flag == 1) + continue; + } + + if (tty && urb->actual_length) { + tty_buffer_request_room(tty, 1); + tty_insert_flip_string(tty, (data + i), 1); + } + + } + tty_flip_buffer_push(tty); + } + + /* Continue trying to always read */ + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + qt_read_bulk_callback, port); + result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (result) + mydbg("%s - failed resubmitting read urb, error %d", + __func__, result); + else { + if (tty && RxCount) + flip_that(tty, UartNumber, serial); + } + + return; + +} + +static void qt_read_bulk_callback(struct urb *urb) +{ + + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + + if (urb->status) { + port->ReadBulkStopped = 1; + mydbg("%s - nonzero write bulk status received: %d\n", + __func__, urb->status); + return; + } + + port_sofrint((void *)port); + schedule_work(&port->work); +} + +static void ProcessRxChar(struct usb_serial_port *port, unsigned char Data) +{ + struct tty_struct *tty; + struct urb *urb = port->read_urb; + tty = port->tty; + /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ + + if (tty && urb->actual_length) { + tty_buffer_request_room(tty, 1); + tty_insert_flip_string(tty, &Data, 1); + /* tty_flip_buffer_push(tty); */ + } + + return; +} + +static void ProcessLineStatus(struct usb_serial_port *port, + unsigned char line_status) +{ + + port->shadowLSR = + line_status & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | + SERIAL_LSR_BI); + return; +} + +static void ProcessModemStatus(struct usb_serial_port *port, + unsigned char modem_status) +{ + + port->shadowMSR = modem_status; + wake_up_interruptible(&port->wait); + return; +} + +static void serqt_usb_disconnect(struct usb_interface *interface) +{ + struct usb_serial *serial = usb_get_intfdata(interface); + /* struct device *dev = &interface->dev; */ + struct usb_serial_port *port; + int i; + + mydbg("%s\n", __func__); + if (serial) { + + serial->dev = NULL; + + for (i = 0; i < serial->num_ports; ++i) + serial->port[i].open_count = 0; + + for (i = 0; i < serial->num_bulk_in; ++i) { + port = &serial->port[i]; + usb_unlink_urb(port->read_urb); + usb_free_urb(port->read_urb); + kfree(port->bulk_in_buffer); + } + for (i = 0; i < serial->num_bulk_out; ++i) { + port = &serial->port[i]; + usb_unlink_urb(port->write_urb); + usb_free_urb(port->write_urb); + kfree(port->bulk_out_buffer); + } + for (i = 0; i < serial->num_interrupt_in; ++i) { + port = &serial->port[i]; + usb_unlink_urb(port->interrupt_in_urb); + usb_free_urb(port->interrupt_in_urb); + kfree(port->interrupt_in_buffer); + } + + /* return the minor range that this device had */ + return_serial(serial); + + /* free up any memory that we allocated */ + kfree(serial); + + } else { + dev_info(&interface->dev, "device disconnected"); + } + +} + +static struct usb_serial *get_serial_by_minor(unsigned int minor) +{ + return serial_table[minor]; +} + +/***************************************************************************** + * Driver tty interface functions + *****************************************************************************/ +static int serial_open(struct tty_struct *tty, struct file *filp) +{ + struct usb_serial *serial; + struct usb_serial_port *port; + unsigned int portNumber; + int retval = 0; + + mydbg("%s\n", __func__); + + /* initialize the pointer incase something fails */ + tty->driver_data = NULL; + + /* get the serial object associated with this tty pointer */ + /* serial = get_serial_by_minor (MINOR(tty->device)); */ + + /* get the serial object associated with this tty pointer */ + serial = get_serial_by_minor(tty->index); + + if (serial_paranoia_check(serial, __func__)) + return -ENODEV; + + /* set up our port structure making the tty driver remember our port object, and us it */ + portNumber = tty->index - serial->minor; + port = &serial->port[portNumber]; + tty->driver_data = port; + + down(&port->sem); + port->tty = tty; + + ++port->open_count; + if (port->open_count == 1) { + port->closePending = 0; + mydbg("%s port->closepending = 0\n", __func__); + + port->RxHolding = 0; + mydbg("%s port->RxHolding = 0\n", __func__); + + retval = qt_open(port, filp); + } + + if (retval) + port->open_count = 0; + mydbg("%s returning port->closePending = %d\n", __func__, + port->closePending); + + up(&port->sem); + return retval; +} + +/***************************************************************************** + *device's specific driver functions + *****************************************************************************/ +static int qt_open(struct usb_serial_port *port, struct file *filp) +{ + struct usb_serial *serial = port->serial; + int result = 0; + unsigned int UartNumber; + struct qt_get_device_data DeviceData; + struct qt_open_channel_data ChannelData; + unsigned short default_divisor = 0x30; /* gives 9600 baud rate */ + unsigned char default_LCR = SERIAL_8_DATA; /* 8, none , 1 */ + int status = 0; + + if (port_paranoia_check(port, __func__)) + return -ENODEV; + + mydbg("%s - port %d\n", __func__, port->number); + + /* force low_latency on so that our tty_push actually forces the data through, + otherwise it is scheduled, and with high data rates (like with OHCI) data + can get lost. */ + if (port->tty) + port->tty->low_latency = 0; + + UartNumber = port->tty->index - serial->minor; + + status = box_get_device(serial, &DeviceData); + if (status < 0) { + mydbg(__FILE__ "box_get_device failed\n"); + return status; + } + serial->num_OpenCount++; + mydbg("%s serial->num_OpenCount = %d\n", __func__, + serial->num_OpenCount); + /* Open uart channel */ + + /* Port specific setups */ + status = BoxOPenCloseChannel(serial, UartNumber, 1, &ChannelData); + if (status < 0) { + mydbg(__FILE__ "BoxOPenCloseChannel failed\n"); + return status; + } + mydbg(__FILE__ "BoxOPenCloseChannel completed.\n"); + + port->shadowLSR = ChannelData.line_status & + (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | SERIAL_LSR_BI); + + port->shadowMSR = ChannelData.modem_status & + (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD); + + /* Set Baud rate to default and turn off (default)flow control here */ + status = BoxSetUart(serial, UartNumber, default_divisor, default_LCR); + if (status < 0) { + mydbg(__FILE__ "BoxSetUart failed\n"); + return status; + } + mydbg(__FILE__ "BoxSetUart completed.\n"); + + /* Put this here to make it responsive to stty and defauls set by the tty layer */ + qt_set_termios(port, NULL); + + /* Initialize the wait que head */ + init_waitqueue_head(&(port->wait)); + + /* if we have a bulk endpoint, start reading from it */ + if (serial->num_bulk_in) { + /* Start reading from the device */ + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port-> + bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + qt_read_bulk_callback, port); + + port->ReadBulkStopped = 0; + + result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + + if (result) { + err("%s - failed resubmitting read urb, error %d\n", + __func__, result); + port->ReadBulkStopped = 1; + } + + } + + return result; +} + +static void serial_close(struct tty_struct *tty, struct file *filp) +{ + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial = get_usb_serial(port, __func__); + + if (!serial) + return; + + down(&port->sem); + + mydbg("%s - port %d\n", __func__, port->number); + + /* if disconnect beat us to the punch here, there's nothing to do */ + if (tty->driver_data) { + if (!port->open_count) { + mydbg("%s - port not opened\n", __func__); + goto exit; + } + + --port->open_count; + if (port->open_count <= 0) { + port->closePending = 1; + mydbg("%s - port->closePending = 1\n", __func__); + + if (serial->dev) { + qt_close(port, filp); + port->open_count = 0; + } + } + + } + +exit: + up(&port->sem); + + mydbg("%s - %d return\n", __func__, port->number); + +} + +static void qt_close(struct usb_serial_port *port, struct file *filp) +{ + unsigned long jift = jiffies + 10 * HZ; + __u8 LSR_Value, MCR_Value; + struct usb_serial *serial = port->serial; + int status; + unsigned int UartNumber; + + struct qt_open_channel_data ChannelData; + status = 0; + LSR_Value = 0; + + mydbg("%s - port %d\n", __func__, port->number); + UartNumber = port->tty->index - serial->minor; + + /* shutdown any bulk reads that might be going on */ + if (serial->num_bulk_out) + usb_unlink_urb(port->write_urb); + if (serial->num_bulk_in) + usb_unlink_urb(port->read_urb); + + /* wait up to 30 seconds for transmitter to empty */ + do { + status = BoxGetRegister(serial, UartNumber, LINE_STATUS_REGISTER, &LSR_Value); + if (status < 0) { + mydbg(__FILE__ "box_get_device failed\n"); + break; + } + + if ((LSR_Value & SERIAL_LSR_TEMT) + && (port->ReadBulkStopped == 1)) + break; + schedule(); + + } + while (jiffies <= jift) + ; + + if (jiffies > jift) + mydbg("%s - port %d timout of checking transmitter empty\n", + __func__, port->number); + else + mydbg("%s - port %d checking transmitter empty succeded\n", + __func__, port->number); + + status = + BoxGetRegister(serial, UartNumber, MODEM_CONTROL_REGISTER, + &MCR_Value); + mydbg(__FILE__ "BoxGetRegister MCR = 0x%x.\n", MCR_Value); + + if (status >= 0) { + MCR_Value &= ~(SERIAL_MCR_DTR | SERIAL_MCR_RTS); + /* status = BoxSetRegister(serial, UartNumber, MODEM_CONTROL_REGISTER, MCR_Value); */ + } + + /* Close uart channel */ + status = BoxOPenCloseChannel(serial, UartNumber, 0, &ChannelData); + if (status < 0) + mydbg("%s - port %d BoxOPenCloseChannel failed.\n", + __func__, port->number); + + serial->num_OpenCount--; + +} + +static int serial_write(struct tty_struct *tty, const unsigned char *buf, + int count) +{ + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial; + int retval = -EINVAL; + unsigned int UartNumber; + int from_user = 0; + + serial = get_usb_serial(port, __func__); + if (serial == NULL) + return -ENODEV; + /* This can happen if we get disconnected a */ + if (port->open_count == 0) + return -ENODEV; + UartNumber = port->tty->index - serial->minor; + + mydbg("%s - port %d, %d byte(s)\n", __func__, port->number, count); + mydbg("%s - port->RxHolding = %d\n", __func__, port->RxHolding); + + if (!port->open_count) { + mydbg("%s - port not opened\n", __func__); + goto exit; + } + + retval = qt_write(port, from_user, buf, count); + +exit: + return retval; +} + +static int qt_write(struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count) +{ + int result; + unsigned int UartNumber; + + struct usb_serial *serial = get_usb_serial(port, __func__); + if (serial == NULL) + return -ENODEV; + + mydbg("%s - port %d\n", __func__, port->number); + + if (count == 0) { + mydbg("%s - write request of 0 bytes\n", __func__); + return 0; + } + + UartNumber = port->tty->index - serial->minor; + /* only do something if we have a bulk out endpoint */ + if (serial->num_bulk_out) { + if (port->write_urb->status == -EINPROGRESS) { + mydbg("%s - already writing\n", __func__); + return 0; + } + + count = + (count > port->bulk_out_size) ? port->bulk_out_size : count; + + if (from_user) { + if (copy_from_user + (port->write_urb->transfer_buffer, buf, count)) + return -EFAULT; + } else { + memcpy(port->write_urb->transfer_buffer, buf, count); + } + + /* usb_serial_debug_data(__FILE__, __func__, count, port->write_urb->transfer_buffer); */ + + /* set up our urb */ + + usb_fill_bulk_urb(port->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port-> + bulk_out_endpointAddress), + port->write_urb->transfer_buffer, count, + qt_write_bulk_callback, port); + + /* send the data out the bulk port */ + result = usb_submit_urb(port->write_urb, GFP_ATOMIC); + if (result) + mydbg("%s - failed submitting write urb, error %d\n", + __func__, result); + else + result = count; + + return result; + } + + /* no bulk out, so return 0 bytes written */ + return 0; +} + +static void qt_write_bulk_callback(struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial = get_usb_serial(port, __func__); + + mydbg("%s - port %d\n", __func__, port->number); + + if (!serial) { + mydbg("%s - bad serial pointer, exiting\n", __func__); + return; + } + + if (urb->status) { + mydbg("%s - nonzero write bulk status received: %d\n", + __func__, urb->status); + return; + } + port_softint(&port->work); + schedule_work(&port->work); + + return; +} + +static void port_softint(struct work_struct *work) +{ + struct usb_serial_port *port = + container_of(work, struct usb_serial_port, work); + struct usb_serial *serial = get_usb_serial(port, __func__); + struct tty_struct *tty; + + mydbg("%s - port %d\n", __func__, port->number); + + if (!serial) + return; + + tty = port->tty; + if (!tty) + return; +#if 0 + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) + && tty->ldisc.write_wakeup) { + mydbg("%s - write wakeup call.\n", __func__); + (tty->ldisc.write_wakeup) (tty); + } +#endif + + wake_up_interruptible(&tty->write_wait); +} +static int serial_write_room(struct tty_struct *tty) +{ + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial = get_usb_serial(port, __func__); + int retval = -EINVAL; + + if (!serial) + return -ENODEV; + + down(&port->sem); + + mydbg("%s - port %d\n", __func__, port->number); + + if (!port->open_count) { + mydbg("%s - port not open\n", __func__); + goto exit; + } + + retval = qt_write_room(port); + +exit: + up(&port->sem); + return retval; +} +static int qt_write_room(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + int room = 0; + if (port->closePending == 1) { + mydbg("%s - port->closePending == 1\n", __func__); + return -ENODEV; + } + + mydbg("%s - port %d\n", __func__, port->number); + + if (serial->num_bulk_out) { + if (port->write_urb->status != -EINPROGRESS) + room = port->bulk_out_size; + } + + mydbg("%s - returns %d\n", __func__, room); + return room; +} +static int serial_chars_in_buffer(struct tty_struct *tty) +{ + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial = get_usb_serial(port, __func__); + int retval = -EINVAL; + + if (!serial) + return -ENODEV; + + down(&port->sem); + + mydbg("%s = port %d\n", __func__, port->number); + + if (!port->open_count) { + mydbg("%s - port not open\n", __func__); + goto exit; + } + + retval = qt_chars_in_buffer(port); + +exit: + up(&port->sem); + return retval; +} + +static int qt_chars_in_buffer(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + int chars = 0; + + mydbg("%s - port %d\n", __func__, port->number); + + if (serial->num_bulk_out) { + if (port->write_urb->status == -EINPROGRESS) + chars = port->write_urb->transfer_buffer_length; + } + + mydbg("%s - returns %d\n", __func__, chars); + return chars; +} + +static int serial_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial = get_usb_serial(port, __func__); + int retval = -ENODEV; + unsigned int UartNumber; + mydbg("In %s \n", __func__); + + if (!serial) + return -ENODEV; + + UartNumber = port->tty->index - serial->minor; + + down(&port->sem); + + mydbg("%s - port %d \n", __func__, port->number); + mydbg("%s - port->RxHolding = %d\n", __func__, port->RxHolding); + + if (!port->open_count) { + mydbg("%s - port not open\n", __func__); + goto exit; + } + + retval = qt_tiocmset(port, file, set); + +exit: + up(&port->sem); + return retval; +} + +static int qt_tiocmset(struct usb_serial_port *port, struct file *file, + unsigned int value) +{ + + __u8 MCR_Value; + int status; + unsigned int UartNumber; + + struct usb_serial *serial = get_usb_serial(port, __func__); + if (serial == NULL) + return -ENODEV; + + mydbg("%s - port %d\n", __func__, port->number); + + /**************************************************************************************/ + /** TIOCMGET + */ + UartNumber = port->tty->index - serial->minor; + status = + BoxGetRegister(port->serial, UartNumber, MODEM_CONTROL_REGISTER, + &MCR_Value); + if (status < 0) + return -ESPIPE; + + /* + * Turn off the RTS and DTR and loopbcck and then only turn on what was + * asked for + */ + MCR_Value &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP); + if (value & TIOCM_RTS) + MCR_Value |= SERIAL_MCR_RTS; + if (value & TIOCM_DTR) + MCR_Value |= SERIAL_MCR_DTR; + if (value & TIOCM_LOOP) + MCR_Value |= SERIAL_MCR_LOOP; + + status = + BoxSetRegister(port->serial, UartNumber, MODEM_CONTROL_REGISTER, + MCR_Value); + if (status < 0) + return -ESPIPE; + else + return 0; +} + +static int serial_tiocmget(struct tty_struct *tty, struct file *file) +{ + + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + + struct usb_serial *serial = get_usb_serial(port, __func__); + int retval = -ENODEV; + unsigned int UartNumber; + mydbg("In %s \n", __func__); + + if (!serial) + return -ENODEV; + + UartNumber = port->tty->index - serial->minor; + + down(&port->sem); + + mydbg("%s - port %d\n", __func__, port->number); + mydbg("%s - port->RxHolding = %d\n", __func__, port->RxHolding); + + if (!port->open_count) { + mydbg("%s - port not open\n", __func__); + goto exit; + } + + retval = qt_tiocmget(port, file); + +exit: + up(&port->sem); + return retval; +} + +static int qt_tiocmget(struct usb_serial_port *port, struct file *file) +{ + + __u8 MCR_Value; + __u8 MSR_Value; + unsigned int result = 0; + int status; + unsigned int UartNumber; + struct tty_struct *tty; + + struct usb_serial *serial = get_usb_serial(port, __func__); + if (serial == NULL) + return -ENODEV; + tty = port->tty; + + mydbg("%s - port %d, tty =0x%p\n", __func__, port->number, tty); + + /**************************************************************************************/ + /** TIOCMGET + */ + UartNumber = port->tty->index - serial->minor; + status = + BoxGetRegister(port->serial, UartNumber, MODEM_CONTROL_REGISTER, + &MCR_Value); + if (status >= 0) { + status = + BoxGetRegister(port->serial, UartNumber, + MODEM_STATUS_REGISTER, &MSR_Value); + + } + + if (status >= 0) { + result = ((MCR_Value & SERIAL_MCR_DTR) ? TIOCM_DTR : 0) + /* DTR IS SET */ + | ((MCR_Value & SERIAL_MCR_RTS) ? TIOCM_RTS : 0) + /* RTS IS SET */ + | ((MSR_Value & SERIAL_MSR_CTS) ? TIOCM_CTS : 0) + /* CTS is set */ + | ((MSR_Value & SERIAL_MSR_CD) ? TIOCM_CAR : 0) + /* Carrier detect is set */ + | ((MSR_Value & SERIAL_MSR_RI) ? TIOCM_RI : 0) + /* Ring indicator set */ + | ((MSR_Value & SERIAL_MSR_DSR) ? TIOCM_DSR : 0); + /* DSR is set */ + return result; + + } else + return -ESPIPE; +} + +static int serial_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial = get_usb_serial(port, __func__); + int retval = -ENODEV; + unsigned int UartNumber; + mydbg("In %s \n", __func__); + + if (!serial) + return -ENODEV; + + UartNumber = port->tty->index - serial->minor; + + down(&port->sem); + + mydbg("%s - port %d, cmd 0x%.4x\n", __func__, port->number, cmd); + mydbg("%s - port->RxHolding = %d\n", __func__, port->RxHolding); + + if (!port->open_count) { + mydbg("%s - port not open\n", __func__); + goto exit; + } + + retval = qt_ioctl(port, file, cmd, arg); + +exit: + up(&port->sem); + return retval; +} +static int qt_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) +{ + __u8 MCR_Value; + __u8 MSR_Value; + unsigned short Prev_MSR_Value; + unsigned int value, result = 0; + int status; + unsigned int UartNumber; + struct tty_struct *tty; + + struct usb_serial *serial = get_usb_serial(port, __func__); + if (serial == NULL) + return -ENODEV; + tty = port->tty; + + mydbg("%s - port %d, tty =0x%p\n", __func__, port->number, tty); + + /* TIOCMGET */ + UartNumber = port->tty->index - serial->minor; + + if (cmd == TIOCMGET) { + MCR_Value = port->shadowMCR; + MSR_Value = port->shadowMSR; + + { + result = ((MCR_Value & SERIAL_MCR_DTR) ? TIOCM_DTR : 0) + /* DTR IS SET */ + | ((MCR_Value & SERIAL_MCR_RTS) ? TIOCM_RTS : 0) + /* RTS IS SET */ + | ((MSR_Value & SERIAL_MSR_CTS) ? TIOCM_CTS : 0) + /* CTS is set */ + | ((MSR_Value & SERIAL_MSR_CD) ? TIOCM_CAR : 0) + /* Carrier detect is set */ + | ((MSR_Value & SERIAL_MSR_RI) ? TIOCM_RI : 0) + /* Ring indicator set */ + | ((MSR_Value & SERIAL_MSR_DSR) ? TIOCM_DSR : 0); + /* DSR is set */ + if (copy_to_user + ((unsigned int *)arg, &result, + sizeof(unsigned int))) + return -EFAULT; + return 0; + + } + } + + /* TIOCMBIS, TIOCMBIC, AND TIOCMSET */ + if (cmd == TIOCMBIS || cmd == TIOCMBIC || cmd == TIOCMSET) { + status = + BoxGetRegister(port->serial, UartNumber, + MODEM_CONTROL_REGISTER, &MCR_Value); + if (status < 0) + return -ESPIPE; + if (copy_from_user + (&value, (unsigned int *)arg, sizeof(unsigned int))) + return -EFAULT; + + switch (cmd) { + case TIOCMBIS: + if (value & TIOCM_RTS) + MCR_Value |= SERIAL_MCR_RTS; + if (value & TIOCM_DTR) + MCR_Value |= SERIAL_MCR_DTR; + if (value & TIOCM_LOOP) + MCR_Value |= SERIAL_MCR_LOOP; + break; + case TIOCMBIC: + if (value & TIOCM_RTS) + MCR_Value &= ~SERIAL_MCR_RTS; + if (value & TIOCM_DTR) + MCR_Value &= ~SERIAL_MCR_DTR; + if (value & TIOCM_LOOP) + MCR_Value &= ~SERIAL_MCR_LOOP; + break; + case TIOCMSET: + /* + * Turn off the RTS and DTR and loopbcck and then only + * turn on what was asked for + */ + MCR_Value &= + ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | + SERIAL_MCR_LOOP); + if (value & TIOCM_RTS) + MCR_Value |= SERIAL_MCR_RTS; + if (value & TIOCM_DTR) + MCR_Value |= SERIAL_MCR_DTR; + if (value & TIOCM_LOOP) + MCR_Value |= SERIAL_MCR_LOOP; + break; + default: + break; + + } + status = + BoxSetRegister(port->serial, UartNumber, + MODEM_CONTROL_REGISTER, MCR_Value); + if (status < 0) + return -ESPIPE; + else { + port->shadowMCR = MCR_Value; + return 0; + } + + } + /**************************************************************************************/ + /** TIOCMBIS, TIOCMBIC, AND TIOCMSET end + */ + /**************************************************************************************/ + + if (cmd == TIOCMIWAIT) { + DECLARE_WAITQUEUE(wait, current); + Prev_MSR_Value = port->shadowMSR & SERIAL_MSR_MASK; + while (1) { + add_wait_queue(&port->wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + remove_wait_queue(&port->wait, &wait); + /* see if a signal woke us up */ + if (signal_pending(current)) + return -ERESTARTSYS; + MSR_Value = port->shadowMSR & SERIAL_MSR_MASK; + if (MSR_Value == Prev_MSR_Value) + return -EIO; /* no change error */ + + if ((arg & TIOCM_RNG + && ((Prev_MSR_Value & SERIAL_MSR_RI) == + (MSR_Value & SERIAL_MSR_RI))) + || (arg & TIOCM_DSR + && ((Prev_MSR_Value & SERIAL_MSR_DSR) == + (MSR_Value & SERIAL_MSR_DSR))) + || (arg & TIOCM_CD + && ((Prev_MSR_Value & SERIAL_MSR_CD) == + (MSR_Value & SERIAL_MSR_CD))) + || (arg & TIOCM_CTS + && ((Prev_MSR_Value & SERIAL_MSR_CTS) == + (MSR_Value & SERIAL_MSR_CTS)))) { + return 0; + } + + } + + } + mydbg("%s -No ioctl for that one. port = %d\n", __func__, + port->number); + + return -ENOIOCTLCMD; +} + +static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) +{ + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial = get_usb_serial(port, __func__); + + if (!serial) + return; + + down(&port->sem); + + mydbg("%s - port %d\n", __func__, port->number); + + if (!port->open_count) { + mydbg("%s - port not open\n", __func__); + goto exit; + } + + /* pass on to the driver specific version of this function if it is available */ + qt_set_termios(port, old); + +exit: + up(&port->sem); +} + +static void qt_set_termios(struct usb_serial_port *port, + struct ktermios *old_termios) +{ + unsigned int cflag; + int baud, divisor, remainder; + unsigned char LCR_change_to = 0; + struct tty_struct *tty; + int status; + struct usb_serial *serial; + __u16 UartNumber; + __u16 tmp, tmp2; + + mydbg("%s - port %d\n", __func__, port->number); + + tmp = port->tty->index; + mydbg("%s - MINOR(port->tty->index) = %d\n", __func__, tmp); + + serial = port->serial; + tmp2 = serial->minor; + mydbg("%s - serial->minor = %d\n", __func__, tmp2); + + UartNumber = port->tty->index - serial->minor; + + tty = port->tty; + + cflag = tty->termios->c_cflag; + + if (old_termios) { + if ((cflag == old_termios->c_cflag) + && (RELEVANT_IFLAG(tty->termios->c_iflag) == + RELEVANT_IFLAG(old_termios->c_iflag))) { + mydbg("%s - Nothing to change\n", __func__); + return; + } + + } + + mydbg("%s - 3\n", __func__); + + switch (cflag) { + case CS5: + LCR_change_to |= SERIAL_5_DATA; + break; + case CS6: + LCR_change_to |= SERIAL_6_DATA; + break; + case CS7: + LCR_change_to |= SERIAL_7_DATA; + break; + default: + case CS8: + LCR_change_to |= SERIAL_8_DATA; + break; + } + + /* Parity stuff */ + if (cflag & PARENB) { + if (cflag & PARODD) + LCR_change_to |= SERIAL_ODD_PARITY; + else + LCR_change_to |= SERIAL_EVEN_PARITY; + } + if (cflag & CSTOPB) + LCR_change_to |= SERIAL_TWO_STOPB; + else + LCR_change_to |= SERIAL_TWO_STOPB; + + mydbg("%s - 4\n", __func__); + /* Thats the LCR stuff, go ahead and set it */ + baud = tty_get_baud_rate(tty); + if (!baud) { + /* pick a default, any default... */ + baud = 9600; + } + + mydbg("%s - got baud = %d\n", __func__, baud); + + divisor = MAX_BAUD_RATE / baud; + remainder = MAX_BAUD_RATE % baud; + /* Round to nearest divisor */ + if (((remainder * 2) >= baud) && (baud != 110)) + divisor++; + + /* + * Set Baud rate to default and turn off (default)flow control here + */ + status = + BoxSetUart(serial, UartNumber, (unsigned short)divisor, + LCR_change_to); + if (status < 0) { + mydbg(__FILE__ "BoxSetUart failed\n"); + return; + } + + /* Now determine flow control */ + if (cflag & CRTSCTS) { + mydbg("%s - Enabling HW flow control port %d\n", __func__, + port->number); + + /* Enable RTS/CTS flow control */ + status = BoxSetHW_FlowCtrl(serial, UartNumber, 1); + + if (status < 0) { + mydbg(__FILE__ "BoxSetHW_FlowCtrl failed\n"); + return; + } + } else { + /* Disable RTS/CTS flow control */ + mydbg("%s - disabling HW flow control port %d\n", __func__, + port->number); + + status = BoxSetHW_FlowCtrl(serial, UartNumber, 0); + if (status < 0) { + mydbg(__FILE__ "BoxSetHW_FlowCtrl failed\n"); + return; + } + + } + + /* if we are implementing XON/XOFF, set the start and stop character in + * the device */ + if (I_IXOFF(tty) || I_IXON(tty)) { + unsigned char stop_char = STOP_CHAR(tty); + unsigned char start_char = START_CHAR(tty); + status = + BoxSetSW_FlowCtrl(serial, UartNumber, stop_char, + start_char); + if (status < 0) + mydbg(__FILE__ "BoxSetSW_FlowCtrl (enabled) failed\n"); + + } else { + /* disable SW flow control */ + status = BoxDisable_SW_FlowCtrl(serial, UartNumber); + if (status < 0) + mydbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n"); + + } + +} + +/**************************************************************************** +* BoxGetRegister +* issuse a GET_REGISTER vendor-spcific request on the default control pipe +* If successful, fills in the pValue with the register value asked for +****************************************************************************/ +static int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number, + unsigned short Register_Num, __u8 *pValue) +{ + int result; + __u16 current_length; + + current_length = sizeof(struct qt_get_device_data); + + result = + usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + QT_GET_SET_REGISTER, 0xC0, Register_Num, + Uart_Number, (void *)pValue, sizeof(*pValue), 300); + + return result; +} + +/**************************************************************************** +* BoxSetRegister +* issuse a GET_REGISTER vendor-spcific request on the default control pipe +* If successful, fills in the pValue with the register value asked for +****************************************************************************/ +static int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number, + unsigned short Register_Num, unsigned short Value) +{ + int result; + unsigned short RegAndByte; + + RegAndByte = Value; + RegAndByte = RegAndByte << 8; + RegAndByte = RegAndByte + Register_Num; + +/* + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_GET_SET_REGISTER, 0xC0, Register_Num, + Uart_Number, NULL, 0, 300); +*/ + + result = + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_GET_SET_REGISTER, 0x40, RegAndByte, Uart_Number, + NULL, 0, 300); + + return result; +} + +/** + * box_get_device + * Issue a GET_DEVICE vendor-specific request on the default control pipe If + * successful, fills in the qt_get_device_data structure pointed to by + * device_data, otherwise return a negative error number of the problem. + */ +static int box_get_device(struct usb_serial *serial, + struct qt_get_device_data *device_data) +{ + int result; + __u16 current_length; + unsigned char *transfer_buffer; + + current_length = sizeof(struct qt_get_device_data); + transfer_buffer = kmalloc(current_length, GFP_KERNEL); + if (!transfer_buffer) + return -ENOMEM; + + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + QT_SET_GET_DEVICE, 0xc0, 0, 0, + transfer_buffer, current_length, 300); + if (result > 0) + memcpy(device_data, transfer_buffer, current_length); + kfree(transfer_buffer); + + return result; +} + +/** + * box_set_device + * Issue a SET_DEVICE vendor-specific request on the default control pipe If + * successful returns the number of bytes written, otherwise it returns a + * negative error number of the problem. + */ +static int box_set_device(struct usb_serial *serial, + struct qt_get_device_data *device_data) +{ + int result; + __u16 length; + __u16 PortSettings; + + PortSettings = ((__u16) (device_data->portb)); + PortSettings = (PortSettings << 8); + PortSettings += ((__u16) (device_data->porta)); + + length = sizeof(struct qt_get_device_data); + mydbg("%s - PortSettings = 0x%x\n", __func__, PortSettings); + + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_SET_GET_DEVICE, 0x40, PortSettings, + 0, NULL, 0, 300); + return result; +} + +/**************************************************************************** + * BoxOPenCloseChannel + * This funciotn notifies the device that the device driver wishes to open a particular UART channel. its + * purpose is to allow the device driver and the device to synchronize state information. + * OpenClose = 1 for open , 0 for close + ****************************************************************************/ +static int BoxOPenCloseChannel(struct usb_serial *serial, __u16 Uart_Number, + __u16 OpenClose, + struct qt_open_channel_data *pDeviceData) +{ + int result; + __u16 length; + __u8 Direcion; + unsigned int pipe; + length = sizeof(struct qt_open_channel_data); + + /* if opening... */ + if (OpenClose == 1) { + Direcion = USBD_TRANSFER_DIRECTION_IN; + pipe = usb_rcvctrlpipe(serial->dev, 0); + result = + usb_control_msg(serial->dev, pipe, QT_OPEN_CLOSE_CHANNEL, + Direcion, OpenClose, Uart_Number, + pDeviceData, length, 300); + + } else { + Direcion = USBD_TRANSFER_DIRECTION_OUT; + pipe = usb_sndctrlpipe(serial->dev, 0); + result = + usb_control_msg(serial->dev, pipe, QT_OPEN_CLOSE_CHANNEL, + Direcion, OpenClose, Uart_Number, NULL, 0, + 300); + + } + + return result; +} + +/**************************************************************************** + * BoxSetPrebufferLevel + TELLS BOX WHEN TO ASSERT FLOW CONTROL + ****************************************************************************/ +static int BoxSetPrebufferLevel(struct usb_serial *serial) +{ + int result; + __u16 buffer_length; + + buffer_length = PREFUFF_LEVEL_CONSERVATIVE; + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_GET_SET_PREBUF_TRIG_LVL, 0x40, + buffer_length, 0, NULL, 0, 300); + return result; +} + +/**************************************************************************** + * BoxSetATC + TELLS BOX WHEN TO ASSERT automatic transmitter control + ****************************************************************************/ +static int BoxSetATC(struct usb_serial *serial, __u16 n_Mode) +{ + int result; + __u16 buffer_length; + + buffer_length = PREFUFF_LEVEL_CONSERVATIVE; + + result = + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_SET_ATF, 0x40, n_Mode, 0, NULL, 0, 300); + + return result; +} + +/**************************************************************************** +* BoxSetUart +* issuse a SET_UART vendor-spcific request on the default control pipe +* If successful sets baud rate divisor and LCR value +****************************************************************************/ +static int BoxSetUart(struct usb_serial *serial, unsigned short Uart_Number, + unsigned short default_divisor, unsigned char default_LCR) +{ + int result; + unsigned short UartNumandLCR; + + UartNumandLCR = (default_LCR << 8) + Uart_Number; + + result = + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_GET_SET_UART, 0x40, default_divisor, + UartNumandLCR, NULL, 0, 300); + + return result; +} + +static int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int UartNumber, + int bSet) +{ + __u8 MCR_Value = 0; + __u8 MSR_Value = 0, MOUT_Value = 0; + struct usb_serial_port *port; + unsigned int status; + + port = serial->port; + + if (bSet == 1) { + /* flow control, box will clear RTS line to prevent remote */ + MCR_Value = SERIAL_MCR_RTS; + } /* device from xmitting more chars */ + else { + /* no flow control to remote device */ + MCR_Value = 0; + + } + MOUT_Value = MCR_Value << 8; + + if (bSet == 1) { + /* flow control, box will inhibit xmit data if CTS line is + * asserted */ + MSR_Value = SERIAL_MSR_CTS; + } else { + /* Box will not inhimbe xmit data due to CTS line */ + MSR_Value = 0; + } + MOUT_Value |= MSR_Value; + + status = + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_HW_FLOW_CONTROL_MASK, 0x40, MOUT_Value, + UartNumber, NULL, 0, 300); + return status; + +} + +static int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 UartNumber, + unsigned char stop_char, unsigned char start_char) +{ + __u16 nSWflowout; + int result; + + nSWflowout = start_char << 8; + nSWflowout = (unsigned short)stop_char; + + result = + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_SW_FLOW_CONTROL_MASK, 0x40, nSWflowout, + UartNumber, NULL, 0, 300); + return result; + +} +static int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 UartNumber) +{ + int result; + + result = + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_SW_FLOW_CONTROL_DISABLE, 0x40, 0, UartNumber, + NULL, 0, 300); + return result; + +} + +static void serial_throttle(struct tty_struct *tty) +{ + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial = get_usb_serial(port, __func__); + mydbg("%s - port %d\n", __func__, port->number); + + if (!serial) + return; + + down(&port->sem); + + if (!port->open_count) { + mydbg("%s - port not open\n", __func__); + goto exit; + } + /* shut down any bulk reads that may be going on */ +/* usb_unlink_urb (port->read_urb); */ + /* pass on to the driver specific version of this function */ + port->RxHolding = 1; + mydbg("%s - port->RxHolding = 1\n", __func__); + +exit: + up(&port->sem); + return; +} + +static void serial_unthrottle(struct tty_struct *tty) +{ + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial = get_usb_serial(port, __func__); + unsigned int result; + + if (!serial) + return; + down(&port->sem); + + mydbg("%s - port %d\n", __func__, port->number); + + if (!port->open_count) { + mydbg("%s - port not open\n", __func__); + goto exit; + } + + if (port->RxHolding == 1) { + mydbg("%s -port->RxHolding == 1\n", __func__); + + port->RxHolding = 0; + mydbg("%s - port->RxHolding = 0\n", __func__); + + /* if we have a bulk endpoint, start it up */ + if ((serial->num_bulk_in) && (port->ReadBulkStopped == 1)) { + /* Start reading from the device */ + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port-> + bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb-> + transfer_buffer_length, + qt_read_bulk_callback, port); + result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (result) + err("%s - failed restarting read urb, error %d", + __func__, result); + } + } +exit: + up(&port->sem); + return; + +} + +static int serial_break(struct tty_struct *tty, int break_state) +{ + struct usb_serial_port *port = + (struct usb_serial_port *)tty->driver_data; + struct usb_serial *serial = get_usb_serial(port, __func__); + __u16 UartNumber, Break_Value; + unsigned int result; + + UartNumber = port->tty->index - serial->minor; + if (!serial) + return -ENODEV; + + if (break_state == -1) + Break_Value = 1; + else + Break_Value = 0; + + down(&port->sem); + + mydbg("%s - port %d\n", __func__, port->number); + + if (!port->open_count) { + mydbg("%s - port not open\n", __func__); + goto exit; + } + + result = + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + QT_BREAK_CONTROL, 0x40, Break_Value, UartNumber, + NULL, 0, 300); + +exit: + up(&port->sem); + return 0; +} + +static int ioctl_serial_usb(struct inode *innod, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + + unsigned err; + unsigned ucOPR_NewValue, uc_Value; + int *p_Num_of_adapters, counts, index, *p_QMCR_Value; + struct identity *p_Identity_of; + struct identity Identity_of; + struct usb_serial *lastserial, *serial; + + mydbg(KERN_DEBUG "ioctl_serial_usb cmd =\n"); + if (_IOC_TYPE(cmd) != SERIALQT_PCI_IOC_MAGIC) + return -ENOTTY; + if (_IOC_NR(cmd) > SERIALQT_IOC_MAXNR) + return -ENOTTY; + mydbg(KERN_DEBUG "ioctl_serial_usb cmd = 0x%x\n", cmd); + err = 0; + switch (cmd) { + + case SERIALQT_WRITE_QMCR: + err = -ENOTTY; + index = arg >> 16; + counts = 0; + + ucOPR_NewValue = arg; + + err = EmulateWriteQMCR_Reg(index, ucOPR_NewValue); + break; + + case SERIALQT_READ_QMCR: + err = -ENOTTY; + p_QMCR_Value = (int *)arg; + index = arg >> 16; + counts = 0; + + err = EmulateReadQMCR_Reg(index, &uc_Value); + if (err == 0) + err = put_user(uc_Value, p_QMCR_Value); + break; + + case SERIALQT_GET_NUMOF_UNITS: + p_Num_of_adapters = (int *)arg; + counts = 0; /* Initialize counts to zero */ + /* struct usb_serial *lastserial = serial_table[0], *serial; */ + lastserial = serial_table[0]; + + mydbg(KERN_DEBUG "SERIALQT_GET_NUMOF_UNITS \n"); + /* if first pointer is nonull, we at least have one box */ + if (lastserial) + counts = 1; /* we at least have one box */ + + for (index = 1; index < SERIAL_TTY_MINORS; index++) { + serial = serial_table[index]; + if (serial) { + if (serial != lastserial) { + /* we had a change in the array, hence + * another box is there */ + lastserial = serial; + counts++; + } + } else + break; + } + + mydbg(KERN_DEBUG "ioctl_serial_usb writting counts = %d", + counts); + + err = put_user(counts, p_Num_of_adapters); + + break; + case SERIALQT_GET_THIS_UNIT: + counts = 0; + p_Identity_of = (struct identity *)arg; + /* copy user structure to local variable */ + get_user(Identity_of.index, &p_Identity_of->index); + mydbg(KERN_DEBUG "SERIALQT_GET_THIS_UNIT Identity_of.index\n"); + mydbg(KERN_DEBUG + "SERIALQT_GET_THIS_UNIT Identity_of.index= 0x%x\n", + Identity_of.index); + + err = -ENOTTY; + serial = find_the_box(Identity_of.index); + if (serial) { + err = + put_user(serial->product, + &p_Identity_of->n_identity); + + } + break; + + case SERIALQT_IS422_EXTENDED: + err = -ENOTTY; + mydbg(KERN_DEBUG "SERIALQT_IS422_EXTENDED \n"); + index = arg >> 16; + + counts = 0; + + mydbg(KERN_DEBUG + "SERIALQT_IS422_EXTENDED, looking Identity_of.indext = 0x%x\n", + index); + serial = find_the_box(index); + if (serial) { + mydbg("%s index = 0x%x, serial = 0x%p\n", __func__, + index, serial); + for (counts = 0; serqt_422_table[counts] != 0; counts++) { + + mydbg + ("%s serial->product = = 0x%x, serqt_422_table[counts] = 0x%x\n", + __func__, serial->product, + serqt_422_table[counts]); + if (serial->product == serqt_422_table[counts]) { + err = 0; + + mydbg + ("%s found match for 422extended\n", + __func__); + break; + } + } + } + break; + + default: + err = -ENOTTY; + } + + mydbg("%s returning err = 0x%x\n", __func__, err); + return err; +} + +static struct usb_serial *find_the_box(unsigned int index) +{ + struct usb_serial *lastserial, *foundserial, *serial; + int counts = 0, index2; + lastserial = serial_table[0]; + foundserial = NULL; + for (index2 = 0; index2 < SERIAL_TTY_MINORS; index2++) { + serial = serial_table[index2]; + + mydbg("%s index = 0x%x, index2 = 0x%x, serial = 0x%p\n", + __func__, index, index2, serial); + + if (serial) { + /* first see if this is the unit we'er looking for */ + mydbg + ("%s inside if(serial) counts = 0x%x , index = 0x%x\n", + __func__, counts, index); + if (counts == index) { + /* we found the one we're looking for, copythe + * product Id to user */ + mydbg("%s we found the one we're looking for serial = 0x%p\n", + __func__, serial); + foundserial = serial; + break; + } + + if (serial != lastserial) { + /* when we have a change in the pointer */ + lastserial = serial; + counts++; + } + } else + break; /* no matches */ + } + + mydbg("%s returning foundserial = 0x%p\n", __func__, foundserial); + return foundserial; +} + +static int EmulateWriteQMCR_Reg(int index, unsigned uc_value) +{ + + __u16 ATC_Mode = 0; + struct usb_serial *serial; + int status; + struct qt_get_device_data DeviceData; + unsigned uc_temp = 0; + mydbg("Inside %s, uc_value = 0x%x\n", __func__, uc_value); + + DeviceData.porta = 0; + DeviceData.portb = 0; + serial = find_the_box(index); + /* Determine Duplex mode */ + if (!(serial)) + return -ENOTTY; + status = box_get_device(serial, &DeviceData); + if (status < 0) { + mydbg(__FILE__ "box_set_device failed\n"); + return status; + } + + uc_temp = uc_value & QMCR_HALF_DUPLEX_MASK; + switch (uc_temp) { + case QMCR_FULL_DUPLEX: + DeviceData.porta &= ~DUPMODE_BITS; + DeviceData.porta |= FULL_DUPLEX; + ATC_Mode = ATC_DISABLED; + break; + case QMCR_HALF_DUPLEX_RTS: + DeviceData.porta &= ~DUPMODE_BITS; + DeviceData.porta |= HALF_DUPLEX_RTS; + ATC_Mode = ATC_RTS_ENABLED; + break; + case QMCR_HALF_DUPLEX_DTR: + DeviceData.porta &= ~DUPMODE_BITS; + DeviceData.porta |= HALF_DUPLEX_DTR; + ATC_Mode = ATC_DTR_ENABLED; + break; + default: + break; + } + + uc_temp = uc_value & QMCR_CONNECTOR_MASK; + switch (uc_temp) { + case QMCR_MODEM_CONTROL: + DeviceData.portb &= ~LOOPMODE_BITS; /* reset connection bits */ + DeviceData.portb |= MODEM_CTRL; + break; + case QMCR_ALL_LOOPBACK: + DeviceData.portb &= ~LOOPMODE_BITS; /* reset connection bits */ + DeviceData.portb |= ALL_LOOPBACK; + break; + } + + mydbg(__FILE__ "Calling box_set_device with failed\n"); + status = box_set_device(serial, &DeviceData); + if (status < 0) { + mydbg(__FILE__ "box_set_device failed\n"); + return status; + } + + /* This bit (otherwise unused) i'll used to detect whether ATC is + * selected */ + if (uc_value & QMCR_RX_EN_MASK) { + + mydbg(__FILE__ + "calling BoxsetATC with DeviceData.porta = 0x%x and DeviceData.portb = 0x%x\n", + DeviceData.porta, DeviceData.portb); + status = BoxSetATC(serial, ATC_Mode); + if (status < 0) { + mydbg(__FILE__ "BoxSetATC failed\n"); + return status; + } + } else { + + mydbg(__FILE__ + "calling BoxsetATC with DeviceData.porta = 0x%x and DeviceData.portb = 0x%x\n", + DeviceData.porta, DeviceData.portb); + status = BoxSetATC(serial, ATC_DISABLED); + if (status < 0) { + mydbg(__FILE__ "BoxSetATC failed\n"); + return status; + } + } + + return 0; + +} + +static int EmulateReadQMCR_Reg(int index, unsigned *uc_value) +{ + struct usb_serial *serial; + int status; + struct qt_get_device_data DeviceData; + __u8 uc_temp; + + *uc_value = 0; + + serial = find_the_box(index); + if (!(serial)) + return -ENOTTY; + + status = box_get_device(serial, &DeviceData); + if (status < 0) { + mydbg(__FILE__ "box_get_device failed\n"); + return status; + } + uc_temp = DeviceData.porta & DUPMODE_BITS; + switch (uc_temp) { + case FULL_DUPLEX: + *uc_value |= QMCR_FULL_DUPLEX; + break; + case HALF_DUPLEX_RTS: + *uc_value |= QMCR_HALF_DUPLEX_RTS; + break; + case HALF_DUPLEX_DTR: + *uc_value |= QMCR_HALF_DUPLEX_DTR; + break; + default: + break; + } + + /* I use this for ATC control se */ + uc_temp = DeviceData.portb & LOOPMODE_BITS; + + switch (uc_temp) { + case ALL_LOOPBACK: + *uc_value |= QMCR_ALL_LOOPBACK; + break; + case MODEM_CTRL: + *uc_value |= QMCR_MODEM_CONTROL; + break; + default: + break; + + } + return 0; + +} + +static int __init serqt_usb_init(void) +{ + int i, result; + int status = 0; + + mydbg("%s\n", __func__); + tty_set_operations(&serial_tty_driver, &serial_ops); + result = tty_register_driver(&serial_tty_driver); + if (result) { + mydbg("tty_register_driver failed error = 0x%x", result); + return result; + } + + /* Initalize our global data */ + for (i = 0; i < SERIAL_TTY_MINORS; ++i) + serial_table[i] = NULL; + + /* register this driver with the USB subsystem */ + result = usb_register(&serqt_usb_driver); + if (result < 0) { + err("usb_register failed for the " __FILE__ + " driver. Error number %d", result); + return result; + } + status = 0; /* Dynamic assignment of major number */ + major_number = + register_chrdev(status, "SerialQT_USB", &serialqt_usb_fops); + if (major_number < 0) { + mydbg(KERN_DEBUG "No devices found \n\n"); + return -EBUSY; + } else + mydbg(KERN_DEBUG "SerQT_USB major number assignment = %d \n\n", + major_number); + + printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION); + return 0; +} + +static void __exit serqt_usb_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&serqt_usb_driver); + tty_unregister_driver(&serial_tty_driver); + unregister_chrdev(major_number, "SerialQT_USB"); +} + +module_init(serqt_usb_init); +module_exit(serqt_usb_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/slicoss/gbdownload.h b/drivers/staging/slicoss/gbdownload.h deleted file mode 100644 index 794432bd1d77..000000000000 --- a/drivers/staging/slicoss/gbdownload.h +++ /dev/null @@ -1,8215 +0,0 @@ -#define MOJAVE_UCODE_VERS_STRING "1.2" -#define MOJAVE_UCODE_VERS_DATE "2006/03/27 15:12:22" -#define MOJAVE_UCODE_HOSTIF_ID 3 - -static s32 MNumSections = 0x2; -static u32 MSectionSize[] = -{ - 0x00008000, 0x00010000, -}; - -static u32 MSectionStart[] = -{ - 0x00000000, 0x00008000, -}; - -static u8 MojaveUCode[2][65536] = -{ - { - 0x12, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, - 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0xa2, 0x40, 0xfd, 0x7f, 0x00, 0x00, - 0x09, 0x00, 0xa2, 0x49, 0xdd, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x80, 0xb2, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x80, 0xb2, 0x01, 0x00, 0x09, 0x00, 0xa2, 0x40, - 0x75, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x0b, 0x00, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x11, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x80, 0x1f, 0xe9, 0x18, 0x31, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe9, - 0x80, 0xb2, 0x01, 0x00, 0x0f, 0x00, 0x40, 0xe9, 0x80, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x16, 0x00, 0x29, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x16, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x0f, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x1c, 0x00, 0x29, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1c, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x11, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x22, 0x00, 0x29, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x22, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x0e, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xdd, 0x81, 0x01, 0x00, 0x2b, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x3c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x27, 0x00, 0x14, 0xbc, - 0x80, 0x32, 0x00, 0x00, 0x14, 0x01, 0x13, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x54, 0x95, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0xb7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb5, 0xb3, 0x01, 0x00, - 0xd9, 0x00, 0x00, 0x40, 0xb3, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xb6, 0xd3, 0x01, 0x00, 0x32, 0x00, 0x95, 0xe8, 0x80, 0x32, 0x00, 0x00, - 0xff, 0xff, 0x00, 0xe8, 0x80, 0x88, 0x01, 0x00, 0xb8, 0x00, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfd, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xff, 0xb3, 0x01, 0x00, 0x3c, 0x00, 0x22, 0x50, - 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xfd, 0x93, 0x01, 0x00, - 0xa5, 0xa5, 0x00, 0xa6, 0xb4, 0xa7, 0x01, 0x00, 0x3c, 0x00, 0xa2, 0x50, - 0xb5, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x3c, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0xfd, 0x93, 0x01, 0x00, 0x41, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x7f, 0x00, 0x00, 0x20, 0xf5, 0xcf, 0x01, 0x00, 0x1c, 0x01, 0x00, 0xfa, - 0xb3, 0x33, 0x01, 0x00, 0xa5, 0xa5, 0x00, 0xda, 0xb5, 0xab, 0x01, 0x00, - 0x99, 0x00, 0xa2, 0x50, 0xb5, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xfd, 0x93, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x44, 0xb3, 0x33, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xd7, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda, 0xed, 0x8b, 0x01, 0x00, - 0xd5, 0x00, 0x00, 0x46, 0xb3, 0x33, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, - 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xd7, 0xb1, 0x01, 0x00, - 0xff, 0x00, 0x00, 0xda, 0xef, 0x8b, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda, - 0xe3, 0x8f, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x48, 0xb3, 0x33, 0x01, 0x00, - 0x3c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda, - 0xd7, 0x8d, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda, 0xf1, 0xdb, 0x01, 0x00, - 0xff, 0x00, 0x00, 0xda, 0xe9, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xe9, 0xe3, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x4b, 0xb3, 0x33, 0x01, 0x00, - 0x2c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xd7, 0xb1, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x4c, 0xb3, 0x33, 0x01, 0x00, - 0xff, 0xff, 0x00, 0xda, 0xeb, 0xdb, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x4e, - 0xb3, 0x33, 0x01, 0x00, 0x03, 0x00, 0x00, 0xda, 0x81, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x81, 0xe0, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda, - 0xb5, 0xdb, 0x01, 0x00, 0x5c, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x01, 0x00, 0x00, 0xda, 0xb5, 0xcf, 0x01, 0x00, 0x00, 0xf0, 0x00, 0xa7, - 0xb4, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0x81, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd8, 0xb1, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x50, - 0xb3, 0x33, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda, 0xb5, 0x8b, 0x01, 0x00, - 0x62, 0x00, 0x26, 0x4c, 0xb5, 0x63, 0x00, 0x00, 0x01, 0x00, 0x00, 0xda, - 0xb5, 0xcf, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xdf, 0xb1, 0x01, 0x00, - 0xd5, 0x00, 0x00, 0x52, 0xb3, 0x33, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda, - 0x4b, 0x89, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xdf, 0xf7, 0x01, 0x00, - 0xff, 0x00, 0x00, 0xef, 0xdf, 0x8b, 0x01, 0x00, 0x69, 0x00, 0x22, 0x40, - 0xdf, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xfd, 0x93, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xda, 0xd7, 0xe5, 0x01, 0x00, 0xf8, 0x00, 0x00, 0xda, - 0xb3, 0x8b, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd9, 0xd7, 0xb1, 0x01, 0x00, 0x02, 0x00, 0x00, 0xd9, - 0xd5, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xd7, 0xb1, 0x01, 0x00, - 0x22, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb5, 0xf3, 0x01, 0x00, - 0x03, 0x00, 0x00, 0xda, 0x7b, 0x89, 0x01, 0x00, 0x00, 0x01, 0x00, 0x40, - 0xdd, 0x9b, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x5d, 0xb3, 0x33, 0x01, 0x00, - 0xff, 0xff, 0x00, 0xda, 0xe7, 0x8b, 0x01, 0x00, 0x8a, 0x00, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfd, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xe7, 0xe3, 0x01, 0x00, 0x00, 0x01, 0x00, 0x40, - 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xe7, 0x97, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0xd7, 0xb1, 0x01, 0x00, 0xd5, 0x00, 0x00, 0x5e, - 0xb3, 0x33, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda, 0xe5, 0x8b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xe5, 0xe3, 0x01, 0x00, 0x08, 0x01, 0x00, 0x40, - 0xd5, 0x99, 0x01, 0x00, 0xff, 0x00, 0x00, 0xda, 0xb5, 0x8f, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf7, 0xb5, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xd7, 0xb1, 0x01, 0x00, 0x3c, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xe5, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0xd7, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0xdd, 0x9b, 0x01, 0x00, - 0x96, 0x00, 0x22, 0xf5, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, 0xd5, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf6, 0xeb, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf5, - 0xd7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xea, 0xd4, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf7, 0xe3, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf1, - 0xd7, 0xb1, 0x01, 0x00, 0x3c, 0x00, 0x00, 0xee, 0xdd, 0xcb, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xee, 0xd5, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xe9, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0xd7, 0xb1, 0x01, 0x00, - 0xd5, 0x00, 0x00, 0x4a, 0xb3, 0x33, 0x01, 0x00, 0xff, 0xff, 0x00, 0xda, - 0xdd, 0x89, 0x01, 0x00, 0xb7, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0xa6, - 0xd6, 0xb1, 0x01, 0x00, 0x9a, 0x13, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa6, - 0xd6, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00, - 0x2c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0xa6, - 0xd6, 0xb1, 0x01, 0x00, 0x9a, 0x13, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00, - 0x3c, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, - 0xd7, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0x93, 0x01, 0x00, - 0x3c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa6, - 0xd6, 0xb1, 0x01, 0x00, 0x00, 0x01, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x06, 0x00, 0x00, 0xa6, - 0xd6, 0xb1, 0x01, 0x00, 0x9a, 0x13, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00, - 0x08, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa6, - 0xd6, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xeb, 0xd6, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xdf, 0xb1, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa6, 0xd6, 0xb1, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40, - 0x4b, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7b, 0x99, 0x01, 0x00, - 0x02, 0x04, 0x00, 0x40, 0xdd, 0x99, 0x01, 0x00, 0xb7, 0x00, 0x13, 0xbc, - 0x80, 0x32, 0x00, 0x00, 0x02, 0x08, 0x00, 0x40, 0xdd, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0xdd, 0x91, 0x01, 0x00, 0xb8, 0x00, 0x95, 0xe8, - 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xe9, 0xfa, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0x42, - 0x80, 0x88, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, - 0xb8, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x02, 0x80, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, - 0xb8, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x81, 0xb0, 0x01, 0x00, 0xca, 0x00, 0x09, 0xf9, 0x81, 0x32, 0x00, 0x00, - 0xc8, 0x00, 0x08, 0xf9, 0x81, 0x32, 0x00, 0x00, 0xd4, 0x00, 0x1f, 0xfd, - 0xf9, 0x33, 0x00, 0x00, 0xc7, 0x00, 0x9e, 0xfd, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, - 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf7, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x49, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x19, 0xb1, 0x01, 0x00, 0xcf, 0x00, 0x0a, 0xf9, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x40, 0xfb, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xfd, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x07, 0x80, 0xf9, 0xf3, 0x8f, 0x01, 0x00, - 0x00, 0x07, 0x42, 0xf9, 0xf3, 0x8f, 0x01, 0x00, 0xd3, 0x00, 0xa2, 0xff, - 0xf7, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0xff, 0xfb, 0xef, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfc, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0xd8, 0x00, 0x06, 0xfe, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xb3, 0xe3, 0x01, 0x00, 0x1c, 0x01, 0x00, 0xfa, 0xb3, 0xc3, 0x00, 0x00, - 0xda, 0x00, 0x00, 0x42, 0x8d, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0xeb, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x84, 0x96, 0x80, 0xb2, 0x00, 0x00, - 0x26, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40, - 0x2d, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0x81, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xb5, 0xeb, 0x01, 0x00, 0xe4, 0x00, 0x84, 0x96, - 0x80, 0x32, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x40, 0xb5, 0x93, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xb5, 0x83, 0x01, 0x00, 0xde, 0x00, 0xa2, 0x41, - 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x2d, 0x81, 0x01, 0x00, - 0x26, 0x01, 0x00, 0x41, 0x2d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xb3, 0xc3, 0x01, 0x00, 0xda, 0x00, 0xa2, 0x41, 0x8d, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xda, 0xb5, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x81, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd9, 0xb9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xb8, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xb9, 0xeb, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xb8, 0x97, 0x01, 0x00, 0x15, 0x00, 0x00, 0xdc, - 0xb9, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2d, 0x81, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xdb, 0x81, 0xb0, 0x01, 0x00, 0x27, 0x01, 0x00, 0x42, - 0x2d, 0x11, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40, 0x2d, 0x11, 0x01, 0x00, - 0x28, 0x01, 0x00, 0x40, 0x2d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x2d, 0x91, 0x01, 0x00, 0x26, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x25, 0x01, 0x00, 0x40, 0x2d, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x2d, 0x81, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x81, 0xd0, 0x00, 0x00, - 0x00, 0x00, 0x84, 0x96, 0x80, 0x32, 0x01, 0x00, 0xff, 0x00, 0xa0, 0xdc, - 0xb9, 0x6b, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x41, 0x2d, 0x91, 0x00, 0x00, - 0xf8, 0x00, 0x00, 0x41, 0x2d, 0x81, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x40, - 0xb3, 0x33, 0x01, 0x00, 0x00, 0x00, 0x90, 0xda, 0x8b, 0xb0, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00, 0x40, 0x00, 0x00, 0x44, - 0x80, 0xce, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0xa3, 0x44, 0x89, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x89, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0xb0, 0x01, 0x00, - 0xd9, 0x00, 0x00, 0x43, 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xb5, 0xf3, 0x01, 0x00, 0x0c, 0x01, 0xa0, 0xda, 0x8b, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x87, 0xc0, 0x01, 0x00, 0x08, 0x01, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x45, 0x88, 0x88, 0x01, 0x00, 0x10, 0x00, 0x00, 0x45, - 0x8a, 0xf4, 0x01, 0x00, 0x12, 0x01, 0x90, 0x44, 0x8a, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, 0xff, 0xff, 0x00, 0x45, - 0x8a, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x50, 0x8b, 0xe0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x40, 0xf9, 0x9b, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x40, - 0xb3, 0xcf, 0x01, 0x00, 0x1c, 0x01, 0x00, 0xfc, 0x19, 0x31, 0x01, 0x00, - 0x1c, 0x01, 0x40, 0xda, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x41, 0xda, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf9, 0xc3, 0x01, 0x00, - 0x16, 0x01, 0x9f, 0xda, 0x81, 0x32, 0x00, 0x00, 0x02, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x91, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00, 0x1e, 0x01, 0x9f, 0x94, - 0x80, 0x32, 0x00, 0x00, 0x18, 0x00, 0x00, 0x94, 0x92, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xb5, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xb4, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xb3, 0xc3, 0x01, 0x00, - 0x1d, 0x01, 0xa2, 0x41, 0x91, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x2b, 0xb1, 0x01, 0x00, 0x29, 0x01, 0x00, 0x51, 0x93, 0xb0, 0x00, 0x00, - 0x29, 0x01, 0x00, 0x4d, 0x93, 0xb0, 0x00, 0x00, 0x29, 0x01, 0x00, 0x49, - 0x93, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x93, 0xb0, 0x01, 0x00, - 0x29, 0x01, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x11, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x12, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x13, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x14, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x15, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x16, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x17, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x18, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x19, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x1d, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa1, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x19, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x15, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0b, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x07, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x01, 0xb0, 0x01, 0x00, 0x44, 0x01, 0x20, 0x48, 0xa1, 0x51, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x50, 0x01, 0x22, 0x4b, - 0x74, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x60, 0x00, 0x00, 0x4b, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1, - 0x7e, 0xb1, 0x01, 0x00, 0x51, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x4e, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x80, 0x40, - 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, 0x07, 0x90, 0x01, 0x00, - 0xf3, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xa5, 0xb3, 0x01, 0x00, 0xaf, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x07, 0x90, 0x01, 0x00, 0xf3, 0x9f, 0x00, 0x40, 0xbf, 0xb3, 0x00, 0x00, - 0x5f, 0x01, 0x22, 0xcc, 0x85, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, - 0x07, 0x90, 0x01, 0x00, 0xf3, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, - 0xa3, 0xc9, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, - 0xe1, 0xb1, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, 0x68, 0x01, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x85, 0x93, 0x01, 0x00, - 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xba, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0xa4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xbc, 0xb3, 0x01, 0x00, 0x00, 0x14, 0x2f, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, - 0xa9, 0xb3, 0x01, 0x00, 0xff, 0x00, 0x00, 0xdd, 0x81, 0x88, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x40, 0x80, 0xf4, 0x01, 0x00, 0x78, 0x01, 0x00, 0x40, - 0x80, 0xc8, 0x01, 0x00, 0x88, 0x01, 0x00, 0xdd, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00, 0x89, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x8b, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x8f, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x91, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd2, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xe1, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x80, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xf1, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf2, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x77, 0x01, 0x00, 0x41, 0x81, 0xc0, 0x1a, 0x00, - 0x5a, 0x01, 0x51, 0x40, 0x81, 0xb2, 0x1a, 0x00, 0x5a, 0x01, 0x52, 0x40, - 0x81, 0xb2, 0x1a, 0x00, 0x5a, 0x01, 0x55, 0x40, 0x81, 0xb2, 0x1a, 0x00, - 0x5a, 0x01, 0x56, 0x40, 0x81, 0xb2, 0x1a, 0x00, 0x55, 0x01, 0x91, 0x81, - 0x80, 0x30, 0x1a, 0x00, 0x5a, 0x01, 0x45, 0x40, 0x81, 0xb2, 0x1a, 0x00, - 0x55, 0x01, 0x91, 0x82, 0x80, 0x30, 0x1a, 0x00, 0x5a, 0x01, 0x46, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x89, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x2f, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40, - 0x49, 0x99, 0x01, 0x00, 0xb5, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x81, 0xc0, 0x01, 0x00, 0x94, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x49, 0xd1, 0x01, 0x00, 0x9c, 0x01, 0x22, 0x40, - 0xe1, 0x6d, 0x00, 0x00, 0x98, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x55, 0x01, 0x00, 0x41, 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xbf, 0xb3, 0x01, 0x00, 0x55, 0x01, 0xa0, 0x0f, 0xbd, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xde, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x49, 0xc1, 0x01, 0x00, 0xb7, 0x01, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x42, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0x19, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x42, 0xff, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x2f, 0xff, 0xe1, 0xb1, 0x01, 0x00, 0x08, 0x14, 0x00, 0xa4, - 0x80, 0xcc, 0x01, 0x00, 0xac, 0x01, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x85, 0xc0, 0x01, 0x00, 0xaa, 0x01, 0xa2, 0x4c, - 0x81, 0x50, 0x00, 0x00, 0xb6, 0x01, 0x22, 0xd2, 0x81, 0x32, 0x00, 0x00, - 0xb1, 0x01, 0x22, 0x41, 0xa5, 0x6f, 0x00, 0x00, 0x55, 0x01, 0xa2, 0xe0, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x89, 0x90, 0x01, 0x00, 0x00, 0x00, 0x40, 0x42, - 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0x43, 0x80, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x88, 0x94, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x44, - 0xe0, 0xb1, 0x00, 0x00, 0xb3, 0x01, 0x00, 0x48, 0x49, 0xc1, 0x00, 0x00, - 0xb1, 0x01, 0x00, 0x5b, 0x89, 0x90, 0x00, 0x00, 0xb0, 0x9f, 0x00, 0xa0, - 0x9e, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xba, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xc4, 0x01, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x8a, 0x80, 0xb0, 0x01, 0x00, 0xb6, 0x9f, 0x00, 0x40, - 0x80, 0xce, 0x01, 0x00, 0xc3, 0x01, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xc4, 0x01, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, - 0x6f, 0x93, 0x01, 0x00, 0xf3, 0x9f, 0x00, 0x52, 0x6f, 0x93, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4d, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xcd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xc7, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xd1, 0x01, 0x91, 0x81, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, - 0x80, 0xb0, 0x01, 0x00, 0xb6, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, - 0xd0, 0x01, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd1, 0x01, 0x55, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x6f, 0x93, 0x01, 0x00, - 0xf3, 0x9f, 0x00, 0x53, 0x6f, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x23, 0x40, 0x81, 0xb0, 0x01, 0x00, 0xda, 0x01, 0x22, 0xde, - 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x49, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0xd5, 0x01, 0xa2, 0x44, - 0x81, 0x6c, 0x00, 0x00, 0x55, 0x01, 0x00, 0x43, 0xbf, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x40, 0xf8, - 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xf0, 0x80, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x40, 0xe1, 0xb1, 0x00, 0x00, - 0xe2, 0x01, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x91, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x05, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, 0x08, 0x00, 0x00, 0xdd, - 0x81, 0xf4, 0x01, 0x00, 0xe7, 0x01, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00, 0xed, 0x01, 0x00, 0x40, - 0x81, 0xb0, 0x00, 0x00, 0x58, 0x01, 0x00, 0xde, 0xa1, 0xb3, 0x00, 0x00, - 0xff, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x02, 0x00, 0x40, - 0x81, 0xb0, 0x00, 0x00, 0x07, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x57, 0x01, 0x00, 0xdf, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0xa1, 0xb1, 0x01, 0x00, - 0x02, 0x00, 0x00, 0xd2, 0xa5, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, - 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, - 0xf7, 0x01, 0x22, 0x44, 0xc1, 0x53, 0x00, 0x00, 0xf6, 0x01, 0x84, 0x41, - 0x81, 0x40, 0x00, 0x00, 0xfa, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0x45, 0xb1, 0x01, 0x00, 0xf1, 0x01, 0x00, 0x41, - 0xa1, 0xc1, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x5a, 0x01, 0x00, 0xdd, - 0xa1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00, 0xb1, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x00, 0xd3, 0xa7, 0xcb, 0x01, 0x00, - 0xc5, 0x02, 0x00, 0xe0, 0xa5, 0xb3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x40, - 0xa3, 0x9b, 0x01, 0x00, 0x58, 0x01, 0x00, 0xde, 0xa1, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xbf, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, - 0x81, 0x90, 0x01, 0x00, 0x55, 0x01, 0xa2, 0xba, 0x80, 0x04, 0x00, 0x00, - 0x60, 0x00, 0x00, 0xde, 0x61, 0x99, 0x01, 0x00, 0x04, 0x02, 0xa8, 0xb1, - 0x80, 0x30, 0x00, 0x00, 0x57, 0x01, 0x00, 0x40, 0xe0, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00, 0x68, 0x02, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0x5d, 0x02, 0x00, 0x4d, 0x83, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xe1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xe3, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe5, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xe9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xeb, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf5, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xf7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xf9, 0xb3, 0x01, 0x00, 0x15, 0x02, 0x22, 0x40, 0x8f, 0x6f, 0x00, 0x00, - 0x75, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x5d, 0x02, 0x00, 0xc7, - 0x83, 0x30, 0x01, 0x00, 0x7d, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0x5d, 0x02, 0x00, 0x42, 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe8, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xea, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xeb, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x85, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xec, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xed, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb2, 0xf0, 0xb1, 0x01, 0x00, - 0xe0, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xab, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb8, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb9, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xba, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbb, - 0xf0, 0xb1, 0x01, 0x00, 0x29, 0x02, 0xb8, 0x40, 0x81, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0x90, 0x01, 0x00, 0x2b, 0x02, 0xb9, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x90, 0x01, 0x00, - 0x2d, 0x02, 0xba, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x81, 0x90, 0x01, 0x00, 0x2f, 0x02, 0xbb, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x81, 0x90, 0x01, 0x00, 0x31, 0x02, 0xbc, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x81, 0x90, 0x01, 0x00, - 0x33, 0x02, 0xbd, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x81, 0x90, 0x01, 0x00, 0x35, 0x02, 0xbe, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x81, 0x90, 0x01, 0x00, 0x37, 0x02, 0xbf, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x81, 0x90, 0x01, 0x00, - 0x39, 0x02, 0xc8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, - 0x81, 0x90, 0x01, 0x00, 0x3b, 0x02, 0xc9, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x81, 0x90, 0x01, 0x00, 0x3d, 0x02, 0xca, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x81, 0x90, 0x01, 0x00, - 0x3f, 0x02, 0xcb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x81, 0x90, 0x01, 0x00, 0x41, 0x02, 0xcc, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x81, 0x90, 0x01, 0x00, 0x43, 0x02, 0xcd, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x81, 0x90, 0x01, 0x00, - 0x45, 0x02, 0xce, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0x81, 0x90, 0x01, 0x00, 0x47, 0x02, 0xcf, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x81, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00, - 0xaf, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x06, 0xa5, 0xb3, 0x01, 0x00, - 0x40, 0x00, 0x00, 0xd3, 0xa7, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf1, 0xb1, 0x01, 0x00, - 0xf7, 0x01, 0x00, 0xc7, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x63, 0x02, 0x00, 0x48, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x51, 0x40, 0x1a, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x60, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x5c, 0x02, 0x49, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40, 0x1c, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x4e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x65, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x5c, 0x02, 0x4a, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, - 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xd8, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa1, 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, - 0xd2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xd4, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, - 0xdc, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xde, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x88, 0xda, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, - 0x8e, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xe6, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xac, 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x99, - 0xfa, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe0, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd5, 0xe2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, - 0xe4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe8, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd5, 0xea, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, - 0xf4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xf6, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd5, 0xf8, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc7, - 0xa9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00, - 0x81, 0x02, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x91, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0x85, 0x02, 0x00, 0x40, - 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00, - 0x8a, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x95, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x95, 0x02, 0x00, 0x46, 0xa3, 0xb3, 0x00, 0x00, - 0x98, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x9e, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x02, 0x23, 0x50, 0xa5, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xa5, 0xb3, 0x01, 0x00, 0xbc, 0x02, 0x00, 0x42, - 0xa5, 0x63, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0xa1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0x94, 0x02, 0x22, 0x44, - 0xa5, 0x53, 0x00, 0x00, 0x91, 0x02, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00, - 0x5a, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0xbc, 0x02, 0x00, 0xde, - 0xa1, 0x33, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x5a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0xbf, 0xb3, 0x01, 0x00, 0x55, 0x01, 0xa2, 0xd2, 0x77, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, - 0x63, 0xb1, 0x01, 0x00, 0x9b, 0x02, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x5a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xbc, 0x02, 0x00, 0x54, - 0xa5, 0x33, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd2, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xd4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0xb1, 0x01, 0x00, - 0xa9, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x5d, 0x02, 0x00, 0x46, - 0x83, 0x30, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa0, 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe8, - 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x45, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xea, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xeb, - 0xa1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, - 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xe1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd1, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, - 0x62, 0xdd, 0x01, 0x00, 0xb9, 0x02, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xcc, 0x85, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe7, - 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, - 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00, - 0xb8, 0x02, 0x00, 0xd4, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xcc, - 0x85, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00, - 0xc7, 0x02, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0xc6, 0x02, 0xa2, 0xf2, - 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x83, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00, 0xcb, 0x02, 0x80, 0xa5, - 0x80, 0x32, 0x00, 0x00, 0xcc, 0x02, 0x00, 0xa5, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0xcd, 0x02, 0x80, 0xa5, - 0x80, 0x32, 0x00, 0x00, 0x80, 0x01, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0xd6, 0x02, 0x20, 0x4f, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0xd6, 0x02, 0x20, 0x4b, 0x81, 0x6c, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xd6, 0x02, 0x20, 0x47, - 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x03, 0x90, 0x00, 0x41, - 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x00, 0x14, 0x2f, 0x4c, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xda, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x02, 0x00, 0x00, 0xa5, 0x80, 0xc8, 0x01, 0x00, 0xdd, 0x02, 0xa2, 0xa5, - 0x80, 0x6c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x90, 0x20, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0xe0, 0x02, 0x1f, 0x91, - 0x80, 0x32, 0x00, 0x00, 0x30, 0x00, 0x00, 0x90, 0x20, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0xe3, 0x02, 0x1f, 0x91, - 0x80, 0x32, 0x00, 0x00, 0x70, 0x00, 0x00, 0x90, 0x20, 0xa9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0xe6, 0x02, 0x1f, 0x91, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, - 0xe8, 0x02, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, 0x40, 0x68, 0x00, 0x90, - 0x20, 0xa9, 0x01, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x21, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x22, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x23, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x24, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x25, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x26, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x27, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x02, 0x01, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, 0x04, 0x03, 0x00, 0x40, - 0x80, 0x98, 0x01, 0x00, 0x06, 0x05, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x08, 0x07, 0x00, 0x41, 0x82, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe0, 0xb1, 0x01, 0x00, - 0x30, 0x03, 0x00, 0x40, 0x85, 0x30, 0x01, 0x00, 0x39, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd8, 0x14, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xff, 0x02, 0xa2, 0xf8, 0x80, 0x6c, 0x00, 0x00, 0x00, 0x03, 0x22, 0xf0, - 0x82, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x21, 0x91, 0x01, 0x00, - 0xd0, 0x14, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x03, 0x00, 0x0c, - 0x85, 0x30, 0x01, 0x00, 0x30, 0x03, 0x00, 0x4d, 0x85, 0x10, 0x01, 0x00, - 0x30, 0x03, 0x00, 0x4e, 0x85, 0x10, 0x01, 0x00, 0xd0, 0x14, 0x20, 0x4f, - 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x03, 0x00, 0x4f, 0x85, 0x10, 0x01, 0x00, - 0x39, 0x03, 0x00, 0x0c, 0x85, 0x30, 0x01, 0x00, 0xd8, 0x14, 0x20, 0x43, - 0x81, 0xb0, 0x01, 0x00, 0x0f, 0x03, 0x22, 0xf0, 0x9e, 0x6e, 0x00, 0x00, - 0x39, 0x03, 0x00, 0x4d, 0x85, 0x10, 0x01, 0x00, 0xd8, 0x14, 0x20, 0x42, - 0x81, 0xb0, 0x01, 0x00, 0x0f, 0x03, 0x22, 0xf0, 0x9e, 0x6e, 0x00, 0x00, - 0x39, 0x03, 0x00, 0x4e, 0x85, 0x10, 0x01, 0x00, 0xd8, 0x14, 0x20, 0x41, - 0x81, 0xb0, 0x01, 0x00, 0x11, 0x03, 0xa2, 0xf0, 0x9e, 0x6e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x81, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x20, 0x95, 0x01, 0x00, 0x03, 0x00, 0x00, 0x90, 0x20, 0x8d, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x21, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x89, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x30, 0x03, 0x00, 0x17, 0x85, 0x30, 0x01, 0x00, 0x30, 0x03, 0x00, 0x58, - 0x85, 0x10, 0x01, 0x00, 0x30, 0x03, 0x00, 0x59, 0x85, 0x10, 0x01, 0x00, - 0xd0, 0x14, 0x20, 0x4f, 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x03, 0x00, 0x5a, - 0x85, 0x10, 0x01, 0x00, 0x39, 0x03, 0x00, 0x17, 0x85, 0x30, 0x01, 0x00, - 0xd8, 0x14, 0x20, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x23, 0x03, 0x22, 0xf0, - 0x9e, 0x6e, 0x00, 0x00, 0x39, 0x03, 0x00, 0x58, 0x85, 0x10, 0x01, 0x00, - 0xd8, 0x14, 0x20, 0x41, 0x81, 0xb0, 0x01, 0x00, 0x23, 0x03, 0x22, 0xf0, - 0x9e, 0x6e, 0x00, 0x00, 0x39, 0x03, 0x00, 0x59, 0x85, 0x10, 0x01, 0x00, - 0xd8, 0x14, 0x20, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x27, 0x03, 0xa2, 0xf0, - 0x9e, 0x6e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x90, 0x20, 0x8d, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x20, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x88, 0xe0, 0x01, 0x00, - 0x2f, 0x03, 0xa2, 0x42, 0x21, 0x7d, 0x00, 0x00, 0xa5, 0xa5, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0xd0, 0x14, 0x20, 0x40, 0xe0, 0xb1, 0x01, 0x00, - 0x30, 0x03, 0x00, 0x44, 0x84, 0x30, 0x01, 0x00, 0x39, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd8, 0x14, 0x20, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x2f, 0x03, 0xa2, 0xf0, 0x80, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x89, 0xe0, 0x01, 0x00, 0xe0, 0x00, 0x80, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x70, 0x15, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, - 0xd0, 0x14, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x87, 0xb4, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x70, 0x15, 0x00, 0x43, 0x62, 0x99, 0x01, 0x00, 0x36, 0x03, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x41, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x70, 0x15, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xf1, 0xb1, 0x01, 0x00, 0xd8, 0x14, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x87, 0xb4, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x70, 0x15, 0x00, 0x43, 0x62, 0x99, 0x01, 0x00, 0x3f, 0x03, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x87, 0xb0, 0x01, 0x00, - 0x42, 0x03, 0xa2, 0x41, 0x87, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xf2, - 0x86, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf1, 0x86, 0xf4, 0x01, 0x00, - 0x41, 0x03, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x84, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x48, 0x84, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x8f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x62, 0xb1, 0x01, 0x00, 0x49, 0x03, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xf5, 0x9f, 0x00, 0x47, 0x98, 0x30, 0x01, 0x00, - 0x00, 0x08, 0x00, 0x47, 0x8e, 0xc8, 0x01, 0x00, 0x47, 0x03, 0x00, 0x5c, - 0x8f, 0x80, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x58, 0x15, 0x2d, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0, - 0x88, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x81, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x45, - 0x82, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x82, 0x94, 0x01, 0x00, 0x20, 0x00, 0x00, 0x41, 0x60, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00, 0x64, 0x03, 0x22, 0x5f, - 0x8d, 0x6c, 0x00, 0x00, 0x55, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x53, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, - 0x85, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x43, - 0x86, 0xd8, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x41, 0x85, 0x50, 0x01, 0x00, - 0x60, 0x03, 0x00, 0x41, 0x83, 0xe0, 0x00, 0x00, 0x5e, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0x85, 0xe0, 0x01, 0x00, - 0xd0, 0x14, 0x2f, 0x46, 0x84, 0x94, 0x01, 0x00, 0x20, 0x00, 0x00, 0x42, - 0x60, 0x99, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x07, 0x00, 0x00, 0x45, - 0x80, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, - 0x00, 0x04, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0x6f, 0x03, 0xa0, 0x41, - 0x81, 0x50, 0x00, 0x00, 0x6d, 0x03, 0x00, 0x41, 0x82, 0xe8, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x41, 0x8e, 0xc0, 0x01, 0x00, 0xae, 0x03, 0x00, 0x40, - 0xa3, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x81, 0xb0, 0x01, 0x00, - 0x60, 0x15, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, - 0x40, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x41, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x41, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x40, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0xa3, 0x55, 0x81, 0x6c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xa3, 0xc1, 0x01, 0x00, 0x73, 0x03, 0x00, 0x50, 0x85, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x7e, 0x03, 0xa2, 0x41, - 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, - 0x0b, 0x00, 0x00, 0x44, 0x82, 0xf4, 0x01, 0x00, 0x1a, 0x15, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0x70, 0x15, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x08, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x16, 0x00, 0x40, 0xe1, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x70, 0x15, 0x00, 0x43, - 0x62, 0x99, 0x01, 0x00, 0x88, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x8a, 0x03, 0x22, 0x5a, 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x8b, 0x03, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, - 0x00, 0x08, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, 0x83, 0x03, 0xa2, 0x41, - 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf7, 0x0f, 0x00, 0xbc, - 0x80, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - }, - { - 0x31, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x34, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x35, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x80, 0x81, 0x80, - 0x80, 0x32, 0x00, 0x00, 0xe6, 0x89, 0xa2, 0x40, 0x91, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x90, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2, - 0x80, 0xb0, 0x01, 0x00, 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00, - 0x90, 0x95, 0x2a, 0xc8, 0xe5, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd3, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x44, 0xb1, 0x01, 0x00, 0x18, 0x80, 0x11, 0x81, - 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x51, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x1a, 0x80, 0x11, 0x82, 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xe6, 0x89, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00, - 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x23, 0x80, 0xa2, 0x42, - 0xfd, 0x7f, 0x00, 0x00, 0x20, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00, - 0x22, 0x80, 0x11, 0x81, 0x82, 0x30, 0x00, 0x00, 0x22, 0x80, 0x51, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x22, 0x80, 0x11, 0x82, 0x82, 0x30, 0x00, 0x00, - 0x22, 0x80, 0x52, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x80, 0x00, 0x48, - 0xfd, 0x93, 0x00, 0x00, 0x27, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00, - 0x26, 0x80, 0xa2, 0x53, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x51, 0x53, - 0x07, 0x90, 0x01, 0x00, 0x2a, 0x80, 0x00, 0x52, 0x07, 0x90, 0x00, 0x00, - 0x29, 0x80, 0xa2, 0x52, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x52, 0x52, - 0x07, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0xf3, 0x93, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2, 0x52, 0xb3, 0x01, 0x00, - 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x45, 0xb1, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x4c, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x1b, 0x84, 0x05, 0x40, 0x49, 0xb1, 0x00, 0x00, 0x1b, 0x84, 0x05, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0xe1, 0x80, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0xde, 0xb2, 0x01, 0x00, 0x77, 0x00, 0x00, 0x40, 0x4b, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xfd, 0x83, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0x9b, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00, 0xde, 0x99, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x58, 0x95, 0x20, 0x44, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0xc0, 0x00, 0xa6, 0x36, 0xb1, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x38, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x06, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x05, 0x18, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x02, 0x09, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x50, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x7b, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xe0, 0x83, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x10, 0x84, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x84, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x60, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x70, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xdd, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x1a, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x71, 0x83, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x02, 0x00, 0x00, 0x97, - 0x80, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2e, 0xb1, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x40, 0x2e, 0xdd, 0x01, 0x00, 0x90, 0x01, 0x00, 0x40, - 0x93, 0x98, 0x01, 0x00, 0x29, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x5c, 0x81, 0x00, 0x40, 0xaf, 0x33, 0x01, 0x00, 0x61, 0x99, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x49, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x77, 0x01, 0x00, 0x41, 0x81, 0xc0, 0x00, 0x00, - 0x71, 0x80, 0x51, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x72, 0x80, 0x52, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x73, 0x80, 0x55, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x74, 0x80, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x01, 0x91, 0x81, - 0x80, 0x30, 0x00, 0x00, 0x5a, 0x01, 0x45, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x55, 0x01, 0x91, 0x82, 0x80, 0x30, 0x00, 0x00, 0x5a, 0x01, 0x46, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00, - 0x5a, 0x01, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x49, - 0xfd, 0x83, 0x00, 0x00, 0x5a, 0x01, 0x00, 0x4a, 0xfd, 0x83, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, - 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0xd0, 0xe1, 0xb1, 0x00, 0x00, - 0x7c, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, - 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00, - 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x84, 0x80, 0xa2, 0x41, - 0x97, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xa1, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x04, - 0x80, 0x94, 0x00, 0x00, 0x80, 0x15, 0x3f, 0x42, 0x97, 0xe3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x03, - 0x02, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xcb, 0x99, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcc, - 0xf3, 0x83, 0x01, 0x00, 0x8e, 0x80, 0xa2, 0x41, 0x97, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xcb, 0xf3, 0x93, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, - 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x44, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa1, 0xe0, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, - 0x95, 0x80, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc6, 0x02, 0x00, 0x20, - 0x42, 0x31, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x05, 0x6c, 0x01, 0x00, - 0x00, 0x00, 0x80, 0xcb, 0xdb, 0x91, 0x01, 0x00, 0x00, 0x00, 0x19, 0x41, - 0x8b, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x9b, 0x80, 0xa8, 0xb1, 0x8c, 0x33, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x9d, 0x80, 0xa8, 0xb1, 0x94, 0x33, 0x00, 0x00, - 0xa3, 0x80, 0x14, 0xc6, 0x81, 0x32, 0x00, 0x00, 0x18, 0x00, 0x00, 0xc6, - 0x83, 0xf4, 0x01, 0x00, 0x6a, 0x84, 0x22, 0x4f, 0x83, 0x04, 0x00, 0x00, - 0x7f, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc6, - 0x81, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x97, 0xa3, 0x01, 0x00, - 0x7f, 0x80, 0x1f, 0x5c, 0x97, 0x53, 0x00, 0x00, 0x9e, 0x83, 0x1d, 0xc6, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x43, 0x81, 0xf0, 0x01, 0x00, - 0xa9, 0x80, 0x00, 0x40, 0x10, 0xc9, 0x00, 0x00, 0x05, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x36, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xda, 0x81, 0x00, 0xca, 0x63, 0xb3, 0x00, 0x00, 0x2d, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x14, 0x81, 0x00, 0x4d, 0x83, 0xb0, 0x00, 0x00, - 0x1e, 0x81, 0x00, 0x4e, 0x61, 0xb1, 0x00, 0x00, 0x0d, 0x81, 0x00, 0x40, - 0x85, 0xb0, 0x00, 0x00, 0x14, 0x81, 0x00, 0x4c, 0x83, 0xb0, 0x00, 0x00, - 0xf0, 0x80, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00, 0x91, 0x81, 0x00, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0x3d, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, - 0x8d, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0d, 0x81, 0x00, 0x40, - 0x85, 0xb0, 0x00, 0x00, 0xdd, 0x81, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, - 0x6a, 0x84, 0x00, 0xca, 0x9b, 0xb3, 0x00, 0x00, 0x46, 0x81, 0x00, 0x40, - 0xc1, 0xb1, 0x00, 0x00, 0x4e, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, - 0x55, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x56, 0x81, 0x00, 0x40, - 0xc1, 0xb1, 0x00, 0x00, 0x57, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, - 0x58, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x59, 0x81, 0x00, 0x40, - 0x81, 0xb0, 0x00, 0x00, 0x59, 0x81, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00, - 0xce, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xdd, 0x83, 0x00, 0xbb, - 0xab, 0xb3, 0x00, 0x00, 0xdb, 0x81, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, - 0xd3, 0x80, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xdf, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xdc, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x6a, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xda, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, 0x77, 0xb3, 0x00, 0x00, - 0x15, 0x81, 0x00, 0x4d, 0x83, 0xb0, 0x00, 0x00, 0x1c, 0x81, 0x00, 0x4e, - 0x61, 0xb1, 0x00, 0x00, 0x0d, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00, - 0x15, 0x81, 0x00, 0x4c, 0x83, 0xb0, 0x00, 0x00, 0x0d, 0x81, 0x00, 0xbb, - 0x85, 0xb0, 0x00, 0x00, 0xf0, 0x80, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00, - 0xe2, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, - 0x4d, 0xb3, 0x00, 0x00, 0x64, 0x82, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, - 0x8f, 0x82, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xc8, 0x14, 0x2e, 0xbb, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xe0, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa2, - 0xa0, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, - 0x75, 0x80, 0x00, 0xca, 0xa7, 0x33, 0x01, 0x00, 0x02, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x4d, 0x93, 0x30, 0x01, 0x00, - 0x4e, 0x01, 0x00, 0x4e, 0x93, 0x30, 0x01, 0x00, 0x4e, 0x01, 0x00, 0x4c, - 0x93, 0x30, 0x01, 0x00, 0x08, 0x84, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x6a, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x54, 0x95, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xe5, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00, 0xe8, 0x80, 0x22, 0x42, - 0x8f, 0x6f, 0x00, 0x00, 0xea, 0x80, 0x22, 0x41, 0x8f, 0x6f, 0x00, 0x00, - 0xec, 0x80, 0x1e, 0xca, 0x81, 0x32, 0x00, 0x00, 0xee, 0x80, 0x1f, 0xca, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xc9, 0xb1, 0x01, 0x00, - 0x6a, 0x84, 0x00, 0x42, 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xcd, 0xb1, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x41, 0x8f, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xcf, 0xb1, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x40, - 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x81, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00, - 0x6a, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6, - 0xc6, 0xb1, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x40, 0x8f, 0xb3, 0x00, 0x00, - 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0x10, 0x00, 0x2f, 0x9c, - 0x89, 0xb0, 0x01, 0x00, 0x07, 0x81, 0x00, 0x40, 0x39, 0x33, 0x01, 0x00, - 0x18, 0x00, 0x2f, 0x9b, 0x89, 0xb0, 0x01, 0x00, 0x07, 0x81, 0x00, 0x40, - 0x37, 0x33, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x9a, 0x89, 0xb0, 0x01, 0x00, - 0x07, 0x81, 0x00, 0x40, 0x35, 0x33, 0x01, 0x00, 0x08, 0x00, 0x2f, 0x99, - 0x89, 0xb0, 0x01, 0x00, 0x07, 0x81, 0x00, 0x40, 0x33, 0x33, 0x01, 0x00, - 0x00, 0x80, 0x00, 0xae, 0x47, 0xc9, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x00, 0x40, - 0xe1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0xae, 0x63, 0xdd, 0x01, 0x00, 0x02, 0x81, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xff, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x02, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x69, 0x93, 0x01, 0x00, 0x6a, 0x84, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00, - 0x05, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x81, 0x00, 0x58, - 0x69, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf0, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0xa4, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0c, 0x81, 0xa2, 0x40, - 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41, - 0xe1, 0xd1, 0x01, 0x00, 0x0d, 0x81, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x62, 0xb1, 0x01, 0x00, 0x11, 0x81, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x0e, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, 0x11, 0x81, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x6a, 0x84, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x16, 0x81, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0x16, 0x81, 0x00, 0xbb, - 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x60, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x17, 0x81, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, - 0x6a, 0x84, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x19, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x50, 0x95, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x1f, 0x81, 0x00, 0xbb, 0x87, 0xb0, 0x00, 0x00, 0x50, 0x95, 0x2f, 0x40, - 0x87, 0xb0, 0x01, 0x00, 0x21, 0x81, 0x22, 0x40, 0x95, 0x7f, 0x00, 0x00, - 0x6a, 0x84, 0x60, 0x40, 0x95, 0x83, 0x00, 0x00, 0x02, 0x00, 0x2d, 0xf0, - 0x84, 0xb0, 0x01, 0x00, 0x22, 0x81, 0x36, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x62, 0xb1, 0x01, 0x00, 0x23, 0x81, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x62, 0xb1, 0x01, 0x00, - 0x25, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, - 0x63, 0xb1, 0x01, 0x00, 0x27, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x16, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x6a, 0x84, 0x22, 0x41, - 0x43, 0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0xca, 0x95, 0xcb, 0x01, 0x00, - 0x22, 0x81, 0x00, 0x41, 0x85, 0xc0, 0x00, 0x00, 0x2f, 0x81, 0xa2, 0x42, - 0x67, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x67, 0xb3, 0x01, 0x00, - 0x2f, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x65, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x93, 0x83, 0x01, 0x00, - 0x00, 0x00, 0x1a, 0xca, 0x69, 0x97, 0x01, 0x00, 0x6a, 0x84, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x34, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x6a, 0x84, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00, 0x6a, 0x84, 0x20, 0x43, - 0x95, 0x6f, 0x00, 0x00, 0x6a, 0x84, 0x80, 0xca, 0x67, 0x33, 0x00, 0x00, - 0x6a, 0x84, 0x22, 0x40, 0x65, 0x6f, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x6f, - 0xdb, 0x91, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x35, 0x80, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x95, 0x93, 0x01, 0x00, - 0x42, 0x81, 0xa2, 0x44, 0x21, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x95, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x95, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x57, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xc3, 0xb1, 0x01, 0x00, 0x45, 0x81, 0x22, 0x5b, 0x95, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0xfd, 0x93, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x49, 0x81, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00, - 0x1b, 0xf5, 0x00, 0xca, 0x95, 0x9b, 0x01, 0x00, 0x4a, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x1b, 0xfd, 0x00, 0xca, 0x95, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0x7f, 0xb3, 0x01, 0x00, 0x26, 0x01, 0x00, 0xca, - 0xc5, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, - 0x6a, 0x84, 0x00, 0xca, 0xc5, 0xb1, 0x00, 0x00, 0xdf, 0x6f, 0x00, 0xca, - 0x95, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x95, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xc7, 0xb1, 0x01, 0x00, 0x6a, 0x84, 0x22, 0x5f, - 0x95, 0x7f, 0x00, 0x00, 0x26, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca, - 0xc7, 0xb1, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xc9, 0xb1, 0x00, 0x00, - 0x6a, 0x84, 0x00, 0xca, 0xcb, 0xb1, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, - 0xcd, 0xb1, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xcf, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x42, 0x81, 0xe0, 0x01, 0x00, 0x98, 0x14, 0x00, 0x40, - 0x48, 0xc9, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xe1, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x09, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x5e, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0x60, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x20, 0x80, 0x00, 0xa6, 0x08, 0xb1, 0x01, 0x00, - 0x62, 0x81, 0x9f, 0x85, 0x82, 0x30, 0x00, 0x00, 0x61, 0x81, 0xa2, 0x4f, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x21, 0xb3, 0x01, 0x00, - 0x02, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x10, 0x00, 0x00, 0x41, 0x84, 0xe4, 0x01, 0x00, - 0x03, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x41, 0x86, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x84, 0x94, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0x10, 0xc4, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00, - 0x75, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x21, 0xb3, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x1c, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x72, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, - 0x7e, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x41, 0x01, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0x50, 0x0c, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00, - 0x7a, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x21, 0xb3, 0x01, 0x00, 0x7e, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x41, 0x01, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x60, 0x0c, 0x00, 0x43, - 0x86, 0x98, 0x01, 0x00, 0x7e, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x21, 0xb3, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x7f, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, - 0x40, 0x13, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0x87, 0x81, 0x22, 0x43, - 0x21, 0x6f, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x84, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, - 0x8c, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x19, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, - 0x89, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x41, - 0x08, 0x99, 0x01, 0x00, 0x8c, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0x81, 0x94, 0x01, 0x00, - 0x8f, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x40, - 0x08, 0xb1, 0x00, 0x00, 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00, - 0x92, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x87, 0xb0, 0x01, 0x00, 0xa1, 0x81, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, - 0xb0, 0x81, 0x22, 0x44, 0x21, 0x6f, 0x00, 0x00, 0x11, 0x80, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xb8, 0x81, 0x22, 0x4a, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x87, 0x90, 0x01, 0x00, 0x9c, 0x81, 0x22, 0x4d, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x87, 0x90, 0x01, 0x00, 0x9e, 0x81, 0x22, 0x4f, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, - 0xa0, 0x81, 0x22, 0x4e, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x87, 0x90, 0x01, 0x00, 0xb8, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0xc9, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x81, 0x22, 0x42, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, - 0x1c, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xab, 0x81, 0x22, 0x45, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x87, 0x90, 0x01, 0x00, 0xad, 0x81, 0x22, 0x44, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, - 0xaf, 0x81, 0x22, 0x43, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x87, 0x90, 0x01, 0x00, 0xb8, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0xc9, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0xc9, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x81, 0x22, 0x42, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x87, 0x90, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0xc9, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbc, 0x81, 0x22, 0x4b, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x80, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xaf, 0xb3, 0x01, 0x00, 0xc5, 0x81, 0x22, 0x40, 0x87, 0x7c, 0x00, 0x00, - 0xc5, 0x81, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xae, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb3, 0x01, 0x00, - 0xc4, 0x81, 0x22, 0x42, 0x87, 0x7c, 0x00, 0x00, 0xc5, 0x81, 0x00, 0x0b, - 0x7d, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x7d, 0xb3, 0x01, 0x00, - 0xff, 0x7f, 0x00, 0xa2, 0xa0, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xa5, 0xb3, 0x01, 0x00, 0x75, 0x80, 0x00, 0xca, 0xa7, 0x33, 0x01, 0x00, - 0x02, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0x41, - 0x82, 0xdc, 0x01, 0x00, 0xca, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00, 0xcc, 0x81, 0x9f, 0x85, - 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xd1, 0x81, 0x14, 0xf7, 0x81, 0x30, 0x00, 0x00, 0xd1, 0x81, 0xa2, 0x49, - 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00, - 0xd4, 0x81, 0x15, 0xf8, 0x81, 0x14, 0x00, 0x00, 0xd4, 0x81, 0xa2, 0x4a, - 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00, - 0xd6, 0x81, 0xa2, 0xc8, 0x81, 0x32, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, - 0x80, 0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xef, 0xb3, 0x01, 0x00, 0xd8, 0x81, 0x42, 0x40, - 0xf1, 0x33, 0x00, 0x00, 0x04, 0x81, 0x00, 0x40, 0x68, 0x97, 0x00, 0x00, - 0x6a, 0x84, 0x00, 0xbb, 0x6b, 0xb3, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xbb, - 0xb1, 0xb3, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xcc, 0x14, 0x2e, 0x40, 0x87, 0xb0, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa2, - 0xa0, 0x8b, 0x01, 0x00, 0xd8, 0x00, 0x00, 0x43, 0xb2, 0x33, 0x01, 0x00, - 0x00, 0x00, 0x68, 0xda, 0x89, 0xb0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40, - 0x8b, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x89, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x89, 0xd0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x44, - 0x88, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xa5, 0xb3, 0x01, 0x00, 0xd8, 0x00, 0x00, 0x43, - 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xa5, 0xc3, 0x01, 0x00, 0xf8, 0x81, 0x22, 0x44, 0x89, 0x50, 0x00, 0x00, - 0xf8, 0x81, 0x22, 0x44, 0x8b, 0x50, 0x00, 0x00, 0xe7, 0x81, 0xa2, 0x50, - 0xa5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0x75, 0x80, 0x00, 0xbb, - 0x85, 0x30, 0x01, 0x00, 0xcc, 0x14, 0x2e, 0xd2, 0x95, 0xc3, 0x01, 0x00, - 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00, - 0xf5, 0x81, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0xf4, 0x81, 0xa2, 0xf2, - 0x80, 0x30, 0x00, 0x00, 0xe7, 0x81, 0x00, 0x40, 0xa5, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xa7, 0xb3, 0x01, 0x00, 0x75, 0x80, 0x00, 0xbb, 0x85, 0x30, 0x01, 0x00, - 0x02, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x41, - 0xb3, 0x73, 0x01, 0x00, 0x00, 0x00, 0x80, 0x50, 0xb5, 0xf3, 0x01, 0x00, - 0xd8, 0x00, 0x00, 0x41, 0xb3, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, - 0xb3, 0xfb, 0x01, 0x00, 0x00, 0x30, 0x00, 0xa6, 0xb8, 0xb3, 0x01, 0x00, - 0xf2, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x25, 0x01, 0x00, 0x42, - 0x2d, 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0xeb, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x81, 0xb0, 0x01, 0x00, 0x26, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x09, 0x82, 0x10, 0xda, 0xb5, 0x6b, 0x00, 0x00, 0x0a, 0x82, 0x00, 0x41, - 0x2d, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2d, 0x91, 0x01, 0x00, - 0x28, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40, - 0x2d, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0x81, 0x01, 0x00, - 0x06, 0x82, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x26, 0x01, 0x00, 0x42, - 0x2d, 0x01, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x26, 0x01, 0x00, 0x42, 0x2d, 0x11, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40, - 0x2d, 0x11, 0x01, 0x00, 0x15, 0x82, 0x04, 0x40, 0x2d, 0x01, 0x00, 0x00, - 0x25, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x11, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x28, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x25, 0x01, 0x00, 0x42, 0x2d, 0x01, 0x01, 0x00, 0xf2, 0x00, 0x00, 0x40, - 0xb9, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x2d, 0x81, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x41, 0x2d, 0x81, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x03, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x18, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x42, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x18, 0xb1, 0x01, 0x00, 0x1f, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x00, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x43, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x81, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf6, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x43, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x29, 0x82, 0xa2, 0x54, - 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x30, 0x82, 0xa2, 0x06, - 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x07, 0x91, 0xb0, 0x01, 0x00, 0xe1, 0x80, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x39, 0x82, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0x3a, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xf5, 0xb1, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x42, - 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00, - 0x4e, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, - 0x50, 0x00, 0x00, 0x40, 0x91, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x8f, 0xb0, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x48, 0xb2, 0x33, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, - 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x91, 0xc0, 0x01, 0x00, - 0x45, 0x82, 0xa2, 0x41, 0x8f, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x45, 0xd1, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xfd, 0xb1, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xfd, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xfd, 0xb1, 0x01, 0x00, 0x16, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xfd, 0xb1, 0x01, 0x00, 0x34, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0x91, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xda, 0x8f, 0xb0, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0xda, 0xfd, 0xb1, 0x01, 0x00, - 0x6f, 0x82, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x6f, 0x82, 0x22, 0x45, - 0xfd, 0x7f, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x35, 0x82, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0x08, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xfe, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x6d, 0x82, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00, 0x72, 0x82, 0x22, 0x20, - 0xb5, 0x6f, 0x00, 0x00, 0x6f, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xdb, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x72, 0x82, 0x22, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x6f, 0x82, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x69, 0x93, 0x01, 0x00, 0x04, 0x81, 0x00, 0x58, - 0x69, 0x93, 0x00, 0x00, 0x54, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x46, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, 0x48, 0x00, 0x00, 0x40, - 0x95, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x97, 0xb0, 0x01, 0x00, - 0xfc, 0x81, 0x00, 0x4a, 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xf7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x95, 0xc0, 0x01, 0x00, 0x85, 0x82, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00, - 0x40, 0x16, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xa7, 0xb3, 0x01, 0x00, 0x75, 0x80, 0x00, 0xbb, 0x85, 0x30, 0x01, 0x00, - 0x02, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa7, 0x82, 0x22, 0x45, - 0xfd, 0x7f, 0x00, 0x00, 0xe0, 0x15, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x1a, 0x00, 0x00, 0xa2, 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xf1, 0xb1, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xa0, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, - 0x96, 0x82, 0xa8, 0xbb, 0xe1, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x83, 0xb0, 0x01, 0x00, 0x99, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x98, 0x82, 0xa2, 0xf2, 0x82, 0x30, 0x00, 0x00, 0xe1, 0x80, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x9f, 0x82, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0xa0, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0xf0, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xa7, 0x82, 0xa2, 0xfa, 0xb4, 0x6f, 0x00, 0x00, - 0xfc, 0x81, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, 0xa7, 0x82, 0xa2, 0xfa, - 0xb4, 0x6f, 0x00, 0x00, 0xfc, 0x81, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, - 0xaa, 0x82, 0x22, 0xfa, 0xb4, 0x6f, 0x00, 0x00, 0xa7, 0x82, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x69, 0x93, 0x01, 0x00, - 0x04, 0x81, 0x00, 0x58, 0x69, 0x93, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x35, 0x82, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, - 0xf6, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x5c, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xfa, 0x8e, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb4, 0xb3, 0x01, 0x00, - 0xb8, 0x82, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00, 0xfc, 0x15, 0x20, 0x20, - 0xe1, 0xb1, 0x01, 0x00, 0xbd, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xdb, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbd, 0x82, 0x22, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0xba, 0x82, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x69, 0x93, 0x01, 0x00, 0x04, 0x81, 0x00, 0x58, - 0x69, 0x93, 0x00, 0x00, 0x34, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xc2, 0x82, 0x22, 0x50, 0xb5, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x91, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xff, 0x81, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, 0x02, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xf8, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xff, 0x81, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xfa, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xff, 0x81, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, 0x08, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4a, - 0xb4, 0x8b, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4a, - 0xb4, 0xf7, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x34, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd8, 0x82, 0x22, 0x50, 0xb5, 0x6f, 0x00, 0x00, 0xd9, 0x82, 0x00, 0x50, - 0xb5, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb5, 0xb3, 0x01, 0x00, - 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x02, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x30, 0x31, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x32, 0x33, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x34, 0x35, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x36, 0x37, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x38, 0x39, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x41, 0x42, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x43, 0x44, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x45, 0x46, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x47, 0x48, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x49, 0x4a, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00, - 0xe7, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x80, 0x16, 0x2e, 0x06, - 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0xea, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00, - 0xed, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40, - 0x95, 0x98, 0x01, 0x00, 0x00, 0x83, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0xf3, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0x00, 0x83, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00, - 0xff, 0x82, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0x45, 0x67, 0x00, 0xa6, 0xe0, 0xb2, 0x01, 0x00, 0x01, 0x23, 0x00, 0x70, - 0xe1, 0x9a, 0x01, 0x00, 0xcd, 0xef, 0x00, 0xa6, 0xe2, 0xb2, 0x01, 0x00, - 0x89, 0xab, 0x00, 0x71, 0xe3, 0x9a, 0x01, 0x00, 0xba, 0x98, 0x00, 0xa6, - 0xe4, 0xb2, 0x01, 0x00, 0xfe, 0xdc, 0x00, 0x72, 0xe5, 0x9a, 0x01, 0x00, - 0x32, 0x10, 0x00, 0xa6, 0xe6, 0xb2, 0x01, 0x00, 0x76, 0x54, 0x00, 0x73, - 0xe7, 0x9a, 0x01, 0x00, 0xd2, 0xc3, 0x00, 0xa6, 0xe8, 0xb2, 0x01, 0x00, - 0xf0, 0xe1, 0x00, 0x74, 0xe9, 0x9a, 0x01, 0x00, 0x80, 0x16, 0x00, 0x4a, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf7, 0xb1, 0x01, 0x00, 0x0d, 0x83, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x80, 0x16, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0xfc, 0x16, 0x2a, 0x47, - 0xe7, 0xb5, 0x01, 0x00, 0x03, 0x00, 0x00, 0x4a, 0xe8, 0xe5, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, - 0xa3, 0x99, 0x01, 0x00, 0x80, 0x16, 0x3d, 0x46, 0x8d, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x40, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, - 0x16, 0x83, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xeb, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xed, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x72, 0xef, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73, - 0xf1, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf3, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x41, - 0x80, 0x88, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, 0xa2, 0xc9, 0x01, 0x00, - 0x33, 0x83, 0xa0, 0x50, 0x83, 0x6c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x40, - 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00, - 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x86, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c, - 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, - 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0xa4, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x20, 0x88, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x41, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x94, 0x01, 0x00, - 0x05, 0x00, 0x00, 0x75, 0x89, 0xe4, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x75, - 0x85, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x84, 0x94, 0x01, 0x00, - 0x3d, 0x83, 0xa3, 0x53, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x76, 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x8b, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00, - 0x4c, 0x83, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41, - 0x80, 0xce, 0x01, 0x00, 0x42, 0x83, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, - 0x89, 0xa4, 0x01, 0x00, 0x4c, 0x83, 0x00, 0x78, 0x89, 0xa4, 0x00, 0x00, - 0x3b, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, 0x3f, 0x83, 0xaa, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76, - 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x88, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, - 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00, - 0x4c, 0x83, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x84, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x85, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x84, 0xc0, 0x01, 0x00, 0x53, 0x83, 0xa3, 0x53, - 0x83, 0x6c, 0x00, 0x00, 0x82, 0x5a, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, - 0x99, 0x79, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, 0x60, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, - 0x58, 0x83, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd9, 0x6e, 0x00, 0xa6, - 0x84, 0xc0, 0x01, 0x00, 0xa1, 0xeb, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, - 0x60, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x41, - 0x80, 0xce, 0x01, 0x00, 0x5d, 0x83, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x8f, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xdc, 0xbc, 0x00, 0x42, - 0x84, 0xc8, 0x01, 0x00, 0x60, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x62, 0xca, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xd6, 0xc1, 0x00, 0x42, - 0x84, 0xc8, 0x01, 0x00, 0x60, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x78, 0xf3, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, - 0xf1, 0xb2, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x76, 0x89, 0xe4, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x76, 0xef, 0xf6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xee, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x75, 0xed, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xea, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x83, 0xc0, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, - 0x1f, 0x83, 0x2a, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, - 0xe1, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76, 0xe3, 0xc2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x77, 0xe5, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, - 0xe7, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0xe9, 0xc2, 0x01, 0x00, - 0x13, 0x83, 0x81, 0x41, 0x8d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x9d, 0x83, 0xa2, 0x4b, 0xb7, 0x6f, 0x00, 0x00, - 0x9d, 0x83, 0xa2, 0x41, 0x2f, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xfd, 0x93, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x35, 0x82, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0x9c, 0x83, 0x22, 0x40, - 0x8f, 0x6c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0xfe, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xdb, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x9c, 0x83, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, - 0x5e, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x7c, 0x16, 0x20, 0xf6, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x31, 0xb3, 0x01, 0x00, - 0x80, 0x83, 0x22, 0x4f, 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, - 0xfd, 0x93, 0x01, 0x00, 0x82, 0x83, 0x22, 0x40, 0x8f, 0x7c, 0x00, 0x00, - 0x86, 0x83, 0x00, 0x54, 0xfd, 0x93, 0x00, 0x00, 0x84, 0x83, 0x22, 0x42, - 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xfd, 0x93, 0x01, 0x00, - 0x86, 0x83, 0x22, 0x41, 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, - 0xfd, 0x93, 0x01, 0x00, 0x9a, 0x83, 0x22, 0x51, 0xfd, 0x7f, 0x00, 0x00, - 0x34, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x95, 0x83, 0xa2, 0x40, 0xb5, 0x6f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x48, 0x96, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0x97, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x4b, - 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x30, 0xb5, 0xb3, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x99, 0x83, 0x22, 0x40, - 0xb5, 0x6f, 0x00, 0x00, 0x9d, 0x83, 0x00, 0x54, 0xfd, 0x93, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xfe, - 0x7f, 0xd9, 0x01, 0x00, 0x9d, 0x83, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x55, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x2f, 0x41, 0x99, 0xb3, 0x01, 0x00, 0xa8, 0x83, 0x22, 0x44, - 0x81, 0x6c, 0x00, 0x00, 0xb0, 0x83, 0x22, 0x48, 0x81, 0x6c, 0x00, 0x00, - 0xaa, 0x83, 0x22, 0x4c, 0x81, 0x6c, 0x00, 0x00, 0xb4, 0x83, 0x22, 0x50, - 0x81, 0x6c, 0x00, 0x00, 0xb5, 0x83, 0x22, 0x54, 0x81, 0x6c, 0x00, 0x00, - 0xb7, 0x83, 0x22, 0x58, 0x81, 0x6c, 0x00, 0x00, 0xbc, 0x83, 0x22, 0x5c, - 0x81, 0x6c, 0x00, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xbc, 0x09, 0xb0, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca, - 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xf3, 0x83, 0x01, 0x00, 0xae, 0x83, 0xa2, 0x42, - 0x05, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x05, 0xb0, 0x01, 0x00, - 0x6a, 0x84, 0x22, 0xca, 0x07, 0x14, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x45, - 0xf3, 0x93, 0x00, 0x00, 0x6a, 0x84, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00, - 0x6a, 0x84, 0x80, 0xca, 0x05, 0x30, 0x00, 0x00, 0x6a, 0x84, 0x22, 0x01, - 0x80, 0x30, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00, - 0x5c, 0x01, 0x00, 0xbc, 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, - 0xb1, 0xb3, 0x01, 0x00, 0x6a, 0x84, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, - 0xff, 0x00, 0x00, 0xca, 0x81, 0x88, 0x01, 0x00, 0x6a, 0x84, 0xa2, 0x40, - 0x74, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00, - 0xb9, 0x83, 0xa8, 0xb1, 0x82, 0x30, 0x00, 0x00, 0xb8, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x6a, 0x84, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xbf, 0x83, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xca, 0x83, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, - 0x80, 0xb0, 0x01, 0x00, 0xb6, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, - 0xc8, 0x83, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xca, 0x83, 0x56, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00, - 0xf3, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xcd, 0x83, 0x01, 0x00, - 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xcf, 0x83, 0xa2, 0x41, - 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xda, 0x83, 0x91, 0x81, - 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x80, 0xb0, 0x01, 0x00, - 0xb6, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, 0xd8, 0x83, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xda, 0x83, 0x55, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, - 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, 0xf3, 0x9f, 0x00, 0x41, - 0x8b, 0xb3, 0x00, 0x00, 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0xc4, 0x14, 0x2f, 0x40, 0x99, 0xb3, 0x01, 0x00, 0x5c, 0x01, 0x00, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0x58, 0x15, 0x2d, 0x40, 0x8d, 0xb0, 0x01, 0x00, - 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8f, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x90, 0xb0, 0x01, 0x00, - 0x00, 0xf8, 0x00, 0x48, 0x90, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, - 0x6a, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x02, 0x00, 0x00, 0xa6, - 0x80, 0xb0, 0x01, 0x00, 0xec, 0x83, 0x22, 0x40, 0x82, 0x6c, 0x00, 0x00, - 0xf0, 0x83, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x47, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00, - 0xf5, 0x83, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00, 0xe7, 0x83, 0xa2, 0x41, - 0x93, 0x50, 0x00, 0x00, 0xe5, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xff, 0x07, 0x00, 0x47, 0x84, 0x88, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xf5, 0x9f, 0x00, 0x47, 0x80, 0x30, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x47, 0x8e, 0xc8, 0x01, 0x00, 0xf0, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x50, 0xb3, 0x01, 0x00, - 0xfb, 0x83, 0x20, 0x18, 0x89, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa6, - 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, - 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00, 0xfe, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00, - 0x20, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, - 0x55, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x50, 0xd3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa8, 0x4f, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x4e, 0xd3, 0x01, 0x00, 0x5e, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x6c, 0x03, 0x00, 0x42, 0x80, 0x30, 0x01, 0x00, 0xf0, 0x83, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x07, 0x84, 0x22, 0xa7, 0x8f, 0x6c, 0x00, 0x00, - 0x49, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xa0, 0x94, 0x2e, 0x43, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x09, 0x84, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x50, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xac, 0x94, 0x2e, 0x43, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x0d, 0x84, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xae, 0x03, 0x00, 0x40, 0xa3, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x60, 0x15, 0x00, 0x40, - 0x85, 0x98, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x40, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x59, 0x41, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x41, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x40, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x41, - 0x81, 0x6c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, - 0x13, 0x84, 0x00, 0x50, 0x85, 0xc0, 0x00, 0x00, 0x49, 0x84, 0xa2, 0x41, - 0x01, 0x7d, 0x00, 0x00, 0x21, 0x84, 0x22, 0x58, 0x73, 0x7d, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x1c, 0x84, 0xa8, 0xb1, - 0x9c, 0x30, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x0e, 0x10, 0xc9, 0x00, 0x00, 0x21, 0x84, 0x33, 0xc4, - 0x81, 0x30, 0x00, 0x00, 0x24, 0x84, 0xa1, 0xad, 0x9d, 0x20, 0x00, 0x00, - 0x1b, 0x84, 0x13, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4e, - 0x5a, 0x83, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00, - 0x2c, 0x84, 0x22, 0xab, 0x80, 0x04, 0x00, 0x00, 0x2a, 0x84, 0xa2, 0x40, - 0x01, 0x7d, 0x00, 0x00, 0x2c, 0x84, 0x22, 0x5f, 0x57, 0x7d, 0x00, 0x00, - 0x21, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x84, 0x22, 0x5e, - 0x57, 0x7d, 0x00, 0x00, 0x84, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x31, 0x84, 0x22, 0x54, 0x73, 0x7d, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x2c, 0x84, 0xa8, 0xb1, 0x00, 0x30, 0x00, 0x00, - 0xfa, 0x85, 0xa2, 0x5f, 0x01, 0x7c, 0x00, 0x00, 0x5c, 0x89, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x33, 0x84, 0xa2, 0x5f, 0x59, 0x27, 0x00, 0x00, - 0x35, 0x84, 0xa2, 0x5c, 0x73, 0x7d, 0x00, 0x00, 0x3c, 0x84, 0xa2, 0x5e, - 0x73, 0x7d, 0x00, 0x00, 0x46, 0x84, 0x22, 0x5c, 0x73, 0x7d, 0x00, 0x00, - 0x47, 0x84, 0x37, 0x40, 0x81, 0x32, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x36, 0x84, 0xa8, 0xb1, 0x36, 0x30, 0x00, 0x00, - 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x38, 0x84, 0xa8, 0xb1, - 0x00, 0x30, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x02, 0x88, 0x01, 0x00, - 0x29, 0x86, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x47, 0x84, 0x34, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x3d, 0x84, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00, 0x44, 0x84, 0x52, 0x21, - 0x13, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14, 0x41, 0x2f, 0xc3, 0x01, 0x00, - 0xff, 0x3f, 0x00, 0x09, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x01, 0xf0, 0x01, 0x00, 0x87, 0x84, 0x00, 0x34, 0x13, 0x84, 0x00, 0x00, - 0xff, 0x3f, 0x14, 0x09, 0x00, 0x8c, 0x01, 0x00, 0xe5, 0x84, 0x00, 0x43, - 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x47, 0x84, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x13, 0x4e, - 0x5a, 0x93, 0x00, 0x00, 0xe6, 0x89, 0xa2, 0x48, 0xfd, 0x7f, 0x00, 0x00, - 0x4e, 0x84, 0x22, 0x59, 0x73, 0x7d, 0x00, 0x00, 0x79, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x4a, 0x84, 0x28, 0xb1, 0x7e, 0x31, 0x00, 0x00, - 0x4b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x52, 0x84, 0x21, 0xac, - 0x9c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x1f, 0xc3, 0x01, 0x00, - 0x04, 0x00, 0xa0, 0x5f, 0x9d, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0x58, 0x91, 0x01, 0x00, 0x56, 0x84, 0x22, 0x5a, 0x73, 0x7d, 0x00, 0x00, - 0x7a, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x53, 0x84, 0xa8, 0xb1, - 0x7e, 0x31, 0x00, 0x00, 0x01, 0x00, 0x00, 0xcf, 0x11, 0xc9, 0x00, 0x00, - 0x5c, 0x84, 0xa2, 0x40, 0x93, 0x7f, 0x00, 0x00, 0x5c, 0x84, 0x22, 0x44, - 0x93, 0x7f, 0x00, 0x00, 0x58, 0x84, 0x42, 0xa5, 0x80, 0x30, 0x00, 0x00, - 0x5b, 0x84, 0xa2, 0x40, 0x93, 0x7f, 0x00, 0x00, 0x71, 0x84, 0x1a, 0x40, - 0x93, 0x93, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x9a, 0x80, 0xa2, 0x40, 0x73, 0x7d, 0x00, 0x00, 0x9b, 0x89, 0x22, 0x44, - 0x21, 0x6f, 0x00, 0x00, 0x92, 0x89, 0x22, 0x40, 0x65, 0x7d, 0x00, 0x00, - 0xa0, 0x89, 0xa2, 0x5b, 0x73, 0x7d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x49, - 0x33, 0x7d, 0x00, 0x00, 0x66, 0x84, 0x22, 0x48, 0x33, 0x7d, 0x00, 0x00, - 0xff, 0x01, 0x00, 0x99, 0x80, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x81, 0xe0, 0x01, 0x00, 0xa8, 0x98, 0x2f, 0x40, 0x33, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe0, 0xc1, 0x01, 0x00, 0x69, 0x84, 0x22, 0x40, - 0xaf, 0x6f, 0x00, 0x00, 0x69, 0x84, 0x22, 0x40, 0x81, 0x6f, 0x00, 0x00, - 0xef, 0x89, 0x1f, 0xa5, 0x82, 0x6f, 0x00, 0x00, 0x49, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0x62, 0xb1, 0x01, 0x00, 0x1b, 0x84, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x6c, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x6f, 0x84, 0x33, 0x40, - 0x1f, 0x30, 0x00, 0x00, 0x1b, 0x84, 0x13, 0x4e, 0x5a, 0x93, 0x00, 0x00, - 0x73, 0x84, 0xa0, 0xce, 0x81, 0x50, 0x00, 0x00, 0x85, 0x84, 0xa0, 0xcd, - 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xb1, 0x81, 0xb0, 0x01, 0x00, 0x85, 0x84, 0x22, 0xb5, - 0x81, 0x14, 0x00, 0x00, 0x80, 0x15, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x77, 0x84, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb4, - 0x65, 0x97, 0x01, 0x00, 0xd0, 0x15, 0x2e, 0x40, 0x69, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x1a, 0x44, 0x93, 0x83, 0x01, 0x00, 0x1a, 0x00, 0x00, 0xa2, - 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xb1, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb5, - 0xf1, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x80, 0x84, 0xa8, 0xa1, - 0xe0, 0x31, 0x00, 0x00, 0x5c, 0x84, 0x00, 0x88, 0x9e, 0xb3, 0x00, 0x00, - 0x5c, 0x84, 0xa2, 0x41, 0x67, 0x6f, 0x00, 0x00, 0x5c, 0x84, 0x00, 0x6f, - 0xdb, 0x91, 0x00, 0x00, 0x85, 0x84, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x5c, 0x84, 0x1a, 0x40, 0x93, 0x83, 0x00, 0x00, 0x00, 0x99, 0x00, 0x09, - 0x46, 0xc9, 0x01, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x0c, 0x88, 0x01, 0x00, - 0x90, 0x84, 0xa6, 0x42, 0x13, 0x60, 0x00, 0x00, 0x3f, 0x97, 0x00, 0x95, - 0x03, 0x30, 0x01, 0x00, 0x8b, 0x84, 0x45, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x75, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x8c, 0x84, 0xa8, 0xb1, - 0x0c, 0x30, 0x00, 0x00, 0x46, 0x97, 0x1d, 0x10, 0x94, 0x30, 0x01, 0x00, - 0x91, 0x84, 0x00, 0x58, 0x1f, 0x90, 0x00, 0x00, 0x38, 0x97, 0x00, 0x95, - 0x03, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0xf0, - 0x2e, 0xb0, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x98, 0x84, 0x23, 0x4b, 0xe4, 0x6d, 0x00, 0x00, 0x98, 0x84, 0x22, 0x4b, - 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00, - 0x22, 0x00, 0x2f, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x9b, 0x84, 0x83, 0x17, - 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x9d, 0x84, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, - 0x47, 0xc1, 0x01, 0x00, 0xa2, 0x84, 0x22, 0x55, 0x2f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x43, 0xd1, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xfa, - 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x97, 0xe0, 0x01, 0x00, - 0xa3, 0x84, 0x00, 0x4b, 0x44, 0xc1, 0x00, 0x00, 0x12, 0x00, 0x00, 0xa2, - 0x44, 0xc9, 0x01, 0x00, 0x28, 0x00, 0x00, 0xf6, 0x02, 0xcc, 0x01, 0x00, - 0x0a, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x28, 0xf0, 0x10, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, - 0x2a, 0xb0, 0x01, 0x00, 0xc0, 0x28, 0x3c, 0x46, 0x0d, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x44, 0x95, 0xb0, 0x01, 0x00, 0xaf, 0x84, 0xa2, 0xf8, - 0x0e, 0x30, 0x00, 0x00, 0xbf, 0x84, 0x22, 0x41, 0x95, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x50, 0x49, 0xc1, 0x01, 0x00, 0xab, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xac, 0x84, 0xa2, 0xf8, 0x16, 0x6c, 0x00, 0x00, - 0xac, 0x84, 0xa2, 0xf8, 0x10, 0x6c, 0x00, 0x00, 0xac, 0x84, 0xa2, 0xf0, - 0x1a, 0x6c, 0x00, 0x00, 0xbd, 0x84, 0x22, 0x58, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0xb4, 0x84, 0x47, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xb8, 0x84, 0xa2, 0xf3, 0x74, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0xe6, 0x95, 0x01, 0x00, 0xbd, 0x84, 0x1f, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x96, 0xb0, 0x01, 0x00, - 0x3f, 0x00, 0x1f, 0xf3, 0x0c, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, - 0xbb, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xbd, 0x84, 0x47, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xc5, 0x84, 0x1f, 0x41, 0x2d, 0xc3, 0x00, 0x00, - 0xc3, 0x84, 0x22, 0x58, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x62, 0xb1, 0x01, 0x00, - 0xc1, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc3, 0x84, 0x47, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xec, 0x84, 0x1f, 0x41, 0x2d, 0xc3, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x0b, 0x96, 0x00, 0x07, - 0x16, 0x30, 0x01, 0x00, 0xd3, 0x84, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, - 0xcb, 0x84, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xd2, 0x84, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, - 0xff, 0x96, 0x00, 0x5f, 0x01, 0x10, 0x01, 0x00, 0xd1, 0x84, 0x22, 0x40, - 0x95, 0x6c, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x74, 0x96, 0x00, 0x52, - 0x95, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0xdb, 0x84, 0xa2, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xdb, 0x84, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00, 0xd8, 0x84, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x85, 0x98, 0x00, 0x42, - 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xce, 0x99, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0xde, 0x84, 0x82, 0xf0, 0x18, 0x30, 0x00, 0x00, - 0x66, 0x8b, 0x00, 0x45, 0x8f, 0xb0, 0x00, 0x00, 0x28, 0x20, 0x00, 0xa6, - 0x96, 0xb0, 0x01, 0x00, 0xe2, 0x84, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, - 0xf5, 0x97, 0x00, 0x4b, 0x95, 0x30, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x4b, - 0x8f, 0xb0, 0x00, 0x00, 0x0b, 0x97, 0x00, 0x03, 0x48, 0x31, 0x01, 0x00, - 0xe7, 0x94, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x68, 0x50, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xe9, 0x84, 0xa8, 0x00, - 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x2e, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x17, 0xb0, 0x01, 0x00, 0x00, 0x41, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00, - 0xee, 0x07, 0x2e, 0x47, 0x97, 0x90, 0x01, 0x00, 0xff, 0x84, 0x22, 0x17, - 0x96, 0x04, 0x00, 0x00, 0xfd, 0x84, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, - 0xfd, 0x84, 0x23, 0xa2, 0x02, 0x6c, 0x00, 0x00, 0x74, 0x96, 0x00, 0x52, - 0x95, 0x30, 0x01, 0x00, 0x04, 0x00, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x0c, 0x00, 0x2d, 0x00, 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, - 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x00, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0xb0, 0x01, 0x00, - 0x1c, 0x85, 0x00, 0x5c, 0x17, 0x90, 0x00, 0x00, 0x11, 0x85, 0x22, 0x43, - 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, - 0x0a, 0x85, 0x22, 0x5f, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, 0xf1, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, - 0xe0, 0xc9, 0x01, 0x00, 0x06, 0x85, 0x45, 0x42, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x07, 0x85, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x1d, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x20, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0xff, 0x0f, 0x00, 0xf6, - 0x80, 0x88, 0x01, 0x00, 0x0e, 0x85, 0xa2, 0xa6, 0x81, 0x6c, 0x00, 0x00, - 0x11, 0x85, 0x00, 0xf2, 0x3a, 0xb0, 0x00, 0x00, 0xf7, 0x85, 0xa2, 0x4b, - 0xfd, 0x7f, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x15, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1c, 0x85, 0x22, 0x4a, - 0x2f, 0x7c, 0x00, 0x00, 0x1c, 0x85, 0x22, 0x48, 0x2f, 0x7c, 0x00, 0x00, - 0x0a, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x3f, 0x00, 0x00, 0xf2, - 0x86, 0x88, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x43, 0x84, 0x88, 0x01, 0x00, - 0x05, 0x00, 0x00, 0x43, 0x80, 0xf4, 0x01, 0x00, 0x98, 0x94, 0x3d, 0x42, - 0x81, 0xe0, 0x01, 0x00, 0x1c, 0x85, 0xa2, 0x42, 0xe0, 0x7d, 0x00, 0x00, - 0xf7, 0x85, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x15, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x1c, 0x85, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, - 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x41, 0x47, 0xc3, 0x01, 0x00, - 0x22, 0x85, 0x22, 0xa1, 0x09, 0x6c, 0x00, 0x00, 0x6b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x1f, 0x85, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00, - 0x5b, 0x85, 0xa3, 0x92, 0x03, 0x6c, 0x00, 0x00, 0xf4, 0x98, 0x00, 0x40, - 0x95, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, - 0x15, 0x8a, 0x22, 0x08, 0x80, 0x32, 0x00, 0x00, 0x28, 0x85, 0x22, 0x5c, - 0x17, 0x7c, 0x00, 0x00, 0x29, 0x85, 0x00, 0x00, 0x2a, 0xb0, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0x02, 0x00, 0x00, 0x08, - 0x80, 0xc8, 0x01, 0x00, 0x2d, 0x85, 0xa2, 0x43, 0x2f, 0x7c, 0x00, 0x00, - 0xf8, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x49, 0x85, 0x00, 0x5e, - 0x17, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x8c, 0xcc, 0x01, 0x00, - 0xf8, 0x97, 0x00, 0x4c, 0x03, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, - 0x02, 0xb0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, - 0x0c, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x15, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x36, 0x85, 0xa8, 0x54, 0x17, 0x10, 0x00, 0x00, 0x49, 0x85, 0x00, 0x5e, - 0x17, 0x90, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, - 0x48, 0x85, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, - 0x8c, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x03, 0xb0, 0x01, 0x00, - 0x19, 0x98, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, - 0x02, 0xb0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, - 0x0c, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x09, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x15, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x49, 0x85, 0x28, 0x54, 0x17, 0x10, 0x00, 0x00, 0x45, 0x85, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x19, 0x98, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, - 0x4b, 0x85, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, - 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17, 0x98, 0x88, 0x01, 0x00, - 0x4e, 0x85, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x17, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x4f, 0x85, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x56, 0x85, 0x22, 0x43, - 0x2f, 0x7c, 0x00, 0x00, 0x16, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1d, 0xe4, 0xb1, 0x01, 0x00, 0xa1, 0x97, 0x00, 0x5e, - 0x05, 0x10, 0x01, 0x00, 0x59, 0x85, 0xa2, 0x5f, 0x2f, 0x7c, 0x00, 0x00, - 0xb9, 0x94, 0x00, 0x01, 0x38, 0x43, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x15, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x5d, 0x85, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0xf4, 0x85, 0x00, 0x41, - 0x43, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x27, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x5f, 0x85, 0x35, 0x01, - 0x86, 0x30, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x66, 0x85, 0x28, 0xb1, 0x30, 0x30, 0x00, 0x00, 0x60, 0x85, 0x22, 0x4d, - 0x75, 0x7d, 0x00, 0x00, 0xe4, 0x85, 0xa2, 0x40, 0x11, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, 0xf3, 0x85, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x66, 0x85, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00, 0x6f, 0x85, 0xa2, 0x40, - 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x09, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x2c, 0xb0, 0x01, 0x00, 0xde, 0x07, 0x00, 0x43, 0x80, 0xce, 0x01, 0x00, - 0x60, 0x85, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0x74, 0x85, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x3e, 0x43, 0x27, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x27, 0xc0, 0x01, 0x00, - 0x60, 0x85, 0xa3, 0x0b, 0x87, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, - 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0x40, 0x00, 0x2d, 0x40, - 0x39, 0xb0, 0x01, 0x00, 0x7c, 0x85, 0xa2, 0x40, 0x27, 0x6c, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x08, 0x12, 0xc8, 0x01, 0x00, 0xde, 0x07, 0x00, 0x40, - 0x25, 0x98, 0x01, 0x00, 0x7f, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x30, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x25, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x14, 0x00, 0x20, 0x01, - 0xe0, 0xb1, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00, - 0x84, 0x85, 0x23, 0x01, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x36, 0xb0, 0x01, 0x00, 0x8f, 0x85, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x8b, 0x85, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x88, 0x85, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xeb, 0x95, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x44, 0xc9, 0x01, 0x00, 0x9e, 0x85, 0x22, 0x45, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, - 0x62, 0xdd, 0x01, 0x00, 0x95, 0x85, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x33, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x25, 0xd0, 0x01, 0x00, - 0x0c, 0x00, 0x2d, 0x4c, 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x37, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2b, 0xc0, 0x01, 0x00, - 0x84, 0x85, 0x00, 0x45, 0x1f, 0x80, 0x00, 0x00, 0xa0, 0x85, 0xa3, 0x12, - 0x36, 0x6c, 0x00, 0x00, 0xa1, 0x85, 0x68, 0x1b, 0x28, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x68, 0x12, 0x28, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, - 0x62, 0xdd, 0x01, 0x00, 0xa4, 0x85, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, - 0xca, 0x85, 0x22, 0x14, 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x33, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00, - 0x0c, 0x00, 0x2d, 0x14, 0x12, 0xc0, 0x01, 0x00, 0xc3, 0x85, 0xa2, 0x14, - 0x36, 0x50, 0x00, 0x00, 0xb4, 0x85, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xb2, 0x85, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xaf, 0x85, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x2a, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x2b, 0x80, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, - 0x37, 0x98, 0x01, 0x00, 0xb9, 0x85, 0x23, 0x01, 0x36, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x36, 0xb0, 0x01, 0x00, 0xc4, 0x85, 0x22, 0x1b, - 0x02, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0xff, 0x07, 0x00, 0x15, 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0xc0, 0x85, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc4, 0x85, 0x00, 0x03, - 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x2a, 0xc0, 0x01, 0x00, - 0x84, 0x85, 0xa2, 0x40, 0x25, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x39, 0xc0, 0x01, 0x00, 0x40, 0x00, 0x3d, 0x43, 0x39, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x12, 0xb0, 0x01, 0x00, 0x84, 0x85, 0x00, 0xf0, 0x30, 0xb0, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0xd0, 0x85, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0xcd, 0x85, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xeb, 0x95, 0x00, 0x40, 0x2b, 0x30, 0x01, 0x00, 0x18, 0x00, 0x2e, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0xd4, 0x85, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x56, 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17, - 0x98, 0x88, 0x01, 0x00, 0xd7, 0x85, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x17, 0x90, 0x01, 0x00, 0xda, 0x85, 0x22, 0x43, - 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x17, 0x90, 0x01, 0x00, - 0x16, 0x00, 0x20, 0x1d, 0xe4, 0xb1, 0x01, 0x00, 0xdc, 0x85, 0xa3, 0x40, - 0x27, 0x6c, 0x00, 0x00, 0xde, 0x85, 0x60, 0x5f, 0x17, 0x90, 0x00, 0x00, - 0x00, 0x84, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x60, 0x13, - 0x16, 0x94, 0x01, 0x00, 0xa1, 0x97, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, - 0x15, 0x8a, 0xa2, 0x5f, 0x2f, 0x7c, 0x00, 0x00, 0x14, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, - 0xb9, 0x94, 0x00, 0x01, 0x38, 0x43, 0x01, 0x00, 0x15, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4d, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0x62, 0xb1, 0x01, 0x00, 0xe6, 0x85, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x62, 0xb1, 0x01, 0x00, 0xe8, 0x85, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xf3, 0x85, 0x22, 0x13, 0x82, 0x6c, 0x00, 0x00, - 0x40, 0x00, 0x3d, 0x43, 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x16, 0x62, 0xb1, 0x01, 0x00, 0xee, 0x85, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x62, 0xb1, 0x01, 0x00, - 0xf0, 0x85, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xea, 0x85, 0x00, 0x41, - 0x83, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, - 0x74, 0x96, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x15, 0x8a, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x01, 0x80, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x0e, 0xf4, 0x01, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x0b, 0x96, 0x00, 0x07, - 0x16, 0x30, 0x01, 0x00, 0x05, 0x86, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, - 0x03, 0x86, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x04, 0x86, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0x0d, 0x86, 0xa2, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0d, 0x86, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00, 0x0a, 0x86, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x85, 0x98, 0x00, 0x42, - 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xce, 0x99, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, - 0x13, 0x86, 0x22, 0x3a, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8e, 0xb0, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40, 0x01, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x17, 0x86, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40, - 0x01, 0xb0, 0x00, 0x00, 0x51, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x38, 0x97, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0x22, 0x00, 0x2d, 0xf0, 0x2e, 0xb0, 0x01, 0x00, 0x28, 0x20, 0x00, 0xa6, - 0x96, 0xb0, 0x01, 0x00, 0x20, 0x86, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, - 0xf5, 0x97, 0x00, 0x4b, 0x95, 0x30, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x4c, - 0x8f, 0xb0, 0x00, 0x00, 0x22, 0x86, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x43, 0xc1, 0x01, 0x00, 0x24, 0x86, 0x85, 0x17, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x43, 0xc1, 0x01, 0x00, - 0x28, 0x00, 0x00, 0xf6, 0x02, 0xcc, 0x01, 0x00, 0x12, 0x00, 0x00, 0xa1, - 0x2a, 0xc8, 0x01, 0x00, 0x0b, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xe7, 0x94, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x2e, 0x86, 0x46, 0x47, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0x2f, 0x86, 0xa8, 0x1b, 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x1e, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xe0, 0x01, 0x00, - 0x08, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x54, 0x86, 0x01, 0xfb, - 0x08, 0x30, 0x00, 0x00, 0xa7, 0x86, 0x87, 0xfb, 0x22, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0x0e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x14, 0xb0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, - 0x0b, 0x96, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, 0x4a, 0x86, 0x22, 0x41, - 0x81, 0x6c, 0x00, 0x00, 0x3e, 0x86, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x49, 0x86, 0x22, 0x5f, - 0x0f, 0x7c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x04, 0x7e, 0x89, 0x01, 0x00, - 0x42, 0x86, 0xa6, 0x5f, 0x0f, 0x00, 0x00, 0x00, 0x5f, 0x95, 0x00, 0x40, - 0x05, 0x30, 0x01, 0x00, 0x47, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0xea, 0x96, 0x00, 0x40, - 0x05, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0x52, 0x86, 0xa2, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x52, 0x86, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00, 0x4f, 0x86, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x85, 0x98, 0x00, 0x42, - 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xce, 0x99, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, - 0x56, 0x86, 0x21, 0x04, 0x80, 0x20, 0x00, 0x00, 0x57, 0x86, 0x00, 0x40, - 0x10, 0xc9, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x4b, 0x81, 0xb0, 0x00, 0x00, - 0x76, 0x86, 0x00, 0x43, 0x81, 0xb0, 0x00, 0x00, 0x7a, 0x86, 0x00, 0xfb, - 0x22, 0xb0, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00, - 0x66, 0x8b, 0x00, 0x4e, 0x8f, 0xb0, 0x00, 0x00, 0x72, 0x86, 0x00, 0x5a, - 0x8f, 0xb0, 0x00, 0x00, 0x5f, 0x86, 0x00, 0x47, 0x8f, 0xb0, 0x00, 0x00, - 0xa8, 0x8a, 0x00, 0x53, 0x81, 0xb0, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x56, - 0x81, 0xb0, 0x00, 0x00, 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x66, 0x8b, 0xa0, 0x0a, 0xe4, 0x6d, 0x00, 0x00, 0x65, 0x86, 0xa2, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0x64, 0x86, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, - 0x66, 0x8b, 0x00, 0x53, 0x8f, 0xb0, 0x00, 0x00, 0x66, 0x8b, 0x00, 0x54, - 0x8f, 0xb0, 0x00, 0x00, 0x6e, 0x86, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, - 0x68, 0x86, 0xa2, 0x0a, 0xe4, 0x6d, 0x00, 0x00, 0x66, 0x8b, 0x00, 0x5d, - 0x8f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x80, 0xd0, 0x01, 0x00, 0x6c, 0x86, 0xa0, 0x91, - 0x81, 0x6c, 0x00, 0x00, 0x66, 0x8b, 0x00, 0x5e, 0x8f, 0xb0, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x70, 0x86, 0x20, 0x91, 0xe5, 0x6d, 0x00, 0x00, - 0x66, 0x8b, 0x00, 0x54, 0x8f, 0xb0, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x66, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x66, 0x8b, 0xa0, 0x0a, - 0xe4, 0x6d, 0x00, 0x00, 0x24, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x66, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x82, 0xf4, 0x01, 0x00, - 0xa8, 0x8a, 0xa0, 0x42, 0x83, 0x6c, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x54, - 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, - 0x42, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00, - 0x83, 0x86, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x40, - 0x87, 0x98, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0xff, 0x89, 0x00, 0x5c, - 0x1f, 0x90, 0x00, 0x00, 0x95, 0x86, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, - 0x90, 0x86, 0xa2, 0x54, 0xfd, 0x7f, 0x00, 0x00, 0x88, 0x86, 0x22, 0x55, - 0xfd, 0x7f, 0x00, 0x00, 0x82, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x80, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x80, 0x86, 0x22, 0x53, - 0xfd, 0x7f, 0x00, 0x00, 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4b, - 0x80, 0xf4, 0x01, 0x00, 0x0c, 0xbc, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x90, 0x86, 0x22, 0x43, 0x80, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, - 0x80, 0x88, 0x01, 0x00, 0x80, 0x86, 0xa2, 0x43, 0x80, 0x6c, 0x00, 0x00, - 0x7c, 0x96, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x91, 0x86, 0x43, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x94, 0x86, 0xa0, 0xf0, 0x30, 0x6f, 0x00, 0x00, - 0x86, 0x86, 0x1b, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x41, - 0x31, 0xc3, 0x01, 0x00, 0x90, 0x95, 0x00, 0x40, 0x25, 0x30, 0x01, 0x00, - 0x99, 0x86, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, - 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x07, 0x18, 0xe4, 0x01, 0x00, 0x00, 0x08, 0x00, 0x0c, - 0xe0, 0x99, 0x01, 0x00, 0xce, 0x99, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, - 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0xa0, 0x86, 0x30, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, - 0x00, 0x02, 0x00, 0xa1, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0xe6, 0x91, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x10, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xa8, 0x8a, 0x00, 0x40, - 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x28, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfb, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x14, 0xb0, 0x01, 0x00, 0xb1, 0x86, 0x22, 0x46, 0x23, 0x7c, 0x00, 0x00, - 0xad, 0x86, 0x22, 0x40, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, - 0x1f, 0x90, 0x01, 0x00, 0xaf, 0x86, 0x22, 0x41, 0x87, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x1f, 0x90, 0x01, 0x00, 0xb1, 0x86, 0x22, 0x42, - 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, - 0xb1, 0x86, 0x47, 0x1b, 0x2c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, - 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x41, 0x41, 0xc3, 0x01, 0x00, - 0xe0, 0x86, 0x23, 0x92, 0x15, 0x6c, 0x00, 0x00, 0xe0, 0x86, 0xa2, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0xe4, 0x86, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, - 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x27, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x0a, 0x24, 0xc8, 0x01, 0x00, - 0xc7, 0x95, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, 0xde, 0x86, 0x22, 0x08, - 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, - 0xf0, 0x07, 0x00, 0x12, 0x24, 0xcc, 0x01, 0x00, 0xba, 0x86, 0xaa, 0x41, - 0x27, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x80, 0xcc, 0x01, 0x00, - 0xda, 0x86, 0x26, 0x40, 0x23, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x60, 0x00, 0x00, 0x03, 0x84, 0xc8, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x48, 0xcd, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0, - 0xa2, 0xc9, 0x01, 0x00, 0xc7, 0x86, 0xa2, 0x40, 0x83, 0x6c, 0x00, 0x00, - 0xd3, 0x86, 0x00, 0x41, 0x83, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x42, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x68, 0x21, 0x38, 0x96, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, 0xcc, 0x86, 0xa2, 0x44, - 0x23, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x20, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xcf, 0x86, 0xa8, 0x42, - 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x85, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xa3, 0xc1, 0x01, 0x00, 0xc5, 0x86, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0xda, 0x86, 0x22, 0x40, 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xd7, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0xee, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0, - 0x2a, 0xc8, 0x01, 0x00, 0xed, 0x86, 0x00, 0x17, 0x10, 0xb0, 0x00, 0x00, - 0xaa, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xe4, 0x86, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xc7, 0x95, 0x00, 0x92, 0x25, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x31, 0xb0, 0x01, 0x00, 0xe4, 0x86, 0x22, 0x08, - 0x2e, 0x30, 0x00, 0x00, 0xed, 0x86, 0x00, 0x41, 0x27, 0xb0, 0x00, 0x00, - 0x80, 0x80, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, - 0x87, 0x98, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x0a, 0x8c, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x90, 0x01, 0x00, 0xec, 0x86, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x88, 0x1c, 0xcc, 0x01, 0x00, 0x6b, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xff, 0x89, 0x00, 0x41, 0x3f, 0xc3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x01, - 0x80, 0xce, 0x01, 0x00, 0x01, 0x87, 0x2a, 0x40, 0x81, 0x30, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0xf6, 0x86, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, - 0xf6, 0x86, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0xf6, 0x86, 0xa3, 0x07, - 0x03, 0x6c, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0xf9, 0x86, 0xa3, 0x40, 0x02, 0x6c, 0x00, 0x00, 0x28, 0x00, 0x00, 0x01, - 0xf0, 0xcd, 0x01, 0x00, 0xfb, 0x86, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x40, 0xf0, 0xcd, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x0e, 0xcc, 0x01, 0x00, 0x28, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, - 0x28, 0x00, 0x00, 0x00, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xff, 0x86, 0xa8, 0x5c, - 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x08, 0xb0, 0x01, 0x00, 0xa0, 0x01, 0x2d, 0x40, - 0x00, 0xc0, 0x01, 0x00, 0xe7, 0x88, 0x22, 0x0f, 0x42, 0x05, 0x00, 0x00, - 0x12, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0x0d, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x0a, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x12, 0x87, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, - 0x42, 0xc1, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa1, 0x46, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, 0xd1, 0x87, 0xa2, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x54, 0x29, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, 0x42, 0x00, 0x00, 0x03, - 0x0a, 0xc8, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x14, 0x10, 0xc0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x08, - 0x10, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0xfe, 0x7f, 0x00, 0x05, 0x44, 0xc9, 0x01, 0x00, 0x23, 0x87, 0x20, 0x94, - 0x15, 0x6c, 0x00, 0x00, 0x24, 0x87, 0x00, 0x94, 0xe5, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0xe4, 0xb1, 0x01, 0x00, 0x3d, 0x87, 0x22, 0x01, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0x2a, 0x87, 0xa3, 0x07, 0x02, 0x6c, 0x00, 0x00, - 0x2b, 0x87, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x07, - 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, 0x37, 0x87, 0x22, 0x40, - 0x03, 0x6c, 0x00, 0x00, 0x37, 0x87, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x5f, 0x87, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x34, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0x39, 0x87, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5f, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0x42, 0x87, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00, - 0x43, 0x87, 0x68, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, - 0x1a, 0xb0, 0x01, 0x00, 0x46, 0x87, 0x80, 0x08, 0xf0, 0x31, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x11, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x1e, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x01, 0x1f, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x4a, 0x87, 0xa8, 0x5c, - 0x1f, 0x10, 0x00, 0x00, 0x7d, 0x87, 0x22, 0x0d, 0x14, 0x6c, 0x00, 0x00, - 0x50, 0x87, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x10, 0xc0, 0x01, 0x00, 0x54, 0x87, 0x00, 0x0d, 0x24, 0xd0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x2b, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, - 0xa2, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x20, 0x10, 0xc8, 0x01, 0x00, - 0xf0, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, 0x56, 0x87, 0x22, 0x42, - 0x23, 0x6c, 0x00, 0x00, 0x5f, 0x87, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x57, 0x87, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x5d, 0x87, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00, - 0xfb, 0x95, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f, - 0x1e, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x7d, 0x87, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, 0x7c, 0x87, 0xa2, 0x0d, - 0x0e, 0x50, 0x00, 0x00, 0x6b, 0x87, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x69, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x66, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, - 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, - 0x70, 0x87, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00, 0x24, 0x87, 0x00, 0x4c, - 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, - 0x24, 0x87, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, - 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x79, 0x87, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, 0x24, 0x87, 0x00, 0x03, - 0x0c, 0xb0, 0x00, 0x00, 0x24, 0x87, 0x00, 0x0d, 0x18, 0xc0, 0x00, 0x00, - 0x04, 0x00, 0x2e, 0x14, 0x0a, 0xd0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x05, - 0x48, 0xcd, 0x01, 0x00, 0xfe, 0x7f, 0x00, 0x05, 0x42, 0xc9, 0x01, 0x00, - 0x0c, 0x00, 0x2a, 0xf2, 0xe0, 0xb1, 0x01, 0x00, 0x83, 0x87, 0x22, 0x40, - 0x31, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00, - 0x1e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x81, 0x00, 0xf6, - 0x80, 0xce, 0x01, 0x00, 0x87, 0x87, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x43, 0xc1, 0x01, 0x00, 0x89, 0x87, 0x22, 0x0b, - 0xed, 0x6d, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00, - 0x02, 0x00, 0x00, 0xa1, 0x46, 0xc9, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xfa, - 0x94, 0x88, 0x01, 0x00, 0x02, 0x00, 0x00, 0x4a, 0x86, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf6, 0x0e, 0xb0, 0x01, 0x00, 0x91, 0x87, 0x22, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x1f, 0x43, 0x0e, 0x50, 0x00, 0x00, - 0x91, 0x87, 0xa0, 0x46, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x0f, 0xc0, 0x01, 0x00, 0x95, 0x87, 0x22, 0x48, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x0f, 0xa2, - 0x42, 0x31, 0x00, 0x00, 0x98, 0x87, 0x00, 0x40, 0x89, 0xb0, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0xa2, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x95, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x82, 0xb0, 0x01, 0x00, 0x9b, 0x87, 0xa0, 0x41, - 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00, - 0xa0, 0x87, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0xa0, 0x87, 0xa0, 0x43, - 0x89, 0x6c, 0x00, 0x00, 0xa0, 0x87, 0x20, 0x45, 0x89, 0x6c, 0x00, 0x00, - 0xa0, 0x87, 0xa0, 0x41, 0x0e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x0f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xc0, 0x01, 0x00, - 0x98, 0x87, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, 0xa9, 0x87, 0x22, 0x48, - 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x48, 0x92, 0xf4, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x48, 0x90, 0x88, 0x01, 0x00, 0xa7, 0x87, 0x90, 0x48, - 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, - 0x0a, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, - 0x93, 0xa4, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x14, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17, - 0xf0, 0xb1, 0x01, 0x00, 0x12, 0x00, 0x00, 0x05, 0xe0, 0xcd, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, - 0xaf, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xbc, 0x87, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0xb9, 0x87, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xb6, 0x87, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xbc, 0x87, 0x87, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0xfb, 0x95, 0x00, 0x41, 0x23, 0x40, 0x01, 0x00, - 0xbe, 0x87, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x52, 0x89, 0x00, 0x17, - 0x10, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0xc1, 0x87, 0xa0, 0x07, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, 0xc5, 0x87, 0x90, 0xf2, - 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14, - 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2b, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x2a, 0x94, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0xcf, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xcc, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x17, - 0x10, 0xdc, 0x01, 0x00, 0x52, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x90, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd5, 0x87, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x66, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x05, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x3c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x34, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x32, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x0a, 0xc8, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, - 0x0c, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x1b, 0x88, 0x22, 0x01, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0xea, 0x87, 0xa3, 0x07, 0x02, 0x6c, 0x00, 0x00, - 0xeb, 0x87, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x07, - 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, 0xfd, 0x87, 0x22, 0x40, - 0x03, 0x6c, 0x00, 0x00, 0xf7, 0x87, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x37, 0x88, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf4, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0xf9, 0x87, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x37, 0x88, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0xff, 0x87, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x22, 0x00, 0x00, 0x19, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, - 0x0f, 0x00, 0x00, 0xf2, 0x3a, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x3b, 0xe0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00, 0x0b, 0x88, 0x23, 0x1a, - 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0xc0, 0x01, 0x00, - 0x37, 0x88, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x1d, - 0x48, 0xc1, 0x01, 0x00, 0xf0, 0x00, 0x00, 0xf2, 0x30, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x31, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x02, 0xc0, 0x01, 0x00, 0x13, 0x88, 0x22, 0x1a, - 0x02, 0x50, 0x00, 0x00, 0x37, 0x88, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x19, 0x48, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x14, - 0x48, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x14, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1d, 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x24, 0xb0, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x17, 0x10, 0xc8, 0x01, 0x00, 0x37, 0x88, 0x00, 0x1a, - 0x10, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0x20, 0x88, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00, - 0x21, 0x88, 0x68, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, - 0x1a, 0xb0, 0x01, 0x00, 0x24, 0x88, 0x80, 0x08, 0xf0, 0x31, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x11, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x1e, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x01, 0x1f, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x28, 0x88, 0xa8, 0x5c, - 0x1f, 0x10, 0x00, 0x00, 0x54, 0x88, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, - 0x54, 0x88, 0x22, 0x0d, 0x24, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x10, 0xc0, 0x01, 0x00, 0x2f, 0x88, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, - 0x37, 0x88, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x30, 0x88, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0xfb, 0x95, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f, - 0x1e, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x53, 0x88, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00, 0x42, 0x88, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x40, 0x88, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x3d, 0x88, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x04, 0xb0, 0x01, 0x00, 0x47, 0x88, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00, - 0xe4, 0x87, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f, - 0x0f, 0x80, 0x01, 0x00, 0xe4, 0x87, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x50, 0x88, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0xe4, 0x87, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0xe4, 0x87, 0x00, 0x0d, - 0x18, 0xc0, 0x00, 0x00, 0x71, 0x88, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x19, 0x0a, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, - 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, - 0x02, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0x0d, 0x00, 0x2d, 0x1d, 0x48, 0xc1, 0x01, 0x00, - 0x09, 0x00, 0x00, 0xf3, 0x38, 0x88, 0x01, 0x00, 0x0d, 0x00, 0x20, 0x50, - 0xe7, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0x40, 0x3f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf4, 0x32, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x1d, - 0x94, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00, - 0x66, 0x88, 0xa0, 0xfc, 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x91, 0xc0, 0x01, 0x00, 0x64, 0x88, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, - 0x04, 0x80, 0x00, 0x05, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x48, 0xc1, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x18, 0x94, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x18, - 0x90, 0xb0, 0x01, 0x00, 0x6e, 0x88, 0xa0, 0xfc, 0x90, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00, 0x6c, 0x88, 0xa2, 0x41, - 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe0, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x48, 0xc1, 0x01, 0x00, - 0x04, 0x80, 0x00, 0x05, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xc0, 0x01, 0x00, - 0x76, 0x88, 0x42, 0x30, 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x41, 0x3d, 0xc3, 0x01, 0x00, - 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, - 0x82, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x2e, 0x1d, 0x82, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x66, 0x18, 0x82, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x80, 0xc0, 0x01, 0x00, 0x80, 0x88, 0xa0, 0x41, 0x80, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, - 0x92, 0xf4, 0x01, 0x00, 0x0a, 0x00, 0x2e, 0x30, 0x81, 0x84, 0x01, 0x00, - 0x84, 0x88, 0x90, 0x40, 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x93, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x93, 0xa4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1d, 0x48, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x20, 0x19, - 0xe8, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x16, 0xc0, 0x01, 0x00, - 0x8a, 0x88, 0xa0, 0x19, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x0d, 0x00, 0x2f, 0x1e, 0x32, 0xc0, 0x01, 0x00, - 0x8f, 0x88, 0xa2, 0x40, 0x15, 0x6c, 0x00, 0x00, 0x8e, 0x88, 0xa0, 0x1c, - 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x63, 0xf3, 0x38, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x05, - 0x48, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x1e, 0x98, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x1a, 0x98, 0xc0, 0x01, 0x00, 0x0c, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x9d, 0x88, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x9b, 0x88, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x98, 0x88, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, - 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x12, 0x00, 0x00, 0x1a, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17, 0xf0, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, - 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, 0xa3, 0x88, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xb1, 0x88, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0xad, 0x88, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xaa, 0x88, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0xfb, 0x95, 0x00, 0x41, 0x23, 0x40, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f, - 0x1e, 0x8c, 0x01, 0x00, 0x20, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x17, 0xf0, 0x01, 0x00, 0xb6, 0x88, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, - 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14, 0x2a, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1d, 0x2a, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2a, 0x94, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xc1, 0x88, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xbe, 0x88, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00, 0xde, 0x88, 0x22, 0x40, - 0x15, 0x6c, 0x00, 0x00, 0xc9, 0x88, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x1f, 0x90, 0x01, 0x00, 0xc8, 0x88, 0x22, 0x9f, - 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88, 0x1c, 0xcc, 0x01, 0x00, - 0x6b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x3f, 0xc3, 0x01, 0x00, 0x4e, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xcc, 0x88, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, - 0x3e, 0xc0, 0x01, 0x00, 0xde, 0x88, 0x22, 0x40, 0x15, 0x6c, 0x00, 0x00, - 0xcf, 0x88, 0x20, 0x1e, 0x14, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x3c, 0xb0, 0x01, 0x00, 0xc7, 0x95, 0x00, 0x1e, 0x24, 0x30, 0x01, 0x00, - 0xd4, 0x88, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, - 0x11, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x10, 0xc0, 0x01, 0x00, - 0x37, 0x88, 0x00, 0x40, 0x17, 0xb0, 0x00, 0x00, 0x6b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xc7, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd1, 0x88, 0xa2, 0x08, 0x2e, 0x30, 0x00, 0x00, 0x80, 0x80, 0x00, 0xa6, - 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0x04, - 0xe0, 0x31, 0x00, 0x00, 0x3d, 0x99, 0x00, 0x1f, 0x8c, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0xff, 0x89, 0x00, 0x5c, - 0x1f, 0x90, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00, 0x4e, 0x99, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xe3, 0x88, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00, - 0xe4, 0x88, 0x00, 0x1e, 0x3e, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, - 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x3d, 0x99, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, 0xff, 0x89, 0x00, 0x5c, - 0x1f, 0x90, 0x00, 0x00, 0xef, 0x88, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0xef, 0x88, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xec, 0x88, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xf4, 0x88, 0x22, 0x07, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x42, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa1, - 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, - 0x04, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00, 0xf7, 0x88, 0x20, 0x94, - 0x15, 0x6c, 0x00, 0x00, 0xf8, 0x88, 0x00, 0x94, 0xe1, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0xe0, 0xb1, 0x01, 0x00, 0xfb, 0x88, 0x22, 0x40, - 0x31, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x89, 0xa8, 0x40, - 0x23, 0x30, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x52, 0x11, 0xc0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, - 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xc1, 0x01, 0x00, - 0x0e, 0x89, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00, 0x0f, 0x89, 0x68, 0x07, - 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, 0x1a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x01, 0x1f, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, - 0x14, 0x89, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, 0x45, 0x89, 0x22, 0x0d, - 0x14, 0x6c, 0x00, 0x00, 0x1a, 0x89, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x10, 0xc0, 0x01, 0x00, 0x1e, 0x89, 0x00, 0x0d, - 0x24, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2b, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x20, - 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, - 0x20, 0x89, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, 0x27, 0x89, 0x00, 0x41, - 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x21, 0x89, 0xa8, 0x5c, - 0x1f, 0x00, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00, 0xc2, 0x94, 0x00, 0x43, - 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, 0x44, 0x89, 0xa2, 0x0d, - 0x0e, 0x50, 0x00, 0x00, 0x33, 0x89, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x31, 0x89, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x2e, 0x89, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, - 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, - 0x38, 0x89, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00, 0x09, 0x89, 0x00, 0x4c, - 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, - 0x09, 0x89, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, - 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x41, 0x89, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, 0x09, 0x89, 0x00, 0x03, - 0x0c, 0xb0, 0x00, 0x00, 0x09, 0x89, 0x00, 0x0d, 0x18, 0xc0, 0x00, 0x00, - 0x4e, 0x89, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x4e, 0x89, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x4b, 0x89, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00, 0xc2, 0x94, 0x00, 0x41, - 0x23, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17, 0x10, 0xb0, 0x01, 0x00, - 0x52, 0x89, 0x00, 0x40, 0x2b, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0xe0, 0xb1, 0x01, 0x00, - 0x57, 0x89, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88, - 0x1c, 0xcc, 0x01, 0x00, 0x6b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x4e, 0x99, 0x00, 0x41, 0x3f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x3d, 0x99, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, 0x15, 0x8a, 0x00, 0x5c, - 0x1f, 0x90, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0e, 0xf4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x3a, 0x01, 0x84, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, - 0x1a, 0xf4, 0x01, 0x00, 0x0b, 0x96, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, - 0x66, 0x89, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, 0x64, 0x89, 0x22, 0x42, - 0x81, 0x6c, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x65, 0x89, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, 0xff, 0x89, 0x00, 0x40, - 0x0f, 0xb0, 0x00, 0x00, 0x6e, 0x89, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, - 0x86, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x6e, 0x89, 0x22, 0x20, - 0x85, 0x6c, 0x00, 0x00, 0x6b, 0x89, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x66, 0x96, 0x00, 0x5c, - 0x1f, 0x00, 0x01, 0x00, 0x85, 0x98, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xce, 0x99, 0x00, 0x07, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xb0, 0x01, 0x00, 0xa8, 0x8a, 0xa2, 0x5f, 0x81, 0x6c, 0x00, 0x00, - 0xa8, 0x00, 0x2d, 0x43, 0x19, 0x80, 0x01, 0x00, 0x37, 0x00, 0x2d, 0xf0, - 0x24, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x8e, 0xf4, 0x01, 0x00, - 0x0f, 0x00, 0x00, 0xf3, 0x90, 0x88, 0x01, 0x00, 0x7d, 0x89, 0x22, 0x48, - 0x8e, 0x6c, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0x7d, 0x89, 0x1f, 0xf0, - 0x24, 0x6c, 0x00, 0x00, 0x7c, 0x89, 0x23, 0x41, 0x8f, 0x6c, 0x00, 0x00, - 0xa8, 0x8a, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x48, - 0x81, 0xb0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xb0, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00, 0x82, 0x89, 0x22, 0x0a, - 0x90, 0x40, 0x00, 0x00, 0x21, 0x99, 0x00, 0x40, 0x91, 0x30, 0x01, 0x00, - 0xa8, 0x8a, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0xb0, 0x00, 0x2d, 0x45, - 0x81, 0xb0, 0x01, 0x00, 0x8e, 0x89, 0x22, 0xf0, 0x2c, 0x30, 0x00, 0x00, - 0xa3, 0x00, 0x2d, 0x30, 0x83, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0xf3, - 0x82, 0xe0, 0x01, 0x00, 0x88, 0x89, 0xa3, 0x41, 0x2c, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x16, 0x82, 0xb0, 0x01, 0x00, 0x98, 0x00, 0x2d, 0xf0, - 0x82, 0xc0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, 0x82, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x98, 0xe8, 0x01, 0x00, 0xa8, 0x8a, 0x20, 0x4c, - 0x82, 0x6c, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0x41, 0x98, 0xe8, 0x01, 0x00, - 0xa8, 0x8a, 0x20, 0xf0, 0x98, 0x6c, 0x00, 0x00, 0xff, 0x89, 0x22, 0x0a, - 0x80, 0x32, 0x00, 0x00, 0x40, 0x02, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00, - 0xff, 0x89, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xa8, 0x8a, 0x00, 0x49, - 0x81, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, - 0x96, 0x89, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, 0x13, 0x80, 0x00, 0x40, - 0x80, 0xdc, 0x01, 0x00, 0x97, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x1a, 0x80, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0x97, 0x89, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0xb1, 0x01, 0x00, - 0x99, 0x89, 0x9f, 0x85, 0x80, 0x32, 0x00, 0x00, 0x9d, 0x89, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x5f, 0x84, 0x22, 0x40, 0x57, 0x7d, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x40, 0x57, 0x99, 0x01, 0x00, 0x9d, 0x89, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x49, 0x84, 0x1a, 0x5b, 0x69, 0x93, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xa0, 0x89, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, - 0xc9, 0x89, 0x1d, 0x40, 0x80, 0x32, 0x00, 0x00, 0xba, 0x89, 0x22, 0x40, - 0xaf, 0x6f, 0x00, 0x00, 0xba, 0x89, 0x22, 0x5b, 0x81, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x5d, 0x73, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xa6, 0x89, 0xa8, 0xb1, 0x94, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0x62, 0xb1, 0x01, 0x00, 0xa9, 0x89, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xab, 0x89, 0x43, 0x40, 0x81, 0x32, 0x00, 0x00, 0xb9, 0x89, 0x22, 0x57, - 0x73, 0x7d, 0x00, 0x00, 0x77, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xad, 0x89, 0xa8, 0xb1, 0x94, 0x30, 0x00, 0x00, 0x77, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xaf, 0x89, 0xa8, 0xb1, 0x96, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0x62, 0xb1, 0x01, 0x00, 0xb2, 0x89, 0xa8, 0x4a, 0x80, 0x33, 0x00, 0x00, - 0xb7, 0x89, 0x22, 0x5f, 0x95, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0xb5, 0x89, 0xa8, 0x4b, 0xac, 0x33, 0x00, 0x00, - 0x00, 0x00, 0x1b, 0xa5, 0x82, 0xb3, 0x01, 0x00, 0xba, 0x89, 0x00, 0xbe, - 0x83, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x40, 0x81, 0xb3, 0x01, 0x00, - 0x40, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0xc7, 0x89, 0xa2, 0x40, 0x86, 0x04, 0x00, 0x00, - 0x1b, 0x84, 0x9c, 0x40, 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x40, - 0x88, 0x88, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x50, 0x47, 0x31, 0x01, 0x00, - 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00, 0xc3, 0x89, 0x52, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xe3, 0x89, 0x00, 0x40, 0x47, 0x31, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x89, 0xb0, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x48, - 0x47, 0x31, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x05, 0x47, 0x31, 0x01, 0x00, - 0x1b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x41, 0xe1, 0xc1, 0x00, 0x00, - 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0xd0, 0x89, 0x22, 0x54, - 0x81, 0x7c, 0x00, 0x00, 0xcb, 0x89, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x82, 0x00, 0xb4, 0x69, 0xdf, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44, - 0x93, 0x93, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0xde, 0x89, 0x0f, 0x40, - 0x80, 0x32, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x40, 0x88, 0x88, 0x01, 0x00, - 0xe3, 0x89, 0x00, 0x50, 0x47, 0x31, 0x01, 0x00, 0x36, 0x00, 0x00, 0x44, - 0x88, 0xcc, 0x01, 0x00, 0xd6, 0x89, 0x99, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x89, 0xd0, 0x01, 0x00, 0xd8, 0x89, 0x9b, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x89, 0xd0, 0x01, 0x00, - 0xda, 0x89, 0x1f, 0x44, 0x80, 0x32, 0x00, 0x00, 0xe3, 0x89, 0x00, 0x40, - 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xb0, 0x01, 0x00, - 0xe3, 0x89, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x58, - 0x47, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x40, 0x86, 0xf4, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x43, - 0x86, 0x88, 0x01, 0x00, 0x1b, 0x84, 0x26, 0x05, 0x47, 0x31, 0x00, 0x00, - 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x44, 0xf0, 0x41, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41, - 0xe1, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0xcb, 0x81, 0xc8, 0x01, 0x00, - 0xe9, 0x89, 0x22, 0x40, 0xf2, 0x7f, 0x00, 0x00, 0x81, 0x80, 0x00, 0x6f, - 0x97, 0x33, 0x01, 0x00, 0xeb, 0x89, 0x22, 0x40, 0x73, 0x7d, 0x00, 0x00, - 0x9b, 0x80, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0xe6, 0x89, 0x22, 0x59, - 0x73, 0x7d, 0x00, 0x00, 0x79, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xe6, 0x89, 0x28, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xec, 0x89, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0xc0, 0x95, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd6, 0x97, 0xb0, 0x01, 0x00, 0xf4, 0x89, 0x22, 0x5d, - 0x73, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xf2, 0x89, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, - 0x7f, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xc5, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x25, 0x01, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf7, 0x89, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0xf9, 0x89, 0x43, 0x5f, 0x7f, 0x13, 0x00, 0x00, 0x26, 0x01, 0x00, 0xbf, - 0xc5, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x7f, 0x83, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5e, 0x7f, 0x93, 0x01, 0x00, 0x75, 0x98, 0x00, 0xbf, - 0xc5, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x06, 0x8a, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x06, 0x8a, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x03, 0x8a, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x62, 0x95, 0x22, 0x02, - 0x80, 0x32, 0x00, 0x00, 0x07, 0x8a, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x62, 0x95, 0x1a, 0x02, - 0x68, 0x97, 0x00, 0x00, 0x11, 0x8a, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x11, 0x8a, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x0e, 0x8a, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x6c, 0x95, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, 0x12, 0x8a, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x6c, 0x95, 0x1a, 0x02, 0x68, 0x97, 0x00, 0x00, 0x1c, 0x8a, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0x1c, 0x8a, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x19, 0x8a, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x6f, 0x84, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, - 0x1d, 0x8a, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00, - 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6, - 0x56, 0xb1, 0x01, 0x00, 0x56, 0x95, 0x2f, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x6d, 0x8a, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00, 0xb8, 0x94, 0x29, 0x41, - 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00, 0x29, 0x00, 0x00, 0x40, - 0x0d, 0x98, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x12, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, - 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x10, 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x34, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, - 0x42, 0xc9, 0x01, 0x00, 0x51, 0x8a, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x32, 0x8a, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07, - 0x84, 0x89, 0x01, 0x00, 0x39, 0x8a, 0x05, 0xc2, 0x24, 0x30, 0x00, 0x00, - 0x51, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x6e, 0x8a, 0x1c, 0xf0, 0x18, 0x30, 0x01, 0x00, - 0x51, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x48, 0x8a, 0xa0, 0x48, 0x23, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x1a, - 0x42, 0xc9, 0x01, 0x00, 0x42, 0x8a, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x1a, - 0x62, 0xdd, 0x01, 0x00, 0x3f, 0x8a, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x6e, 0x8a, 0x00, 0xf8, 0x18, 0x30, 0x01, 0x00, - 0x43, 0x8a, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0x10, - 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x34, 0x94, 0x01, 0x00, - 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x1a, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00, - 0x4c, 0x8a, 0xa8, 0x09, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x11, 0xc0, 0x01, 0x00, 0x5d, 0x8a, 0x22, 0x41, - 0x0d, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00, - 0x59, 0x8a, 0xa0, 0xaa, 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x0f, 0xb0, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x12, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x1b, 0xb0, 0x01, 0x00, 0x30, 0x8a, 0x00, 0x41, 0x17, 0xb0, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x09, 0x12, 0xc8, 0x01, 0x00, 0x30, 0x8a, 0x83, 0x41, - 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, - 0x30, 0x8a, 0x00, 0x41, 0x1b, 0xc0, 0x00, 0x00, 0x68, 0x8a, 0x23, 0x40, - 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x1a, 0x42, 0xc9, 0x01, 0x00, 0x65, 0x8a, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00, 0x62, 0x8a, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x6e, 0x8a, 0x00, 0xf8, - 0x18, 0x30, 0x01, 0x00, 0x66, 0x8a, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00, 0x6b, 0x8a, 0xa0, 0xaa, - 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xb0, 0x01, 0x00, - 0xb8, 0x94, 0x20, 0x07, 0xe4, 0xb1, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xff, 0x89, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x0c, 0x80, 0xd8, 0x01, 0x00, 0xc0, 0x02, 0x00, 0x0c, - 0x7e, 0x89, 0x01, 0x00, 0x80, 0x8a, 0x26, 0x54, 0x61, 0x31, 0x00, 0x00, - 0x76, 0x8a, 0x87, 0x0c, 0x80, 0x32, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x40, - 0x62, 0x99, 0x01, 0x00, 0x76, 0x8a, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x76, 0x8a, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, 0x72, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x7b, 0x8a, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00, - 0x0d, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x01, 0x00, - 0x77, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x80, 0x8a, 0x22, 0x49, - 0x19, 0x7c, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, - 0x77, 0x7d, 0x01, 0x00, 0x7b, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x01, 0x00, - 0x80, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x94, 0x2f, 0x55, - 0xf1, 0x93, 0x01, 0x00, 0x00, 0x40, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00, - 0x6f, 0x84, 0xa2, 0x41, 0xe5, 0x51, 0x00, 0x00, 0x64, 0x00, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x88, 0x8a, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x8b, 0x8a, 0xa2, 0x93, 0x57, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x57, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x1a, 0xab, 0x27, 0xb3, 0x01, 0x00, - 0x6f, 0x84, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x6f, 0x84, 0x22, 0x51, - 0xfd, 0x7f, 0x00, 0x00, 0x6f, 0x84, 0xa2, 0x41, 0x1d, 0x53, 0x00, 0x00, - 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x34, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0xfc, 0x81, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0x97, 0x8a, 0x22, 0x40, - 0xb5, 0x6f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0xff, 0x81, 0x00, 0x41, 0xb5, 0x53, 0x01, 0x00, 0x6f, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00, - 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x35, 0x82, 0x00, 0x40, - 0x49, 0x31, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0xfc, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0xff, 0x81, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00, 0x60, 0x16, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0xdb, 0x82, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4a, - 0xb4, 0x8b, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4a, - 0xb4, 0xf7, 0x01, 0x00, 0xff, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x6f, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x05, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x20, 0x40, 0xe6, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00, - 0xae, 0x8a, 0x00, 0x4b, 0x10, 0xc9, 0x00, 0x00, 0xd1, 0x8d, 0x00, 0x41, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x05, 0x8e, 0x00, 0x41, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x37, 0x8e, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x37, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x37, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x37, 0x8e, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x76, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x9f, 0x8e, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0xa3, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x0b, 0x90, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xaf, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xae, 0x8e, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x6f, 0x8f, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x6f, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x6f, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x9b, 0x8f, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xb9, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb9, 0x8f, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xb9, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xe1, 0x8f, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0xf2, 0x8f, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xf2, 0x8f, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xf4, 0x8f, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0xf4, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0xf4, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xf4, 0x8f, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xfc, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x0d, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0xfd, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x0d, 0x90, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x0e, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x90, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, - 0x6d, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x6d, 0x8f, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x6d, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x41, - 0x09, 0xb0, 0x00, 0x00, 0x0f, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x0f, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x0f, 0x90, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x16, 0x90, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x18, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x24, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x8d, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xa3, 0x8e, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x95, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0xa3, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xa6, 0x90, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xcf, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x73, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x91, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xa3, 0x8e, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x20, 0x47, - 0xe6, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x47, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00, - 0x6e, 0x8b, 0x00, 0x4b, 0x10, 0xc9, 0x00, 0x00, 0xbe, 0x90, 0x00, 0x49, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xf7, 0x90, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xfd, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x0b, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x27, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x2f, 0x91, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x87, 0x91, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x86, 0x91, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x00, 0x91, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x00, 0x91, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x00, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x49, 0x09, 0xb0, 0x00, 0x00, - 0x00, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x4b, - 0x09, 0xb0, 0x00, 0x00, 0x00, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, - 0x00, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xe6, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xe6, 0x91, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xfe, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xf2, 0x91, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x6a, 0x94, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x27, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x87, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x2f, 0x91, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x86, 0x91, 0x00, 0x4c, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x1b, 0x92, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x1b, 0x92, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x1b, 0x92, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x00, 0x91, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x3e, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x26, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x26, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x26, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x3e, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x26, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x4d, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x4d, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xaf, 0x92, 0x00, 0x40, 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xc0, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x1e, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0xd3, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xd3, 0x92, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xc0, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0xc0, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xe6, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe6, 0x91, 0x00, 0x4c, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x3d, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x31, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x25, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x3d, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x31, 0x92, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x25, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x25, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x31, 0x92, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xd5, 0x92, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x4b, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xd5, 0x92, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0xd5, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x4c, - 0x09, 0xb0, 0x00, 0x00, 0xd5, 0x92, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xef, 0x92, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xef, 0x92, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xf6, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xf6, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xf6, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x19, 0x94, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x18, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x19, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x18, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xe0, 0x92, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xec, 0x92, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xec, 0x92, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xec, 0x92, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xec, 0x92, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xec, 0x92, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0xec, 0x92, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0xec, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xec, 0x92, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xec, 0x92, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xfe, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xf2, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xb8, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x5f, 0x94, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x5f, 0x94, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x5f, 0x94, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x5f, 0x94, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x5f, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x5f, 0x94, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xf2, 0x91, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x6a, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xf2, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x6a, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x6a, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x6e, 0x94, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xb0, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x6e, 0x94, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7f, 0x94, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x5d, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7f, 0x94, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x5d, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x90, 0x94, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x90, 0x94, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x90, 0x94, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x0b, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xae, 0x94, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x0b, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xae, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xb0, 0x94, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xb0, 0x94, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x6b, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x6b, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x15, 0x92, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x6b, 0x94, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x6b, 0x94, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xb6, 0x94, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x5d, 0x94, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xb6, 0x94, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x25, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x5d, 0x94, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x2f, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x2f, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, - 0x25, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x25, 0x91, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x2e, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0x0a, 0x8a, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00, - 0xba, 0x8d, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x3a, - 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xba, 0x8d, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x0f, - 0x1e, 0x8c, 0x01, 0x00, 0x21, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xca, 0x8d, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xca, 0x8d, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xc7, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x13, 0x86, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, - 0xcb, 0x8d, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00, - 0x13, 0x86, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x05, 0x00, 0x2e, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0x0a, 0x8a, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x40, 0x00, 0x00, 0xa1, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xe0, 0xb1, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x06, 0x07, 0x40, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x07, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x2e, 0x5c, - 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xb1, 0x01, 0x00, - 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x96, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x4b, - 0x94, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x95, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x96, 0xc0, 0x01, 0x00, 0x5e, 0x01, 0x2e, 0x34, - 0x97, 0x84, 0x01, 0x00, 0x02, 0x00, 0x00, 0x4b, 0xe4, 0xe5, 0x01, 0x00, - 0x64, 0x01, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00, - 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0xf4, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x08, 0x00, 0x2e, 0x40, 0x95, 0xb0, 0x01, 0x00, 0xfc, 0x8d, 0x20, 0x4b, - 0x94, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0xf9, 0x8d, 0x00, 0x41, 0x95, 0xc0, 0x00, 0x00, 0x10, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x03, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xff, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0xaf, 0x97, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00, - 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x86, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x88, 0xb0, 0x01, 0x00, 0x08, 0x8e, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x0b, 0x8e, 0xa2, 0x4c, 0xfd, 0x7f, 0x00, 0x00, - 0x0c, 0x8e, 0x00, 0x4c, 0xfd, 0x93, 0x00, 0x00, 0x0d, 0x8e, 0x20, 0xf0, - 0x56, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x56, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x70, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x13, 0x8e, 0xa8, 0x44, - 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x46, 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x68, 0x01, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, - 0x64, 0x00, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x62, 0xb1, 0x01, 0x00, - 0x1b, 0x8e, 0xa8, 0x44, 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, 0x86, 0xe4, 0x01, 0x00, - 0x38, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x23, 0x8e, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, 0x26, 0x8e, 0x22, 0x44, - 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x45, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x19, 0x90, 0x01, 0x00, 0x68, 0x01, 0x20, 0xa2, - 0xe4, 0xb1, 0x01, 0x00, 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x2a, 0x8e, 0x23, 0x0b, 0xe5, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x19, 0x90, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x50, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43, - 0xf0, 0xc9, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x2f, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5c, 0x00, 0x2e, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x60, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0xaf, 0x97, 0x00, 0x41, - 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x3a, 0x8e, 0xa2, 0x49, 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x3e, 0x8e, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00, - 0x86, 0x00, 0x2f, 0x49, 0x19, 0x80, 0x01, 0x00, 0x3e, 0x8e, 0xa2, 0xf2, - 0x80, 0x32, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xe7, 0x91, 0x01, 0x00, 0x41, 0x8e, 0xa2, 0x46, - 0x19, 0x7c, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x45, 0x8e, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00, 0xa0, 0x00, 0x2f, 0x46, - 0x19, 0x80, 0x01, 0x00, 0x45, 0x8e, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00, - 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xe7, 0x91, 0x01, 0x00, 0xa8, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x34, 0x00, 0x2d, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, - 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x10, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfb, 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, - 0x16, 0x88, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x14, 0xf4, 0x01, 0x00, - 0x70, 0x8e, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x58, 0x8e, 0x22, 0x0a, - 0x16, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, - 0x84, 0x30, 0x00, 0x00, 0xe7, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x13, 0xc0, 0x01, 0x00, - 0x57, 0x8e, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x13, 0xb0, 0x01, 0x00, 0x4d, 0x8e, 0x00, 0x41, 0x15, 0xd0, 0x00, 0x00, - 0x70, 0x8e, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, - 0x13, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00, 0xe7, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x70, 0x8e, 0x22, 0x41, 0x15, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x11, 0xc0, 0x01, 0x00, 0x64, 0x8e, 0xa0, 0x43, - 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0x11, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x36, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x00, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0xee, 0x97, 0x00, 0x47, - 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x5f, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x6c, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x60, 0x8e, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x37, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x20, 0x98, 0x00, 0x51, - 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x78, 0x8e, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00, - 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x7d, 0x8e, 0x22, 0x45, - 0x23, 0x7c, 0x00, 0x00, 0xb0, 0x00, 0x2f, 0xf0, 0x8c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x35, 0x00, 0x2d, 0xf0, 0x8c, 0xb0, 0x01, 0x00, - 0x58, 0x00, 0x3e, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0x82, 0x8e, 0x22, 0x48, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x68, 0x0a, 0x8c, 0xc0, 0x01, 0x00, 0x38, 0x00, 0x2a, 0x4a, - 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, - 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x38, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x26, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8, - 0x02, 0x30, 0x00, 0x00, 0x90, 0x8e, 0x23, 0x01, 0x14, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x82, 0xb0, 0x01, 0x00, 0x4c, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00, - 0x44, 0x00, 0x20, 0x40, 0xe0, 0xb1, 0x01, 0x00, 0x48, 0x00, 0x20, 0x41, - 0xe0, 0xb1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x21, 0x99, 0x00, 0xf0, 0x24, 0x30, 0x01, 0x00, 0x99, 0x8e, 0xa2, 0x44, - 0x81, 0x6c, 0x00, 0x00, 0x97, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x8a, 0x96, 0x00, 0x40, 0x3b, 0x30, 0x01, 0x00, 0xbd, 0x8e, 0xa2, 0x08, - 0x3c, 0x30, 0x00, 0x00, 0x99, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xc7, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbd, 0x8e, 0xa2, 0x08, - 0x3c, 0x30, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01, - 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, - 0x20, 0x98, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x69, 0x96, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x78, 0x8e, 0x22, 0x4a, - 0x80, 0x32, 0x00, 0x00, 0xa5, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x69, 0x96, 0x00, 0xf3, - 0x94, 0x30, 0x01, 0x00, 0x58, 0x00, 0x3e, 0x43, 0x97, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1b, 0xf0, 0xb1, 0x01, 0x00, 0x1f, 0x00, 0x60, 0x00, - 0x00, 0x8c, 0x01, 0x00, 0xcf, 0x8d, 0x85, 0x11, 0x80, 0x32, 0x00, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0xf0, - 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00, - 0x20, 0x98, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xaf, 0x8e, 0x00, 0x49, 0x19, 0x80, 0x00, 0x00, - 0xb4, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x8a, 0x96, 0x00, 0x40, - 0x3b, 0x30, 0x01, 0x00, 0xb8, 0x8e, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xc7, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xb8, 0x8e, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x5f, - 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x50, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x54, 0x00, 0x2d, 0xf0, - 0x38, 0xb0, 0x01, 0x00, 0x4e, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, - 0x40, 0x00, 0x2d, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x14, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x46, 0x44, 0xc9, 0x01, 0x00, 0x68, 0x01, 0x2d, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x68, 0xf2, 0x80, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x37, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x36, 0xd0, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0x40, - 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x52, 0x81, 0xd0, 0x01, 0x00, 0xcb, 0x8e, 0x20, 0x94, - 0x81, 0x6c, 0x00, 0x00, 0xb5, 0x97, 0x00, 0x94, 0xe5, 0x31, 0x01, 0x00, - 0xcc, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x97, 0x00, 0x40, - 0xe4, 0x31, 0x01, 0x00, 0x20, 0x00, 0x00, 0x46, 0x62, 0xdd, 0x01, 0x00, - 0xcc, 0x8e, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, - 0x1e, 0x8c, 0x01, 0x00, 0xdc, 0x8e, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xd6, 0x8e, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xd3, 0x8e, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x48, 0xb1, 0x01, 0x00, 0xfb, 0x95, 0x00, 0x43, - 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x23, 0xb0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x1e, 0x8c, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, 0xe4, 0x8e, 0x22, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0xe0, 0x8e, 0xa3, 0x01, 0x0c, 0x6c, 0x00, 0x00, - 0xe1, 0x8e, 0x00, 0x06, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x04, 0xb0, 0x01, 0x00, 0xe3, 0x8e, 0x20, 0x02, 0x36, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x01, 0x00, 0xe7, 0x8e, 0x00, 0x02, - 0xf0, 0xb1, 0x00, 0x00, 0xe6, 0x8e, 0xa3, 0x01, 0x0c, 0x6c, 0x00, 0x00, - 0xe7, 0x8e, 0x68, 0x06, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, - 0x04, 0xb0, 0x01, 0x00, 0xe9, 0x8e, 0x80, 0x08, 0xf0, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x11, 0x1e, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x01, 0x1f, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0xeb, 0x8e, 0xa8, 0x13, - 0xe0, 0x31, 0x00, 0x00, 0x22, 0x8f, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, - 0x44, 0x00, 0x2d, 0x02, 0x0c, 0xd0, 0x01, 0x00, 0x12, 0x8f, 0xa2, 0x02, - 0x02, 0x50, 0x00, 0x00, 0xf9, 0x8e, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0xf8, 0x8e, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xf4, 0x8e, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x44, 0x00, 0x2d, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x48, 0x00, 0x2d, 0xf0, 0x38, 0xb0, 0x01, 0x00, - 0x4c, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, 0x38, 0x00, 0x2f, 0xf2, - 0x02, 0xb0, 0x01, 0x00, 0x13, 0x8f, 0x22, 0x01, 0x14, 0x6c, 0x00, 0x00, - 0x06, 0x8f, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x1f, 0x80, 0x01, 0x00, 0x20, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0x05, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x02, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x38, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x38, 0x00, 0x2d, 0xf0, - 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0xe1, 0xc1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x22, 0x4a, - 0xf1, 0xb1, 0x01, 0x00, 0x44, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x0f, 0x8f, 0xa8, 0x5c, - 0x1f, 0x10, 0x00, 0x00, 0x13, 0x8f, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x38, 0xc0, 0x01, 0x00, 0x1d, 0x8f, 0x22, 0x06, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, - 0x1b, 0x8f, 0xa2, 0x02, 0x36, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x8f, 0x0d, - 0x42, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf8, 0x10, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x11, 0x80, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, - 0x37, 0x98, 0x01, 0x00, 0xcf, 0x8e, 0x00, 0xa1, 0x1a, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0xcf, 0x8e, 0x00, 0x02, - 0x36, 0xd0, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01, - 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, - 0x27, 0x8f, 0x00, 0x5f, 0x01, 0xb0, 0x00, 0x00, 0x37, 0x00, 0x2d, 0x46, - 0x01, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x80, 0xf4, 0x01, 0x00, - 0x26, 0x8f, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x01, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0x2d, 0x8f, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0x2a, 0x8f, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xfb, 0x95, 0x00, 0x10, 0x48, 0x31, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x34, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x31, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x60, 0x01, 0x2f, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, 0x39, 0x8f, 0x90, 0xf2, - 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x32, 0x00, 0x00, 0xa6, - 0x2a, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2a, 0x94, 0x01, 0x00, - 0x42, 0x8f, 0x22, 0x49, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x00, 0xf0, 0x00, 0x0c, 0x18, 0x8c, 0x01, 0x00, 0xf5, 0x97, 0x00, 0x4c, - 0x95, 0x30, 0x01, 0x00, 0x52, 0x8f, 0x00, 0x00, 0x92, 0xb0, 0x00, 0x00, - 0x49, 0x8f, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x1e, - 0x94, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x96, 0xb0, 0x01, 0x00, - 0x72, 0x98, 0x00, 0x40, 0x05, 0x30, 0x01, 0x00, 0x48, 0x8f, 0xa2, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x5b, 0x8f, 0x00, 0x47, 0x19, 0x80, 0x00, 0x00, - 0x52, 0x8f, 0x00, 0x00, 0x92, 0xb0, 0x00, 0x00, 0x49, 0x8f, 0x43, 0x48, - 0x61, 0x31, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x1e, 0x62, 0xdd, 0x01, 0x00, - 0x4e, 0x8f, 0x28, 0x40, 0x05, 0x30, 0x00, 0x00, 0x4a, 0x8f, 0x22, 0x48, - 0x77, 0x7d, 0x00, 0x00, 0x51, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x15, 0x62, 0xb1, 0x01, 0x00, 0x5a, 0x8f, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x4e, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x1b, 0x00, 0x92, 0xb0, 0x01, 0x00, 0x57, 0x8f, 0x22, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0xcc, 0x95, 0x00, 0xf8, 0x00, 0x30, 0x01, 0x00, 0x54, 0x8f, 0xa2, 0x41, - 0x3b, 0x50, 0x00, 0x00, 0x5b, 0x8f, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00, - 0xff, 0x07, 0x00, 0x1e, 0x00, 0x8c, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x5b, 0x8f, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x1b, 0x47, 0x19, 0x80, 0x01, 0x00, 0x5e, 0x8f, 0x22, 0x5f, - 0x01, 0x6c, 0x00, 0x00, 0x4b, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xaa, 0x8a, 0x00, 0x00, 0x80, 0xb0, 0x00, 0x00, 0x65, 0x8f, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x65, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x62, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x65, 0x8f, 0x40, 0x05, 0x48, 0x31, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x07, 0x94, 0x89, 0x01, 0x00, 0x6b, 0x8f, 0x85, 0xca, - 0x94, 0x30, 0x00, 0x00, 0x4b, 0x99, 0x18, 0x5c, 0x1f, 0x00, 0x01, 0x00, - 0x0e, 0x00, 0x00, 0x0f, 0x1e, 0x8c, 0x01, 0x00, 0x72, 0x89, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x20, 0x98, 0x18, 0x00, 0x80, 0x30, 0x01, 0x00, - 0xcf, 0x8d, 0x00, 0x47, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x19, 0x80, 0x01, 0x00, 0xcf, 0x8d, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00, - 0xc7, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x72, 0x8f, 0xa2, 0x08, - 0x80, 0x32, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb5, 0x97, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00, 0x9c, 0x01, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00, - 0x8b, 0x00, 0x2d, 0x50, 0x17, 0xf0, 0x01, 0x00, 0x78, 0x8f, 0x90, 0x4c, - 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x7a, 0x8f, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x45, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, - 0x68, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2, - 0x80, 0xb0, 0x01, 0x00, 0x3e, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, - 0x81, 0x8f, 0x24, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x81, 0xc0, 0x01, 0x00, 0x82, 0x8f, 0x00, 0x94, 0xe5, 0xb1, 0x00, 0x00, - 0x02, 0x00, 0x62, 0x40, 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, - 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x40, 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x88, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x94, 0x8f, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x08, 0x94, 0xdc, 0x01, 0x00, 0x72, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x92, 0x8f, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x08, 0x00, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xcf, 0x8d, 0x00, 0x47, 0x19, 0x80, 0x00, 0x00, 0x94, 0x8f, 0x43, 0x48, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x50, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, - 0x9a, 0x8f, 0x28, 0x40, 0x05, 0x30, 0x00, 0x00, 0x95, 0x8f, 0x22, 0x48, - 0x77, 0x7d, 0x00, 0x00, 0xcc, 0x95, 0x1b, 0x08, 0x00, 0x30, 0x01, 0x00, - 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xcf, 0x8d, 0x1b, 0x47, - 0x19, 0x80, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x63, 0xf3, 0x84, 0xc8, 0x01, 0x00, 0x9f, 0x8f, 0xa0, 0x43, - 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, - 0xa8, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0, - 0x24, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00, - 0xaa, 0x8f, 0xa2, 0x41, 0x9e, 0x06, 0x00, 0x00, 0xcf, 0x8d, 0x22, 0x44, - 0x83, 0x70, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xcf, 0x8d, 0x1f, 0xf0, - 0x24, 0x6c, 0x00, 0x00, 0x4b, 0x99, 0x00, 0x48, 0x81, 0x30, 0x01, 0x00, - 0xaa, 0x8a, 0x23, 0x41, 0x83, 0x6c, 0x00, 0x00, 0xaa, 0x8a, 0x00, 0x47, - 0x81, 0xb0, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x85, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0xee, 0x97, 0x00, 0x47, 0x61, 0x31, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0x08, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x8e, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x7e, 0x8e, 0xa2, 0x40, - 0x8f, 0x7c, 0x00, 0x00, 0xb8, 0x8f, 0x22, 0x47, 0x8f, 0x7c, 0x00, 0x00, - 0x7e, 0x8e, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00, 0x27, 0x90, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x5d, 0x05, 0xb4, 0x01, 0x00, - 0x37, 0x00, 0x2d, 0xf3, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x8e, 0xb0, 0x01, 0x00, 0x5c, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00, - 0xa8, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x24, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x86, 0xdc, 0x01, 0x00, - 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0xce, 0x94, 0x00, 0x4a, - 0xf0, 0x31, 0x01, 0x00, 0x36, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0xc6, 0x8f, 0xa2, 0x50, 0x8f, 0x50, 0x00, 0x00, 0x34, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x41, 0x81, 0xc0, 0x01, 0x00, 0xc9, 0x8f, 0xa0, 0x43, - 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x63, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0x37, 0x00, 0x20, 0x47, 0xe6, 0xb1, 0x01, 0x00, 0xcf, 0x8d, 0x22, 0x47, - 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x47, 0x0c, 0xf4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x8f, 0x84, 0x01, 0x00, 0xde, 0x8f, 0x22, 0x47, - 0x0c, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00, - 0xde, 0x8f, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xd7, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xd4, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xd7, 0x8f, 0x42, 0x40, 0x05, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x5d, - 0x69, 0x93, 0x01, 0x00, 0xdc, 0x8f, 0x23, 0x41, 0x0d, 0x6c, 0x00, 0x00, - 0xb9, 0x8f, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x4b, 0x99, 0x00, 0x05, - 0x48, 0x31, 0x01, 0x00, 0xaa, 0x8a, 0x00, 0x48, 0x81, 0xb0, 0x00, 0x00, - 0xcf, 0x8d, 0x22, 0x40, 0x8f, 0x6c, 0x00, 0x00, 0x20, 0x98, 0x00, 0x5f, - 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xa2, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x84, 0xb0, 0x01, 0x00, 0xa6, 0x00, 0x2d, 0x49, 0x19, 0x90, 0x01, 0x00, - 0x02, 0x00, 0x00, 0xf2, 0x80, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2d, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x82, 0xf8, 0x01, 0x00, 0x19, 0x00, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0xed, 0x8f, 0xa0, 0x40, 0x82, 0x6c, 0x00, 0x00, - 0x2c, 0x01, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0xed, 0x8f, 0xa3, 0x40, - 0x82, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x80, 0xb0, 0x01, 0x00, - 0xef, 0x8f, 0x20, 0x4c, 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x85, 0xc0, 0x01, 0x00, 0x86, 0x00, 0x20, 0x40, 0xe4, 0xb1, 0x01, 0x00, - 0xa2, 0x00, 0x20, 0x42, 0xe6, 0xb1, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x50, 0x81, 0x30, 0x01, 0x00, - 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x80, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x40, - 0x87, 0x30, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x60, 0xf0, 0x80, 0xc0, 0x01, 0x00, 0x20, 0x98, 0x00, 0x5f, - 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xcf, 0x8d, 0x22, 0x46, - 0x19, 0x7c, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x62, 0xf2, 0x96, 0xcc, 0x01, 0x00, 0xcf, 0x8d, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x20, 0x98, 0x00, 0x4a, 0x81, 0x30, 0x01, 0x00, - 0xf5, 0x97, 0x00, 0x46, 0x95, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xcf, 0x8d, 0x22, 0x49, 0x19, 0x7c, 0x00, 0x00, - 0x86, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2, - 0x80, 0xcc, 0x01, 0x00, 0xcf, 0x8d, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x4a, 0x81, 0x30, 0x01, 0x00, 0xf5, 0x97, 0x00, 0x47, - 0x95, 0x30, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x5f, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xcf, 0x8d, 0x00, 0x5c, - 0x1f, 0x90, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2, 0x80, 0xc8, 0x01, 0x00, - 0x13, 0x90, 0x90, 0x40, 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x62, 0x40, - 0x81, 0x98, 0x01, 0x00, 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xcf, 0x8d, 0x22, 0x40, 0xe5, 0x6d, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x41, - 0xe5, 0xc1, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x4d, 0x81, 0x30, 0x01, 0x00, - 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x96, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x40, - 0x87, 0x30, 0x01, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x23, 0x90, 0x80, 0xf3, 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe7, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00, - 0xcf, 0x8d, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x34, 0x00, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x11, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0xc7, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x38, 0x90, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x63, 0x51, 0x83, 0xd0, 0x01, 0x00, - 0x34, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, - 0x84, 0xcc, 0x01, 0x00, 0x30, 0x90, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x42, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, - 0x32, 0x90, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x62, 0xb1, 0x01, 0x00, 0x33, 0x90, 0xa8, 0x4b, 0x19, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, 0x35, 0x90, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xff, 0x89, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, - 0x94, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0xf0, 0x30, 0xb0, 0x01, 0x00, - 0x35, 0x00, 0x2d, 0xf0, 0x28, 0xb0, 0x01, 0x00, 0x58, 0x00, 0x3e, 0x43, - 0xe7, 0xe1, 0x01, 0x00, 0x01, 0x00, 0x00, 0x18, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x38, 0x00, 0x20, 0x00, - 0xe0, 0xb1, 0x01, 0x00, 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x2b, 0xb0, 0x01, 0x00, 0x04, 0x98, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x16, 0xc0, 0x01, 0x00, 0x47, 0x90, 0xa0, 0x14, - 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0xf8, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0x14, 0xf8, 0xb1, 0x01, 0x00, - 0x10, 0x50, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x50, 0x90, 0x22, 0x4a, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43, 0x86, 0xc8, 0x01, 0x00, - 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00, 0x50, 0x90, 0xa4, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x01, 0x00, 0x6e, 0x43, 0x86, 0x98, 0x01, 0x00, 0x3b, 0x98, 0x00, 0x30, - 0x81, 0x30, 0x01, 0x00, 0x54, 0x90, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x5b, 0x90, 0x22, 0x4a, - 0x19, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, - 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, - 0x17, 0xc0, 0x01, 0x00, 0x5a, 0x90, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x64, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x41, 0x31, 0xc0, 0x01, 0x00, 0xbc, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x61, 0x90, 0x06, 0x0c, 0x80, 0x32, 0x00, 0x00, - 0xa0, 0x00, 0x20, 0xf2, 0xe4, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x09, 0x46, - 0x19, 0x10, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x50, - 0x17, 0xf0, 0x01, 0x00, 0x66, 0x90, 0x90, 0x4c, 0x16, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x68, 0x90, 0x22, 0x43, - 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x68, 0x01, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2, 0x80, 0xb0, 0x01, 0x00, - 0x3e, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, 0x6f, 0x90, 0x24, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x81, 0xc0, 0x01, 0x00, - 0x70, 0x90, 0x00, 0x94, 0xe5, 0xb1, 0x00, 0x00, 0x02, 0x00, 0x62, 0x40, - 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x81, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40, - 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, - 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0x76, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x80, 0x90, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x08, - 0x94, 0xdc, 0x01, 0x00, 0x72, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x7b, 0x90, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x84, 0x90, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0x80, 0x90, 0x43, 0x48, 0x61, 0x31, 0x00, 0x00, 0x00, 0x50, 0x00, 0x08, - 0x62, 0xdd, 0x01, 0x00, 0x81, 0x90, 0xa8, 0x40, 0x05, 0x30, 0x00, 0x00, - 0x35, 0x00, 0x1b, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, - 0x84, 0xc8, 0x01, 0x00, 0x87, 0x90, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00, - 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0xe7, 0x91, 0x01, 0x00, 0x20, 0x98, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, - 0xcf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x69, 0x96, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, - 0x27, 0x90, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00, 0xa5, 0x8e, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x69, 0x96, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x75, 0x8e, 0x22, 0x4a, - 0x80, 0x32, 0x00, 0x00, 0xa5, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, - 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, 0x90, 0x88, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xf3, 0x0c, 0xf4, 0x01, 0x00, 0x9f, 0x8e, 0x22, 0x06, - 0x90, 0x6c, 0x00, 0x00, 0x5c, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, - 0xa8, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0, - 0x24, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x2a, 0x50, 0xe7, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x41, 0x13, 0xc0, 0x01, 0x00, 0xa1, 0x90, 0xa0, 0x43, - 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xcc, 0x94, 0x00, 0x10, 0x86, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xa3, 0x90, 0x42, 0x05, 0x48, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x9f, 0x8e, 0x1a, 0x5d, - 0x69, 0x93, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x10, 0x86, 0xb0, 0x01, 0x00, - 0x5c, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0, - 0x94, 0xb0, 0x01, 0x00, 0x35, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00, - 0x01, 0x00, 0x6b, 0xfb, 0x84, 0xc8, 0x01, 0x00, 0xae, 0x90, 0xa0, 0x43, - 0x85, 0x6c, 0x00, 0x00, 0x35, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, - 0x12, 0xc8, 0x01, 0x00, 0xb1, 0x90, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0xce, 0x94, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xb4, 0x90, 0x42, 0x05, - 0x48, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x1a, 0x5d, 0x69, 0x93, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x11, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00, - 0xa3, 0x8f, 0x22, 0x41, 0x9e, 0x06, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0xad, 0x8f, 0x00, 0xf0, - 0x00, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xbf, 0x90, 0x47, 0xf2, 0x12, 0x30, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, - 0x13, 0xf0, 0x01, 0x00, 0xc4, 0x90, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00, - 0x6b, 0x84, 0x1f, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xbe, 0x90, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x1f, 0x42, 0x19, 0x90, 0x01, 0x00, 0x75, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xc6, 0x90, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00, - 0x46, 0x97, 0x00, 0x10, 0x94, 0x30, 0x01, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x97, 0xb0, 0x01, 0x00, 0xd0, 0x90, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00, - 0x04, 0x00, 0x02, 0x41, 0x97, 0x40, 0x00, 0x00, 0xcd, 0x90, 0x00, 0x50, - 0x43, 0xc1, 0x00, 0x00, 0xdc, 0x90, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x62, 0x4b, 0x12, 0x94, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x97, 0xc0, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x94, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x4a, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf1, 0xb1, 0x01, 0x00, - 0x5e, 0x01, 0x00, 0x4b, 0xf0, 0xc9, 0x01, 0x00, 0x5e, 0x01, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x4a, 0x62, 0xdd, 0x01, 0x00, 0xda, 0x90, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x09, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00, - 0xd4, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0xe2, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, - 0xe6, 0x90, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, - 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x1f, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, - 0x62, 0xb1, 0x01, 0x00, 0xea, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xef, 0x90, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0xed, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x97, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x96, - 0x97, 0xb0, 0x01, 0x00, 0xf5, 0x90, 0x20, 0x09, 0x96, 0x6c, 0x00, 0x00, - 0xf5, 0x90, 0x1f, 0x09, 0x96, 0x24, 0x00, 0x00, 0x6b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xf0, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xaf, 0x97, 0x00, 0x57, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xfb, 0x90, 0x22, 0xf3, 0x80, 0x32, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x42, - 0x81, 0x30, 0x01, 0x00, 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x42, - 0x19, 0x80, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, - 0x20, 0x98, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xc9, 0x96, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x22, 0x40, - 0x95, 0x6c, 0x00, 0x00, 0x06, 0x91, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xff, 0x89, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x74, 0x96, 0x00, 0x52, - 0x95, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x98, 0x00, 0x40, - 0x95, 0x30, 0x01, 0x00, 0x11, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0xff, 0x89, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x23, 0x00, 0xa6, - 0x16, 0xb0, 0x01, 0x00, 0x14, 0x91, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x08, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2a, 0xc0, 0x01, 0x00, 0xf8, 0x97, 0x00, 0x08, 0x80, 0x30, 0x01, 0x00, - 0x18, 0x91, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x19, 0x98, 0x00, 0x43, - 0x61, 0x31, 0x01, 0x00, 0xda, 0x94, 0x00, 0x40, 0x8d, 0x30, 0x01, 0x00, - 0x00, 0x98, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x20, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x1d, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xa1, 0x97, 0x00, 0x5e, - 0x05, 0x10, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x24, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0xbf, 0x8d, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00, - 0x2b, 0x91, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x3d, 0x80, 0x01, 0x00, - 0x2c, 0x91, 0x00, 0x42, 0x19, 0x90, 0x00, 0x00, 0x14, 0x00, 0x2d, 0x45, - 0x1f, 0x90, 0x01, 0x00, 0x87, 0x91, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00, - 0x87, 0x91, 0x00, 0x44, 0x19, 0x90, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x3f, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x3b, 0x91, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, - 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x38, 0x91, 0xa2, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x96, 0x00, 0x15, - 0x94, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf9, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xff, 0x89, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x42, 0x91, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x43, 0x91, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xc9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x6f, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x15, - 0x98, 0xc8, 0x01, 0x00, 0x6f, 0x91, 0xa0, 0x0b, 0x99, 0x6c, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, - 0x4b, 0x91, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x15, 0x98, 0xc8, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x0b, - 0x99, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x6a, 0x50, 0x99, 0xc0, 0x01, 0x00, - 0xc0, 0x00, 0x62, 0x01, 0x80, 0xcc, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x2d, 0x00, 0x2d, 0xf0, 0x22, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x23, 0x80, 0x01, 0x00, 0xd4, 0x00, 0x3f, 0x41, 0xe7, 0xe1, 0x01, 0x00, - 0x0b, 0x00, 0x00, 0x11, 0xe4, 0xf5, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x47, - 0xe7, 0xb5, 0x01, 0x00, 0x5c, 0x91, 0x23, 0x0b, 0x81, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0xe5, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x03, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x15, 0x02, 0xd0, 0x01, 0x00, 0xf8, 0x97, 0x00, 0x00, - 0x2a, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x61, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01, - 0x80, 0xce, 0x01, 0x00, 0x6d, 0x91, 0x26, 0x11, 0x00, 0x30, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xc0, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x98, 0xd0, 0x01, 0x00, 0xf8, 0x97, 0x00, 0x4c, 0x02, 0x30, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00, 0x74, 0x91, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x2f, 0x08, 0x80, 0xb0, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x15, 0xf4, 0xc9, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01, - 0xe4, 0xcd, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00, - 0xf8, 0x97, 0x00, 0x00, 0x2a, 0x40, 0x01, 0x00, 0x79, 0x91, 0x22, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x40, 0x13, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x7a, 0x91, 0x00, 0x01, 0xe0, 0xd1, 0x00, 0x00, - 0xda, 0x94, 0x00, 0x40, 0x8d, 0x30, 0x01, 0x00, 0x80, 0x63, 0x00, 0xa6, - 0x16, 0xb0, 0x01, 0x00, 0x00, 0x98, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x82, 0x91, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x7f, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xa1, 0x97, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x85, 0x91, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xba, 0x8d, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x87, 0x91, 0x00, 0x4a, - 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xb0, 0x01, 0x00, - 0x24, 0x00, 0x2d, 0x15, 0x10, 0xc0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0, - 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, - 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xe0, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15, - 0x1a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x2a, 0xb0, 0x01, 0x00, 0x5b, 0x97, 0x00, 0x40, - 0x35, 0xb0, 0x00, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xcb, 0x91, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x24, 0x00, 0x20, 0x0b, - 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, - 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00, 0xa1, 0x91, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xa1, 0x91, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x9d, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x42, 0xc9, 0x01, 0x00, 0xc4, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0xb2, 0x91, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x21, 0x97, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x74, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xbf, 0x91, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xa8, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xae, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xe2, 0x95, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, 0xaf, 0x91, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xb1, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0x21, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x70, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xb5, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xbb, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x95, 0x00, 0x40, - 0x11, 0x30, 0x01, 0x00, 0xbc, 0x91, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbe, 0x91, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xc0, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xc7, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x95, 0x00, 0x40, - 0x11, 0x30, 0x01, 0x00, 0xc8, 0x91, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xca, 0x91, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0xbf, 0x8d, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x42, 0xc9, 0x01, 0x00, 0xd2, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xce, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xd6, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x95, 0x00, 0x40, - 0x11, 0x30, 0x01, 0x00, 0xd7, 0x91, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x0a, - 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0x14, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xdc, 0x91, 0x03, 0x1e, - 0x80, 0x32, 0x00, 0x00, 0xdd, 0x91, 0x00, 0x41, 0x87, 0xb0, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xea, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0xe1, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0xe4, 0x91, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x80, 0x01, 0x00, 0xba, 0x8d, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00, - 0xbf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0xea, 0x91, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, - 0xcc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xfb, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x8d, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x2d, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0xd8, 0x98, 0x00, 0xf0, 0x84, 0x30, 0x01, 0x00, - 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbf, 0x8d, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0xbf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xf6, 0x91, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xfe, 0x91, 0xa2, 0x40, - 0xe5, 0x6d, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x24, 0x00, 0x20, 0x0b, 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13, - 0xe0, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00, - 0x14, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, 0xbf, 0x8d, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0xbf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0c, 0x92, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0x99, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15, 0x98, 0x50, 0x00, 0x00, - 0x0c, 0x92, 0x20, 0x01, 0x98, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, 0x1f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x09, 0x92, 0xa8, 0x00, - 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xac, 0x00, 0x2f, 0x00, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xe0, 0xc1, 0x01, 0x00, 0x14, 0x00, 0x2f, 0x15, 0x10, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x01, - 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00, - 0x8e, 0x91, 0x22, 0x09, 0x80, 0x32, 0x00, 0x00, 0x20, 0x98, 0x00, 0x09, - 0x80, 0x30, 0x01, 0x00, 0x8e, 0x91, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x43, 0xc1, 0x01, 0x00, 0xea, 0x96, 0x00, 0xf0, - 0x84, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, - 0x2c, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x42, 0x19, 0x80, 0x00, 0x00, - 0xdc, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf5, 0x97, 0x00, 0x48, - 0x95, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x21, 0x92, 0xa8, 0x40, - 0x13, 0x30, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x27, 0x92, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x26, 0x92, 0x00, 0x40, - 0x13, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xb0, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x14, 0x00, 0x2d, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xea, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0x3f, 0x92, 0x00, 0x09, 0x00, 0xb0, 0x00, 0x00, 0xba, 0x8d, 0x87, 0x42, - 0x19, 0x10, 0x00, 0x00, 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00, - 0xba, 0x8d, 0x00, 0x40, 0xe7, 0x91, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x3d, 0x92, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00, - 0x51, 0x95, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00, 0x3d, 0x92, 0x22, 0x00, - 0x80, 0x32, 0x00, 0x00, 0x38, 0x92, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x3d, 0x92, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00, 0x74, 0x96, 0x00, 0xf2, - 0x02, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x3e, 0x92, 0x00, 0x40, - 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x44, 0x92, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x43, 0x92, 0xa2, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0xc9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x44, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf9, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xce, 0x92, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x4c, 0x92, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x49, 0x92, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xce, 0x92, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x52, 0x92, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x4d, - 0x81, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x96, 0xb0, 0x01, 0x00, 0x60, 0x92, 0x22, 0x42, 0x96, 0x14, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x68, 0x40, - 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x5d, 0x92, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x61, 0x92, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x65, 0x92, 0x47, 0xf2, 0x12, 0x30, 0x00, 0x00, - 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0x6a, 0x92, 0x22, 0x47, - 0xe7, 0x7d, 0x00, 0x00, 0x6b, 0x84, 0x1f, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x64, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0xe7, 0x91, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x09, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x72, 0x92, 0xa8, 0x40, - 0xe1, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0x76, 0x92, 0x47, 0x05, - 0x48, 0x31, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x7e, 0x92, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0x7c, 0x92, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x62, 0x00, 0x0b, - 0x16, 0xdc, 0x01, 0x00, 0x51, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x96, 0x92, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xff, 0x96, 0x00, 0x5f, - 0x01, 0x10, 0x01, 0x00, 0x80, 0x92, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x88, 0x92, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x74, 0x96, 0x00, 0x52, - 0x95, 0x30, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x80, 0x92, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x80, 0x92, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x00, 0x98, 0x00, 0x40, 0x03, 0x30, 0x01, 0x00, 0x17, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x4c, 0x97, 0xf0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0xe1, 0xb1, 0x01, 0x00, - 0xa1, 0x97, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, - 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00, - 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0xa0, 0x92, 0x30, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x81, 0x01, 0x00, - 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0xe6, 0x81, 0x01, 0x00, 0x10, 0x00, 0x10, 0x0f, 0x94, 0xf4, 0x01, 0x00, - 0xd1, 0x99, 0x00, 0x5f, 0x95, 0x04, 0x01, 0x00, 0x55, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xaa, 0x92, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, - 0xa8, 0x92, 0x43, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x41, - 0x31, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0f, 0xb0, 0x01, 0x00, 0xb8, 0x95, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xbb, 0x92, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, - 0xb4, 0x92, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x62, 0xb1, 0x01, 0x00, 0xb8, 0x92, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xb5, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x62, 0xb1, 0x01, 0x00, 0xb8, 0x92, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xff, 0x89, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x22, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0xf5, 0x97, 0x00, 0x4a, 0x95, 0x30, 0x01, 0x00, 0xdc, 0x96, 0x00, 0x5c, - 0x1f, 0x10, 0x01, 0x00, 0x52, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2f, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xcc, 0x92, 0x22, 0x47, - 0xe7, 0x7d, 0x00, 0x00, 0x51, 0x95, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00, - 0xcc, 0x92, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xc7, 0x92, 0xa2, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xcc, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00, - 0x74, 0x96, 0x00, 0xf2, 0x02, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xf5, 0x97, 0x00, 0x48, 0x95, 0x30, 0x01, 0x00, 0xdc, 0x96, 0x00, 0x5c, - 0x1f, 0x10, 0x01, 0x00, 0xd1, 0x92, 0x87, 0x42, 0x19, 0x10, 0x00, 0x00, - 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe7, 0x91, 0x01, 0x00, 0x20, 0x98, 0x00, 0x42, 0x81, 0x30, 0x01, 0x00, - 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xdc, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, - 0xba, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x8d, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0xd8, 0x98, 0x00, 0xf0, - 0x84, 0x30, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x20, 0x98, 0x00, 0x45, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x22, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, - 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xe5, 0x92, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x47, - 0x80, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0xe1, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x07, 0x84, 0x94, 0x01, 0x00, - 0xa1, 0x97, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xcc, 0x95, 0x00, 0x41, 0xe7, 0x41, 0x01, 0x00, 0xbf, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x0a, - 0x2c, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x0b, 0x96, 0x88, 0x01, 0x00, 0x01, 0x93, 0x26, 0x47, - 0x97, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, - 0x01, 0x93, 0x23, 0x4b, 0x0c, 0x6c, 0x00, 0x00, 0x33, 0x98, 0x00, 0x4b, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x16, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0xb0, 0x01, 0x00, - 0x33, 0x98, 0x00, 0x4b, 0x04, 0x50, 0x01, 0x00, 0x02, 0x93, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x33, 0x98, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00, - 0x08, 0x93, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0x06, 0x93, 0x84, 0x48, - 0x1f, 0x10, 0x00, 0x00, 0xac, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x08, 0x93, 0x00, 0x0a, 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x02, 0xb0, 0x01, 0x00, 0xda, 0x94, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x09, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, - 0x16, 0x93, 0x22, 0x06, 0x14, 0x50, 0x00, 0x00, 0x24, 0x97, 0x00, 0x45, - 0x1f, 0x00, 0x01, 0x00, 0xf5, 0x92, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x12, 0x93, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xf5, 0x92, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, - 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xea, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x1c, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x22, 0x93, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x26, 0x93, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x26, 0x93, 0xa2, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00, - 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x34, 0x93, 0x22, 0x4a, - 0x1f, 0x7c, 0x00, 0x00, 0x2c, 0x93, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x30, 0x93, 0x22, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x31, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc9, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, - 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x16, - 0xe4, 0xb1, 0x00, 0x00, 0x46, 0x93, 0x22, 0x16, 0x02, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0xf4, 0x98, 0x00, 0x40, - 0x95, 0x30, 0x01, 0x00, 0x47, 0x93, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00, - 0xac, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2b, 0x01, - 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, 0xf8, 0x97, 0x00, 0x08, - 0x80, 0x30, 0x01, 0x00, 0x3f, 0x93, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, - 0x19, 0x98, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x40, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x98, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0xa1, 0x97, 0x00, 0x5e, - 0x05, 0x10, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xbf, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x1f, 0x15, 0x1a, 0x50, 0x00, 0x00, 0x54, 0x93, 0x20, 0x16, - 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x51, 0x93, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x2a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x2c, 0xd0, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x5b, 0x93, 0x84, 0x45, 0x1f, 0x10, 0x00, 0x00, 0x5c, 0x93, 0x00, 0x0a, - 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0xb0, 0x01, 0x00, - 0x5b, 0x97, 0x00, 0x40, 0x35, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x42, 0xc9, 0x01, 0x00, 0x64, 0x93, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x60, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x73, 0x93, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00, - 0x74, 0x93, 0x22, 0x40, 0x2d, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, - 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x6b, 0x93, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00, - 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00, 0x74, 0x93, 0x00, 0x5c, - 0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, - 0xe2, 0x95, 0x00, 0x40, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x78, 0x93, 0x23, 0x0d, 0x2c, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00, 0x80, 0x93, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x80, 0x93, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x7c, 0x93, 0xa8, 0x46, 0x1f, 0x00, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xea, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x85, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x8b, 0x93, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x8f, 0x93, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x8f, 0x93, 0xa2, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00, - 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0xa4, 0x93, 0x22, 0x4a, - 0x1f, 0x7c, 0x00, 0x00, 0x95, 0x93, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0xa0, 0x93, 0x22, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0x99, 0x93, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa5, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x85, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00, - 0x9d, 0x93, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, - 0x11, 0x90, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00, - 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xa1, 0x93, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xc9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, 0x32, 0x00, 0x2a, 0x15, - 0xe4, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x16, 0xe4, 0xb1, 0x00, 0x00, - 0xa7, 0x93, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf4, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0xb4, 0x93, 0x22, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0xb1, 0x93, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0xac, 0x93, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xd0, 0x01, 0x00, - 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00, 0xb0, 0x93, 0x22, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x11, 0x90, 0x01, 0x00, - 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00, 0x58, 0x01, 0x2d, 0x00, - 0x2a, 0xd0, 0x01, 0x00, 0x60, 0x01, 0x2d, 0xf0, 0x10, 0xb0, 0x01, 0x00, - 0x3f, 0x91, 0x00, 0xf0, 0x2c, 0xb0, 0x00, 0x00, 0xf4, 0x98, 0x00, 0x41, - 0x95, 0x30, 0x01, 0x00, 0xbb, 0x93, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x97, 0xb0, 0x01, 0x00, 0xb9, 0x93, 0x23, 0x0d, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, - 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0xf4, 0x93, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x01, 0x14, 0xb0, 0x01, 0x00, - 0xb0, 0x00, 0x2b, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6, - 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, - 0xcb, 0x93, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0xc4, 0x93, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, - 0x22, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x23, 0x80, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x84, 0xb0, 0x01, 0x00, 0xce, 0x93, 0x23, 0x0d, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x80, 0xb0, 0x01, 0x00, 0xd3, 0x93, 0x22, 0x40, - 0x1b, 0x6c, 0x00, 0x00, 0xf8, 0x97, 0x00, 0x01, 0x84, 0x50, 0x01, 0x00, - 0xdb, 0x93, 0x22, 0x40, 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x80, 0xc0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xf0, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00, - 0xd9, 0x93, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00, 0xea, 0x93, 0x00, 0x5e, - 0x17, 0x90, 0x00, 0x00, 0xde, 0x93, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x84, 0xd0, 0x01, 0x00, 0xe3, 0x93, 0x22, 0x40, 0x1b, 0x6c, 0x00, 0x00, - 0x19, 0x98, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0xea, 0x93, 0x22, 0x40, - 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0xc0, 0x01, 0x00, - 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0xf0, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00, - 0xe8, 0x93, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xeb, 0x93, 0xa8, 0x0a, 0x02, 0x30, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, - 0xf2, 0x93, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, 0xff, 0x07, 0x00, 0x11, - 0x00, 0x8c, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x98, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0xa1, 0x97, 0x00, 0x5e, - 0x05, 0x10, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xbf, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x8e, 0xb0, 0x01, 0x00, 0xb3, 0x96, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xea, 0x96, 0x00, 0x41, - 0x87, 0x30, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x05, 0x94, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x01, 0x94, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x07, 0x94, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x1a, 0xd0, 0x01, 0x00, 0x0d, 0x94, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xf4, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, 0x15, 0x94, 0x22, 0x08, - 0x80, 0x32, 0x00, 0x00, 0x38, 0x93, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00, - 0xf4, 0x98, 0x00, 0x41, 0x95, 0x30, 0x01, 0x00, 0x10, 0x94, 0x22, 0x08, - 0x80, 0x32, 0x00, 0x00, 0xbb, 0x93, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x97, 0xb0, 0x01, 0x00, 0x13, 0x94, 0x23, 0x0d, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, - 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x19, 0x94, 0x00, 0x4a, 0x1f, 0x90, 0x00, 0x00, - 0xf4, 0x95, 0x00, 0x00, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x0b, 0x96, 0x88, 0x01, 0x00, 0x27, 0x94, 0x26, 0x47, - 0x97, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, - 0x27, 0x94, 0x23, 0x4b, 0x0c, 0x6c, 0x00, 0x00, 0x33, 0x98, 0x00, 0x4b, - 0x04, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x16, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0xb0, 0x01, 0x00, - 0x33, 0x98, 0x00, 0x4b, 0x04, 0x50, 0x01, 0x00, 0x28, 0x94, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x33, 0x98, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00, - 0x2d, 0x94, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x2c, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x02, 0xb0, 0x01, 0x00, 0xda, 0x94, 0x00, 0x01, - 0x8c, 0x30, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, - 0x34, 0x94, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x30, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0x3d, 0x94, 0x22, 0x06, - 0x14, 0x50, 0x00, 0x00, 0x24, 0x97, 0x00, 0x45, 0x1f, 0x00, 0x01, 0x00, - 0x1b, 0x94, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x39, 0x94, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x1b, 0x94, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xea, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x42, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x48, 0x94, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x4b, 0x94, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x80, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, - 0x59, 0x94, 0x22, 0x4a, 0x1f, 0x7c, 0x00, 0x00, 0x51, 0x94, 0xa2, 0x16, - 0x02, 0x30, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, - 0x55, 0x94, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xf9, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x56, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xc9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, - 0x2a, 0xd0, 0x01, 0x00, 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, - 0xba, 0x8d, 0x00, 0x16, 0xe4, 0xb1, 0x00, 0x00, 0x35, 0x93, 0xa2, 0x16, - 0x02, 0x30, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xbf, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x95, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00, - 0x49, 0x93, 0x00, 0x10, 0x32, 0xb0, 0x00, 0x00, 0x8a, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0x63, 0x94, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x66, 0x94, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x74, 0x96, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00, - 0x7b, 0x96, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x68, 0x94, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0x20, 0x98, 0x00, 0x45, - 0x81, 0x30, 0x01, 0x00, 0xba, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xfe, 0x91, 0x00, 0x45, 0x1f, 0x90, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x49, 0x93, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x7a, 0x94, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, - 0x73, 0x94, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x62, 0xb1, 0x01, 0x00, 0x77, 0x94, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x74, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x62, 0xb1, 0x01, 0x00, 0x77, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xff, 0x89, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08, - 0xe0, 0xb1, 0x01, 0x00, 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00, - 0xb6, 0x96, 0x00, 0x47, 0x1f, 0x10, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x49, 0x93, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00, - 0xbf, 0x95, 0x00, 0x47, 0x1f, 0x10, 0x01, 0x00, 0x8c, 0x94, 0xa2, 0x08, - 0x80, 0x32, 0x00, 0x00, 0x88, 0x94, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, - 0x74, 0x96, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00, 0x7b, 0x96, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xf9, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0xaf, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, - 0xff, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08, - 0xe0, 0xb1, 0x01, 0x00, 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00, - 0xf4, 0x95, 0x00, 0x10, 0x32, 0x30, 0x01, 0x00, 0x49, 0x93, 0x00, 0x40, - 0x13, 0xb0, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x9c, 0x94, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, - 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x95, 0x94, 0x37, 0x5c, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00, - 0x99, 0x94, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x96, 0x94, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, - 0x99, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0x89, 0x17, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x8e, 0xb0, 0x01, 0x00, - 0xb3, 0x96, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0xea, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, - 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0xab, 0x94, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xa7, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x3f, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0x3f, 0x91, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x14, 0x00, 0x2d, 0x45, 0x1f, 0x90, 0x01, 0x00, - 0x87, 0x91, 0x00, 0x44, 0x19, 0x90, 0x00, 0x00, 0xb3, 0x94, 0xa2, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00, - 0xef, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x96, 0x00, 0x4a, - 0x1f, 0x10, 0x01, 0x00, 0x6f, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x49, 0x93, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00, 0xf4, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x49, 0x93, 0x00, 0x10, 0x32, 0xb0, 0x00, 0x00, - 0xfe, 0x91, 0x00, 0x45, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x37, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x33, 0xc3, 0x01, 0x00, - 0x36, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00, 0x00, 0x00, 0xd2, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xbf, 0x94, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x9f, 0x48, 0x03, 0xd0, 0x00, 0x00, 0xc1, 0x94, 0x9c, 0x17, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x4c, 0x03, 0xd0, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x01, 0x34, 0xc3, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x11, - 0x10, 0xc1, 0x00, 0x00, 0xc6, 0x94, 0x00, 0x40, 0x43, 0xc1, 0x00, 0x00, - 0xc6, 0x94, 0x00, 0x50, 0x43, 0xc1, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa1, - 0x42, 0xc9, 0x01, 0x00, 0xca, 0x94, 0x22, 0x40, 0xe5, 0x6d, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x40, 0xe5, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49, 0x1f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x41, 0x23, 0xd0, 0x00, 0x00, 0xc6, 0x94, 0x00, 0x50, - 0x43, 0xd1, 0x00, 0x00, 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0, 0xb1, 0x01, 0x00, - 0xd0, 0x95, 0x00, 0x41, 0xe1, 0x31, 0x01, 0x00, 0x00, 0x80, 0x00, 0x43, - 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd7, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x01, 0x8c, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x46, 0xe0, 0xc1, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x40, - 0x13, 0xb0, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x01, 0xe0, 0xc1, 0x01, 0x00, - 0xe1, 0x94, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0xfb, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xe3, 0x94, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x13, 0x90, 0x01, 0x00, 0x8d, 0x98, 0x00, 0x47, - 0x19, 0x10, 0x01, 0x00, 0xc0, 0x00, 0x2d, 0x44, 0x1f, 0x90, 0x01, 0x00, - 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0xd8, 0x98, 0x00, 0xf0, - 0x84, 0xb0, 0x00, 0x00, 0x90, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xf8, 0x94, 0xa2, 0x4b, 0x1f, 0x7c, 0x00, 0x00, 0x4b, 0x95, 0xa2, 0x4c, - 0x1f, 0x7c, 0x00, 0x00, 0xf8, 0x94, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, - 0xfb, 0x94, 0xa2, 0x01, 0x80, 0x32, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x46, - 0x8f, 0xb0, 0x01, 0x00, 0xf1, 0x94, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, - 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xf3, 0x94, 0x22, 0xf0, - 0x3a, 0x6c, 0x00, 0x00, 0x48, 0x95, 0x1f, 0xf0, 0x3a, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f, - 0x8f, 0xb0, 0x01, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x49, 0x95, 0x20, 0x42, 0xe7, 0x6d, 0x00, 0x00, 0xf7, 0x94, 0x22, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x59, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x58, 0x8f, 0xb0, 0x01, 0x00, 0xfa, 0x94, 0x22, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x5b, 0x8f, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, - 0xff, 0x94, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0x08, 0x95, 0x23, 0xf0, - 0x02, 0x6c, 0x00, 0x00, 0x05, 0x95, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00, - 0x4a, 0x95, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0x4a, 0x95, 0xa2, 0x41, - 0x03, 0x6c, 0x00, 0x00, 0x04, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x51, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x52, - 0x8f, 0xb0, 0x01, 0x00, 0x4a, 0x95, 0x1f, 0x12, 0x84, 0x50, 0x00, 0x00, - 0x4a, 0x95, 0xa0, 0x01, 0x84, 0x6c, 0x00, 0x00, 0xf8, 0x94, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x33, 0x95, 0xa2, 0x46, 0xe7, 0x7d, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x25, 0x95, 0x22, 0xf0, 0x14, 0x30, 0x00, 0x00, - 0x11, 0x95, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0x22, 0x95, 0x03, 0x1e, - 0x80, 0x32, 0x00, 0x00, 0x10, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49, - 0x8f, 0xb0, 0x01, 0x00, 0x16, 0x95, 0x22, 0x0a, 0x02, 0x6c, 0x00, 0x00, - 0x19, 0x95, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x15, 0x95, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00, 0x18, 0x95, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x82, 0xd0, 0x01, 0x00, - 0x1f, 0x95, 0x20, 0x91, 0x83, 0x6c, 0x00, 0x00, 0x1e, 0x95, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x27, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x21, 0x95, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x20, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x24, 0x95, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x22, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x23, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x88, 0x00, 0x2d, 0x44, - 0x8f, 0xb0, 0x01, 0x00, 0x2e, 0x95, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x2b, 0x95, 0xa2, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0x2b, 0x95, 0xa2, 0xf2, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0x2d, 0x95, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, 0x2b, 0x95, 0xa0, 0x91, - 0x03, 0x6c, 0x00, 0x00, 0x29, 0x95, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00, - 0x32, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x28, 0x00, 0x80, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x29, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x3c, 0x95, 0xa2, 0xf0, - 0x14, 0x30, 0x00, 0x00, 0x88, 0x00, 0x2d, 0x44, 0x8f, 0xb0, 0x01, 0x00, - 0x39, 0x95, 0xa2, 0xf2, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, - 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, - 0x2b, 0x95, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x29, 0x95, 0x20, 0x91, - 0x03, 0x6c, 0x00, 0x00, 0x2b, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x40, 0x95, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0x3f, 0x95, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0x45, 0x95, 0x22, 0x0a, - 0x02, 0x6c, 0x00, 0x00, 0x19, 0x95, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x44, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00, - 0x47, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, - 0x4d, 0x95, 0x00, 0x43, 0x95, 0xb0, 0x00, 0x00, 0x4d, 0x95, 0x00, 0x41, - 0x95, 0xb0, 0x00, 0x00, 0x4d, 0x95, 0x00, 0x42, 0x95, 0xb0, 0x00, 0x00, - 0x4d, 0x95, 0x00, 0x44, 0x95, 0xb0, 0x00, 0x00, 0x4d, 0x95, 0x00, 0x4c, - 0x95, 0xb0, 0x00, 0x00, 0xf5, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x50, 0x95, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4b, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4c, 0x8f, 0xb0, 0x01, 0x00, - 0x2d, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, - 0x84, 0xb0, 0x01, 0x00, 0x55, 0x95, 0xa2, 0xf3, 0x96, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x01, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x2a, 0x41, - 0xe7, 0xd1, 0x01, 0x00, 0xd4, 0x00, 0x3d, 0x41, 0x85, 0xe0, 0x01, 0x00, - 0x0b, 0x00, 0x00, 0xf2, 0x00, 0xe4, 0x01, 0x00, 0x5b, 0x95, 0x22, 0x5a, - 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00, - 0x5c, 0x95, 0x00, 0x5a, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x63, 0x41, 0x85, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0xa0, 0xa5, 0x85, 0x6c, 0x01, 0x00, 0x00, 0x00, 0xe3, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x3d, 0x99, 0x00, 0xf0, - 0x8c, 0xb0, 0x00, 0x00, 0x69, 0x95, 0x22, 0x40, 0x0f, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x66, 0x95, 0xa2, 0x4b, - 0x19, 0x7c, 0x00, 0x00, 0x67, 0x95, 0x22, 0xf0, 0x18, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x32, 0x96, 0x00, 0x07, - 0x10, 0x30, 0x01, 0x00, 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0x6b, 0x95, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0xb8, 0x95, 0x00, 0x40, - 0x81, 0x30, 0x01, 0x00, 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0x32, 0x96, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00, - 0x6f, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0x32, 0x96, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x05, 0xb0, 0x01, 0x00, 0x74, 0x95, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x77, 0x95, 0xa1, 0xad, 0x95, 0x20, 0x00, 0x00, 0x85, 0x95, 0x13, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4a, 0x5a, 0x83, 0x01, 0x00, - 0x30, 0x00, 0x39, 0x45, 0x95, 0xe0, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x0f, - 0x5e, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x5f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x45, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x48, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x58, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, - 0x4e, 0xb0, 0x01, 0x00, 0x12, 0x86, 0x00, 0x40, 0x5d, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x41, 0x97, 0xb0, 0x00, 0x00, - 0x82, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x97, 0xb0, 0x01, 0x00, 0x86, 0x95, 0x44, 0x07, 0x96, 0x30, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00, 0x00, 0x00, 0x1c, 0xc2, - 0x24, 0xb0, 0x01, 0x00, 0x90, 0x95, 0xa2, 0x45, 0x25, 0x7c, 0x00, 0x00, - 0x8a, 0x95, 0x31, 0x20, 0x85, 0x30, 0x00, 0x00, 0x91, 0x95, 0x22, 0x12, - 0x48, 0x7f, 0x00, 0x00, 0x51, 0x98, 0x11, 0x12, 0x48, 0x03, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x1e, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00, - 0x90, 0x95, 0x31, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, - 0x24, 0xb0, 0x01, 0x00, 0x91, 0x95, 0x22, 0x12, 0x48, 0x7f, 0x00, 0x00, - 0x51, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x9e, 0x95, 0x0b, 0xf0, 0x84, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x11, 0x12, 0x48, 0x83, 0x01, 0x00, 0x9b, 0x95, 0x22, 0x50, - 0x85, 0x70, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x51, 0x97, 0x00, 0xf2, 0x96, 0x30, 0x01, 0x00, 0xd1, 0x99, 0x00, 0x12, - 0x94, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x1f, 0x90, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4b, - 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x42, 0x10, 0xf4, 0x01, 0x00, - 0x00, 0xb7, 0x3f, 0x43, 0x11, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08, - 0x8a, 0x88, 0x01, 0x00, 0xa1, 0x95, 0x30, 0xa1, 0x0c, 0x30, 0x00, 0x00, - 0xa4, 0x95, 0x22, 0x45, 0xe6, 0x7d, 0x00, 0x00, 0x91, 0x95, 0x10, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x45, 0xe6, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x10, 0x12, 0x48, 0x83, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x85, 0x80, 0x01, 0x00, - 0x5e, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x51, 0x97, 0x00, 0xf2, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0xd8, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0xaf, 0x95, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x08, 0x86, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x68, 0xa7, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0xb3, 0x95, 0xa8, 0x05, 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x14, 0x00, 0x4b, 0x96, 0xdc, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x4b, 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x0f, - 0x84, 0xf4, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x42, 0x84, 0x88, 0x01, 0x00, - 0xbc, 0x95, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, 0xbd, 0x95, 0x00, 0x42, - 0x68, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x6a, 0xb1, 0x01, 0x00, - 0xbd, 0x95, 0x31, 0x5a, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x42, - 0x48, 0x93, 0x01, 0x00, 0xbf, 0x95, 0x35, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xc4, 0x95, 0x28, 0xb1, - 0x2c, 0x30, 0x00, 0x00, 0xc0, 0x95, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x95, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x6d, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xc4, 0x95, 0xa8, 0xb1, 0x10, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x95, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x7f, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xcb, 0x95, 0x28, 0xb1, 0x10, 0x30, 0x00, 0x00, - 0xc7, 0x95, 0x9f, 0xba, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x11, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x24, 0x11, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xcd, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xac, 0x94, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0xd1, 0x95, 0x32, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xd7, 0x95, 0x22, 0xf8, 0x96, 0x30, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf8, - 0x90, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x92, 0xb0, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x4b, 0xf0, 0xcd, 0x01, 0x00, 0x20, 0x00, 0x92, 0x48, - 0xe0, 0xc9, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xdb, 0x95, 0x28, 0xb1, 0x92, 0x30, 0x00, 0x00, 0xd7, 0x95, 0x22, 0x4c, - 0x75, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x12, 0x40, 0x91, 0xb0, 0x00, 0x00, - 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xdb, 0x95, 0xa8, 0xb1, - 0x90, 0x30, 0x00, 0x00, 0xff, 0x00, 0x00, 0x48, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x90, 0xd0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x4b, - 0xf0, 0xcd, 0x01, 0x00, 0x20, 0x00, 0x00, 0x48, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x92, 0x49, 0xe0, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0x82, 0x8c, 0x01, 0x00, - 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, - 0x00, 0xec, 0x00, 0x00, 0xe8, 0x95, 0x22, 0x1a, 0x00, 0x6c, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x00, 0x34, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x49, 0xc1, 0x01, 0x00, 0xe4, 0x95, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x15, 0x82, 0x8c, 0x01, 0x00, - 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, - 0x00, 0xec, 0x00, 0x00, 0xf1, 0x95, 0x22, 0x0d, 0x00, 0x6c, 0x00, 0x00, - 0xcc, 0x95, 0x00, 0x00, 0x1a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x49, 0xc1, 0x01, 0x00, 0xed, 0x95, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xf6, 0x95, 0x83, 0x1e, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x90, 0x01, 0x00, - 0x24, 0x00, 0x2d, 0x01, 0x2c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0, - 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, - 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x11, 0x10, 0xc1, 0x00, 0x00, - 0xff, 0x95, 0x00, 0x40, 0x43, 0xc1, 0x00, 0x00, 0xff, 0x95, 0x00, 0x50, - 0x43, 0xc1, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00, - 0x04, 0x96, 0x22, 0x40, 0xf5, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x43, 0xd1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, 0xe5, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49, - 0x1f, 0x90, 0x01, 0x00, 0x07, 0x96, 0x22, 0x11, 0x1e, 0x7c, 0x00, 0x00, - 0x09, 0x96, 0xa0, 0xf0, 0x16, 0x40, 0x00, 0x00, 0x09, 0x96, 0x00, 0x41, - 0x17, 0xc0, 0x00, 0x00, 0x09, 0x96, 0xa0, 0xf4, 0x16, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, - 0x23, 0xd0, 0x00, 0x00, 0xff, 0x95, 0x00, 0x52, 0x43, 0xd1, 0x00, 0x00, - 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, 0x0c, 0x96, 0x30, 0x47, - 0x17, 0x04, 0x00, 0x00, 0x0f, 0x96, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x90, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d, - 0x46, 0xc9, 0x01, 0x00, 0x13, 0x96, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, 0x00, 0x00, 0x90, 0x41, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x14, 0x96, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00, 0xdb, 0x99, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x1e, 0x96, 0xa2, 0x45, 0x95, 0x7c, 0x00, 0x00, - 0x01, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00, - 0x40, 0x97, 0x3e, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40, 0x9d, 0xe0, 0x01, 0x00, - 0x31, 0x96, 0x00, 0x3b, 0xe7, 0xb1, 0x00, 0x00, 0x1e, 0x96, 0x30, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x28, 0x96, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x24, 0x96, 0xa2, 0x0b, - 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x98, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d, - 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x41, - 0x81, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x21, 0xa2, 0x95, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x4a, 0x44, 0x83, 0x01, 0x00, 0x00, 0x97, 0x3e, 0x41, - 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf6, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40, - 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x07, - 0x92, 0x89, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x08, 0x86, 0xf4, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x43, - 0x46, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08, 0x82, 0x88, 0x01, 0x00, - 0x35, 0x96, 0x40, 0x08, 0x96, 0x30, 0x00, 0x00, 0xdb, 0x99, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x41, 0x96, 0x22, 0x45, 0x95, 0x7c, 0x00, 0x00, - 0x3d, 0x96, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, - 0x96, 0xf4, 0x01, 0x00, 0x3a, 0x96, 0x31, 0x5f, 0x97, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x11, 0x4b, 0x48, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x6a, 0xb1, 0x01, 0x00, 0x3d, 0x96, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xe6, 0x81, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x96, 0xb0, 0x01, 0x00, 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x63, 0xf3, 0x88, 0xb0, 0x01, 0x00, 0x49, 0x96, 0xa2, 0x3b, - 0x89, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, - 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00, 0x4a, 0x96, 0x18, 0x4a, - 0x44, 0x93, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x30, 0x00, 0x39, 0x45, 0x97, 0xe0, 0x01, 0x00, 0x4f, 0x96, 0x22, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x0f, 0x98, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x5e, 0x94, 0x01, 0x00, 0x51, 0x96, 0x00, 0x05, - 0x4a, 0xb0, 0x00, 0x00, 0x1f, 0x04, 0x00, 0xa7, 0x5e, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x4b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x52, 0x96, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x55, 0x96, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00, - 0xdb, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x59, 0x96, 0x22, 0x45, - 0x95, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xd9, 0x99, 0x00, 0x4a, 0x44, 0x13, 0x01, 0x00, 0x00, 0x97, 0x3f, 0x41, - 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, - 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3, - 0x88, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45, 0x97, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, - 0x61, 0x96, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x5a, 0x96, 0xa2, 0x3b, - 0x89, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xd1, 0x99, 0x00, 0x12, - 0x94, 0x30, 0x01, 0x00, 0x32, 0x96, 0x00, 0x5a, 0x1f, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00, 0x11, 0x00, 0x00, 0x4a, - 0xe6, 0xc9, 0x01, 0x00, 0x34, 0x00, 0x2f, 0x4f, 0x95, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0x4b, - 0x84, 0xc8, 0x01, 0x00, 0x00, 0x00, 0xa0, 0x43, 0x85, 0x6c, 0x01, 0x00, - 0x00, 0x00, 0xe3, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x2d, 0x44, - 0x1f, 0x90, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x2a, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf2, 0x02, 0x30, 0x00, 0x00, 0x51, 0x95, 0x00, 0x10, - 0x32, 0x30, 0x01, 0x00, 0x32, 0x00, 0xa0, 0x40, 0xe5, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, - 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x02, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x4c, 0x02, 0xd0, 0x00, 0x00, - 0x78, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, - 0x36, 0xb0, 0x01, 0x00, 0x88, 0x96, 0x22, 0x41, 0x03, 0x50, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xf1, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x81, 0x96, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x7c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, 0x7c, 0x96, 0x00, 0x5c, - 0x01, 0x80, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1b, 0x10, 0xb1, 0x00, 0x00, 0x68, 0x01, 0x2d, 0x06, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x82, 0xc0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x46, 0xc9, 0x01, 0x00, 0xc7, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xaf, 0x96, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x68, 0x08, 0x38, 0x96, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x41, - 0x82, 0xcc, 0x01, 0x00, 0x8d, 0x96, 0xaa, 0x41, 0x3b, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x11, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x04, 0xcc, 0x01, 0x00, - 0xae, 0x96, 0x26, 0x46, 0x23, 0x30, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, - 0x12, 0xc8, 0x01, 0x00, 0x64, 0x01, 0x20, 0xf0, 0xe0, 0xb1, 0x01, 0x00, - 0xad, 0x96, 0x22, 0x41, 0x05, 0x50, 0x00, 0x00, 0x20, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xf8, 0x86, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x22, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x9f, 0x96, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0xac, 0x96, 0x22, 0x41, 0x05, 0x50, 0x00, 0x00, 0xaa, 0x96, 0xa2, 0x41, - 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x1a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xa5, 0x96, 0xa8, 0x46, 0x23, 0x30, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x42, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x13, 0xc0, 0x01, 0x00, 0x9a, 0x96, 0x00, 0x50, - 0x49, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x1a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xae, 0x96, 0x22, 0x40, 0x3b, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x5c, - 0x01, 0x00, 0x01, 0x00, 0xaf, 0x96, 0x00, 0x41, 0x3b, 0xd0, 0x00, 0x00, - 0x00, 0x00, 0x8d, 0x47, 0x80, 0x32, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x5f, - 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xf0, 0x8c, 0xc0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, - 0xbb, 0x96, 0x8c, 0xf8, 0x8e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8, 0x14, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x26, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x2e, 0xf8, 0x0c, 0xb0, 0x01, 0x00, - 0x0c, 0x00, 0x2a, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, - 0xe0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, - 0xc8, 0x96, 0x20, 0x0a, 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x96, 0xb0, 0x01, 0x00, - 0x20, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x20, 0x4a, - 0xe0, 0xb1, 0x01, 0x00, 0x1c, 0x00, 0x20, 0x4b, 0xe0, 0xb1, 0x01, 0x00, - 0xb3, 0x96, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, 0x2c, 0x00, 0x2d, 0x42, - 0x19, 0x90, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0xce, 0x96, 0xa2, 0xa5, - 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00, - 0xd1, 0x96, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41, - 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, - 0xd6, 0x96, 0xa0, 0xa5, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x2c, 0x00, 0x20, 0x41, 0xe6, 0xb1, 0x01, 0x00, - 0xdb, 0x96, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x98, 0xdc, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x4c, 0xe4, 0xf5, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x1f, 0x80, 0x01, 0x00, 0x0b, 0x00, 0x80, 0x00, - 0xe4, 0xf5, 0x01, 0x00, 0xd0, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x41, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00, - 0xe7, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd0, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00, - 0xf6, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x84, 0xb0, 0x01, 0x00, - 0x01, 0x00, 0x63, 0xf3, 0x96, 0xc8, 0x01, 0x00, 0xfe, 0x96, 0x9f, 0x41, - 0x85, 0x50, 0x00, 0x00, 0x01, 0x00, 0x00, 0xa5, 0x85, 0xcc, 0x01, 0x00, - 0x2d, 0x00, 0xa0, 0x42, 0xe6, 0xb1, 0x01, 0x00, 0x5e, 0x01, 0x2d, 0x00, - 0x80, 0xb0, 0x01, 0x00, 0x03, 0x97, 0x52, 0x43, 0x81, 0x60, 0x00, 0x00, - 0x02, 0x00, 0x00, 0xf2, 0x82, 0xf4, 0x01, 0x00, 0x04, 0x97, 0x00, 0x41, - 0x80, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5e, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x95, 0xb0, 0x00, 0x00, - 0x05, 0x97, 0x9e, 0xbb, 0x80, 0x32, 0x00, 0x00, 0x0a, 0x97, 0xa2, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x15, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x2b, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x38, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x3a, 0xb0, 0x01, 0x00, 0x1f, 0x97, 0x9c, 0x17, - 0x80, 0x32, 0x00, 0x00, 0x14, 0x97, 0xa2, 0x4a, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x4c, 0x1f, 0x90, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x1e, - 0x98, 0xf4, 0x01, 0x00, 0x13, 0x97, 0xa2, 0x48, 0x99, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x15, 0x42, 0xb1, 0x01, 0x00, 0x13, 0x97, 0xa2, 0x8a, - 0xf1, 0x6d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x3e, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xf4, - 0x28, 0xcc, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x1e, 0x97, 0x20, 0xf0, 0x3e, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x2b, 0xc0, 0x01, 0x00, - 0xbf, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0xf3, - 0x3a, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0x07, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04, - 0xe6, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x1c, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x2d, 0xf0, - 0x26, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x06, 0x14, 0xec, 0x00, 0x00, 0x2b, 0x97, 0x22, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x06, 0x2a, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x96, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x2a, 0x4c, 0xe1, 0xc1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, - 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x18, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x35, 0x97, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0x01, 0x96, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x3b, 0x97, 0x45, 0x42, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0x3c, 0x97, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x68, 0x01, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x42, 0x97, 0x45, 0x42, 0x61, 0x31, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x43, 0x97, 0xa8, 0x00, - 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, - 0xf1, 0xb1, 0x01, 0x00, 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00, - 0xff, 0x7f, 0x00, 0xa1, 0xf0, 0x89, 0x01, 0x00, 0x02, 0x00, 0x00, 0x09, - 0x96, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x97, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x60, 0xa8, 0x97, 0xc0, 0x01, 0x00, 0x4d, 0x97, 0x46, 0x42, - 0x61, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x4a, 0x62, 0xc9, 0x01, 0x00, - 0x4e, 0x97, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x97, 0xf0, 0x01, 0x00, - 0x52, 0x97, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, 0x5a, 0x97, 0x22, 0xf3, - 0x74, 0x06, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x94, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x07, 0xe7, 0x85, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x55, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x62, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x57, 0x97, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa8, 0x36, 0xb0, 0x01, 0x00, 0x6a, 0x97, 0x82, 0x41, - 0x23, 0x40, 0x00, 0x00, 0x5f, 0x97, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0xda, 0x94, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, 0x20, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x65, 0x97, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x62, 0x97, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x6a, 0x97, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x95, 0x00, 0x43, - 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00, - 0x6c, 0x97, 0xa3, 0x15, 0x0c, 0x6c, 0x00, 0x00, 0x6d, 0x97, 0x00, 0x06, - 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x04, 0xb0, 0x01, 0x00, - 0x6f, 0x97, 0x20, 0x02, 0x1a, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x04, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x0b, 0x96, 0x88, 0x01, 0x00, - 0x74, 0x97, 0x26, 0x47, 0x97, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x97, 0xc0, 0x01, 0x00, 0x74, 0x97, 0x23, 0x4b, 0x04, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x04, 0xb0, 0x01, 0x00, 0x33, 0x98, 0x00, 0x05, - 0x48, 0x31, 0x01, 0x00, 0x9e, 0x97, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, - 0x78, 0x97, 0xa2, 0x02, 0x2a, 0x50, 0x00, 0x00, 0x9e, 0x97, 0xa2, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0x7a, 0x97, 0x22, 0x02, 0x0c, 0x50, 0x00, 0x00, - 0x83, 0x97, 0x00, 0x02, 0x16, 0xc0, 0x00, 0x00, 0x82, 0x97, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0x82, 0x97, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x7e, 0x97, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x24, 0x97, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x9e, 0x97, 0x22, 0x15, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, - 0x9d, 0x97, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00, 0x8f, 0x97, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x8f, 0x97, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x8b, 0x97, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00, - 0x2f, 0x00, 0x2f, 0x5c, 0x11, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0xe7, 0x91, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00, - 0x5c, 0x97, 0x20, 0x15, 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, - 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x9a, 0x97, 0xa8, 0x46, - 0x1f, 0x10, 0x00, 0x00, 0x5c, 0x97, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x5c, 0x97, 0x00, 0x02, 0x10, 0xc0, 0x00, 0x00, 0xa0, 0x97, 0xa2, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0xda, 0x94, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1b, 0x10, 0xb1, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x08, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5c, 0x1f, 0x90, 0x00, 0x00, - 0xa7, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, - 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x27, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x00, 0xb0, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x41, - 0xa3, 0x41, 0x01, 0x00, 0xab, 0x97, 0x00, 0x41, 0x27, 0xd0, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x07, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xb2, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x98, 0x00, 0x40, 0x2b, 0x30, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x06, - 0x16, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x16, 0xc4, 0x01, 0x00, - 0xba, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x6c, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x40, - 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xf0, 0x28, 0xb0, 0x01, 0x00, - 0xc3, 0x97, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43, - 0x86, 0xc8, 0x01, 0x00, 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00, - 0xc3, 0x97, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0xe4, 0x97, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00, - 0xd0, 0x97, 0xa2, 0x06, 0x14, 0x6c, 0x00, 0x00, 0xcd, 0x97, 0x22, 0x48, - 0x19, 0x7c, 0x00, 0x00, 0xc8, 0x97, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x31, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00, - 0x8b, 0x00, 0x2d, 0x48, 0x19, 0x80, 0x01, 0x00, 0x8b, 0x00, 0x20, 0x45, - 0xe7, 0x91, 0x01, 0x00, 0xd0, 0x97, 0x00, 0x40, 0x87, 0x90, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00, 0xd0, 0x97, 0xa0, 0x48, - 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0xb0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43, - 0xfc, 0xc9, 0x01, 0x00, 0x3b, 0x98, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0xdb, 0x97, 0x22, 0x4a, - 0x19, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, - 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, - 0x17, 0xc0, 0x01, 0x00, 0xda, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0xdf, 0x97, 0x64, 0xf0, - 0x82, 0xb0, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xdf, 0x97, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xe5, 0xb1, 0x01, 0x00, 0x8c, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00, - 0x90, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x06, - 0x30, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x86, 0x0c, 0x80, 0xb2, 0x00, 0x00, - 0xbc, 0x00, 0x2d, 0x46, 0x19, 0x90, 0x01, 0x00, 0xa0, 0x00, 0xa0, 0xf2, - 0xe4, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x10, 0x50, 0x00, 0x43, 0xfc, 0xc9, 0x01, 0x00, 0x3b, 0x98, 0x00, 0x30, - 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x4a, 0x19, 0xfc, 0x00, 0x00, - 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00, - 0xed, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xe4, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x1b, 0xe0, 0xb1, 0x00, 0x00, - 0xf2, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, - 0x7e, 0x89, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x4c, 0x95, 0x60, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x4a, 0x18, 0x94, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x01, 0xf0, 0x31, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x15, - 0xe0, 0xb1, 0x00, 0x00, 0xfd, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x10, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0xe8, 0x5f, 0x17, 0x90, 0x01, 0x00, 0x70, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x7a, 0x01, 0x2e, 0xfe, 0x92, 0xb0, 0x01, 0x00, - 0x8b, 0x00, 0x2d, 0xf6, 0x16, 0xb0, 0x01, 0x00, 0x0a, 0x98, 0x22, 0x43, - 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xa6, 0x2a, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x6e, 0x06, - 0x82, 0xc8, 0x01, 0x00, 0x0e, 0x98, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x45, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x6e, 0x4c, - 0x83, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x92, 0xc0, 0x01, 0x00, - 0x0f, 0x98, 0x42, 0x30, 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x66, 0x9e, - 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x41, 0x3d, 0xc3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x92, 0xc0, 0x01, 0x00, 0x06, 0x00, 0x00, 0xa2, - 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x49, 0x98, 0xf4, 0x01, 0x00, - 0x18, 0x98, 0x26, 0x30, 0x93, 0x04, 0x00, 0x00, 0x18, 0x98, 0x90, 0x4c, - 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, - 0xff, 0xff, 0x80, 0x49, 0xec, 0xa9, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x01, 0xf0, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0xf0, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x15, 0xe0, 0xb1, 0x00, 0x00, 0x1d, 0x98, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x2a, 0x98, 0x22, 0x5f, 0x81, 0x7c, 0x00, 0x00, - 0x29, 0x98, 0xa2, 0x40, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x07, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x97, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, - 0x29, 0x98, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x26, 0x98, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x21, 0x81, 0x84, 0x00, 0x00, - 0x2d, 0x98, 0xa2, 0x5f, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x43, - 0x19, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x19, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x96, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x30, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x02, - 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x13, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x08, 0xe0, 0xb1, 0x00, 0x00, 0x38, 0x98, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, - 0x02, 0x00, 0x00, 0xf0, 0x98, 0xf4, 0x01, 0x00, 0x41, 0x98, 0x20, 0x4c, - 0x84, 0x6c, 0x00, 0x00, 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x41, 0x98, 0x20, 0xf2, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x98, 0x00, 0x2d, 0x14, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x98, 0xb0, 0x01, 0x00, 0xa3, 0x00, 0x2d, 0x14, - 0x98, 0xd0, 0x01, 0x00, 0x46, 0x98, 0x20, 0x4c, 0x84, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x80, 0xe0, 0x01, 0x00, 0x49, 0x98, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x84, 0xb0, 0x01, 0x00, 0xd0, 0x00, 0x20, 0x14, - 0xe0, 0xb1, 0x01, 0x00, 0x98, 0x00, 0x25, 0x42, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x6e, 0xf3, 0x80, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x42, - 0x82, 0xc0, 0x00, 0x00, 0x4f, 0x98, 0xa0, 0x40, 0x16, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0, - 0x82, 0xec, 0x00, 0x00, 0x98, 0x00, 0xa0, 0x41, 0xe0, 0xb1, 0x01, 0x00, - 0x52, 0x98, 0x00, 0x12, 0x10, 0xc9, 0x00, 0x00, 0x00, 0x48, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x49, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x80, 0x4b, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x4d, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x4f, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0xc0, 0x50, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x52, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x40, 0x54, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x56, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x57, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x80, 0x59, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x40, 0x5b, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x5d, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x5e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x80, 0x60, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x62, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x64, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0xc0, 0x65, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x67, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x40, 0x69, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x6b, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x6c, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x80, 0x6e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x40, 0x70, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x72, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x73, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x80, 0x75, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x77, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x79, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0xc0, 0x7a, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x7c, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x40, 0x7e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x72, 0x98, 0x43, 0x57, 0x61, 0x31, 0x00, 0x00, 0x7e, 0x98, 0xa2, 0x57, - 0x73, 0x7d, 0x00, 0x00, 0x7e, 0x98, 0xa2, 0x40, 0x81, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x4a, - 0x62, 0xdd, 0x01, 0x00, 0x76, 0x98, 0xa8, 0x4a, 0x80, 0x33, 0x00, 0x00, - 0x7b, 0x98, 0x22, 0x5f, 0x95, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0x79, 0x98, 0xa8, 0x4b, 0xac, 0x33, 0x00, 0x00, - 0x00, 0x00, 0x1b, 0xa5, 0x82, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbe, - 0x83, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0x00, 0x10, 0x00, 0x4a, 0x62, 0xdd, 0x01, 0x00, 0x82, 0x98, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x7e, 0x98, 0x22, 0x57, 0x77, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x9b, 0x20, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0x82, 0x98, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x9b, 0x40, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x60, 0xa7, 0x97, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xa8, 0x00, 0x2d, 0x1c, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0, - 0x8a, 0xd0, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x8b, 0xec, 0x00, 0x00, - 0x8a, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0xa4, 0x00, 0x2d, 0x45, 0xe0, 0xd1, 0x01, 0x00, - 0x97, 0x98, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0xbe, 0x00, 0x2f, 0xab, - 0x83, 0xb0, 0x01, 0x00, 0xff, 0x98, 0x00, 0x14, 0x82, 0x50, 0x01, 0x00, - 0x9c, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x9c, 0x98, 0x22, 0xf2, - 0x82, 0x30, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x9c, 0x98, 0x9f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0xff, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xa8, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, 0x9c, 0x00, 0x2d, 0x30, - 0x81, 0xb0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, - 0x94, 0x00, 0x2d, 0xf2, 0x86, 0xb0, 0x01, 0x00, 0xc6, 0x98, 0x23, 0xf0, - 0x84, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x42, 0x88, 0xf4, 0x01, 0x00, - 0xc6, 0x98, 0x20, 0x50, 0x89, 0x6c, 0x00, 0x00, 0xb5, 0x98, 0xa3, 0x92, - 0x87, 0x6c, 0x00, 0x00, 0xa5, 0x98, 0x00, 0x44, 0x10, 0xc9, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x0a, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x09, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x08, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x07, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x07, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x07, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x06, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x06, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x06, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x06, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x06, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x05, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x05, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x05, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x05, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x05, 0x87, 0xb0, 0x00, 0x00, 0xb6, 0x98, 0x00, 0x44, - 0x10, 0xc9, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0f, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x0e, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0d, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0c, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x0c, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0c, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0c, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x0c, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0c, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00, - 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b, - 0x87, 0xb0, 0x00, 0x00, 0xc6, 0x98, 0x00, 0x0b, 0x87, 0xb0, 0x00, 0x00, - 0xbf, 0x00, 0x2d, 0x43, 0x84, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3, - 0x80, 0xe0, 0x01, 0x00, 0xcb, 0x98, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, - 0x94, 0x00, 0x20, 0x9d, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x84, 0xb0, 0x01, 0x00, 0xcf, 0x98, 0xa2, 0xf0, 0x38, 0x6c, 0x00, 0x00, - 0x9c, 0x00, 0x20, 0x42, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x13, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x46, 0x19, 0x80, 0x01, 0x00, - 0x9c, 0x00, 0x20, 0x42, 0xe0, 0xb1, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x80, 0xf4, 0x01, 0x00, - 0x0f, 0x00, 0x00, 0xf3, 0x82, 0x88, 0x01, 0x00, 0xd5, 0x98, 0x23, 0x41, - 0x80, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x89, 0x0c, 0x80, 0xb2, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xa0, 0x00, 0xa0, 0xf2, 0xe4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x9f, 0x41, 0x24, 0xec, 0x00, 0x00, 0xdf, 0x98, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x42, 0x38, 0xec, 0x00, 0x00, - 0xdf, 0x98, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xe1, 0x98, 0xa3, 0xf0, 0x3a, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xe5, 0x98, 0x22, 0xf0, 0x3a, 0x6c, 0x00, 0x00, - 0xb4, 0x00, 0x20, 0x1d, 0xe0, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x5f, - 0x13, 0x94, 0x01, 0x00, 0xe5, 0x98, 0x23, 0xf0, 0x3a, 0x6c, 0x00, 0x00, - 0x80, 0x00, 0x20, 0x1d, 0xe0, 0xb1, 0x01, 0x00, 0xc0, 0x00, 0x20, 0x12, - 0xe0, 0xb1, 0x01, 0x00, 0xc4, 0x00, 0xa0, 0x1c, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xe0, 0xb1, 0x01, 0x00, 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0xee, 0x98, 0x9f, 0x41, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, 0x8c, 0xd0, 0x01, 0x00, - 0xef, 0x98, 0x00, 0x41, 0x24, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0x3d, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xf1, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x08, 0x80, 0x32, 0x01, 0x00, - 0xf8, 0x98, 0xa2, 0x40, 0x95, 0x6c, 0x00, 0x00, 0xcc, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, - 0xa0, 0x98, 0x2f, 0x40, 0x11, 0xb0, 0x01, 0x00, 0xe3, 0x89, 0x00, 0x41, - 0x89, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xf8, 0x3e, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x9f, 0x12, 0xe0, 0xed, 0x00, 0x00, 0xc8, 0x00, 0x20, 0xab, - 0xe1, 0xb1, 0x01, 0x00, 0xcc, 0x00, 0xa0, 0x1f, 0xe0, 0xb1, 0x01, 0x00, - 0x01, 0x99, 0xa3, 0x5f, 0xe7, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xe7, 0xc1, 0x01, 0x00, 0xa6, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x15, 0x99, 0x22, 0xf2, 0x86, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x43, - 0x84, 0xf4, 0x01, 0x00, 0x01, 0x00, 0x00, 0x41, 0x80, 0xcc, 0x01, 0x00, - 0xb8, 0x00, 0x2d, 0x42, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x62, 0x40, - 0x86, 0xc0, 0x01, 0x00, 0x09, 0x99, 0x1f, 0x43, 0x80, 0x32, 0x00, 0x00, - 0x0a, 0x99, 0xa2, 0x40, 0x87, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x62, 0x41, - 0x87, 0xb0, 0x01, 0x00, 0x0e, 0x99, 0x9f, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x84, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x88, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x44, - 0x84, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2e, 0x42, 0x80, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x62, 0x40, 0x88, 0xc0, 0x01, 0x00, 0x14, 0x99, 0x1f, 0x44, - 0x80, 0x32, 0x00, 0x00, 0x18, 0x99, 0xa2, 0x40, 0x89, 0x6c, 0x00, 0x00, - 0x18, 0x99, 0x62, 0x41, 0x89, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x62, 0x41, - 0x86, 0xe4, 0x01, 0x00, 0xb8, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x62, 0x41, 0x88, 0xe4, 0x01, 0x00, 0xa4, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0xa2, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xbc, 0x00, 0x2e, 0x43, 0x87, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x86, 0xc0, 0x01, 0x00, 0x1e, 0x99, 0x20, 0x43, 0x87, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x43, 0xe5, 0xb1, 0x01, 0x00, 0x40, 0x01, 0x00, 0x43, - 0x80, 0xce, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x43, 0xe4, 0x31, 0x01, 0x00, - 0x40, 0x01, 0xe2, 0x40, 0x87, 0x98, 0x01, 0x00, 0x88, 0x00, 0x2d, 0x44, - 0x81, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf2, 0x2e, 0xb0, 0x01, 0x00, - 0x9c, 0x00, 0x2d, 0xf0, 0x86, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0xba, 0x00, 0x2d, 0xf0, 0x98, 0xb0, 0x01, 0x00, - 0x2b, 0x99, 0xa2, 0x12, 0x98, 0x6c, 0x00, 0x00, 0xbc, 0x00, 0x2d, 0xf2, - 0x98, 0xb0, 0x01, 0x00, 0x2b, 0x99, 0xa0, 0xf2, 0x98, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x17, 0x82, 0xb0, 0x01, 0x00, 0x9c, 0x00, 0x20, 0x41, - 0xe0, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x2d, 0x12, 0x86, 0xd0, 0x01, 0x00, - 0x2e, 0x99, 0xa3, 0x41, 0xe0, 0x6d, 0x00, 0x00, 0x2f, 0x99, 0x00, 0xf0, - 0x84, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x84, 0xb0, 0x01, 0x00, - 0x80, 0x00, 0x2d, 0x43, 0x84, 0xd0, 0x01, 0x00, 0x32, 0x99, 0x9f, 0x42, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, - 0x34, 0x99, 0xa3, 0x42, 0x14, 0x6c, 0x00, 0x00, 0x35, 0x99, 0x00, 0x0a, - 0x0c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x0c, 0xb0, 0x01, 0x00, - 0x37, 0x99, 0xa0, 0x17, 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x17, - 0x0c, 0xb0, 0x01, 0x00, 0x3c, 0x99, 0x22, 0x40, 0x0d, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0xa0, 0x0a, 0x0c, 0xec, 0x00, 0x00, 0x01, 0x00, 0x00, 0xf0, - 0x82, 0xf4, 0x01, 0x00, 0x3c, 0x99, 0xa0, 0x41, 0x0c, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb0, 0x01, 0x00, 0xd0, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x41, 0x87, 0x94, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00, - 0x48, 0x99, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0x05, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x04, 0xe6, 0xb1, 0x01, 0x00, 0x52, 0x99, 0x22, 0x49, - 0x1f, 0x7c, 0x00, 0x00, 0x42, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x1f, 0x80, 0x01, 0x00, 0xaa, 0x97, 0x00, 0x40, - 0x8d, 0xb0, 0x00, 0x00, 0x58, 0x99, 0x22, 0x40, 0xaf, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x15, 0x96, 0xb0, 0x01, 0x00, 0x72, 0x98, 0x00, 0x08, - 0x94, 0x30, 0x01, 0x00, 0x57, 0x99, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00, - 0xaa, 0x97, 0x00, 0x46, 0x87, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x87, 0xb0, 0x01, 0x00, 0x58, 0x99, 0x43, 0x48, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0x5d, 0x99, 0x28, 0x40, - 0x87, 0x30, 0x00, 0x00, 0x59, 0x99, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00, - 0xaa, 0x97, 0x1b, 0x46, 0x87, 0xb0, 0x00, 0x00, 0x60, 0x99, 0x22, 0x5f, - 0x11, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x15, 0x62, 0x31, 0x00, 0x00, - 0x5e, 0x99, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0xb0, 0x01, 0x00, - 0xb1, 0x99, 0x00, 0x49, 0x96, 0x30, 0x01, 0x00, 0x07, 0x00, 0x00, 0x49, - 0x06, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x03, 0x06, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xd0, - 0xa0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, - 0x65, 0x99, 0xa0, 0x54, 0x93, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x05, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x48, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xc0, 0x01, 0x00, 0xa2, - 0x44, 0xc9, 0x01, 0x00, 0x6e, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x49, 0xb3, 0x01, 0x00, 0xb6, 0x99, 0x00, 0x40, - 0x49, 0x31, 0x01, 0x00, 0x00, 0xb5, 0x2e, 0x08, 0x97, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x74, 0x99, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x00, 0x97, 0x2e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x78, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x2e, 0x05, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x7c, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x57, 0x95, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0x30, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x64, 0x00, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xb8, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00, - 0xba, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00, 0x98, 0x94, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x86, 0x99, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x68, 0xb1, 0x01, 0x00, 0x8a, 0x99, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00, - 0xc3, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x39, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x37, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x35, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x33, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x41, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x3f, 0xb3, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x40, - 0x29, 0x9b, 0x01, 0x00, 0xee, 0x05, 0x00, 0x40, 0x25, 0x9b, 0x01, 0x00, - 0x42, 0x00, 0x00, 0x40, 0x4b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x2f, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x47, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x43, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40, 0x2b, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, - 0xf1, 0x93, 0x01, 0x00, 0xff, 0xff, 0x00, 0xa5, 0x3c, 0x8b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x2c, 0x5b, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2c, - 0x45, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x59, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x57, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x27, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x53, 0xb3, 0x01, 0x00, - 0xa7, 0x99, 0xa2, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0xa7, 0x99, 0xa2, 0x51, - 0xfd, 0x7f, 0x00, 0x00, 0xa8, 0x99, 0x00, 0x40, 0x1d, 0xb3, 0x00, 0x00, - 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x00, 0xc0, 0x00, 0xa6, - 0x88, 0xb3, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xa6, 0x3a, 0xb3, 0x01, 0x00, - 0x00, 0xc0, 0x00, 0x9d, 0x3b, 0x9b, 0x01, 0x00, 0xb4, 0x05, 0x00, 0x40, - 0x23, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x4d, 0xb3, 0x01, 0x00, - 0x08, 0x0a, 0x00, 0xa6, 0x14, 0xb3, 0x01, 0x00, 0x01, 0x01, 0x00, 0x8a, - 0x15, 0x9b, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x5e, 0x57, 0xb5, 0x01, 0x00, 0x18, 0x00, 0x00, 0x4b, - 0x20, 0xe4, 0x01, 0x00, 0x06, 0x00, 0x00, 0x4b, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x43, 0x00, 0x4b, 0x96, 0xc8, 0x01, 0x00, 0x18, 0x00, 0x00, 0x10, - 0x20, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4b, 0x20, 0x94, 0x01, 0x00, - 0x00, 0x99, 0x2e, 0x0a, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xb7, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0xa9, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0xbb, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, - 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0xbf, 0x99, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xbf, 0x99, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x87, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x80, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, - 0x82, 0xb1, 0x01, 0x00, 0xc5, 0x99, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x97, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x90, 0xb1, 0x01, 0x00, - 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00, 0xca, 0x99, 0x85, 0x41, - 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xce, 0x99, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, - 0x80, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x9c, 0x4b, 0x82, 0x89, 0x01, 0x00, - 0xd1, 0x99, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0x80, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x9c, 0xa6, 0x82, 0xb1, 0x01, 0x00, - 0xd4, 0x99, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, - 0x84, 0x89, 0x01, 0x00, 0x00, 0x00, 0x9c, 0xc2, 0x24, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x80, 0x4b, - 0x92, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, - 0x01, 0x00, 0x80, 0xa6, 0x92, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4b, - 0x94, 0x89, 0x01, 0x00, 0x00, 0x00, 0x80, 0xca, 0x94, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb0, 0x01, 0x00, 0xdf, 0x99, 0x80, 0xa5, 0x80, 0x32, 0x00, 0x00, - 0xe0, 0x99, 0x00, 0xa5, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x81, 0xc0, 0x01, 0x00, 0xe1, 0x99, 0x80, 0xa5, 0x80, 0x32, 0x00, 0x00, - 0x80, 0x01, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xea, 0x99, 0x20, 0x4f, - 0x81, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0xea, 0x99, 0x20, 0x4b, 0x81, 0x6c, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0xea, 0x99, 0x20, 0x47, 0x81, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x82, 0xdc, 0x01, 0x00, 0x03, 0x90, 0x00, 0x41, 0x20, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x14, 0x2f, 0x4c, - 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0xee, 0x99, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x64, 0x00, 0x00, 0xa5, - 0x80, 0xc8, 0x01, 0x00, 0xf1, 0x99, 0xa2, 0xa5, 0x80, 0x6c, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x90, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x23, 0x91, 0x01, 0x00, 0xf4, 0x99, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x90, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x23, 0x91, 0x01, 0x00, 0xf7, 0x99, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x90, 0x20, 0xa9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x23, 0x91, 0x01, 0x00, 0xfa, 0x99, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0xfc, 0x99, 0x1f, 0x91, - 0x80, 0x32, 0x00, 0x00, 0x40, 0x68, 0x00, 0x90, 0x20, 0xa9, 0x01, 0x00, - 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x21, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x22, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x23, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x25, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x26, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x27, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xd0, 0x14, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x30, 0x03, 0x00, 0x40, 0x85, 0x30, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x02, 0x01, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, - 0x04, 0x03, 0x00, 0x40, 0x80, 0x98, 0x01, 0x00, 0x06, 0x05, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x08, 0x07, 0x00, 0x41, 0x82, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xe0, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00, - 0x30, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x39, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd8, 0x14, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xff, 0x02, 0xa2, 0xf8, 0x80, 0x6c, 0x00, 0x00, 0x00, 0x03, 0x22, 0xf0, - 0x82, 0x6c, 0x00, 0x00, 0xff, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd0, 0x14, 0x2e, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, - 0xa3, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc1, 0xb3, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0x1e, 0x9a, 0x00, 0x40, - 0x10, 0xc9, 0x00, 0x00, 0x24, 0x9a, 0x00, 0x05, 0x81, 0xb0, 0x00, 0x00, - 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x9a, 0x00, 0x05, - 0x81, 0xb0, 0x00, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x31, 0x9a, 0x00, 0x44, 0xa5, 0xb3, 0x00, 0x00, 0x33, 0x9a, 0x00, 0x44, - 0xa5, 0xb3, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0xa4, 0xe7, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xe0, 0x81, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0xc1, - 0xf0, 0x89, 0x01, 0x00, 0x29, 0x9a, 0x22, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x25, 0x9a, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xc5, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x5a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, - 0xa4, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x91, 0xb1, 0x01, 0x00, - 0xff, 0xff, 0x00, 0xc9, 0xf0, 0x89, 0x01, 0x00, 0x29, 0x9a, 0x22, 0x41, - 0x81, 0x50, 0x00, 0x00, 0x2d, 0x9a, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00, - 0xff, 0xff, 0x00, 0xde, 0x85, 0x89, 0x01, 0x00, 0x29, 0x9a, 0x00, 0xc2, - 0xe0, 0xb1, 0x00, 0x00, 0xff, 0xff, 0x00, 0xde, 0x95, 0x89, 0x01, 0x00, - 0x29, 0x9a, 0x00, 0xca, 0xe0, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0xcb, - 0x81, 0xc8, 0x01, 0x00, 0x6a, 0x84, 0x00, 0x40, 0xf2, 0x93, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb6, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, 0xb6, 0x9f, 0x00, 0x88, - 0x9a, 0xb0, 0x00, 0x00, 0xb6, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, - 0xb6, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, 0xb6, 0x9f, 0x00, 0x88, - 0x9a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x9a, 0xb0, 0x01, 0x00, - 0xb6, 0x9f, 0x41, 0x40, 0x81, 0x32, 0x00, 0x00, 0xb9, 0x9f, 0x22, 0x40, - 0x7b, 0x6f, 0x00, 0x00, 0xb6, 0x9f, 0x19, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x19, 0x41, 0x7b, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, - 0xc4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xc6, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x2f, 0xa2, 0xc8, 0xb3, 0x01, 0x00, 0x08, 0x14, 0x00, 0x40, - 0x49, 0x99, 0x01, 0x00, 0xb0, 0x9f, 0x00, 0x4d, 0x9a, 0xcc, 0x01, 0x00, - 0xc2, 0x9f, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x49, 0xc1, 0x01, 0x00, 0xc0, 0x9f, 0xa2, 0x41, 0x9b, 0x50, 0x00, 0x00, - 0xc6, 0x9f, 0x80, 0x80, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x52, 0x49, - 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xfd, 0x93, 0x01, 0x00, - 0xc9, 0x9f, 0x00, 0x42, 0xcd, 0x93, 0x00, 0x00, 0x00, 0x00, 0x51, 0x4a, - 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0xfd, 0x93, 0x01, 0x00, - 0xc9, 0x9f, 0x00, 0x43, 0xcb, 0x93, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xd9, 0x9f, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x49, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x40, 0xf0, 0x80, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x41, 0x4d, 0x80, 0xb2, 0x01, 0x00, 0xd1, 0x9f, 0x00, 0x40, - 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x9a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x10, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe2, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe3, - 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x45, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x7b, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x48, 0x4f, - 0x40, 0xb1, 0x01, 0x00, 0xd9, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x6a, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x19, 0x9a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x35, 0x9a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8, - 0x10, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, - }, -}; diff --git a/drivers/staging/slicoss/gbrcvucode.h b/drivers/staging/slicoss/gbrcvucode.h deleted file mode 100644 index 4fa5a4c23e57..000000000000 --- a/drivers/staging/slicoss/gbrcvucode.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 1997-2002 Alacritech, Inc. All rights reserved - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation - * are those of the authors and should not be interpreted as representing - * official policies, either expressed or implied, of Alacritech, Inc. - * - **************************************************************************/ -#define GB_RCVUCODE_VERS_STRING "1.2" -#define GB_RCVUCODE_VERS_DATE "2006/03/27 15:12:15" - -static u32 GBRcvUCodeLen = 512; - -static u8 GBRcvUCode[2560] = -{ -0x47, 0x75, 0x01, 0x00, 0x04, 0xa0, 0x13, 0x01, 0x00, 0x1c, 0xb7, 0x5b, 0x09, -0x30, 0x00, 0xb6, 0x5f, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x18, 0x3b, -0x78, 0x3a, 0x00, 0x1c, 0xa2, 0x77, 0x01, 0x00, 0x1c, 0x07, 0x1d, 0x01, 0x70, -0x18, 0xb3, 0x7b, 0xa9, 0xaa, 0x1e, 0xb4, 0x7b, 0x01, 0x0c, 0x1c, 0xb5, 0x7b, -0x1d, 0x06, 0x1c, 0x00, 0x00, 0x40, 0x64, 0x08, 0x0c, 0x31, 0x56, 0x70, 0x04, -0x0c, 0x31, 0x56, 0x80, 0x04, 0x0c, 0x31, 0x4a, 0x90, 0x04, 0x0c, 0x31, 0x46, -0xa0, 0x00, 0x09, 0x25, 0x51, 0xc0, 0x04, 0x0c, 0x31, 0x4e, 0xb0, 0x00, 0xe9, -0x24, 0x51, 0xc0, 0x04, 0xcc, 0xb3, 0x00, 0x1c, 0x1c, 0xeb, 0x2d, 0x01, 0x00, -0x1c, 0x06, 0x56, 0x42, 0xd4, 0x08, 0x07, 0x9d, 0x00, 0x00, 0x1c, 0x7b, 0xb7, -0x02, 0x00, 0x10, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0x06, 0x56, 0x5a, 0xc0, 0x04, -0xa0, 0x30, 0x6c, 0x03, 0x00, 0xac, 0x30, 0x6d, 0x03, 0x00, 0xcd, 0x03, 0x3a, -0x00, 0x1c, 0x7b, 0xb7, 0x02, 0x00, 0x1c, 0x60, 0x8e, 0x41, 0x54, 0x09, 0x29, -0x25, 0x6d, 0x03, 0x00, 0x80, 0x8e, 0x41, 0x54, 0x09, 0x8c, 0x30, 0x8d, 0x00, -0x04, 0x47, 0x1c, 0x01, 0x00, 0x1c, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0x00, 0x00, -0x60, 0x00, 0x04, 0x47, 0x1c, 0x61, 0xc0, 0x04, 0x47, 0x1c, 0x6d, 0x03, 0x00, -0x6c, 0x30, 0x01, 0x00, 0x1c, 0x4d, 0x34, 0x02, 0x00, 0x1c, 0x7b, 0xb7, 0x02, -0x00, 0x1c, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xc8, 0x83, 0x37, 0x00, 0x1c, 0x80, -0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x60, 0x00, 0x04, 0xa0, 0x0f, 0x40, 0x54, -0x09, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x7b, 0xfb, 0xf2, 0x00, 0x1c, 0xcc, 0x33, -0x0d, 0x00, 0x1c, 0xb4, 0x7b, 0xfd, 0x03, 0x1c, 0x80, 0x0e, 0x40, 0x54, 0x09, -0xe0, 0xfb, 0x05, 0x00, 0x1c, 0x00, 0x00, 0xa0, 0x03, 0x00, 0xb3, 0x0f, 0x41, -0x54, 0x09, 0x00, 0x00, 0xe8, 0x70, 0x04, 0x00, 0x00, 0xe8, 0x80, 0x04, 0x00, -0x00, 0xa0, 0x93, 0x00, 0x61, 0x76, 0xa1, 0xc3, 0x04, 0xc0, 0x8d, 0x41, 0x54, -0x09, 0xe0, 0x7b, 0x00, 0xc0, 0x1f, 0xa0, 0xfd, 0xc1, 0x01, 0x00, 0xcc, 0x33, -0x05, 0x00, 0x1c, 0xd4, 0x03, 0x00, 0x3c, 0x1c, 0xd4, 0xd3, 0x1b, 0x00, 0x1c, -0xc0, 0xd3, 0x52, 0x00, 0x1c, 0x00, 0x00, 0x74, 0x13, 0x04, 0x8e, 0x8e, 0x42, -0x54, 0x09, 0x5b, 0x80, 0x76, 0x13, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, -0x00, 0x90, 0x01, 0x00, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41, 0x54, -0x09, 0xc0, 0x03, 0xfc, 0x7f, 0x1c, 0xa0, 0x01, 0x9c, 0x01, 0x00, 0x00, 0x00, -0xa0, 0x01, 0x00, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xc0, 0x03, 0xfc, 0x03, 0x1c, -0xf5, 0x77, 0x01, 0x00, 0x1c, 0x26, 0x7a, 0xf6, 0x05, 0x1c, 0xa0, 0x0f, 0x41, -0x54, 0x09, 0xb3, 0x0f, 0x41, 0x54, 0x09, 0xb5, 0x02, 0x02, 0x00, 0x1c, 0xa0, -0x0f, 0x41, 0x54, 0x09, 0x7a, 0x06, 0x02, 0x00, 0x1c, 0xb5, 0x02, 0x02, 0x00, -0x1c, 0x53, 0x0f, 0x42, 0x54, 0x09, 0xaf, 0x03, 0x01, 0x00, 0x1c, 0x7a, 0x0e, -0x42, 0x54, 0x09, 0xb5, 0x02, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x02, 0x00, 0x1c, -0xa0, 0x3d, 0xa6, 0x11, 0x04, 0x00, 0x00, 0xa8, 0x11, 0x04, 0xd4, 0xd3, 0x52, -0x00, 0x1c, 0xb5, 0x3e, 0xae, 0x01, 0x00, 0x20, 0xfb, 0xfd, 0xff, 0x1f, 0x80, -0x2c, 0x84, 0x03, 0x00, 0xb9, 0x3a, 0x9a, 0x01, 0x00, 0x75, 0x3b, 0x02, 0x00, -0x1c, 0xa7, 0x1c, 0x01, 0x00, 0x10, 0xdb, 0x83, 0x16, 0x00, 0x1c, 0xc7, 0x1d, -0x1d, 0xc1, 0x04, 0xb9, 0x3b, 0x89, 0xc1, 0x04, 0x8b, 0x2c, 0x01, 0x00, 0x1c, -0x6b, 0x2c, 0x31, 0xc1, 0x04, 0x00, 0x00, 0x74, 0x11, 0x00, 0xcb, 0x2c, 0x75, -0xc1, 0x04, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0x54, -0xd0, 0x02, 0x00, 0x1c, 0x49, 0x25, 0xad, 0x01, 0x00, 0xab, 0x2c, 0x7d, 0xc1, -0x04, 0xa7, 0x1d, 0x6d, 0x03, 0x00, 0xcc, 0x33, 0x09, 0x00, 0x1c, 0xeb, 0x2d, -0x01, 0x00, 0x1c, 0xea, 0x29, 0x01, 0x00, 0x1c, 0xa0, 0x0f, 0x41, 0x54, 0x09, -0xae, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xd4, 0x07, 0xfc, -0x03, 0x1c, 0x99, 0x3a, 0x02, 0x00, 0x1c, 0xbb, 0x38, 0x02, 0x00, 0x1c, 0x00, -0x38, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xf8, 0x01, 0x04, 0xdb, 0x3b, 0x7e, 0x00, -0x1c, 0xc7, 0x1d, 0x01, 0x00, 0x1c, 0x26, 0x7a, 0x0a, 0x06, 0x1c, 0x27, 0x1d, -0x01, 0x00, 0x1c, 0xb3, 0x0f, 0x41, 0x54, 0x09, 0x7a, 0x0e, 0x42, 0x54, 0x09, -0x53, 0x0f, 0x42, 0x54, 0x09, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f, 0x42, -0x54, 0x09, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f, 0x42, 0x54, 0x09, 0xa0, -0x0f, 0x41, 0x54, 0x09, 0x7a, 0x06, 0x02, 0x00, 0x1c, 0x53, 0x0f, 0x42, 0x54, -0x09, 0xaf, 0x03, 0x01, 0x00, 0x1c, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f, -0x42, 0x54, 0x09, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f, 0x42, 0x54, 0x09, -0x7a, 0x0e, 0x42, 0x54, 0x09, 0x53, 0x0f, 0x42, 0x54, 0x09, 0x7a, 0x0e, 0x42, -0x54, 0x09, 0x00, 0x3d, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x54, 0x12, 0x00, 0xcb, -0x2c, 0x01, 0x00, 0x1c, 0x75, 0x3b, 0x02, 0x00, 0x1c, 0xa7, 0x1c, 0x01, 0x00, -0x10, 0xa6, 0x7b, 0xf1, 0x05, 0x1c, 0x00, 0x00, 0x88, 0xc2, 0x04, 0xa6, 0x7b, -0xf1, 0x05, 0x1c, 0x00, 0x00, 0xa0, 0xc2, 0x04, 0xcb, 0x2f, 0x05, 0x00, 0x1c, -0x60, 0x2c, 0x00, 0x00, 0x1c, 0xc7, 0x1c, 0xe1, 0x02, 0x00, 0x53, 0x0f, 0x42, -0x54, 0x09, 0xc0, 0x83, 0xf1, 0x32, 0x1c, 0x00, 0x00, 0x5c, 0x02, 0x04, 0x46, -0x7a, 0xda, 0x05, 0x1c, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0xc0, 0x83, 0xf1, 0x32, -0x1c, 0x00, 0x00, 0x64, 0x02, 0x04, 0x40, 0xfa, 0x15, 0x00, 0x1c, 0x00, 0x00, -0xa0, 0x02, 0x04, 0x46, 0x7a, 0xda, 0x05, 0x1c, 0xa0, 0x0f, 0x41, 0x54, 0x09, -0xa0, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xa0, 0x0f, 0x41, -0x54, 0x09, 0xb3, 0x7b, 0x01, 0xc0, 0x1f, 0x74, 0x0e, 0x40, 0x54, 0x09, 0xc0, -0x03, 0x9c, 0x00, 0x1c, 0x80, 0x00, 0xf0, 0x02, 0x00, 0x00, 0x00, 0xf0, 0x02, -0x04, 0x00, 0x00, 0xc4, 0x12, 0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xd4, 0xd3, -0x2b, 0x00, 0x1c, 0xd4, 0xd3, 0x52, 0x00, 0x1c, 0x80, 0x76, 0x95, 0x13, 0x04, -0x00, 0x00, 0xf8, 0x02, 0x00, 0xa6, 0x7b, 0xa9, 0x03, 0x10, 0xc7, 0x9c, 0x00, -0x00, 0x1c, 0x80, 0x2c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x78, 0x02, 0x04, 0x00, -0x00, 0x6c, 0xc3, 0x04, 0xab, 0x2d, 0xf1, 0x12, 0x05, 0x07, 0x1d, 0xcd, 0xc2, -0x04, 0x8b, 0x2d, 0x01, 0x00, 0x1c, 0x69, 0x25, 0x01, 0x00, 0x1c, 0xa6, 0x7b, -0xa9, 0x03, 0x10, 0xcb, 0x2f, 0x09, 0x00, 0x1c, 0x60, 0x2c, 0x00, 0x00, 0x1c, -0x00, 0x00, 0x60, 0x03, 0x00, 0x53, 0x0f, 0x42, 0x54, 0x09, 0x46, 0x7a, 0xda, -0x05, 0x1c, 0x7a, 0x0e, 0x42, 0x54, 0x09, 0x40, 0xfa, 0x15, 0x00, 0x1c, 0x00, -0x00, 0x28, 0x03, 0x04, 0x46, 0x7a, 0xda, 0x05, 0x1c, 0xb5, 0x0f, 0x41, 0x54, -0x09, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0x73, 0xec, 0x42, 0x03, 0x04, 0x60, 0x2c, -0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x03, 0x00, 0xc7, 0x1c, 0x01, 0x00, 0x1c, -0x00, 0x00, 0x40, 0x13, 0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xc0, 0xd7, 0x22, -0x00, 0x1c, 0x75, 0x56, 0x96, 0x13, 0x04, 0x60, 0x2c, 0x00, 0x00, 0x1c, 0xe7, -0x1c, 0x5d, 0x03, 0x04, 0xe7, 0x9c, 0x00, 0x00, 0x1c, 0xa6, 0x7b, 0xa9, 0x03, -0x10, 0x80, 0x2c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x10, 0x03, 0x04, 0x00, 0x00, -0x6c, 0xc3, 0x04, 0xb9, 0x7b, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xa0, 0xc3, 0x04, -0xcb, 0xaf, 0xfc, 0x07, 0x1c, 0xcb, 0x2f, 0x01, 0x04, 0x1c, 0xc7, 0x9f, 0x80, -0x03, 0x1c, 0x00, 0x00, 0xa0, 0xc3, 0x04, 0xcb, 0xaf, 0xfc, 0x07, 0x1c, 0xcb, -0x2f, 0x0d, 0x04, 0x1c, 0xc7, 0x9f, 0x80, 0x03, 0x1c, 0x00, 0x00, 0xa0, 0xc3, -0x04, 0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb, 0x2f, 0x01, 0x00, 0x1d, 0x00, 0x00, -0xa0, 0xc3, 0x04, 0x00, 0x00, 0xa0, 0x13, 0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c, -0xc0, 0x1d, 0xf0, 0xd3, 0x08, 0x27, 0x9d, 0xf8, 0x03, 0x00, 0xa0, 0xee, 0x56, -0xd4, 0x00, 0xfb, 0x75, 0x19, 0x14, 0x04, 0x20, 0x7b, 0x06, 0x00, 0x1c, 0xc0, -0x1c, 0x2c, 0x04, 0x00, 0x00, 0x00, 0xc4, 0xd3, 0x08, 0x00, 0x00, 0x10, 0xf4, -0x00, 0xc0, 0xef, 0xf2, 0x00, 0x1c, 0x20, 0x25, 0x6c, 0x14, 0x04, 0x60, 0xb7, -0xe6, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x15, 0x00, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, -0xcc, 0x33, 0x05, 0x02, 0x1c, 0x00, 0x00, 0x1c, 0xc5, 0x04, 0x60, 0xb7, 0x1e, -0x05, 0x04, 0x00, 0x00, 0x1c, 0x15, 0x04, 0x00, 0x00, 0x6c, 0xc4, 0x04, 0xc0, -0x1d, 0xac, 0xf3, 0x04, 0x00, 0x00, 0x78, 0xc4, 0x04, 0x07, 0x9d, 0x00, 0x00, -0x1c, 0x1b, 0x74, 0x0d, 0xf4, 0x04, 0xa0, 0x0f, 0x41, 0x54, 0x09, 0xe0, 0x7b, -0x00, 0xfc, 0x1f, 0x39, 0x7f, 0x02, 0x00, 0x1c, 0x07, 0x1d, 0xb1, 0xc3, 0x04, -0xa6, 0x7b, 0xc1, 0x03, 0x1c, 0x00, 0x00, 0x78, 0xc4, 0x04, 0xe0, 0x1c, 0x00, -0x00, 0x1c, 0x00, 0x00, 0xb8, 0x03, 0x04, 0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb, -0x2f, 0x01, 0x10, 0x1d, 0x00, 0x00, 0xc0, 0xc3, 0x04, 0x00, 0x00, 0xc0, 0x03, -0x04, 0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb, 0x2f, 0x01, 0x18, 0x1d, 0xc7, 0x9f, -0x00, 0x0b, 0x1c, 0x00, 0x00, 0xc0, 0xc3, 0x04, 0xfb, 0x75, 0x01, 0x00, 0x1c, -0x07, 0x1d, 0x01, 0x00, 0x1c, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x01, -0x02, 0x1c, 0x00, 0x00, 0xc0, 0xc3, 0x04, 0xa0, 0x1c, 0x00, 0x00, 0x1c, 0xa0, -0xee, 0xb6, 0x03, 0x04, 0xcb, 0xaf, 0xfc, 0x07, 0x1c, 0xcb, 0x2f, 0x09, 0x04, -0x1c, 0xfb, 0x75, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xc0, 0xc3, 0x04, 0xcc, 0xb3, -0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x01, 0x02, 0x1c, 0x00, 0x00, 0x1c, 0xc5, 0x04, -0x00, 0x00, 0x88, 0x34, 0x05, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x15, -0x02, 0x1c, 0x47, 0x9d, 0x64, 0xc4, 0x04, 0x00, 0x00, 0x88, 0x44, 0x00, 0x80, -0x1d, 0x8c, 0x54, 0x04, 0x87, 0x1d, 0x9d, 0x04, 0x00, 0xce, 0x76, 0x01, 0x00, -0x1c, 0xef, 0x76, 0xad, 0xc4, 0x04, 0xa4, 0x77, 0x9d, 0x24, 0x09, 0xe4, 0x76, -0x01, 0x00, 0x1c, 0xc4, 0x76, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xa8, 0x54, 0x04, -0xd7, 0x76, 0x01, 0x50, 0x18, 0xf6, 0x76, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, -0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0xcc, 0x30, 0x51, 0xc5, 0x04, 0xeb, -0x2d, 0x01, 0x00, 0x1c, 0xea, 0x29, 0x01, 0x00, 0x1c, 0xc0, 0x59, 0x01, 0x00, -0x1c, 0xf5, 0x77, 0x39, 0xc5, 0x04, 0xe0, 0x30, 0xec, 0x04, 0x00, 0x00, 0x4c, -0xc0, 0x04, 0x00, 0x20, 0x4c, 0x04, 0x05, 0x00, 0x00, 0x00, 0xf8, 0x04, 0x00, -0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x09, 0x02, 0x1c, 0xeb, 0x2d, 0xc5, -0xc4, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x19, 0x02, 0x1c, 0xeb, -0x2d, 0xc5, 0xc4, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x0d, 0x02, -0x1c, 0xeb, 0x2d, 0xc5, 0xc4, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, -0x11, 0x02, 0x1c, 0xeb, 0x2d, 0xc5, 0xc4, 0x04, 0x00, 0x7b, 0x00, 0x80, 0x1c, -0xae, 0x77, 0x51, 0x05, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x04, 0xd3, 0x8b, 0x00, -0xfc, 0x1f, 0x60, 0x7a, 0x3c, 0x00, 0x1c, 0x60, 0x4c, 0xd0, 0x04, 0x00, 0xc0, -0x2f, 0x20, 0x05, 0x1f, 0xe0, 0x30, 0xc0, 0x04, 0x00, 0x80, 0x25, 0xc0, 0x04, -0x00, 0xb5, 0x5b, 0xc1, 0x04, 0x04, 0x69, 0x26, 0x01, 0x00, 0x1c, 0x6a, 0x2b, -0x01, 0x00, 0x1c, 0x80, 0x1d, 0x00, 0x00, 0x1c, 0xa9, 0x25, 0x51, 0x05, 0x00, -0xee, 0x30, 0x00, 0x00, 0x1c, 0xaf, 0x77, 0x11, 0x05, 0x00, 0xb4, 0x5f, 0x01, -0x40, 0x18, 0x07, 0x9d, 0x54, 0x55, 0x04, 0xb7, 0x76, 0x01, 0x00, 0x1c, 0x96, -0x76, 0x01, 0x00, 0x1c, 0x47, 0x1d, 0x01, 0x00, 0x1c, 0xa4, 0x33, 0x01, 0x60, -0x18, 0xa4, 0x2f, 0x01, 0x60, 0x18, 0x64, 0x77, 0x01, 0x60, 0x18, 0x24, 0x77, -0x01, 0x60, 0x18, 0x44, 0x77, 0x01, 0x00, 0x1c, 0x64, 0x88, 0x03, 0x00, 0x1c, -0xa4, 0x3f, 0x01, 0x00, 0x1c, 0xa4, 0x3b, 0x01, 0x00, 0x1c, 0x53, 0x77, 0x01, -0x00, 0x1c, 0xd3, 0xcf, 0x3b, 0x00, 0x1c, 0x53, 0x4f, 0x02, 0x00, 0x1c, 0xd3, -0xcf, 0x00, 0x00, 0x1f, 0xda, 0xcf, 0x0b, 0x00, 0x1c, 0xd5, 0x57, 0x0f, 0x00, -0x1c, 0xd3, 0xd3, 0x37, 0x00, 0x1c, 0xd4, 0x53, 0x0f, 0x00, 0x1c, 0xe0, 0x29, -0x00, 0x00, 0x1c, 0xf5, 0xd5, 0xc0, 0x05, 0x00, 0x00, 0x00, 0xac, 0x55, 0x04, -0x77, 0x56, 0x01, 0x00, 0x1c, 0x56, 0x53, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, -0x10, 0x18, 0x00, 0x00, 0x04, 0xc0, 0x04, 0xf5, 0x55, 0x01, 0x00, 0x1c, 0x00, -0x00, 0xc4, 0x55, 0x04, 0x77, 0x56, 0x01, 0x00, 0x1c, 0x56, 0x53, 0x01, 0x00, -0x1c, 0x00, 0x00, 0x00, 0x10, 0x18, 0x00, 0x00, 0x04, 0xc0, 0x04, 0xcb, 0x2f, -0x01, 0x18, 0x10, 0xcb, 0x2f, 0x01, 0x10, 0x10, 0xcb, 0x2f, 0x01, 0x08, 0x10, -0xcb, 0x2f, 0x01, 0x08, 0x10, 0xcb, 0x2f, 0x01, 0x20, 0x10, 0xcb, 0x2f, 0x01, -0x00, 0x10, 0xcb, 0x2f, 0x01, 0x28, 0x10, 0x89, 0x25, 0x6d, 0xc2, 0x04, 0x00, -0x00, 0x04, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3, -0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc2, 0x04, 0x00, 0x00, -0x04, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, -0x00, 0x00, 0x6c, 0xc3, 0x04, 0x40, 0x1c, 0x68, 0xc0, 0x04, 0x40, 0x1c, 0x98, -0xc0, 0x04, 0xa7, 0x77, 0x6d, 0xc3, 0x04, 0x00, 0x00, 0xc0, 0xc0, 0x04, 0x27, -0x1d, 0xed, 0xc0, 0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x6c, 0xc3, -0x04, 0x00, 0x00, 0x6c, 0xc3, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, -0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, -0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, -0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, -0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, -0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, -0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, -0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, -0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, -0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, -0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, -0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, -0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, -0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, -0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, -0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, -0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, -0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, -0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, -0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, -0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, -0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, -0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, -0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, -0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, -0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, -0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, -0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, -0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, -0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, -0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, -0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, -0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, -0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, -0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, 0x00, 0x00, 0x3c, 0xc6, 0x04, -}; diff --git a/drivers/staging/slicoss/oasisdbgdownload.h b/drivers/staging/slicoss/oasisdbgdownload.h deleted file mode 100644 index 519e00797d44..000000000000 --- a/drivers/staging/slicoss/oasisdbgdownload.h +++ /dev/null @@ -1,6850 +0,0 @@ -#define OASIS_UCODE_VERS_STRING "1.2" -#define OASIS_UCODE_VERS_DATE "2006/03/27 15:11:22" -#define OASIS_UCODE_HOSTIF_ID 3 - -static s32 ONumSections = 0x2; -static u32 OSectionSize[] = -{ - 0x00004000, 0x00010000, -}; - -static u32 OSectionStart[] = -{ - 0x00000000, 0x00008000, -}; - -static u8 OasisUCode[2][65536] = -{ - { - 0x15, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, - 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0xa2, 0x40, 0xfd, 0x7f, 0x00, 0x00, - 0x09, 0x00, 0xa2, 0x49, 0xdd, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x80, 0xb2, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x80, 0xb2, 0x01, 0x00, 0x09, 0x00, 0xa2, 0x40, - 0x75, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x0b, 0x00, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x8f, 0x98, 0x18, 0x31, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x98, 0x80, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x41, 0x98, - 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x98, 0x80, 0xe4, 0x01, 0x00, 0x0e, 0x00, 0x40, 0x98, - 0x80, 0x94, 0x00, 0x00, 0x11, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x19, 0x00, 0x29, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x19, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x0e, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x1f, 0x00, 0x29, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x12, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x25, 0x00, 0x29, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x25, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x14, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xdd, 0x81, 0x01, 0x00, 0x12, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x33, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2a, 0x00, 0x14, 0xbc, - 0x80, 0x32, 0x00, 0x00, 0xfe, 0x00, 0x13, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x54, 0x95, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xfd, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xb3, 0x01, 0x00, - 0x33, 0x00, 0x18, 0xee, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x89, 0xb0, 0x01, 0x00, 0x32, 0x00, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00, - 0x99, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x30, 0x94, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x20, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0xe0, 0xb3, 0x01, 0x00, 0x39, 0x00, 0x98, 0xee, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x80, 0xb0, 0x01, 0x00, - 0x3b, 0x00, 0x80, 0xf3, 0xde, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0xfd, 0x93, 0x01, 0x00, 0x3e, 0x00, 0x83, 0xf3, 0x80, 0x32, 0x00, 0x00, - 0xf0, 0x00, 0x00, 0xf3, 0x80, 0x88, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, - 0x2e, 0xdd, 0x01, 0x00, 0x00, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x43, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, - 0x24, 0xb1, 0x01, 0x00, 0x7c, 0x00, 0x18, 0xee, 0x80, 0x32, 0x00, 0x00, - 0x45, 0x00, 0x95, 0xe8, 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0xe8, - 0x80, 0x88, 0x01, 0x00, 0x7c, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd6, 0xb1, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xd6, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf8, 0xee, 0x8b, 0x01, 0x00, - 0x08, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf0, - 0x80, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x81, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf8, - 0x80, 0x88, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0xff, 0x00, 0x00, 0xf0, 0xd6, 0x8d, 0x01, 0x00, 0xff, 0xff, 0x00, 0xf0, - 0xf0, 0xdb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x81, 0x94, 0x01, 0x00, 0x3c, 0x01, 0x00, 0x40, - 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, - 0xff, 0x00, 0x00, 0xf8, 0x80, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0x81, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x81, 0x94, 0x01, 0x00, - 0x3c, 0x02, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xd6, 0xb1, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xd6, 0xb1, 0x01, 0x00, 0x1e, 0x00, 0x00, 0xf0, - 0x82, 0xf4, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xf8, 0x80, 0xd8, 0x01, 0x00, - 0x64, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x81, 0xd0, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40, 0x80, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xd8, 0xb1, 0x01, 0x00, 0x68, 0x00, 0x22, 0xfa, 0x80, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x81, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x40, - 0x80, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xde, 0xb1, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa, - 0x80, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x81, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, - 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa, 0x80, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf6, 0x81, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xd6, 0xb1, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0x10, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, - 0xd5, 0x99, 0x01, 0x00, 0x18, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, - 0x48, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa, - 0xd6, 0xe5, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0x10, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, 0x03, 0x00, 0x00, 0xfb, - 0x7a, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xdc, 0xb1, 0x01, 0x00, - 0x7c, 0x00, 0x00, 0x4c, 0xdd, 0x91, 0x00, 0x00, 0x7c, 0x00, 0x95, 0xe8, - 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xe9, 0xfa, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0x42, - 0x80, 0x88, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, - 0x7c, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x85, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x02, 0x80, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x7c, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x81, 0xb0, 0x01, 0x00, 0x8e, 0x00, 0x09, 0xf9, 0x81, 0x32, 0x00, 0x00, - 0x8c, 0x00, 0x08, 0xf9, 0x81, 0x32, 0x00, 0x00, 0x98, 0x00, 0x1f, 0xfd, - 0xf9, 0x33, 0x00, 0x00, 0x8b, 0x00, 0x9e, 0xfd, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, - 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf7, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x49, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x19, 0xb1, 0x01, 0x00, 0x93, 0x00, 0x0a, 0xf9, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x40, 0xfb, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xfd, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x07, 0x80, 0xf9, 0xf3, 0x8f, 0x01, 0x00, - 0x00, 0x07, 0x42, 0xf9, 0xf3, 0x8f, 0x01, 0x00, 0x97, 0x00, 0xa2, 0xff, - 0xf7, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0xff, 0xfb, 0xef, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfc, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x94, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xbb, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x46, 0xfd, 0x7f, 0x01, 0x00, - 0x00, 0x94, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xce, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, 0xfd, 0x7f, 0x01, 0x00, - 0x00, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0xff, 0x7f, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x9a, 0x13, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x03, 0x01, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x9a, 0x13, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x02, 0x29, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x67, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0xfd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0xfd, 0x83, 0x01, 0x00, - 0xff, 0x7f, 0x00, 0x40, 0x25, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, 0x80, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0xfd, 0x93, 0x01, 0x00, 0xe2, 0x00, 0x00, 0x40, - 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x46, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x40, 0x2b, 0x31, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x46, 0x88, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x94, 0x8c, 0xb0, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x46, 0x80, 0x88, 0x01, 0x00, 0xa5, 0xa5, 0xa2, 0x40, - 0x80, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0xf0, 0x01, 0x00, - 0xc9, 0x00, 0x82, 0x41, 0x89, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xfd, 0x83, 0x01, 0x00, - 0xd4, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, - 0x80, 0xb2, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x08, 0x83, 0x30, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x44, - 0xfd, 0x93, 0x01, 0x00, 0x00, 0x30, 0x00, 0x08, 0x83, 0x98, 0x01, 0x00, - 0x80, 0x00, 0x00, 0x40, 0x2b, 0x99, 0x01, 0x00, 0xdb, 0x00, 0x00, 0x40, - 0x89, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x46, 0x80, 0xb2, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x94, 0x80, 0x88, 0x01, 0x00, 0xa5, 0xa5, 0xa2, 0x40, - 0x80, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x80, 0x43, 0x89, 0xb0, 0x01, 0x00, - 0x03, 0x84, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, 0xde, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x03, 0x88, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x96, - 0x80, 0xb2, 0x00, 0x00, 0xdf, 0x00, 0xa2, 0x41, 0x8d, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, - 0x25, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x89, 0xe0, 0x01, 0x00, - 0xdd, 0x00, 0x00, 0x44, 0x82, 0x14, 0x01, 0x00, 0x00, 0x00, 0x90, 0x94, - 0x8a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf0, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x89, 0xd0, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x44, 0x2b, 0x41, 0x01, 0x00, - 0xec, 0x00, 0x08, 0x41, 0x80, 0x32, 0x00, 0x00, 0xed, 0x00, 0x00, 0x94, - 0x24, 0xb1, 0x00, 0x00, 0x10, 0x00, 0x00, 0x94, 0x24, 0xf5, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x94, 0xf0, 0xb1, 0x01, 0x00, 0xf2, 0x00, 0xa0, 0x44, - 0x89, 0x50, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x44, 0x2b, 0x41, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x94, 0xf0, 0xb1, 0x01, 0x00, 0xef, 0x00, 0x20, 0x44, - 0x89, 0x50, 0x00, 0x00, 0x10, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x42, - 0x89, 0xd0, 0x00, 0x00, 0xf7, 0x00, 0xa0, 0xfa, 0x8a, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, 0xf5, 0x00, 0xa3, 0x42, - 0x89, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0x45, 0x88, 0x88, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x45, 0x8a, 0xf4, 0x01, 0x00, 0xfc, 0x00, 0x90, 0x44, - 0x8a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x45, 0x8a, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x50, - 0x8b, 0xe0, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, 0x25, 0x99, 0x01, 0x00, - 0x7c, 0x00, 0x00, 0x40, 0x2b, 0x99, 0x01, 0x00, 0x00, 0x30, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x08, 0x83, 0x14, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x94, 0x2a, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, - 0xf9, 0x9b, 0x01, 0x00, 0xdd, 0x00, 0x00, 0xfc, 0x19, 0x31, 0x01, 0x00, - 0x00, 0x00, 0x40, 0x94, 0x80, 0xb2, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x44, - 0x2b, 0x41, 0x01, 0x00, 0x00, 0x00, 0x41, 0x94, 0x80, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xf9, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x2b, 0xc1, 0x01, 0x00, 0x04, 0x01, 0x9f, 0x94, 0x80, 0x32, 0x00, 0x00, - 0x02, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x01, 0x00, 0x51, - 0x93, 0xb0, 0x00, 0x00, 0x10, 0x01, 0x00, 0x4d, 0x93, 0xb0, 0x00, 0x00, - 0x10, 0x01, 0x00, 0x49, 0x93, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x93, 0xb0, 0x01, 0x00, 0x10, 0x01, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x12, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x13, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x15, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x16, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x17, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x18, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x19, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x1b, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x1e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x70, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x71, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x72, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x73, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x74, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x75, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x76, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x77, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x78, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x79, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x7a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7b, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x7d, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7e, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa1, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x19, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x15, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0b, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x07, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x01, 0xb0, 0x01, 0x00, 0x3b, 0x01, 0x20, 0x48, 0xa1, 0x51, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x47, 0x01, 0x22, 0x4b, - 0x74, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x60, 0x00, 0x00, 0x4b, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1, - 0x7e, 0xb1, 0x01, 0x00, 0x48, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x45, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x05, 0x00, 0x80, 0x40, - 0x97, 0x98, 0x01, 0x00, 0x18, 0x00, 0x00, 0xaa, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x43, 0x97, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0xaa, - 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x58, 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, - 0xd8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x07, 0x90, 0x01, 0x00, - 0xd8, 0x9f, 0x00, 0x40, 0xbf, 0xb3, 0x00, 0x00, 0x5a, 0x01, 0x22, 0xcc, - 0x85, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x07, 0x90, 0x01, 0x00, - 0xd8, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, - 0xd0, 0x14, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe1, 0xb1, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, - 0x62, 0xdd, 0x01, 0x00, 0x63, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xcc, 0x85, 0x93, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, - 0xa4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbc, 0xb3, 0x01, 0x00, - 0x00, 0x14, 0x2f, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe7, - 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00, - 0xff, 0x00, 0x00, 0xdd, 0x81, 0x88, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, - 0x80, 0xf4, 0x01, 0x00, 0x73, 0x01, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00, - 0x86, 0x01, 0x00, 0xdd, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x10, 0xb1, 0x00, 0x00, 0x87, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x88, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x89, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x8b, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xc4, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x82, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x83, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, 0xb8, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x28, 0x00, 0xd4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, - 0xd5, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, 0xd6, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x28, 0x00, 0xd7, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, - 0x72, 0x01, 0x00, 0x41, 0x81, 0xc0, 0x28, 0x00, 0x55, 0x01, 0x51, 0x49, - 0xfd, 0x93, 0x28, 0x00, 0x55, 0x01, 0x52, 0x4a, 0xfd, 0x93, 0x2a, 0x00, - 0x55, 0x01, 0x55, 0x49, 0xfd, 0x83, 0x2a, 0x00, 0x55, 0x01, 0x56, 0x4a, - 0xfd, 0x83, 0x2a, 0x00, 0x50, 0x01, 0x91, 0x81, 0x80, 0x30, 0x2a, 0x00, - 0x55, 0x01, 0x45, 0x40, 0x81, 0xb2, 0x2a, 0x00, 0x50, 0x01, 0x91, 0x82, - 0x80, 0x30, 0x2a, 0x00, 0x55, 0x01, 0x46, 0x40, 0x81, 0xb2, 0x2a, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x89, 0xb0, 0x2b, 0x00, 0x00, 0x00, 0x2f, 0x40, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, - 0xb3, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, - 0x92, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x49, 0xd1, 0x01, 0x00, 0x9a, 0x01, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00, - 0x96, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x50, 0x01, 0x00, 0x41, - 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xbf, 0xb3, 0x01, 0x00, - 0x50, 0x01, 0xa0, 0x0f, 0xbd, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00, - 0xb5, 0x01, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x42, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, 0x85, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xde, 0x19, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x42, 0xff, - 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, 0xe1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x2f, 0xff, - 0xe1, 0xb1, 0x01, 0x00, 0x08, 0x14, 0x00, 0xa4, 0x80, 0xcc, 0x01, 0x00, - 0xaa, 0x01, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x85, 0xc0, 0x01, 0x00, 0xa8, 0x01, 0xa2, 0x4c, 0x81, 0x50, 0x00, 0x00, - 0xb4, 0x01, 0x22, 0xd2, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x01, 0x22, 0x41, - 0xa5, 0x6f, 0x00, 0x00, 0x50, 0x01, 0xa2, 0xe0, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x89, 0x90, 0x01, 0x00, 0x00, 0x00, 0x40, 0x42, 0x80, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x41, 0x43, 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x88, 0x94, 0x01, 0x00, 0x55, 0x01, 0x00, 0x44, 0xe0, 0xb1, 0x00, 0x00, - 0xb1, 0x01, 0x00, 0x48, 0x49, 0xc1, 0x00, 0x00, 0xaf, 0x01, 0x00, 0x5b, - 0x89, 0x90, 0x00, 0x00, 0xa8, 0x9f, 0x00, 0xa0, 0x9e, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40, - 0x49, 0x99, 0x01, 0x00, 0x00, 0x00, 0x23, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0xbe, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, - 0xb9, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x50, 0x01, 0x00, 0x43, - 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x40, 0xf8, 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xf0, - 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x55, 0x01, 0x00, 0x40, - 0xe1, 0xb1, 0x00, 0x00, 0xc6, 0x01, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x91, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0xcb, 0x01, 0x00, 0x40, - 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00, - 0xd1, 0x01, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0x53, 0x01, 0x00, 0xde, - 0xa1, 0xb3, 0x00, 0x00, 0xe3, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xe5, 0x01, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0xeb, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x52, 0x01, 0x00, 0xdf, 0xe1, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, - 0xa1, 0xb1, 0x01, 0x00, 0x02, 0x00, 0x00, 0xd2, 0xa5, 0xe7, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb1, 0x01, 0x00, 0xdb, 0x01, 0x22, 0x44, 0xc1, 0x53, 0x00, 0x00, - 0xda, 0x01, 0x84, 0x41, 0x81, 0x40, 0x00, 0x00, 0xde, 0x01, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x45, 0xb1, 0x01, 0x00, - 0xd5, 0x01, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00, 0xda, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x55, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00, - 0xda, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x00, 0xd3, - 0xa7, 0xcb, 0x01, 0x00, 0xf8, 0x02, 0x00, 0xe0, 0xa5, 0xb3, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, 0x53, 0x01, 0x00, 0xde, - 0xa1, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xbf, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xde, 0x81, 0x90, 0x01, 0x00, 0x50, 0x01, 0xa2, 0xba, - 0x80, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00, 0xde, 0x61, 0x99, 0x01, 0x00, - 0xe8, 0x01, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x52, 0x01, 0x00, 0x40, - 0xe0, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00, - 0x6b, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x4d, - 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe1, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xe3, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xe5, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe9, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xeb, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xf5, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf7, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xf9, 0xb3, 0x01, 0x00, 0xf9, 0x01, 0x22, 0x40, - 0x8f, 0x6f, 0x00, 0x00, 0x78, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0x60, 0x02, 0x00, 0xc7, 0x83, 0x30, 0x01, 0x00, 0x80, 0x02, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x42, 0x83, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xe8, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xea, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x85, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xec, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xed, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb2, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xac, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xb9, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xba, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xf0, 0xb1, 0x01, 0x00, - 0x0c, 0x02, 0xb8, 0x40, 0x81, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0x90, 0x01, 0x00, 0x0e, 0x02, 0xb9, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0x90, 0x01, 0x00, 0x10, 0x02, 0xba, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x81, 0x90, 0x01, 0x00, - 0x12, 0x02, 0xbb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x81, 0x90, 0x01, 0x00, 0x14, 0x02, 0xbc, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x81, 0x90, 0x01, 0x00, 0x16, 0x02, 0xbd, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x81, 0x90, 0x01, 0x00, - 0x18, 0x02, 0xbe, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x81, 0x90, 0x01, 0x00, 0x1a, 0x02, 0xbf, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x81, 0x90, 0x01, 0x00, 0x1c, 0x02, 0xc8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0x90, 0x01, 0x00, - 0x1e, 0x02, 0xc9, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x81, 0x90, 0x01, 0x00, 0x20, 0x02, 0xca, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x81, 0x90, 0x01, 0x00, 0x22, 0x02, 0xcb, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x81, 0x90, 0x01, 0x00, - 0x24, 0x02, 0xcc, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x81, 0x90, 0x01, 0x00, 0x26, 0x02, 0xcd, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4d, 0x81, 0x90, 0x01, 0x00, 0x28, 0x02, 0xce, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0x90, 0x01, 0x00, - 0x2a, 0x02, 0xcf, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x81, 0x90, 0x01, 0x00, 0x2c, 0x02, 0xf0, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x81, 0x90, 0x01, 0x00, 0x2e, 0x02, 0xf1, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x81, 0x90, 0x01, 0x00, - 0x30, 0x02, 0xf2, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, - 0x81, 0x90, 0x01, 0x00, 0x32, 0x02, 0xf3, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x53, 0x81, 0x90, 0x01, 0x00, 0x34, 0x02, 0xf4, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x81, 0x90, 0x01, 0x00, - 0x36, 0x02, 0xf5, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x81, 0x90, 0x01, 0x00, 0x38, 0x02, 0xf6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x56, 0x81, 0x90, 0x01, 0x00, 0x3a, 0x02, 0xf7, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x81, 0x90, 0x01, 0x00, - 0x3c, 0x02, 0xf8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, - 0x81, 0x90, 0x01, 0x00, 0x3e, 0x02, 0xf9, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x59, 0x81, 0x90, 0x01, 0x00, 0x40, 0x02, 0xfa, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x81, 0x90, 0x01, 0x00, - 0x42, 0x02, 0xfb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x81, 0x90, 0x01, 0x00, 0x44, 0x02, 0xfc, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x81, 0x90, 0x01, 0x00, 0x46, 0x02, 0xfd, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x81, 0x90, 0x01, 0x00, - 0x48, 0x02, 0xfe, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, - 0x81, 0x90, 0x01, 0x00, 0x4a, 0x02, 0xff, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00, - 0xd8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x06, 0xa5, 0xb3, 0x01, 0x00, - 0x40, 0x00, 0x00, 0xd3, 0xa7, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf1, 0xb1, 0x01, 0x00, - 0xdb, 0x01, 0x00, 0xc7, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x66, 0x02, 0x00, 0x48, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x51, 0x40, 0x1a, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x63, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x5f, 0x02, 0x49, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40, 0x1c, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x4e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x68, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x5f, 0x02, 0x4a, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, - 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xd8, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa1, 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, - 0xd2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xd4, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, - 0xdc, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xde, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x88, 0xda, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, - 0x8e, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xe6, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xac, 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x99, - 0xfa, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe0, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd5, 0xe2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, - 0xe4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe8, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd5, 0xea, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, - 0xf4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xf6, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd5, 0xf8, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc7, - 0xa9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00, - 0x84, 0x02, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x91, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0x88, 0x02, 0x00, 0x40, - 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00, - 0x8d, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x98, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x98, 0x02, 0x00, 0x46, 0xa3, 0xb3, 0x00, 0x00, - 0x9b, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa1, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x02, 0x23, 0x50, 0xa5, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xa5, 0xb3, 0x01, 0x00, 0xe8, 0x02, 0x00, 0x42, - 0xa5, 0x63, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0xa1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0x97, 0x02, 0x22, 0x44, - 0xa5, 0x53, 0x00, 0x00, 0x94, 0x02, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00, - 0x55, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0xe8, 0x02, 0x00, 0xde, - 0xa1, 0x33, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0xbf, 0xb3, 0x01, 0x00, 0x50, 0x01, 0xa2, 0xd2, 0x77, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, - 0x63, 0xb1, 0x01, 0x00, 0x9e, 0x02, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x54, - 0xa5, 0x33, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd2, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xd4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0xb1, 0x01, 0x00, - 0xac, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x46, - 0x83, 0x30, 0x01, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa0, 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe8, - 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x45, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xea, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xeb, - 0xa1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd0, 0x14, 0x2e, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, - 0xa3, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc1, 0xb3, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0xbd, 0x02, 0x00, 0x40, - 0x10, 0xc9, 0x00, 0x00, 0xc3, 0x02, 0x00, 0x05, 0x81, 0xb0, 0x00, 0x00, - 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xcb, 0x02, 0x00, 0x05, - 0x81, 0xb0, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd0, 0x02, 0x00, 0x44, 0xa5, 0xb3, 0x00, 0x00, 0xd2, 0x02, 0x00, 0x44, - 0xa5, 0xb3, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0xa4, 0xe7, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xe0, 0x81, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0xc1, - 0xf0, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x22, 0x41, 0x81, 0x50, 0x00, 0x00, - 0xc4, 0x02, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00, 0xda, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, - 0xa4, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x91, 0xb1, 0x01, 0x00, - 0xff, 0xff, 0x00, 0xc9, 0xf0, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x22, 0x41, - 0x81, 0x50, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00, - 0xff, 0xff, 0x00, 0xde, 0x85, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x00, 0xc2, - 0xe0, 0xb1, 0x00, 0x00, 0xff, 0xff, 0x00, 0xde, 0x95, 0x89, 0x01, 0x00, - 0xc8, 0x02, 0x00, 0xca, 0xe0, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd4, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, 0xe2, 0x02, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x93, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, - 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, - 0xf1, 0xb1, 0x01, 0x00, 0xe1, 0x02, 0x00, 0xd4, 0xe1, 0xb1, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xcc, - 0x85, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00, - 0xfa, 0x02, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0xf9, 0x02, 0xa2, 0xf2, - 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x83, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x41, - 0x99, 0xb3, 0x01, 0x00, 0x0a, 0x03, 0x22, 0x44, 0x81, 0x6c, 0x00, 0x00, - 0x12, 0x03, 0x22, 0x48, 0x81, 0x6c, 0x00, 0x00, 0x0c, 0x03, 0x22, 0x4c, - 0x81, 0x6c, 0x00, 0x00, 0x16, 0x03, 0x22, 0x50, 0x81, 0x6c, 0x00, 0x00, - 0x17, 0x03, 0x22, 0x54, 0x81, 0x6c, 0x00, 0x00, 0x19, 0x03, 0x22, 0x58, - 0x81, 0x6c, 0x00, 0x00, 0x1e, 0x03, 0x22, 0x5c, 0x81, 0x6c, 0x00, 0x00, - 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, - 0x09, 0xb0, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0xca, 0x01, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xf3, 0x83, 0x01, 0x00, 0x10, 0x03, 0xa2, 0x42, 0x05, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x05, 0xb0, 0x01, 0x00, 0xdd, 0x9f, 0x22, 0xca, - 0x07, 0x14, 0x00, 0x00, 0xdd, 0x9f, 0x00, 0x45, 0xf3, 0x93, 0x00, 0x00, - 0xdd, 0x9f, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00, 0xdd, 0x9f, 0x80, 0xca, - 0x05, 0x30, 0x00, 0x00, 0xdd, 0x9f, 0x22, 0x01, 0x80, 0x30, 0x00, 0x00, - 0xdd, 0x9f, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00, 0x57, 0x01, 0x00, 0xbc, - 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xb1, 0xb3, 0x01, 0x00, - 0xdd, 0x9f, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xca, - 0x81, 0x88, 0x01, 0x00, 0xdd, 0x9f, 0xa2, 0x40, 0x74, 0x7d, 0x00, 0x00, - 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00, 0x1b, 0x03, 0xa8, 0xb1, - 0x82, 0x30, 0x00, 0x00, 0x1a, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xdd, 0x9f, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x22, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x2d, 0x03, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x8a, 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, - 0x80, 0xce, 0x01, 0x00, 0x2b, 0x03, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x2d, 0x03, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, - 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, - 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xcd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x32, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x3d, 0x03, 0x91, 0x81, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, - 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, - 0x3b, 0x03, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3d, 0x03, 0x55, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00, 0xb5, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, - 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0xc4, 0x14, 0x2f, 0x40, 0x99, 0xb3, 0x01, 0x00, - 0x57, 0x01, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x30, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x90, 0x00, 0xf8, - 0x80, 0x98, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf2, 0x88, 0xe4, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x23, 0x91, 0x01, 0x00, 0x4d, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x23, 0x91, 0x01, 0x00, 0x50, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x23, 0x91, 0x01, 0x00, 0x53, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0x55, 0x03, 0x1f, 0x91, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x08, 0x80, 0x40, 0x20, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x48, 0x84, 0x84, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x8f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x62, 0xb1, 0x01, 0x00, - 0x5a, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x08, 0x00, 0x47, - 0x8e, 0xc8, 0x01, 0x00, 0x58, 0x03, 0x00, 0x5c, 0x8f, 0x80, 0x00, 0x00, - 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x58, 0x15, 0x2d, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x81, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x45, 0x82, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x82, 0x94, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x41, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x8d, 0xc0, 0x01, 0x00, 0x74, 0x03, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00, - 0x65, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x63, 0x03, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x86, 0xb0, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x43, 0x86, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0xa6, 0x41, 0x85, 0x50, 0x01, 0x00, 0x70, 0x03, 0x00, 0x41, - 0x83, 0xe0, 0x00, 0x00, 0x6e, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x85, 0xe0, 0x01, 0x00, 0xd0, 0x14, 0x2f, 0x46, - 0x84, 0x94, 0x01, 0x00, 0x20, 0x00, 0x00, 0x42, 0x60, 0x99, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x07, 0x00, 0x00, 0x45, 0x80, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x85, 0x03, 0xa0, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x83, 0x03, 0x00, 0x41, 0x82, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, - 0x8e, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0x00, 0x39, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x8b, 0x03, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x44, - 0x82, 0xf4, 0x01, 0x00, 0x1a, 0x15, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, - 0x70, 0x15, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x08, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x39, 0x00, 0x40, 0xe1, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x70, 0x15, 0x00, 0x43, 0x62, 0x99, 0x01, 0x00, - 0x95, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x97, 0x03, 0x22, 0x5a, - 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x98, 0x03, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x00, 0x08, 0x00, 0x42, - 0x84, 0xc8, 0x01, 0x00, 0x90, 0x03, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x58, 0x15, 0x2d, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x8f, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, - 0x90, 0xb0, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x48, 0x90, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, - 0x8a, 0xb0, 0x01, 0x00, 0x80, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x02, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, 0xac, 0x03, 0x22, 0x40, - 0x82, 0x6c, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x58, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x8d, 0xc0, 0x01, 0x00, 0xb5, 0x03, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00, - 0xa7, 0x03, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00, 0xa5, 0x03, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xff, 0x07, 0x00, 0x47, 0x84, 0x88, 0x01, 0x00, - 0x00, 0x00, 0xa6, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xed, 0x9f, 0x00, 0x47, - 0x80, 0x30, 0x01, 0x00, 0x00, 0x02, 0x00, 0x47, 0x8e, 0xc8, 0x01, 0x00, - 0xb0, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x50, 0xb3, 0x01, 0x00, 0xbb, 0x03, 0x20, 0x18, 0x89, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00, - 0xbe, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa6, - 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, - 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x50, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x4f, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x4e, 0xd3, 0x01, 0x00, 0x6e, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x82, 0x03, 0x00, 0x42, 0x80, 0x30, 0x01, 0x00, - 0xb0, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc7, 0x03, 0x22, 0xa7, - 0x8f, 0x6c, 0x00, 0x00, 0x5a, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xc4, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xee, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xa0, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xca, - 0xa7, 0x33, 0x01, 0x00, 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x03, 0x22, 0x42, - 0x75, 0x6f, 0x00, 0x00, 0xd8, 0x03, 0x22, 0x41, 0x75, 0x6f, 0x00, 0x00, - 0xda, 0x03, 0x1e, 0xca, 0x81, 0x32, 0x00, 0x00, 0xdc, 0x03, 0x1f, 0xca, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xc9, 0xb1, 0x01, 0x00, - 0xdd, 0x9f, 0x00, 0x42, 0x75, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xcd, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x41, 0x75, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xcf, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x40, - 0x75, 0xb3, 0x00, 0x00, 0x00, 0x81, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00, - 0xdd, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6, - 0xc6, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x40, 0x75, 0xb3, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x45, 0x01, 0x00, 0x4d, 0x93, 0x30, 0x01, 0x00, - 0x45, 0x01, 0x00, 0x4e, 0x93, 0x30, 0x01, 0x00, 0x45, 0x01, 0x00, 0x4c, - 0x93, 0x30, 0x01, 0x00, 0xec, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xdd, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x54, 0x95, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0xca, 0xe5, 0xb1, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xcc, 0x14, 0x2e, 0x40, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, - 0xa0, 0xb3, 0x01, 0x00, 0x15, 0x04, 0x00, 0x43, 0xb2, 0x33, 0x01, 0x00, - 0x00, 0x00, 0x68, 0xda, 0x89, 0xb0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40, - 0x8b, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x89, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x89, 0xd0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x44, - 0x88, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x87, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xa5, 0xb3, 0x01, 0x00, 0x15, 0x04, 0x00, 0x43, - 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xa5, 0xc3, 0x01, 0x00, 0x0b, 0x04, 0x22, 0x44, 0x89, 0x50, 0x00, 0x00, - 0x0b, 0x04, 0x22, 0x44, 0x8b, 0x50, 0x00, 0x00, 0xfa, 0x03, 0xa2, 0x50, - 0xa5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb, - 0x85, 0x30, 0x01, 0x00, 0xcc, 0x14, 0x2e, 0xd2, 0x95, 0xc3, 0x01, 0x00, - 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00, - 0x08, 0x04, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x07, 0x04, 0xa2, 0xf2, - 0x80, 0x30, 0x00, 0x00, 0xfa, 0x03, 0x00, 0x40, 0xa5, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb, 0x85, 0x30, 0x01, 0x00, - 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00, - 0x00, 0x10, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xdb, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xff, 0xff, 0x00, 0x94, 0xb4, 0x8b, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd9, - 0x2b, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0xdd, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x94, - 0xb4, 0xb3, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0x27, 0xb1, 0x01, 0x00, 0x06, 0xc0, 0x00, 0x40, 0x2d, 0x99, 0x01, 0x00, - 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x02, 0xc4, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, - 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x40, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x05, 0x82, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, - 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2d, 0x04, 0x80, 0x94, - 0x80, 0x32, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x28, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x40, - 0x2d, 0x99, 0x01, 0x00, 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x31, 0x04, 0x00, 0x12, - 0x10, 0xc9, 0x00, 0x00, 0x00, 0x48, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0xc0, 0x49, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x4b, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x40, 0x4d, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x4f, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x50, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x80, 0x52, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x40, 0x54, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x56, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x57, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x80, 0x59, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x5b, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x5d, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0xc0, 0x5e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x60, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x40, 0x62, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x64, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x65, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x80, 0x67, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x40, 0x69, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x6b, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x6c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x80, 0x6e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x70, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x72, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0xc0, 0x73, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x75, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x40, 0x77, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x79, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x7a, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x80, 0x7c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x40, 0x7e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x59, 0x04, 0x00, 0x12, 0x10, 0xc9, 0x00, 0x00, - 0x00, 0x80, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x82, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x84, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x86, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x88, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x8a, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x8c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x8e, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x90, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x92, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x94, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x96, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x98, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x9a, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x9c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x9e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa0, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa2, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xa4, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa6, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa8, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xaa, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xac, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xae, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xb0, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb2, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb4, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xb6, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb8, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xba, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xbc, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xbe, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x80, 0xb1, 0x01, 0x00, - 0x01, 0x00, 0x00, 0xa6, 0x82, 0xb1, 0x01, 0x00, 0x82, 0x04, 0x85, 0x41, - 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00, - 0x87, 0x04, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x90, 0x04, 0x60, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0xb1, 0x01, 0x00, - 0xff, 0xff, 0xf0, 0x4b, 0x82, 0x89, 0x01, 0x00, 0x93, 0x04, 0x60, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x80, 0xb1, 0x01, 0x00, - 0x01, 0x00, 0xf0, 0xa6, 0x82, 0xb1, 0x01, 0x00, 0x96, 0x04, 0x60, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00, - 0x00, 0x00, 0xf0, 0xc2, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x80, 0x4b, 0x92, 0x89, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x80, 0xa6, - 0x92, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x94, 0x89, 0x01, 0x00, - 0x00, 0x00, 0x80, 0xca, 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x88, 0x94, 0x01, 0x00, 0xa6, 0x04, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xad, 0x04, 0x22, 0x20, 0x87, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xa6, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0x80, 0x86, 0xb3, 0x01, 0x00, 0xb0, 0x04, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x62, 0xb1, 0x01, 0x00, 0xb1, 0x04, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xb8, 0x04, 0x22, 0x4b, 0x89, 0x7c, 0x00, 0x00, 0xb6, 0x04, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0xb6, 0x04, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x87, 0xb3, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x99, 0xb0, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xc1, 0x04, 0xa8, 0xb1, 0x52, 0x33, 0x00, 0x00, 0xc6, 0x04, 0x22, 0x4b, - 0x53, 0x7f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xc4, 0x04, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xc1, 0x04, 0xa2, 0x41, - 0x99, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x4f, 0x77, 0xfd, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x99, 0xe0, 0x01, 0x00, 0xd6, 0x04, 0x00, 0x4c, - 0x88, 0x94, 0x00, 0x00, 0xd6, 0x04, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xdd, 0x04, 0x22, 0x20, 0x87, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xd6, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0x80, 0x86, 0xb3, 0x01, 0x00, 0xe0, 0x04, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x62, 0xb1, 0x01, 0x00, 0xe1, 0x04, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xe8, 0x04, 0x22, 0x4a, 0x89, 0x7c, 0x00, 0x00, 0xe6, 0x04, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0xe6, 0x04, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x87, 0xb3, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x99, 0xb0, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xf1, 0x04, 0xa8, 0xb1, 0x52, 0x33, 0x00, 0x00, 0xf6, 0x04, 0x22, 0x4a, - 0x53, 0x7f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xf4, 0x04, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xf1, 0x04, 0xa2, 0x41, - 0x99, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x4f, 0x77, 0xfd, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x00, 0x05, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x12, 0x05, 0x1d, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x40, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x10, 0x05, 0xa2, 0x40, - 0x86, 0x04, 0x00, 0x00, 0xde, 0x9f, 0x9c, 0x40, 0x80, 0x32, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x40, 0x88, 0x88, 0x01, 0x00, 0x30, 0x05, 0x00, 0x50, - 0x47, 0x31, 0x01, 0x00, 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00, - 0x0c, 0x05, 0x52, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x05, 0x00, 0x40, - 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xb0, 0x01, 0x00, - 0x30, 0x05, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00, 0x30, 0x05, 0x00, 0x05, - 0x47, 0x31, 0x01, 0x00, 0xde, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x1b, 0x00, 0xde, 0x9f, 0x00, 0x41, - 0xe1, 0xc1, 0x1a, 0x00, 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x1b, 0x00, - 0x19, 0x05, 0x22, 0x54, 0x81, 0x7c, 0x1a, 0x00, 0x14, 0x05, 0x42, 0x40, - 0x81, 0x32, 0x1a, 0x00, 0x00, 0x82, 0x00, 0xb3, 0x67, 0xdf, 0x1b, 0x00, - 0x00, 0x00, 0x1a, 0x44, 0x93, 0x93, 0x1b, 0x00, 0x28, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x1b, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, - 0x27, 0x05, 0x0f, 0x40, 0x80, 0x32, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x40, - 0x88, 0x88, 0x01, 0x00, 0x30, 0x05, 0x00, 0x50, 0x47, 0x31, 0x01, 0x00, - 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00, 0x1f, 0x05, 0x99, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0xd0, 0x01, 0x00, - 0x21, 0x05, 0x9b, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x89, 0xd0, 0x01, 0x00, 0x23, 0x05, 0x1f, 0x44, 0x80, 0x32, 0x00, 0x00, - 0x30, 0x05, 0x00, 0x40, 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x89, 0xb0, 0x01, 0x00, 0x30, 0x05, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00, - 0x30, 0x05, 0x00, 0x58, 0x47, 0x31, 0x01, 0x00, 0xde, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x86, 0xf4, 0x01, 0x00, - 0x6f, 0x00, 0x00, 0x43, 0x86, 0x88, 0x01, 0x00, 0xde, 0x9f, 0x26, 0x05, - 0x47, 0x31, 0x00, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, - 0xde, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x44, 0xf0, 0x41, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41, - 0xe1, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x07, - 0x91, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x97, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x05, 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x44, 0x05, 0xa2, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0x45, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00, 0x10, 0x04, 0x00, 0x42, - 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xf5, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, - 0xf7, 0xf5, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0x91, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x8f, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x48, - 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x91, 0xc0, 0x01, 0x00, 0x50, 0x05, 0xa2, 0x41, 0x8f, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x45, 0xd1, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0x91, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xda, - 0x8f, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xfd, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0xda, - 0xfd, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x7a, 0x05, 0x22, 0x45, 0xfd, 0x7f, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0xdb, 0x9f, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x15, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x78, 0x05, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00, - 0x7d, 0x05, 0x22, 0x20, 0xb5, 0x6f, 0x00, 0x00, 0x7a, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x1f, 0x00, - 0x7d, 0x05, 0x22, 0x40, 0x97, 0x6c, 0x1e, 0x00, 0x7a, 0x05, 0x42, 0x40, - 0x81, 0x32, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x67, 0x93, 0x1f, 0x00, - 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x1e, 0x00, 0x54, 0x16, 0x00, 0x40, - 0x47, 0x99, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x1f, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, - 0x46, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, - 0x48, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x97, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x4a, 0xb2, 0x33, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, - 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x95, 0xc0, 0x01, 0x00, - 0x90, 0x05, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x40, - 0xa5, 0x9b, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb, - 0x85, 0x30, 0x01, 0x00, 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb8, 0x05, 0x22, 0x45, 0xfd, 0x7f, 0x00, 0x00, 0xe0, 0x15, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x1a, 0x00, 0x00, 0xa2, 0x80, 0xdc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, - 0x62, 0xdd, 0x01, 0x00, 0xa7, 0x05, 0xa8, 0xbb, 0xe1, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0xaa, 0x05, 0xa2, 0x41, - 0x83, 0x50, 0x00, 0x00, 0xa9, 0x05, 0xa2, 0xf2, 0x82, 0x30, 0x00, 0x00, - 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb0, 0x05, 0xa2, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0xb1, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x05, 0xa2, 0xfa, - 0xb4, 0x6f, 0x00, 0x00, 0x10, 0x04, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, - 0xb8, 0x05, 0xa2, 0xfa, 0xb4, 0x6f, 0x00, 0x00, 0x10, 0x04, 0x00, 0x42, - 0xb3, 0x43, 0x01, 0x00, 0xbb, 0x05, 0x22, 0xfa, 0xb4, 0x6f, 0x00, 0x00, - 0xb8, 0x05, 0x42, 0x40, 0x81, 0x32, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0x67, 0x93, 0x21, 0x00, 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x20, 0x00, - 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x21, 0x00, 0xdb, 0x9f, 0x00, 0x40, - 0x49, 0x31, 0x21, 0x00, 0xf6, 0x15, 0x00, 0x40, 0x43, 0x99, 0x21, 0x00, - 0x5c, 0x16, 0x00, 0x40, 0x45, 0x99, 0x21, 0x00, 0x00, 0x00, 0x6e, 0xfa, - 0x8e, 0xb0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xb4, 0xb3, 0x01, 0x00, 0xc9, 0x05, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00, - 0xfc, 0x15, 0x20, 0x20, 0xe1, 0xb1, 0x01, 0x00, 0xce, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x24, 0x00, 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x25, 0x00, - 0xce, 0x05, 0x22, 0x40, 0x97, 0x6c, 0x24, 0x00, 0xcb, 0x05, 0x42, 0x40, - 0x81, 0x32, 0x24, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x67, 0x93, 0x25, 0x00, - 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x24, 0x00, 0x38, 0x05, 0x00, 0x40, - 0x81, 0x32, 0x25, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x25, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd3, 0x05, 0x22, 0x50, - 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x91, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xf8, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfa, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x94, 0xb0, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x4a, 0xb4, 0x8b, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x4a, 0xb4, 0xf7, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xe9, 0x05, 0x22, 0x50, 0xb5, 0x6f, 0x00, 0x00, - 0xea, 0x05, 0x00, 0x50, 0xb5, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xb5, 0xb3, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x30, 0x31, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x32, 0x33, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x34, 0x35, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x36, 0x37, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x38, 0x39, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x41, 0x42, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x43, 0x44, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x45, 0x46, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x47, 0x48, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x49, 0x4a, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00, - 0xfc, 0x05, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x80, 0x16, 0x2e, 0x06, - 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0xff, 0x05, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00, - 0x02, 0x06, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40, - 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0x08, 0x06, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00, - 0x14, 0x06, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x45, 0x67, 0x00, 0xa6, 0xe0, 0xb2, 0x01, 0x00, 0x01, 0x23, 0x00, 0x70, - 0xe1, 0x9a, 0x01, 0x00, 0xcd, 0xef, 0x00, 0xa6, 0xe2, 0xb2, 0x01, 0x00, - 0x89, 0xab, 0x00, 0x71, 0xe3, 0x9a, 0x01, 0x00, 0xba, 0x98, 0x00, 0xa6, - 0xe4, 0xb2, 0x01, 0x00, 0xfe, 0xdc, 0x00, 0x72, 0xe5, 0x9a, 0x01, 0x00, - 0x32, 0x10, 0x00, 0xa6, 0xe6, 0xb2, 0x01, 0x00, 0x76, 0x54, 0x00, 0x73, - 0xe7, 0x9a, 0x01, 0x00, 0xd2, 0xc3, 0x00, 0xa6, 0xe8, 0xb2, 0x01, 0x00, - 0xf0, 0xe1, 0x00, 0x74, 0xe9, 0x9a, 0x01, 0x00, 0x80, 0x16, 0x00, 0x4a, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf7, 0xb1, 0x01, 0x00, 0x25, 0x06, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x80, 0x16, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0xfc, 0x16, 0x2a, 0x47, - 0xe7, 0xb5, 0x01, 0x00, 0x03, 0x00, 0x00, 0x4a, 0xe8, 0xe5, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, - 0xa3, 0x99, 0x01, 0x00, 0x80, 0x16, 0x3d, 0x46, 0x8d, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x40, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, - 0x2e, 0x06, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xeb, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xed, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x72, 0xef, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73, - 0xf1, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf3, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x41, - 0x80, 0x88, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, 0xa2, 0xc9, 0x01, 0x00, - 0x4b, 0x06, 0xa0, 0x50, 0x83, 0x6c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x40, - 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00, - 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x86, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c, - 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, - 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0xa4, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x20, 0x88, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x41, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x94, 0x01, 0x00, - 0x05, 0x00, 0x00, 0x75, 0x89, 0xe4, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x75, - 0x85, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x84, 0x94, 0x01, 0x00, - 0x55, 0x06, 0xa3, 0x53, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x76, 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x8b, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00, - 0x64, 0x06, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41, - 0x80, 0xce, 0x01, 0x00, 0x5a, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, - 0x89, 0xa4, 0x01, 0x00, 0x64, 0x06, 0x00, 0x78, 0x89, 0xa4, 0x00, 0x00, - 0x3b, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, 0x57, 0x06, 0xaa, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76, - 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x88, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, - 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00, - 0x64, 0x06, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x84, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x85, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x84, 0xc0, 0x01, 0x00, 0x6b, 0x06, 0xa3, 0x53, - 0x83, 0x6c, 0x00, 0x00, 0x82, 0x5a, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, - 0x99, 0x79, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, - 0x70, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd9, 0x6e, 0x00, 0xa6, - 0x84, 0xc0, 0x01, 0x00, 0xa1, 0xeb, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, - 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x41, - 0x80, 0xce, 0x01, 0x00, 0x75, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x8f, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xdc, 0xbc, 0x00, 0x42, - 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x62, 0xca, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xd6, 0xc1, 0x00, 0x42, - 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x78, 0xf3, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, - 0xf1, 0xb2, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x76, 0x89, 0xe4, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x76, 0xef, 0xf6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xee, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x75, 0xed, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xea, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x83, 0xc0, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, - 0x37, 0x06, 0x2a, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, - 0xe1, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76, 0xe3, 0xc2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x77, 0xe5, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, - 0xe7, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0xe9, 0xc2, 0x01, 0x00, - 0x2b, 0x06, 0x81, 0x41, 0x8d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xfd, 0x93, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0xdb, 0x9f, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x15, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xb9, 0x06, 0x22, 0x40, 0x8f, 0x6c, 0x00, 0x00, - 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb9, 0x06, 0xa2, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x5e, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x7c, 0x16, 0x20, 0xf6, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x31, 0xb3, 0x01, 0x00, 0x9d, 0x06, 0x22, 0x4f, 0x8f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x51, 0xfd, 0x93, 0x01, 0x00, 0x9f, 0x06, 0x22, 0x40, - 0x8f, 0x7c, 0x00, 0x00, 0xa3, 0x06, 0x00, 0x54, 0xfd, 0x93, 0x00, 0x00, - 0xa1, 0x06, 0x22, 0x42, 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, - 0xfd, 0x93, 0x01, 0x00, 0xa3, 0x06, 0x22, 0x41, 0x8f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x53, 0xfd, 0x93, 0x01, 0x00, 0xb7, 0x06, 0x22, 0x51, - 0xfd, 0x7f, 0x00, 0x00, 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0c, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xb2, 0x06, 0xa2, 0x40, 0xb5, 0x6f, 0x00, 0x00, - 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x48, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97, 0xc0, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x4b, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, 0xb5, 0xb3, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xb6, 0x06, 0x22, 0x40, 0xb5, 0x6f, 0x00, 0x00, 0xba, 0x06, 0x00, 0x54, - 0xfd, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00, - 0x1c, 0x00, 0x00, 0xfe, 0x7f, 0xd9, 0x01, 0x00, 0xba, 0x06, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xfd, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xe7, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc4, 0x06, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xe9, 0x9f, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x3c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x34, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x32, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x0a, 0xc8, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, - 0x0c, 0xc8, 0x01, 0x00, 0xea, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x0a, 0x07, 0x22, 0x01, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0xd9, 0x06, 0xa3, 0x07, 0x02, 0x6c, 0x00, 0x00, - 0xda, 0x06, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x07, - 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, 0xec, 0x06, 0x22, 0x40, - 0x03, 0x6c, 0x00, 0x00, 0xe6, 0x06, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x23, 0x07, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe3, 0x06, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0xe8, 0x06, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, - 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x23, 0x07, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0xee, 0x06, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, - 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x22, 0x00, 0x00, 0x19, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, - 0x0f, 0x00, 0x00, 0xf2, 0x3a, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x3b, 0xe0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00, 0xfa, 0x06, 0x23, 0x1a, - 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0xc0, 0x01, 0x00, - 0x23, 0x07, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x1d, - 0x48, 0xc1, 0x01, 0x00, 0xf0, 0x00, 0x00, 0xf2, 0x30, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x31, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x02, 0xc0, 0x01, 0x00, 0x02, 0x07, 0x22, 0x1a, - 0x02, 0x50, 0x00, 0x00, 0x23, 0x07, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x19, 0x48, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x14, - 0x48, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x14, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1d, 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x24, 0xb0, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x17, 0x10, 0xc8, 0x01, 0x00, 0x23, 0x07, 0x00, 0x1a, - 0x10, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0x0f, 0x07, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00, - 0x10, 0x07, 0x60, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x60, 0x12, - 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x0d, 0x16, 0x94, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x17, 0x07, 0xa8, 0x5c, - 0x1f, 0x10, 0x00, 0x00, 0x40, 0x07, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, - 0x40, 0x07, 0x22, 0x0d, 0x24, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x10, 0xc0, 0x01, 0x00, 0x1e, 0x07, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, - 0x23, 0x07, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x1f, 0x07, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x3f, 0x07, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00, 0x2e, 0x07, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x2c, 0x07, 0x22, 0xf2, - 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x29, 0x07, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x04, 0xb0, 0x01, 0x00, 0x33, 0x07, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00, - 0xd3, 0x06, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f, - 0x0f, 0x80, 0x01, 0x00, 0xd3, 0x06, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x3c, 0x07, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0xd3, 0x06, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0xd3, 0x06, 0x00, 0x0d, - 0x18, 0xc0, 0x00, 0x00, 0x5f, 0x07, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x19, 0x0a, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, - 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, - 0x02, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0x0d, 0x00, 0x2d, 0x1d, 0x48, 0xc1, 0x01, 0x00, - 0x09, 0x00, 0x00, 0xf3, 0x38, 0x88, 0x01, 0x00, 0x0d, 0x00, 0x20, 0x50, - 0xe7, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0x40, 0x3f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf4, 0x32, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x1d, - 0x94, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00, - 0x52, 0x07, 0xa0, 0xfc, 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x91, 0xc0, 0x01, 0x00, 0x50, 0x07, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0x96, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x18, 0x94, 0xf4, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x18, 0x90, 0xb0, 0x01, 0x00, 0x5c, 0x07, 0xa0, 0xfc, - 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00, - 0x5a, 0x07, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x80, 0xb0, 0x2d, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xb0, 0x2d, 0x00, - 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x48, 0xc1, 0x2d, 0x00, 0x64, 0x07, 0x43, 0x30, 0x3d, 0x07, 0x2c, 0x00, - 0x00, 0x00, 0x00, 0x9e, 0x85, 0xb0, 0x2d, 0x00, 0x00, 0x00, 0x1b, 0x41, - 0x3d, 0xc3, 0x2d, 0x00, 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x2d, 0x00, - 0x00, 0x00, 0x00, 0x1e, 0x82, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x2e, 0x1d, - 0x82, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x18, 0x82, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x80, 0xc0, 0x01, 0x00, 0x6e, 0x07, 0xa0, 0x41, - 0x80, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x40, 0x92, 0xf4, 0x01, 0x00, 0x0a, 0x00, 0x2e, 0x30, - 0x81, 0x84, 0x01, 0x00, 0x72, 0x07, 0x90, 0x40, 0x92, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, - 0x93, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x48, 0xc1, 0x01, 0x00, - 0x04, 0x00, 0x20, 0x19, 0xe8, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, - 0x16, 0xc0, 0x01, 0x00, 0x78, 0x07, 0xa0, 0x19, 0x16, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x0d, 0x00, 0x2f, 0x1e, - 0x32, 0xc0, 0x01, 0x00, 0x7d, 0x07, 0xa2, 0x40, 0x15, 0x6c, 0x00, 0x00, - 0x7c, 0x07, 0xa0, 0x1c, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3, 0x38, 0x94, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x1e, - 0x98, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x1a, 0x98, 0xc0, 0x01, 0x00, - 0x0c, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x8b, 0x07, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x89, 0x07, 0x22, 0xf2, - 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x86, 0x07, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0xe1, 0x91, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x1a, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17, - 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, - 0x91, 0x07, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x9b, 0x07, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x9b, 0x07, 0x22, 0xf2, - 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x98, 0x07, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xeb, 0x9f, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x20, 0x00, 0x2f, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, 0xa1, 0x07, 0x90, 0xf2, - 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14, - 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x2a, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x2a, 0x94, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xac, 0x07, 0x22, 0xf2, 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xa9, 0x07, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00, - 0xc9, 0x07, 0x22, 0x40, 0x15, 0x6c, 0x00, 0x00, 0xb4, 0x07, 0xa2, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x1f, 0x90, 0x01, 0x00, - 0xb3, 0x07, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88, - 0x1c, 0xcc, 0x01, 0x00, 0xe4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x3f, 0xc3, 0x01, 0x00, 0xe6, 0x9f, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xb7, 0x07, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1e, 0x3e, 0xc0, 0x01, 0x00, 0xc9, 0x07, 0x22, 0x40, - 0x15, 0x6c, 0x00, 0x00, 0xba, 0x07, 0x20, 0x1e, 0x14, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x3c, 0xb0, 0x01, 0x00, 0xe5, 0x9f, 0x00, 0x1e, - 0x24, 0x30, 0x01, 0x00, 0xbf, 0x07, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x52, 0x11, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1a, - 0x10, 0xc0, 0x01, 0x00, 0x23, 0x07, 0x00, 0x40, 0x17, 0xb0, 0x00, 0x00, - 0xe4, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xe5, 0x9f, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xbc, 0x07, 0xa2, 0x08, 0x2e, 0x30, 0x00, 0x00, - 0x80, 0x80, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, - 0x87, 0x98, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00, 0xe8, 0x9f, 0x00, 0x1f, - 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, - 0xe2, 0x9f, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x44, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00, - 0xe6, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xce, 0x07, 0xa2, 0x41, - 0x87, 0x7c, 0x00, 0x00, 0xcf, 0x07, 0x00, 0x1e, 0x3e, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1f, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x05, 0xb0, 0x01, 0x00, 0xe8, 0x9f, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, - 0xe2, 0x9f, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xf7, 0x07, 0x00, 0xbc, 0x80, 0xb2, 0x00, 0x00, - 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, - }, - { - 0x31, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x34, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x35, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x80, 0x81, 0x80, - 0x80, 0x32, 0x00, 0x00, 0xe4, 0x87, 0xa2, 0x40, 0x91, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x90, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2, - 0x80, 0xb0, 0x01, 0x00, 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00, - 0x90, 0x95, 0x2a, 0xc8, 0xe5, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd3, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x44, 0xb1, 0x01, 0x00, 0x18, 0x80, 0x11, 0x81, - 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x51, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x1a, 0x80, 0x11, 0x82, 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xe4, 0x87, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00, - 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x23, 0x80, 0xa2, 0x42, - 0xfd, 0x7f, 0x00, 0x00, 0x20, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00, - 0x22, 0x80, 0x11, 0x81, 0x82, 0x30, 0x00, 0x00, 0x22, 0x80, 0x51, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x22, 0x80, 0x11, 0x82, 0x82, 0x30, 0x00, 0x00, - 0x22, 0x80, 0x52, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x80, 0x00, 0x48, - 0xfd, 0x93, 0x00, 0x00, 0x27, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00, - 0x26, 0x80, 0xa2, 0x53, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x51, 0x53, - 0x07, 0x90, 0x01, 0x00, 0x2a, 0x80, 0x00, 0x52, 0x07, 0x90, 0x00, 0x00, - 0x29, 0x80, 0xa2, 0x52, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x52, 0x52, - 0x07, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0xf3, 0x93, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2, 0x52, 0xb3, 0x01, 0x00, - 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x45, 0xb1, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x4c, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xc6, 0x82, 0x05, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xc6, 0x82, 0x05, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0xde, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfd, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xfd, 0x83, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, - 0x9b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00, - 0x48, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x58, 0x95, 0x20, 0x44, - 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x24, 0xb1, 0x01, 0x00, 0x00, 0x0c, 0x00, 0xee, - 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x97, 0xf0, 0x01, 0x00, - 0x44, 0x80, 0xa2, 0x43, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xfd, 0x93, 0x01, 0x00, 0x00, 0xc0, 0x00, 0xa6, 0x36, 0xb1, 0x01, 0x00, - 0xd0, 0x14, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x00, 0x38, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x06, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x05, 0x10, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x02, 0x09, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x60, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x88, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xa0, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xb9, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xb1, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x60, 0x95, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x70, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x49, 0xdd, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x91, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7b, 0xb3, 0x01, 0x00, - 0x99, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x85, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x3c, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x90, 0x06, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x2f, 0x81, 0x01, 0x00, - 0xa2, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x9e, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x01, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xc6, 0x82, 0x00, 0x41, 0xe1, 0xc1, 0x00, 0x00, 0x78, 0x18, 0x00, 0x40, - 0x49, 0x99, 0x01, 0x00, 0x19, 0x05, 0x22, 0x54, 0x81, 0x7c, 0x00, 0x00, - 0x6c, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0xb4, - 0x69, 0xdf, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x18, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x55, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x7d, 0x80, 0x22, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x7a, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x69, 0x93, 0x01, 0x00, 0x43, 0x81, 0x00, 0x58, - 0x69, 0x93, 0x00, 0x00, 0x54, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x80, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x80, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0x69, 0x93, 0x01, 0x00, 0x43, 0x81, 0x00, 0x58, - 0x69, 0x93, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x40, 0x05, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x5c, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x6e, 0xfa, 0x8e, 0xb0, 0x01, 0x00, 0xc1, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x96, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x96, 0x80, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00, - 0x93, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x69, 0x93, 0x01, 0x00, 0x43, 0x81, 0x00, 0x58, 0x69, 0x93, 0x00, 0x00, - 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xd0, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x83, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xb8, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd5, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd7, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x72, 0x01, 0x00, 0x41, - 0x81, 0xc0, 0x00, 0x00, 0x55, 0x01, 0x51, 0x49, 0xfd, 0x93, 0x00, 0x00, - 0x55, 0x01, 0x52, 0x4a, 0xfd, 0x93, 0x00, 0x00, 0x55, 0x01, 0x55, 0x49, - 0xfd, 0x83, 0x00, 0x00, 0x55, 0x01, 0x56, 0x4a, 0xfd, 0x83, 0x00, 0x00, - 0x50, 0x01, 0x91, 0x81, 0x80, 0x30, 0x00, 0x00, 0x55, 0x01, 0x45, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x50, 0x01, 0x91, 0x82, 0x80, 0x30, 0x00, 0x00, - 0x55, 0x01, 0x46, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x48, 0xc1, 0x01, 0x00, - 0xb4, 0x80, 0x43, 0x30, 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x41, 0x3d, 0xc3, 0x01, 0x00, - 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40, - 0x91, 0x6f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x46, 0xb1, 0x01, 0x00, 0xc4, 0x80, 0xa2, 0x40, 0xe1, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0xd0, 0xe1, 0xb1, 0x00, 0x00, - 0xc1, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, - 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00, - 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0xc9, 0x80, 0xa2, 0x42, - 0x97, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xa1, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x04, - 0x80, 0x94, 0x00, 0x00, 0x80, 0x15, 0x3f, 0x42, 0x97, 0xe3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x03, - 0x02, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xcb, 0x99, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcc, - 0xf3, 0x83, 0x01, 0x00, 0xd3, 0x80, 0xa2, 0x42, 0x97, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xcb, 0xf3, 0x93, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, - 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x44, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa1, 0xe0, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, - 0xda, 0x80, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf9, 0x02, 0x00, 0x20, - 0x42, 0x31, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x05, 0x6c, 0x01, 0x00, - 0x00, 0x00, 0x80, 0xcb, 0xdb, 0x91, 0x01, 0x00, 0x00, 0x00, 0x19, 0x41, - 0x8b, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xe0, 0x80, 0xa8, 0xb1, 0x8c, 0x33, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xe2, 0x80, 0xa8, 0xb1, 0x94, 0x33, 0x00, 0x00, - 0xe8, 0x80, 0x14, 0xc6, 0x81, 0x32, 0x00, 0x00, 0x18, 0x00, 0x00, 0xc6, - 0x83, 0xf4, 0x01, 0x00, 0x22, 0x83, 0x22, 0x4f, 0x83, 0x04, 0x00, 0x00, - 0xc4, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc6, - 0x81, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x97, 0xa3, 0x01, 0x00, - 0xc4, 0x80, 0x1f, 0x5c, 0x97, 0x53, 0x00, 0x00, 0x6d, 0x82, 0x1e, 0xc6, - 0x81, 0x32, 0x00, 0x00, 0xf2, 0x80, 0x22, 0x48, 0xfd, 0x7f, 0x00, 0x00, - 0xf2, 0x80, 0x22, 0x58, 0x81, 0x6c, 0x00, 0x00, 0xf2, 0x80, 0x22, 0x48, - 0x81, 0x6c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x84, 0xcc, 0x01, 0x00, - 0xf2, 0x80, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xc4, 0x80, 0xa2, 0xc6, 0x8f, 0x06, 0x00, 0x00, - 0xc4, 0x80, 0x1e, 0xc6, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x43, - 0x81, 0xf0, 0x01, 0x00, 0xf6, 0x80, 0x00, 0x40, 0x10, 0xc9, 0x00, 0x00, - 0x44, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7e, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x39, 0x82, 0x00, 0xca, 0x63, 0xb3, 0x00, 0x00, - 0x75, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x81, 0x00, 0x4d, - 0x83, 0xb0, 0x00, 0x00, 0x60, 0x81, 0x00, 0x4e, 0x61, 0xb1, 0x00, 0x00, - 0x4c, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00, 0x55, 0x81, 0x00, 0x4c, - 0x83, 0xb0, 0x00, 0x00, 0x2e, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00, - 0xf8, 0x81, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0x86, 0x81, 0x00, 0x40, - 0xc1, 0xb1, 0x00, 0x00, 0xf4, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x4c, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca, 0x9b, 0xb3, 0x00, 0x00, - 0x90, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x94, 0x81, 0x00, 0x40, - 0xc1, 0xb1, 0x00, 0x00, 0x9b, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, - 0x9c, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x9d, 0x81, 0x00, 0x40, - 0xc1, 0xb1, 0x00, 0x00, 0x9e, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, - 0x9f, 0x81, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0x9f, 0x81, 0x00, 0x41, - 0x81, 0xb0, 0x00, 0x00, 0x2d, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xae, 0x82, 0x00, 0xbb, 0xab, 0xb3, 0x00, 0x00, 0x3a, 0x82, 0x00, 0xca, - 0xcf, 0xb3, 0x00, 0x00, 0xc8, 0x03, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, - 0xe8, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc4, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xe0, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca, - 0x77, 0xb3, 0x00, 0x00, 0x56, 0x81, 0x00, 0x4d, 0x83, 0xb0, 0x00, 0x00, - 0x5e, 0x81, 0x00, 0x4e, 0x61, 0xb1, 0x00, 0x00, 0x4c, 0x81, 0x00, 0xbb, - 0x85, 0xb0, 0x00, 0x00, 0x56, 0x81, 0x00, 0x4c, 0x83, 0xb0, 0x00, 0x00, - 0x4c, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00, 0x2e, 0x81, 0x00, 0xbb, - 0x85, 0xb0, 0x00, 0x00, 0x20, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x22, 0x83, 0x00, 0xca, 0x4d, 0xb3, 0x00, 0x00, 0x70, 0x05, 0x00, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0xa0, 0x05, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, - 0x26, 0x81, 0x22, 0x42, 0x8f, 0x6f, 0x00, 0x00, 0x28, 0x81, 0x22, 0x41, - 0x8f, 0x6f, 0x00, 0x00, 0x2a, 0x81, 0x1e, 0xca, 0x81, 0x32, 0x00, 0x00, - 0x2c, 0x81, 0x1f, 0xca, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xc9, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x00, 0x42, 0x8f, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xcd, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x00, 0x41, - 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xcf, 0xb1, 0x01, 0x00, - 0x22, 0x83, 0x00, 0x40, 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x81, 0x00, 0xa6, - 0xc6, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x80, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x00, 0x40, - 0x8f, 0xb3, 0x00, 0x00, 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, - 0x10, 0x00, 0x2f, 0x9c, 0x89, 0xb0, 0x01, 0x00, 0x46, 0x81, 0x00, 0x40, - 0x39, 0x33, 0x01, 0x00, 0x18, 0x00, 0x2f, 0x9b, 0x89, 0xb0, 0x01, 0x00, - 0x46, 0x81, 0x00, 0x40, 0x37, 0x33, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x9a, - 0x89, 0xb0, 0x01, 0x00, 0x46, 0x81, 0x00, 0x40, 0x35, 0x33, 0x01, 0x00, - 0x08, 0x00, 0x2f, 0x99, 0x89, 0xb0, 0x01, 0x00, 0x46, 0x81, 0x00, 0x40, - 0x33, 0x33, 0x01, 0x00, 0x00, 0x80, 0x00, 0xae, 0x47, 0xc9, 0x01, 0x00, - 0xc4, 0x80, 0xa2, 0x40, 0xe1, 0x6d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x00, 0x40, - 0xe1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0xae, 0x63, 0xdd, 0x01, 0x00, 0x41, 0x81, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x3e, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x41, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x69, 0x93, 0x01, 0x00, 0x22, 0x83, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00, - 0x44, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x43, 0x81, 0x00, 0x58, - 0x69, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf0, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0xa4, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4b, 0x81, 0xa2, 0x40, - 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41, - 0xe1, 0xd1, 0x01, 0x00, 0x4c, 0x81, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x62, 0xb1, 0x01, 0x00, 0x52, 0x81, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x4d, 0x81, 0x22, 0x5c, 0x77, 0x7d, 0x00, 0x00, - 0xc4, 0x80, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4d, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, - 0x52, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x22, 0x83, 0x17, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x57, 0x81, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, - 0x57, 0x81, 0x00, 0xbb, 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x60, 0xb1, 0x01, 0x00, 0xc4, 0x80, 0xa2, 0x41, 0x76, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x59, 0x81, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, - 0x22, 0x83, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x5b, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x50, 0x95, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x61, 0x81, 0x00, 0xbb, 0x87, 0xb0, 0x00, 0x00, 0x50, 0x95, 0x2f, 0x40, - 0x87, 0xb0, 0x01, 0x00, 0x65, 0x81, 0x22, 0x40, 0x95, 0x7f, 0x00, 0x00, - 0xc4, 0x80, 0xa2, 0x40, 0xe1, 0x6d, 0x00, 0x00, 0xc4, 0x80, 0x22, 0x40, - 0x95, 0x6f, 0x00, 0x00, 0x22, 0x83, 0x60, 0x40, 0x95, 0x83, 0x00, 0x00, - 0x02, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0xc4, 0x80, 0x22, 0x40, - 0x85, 0x6c, 0x00, 0x00, 0xc4, 0x80, 0xa2, 0x40, 0x85, 0x7c, 0x00, 0x00, - 0xc4, 0x80, 0xa2, 0x4e, 0x77, 0x7d, 0x00, 0x00, 0x69, 0x81, 0x36, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x62, 0xb1, 0x01, 0x00, - 0x6a, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x62, 0xb1, 0x01, 0x00, 0x6c, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, 0x6e, 0x81, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x16, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x74, 0x81, 0x22, 0x41, 0x43, 0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0xca, - 0x95, 0xcb, 0x01, 0x00, 0x68, 0x81, 0x00, 0x41, 0x85, 0xc0, 0x00, 0x00, - 0x22, 0x83, 0x00, 0x40, 0xe1, 0xb1, 0x00, 0x00, 0x77, 0x81, 0xa2, 0x42, - 0x67, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x67, 0xb3, 0x01, 0x00, - 0x77, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x65, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x93, 0x83, 0x01, 0x00, - 0x00, 0x00, 0x1a, 0xca, 0x69, 0x97, 0x01, 0x00, 0x22, 0x83, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x7c, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x22, 0x83, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00, 0xc4, 0x80, 0x20, 0x43, - 0x95, 0x6f, 0x00, 0x00, 0x22, 0x83, 0x80, 0xca, 0x67, 0x33, 0x00, 0x00, - 0x22, 0x83, 0x22, 0x40, 0x65, 0x6f, 0x00, 0x00, 0xc4, 0x80, 0xa2, 0x48, - 0xdb, 0x7d, 0x00, 0x00, 0x22, 0x83, 0x00, 0x6f, 0xdb, 0x91, 0x00, 0x00, - 0x85, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x35, 0x80, 0x22, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x58, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x95, 0x93, 0x01, 0x00, 0x8c, 0x81, 0xa2, 0x44, 0x21, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e, - 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x95, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xc3, 0xb1, 0x01, 0x00, 0x8f, 0x81, 0x22, 0x5b, - 0x95, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xfd, 0x93, 0x01, 0x00, - 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0xfd, 0x00, 0xca, - 0x95, 0x9b, 0x01, 0x00, 0x0d, 0x01, 0x00, 0xca, 0xc5, 0x31, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0x22, 0x83, 0x00, 0xca, - 0xc5, 0xb1, 0x00, 0x00, 0xdf, 0x6f, 0x00, 0xca, 0x95, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xc7, 0xb1, 0x01, 0x00, 0x22, 0x83, 0x22, 0x5f, 0x95, 0x7f, 0x00, 0x00, - 0x0d, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x95, 0x83, 0x01, 0x00, 0x22, 0x83, 0x00, 0xca, 0xc7, 0xb1, 0x00, 0x00, - 0x22, 0x83, 0x00, 0xca, 0xc9, 0xb1, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca, - 0xcb, 0xb1, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca, 0xcd, 0xb1, 0x00, 0x00, - 0x22, 0x83, 0x00, 0xca, 0xcf, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x42, - 0x81, 0xe0, 0x01, 0x00, 0x98, 0x14, 0x00, 0x40, 0x48, 0xc9, 0x01, 0x00, - 0x22, 0x83, 0x00, 0xca, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x09, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0xa4, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x80, 0x00, 0x41, - 0x08, 0x99, 0x01, 0x00, 0xa6, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, - 0x20, 0x80, 0x00, 0xa6, 0x08, 0xb1, 0x01, 0x00, 0xa8, 0x81, 0x9f, 0x85, - 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x83, 0x84, 0x01, 0x00, - 0xdd, 0x81, 0x22, 0x30, 0x83, 0x6c, 0x00, 0x00, 0xa7, 0x81, 0xa2, 0x4f, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x21, 0xb3, 0x01, 0x00, - 0x02, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x10, 0x00, 0x00, 0x41, 0x84, 0xe4, 0x01, 0x00, - 0x03, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x41, 0x86, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x84, 0x94, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0x10, 0xc4, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00, - 0xbd, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x21, 0xb3, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x1c, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0xba, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, - 0xcf, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x41, 0x01, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0x50, 0x0c, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00, - 0xc2, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x21, 0xb3, 0x01, 0x00, 0xcf, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x41, 0x01, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x60, 0x0c, 0x00, 0x43, - 0x86, 0x98, 0x01, 0x00, 0xcf, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x21, 0xb3, 0x01, 0x00, 0x18, 0x80, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x41, 0x82, 0x88, 0x01, 0x00, 0x00, 0x77, 0x00, 0x41, - 0x82, 0x8c, 0x01, 0x00, 0x01, 0x02, 0x00, 0x41, 0x82, 0x98, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x18, 0x00, 0x00, 0x41, - 0x82, 0xdc, 0x01, 0x00, 0xcd, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0xd0, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, - 0x40, 0x13, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0xd8, 0x81, 0x22, 0x43, - 0x21, 0x6f, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0xd5, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, - 0xf3, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x19, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, - 0xda, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x41, - 0x08, 0x99, 0x01, 0x00, 0xf3, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x21, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x83, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5e, 0x83, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, - 0x83, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xc2, 0xb1, 0x01, 0x00, - 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x83, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xc2, 0xb1, 0x01, 0x00, - 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x11, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, - 0xec, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x41, - 0x08, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0xef, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x40, 0x13, 0x00, 0x41, - 0x08, 0x99, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x41, 0x2e, 0x99, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0x81, 0x94, 0x01, 0x00, 0xf6, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40, 0x08, 0xb1, 0x00, 0x00, - 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00, 0xf9, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00, - 0x08, 0x82, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, 0x17, 0x82, 0x22, 0x44, - 0x21, 0x6f, 0x00, 0x00, 0x11, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x1f, 0x82, 0x22, 0x4a, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, - 0x03, 0x82, 0x22, 0x4d, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x87, 0x90, 0x01, 0x00, 0x05, 0x82, 0x22, 0x4f, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0x07, 0x82, 0x22, 0x4e, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0x90, 0x01, 0x00, - 0x1f, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x80, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x1f, 0x82, 0x22, 0x42, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, 0x1c, 0x80, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x12, 0x82, 0x22, 0x45, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x87, 0x90, 0x01, 0x00, 0x14, 0x82, 0x22, 0x44, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0x16, 0x82, 0x22, 0x43, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0x90, 0x01, 0x00, - 0x1f, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x80, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x1f, 0x82, 0x22, 0x42, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x87, 0x90, 0x01, 0x00, - 0x00, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x28, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x23, 0x82, 0x22, 0x4b, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0xe0, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa2, 0xa0, 0x8b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, 0xb8, 0x80, 0x00, 0xca, - 0xa7, 0x33, 0x01, 0x00, 0x41, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x29, 0x82, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00, - 0x2b, 0x82, 0x9f, 0x85, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x30, 0x82, 0x14, 0xf7, 0x81, 0x30, 0x00, 0x00, - 0x30, 0x82, 0xa2, 0x49, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xfd, 0x93, 0x01, 0x00, 0x33, 0x82, 0x15, 0xf8, 0x81, 0x14, 0x00, 0x00, - 0x33, 0x82, 0xa2, 0x4a, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xfd, 0x93, 0x01, 0x00, 0x35, 0x82, 0xa2, 0xc8, 0x81, 0x32, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, - 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xef, 0xb3, 0x01, 0x00, - 0x37, 0x82, 0x42, 0x40, 0xf1, 0x33, 0x00, 0x00, 0x43, 0x81, 0x00, 0x40, - 0x68, 0x97, 0x00, 0x00, 0x22, 0x83, 0x00, 0xbb, 0x6b, 0xb3, 0x00, 0x00, - 0x22, 0x83, 0x00, 0xbb, 0xb1, 0xb3, 0x00, 0x00, 0x22, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x18, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x42, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x18, 0xb1, 0x01, 0x00, 0x40, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x00, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x43, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x81, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf6, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x43, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x4a, 0x82, 0xa2, 0x54, - 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x51, 0x82, 0xa2, 0x06, - 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x80, 0x16, 0x2e, 0x06, - 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0x57, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00, - 0x5a, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40, - 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0x60, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00, - 0x6c, 0x82, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0xc4, 0x80, 0xa2, 0x42, 0x97, 0x6f, 0x00, 0x00, 0xb6, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x42, 0x99, 0xb3, 0x01, 0x00, - 0x78, 0x82, 0x22, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x80, 0x82, 0x22, 0x48, - 0x81, 0x6c, 0x00, 0x00, 0x7a, 0x82, 0x22, 0x4c, 0x81, 0x6c, 0x00, 0x00, - 0x85, 0x82, 0x22, 0x50, 0x81, 0x6c, 0x00, 0x00, 0x86, 0x82, 0x22, 0x54, - 0x81, 0x6c, 0x00, 0x00, 0x88, 0x82, 0x22, 0x58, 0x81, 0x6c, 0x00, 0x00, - 0x8d, 0x82, 0x22, 0x5c, 0x81, 0x6c, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x09, 0xb0, 0x01, 0x00, - 0x22, 0x83, 0x00, 0xca, 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf3, 0x83, 0x01, 0x00, - 0x7e, 0x82, 0xa2, 0x42, 0x05, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x05, 0xb0, 0x01, 0x00, 0x22, 0x83, 0x22, 0xca, 0x07, 0x14, 0x00, 0x00, - 0x22, 0x83, 0x00, 0x46, 0xf3, 0x93, 0x00, 0x00, 0x22, 0x83, 0x20, 0x43, - 0x95, 0x6f, 0x00, 0x00, 0x22, 0x83, 0x80, 0xca, 0x05, 0x30, 0x00, 0x00, - 0x22, 0x83, 0x22, 0x01, 0x80, 0x30, 0x00, 0x00, 0xc4, 0x80, 0xa2, 0x48, - 0xdb, 0x7d, 0x00, 0x00, 0x22, 0x83, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00, - 0x57, 0x01, 0x00, 0xbc, 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, - 0xb1, 0xb3, 0x01, 0x00, 0x22, 0x83, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, - 0xff, 0x00, 0x00, 0xca, 0x81, 0x88, 0x01, 0x00, 0x22, 0x83, 0xa2, 0x40, - 0x74, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00, - 0x8a, 0x82, 0xa8, 0xb1, 0x82, 0x30, 0x00, 0x00, 0x89, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x22, 0x83, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x90, 0x82, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x9b, 0x82, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, - 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, - 0x99, 0x82, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x9b, 0x82, 0x56, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00, - 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xcd, 0x83, 0x01, 0x00, - 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xa0, 0x82, 0xa2, 0x41, - 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xab, 0x82, 0x91, 0x81, - 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x80, 0xb0, 0x01, 0x00, - 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, 0xa9, 0x82, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xab, 0x82, 0x55, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, - 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41, - 0x8b, 0xb3, 0x00, 0x00, 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0xc4, 0x14, 0x2f, 0x40, 0x99, 0xb3, 0x01, 0x00, 0x57, 0x01, 0x00, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0xa0, 0x94, 0x2e, 0x43, 0x97, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0xb2, 0x82, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x50, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0xac, 0x94, 0x2e, 0x43, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xb6, 0x82, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xae, 0x03, 0x00, 0x40, - 0xa3, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0x60, 0x15, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, - 0x40, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x59, 0x41, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x41, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x40, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x42, - 0x81, 0x6c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, - 0xbc, 0x82, 0xa0, 0x42, 0x81, 0x6c, 0x00, 0x00, 0xbc, 0x82, 0x00, 0x50, - 0x85, 0xc0, 0x00, 0x00, 0x01, 0x83, 0xa2, 0x41, 0x01, 0x7d, 0x00, 0x00, - 0xcf, 0x82, 0x22, 0x58, 0x73, 0x7d, 0x00, 0x00, 0x78, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xc7, 0x82, 0xa8, 0xb1, 0x9c, 0x30, 0x00, 0x00, - 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5f, - 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5e, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0xc0, 0x00, 0xa6, 0x1e, 0xa4, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e, - 0x10, 0xc9, 0x00, 0x00, 0xcf, 0x82, 0x33, 0xc4, 0x81, 0x30, 0x00, 0x00, - 0xd2, 0x82, 0xa1, 0xad, 0x9d, 0x20, 0x00, 0x00, 0xc6, 0x82, 0x13, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4e, 0x5a, 0x83, 0x01, 0x00, - 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5f, - 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5e, 0x1f, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x40, 0x05, 0x6c, 0x00, 0x00, 0xdd, 0x82, 0x22, 0xab, - 0x80, 0x04, 0x00, 0x00, 0xdb, 0x82, 0xa2, 0x40, 0x01, 0x7d, 0x00, 0x00, - 0xdd, 0x82, 0x22, 0x5f, 0x57, 0x7d, 0x00, 0x00, 0x0f, 0x88, 0x00, 0x5f, - 0x1f, 0xb4, 0x00, 0x00, 0xdd, 0x82, 0x22, 0x5e, 0x57, 0x7d, 0x00, 0x00, - 0x7d, 0x88, 0x00, 0x5f, 0x1f, 0xb4, 0x00, 0x00, 0xe3, 0x82, 0x22, 0x54, - 0x73, 0x7d, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xdd, 0x82, 0xa8, 0xb1, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x1f, 0xb4, 0x01, 0x00, 0xf4, 0x84, 0xa2, 0x5f, 0x01, 0x7c, 0x00, 0x00, - 0x92, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xe5, 0x82, 0xa2, 0x5f, - 0x59, 0x27, 0x00, 0x00, 0xe7, 0x82, 0xa2, 0x5c, 0x73, 0x7d, 0x00, 0x00, - 0xee, 0x82, 0xa2, 0x5e, 0x73, 0x7d, 0x00, 0x00, 0xfa, 0x82, 0x22, 0x5c, - 0x73, 0x7d, 0x00, 0x00, 0xfb, 0x82, 0x37, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xe8, 0x82, 0xa8, 0xb1, - 0x36, 0x30, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xea, 0x82, 0xa8, 0xb1, 0x00, 0x30, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, - 0x02, 0x88, 0x01, 0x00, 0x34, 0x85, 0x17, 0x5f, 0x1f, 0xb4, 0x00, 0x00, - 0xfb, 0x82, 0x34, 0x40, 0x81, 0x32, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xef, 0x82, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00, - 0xf7, 0x82, 0x52, 0x21, 0x13, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14, 0x41, - 0x2f, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x1f, 0xb4, 0x01, 0x00, - 0xff, 0x3f, 0x00, 0x09, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x01, 0xf0, 0x01, 0x00, 0x4f, 0x83, 0x00, 0x34, 0x13, 0x84, 0x00, 0x00, - 0xff, 0x3f, 0x14, 0x09, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x1f, 0xb4, 0x01, 0x00, 0xc2, 0x83, 0x00, 0x43, 0x01, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xfb, 0x82, 0x33, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4e, 0x5a, 0x7f, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x4e, 0x80, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x40, - 0x80, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, 0x06, 0x6c, 0x00, 0x00, - 0xc6, 0x82, 0x13, 0x4e, 0x5a, 0x93, 0x00, 0x00, 0xe4, 0x87, 0xa2, 0x48, - 0xfd, 0x7f, 0x00, 0x00, 0x05, 0x83, 0x02, 0xe6, 0x81, 0x32, 0x00, 0x00, - 0x06, 0x83, 0x83, 0xe5, 0x81, 0x32, 0x00, 0x00, 0x8e, 0x82, 0x00, 0x42, - 0x97, 0xb3, 0x00, 0x00, 0x9e, 0x82, 0x00, 0x42, 0x97, 0xb3, 0x00, 0x00, - 0x09, 0x83, 0x22, 0x46, 0xf3, 0x7f, 0x00, 0x00, 0x0c, 0x83, 0xa2, 0x41, - 0xf3, 0x7f, 0x00, 0x00, 0xc6, 0x80, 0x00, 0x42, 0x97, 0x33, 0x01, 0x00, - 0x0c, 0x83, 0x22, 0x44, 0xf3, 0x7f, 0x00, 0x00, 0x0c, 0x83, 0xa2, 0x41, - 0xf3, 0x7f, 0x00, 0x00, 0xc6, 0x80, 0x00, 0x6f, 0x97, 0x33, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0xac, 0x80, 0x32, 0x00, 0x00, 0x11, 0x83, 0x22, 0x5a, - 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x0e, 0x83, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x01, 0x00, 0x00, 0xcf, - 0x11, 0xc9, 0x00, 0x00, 0x17, 0x83, 0xa2, 0x40, 0x93, 0x7f, 0x00, 0x00, - 0x17, 0x83, 0x22, 0x44, 0x93, 0x7f, 0x00, 0x00, 0x13, 0x83, 0x42, 0xa5, - 0x80, 0x30, 0x00, 0x00, 0x16, 0x83, 0xa2, 0x40, 0x93, 0x7f, 0x00, 0x00, - 0x38, 0x83, 0x1a, 0x40, 0x93, 0x93, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xdf, 0x80, 0xa2, 0x40, 0x73, 0x7d, 0x00, 0x00, - 0xdf, 0x87, 0x22, 0x44, 0x21, 0x6f, 0x00, 0x00, 0xd6, 0x87, 0x22, 0x40, - 0x65, 0x7d, 0x00, 0x00, 0x00, 0x05, 0xa2, 0x5b, 0x73, 0x7d, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x49, 0x33, 0x7d, 0x00, 0x00, 0x21, 0x83, 0x22, 0x48, - 0x33, 0x7d, 0x00, 0x00, 0xff, 0x01, 0x00, 0x99, 0x80, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x81, 0xe0, 0x01, 0x00, 0xa8, 0x98, 0x2f, 0x40, - 0x33, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe0, 0xc1, 0x01, 0x00, - 0x01, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x82, 0x00, 0x40, - 0x8b, 0xb3, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5e, 0x1f, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x5f, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, - 0x1f, 0x90, 0x01, 0x00, 0xc6, 0x82, 0x00, 0x5f, 0x1f, 0x80, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x5e, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5f, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x1f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x62, 0xb1, 0x01, 0x00, - 0xc6, 0x82, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x2c, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5e, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5f, - 0x1f, 0x7c, 0x00, 0x00, 0x32, 0x83, 0x33, 0x40, 0x1f, 0x30, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x4e, 0x5a, 0x7f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x4e, - 0x80, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x40, 0x06, 0x6c, 0x00, 0x00, 0xc6, 0x82, 0x13, 0x4e, - 0x5a, 0x93, 0x00, 0x00, 0x3a, 0x83, 0xa0, 0xce, 0x81, 0x50, 0x00, 0x00, - 0x4d, 0x83, 0xa0, 0xcd, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, - 0x9c, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x81, 0xb0, 0x01, 0x00, - 0x4d, 0x83, 0x22, 0xb5, 0x81, 0x14, 0x00, 0x00, 0x80, 0x15, 0x2f, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0x3e, 0x83, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x60, 0xb4, 0x65, 0x97, 0x01, 0x00, 0xd0, 0x15, 0x2e, 0x40, - 0x69, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44, 0x93, 0x83, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00, 0x1a, 0x00, 0x00, 0xa2, - 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xb1, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb5, - 0xf1, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x80, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, 0x48, 0x83, 0xa8, 0xa1, - 0xe0, 0x31, 0x00, 0x00, 0x17, 0x83, 0x00, 0x88, 0x9e, 0xb3, 0x00, 0x00, - 0x17, 0x83, 0xa2, 0x41, 0x67, 0x6f, 0x00, 0x00, 0x17, 0x83, 0x00, 0x6f, - 0xdb, 0x91, 0x00, 0x00, 0x4d, 0x83, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x17, 0x83, 0x1a, 0x40, 0x93, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5a, 0x01, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, - 0x01, 0x6c, 0x00, 0x00, 0x00, 0x99, 0x00, 0x09, 0x46, 0xc9, 0x01, 0x00, - 0x3f, 0x00, 0x00, 0xf3, 0x0c, 0x88, 0x01, 0x00, 0x5c, 0x83, 0xa6, 0x42, - 0x13, 0x60, 0x00, 0x00, 0x95, 0x96, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00, - 0x57, 0x83, 0x61, 0x40, 0x81, 0x32, 0x00, 0x00, 0x75, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x58, 0x83, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00, - 0xa3, 0x96, 0x71, 0x10, 0x94, 0x30, 0x01, 0x00, 0x5d, 0x83, 0x00, 0x58, - 0x1f, 0x90, 0x00, 0x00, 0x87, 0x96, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0xf0, 0x2e, 0xb0, 0x01, 0x00, - 0x80, 0x04, 0x00, 0x17, 0x96, 0x88, 0x01, 0x00, 0x04, 0x00, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x4a, 0xc1, 0x00, 0x17, 0x96, 0xd8, 0x01, 0x00, - 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xee, 0x07, 0x00, 0x40, - 0x97, 0x98, 0x01, 0x00, 0x68, 0x83, 0x23, 0x4b, 0xe4, 0x6d, 0x00, 0x00, - 0x68, 0x83, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x1f, 0x90, 0x01, 0x00, 0x22, 0x00, 0x2f, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x6b, 0x83, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x6d, 0x83, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x47, 0xc1, 0x01, 0x00, 0x72, 0x83, 0x22, 0x55, - 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0xd1, 0x01, 0x00, - 0x0f, 0x00, 0x00, 0xfa, 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x97, 0xe0, 0x01, 0x00, 0x73, 0x83, 0x00, 0x4b, 0x44, 0xc1, 0x00, 0x00, - 0x12, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x28, 0x00, 0x00, 0xf6, - 0x02, 0xcc, 0x01, 0x00, 0x0a, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x28, 0xf0, - 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa2, 0x2a, 0xb0, 0x01, 0x00, 0xc0, 0x28, 0x3c, 0x46, - 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x44, 0x95, 0xb0, 0x01, 0x00, - 0x7f, 0x83, 0xa2, 0xf8, 0x0e, 0x30, 0x00, 0x00, 0x8f, 0x83, 0x22, 0x41, - 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x50, 0x49, 0xc1, 0x01, 0x00, - 0x7b, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7c, 0x83, 0xa2, 0xf8, - 0x16, 0x6c, 0x00, 0x00, 0x7c, 0x83, 0xa2, 0xf8, 0x10, 0x6c, 0x00, 0x00, - 0x7c, 0x83, 0xa2, 0xf0, 0x1a, 0x6c, 0x00, 0x00, 0x8d, 0x83, 0x22, 0x58, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, - 0x84, 0x83, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, 0x88, 0x83, 0xa2, 0xf3, - 0x74, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xe6, 0x95, 0x01, 0x00, - 0x8d, 0x83, 0x75, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, - 0x96, 0xb0, 0x01, 0x00, 0x3f, 0x00, 0x75, 0xf3, 0x0c, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0x8b, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x8d, 0x83, 0x67, 0x40, 0x81, 0x32, 0x00, 0x00, 0x95, 0x83, 0x77, 0x41, - 0x2d, 0xc3, 0x00, 0x00, 0x93, 0x83, 0x22, 0x58, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, - 0x62, 0xb1, 0x01, 0x00, 0x91, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x93, 0x83, 0x67, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd3, 0x83, 0x77, 0x41, - 0x2d, 0xc3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, - 0x12, 0x95, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, 0xa6, 0x83, 0x22, 0x41, - 0x81, 0x6c, 0x00, 0x00, 0x9b, 0x83, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xa5, 0x83, 0x22, 0x5f, - 0x0f, 0x7c, 0x00, 0x00, 0x48, 0x96, 0x00, 0x5f, 0x01, 0x10, 0x01, 0x00, - 0xa1, 0x83, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, - 0x9f, 0x95, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x80, 0x01, 0x00, - 0x01, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, - 0x8a, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, - 0xb5, 0x83, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x0d, - 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x6a, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb5, 0x83, 0x22, 0x20, - 0x85, 0x6c, 0x00, 0x00, 0xb0, 0x83, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c, - 0x1f, 0x00, 0x01, 0x00, 0xc2, 0x97, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x4b, 0xe1, 0x7d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xb9, 0x83, 0x82, 0xf0, 0x18, 0x30, 0x00, 0x00, 0x69, 0x89, 0x00, 0x45, - 0x8f, 0xb0, 0x00, 0x00, 0x28, 0x20, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00, - 0xbf, 0x83, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, 0x34, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x55, 0x97, 0x00, 0x4b, 0x95, 0x30, 0x01, 0x00, 0x69, 0x89, 0x00, 0x4b, - 0x8f, 0xb0, 0x00, 0x00, 0x57, 0x96, 0x00, 0x03, 0x48, 0x31, 0x01, 0x00, - 0xa9, 0x93, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, - 0x00, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, - 0x8a, 0x30, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, 0x01, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0x50, - 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50, - 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xce, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, - 0x62, 0xc9, 0x01, 0x00, 0xd0, 0x83, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x2e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, - 0x00, 0x41, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00, 0xee, 0x07, 0x2e, 0x47, - 0x97, 0x90, 0x01, 0x00, 0xe6, 0x83, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, - 0xe4, 0x83, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0xe4, 0x83, 0x23, 0xa2, - 0x02, 0x6c, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x00, - 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x03, 0xb0, 0x01, 0x00, 0x03, 0x84, 0x00, 0x5c, - 0x17, 0x90, 0x00, 0x00, 0xf8, 0x83, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, 0xf1, 0x83, 0x22, 0x5f, - 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x58, 0xf1, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03, - 0xf0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, - 0xed, 0x83, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0xee, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x72, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0xff, 0x0f, 0x00, 0xf6, 0x80, 0x88, 0x01, 0x00, - 0xf5, 0x83, 0xa2, 0xa6, 0x81, 0x6c, 0x00, 0x00, 0xf8, 0x83, 0x00, 0xf2, - 0x3a, 0xb0, 0x00, 0x00, 0xf1, 0x84, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00, - 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x03, 0x88, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x03, 0x84, 0x22, 0x4a, 0x2f, 0x7c, 0x00, 0x00, - 0x03, 0x84, 0x22, 0x48, 0x2f, 0x7c, 0x00, 0x00, 0x0a, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x3f, 0x00, 0x00, 0xf2, 0x86, 0x88, 0x01, 0x00, - 0x1f, 0x00, 0x00, 0x43, 0x84, 0x88, 0x01, 0x00, 0x05, 0x00, 0x00, 0x43, - 0x80, 0xf4, 0x01, 0x00, 0x98, 0x94, 0x3d, 0x42, 0x81, 0xe0, 0x01, 0x00, - 0x03, 0x84, 0xa2, 0x42, 0xe0, 0x7d, 0x00, 0x00, 0xf1, 0x84, 0xa2, 0x4b, - 0xfd, 0x7f, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x03, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x02, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x05, 0x84, 0x69, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, - 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x79, 0x41, 0x47, 0xc3, 0x01, 0x00, - 0x04, 0x00, 0xa0, 0xa1, 0x09, 0x6c, 0x00, 0x00, 0x0c, 0x84, 0x22, 0xa1, - 0x09, 0x6c, 0x00, 0x00, 0x27, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x08, 0x84, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00, 0x46, 0x84, 0xa3, 0x92, - 0x03, 0x6c, 0x00, 0x00, 0x25, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0x80, 0xb2, 0x01, 0x00, 0x03, 0x88, 0x27, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x13, 0x84, 0x22, 0x5c, 0x17, 0x7c, 0x00, 0x00, 0x14, 0x84, 0x00, 0x00, - 0x2a, 0xb0, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x08, 0x80, 0xc8, 0x01, 0x00, 0x18, 0x84, 0xa2, 0x43, - 0x2f, 0x7c, 0x00, 0x00, 0x58, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x34, 0x84, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, - 0x8c, 0xcc, 0x01, 0x00, 0x58, 0x97, 0x00, 0x4c, 0x03, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x46, 0x02, 0xb0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, - 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, - 0x2c, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x15, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x21, 0x84, 0xa8, 0x54, 0x17, 0x10, 0x00, 0x00, - 0x34, 0x84, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x2a, 0xc8, 0x01, 0x00, 0x33, 0x84, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x01, 0x8c, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x03, 0xb0, 0x01, 0x00, 0x79, 0x97, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x46, 0x02, 0xb0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, - 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, - 0x0c, 0x00, 0x00, 0x09, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x15, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x34, 0x84, 0x28, 0x54, 0x17, 0x10, 0x00, 0x00, - 0x30, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x79, 0x97, 0x00, 0x43, - 0x61, 0x31, 0x01, 0x00, 0x36, 0x84, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x56, 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17, - 0x98, 0x88, 0x01, 0x00, 0x39, 0x84, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x17, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x3a, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x60, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x41, 0x84, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, 0x16, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xe4, 0xb1, 0x01, 0x00, - 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x44, 0x84, 0xa2, 0x5f, - 0x2f, 0x7c, 0x00, 0x00, 0x80, 0x93, 0x00, 0x01, 0x38, 0x43, 0x01, 0x00, - 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x03, 0x88, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x48, 0x84, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00, - 0xee, 0x84, 0x00, 0x41, 0x43, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x27, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x4b, 0x84, 0x35, 0x01, - 0x86, 0x30, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x54, 0x84, 0x28, 0xb1, 0x30, 0x30, 0x00, 0x00, 0x4c, 0x84, 0x22, 0x4d, - 0x75, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00, - 0xdb, 0x84, 0xa7, 0x40, 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x43, 0xc3, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, 0x27, 0x6c, 0x00, 0x00, - 0xed, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x54, 0x84, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00, 0x5e, 0x84, 0xa7, 0x40, - 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x09, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x2c, 0xb0, 0x01, 0x00, 0xde, 0x07, 0x00, 0x43, 0x80, 0xce, 0x01, 0x00, - 0x4c, 0x84, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0x63, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x3e, 0x43, 0x27, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x27, 0xc0, 0x01, 0x00, - 0x4c, 0x84, 0xa3, 0x0b, 0x87, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, - 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x03, 0x48, 0x6d, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x2a, 0xc8, 0x01, 0x00, 0x40, 0x00, 0x2d, 0x40, 0x39, 0xb0, 0x01, 0x00, - 0x6d, 0x84, 0xa2, 0x40, 0x27, 0x6c, 0x00, 0x00, 0x22, 0x00, 0x00, 0x08, - 0x12, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x16, 0x30, 0x6c, 0x00, 0x00, - 0xde, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, 0x70, 0x84, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x12, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x14, 0x00, 0x20, 0x01, 0xe0, 0xb1, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40, - 0x37, 0x98, 0x01, 0x00, 0x75, 0x84, 0x23, 0x01, 0x36, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x36, 0xb0, 0x01, 0x00, 0x80, 0x84, 0x82, 0x41, - 0x23, 0x40, 0x00, 0x00, 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0x7c, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x79, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xed, 0x94, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, 0x91, 0x84, 0x22, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x41, 0x23, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x0b, 0x25, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, - 0x88, 0x84, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x25, 0xd0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x4c, - 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x37, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x2b, 0xc0, 0x01, 0x00, 0x75, 0x84, 0x00, 0x45, - 0x1f, 0x80, 0x00, 0x00, 0x93, 0x84, 0xa3, 0x12, 0x36, 0x6c, 0x00, 0x00, - 0x94, 0x84, 0x68, 0x1b, 0x28, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, - 0x28, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, - 0x97, 0x84, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, 0xbf, 0x84, 0x22, 0x14, - 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x14, - 0x12, 0xc0, 0x01, 0x00, 0xb7, 0x84, 0xa2, 0x14, 0x36, 0x50, 0x00, 0x00, - 0xa7, 0x84, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0xa5, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xa2, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x10, 0x00, 0x00, 0xf0, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x2b, 0x80, 0x01, 0x00, 0x04, 0x00, 0x22, 0x50, 0x2b, 0x6c, 0x00, 0x00, - 0xf0, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00, 0xad, 0x84, 0x23, 0x01, - 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36, 0xb0, 0x01, 0x00, - 0xb8, 0x84, 0x22, 0x1b, 0x02, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x15, 0xe0, 0x8d, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0xb4, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xb8, 0x84, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x2a, 0xc0, 0x01, 0x00, 0x75, 0x84, 0xa2, 0x40, 0x25, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x39, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x13, - 0x38, 0x6c, 0x00, 0x00, 0x40, 0x00, 0x3d, 0x43, 0x39, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x12, 0xb0, 0x01, 0x00, 0x75, 0x84, 0x00, 0xf0, 0x30, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x42, 0xc9, 0x01, 0x00, 0xc6, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x19, - 0x62, 0xdd, 0x01, 0x00, 0xc3, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xed, 0x94, 0x00, 0x40, - 0x2b, 0x30, 0x01, 0x00, 0x18, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0xca, 0x84, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, - 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17, 0x98, 0x88, 0x01, 0x00, - 0xcd, 0x84, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x17, 0x90, 0x01, 0x00, 0xd0, 0x84, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x17, 0x90, 0x01, 0x00, 0x16, 0x00, 0x20, 0x1d, - 0xe4, 0xb1, 0x01, 0x00, 0xd2, 0x84, 0xa3, 0x40, 0x27, 0x6c, 0x00, 0x00, - 0xd4, 0x84, 0x60, 0x5f, 0x17, 0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x0b, - 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x60, 0x13, 0x16, 0x94, 0x01, 0x00, - 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, - 0x0f, 0x6c, 0x00, 0x00, 0x03, 0x88, 0xa2, 0x5f, 0x2f, 0x7c, 0x00, 0x00, - 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x02, 0xb0, 0x01, 0x00, 0x80, 0x93, 0x00, 0x01, 0x38, 0x43, 0x01, 0x00, - 0x03, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x03, - 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d, - 0x61, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x16, 0x62, 0xb1, 0x01, 0x00, 0xe0, 0x84, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x62, 0xb1, 0x01, 0x00, - 0xe2, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xed, 0x84, 0x22, 0x13, - 0x82, 0x6c, 0x00, 0x00, 0x40, 0x00, 0x3d, 0x43, 0x83, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0x62, 0xb1, 0x01, 0x00, - 0xe8, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x62, 0xb1, 0x01, 0x00, 0xea, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xe4, 0x84, 0x00, 0x41, 0x83, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, - 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41, - 0x89, 0x30, 0x01, 0x00, 0x9f, 0x95, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00, - 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x03, 0x88, 0x00, 0x40, - 0x0f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x01, 0x80, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x0e, 0xf4, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, - 0x05, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, - 0x8a, 0x30, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, - 0x12, 0x95, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, 0x05, 0x85, 0x22, 0x41, - 0x81, 0x6c, 0x00, 0x00, 0x00, 0x85, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x04, 0x85, 0x22, 0x5f, - 0x0f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x80, 0x01, 0x00, - 0x06, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, - 0x8a, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, - 0x14, 0x85, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x0d, - 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x6a, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x14, 0x85, 0x22, 0x20, - 0x85, 0x6c, 0x00, 0x00, 0x0f, 0x85, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c, - 0x1f, 0x00, 0x01, 0x00, 0xc2, 0x97, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x4b, 0xe1, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, - 0x19, 0x85, 0x22, 0x3a, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8e, 0xb0, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, 0x01, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x1e, 0x85, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, - 0x01, 0xb0, 0x00, 0x00, 0x17, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x35, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x87, 0x96, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0x22, 0x00, 0x2d, 0xf0, 0x2e, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x17, - 0x80, 0x32, 0x00, 0x00, 0x28, 0x20, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00, - 0x2b, 0x85, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, 0x55, 0x97, 0x00, 0x4b, - 0x95, 0x30, 0x01, 0x00, 0x69, 0x89, 0x00, 0x4c, 0x8f, 0xb0, 0x00, 0x00, - 0x2d, 0x85, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x43, 0xc1, 0x01, 0x00, 0x2f, 0x85, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x43, 0xc1, 0x01, 0x00, 0x28, 0x00, 0x00, 0xf6, - 0x02, 0xcc, 0x01, 0x00, 0x12, 0x00, 0x00, 0xa1, 0x2a, 0xc8, 0x01, 0x00, - 0x57, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xa9, 0x93, 0x00, 0x41, - 0x81, 0x30, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb1, 0x01, 0x00, 0x39, 0x85, 0x64, 0x47, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x3a, 0x85, 0xa8, 0x1b, - 0xe0, 0x31, 0x00, 0x00, 0x23, 0x83, 0x74, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x03, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa0, 0x05, - 0x03, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa3, 0x09, 0x03, 0x6c, 0x00, 0x00, - 0x08, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x6b, 0x85, 0x01, 0xfb, - 0x08, 0x30, 0x00, 0x00, 0xd5, 0x85, 0x87, 0xfb, 0x22, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0x0e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x14, 0xb0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, - 0x12, 0x95, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, 0x5c, 0x85, 0x22, 0x41, - 0x81, 0x6c, 0x00, 0x00, 0x4b, 0x85, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5b, 0x85, 0x22, 0x5f, - 0x0f, 0x7c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x04, 0x7e, 0x89, 0x01, 0x00, - 0x51, 0x85, 0xa6, 0x5f, 0x0f, 0x00, 0x00, 0x00, 0x2b, 0x94, 0x00, 0x40, - 0x05, 0x30, 0x01, 0x00, 0x0a, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, 0x58, 0x85, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x84, 0xb0, 0x01, 0x00, - 0x26, 0x96, 0x00, 0x40, 0x05, 0x30, 0x01, 0x00, 0x08, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x90, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, - 0x69, 0x85, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x0d, - 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x6a, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x69, 0x85, 0x22, 0x20, - 0x85, 0x6c, 0x00, 0x00, 0x66, 0x85, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c, - 0x1f, 0x00, 0x01, 0x00, 0xc2, 0x97, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, 0x6d, 0x85, 0x21, 0x04, - 0x80, 0x20, 0x00, 0x00, 0x6e, 0x85, 0x00, 0x40, 0x10, 0xc9, 0x00, 0x00, - 0xa1, 0x88, 0x00, 0x4b, 0x81, 0xb0, 0x00, 0x00, 0x9c, 0x85, 0x00, 0x43, - 0x81, 0xb0, 0x00, 0x00, 0xa0, 0x85, 0x00, 0xfb, 0x22, 0xb0, 0x00, 0x00, - 0xa1, 0x88, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00, 0x69, 0x89, 0x00, 0x4e, - 0x8f, 0xb0, 0x00, 0x00, 0x91, 0x85, 0x00, 0x5a, 0x8f, 0xb0, 0x00, 0x00, - 0x76, 0x85, 0x00, 0x47, 0x8f, 0xb0, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x53, - 0x81, 0xb0, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x56, 0x81, 0xb0, 0x00, 0x00, - 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x07, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x3c, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x0a, - 0x8a, 0x30, 0x01, 0x00, 0x3d, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x18, 0x00, 0x00, 0x11, 0x8a, 0xe4, 0x01, 0x00, 0x02, 0x99, 0x00, 0xf2, - 0x8a, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x69, 0x89, 0xa0, 0x0a, 0xe4, 0x6d, 0x00, 0x00, 0x84, 0x85, 0xa2, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0x83, 0x85, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, - 0x69, 0x89, 0x00, 0x53, 0x8f, 0xb0, 0x00, 0x00, 0x69, 0x89, 0x00, 0x54, - 0x8f, 0xb0, 0x00, 0x00, 0x8d, 0x85, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, - 0x87, 0x85, 0xa2, 0x0a, 0xe4, 0x6d, 0x00, 0x00, 0x69, 0x89, 0x00, 0x5d, - 0x8f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x80, 0xd0, 0x01, 0x00, 0x8b, 0x85, 0xa0, 0x91, - 0x81, 0x6c, 0x00, 0x00, 0x69, 0x89, 0x00, 0x5e, 0x8f, 0xb0, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x85, 0x20, 0x91, 0xe5, 0x6d, 0x00, 0x00, - 0x69, 0x89, 0x00, 0x54, 0x8f, 0xb0, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x07, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x3c, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x0a, - 0x8a, 0x30, 0x01, 0x00, 0x3d, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x02, 0x99, 0x00, 0xf2, 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x69, 0x89, 0xa0, 0x0a, 0xe4, 0x6d, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x69, 0x89, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xf3, 0x82, 0xf4, 0x01, 0x00, 0xa1, 0x88, 0xa0, 0x42, - 0x83, 0x6c, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x54, 0x81, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x23, 0x40, - 0x0f, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x20, 0xaa, 0x0f, 0x6c, 0x00, 0x00, - 0x09, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, - 0x8a, 0x30, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, - 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, - 0x16, 0x88, 0x01, 0x00, 0xae, 0x85, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x78, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0x1c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0xed, 0x87, 0x00, 0x5c, - 0x1f, 0x90, 0x00, 0x00, 0xc0, 0x85, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, - 0xbb, 0x85, 0xa2, 0x54, 0xfd, 0x7f, 0x00, 0x00, 0xb3, 0x85, 0x22, 0x55, - 0xfd, 0x7f, 0x00, 0x00, 0x82, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0xaa, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x53, - 0xfd, 0x7f, 0x00, 0x00, 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4b, - 0x80, 0xf4, 0x01, 0x00, 0x0c, 0xbc, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0xbb, 0x85, 0x22, 0x43, 0x80, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, - 0x80, 0x88, 0x01, 0x00, 0xaa, 0x85, 0xa2, 0x43, 0x80, 0x6c, 0x00, 0x00, - 0x7c, 0x96, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xbc, 0x85, 0x46, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xbf, 0x85, 0xa0, 0xf0, 0x30, 0x6f, 0x00, 0x00, - 0xb1, 0x85, 0x1e, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x41, - 0x31, 0xc3, 0x01, 0x00, 0x79, 0x94, 0x00, 0x40, 0x25, 0x30, 0x01, 0x00, - 0xc4, 0x85, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, - 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x96, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07, - 0x18, 0xe4, 0x01, 0x00, 0x00, 0x08, 0x00, 0x0c, 0xe0, 0x99, 0x01, 0x00, - 0x90, 0x04, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, - 0x46, 0xc9, 0x01, 0x00, 0xcc, 0x85, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0xe6, 0x91, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa1, 0x46, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0xe6, 0x91, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x10, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xa1, 0x88, 0x00, 0x40, - 0x81, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x28, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfb, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x14, 0xb0, 0x01, 0x00, 0xe0, 0x85, 0x22, 0x46, 0x23, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x40, 0x87, 0x6c, 0x00, 0x00, 0xdc, 0x85, 0x22, 0x40, - 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x1f, 0x90, 0x01, 0x00, - 0xde, 0x85, 0x22, 0x41, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x1f, 0x90, 0x01, 0x00, 0xe0, 0x85, 0x22, 0x42, 0x87, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, - 0x09, 0x7c, 0x00, 0x00, 0xe1, 0x85, 0x66, 0x1b, 0x2c, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa0, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x76, 0x41, - 0x41, 0xc3, 0x01, 0x00, 0x13, 0x86, 0x23, 0x92, 0x15, 0x6c, 0x00, 0x00, - 0x13, 0x86, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x19, 0x86, 0x22, 0x4b, - 0xfd, 0x7f, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x27, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x0a, - 0x24, 0xc8, 0x01, 0x00, 0xb9, 0x94, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, - 0x11, 0x86, 0x22, 0x08, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xa3, 0xc1, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x12, 0x24, 0xcc, 0x01, 0x00, - 0xea, 0x85, 0xaa, 0x41, 0x27, 0x40, 0x00, 0x00, 0x04, 0x00, 0xa3, 0x49, - 0x27, 0x6c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x80, 0xcc, 0x01, 0x00, - 0x0b, 0x86, 0x26, 0x40, 0x23, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x60, 0x00, 0x00, 0x03, 0x84, 0xc8, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x48, 0xcd, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0, - 0xa2, 0xc9, 0x01, 0x00, 0xf8, 0x85, 0xa2, 0x40, 0x83, 0x6c, 0x00, 0x00, - 0x04, 0x86, 0x00, 0x41, 0x83, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x42, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x68, 0x21, 0x38, 0x96, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, 0xfd, 0x85, 0xa2, 0x44, - 0x23, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x20, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x86, 0xa8, 0x42, - 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x85, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xa3, 0xc1, 0x01, 0x00, 0xf6, 0x85, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x0b, 0x86, 0x22, 0x40, 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x08, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x0b, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, - 0x17, 0x00, 0x00, 0xd0, 0x2a, 0xc8, 0x01, 0x00, 0x24, 0x86, 0x00, 0x17, - 0x10, 0xb0, 0x00, 0x00, 0x04, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x19, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb9, 0x94, 0x00, 0x92, - 0x25, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x31, 0xb0, 0x01, 0x00, - 0x0b, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, - 0x8a, 0x30, 0x01, 0x00, 0x19, 0x86, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00, - 0x24, 0x86, 0x00, 0x41, 0x27, 0xb0, 0x00, 0x00, 0x80, 0x80, 0x00, 0xa6, - 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x78, 0x98, 0x00, 0x0a, 0x8c, 0x30, 0x01, 0x00, 0x04, 0x00, 0x1c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x04, 0x00, 0xa0, 0x9f, - 0x13, 0x6c, 0x00, 0x00, 0x23, 0x86, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x88, 0x1c, 0xcc, 0x01, 0x00, 0x27, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xed, 0x87, 0x00, 0x41, 0x3f, 0xc3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x01, - 0x80, 0xce, 0x01, 0x00, 0x38, 0x86, 0x2a, 0x40, 0x81, 0x30, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0x2d, 0x86, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, - 0x2d, 0x86, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x2d, 0x86, 0xa3, 0x07, - 0x03, 0x6c, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0x30, 0x86, 0xa3, 0x40, 0x02, 0x6c, 0x00, 0x00, 0x28, 0x00, 0x00, 0x01, - 0xf0, 0xcd, 0x01, 0x00, 0x32, 0x86, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x40, 0xf0, 0xcd, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x0e, 0xcc, 0x01, 0x00, 0x28, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, - 0x28, 0x00, 0x00, 0x00, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x36, 0x86, 0xa8, 0x5c, - 0x1f, 0x10, 0x00, 0x00, 0x04, 0x00, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x03, 0x48, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x08, 0xb0, 0x01, 0x00, - 0xa0, 0x01, 0x2d, 0x40, 0x00, 0xc0, 0x01, 0x00, 0x19, 0x87, 0x22, 0x0f, - 0x42, 0x05, 0x00, 0x00, 0x4b, 0x86, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x46, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x43, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x4b, 0x86, 0x22, 0x07, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x42, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa1, - 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, - 0xc0, 0x06, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x54, 0x29, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5f, - 0x0f, 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x14, 0x80, 0xce, 0x01, 0x00, - 0x04, 0x00, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0x42, 0x00, 0x00, 0x03, - 0x0a, 0xc8, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00, - 0x10, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x14, 0x10, 0xc0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x08, - 0x10, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0xfe, 0x7f, 0x00, 0x05, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xa2, - 0x86, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xe4, 0xb1, 0x01, 0x00, - 0x79, 0x86, 0x22, 0x01, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, - 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x66, 0x86, 0xa3, 0x07, - 0x02, 0x6c, 0x00, 0x00, 0x67, 0x86, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x68, 0x07, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x02, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, - 0x73, 0x86, 0x22, 0x40, 0x03, 0x6c, 0x00, 0x00, 0x73, 0x86, 0x22, 0x42, - 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x99, 0x86, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x70, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x75, 0x86, 0xa8, 0x40, - 0x23, 0x30, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x99, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, - 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x7e, 0x86, 0xa3, 0x12, - 0x0e, 0x6c, 0x00, 0x00, 0x7f, 0x86, 0x60, 0x07, 0x1a, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x12, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x0d, - 0x16, 0x94, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00, - 0x14, 0x99, 0x00, 0x08, 0x98, 0x30, 0x01, 0x00, 0x00, 0x00, 0x68, 0x08, - 0x3e, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x87, 0x86, 0xa8, 0x5c, - 0x1f, 0x10, 0x00, 0x00, 0xb9, 0x86, 0x22, 0x0d, 0x14, 0x6c, 0x00, 0x00, - 0x8d, 0x86, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x10, 0xc0, 0x01, 0x00, 0x92, 0x86, 0x00, 0x0d, 0x24, 0xd0, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x2b, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x20, 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, - 0x25, 0x98, 0x01, 0x00, 0x94, 0x86, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, - 0x99, 0x86, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x95, 0x86, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0xb9, 0x86, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, 0xb8, 0x86, 0xa2, 0x0d, - 0x0e, 0x50, 0x00, 0x00, 0xa5, 0x86, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0xa3, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xa0, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, - 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf0, 0x0e, 0x30, 0x00, 0x00, 0xab, 0x86, 0xa2, 0x5f, - 0x0f, 0x7c, 0x00, 0x00, 0x60, 0x86, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0x60, 0x86, 0x23, 0x07, - 0x14, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0xb5, 0x86, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0x60, 0x86, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0x60, 0x86, 0x00, 0x0d, - 0x18, 0xc0, 0x00, 0x00, 0x04, 0x00, 0x2e, 0x14, 0x0a, 0xd0, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x05, 0x48, 0xcd, 0x01, 0x00, 0xfe, 0x7f, 0x00, 0x05, - 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xa4, 0x86, 0x06, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0xa1, 0x86, 0x06, 0x00, 0x00, 0x0c, 0x00, 0x2a, 0xf2, - 0xe0, 0xb1, 0x01, 0x00, 0xc1, 0x86, 0x22, 0x40, 0x31, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x81, 0x00, 0xf6, 0x80, 0xce, 0x01, 0x00, - 0xc5, 0x86, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x43, 0xc1, 0x01, 0x00, 0xc7, 0x86, 0x22, 0x0b, 0xed, 0x6d, 0x00, 0x00, - 0x08, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x00, 0xa1, - 0x46, 0xc9, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xa1, 0x86, 0x06, 0x00, 0x00, - 0x0f, 0x00, 0x00, 0xfa, 0x94, 0x88, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x45, - 0x95, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x4a, 0x86, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf6, 0x0e, 0xb0, 0x01, 0x00, 0xd1, 0x86, 0x22, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x1f, 0x43, 0x0e, 0x50, 0x00, 0x00, - 0xd1, 0x86, 0xa0, 0x46, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x0f, 0xc0, 0x01, 0x00, 0xd5, 0x86, 0x22, 0x48, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x0f, 0xa2, - 0x42, 0x31, 0x00, 0x00, 0xd8, 0x86, 0x00, 0x40, 0x89, 0xb0, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0xa2, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x95, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x82, 0xb0, 0x01, 0x00, 0xdb, 0x86, 0xa0, 0x41, - 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00, - 0xe0, 0x86, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0xe0, 0x86, 0xa0, 0x43, - 0x89, 0x6c, 0x00, 0x00, 0xe0, 0x86, 0x20, 0x45, 0x89, 0x6c, 0x00, 0x00, - 0xe0, 0x86, 0xa0, 0x41, 0x0e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x0f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xc0, 0x01, 0x00, - 0xd8, 0x86, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, 0xed, 0x86, 0x22, 0x48, - 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x48, 0x92, 0xf4, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x48, 0x90, 0x88, 0x01, 0x00, 0xe7, 0x86, 0x90, 0x48, - 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, - 0x0a, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, - 0x93, 0xa4, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x43, 0x80, 0xcc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa2, 0x80, 0xc0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, - 0x42, 0x6d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0xa1, 0x86, 0x06, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x46, 0x1f, 0x7c, 0x00, 0x00, 0x14, 0x99, 0x00, 0x17, - 0x98, 0x30, 0x01, 0x00, 0xff, 0x07, 0x00, 0x17, 0x7e, 0x89, 0x01, 0x00, - 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x12, 0x00, 0x00, 0x14, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x17, 0xf0, 0xb1, 0x01, 0x00, 0x12, 0x00, 0x00, 0x05, - 0xe0, 0xcd, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, - 0x62, 0xdd, 0x01, 0x00, 0xf7, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x02, 0x87, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, - 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, - 0x01, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xfe, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x05, 0x87, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x06, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x85, 0x87, 0x00, 0x17, 0x10, 0xb0, 0x00, 0x00, - 0x0d, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x09, 0x87, 0xa0, 0x07, 0x16, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, - 0x0d, 0x87, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x14, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2a, 0x94, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x17, 0x87, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x14, 0x87, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00, 0x85, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x21, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x21, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x1e, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x26, 0x87, 0x22, 0x07, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x42, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa1, - 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, - 0x04, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0xe0, 0xb1, 0x01, 0x00, 0x2b, 0x87, 0x22, 0x40, 0x31, 0x6c, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x18, - 0x38, 0x96, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x30, 0x87, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x52, - 0x11, 0xc0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, - 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, - 0x15, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0x3f, 0x87, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00, - 0x40, 0x87, 0x68, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, - 0x1a, 0xb0, 0x01, 0x00, 0x14, 0x99, 0x00, 0x08, 0x98, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x08, 0x3e, 0x96, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x47, 0x87, 0xa8, 0x5c, - 0x1f, 0x10, 0x00, 0x00, 0x79, 0x87, 0x22, 0x0d, 0x14, 0x6c, 0x00, 0x00, - 0x4d, 0x87, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x10, 0xc0, 0x01, 0x00, 0x52, 0x87, 0x00, 0x0d, 0x24, 0xd0, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x2b, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x20, 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, - 0x25, 0x98, 0x01, 0x00, 0x54, 0x87, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, - 0x59, 0x87, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x55, 0x87, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, 0x78, 0x87, 0xa2, 0x0d, - 0x0e, 0x50, 0x00, 0x00, 0x65, 0x87, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x63, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x60, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, - 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf0, 0x0e, 0x30, 0x00, 0x00, 0x6b, 0x87, 0xa2, 0x5f, - 0x0f, 0x7c, 0x00, 0x00, 0x39, 0x87, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0x39, 0x87, 0x23, 0x07, - 0x14, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x75, 0x87, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0x39, 0x87, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0x39, 0x87, 0x00, 0x0d, - 0x18, 0xc0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x83, 0x87, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x83, 0x87, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x80, 0x87, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x17, 0x10, 0xb0, 0x01, 0x00, 0x85, 0x87, 0x00, 0x40, - 0x2b, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x04, 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa0, 0x9f, 0x13, 0x6c, 0x00, 0x00, - 0x8c, 0x87, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88, - 0x1c, 0xcc, 0x01, 0x00, 0x27, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x8d, 0x98, 0x00, 0x41, 0x3f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x78, 0x98, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x03, 0x88, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x0e, 0xf4, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x01, 0x84, 0x01, 0x00, - 0x98, 0x87, 0x22, 0x50, 0x01, 0x6c, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x12, 0x95, 0x00, 0x07, - 0x16, 0x30, 0x01, 0x00, 0xa3, 0x87, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, - 0x9e, 0x87, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xa2, 0x87, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0x0e, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0xed, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0xb0, 0x87, 0xa2, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b, - 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x6a, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xb0, 0x87, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00, - 0xad, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x87, 0x95, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, - 0xc2, 0x97, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x01, 0x00, - 0xa1, 0x88, 0xa2, 0x5f, 0x81, 0x6c, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x43, - 0x19, 0x80, 0x01, 0x00, 0x37, 0x00, 0x2d, 0xf0, 0x24, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xf3, 0x8e, 0xf4, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, - 0x90, 0x88, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x43, 0x8f, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0xa3, 0x43, 0x91, 0x6c, 0x00, 0x00, 0xc1, 0x87, 0x22, 0x48, - 0x8e, 0x6c, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xc1, 0x87, 0x1f, 0xf0, - 0x24, 0x6c, 0x00, 0x00, 0xc0, 0x87, 0x23, 0x41, 0x8f, 0x6c, 0x00, 0x00, - 0xa1, 0x88, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x48, - 0x81, 0xb0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xb0, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00, 0xc6, 0x87, 0x22, 0x0a, - 0x90, 0x40, 0x00, 0x00, 0x58, 0x98, 0x00, 0x40, 0x91, 0x30, 0x01, 0x00, - 0xa1, 0x88, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0xb0, 0x00, 0x2d, 0x45, - 0x81, 0xb0, 0x01, 0x00, 0xd2, 0x87, 0x22, 0xf0, 0x2c, 0x30, 0x00, 0x00, - 0xa3, 0x00, 0x2d, 0x30, 0x83, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0xf3, - 0x82, 0xe0, 0x01, 0x00, 0xcc, 0x87, 0xa3, 0x41, 0x2c, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x16, 0x82, 0xb0, 0x01, 0x00, 0x98, 0x00, 0x2d, 0xf0, - 0x82, 0xc0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, 0x82, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x98, 0xe8, 0x01, 0x00, 0xa1, 0x88, 0x20, 0x4c, - 0x82, 0x6c, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0x41, 0x98, 0xe8, 0x01, 0x00, - 0xa1, 0x88, 0x20, 0xf0, 0x98, 0x6c, 0x00, 0x00, 0xed, 0x87, 0x22, 0x0a, - 0x80, 0x32, 0x00, 0x00, 0x40, 0x02, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00, - 0xed, 0x87, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xa1, 0x88, 0x00, 0x49, - 0x81, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, - 0xda, 0x87, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, 0x13, 0x80, 0x00, 0x40, - 0x80, 0xdc, 0x01, 0x00, 0xdb, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x1a, 0x80, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0xdb, 0x87, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0xb1, 0x01, 0x00, - 0xdd, 0x87, 0x9f, 0x85, 0x80, 0x32, 0x00, 0x00, 0xe1, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x1a, 0x83, 0x22, 0x40, 0x57, 0x7d, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x40, 0x57, 0x99, 0x01, 0x00, 0xe1, 0x87, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x01, 0x83, 0x1a, 0x5b, 0x69, 0x93, 0x00, 0x00, 0xe7, 0x87, 0x22, 0x46, - 0xf3, 0x7f, 0x00, 0x00, 0xe7, 0x87, 0xa2, 0x41, 0xf3, 0x7f, 0x00, 0x00, - 0xc6, 0x80, 0x00, 0x42, 0x97, 0x33, 0x01, 0x00, 0x04, 0x00, 0x00, 0xcb, - 0x81, 0xc8, 0x01, 0x00, 0xea, 0x87, 0x22, 0x40, 0xf2, 0x7f, 0x00, 0x00, - 0xc6, 0x80, 0x00, 0x6f, 0x97, 0x33, 0x01, 0x00, 0xec, 0x87, 0x22, 0x40, - 0x73, 0x7d, 0x00, 0x00, 0xe0, 0x80, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, - 0xe4, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x87, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xf4, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xf1, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x2e, 0x94, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, - 0xf5, 0x87, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x93, 0x93, 0x01, 0x00, 0x2e, 0x94, 0x1a, 0x02, 0x68, 0x97, 0x00, 0x00, - 0xff, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0xff, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xfc, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x3e, 0x94, 0x22, 0x02, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x88, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x3e, 0x94, 0x1a, 0x02, - 0x68, 0x97, 0x00, 0x00, 0x0a, 0x88, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x0a, 0x88, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x07, 0x88, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x2f, 0x83, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, 0x0b, 0x88, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40, - 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00, - 0x56, 0x95, 0x2f, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, - 0xe7, 0x6d, 0x00, 0x00, 0xb8, 0x94, 0x29, 0x41, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x0e, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x0c, 0x55, 0x6f, 0x00, 0x00, - 0x29, 0x00, 0x00, 0x40, 0x0d, 0x98, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x12, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, - 0x16, 0x88, 0x01, 0x00, 0xff, 0xff, 0x00, 0x10, 0x34, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x34, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x23, 0xb0, 0x01, 0x00, 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, - 0x04, 0x00, 0x20, 0xaa, 0x0f, 0x6c, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d, - 0x42, 0xc9, 0x01, 0x00, 0x43, 0x88, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x22, 0x88, 0x60, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07, - 0x84, 0x89, 0x01, 0x00, 0x2b, 0x88, 0x05, 0xc2, 0x24, 0x30, 0x00, 0x00, - 0x58, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x60, 0x88, 0x70, 0xf0, 0x18, 0x30, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x0c, 0x82, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x41, - 0x0e, 0x6c, 0x00, 0x00, 0x43, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x70, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x3a, 0x88, 0xa0, 0x48, - 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x1a, 0x42, 0xc9, 0x01, 0x00, 0x34, 0x88, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00, 0x31, 0x88, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x60, 0x88, 0x00, 0xf8, - 0x18, 0x30, 0x01, 0x00, 0x35, 0x88, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x10, 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x34, 0x94, 0x01, 0x00, 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x1a, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x1a, - 0x62, 0xdd, 0x01, 0x00, 0x3e, 0x88, 0xa8, 0x09, 0xe0, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x35, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x11, 0xc0, 0x01, 0x00, - 0x4f, 0x88, 0x22, 0x41, 0x0d, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x0f, 0xc0, 0x01, 0x00, 0x4b, 0x88, 0xa0, 0xaa, 0x0f, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x0f, 0xb0, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x12, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x1b, 0xb0, 0x01, 0x00, 0x1f, 0x88, 0x00, 0x41, - 0x17, 0xb0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x12, 0xc8, 0x01, 0x00, - 0x1f, 0x88, 0x83, 0x41, 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x17, 0xb0, 0x01, 0x00, 0x1f, 0x88, 0x00, 0x41, 0x1b, 0xc0, 0x00, 0x00, - 0x5a, 0x88, 0x23, 0x40, 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x35, 0xd0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x1a, 0x42, 0xc9, 0x01, 0x00, - 0x57, 0x88, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00, - 0x54, 0x88, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x60, 0x88, 0x00, 0xf8, 0x18, 0x30, 0x01, 0x00, 0x58, 0x88, 0xa2, 0x41, - 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00, - 0x5d, 0x88, 0xa0, 0xaa, 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x0f, 0xb0, 0x01, 0x00, 0xb8, 0x94, 0x20, 0x07, 0xe4, 0xb1, 0x01, 0x00, - 0x56, 0x95, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, - 0x0f, 0xb0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x80, 0xd8, 0x01, 0x00, - 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x0c, - 0x7e, 0x89, 0x01, 0x00, 0x79, 0x88, 0x26, 0x54, 0x61, 0x31, 0x00, 0x00, - 0x6c, 0x88, 0x87, 0x0c, 0x80, 0x32, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x0c, 0x8a, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x40, - 0x62, 0x99, 0x01, 0x00, 0x6c, 0x88, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, 0x68, 0x88, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x74, 0x88, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00, - 0x2a, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x0c, - 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, - 0x0d, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, - 0x6d, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x79, 0x88, 0x22, 0x49, - 0x19, 0x7c, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54, - 0x77, 0x7d, 0x00, 0x00, 0x74, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, - 0x79, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x94, 0x2f, 0x55, - 0xf1, 0x93, 0x01, 0x00, 0x00, 0x40, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00, - 0x2f, 0x83, 0xa2, 0x41, 0xe5, 0x51, 0x00, 0x00, 0x64, 0x00, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x81, 0x88, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x84, 0x88, 0xa2, 0x93, 0x57, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x57, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x1c, 0xab, 0x27, 0xb3, 0x01, 0x00, - 0x2f, 0x83, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x2f, 0x83, 0x22, 0x51, - 0xfd, 0x7f, 0x00, 0x00, 0x2f, 0x83, 0xa2, 0x41, 0x1d, 0x53, 0x00, 0x00, - 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0x90, 0x88, 0x22, 0x40, - 0xb5, 0x6f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x41, 0xb5, 0x53, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00, - 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x40, 0x05, 0x00, 0x40, - 0x49, 0x31, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00, 0x60, 0x16, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0x55, 0x82, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4a, - 0xb4, 0x8b, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4a, - 0xb4, 0xf7, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2f, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0xf2, 0x0e, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x02, - 0x80, 0x32, 0x00, 0x00, 0x05, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00, 0xab, 0x88, 0x22, 0x50, - 0x81, 0x6c, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x40, 0x8a, 0xe4, 0x01, 0x00, 0x02, 0x99, 0x00, 0x04, - 0x8a, 0x14, 0x01, 0x00, 0x04, 0x00, 0x20, 0x48, 0x09, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0x20, 0x57, 0x81, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x20, 0x40, - 0xe6, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00, 0xb1, 0x88, 0x00, 0x4b, - 0x10, 0xc9, 0x00, 0x00, 0xe1, 0x8b, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x16, 0x8c, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x52, 0x8c, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x52, 0x8c, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x52, 0x8c, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x52, 0x8c, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x99, 0x8c, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0xc8, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0xcc, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x3b, 0x8e, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdc, 0x8c, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0xda, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x95, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x95, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x95, 0x8d, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xb5, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8d, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8d, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xdd, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x0c, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xdd, 0x8b, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x1f, 0x8e, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x1f, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x21, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x21, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x21, 0x8e, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x21, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x2c, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x3e, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x2d, 0x8e, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x3e, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x40, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x34, 0x8e, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xdd, 0x8b, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x93, 0x8d, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x93, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x93, 0x8d, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, - 0x42, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x42, 0x8e, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x42, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0xdd, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x49, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x4b, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x58, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xbe, 0x8e, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x3b, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xc6, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x8c, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x3b, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xda, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x93, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xc2, 0x8e, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0xcc, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x3b, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x02, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf2, - 0x0e, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x02, 0x80, 0x32, 0x00, 0x00, - 0x07, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x08, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x47, 0x8a, 0xe4, 0x01, 0x00, 0x02, 0x99, 0x00, 0x04, - 0x8a, 0x14, 0x01, 0x00, 0x04, 0x00, 0x20, 0x4e, 0x09, 0x6c, 0x00, 0x00, - 0x2a, 0x00, 0x00, 0x47, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0x24, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x06, 0x00, 0x20, 0x47, 0xe6, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x47, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x96, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00, 0x7a, 0x89, 0x00, 0x4b, - 0x10, 0xc9, 0x00, 0x00, 0xf6, 0x8e, 0x00, 0x49, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x2f, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x36, 0x8f, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x47, 0x8f, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x6a, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x64, 0x8f, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x71, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xdc, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xda, 0x8f, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x41, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x3a, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x3a, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x3a, 0x8f, 0x00, 0x49, 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, - 0x3a, 0x8f, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x4d, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x45, 0x90, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x4b, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x62, 0x90, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x53, 0x90, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x0f, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x6a, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x47, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x64, 0x8f, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xdc, 0x8f, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x71, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x81, 0x90, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x81, 0x90, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0xc6, 0x8b, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0xc6, 0x8b, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x81, 0x90, 0x00, 0x4b, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x3a, 0x8f, 0x00, 0x41, - 0x09, 0xb0, 0x00, 0x00, 0xac, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xac, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xbb, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0xbb, 0x90, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x91, 0x00, 0x40, - 0x09, 0xb0, 0x00, 0x00, 0x4e, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x40, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x87, 0x90, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x87, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x4e, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x57, 0x91, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x57, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x40, 0x91, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x87, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x87, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x40, 0x91, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x45, 0x90, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x45, 0x90, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xab, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x9d, 0x90, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x8e, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x8e, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xab, 0x90, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xc6, 0x8b, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0xc6, 0x8b, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x9d, 0x90, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x8e, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x8e, 0x90, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x9d, 0x90, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x5a, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x5a, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x5a, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, - 0x5a, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x77, 0x91, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x77, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x96, 0x92, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x96, 0x92, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x96, 0x92, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xbf, 0x92, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xbd, 0x92, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xbf, 0x92, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xbd, 0x92, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x67, 0x91, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x74, 0x91, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x4b, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x74, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x74, 0x91, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x91, 0x00, 0x4c, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x62, 0x90, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x53, 0x90, 0x00, 0x4c, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7d, 0x93, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x93, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x93, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x93, 0x00, 0x4b, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x93, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x93, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x93, 0x00, 0x4c, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x53, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x0f, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x53, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x0f, 0x93, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x0f, 0x93, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x16, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x6e, 0x93, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x16, 0x93, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xfd, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x2c, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xfd, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x44, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x44, 0x93, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x44, 0x93, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x47, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x6a, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x67, 0x93, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x6a, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x47, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x67, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x6e, 0x93, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x7a, 0x90, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x6e, 0x93, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x10, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x10, 0x93, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x7a, 0x90, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x10, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x10, 0x93, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x77, 0x93, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xfd, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x77, 0x93, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x62, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xfd, 0x92, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x71, 0x8f, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x71, 0x8f, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x62, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00, 0x07, 0x00, 0x2e, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0xf8, 0x87, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00, - 0xc6, 0x8b, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x09, 0x97, 0x00, 0x3a, - 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xc6, 0x8b, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x0f, - 0x1e, 0x8c, 0x01, 0x00, 0x6d, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd8, 0x8b, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xd8, 0x8b, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xd5, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x1a, 0x85, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, - 0xd9, 0x8b, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00, - 0x1a, 0x85, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00, - 0x05, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00, 0xf8, 0x87, 0x00, 0x04, - 0xe6, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0xa1, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb1, 0x01, 0x00, 0x78, 0x98, 0x00, 0x06, - 0x07, 0x40, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x07, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x2e, 0x5c, - 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xb1, 0x01, 0x00, - 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x96, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x4b, - 0x94, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x95, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x96, 0xc0, 0x01, 0x00, 0x5e, 0x01, 0x2e, 0x34, - 0x97, 0x84, 0x01, 0x00, 0x02, 0x00, 0x00, 0x4b, 0xe4, 0xe5, 0x01, 0x00, - 0x64, 0x01, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00, - 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x05, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x08, 0x00, 0x2e, 0x40, 0x95, 0xb0, 0x01, 0x00, 0x0d, 0x8c, 0x20, 0x4b, - 0x94, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x0a, 0x8c, 0x00, 0x41, 0x95, 0xc0, 0x00, 0x00, 0x10, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x14, 0x8c, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x10, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x09, 0x97, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00, - 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x86, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x88, 0xb0, 0x01, 0x00, 0x14, 0x80, 0x00, 0x03, - 0x98, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xa1, 0x98, 0x6c, 0x00, 0x00, - 0x1b, 0x8c, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, 0x1e, 0x8c, 0xa2, 0x4c, - 0xfd, 0x7f, 0x00, 0x00, 0x1f, 0x8c, 0x00, 0x4c, 0xfd, 0x93, 0x00, 0x00, - 0x20, 0x8c, 0x20, 0xf0, 0x56, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x56, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x64, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40, - 0x80, 0xcc, 0x01, 0x00, 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xd8, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x43, - 0x81, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x64, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x70, 0x00, 0x00, 0x05, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x2b, 0x8c, 0xa8, 0x44, 0xe0, 0x31, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x46, - 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x68, 0x01, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x00, 0x43, - 0xf0, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x24, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x62, 0xb1, 0x01, 0x00, 0x34, 0x8c, 0xa8, 0x44, 0xe0, 0x31, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x86, 0xe4, 0x01, 0x00, 0x38, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00, - 0x8b, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x3c, 0x8c, 0x22, 0x43, - 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, - 0x3f, 0x8c, 0x22, 0x44, 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x45, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x19, 0x90, 0x01, 0x00, - 0x68, 0x01, 0x20, 0xa2, 0xe4, 0xb1, 0x01, 0x00, 0x88, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x43, 0x8c, 0x23, 0x0b, 0xe5, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x19, 0x90, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x58, 0x01, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x48, 0x8c, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x5c, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x96, 0xb0, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf2, - 0x80, 0x32, 0x00, 0x00, 0x09, 0x97, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00, - 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x55, 0x8c, 0xa2, 0x49, - 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x59, 0x8c, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00, 0x86, 0x00, 0x2f, 0x49, - 0x19, 0x80, 0x01, 0x00, 0x59, 0x8c, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00, - 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xe7, 0x91, 0x01, 0x00, 0x5c, 0x8c, 0xa2, 0x46, 0x19, 0x7c, 0x00, 0x00, - 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x60, 0x8c, 0x00, 0x40, - 0xe5, 0xb1, 0x00, 0x00, 0xa0, 0x00, 0x2f, 0x46, 0x19, 0x80, 0x01, 0x00, - 0x60, 0x8c, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe7, 0x91, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x4e, 0x80, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x40, - 0x80, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x40, 0x06, 0x6c, 0x00, 0x00, - 0xa8, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x34, 0x00, 0x2d, 0xf0, - 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x0c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfb, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, - 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, 0x16, 0x88, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xf3, 0x14, 0xf4, 0x01, 0x00, 0x90, 0x8c, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x76, 0x8c, 0x22, 0x0a, 0x16, 0x6c, 0x00, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00, - 0x15, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x13, 0xc0, 0x01, 0x00, 0x75, 0x8c, 0xa0, 0x43, - 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x13, 0xb0, 0x01, 0x00, - 0x6b, 0x8c, 0x00, 0x41, 0x15, 0xd0, 0x00, 0x00, 0x90, 0x8c, 0x22, 0x0a, - 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x08, 0x12, 0x6c, 0x00, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00, - 0x15, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x90, 0x8c, 0x22, 0x41, - 0x15, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x11, 0xc0, 0x01, 0x00, - 0x83, 0x8c, 0xa0, 0x43, 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x11, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x06, 0x10, 0x6c, 0x00, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0x11, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x36, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x00, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0x4e, 0x97, 0x00, 0x47, - 0x61, 0x31, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x2b, 0x94, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x8c, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x7f, 0x8c, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x37, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x80, 0x97, 0x00, 0x51, - 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf3, - 0x80, 0x32, 0x00, 0x00, 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, - 0x00, 0x11, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x48, - 0x19, 0x7c, 0x00, 0x00, 0x9d, 0x8c, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf3, - 0x80, 0x32, 0x00, 0x00, 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, - 0x00, 0x11, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, - 0xa4, 0x8c, 0x22, 0x45, 0x23, 0x7c, 0x00, 0x00, 0xb0, 0x00, 0x2f, 0xf0, - 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00, - 0x7c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa3, 0xf0, - 0x8c, 0x6c, 0x00, 0x00, 0x90, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x35, 0x00, 0x2d, 0xf0, 0x8c, 0xb0, 0x01, 0x00, 0x34, 0x00, 0x2d, 0xf3, - 0x84, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf3, 0x84, 0x6c, 0x00, 0x00, - 0x58, 0x00, 0x3e, 0x43, 0x85, 0xe0, 0x01, 0x00, 0xab, 0x8c, 0x22, 0x48, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x68, 0x0a, 0x8c, 0xc0, 0x01, 0x00, 0x38, 0x00, 0x2a, 0x4a, - 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, - 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x38, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x26, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8, - 0x02, 0x30, 0x00, 0x00, 0xb9, 0x8c, 0x23, 0x01, 0x14, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x82, 0xb0, 0x01, 0x00, 0x4c, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00, - 0x44, 0x00, 0x20, 0x40, 0xe0, 0xb1, 0x01, 0x00, 0x48, 0x00, 0x20, 0x41, - 0xe0, 0xb1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x58, 0x98, 0x00, 0xf0, 0x24, 0x30, 0x01, 0x00, 0xc2, 0x8c, 0xa2, 0x44, - 0x81, 0x6c, 0x00, 0x00, 0xc0, 0x8c, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xb6, 0x95, 0x00, 0x40, 0x3b, 0x30, 0x01, 0x00, 0xea, 0x8c, 0xa2, 0x08, - 0x3c, 0x30, 0x00, 0x00, 0xc2, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xea, 0x8c, 0xa2, 0x08, - 0x3c, 0x30, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01, - 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, - 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x8f, 0x95, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x9d, 0x8c, 0x22, 0x4a, - 0x80, 0x32, 0x00, 0x00, 0xce, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x8f, 0x95, 0x00, 0xf3, - 0x94, 0x30, 0x01, 0x00, 0x04, 0x00, 0x20, 0x43, 0x97, 0x6c, 0x00, 0x00, - 0x58, 0x00, 0x3e, 0x43, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0xf0, 0xb1, 0x01, 0x00, 0x1f, 0x00, 0x60, 0x00, 0x00, 0x8c, 0x01, 0x00, - 0xdd, 0x8b, 0x85, 0x11, 0x80, 0x32, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0xf0, 0x8c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa3, 0xf0, 0x8c, 0x6c, 0x00, 0x00, - 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x49, 0x19, 0x7c, 0x00, 0x00, - 0xdc, 0x8c, 0x00, 0x49, 0x19, 0x80, 0x00, 0x00, 0xe1, 0x8c, 0x22, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0xb6, 0x95, 0x00, 0x40, 0x3b, 0x30, 0x01, 0x00, - 0xe5, 0x8c, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x5f, - 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xe5, 0x8c, 0xa2, 0x08, - 0x3c, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, - 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x50, 0x00, 0x2d, 0x10, - 0x32, 0xb0, 0x01, 0x00, 0x54, 0x00, 0x2d, 0xf0, 0x38, 0xb0, 0x01, 0x00, - 0x4e, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x2d, 0xf2, - 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x14, 0xb0, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x46, - 0x44, 0xc9, 0x01, 0x00, 0x68, 0x01, 0x2d, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x68, 0xf2, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x37, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x36, 0xd0, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0x40, 0x10, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, - 0x81, 0xd0, 0x01, 0x00, 0x12, 0x97, 0x00, 0x40, 0xe4, 0x31, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x46, 0x62, 0xdd, 0x01, 0x00, 0xf6, 0x8c, 0xa8, 0x40, - 0x23, 0x30, 0x00, 0x00, 0x08, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x10, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x8d, 0x82, 0x41, - 0x23, 0x40, 0x00, 0x00, 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0x01, 0x8d, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xfe, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x23, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, - 0x0c, 0x8d, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x08, 0x8d, 0xa3, 0x01, - 0x0c, 0x6c, 0x00, 0x00, 0x09, 0x8d, 0x00, 0x06, 0x04, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x04, 0xb0, 0x01, 0x00, 0x0b, 0x8d, 0x20, 0x02, - 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x04, 0xb0, 0x01, 0x00, - 0x0f, 0x8d, 0x00, 0x02, 0xe0, 0xb1, 0x00, 0x00, 0x0e, 0x8d, 0xa3, 0x01, - 0x0c, 0x6c, 0x00, 0x00, 0x0f, 0x8d, 0x00, 0x06, 0x04, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x02, - 0x16, 0x94, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0x68, 0x08, 0x3e, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0x14, 0x8d, 0xa8, 0x13, - 0xe0, 0x31, 0x00, 0x00, 0x51, 0x8d, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, - 0x44, 0x00, 0x2d, 0x02, 0x0c, 0xd0, 0x01, 0x00, 0x3c, 0x8d, 0xa2, 0x02, - 0x02, 0x50, 0x00, 0x00, 0x22, 0x8d, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x21, 0x8d, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x1d, 0x8d, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x44, 0x00, 0x2d, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x48, 0x00, 0x2d, 0xf0, 0x38, 0xb0, 0x01, 0x00, - 0x4c, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, 0x38, 0x00, 0x2f, 0xf2, - 0x02, 0xb0, 0x01, 0x00, 0x3e, 0x8d, 0x22, 0x01, 0x14, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x8d, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, - 0x20, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x2f, 0x8d, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x2c, 0x8d, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x38, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x94, 0xb0, 0x01, 0x00, 0x38, 0x00, 0x2d, 0xf0, 0x96, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0xe1, 0xc1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x22, 0x4a, 0xf1, 0xb1, 0x01, 0x00, - 0x44, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x39, 0x8d, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, - 0x3e, 0x8d, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x38, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x24, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x4c, 0x8d, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x33, 0xc0, 0x01, 0x00, 0x4a, 0x8d, 0xa2, 0x02, 0x36, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x8f, 0x0d, - 0x42, 0x31, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x80, 0x32, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x5c, 0xe1, 0x7d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0xf0, - 0x6a, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf8, 0x10, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x11, 0x80, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, - 0x37, 0x98, 0x01, 0x00, 0xfa, 0x8c, 0x00, 0xa1, 0x1a, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, 0xfa, 0x8c, 0x00, 0x02, - 0x36, 0xd0, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01, - 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, - 0x58, 0x8d, 0x00, 0x5f, 0x01, 0xb0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x02, - 0x02, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x02, 0x0c, 0x6c, 0x00, 0x00, - 0x37, 0x00, 0x2d, 0x46, 0x01, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, - 0x80, 0xf4, 0x01, 0x00, 0x57, 0x8d, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x01, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, - 0x5e, 0x8d, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, - 0x5b, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x0d, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x65, 0x8d, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x62, 0x8d, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x60, 0x01, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, - 0x6a, 0x8d, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, - 0x32, 0x00, 0x00, 0xa6, 0x2a, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x2a, 0x94, 0x01, 0x00, 0x6d, 0x8d, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00, - 0x00, 0xd0, 0x00, 0x1e, 0x62, 0xdd, 0x01, 0x00, 0x72, 0x8d, 0x28, 0x40, - 0x05, 0x30, 0x00, 0x00, 0x6e, 0x8d, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00, - 0x75, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x62, 0xb1, 0x01, 0x00, 0x80, 0x8d, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x72, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, - 0x92, 0xb0, 0x01, 0x00, 0x7d, 0x8d, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa3, 0x48, - 0x3b, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0xc3, 0x94, 0x00, 0xf8, 0x00, 0x30, 0x01, 0x00, 0x7a, 0x8d, 0xa2, 0x41, - 0x3b, 0x50, 0x00, 0x00, 0x81, 0x8d, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00, - 0xff, 0x07, 0x00, 0x1e, 0x00, 0x8c, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x81, 0x8d, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x1d, 0x47, 0x19, 0x80, 0x01, 0x00, 0x84, 0x8d, 0x22, 0x5f, - 0x01, 0x6c, 0x00, 0x00, 0x87, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xa7, 0x88, 0x00, 0x00, 0x80, 0xb0, 0x00, 0x00, 0x8b, 0x8d, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x8b, 0x8d, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x88, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x8b, 0x8d, 0x40, 0x05, 0x48, 0x31, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x07, 0x94, 0x89, 0x01, 0x00, 0x91, 0x8d, 0x85, 0xca, - 0x94, 0x30, 0x00, 0x00, 0x87, 0x98, 0x18, 0x5c, 0x1f, 0x00, 0x01, 0x00, - 0x0e, 0x00, 0x00, 0x0f, 0x1e, 0x8c, 0x01, 0x00, 0xb4, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x80, 0x97, 0x18, 0x00, 0x80, 0x30, 0x01, 0x00, - 0xdd, 0x8b, 0x00, 0x47, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x19, 0x80, 0x01, 0x00, 0xdd, 0x8b, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00, - 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x98, 0x8d, 0xa2, 0x08, - 0x80, 0x32, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x12, 0x97, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00, 0x9c, 0x01, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00, - 0x8b, 0x00, 0x2d, 0x50, 0x17, 0xf0, 0x01, 0x00, 0x9e, 0x8d, 0x90, 0x4c, - 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0xa0, 0x8d, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x45, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, - 0x68, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2, - 0x80, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x62, 0x40, 0x7e, 0xcd, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x57, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40, 0xf0, 0x8d, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xaa, 0x8d, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xae, 0x8d, 0x45, 0x48, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x50, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, - 0xb4, 0x8d, 0x28, 0x40, 0x05, 0x30, 0x00, 0x00, 0xaf, 0x8d, 0x22, 0x48, - 0x77, 0x7d, 0x00, 0x00, 0xc3, 0x94, 0x1d, 0x08, 0x00, 0x30, 0x01, 0x00, - 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xdd, 0x8b, 0x1d, 0x47, - 0x19, 0x80, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x35, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, - 0x84, 0xc8, 0x01, 0x00, 0xba, 0x8d, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xa8, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf3, 0x9e, 0x06, 0x00, 0x00, 0x01, 0x00, 0x63, 0xf3, - 0x82, 0xcc, 0x01, 0x00, 0xc8, 0x8d, 0xa2, 0x41, 0x9e, 0x06, 0x00, 0x00, - 0xdd, 0x8b, 0x22, 0x44, 0x83, 0x70, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, 0x24, 0x6c, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, - 0xe7, 0xe1, 0x01, 0x00, 0xdd, 0x8b, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00, - 0x87, 0x98, 0x00, 0x48, 0x81, 0x30, 0x01, 0x00, 0xa7, 0x88, 0x23, 0x41, - 0x83, 0x6c, 0x00, 0x00, 0xa7, 0x88, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0x42, - 0xe6, 0x6d, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x85, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x00, 0xbe, 0x06, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x4e, 0x97, 0x00, 0x47, 0x61, 0x31, 0x01, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x8e, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, - 0x14, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xa5, 0x8c, 0xa2, 0x40, 0x8f, 0x7c, 0x00, 0x00, 0xdb, 0x8d, 0x22, 0x47, - 0x8f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x48, 0x19, 0x7c, 0x00, 0x00, - 0xa5, 0x8c, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00, 0x04, 0x00, 0x22, 0x46, - 0x8f, 0x7c, 0x00, 0x00, 0x5d, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x5d, - 0x05, 0xb4, 0x01, 0x00, 0x37, 0x00, 0x2d, 0xf3, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x8e, 0xb0, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x47, - 0x7e, 0x89, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x5c, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0, - 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x86, 0xdc, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x8c, 0x93, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x36, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0xef, 0x8d, 0xa2, 0x50, 0x8f, 0x50, 0x00, 0x00, 0x34, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xf0, 0x00, 0x00, 0x47, 0x7e, 0x89, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x63, 0x41, 0x81, 0xc0, 0x01, 0x00, - 0xf4, 0x8d, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x63, 0x40, - 0x81, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x20, 0x47, 0xe6, 0xb1, 0x01, 0x00, - 0xdd, 0x8b, 0x22, 0x47, 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x47, - 0x0c, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x8f, 0x84, 0x01, 0x00, - 0x09, 0x8e, 0x22, 0x47, 0x0c, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, - 0x81, 0xe0, 0x01, 0x00, 0x09, 0x8e, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x02, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xff, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x02, 0x8e, 0x42, 0x40, - 0x05, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x1a, 0x5d, 0x69, 0x93, 0x01, 0x00, 0x07, 0x8e, 0x23, 0x41, - 0x0d, 0x6c, 0x00, 0x00, 0xdd, 0x8d, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x87, 0x98, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0xa7, 0x88, 0x00, 0x48, - 0x81, 0xb0, 0x00, 0x00, 0xdd, 0x8b, 0x22, 0x40, 0x8f, 0x6c, 0x00, 0x00, - 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x40, 0x02, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00, - 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x84, 0xb0, 0x01, 0x00, - 0xa6, 0x00, 0x2d, 0x49, 0x19, 0x90, 0x01, 0x00, 0x02, 0x00, 0x00, 0xf2, - 0x80, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x82, 0xf8, 0x01, 0x00, 0x19, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0x1a, 0x8e, 0xa0, 0x40, 0x82, 0x6c, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0x1a, 0x8e, 0xa3, 0x40, 0x82, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x80, 0xb0, 0x01, 0x00, 0x1c, 0x8e, 0x20, 0x4c, - 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xc0, 0x01, 0x00, - 0x86, 0x00, 0x20, 0x40, 0xe4, 0xb1, 0x01, 0x00, 0xa2, 0x00, 0x20, 0x42, - 0xe6, 0xb1, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x09, 0x97, 0x00, 0x50, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf0, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0x78, 0x98, 0x00, 0x40, 0x87, 0x30, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0xb0, 0x00, 0x2f, 0x5c, - 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x80, 0xc0, 0x01, 0x00, - 0x7c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa3, 0xf0, - 0x80, 0x6c, 0x00, 0x00, 0x80, 0x97, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, - 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xdd, 0x8b, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00, - 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2, - 0x96, 0xcc, 0x01, 0x00, 0xdd, 0x8b, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x80, 0x97, 0x00, 0x4a, 0x81, 0x30, 0x01, 0x00, 0x55, 0x97, 0x00, 0x46, - 0x95, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xdd, 0x8b, 0x22, 0x49, 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2, 0x80, 0xcc, 0x01, 0x00, - 0xdd, 0x8b, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x80, 0x97, 0x00, 0x4a, - 0x81, 0x30, 0x01, 0x00, 0x55, 0x97, 0x00, 0x47, 0x95, 0x30, 0x01, 0x00, - 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2b, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0xdd, 0x8b, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x46, - 0x19, 0x7c, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x49, 0x19, 0x7c, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x62, 0xf2, 0x80, 0xc8, 0x01, 0x00, 0x46, 0x8e, 0x90, 0x40, - 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x62, 0x40, 0x81, 0x98, 0x01, 0x00, - 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xdd, 0x8b, 0x22, 0x40, - 0xe5, 0x6d, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x41, 0xe5, 0xc1, 0x00, 0x00, - 0x09, 0x97, 0x00, 0x4d, 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf0, 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0x78, 0x98, 0x00, 0x40, 0x87, 0x30, 0x01, 0x00, - 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x56, 0x8e, 0x80, 0xf3, - 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0x81, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0xdd, 0x8b, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf3, - 0x80, 0x32, 0x00, 0x00, 0x34, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x6e, 0x8e, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x51, 0x83, 0xd0, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x84, 0xcc, 0x01, 0x00, - 0x66, 0x8e, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x63, 0x42, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x68, 0x8e, 0x37, 0x5c, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00, - 0x69, 0x8e, 0xa8, 0x4b, 0x19, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x62, 0xb1, 0x01, 0x00, 0x6b, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xed, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, - 0xac, 0x00, 0x2d, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0x35, 0x00, 0x2d, 0xf0, - 0x28, 0xb0, 0x01, 0x00, 0x34, 0x00, 0x2d, 0xf3, 0x84, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf3, 0x84, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3e, 0x43, - 0x85, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x18, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x38, 0x00, 0x20, 0x00, - 0xe0, 0xb1, 0x01, 0x00, 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x2b, 0xb0, 0x01, 0x00, 0x64, 0x97, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x16, 0xc0, 0x01, 0x00, 0x7f, 0x8e, 0xa0, 0x14, - 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0xf8, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0x14, 0xf8, 0xb1, 0x01, 0x00, - 0x10, 0x50, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x88, 0x8e, 0x22, 0x4a, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43, 0x86, 0xc8, 0x01, 0x00, - 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00, 0x88, 0x8e, 0xa4, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x01, 0x00, 0x6e, 0x43, 0x86, 0x98, 0x01, 0x00, 0xa8, 0x97, 0x00, 0x30, - 0x81, 0x30, 0x01, 0x00, 0x8c, 0x8e, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x93, 0x8e, 0x22, 0x4a, - 0x19, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, - 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, - 0x17, 0xc0, 0x01, 0x00, 0x92, 0x8e, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x64, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x41, 0x31, 0xc0, 0x01, 0x00, 0xbc, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x99, 0x8e, 0x06, 0x0c, 0x80, 0x32, 0x00, 0x00, - 0xa0, 0x00, 0x20, 0xf2, 0xe4, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x09, 0x46, - 0x19, 0x10, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x50, - 0x17, 0xf0, 0x01, 0x00, 0x9e, 0x8e, 0x90, 0x4c, 0x16, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0xa0, 0x8e, 0x22, 0x43, - 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x68, 0x01, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2, 0x80, 0xb0, 0x01, 0x00, - 0x02, 0x00, 0x62, 0x40, 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, - 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x40, 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0xaa, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0xae, 0x8e, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0xaf, 0x8e, 0xa8, 0x40, - 0x05, 0x30, 0x00, 0x00, 0x35, 0x00, 0x1d, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x63, 0xf3, 0x84, 0xc8, 0x01, 0x00, 0xb5, 0x8e, 0xa0, 0x43, - 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, - 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf3, - 0x9e, 0x06, 0x00, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x41, 0x9e, 0x06, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x45, 0xe7, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0xe7, 0x91, 0x01, 0x00, 0x80, 0x97, 0x00, 0x5f, - 0x81, 0x30, 0x01, 0x00, 0xdd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x8f, 0x95, 0x00, 0xf3, - 0x94, 0x30, 0x01, 0x00, 0x5d, 0x8e, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00, - 0xce, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x8f, 0x95, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, - 0x97, 0x8c, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00, 0xce, 0x8c, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfb, 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, - 0x90, 0x88, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x0c, 0xf4, 0x01, 0x00, - 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc8, 0x8c, 0x22, 0x06, - 0x90, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x5c, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0, - 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00, - 0x37, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x2a, 0x50, - 0xe7, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x63, 0x41, 0x13, 0xc0, 0x01, 0x00, - 0xd5, 0x8e, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0x89, 0x93, 0x00, 0x10, 0x86, 0x30, 0x01, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xd7, 0x8e, 0x42, 0x05, - 0x48, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, - 0xc8, 0x8c, 0x1a, 0x5d, 0x69, 0x93, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x10, 0x86, 0xb0, 0x01, 0x00, - 0x5c, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0, - 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00, - 0x35, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x6b, 0xfb, - 0x84, 0xc8, 0x01, 0x00, 0xe4, 0x8e, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00, - 0x35, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x12, 0xc8, 0x01, 0x00, - 0xe7, 0x8e, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x8c, 0x93, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xea, 0x8e, 0x42, 0x05, 0x48, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x5d, - 0x69, 0x93, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf3, 0x9e, 0x06, 0x00, 0x00, 0x11, 0x00, 0x63, 0xf3, - 0x82, 0xcc, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x41, 0x80, 0x32, 0x00, 0x00, - 0xbf, 0x8d, 0x22, 0x41, 0x9e, 0x06, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0xcd, 0x8d, 0x00, 0xf0, - 0x00, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xf7, 0x8e, 0x65, 0xf2, 0x12, 0x30, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, - 0x13, 0xf0, 0x01, 0x00, 0xfc, 0x8e, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00, - 0x27, 0x83, 0x75, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xf6, 0x8e, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x75, 0x42, 0x19, 0x90, 0x01, 0x00, 0x75, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xfe, 0x8e, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00, - 0xa3, 0x96, 0x00, 0x10, 0x94, 0x30, 0x01, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x97, 0xb0, 0x01, 0x00, 0x08, 0x8f, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00, - 0x04, 0x00, 0x02, 0x41, 0x97, 0x40, 0x00, 0x00, 0x05, 0x8f, 0x00, 0x50, - 0x43, 0xc1, 0x00, 0x00, 0x14, 0x8f, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x62, 0x4b, 0x12, 0x94, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x97, 0xc0, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x94, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x4a, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf1, 0xb1, 0x01, 0x00, - 0x5e, 0x01, 0x00, 0x4b, 0xf0, 0xc9, 0x01, 0x00, 0x5e, 0x01, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x4a, 0x62, 0xdd, 0x01, 0x00, 0x12, 0x8f, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x09, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00, - 0xd4, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0x1a, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, - 0x1e, 0x8f, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, - 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x75, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, - 0x62, 0xb1, 0x01, 0x00, 0x22, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x27, 0x8f, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0x25, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x97, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x96, - 0x97, 0xb0, 0x01, 0x00, 0x2d, 0x8f, 0x20, 0x09, 0x96, 0x6c, 0x00, 0x00, - 0x2d, 0x8f, 0x1f, 0x09, 0x96, 0x24, 0x00, 0x00, 0x27, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x28, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x09, 0x97, 0x00, 0x57, 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x34, 0x8f, 0x22, 0xf3, - 0x80, 0x32, 0x00, 0x00, 0x09, 0x97, 0x00, 0x42, 0x81, 0x30, 0x01, 0x00, - 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x80, 0x97, 0x00, 0x52, - 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x42, 0x19, 0x80, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x09, 0x97, 0x00, 0x3a, - 0x81, 0x30, 0x01, 0x00, 0x80, 0x97, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00, - 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x05, 0xb0, 0x01, 0x00, 0xff, 0x95, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, - 0xc6, 0x8b, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00, 0x24, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x42, 0x8f, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x02, 0xb0, 0x01, 0x00, 0x9f, 0x95, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00, - 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0xed, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x25, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, - 0x4e, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x4e, 0x8f, 0xa2, 0x16, - 0x80, 0x32, 0x00, 0x00, 0xed, 0x87, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x09, 0x97, 0x00, 0x3a, - 0x81, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x23, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00, 0x51, 0x8f, 0x83, 0x1e, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2a, 0xc0, 0x01, 0x00, 0x58, 0x97, 0x00, 0x08, - 0x80, 0x30, 0x01, 0x00, 0x55, 0x8f, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, - 0x79, 0x97, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0x98, 0x93, 0x00, 0x40, - 0x8d, 0x30, 0x01, 0x00, 0x60, 0x97, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x5d, 0x8f, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x5a, 0x8f, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x61, 0x8f, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, - 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4a, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00, - 0x69, 0x8f, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x3d, 0x80, 0x01, 0x00, - 0x6a, 0x8f, 0x00, 0x42, 0x19, 0x90, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4f, - 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, - 0x14, 0x00, 0x2d, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, - 0x14, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa0, 0x01, 0x14, 0x6c, 0x00, 0x00, - 0xdc, 0x8f, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00, 0xdc, 0x8f, 0x00, 0x44, - 0x19, 0x90, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x47, 0xe7, 0x7d, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x84, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x84, 0x8f, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, 0x80, 0x8f, 0xa2, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, - 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41, - 0x89, 0x30, 0x01, 0x00, 0x7d, 0x8f, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00, - 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0xed, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x09, 0x97, 0x00, 0x3a, - 0x81, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x87, 0x8f, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x88, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xff, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc0, 0x8f, 0x22, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x15, 0x98, 0xc8, 0x01, 0x00, - 0xc0, 0x8f, 0xa0, 0x0b, 0x99, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x7e, 0x89, 0x01, 0x00, - 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, - 0x80, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x44, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0x93, 0x8f, 0xa8, 0x00, - 0xe0, 0x31, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x15, - 0x98, 0xc8, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x0b, 0x99, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x6a, 0x50, 0x99, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x0b, - 0x99, 0x6c, 0x00, 0x00, 0xc0, 0x00, 0x62, 0x01, 0x80, 0xcc, 0x01, 0x00, - 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x2d, 0x00, 0x2d, 0xf0, - 0x22, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x23, 0x80, 0x01, 0x00, 0xd4, 0x00, 0x3f, 0x41, - 0xe7, 0xe1, 0x01, 0x00, 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0xf2, 0x98, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, - 0x99, 0x80, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x00, 0x98, 0x6c, 0x00, 0x00, - 0x20, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x11, - 0x8a, 0x30, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x11, 0xe4, 0xf5, 0x01, 0x00, - 0x2f, 0x00, 0x20, 0x47, 0xe7, 0xb5, 0x01, 0x00, 0xab, 0x8f, 0x23, 0x0b, - 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0xe5, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x80, 0xb0, 0x01, 0x00, 0xc1, 0x00, 0x00, 0x01, - 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x02, 0xd0, 0x01, 0x00, 0x58, 0x97, 0x00, 0x00, 0x2a, 0x40, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xb2, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x05, - 0x48, 0x31, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x80, 0xce, 0x01, 0x00, - 0xbe, 0x8f, 0x26, 0x11, 0x00, 0x30, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x80, 0xc0, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, - 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x98, 0xd0, 0x01, 0x00, - 0x58, 0x97, 0x00, 0x4c, 0x02, 0x30, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, - 0x03, 0x98, 0x01, 0x00, 0xc8, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x30, 0x00, 0x2f, 0x08, 0x80, 0xb0, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x15, - 0xf4, 0xc9, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01, 0xe4, 0xcd, 0x01, 0x00, - 0xc1, 0x00, 0x00, 0x01, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xa4, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x20, 0x0b, 0xe5, 0x6d, 0x00, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00, 0x58, 0x97, 0x00, 0x00, - 0x2a, 0x40, 0x01, 0x00, 0xcd, 0x8f, 0x22, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0xac, 0x00, 0x2f, 0x40, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xe0, 0xc1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xce, 0x8f, 0x00, 0x01, 0xe0, 0xd1, 0x00, 0x00, 0x98, 0x93, 0x00, 0x40, - 0x8d, 0x30, 0x01, 0x00, 0x80, 0x63, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00, - 0x60, 0x97, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0xd6, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xd3, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xfa, 0x96, 0x00, 0x5e, - 0x05, 0x10, 0x01, 0x00, 0xd9, 0x8f, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, - 0x80, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00, - 0xdc, 0x8f, 0x00, 0x4a, 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4f, - 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0xb0, 0x01, 0x00, 0x24, 0x00, 0x2d, 0x15, 0x10, 0xc0, 0x01, 0x00, - 0x28, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, - 0x26, 0xb0, 0x01, 0x00, 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x32, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x1f, 0x15, 0x1a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2a, 0xb0, 0x01, 0x00, - 0xb8, 0x96, 0x00, 0x40, 0x35, 0xb0, 0x00, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0x26, 0x90, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x24, 0x00, 0x20, 0x0b, - 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, - 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00, 0xfa, 0x8f, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xfa, 0x8f, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xf6, 0x8f, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x14, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, 0x14, 0x6c, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0x1f, 0x90, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x0d, 0x90, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x6d, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x54, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x1a, 0x90, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x03, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x09, 0x90, 0x22, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0xe1, 0x94, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, - 0x0a, 0x90, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0c, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, - 0x80, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40, - 0x05, 0xb0, 0x00, 0x00, 0x6d, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x49, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x10, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x16, 0x90, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xe1, 0x94, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, 0x17, 0x90, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x19, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x1b, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x22, 0x90, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xe1, 0x94, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, 0x23, 0x90, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x25, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, - 0x14, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, - 0x2f, 0x90, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x2b, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x33, 0x90, 0x22, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0xe1, 0x94, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, - 0x34, 0x90, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x0a, 0x84, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x14, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x3a, 0x90, 0x03, 0x1e, 0x80, 0x32, 0x00, 0x00, 0x3b, 0x90, 0x00, 0x41, - 0x87, 0xb0, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x26, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0x40, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x43, 0x90, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, - 0x80, 0x97, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x80, 0x01, 0x00, 0xc6, 0x8b, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00, - 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, - 0x4b, 0x90, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x4a, - 0x19, 0x7c, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x2f, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xce, 0x97, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x05, 0x98, 0x00, 0xf0, - 0x84, 0x30, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xcd, 0x8b, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x57, 0x90, 0x22, 0x40, - 0xe7, 0x6d, 0x00, 0x00, 0x32, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x62, 0x90, 0xa2, 0x40, 0xe5, 0x6d, 0x00, 0x00, 0xec, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x24, 0x00, 0x20, 0x0b, 0xe0, 0xb1, 0x01, 0x00, - 0x28, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x20, 0x06, - 0xe4, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, - 0x80, 0x32, 0x00, 0x00, 0x14, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, - 0xcd, 0x8b, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xec, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x97, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x70, 0x90, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x99, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15, - 0x98, 0x50, 0x00, 0x00, 0x70, 0x90, 0x20, 0x01, 0x98, 0x6c, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, - 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x6d, 0x90, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x00, 0x10, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0x14, 0x00, 0x2f, 0x15, - 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x01, - 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00, - 0xe6, 0x8f, 0x22, 0x09, 0x80, 0x32, 0x00, 0x00, 0x80, 0x97, 0x00, 0x09, - 0x80, 0x30, 0x01, 0x00, 0xe6, 0x8f, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x43, 0xc1, 0x01, 0x00, 0x26, 0x96, 0x00, 0xf0, - 0x84, 0x30, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0xc6, 0x8b, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x2c, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf3, - 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0xc6, 0x8b, 0x00, 0x42, 0x19, 0x80, 0x00, 0x00, 0x16, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x55, 0x97, 0x00, 0x48, 0x95, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x8a, 0x90, 0xa8, 0x40, 0x13, 0x30, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x90, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x12, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x14, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf0, - 0x84, 0x30, 0x00, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x26, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0xad, 0x90, 0x00, 0x09, 0x00, 0xb0, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0xc6, 0x8b, 0x87, 0x42, 0x19, 0x10, 0x00, 0x00, - 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, - 0xe7, 0x91, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, - 0x2f, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xab, 0x90, 0x22, 0x47, - 0xe7, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x17, 0x94, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00, 0xab, 0x90, 0x22, 0x00, - 0x80, 0x32, 0x00, 0x00, 0xa6, 0x90, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, - 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xab, 0x90, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00, 0x9f, 0x95, 0x00, 0xf2, - 0x02, 0x30, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xac, 0x90, 0x00, 0x40, - 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xb2, 0x90, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xb1, 0x90, 0xa2, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0xff, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xb2, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x51, 0x91, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0xba, 0x90, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xb7, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x51, 0x91, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xc1, 0x90, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0xc1, 0x90, 0xa2, 0x16, - 0x80, 0x32, 0x00, 0x00, 0x09, 0x97, 0x00, 0x4d, 0x81, 0x30, 0x01, 0x00, - 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x96, 0xb0, 0x01, 0x00, - 0xd2, 0x90, 0x22, 0x42, 0x96, 0x14, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x68, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x64, 0x00, 0x00, 0x4b, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xce, 0x90, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xd3, 0x90, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xd7, 0x90, 0x65, 0xf2, 0x12, 0x30, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, - 0x13, 0xf0, 0x01, 0x00, 0xdc, 0x90, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00, - 0x27, 0x83, 0x75, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xd6, 0x90, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00, - 0x04, 0x00, 0x75, 0x09, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0xe4, 0x90, 0xa8, 0x40, 0xe1, 0x31, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, - 0x13, 0xf0, 0x01, 0x00, 0xe8, 0x90, 0x65, 0x05, 0x48, 0x31, 0x00, 0x00, - 0x3f, 0x00, 0x00, 0xf3, 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x75, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xf0, 0x90, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, - 0xee, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, - 0x16, 0xb0, 0x01, 0x00, 0x00, 0x62, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00, - 0x2f, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x47, - 0xe7, 0x7d, 0x00, 0x00, 0x17, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0d, 0x91, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x48, 0x96, 0x00, 0x5f, - 0x01, 0x10, 0x01, 0x00, 0xf4, 0x90, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xfe, 0x90, 0xa8, 0x00, - 0xe0, 0x31, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x20, 0x31, 0x03, 0x6c, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x52, - 0x95, 0x30, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xf4, 0x90, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0xf4, 0x90, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x60, 0x97, 0x00, 0x40, 0x03, 0x30, 0x01, 0x00, 0x17, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x4c, 0x97, 0xf0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x4d, - 0x97, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00, - 0x10, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, - 0xe1, 0xb1, 0x01, 0x00, 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, - 0x16, 0x88, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, - 0x19, 0x91, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x0b, - 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x81, 0x01, 0x00, - 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0b, - 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x81, 0x01, 0x00, - 0x10, 0x00, 0x10, 0x0f, 0x94, 0xf4, 0x01, 0x00, 0x93, 0x04, 0x00, 0x5f, - 0x95, 0x04, 0x01, 0x00, 0x70, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x27, 0x91, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x23, 0x91, 0x46, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x26, 0x91, 0xa2, 0x40, 0x31, 0x6f, 0x00, 0x00, - 0x04, 0x00, 0x1e, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x41, - 0x31, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0f, 0xb0, 0x01, 0x00, 0xa5, 0x94, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00, - 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x3a, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x3a, 0x91, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, - 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x32, 0x91, 0x37, 0x5c, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00, - 0x37, 0x91, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x77, 0x7d, 0x00, 0x00, 0x33, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, 0x37, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xed, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x74, 0x00, 0x22, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x55, 0x97, 0x00, 0x4a, 0x95, 0x30, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x16, 0x96, 0x00, 0x5c, - 0x1f, 0x10, 0x01, 0x00, 0xc1, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x4e, 0x91, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x17, 0x94, 0x00, 0x40, - 0xe7, 0x31, 0x01, 0x00, 0x4e, 0x91, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, - 0x49, 0x91, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x4e, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, - 0x94, 0xb0, 0x01, 0x00, 0x9f, 0x95, 0x00, 0xf2, 0x02, 0x30, 0x01, 0x00, - 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x55, 0x97, 0x00, 0x48, 0x95, 0x30, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x16, 0x96, 0x00, 0x5c, - 0x1f, 0x10, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x55, 0x91, 0x87, 0x42, 0x19, 0x10, 0x00, 0x00, 0x8b, 0x00, 0x2f, 0x47, - 0x19, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0x91, 0x01, 0x00, - 0x80, 0x97, 0x00, 0x42, 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x16, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0xc6, 0x8b, 0x00, 0x5c, - 0x1f, 0x90, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0xce, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x2d, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x05, 0x98, 0x00, 0xf0, 0x84, 0x30, 0x01, 0x00, - 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x80, 0x97, 0x00, 0x45, - 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x09, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xae, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x6d, 0x91, 0xa2, 0x08, - 0x80, 0x32, 0x00, 0x00, 0x6d, 0x91, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, - 0x09, 0x97, 0x00, 0x47, 0x80, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02, - 0x04, 0xdc, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x10, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0xe1, 0x00, 0xa6, - 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x07, - 0x84, 0x94, 0x01, 0x00, 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, - 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x41, 0xe7, 0x41, 0x01, 0x00, - 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0xec, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x0a, 0x0c, 0x6c, 0x00, 0x00, - 0x97, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x0a, - 0x2c, 0x50, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00, 0x9b, 0x97, 0x00, 0x06, - 0x04, 0x30, 0x01, 0x00, 0x8a, 0x91, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, - 0x88, 0x91, 0x84, 0x48, 0x1f, 0x10, 0x00, 0x00, 0xac, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x8a, 0x91, 0x00, 0x0a, 0xe0, 0xc1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x02, 0xb0, 0x01, 0x00, 0x98, 0x93, 0x00, 0x01, - 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x8b, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x10, 0xc0, 0x01, 0x00, 0x98, 0x91, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, - 0x73, 0x96, 0x00, 0x45, 0x1f, 0x00, 0x01, 0x00, 0x83, 0x91, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x94, 0x91, 0xa8, 0x5c, - 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x83, 0x91, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0x1b, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x05, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x9e, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0xa4, 0x91, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, - 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0xa8, 0x91, 0x22, 0x44, - 0x19, 0x7c, 0x00, 0x00, 0x80, 0x97, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, - 0xa8, 0x91, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x80, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, - 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0xb7, 0x91, 0x22, 0x4a, - 0x1f, 0x7c, 0x00, 0x00, 0xaf, 0x91, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, - 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0xb3, 0x91, 0x22, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xb4, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xff, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, - 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x16, - 0xe4, 0xb1, 0x00, 0x00, 0xcd, 0x91, 0x22, 0x16, 0x02, 0x30, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x2a, 0xb0, 0x01, 0x00, 0x25, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, - 0xbd, 0x91, 0xa2, 0x40, 0x11, 0x6c, 0x00, 0x00, 0xce, 0x91, 0x22, 0x40, - 0x2d, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x44, 0x1f, 0x7c, 0x00, 0x00, 0xac, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2b, 0x01, 0xe0, 0xc1, 0x01, 0x00, - 0x00, 0x2b, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xe0, 0xd1, 0x01, 0x00, 0x58, 0x97, 0x00, 0x08, 0x80, 0x30, 0x01, 0x00, - 0xc6, 0x91, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x79, 0x97, 0x00, 0x43, - 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xc7, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x60, 0x97, 0x00, 0x07, - 0x16, 0x14, 0x01, 0x00, 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, - 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15, - 0x1a, 0x50, 0x00, 0x00, 0xdc, 0x91, 0x20, 0x16, 0x1a, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xd9, 0x91, 0xa8, 0x46, - 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x2a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x2c, 0xd0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x16, - 0x80, 0x32, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x40, - 0x23, 0xb0, 0x01, 0x00, 0xe6, 0x91, 0x84, 0x45, 0x1f, 0x10, 0x00, 0x00, - 0xe7, 0x91, 0x00, 0x0a, 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x02, 0xb0, 0x01, 0x00, 0xb8, 0x96, 0x00, 0x40, 0x35, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x42, 0xc9, 0x01, 0x00, 0xf0, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xec, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x92, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00, - 0x05, 0x92, 0x22, 0x40, 0x2d, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0xe0, 0x8d, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0xf8, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, - 0x1b, 0x98, 0x01, 0x00, 0x05, 0x92, 0x00, 0x5c, 0x11, 0x80, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x5f, 0x1b, 0x7c, 0x00, 0x00, 0xff, 0x07, 0x00, 0x08, - 0x98, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x98, 0xc0, 0x01, 0x00, - 0x04, 0x00, 0x20, 0x0b, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, 0x23, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0xa3, 0x43, 0x23, 0x6c, 0x00, 0x00, 0xe1, 0x94, 0x00, 0x40, - 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x0b, 0x92, 0x23, 0x0d, 0x2c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x1f, 0x90, 0x01, 0x00, 0x13, 0x92, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x13, 0x92, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x0f, 0x92, 0xa8, 0x46, - 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41, - 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x18, 0x92, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x1e, 0x92, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0x22, 0x92, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, 0x80, 0x97, 0x00, 0x4f, - 0x81, 0x30, 0x01, 0x00, 0x22, 0x92, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, - 0x00, 0x8c, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x38, 0x92, 0x22, 0x4a, 0x1f, 0x7c, 0x00, 0x00, 0x29, 0x92, 0xa2, 0x16, - 0x02, 0x30, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, - 0x34, 0x92, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x2d, 0x92, 0xa2, 0xf3, - 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x85, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x85, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41, - 0x85, 0xe0, 0x01, 0x00, 0x31, 0x92, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5a, 0x11, 0x90, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x08, - 0xe4, 0xf5, 0x01, 0x00, 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x35, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xff, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, - 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x16, - 0xe4, 0xb1, 0x00, 0x00, 0x3b, 0x92, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, - 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x94, 0x92, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, - 0x4e, 0x92, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa0, 0x91, - 0x03, 0x6c, 0x00, 0x00, 0x48, 0x92, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x41, 0x92, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xd0, 0x01, 0x00, - 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00, 0x45, 0x92, 0x22, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x11, 0x90, 0x01, 0x00, - 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x08, 0x8a, 0x30, 0x01, 0x00, - 0x58, 0x01, 0x2d, 0x00, 0x2a, 0xd0, 0x01, 0x00, 0x60, 0x01, 0x2d, 0xf0, - 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x27, 0x40, - 0x11, 0x6c, 0x00, 0x00, 0x84, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0xa3, 0x91, 0x03, 0x6c, 0x00, 0x00, 0x25, 0x98, 0x00, 0x41, - 0x95, 0x30, 0x01, 0x00, 0x57, 0x92, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x57, 0x92, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x97, 0xb0, 0x01, 0x00, 0x55, 0x92, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x94, 0x92, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x01, 0x14, 0xb0, 0x01, 0x00, - 0xb0, 0x00, 0x2b, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6, - 0x16, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, 0x6a, 0x92, 0x23, 0x0d, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x63, 0x92, 0xa8, 0x00, - 0xe0, 0x31, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x22, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x23, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x84, 0xb0, 0x01, 0x00, 0x6d, 0x92, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x80, 0xb0, 0x01, 0x00, 0x72, 0x92, 0x22, 0x40, 0x1b, 0x6c, 0x00, 0x00, - 0x58, 0x97, 0x00, 0x01, 0x84, 0x50, 0x01, 0x00, 0x7b, 0x92, 0x22, 0x40, - 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xc0, 0x01, 0x00, - 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00, 0x78, 0x92, 0xa8, 0x11, - 0xe0, 0x31, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, 0x23, 0x6c, 0x00, 0x00, - 0x8a, 0x92, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0x7e, 0x92, 0x23, 0x0d, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x84, 0xd0, 0x01, 0x00, 0x83, 0x92, 0x22, 0x40, - 0x1b, 0x6c, 0x00, 0x00, 0x79, 0x97, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, - 0x8a, 0x92, 0x22, 0x40, 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x12, 0xc0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1, - 0x62, 0xdd, 0x01, 0x00, 0x88, 0x92, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x8b, 0x92, 0xa8, 0x0a, 0x02, 0x30, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x05, - 0x48, 0x31, 0x01, 0x00, 0x92, 0x92, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, - 0xff, 0x07, 0x00, 0x11, 0x00, 0x8c, 0x01, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x60, 0x97, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, - 0xfa, 0x96, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x8e, 0xb0, 0x01, 0x00, 0xe6, 0x95, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0x04, 0x00, 0x0c, 0x47, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, - 0x97, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0x20, 0x91, - 0x03, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xa8, 0x92, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xa4, 0x92, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xaa, 0x92, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x15, 0x1a, 0xd0, 0x01, 0x00, 0xb1, 0x92, 0xa2, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0x25, 0x98, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00, 0xba, 0x92, 0x27, 0x08, - 0x80, 0x32, 0x00, 0x00, 0xbd, 0x91, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00, - 0x25, 0x98, 0x00, 0x41, 0x95, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0x80, 0xb2, 0x01, 0x00, 0xb5, 0x92, 0x27, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x57, 0x92, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x97, 0xb0, 0x01, 0x00, 0xb8, 0x92, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xc6, 0x8b, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x09, 0x97, 0x00, 0x3a, - 0x81, 0x30, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00, 0xbf, 0x92, 0x00, 0x4a, - 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x4f, 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, - 0xf9, 0x94, 0x00, 0x00, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x9b, 0x97, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00, 0xcc, 0x92, 0xa2, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x2c, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x02, 0xb0, 0x01, 0x00, 0x98, 0x93, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0xd3, 0x92, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xcf, 0x92, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x10, 0xc0, 0x01, 0x00, 0xdc, 0x92, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, - 0x73, 0x96, 0x00, 0x45, 0x1f, 0x00, 0x01, 0x00, 0xc5, 0x92, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xd8, 0x92, 0xa8, 0x5c, - 0x1f, 0x00, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xc5, 0x92, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x08, 0x00, 0x2d, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41, - 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xe1, 0x92, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xe7, 0x92, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0xea, 0x92, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, 0x80, 0x97, 0x00, 0x4f, - 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00, - 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xf9, 0x92, 0x22, 0x4a, 0x1f, 0x7c, 0x00, 0x00, - 0xf1, 0x92, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x2d, 0x08, - 0x2a, 0xb0, 0x01, 0x00, 0xf5, 0x92, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x36, 0x96, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf6, 0x92, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xff, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, 0x32, 0x00, 0x2a, 0x15, - 0xe4, 0xb1, 0x01, 0x00, 0xc6, 0x8b, 0x00, 0x16, 0xe4, 0xb1, 0x00, 0x00, - 0xb8, 0x91, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xcd, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4f, 0x2b, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00, - 0xf9, 0x94, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x10, - 0x32, 0xb0, 0x00, 0x00, 0x8a, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x08, 0x93, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0b, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x9f, 0x95, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x0d, 0x93, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x09, 0x97, 0x00, 0x3a, - 0x81, 0x30, 0x01, 0x00, 0x80, 0x97, 0x00, 0x45, 0x81, 0x30, 0x01, 0x00, - 0xc6, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x62, 0x90, 0x00, 0x45, - 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, 0xec, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x0a, 0x0c, 0x6c, 0x00, 0x00, - 0x97, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x01, - 0x2c, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x26, 0x93, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x26, 0x93, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, - 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x1e, 0x93, 0x37, 0x5c, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00, - 0x23, 0x93, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x77, 0x7d, 0x00, 0x00, 0x1f, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, 0x23, 0x93, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xed, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x58, 0x01, 0x20, 0x08, 0xe0, 0xb1, 0x01, 0x00, 0x60, 0x01, 0x20, 0x16, - 0xe0, 0xb1, 0x01, 0x00, 0xec, 0x95, 0x00, 0x47, 0x1f, 0x10, 0x01, 0x00, - 0x04, 0x00, 0xa3, 0x0a, 0x0c, 0x6c, 0x00, 0x00, 0x97, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0xae, 0x94, 0x00, 0x47, 0x1f, 0x10, 0x01, 0x00, - 0x3d, 0x93, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x3d, 0x93, 0xa2, 0x16, - 0x80, 0x32, 0x00, 0x00, 0x39, 0x93, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x15, - 0x94, 0x30, 0x01, 0x00, 0xa6, 0x95, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x36, 0x96, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0x09, 0x97, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xed, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08, 0xe0, 0xb1, 0x01, 0x00, - 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x4f, - 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0xf9, 0x94, 0x00, 0x10, - 0x32, 0x30, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, - 0xae, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x52, 0x93, 0xa2, 0x08, - 0x80, 0x32, 0x00, 0x00, 0x52, 0x93, 0xa2, 0x16, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, - 0x4a, 0x93, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x62, 0xb1, 0x01, 0x00, 0x4f, 0x93, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x77, 0x7d, 0x00, 0x00, 0x4b, 0x93, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, - 0x4f, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xed, 0x87, 0x17, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x8e, 0xb0, 0x01, 0x00, 0xe6, 0x95, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x04, 0x00, 0x0c, 0x47, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x26, 0x96, 0x00, 0x41, - 0x87, 0x30, 0x01, 0x00, 0x97, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x04, 0x00, 0xa0, 0x91, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x64, 0x93, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x60, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x84, 0x8f, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, - 0x80, 0x97, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, 0x84, 0x8f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x4f, 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0x14, 0x00, 0x2d, 0x45, 0x1f, 0x90, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0xf0, 0x14, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa0, 0x01, - 0x14, 0x6c, 0x00, 0x00, 0xdc, 0x8f, 0x00, 0x44, 0x19, 0x90, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00, 0x72, 0x93, 0xa2, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00, - 0x77, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x48, - 0x1f, 0x7c, 0x00, 0x00, 0xec, 0x95, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00, - 0x04, 0x00, 0xa3, 0x0a, 0x0c, 0x6c, 0x00, 0x00, 0x97, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4f, - 0x2b, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0xf9, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd0, 0x91, 0x00, 0x10, 0x32, 0xb0, 0x00, 0x00, - 0x8b, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x46, - 0xe7, 0x7d, 0x00, 0x00, 0x62, 0x90, 0x00, 0x45, 0x1f, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x37, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x33, 0xc3, 0x01, 0x00, 0x36, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00, - 0x00, 0x00, 0xd2, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x86, 0x93, 0x85, 0x17, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x48, 0x03, 0xd0, 0x00, 0x00, - 0x88, 0x93, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x4c, - 0x03, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x34, 0xc3, 0x01, 0x00, - 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0xf0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, - 0xf0, 0xb1, 0x01, 0x00, 0xcb, 0x94, 0x00, 0x41, 0xe1, 0x31, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x43, 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x49, 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x95, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2d, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0xa5, - 0x8a, 0x30, 0x01, 0x00, 0xba, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, - 0xb0, 0x00, 0x2f, 0x01, 0x8c, 0xd0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0xf0, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xe0, 0xc1, 0x01, 0x00, - 0xac, 0x00, 0x2f, 0x40, 0x13, 0xb0, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x01, - 0xe0, 0xc1, 0x01, 0x00, 0xa3, 0x93, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, 0x2f, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xa5, 0x93, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x13, 0x90, 0x01, 0x00, 0xce, 0x97, 0x00, 0x47, - 0x19, 0x10, 0x01, 0x00, 0xc0, 0x00, 0x2d, 0x44, 0x1f, 0x90, 0x01, 0x00, - 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x05, 0x98, 0x00, 0xf0, - 0x84, 0xb0, 0x00, 0x00, 0x90, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xba, 0x93, 0xa2, 0x4b, 0x1f, 0x7c, 0x00, 0x00, 0x0f, 0x94, 0xa2, 0x4c, - 0x1f, 0x7c, 0x00, 0x00, 0xba, 0x93, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, - 0xbd, 0x93, 0xa2, 0x01, 0x80, 0x32, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x46, - 0x8f, 0xb0, 0x01, 0x00, 0xb3, 0x93, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, - 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xb5, 0x93, 0x22, 0xf0, - 0x3a, 0x6c, 0x00, 0x00, 0x0c, 0x94, 0x1f, 0xf0, 0x3a, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f, - 0x8f, 0xb0, 0x01, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x0d, 0x94, 0x20, 0x42, 0xe7, 0x6d, 0x00, 0x00, 0xb9, 0x93, 0x22, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x59, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x58, 0x8f, 0xb0, 0x01, 0x00, 0xbc, 0x93, 0x22, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x5b, 0x8f, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, - 0xc1, 0x93, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0xcc, 0x93, 0x23, 0xf0, - 0x02, 0x6c, 0x00, 0x00, 0xb0, 0x00, 0x00, 0xa1, 0x80, 0xce, 0x01, 0x00, - 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xc9, 0x93, 0xa2, 0xf0, - 0x80, 0x32, 0x00, 0x00, 0x0e, 0x94, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, - 0x0e, 0x94, 0xa2, 0x41, 0x03, 0x6c, 0x00, 0x00, 0xc8, 0x93, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x51, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x52, 0x8f, 0xb0, 0x01, 0x00, 0x0e, 0x94, 0x1f, 0x12, - 0x84, 0x50, 0x00, 0x00, 0x0e, 0x94, 0xa0, 0x01, 0x84, 0x6c, 0x00, 0x00, - 0xba, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xf7, 0x93, 0xa2, 0x46, 0xe7, 0x7d, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xe9, 0x93, 0x22, 0xf0, - 0x14, 0x30, 0x00, 0x00, 0xd5, 0x93, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, - 0xe6, 0x93, 0x03, 0x1e, 0x80, 0x32, 0x00, 0x00, 0xd4, 0x93, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0xda, 0x93, 0x22, 0x0a, - 0x02, 0x6c, 0x00, 0x00, 0xdd, 0x93, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xd9, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00, - 0xdc, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x82, 0xd0, 0x01, 0x00, 0xe3, 0x93, 0x20, 0x91, 0x83, 0x6c, 0x00, 0x00, - 0xe2, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x80, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x27, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0xe5, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x80, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x20, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0xe8, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x22, 0x00, 0x80, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x23, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x88, 0x00, 0x2d, 0x44, 0x8f, 0xb0, 0x01, 0x00, 0xf2, 0x93, 0xa2, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0xef, 0x93, 0xa2, 0x43, 0x3d, 0x7c, 0x00, 0x00, - 0xef, 0x93, 0xa2, 0xf2, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, - 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, - 0xf1, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, - 0xef, 0x93, 0xa0, 0x91, 0x03, 0x6c, 0x00, 0x00, 0xed, 0x93, 0x22, 0x43, - 0x3d, 0x7c, 0x00, 0x00, 0xf6, 0x93, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x28, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x29, 0x00, 0x80, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x94, 0xa2, 0xf0, 0x14, 0x30, 0x00, 0x00, 0x88, 0x00, 0x2d, 0x44, - 0x8f, 0xb0, 0x01, 0x00, 0xfd, 0x93, 0xa2, 0xf2, 0x02, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x49, - 0x8f, 0xb0, 0x01, 0x00, 0xef, 0x93, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xed, 0x93, 0x20, 0x91, 0x03, 0x6c, 0x00, 0x00, 0xef, 0x93, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x94, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, - 0x03, 0x94, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, - 0x09, 0x94, 0x22, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0xdd, 0x93, 0xa2, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0x08, 0x94, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x55, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x56, - 0x8f, 0xb0, 0x01, 0x00, 0x0b, 0x94, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, - 0x8f, 0xb0, 0x01, 0x00, 0x11, 0x94, 0x00, 0x43, 0x95, 0xb0, 0x00, 0x00, - 0x11, 0x94, 0x00, 0x41, 0x95, 0xb0, 0x00, 0x00, 0x11, 0x94, 0x00, 0x42, - 0x95, 0xb0, 0x00, 0x00, 0x11, 0x94, 0x00, 0x44, 0x95, 0xb0, 0x00, 0x00, - 0x11, 0x94, 0x00, 0x4c, 0x95, 0xb0, 0x00, 0x00, 0x30, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x4a, 0x8a, 0x30, 0x01, 0x00, - 0x55, 0x97, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x16, 0x94, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4b, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x4c, 0x8f, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x2e, 0x00, 0x2f, 0xf3, 0x84, 0xb0, 0x01, 0x00, 0x1c, 0x94, 0xa2, 0xf3, - 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x01, 0xb0, 0x01, 0x00, - 0x2d, 0x00, 0x2a, 0x41, 0xe7, 0xd1, 0x01, 0x00, 0xd4, 0x00, 0x3d, 0x41, - 0x85, 0xe0, 0x01, 0x00, 0x0b, 0x00, 0x00, 0xf2, 0x00, 0xe4, 0x01, 0x00, - 0x22, 0x94, 0x22, 0x5a, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x1f, 0x90, 0x01, 0x00, 0x23, 0x94, 0x00, 0x5a, 0x01, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x63, 0x41, - 0x85, 0xc0, 0x01, 0x00, 0x26, 0x94, 0xa0, 0xa5, 0x85, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x12, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0xa0, 0xa5, - 0x85, 0x6c, 0x01, 0x00, 0x00, 0x00, 0xe3, 0x40, 0x85, 0xb0, 0x01, 0x00, - 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x12, 0x00, 0x00, 0x40, - 0x87, 0x98, 0x01, 0x00, 0x78, 0x98, 0x00, 0xf0, 0x8c, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x5f, 0x1f, 0x7c, 0x00, 0x00, 0x3b, 0x94, 0x22, 0x40, - 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf0, - 0x98, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07, 0x98, 0x6c, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x0c, 0x98, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07, - 0x98, 0x6c, 0x00, 0x00, 0x38, 0x94, 0xa2, 0x4b, 0x19, 0x7c, 0x00, 0x00, - 0x39, 0x94, 0x22, 0xf0, 0x18, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0x3d, 0x95, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00, - 0x2f, 0x83, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x3d, 0x94, 0x22, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0xa5, 0x94, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00, - 0x2f, 0x83, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5f, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, 0x0f, 0x6c, 0x00, 0x00, - 0x10, 0x00, 0x00, 0xf0, 0x96, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07, - 0x96, 0x6c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0c, 0x96, 0xf4, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x07, 0x96, 0x6c, 0x00, 0x00, 0x3d, 0x95, 0x00, 0x07, - 0x10, 0x30, 0x01, 0x00, 0x2f, 0x83, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x5f, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, - 0x0f, 0x6c, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x96, 0xf4, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x07, 0x96, 0x6c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0c, - 0x96, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07, 0x96, 0x6c, 0x00, 0x00, - 0x3d, 0x95, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x05, 0xb0, 0x01, 0x00, 0x54, 0x94, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x57, 0x94, 0xa1, 0xad, 0x95, 0x20, 0x00, 0x00, 0x69, 0x94, 0x13, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4a, 0x5a, 0x83, 0x01, 0x00, - 0x30, 0x00, 0x39, 0x45, 0x95, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5f, - 0x5f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5e, 0x5f, 0x7c, 0x00, 0x00, - 0x1f, 0x00, 0x00, 0x0f, 0x5e, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, - 0x5f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x5f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x45, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x48, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x58, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, - 0x4e, 0xb0, 0x01, 0x00, 0x19, 0x85, 0x00, 0x40, 0x5d, 0x98, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x44, 0x5f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x62, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x41, 0x97, 0xb0, 0x00, 0x00, 0x66, 0x94, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x40, 0x05, 0x6c, 0x00, 0x00, 0x15, 0x99, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x6c, 0x94, 0x60, 0x07, 0x96, 0x30, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00, 0x00, 0x00, 0x70, 0xc2, - 0x24, 0xb0, 0x01, 0x00, 0x79, 0x94, 0xa2, 0x45, 0x25, 0x7c, 0x00, 0x00, - 0x70, 0x94, 0x31, 0x20, 0x85, 0x30, 0x00, 0x00, 0x7a, 0x94, 0x22, 0x12, - 0x48, 0x7f, 0x00, 0x00, 0x58, 0x04, 0x11, 0x12, 0x48, 0x03, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x1e, 0x94, 0x01, 0x00, 0x17, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x12, 0x8a, 0xb0, 0x01, 0x00, 0x02, 0x99, 0x00, 0x5f, - 0x8b, 0x10, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00, - 0x79, 0x94, 0x31, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, - 0x24, 0xb0, 0x01, 0x00, 0x7a, 0x94, 0x22, 0x12, 0x48, 0x7f, 0x00, 0x00, - 0x58, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x17, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x12, 0x8a, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x89, 0x94, 0x0b, 0xf0, - 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x11, 0x12, 0x48, 0x83, 0x01, 0x00, - 0x86, 0x94, 0x22, 0x50, 0x85, 0x70, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xae, 0x96, 0x00, 0xf2, 0x96, 0x30, 0x01, 0x00, - 0x93, 0x04, 0x00, 0x12, 0x94, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, - 0x1f, 0x90, 0x01, 0x00, 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x4b, 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x42, - 0x10, 0xf4, 0x01, 0x00, 0x04, 0x00, 0x22, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x00, 0xb7, 0x3f, 0x43, 0x11, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08, - 0x8a, 0x88, 0x01, 0x00, 0x8d, 0x94, 0x30, 0xa1, 0x0c, 0x30, 0x00, 0x00, - 0x90, 0x94, 0x22, 0x45, 0xe6, 0x7d, 0x00, 0x00, 0x7a, 0x94, 0x10, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x45, 0xe6, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x10, 0x12, 0x48, 0x83, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x4b, 0x85, 0x80, 0x01, 0x00, 0x5e, 0x01, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xae, 0x96, 0x00, 0xf2, 0x96, 0x30, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0xd8, 0x00, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x9c, 0x94, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x40, - 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00, - 0x09, 0x00, 0x00, 0x08, 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa7, - 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xa0, 0x94, 0xa8, 0x05, - 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x14, 0x00, 0x4b, 0x96, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4b, - 0x1e, 0x94, 0x01, 0x00, 0x04, 0x00, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x0f, 0x84, 0xf4, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x42, - 0x84, 0x88, 0x01, 0x00, 0xaa, 0x94, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, - 0xab, 0x94, 0x00, 0x42, 0x68, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x6a, 0xb1, 0x01, 0x00, 0xab, 0x94, 0x31, 0x5a, 0x1f, 0x00, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x42, 0x48, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x91, 0x42, - 0x48, 0x93, 0x01, 0x00, 0xae, 0x94, 0x35, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xb4, 0x94, 0x28, 0xb1, - 0x2c, 0x30, 0x00, 0x00, 0xaf, 0x94, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x2d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x95, 0x40, - 0x11, 0xb0, 0x01, 0x00, 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xb4, 0x94, 0xa8, 0xb1, 0x10, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, - 0x80, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x27, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x95, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x7f, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xbf, 0x94, 0x28, 0xb1, 0x10, 0x30, 0x00, 0x00, - 0xb9, 0x94, 0x9f, 0xba, 0x80, 0x32, 0x00, 0x00, 0x15, 0x00, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x5c, - 0x11, 0x7c, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x5a, 0x11, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x08, 0x48, 0x06, 0x00, 0x00, 0x00, 0x00, 0x80, 0x24, - 0x11, 0x84, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, 0x01, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x5a, 0x01, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x00, - 0x48, 0x06, 0x00, 0x00, 0x04, 0x00, 0x1f, 0xbb, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xc8, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xac, 0x94, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0xcc, 0x94, 0x32, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xd4, 0x94, 0x22, 0xf8, 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x90, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x92, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x80, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x27, 0x49, - 0x80, 0x32, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4b, 0xf0, 0xcd, 0x01, 0x00, - 0x20, 0x00, 0x92, 0x48, 0xe0, 0xc9, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xd8, 0x94, 0x28, 0xb1, 0x92, 0x30, 0x00, 0x00, - 0xd4, 0x94, 0x22, 0x4c, 0x75, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x12, 0x40, - 0x91, 0xb0, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xd8, 0x94, 0xa8, 0xb1, 0x90, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x80, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x27, 0x48, 0x80, 0x32, 0x00, 0x00, - 0xff, 0x00, 0x00, 0x48, 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x90, 0xd0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x4b, 0xf0, 0xcd, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x48, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x92, 0x49, - 0xe0, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0xff, 0x07, 0x00, 0x08, 0x82, 0x8c, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x83, 0x7c, 0x00, 0x00, 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x01, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, - 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x00, 0xec, 0x00, 0x00, - 0xea, 0x94, 0x22, 0x1a, 0x00, 0x6c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x00, - 0x34, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x49, 0xc1, 0x01, 0x00, - 0xe4, 0x94, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0xff, 0x07, 0x00, 0x15, 0x82, 0x8c, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x83, 0x7c, 0x00, 0x00, 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5c, 0x01, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, - 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x41, 0x00, 0xec, 0x00, 0x00, - 0xf6, 0x94, 0x22, 0x0d, 0x00, 0x6c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x00, - 0x1a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x49, 0xc1, 0x01, 0x00, - 0xf0, 0x94, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xfb, 0x94, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x19, 0x90, 0x01, 0x00, 0x24, 0x00, 0x2d, 0x01, - 0x2c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00, - 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, 0x14, 0x00, 0x2f, 0xf2, - 0x0c, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0xf0, 0x14, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0x20, 0x01, 0x14, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x60, 0x97, 0x2e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x04, 0x95, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x64, 0x97, 0x3e, 0x43, 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3e, 0x43, 0x9d, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x0b, 0xe8, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3f, 0x43, - 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3f, 0x43, - 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x16, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x60, 0x17, 0x3d, 0x43, - 0x9d, 0xe0, 0x01, 0x00, 0x10, 0x00, 0x80, 0xa1, 0x16, 0xe4, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x07, 0x16, 0x6c, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x10, 0x00, 0x00, 0x0b, 0x8a, 0xe4, 0x01, 0x00, - 0x02, 0x99, 0x00, 0x0d, 0x8a, 0x14, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, - 0x42, 0xc9, 0x01, 0x00, 0x17, 0x95, 0x30, 0x47, 0x17, 0x04, 0x00, 0x00, - 0x1a, 0x95, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x90, 0x42, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, - 0x1e, 0x95, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0xe6, 0x91, 0x01, 0x00, 0x00, 0x00, 0x90, 0x41, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x1f, 0x95, 0x40, 0x07, - 0x96, 0x30, 0x00, 0x00, 0x9d, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x29, 0x95, 0xa2, 0x45, 0x95, 0x7c, 0x00, 0x00, 0x01, 0x97, 0x3f, 0x41, - 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40, - 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00, - 0x40, 0x97, 0x3e, 0x40, 0x9d, 0xe0, 0x01, 0x00, 0x3c, 0x95, 0x00, 0x3b, - 0xe7, 0xb1, 0x00, 0x00, 0x29, 0x95, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x33, 0x95, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x0d, - 0x46, 0xc9, 0x01, 0x00, 0x2f, 0x95, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x42, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x41, 0x81, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x21, 0xa2, 0x95, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x4a, - 0x44, 0x83, 0x01, 0x00, 0x00, 0x97, 0x3e, 0x41, 0x95, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0xf6, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40, 0x9d, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x3b, 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x07, 0x92, 0x89, 0x01, 0x00, - 0x00, 0x00, 0x98, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x11, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x08, 0x8a, 0x30, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x08, 0x86, 0xf4, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x43, - 0x46, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08, 0x82, 0x88, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x08, 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x41, - 0xe6, 0x7d, 0x00, 0x00, 0x44, 0x95, 0x40, 0x08, 0x96, 0x30, 0x00, 0x00, - 0x9d, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x52, 0x95, 0x22, 0x45, - 0x95, 0x7c, 0x00, 0x00, 0x4d, 0x95, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x0f, 0x96, 0xf4, 0x01, 0x00, 0x49, 0x95, 0x31, 0x5f, - 0x97, 0x04, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x4b, 0x48, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x11, 0x4b, 0x48, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x6a, 0xb1, 0x01, 0x00, 0x4d, 0x95, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x41, 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xe6, 0x81, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x97, 0x3f, 0x41, - 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, - 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3, - 0x88, 0xb0, 0x01, 0x00, 0x5b, 0x95, 0xa2, 0x3b, 0x89, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, - 0x92, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x4a, 0x44, 0x7f, 0x00, 0x00, - 0x5c, 0x95, 0x18, 0x4a, 0x44, 0x93, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x3f, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x16, 0x00, 0x00, 0x12, 0x8a, 0xe4, 0x01, 0x00, 0x02, 0x99, 0x00, 0x4b, - 0x8a, 0x14, 0x01, 0x00, 0x30, 0x00, 0x39, 0x45, 0x97, 0xe0, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5f, 0x5f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5e, - 0x5f, 0x7c, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x2f, 0x7e, 0xd9, 0x01, 0x00, - 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x68, 0x95, 0x22, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x0f, 0x98, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x5e, 0x94, 0x01, 0x00, 0x6a, 0x95, 0x00, 0x05, - 0x4a, 0xb0, 0x00, 0x00, 0x1f, 0x04, 0x00, 0xa7, 0x5e, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x4b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e, - 0x5f, 0x90, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x08, 0x4e, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x6d, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x33, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x07, 0x8a, 0x30, 0x01, 0x00, - 0x72, 0x95, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00, 0x9d, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x76, 0x95, 0x22, 0x45, 0x95, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x4a, - 0x44, 0x7f, 0x00, 0x00, 0x9b, 0x04, 0x00, 0x4a, 0x44, 0x13, 0x01, 0x00, - 0x00, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x96, 0xb0, 0x01, 0x00, 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x63, 0xf3, 0x88, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45, - 0x97, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5f, 0x1f, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x5e, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x20, 0xaa, - 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0x82, 0x95, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x78, 0x95, 0xa2, 0x3b, 0x89, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45, - 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x08, 0x80, 0x32, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, - 0x94, 0xf4, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x4a, 0x46, 0xc9, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x08, 0x96, 0x88, 0x01, 0x00, 0x04, 0x00, 0x22, 0x4b, - 0xe6, 0x7d, 0x00, 0x00, 0x93, 0x04, 0x00, 0x12, 0x94, 0x30, 0x01, 0x00, - 0x3d, 0x95, 0x00, 0x5a, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5a, - 0x1f, 0x90, 0x01, 0x00, 0x11, 0x00, 0x00, 0x4a, 0xe6, 0xc9, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x4a, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0x24, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x34, 0x00, 0x2f, 0x4f, 0x95, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0x4b, - 0x84, 0xc8, 0x01, 0x00, 0x00, 0x00, 0xa0, 0x43, 0x85, 0x6c, 0x01, 0x00, - 0x00, 0x00, 0xe3, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x2d, 0x44, - 0x1f, 0x90, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x2a, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf2, - 0x02, 0x30, 0x00, 0x00, 0x17, 0x94, 0x00, 0x10, 0x32, 0x30, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0x32, 0x00, 0xa0, 0x40, 0xe5, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, - 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x02, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x4c, 0x02, 0xd0, 0x00, 0x00, - 0xa3, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, - 0x36, 0xb0, 0x01, 0x00, 0xb4, 0x95, 0x22, 0x41, 0x03, 0x50, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xf1, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0xac, 0x95, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x7c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0xb0, 0x01, 0x00, 0xa7, 0x95, 0x00, 0x5c, 0x01, 0x80, 0x00, 0x00, - 0xc3, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x10, 0xb1, 0x00, 0x00, 0x68, 0x01, 0x2d, 0x06, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x82, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x46, 0xc9, 0x01, 0x00, 0xb9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xe2, 0x95, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x68, 0x08, - 0x38, 0x96, 0x01, 0x00, 0x3a, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x02, 0x99, 0x00, 0x08, 0x8a, 0x30, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x41, - 0x82, 0xcc, 0x01, 0x00, 0xb9, 0x95, 0xaa, 0x41, 0x3b, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x11, 0x80, 0x01, 0x00, 0x04, 0x00, 0xa3, 0x48, 0x3b, 0x6c, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x1d, 0x04, 0xcc, 0x01, 0x00, 0xe0, 0x95, 0x26, 0x46, - 0x23, 0x30, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x12, 0xc8, 0x01, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x98, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x4c, - 0x42, 0x6d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x64, 0x01, 0x20, 0xf0, 0xe0, 0xb1, 0x01, 0x00, 0xdf, 0x95, 0x22, 0x41, - 0x05, 0x50, 0x00, 0x00, 0x20, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x0c, 0x00, 0x00, 0xf8, 0x86, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x22, 0x44, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x09, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0xd1, 0x95, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, 0xde, 0x95, 0x22, 0x41, - 0x05, 0x50, 0x00, 0x00, 0xdc, 0x95, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa1, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xd7, 0x95, 0xa8, 0x46, 0x23, 0x30, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x13, 0xc0, 0x01, 0x00, 0xcc, 0x95, 0x00, 0x50, 0x49, 0xc1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03, - 0x1a, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xe0, 0x95, 0x22, 0x40, - 0x3b, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, - 0xc3, 0x94, 0x00, 0x5c, 0x01, 0x00, 0x01, 0x00, 0xe2, 0x95, 0x00, 0x41, - 0x3b, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x47, 0x80, 0x32, 0x01, 0x00, - 0xb0, 0x00, 0x2f, 0x5f, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, - 0x8c, 0xc0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x04, 0x00, 0xa3, 0xf0, 0x8c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x8c, 0xb0, 0x01, 0x00, 0xf1, 0x95, 0x8c, 0xf8, 0x8e, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8, - 0x14, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x26, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x2e, 0xf8, - 0x0c, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2a, 0x4a, 0xe0, 0xb1, 0x01, 0x00, - 0x28, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x20, 0x1b, - 0xe0, 0xb1, 0x01, 0x00, 0xfe, 0x95, 0x20, 0x0a, 0x0c, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x96, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00, - 0x18, 0x00, 0x20, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x1c, 0x00, 0x20, 0x4b, - 0xe0, 0xb1, 0x01, 0x00, 0xe6, 0x95, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x2c, 0x00, 0x2d, 0x42, - 0x19, 0x90, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x05, 0x96, 0xa2, 0xa5, - 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00, - 0x08, 0x96, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41, - 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, - 0x0d, 0x96, 0xa0, 0xa5, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x2c, 0x00, 0x20, 0x41, 0xe6, 0xb1, 0x01, 0x00, - 0x12, 0x96, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x98, 0xdc, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x4c, 0xe4, 0xf5, 0x01, 0x00, - 0x13, 0x96, 0x00, 0x40, 0x1f, 0x80, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, - 0xe4, 0xf5, 0x01, 0x00, 0x1e, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xcb, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x40, - 0xe1, 0x6d, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x41, 0x87, 0xb0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x49, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, - 0x05, 0x90, 0x00, 0x00, 0x23, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xcb, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00, - 0x33, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x82, 0x0c, 0x80, 0x32, 0x00, 0x00, - 0x2d, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, - 0x84, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x96, 0xc8, 0x01, 0x00, - 0x3d, 0x96, 0x9f, 0x41, 0x85, 0x50, 0x00, 0x00, 0x01, 0x00, 0x00, 0xa5, - 0x85, 0xcc, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x42, 0xe6, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0xa3, 0xa5, 0x97, 0x6c, 0x00, 0x00, 0xd4, 0x00, 0x3d, 0x41, - 0x85, 0xe0, 0x01, 0x00, 0x0b, 0x00, 0x00, 0xf2, 0x98, 0xe4, 0x01, 0x00, - 0x44, 0x96, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x5a, - 0x99, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x99, 0x80, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x00, 0x98, 0x6c, 0x00, 0x00, 0x20, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x21, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x00, 0x8a, 0x30, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x00, 0x6a, 0x06, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x00, - 0x80, 0xb0, 0x01, 0x00, 0x4f, 0x96, 0x52, 0x43, 0x81, 0x60, 0x00, 0x00, - 0x02, 0x00, 0x00, 0xf2, 0x82, 0xf4, 0x01, 0x00, 0x50, 0x96, 0x00, 0x41, - 0x80, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5e, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x95, 0xb0, 0x00, 0x00, - 0x51, 0x96, 0x9e, 0xbb, 0x80, 0x32, 0x00, 0x00, 0x56, 0x96, 0xa2, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x15, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x2b, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x38, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x3a, 0xb0, 0x01, 0x00, 0x6b, 0x96, 0x9c, 0x17, - 0x80, 0x32, 0x00, 0x00, 0x60, 0x96, 0xa2, 0x4a, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x4c, 0x1f, 0x90, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x1e, - 0x98, 0xf4, 0x01, 0x00, 0x5f, 0x96, 0xa2, 0x48, 0x99, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x15, 0x42, 0xb1, 0x01, 0x00, 0x5f, 0x96, 0xa2, 0x8a, - 0xf1, 0x6d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x3e, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xf4, - 0x28, 0xcc, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x6a, 0x96, 0x20, 0xf0, 0x3e, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x2b, 0xc0, 0x01, 0x00, - 0xbf, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0xf3, - 0x3a, 0xe0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x0c, 0x96, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07, - 0x96, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0x07, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04, - 0xe6, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x1c, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x2d, 0xf0, - 0x26, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x06, 0x14, 0xec, 0x00, 0x00, 0x7a, 0x96, 0x22, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x06, 0x2a, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x96, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x2a, 0x4c, 0xe1, 0xc1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, - 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x18, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x84, 0x96, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x95, - 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03, - 0xf0, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x8f, 0x96, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x90, 0x96, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x62, 0xc9, 0x01, 0x00, 0x92, 0x96, 0xa8, 0x00, - 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x95, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x06, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x9d, 0x96, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x9e, 0x96, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0xa0, 0x96, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x30, 0x80, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x06, 0xf1, 0xb1, 0x01, 0x00, 0xc0, 0xa8, 0x3d, 0x46, - 0x0d, 0xe0, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa1, 0xf0, 0x89, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x09, 0x96, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xa8, 0x97, 0xc0, 0x01, 0x00, - 0xaa, 0x96, 0x63, 0x42, 0x61, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x4a, - 0x62, 0xc9, 0x01, 0x00, 0xab, 0x96, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0xf3, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x99, 0x3f, 0x42, - 0x97, 0xf0, 0x01, 0x00, 0xaf, 0x96, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xb7, 0x96, 0x22, 0xf3, 0x74, 0x06, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, - 0x94, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe7, 0x85, 0x01, 0x00, - 0x00, 0x00, 0x75, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb4, 0x96, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x36, 0xb0, 0x01, 0x00, - 0xc7, 0x96, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00, 0xbc, 0x96, 0xa2, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0x98, 0x93, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, - 0x20, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xc2, 0x96, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xbf, 0x96, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x32, 0xb0, 0x01, 0x00, 0xc7, 0x96, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xe1, 0x94, 0x00, 0x43, 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x23, 0xb0, 0x01, 0x00, 0xc9, 0x96, 0xa3, 0x15, 0x0c, 0x6c, 0x00, 0x00, - 0xca, 0x96, 0x00, 0x06, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x04, 0xb0, 0x01, 0x00, 0xcc, 0x96, 0x20, 0x02, 0x1a, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x04, 0xb0, 0x01, 0x00, 0x9b, 0x97, 0x00, 0x05, - 0x48, 0x31, 0x01, 0x00, 0xf7, 0x96, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, - 0xd0, 0x96, 0xa2, 0x02, 0x2a, 0x50, 0x00, 0x00, 0xf7, 0x96, 0xa2, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0xd2, 0x96, 0x22, 0x02, 0x0c, 0x50, 0x00, 0x00, - 0xdb, 0x96, 0x00, 0x02, 0x16, 0xc0, 0x00, 0x00, 0xda, 0x96, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xda, 0x96, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xd6, 0x96, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x73, 0x96, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0xf7, 0x96, 0x22, 0x15, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, - 0xf6, 0x96, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00, 0xe7, 0x96, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0xe7, 0x96, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xe3, 0x96, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x23, 0x83, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x80, 0x32, 0x00, 0x00, - 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00, 0x2f, 0x00, 0x2f, 0x5c, - 0x11, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00, - 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00, 0xb9, 0x96, 0x20, 0x15, - 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0xe0, 0x8d, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0xf3, 0x96, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0xb9, 0x96, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0xb9, 0x96, 0x00, 0x02, - 0x10, 0xc0, 0x00, 0x00, 0xf9, 0x96, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0x98, 0x93, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x10, 0xb1, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0x08, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5c, - 0x1f, 0x90, 0x00, 0x00, 0x01, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40, - 0x27, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xb0, 0x01, 0x00, - 0xc3, 0x94, 0x00, 0x41, 0xa3, 0x41, 0x01, 0x00, 0x05, 0x97, 0x00, 0x41, - 0x27, 0xd0, 0x00, 0x00, 0x36, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x02, 0x99, 0x00, 0x40, 0x8a, 0x30, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x80, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x14, 0xbb, 0x80, 0x32, 0x00, 0x00, 0x0e, 0x97, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x64, 0x97, 0x00, 0x40, 0x2b, 0x30, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x06, - 0x16, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x16, 0xc4, 0x01, 0x00, - 0x18, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x6c, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x40, - 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xf0, 0x28, 0xb0, 0x01, 0x00, - 0x21, 0x97, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43, - 0x86, 0xc8, 0x01, 0x00, 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00, - 0x21, 0x97, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x44, 0x97, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00, - 0x2f, 0x97, 0xa2, 0x06, 0x14, 0x6c, 0x00, 0x00, 0x2c, 0x97, 0x22, 0x48, - 0x19, 0x7c, 0x00, 0x00, 0x26, 0x97, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x31, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00, - 0x8b, 0x00, 0x2d, 0x48, 0x19, 0x80, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x45, - 0xe7, 0x7d, 0x00, 0x00, 0x8b, 0x00, 0x20, 0x45, 0xe7, 0x91, 0x01, 0x00, - 0x2f, 0x97, 0x00, 0x40, 0x87, 0x90, 0x00, 0x00, 0x08, 0x00, 0x00, 0x43, - 0x86, 0x98, 0x01, 0x00, 0x2f, 0x97, 0xa0, 0x48, 0x17, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43, 0xfc, 0xc9, 0x01, 0x00, - 0xa8, 0x97, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0x3a, 0x97, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, - 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00, - 0x39, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x3e, 0x97, 0x64, 0xf0, 0x82, 0xb0, 0x00, 0x00, - 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x3e, 0x97, 0xa2, 0xf2, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe5, 0xb1, 0x01, 0x00, - 0x8c, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x06, 0x30, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x86, 0x0c, 0x80, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x49, - 0x19, 0x7c, 0x00, 0x00, 0xbc, 0x00, 0x2d, 0x46, 0x19, 0x90, 0x01, 0x00, - 0xa0, 0x00, 0xa0, 0xf2, 0xe4, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43, 0xfc, 0xc9, 0x01, 0x00, - 0xa8, 0x97, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x4a, - 0x19, 0xfc, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, - 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, - 0x17, 0xc0, 0x01, 0x00, 0x4d, 0x97, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xe4, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x1b, - 0xe0, 0xb1, 0x00, 0x00, 0x52, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0xf0, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x4c, - 0x95, 0x60, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4a, 0x18, 0x94, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x01, - 0xf0, 0x31, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x15, 0xe0, 0xb1, 0x00, 0x00, 0x5d, 0x97, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x10, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x06, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xe8, 0x5f, 0x17, 0x90, 0x01, 0x00, - 0x70, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x7a, 0x01, 0x2e, 0xfe, - 0x92, 0xb0, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0xf6, 0x16, 0xb0, 0x01, 0x00, - 0x6a, 0x97, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x45, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0xa6, 0x2a, 0xb0, 0x01, 0x00, - 0x28, 0x00, 0x6e, 0x06, 0x82, 0xc8, 0x01, 0x00, 0x6e, 0x97, 0x22, 0x4a, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x6e, 0x4c, 0x83, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x92, 0xc0, 0x01, 0x00, 0x6f, 0x97, 0x43, 0x30, 0x3d, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x9e, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x41, - 0x3d, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x92, 0xc0, 0x01, 0x00, - 0x06, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x49, - 0x98, 0xf4, 0x01, 0x00, 0x78, 0x97, 0x26, 0x30, 0x93, 0x04, 0x00, 0x00, - 0x78, 0x97, 0x90, 0x4c, 0x92, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x93, 0xc0, 0x01, 0x00, 0xff, 0xff, 0x80, 0x49, 0xec, 0xa9, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x01, - 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x15, 0xe0, 0xb1, 0x00, 0x00, - 0x7d, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x20, - 0x81, 0x6c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, 0x81, 0x6c, 0x00, 0x00, - 0x8f, 0x97, 0x22, 0x5f, 0x81, 0x7c, 0x00, 0x00, 0x8c, 0x97, 0xa2, 0x40, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x19, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x97, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x8c, 0x97, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, - 0x88, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x25, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x40, 0x8a, 0x30, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x21, 0x81, 0x84, 0x00, 0x00, 0x92, 0x97, 0xa2, 0x5f, - 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x43, 0x19, 0x7c, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x19, 0x90, 0x01, 0x00, 0x25, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x40, 0x8a, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x96, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, - 0x97, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x22, 0x08, - 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, - 0xa0, 0x97, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0xb4, 0x05, 0x00, 0x02, - 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x02, - 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x13, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x08, 0xe0, 0xb1, 0x00, 0x00, 0xa5, 0x97, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0xb0, 0x00, 0x00, 0xa1, 0x80, 0xce, 0x01, 0x00, 0x04, 0x00, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, - 0x02, 0x00, 0x00, 0xf0, 0x98, 0xf4, 0x01, 0x00, 0xb1, 0x97, 0x20, 0x4c, - 0x84, 0x6c, 0x00, 0x00, 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xb1, 0x97, 0x20, 0xf2, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x98, 0x00, 0x2d, 0x14, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x98, 0xb0, 0x01, 0x00, 0xa3, 0x00, 0x2d, 0x14, - 0x98, 0xd0, 0x01, 0x00, 0xb6, 0x97, 0x20, 0x4c, 0x84, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x84, 0xb0, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x30, - 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x80, 0xe0, 0x01, 0x00, - 0xba, 0x97, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x84, 0xb0, 0x01, 0x00, 0xd0, 0x00, 0x20, 0x14, 0xe0, 0xb1, 0x01, 0x00, - 0x98, 0x00, 0x25, 0x42, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xf3, - 0x80, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x42, 0x82, 0xc0, 0x00, 0x00, - 0xc0, 0x97, 0xa0, 0x40, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0, 0x82, 0xec, 0x00, 0x00, - 0x98, 0x00, 0xa0, 0x41, 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x37, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, - 0x02, 0x99, 0x00, 0x05, 0x8a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0xa8, 0x01, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, - 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x60, 0xa7, 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xcb, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x1c, - 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0, 0x8a, 0xd0, 0x00, 0x00, - 0x00, 0x00, 0xa2, 0x40, 0x8b, 0xec, 0x00, 0x00, 0x8a, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xa4, 0x00, 0x2d, 0x45, 0xe0, 0xd1, 0x01, 0x00, 0xd9, 0x97, 0x9c, 0x17, - 0x80, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, - 0xbe, 0x00, 0x2f, 0xab, 0x83, 0xb0, 0x01, 0x00, 0x35, 0x98, 0x00, 0x14, - 0x82, 0x50, 0x01, 0x00, 0xde, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xde, 0x97, 0x22, 0xf2, 0x82, 0x30, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xde, 0x97, 0x9f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, - 0xbe, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x35, 0x98, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xa8, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, - 0x9c, 0x00, 0x2d, 0x30, 0x81, 0xb0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, - 0x84, 0xb0, 0x01, 0x00, 0x94, 0x00, 0x2d, 0xf2, 0x86, 0xb0, 0x01, 0x00, - 0xf2, 0x97, 0x23, 0xf0, 0x84, 0x6c, 0x00, 0x00, 0xe6, 0x97, 0x23, 0x92, - 0x87, 0x6c, 0x00, 0x00, 0xc9, 0x04, 0x00, 0xa6, 0x94, 0xb0, 0x01, 0x00, - 0xe8, 0x97, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x94, 0xb0, 0x01, 0x00, 0x60, 0x89, 0x00, 0x4a, 0x94, 0x98, 0x01, 0x00, - 0xe8, 0x97, 0x68, 0x40, 0x81, 0x32, 0x00, 0x00, 0x04, 0x00, 0x22, 0x40, - 0xbd, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xb0, 0xb1, 0x01, 0x00, - 0xbf, 0x00, 0x2d, 0x42, 0xb2, 0xb1, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3, - 0x80, 0xe0, 0x01, 0x00, 0xed, 0x97, 0xd4, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x78, 0xda, 0x84, 0xc0, 0x01, 0x00, 0xf7, 0x97, 0x23, 0x40, - 0x84, 0x6c, 0x00, 0x00, 0x94, 0x00, 0x20, 0x9d, 0xe1, 0xb1, 0x01, 0x00, - 0xf7, 0x97, 0x00, 0x40, 0x84, 0xb0, 0x00, 0x00, 0xbf, 0x00, 0x2d, 0x43, - 0x84, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3, 0x80, 0xe0, 0x01, 0x00, - 0xf7, 0x97, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, 0x94, 0x00, 0x20, 0x9d, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x84, 0xb0, 0x01, 0x00, - 0xfb, 0x97, 0xa2, 0xf0, 0x38, 0x6c, 0x00, 0x00, 0x9c, 0x00, 0x20, 0x42, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x46, 0x19, 0x80, 0x01, 0x00, 0x9c, 0x00, 0x20, 0x42, - 0xe0, 0xb1, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xf3, 0x80, 0xf4, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, - 0x82, 0x88, 0x01, 0x00, 0x01, 0x98, 0x23, 0x41, 0x80, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00, 0x00, 0x00, 0x89, 0x0c, - 0x80, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x86, 0x0c, 0x80, 0x32, 0x00, 0x00, - 0xbc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xa0, 0x00, 0xa0, 0xf2, - 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x41, 0x24, 0xec, 0x00, 0x00, - 0x0d, 0x98, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x42, - 0x38, 0xec, 0x00, 0x00, 0x0d, 0x98, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x0f, 0x98, 0xa3, 0xf0, - 0x3a, 0x6c, 0x00, 0x00, 0x04, 0x00, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x13, 0x98, 0x22, 0xf0, 0x3a, 0x6c, 0x00, 0x00, - 0xb4, 0x00, 0x20, 0x1d, 0xe0, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x5f, - 0x13, 0x94, 0x01, 0x00, 0x13, 0x98, 0x23, 0xf0, 0x3a, 0x6c, 0x00, 0x00, - 0x80, 0x00, 0x20, 0x1d, 0xe0, 0xb1, 0x01, 0x00, 0xc0, 0x00, 0x20, 0x12, - 0xe0, 0xb1, 0x01, 0x00, 0xc4, 0x00, 0xa0, 0x1c, 0xe0, 0xb1, 0x01, 0x00, - 0x27, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x42, - 0x8a, 0x30, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xe0, 0xb1, 0x01, 0x00, 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x1f, 0x98, 0x9f, 0x41, 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, 0x8c, 0xd0, 0x01, 0x00, - 0x20, 0x98, 0x00, 0x41, 0x24, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0x78, 0x98, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x22, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xae, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0x80, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0xa7, 0x08, 0x80, 0x32, 0x01, 0x00, 0x32, 0x04, 0x00, 0x40, - 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x08, 0x8a, 0x30, 0x01, 0x00, - 0x2c, 0x98, 0xa2, 0x40, 0x95, 0x6c, 0x00, 0x00, 0xc3, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, - 0xa0, 0x98, 0x2f, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41, - 0x89, 0xb0, 0x00, 0x00, 0xcc, 0x00, 0x00, 0xa1, 0x80, 0xce, 0x01, 0x00, - 0x04, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xf8, - 0x3e, 0xec, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x12, 0xe0, 0xed, 0x00, 0x00, - 0xc8, 0x00, 0x20, 0xab, 0xe1, 0xb1, 0x01, 0x00, 0xcc, 0x00, 0xa0, 0x1f, - 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, - 0x38, 0x98, 0xa3, 0x5f, 0xe7, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xe7, 0xc1, 0x01, 0x00, 0xa6, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x4c, 0x98, 0x22, 0xf2, 0x86, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x43, - 0x84, 0xf4, 0x01, 0x00, 0x01, 0x00, 0x00, 0x41, 0x80, 0xcc, 0x01, 0x00, - 0xb8, 0x00, 0x2d, 0x42, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x62, 0x40, - 0x86, 0xc0, 0x01, 0x00, 0x40, 0x98, 0x1f, 0x43, 0x80, 0x32, 0x00, 0x00, - 0x41, 0x98, 0xa2, 0x40, 0x87, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x62, 0x41, - 0x87, 0xb0, 0x01, 0x00, 0x45, 0x98, 0x9f, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x84, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x88, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x44, - 0x84, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2e, 0x42, 0x80, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x62, 0x40, 0x88, 0xc0, 0x01, 0x00, 0x4b, 0x98, 0x1f, 0x44, - 0x80, 0x32, 0x00, 0x00, 0x4f, 0x98, 0xa2, 0x40, 0x89, 0x6c, 0x00, 0x00, - 0x4f, 0x98, 0x62, 0x41, 0x89, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x62, 0x41, - 0x86, 0xe4, 0x01, 0x00, 0xb8, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x62, 0x41, 0x88, 0xe4, 0x01, 0x00, 0xa4, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0xa2, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xbc, 0x00, 0x2e, 0x43, 0x87, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x86, 0xc0, 0x01, 0x00, 0x55, 0x98, 0x20, 0x43, 0x87, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x43, 0xe5, 0xb1, 0x01, 0x00, 0x40, 0x01, 0x00, 0x43, - 0x80, 0xce, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x43, 0xe4, 0x31, 0x01, 0x00, - 0x40, 0x01, 0xe2, 0x40, 0x87, 0x98, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x05, - 0x48, 0x6d, 0x00, 0x00, 0x04, 0x00, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, - 0x88, 0x00, 0x2d, 0x44, 0x81, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf2, - 0x2e, 0xb0, 0x01, 0x00, 0x9c, 0x00, 0x2d, 0xf0, 0x86, 0xb0, 0x01, 0x00, - 0x90, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0xba, 0x00, 0x2d, 0xf0, - 0x98, 0xb0, 0x01, 0x00, 0x64, 0x98, 0xa2, 0x12, 0x98, 0x6c, 0x00, 0x00, - 0xbc, 0x00, 0x2d, 0xf2, 0x98, 0xb0, 0x01, 0x00, 0x64, 0x98, 0xa0, 0xf2, - 0x98, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x82, 0xb0, 0x01, 0x00, - 0x9c, 0x00, 0x20, 0x41, 0xe0, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x2d, 0x12, - 0x86, 0xd0, 0x01, 0x00, 0x67, 0x98, 0xa3, 0x41, 0xe0, 0x6d, 0x00, 0x00, - 0x68, 0x98, 0x00, 0xf0, 0x84, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x84, 0xb0, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x43, 0x84, 0xd0, 0x01, 0x00, - 0x6b, 0x98, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x6d, 0x98, 0xa3, 0x42, 0x14, 0x6c, 0x00, 0x00, - 0x6e, 0x98, 0x00, 0x0a, 0x0c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x0c, 0xb0, 0x01, 0x00, 0x70, 0x98, 0xa0, 0x17, 0x0c, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x17, 0x0c, 0xb0, 0x01, 0x00, 0x75, 0x98, 0x22, 0x40, - 0x0d, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x0c, 0xec, 0x00, 0x00, - 0x01, 0x00, 0x00, 0xf0, 0x82, 0xf4, 0x01, 0x00, 0x75, 0x98, 0xa0, 0x41, - 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xf0, 0x80, 0x32, 0x01, 0x00, - 0x29, 0x00, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0xcb, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x00, 0x22, 0x03, - 0x80, 0x32, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x46, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x41, 0x87, 0x94, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x49, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, - 0x05, 0x90, 0x00, 0x00, 0x84, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0xa2, 0x05, 0x48, 0x6d, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0c, - 0x96, 0xf4, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x07, 0x96, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00, 0x05, 0x00, 0x2a, 0x0c, - 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04, 0xe6, 0xb1, 0x01, 0x00, - 0x3e, 0x04, 0x00, 0x40, 0x89, 0x98, 0x01, 0x00, 0x02, 0x99, 0x00, 0x08, - 0x8a, 0x30, 0x01, 0x00, 0x8f, 0x98, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0x95, 0x98, 0x28, 0x40, - 0x87, 0x30, 0x00, 0x00, 0x90, 0x98, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x40, 0x27, 0x6c, 0x00, 0x00, 0x04, 0x97, 0x1d, 0x46, - 0x87, 0xb0, 0x00, 0x00, 0x98, 0x98, 0x22, 0x5f, 0x11, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0x22, 0x15, 0x62, 0x31, 0x00, 0x00, 0x96, 0x98, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x14, 0x2f, 0x4c, - 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x9b, 0x98, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0xb0, 0x01, 0x00, - 0xef, 0x98, 0x00, 0x49, 0x96, 0x30, 0x01, 0x00, 0x07, 0x00, 0x00, 0x49, - 0x06, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x03, 0x06, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xd0, - 0xa0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, - 0xa2, 0x98, 0xa0, 0x54, 0x93, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x05, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa2, - 0x44, 0xc9, 0x01, 0x00, 0xab, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x49, 0xb3, 0x01, 0x00, 0xf5, 0x98, 0x00, 0x40, - 0x49, 0x31, 0x01, 0x00, 0x02, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0xb5, 0x2e, 0x08, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xb2, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0x97, 0x2e, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0xb6, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x2e, 0x05, 0x97, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0xba, 0x98, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x57, 0x95, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x30, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xb8, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00, 0xba, 0x94, 0x20, 0x41, - 0xe5, 0xb1, 0x01, 0x00, 0x98, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xc4, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x6f, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x68, 0xb1, 0x01, 0x00, - 0xc8, 0x98, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00, 0x80, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x39, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x37, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x35, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x33, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x41, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x3f, 0xb3, 0x01, 0x00, 0xee, 0x05, 0x00, 0x40, 0x25, 0x9b, 0x01, 0x00, - 0x42, 0x00, 0x00, 0x40, 0x4b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x2f, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2d, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x47, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x43, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40, 0x2b, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, - 0xf1, 0x93, 0x01, 0x00, 0xff, 0xff, 0x00, 0xa5, 0x3c, 0x8b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x2c, 0x5b, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2c, - 0x45, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x59, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x57, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x27, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x53, 0xb3, 0x01, 0x00, - 0xe4, 0x98, 0xa2, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0xe4, 0x98, 0xa2, 0x51, - 0xfd, 0x7f, 0x00, 0x00, 0xe5, 0x98, 0x00, 0x40, 0x1d, 0xb3, 0x00, 0x00, - 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x00, 0xc0, 0x00, 0xa6, - 0x88, 0xb3, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xa6, 0x3a, 0xb3, 0x01, 0x00, - 0x00, 0xc0, 0x00, 0x9d, 0x3b, 0x9b, 0x01, 0x00, 0xb4, 0x05, 0x00, 0x40, - 0x23, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x4d, 0xb3, 0x01, 0x00, - 0x08, 0x0a, 0x00, 0xa6, 0x14, 0xb3, 0x01, 0x00, 0x01, 0x01, 0x00, 0x8a, - 0x15, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x87, 0xb3, 0x01, 0x00, - 0x00, 0x80, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5e, - 0x57, 0xb5, 0x01, 0x00, 0x18, 0x00, 0x00, 0x4b, 0x20, 0xe4, 0x01, 0x00, - 0x06, 0x00, 0x00, 0x4b, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x43, 0x00, 0x4b, - 0x96, 0xc8, 0x01, 0x00, 0x18, 0x00, 0x00, 0x10, 0x20, 0xdc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x20, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x57, - 0x21, 0x90, 0x01, 0x00, 0x00, 0x99, 0x2e, 0x0a, 0x97, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0xf6, 0x98, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x00, 0xa9, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xfa, 0x98, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, - 0xfe, 0x98, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xfe, 0x98, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, - 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x99, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x88, 0x94, 0x01, 0x00, - 0x08, 0x99, 0x6a, 0x40, 0x81, 0x32, 0x00, 0x00, 0x0b, 0x99, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x62, 0xb1, 0x01, 0x00, 0x0c, 0x99, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x13, 0x99, 0x22, 0x4a, 0x89, 0x7c, 0x00, 0x00, 0x11, 0x99, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0x11, 0x99, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0xa2, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x98, 0xf4, 0x01, 0x00, - 0x04, 0x00, 0xa2, 0x5f, 0x99, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, - 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, - 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, - 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x88, 0x9a, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x41, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xb2, 0x9f, 0x22, 0x40, 0x7b, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x19, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x19, 0x41, 0x7b, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0xc4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1, - 0xc6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x2f, 0xa2, 0xc8, 0xb3, 0x01, 0x00, - 0x08, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0xa8, 0x9f, 0x00, 0x4d, - 0x9a, 0xcc, 0x01, 0x00, 0xbb, 0x9f, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x49, 0xc1, 0x01, 0x00, 0xb9, 0x9f, 0xa2, 0x41, - 0x9b, 0x50, 0x00, 0x00, 0xbf, 0x9f, 0x80, 0x80, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x52, 0x49, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0xfd, 0x93, 0x01, 0x00, 0xc2, 0x9f, 0x00, 0x42, 0xcd, 0x93, 0x00, 0x00, - 0x00, 0x00, 0x51, 0x4a, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xfd, 0x93, 0x01, 0x00, 0xc2, 0x9f, 0x00, 0x43, 0xcb, 0x93, 0x00, 0x00, - 0x00, 0x00, 0x50, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xd2, 0x9f, 0x00, 0x40, - 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x40, 0xf0, - 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0x4d, 0x80, 0xb2, 0x01, 0x00, - 0xca, 0x9f, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d, - 0x10, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x49, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xe3, 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe4, - 0x45, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7b, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x48, 0x4f, 0x40, 0xb1, 0x01, 0x00, 0xd2, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xcb, - 0x81, 0xc8, 0x01, 0x00, 0x22, 0x83, 0x00, 0x40, 0xf2, 0x93, 0x00, 0x00, - 0x55, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x18, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x22, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x43, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x41, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb8, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xed, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x23, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x27, 0x83, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xb9, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x8d, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x79, 0x94, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x78, 0x98, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x87, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x95, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x0a, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb1, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x19, 0x99, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, - }, -}; diff --git a/drivers/staging/slicoss/oasisdownload.h b/drivers/staging/slicoss/oasisdownload.h deleted file mode 100644 index 6438c23d7548..000000000000 --- a/drivers/staging/slicoss/oasisdownload.h +++ /dev/null @@ -1,6848 +0,0 @@ -#define OASIS_UCODE_VERS_STRING "1.2" -#define OASIS_UCODE_VERS_DATE "2006/03/27 15:10:37" -#define OASIS_UCODE_HOSTIF_ID 3 - -static s32 ONumSections = 0x2; -static u32 OSectionSize[] = { - 0x00004000, 0x00010000, -}; - -static u32 OSectionStart[] = { - 0x00000000, 0x00008000, -}; - -static u8 OasisUCode[2][65536] = -{ - { - 0x15, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, - 0x98, 0xb0, 0x01, 0x00, 0x04, 0x80, 0xa2, 0x40, 0xfd, 0x7f, 0x00, 0x00, - 0x09, 0x00, 0xa2, 0x49, 0xdd, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x80, 0xb2, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x80, 0xb2, 0x01, 0x00, 0x09, 0x00, 0xa2, 0x40, - 0x75, 0x7d, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x0b, 0x00, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x8f, 0x98, 0x18, 0x31, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x98, 0x80, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x41, 0x98, - 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x98, 0x80, 0xe4, 0x01, 0x00, 0x0e, 0x00, 0x40, 0x98, - 0x80, 0x94, 0x00, 0x00, 0x11, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x19, 0x00, 0x29, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x19, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x0e, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x1f, 0x00, 0x29, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x12, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x40, 0xa5, 0x99, 0x01, 0x00, 0x25, 0x00, 0x29, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x25, 0x00, 0x14, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x14, 0x00, 0x93, 0xbc, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xdd, 0x81, 0x01, 0x00, 0x12, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x33, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2a, 0x00, 0x14, 0xbc, - 0x80, 0x32, 0x00, 0x00, 0xfe, 0x00, 0x13, 0xbc, 0x80, 0x32, 0x00, 0x00, - 0x54, 0x95, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xfd, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xb3, 0x01, 0x00, - 0x33, 0x00, 0x18, 0xee, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x89, 0xb0, 0x01, 0x00, 0x32, 0x00, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00, - 0x99, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x30, 0x94, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x20, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0xe0, 0xb3, 0x01, 0x00, 0x39, 0x00, 0x98, 0xee, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x80, 0xb0, 0x01, 0x00, - 0x3b, 0x00, 0x80, 0xf3, 0xde, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0xfd, 0x93, 0x01, 0x00, 0x3e, 0x00, 0x83, 0xf3, 0x80, 0x32, 0x00, 0x00, - 0xf0, 0x00, 0x00, 0xf3, 0x80, 0x88, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, - 0x2e, 0xdd, 0x01, 0x00, 0x00, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x43, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, - 0x24, 0xb1, 0x01, 0x00, 0x7c, 0x00, 0x18, 0xee, 0x80, 0x32, 0x00, 0x00, - 0x45, 0x00, 0x95, 0xe8, 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0xe8, - 0x80, 0x88, 0x01, 0x00, 0x7c, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd6, 0xb1, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xd6, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf8, 0xee, 0x8b, 0x01, 0x00, - 0x08, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf0, - 0x80, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x81, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0xf8, - 0x80, 0x88, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0xff, 0x00, 0x00, 0xf0, 0xd6, 0x8d, 0x01, 0x00, 0xff, 0xff, 0x00, 0xf0, - 0xf0, 0xdb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x81, 0x94, 0x01, 0x00, 0x3c, 0x01, 0x00, 0x40, - 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, - 0xff, 0x00, 0x00, 0xf8, 0x80, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0x81, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x81, 0x94, 0x01, 0x00, - 0x3c, 0x02, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xd6, 0xb1, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xd6, 0xb1, 0x01, 0x00, 0x1e, 0x00, 0x00, 0xf0, - 0x82, 0xf4, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xf8, 0x80, 0xd8, 0x01, 0x00, - 0x64, 0x00, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x81, 0xd0, 0x01, 0x00, 0xff, 0xff, 0x00, 0x40, 0x80, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x80, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xd8, 0xb1, 0x01, 0x00, 0x68, 0x00, 0x22, 0xfa, 0x80, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x81, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x40, - 0x80, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xde, 0xb1, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa, - 0x80, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x81, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd6, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, - 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa, 0x80, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf6, 0x81, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xd6, 0xb1, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0x10, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, - 0xd5, 0x99, 0x01, 0x00, 0x18, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, - 0x48, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0xfa, - 0xd6, 0xe5, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0xd5, 0x99, 0x01, 0x00, - 0x10, 0x00, 0x00, 0xfb, 0xd6, 0xe5, 0x01, 0x00, 0x03, 0x00, 0x00, 0xfb, - 0x7a, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xdc, 0xb1, 0x01, 0x00, - 0x7c, 0x00, 0x00, 0x4c, 0xdd, 0x91, 0x00, 0x00, 0x7c, 0x00, 0x95, 0xe8, - 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xe9, 0xfa, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xd1, 0xb1, 0x01, 0x00, 0xff, 0x00, 0x00, 0x42, - 0x80, 0x88, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, - 0x7c, 0x00, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x85, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x02, 0x80, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x7c, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x81, 0xb0, 0x01, 0x00, 0x8e, 0x00, 0x09, 0xf9, 0x81, 0x32, 0x00, 0x00, - 0x8c, 0x00, 0x08, 0xf9, 0x81, 0x32, 0x00, 0x00, 0x98, 0x00, 0x1f, 0xfd, - 0xf9, 0x33, 0x00, 0x00, 0x8b, 0x00, 0x9e, 0xfd, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, - 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf7, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x49, 0xf3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x19, 0xb1, 0x01, 0x00, 0x93, 0x00, 0x0a, 0xf9, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x40, 0xfb, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xfd, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x07, 0x80, 0xf9, 0xf3, 0x8f, 0x01, 0x00, - 0x00, 0x07, 0x42, 0xf9, 0xf3, 0x8f, 0x01, 0x00, 0x97, 0x00, 0xa2, 0xff, - 0xf7, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0xff, 0xfb, 0xef, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfc, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x94, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xbb, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x46, 0xfd, 0x7f, 0x01, 0x00, - 0x00, 0x94, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xce, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, 0xfd, 0x7f, 0x01, 0x00, - 0x00, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0xff, 0x7f, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x9a, 0x13, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x03, 0x01, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x9a, 0x13, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x02, 0x29, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x67, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0xfd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0xfd, 0x83, 0x01, 0x00, - 0xff, 0x7f, 0x00, 0x40, 0x25, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, 0x80, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0xfd, 0x93, 0x01, 0x00, 0xe2, 0x00, 0x00, 0x40, - 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x46, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x40, 0x2b, 0x31, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x46, 0x88, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x94, 0x8c, 0xb0, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x46, 0x80, 0x88, 0x01, 0x00, 0xa5, 0xa5, 0xa2, 0x40, - 0x80, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0xf0, 0x01, 0x00, - 0xc9, 0x00, 0x82, 0x41, 0x89, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xfd, 0x83, 0x01, 0x00, - 0xd4, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x44, - 0x80, 0xb2, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x08, 0x83, 0x30, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x45, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x44, - 0xfd, 0x93, 0x01, 0x00, 0x00, 0x30, 0x00, 0x08, 0x83, 0x98, 0x01, 0x00, - 0x80, 0x00, 0x00, 0x40, 0x2b, 0x99, 0x01, 0x00, 0xdb, 0x00, 0x00, 0x40, - 0x89, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x46, 0x80, 0xb2, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x94, 0x80, 0x88, 0x01, 0x00, 0xa5, 0xa5, 0xa2, 0x40, - 0x80, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x80, 0x43, 0x89, 0xb0, 0x01, 0x00, - 0x03, 0x84, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, 0xde, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x03, 0x88, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x96, - 0x80, 0xb2, 0x00, 0x00, 0xdf, 0x00, 0xa2, 0x41, 0x8d, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, - 0x25, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x89, 0xe0, 0x01, 0x00, - 0xdd, 0x00, 0x00, 0x44, 0x82, 0x14, 0x01, 0x00, 0x00, 0x00, 0x90, 0x94, - 0x8a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf0, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x89, 0xd0, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x44, 0x2b, 0x41, 0x01, 0x00, - 0xec, 0x00, 0x08, 0x41, 0x80, 0x32, 0x00, 0x00, 0xed, 0x00, 0x00, 0x94, - 0x24, 0xb1, 0x00, 0x00, 0x10, 0x00, 0x00, 0x94, 0x24, 0xf5, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x94, 0xf0, 0xb1, 0x01, 0x00, 0xf2, 0x00, 0xa0, 0x44, - 0x89, 0x50, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x44, 0x2b, 0x41, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x94, 0xf0, 0xb1, 0x01, 0x00, 0xef, 0x00, 0x20, 0x44, - 0x89, 0x50, 0x00, 0x00, 0x10, 0x00, 0x00, 0x45, 0x88, 0xf4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x42, - 0x89, 0xd0, 0x00, 0x00, 0xf7, 0x00, 0xa0, 0xfa, 0x8a, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, 0xf5, 0x00, 0xa3, 0x42, - 0x89, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0x45, 0x88, 0x88, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x45, 0x8a, 0xf4, 0x01, 0x00, 0xfc, 0x00, 0x90, 0x44, - 0x8a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8b, 0xc0, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x45, 0x8a, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x50, - 0x8b, 0xe0, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x40, 0x25, 0x99, 0x01, 0x00, - 0x7c, 0x00, 0x00, 0x40, 0x2b, 0x99, 0x01, 0x00, 0x00, 0x30, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x08, 0x83, 0x14, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x94, 0x2a, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, - 0xf9, 0x9b, 0x01, 0x00, 0xdd, 0x00, 0x00, 0xfc, 0x19, 0x31, 0x01, 0x00, - 0x00, 0x00, 0x40, 0x94, 0x80, 0xb2, 0x01, 0x00, 0xdd, 0x00, 0x00, 0x44, - 0x2b, 0x41, 0x01, 0x00, 0x00, 0x00, 0x41, 0x94, 0x80, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xf9, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x2b, 0xc1, 0x01, 0x00, 0x04, 0x01, 0x9f, 0x94, 0x80, 0x32, 0x00, 0x00, - 0x02, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x01, 0x00, 0x51, - 0x93, 0xb0, 0x00, 0x00, 0x10, 0x01, 0x00, 0x4d, 0x93, 0xb0, 0x00, 0x00, - 0x10, 0x01, 0x00, 0x49, 0x93, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x93, 0xb0, 0x01, 0x00, 0x10, 0x01, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x12, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x13, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x15, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x16, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x17, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x18, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x19, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x1b, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x1e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x70, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x71, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x72, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x73, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x74, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x75, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x76, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x77, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x78, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x79, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x7a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7b, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x7d, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7e, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa1, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x19, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x15, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0b, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x09, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x07, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x01, 0xb0, 0x01, 0x00, 0x3b, 0x01, 0x20, 0x48, 0xa1, 0x51, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x47, 0x01, 0x22, 0x4b, - 0x74, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x60, 0x00, 0x00, 0x4b, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1, - 0x7e, 0xb1, 0x01, 0x00, 0x48, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x45, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x05, 0x00, 0x80, 0x40, - 0x97, 0x98, 0x01, 0x00, 0x18, 0x00, 0x00, 0xaa, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x43, 0x97, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0xaa, - 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x58, 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, - 0xd8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x07, 0x90, 0x01, 0x00, - 0xd8, 0x9f, 0x00, 0x40, 0xbf, 0xb3, 0x00, 0x00, 0x5a, 0x01, 0x22, 0xcc, - 0x85, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x07, 0x90, 0x01, 0x00, - 0xd8, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, - 0xd0, 0x14, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe1, 0xb1, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, - 0x62, 0xdd, 0x01, 0x00, 0x63, 0x01, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xcc, 0x85, 0x93, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, - 0xa4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbc, 0xb3, 0x01, 0x00, - 0x00, 0x14, 0x2f, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe7, - 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00, - 0xff, 0x00, 0x00, 0xdd, 0x81, 0x88, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, - 0x80, 0xf4, 0x01, 0x00, 0x73, 0x01, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00, - 0x86, 0x01, 0x00, 0xdd, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x10, 0xb1, 0x00, 0x00, 0x87, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x88, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x89, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x8b, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xc4, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x82, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x83, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, 0xb8, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x28, 0x00, 0xd4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, - 0xd5, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, 0xd6, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x28, 0x00, 0xd7, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x28, 0x00, - 0x72, 0x01, 0x00, 0x41, 0x81, 0xc0, 0x28, 0x00, 0x55, 0x01, 0x51, 0x49, - 0xfd, 0x93, 0x28, 0x00, 0x55, 0x01, 0x52, 0x4a, 0xfd, 0x93, 0x2a, 0x00, - 0x55, 0x01, 0x55, 0x49, 0xfd, 0x83, 0x2a, 0x00, 0x55, 0x01, 0x56, 0x4a, - 0xfd, 0x83, 0x2a, 0x00, 0x50, 0x01, 0x91, 0x81, 0x80, 0x30, 0x2a, 0x00, - 0x55, 0x01, 0x45, 0x40, 0x81, 0xb2, 0x2a, 0x00, 0x50, 0x01, 0x91, 0x82, - 0x80, 0x30, 0x2a, 0x00, 0x55, 0x01, 0x46, 0x40, 0x81, 0xb2, 0x2a, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x89, 0xb0, 0x2b, 0x00, 0x00, 0x00, 0x2f, 0x40, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, - 0xb3, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, - 0x92, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x49, 0xd1, 0x01, 0x00, 0x9a, 0x01, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00, - 0x96, 0x01, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x50, 0x01, 0x00, 0x41, - 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xbf, 0xb3, 0x01, 0x00, - 0x50, 0x01, 0xa0, 0x0f, 0xbd, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00, - 0xb5, 0x01, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x42, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, 0x85, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xde, 0x19, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x42, 0xff, - 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, 0xe1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x2f, 0xff, - 0xe1, 0xb1, 0x01, 0x00, 0x08, 0x14, 0x00, 0xa4, 0x80, 0xcc, 0x01, 0x00, - 0xaa, 0x01, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x85, 0xc0, 0x01, 0x00, 0xa8, 0x01, 0xa2, 0x4c, 0x81, 0x50, 0x00, 0x00, - 0xb4, 0x01, 0x22, 0xd2, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x01, 0x22, 0x41, - 0xa5, 0x6f, 0x00, 0x00, 0x50, 0x01, 0xa2, 0xe0, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x89, 0x90, 0x01, 0x00, 0x00, 0x00, 0x40, 0x42, 0x80, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x41, 0x43, 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x88, 0x94, 0x01, 0x00, 0x55, 0x01, 0x00, 0x44, 0xe0, 0xb1, 0x00, 0x00, - 0xb1, 0x01, 0x00, 0x48, 0x49, 0xc1, 0x00, 0x00, 0xaf, 0x01, 0x00, 0x5b, - 0x89, 0x90, 0x00, 0x00, 0xa8, 0x9f, 0x00, 0xa0, 0x9e, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x40, - 0x49, 0x99, 0x01, 0x00, 0x00, 0x00, 0x23, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0xbe, 0x01, 0x22, 0xde, 0xe1, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, - 0xb9, 0x01, 0xa2, 0x44, 0x81, 0x6c, 0x00, 0x00, 0x50, 0x01, 0x00, 0x43, - 0xbf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x40, 0xf8, 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0xf0, - 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x55, 0x01, 0x00, 0x40, - 0xe1, 0xb1, 0x00, 0x00, 0xc6, 0x01, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x91, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0xcb, 0x01, 0x00, 0x40, - 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00, - 0xd1, 0x01, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0x53, 0x01, 0x00, 0xde, - 0xa1, 0xb3, 0x00, 0x00, 0xe3, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xe5, 0x01, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, 0xeb, 0x01, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x52, 0x01, 0x00, 0xdf, 0xe1, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, - 0xa1, 0xb1, 0x01, 0x00, 0x02, 0x00, 0x00, 0xd2, 0xa5, 0xe7, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xc1, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb1, 0x01, 0x00, 0xdb, 0x01, 0x22, 0x44, 0xc1, 0x53, 0x00, 0x00, - 0xda, 0x01, 0x84, 0x41, 0x81, 0x40, 0x00, 0x00, 0xde, 0x01, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x45, 0xb1, 0x01, 0x00, - 0xd5, 0x01, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00, 0xda, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x55, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00, - 0xda, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x00, 0xd3, - 0xa7, 0xcb, 0x01, 0x00, 0xf8, 0x02, 0x00, 0xe0, 0xa5, 0xb3, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, 0x53, 0x01, 0x00, 0xde, - 0xa1, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xbf, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xde, 0x81, 0x90, 0x01, 0x00, 0x50, 0x01, 0xa2, 0xba, - 0x80, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00, 0xde, 0x61, 0x99, 0x01, 0x00, - 0xe8, 0x01, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x52, 0x01, 0x00, 0x40, - 0xe0, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xba, 0xb3, 0x01, 0x00, - 0x6b, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x4d, - 0x83, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe1, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xe3, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xe5, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xe9, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xeb, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xf5, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf7, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xf9, 0xb3, 0x01, 0x00, 0xf9, 0x01, 0x22, 0x40, - 0x8f, 0x6f, 0x00, 0x00, 0x78, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0x60, 0x02, 0x00, 0xc7, 0x83, 0x30, 0x01, 0x00, 0x80, 0x02, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x42, 0x83, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xe8, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xea, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x85, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xec, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xed, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb2, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xac, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xb9, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xba, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xf0, 0xb1, 0x01, 0x00, - 0x0c, 0x02, 0xb8, 0x40, 0x81, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0x90, 0x01, 0x00, 0x0e, 0x02, 0xb9, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0x90, 0x01, 0x00, 0x10, 0x02, 0xba, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x81, 0x90, 0x01, 0x00, - 0x12, 0x02, 0xbb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x81, 0x90, 0x01, 0x00, 0x14, 0x02, 0xbc, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x81, 0x90, 0x01, 0x00, 0x16, 0x02, 0xbd, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x81, 0x90, 0x01, 0x00, - 0x18, 0x02, 0xbe, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x81, 0x90, 0x01, 0x00, 0x1a, 0x02, 0xbf, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x81, 0x90, 0x01, 0x00, 0x1c, 0x02, 0xc8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0x90, 0x01, 0x00, - 0x1e, 0x02, 0xc9, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x81, 0x90, 0x01, 0x00, 0x20, 0x02, 0xca, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x81, 0x90, 0x01, 0x00, 0x22, 0x02, 0xcb, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x81, 0x90, 0x01, 0x00, - 0x24, 0x02, 0xcc, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x81, 0x90, 0x01, 0x00, 0x26, 0x02, 0xcd, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4d, 0x81, 0x90, 0x01, 0x00, 0x28, 0x02, 0xce, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0x90, 0x01, 0x00, - 0x2a, 0x02, 0xcf, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x81, 0x90, 0x01, 0x00, 0x2c, 0x02, 0xf0, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x81, 0x90, 0x01, 0x00, 0x2e, 0x02, 0xf1, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x81, 0x90, 0x01, 0x00, - 0x30, 0x02, 0xf2, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, - 0x81, 0x90, 0x01, 0x00, 0x32, 0x02, 0xf3, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x53, 0x81, 0x90, 0x01, 0x00, 0x34, 0x02, 0xf4, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x81, 0x90, 0x01, 0x00, - 0x36, 0x02, 0xf5, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x81, 0x90, 0x01, 0x00, 0x38, 0x02, 0xf6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x56, 0x81, 0x90, 0x01, 0x00, 0x3a, 0x02, 0xf7, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x81, 0x90, 0x01, 0x00, - 0x3c, 0x02, 0xf8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, - 0x81, 0x90, 0x01, 0x00, 0x3e, 0x02, 0xf9, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x59, 0x81, 0x90, 0x01, 0x00, 0x40, 0x02, 0xfa, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x81, 0x90, 0x01, 0x00, - 0x42, 0x02, 0xfb, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, - 0x81, 0x90, 0x01, 0x00, 0x44, 0x02, 0xfc, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x81, 0x90, 0x01, 0x00, 0x46, 0x02, 0xfd, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x81, 0x90, 0x01, 0x00, - 0x48, 0x02, 0xfe, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, - 0x81, 0x90, 0x01, 0x00, 0x4a, 0x02, 0xff, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0xa5, 0x9b, 0x01, 0x00, - 0xd8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd0, 0x14, 0x2e, 0x06, 0xa5, 0xb3, 0x01, 0x00, - 0x40, 0x00, 0x00, 0xd3, 0xa7, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf5, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xeb, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xf1, 0xb1, 0x01, 0x00, - 0xdb, 0x01, 0x00, 0xc7, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x66, 0x02, 0x00, 0x48, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x51, 0x40, 0x1a, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x63, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x5f, 0x02, 0x49, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40, 0x1c, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x4e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x68, 0x02, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x5f, 0x02, 0x4a, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, - 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xd8, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa1, 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, - 0xd2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xd4, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, - 0xdc, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xde, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x88, 0xda, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, - 0x8e, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xe6, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xac, 0xec, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x99, - 0xfa, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe0, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd5, 0xe2, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, - 0xe4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xe8, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd5, 0xea, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, - 0xf4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xf6, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd5, 0xf8, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc7, - 0xa9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00, - 0x84, 0x02, 0x00, 0x40, 0x91, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x91, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x40, 0xa3, 0x9b, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0x88, 0x02, 0x00, 0x40, - 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb1, 0x00, 0x00, - 0x8d, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x98, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x98, 0x02, 0x00, 0x46, 0xa3, 0xb3, 0x00, 0x00, - 0x9b, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa1, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8f, 0x02, 0x23, 0x50, 0xa5, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xa5, 0xb3, 0x01, 0x00, 0xe8, 0x02, 0x00, 0x42, - 0xa5, 0x63, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xba, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, 0xa1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0x97, 0x02, 0x22, 0x44, - 0xa5, 0x53, 0x00, 0x00, 0x94, 0x02, 0x00, 0x41, 0xa1, 0xc1, 0x00, 0x00, - 0x55, 0x01, 0x00, 0xdd, 0xa1, 0xb1, 0x00, 0x00, 0xe8, 0x02, 0x00, 0xde, - 0xa1, 0x33, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0xbf, 0xb3, 0x01, 0x00, 0x50, 0x01, 0xa2, 0xd2, 0x77, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xde, - 0x63, 0xb1, 0x01, 0x00, 0x9e, 0x02, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x54, - 0xa5, 0x33, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd0, 0x14, 0x2d, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xd0, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd2, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xd4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xd6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0xb1, 0x01, 0x00, - 0xac, 0x02, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x60, 0x02, 0x00, 0x46, - 0x83, 0x30, 0x01, 0x00, 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa0, 0x9e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe8, - 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x45, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xea, 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xeb, - 0xa1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x40, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd0, 0x14, 0x2e, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, - 0xa3, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc1, 0xb3, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xdd, 0x81, 0xf4, 0x01, 0x00, 0xbd, 0x02, 0x00, 0x40, - 0x10, 0xc9, 0x00, 0x00, 0xc3, 0x02, 0x00, 0x05, 0x81, 0xb0, 0x00, 0x00, - 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xcb, 0x02, 0x00, 0x05, - 0x81, 0xb0, 0x00, 0x00, 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd0, 0x02, 0x00, 0x44, 0xa5, 0xb3, 0x00, 0x00, 0xd2, 0x02, 0x00, 0x44, - 0xa5, 0xb3, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0xa4, 0xe7, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xe0, 0x81, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0xc1, - 0xf0, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x22, 0x41, 0x81, 0x50, 0x00, 0x00, - 0xc4, 0x02, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00, 0xda, 0x02, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf8, 0x02, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x55, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, - 0xa4, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x91, 0xb1, 0x01, 0x00, - 0xff, 0xff, 0x00, 0xc9, 0xf0, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x22, 0x41, - 0x81, 0x50, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x41, 0xc1, 0xc3, 0x00, 0x00, - 0xff, 0xff, 0x00, 0xde, 0x85, 0x89, 0x01, 0x00, 0xc8, 0x02, 0x00, 0xc2, - 0xe0, 0xb1, 0x00, 0x00, 0xff, 0xff, 0x00, 0xde, 0x95, 0x89, 0x01, 0x00, - 0xc8, 0x02, 0x00, 0xca, 0xe0, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd8, 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd4, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, 0xe2, 0x02, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x93, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe7, 0xa7, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd8, - 0xa9, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, - 0xf1, 0xb1, 0x01, 0x00, 0xe1, 0x02, 0x00, 0xd4, 0xe1, 0xb1, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xcc, - 0x85, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00, - 0xfa, 0x02, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0xf9, 0x02, 0xa2, 0xf2, - 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0x85, 0x83, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x41, - 0x99, 0xb3, 0x01, 0x00, 0x0a, 0x03, 0x22, 0x44, 0x81, 0x6c, 0x00, 0x00, - 0x12, 0x03, 0x22, 0x48, 0x81, 0x6c, 0x00, 0x00, 0x0c, 0x03, 0x22, 0x4c, - 0x81, 0x6c, 0x00, 0x00, 0x16, 0x03, 0x22, 0x50, 0x81, 0x6c, 0x00, 0x00, - 0x17, 0x03, 0x22, 0x54, 0x81, 0x6c, 0x00, 0x00, 0x19, 0x03, 0x22, 0x58, - 0x81, 0x6c, 0x00, 0x00, 0x1e, 0x03, 0x22, 0x5c, 0x81, 0x6c, 0x00, 0x00, - 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, - 0x09, 0xb0, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0xca, 0x01, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xf3, 0x83, 0x01, 0x00, 0x10, 0x03, 0xa2, 0x42, 0x05, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x05, 0xb0, 0x01, 0x00, 0xdd, 0x9f, 0x22, 0xca, - 0x07, 0x14, 0x00, 0x00, 0xdd, 0x9f, 0x00, 0x45, 0xf3, 0x93, 0x00, 0x00, - 0xdd, 0x9f, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00, 0xdd, 0x9f, 0x80, 0xca, - 0x05, 0x30, 0x00, 0x00, 0xdd, 0x9f, 0x22, 0x01, 0x80, 0x30, 0x00, 0x00, - 0xdd, 0x9f, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00, 0x57, 0x01, 0x00, 0xbc, - 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xb1, 0xb3, 0x01, 0x00, - 0xdd, 0x9f, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xca, - 0x81, 0x88, 0x01, 0x00, 0xdd, 0x9f, 0xa2, 0x40, 0x74, 0x7d, 0x00, 0x00, - 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00, 0x1b, 0x03, 0xa8, 0xb1, - 0x82, 0x30, 0x00, 0x00, 0x1a, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xdd, 0x9f, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0xcb, 0x83, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x22, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x2d, 0x03, 0x91, 0x82, 0x82, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x8a, 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, - 0x80, 0xce, 0x01, 0x00, 0x2b, 0x03, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x2d, 0x03, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, - 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, - 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xcd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x32, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x3d, 0x03, 0x91, 0x81, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, - 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, - 0x3b, 0x03, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3d, 0x03, 0x55, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xb5, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00, 0xb5, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, - 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0xc4, 0x14, 0x2f, 0x40, 0x99, 0xb3, 0x01, 0x00, - 0x57, 0x01, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x30, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x90, 0x00, 0xf8, - 0x80, 0x98, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf2, 0x88, 0xe4, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x23, 0x91, 0x01, 0x00, 0x4d, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x23, 0x91, 0x01, 0x00, 0x50, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x40, 0x20, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x23, 0x91, 0x01, 0x00, 0x53, 0x03, 0x1f, 0x91, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x23, 0x91, 0x01, 0x00, 0x55, 0x03, 0x1f, 0x91, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x08, 0x80, 0x40, 0x20, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x48, 0x84, 0x84, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x8f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x62, 0xb1, 0x01, 0x00, - 0x5a, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x08, 0x00, 0x47, - 0x8e, 0xc8, 0x01, 0x00, 0x58, 0x03, 0x00, 0x5c, 0x8f, 0x80, 0x00, 0x00, - 0xe0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x58, 0x15, 0x2d, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfa, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x81, 0xb0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x45, 0x82, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x82, 0x94, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x41, 0x60, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x8d, 0xc0, 0x01, 0x00, 0x74, 0x03, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00, - 0x65, 0x03, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x63, 0x03, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x40, 0x85, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x86, 0xb0, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x43, 0x86, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0xa6, 0x41, 0x85, 0x50, 0x01, 0x00, 0x70, 0x03, 0x00, 0x41, - 0x83, 0xe0, 0x00, 0x00, 0x6e, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x85, 0xe0, 0x01, 0x00, 0xd0, 0x14, 0x2f, 0x46, - 0x84, 0x94, 0x01, 0x00, 0x20, 0x00, 0x00, 0x42, 0x60, 0x99, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x07, 0x00, 0x00, 0x45, 0x80, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x8b, 0xf0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x85, 0x03, 0xa0, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x83, 0x03, 0x00, 0x41, 0x82, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, - 0x8e, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0x00, 0x39, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x8b, 0x03, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x44, - 0x82, 0xf4, 0x01, 0x00, 0x1a, 0x15, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, - 0x70, 0x15, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x08, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x39, 0x00, 0x40, 0xe1, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x70, 0x15, 0x00, 0x43, 0x62, 0x99, 0x01, 0x00, - 0x95, 0x03, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x97, 0x03, 0x22, 0x5a, - 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x98, 0x03, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0x00, 0x08, 0x00, 0x42, - 0x84, 0xc8, 0x01, 0x00, 0x90, 0x03, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x58, 0x15, 0x2d, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0xd0, 0x14, 0x2d, 0xf0, 0x88, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x8f, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, - 0x90, 0xb0, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x48, 0x90, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, - 0x8a, 0xb0, 0x01, 0x00, 0x80, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x02, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, 0xac, 0x03, 0x22, 0x40, - 0x82, 0x6c, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x58, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x8d, 0xc0, 0x01, 0x00, 0xb5, 0x03, 0x22, 0x5f, 0x8d, 0x6c, 0x00, 0x00, - 0xa7, 0x03, 0xa2, 0x41, 0x93, 0x50, 0x00, 0x00, 0xa5, 0x03, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xff, 0x07, 0x00, 0x47, 0x84, 0x88, 0x01, 0x00, - 0x00, 0x00, 0xa6, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xed, 0x9f, 0x00, 0x47, - 0x80, 0x30, 0x01, 0x00, 0x00, 0x02, 0x00, 0x47, 0x8e, 0xc8, 0x01, 0x00, - 0xb0, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x50, 0xb3, 0x01, 0x00, 0xbb, 0x03, 0x20, 0x18, 0x89, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00, - 0xbe, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa6, - 0x84, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, - 0x00, 0x10, 0x00, 0x40, 0x55, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x50, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x4f, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x4e, 0xd3, 0x01, 0x00, 0x6e, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x82, 0x03, 0x00, 0x42, 0x80, 0x30, 0x01, 0x00, - 0xb0, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc7, 0x03, 0x22, 0xa7, - 0x8f, 0x6c, 0x00, 0x00, 0x5a, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xc4, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xee, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xa0, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xca, - 0xa7, 0x33, 0x01, 0x00, 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x03, 0x22, 0x42, - 0x75, 0x6f, 0x00, 0x00, 0xd8, 0x03, 0x22, 0x41, 0x75, 0x6f, 0x00, 0x00, - 0xda, 0x03, 0x1e, 0xca, 0x81, 0x32, 0x00, 0x00, 0xdc, 0x03, 0x1f, 0xca, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xc9, 0xb1, 0x01, 0x00, - 0xdd, 0x9f, 0x00, 0x42, 0x75, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xcd, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x41, 0x75, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xcf, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x40, - 0x75, 0xb3, 0x00, 0x00, 0x00, 0x81, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00, - 0xdd, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6, - 0xc6, 0xb1, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0x40, 0x75, 0xb3, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x45, 0x01, 0x00, 0x4d, 0x93, 0x30, 0x01, 0x00, - 0x45, 0x01, 0x00, 0x4e, 0x93, 0x30, 0x01, 0x00, 0x45, 0x01, 0x00, 0x4c, - 0x93, 0x30, 0x01, 0x00, 0xec, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xdd, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x54, 0x95, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0xdd, 0x9f, 0x00, 0xca, 0xe5, 0xb1, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xcc, 0x14, 0x2e, 0x40, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, - 0xa0, 0xb3, 0x01, 0x00, 0x15, 0x04, 0x00, 0x43, 0xb2, 0x33, 0x01, 0x00, - 0x00, 0x00, 0x68, 0xda, 0x89, 0xb0, 0x01, 0x00, 0x7c, 0x00, 0x00, 0x40, - 0x8b, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x89, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x89, 0xd0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x44, - 0x88, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x87, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xa5, 0xb3, 0x01, 0x00, 0x15, 0x04, 0x00, 0x43, - 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xa5, 0xc3, 0x01, 0x00, 0x0b, 0x04, 0x22, 0x44, 0x89, 0x50, 0x00, 0x00, - 0x0b, 0x04, 0x22, 0x44, 0x8b, 0x50, 0x00, 0x00, 0xfa, 0x03, 0xa2, 0x50, - 0xa5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb, - 0x85, 0x30, 0x01, 0x00, 0xcc, 0x14, 0x2e, 0xd2, 0x95, 0xc3, 0x01, 0x00, - 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xb0, 0x01, 0x00, - 0x08, 0x04, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x07, 0x04, 0xa2, 0xf2, - 0x80, 0x30, 0x00, 0x00, 0xfa, 0x03, 0x00, 0x40, 0xa5, 0xb3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xa5, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb, 0x85, 0x30, 0x01, 0x00, - 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00, - 0x00, 0x10, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xdb, 0x00, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xff, 0xff, 0x00, 0x94, 0xb4, 0x8b, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd9, - 0x2b, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, - 0xdd, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x94, - 0xb4, 0xb3, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd9, 0x2b, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0x27, 0xb1, 0x01, 0x00, 0x06, 0xc0, 0x00, 0x40, 0x2d, 0x99, 0x01, 0x00, - 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x02, 0xc4, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, - 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x40, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x05, 0x82, 0x00, 0x41, 0x2c, 0x99, 0x01, 0x00, - 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2d, 0x04, 0x80, 0x94, - 0x80, 0x32, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x28, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x40, - 0x2d, 0x99, 0x01, 0x00, 0xde, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x31, 0x04, 0x00, 0x12, - 0x10, 0xc9, 0x00, 0x00, 0x00, 0x48, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0xc0, 0x49, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x4b, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x40, 0x4d, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x4f, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x50, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x80, 0x52, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x40, 0x54, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x56, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x57, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x80, 0x59, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x5b, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x5d, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0xc0, 0x5e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x60, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x40, 0x62, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x64, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x65, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x80, 0x67, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x40, 0x69, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x6b, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x6c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x80, 0x6e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x40, 0x70, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x72, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0xc0, 0x73, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x80, 0x75, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x40, 0x77, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x79, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0xc0, 0x7a, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x80, 0x7c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x40, 0x7e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x59, 0x04, 0x00, 0x12, 0x10, 0xc9, 0x00, 0x00, - 0x00, 0x80, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x82, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x84, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x86, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x88, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x8a, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x8c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x8e, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x90, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x92, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x94, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x96, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x98, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0x9a, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0x9c, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0x9e, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa0, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa2, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xa4, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa6, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xa8, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xaa, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xac, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xae, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xb0, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb2, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb4, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xb6, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xb8, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x00, 0xba, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, - 0x00, 0xbc, 0x80, 0x40, 0x0b, 0x98, 0x01, 0x00, 0x00, 0xbe, 0x80, 0x40, - 0x0b, 0x98, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x80, 0xb1, 0x01, 0x00, - 0x01, 0x00, 0x00, 0xa6, 0x82, 0xb1, 0x01, 0x00, 0x82, 0x04, 0x85, 0x41, - 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00, - 0x87, 0x04, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x90, 0x04, 0x60, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0xb1, 0x01, 0x00, - 0xff, 0xff, 0xf0, 0x4b, 0x82, 0x89, 0x01, 0x00, 0x93, 0x04, 0x60, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x80, 0xb1, 0x01, 0x00, - 0x01, 0x00, 0xf0, 0xa6, 0x82, 0xb1, 0x01, 0x00, 0x96, 0x04, 0x60, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00, - 0x00, 0x00, 0xf0, 0xc2, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x80, 0x4b, 0x92, 0x89, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0x01, 0x00, 0x80, 0xa6, - 0x92, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x94, 0x89, 0x01, 0x00, - 0x00, 0x00, 0x80, 0xca, 0x94, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x88, 0x94, 0x01, 0x00, 0xa6, 0x04, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xad, 0x04, 0x22, 0x20, 0x87, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xa6, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0x80, 0x86, 0xb3, 0x01, 0x00, 0xb0, 0x04, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x62, 0xb1, 0x01, 0x00, 0xb1, 0x04, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xb8, 0x04, 0x22, 0x4b, 0x89, 0x7c, 0x00, 0x00, 0xb6, 0x04, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0xb6, 0x04, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x87, 0xb3, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x99, 0xb0, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xc1, 0x04, 0xa8, 0xb1, 0x52, 0x33, 0x00, 0x00, 0xc6, 0x04, 0x22, 0x4b, - 0x53, 0x7f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xc4, 0x04, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xc1, 0x04, 0xa2, 0x41, - 0x99, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x4f, 0x77, 0xfd, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x4e, 0x98, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x98, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x99, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x98, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x99, 0xe0, 0x01, 0x00, 0xd6, 0x04, 0x00, 0x4c, - 0x88, 0x94, 0x00, 0x00, 0xd6, 0x04, 0x47, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xdd, 0x04, 0x22, 0x20, 0x87, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xd6, 0x04, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0x80, 0x86, 0xb3, 0x01, 0x00, 0xe0, 0x04, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x62, 0xb1, 0x01, 0x00, 0xe1, 0x04, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xe8, 0x04, 0x22, 0x4a, 0x89, 0x7c, 0x00, 0x00, 0xe6, 0x04, 0x22, 0x4f, - 0x77, 0x7d, 0x00, 0x00, 0xf0, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x62, 0xb1, 0x01, 0x00, 0xe6, 0x04, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x87, 0xb3, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x99, 0xb0, 0x01, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xf1, 0x04, 0xa8, 0xb1, 0x52, 0x33, 0x00, 0x00, 0xf6, 0x04, 0x22, 0x4a, - 0x53, 0x7f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xf4, 0x04, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, 0xf1, 0x04, 0xa2, 0x41, - 0x99, 0x50, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x4f, 0x77, 0xfd, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x00, 0x05, 0xa8, 0xb1, 0x80, 0x30, 0x00, 0x00, 0x12, 0x05, 0x1d, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x40, 0x18, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x10, 0x05, 0xa2, 0x40, - 0x86, 0x04, 0x00, 0x00, 0xde, 0x9f, 0x9c, 0x40, 0x80, 0x32, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x40, 0x88, 0x88, 0x01, 0x00, 0x30, 0x05, 0x00, 0x50, - 0x47, 0x31, 0x01, 0x00, 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00, - 0x0c, 0x05, 0x52, 0x40, 0x81, 0x32, 0x00, 0x00, 0x30, 0x05, 0x00, 0x40, - 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x89, 0xb0, 0x01, 0x00, - 0x30, 0x05, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00, 0x30, 0x05, 0x00, 0x05, - 0x47, 0x31, 0x01, 0x00, 0xde, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x1b, 0x00, 0xde, 0x9f, 0x00, 0x41, - 0xe1, 0xc1, 0x1a, 0x00, 0x78, 0x18, 0x00, 0x40, 0x49, 0x99, 0x1b, 0x00, - 0x19, 0x05, 0x22, 0x54, 0x81, 0x7c, 0x1a, 0x00, 0x14, 0x05, 0x42, 0x40, - 0x81, 0x32, 0x1a, 0x00, 0x00, 0x82, 0x00, 0xb3, 0x67, 0xdf, 0x1b, 0x00, - 0x00, 0x00, 0x1a, 0x44, 0x93, 0x93, 0x1b, 0x00, 0x28, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x1b, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, - 0x27, 0x05, 0x0f, 0x40, 0x80, 0x32, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x40, - 0x88, 0x88, 0x01, 0x00, 0x30, 0x05, 0x00, 0x50, 0x47, 0x31, 0x01, 0x00, - 0x36, 0x00, 0x00, 0x44, 0x88, 0xcc, 0x01, 0x00, 0x1f, 0x05, 0x99, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0xd0, 0x01, 0x00, - 0x21, 0x05, 0x9b, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x89, 0xd0, 0x01, 0x00, 0x23, 0x05, 0x1f, 0x44, 0x80, 0x32, 0x00, 0x00, - 0x30, 0x05, 0x00, 0x40, 0x47, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x89, 0xb0, 0x01, 0x00, 0x30, 0x05, 0x00, 0x48, 0x47, 0x31, 0x01, 0x00, - 0x30, 0x05, 0x00, 0x58, 0x47, 0x31, 0x01, 0x00, 0xde, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x86, 0xf4, 0x01, 0x00, - 0x6f, 0x00, 0x00, 0x43, 0x86, 0x88, 0x01, 0x00, 0xde, 0x9f, 0x26, 0x05, - 0x47, 0x31, 0x00, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, - 0xde, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x44, 0xf0, 0x41, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41, - 0xe1, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x07, - 0x91, 0x30, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x97, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x05, 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x44, 0x05, 0xa2, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0x45, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00, 0x10, 0x04, 0x00, 0x42, - 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf5, 0xb1, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xf5, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, - 0xf7, 0xf5, 0x01, 0x00, 0x50, 0x00, 0x00, 0x40, 0x91, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x8f, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x48, - 0xb2, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00, - 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x91, 0xc0, 0x01, 0x00, 0x50, 0x05, 0xa2, 0x41, 0x8f, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x45, 0xd1, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xfd, 0xb1, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0x91, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xda, - 0x8f, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0xfd, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0xda, - 0xfd, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x7a, 0x05, 0x22, 0x45, 0xfd, 0x7f, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0xdb, 0x9f, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x15, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x78, 0x05, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00, - 0x7d, 0x05, 0x22, 0x20, 0xb5, 0x6f, 0x00, 0x00, 0x7a, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x1f, 0x00, - 0x7d, 0x05, 0x22, 0x40, 0x97, 0x6c, 0x1e, 0x00, 0x7a, 0x05, 0x42, 0x40, - 0x81, 0x32, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x67, 0x93, 0x1f, 0x00, - 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x1e, 0x00, 0x54, 0x16, 0x00, 0x40, - 0x47, 0x99, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x1f, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, - 0x46, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, 0xf7, 0xf5, 0x01, 0x00, - 0x48, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x97, 0xb0, 0x01, 0x00, 0x10, 0x04, 0x00, 0x4a, 0xb2, 0x33, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xda, 0xf7, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x00, 0xda, - 0xf7, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x95, 0xc0, 0x01, 0x00, - 0x90, 0x05, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x40, - 0xa5, 0x9b, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40, 0xa1, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xa7, 0xb3, 0x01, 0x00, 0xe1, 0x9f, 0x00, 0xbb, - 0x85, 0x30, 0x01, 0x00, 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb8, 0x05, 0x22, 0x45, 0xfd, 0x7f, 0x00, 0x00, 0xe0, 0x15, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x1a, 0x00, 0x00, 0xa2, 0x80, 0xdc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, - 0x62, 0xdd, 0x01, 0x00, 0xa7, 0x05, 0xa8, 0xbb, 0xe1, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0xaa, 0x05, 0xa2, 0x41, - 0x83, 0x50, 0x00, 0x00, 0xa9, 0x05, 0xa2, 0xf2, 0x82, 0x30, 0x00, 0x00, - 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb0, 0x05, 0xa2, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x40, 0xb3, 0x9b, 0x01, 0x00, - 0xb1, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, - 0xb3, 0x9b, 0x01, 0x00, 0xf0, 0x15, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x05, 0xa2, 0xfa, - 0xb4, 0x6f, 0x00, 0x00, 0x10, 0x04, 0x00, 0x42, 0xb3, 0x43, 0x01, 0x00, - 0xb8, 0x05, 0xa2, 0xfa, 0xb4, 0x6f, 0x00, 0x00, 0x10, 0x04, 0x00, 0x42, - 0xb3, 0x43, 0x01, 0x00, 0xbb, 0x05, 0x22, 0xfa, 0xb4, 0x6f, 0x00, 0x00, - 0xb8, 0x05, 0x42, 0x40, 0x81, 0x32, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0x67, 0x93, 0x21, 0x00, 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x20, 0x00, - 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x21, 0x00, 0xdb, 0x9f, 0x00, 0x40, - 0x49, 0x31, 0x21, 0x00, 0xf6, 0x15, 0x00, 0x40, 0x43, 0x99, 0x21, 0x00, - 0x5c, 0x16, 0x00, 0x40, 0x45, 0x99, 0x21, 0x00, 0x00, 0x00, 0x6e, 0xfa, - 0x8e, 0xb0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xb4, 0xb3, 0x01, 0x00, 0xc9, 0x05, 0xa2, 0x40, 0x8f, 0x6c, 0x00, 0x00, - 0xfc, 0x15, 0x20, 0x20, 0xe1, 0xb1, 0x01, 0x00, 0xce, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x24, 0x00, 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x25, 0x00, - 0xce, 0x05, 0x22, 0x40, 0x97, 0x6c, 0x24, 0x00, 0xcb, 0x05, 0x42, 0x40, - 0x81, 0x32, 0x24, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x67, 0x93, 0x25, 0x00, - 0xdf, 0x9f, 0x00, 0x58, 0x67, 0x93, 0x24, 0x00, 0x38, 0x05, 0x00, 0x40, - 0x81, 0x32, 0x25, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x25, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd3, 0x05, 0x22, 0x50, - 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x91, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xf8, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfa, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x20, 0x04, 0x00, 0xf2, 0xb4, 0x33, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xfc, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x94, 0xb0, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x4a, 0xb4, 0x8b, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x4a, 0xb4, 0xf7, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xe9, 0x05, 0x22, 0x50, 0xb5, 0x6f, 0x00, 0x00, - 0xea, 0x05, 0x00, 0x50, 0xb5, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xb5, 0xb3, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xe0, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x30, 0x31, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x32, 0x33, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x34, 0x35, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x36, 0x37, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x38, 0x39, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x41, 0x42, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x43, 0x44, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x45, 0x46, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x47, 0x48, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x49, 0x4a, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00, - 0xfc, 0x05, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x80, 0x16, 0x2e, 0x06, - 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0xff, 0x05, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00, - 0x02, 0x06, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40, - 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0x08, 0x06, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00, - 0x14, 0x06, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x45, 0x67, 0x00, 0xa6, 0xe0, 0xb2, 0x01, 0x00, 0x01, 0x23, 0x00, 0x70, - 0xe1, 0x9a, 0x01, 0x00, 0xcd, 0xef, 0x00, 0xa6, 0xe2, 0xb2, 0x01, 0x00, - 0x89, 0xab, 0x00, 0x71, 0xe3, 0x9a, 0x01, 0x00, 0xba, 0x98, 0x00, 0xa6, - 0xe4, 0xb2, 0x01, 0x00, 0xfe, 0xdc, 0x00, 0x72, 0xe5, 0x9a, 0x01, 0x00, - 0x32, 0x10, 0x00, 0xa6, 0xe6, 0xb2, 0x01, 0x00, 0x76, 0x54, 0x00, 0x73, - 0xe7, 0x9a, 0x01, 0x00, 0xd2, 0xc3, 0x00, 0xa6, 0xe8, 0xb2, 0x01, 0x00, - 0xf0, 0xe1, 0x00, 0x74, 0xe9, 0x9a, 0x01, 0x00, 0x80, 0x16, 0x00, 0x4a, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf7, 0xb1, 0x01, 0x00, 0x25, 0x06, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x80, 0x16, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0xfc, 0x16, 0x2a, 0x47, - 0xe7, 0xb5, 0x01, 0x00, 0x03, 0x00, 0x00, 0x4a, 0xe8, 0xe5, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, - 0xa3, 0x99, 0x01, 0x00, 0x80, 0x16, 0x3d, 0x46, 0x8d, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x40, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, - 0x2e, 0x06, 0xa2, 0x41, 0x89, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xeb, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xed, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x72, 0xef, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73, - 0xf1, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf3, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x41, - 0x80, 0x88, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, 0xa2, 0xc9, 0x01, 0x00, - 0x4b, 0x06, 0xa0, 0x50, 0x83, 0x6c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x40, - 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00, - 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x86, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c, - 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x40, 0x98, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x99, 0x84, 0x01, 0x00, 0x50, 0x03, 0x00, 0x4c, 0xa2, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x86, 0xa4, 0x01, 0x00, 0x50, 0x03, 0x00, 0x40, - 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40, 0xa4, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x20, 0x88, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x41, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x94, 0x01, 0x00, - 0x05, 0x00, 0x00, 0x75, 0x89, 0xe4, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x75, - 0x85, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x84, 0x94, 0x01, 0x00, - 0x55, 0x06, 0xa3, 0x53, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x76, 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x8b, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00, - 0x64, 0x06, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41, - 0x80, 0xce, 0x01, 0x00, 0x5a, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, - 0x89, 0xa4, 0x01, 0x00, 0x64, 0x06, 0x00, 0x78, 0x89, 0xa4, 0x00, 0x00, - 0x3b, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, 0x57, 0x06, 0xaa, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x89, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x77, 0x89, 0x84, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76, - 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x88, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, - 0x8b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8b, 0x84, 0x01, 0x00, - 0x64, 0x06, 0x00, 0x45, 0x88, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x84, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0x85, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x84, 0xc0, 0x01, 0x00, 0x6b, 0x06, 0xa3, 0x53, - 0x83, 0x6c, 0x00, 0x00, 0x82, 0x5a, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, - 0x99, 0x79, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x27, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, - 0x70, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, 0xd9, 0x6e, 0x00, 0xa6, - 0x84, 0xc0, 0x01, 0x00, 0xa1, 0xeb, 0x00, 0x42, 0x84, 0xc8, 0x01, 0x00, - 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x41, - 0x80, 0xce, 0x01, 0x00, 0x75, 0x06, 0xaa, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x1b, 0x8f, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xdc, 0xbc, 0x00, 0x42, - 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x62, 0xca, 0x00, 0xa6, 0x84, 0xc0, 0x01, 0x00, 0xd6, 0xc1, 0x00, 0x42, - 0x84, 0xc8, 0x01, 0x00, 0x78, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x78, 0xf3, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x77, - 0xf1, 0xb2, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x76, 0x89, 0xe4, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x76, 0xef, 0xf6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xee, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x75, 0xed, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xea, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x83, 0xc0, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x41, 0x80, 0xce, 0x01, 0x00, - 0x37, 0x06, 0x2a, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, - 0xe1, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x76, 0xe3, 0xc2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x77, 0xe5, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, - 0xe7, 0xc2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x79, 0xe9, 0xc2, 0x01, 0x00, - 0x2b, 0x06, 0x81, 0x41, 0x8d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xfd, 0x93, 0x01, 0x00, 0x40, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0xdb, 0x9f, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x15, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xb9, 0x06, 0x22, 0x40, 0x8f, 0x6c, 0x00, 0x00, - 0xda, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb9, 0x06, 0xa2, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x5e, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x7c, 0x16, 0x20, 0xf6, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x31, 0xb3, 0x01, 0x00, 0x9d, 0x06, 0x22, 0x4f, 0x8f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x51, 0xfd, 0x93, 0x01, 0x00, 0x9f, 0x06, 0x22, 0x40, - 0x8f, 0x7c, 0x00, 0x00, 0xa3, 0x06, 0x00, 0x54, 0xfd, 0x93, 0x00, 0x00, - 0xa1, 0x06, 0x22, 0x42, 0x8f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, - 0xfd, 0x93, 0x01, 0x00, 0xa3, 0x06, 0x22, 0x41, 0x8f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x53, 0xfd, 0x93, 0x01, 0x00, 0xb7, 0x06, 0x22, 0x51, - 0xfd, 0x7f, 0x00, 0x00, 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0c, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xb2, 0x06, 0xa2, 0x40, 0xb5, 0x6f, 0x00, 0x00, - 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x48, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, 0x97, 0xc0, 0x01, 0x00, - 0x04, 0x00, 0x00, 0x4b, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, 0xb5, 0xb3, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xb6, 0x06, 0x22, 0x40, 0xb5, 0x6f, 0x00, 0x00, 0xba, 0x06, 0x00, 0x54, - 0xfd, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00, - 0x1c, 0x00, 0x00, 0xfe, 0x7f, 0xd9, 0x01, 0x00, 0xba, 0x06, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xfd, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xe7, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc4, 0x06, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xe9, 0x9f, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x3c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x34, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x32, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x0a, 0xc8, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, - 0x0c, 0xc8, 0x01, 0x00, 0xea, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x0a, 0x07, 0x22, 0x01, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0xd9, 0x06, 0xa3, 0x07, 0x02, 0x6c, 0x00, 0x00, - 0xda, 0x06, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x07, - 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, 0xec, 0x06, 0x22, 0x40, - 0x03, 0x6c, 0x00, 0x00, 0xe6, 0x06, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x23, 0x07, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe3, 0x06, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0xe8, 0x06, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, - 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x23, 0x07, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0xee, 0x06, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, - 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x22, 0x00, 0x00, 0x19, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, - 0x0f, 0x00, 0x00, 0xf2, 0x3a, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x3b, 0xe0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x14, 0x02, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00, 0xfa, 0x06, 0x23, 0x1a, - 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0xc0, 0x01, 0x00, - 0x23, 0x07, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x1d, - 0x48, 0xc1, 0x01, 0x00, 0xf0, 0x00, 0x00, 0xf2, 0x30, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x31, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x02, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x02, 0xc0, 0x01, 0x00, 0x02, 0x07, 0x22, 0x1a, - 0x02, 0x50, 0x00, 0x00, 0x23, 0x07, 0x00, 0x01, 0x34, 0xc0, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x19, 0x48, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x2d, 0x14, - 0x48, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x14, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1d, 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x14, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x24, 0xb0, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x17, 0x10, 0xc8, 0x01, 0x00, 0x23, 0x07, 0x00, 0x1a, - 0x10, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0x0f, 0x07, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00, - 0x10, 0x07, 0x60, 0x07, 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x60, 0x12, - 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x0d, 0x16, 0x94, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, 0x17, 0x07, 0xa8, 0x5c, - 0x1f, 0x10, 0x00, 0x00, 0x40, 0x07, 0x22, 0x0d, 0x14, 0x50, 0x00, 0x00, - 0x40, 0x07, 0x22, 0x0d, 0x24, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x10, 0xc0, 0x01, 0x00, 0x1e, 0x07, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, - 0x23, 0x07, 0x00, 0x41, 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x1f, 0x07, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x3f, 0x07, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00, 0x2e, 0x07, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x2c, 0x07, 0x22, 0xf2, - 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x29, 0x07, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x04, 0xb0, 0x01, 0x00, 0x33, 0x07, 0x1f, 0xf0, 0x0e, 0x30, 0x00, 0x00, - 0xd3, 0x06, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x5f, - 0x0f, 0x80, 0x01, 0x00, 0xd3, 0x06, 0x23, 0x07, 0x14, 0x6c, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x24, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x3c, 0x07, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0xd3, 0x06, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, 0xd3, 0x06, 0x00, 0x0d, - 0x18, 0xc0, 0x00, 0x00, 0x5f, 0x07, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x19, 0x0a, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, - 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, - 0x02, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0x0d, 0x00, 0x2d, 0x1d, 0x48, 0xc1, 0x01, 0x00, - 0x09, 0x00, 0x00, 0xf3, 0x38, 0x88, 0x01, 0x00, 0x0d, 0x00, 0x20, 0x50, - 0xe7, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0x40, 0x3f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf4, 0x32, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x14, 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x1d, - 0x94, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0xb0, 0x01, 0x00, - 0x52, 0x07, 0xa0, 0xfc, 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x91, 0xc0, 0x01, 0x00, 0x50, 0x07, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0x96, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x48, 0xc1, 0x01, 0x00, 0x02, 0x00, 0x00, 0x18, 0x94, 0xf4, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x18, 0x90, 0xb0, 0x01, 0x00, 0x5c, 0x07, 0xa0, 0xfc, - 0x90, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00, - 0x5a, 0x07, 0xa2, 0x41, 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x80, 0xb0, 0x2d, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xb0, 0x2d, 0x00, - 0x22, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x48, 0xc1, 0x2d, 0x00, 0x64, 0x07, 0x43, 0x30, 0x3d, 0x07, 0x2c, 0x00, - 0x00, 0x00, 0x00, 0x9e, 0x85, 0xb0, 0x2d, 0x00, 0x00, 0x00, 0x1b, 0x41, - 0x3d, 0xc3, 0x2d, 0x00, 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x2d, 0x00, - 0x00, 0x00, 0x00, 0x1e, 0x82, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x2e, 0x1d, - 0x82, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x18, 0x82, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x80, 0xc0, 0x01, 0x00, 0x6e, 0x07, 0xa0, 0x41, - 0x80, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x40, 0x92, 0xf4, 0x01, 0x00, 0x0a, 0x00, 0x2e, 0x30, - 0x81, 0x84, 0x01, 0x00, 0x72, 0x07, 0x90, 0x40, 0x92, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, - 0x93, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x48, 0xc1, 0x01, 0x00, - 0x04, 0x00, 0x20, 0x19, 0xe8, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, - 0x16, 0xc0, 0x01, 0x00, 0x78, 0x07, 0xa0, 0x19, 0x16, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x0d, 0x00, 0x2f, 0x1e, - 0x32, 0xc0, 0x01, 0x00, 0x7d, 0x07, 0xa2, 0x40, 0x15, 0x6c, 0x00, 0x00, - 0x7c, 0x07, 0xa0, 0x1c, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3, 0x38, 0x94, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x05, 0x48, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x1e, - 0x98, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x1a, 0x98, 0xc0, 0x01, 0x00, - 0x0c, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x8b, 0x07, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x89, 0x07, 0x22, 0xf2, - 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x86, 0x07, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0xe1, 0x91, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x1a, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17, - 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, - 0x91, 0x07, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x9b, 0x07, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x2d, 0x10, 0x48, 0xc1, 0x01, 0x00, 0x9b, 0x07, 0x22, 0xf2, - 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x98, 0x07, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xeb, 0x9f, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x20, 0x00, 0x2f, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, 0xa1, 0x07, 0x90, 0xf2, - 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14, - 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x2a, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x2a, 0x94, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xac, 0x07, 0x22, 0xf2, 0x64, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xa9, 0x07, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe3, 0x9f, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00, - 0xc9, 0x07, 0x22, 0x40, 0x15, 0x6c, 0x00, 0x00, 0xb4, 0x07, 0xa2, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x1f, 0x90, 0x01, 0x00, - 0xb3, 0x07, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88, - 0x1c, 0xcc, 0x01, 0x00, 0xe4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x3f, 0xc3, 0x01, 0x00, 0xe6, 0x9f, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xb7, 0x07, 0xa2, 0x41, 0x87, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1e, 0x3e, 0xc0, 0x01, 0x00, 0xc9, 0x07, 0x22, 0x40, - 0x15, 0x6c, 0x00, 0x00, 0xba, 0x07, 0x20, 0x1e, 0x14, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x3c, 0xb0, 0x01, 0x00, 0xe5, 0x9f, 0x00, 0x1e, - 0x24, 0x30, 0x01, 0x00, 0xbf, 0x07, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x52, 0x11, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1a, - 0x10, 0xc0, 0x01, 0x00, 0x23, 0x07, 0x00, 0x40, 0x17, 0xb0, 0x00, 0x00, - 0xe4, 0x9f, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xe5, 0x9f, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xbc, 0x07, 0xa2, 0x08, 0x2e, 0x30, 0x00, 0x00, - 0x80, 0x80, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, - 0x87, 0x98, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00, 0xe8, 0x9f, 0x00, 0x1f, - 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, - 0xe2, 0x9f, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x44, 0x99, 0x01, 0x00, 0x04, 0x00, 0x22, 0x04, 0xe0, 0x31, 0x00, 0x00, - 0xe6, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xce, 0x07, 0xa2, 0x41, - 0x87, 0x7c, 0x00, 0x00, 0xcf, 0x07, 0x00, 0x1e, 0x3e, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1f, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x05, 0xb0, 0x01, 0x00, 0xe8, 0x9f, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, - 0xe2, 0x9f, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xf7, 0x07, 0x00, 0xbc, 0x80, 0xb2, 0x00, 0x00, - 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x03, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x03, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, - }, - { - 0x31, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x34, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x35, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0x80, 0x81, 0x80, - 0x80, 0x32, 0x00, 0x00, 0x0e, 0x87, 0xa2, 0x40, 0x91, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x90, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2, - 0x80, 0xb0, 0x01, 0x00, 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00, - 0x90, 0x95, 0x2a, 0xc8, 0xe5, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd2, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xd3, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xee, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x44, 0xb1, 0x01, 0x00, 0x18, 0x80, 0x11, 0x81, - 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x51, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x1a, 0x80, 0x11, 0x82, 0x98, 0x30, 0x00, 0x00, 0x00, 0x00, 0x52, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x0e, 0x87, 0x00, 0x48, 0xfd, 0x93, 0x00, 0x00, - 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x23, 0x80, 0xa2, 0x42, - 0xfd, 0x7f, 0x00, 0x00, 0x20, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00, - 0x22, 0x80, 0x11, 0x81, 0x82, 0x30, 0x00, 0x00, 0x22, 0x80, 0x51, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x22, 0x80, 0x11, 0x82, 0x82, 0x30, 0x00, 0x00, - 0x22, 0x80, 0x52, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x80, 0x00, 0x48, - 0xfd, 0x93, 0x00, 0x00, 0x27, 0x80, 0x00, 0x80, 0x80, 0x32, 0x00, 0x00, - 0x26, 0x80, 0xa2, 0x53, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x51, 0x53, - 0x07, 0x90, 0x01, 0x00, 0x2a, 0x80, 0x00, 0x52, 0x07, 0x90, 0x00, 0x00, - 0x29, 0x80, 0xa2, 0x52, 0x07, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x52, 0x52, - 0x07, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0xf3, 0x93, 0x01, 0x00, 0x5c, 0x95, 0x2e, 0xa2, 0x52, 0xb3, 0x01, 0x00, - 0xff, 0x00, 0x00, 0x80, 0xf4, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x45, 0xb1, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x4c, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xaf, 0x82, 0x05, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xaf, 0x82, 0x05, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x4c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0xde, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfd, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xfd, 0x83, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, - 0x9b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00, - 0x48, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x58, 0x95, 0x20, 0x44, - 0xe0, 0xb1, 0x01, 0x00, 0x04, 0x94, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x24, 0xb1, 0x01, 0x00, 0x00, 0x0c, 0x00, 0xee, - 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x97, 0xf0, 0x01, 0x00, - 0x44, 0x80, 0xa2, 0x43, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xfd, 0x93, 0x01, 0x00, 0x00, 0xc0, 0x00, 0xa6, 0x36, 0xb1, 0x01, 0x00, - 0xd0, 0x14, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x00, 0x38, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x00, 0x06, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x05, 0x10, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, - 0x02, 0x09, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, - 0xf5, 0x99, 0x01, 0x00, 0x60, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x88, 0x03, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xa0, 0x03, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xa2, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x9a, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x60, 0x95, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x70, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x49, 0xdd, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x91, 0xb3, 0x01, 0x00, 0xe0, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb3, 0x01, 0x00, 0x5c, 0x95, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x27, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x90, 0x06, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x2f, 0x81, 0x01, 0x00, 0x8d, 0x81, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xe5, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x45, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x55, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xdd, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xaf, 0x82, 0x00, 0x41, 0xe1, 0xc1, 0x00, 0x00, 0x78, 0x18, 0x00, 0x40, - 0x49, 0x99, 0x01, 0x00, 0x19, 0x05, 0x22, 0x54, 0x81, 0x7c, 0x00, 0x00, - 0x6c, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0xb4, - 0x69, 0xdf, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x28, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x18, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x40, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x7d, 0x80, 0x22, 0x40, - 0x97, 0x6c, 0x00, 0x00, 0x7a, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x69, 0x93, 0x01, 0x00, 0x38, 0x81, 0x00, 0x58, - 0x69, 0x93, 0x00, 0x00, 0x54, 0x16, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xf4, 0xb1, 0x01, 0x00, 0x80, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x80, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0x69, 0x93, 0x01, 0x00, 0x38, 0x81, 0x00, 0x58, - 0x69, 0x93, 0x00, 0x00, 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x40, 0x05, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0xf6, 0x15, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x5c, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x6e, 0xfa, 0x8e, 0xb0, 0x01, 0x00, 0xc1, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x96, 0x80, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x96, 0x80, 0x22, 0x40, 0x97, 0x6c, 0x00, 0x00, - 0x93, 0x80, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x69, 0x93, 0x01, 0x00, 0x38, 0x81, 0x00, 0x58, 0x69, 0x93, 0x00, 0x00, - 0x38, 0x05, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, - 0xb2, 0xcb, 0x01, 0x00, 0xd0, 0x05, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x83, 0x02, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xb8, 0x02, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd4, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd5, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd7, 0x9f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x72, 0x01, 0x00, 0x41, - 0x81, 0xc0, 0x00, 0x00, 0x55, 0x01, 0x51, 0x48, 0xfd, 0x93, 0x00, 0x00, - 0x55, 0x01, 0x52, 0x48, 0xfd, 0x93, 0x00, 0x00, 0x55, 0x01, 0x55, 0x49, - 0xfd, 0x83, 0x00, 0x00, 0x55, 0x01, 0x56, 0x4a, 0xfd, 0x83, 0x00, 0x00, - 0x50, 0x01, 0x91, 0x81, 0x80, 0x30, 0x00, 0x00, 0x55, 0x01, 0x45, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x50, 0x01, 0x91, 0x82, 0x80, 0x30, 0x00, 0x00, - 0x55, 0x01, 0x46, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x89, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x00, 0x05, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x48, 0xc1, 0x01, 0x00, - 0xb4, 0x80, 0x43, 0x30, 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x41, 0x3d, 0xc3, 0x01, 0x00, - 0x04, 0x00, 0x20, 0x42, 0xec, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x46, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd2, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0xd0, 0xe1, 0xb1, 0x00, 0x00, 0xbf, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x98, 0xb0, 0x01, 0x00, - 0x04, 0x80, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00, 0xb1, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0xc7, 0x80, 0xa2, 0x42, 0x97, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0xa1, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x04, 0x80, 0x94, 0x00, 0x00, - 0x80, 0x15, 0x3f, 0x42, 0x97, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x03, 0x02, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x07, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xcb, - 0x99, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xf3, 0x83, 0x01, 0x00, - 0xd1, 0x80, 0xa2, 0x42, 0x97, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, - 0xf3, 0x93, 0x01, 0x00, 0xae, 0x03, 0x00, 0xcb, 0xa3, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x44, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x04, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1, - 0xe0, 0xb1, 0x01, 0x00, 0x05, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x20, 0x62, 0xdd, 0x01, 0x00, 0xd8, 0x80, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xf9, 0x02, 0x00, 0x20, 0x42, 0x31, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x41, 0x05, 0x6c, 0x01, 0x00, 0x00, 0x00, 0x80, 0xcb, - 0xdb, 0x91, 0x01, 0x00, 0x00, 0x00, 0x19, 0x41, 0x8b, 0xb3, 0x01, 0x00, - 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xde, 0x80, 0xa8, 0xb1, - 0x8c, 0x33, 0x00, 0x00, 0x60, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xe0, 0x80, 0xa8, 0xb1, 0x94, 0x33, 0x00, 0x00, 0xe6, 0x80, 0x14, 0xc6, - 0x81, 0x32, 0x00, 0x00, 0x18, 0x00, 0x00, 0xc6, 0x83, 0xf4, 0x01, 0x00, - 0xf4, 0x82, 0x22, 0x4f, 0x83, 0x04, 0x00, 0x00, 0xc2, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc6, 0x81, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xc6, 0x97, 0xa3, 0x01, 0x00, 0xc2, 0x80, 0x1f, 0x5c, - 0x97, 0x53, 0x00, 0x00, 0x58, 0x82, 0x1e, 0xc6, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x2f, 0x43, 0x81, 0xf0, 0x01, 0x00, 0xec, 0x80, 0x00, 0x40, - 0x10, 0xc9, 0x00, 0x00, 0x39, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x6a, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x24, 0x82, 0x00, 0xca, - 0x63, 0xb3, 0x00, 0x00, 0x61, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x48, 0x81, 0x00, 0x4d, 0x83, 0xb0, 0x00, 0x00, 0x52, 0x81, 0x00, 0x4e, - 0x61, 0xb1, 0x00, 0x00, 0x41, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00, - 0x48, 0x81, 0x00, 0x4c, 0x83, 0xb0, 0x00, 0x00, 0x24, 0x81, 0x00, 0x40, - 0x85, 0xb0, 0x00, 0x00, 0xe3, 0x81, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, - 0x71, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0xdf, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x41, 0x81, 0x00, 0x40, 0x85, 0xb0, 0x00, 0x00, - 0xf0, 0x03, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xca, - 0x9b, 0xb3, 0x00, 0x00, 0x7b, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, - 0x7f, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x86, 0x81, 0x00, 0x40, - 0xc1, 0xb1, 0x00, 0x00, 0x87, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, - 0x88, 0x81, 0x00, 0x40, 0xc1, 0xb1, 0x00, 0x00, 0x89, 0x81, 0x00, 0x40, - 0xc1, 0xb1, 0x00, 0x00, 0x8a, 0x81, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, - 0x8a, 0x81, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00, 0x18, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x97, 0x82, 0x00, 0xbb, 0xab, 0xb3, 0x00, 0x00, - 0x25, 0x82, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, 0xc8, 0x03, 0x00, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x26, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xf4, 0x82, 0x00, 0xca, 0x77, 0xb3, 0x00, 0x00, 0x49, 0x81, 0x00, 0x4d, - 0x83, 0xb0, 0x00, 0x00, 0x50, 0x81, 0x00, 0x4e, 0x61, 0xb1, 0x00, 0x00, - 0x41, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00, 0x49, 0x81, 0x00, 0x4c, - 0x83, 0xb0, 0x00, 0x00, 0x41, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00, - 0x24, 0x81, 0x00, 0xbb, 0x85, 0xb0, 0x00, 0x00, 0x16, 0x81, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xca, 0x4d, 0xb3, 0x00, 0x00, - 0x70, 0x05, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, 0xa0, 0x05, 0x00, 0x40, - 0x49, 0xb1, 0x00, 0x00, 0x1c, 0x81, 0x22, 0x42, 0x8f, 0x6f, 0x00, 0x00, - 0x1e, 0x81, 0x22, 0x41, 0x8f, 0x6f, 0x00, 0x00, 0x20, 0x81, 0x1e, 0xca, - 0x81, 0x32, 0x00, 0x00, 0x22, 0x81, 0x1f, 0xca, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xc9, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x00, 0x42, - 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0xcd, 0xb1, 0x01, 0x00, - 0xf4, 0x82, 0x00, 0x41, 0x8f, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xcf, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x00, 0x40, 0x8f, 0xb3, 0x00, 0x00, - 0x00, 0x81, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6, 0xc6, 0xb1, 0x01, 0x00, - 0xf4, 0x82, 0x00, 0x40, 0x8f, 0xb3, 0x00, 0x00, 0x78, 0x18, 0x00, 0x40, - 0x49, 0x99, 0x01, 0x00, 0x10, 0x00, 0x2f, 0x9c, 0x89, 0xb0, 0x01, 0x00, - 0x3b, 0x81, 0x00, 0x40, 0x39, 0x33, 0x01, 0x00, 0x18, 0x00, 0x2f, 0x9b, - 0x89, 0xb0, 0x01, 0x00, 0x3b, 0x81, 0x00, 0x40, 0x37, 0x33, 0x01, 0x00, - 0x00, 0x00, 0x2f, 0x9a, 0x89, 0xb0, 0x01, 0x00, 0x3b, 0x81, 0x00, 0x40, - 0x35, 0x33, 0x01, 0x00, 0x08, 0x00, 0x2f, 0x99, 0x89, 0xb0, 0x01, 0x00, - 0x3b, 0x81, 0x00, 0x40, 0x33, 0x33, 0x01, 0x00, 0x00, 0x80, 0x00, 0xae, - 0x47, 0xc9, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x00, 0x40, 0xe1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xae, - 0x63, 0xdd, 0x01, 0x00, 0x36, 0x81, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x33, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x36, 0x81, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x69, 0x93, 0x01, 0x00, - 0xf4, 0x82, 0x1a, 0x44, 0x93, 0x93, 0x00, 0x00, 0x39, 0x81, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x38, 0x81, 0x00, 0x58, 0x69, 0x93, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xf0, 0xd1, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x40, 0x81, 0xa2, 0x40, 0xe1, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x45, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x41, 0xe1, 0xd1, 0x01, 0x00, - 0x41, 0x81, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x62, 0xb1, 0x01, 0x00, 0x45, 0x81, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x42, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, - 0x63, 0xb1, 0x01, 0x00, 0x45, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xf4, 0x82, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x4a, 0x81, 0x00, 0x40, - 0x81, 0xb0, 0x00, 0x00, 0x4a, 0x81, 0x00, 0xbb, 0x81, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x60, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0x4b, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x4d, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x50, 0x95, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x53, 0x81, 0x00, 0xbb, - 0x87, 0xb0, 0x00, 0x00, 0x50, 0x95, 0x2f, 0x40, 0x87, 0xb0, 0x01, 0x00, - 0x55, 0x81, 0x22, 0x40, 0x95, 0x7f, 0x00, 0x00, 0xf4, 0x82, 0x60, 0x40, - 0x95, 0x83, 0x00, 0x00, 0x02, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, - 0x56, 0x81, 0x36, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x62, 0xb1, 0x01, 0x00, 0x57, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x62, 0xb1, 0x01, 0x00, 0x59, 0x81, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x63, 0xb1, 0x01, 0x00, - 0x5b, 0x81, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x16, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xf4, 0x82, 0x22, 0x41, 0x43, 0x51, 0x00, 0x00, - 0x00, 0x08, 0x00, 0xca, 0x95, 0xcb, 0x01, 0x00, 0x56, 0x81, 0x00, 0x41, - 0x85, 0xc0, 0x00, 0x00, 0x63, 0x81, 0xa2, 0x42, 0x67, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x67, 0xb3, 0x01, 0x00, 0x63, 0x81, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x65, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x93, 0x83, 0x01, 0x00, 0x00, 0x00, 0x1a, 0xca, - 0x69, 0x97, 0x01, 0x00, 0xf4, 0x82, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x68, 0x81, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf4, 0x82, 0x1a, 0x44, - 0x93, 0x93, 0x00, 0x00, 0xf4, 0x82, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00, - 0xf4, 0x82, 0x80, 0xca, 0x67, 0x33, 0x00, 0x00, 0xf4, 0x82, 0x22, 0x40, - 0x65, 0x6f, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x6f, 0xdb, 0x91, 0x00, 0x00, - 0x85, 0x00, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x35, 0x80, 0x22, 0x40, - 0x80, 0x32, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x58, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x95, 0x93, 0x01, 0x00, 0x77, 0x81, 0xa2, 0x44, 0x21, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5e, - 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x95, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0xc3, 0xb1, 0x01, 0x00, 0x7a, 0x81, 0x22, 0x5b, - 0x95, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xfd, 0x93, 0x01, 0x00, - 0xf4, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1b, 0xfd, 0x00, 0xca, - 0x95, 0x9b, 0x01, 0x00, 0x0d, 0x01, 0x00, 0xca, 0xc5, 0x31, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x95, 0x83, 0x01, 0x00, 0xf4, 0x82, 0x00, 0xca, - 0xc5, 0xb1, 0x00, 0x00, 0xdf, 0x6f, 0x00, 0xca, 0x95, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x95, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0xca, - 0xc7, 0xb1, 0x01, 0x00, 0xf4, 0x82, 0x22, 0x5f, 0x95, 0x7f, 0x00, 0x00, - 0x0d, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x95, 0x83, 0x01, 0x00, 0xf4, 0x82, 0x00, 0xca, 0xc7, 0xb1, 0x00, 0x00, - 0xf4, 0x82, 0x00, 0xca, 0xc9, 0xb1, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xca, - 0xcb, 0xb1, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xca, 0xcd, 0xb1, 0x00, 0x00, - 0xf4, 0x82, 0x00, 0xca, 0xcf, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x42, - 0x81, 0xe0, 0x01, 0x00, 0x98, 0x14, 0x00, 0x40, 0x48, 0xc9, 0x01, 0x00, - 0xf4, 0x82, 0x00, 0xca, 0xe1, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x09, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x8f, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x80, 0x00, 0x41, - 0x08, 0x99, 0x01, 0x00, 0x91, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, - 0x20, 0x80, 0x00, 0xa6, 0x08, 0xb1, 0x01, 0x00, 0x93, 0x81, 0x9f, 0x85, - 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x83, 0x84, 0x01, 0x00, - 0xc8, 0x81, 0x22, 0x30, 0x83, 0x6c, 0x00, 0x00, 0x92, 0x81, 0xa2, 0x4f, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x21, 0xb3, 0x01, 0x00, - 0x02, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x10, 0x00, 0x00, 0x41, 0x84, 0xe4, 0x01, 0x00, - 0x03, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x41, 0x86, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x84, 0x94, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0x10, 0xc4, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00, - 0xa8, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x21, 0xb3, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x1c, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0xa5, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, - 0xba, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x41, 0x01, 0x00, 0xa6, - 0x86, 0xb0, 0x01, 0x00, 0x50, 0x0c, 0x00, 0x43, 0x86, 0x98, 0x01, 0x00, - 0xad, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x21, 0xb3, 0x01, 0x00, 0xba, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x41, 0x01, 0x00, 0xa6, 0x86, 0xb0, 0x01, 0x00, 0x60, 0x0c, 0x00, 0x43, - 0x86, 0x98, 0x01, 0x00, 0xba, 0x81, 0xa2, 0x43, 0x84, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x21, 0xb3, 0x01, 0x00, 0x18, 0x80, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x41, 0x82, 0x88, 0x01, 0x00, 0x00, 0x77, 0x00, 0x41, - 0x82, 0x8c, 0x01, 0x00, 0x01, 0x02, 0x00, 0x41, 0x82, 0x98, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x18, 0x00, 0x00, 0x41, - 0x82, 0xdc, 0x01, 0x00, 0xb8, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0xbb, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, - 0x40, 0x13, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0xc3, 0x81, 0x22, 0x43, - 0x21, 0x6f, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0xc0, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, - 0xde, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x19, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, - 0xc5, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x41, - 0x08, 0x99, 0x01, 0x00, 0xde, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x21, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x83, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5e, 0x83, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, - 0x83, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xc2, 0xb1, 0x01, 0x00, - 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x83, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xc2, 0xb1, 0x01, 0x00, - 0x0c, 0x01, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x41, 0x08, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x11, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, - 0xd7, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x41, - 0x08, 0x99, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0xda, 0x81, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x40, 0x13, 0x00, 0x41, - 0x08, 0x99, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x41, 0x2e, 0x99, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xca, 0x81, 0x94, 0x01, 0x00, 0xe1, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x40, 0x08, 0xb1, 0x00, 0x00, - 0xc8, 0x14, 0x2e, 0xbb, 0x85, 0xb0, 0x01, 0x00, 0xe4, 0x81, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00, - 0xf3, 0x81, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, 0x02, 0x82, 0x22, 0x44, - 0x21, 0x6f, 0x00, 0x00, 0x11, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, - 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x0a, 0x82, 0x22, 0x4a, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, - 0xee, 0x81, 0x22, 0x4d, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x87, 0x90, 0x01, 0x00, 0xf0, 0x81, 0x22, 0x4f, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0xf2, 0x81, 0x22, 0x4e, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0x90, 0x01, 0x00, - 0x0a, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x80, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0a, 0x82, 0x22, 0x42, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, 0x1c, 0x80, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xfd, 0x81, 0x22, 0x45, 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x87, 0x90, 0x01, 0x00, 0xff, 0x81, 0x22, 0x44, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x87, 0x90, 0x01, 0x00, 0x01, 0x82, 0x22, 0x43, - 0x83, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x87, 0x90, 0x01, 0x00, - 0x0a, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x01, 0x80, 0x00, 0xa6, - 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x01, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0a, 0x82, 0x22, 0x42, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x87, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x87, 0x90, 0x01, 0x00, - 0x00, 0x80, 0x00, 0xa6, 0x82, 0xb0, 0x01, 0x00, 0x13, 0x82, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0e, 0x82, 0x22, 0x4b, 0x83, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0xe0, 0xb1, 0x01, 0x00, 0xff, 0x7f, 0x00, 0xa2, 0xa0, 0x8b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xa5, 0xb3, 0x01, 0x00, 0xb8, 0x80, 0x00, 0xca, - 0xa7, 0x33, 0x01, 0x00, 0x36, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x41, 0x82, 0xdc, 0x01, 0x00, 0x14, 0x82, 0xa2, 0x5e, - 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0xb1, 0x01, 0x00, - 0x16, 0x82, 0x9f, 0x85, 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x1b, 0x82, 0x14, 0xf7, 0x81, 0x30, 0x00, 0x00, - 0x1b, 0x82, 0xa2, 0x49, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xfd, 0x93, 0x01, 0x00, 0x1e, 0x82, 0x15, 0xf8, 0x81, 0x14, 0x00, 0x00, - 0x1e, 0x82, 0xa2, 0x4a, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xfd, 0x93, 0x01, 0x00, 0x20, 0x82, 0xa2, 0xc8, 0x81, 0x32, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0x00, 0x10, 0x00, 0x40, - 0x80, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xef, 0xb3, 0x01, 0x00, - 0x22, 0x82, 0x42, 0x40, 0xf1, 0x33, 0x00, 0x00, 0x38, 0x81, 0x00, 0x40, - 0x68, 0x97, 0x00, 0x00, 0xf4, 0x82, 0x00, 0xbb, 0x6b, 0xb3, 0x00, 0x00, - 0xf4, 0x82, 0x00, 0xbb, 0xb1, 0xb3, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x18, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x42, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x43, 0xff, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x18, 0xb1, 0x01, 0x00, 0x2b, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x00, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x19, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x43, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x81, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf6, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x43, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x35, 0x82, 0xa2, 0x54, - 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, 0x3c, 0x82, 0xa2, 0x06, - 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x16, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x80, 0x16, 0x2e, 0x06, - 0x83, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0x42, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x22, 0x00, 0x00, 0x40, - 0x83, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xf6, 0xb1, 0x01, 0x00, - 0x45, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x62, 0x00, 0x00, 0x40, - 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x16, 0x2d, 0x06, 0x83, 0xb0, 0x01, 0x00, 0x80, 0x16, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x5c, 0x00, 0x00, 0xfb, 0xf6, 0xa9, 0x01, 0x00, - 0x4b, 0x82, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71, 0xf9, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x72, 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x74, 0xf9, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x00, 0x40, 0x95, 0x98, 0x01, 0x00, 0xdc, 0x9f, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0xb0, 0x01, 0x00, - 0x57, 0x82, 0x22, 0x70, 0xb5, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x42, - 0x99, 0xb3, 0x01, 0x00, 0x62, 0x82, 0x22, 0x44, 0x81, 0x6c, 0x00, 0x00, - 0x6a, 0x82, 0x22, 0x48, 0x81, 0x6c, 0x00, 0x00, 0x64, 0x82, 0x22, 0x4c, - 0x81, 0x6c, 0x00, 0x00, 0x6e, 0x82, 0x22, 0x50, 0x81, 0x6c, 0x00, 0x00, - 0x6f, 0x82, 0x22, 0x54, 0x81, 0x6c, 0x00, 0x00, 0x71, 0x82, 0x22, 0x58, - 0x81, 0x6c, 0x00, 0x00, 0x76, 0x82, 0x22, 0x5c, 0x81, 0x6c, 0x00, 0x00, - 0x50, 0x01, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, - 0x09, 0xb0, 0x01, 0x00, 0xf4, 0x82, 0x00, 0xca, 0x01, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xf3, 0x83, 0x01, 0x00, 0x68, 0x82, 0xa2, 0x42, 0x05, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x05, 0xb0, 0x01, 0x00, 0xf4, 0x82, 0x22, 0xca, - 0x07, 0x14, 0x00, 0x00, 0xf4, 0x82, 0x00, 0x46, 0xf3, 0x93, 0x00, 0x00, - 0xf4, 0x82, 0x20, 0x43, 0x95, 0x6f, 0x00, 0x00, 0xf4, 0x82, 0x80, 0xca, - 0x05, 0x30, 0x00, 0x00, 0xf4, 0x82, 0x22, 0x01, 0x80, 0x30, 0x00, 0x00, - 0xf4, 0x82, 0x00, 0xcb, 0xdb, 0x91, 0x00, 0x00, 0x57, 0x01, 0x00, 0xbc, - 0xab, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xb1, 0xb3, 0x01, 0x00, - 0xf4, 0x82, 0x00, 0xca, 0xcf, 0xb3, 0x00, 0x00, 0xff, 0x00, 0x00, 0xca, - 0x81, 0x88, 0x01, 0x00, 0xf4, 0x82, 0xa2, 0x40, 0x74, 0x7d, 0x00, 0x00, - 0x60, 0x00, 0x20, 0x40, 0x60, 0x99, 0x01, 0x00, 0x73, 0x82, 0xa8, 0xb1, - 0x82, 0x30, 0x00, 0x00, 0x72, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xf4, 0x82, 0x00, 0xca, 0x79, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0xcb, 0x83, 0x01, 0x00, - 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x79, 0x82, 0xa2, 0x41, - 0x81, 0x50, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x45, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x84, 0x82, 0x91, 0x82, - 0x82, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x80, 0xb0, 0x01, 0x00, - 0xae, 0x9f, 0x00, 0x40, 0x80, 0xce, 0x01, 0x00, 0x82, 0x82, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x84, 0x82, 0x56, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, - 0x07, 0x90, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41, - 0x8b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x81, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xcd, 0x83, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x89, 0x82, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x46, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x46, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x94, 0x82, 0x91, 0x81, 0x82, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x89, 0x80, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, - 0x80, 0xce, 0x01, 0x00, 0x92, 0x82, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x94, 0x82, 0x55, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb6, 0x03, 0x00, 0x40, - 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x07, 0x90, 0x01, 0x00, - 0xb6, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x53, - 0x07, 0x90, 0x01, 0x00, 0xd8, 0x9f, 0x00, 0x41, 0x8b, 0xb3, 0x00, 0x00, - 0xb1, 0x03, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, 0xc4, 0x14, 0x2f, 0x40, - 0x99, 0xb3, 0x01, 0x00, 0x57, 0x01, 0x00, 0x40, 0x49, 0xb1, 0x00, 0x00, - 0xa0, 0x94, 0x2e, 0x43, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x9b, 0x82, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x50, 0x95, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xac, 0x94, 0x2e, 0x43, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x9f, 0x82, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xae, 0x03, 0x00, 0x40, 0xa3, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x60, 0x15, 0x00, 0x40, - 0x85, 0x98, 0x01, 0x00, 0x08, 0x00, 0x00, 0x40, 0x40, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x59, 0x41, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x41, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x40, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x57, 0x41, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x42, 0x81, 0x6c, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, 0xa5, 0x82, 0xa0, 0x42, - 0x81, 0x6c, 0x00, 0x00, 0xa5, 0x82, 0x00, 0x50, 0x85, 0xc0, 0x00, 0x00, - 0xdd, 0x82, 0xa2, 0x41, 0x01, 0x7d, 0x00, 0x00, 0xb5, 0x82, 0x22, 0x58, - 0x73, 0x7d, 0x00, 0x00, 0x78, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xb0, 0x82, 0xa8, 0xb1, 0x9c, 0x30, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45, - 0x9d, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0xc9, 0x00, 0x00, - 0xb5, 0x82, 0x33, 0xc4, 0x81, 0x30, 0x00, 0x00, 0xb8, 0x82, 0xa1, 0xad, - 0x9d, 0x20, 0x00, 0x00, 0xaf, 0x82, 0x13, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x13, 0x4e, 0x5a, 0x83, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45, - 0x9d, 0xe0, 0x01, 0x00, 0xc0, 0x82, 0x22, 0xab, 0x80, 0x04, 0x00, 0x00, - 0xbe, 0x82, 0xa2, 0x40, 0x01, 0x7d, 0x00, 0x00, 0xc0, 0x82, 0x22, 0x5f, - 0x57, 0x7d, 0x00, 0x00, 0x36, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xc0, 0x82, 0x22, 0x5e, 0x57, 0x7d, 0x00, 0x00, 0x99, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xc5, 0x82, 0x22, 0x54, 0x73, 0x7d, 0x00, 0x00, - 0x74, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xc0, 0x82, 0xa8, 0xb1, - 0x00, 0x30, 0x00, 0x00, 0x8a, 0x84, 0xa2, 0x5f, 0x01, 0x7c, 0x00, 0x00, - 0xca, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc7, 0x82, 0xa2, 0x5f, - 0x59, 0x27, 0x00, 0x00, 0xc9, 0x82, 0xa2, 0x5c, 0x73, 0x7d, 0x00, 0x00, - 0xd0, 0x82, 0xa2, 0x5e, 0x73, 0x7d, 0x00, 0x00, 0xda, 0x82, 0x22, 0x5c, - 0x73, 0x7d, 0x00, 0x00, 0xdb, 0x82, 0x37, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xca, 0x82, 0xa8, 0xb1, - 0x36, 0x30, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xcc, 0x82, 0xa8, 0xb1, 0x00, 0x30, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, - 0x02, 0x88, 0x01, 0x00, 0xb9, 0x84, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xdb, 0x82, 0x34, 0x40, 0x81, 0x32, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xd1, 0x82, 0xa8, 0xb1, 0x12, 0x30, 0x00, 0x00, - 0xd8, 0x82, 0x52, 0x21, 0x13, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14, 0x41, - 0x2f, 0xc3, 0x01, 0x00, 0xff, 0x3f, 0x00, 0x09, 0x00, 0x8c, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x01, 0xf0, 0x01, 0x00, 0x11, 0x83, 0x00, 0x34, - 0x13, 0x84, 0x00, 0x00, 0xff, 0x3f, 0x14, 0x09, 0x00, 0x8c, 0x01, 0x00, - 0x6f, 0x83, 0x00, 0x43, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xdb, 0x82, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x13, 0x4e, 0x5a, 0x93, 0x00, 0x00, 0x0e, 0x87, 0xa2, 0x48, - 0xfd, 0x7f, 0x00, 0x00, 0x04, 0x00, 0xa2, 0xac, 0x80, 0x32, 0x00, 0x00, - 0xe3, 0x82, 0x22, 0x5a, 0x73, 0x7d, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xe0, 0x82, 0xa8, 0xb1, 0x7e, 0x31, 0x00, 0x00, - 0x01, 0x00, 0x00, 0xcf, 0x11, 0xc9, 0x00, 0x00, 0xe9, 0x82, 0xa2, 0x40, - 0x93, 0x7f, 0x00, 0x00, 0xe9, 0x82, 0x22, 0x44, 0x93, 0x7f, 0x00, 0x00, - 0xe5, 0x82, 0x42, 0xa5, 0x80, 0x30, 0x00, 0x00, 0xe8, 0x82, 0xa2, 0x40, - 0x93, 0x7f, 0x00, 0x00, 0xfb, 0x82, 0x1a, 0x40, 0x93, 0x93, 0x00, 0x00, - 0x00, 0x00, 0x1a, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xdd, 0x80, 0xa2, 0x40, - 0x73, 0x7d, 0x00, 0x00, 0x09, 0x87, 0x22, 0x44, 0x21, 0x6f, 0x00, 0x00, - 0x00, 0x87, 0x22, 0x40, 0x65, 0x7d, 0x00, 0x00, 0x00, 0x05, 0xa2, 0x5b, - 0x73, 0x7d, 0x00, 0x00, 0x04, 0x00, 0xa2, 0x49, 0x33, 0x7d, 0x00, 0x00, - 0xf3, 0x82, 0x22, 0x48, 0x33, 0x7d, 0x00, 0x00, 0xff, 0x01, 0x00, 0x99, - 0x80, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x81, 0xe0, 0x01, 0x00, - 0xa8, 0x98, 0x2f, 0x40, 0x33, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe0, 0xc1, 0x01, 0x00, 0xdd, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x40, 0x8b, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x62, 0xb1, 0x01, 0x00, - 0xaf, 0x82, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf6, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xf9, 0x82, 0x33, 0x40, 0x1f, 0x30, 0x00, 0x00, - 0xaf, 0x82, 0x13, 0x4e, 0x5a, 0x93, 0x00, 0x00, 0xfd, 0x82, 0xa0, 0xce, - 0x81, 0x50, 0x00, 0x00, 0x0f, 0x83, 0xa0, 0xcd, 0x81, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa5, 0x9c, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1, - 0x81, 0xb0, 0x01, 0x00, 0x0f, 0x83, 0x22, 0xb5, 0x81, 0x14, 0x00, 0x00, - 0x80, 0x15, 0x2f, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x01, 0x83, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb4, 0x65, 0x97, 0x01, 0x00, - 0xd0, 0x15, 0x2e, 0x40, 0x69, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x44, - 0x93, 0x83, 0x01, 0x00, 0x1a, 0x00, 0x00, 0xa2, 0x80, 0xdc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb1, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xf1, 0xb1, 0x01, 0x00, - 0x05, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x80, 0x00, 0x00, 0x40, - 0x62, 0xdd, 0x01, 0x00, 0x0a, 0x83, 0xa8, 0xa1, 0xe0, 0x31, 0x00, 0x00, - 0xe9, 0x82, 0x00, 0x88, 0x9e, 0xb3, 0x00, 0x00, 0xe9, 0x82, 0xa2, 0x41, - 0x67, 0x6f, 0x00, 0x00, 0xe9, 0x82, 0x00, 0x6f, 0xdb, 0x91, 0x00, 0x00, - 0x0f, 0x83, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0xe9, 0x82, 0x1a, 0x40, - 0x93, 0x83, 0x00, 0x00, 0x00, 0x99, 0x00, 0x09, 0x46, 0xc9, 0x01, 0x00, - 0x3f, 0x00, 0x00, 0xf3, 0x0c, 0x88, 0x01, 0x00, 0x1a, 0x83, 0xa6, 0x42, - 0x13, 0x60, 0x00, 0x00, 0x12, 0x94, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00, - 0x15, 0x83, 0x61, 0x40, 0x81, 0x32, 0x00, 0x00, 0x75, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x16, 0x83, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00, - 0x1f, 0x94, 0x71, 0x10, 0x94, 0x30, 0x01, 0x00, 0x1b, 0x83, 0x00, 0x58, - 0x1f, 0x90, 0x00, 0x00, 0x05, 0x94, 0x00, 0x95, 0x03, 0x30, 0x01, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x2d, 0xf0, 0x2e, 0xb0, 0x01, 0x00, - 0xee, 0x07, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x22, 0x83, 0x23, 0x4b, - 0xe4, 0x6d, 0x00, 0x00, 0x22, 0x83, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00, 0x22, 0x00, 0x2f, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x25, 0x83, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x27, 0x83, 0x85, 0x17, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x47, 0xc1, 0x01, 0x00, - 0x2c, 0x83, 0x22, 0x55, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x43, 0xd1, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xfa, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x97, 0xe0, 0x01, 0x00, 0x2d, 0x83, 0x00, 0x4b, - 0x44, 0xc1, 0x00, 0x00, 0x12, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, - 0x28, 0x00, 0x00, 0xf6, 0x02, 0xcc, 0x01, 0x00, 0x0a, 0x00, 0x00, 0xa1, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x28, 0xf0, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x2a, 0xb0, 0x01, 0x00, - 0xc0, 0x28, 0x3c, 0x46, 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x44, - 0x95, 0xb0, 0x01, 0x00, 0x39, 0x83, 0xa2, 0xf8, 0x0e, 0x30, 0x00, 0x00, - 0x49, 0x83, 0x22, 0x41, 0x95, 0x50, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x50, - 0x49, 0xc1, 0x01, 0x00, 0x35, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x36, 0x83, 0xa2, 0xf8, 0x16, 0x6c, 0x00, 0x00, 0x36, 0x83, 0xa2, 0xf8, - 0x10, 0x6c, 0x00, 0x00, 0x36, 0x83, 0xa2, 0xf0, 0x1a, 0x6c, 0x00, 0x00, - 0x47, 0x83, 0x22, 0x58, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, - 0x13, 0xf0, 0x01, 0x00, 0x3e, 0x83, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x42, 0x83, 0xa2, 0xf3, 0x74, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, - 0xe6, 0x95, 0x01, 0x00, 0x47, 0x83, 0x75, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x96, 0xb0, 0x01, 0x00, 0x3f, 0x00, 0x75, 0xf3, - 0x0c, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x45, 0x83, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x47, 0x83, 0x67, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x4f, 0x83, 0x77, 0x41, 0x2d, 0xc3, 0x00, 0x00, 0x4d, 0x83, 0x22, 0x58, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x62, 0xb1, 0x01, 0x00, 0x4b, 0x83, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x4d, 0x83, 0x67, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x7c, 0x83, 0x77, 0x41, 0x2d, 0xc3, 0x00, 0x00, 0x03, 0x00, 0x00, 0x07, - 0x1a, 0xf4, 0x01, 0x00, 0xd8, 0x92, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, - 0x5d, 0x83, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, 0x55, 0x83, 0x22, 0x42, - 0x81, 0x6c, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x5c, 0x83, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, 0xcc, 0x93, 0x00, 0x5f, - 0x01, 0x10, 0x01, 0x00, 0x5b, 0x83, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x02, 0xb0, 0x01, 0x00, 0x41, 0x93, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00, - 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x14, 0x87, 0x00, 0x40, - 0x0f, 0xb0, 0x00, 0x00, 0x65, 0x83, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, - 0x53, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x65, 0x83, 0x22, 0x20, - 0x85, 0x6c, 0x00, 0x00, 0x62, 0x83, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x33, 0x93, 0x00, 0x5c, - 0x1f, 0x00, 0x01, 0x00, 0x25, 0x95, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x68, 0x83, 0x82, 0xf0, 0x18, 0x30, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x45, - 0x8f, 0xb0, 0x00, 0x00, 0x28, 0x20, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00, - 0x6c, 0x83, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, 0xc9, 0x94, 0x00, 0x4b, - 0x95, 0x30, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x4b, 0x8f, 0xb0, 0x00, 0x00, - 0xd8, 0x93, 0x00, 0x03, 0x48, 0x31, 0x01, 0x00, 0xb4, 0x91, 0x00, 0x40, - 0x81, 0x30, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0x50, - 0x03, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50, - 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x77, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, - 0x62, 0xc9, 0x01, 0x00, 0x79, 0x83, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x2e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, - 0x00, 0x41, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00, 0xee, 0x07, 0x2e, 0x47, - 0x97, 0x90, 0x01, 0x00, 0x8f, 0x83, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, - 0x8d, 0x83, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x8d, 0x83, 0x23, 0xa2, - 0x02, 0x6c, 0x00, 0x00, 0x41, 0x93, 0x00, 0x52, 0x95, 0x30, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x00, 0x2d, 0x00, - 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x03, 0xb0, 0x01, 0x00, 0xac, 0x83, 0x00, 0x5c, - 0x17, 0x90, 0x00, 0x00, 0xa1, 0x83, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x9a, 0x83, 0x22, 0x5f, - 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x58, 0xf1, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03, - 0xf0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, - 0x96, 0x83, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x97, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x72, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0xff, 0x0f, 0x00, 0xf6, 0x80, 0x88, 0x01, 0x00, - 0x9e, 0x83, 0xa2, 0xa6, 0x81, 0x6c, 0x00, 0x00, 0xa1, 0x83, 0x00, 0xf2, - 0x3a, 0xb0, 0x00, 0x00, 0x87, 0x84, 0xa2, 0x4b, 0xfd, 0x7f, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2a, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xac, 0x83, 0x22, 0x4a, 0x2f, 0x7c, 0x00, 0x00, - 0xac, 0x83, 0x22, 0x48, 0x2f, 0x7c, 0x00, 0x00, 0x0a, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x3f, 0x00, 0x00, 0xf2, 0x86, 0x88, 0x01, 0x00, - 0x1f, 0x00, 0x00, 0x43, 0x84, 0x88, 0x01, 0x00, 0x05, 0x00, 0x00, 0x43, - 0x80, 0xf4, 0x01, 0x00, 0x98, 0x94, 0x3d, 0x42, 0x81, 0xe0, 0x01, 0x00, - 0xac, 0x83, 0xa2, 0x42, 0xe0, 0x7d, 0x00, 0x00, 0x87, 0x84, 0xa2, 0x4b, - 0xfd, 0x7f, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2a, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xac, 0x83, 0x69, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x09, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x79, 0x41, 0x47, 0xc3, 0x01, 0x00, 0xb2, 0x83, 0x22, 0xa1, - 0x09, 0x6c, 0x00, 0x00, 0xf5, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xaf, 0x83, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00, 0xeb, 0x83, 0xa3, 0x92, - 0x03, 0x6c, 0x00, 0x00, 0x7d, 0x95, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, 0x2a, 0x87, 0x22, 0x08, - 0x80, 0x32, 0x00, 0x00, 0xb8, 0x83, 0x22, 0x5c, 0x17, 0x7c, 0x00, 0x00, - 0xb9, 0x83, 0x00, 0x00, 0x2a, 0xb0, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x2a, 0xc8, 0x01, 0x00, 0x02, 0x00, 0x00, 0x08, 0x80, 0xc8, 0x01, 0x00, - 0xbd, 0x83, 0xa2, 0x43, 0x2f, 0x7c, 0x00, 0x00, 0xcc, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd9, 0x83, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x01, 0x8c, 0xcc, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x4c, - 0x03, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, 0x02, 0xb0, 0x01, 0x00, - 0x10, 0x80, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, - 0xf0, 0xcd, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x15, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xc6, 0x83, 0xa8, 0x54, - 0x17, 0x10, 0x00, 0x00, 0xd9, 0x83, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0xd8, 0x83, 0x22, 0x43, - 0x2f, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x8c, 0xcc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x03, 0xb0, 0x01, 0x00, 0xed, 0x94, 0x00, 0x43, - 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, 0x02, 0xb0, 0x01, 0x00, - 0x10, 0x80, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, - 0xf0, 0xcd, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x09, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x15, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xd9, 0x83, 0x28, 0x54, - 0x17, 0x10, 0x00, 0x00, 0xd5, 0x83, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xed, 0x94, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0xdb, 0x83, 0x22, 0x50, - 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x17, 0x90, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x17, 0x98, 0x88, 0x01, 0x00, 0xde, 0x83, 0xa2, 0x41, - 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x17, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xdf, 0x83, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xd4, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xe6, 0x83, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, - 0x16, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1d, - 0xe4, 0xb1, 0x01, 0x00, 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, - 0xe9, 0x83, 0xa2, 0x5f, 0x2f, 0x7c, 0x00, 0x00, 0x90, 0x91, 0x00, 0x01, - 0x38, 0x43, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2a, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xed, 0x83, 0xa2, 0x4b, - 0xfd, 0x7f, 0x00, 0x00, 0x84, 0x84, 0x00, 0x41, 0x43, 0xc3, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x27, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x11, 0xb0, 0x01, 0x00, 0xef, 0x83, 0x35, 0x01, 0x86, 0x30, 0x00, 0x00, - 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xf6, 0x83, 0x28, 0xb1, - 0x30, 0x30, 0x00, 0x00, 0xf0, 0x83, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00, - 0x74, 0x84, 0xa2, 0x40, 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x43, 0xc3, 0x01, 0x00, 0x83, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xf6, 0x83, 0xa8, 0xb1, - 0x12, 0x30, 0x00, 0x00, 0xff, 0x83, 0xa2, 0x40, 0x11, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x43, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2c, 0xb0, 0x01, 0x00, - 0xde, 0x07, 0x00, 0x43, 0x80, 0xce, 0x01, 0x00, 0xf0, 0x83, 0xaa, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x04, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x40, 0x00, 0x3e, 0x43, 0x27, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x27, 0xc0, 0x01, 0x00, 0xf0, 0x83, 0xa3, 0x0b, - 0x87, 0x50, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, 0x1b, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x2a, 0xc8, 0x01, 0x00, 0x40, 0x00, 0x2d, 0x40, 0x39, 0xb0, 0x01, 0x00, - 0x0c, 0x84, 0xa2, 0x40, 0x27, 0x6c, 0x00, 0x00, 0x22, 0x00, 0x00, 0x08, - 0x12, 0xc8, 0x01, 0x00, 0xde, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, - 0x0f, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x12, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x32, 0xb0, 0x01, 0x00, 0x14, 0x00, 0x20, 0x01, 0xe0, 0xb1, 0x01, 0x00, - 0xee, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00, 0x14, 0x84, 0x23, 0x01, - 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36, 0xb0, 0x01, 0x00, - 0x1f, 0x84, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00, 0x20, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x1b, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x18, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xb8, 0x92, 0x00, 0x43, - 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x44, 0xc9, 0x01, 0x00, - 0x2e, 0x84, 0x22, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, - 0x25, 0x84, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x25, 0xd0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x4c, - 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x37, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x2b, 0xc0, 0x01, 0x00, 0x14, 0x84, 0x00, 0x45, - 0x1f, 0x80, 0x00, 0x00, 0x30, 0x84, 0xa3, 0x12, 0x36, 0x6c, 0x00, 0x00, - 0x31, 0x84, 0x68, 0x1b, 0x28, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, - 0x28, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, - 0x34, 0x84, 0xa8, 0x15, 0xe0, 0x31, 0x00, 0x00, 0x5a, 0x84, 0x22, 0x14, - 0x02, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x14, - 0x12, 0xc0, 0x01, 0x00, 0x53, 0x84, 0xa2, 0x14, 0x36, 0x50, 0x00, 0x00, - 0x44, 0x84, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, 0x30, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x42, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x3f, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x10, 0x00, 0x00, 0xf0, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x2b, 0x80, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00, - 0x49, 0x84, 0x23, 0x01, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x36, 0xb0, 0x01, 0x00, 0x54, 0x84, 0x22, 0x1b, 0x02, 0x6c, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x5c, - 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x15, - 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x50, 0x84, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x54, 0x84, 0x00, 0x03, 0x48, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x14, 0x2a, 0xc0, 0x01, 0x00, 0x14, 0x84, 0xa2, 0x40, - 0x25, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x39, 0xc0, 0x01, 0x00, - 0x40, 0x00, 0x3d, 0x43, 0x39, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0x25, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x12, 0xb0, 0x01, 0x00, - 0x14, 0x84, 0x00, 0xf0, 0x30, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x42, 0xc9, 0x01, 0x00, 0x60, 0x84, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x19, - 0x62, 0xdd, 0x01, 0x00, 0x5d, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xb8, 0x92, 0x00, 0x40, - 0x2b, 0x30, 0x01, 0x00, 0x18, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0x64, 0x84, 0x22, 0x50, 0x2f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, - 0x17, 0x90, 0x01, 0x00, 0x07, 0x00, 0x00, 0x17, 0x98, 0x88, 0x01, 0x00, - 0x67, 0x84, 0xa2, 0x41, 0x99, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, - 0x17, 0x90, 0x01, 0x00, 0x6a, 0x84, 0x22, 0x43, 0x2f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x17, 0x90, 0x01, 0x00, 0x16, 0x00, 0x20, 0x1d, - 0xe4, 0xb1, 0x01, 0x00, 0x6c, 0x84, 0xa3, 0x40, 0x27, 0x6c, 0x00, 0x00, - 0x6e, 0x84, 0x60, 0x5f, 0x17, 0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x0b, - 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x60, 0x13, 0x16, 0x94, 0x01, 0x00, - 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x2a, 0x87, 0xa2, 0x5f, - 0x2f, 0x7c, 0x00, 0x00, 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x90, 0x91, 0x00, 0x01, - 0x38, 0x43, 0x01, 0x00, 0x2a, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0x62, 0xb1, 0x01, 0x00, - 0x76, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x62, 0xb1, 0x01, 0x00, 0x78, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x83, 0x84, 0x22, 0x13, 0x82, 0x6c, 0x00, 0x00, 0x40, 0x00, 0x3d, 0x43, - 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, - 0x62, 0xb1, 0x01, 0x00, 0x7e, 0x84, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x62, 0xb1, 0x01, 0x00, 0x80, 0x84, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x7a, 0x84, 0x00, 0x41, 0x83, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x15, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x82, 0x00, 0xa6, - 0x04, 0xb0, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x41, 0x93, 0x00, 0x52, - 0x95, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0x2a, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x01, 0x80, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0e, 0xf4, 0x01, 0x00, - 0x3f, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, - 0x1a, 0xf4, 0x01, 0x00, 0xd8, 0x92, 0x00, 0x07, 0x16, 0x30, 0x01, 0x00, - 0x95, 0x84, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, 0x93, 0x84, 0x22, 0x42, - 0x81, 0x6c, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x94, 0x84, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, 0x14, 0x87, 0x00, 0x40, - 0x0f, 0xb0, 0x00, 0x00, 0x9d, 0x84, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, - 0x53, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x9d, 0x84, 0x22, 0x20, - 0x85, 0x6c, 0x00, 0x00, 0x9a, 0x84, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x33, 0x93, 0x00, 0x5c, - 0x1f, 0x00, 0x01, 0x00, 0x25, 0x95, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, 0xa3, 0x84, 0x22, 0x3a, - 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0xb0, 0x01, 0x00, - 0x7b, 0x88, 0x00, 0x40, 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xa7, 0x84, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40, 0x01, 0xb0, 0x00, 0x00, - 0x1e, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x05, 0x94, 0x00, 0x95, - 0x03, 0x30, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, - 0x2e, 0xb0, 0x01, 0x00, 0x28, 0x20, 0x00, 0xa6, 0x96, 0xb0, 0x01, 0x00, - 0xb0, 0x84, 0x22, 0x17, 0x96, 0x04, 0x00, 0x00, 0xc9, 0x94, 0x00, 0x4b, - 0x95, 0x30, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x4c, 0x8f, 0xb0, 0x00, 0x00, - 0xb2, 0x84, 0x83, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x43, 0xc1, 0x01, 0x00, 0xb4, 0x84, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0x43, 0xc1, 0x01, 0x00, 0x28, 0x00, 0x00, 0xf6, - 0x02, 0xcc, 0x01, 0x00, 0x12, 0x00, 0x00, 0xa1, 0x2a, 0xc8, 0x01, 0x00, - 0xd8, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb4, 0x91, 0x00, 0x41, - 0x81, 0x30, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb1, 0x01, 0x00, 0xbe, 0x84, 0x64, 0x47, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0xbf, 0x84, 0xa8, 0x1b, - 0xe0, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x74, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x03, 0xe0, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0xe4, 0x84, 0x01, 0xfb, 0x08, 0x30, 0x00, 0x00, - 0x37, 0x85, 0x87, 0xfb, 0x22, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, - 0x0e, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0xb0, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0xd8, 0x92, 0x00, 0x07, - 0x16, 0x30, 0x01, 0x00, 0xda, 0x84, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, - 0xce, 0x84, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xd9, 0x84, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x04, 0x7e, 0x89, 0x01, 0x00, 0xd2, 0x84, 0xa6, 0x5f, - 0x0f, 0x00, 0x00, 0x00, 0x2c, 0x92, 0x00, 0x40, 0x05, 0x30, 0x01, 0x00, - 0xd7, 0x84, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x13, 0x00, 0x00, 0x40, - 0x87, 0x98, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0x0c, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x84, 0xb0, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x40, 0x05, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40, - 0x0f, 0xb0, 0x00, 0x00, 0xe2, 0x84, 0xa2, 0x5a, 0x1f, 0x7c, 0x00, 0x00, - 0x53, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xe2, 0x84, 0x22, 0x20, - 0x85, 0x6c, 0x00, 0x00, 0xdf, 0x84, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x33, 0x93, 0x00, 0x5c, - 0x1f, 0x00, 0x01, 0x00, 0x25, 0x95, 0x00, 0x42, 0x61, 0x31, 0x01, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x90, 0x04, 0x00, 0x07, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, 0xe6, 0x84, 0x21, 0x04, - 0x80, 0x20, 0x00, 0x00, 0xe7, 0x84, 0x00, 0x40, 0x10, 0xc9, 0x00, 0x00, - 0xbd, 0x87, 0x00, 0x4b, 0x81, 0xb0, 0x00, 0x00, 0x06, 0x85, 0x00, 0x43, - 0x81, 0xb0, 0x00, 0x00, 0x0a, 0x85, 0x00, 0xfb, 0x22, 0xb0, 0x00, 0x00, - 0xbd, 0x87, 0x00, 0x41, 0x81, 0xb0, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x4e, - 0x8f, 0xb0, 0x00, 0x00, 0x02, 0x85, 0x00, 0x5a, 0x8f, 0xb0, 0x00, 0x00, - 0xef, 0x84, 0x00, 0x47, 0x8f, 0xb0, 0x00, 0x00, 0xbd, 0x87, 0x00, 0x53, - 0x81, 0xb0, 0x00, 0x00, 0xbd, 0x87, 0x00, 0x56, 0x81, 0xb0, 0x00, 0x00, - 0x32, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x7b, 0x88, 0xa0, 0x0a, - 0xe4, 0x6d, 0x00, 0x00, 0xf5, 0x84, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xf4, 0x84, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x53, - 0x8f, 0xb0, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x54, 0x8f, 0xb0, 0x00, 0x00, - 0xfe, 0x84, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0xf8, 0x84, 0xa2, 0x0a, - 0xe4, 0x6d, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x5d, 0x8f, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x80, 0xd0, 0x01, 0x00, 0xfc, 0x84, 0xa0, 0x91, 0x81, 0x6c, 0x00, 0x00, - 0x7b, 0x88, 0x00, 0x5e, 0x8f, 0xb0, 0x00, 0x00, 0x25, 0x00, 0x00, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x85, 0x20, 0x91, 0xe5, 0x6d, 0x00, 0x00, 0x7b, 0x88, 0x00, 0x54, - 0x8f, 0xb0, 0x00, 0x00, 0x21, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x7b, 0x88, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x32, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x7b, 0x88, 0xa0, 0x0a, 0xe4, 0x6d, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x7b, 0x88, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xf3, 0x82, 0xf4, 0x01, 0x00, 0xbd, 0x87, 0xa0, 0x42, - 0x83, 0x6c, 0x00, 0x00, 0xbd, 0x87, 0x00, 0x54, 0x81, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, - 0x1a, 0xf4, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00, 0x13, 0x85, 0x22, 0x0b, - 0xe6, 0x7d, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0xc6, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0f, 0xb0, 0x01, 0x00, 0x14, 0x87, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, - 0x25, 0x85, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0x20, 0x85, 0xa2, 0x54, - 0xfd, 0x7f, 0x00, 0x00, 0x18, 0x85, 0x22, 0x55, 0xfd, 0x7f, 0x00, 0x00, - 0x82, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x10, 0x85, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x10, 0x85, 0x22, 0x53, 0xfd, 0x7f, 0x00, 0x00, - 0x14, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x96, 0xb0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4b, 0x80, 0xf4, 0x01, 0x00, - 0x0c, 0xbc, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x20, 0x85, 0x22, 0x43, - 0x80, 0x6c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x4b, 0x80, 0x88, 0x01, 0x00, - 0x10, 0x85, 0xa2, 0x43, 0x80, 0x6c, 0x00, 0x00, 0x7c, 0x96, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x21, 0x85, 0x46, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x24, 0x85, 0xa0, 0xf0, 0x30, 0x6f, 0x00, 0x00, 0x16, 0x85, 0x1e, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x41, 0x31, 0xc3, 0x01, 0x00, - 0x5d, 0x92, 0x00, 0x40, 0x25, 0x30, 0x01, 0x00, 0x29, 0x85, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x33, 0x93, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x14, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x96, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07, - 0x18, 0xe4, 0x01, 0x00, 0x00, 0x08, 0x00, 0x0c, 0xe0, 0x99, 0x01, 0x00, - 0x90, 0x04, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, - 0x46, 0xc9, 0x01, 0x00, 0x30, 0x85, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, 0x00, 0x02, 0x00, 0xa1, - 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, - 0x04, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0xbd, 0x87, 0x00, 0x40, 0x81, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfb, 0x28, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, - 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0xb0, 0x01, 0x00, - 0x41, 0x85, 0x22, 0x46, 0x23, 0x7c, 0x00, 0x00, 0x3d, 0x85, 0x22, 0x40, - 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x1f, 0x90, 0x01, 0x00, - 0x3f, 0x85, 0x22, 0x41, 0x87, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x1f, 0x90, 0x01, 0x00, 0x41, 0x85, 0x22, 0x42, 0x87, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x41, 0x85, 0x66, 0x1b, - 0x2c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x13, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x76, 0x41, 0x41, 0xc3, 0x01, 0x00, 0x70, 0x85, 0x23, 0x92, - 0x15, 0x6c, 0x00, 0x00, 0x70, 0x85, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, - 0x74, 0x85, 0x22, 0x4b, 0xfd, 0x7f, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, - 0xa2, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x27, 0xb0, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x0a, 0x24, 0xc8, 0x01, 0x00, 0x94, 0x92, 0x00, 0x40, - 0x0f, 0x30, 0x01, 0x00, 0x6e, 0x85, 0x22, 0x08, 0x40, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x12, - 0x24, 0xcc, 0x01, 0x00, 0x4a, 0x85, 0xaa, 0x41, 0x27, 0x40, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x13, 0x80, 0xcc, 0x01, 0x00, 0x6a, 0x85, 0x26, 0x40, - 0x23, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x83, 0xb0, 0x01, 0x00, - 0x60, 0x00, 0x00, 0x03, 0x84, 0xc8, 0x01, 0x00, 0x10, 0x00, 0x00, 0x10, - 0x48, 0xcd, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00, - 0x57, 0x85, 0xa2, 0x40, 0x83, 0x6c, 0x00, 0x00, 0x63, 0x85, 0x00, 0x41, - 0x83, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x42, 0x44, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x68, 0x21, 0x38, 0x96, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50, - 0x49, 0xc1, 0x01, 0x00, 0x5c, 0x85, 0xa2, 0x44, 0x23, 0x6c, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xf1, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x20, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x5f, 0x85, 0xa8, 0x42, 0xe0, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x85, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xa3, 0xc1, 0x01, 0x00, - 0x55, 0x85, 0xa2, 0x41, 0x81, 0x50, 0x00, 0x00, 0x6a, 0x85, 0x22, 0x40, - 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x67, 0x85, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x48, 0xb1, 0x01, 0x00, 0xee, 0x07, 0x00, 0x40, - 0x25, 0x98, 0x01, 0x00, 0x17, 0x00, 0x00, 0xd0, 0x2a, 0xc8, 0x01, 0x00, - 0x7d, 0x85, 0x00, 0x17, 0x10, 0xb0, 0x00, 0x00, 0x7e, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x74, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x94, 0x92, 0x00, 0x92, 0x25, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x31, 0xb0, 0x01, 0x00, 0x74, 0x85, 0x22, 0x08, 0x2e, 0x30, 0x00, 0x00, - 0x7d, 0x85, 0x00, 0x41, 0x27, 0xb0, 0x00, 0x00, 0x80, 0x80, 0x00, 0xa6, - 0x04, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0xc6, 0x95, 0x00, 0x0a, 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0x7c, 0x85, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x00, 0x88, - 0x1c, 0xcc, 0x01, 0x00, 0xf5, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x14, 0x87, 0x00, 0x41, 0x3f, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0f, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x00, 0x01, 0x80, 0xce, 0x01, 0x00, - 0x91, 0x85, 0x2a, 0x40, 0x81, 0x30, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0x86, 0x85, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x85, 0xa2, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0x86, 0x85, 0xa3, 0x07, 0x03, 0x6c, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x89, 0x85, 0xa3, 0x40, - 0x02, 0x6c, 0x00, 0x00, 0x28, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, - 0x8b, 0x85, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, - 0xf0, 0xcd, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x0e, 0xcc, 0x01, 0x00, - 0x28, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x8f, 0x85, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x08, 0xb0, 0x01, 0x00, 0xa0, 0x01, 0x2d, 0x40, 0x00, 0xc0, 0x01, 0x00, - 0x5b, 0x86, 0x22, 0x0f, 0x42, 0x05, 0x00, 0x00, 0xa2, 0x85, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x9d, 0x85, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x9a, 0x85, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xa2, 0x85, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00, - 0x00, 0x80, 0x00, 0xa1, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0xe1, 0x91, 0x01, 0x00, 0xc0, 0x06, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x54, - 0x29, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x0e, 0xb0, 0x01, 0x00, 0x42, 0x00, 0x00, 0x03, 0x0a, 0xc8, 0x01, 0x00, - 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00, 0xd6, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x02, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x14, 0x24, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x10, 0xc0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x08, 0x10, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0xfe, 0x7f, 0x00, 0x05, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xe4, 0xb1, 0x01, 0x00, - 0xcb, 0x85, 0x22, 0x01, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, - 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa4, 0x80, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x48, 0xc1, 0x01, 0x00, 0xb8, 0x85, 0xa3, 0x07, - 0x02, 0x6c, 0x00, 0x00, 0xb9, 0x85, 0x68, 0x01, 0x1a, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x68, 0x07, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x02, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0xc0, 0x01, 0x00, - 0xc5, 0x85, 0x22, 0x40, 0x03, 0x6c, 0x00, 0x00, 0xc5, 0x85, 0x22, 0x42, - 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0xe9, 0x85, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xc2, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, 0xc7, 0x85, 0xa8, 0x40, - 0x23, 0x30, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xe9, 0x85, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, - 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x86, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x10, 0x48, 0xc1, 0x01, 0x00, 0xd0, 0x85, 0xa3, 0x12, - 0x0e, 0x6c, 0x00, 0x00, 0xd1, 0x85, 0x60, 0x07, 0x1a, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x12, 0x1a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x0d, - 0x16, 0x94, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x16, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0x68, 0x08, 0x3e, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, - 0xd8, 0x85, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, 0x07, 0x86, 0x22, 0x0d, - 0x14, 0x6c, 0x00, 0x00, 0xde, 0x85, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x10, 0xc0, 0x01, 0x00, 0xe2, 0x85, 0x00, 0x0d, - 0x24, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2b, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x20, - 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, - 0xe4, 0x85, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, 0xe9, 0x85, 0x00, 0x41, - 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xe5, 0x85, 0xa8, 0x5c, - 0x1f, 0x00, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x07, 0x86, 0x22, 0x0d, - 0x14, 0x50, 0x00, 0x00, 0x06, 0x86, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00, - 0xf5, 0x85, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xf3, 0x85, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xf0, 0x85, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0xfa, 0x85, 0x1f, 0xf0, - 0x0e, 0x30, 0x00, 0x00, 0xb2, 0x85, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0xb2, 0x85, 0x23, 0x07, - 0x14, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, - 0x24, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x00, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x03, 0x86, 0xa8, 0x46, - 0x1f, 0x10, 0x00, 0x00, 0xb2, 0x85, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, - 0xb2, 0x85, 0x00, 0x0d, 0x18, 0xc0, 0x00, 0x00, 0x04, 0x00, 0x2e, 0x14, - 0x0a, 0xd0, 0x01, 0x00, 0x12, 0x00, 0x00, 0x05, 0x48, 0xcd, 0x01, 0x00, - 0xfe, 0x7f, 0x00, 0x05, 0x42, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x2a, 0xf2, - 0xe0, 0xb1, 0x01, 0x00, 0x0d, 0x86, 0x22, 0x40, 0x31, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x81, 0x00, 0xf6, 0x80, 0xce, 0x01, 0x00, - 0x11, 0x86, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x43, 0xc1, 0x01, 0x00, 0x13, 0x86, 0x22, 0x0b, 0xed, 0x6d, 0x00, 0x00, - 0x08, 0x00, 0x00, 0xa1, 0x42, 0xc9, 0x01, 0x00, 0x02, 0x00, 0x00, 0xa1, - 0x46, 0xc9, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xfa, 0x94, 0x88, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x4a, 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, - 0x0e, 0xb0, 0x01, 0x00, 0x1b, 0x86, 0x22, 0x47, 0x1f, 0x7c, 0x00, 0x00, - 0x04, 0x00, 0x1f, 0x43, 0x0e, 0x50, 0x00, 0x00, 0x1b, 0x86, 0xa0, 0x46, - 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00, - 0x1f, 0x86, 0x22, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x91, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x0f, 0xa2, 0x42, 0x31, 0x00, 0x00, - 0x22, 0x86, 0x00, 0x40, 0x89, 0xb0, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xa2, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x89, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x95, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x82, 0xb0, 0x01, 0x00, 0x25, 0x86, 0xa0, 0x41, 0x90, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x91, 0xc0, 0x01, 0x00, 0x2a, 0x86, 0x22, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0x2a, 0x86, 0xa0, 0x43, 0x89, 0x6c, 0x00, 0x00, - 0x2a, 0x86, 0x20, 0x45, 0x89, 0x6c, 0x00, 0x00, 0x2a, 0x86, 0xa0, 0x41, - 0x0e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x89, 0xc0, 0x01, 0x00, 0x22, 0x86, 0xa2, 0x41, - 0x95, 0x50, 0x00, 0x00, 0x33, 0x86, 0x22, 0x48, 0x1f, 0x7c, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x48, 0x92, 0xf4, 0x01, 0x00, 0xff, 0xff, 0x00, 0x48, - 0x90, 0x88, 0x01, 0x00, 0x31, 0x86, 0x90, 0x48, 0x92, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, 0x0a, 0x00, 0x00, 0xa2, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x93, 0xa4, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x12, 0x00, 0x00, 0x14, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x17, 0xf0, 0xb1, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x05, 0xe0, 0xcd, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, - 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x40, 0x62, 0xdd, 0x01, 0x00, 0x39, 0x86, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x44, 0x86, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0x43, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x40, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x47, 0x86, 0xa2, 0x47, 0x1f, 0x7c, 0x00, 0x00, - 0xcc, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc0, 0x86, 0x00, 0x17, - 0x10, 0xb0, 0x00, 0x00, 0xd3, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x2f, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x4b, 0x86, 0xa0, 0x07, - 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x17, 0xf0, 0x01, 0x00, 0x4f, 0x86, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, - 0x17, 0xa4, 0x01, 0x00, 0x10, 0x00, 0x00, 0x14, 0x2a, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x2b, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x2a, 0x94, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0x59, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x56, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x17, 0x10, 0xdc, 0x01, 0x00, - 0xc0, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x63, 0x86, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x63, 0x86, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x60, 0x86, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x68, 0x86, 0x22, 0x07, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x42, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x42, 0xc1, 0x01, 0x00, - 0x00, 0x80, 0x00, 0xa1, 0x46, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0xe1, 0x91, 0x01, 0x00, 0x04, 0x00, 0x2e, 0x03, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0xe0, 0xb1, 0x01, 0x00, 0x6d, 0x86, 0x22, 0x40, - 0x31, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x18, 0x38, 0x96, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x72, 0x86, 0xa8, 0x40, - 0x23, 0x30, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x52, 0x11, 0xc0, 0x01, 0x00, 0x10, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x0e, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xa4, 0x0c, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, - 0x86, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xc1, 0x01, 0x00, - 0x80, 0x86, 0xa3, 0x12, 0x0e, 0x6c, 0x00, 0x00, 0x81, 0x86, 0x68, 0x07, - 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x68, 0x12, 0x1a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x86, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x68, 0x08, - 0x3e, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x02, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x43, 0x62, 0xdd, 0x01, 0x00, - 0x86, 0x86, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, 0xb5, 0x86, 0x22, 0x0d, - 0x14, 0x6c, 0x00, 0x00, 0x8c, 0x86, 0x22, 0x0d, 0x24, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x10, 0xc0, 0x01, 0x00, 0x90, 0x86, 0x00, 0x0d, - 0x24, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2b, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x15, 0xa2, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x20, - 0x10, 0xc8, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x25, 0x98, 0x01, 0x00, - 0x92, 0x86, 0x22, 0x42, 0x23, 0x6c, 0x00, 0x00, 0x97, 0x86, 0x00, 0x41, - 0x23, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x93, 0x86, 0xa8, 0x5c, - 0x1f, 0x00, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0x0d, - 0x14, 0x50, 0x00, 0x00, 0xb4, 0x86, 0xa2, 0x0d, 0x0e, 0x50, 0x00, 0x00, - 0xa3, 0x86, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x1f, 0x80, 0x01, 0x00, 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xa1, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x9e, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x46, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0xe1, 0x91, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x06, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x04, 0xb0, 0x01, 0x00, 0xa8, 0x86, 0x1f, 0xf0, - 0x0e, 0x30, 0x00, 0x00, 0x7b, 0x86, 0x00, 0x4c, 0x0d, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x5f, 0x0f, 0x80, 0x01, 0x00, 0x7b, 0x86, 0x23, 0x07, - 0x14, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, - 0x24, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x00, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xb1, 0x86, 0xa8, 0x46, - 0x1f, 0x10, 0x00, 0x00, 0x7b, 0x86, 0x00, 0x03, 0x0c, 0xb0, 0x00, 0x00, - 0x7b, 0x86, 0x00, 0x0d, 0x18, 0xc0, 0x00, 0x00, 0xbe, 0x86, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x00, 0x00, 0x3c, 0x44, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x10, - 0x48, 0xc1, 0x01, 0x00, 0xbe, 0x86, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xbb, 0x86, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, - 0x10, 0xb0, 0x01, 0x00, 0xc0, 0x86, 0x00, 0x40, 0x2b, 0xb0, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, - 0xe0, 0xb1, 0x01, 0x00, 0xc5, 0x86, 0x22, 0x9f, 0x13, 0x6c, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x88, 0x1c, 0xcc, 0x01, 0x00, 0xf5, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xd7, 0x95, 0x00, 0x41, 0x3f, 0x43, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x05, 0xb0, 0x01, 0x00, 0xc6, 0x95, 0x00, 0x40, 0x0f, 0x30, 0x01, 0x00, - 0x2a, 0x87, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x0e, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x01, 0x84, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x07, 0x1a, 0xf4, 0x01, 0x00, 0xd8, 0x92, 0x00, 0x07, - 0x16, 0x30, 0x01, 0x00, 0xd4, 0x86, 0x22, 0x41, 0x81, 0x6c, 0x00, 0x00, - 0xd2, 0x86, 0x22, 0x42, 0x81, 0x6c, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xd3, 0x86, 0x22, 0x5f, 0x0f, 0x7c, 0x00, 0x00, - 0x14, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, 0xdc, 0x86, 0xa2, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x53, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xdc, 0x86, 0x22, 0x20, 0x85, 0x6c, 0x00, 0x00, 0xd9, 0x86, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x33, 0x93, 0x00, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x25, 0x95, 0x00, 0x42, - 0x61, 0x31, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x90, 0x04, 0x00, 0x07, 0x96, 0x30, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x18, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x01, 0x00, 0xbd, 0x87, 0xa2, 0x5f, - 0x81, 0x6c, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x43, 0x19, 0x80, 0x01, 0x00, - 0x37, 0x00, 0x2d, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, - 0x8e, 0xf4, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, 0x90, 0x88, 0x01, 0x00, - 0xeb, 0x86, 0x22, 0x48, 0x8e, 0x6c, 0x00, 0x00, 0x36, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, - 0xeb, 0x86, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00, 0xea, 0x86, 0x23, 0x41, - 0x8f, 0x6c, 0x00, 0x00, 0xbd, 0x87, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00, - 0xbd, 0x87, 0x00, 0x48, 0x81, 0xb0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00, - 0xf0, 0x86, 0x22, 0x0a, 0x90, 0x40, 0x00, 0x00, 0xaa, 0x95, 0x00, 0x40, - 0x91, 0x30, 0x01, 0x00, 0xbd, 0x87, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, - 0xb0, 0x00, 0x2d, 0x45, 0x81, 0xb0, 0x01, 0x00, 0xfc, 0x86, 0x22, 0xf0, - 0x2c, 0x30, 0x00, 0x00, 0xa3, 0x00, 0x2d, 0x30, 0x83, 0xb0, 0x01, 0x00, - 0xac, 0x00, 0x2d, 0xf3, 0x82, 0xe0, 0x01, 0x00, 0xf6, 0x86, 0xa3, 0x41, - 0x2c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x82, 0xb0, 0x01, 0x00, - 0x98, 0x00, 0x2d, 0xf0, 0x82, 0xc0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, - 0x82, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x98, 0xe8, 0x01, 0x00, - 0xbd, 0x87, 0x20, 0x4c, 0x82, 0x6c, 0x00, 0x00, 0x7c, 0x00, 0x2d, 0x41, - 0x98, 0xe8, 0x01, 0x00, 0xbd, 0x87, 0x20, 0xf0, 0x98, 0x6c, 0x00, 0x00, - 0x14, 0x87, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0x40, 0x02, 0x00, 0x0c, - 0x7e, 0x89, 0x01, 0x00, 0x14, 0x87, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xbd, 0x87, 0x00, 0x49, 0x81, 0xb0, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, - 0x80, 0xb0, 0x01, 0x00, 0x04, 0x87, 0x22, 0x43, 0x21, 0x6f, 0x00, 0x00, - 0x13, 0x80, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, 0x05, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x1a, 0x80, 0x00, 0x40, 0x80, 0xdc, 0x01, 0x00, - 0x05, 0x87, 0xa2, 0x5e, 0x0b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x08, 0xb1, 0x01, 0x00, 0x07, 0x87, 0x9f, 0x85, 0x80, 0x32, 0x00, 0x00, - 0x0b, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xec, 0x82, 0x22, 0x40, - 0x57, 0x7d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, 0x57, 0x99, 0x01, 0x00, - 0x0b, 0x87, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x93, 0x93, 0x01, 0x00, 0xdd, 0x82, 0x1a, 0x5b, 0x69, 0x93, 0x00, 0x00, - 0x04, 0x00, 0x00, 0xcb, 0x81, 0xc8, 0x01, 0x00, 0x11, 0x87, 0x22, 0x40, - 0xf2, 0x7f, 0x00, 0x00, 0xc4, 0x80, 0x00, 0x6f, 0x97, 0x33, 0x01, 0x00, - 0x13, 0x87, 0x22, 0x40, 0x73, 0x7d, 0x00, 0x00, 0xde, 0x80, 0x00, 0x41, - 0x8b, 0xb3, 0x00, 0x00, 0x0e, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x1b, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x1b, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x18, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x2f, 0x92, 0x22, 0x02, - 0x80, 0x32, 0x00, 0x00, 0x1c, 0x87, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0x2f, 0x92, 0x1a, 0x02, - 0x68, 0x97, 0x00, 0x00, 0x26, 0x87, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x26, 0x87, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x23, 0x87, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x39, 0x92, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, 0x27, 0x87, 0x42, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x39, 0x92, 0x1a, 0x02, 0x68, 0x97, 0x00, 0x00, 0x31, 0x87, 0x9c, 0x0f, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0x31, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x2e, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xf9, 0x82, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, - 0x32, 0x87, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00, - 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa6, - 0x56, 0xb1, 0x01, 0x00, 0x56, 0x95, 0x2f, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x82, 0x87, 0xa2, 0x40, 0xe7, 0x6d, 0x00, 0x00, 0xb8, 0x94, 0x29, 0x41, - 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x0e, 0xb0, 0x01, 0x00, 0x29, 0x00, 0x00, 0x40, - 0x0d, 0x98, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x12, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, - 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x10, 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x34, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, 0x00, 0xb5, 0x00, 0x0d, - 0x42, 0xc9, 0x01, 0x00, 0x66, 0x87, 0x22, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x47, 0x87, 0x60, 0x40, 0x81, 0x32, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07, - 0x84, 0x89, 0x01, 0x00, 0x4e, 0x87, 0x05, 0xc2, 0x24, 0x30, 0x00, 0x00, - 0x58, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x83, 0x87, 0x70, 0xf0, 0x18, 0x30, 0x01, 0x00, - 0x66, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x70, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x5d, 0x87, 0xa0, 0x48, 0x23, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x1a, - 0x42, 0xc9, 0x01, 0x00, 0x57, 0x87, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x1a, - 0x62, 0xdd, 0x01, 0x00, 0x54, 0x87, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x20, 0x98, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x83, 0x87, 0x00, 0xf8, 0x18, 0x30, 0x01, 0x00, - 0x58, 0x87, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, 0xff, 0xff, 0x00, 0x10, - 0x34, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x34, 0x94, 0x01, 0x00, - 0x20, 0x18, 0x00, 0x40, 0x11, 0x98, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x1a, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00, - 0x61, 0x87, 0xa8, 0x09, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x23, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x11, 0xc0, 0x01, 0x00, 0x72, 0x87, 0x22, 0x41, - 0x0d, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00, - 0x6e, 0x87, 0xa0, 0xaa, 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x0f, 0xb0, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, 0x12, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa7, 0x13, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x1b, 0xb0, 0x01, 0x00, 0x45, 0x87, 0x00, 0x41, 0x17, 0xb0, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x09, 0x12, 0xc8, 0x01, 0x00, 0x45, 0x87, 0x83, 0x41, - 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x17, 0xb0, 0x01, 0x00, - 0x45, 0x87, 0x00, 0x41, 0x1b, 0xc0, 0x00, 0x00, 0x7d, 0x87, 0x23, 0x40, - 0x23, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x35, 0xd0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x1a, 0x42, 0xc9, 0x01, 0x00, 0x7a, 0x87, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x1a, 0x62, 0xdd, 0x01, 0x00, 0x77, 0x87, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x20, 0x98, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x83, 0x87, 0x00, 0xf8, - 0x18, 0x30, 0x01, 0x00, 0x7b, 0x87, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x0f, 0xc0, 0x01, 0x00, 0x80, 0x87, 0xa0, 0xaa, - 0x0f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0f, 0xb0, 0x01, 0x00, - 0xb8, 0x94, 0x20, 0x07, 0xe4, 0xb1, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40, 0x0f, 0xb0, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x0c, 0x80, 0xd8, 0x01, 0x00, 0xc0, 0x02, 0x00, 0x0c, - 0x7e, 0x89, 0x01, 0x00, 0x95, 0x87, 0x26, 0x54, 0x61, 0x31, 0x00, 0x00, - 0x8b, 0x87, 0x87, 0x0c, 0x80, 0x32, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x40, - 0x62, 0x99, 0x01, 0x00, 0x8b, 0x87, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x8b, 0x87, 0xa2, 0x54, 0x77, 0x7d, 0x00, 0x00, 0x87, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x90, 0x87, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00, - 0x0d, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x01, 0x00, - 0x8c, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x95, 0x87, 0x22, 0x49, - 0x19, 0x7c, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, - 0x77, 0x7d, 0x01, 0x00, 0x90, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x40, 0x62, 0x99, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x54, 0x77, 0x7d, 0x01, 0x00, - 0x95, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x94, 0x2f, 0x55, - 0xf1, 0x93, 0x01, 0x00, 0x00, 0x40, 0x00, 0xa6, 0x56, 0xb1, 0x01, 0x00, - 0xf9, 0x82, 0xa2, 0x41, 0xe5, 0x51, 0x00, 0x00, 0x64, 0x00, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x9d, 0x87, 0x44, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xa0, 0x87, 0xa2, 0x93, 0x57, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x57, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x1c, 0xab, 0x27, 0xb3, 0x01, 0x00, - 0xf9, 0x82, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, 0xf9, 0x82, 0x22, 0x51, - 0xfd, 0x7f, 0x00, 0x00, 0xf9, 0x82, 0xa2, 0x41, 0x1d, 0x53, 0x00, 0x00, - 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, 0x38, 0x05, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0xac, 0x87, 0x22, 0x40, - 0xb5, 0x6f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x41, 0xb5, 0x53, 0x01, 0x00, 0xf9, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xfd, 0x83, 0x01, 0x00, - 0x40, 0x16, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x40, 0x05, 0x00, 0x40, - 0x49, 0x31, 0x01, 0x00, 0x1e, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x10, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0xda, - 0x91, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00, 0x60, 0x16, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0x40, 0x82, 0x00, 0x40, 0xb5, 0x33, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0xff, 0xff, 0x00, 0x4a, - 0xb4, 0x8b, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x0a, 0x00, 0x00, 0x48, 0xb2, 0xcb, 0x01, 0x00, 0x10, 0x00, 0x00, 0x4a, - 0xb4, 0xf7, 0x01, 0x00, 0x20, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xf9, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x05, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x20, 0x40, 0xe6, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00, - 0xc3, 0x87, 0x00, 0x4b, 0x10, 0xc9, 0x00, 0x00, 0xe6, 0x8a, 0x00, 0x41, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x1a, 0x8b, 0x00, 0x41, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x4c, 0x8b, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x4c, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x4c, 0x8b, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x4c, 0x8b, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x8b, 0x8b, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb4, 0x8b, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0xb8, 0x8b, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x03, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xc4, 0x8b, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xc3, 0x8b, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x73, 0x8c, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x73, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x73, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x93, 0x8c, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xb1, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb1, 0x8c, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xb1, 0x8c, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xd9, 0x8c, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0xea, 0x8c, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xea, 0x8c, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xec, 0x8c, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0xec, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0xec, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xec, 0x8c, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xf4, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x05, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0xf5, 0x8c, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x05, 0x8d, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x06, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0xfc, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, - 0x71, 0x8c, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x71, 0x8c, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x71, 0x8c, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x41, - 0x09, 0xb0, 0x00, 0x00, 0x07, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x07, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x07, 0x8d, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x0e, 0x8d, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x10, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x1c, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x7b, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb8, 0x8b, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x83, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0xb8, 0x8b, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x94, 0x8d, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0xe4, 0x8a, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x88, 0x8b, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x7f, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0xb8, 0x8b, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x8f, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x8f, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x08, 0xb0, 0x01, 0x00, 0x06, 0x00, 0x20, 0x47, - 0xe6, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x47, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x96, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x96, 0xc0, 0x01, 0x00, - 0x83, 0x88, 0x00, 0x4b, 0x10, 0xc9, 0x00, 0x00, 0xac, 0x8d, 0x00, 0x49, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe5, 0x8d, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xeb, 0x8d, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xf9, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x1a, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x15, 0x8e, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x1d, 0x8e, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x75, 0x8e, 0x00, 0x44, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x74, 0x8e, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xee, 0x8d, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0xee, 0x8d, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0xee, 0x8d, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x49, 0x09, 0xb0, 0x00, 0x00, - 0xee, 0x8d, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x4b, - 0x09, 0xb0, 0x00, 0x00, 0xee, 0x8d, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, - 0xee, 0x8d, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xd4, 0x8e, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xd4, 0x8e, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xec, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe0, 0x8e, 0x00, 0x45, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x41, 0x91, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x1a, 0x8e, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0xf9, 0x8d, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x15, 0x8e, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x75, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0x1d, 0x8e, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x74, 0x8e, 0x00, 0x4c, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x09, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x09, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x09, 0x8f, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xee, 0x8d, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, 0x2c, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x14, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x14, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x14, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x2c, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x14, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x3b, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x3b, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x9d, 0x8f, 0x00, 0x40, 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xae, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x0c, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x0c, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xba, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0xc1, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xc1, 0x8f, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xae, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x0c, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x0c, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0xae, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xd4, 0x8e, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xd4, 0x8e, 0x00, 0x4c, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x2b, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x1f, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x2b, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x1f, 0x8f, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x13, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x1f, 0x8f, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xc3, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x4b, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xc3, 0x8f, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0xc3, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x4c, - 0x09, 0xb0, 0x00, 0x00, 0xc3, 0x8f, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xdd, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xdd, 0x8f, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xd8, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xd8, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xd8, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xfb, 0x90, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xfa, 0x90, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xfb, 0x90, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xfa, 0x90, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xce, 0x8f, 0x00, 0x41, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xda, 0x8f, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xda, 0x8f, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xda, 0x8f, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0xda, 0x8f, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0xda, 0x8f, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xda, 0x8f, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xec, 0x8e, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0xe0, 0x8e, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x8f, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x36, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x36, 0x91, 0x00, 0x44, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x36, 0x91, 0x00, 0x4b, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x36, 0x91, 0x00, 0x45, 0x09, 0xb0, 0x00, 0x00, - 0x36, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x36, 0x91, 0x00, 0x4c, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0xe0, 0x8e, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x41, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xe0, 0x8e, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x41, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x41, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x45, 0x91, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x87, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x45, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x56, 0x91, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x34, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x56, 0x91, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x34, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x67, 0x91, 0x00, 0x43, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x67, 0x91, 0x00, 0x43, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x67, 0x91, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0xf9, 0x8d, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x1a, 0x8e, 0x00, 0x42, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x85, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x1a, 0x8e, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0xf9, 0x8d, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x85, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x87, 0x91, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x87, 0x91, 0x00, 0x4a, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x42, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x42, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x42, 0x91, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x42, 0x91, 0x00, 0x46, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x8d, 0x91, 0x00, 0x42, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x34, 0x91, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x8d, 0x91, 0x00, 0x46, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, - 0x13, 0x8e, 0x00, 0x48, 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x34, 0x91, 0x00, 0x4a, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x1d, 0x8e, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x1d, 0x8e, 0x00, 0x4d, 0x09, 0xb0, 0x00, 0x00, - 0x13, 0x8e, 0x00, 0x47, 0x09, 0xb0, 0x00, 0x00, 0x13, 0x8e, 0x00, 0x48, - 0x09, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, - 0x85, 0xb0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x20, 0x85, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x2e, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0x1f, 0x87, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00, - 0xcf, 0x8a, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x83, 0x94, 0x00, 0x3a, - 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xcf, 0x8a, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x0f, - 0x1e, 0x8c, 0x01, 0x00, 0xee, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xdf, 0x8a, 0x9c, 0x0f, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0xdf, 0x8a, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xdc, 0x8a, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xa3, 0x84, 0x22, 0x02, 0x80, 0x32, 0x00, 0x00, - 0xe0, 0x8a, 0x42, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x68, 0x97, 0x01, 0x00, - 0xa3, 0x84, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x05, 0x00, 0x2e, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0x1f, 0x87, 0x00, 0x04, 0xe6, 0xb1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x40, 0x00, 0x00, 0xa1, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xe0, 0xb1, 0x01, 0x00, 0xc6, 0x95, 0x00, 0x06, 0x07, 0x40, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x07, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x2e, 0x5c, - 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xb1, 0x01, 0x00, - 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x96, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x96, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x96, 0xc0, 0x01, 0x00, 0x00, 0x30, 0x00, 0x4b, - 0x94, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x95, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x96, 0xc0, 0x01, 0x00, 0x5e, 0x01, 0x2e, 0x34, - 0x97, 0x84, 0x01, 0x00, 0x02, 0x00, 0x00, 0x4b, 0xe4, 0xe5, 0x01, 0x00, - 0x64, 0x01, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x86, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x48, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00, - 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x09, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x08, 0x00, 0x2e, 0x40, 0x95, 0xb0, 0x01, 0x00, 0x11, 0x8b, 0x20, 0x4b, - 0x94, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x0e, 0x8b, 0x00, 0x41, 0x95, 0xc0, 0x00, 0x00, 0x10, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x18, 0x8b, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x14, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x83, 0x94, 0x00, 0x40, 0x81, 0x30, 0x01, 0x00, - 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x86, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x88, 0xb0, 0x01, 0x00, 0x1d, 0x8b, 0x44, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x20, 0x8b, 0xa2, 0x4c, 0xfd, 0x7f, 0x00, 0x00, - 0x21, 0x8b, 0x00, 0x4c, 0xfd, 0x93, 0x00, 0x00, 0x22, 0x8b, 0x20, 0xf0, - 0x56, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x56, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x1c, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x70, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x28, 0x8b, 0xa8, 0x44, - 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x46, 0x44, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, - 0xf1, 0x99, 0x01, 0x00, 0x68, 0x01, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, - 0x64, 0x00, 0x00, 0x43, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x62, 0xb1, 0x01, 0x00, - 0x30, 0x8b, 0xa8, 0x44, 0xe0, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, 0x86, 0xe4, 0x01, 0x00, - 0x38, 0x00, 0x2e, 0xa7, 0x87, 0xc0, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x38, 0x8b, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, 0x3b, 0x8b, 0x22, 0x44, - 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x45, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x19, 0x90, 0x01, 0x00, 0x68, 0x01, 0x20, 0xa2, - 0xe4, 0xb1, 0x01, 0x00, 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x3f, 0x8b, 0x23, 0x0b, 0xe5, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x19, 0x90, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x50, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x58, 0x01, 0x00, 0x43, - 0xf0, 0xc9, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x44, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5c, 0x00, 0x2e, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x60, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0x83, 0x94, 0x00, 0x41, - 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x4f, 0x8b, 0xa2, 0x49, 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x53, 0x8b, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00, - 0x86, 0x00, 0x2f, 0x49, 0x19, 0x80, 0x01, 0x00, 0x53, 0x8b, 0xa2, 0xf2, - 0x80, 0x32, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xe7, 0x91, 0x01, 0x00, 0x56, 0x8b, 0xa2, 0x46, - 0x19, 0x7c, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x5a, 0x8b, 0x00, 0x40, 0xe5, 0xb1, 0x00, 0x00, 0xa0, 0x00, 0x2f, 0x46, - 0x19, 0x80, 0x01, 0x00, 0x5a, 0x8b, 0xa2, 0xf2, 0x80, 0x32, 0x00, 0x00, - 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0xe7, 0x91, 0x01, 0x00, 0xa8, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x34, 0x00, 0x2d, 0xf0, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, - 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x10, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfb, 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, - 0x16, 0x88, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, 0x14, 0xf4, 0x01, 0x00, - 0x85, 0x8b, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, 0x6d, 0x8b, 0x22, 0x0a, - 0x16, 0x6c, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, - 0x84, 0x30, 0x00, 0x00, 0x70, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x13, 0xc0, 0x01, 0x00, - 0x6c, 0x8b, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x13, 0xb0, 0x01, 0x00, 0x62, 0x8b, 0x00, 0x41, 0x15, 0xd0, 0x00, 0x00, - 0x85, 0x8b, 0x22, 0x0a, 0x80, 0x32, 0x00, 0x00, 0x58, 0x00, 0x3d, 0x43, - 0x13, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00, 0x70, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x85, 0x8b, 0x22, 0x41, 0x15, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x11, 0xc0, 0x01, 0x00, 0x79, 0x8b, 0xa0, 0x43, - 0x11, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0xb0, 0x01, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0x11, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x36, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x00, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x83, 0xb0, 0x01, 0x00, 0xc2, 0x94, 0x00, 0x47, - 0x61, 0x31, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x2c, 0x92, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x81, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x75, 0x8b, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x37, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x51, - 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x8d, 0x8b, 0x00, 0x48, 0x19, 0x90, 0x00, 0x00, - 0x34, 0x00, 0x2e, 0x41, 0xf5, 0xb1, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x92, 0x8b, 0x22, 0x45, - 0x23, 0x7c, 0x00, 0x00, 0xb0, 0x00, 0x2f, 0xf0, 0x8c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x35, 0x00, 0x2d, 0xf0, 0x8c, 0xb0, 0x01, 0x00, - 0x58, 0x00, 0x3e, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0x97, 0x8b, 0x22, 0x48, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8d, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x68, 0x0a, 0x8c, 0xc0, 0x01, 0x00, 0x38, 0x00, 0x2a, 0x4a, - 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, - 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x38, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x26, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8, - 0x02, 0x30, 0x00, 0x00, 0xa5, 0x8b, 0x23, 0x01, 0x14, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x82, 0xb0, 0x01, 0x00, 0x4c, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00, - 0x44, 0x00, 0x20, 0x40, 0xe0, 0xb1, 0x01, 0x00, 0x48, 0x00, 0x20, 0x41, - 0xe0, 0xb1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0xaa, 0x95, 0x00, 0xf0, 0x24, 0x30, 0x01, 0x00, 0xae, 0x8b, 0xa2, 0x44, - 0x81, 0x6c, 0x00, 0x00, 0xac, 0x8b, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x57, 0x93, 0x00, 0x40, 0x3b, 0x30, 0x01, 0x00, 0xd2, 0x8b, 0xa2, 0x08, - 0x3c, 0x30, 0x00, 0x00, 0xae, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x94, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd2, 0x8b, 0xa2, 0x08, - 0x3c, 0x30, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, - 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, 0x4e, 0x00, 0x20, 0x01, - 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, - 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x36, 0x93, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x8d, 0x8b, 0x22, 0x4a, - 0x80, 0x32, 0x00, 0x00, 0xba, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x36, 0x93, 0x00, 0xf3, - 0x94, 0x30, 0x01, 0x00, 0x58, 0x00, 0x3e, 0x43, 0x97, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1b, 0xf0, 0xb1, 0x01, 0x00, 0x1f, 0x00, 0x60, 0x00, - 0x00, 0x8c, 0x01, 0x00, 0xe4, 0x8a, 0x85, 0x11, 0x80, 0x32, 0x00, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0xf0, - 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x8c, 0xc0, 0x01, 0x00, - 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xc4, 0x8b, 0x00, 0x49, 0x19, 0x80, 0x00, 0x00, - 0xc9, 0x8b, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x57, 0x93, 0x00, 0x40, - 0x3b, 0x30, 0x01, 0x00, 0xcd, 0x8b, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00, - 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x94, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xcd, 0x8b, 0xa2, 0x08, 0x3c, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x5f, - 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x50, 0x00, 0x2d, 0x10, 0x32, 0xb0, 0x01, 0x00, 0x54, 0x00, 0x2d, 0xf0, - 0x38, 0xb0, 0x01, 0x00, 0x4e, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, - 0x40, 0x00, 0x2d, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x14, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, 0x8c, 0xc8, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x46, 0x44, 0xc9, 0x01, 0x00, 0x68, 0x01, 0x2d, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x68, 0xf2, 0x80, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x37, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x36, 0xd0, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0x40, - 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x52, 0x81, 0xd0, 0x01, 0x00, 0x89, 0x94, 0x00, 0x40, - 0xe4, 0x31, 0x01, 0x00, 0x20, 0x00, 0x00, 0x46, 0x62, 0xdd, 0x01, 0x00, - 0xde, 0x8b, 0xa8, 0x40, 0x23, 0x30, 0x00, 0x00, 0xce, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd6, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xec, 0x8b, 0x82, 0x41, 0x23, 0x40, 0x00, 0x00, 0x20, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0xe9, 0x8b, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xe6, 0x8b, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x44, 0xc9, 0x01, 0x00, 0xf4, 0x8b, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xf0, 0x8b, 0xa3, 0x01, 0x0c, 0x6c, 0x00, 0x00, 0xf1, 0x8b, 0x00, 0x06, - 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0xb0, 0x01, 0x00, - 0xf3, 0x8b, 0x20, 0x02, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x04, 0xb0, 0x01, 0x00, 0xf7, 0x8b, 0x00, 0x02, 0xe0, 0xb1, 0x00, 0x00, - 0xf6, 0x8b, 0xa3, 0x01, 0x0c, 0x6c, 0x00, 0x00, 0xf7, 0x8b, 0x00, 0x06, - 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x68, 0x02, 0x16, 0x94, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, - 0x16, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x68, 0x08, 0x3e, 0x96, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1c, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, - 0xfc, 0x8b, 0xa8, 0x13, 0xe0, 0x31, 0x00, 0x00, 0x33, 0x8c, 0x22, 0x02, - 0x14, 0x50, 0x00, 0x00, 0x44, 0x00, 0x2d, 0x02, 0x0c, 0xd0, 0x01, 0x00, - 0x23, 0x8c, 0xa2, 0x02, 0x02, 0x50, 0x00, 0x00, 0x0a, 0x8c, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x09, 0x8c, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x05, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x44, 0x00, 0x2d, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x48, 0x00, 0x2d, 0xf0, - 0x38, 0xb0, 0x01, 0x00, 0x4c, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, - 0x38, 0x00, 0x2f, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x24, 0x8c, 0x22, 0x01, - 0x14, 0x6c, 0x00, 0x00, 0x17, 0x8c, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x46, 0x1f, 0x80, 0x01, 0x00, 0x20, 0x00, 0x2d, 0x03, - 0x48, 0xb1, 0x01, 0x00, 0x16, 0x8c, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x13, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x38, 0x00, 0x2f, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, - 0x38, 0x00, 0x2d, 0xf0, 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0xe1, 0xc1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x22, 0x4a, 0xf1, 0xb1, 0x01, 0x00, 0x44, 0x00, 0x00, 0x05, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, - 0x20, 0x8c, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, 0x24, 0x8c, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38, 0xc0, 0x01, 0x00, - 0x2e, 0x8c, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x33, 0xc0, 0x01, 0x00, 0x2c, 0x8c, 0xa2, 0x02, 0x36, 0x6c, 0x00, 0x00, - 0x04, 0x00, 0x8f, 0x0d, 0x42, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0xf8, - 0x10, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x11, 0x80, 0x01, 0x00, - 0xf0, 0x07, 0x00, 0x40, 0x37, 0x98, 0x01, 0x00, 0xe2, 0x8b, 0x00, 0xa1, - 0x1a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, - 0xe2, 0x8b, 0x00, 0x02, 0x36, 0xd0, 0x00, 0x00, 0x50, 0x00, 0x20, 0x1c, - 0xe0, 0xb1, 0x01, 0x00, 0x54, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, - 0x4e, 0x00, 0x20, 0x01, 0xe4, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x0a, - 0xe0, 0xb1, 0x01, 0x00, 0x38, 0x8c, 0x00, 0x5f, 0x01, 0xb0, 0x00, 0x00, - 0x37, 0x00, 0x2d, 0x46, 0x01, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xf3, - 0x80, 0xf4, 0x01, 0x00, 0x37, 0x8c, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x01, 0xb0, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, - 0x3e, 0x8c, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, - 0x3b, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xd3, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x45, 0x8c, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x42, 0x8c, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x60, 0x01, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x17, 0xf0, 0x01, 0x00, - 0x4a, 0x8c, 0x90, 0xf2, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, - 0x32, 0x00, 0x00, 0xa6, 0x2a, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x2a, 0x94, 0x01, 0x00, 0x4d, 0x8c, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00, - 0x00, 0xd0, 0x00, 0x1e, 0x62, 0xdd, 0x01, 0x00, 0x52, 0x8c, 0x28, 0x40, - 0x05, 0x30, 0x00, 0x00, 0x4e, 0x8c, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00, - 0x55, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x62, 0xb1, 0x01, 0x00, 0x5e, 0x8c, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x52, 0x8c, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, - 0x92, 0xb0, 0x01, 0x00, 0x5b, 0x8c, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x99, 0x92, 0x00, 0xf8, - 0x00, 0x30, 0x01, 0x00, 0x58, 0x8c, 0xa2, 0x41, 0x3b, 0x50, 0x00, 0x00, - 0x5f, 0x8c, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00, 0xff, 0x07, 0x00, 0x1e, - 0x00, 0x8c, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x5f, 0x8c, 0x00, 0x49, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x47, - 0x19, 0x80, 0x01, 0x00, 0x62, 0x8c, 0x22, 0x5f, 0x01, 0x6c, 0x00, 0x00, - 0xd4, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xbf, 0x87, 0x00, 0x00, - 0x80, 0xb0, 0x00, 0x00, 0x69, 0x8c, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x20, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x69, 0x8c, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x66, 0x8c, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x69, 0x8c, 0x40, 0x05, 0x48, 0x31, 0x00, 0x00, 0xff, 0xff, 0x00, 0x07, - 0x94, 0x89, 0x01, 0x00, 0x6f, 0x8c, 0x85, 0xca, 0x94, 0x30, 0x00, 0x00, - 0xd4, 0x95, 0x18, 0x5c, 0x1f, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x0f, - 0x1e, 0x8c, 0x01, 0x00, 0xe0, 0x86, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xf4, 0x94, 0x18, 0x00, 0x80, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x47, - 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x19, 0x80, 0x01, 0x00, - 0xe4, 0x8a, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00, 0x94, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x76, 0x8c, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x89, 0x94, 0x00, 0x40, - 0x0d, 0x30, 0x01, 0x00, 0x9c, 0x01, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0xff, 0xff, 0x00, 0x0b, 0x98, 0x88, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x50, - 0x17, 0xf0, 0x01, 0x00, 0x7c, 0x8c, 0x90, 0x4c, 0x16, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x7e, 0x8c, 0x22, 0x43, - 0xe7, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x66, 0x20, 0x17, 0xa4, 0x01, 0x00, 0x68, 0x01, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x5c, 0x01, 0x2e, 0xf2, 0x80, 0xb0, 0x01, 0x00, - 0x02, 0x00, 0x62, 0x40, 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, - 0x81, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x40, 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0xf0, 0xb1, 0x01, 0x00, 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x88, 0x8c, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x8c, 0x8c, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x50, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0x92, 0x8c, 0x28, 0x40, - 0x05, 0x30, 0x00, 0x00, 0x8d, 0x8c, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00, - 0x99, 0x92, 0x1d, 0x08, 0x00, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xe4, 0x8a, 0x1d, 0x47, 0x19, 0x80, 0x00, 0x00, - 0x35, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, - 0x84, 0xc8, 0x01, 0x00, 0x97, 0x8c, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xa8, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00, - 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00, 0xa2, 0x8c, 0xa2, 0x41, - 0x9e, 0x06, 0x00, 0x00, 0xe4, 0x8a, 0x22, 0x44, 0x83, 0x70, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, - 0xe7, 0xe1, 0x01, 0x00, 0xe4, 0x8a, 0x1f, 0xf0, 0x24, 0x6c, 0x00, 0x00, - 0xd4, 0x95, 0x00, 0x48, 0x81, 0x30, 0x01, 0x00, 0xbf, 0x87, 0x23, 0x41, - 0x83, 0x6c, 0x00, 0x00, 0xbf, 0x87, 0x00, 0x47, 0x81, 0xb0, 0x00, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0x85, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x36, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, - 0x28, 0x00, 0x00, 0x40, 0x83, 0x98, 0x01, 0x00, 0xc2, 0x94, 0x00, 0x47, - 0x61, 0x31, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x03, 0x48, 0xb1, 0x01, 0x00, 0x08, 0x00, 0x2d, 0xf0, - 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8e, 0xb0, 0x01, 0x00, - 0x90, 0x00, 0x2d, 0xf0, 0x14, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x93, 0x8b, 0xa2, 0x40, 0x8f, 0x7c, 0x00, 0x00, - 0xb0, 0x8c, 0x22, 0x47, 0x8f, 0x7c, 0x00, 0x00, 0x93, 0x8b, 0x00, 0x48, - 0x19, 0x90, 0x00, 0x00, 0x1f, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x36, 0x00, 0x2d, 0x5d, 0x05, 0xb4, 0x01, 0x00, 0x37, 0x00, 0x2d, 0xf3, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x8e, 0xb0, 0x01, 0x00, - 0x5c, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0, - 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x24, 0xb0, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x86, 0xdc, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x9b, 0x91, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00, - 0x36, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0xbe, 0x8c, 0xa2, 0x50, - 0x8f, 0x50, 0x00, 0x00, 0x34, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x63, 0x41, - 0x81, 0xc0, 0x01, 0x00, 0xc1, 0x8c, 0xa0, 0x43, 0x81, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x40, 0x81, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x20, 0x47, - 0xe6, 0xb1, 0x01, 0x00, 0xe4, 0x8a, 0x22, 0x47, 0x80, 0x32, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x47, 0x0c, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x8f, 0x84, 0x01, 0x00, 0xd6, 0x8c, 0x22, 0x47, 0x0c, 0x6c, 0x00, 0x00, - 0x58, 0x00, 0x3d, 0x43, 0x81, 0xe0, 0x01, 0x00, 0xd6, 0x8c, 0x1f, 0xf0, - 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xcf, 0x8c, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xcc, 0x8c, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xcf, 0x8c, 0x42, 0x40, 0x05, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x93, 0x93, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x5d, 0x69, 0x93, 0x01, 0x00, - 0xd4, 0x8c, 0x23, 0x41, 0x0d, 0x6c, 0x00, 0x00, 0xb1, 0x8c, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0xd4, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, - 0xbf, 0x87, 0x00, 0x48, 0x81, 0xb0, 0x00, 0x00, 0xe4, 0x8a, 0x22, 0x40, - 0x8f, 0x6c, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, - 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x84, 0xb0, 0x01, 0x00, - 0xa6, 0x00, 0x2d, 0x49, 0x19, 0x90, 0x01, 0x00, 0x02, 0x00, 0x00, 0xf2, - 0x80, 0xf4, 0x01, 0x00, 0xb8, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x82, 0xf8, 0x01, 0x00, 0x19, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, - 0xe5, 0x8c, 0xa0, 0x40, 0x82, 0x6c, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x40, - 0x81, 0x98, 0x01, 0x00, 0xe5, 0x8c, 0xa3, 0x40, 0x82, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x80, 0xb0, 0x01, 0x00, 0xe7, 0x8c, 0x20, 0x4c, - 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xc0, 0x01, 0x00, - 0x86, 0x00, 0x20, 0x40, 0xe4, 0xb1, 0x01, 0x00, 0xa2, 0x00, 0x20, 0x42, - 0xe6, 0xb1, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x83, 0x94, 0x00, 0x50, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf0, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0xc6, 0x95, 0x00, 0x40, 0x87, 0x30, 0x01, 0x00, - 0xb0, 0x00, 0x2f, 0x5c, 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x60, 0xf0, - 0x80, 0xc0, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, - 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xe4, 0x8a, 0x22, 0x46, 0x19, 0x7c, 0x00, 0x00, - 0xa0, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2, - 0x96, 0xcc, 0x01, 0x00, 0xe4, 0x8a, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xf4, 0x94, 0x00, 0x4a, 0x81, 0x30, 0x01, 0x00, 0xc9, 0x94, 0x00, 0x46, - 0x95, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xe4, 0x8a, 0x22, 0x49, 0x19, 0x7c, 0x00, 0x00, 0x86, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0xf2, 0x80, 0xcc, 0x01, 0x00, - 0xe4, 0x8a, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x4a, - 0x81, 0x30, 0x01, 0x00, 0xc9, 0x94, 0x00, 0x47, 0x95, 0x30, 0x01, 0x00, - 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2c, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, - 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x62, 0xf2, 0x80, 0xc8, 0x01, 0x00, 0x0b, 0x8d, 0x90, 0x40, - 0x80, 0x32, 0x00, 0x00, 0xff, 0xff, 0x62, 0x40, 0x81, 0x98, 0x01, 0x00, - 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xe4, 0x8a, 0x22, 0x40, - 0xe5, 0x6d, 0x00, 0x00, 0xe4, 0x8a, 0x00, 0x41, 0xe5, 0xc1, 0x00, 0x00, - 0x83, 0x94, 0x00, 0x4d, 0x81, 0x30, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf0, 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x8d, 0xb0, 0x01, 0x00, 0xc6, 0x95, 0x00, 0x40, 0x87, 0x30, 0x01, 0x00, - 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x1b, 0x8d, 0x80, 0xf3, - 0x96, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0x81, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00, 0xe4, 0x8a, 0x00, 0x5c, - 0x1f, 0x90, 0x00, 0x00, 0x34, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x40, 0xf5, 0x99, 0x01, 0x00, 0x00, 0x11, 0x00, 0x40, - 0xe5, 0x99, 0x01, 0x00, 0x94, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x30, 0x8d, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x51, 0x83, 0xd0, 0x01, 0x00, 0x34, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x84, 0xcc, 0x01, 0x00, - 0x28, 0x8d, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x63, 0x42, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x2a, 0x8d, 0x37, 0x5c, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00, - 0x2b, 0x8d, 0xa8, 0x4b, 0x19, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x62, 0xb1, 0x01, 0x00, 0x2d, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x14, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, - 0xac, 0x00, 0x2d, 0xf0, 0x30, 0xb0, 0x01, 0x00, 0x35, 0x00, 0x2d, 0xf0, - 0x28, 0xb0, 0x01, 0x00, 0x58, 0x00, 0x3e, 0x43, 0xe7, 0xe1, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x18, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0xe0, 0xb1, 0x01, 0x00, 0x38, 0x00, 0x20, 0x00, 0xe0, 0xb1, 0x01, 0x00, - 0x3c, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x20, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x2b, 0xb0, 0x01, 0x00, - 0xd8, 0x94, 0x00, 0x40, 0x0d, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x16, 0xc0, 0x01, 0x00, 0x3f, 0x8d, 0xa0, 0x14, 0x16, 0x44, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x0e, 0x00, 0x00, 0xa2, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf8, 0xb1, 0x01, 0x00, - 0xb0, 0x00, 0x2d, 0x14, 0xf8, 0xb1, 0x01, 0x00, 0x10, 0x50, 0x00, 0x40, - 0x87, 0x98, 0x01, 0x00, 0x48, 0x8d, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x43, 0x86, 0xc8, 0x01, 0x00, 0x00, 0x30, 0x00, 0x0b, - 0x16, 0xc8, 0x01, 0x00, 0x48, 0x8d, 0xa4, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0x01, 0x00, 0x6e, 0x43, - 0x86, 0x98, 0x01, 0x00, 0x0f, 0x95, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00, - 0x4c, 0x8d, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x53, 0x8d, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, - 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00, - 0x52, 0x8d, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x64, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0x90, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x41, - 0x31, 0xc0, 0x01, 0x00, 0xbc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x59, 0x8d, 0x06, 0x0c, 0x80, 0x32, 0x00, 0x00, 0xa0, 0x00, 0x20, 0xf2, - 0xe4, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x09, 0x46, 0x19, 0x10, 0x00, 0x00, - 0x9c, 0x01, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0xff, 0xff, 0x00, 0x0b, - 0x98, 0x88, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x50, 0x17, 0xf0, 0x01, 0x00, - 0x5e, 0x8d, 0x90, 0x4c, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x60, 0x8d, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x66, 0x20, - 0x17, 0xa4, 0x01, 0x00, 0x68, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x5c, 0x01, 0x2e, 0xf2, 0x80, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x62, 0x40, - 0x7e, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57, 0x81, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, 0x03, 0x00, 0x00, 0x40, - 0xf0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf0, 0xb1, 0x01, 0x00, - 0x58, 0x01, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0x6a, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x6e, 0x8d, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00, 0x00, 0x50, 0x00, 0x08, - 0x62, 0xdd, 0x01, 0x00, 0x6f, 0x8d, 0xa8, 0x40, 0x05, 0x30, 0x00, 0x00, - 0x35, 0x00, 0x1d, 0x40, 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, - 0x84, 0xc8, 0x01, 0x00, 0x75, 0x8d, 0xa0, 0x43, 0x85, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00, - 0x8b, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0xe7, 0x91, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x5f, 0x81, 0x30, 0x01, 0x00, - 0xe4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x36, 0x93, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, - 0x1f, 0x8d, 0x22, 0x4a, 0x80, 0x32, 0x00, 0x00, 0xba, 0x8b, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x37, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x36, 0x93, 0x00, 0xf3, 0x94, 0x30, 0x01, 0x00, 0x8a, 0x8b, 0x22, 0x4a, - 0x80, 0x32, 0x00, 0x00, 0xba, 0x8b, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfb, - 0x12, 0xb0, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, 0x90, 0x88, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xf3, 0x0c, 0xf4, 0x01, 0x00, 0xb4, 0x8b, 0x22, 0x06, - 0x90, 0x6c, 0x00, 0x00, 0x5c, 0x00, 0x3d, 0x43, 0x13, 0xe0, 0x01, 0x00, - 0xa8, 0x00, 0x2d, 0xf0, 0x94, 0xb0, 0x01, 0x00, 0x37, 0x00, 0x2f, 0xf0, - 0x24, 0xb0, 0x01, 0x00, 0x36, 0x00, 0x2a, 0x50, 0xe7, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x41, 0x13, 0xc0, 0x01, 0x00, 0x8f, 0x8d, 0xa0, 0x43, - 0x13, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x99, 0x91, 0x00, 0x10, 0x86, 0x30, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x91, 0x8d, 0x42, 0x05, 0x48, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, 0xb4, 0x8b, 0x1a, 0x5d, - 0x69, 0x93, 0x00, 0x00, 0x36, 0x00, 0x2d, 0x10, 0x86, 0xb0, 0x01, 0x00, - 0x5c, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, 0xa8, 0x00, 0x2d, 0xf0, - 0x94, 0xb0, 0x01, 0x00, 0x35, 0x00, 0x2f, 0xf0, 0x24, 0xb0, 0x01, 0x00, - 0x01, 0x00, 0x6b, 0xfb, 0x84, 0xc8, 0x01, 0x00, 0x9c, 0x8d, 0xa0, 0x43, - 0x85, 0x6c, 0x00, 0x00, 0x35, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x01, 0x00, 0x63, 0xf3, - 0x12, 0xc8, 0x01, 0x00, 0x9f, 0x8d, 0xa0, 0x43, 0x13, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x9b, 0x91, 0x00, 0x4a, 0xf0, 0x31, 0x01, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xa2, 0x8d, 0x42, 0x05, - 0x48, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x93, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x1a, 0x5d, 0x69, 0x93, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x11, 0x00, 0x63, 0xf3, 0x82, 0xcc, 0x01, 0x00, - 0x9b, 0x8c, 0x22, 0x41, 0x9e, 0x06, 0x00, 0x00, 0x35, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x58, 0x00, 0x3d, 0x43, 0xe7, 0xe1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x36, 0xb0, 0x01, 0x00, 0xa5, 0x8c, 0x00, 0xf0, - 0x00, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xad, 0x8d, 0x65, 0xf2, 0x12, 0x30, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, - 0x13, 0xf0, 0x01, 0x00, 0xb2, 0x8d, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00, - 0xf5, 0x82, 0x75, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xac, 0x8d, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x75, 0x42, 0x19, 0x90, 0x01, 0x00, 0x75, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0xb4, 0x8d, 0xa8, 0xb1, 0x0c, 0x30, 0x00, 0x00, - 0x1f, 0x94, 0x00, 0x10, 0x94, 0x30, 0x01, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x97, 0xb0, 0x01, 0x00, 0xbe, 0x8d, 0x22, 0x40, 0xe1, 0x6d, 0x00, 0x00, - 0x04, 0x00, 0x02, 0x41, 0x97, 0x40, 0x00, 0x00, 0xbb, 0x8d, 0x00, 0x50, - 0x43, 0xc1, 0x00, 0x00, 0xca, 0x8d, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x62, 0x4b, 0x12, 0x94, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x97, 0xc0, 0x01, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x94, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x4a, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf1, 0xb1, 0x01, 0x00, - 0x5e, 0x01, 0x00, 0x4b, 0xf0, 0xc9, 0x01, 0x00, 0x5e, 0x01, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x4a, 0x62, 0xdd, 0x01, 0x00, 0xc8, 0x8d, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x04, 0x00, 0x00, 0x09, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00, - 0xd4, 0x00, 0x00, 0x05, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0xd0, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, - 0xd4, 0x8d, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, - 0x96, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x75, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, - 0x62, 0xb1, 0x01, 0x00, 0xd8, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xdd, 0x8d, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0xdb, 0x8d, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x97, 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x96, - 0x97, 0xb0, 0x01, 0x00, 0xe3, 0x8d, 0x20, 0x09, 0x96, 0x6c, 0x00, 0x00, - 0xe3, 0x8d, 0x1f, 0x09, 0x96, 0x24, 0x00, 0x00, 0xf5, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0xde, 0x8d, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x83, 0x94, 0x00, 0x57, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xe9, 0x8d, 0x22, 0xf3, 0x80, 0x32, 0x00, 0x00, 0x83, 0x94, 0x00, 0x42, - 0x81, 0x30, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xf4, 0x94, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x42, - 0x19, 0x80, 0x00, 0x00, 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, - 0xf4, 0x94, 0x00, 0x52, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x96, 0x93, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x22, 0x40, - 0x95, 0x6c, 0x00, 0x00, 0xf4, 0x8d, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x41, 0x93, 0x00, 0x52, - 0x95, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7d, 0x95, 0x00, 0x40, - 0x95, 0x30, 0x01, 0x00, 0xff, 0x8d, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x14, 0x87, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, - 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x23, 0x00, 0xa6, - 0x16, 0xb0, 0x01, 0x00, 0x02, 0x8e, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x08, 0x00, 0x0b, 0x16, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2a, 0xc0, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x08, 0x80, 0x30, 0x01, 0x00, - 0x06, 0x8e, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, 0xed, 0x94, 0x00, 0x43, - 0x61, 0x31, 0x01, 0x00, 0xa7, 0x91, 0x00, 0x40, 0x8d, 0x30, 0x01, 0x00, - 0xd4, 0x94, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x0e, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x0b, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x75, 0x94, 0x00, 0x5e, - 0x05, 0x10, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x12, 0x8e, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0xd4, 0x8a, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00, - 0x19, 0x8e, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x3d, 0x80, 0x01, 0x00, - 0x1a, 0x8e, 0x00, 0x42, 0x19, 0x90, 0x00, 0x00, 0x14, 0x00, 0x2d, 0x45, - 0x1f, 0x90, 0x01, 0x00, 0x75, 0x8e, 0x83, 0x1e, 0x80, 0x32, 0x00, 0x00, - 0x75, 0x8e, 0x00, 0x44, 0x19, 0x90, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x2d, 0x8e, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x29, 0x8e, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, - 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x26, 0x8e, 0xa2, 0x41, - 0x19, 0x7c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x41, 0x93, 0x00, 0x15, - 0x94, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x30, 0x8e, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x31, 0x8e, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x5d, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x15, - 0x98, 0xc8, 0x01, 0x00, 0x5d, 0x8e, 0xa0, 0x0b, 0x99, 0x6c, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x10, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x62, 0xb1, 0x01, 0x00, - 0x39, 0x8e, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x15, 0x98, 0xc8, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x0b, - 0x99, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x6a, 0x50, 0x99, 0xc0, 0x01, 0x00, - 0xc0, 0x00, 0x62, 0x01, 0x80, 0xcc, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x2d, 0x00, 0x2d, 0xf0, 0x22, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x80, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x23, 0x80, 0x01, 0x00, 0xd4, 0x00, 0x3f, 0x41, 0xe7, 0xe1, 0x01, 0x00, - 0x0b, 0x00, 0x00, 0x11, 0xe4, 0xf5, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x47, - 0xe7, 0xb5, 0x01, 0x00, 0x4a, 0x8e, 0x23, 0x0b, 0x81, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0xe5, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x03, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x15, 0x02, 0xd0, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x00, - 0x2a, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x4f, 0x8e, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01, - 0x80, 0xce, 0x01, 0x00, 0x5b, 0x8e, 0x26, 0x11, 0x00, 0x30, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x2a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xc0, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x98, 0xd0, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x4c, 0x02, 0x30, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00, 0x62, 0x8e, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x2f, 0x08, 0x80, 0xb0, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x15, 0xf4, 0xc9, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x01, - 0xe4, 0xcd, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x03, 0x98, 0x01, 0x00, - 0xcc, 0x94, 0x00, 0x00, 0x2a, 0x40, 0x01, 0x00, 0x67, 0x8e, 0x22, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x40, 0x13, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x68, 0x8e, 0x00, 0x01, 0xe0, 0xd1, 0x00, 0x00, - 0xa7, 0x91, 0x00, 0x40, 0x8d, 0x30, 0x01, 0x00, 0x80, 0x63, 0x00, 0xa6, - 0x16, 0xb0, 0x01, 0x00, 0xd4, 0x94, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x70, 0x8e, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x6d, 0x8e, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x73, 0x8e, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xcf, 0x8a, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x75, 0x8e, 0x00, 0x4a, - 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xb0, 0x01, 0x00, - 0x24, 0x00, 0x2d, 0x15, 0x10, 0xc0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0, - 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, - 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xe0, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15, - 0x1a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x2a, 0xb0, 0x01, 0x00, 0x34, 0x94, 0x00, 0x40, - 0x35, 0xb0, 0x00, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xb9, 0x8e, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, 0x24, 0x00, 0x20, 0x0b, - 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13, 0xe0, 0xb1, 0x01, 0x00, - 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00, 0x8f, 0x8e, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x8f, 0x8e, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x8b, 0x8e, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x42, 0xc9, 0x01, 0x00, 0xb2, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0xa0, 0x8e, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0xee, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x41, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xad, 0x8e, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x96, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x9c, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xaf, 0x92, 0x00, 0x40, 0x11, 0x30, 0x01, 0x00, 0x9d, 0x8e, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x9f, 0x8e, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0xee, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x3d, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xa3, 0x8e, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xa9, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x92, 0x00, 0x40, - 0x11, 0x30, 0x01, 0x00, 0xaa, 0x8e, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xac, 0x8e, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xae, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xb5, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x92, 0x00, 0x40, - 0x11, 0x30, 0x01, 0x00, 0xb6, 0x8e, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xb8, 0x8e, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0xd4, 0x8a, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x42, 0xc9, 0x01, 0x00, 0xc0, 0x8e, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xbc, 0x8e, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xc4, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x92, 0x00, 0x40, - 0x11, 0x30, 0x01, 0x00, 0xc5, 0x8e, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x08, 0x00, 0x2d, 0x0a, - 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0x14, 0x00, 0x20, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0xca, 0x8e, 0x03, 0x1e, - 0x80, 0x32, 0x00, 0x00, 0xcb, 0x8e, 0x00, 0x41, 0x87, 0xb0, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0xcf, 0x8e, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0xd2, 0x8e, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, - 0xf4, 0x94, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x80, 0x01, 0x00, 0xcf, 0x8a, 0xa2, 0x4a, 0x1f, 0x7c, 0x00, 0x00, - 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0xd8, 0x8e, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, - 0xcc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x84, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x2d, 0x95, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xc4, 0x00, 0x2d, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x61, 0x95, 0x00, 0xf0, 0x84, 0x30, 0x01, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xd4, 0x8a, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xe4, 0x8e, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xec, 0x8e, 0xa2, 0x40, - 0xe5, 0x6d, 0x00, 0x00, 0x83, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x24, 0x00, 0x20, 0x0b, 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x20, 0x13, - 0xe0, 0xb1, 0x01, 0x00, 0x22, 0x00, 0x20, 0x06, 0xe4, 0xb1, 0x01, 0x00, - 0x14, 0x00, 0x20, 0x0a, 0xe0, 0xb1, 0x01, 0x00, 0xd4, 0x8a, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x83, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xfa, 0x8e, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0x99, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x15, 0x98, 0x50, 0x00, 0x00, - 0xfa, 0x8e, 0x20, 0x01, 0x98, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x46, 0x1f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0xf7, 0x8e, 0xa8, 0x00, - 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xac, 0x00, 0x2f, 0x00, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xe0, 0xc1, 0x01, 0x00, 0x14, 0x00, 0x2f, 0x15, 0x10, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x60, 0x01, - 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0x19, 0x90, 0x01, 0x00, - 0x7c, 0x8e, 0x22, 0x09, 0x80, 0x32, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x09, - 0x80, 0x30, 0x01, 0x00, 0x7c, 0x8e, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x43, 0xc1, 0x01, 0x00, 0xb7, 0x93, 0x00, 0xf0, - 0x84, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, - 0x2c, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x42, 0x19, 0x80, 0x00, 0x00, - 0xa9, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0xc9, 0x94, 0x00, 0x48, - 0x95, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x0f, 0x8f, 0xa8, 0x40, - 0x13, 0x30, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x15, 0x8f, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x14, 0x8f, 0x00, 0x40, - 0x13, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xb0, 0x01, 0x00, - 0x08, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x14, 0x00, 0x2d, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf0, 0x84, 0x30, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0x2d, 0x8f, 0x00, 0x09, 0x00, 0xb0, 0x00, 0x00, 0xcf, 0x8a, 0x87, 0x42, - 0x19, 0x10, 0x00, 0x00, 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00, - 0xcf, 0x8a, 0x00, 0x40, 0xe7, 0x91, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x2b, 0x8f, 0x22, 0x47, 0xe7, 0x7d, 0x00, 0x00, - 0x1e, 0x92, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00, 0x2b, 0x8f, 0x22, 0x00, - 0x80, 0x32, 0x00, 0x00, 0x26, 0x8f, 0xa2, 0x40, 0x1f, 0x7c, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2b, 0x8f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00, 0x41, 0x93, 0x00, 0xf2, - 0x02, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x2c, 0x8f, 0x00, 0x40, - 0x01, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x32, 0x8f, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0x31, 0x8f, 0xa2, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x32, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xbc, 0x8f, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x3a, 0x8f, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x37, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xbc, 0x8f, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x40, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x83, 0x94, 0x00, 0x4d, - 0x81, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, - 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x96, 0xb0, 0x01, 0x00, 0x4e, 0x8f, 0x22, 0x42, 0x96, 0x14, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x64, 0x00, 0x68, 0x40, - 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x05, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x4b, 0x8f, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x4f, 0x8f, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x5e, 0x01, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x53, 0x8f, 0x65, 0xf2, 0x12, 0x30, 0x00, 0x00, - 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0x58, 0x8f, 0x22, 0x47, - 0xe7, 0x7d, 0x00, 0x00, 0xf5, 0x82, 0x75, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x52, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, - 0xe7, 0x91, 0x01, 0x00, 0x04, 0x00, 0x75, 0x09, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x97, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x44, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x60, 0x8f, 0xa8, 0x40, - 0xe1, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x99, 0x3f, 0x42, 0x13, 0xf0, 0x01, 0x00, 0x64, 0x8f, 0x65, 0x05, - 0x48, 0x31, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x75, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x6c, 0x8f, 0x22, 0x4b, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0x6a, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x62, 0x00, 0x0b, - 0x16, 0xdc, 0x01, 0x00, 0x1e, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x84, 0x8f, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xcc, 0x93, 0x00, 0x5f, - 0x01, 0x10, 0x01, 0x00, 0x6e, 0x8f, 0x22, 0x40, 0x95, 0x6c, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x76, 0x8f, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x02, 0xb0, 0x01, 0x00, 0x41, 0x93, 0x00, 0x52, - 0x95, 0x30, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x6e, 0x8f, 0x22, 0x41, 0x97, 0x50, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5c, 0x01, 0x80, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x6e, 0x8f, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, - 0xd4, 0x94, 0x00, 0x40, 0x03, 0x30, 0x01, 0x00, 0x17, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x4c, 0x97, 0xf0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0xe1, 0xb1, 0x01, 0x00, - 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0x03, 0x00, 0x00, 0x07, - 0x1a, 0xf4, 0x01, 0x00, 0x07, 0x00, 0x00, 0x07, 0x16, 0x88, 0x01, 0x00, - 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x8e, 0x8f, 0x30, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x81, 0x01, 0x00, - 0x00, 0xb7, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, - 0xe6, 0x81, 0x01, 0x00, 0x10, 0x00, 0x10, 0x0f, 0x94, 0xf4, 0x01, 0x00, - 0x93, 0x04, 0x00, 0x5f, 0x95, 0x04, 0x01, 0x00, 0x22, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x98, 0x8f, 0x22, 0x50, 0xfd, 0x7f, 0x00, 0x00, - 0x96, 0x8f, 0x46, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x41, - 0x31, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x0f, 0xb0, 0x01, 0x00, 0x85, 0x92, 0x00, 0x41, 0x81, 0x30, 0x01, 0x00, - 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xa9, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, - 0xa2, 0x8f, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x62, 0xb1, 0x01, 0x00, 0xa6, 0x8f, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xa3, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x62, 0xb1, 0x01, 0x00, 0xa6, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x14, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x74, 0x00, 0x22, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0xc9, 0x94, 0x00, 0x4a, 0x95, 0x30, 0x01, 0x00, 0xa9, 0x93, 0x00, 0x5c, - 0x1f, 0x10, 0x01, 0x00, 0x40, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2f, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xba, 0x8f, 0x22, 0x47, - 0xe7, 0x7d, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x40, 0xe7, 0x31, 0x01, 0x00, - 0xba, 0x8f, 0x22, 0x00, 0x80, 0x32, 0x00, 0x00, 0xb5, 0x8f, 0xa2, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xba, 0x8f, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x94, 0xb0, 0x01, 0x00, - 0x41, 0x93, 0x00, 0xf2, 0x02, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xc9, 0x94, 0x00, 0x48, 0x95, 0x30, 0x01, 0x00, 0xa9, 0x93, 0x00, 0x5c, - 0x1f, 0x10, 0x01, 0x00, 0xbf, 0x8f, 0x87, 0x42, 0x19, 0x10, 0x00, 0x00, - 0x8b, 0x00, 0x2f, 0x47, 0x19, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe7, 0x91, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x42, 0x81, 0x30, 0x01, 0x00, - 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xa9, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x5c, 0x1f, 0x90, 0x00, 0x00, - 0xba, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, 0x2d, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x61, 0x95, 0x00, 0xf0, - 0x84, 0x30, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xf4, 0x94, 0x00, 0x45, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x22, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, - 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd3, 0x8f, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x83, 0x94, 0x00, 0x47, - 0x80, 0x30, 0x01, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, - 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0xe1, 0x00, 0xa6, 0x84, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x07, 0x84, 0x94, 0x01, 0x00, - 0x75, 0x94, 0x00, 0x5e, 0x05, 0x10, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x99, 0x92, 0x00, 0x41, 0xe7, 0x41, 0x01, 0x00, 0xd4, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x83, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x2c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x1f, 0x0a, - 0x2c, 0x50, 0x00, 0x00, 0x07, 0x95, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00, - 0xea, 0x8f, 0xa2, 0x48, 0x1f, 0x7c, 0x00, 0x00, 0xe8, 0x8f, 0x84, 0x48, - 0x1f, 0x10, 0x00, 0x00, 0xac, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0xea, 0x8f, 0x00, 0x0a, 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x02, 0xb0, 0x01, 0x00, 0xa7, 0x91, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xeb, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, - 0xf8, 0x8f, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, 0xf1, 0x93, 0x00, 0x45, - 0x1f, 0x00, 0x01, 0x00, 0xe3, 0x8f, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0xf4, 0x8f, 0xa8, 0x5c, 0x1f, 0x00, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0xe3, 0x8f, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, - 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xb7, 0x93, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xfe, 0x8f, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x04, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x08, 0x90, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, - 0xf4, 0x94, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x08, 0x90, 0xa2, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00, - 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x16, 0x90, 0x22, 0x4a, - 0x1f, 0x7c, 0x00, 0x00, 0x0e, 0x90, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x12, 0x90, 0x22, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x13, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, - 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x16, - 0xe4, 0xb1, 0x00, 0x00, 0x28, 0x90, 0x22, 0x16, 0x02, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x7d, 0x95, 0x00, 0x40, - 0x95, 0x30, 0x01, 0x00, 0x29, 0x90, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00, - 0xac, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2b, 0x01, - 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6, 0x16, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, 0xcc, 0x94, 0x00, 0x08, - 0x80, 0x30, 0x01, 0x00, 0x21, 0x90, 0x00, 0x5e, 0x17, 0x90, 0x00, 0x00, - 0xed, 0x94, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x22, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xd4, 0x94, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x75, 0x94, 0x00, 0x5e, - 0x05, 0x10, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xd4, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x1f, 0x15, 0x1a, 0x50, 0x00, 0x00, 0x36, 0x90, 0x20, 0x16, - 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x33, 0x90, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x10, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x2a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x2c, 0xd0, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x40, 0x23, 0xb0, 0x01, 0x00, - 0x3d, 0x90, 0x84, 0x45, 0x1f, 0x10, 0x00, 0x00, 0x3e, 0x90, 0x00, 0x0a, - 0xe0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0xb0, 0x01, 0x00, - 0x34, 0x94, 0x00, 0x40, 0x35, 0xb0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x42, 0xc9, 0x01, 0x00, 0x46, 0x90, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x42, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x55, 0x90, 0xa2, 0x02, 0x1a, 0x50, 0x00, 0x00, - 0x56, 0x90, 0x22, 0x40, 0x2d, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, - 0xe0, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x4d, 0x90, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00, - 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00, 0x56, 0x90, 0x00, 0x5c, - 0x11, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xc0, 0x01, 0x00, - 0xaf, 0x92, 0x00, 0x40, 0x1f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x5a, 0x90, 0x23, 0x0d, 0x2c, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00, 0x62, 0x90, 0x22, 0x46, - 0x1f, 0x7c, 0x00, 0x00, 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x62, 0x90, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x5e, 0x90, 0xa8, 0x46, 0x1f, 0x00, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x08, 0x00, 0x2d, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0xb7, 0x93, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x67, 0x90, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x6d, 0x90, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x71, 0x90, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, - 0xf4, 0x94, 0x00, 0x4f, 0x81, 0x30, 0x01, 0x00, 0x71, 0x90, 0xa2, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00, - 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x86, 0x90, 0x22, 0x4a, - 0x1f, 0x7c, 0x00, 0x00, 0x77, 0x90, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x82, 0x90, 0x22, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0x7b, 0x90, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xa5, 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x85, 0xd0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00, - 0x7f, 0x90, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, - 0x11, 0x90, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00, - 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x83, 0x90, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, 0x32, 0x00, 0x2a, 0x15, - 0xe4, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x16, 0xe4, 0xb1, 0x00, 0x00, - 0x89, 0x90, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xd6, 0x90, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x96, 0x90, 0x22, 0x47, - 0x1f, 0x7c, 0x00, 0x00, 0x93, 0x90, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x8e, 0x90, 0xa2, 0xf3, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x85, 0xd0, 0x01, 0x00, - 0xd4, 0x00, 0x3e, 0x41, 0x85, 0xe0, 0x01, 0x00, 0x92, 0x90, 0x22, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x11, 0x90, 0x01, 0x00, - 0x0b, 0x00, 0x00, 0x08, 0xe4, 0xf5, 0x01, 0x00, 0x58, 0x01, 0x2d, 0x00, - 0x2a, 0xd0, 0x01, 0x00, 0x60, 0x01, 0x2d, 0xf0, 0x10, 0xb0, 0x01, 0x00, - 0x2d, 0x8e, 0x00, 0xf0, 0x2c, 0xb0, 0x00, 0x00, 0x7d, 0x95, 0x00, 0x41, - 0x95, 0x30, 0x01, 0x00, 0x9d, 0x90, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x97, 0xb0, 0x01, 0x00, 0x9b, 0x90, 0x23, 0x0d, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, - 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0xd6, 0x90, 0x00, 0x05, - 0x48, 0xb1, 0x00, 0x00, 0xac, 0x00, 0x2f, 0x01, 0x14, 0xb0, 0x01, 0x00, - 0xb0, 0x00, 0x2b, 0x01, 0xe0, 0xc1, 0x01, 0x00, 0x00, 0x2b, 0x00, 0xa6, - 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0xd1, 0x01, 0x00, - 0xad, 0x90, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0xa6, 0x90, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0xf0, - 0x22, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x23, 0x80, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x84, 0xb0, 0x01, 0x00, 0xb0, 0x90, 0x23, 0x0d, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x80, 0xb0, 0x01, 0x00, 0xb5, 0x90, 0x22, 0x40, - 0x1b, 0x6c, 0x00, 0x00, 0xcc, 0x94, 0x00, 0x01, 0x84, 0x50, 0x01, 0x00, - 0xbd, 0x90, 0x22, 0x40, 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x80, 0xc0, 0x01, 0x00, 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4f, 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xf0, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x40, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00, - 0xbb, 0x90, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00, 0xcc, 0x90, 0x00, 0x5e, - 0x17, 0x90, 0x00, 0x00, 0xc0, 0x90, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x02, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x84, 0xd0, 0x01, 0x00, 0xc5, 0x90, 0x22, 0x40, 0x1b, 0x6c, 0x00, 0x00, - 0xed, 0x94, 0x00, 0x43, 0x61, 0x31, 0x01, 0x00, 0xcc, 0x90, 0x22, 0x40, - 0x85, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0xc0, 0x01, 0x00, - 0x10, 0x80, 0x00, 0x10, 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x43, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x09, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, - 0xf0, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa1, 0x62, 0xdd, 0x01, 0x00, - 0xca, 0x90, 0xa8, 0x11, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0xcd, 0x90, 0xa8, 0x0a, 0x02, 0x30, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x99, 0x92, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, - 0xd4, 0x90, 0x23, 0x0d, 0x02, 0x6c, 0x00, 0x00, 0xff, 0x07, 0x00, 0x11, - 0x00, 0x8c, 0x01, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xd4, 0x94, 0x00, 0x07, 0x16, 0x14, 0x01, 0x00, 0x75, 0x94, 0x00, 0x5e, - 0x05, 0x10, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x8e, 0xb0, 0x01, 0x00, 0x80, 0x93, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x41, - 0x87, 0x30, 0x01, 0x00, 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0xe7, 0x90, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0xe3, 0x90, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xe9, 0x90, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x1a, 0xd0, 0x01, 0x00, 0xef, 0x90, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x7d, 0x95, 0x00, 0x40, 0x95, 0x30, 0x01, 0x00, 0xf7, 0x90, 0x22, 0x08, - 0x80, 0x32, 0x00, 0x00, 0x1a, 0x90, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00, - 0x7d, 0x95, 0x00, 0x41, 0x95, 0x30, 0x01, 0x00, 0xf2, 0x90, 0x22, 0x08, - 0x80, 0x32, 0x00, 0x00, 0x9d, 0x90, 0x00, 0x00, 0x2a, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x97, 0xb0, 0x01, 0x00, 0xf5, 0x90, 0x23, 0x0d, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x97, 0xc0, 0x01, 0x00, - 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, - 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xfb, 0x90, 0x00, 0x4a, 0x1f, 0x90, 0x00, 0x00, - 0xc1, 0x92, 0x00, 0x00, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, - 0x10, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x07, 0x95, 0x00, 0x06, 0x04, 0x30, 0x01, 0x00, 0x04, 0x91, 0xa2, 0x44, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x1b, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x2c, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x02, 0xb0, 0x01, 0x00, 0xa7, 0x91, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x19, 0x42, 0xc9, 0x01, 0x00, 0x0b, 0x91, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x07, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x10, 0xc0, 0x01, 0x00, 0x14, 0x91, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, - 0xf1, 0x93, 0x00, 0x45, 0x1f, 0x00, 0x01, 0x00, 0xfd, 0x90, 0x22, 0x5c, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x10, 0x91, 0xa8, 0x5c, - 0x1f, 0x00, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0xfd, 0x90, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x08, 0x00, 0x2d, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, 0xb7, 0x93, 0x00, 0x41, - 0x87, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x19, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x1f, 0x91, 0x22, 0x09, - 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, 0x13, 0x30, 0x01, 0x00, - 0x22, 0x91, 0x22, 0x44, 0x19, 0x7c, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x4f, - 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x80, 0x01, 0x00, - 0xff, 0x07, 0x00, 0x08, 0x00, 0x8c, 0x01, 0x00, 0x30, 0x91, 0x22, 0x4a, - 0x1f, 0x7c, 0x00, 0x00, 0x28, 0x91, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x2d, 0x00, 0x2d, 0x08, 0x2a, 0xb0, 0x01, 0x00, 0x2c, 0x91, 0x22, 0x42, - 0x19, 0x7c, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2d, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x96, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x2a, 0xd0, 0x01, 0x00, - 0x32, 0x00, 0x2a, 0x15, 0xe4, 0xb1, 0x01, 0x00, 0xcf, 0x8a, 0x00, 0x16, - 0xe4, 0xb1, 0x00, 0x00, 0x17, 0x90, 0xa2, 0x16, 0x02, 0x30, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2f, 0x00, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xd4, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xc1, 0x92, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00, 0x2b, 0x90, 0x00, 0x10, - 0x32, 0xb0, 0x00, 0x00, 0x8a, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x3a, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x3d, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x41, 0x93, 0x00, 0x15, 0x94, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, - 0x02, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x3f, 0x91, 0x22, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x83, 0x94, 0x00, 0x3a, - 0x81, 0x30, 0x01, 0x00, 0xf4, 0x94, 0x00, 0x45, 0x81, 0x30, 0x01, 0x00, - 0xcf, 0x8a, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xec, 0x8e, 0x00, 0x45, - 0x1f, 0x90, 0x00, 0x00, 0x83, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2b, 0x90, 0x00, 0x01, - 0x2c, 0xb0, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x51, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, - 0x04, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x4a, 0x91, 0x37, 0x5c, - 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00, - 0x4e, 0x91, 0x28, 0x40, 0x81, 0x32, 0x00, 0x00, 0x4b, 0x91, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, - 0x4e, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x14, 0x87, 0x17, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08, 0xe0, 0xb1, 0x01, 0x00, - 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00, 0x83, 0x93, 0x00, 0x47, - 0x1f, 0x10, 0x01, 0x00, 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2b, 0x90, 0x00, 0x01, 0x2c, 0xb0, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x47, - 0x1f, 0x10, 0x01, 0x00, 0x63, 0x91, 0xa2, 0x08, 0x80, 0x32, 0x00, 0x00, - 0x5f, 0x91, 0xa2, 0x42, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, - 0x04, 0xdc, 0x01, 0x00, 0xa0, 0x98, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, - 0x30, 0x05, 0x00, 0x41, 0x89, 0x30, 0x01, 0x00, 0x41, 0x93, 0x00, 0x15, - 0x94, 0x30, 0x01, 0x00, 0x48, 0x93, 0x00, 0x4b, 0x02, 0xb0, 0x00, 0x00, - 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0x83, 0x94, 0x00, 0x3a, 0x81, 0x30, 0x01, 0x00, 0x14, 0x87, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x58, 0x01, 0x20, 0x08, 0xe0, 0xb1, 0x01, 0x00, - 0x60, 0x01, 0x20, 0x16, 0xe0, 0xb1, 0x01, 0x00, 0xc1, 0x92, 0x00, 0x10, - 0x32, 0x30, 0x01, 0x00, 0x2b, 0x90, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, - 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x73, 0x91, 0xa2, 0x08, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x82, 0x00, 0x02, 0x04, 0xdc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x03, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0xc0, 0x01, 0x00, 0x6c, 0x91, 0x37, 0x5c, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1b, 0x62, 0xb1, 0x01, 0x00, 0x70, 0x91, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x6d, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x62, 0xb1, 0x01, 0x00, 0x70, 0x91, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x14, 0x87, 0x17, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x8e, 0xb0, 0x01, 0x00, 0x80, 0x93, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, - 0xb7, 0x93, 0x00, 0x41, 0x87, 0x30, 0x01, 0x00, 0x3c, 0x93, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, - 0x82, 0x91, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x7e, 0x91, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, - 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x2d, 0x8e, 0x22, 0x09, 0x80, 0x30, 0x00, 0x00, 0xf4, 0x94, 0x00, 0x40, - 0x13, 0x30, 0x01, 0x00, 0x2d, 0x8e, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x14, 0x00, 0x2d, 0x45, 0x1f, 0x90, 0x01, 0x00, 0x75, 0x8e, 0x00, 0x44, - 0x19, 0x90, 0x00, 0x00, 0x8a, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x1f, 0x90, 0x01, 0x00, 0xdd, 0x8f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x83, 0x93, 0x00, 0x4a, 0x1f, 0x10, 0x01, 0x00, - 0x3c, 0x93, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x2b, 0x90, 0x00, 0x01, - 0x2c, 0xb0, 0x00, 0x00, 0xc1, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x2b, 0x90, 0x00, 0x10, 0x32, 0xb0, 0x00, 0x00, 0xec, 0x8e, 0x00, 0x45, - 0x1f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x37, 0xc3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x33, 0xc3, 0x01, 0x00, 0x36, 0x00, 0x00, 0x01, - 0x02, 0xcc, 0x01, 0x00, 0x00, 0x00, 0xd2, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x96, 0x91, 0x85, 0x17, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x48, - 0x03, 0xd0, 0x00, 0x00, 0x98, 0x91, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x9f, 0x4c, 0x03, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, - 0x34, 0xc3, 0x01, 0x00, 0x40, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, 0xf0, 0xb1, 0x01, 0x00, - 0x9d, 0x92, 0x00, 0x41, 0xe1, 0x31, 0x01, 0x00, 0x00, 0x80, 0x00, 0x43, - 0x44, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xf0, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xa4, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xba, 0x00, 0x20, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x01, 0x8c, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x46, 0xe0, 0xc1, 0x01, 0x00, 0xac, 0x00, 0x2f, 0x40, - 0x13, 0xb0, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x01, 0xe0, 0xc1, 0x01, 0x00, - 0xae, 0x91, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0x84, 0x95, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xb0, 0x91, 0x22, 0x47, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x13, 0x90, 0x01, 0x00, 0x2d, 0x95, 0x00, 0x47, - 0x19, 0x10, 0x01, 0x00, 0xc0, 0x00, 0x2d, 0x44, 0x1f, 0x90, 0x01, 0x00, - 0xc4, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x61, 0x95, 0x00, 0xf0, - 0x84, 0xb0, 0x00, 0x00, 0x90, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xc5, 0x91, 0xa2, 0x4b, 0x1f, 0x7c, 0x00, 0x00, 0x18, 0x92, 0xa2, 0x4c, - 0x1f, 0x7c, 0x00, 0x00, 0xc5, 0x91, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, - 0xc8, 0x91, 0xa2, 0x01, 0x80, 0x32, 0x00, 0x00, 0xa8, 0x00, 0x2d, 0x46, - 0x8f, 0xb0, 0x01, 0x00, 0xbe, 0x91, 0x1f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, - 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0xc0, 0x91, 0x22, 0xf0, - 0x3a, 0x6c, 0x00, 0x00, 0x15, 0x92, 0x1f, 0xf0, 0x3a, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f, - 0x8f, 0xb0, 0x01, 0x00, 0x8a, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x16, 0x92, 0x20, 0x42, 0xe7, 0x6d, 0x00, 0x00, 0xc4, 0x91, 0x22, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x59, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x58, 0x8f, 0xb0, 0x01, 0x00, 0xc7, 0x91, 0x22, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x5b, 0x8f, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xb0, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, - 0xcc, 0x91, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0xd5, 0x91, 0x23, 0xf0, - 0x02, 0x6c, 0x00, 0x00, 0xd2, 0x91, 0xa2, 0xf0, 0x80, 0x32, 0x00, 0x00, - 0x17, 0x92, 0xa2, 0x42, 0x24, 0x6c, 0x00, 0x00, 0x17, 0x92, 0xa2, 0x41, - 0x03, 0x6c, 0x00, 0x00, 0xd1, 0x91, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x51, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x52, - 0x8f, 0xb0, 0x01, 0x00, 0x17, 0x92, 0x1f, 0x12, 0x84, 0x50, 0x00, 0x00, - 0x17, 0x92, 0xa0, 0x01, 0x84, 0x6c, 0x00, 0x00, 0xc5, 0x91, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x00, 0x92, 0xa2, 0x46, 0xe7, 0x7d, 0x00, 0x00, 0x14, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0xf2, 0x91, 0x22, 0xf0, 0x14, 0x30, 0x00, 0x00, - 0xde, 0x91, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0xef, 0x91, 0x03, 0x1e, - 0x80, 0x32, 0x00, 0x00, 0xdd, 0x91, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x49, - 0x8f, 0xb0, 0x01, 0x00, 0xe3, 0x91, 0x22, 0x0a, 0x02, 0x6c, 0x00, 0x00, - 0xe6, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xe2, 0x91, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00, 0xe5, 0x91, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x82, 0xd0, 0x01, 0x00, - 0xec, 0x91, 0x20, 0x91, 0x83, 0x6c, 0x00, 0x00, 0xeb, 0x91, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x26, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x27, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0xee, 0x91, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x1f, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x20, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0xf1, 0x91, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x22, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x23, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, 0x88, 0x00, 0x2d, 0x44, - 0x8f, 0xb0, 0x01, 0x00, 0xfb, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0xf8, 0x91, 0xa2, 0x43, 0x3d, 0x7c, 0x00, 0x00, 0xf8, 0x91, 0xa2, 0xf2, - 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x80, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0xfa, 0x91, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, 0xf8, 0x91, 0xa0, 0x91, - 0x03, 0x6c, 0x00, 0x00, 0xf6, 0x91, 0x22, 0x43, 0x3d, 0x7c, 0x00, 0x00, - 0xff, 0x91, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x28, 0x00, 0x80, 0x40, - 0x8f, 0x98, 0x01, 0x00, 0x29, 0x00, 0x80, 0x40, 0x8f, 0x98, 0x01, 0x00, - 0x14, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x09, 0x92, 0xa2, 0xf0, - 0x14, 0x30, 0x00, 0x00, 0x88, 0x00, 0x2d, 0x44, 0x8f, 0xb0, 0x01, 0x00, - 0x06, 0x92, 0xa2, 0xf2, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, - 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, - 0xf8, 0x91, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xf6, 0x91, 0x20, 0x91, - 0x03, 0x6c, 0x00, 0x00, 0xf8, 0x91, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x0d, 0x92, 0x20, 0x0a, 0x02, 0x6c, 0x00, 0x00, 0x0c, 0x92, 0xa2, 0x40, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x8f, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x49, 0x8f, 0xb0, 0x01, 0x00, 0x12, 0x92, 0x22, 0x0a, - 0x02, 0x6c, 0x00, 0x00, 0xe6, 0x91, 0xa2, 0x41, 0x19, 0x7c, 0x00, 0x00, - 0x11, 0x92, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x55, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x56, 0x8f, 0xb0, 0x01, 0x00, - 0x14, 0x92, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x48, 0x8f, 0xb0, 0x01, 0x00, - 0x1a, 0x92, 0x00, 0x43, 0x95, 0xb0, 0x00, 0x00, 0x1a, 0x92, 0x00, 0x41, - 0x95, 0xb0, 0x00, 0x00, 0x1a, 0x92, 0x00, 0x42, 0x95, 0xb0, 0x00, 0x00, - 0x1a, 0x92, 0x00, 0x44, 0x95, 0xb0, 0x00, 0x00, 0x1a, 0x92, 0x00, 0x4c, - 0x95, 0xb0, 0x00, 0x00, 0xc9, 0x94, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x1d, 0x92, 0xa2, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4b, - 0x8f, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4c, 0x8f, 0xb0, 0x01, 0x00, - 0x2d, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, - 0x84, 0xb0, 0x01, 0x00, 0x22, 0x92, 0xa2, 0xf3, 0x96, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x01, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x2a, 0x41, - 0xe7, 0xd1, 0x01, 0x00, 0xd4, 0x00, 0x3d, 0x41, 0x85, 0xe0, 0x01, 0x00, - 0x0b, 0x00, 0x00, 0xf2, 0x00, 0xe4, 0x01, 0x00, 0x28, 0x92, 0x22, 0x5a, - 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x90, 0x01, 0x00, - 0x29, 0x92, 0x00, 0x5a, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x1f, 0x80, 0x01, 0x00, 0x00, 0x00, 0x63, 0x41, 0x85, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0xa0, 0xa5, 0x85, 0x6c, 0x01, 0x00, 0x00, 0x00, 0xe3, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0xc6, 0x95, 0x00, 0xf0, - 0x8c, 0xb0, 0x00, 0x00, 0x36, 0x92, 0x22, 0x40, 0x0f, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x33, 0x92, 0xa2, 0x4b, - 0x19, 0x7c, 0x00, 0x00, 0x34, 0x92, 0x22, 0xf0, 0x18, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00, 0xff, 0x92, 0x00, 0x07, - 0x10, 0x30, 0x01, 0x00, 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0x38, 0x92, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x85, 0x92, 0x00, 0x40, - 0x81, 0x30, 0x01, 0x00, 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x2f, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, - 0x19, 0x90, 0x01, 0x00, 0xff, 0x92, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00, - 0xf9, 0x82, 0x00, 0x40, 0x05, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0xff, 0x92, 0x00, 0x07, 0x10, 0x30, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x05, 0xb0, 0x01, 0x00, 0x41, 0x92, 0x33, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x44, 0x92, 0xa1, 0xad, 0x95, 0x20, 0x00, 0x00, 0x52, 0x92, 0x13, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x13, 0x4a, 0x5a, 0x83, 0x01, 0x00, - 0x30, 0x00, 0x39, 0x45, 0x95, 0xe0, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x0f, - 0x5e, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x5f, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x45, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x48, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x58, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, - 0x4e, 0xb0, 0x01, 0x00, 0xa2, 0x84, 0x00, 0x40, 0x5d, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x58, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x41, 0x97, 0xb0, 0x00, 0x00, - 0x4f, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x97, 0xb0, 0x01, 0x00, 0x53, 0x92, 0x60, 0x07, 0x96, 0x30, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x4b, 0x84, 0x89, 0x01, 0x00, 0x00, 0x00, 0x70, 0xc2, - 0x24, 0xb0, 0x01, 0x00, 0x5d, 0x92, 0xa2, 0x45, 0x25, 0x7c, 0x00, 0x00, - 0x57, 0x92, 0x31, 0x20, 0x85, 0x30, 0x00, 0x00, 0x5e, 0x92, 0x22, 0x12, - 0x48, 0x7f, 0x00, 0x00, 0x58, 0x04, 0x11, 0x12, 0x48, 0x03, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x1e, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00, - 0x5d, 0x92, 0x31, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, - 0x24, 0xb0, 0x01, 0x00, 0x5e, 0x92, 0x22, 0x12, 0x48, 0x7f, 0x00, 0x00, - 0x58, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x2f, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x6b, 0x92, 0x0b, 0xf0, 0x84, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x11, 0x12, 0x48, 0x83, 0x01, 0x00, 0x68, 0x92, 0x22, 0x50, - 0x85, 0x70, 0x00, 0x00, 0x5e, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x2a, 0x94, 0x00, 0xf2, 0x96, 0x30, 0x01, 0x00, 0x93, 0x04, 0x00, 0x12, - 0x94, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x1f, 0x90, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x12, 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4b, - 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x42, 0x10, 0xf4, 0x01, 0x00, - 0x00, 0xb7, 0x3f, 0x43, 0x11, 0xf0, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08, - 0x8a, 0x88, 0x01, 0x00, 0x6e, 0x92, 0x30, 0xa1, 0x0c, 0x30, 0x00, 0x00, - 0x71, 0x92, 0x22, 0x45, 0xe6, 0x7d, 0x00, 0x00, 0x5e, 0x92, 0x10, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x45, 0xe6, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x10, 0x12, 0x48, 0x83, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x60, 0x4b, 0x85, 0x80, 0x01, 0x00, - 0x5e, 0x01, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x2a, 0x94, 0x00, 0xf2, - 0x96, 0x30, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0xd8, 0x00, 0x00, 0x40, 0x81, 0x98, 0x01, 0x00, 0x2e, 0x00, 0x2d, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x7c, 0x92, 0x22, 0x40, 0xe7, 0x6d, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x40, 0x80, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x08, 0x86, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x68, 0xa7, 0x87, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0x80, 0x92, 0xa8, 0x05, 0xe0, 0x31, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x14, 0x00, 0x4b, 0x96, 0xdc, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x4b, 0x1e, 0x94, 0x01, 0x00, 0x10, 0x00, 0x00, 0x0f, - 0x84, 0xf4, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x42, 0x84, 0x88, 0x01, 0x00, - 0x89, 0x92, 0x22, 0x40, 0x80, 0x32, 0x00, 0x00, 0x8a, 0x92, 0x00, 0x42, - 0x68, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x6a, 0xb1, 0x01, 0x00, - 0x8a, 0x92, 0x31, 0x5a, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x42, - 0x48, 0x93, 0x01, 0x00, 0x8c, 0x92, 0x35, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x6d, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0x91, 0x92, 0x28, 0xb1, - 0x2c, 0x30, 0x00, 0x00, 0x8d, 0x92, 0x22, 0x4d, 0x75, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x95, 0x40, 0x11, 0xb0, 0x01, 0x00, 0x6d, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x91, 0x92, 0xa8, 0xb1, 0x10, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x95, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x7f, 0x00, 0x00, 0x40, - 0x61, 0x99, 0x01, 0x00, 0x98, 0x92, 0x28, 0xb1, 0x10, 0x30, 0x00, 0x00, - 0x94, 0x92, 0x9f, 0xba, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x11, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x24, 0x11, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x9a, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xac, 0x94, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x9e, 0x92, 0x32, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xa4, 0x92, 0x22, 0xf8, 0x96, 0x30, 0x00, 0x00, 0x04, 0x00, 0x22, 0xf8, - 0x90, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x92, 0xb0, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x4b, 0xf0, 0xcd, 0x01, 0x00, 0x20, 0x00, 0x92, 0x48, - 0xe0, 0xc9, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, - 0xa8, 0x92, 0x28, 0xb1, 0x92, 0x30, 0x00, 0x00, 0xa4, 0x92, 0x22, 0x4c, - 0x75, 0x7d, 0x00, 0x00, 0x04, 0x00, 0x12, 0x40, 0x91, 0xb0, 0x00, 0x00, - 0x6c, 0x00, 0x00, 0x40, 0x61, 0x99, 0x01, 0x00, 0xa8, 0x92, 0xa8, 0xb1, - 0x90, 0x30, 0x00, 0x00, 0xff, 0x00, 0x00, 0x48, 0x96, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x90, 0xd0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x4b, - 0xf0, 0xcd, 0x01, 0x00, 0x20, 0x00, 0x00, 0x48, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x92, 0x49, 0xe0, 0xb1, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0x82, 0x8c, 0x01, 0x00, - 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, - 0x00, 0xec, 0x00, 0x00, 0xb5, 0x92, 0x22, 0x1a, 0x00, 0x6c, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x00, 0x34, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x49, 0xc1, 0x01, 0x00, 0xb1, 0x92, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x15, 0x82, 0x8c, 0x01, 0x00, - 0xff, 0x07, 0x00, 0xf0, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x41, - 0x00, 0xec, 0x00, 0x00, 0xbe, 0x92, 0x22, 0x0d, 0x00, 0x6c, 0x00, 0x00, - 0x99, 0x92, 0x00, 0x00, 0x1a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x49, 0xc1, 0x01, 0x00, 0xba, 0x92, 0xa2, 0x41, 0x23, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xc3, 0x92, 0x83, 0x1e, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x19, 0x90, 0x01, 0x00, - 0x24, 0x00, 0x2d, 0x01, 0x2c, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x2d, 0xf0, - 0x16, 0xb0, 0x01, 0x00, 0x22, 0x00, 0x2d, 0xf0, 0x26, 0xb0, 0x01, 0x00, - 0x14, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x60, 0x97, 0x2e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xca, 0x92, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x64, 0x97, 0x3e, 0x43, 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0xe1, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3e, 0x43, 0x9d, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x0b, 0xe8, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3f, 0x43, - 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x16, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x64, 0x97, 0x3f, 0x43, - 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x16, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0xe1, 0xb1, 0x01, 0x00, 0x60, 0x17, 0x3d, 0x43, - 0x9d, 0xe0, 0x01, 0x00, 0x10, 0x00, 0x80, 0xa1, 0x16, 0xe4, 0x01, 0x00, - 0x00, 0xb5, 0x00, 0x0d, 0x42, 0xc9, 0x01, 0x00, 0xd9, 0x92, 0x30, 0x47, - 0x17, 0x04, 0x00, 0x00, 0xdc, 0x92, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x90, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d, - 0x46, 0xc9, 0x01, 0x00, 0xe0, 0x92, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, 0x00, 0x00, 0x90, 0x41, - 0x81, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0xe1, 0x92, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00, 0x9d, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0xeb, 0x92, 0xa2, 0x45, 0x95, 0x7c, 0x00, 0x00, - 0x01, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x96, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00, - 0x40, 0x97, 0x3e, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, - 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40, 0x9d, 0xe0, 0x01, 0x00, - 0xfe, 0x92, 0x00, 0x3b, 0xe7, 0xb1, 0x00, 0x00, 0xeb, 0x92, 0x30, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xf5, 0x92, 0xa2, 0x0b, 0xe6, 0x7d, 0x00, 0x00, - 0x00, 0xb5, 0x00, 0x0d, 0x46, 0xc9, 0x01, 0x00, 0xf1, 0x92, 0xa2, 0x0b, - 0xe6, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x98, 0x42, 0x81, 0xb0, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x0d, - 0x46, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe6, 0x91, 0x01, 0x00, - 0x00, 0x00, 0x10, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x41, - 0x81, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x21, 0xa2, 0x95, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x4a, 0x44, 0x83, 0x01, 0x00, 0x00, 0x97, 0x3e, 0x41, - 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xf6, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4e, 0xe6, 0xb1, 0x01, 0x00, 0x40, 0x97, 0x3e, 0x40, - 0x9d, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, 0xff, 0xff, 0x00, 0x07, - 0x92, 0x89, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x08, 0x86, 0xf4, 0x01, 0x00, 0x00, 0xb7, 0x00, 0x43, - 0x46, 0xc9, 0x01, 0x00, 0x07, 0x00, 0x00, 0x08, 0x82, 0x88, 0x01, 0x00, - 0x02, 0x93, 0x40, 0x08, 0x96, 0x30, 0x00, 0x00, 0x9d, 0x04, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x0e, 0x93, 0x22, 0x45, 0x95, 0x7c, 0x00, 0x00, - 0x0a, 0x93, 0x22, 0x5a, 0x1f, 0x7c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, - 0x96, 0xf4, 0x01, 0x00, 0x07, 0x93, 0x31, 0x5f, 0x97, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x11, 0x4b, 0x48, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x6a, 0xb1, 0x01, 0x00, 0x0a, 0x93, 0x30, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xe6, 0x81, 0x01, 0x00, 0x00, 0x00, 0x10, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x97, 0x3f, 0x41, 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, - 0x96, 0xb0, 0x01, 0x00, 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x63, 0xf3, 0x88, 0xb0, 0x01, 0x00, 0x16, 0x93, 0xa2, 0x3b, - 0x89, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x90, 0xb1, 0x01, 0x00, - 0x01, 0x00, 0x00, 0xa6, 0x92, 0xb1, 0x01, 0x00, 0x17, 0x93, 0x18, 0x4a, - 0x44, 0x93, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x30, 0x00, 0x39, 0x45, 0x97, 0xe0, 0x01, 0x00, 0x1c, 0x93, 0x22, 0x5a, - 0x1f, 0x7c, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x0f, 0x98, 0xd8, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x5e, 0x94, 0x01, 0x00, 0x1e, 0x93, 0x00, 0x05, - 0x4a, 0xb0, 0x00, 0x00, 0x1f, 0x04, 0x00, 0xa7, 0x5e, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x4b, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x1f, 0x93, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x22, 0x93, 0x40, 0x07, 0x96, 0x30, 0x00, 0x00, - 0x9d, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x26, 0x93, 0x22, 0x45, - 0x95, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x9b, 0x04, 0x00, 0x4a, 0x44, 0x13, 0x01, 0x00, 0x00, 0x97, 0x3f, 0x41, - 0x95, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, - 0x40, 0x97, 0x3d, 0x40, 0x97, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x63, 0xf3, - 0x88, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x38, 0x45, 0x97, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x0f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, - 0x2e, 0x93, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x27, 0x93, 0xa2, 0x3b, - 0x89, 0x6c, 0x00, 0x00, 0x30, 0x00, 0x38, 0x45, 0x9d, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x98, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x93, 0x04, 0x00, 0x12, - 0x94, 0x30, 0x01, 0x00, 0xff, 0x92, 0x00, 0x5a, 0x1f, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x5a, 0x1f, 0x90, 0x01, 0x00, 0x11, 0x00, 0x00, 0x4a, - 0xe6, 0xc9, 0x01, 0x00, 0x34, 0x00, 0x2f, 0x4f, 0x95, 0x84, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x63, 0x4b, - 0x84, 0xc8, 0x01, 0x00, 0x00, 0x00, 0xa0, 0x43, 0x85, 0x6c, 0x01, 0x00, - 0x00, 0x00, 0xe3, 0x40, 0x85, 0xb0, 0x01, 0x00, 0x30, 0x00, 0x2d, 0x44, - 0x1f, 0x90, 0x01, 0x00, 0x32, 0x00, 0x2d, 0xf2, 0x2a, 0xb0, 0x01, 0x00, - 0x04, 0x00, 0x22, 0xf2, 0x02, 0x30, 0x00, 0x00, 0x1e, 0x92, 0x00, 0x10, - 0x32, 0x30, 0x01, 0x00, 0x32, 0x00, 0xa0, 0x40, 0xe5, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x40, - 0x99, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x02, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x03, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x97, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x4c, 0x02, 0xd0, 0x00, 0x00, - 0x45, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, - 0x36, 0xb0, 0x01, 0x00, 0x55, 0x93, 0x22, 0x41, 0x03, 0x50, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, - 0xf1, 0xb1, 0x01, 0x00, 0x70, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x62, 0xb1, 0x01, 0x00, 0x4e, 0x93, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x7c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb0, 0x01, 0x00, 0x49, 0x93, 0x00, 0x5c, - 0x01, 0x80, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x1b, 0x10, 0xb1, 0x00, 0x00, 0x68, 0x01, 0x2d, 0x06, - 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x82, 0xc0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x46, 0xc9, 0x01, 0x00, 0x94, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x7c, 0x93, 0x22, 0x40, 0x11, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x68, 0x08, 0x38, 0x96, 0x01, 0x00, 0xf0, 0x07, 0x00, 0x41, - 0x82, 0xcc, 0x01, 0x00, 0x5a, 0x93, 0xaa, 0x41, 0x3b, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x10, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5c, - 0x11, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x04, 0xcc, 0x01, 0x00, - 0x7b, 0x93, 0x26, 0x46, 0x23, 0x30, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, - 0x12, 0xc8, 0x01, 0x00, 0x64, 0x01, 0x20, 0xf0, 0xe0, 0xb1, 0x01, 0x00, - 0x7a, 0x93, 0x22, 0x41, 0x05, 0x50, 0x00, 0x00, 0x20, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x0c, 0x00, 0x00, 0xf8, 0x86, 0xc8, 0x01, 0x00, - 0x00, 0x00, 0x22, 0x44, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x6c, 0x93, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0x79, 0x93, 0x22, 0x41, 0x05, 0x50, 0x00, 0x00, 0x77, 0x93, 0xa2, 0x41, - 0x23, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x1a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x72, 0x93, 0xa8, 0x46, 0x23, 0x30, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, - 0x48, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x42, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x13, 0xc0, 0x01, 0x00, 0x67, 0x93, 0x00, 0x50, - 0x49, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x1a, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x7b, 0x93, 0x22, 0x40, 0x3b, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x00, 0xb0, 0x01, 0x00, 0x99, 0x92, 0x00, 0x5c, - 0x01, 0x00, 0x01, 0x00, 0x7c, 0x93, 0x00, 0x41, 0x3b, 0xd0, 0x00, 0x00, - 0x00, 0x00, 0x8d, 0x47, 0x80, 0x32, 0x01, 0x00, 0xb0, 0x00, 0x2f, 0x5f, - 0x13, 0xb0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xf0, 0x8c, 0xc0, 0x01, 0x00, - 0x00, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x8c, 0xb0, 0x01, 0x00, - 0x88, 0x93, 0x8c, 0xf8, 0x8e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x19, 0x90, 0x01, 0x00, 0x04, 0x00, 0x22, 0xf8, 0x14, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x16, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x26, 0xb0, 0x01, 0x00, 0x08, 0x00, 0x2e, 0xf8, 0x0c, 0xb0, 0x01, 0x00, - 0x0c, 0x00, 0x2a, 0x4a, 0xe0, 0xb1, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, - 0xe0, 0xc9, 0x01, 0x00, 0x10, 0x00, 0x20, 0x1b, 0xe0, 0xb1, 0x01, 0x00, - 0x95, 0x93, 0x20, 0x0a, 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x96, 0xb0, 0x01, 0x00, - 0x20, 0x00, 0x20, 0xf0, 0xe4, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x20, 0x4a, - 0xe0, 0xb1, 0x01, 0x00, 0x1c, 0x00, 0x20, 0x4b, 0xe0, 0xb1, 0x01, 0x00, - 0x80, 0x93, 0x00, 0x40, 0x13, 0xb0, 0x00, 0x00, 0x2c, 0x00, 0x2d, 0x42, - 0x19, 0x90, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x82, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf3, 0x96, 0xb0, 0x01, 0x00, 0x9b, 0x93, 0xa2, 0xa5, - 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00, - 0x9e, 0x93, 0xa2, 0x40, 0x97, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x2d, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x63, 0x41, 0x97, 0xc0, 0x01, 0x00, 0xd4, 0x00, 0x3e, 0x41, - 0x83, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x83, 0xc0, 0x01, 0x00, - 0xa3, 0x93, 0xa0, 0xa5, 0x83, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x83, 0xb0, 0x01, 0x00, 0x2c, 0x00, 0x20, 0x41, 0xe6, 0xb1, 0x01, 0x00, - 0xa8, 0x93, 0x22, 0x40, 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x98, 0xdc, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x4c, 0xe4, 0xf5, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x1f, 0x80, 0x01, 0x00, 0x0b, 0x00, 0x80, 0x00, - 0xe4, 0xf5, 0x01, 0x00, 0x9d, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x04, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x41, 0x87, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00, - 0xb4, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x9d, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00, - 0xc3, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x2e, 0x00, 0x2f, 0xf3, 0x84, 0xb0, 0x01, 0x00, - 0x01, 0x00, 0x63, 0xf3, 0x96, 0xc8, 0x01, 0x00, 0xcb, 0x93, 0x9f, 0x41, - 0x85, 0x50, 0x00, 0x00, 0x01, 0x00, 0x00, 0xa5, 0x85, 0xcc, 0x01, 0x00, - 0x2d, 0x00, 0xa0, 0x42, 0xe6, 0xb1, 0x01, 0x00, 0x5e, 0x01, 0x2d, 0x00, - 0x80, 0xb0, 0x01, 0x00, 0xd0, 0x93, 0x52, 0x43, 0x81, 0x60, 0x00, 0x00, - 0x02, 0x00, 0x00, 0xf2, 0x82, 0xf4, 0x01, 0x00, 0xd1, 0x93, 0x00, 0x41, - 0x80, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x81, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x5e, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x95, 0xb0, 0x00, 0x00, - 0xd2, 0x93, 0x9e, 0xbb, 0x80, 0x32, 0x00, 0x00, 0xd7, 0x93, 0xa2, 0x40, - 0x1f, 0x7c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x41, 0x95, 0xb0, 0x01, 0x00, 0x04, 0x00, 0x00, 0x15, - 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0x2b, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x24, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, - 0x38, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x3a, 0xb0, 0x01, 0x00, 0xec, 0x93, 0x9c, 0x17, - 0x80, 0x32, 0x00, 0x00, 0xe1, 0x93, 0xa2, 0x4a, 0x19, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x4c, 0x1f, 0x90, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x1e, - 0x98, 0xf4, 0x01, 0x00, 0xe0, 0x93, 0xa2, 0x48, 0x99, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x15, 0x42, 0xb1, 0x01, 0x00, 0xe0, 0x93, 0xa2, 0x8a, - 0xf1, 0x6d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x02, 0xcc, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x3e, 0xb0, 0x01, 0x00, 0x01, 0x00, 0x00, 0xf4, - 0x28, 0xcc, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, - 0xeb, 0x93, 0x20, 0xf0, 0x3e, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x1f, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x2b, 0xc0, 0x01, 0x00, - 0xbf, 0x00, 0x2d, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0xf3, - 0x3a, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0x07, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04, - 0xe6, 0xb1, 0x01, 0x00, 0x18, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x1c, 0x00, 0x2d, 0xf0, 0x16, 0xb0, 0x01, 0x00, 0x20, 0x00, 0x2d, 0xf0, - 0x26, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2f, 0xf2, 0x0c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x06, 0x14, 0xec, 0x00, 0x00, 0xf8, 0x93, 0x22, 0x45, - 0x1f, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x06, 0x2a, 0xec, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0x94, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x96, 0xb0, 0x01, 0x00, 0x0c, 0x00, 0x2d, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x2a, 0x4c, 0xe1, 0xc1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x10, - 0x48, 0xc9, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x18, 0x00, 0x00, 0x05, 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x02, 0x94, 0xa8, 0x5c, 0x1f, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x05, 0x48, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x03, 0xf0, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, - 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x06, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0x0c, 0x94, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x0d, 0x94, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x62, 0xc9, 0x01, 0x00, - 0x0f, 0x94, 0xa8, 0x00, 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, 0x48, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x01, 0xf0, 0xcd, 0x01, 0x00, 0x40, 0x00, 0x00, 0x03, - 0xf0, 0xc9, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe0, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x2e, 0x50, 0x49, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, - 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, - 0x19, 0x94, 0x62, 0x42, 0x61, 0x31, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x1a, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xa0, 0x00, 0x00, 0xa4, 0x62, 0xdd, 0x01, 0x00, 0x1c, 0x94, 0xa8, 0x00, - 0xe0, 0x31, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x30, 0x80, 0x00, 0x4a, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, - 0xf1, 0xb1, 0x01, 0x00, 0xc0, 0xa8, 0x3d, 0x46, 0x0d, 0xe0, 0x01, 0x00, - 0xff, 0x7f, 0x00, 0xa1, 0xf0, 0x89, 0x01, 0x00, 0x02, 0x00, 0x00, 0x09, - 0x96, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0x97, 0xe0, 0x01, 0x00, - 0x00, 0x00, 0x60, 0xa8, 0x97, 0xc0, 0x01, 0x00, 0x26, 0x94, 0x63, 0x42, - 0x61, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x4a, 0x62, 0xc9, 0x01, 0x00, - 0x27, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x99, 0x3f, 0x42, 0x97, 0xf0, 0x01, 0x00, - 0x2b, 0x94, 0x65, 0x40, 0x81, 0x32, 0x00, 0x00, 0x33, 0x94, 0x22, 0xf3, - 0x74, 0x06, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf3, 0x94, 0x88, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x07, 0xe7, 0x85, 0x01, 0x00, 0x00, 0x00, 0x75, 0x55, - 0x61, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x62, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x30, 0x94, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x40, 0x81, 0xb2, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa8, 0x36, 0xb0, 0x01, 0x00, 0x43, 0x94, 0x82, 0x41, - 0x23, 0x40, 0x00, 0x00, 0x38, 0x94, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0xa7, 0x91, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, 0x20, 0x80, 0x00, 0x10, - 0x42, 0xc9, 0x01, 0x00, 0x3e, 0x94, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x3b, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x23, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb0, 0x01, 0x00, - 0x43, 0x94, 0x22, 0x41, 0x19, 0x7c, 0x00, 0x00, 0xaf, 0x92, 0x00, 0x43, - 0x23, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x23, 0xb0, 0x01, 0x00, - 0x45, 0x94, 0xa3, 0x15, 0x0c, 0x6c, 0x00, 0x00, 0x46, 0x94, 0x00, 0x06, - 0x04, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x04, 0xb0, 0x01, 0x00, - 0x48, 0x94, 0x20, 0x02, 0x1a, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, - 0x04, 0xb0, 0x01, 0x00, 0x07, 0x95, 0x00, 0x05, 0x48, 0x31, 0x01, 0x00, - 0x72, 0x94, 0x22, 0x02, 0x14, 0x50, 0x00, 0x00, 0x4c, 0x94, 0xa2, 0x02, - 0x2a, 0x50, 0x00, 0x00, 0x72, 0x94, 0xa2, 0x45, 0x1f, 0x7c, 0x00, 0x00, - 0x4e, 0x94, 0x22, 0x02, 0x0c, 0x50, 0x00, 0x00, 0x57, 0x94, 0x00, 0x02, - 0x16, 0xc0, 0x00, 0x00, 0x56, 0x94, 0x22, 0x5c, 0x1f, 0x7c, 0x00, 0x00, - 0x30, 0x80, 0x00, 0x10, 0x42, 0xc9, 0x01, 0x00, 0x56, 0x94, 0x22, 0x40, - 0xe3, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61, 0xb1, 0x01, 0x00, - 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x52, 0x94, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x48, 0xb1, 0x01, 0x00, 0xf1, 0x93, 0x00, 0x5c, - 0x1f, 0x00, 0x01, 0x00, 0x72, 0x94, 0x22, 0x15, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x33, 0xc0, 0x01, 0x00, 0x71, 0x94, 0xa2, 0x02, - 0x1a, 0x50, 0x00, 0x00, 0x63, 0x94, 0x22, 0x46, 0x1f, 0x7c, 0x00, 0x00, - 0x70, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x1f, 0x80, 0x01, 0x00, 0x63, 0x94, 0x22, 0x40, 0xe3, 0x6d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x5f, 0x94, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x88, 0x1c, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x48, 0xb1, 0x01, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x42, 0xc9, 0x01, 0x00, - 0x10, 0x00, 0x00, 0xf0, 0x10, 0xc8, 0x01, 0x00, 0x2f, 0x00, 0x2f, 0x5c, - 0x11, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x47, 0xe7, 0x91, 0x01, 0x00, - 0xf0, 0x07, 0x00, 0x40, 0x1b, 0x98, 0x01, 0x00, 0x35, 0x94, 0x20, 0x15, - 0x1a, 0x6c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x48, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x22, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xf0, 0xb1, 0x01, 0x00, 0xff, 0x07, 0x00, 0x08, 0xe0, 0x8d, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x61, 0xb1, 0x01, 0x00, 0xa0, 0x00, 0x00, 0xa4, - 0x62, 0xdd, 0x01, 0x00, 0x6e, 0x94, 0xa8, 0x46, 0x1f, 0x10, 0x00, 0x00, - 0x35, 0x94, 0x00, 0x05, 0x48, 0xb1, 0x00, 0x00, 0x35, 0x94, 0x00, 0x02, - 0x10, 0xc0, 0x00, 0x00, 0x74, 0x94, 0xa2, 0x44, 0x1f, 0x7c, 0x00, 0x00, - 0xa7, 0x91, 0x00, 0x01, 0x8c, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1b, - 0x10, 0xb1, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, 0x10, 0x00, 0x00, 0x08, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x03, 0xe0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x5c, 0x1f, 0x90, 0x00, 0x00, 0x7b, 0x94, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, 0xa2, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x40, 0x27, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0xb0, 0x01, 0x00, 0x99, 0x92, 0x00, 0x41, 0xa3, 0x41, 0x01, 0x00, - 0x7f, 0x94, 0x00, 0x41, 0x27, 0xd0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x80, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x86, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd8, 0x94, 0x00, 0x40, - 0x2b, 0x30, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x06, 0x16, 0xc0, 0x01, 0x00, - 0x90, 0x00, 0x2d, 0xf0, 0x16, 0xc4, 0x01, 0x00, 0x8e, 0x94, 0xa0, 0xf0, - 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x0e, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xf0, - 0x30, 0xb0, 0x01, 0x00, 0xac, 0x00, 0x2d, 0x40, 0x87, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x6c, 0xf0, 0x28, 0xb0, 0x01, 0x00, 0x97, 0x94, 0x22, 0x4a, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x43, 0x86, 0xc8, 0x01, 0x00, - 0x00, 0x30, 0x00, 0x0b, 0x16, 0xc8, 0x01, 0x00, 0x97, 0x94, 0xa4, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0xb8, 0x94, 0x22, 0x06, 0x80, 0x32, 0x00, 0x00, 0xa4, 0x94, 0xa2, 0x06, - 0x14, 0x6c, 0x00, 0x00, 0xa1, 0x94, 0x22, 0x48, 0x19, 0x7c, 0x00, 0x00, - 0x9c, 0x94, 0xa0, 0x41, 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0x31, 0xc0, 0x01, 0x00, - 0x90, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0x48, - 0x19, 0x80, 0x01, 0x00, 0x8b, 0x00, 0x20, 0x45, 0xe7, 0x91, 0x01, 0x00, - 0xa4, 0x94, 0x00, 0x40, 0x87, 0x90, 0x00, 0x00, 0x08, 0x00, 0x00, 0x43, - 0x86, 0x98, 0x01, 0x00, 0xa4, 0x94, 0xa0, 0x48, 0x17, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, 0xb0, 0x00, 0x00, 0x40, - 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43, 0xfc, 0xc9, 0x01, 0x00, - 0x0f, 0x95, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xe5, 0xb1, 0x01, 0x00, 0xaf, 0x94, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, - 0x08, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab, - 0xf9, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00, - 0xae, 0x94, 0xa0, 0xf0, 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0xb3, 0x94, 0x64, 0xf0, 0x82, 0xb0, 0x00, 0x00, - 0xa4, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0xb3, 0x94, 0xa2, 0xf2, - 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe5, 0xb1, 0x01, 0x00, - 0x8c, 0x00, 0x20, 0x18, 0xe0, 0xb1, 0x01, 0x00, 0x90, 0x00, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x60, 0x06, 0x30, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x86, 0x0c, 0x80, 0xb2, 0x00, 0x00, 0xbc, 0x00, 0x2d, 0x46, - 0x19, 0x90, 0x01, 0x00, 0xa0, 0x00, 0xa0, 0xf2, 0xe4, 0xb1, 0x01, 0x00, - 0xb0, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x10, 0x50, 0x00, 0x43, - 0xfc, 0xc9, 0x01, 0x00, 0x0f, 0x95, 0x00, 0x30, 0x81, 0x30, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x4a, 0x19, 0xfc, 0x00, 0x00, 0x08, 0x00, 0x00, 0xa2, - 0x44, 0xc9, 0x01, 0x00, 0xcc, 0x00, 0x2d, 0xab, 0xf9, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xab, 0x17, 0xc0, 0x01, 0x00, 0xc1, 0x94, 0xa0, 0xf0, - 0x16, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x17, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0xe4, 0xf0, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x1b, 0xe0, 0xb1, 0x00, 0x00, 0xc6, 0x94, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x7e, 0x89, 0x01, 0x00, - 0x00, 0x00, 0xa6, 0x4c, 0x95, 0x60, 0x01, 0x00, 0x00, 0x00, 0x80, 0x4a, - 0x18, 0x94, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x01, 0xf0, 0x31, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, - 0xf0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, - 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x15, 0xe0, 0xb1, 0x00, 0x00, - 0xd1, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x10, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xe8, 0x5f, - 0x17, 0x90, 0x01, 0x00, 0x70, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x7a, 0x01, 0x2e, 0xfe, 0x92, 0xb0, 0x01, 0x00, 0x8b, 0x00, 0x2d, 0xf6, - 0x16, 0xb0, 0x01, 0x00, 0xde, 0x94, 0x22, 0x43, 0xe7, 0x7d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x45, 0xc1, 0x01, 0x00, 0x04, 0x00, 0x00, 0xa6, - 0x2a, 0xb0, 0x01, 0x00, 0x28, 0x00, 0x6e, 0x06, 0x82, 0xc8, 0x01, 0x00, - 0xe2, 0x94, 0x22, 0x4a, 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, - 0x45, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x6e, 0x4c, 0x83, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x92, 0xc0, 0x01, 0x00, 0xe3, 0x94, 0x43, 0x30, - 0x3d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x66, 0x9e, 0x83, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x1b, 0x41, 0x3d, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x92, 0xc0, 0x01, 0x00, 0x06, 0x00, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, - 0x10, 0x00, 0x00, 0x49, 0x98, 0xf4, 0x01, 0x00, 0xec, 0x94, 0x26, 0x30, - 0x93, 0x04, 0x00, 0x00, 0xec, 0x94, 0x90, 0x4c, 0x92, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x93, 0xc0, 0x01, 0x00, 0xff, 0xff, 0x80, 0x49, - 0xec, 0xa9, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x04, 0x00, 0x22, 0x01, 0xf0, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf0, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x15, - 0xe0, 0xb1, 0x00, 0x00, 0xf1, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xfe, 0x94, 0x22, 0x5f, 0x81, 0x7c, 0x00, 0x00, 0xfd, 0x94, 0xa2, 0x40, - 0x19, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x19, 0x90, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x54, 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x97, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0xfd, 0x94, 0x28, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xfa, 0x94, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x00, 0x00, 0xa2, 0x21, 0x81, 0x84, 0x00, 0x00, 0x01, 0x95, 0xa2, 0x5f, - 0x81, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x43, 0x19, 0x7c, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x43, 0x19, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, - 0x61, 0xb1, 0x01, 0x00, 0x10, 0x00, 0x00, 0x07, 0x96, 0xe4, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x96, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x80, 0x00, 0x19, - 0x44, 0xc9, 0x01, 0x00, 0x04, 0x00, 0x22, 0x02, 0xf0, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x13, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x43, 0x61, 0xb1, 0x01, 0x00, - 0x20, 0x00, 0x00, 0x19, 0x62, 0xdd, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x08, - 0xe0, 0xb1, 0x00, 0x00, 0x0c, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x7c, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0xf0, - 0x98, 0xf4, 0x01, 0x00, 0x15, 0x95, 0x20, 0x4c, 0x84, 0x6c, 0x00, 0x00, - 0x88, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, 0x15, 0x95, 0x20, 0xf2, - 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, - 0x98, 0x00, 0x2d, 0x14, 0x82, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, - 0x98, 0xb0, 0x01, 0x00, 0xa3, 0x00, 0x2d, 0x14, 0x98, 0xd0, 0x01, 0x00, - 0x1a, 0x95, 0x20, 0x4c, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, - 0x84, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x80, 0xe0, 0x01, 0x00, - 0x1d, 0x95, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x84, 0xb0, 0x01, 0x00, 0xd0, 0x00, 0x20, 0x14, 0xe0, 0xb1, 0x01, 0x00, - 0x98, 0x00, 0x25, 0x42, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x6e, 0xf3, - 0x80, 0xf0, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x42, 0x82, 0xc0, 0x00, 0x00, - 0x23, 0x95, 0xa0, 0x40, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x17, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0, 0x82, 0xec, 0x00, 0x00, - 0x98, 0x00, 0xa0, 0x41, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x10, - 0x48, 0xb1, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x40, 0xf1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x05, 0xf0, 0xb1, 0x01, 0x00, 0x09, 0x00, 0x00, 0x07, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x60, 0xa7, 0x97, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x62, 0xb1, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x2a, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xa8, 0x00, 0x2d, 0x1c, 0x8a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x9f, 0xf0, - 0x8a, 0xd0, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0x8b, 0xec, 0x00, 0x00, - 0x8a, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0xa4, 0x00, 0x2d, 0x45, 0xe0, 0xd1, 0x01, 0x00, - 0x37, 0x95, 0x9c, 0x17, 0x80, 0x32, 0x00, 0x00, 0xbe, 0x00, 0x2f, 0xab, - 0x83, 0xb0, 0x01, 0x00, 0x88, 0x95, 0x00, 0x14, 0x82, 0x50, 0x01, 0x00, - 0x3c, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x3c, 0x95, 0x22, 0xf2, - 0x82, 0x30, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x3c, 0x95, 0x9f, 0x1c, 0xe0, 0x6d, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x40, - 0x47, 0x99, 0x01, 0x00, 0x88, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0xa8, 0x00, 0x20, 0x1c, 0xe0, 0xb1, 0x01, 0x00, 0x9c, 0x00, 0x2d, 0x30, - 0x81, 0xb0, 0x01, 0x00, 0x88, 0x00, 0x2d, 0xf0, 0x84, 0xb0, 0x01, 0x00, - 0x94, 0x00, 0x2d, 0xf2, 0x86, 0xb0, 0x01, 0x00, 0x4f, 0x95, 0x23, 0xf0, - 0x84, 0x6c, 0x00, 0x00, 0x44, 0x95, 0x23, 0x92, 0x87, 0x6c, 0x00, 0x00, - 0xc9, 0x04, 0x00, 0xa6, 0x94, 0xb0, 0x01, 0x00, 0x46, 0x95, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa6, 0x94, 0xb0, 0x01, 0x00, - 0x60, 0x89, 0x00, 0x4a, 0x94, 0x98, 0x01, 0x00, 0x46, 0x95, 0x68, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xb0, 0xb1, 0x01, 0x00, - 0xbf, 0x00, 0x2d, 0x42, 0xb2, 0xb1, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3, - 0x80, 0xe0, 0x01, 0x00, 0x4a, 0x95, 0xd4, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x78, 0xda, 0x84, 0xc0, 0x01, 0x00, 0x54, 0x95, 0x23, 0x40, - 0x84, 0x6c, 0x00, 0x00, 0x94, 0x00, 0x20, 0x9d, 0xe1, 0xb1, 0x01, 0x00, - 0x54, 0x95, 0x00, 0x40, 0x84, 0xb0, 0x00, 0x00, 0xbf, 0x00, 0x2d, 0x43, - 0x84, 0xc0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf3, 0x80, 0xe0, 0x01, 0x00, - 0x54, 0x95, 0x23, 0x40, 0x84, 0x6c, 0x00, 0x00, 0x94, 0x00, 0x20, 0x9d, - 0xe1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x84, 0xb0, 0x01, 0x00, - 0x58, 0x95, 0xa2, 0xf0, 0x38, 0x6c, 0x00, 0x00, 0x9c, 0x00, 0x20, 0x42, - 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00, - 0x00, 0x00, 0x80, 0x46, 0x19, 0x80, 0x01, 0x00, 0x9c, 0x00, 0x20, 0x42, - 0xe0, 0xb1, 0x01, 0x00, 0x37, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x04, 0x00, 0x00, 0xf3, 0x80, 0xf4, 0x01, 0x00, 0x0f, 0x00, 0x00, 0xf3, - 0x82, 0x88, 0x01, 0x00, 0x5e, 0x95, 0x23, 0x41, 0x80, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5f, 0x13, 0x94, 0x01, 0x00, 0x00, 0x00, 0x89, 0x0c, - 0x80, 0xb2, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0xa0, 0x00, 0xa0, 0xf2, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x41, - 0x24, 0xec, 0x00, 0x00, 0x68, 0x95, 0xa6, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x9f, 0x42, 0x38, 0xec, 0x00, 0x00, 0x68, 0x95, 0xa6, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x6a, 0x95, 0xa3, 0xf0, 0x3a, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x40, 0x43, 0x99, 0x01, 0x00, - 0x6e, 0x95, 0x22, 0xf0, 0x3a, 0x6c, 0x00, 0x00, 0xb4, 0x00, 0x20, 0x1d, - 0xe0, 0xb1, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x5f, 0x13, 0x94, 0x01, 0x00, - 0x6e, 0x95, 0x23, 0xf0, 0x3a, 0x6c, 0x00, 0x00, 0x80, 0x00, 0x20, 0x1d, - 0xe0, 0xb1, 0x01, 0x00, 0xc0, 0x00, 0x20, 0x12, 0xe0, 0xb1, 0x01, 0x00, - 0xc4, 0x00, 0xa0, 0x1c, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0xe0, 0xb1, 0x01, 0x00, - 0x12, 0x00, 0x00, 0x40, 0x87, 0x98, 0x01, 0x00, 0x77, 0x95, 0x9f, 0x41, - 0x24, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x8c, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x12, 0x8c, 0xd0, 0x01, 0x00, 0x78, 0x95, 0x00, 0x41, - 0x24, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8d, 0xb0, 0x01, 0x00, - 0xc6, 0x95, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x40, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x7a, 0x95, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x8c, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x00, 0xa2, 0x08, 0x80, 0x32, 0x01, 0x00, 0x81, 0x95, 0xa2, 0x40, - 0x95, 0x6c, 0x00, 0x00, 0x99, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, - 0x00, 0x82, 0x00, 0xa6, 0x04, 0xb0, 0x01, 0x00, 0xa0, 0x98, 0x2f, 0x40, - 0x11, 0xb0, 0x01, 0x00, 0x30, 0x05, 0x00, 0x41, 0x89, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x9f, 0xf8, 0x3e, 0xec, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x12, - 0xe0, 0xed, 0x00, 0x00, 0xc8, 0x00, 0x20, 0xab, 0xe1, 0xb1, 0x01, 0x00, - 0xcc, 0x00, 0xa0, 0x1f, 0xe0, 0xb1, 0x01, 0x00, 0x8a, 0x95, 0xa3, 0x5f, - 0xe7, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xe7, 0xc1, 0x01, 0x00, - 0xa6, 0x00, 0x00, 0x40, 0x47, 0x99, 0x01, 0x00, 0x9e, 0x95, 0x22, 0xf2, - 0x86, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x43, 0x84, 0xf4, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x41, 0x80, 0xcc, 0x01, 0x00, 0xb8, 0x00, 0x2d, 0x42, - 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x62, 0x40, 0x86, 0xc0, 0x01, 0x00, - 0x92, 0x95, 0x1f, 0x43, 0x80, 0x32, 0x00, 0x00, 0x93, 0x95, 0xa2, 0x40, - 0x87, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x62, 0x41, 0x87, 0xb0, 0x01, 0x00, - 0x97, 0x95, 0x9f, 0x40, 0x80, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x85, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x84, 0xd0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x80, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf2, - 0x88, 0xb0, 0x01, 0x00, 0x02, 0x00, 0x00, 0x44, 0x84, 0xf4, 0x01, 0x00, - 0xb8, 0x00, 0x2e, 0x42, 0x80, 0xd0, 0x01, 0x00, 0x00, 0x00, 0x62, 0x40, - 0x88, 0xc0, 0x01, 0x00, 0x9d, 0x95, 0x1f, 0x44, 0x80, 0x32, 0x00, 0x00, - 0xa1, 0x95, 0xa2, 0x40, 0x89, 0x6c, 0x00, 0x00, 0xa1, 0x95, 0x62, 0x41, - 0x89, 0xb0, 0x00, 0x00, 0x03, 0x00, 0x62, 0x41, 0x86, 0xe4, 0x01, 0x00, - 0xb8, 0x00, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, 0x01, 0x00, 0x62, 0x41, - 0x88, 0xe4, 0x01, 0x00, 0xa4, 0x00, 0x20, 0x40, 0xe5, 0xb1, 0x01, 0x00, - 0xa2, 0x00, 0x20, 0x40, 0xe7, 0xb1, 0x01, 0x00, 0xbc, 0x00, 0x2e, 0x43, - 0x87, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x86, 0xc0, 0x01, 0x00, - 0xa7, 0x95, 0x20, 0x43, 0x87, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, - 0xe5, 0xb1, 0x01, 0x00, 0x40, 0x01, 0x00, 0x43, 0x80, 0xce, 0x01, 0x00, - 0x00, 0x00, 0xa4, 0x43, 0xe4, 0x31, 0x01, 0x00, 0x40, 0x01, 0xe2, 0x40, - 0x87, 0x98, 0x01, 0x00, 0x88, 0x00, 0x2d, 0x44, 0x81, 0xb0, 0x01, 0x00, - 0x90, 0x00, 0x2d, 0xf2, 0x2e, 0xb0, 0x01, 0x00, 0x9c, 0x00, 0x2d, 0xf0, - 0x86, 0xb0, 0x01, 0x00, 0x90, 0x00, 0x2d, 0xf0, 0x82, 0xb0, 0x01, 0x00, - 0xba, 0x00, 0x2d, 0xf0, 0x98, 0xb0, 0x01, 0x00, 0xb4, 0x95, 0xa2, 0x12, - 0x98, 0x6c, 0x00, 0x00, 0xbc, 0x00, 0x2d, 0xf2, 0x98, 0xb0, 0x01, 0x00, - 0xb4, 0x95, 0xa0, 0xf2, 0x98, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, - 0x82, 0xb0, 0x01, 0x00, 0x9c, 0x00, 0x20, 0x41, 0xe0, 0xb1, 0x01, 0x00, - 0xb4, 0x00, 0x2d, 0x12, 0x86, 0xd0, 0x01, 0x00, 0xb7, 0x95, 0xa3, 0x41, - 0xe0, 0x6d, 0x00, 0x00, 0xb8, 0x95, 0x00, 0xf0, 0x84, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x84, 0xb0, 0x01, 0x00, 0x80, 0x00, 0x2d, 0x43, - 0x84, 0xd0, 0x01, 0x00, 0xbb, 0x95, 0x9f, 0x42, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x85, 0xb0, 0x01, 0x00, 0xbd, 0x95, 0xa3, 0x42, - 0x14, 0x6c, 0x00, 0x00, 0xbe, 0x95, 0x00, 0x0a, 0x0c, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x0c, 0xb0, 0x01, 0x00, 0xc0, 0x95, 0xa0, 0x17, - 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x17, 0x0c, 0xb0, 0x01, 0x00, - 0xc5, 0x95, 0x22, 0x40, 0x0d, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, - 0x0c, 0xec, 0x00, 0x00, 0x01, 0x00, 0x00, 0xf0, 0x82, 0xf4, 0x01, 0x00, - 0xc5, 0x95, 0xa0, 0x41, 0x0c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xf0, - 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x81, 0xb0, 0x01, 0x00, - 0x9d, 0x92, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x04, 0x80, 0x00, 0x03, - 0x44, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x46, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x60, 0x41, - 0x87, 0x94, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x44, 0xc9, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x50, 0xf1, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, - 0xf0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0xf0, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xe0, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x45, - 0x61, 0xb1, 0x01, 0x00, 0x20, 0x00, 0x00, 0x10, 0x62, 0xdd, 0x01, 0x00, - 0x00, 0x00, 0xa8, 0x5d, 0x05, 0x90, 0x00, 0x00, 0xd1, 0x95, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x4b, 0x19, 0x90, 0x01, 0x00, - 0x05, 0x00, 0x2a, 0x0c, 0xe4, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x04, - 0xe6, 0xb1, 0x01, 0x00, 0xd7, 0x95, 0x45, 0x48, 0x61, 0x31, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x08, 0x62, 0xdd, 0x01, 0x00, 0xdc, 0x95, 0x28, 0x40, - 0x87, 0x30, 0x00, 0x00, 0xd8, 0x95, 0x22, 0x48, 0x77, 0x7d, 0x00, 0x00, - 0x7e, 0x94, 0x1d, 0x46, 0x87, 0xb0, 0x00, 0x00, 0xdf, 0x95, 0x22, 0x5f, - 0x11, 0x7c, 0x00, 0x00, 0x04, 0x00, 0x22, 0x15, 0x62, 0x31, 0x00, 0x00, - 0xdd, 0x95, 0xa8, 0x40, 0x81, 0x32, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, - 0x00, 0x14, 0x2f, 0x4c, 0x83, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xe2, 0x95, 0xa2, 0x41, 0x83, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x49, 0xb1, 0x01, 0x00, 0x30, 0x00, 0x00, 0x40, 0xa1, 0x99, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x93, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x1f, 0xb0, 0x01, 0x00, 0x35, 0x96, 0x00, 0x49, 0x96, 0x30, 0x01, 0x00, - 0x07, 0x00, 0x00, 0x49, 0x06, 0xe4, 0x01, 0x00, 0x00, 0x39, 0x00, 0x03, - 0x06, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0xb0, 0x01, 0x00, - 0x20, 0x00, 0x00, 0xd0, 0xa0, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x41, - 0x93, 0xc0, 0x01, 0x00, 0xe9, 0x95, 0xa0, 0x54, 0x93, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x2e, 0x05, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, - 0x49, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe1, 0xb1, 0x01, 0x00, - 0x00, 0x02, 0x00, 0xa2, 0x44, 0xc9, 0x01, 0x00, 0xf2, 0x95, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x49, 0xb3, 0x01, 0x00, - 0x3b, 0x96, 0x00, 0x40, 0x49, 0x31, 0x01, 0x00, 0xc8, 0x92, 0x00, 0x40, - 0x81, 0x32, 0x01, 0x00, 0x00, 0xb5, 0x2e, 0x08, 0x97, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0xf9, 0x95, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x00, 0x97, 0x2e, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0xfd, 0x95, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x49, 0xb1, 0x01, 0x00, 0x40, 0x18, 0x2e, 0x05, - 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x01, 0x96, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x57, 0x95, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0x30, 0x94, 0x00, 0x40, 0x45, 0x99, 0x01, 0x00, - 0x64, 0x00, 0x00, 0x40, 0xe5, 0x99, 0x01, 0x00, 0x56, 0x95, 0x20, 0x40, - 0xe7, 0xb1, 0x01, 0x00, 0xb8, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00, - 0xba, 0x94, 0x20, 0x41, 0xe5, 0xb1, 0x01, 0x00, 0x98, 0x94, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x02, 0x00, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, 0x0b, 0x96, 0xa2, 0x41, - 0x97, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x68, 0xb1, 0x01, 0x00, 0x0f, 0x96, 0x85, 0x41, 0x97, 0x40, 0x00, 0x00, - 0x80, 0x04, 0x00, 0x40, 0x81, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x39, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x37, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x35, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x33, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x41, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x3f, 0xb3, 0x01, 0x00, 0xee, 0x05, 0x00, 0x40, - 0x25, 0x9b, 0x01, 0x00, 0x42, 0x00, 0x00, 0x40, 0x4b, 0x9b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x2f, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x2d, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x47, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x43, 0xb3, 0x01, 0x00, 0x60, 0x00, 0x00, 0x40, - 0x2b, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x54, 0xef, 0x93, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x55, 0xf1, 0x93, 0x01, 0x00, 0xff, 0xff, 0x00, 0xa5, - 0x3c, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x5b, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x2c, 0x45, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x59, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x57, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x27, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x53, 0xb3, 0x01, 0x00, 0x2b, 0x96, 0xa2, 0x50, 0xfd, 0x7f, 0x00, 0x00, - 0x2b, 0x96, 0xa2, 0x51, 0xfd, 0x7f, 0x00, 0x00, 0x2c, 0x96, 0x00, 0x40, - 0x1d, 0xb3, 0x00, 0x00, 0x50, 0x46, 0x00, 0x40, 0x1d, 0x9b, 0x01, 0x00, - 0x00, 0xc0, 0x00, 0xa6, 0x88, 0xb3, 0x01, 0x00, 0xff, 0x3f, 0x00, 0xa6, - 0x3a, 0xb3, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x9d, 0x3b, 0x9b, 0x01, 0x00, - 0xb4, 0x05, 0x00, 0x40, 0x23, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x4d, 0xb3, 0x01, 0x00, 0x08, 0x0a, 0x00, 0xa6, 0x14, 0xb3, 0x01, 0x00, - 0x01, 0x01, 0x00, 0x8a, 0x15, 0x9b, 0x01, 0x00, 0x00, 0x80, 0x00, 0xa6, - 0x56, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x80, 0x5e, 0x57, 0xb5, 0x01, 0x00, - 0x18, 0x00, 0x00, 0x4b, 0x20, 0xe4, 0x01, 0x00, 0x06, 0x00, 0x00, 0x4b, - 0x96, 0xe4, 0x01, 0x00, 0x00, 0x43, 0x00, 0x4b, 0x96, 0xc8, 0x01, 0x00, - 0x18, 0x00, 0x00, 0x10, 0x20, 0xdc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x20, 0x94, 0x01, 0x00, 0x00, 0x00, 0x80, 0x57, 0x21, 0x90, 0x01, 0x00, - 0x00, 0x99, 0x2e, 0x0a, 0x97, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, - 0xf1, 0xb1, 0x01, 0x00, 0x3c, 0x96, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x40, 0x97, 0x98, 0x01, 0x00, 0x00, 0xa9, 0x00, 0x40, - 0x45, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0xf1, 0xb1, 0x01, 0x00, - 0x40, 0x96, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, - 0x97, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x61, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x4b, 0x62, 0xb1, 0x01, 0x00, 0x44, 0x96, 0xa8, 0x40, - 0x81, 0x32, 0x00, 0x00, 0x44, 0x96, 0xa2, 0x41, 0x97, 0x50, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x40, 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, - 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, - 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, - 0x9a, 0xb0, 0x00, 0x00, 0xae, 0x9f, 0x00, 0x88, 0x9a, 0xb0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x88, 0x9a, 0xb0, 0x01, 0x00, 0xae, 0x9f, 0x41, 0x40, - 0x81, 0x32, 0x00, 0x00, 0xb2, 0x9f, 0x22, 0x40, 0x7b, 0x6f, 0x00, 0x00, - 0x00, 0x00, 0x19, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xae, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x19, 0x41, 0x7b, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xa4, 0xc4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa1, - 0xc6, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x2f, 0xa2, 0xc8, 0xb3, 0x01, 0x00, - 0x08, 0x14, 0x00, 0x40, 0x49, 0x99, 0x01, 0x00, 0xa8, 0x9f, 0x00, 0x4d, - 0x9a, 0xcc, 0x01, 0x00, 0xbb, 0x9f, 0x26, 0x40, 0x81, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x4c, 0x49, 0xc1, 0x01, 0x00, 0xb9, 0x9f, 0xa2, 0x41, - 0x9b, 0x50, 0x00, 0x00, 0xbf, 0x9f, 0x80, 0x80, 0x80, 0x32, 0x00, 0x00, - 0x00, 0x00, 0x52, 0x49, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4a, - 0xfd, 0x93, 0x01, 0x00, 0xc2, 0x9f, 0x00, 0x42, 0xcd, 0x93, 0x00, 0x00, - 0x00, 0x00, 0x51, 0x4a, 0xfd, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, - 0xfd, 0x93, 0x01, 0x00, 0xc2, 0x9f, 0x00, 0x43, 0xcb, 0x93, 0x00, 0x00, - 0x00, 0x00, 0x50, 0x40, 0x81, 0xb2, 0x01, 0x00, 0xd2, 0x9f, 0x00, 0x40, - 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x40, 0xf0, - 0x80, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x41, 0x4d, 0x80, 0xb2, 0x01, 0x00, - 0xca, 0x9f, 0x00, 0x40, 0x19, 0x99, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0xd1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xf0, 0x9a, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4d, - 0x10, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x49, 0xb1, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xe3, 0x43, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe4, - 0x45, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7b, 0xb3, 0x01, 0x00, - 0x00, 0x00, 0x48, 0x4f, 0x40, 0xb1, 0x01, 0x00, 0xd2, 0x9f, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xcb, - 0x81, 0xc8, 0x01, 0x00, 0xf4, 0x82, 0x00, 0x40, 0xf2, 0x93, 0x00, 0x00, - 0x40, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x40, 0x05, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x18, 0x06, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xf4, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xaf, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x38, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x36, 0x81, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xb8, 0x80, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x14, 0x87, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xaf, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xf5, 0x82, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x94, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0xd7, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x5d, 0x92, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xc6, 0x95, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x33, 0x93, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0xd6, 0x92, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0xd0, 0x92, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x9a, 0x82, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, - 0x81, 0xb2, 0x01, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x40, 0x81, 0xb2, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, - 0x81, 0xb2, 0x00, 0x00, - }, -}; diff --git a/drivers/staging/slicoss/oasisrcvucode.h b/drivers/staging/slicoss/oasisrcvucode.h deleted file mode 100644 index 5b3531f04cb9..000000000000 --- a/drivers/staging/slicoss/oasisrcvucode.h +++ /dev/null @@ -1,205 +0,0 @@ -#define OASIS_RCVUCODE_VERS_STRING "1.2" -#define OASIS_RCVUCODE_VERS_DATE "2006/03/27 15:10:28" - -static u32 OasisRcvUCodeLen = 512; - -static u8 OasisRcvUCode[2560] = -{ -0x47, 0x75, 0x01, 0x00, 0x04, 0xa0, 0x13, 0x01, 0x00, 0x1c, 0xb7, 0x5b, 0x09, -0x30, 0x00, 0xb6, 0x5f, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x18, 0x3b, -0x78, 0x3a, 0x00, 0x1c, 0xa2, 0x77, 0x01, 0x00, 0x1c, 0x07, 0x1d, 0x01, 0x70, -0x18, 0xad, 0x7b, 0xf1, 0xff, 0x1c, 0xb3, 0x7b, 0xa9, 0xaa, 0x1e, 0xb4, 0x7b, -0x01, 0x0c, 0x1c, 0xb5, 0x7b, 0x0d, 0x06, 0x1c, 0x00, 0x00, 0x30, 0x64, 0x08, -0x0c, 0x31, 0x5a, 0x70, 0x04, 0x0c, 0x31, 0x5a, 0x80, 0x04, 0x0c, 0x31, 0x4e, -0x90, 0x04, 0x0c, 0x31, 0x4a, 0xa0, 0x00, 0x09, 0x25, 0x55, 0xc0, 0x04, 0x0c, -0x31, 0x52, 0xb0, 0x00, 0xe9, 0x24, 0x55, 0xc0, 0x04, 0xcc, 0xb3, 0x00, 0x1c, -0x1c, 0xeb, 0x2d, 0x01, 0x00, 0x1c, 0x06, 0x56, 0x32, 0xd4, 0x08, 0x07, 0x9d, -0x00, 0x00, 0x1c, 0x7b, 0xb7, 0x02, 0x00, 0x10, 0xa0, 0x0f, 0x31, 0x54, 0x09, -0x06, 0x56, 0x5e, 0xc0, 0x04, 0xa0, 0x30, 0x54, 0x03, 0x00, 0xac, 0x30, 0x55, -0x03, 0x00, 0xcd, 0x03, 0x3a, 0x00, 0x1c, 0x7b, 0xb7, 0x02, 0x00, 0x1c, 0x60, -0x8e, 0x31, 0x54, 0x09, 0x29, 0x25, 0x55, 0x03, 0x00, 0x80, 0x8e, 0x31, 0x54, -0x09, 0x8c, 0x30, 0x91, 0x00, 0x04, 0x47, 0x1c, 0x01, 0x00, 0x1c, 0xa0, 0x0f, -0x31, 0x54, 0x09, 0x00, 0x00, 0x64, 0x00, 0x04, 0x47, 0x1c, 0x65, 0xc0, 0x04, -0x47, 0x1c, 0x55, 0x03, 0x00, 0x6c, 0x30, 0x01, 0x00, 0x1c, 0x4d, 0x34, 0x02, -0x00, 0x1c, 0x7b, 0xb7, 0x02, 0x00, 0x1c, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xc8, -0x83, 0x37, 0x00, 0x1c, 0x80, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x64, 0x00, -0x04, 0xa0, 0x0f, 0x30, 0x54, 0x09, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x7b, 0xfb, -0xf2, 0x00, 0x1c, 0xcc, 0x33, 0x0d, 0x00, 0x1c, 0xb4, 0x7b, 0xfd, 0x03, 0x1c, -0x80, 0x0e, 0x30, 0x54, 0x09, 0xe0, 0xfb, 0x05, 0x00, 0x1c, 0x00, 0x00, 0x8c, -0x03, 0x00, 0xb3, 0x0f, 0x31, 0x54, 0x09, 0x00, 0x00, 0xec, 0x70, 0x04, 0x00, -0x00, 0xec, 0x80, 0x04, 0x00, 0x00, 0x8c, 0x93, 0x00, 0x61, 0x76, 0x8d, 0xc3, -0x04, 0xc0, 0x8d, 0x31, 0x54, 0x09, 0xe0, 0x7b, 0x00, 0xc0, 0x1f, 0xa0, 0xfd, -0xc5, 0x01, 0x00, 0xcc, 0x33, 0x05, 0x00, 0x1c, 0xd4, 0x03, 0x00, 0x3c, 0x1c, -0xd4, 0xd3, 0x1b, 0x00, 0x1c, 0xc0, 0xd3, 0x52, 0x00, 0x1c, 0x00, 0x00, 0x5c, -0x13, 0x04, 0x8e, 0x8e, 0x32, 0x54, 0x09, 0x5b, 0x80, 0x5e, 0x13, 0x04, 0x00, -0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x94, 0x01, 0x00, 0xa0, 0x0f, 0x31, 0x54, -0x09, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xc0, 0x03, 0xfc, 0x7f, 0x1c, 0xa0, 0x01, -0xa0, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x01, 0x00, 0xa0, 0x0f, 0x31, 0x54, 0x09, -0xc0, 0x03, 0xfc, 0x03, 0x1c, 0xf5, 0x77, 0x01, 0x00, 0x1c, 0x26, 0x7a, 0xe6, -0x05, 0x1c, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xb3, 0x0f, 0x31, 0x54, 0x09, 0xb5, -0x02, 0x02, 0x00, 0x1c, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0x7a, 0x7e, 0x02, 0x00, -0x1c, 0xb5, 0x02, 0x02, 0x00, 0x1c, 0x53, 0x0f, 0x32, 0x54, 0x09, 0xaf, 0x03, -0x01, 0x00, 0x1c, 0x7a, 0x0e, 0x32, 0x54, 0x09, 0xb5, 0x02, 0x02, 0x00, 0x1c, -0x00, 0x00, 0x02, 0x00, 0x1c, 0xa0, 0x3d, 0xaa, 0x11, 0x04, 0x00, 0x00, 0xac, -0x11, 0x04, 0xd4, 0xd3, 0x52, 0x00, 0x1c, 0xb5, 0x3e, 0xb2, 0x01, 0x00, 0x20, -0xfb, 0xfd, 0xff, 0x1f, 0x80, 0x2c, 0x6c, 0x03, 0x00, 0xb9, 0x3a, 0x9e, 0x01, -0x00, 0x75, 0x3b, 0x02, 0x00, 0x1c, 0xa7, 0x1c, 0x01, 0x00, 0x10, 0xdb, 0x83, -0x16, 0x00, 0x1c, 0xc7, 0x1d, 0x21, 0xc1, 0x04, 0xb9, 0x3b, 0x8d, 0xc1, 0x04, -0x8b, 0x2c, 0x01, 0x00, 0x1c, 0x6b, 0x2c, 0x35, 0xc1, 0x04, 0x00, 0x00, 0x78, -0x11, 0x00, 0xcb, 0x2c, 0x79, 0xc1, 0x04, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xa0, -0x0f, 0x31, 0x54, 0x09, 0x54, 0xd0, 0x02, 0x00, 0x1c, 0x49, 0x25, 0xb1, 0x01, -0x00, 0xab, 0x2c, 0x81, 0xc1, 0x04, 0xa7, 0x1d, 0x55, 0x03, 0x00, 0xcc, 0x33, -0x09, 0x00, 0x1c, 0xeb, 0x2d, 0x01, 0x00, 0x1c, 0xea, 0x29, 0x01, 0x00, 0x1c, -0xa0, 0x0f, 0x31, 0x54, 0x09, 0xae, 0x0f, 0x31, 0x54, 0x09, 0xa0, 0x0f, 0x31, -0x54, 0x09, 0xd4, 0x07, 0xfc, 0x03, 0x1c, 0x99, 0x3a, 0x02, 0x00, 0x1c, 0xbb, -0x38, 0x02, 0x00, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xfc, 0x01, -0x04, 0xdb, 0x3b, 0x7e, 0x00, 0x1c, 0xc7, 0x1d, 0x01, 0x00, 0x1c, 0x26, 0x7a, -0xfa, 0x05, 0x1c, 0x27, 0x1d, 0x01, 0x00, 0x1c, 0xb3, 0x0f, 0x31, 0x54, 0x09, -0x7a, 0x0e, 0x32, 0x54, 0x09, 0x53, 0x0f, 0x32, 0x54, 0x09, 0x7a, 0x0e, 0x32, -0x54, 0x09, 0x53, 0x0f, 0x32, 0x54, 0x09, 0x7a, 0x0e, 0x32, 0x54, 0x09, 0x53, -0x0f, 0x32, 0x54, 0x09, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0x7a, 0x06, 0x02, 0x00, -0x1c, 0x53, 0x0f, 0x32, 0x54, 0x09, 0xaf, 0x03, 0x01, 0x00, 0x1c, 0x7a, 0x0e, -0x32, 0x54, 0x09, 0x53, 0x0f, 0x32, 0x54, 0x09, 0x7a, 0x0e, 0x32, 0x54, 0x09, -0x53, 0x0f, 0x32, 0x54, 0x09, 0x7a, 0x0e, 0x32, 0x54, 0x09, 0x53, 0x0f, 0x32, -0x54, 0x09, 0x7a, 0x0e, 0x32, 0x54, 0x09, 0x00, 0x3d, 0x02, 0x00, 0x1c, 0x00, -0x00, 0x58, 0x12, 0x00, 0xcb, 0x2c, 0x01, 0x00, 0x1c, 0x75, 0x3b, 0x02, 0x00, -0x1c, 0xa7, 0x1c, 0x01, 0x00, 0x10, 0xcb, 0x2f, 0x05, 0x00, 0x1c, 0x60, 0x2c, -0x00, 0x00, 0x1c, 0xc7, 0x1c, 0xc9, 0x02, 0x00, 0xa0, 0x0f, 0x31, 0x54, 0x09, -0x53, 0x07, 0x02, 0x00, 0x1c, 0x46, 0x7a, 0xca, 0x05, 0x1c, 0x7a, 0x0e, 0x32, -0x54, 0x09, 0x40, 0xfa, 0x19, 0x00, 0x1c, 0x00, 0x00, 0x88, 0x02, 0x04, 0x46, -0x7a, 0xca, 0x05, 0x1c, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xa0, 0x0f, 0x31, 0x54, -0x09, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xa0, 0x0f, 0x31, 0x54, 0x09, 0xb3, 0x7b, -0x01, 0xc0, 0x1f, 0x74, 0x0e, 0x30, 0x54, 0x09, 0xc0, 0x03, 0x9c, 0x00, 0x1c, -0x80, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x04, 0x00, 0x00, 0xac, -0x12, 0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xd4, 0xd3, 0x2b, 0x00, 0x1c, 0xd4, -0xd3, 0x52, 0x00, 0x1c, 0x80, 0x76, 0x7d, 0x13, 0x04, 0x00, 0x00, 0xe0, 0x02, -0x00, 0xa6, 0x7b, 0x95, 0x03, 0x10, 0xc7, 0x9c, 0x00, 0x00, 0x1c, 0x80, 0x2c, -0x00, 0x00, 0x1c, 0x00, 0x00, 0x6c, 0x02, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, -0xab, 0x2d, 0xd9, 0x12, 0x05, 0x07, 0x1d, 0xb5, 0xc2, 0x04, 0x8b, 0x2d, 0x01, -0x00, 0x1c, 0x69, 0x25, 0x01, 0x00, 0x1c, 0xa6, 0x7b, 0x95, 0x03, 0x10, 0xcb, -0x2f, 0x09, 0x00, 0x1c, 0x60, 0x2c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x48, 0x03, -0x00, 0x53, 0x0f, 0x32, 0x54, 0x09, 0x46, 0x7a, 0xca, 0x05, 0x1c, 0x7a, 0x0e, -0x32, 0x54, 0x09, 0x40, 0xfa, 0x19, 0x00, 0x1c, 0x00, 0x00, 0x10, 0x03, 0x04, -0x46, 0x7a, 0xca, 0x05, 0x1c, 0xb5, 0x0f, 0x31, 0x54, 0x09, 0xa0, 0x0f, 0x31, -0x54, 0x09, 0x73, 0xec, 0x2a, 0x03, 0x04, 0x60, 0x2c, 0x00, 0x00, 0x1c, 0x00, -0x00, 0x28, 0x03, 0x00, 0xc7, 0x1c, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x28, 0x13, -0x05, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xc0, 0xd7, 0x22, 0x00, 0x1c, 0x75, 0x56, -0x7e, 0x13, 0x04, 0x60, 0x2c, 0x00, 0x00, 0x1c, 0xe7, 0x1c, 0x45, 0x03, 0x04, -0xe7, 0x9c, 0x00, 0x00, 0x1c, 0xa6, 0x7b, 0x95, 0x03, 0x10, 0x80, 0x2c, 0x00, -0x00, 0x1c, 0x00, 0x00, 0xf8, 0x02, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0xb9, -0x7b, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x8c, 0xc3, 0x04, 0xcb, 0xaf, 0xfc, 0x07, -0x1c, 0xcb, 0x2f, 0x01, 0x04, 0x1c, 0xc7, 0x9f, 0x80, 0x03, 0x1c, 0x00, 0x00, -0x8c, 0xc3, 0x04, 0xcb, 0xaf, 0xfc, 0x07, 0x1c, 0xcb, 0x2f, 0x0d, 0x04, 0x1c, -0xc7, 0x9f, 0x80, 0x03, 0x1c, 0x00, 0x00, 0x8c, 0xc3, 0x04, 0xcb, 0xaf, 0x00, -0xf8, 0x1d, 0xcb, 0x2f, 0x01, 0x00, 0x1d, 0xa6, 0x7b, 0x95, 0x03, 0x1c, 0xc7, -0x9c, 0x8c, 0xc3, 0x04, 0x00, 0x00, 0x8c, 0x13, 0x05, 0x07, 0x1d, 0x01, 0x00, -0x1c, 0xc0, 0x1d, 0xdc, 0xd3, 0x08, 0x27, 0x9d, 0xe4, 0x03, 0x00, 0xa0, 0xee, -0x46, 0xd4, 0x00, 0xfb, 0x75, 0x09, 0x14, 0x04, 0x20, 0x7b, 0x06, 0x00, 0x1c, -0xc0, 0x1c, 0x1c, 0x04, 0x00, 0x00, 0x00, 0xb0, 0xd3, 0x08, 0x00, 0x00, 0x00, -0xf4, 0x00, 0xc0, 0xef, 0xf2, 0x00, 0x1c, 0x20, 0x25, 0x5c, 0x14, 0x04, 0x60, -0xb7, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x15, 0x00, 0xcc, 0xb3, 0xfc, 0x03, -0x1c, 0xcc, 0x33, 0x05, 0x02, 0x1c, 0x00, 0x00, 0x0c, 0xc5, 0x04, 0x60, 0xb7, -0x0e, 0x05, 0x04, 0x00, 0x00, 0x0c, 0x15, 0x04, 0x00, 0x00, 0x5c, 0xc4, 0x04, -0xc0, 0x1d, 0x98, 0xf3, 0x04, 0x00, 0x00, 0x68, 0xc4, 0x04, 0x07, 0x9d, 0x00, -0x00, 0x1c, 0x1b, 0x74, 0xfd, 0xf3, 0x04, 0xa6, 0x7b, 0xf1, 0x03, 0x1c, 0xa0, -0x0f, 0x69, 0x54, 0x09, 0xe0, 0x7b, 0x00, 0xfc, 0x1f, 0x39, 0x7f, 0x02, 0x00, -0x1c, 0x07, 0x1d, 0x9d, 0xc3, 0x04, 0xa6, 0x7b, 0xad, 0x03, 0x1c, 0x00, 0x00, -0x68, 0xc4, 0x04, 0xe0, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xa4, 0x03, 0x04, -0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb, 0x2f, 0x01, 0x10, 0x1d, 0x00, 0x00, 0xac, -0xc3, 0x04, 0x00, 0x00, 0xac, 0x03, 0x04, 0xcb, 0xaf, 0x00, 0xf8, 0x1d, 0xcb, -0x2f, 0x01, 0x18, 0x1d, 0xc7, 0x9f, 0x00, 0x0b, 0x1c, 0x00, 0x00, 0xac, 0xc3, -0x04, 0xfb, 0x75, 0x01, 0x00, 0x1c, 0x07, 0x1d, 0x01, 0x00, 0x1c, 0xcc, 0xb3, -0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x01, 0x02, 0x1c, 0x00, 0x00, 0xac, 0xc3, 0x04, -0xa0, 0x1c, 0x00, 0x00, 0x1c, 0xa0, 0xee, 0xa2, 0x03, 0x04, 0xcb, 0xaf, 0xfc, -0x07, 0x1c, 0xcb, 0x2f, 0x09, 0x04, 0x1c, 0xfb, 0x75, 0x01, 0x00, 0x1c, 0x00, -0x00, 0xac, 0xc3, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x01, 0x02, -0x1c, 0x00, 0x00, 0x0c, 0xc5, 0x04, 0x00, 0x00, 0x78, 0x34, 0x05, 0xcc, 0xb3, -0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x15, 0x02, 0x1c, 0x47, 0x9d, 0x54, 0xc4, 0x04, -0x00, 0x00, 0x78, 0x44, 0x00, 0x80, 0x1d, 0x7c, 0x54, 0x04, 0x87, 0x1d, 0x8d, -0x04, 0x00, 0xce, 0x76, 0x01, 0x00, 0x1c, 0xef, 0x76, 0x9d, 0xc4, 0x04, 0xa4, -0x77, 0x8d, 0x24, 0x09, 0xe4, 0x76, 0x01, 0x00, 0x1c, 0xc4, 0x76, 0x01, 0x00, -0x1c, 0x00, 0x00, 0x98, 0x54, 0x04, 0xd7, 0x76, 0x01, 0x50, 0x18, 0xf6, 0x76, -0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, -0xcc, 0x30, 0x45, 0xc5, 0x04, 0xeb, 0x2d, 0x01, 0x00, 0x1c, 0xea, 0x29, 0x01, -0x00, 0x1c, 0xc0, 0x59, 0x01, 0x00, 0x1c, 0xf5, 0x77, 0x29, 0xc5, 0x04, 0xe0, -0x30, 0xdc, 0x04, 0x00, 0x00, 0x4c, 0xb0, 0x04, 0x00, 0x20, 0x4c, 0xf4, 0x04, -0x00, 0x00, 0x00, 0xe8, 0x04, 0x00, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, -0x09, 0x02, 0x1c, 0xeb, 0x2d, 0xb5, 0xc4, 0x04, 0xcc, 0xb3, 0xfc, 0x03, 0x1c, -0xcc, 0x33, 0x19, 0x02, 0x1c, 0xeb, 0x2d, 0xb5, 0xc4, 0x04, 0xcc, 0xb3, 0xfc, -0x03, 0x1c, 0xcc, 0x33, 0x0d, 0x02, 0x1c, 0xeb, 0x2d, 0xb5, 0xc4, 0x04, 0xcc, -0xb3, 0xfc, 0x03, 0x1c, 0xcc, 0x33, 0x11, 0x02, 0x1c, 0xeb, 0x2d, 0xb5, 0xc4, -0x04, 0x00, 0x7b, 0x00, 0x80, 0x1c, 0xae, 0x77, 0x45, 0x05, 0x00, 0x00, 0x00, -0x04, 0xc0, 0x04, 0xd3, 0x8b, 0x00, 0xfc, 0x1f, 0x60, 0x7a, 0x3c, 0x00, 0x1c, -0x60, 0x4c, 0xc0, 0x04, 0x00, 0xc0, 0x2f, 0x20, 0x05, 0x1f, 0xe0, 0x30, 0xb0, -0x04, 0x00, 0x80, 0x25, 0xb0, 0x04, 0x00, 0xb5, 0x5b, 0xb1, 0x04, 0x04, 0x69, -0x26, 0x01, 0x00, 0x1c, 0x6a, 0x2b, 0x01, 0x00, 0x1c, 0x80, 0x1d, 0x00, 0x00, -0x1c, 0xa9, 0x25, 0x45, 0x05, 0x00, 0xee, 0x30, 0x00, 0x00, 0x1c, 0xaf, 0x77, -0x01, 0x05, 0x00, 0x00, 0x00, 0xac, 0x24, 0x04, 0xb4, 0x5f, 0x01, 0x40, 0x18, -0x07, 0x9d, 0x48, 0x55, 0x04, 0xb7, 0x76, 0x01, 0x00, 0x1c, 0x96, 0x76, 0x01, -0x00, 0x1c, 0x47, 0x1d, 0x01, 0x00, 0x1c, 0xa4, 0x33, 0x01, 0x60, 0x18, 0xa4, -0x2f, 0x01, 0x60, 0x18, 0x64, 0x77, 0x01, 0x60, 0x18, 0x24, 0x77, 0x01, 0x60, -0x18, 0x44, 0x77, 0x01, 0x00, 0x1c, 0x64, 0x88, 0x03, 0x00, 0x1c, 0xa4, 0x3f, -0x01, 0x00, 0x1c, 0xa4, 0x3b, 0x01, 0x00, 0x1c, 0x53, 0x7b, 0x00, 0xc0, 0x1c, -0xd3, 0xcf, 0x1b, 0x00, 0x1c, 0x53, 0x4f, 0x02, 0x00, 0x1c, 0xda, 0xcf, 0x00, -0xc0, 0x1f, 0xd5, 0x57, 0x0f, 0x00, 0x1c, 0xd3, 0xd3, 0x37, 0x00, 0x1c, 0xd4, -0x53, 0x0f, 0x00, 0x1c, 0xe0, 0x29, 0x00, 0x00, 0x1c, 0xf5, 0xd5, 0xb0, 0x05, -0x00, 0x00, 0x00, 0x9c, 0x55, 0x04, 0x77, 0x56, 0x01, 0x00, 0x1c, 0x56, 0x53, -0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x18, 0x00, 0x00, 0x04, 0xc0, 0x04, -0xf5, 0x55, 0x01, 0x00, 0x1c, 0x00, 0x00, 0xb4, 0x55, 0x04, 0x77, 0x56, 0x01, -0x00, 0x1c, 0x56, 0x53, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x18, 0x00, -0x00, 0x04, 0xc0, 0x04, 0xcb, 0x2f, 0x01, 0x18, 0x10, 0xcb, 0x2f, 0x01, 0x10, -0x10, 0xcb, 0x2f, 0x01, 0x08, 0x10, 0xcb, 0x2f, 0x01, 0x08, 0x10, 0xcb, 0x2f, -0x01, 0x20, 0x10, 0xcb, 0x2f, 0x01, 0x28, 0x10, 0xcb, 0x2f, 0x01, 0x00, 0x10, -0x89, 0x25, 0x61, 0xc2, 0x04, 0x00, 0x00, 0xec, 0xc2, 0x04, 0x00, 0x00, 0x54, -0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00, -0x00, 0x60, 0xc2, 0x04, 0x00, 0x00, 0xec, 0xc2, 0x04, 0x00, 0x00, 0x54, 0xc3, -0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x40, 0x1c, -0x6c, 0xc0, 0x04, 0x40, 0x1c, 0x9c, 0xc0, 0x04, 0xa7, 0x77, 0x55, 0xc3, 0x04, -0x00, 0x00, 0xc4, 0xc0, 0x04, 0x27, 0x1d, 0xf1, 0xc0, 0x04, 0x00, 0x00, 0x54, -0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00, 0x00, 0x54, 0xc3, 0x04, 0x00, -0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, -0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, -0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, -0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, -0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, -0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, -0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, -0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, -0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, -0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, -0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, -0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, -0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, -0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, -0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, -0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, -0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, -0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, -0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, -0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, -0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, -0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, -0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, -0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, -0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, -0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, -0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, -0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, -0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, -0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, -0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, -0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, -0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, -0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, -0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, -0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, 0x00, 0x00, 0x2c, 0xc6, 0x04, -}; diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index a8ea59d7ea15..ccf7625b8bb3 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -46,30 +46,10 @@ #define OASIS_UCODE_VERS_DATE "2006/03/27 15:10:37" #define OASIS_UCODE_HOSTIF_ID 3 -static s32 ONumSections = 0x2; -static u32 OSectionSize[] = { - 0x00004000, 0x00010000, -}; - -static u32 OSectionStart[] = { - 0x00000000, 0x00008000, -}; - #define MOJAVE_UCODE_VERS_STRING "1.2" #define MOJAVE_UCODE_VERS_DATE "2006/03/27 15:12:22" #define MOJAVE_UCODE_HOSTIF_ID 3 -static s32 MNumSections = 0x2; -static u32 MSectionSize[] = -{ - 0x00008000, 0x00010000, -}; - -static u32 MSectionStart[] = -{ - 0x00000000, 0x00008000, -}; - #define GB_RCVUCODE_VERS_STRING "1.2" #define GB_RCVUCODE_VERS_DATE "2006/03/27 15:12:15" static u32 OasisRcvUCodeLen = 512; @@ -201,17 +181,6 @@ struct slic_cmdqueue { #define SLIC_MAX_CARDS 32 #define SLIC_MAX_PORTS 4 /* Max # of ports per card */ -#if SLIC_DUMP_ENABLED -/* -Dump buffer size - -This cannot be bigger than the max DMA size the card supports, -given the current code structure in the host and ucode. -Mojave supports 16K, Oasis supports 16K-1, so -just set this at 15K, shouldnt make that much of a diff. -*/ -#define DUMP_BUF_SIZE 0x3C00 -#endif struct mcast_address { @@ -367,30 +336,6 @@ struct sliccard { u32 max_isr_xmits; u32 rcv_interrupt_yields; u32 tx_packets; -#if SLIC_DUMP_ENABLED - u32 dumpstatus; /* Result of dump UPR */ - void *cmdbuffer; - - ulong cmdbuffer_phys; - u32 cmdbuffer_physl; - u32 cmdbuffer_physh; - - u32 dump_count; - struct task_struct *dump_task_id; - u32 dump_wait_count; - uint dumpthread_running; /* has a dump thread been init'd */ - uint dump_requested; /* 0 no, 1 = reqstd 2=curr 3=done */ - u32 dumptime_start; - u32 dumptime_complete; - u32 dumptime_delta; - void *dumpbuffer; - ulong dumpbuffer_phys; - u32 dumpbuffer_physl; - u32 dumpbuffer_physh; - wait_queue_head_t dump_wq; - struct file *dumphandle; - mm_segment_t dumpfile_fs; -#endif u32 debug_ix; ushort reg_type[32]; ushort reg_offset[32]; @@ -516,8 +461,6 @@ struct adapter { uint upr_busy; struct timer_list pingtimer; u32 pingtimerset; - struct timer_list statstimer; - u32 statstimerset; struct timer_list loadtimer; u32 loadtimerset; struct dentry *debugfs_entry; @@ -570,25 +513,6 @@ struct adapter { struct net_device_stats stats; }; -#if SLIC_DUMP_ENABLED -#define SLIC_DUMP_REQUESTED 1 -#define SLIC_DUMP_IN_PROGRESS 2 -#define SLIC_DUMP_DONE 3 - -/**************************************************************************** - * - * Microcode crash information structure. This - * structure is written out to the card's SRAM when the microcode panic's. - * - ****************************************************************************/ -struct slic_crash_info { - ushort cpu_id; - ushort crash_pc; -}; - -#define CRASH_INFO_OFFSET 0x155C - -#endif #define UPDATE_STATS(largestat, newstat, oldstat) \ { \ @@ -605,11 +529,11 @@ struct slic_crash_info { #define ETHER_EQ_ADDR(_AddrA, _AddrB, _Result) \ { \ - _Result = TRUE; \ + _Result = true; \ if (*(u32 *)(_AddrA) != *(u32 *)(_AddrB)) \ - _Result = FALSE; \ + _Result = false; \ if (*(u16 *)(&((_AddrA)[4])) != *(u16 *)(&((_AddrB)[4]))) \ - _Result = FALSE; \ + _Result = false; \ } #if defined(CONFIG_X86_64) || defined(CONFIG_IA64) @@ -622,8 +546,8 @@ struct slic_crash_info { #define SLIC_GET_ADDR_HIGH(_addr) (u32)0 #endif -#define FLUSH TRUE -#define DONT_FLUSH FALSE +#define FLUSH true +#define DONT_FLUSH false #define SIOCSLICDUMPCARD (SIOCDEVPRIVATE+9) #define SIOCSLICSETINTAGG (SIOCDEVPRIVATE+10) diff --git a/drivers/staging/slicoss/slic_os.h b/drivers/staging/slicoss/slic_os.h deleted file mode 100644 index 46c678440d28..000000000000 --- a/drivers/staging/slicoss/slic_os.h +++ /dev/null @@ -1,84 +0,0 @@ -/************************************************************************** - * - * Copyright (c)2000-2002 Alacritech, Inc. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation - * are those of the authors and should not be interpreted as representing - * official policies, either expressed or implied, of Alacritech, Inc. - * - **************************************************************************/ - -/* - * FILENAME: slic_os.h - * - * These are the Linux-specific definitions required for the SLICOSS - * driver, which should allow for greater portability to other OSes. - */ -#ifndef _SLIC_OS_SPECIFIC_H_ -#define _SLIC_OS_SPECIFIC_H_ - -#define FALSE (0) -#define TRUE (1) - -#define SLIC_SECS_TO_JIFFS(x) ((x) * HZ) -#define SLIC_MS_TO_JIFFIES(x) (SLIC_SECS_TO_JIFFS((x)) / 1000) - -#ifdef DEBUG_REGISTER_TRACE -#define WRITE_REG(reg, value, flush) \ - { \ - adapter->card->reg_type[adapter->card->debug_ix] = 0; \ - adapter->card->reg_offset[adapter->card->debug_ix] = \ - ((unsigned char *)(®)) - \ - ((unsigned char *)adapter->slic_regs); \ - adapter->card->reg_value[adapter->card->debug_ix++] = value; \ - if (adapter->card->debug_ix == 32) \ - adapter->card->debug_ix = 0; \ - slic_reg32_write((®), (value), (flush)); \ - } -#define WRITE_REG64(a, reg, value, regh, valh, flush) \ - { \ - adapter->card->reg_type[adapter->card->debug_ix] = 1; \ - adapter->card->reg_offset[adapter->card->debug_ix] = \ - ((unsigned char *)(®)) - \ - ((unsigned char *)adapter->slic_regs); \ - adapter->card->reg_value[adapter->card->debug_ix] = value; \ - adapter->card->reg_valueh[adapter->card->debug_ix++] = valh; \ - if (adapter->card->debug_ix == 32) \ - adapter->card->debug_ix = 0; \ - slic_reg64_write((a), (®), (value), (®h), (valh), \ - (flush));\ - } -#else -#define WRITE_REG(reg, value, flush) \ - slic_reg32_write((®), (value), (flush)) -#define WRITE_REG64(a, reg, value, regh, valh, flush) \ - slic_reg64_write((a), (®), (value), (®h), (valh), (flush)) -#endif - -#endif /* _SLIC_OS_SPECIFIC_H_ */ - diff --git a/drivers/staging/slicoss/slicbuild.h b/drivers/staging/slicoss/slicbuild.h deleted file mode 100644 index ae05e043d07e..000000000000 --- a/drivers/staging/slicoss/slicbuild.h +++ /dev/null @@ -1,96 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation - * are those of the authors and should not be interpreted as representing - * official policies, either expressed or implied, of Alacritech, Inc. - * - **************************************************************************/ - -/* - * FILENAME: slicbuild.h - * - * The following contains the compiler directive switches used for - * different SLIC build options. They can all be set in the Makefile - * but the defaults are defined here. - */ -#ifndef _SLIC_BUILD_H_ -#define _SLIC_BUILD_H_ - -#ifndef SLIC_PRODUCTION_BUILD -#define SLIC_PRODUCTION_BUILD 1 -#endif -#ifndef SLIC_FAILURE_RESET -#define SLIC_FAILURE_RESET 1 -#endif -#define DBG 1 -#ifndef SLIC_ASSERT_ENABLED -#define SLIC_ASSERT_ENABLED 1 -#endif -#ifndef SLIC_MCAST_ENABLED -#define SLIC_MCAST_ENABLED 1 -#endif -#ifndef SLIC_GET_STATS_ENABLED -#define SLIC_GET_STATS_ENABLED 1 -#endif -#ifndef SLIC_GET_STATS_TIMER_ENABLED -#define SLIC_GET_STATS_TIMER_ENABLED 0 -#endif -#ifndef SLIC_PING_TIMER_ENABLED -#define SLIC_PING_TIMER_ENABLED 1 -#endif -#ifndef SLIC_IOCTL_SUPPORT_ENABLED -#define SLIC_IOCTL_SUPPORT_ENABLED 1 -#endif -#ifndef ATK_DEBUG -#define ATK_DEBUG 1 -#endif -#ifndef SLIC_POWER_MANAGEMENT_ENABLED -#define SLIC_POWER_MANAGEMENT_ENABLED 0 -#endif -#ifndef SLIC_INTERRUPT_PROCESS_LIMIT -#define SLIC_INTERRUPT_PROCESS_LIMIT 1 -#endif -#ifndef LINUX_FREES_ADAPTER_RESOURCES -#define LINUX_FREES_ADAPTER_RESOURCES 1 -#endif -#ifndef SLIC_OFFLOAD_IP_CHECKSUM -#define SLIC_OFFLOAD_IP_CHECKSUM 1 -#endif -#ifndef SLIC_POWER_MANAGEMENT_ENABLED -#define SLIC_POWER_MANAGEMENT_ENABLED 0 -#endif -#ifndef STATS_TIMER_INTERVAL -#define STATS_TIMER_INTERVAL 2 -#endif -#ifndef PING_TIMER_INTERVAL -#define PING_TIMER_INTERVAL 1 -#endif - -#endif /* _SLIC_BUILD_H_ */ diff --git a/drivers/staging/slicoss/slicdbg.h b/drivers/staging/slicoss/slicdbg.h deleted file mode 100644 index c54e44fb1f63..000000000000 --- a/drivers/staging/slicoss/slicdbg.h +++ /dev/null @@ -1,100 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation - * are those of the authors and should not be interpreted as representing - * official policies, either expressed or implied, of Alacritech, Inc. - * - **************************************************************************/ - -/* - * FILENAME: slicdbg.h - * - * All debug and assertion-based definitions and macros are included - * in this file for the SLICOSS driver. - */ -#ifndef _SLIC_DEBUG_H_ -#define _SLIC_DEBUG_H_ - -#ifdef SLIC_DEFAULT_LOG_LEVEL -#else -#define SLICLEVEL KERN_DEBUG -#endif -#define SLIC_DISPLAY printk -#define DBG_ERROR(n, args...) SLIC_DISPLAY(KERN_EMERG n, ##args) - -#define SLIC_DEBUG_MESSAGE 1 -#if SLIC_DEBUG_MESSAGE -/*#define DBG_MSG(n, args...) SLIC_DISPLAY(SLICLEVEL n, ##args)*/ -#define DBG_MSG(n, args...) -#else -#define DBG_MSG(n, args...) -#endif - -#ifdef ASSERT -#undef ASSERT -#endif - -#if SLIC_ASSERT_ENABLED -#ifdef CONFIG_X86_64 -#define VALID_ADDRESS(p) (1) -#else -#define VALID_ADDRESS(p) (((u32)(p) & 0x80000000) || ((u32)(p) == 0)) -#endif -#ifndef ASSERT -#define ASSERT(a) \ - { \ - if (!(a)) { \ - DBG_ERROR("ASSERT() Failure: file %s, function %s line %d\n",\ - __FILE__, __func__, __LINE__); \ - slic_assert_fail(); \ - } \ - } -#endif -#ifndef ASSERTMSG -#define ASSERTMSG(a,msg) \ - { \ - if (!(a)) { \ - DBG_ERROR("ASSERT() Failure: file %s, function %s"\ - "line %d: %s\n",\ - __FILE__, __func__, __LINE__, (msg)); \ - slic_assert_fail(); \ - } \ - } -#endif -#else -#ifndef ASSERT -#define ASSERT(a) -#endif -#ifndef ASSERTMSG -#define ASSERTMSG(a, msg) -#endif -#endif /* SLIC_ASSERT_ENABLED */ - -#endif /* _SLIC_DEBUG_H_ */ diff --git a/drivers/staging/slicoss/slicdump.h b/drivers/staging/slicoss/slicdump.h deleted file mode 100644 index 92a9b44bcade..000000000000 --- a/drivers/staging/slicoss/slicdump.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - * - * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * NO LICENSE TO ANY ALACRITECH PATENT CLAIM IS GRANTED BY ANY COPYRIGHT - * LICENSE TO THIS OR OTHER SOFTWARE. THIS SOFTWARE MAY BE COVERED BY - * ALACRITECH PATENTS INCLUDING BUT NOT LIMITED TO U.S. PATENT NOS. 6,226,680, - * 6,247,060, 6,334,153, 6,389,479, 6,393,487, 6,427,171, 6,427,173 - * and 6,434,620. - * THIS SOFTWARE IS NOT SUBJECT TO THE GNU GENERAL PUBLIC LICENSE (GPL). - * - * The views and conclusions contained in the software and - * documentation are those of the authors and should not be - * interpreted as representing official policies, either - * expressed or implied, of Alacritech, Inc. - */ -#ifndef _SLIC_DUMP_H_ -#define _SLIC_DUMP_H_ - -#define DEBUG_SUCCESS 0 - -/*********************************************************************** - * - * Utility processor register locations - * - **********************************************************************/ -#define UTILITY_RESET 0x0 -#define UTILITY_ISP_ADDR 0x4 /* Interrupt status Pointer */ -#define UTILITY_ISR_ADDR 0x8 /* Interrupt status Register */ -#define UTILITY_ICR_ADDR 0xc /* Interrupt Control Register */ -#define UTILITY_CPR_ADDR 0x10 /* Command Pointer Register */ -#define UTILITY_DPR_ADDR 0x14 /* Data Pointer Register */ -#define UTILITY_DMP_TRQ 0x18 /* Dump queue onto ALU for analyser */ -#define UTILITY_UPP_ADDR 0x1c /* Bits 63-32 of cmd/data pointer */ - -/*********************************************************************** - * - * INIC status register bits - * - ***********************************************************************/ -#define SLIC_ISR_CC 0x10000000 /* Command complete - synchronous */ -#define SLIC_ISR_ERR 0x01000000 /* Command Error - synchronous */ -#define SLIC_ISR_CMD_MASK 0x11000000 /* Command status mask */ -#define SLIC_ISR_TPH 0x00080000 /* Transmit processor halted - async */ -#define SLIC_ISR_RPH 0x00040000 /* Receive processor halted - async */ - -/*********************************************************************** - * - * INIC Control register values - * - ***********************************************************************/ -#define SLIC_ICR_OFF 0 /* Interrupts disabled */ -#define SLIC_ICR_ON 1 /* Interrupts enabled */ -#define SLIC_ICR_MASK 2 /* Interrupts masked */ - -#define WRITE_DREG(reg, value, flush) \ -{ \ - writel((value), (reg)); \ - if ((flush)) { \ - mb(); \ - } \ -} - -/************************************************************************ - * - * Command Format - * - * Each command contains a command byte which is defined as follows: - * - * bits: 7-3 2 1-0 - * ---------------------------------------------- - * command Alt. Proc Processor - * - ************************************************************************/ - -/* - * Macro to create the command byte given the command, Alt. Proc, and - * Processor values. Note that the macro assumes that the values are - * preshifted. That is, the values for alt. proc are 0 for transmit and - * 4 for receive. - */ -#define COMMAND_BYTE(command, alt_proc, proc) ((command) | (alt_proc) | (proc)) - -/* - * Command values - */ -#define CMD_HALT 0x0 /* Send a halt to the INIC */ -#define CMD_RUN 0x8 /* Start the halted INIC */ -#define CMD_STEP 0x10 /* Single step the inic */ -#define CMD_BREAK 0x18 /* Set a breakpoint - 8 byte command */ -#define CMD_RESET_BREAK 0x20 /* Reset a breakpoint - 8 byte cmd */ -#define CMD_DUMP 0x28 /* Dump INIC memory - 8 byte command */ -#define CMD_LOAD 0x30 /* Load INIC memory - 8 byte command */ -#define CMD_MAP 0x38 /* Map out a ROM instruction - 8 BC */ -#define CMD_CAM_OPS 0x38 /* perform ops on specific CAM */ -#define CMD_XMT 0x40 /* Transmit frame */ -#define CMD_RCV 0x48 /* Receive frame */ - -/* - * Alt. Proc values - * - * When the proc value is set to the utility processor, the Alt. Proc - * specifies which processor handles the debugging. - */ -#define ALT_PROC_TRANSMIT 0x0 -#define ALT_PROC_RECEIVE 0x4 - -/* - * Proc values - */ -#define PROC_INVALID 0x0 -#define PROC_NONE 0x0 /* Gigabit use */ -#define PROC_TRANSMIT 0x1 -#define PROC_RECEIVE 0x2 -#define PROC_UTILITY 0x3 - -/****************************************************************** - * - * 8 byte command structure definitions - * - ******************************************************************/ - -/* - * Break and Reset Break command structure - */ -struct BREAK { - unsigned char command; /* Command word defined above */ - unsigned char resvd; - ushort count; /* Number of executions before break */ - u32 addr; /* Address of break point */ -}; - -/* - * Dump and Load command structure - */ -struct dump_cmd { - unsigned char cmd; /* Command word defined above */ - unsigned char desc; /* Descriptor values - defined below */ - ushort count; /* number of 4 byte words to be transferred */ - u32 addr; /* start address of dump or load */ -}; - -/* - * Receive or Transmit a frame. - */ -struct RCV_OR_XMT_FRAME { - unsigned char command; /* Command word defined above */ - unsigned char MacId; /* Mac ID of interface - transmit only */ - ushort count; /* Length of frame in bytes */ - u32 pad; /* not used */ -}; - -/* - * Values of desc field in DUMP_OR_LOAD structure - */ -#define DESC_RFILE 0x0 /* Register file */ -#define DESC_SRAM 0x1 /* SRAM */ -#define DESC_DRAM 0x2 /* DRAM */ -#define DESC_QUEUE 0x3 /* queues */ -#define DESC_REG 0x4 /* General registers (pc, status, etc) */ -#define DESC_SENSE 0x5 /* Sense register */ - -/* Descriptor field definitions for CMD_DUMP_CAM */ -#define DUMP_CAM_A 0 -#define DUMP_CAM_B 1 /* unused at present */ -#define DUMP_CAM_C 2 -#define DUMP_CAM_D 3 -#define SEARCH_CAM_A 4 -#define SEARCH_CAM_C 5 - -/* - * Map command to replace a command in ROM with a command in WCS - */ -struct MAP { - unsigned char command; /* Command word defined above */ - unsigned char not_used[3]; - ushort map_to; /* Instruction address in WCS */ - ushort map_out; /* Instruction address in ROM */ -}; - -/* - * Misc definitions - */ -#define SLIC_MAX_QUEUE 32 /* Total # of queues on the INIC (0-31)*/ -#define SLIC_4MAX_REG 512 /* Total # of 4-port file-registers */ -#define SLIC_1MAX_REG 384 /* Total # of file-registers */ -#define SLIC_GBMAX_REG 1024 /* Total # of Gbit file-registers */ -#define SLIC_NUM_REG 32 /* non-file-registers = NUM_REG in tm-simba.h */ -#define SLIC_GB_CAMA_SZE 32 -#define SLIC_GB_CAMB_SZE 16 -#define SLIC_GB_CAMAB_SZE 32 -#define SLIC_GB_CAMC_SZE 16 -#define SLIC_GB_CAMD_SZE 16 -#define SLIC_GB_CAMCD_SZE 32 - -/* - * Coredump header structure - */ -struct CORE_Q { - u32 queueOff; /* Offset of queue */ - u32 queuesize; /* size of queue */ -}; - -#define DRIVER_NAME_SIZE 32 - -struct sliccore_hdr { - unsigned char driver_version[DRIVER_NAME_SIZE]; /* Driver version string */ - u32 RcvRegOff; /* Offset of receive registers */ - u32 RcvRegsize; /* size of receive registers */ - u32 XmtRegOff; /* Offset of transmit registers */ - u32 XmtRegsize; /* size of transmit registers */ - u32 FileRegOff; /* Offset of register file */ - u32 FileRegsize; /* size of register file */ - u32 SramOff; /* Offset of Sram */ - u32 Sramsize; /* size of Sram */ - u32 DramOff; /* Offset of Dram */ - u32 Dramsize; /* size of Dram */ - CORE_Q queues[SLIC_MAX_QUEUE]; /* size and offsets of queues */ - u32 CamAMOff; /* Offset of CAM A contents */ - u32 CamASize; /* Size of Cam A */ - u32 CamBMOff; /* Offset of CAM B contents */ - u32 CamBSize; /* Size of Cam B */ - u32 CamCMOff; /* Offset of CAM C contents */ - u32 CamCSize; /* Size of Cam C */ - u32 CamDMOff; /* Offset of CAM D contents */ - u32 CamDSize; /* Size of Cam D */ -}; - -/* - * definitions needed for our kernel-mode gdb stub. - */ -/*********************************************************************** - * - * Definitions & Typedefs - * - **********************************************************************/ -#define BUFMAX 0x20000 /* 128k - size of input/output buffer */ -#define BUFMAXP2 5 /* 2**5 (32) 4K pages */ - -#define IOCTL_SIMBA_BREAK _IOW('s', 0, unsigned long) -/* #define IOCTL_SIMBA_INIT _IOW('s', 1, unsigned long) */ -#define IOCTL_SIMBA_KILL_TGT_PROC _IOW('s', 2, unsigned long) - -/*********************************************************************** - * - * Global variables - * - ***********************************************************************/ - -#define THREADRECEIVE 1 /* bit 0 of StoppedThreads */ -#define THREADTRANSMIT 2 /* bit 1 of StoppedThreads */ -#define THREADBOTH 3 /* bit 0 and 1.. */ - -#endif /* _SLIC_DUMP_H */ diff --git a/drivers/staging/slicoss/slichw.h b/drivers/staging/slicoss/slichw.h index d03e90b06753..6275d4529676 100644 --- a/drivers/staging/slicoss/slichw.h +++ b/drivers/staging/slicoss/slichw.h @@ -41,300 +41,286 @@ #ifndef __SLICHW_H__ #define __SLICHW_H__ -#define PCI_VENDOR_ID_ALACRITECH 0x139A -#define SLIC_1GB_DEVICE_ID 0x0005 -#define SLIC_2GB_DEVICE_ID 0x0007 /*Oasis Device ID */ +#define PCI_VENDOR_ID_ALACRITECH 0x139A +#define SLIC_1GB_DEVICE_ID 0x0005 +#define SLIC_2GB_DEVICE_ID 0x0007 /* Oasis Device ID */ -#define SLIC_1GB_CICADA_SUBSYS_ID 0x0008 +#define SLIC_1GB_CICADA_SUBSYS_ID 0x0008 -#define SLIC_NBR_MACS 4 +#define SLIC_NBR_MACS 4 -#define SLIC_RCVBUF_SIZE 2048 -#define SLIC_RCVBUF_HEADSIZE 34 -#define SLIC_RCVBUF_TAILSIZE 0 -#define SLIC_RCVBUF_DATASIZE (SLIC_RCVBUF_SIZE - (SLIC_RCVBUF_HEADSIZE +\ - SLIC_RCVBUF_TAILSIZE)) +#define SLIC_RCVBUF_SIZE 2048 +#define SLIC_RCVBUF_HEADSIZE 34 +#define SLIC_RCVBUF_TAILSIZE 0 +#define SLIC_RCVBUF_DATASIZE (SLIC_RCVBUF_SIZE - \ + (SLIC_RCVBUF_HEADSIZE + \ + SLIC_RCVBUF_TAILSIZE)) -#define VGBSTAT_XPERR 0x40000000 -#define VGBSTAT_XERRSHFT 25 -#define VGBSTAT_XCSERR 0x23 -#define VGBSTAT_XUFLOW 0x22 -#define VGBSTAT_XHLEN 0x20 -#define VGBSTAT_NETERR 0x01000000 -#define VGBSTAT_NERRSHFT 16 -#define VGBSTAT_NERRMSK 0x1ff -#define VGBSTAT_NCSERR 0x103 -#define VGBSTAT_NUFLOW 0x102 -#define VGBSTAT_NHLEN 0x100 -#define VGBSTAT_LNKERR 0x00000080 -#define VGBSTAT_LERRMSK 0xff -#define VGBSTAT_LDEARLY 0x86 -#define VGBSTAT_LBOFLO 0x85 -#define VGBSTAT_LCODERR 0x84 -#define VGBSTAT_LDBLNBL 0x83 -#define VGBSTAT_LCRCERR 0x82 -#define VGBSTAT_LOFLO 0x81 -#define VGBSTAT_LUFLO 0x80 -#define IRHDDR_FLEN_MSK 0x0000ffff -#define IRHDDR_SVALID 0x80000000 -#define IRHDDR_ERR 0x10000000 -#define VRHSTAT_802OE 0x80000000 -#define VRHSTAT_TPOFLO 0x10000000 -#define VRHSTATB_802UE 0x80000000 -#define VRHSTATB_RCVE 0x40000000 -#define VRHSTATB_BUFF 0x20000000 -#define VRHSTATB_CARRE 0x08000000 -#define VRHSTATB_LONGE 0x02000000 -#define VRHSTATB_PREA 0x01000000 -#define VRHSTATB_CRC 0x00800000 -#define VRHSTATB_DRBL 0x00400000 -#define VRHSTATB_CODE 0x00200000 -#define VRHSTATB_TPCSUM 0x00100000 -#define VRHSTATB_TPHLEN 0x00080000 -#define VRHSTATB_IPCSUM 0x00040000 -#define VRHSTATB_IPLERR 0x00020000 -#define VRHSTATB_IPHERR 0x00010000 -#define SLIC_MAX64_BCNT 23 -#define SLIC_MAX32_BCNT 26 -#define IHCMD_XMT_REQ 0x01 -#define IHFLG_IFSHFT 2 -#define SLIC_RSPBUF_SIZE 32 +#define VGBSTAT_XPERR 0x40000000 +#define VGBSTAT_XERRSHFT 25 +#define VGBSTAT_XCSERR 0x23 +#define VGBSTAT_XUFLOW 0x22 +#define VGBSTAT_XHLEN 0x20 +#define VGBSTAT_NETERR 0x01000000 +#define VGBSTAT_NERRSHFT 16 +#define VGBSTAT_NERRMSK 0x1ff +#define VGBSTAT_NCSERR 0x103 +#define VGBSTAT_NUFLOW 0x102 +#define VGBSTAT_NHLEN 0x100 +#define VGBSTAT_LNKERR 0x00000080 +#define VGBSTAT_LERRMSK 0xff +#define VGBSTAT_LDEARLY 0x86 +#define VGBSTAT_LBOFLO 0x85 +#define VGBSTAT_LCODERR 0x84 +#define VGBSTAT_LDBLNBL 0x83 +#define VGBSTAT_LCRCERR 0x82 +#define VGBSTAT_LOFLO 0x81 +#define VGBSTAT_LUFLO 0x80 +#define IRHDDR_FLEN_MSK 0x0000ffff +#define IRHDDR_SVALID 0x80000000 +#define IRHDDR_ERR 0x10000000 +#define VRHSTAT_802OE 0x80000000 +#define VRHSTAT_TPOFLO 0x10000000 +#define VRHSTATB_802UE 0x80000000 +#define VRHSTATB_RCVE 0x40000000 +#define VRHSTATB_BUFF 0x20000000 +#define VRHSTATB_CARRE 0x08000000 +#define VRHSTATB_LONGE 0x02000000 +#define VRHSTATB_PREA 0x01000000 +#define VRHSTATB_CRC 0x00800000 +#define VRHSTATB_DRBL 0x00400000 +#define VRHSTATB_CODE 0x00200000 +#define VRHSTATB_TPCSUM 0x00100000 +#define VRHSTATB_TPHLEN 0x00080000 +#define VRHSTATB_IPCSUM 0x00040000 +#define VRHSTATB_IPLERR 0x00020000 +#define VRHSTATB_IPHERR 0x00010000 +#define SLIC_MAX64_BCNT 23 +#define SLIC_MAX32_BCNT 26 +#define IHCMD_XMT_REQ 0x01 +#define IHFLG_IFSHFT 2 +#define SLIC_RSPBUF_SIZE 32 -#define SLIC_RESET_MAGIC 0xDEAD -#define ICR_INT_OFF 0 -#define ICR_INT_ON 1 -#define ICR_INT_MASK 2 +#define SLIC_RESET_MAGIC 0xDEAD +#define ICR_INT_OFF 0 +#define ICR_INT_ON 1 +#define ICR_INT_MASK 2 -#define ISR_ERR 0x80000000 -#define ISR_RCV 0x40000000 -#define ISR_CMD 0x20000000 -#define ISR_IO 0x60000000 -#define ISR_UPC 0x10000000 -#define ISR_LEVENT 0x08000000 -#define ISR_RMISS 0x02000000 -#define ISR_UPCERR 0x01000000 -#define ISR_XDROP 0x00800000 -#define ISR_UPCBSY 0x00020000 -#define ISR_EVMSK 0xffff0000 -#define ISR_PINGMASK 0x00700000 -#define ISR_PINGDSMASK 0x00710000 -#define ISR_UPCMASK 0x11000000 -#define SLIC_WCS_START 0x80000000 -#define SLIC_WCS_COMPARE 0x40000000 -#define SLIC_RCVWCS_BEGIN 0x40000000 -#define SLIC_RCVWCS_FINISH 0x80000000 -#define SLIC_PM_MAXPATTERNS 6 -#define SLIC_PM_PATTERNSIZE 128 -#define SLIC_PMCAPS_WAKEONLAN 0x00000001 -#define MIICR_REG_PCR 0x00000000 -#define MIICR_REG_4 0x00040000 -#define MIICR_REG_9 0x00090000 -#define MIICR_REG_16 0x00100000 -#define PCR_RESET 0x8000 -#define PCR_POWERDOWN 0x0800 -#define PCR_SPEED_100 0x2000 -#define PCR_SPEED_1000 0x0040 -#define PCR_AUTONEG 0x1000 -#define PCR_AUTONEG_RST 0x0200 -#define PCR_DUPLEX_FULL 0x0100 -#define PSR_LINKUP 0x0004 +#define ISR_ERR 0x80000000 +#define ISR_RCV 0x40000000 +#define ISR_CMD 0x20000000 +#define ISR_IO 0x60000000 +#define ISR_UPC 0x10000000 +#define ISR_LEVENT 0x08000000 +#define ISR_RMISS 0x02000000 +#define ISR_UPCERR 0x01000000 +#define ISR_XDROP 0x00800000 +#define ISR_UPCBSY 0x00020000 +#define ISR_EVMSK 0xffff0000 +#define ISR_PINGMASK 0x00700000 +#define ISR_PINGDSMASK 0x00710000 +#define ISR_UPCMASK 0x11000000 +#define SLIC_WCS_START 0x80000000 +#define SLIC_WCS_COMPARE 0x40000000 +#define SLIC_RCVWCS_BEGIN 0x40000000 +#define SLIC_RCVWCS_FINISH 0x80000000 +#define SLIC_PM_MAXPATTERNS 6 +#define SLIC_PM_PATTERNSIZE 128 +#define SLIC_PMCAPS_WAKEONLAN 0x00000001 +#define MIICR_REG_PCR 0x00000000 +#define MIICR_REG_4 0x00040000 +#define MIICR_REG_9 0x00090000 +#define MIICR_REG_16 0x00100000 +#define PCR_RESET 0x8000 +#define PCR_POWERDOWN 0x0800 +#define PCR_SPEED_100 0x2000 +#define PCR_SPEED_1000 0x0040 +#define PCR_AUTONEG 0x1000 +#define PCR_AUTONEG_RST 0x0200 +#define PCR_DUPLEX_FULL 0x0100 +#define PSR_LINKUP 0x0004 -#define PAR_ADV100FD 0x0100 -#define PAR_ADV100HD 0x0080 -#define PAR_ADV10FD 0x0040 -#define PAR_ADV10HD 0x0020 -#define PAR_ASYMPAUSE 0x0C00 -#define PAR_802_3 0x0001 +#define PAR_ADV100FD 0x0100 +#define PAR_ADV100HD 0x0080 +#define PAR_ADV10FD 0x0040 +#define PAR_ADV10HD 0x0020 +#define PAR_ASYMPAUSE 0x0C00 +#define PAR_802_3 0x0001 -#define PAR_ADV1000XFD 0x0020 -#define PAR_ADV1000XHD 0x0040 -#define PAR_ASYMPAUSE_FIBER 0x0180 +#define PAR_ADV1000XFD 0x0020 +#define PAR_ADV1000XHD 0x0040 +#define PAR_ASYMPAUSE_FIBER 0x0180 -#define PGC_ADV1000FD 0x0200 -#define PGC_ADV1000HD 0x0100 -#define SEEQ_LINKFAIL 0x4000 -#define SEEQ_SPEED 0x0080 -#define SEEQ_DUPLEX 0x0040 -#define TDK_DUPLEX 0x0800 -#define TDK_SPEED 0x0400 -#define MRV_REG16_XOVERON 0x0068 -#define MRV_REG16_XOVEROFF 0x0008 -#define MRV_SPEED_1000 0x8000 -#define MRV_SPEED_100 0x4000 -#define MRV_SPEED_10 0x0000 -#define MRV_FULLDUPLEX 0x2000 -#define MRV_LINKUP 0x0400 +#define PGC_ADV1000FD 0x0200 +#define PGC_ADV1000HD 0x0100 +#define SEEQ_LINKFAIL 0x4000 +#define SEEQ_SPEED 0x0080 +#define SEEQ_DUPLEX 0x0040 +#define TDK_DUPLEX 0x0800 +#define TDK_SPEED 0x0400 +#define MRV_REG16_XOVERON 0x0068 +#define MRV_REG16_XOVEROFF 0x0008 +#define MRV_SPEED_1000 0x8000 +#define MRV_SPEED_100 0x4000 +#define MRV_SPEED_10 0x0000 +#define MRV_FULLDUPLEX 0x2000 +#define MRV_LINKUP 0x0400 -#define GIG_LINKUP 0x0001 -#define GIG_FULLDUPLEX 0x0002 -#define GIG_SPEED_MASK 0x000C -#define GIG_SPEED_1000 0x0008 -#define GIG_SPEED_100 0x0004 -#define GIG_SPEED_10 0x0000 +#define GIG_LINKUP 0x0001 +#define GIG_FULLDUPLEX 0x0002 +#define GIG_SPEED_MASK 0x000C +#define GIG_SPEED_1000 0x0008 +#define GIG_SPEED_100 0x0004 +#define GIG_SPEED_10 0x0000 -#define MCR_RESET 0x80000000 -#define MCR_CRCEN 0x40000000 -#define MCR_FULLD 0x10000000 -#define MCR_PAD 0x02000000 -#define MCR_RETRYLATE 0x01000000 -#define MCR_BOL_SHIFT 21 -#define MCR_IPG1_SHIFT 14 -#define MCR_IPG2_SHIFT 7 -#define MCR_IPG3_SHIFT 0 -#define GMCR_RESET 0x80000000 -#define GMCR_GBIT 0x20000000 -#define GMCR_FULLD 0x10000000 -#define GMCR_GAPBB_SHIFT 14 -#define GMCR_GAPR1_SHIFT 7 -#define GMCR_GAPR2_SHIFT 0 -#define GMCR_GAPBB_1000 0x60 -#define GMCR_GAPR1_1000 0x2C -#define GMCR_GAPR2_1000 0x40 -#define GMCR_GAPBB_100 0x70 -#define GMCR_GAPR1_100 0x2C -#define GMCR_GAPR2_100 0x40 -#define XCR_RESET 0x80000000 -#define XCR_XMTEN 0x40000000 -#define XCR_PAUSEEN 0x20000000 -#define XCR_LOADRNG 0x10000000 -#define RCR_RESET 0x80000000 -#define RCR_RCVEN 0x40000000 -#define RCR_RCVALL 0x20000000 -#define RCR_RCVBAD 0x10000000 -#define RCR_CTLEN 0x08000000 -#define RCR_ADDRAEN 0x02000000 -#define GXCR_RESET 0x80000000 -#define GXCR_XMTEN 0x40000000 -#define GXCR_PAUSEEN 0x20000000 -#define GRCR_RESET 0x80000000 -#define GRCR_RCVEN 0x40000000 -#define GRCR_RCVALL 0x20000000 -#define GRCR_RCVBAD 0x10000000 -#define GRCR_CTLEN 0x08000000 -#define GRCR_ADDRAEN 0x02000000 -#define GRCR_HASHSIZE_SHIFT 17 -#define GRCR_HASHSIZE 14 +#define MCR_RESET 0x80000000 +#define MCR_CRCEN 0x40000000 +#define MCR_FULLD 0x10000000 +#define MCR_PAD 0x02000000 +#define MCR_RETRYLATE 0x01000000 +#define MCR_BOL_SHIFT 21 +#define MCR_IPG1_SHIFT 14 +#define MCR_IPG2_SHIFT 7 +#define MCR_IPG3_SHIFT 0 +#define GMCR_RESET 0x80000000 +#define GMCR_GBIT 0x20000000 +#define GMCR_FULLD 0x10000000 +#define GMCR_GAPBB_SHIFT 14 +#define GMCR_GAPR1_SHIFT 7 +#define GMCR_GAPR2_SHIFT 0 +#define GMCR_GAPBB_1000 0x60 +#define GMCR_GAPR1_1000 0x2C +#define GMCR_GAPR2_1000 0x40 +#define GMCR_GAPBB_100 0x70 +#define GMCR_GAPR1_100 0x2C +#define GMCR_GAPR2_100 0x40 +#define XCR_RESET 0x80000000 +#define XCR_XMTEN 0x40000000 +#define XCR_PAUSEEN 0x20000000 +#define XCR_LOADRNG 0x10000000 +#define RCR_RESET 0x80000000 +#define RCR_RCVEN 0x40000000 +#define RCR_RCVALL 0x20000000 +#define RCR_RCVBAD 0x10000000 +#define RCR_CTLEN 0x08000000 +#define RCR_ADDRAEN 0x02000000 +#define GXCR_RESET 0x80000000 +#define GXCR_XMTEN 0x40000000 +#define GXCR_PAUSEEN 0x20000000 +#define GRCR_RESET 0x80000000 +#define GRCR_RCVEN 0x40000000 +#define GRCR_RCVALL 0x20000000 +#define GRCR_RCVBAD 0x10000000 +#define GRCR_CTLEN 0x08000000 +#define GRCR_ADDRAEN 0x02000000 +#define GRCR_HASHSIZE_SHIFT 17 +#define GRCR_HASHSIZE 14 -#define SLIC_EEPROM_ID 0xA5A5 -#define SLIC_SRAM_SIZE2GB (64 * 1024) -#define SLIC_SRAM_SIZE1GB (32 * 1024) -#define SLIC_HOSTID_DEFAULT 0xFFFF /* uninitialized hostid */ -#define SLIC_NBR_MACS 4 - -#ifndef FALSE -#define FALSE 0 -#else -#undef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#else -#undef TRUE -#define TRUE 1 -#endif +#define SLIC_EEPROM_ID 0xA5A5 +#define SLIC_SRAM_SIZE2GB (64 * 1024) +#define SLIC_SRAM_SIZE1GB (32 * 1024) +#define SLIC_HOSTID_DEFAULT 0xFFFF /* uninitialized hostid */ +#define SLIC_NBR_MACS 4 struct slic_rcvbuf { - unsigned char pad1[6]; - ushort pad2; - u32 pad3; - u32 pad4; - u32 buffer; - u32 length; - u32 status; - u32 pad5; - ushort pad6; - unsigned char data[SLIC_RCVBUF_DATASIZE]; + u8 pad1[6]; + u16 pad2; + u32 pad3; + u32 pad4; + u32 buffer; + u32 length; + u32 status; + u32 pad5; + u16 pad6; + u8 data[SLIC_RCVBUF_DATASIZE]; }; - struct slic_hddr_wds { - union { - struct { - u32 frame_status; - u32 frame_status_b; - u32 time_stamp; - u32 checksum; - } hdrs_14port; - struct { - u32 frame_status; - ushort ByteCnt; - ushort TpChksum; - ushort CtxHash; - ushort MacHash; - u32 BufLnk; - } hdrs_gbit; - } u0; +struct slic_hddr_wds { + union { + struct { + u32 frame_status; + u32 frame_status_b; + u32 time_stamp; + u32 checksum; + } hdrs_14port; + struct { + u32 frame_status; + u16 ByteCnt; + u16 TpChksum; + u16 CtxHash; + u16 MacHash; + u32 BufLnk; + } hdrs_gbit; + } u0; }; -#define frame_status14 u0.hdrs_14port.frame_status -#define frame_status_b14 u0.hdrs_14port.frame_status_b -#define frame_statusGB u0.hdrs_gbit.frame_status +#define frame_status14 u0.hdrs_14port.frame_status +#define frame_status_b14 u0.hdrs_14port.frame_status_b +#define frame_statusGB u0.hdrs_gbit.frame_status struct slic_host64sg { - u32 paddrl; - u32 paddrh; - u32 length; + u32 paddrl; + u32 paddrh; + u32 length; }; struct slic_host64_cmd { - u32 hosthandle; - u32 RSVD; - unsigned char command; - unsigned char flags; - union { - ushort rsv1; - ushort rsv2; - } u0; - union { - struct { - u32 totlen; - struct slic_host64sg bufs[SLIC_MAX64_BCNT]; - } slic_buffers; - } u; + u32 hosthandle; + u32 RSVD; + u8 command; + u8 flags; + union { + u16 rsv1; + u16 rsv2; + } u0; + union { + struct { + u32 totlen; + struct slic_host64sg bufs[SLIC_MAX64_BCNT]; + } slic_buffers; + } u; }; struct slic_rspbuf { - u32 hosthandle; - u32 pad0; - u32 pad1; - u32 status; - u32 pad2[4]; - + u32 hosthandle; + u32 pad0; + u32 pad1; + u32 status; + u32 pad2[4]; }; struct slic_regs { - u32 slic_reset; /* Reset Register */ + u32 slic_reset; /* Reset Register */ u32 pad0; - u32 slic_icr; /* Interrupt Control Register */ + u32 slic_icr; /* Interrupt Control Register */ u32 pad2; #define SLIC_ICR 0x0008 - u32 slic_isp; /* Interrupt status pointer */ + u32 slic_isp; /* Interrupt status pointer */ u32 pad1; #define SLIC_ISP 0x0010 - u32 slic_isr; /* Interrupt status */ + u32 slic_isr; /* Interrupt status */ u32 pad3; #define SLIC_ISR 0x0018 - u32 slic_hbar; /* Header buffer address reg */ - u32 pad4; + u32 slic_hbar; /* Header buffer address reg */ + u32 pad4; /* 31-8 - phy addr of set of contiguous hdr buffers 7-0 - number of buffers passed Buffers are 256 bytes long on 256-byte boundaries. */ #define SLIC_HBAR 0x0020 #define SLIC_HBAR_CNT_MSK 0x000000FF - u32 slic_dbar; /* Data buffer handle & address reg */ - u32 pad5; + u32 slic_dbar; /* Data buffer handle & address reg */ + u32 pad5; /* 4 sets of registers; Buffers are 2K bytes long 2 per 4K page. */ #define SLIC_DBAR 0x0028 #define SLIC_DBAR_SIZE 2048 - u32 slic_cbar; /* Xmt Cmd buf addr regs.*/ + u32 slic_cbar; /* Xmt Cmd buf addr regs.*/ /* 1 per XMT interface 31-5 - phy addr of host command buffer 4-0 - length of cmd in multiples of 32 bytes @@ -343,13 +329,13 @@ struct slic_regs { #define SLIC_CBAR_LEN_MSK 0x0000001F #define SLIC_CBAR_ALIGN 0x00000020 - u32 slic_wcs; /* write control store*/ + u32 slic_wcs; /* write control store*/ #define SLIC_WCS 0x0034 #define SLIC_WCS_START 0x80000000 /*Start the SLIC (Jump to WCS)*/ #define SLIC_WCS_COMPARE 0x40000000 /* Compare with value in WCS*/ - u32 slic_rbar; /* Response buffer address reg.*/ - u32 pad7; + u32 slic_rbar; /* Response buffer address reg.*/ + u32 pad7; /*31-8 - phy addr of set of contiguous response buffers 7-0 - number of buffers passed Buffers are 32 bytes long on 32-byte boundaries.*/ @@ -357,215 +343,214 @@ struct slic_regs { #define SLIC_RBAR_CNT_MSK 0x000000FF #define SLIC_RBAR_SIZE 32 - u32 slic_stats; /* read statistics (UPR) */ - u32 pad8; + u32 slic_stats; /* read statistics (UPR) */ + u32 pad8; #define SLIC_RSTAT 0x0040 - u32 slic_rlsr; /* read link status */ - u32 pad9; + u32 slic_rlsr; /* read link status */ + u32 pad9; #define SLIC_LSTAT 0x0048 - u32 slic_wmcfg; /* Write Mac Config */ - u32 pad10; + u32 slic_wmcfg; /* Write Mac Config */ + u32 pad10; #define SLIC_WMCFG 0x0050 - u32 slic_wphy; /* Write phy register */ - u32 pad11; + u32 slic_wphy; /* Write phy register */ + u32 pad11; #define SLIC_WPHY 0x0058 - u32 slic_rcbar; /*Rcv Cmd buf addr reg*/ - u32 pad12; + u32 slic_rcbar; /* Rcv Cmd buf addr reg */ + u32 pad12; #define SLIC_RCBAR 0x0060 - u32 slic_rconfig; /* Read SLIC Config*/ - u32 pad13; + u32 slic_rconfig; /* Read SLIC Config*/ + u32 pad13; #define SLIC_RCONFIG 0x0068 - u32 slic_intagg; /* Interrupt aggregation time*/ - u32 pad14; + u32 slic_intagg; /* Interrupt aggregation time */ + u32 pad14; #define SLIC_INTAGG 0x0070 - u32 slic_wxcfg; /* Write XMIT config reg*/ - u32 pad16; + u32 slic_wxcfg; /* Write XMIT config reg*/ + u32 pad16; #define SLIC_WXCFG 0x0078 - u32 slic_wrcfg; /* Write RCV config reg*/ - u32 pad17; + u32 slic_wrcfg; /* Write RCV config reg*/ + u32 pad17; #define SLIC_WRCFG 0x0080 - u32 slic_wraddral; /* Write rcv addr a low*/ - u32 pad18; + u32 slic_wraddral; /* Write rcv addr a low*/ + u32 pad18; #define SLIC_WRADDRAL 0x0088 - u32 slic_wraddrah; /* Write rcv addr a high*/ - u32 pad19; + u32 slic_wraddrah; /* Write rcv addr a high*/ + u32 pad19; #define SLIC_WRADDRAH 0x0090 - u32 slic_wraddrbl; /* Write rcv addr b low*/ - u32 pad20; + u32 slic_wraddrbl; /* Write rcv addr b low*/ + u32 pad20; #define SLIC_WRADDRBL 0x0098 - u32 slic_wraddrbh; /* Write rcv addr b high*/ + u32 slic_wraddrbh; /* Write rcv addr b high*/ u32 pad21; #define SLIC_WRADDRBH 0x00a0 - u32 slic_mcastlow; /* Low bits of mcast mask*/ + u32 slic_mcastlow; /* Low bits of mcast mask*/ u32 pad22; #define SLIC_MCASTLOW 0x00a8 - u32 slic_mcasthigh; /* High bits of mcast mask*/ + u32 slic_mcasthigh; /* High bits of mcast mask*/ u32 pad23; #define SLIC_MCASTHIGH 0x00b0 - u32 slic_ping; /* Ping the card*/ - u32 pad24; + u32 slic_ping; /* Ping the card*/ + u32 pad24; #define SLIC_PING 0x00b8 - u32 slic_dump_cmd; /* Dump command */ - u32 pad25; + u32 slic_dump_cmd; /* Dump command */ + u32 pad25; #define SLIC_DUMP_CMD 0x00c0 - u32 slic_dump_data; /* Dump data pointer */ - u32 pad26; + u32 slic_dump_data; /* Dump data pointer */ + u32 pad26; #define SLIC_DUMP_DATA 0x00c8 u32 slic_pcistatus; /* Read card's pci_status register */ - u32 pad27; + u32 pad27; #define SLIC_PCISTATUS 0x00d0 - u32 slic_wrhostid; /* Write hostid field */ + u32 slic_wrhostid; /* Write hostid field */ u32 pad28; #define SLIC_WRHOSTID 0x00d8 #define SLIC_RDHOSTID_1GB 0x1554 #define SLIC_RDHOSTID_2GB 0x1554 u32 slic_low_power; /* Put card in a low power state */ - u32 pad29; + u32 pad29; #define SLIC_LOW_POWER 0x00e0 u32 slic_quiesce; /* force slic into quiescent state - before soft reset */ - u32 pad30; + before soft reset */ + u32 pad30; #define SLIC_QUIESCE 0x00e8 - u32 slic_reset_iface; /* reset interface queues */ - u32 pad31; + u32 slic_reset_iface;/* reset interface queues */ + u32 pad31; #define SLIC_RESET_IFACE 0x00f0 - u32 slic_addr_upper; /* Bits 63-32 for host i/f addrs */ - u32 pad32; + u32 slic_addr_upper;/* Bits 63-32 for host i/f addrs */ + u32 pad32; #define SLIC_ADDR_UPPER 0x00f8 /*Register is only written when it has changed*/ - u32 slic_hbar64; /* 64 bit Header buffer address reg */ - u32 pad33; + u32 slic_hbar64; /* 64 bit Header buffer address reg */ + u32 pad33; #define SLIC_HBAR64 0x0100 - u32 slic_dbar64; /* 64 bit Data buffer handle & address reg */ - u32 pad34; + u32 slic_dbar64; /* 64 bit Data buffer handle & address reg */ + u32 pad34; #define SLIC_DBAR64 0x0108 - u32 slic_cbar64; /* 64 bit Xmt Cmd buf addr regs. */ - u32 pad35; + u32 slic_cbar64; /* 64 bit Xmt Cmd buf addr regs. */ + u32 pad35; #define SLIC_CBAR64 0x0110 - u32 slic_rbar64; /* 64 bit Response buffer address reg.*/ - u32 pad36; + u32 slic_rbar64; /* 64 bit Response buffer address reg.*/ + u32 pad36; #define SLIC_RBAR64 0x0118 - u32 slic_rcbar64; /* 64 bit Rcv Cmd buf addr reg*/ - u32 pad37; + u32 slic_rcbar64; /* 64 bit Rcv Cmd buf addr reg*/ + u32 pad37; #define SLIC_RCBAR64 0x0120 - u32 slic_stats64; /*read statistics (64 bit UPR)*/ - u32 pad38; + u32 slic_stats64; /* read statistics (64 bit UPR) */ + u32 pad38; #define SLIC_RSTAT64 0x0128 u32 slic_rcv_wcs; /*Download Gigabit RCV sequencer ucode*/ - u32 pad39; + u32 pad39; #define SLIC_RCV_WCS 0x0130 #define SLIC_RCVWCS_BEGIN 0x40000000 #define SLIC_RCVWCS_FINISH 0x80000000 - u32 slic_wrvlanid; /* Write VlanId field */ - u32 pad40; + u32 slic_wrvlanid; /* Write VlanId field */ + u32 pad40; #define SLIC_WRVLANID 0x0138 - u32 slic_read_xf_info; /* Read Transformer info */ - u32 pad41; + u32 slic_read_xf_info; /* Read Transformer info */ + u32 pad41; #define SLIC_READ_XF_INFO 0x0140 - u32 slic_write_xf_info; /* Write Transformer info */ - u32 pad42; + u32 slic_write_xf_info; /* Write Transformer info */ + u32 pad42; #define SLIC_WRITE_XF_INFO 0x0148 - u32 RSVD1; /* TOE Only */ - u32 pad43; + u32 RSVD1; /* TOE Only */ + u32 pad43; - u32 RSVD2; /* TOE Only */ - u32 pad44; + u32 RSVD2; /* TOE Only */ + u32 pad44; - u32 RSVD3; /* TOE Only */ - u32 pad45; + u32 RSVD3; /* TOE Only */ + u32 pad45; - u32 RSVD4; /* TOE Only */ - u32 pad46; + u32 RSVD4; /* TOE Only */ + u32 pad46; u32 slic_ticks_per_sec; /* Write card ticks per second */ - u32 pad47; + u32 pad47; #define SLIC_TICKS_PER_SEC 0x0170 - }; enum UPR_REQUEST { - SLIC_UPR_STATS, - SLIC_UPR_RLSR, - SLIC_UPR_WCFG, - SLIC_UPR_RCONFIG, - SLIC_UPR_RPHY, - SLIC_UPR_ENLB, - SLIC_UPR_ENCT, - SLIC_UPR_PDWN, - SLIC_UPR_PING, - SLIC_UPR_DUMP, + SLIC_UPR_STATS, + SLIC_UPR_RLSR, + SLIC_UPR_WCFG, + SLIC_UPR_RCONFIG, + SLIC_UPR_RPHY, + SLIC_UPR_ENLB, + SLIC_UPR_ENCT, + SLIC_UPR_PDWN, + SLIC_UPR_PING, + SLIC_UPR_DUMP, }; struct inicpm_wakepattern { - u32 patternlength; - unsigned char pattern[SLIC_PM_PATTERNSIZE]; - unsigned char mask[SLIC_PM_PATTERNSIZE]; + u32 patternlength; + u8 pattern[SLIC_PM_PATTERNSIZE]; + u8 mask[SLIC_PM_PATTERNSIZE]; }; struct inicpm_state { - u32 powercaps; - u32 powerstate; - u32 wake_linkstatus; - u32 wake_magicpacket; - u32 wake_framepattern; - struct inicpm_wakepattern wakepattern[SLIC_PM_MAXPATTERNS]; + u32 powercaps; + u32 powerstate; + u32 wake_linkstatus; + u32 wake_magicpacket; + u32 wake_framepattern; + struct inicpm_wakepattern wakepattern[SLIC_PM_MAXPATTERNS]; }; struct slicpm_packet_pattern { - u32 priority; - u32 reserved; - u32 masksize; - u32 patternoffset; - u32 patternsize; - u32 patternflags; + u32 priority; + u32 reserved; + u32 masksize; + u32 patternoffset; + u32 patternsize; + u32 patternflags; }; enum slicpm_power_state { - slicpm_state_unspecified = 0, - slicpm_state_d0, - slicpm_state_d1, - slicpm_state_d2, - slicpm_state_d3, - slicpm_state_maximum + slicpm_state_unspecified = 0, + slicpm_state_d0, + slicpm_state_d1, + slicpm_state_d2, + slicpm_state_d3, + slicpm_state_maximum }; struct slicpm_wakeup_capabilities { - enum slicpm_power_state min_magic_packet_wakeup; - enum slicpm_power_state min_pattern_wakeup; - enum slicpm_power_state min_link_change_wakeup; + enum slicpm_power_state min_magic_packet_wakeup; + enum slicpm_power_state min_pattern_wakeup; + enum slicpm_power_state min_link_change_wakeup; }; struct slic_pnp_capabilities { @@ -612,136 +597,135 @@ struct rcv_statsgb { }; struct slic_stats { - union { - struct { - struct xmt_stats xmt100; - struct rcv_stats rcv100; - } stats_100; - struct { - struct xmt_statsgb xmtGB; - struct rcv_statsgb rcvGB; - } stats_GB; - } u; + union { + struct { + struct xmt_stats xmt100; + struct rcv_stats rcv100; + } stats_100; + struct { + struct xmt_statsgb xmtGB; + struct rcv_statsgb rcvGB; + } stats_GB; + } u; }; -#define xmit_tcp_segs100 u.stats_100.xmt100.xmit_tcp_segs -#define xmit_tcp_bytes100 u.stats_100.xmt100.xmit_tcp_bytes -#define xmit_bytes100 u.stats_100.xmt100.xmit_bytes -#define xmit_collisions100 u.stats_100.xmt100.xmit_collisions -#define xmit_unicasts100 u.stats_100.xmt100.xmit_unicasts -#define xmit_other_error100 u.stats_100.xmt100.xmit_other_error -#define xmit_excess_collisions100 u.stats_100.xmt100.xmit_excess_collisions -#define rcv_tcp_segs100 u.stats_100.rcv100.rcv_tcp_segs -#define rcv_tcp_bytes100 u.stats_100.rcv100.rcv_tcp_bytes -#define rcv_bytes100 u.stats_100.rcv100.rcv_bytes -#define rcv_unicasts100 u.stats_100.rcv100.rcv_unicasts -#define rcv_other_error100 u.stats_100.rcv100.rcv_other_error -#define rcv_drops100 u.stats_100.rcv100.rcv_drops -#define xmit_tcp_segs_gb u.stats_GB.xmtGB.xmit_tcp_segs -#define xmit_tcp_bytes_gb u.stats_GB.xmtGB.xmit_tcp_bytes -#define xmit_bytes_gb u.stats_GB.xmtGB.xmit_bytes -#define xmit_collisions_gb u.stats_GB.xmtGB.xmit_collisions -#define xmit_unicasts_gb u.stats_GB.xmtGB.xmit_unicasts -#define xmit_other_error_gb u.stats_GB.xmtGB.xmit_other_error -#define xmit_excess_collisions_gb u.stats_GB.xmtGB.xmit_excess_collisions +#define xmit_tcp_segs100 u.stats_100.xmt100.xmit_tcp_segs +#define xmit_tcp_bytes100 u.stats_100.xmt100.xmit_tcp_bytes +#define xmit_bytes100 u.stats_100.xmt100.xmit_bytes +#define xmit_collisions100 u.stats_100.xmt100.xmit_collisions +#define xmit_unicasts100 u.stats_100.xmt100.xmit_unicasts +#define xmit_other_error100 u.stats_100.xmt100.xmit_other_error +#define xmit_excess_collisions100 u.stats_100.xmt100.xmit_excess_collisions +#define rcv_tcp_segs100 u.stats_100.rcv100.rcv_tcp_segs +#define rcv_tcp_bytes100 u.stats_100.rcv100.rcv_tcp_bytes +#define rcv_bytes100 u.stats_100.rcv100.rcv_bytes +#define rcv_unicasts100 u.stats_100.rcv100.rcv_unicasts +#define rcv_other_error100 u.stats_100.rcv100.rcv_other_error +#define rcv_drops100 u.stats_100.rcv100.rcv_drops +#define xmit_tcp_segs_gb u.stats_GB.xmtGB.xmit_tcp_segs +#define xmit_tcp_bytes_gb u.stats_GB.xmtGB.xmit_tcp_bytes +#define xmit_bytes_gb u.stats_GB.xmtGB.xmit_bytes +#define xmit_collisions_gb u.stats_GB.xmtGB.xmit_collisions +#define xmit_unicasts_gb u.stats_GB.xmtGB.xmit_unicasts +#define xmit_other_error_gb u.stats_GB.xmtGB.xmit_other_error +#define xmit_excess_collisions_gb u.stats_GB.xmtGB.xmit_excess_collisions -#define rcv_tcp_segs_gb u.stats_GB.rcvGB.rcv_tcp_segs -#define rcv_tcp_bytes_gb u.stats_GB.rcvGB.rcv_tcp_bytes -#define rcv_bytes_gb u.stats_GB.rcvGB.rcv_bytes -#define rcv_unicasts_gb u.stats_GB.rcvGB.rcv_unicasts -#define rcv_other_error_gb u.stats_GB.rcvGB.rcv_other_error -#define rcv_drops_gb u.stats_GB.rcvGB.rcv_drops +#define rcv_tcp_segs_gb u.stats_GB.rcvGB.rcv_tcp_segs +#define rcv_tcp_bytes_gb u.stats_GB.rcvGB.rcv_tcp_bytes +#define rcv_bytes_gb u.stats_GB.rcvGB.rcv_bytes +#define rcv_unicasts_gb u.stats_GB.rcvGB.rcv_unicasts +#define rcv_other_error_gb u.stats_GB.rcvGB.rcv_other_error +#define rcv_drops_gb u.stats_GB.rcvGB.rcv_drops struct slic_config_mac { - unsigned char macaddrA[6]; + u8 macaddrA[6]; }; -#define ATK_FRU_FORMAT 0x00 -#define VENDOR1_FRU_FORMAT 0x01 -#define VENDOR2_FRU_FORMAT 0x02 -#define VENDOR3_FRU_FORMAT 0x03 -#define VENDOR4_FRU_FORMAT 0x04 -#define NO_FRU_FORMAT 0xFF +#define ATK_FRU_FORMAT 0x00 +#define VENDOR1_FRU_FORMAT 0x01 +#define VENDOR2_FRU_FORMAT 0x02 +#define VENDOR3_FRU_FORMAT 0x03 +#define VENDOR4_FRU_FORMAT 0x04 +#define NO_FRU_FORMAT 0xFF struct atk_fru { - unsigned char assembly[6]; - unsigned char revision[2]; - unsigned char serial[14]; - unsigned char pad[3]; + u8 assembly[6]; + u8 revision[2]; + u8 serial[14]; + u8 pad[3]; }; struct vendor1_fru { - unsigned char commodity; - unsigned char assembly[4]; - unsigned char revision[2]; - unsigned char supplier[2]; - unsigned char date[2]; - unsigned char sequence[3]; - unsigned char pad[13]; + u8 commodity; + u8 assembly[4]; + u8 revision[2]; + u8 supplier[2]; + u8 date[2]; + u8 sequence[3]; + u8 pad[13]; }; struct vendor2_fru { - unsigned char part[8]; - unsigned char supplier[5]; - unsigned char date[3]; - unsigned char sequence[4]; - unsigned char pad[7]; + u8 part[8]; + u8 supplier[5]; + u8 date[3]; + u8 sequence[4]; + u8 pad[7]; }; struct vendor3_fru { - unsigned char assembly[6]; - unsigned char revision[2]; - unsigned char serial[14]; - unsigned char pad[3]; + u8 assembly[6]; + u8 revision[2]; + u8 serial[14]; + u8 pad[3]; }; struct vendor4_fru { - unsigned char number[8]; - unsigned char part[8]; - unsigned char version[8]; - unsigned char pad[3]; + u8 number[8]; + u8 part[8]; + u8 version[8]; + u8 pad[3]; }; union oemfru { - struct vendor1_fru vendor1_fru; - struct vendor2_fru vendor2_fru; - struct vendor3_fru vendor3_fru; - struct vendor4_fru vendor4_fru; + struct vendor1_fru vendor1_fru; + struct vendor2_fru vendor2_fru; + struct vendor3_fru vendor3_fru; + struct vendor4_fru vendor4_fru; }; /* - SLIC EEPROM structure for Mojave -*/ + * SLIC EEPROM structure for Mojave + */ struct slic_eeprom { - ushort Id; /* 00 EEPROM/FLASH Magic code 'A5A5'*/ - ushort EecodeSize; /* 01 Size of EEPROM Codes (bytes * 4)*/ - ushort FlashSize; /* 02 Flash size */ - ushort EepromSize; /* 03 EEPROM Size */ - ushort VendorId; /* 04 Vendor ID */ - ushort DeviceId; /* 05 Device ID */ - unsigned char RevisionId; /* 06 Revision ID */ - unsigned char ClassCode[3]; /* 07 Class Code */ - unsigned char DbgIntPin; /* 08 Debug Interrupt pin */ - unsigned char NetIntPin0; /* Network Interrupt Pin */ - unsigned char MinGrant; /* 09 Minimum grant */ - unsigned char MaxLat; /* Maximum Latency */ - ushort PciStatus; /* 10 PCI Status */ - ushort SubSysVId; /* 11 Subsystem Vendor Id */ - ushort SubSysId; /* 12 Subsystem ID */ - ushort DbgDevId; /* 13 Debug Device Id */ - ushort DramRomFn; /* 14 Dram/Rom function */ - ushort DSize2Pci; /* 15 DRAM size to PCI (bytes * 64K) */ - ushort RSize2Pci; /* 16 ROM extension size to PCI (bytes * 4k) */ - unsigned char NetIntPin1;/* 17 Network Interface Pin 1 + u16 Id; /* 00 EEPROM/FLASH Magic code 'A5A5'*/ + u16 EecodeSize; /* 01 Size of EEPROM Codes (bytes * 4)*/ + u16 FlashSize; /* 02 Flash size */ + u16 EepromSize; /* 03 EEPROM Size */ + u16 VendorId; /* 04 Vendor ID */ + u16 DeviceId; /* 05 Device ID */ + u8 RevisionId; /* 06 Revision ID */ + u8 ClassCode[3]; /* 07 Class Code */ + u8 DbgIntPin; /* 08 Debug Interrupt pin */ + u8 NetIntPin0; /* Network Interrupt Pin */ + u8 MinGrant; /* 09 Minimum grant */ + u8 MaxLat; /* Maximum Latency */ + u16 PciStatus; /* 10 PCI Status */ + u16 SubSysVId; /* 11 Subsystem Vendor Id */ + u16 SubSysId; /* 12 Subsystem ID */ + u16 DbgDevId; /* 13 Debug Device Id */ + u16 DramRomFn; /* 14 Dram/Rom function */ + u16 DSize2Pci; /* 15 DRAM size to PCI (bytes * 64K) */ + u16 RSize2Pci; /* 16 ROM extension size to PCI (bytes * 4k) */ + u8 NetIntPin1; /* 17 Network Interface Pin 1 (simba/leone only) */ - unsigned char NetIntPin2; /*Network Interface Pin 2 (simba/leone only)*/ + u8 NetIntPin2; /* Network Interface Pin 2 (simba/leone only)*/ union { - unsigned char NetIntPin3;/*18 Network Interface Pin 3 - (simba only)*/ - unsigned char FreeTime;/*FreeTime setting (leone/mojave only) */ + u8 NetIntPin3; /* 18 Network Interface Pin 3 (simba only) */ + u8 FreeTime; /* FreeTime setting (leone/mojave only) */ } u1; - unsigned char TBIctl; /* 10-bit interface control (Mojave only) */ - ushort DramSize; /* 19 DRAM size (bytes * 64k) */ + u8 TBIctl; /* 10-bit interface control (Mojave only) */ + u16 DramSize; /* 19 DRAM size (bytes * 64k) */ union { struct { /* Mac Interface Specific portions */ @@ -750,67 +734,64 @@ struct slic_eeprom { struct { /* use above struct for MAC access */ struct slic_config_mac pad[SLIC_NBR_MACS - 1]; - ushort DeviceId2; /* Device ID for 2nd - PCI function */ - unsigned char IntPin2; /* Interrupt pin for - 2nd PCI function */ - unsigned char ClassCode2[3]; /* Class Code for 2nd - PCI function */ + u16 DeviceId2; /* Device ID for 2nd PCI function */ + u8 IntPin2; /* Interrupt pin for 2nd PCI function */ + u8 ClassCode2[3]; /* Class Code for 2nd PCI function */ } mojave; /* 2nd function access for gigabit board */ } u2; - ushort CfgByte6; /* Config Byte 6 */ - ushort PMECapab; /* Power Mgment capabilities */ - ushort NwClkCtrls; /* NetworkClockControls */ - unsigned char FruFormat; /* Alacritech FRU format type */ - struct atk_fru AtkFru; /* Alacritech FRU information */ - unsigned char OemFruFormat; /* optional OEM FRU format type */ - union oemfru OemFru; /* optional OEM FRU information */ - unsigned char Pad[4]; /* Pad to 128 bytes - includes 2 cksum bytes - *(if OEM FRU info exists) and two unusable + u16 CfgByte6; /* Config Byte 6 */ + u16 PMECapab; /* Power Mgment capabilities */ + u16 NwClkCtrls; /* NetworkClockControls */ + u8 FruFormat; /* Alacritech FRU format type */ + struct atk_fru AtkFru; /* Alacritech FRU information */ + u8 OemFruFormat; /* optional OEM FRU format type */ + union oemfru OemFru; /* optional OEM FRU information */ + u8 Pad[4]; /* Pad to 128 bytes - includes 2 cksum bytes + * (if OEM FRU info exists) and two unusable * bytes at the end */ }; /* SLIC EEPROM structure for Oasis */ struct oslic_eeprom { - ushort Id; /* 00 EEPROM/FLASH Magic code 'A5A5' */ - ushort EecodeSize; /* 01 Size of EEPROM Codes (bytes * 4)*/ - ushort FlashConfig0; /* 02 Flash Config for SPI device 0 */ - ushort FlashConfig1; /* 03 Flash Config for SPI device 1 */ - ushort VendorId; /* 04 Vendor ID */ - ushort DeviceId; /* 05 Device ID (function 0) */ - unsigned char RevisionId; /* 06 Revision ID */ - unsigned char ClassCode[3]; /* 07 Class Code for PCI function 0 */ - unsigned char IntPin1; /* 08 Interrupt pin for PCI function 1*/ - unsigned char ClassCode2[3]; /* 09 Class Code for PCI function 1 */ - unsigned char IntPin2; /* 10 Interrupt pin for PCI function 2*/ - unsigned char IntPin0; /* Interrupt pin for PCI function 0*/ - unsigned char MinGrant; /* 11 Minimum grant */ - unsigned char MaxLat; /* Maximum Latency */ - ushort SubSysVId; /* 12 Subsystem Vendor Id */ - ushort SubSysId; /* 13 Subsystem ID */ - ushort FlashSize; /* 14 Flash size (bytes / 4K) */ - ushort DSize2Pci; /* 15 DRAM size to PCI (bytes / 64K) */ - ushort RSize2Pci; /* 16 Flash (ROM extension) size to - PCI (bytes / 4K) */ - ushort DeviceId1; /* 17 Device Id (function 1) */ - ushort DeviceId2; /* 18 Device Id (function 2) */ - ushort CfgByte6; /* 19 Device Status Config Bytes 6-7 */ - ushort PMECapab; /* 20 Power Mgment capabilities */ - unsigned char MSICapab; /* 21 MSI capabilities */ - unsigned char ClockDivider; /* Clock divider */ - ushort PciStatusLow; /* 22 PCI Status bits 15:0 */ - ushort PciStatusHigh; /* 23 PCI Status bits 31:16 */ - ushort DramConfigLow; /* 24 DRAM Configuration bits 15:0 */ - ushort DramConfigHigh; /* 25 DRAM Configuration bits 31:16 */ - ushort DramSize; /* 26 DRAM size (bytes / 64K) */ - ushort GpioTbiCtl;/* 27 GPIO/TBI controls for functions 1/0 */ - ushort EepromSize; /* 28 EEPROM Size */ + u16 Id; /* 00 EEPROM/FLASH Magic code 'A5A5' */ + u16 EecodeSize; /* 01 Size of EEPROM Codes (bytes * 4)*/ + u16 FlashConfig0; /* 02 Flash Config for SPI device 0 */ + u16 FlashConfig1; /* 03 Flash Config for SPI device 1 */ + u16 VendorId; /* 04 Vendor ID */ + u16 DeviceId; /* 05 Device ID (function 0) */ + u8 RevisionId; /* 06 Revision ID */ + u8 ClassCode[3]; /* 07 Class Code for PCI function 0 */ + u8 IntPin1; /* 08 Interrupt pin for PCI function 1*/ + u8 ClassCode2[3]; /* 09 Class Code for PCI function 1 */ + u8 IntPin2; /* 10 Interrupt pin for PCI function 2*/ + u8 IntPin0; /* Interrupt pin for PCI function 0*/ + u8 MinGrant; /* 11 Minimum grant */ + u8 MaxLat; /* Maximum Latency */ + u16 SubSysVId; /* 12 Subsystem Vendor Id */ + u16 SubSysId; /* 13 Subsystem ID */ + u16 FlashSize; /* 14 Flash size (bytes / 4K) */ + u16 DSize2Pci; /* 15 DRAM size to PCI (bytes / 64K) */ + u16 RSize2Pci; /* 16 Flash (ROM extension) size to PCI + (bytes / 4K) */ + u16 DeviceId1; /* 17 Device Id (function 1) */ + u16 DeviceId2; /* 18 Device Id (function 2) */ + u16 CfgByte6; /* 19 Device Status Config Bytes 6-7 */ + u16 PMECapab; /* 20 Power Mgment capabilities */ + u8 MSICapab; /* 21 MSI capabilities */ + u8 ClockDivider; /* Clock divider */ + u16 PciStatusLow; /* 22 PCI Status bits 15:0 */ + u16 PciStatusHigh; /* 23 PCI Status bits 31:16 */ + u16 DramConfigLow; /* 24 DRAM Configuration bits 15:0 */ + u16 DramConfigHigh; /* 25 DRAM Configuration bits 31:16 */ + u16 DramSize; /* 26 DRAM size (bytes / 64K) */ + u16 GpioTbiCtl; /* 27 GPIO/TBI controls for functions 1/0 */ + u16 EepromSize; /* 28 EEPROM Size */ struct slic_config_mac MacInfo[2]; /* 29 MAC addresses (2 ports) */ - unsigned char FruFormat; /* 35 Alacritech FRU format type */ + u8 FruFormat; /* 35 Alacritech FRU format type */ struct atk_fru AtkFru; /* Alacritech FRU information */ - unsigned char OemFruFormat; /* optional OEM FRU format type */ - union oemfru OemFru; /* optional OEM FRU information */ - unsigned char Pad[4]; /* Pad to 128 bytes - includes 2 checksum bytes + u8 OemFruFormat; /* optional OEM FRU format type */ + union oemfru OemFru; /* optional OEM FRU information */ + u8 Pad[4]; /* Pad to 128 bytes - includes 2 checksum bytes * (if OEM FRU info exists) and two unusable * bytes at the end */ @@ -819,24 +800,25 @@ struct oslic_eeprom { #define MAX_EECODE_SIZE sizeof(struct slic_eeprom) #define MIN_EECODE_SIZE 0x62 /* code size without optional OEM FRU stuff */ -/* SLIC CONFIG structure - - This structure lives in the CARD structure and is valid for all - board types. It is filled in from the appropriate EEPROM structure - by SlicGetConfigData(). -*/ +/* + * SLIC CONFIG structure + * + * This structure lives in the CARD structure and is valid for all board types. + * It is filled in from the appropriate EEPROM structure by + * SlicGetConfigData() + */ struct slic_config { bool EepromValid; /* Valid EEPROM flag (checksum good?) */ - ushort DramSize; /* DRAM size (bytes / 64K) */ + u16 DramSize; /* DRAM size (bytes / 64K) */ struct slic_config_mac MacInfo[SLIC_NBR_MACS]; /* MAC addresses */ - unsigned char FruFormat; /* Alacritech FRU format type */ + u8 FruFormat; /* Alacritech FRU format type */ struct atk_fru AtkFru; /* Alacritech FRU information */ - unsigned char OemFruFormat; /* optional OEM FRU format type */ + u8 OemFruFormat; /* optional OEM FRU format type */ union { - struct vendor1_fru vendor1_fru; - struct vendor2_fru vendor2_fru; - struct vendor3_fru vendor3_fru; - struct vendor4_fru vendor4_fru; + struct vendor1_fru vendor1_fru; + struct vendor2_fru vendor2_fru; + struct vendor3_fru vendor3_fru; + struct vendor4_fru vendor4_fru; } OemFru; }; diff --git a/drivers/staging/slicoss/slicinc.h b/drivers/staging/slicoss/slicinc.h deleted file mode 100644 index 71288c4f7be3..000000000000 --- a/drivers/staging/slicoss/slicinc.h +++ /dev/null @@ -1,185 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2000-2002 Alacritech, Inc. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation - * are those of the authors and should not be interpreted as representing - * official policies, either expressed or implied, of Alacritech, Inc. - * - **************************************************************************/ - -/* - * FILENAME: slicinc.h - * - * This file contains all other include files and prototype definitions - * for the SLICOSS driver. - */ -#ifndef _SLIC_INCLUDE_H_ -#define _SLIC_INCLUDE_H_ - -#include "slic_os.h" -#include "slicdbg.h" -#include "slichw.h" -#include "slic.h" - -static int slic_entry_probe(struct pci_dev *pcidev, - const struct pci_device_id *ent); -static void slic_entry_remove(struct pci_dev *pcidev); - -static void slic_init_driver(void); -static int slic_entry_open(struct net_device *dev); -static int slic_entry_halt(struct net_device *dev); -static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev); -static void slic_xmit_fail(struct adapter *adapter, - struct sk_buff *skb, - void *cmd, - u32 skbtype, - u32 status); -static void slic_config_pci(struct pci_dev *pcidev); -static struct sk_buff *slic_rcvqueue_getnext(struct adapter *adapter); - -static inline void slic_reg32_write(void __iomem *reg, u32 value, uint flush); -static inline void slic_reg64_write(struct adapter *adapter, void __iomem *reg, - u32 value, void __iomem *regh, u32 paddrh, uint flush); - -#if SLIC_GET_STATS_ENABLED -static struct net_device_stats *slic_get_stats(struct net_device *dev); -#endif - -static int slic_mac_set_address(struct net_device *dev, void *ptr); -static void slic_rcv_handler(struct adapter *adapter); -static void slic_link_event_handler(struct adapter *adapter); -static void slic_xmit_complete(struct adapter *adapter); -static void slic_upr_request_complete(struct adapter *adapter, u32 isr); -static int slic_rspqueue_init(struct adapter *adapter); -static int slic_rspqueue_reset(struct adapter *adapter); -static void slic_rspqueue_free(struct adapter *adapter); -static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter); -static void slic_cmdqmem_init(struct adapter *adapter); -static void slic_cmdqmem_free(struct adapter *adapter); -static u32 *slic_cmdqmem_addpage(struct adapter *adapter); -static int slic_cmdq_init(struct adapter *adapter); -static void slic_cmdq_free(struct adapter *adapter); -static void slic_cmdq_reset(struct adapter *adapter); -static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page); -static void slic_cmdq_getdone(struct adapter *adapter); -static void slic_cmdq_putdone_irq(struct adapter *adapter, - struct slic_hostcmd *cmd); -static struct slic_hostcmd *slic_cmdq_getfree(struct adapter *adapter); -static int slic_rcvqueue_init(struct adapter *adapter); -static int slic_rcvqueue_reset(struct adapter *adapter); -static int slic_rcvqueue_fill(struct adapter *adapter); -static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb); -static void slic_rcvqueue_free(struct adapter *adapter); -static void slic_rcv_handle_error(struct adapter *adapter, - struct slic_rcvbuf *rcvbuf); -static void slic_adapter_set_hwaddr(struct adapter *adapter); -static int slic_card_init(struct sliccard *card, struct adapter *adapter); -static void slic_intagg_set(struct adapter *adapter, u32 value); -static int slic_card_download(struct adapter *adapter); -static u32 slic_card_locate(struct adapter *adapter); - -static void slic_if_stop_queue(struct adapter *adapter); -static void slic_if_start_queue(struct adapter *adapter); -static int slic_if_init(struct adapter *adapter); -static int slic_adapter_allocresources(struct adapter *adapter); -static void slic_adapter_freeresources(struct adapter *adapter); -static void slic_link_config(struct adapter *adapter, u32 linkspeed, - u32 linkduplex); -static void slic_unmap_mmio_space(struct adapter *adapter); -static void slic_card_cleanup(struct sliccard *card); -static void slic_init_cleanup(struct adapter *adapter); -static void slic_soft_reset(struct adapter *adapter); -static bool slic_mac_filter(struct adapter *adapter, - struct ether_header *ether_frame); -static void slic_mac_address_config(struct adapter *adapter); -static void slic_mac_config(struct adapter *adapter); -static void slic_mcast_set_mask(struct adapter *adapter); -static int slic_mcast_add_list(struct adapter *adapter, char *address); -static unsigned char slic_mcast_get_mac_hash(char *macaddr); -static void slic_mcast_set_bit(struct adapter *adapter, char *address); -static void slic_config_set(struct adapter *adapter, bool linkchange); -static void slic_config_clear(struct adapter *adapter); -static void slic_config_get(struct adapter *adapter, u32 config, - u32 configh); -static void slic_timer_load_check(ulong context); -static void slic_timer_ping(ulong dev); -static void slic_assert_fail(void); -static ushort slic_eeprom_cksum(char *m, int len); -/* upr */ -static void slic_upr_start(struct adapter *adapter); -static void slic_link_upr_complete(struct adapter *adapter, u32 Isr); -static int slic_upr_request(struct adapter *adapter, - u32 upr_request, - u32 upr_data, - u32 upr_data_h, - u32 upr_buffer, - u32 upr_buffer_h); -static int slic_upr_queue_request(struct adapter *adapter, - u32 upr_request, - u32 upr_data, - u32 upr_data_h, - u32 upr_buffer, - u32 upr_buffer_h); -static void slic_mcast_set_list(struct net_device *dev); -static void slic_mcast_init_crc32(void); - -#if SLIC_DUMP_ENABLED -static int slic_dump_thread(void *context); -static uint slic_init_dump_thread(struct sliccard *card); -static unsigned char slic_get_dump_index(char *path); -static u32 slic_dump_card(struct sliccard *card, bool resume); -static u32 slic_dump_halt(struct sliccard *card, unsigned char proc); -static u32 slic_dump_reg(struct sliccard *card, unsigned char proc); -static u32 slic_dump_data(struct sliccard *card, u32 addr, - ushort count, unsigned char desc); -static u32 slic_dump_queue(struct sliccard *card, u32 buf_phys, - u32 buf_physh, u32 queue); -static u32 slic_dump_load_queue(struct sliccard *card, u32 data, - u32 queue); -static u32 slic_dump_cam(struct sliccard *card, u32 addr, - u32 count, unsigned char desc); - -static u32 slic_dump_resume(struct sliccard *card, unsigned char proc); -static u32 slic_dump_send_cmd(struct sliccard *card, u32 cmd_phys, - u32 cmd_physh, u32 buf_phys, - u32 buf_physh); - -#define create_file(x) STATUS_SUCCESS -#define write_file(w, x, y, z) STATUS_SUCCESS -#define close_file(x) STATUS_SUCCESS -#define read_file(w, x, y, z) STATUS_SUCCESS -#define open_file(x) STATUS_SUCCESS - -/* PAGE_SIZE * 16 */ -#define DUMP_PAGE_SIZE 0xFFFF -#define DUMP_PAGE_SIZE_HALF 0x7FFE -#endif - -#endif /* _SLIC_INCLUDE_H_ */ diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index bf7da8f898ab..953684f729da 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -55,19 +55,10 @@ */ -#define SLIC_DUMP_ENABLED 0 #define KLUDGE_FOR_4GB_BOUNDARY 1 #define DEBUG_MICROCODE 1 -#define SLIC_PRODUCTION_BUILD 1 -#define SLIC_FAILURE_RESET 1 #define DBG 1 -#define SLIC_ASSERT_ENABLED 1 -#define SLIC_GET_STATS_ENABLED 1 -#define SLIC_GET_STATS_TIMER_ENABLED 0 -#define SLIC_PING_TIMER_ENABLED 1 -#define SLIC_POWER_MANAGEMENT_ENABLED 0 #define SLIC_INTERRUPT_PROCESS_LIMIT 1 -#define LINUX_FREES_ADAPTER_RESOURCES 1 #define SLIC_OFFLOAD_IP_CHECKSUM 1 #define STATS_TIMER_INTERVAL 2 #define PING_TIMER_INTERVAL 1 @@ -102,20 +93,73 @@ #include #include -#define SLIC_ETHTOOL_SUPPORT 1 - #include -#include "slicinc.h" +#include "slichw.h" +#include "slic.h" -#if SLIC_DUMP_ENABLED -#include "slicdump.h" -#endif +static struct net_device_stats *slic_get_stats(struct net_device *dev); +static int slic_entry_open(struct net_device *dev); +static int slic_entry_halt(struct net_device *dev); +static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev); +static void slic_xmit_fail(struct adapter *adapter, struct sk_buff *skb, + void *cmd, u32 skbtype, u32 status); +static void slic_config_pci(struct pci_dev *pcidev); +static struct sk_buff *slic_rcvqueue_getnext(struct adapter *adapter); +static int slic_mac_set_address(struct net_device *dev, void *ptr); +static void slic_link_event_handler(struct adapter *adapter); +static void slic_upr_request_complete(struct adapter *adapter, u32 isr); +static int slic_rspqueue_init(struct adapter *adapter); +static void slic_rspqueue_free(struct adapter *adapter); +static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter); +static int slic_cmdq_init(struct adapter *adapter); +static void slic_cmdq_free(struct adapter *adapter); +static void slic_cmdq_reset(struct adapter *adapter); +static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page); +static void slic_cmdq_getdone(struct adapter *adapter); +static void slic_cmdq_putdone_irq(struct adapter *adapter, + struct slic_hostcmd *cmd); +static struct slic_hostcmd *slic_cmdq_getfree(struct adapter *adapter); +static int slic_rcvqueue_init(struct adapter *adapter); +static int slic_rcvqueue_fill(struct adapter *adapter); +static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb); +static void slic_rcvqueue_free(struct adapter *adapter); +static void slic_adapter_set_hwaddr(struct adapter *adapter); +static int slic_card_init(struct sliccard *card, struct adapter *adapter); +static void slic_intagg_set(struct adapter *adapter, u32 value); +static int slic_card_download(struct adapter *adapter); +static u32 slic_card_locate(struct adapter *adapter); +static int slic_if_init(struct adapter *adapter); +static int slic_adapter_allocresources(struct adapter *adapter); +static void slic_adapter_freeresources(struct adapter *adapter); +static void slic_link_config(struct adapter *adapter, u32 linkspeed, + u32 linkduplex); +static void slic_unmap_mmio_space(struct adapter *adapter); +static void slic_card_cleanup(struct sliccard *card); +static void slic_soft_reset(struct adapter *adapter); +static bool slic_mac_filter(struct adapter *adapter, + struct ether_header *ether_frame); +static void slic_mac_address_config(struct adapter *adapter); +static void slic_mac_config(struct adapter *adapter); +static void slic_mcast_set_mask(struct adapter *adapter); +static void slic_config_set(struct adapter *adapter, bool linkchange); +static void slic_config_clear(struct adapter *adapter); +static void slic_config_get(struct adapter *adapter, u32 config, + u32 configh); +static void slic_timer_load_check(ulong context); +static void slic_assert_fail(void); +static ushort slic_eeprom_cksum(char *m, int len); +static void slic_upr_start(struct adapter *adapter); +static void slic_link_upr_complete(struct adapter *adapter, u32 Isr); +static int slic_upr_request(struct adapter *adapter, u32 upr_request, + u32 upr_data, u32 upr_data_h, u32 upr_buffer, + u32 upr_buffer_h); +static void slic_mcast_set_list(struct net_device *dev); -#define SLIC_POWER_MANAGEMENT 0 static uint slic_first_init = 1; static char *slic_banner = "Alacritech SLIC Technology(tm) Server "\ - "and Storage Accelerator (Non-Accelerated)\n"; + "and Storage Accelerator (Non-Accelerated)"; static char *slic_proc_version = "2.0.351 2006/07/14 12:26:00"; static char *slic_product_name = "SLIC Technology(tm) Server "\ @@ -129,8 +173,6 @@ static struct net_device *head_netdevice; static struct base_driver slic_global = { {}, 0, 0, 0, 1, NULL, NULL }; static int intagg_delay = 100; static u32 dynamic_intagg; -static int errormsg; -static int goodmsg; static unsigned int rcv_count; static struct dentry *slic_debugfs; @@ -164,6 +206,21 @@ static struct pci_device_id slic_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, slic_pci_tbl); +#ifdef ASSERT +#undef ASSERT +#endif + +#ifndef ASSERT +#define ASSERT(a) do { \ + if (!(a)) { \ + printk(KERN_ERR "slicoss ASSERT() Failure: function %s" \ + "line %d\n", __func__, __LINE__); \ + slic_assert_fail(); \ + } \ +} while (0) +#endif + + #define SLIC_GET_SLIC_HANDLE(_adapter, _pslic_handle) \ { \ spin_lock_irqsave(&_adapter->handle_lock.lock, \ @@ -195,17 +252,16 @@ static void slic_debug_adapter_destroy(struct adapter *adapter); static void slic_debug_card_create(struct sliccard *card); static void slic_debug_card_destroy(struct sliccard *card); -static inline void slic_reg32_write(void __iomem *reg, u32 value, uint flush) +static inline void slic_reg32_write(void __iomem *reg, u32 value, bool flush) { writel(value, reg); if (flush) mb(); } -static inline void slic_reg64_write(struct adapter *adapter, - void __iomem *reg, - u32 value, - void __iomem *regh, u32 paddrh, uint flush) +static inline void slic_reg64_write(struct adapter *adapter, void __iomem *reg, + u32 value, void __iomem *regh, u32 paddrh, + bool flush) { spin_lock_irqsave(&adapter->bit64reglock.lock, adapter->bit64reglock.flags); @@ -223,43 +279,12 @@ static inline void slic_reg64_write(struct adapter *adapter, static void slic_init_driver(void) { if (slic_first_init) { - DBG_MSG("slicoss: %s slic_first_init set jiffies[%lx]\n", - __func__, jiffies); slic_first_init = 0; spin_lock_init(&slic_global.driver_lock.lock); slic_debug_init(); } } -static void slic_dbg_macaddrs(struct adapter *adapter) -{ - DBG_MSG(" (%s) curr %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", - adapter->netdev->name, adapter->currmacaddr[0], - adapter->currmacaddr[1], adapter->currmacaddr[2], - adapter->currmacaddr[3], adapter->currmacaddr[4], - adapter->currmacaddr[5]); - DBG_MSG(" (%s) mac %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", - adapter->netdev->name, adapter->macaddr[0], - adapter->macaddr[1], adapter->macaddr[2], - adapter->macaddr[3], adapter->macaddr[4], adapter->macaddr[5]); - return; -} - -#ifdef DEBUG_REGISTER_TRACE -static void slic_dbg_register_trace(struct adapter *adapter, - struct sliccard *card) -{ - uint i; - - DBG_ERROR("Dump Register Write Trace: curr_ix == %d\n", card->debug_ix); - for (i = 0; i < 32; i++) { - DBG_ERROR("%2d %d %4x %x %x\n", - i, card->reg_type[i], card->reg_offset[i], - card->reg_value[i], card->reg_valueh[i]); - } -} -#endif - static void slic_init_adapter(struct net_device *netdev, struct pci_dev *pcidev, const struct pci_device_id *pci_tbl_entry, @@ -268,9 +293,7 @@ static void slic_init_adapter(struct net_device *netdev, ushort index; struct slic_handle *pslic_handle; struct adapter *adapter = (struct adapter *)netdev_priv(netdev); -/* - DBG_MSG("slicoss: %s (%s)\n netdev [%p]\n adapter[%p]\n " - "pcidev [%p]\n", __func__, netdev->name, netdev, adapter, pcidev);*/ + /* adapter->pcidev = pcidev;*/ adapter->vendid = pci_tbl_entry->vendor; adapter->devid = pci_tbl_entry->device; @@ -310,19 +333,11 @@ static void slic_init_adapter(struct net_device *netdev, pslic_handle->next = adapter->pfree_slic_handles; adapter->pfree_slic_handles = pslic_handle; } -/* - DBG_MSG(".........\nix[%d] phandle[%p] pfree[%p] next[%p]\n", - index, pslic_handle, adapter->pfree_slic_handles, pslic_handle->next);*/ adapter->pshmem = (struct slic_shmem *) pci_alloc_consistent(adapter->pcidev, sizeof(struct slic_shmem), &adapter-> phys_shmem); -/* - DBG_MSG("slicoss: %s (%s)\n pshmem [%p]\n phys_shmem[%p]\n"\ - "slic_regs [%p]\n", __func__, netdev->name, adapter->pshmem, - (void *)adapter->phys_shmem, adapter->slic_regs); -*/ ASSERT(adapter->pshmem); memset(adapter->pshmem, 0, sizeof(struct slic_shmem)); @@ -335,7 +350,7 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev, { static int cards_found; static int did_version; - int err; + int err = -ENODEV; struct net_device *netdev; struct adapter *adapter; void __iomem *memmapped_ioaddr = NULL; @@ -344,54 +359,36 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev, ulong mmio_len = 0; struct sliccard *card = NULL; - DBG_MSG("slicoss: %s 2.6 VERSION ENTER jiffies[%lx] cpu %d\n", - __func__, jiffies, smp_processor_id()); - slic_global.dynamic_intagg = dynamic_intagg; err = pci_enable_device(pcidev); - DBG_MSG("Call pci_enable_device(%p) status[%x]\n", pcidev, err); if (err) return err; if (slic_debug > 0 && did_version++ == 0) { - printk(slic_banner); - printk(slic_proc_version); + printk(KERN_DEBUG "%s\n", slic_banner); + printk(KERN_DEBUG "%s\n", slic_proc_version); } err = pci_set_dma_mask(pcidev, DMA_64BIT_MASK); - if (!err) { - DBG_MSG("pci_set_dma_mask(DMA_64BIT_MASK) successful\n"); - } else { + if (err) { err = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); - if (err) { - DBG_MSG - ("No usable DMA configuration, aborting err[%x]\n", - err); - return err; - } - DBG_MSG("pci_set_dma_mask(DMA_32BIT_MASK) successful\n"); + if (err) + goto err_out_disable_pci; } - DBG_MSG("Call pci_request_regions\n"); - err = pci_request_regions(pcidev, DRV_NAME); - if (err) { - DBG_MSG("pci_request_regions FAILED err[%x]\n", err); - return err; - } + if (err) + goto err_out_disable_pci; - DBG_MSG("call pci_set_master\n"); pci_set_master(pcidev); - DBG_MSG("call alloc_etherdev\n"); netdev = alloc_etherdev(sizeof(struct adapter)); if (!netdev) { err = -ENOMEM; goto err_out_exit_slic_probe; } - DBG_MSG("alloc_etherdev for slic netdev[%p]\n", netdev); SET_NETDEV_DEV(netdev, &pcidev->dev); @@ -403,24 +400,15 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev, mmio_start = pci_resource_start(pcidev, 0); mmio_len = pci_resource_len(pcidev, 0); - DBG_MSG("slicoss: call ioremap(mmio_start[%lx], mmio_len[%lx])\n", - mmio_start, mmio_len); -/* memmapped_ioaddr = (u32)ioremap_nocache(mmio_start, mmio_len);*/ +/* memmapped_ioaddr = (u32)ioremap_nocache(mmio_start, mmio_len);*/ memmapped_ioaddr = ioremap(mmio_start, mmio_len); - DBG_MSG("slicoss: %s MEMMAPPED_IOADDR [%p]\n", __func__, - memmapped_ioaddr); if (!memmapped_ioaddr) { - DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n", - __func__, mmio_len, mmio_start); - goto err_out_free_mmio_region; + dev_err(&pcidev->dev, "cannot remap MMIO region %lx @ %lx\n", + mmio_len, mmio_start); + goto err_out_free_netdev; } - DBG_MSG - ("slicoss: %s found Alacritech SLICOSS PCI, MMIO at %p, "\ - "start[%lx] len[%lx], IRQ %d.\n", - __func__, memmapped_ioaddr, mmio_start, mmio_len, pcidev->irq); - slic_config_pci(pcidev); slic_init_driver(); @@ -430,7 +418,7 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev, status = slic_card_locate(adapter); if (status) { - DBG_ERROR("%s cannot locate card\n", __func__); + dev_err(&pcidev->dev, "cannot locate card\n"); goto err_out_free_mmio_region; } @@ -441,22 +429,13 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev, adapter->allocated = 1; } - DBG_MSG("slicoss: %s card: %p\n", __func__, - adapter->card); - DBG_MSG("slicoss: %s card->adapter[%d] == [%p]\n", __func__, - (uint) adapter->port, adapter); - DBG_MSG("slicoss: %s card->adapters_allocated [%d]\n", __func__, - card->adapters_allocated); - DBG_MSG("slicoss: %s card->adapters_activated [%d]\n", __func__, - card->adapters_activated); - status = slic_card_init(card, adapter); if (status != STATUS_SUCCESS) { card->state = CARD_FAIL; adapter->state = ADAPT_FAIL; adapter->linkstate = LINK_DOWN; - DBG_ERROR("slic_card_init FAILED status[%x]\n", status); + dev_err(&pcidev->dev, "FAILED status[%x]\n", status); } else { slic_adapter_set_hwaddr(adapter); } @@ -468,9 +447,7 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev, netdev->hard_start_xmit = slic_xmit_start; netdev->do_ioctl = slic_ioctl; netdev->set_mac_address = slic_mac_set_address; -#if SLIC_GET_STATS_ENABLED netdev->get_stats = slic_get_stats; -#endif netdev->set_multicast_list = slic_mcast_set_list; slic_debug_adapter_create(adapter); @@ -478,35 +455,25 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev, strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) { - DBG_ERROR("Cannot register net device, aborting.\n"); + dev_err(&pcidev->dev, "Cannot register net device, aborting.\n"); goto err_out_unmap; } - DBG_MSG - ("slicoss: addr 0x%lx, irq %d, MAC addr "\ - "%02X:%02X:%02X:%02X:%02X:%02X\n", - mmio_start, /*pci_resource_start(pcidev, 0), */ pcidev->irq, - netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], - netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); - cards_found++; - DBG_MSG("slicoss: %s EXIT status[%x] jiffies[%lx] cpu %d\n", - __func__, status, jiffies, smp_processor_id()); return status; err_out_unmap: iounmap(memmapped_ioaddr); - err_out_free_mmio_region: release_mem_region(mmio_start, mmio_len); - +err_out_free_netdev: + free_netdev(netdev); err_out_exit_slic_probe: pci_release_regions(pcidev); - DBG_ERROR("%s EXIT jiffies[%lx] cpu %d\n", __func__, jiffies, - smp_processor_id()); - - return -ENODEV; +err_out_disable_pci: + pci_disable_device(pcidev); + return err; } static int slic_entry_open(struct net_device *dev) @@ -518,16 +485,6 @@ static int slic_entry_open(struct net_device *dev) ASSERT(adapter); ASSERT(card); - DBG_MSG - ("slicoss: %s adapter->activated[%d] card->adapters[%x] "\ - "allocd[%x]\n", __func__, adapter->activated, - card->adapters_activated, - card->adapters_allocated); - DBG_MSG - ("slicoss: %s (%s): [jiffies[%lx] cpu %d] dev[%p] adapt[%p] "\ - "port[%d] card[%p]\n", - __func__, adapter->netdev->name, jiffies, smp_processor_id(), - adapter->netdev, adapter, adapter->port, card); netif_stop_queue(adapter->netdev); @@ -554,29 +511,14 @@ static int slic_entry_open(struct net_device *dev) } return status; } - DBG_MSG("slicoss: %s set card->master[%p] adapter[%p]\n", __func__, - card->master, adapter); if (!card->master) card->master = adapter; -#if SLIC_DUMP_ENABLED - if (!(card->dumpthread_running)) - init_waitqueue_head(&card->dump_wq); -#endif if (locked) { spin_unlock_irqrestore(&slic_global.driver_lock.lock, slic_global.driver_lock.flags); locked = 0; } -#if SLIC_DUMP_ENABLED - if (!(card->dumpthread_running)) { - DBG_MSG("attempt to initialize dump thread\n"); - status = slic_init_dump_thread(card); - /* - Even if the dump thread fails, we will continue at this point - */ - } -#endif return STATUS_SUCCESS; } @@ -591,22 +533,15 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev) struct mcast_address *mcaddr, *mlist; ASSERT(adapter); - DBG_MSG("slicoss: %s ENTER dev[%p] adapter[%p]\n", __func__, dev, - adapter); slic_adapter_freeresources(adapter); slic_unmap_mmio_space(adapter); - DBG_MSG("slicoss: %s unregister_netdev\n", __func__); unregister_netdev(dev); mmio_start = pci_resource_start(pcidev, 0); mmio_len = pci_resource_len(pcidev, 0); - DBG_MSG("slicoss: %s rel_region(0) start[%x] len[%x]\n", __func__, - mmio_start, mmio_len); release_mem_region(mmio_start, mmio_len); - DBG_MSG("slicoss: %s iounmap dev->base_addr[%x]\n", __func__, - (uint) dev->base_addr); iounmap((void __iomem *)dev->base_addr); /* free multicast addresses */ mlist = adapter->mcastaddrs; @@ -620,10 +555,6 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev) ASSERT(card->adapters_allocated); card->adapters_allocated--; adapter->allocated = 0; - DBG_MSG - ("slicoss: %s init[%x] alloc[%x] card[%p] adapter[%p]\n", - __func__, card->adapters_activated, card->adapters_allocated, - card, adapter); if (!card->adapters_allocated) { struct sliccard *curr_card = slic_global.slic_card; if (curr_card == card) { @@ -638,10 +569,8 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev) slic_global.num_slic_cards--; slic_card_cleanup(card); } - DBG_MSG("slicoss: %s deallocate device\n", __func__); kfree(dev); pci_release_regions(pcidev); - DBG_MSG("slicoss: %s EXIT\n", __func__); } static int slic_entry_halt(struct net_device *dev) @@ -653,75 +582,35 @@ static int slic_entry_halt(struct net_device *dev) spin_lock_irqsave(&slic_global.driver_lock.lock, slic_global.driver_lock.flags); ASSERT(card); - DBG_MSG("slicoss: %s (%s) ENTER\n", __func__, dev->name); - DBG_MSG("slicoss: %s (%s) actvtd[%d] alloc[%d] state[%x] adapt[%p]\n", - __func__, dev->name, card->adapters_activated, - card->adapters_allocated, card->state, adapter); - slic_if_stop_queue(adapter); + netif_stop_queue(adapter->netdev); adapter->state = ADAPT_DOWN; adapter->linkstate = LINK_DOWN; adapter->upr_list = NULL; adapter->upr_busy = 0; adapter->devflags_prev = 0; - DBG_MSG("slicoss: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n", - __func__, dev->name, adapter, adapter->state); ASSERT(card->adapter[adapter->cardindex] == adapter); - WRITE_REG(slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); adapter->all_reg_writes++; adapter->icr_reg_writes++; slic_config_clear(adapter); - DBG_MSG("slicoss: %s (%s) dev[%p] adapt[%p] card[%p]\n", - __func__, dev->name, dev, adapter, card); if (adapter->activated) { card->adapters_activated--; slic_global.num_slic_ports_active--; adapter->activated = 0; } #ifdef AUTOMATIC_RESET - WRITE_REG(slic_regs->slic_reset_iface, 0, FLUSH); + slic_reg32_write(&slic_regs->slic_reset_iface, 0, FLUSH); #endif /* - * Reset the adapter's rsp, cmd, and rcv queues + * Reset the adapter's cmd queues */ slic_cmdq_reset(adapter); - slic_rspqueue_reset(adapter); - slic_rcvqueue_reset(adapter); #ifdef AUTOMATIC_RESET - if (!card->adapters_activated) { - -#if SLIC_DUMP_ENABLED - if (card->dumpthread_running) { - uint status; - DBG_MSG("attempt to terminate dump thread pid[%x]\n", - card->dump_task_id); - status = kill_proc(card->dump_task_id->pid, SIGKILL, 1); - - if (!status) { - int count = 10 * 100; - while (card->dumpthread_running && --count) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - - if (!count) { - DBG_MSG - ("slicmon thread cleanup FAILED \ - pid[%x]\n", - card->dump_task_id->pid); - } - } - } -#endif - DBG_MSG("slicoss: %s (%s) initiate CARD_HALT\n", __func__, - dev->name); - + if (!card->adapters_activated) slic_card_init(card, adapter); - } #endif - DBG_MSG("slicoss: %s (%s) EXIT\n", __func__, dev->name); - DBG_MSG("slicoss: %s EXIT\n", __func__); spin_unlock_irqrestore(&slic_global.driver_lock.lock, slic_global.driver_lock.flags); return STATUS_SUCCESS; @@ -729,69 +618,27 @@ static int slic_entry_halt(struct net_device *dev) static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { + struct adapter *adapter = (struct adapter *)netdev_priv(dev); + struct ethtool_cmd edata; + struct ethtool_cmd ecmd; + u32 data[7]; + u32 intagg; + ASSERT(rq); -/* - DBG_MSG("slicoss: %s cmd[%x] rq[%p] dev[%p]\n", __func__, cmd, rq, dev); -*/ switch (cmd) { case SIOCSLICSETINTAGG: - { - struct adapter *adapter = (struct adapter *) - netdev_priv(dev); - u32 data[7]; - u32 intagg; - - if (copy_from_user(data, rq->ifr_data, 28)) { - DBG_ERROR - ("copy_from_user FAILED getting initial \ - params\n"); - return -EFAULT; - } - intagg = data[0]; - printk(KERN_EMERG - "%s: set interrupt aggregation to %d\n", - __func__, intagg); - slic_intagg_set(adapter, intagg); - return 0; - } -#ifdef SLIC_USER_REQUEST_DUMP_ENABLED - case SIOCSLICDUMPCARD: - { - struct adapter *adapter = netdev_priv(dev); - struct sliccard *card; - - ASSERT(adapter); - ASSERT(adapter->card) - card = adapter->card; - - DBG_IOCTL("slic_ioctl SIOCSLIC_DUMP_CARD\n"); - - if (card->dump_requested == SLIC_DUMP_DONE) { - printk(SLICLEVEL - "SLIC Card dump to be overwritten\n"); - card->dump_requested = SLIC_DUMP_REQUESTED; - } else if ((card->dump_requested == SLIC_DUMP_REQUESTED) - || (card->dump_requested == - SLIC_DUMP_IN_PROGRESS)) { - printk(SLICLEVEL - "SLIC Card dump Requested but already \ - in progress... ignore\n"); - } else { - printk(SLICLEVEL - "SLIC Card #%d Dump Requested\n", - card->cardnum); - card->dump_requested = SLIC_DUMP_REQUESTED; - } - return 0; - } -#endif + if (copy_from_user(data, rq->ifr_data, 28)) + return -EFAULT; + intagg = data[0]; + dev_err(&dev->dev, "%s: set interrupt aggregation to %d\n", + __func__, intagg); + slic_intagg_set(adapter, intagg); + return 0; #ifdef SLIC_TRACE_DUMP_ENABLED case SIOCSLICTRACEDUMP: { - ulong data[7]; - ulong value; - + u32 value; DBG_IOCTL("slic_ioctl SIOCSLIC_TRACE_DUMP\n"); if (copy_from_user(data, rq->ifr_data, 28)) { @@ -824,104 +671,76 @@ static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return 0; } #endif -#if SLIC_ETHTOOL_SUPPORT case SIOCETHTOOL: - { - struct adapter *adapter = (struct adapter *) - netdev_priv(dev); - struct ethtool_cmd data; - struct ethtool_cmd ecmd; + ASSERT(adapter); + if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd))) + return -EFAULT; - ASSERT(adapter); -/* DBG_MSG("slicoss: %s SIOCETHTOOL\n", __func__); */ - if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd))) + if (ecmd.cmd == ETHTOOL_GSET) { + edata.supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_MII); + edata.port = PORT_MII; + edata.transceiver = XCVR_INTERNAL; + edata.phy_address = 0; + if (adapter->linkspeed == LINK_100MB) + edata.speed = SPEED_100; + else if (adapter->linkspeed == LINK_10MB) + edata.speed = SPEED_10; + else + edata.speed = 0; + + if (adapter->linkduplex == LINK_FULLD) + edata.duplex = DUPLEX_FULL; + else + edata.duplex = DUPLEX_HALF; + + edata.autoneg = AUTONEG_ENABLE; + edata.maxtxpkt = 1; + edata.maxrxpkt = 1; + if (copy_to_user(rq->ifr_data, &edata, sizeof(edata))) return -EFAULT; - if (ecmd.cmd == ETHTOOL_GSET) { - data.supported = - (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_MII); - data.port = PORT_MII; - data.transceiver = XCVR_INTERNAL; - data.phy_address = 0; - if (adapter->linkspeed == LINK_100MB) - data.speed = SPEED_100; - else if (adapter->linkspeed == LINK_10MB) - data.speed = SPEED_10; + } else if (ecmd.cmd == ETHTOOL_SSET) { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (adapter->linkspeed == LINK_100MB) + edata.speed = SPEED_100; + else if (adapter->linkspeed == LINK_10MB) + edata.speed = SPEED_10; + else + edata.speed = 0; + + if (adapter->linkduplex == LINK_FULLD) + edata.duplex = DUPLEX_FULL; + else + edata.duplex = DUPLEX_HALF; + + edata.autoneg = AUTONEG_ENABLE; + edata.maxtxpkt = 1; + edata.maxrxpkt = 1; + if ((ecmd.speed != edata.speed) || + (ecmd.duplex != edata.duplex)) { + u32 speed; + u32 duplex; + + if (ecmd.speed == SPEED_10) + speed = 0; else - data.speed = 0; - - if (adapter->linkduplex == LINK_FULLD) - data.duplex = DUPLEX_FULL; + speed = PCR_SPEED_100; + if (ecmd.duplex == DUPLEX_FULL) + duplex = PCR_DUPLEX_FULL; else - data.duplex = DUPLEX_HALF; - - data.autoneg = AUTONEG_ENABLE; - data.maxtxpkt = 1; - data.maxrxpkt = 1; - if (copy_to_user - (rq->ifr_data, &data, sizeof(data))) - return -EFAULT; - - } else if (ecmd.cmd == ETHTOOL_SSET) { - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (adapter->linkspeed == LINK_100MB) - data.speed = SPEED_100; - else if (adapter->linkspeed == LINK_10MB) - data.speed = SPEED_10; - else - data.speed = 0; - - if (adapter->linkduplex == LINK_FULLD) - data.duplex = DUPLEX_FULL; - else - data.duplex = DUPLEX_HALF; - - data.autoneg = AUTONEG_ENABLE; - data.maxtxpkt = 1; - data.maxrxpkt = 1; - if ((ecmd.speed != data.speed) || - (ecmd.duplex != data.duplex)) { - u32 speed; - u32 duplex; - - if (ecmd.speed == SPEED_10) { - speed = 0; - SLIC_DISPLAY - ("%s: slic ETHTOOL set \ - link speed==10MB", - dev->name); - } else { - speed = PCR_SPEED_100; - SLIC_DISPLAY - ("%s: slic ETHTOOL set \ - link speed==100MB", - dev->name); - } - if (ecmd.duplex == DUPLEX_FULL) { - duplex = PCR_DUPLEX_FULL; - SLIC_DISPLAY - (": duplex==FULL\n"); - } else { - duplex = 0; - SLIC_DISPLAY - (": duplex==HALF\n"); - } - slic_link_config(adapter, - speed, duplex); - slic_link_event_handler(adapter); - } + duplex = 0; + slic_link_config(adapter, speed, duplex); + slic_link_event_handler(adapter); } - return 0; } -#endif + return 0; default: -/* DBG_MSG("slicoss: %s UNSUPPORTED[%x]\n", __func__, cmd); */ return -EOPNOTSUPP; } } @@ -970,11 +789,6 @@ static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev) card = adapter->card; ASSERT(card); -/* - DBG_ERROR("xmit_start (%s) ENTER skb[%p] len[%d] linkstate[%x] state[%x]\n", - adapter->netdev->name, skb, skb->len, adapter->linkstate, - adapter->state); -*/ if ((adapter->linkstate != LINK_UP) || (adapter->state != ADAPT_UP) || (card->state != CARD_UP)) { status = XMIT_FAIL_LINK_STATE; @@ -1015,14 +829,13 @@ static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev) } #endif if (hcmd->paddrh == 0) { - WRITE_REG(adapter->slic_regs->slic_cbar, - (hcmd->paddrl | hcmd->cmdsize), DONT_FLUSH); + slic_reg32_write(&adapter->slic_regs->slic_cbar, + (hcmd->paddrl | hcmd->cmdsize), DONT_FLUSH); } else { - WRITE_REG64(adapter, - adapter->slic_regs->slic_cbar64, - (hcmd->paddrl | hcmd->cmdsize), - adapter->slic_regs->slic_addr_upper, - hcmd->paddrh, DONT_FLUSH); + slic_reg64_write(adapter, &adapter->slic_regs->slic_cbar64, + (hcmd->paddrl | hcmd->cmdsize), + &adapter->slic_regs->slic_addr_upper, + hcmd->paddrh, DONT_FLUSH); } xmit_done: return 0; @@ -1036,29 +849,29 @@ static void slic_xmit_fail(struct adapter *adapter, void *cmd, u32 skbtype, u32 status) { if (adapter->xmitq_full) - slic_if_stop_queue(adapter); + netif_stop_queue(adapter->netdev); if ((cmd == NULL) && (status <= XMIT_FAIL_HOSTCMD_FAIL)) { switch (status) { case XMIT_FAIL_LINK_STATE: - DBG_ERROR - ("(%s) reject xmit skb[%p: %x] linkstate[%s] \ - adapter[%s:%d] card[%s:%d]\n", - adapter->netdev->name, skb, skb->pkt_type, - SLIC_LINKSTATE(adapter->linkstate), - SLIC_ADAPTER_STATE(adapter->state), adapter->state, - SLIC_CARD_STATE(adapter->card->state), - adapter->card->state); + dev_err(&adapter->netdev->dev, + "reject xmit skb[%p: %x] linkstate[%s] " + "adapter[%s:%d] card[%s:%d]\n", + skb, skb->pkt_type, + SLIC_LINKSTATE(adapter->linkstate), + SLIC_ADAPTER_STATE(adapter->state), + adapter->state, + SLIC_CARD_STATE(adapter->card->state), + adapter->card->state); break; case XMIT_FAIL_ZERO_LENGTH: - DBG_ERROR - ("xmit_start skb->len == 0 skb[%p] type[%x]!!!! \n", - skb, skb->pkt_type); + dev_err(&adapter->netdev->dev, + "xmit_start skb->len == 0 skb[%p] type[%x]\n", + skb, skb->pkt_type); break; case XMIT_FAIL_HOSTCMD_FAIL: - DBG_ERROR - ("xmit_start skb[%p] type[%x] No host commands \ - available !!!! \n", - skb, skb->pkt_type); + dev_err(&adapter->netdev->dev, + "xmit_start skb[%p] type[%x] No host commands " + "available\n", skb, skb->pkt_type); break; default: ASSERT(0); @@ -1183,11 +996,6 @@ static void slic_rcv_handler(struct adapter *adapter) if (!slic_mac_filter(adapter, (struct ether_header *) rcvbuf->data)) { -#if 0 - DBG_MSG - ("slicoss: %s (%s) drop frame due to mac filter\n", - __func__, adapter->netdev->name); -#endif slic_rcvqueue_reinsert(adapter, skb); continue; } @@ -1242,12 +1050,6 @@ static void slic_xmit_complete(struct adapter *adapter) ASSERT(hcmd); ASSERT(hcmd->pslic_handle == &adapter->slic_handles[slic_handle_word.handle_index]); -/* - DBG_ERROR("xmit_complete (%s) hcmd[%p] hosthandle[%x]\n", - adapter->netdev->name, hcmd, hcmd->cmd64.hosthandle); - DBG_ERROR(" skb[%p] len %d hcmdtype[%x]\n", hcmd->skb, - hcmd->skb->len, hcmd->type); -*/ if (hcmd->type == SLIC_CMD_DUMB) { if (hcmd->skb) dev_kfree_skb_irq(hcmd->skb); @@ -1267,7 +1069,8 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) u32 isr; if ((adapter->pshmem) && (adapter->pshmem->isr)) { - WRITE_REG(adapter->slic_regs->slic_icr, ICR_INT_MASK, FLUSH); + slic_reg32_write(&adapter->slic_regs->slic_icr, + ICR_INT_MASK, FLUSH); isr = adapter->isrcopy = adapter->pshmem->isr; adapter->pshmem->isr = 0; adapter->num_isrs++; @@ -1299,29 +1102,18 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) if (!count) break; } - DBG_MSG - ("(%s): [%x] ISR_RMISS \ - initial[%x] pre[%x] \ - errors[%x] \ - post_count[%x]\n", - adapter->netdev->name, - isr, rcv_count, pre_count, - errors, rcvq->count); } else if (isr & ISR_XDROP) { - DBG_ERROR - ("isr & ISR_ERR [%x] \ - ISR_XDROP \n", - isr); + dev_err(&dev->dev, + "isr & ISR_ERR [%x] " + "ISR_XDROP \n", isr); } else { - DBG_ERROR - ("isr & ISR_ERR [%x]\n", - isr); + dev_err(&dev->dev, + "isr & ISR_ERR [%x]\n", + isr); } } if (isr & ISR_LEVENT) { - /*DBG_MSG("%s (%s) ISR_LEVENT \n", - __func__, adapter->netdev->name);*/ adapter->linkevent_interrupts++; slic_link_event_handler(adapter); } @@ -1359,7 +1151,7 @@ static irqreturn_t slic_interrupt(int irq, void *dev_id) adapter->isrcopy = 0; adapter->all_reg_writes += 2; adapter->isr_reg_writes++; - WRITE_REG(adapter->slic_regs->slic_isr, 0, FLUSH); + slic_reg32_write(&adapter->slic_regs->slic_isr, 0, FLUSH); } else { adapter->false_interrupts++; } @@ -1389,11 +1181,6 @@ static void slic_link_event_handler(struct adapter *adapter) pshmem = (struct slic_shmem *)adapter->phys_shmem; #if defined(CONFIG_X86_64) -/* - DBG_MSG("slic_event_handler pshmem->linkstatus[%x] pshmem[%p]\n \ - &linkstatus[%p] &isr[%p]\n", adapter->pshmem->linkstatus, pshmem, - &pshmem->linkstatus, &pshmem->isr); -*/ status = slic_upr_request(adapter, SLIC_UPR_RLSR, SLIC_GET_ADDR_LOW(&pshmem->linkstatus), @@ -1411,46 +1198,29 @@ static void slic_link_event_handler(struct adapter *adapter) static void slic_init_cleanup(struct adapter *adapter) { - DBG_MSG("slicoss: %s ENTER adapter[%p] ", __func__, adapter); if (adapter->intrregistered) { - DBG_MSG("FREE_IRQ "); adapter->intrregistered = 0; free_irq(adapter->netdev->irq, adapter->netdev); } if (adapter->pshmem) { - DBG_MSG("FREE_SHMEM "); - DBG_MSG("adapter[%p] port %d pshmem[%p] FreeShmem ", - adapter, adapter->port, (void *) adapter->pshmem); pci_free_consistent(adapter->pcidev, sizeof(struct slic_shmem), adapter->pshmem, adapter->phys_shmem); adapter->pshmem = NULL; adapter->phys_shmem = (dma_addr_t) NULL; } -#if SLIC_GET_STATS_TIMER_ENABLED - if (adapter->statstimerset) { - DBG_MSG("statstimer "); - adapter->statstimerset = 0; - del_timer(&adapter->statstimer); - } -#endif -#if !SLIC_DUMP_ENABLED && SLIC_PING_TIMER_ENABLED -/*#if SLIC_DUMP_ENABLED && SLIC_PING_TIMER_ENABLED*/ + if (adapter->pingtimerset) { - DBG_MSG("pingtimer "); adapter->pingtimerset = 0; del_timer(&adapter->pingtimer); } -#endif + slic_rspqueue_free(adapter); slic_cmdq_free(adapter); slic_rcvqueue_free(adapter); - - DBG_MSG("\n"); } -#if SLIC_GET_STATS_ENABLED static struct net_device_stats *slic_get_stats(struct net_device *dev) { struct adapter *adapter = (struct adapter *)netdev_priv(dev); @@ -1470,7 +1240,6 @@ static struct net_device_stats *slic_get_stats(struct net_device *dev) stats->rx_length_errors = 0; return &adapter->stats; } -#endif /* * Allocate a mcast_address structure to hold the multicast address. @@ -1491,7 +1260,7 @@ static int slic_mcast_add_list(struct adapter *adapter, char *address) } /* Doesn't already exist. Allocate a structure to hold it */ - mcaddr = kmalloc(sizeof(struct mcast_address), GFP_ATOMIC); + mcaddr = kmalloc(sizeof(struct mcast_address), GFP_KERNEL); if (mcaddr == NULL) return 1; @@ -1608,8 +1377,6 @@ static void slic_mcast_set_list(struct net_device *dev) mc_list = mc_list->next; } - DBG_MSG("%s a->devflags_prev[%x] dev->flags[%x] status[%x]\n", - __func__, adapter->devflags_prev, dev->flags, status); if (adapter->devflags_prev != dev->flags) { adapter->macopts = MAC_DIRECTED; if (dev->flags) { @@ -1623,9 +1390,7 @@ static void slic_mcast_set_list(struct net_device *dev) adapter->macopts |= MAC_MCAST; } adapter->devflags_prev = dev->flags; - DBG_MSG("%s call slic_config_set adapter->macopts[%x]\n", - __func__, adapter->macopts); - slic_config_set(adapter, TRUE); + slic_config_set(adapter, true); } else { if (status == STATUS_SUCCESS) slic_mcast_set_mask(adapter); @@ -1637,36 +1402,23 @@ static void slic_mcast_set_mask(struct adapter *adapter) { __iomem struct slic_regs *slic_regs = adapter->slic_regs; - DBG_MSG("%s ENTER (%s) macopts[%x] mask[%llx]\n", __func__, - adapter->netdev->name, (uint) adapter->macopts, - adapter->mcastmask); - if (adapter->macopts & (MAC_ALLMCAST | MAC_PROMISC)) { /* Turn on all multicast addresses. We have to do this for * promiscuous mode as well as ALLMCAST mode. It saves the * Microcode from having to keep state about the MAC * configuration. */ -/* DBG_MSG("slicoss: %s macopts = MAC_ALLMCAST | MAC_PROMISC\n\ - SLUT MODE!!!\n",__func__); */ - WRITE_REG(slic_regs->slic_mcastlow, 0xFFFFFFFF, FLUSH); - WRITE_REG(slic_regs->slic_mcasthigh, 0xFFFFFFFF, FLUSH); -/* DBG_MSG("%s (%s) WRITE to slic_regs slic_mcastlow&high 0xFFFFFFFF\n", - _func__, adapter->netdev->name); */ + slic_reg32_write(&slic_regs->slic_mcastlow, 0xFFFFFFFF, FLUSH); + slic_reg32_write(&slic_regs->slic_mcasthigh, 0xFFFFFFFF, + FLUSH); } else { /* Commit our multicast mast to the SLIC by writing to the * multicast address mask registers */ - DBG_MSG("%s (%s) WRITE mcastlow[%x] mcasthigh[%x]\n", - __func__, adapter->netdev->name, - ((ulong) (adapter->mcastmask & 0xFFFFFFFF)), - ((ulong) ((adapter->mcastmask >> 32) & 0xFFFFFFFF))); - - WRITE_REG(slic_regs->slic_mcastlow, - (u32) (adapter->mcastmask & 0xFFFFFFFF), FLUSH); - WRITE_REG(slic_regs->slic_mcasthigh, - (u32) ((adapter->mcastmask >> 32) & 0xFFFFFFFF), - FLUSH); + slic_reg32_write(&slic_regs->slic_mcastlow, + (u32)(adapter->mcastmask & 0xFFFFFFFF), FLUSH); + slic_reg32_write(&slic_regs->slic_mcasthigh, + (u32)((adapter->mcastmask >> 32) & 0xFFFFFFFF), FLUSH); } } @@ -1680,53 +1432,11 @@ static void slic_timer_ping(ulong dev) ASSERT(adapter); card = adapter->card; ASSERT(card); -#if !SLIC_DUMP_ENABLED -/*#if SLIC_DUMP_ENABLED*/ - if ((adapter->state == ADAPT_UP) && (card->state == CARD_UP)) { - int status; - if (card->pingstatus != ISR_PINGMASK) { - if (errormsg++ < 5) { - DBG_MSG - ("%s (%s) CARD HAS CRASHED PING_status == \ - %x ERRORMSG# %d\n", - __func__, adapter->netdev->name, - card->pingstatus, errormsg); - } - /* ASSERT(card->pingstatus == ISR_PINGMASK); */ - } else { - if (goodmsg++ < 5) { - DBG_MSG - ("slicoss: %s (%s) PING_status == %x \ - GOOD!!!!!!!! msg# %d\n", - __func__, adapter->netdev->name, - card->pingstatus, errormsg); - } - } - card->pingstatus = 0; - status = slic_upr_request(adapter, SLIC_UPR_PING, 0, 0, 0, 0); - - ASSERT(status == 0); - } else { - DBG_MSG("slicoss %s (%s) adapter[%p] NOT UP!!!!\n", - __func__, adapter->netdev->name, adapter); - } -#endif - adapter->pingtimer.expires = - jiffies + SLIC_SECS_TO_JIFFS(PING_TIMER_INTERVAL); + adapter->pingtimer.expires = jiffies + (PING_TIMER_INTERVAL * HZ); add_timer(&adapter->pingtimer); } -static void slic_if_stop_queue(struct adapter *adapter) -{ - netif_stop_queue(adapter->netdev); -} - -static void slic_if_start_queue(struct adapter *adapter) -{ - netif_start_queue(adapter->netdev); -} - /* * slic_if_init * @@ -1742,14 +1452,11 @@ static int slic_if_init(struct adapter *adapter) int status = 0; ASSERT(card); - DBG_MSG("slicoss: %s (%s) ENTER states[%d:%d:%d:%d] flags[%x]\n", - __func__, adapter->netdev->name, - adapter->queues_initialized, adapter->state, adapter->linkstate, - card->state, dev->flags); /* adapter should be down at this point */ if (adapter->state != ADAPT_DOWN) { - DBG_ERROR("slic_if_init adapter->state != ADAPT_DOWN\n"); + dev_err(&dev->dev, "%s: adapter->state != ADAPT_DOWN\n", + __func__); return -EIO; } ASSERT(adapter->linkstate == LINK_DOWN); @@ -1757,54 +1464,35 @@ static int slic_if_init(struct adapter *adapter) adapter->devflags_prev = dev->flags; adapter->macopts = MAC_DIRECTED; if (dev->flags) { - DBG_MSG("slicoss: %s (%s) Set MAC options: ", __func__, - adapter->netdev->name); - if (dev->flags & IFF_BROADCAST) { + if (dev->flags & IFF_BROADCAST) adapter->macopts |= MAC_BCAST; - DBG_MSG("BCAST "); - } - if (dev->flags & IFF_PROMISC) { + if (dev->flags & IFF_PROMISC) adapter->macopts |= MAC_PROMISC; - DBG_MSG("PROMISC "); - } - if (dev->flags & IFF_ALLMULTI) { + if (dev->flags & IFF_ALLMULTI) adapter->macopts |= MAC_ALLMCAST; - DBG_MSG("ALL_MCAST "); - } - if (dev->flags & IFF_MULTICAST) { + if (dev->flags & IFF_MULTICAST) adapter->macopts |= MAC_MCAST; - DBG_MSG("MCAST "); - } - DBG_MSG("\n"); } status = slic_adapter_allocresources(adapter); if (status != STATUS_SUCCESS) { - DBG_ERROR - ("slic_if_init: slic_adapter_allocresources FAILED %x\n", - status); + dev_err(&dev->dev, + "%s: slic_adapter_allocresources FAILED %x\n", + __func__, status); slic_adapter_freeresources(adapter); return status; } if (!adapter->queues_initialized) { - DBG_MSG("slicoss: %s call slic_rspqueue_init\n", __func__); if (slic_rspqueue_init(adapter)) return -ENOMEM; - DBG_MSG - ("slicoss: %s call slic_cmdq_init adapter[%p] port %d \n", - __func__, adapter, adapter->port); if (slic_cmdq_init(adapter)) return -ENOMEM; - DBG_MSG - ("slicoss: %s call slic_rcvqueue_init adapter[%p] \ - port %d \n", __func__, adapter, adapter->port); if (slic_rcvqueue_init(adapter)) return -ENOMEM; adapter->queues_initialized = 1; } - DBG_MSG("slicoss: %s disable interrupts(slic)\n", __func__); - WRITE_REG(slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); mdelay(1); if (!adapter->isp_initialized) { @@ -1814,13 +1502,13 @@ static int slic_if_init(struct adapter *adapter) adapter->bit64reglock.flags); #if defined(CONFIG_X86_64) - WRITE_REG(slic_regs->slic_addr_upper, - SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH); - WRITE_REG(slic_regs->slic_isp, - SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH); + slic_reg32_write(&slic_regs->slic_addr_upper, + SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH); + slic_reg32_write(&slic_regs->slic_isp, + SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH); #elif defined(CONFIG_X86) - WRITE_REG(slic_regs->slic_addr_upper, (u32) 0, DONT_FLUSH); - WRITE_REG(slic_regs->slic_isp, (u32) &pshmem->isr, FLUSH); + slic_reg32_write(&slic_regs->slic_addr_upper, 0, DONT_FLUSH); + slic_reg32_write(&slic_regs->slic_isp, (u32)&pshmem->isr, FLUSH); #else Stop Compilations #endif @@ -1833,66 +1521,44 @@ static int slic_if_init(struct adapter *adapter) if (!card->loadtimerset) { init_timer(&card->loadtimer); card->loadtimer.expires = - jiffies + SLIC_SECS_TO_JIFFS(SLIC_LOADTIMER_PERIOD); + jiffies + (SLIC_LOADTIMER_PERIOD * HZ); card->loadtimer.data = (ulong) card; card->loadtimer.function = &slic_timer_load_check; add_timer(&card->loadtimer); card->loadtimerset = 1; } -#if SLIC_GET_STATS_TIMER_ENABLED - if (!adapter->statstimerset) { - DBG_MSG("slicoss: %s start getstats_timer(slic)\n", - __func__); - init_timer(&adapter->statstimer); - adapter->statstimer.expires = - jiffies + SLIC_SECS_TO_JIFFS(STATS_TIMER_INTERVAL); - adapter->statstimer.data = (ulong) adapter->netdev; - adapter->statstimer.function = &slic_timer_get_stats; - add_timer(&adapter->statstimer); - adapter->statstimerset = 1; - } -#endif -#if !SLIC_DUMP_ENABLED && SLIC_PING_TIMER_ENABLED -/*#if SLIC_DUMP_ENABLED && SLIC_PING_TIMER_ENABLED*/ + if (!adapter->pingtimerset) { - DBG_MSG("slicoss: %s start card_ping_timer(slic)\n", - __func__); init_timer(&adapter->pingtimer); adapter->pingtimer.expires = - jiffies + SLIC_SECS_TO_JIFFS(PING_TIMER_INTERVAL); + jiffies + (PING_TIMER_INTERVAL * HZ); adapter->pingtimer.data = (ulong) dev; adapter->pingtimer.function = &slic_timer_ping; add_timer(&adapter->pingtimer); adapter->pingtimerset = 1; adapter->card->pingstatus = ISR_PINGMASK; } -#endif /* * clear any pending events, then enable interrupts */ - DBG_MSG("slicoss: %s ENABLE interrupts(slic)\n", __func__); adapter->isrcopy = 0; adapter->pshmem->isr = 0; - WRITE_REG(slic_regs->slic_isr, 0, FLUSH); - WRITE_REG(slic_regs->slic_icr, ICR_INT_ON, FLUSH); + slic_reg32_write(&slic_regs->slic_isr, 0, FLUSH); + slic_reg32_write(&slic_regs->slic_icr, ICR_INT_ON, FLUSH); - DBG_MSG("slicoss: %s call slic_link_config(slic)\n", __func__); slic_link_config(adapter, LINK_AUTOSPEED, LINK_AUTOD); slic_link_event_handler(adapter); - DBG_MSG("slicoss: %s EXIT\n", __func__); return STATUS_SUCCESS; } static void slic_unmap_mmio_space(struct adapter *adapter) { -#if LINUX_FREES_ADAPTER_RESOURCES if (adapter->slic_regs) iounmap(adapter->slic_regs); adapter->slic_regs = NULL; -#endif } static int slic_adapter_allocresources(struct adapter *adapter) @@ -1900,13 +1566,6 @@ static int slic_adapter_allocresources(struct adapter *adapter) if (!adapter->intrregistered) { int retval; - DBG_MSG - ("slicoss: %s AllocAdaptRsrcs adapter[%p] shmem[%p] \ - phys_shmem[%p] dev->irq[%x] %x\n", - __func__, adapter, adapter->pshmem, - (void *)adapter->phys_shmem, adapter->netdev->irq, - NR_IRQS); - spin_unlock_irqrestore(&slic_global.driver_lock.lock, slic_global.driver_lock.flags); @@ -1919,16 +1578,12 @@ static int slic_adapter_allocresources(struct adapter *adapter) slic_global.driver_lock.flags); if (retval) { - DBG_ERROR("slicoss: request_irq (%s) FAILED [%x]\n", - adapter->netdev->name, retval); + dev_err(&adapter->netdev->dev, + "request_irq (%s) FAILED [%x]\n", + adapter->netdev->name, retval); return retval; } adapter->intrregistered = 1; - DBG_MSG - ("slicoss: %s AllocAdaptRsrcs adapter[%p] shmem[%p] \ - pshmem[%p] dev->irq[%x]\n", - __func__, adapter, adapter->pshmem, - (void *)adapter->pshmem, adapter->netdev->irq); } return STATUS_SUCCESS; } @@ -1939,22 +1594,17 @@ static void slic_config_pci(struct pci_dev *pcidev) u16 new_command; pci_read_config_word(pcidev, PCI_COMMAND, &pci_command); - DBG_MSG("slicoss: %s PCI command[%4.4x]\n", __func__, pci_command); new_command = pci_command | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; - if (pci_command != new_command) { - DBG_MSG("%s -- Updating PCI COMMAND register %4.4x->%4.4x.\n", - __func__, pci_command, new_command); + if (pci_command != new_command) pci_write_config_word(pcidev, PCI_COMMAND, new_command); - } } static void slic_adapter_freeresources(struct adapter *adapter) { - DBG_MSG("slicoss: %s ENTER adapter[%p]\n", __func__, adapter); slic_init_cleanup(adapter); memset(&adapter->stats, 0, sizeof(struct net_device_stats)); adapter->error_interrupts = 0; @@ -1967,7 +1617,6 @@ static void slic_adapter_freeresources(struct adapter *adapter) adapter->rcv_broadcasts = 0; adapter->rcv_multicasts = 0; adapter->rcv_unicasts = 0; - DBG_MSG("slicoss: %s EXIT\n", __func__); } /* @@ -1979,21 +1628,15 @@ static void slic_adapter_freeresources(struct adapter *adapter) static void slic_link_config(struct adapter *adapter, u32 linkspeed, u32 linkduplex) { + u32 __iomem *wphy; u32 speed; u32 duplex; u32 phy_config; u32 phy_advreg; u32 phy_gctlreg; - if (adapter->state != ADAPT_UP) { - DBG_MSG - ("%s (%s) ADAPT Not up yet, Return! speed[%x] duplex[%x]\n", - __func__, adapter->netdev->name, linkspeed, - linkduplex); + if (adapter->state != ADAPT_UP) return; - } - DBG_MSG("slicoss: %s (%s) slic_link_config: speed[%x] duplex[%x]\n", - __func__, adapter->netdev->name, linkspeed, linkduplex); ASSERT((adapter->devid == SLIC_1GB_DEVICE_ID) || (adapter->devid == SLIC_2GB_DEVICE_ID)); @@ -2003,6 +1646,8 @@ static void slic_link_config(struct adapter *adapter, if (linkduplex > LINK_AUTOD) linkduplex = LINK_AUTOD; + wphy = &adapter->slic_regs->slic_wphy; + if ((linkspeed == LINK_AUTOSPEED) || (linkspeed == LINK_1000MB)) { if (adapter->flags & ADAPT_FLAGS_FIBERMEDIA) { /* We've got a fiber gigabit interface, and register @@ -2013,8 +1658,7 @@ static void slic_link_config(struct adapter *adapter, phy_advreg = (MIICR_REG_4 | (PAR_ADV1000XFD)); /* enable PAUSE frames */ phy_advreg |= PAR_ASYMPAUSE_FIBER; - WRITE_REG(adapter->slic_regs->slic_wphy, phy_advreg, - FLUSH); + slic_reg32_write(wphy, phy_advreg, FLUSH); if (linkspeed == LINK_AUTOSPEED) { /* reset phy, enable auto-neg */ @@ -2022,14 +1666,12 @@ static void slic_link_config(struct adapter *adapter, (MIICR_REG_PCR | (PCR_RESET | PCR_AUTONEG | PCR_AUTONEG_RST)); - WRITE_REG(adapter->slic_regs->slic_wphy, - phy_config, FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); } else { /* forced 1000 Mb FD*/ /* power down phy to break link this may not work) */ phy_config = (MIICR_REG_PCR | PCR_POWERDOWN); - WRITE_REG(adapter->slic_regs->slic_wphy, - phy_config, FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); /* wait, Marvell says 1 sec, try to get away with 10 ms */ mdelay(10); @@ -2040,8 +1682,7 @@ static void slic_link_config(struct adapter *adapter, (MIICR_REG_PCR | (PCR_RESET | PCR_SPEED_1000 | PCR_DUPLEX_FULL)); - WRITE_REG(adapter->slic_regs->slic_wphy, - phy_config, FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); } } else { /* copper gigabit */ @@ -2065,35 +1706,30 @@ static void slic_link_config(struct adapter *adapter, phy_advreg |= PAR_ASYMPAUSE; /* required by the Cicada PHY */ phy_advreg |= PAR_802_3; - WRITE_REG(adapter->slic_regs->slic_wphy, phy_advreg, - FLUSH); + slic_reg32_write(wphy, phy_advreg, FLUSH); /* advertise FD only @1000 Mb */ phy_gctlreg = (MIICR_REG_9 | (PGC_ADV1000FD)); - WRITE_REG(adapter->slic_regs->slic_wphy, phy_gctlreg, - FLUSH); + slic_reg32_write(wphy, phy_gctlreg, FLUSH); if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) { /* if a Marvell PHY enable auto crossover */ phy_config = (MIICR_REG_16 | (MRV_REG16_XOVERON)); - WRITE_REG(adapter->slic_regs->slic_wphy, - phy_config, FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); /* reset phy, enable auto-neg */ phy_config = (MIICR_REG_PCR | (PCR_RESET | PCR_AUTONEG | PCR_AUTONEG_RST)); - WRITE_REG(adapter->slic_regs->slic_wphy, - phy_config, FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); } else { /* it's a Cicada PHY */ /* enable and restart auto-neg (don't reset) */ phy_config = (MIICR_REG_PCR | (PCR_AUTONEG | PCR_AUTONEG_RST)); - WRITE_REG(adapter->slic_regs->slic_wphy, - phy_config, FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); } } } else { @@ -2111,13 +1747,12 @@ static void slic_link_config(struct adapter *adapter, /* if a Marvell PHY disable auto crossover */ phy_config = (MIICR_REG_16 | (MRV_REG16_XOVEROFF)); - WRITE_REG(adapter->slic_regs->slic_wphy, phy_config, - FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); } /* power down phy to break link (this may not work) */ phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN | speed | duplex)); - WRITE_REG(adapter->slic_regs->slic_wphy, phy_config, FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); /* wait, Marvell says 1 sec, try to get away with 10 ms */ mdelay(10); @@ -2128,43 +1763,17 @@ static void slic_link_config(struct adapter *adapter, soft reset phy, powerup */ phy_config = (MIICR_REG_PCR | (PCR_RESET | speed | duplex)); - WRITE_REG(adapter->slic_regs->slic_wphy, phy_config, - FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); } else { /* it's a Cicada PHY */ /* disable auto-neg, set speed, powerup */ phy_config = (MIICR_REG_PCR | (speed | duplex)); - WRITE_REG(adapter->slic_regs->slic_wphy, phy_config, - FLUSH); + slic_reg32_write(wphy, phy_config, FLUSH); } } - - DBG_MSG - ("slicoss: %s (%s) EXIT slic_link_config : state[%d] \ - phy_config[%x]\n", __func__, adapter->netdev->name, adapter->state, - phy_config); } static void slic_card_cleanup(struct sliccard *card) { - DBG_MSG("slicoss: %s ENTER\n", __func__); - -#if SLIC_DUMP_ENABLED - if (card->dumpbuffer) { - card->dumpbuffer_phys = 0; - card->dumpbuffer_physl = 0; - card->dumpbuffer_physh = 0; - kfree(card->dumpbuffer); - card->dumpbuffer = NULL; - } - if (card->cmdbuffer) { - card->cmdbuffer_phys = 0; - card->cmdbuffer_physl = 0; - card->cmdbuffer_physh = 0; - kfree(card->cmdbuffer); - card->cmdbuffer = NULL; - } -#endif - if (card->loadtimerset) { card->loadtimerset = 0; del_timer(&card->loadtimer); @@ -2173,7 +1782,6 @@ static void slic_card_cleanup(struct sliccard *card) slic_debug_card_destroy(card); kfree(card); - DBG_MSG("slicoss: %s EXIT\n", __func__); } static int slic_card_download_gbrcv(struct adapter *adapter) @@ -2183,15 +1791,16 @@ static int slic_card_download_gbrcv(struct adapter *adapter) int ret; __iomem struct slic_regs *slic_regs = adapter->slic_regs; u32 codeaddr; - unsigned char *instruction = NULL; + u32 instruction; + int index = 0; u32 rcvucodelen = 0; switch (adapter->devid) { case SLIC_2GB_DEVICE_ID: - file = "oasis_rcv.bin"; + file = "slicoss/oasisrcvucode.sys"; break; case SLIC_1GB_DEVICE_ID: - file = "gb_rcv.bin"; + file = "slicoss/gbrcvucode.sys"; break; default: ASSERT(0); @@ -2200,12 +1809,13 @@ static int slic_card_download_gbrcv(struct adapter *adapter) ret = request_firmware(&fw, file, &adapter->pcidev->dev); if (ret) { - printk(KERN_ERR "SLICOSS: Failed to load firmware %s\n", file); + dev_err(&adapter->pcidev->dev, + "SLICOSS: Failed to load firmware %s\n", file); return ret; } - instruction = (unsigned char *)fw->data; - rcvucodelen = fw->size; + rcvucodelen = *(u32 *)(fw->data + index); + index += 4; switch (adapter->devid) { case SLIC_2GB_DEVICE_ID: if (rcvucodelen != OasisRcvUCodeLen) @@ -2219,29 +1829,28 @@ static int slic_card_download_gbrcv(struct adapter *adapter) ASSERT(0); break; } - /* start download */ - WRITE_REG(slic_regs->slic_rcv_wcs, SLIC_RCVWCS_BEGIN, FLUSH); - + slic_reg32_write(&slic_regs->slic_rcv_wcs, SLIC_RCVWCS_BEGIN, FLUSH); /* download the rcv sequencer ucode */ for (codeaddr = 0; codeaddr < rcvucodelen; codeaddr++) { /* write out instruction address */ - WRITE_REG(slic_regs->slic_rcv_wcs, codeaddr, FLUSH); + slic_reg32_write(&slic_regs->slic_rcv_wcs, codeaddr, FLUSH); + instruction = *(u32 *)(fw->data + index); + index += 4; /* write out the instruction data low addr */ - WRITE_REG(slic_regs->slic_rcv_wcs, - (u32) *(u32 *) instruction, FLUSH); - instruction += 4; + slic_reg32_write(&slic_regs->slic_rcv_wcs, instruction, FLUSH); + instruction = *(u8 *)(fw->data + index); + index++; /* write out the instruction data high addr */ - WRITE_REG(slic_regs->slic_rcv_wcs, (u32) *instruction, - FLUSH); - instruction += 1; + slic_reg32_write(&slic_regs->slic_rcv_wcs, (u8)instruction, + FLUSH); } /* download finished */ release_firmware(fw); - WRITE_REG(slic_regs->slic_rcv_wcs, SLIC_RCVWCS_FINISH, FLUSH); + slic_reg32_write(&slic_regs->slic_rcv_wcs, SLIC_RCVWCS_FINISH, FLUSH); return 0; } @@ -2254,41 +1863,21 @@ static int slic_card_download(struct adapter *adapter) int thissectionsize; int codeaddr; __iomem struct slic_regs *slic_regs = adapter->slic_regs; - u32 *instruction = NULL; - u32 *lastinstruct = NULL; - u32 *startinstruct = NULL; - unsigned char *nextinstruct; + u32 instruction; u32 baseaddress; u32 failure; u32 i; u32 numsects = 0; u32 sectsize[3]; u32 sectstart[3]; - -/* DBG_MSG ("slicoss: %s (%s) adapter[%p] card[%p] devid[%x] \ - jiffies[%lx] cpu %d\n", __func__, adapter->netdev->name, adapter, - adapter->card, adapter->devid,jiffies, smp_processor_id()); */ + int ucode_start, index = 0; switch (adapter->devid) { case SLIC_2GB_DEVICE_ID: -/* DBG_MSG ("slicoss: %s devid==SLIC_2GB_DEVICE_ID sections[%x]\n", - __func__, (uint) ONumSections); */ - file = "slic_oasis.bin"; - numsects = ONumSections; - for (i = 0; i < numsects; i++) { - sectsize[i] = OSectionSize[i]; - sectstart[i] = OSectionStart[i]; - } + file = "slicoss/oasisdownload.sys"; break; case SLIC_1GB_DEVICE_ID: -/* DBG_MSG ("slicoss: %s devid==SLIC_1GB_DEVICE_ID sections[%x]\n", - __func__, (uint) MNumSections); */ - file = "slic_mojave.bin"; - numsects = MNumSections; - for (i = 0; i < numsects; i++) { - sectsize[i] = MSectionSize[i]; - sectstart[i] = MSectionStart[i]; - } + file = "slicoss/gbdownload.sys"; break; default: ASSERT(0); @@ -2296,131 +1885,84 @@ static int slic_card_download(struct adapter *adapter) } ret = request_firmware(&fw, file, &adapter->pcidev->dev); if (ret) { - printk(KERN_ERR "SLICOSS: Failed to load firmware %s\n", file); + dev_err(&adapter->pcidev->dev, + "SLICOSS: Failed to load firmware %s\n", file); return ret; } - + numsects = *(u32 *)(fw->data + index); + index += 4; ASSERT(numsects <= 3); - + for (i = 0; i < numsects; i++) { + sectsize[i] = *(u32 *)(fw->data + index); + index += 4; + } + for (i = 0; i < numsects; i++) { + sectstart[i] = *(u32 *)(fw->data + index); + index += 4; + } + ucode_start = index; + instruction = *(u32 *)(fw->data + index); + index += 4; for (section = 0; section < numsects; section++) { - switch (adapter->devid) { - case SLIC_2GB_DEVICE_ID: - instruction = (u32 *)(fw->data + (SECTION_SIZE * - section)); - baseaddress = sectstart[section]; - thissectionsize = sectsize[section] >> 3; - lastinstruct = - (u32 *)(fw->data + (SECTION_SIZE * section) + - sectsize[section] - 8); - break; - case SLIC_1GB_DEVICE_ID: - instruction = (u32 *)(fw->data + (SECTION_SIZE * - section)); - baseaddress = sectstart[section]; - thissectionsize = sectsize[section] >> 3; - lastinstruct = - (u32 *)(fw->data + (SECTION_SIZE * section) + - sectsize[section] - 8); - break; - default: - ASSERT(0); - break; - } - baseaddress = sectstart[section]; thissectionsize = sectsize[section] >> 3; for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) { - startinstruct = instruction; - nextinstruct = ((unsigned char *)instruction) + 8; /* Write out instruction address */ - WRITE_REG(slic_regs->slic_wcs, baseaddress + codeaddr, - FLUSH); + slic_reg32_write(&slic_regs->slic_wcs, + baseaddress + codeaddr, FLUSH); /* Write out instruction to low addr */ - WRITE_REG(slic_regs->slic_wcs, *instruction, FLUSH); -#ifdef CONFIG_X86_64 - instruction = (u32 *)((unsigned char *)instruction + 4); -#else - instruction++; -#endif + slic_reg32_write(&slic_regs->slic_wcs, instruction, FLUSH); + instruction = *(u32 *)(fw->data + index); + index += 4; + /* Write out instruction to high addr */ - WRITE_REG(slic_regs->slic_wcs, *instruction, FLUSH); -#ifdef CONFIG_X86_64 - instruction = (u32 *)((unsigned char *)instruction + 4); -#else - instruction++; -#endif + slic_reg32_write(&slic_regs->slic_wcs, instruction, FLUSH); + instruction = *(u32 *)(fw->data + index); + index += 4; } } - + index = ucode_start; for (section = 0; section < numsects; section++) { - switch (adapter->devid) { - case SLIC_2GB_DEVICE_ID: - instruction = (u32 *)fw->data + (SECTION_SIZE * - section); - break; - case SLIC_1GB_DEVICE_ID: - instruction = (u32 *)fw->data + (SECTION_SIZE * - section); - break; - default: - ASSERT(0); - break; - } - + instruction = *(u32 *)(fw->data + index); baseaddress = sectstart[section]; if (baseaddress < 0x8000) continue; thissectionsize = sectsize[section] >> 3; -/* DBG_MSG ("slicoss: COMPARE secton[%x] baseaddr[%x] sectnsize[%x]\n", - (uint)section,baseaddress,thissectionsize);*/ - for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) { /* Write out instruction address */ - WRITE_REG(slic_regs->slic_wcs, - SLIC_WCS_COMPARE | (baseaddress + codeaddr), - FLUSH); + slic_reg32_write(&slic_regs->slic_wcs, + SLIC_WCS_COMPARE | (baseaddress + codeaddr), + FLUSH); /* Write out instruction to low addr */ - WRITE_REG(slic_regs->slic_wcs, *instruction, FLUSH); -#ifdef CONFIG_X86_64 - instruction = (u32 *)((unsigned char *)instruction + 4); -#else - instruction++; -#endif + slic_reg32_write(&slic_regs->slic_wcs, instruction, + FLUSH); + instruction = *(u32 *)(fw->data + index); + index += 4; /* Write out instruction to high addr */ - WRITE_REG(slic_regs->slic_wcs, *instruction, FLUSH); -#ifdef CONFIG_X86_64 - instruction = (u32 *)((unsigned char *)instruction + 4); -#else - instruction++; -#endif + slic_reg32_write(&slic_regs->slic_wcs, instruction, + FLUSH); + instruction = *(u32 *)(fw->data + index); + index += 4; + /* Check SRAM location zero. If it is non-zero. Abort.*/ - failure = readl((u32 __iomem *)&slic_regs->slic_reset); +/* failure = readl((u32 __iomem *)&slic_regs->slic_reset); if (failure) { - DBG_MSG - ("slicoss: %s FAILURE EXIT codeaddr[%x] \ - thissectionsize[%x] failure[%x]\n", - __func__, codeaddr, thissectionsize, - failure); release_firmware(fw); return -EIO; - } + }*/ } } -/* DBG_MSG ("slicoss: Compare done\n");*/ release_firmware(fw); /* Everything OK, kick off the card */ mdelay(10); - WRITE_REG(slic_regs->slic_wcs, SLIC_WCS_START, FLUSH); + slic_reg32_write(&slic_regs->slic_wcs, SLIC_WCS_START, FLUSH); /* stall for 20 ms, long enough for ucode to init card and reach mainloop */ mdelay(20); - DBG_MSG("slicoss: %s (%s) EXIT adapter[%p] card[%p]\n", - __func__, adapter->netdev->name, adapter, adapter->card); - return STATUS_SUCCESS; } @@ -2428,19 +1970,10 @@ static void slic_adapter_set_hwaddr(struct adapter *adapter) { struct sliccard *card = adapter->card; -/* DBG_MSG ("%s ENTER card->config_set[%x] port[%d] physport[%d] funct#[%d]\n", - __func__, card->config_set, adapter->port, adapter->physport, - adapter->functionnumber); - - slic_dbg_macaddrs(adapter); */ - if ((adapter->card) && (card->config_set)) { memcpy(adapter->macaddr, card->config.MacInfo[adapter->functionnumber].macaddrA, sizeof(struct slic_config_mac)); -/* DBG_MSG ("%s AFTER copying from config.macinfo into currmacaddr\n", - __func__); - slic_dbg_macaddrs(adapter);*/ if (!(adapter->currmacaddr[0] || adapter->currmacaddr[1] || adapter->currmacaddr[2] || adapter->currmacaddr[3] || adapter->currmacaddr[4] || adapter->currmacaddr[5])) { @@ -2451,15 +1984,11 @@ static void slic_adapter_set_hwaddr(struct adapter *adapter) 6); } } -/* DBG_MSG ("%s EXIT port %d\n", __func__, adapter->port); - slic_dbg_macaddrs(adapter); */ } static void slic_intagg_set(struct adapter *adapter, u32 value) { - __iomem struct slic_regs *slic_regs = adapter->slic_regs; - - WRITE_REG(slic_regs->slic_intagg, value, FLUSH); + slic_reg32_write(&adapter->slic_regs->slic_intagg, value, FLUSH); adapter->card->loadlevel_current = value; } @@ -2485,10 +2014,6 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) struct atk_fru *patkfru; union oemfru *poemfru; - DBG_MSG - ("slicoss: %s ENTER card[%p] adapter[%p] card->state[%x] \ - size[%d]\n", __func__, card, adapter, card->state, card->card_size); - /* Reset everything except PCI configuration space */ slic_soft_reset(adapter); @@ -2496,9 +2021,9 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) status = slic_card_download(adapter); if (status != STATUS_SUCCESS) { - DBG_ERROR("SLIC download failed bus %d slot %d\n", - (uint) adapter->busnumber, - (uint) adapter->slotnumber); + dev_err(&adapter->pcidev->dev, + "download failed bus %d slot %d\n", + adapter->busnumber, adapter->slotnumber); return status; } @@ -2510,33 +2035,24 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) phys_configl = SLIC_GET_ADDR_LOW(phys_config); phys_configh = SLIC_GET_ADDR_HIGH(phys_config); - DBG_MSG("slicoss: %s Eeprom info adapter [%p]\n " - "size [%x]\n peeprom [%p]\n " - "phys_config [%p]\n phys_configl[%x]\n " - "phys_configh[%x]\n", - __func__, adapter, - (u32)sizeof(struct slic_eeprom), - peeprom, (void *) phys_config, phys_configl, - phys_configh); if (!peeprom) { - DBG_ERROR - ("SLIC eeprom read failed to get memory bus %d \ - slot %d\n", - (uint) adapter->busnumber, - (uint) adapter->slotnumber); + dev_err(&adapter->pcidev->dev, + "eeprom read failed to get memory " + "bus %d slot %d\n", adapter->busnumber, + adapter->slotnumber); return -ENOMEM; } else { memset(peeprom, 0, sizeof(struct slic_eeprom)); } - WRITE_REG(slic_regs->slic_icr, ICR_INT_OFF, FLUSH); + slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH); mdelay(1); pshmem = (struct slic_shmem *)adapter->phys_shmem; spin_lock_irqsave(&adapter->bit64reglock.lock, adapter->bit64reglock.flags); - WRITE_REG(slic_regs->slic_addr_upper, 0, DONT_FLUSH); - WRITE_REG(slic_regs->slic_isp, - SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH); + slic_reg32_write(&slic_regs->slic_addr_upper, 0, DONT_FLUSH); + slic_reg32_write(&slic_regs->slic_isp, + SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH); spin_unlock_irqrestore(&adapter->bit64reglock.lock, adapter->bit64reglock.flags); @@ -2544,41 +2060,33 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) for (;;) { if (adapter->pshmem->isr) { - DBG_MSG("%s shmem[%p] shmem->isr[%x]\n", - __func__, adapter->pshmem, - adapter->pshmem->isr); - if (adapter->pshmem->isr & ISR_UPC) { adapter->pshmem->isr = 0; - WRITE_REG64(adapter, - slic_regs->slic_isp, - 0, - slic_regs->slic_addr_upper, - 0, FLUSH); - WRITE_REG(slic_regs->slic_isr, 0, - FLUSH); + slic_reg64_write(adapter, + &slic_regs->slic_isp, 0, + &slic_regs->slic_addr_upper, + 0, FLUSH); + slic_reg32_write(&slic_regs->slic_isr, + 0, FLUSH); slic_upr_request_complete(adapter, 0); break; } else { adapter->pshmem->isr = 0; - WRITE_REG(slic_regs->slic_isr, 0, - FLUSH); + slic_reg32_write(&slic_regs->slic_isr, + 0, FLUSH); } } else { mdelay(1); i++; if (i > 5000) { - DBG_ERROR - ("SLIC: %d config data fetch timed\ - out!\n", adapter->port); - DBG_MSG("%s shmem[%p] shmem->isr[%x]\n", - __func__, adapter->pshmem, - adapter->pshmem->isr); - WRITE_REG64(adapter, - slic_regs->slic_isp, 0, - slic_regs->slic_addr_upper, - 0, FLUSH); + dev_err(&adapter->pcidev->dev, + "%d config data fetch timed out!\n", + adapter->port); + slic_reg64_write(adapter, + &slic_regs->slic_isp, 0, + &slic_regs->slic_addr_upper, + 0, FLUSH); return -EINVAL; } } @@ -2614,7 +2122,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) break; } - card->config.EepromValid = FALSE; + card->config.EepromValid = false; /* see if the EEPROM is valid by checking it's checksum */ if ((eecodesize <= MAX_EECODE_SIZE) && @@ -2633,7 +2141,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) we wouldn't need this shit */ if (ee_chksum == calc_chksum) - card->config.EepromValid = TRUE; + card->config.EepromValid = true; } /* copy in the DRAM size */ card->config.DramSize = dramsize; @@ -2643,8 +2151,6 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) memcpy(&card->config.MacInfo[i], &pmac[i], sizeof(struct slic_config_mac)); } -/* DBG_MSG ("%s EEPROM Checksum Good? %d MacAddress\n",__func__, - card->config.EepromValid); */ /* copy the Alacritech FRU information */ card->config.FruFormat = fruformat; @@ -2654,20 +2160,14 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) pci_free_consistent(adapter->pcidev, sizeof(struct slic_eeprom), peeprom, phys_config); - DBG_MSG - ("slicoss: %s adapter%d [%p] size[%x] FREE peeprom[%p] \ - phys_config[%p]\n", - __func__, adapter->port, adapter, - (u32) sizeof(struct slic_eeprom), peeprom, - (void *) phys_config); if ((!card->config.EepromValid) && (adapter->reg_params.fail_on_bad_eeprom)) { - WRITE_REG64(adapter, - slic_regs->slic_isp, - 0, slic_regs->slic_addr_upper, 0, FLUSH); - DBG_ERROR - ("unsupported CONFIGURATION EEPROM invalid\n"); + slic_reg64_write(adapter, &slic_regs->slic_isp, 0, + &slic_regs->slic_addr_upper, + 0, FLUSH); + dev_err(&adapter->pcidev->dev, + "unsupported CONFIGURATION EEPROM invalid\n"); return -EINVAL; } @@ -2675,74 +2175,26 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) } if (slic_card_download_gbrcv(adapter)) { - DBG_ERROR("%s unable to download GB receive microcode\n", - __func__); + dev_err(&adapter->pcidev->dev, + "unable to download GB receive microcode\n"); return -EINVAL; } - if (slic_global.dynamic_intagg) { - DBG_MSG - ("Dynamic Interrupt Aggregation[ENABLED]: slic%d \ - SET intagg to %d\n", - card->cardnum, 0); + if (slic_global.dynamic_intagg) slic_intagg_set(adapter, 0); - } else { + else slic_intagg_set(adapter, intagg_delay); - DBG_MSG - ("Dynamic Interrupt Aggregation[DISABLED]: slic%d \ - SET intagg to %d\n", - card->cardnum, intagg_delay); - } /* * Initialize ping status to "ok" */ card->pingstatus = ISR_PINGMASK; -#if SLIC_DUMP_ENABLED - if (!card->dumpbuffer) { - card->dumpbuffer = kmalloc(DUMP_PAGE_SIZE, GFP_ATOMIC); - - ASSERT(card->dumpbuffer); - if (card->dumpbuffer == NULL) - return -ENOMEM; - } - /* - * Smear the shared memory structure and then obtain - * the PHYSICAL address of this structure - */ - memset(card->dumpbuffer, 0, DUMP_PAGE_SIZE); - card->dumpbuffer_phys = virt_to_bus(card->dumpbuffer); - card->dumpbuffer_physh = SLIC_GET_ADDR_HIGH(card->dumpbuffer_phys); - card->dumpbuffer_physl = SLIC_GET_ADDR_LOW(card->dumpbuffer_phys); - - /* - * Allocate COMMAND BUFFER - */ - if (!card->cmdbuffer) { - card->cmdbuffer = kmalloc(sizeof(struct dump_cmd), GFP_ATOMIC); - - ASSERT(card->cmdbuffer); - if (card->cmdbuffer == NULL) - return -ENOMEM; - } - /* - * Smear the shared memory structure and then obtain - * the PHYSICAL address of this structure - */ - memset(card->cmdbuffer, 0, sizeof(struct dump_cmd)); - card->cmdbuffer_phys = virt_to_bus(card->cmdbuffer); - card->cmdbuffer_physh = SLIC_GET_ADDR_HIGH(card->cmdbuffer_phys); - card->cmdbuffer_physl = SLIC_GET_ADDR_LOW(card->cmdbuffer_phys); -#endif - /* * Lastly, mark our card state as up and return success */ card->state = CARD_UP; card->reset_in_progress = 0; - DBG_MSG("slicoss: %s EXIT card[%p] adapter[%p] card->state[%x]\n", - __func__, card, adapter, card->state); return STATUS_SUCCESS; } @@ -2756,10 +2208,6 @@ static u32 slic_card_locate(struct adapter *adapter) uint i; uint rdhostid_offset = 0; - DBG_MSG("slicoss: %s adapter[%p] slot[%x] bus[%x] port[%x]\n", - __func__, adapter, adapter->slotnumber, adapter->busnumber, - adapter->port); - switch (adapter->devid) { case SLIC_2GB_DEVICE_ID: rdhostid_offset = SLIC_RDHOSTID_2GB; @@ -2775,11 +2223,9 @@ static u32 slic_card_locate(struct adapter *adapter) hostid_reg = (u16 __iomem *) (((u8 __iomem *) (adapter->slic_regs)) + rdhostid_offset); - DBG_MSG("slicoss: %s *hostid_reg[%p] == ", __func__, hostid_reg); /* read the 16 bit hostid from SRAM */ card_hostid = (ushort) readw(hostid_reg); - DBG_MSG(" card_hostid[%x]\n", card_hostid); /* Initialize a new card structure if need be */ if (card_hostid == SLIC_HOSTID_DEFAULT) { @@ -2789,17 +2235,6 @@ static u32 slic_card_locate(struct adapter *adapter) card->next = slic_global.slic_card; slic_global.slic_card = card; -#if DBG - if (adapter->devid == SLIC_2GB_DEVICE_ID) { - DBG_MSG - ("SLICOSS ==> Initialize 2 Port Gigabit Server \ - and Storage Accelerator\n"); - } else { - DBG_MSG - ("SLICOSS ==> Initialize 1 Port Gigabit Server \ - and Storage Accelerator\n"); - } -#endif card->busnumber = adapter->busnumber; card->slotnumber = adapter->slotnumber; @@ -2812,23 +2247,11 @@ static u32 slic_card_locate(struct adapter *adapter) } } slic_global.num_slic_cards++; - DBG_MSG("\nCARDNUM == %d Total %d Card[%p]\n\n", - card->cardnum, slic_global.num_slic_cards, card); slic_debug_card_create(card); } else { - DBG_MSG - ("slicoss: %s CARD already allocated, find the \ - correct card\n", __func__); /* Card exists, find the card this adapter belongs to */ while (card) { - DBG_MSG - ("slicoss: %s card[%p] slot[%x] bus[%x] \ - adaptport[%p] hostid[%x] cardnum[%x]\n", - __func__, card, card->slotnumber, - card->busnumber, card->adapter[adapter->port], - card_hostid, card->cardnum); - if (card->cardnum == card_hostid) break; card = card->next; @@ -2861,14 +2284,9 @@ static u32 slic_card_locate(struct adapter *adapter) } if (!physcard) { /* no structure allocated for this physical card yet */ - physcard = kzalloc(sizeof(struct physcard), GFP_ATOMIC); + physcard = kzalloc(sizeof(struct physcard), GFP_KERNEL); ASSERT(physcard); - DBG_MSG - ("\n%s Allocate a PHYSICALcard:\n PHYSICAL_Card[%p]\n\ - LogicalCard [%p]\n adapter [%p]\n", - __func__, physcard, card, adapter); - physcard->next = slic_global.phys_card; slic_global.phys_card = physcard; physcard->adapters_allocd = 1; @@ -2881,8 +2299,6 @@ static u32 slic_card_locate(struct adapter *adapter) ASSERT(physcard->adapter[adapter->physport] == NULL); physcard->adapter[adapter->physport] = adapter; adapter->physcard = physcard; - DBG_MSG(" PHYSICAL_Port %d Logical_Port %d\n", adapter->physport, - adapter->port); return 0; } @@ -2890,16 +2306,12 @@ static u32 slic_card_locate(struct adapter *adapter) static void slic_soft_reset(struct adapter *adapter) { if (adapter->card->state == CARD_UP) { - DBG_MSG("slicoss: %s QUIESCE adapter[%p] card[%p] devid[%x]\n", - __func__, adapter, adapter->card, adapter->devid); - WRITE_REG(adapter->slic_regs->slic_quiesce, 0, FLUSH); + slic_reg32_write(&adapter->slic_regs->slic_quiesce, 0, FLUSH); mdelay(1); } -/* DBG_MSG ("slicoss: %s (%s) adapter[%p] card[%p] devid[%x]\n", - __func__, adapter->netdev->name, adapter, adapter->card, - adapter->devid); */ - WRITE_REG(adapter->slic_regs->slic_reset, SLIC_RESET_MAGIC, FLUSH); + slic_reg32_write(&adapter->slic_regs->slic_reset, SLIC_RESET_MAGIC, + FLUSH); mdelay(1); } @@ -2909,10 +2321,6 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) u32 RcrReset; __iomem struct slic_regs *slic_regs = adapter->slic_regs; - DBG_MSG("slicoss: %s (%s) slic_interface_enable[%p](%d)\n", - __func__, adapter->netdev->name, adapter, - adapter->cardindex); - if (linkchange) { /* Setup MAC */ slic_mac_config(adapter); @@ -2928,9 +2336,7 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) GXCR_XMTEN | /* Enable transmit */ GXCR_PAUSEEN); /* Enable pause */ - DBG_MSG("slicoss: FDX adapt[%p] set xmtcfg to [%x]\n", adapter, - value); - WRITE_REG(slic_regs->slic_wxcfg, value, FLUSH); + slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH); /* Setup rcvcfg last */ value = (RcrReset | /* Reset, if linkchange */ @@ -2943,9 +2349,7 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) value = (GXCR_RESET | /* Always reset */ GXCR_XMTEN); /* Enable transmit */ - DBG_MSG("slicoss: HDX adapt[%p] set xmtcfg to [%x]\n", adapter, - value); - WRITE_REG(slic_regs->slic_wxcfg, value, FLUSH); + slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH); /* Setup rcvcfg last */ value = (RcrReset | /* Reset, if linkchange */ @@ -2962,8 +2366,7 @@ static void slic_config_set(struct adapter *adapter, bool linkchange) if (adapter->macopts & MAC_PROMISC) value |= GRCR_RCVALL; - DBG_MSG("slicoss: adapt[%p] set rcvcfg to [%x]\n", adapter, value); - WRITE_REG(slic_regs->slic_wrcfg, value, FLUSH); + slic_reg32_write(&slic_regs->slic_wrcfg, value, FLUSH); } /* @@ -2979,18 +2382,18 @@ static void slic_config_clear(struct adapter *adapter) value = (GXCR_RESET | /* Always reset */ GXCR_PAUSEEN); /* Enable pause */ - WRITE_REG(slic_regs->slic_wxcfg, value, FLUSH); + slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH); value = (GRCR_RESET | /* Always reset */ GRCR_CTLEN | /* Enable CTL frames */ GRCR_ADDRAEN | /* Address A enable */ (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT)); - WRITE_REG(slic_regs->slic_wrcfg, value, FLUSH); + slic_reg32_write(&slic_regs->slic_wrcfg, value, FLUSH); /* power down phy */ phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN)); - WRITE_REG(slic_regs->slic_wphy, phy_config, FLUSH); + slic_reg32_write(&slic_regs->slic_wphy, phy_config, FLUSH); } static void slic_config_get(struct adapter *adapter, u32 config, @@ -3012,18 +2415,14 @@ static void slic_mac_address_config(struct adapter *adapter) value = *(u32 *) &adapter->currmacaddr[2]; value = ntohl(value); - WRITE_REG(slic_regs->slic_wraddral, value, FLUSH); - WRITE_REG(slic_regs->slic_wraddrbl, value, FLUSH); + slic_reg32_write(&slic_regs->slic_wraddral, value, FLUSH); + slic_reg32_write(&slic_regs->slic_wraddrbl, value, FLUSH); value2 = (u32) ((adapter->currmacaddr[0] << 8 | adapter->currmacaddr[1]) & 0xFFFF); - WRITE_REG(slic_regs->slic_wraddrah, value2, FLUSH); - WRITE_REG(slic_regs->slic_wraddrbh, value2, FLUSH); - - DBG_MSG("%s value1[%x] value2[%x] Call slic_mcast_set_mask\n", - __func__, value, value2); - slic_dbg_macaddrs(adapter); + slic_reg32_write(&slic_regs->slic_wraddrah, value2, FLUSH); + slic_reg32_write(&slic_regs->slic_wraddrbh, value2, FLUSH); /* Write our multicast mask out to the card. This is done */ /* here in addition to the slic_mcast_addr_set routine */ @@ -3058,7 +2457,7 @@ static void slic_mac_config(struct adapter *adapter) } /* write mac config */ - WRITE_REG(slic_regs->slic_wmcfg, value, FLUSH); + slic_reg32_write(&slic_regs->slic_wmcfg, value, FLUSH); /* setup mac addresses */ slic_mac_address_config(adapter); @@ -3072,18 +2471,15 @@ static bool slic_mac_filter(struct adapter *adapter, u16 *dhost2 = (u16 *)ðer_frame->ether_dhost[4]; bool equaladdr; - if (opts & MAC_PROMISC) { - DBG_MSG("slicoss: %s (%s) PROMISCUOUS. Accept frame\n", - __func__, adapter->netdev->name); - return TRUE; - } + if (opts & MAC_PROMISC) + return true; if ((*dhost4 == 0xFFFFFFFF) && (*dhost2 == 0xFFFF)) { if (opts & MAC_BCAST) { adapter->rcv_broadcasts++; - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -3091,7 +2487,7 @@ static bool slic_mac_filter(struct adapter *adapter, if (opts & MAC_ALLMCAST) { adapter->rcv_multicasts++; adapter->stats.multicast++; - return TRUE; + return true; } if (opts & MAC_MCAST) { struct mcast_address *mcaddr = adapter->mcastaddrs; @@ -3103,20 +2499,20 @@ static bool slic_mac_filter(struct adapter *adapter, if (equaladdr) { adapter->rcv_multicasts++; adapter->stats.multicast++; - return TRUE; + return true; } mcaddr = mcaddr->next; } - return FALSE; + return false; } else { - return FALSE; + return false; } } if (opts & MAC_DIRECTED) { adapter->rcv_unicasts++; - return TRUE; + return true; } - return FALSE; + return false; } @@ -3125,80 +2521,28 @@ static int slic_mac_set_address(struct net_device *dev, void *ptr) struct adapter *adapter = (struct adapter *)netdev_priv(dev); struct sockaddr *addr = ptr; - DBG_MSG("%s ENTER (%s)\n", __func__, adapter->netdev->name); - if (netif_running(dev)) return -EBUSY; if (!adapter) return -EBUSY; - DBG_MSG("slicoss: %s (%s) curr %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", - __func__, adapter->netdev->name, adapter->currmacaddr[0], - adapter->currmacaddr[1], adapter->currmacaddr[2], - adapter->currmacaddr[3], adapter->currmacaddr[4], - adapter->currmacaddr[5]); + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); memcpy(adapter->currmacaddr, addr->sa_data, dev->addr_len); - DBG_MSG("slicoss: %s (%s) new %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", - __func__, adapter->netdev->name, adapter->currmacaddr[0], - adapter->currmacaddr[1], adapter->currmacaddr[2], - adapter->currmacaddr[3], adapter->currmacaddr[4], - adapter->currmacaddr[5]); - slic_config_set(adapter, TRUE); + slic_config_set(adapter, true); return 0; } -/* - * slic_timer_get_stats - * - * Timer function used to suck the statistics out of the card every - * 50 seconds or whatever STATS_TIMER_INTERVAL is set to. - * - */ -#if SLIC_GET_STATS_TIMER_ENABLED -static void slic_timer_get_stats(ulong dev) -{ - struct adapter *adapter; - struct sliccard *card; - struct slic_shmem *pshmem; - - ASSERT(dev); - adapter = netdev_priv((struct net_device *)dev); - ASSERT(adapter); - card = adapter->card; - ASSERT(card); - - if ((card->state == CARD_UP) && - (adapter->state == ADAPT_UP) && (adapter->linkstate == LINK_UP)) { - pshmem = (struct slic_shmem *)adapter->phys_shmem; -#ifdef CONFIG_X86_64 - slic_upr_request(adapter, - SLIC_UPR_STATS, - SLIC_GET_ADDR_LOW(&pshmem->inicstats), - SLIC_GET_ADDR_HIGH(&pshmem->inicstats), 0, 0); -#elif defined(CONFIG_X86) - slic_upr_request(adapter, - SLIC_UPR_STATS, - (u32) &pshmem->inicstats, 0, 0, 0); -#else - Stop compilation; -#endif - } else { -/* DBG_MSG ("slicoss: %s adapter[%p] linkstate[%x] NOT UP!\n", - __func__, adapter, adapter->linkstate); */ - } - adapter->statstimer.expires = jiffies + - SLIC_SECS_TO_JIFFS(STATS_TIMER_INTERVAL); - add_timer(&adapter->statstimer); -} -#endif static void slic_timer_load_check(ulong cardaddr) { struct sliccard *card = (struct sliccard *)cardaddr; struct adapter *adapter = card->master; + u32 __iomem *intagg; u32 load = card->events; u32 level = 0; + intagg = &adapter->slic_regs->slic_intagg; + if ((adapter) && (adapter->state == ADAPT_UP) && (card->state == CARD_UP) && (slic_global.dynamic_intagg)) { if (adapter->devid == SLIC_1GB_DEVICE_ID) { @@ -3220,8 +2564,7 @@ static void slic_timer_load_check(ulong cardaddr) } if (card->loadlevel_current != level) { card->loadlevel_current = level; - WRITE_REG(adapter->slic_regs->slic_intagg, - level, FLUSH); + slic_reg32_write(intagg, level, FLUSH); } } else { if (load > SLIC_LOAD_5) @@ -3238,14 +2581,12 @@ static void slic_timer_load_check(ulong cardaddr) level = SLIC_INTAGG_0; if (card->loadlevel_current != level) { card->loadlevel_current = level; - WRITE_REG(adapter->slic_regs->slic_intagg, - level, FLUSH); + slic_reg32_write(intagg, level, FLUSH); } } } card->events = 0; - card->loadtimer.expires = - jiffies + SLIC_SECS_TO_JIFFS(SLIC_LOADTIMER_PERIOD); + card->loadtimer.expires = jiffies + (SLIC_LOADTIMER_PERIOD * HZ); add_timer(&card->loadtimer); } @@ -3256,7 +2597,8 @@ static void slic_assert_fail(void) cpuid = smp_processor_id(); curr_pid = current->pid; - DBG_ERROR("%s CPU # %d ---- PID # %d\n", __func__, cpuid, curr_pid); + printk(KERN_ERR "%s CPU # %d ---- PID # %d\n", + __func__, cpuid, curr_pid); } static int slic_upr_queue_request(struct adapter *adapter, @@ -3269,11 +2611,9 @@ static int slic_upr_queue_request(struct adapter *adapter, struct slic_upr *uprqueue; upr = kmalloc(sizeof(struct slic_upr), GFP_ATOMIC); - if (!upr) { - DBG_MSG("%s COULD NOT ALLOCATE UPR MEM\n", __func__); - + if (!upr) return -ENOMEM; - } + upr->adapter = adapter->port; upr->upr_request = upr_request; upr->upr_data = upr_data; @@ -3322,10 +2662,6 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr) struct sliccard *card = adapter->card; struct slic_upr *upr; -/* if (card->dump_requested) { - DBG_MSG("ENTER slic_upr_request_complete Dump in progress ISR[%x]\n", - isr); - } */ spin_lock_irqsave(&adapter->upr_lock.lock, adapter->upr_lock.flags); upr = adapter->upr_list; if (!upr) { @@ -3341,38 +2677,19 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr) switch (upr->upr_request) { case SLIC_UPR_STATS: { -#if SLIC_GET_STATS_ENABLED struct slic_stats *slicstats = (struct slic_stats *) &adapter->pshmem->inicstats; struct slic_stats *newstats = slicstats; struct slic_stats *old = &adapter->inicstats_prev; struct slicnet_stats *stst = &adapter->slic_stats; -#endif + if (isr & ISR_UPCERR) { - DBG_ERROR - ("SLIC_UPR_STATS command failed isr[%x]\n", - isr); + dev_err(&adapter->netdev->dev, + "SLIC_UPR_STATS command failed isr[%x]\n", + isr); break; } -#if SLIC_GET_STATS_ENABLED -/* DBG_MSG ("slicoss: %s rcv %lx:%lx:%lx:%lx:%lx %lx %lx " - "xmt %lx:%lx:%lx:%lx:%lx %lx %lx\n", - __func__, - slicstats->rcv_unicasts100, - slicstats->rcv_bytes100, - slicstats->rcv_bytes100, - slicstats->rcv_tcp_bytes100, - slicstats->rcv_tcp_segs100, - slicstats->rcv_other_error100, - slicstats->rcv_drops100, - slicstats->xmit_unicasts100, - slicstats->xmit_bytes100, - slicstats->xmit_bytes100, - slicstats->xmit_tcp_bytes100, - slicstats->xmit_tcp_segs100, - slicstats->xmit_other_error100, - slicstats->xmit_collisions100);*/ UPDATE_STATS_GB(stst->tcp.xmit_tcp_segs, newstats->xmit_tcp_segs_gb, old->xmit_tcp_segs_gb); @@ -3431,7 +2748,6 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr) old->rcv_drops_gb); } memcpy(old, newstats, sizeof(struct slic_stats)); -#endif break; } case SLIC_UPR_RLSR: @@ -3454,11 +2770,6 @@ static void slic_upr_request_complete(struct adapter *adapter, u32 isr) case SLIC_UPR_PING: card->pingstatus |= (isr & ISR_PINGDSMASK); break; -#if SLIC_DUMP_ENABLED - case SLIC_UPR_DUMP: - card->dumpstatus |= (isr & ISR_UPCMASK); - break; -#endif default: ASSERT(0); } @@ -3487,74 +2798,29 @@ static void slic_upr_start(struct adapter *adapter) switch (upr->upr_request) { case SLIC_UPR_STATS: if (upr->upr_data_h == 0) { - WRITE_REG(slic_regs->slic_stats, upr->upr_data, FLUSH); + slic_reg32_write(&slic_regs->slic_stats, upr->upr_data, + FLUSH); } else { - WRITE_REG64(adapter, - slic_regs->slic_stats64, - upr->upr_data, - slic_regs->slic_addr_upper, - upr->upr_data_h, FLUSH); + slic_reg64_write(adapter, &slic_regs->slic_stats64, + upr->upr_data, + &slic_regs->slic_addr_upper, + upr->upr_data_h, FLUSH); } break; case SLIC_UPR_RLSR: - WRITE_REG64(adapter, - slic_regs->slic_rlsr, - upr->upr_data, - slic_regs->slic_addr_upper, upr->upr_data_h, FLUSH); + slic_reg64_write(adapter, &slic_regs->slic_rlsr, upr->upr_data, + &slic_regs->slic_addr_upper, upr->upr_data_h, + FLUSH); break; case SLIC_UPR_RCONFIG: - DBG_MSG("%s SLIC_UPR_RCONFIG!!!!\n", __func__); - DBG_MSG("WRITE_REG64 adapter[%p]\n" - " a->slic_regs[%p] slic_regs[%p]\n" - " &slic_rconfig[%p] &slic_addr_upper[%p]\n" - " upr[%p]\n" - " uprdata[%x] uprdatah[%x]\n", - adapter, adapter->slic_regs, slic_regs, - &slic_regs->slic_rconfig, &slic_regs->slic_addr_upper, - upr, upr->upr_data, upr->upr_data_h); - WRITE_REG64(adapter, - slic_regs->slic_rconfig, - upr->upr_data, - slic_regs->slic_addr_upper, upr->upr_data_h, FLUSH); + slic_reg64_write(adapter, &slic_regs->slic_rconfig, + upr->upr_data, &slic_regs->slic_addr_upper, + upr->upr_data_h, FLUSH); break; -#if SLIC_DUMP_ENABLED - case SLIC_UPR_DUMP: -#if 0 - DBG_MSG("%s SLIC_UPR_DUMP!!!!\n", __func__); - DBG_MSG("WRITE_REG64 adapter[%p]\n" - " upr_buffer[%x] upr_bufferh[%x]\n" - " upr_data[%x] upr_datah[%x]\n" - " cmdbuff[%p] cmdbuffP[%p]\n" - " dumpbuff[%p] dumpbuffP[%p]\n", - adapter, upr->upr_buffer, upr->upr_buffer_h, - upr->upr_data, upr->upr_data_h, - adapter->card->cmdbuffer, - (void *)adapter->card->cmdbuffer_phys, - adapter->card->dumpbuffer, ( - void *)adapter->card->dumpbuffer_phys); - - ptr1 = (char *)slic_regs; - ptr2 = (char *)(&slic_regs->slic_dump_cmd); - cmdoffset = ptr2 - ptr1; - DBG_MSG("slic_dump_cmd register offset [%x]\n", cmdoffset); -#endif - if (upr->upr_buffer || upr->upr_buffer_h) { - WRITE_REG64(adapter, - slic_regs->slic_dump_data, - upr->upr_buffer, - slic_regs->slic_addr_upper, - upr->upr_buffer_h, FLUSH); - } - WRITE_REG64(adapter, - slic_regs->slic_dump_cmd, - upr->upr_data, - slic_regs->slic_addr_upper, upr->upr_data_h, FLUSH); - break; -#endif case SLIC_UPR_PING: - WRITE_REG(slic_regs->slic_ping, 1, FLUSH); + slic_reg32_write(&slic_regs->slic_ping, 1, FLUSH); break; default: ASSERT(0); @@ -3568,10 +2834,6 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr) unsigned char linkspeed; unsigned char linkduplex; - DBG_MSG("%s: %s ISR[%x] linkstatus[%x]\n adapter[%p](%d)\n", - __func__, adapter->netdev->name, isr, linkstatus, adapter, - adapter->cardindex); - if ((isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) { struct slic_shmem *pshmem; @@ -3599,50 +2861,33 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr) || (adapter->devid == SLIC_2GB_DEVICE_ID)); linkup = linkstatus & GIG_LINKUP ? LINK_UP : LINK_DOWN; - if (linkstatus & GIG_SPEED_1000) { + if (linkstatus & GIG_SPEED_1000) linkspeed = LINK_1000MB; - DBG_MSG("slicoss: %s (%s) GIGABIT Speed==1000MB ", - __func__, adapter->netdev->name); - } else if (linkstatus & GIG_SPEED_100) { + else if (linkstatus & GIG_SPEED_100) linkspeed = LINK_100MB; - DBG_MSG("slicoss: %s (%s) GIGABIT Speed==100MB ", __func__, - adapter->netdev->name); - } else { + else linkspeed = LINK_10MB; - DBG_MSG("slicoss: %s (%s) GIGABIT Speed==10MB ", __func__, - adapter->netdev->name); - } - if (linkstatus & GIG_FULLDUPLEX) { - linkduplex = LINK_FULLD; - DBG_MSG(" Duplex == FULL\n"); - } else { - linkduplex = LINK_HALFD; - DBG_MSG(" Duplex == HALF\n"); - } - if ((adapter->linkstate == LINK_DOWN) && (linkup == LINK_DOWN)) { - DBG_MSG("slicoss: %s (%s) physport(%d) link still down\n", - __func__, adapter->netdev->name, adapter->physport); + if (linkstatus & GIG_FULLDUPLEX) + linkduplex = LINK_FULLD; + else + linkduplex = LINK_HALFD; + + if ((adapter->linkstate == LINK_DOWN) && (linkup == LINK_DOWN)) return; - } /* link up event, but nothing has changed */ if ((adapter->linkstate == LINK_UP) && (linkup == LINK_UP) && (adapter->linkspeed == linkspeed) && - (adapter->linkduplex == linkduplex)) { - DBG_MSG("slicoss: %s (%s) port(%d) link still up\n", - __func__, adapter->netdev->name, adapter->physport); + (adapter->linkduplex == linkduplex)) return; - } /* link has changed at this point */ /* link has gone from up to down */ if (linkup == LINK_DOWN) { adapter->linkstate = LINK_DOWN; - DBG_MSG("slicoss: %s %d LinkDown!\n", __func__, - adapter->physport); return; } @@ -3652,30 +2897,10 @@ static void slic_link_upr_complete(struct adapter *adapter, u32 isr) if (adapter->linkstate != LINK_UP) { /* setup the mac */ - DBG_MSG("%s call slic_config_set\n", __func__); - slic_config_set(adapter, TRUE); + slic_config_set(adapter, true); adapter->linkstate = LINK_UP; - DBG_MSG("\n(%s) Link UP: CALL slic_if_start_queue", - adapter->netdev->name); - slic_if_start_queue(adapter); + netif_start_queue(adapter->netdev); } -#if 1 - switch (linkspeed) { - case LINK_1000MB: - DBG_MSG - ("\n(%s) LINK UP!: GIGABIT SPEED == 1000MB duplex[%x]\n", - adapter->netdev->name, adapter->linkduplex); - break; - case LINK_100MB: - DBG_MSG("\n(%s) LINK UP!: SPEED == 100MB duplex[%x]\n", - adapter->netdev->name, adapter->linkduplex); - break; - default: - DBG_MSG("\n(%s) LINK UP!: SPEED == 10MB duplex[%x]\n", - adapter->netdev->name, adapter->linkduplex); - break; - } -#endif } /* @@ -3787,20 +3012,18 @@ static int slic_rspqueue_init(struct adapter *adapter) __iomem struct slic_regs *slic_regs = adapter->slic_regs; u32 paddrh = 0; - DBG_MSG("slicoss: %s (%s) ENTER adapter[%p]\n", __func__, - adapter->netdev->name, adapter); ASSERT(adapter->state == ADAPT_DOWN); memset(rspq, 0, sizeof(struct slic_rspqueue)); rspq->num_pages = SLIC_RSPQ_PAGES_GB; for (i = 0; i < rspq->num_pages; i++) { - rspq->vaddr[i] = - pci_alloc_consistent(adapter->pcidev, PAGE_SIZE, - &rspq->paddr[i]); + rspq->vaddr[i] = pci_alloc_consistent(adapter->pcidev, + PAGE_SIZE, + &rspq->paddr[i]); if (!rspq->vaddr[i]) { - DBG_ERROR - ("rspqueue_init_failed pci_alloc_consistent\n"); + dev_err(&adapter->pcidev->dev, + "pci_alloc_consistent failed\n"); slic_rspqueue_free(adapter); return STATUS_FAILURE; } @@ -3811,47 +3034,21 @@ static int slic_rspqueue_init(struct adapter *adapter) (u32) rspq->paddr[i]); #endif memset(rspq->vaddr[i], 0, PAGE_SIZE); -/* DBG_MSG("slicoss: %s UPLOAD RSPBUFF Page pageix[%x] paddr[%p] " - "vaddr[%p]\n", - __func__, i, (void *)rspq->paddr[i], rspq->vaddr[i]); */ if (paddrh == 0) { - WRITE_REG(slic_regs->slic_rbar, - (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE), - DONT_FLUSH); + slic_reg32_write(&slic_regs->slic_rbar, + (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE), + DONT_FLUSH); } else { - WRITE_REG64(adapter, - slic_regs->slic_rbar64, - (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE), - slic_regs->slic_addr_upper, - paddrh, DONT_FLUSH); + slic_reg64_write(adapter, &slic_regs->slic_rbar64, + (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE), + &slic_regs->slic_addr_upper, + paddrh, DONT_FLUSH); } } rspq->offset = 0; rspq->pageindex = 0; rspq->rspbuf = (struct slic_rspbuf *)rspq->vaddr[0]; - DBG_MSG("slicoss: %s (%s) EXIT adapter[%p]\n", __func__, - adapter->netdev->name, adapter); - return STATUS_SUCCESS; -} - -static int slic_rspqueue_reset(struct adapter *adapter) -{ - struct slic_rspqueue *rspq = &adapter->rspqueue; - - DBG_MSG("slicoss: %s (%s) ENTER adapter[%p]\n", __func__, - adapter->netdev->name, adapter); - ASSERT(adapter->state == ADAPT_DOWN); - ASSERT(rspq); - - DBG_MSG("slicoss: Nothing to do. rspq[%p]\n" - " offset[%x]\n" - " pageix[%x]\n" - " rspbuf[%p]\n", - rspq, rspq->offset, rspq->pageindex, rspq->rspbuf); - - DBG_MSG("slicoss: %s (%s) EXIT adapter[%p]\n", __func__, - adapter->netdev->name, adapter); return STATUS_SUCCESS; } @@ -3860,14 +3057,8 @@ static void slic_rspqueue_free(struct adapter *adapter) int i; struct slic_rspqueue *rspq = &adapter->rspqueue; - DBG_MSG("slicoss: %s adapter[%p] port %d rspq[%p] FreeRSPQ\n", - __func__, adapter, adapter->physport, rspq); for (i = 0; i < rspq->num_pages; i++) { if (rspq->vaddr[i]) { - DBG_MSG - ("slicoss: pci_free_consistent rspq->vaddr[%p] \ - paddr[%p]\n", - rspq->vaddr[i], (void *) rspq->paddr[i]); pci_free_consistent(adapter->pcidev, PAGE_SIZE, rspq->vaddr[i], rspq->paddr[i]); } @@ -3900,11 +3091,9 @@ static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter) #endif } else { ASSERT(rspq->offset == SLIC_RSPQ_BUFSINPAGE); - WRITE_REG64(adapter, - adapter->slic_regs->slic_rbar64, - (rspq-> - paddr[rspq->pageindex] | SLIC_RSPQ_BUFSINPAGE), - adapter->slic_regs->slic_addr_upper, 0, DONT_FLUSH); + slic_reg64_write(adapter, &adapter->slic_regs->slic_rbar64, + (rspq->paddr[rspq->pageindex] | SLIC_RSPQ_BUFSINPAGE), + &adapter->slic_regs->slic_addr_upper, 0, DONT_FLUSH); rspq->pageindex = (++rspq->pageindex) % rspq->num_pages; rspq->offset = 0; rspq->rspbuf = (struct slic_rspbuf *) @@ -3932,12 +3121,8 @@ static void slic_cmdqmem_free(struct adapter *adapter) struct slic_cmdqmem *cmdqmem = &adapter->cmdqmem; int i; - DBG_MSG("slicoss: (%s) adapter[%p] port %d rspq[%p] Free CMDQ Memory\n", - __func__, adapter, adapter->physport, cmdqmem); for (i = 0; i < SLIC_CMDQ_MAXPAGES; i++) { if (cmdqmem->pages[i]) { - DBG_MSG("slicoss: %s Deallocate page CmdQPage[%p]\n", - __func__, (void *) cmdqmem->pages[i]); pci_free_consistent(adapter->pcidev, PAGE_SIZE, (void *) cmdqmem->pages[i], @@ -3972,7 +3157,6 @@ static int slic_cmdq_init(struct adapter *adapter) int i; u32 *pageaddr; - DBG_MSG("slicoss: %s ENTER adapter[%p]\n", __func__, adapter); ASSERT(adapter->state == ADAPT_DOWN); memset(&adapter->cmdq_all, 0, sizeof(struct slic_cmdqueue)); memset(&adapter->cmdq_free, 0, sizeof(struct slic_cmdqueue)); @@ -3994,7 +3178,6 @@ static int slic_cmdq_init(struct adapter *adapter) slic_cmdq_addcmdpage(adapter, pageaddr); } adapter->slic_handle_ix = 1; - DBG_MSG("slicoss: %s reset slic_handle_ix to ONE\n", __func__); return STATUS_SUCCESS; } @@ -4003,8 +3186,6 @@ static void slic_cmdq_free(struct adapter *adapter) { struct slic_hostcmd *cmd; - DBG_MSG("slicoss: %s adapter[%p] port %d FreeCommandsFrom CMDQ\n", - __func__, adapter, adapter->physport); cmd = adapter->cmdq_all.head; while (cmd) { if (cmd->busy) { @@ -4030,7 +3211,6 @@ static void slic_cmdq_reset(struct adapter *adapter) struct sk_buff *skb; u32 outstanding; - DBG_MSG("%s ENTER adapter[%p]\n", __func__, adapter); spin_lock_irqsave(&adapter->cmdq_free.lock.lock, adapter->cmdq_free.lock.flags); spin_lock_irqsave(&adapter->cmdq_done.lock.lock, @@ -4042,11 +3222,8 @@ static void slic_cmdq_reset(struct adapter *adapter) if (hcmd->busy) { skb = hcmd->skb; ASSERT(skb); - DBG_MSG("slicoss: %s hcmd[%p] skb[%p] ", __func__, - hcmd, skb); hcmd->busy = 0; hcmd->skb = NULL; - DBG_MSG(" Free SKB\n"); dev_kfree_skb_irq(skb); } hcmd = hcmd->next_all; @@ -4065,14 +3242,14 @@ static void slic_cmdq_reset(struct adapter *adapter) hcmd = hcmd->next_all; } if (adapter->cmdq_free.count != adapter->cmdq_all.count) { - DBG_ERROR("%s free_count %d != all count %d\n", __func__, - adapter->cmdq_free.count, adapter->cmdq_all.count); + dev_err(&adapter->netdev->dev, + "free_count %d != all count %d\n", + adapter->cmdq_free.count, adapter->cmdq_all.count); } spin_unlock_irqrestore(&adapter->cmdq_done.lock.lock, adapter->cmdq_done.lock.flags); spin_unlock_irqrestore(&adapter->cmdq_free.lock.lock, adapter->cmdq_free.lock.flags); - DBG_MSG("%s EXIT adapter[%p]\n", __func__, adapter); } static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page) @@ -4090,8 +3267,6 @@ static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page) cmdaddr = page; cmd = (struct slic_hostcmd *)cmdaddr; -/* DBG_MSG("CMDQ Page addr[%p] ix[%d] pfree[%p]\n", cmdaddr, slic_handle_ix, - adapter->pfree_slic_handles); */ cmdcnt = 0; phys_addr = virt_to_bus((void *)page); @@ -4117,7 +3292,7 @@ static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page) cmd->pslic_handle = pslic_handle; cmd->cmd64.hosthandle = pslic_handle->token.handle_token; - cmd->busy = FALSE; + cmd->busy = false; cmd->paddrl = phys_addrl; cmd->paddrh = phys_addrh; cmd->next_all = prev; @@ -4133,13 +3308,11 @@ static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page) cmdq = &adapter->cmdq_all; cmdq->count += cmdcnt; /* SLIC_CMDQ_CMDSINPAGE; mooktodo */ tail->next_all = cmdq->head; - ASSERT(VALID_ADDRESS(prev)); cmdq->head = prev; cmdq = &adapter->cmdq_free; spin_lock_irqsave(&cmdq->lock.lock, cmdq->lock.flags); cmdq->count += cmdcnt; /* SLIC_CMDQ_CMDSINPAGE; mooktodo */ tail->next = cmdq->head; - ASSERT(VALID_ADDRESS(prev)); cmdq->head = prev; spin_unlock_irqrestore(&cmdq->lock.lock, cmdq->lock.flags); } @@ -4184,7 +3357,6 @@ static void slic_cmdq_getdone(struct adapter *adapter) ASSERT(free_cmdq->head == NULL); spin_lock_irqsave(&done_cmdq->lock.lock, done_cmdq->lock.flags); - ASSERT(VALID_ADDRESS(done_cmdq->head)); free_cmdq->head = done_cmdq->head; free_cmdq->count = done_cmdq->count; @@ -4201,9 +3373,7 @@ static void slic_cmdq_putdone_irq(struct adapter *adapter, spin_lock(&cmdq->lock.lock); cmd->busy = 0; - ASSERT(VALID_ADDRESS(cmdq->head)); cmd->next = cmdq->head; - ASSERT(VALID_ADDRESS(cmd)); cmdq->head = cmd; cmdq->count++; if ((adapter->xmitq_full) && (cmdq->count > 10)) @@ -4216,7 +3386,6 @@ static int slic_rcvqueue_init(struct adapter *adapter) int i, count; struct slic_rcvqueue *rcvq = &adapter->rcvqueue; - DBG_MSG("slicoss: %s ENTER adapter[%p]\n", __func__, adapter); ASSERT(adapter->state == ADAPT_DOWN); rcvq->tail = NULL; rcvq->head = NULL; @@ -4233,25 +3402,6 @@ static int slic_rcvqueue_init(struct adapter *adapter) slic_rcvqueue_free(adapter); return STATUS_FAILURE; } - DBG_MSG("slicoss: %s EXIT adapter[%p]\n", __func__, adapter); - return STATUS_SUCCESS; -} - -static int slic_rcvqueue_reset(struct adapter *adapter) -{ - struct slic_rcvqueue *rcvq = &adapter->rcvqueue; - - DBG_MSG("slicoss: %s ENTER adapter[%p]\n", __func__, adapter); - ASSERT(adapter->state == ADAPT_DOWN); - ASSERT(rcvq); - - DBG_MSG("slicoss: Nothing to do. rcvq[%p]\n" - " count[%x]\n" - " head[%p]\n" - " tail[%p]\n", - rcvq, rcvq->count, rcvq->head, rcvq->tail); - - DBG_MSG("slicoss: %s EXIT adapter[%p]\n", __func__, adapter); return STATUS_SUCCESS; } @@ -4290,8 +3440,8 @@ static struct sk_buff *slic_rcvqueue_getnext(struct adapter *adapter) skb = NULL; } } else { - DBG_ERROR("RcvQ Empty!! adapter[%p] rcvq[%p] count[%x]\n", - adapter, rcvq, rcvq->count); + dev_err(&adapter->netdev->dev, + "RcvQ Empty!! rcvq[%p] count[%x]\n", rcvq, rcvq->count); skb = NULL; } while (rcvq->count < SLIC_RCVQ_FILLTHRESH) { @@ -4311,6 +3461,7 @@ static int slic_rcvqueue_fill(struct adapter *adapter) u32 paddrh; struct slic_rcvqueue *rcvq = &adapter->rcvqueue; int i = 0; + struct device *dev = &adapter->netdev->dev; while (i < SLIC_RCVQ_FILLENTRIES) { struct slic_rcvbuf *rcvbuf; @@ -4333,44 +3484,45 @@ retry_rcvqfill: skb->next = NULL; #ifdef KLUDGE_FOR_4GB_BOUNDARY if (paddrl == 0) { - DBG_ERROR - ("%s: LOW 32bits PHYSICAL ADDRESS == 0 " - "skb[%p] PROBLEM\n" - " skbdata[%p]\n" - " skblen[%x]\n" - " paddr[%p]\n" - " paddrl[%x]\n" - " paddrh[%x]\n", __func__, skb, - skb->data, skb->len, paddr, paddrl, - paddrh); - DBG_ERROR(" rcvq->head[%p]\n" - " rcvq->tail[%p]\n" - " rcvq->count[%x]\n", - rcvq->head, rcvq->tail, rcvq->count); - DBG_ERROR("SKIP THIS SKB!!!!!!!!\n"); + dev_err(dev, "%s: LOW 32bits PHYSICAL ADDRESS == 0\n", + __func__); + dev_err(dev, "skb[%p] PROBLEM\n", skb); + dev_err(dev, " skbdata[%p]\n", skb->data); + dev_err(dev, " skblen[%x]\n", skb->len); + dev_err(dev, " paddr[%p]\n", paddr); + dev_err(dev, " paddrl[%x]\n", paddrl); + dev_err(dev, " paddrh[%x]\n", paddrh); + dev_err(dev, " rcvq->head[%p]\n", rcvq->head); + dev_err(dev, " rcvq->tail[%p]\n", rcvq->tail); + dev_err(dev, " rcvq->count[%x]\n", rcvq->count); + dev_err(dev, "SKIP THIS SKB!!!!!!!!\n"); goto retry_rcvqfill; } #else if (paddrl == 0) { - DBG_ERROR - ("\n\n%s: LOW 32bits PHYSICAL ADDRESS == 0 " - "skb[%p] GIVE TO CARD ANYWAY\n" - " skbdata[%p]\n" - " paddr[%p]\n" - " paddrl[%x]\n" - " paddrh[%x]\n", __func__, skb, - skb->data, paddr, paddrl, paddrh); + dev_err(dev, "%s: LOW 32bits PHYSICAL ADDRESS == 0\n", + __func__); + dev_err(dev, "skb[%p] PROBLEM\n", skb); + dev_err(dev, " skbdata[%p]\n", skb->data); + dev_err(dev, " skblen[%x]\n", skb->len); + dev_err(dev, " paddr[%p]\n", paddr); + dev_err(dev, " paddrl[%x]\n", paddrl); + dev_err(dev, " paddrh[%x]\n", paddrh); + dev_err(dev, " rcvq->head[%p]\n", rcvq->head); + dev_err(dev, " rcvq->tail[%p]\n", rcvq->tail); + dev_err(dev, " rcvq->count[%x]\n", rcvq->count); + dev_err(dev, "GIVE TO CARD ANYWAY\n"); } #endif if (paddrh == 0) { - WRITE_REG(adapter->slic_regs->slic_hbar, - (u32) paddrl, DONT_FLUSH); + slic_reg32_write(&adapter->slic_regs->slic_hbar, + (u32)paddrl, DONT_FLUSH); } else { - WRITE_REG64(adapter, - adapter->slic_regs->slic_hbar64, - (u32) paddrl, - adapter->slic_regs->slic_addr_upper, - (u32) paddrh, DONT_FLUSH); + slic_reg64_write(adapter, + &adapter->slic_regs->slic_hbar64, + paddrl, + &adapter->slic_regs->slic_addr_upper, + paddrh, DONT_FLUSH); } if (rcvq->head) rcvq->tail->next = skb; @@ -4380,10 +3532,9 @@ retry_rcvqfill: rcvq->count++; i++; } else { - DBG_ERROR - ("%s slic_rcvqueue_fill could only get [%d] " - "skbuffs\n", - adapter->netdev->name, i); + dev_err(&adapter->netdev->dev, + "slic_rcvqueue_fill could only get [%d] skbuffs\n", + i); break; } } @@ -4397,6 +3548,7 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb) u32 paddrl; u32 paddrh; struct slic_rcvbuf *rcvbuf = (struct slic_rcvbuf *)skb->head; + struct device *dev; ASSERT(skb->len == SLIC_RCVBUF_HEADSIZE); @@ -4409,26 +3561,26 @@ static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb) paddrh = SLIC_GET_ADDR_HIGH(paddr); if (paddrl == 0) { - DBG_ERROR - ("%s: LOW 32bits PHYSICAL ADDRESS == 0 skb[%p] PROBLEM\n" - " skbdata[%p]\n" " skblen[%x]\n" - " paddr[%p]\n" " paddrl[%x]\n" - " paddrh[%x]\n", __func__, skb, skb->data, - skb->len, paddr, paddrl, paddrh); - DBG_ERROR(" rcvq->head[%p]\n" - " rcvq->tail[%p]\n" - " rcvq->count[%x]\n", rcvq->head, rcvq->tail, - rcvq->count); + dev = &adapter->netdev->dev; + dev_err(dev, "%s: LOW 32bits PHYSICAL ADDRESS == 0\n", + __func__); + dev_err(dev, "skb[%p] PROBLEM\n", skb); + dev_err(dev, " skbdata[%p]\n", skb->data); + dev_err(dev, " skblen[%x]\n", skb->len); + dev_err(dev, " paddr[%p]\n", paddr); + dev_err(dev, " paddrl[%x]\n", paddrl); + dev_err(dev, " paddrh[%x]\n", paddrh); + dev_err(dev, " rcvq->head[%p]\n", rcvq->head); + dev_err(dev, " rcvq->tail[%p]\n", rcvq->tail); + dev_err(dev, " rcvq->count[%x]\n", rcvq->count); } if (paddrh == 0) { - WRITE_REG(adapter->slic_regs->slic_hbar, (u32) paddrl, - DONT_FLUSH); + slic_reg32_write(&adapter->slic_regs->slic_hbar, (u32)paddrl, + DONT_FLUSH); } else { - WRITE_REG64(adapter, - adapter->slic_regs->slic_hbar64, - paddrl, - adapter->slic_regs->slic_addr_upper, - paddrh, DONT_FLUSH); + slic_reg64_write(adapter, &adapter->slic_regs->slic_hbar64, + paddrl, &adapter->slic_regs->slic_addr_upper, + paddrh, DONT_FLUSH); } if (rcvq->head) rcvq->tail->next = skb; @@ -4449,7 +3601,7 @@ static int slic_debug_card_show(struct seq_file *seq, void *v) unsigned char *oemfru = (unsigned char *)(&card->config.OemFru); #endif - seq_printf(seq, "driver_version : %s", slic_proc_version); + seq_printf(seq, "driver_version : %s\n", slic_proc_version); seq_printf(seq, "Microcode versions: \n"); seq_printf(seq, " Gigabit (gb) : %s %s\n", MOJAVE_UCODE_VERS_STRING, MOJAVE_UCODE_VERS_DATE); @@ -4882,1030 +4034,6 @@ static void slic_debug_cleanup(void) } } -/*============================================================================= - ============================================================================= - === === - === SLIC DUMP MANAGEMENT SECTION === - === === - === === - === Dump routines === - === === - === === - ============================================================================= - ============================================================================*/ - -#if SLIC_DUMP_ENABLED - -#include - -void *slic_dump_handle; /* thread handle */ - -/* - * These are the only things you should do on a core-file: use only these - * functions to write out all the necessary info. - */ -static int slic_dump_seek(struct file *SLIChandle, u32 file_offset) -{ - if (SLIChandle->f_pos != file_offset) { - /*DBG_MSG("slic_dump_seek now needed [%x : %x]\n", - (u32)SLIChandle->f_pos, (u32)file_offset); */ - if (SLIChandle->f_op->llseek) { - if (SLIChandle->f_op-> - llseek(SLIChandle, file_offset, 0) != file_offset) - return 0; - } else { - SLIChandle->f_pos = file_offset; - } - } - return 1; -} - -static int slic_dump_write(struct sliccard *card, - const void *addr, int size, u32 file_offset) -{ - int r = 1; - u32 result = 0; - struct file *SLIChandle = card->dumphandle; - -#ifdef HISTORICAL /* legacy */ - down(&SLIChandle->f_dentry->d_inode->i_sem); -#endif - if (size) { - slic_dump_seek(SLIChandle, file_offset); - - result = - SLIChandle->f_op->write(SLIChandle, addr, size, - &SLIChandle->f_pos); - - r = result == size; - } - - card->dumptime_complete = jiffies; - card->dumptime_delta = card->dumptime_complete - card->dumptime_start; - card->dumptime_start = jiffies; - -#ifdef HISTORICAL - up(&SLIChandle->f_dentry->d_inode->i_sem); -#endif - if (!r) { - DBG_ERROR("%s: addr[%p] size[%x] result[%x] file_offset[%x]\n", - __func__, addr, size, result, file_offset); - } - return r; -} - -static uint slic_init_dump_thread(struct sliccard *card) -{ - card->dump_task_id = kthread_run(slic_dump_thread, (void *)card, 0); - -/* DBG_MSG("create slic_dump_thread dump_pid[%x]\n", card->dump_pid); */ - if (IS_ERR(card->dump_task_id)) { - DBG_MSG("create slic_dump_thread FAILED \n"); - return STATUS_FAILURE; - } - - return STATUS_SUCCESS; -} - -static int slic_dump_thread(void *context) -{ - struct sliccard *card = (struct sliccard *)context; - struct adapter *adapter; - struct adapter *dump_adapter = NULL; - u32 dump_complete = 0; - u32 delay = SLIC_SECS_TO_JIFFS(PING_TIMER_INTERVAL); - struct slic_regs *pregs; - u32 i; - struct slic_upr *upr, *uprnext; - u32 dump_card; - - ASSERT(card); - - card->dumpthread_running = 1; - -#ifdef HISTORICAL - lock_kernel(); - /* - * This thread doesn't need any user-level access, - * so get rid of all our resources - */ - exit_files(current); /* daemonize doesn't do exit_files */ - current->files = init_task.files; - atomic_inc(¤t->files->count); -#endif - - daemonize("%s", "slicmon"); - - /* Setup a nice name */ - strcpy(current->comm, "slicmon"); - DBG_ERROR - ("slic_dump_thread[slicmon] daemon is alive card[%p] pid[%x]\n", - card, card->dump_task_id->pid); - - /* - * Send me a signal to get me to die (for debugging) - */ - do { - /* - * If card state is not set to up, skip - */ - if (card->state != CARD_UP) { - if (card->adapters_activated) - goto wait; - else - goto end_thread; - } - /* - * Check the results of our last ping. - */ - dump_card = 0; -#ifdef SLIC_FAILURE_DUMP - if (card->pingstatus != ISR_PINGMASK) { - DBG_MSG - ("\n[slicmon] CARD #%d TIMED OUT - status " - "%x: DUMP THE CARD!\n", - card->cardnum, card->pingstatus); - dump_card = 1; - } -#else - /* - * Cause a card RESET instead? - */ - if (card->pingstatus != ISR_PINGMASK) { - /* todo. do we want to reset the card in production */ - /* DBG_MSG("\n[slicmon] CARD #%d TIMED OUT - " - status %x: RESET THE CARD!\n", card->cardnum, - card->pingstatus); */ - DBG_ERROR - ("\n[slicmon] CARD #%d TIMED OUT - status %x: " - "DUMP THE CARD!\n", - card->cardnum, card->pingstatus); - dump_card = 1; - } -#endif - if ((dump_card) - || (card->dump_requested == SLIC_DUMP_REQUESTED)) { - if (card->dump_requested == SLIC_DUMP_REQUESTED) { - DBG_ERROR - ("[slicmon]: Dump card Requested: Card %x\n", - card->cardnum); - } - if (card->pingstatus != ISR_PINGMASK) { - ushort cpuid = 0; - ushort crashpc = 0; - - if (card->adapter[0]) { - if ((card->adapter[0])->memorylength >= - CRASH_INFO_OFFSET + - sizeof(slic_crash_info)) { - char *crashptr; - p_slic_crash_info crashinfo; - - crashptr = - ((char *)card->adapter[0]-> - slic_regs) + - CRASH_INFO_OFFSET; - crashinfo = - (p_slic_crash_info) - crashptr; - cpuid = crashinfo->cpu_id; - crashpc = crashinfo->crash_pc; - } - } - DBG_ERROR - ("[slicmon]: Dump card: Card %x crashed " - "and failed to answer PING. " - "CPUID[%x] PC[%x]\n ", - card->cardnum, cpuid, crashpc); - } - - card->dump_requested = SLIC_DUMP_IN_PROGRESS; - - /* - * Set the card state to DOWN and the adapter states - * to RESET.They will check this in SimbaCheckForHang - * and initiate interface reset (which in turn will - * reinitialize the card). - */ - card->state = CARD_DOWN; - - for (i = 0; i < card->card_size; i++) { - adapter = card->adapter[i]; - if (adapter) { - slic_if_stop_queue(adapter); - - if (adapter->state == ADAPT_UP) { - adapter->state = ADAPT_RESET; - adapter->linkstate = LINK_DOWN; - DBG_ERROR - ("[slicmon]: SLIC Card[%d] " - "Port[%d] adapter[%p] " - "down\n", - (uint) card->cardnum, - (uint) i, adapter); - } -#if SLIC_GET_STATS_TIMER_ENABLED - /* free stats timer */ - if (adapter->statstimerset) { - adapter->statstimerset = 0; - del_timer(&adapter->statstimer); - } -#endif - } - } - - for (i = 0; i < card->card_size; i++) { - adapter = card->adapter[i]; - if ((adapter) && (adapter->activated)) { - pregs = adapter->slic_regs; - dump_adapter = adapter; - - /* - * If the dump status is zero, then - * the utility processor has crashed. - * If this is the case, any pending - * utilityprocessor requests will not - * complete and our dump commands will - * not be issued. - * - * To avoid this we will clear any - * pending utility processor requests - * now. - */ - if (!card->pingstatus) { - spin_lock_irqsave( - &adapter->upr_lock.lock, - adapter->upr_lock.flags); - upr = adapter->upr_list; - while (upr) { - uprnext = upr->next; - kfree(upr); - upr = uprnext; - } - adapter->upr_list = 0; - adapter->upr_busy = 0; - spin_unlock_irqrestore( - &adapter->upr_lock.lock, - adapter->upr_lock.flags); - } - - slic_dump_card(card, FALSE); - dump_complete = 1; - } - - if (dump_complete) { - DBG_ERROR("SLIC Dump Complete\n"); - /* Only dump the card one time */ - break; - } - } - - if (dump_adapter) { - DBG_ERROR - ("slic dump completed. " - "Reenable interfaces\n"); - slic_card_init(card, dump_adapter); - - /* - * Reenable the adapters that were reset - */ - for (i = 0; i < card->card_size; i++) { - adapter = card->adapter[i]; - if (adapter) { - if (adapter->state == - ADAPT_RESET) { - DBG_ERROR - ("slicdump: SLIC " - "Card[%d] Port[%d] adapter[%p] " - "bring UP\n", - (uint) card-> - cardnum, (uint) i, - adapter); - adapter->state = - ADAPT_DOWN; - adapter->linkstate = - LINK_DOWN; - slic_entry_open - (adapter->netdev); - } - } - } - - card->dump_requested = SLIC_DUMP_DONE; - } - } else { - /* if pingstatus != ISR_PINGMASK) || dump_requested...ELSE - * We received a valid ping response. - * Clear the Pingstatus field, find a valid adapter - * structure and send another ping. - */ - for (i = 0; i < card->card_size; i++) { - adapter = card->adapter[i]; - if (adapter && (adapter->state == ADAPT_UP)) { - card->pingstatus = 0; - slic_upr_request(adapter, SLIC_UPR_PING, - 0, 0, 0, 0); - break; /* Only issue one per card */ - } - } - } -wait: - SLIC_INTERRUPTIBLE_SLEEP_ON_TIMEOUT(card->dump_wq, delay); - } while (!signal_pending(current)); - -end_thread: -/* DBG_MSG("[slicmon] slic_dump_thread card[%p] pid[%x] ENDING\n", - card, card->dump_pid); */ - card->dumpthread_running = 0; - - return 0; -} - -/* - * Read a single byte from our dump index file. This - * value is used as our suffix for our dump path. The - * value is incremented and written back to the file - */ -static unsigned char slic_get_dump_index(char *path) -{ - unsigned char index = 0; -#ifdef SLIC_DUMP_INDEX_SUPPORT - u32 status; - void *FileHandle; - u32 offset; - - offset = 0; - - /* - * Open the index file. If one doesn't exist, create it - */ - status = create_file(&FileHandle); - - if (status != STATUS_SUCCESS) - return (unsigned char) 0; - - status = read_file(FileHandle, &index, 1, &offset); - - index++; - - status = write_file(FileHandle, &index, 1, &offset); - - close_file(FileHandle); -#else - index = 0; -#endif - return index; -} - -static struct file *slic_dump_open_file(struct sliccard *card) -{ - struct file *SLIChandle = NULL; - struct dentry *dentry = NULL; - struct inode *inode = NULL; - char SLICfile[50]; - - card->dumpfile_fs = get_fs(); - - set_fs(KERNEL_DS); - - memset(SLICfile, 0, sizeof(SLICfile)); - sprintf(SLICfile, "/var/tmp/slic%d-dump-%d", card->cardnum, - (uint) card->dump_count); - card->dump_count++; - - SLIChandle = - filp_open(SLICfile, O_CREAT | O_RDWR | O_SYNC | O_LARGEFILE, 0666); - - DBG_MSG("[slicmon]: Dump Card #%d to file: %s \n", card->cardnum, - SLICfile); - -/* DBG_MSG("[slicmon] filp_open %s SLIChandle[%p]\n", SLICfile, SLIChandle);*/ - - if (IS_ERR(SLIChandle)) - goto end_slicdump; - - dentry = SLIChandle->f_dentry; - inode = dentry->d_inode; - -/* DBG_MSG("[slicmon] inode[%p] i_nlink[%x] i_mode[%x] i_op[%p] i_fop[%p]\n" - "f_op->write[%p]\n", - inode, inode->i_nlink, inode->i_mode, inode->i_op, - inode->i_fop, SLIChandle->f_op->write); */ - if (inode->i_nlink > 1) - goto close_slicdump; /* multiple links - don't dump */ -#ifdef HISTORICAL - if (!S_ISREG(inode->i_mode)) - goto close_slicdump; -#endif - if (!inode->i_op || !inode->i_fop) - goto close_slicdump; - - if (!SLIChandle->f_op->write) - goto close_slicdump; - - /* - * If we got here we have SUCCESSFULLY OPENED the dump file - */ -/* DBG_MSG("opened %s SLIChandle[%p]\n", SLICfile, SLIChandle); */ - return SLIChandle; - -close_slicdump: - DBG_MSG("[slicmon] slic_dump_open_file failed close SLIChandle[%p]\n", - SLIChandle); - filp_close(SLIChandle, NULL); - -end_slicdump: - set_fs(card->dumpfile_fs); - - return NULL; -} - -static void slic_dump_close_file(struct sliccard *card) -{ - -/* DBG_MSG("[slicmon] slic_dump_CLOSE_file close SLIChandle[%p]\n", - card->dumphandle); */ - - filp_close(card->dumphandle, NULL); - - set_fs(card->dumpfile_fs); -} - -static u32 slic_dump_card(struct sliccard *card, bool resume) -{ - struct adapter *adapter = card->master; - u32 status; - u32 queue; - u32 len, offset; - u32 sram_size, dram_size, regs; - struct sliccore_hdr corehdr; - u32 file_offset; - char *namestr; - u32 i; - u32 max_queues = 0; - u32 result; - - card->dumphandle = slic_dump_open_file(card); - - if (card->dumphandle == NULL) { - DBG_MSG("[slicmon] Cant create Dump file - dump failed\n"); - return -ENOMEM; - } - if (!card->dumpbuffer) { - DBG_MSG("[slicmon] Insufficient memory for dump\n"); - return -ENOMEM; - } - if (!card->cmdbuffer) { - DBG_MSG("[slicmon] Insufficient cmd memory for dump\n"); - return -ENOMEM; - } - - /* - * Write the file version to the core header. - */ - namestr = slic_proc_version; - for (i = 0; i < (DRIVER_NAME_SIZE - 1); i++, namestr++) { - if (!namestr) - break; - corehdr.driver_version[i] = *namestr; - } - corehdr.driver_version[i] = 0; - - file_offset = sizeof(struct sliccore_hdr); - - /* - * Issue the following debug commands to the SLIC: - * - Halt both receive and transmit - * - Dump receive registers - * - Dump transmit registers - * - Dump sram - * - Dump dram - * - Dump queues - */ - DBG_MSG("slicDump HALT Receive Processor\n"); - card->dumptime_start = jiffies; - - status = slic_dump_halt(card, PROC_RECEIVE); - if (status != STATUS_SUCCESS) { - DBG_ERROR - ("Cant halt receive sequencer - dump failed status[%x]\n", - status); - goto done; - } - - DBG_MSG("slicDump HALT Transmit Processor\n"); - status = slic_dump_halt(card, PROC_TRANSMIT); - if (status != STATUS_SUCCESS) { - DBG_ERROR("Cant halt transmit sequencer - dump failed\n"); - goto done; - } - - /* Dump receive regs */ - status = slic_dump_reg(card, PROC_RECEIVE); - if (status != STATUS_SUCCESS) { - DBG_ERROR("Cant dump receive registers - dump failed\n"); - goto done; - } - - DBG_MSG("slicDump Write Receive REGS len[%x] offset[%x]\n", - (SLIC_NUM_REG * 4), file_offset); - - result = - slic_dump_write(card, card->dumpbuffer, SLIC_NUM_REG * 4, - file_offset); - if (!result) { - DBG_ERROR - ("Cant write rcv registers to dump file - dump failed\n"); - goto done; - } - - corehdr.RcvRegOff = file_offset; - corehdr.RcvRegsize = SLIC_NUM_REG * 4; - file_offset += SLIC_NUM_REG * 4; - - /* Dump transmit regs */ - status = slic_dump_reg(card, PROC_TRANSMIT); - if (status != STATUS_SUCCESS) { - DBG_ERROR("Cant dump transmit registers - dump failed\n"); - goto done; - } - - DBG_MSG("slicDump Write XMIT REGS len[%x] offset[%x]\n", - (SLIC_NUM_REG * 4), file_offset); - - result = - slic_dump_write(card, card->dumpbuffer, SLIC_NUM_REG * 4, - file_offset); - if (!result) { - DBG_ERROR - ("Cant write xmt registers to dump file - dump failed\n"); - goto done; - } - - corehdr.XmtRegOff = file_offset; - corehdr.XmtRegsize = SLIC_NUM_REG * 4; - file_offset += SLIC_NUM_REG * 4; - - regs = SLIC_GBMAX_REG; - - corehdr.FileRegOff = file_offset; - corehdr.FileRegsize = regs * 4; - - for (offset = 0; regs;) { - len = MIN(regs, 16); /* Can only xfr 16 regs at a time */ - - status = slic_dump_data(card, offset, (ushort) len, DESC_RFILE); - - if (status != STATUS_SUCCESS) { - DBG_ERROR("Cant dump register file - dump failed\n"); - goto done; - } - - DBG_MSG("slicDump Write RegisterFile len[%x] offset[%x]\n", - (len * 4), file_offset); - - result = - slic_dump_write(card, card->dumpbuffer, len * 4, - file_offset); - if (!result) { - DBG_ERROR - ("Cant write register file to dump file - " - "dump failed\n"); - goto done; - } - - file_offset += len * 4; - offset += len; - regs -= len; - } - - dram_size = card->config.DramSize * 0x10000; - - switch (adapter->devid) { - case SLIC_2GB_DEVICE_ID: - sram_size = SLIC_SRAM_SIZE2GB; - break; - case SLIC_1GB_DEVICE_ID: - sram_size = SLIC_SRAM_SIZE1GB; - break; - default: - sram_size = 0; - ASSERT(0); - break; - } - - corehdr.SramOff = file_offset; - corehdr.Sramsize = sram_size; - - for (offset = 0; sram_size;) { - len = MIN(sram_size, DUMP_BUF_SIZE); - status = slic_dump_data(card, offset, (ushort) len, DESC_SRAM); - if (status != STATUS_SUCCESS) { - DBG_ERROR - ("[slicmon] Cant dump SRAM at offset %x - " - "dump failed\n", (uint) offset); - goto done; - } - - DBG_MSG("[slicmon] slicDump Write SRAM len[%x] offset[%x]\n", - len, file_offset); - - result = - slic_dump_write(card, card->dumpbuffer, len, file_offset); - if (!result) { - DBG_ERROR - ("[slicmon] Cant write SRAM to dump file - " - "dump failed\n"); - goto done; - } - - file_offset += len; - offset += len; - sram_size -= len; - } - - corehdr.DramOff = file_offset; - corehdr.Dramsize = dram_size; - - for (offset = 0; dram_size;) { - len = MIN(dram_size, DUMP_BUF_SIZE); - - status = slic_dump_data(card, offset, (ushort) len, DESC_DRAM); - if (status != STATUS_SUCCESS) { - DBG_ERROR - ("[slicmon] Cant dump dram at offset %x - " - "dump failed\n", (uint) offset); - goto done; - } - - DBG_MSG("slicDump Write DRAM len[%x] offset[%x]\n", len, - file_offset); - - result = - slic_dump_write(card, card->dumpbuffer, len, file_offset); - if (!result) { - DBG_ERROR - ("[slicmon] Cant write DRAM to dump file - " - "dump failed\n"); - goto done; - } - - file_offset += len; - offset += len; - dram_size -= len; - } - - max_queues = SLIC_MAX_QUEUE; - - for (queue = 0; queue < max_queues; queue++) { - u32 *qarray = (u32 *) card->dumpbuffer; - u32 qarray_physl = card->dumpbuffer_physl; - u32 qarray_physh = card->dumpbuffer_physh; - u32 qstart; - u32 qdelta; - u32 qtotal = 0; - - DBG_MSG("[slicmon] Start Dump of QUEUE #0x%x\n", (uint) queue); - - for (offset = 0; offset < (DUMP_BUF_SIZE >> 2); offset++) { - qstart = jiffies; - qdelta = 0; - - status = slic_dump_queue(card, - qarray_physl, - qarray_physh, queue); - qarray_physl += 4; - - if (status != STATUS_SUCCESS) - break; - - if (jiffies > qstart) { - qdelta = jiffies - qstart; - qtotal += qdelta; - } - } - - if (offset) - qdelta = qtotal / offset; - else - qdelta = 0; - -/* DBG_MSG(" slicDump Write QUEUE #0x%x len[%x] offset[%x] " - "avgjiffs[%x]\n", queue, (offset*4), file_offset, qdelta); */ - - result = - slic_dump_write(card, card->dumpbuffer, offset * 4, - file_offset); - - if (!result) { - DBG_ERROR - ("[slicmon] Cant write QUEUES to dump file - " - "dump failed\n"); - goto done; - } - - corehdr.queues[queue].queueOff = file_offset; - corehdr.queues[queue].queuesize = offset * 4; - file_offset += offset * 4; - -/* DBG_MSG(" Reload QUEUE #0x%x elements[%x]\n", (uint)queue, offset);*/ - /* - * Fill the queue back up - */ - for (i = 0; i < offset; i++) { - qstart = jiffies; - qdelta = 0; - - status = slic_dump_load_queue(card, qarray[i], queue); - if (status != STATUS_SUCCESS) - break; - - if (jiffies > qstart) { - qdelta = jiffies - qstart; - qtotal += qdelta; - } - } - - if (offset) - qdelta = qtotal / offset; - else - qdelta = 0; - -/* DBG_MSG(" Reload DONE avgjiffs[%x]\n", qdelta); */ - - resume = 1; - } - - len = SLIC_GB_CAMAB_SZE * 4; - status = slic_dump_cam(card, 0, len, DUMP_CAM_A); - if (status != STATUS_SUCCESS) { - DBG_ERROR("[slicmon] Can't dump CAM_A - dump failed\n"); - goto done; - } - - result = slic_dump_write(card, card->dumpbuffer, len, file_offset); - if (result) { - DBG_ERROR - ("[slicmon] Can't write CAM_A data to dump file - " - "dump failed\n"); - goto done; - } - corehdr.CamAMOff = file_offset; - corehdr.CamASize = len; - file_offset += len; - - len = SLIC_GB_CAMCD_SZE * 4; - status = slic_dump_cam(card, 0, len, DUMP_CAM_C); - if (status) { - DBG_ERROR("[slicmon] Can't dump CAM_C - dump failed\n"); - goto done; - } - - result = slic_dump_write(card, card->dumpbuffer, len, file_offset); - if (result) { - DBG_ERROR - ("[slicmon] Can't write CAM_C data to dump file - " - "dump failed\n"); - goto done; - } - corehdr.CamCMOff = file_offset; - corehdr.CamCSize = len; - file_offset += len; - -done: - /* - * Write out the core header - */ - file_offset = 0; - DBG_MSG("[slicmon] Write CoreHeader len[%x] offset[%x]\n", - (uint) sizeof(struct sliccore_hdr), file_offset); - - result = - slic_dump_write(card, &corehdr, sizeof(struct sliccore_hdr), - file_offset); - DBG_MSG("[slicmon] corehdr xoff[%x] xsz[%x]\n" - " roff[%x] rsz[%x] fileoff[%x] filesz[%x]\n" - " sramoff[%x] sramsz[%x], dramoff[%x] dramsz[%x]\n" - " corehdr_offset[%x]\n", corehdr.XmtRegOff, - corehdr.XmtRegsize, corehdr.RcvRegOff, corehdr.RcvRegsize, - corehdr.FileRegOff, corehdr.FileRegsize, corehdr.SramOff, - corehdr.Sramsize, corehdr.DramOff, corehdr.Dramsize, - (uint) sizeof(struct sliccore_hdr)); - for (i = 0; i < max_queues; i++) { - DBG_MSG("[slicmon] QUEUE 0x%x offset[%x] size[%x]\n", - (uint) i, corehdr.queues[i].queueOff, - corehdr.queues[i].queuesize); - - } - - slic_dump_close_file(card); - - if (resume) { - DBG_MSG("slicDump RESTART RECEIVE and XMIT PROCESSORS\n\n"); - slic_dump_resume(card, PROC_RECEIVE); - slic_dump_resume(card, PROC_TRANSMIT); - } - - return status; -} - -static u32 slic_dump_halt(struct sliccard *card, unsigned char proc) -{ - unsigned char *cmd = card->cmdbuffer; - - *cmd = COMMAND_BYTE(CMD_HALT, 0, proc); - - return slic_dump_send_cmd(card, - card->cmdbuffer_physl, - card->cmdbuffer_physh, 0, 0); -} - -static u32 slic_dump_resume(struct sliccard *card, unsigned char proc) -{ - unsigned char *cmd = card->cmdbuffer; - - *cmd = COMMAND_BYTE(CMD_RUN, 0, proc); - - return slic_dump_send_cmd(card, - card->cmdbuffer_physl, - card->cmdbuffer_physh, 0, 0); -} - -static u32 slic_dump_reg(struct sliccard *card, unsigned char proc) -{ - struct dump_cmd *dump = (struct dump_cmd *)card->cmdbuffer; - - dump->cmd = COMMAND_BYTE(CMD_DUMP, 0, proc); - dump->desc = DESC_REG; - dump->count = 0; - dump->addr = 0; - - return slic_dump_send_cmd(card, - card->cmdbuffer_physl, - card->cmdbuffer_physh, - card->dumpbuffer_physl, - card->dumpbuffer_physh); -} - -static u32 slic_dump_data(struct sliccard *card, - u32 addr, ushort count, unsigned char desc) -{ - struct dump_cmd *dump = (struct dump_cmd *)card->cmdbuffer; - - dump->cmd = COMMAND_BYTE(CMD_DUMP, 0, PROC_RECEIVE); - dump->desc = desc; - dump->count = count; - dump->addr = addr; - - return slic_dump_send_cmd(card, - card->cmdbuffer_physl, - card->cmdbuffer_physh, - card->dumpbuffer_physl, - card->dumpbuffer_physh); -} - -static u32 slic_dump_queue(struct sliccard *card, - u32 addr, u32 buf_physh, u32 queue) -{ - struct dump_cmd *dump = (struct dump_cmd *)card->cmdbuffer; - - dump->cmd = COMMAND_BYTE(CMD_DUMP, 0, PROC_RECEIVE); - dump->desc = DESC_QUEUE; - dump->count = 1; - dump->addr = queue; - - return slic_dump_send_cmd(card, - card->cmdbuffer_physl, - card->cmdbuffer_physh, - addr, card->dumpbuffer_physh); -} - -static u32 slic_dump_load_queue(struct sliccard *card, u32 data, - u32 queue) -{ - struct dump_cmd *load = (struct dump_cmd *) card->cmdbuffer; - - load->cmd = COMMAND_BYTE(CMD_LOAD, 0, PROC_RECEIVE); - load->desc = DESC_QUEUE; - load->count = (ushort) queue; - load->addr = data; - - return slic_dump_send_cmd(card, - card->cmdbuffer_physl, - card->cmdbuffer_physh, 0, 0); -} - -static u32 slic_dump_cam(struct sliccard *card, - u32 addr, u32 count, unsigned char desc) -{ - struct dump_cmd *dump = (struct dump_cmd *)card->cmdbuffer; - - dump->cmd = COMMAND_BYTE(CMD_CAM_OPS, 0, PROC_NONE); - dump->desc = desc; - dump->count = count; - dump->addr = 0; - - return slic_dump_send_cmd(card, - card->cmdbuffer_physl, - card->cmdbuffer_physh, - addr, card->dumpbuffer_physh); -} - -static u32 slic_dump_send_cmd(struct sliccard *card, - u32 cmd_physl, - u32 cmd_physh, - u32 buf_physl, u32 buf_physh) -{ - ulong timeout = SLIC_MS_TO_JIFFIES(500); /* 500 msec */ - u32 attempts = 5; - u32 delay = SLIC_MS_TO_JIFFIES(10); /* 10 msec */ - struct adapter *adapter = card->master; - - ASSERT(adapter); - do { - /* - * Zero the Dumpstatus field of the adapter structure - */ - card->dumpstatus = 0; - /* - * Issue the dump command via a utility processor request. - * - * Kludge: We use the Informationbuffer parameter to hold - * the buffer address - */ - slic_upr_request(adapter, SLIC_UPR_DUMP, cmd_physl, cmd_physh, - buf_physl, buf_physh); - - timeout += jiffies; - /* - * Spin until completion or timeout. - */ - while (!card->dumpstatus) { - int num_sleeps = 0; - - if (jiffies > timeout) { - /* - * Complete the timed-out DUMP UPR request. - */ - slic_upr_request_complete(adapter, 0); - DBG_ERROR - ("%s: TIMED OUT num_sleeps[%x] " - "status[%x]\n", - __func__, num_sleeps, STATUS_FAILURE); - - return STATUS_FAILURE; - } - num_sleeps++; - SLIC_INTERRUPTIBLE_SLEEP_ON_TIMEOUT(card->dump_wq, - delay); - } - - if (card->dumpstatus & ISR_UPCERR) { - /* - * Error (or queue empty) - */ -/* DBG_ERROR("[slicmon] %s: DUMP_STATUS & ISR_UPCERR status[%x]\n", - __func__, STATUS_FAILURE); */ - - return STATUS_FAILURE; - } else if (card->dumpstatus & ISR_UPCBSY) { - /* - * Retry - */ - DBG_ERROR("%s: ISR_UPCBUSY attempt[%x]\n", __func__, - attempts); - - attempts--; - } else { - /* - * success - */ - return STATUS_SUCCESS; - } - - } while (attempts); - - DBG_ERROR("%s: GAVE UP AFTER SEVERAL ATTEMPTS status[%x]\n", - __func__, STATUS_FAILURE); - - /* - * Gave up after several attempts - */ - return STATUS_FAILURE; -} - -#endif -/*============================================================================= - ============================================================================= - === === - === *** END **** END **** END **** END *** === - === SLIC DUMP MANAGEMENT SECTION === - === === - === === - === === - ============================================================================= - ============================================================================*/ - /******************************************************************************/ /**************** MODULE INITIATION / TERMINATION FUNCTIONS ***************/ /******************************************************************************/ @@ -5915,46 +4043,25 @@ static struct pci_driver slic_driver = { .id_table = slic_pci_tbl, .probe = slic_entry_probe, .remove = slic_entry_remove, -#if SLIC_POWER_MANAGEMENT_ENABLED - .suspend = slicpm_suspend, - .resume = slicpm_resume, -#endif -/* .shutdown = slic_shutdown, MOOK_INVESTIGATE */ }; static int __init slic_module_init(void) { - struct pci_device_id *pcidev; - int ret; - -/* DBG_MSG("slicoss: %s ENTER cpu %d\n", __func__, smp_processor_id()); */ - slic_init_driver(); if (debug >= 0 && slic_debug != debug) - printk(SLICLEVEL "slicoss: debug level is %d.\n", debug); + printk(KERN_DEBUG KBUILD_MODNAME ": debug level is %d.\n", + debug); if (debug >= 0) slic_debug = debug; - pcidev = (struct pci_device_id *)slic_driver.id_table; -/* DBG_MSG("slicoss: %s call pci_module_init jiffies[%lx] cpu #%d\n", - __func__, jiffies, smp_processor_id()); */ - - ret = pci_register_driver(&slic_driver); - -/* DBG_MSG("slicoss: %s EXIT after call pci_module_init jiffies[%lx] " - "cpu #%d status[%x]\n",__func__, jiffies, - smp_processor_id(), ret); */ - - return ret; + return pci_register_driver(&slic_driver); } static void __exit slic_module_cleanup(void) { -/* DBG_MSG("slicoss: %s ENTER\n", __func__); */ pci_unregister_driver(&slic_driver); slic_debug_cleanup(); -/* DBG_MSG("slicoss: %s EXIT\n", __func__); */ } module_init(slic_module_init); diff --git a/drivers/staging/stlc45xx/Kconfig b/drivers/staging/stlc45xx/Kconfig new file mode 100644 index 000000000000..8d3f46f190e8 --- /dev/null +++ b/drivers/staging/stlc45xx/Kconfig @@ -0,0 +1,8 @@ +config STLC45XX + tristate "stlc4550/4560 support" + depends on MAC80211 && WLAN_80211 && SPI_MASTER + ---help--- + This is a driver for stlc4550 and stlc4560 chipsets. + + To compile this driver as a module, choose M here: the module will be + called stlc45xx. If unsure, say N. diff --git a/drivers/staging/stlc45xx/Makefile b/drivers/staging/stlc45xx/Makefile new file mode 100644 index 000000000000..7ee32903055a --- /dev/null +++ b/drivers/staging/stlc45xx/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_STLC45XX) += stlc45xx.o diff --git a/drivers/staging/stlc45xx/stlc45xx.c b/drivers/staging/stlc45xx/stlc45xx.c new file mode 100644 index 000000000000..3eced5520c56 --- /dev/null +++ b/drivers/staging/stlc45xx/stlc45xx.c @@ -0,0 +1,2606 @@ +/* + * This file is part of stlc45xx + * + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "stlc45xx.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stlc45xx_lmac.h" + +/* + * gpios should be handled in board files and provided via platform data, + * but because it's currently impossible for stlc45xx to have a header file + * in include/linux, let's use module paramaters for now + */ +static int stlc45xx_gpio_power = 97; +module_param(stlc45xx_gpio_power, int, 0444); +MODULE_PARM_DESC(stlc45xx_gpio_power, "stlc45xx gpio number for power line"); + +static int stlc45xx_gpio_irq = 87; +module_param(stlc45xx_gpio_irq, int, 0444); +MODULE_PARM_DESC(stlc45xx_gpio_irq, "stlc45xx gpio number for irq line"); + +static const u8 default_cal_channels[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x09, + 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, + 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xe0, 0x00, 0xe0, 0x00, + 0xe0, 0x00, 0xe0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, + 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, + 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, + 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, + 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, + 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, + 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, + 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, + 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, + 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, + 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, + 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, + 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, + 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, + 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, + 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, + 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x71, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, + 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, + 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, + 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, + 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, + 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, + 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, + 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, + 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, + 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, + 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, + 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, + 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, + 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, + 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, + 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, + 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, + 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, + 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, + 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, + 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, + 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, + 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, + 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, + 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, + 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, + 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, + 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, + 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, + 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, + 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, + 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, + 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, + 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, + 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x09, 0x00, 0x00, 0xc9, 0xff, + 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, + 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, + 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, + 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, + 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, + 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, + 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, + 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, + 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, + 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, + 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, + 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, + 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, + 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, + 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, + 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, + 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, + 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, + 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, + 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, + 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, + 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, + 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, + 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, + 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, + 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, + 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, + 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, + 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, + 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, + 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, + 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, + 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x09, 0x00, 0x00, 0xc9, + 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, + 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, + 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, + 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, + 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, + 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, + 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, + 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, + 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, + 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, + 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, + 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, + 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, + 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, + 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, + 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, + 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, + 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, + 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x8a, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, + 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, + 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, + 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, + 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, + 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, + 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, + 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, + 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, + 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, + 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, + 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, + 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, + 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, + 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, + 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, + 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, + 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x09, 0x00, 0x00, + 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, + 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, + 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, + 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, + 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, + 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, + 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, + 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, + 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, + 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, + 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, + 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, + 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, + 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, + 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, + 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, + 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, + 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, + 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x94, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, + 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, + 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, + 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, + 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, + 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, + 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, + 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, + 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, + 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, + 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, + 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, + 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, + 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, + 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, + 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, + 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, + 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, + 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x09, 0x00, + 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, + 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, + 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, + 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, + 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, + 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, + 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, + 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, + 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, + 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, + 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, + 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, + 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, + 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, + 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, + 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, + 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, + 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x9e, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, + 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, + 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, + 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, + 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, + 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, + 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, + 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, + 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, + 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, + 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, + 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, + 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, + 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, + 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, + 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, + 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, + 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, + 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 }; + +static const u8 default_cal_rssi[] = { + 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, + 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, + 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, + 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, + 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, + 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, + 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, + 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static void stlc45xx_tx_edcf(struct stlc45xx *stlc); +static void stlc45xx_tx_setup(struct stlc45xx *stlc); +static void stlc45xx_tx_scan(struct stlc45xx *stlc); +static void stlc45xx_tx_psm(struct stlc45xx *stlc, bool enable); +static int stlc45xx_tx_nullfunc(struct stlc45xx *stlc, bool powersave); +static int stlc45xx_tx_pspoll(struct stlc45xx *stlc, bool powersave); + +static ssize_t stlc45xx_sysfs_show_cal_rssi(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct stlc45xx *stlc = dev_get_drvdata(dev); + ssize_t len; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + len = PAGE_SIZE; + + mutex_lock(&stlc->mutex); + + if (stlc->cal_rssi) + hex_dump_to_buffer(stlc->cal_rssi, RSSI_CAL_ARRAY_LEN, 16, + 2, buf, len, 0); + mutex_unlock(&stlc->mutex); + + len = strlen(buf); + + return len; +} + +static ssize_t stlc45xx_sysfs_store_cal_rssi(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct stlc45xx *stlc = dev_get_drvdata(dev); + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + mutex_lock(&stlc->mutex); + + if (count != RSSI_CAL_ARRAY_LEN) { + stlc45xx_error("invalid cal_rssi length: %zu", count); + count = 0; + goto out_unlock; + } + + kfree(stlc->cal_rssi); + + stlc->cal_rssi = kmemdup(buf, RSSI_CAL_ARRAY_LEN, GFP_KERNEL); + + if (!stlc->cal_rssi) { + stlc45xx_error("failed to allocate memory for cal_rssi"); + count = 0; + goto out_unlock; + } + + out_unlock: + mutex_unlock(&stlc->mutex); + + return count; +} + +static ssize_t stlc45xx_sysfs_show_cal_channels(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct stlc45xx *stlc = dev_get_drvdata(dev); + ssize_t len; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + len = PAGE_SIZE; + + mutex_lock(&stlc->mutex); + + if (stlc->cal_channels) + hex_dump_to_buffer(stlc->cal_channels, CHANNEL_CAL_ARRAY_LEN, + 16, 2, buf, len, 0); + + mutex_unlock(&stlc->mutex); + + len = strlen(buf); + + return len; +} + +static ssize_t stlc45xx_sysfs_store_cal_channels(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct stlc45xx *stlc = dev_get_drvdata(dev); + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + mutex_lock(&stlc->mutex); + + if (count != CHANNEL_CAL_ARRAY_LEN) { + stlc45xx_error("invalid cal_channels size: %zu ", count); + count = 0; + goto out_unlock; + } + + kfree(stlc->cal_channels); + + stlc->cal_channels = kmemdup(buf, count, GFP_KERNEL); + + if (!stlc->cal_channels) { + stlc45xx_error("failed to allocate memory for cal_channels"); + count = 0; + goto out_unlock; + } + +out_unlock: + mutex_unlock(&stlc->mutex); + + return count; +} + +static ssize_t stlc45xx_sysfs_show_tx_buf(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct stlc45xx *stlc = dev_get_drvdata(dev); + struct txbuffer *entry; + ssize_t len = 0; + + stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); + + mutex_lock(&stlc->mutex); + + list_for_each_entry(entry, &stlc->tx_sent, tx_list) { + len += sprintf(buf + len, "0x%x: 0x%x-0x%x\n", + entry->handle, entry->start, + entry->end); + } + + mutex_unlock(&stlc->mutex); + + return len; +} + +static DEVICE_ATTR(cal_rssi, S_IRUGO | S_IWUSR, + stlc45xx_sysfs_show_cal_rssi, + stlc45xx_sysfs_store_cal_rssi); +static DEVICE_ATTR(cal_channels, S_IRUGO | S_IWUSR, + stlc45xx_sysfs_show_cal_channels, + stlc45xx_sysfs_store_cal_channels); +static DEVICE_ATTR(tx_buf, S_IRUGO, stlc45xx_sysfs_show_tx_buf, NULL); + +static void stlc45xx_spi_read(struct stlc45xx *stlc, unsigned long addr, + void *buf, size_t len) +{ + struct spi_transfer t[2]; + struct spi_message m; + + /* We first push the address */ + addr = (addr << 8) | ADDR_READ_BIT_15; + + spi_message_init(&m); + memset(t, 0, sizeof(t)); + + t[0].tx_buf = &addr; + t[0].len = 2; + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + spi_sync(stlc->spi, &m); +} + + +static void stlc45xx_spi_write(struct stlc45xx *stlc, unsigned long addr, + void *buf, size_t len) +{ + struct spi_transfer t[3]; + struct spi_message m; + u16 last_word; + + /* We first push the address */ + addr = addr << 8; + + spi_message_init(&m); + memset(t, 0, sizeof(t)); + + t[0].tx_buf = &addr; + t[0].len = 2; + spi_message_add_tail(&t[0], &m); + + t[1].tx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); + + if (len % 2) { + last_word = ((u8 *)buf)[len - 1]; + + t[2].tx_buf = &last_word; + t[2].len = 2; + spi_message_add_tail(&t[2], &m); + } + + spi_sync(stlc->spi, &m); +} + +static u16 stlc45xx_read16(struct stlc45xx *stlc, unsigned long addr) +{ + u16 val; + + stlc45xx_spi_read(stlc, addr, &val, sizeof(val)); + + return val; +} + +static u32 stlc45xx_read32(struct stlc45xx *stlc, unsigned long addr) +{ + u32 val; + + stlc45xx_spi_read(stlc, addr, &val, sizeof(val)); + + return val; +} + +static void stlc45xx_write16(struct stlc45xx *stlc, unsigned long addr, u16 val) +{ + stlc45xx_spi_write(stlc, addr, &val, sizeof(val)); +} + +static void stlc45xx_write32(struct stlc45xx *stlc, unsigned long addr, u32 val) +{ + stlc45xx_spi_write(stlc, addr, &val, sizeof(val)); +} + +struct stlc45xx_spi_reg { + u16 address; + u16 length; + char *name; +}; + +/* caller must hold tx_lock */ +static void stlc45xx_txbuffer_dump(struct stlc45xx *stlc) +{ + struct txbuffer *txbuffer; + char *buf, *pos; + int buf_len, l, count; + + if (!(DEBUG_LEVEL & DEBUG_TXBUFFER)) + return; + + stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); + + buf_len = 500; + buf = kmalloc(buf_len, GFP_ATOMIC); + if (!buf) + return; + + pos = buf; + count = 0; + + list_for_each_entry(txbuffer, &stlc->txbuffer, buffer_list) { + l = snprintf(pos, buf_len, "0x%x-0x%x,", + txbuffer->start, txbuffer->end); + /* drop the null byte */ + pos += l; + buf_len -= l; + count++; + } + + if (count == 0) + *pos = '\0'; + else + *--pos = '\0'; + + stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: in buffer %d regions: %s", + count, buf); + + kfree(buf); +} + +/* caller must hold tx_lock */ +static int stlc45xx_txbuffer_find(struct stlc45xx *stlc, size_t len) +{ + struct txbuffer *txbuffer; + int pos; + + stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); + + pos = FIRMWARE_TXBUFFER_START; + + if (list_empty(&stlc->txbuffer)) + goto out; + + /* + * the entries in txbuffer must be in the same order as they are in + * the real buffer + */ + list_for_each_entry(txbuffer, &stlc->txbuffer, buffer_list) { + if (pos + len < txbuffer->start) + break; + pos = ALIGN(txbuffer->end + 1, 4); + } + + if (pos + len > FIRMWARE_TXBUFFER_END) + /* not enough room */ + pos = -1; + + stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: find %zu B: 0x%x", len, pos); + +out: + return pos; +} + +static int stlc45xx_txbuffer_add(struct stlc45xx *stlc, + struct txbuffer *txbuffer) +{ + struct txbuffer *r, *prev = NULL; + + if (list_empty(&stlc->txbuffer)) { + list_add(&txbuffer->buffer_list, &stlc->txbuffer); + return 0; + } + + r = list_first_entry(&stlc->txbuffer, struct txbuffer, buffer_list); + + if (txbuffer->start < r->start) { + /* add to the beginning of the list */ + list_add(&txbuffer->buffer_list, &stlc->txbuffer); + return 0; + } + + prev = NULL; + list_for_each_entry(r, &stlc->txbuffer, buffer_list) { + /* skip first entry, we checked for that above */ + if (!prev) { + prev = r; + continue; + } + + /* double-check overlaps */ + WARN_ON_ONCE(txbuffer->start >= r->start && + txbuffer->start <= r->end); + WARN_ON_ONCE(txbuffer->end >= r->start && + txbuffer->end <= r->end); + + if (prev->end < txbuffer->start && + txbuffer->end < r->start) { + /* insert at this spot */ + list_add_tail(&txbuffer->buffer_list, &r->buffer_list); + return 0; + } + + prev = r; + } + + /* not found */ + list_add_tail(&txbuffer->buffer_list, &stlc->txbuffer); + + return 0; + +} + +/* caller must hold tx_lock */ +static struct txbuffer *stlc45xx_txbuffer_alloc(struct stlc45xx *stlc, + size_t frame_len) +{ + struct txbuffer *entry = NULL; + size_t len; + int pos; + + stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); + + len = FIRMWARE_TXBUFFER_HEADER + frame_len + FIRMWARE_TXBUFFER_TRAILER; + pos = stlc45xx_txbuffer_find(stlc, len); + + if (pos < 0) + return NULL; + + WARN_ON_ONCE(pos + len > FIRMWARE_TXBUFFER_END); + WARN_ON_ONCE(pos < FIRMWARE_TXBUFFER_START); + + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + entry->start = pos; + entry->frame_start = pos + FIRMWARE_TXBUFFER_HEADER; + entry->end = entry->start + len - 1; + + stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: allocated 0x%x-0x%x", + entry->start, entry->end); + + stlc45xx_txbuffer_add(stlc, entry); + + stlc45xx_txbuffer_dump(stlc); + + return entry; +} + +/* caller must hold tx_lock */ +static void stlc45xx_txbuffer_free(struct stlc45xx *stlc, + struct txbuffer *txbuffer) +{ + stlc45xx_debug(DEBUG_FUNC, "%s()", __func__); + + stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: freed 0x%x-0x%x", + txbuffer->start, txbuffer->end); + + list_del(&txbuffer->buffer_list); + kfree(txbuffer); +} + + +static int stlc45xx_wait_bit(struct stlc45xx *stlc, u16 reg, u32 mask, + u32 expected) +{ + int i; + char buffer[4]; + + for (i = 0; i < 2000; i++) { + stlc45xx_spi_read(stlc, reg, buffer, sizeof(buffer)); + if (((*(u32 *)buffer) & mask) == expected) + return 1; + msleep(1); + } + + return 0; +} + +static int stlc45xx_request_firmware(struct stlc45xx *stlc) +{ + const struct firmware *fw; + int ret; + + /* FIXME: should driver use it's own struct device? */ + ret = request_firmware(&fw, "3826.arm", &stlc->spi->dev); + + if (ret < 0) { + stlc45xx_error("request_firmware() failed: %d", ret); + return ret; + } + + if (fw->size % 4) { + stlc45xx_error("firmware size is not multiple of 32bit: %zu", + fw->size); + return -EILSEQ; /* Illegal byte sequence */; + } + + if (fw->size < 1000) { + stlc45xx_error("firmware is too small: %zu", fw->size); + return -EILSEQ; + } + + stlc->fw = kmemdup(fw->data, fw->size, GFP_KERNEL); + if (!stlc->fw) { + stlc45xx_error("could not allocate memory for firmware"); + return -ENOMEM; + } + + stlc->fw_len = fw->size; + + release_firmware(fw); + + return 0; +} + +static int stlc45xx_upload_firmware(struct stlc45xx *stlc) +{ + struct s_dma_regs dma_regs; + unsigned long fw_len, fw_addr; + long _fw_len; + int ret; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + if (!stlc->fw) { + ret = stlc45xx_request_firmware(stlc); + if (ret < 0) + return ret; + } + + /* stop the device */ + stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT, + SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET + | SPI_CTRL_STAT_START_HALTED); + + msleep(TARGET_BOOT_SLEEP); + + stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT, + SPI_CTRL_STAT_HOST_OVERRIDE + | SPI_CTRL_STAT_START_HALTED); + + msleep(TARGET_BOOT_SLEEP); + + fw_addr = FIRMWARE_ADDRESS; + fw_len = stlc->fw_len; + + while (fw_len > 0) { + _fw_len = (fw_len > SPI_MAX_PACKET_SIZE) + ? SPI_MAX_PACKET_SIZE : fw_len; + dma_regs.cmd = SPI_DMA_WRITE_CTRL_ENABLE; + dma_regs.len = cpu_to_le16(_fw_len); + dma_regs.addr = cpu_to_le32(fw_addr); + + fw_len -= _fw_len; + fw_addr += _fw_len; + + stlc45xx_write16(stlc, SPI_ADRS_DMA_WRITE_CTRL, dma_regs.cmd); + + if (stlc45xx_wait_bit(stlc, SPI_ADRS_DMA_WRITE_CTRL, + HOST_ALLOWED, HOST_ALLOWED) == 0) { + stlc45xx_error("fw_upload not allowed to DMA write"); + return -EAGAIN; + } + + stlc45xx_write16(stlc, SPI_ADRS_DMA_WRITE_LEN, dma_regs.len); + stlc45xx_write32(stlc, SPI_ADRS_DMA_WRITE_BASE, dma_regs.addr); + + stlc45xx_spi_write(stlc, SPI_ADRS_DMA_DATA, stlc->fw, _fw_len); + + /* FIXME: I think this doesn't work if firmware is large, + * this loop goes to second round. fw->data is not + * increased at all! */ + } + + BUG_ON(fw_len != 0); + + /* enable host interrupts */ + stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_EN, SPI_HOST_INTS_DEFAULT); + + /* boot the device */ + stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT, + SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET + | SPI_CTRL_STAT_RAM_BOOT); + + msleep(TARGET_BOOT_SLEEP); + + stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT, + SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT); + msleep(TARGET_BOOT_SLEEP); + + return 0; +} + +/* caller must hold tx_lock */ +static void stlc45xx_check_txsent(struct stlc45xx *stlc) +{ + struct txbuffer *entry, *n; + + list_for_each_entry_safe(entry, n, &stlc->tx_sent, tx_list) { + if (time_after(jiffies, entry->lifetime)) { + if (net_ratelimit()) + stlc45xx_warning("frame 0x%x lifetime exceeded", + entry->start); + list_del(&entry->tx_list); + skb_pull(entry->skb, entry->header_len); + ieee80211_tx_status(stlc->hw, entry->skb); + stlc45xx_txbuffer_free(stlc, entry); + } + } +} + +static void stlc45xx_power_off(struct stlc45xx *stlc) +{ + disable_irq(gpio_to_irq(stlc45xx_gpio_irq)); + gpio_set_value(stlc45xx_gpio_power, 0); +} + +static void stlc45xx_power_on(struct stlc45xx *stlc) +{ + gpio_set_value(stlc45xx_gpio_power, 1); + enable_irq(gpio_to_irq(stlc45xx_gpio_irq)); + + /* + * need to wait a while before device can be accessed, the length + * is just a guess + */ + msleep(10); +} + +/* caller must hold tx_lock */ +static void stlc45xx_flush_queues(struct stlc45xx *stlc) +{ + struct txbuffer *entry; + + while (!list_empty(&stlc->tx_sent)) { + entry = list_first_entry(&stlc->tx_sent, + struct txbuffer, tx_list); + list_del(&entry->tx_list); + dev_kfree_skb(entry->skb); + stlc45xx_txbuffer_free(stlc, entry); + } + + WARN_ON(!list_empty(&stlc->tx_sent)); + + while (!list_empty(&stlc->tx_pending)) { + entry = list_first_entry(&stlc->tx_pending, + struct txbuffer, tx_list); + list_del(&entry->tx_list); + dev_kfree_skb(entry->skb); + stlc45xx_txbuffer_free(stlc, entry); + } + + WARN_ON(!list_empty(&stlc->tx_pending)); + WARN_ON(!list_empty(&stlc->txbuffer)); +} + +static void stlc45xx_work_reset(struct work_struct *work) +{ + struct stlc45xx *stlc = container_of(work, struct stlc45xx, + work_reset); + + mutex_lock(&stlc->mutex); + + if (stlc->fw_state != FW_STATE_RESET) + goto out; + + stlc45xx_power_off(stlc); + + mutex_unlock(&stlc->mutex); + + /* wait that all work_structs have finished, we can't hold + * stlc->mutex to avoid deadlock */ + cancel_work_sync(&stlc->work); + + /* FIXME: find out good value to wait for chip power down */ + msleep(100); + + mutex_lock(&stlc->mutex); + + /* FIXME: we should gracefully handle if the state has changed + * after re-acquiring mutex */ + WARN_ON(stlc->fw_state != FW_STATE_RESET); + + spin_lock_bh(&stlc->tx_lock); + stlc45xx_flush_queues(stlc); + spin_unlock_bh(&stlc->tx_lock); + + stlc->fw_state = FW_STATE_RESETTING; + + stlc45xx_power_on(stlc); + stlc45xx_upload_firmware(stlc); + +out: + mutex_unlock(&stlc->mutex); +} + +/* caller must hold mutex */ +static void stlc45xx_reset(struct stlc45xx *stlc) +{ + stlc45xx_warning("resetting firmware"); + stlc->fw_state = FW_STATE_RESET; + ieee80211_stop_queues(stlc->hw); + queue_work(stlc->hw->workqueue, &stlc->work_reset); +} + +static void stlc45xx_work_tx_timeout(struct work_struct *work) +{ + struct stlc45xx *stlc = container_of(work, struct stlc45xx, + work_tx_timeout.work); + + stlc45xx_warning("tx timeout"); + + mutex_lock(&stlc->mutex); + + if (stlc->fw_state != FW_STATE_READY) + goto out; + + stlc45xx_reset(stlc); + +out: + mutex_unlock(&stlc->mutex); +} + +static void stlc45xx_int_ack(struct stlc45xx *stlc, u32 val) +{ + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_ACK, val); +} + +static void stlc45xx_wakeup(struct stlc45xx *stlc) +{ + unsigned long timeout; + u32 ints; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + /* wake the chip */ + stlc45xx_write32(stlc, SPI_ADRS_ARM_INTERRUPTS, SPI_TARGET_INT_WAKEUP); + + /* And wait for the READY interrupt */ + timeout = jiffies + HZ; + + ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); + while (!(ints & SPI_HOST_INT_READY)) { + if (time_after(jiffies, timeout)) + goto out; + ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); + } + + stlc45xx_int_ack(stlc, SPI_HOST_INT_READY); + +out: + return; +} + +static void stlc45xx_sleep(struct stlc45xx *stlc) +{ + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + stlc45xx_write32(stlc, SPI_ADRS_ARM_INTERRUPTS, SPI_TARGET_INT_SLEEP); +} + +static void stlc45xx_int_ready(struct stlc45xx *stlc) +{ + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_EN, + SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE); + + switch (stlc->fw_state) { + case FW_STATE_BOOTING: + stlc->fw_state = FW_STATE_READY; + complete(&stlc->fw_comp); + break; + case FW_STATE_RESETTING: + stlc->fw_state = FW_STATE_READY; + + stlc45xx_tx_scan(stlc); + stlc45xx_tx_setup(stlc); + stlc45xx_tx_edcf(stlc); + + ieee80211_wake_queues(stlc->hw); + break; + default: + break; + } +} + +static int stlc45xx_rx_txack(struct stlc45xx *stlc, struct sk_buff *skb) +{ + struct ieee80211_tx_info *info; + struct s_lm_control *control; + struct s_lmo_tx *tx; + struct txbuffer *entry; + int found = 0; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + control = (struct s_lm_control *) skb->data; + tx = (struct s_lmo_tx *) (control + 1); + + if (list_empty(&stlc->tx_sent)) { + if (net_ratelimit()) + stlc45xx_warning("no frames waiting for " + "acknowledgement"); + return -1; + } + + list_for_each_entry(entry, &stlc->tx_sent, tx_list) { + if (control->handle == entry->handle) { + found = 1; + break; + } + } + + if (!found) { + if (net_ratelimit()) + stlc45xx_warning("couldn't find frame for tx ack 0x%x", + control->handle); + return -1; + } + + stlc45xx_debug(DEBUG_TX, "TX ACK 0x%x", entry->handle); + + if (entry->status_needed) { + info = IEEE80211_SKB_CB(entry->skb); + + if (!(tx->flags & LM_TX_FAILED)) { + /* frame was acked */ + info->flags |= IEEE80211_TX_STAT_ACK; + info->status.ack_signal = tx->rcpi / 2 - 110; + } + + skb_pull(entry->skb, entry->header_len); + + ieee80211_tx_status(stlc->hw, entry->skb); + } + + list_del(&entry->tx_list); + + stlc45xx_check_txsent(stlc); + if (list_empty(&stlc->tx_sent)) + /* there are no pending frames, we can stop the tx timeout + * timer */ + cancel_delayed_work(&stlc->work_tx_timeout); + + spin_lock_bh(&stlc->tx_lock); + + stlc45xx_txbuffer_free(stlc, entry); + + if (stlc->tx_queue_stopped && + stlc45xx_txbuffer_find(stlc, MAX_FRAME_LEN) != -1) { + stlc45xx_debug(DEBUG_QUEUE, "room in tx buffer, waking queues"); + ieee80211_wake_queues(stlc->hw); + stlc->tx_queue_stopped = 0; + } + + spin_unlock_bh(&stlc->tx_lock); + + return 0; +} + +static int stlc45xx_rx_control(struct stlc45xx *stlc, struct sk_buff *skb) +{ + struct s_lm_control *control; + int ret = 0; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + control = (struct s_lm_control *) skb->data; + + switch (control->oid) { + case LM_OID_TX: + ret = stlc45xx_rx_txack(stlc, skb); + break; + case LM_OID_SETUP: + case LM_OID_SCAN: + case LM_OID_TRAP: + case LM_OID_EDCF: + case LM_OID_KEYCACHE: + case LM_OID_PSM: + case LM_OID_STATS: + case LM_OID_LED: + default: + stlc45xx_warning("unhandled rx control oid %d\n", + control->oid); + break; + } + + dev_kfree_skb(skb); + + return ret; +} + +/* copied from mac80211 */ +static void stlc45xx_parse_elems(u8 *start, size_t len, + struct stlc45xx_ie_tim **tim, + size_t *tim_len) +{ + size_t left = len; + u8 *pos = start; + + while (left >= 2) { + u8 id, elen; + + id = *pos++; + elen = *pos++; + left -= 2; + + if (elen > left) + return; + + switch (id) { + case WLAN_EID_TIM: + *tim = (struct stlc45xx_ie_tim *) pos; + *tim_len = elen; + break; + default: + break; + } + + left -= elen; + pos += elen; + } +} + +/* + * mac80211 doesn't have support for asking frames with PS-Poll, so let's + * implement in the driver for now. We have to add support to mac80211 + * later. + */ +static int stlc45xx_check_more_data(struct stlc45xx *stlc, struct sk_buff *skb) +{ + struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data; + struct ieee80211_hdr *hdr; + size_t len; + u16 fc; + + hdr = (void *) skb->data + sizeof(*data); + len = skb->len - sizeof(*data); + + /* minimum frame length is the null frame length 24 bytes */ + if (len < 24) { + stlc45xx_warning("invalid frame length when checking for " + "more data"); + return -EINVAL; + } + + fc = le16_to_cpu(hdr->frame_control); + if (!(fc & IEEE80211_FCTL_FROMDS)) + /* this is not from DS */ + return 0; + + if (compare_ether_addr(hdr->addr1, stlc->mac_addr) != 0) + /* the frame was not for us */ + return 0; + + if (!(fc & IEEE80211_FCTL_MOREDATA)) { + /* AP has no more frames buffered for us */ + stlc45xx_debug(DEBUG_PSM, "all buffered frames retrieved"); + stlc->pspolling = false; + return 0; + } + + /* MOREDATA bit is set, let's ask for a new frame from the AP */ + stlc45xx_tx_pspoll(stlc, stlc->psm); + + return 0; +} + +/* + * mac80211 cannot read TIM from beacons, so let's add a hack to the + * driver. We have to add support to mac80211 later. + */ +static int stlc45xx_rx_data_beacon(struct stlc45xx *stlc, struct sk_buff *skb) +{ + struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data; + size_t len = skb->len, tim_len = 0, baselen, pvbmap_len; + struct ieee80211_mgmt *mgmt; + struct stlc45xx_ie_tim *tim = NULL; + int bmap_offset, index, aid_bit; + + mgmt = (void *) skb->data + sizeof(*data); + + baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; + if (baselen > len) { + stlc45xx_warning("invalid baselen in beacon"); + return -EINVAL; + } + + stlc45xx_parse_elems(mgmt->u.beacon.variable, len - baselen, &tim, + &tim_len); + + if (!tim) { + stlc45xx_warning("didn't find tim from a beacon"); + return -EINVAL; + } + + bmap_offset = tim->bmap_control & 0xfe; + index = stlc->aid / 8 - bmap_offset; + + pvbmap_len = tim_len - 3; + if (index > pvbmap_len) + return -EINVAL; + + aid_bit = !!(tim->pvbmap[index] & (1 << stlc->aid % 8)); + + stlc45xx_debug(DEBUG_PSM, "fc 0x%x duration %d seq %d dtim %u " + "bmap_control 0x%x aid_bit %d", + mgmt->frame_control, mgmt->duration, mgmt->seq_ctrl >> 4, + tim->dtim_count, tim->bmap_control, aid_bit); + + if (!aid_bit) + return 0; + + stlc->pspolling = true; + stlc45xx_tx_pspoll(stlc, stlc->psm); + + return 0; +} + +static int stlc45xx_rx_data(struct stlc45xx *stlc, struct sk_buff *skb) +{ + struct ieee80211_rx_status status; + struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data; + int align = 0; + u8 *p, align_len; + u16 len; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + if (stlc->psm) { + if (data->flags & LM_IN_BEACON) + stlc45xx_rx_data_beacon(stlc, skb); + else if (stlc->pspolling && (data->flags & LM_IN_DATA)) + stlc45xx_check_more_data(stlc, skb); + } + + memset(&status, 0, sizeof(status)); + + status.freq = data->frequency; + status.signal = data->rcpi / 2 - 110; + + /* let's assume that maximum rcpi value is 140 (= 35 dBm) */ + status.qual = data->rcpi * 100 / 140; + + status.band = IEEE80211_BAND_2GHZ; + + /* + * FIXME: this gives warning from __ieee80211_rx() + * + * status.rate_idx = data->rate; + */ + + len = data->length; + + if (data->flags & LM_FLAG_ALIGN) + align = 1; + + skb_pull(skb, sizeof(*data)); + + if (align) { + p = skb->data; + align_len = *p; + skb_pull(skb, align_len); + } + + skb_trim(skb, len); + + stlc45xx_debug(DEBUG_RX, "rx data 0x%p %d B", skb->data, skb->len); + stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len); + + ieee80211_rx(stlc->hw, skb, &status); + + return 0; +} + + + +static int stlc45xx_rx(struct stlc45xx *stlc) +{ + struct s_lm_control *control; + struct sk_buff *skb; + int ret; + u16 len; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + stlc45xx_wakeup(stlc); + + /* dummy read to flush SPI DMA controller bug */ + stlc45xx_read16(stlc, SPI_ADRS_GEN_PURP_1); + + len = stlc45xx_read16(stlc, SPI_ADRS_DMA_DATA); + + if (len == 0) { + stlc45xx_warning("rx request of zero bytes"); + return 0; + } + + skb = dev_alloc_skb(len); + if (!skb) { + stlc45xx_warning("could not alloc skb"); + return 0; + } + + stlc45xx_spi_read(stlc, SPI_ADRS_DMA_DATA, skb_put(skb, len), len); + + stlc45xx_sleep(stlc); + + stlc45xx_debug(DEBUG_RX, "rx frame 0x%p %d B", skb->data, skb->len); + stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len); + + control = (struct s_lm_control *) skb->data; + + if (control->flags & LM_FLAG_CONTROL) + ret = stlc45xx_rx_control(stlc, skb); + else + ret = stlc45xx_rx_data(stlc, skb); + + return ret; +} + + +static irqreturn_t stlc45xx_interrupt(int irq, void *config) +{ + struct spi_device *spi = config; + struct stlc45xx *stlc = dev_get_drvdata(&spi->dev); + + stlc45xx_debug(DEBUG_IRQ, "IRQ"); + + queue_work(stlc->hw->workqueue, &stlc->work); + + return IRQ_HANDLED; +} + +static int stlc45xx_tx_frame(struct stlc45xx *stlc, u32 address, + void *buf, size_t len) +{ + struct s_dma_regs dma_regs; + unsigned long timeout; + int ret = 0; + u32 ints; + + stlc->tx_frames++; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + stlc45xx_debug(DEBUG_TX, "tx frame 0x%p %zu B", buf, len); + stlc45xx_dump(DEBUG_TX_CONTENT, buf, len); + + stlc45xx_wakeup(stlc); + + dma_regs.cmd = SPI_DMA_WRITE_CTRL_ENABLE; + dma_regs.len = cpu_to_le16(len); + dma_regs.addr = cpu_to_le32(address); + + stlc45xx_spi_write(stlc, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs, + sizeof(dma_regs)); + + stlc45xx_spi_write(stlc, SPI_ADRS_DMA_DATA, buf, len); + + timeout = jiffies + 2 * HZ; + ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); + while (!(ints & SPI_HOST_INT_WR_READY)) { + if (time_after(jiffies, timeout)) { + stlc45xx_warning("WR_READY timeout"); + ret = -1; + goto out; + } + ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); + } + + stlc45xx_int_ack(stlc, SPI_HOST_INT_WR_READY); + + stlc45xx_sleep(stlc); + +out: + return ret; +} + +static int stlc45xx_wq_tx(struct stlc45xx *stlc) +{ + struct txbuffer *entry; + int ret = 0; + + spin_lock_bh(&stlc->tx_lock); + + while (!list_empty(&stlc->tx_pending)) { + entry = list_entry(stlc->tx_pending.next, + struct txbuffer, tx_list); + + list_del_init(&entry->tx_list); + + spin_unlock_bh(&stlc->tx_lock); + + ret = stlc45xx_tx_frame(stlc, entry->frame_start, + entry->skb->data, entry->skb->len); + + spin_lock_bh(&stlc->tx_lock); + + if (ret < 0) { + /* frame transfer to firmware buffer failed */ + /* FIXME: report this to mac80211 */ + dev_kfree_skb(entry->skb); + stlc45xx_txbuffer_free(stlc, entry); + goto out; + } + + list_add(&entry->tx_list, &stlc->tx_sent); + queue_delayed_work(stlc->hw->workqueue, + &stlc->work_tx_timeout, + msecs_to_jiffies(TX_TIMEOUT)); + } + +out: + spin_unlock_bh(&stlc->tx_lock); + return ret; +} + +static void stlc45xx_work(struct work_struct *work) +{ + struct stlc45xx *stlc = container_of(work, struct stlc45xx, work); + u32 ints; + int ret; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + mutex_lock(&stlc->mutex); + + if (stlc->fw_state == FW_STATE_OFF && + stlc->fw_state == FW_STATE_RESET) + goto out; + + ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); + stlc45xx_debug(DEBUG_BH, "begin host_ints 0x%08x", ints); + + if (ints & SPI_HOST_INT_READY) { + stlc45xx_int_ready(stlc); + stlc45xx_int_ack(stlc, SPI_HOST_INT_READY); + } + + if (stlc->fw_state != FW_STATE_READY) + goto out; + + if (ints & SPI_HOST_INT_UPDATE) { + stlc45xx_int_ack(stlc, SPI_HOST_INT_UPDATE); + ret = stlc45xx_rx(stlc); + if (ret < 0) { + stlc45xx_reset(stlc); + goto out; + } + } + if (ints & SPI_HOST_INT_SW_UPDATE) { + stlc45xx_int_ack(stlc, SPI_HOST_INT_SW_UPDATE); + ret = stlc45xx_rx(stlc); + if (ret < 0) { + stlc45xx_reset(stlc); + goto out; + } + } + + ret = stlc45xx_wq_tx(stlc); + if (ret < 0) { + stlc45xx_reset(stlc); + goto out; + } + + ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS); + stlc45xx_debug(DEBUG_BH, "end host_ints 0x%08x", ints); + +out: + mutex_unlock(&stlc->mutex); +} + +static void stlc45xx_tx_edcf(struct stlc45xx *stlc) +{ + struct s_lm_control *control; + struct s_lmo_edcf *edcf; + size_t len, edcf_len; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + edcf_len = sizeof(*edcf); + len = sizeof(*control) + edcf_len; + control = kzalloc(len, GFP_KERNEL); + edcf = (struct s_lmo_edcf *) (control + 1); + + control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET; + control->length = edcf_len; + control->oid = LM_OID_EDCF; + + edcf->slottime = 0x14; + edcf->sifs = 10; + edcf->eofpad = 6; + edcf->maxburst = 1500; + + edcf->queues[0].aifs = 2; + edcf->queues[0].pad0 = 1; + edcf->queues[0].cwmin = 3; + edcf->queues[0].cwmax = 7; + edcf->queues[0].txop = 47; + edcf->queues[1].aifs = 2; + edcf->queues[1].pad0 = 0; + edcf->queues[1].cwmin = 7; + edcf->queues[1].cwmax = 15; + edcf->queues[1].txop = 94; + edcf->queues[2].aifs = 3; + edcf->queues[2].pad0 = 0; + edcf->queues[2].cwmin = 15; + edcf->queues[2].cwmax = 1023; + edcf->queues[2].txop = 0; + edcf->queues[3].aifs = 7; + edcf->queues[3].pad0 = 0; + edcf->queues[3].cwmin = 15; + edcf->queues[3].cwmax = 1023; + edcf->queues[3].txop = 0; + edcf->queues[4].aifs = 13; + edcf->queues[4].pad0 = 99; + edcf->queues[4].cwmin = 3437; + edcf->queues[4].cwmax = 512; + edcf->queues[4].txop = 12; + edcf->queues[5].aifs = 142; + edcf->queues[5].pad0 = 109; + edcf->queues[5].cwmin = 8756; + edcf->queues[5].cwmax = 6; + edcf->queues[5].txop = 0; + edcf->queues[6].aifs = 4; + edcf->queues[6].pad0 = 0; + edcf->queues[6].cwmin = 0; + edcf->queues[6].cwmax = 58705; + edcf->queues[6].txop = 25716; + edcf->queues[7].aifs = 0; + edcf->queues[7].pad0 = 0; + edcf->queues[7].cwmin = 0; + edcf->queues[7].cwmax = 0; + edcf->queues[7].txop = 0; + + stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len); + + kfree(control); +} + +static void stlc45xx_tx_setup(struct stlc45xx *stlc) +{ + struct s_lm_control *control; + struct s_lmo_setup *setup; + size_t len, setup_len; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + setup_len = sizeof(*setup); + len = sizeof(*control) + setup_len; + control = kzalloc(len, GFP_KERNEL); + setup = (struct s_lmo_setup *) (control + 1); + + control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET; + control->length = setup_len; + control->oid = LM_OID_SETUP; + + setup->flags = LM_SETUP_INFRA; + setup->antenna = 2; + setup->rx_align = 0; + setup->rx_buffer = FIRMWARE_RXBUFFER_START; + setup->rx_mtu = FIRMWARE_MTU; + setup->frontend = 5; + setup->timeout = 0; + setup->truncate = 48896; + setup->bratemask = 0xffffffff; + setup->ref_clock = 644245094; + setup->lpf_bandwidth = 65535; + setup->osc_start_delay = 65535; + + memcpy(setup->macaddr, stlc->mac_addr, ETH_ALEN); + memcpy(setup->bssid, stlc->bssid, ETH_ALEN); + + stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len); + + kfree(control); +} + +static void stlc45xx_tx_scan(struct stlc45xx *stlc) +{ + struct s_lm_control *control; + struct s_lmo_scan *scan; + size_t len, scan_len; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + scan_len = sizeof(*scan); + len = sizeof(*control) + scan_len; + control = kzalloc(len, GFP_KERNEL); + scan = (struct s_lmo_scan *) (control + 1); + + control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET; + control->length = scan_len; + control->oid = LM_OID_SCAN; + + scan->flags = LM_SCAN_EXIT; + scan->bratemask = 0x15f; + scan->aloft[0] = 3; + scan->aloft[1] = 3; + scan->aloft[2] = 1; + scan->aloft[3] = 0; + scan->aloft[4] = 0; + scan->aloft[5] = 0; + scan->aloft[6] = 0; + scan->aloft[7] = 0; + + memcpy(&scan->rssical, &stlc->cal_rssi[(stlc->channel - 1) * + RSSI_CAL_LEN], + RSSI_CAL_LEN); + memcpy(&scan->channel, &stlc->cal_channels[(stlc->channel - 1) * + CHANNEL_CAL_LEN], + CHANNEL_CAL_LEN); + + stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len); + + kfree(control); +} + +/* + * caller must hold mutex + */ +static int stlc45xx_tx_pspoll(struct stlc45xx *stlc, bool powersave) +{ + struct ieee80211_hdr *pspoll; + int payload_len, padding, i; + struct s_lm_data_out *data; + struct txbuffer *entry; + DECLARE_MAC_BUF(mac); + struct sk_buff *skb; + char *payload; + u16 fc; + + skb = dev_alloc_skb(stlc->hw->extra_tx_headroom + 16); + if (!skb) { + stlc45xx_warning("failed to allocate pspoll frame"); + return -ENOMEM; + } + skb_reserve(skb, stlc->hw->extra_tx_headroom); + + pspoll = (struct ieee80211_hdr *) skb_put(skb, 16); + memset(pspoll, 0, 16); + fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL; + if (powersave) + fc |= IEEE80211_FCTL_PM; + pspoll->frame_control = cpu_to_le16(fc); + pspoll->duration_id = cpu_to_le16(stlc->aid); + + /* aid in PS-Poll has its two MSBs each set to 1 */ + pspoll->duration_id |= cpu_to_le16(1 << 15) | cpu_to_le16(1 << 14); + + memcpy(pspoll->addr1, stlc->bssid, ETH_ALEN); + memcpy(pspoll->addr2, stlc->mac_addr, ETH_ALEN); + + stlc45xx_debug(DEBUG_PSM, "sending PS-Poll frame to %s (powersave %d, " + "fc 0x%x, aid %d)", print_mac(mac, pspoll->addr1), + powersave, fc, stlc->aid); + + spin_lock_bh(&stlc->tx_lock); + + entry = stlc45xx_txbuffer_alloc(stlc, skb->len); + + spin_unlock_bh(&stlc->tx_lock); + + if (!entry) { + /* + * The queue should be stopped before the firmware buffer + * is full, so firmware buffer should always have enough + * space. + * + * But I'm too lazy and omit it for now. + */ + if (net_ratelimit()) + stlc45xx_warning("firmware tx buffer full is full " + "for null frame"); + return -ENOSPC; + } + + payload = skb->data; + payload_len = skb->len; + padding = (int) (skb->data - sizeof(*data)) & 3; + entry->header_len = sizeof(*data) + padding; + + entry->skb = skb; + entry->status_needed = false; + entry->handle = (u32) skb; + entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME); + + stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B " + "padding %d header_len %d)", + entry->handle, payload, payload_len, padding, + entry->header_len); + stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len); + + data = (struct s_lm_data_out *) skb_push(skb, entry->header_len); + + memset(data, 0, entry->header_len); + + if (padding) + data->flags = LM_FLAG_ALIGN; + + data->flags = LM_OUT_BURST; + data->length = payload_len; + data->handle = entry->handle; + data->aid = 1; + data->rts_retries = 7; + data->retries = 7; + data->aloft_ctrl = 0; + data->crypt_offset = 58; + data->keytype = 0; + data->keylen = 0; + data->queue = LM_QUEUE_DATA3; + data->backlog = 32; + data->antenna = 2; + data->cts = 3; + data->power = 127; + + for (i = 0; i < 8; i++) + data->aloft[i] = 0; + + /* + * check if there's enough space in tx buffer + * + * FIXME: ignored for now + */ + + stlc45xx_tx_frame(stlc, entry->start, skb->data, skb->len); + + list_add(&entry->tx_list, &stlc->tx_sent); + + return 0; +} + +/* + * caller must hold mutex + * + * shamelessly stolen from mac80211/ieee80211_send_nullfunc + */ +static int stlc45xx_tx_nullfunc(struct stlc45xx *stlc, bool powersave) +{ + struct ieee80211_hdr *nullfunc; + int payload_len, padding, i; + struct s_lm_data_out *data; + struct txbuffer *entry; + DECLARE_MAC_BUF(mac); + struct sk_buff *skb; + char *payload; + u16 fc; + + skb = dev_alloc_skb(stlc->hw->extra_tx_headroom + 24); + if (!skb) { + stlc45xx_warning("failed to allocate buffer for null frame\n"); + return -ENOMEM; + } + skb_reserve(skb, stlc->hw->extra_tx_headroom); + + nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); + memset(nullfunc, 0, 24); + fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_TODS; + + if (powersave) + fc |= IEEE80211_FCTL_PM; + + nullfunc->frame_control = cpu_to_le16(fc); + memcpy(nullfunc->addr1, stlc->bssid, ETH_ALEN); + memcpy(nullfunc->addr2, stlc->mac_addr, ETH_ALEN); + memcpy(nullfunc->addr3, stlc->bssid, ETH_ALEN); + + stlc45xx_debug(DEBUG_PSM, "sending Null frame to %s (powersave %d, " + "fc 0x%x)", + print_mac(mac, nullfunc->addr1), powersave, fc); + + spin_lock_bh(&stlc->tx_lock); + + entry = stlc45xx_txbuffer_alloc(stlc, skb->len); + + spin_unlock_bh(&stlc->tx_lock); + + if (!entry) { + /* + * The queue should be stopped before the firmware buffer + * is full, so firmware buffer should always have enough + * space. + * + * But I'm too lazy and omit it for now. + */ + if (net_ratelimit()) + stlc45xx_warning("firmware tx buffer full is full " + "for null frame"); + return -ENOSPC; + } + + payload = skb->data; + payload_len = skb->len; + padding = (int) (skb->data - sizeof(*data)) & 3; + entry->header_len = sizeof(*data) + padding; + + entry->skb = skb; + entry->status_needed = false; + entry->handle = (u32) skb; + entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME); + + stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B " + "padding %d header_len %d)", + entry->handle, payload, payload_len, padding, + entry->header_len); + stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len); + + data = (struct s_lm_data_out *) skb_push(skb, entry->header_len); + + memset(data, 0, entry->header_len); + + if (padding) + data->flags = LM_FLAG_ALIGN; + + data->flags = LM_OUT_BURST; + data->length = payload_len; + data->handle = entry->handle; + data->aid = 1; + data->rts_retries = 7; + data->retries = 7; + data->aloft_ctrl = 0; + data->crypt_offset = 58; + data->keytype = 0; + data->keylen = 0; + data->queue = LM_QUEUE_DATA3; + data->backlog = 32; + data->antenna = 2; + data->cts = 3; + data->power = 127; + + for (i = 0; i < 8; i++) + data->aloft[i] = 0; + + /* + * check if there's enough space in tx buffer + * + * FIXME: ignored for now + */ + + stlc45xx_tx_frame(stlc, entry->start, skb->data, skb->len); + + list_add(&entry->tx_list, &stlc->tx_sent); + + return 0; +} + +/* caller must hold mutex */ +static void stlc45xx_tx_psm(struct stlc45xx *stlc, bool enable) +{ + struct s_lm_control *control; + struct s_lmo_psm *psm; + size_t len, psm_len; + + WARN_ON(!stlc->associated); + WARN_ON(stlc->aid < 1); + WARN_ON(stlc->aid > 2007); + + psm_len = sizeof(*psm); + len = sizeof(*control) + psm_len; + control = kzalloc(len, GFP_KERNEL); + psm = (struct s_lmo_psm *) (control + 1); + + control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET; + control->length = psm_len; + control->oid = LM_OID_PSM; + + if (enable) + psm->flags |= LM_PSM; + + psm->aid = stlc->aid; + + psm->beacon_rcpi_skip_max = 60; + + psm->intervals[0].interval = 1; + psm->intervals[0].periods = 1; + psm->intervals[1].interval = 1; + psm->intervals[1].periods = 1; + psm->intervals[2].interval = 1; + psm->intervals[2].periods = 1; + psm->intervals[3].interval = 1; + psm->intervals[3].periods = 1; + + psm->nr = 0; + psm->exclude[0] = 0; + + stlc45xx_debug(DEBUG_PSM, "sending LM_OID_PSM (aid %d, interval %d)", + psm->aid, psm->intervals[0].interval); + + stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len); + + kfree(control); +} + +static int stlc45xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct stlc45xx *stlc = hw->priv; + struct ieee80211_tx_info *info; + struct ieee80211_rate *rate; + int payload_len, padding, i; + struct s_lm_data_out *data; + struct txbuffer *entry; + char *payload; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + spin_lock_bh(&stlc->tx_lock); + + entry = stlc45xx_txbuffer_alloc(stlc, skb->len); + if (!entry) { + /* the queue should be stopped before the firmware buffer + * is full, so firmware buffer should always have enough + * space */ + if (net_ratelimit()) + stlc45xx_warning("firmware buffer full"); + spin_unlock_bh(&stlc->tx_lock); + return NETDEV_TX_BUSY; + } + + info = IEEE80211_SKB_CB(skb); + + payload = skb->data; + payload_len = skb->len; + padding = (int) (skb->data - sizeof(*data)) & 3; + entry->header_len = sizeof(*data) + padding; + + entry->skb = skb; + entry->status_needed = true; + entry->handle = (u32) skb; + entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME); + + stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B " + "padding %d header_len %d)", + entry->handle, payload, payload_len, padding, + entry->header_len); + stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len); + + data = (struct s_lm_data_out *) skb_push(skb, entry->header_len); + + memset(data, 0, entry->header_len); + + if (padding) + data->flags = LM_FLAG_ALIGN; + + data->flags = LM_OUT_BURST; + data->length = payload_len; + data->handle = entry->handle; + data->aid = 1; + data->rts_retries = 7; + data->retries = 7; + data->aloft_ctrl = 0; + data->crypt_offset = 58; + data->keytype = 0; + data->keylen = 0; + data->queue = 2; + data->backlog = 32; + data->antenna = 2; + data->cts = 3; + data->power = 127; + + for (i = 0; i < 8; i++) { + rate = ieee80211_get_tx_rate(stlc->hw, info); + data->aloft[i] = rate->hw_value; + } + + list_add_tail(&entry->tx_list, &stlc->tx_pending); + + /* check if there's enough space in tx buffer */ + if (stlc45xx_txbuffer_find(stlc, MAX_FRAME_LEN) == -1) { + stlc45xx_debug(DEBUG_QUEUE, "tx buffer full, stopping queues"); + stlc->tx_queue_stopped = 1; + ieee80211_stop_queues(stlc->hw); + } + + queue_work(stlc->hw->workqueue, &stlc->work); + + spin_unlock_bh(&stlc->tx_lock); + + return NETDEV_TX_OK; +} + +static int stlc45xx_op_start(struct ieee80211_hw *hw) +{ + struct stlc45xx *stlc = hw->priv; + unsigned long timeout; + int ret = 0; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + mutex_lock(&stlc->mutex); + + stlc->fw_state = FW_STATE_BOOTING; + stlc->channel = 1; + + stlc45xx_power_on(stlc); + + ret = stlc45xx_upload_firmware(stlc); + if (ret < 0) { + stlc45xx_power_off(stlc); + goto out_unlock; + } + + stlc->tx_queue_stopped = 0; + + mutex_unlock(&stlc->mutex); + + timeout = msecs_to_jiffies(2000); + timeout = wait_for_completion_interruptible_timeout(&stlc->fw_comp, + timeout); + if (!timeout) { + stlc45xx_error("firmware boot failed"); + stlc45xx_power_off(stlc); + ret = -1; + goto out; + } + + stlc45xx_debug(DEBUG_BOOT, "firmware booted"); + + /* FIXME: should we take mutex just after wait_for_completion()? */ + mutex_lock(&stlc->mutex); + + WARN_ON(stlc->fw_state != FW_STATE_READY); + +out_unlock: + mutex_unlock(&stlc->mutex); + +out: + return ret; +} + +static void stlc45xx_op_stop(struct ieee80211_hw *hw) +{ + struct stlc45xx *stlc = hw->priv; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + mutex_lock(&stlc->mutex); + + WARN_ON(stlc->fw_state != FW_STATE_READY); + + stlc45xx_power_off(stlc); + + /* FIXME: make sure that all work_structs have completed */ + + spin_lock_bh(&stlc->tx_lock); + stlc45xx_flush_queues(stlc); + spin_unlock_bh(&stlc->tx_lock); + + stlc->fw_state = FW_STATE_OFF; + + mutex_unlock(&stlc->mutex); +} + +static int stlc45xx_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + struct stlc45xx *stlc = hw->priv; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + switch (conf->type) { + case NL80211_IFTYPE_STATION: + break; + default: + return -EOPNOTSUPP; + } + + memcpy(stlc->mac_addr, conf->mac_addr, ETH_ALEN); + + return 0; +} + +static void stlc45xx_op_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_if_init_conf *conf) +{ + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); +} + +static int stlc45xx_op_config_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf) +{ + struct stlc45xx *stlc = hw->priv; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + mutex_lock(&stlc->mutex); + + memcpy(stlc->bssid, conf->bssid, ETH_ALEN); + stlc45xx_tx_setup(stlc); + + mutex_unlock(&stlc->mutex); + + return 0; +} + +static int stlc45xx_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct stlc45xx *stlc = hw->priv; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + mutex_lock(&stlc->mutex); + + stlc->channel = hw->conf.channel->hw_value; + stlc45xx_tx_scan(stlc); + stlc45xx_tx_setup(stlc); + stlc45xx_tx_edcf(stlc); + + if ((hw->conf.flags & IEEE80211_CONF_PS) != stlc->psm) { + stlc->psm = hw->conf.flags & IEEE80211_CONF_PS; + if (stlc->associated) { + stlc45xx_tx_psm(stlc, stlc->psm); + stlc45xx_tx_nullfunc(stlc, stlc->psm); + } + } + + mutex_unlock(&stlc->mutex); + + return 0; +} + +static void stlc45xx_op_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mc_list) +{ + *total_flags = 0; +} + +static void stlc45xx_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + struct stlc45xx *stlc = hw->priv; + + if (changed & BSS_CHANGED_ASSOC) { + stlc->associated = info->assoc; + if (info->assoc) + stlc->aid = info->aid; + else + stlc->aid = -1; + + if (stlc->psm) { + stlc45xx_tx_psm(stlc, stlc->psm); + stlc45xx_tx_nullfunc(stlc, stlc->psm); + } + } +} + + +/* can't be const, mac80211 writes to this */ +static struct ieee80211_rate stlc45xx_rates[] = { + { .bitrate = 10, .hw_value = 0, .hw_value_short = 0, }, + { .bitrate = 20, .hw_value = 1, .hw_value_short = 1, }, + { .bitrate = 55, .hw_value = 2, .hw_value_short = 2, }, + { .bitrate = 110, .hw_value = 3, .hw_value_short = 3, }, + { .bitrate = 60, .hw_value = 4, .hw_value_short = 4, }, + { .bitrate = 90, .hw_value = 5, .hw_value_short = 5, }, + { .bitrate = 120, .hw_value = 6, .hw_value_short = 6, }, + { .bitrate = 180, .hw_value = 7, .hw_value_short = 7, }, + { .bitrate = 240, .hw_value = 8, .hw_value_short = 8, }, + { .bitrate = 360, .hw_value = 9, .hw_value_short = 9, }, + { .bitrate = 480, .hw_value = 10, .hw_value_short = 10, }, + { .bitrate = 540, .hw_value = 11, .hw_value_short = 11, }, +}; + +/* can't be const, mac80211 writes to this */ +static struct ieee80211_channel stlc45xx_channels[] = { + { .hw_value = 1, .center_freq = 2412}, + { .hw_value = 2, .center_freq = 2417}, + { .hw_value = 3, .center_freq = 2422}, + { .hw_value = 4, .center_freq = 2427}, + { .hw_value = 5, .center_freq = 2432}, + { .hw_value = 6, .center_freq = 2437}, + { .hw_value = 7, .center_freq = 2442}, + { .hw_value = 8, .center_freq = 2447}, + { .hw_value = 9, .center_freq = 2452}, + { .hw_value = 10, .center_freq = 2457}, + { .hw_value = 11, .center_freq = 2462}, + { .hw_value = 12, .center_freq = 2467}, + { .hw_value = 13, .center_freq = 2472}, +}; + +/* can't be const, mac80211 writes to this */ +static struct ieee80211_supported_band stlc45xx_band_2ghz = { + .channels = stlc45xx_channels, + .n_channels = ARRAY_SIZE(stlc45xx_channels), + .bitrates = stlc45xx_rates, + .n_bitrates = ARRAY_SIZE(stlc45xx_rates), +}; + +static const struct ieee80211_ops stlc45xx_ops = { + .start = stlc45xx_op_start, + .stop = stlc45xx_op_stop, + .add_interface = stlc45xx_op_add_interface, + .remove_interface = stlc45xx_op_remove_interface, + .config = stlc45xx_op_config, + .config_interface = stlc45xx_op_config_interface, + .configure_filter = stlc45xx_op_configure_filter, + .tx = stlc45xx_op_tx, + .bss_info_changed = stlc45xx_op_bss_info_changed, +}; + +static int stlc45xx_register_mac80211(struct stlc45xx *stlc) +{ + /* FIXME: SET_IEEE80211_PERM_ADDR() requires default_mac_addr + to be non-const for some strange reason */ + static u8 default_mac_addr[ETH_ALEN] = { + 0x00, 0x02, 0xee, 0xc0, 0xff, 0xee + }; + int ret; + + SET_IEEE80211_PERM_ADDR(stlc->hw, default_mac_addr); + + ret = ieee80211_register_hw(stlc->hw); + if (ret) { + stlc45xx_error("unable to register mac80211 hw: %d", ret); + return ret; + } + + return 0; +} + +static void stlc45xx_device_release(struct device *dev) +{ + +} + +static struct platform_device stlc45xx_device = { + .name = "stlc45xx", + .id = -1, + + /* device model insists to have a release function */ + .dev = { + .release = stlc45xx_device_release, + }, +}; + +static int __devinit stlc45xx_probe(struct spi_device *spi) +{ + struct stlc45xx *stlc; + struct ieee80211_hw *hw; + int ret; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + /* mac80211 alloc */ + hw = ieee80211_alloc_hw(sizeof(*stlc), &stlc45xx_ops); + if (!hw) { + stlc45xx_error("could not alloc ieee80211_hw"); + ret = -ENOMEM; + goto out; + } + + /* mac80211 clears hw->priv */ + stlc = hw->priv; + + stlc->hw = hw; + dev_set_drvdata(&spi->dev, stlc); + stlc->spi = spi; + + spi->bits_per_word = 16; + spi->max_speed_hz = 24000000; + + ret = spi_setup(spi); + if (ret < 0) + stlc45xx_error("spi_setup failed"); + + ret = gpio_request(stlc45xx_gpio_power, "stlc45xx power"); + if (ret < 0) { + stlc45xx_error("power GPIO request failed: %d", ret); + return ret; + } + + ret = gpio_request(stlc45xx_gpio_irq, "stlc45xx irq"); + if (ret < 0) { + stlc45xx_error("irq GPIO request failed: %d", ret); + goto out; + } + + gpio_direction_output(stlc45xx_gpio_power, 0); + gpio_direction_input(stlc45xx_gpio_irq); + + ret = request_irq(gpio_to_irq(stlc45xx_gpio_irq), + stlc45xx_interrupt, IRQF_DISABLED, "stlc45xx", + stlc->spi); + if (ret < 0) + /* FIXME: handle the error */ + stlc45xx_error("request_irq() failed"); + + set_irq_type(gpio_to_irq(stlc45xx_gpio_irq), + IRQ_TYPE_EDGE_RISING); + + disable_irq(gpio_to_irq(stlc45xx_gpio_irq)); + + ret = platform_device_register(&stlc45xx_device); + if (ret) { + stlc45xx_error("Couldn't register wlan_omap device."); + return ret; + } + dev_set_drvdata(&stlc45xx_device.dev, stlc); + + INIT_WORK(&stlc->work, stlc45xx_work); + INIT_WORK(&stlc->work_reset, stlc45xx_work_reset); + INIT_DELAYED_WORK(&stlc->work_tx_timeout, stlc45xx_work_tx_timeout); + mutex_init(&stlc->mutex); + init_completion(&stlc->fw_comp); + spin_lock_init(&stlc->tx_lock); + INIT_LIST_HEAD(&stlc->txbuffer); + INIT_LIST_HEAD(&stlc->tx_pending); + INIT_LIST_HEAD(&stlc->tx_sent); + + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_NOISE_DBM; + /* four bytes for padding */ + hw->extra_tx_headroom = sizeof(struct s_lm_data_out) + 4; + + /* unit us */ + hw->channel_change_time = 1000; + + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &stlc45xx_band_2ghz; + + SET_IEEE80211_DEV(hw, &spi->dev); + + BUILD_BUG_ON(sizeof(default_cal_rssi) != RSSI_CAL_ARRAY_LEN); + BUILD_BUG_ON(sizeof(default_cal_channels) != CHANNEL_CAL_ARRAY_LEN); + + stlc->cal_rssi = kmemdup(default_cal_rssi, RSSI_CAL_ARRAY_LEN, + GFP_KERNEL); + stlc->cal_channels = kmemdup(default_cal_channels, + CHANNEL_CAL_ARRAY_LEN, + GFP_KERNEL); + + ret = device_create_file(&stlc45xx_device.dev, &dev_attr_cal_rssi); + if (ret < 0) { + stlc45xx_error("failed to create sysfs file cal_rssi"); + goto out; + } + + ret = device_create_file(&stlc45xx_device.dev, &dev_attr_cal_channels); + if (ret < 0) { + stlc45xx_error("failed to create sysfs file cal_channels"); + goto out; + } + + ret = device_create_file(&stlc45xx_device.dev, &dev_attr_tx_buf); + if (ret < 0) { + stlc45xx_error("failed to create sysfs file tx_buf"); + goto out; + } + + ret = stlc45xx_register_mac80211(stlc); + if (ret < 0) + goto out; + + stlc45xx_info("v" DRIVER_VERSION " loaded"); + + stlc45xx_info("config buffer 0x%x-0x%x", + FIRMWARE_CONFIG_START, FIRMWARE_CONFIG_END); + stlc45xx_info("tx 0x%x-0x%x, rx 0x%x-0x%x", + FIRMWARE_TXBUFFER_START, FIRMWARE_TXBUFFER_END, + FIRMWARE_RXBUFFER_START, FIRMWARE_RXBUFFER_END); + +out: + return ret; +} + +static int __devexit stlc45xx_remove(struct spi_device *spi) +{ + struct stlc45xx *stlc = dev_get_drvdata(&spi->dev); + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + platform_device_unregister(&stlc45xx_device); + + ieee80211_unregister_hw(stlc->hw); + + free_irq(gpio_to_irq(stlc45xx_gpio_irq), spi); + + gpio_free(stlc45xx_gpio_power); + gpio_free(stlc45xx_gpio_irq); + + /* FIXME: free cal_channels and cal_rssi? */ + + kfree(stlc->fw); + + mutex_destroy(&stlc->mutex); + + /* frees also stlc */ + ieee80211_free_hw(stlc->hw); + stlc = NULL; + + return 0; +} + + +static struct spi_driver stlc45xx_spi_driver = { + .driver = { + /* use cx3110x name because board-n800.c uses that for the + * SPI port */ + .name = "cx3110x", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = stlc45xx_probe, + .remove = __devexit_p(stlc45xx_remove), +}; + +static int __init stlc45xx_init(void) +{ + int ret; + + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + ret = spi_register_driver(&stlc45xx_spi_driver); + if (ret < 0) { + stlc45xx_error("failed to register SPI driver: %d", ret); + goto out; + } + +out: + return ret; +} + +static void __exit stlc45xx_exit(void) +{ + stlc45xx_debug(DEBUG_FUNC, "%s", __func__); + + spi_unregister_driver(&stlc45xx_spi_driver); + + stlc45xx_info("unloaded"); +} + +module_init(stlc45xx_init); +module_exit(stlc45xx_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kalle Valo "); diff --git a/drivers/staging/stlc45xx/stlc45xx.h b/drivers/staging/stlc45xx/stlc45xx.h new file mode 100644 index 000000000000..ac96bbbde79f --- /dev/null +++ b/drivers/staging/stlc45xx/stlc45xx.h @@ -0,0 +1,283 @@ +/* + * This file is part of stlc45xx + * + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: Kalle Valo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include + +#include "stlc45xx_lmac.h" + +#define DRIVER_NAME "stlc45xx" +#define DRIVER_VERSION "0.1.3" + +#define DRIVER_PREFIX DRIVER_NAME ": " + +enum { + DEBUG_NONE = 0, + DEBUG_FUNC = 1 << 0, + DEBUG_IRQ = 1 << 1, + DEBUG_BH = 1 << 2, + DEBUG_RX = 1 << 3, + DEBUG_RX_CONTENT = 1 << 5, + DEBUG_TX = 1 << 6, + DEBUG_TX_CONTENT = 1 << 8, + DEBUG_TXBUFFER = 1 << 9, + DEBUG_QUEUE = 1 << 10, + DEBUG_BOOT = 1 << 11, + DEBUG_PSM = 1 << 12, + DEBUG_ALL = ~0, +}; + +#define DEBUG_LEVEL DEBUG_NONE +/* #define DEBUG_LEVEL DEBUG_ALL */ +/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_RX | DEBUG_IRQ) */ +/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_MEMREGION | DEBUG_QUEUE) */ +/* #define DEBUG_LEVEL (DEBUG_MEMREGION | DEBUG_QUEUE) */ + +#define stlc45xx_error(fmt, arg...) \ + printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg) + +#define stlc45xx_warning(fmt, arg...) \ + printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg) + +#define stlc45xx_info(fmt, arg...) \ + printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg) + +#define stlc45xx_debug(level, fmt, arg...) \ + do { \ + if (level & DEBUG_LEVEL) \ + printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \ + } while (0) + +#define stlc45xx_dump(level, buf, len) \ + do { \ + if (level & DEBUG_LEVEL) \ + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ + 16, 1, buf, len, 1); \ + } while (0) + +#define MAC2STR(a) ((a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]) +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" + +/* Bit 15 is read/write bit; ON = READ, OFF = WRITE */ +#define ADDR_READ_BIT_15 0x8000 + +#define SPI_ADRS_ARM_INTERRUPTS 0x00 +#define SPI_ADRS_ARM_INT_EN 0x04 + +#define SPI_ADRS_HOST_INTERRUPTS 0x08 +#define SPI_ADRS_HOST_INT_EN 0x0c +#define SPI_ADRS_HOST_INT_ACK 0x10 + +#define SPI_ADRS_GEN_PURP_1 0x14 +#define SPI_ADRS_GEN_PURP_2 0x18 + +/* high word */ +#define SPI_ADRS_DEV_CTRL_STAT 0x26 + +#define SPI_ADRS_DMA_DATA 0x28 + +#define SPI_ADRS_DMA_WRITE_CTRL 0x2c +#define SPI_ADRS_DMA_WRITE_LEN 0x2e +#define SPI_ADRS_DMA_WRITE_BASE 0x30 + +#define SPI_ADRS_DMA_READ_CTRL 0x34 +#define SPI_ADRS_DMA_READ_LEN 0x36 +#define SPI_ADRS_DMA_READ_BASE 0x38 + +#define SPI_CTRL_STAT_HOST_OVERRIDE 0x8000 +#define SPI_CTRL_STAT_START_HALTED 0x4000 +#define SPI_CTRL_STAT_RAM_BOOT 0x2000 +#define SPI_CTRL_STAT_HOST_RESET 0x1000 +#define SPI_CTRL_STAT_HOST_CPU_EN 0x0800 + +#define SPI_DMA_WRITE_CTRL_ENABLE 0x0001 +#define SPI_DMA_READ_CTRL_ENABLE 0x0001 +#define HOST_ALLOWED (1 << 7) + +#define FIRMWARE_ADDRESS 0x20000 + +#define SPI_TIMEOUT 100 /* msec */ + +#define SPI_MAX_TX_PACKETS 32 + +#define SPI_MAX_PACKET_SIZE 32767 + +#define SPI_TARGET_INT_WAKEUP 0x00000001 +#define SPI_TARGET_INT_SLEEP 0x00000002 +#define SPI_TARGET_INT_RDDONE 0x00000004 + +#define SPI_TARGET_INT_CTS 0x00004000 +#define SPI_TARGET_INT_DR 0x00008000 + +#define SPI_HOST_INT_READY 0x00000001 +#define SPI_HOST_INT_WR_READY 0x00000002 +#define SPI_HOST_INT_SW_UPDATE 0x00000004 +#define SPI_HOST_INT_UPDATE 0x10000000 + +/* clear to send */ +#define SPI_HOST_INT_CTS 0x00004000 + +/* data ready */ +#define SPI_HOST_INT_DR 0x00008000 + +#define SPI_HOST_INTS_DEFAULT \ + (SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE) + +#define TARGET_BOOT_SLEEP 50 + +/* The firmware buffer is divided into three areas: + * + * o config area (for control commands) + * o tx buffer + * o rx buffer + */ +#define FIRMWARE_BUFFER_START 0x20200 +#define FIRMWARE_BUFFER_END 0x27c60 +#define FIRMWARE_BUFFER_LEN (FIRMWARE_BUFFER_END - FIRMWARE_BUFFER_START) +#define FIRMWARE_MTU 3240 +#define FIRMWARE_CONFIG_PAYLOAD_LEN 1024 +#define FIRMWARE_CONFIG_START FIRMWARE_BUFFER_START +#define FIRMWARE_CONFIG_LEN (sizeof(struct s_lm_control) + \ + FIRMWARE_CONFIG_PAYLOAD_LEN) +#define FIRMWARE_CONFIG_END (FIRMWARE_CONFIG_START + FIRMWARE_CONFIG_LEN - 1) +#define FIRMWARE_RXBUFFER_LEN (5 * FIRMWARE_MTU + 1024) +#define FIRMWARE_RXBUFFER_START (FIRMWARE_BUFFER_END - FIRMWARE_RXBUFFER_LEN) +#define FIRMWARE_RXBUFFER_END (FIRMWARE_RXBUFFER_START + \ + FIRMWARE_RXBUFFER_LEN - 1) +#define FIRMWARE_TXBUFFER_START (FIRMWARE_BUFFER_START + FIRMWARE_CONFIG_LEN) +#define FIRMWARE_TXBUFFER_LEN (FIRMWARE_BUFFER_LEN - FIRMWARE_CONFIG_LEN - \ + FIRMWARE_RXBUFFER_LEN) +#define FIRMWARE_TXBUFFER_END (FIRMWARE_TXBUFFER_START + \ + FIRMWARE_TXBUFFER_LEN - 1) + +#define FIRMWARE_TXBUFFER_HEADER 100 +#define FIRMWARE_TXBUFFER_TRAILER 4 + +/* FIXME: come up with a proper value */ +#define MAX_FRAME_LEN 2500 + +/* unit is ms */ +#define TX_FRAME_LIFETIME 2000 +#define TX_TIMEOUT 4000 + +#define SUPPORTED_CHANNELS 13 + +/* FIXME */ +/* #define CHANNEL_CAL_LEN offsetof(struct s_lmo_scan, bratemask) - \ */ +/* offsetof(struct s_lmo_scan, channel) */ +#define CHANNEL_CAL_LEN 292 +#define CHANNEL_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * CHANNEL_CAL_LEN) +/* FIXME */ +/* #define RSSI_CAL_LEN sizeof(struct s_lmo_scan) - \ */ +/* offsetof(struct s_lmo_scan, rssical) */ +#define RSSI_CAL_LEN 8 +#define RSSI_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * RSSI_CAL_LEN) + +struct s_dma_regs { + unsigned short cmd; + unsigned short len; + unsigned long addr; +}; + +struct stlc45xx_ie_tim { + u8 dtim_count; + u8 dtim_period; + u8 bmap_control; + u8 pvbmap[251]; +}; + +struct txbuffer { + /* can be removed when switched to skb queue */ + struct list_head tx_list; + + struct list_head buffer_list; + + int start; + int frame_start; + int end; + + struct sk_buff *skb; + u32 handle; + + bool status_needed; + + int header_len; + + /* unit jiffies */ + unsigned long lifetime; +}; + +enum fw_state { + FW_STATE_OFF, + FW_STATE_BOOTING, + FW_STATE_READY, + FW_STATE_RESET, + FW_STATE_RESETTING, +}; + +struct stlc45xx { + struct ieee80211_hw *hw; + struct spi_device *spi; + struct work_struct work; + struct work_struct work_reset; + struct delayed_work work_tx_timeout; + struct mutex mutex; + struct completion fw_comp; + + + u8 bssid[ETH_ALEN]; + u8 mac_addr[ETH_ALEN]; + int channel; + + u8 *cal_rssi; + u8 *cal_channels; + + enum fw_state fw_state; + + spinlock_t tx_lock; + + /* protected by tx_lock */ + struct list_head txbuffer; + + /* protected by tx_lock */ + struct list_head tx_pending; + + /* protected by tx_lock */ + int tx_queue_stopped; + + /* protected by mutex */ + struct list_head tx_sent; + + int tx_frames; + + u8 *fw; + int fw_len; + + bool psm; + bool associated; + int aid; + bool pspolling; +}; + + diff --git a/drivers/staging/stlc45xx/stlc45xx_lmac.h b/drivers/staging/stlc45xx/stlc45xx_lmac.h new file mode 100644 index 000000000000..af5db801347f --- /dev/null +++ b/drivers/staging/stlc45xx/stlc45xx_lmac.h @@ -0,0 +1,434 @@ +/************************************************************************ +* This is the LMAC API interface header file for STLC4560. * +* Copyright (C) 2007 Conexant Systems, Inc. * +* 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, see .* +*************************************************************************/ + +#ifndef __lmac_h__ +#define __lmac_h__ + +#define LM_TOP_VARIANT 0x0506 +#define LM_BOTTOM_VARIANT 0x0506 + +/* + * LMAC - UMAC interface definition: + */ + +#define LM_FLAG_CONTROL 0x8000 +#define LM_FLAG_ALIGN 0x4000 + +#define LM_CTRL_OPSET 0x0001 + +#define LM_OUT_PROMISC 0x0001 +#define LM_OUT_TIMESTAMP 0x0002 +#define LM_OUT_SEQNR 0x0004 +#define LM_OUT_BURST 0x0010 +#define LM_OUT_NOCANCEL 0x0020 +#define LM_OUT_CLEARTIM 0x0040 +#define LM_OUT_HITCHHIKE 0x0080 +#define LM_OUT_COMPRESS 0x0100 +#define LM_OUT_CONCAT 0x0200 +#define LM_OUT_PCS_ACCEPT 0x0400 +#define LM_OUT_WAITEOSP 0x0800 + + +#define LM_ALOFT_SP 0x10 +#define LM_ALOFT_CTS 0x20 +#define LM_ALOFT_RTS 0x40 +#define LM_ALOFT_MASK 0x1f +#define LM_ALOFT_RATE 0x0f + +#define LM_IN_FCS_GOOD 0x0001 +#define LM_IN_MATCH_MAC 0x0002 +#define LM_IN_MCBC 0x0004 +#define LM_IN_BEACON 0x0008 +#define LM_IN_MATCH_BSS 0x0010 +#define LM_IN_BCAST_BSS 0x0020 +#define LM_IN_DATA 0x0040 +#define LM_IN_TRUNCATED 0x0080 + +#define LM_IN_TRANSPARENT 0x0200 + +#define LM_QUEUE_BEACON 0 +#define LM_QUEUE_SCAN 1 +#define LM_QUEUE_MGT 2 +#define LM_QUEUE_MCBC 3 +#define LM_QUEUE_DATA 4 +#define LM_QUEUE_DATA0 4 +#define LM_QUEUE_DATA1 5 +#define LM_QUEUE_DATA2 6 +#define LM_QUEUE_DATA3 7 + +#define LM_SETUP_INFRA 0x0001 +#define LM_SETUP_IBSS 0x0002 +#define LM_SETUP_TRANSPARENT 0x0008 +#define LM_SETUP_PROMISCUOUS 0x0010 +#define LM_SETUP_HIBERNATE 0x0020 +#define LM_SETUP_NOACK 0x0040 +#define LM_SETUP_RX_DISABLED 0x0080 + +#define LM_ANTENNA_0 0 +#define LM_ANTENNA_1 1 +#define LM_ANTENNA_DIVERSITY 2 + +#define LM_TX_FAILED 0x0001 +#define LM_TX_PSM 0x0002 +#define LM_TX_PSM_CANCELLED 0x0004 + +#define LM_SCAN_EXIT 0x0001 +#define LM_SCAN_TRAP 0x0002 +#define LM_SCAN_ACTIVE 0x0004 +#define LM_SCAN_FILTER 0x0008 + +#define LM_PSM 0x0001 +#define LM_PSM_DTIM 0x0002 +#define LM_PSM_MCBC 0x0004 +#define LM_PSM_CHECKSUM 0x0008 +#define LM_PSM_SKIP_MORE_DATA 0x0010 +#define LM_PSM_BEACON_TIMEOUT 0x0020 +#define LM_PSM_HFOSLEEP 0x0040 +#define LM_PSM_AUTOSWITCH_SLEEP 0x0080 +#define LM_PSM_LPIT 0x0100 +#define LM_PSM_BF_UCAST_SKIP 0x0200 +#define LM_PSM_BF_MCAST_SKIP 0x0400 + +/* hfosleep */ +#define LM_PSM_SLEEP_OPTION_MASK (LM_PSM_AUTOSWITCH_SLEEP | LM_PSM_HFOSLEEP) +#define LM_PSM_SLEEP_OPTION_SHIFT 6 +/* hfosleepend */ +#define LM_PSM_BF_OPTION_MASK (LM_PSM_BF_MCAST_SKIP | LM_PSM_BF_UCAST_SKIP) +#define LM_PSM_BF_OPTION_SHIFT 9 + + +#define LM_PRIVACC_WEP 0x01 +#define LM_PRIVACC_TKIP 0x02 +#define LM_PRIVACC_MICHAEL 0x04 +#define LM_PRIVACC_CCX_KP 0x08 +#define LM_PRIVACC_CCX_MIC 0x10 +#define LM_PRIVACC_AES_CCMP 0x20 + +/* size of s_lm_descr in words */ +#define LM_DESCR_SIZE_WORDS 11 + +#ifndef __ASSEMBLER__ + +enum { + LM_MODE_CLIENT = 0, + LM_MODE_AP +}; + +struct s_lm_descr { + uint16_t modes; + uint16_t flags; + uint32_t buffer_start; + uint32_t buffer_end; + uint8_t header; + uint8_t trailer; + uint8_t tx_queues; + uint8_t tx_depth; + uint8_t privacy; + uint8_t rx_keycache; + uint8_t tim_size; + uint8_t pad1; + uint8_t rates[16]; + uint32_t link; + uint16_t mtu; +}; + + +struct s_lm_control { + uint16_t flags; + uint16_t length; + uint32_t handle; + uint16_t oid; + uint16_t pad; + /* uint8_t data[]; */ +}; + +enum { + LM_PRIV_NONE = 0, + LM_PRIV_WEP, + LM_PRIV_TKIP, + LM_PRIV_TKIPMICHAEL, + LM_PRIV_CCX_WEPMIC, + LM_PRIV_CCX_KPMIC, + LM_PRIV_CCX_KP, + LM_PRIV_AES_CCMP +}; + +enum { + LM_DECRYPT_NONE, + LM_DECRYPT_OK, + LM_DECRYPT_NOKEY, + LM_DECRYPT_NOMICHAEL, + LM_DECRYPT_NOCKIPMIC, + LM_DECRYPT_FAIL_WEP, + LM_DECRYPT_FAIL_TKIP, + LM_DECRYPT_FAIL_MICHAEL, + LM_DECRYPT_FAIL_CKIPKP, + LM_DECRYPT_FAIL_CKIPMIC, + LM_DECRYPT_FAIL_AESCCMP +}; + +struct s_lm_data_out { + uint16_t flags; + uint16_t length; + uint32_t handle; + uint16_t aid; + uint8_t rts_retries; + uint8_t retries; + uint8_t aloft[8]; + uint8_t aloft_ctrl; + uint8_t crypt_offset; + uint8_t keytype; + uint8_t keylen; + uint8_t key[16]; + uint8_t queue; + uint8_t backlog; + uint16_t durations[4]; + uint8_t antenna; + uint8_t cts; + int16_t power; + uint8_t pad[2]; + /*uint8_t data[];*/ +}; + +#define LM_RCPI_INVALID (0xff) + +struct s_lm_data_in { + uint16_t flags; + uint16_t length; + uint16_t frequency; + uint8_t antenna; + uint8_t rate; + uint8_t rcpi; + uint8_t sq; + uint8_t decrypt; + uint8_t rssi_raw; + uint32_t clock[2]; + /*uint8_t data[];*/ +}; + +union u_lm_data { + struct s_lm_data_out out; + struct s_lm_data_in in; +}; + +enum { + LM_OID_SETUP = 0, + LM_OID_SCAN = 1, + LM_OID_TRAP = 2, + LM_OID_EDCF = 3, + LM_OID_KEYCACHE = 4, + LM_OID_PSM = 6, + LM_OID_TXCANCEL = 7, + LM_OID_TX = 8, + LM_OID_BURST = 9, + LM_OID_STATS = 10, + LM_OID_LED = 13, + LM_OID_TIMER = 15, + LM_OID_NAV = 20, + LM_OID_PCS = 22, + LM_OID_BT_BALANCER = 28, + LM_OID_GROUP_ADDRESS_TABLE = 30, + LM_OID_ARPTABLE = 31, + LM_OID_BT_OPTIONS = 35 +}; + +enum { + LM_FRONTEND_UNKNOWN = 0, + LM_FRONTEND_DUETTE3, + LM_FRONTEND_DUETTE2, + LM_FRONTEND_FRISBEE, + LM_FRONTEND_CROSSBOW, + LM_FRONTEND_LONGBOW +}; + + +#define INVALID_LPF_BANDWIDTH 0xffff +#define INVALID_OSC_START_DELAY 0xffff + +struct s_lmo_setup { + uint16_t flags; + uint8_t macaddr[6]; + uint8_t bssid[6]; + uint8_t antenna; + uint8_t rx_align; + uint32_t rx_buffer; + uint16_t rx_mtu; + uint16_t frontend; + uint16_t timeout; + uint16_t truncate; + uint32_t bratemask; + uint8_t sbss_offset; + uint8_t mcast_window; + uint8_t rx_rssi_threshold; + uint8_t rx_ed_threshold; + uint32_t ref_clock; + uint16_t lpf_bandwidth; + uint16_t osc_start_delay; +}; + + +struct s_lmo_scan { + uint16_t flags; + uint16_t dwell; + uint8_t channel[292]; + uint32_t bratemask; + uint8_t aloft[8]; + uint8_t rssical[8]; +}; + + +enum { + LM_TRAP_SCAN = 0, + LM_TRAP_TIMER, + LM_TRAP_BEACON_TX, + LM_TRAP_FAA_RADIO_ON, + LM_TRAP_FAA_RADIO_OFF, + LM_TRAP_RADAR, + LM_TRAP_NO_BEACON, + LM_TRAP_TBTT, + LM_TRAP_SCO_ENTER, + LM_TRAP_SCO_EXIT +}; + +struct s_lmo_trap { + uint16_t event; + uint16_t frequency; +}; + +struct s_lmo_timer { + uint32_t interval; +}; + +struct s_lmo_nav { + uint32_t period; +}; + + +struct s_lmo_edcf_queue; + +struct s_lmo_edcf { + uint8_t flags; + uint8_t slottime; + uint8_t sifs; + uint8_t eofpad; + struct s_lmo_edcf_queue { + uint8_t aifs; + uint8_t pad0; + uint16_t cwmin; + uint16_t cwmax; + uint16_t txop; + } queues[8]; + uint8_t mapping[4]; + uint16_t maxburst; + uint16_t round_trip_delay; +}; + +struct s_lmo_keycache { + uint8_t entry; + uint8_t keyid; + uint8_t address[6]; + uint8_t pad[2]; + uint8_t keytype; + uint8_t keylen; + uint8_t key[24]; +}; + + +struct s_lm_interval; + +struct s_lmo_psm { + uint16_t flags; + uint16_t aid; + struct s_lm_interval { + uint16_t interval; + uint16_t periods; + } intervals[4]; + /* uint16_t pad; */ + uint8_t beacon_rcpi_skip_max; + uint8_t rcpi_delta_threshold; + uint8_t nr; + uint8_t exclude[1]; +}; + +#define MC_FILTER_ADDRESS_NUM 4 + +struct s_lmo_group_address_table { + uint16_t filter_enable; + uint16_t num_address; + uint8_t macaddr_list[MC_FILTER_ADDRESS_NUM][6]; +}; + +struct s_lmo_txcancel { + uint32_t address[1]; +}; + + +struct s_lmo_tx { + uint8_t flags; + uint8_t retries; + uint8_t rcpi; + uint8_t sq; + uint16_t seqctrl; + uint8_t antenna; + uint8_t pad; +}; + +struct s_lmo_burst { + uint8_t flags; + uint8_t queue; + uint8_t backlog; + uint8_t pad; + uint16_t durations[32]; +}; + +struct s_lmo_stats { + uint32_t valid; + uint32_t fcs; + uint32_t abort; + uint32_t phyabort; + uint32_t rts_success; + uint32_t rts_fail; + uint32_t timestamp; + uint32_t time_tx; + uint32_t noisefloor; + uint32_t sample_noise[8]; + uint32_t sample_cca; + uint32_t sample_tx; +}; + + +struct s_lmo_led { + uint16_t flags; + uint16_t mask[2]; + uint16_t delay/*[2]*/; +}; + + +struct s_lmo_bt_balancer { + uint16_t prio_thresh; + uint16_t acl_thresh; +}; + + +struct s_lmo_arp_table { + uint16_t filter_enable; + uint32_t ipaddr; +}; + +#endif /* __ASSEMBLER__ */ + +#endif /* __lmac_h__ */ diff --git a/drivers/staging/sxg/Kconfig b/drivers/staging/sxg/Kconfig index 6e6cf0b9ef99..c5cbdafee4d3 100644 --- a/drivers/staging/sxg/Kconfig +++ b/drivers/staging/sxg/Kconfig @@ -8,4 +8,4 @@ config SXG 10Gbe network cards. To compile this driver as a module, choose - M here: the module will be called sxg. + M here: the module will be called sxg_nic. diff --git a/drivers/staging/sxg/Makefile b/drivers/staging/sxg/Makefile index ec48faa7b3e3..8e053222c2ae 100644 --- a/drivers/staging/sxg/Makefile +++ b/drivers/staging/sxg/Makefile @@ -1 +1,3 @@ -obj-$(CONFIG_SXG) += sxg.o +obj-$(CONFIG_SXG) += sxg_nic.o + +sxg_nic-y := sxg.o sxg_ethtool.o diff --git a/drivers/staging/sxg/saharadbgdownload.h b/drivers/staging/sxg/saharadbgdownload.h deleted file mode 100644 index d8865ba05047..000000000000 --- a/drivers/staging/sxg/saharadbgdownload.h +++ /dev/null @@ -1,4854 +0,0 @@ -#define SAHARA_UCODE_VERS_STRING "$Revision: 1.1 $" -#define SAHARA_UCODE_VERS_DATE "$Date: 2008/06/27 12:58:27 $" -#define SAHARA_UCODE_HOSTIF_ID 3 - -static u32 SNumSections = 0x2; -static u32 SSectionSize[] = -{ - 0x0000e274, 0x0000000c, -}; - -static u32 SSectionStart[] = -{ - 0x00000000, 0x00001fff, -}; - -static unsigned char SaharaUCode[2][57972] = -{ -{ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0x4d, 0x29, 0x3a, - 0x00, 0x00, 0xb2, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x40, 0x2b, 0x92, - 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x98, 0x1e, 0x80, 0xe9, 0x9a, - 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x0f, 0x80, 0x28, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x40, 0x00, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x80, 0x01, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x02, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x40, 0x02, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x80, 0x02, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x03, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x40, 0x03, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0x80, 0x03, 0x92, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0f, 0xc0, 0x03, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x5f, 0x3f, 0x00, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x42, 0xff, 0xfc, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x80, 0xfd, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x8a, 0x11, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0x8d, 0xfd, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x80, 0xfd, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xc0, 0x01, 0x32, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x84, 0x82, 0x4d, 0x28, 0x1a, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x60, 0x5f, 0x0a, 0xf6, 0x94, - 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0e, 0x80, 0x18, 0x92, - 0x00, 0x00, 0xd2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x20, 0x92, - 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x21, 0x92, - 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x21, 0x92, - 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x85, 0x21, 0x90, - 0x00, 0x00, 0x4b, 0x03, 0x00, 0x00, 0x00, 0xec, 0x02, 0xc0, 0x22, 0x92, - 0x00, 0x00, 0x43, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x40, 0x18, 0x9d, - 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x8b, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x21, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe8, 0x02, 0x00, 0x90, 0x72, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xb2, 0x00, 0xe9, 0xb6, - 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0x7c, 0x1e, 0xc0, 0xe7, 0x9a, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x13, 0x40, 0x01, 0x39, - 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0x08, 0xb8, 0x01, 0x00, 0x94, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb3, 0x40, 0x01, 0x39, - 0x00, 0x00, 0xb0, 0x03, 0xb2, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x17, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x69, 0x05, 0x00, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x0a, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0xb2, - 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x18, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x2b, 0x32, - 0x00, 0x00, 0x57, 0x00, 0x80, 0x01, 0x00, 0x80, 0x12, 0x81, 0xfc, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x2b, 0xbc, - 0x02, 0x00, 0x57, 0x00, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9, - 0x00, 0x00, 0x5a, 0x00, 0x04, 0x01, 0x00, 0x80, 0x02, 0xc0, 0xb0, 0xbc, - 0x00, 0x00, 0x60, 0x00, 0xa0, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x5c, 0x00, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x4a, 0xd0, 0xb6, - 0x00, 0x00, 0x60, 0x00, 0xa0, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x34, - 0x00, 0x00, 0xfa, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xd2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x54, 0x00, 0x03, 0x01, 0x00, 0xb0, 0x02, 0x40, 0x18, 0xbd, - 0x08, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xa3, 0x40, 0x01, 0x99, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x16, 0x32, - 0x00, 0x00, 0x67, 0x00, 0x03, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x80, 0xbd, - 0x00, 0x00, 0x76, 0x00, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0x39, - 0x76, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x6b, 0x00, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x22, 0xb2, - 0x00, 0x00, 0x65, 0x00, 0x04, 0x01, 0x00, 0x80, 0x82, 0x85, 0x80, 0xbc, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39, - 0x63, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x68, 0x8b, 0x80, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xb8, 0xff, 0x85, 0x30, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x21, 0xff, 0x38, - 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x4d, 0x80, 0x3a, - 0x2c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x0d, 0x80, 0x3a, - 0x00, 0xc4, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x54, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x12, 0x80, 0x2d, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x48, 0x41, 0x80, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x86, 0x98, 0x67, 0xc0, 0x82, 0x3a, - 0x00, 0x00, 0x63, 0x00, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x62, 0x8b, 0x80, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x12, 0x80, 0x2d, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x08, 0x80, 0x70, 0x32, - 0x00, 0x00, 0x7c, 0x00, 0x90, 0x99, 0x86, 0x2c, 0x28, 0xde, 0x82, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x18, 0xc0, 0x82, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x08, 0xc5, 0x82, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xc5, 0x82, 0xbc, - 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x08, 0x68, 0x8b, 0x80, 0x94, - 0x08, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x40, 0x01, 0x99, - 0x08, 0x00, 0x38, 0x03, 0x0c, 0x00, 0x00, 0xf8, 0x53, 0x40, 0x01, 0xb9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x05, 0x80, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x3d, 0x32, - 0x00, 0x00, 0x7e, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0x00, 0x80, 0xd7, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x62, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0x3a, 0x80, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0x3a, 0x80, 0xbc, - 0x00, 0x90, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x0d, 0x80, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32, - 0x02, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x0d, 0x80, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x54, 0x02, 0xa4, 0x38, 0xb2, - 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00, 0x2c, 0x08, 0x00, 0x37, 0x32, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x08, 0x80, 0x72, 0x32, - 0x00, 0x00, 0x96, 0x00, 0x9f, 0x00, 0x00, 0x5c, 0x08, 0x00, 0x72, 0xb2, - 0x87, 0x00, 0x95, 0x00, 0x80, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x85, 0xb0, - 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd8, 0xc1, 0x82, 0x94, - 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x88, 0xc1, 0x82, 0x94, - 0x00, 0x00, 0x9e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x52, 0x7d, 0x80, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x05, 0x80, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32, - 0x00, 0x00, 0xa4, 0x03, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39, - 0x9a, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x0f, 0x97, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x85, 0xb0, - 0x10, 0x00, 0xa5, 0x00, 0x87, 0x00, 0x00, 0x78, 0x79, 0x21, 0x16, 0xb8, - 0x01, 0x00, 0xa5, 0x00, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc, - 0x87, 0x00, 0xaf, 0x00, 0x87, 0x00, 0x00, 0x78, 0x89, 0xcd, 0x85, 0xb0, - 0x00, 0x00, 0xa4, 0x00, 0x04, 0x01, 0x00, 0x80, 0x12, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd8, 0xc1, 0x82, 0x94, - 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x88, 0xc1, 0x82, 0x94, - 0x00, 0x00, 0xaf, 0x00, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc0, 0x85, 0xb6, - 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x98, 0xc1, 0x82, 0x94, - 0x00, 0x00, 0xad, 0x00, 0x80, 0x01, 0x00, 0x80, 0xd2, 0xc1, 0x82, 0xb6, - 0x00, 0x00, 0xaf, 0x00, 0x80, 0x01, 0x00, 0x80, 0x72, 0x80, 0xfc, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xa8, 0x42, 0x3d, 0x72, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x18, 0x99, 0xb1, 0xf2, 0xc0, 0x7c, 0x30, - 0x00, 0x00, 0xd6, 0x00, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0xc1, 0x82, 0xb6, - 0x00, 0x00, 0xa9, 0x00, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0xfc, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32, - 0x80, 0x00, 0x80, 0x20, 0x00, 0x00, 0x00, 0x80, 0xc2, 0xcd, 0x85, 0x30, - 0x00, 0x00, 0xc6, 0x00, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0xcd, 0x85, 0x30, - 0x80, 0x00, 0xc6, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc, - 0xa0, 0x00, 0xc6, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc, - 0x00, 0x00, 0xbd, 0x00, 0x80, 0x01, 0x00, 0x80, 0x62, 0x80, 0xfc, 0xb6, - 0x87, 0x00, 0xbd, 0x00, 0x87, 0x00, 0x00, 0x78, 0x89, 0xcd, 0x85, 0xb0, - 0x00, 0x00, 0xb9, 0x00, 0x04, 0x00, 0x00, 0x80, 0x12, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0xbd, 0x00, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0xbd, 0x00, 0x80, 0x01, 0x00, 0x80, 0x72, 0xc1, 0x85, 0xb6, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x61, 0x16, 0x38, - 0x00, 0x00, 0xc4, 0x00, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xb8, 0xc1, 0x82, 0x94, - 0x00, 0x00, 0xc4, 0x00, 0x80, 0x01, 0x00, 0x80, 0x52, 0x80, 0xfc, 0xb6, - 0x00, 0x00, 0xc4, 0x00, 0x80, 0x00, 0x00, 0x80, 0x72, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0xc4, 0x00, 0x80, 0x01, 0x00, 0x80, 0x02, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0xc4, 0x00, 0x80, 0x01, 0x00, 0x80, 0xd2, 0xc1, 0x85, 0xb6, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0xe1, 0x16, 0x38, - 0x00, 0x00, 0xc4, 0x00, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xc8, 0xc1, 0x82, 0x94, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x04, 0x32, - 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xa8, 0xc1, 0x82, 0x94, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x21, 0x17, 0x38, - 0x00, 0x00, 0xd6, 0x00, 0x04, 0x00, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0xd6, 0x00, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x97, 0xbc, - 0x1f, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x89, 0x8d, 0x72, 0x30, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xa9, 0xdc, 0x17, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x90, 0x37, - 0x00, 0x00, 0xd6, 0x00, 0x80, 0x00, 0x86, 0x80, 0x22, 0x24, 0x7c, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x05, 0x80, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x05, 0x80, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32, - 0x00, 0x00, 0xa4, 0x03, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39, - 0xd2, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0x00, 0x80, 0xd7, - 0x00, 0x00, 0xdd, 0x00, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2, - 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2, - 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32, - 0x00, 0x00, 0xe4, 0x00, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39, - 0xe0, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0xc0, 0xf4, 0x00, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x02, 0x00, 0x86, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x05, 0x80, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0, - 0x00, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x68, 0x02, 0x05, 0x80, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x78, 0x09, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x29, 0xc1, 0x72, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x07, 0x80, 0x97, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x17, 0x20, 0x90, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0xc0, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32, - 0x00, 0x00, 0xff, 0x00, 0x80, 0x01, 0x00, 0x80, 0xa2, 0xc1, 0x82, 0xb6, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x57, 0x00, 0x80, 0x97, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0xa0, 0x04, 0x39, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x05, 0x80, 0xb0, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x05, 0x80, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0x08, 0xe8, 0x81, 0x80, 0x34, - 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x45, 0x90, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x12, 0x00, 0x28, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x11, 0x01, 0xf0, 0x01, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x59, 0xc0, 0x6e, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x78, 0x19, 0xc0, 0x6e, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x4e, 0x04, 0x01, 0xec, 0x06, 0xbd, 0x97, 0x30, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf4, 0x1e, 0x40, 0xef, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x09, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x36, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0xc0, 0x29, 0x37, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x17, 0x3d, 0x90, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0xf4, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x83, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x72, 0x00, 0x2b, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x3d, 0x32, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0xa4, 0x01, 0x80, 0x38, 0x00, 0x80, 0x22, 0xc0, 0x72, 0xb6, - 0x00, 0x00, 0x27, 0x01, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2, - 0x00, 0x00, 0x2c, 0x01, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x02, 0x80, 0x2c, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0xff, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x72, 0x00, 0x85, 0x30, - 0x00, 0x00, 0x89, 0x01, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39, - 0x28, 0x01, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xcd, 0x85, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x24, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x72, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x72, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x28, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x80, 0x52, 0xbd, 0x82, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x30, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x80, 0x82, 0x32, - 0x00, 0x00, 0x3d, 0x01, 0x06, 0x00, 0x00, 0x80, 0x62, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x3c, 0x00, 0x14, 0x28, 0x80, 0x72, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x32, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0x4a, 0x09, 0x39, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x00, 0x82, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x19, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32, - 0x00, 0x00, 0x64, 0x01, 0x04, 0x38, 0x00, 0x78, 0xd9, 0xc5, 0x72, 0xb0, - 0x00, 0x00, 0x41, 0x01, 0x80, 0x01, 0x00, 0x80, 0x02, 0x80, 0x97, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0x43, 0x01, 0x80, 0x01, 0x00, 0x80, 0x12, 0x80, 0x97, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x92, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x3c, 0xb8, 0x1c, 0x17, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x28, 0xc0, 0x83, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x2c, 0x08, 0xc0, 0x72, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xb8, 0xe0, 0x83, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0xcb, 0x29, 0x00, 0x20, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x63, 0x01, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x81, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x78, 0xa0, 0x81, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xd8, 0xe0, 0x81, 0x3c, - 0x00, 0x00, 0x51, 0x01, 0x06, 0x3a, 0x00, 0x80, 0xb2, 0x5c, 0x83, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x89, 0xc1, 0x72, 0x37, - 0x07, 0x00, 0x50, 0x01, 0x2b, 0x01, 0x00, 0x04, 0x79, 0x0a, 0x04, 0xb9, - 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x04, 0x19, 0x41, 0x90, 0x34, - 0x00, 0x00, 0x54, 0x01, 0x00, 0x3a, 0x00, 0x2c, 0x07, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x2c, 0xd7, 0xe0, 0x72, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x64, 0x83, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0x73, 0x01, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0x3a, - 0x00, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2, - 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a, - 0x00, 0x00, 0xd7, 0x10, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0xf4, - 0x00, 0x00, 0x61, 0x01, 0x04, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0xbc, - 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0x9a, - 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2, - 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0xcb, 0x19, 0x00, 0x20, 0x07, 0x00, 0x00, 0x32, - 0x07, 0x00, 0x66, 0x01, 0x2b, 0x01, 0x00, 0x04, 0x79, 0x0a, 0x02, 0xb9, - 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x04, 0x19, 0x41, 0x90, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0xa7, 0xa0, 0x81, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0x73, 0x01, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x60, 0x83, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0x3a, - 0x00, 0x00, 0x70, 0x01, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2, - 0x00, 0x00, 0x71, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a, - 0x00, 0x00, 0xd7, 0x10, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0xf4, - 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2, - 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x09, 0x80, 0x73, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x08, 0x89, 0x80, 0x73, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x86, 0x32, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x8c, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x7f, 0x01, 0x29, 0x08, 0x00, 0x80, 0x07, 0xc0, 0x85, 0xb2, - 0x00, 0x00, 0x82, 0x01, 0x28, 0x10, 0x00, 0x8c, 0x07, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x83, 0x01, 0x00, 0x12, 0x00, 0x84, 0x07, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x8c, 0xf7, 0xe0, 0x82, 0x3a, - 0x00, 0x00, 0x82, 0x01, 0x28, 0x18, 0x00, 0x80, 0x07, 0x40, 0x90, 0xb2, - 0x00, 0x00, 0x83, 0x01, 0x00, 0x12, 0x00, 0x84, 0x07, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x84, 0x27, 0xe4, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x72, 0x00, 0x85, 0x30, - 0x00, 0x00, 0x87, 0x01, 0x04, 0x00, 0x00, 0xdc, 0x43, 0x60, 0x3d, 0xb3, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39, - 0x83, 0x01, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x52, 0x81, 0x2c, 0xb4, - 0x00, 0x00, 0x89, 0x01, 0xf2, 0x01, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0x8a, 0x01, 0xf0, 0x01, 0x00, 0x08, 0x38, 0x81, 0x80, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf4, 0x1e, 0x40, 0xef, 0x3c, - 0x00, 0x00, 0x93, 0x01, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x3b, 0x32, - 0x00, 0x00, 0x8e, 0x01, 0xb9, 0x00, 0x00, 0x78, 0xc9, 0x3b, 0x3a, 0xbc, - 0x00, 0x00, 0x92, 0x01, 0x02, 0x00, 0x00, 0x80, 0x82, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xa4, 0x03, 0xe2, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0xf0, 0x0e, 0x00, 0x3a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xba, 0x83, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xbd, 0x97, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0xf4, 0xbd, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x97, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0e, 0x80, 0x83, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x22, 0x7a, 0xe8, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xe8, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xc0, 0x29, 0x37, - 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x0d, 0x90, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0xe8, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0xe8, 0x32, - 0x00, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x08, 0x80, 0x72, 0x32, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x54, 0xa8, 0x5c, 0x16, 0x38, - 0x0b, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x2c, 0xa8, 0xdc, 0x16, 0x38, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x88, 0x4d, 0x85, 0x3a, - 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x10, 0x00, 0xe2, 0x10, 0x00, 0x38, 0x00, 0x14, 0xa9, 0x9c, 0x87, 0xd9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x24, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x72, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x30, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x3c, 0x00, 0x14, 0x18, 0x80, 0x72, 0xbc, - 0x00, 0x00, 0xbb, 0x01, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x32, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0x4a, 0x09, 0x39, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x00, 0x82, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x19, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x78, 0xc0, 0x29, 0x37, - 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x88, 0x4d, 0x86, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x77, 0xa0, 0x81, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x40, 0x86, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0xd6, 0x01, 0x04, 0x00, 0x00, 0x1c, 0xd8, 0xe0, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xd8, 0x60, 0x86, 0x3a, - 0x00, 0x00, 0xca, 0x01, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0x02, 0xc0, 0x38, 0xb2, - 0x00, 0x00, 0xd2, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xd0, 0x01, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xcb, 0x01, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32, - 0x00, 0x00, 0xd4, 0x01, 0x04, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0xbc, - 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0x9a, - 0x00, 0x00, 0x32, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2, - 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xdc, 0x01, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xd7, 0x01, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0xe8, 0x01, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x84, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x40, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x22, 0x40, 0x85, 0x3a, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x40, 0x88, 0xcd, 0x74, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x28, 0x00, 0x84, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32, - 0x14, 0x00, 0xe8, 0x01, 0x04, 0x00, 0x00, 0x1c, 0x88, 0x0d, 0x84, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x61, 0x85, 0x3a, - 0x80, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xd8, 0x60, 0x86, 0x3a, - 0x00, 0x00, 0xd2, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x92, - 0x00, 0x00, 0xea, 0x01, 0x04, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0xbc, - 0x00, 0x00, 0xec, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0x9a, - 0x00, 0x00, 0x32, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x40, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x22, 0xc0, 0x82, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xb8, 0x60, 0x85, 0x3c, - 0x04, 0x00, 0xf2, 0x01, 0x81, 0x00, 0x00, 0x60, 0x88, 0xcd, 0x74, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x28, 0xf8, 0xa0, 0x75, 0x3c, - 0x00, 0x00, 0xf3, 0x01, 0x00, 0x08, 0x00, 0x74, 0x08, 0x80, 0x75, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0xf8, 0xa0, 0x75, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x08, 0xa1, 0x82, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xf2, 0x60, 0x2a, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x08, 0x00, 0x75, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x7c, 0x08, 0x80, 0x75, 0x32, - 0x09, 0x00, 0xf9, 0x01, 0x04, 0x1a, 0x00, 0x70, 0x88, 0xcd, 0x74, 0xb0, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x4c, 0x87, 0xcd, 0x74, 0x31, - 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x88, 0x4d, 0x86, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x28, 0x40, 0x86, 0x3a, - 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x82, 0xd2, - 0x00, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2, - 0x00, 0x00, 0x01, 0x02, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x02, 0x80, 0x2c, 0xb2, - 0x00, 0x00, 0x27, 0x01, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x40, 0x00, 0x32, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xcd, 0x85, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xe8, 0xa1, 0x82, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x22, 0xc0, 0x82, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x08, 0xe1, 0x81, 0x3a, - 0x00, 0x00, 0x0b, 0x02, 0x04, 0x01, 0x00, 0x80, 0x42, 0x00, 0x86, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x58, 0x07, 0x40, 0x87, 0x32, - 0x00, 0x00, 0x0a, 0x02, 0x8f, 0x01, 0x00, 0x74, 0x18, 0x40, 0x87, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x0d, 0x02, 0x00, 0x04, 0x00, 0x58, 0xf7, 0xa0, 0x86, 0x9a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0xa0, 0x86, 0x3a, - 0x28, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x58, 0x87, 0x8d, 0x97, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x22, 0x40, 0x85, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x50, 0x07, 0x80, 0x84, 0x32, - 0x00, 0x00, 0x11, 0x02, 0x04, 0x01, 0x00, 0x80, 0x72, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x4c, 0xc7, 0xe1, 0x74, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x78, 0xa0, 0x84, 0x3a, - 0x00, 0x00, 0x14, 0x02, 0x90, 0x01, 0x00, 0x78, 0xf9, 0xa1, 0x86, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0x80, 0x97, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x58, 0x07, 0x80, 0x97, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x58, 0xa1, 0x86, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x60, 0x85, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x86, 0x32, - 0x00, 0x00, 0x1a, 0x02, 0x12, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x38, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x84, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x57, 0x21, 0x80, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x57, 0x61, 0x86, 0x3a, - 0x00, 0x00, 0x1f, 0x02, 0x12, 0x00, 0x00, 0x4c, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x80, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0xc0, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xcb, 0x19, 0x00, 0x20, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x80, 0x3a, - 0x07, 0x00, 0x27, 0x02, 0x2b, 0x01, 0x00, 0x04, 0x79, 0x0a, 0x02, 0xb9, - 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x04, 0x19, 0x41, 0x90, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x77, 0xa0, 0x81, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0x3c, - 0x00, 0x00, 0x41, 0x02, 0x04, 0x00, 0x00, 0x1c, 0xd8, 0xe0, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x60, 0x83, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0x3a, - 0x00, 0x00, 0x32, 0x02, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2, - 0x00, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x3d, 0x02, 0x06, 0x01, 0x00, 0x80, 0x22, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x3a, 0x02, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x34, 0x02, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x35, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x34, 0x02, 0x67, 0x00, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc, - 0x00, 0x00, 0x35, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0xc0, 0x00, 0x32, - 0x00, 0x00, 0x32, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2, - 0x00, 0x00, 0x25, 0x02, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xf9, 0x41, 0x90, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x48, 0x02, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x43, 0x02, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x44, 0x02, 0x00, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0x92, - 0x00, 0x00, 0x4b, 0x02, 0x04, 0x00, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc, - 0x00, 0x00, 0x43, 0x02, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x44, 0x02, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc, - 0x00, 0x00, 0x4f, 0x02, 0x04, 0x01, 0x00, 0x80, 0x42, 0x00, 0x86, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x89, 0x80, 0x71, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x80, 0x71, 0x32, - 0x00, 0x00, 0x53, 0x02, 0x90, 0x19, 0x00, 0x04, 0xe9, 0x5c, 0x90, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x19, 0x40, 0x90, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x80, 0x86, 0x32, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x8c, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x07, 0xc0, 0x85, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x8c, 0x07, 0x40, 0x85, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x80, 0x07, 0x45, 0x90, 0x30, - 0x00, 0x00, 0x5a, 0x02, 0x04, 0x01, 0x00, 0x80, 0x42, 0x00, 0x86, 0xbc, - 0x00, 0x00, 0x5b, 0x02, 0x00, 0x12, 0x00, 0x84, 0x27, 0xe4, 0x82, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x84, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x5f, 0x02, 0x27, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2, - 0x00, 0x00, 0x5f, 0x02, 0x04, 0x00, 0x00, 0x80, 0x42, 0x60, 0x3d, 0xb3, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39, - 0x5b, 0x02, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x52, 0x81, 0x2c, 0xb4, - 0x00, 0x00, 0x64, 0x02, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x82, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x03, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x67, 0x02, 0x04, 0x01, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0xbc, - 0x00, 0x00, 0x32, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x08, 0x80, 0x2d, 0xf2, - 0x00, 0x00, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x92, - 0x00, 0x00, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0x9a, - 0x08, 0x00, 0x00, 0x00, 0xc6, 0x01, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x81, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x45, 0x81, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xa4, 0x03, 0x80, 0x01, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6, - 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x72, 0x02, 0x04, 0x06, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x06, 0x01, 0xec, 0x56, 0xe0, 0x6e, 0x9a, - 0x00, 0x00, 0x00, 0x00, 0xc4, 0x07, 0x01, 0xec, 0x56, 0xe0, 0x6e, 0x3a, - 0x08, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x03, 0xb8, 0x00, 0x00, 0x09, 0xc0, 0x6e, 0xbd, - 0x77, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0x0d, 0x90, 0x3a, - 0x2e, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x2b, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x37, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x38, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6, - 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x86, 0x02, 0x04, 0x00, 0x00, 0x80, 0x52, 0x40, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x40, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x05, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x34, - 0x08, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x04, 0x01, 0x14, 0x59, 0xc0, 0x6e, 0xd7, - 0x02, 0x00, 0x8f, 0x02, 0x04, 0xb8, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc, - 0x08, 0x00, 0x8a, 0x11, 0x04, 0xb9, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0xec, 0x06, 0x40, 0x00, 0x32, - 0x00, 0x00, 0x91, 0x02, 0xb5, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x80, 0xa0, 0x36, 0x0b, 0x6a, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x01, 0xe8, 0x06, 0xc0, 0x2c, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0x85, 0x2f, 0x30, - 0x00, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb0, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x81, 0xd2, - 0x00, 0x00, 0xa1, 0x02, 0x80, 0x00, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6, - 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0xb8, 0x00, 0x14, 0x09, 0xc0, 0x6e, 0xd2, - 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0xa4, 0x02, 0x04, 0x02, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x02, 0x01, 0xec, 0x56, 0xe0, 0x6e, 0x9a, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x01, 0xec, 0x56, 0xe0, 0x6e, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2f, 0xb6, - 0x00, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x20, 0x00, 0x8a, 0x11, 0x04, 0x39, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc, - 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x30, 0x00, 0x14, 0x09, 0x00, 0x6e, 0xd2, - 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x20, 0x01, 0x14, 0x09, 0x00, 0x6e, 0xd2, - 0x1b, 0x00, 0xaf, 0x02, 0x38, 0x01, 0x00, 0x10, 0x09, 0x00, 0x36, 0xb2, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x30, 0x01, 0x14, 0x09, 0x00, 0x6e, 0xd2, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x79, 0x0b, 0x14, 0x38, - 0x10, 0x00, 0xe2, 0x10, 0x00, 0x50, 0x01, 0x14, 0xa9, 0x5b, 0x91, 0xd9, - 0x00, 0x00, 0xbe, 0x02, 0x38, 0x28, 0x00, 0x18, 0x09, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0xb6, 0x02, 0x04, 0x21, 0x01, 0x08, 0x69, 0x24, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x03, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xba, 0x02, 0x02, 0x30, 0x00, 0x80, 0x82, 0x9b, 0x90, 0xbc, - 0x00, 0x00, 0xb9, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x04, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x05, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x30, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0xbd, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x0a, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x0b, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xc1, 0x02, 0x04, 0x21, 0x01, 0x08, 0x69, 0x24, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x03, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xc3, 0x02, 0x02, 0x30, 0x00, 0x80, 0x82, 0x9b, 0x90, 0xbc, - 0x04, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xc5, 0x02, 0x9f, 0x31, 0x01, 0x0c, 0x69, 0x24, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xc9, 0x02, 0x04, 0x31, 0x00, 0x80, 0x82, 0x9b, 0x90, 0xbc, - 0x00, 0x00, 0xc8, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x20, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x21, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xcd, 0x02, 0x04, 0x00, 0x00, 0x80, 0x32, 0xa4, 0x90, 0xbc, - 0x00, 0x00, 0xcc, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x22, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x23, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xcf, 0x02, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x20, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x21, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x08, 0x00, 0x8a, 0x11, 0x0c, 0x00, 0x00, 0xf8, 0x63, 0x40, 0x01, 0xb9, - 0x10, 0x00, 0xd4, 0x02, 0xc5, 0x01, 0x00, 0xcc, 0x02, 0x20, 0x15, 0x98, - 0x08, 0x00, 0x38, 0x03, 0x0c, 0x00, 0x00, 0xf8, 0x43, 0x40, 0x01, 0xb9, - 0x10, 0x00, 0x00, 0x00, 0xc5, 0x01, 0x00, 0xcc, 0x02, 0x20, 0x15, 0x38, - 0x00, 0x00, 0x7e, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0x00, 0x80, 0xd7, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x08, 0x05, 0x80, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xfa, 0x85, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xfa, 0x85, 0xbc, - 0x00, 0x00, 0xdf, 0x02, 0x36, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x0e, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0xa9, 0xdb, 0x85, 0x39, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x54, 0x02, 0xa4, 0x38, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x8c, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x94, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x98, 0x28, 0x80, 0x6e, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x38, 0x22, 0x14, 0x37, - 0x00, 0x00, 0xeb, 0x02, 0x04, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x14, 0x08, 0x80, 0x6e, 0x32, - 0x05, 0x00, 0xee, 0x02, 0x00, 0x30, 0x02, 0x00, 0x78, 0xe1, 0x6e, 0x99, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x78, 0x09, 0xc0, 0x6e, 0x32, - 0x05, 0x00, 0x00, 0x00, 0x68, 0x08, 0x00, 0x00, 0x77, 0xa1, 0x97, 0x39, - 0x00, 0x00, 0xf0, 0x02, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x14, 0x10, 0xf4, 0x02, 0x04, 0x00, 0x00, 0x80, 0xa2, 0x0d, 0x72, 0xb0, - 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0x02, 0xf2, - 0x0d, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x09, 0x00, 0x80, 0x52, 0xbd, 0x72, 0xbc, - 0x00, 0x00, 0xfb, 0x02, 0x33, 0x15, 0x00, 0xa4, 0x02, 0xc0, 0x72, 0xb2, - 0x00, 0x00, 0x33, 0x03, 0x80, 0x01, 0x00, 0x80, 0xb2, 0x01, 0x72, 0xb6, - 0x01, 0x01, 0x08, 0x0a, 0x00, 0x28, 0x00, 0x80, 0xc2, 0x0d, 0x74, 0x3c, - 0x00, 0x00, 0x33, 0x03, 0x0b, 0x31, 0x00, 0x7c, 0x08, 0x00, 0x75, 0xb2, - 0x00, 0x00, 0x33, 0x03, 0x9f, 0xf0, 0x01, 0x80, 0x82, 0xdb, 0x87, 0xbc, - 0x00, 0x00, 0xfc, 0x02, 0x00, 0x38, 0x00, 0x88, 0x18, 0x00, 0x75, 0x9c, - 0x00, 0x00, 0x33, 0x03, 0x80, 0x00, 0x00, 0x80, 0xb2, 0x01, 0x72, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x08, 0x00, 0x75, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, 0x08, 0x00, 0x75, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x74, 0x38, 0xa2, 0x75, 0x37, - 0x00, 0x00, 0x01, 0x03, 0x83, 0x1b, 0x00, 0x78, 0x08, 0xc0, 0x74, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0xf2, 0x02, 0x80, 0x01, 0x00, 0x80, 0x42, 0x80, 0x87, 0xb6, - 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x84, 0xd2, - 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x87, 0xd2, - 0x00, 0x00, 0x15, 0x03, 0x9f, 0x78, 0x01, 0x80, 0xc2, 0x21, 0x6e, 0xbc, - 0x00, 0x00, 0x0a, 0x03, 0x9f, 0x99, 0x01, 0x64, 0x88, 0x1b, 0x87, 0xbc, - 0x00, 0x00, 0x16, 0x03, 0x9f, 0x68, 0x01, 0x64, 0x88, 0x5b, 0x86, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0xa4, 0x02, 0xc0, 0x72, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x02, 0xa4, 0xb2, 0x5b, 0x2a, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x02, 0x78, 0x09, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x17, 0x03, 0x08, 0x01, 0x00, 0x04, 0xe8, 0xa5, 0x75, 0xbc, - 0x0f, 0x00, 0x33, 0x03, 0x0b, 0x01, 0x00, 0x1c, 0x08, 0x00, 0x36, 0xb2, - 0x00, 0x00, 0x15, 0x03, 0x04, 0xa1, 0x01, 0x80, 0x82, 0x9b, 0x84, 0xbc, - 0x00, 0x00, 0x9d, 0x05, 0x9f, 0x98, 0x01, 0x80, 0xc2, 0x21, 0x6e, 0xbc, - 0x00, 0x00, 0x9d, 0x05, 0x06, 0xb1, 0x01, 0x80, 0x82, 0x5b, 0x87, 0xbc, - 0x00, 0x00, 0x32, 0x03, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x30, 0x03, 0x02, 0xd4, 0x01, 0x80, 0x92, 0xfb, 0x6e, 0xbc, - 0x15, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x16, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x1c, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x08, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x28, 0x72, 0x61, 0x80, 0xb9, - 0x00, 0x00, 0x1a, 0x03, 0x04, 0xa1, 0x01, 0x80, 0x82, 0x9b, 0x84, 0xbc, - 0x00, 0x00, 0x21, 0x03, 0x06, 0xa8, 0x01, 0x80, 0x82, 0x5b, 0x80, 0xbc, - 0x00, 0x00, 0x1e, 0x03, 0x04, 0xa9, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x31, 0x03, 0x04, 0xa9, 0x01, 0x80, 0x82, 0x9b, 0x84, 0xbc, - 0x00, 0x00, 0x31, 0x03, 0x04, 0x01, 0x00, 0x80, 0x12, 0x40, 0x80, 0xbc, - 0x13, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x31, 0x03, 0x9f, 0xa0, 0x01, 0x78, 0x29, 0x21, 0x6e, 0xbc, - 0x00, 0x00, 0x31, 0x03, 0x02, 0x01, 0x00, 0x80, 0x12, 0xa0, 0x97, 0xbc, - 0x00, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x2c, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x02, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x27, 0x03, 0x02, 0x00, 0x00, 0x80, 0xa2, 0x60, 0x80, 0xbc, - 0x06, 0x00, 0x9d, 0x05, 0x2c, 0x01, 0x00, 0x1c, 0x08, 0x00, 0x36, 0xb2, - 0x00, 0xc0, 0x29, 0x03, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0xb0, - 0x06, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x29, 0x03, 0x04, 0x00, 0x00, 0x80, 0xa2, 0x60, 0x80, 0xbc, - 0x09, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x2b, 0x03, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x07, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x08, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x02, 0x00, 0x9d, 0x05, 0x38, 0x01, 0x00, 0x1c, 0x08, 0x00, 0x36, 0xb2, - 0x00, 0x00, 0x2f, 0x03, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0x5b, 0x80, 0xbc, - 0x1f, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x1e, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x00, 0x28, 0x09, 0x40, 0x00, 0x92, - 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x01, 0x92, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x92, 0xd2, - 0x0d, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0xf2, - 0x00, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x10, 0x00, 0x8a, 0x11, 0x2a, 0x00, 0x00, 0xcc, 0x02, 0x20, 0x15, 0xb8, - 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x38, 0xf2, - 0x1d, 0x00, 0x49, 0x03, 0x80, 0x01, 0x00, 0x78, 0x09, 0xe0, 0x00, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x1d, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x97, 0xbc, - 0x14, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xa8, 0x05, 0x28, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x2c, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb0, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x83, 0x40, 0x01, 0x39, - 0x35, 0x00, 0x54, 0x03, 0x04, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x81, 0xd2, - 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, 0x38, 0xf2, - 0x2b, 0x00, 0x9d, 0x05, 0x02, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc, - 0x00, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x5a, 0x03, 0x1d, 0x41, 0x02, 0x5c, 0xf8, 0x01, 0x68, 0xb4, - 0x41, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0x91, - 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0xc0, 0x85, 0xd7, - 0x10, 0x00, 0x00, 0x00, 0xd0, 0x2c, 0x02, 0x00, 0xa9, 0xdb, 0x85, 0x39, - 0x00, 0x00, 0xe1, 0x02, 0x12, 0x01, 0x00, 0x54, 0x02, 0xa4, 0x38, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x64, 0x03, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x60, 0x11, 0x00, 0x78, 0x01, 0x60, 0x08, 0x00, 0x6e, 0xf2, - 0x2f, 0x00, 0x93, 0x05, 0xd7, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x65, 0x03, 0x06, 0xa9, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x6d, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x70, 0x03, 0x04, 0xa8, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x08, 0x89, 0x9b, 0x90, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x08, 0x89, 0x9b, 0x90, 0x3a, - 0x00, 0x00, 0x70, 0x03, 0x9f, 0x88, 0x01, 0x08, 0x89, 0x9b, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x04, 0xf9, 0xba, 0x6e, 0x37, - 0x00, 0x00, 0x6c, 0x03, 0x02, 0x00, 0x00, 0x80, 0x12, 0xa4, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x80, 0x90, 0x37, - 0x00, 0x00, 0x70, 0x03, 0x02, 0x01, 0x02, 0x80, 0x82, 0x9b, 0x90, 0xbc, - 0x30, 0x00, 0x93, 0x05, 0xd7, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x70, 0x03, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x12, 0x70, 0x03, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0xb0, - 0x31, 0x00, 0x93, 0x05, 0xd7, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x34, - 0x08, 0xc0, 0x74, 0x02, 0x12, 0x01, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x81, 0xd2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x2c, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb0, - 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x32, - 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, 0x38, 0xf2, - 0x2b, 0x00, 0x9d, 0x05, 0x02, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc, - 0x00, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x10, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x89, 0x4d, 0x81, 0xd7, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x2c, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb0, - 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6, - 0x00, 0x00, 0xdc, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x8a, 0x03, 0x04, 0x20, 0x01, 0x80, 0x52, 0x20, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x25, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x24, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x93, 0x03, 0x04, 0x01, 0x00, 0xd8, 0x1e, 0x80, 0xed, 0xbc, - 0x00, 0x00, 0x8c, 0x03, 0xb7, 0x00, 0x00, 0xd8, 0x0e, 0xc0, 0xed, 0xb2, - 0x00, 0x00, 0x8f, 0x03, 0x04, 0x01, 0x00, 0x80, 0x42, 0x3b, 0xee, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1e, 0x00, 0xee, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0xd0, 0x0e, 0x00, 0xee, 0x32, - 0x00, 0x00, 0x93, 0x03, 0x80, 0x01, 0x00, 0x80, 0x92, 0x80, 0xfc, 0xb6, - 0x00, 0x00, 0x93, 0x03, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0xfc, 0xb6, - 0x00, 0x00, 0x93, 0x03, 0x04, 0x01, 0x00, 0xb0, 0x1e, 0x00, 0xeb, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x86, 0xcc, 0x02, 0x80, 0x6c, 0x32, - 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x97, 0x03, 0x80, 0x01, 0x80, 0x80, 0x32, 0x0b, 0x6a, 0xb6, - 0x35, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x99, 0x03, 0x04, 0x01, 0x00, 0x80, 0x42, 0xc5, 0x2c, 0xbc, - 0x00, 0x00, 0x9a, 0x03, 0x00, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x12, 0xc0, 0x2c, 0x3a, - 0x00, 0x00, 0x95, 0x03, 0x04, 0x01, 0x00, 0x00, 0x19, 0x00, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x86, 0xc8, 0x06, 0xc0, 0x2c, 0x32, - 0x08, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xc3, 0x40, 0x01, 0x99, - 0x00, 0x00, 0x9f, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x55, 0x01, 0x80, 0xb2, 0x1b, 0x2b, 0xbc, - 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0x09, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa3, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x55, 0x01, 0x80, 0xb2, 0x1b, 0x2b, 0xbc, - 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0xad, 0x03, 0x04, 0x00, 0x00, 0x28, 0x09, 0x80, 0x80, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xef, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0xd2, - 0x00, 0x00, 0xad, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xb0, 0x03, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0x39, - 0xb0, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xb0, 0x03, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x99, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x0f, 0x00, 0x00, 0x32, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xc2, 0x03, 0x8b, 0x01, 0x00, 0xa0, 0x12, 0x00, 0x2a, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xc5, 0x03, 0x06, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2a, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xc8, 0x03, 0x85, 0x01, 0x00, 0x9c, 0x12, 0xc0, 0x29, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x0b, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x13, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x0c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x06, 0x32, - 0x0f, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x0d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x14, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x18, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x1d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x04, 0x32, - 0x1e, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x1f, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x32, - 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0xe0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x17, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x1b, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x1c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x00, 0x32, - 0x16, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x1a, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x19, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x0c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x64, 0x02, 0x39, - 0x00, 0x00, 0xfb, 0x03, 0x85, 0x01, 0x00, 0x00, 0x19, 0x00, 0x90, 0xba, - 0x25, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x32, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf3, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe3, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc3, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb3, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa3, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x83, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x63, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x53, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x43, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x33, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x13, 0x40, 0x01, 0x39, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x23, 0x40, 0x01, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x80, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x3f, 0x80, 0xfc, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x32, - 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0x40, 0x38, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xd2, 0x01, 0x30, 0xb6, - 0x00, 0x00, 0x13, 0x04, 0x04, 0x01, 0x00, 0xd0, 0x12, 0x00, 0x2d, 0xbc, - 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xe4, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x12, 0x00, 0x2d, 0x3a, - 0x4c, 0x00, 0x1a, 0x04, 0x02, 0x01, 0x00, 0x80, 0x82, 0x0d, 0x2d, 0xbc, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xae, 0x0d, 0x02, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x32, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x88, 0x86, 0xcc, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x86, 0xcc, 0x07, 0x80, 0x00, 0x3a, - 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0x02, 0x40, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x29, 0x40, 0x90, 0x3a, - 0x00, 0x00, 0x26, 0x04, 0x12, 0x00, 0x00, 0x78, 0x09, 0xc0, 0x20, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x97, 0xb6, - 0x1d, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x78, 0xe9, 0xe5, 0x00, 0xb8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x45, 0x90, 0x30, - 0x00, 0x00, 0x24, 0x04, 0x02, 0x01, 0x00, 0x80, 0xc2, 0x82, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x2c, 0x04, 0x8e, 0x01, 0x00, 0x80, 0x02, 0x40, 0x28, 0xb2, - 0x00, 0x00, 0x26, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xd2, - 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x0e, 0x00, 0x36, 0x32, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x05, 0x36, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x73, 0x80, 0x97, 0x34, - 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x32, - 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x73, 0x80, 0x97, 0x34, - 0x09, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0xfe, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x36, 0x32, - 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x3b, 0x04, 0x12, 0x01, 0x00, 0x00, 0x09, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x3b, 0x04, 0x12, 0x00, 0x00, 0x04, 0x09, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0x3e, 0x04, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x3d, 0x04, 0x12, 0x00, 0x00, 0x08, 0x09, 0x40, 0x20, 0xb2, - 0x02, 0x00, 0x39, 0x04, 0x04, 0x01, 0x00, 0x78, 0x09, 0x24, 0x17, 0xb8, - 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x64, 0x16, 0x38, - 0x00, 0x00, 0x39, 0x04, 0x04, 0x01, 0x00, 0x80, 0x02, 0x81, 0x97, 0xbc, - 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x36, 0x32, - 0xfe, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x48, 0x03, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x00, 0x09, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0x44, 0x04, 0x12, 0x00, 0x00, 0x04, 0x09, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0x47, 0x04, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x46, 0x04, 0x12, 0x00, 0x00, 0x08, 0x09, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x02, 0x00, 0x90, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x06, 0x00, 0x59, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x09, 0x64, 0x16, 0x98, - 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x92, - 0x00, 0x00, 0x97, 0x02, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x92, - 0x33, 0x00, 0x74, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x11, 0x00, 0x74, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x39, 0x00, 0x74, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x92, - 0x00, 0x00, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x90, 0x92, - 0x5a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0xcd, 0x90, 0x3a, - 0x0d, 0x00, 0x7c, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x98, - 0x0d, 0x00, 0x8e, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x98, - 0x0d, 0x00, 0x97, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x98, - 0x00, 0x00, 0xa3, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xad, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x90, 0x9d, - 0x00, 0x00, 0xb3, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xbd, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc7, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xd1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x90, 0x9d, - 0x00, 0x00, 0xd8, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x90, 0x9d, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xf3, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x92, - 0x00, 0x00, 0xf3, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x92, - 0xd8, 0x00, 0xf5, 0x04, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xff, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xdc, 0x0f, 0x40, 0x90, 0x92, - 0x00, 0x00, 0xe8, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xed, 0x04, 0x00, 0x00, 0x00, 0x78, 0x39, 0x40, 0x90, 0x97, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xec, 0x0e, 0x40, 0x90, 0x92, - 0x00, 0x00, 0xef, 0x04, 0x00, 0x00, 0x00, 0xe8, 0x0e, 0x40, 0x90, 0x92, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xd4, 0x0e, 0x40, 0x90, 0x92, - 0x00, 0x00, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x85, 0x05, 0x00, 0x00, 0x00, 0xdc, 0x0e, 0x40, 0x90, 0x92, - 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x15, 0x05, 0x00, 0x00, 0x00, 0x50, 0x1f, 0x24, 0x16, 0x98, - 0x00, 0x00, 0x27, 0x05, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x92, - 0x0d, 0x00, 0x32, 0x05, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x98, - 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x89, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x45, 0x90, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x22, 0x80, 0x97, 0xbc, - 0x3f, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x0d, 0x00, 0xb0, - 0x02, 0x00, 0x80, 0x04, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0x6b, 0x41, 0x90, 0x34, - 0x00, 0x00, 0xb0, 0x03, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0xb0, 0xb6, - 0x00, 0x00, 0xb0, 0x03, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0xb0, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x2b, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x01, 0x00, 0x34, - 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x2a, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x00, 0xb0, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0x39, - 0xb0, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x08, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x99, - 0x00, 0x00, 0x91, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32, - 0x02, 0x00, 0x91, 0x04, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0x3b, 0x40, 0xb0, 0x31, - 0x00, 0x00, 0x8d, 0x04, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x2b, 0xbc, - 0xf1, 0x0f, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x8c, 0x0e, 0x00, 0x36, 0x92, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x02, 0x00, 0x98, 0x04, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9, - 0x00, 0x00, 0x9b, 0x04, 0x80, 0x01, 0x00, 0x80, 0x12, 0x40, 0xb0, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3b, 0x40, 0xb0, 0x33, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0b, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x0c, 0x1b, 0xe4, 0xb0, 0x32, - 0x00, 0x00, 0xb0, 0x03, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xa1, 0x04, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x90, 0xb2, - 0x1f, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0x80, 0x11, 0x40, 0x00, 0x99, - 0x00, 0x00, 0xa0, 0x04, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0xf8, 0xbc, - 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xf8, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0xfc, 0xb6, - 0x00, 0x00, 0xa7, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32, - 0x09, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32, - 0x0a, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xc8, 0x0f, 0x81, 0xfc, 0x94, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x72, 0x42, 0x90, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0xe2, 0x42, 0x90, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x78, 0x09, 0x64, 0x90, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x73, 0x00, 0x90, 0x3c, - 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xb6, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32, - 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32, - 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xe4, 0x0f, 0x40, 0x90, 0x92, - 0x00, 0x00, 0xc0, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32, - 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0e, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xac, 0x0e, 0x40, 0x90, 0x92, - 0x00, 0x00, 0xca, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32, - 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32, - 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x0f, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x48, 0x0f, 0x40, 0x90, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x82, 0x42, 0x90, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x78, 0x09, 0x64, 0x90, 0xb5, - 0x00, 0x00, 0xd5, 0x04, 0x04, 0x01, 0x00, 0x80, 0x82, 0x42, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x90, 0x32, - 0x12, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x40, 0x1f, 0x40, 0x90, 0x9c, - 0x00, 0x00, 0xdb, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x85, 0x90, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x80, 0x90, 0x32, - 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x40, 0x90, 0x32, - 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x82, 0x42, 0x90, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x78, 0x09, 0x64, 0x90, 0xb5, - 0x00, 0x00, 0xe5, 0x04, 0x04, 0x01, 0x00, 0x80, 0x82, 0x42, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x90, 0x32, - 0x11, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0x40, 0x90, 0x9c, - 0x00, 0x00, 0xeb, 0x04, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x0e, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x88, 0x0e, 0x40, 0x90, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x40, 0x90, 0x37, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xa4, 0x97, 0x9a, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xbc, 0x0e, 0x80, 0xee, 0x9d, - 0x00, 0x00, 0xf2, 0x04, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0x00, 0x32, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xe4, 0x1e, 0x40, 0x90, 0x9c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x90, 0x37, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x86, 0xc0, 0x07, 0x40, 0x90, 0x92, - 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x38, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xfa, 0x04, 0x04, 0x00, 0x00, 0x80, 0x02, 0x24, 0xf6, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x3f, 0x80, 0xfc, 0x34, - 0x40, 0x80, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0f, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x79, 0x01, 0x00, 0x34, - 0x02, 0x00, 0xfc, 0x04, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x0c, 0xab, 0xe4, 0xb0, 0x32, - 0x1f, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x40, 0x00, 0x99, - 0xea, 0x05, 0x05, 0x05, 0x04, 0x01, 0x00, 0x80, 0x82, 0x4d, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x0f, 0x00, 0x15, 0x32, - 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x37, 0x32, - 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x0f, 0x00, 0x36, 0x32, - 0x98, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x0f, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x0b, 0x05, 0x00, 0x00, 0x00, 0xc8, 0x4f, 0x80, 0xfc, 0x95, - 0x36, 0x23, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x4d, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x0f, 0x80, 0x14, 0x32, - 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x37, 0x32, - 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x0f, 0x00, 0x36, 0x32, - 0x98, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x0f, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x4f, 0x80, 0xfc, 0x34, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x8f, 0x4d, 0x90, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x60, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x7a, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xa9, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x12, 0x05, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0x90, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x6f, 0x80, 0xfc, 0x34, - 0x00, 0x00, 0x14, 0x05, 0x80, 0x01, 0x00, 0x80, 0x12, 0x40, 0x90, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x5f, 0x80, 0xfc, 0x34, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x17, 0x05, 0x04, 0x01, 0x00, 0x80, 0x32, 0x40, 0x90, 0xb0, - 0x80, 0x01, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xc8, 0x8f, 0x8d, 0xfc, 0x91, - 0x00, 0x00, 0x19, 0x05, 0x80, 0x00, 0x00, 0x80, 0x12, 0x40, 0x90, 0xb6, - 0x00, 0x00, 0x1a, 0x05, 0x00, 0x00, 0x00, 0xc8, 0x7f, 0x80, 0xfc, 0x95, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x7f, 0x80, 0xfc, 0x34, - 0x00, 0x00, 0x1c, 0x05, 0x80, 0x00, 0x00, 0x80, 0x02, 0x40, 0x90, 0xb6, - 0x00, 0x00, 0x1d, 0x05, 0x00, 0x00, 0x00, 0xc8, 0x8f, 0x80, 0xfc, 0x95, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x8f, 0x80, 0xfc, 0x34, - 0x00, 0x00, 0x20, 0x05, 0x80, 0x00, 0x00, 0x80, 0x22, 0x40, 0x90, 0xb6, - 0xf1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x0e, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x22, 0x05, 0x00, 0x00, 0x00, 0xc8, 0x1f, 0x81, 0xfc, 0x95, - 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x0e, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x1f, 0x81, 0xfc, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x82, 0x02, 0xf5, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x03, 0x00, 0x00, 0x78, 0x09, 0x00, 0xf5, 0xbd, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xe2, 0x25, 0xf5, 0xb5, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x1f, 0x24, 0x16, 0x38, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x50, 0x1f, 0x00, 0xf5, 0x9c, - 0x80, 0x01, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0xfc, 0xb0, - 0x00, 0x00, 0x2b, 0x05, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0xfd, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0xf5, 0x3a, - 0x8c, 0xcc, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x80, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xec, 0x03, 0x40, 0x90, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x90, 0xbc, - 0x00, 0x00, 0x34, 0x05, 0xb2, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0xec, 0x16, 0xe4, 0x6e, 0x3a, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x00, 0x00, 0x69, 0x05, 0x17, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0xb2, - 0x06, 0x00, 0x3f, 0x05, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0xb0, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0x32, - 0x00, 0xc0, 0xd3, 0x0e, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x36, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x32, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x46, 0x05, 0x04, 0x19, 0x86, 0x80, 0x02, 0x80, 0x6c, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x12, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xc1, 0x08, 0x00, 0x04, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x15, 0x86, 0x2c, 0x09, 0xc0, 0x6c, 0x32, - 0x00, 0x00, 0x4c, 0x05, 0x22, 0x1d, 0x86, 0xc8, 0x06, 0xc0, 0x92, 0xb2, - 0x00, 0x00, 0x4c, 0x05, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x40, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x22, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xc2, 0x48, 0x00, 0x04, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x16, 0x86, 0x2c, 0x09, 0xc0, 0x6c, 0x32, - 0x00, 0x00, 0x4c, 0x05, 0x21, 0x1d, 0x86, 0xc8, 0x06, 0xc0, 0x92, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x54, 0x05, 0x04, 0x02, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0xd3, 0x0e, 0x00, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xdc, - 0x00, 0x00, 0x52, 0x05, 0x80, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x54, 0x05, 0x81, 0x00, 0x00, 0xf8, 0x22, 0x80, 0x2f, 0xb4, - 0x00, 0x00, 0x54, 0x05, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x40, 0x00, 0x92, - 0x00, 0x00, 0x54, 0x05, 0x82, 0x00, 0x00, 0xf8, 0x12, 0x80, 0x2f, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x0a, 0x32, - 0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x00, 0x07, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0xc0, 0x69, 0x05, 0x18, 0x00, 0x00, 0x00, 0xa9, 0xcd, 0x3e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x86, 0x04, 0x19, 0x80, 0x6c, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x01, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x0c, 0xf7, 0x7f, 0x90, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x86, 0x80, 0x72, 0x82, 0x6c, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0xa8, 0x42, 0x80, 0x6c, 0x37, - 0x00, 0x00, 0x78, 0x05, 0x12, 0x00, 0x70, 0x38, 0x02, 0x00, 0x7c, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xe0, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x3c, 0x02, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x30, 0x02, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x34, 0x02, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x6b, 0x05, 0x02, 0x01, 0x00, 0x80, 0xb2, 0x82, 0x2a, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0xd0, 0x02, 0x00, 0x00, 0x32, - 0x06, 0x00, 0x3f, 0x05, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0xb0, - 0x00, 0x00, 0x39, 0x05, 0x04, 0x03, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x06, 0x80, 0x2f, 0x32, - 0x00, 0x00, 0xa4, 0x03, 0xa2, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x7a, 0x05, 0x04, 0x03, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x83, 0x05, 0x00, 0x10, 0x86, 0xc8, 0x46, 0x80, 0x2a, 0x96, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x86, 0xc8, 0x46, 0x80, 0x2a, 0x36, - 0x00, 0x00, 0x7e, 0x05, 0x80, 0x00, 0x00, 0x80, 0x12, 0x80, 0x2f, 0xb6, - 0x03, 0x00, 0x80, 0x05, 0x22, 0x00, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0xb2, - 0x00, 0x00, 0x80, 0x05, 0x00, 0x18, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x83, 0x05, 0x80, 0x00, 0x00, 0x80, 0x22, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35, - 0x00, 0xc0, 0xd3, 0x0e, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x36, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0x3c, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x06, 0x80, 0x2f, 0x32, - 0x00, 0x00, 0xa4, 0x03, 0xa2, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x05, 0x04, 0x01, 0x00, 0x80, 0xa2, 0xc0, 0xed, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0e, 0x80, 0x02, 0x32, - 0x40, 0x7e, 0x05, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x0e, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x0e, 0x80, 0x07, 0x32, - 0x64, 0x00, 0x8f, 0x05, 0x00, 0x00, 0x00, 0xcc, 0x0e, 0x00, 0x36, 0x92, - 0x64, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xed, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0e, 0x40, 0x00, 0x32, - 0xa0, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x0e, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x0e, 0xc0, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x0e, 0x80, 0x02, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x33, 0x7b, 0xec, 0x39, - 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x6e, 0xc0, 0xec, 0x37, - 0x00, 0x00, 0x8d, 0x04, 0x00, 0x00, 0x00, 0xd8, 0x0e, 0xc0, 0xed, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x65, 0x01, 0x80, 0xa2, 0xdb, 0x2c, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x1c, 0x01, 0x80, 0x52, 0xc0, 0x6e, 0xbc, - 0x2b, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc, - 0x3d, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc, - 0x35, 0x00, 0x9c, 0x05, 0x04, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc, - 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x89, 0xcd, 0x81, 0x3c, - 0x10, 0x00, 0xe2, 0x10, 0x00, 0x1c, 0x01, 0x14, 0x59, 0xe4, 0x6e, 0xd9, - 0xa4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0xcd, 0x81, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x65, 0x01, 0x80, 0xa2, 0xdb, 0x2c, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x18, 0x01, 0x80, 0x92, 0xc0, 0x6e, 0xbc, - 0x2b, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x10, 0x00, 0xe2, 0x10, 0x00, 0x18, 0x01, 0x14, 0x79, 0xe0, 0x6e, 0xd9, - 0xa4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0xcd, 0x81, 0x3a, - 0xe1, 0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xea, 0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xf3, 0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xfc, 0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x05, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x0e, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x17, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x20, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x29, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x32, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x3b, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x44, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x4d, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x56, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x5f, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x68, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x71, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x7a, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x83, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x8c, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x95, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x9e, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xa7, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xb0, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xb9, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xc2, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xcb, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xd4, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xdd, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xe6, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xef, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0xf8, 0x06, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x01, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x0a, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x13, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x1c, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x25, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x2e, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x37, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x40, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x49, 0x07, 0x00, 0x00, 0x00, 0x18, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x00, 0x00, 0x57, 0x03, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x52, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x57, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x5c, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x61, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x66, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x6b, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x70, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x75, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x7a, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x7f, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x84, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x89, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x8e, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x93, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x98, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x9d, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x88, 0x82, 0xcd, 0x6e, 0x3a, - 0x00, 0x00, 0x5f, 0x03, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x71, 0x03, 0x00, 0x00, 0x00, 0xd4, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x3b, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x79, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xda, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xda, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xda, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xea, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xea, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xea, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x86, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xd7, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x7d, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xd7, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x7d, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xd7, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe9, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe9, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe9, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe9, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc1, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0xb8, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0xc1, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc1, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92, - 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x86, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x01, 0x92, - 0x00, 0x00, 0x81, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x76, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x76, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x76, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x76, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc9, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x47, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x4b, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0xb0, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x4b, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x4b, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0xa3, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x02, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x4c, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0xb0, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x4c, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x4c, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x51, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x51, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x51, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x51, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x68, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x64, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x64, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x64, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x64, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x7e, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x7e, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x7e, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x7e, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8f, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xa0, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xa0, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xb5, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xb5, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xb5, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x75, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xcc, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x02, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xd4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc4, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xa2, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa8, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x2a, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x2a, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x34, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x34, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x31, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xab, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xf3, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xb6, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xb6, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xb6, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x0a, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x1a, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xb4, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc3, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xc3, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe5, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe8, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xe8, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xea, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xea, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xea, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92, - 0x00, 0x00, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x40, 0x00, 0x92, - 0x00, 0x00, 0xf8, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xf8, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x2e, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x22, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0x22, 0x09, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xef, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0x80, 0x00, 0x92, - 0x00, 0x00, 0xef, 0x08, 0x00, 0x00, 0x00, 0x10, 0x08, 0xc0, 0x00, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x01, 0x92, - 0x08, 0x00, 0xa1, 0x03, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x99, - 0x08, 0x00, 0x9d, 0x03, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x99, - 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x08, 0x00, 0xa7, 0x07, 0x1d, 0x19, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xb9, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0xa1, 0x03, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x94, - 0x08, 0x00, 0xa1, 0x03, 0x00, 0x1c, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x99, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x0f, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0xec, 0x06, 0xc0, 0x6e, 0x35, - 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37, - 0xb4, 0xcc, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xc0, 0x2c, 0x37, - 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x97, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x00, 0x00, 0x87, 0xbf, 0x97, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0xfe, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x78, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0xb7, 0x07, 0xb7, 0x10, 0x02, 0xe0, 0x06, 0x80, 0x97, 0xb2, - 0x00, 0x00, 0xba, 0x07, 0x80, 0x00, 0x00, 0x80, 0xf2, 0x80, 0xfc, 0xb6, - 0x00, 0x00, 0xbb, 0x07, 0x00, 0x00, 0x00, 0xc8, 0xff, 0x80, 0xfc, 0x94, - 0x00, 0x00, 0xbc, 0x07, 0x9f, 0x99, 0x00, 0x80, 0x82, 0x1b, 0xee, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0xe0, 0x0e, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x1c, 0x09, 0x00, 0x6e, 0x32, - 0x40, 0x00, 0xc1, 0x07, 0x06, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x91, 0xbc, - 0x00, 0x40, 0xc2, 0x07, 0x00, 0x18, 0x02, 0xe0, 0xa6, 0xcd, 0x2c, 0x92, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x18, 0x02, 0xe0, 0xa6, 0xcd, 0x2c, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x80, 0x03, 0x32, - 0x00, 0x00, 0xc5, 0x07, 0x80, 0xd7, 0x01, 0x80, 0x32, 0xc0, 0x6e, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x49, 0x00, 0x92, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x18, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0x24, 0x09, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x28, 0x09, 0x80, 0x6e, 0x32, - 0x00, 0x00, 0xd3, 0x07, 0x80, 0x0e, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xb6, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0x02, 0xec, 0x06, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x01, 0x92, 0x3a, - 0x00, 0x00, 0xcf, 0x07, 0x80, 0xd6, 0x01, 0x80, 0x42, 0xc0, 0x6e, 0xb6, - 0x00, 0x82, 0x00, 0x00, 0x00, 0x10, 0x02, 0xe0, 0xa6, 0xcd, 0x91, 0x32, - 0x00, 0xa0, 0x00, 0x00, 0x00, 0x2c, 0x02, 0xe8, 0x06, 0x00, 0x36, 0x32, - 0x28, 0x00, 0xdd, 0x07, 0x00, 0x32, 0x02, 0xec, 0x06, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0xd3, 0x01, 0x00, 0x1c, 0xd9, 0xc1, 0x91, 0x34, - 0x00, 0x82, 0x00, 0x00, 0x00, 0x10, 0x02, 0xe0, 0xa6, 0xcd, 0x91, 0x32, - 0x00, 0xa0, 0x00, 0x00, 0x00, 0x2c, 0x02, 0xe8, 0x06, 0x00, 0x36, 0x32, - 0x34, 0x00, 0xdd, 0x07, 0x00, 0x32, 0x02, 0xec, 0x06, 0x00, 0x36, 0x92, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x34, 0x02, 0xec, 0x06, 0x00, 0x36, 0x32, - 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x0d, 0x92, 0x3a, - 0x00, 0x00, 0xd9, 0x07, 0x80, 0xd6, 0x01, 0x80, 0x42, 0xc0, 0x6e, 0xb6, - 0x00, 0x86, 0x00, 0x00, 0x00, 0x10, 0x02, 0xe0, 0xa6, 0xcd, 0x91, 0x32, - 0x04, 0xa0, 0x00, 0x00, 0x00, 0x2c, 0x02, 0xe8, 0x06, 0x00, 0x36, 0x32, - 0x14, 0x00, 0xdd, 0x07, 0x00, 0x32, 0x02, 0xec, 0x06, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0xd3, 0x01, 0x00, 0x1c, 0xd9, 0xc1, 0x91, 0x34, - 0x00, 0x86, 0x00, 0x00, 0x00, 0x10, 0x02, 0xe0, 0xa6, 0xcd, 0x91, 0x32, - 0x04, 0xa0, 0x00, 0x00, 0x00, 0x2c, 0x02, 0xe8, 0x06, 0x00, 0x36, 0x32, - 0x20, 0x00, 0xdd, 0x07, 0x00, 0x32, 0x02, 0xec, 0x06, 0x00, 0x36, 0x92, - 0x12, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0xec, 0x86, 0xcd, 0x91, 0x3a, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x28, 0x02, 0xe8, 0x86, 0x24, 0x90, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0xe0, 0x96, 0x24, 0x14, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xe0, 0x06, 0x80, 0x91, 0x32, - 0x00, 0x00, 0xe3, 0x07, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37, - 0x00, 0xcd, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xc0, 0x2c, 0x37, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x97, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x00, 0x00, 0x87, 0xbf, 0x97, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0xfe, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xc9, 0x01, 0x80, 0x02, 0x80, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0xec, 0x06, 0x80, 0x83, 0x32, - 0x01, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0xf9, 0x07, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x2c, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0xff, 0x07, 0x80, 0xd7, 0x01, 0x2c, 0x09, 0xc0, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xda, 0xd7, 0x01, 0xec, 0x06, 0xc0, 0x6e, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x01, 0xec, 0x06, 0x40, 0xed, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0xec, 0x06, 0x80, 0xee, 0x32, - 0x00, 0x00, 0x02, 0x08, 0x80, 0x01, 0x00, 0x80, 0x62, 0xc0, 0x92, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x82, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0xaa, 0x07, 0x04, 0x06, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0xaa, 0x07, 0x80, 0x00, 0x00, 0x80, 0x72, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x34, - 0x3b, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xb2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x0a, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x60, 0x11, 0x00, 0x78, 0x01, 0x60, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x0f, 0x08, 0x12, 0x01, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2, - 0x00, 0x00, 0x12, 0x08, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x1e, 0x08, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2, - 0x00, 0x00, 0x12, 0x08, 0x12, 0x01, 0x00, 0x60, 0x02, 0x80, 0x2c, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x14, 0x08, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x80, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0xff, 0x3a, - 0x00, 0x00, 0x17, 0x08, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0xaa, 0x07, 0x80, 0x00, 0x00, 0x80, 0x72, 0x81, 0x2f, 0xb6, - 0x3b, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x14, 0x08, 0x80, 0x6e, 0x32, - 0x00, 0x00, 0x12, 0x08, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2, - 0x00, 0x00, 0x10, 0x08, 0x12, 0x00, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x78, 0xe1, 0x6e, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x20, 0x07, 0x00, 0x00, 0x32, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x78, 0xca, 0xe9, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0x32, - 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x21, 0x2f, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x02, 0x44, 0xe2, 0x25, 0x6e, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x90, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0x3c, - 0x00, 0x00, 0x82, 0x08, 0x04, 0xb0, 0x00, 0xe0, 0xd6, 0x20, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x50, 0x08, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc, - 0x00, 0x00, 0x34, 0x08, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0xe2, 0xe0, 0x38, 0xb2, - 0x00, 0x00, 0x41, 0x08, 0x51, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x83, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0xe2, 0xe5, 0x38, 0xb2, - 0x00, 0x00, 0x39, 0x08, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x5c, 0x10, 0x00, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0x32, - 0x00, 0x00, 0x3b, 0x08, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x3f, 0x08, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x3a, 0x08, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x46, 0x08, 0x2a, 0x01, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xba, - 0x00, 0x00, 0x45, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x00, 0x00, 0xca, 0xe0, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xf0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x81, 0x83, 0x35, - 0x00, 0x00, 0x28, 0x08, 0x04, 0xb0, 0x00, 0x80, 0x82, 0x9b, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x35, - 0x08, 0xa0, 0x28, 0x08, 0x12, 0x01, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x83, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0xe2, 0xe5, 0x38, 0xb2, - 0x00, 0x00, 0x58, 0x08, 0x28, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0xba, - 0x00, 0x00, 0x5b, 0x10, 0x00, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x58, 0x08, 0x1d, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0xb2, - 0x00, 0x00, 0x58, 0x08, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0x5c, 0x08, 0x04, 0xa0, 0x00, 0xe0, 0x06, 0x80, 0x81, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x90, 0x00, 0xe0, 0x06, 0xc0, 0x86, 0xb2, - 0x00, 0x00, 0x6e, 0x08, 0x00, 0x98, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0x92, - 0x00, 0x00, 0x62, 0x08, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x5f, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x62, 0x08, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x5e, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x94, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xe0, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xca, 0xe8, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xf0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x6a, 0x08, 0x04, 0xb0, 0x00, 0x80, 0x82, 0x9b, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x35, - 0x08, 0xa0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0xe0, 0x06, 0x80, 0x81, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x90, 0x00, 0xe0, 0x06, 0xc0, 0x86, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32, - 0x00, 0x00, 0x74, 0x08, 0x2a, 0x5d, 0x01, 0xec, 0x06, 0x80, 0xee, 0xb2, - 0x00, 0x00, 0x71, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x74, 0x08, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x94, - 0x10, 0x04, 0x77, 0x08, 0x37, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0xb1, - 0x3b, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x34, - 0x08, 0x00, 0x00, 0x00, 0xca, 0x1c, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x39, - 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0x7d, 0x08, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x7c, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xc2, 0x00, 0x03, 0xbc, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x80, 0x67, 0xa1, 0x73, 0x39, - 0x30, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x5c, 0xa2, 0x8d, 0x2c, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xd2, 0xe0, 0x83, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x2a, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x83, 0xb4, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0xe2, 0xe5, 0x38, 0xb2, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x8a, 0x08, 0x1d, 0x00, 0x00, 0x38, 0x18, 0x81, 0x83, 0xb5, - 0x00, 0x00, 0x8a, 0x08, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0x8d, 0x08, 0x04, 0x06, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x34, - 0x08, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0xb2, - 0x00, 0x00, 0x90, 0x08, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x5c, 0x10, 0x00, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0x32, - 0x00, 0x00, 0x92, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xae, 0x08, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x95, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0x35, - 0x00, 0x00, 0xac, 0x08, 0x04, 0x00, 0x00, 0x80, 0x02, 0x61, 0x80, 0xbc, - 0x00, 0x00, 0xa4, 0x08, 0x80, 0xb8, 0x00, 0x00, 0x09, 0xc0, 0x6e, 0xb2, - 0x40, 0x00, 0x9c, 0x08, 0x04, 0x00, 0x00, 0x80, 0x82, 0x0d, 0x90, 0xbc, - 0x80, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x0d, 0x90, 0xbc, - 0x00, 0x00, 0x9c, 0x08, 0x02, 0xb0, 0x00, 0x80, 0x82, 0x1b, 0x84, 0xbc, - 0x00, 0x00, 0xa4, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xb2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0xd6, 0x01, 0x80, 0x52, 0xc0, 0x6e, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x56, 0xc0, 0x6e, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x00, 0x86, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb7, 0x01, 0x78, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x01, 0xe0, 0x06, 0x00, 0x86, 0x32, - 0x40, 0x00, 0xae, 0x08, 0x04, 0x00, 0x00, 0x80, 0x82, 0x0d, 0x90, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa0, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xfa, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x00, 0x00, 0x3c, 0x18, 0x20, 0x84, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xb0, 0x00, 0x3c, 0x88, 0xdb, 0x83, 0xbe, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x01, 0x78, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf7, 0x20, 0x78, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x58, 0x78, 0x01, 0xe0, 0xf6, 0x20, 0x86, 0x3a, - 0x00, 0x00, 0x25, 0x08, 0x00, 0x00, 0x00, 0x04, 0xf8, 0x60, 0x80, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x81, 0x2f, 0xb6, - 0x2e, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xc2, 0x00, 0x03, 0xbc, - 0x10, 0x00, 0x00, 0x00, 0xd4, 0x18, 0x00, 0x80, 0x67, 0xa1, 0x73, 0x39, - 0x00, 0x00, 0x00, 0x00, 0xda, 0x5c, 0x01, 0xec, 0x06, 0x80, 0xee, 0x32, - 0x30, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x5c, 0xa2, 0x8d, 0x2c, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x1a, 0x08, 0x00, 0x00, 0x00, 0xf8, 0xc2, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0xb8, 0x08, 0x80, 0x00, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xbb, 0x08, 0x00, 0xd0, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc2, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0xbb, 0x08, 0x04, 0xd1, 0x01, 0x80, 0x02, 0x80, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x26, 0xc0, 0x6e, 0x34, - 0x00, 0x00, 0xbd, 0x08, 0x80, 0x00, 0x00, 0x80, 0x92, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xc0, 0x08, 0x00, 0xc8, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x92, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0xc0, 0x08, 0x04, 0xc9, 0x01, 0x80, 0x02, 0x80, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0x34, - 0x10, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xaa, 0x07, 0x9a, 0x01, 0x00, 0xf8, 0x42, 0x81, 0x2f, 0xb5, - 0x00, 0x00, 0xaa, 0x07, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2, - 0x00, 0x00, 0xc7, 0x08, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x02, 0x80, 0x2c, 0xb2, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0xff, 0x9a, - 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x21, 0x2f, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x97, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x02, 0x44, 0xe2, 0x25, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x01, 0x60, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x0c, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x1c, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x77, 0x10, 0x00, 0xa8, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0xd4, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xda, 0x5c, 0x01, 0xec, 0x06, 0x80, 0xee, 0x32, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0xd4, 0x08, 0x23, 0x29, 0x02, 0x04, 0x09, 0x80, 0x6e, 0xb2, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x08, 0x00, 0xd8, 0x08, 0x1d, 0x1c, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xb9, - 0x00, 0x00, 0xd8, 0x08, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0xdc, 0x08, 0x9d, 0x01, 0x00, 0x80, 0x07, 0xc0, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x80, 0x07, 0xc0, 0x91, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x80, 0x07, 0x00, 0xee, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x07, 0xc0, 0x85, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x07, 0x40, 0x90, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x80, 0x87, 0x8d, 0x85, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x07, 0x00, 0x86, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x80, 0x07, 0x00, 0x85, 0x32, - 0x00, 0x00, 0xe3, 0x08, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x30, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x5c, 0xa2, 0x8d, 0x2c, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x12, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x01, 0x78, 0x09, 0x80, 0x6e, 0x32, - 0x00, 0x00, 0xaa, 0x07, 0xdc, 0xd1, 0x01, 0xe8, 0x06, 0x80, 0x97, 0x92, - 0x12, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x00, 0x00, 0x18, 0x09, 0x40, 0x81, 0xf2, - 0x00, 0x00, 0x2f, 0x0e, 0x00, 0xa8, 0x01, 0x20, 0x09, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0xaa, 0x07, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x80, 0x2f, 0xb6, - 0x30, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0xaa, 0x07, 0x35, 0x01, 0x00, 0xf8, 0x12, 0x81, 0x2f, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0xc0, 0xf6, 0x08, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x47, 0x10, 0x00, 0x98, 0x01, 0x28, 0x09, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0x08, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xff, 0x08, 0x80, 0x00, 0x00, 0x80, 0x42, 0x81, 0x2f, 0xb6, - 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x2f, 0xd2, - 0x00, 0x00, 0xff, 0x08, 0x08, 0x5b, 0x01, 0xec, 0x06, 0xfb, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32, - 0x34, 0x00, 0x00, 0x00, 0xd4, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0x32, - 0x00, 0x00, 0x06, 0x09, 0x80, 0x01, 0x00, 0x80, 0x92, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x0d, 0x09, 0x08, 0xc9, 0x01, 0xe8, 0x06, 0xbb, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32, - 0x32, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x01, 0xf2, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x0d, 0x09, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x92, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x0d, 0x09, 0x08, 0xd1, 0x01, 0xe8, 0x06, 0xbb, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32, - 0x32, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0x01, 0xf2, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xaa, 0x07, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6, - 0x17, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x13, 0x09, 0x12, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x20, 0xb2, - 0x00, 0x00, 0x16, 0x09, 0x12, 0x01, 0x00, 0x5c, 0x08, 0x80, 0x20, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x02, 0x80, 0x2c, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0xff, 0x3a, - 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x79, 0x21, 0x2f, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf9, 0x81, 0x97, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x02, 0x44, 0xe2, 0x25, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xd4, 0xa0, 0x01, 0x50, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xdb, 0x79, 0x01, 0x60, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x5c, 0x10, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xe0, 0x06, 0x00, 0x85, 0x32, - 0x00, 0x00, 0x1f, 0x09, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x30, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0xa2, 0x8d, 0x2c, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0xaa, 0x07, 0xda, 0x5c, 0x01, 0xec, 0x06, 0x80, 0xee, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x9f, 0x41, 0x01, 0x80, 0x52, 0x20, 0x6e, 0xbc, - 0x00, 0x00, 0x2d, 0x09, 0x9f, 0x98, 0x01, 0x80, 0x52, 0x20, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0xc0, 0x2b, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0xaa, 0x07, 0x31, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x12, 0x81, 0x2f, 0x34, - 0x3a, 0x00, 0xaa, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x47, 0x10, 0x00, 0x98, 0x01, 0x28, 0x09, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xaa, 0x07, 0xd5, 0x41, 0x01, 0xe0, 0x06, 0x40, 0x81, 0x92, - 0x00, 0x00, 0xaa, 0x07, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x60, 0x11, 0x00, 0x78, 0x01, 0x60, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x78, 0x09, 0x80, 0x6e, 0x32, - 0x00, 0x00, 0x35, 0x09, 0x04, 0xd4, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0x80, 0x97, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0xe0, 0xe6, 0x25, 0x6e, 0x3a, - 0x00, 0x00, 0x60, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xaa, 0x07, 0x00, 0x90, 0x01, 0xe0, 0x06, 0x00, 0x80, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0xe0, 0x06, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x1a, 0x08, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x00, 0x6e, 0x32, - 0x02, 0x00, 0x3f, 0x09, 0x04, 0xb9, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc, - 0x00, 0x00, 0x41, 0x09, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0xfc, 0xb6, - 0x00, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x41, 0x09, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0xfc, 0xb6, - 0x00, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0xf5, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x42, 0xbd, 0x97, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x99, 0xb1, 0xf2, 0xc0, 0x7c, 0x30, - 0x00, 0xc0, 0x48, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x50, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x07, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xa2, 0x00, 0x2d, 0x37, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x99, 0xe1, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x4d, 0x09, 0x04, 0x01, 0x00, 0x78, 0x19, 0x80, 0x97, 0xbc, - 0x02, 0x00, 0x59, 0x09, 0x04, 0xb9, 0x00, 0x80, 0x82, 0xcd, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x48, 0xd6, 0x01, 0x00, 0x78, 0xc9, 0xcd, 0x2c, 0x32, - 0x00, 0x00, 0x51, 0x09, 0xb6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0x02, 0x80, 0x97, 0xb2, - 0x00, 0x00, 0x53, 0x09, 0x12, 0x08, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x54, 0x09, 0x12, 0x18, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x55, 0x09, 0x12, 0x10, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xa6, 0x54, 0x01, 0xec, 0x06, 0x00, 0x2b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x01, 0xe8, 0x06, 0xc0, 0x2c, 0x32, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x0e, 0x01, 0xec, 0x06, 0x00, 0x00, 0x94, - 0x00, 0x20, 0x00, 0x4c, 0xd6, 0x01, 0x00, 0x78, 0xc9, 0xcd, 0x2c, 0x32, - 0x00, 0x00, 0x5a, 0x09, 0xb6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0x02, 0x80, 0x97, 0xb2, - 0x00, 0x00, 0x5c, 0x09, 0x12, 0x08, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x5d, 0x09, 0x12, 0x30, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x5e, 0x09, 0x12, 0x38, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x5f, 0x09, 0x12, 0x40, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x60, 0x09, 0x12, 0x48, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x61, 0x09, 0x12, 0x10, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x62, 0x09, 0x12, 0x18, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x63, 0x09, 0x12, 0x20, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x64, 0x09, 0x12, 0x28, 0x00, 0x64, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xa6, 0x54, 0x01, 0xec, 0x06, 0x00, 0x2b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x01, 0xe8, 0x06, 0xc0, 0x2c, 0x32, - 0x03, 0x00, 0xa2, 0x07, 0x00, 0x0e, 0x01, 0xec, 0x06, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32, - 0x00, 0x00, 0x6b, 0x09, 0x00, 0x00, 0x00, 0x14, 0x08, 0x80, 0x3d, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x02, 0x32, - 0x00, 0x00, 0x6e, 0x09, 0x04, 0x00, 0x00, 0xdc, 0x53, 0x60, 0x3d, 0xb3, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x03, 0x39, - 0x6a, 0x09, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0x74, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x14, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32, - 0x00, 0x10, 0x00, 0x82, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0xa2, 0x07, 0xca, 0x01, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x94, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6, - 0x2c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x7d, 0x09, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x29, 0x00, 0xa2, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x2c, 0x09, 0xc0, 0x85, 0xd2, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0xa1, 0x03, 0x23, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x3c, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x2c, 0x09, 0xc0, 0x85, 0xd2, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0x8c, 0x09, 0x38, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2, - 0x00, 0x00, 0x8c, 0x09, 0x1e, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8f, 0x09, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2, - 0x00, 0x82, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2, - 0x00, 0xc0, 0x99, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2, - 0x20, 0x80, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x01, 0x0e, 0x00, 0x30, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0xfa, - 0x00, 0x00, 0xa2, 0x09, 0x38, 0x01, 0x00, 0x2c, 0xf8, 0x01, 0x0b, 0xb4, - 0x00, 0x00, 0xa2, 0x09, 0x02, 0x0d, 0x02, 0x80, 0xa2, 0x5b, 0x80, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xc8, 0xc1, 0x82, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0xa8, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0xbc, - 0x00, 0x00, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xa7, 0x09, 0x27, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x2c, 0xe8, 0xc0, 0x82, 0x34, - 0x00, 0x00, 0x00, 0x00, 0xd5, 0x40, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32, - 0x08, 0x00, 0xb0, 0x10, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xf9, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0xab, 0x09, 0x23, 0x19, 0x00, 0x00, 0x07, 0x80, 0x81, 0xb2, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xad, 0x09, 0x1d, 0x21, 0x00, 0x00, 0x07, 0x00, 0x82, 0xb2, - 0x00, 0x00, 0xb0, 0x09, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0xb0, 0x09, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x80, 0x2d, 0xbc, - 0x10, 0x00, 0xb6, 0x09, 0x2c, 0x30, 0x00, 0x00, 0x17, 0xe0, 0x2c, 0xb9, - 0x00, 0x00, 0xb8, 0x09, 0x8e, 0x39, 0x00, 0x00, 0x07, 0xc0, 0x82, 0xb2, - 0x00, 0x00, 0xb8, 0x09, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x87, 0x92, - 0x00, 0x00, 0xb8, 0x09, 0x8e, 0x39, 0x00, 0x00, 0xb7, 0xc1, 0x82, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x87, 0x32, - 0x00, 0x00, 0xba, 0x09, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xc0, 0x09, 0x04, 0x01, 0x00, 0x80, 0x12, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0xb8, 0x09, 0x9f, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34, - 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xc8, 0x09, 0x1e, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0xa8, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0xbc, - 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xa4, 0x07, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0xce, 0x09, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x1c, 0x40, 0x02, 0x80, 0x06, 0xc0, 0x85, 0xb2, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x2c, 0x10, 0xd6, 0x01, 0x00, 0x2c, 0x09, 0xc0, 0x85, 0xd2, - 0x00, 0x00, 0xa1, 0x03, 0xd2, 0x01, 0x00, 0x94, 0x1e, 0x40, 0xe9, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xee, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x51, 0x01, 0x80, 0x02, 0x80, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x21, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32, - 0x00, 0x00, 0xe4, 0x09, 0x1f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xe1, 0x09, 0x9e, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa4, 0x07, 0x2a, 0x31, 0x01, 0xe0, 0x06, 0x00, 0x00, 0xb2, - 0x18, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0x39, - 0xa4, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x0c, 0x00, 0xeb, 0x09, 0x00, 0x00, 0x00, 0x58, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0xeb, 0x09, 0x00, 0x00, 0x00, 0x58, 0x08, 0x00, 0x00, 0x92, - 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x08, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xee, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x25, 0x0a, 0x38, 0x00, 0x00, 0xa4, 0x08, 0x80, 0x82, 0xb2, - 0x00, 0x00, 0x25, 0x0a, 0x04, 0x28, 0x01, 0x04, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x08, 0x50, 0x01, 0x04, 0xa8, 0x5b, 0x80, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x08, 0x20, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x0a, 0x0a, 0x08, 0x01, 0x00, 0x28, 0x18, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0xa6, 0x20, 0x00, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0xfb, 0x09, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x80, 0x97, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x97, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32, - 0x00, 0x20, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x3d, 0x00, 0x0c, 0x07, 0x80, 0x83, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x40, 0x00, 0x32, - 0x00, 0x00, 0x08, 0x0a, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a, - 0x00, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2, - 0x00, 0x00, 0x66, 0x0a, 0x12, 0x01, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x6c, 0x18, 0x20, 0x6e, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x0f, 0x0a, 0x00, 0x38, 0x01, 0xe0, 0x06, 0x40, 0x80, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x6c, 0x18, 0x20, 0x6e, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x11, 0x0a, 0x9f, 0x01, 0x00, 0x04, 0x68, 0x60, 0x80, 0xbc, - 0x00, 0x00, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x18, 0x18, 0x20, 0x00, 0x9c, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x14, 0x0a, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x70, 0x00, 0x18, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x0d, 0x0a, 0x02, 0x01, 0x00, 0x80, 0x62, 0x60, 0x80, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35, - 0x00, 0xa0, 0x0d, 0x0a, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x1f, 0x0a, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x1f, 0x0a, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xa0, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35, - 0x00, 0xa0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x80, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xe0, 0x06, 0x80, 0x81, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0xe0, 0x06, 0xc0, 0x86, 0xb2, - 0x00, 0x00, 0x27, 0x0a, 0x00, 0x18, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0xa3, 0x0e, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0x2a, 0x0a, 0x00, 0x50, 0x01, 0x3c, 0xa8, 0x5b, 0x80, 0x9c, - 0x00, 0x00, 0xa4, 0x07, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x2f, 0x0a, 0x3e, 0x51, 0x01, 0x00, 0xa8, 0x1b, 0x80, 0xba, - 0x00, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0xf8, 0xf2, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0xec, 0x06, 0xc0, 0xee, 0x32, - 0x00, 0x00, 0x2f, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x87, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0x4c, 0x0f, 0x60, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0x7b, 0x0a, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x3a, 0x0a, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xc9, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0xa4, 0xa8, 0x60, 0x8a, 0x3c, - 0x00, 0x00, 0x8a, 0x11, 0x0f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0xc0, 0x3e, 0x0a, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0xa4, 0xa8, 0x60, 0x8a, 0x3c, - 0x00, 0x00, 0x8a, 0x11, 0x0f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xde, 0xa8, 0x01, 0x20, 0x99, 0x22, 0x6e, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x02, 0x80, 0x82, 0x1b, 0x92, 0xbc, - 0x00, 0x00, 0x42, 0x0a, 0x2f, 0x20, 0x01, 0xe0, 0x96, 0x22, 0x6e, 0xbc, - 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x4a, 0x0a, 0x1f, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x45, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x83, 0xbc, - 0x00, 0x00, 0x4a, 0x0a, 0x00, 0x50, 0x01, 0xe8, 0xf6, 0x60, 0x80, 0x9c, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x08, 0x00, 0x73, 0x11, 0x00, 0x40, 0x02, 0x14, 0x39, 0x9a, 0xfe, 0xd8, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0x38, - 0x00, 0x00, 0x4f, 0x0a, 0x2a, 0xa9, 0x01, 0xe0, 0x06, 0x00, 0x92, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x4f, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x4b, 0x0a, 0x04, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x52, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x2f, 0xb6, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x32, - 0x00, 0xc0, 0x61, 0x0a, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x18, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x82, 0xb6, - 0x00, 0x00, 0x58, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x81, 0xbc, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x18, 0x00, 0x5a, 0x0a, 0x2e, 0x49, 0x01, 0xe0, 0xe6, 0xa0, 0x82, 0xb9, - 0x00, 0x00, 0x5b, 0x0a, 0x00, 0x5e, 0x01, 0xec, 0x76, 0x00, 0x00, 0x94, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32, - 0x20, 0x80, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2, - 0x1b, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x0c, 0x00, 0xa1, 0x03, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x85, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x30, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x9e, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x80, 0x85, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2f, 0xb6, - 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x67, 0x0a, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x6e, 0x0a, 0x3d, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2, - 0x00, 0x00, 0x6e, 0x0a, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x72, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x92, 0x80, 0x2f, 0xb6, - 0x2a, 0x00, 0x78, 0x0a, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x75, 0x0a, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x78, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x78, 0x0a, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0xa2, 0x07, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x85, 0xbc, - 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x9e, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x80, 0x85, 0x92, - 0x00, 0x00, 0xa4, 0x07, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x80, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x31, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x31, 0x00, 0x80, 0x82, 0x9b, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x12, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xce, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0x86, 0x0a, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x8f, 0x0a, 0x3f, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0xb2, - 0x00, 0x00, 0x8f, 0x0a, 0x80, 0x01, 0x00, 0x80, 0xe2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0xf8, 0xf2, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0xec, 0x06, 0xc0, 0xee, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0xda, 0x0a, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0x3c, - 0x00, 0x00, 0xb0, 0x0a, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc, - 0x00, 0x00, 0x9b, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0x02, 0xc0, 0x38, 0xb2, - 0x00, 0x00, 0xae, 0x0a, 0x51, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0xa7, 0x0a, 0x28, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0xa5, 0x0a, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0xa1, 0x0a, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0xa5, 0x0a, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0xa5, 0x0a, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0xa3, 0x0a, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x16, 0x20, 0x6e, 0x3c, - 0x00, 0x00, 0x3c, 0x0e, 0xda, 0x5b, 0x01, 0xec, 0x06, 0x40, 0xed, 0xf2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xac, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xa7, 0x0a, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xaf, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xfa, - 0x00, 0x00, 0x90, 0x0a, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0xbc, 0x0a, 0x28, 0x00, 0x00, 0x80, 0x08, 0x40, 0x00, 0xb2, - 0x00, 0x00, 0xba, 0x0a, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0xb6, 0x0a, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0xba, 0x0a, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0xba, 0x0a, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0xb8, 0x0a, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x16, 0x20, 0x6e, 0x3c, - 0x00, 0x00, 0x3c, 0x0e, 0xda, 0x5b, 0x01, 0xec, 0x06, 0x40, 0xed, 0xf2, - 0x00, 0x00, 0xe0, 0x0a, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xc0, 0x0a, 0x04, 0x21, 0x00, 0xe0, 0x06, 0x80, 0x81, 0xb2, - 0x00, 0x00, 0xaf, 0x0e, 0x00, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xe0, 0x06, 0x80, 0x81, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32, - 0x00, 0x00, 0xc6, 0x0a, 0x2a, 0x11, 0x00, 0xe0, 0xd6, 0xe0, 0x86, 0xba, - 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0xc6, 0x0a, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0xc2, 0x0a, 0x9f, 0x01, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x08, 0x00, 0xca, 0x0a, 0x23, 0x19, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xb9, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xce, 0x0a, 0x1d, 0x18, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0xb2, - 0x00, 0x00, 0xce, 0x0a, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0xd3, 0x0a, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x88, 0xbc, - 0x00, 0x00, 0xd2, 0x0a, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x19, 0x20, 0x6e, 0x3c, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xe2, 0xa5, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x88, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0xe4, 0x0a, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2, - 0x00, 0x00, 0xe5, 0x0a, 0xc9, 0x01, 0x00, 0x14, 0x08, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x45, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xef, 0x0a, 0x28, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0xee, 0x0a, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0xea, 0x0a, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0xee, 0x0a, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0xee, 0x0a, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0xec, 0x0a, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x3c, 0x0e, 0xda, 0x5b, 0x01, 0xec, 0x06, 0x40, 0xed, 0xf2, - 0x00, 0x20, 0x00, 0x80, 0xdf, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x00, 0x00, 0xf3, 0x0a, 0x3d, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2, - 0x00, 0x00, 0xf3, 0x0a, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x81, 0x2f, 0xf5, - 0x08, 0x00, 0xb0, 0x10, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xf9, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0xf8, 0x0a, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x2f, 0xb6, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xfd, 0x0a, 0x29, 0x08, 0x01, 0xe4, 0x06, 0xc0, 0x2d, 0xb2, - 0x00, 0x00, 0x02, 0x0b, 0x1d, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x02, 0x0b, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0xff, 0x0a, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x01, 0x0b, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0xfe, 0x0a, 0x00, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0x9c, - 0x2a, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xc7, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0x05, 0x0b, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x81, 0xbc, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x00, 0x00, 0xa4, 0x03, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x31, 0x00, 0x80, 0x82, 0x9b, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x80, 0x12, 0xa0, 0x82, 0xbc, - 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x10, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0xa9, 0x60, 0x80, 0xd9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0x15, 0x0b, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x20, 0x0b, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xa8, 0x60, 0x80, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0x32, - 0x00, 0x00, 0x3b, 0x0e, 0x00, 0x00, 0x00, 0x04, 0x08, 0x80, 0x82, 0xf2, - 0x00, 0x00, 0x21, 0x0b, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x20, 0x80, 0x3a, - 0x00, 0x00, 0x26, 0x0b, 0x04, 0x00, 0x00, 0x28, 0x68, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xaf, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x81, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x00, 0x00, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4, - 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x2e, 0x0b, 0x3d, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2, - 0x00, 0x00, 0x2e, 0x0b, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x04, 0x08, 0x80, 0x86, 0xb2, - 0x00, 0x00, 0x3c, 0x0b, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x28, 0x09, 0x80, 0x80, 0xb2, - 0x00, 0x00, 0xef, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xd2, - 0x00, 0x00, 0x34, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x3a, 0x10, 0x00, 0x00, 0x00, 0x78, 0x38, 0x80, 0x87, 0xf5, - 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0xa5, 0x02, 0x23, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x32, 0x80, 0x2f, 0x35, - 0x3c, 0x00, 0xa5, 0x02, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x3f, 0x0b, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x31, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x41, 0x0b, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2, - 0x00, 0x82, 0x4b, 0x0b, 0x00, 0x00, 0x00, 0x08, 0xa8, 0x8d, 0x80, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0x5c, 0x0b, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa8, 0x8d, 0x80, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2, - 0x00, 0x00, 0x53, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x4f, 0x0b, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0x53, 0x0b, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0x53, 0x0b, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0x51, 0x0b, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x3a, - 0x00, 0x00, 0xa4, 0x07, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x39, 0x10, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x17, 0xe0, 0x2c, 0x39, - 0x00, 0x10, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32, - 0x00, 0x00, 0xb0, 0x10, 0x00, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x6a, 0x0b, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x2f, 0xb6, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xc3, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x6e, 0x0b, 0x1d, 0x21, 0x00, 0x00, 0x07, 0x00, 0x82, 0xb2, - 0x00, 0x00, 0x71, 0x0b, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x71, 0x0b, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0x74, 0x0b, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0xa4, 0x03, 0xca, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92, - 0x00, 0x00, 0x7e, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x7a, 0x0b, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0x7e, 0x0b, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0x7e, 0x0b, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0x7c, 0x0b, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x80, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x86, 0xbc, - 0x00, 0x00, 0x0a, 0x11, 0x00, 0x90, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x3f, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x87, 0x0b, 0x33, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2, - 0x00, 0x00, 0x87, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xb2, 0x01, 0x72, 0xb6, - 0x00, 0x00, 0x87, 0x0b, 0x9f, 0xf0, 0x01, 0x80, 0x82, 0xdb, 0x87, 0xbc, - 0x00, 0x00, 0x87, 0x0b, 0x9f, 0xf8, 0x01, 0x80, 0x22, 0x21, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x01, 0xe0, 0x06, 0x00, 0xee, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xe0, 0x06, 0xc0, 0x87, 0x32, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x39, - 0x00, 0x00, 0x8d, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xd2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8d, 0x0b, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x34, - 0x3b, 0x00, 0x8d, 0x0b, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x9d, 0x0b, 0x27, 0x09, 0x01, 0xe4, 0x06, 0xc0, 0x2d, 0xb2, - 0x00, 0xc0, 0x95, 0x0b, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x20, 0x80, 0xa4, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x92, - 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x98, 0x01, 0x14, 0x09, 0x00, 0x6e, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xe0, 0x06, 0x40, 0x88, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xd5, 0x08, 0x00, 0x00, 0x07, 0x40, 0x88, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32, - 0x00, 0x40, 0x00, 0x80, 0xca, 0x39, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34, - 0x00, 0x00, 0xa1, 0x0b, 0x1d, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xa1, 0x0b, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0xc7, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0xa4, 0x03, 0x12, 0x01, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0xae, 0x0b, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xee, 0x10, 0x00, 0x20, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x08, 0x80, 0x82, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x18, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0xb6, 0x0b, 0x00, 0x50, 0x01, 0x3c, 0xa8, 0x5b, 0x80, 0x9c, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0xa8, 0x1b, 0x80, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0xee, 0x0b, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0x3c, - 0x00, 0x00, 0xd4, 0x0b, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc, - 0x00, 0x00, 0xc5, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0x02, 0xc0, 0x38, 0xb2, - 0x00, 0x00, 0xcd, 0x0b, 0x51, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xcb, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xc6, 0x0b, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xd2, 0x0b, 0x2a, 0x01, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xba, - 0x00, 0x00, 0xd1, 0x0b, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0xba, 0x0b, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0xdb, 0x0b, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xd5, 0x0b, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x08, 0x00, 0x73, 0x11, 0x00, 0x40, 0x02, 0x14, 0x39, 0x9a, 0xfe, 0xd8, - 0x08, 0x00, 0x8a, 0x11, 0x12, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0xba, - 0x00, 0x00, 0xa3, 0x0e, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0xe6, 0x0b, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xb9, 0x0b, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc, - 0x00, 0x00, 0xec, 0x0b, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xeb, 0x0b, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0xba, 0x0b, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x45, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0xf6, 0x0b, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xc9, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a, - 0x00, 0xc0, 0xf7, 0x0b, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x20, 0x99, 0x22, 0x6e, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x02, 0x80, 0x82, 0x1b, 0x92, 0xbc, - 0x00, 0x00, 0xfb, 0x0b, 0x2f, 0x20, 0x01, 0xe0, 0x96, 0x22, 0x6e, 0xbc, - 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xff, 0x0b, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc, - 0x00, 0x00, 0xfe, 0x0b, 0x9f, 0x31, 0x01, 0xe0, 0x96, 0x22, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x07, 0x0c, 0x00, 0x50, 0x01, 0xe8, 0xf6, 0x60, 0x80, 0x9c, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x08, 0x00, 0x73, 0x11, 0x00, 0x40, 0x02, 0x14, 0x39, 0x9a, 0xfe, 0xd8, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0x38, - 0x00, 0x00, 0x06, 0x0c, 0x9f, 0x31, 0x01, 0xe0, 0x96, 0x22, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x06, 0x00, 0x92, 0x32, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x0c, 0x0c, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x08, 0x0c, 0x04, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x14, 0x0c, 0x23, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0xba, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x15, 0x0c, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x1c, 0x0c, 0x3d, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2, - 0x00, 0x00, 0x1c, 0x0c, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x20, 0x0c, 0x29, 0x31, 0x01, 0x0c, 0x09, 0x00, 0x6e, 0xb2, - 0x2a, 0x00, 0xa2, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x27, 0x0e, 0x00, 0x0c, 0x02, 0x00, 0x09, 0x80, 0x6e, 0xf2, - 0x00, 0x00, 0x24, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x02, 0xe4, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x27, 0x0c, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xa2, 0x07, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x18, 0x09, 0x40, 0x81, 0xb2, - 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x2f, 0x0e, 0x00, 0xa8, 0x01, 0x20, 0x09, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x0c, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x27, 0x0e, 0x00, 0x0c, 0x02, 0x00, 0x09, 0x80, 0x6e, 0xf2, - 0x00, 0x00, 0xa4, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x90, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x78, 0x0b, 0x16, 0x38, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x78, 0x0b, 0x16, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa8, 0x00, 0x2d, 0x37, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x88, 0x0d, 0x8b, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xb4, 0x08, 0x80, 0x6e, 0x32, - 0x00, 0x00, 0x45, 0x0c, 0x04, 0x31, 0x01, 0x90, 0x08, 0x00, 0x6e, 0xb2, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0x8d, 0x8a, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc2, 0xa2, 0x2c, 0x3a, - 0x18, 0x00, 0x43, 0x0c, 0x86, 0x41, 0x02, 0x78, 0x88, 0x0d, 0x78, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xe2, 0x8a, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x41, 0x02, 0x80, 0xb2, 0x3f, 0x78, 0xb0, - 0x00, 0x00, 0x3c, 0x0c, 0x9f, 0x01, 0x00, 0xa8, 0x18, 0x80, 0x8a, 0xbc, - 0xb7, 0x00, 0x3c, 0x0c, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x04, 0xb8, 0x3f, 0x78, 0x30, - 0x00, 0x00, 0x58, 0x0c, 0x00, 0x00, 0x00, 0x04, 0xd8, 0x62, 0x80, 0x9c, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0x1b, 0x89, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x80, 0x2f, 0xb6, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0x8d, 0x8a, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc2, 0xa2, 0x2c, 0x3a, - 0x18, 0x00, 0x4e, 0x0c, 0x86, 0x41, 0x02, 0x78, 0x88, 0x0d, 0x78, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xe2, 0x8a, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x41, 0x02, 0x80, 0xb2, 0x3f, 0x78, 0xb0, - 0x00, 0x00, 0x47, 0x0c, 0x9f, 0x01, 0x00, 0xa8, 0x18, 0x80, 0x8a, 0xbc, - 0xb7, 0x00, 0x47, 0x0c, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x51, 0x0c, 0x28, 0x40, 0x02, 0x04, 0xb8, 0x3f, 0x78, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x04, 0xd8, 0x62, 0x80, 0x3c, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x40, 0x80, 0xb2, - 0x00, 0x00, 0x55, 0x0c, 0x02, 0x01, 0x00, 0x90, 0x18, 0x20, 0x89, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x47, 0x0c, 0x9f, 0x01, 0x00, 0xa8, 0x18, 0x80, 0x8a, 0xbc, - 0xb7, 0x00, 0x47, 0x0c, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x58, 0x0c, 0x04, 0x00, 0x00, 0x90, 0x18, 0x20, 0x89, 0xba, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x04, 0x48, 0x62, 0x80, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x90, 0x00, 0x00, 0xb4, 0x48, 0x62, 0x8b, 0xba, - 0x03, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x00, 0x08, 0x1e, 0xff, 0xb8, - 0x00, 0x00, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x22, 0x80, 0x9a, - 0x00, 0x00, 0x89, 0x0c, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xe2, 0x8a, 0xbc, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0x8d, 0x8a, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc2, 0xa2, 0x2c, 0x3a, - 0x18, 0x00, 0x87, 0x0c, 0x86, 0x40, 0x02, 0x78, 0x88, 0x0d, 0x78, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x04, 0xb8, 0x3f, 0x78, 0xb0, - 0x03, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x00, 0x08, 0x1e, 0xff, 0xb8, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2, - 0x00, 0x00, 0x67, 0x0c, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2, - 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0x72, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2, - 0x20, 0x80, 0x64, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0xb8, 0x1b, 0x80, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x64, 0x30, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x17, 0xe0, 0x2c, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xf7, 0x01, 0x0b, 0x34, - 0x00, 0x00, 0x81, 0x0c, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x87, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xb7, 0x01, 0x70, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34, - 0x00, 0x00, 0x93, 0x0c, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0x1b, 0x89, 0xbc, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x5a, 0x0c, 0x9f, 0x01, 0x00, 0xa8, 0x18, 0x80, 0x8a, 0xbc, - 0xb7, 0x00, 0x5a, 0x0c, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x36, 0x92, - 0x27, 0x00, 0x8c, 0x0c, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0x81, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x78, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0xa2, 0x97, 0xbc, - 0x00, 0x00, 0x8e, 0x0c, 0x23, 0x55, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0xb2, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x90, 0x0c, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc7, 0x01, 0x70, 0x34, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x08, 0x00, 0x97, 0x0c, 0x23, 0x19, 0x01, 0xe8, 0x76, 0x20, 0x81, 0xb9, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x99, 0x0c, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x9c, 0x0c, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0x9c, 0x0c, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xc6, 0x0e, 0x00, 0x00, 0x00, 0x2c, 0xf9, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0xa0, 0x0c, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0xa4, 0x03, 0xca, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0xc0, 0xad, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x18, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x82, 0xb6, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x01, 0xec, 0x66, 0x00, 0x00, 0x34, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x48, 0x01, 0xe0, 0xe6, 0xa0, 0x82, 0x39, - 0x1b, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x20, 0x00, 0x84, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x00, 0x00, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0xc0, 0xb6, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x02, 0xf2, - 0x00, 0x00, 0xbd, 0x0c, 0x00, 0x00, 0x00, 0x5c, 0x08, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0xc0, 0xbd, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x9c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0xf2, - 0x00, 0x00, 0xa1, 0x03, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x20, 0x00, 0x84, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x00, 0x00, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0xc2, 0x0c, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xc6, 0x0c, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x85, 0xb2, - 0x00, 0x00, 0xc6, 0x0c, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xd2, 0x41, 0x02, 0x80, 0x06, 0xc0, 0x85, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1c, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x4c, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x4c, 0x0d, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x85, 0x92, - 0x00, 0x00, 0x1a, 0x0d, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x22, 0x0d, 0x1f, 0x20, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x1a, 0x0d, 0x04, 0x30, 0x01, 0x08, 0x89, 0x9b, 0x90, 0xbc, - 0x00, 0x00, 0xd2, 0x0c, 0x04, 0x31, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xd0, 0x0c, 0x00, 0x50, 0x01, 0x48, 0x08, 0x80, 0x6e, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0x61, 0x80, 0x3c, - 0x00, 0x00, 0xeb, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x28, 0x21, 0x80, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x80, 0x90, 0xb2, - 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x30, 0x01, 0x48, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0xd6, 0x0c, 0x00, 0x50, 0x01, 0x04, 0xa8, 0x5b, 0x80, 0x9c, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0xa8, 0x1b, 0x80, 0x3a, - 0x00, 0x00, 0xe8, 0x0c, 0x07, 0x00, 0x00, 0x48, 0x18, 0xa0, 0x84, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa0, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x05, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xa0, 0xfe, 0xd8, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x02, 0xa0, 0xfe, 0x38, - 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xe1, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe8, 0x0c, 0x07, 0x00, 0x00, 0x48, 0x18, 0xa0, 0x84, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa0, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x05, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xa0, 0xfe, 0xd8, - 0x05, 0x00, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x68, 0x02, 0xa0, 0xfe, 0x98, - 0x00, 0x00, 0xeb, 0x0c, 0x04, 0x00, 0x00, 0x48, 0x18, 0xa0, 0x84, 0xba, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x04, 0x28, 0x61, 0x80, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x21, 0x80, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0xf4, 0x0c, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2, - 0x03, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x00, 0x38, 0x1a, 0xff, 0xb8, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x60, 0x80, 0x39, - 0x18, 0x00, 0x00, 0x00, 0xd2, 0x41, 0x02, 0x8c, 0xe6, 0xa1, 0x97, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x80, 0x84, 0x32, - 0x00, 0x82, 0x00, 0x00, 0xd6, 0x01, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x28, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0xfe, 0x0c, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2, - 0x00, 0x00, 0xed, 0x0c, 0x12, 0x01, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x86, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x81, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x17, 0xe0, 0x2c, 0x39, - 0x00, 0x00, 0x0d, 0x0d, 0x80, 0x00, 0x00, 0x80, 0x32, 0x80, 0x87, 0xb6, - 0x00, 0x10, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x0e, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x10, 0x00, 0x88, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x05, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xa0, 0xfe, 0xd8, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x02, 0xa0, 0xfe, 0x38, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa0, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0xeb, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x22, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x05, 0x00, 0x1d, 0x0d, 0x00, 0x00, 0x00, 0x68, 0x02, 0xa0, 0xfe, 0x98, - 0x00, 0x00, 0x22, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x05, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xa0, 0xfe, 0xd8, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa0, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x1a, 0x0d, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37, - 0xb4, 0xcc, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xc0, 0x2c, 0x37, - 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x97, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x00, 0x00, 0x87, 0xbf, 0x97, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0xfe, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x2b, 0x0d, 0xb6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x20, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0xa2, 0xcd, 0x2c, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x30, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xa2, 0x07, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x62, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x39, 0x0d, 0x12, 0x01, 0x00, 0x60, 0x08, 0x40, 0x23, 0xb2, - 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x28, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x24, 0x08, 0x00, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x20, 0x08, 0xc0, 0x23, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x18, 0x08, 0x80, 0x23, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0x43, 0x0d, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x38, 0x02, 0x80, 0x81, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x82, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x30, 0x02, 0x40, 0x82, 0xb2, - 0x00, 0x00, 0xed, 0x0c, 0x12, 0x01, 0x00, 0x34, 0x02, 0x00, 0x86, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x48, 0x08, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0x46, 0x0d, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x0d, 0x00, 0x50, 0x01, 0x00, 0xa8, 0x1b, 0x80, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0x80, 0x02, 0xf2, - 0x00, 0x00, 0x2b, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x02, 0xf2, - 0x00, 0x00, 0x4f, 0x0d, 0x9a, 0x01, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0xb4, - 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x06, 0xc0, 0x6e, 0x34, - 0x2d, 0x00, 0xa2, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa9, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x5a, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x56, 0x0d, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0x5a, 0x0d, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0x5a, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0x58, 0x0d, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x5c, 0x0d, 0x04, 0x98, 0x01, 0x64, 0x88, 0x1b, 0x87, 0xbc, - 0x00, 0x00, 0x0a, 0x11, 0x00, 0x90, 0x01, 0x08, 0x09, 0x80, 0x6e, 0xf2, - 0x00, 0x00, 0x3f, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x30, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x6c, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x68, 0x0d, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0x6c, 0x0d, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0x6c, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0x6a, 0x0d, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x00, 0x00, 0xa4, 0x07, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x36, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x7d, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x79, 0x0d, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0x7d, 0x0d, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0x7d, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0x7b, 0x0d, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x88, 0x0d, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x86, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x82, 0x0d, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0x86, 0x0d, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0x86, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0x84, 0x0d, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x30, 0x00, 0x88, 0x0d, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd5, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xa2, 0x07, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xa2, 0x07, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x93, 0x0d, 0x80, 0x00, 0x00, 0x80, 0x02, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x58, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0xa2, 0x07, 0x08, 0x59, 0x01, 0xec, 0x06, 0xfb, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0xc0, 0x9c, 0x0d, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0xec, 0x06, 0xfb, 0x6e, 0x3a, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x81, 0x2f, 0xf4, - 0x00, 0x00, 0x9f, 0x0d, 0x06, 0x03, 0x01, 0x80, 0x12, 0xc0, 0x6e, 0xbc, - 0x18, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x19, 0x00, 0x9d, 0x05, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xe2, 0x81, 0x2f, 0xb6, - 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x20, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x28, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x45, 0x30, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xc7, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0xad, 0x0d, 0x04, 0x02, 0x01, 0xec, 0x16, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xc9, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x34, - 0x00, 0xc0, 0xad, 0x0d, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x18, 0x00, 0x36, 0x00, 0xca, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xad, 0x0d, 0x9f, 0x01, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0xb2, 0x0d, 0x3d, 0x01, 0x00, 0xb0, 0x02, 0x00, 0x85, 0xb2, - 0x00, 0x00, 0xb2, 0x0d, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5, - 0x34, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xa4, 0x07, 0x80, 0x01, 0x00, 0x80, 0x92, 0x80, 0x2f, 0xb6, - 0x2a, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0xc0, 0xbc, 0x0d, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x00, 0x00, 0x9d, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x72, 0xe0, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x20, 0x00, 0x80, 0xdf, 0x00, 0x00, 0x28, 0x09, 0x00, 0x37, 0x32, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x48, 0x01, 0x38, 0x88, 0x1b, 0x16, 0x38, - 0x00, 0x00, 0x00, 0x00, 0xde, 0x48, 0x01, 0x28, 0x88, 0x04, 0x6e, 0x30, - 0x00, 0x00, 0xc1, 0x0d, 0x80, 0x5f, 0x01, 0x80, 0x72, 0xc0, 0x6e, 0xb6, - 0x00, 0x00, 0xc3, 0x0d, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x94, - 0x00, 0x00, 0xc3, 0x0d, 0x80, 0x5f, 0x01, 0x80, 0x62, 0xc0, 0x6e, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xa9, 0x81, 0x92, 0x34, - 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x00, 0x08, 0xe8, 0x01, 0x00, 0xf4, - 0x00, 0x00, 0xc6, 0x0d, 0x12, 0x01, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc9, 0x0d, 0x80, 0x01, 0x00, 0x80, 0xd2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xc9, 0x0d, 0x34, 0x00, 0x00, 0xf8, 0xd2, 0x81, 0x2f, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0xa4, 0x07, 0x04, 0x30, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x2a, 0x00, 0xa4, 0x07, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0xd8, 0x02, 0x80, 0x01, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0xc0, 0xd2, 0x0d, 0x18, 0x01, 0x00, 0x0c, 0xa8, 0xcd, 0x3e, 0xb2, - 0x00, 0x82, 0x00, 0x00, 0xd6, 0x01, 0x00, 0x08, 0x08, 0x80, 0x36, 0x32, - 0x1d, 0x00, 0xa1, 0x03, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xc2, 0x10, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x80, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x01, 0x78, 0x09, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32, - 0x00, 0x10, 0x00, 0xa0, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x00, 0xee, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x0c, 0x07, 0x80, 0x97, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0xf0, 0xe1, 0x0d, 0x1d, 0x40, 0x02, 0x00, 0xa8, 0x0d, 0x68, 0xb1, - 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x1e, 0x40, 0x02, 0x84, 0x06, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x80, 0xd0, - 0x00, 0x00, 0xde, 0x0d, 0xb6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0xc0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x64, 0xa2, 0x0d, 0x80, 0xb2, - 0x00, 0x00, 0xda, 0x0d, 0xa6, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xe1, 0x0d, 0xb5, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x80, 0xa0, 0x36, 0x0b, 0x6a, 0x35, - 0x00, 0x00, 0xe6, 0x0d, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x80, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe9, 0x01, 0x00, 0x34, - 0x00, 0x00, 0xef, 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xd2, - 0x00, 0x00, 0xeb, 0x0d, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x39, 0x0b, 0x2e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xf3, 0x81, 0x97, 0x34, - 0x00, 0x00, 0xf1, 0x0d, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x30, 0x30, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xa4, 0x03, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x33, 0x0b, 0x2f, 0x32, - 0x00, 0x00, 0xa4, 0x03, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x05, 0x30, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x80, 0x97, 0x32, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x29, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xff, 0x0d, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x2f, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x00, 0x2c, 0x32, - 0xd9, 0x02, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc, - 0x46, 0x03, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xf1, 0x0d, 0x00, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x18, 0x0e, 0x02, 0x00, 0x00, 0x80, 0xa2, 0x42, 0x80, 0xbc, - 0x00, 0x00, 0x18, 0x0e, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0x18, 0x0e, 0x1f, 0x40, 0x02, 0x08, 0xb9, 0xbf, 0x68, 0xb0, - 0x00, 0x00, 0x08, 0x0e, 0x80, 0x41, 0x02, 0x80, 0xe2, 0x81, 0x68, 0xb6, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x79, 0x61, 0x80, 0x39, - 0x00, 0x00, 0x00, 0x00, 0xd2, 0x21, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x41, 0x02, 0x88, 0xe6, 0x21, 0x91, 0x79, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x19, 0xa0, 0x90, 0x3a, - 0x00, 0x00, 0x18, 0x0e, 0x06, 0x01, 0x00, 0x80, 0xd2, 0xff, 0x90, 0xbc, - 0x00, 0x00, 0x0c, 0x0e, 0x2c, 0x41, 0x02, 0x78, 0xf9, 0x81, 0x68, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x81, 0x97, 0x34, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x59, 0xc0, 0x85, 0xd7, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x29, 0x1a, 0xff, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0xb9, 0x1b, 0x90, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0xd2, 0x41, 0x02, 0x88, 0x16, 0xa0, 0x97, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x27, 0x24, 0x90, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x8a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x58, 0xf2, 0xc1, 0x38, 0x74, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x23, 0x0e, 0x1e, 0x01, 0x00, 0x34, 0x79, 0x61, 0x80, 0xb9, - 0x00, 0x00, 0x8a, 0x11, 0x38, 0x00, 0x00, 0x54, 0x1f, 0x40, 0xf5, 0xba, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x40, 0x02, 0x00, 0x09, 0x40, 0x68, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xb9, 0x3f, 0x90, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0x26, 0x24, 0x6e, 0x3a, - 0x08, 0x00, 0x8a, 0x11, 0x1e, 0x00, 0x00, 0x00, 0x09, 0xa4, 0xfe, 0xb8, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x05, 0x90, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x05, 0x90, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x05, 0x90, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xd2, 0x21, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a, - 0x18, 0x00, 0x00, 0x00, 0x1e, 0x41, 0x02, 0x84, 0xe6, 0x61, 0x93, 0x79, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x01, 0x80, 0x82, 0xdb, 0x90, 0x7c, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x20, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0xdb, 0x90, 0x7c, - 0x00, 0x00, 0x2d, 0x0e, 0x06, 0x21, 0x01, 0x80, 0x82, 0x1b, 0x90, 0xbc, - 0x26, 0x00, 0x2e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x36, 0x92, - 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x00, 0x2c, 0x3a, - 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x92, 0xd2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x92, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x2f, 0xa0, 0x01, 0x78, 0x89, 0x1b, 0x92, 0x7a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x78, 0x89, 0x9b, 0x97, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0xf9, 0xba, 0x6e, 0x37, - 0x00, 0x00, 0x39, 0x0e, 0x02, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x97, 0xbc, - 0x00, 0x00, 0x39, 0x0e, 0x02, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x97, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x02, 0x80, 0x82, 0x9b, 0x97, 0x7c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0xf2, 0x80, 0x2f, 0x74, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0xda, 0x5b, 0x01, 0xec, 0x06, 0x40, 0xed, 0x32, - 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x89, 0xd2, - 0x00, 0x00, 0x42, 0x0e, 0x08, 0x5d, 0x01, 0xec, 0x16, 0x40, 0x89, 0xbc, - 0x00, 0x00, 0x42, 0x0e, 0x0b, 0x5d, 0x01, 0xec, 0x06, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x42, 0x0e, 0x80, 0x00, 0x00, 0x80, 0x42, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x78, 0x89, 0x1b, 0x87, 0x3c, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x92, 0xa1, 0x97, 0xbc, - 0x00, 0x00, 0x47, 0x0e, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x86, 0xbc, - 0x00, 0x00, 0x0a, 0x11, 0x00, 0x90, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a, - 0x00, 0x00, 0x3f, 0x11, 0x33, 0x01, 0x00, 0xf8, 0x82, 0x80, 0x2f, 0xb4, - 0x00, 0x00, 0x3f, 0x11, 0x9f, 0xf0, 0x01, 0x80, 0x82, 0xdb, 0x87, 0xbc, - 0x00, 0x00, 0x3f, 0x11, 0x9f, 0xf8, 0x01, 0x80, 0x22, 0x21, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x01, 0xe0, 0x06, 0x00, 0xee, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xe0, 0x06, 0xc0, 0x87, 0x32, - 0x00, 0x00, 0x3f, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x08, 0x00, 0x00, 0x80, 0x02, 0x80, 0x91, 0xbc, - 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x10, 0x00, 0xe2, 0x10, 0x00, 0x50, 0x01, 0x14, 0xa9, 0x9b, 0x91, 0xd9, - 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x14, 0x89, 0x0d, 0x6e, 0x37, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x30, 0x01, 0x14, 0x89, 0x5b, 0x91, 0xd2, - 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x2d, 0xd2, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x21, 0x01, 0x80, 0x82, 0x9b, 0x91, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x78, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x02, 0x80, 0x82, 0x9b, 0x97, 0xbc, - 0x00, 0x00, 0x71, 0x0e, 0x04, 0x21, 0x01, 0x30, 0x69, 0x24, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0xa9, 0x9b, 0x91, 0x3a, - 0x00, 0x00, 0x66, 0x0e, 0x1f, 0x40, 0x02, 0x24, 0x09, 0x40, 0x68, 0xb2, - 0x00, 0x00, 0x5c, 0x0e, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x41, 0x92, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xb9, 0x7f, 0x92, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x24, 0x90, 0x3c, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xa4, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x08, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x99, 0xa4, 0xfe, 0xd8, - 0x08, 0x00, 0x5c, 0x0e, 0x12, 0x01, 0x00, 0x68, 0x92, 0xa4, 0xfe, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xbc, - 0x00, 0x00, 0x6b, 0x0e, 0x38, 0x50, 0x01, 0x78, 0x09, 0x80, 0x6e, 0xb2, - 0x00, 0x00, 0x6b, 0x0e, 0x04, 0x28, 0x01, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x28, 0x01, 0x78, 0xe9, 0x25, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x08, 0x01, 0x00, 0x78, 0x69, 0xa4, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x66, 0x24, 0x6e, 0x3a, - 0x00, 0x00, 0x6e, 0x0e, 0x38, 0x20, 0x01, 0xe0, 0x06, 0x00, 0x93, 0xb2, - 0x00, 0x00, 0x6f, 0x0e, 0x00, 0x28, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x77, 0x0e, 0x38, 0x51, 0x01, 0x00, 0xa9, 0x9b, 0x91, 0xba, - 0x00, 0x00, 0x75, 0x0e, 0x04, 0x41, 0x02, 0x08, 0xb9, 0xff, 0x68, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x41, 0x02, 0x80, 0xe2, 0xc1, 0x68, 0xb6, - 0x00, 0x00, 0x72, 0x0e, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92, - 0x00, 0x00, 0x84, 0x0e, 0x9f, 0x31, 0x01, 0xe0, 0x66, 0x24, 0x6e, 0xbc, - 0x00, 0x00, 0x84, 0x0e, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x92, - 0x00, 0x00, 0x81, 0x0e, 0x04, 0x28, 0x01, 0x04, 0x09, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x50, 0x01, 0x80, 0xa2, 0x5b, 0x90, 0xbc, - 0x00, 0x00, 0x7f, 0x0e, 0x9f, 0x01, 0x00, 0x00, 0x19, 0x24, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x66, 0x24, 0x6e, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0x06, 0x24, 0x00, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0xe0, 0x06, 0x00, 0x93, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x8e, 0x0e, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xbc, - 0x00, 0x00, 0x84, 0x0e, 0x04, 0x41, 0x02, 0x08, 0xb9, 0xff, 0x68, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x41, 0x02, 0x80, 0xe2, 0xc1, 0x68, 0xb6, - 0x00, 0x00, 0x81, 0x0e, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92, - 0x00, 0x00, 0x88, 0x0e, 0x02, 0x00, 0x00, 0x80, 0x22, 0x24, 0x90, 0xbc, - 0x00, 0x00, 0x8e, 0x0e, 0x80, 0x40, 0x02, 0x80, 0xf2, 0xc1, 0x68, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x8c, 0xb6, 0xc1, 0x68, 0x35, - 0x00, 0x00, 0x8e, 0x0e, 0x00, 0x00, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0x94, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x97, 0xd2, - 0x08, 0x00, 0x8a, 0x11, 0x12, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0xb8, - 0x00, 0x00, 0x81, 0x0e, 0x04, 0x01, 0x00, 0x00, 0x29, 0x24, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x79, 0x0b, 0x16, 0x38, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x0b, 0x16, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x42, 0xe4, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xa9, 0x00, 0x2d, 0x37, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x89, 0x4d, 0x90, 0x3a, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x82, 0x0d, 0x91, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x12, 0xa4, 0x2a, 0x3a, - 0x00, 0x00, 0x99, 0x0e, 0x80, 0x40, 0x02, 0x80, 0xe2, 0x01, 0x7c, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x78, 0xb9, 0x3f, 0x7c, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe9, 0xa5, 0x90, 0x3a, - 0x00, 0x00, 0x9b, 0x0e, 0x9f, 0x01, 0x00, 0x10, 0x19, 0x00, 0x91, 0xbc, - 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x94, 0x0e, 0x04, 0x01, 0x00, 0x80, 0x42, 0xe4, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xc9, 0x24, 0x90, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x22, 0xa4, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x66, 0x24, 0x6e, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0xe0, 0x06, 0x00, 0x93, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x18, 0x00, 0xa5, 0x0e, 0x1f, 0x41, 0x02, 0x78, 0x88, 0xcd, 0x68, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x00, 0x2c, 0x3a, - 0x00, 0x00, 0xa8, 0x0e, 0x80, 0x01, 0x00, 0x80, 0x62, 0x80, 0x87, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x41, 0x02, 0x80, 0xb2, 0xff, 0x68, 0xb0, - 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x92, - 0x03, 0x00, 0x8a, 0x11, 0x04, 0x40, 0x02, 0x00, 0x38, 0x1a, 0xff, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x40, 0x02, 0x04, 0xb8, 0xff, 0x68, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0xb8, 0x1b, 0x80, 0x3a, - 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x00, 0x80, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xb6, 0x0e, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xb3, 0x0e, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32, - 0x1d, 0x00, 0xb6, 0x0e, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0xb0, 0x0e, 0x9f, 0x01, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x68, 0x00, 0x4c, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x70, 0x00, 0x18, 0x08, 0x00, 0x6e, 0xb2, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x10, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0xa9, 0x60, 0x81, 0xd9, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0xa2, 0xa0, 0x81, 0x7c, - 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xc1, 0x0e, 0x80, 0x01, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xc1, 0x0e, 0x1b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x62, 0xe0, 0x83, 0x7c, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35, - 0x00, 0xa0, 0x00, 0x00, 0x12, 0x01, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0x72, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xe4, 0x06, 0xc0, 0x2d, 0x32, - 0xee, 0xff, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x86, 0x8d, 0x2f, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xb3, 0xe4, 0x39, 0x32, - 0x00, 0x00, 0xcd, 0x0e, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x05, 0x30, 0x30, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe3, 0xa5, 0x03, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x33, 0x0b, 0x2f, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0x76, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xb9, 0x05, 0x30, 0x30, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0xe3, 0xa5, 0x03, 0x79, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xd8, 0x0e, 0x20, 0x00, 0x01, 0x2c, 0x09, 0xc0, 0x6e, 0xb2, - 0x00, 0x00, 0xd9, 0x0e, 0x00, 0x16, 0x86, 0xcc, 0x06, 0xc0, 0x92, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x86, 0xcc, 0x06, 0xc0, 0x92, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x40, 0x62, 0x8e, 0x92, 0x52, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xdf, 0x0e, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x42, 0x80, 0x97, 0xbc, - 0xdf, 0x0e, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x60, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0xb1, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x03, 0x00, 0x38, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x02, 0x00, 0x30, 0x32, - 0x00, 0x00, 0x22, 0x0f, 0x04, 0x00, 0x00, 0x24, 0xd8, 0x01, 0x30, 0xb6, - 0xe4, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0x4d, 0x82, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0xdf, 0x0e, 0x36, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xec, 0x0e, 0x00, 0x00, 0x00, 0x20, 0x48, 0x05, 0x30, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xf7, 0x0e, 0x32, 0x0f, 0x01, 0xbc, 0x08, 0xc0, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xdc, 0x02, 0x40, 0x6e, 0x32, - 0x00, 0x00, 0xf0, 0x0e, 0x1f, 0x01, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0xf6, 0x0e, 0x1d, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0xe0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37, - 0x20, 0xcd, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x87, 0xa0, 0xea, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0xea, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x38, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x26, 0x01, 0x6e, 0x35, - 0x00, 0x00, 0xfb, 0x0e, 0x80, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x8b, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0e, 0x82, 0x32, - 0x00, 0xe0, 0x03, 0x0f, 0x12, 0x01, 0x00, 0x48, 0xa2, 0x0d, 0x90, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x32, - 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0x00, 0x82, 0x37, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x10, 0x00, 0x00, 0x87, 0xbf, 0x97, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x40, 0xfe, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x89, 0x60, 0x38, 0x32, - 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa4, 0x17, 0x38, - 0x00, 0x00, 0x09, 0x0f, 0x80, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x8b, 0xb6, - 0x00, 0x00, 0x0a, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf3, 0x41, 0x90, 0x34, - 0x00, 0x00, 0x0f, 0x0f, 0x04, 0x00, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x05, 0x30, 0x30, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xa4, 0x03, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xce, 0x2c, 0x32, - 0x00, 0xe0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x0d, 0x90, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xdc, 0x02, 0x40, 0x6e, 0x32, - 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xa4, 0x17, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x32, 0x80, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x10, 0x01, 0x80, 0x22, 0x01, 0x6e, 0xb6, - 0x00, 0x00, 0x18, 0x0f, 0x1f, 0x01, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x20, 0x0f, 0x1d, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0xb2, - 0xe0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x00, 0x2d, 0x37, - 0x20, 0xcd, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x97, 0x3a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x37, 0x8b, 0xea, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0xea, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0x32, - 0xee, 0xff, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0xee, 0xff, 0x8a, 0x11, 0x04, 0x11, 0x01, 0x80, 0x82, 0x0d, 0x6e, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xf8, 0x02, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x01, 0xdc, 0x02, 0x40, 0x6e, 0x72, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x89, 0x4d, 0x0d, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x2b, 0x0f, 0x12, 0x00, 0x00, 0x4c, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x2c, 0x0f, 0x12, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x02, 0x90, 0x3a, - 0x00, 0x00, 0x28, 0x0f, 0x04, 0x01, 0x00, 0x04, 0x19, 0x40, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x3b, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x35, 0x0f, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x3a, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x22, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x80, 0x18, 0x00, 0x88, 0xbc, - 0x00, 0x00, 0x35, 0x0f, 0x12, 0x01, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x34, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x88, 0x1c, 0x83, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4c, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x08, 0x50, 0x00, 0x18, 0xc8, 0x20, 0x72, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x81, 0x7c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0x3c, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x20, 0x88, 0x01, 0x82, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x36, 0xbc, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0x4a, 0x09, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x19, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x72, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0xc0, 0x86, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0xc0, 0x84, 0x32, - 0x00, 0x00, 0xa3, 0x0f, 0x04, 0x00, 0x00, 0x28, 0xd8, 0xa0, 0x82, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x09, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd8, 0xa0, 0x81, 0x3c, - 0x00, 0x00, 0x67, 0x0f, 0x04, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc, - 0x00, 0x00, 0x58, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0x02, 0xc0, 0x38, 0xb2, - 0x00, 0x00, 0x60, 0x0f, 0x51, 0x00, 0x00, 0xd8, 0x12, 0x80, 0x2d, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x5e, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x59, 0x0f, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x65, 0x0f, 0x2a, 0x01, 0x00, 0x00, 0xd8, 0x20, 0x80, 0xba, - 0x00, 0x00, 0x64, 0x0f, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x4d, 0x0f, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x6e, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x68, 0x0f, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x78, 0x39, 0x9a, 0xfe, 0x38, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x97, 0xd2, - 0x08, 0x00, 0x8a, 0x11, 0x12, 0x40, 0x02, 0x68, 0x12, 0x9a, 0xfe, 0xb8, - 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x00, 0x00, 0x86, 0x0f, 0x1f, 0x00, 0x00, 0x6c, 0xd8, 0xe0, 0x86, 0xba, - 0x00, 0x00, 0xa3, 0x0e, 0x51, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0xf2, - 0x00, 0x00, 0x79, 0x0f, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x40, 0x80, 0x92, - 0x00, 0x00, 0x86, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x7e, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x7e, 0x0f, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x7e, 0x0f, 0x80, 0x01, 0x00, 0x80, 0x32, 0x80, 0x87, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xe2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0x4c, 0x0f, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x81, 0xbc, - 0x00, 0x00, 0x84, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x83, 0x0f, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x4d, 0x0f, 0x4d, 0x00, 0x00, 0x00, 0x67, 0xe0, 0x83, 0x9e, - 0x00, 0x00, 0x89, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xa7, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0xa8, 0x60, 0x8a, 0x3c, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x21, 0x01, 0x80, 0x82, 0x5b, 0x8a, 0xbc, - 0x00, 0x00, 0x8d, 0x0f, 0x2f, 0xa8, 0x01, 0x20, 0x99, 0x22, 0x6e, 0xba, - 0x00, 0x00, 0x2f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x02, 0x80, 0x82, 0x1b, 0x92, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x06, 0x00, 0x92, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0xe8, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x92, 0x0f, 0x23, 0x21, 0x01, 0xe0, 0x06, 0x00, 0x00, 0xb2, - 0x3c, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x30, 0x00, 0xe0, 0x06, 0x80, 0x82, 0xb2, - 0x00, 0x00, 0x9c, 0x0f, 0x04, 0x21, 0x00, 0xe0, 0x06, 0x80, 0x81, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xe2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x9a, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x99, 0x0f, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x32, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0xb7, 0x0e, 0x00, 0x60, 0x00, 0x6c, 0x08, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xe0, 0x06, 0x80, 0x81, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xe8, 0x06, 0x40, 0x81, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x10, 0x00, 0xe0, 0x06, 0xc0, 0x86, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x2a, 0x19, 0x00, 0xe0, 0x06, 0xc0, 0x84, 0x72, - 0x00, 0x00, 0xa1, 0x0f, 0x12, 0x01, 0x00, 0x00, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x1d, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xa4, 0x17, 0xb8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0x75, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xd8, 0xe0, 0x83, 0x3c, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x00, 0x2c, 0x3a, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x32, - 0xee, 0x05, 0xaf, 0x0f, 0x04, 0x01, 0x00, 0x80, 0x82, 0x4d, 0xf5, 0xbc, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xb1, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x09, 0xc0, 0x09, 0x92, - 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x80, 0x09, 0x32, - 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x87, 0xcd, 0x00, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x60, 0xc0, 0x07, 0x80, 0x97, 0x32, - 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x8d, 0x2a, 0x3a, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x52, 0x81, 0x97, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x24, 0x90, 0x3a, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x0d, 0x90, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x19, 0x40, 0x90, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x52, 0x82, 0x2a, 0x3a, - 0x00, 0x08, 0xb1, 0x0f, 0x02, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2a, 0xbc, - 0x00, 0x00, 0xc2, 0x0f, 0x06, 0x00, 0x00, 0x80, 0x02, 0x40, 0x90, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x20, 0xb2, - 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x87, 0xcd, 0x00, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x07, 0x80, 0x97, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x5c, 0x52, 0x81, 0x2a, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x24, 0x90, 0x3a, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x0d, 0x90, 0x36, - 0x00, 0x00, 0xbb, 0x0f, 0x04, 0x01, 0x00, 0x04, 0x19, 0x40, 0x90, 0xbc, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x89, 0x0d, 0x90, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0e, 0x80, 0x97, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0x80, 0x97, 0xb2, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x89, 0x0d, 0x90, 0x36, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x89, 0x4d, 0x92, 0x3c, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0x4d, 0x92, 0x36, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x89, 0x4d, 0x92, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x18, 0x9b, 0x81, 0xb2, 0xe4, 0x78, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x9b, 0x8d, 0xb7, 0xe4, 0x78, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0e, 0x80, 0x97, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x24, 0x90, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x59, 0x00, 0x90, 0x36, - 0x00, 0x00, 0xc4, 0x0f, 0x95, 0x01, 0x00, 0x80, 0x22, 0x24, 0x90, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xec, 0x0f, 0x04, 0x01, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0x29, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xb2, 0x45, 0x28, 0x30, - 0x00, 0x00, 0xdd, 0x0f, 0x86, 0x01, 0x00, 0x08, 0x09, 0x80, 0x2f, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x09, 0x40, 0x81, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00, 0x32, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x80, 0x92, 0x32, - 0x00, 0x00, 0xdc, 0x0f, 0x04, 0x07, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0xbc, - 0x00, 0x00, 0xe7, 0x0f, 0xc3, 0x07, 0x01, 0xec, 0xb6, 0xe4, 0x6e, 0x9a, - 0x00, 0x00, 0xe7, 0x0f, 0x00, 0x06, 0x01, 0xec, 0xb6, 0xe4, 0x6e, 0x9a, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x52, 0x80, 0x90, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x09, 0x05, 0x80, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00, 0x32, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x80, 0x92, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xf2, 0xc1, 0x92, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xfa, 0x92, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xfa, 0x92, 0xbc, - 0x44, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x8d, 0x2f, 0xd2, - 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x92, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0x32, - 0x00, 0x00, 0xec, 0x0f, 0x04, 0x01, 0x00, 0x78, 0xd9, 0x01, 0x30, 0xb6, - 0x00, 0x00, 0xd4, 0x0f, 0x00, 0x00, 0x00, 0x9c, 0xb2, 0x45, 0x28, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x22, 0x80, 0x97, 0x7c, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0xe8, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0xc0, 0xe8, 0x32, - 0x02, 0x00, 0xf1, 0x0f, 0xb0, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0xb9, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xab, 0xe4, 0xb0, 0x32, - 0x00, 0x00, 0xf6, 0x0f, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x4a, 0xd0, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x28, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0xf9, 0x0f, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0xf8, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x80, 0x01, 0x00, 0xf8, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x4a, 0xd0, 0xb6, - 0x00, 0x00, 0x00, 0x10, 0x04, 0x01, 0x00, 0x28, 0x09, 0x34, 0xb0, 0xba, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xc2, 0x4a, 0xd0, 0xb6, - 0x00, 0x00, 0xfd, 0x0f, 0xb0, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52, - 0x00, 0x00, 0x00, 0x10, 0xb0, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x2b, 0xb7, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x84, 0xc0, 0x37, 0xac, 0xb0, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x32, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x4d, 0xb0, 0x30, - 0x00, 0x00, 0x08, 0x10, 0x80, 0x00, 0x00, 0x80, 0x02, 0x40, 0xb0, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x12, 0x40, 0xb0, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x69, 0x81, 0x97, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08, 0x0b, 0x00, 0x7c, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x25, 0x01, 0x32, - 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x2a, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0xb0, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0x54, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x0e, 0x10, 0xb0, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xab, 0xe4, 0xb0, 0x32, - 0x00, 0x00, 0x13, 0x10, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0xd0, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x28, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x16, 0x10, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0xf8, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x80, 0x01, 0x00, 0xf8, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0x0d, 0x40, 0xd0, 0x34, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0xd0, 0xb6, - 0x00, 0x00, 0x1d, 0x10, 0x04, 0x01, 0x00, 0x28, 0x09, 0x34, 0xb0, 0xba, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x02, 0x40, 0xd0, 0xb6, - 0x00, 0x00, 0x1a, 0x10, 0xb0, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x04, 0x0d, 0x40, 0xd0, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52, - 0x00, 0x00, 0x1d, 0x10, 0xb0, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x84, 0xc0, 0x37, 0xac, 0xb0, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x32, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x4d, 0xb0, 0x30, - 0x00, 0x00, 0x25, 0x10, 0x80, 0x00, 0x00, 0x80, 0x02, 0x40, 0xb0, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x12, 0x40, 0xb0, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x69, 0x81, 0x97, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x08, 0x0b, 0x00, 0x7c, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x25, 0x01, 0x32, - 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x2a, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0xb0, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0x54, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x1c, 0x41, 0x02, 0x80, 0x06, 0xc0, 0x92, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x92, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x97, 0xd2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x92, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x0b, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x3a, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x92, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0xb0, 0x02, 0xc0, 0x6e, 0x32, - 0x00, 0x82, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x80, 0x36, 0x52, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x38, 0x80, 0x87, 0x35, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x80, 0x87, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0xe0, 0x16, 0x20, 0x6e, 0x3c, - 0x08, 0x00, 0x00, 0x00, 0xd2, 0x01, 0x00, 0x78, 0xe9, 0xe5, 0x83, 0x39, - 0x18, 0x00, 0x8a, 0x11, 0x1f, 0x41, 0x02, 0x84, 0xe6, 0xa1, 0x97, 0xb9, - 0x00, 0x00, 0x43, 0x10, 0x36, 0x51, 0x01, 0xe8, 0x16, 0xe0, 0x83, 0xbc, - 0x00, 0x00, 0x43, 0x10, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x45, 0x10, 0x38, 0x21, 0x01, 0xe0, 0x06, 0x40, 0x80, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0xe0, 0x06, 0x40, 0x80, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x72, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x92, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0xd5, 0x08, 0x00, 0x00, 0x07, 0x80, 0x92, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32, - 0x00, 0x40, 0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x41, 0x01, 0xe0, 0x06, 0x80, 0x92, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x48, 0x02, 0xc0, 0x80, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xe8, 0x01, 0x00, 0x74, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x62, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0x80, 0x92, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x3d, 0x00, 0x0c, 0x07, 0x80, 0x83, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0x02, 0xc0, 0x80, 0x72, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x57, 0x01, 0x80, 0x02, 0xc0, 0x6e, 0x7c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x01, 0xec, 0x06, 0x80, 0x92, 0x72, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xd1, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x38, 0xf2, - 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x10, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x19, 0xa0, 0x2c, 0xd9, - 0x00, 0x00, 0x60, 0x10, 0x9d, 0x11, 0x02, 0x0c, 0x09, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x61, 0x10, 0x00, 0xf0, 0x01, 0x1c, 0x09, 0x00, 0x6e, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x01, 0x1c, 0x09, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x63, 0x10, 0x2c, 0xcd, 0x01, 0x18, 0x09, 0x80, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xc9, 0xc1, 0x90, 0x34, - 0x00, 0x00, 0x67, 0x10, 0x3b, 0x29, 0x02, 0x04, 0x09, 0x80, 0x6e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0xd6, 0x01, 0x80, 0x52, 0xc0, 0x6e, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x01, 0xec, 0x56, 0xc0, 0x6e, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xb9, 0xc1, 0x90, 0x34, - 0x00, 0x00, 0x77, 0x10, 0x00, 0xa8, 0x01, 0x08, 0x09, 0x00, 0x6e, 0xf2, - 0x00, 0x00, 0x6b, 0x10, 0x9d, 0x01, 0x00, 0x80, 0x17, 0xe0, 0x90, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x80, 0x07, 0xc0, 0x91, 0x32, - 0x00, 0x00, 0x6e, 0x10, 0x00, 0x38, 0x00, 0x80, 0x07, 0x00, 0xee, 0x92, - 0x00, 0x00, 0x6e, 0x10, 0x04, 0x01, 0x00, 0x80, 0x02, 0xc0, 0x91, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x01, 0xe0, 0x06, 0x00, 0xee, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x01, 0xe0, 0x06, 0x00, 0x86, 0x32, - 0x00, 0x00, 0x71, 0x10, 0x39, 0x08, 0x00, 0x80, 0x07, 0xc0, 0x85, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xc2, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xd9, 0xc9, 0x01, 0xe8, 0x06, 0x80, 0x91, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xc8, 0x11, 0x00, 0x80, 0x07, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x74, 0x10, 0x3b, 0x21, 0x00, 0x80, 0x07, 0x00, 0x86, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x60, 0x18, 0x00, 0x86, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x58, 0x78, 0x01, 0xe0, 0x16, 0x20, 0x86, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x80, 0x07, 0x00, 0x85, 0x72, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x7b, 0x10, 0x02, 0x0c, 0x02, 0x80, 0xa2, 0x9b, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x78, 0x29, 0x00, 0x6e, 0x36, - 0x00, 0x00, 0x7b, 0x10, 0x02, 0x00, 0x00, 0x80, 0xe2, 0xa5, 0x90, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x78, 0x49, 0x21, 0x6e, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe9, 0xa5, 0x90, 0x3f, - 0x00, 0x00, 0x82, 0x10, 0x04, 0x20, 0x02, 0x08, 0x89, 0x9b, 0x90, 0xbe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0x58, 0xb8, 0x9b, 0x90, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x49, 0xa1, 0x90, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x9f, 0x88, 0x01, 0x80, 0x82, 0x9b, 0x97, 0x7c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x01, 0xe0, 0x06, 0x80, 0x97, 0x72, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x02, 0x58, 0xb8, 0x9b, 0x90, 0x76, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8b, 0x10, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x89, 0x10, 0x12, 0x01, 0x00, 0x78, 0x09, 0xc0, 0x21, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8b, 0x10, 0xca, 0x00, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x92, - 0x15, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x78, 0xe9, 0x65, 0x17, 0xb8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0x35, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x88, 0x1c, 0x83, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4c, 0x08, 0x00, 0x72, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x08, 0x50, 0x00, 0x18, 0xc8, 0x20, 0x72, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x62, 0xa0, 0x82, 0x7c, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x00, 0x00, 0x14, 0x18, 0x40, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x00, 0x00, 0x20, 0x88, 0x01, 0x82, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x02, 0x00, 0x36, 0xbc, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x77, 0x4a, 0x09, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x82, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x19, 0x00, 0x00, 0x07, 0x40, 0x82, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0xc1, 0x38, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd8, 0x02, 0x40, 0x84, 0x72, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x85, 0xd2, - 0x00, 0x00, 0xa6, 0x10, 0x80, 0x01, 0x00, 0x80, 0xf2, 0xc1, 0x85, 0xb6, - 0x00, 0x00, 0xa2, 0x10, 0x1f, 0x40, 0x02, 0x84, 0xe6, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0xa6, 0x10, 0x1d, 0x01, 0x00, 0xf8, 0x22, 0x81, 0x2f, 0xb4, - 0x00, 0x00, 0xa6, 0x10, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x95, - 0x00, 0x00, 0xa4, 0x10, 0x1d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x62, 0x81, 0x2f, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x80, 0x02, 0x40, 0x68, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x1f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x73, 0x11, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc5, 0x85, 0xd0, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x68, 0x02, 0xc5, 0x85, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0xc5, 0x85, 0x30, - 0x00, 0x00, 0x8a, 0x11, 0x02, 0x01, 0x00, 0x80, 0x82, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x06, 0x01, 0x00, 0x80, 0x92, 0xba, 0x97, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x5c, 0x1f, 0xc0, 0xf5, 0x7a, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0x70, - 0x29, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x02, 0x81, 0x2f, 0x74, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x80, 0xa8, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0x70, - 0x00, 0x00, 0xb7, 0x10, 0x80, 0x01, 0x00, 0x80, 0xd2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x72, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0xba, 0x10, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x72, 0x81, 0x2f, 0x34, - 0x3b, 0x00, 0xba, 0x10, 0x12, 0x01, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xba, 0x10, 0x80, 0x01, 0x00, 0x80, 0xf2, 0x80, 0x2f, 0xb6, - 0x30, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0xbd, 0x10, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x81, 0x2f, 0x94, - 0x00, 0x00, 0xbd, 0x10, 0x80, 0x01, 0x00, 0x80, 0xb2, 0x80, 0x2f, 0xb6, - 0x34, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x42, 0x81, 0x2f, 0x34, - 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x82, 0x8d, 0x2f, 0x70, - 0x02, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0x70, - 0x3a, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x2c, 0x82, 0xcd, 0x2e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x12, 0x81, 0x2f, 0x74, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x65, 0x01, 0x80, 0xa2, 0xdb, 0x2c, 0xbc, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x39, - 0xee, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0x71, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xcb, 0x10, 0x00, 0x00, 0x01, 0x38, 0x08, 0xc0, 0x6e, 0xf2, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0x02, 0xc0, 0x80, 0x72, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xcd, 0x10, 0x04, 0x38, 0x01, 0x78, 0x09, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x11, 0x00, 0x00, 0x07, 0x80, 0x82, 0x32, - 0x00, 0x00, 0xd1, 0x10, 0x2e, 0x19, 0x00, 0x00, 0x07, 0x80, 0x97, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe9, 0x81, 0x92, 0x34, - 0x00, 0x00, 0xd5, 0x10, 0x27, 0x31, 0x00, 0x00, 0x07, 0xc0, 0x2c, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0xd5, 0x08, 0x00, 0x00, 0x07, 0x00, 0x87, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x28, 0xe9, 0x80, 0x92, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0xe7, 0xa0, 0x92, 0x79, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x90, 0xd2, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x44, 0x12, 0xe4, 0x38, 0xb2, - 0x18, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x03, 0xf9, - 0x00, 0x00, 0xdf, 0x10, 0x04, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0xda, 0x10, 0x67, 0x00, 0x00, 0xf8, 0xa2, 0x80, 0x2f, 0xb5, - 0x00, 0x00, 0x8a, 0x11, 0x12, 0x00, 0x00, 0xe8, 0x02, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0x72, 0x80, 0x2d, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xd8, 0x02, 0x40, 0x00, 0x72, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x79, 0x0a, 0x91, 0x39, - 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x39, 0x0b, 0x91, 0x39, - 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x59, 0x0a, 0x91, 0x39, - 0x09, 0x00, 0xe5, 0x10, 0xf1, 0x01, 0x00, 0x10, 0x69, 0x0b, 0x91, 0xb9, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x24, 0x86, 0xa8, 0x82, 0x8d, 0x6c, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe0, 0x07, 0x00, 0x91, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe0, 0x07, 0x40, 0x91, 0x32, - 0x00, 0x80, 0xeb, 0x10, 0x02, 0x01, 0x00, 0x80, 0x82, 0x8d, 0x2a, 0xbc, - 0x00, 0x00, 0xec, 0x10, 0xe1, 0x24, 0x86, 0xc8, 0x06, 0x00, 0x00, 0x92, - 0x03, 0x00, 0x00, 0x00, 0xe1, 0x24, 0x86, 0xc8, 0x86, 0x8d, 0x2a, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xf4, 0x10, 0x04, 0x30, 0x00, 0x80, 0x82, 0x9b, 0x81, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0x3c, 0x00, 0x14, 0x28, 0x80, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x02, 0x80, 0x2f, 0x35, - 0x00, 0xa0, 0x8a, 0x11, 0x12, 0x00, 0x00, 0x40, 0xa2, 0x8d, 0x39, 0xb2, - 0x00, 0x00, 0xf6, 0x10, 0x80, 0x39, 0x00, 0x80, 0xe2, 0x80, 0x6e, 0xb6, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x38, 0x00, 0x80, 0xf2, 0x80, 0x6e, 0xb6, - 0x00, 0xe0, 0x8a, 0x11, 0x04, 0x01, 0x00, 0x80, 0xa2, 0x8d, 0x2f, 0xb0, - 0x00, 0xe0, 0xfd, 0x10, 0x04, 0x38, 0x00, 0x78, 0x89, 0x8d, 0x6e, 0xb0, - 0x10, 0x00, 0xfd, 0x10, 0x9f, 0x01, 0x00, 0xf8, 0xe2, 0xa5, 0x2f, 0xb9, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0xee, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0x82, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0xec, 0x06, 0xc0, 0xee, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0x00, 0x18, 0x09, 0x00, 0x6e, 0x72, - 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x2f, 0x0e, 0x00, 0xa8, 0x01, 0x20, 0x09, 0x00, 0x6e, 0x92, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xa9, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x04, 0xb0, 0x00, 0x80, 0x82, 0x9b, 0x81, 0x7c, - 0x00, 0x00, 0x8a, 0x11, 0x0d, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x9f, 0xbc, 0x00, 0x14, 0x28, 0x80, 0x6e, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xca, 0x01, 0x00, 0xf8, 0x42, 0x80, 0x2f, 0x35, - 0x08, 0xa0, 0x00, 0x00, 0x12, 0x01, 0x00, 0x40, 0xa2, 0xcd, 0x39, 0x72, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x80, 0x90, 0xd2, - 0x00, 0x00, 0x0f, 0x11, 0x33, 0xcd, 0x01, 0xbc, 0x08, 0x80, 0x6e, 0xb2, - 0x00, 0x00, 0x4e, 0x11, 0x00, 0x00, 0x00, 0x28, 0x29, 0x22, 0xee, 0xdc, - 0x00, 0x00, 0x14, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x14, 0x11, 0x04, 0xb8, 0x01, 0x28, 0x09, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x14, 0x11, 0x9f, 0x71, 0x01, 0x80, 0xc2, 0x21, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xa9, 0x24, 0xee, 0x3c, - 0x00, 0x00, 0x4e, 0x11, 0x00, 0x00, 0x00, 0x28, 0x19, 0x80, 0x92, 0xdf, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x28, 0x11, 0x06, 0x80, 0x01, 0x80, 0x82, 0x9b, 0x90, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x90, 0xbc, - 0xee, 0x05, 0x20, 0x11, 0x06, 0x0c, 0x02, 0x80, 0x82, 0x8d, 0x6e, 0xbc, - 0x00, 0x90, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x84, 0x02, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x1a, 0x11, 0xb8, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x18, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x03, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0xe0, 0x96, 0x21, 0x6e, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x61, 0x98, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x78, 0x49, 0x40, 0x3c, 0x37, - 0x00, 0x00, 0x2d, 0x11, 0x00, 0x00, 0x00, 0x08, 0xe9, 0xa5, 0x90, 0x9a, - 0x60, 0x89, 0x20, 0x00, 0x00, 0x00, 0x00, 0x84, 0x02, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x23, 0x11, 0xb8, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0xb0, - 0x00, 0x00, 0x21, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x03, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0xe0, 0x96, 0x21, 0x6e, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x61, 0x98, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x2d, 0x11, 0xa8, 0x00, 0x00, 0x08, 0x19, 0x8f, 0x90, 0x9a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x99, 0xa1, 0x89, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe9, 0xa5, 0x90, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0xe0, 0x96, 0x21, 0x6e, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0x61, 0x98, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x01, 0xec, 0x06, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x30, 0x11, 0x06, 0x00, 0x00, 0x80, 0x72, 0xa2, 0x90, 0xbc, - 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x80, 0x01, 0xe0, 0x06, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0xc0, 0x89, 0x32, - 0x00, 0x00, 0x36, 0x11, 0x04, 0x79, 0x01, 0x80, 0x82, 0x1b, 0x87, 0xbc, - 0x00, 0x00, 0x34, 0x11, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0xe0, 0x06, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x92, 0x81, 0x2f, 0x75, - 0x00, 0x00, 0x3c, 0x11, 0x80, 0x00, 0x00, 0x80, 0x52, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x3c, 0x11, 0xd5, 0x41, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x92, - 0x00, 0x00, 0x39, 0x11, 0x3c, 0x90, 0x01, 0xe0, 0x06, 0x80, 0x90, 0xb2, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x01, 0x00, 0x80, 0x92, 0x81, 0x2f, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x01, 0xe8, 0x06, 0xc0, 0x8b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x95, 0x01, 0x00, 0x80, 0x02, 0x80, 0x2f, 0x72, - 0x00, 0x00, 0x3d, 0x11, 0x9f, 0x41, 0x01, 0x80, 0x82, 0x1b, 0x87, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0xd9, 0x90, 0x01, 0xe0, 0x06, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x72, 0x80, 0x2f, 0x74, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0x40, 0x87, 0xd2, - 0x00, 0x00, 0x47, 0x11, 0x9f, 0xd8, 0x01, 0x80, 0x22, 0x21, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x47, 0x11, 0x9f, 0xe0, 0x01, 0x80, 0xc2, 0x21, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x47, 0x11, 0x9f, 0xb0, 0x01, 0x80, 0xd2, 0x21, 0x6e, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x49, 0x11, 0x06, 0x68, 0x01, 0x80, 0x82, 0x5b, 0x87, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0xe0, 0x06, 0x40, 0x87, 0x32, - 0x00, 0x00, 0x4b, 0x11, 0x37, 0xb0, 0x01, 0xe0, 0x06, 0x40, 0x87, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd2, 0x80, 0x2f, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x01, 0xe0, 0x06, 0x80, 0x84, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x01, 0xe0, 0x06, 0x00, 0x87, 0x72, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x08, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xbc, - 0x00, 0x00, 0x5b, 0x11, 0x04, 0xc1, 0x01, 0x84, 0x02, 0x00, 0x6e, 0xb2, - 0x05, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xe8, 0x86, 0x8d, 0x92, 0x37, - 0x03, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x01, 0xe8, 0x86, 0x8d, 0x92, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x30, - 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x2c, 0x89, 0x8d, 0x6e, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x01, 0x2c, 0xa9, 0xdb, 0x92, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x29, 0xc0, 0x92, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x19, 0xfb, 0x92, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x29, 0x80, 0x92, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xa9, 0xe4, 0x92, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x6f, 0xcc, 0x01, 0xe8, 0x26, 0xfb, 0x92, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x02, 0x80, 0x92, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x06, 0x40, 0x28, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x6f, 0xcc, 0x01, 0xe8, 0x86, 0xcd, 0x2a, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x01, 0xe0, 0x06, 0x00, 0x00, 0x52, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0xb0, 0x00, 0x80, 0x02, 0x00, 0x6e, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0xbc, 0x08, 0x00, 0x6e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0xbc, 0x88, 0xdb, 0x8b, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0xbc, 0x88, 0xdb, 0x8b, 0x3a, - 0x00, 0x00, 0x6a, 0x11, 0x9f, 0x00, 0x00, 0xbc, 0x88, 0xe1, 0x8b, 0xbc, - 0x00, 0x00, 0x6a, 0x11, 0x04, 0x0c, 0x02, 0x40, 0xa8, 0xdb, 0x8b, 0xbe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x04, 0x88, 0x1b, 0x84, 0x3e, - 0x00, 0x00, 0x69, 0x11, 0x04, 0xb1, 0x00, 0x80, 0x82, 0x5b, 0x80, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0xc2, 0x80, 0x2f, 0x74, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x02, 0x80, 0xa2, 0x5b, 0x80, 0x7c, - 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x14, 0x09, 0xc0, 0x8b, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x12, 0x00, 0x2c, 0x3a, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x04, 0x65, 0x01, 0x80, 0xa2, 0xdb, 0x2c, 0xbc, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x00, 0x00, 0x80, 0xa2, 0x80, 0x2f, 0xb6, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x01, 0xe8, 0x76, 0x20, 0x81, 0x39, - 0xee, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf8, 0x82, 0x8d, 0x2f, 0x71, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xd9, 0x4a, 0x91, 0x39, - 0x39, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x09, 0x45, 0x91, 0x30, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x89, 0x4d, 0x91, 0x36, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x89, 0xcd, 0x93, 0x3c, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0xcd, 0x93, 0x36, - 0x07, 0x00, 0x79, 0x11, 0xf3, 0x01, 0x00, 0x40, 0x89, 0xcd, 0x93, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x18, 0x9b, 0x81, 0x02, 0xe5, 0x78, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xe3, 0x18, 0x9b, 0x8d, 0x07, 0xe5, 0x78, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xd9, 0x4a, 0x91, 0x39, - 0x3a, 0x00, 0xe2, 0x10, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x36, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x09, 0x45, 0x91, 0x30, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x89, 0x4d, 0x91, 0x36, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x89, 0xcd, 0x93, 0x3c, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x82, 0xcd, 0x93, 0x36, - 0x07, 0x00, 0x84, 0x11, 0xf3, 0x01, 0x00, 0x40, 0x89, 0xcd, 0x93, 0xb0, - 0x00, 0x00, 0x8a, 0x11, 0x80, 0x19, 0x9b, 0x81, 0x02, 0xe5, 0x78, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0xe3, 0x18, 0x9b, 0x8d, 0x07, 0xe5, 0x78, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x8a, 0x11, 0x00, 0x00, 0x00, 0xb4, 0x0f, 0x40, 0xfb, 0x94, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x0f, 0x40, 0x2b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x28, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x0f, 0x00, 0x29, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x0f, 0x40, 0x18, 0x32, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x5f, 0xca, 0xf9, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0xc0, 0xf9, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x32, - 0x41, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x32, - 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0f, 0x80, 0x2a, 0x32, - 0x4c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32, - 0x98, 0x11, 0x97, 0x12, 0x00, 0x00, 0x00, 0xb0, 0x0f, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x01, 0x84, 0x12, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x36, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x80, 0x2a, 0x32, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0f, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0xc0, 0xfa, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0xf9, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0xfa, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0xfa, 0x32, - 0x00, 0x00, 0xac, 0x11, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0xfa, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0xfb, 0x32, - 0x01, 0x00, 0xcf, 0x11, 0x04, 0x01, 0x00, 0xb4, 0x8f, 0x4d, 0xfb, 0xb0, - 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xab, 0xcd, 0xb0, 0x32, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x5b, 0xca, 0xb0, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x2b, 0xfe, 0xb0, 0x32, - 0x00, 0x00, 0xaa, 0x11, 0x12, 0x01, 0x00, 0x80, 0x02, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0xbe, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x01, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe0, 0x07, 0x80, 0x3f, 0x52, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x8a, 0x02, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x53, 0x0a, 0x16, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x80, 0x90, 0x32, - 0xa2, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x37, 0x32, - 0xb9, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x03, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x83, 0x0d, 0x00, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0x0d, 0x00, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x53, 0x0a, 0x00, 0x34, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0xf9, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0xfa, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x40, 0xfa, 0x32, - 0x00, 0x00, 0xc9, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0x39, - 0x00, 0x00, 0xc0, 0x11, 0x80, 0x01, 0x00, 0x80, 0x12, 0x40, 0xb0, 0xb6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3b, 0x40, 0xb0, 0x33, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x35, - 0x00, 0x00, 0xc4, 0x11, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x40, 0x90, 0x92, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0x39, - 0x00, 0x00, 0xc4, 0x11, 0x00, 0x00, 0x00, 0x04, 0x6b, 0x41, 0x90, 0x94, - 0x00, 0x00, 0xc4, 0x11, 0x12, 0x00, 0x00, 0x00, 0x09, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0xc5, 0x11, 0x12, 0x00, 0x00, 0x04, 0x09, 0x40, 0x20, 0xb2, - 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0xe4, 0x16, 0x38, - 0x00, 0x00, 0xc9, 0x11, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0xc8, 0x11, 0x12, 0x00, 0x00, 0x08, 0x09, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x02, 0x00, 0xc4, 0x11, 0x04, 0x01, 0x00, 0xbc, 0x0f, 0x24, 0x17, 0xb8, - 0x06, 0x00, 0xc2, 0x11, 0x04, 0x00, 0x00, 0xbc, 0x0f, 0x64, 0x16, 0xb8, - 0x00, 0x00, 0xbd, 0x11, 0x04, 0x00, 0x00, 0x80, 0x22, 0xc0, 0xfb, 0xbc, - 0x20, 0x00, 0xc4, 0x11, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfb, 0xbc, - 0x00, 0x00, 0xd7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0xd1, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x82, 0xcd, 0xf9, 0x3a, - 0x00, 0x00, 0xb7, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xf7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xf8, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xfc, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x04, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x32, - 0x40, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x80, 0x2a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x40, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xde, 0x11, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x80, 0x90, 0x32, - 0x00, 0x00, 0xde, 0x11, 0x12, 0x00, 0x00, 0x40, 0xf2, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0x32, - 0x00, 0x00, 0xe0, 0x11, 0x12, 0x00, 0x00, 0x9c, 0x0f, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x00, 0x7e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0xfa, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32, - 0x4c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x80, 0x2a, 0x32, - 0x00, 0x00, 0xad, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0xb3, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xcb, 0xc1, 0xb0, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xef, 0x0f, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0xb0, 0xd2, - 0x00, 0x00, 0xeb, 0x11, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xb2, - 0x00, 0x00, 0xef, 0x11, 0x12, 0x00, 0x00, 0x9c, 0x0f, 0xc0, 0x21, 0xb2, - 0x02, 0x00, 0xf2, 0x11, 0x04, 0x01, 0x00, 0xb4, 0x8f, 0x4d, 0xfb, 0xb0, - 0x00, 0x00, 0xc4, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x93, 0x40, 0x01, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x1f, 0x40, 0xfb, 0x35, - 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x03, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x00, 0x34, - 0x00, 0x00, 0xeb, 0x11, 0x00, 0x00, 0x00, 0x0c, 0x8b, 0xc1, 0xb0, 0x94, - 0x00, 0x00, 0xbb, 0x12, 0x00, 0x08, 0x00, 0x00, 0x07, 0x40, 0xfa, 0x92, - 0x00, 0x00, 0xad, 0x12, 0x00, 0x08, 0x00, 0x00, 0x07, 0x40, 0xfa, 0xd2, - 0x00, 0x00, 0xf9, 0x11, 0x12, 0x00, 0x00, 0x50, 0xf2, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0xb4, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0xbd, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0xb0, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x12, 0x00, 0x2a, 0x3a, - 0x00, 0x00, 0xff, 0x11, 0x04, 0x01, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0xbc, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xba, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x0c, 0x12, 0x04, 0x01, 0x00, 0x80, 0x02, 0x40, 0xfa, 0xb2, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x0e, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x1b, 0x12, 0x00, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0xd2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x3c, 0x32, - 0x00, 0x00, 0x08, 0x12, 0x8e, 0x01, 0x00, 0x80, 0x02, 0x40, 0x28, 0xb2, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xf7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x8f, 0x4d, 0xfa, 0x3a, - 0x00, 0x00, 0xf7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32, - 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x08, 0x00, 0x10, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32, - 0x0e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x0b, 0x00, 0x14, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32, - 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x27, 0x00, 0x18, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32, - 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x20, 0x00, 0x1d, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x03, 0xc0, 0xf9, 0x32, - 0x0d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0xc0, 0xfa, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x3e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0x5a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0xc0, 0xf9, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x3e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0x3a, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xac, 0x8f, 0xcd, 0xf9, 0x50, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x2b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x3e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x12, 0x00, 0x2b, 0x3a, - 0x0f, 0x00, 0x2b, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0x0d, 0x2b, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x3e, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x02, 0xc0, 0xf9, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x3a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x3a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x3a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x3a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x2b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x3d, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x3d, 0x32, - 0x00, 0x00, 0x36, 0x12, 0x84, 0x01, 0x00, 0xb0, 0x12, 0x00, 0x2b, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x02, 0xc0, 0xf9, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32, - 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x73, 0x3e, 0x00, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x30, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0x3a, - 0x70, 0x00, 0x3b, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xf9, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x30, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x30, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0xc0, 0x29, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0xc0, 0xf9, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0xc0, 0x2c, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0xfa, 0x32, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x73, 0x7e, 0xfa, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x30, 0x32, - 0x00, 0x00, 0x44, 0x12, 0x85, 0x01, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x25, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x0e, 0x00, 0x53, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfa, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x4d, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x3f, 0xc0, 0xf9, 0x9a, - 0x1c, 0x00, 0x4d, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfa, 0xbc, - 0x02, 0x00, 0x25, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x8f, 0xcd, 0xf9, 0xda, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x37, 0x32, - 0x00, 0x00, 0x25, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x0e, 0x00, 0x5b, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfa, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x57, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0x9a, - 0x26, 0x00, 0x57, 0x12, 0x04, 0x01, 0x00, 0x80, 0x82, 0xcd, 0xfa, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0f, 0x40, 0x29, 0x32, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x56, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x29, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x18, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x00, 0x32, - 0xa2, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x37, 0x32, - 0x6b, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x03, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x80, 0x2a, 0x32, - 0x00, 0x00, 0x6b, 0x12, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x29, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x83, 0x3e, 0x00, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0x3e, 0x00, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x53, 0x0a, 0x00, 0x34, - 0x00, 0x00, 0x6c, 0x12, 0x00, 0x00, 0x00, 0x88, 0x0f, 0x40, 0x2b, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x28, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x0f, 0x00, 0x29, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0f, 0x80, 0x2a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0xc0, 0xf9, 0x32, - 0x71, 0x12, 0x97, 0x12, 0x00, 0x00, 0x00, 0xb0, 0x0f, 0x00, 0x36, 0x92, - 0x07, 0x00, 0x74, 0x12, 0x04, 0x00, 0x00, 0x80, 0x82, 0x4d, 0x29, 0xbc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x1f, 0x00, 0xfa, 0x3a, - 0x00, 0x00, 0x68, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x80, 0x2a, 0x92, - 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x0f, 0x00, 0x36, 0x32, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x84, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x1f, 0x00, 0x7a, 0x12, 0x04, 0x00, 0x00, 0x80, 0x82, 0xcd, 0x29, 0xbc, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x8f, 0xcd, 0xfa, 0x3a, - 0x00, 0x00, 0x76, 0x12, 0x00, 0x00, 0x00, 0x9c, 0x12, 0xc0, 0x29, 0x9a, - 0x00, 0x00, 0x3a, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x30, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x82, 0x12, 0x04, 0x00, 0x00, 0x80, 0x52, 0x8a, 0xfa, 0xbc, - 0xa2, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x37, 0x32, - 0x82, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x03, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa3, 0x3e, 0x00, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xa3, 0x3e, 0x00, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x53, 0x0a, 0x00, 0x34, - 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x0f, 0x00, 0x36, 0x32, - 0x00, 0x00, 0xf7, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x02, 0xc0, 0xfa, 0x32, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x0f, 0x40, 0x2f, 0x32, - 0x00, 0x00, 0x8b, 0x12, 0x04, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0xbc, - 0x00, 0x00, 0x8a, 0x12, 0x04, 0x00, 0x00, 0x80, 0x02, 0x40, 0x2f, 0xb2, - 0x00, 0x00, 0x87, 0x12, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x2c, 0x92, - 0x00, 0x00, 0x87, 0x12, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x2c, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x2c, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x2c, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x2d, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x2d, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x2d, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x2d, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0xfb, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x2f, 0x32, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x73, 0x0a, 0x02, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe0, 0x07, 0x80, 0x3f, 0x52, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0xf9, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x28, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0xf8, 0x32, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x0f, 0xc0, 0x2b, 0x32, - 0x00, 0x00, 0xa0, 0x12, 0x04, 0x00, 0x00, 0x9c, 0x1f, 0xc0, 0xf9, 0xbc, - 0x00, 0x00, 0x9f, 0x12, 0x04, 0x00, 0x00, 0x80, 0x02, 0xc0, 0x2b, 0xb2, - 0x00, 0x00, 0x9c, 0x12, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x28, 0x92, - 0x00, 0x00, 0x9c, 0x12, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x36, 0x92, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0xf9, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x29, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x29, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x29, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x2a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x2a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0xf9, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0x2a, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x2b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x40, 0x2b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, 0x2b, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xc0, 0xfb, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0x00, 0xfb, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xb1, 0x12, 0x9f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, 0x40, 0x90, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x80, 0x90, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x07, 0x40, 0x90, 0x52, - 0x00, 0x00, 0xb3, 0x12, 0x12, 0x00, 0x00, 0x48, 0xf2, 0x01, 0x00, 0xb4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x90, 0x32, - 0x00, 0x00, 0xb5, 0x12, 0x12, 0x00, 0x00, 0x9c, 0x0f, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x0f, 0x40, 0xfb, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32, - 0x4c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x36, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x80, 0x2a, 0x32, - 0x00, 0x00, 0xad, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0xb3, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0xd0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xcb, 0xc1, 0xb0, 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00, 0x32, - 0x00, 0x00, 0xc4, 0x12, 0x00, 0x00, 0x00, 0x28, 0x09, 0xc0, 0xb0, 0xd2, - 0x00, 0x00, 0xbe, 0x12, 0x04, 0x00, 0x00, 0x80, 0x02, 0x80, 0x92, 0xb2, - 0x00, 0x00, 0xc2, 0x12, 0x12, 0x00, 0x00, 0x9c, 0x0f, 0xc0, 0x21, 0xb2, - 0x00, 0x00, 0xc4, 0x11, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00, 0x32, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0x39, - 0x00, 0x00, 0xc8, 0x12, 0x04, 0x01, 0x00, 0x28, 0x09, 0x34, 0xb0, 0xba, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x09, 0x00, 0x00, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x22, 0x00, 0x2b, 0x37, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xc0, 0x37, 0xac, 0xb0, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x32, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xa9, 0x4d, 0xb0, 0x30, - 0x00, 0x00, 0xd8, 0x12, 0x80, 0x00, 0x00, 0x80, 0x02, 0x40, 0xb0, 0xb6, - 0x00, 0x00, 0xcd, 0x12, 0x12, 0x00, 0x00, 0x00, 0x09, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0xce, 0x12, 0x12, 0x00, 0x00, 0x04, 0x09, 0x40, 0x20, 0xb2, - 0x00, 0x00, 0xd1, 0x12, 0x9f, 0x01, 0x00, 0x80, 0x02, 0x00, 0x90, 0xb2, - 0x00, 0x00, 0xd0, 0x12, 0x12, 0x00, 0x00, 0x08, 0x09, 0x40, 0x20, 0xb2, - 0x0d, 0x00, 0xcd, 0x12, 0x04, 0x01, 0x00, 0x80, 0x02, 0xe4, 0x16, 0xb8, - 0x02, 0x00, 0xcd, 0x12, 0x04, 0x01, 0x00, 0xbc, 0x0f, 0x24, 0x17, 0xb8, - 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x0f, 0x64, 0x16, 0x38, - 0x00, 0x00, 0xcd, 0x12, 0x04, 0x01, 0x00, 0x80, 0x22, 0xc0, 0xfb, 0xbc, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xc2, 0x0a, 0x00, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3b, 0x40, 0xb0, 0x33, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xcd, 0x4a, 0xd0, 0x35, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x25, 0x01, 0x32, - 0x00, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x87, 0x8d, 0x2a, 0x3a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0xb0, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x00, 0x48, 0xf2, 0xc1, 0x38, 0x54, - 0x00, 0x00, 0xdc, 0x12, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, -}, -{ - 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x90, -}, -}; diff --git a/drivers/staging/sxg/sxg.c b/drivers/staging/sxg/sxg.c index 1e0cfcd7f0f3..0050a022010f 100644 --- a/drivers/staging/sxg/sxg.c +++ b/drivers/staging/sxg/sxg.c @@ -30,6 +30,8 @@ * are those of the authors and should not be interpreted as representing * official policies, either expressed or implied, of Alacritech, Inc. * + * Parts developed by LinSysSoft Sahara team + * **************************************************************************/ /* @@ -46,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -61,101 +64,122 @@ #include #include #include +#include +#include +#include +#include -#define SLIC_DUMP_ENABLED 0 #define SLIC_GET_STATS_ENABLED 0 #define LINUX_FREES_ADAPTER_RESOURCES 1 #define SXG_OFFLOAD_IP_CHECKSUM 0 #define SXG_POWER_MANAGEMENT_ENABLED 0 #define VPCI 0 -#define DBG 1 #define ATK_DEBUG 1 +#define SXG_UCODE_DEBUG 0 + #include "sxg_os.h" #include "sxghw.h" #include "sxghif.h" #include "sxg.h" #include "sxgdbg.h" - -#include "sxgphycode.h" -#include "saharadbgdownload.h" +#include "sxgphycode-1.2.h" static int sxg_allocate_buffer_memory(struct adapter_t *adapter, u32 Size, - enum SXG_BUFFER_TYPE BufferType); -static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter, void *RcvBlock, - dma_addr_t PhysicalAddress, - u32 Length); + enum sxg_buffer_type BufferType); +static int sxg_allocate_rcvblock_complete(struct adapter_t *adapter, + void *RcvBlock, + dma_addr_t PhysicalAddress, + u32 Length); static void sxg_allocate_sgl_buffer_complete(struct adapter_t *adapter, - struct SXG_SCATTER_GATHER *SxgSgl, + struct sxg_scatter_gather *SxgSgl, dma_addr_t PhysicalAddress, u32 Length); static void sxg_mcast_init_crc32(void); - -static int sxg_entry_open(p_net_device dev); -static int sxg_entry_halt(p_net_device dev); -static int sxg_ioctl(p_net_device dev, struct ifreq *rq, int cmd); -static int sxg_send_packets(struct sk_buff *skb, p_net_device dev); +static int sxg_entry_open(struct net_device *dev); +static int sxg_second_open(struct net_device * dev); +static int sxg_entry_halt(struct net_device *dev); +static int sxg_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static int sxg_send_packets(struct sk_buff *skb, struct net_device *dev); static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb); -static void sxg_dumb_sgl(struct SCATTER_GATHER_LIST *pSgl, struct SXG_SCATTER_GATHER *SxgSgl); +static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl, + struct sxg_scatter_gather *SxgSgl); -static void sxg_handle_interrupt(struct adapter_t *adapter); +static void sxg_handle_interrupt(struct adapter_t *adapter, int *work_done, + int budget); +static void sxg_interrupt(struct adapter_t *adapter); +static int sxg_poll(struct napi_struct *napi, int budget); static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId); -static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId); +static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId, + int *sxg_napi_continue, int *work_done, int budget); static void sxg_complete_slow_send(struct adapter_t *adapter); -static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter, struct SXG_EVENT *Event); +static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter, + struct sxg_event *Event); static void sxg_process_rcv_error(struct adapter_t *adapter, u32 ErrorStatus); static bool sxg_mac_filter(struct adapter_t *adapter, struct ether_header *EtherHdr, ushort length); +static struct net_device_stats *sxg_get_stats(struct net_device * dev); +void sxg_free_resources(struct adapter_t *adapter); +void sxg_free_rcvblocks(struct adapter_t *adapter); +void sxg_free_sgl_buffers(struct adapter_t *adapter); +void sxg_unmap_resources(struct adapter_t *adapter); +void sxg_free_mcast_addrs(struct adapter_t *adapter); +void sxg_collect_statistics(struct adapter_t *adapter); +static int sxg_register_interrupt(struct adapter_t *adapter); +static void sxg_remove_isr(struct adapter_t *adapter); +static irqreturn_t sxg_isr(int irq, void *dev_id); -#if SLIC_GET_STATS_ENABLED -static struct net_device_stats *sxg_get_stats(p_net_device dev); -#endif +static void sxg_watchdog(unsigned long data); +static void sxg_update_link_status (struct work_struct *work); #define XXXTODO 0 #if XXXTODO -static int sxg_mac_set_address(p_net_device dev, void *ptr); -static void sxg_mcast_set_list(p_net_device dev); +static int sxg_mac_set_address(struct net_device *dev, void *ptr); #endif +static void sxg_mcast_set_list(struct net_device *dev); -static void sxg_adapter_set_hwaddr(struct adapter_t *adapter); - -static void sxg_unmap_mmio_space(struct adapter_t *adapter); +static int sxg_adapter_set_hwaddr(struct adapter_t *adapter); static int sxg_initialize_adapter(struct adapter_t *adapter); static void sxg_stock_rcv_buffers(struct adapter_t *adapter); static void sxg_complete_descriptor_blocks(struct adapter_t *adapter, unsigned char Index); +int sxg_change_mtu (struct net_device *netdev, int new_mtu); static int sxg_initialize_link(struct adapter_t *adapter); static int sxg_phy_init(struct adapter_t *adapter); static void sxg_link_event(struct adapter_t *adapter); static enum SXG_LINK_STATE sxg_get_link_state(struct adapter_t *adapter); -static void sxg_link_state(struct adapter_t *adapter, enum SXG_LINK_STATE LinkState); +static void sxg_link_state(struct adapter_t *adapter, + enum SXG_LINK_STATE LinkState); static int sxg_write_mdio_reg(struct adapter_t *adapter, u32 DevAddr, u32 RegAddr, u32 Value); static int sxg_read_mdio_reg(struct adapter_t *adapter, u32 DevAddr, u32 RegAddr, u32 *pValue); +static void sxg_set_mcast_addr(struct adapter_t *adapter); static unsigned int sxg_first_init = 1; static char *sxg_banner = - "Alacritech SLIC Technology(tm) Server and Storage 10Gbe Accelerator (Non-Accelerated)\n"; + "Alacritech SLIC Technology(tm) Server and Storage \ + 10Gbe Accelerator (Non-Accelerated)\n"; static int sxg_debug = 1; static int debug = -1; -static p_net_device head_netdevice = NULL; +static struct net_device *head_netdevice = NULL; -static struct sxgbase_driver_t sxg_global = { +static struct sxgbase_driver sxg_global = { .dynamic_intagg = 1, }; static int intagg_delay = 100; static u32 dynamic_intagg = 0; -#define DRV_NAME "sxg" -#define DRV_VERSION "1.0.1" +char sxg_driver_name[] = "sxg_nic"; #define DRV_AUTHOR "Alacritech, Inc. Engineering" -#define DRV_DESCRIPTION "Alacritech SLIC Techonology(tm) Non-Accelerated 10Gbe Driver" -#define DRV_COPYRIGHT "Copyright 2000-2008 Alacritech, Inc. All rights reserved." +#define DRV_DESCRIPTION \ + "Alacritech SLIC Techonology(tm) Non-Accelerated 10Gbe Driver" +#define DRV_COPYRIGHT \ + "Copyright 2000-2008 Alacritech, Inc. All rights reserved." MODULE_AUTHOR(DRV_AUTHOR); MODULE_DESCRIPTION(DRV_DESCRIPTION); @@ -173,12 +197,6 @@ static struct pci_device_id sxg_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, sxg_pci_tbl); -/*********************************************************************** -************************************************************************ -************************************************************************ -************************************************************************ -************************************************************************/ - static inline void sxg_reg32_write(void __iomem *reg, u32 value, bool flush) { writel(value, reg); @@ -225,17 +243,143 @@ static void sxg_dbg_macaddrs(struct adapter_t *adapter) } /* SXG Globals */ -static struct SXG_DRIVER SxgDriver; +static struct sxg_driver SxgDriver; #ifdef ATKDBG -static struct sxg_trace_buffer_t LSxgTraceBuffer; +static struct sxg_trace_buffer LSxgTraceBuffer; #endif /* ATKDBG */ -static struct sxg_trace_buffer_t *SxgTraceBuffer = NULL; +static struct sxg_trace_buffer *SxgTraceBuffer = NULL; + +/* + * MSI Related API's + */ +int sxg_register_intr(struct adapter_t *adapter); +int sxg_enable_msi_x(struct adapter_t *adapter); +int sxg_add_msi_isr(struct adapter_t *adapter); +void sxg_remove_msix_isr(struct adapter_t *adapter); +int sxg_set_interrupt_capability(struct adapter_t *adapter); + +int sxg_set_interrupt_capability(struct adapter_t *adapter) +{ + int ret; + + ret = sxg_enable_msi_x(adapter); + if (ret != STATUS_SUCCESS) { + adapter->msi_enabled = FALSE; + DBG_ERROR("sxg_set_interrupt_capability MSI-X Disable\n"); + } else { + adapter->msi_enabled = TRUE; + DBG_ERROR("sxg_set_interrupt_capability MSI-X Enable\n"); + } + return ret; +} + +int sxg_register_intr(struct adapter_t *adapter) +{ + int ret = 0; + + if (adapter->msi_enabled) { + ret = sxg_add_msi_isr(adapter); + } + else { + DBG_ERROR("MSI-X Enable Failed. Using Pin INT\n"); + ret = sxg_register_interrupt(adapter); + if (ret != STATUS_SUCCESS) { + DBG_ERROR("sxg_register_interrupt Failed\n"); + } + } + return ret; +} + +int sxg_enable_msi_x(struct adapter_t *adapter) +{ + int ret; + + adapter->nr_msix_entries = 1; + adapter->msi_entries = kmalloc(adapter->nr_msix_entries * + sizeof(struct msix_entry),GFP_KERNEL); + if (!adapter->msi_entries) { + DBG_ERROR("%s:MSI Entries memory allocation Failed\n",__func__); + return -ENOMEM; + } + memset(adapter->msi_entries, 0, adapter->nr_msix_entries * + sizeof(struct msix_entry)); + + ret = pci_enable_msix(adapter->pcidev, adapter->msi_entries, + adapter->nr_msix_entries); + if (ret) { + DBG_ERROR("Enabling MSI-X with %d vectors failed\n", + adapter->nr_msix_entries); + /*Should try with less vector returned.*/ + kfree(adapter->msi_entries); + return STATUS_FAILURE; /*MSI-X Enable failed.*/ + } + return (STATUS_SUCCESS); +} + +int sxg_add_msi_isr(struct adapter_t *adapter) +{ + int ret,i; + + if (!adapter->intrregistered) { + for (i=0; inr_msix_entries; i++) { + ret = request_irq (adapter->msi_entries[i].vector, + sxg_isr, + IRQF_SHARED, + adapter->netdev->name, + adapter->netdev); + if (ret) { + DBG_ERROR("sxg: MSI-X request_irq (%s) " + "FAILED [%x]\n", adapter->netdev->name, + ret); + return (ret); + } + } + } + adapter->msi_enabled = TRUE; + adapter->intrregistered = 1; + adapter->IntRegistered = TRUE; + return (STATUS_SUCCESS); +} + +void sxg_remove_msix_isr(struct adapter_t *adapter) +{ + int i,vector; + struct net_device *netdev = adapter->netdev; + + for(i=0; i< adapter->nr_msix_entries;i++) + { + vector = adapter->msi_entries[i].vector; + DBG_ERROR("%s : Freeing IRQ vector#%d\n",__FUNCTION__,vector); + free_irq(vector,netdev); + } +} + + +static void sxg_remove_isr(struct adapter_t *adapter) +{ + struct net_device *netdev = adapter->netdev; + if (adapter->msi_enabled) + sxg_remove_msix_isr(adapter); + else + free_irq(adapter->netdev->irq, netdev); +} + +void sxg_reset_interrupt_capability(struct adapter_t *adapter) +{ + if (adapter->msi_enabled) { + pci_disable_msix(adapter->pcidev); + kfree(adapter->msi_entries); + adapter->msi_entries = NULL; + } + return; +} /* * sxg_download_microcode * - * Download Microcode to Sahara adapter + * Download Microcode to Sahara adapter using the Linux + * Firmware module to get the ucode.sys file. * * Arguments - * adapter - A pointer to our adapter structure @@ -244,98 +388,141 @@ static struct sxg_trace_buffer_t *SxgTraceBuffer = NULL; * Return * int */ -static bool sxg_download_microcode(struct adapter_t *adapter, enum SXG_UCODE_SEL UcodeSel) +static bool sxg_download_microcode(struct adapter_t *adapter, + enum SXG_UCODE_SEL UcodeSel) { - struct SXG_HW_REGS *HwRegs = adapter->HwRegs; + const struct firmware *fw; + const char *file = ""; + struct sxg_hw_regs *HwRegs = adapter->HwRegs; + int ret; + int ucode_start; u32 Section; u32 ThisSectionSize; - u32 *Instruction = NULL; + u32 instruction = 0; u32 BaseAddress, AddressOffset, Address; -/* u32 Failure; */ + /* u32 Failure; */ u32 ValueRead; u32 i; - u32 numSections = 0; + u32 index = 0; + u32 num_sections = 0; u32 sectionSize[16]; u32 sectionStart[16]; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DnldUcod", adapter, 0, 0, 0); - DBG_ERROR("sxg: %s ENTER\n", __func__); - switch (UcodeSel) { - case SXG_UCODE_SAHARA: /* Sahara operational ucode */ - numSections = SNumSections; - for (i = 0; i < numSections; i++) { - sectionSize[i] = SSectionSize[i]; - sectionStart[i] = SSectionStart[i]; - } - break; - default: - printk(KERN_ERR KBUILD_MODNAME - ": Woah, big error with the microcode!\n"); - break; + /* + * This routine is only implemented to download the microcode + * for the Revision B Sahara chip. Rev A and Diagnostic + * microcode is not supported at this time. If Rev A or + * diagnostic ucode is required, this routine will obviously + * need to change. Also, eventually need to add support for + * Rev B checked version of ucode. That's easy enough once + * the free version of Rev B works. + */ + ASSERT(UcodeSel == SXG_UCODE_SYSTEM); + ASSERT(adapter->asictype == SAHARA_REV_B); +#if SXG_UCODE_DEBUG + file = "sxg/saharadbgdownloadB.sys"; +#else + file = "sxg/saharadownloadB.sys"; +#endif + ret = request_firmware(&fw, file, &adapter->pcidev->dev); + if (ret) { + DBG_ERROR("%s SXG_NIC: Failed to load firmware %s\n", __func__,file); + return ret; + } + + /* + * The microcode .sys file contains starts with a 4 byte word containing + * the number of sections. That is followed by "num_sections" 4 byte + * words containing each "section" size. That is followed num_sections + * 4 byte words containing each section "start" address. + * + * Following the above header, the .sys file contains num_sections, + * where each section size is specified, newline delineatetd 12 byte + * microcode instructions. + */ + num_sections = *(u32 *)(fw->data + index); + index += 4; + ASSERT(num_sections <= 3); + for (i = 0; i < num_sections; i++) { + sectionSize[i] = *(u32 *)(fw->data + index); + index += 4; + } + for (i = 0; i < num_sections; i++) { + sectionStart[i] = *(u32 *)(fw->data + index); + index += 4; } - DBG_ERROR("sxg: RESET THE CARD\n"); /* First, reset the card */ WRITE_REG(HwRegs->Reset, 0xDEAD, FLUSH); + udelay(50); + HwRegs = adapter->HwRegs; - /* Download each section of the microcode as specified in */ - /* its download file. The *download.c file is generated using */ - /* the saharaobjtoc facility which converts the metastep .obj */ - /* file to a .c file which contains a two dimentional array. */ - for (Section = 0; Section < numSections; Section++) { - DBG_ERROR("sxg: SECTION # %d\n", Section); - switch (UcodeSel) { - case SXG_UCODE_SAHARA: - Instruction = (u32 *) & SaharaUCode[Section][0]; - break; - default: - ASSERT(0); - break; - } + /* + * Download each section of the microcode as specified in + * sectionSize[index] to sectionStart[index] address. As + * described above, the .sys file contains 12 byte word + * microcode instructions. The *download.sys file is generated + * using the objtosys.exe utility that was built for Sahara + * microcode. + */ + /* See usage of this below when we read back for parity */ + ucode_start = index; + instruction = *(u32 *)(fw->data + index); + index += 4; + + for (Section = 0; Section < num_sections; Section++) { BaseAddress = sectionStart[Section]; - ThisSectionSize = sectionSize[Section] / 12; /* Size in instructions */ + /* Size in instructions */ + ThisSectionSize = sectionSize[Section] / 12; for (AddressOffset = 0; AddressOffset < ThisSectionSize; AddressOffset++) { + u32 first_instr = 0; /* See comment below */ + Address = BaseAddress + AddressOffset; ASSERT((Address & ~MICROCODE_ADDRESS_MASK) == 0); - /* Write instruction bits 31 - 0 */ - WRITE_REG(HwRegs->UcodeDataLow, *Instruction, FLUSH); - /* Write instruction bits 63-32 */ - WRITE_REG(HwRegs->UcodeDataMiddle, *(Instruction + 1), - FLUSH); - /* Write instruction bits 95-64 */ - WRITE_REG(HwRegs->UcodeDataHigh, *(Instruction + 2), - FLUSH); + /* Write instruction bits 31 - 0 (low) */ + first_instr = instruction; + WRITE_REG(HwRegs->UcodeDataLow, instruction, FLUSH); + instruction = *(u32 *)(fw->data + index); + index += 4; /* Advance to the "next" instruction */ + + /* Write instruction bits 63-32 (middle) */ + WRITE_REG(HwRegs->UcodeDataMiddle, instruction, FLUSH); + instruction = *(u32 *)(fw->data + index); + index += 4; /* Advance to the "next" instruction */ + + /* Write instruction bits 95-64 (high) */ + WRITE_REG(HwRegs->UcodeDataHigh, instruction, FLUSH); + instruction = *(u32 *)(fw->data + index); + index += 4; /* Advance to the "next" instruction */ + /* Write instruction address with the WRITE bit set */ WRITE_REG(HwRegs->UcodeAddr, (Address | MICROCODE_ADDRESS_WRITE), FLUSH); - /* Sahara bug in the ucode download logic - the write to DataLow */ - /* for the next instruction could get corrupted. To avoid this, */ - /* write to DataLow again for this instruction (which may get */ - /* corrupted, but it doesn't matter), then increment the address */ - /* and write the data for the next instruction to DataLow. That */ - /* write should succeed. */ - WRITE_REG(HwRegs->UcodeDataLow, *Instruction, TRUE); - /* Advance 3 u32S to start of next instruction */ - Instruction += 3; + /* + * Sahara bug in the ucode download logic - the write to DataLow + * for the next instruction could get corrupted. To avoid this, + * write to DataLow again for this instruction (which may get + * corrupted, but it doesn't matter), then increment the address + * and write the data for the next instruction to DataLow. That + * write should succeed. + */ + WRITE_REG(HwRegs->UcodeDataLow, first_instr, FLUSH); } } - /* Now repeat the entire operation reading the instruction back and */ - /* checking for parity errors */ - for (Section = 0; Section < numSections; Section++) { - DBG_ERROR("sxg: check SECTION # %d\n", Section); - switch (UcodeSel) { - case SXG_UCODE_SAHARA: - Instruction = (u32 *) & SaharaUCode[Section][0]; - break; - default: - ASSERT(0); - break; - } + /* + * Now repeat the entire operation reading the instruction back and + * checking for parity errors + */ + index = ucode_start; + + for (Section = 0; Section < num_sections; Section++) { BaseAddress = sectionStart[Section]; - ThisSectionSize = sectionSize[Section] / 12; /* Size in instructions */ + /* Size in instructions */ + ThisSectionSize = sectionSize[Section] / 12; for (AddressOffset = 0; AddressOffset < ThisSectionSize; AddressOffset++) { Address = BaseAddress + AddressOffset; @@ -348,62 +535,70 @@ static bool sxg_download_microcode(struct adapter_t *adapter, enum SXG_UCODE_SEL DBG_ERROR("sxg: %s PARITY ERROR\n", __func__); - return (FALSE); /* Parity error */ + return FALSE; /* Parity error */ } ASSERT((ValueRead & MICROCODE_ADDRESS_MASK) == Address); /* Read the instruction back and compare */ + /* First instruction */ + instruction = *(u32 *)(fw->data + index); + index += 4; READ_REG(HwRegs->UcodeDataLow, ValueRead); - if (ValueRead != *Instruction) { + if (ValueRead != instruction) { DBG_ERROR("sxg: %s MISCOMPARE LOW\n", __func__); - return (FALSE); /* Miscompare */ + return FALSE; /* Miscompare */ } + instruction = *(u32 *)(fw->data + index); + index += 4; READ_REG(HwRegs->UcodeDataMiddle, ValueRead); - if (ValueRead != *(Instruction + 1)) { + if (ValueRead != instruction) { DBG_ERROR("sxg: %s MISCOMPARE MIDDLE\n", __func__); - return (FALSE); /* Miscompare */ + return FALSE; /* Miscompare */ } + instruction = *(u32 *)(fw->data + index); + index += 4; READ_REG(HwRegs->UcodeDataHigh, ValueRead); - if (ValueRead != *(Instruction + 2)) { + if (ValueRead != instruction) { DBG_ERROR("sxg: %s MISCOMPARE HIGH\n", __func__); - return (FALSE); /* Miscompare */ + return FALSE; /* Miscompare */ } - /* Advance 3 u32S to start of next instruction */ - Instruction += 3; } } + /* download finished */ + release_firmware(fw); /* Everything OK, Go. */ WRITE_REG(HwRegs->UcodeAddr, MICROCODE_ADDRESS_GO, FLUSH); - /* Poll the CardUp register to wait for microcode to initialize */ - /* Give up after 10,000 attemps (500ms). */ + /* + * Poll the CardUp register to wait for microcode to initialize + * Give up after 10,000 attemps (500ms). + */ for (i = 0; i < 10000; i++) { udelay(50); READ_REG(adapter->UcodeRegs[0].CardUp, ValueRead); if (ValueRead == 0xCAFE) { - DBG_ERROR("sxg: %s BOO YA 0xCAFE\n", __func__); break; } } if (i == 10000) { - DBG_ERROR("sxg: %s TIMEOUT\n", __func__); + DBG_ERROR("sxg: %s TIMEOUT bringing up card - verify MICROCODE\n", __func__); - return (FALSE); /* Timeout */ + return FALSE; /* Timeout */ } - /* Now write the LoadSync register. This is used to */ - /* synchronize with the card so it can scribble on the memory */ - /* that contained 0xCAFE from the "CardUp" step above */ - if (UcodeSel == SXG_UCODE_SAHARA) { + /* + * Now write the LoadSync register. This is used to + * synchronize with the card so it can scribble on the memory + * that contained 0xCAFE from the "CardUp" step above + */ + if (UcodeSel == SXG_UCODE_SYSTEM) { WRITE_REG(adapter->UcodeRegs[0].LoadSync, 0, FLUSH); } SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDnldUcd", adapter, 0, 0, 0); - DBG_ERROR("sxg: %s EXIT\n", __func__); - return (TRUE); } @@ -411,18 +606,16 @@ static bool sxg_download_microcode(struct adapter_t *adapter, enum SXG_UCODE_SEL * sxg_allocate_resources - Allocate memory and locks * * Arguments - - * adapter - A pointer to our adapter structure + * adapter - A pointer to our adapter structure * - * Return - * int + * Return - int */ static int sxg_allocate_resources(struct adapter_t *adapter) { - int status; - u32 i; + int status = STATUS_SUCCESS; u32 RssIds, IsrCount; -/* struct SXG_XMT_RING *XmtRing; */ -/* struct SXG_RCV_RING *RcvRing; */ + /* struct sxg_xmt_ring *XmtRing; */ + /* struct sxg_rcv_ring *RcvRing; */ DBG_ERROR("%s ENTER\n", __func__); @@ -432,7 +625,7 @@ static int sxg_allocate_resources(struct adapter_t *adapter) /* Windows tells us how many CPUs it plans to use for */ /* RSS */ RssIds = SXG_RSS_CPU_COUNT(adapter); - IsrCount = adapter->MsiEnabled ? RssIds : 1; + IsrCount = adapter->msi_enabled ? RssIds : 1; DBG_ERROR("%s Setup the spinlocks\n", __func__); @@ -442,6 +635,7 @@ static int sxg_allocate_resources(struct adapter_t *adapter) spin_lock_init(&adapter->XmtZeroLock); spin_lock_init(&adapter->Bit64RegLock); spin_lock_init(&adapter->AdapterLock); + atomic_set(&adapter->pending_allocations, 0); DBG_ERROR("%s Setup the lists\n", __func__); @@ -451,62 +645,82 @@ static int sxg_allocate_resources(struct adapter_t *adapter) InitializeListHead(&adapter->FreeSglBuffers); InitializeListHead(&adapter->AllSglBuffers); - /* Mark these basic allocations done. This flags essentially */ - /* tells the SxgFreeResources routine that it can grab spinlocks */ - /* and reference listheads. */ + /* + * Mark these basic allocations done. This flags essentially + * tells the SxgFreeResources routine that it can grab spinlocks + * and reference listheads. + */ adapter->BasicAllocations = TRUE; - /* Main allocation loop. Start with the maximum supported by */ - /* the microcode and back off if memory allocation */ - /* fails. If we hit a minimum, fail. */ + /* + * Main allocation loop. Start with the maximum supported by + * the microcode and back off if memory allocation + * fails. If we hit a minimum, fail. + */ for (;;) { DBG_ERROR("%s Allocate XmtRings size[%x]\n", __func__, - (unsigned int)(sizeof(struct SXG_XMT_RING) * 1)); + (unsigned int)(sizeof(struct sxg_xmt_ring) * 1)); - /* Start with big items first - receive and transmit rings. At the moment */ - /* I'm going to keep the ring size fixed and adjust the number of */ - /* TCBs if we fail. Later we might consider reducing the ring size as well.. */ + /* + * Start with big items first - receive and transmit rings. + * At the moment I'm going to keep the ring size fixed and + * adjust the TCBs if we fail. Later we might + * consider reducing the ring size as well.. + */ adapter->XmtRings = pci_alloc_consistent(adapter->pcidev, - sizeof(struct SXG_XMT_RING) * - 1, - &adapter->PXmtRings); + sizeof(struct sxg_xmt_ring) * + 1, + &adapter->PXmtRings); DBG_ERROR("%s XmtRings[%p]\n", __func__, adapter->XmtRings); if (!adapter->XmtRings) { goto per_tcb_allocation_failed; } - memset(adapter->XmtRings, 0, sizeof(struct SXG_XMT_RING) * 1); + memset(adapter->XmtRings, 0, sizeof(struct sxg_xmt_ring) * 1); DBG_ERROR("%s Allocate RcvRings size[%x]\n", __func__, - (unsigned int)(sizeof(struct SXG_RCV_RING) * 1)); + (unsigned int)(sizeof(struct sxg_rcv_ring) * 1)); adapter->RcvRings = pci_alloc_consistent(adapter->pcidev, - sizeof(struct SXG_RCV_RING) * 1, + sizeof(struct sxg_rcv_ring) * 1, &adapter->PRcvRings); DBG_ERROR("%s RcvRings[%p]\n", __func__, adapter->RcvRings); if (!adapter->RcvRings) { goto per_tcb_allocation_failed; } - memset(adapter->RcvRings, 0, sizeof(struct SXG_RCV_RING) * 1); + memset(adapter->RcvRings, 0, sizeof(struct sxg_rcv_ring) * 1); + adapter->ucode_stats = kzalloc(sizeof(struct sxg_ucode_stats), GFP_ATOMIC); + adapter->pucode_stats = pci_map_single(adapter->pcidev, + adapter->ucode_stats, + sizeof(struct sxg_ucode_stats), + PCI_DMA_FROMDEVICE); +// memset(adapter->ucode_stats, 0, sizeof(struct sxg_ucode_stats)); break; per_tcb_allocation_failed: /* an allocation failed. Free any successful allocations. */ if (adapter->XmtRings) { pci_free_consistent(adapter->pcidev, - sizeof(struct SXG_XMT_RING) * 4096, + sizeof(struct sxg_xmt_ring) * 1, adapter->XmtRings, adapter->PXmtRings); adapter->XmtRings = NULL; } if (adapter->RcvRings) { pci_free_consistent(adapter->pcidev, - sizeof(struct SXG_RCV_RING) * 4096, + sizeof(struct sxg_rcv_ring) * 1, adapter->RcvRings, adapter->PRcvRings); adapter->RcvRings = NULL; } /* Loop around and try again.... */ + if (adapter->ucode_stats) { + pci_unmap_single(adapter->pcidev, + sizeof(struct sxg_ucode_stats), + adapter->pucode_stats, PCI_DMA_FROMDEVICE); + adapter->ucode_stats = NULL; + } + } DBG_ERROR("%s Initialize RCV ZERO and XMT ZERO rings\n", __func__); @@ -515,53 +729,37 @@ static int sxg_allocate_resources(struct adapter_t *adapter) SXG_INITIALIZE_RING(adapter->XmtRingZeroInfo, SXG_XMT_RING_SIZE); /* Sanity check receive data structure format */ - ASSERT((adapter->ReceiveBufferSize == SXG_RCV_DATA_BUFFER_SIZE) || - (adapter->ReceiveBufferSize == SXG_RCV_JUMBO_BUFFER_SIZE)); - ASSERT(sizeof(struct SXG_RCV_DESCRIPTOR_BLOCK) == + /* ASSERT((adapter->ReceiveBufferSize == SXG_RCV_DATA_BUFFER_SIZE) || + (adapter->ReceiveBufferSize == SXG_RCV_JUMBO_BUFFER_SIZE)); */ + ASSERT(sizeof(struct sxg_rcv_descriptor_block) == SXG_RCV_DESCRIPTOR_BLOCK_SIZE); - /* Allocate receive data buffers. We allocate a block of buffers and */ - /* a corresponding descriptor block at once. See sxghw.h:SXG_RCV_BLOCK */ - for (i = 0; i < SXG_INITIAL_RCV_DATA_BUFFERS; - i += SXG_RCV_DESCRIPTORS_PER_BLOCK) { - sxg_allocate_buffer_memory(adapter, - SXG_RCV_BLOCK_SIZE(adapter-> - ReceiveBufferSize), - SXG_BUFFER_TYPE_RCV); - } - /* NBL resource allocation can fail in the 'AllocateComplete' routine, which */ - /* doesn't return status. Make sure we got the number of buffers we requested */ - if (adapter->FreeRcvBufferCount < SXG_INITIAL_RCV_DATA_BUFFERS) { - SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF6", - adapter, adapter->FreeRcvBufferCount, SXG_MAX_ENTRIES, - 0); - return (STATUS_RESOURCES); - } - DBG_ERROR("%s Allocate EventRings size[%x]\n", __func__, - (unsigned int)(sizeof(struct SXG_EVENT_RING) * RssIds)); + (unsigned int)(sizeof(struct sxg_event_ring) * RssIds)); /* Allocate event queues. */ adapter->EventRings = pci_alloc_consistent(adapter->pcidev, - sizeof(struct SXG_EVENT_RING) * - RssIds, - &adapter->PEventRings); + sizeof(struct sxg_event_ring) * + RssIds, + &adapter->PEventRings); if (!adapter->EventRings) { - /* Caller will call SxgFreeAdapter to clean up above allocations */ + /* Caller will call SxgFreeAdapter to clean up above + * allocations */ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF8", adapter, SXG_MAX_ENTRIES, 0, 0); status = STATUS_RESOURCES; goto per_tcb_allocation_failed; } - memset(adapter->EventRings, 0, sizeof(struct SXG_EVENT_RING) * RssIds); + memset(adapter->EventRings, 0, sizeof(struct sxg_event_ring) * RssIds); DBG_ERROR("%s Allocate ISR size[%x]\n", __func__, IsrCount); /* Allocate ISR */ adapter->Isr = pci_alloc_consistent(adapter->pcidev, IsrCount, &adapter->PIsr); if (!adapter->Isr) { - /* Caller will call SxgFreeAdapter to clean up above allocations */ + /* Caller will call SxgFreeAdapter to clean up above + * allocations */ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF9", adapter, SXG_MAX_ENTRIES, 0, 0); status = STATUS_RESOURCES; @@ -588,8 +786,7 @@ static int sxg_allocate_resources(struct adapter_t *adapter) SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlcResS", adapter, SXG_MAX_ENTRIES, 0, 0); - DBG_ERROR("%s EXIT\n", __func__); - return (STATUS_SUCCESS); + return status; } /* @@ -599,7 +796,6 @@ static int sxg_allocate_resources(struct adapter_t *adapter) * * Arguments - * pcidev - A pointer to our adapter structure - * */ static void sxg_config_pci(struct pci_dev *pcidev) { @@ -609,12 +805,19 @@ static void sxg_config_pci(struct pci_dev *pcidev) pci_read_config_word(pcidev, PCI_COMMAND, &pci_command); DBG_ERROR("sxg: %s PCI command[%4.4x]\n", __func__, pci_command); /* Set the command register */ - new_command = pci_command | (PCI_COMMAND_MEMORY | /* Memory Space Enable */ - PCI_COMMAND_MASTER | /* Bus master enable */ - PCI_COMMAND_INVALIDATE | /* Memory write and invalidate */ - PCI_COMMAND_PARITY | /* Parity error response */ - PCI_COMMAND_SERR | /* System ERR */ - PCI_COMMAND_FAST_BACK); /* Fast back-to-back */ + new_command = pci_command | ( + /* Memory Space Enable */ + PCI_COMMAND_MEMORY | + /* Bus master enable */ + PCI_COMMAND_MASTER | + /* Memory write and invalidate */ + PCI_COMMAND_INVALIDATE | + /* Parity error response */ + PCI_COMMAND_PARITY | + /* System ERR */ + PCI_COMMAND_SERR | + /* Fast back-to-back */ + PCI_COMMAND_FAST_BACK); if (pci_command != new_command) { DBG_ERROR("%s -- Updating PCI COMMAND register %4.4x->%4.4x.\n", __func__, pci_command, new_command); @@ -622,6 +825,77 @@ static void sxg_config_pci(struct pci_dev *pcidev) } } +/* + * sxg_read_config + * @adapter : Pointer to the adapter structure for the card + * This function will read the configuration data from EEPROM/FLASH + */ +static inline int sxg_read_config(struct adapter_t *adapter) +{ + /* struct sxg_config data; */ + struct sxg_config *config; + struct sw_cfg_data *data; + dma_addr_t p_addr; + unsigned long status; + unsigned long i; + config = pci_alloc_consistent(adapter->pcidev, + sizeof(struct sxg_config), &p_addr); + + if(!config) { + /* + * We cant get even this much memory. Raise a hell + * Get out of here + */ + printk(KERN_ERR"%s : Could not allocate memory for reading \ + EEPROM\n", __FUNCTION__); + return -ENOMEM; + } + + data = &config->SwCfg; + + /* Initialize (reflective memory) status register */ + WRITE_REG(adapter->UcodeRegs[0].ConfigStat, SXG_CFG_TIMEOUT, TRUE); + + /* Send request to fetch configuration data */ + WRITE_REG64(adapter, adapter->UcodeRegs[0].Config, p_addr, 0); + for(i=0; i<1000; i++) { + READ_REG(adapter->UcodeRegs[0].ConfigStat, status); + if (status != SXG_CFG_TIMEOUT) + break; + mdelay(1); /* Do we really need this */ + } + + switch(status) { + /* Config read from EEPROM succeeded */ + case SXG_CFG_LOAD_EEPROM: + /* Config read from Flash succeeded */ + case SXG_CFG_LOAD_FLASH: + /* + * Copy the MAC address to adapter structure + * TODO: We are not doing the remaining part : FRU, etc + */ + memcpy(adapter->macaddr, data->MacAddr[0].MacAddr, + sizeof(struct sxg_config_mac)); + break; + case SXG_CFG_TIMEOUT: + case SXG_CFG_LOAD_INVALID: + case SXG_CFG_LOAD_ERROR: + default: /* Fix default handler later */ + printk(KERN_WARNING"%s : We could not read the config \ + word. Status = %ld\n", __FUNCTION__, status); + break; + } + pci_free_consistent(adapter->pcidev, sizeof(struct sw_cfg_data), data, + p_addr); + if (adapter->netdev) { + memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, 6); + memcpy(adapter->netdev->perm_addr, adapter->currmacaddr, 6); + } + sxg_dbg_macaddrs(adapter); + + return status; +} + static int sxg_entry_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_tbl_entry) { @@ -633,6 +907,7 @@ static int sxg_entry_probe(struct pci_dev *pcidev, u32 status = 0; ulong mmio_start = 0; ulong mmio_len = 0; + unsigned char revision_id; DBG_ERROR("sxg: %s 2.6 VERSION ENTER jiffies[%lx] cpu %d\n", __func__, jiffies, smp_processor_id()); @@ -654,9 +929,11 @@ static int sxg_entry_probe(struct pci_dev *pcidev, if (sxg_debug > 0 && did_version++ == 0) { printk(KERN_INFO "%s\n", sxg_banner); - printk(KERN_INFO "%s\n", DRV_VERSION); + printk(KERN_INFO "%s\n", SXG_DRV_VERSION); } + pci_read_config_byte(pcidev, PCI_REVISION_ID, &revision_id); + if (!(err = pci_set_dma_mask(pcidev, DMA_64BIT_MASK))) { DBG_ERROR("pci_set_dma_mask(DMA_64BIT_MASK) successful\n"); } else { @@ -671,7 +948,7 @@ static int sxg_entry_probe(struct pci_dev *pcidev, DBG_ERROR("Call pci_request_regions\n"); - err = pci_request_regions(pcidev, DRV_NAME); + err = pci_request_regions(pcidev, sxg_driver_name); if (err) { DBG_ERROR("pci_request_regions FAILED err[%x]\n", err); return err; @@ -692,6 +969,15 @@ static int sxg_entry_probe(struct pci_dev *pcidev, pci_set_drvdata(pcidev, netdev); adapter = netdev_priv(netdev); + if (revision_id == 1) { + adapter->asictype = SAHARA_REV_A; + } else if (revision_id == 2) { + adapter->asictype = SAHARA_REV_B; + } else { + ASSERT(0); + DBG_ERROR("%s Unexpected revision ID %x\n", __FUNCTION__, revision_id); + goto err_out_exit_sxg_probe; + } adapter->netdev = netdev; adapter->pcidev = pcidev; @@ -707,12 +993,12 @@ static int sxg_entry_probe(struct pci_dev *pcidev, if (!memmapped_ioaddr) { DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n", __func__, mmio_len, mmio_start); - goto err_out_free_mmio_region; + goto err_out_free_mmio_region_0; } - DBG_ERROR - ("sxg: %s found Alacritech SXG PCI, MMIO at %p, start[%lx] len[%lx], IRQ %d.\n", - __func__, memmapped_ioaddr, mmio_start, mmio_len, pcidev->irq); + DBG_ERROR("sxg: %s found Alacritech SXG PCI, MMIO at %p, start[%lx] \ + len[%lx], IRQ %d.\n", __func__, memmapped_ioaddr, mmio_start, + mmio_len, pcidev->irq); adapter->HwRegs = (void *)memmapped_ioaddr; adapter->base_addr = memmapped_ioaddr; @@ -729,7 +1015,7 @@ static int sxg_entry_probe(struct pci_dev *pcidev, if (!memmapped_ioaddr) { DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n", __func__, mmio_len, mmio_start); - goto err_out_free_mmio_region; + goto err_out_free_mmio_region_2; } DBG_ERROR("sxg: %s found Alacritech SXG PCI, MMIO at %p, " @@ -739,8 +1025,10 @@ static int sxg_entry_probe(struct pci_dev *pcidev, adapter->UcodeRegs = (void *)memmapped_ioaddr; adapter->State = SXG_STATE_INITIALIZING; - /* Maintain a list of all adapters anchored by */ - /* the global SxgDriver structure. */ + /* + * Maintain a list of all adapters anchored by + * the global SxgDriver structure. + */ adapter->Next = SxgDriver.Adapters; SxgDriver.Adapters = adapter; adapter->AdapterID = ++SxgDriver.AdapterID; @@ -758,10 +1046,12 @@ static int sxg_entry_probe(struct pci_dev *pcidev, adapter->ReceiveBufferSize = SXG_RCV_DATA_BUFFER_SIZE; } -/* status = SXG_READ_EEPROM(adapter); */ -/* if (!status) { */ -/* goto sxg_init_bad; */ -/* } */ + /* + * status = SXG_READ_EEPROM(adapter); + * if (!status) { + * goto sxg_init_bad; + * } + */ DBG_ERROR("sxg: %s ENTER sxg_config_pci\n", __func__); sxg_config_pci(pcidev); @@ -774,16 +1064,13 @@ static int sxg_entry_probe(struct pci_dev *pcidev, adapter->vendid = pci_tbl_entry->vendor; adapter->devid = pci_tbl_entry->device; adapter->subsysid = pci_tbl_entry->subdevice; - adapter->busnumber = pcidev->bus->number; adapter->slotnumber = ((pcidev->devfn >> 3) & 0x1F); adapter->functionnumber = (pcidev->devfn & 0x7); adapter->memorylength = pci_resource_len(pcidev, 0); adapter->irq = pcidev->irq; adapter->next_netdevice = head_netdevice; head_netdevice = netdev; -/* adapter->chipid = chip_idx; */ adapter->port = 0; /*adapter->functionnumber; */ - adapter->cardindex = adapter->port; /* Allocate memory and other resources */ DBG_ERROR("sxg: %s ENTER sxg_allocate_resources\n", __func__); @@ -795,10 +1082,11 @@ static int sxg_entry_probe(struct pci_dev *pcidev, } DBG_ERROR("sxg: %s ENTER sxg_download_microcode\n", __func__); - if (sxg_download_microcode(adapter, SXG_UCODE_SAHARA)) { + if (sxg_download_microcode(adapter, SXG_UCODE_SYSTEM)) { DBG_ERROR("sxg: %s ENTER sxg_adapter_set_hwaddr\n", __func__); - sxg_adapter_set_hwaddr(adapter); + sxg_read_config(adapter); + status = sxg_adapter_set_hwaddr(adapter); } else { adapter->state = ADAPT_FAIL; adapter->linkstate = LINK_DOWN; @@ -811,40 +1099,63 @@ static int sxg_entry_probe(struct pci_dev *pcidev, netdev->stop = sxg_entry_halt; netdev->hard_start_xmit = sxg_send_packets; netdev->do_ioctl = sxg_ioctl; + netdev->change_mtu = sxg_change_mtu; #if XXXTODO netdev->set_mac_address = sxg_mac_set_address; -#if SLIC_GET_STATS_ENABLED +#endif netdev->get_stats = sxg_get_stats; -#endif netdev->set_multicast_list = sxg_mcast_set_list; -#endif + SET_ETHTOOL_OPS(netdev, &sxg_nic_ethtool_ops); + netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + err = sxg_set_interrupt_capability(adapter); + if (err != STATUS_SUCCESS) + DBG_ERROR("Cannot enable MSI-X capability\n"); strcpy(netdev->name, "eth%d"); -/* strcpy(netdev->name, pci_name(pcidev)); */ + /* strcpy(netdev->name, pci_name(pcidev)); */ if ((err = register_netdev(netdev))) { DBG_ERROR("Cannot register net device, aborting. %s\n", netdev->name); goto err_out_unmap; } + netif_napi_add(netdev, &adapter->napi, + sxg_poll, SXG_NETDEV_WEIGHT); + netdev->watchdog_timeo = 2 * HZ; + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = &sxg_watchdog; + adapter->watchdog_timer.data = (unsigned long) adapter; + INIT_WORK(&adapter->update_link_status, sxg_update_link_status); + DBG_ERROR - ("sxg: %s addr 0x%lx, irq %d, MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n", + ("sxg: %s addr 0x%lx, irq %d, MAC addr \ + %02X:%02X:%02X:%02X:%02X:%02X\n", netdev->name, netdev->base_addr, pcidev->irq, netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); -/*sxg_init_bad: */ + /* sxg_init_bad: */ ASSERT(status == FALSE); -/* sxg_free_adapter(adapter); */ + /* sxg_free_adapter(adapter); */ DBG_ERROR("sxg: %s EXIT status[%x] jiffies[%lx] cpu %d\n", __func__, status, jiffies, smp_processor_id()); return status; err_out_unmap: - iounmap((void *)memmapped_ioaddr); + sxg_free_resources(adapter); + + err_out_free_mmio_region_2: + + mmio_start = pci_resource_start(pcidev, 2); + mmio_len = pci_resource_len(pcidev, 2); + release_mem_region(mmio_start, mmio_len); + + err_out_free_mmio_region_0: + + mmio_start = pci_resource_start(pcidev, 0); + mmio_len = pci_resource_len(pcidev, 0); - err_out_free_mmio_region: release_mem_region(mmio_start, mmio_len); err_out_exit_sxg_probe: @@ -852,13 +1163,16 @@ static int sxg_entry_probe(struct pci_dev *pcidev, DBG_ERROR("%s EXIT jiffies[%lx] cpu %d\n", __func__, jiffies, smp_processor_id()); + pci_disable_device(pcidev); + DBG_ERROR("sxg: %s deallocate device\n", __FUNCTION__); + kfree(netdev); + printk("Exit %s, Sxg driver loading failed..\n", __FUNCTION__); + return -ENODEV; } -/*********************************************************************** - * LINE BASE Interrupt routines.. - ***********************************************************************/ /* + * LINE BASE Interrupt routines.. * * sxg_disable_interrupt * @@ -877,10 +1191,7 @@ static void sxg_disable_interrupt(struct adapter_t *adapter) adapter, adapter->InterruptsEnabled, 0, 0); /* For now, RSS is disabled with line based interrupts */ ASSERT(adapter->RssEnabled == FALSE); - ASSERT(adapter->MsiEnabled == FALSE); - /* */ /* Turn off interrupts by writing to the icr register. */ - /* */ WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_DISABLE), TRUE); adapter->InterruptsEnabled = 0; @@ -890,7 +1201,6 @@ static void sxg_disable_interrupt(struct adapter_t *adapter) } /* - * * sxg_enable_interrupt * * EnableInterrupt Handler @@ -908,10 +1218,7 @@ static void sxg_enable_interrupt(struct adapter_t *adapter) adapter, adapter->InterruptsEnabled, 0, 0); /* For now, RSS is disabled with line based interrupts */ ASSERT(adapter->RssEnabled == FALSE); - ASSERT(adapter->MsiEnabled == FALSE); - /* */ /* Turn on interrupts by writing to the icr register. */ - /* */ WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_ENABLE), TRUE); adapter->InterruptsEnabled = 1; @@ -921,50 +1228,51 @@ static void sxg_enable_interrupt(struct adapter_t *adapter) } /* - * * sxg_isr - Process an line-based interrupt * * Arguments: - * Context - Our adapter structure + * Context - Our adapter structure * QueueDefault - Output parameter to queue to default CPU - * TargetCpus - Output bitmap to schedule DPC's + * TargetCpus - Output bitmap to schedule DPC's * - * Return Value: - * TRUE if our interrupt + * Return Value: TRUE if our interrupt */ static irqreturn_t sxg_isr(int irq, void *dev_id) { - p_net_device dev = (p_net_device) dev_id; + struct net_device *dev = (struct net_device *) dev_id; struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); -/* u32 CpuMask = 0, i; */ + if(adapter->state != ADAPT_UP) + return IRQ_NONE; adapter->Stats.NumInts++; if (adapter->Isr[0] == 0) { - /* The SLIC driver used to experience a number of spurious interrupts */ - /* due to the delay associated with the masking of the interrupt */ - /* (we'd bounce back in here). If we see that again with Sahara, */ - /* add a READ_REG of the Icr register after the WRITE_REG below. */ + /* + * The SLIC driver used to experience a number of spurious + * interrupts due to the delay associated with the masking of + * the interrupt (we'd bounce back in here). If we see that + * again with Sahara,add a READ_REG of the Icr register after + * the WRITE_REG below. + */ adapter->Stats.FalseInts++; return IRQ_NONE; } - /* */ - /* Move the Isr contents and clear the value in */ - /* shared memory, and mask interrupts */ - /* */ - adapter->IsrCopy[0] = adapter->Isr[0]; - adapter->Isr[0] = 0; - WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_MASK), TRUE); -/* ASSERT(adapter->IsrDpcsPending == 0); */ + /* + * Move the Isr contents and clear the value in + * shared memory, and mask interrupts + */ + /* ASSERT(adapter->IsrDpcsPending == 0); */ #if XXXTODO /* RSS Stuff */ - /* If RSS is enabled and the ISR specifies */ - /* SXG_ISR_EVENT, then schedule DPC's */ - /* based on event queues. */ + /* + * If RSS is enabled and the ISR specifies SXG_ISR_EVENT, then + * schedule DPC's based on event queues. + */ if (adapter->RssEnabled && (adapter->IsrCopy[0] & SXG_ISR_EVENT)) { for (i = 0; i < adapter->RssSystemInfo->ProcessorInfo.RssCpuCount; i++) { - struct XG_EVENT_RING *EventRing = &adapter->EventRings[i]; - struct SXG_EVENT *Event = + struct sxg_event_ring *EventRing = + &adapter->EventRings[i]; + struct sxg_event *Event = &EventRing->Ring[adapter->NextEvent[i]]; unsigned char Cpu = adapter->RssSystemInfo->RssIdToCpu[i]; @@ -974,8 +1282,10 @@ static irqreturn_t sxg_isr(int irq, void *dev_id) } } } - /* Now, either schedule the CPUs specified by the CpuMask, */ - /* or queue default */ + /* + * Now, either schedule the CPUs specified by the CpuMask, + * or queue default + */ if (CpuMask) { *QueueDefault = FALSE; } else { @@ -984,34 +1294,41 @@ static irqreturn_t sxg_isr(int irq, void *dev_id) } *TargetCpus = CpuMask; #endif - /* */ - /* There are no DPCs in Linux, so call the handler now */ - /* */ - sxg_handle_interrupt(adapter); + sxg_interrupt(adapter); return IRQ_HANDLED; } -static void sxg_handle_interrupt(struct adapter_t *adapter) +static void sxg_interrupt(struct adapter_t *adapter) { -/* unsigned char RssId = 0; */ - u32 NewIsr; + WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_MASK), TRUE); - if (adapter->Stats.RcvNoBuffer < 5) { - DBG_ERROR("Enter sxg_handle_interrupt ISR[%x]\n", - adapter->IsrCopy[0]); + if (napi_schedule_prep(&adapter->napi)) { + __napi_schedule(&adapter->napi); } +} + +static void sxg_handle_interrupt(struct adapter_t *adapter, int *work_done, + int budget) +{ + /* unsigned char RssId = 0; */ + u32 NewIsr; + int sxg_napi_continue = 1; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "HndlIntr", adapter, adapter->IsrCopy[0], 0, 0); /* For now, RSS is disabled with line based interrupts */ ASSERT(adapter->RssEnabled == FALSE); - ASSERT(adapter->MsiEnabled == FALSE); - ASSERT(adapter->IsrCopy[0]); -/*/////////////////////////// */ + + adapter->IsrCopy[0] = adapter->Isr[0]; + adapter->Isr[0] = 0; /* Always process the event queue. */ - sxg_process_event_queue(adapter, - (adapter->RssEnabled ? /*RssId */ 0 : 0)); + while (sxg_napi_continue) + { + sxg_process_event_queue(adapter, + (adapter->RssEnabled ? /*RssId */ 0 : 0), + &sxg_napi_continue, work_done, budget); + } #if XXXTODO /* RSS stuff */ if (--adapter->IsrDpcsPending) { @@ -1022,30 +1339,31 @@ static void sxg_handle_interrupt(struct adapter_t *adapter) return; } #endif - /* */ /* Last (or only) DPC processes the ISR and clears the interrupt. */ - /* */ NewIsr = sxg_process_isr(adapter, 0); - /* */ /* Reenable interrupts */ - /* */ adapter->IsrCopy[0] = 0; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ClearIsr", adapter, NewIsr, 0, 0); - if (adapter->Stats.RcvNoBuffer < 5) { - DBG_ERROR - ("Exit sxg_handle_interrupt2 after enabling interrupt\n"); - } - - WRITE_REG(adapter->UcodeRegs[0].Isr, NewIsr, TRUE); - SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XHndlInt", adapter, 0, 0, 0); } +static int sxg_poll(struct napi_struct *napi, int budget) +{ + struct adapter_t *adapter = container_of(napi, struct adapter_t, napi); + int work_done = 0; + + sxg_handle_interrupt(adapter, &work_done, budget); + + if (work_done < budget) { + napi_complete(napi); + WRITE_REG(adapter->UcodeRegs[0].Isr, 0, TRUE); + } + return work_done; +} /* - * * sxg_process_isr - Process an interrupt. Called from the line-based and * message based interrupt DPC routines * @@ -1072,24 +1390,28 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId) } /* No host buffer */ if (Isr & SXG_ISR_RMISS) { - /* There is a bunch of code in the SLIC driver which */ - /* attempts to process more receive events per DPC */ - /* if we start to fall behind. We'll probably */ - /* need to do something similar here, but hold */ - /* off for now. I don't want to make the code more */ - /* complicated than strictly needed. */ - adapter->Stats.RcvNoBuffer++; - if (adapter->Stats.RcvNoBuffer < 5) { + /* + * There is a bunch of code in the SLIC driver which + * attempts to process more receive events per DPC + * if we start to fall behind. We'll probablyd + * need to do something similar here, but hold + * off for now. I don't want to make the code more + * complicated than strictly needed. + */ + adapter->stats.rx_missed_errors++; + if (adapter->stats.rx_missed_errors< 5) { DBG_ERROR("%s: SXG_ISR_ERR RMISS!!\n", __func__); } } /* Card crash */ if (Isr & SXG_ISR_DEAD) { - /* Set aside the crash info and set the adapter state to RESET */ - adapter->CrashCpu = - (unsigned char)((Isr & SXG_ISR_CPU) >> - SXG_ISR_CPU_SHIFT); + /* + * Set aside the crash info and set the adapter state + * to RESET + */ + adapter->CrashCpu = (unsigned char) + ((Isr & SXG_ISR_CPU) >> SXG_ISR_CPU_SHIFT); adapter->CrashLocation = (ushort) (Isr & SXG_ISR_CRASH); adapter->Dead = TRUE; DBG_ERROR("%s: ISR_DEAD %x, CPU: %d\n", __func__, @@ -1097,18 +1419,18 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId) } /* Event ring full */ if (Isr & SXG_ISR_ERFULL) { - /* Same issue as RMISS, really. This means the */ - /* host is falling behind the card. Need to increase */ - /* event ring size, process more events per interrupt, */ - /* and/or reduce/remove interrupt aggregation. */ + /* + * Same issue as RMISS, really. This means the + * host is falling behind the card. Need to increase + * event ring size, process more events per interrupt, + * and/or reduce/remove interrupt aggregation. + */ adapter->Stats.EventRingFull++; DBG_ERROR("%s: SXG_ISR_ERR EVENT RING FULL!!\n", __func__); } /* Transmit drop - no DRAM buffers or XMT error */ if (Isr & SXG_ISR_XDROP) { - adapter->Stats.XmtDrops++; - adapter->Stats.XmtErrors++; DBG_ERROR("%s: SXG_ISR_ERR XDROP!!\n", __func__); } } @@ -1118,18 +1440,24 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId) } /* Dump */ if (Isr & SXG_ISR_UPC) { - ASSERT(adapter->DumpCmdRunning); /* Maybe change when debug is added.. */ + /* Maybe change when debug is added.. */ +// ASSERT(adapter->DumpCmdRunning); adapter->DumpCmdRunning = FALSE; } /* Link event */ if (Isr & SXG_ISR_LINK) { - sxg_link_event(adapter); + if (adapter->state != ADAPT_DOWN) { + adapter->link_status_changed = 1; + schedule_work(&adapter->update_link_status); + } } /* Debug - breakpoint hit */ if (Isr & SXG_ISR_BREAK) { - /* At the moment AGDB isn't written to support interactive */ - /* debug sessions. When it is, this interrupt will be used */ - /* to signal AGDB that it has hit a breakpoint. For now, ASSERT. */ + /* + * At the moment AGDB isn't written to support interactive + * debug sessions. When it is, this interrupt will be used to + * signal AGDB that it has hit a breakpoint. For now, ASSERT. + */ ASSERT(0); } /* Heartbeat response */ @@ -1143,7 +1471,33 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId) } /* + * sxg_rcv_checksum - Set the checksum for received packet * + * Arguements: + * @adapter - Adapter structure on which packet is received + * @skb - Packet which is receieved + * @Event - Event read from hardware + */ + +void sxg_rcv_checksum(struct adapter_t *adapter, struct sk_buff *skb, + struct sxg_event *Event) +{ + skb->ip_summed = CHECKSUM_NONE; + if (likely(adapter->flags & SXG_RCV_IP_CSUM_ENABLED)) { + if (likely(adapter->flags & SXG_RCV_TCP_CSUM_ENABLED) + && (Event->Status & EVENT_STATUS_TCPIP)) { + if(!(Event->Status & EVENT_STATUS_TCPBAD)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + if(!(Event->Status & EVENT_STATUS_IPBAD)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if(Event->Status & EVENT_STATUS_IPONLY) { + if(!(Event->Status & EVENT_STATUS_IPBAD)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + } +} + +/* * sxg_process_event_queue - Process our event queue * * Arguments: @@ -1153,46 +1507,52 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId) * Return Value: * None. */ -static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId) +static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId, + int *sxg_napi_continue, int *work_done, int budget) { - struct SXG_EVENT_RING *EventRing = &adapter->EventRings[RssId]; - struct SXG_EVENT *Event = &EventRing->Ring[adapter->NextEvent[RssId]]; + struct sxg_event_ring *EventRing = &adapter->EventRings[RssId]; + struct sxg_event *Event = &EventRing->Ring[adapter->NextEvent[RssId]]; u32 EventsProcessed = 0, Batches = 0; - u32 num_skbs = 0; struct sk_buff *skb; #ifdef LINUX_HANDLES_RCV_INDICATION_LISTS struct sk_buff *prev_skb = NULL; struct sk_buff *IndicationList[SXG_RCV_ARRAYSIZE]; u32 Index; - struct SXG_RCV_DATA_BUFFER_HDR *RcvDataBufferHdr; + struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr; #endif u32 ReturnStatus = 0; + int sxg_rcv_data_buffers = SXG_RCV_DATA_BUFFERS; ASSERT((adapter->State == SXG_STATE_RUNNING) || (adapter->State == SXG_STATE_PAUSING) || (adapter->State == SXG_STATE_PAUSED) || (adapter->State == SXG_STATE_HALTING)); - /* We may still have unprocessed events on the queue if */ - /* the card crashed. Don't process them. */ + /* + * We may still have unprocessed events on the queue if + * the card crashed. Don't process them. + */ if (adapter->Dead) { return (0); } - /* In theory there should only be a single processor that */ - /* accesses this queue, and only at interrupt-DPC time. So */ - /* we shouldn't need a lock for any of this. */ + /* + * In theory there should only be a single processor that + * accesses this queue, and only at interrupt-DPC time. So/ + * we shouldn't need a lock for any of this. + */ while (Event->Status & EVENT_STATUS_VALID) { + (*sxg_napi_continue) = 1; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "Event", Event, Event->Code, Event->Status, adapter->NextEvent); switch (Event->Code) { case EVENT_CODE_BUFFERS: - ASSERT(!(Event->CommandIndex & 0xFF00)); /* SXG_RING_INFO Head & Tail == unsigned char */ - /* */ + /* struct sxg_ring_info Head & Tail == unsigned char */ + ASSERT(!(Event->CommandIndex & 0xFF00)); sxg_complete_descriptor_blocks(adapter, Event->CommandIndex); - /* */ break; case EVENT_CODE_SLOWRCV: + (*work_done)++; --adapter->RcvBuffersOnCard; if ((skb = sxg_slow_receive(adapter, Event))) { u32 rx_bytes; @@ -1200,51 +1560,61 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId) /* Add it to our indication list */ SXG_ADD_RCV_PACKET(adapter, skb, prev_skb, IndicationList, num_skbs); - /* In Linux, we just pass up each skb to the protocol above at this point, */ - /* there is no capability of an indication list. */ + /* + * Linux, we just pass up each skb to the + * protocol above at this point, there is no + * capability of an indication list. + */ #else -/* CHECK skb_pull(skb, INIC_RCVBUF_HEADSIZE); */ - rx_bytes = Event->Length; /* (rcvbuf->length & IRHDDR_FLEN_MSK); */ - skb_put(skb, rx_bytes); + /* CHECK skb_pull(skb, INIC_RCVBUF_HEADSIZE); */ + /* (rcvbuf->length & IRHDDR_FLEN_MSK); */ + rx_bytes = Event->Length; adapter->stats.rx_packets++; adapter->stats.rx_bytes += rx_bytes; -#if SXG_OFFLOAD_IP_CHECKSUM - skb->ip_summed = CHECKSUM_UNNECESSARY; -#endif + sxg_rcv_checksum(adapter, skb, Event); skb->dev = adapter->netdev; - skb->protocol = eth_type_trans(skb, skb->dev); - netif_rx(skb); + netif_receive_skb(skb); #endif } break; default: DBG_ERROR("%s: ERROR Invalid EventCode %d\n", __func__, Event->Code); -/* ASSERT(0); */ + /* ASSERT(0); */ } - /* See if we need to restock card receive buffers. */ - /* There are two things to note here: */ - /* First - This test is not SMP safe. The */ - /* adapter->BuffersOnCard field is protected via atomic interlocked calls, but */ - /* we do not protect it with respect to these tests. The only way to do that */ - /* is with a lock, and I don't want to grab a lock every time we adjust the */ - /* BuffersOnCard count. Instead, we allow the buffer replenishment to be off */ - /* once in a while. The worst that can happen is the card is given one */ - /* more-or-less descriptor block than the arbitrary value we've chosen. */ - /* No big deal */ - /* In short DO NOT ADD A LOCK HERE, OR WHERE RcvBuffersOnCard is adjusted. */ - /* Second - We expect this test to rarely evaluate to true. We attempt to */ - /* refill descriptor blocks as they are returned to us */ - /* (sxg_complete_descriptor_blocks), so The only time this should evaluate */ - /* to true is when sxg_complete_descriptor_blocks failed to allocate */ - /* receive buffers. */ - if (adapter->RcvBuffersOnCard < SXG_RCV_DATA_BUFFERS) { + /* + * See if we need to restock card receive buffers. + * There are two things to note here: + * First - This test is not SMP safe. The + * adapter->BuffersOnCard field is protected via atomic + * interlocked calls, but we do not protect it with respect + * to these tests. The only way to do that is with a lock, + * and I don't want to grab a lock every time we adjust the + * BuffersOnCard count. Instead, we allow the buffer + * replenishment to be off once in a while. The worst that + * can happen is the card is given on more-or-less descriptor + * block than the arbitrary value we've chosen. No big deal + * In short DO NOT ADD A LOCK HERE, OR WHERE RcvBuffersOnCard + * is adjusted. + * Second - We expect this test to rarely + * evaluate to true. We attempt to refill descriptor blocks + * as they are returned to us (sxg_complete_descriptor_blocks) + * so The only time this should evaluate to true is when + * sxg_complete_descriptor_blocks failed to allocate + * receive buffers. + */ + if (adapter->JumboEnabled) + sxg_rcv_data_buffers = SXG_JUMBO_RCV_DATA_BUFFERS; + + if (adapter->RcvBuffersOnCard < sxg_rcv_data_buffers) { sxg_stock_rcv_buffers(adapter); } - /* It's more efficient to just set this to zero. */ - /* But clearing the top bit saves potential debug info... */ + /* + * It's more efficient to just set this to zero. + * But clearing the top bit saves potential debug info... + */ Event->Status &= ~EVENT_STATUS_VALID; - /* Advanct to the next event */ + /* Advance to the next event */ SXG_ADVANCE_INDEX(adapter->NextEvent[RssId], EVENT_RING_SIZE); Event = &EventRing->Ring[adapter->NextEvent[RssId]]; EventsProcessed++; @@ -1253,9 +1623,11 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId) WRITE_REG(adapter->UcodeRegs[RssId].EventRelease, EVENT_RING_BATCH, FALSE); EventsProcessed = 0; - /* If we've processed our batch limit, break out of the */ - /* loop and return SXG_ISR_EVENT to arrange for us to */ - /* be called again */ + /* + * If we've processed our batch limit, break out of the + * loop and return SXG_ISR_EVENT to arrange for us to + * be called again + */ if (Batches++ == EVENT_BATCH_LIMIT) { SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "EvtLimit", Batches, @@ -1264,16 +1636,22 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId) break; } } + if (*work_done >= budget) { + WRITE_REG(adapter->UcodeRegs[RssId].EventRelease, + EventsProcessed, FALSE); + EventsProcessed = 0; + (*sxg_napi_continue) = 0; + break; + } } + if (!(Event->Status & EVENT_STATUS_VALID)) + (*sxg_napi_continue) = 0; + #ifdef LINUX_HANDLES_RCV_INDICATION_LISTS - /* */ /* Indicate any received dumb-nic frames */ - /* */ SXG_INDICATE_PACKETS(adapter, IndicationList, num_skbs); #endif - /* */ /* Release events back to the card. */ - /* */ if (EventsProcessed) { WRITE_REG(adapter->UcodeRegs[RssId].EventRelease, EventsProcessed, FALSE); @@ -1289,27 +1667,35 @@ static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId) * * Arguments - * adapter - A pointer to our adapter structure - * Return * None */ static void sxg_complete_slow_send(struct adapter_t *adapter) { - struct SXG_XMT_RING *XmtRing = &adapter->XmtRings[0]; - struct SXG_RING_INFO *XmtRingInfo = &adapter->XmtRingZeroInfo; + struct sxg_xmt_ring *XmtRing = &adapter->XmtRings[0]; + struct sxg_ring_info *XmtRingInfo = &adapter->XmtRingZeroInfo; u32 *ContextType; - struct SXG_CMD *XmtCmd; + struct sxg_cmd *XmtCmd; + unsigned long flags = 0; + unsigned long sgl_flags = 0; + unsigned int processed_count = 0; + + /* + * NOTE - This lock is dropped and regrabbed in this loop. + * This means two different processors can both be running/ + * through this loop. Be *very* careful. + */ + spin_lock_irqsave(&adapter->XmtZeroLock, flags); - /* NOTE - This lock is dropped and regrabbed in this loop. */ - /* This means two different processors can both be running */ - /* through this loop. Be *very* careful. */ - spin_lock(&adapter->XmtZeroLock); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnds", adapter, XmtRingInfo->Head, XmtRingInfo->Tail, 0); - while (XmtRingInfo->Tail != *adapter->XmtRingZeroIndex) { - /* Locate the current Cmd (ring descriptor entry), and */ - /* associated SGL, and advance the tail */ + while ((XmtRingInfo->Tail != *adapter->XmtRingZeroIndex) + && processed_count++ < SXG_COMPLETE_SLOW_SEND_LIMIT) { + /* + * Locate the current Cmd (ring descriptor entry), and + * associated SGL, and advance the tail + */ SXG_RETURN_CMD(XmtRing, XmtRingInfo, XmtCmd, ContextType); ASSERT(ContextType); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnd", @@ -1321,30 +1707,45 @@ static void sxg_complete_slow_send(struct adapter_t *adapter) case SXG_SGL_DUMB: { struct sk_buff *skb; + struct sxg_scatter_gather *SxgSgl = + (struct sxg_scatter_gather *)ContextType; + dma64_addr_t FirstSgeAddress; + u32 FirstSgeLength; + /* Dumb-nic send. Command context is the dumb-nic SGL */ skb = (struct sk_buff *)ContextType; + skb = SxgSgl->DumbPacket; + FirstSgeAddress = XmtCmd->Buffer.FirstSgeAddress; + FirstSgeLength = XmtCmd->Buffer.FirstSgeLength; /* Complete the send */ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DmSndCmp", skb, 0, 0, 0); ASSERT(adapter->Stats.XmtQLen); - adapter->Stats.XmtQLen--; /* within XmtZeroLock */ - adapter->Stats.XmtOk++; - /* Now drop the lock and complete the send back to */ - /* Microsoft. We need to drop the lock because */ - /* Microsoft can come back with a chimney send, which */ - /* results in a double trip in SxgTcpOuput */ - spin_unlock(&adapter->XmtZeroLock); - SXG_COMPLETE_DUMB_SEND(adapter, skb); + /* + * Now drop the lock and complete the send + * back to Microsoft. We need to drop the lock + * because Microsoft can come back with a + * chimney send, which results in a double trip + * in SxgTcpOuput + */ + spin_unlock_irqrestore( + &adapter->XmtZeroLock, flags); + + SxgSgl->DumbPacket = NULL; + SXG_COMPLETE_DUMB_SEND(adapter, skb, + FirstSgeAddress, + FirstSgeLength); + SXG_FREE_SGL_BUFFER(adapter, SxgSgl, NULL); /* and reacquire.. */ - spin_lock(&adapter->XmtZeroLock); + spin_lock_irqsave(&adapter->XmtZeroLock, flags); } break; default: ASSERT(0); } } - spin_unlock(&adapter->XmtZeroLock); + spin_unlock_irqrestore(&adapter->XmtZeroLock, flags); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnd", adapter, XmtRingInfo->Head, XmtRingInfo->Tail, 0); } @@ -1356,22 +1757,27 @@ static void sxg_complete_slow_send(struct adapter_t *adapter) * adapter - A pointer to our adapter structure * Event - Receive event * - * Return - * skb + * Return - skb */ -static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter, struct SXG_EVENT *Event) +static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter, + struct sxg_event *Event) { - struct SXG_RCV_DATA_BUFFER_HDR *RcvDataBufferHdr; + u32 BufferSize = adapter->ReceiveBufferSize; + struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr; struct sk_buff *Packet; + static int read_counter = 0; - RcvDataBufferHdr = (struct SXG_RCV_DATA_BUFFER_HDR*) Event->HostHandle; + RcvDataBufferHdr = (struct sxg_rcv_data_buffer_hdr *) Event->HostHandle; + if(read_counter++ & 0x100) + { + sxg_collect_statistics(adapter); + read_counter = 0; + } ASSERT(RcvDataBufferHdr); ASSERT(RcvDataBufferHdr->State == SXG_BUFFER_ONCARD); - ASSERT(SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr) == - RcvDataBufferHdr->VirtualAddress); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "SlowRcv", Event, RcvDataBufferHdr, RcvDataBufferHdr->State, - RcvDataBufferHdr->VirtualAddress); + /*RcvDataBufferHdr->VirtualAddress*/ 0); /* Drop rcv frames in non-running state */ switch (adapter->State) { case SXG_STATE_RUNNING: @@ -1385,14 +1791,16 @@ static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter, struct SXG_EV goto drop; } + /* + * memcpy(SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr), + * RcvDataBufferHdr->VirtualAddress, Event->Length); + */ + /* Change buffer state to UPSTREAM */ RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM; if (Event->Status & EVENT_STATUS_RCVERR) { SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RcvError", Event, Event->Status, Event->HostHandle, 0); - /* XXXTODO - Remove this print later */ - DBG_ERROR("SXG: Receive error %x\n", *(u32 *) - SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr)); sxg_process_rcv_error(adapter, *(u32 *) SXG_RECEIVE_DATA_LOCATION (RcvDataBufferHdr)); @@ -1400,8 +1808,9 @@ static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter, struct SXG_EV } #if XXXTODO /* VLAN stuff */ /* If there's a VLAN tag, extract it and validate it */ - if (((struct ether_header*) (SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr)))-> - EtherType == ETHERTYPE_VLAN) { + if (((struct ether_header *) + (SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr)))->EtherType + == ETHERTYPE_VLAN) { if (SxgExtractVlanHeader(adapter, RcvDataBufferHdr, Event) != STATUS_SUCCESS) { SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, @@ -1412,33 +1821,41 @@ static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter, struct SXG_EV } } #endif - /* */ /* Dumb-nic frame. See if it passes our mac filter and update stats */ - /* */ - if (!sxg_mac_filter(adapter, (struct ether_header*) - SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr), - Event->Length)) { + + if (!sxg_mac_filter(adapter, + (struct ether_header *)(SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr)), + Event->Length)) { SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RcvFiltr", - Event, SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr), - Event->Length, 0); - goto drop; + Event, SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr), + Event->Length, 0); + goto drop; } Packet = RcvDataBufferHdr->SxgDumbRcvPacket; + SXG_ADJUST_RCV_PACKET(Packet, RcvDataBufferHdr, Event); + Packet->protocol = eth_type_trans(Packet, adapter->netdev); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumbRcv", RcvDataBufferHdr, Packet, Event->Length, 0); - /* */ /* Lastly adjust the receive packet length. */ - /* */ - SXG_ADJUST_RCV_PACKET(Packet, RcvDataBufferHdr, Event); - + RcvDataBufferHdr->SxgDumbRcvPacket = NULL; + RcvDataBufferHdr->PhysicalAddress = (dma_addr_t)NULL; + SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr, BufferSize); + if (RcvDataBufferHdr->skb) + { + spin_lock(&adapter->RcvQLock); + SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr); + // adapter->RcvBuffersOnCard ++; + spin_unlock(&adapter->RcvQLock); + } return (Packet); drop: SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DropRcv", RcvDataBufferHdr, Event->Length, 0, 0); - adapter->Stats.RcvDiscards++; + adapter->stats.rx_dropped++; +// adapter->Stats.RcvDiscards++; spin_lock(&adapter->RcvQLock); SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr); spin_unlock(&adapter->RcvQLock); @@ -1453,14 +1870,13 @@ static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter, struct SXG_EV * adapter - Adapter structure * ErrorStatus - 4-byte receive error status * - * Return Value: - * None + * Return Value : None */ static void sxg_process_rcv_error(struct adapter_t *adapter, u32 ErrorStatus) { u32 Error; - adapter->Stats.RcvErrors++; + adapter->stats.rx_errors++; if (ErrorStatus & SXG_RCV_STATUS_TRANSPORT_ERROR) { Error = ErrorStatus & SXG_RCV_STATUS_TRANSPORT_MASK; @@ -1532,13 +1948,13 @@ static void sxg_process_rcv_error(struct adapter_t *adapter, u32 ErrorStatus) * pether - Ethernet header * length - Frame length * - * Return Value: - * TRUE if the frame is to be allowed + * Return Value : TRUE if the frame is to be allowed */ -static bool sxg_mac_filter(struct adapter_t *adapter, struct ether_header *EtherHdr, - ushort length) +static bool sxg_mac_filter(struct adapter_t *adapter, + struct ether_header *EtherHdr, ushort length) { bool EqualAddr; + struct net_device *dev = adapter->netdev; if (SXG_MULTICAST_PACKET(EtherHdr)) { if (SXG_BROADCAST_PACKET(EtherHdr)) { @@ -1546,8 +1962,6 @@ static bool sxg_mac_filter(struct adapter_t *adapter, struct ether_header *Ether if (adapter->MacFilter & MAC_BCAST) { adapter->Stats.DumbRcvBcastPkts++; adapter->Stats.DumbRcvBcastBytes += length; - adapter->Stats.DumbRcvPkts++; - adapter->Stats.DumbRcvBytes += length; return (TRUE); } } else { @@ -1555,15 +1969,12 @@ static bool sxg_mac_filter(struct adapter_t *adapter, struct ether_header *Ether if (adapter->MacFilter & MAC_ALLMCAST) { adapter->Stats.DumbRcvMcastPkts++; adapter->Stats.DumbRcvMcastBytes += length; - adapter->Stats.DumbRcvPkts++; - adapter->Stats.DumbRcvBytes += length; return (TRUE); } if (adapter->MacFilter & MAC_MCAST) { - struct SXG_MULTICAST_ADDRESS *MulticastAddrs = - adapter->MulticastAddrs; - while (MulticastAddrs) { - ETHER_EQ_ADDR(MulticastAddrs->Address, + struct dev_mc_list *mclist = dev->mc_list; + while (mclist) { + ETHER_EQ_ADDR(mclist->da_addr, EtherHdr->ether_dhost, EqualAddr); if (EqualAddr) { @@ -1571,32 +1982,26 @@ static bool sxg_mac_filter(struct adapter_t *adapter, struct ether_header *Ether DumbRcvMcastPkts++; adapter->Stats. DumbRcvMcastBytes += length; - adapter->Stats.DumbRcvPkts++; - adapter->Stats.DumbRcvBytes += - length; return (TRUE); } - MulticastAddrs = MulticastAddrs->Next; + mclist = mclist->next; } } } } else if (adapter->MacFilter & MAC_DIRECTED) { - /* Not broadcast or multicast. Must be directed at us or */ - /* the card is in promiscuous mode. Either way, consider it */ - /* ours if MAC_DIRECTED is set */ + /* + * Not broadcast or multicast. Must be directed at us or + * the card is in promiscuous mode. Either way, consider it + * ours if MAC_DIRECTED is set + */ adapter->Stats.DumbRcvUcastPkts++; adapter->Stats.DumbRcvUcastBytes += length; - adapter->Stats.DumbRcvPkts++; - adapter->Stats.DumbRcvBytes += length; return (TRUE); } if (adapter->MacFilter & MAC_PROMISC) { /* Whatever it is, keep it. */ - adapter->Stats.DumbRcvPkts++; - adapter->Stats.DumbRcvBytes += length; return (TRUE); } - adapter->Stats.RcvDiscards++; return (FALSE); } @@ -1627,7 +2032,6 @@ static int sxg_register_interrupt(struct adapter_t *adapter) adapter->intrregistered = 1; adapter->IntRegistered = TRUE; /* Disable RSS with line-based interrupts */ - adapter->MsiEnabled = FALSE; adapter->RssEnabled = FALSE; DBG_ERROR("sxg: %s AllocAdaptRsrcs adapter[%p] dev->irq[%x]\n", __func__, adapter, adapter->netdev->irq); @@ -1663,12 +2067,12 @@ static void sxg_deregister_interrupt(struct adapter_t *adapter) */ static int sxg_if_init(struct adapter_t *adapter) { - p_net_device dev = adapter->netdev; + struct net_device *dev = adapter->netdev; int status = 0; - DBG_ERROR("sxg: %s (%s) ENTER states[%d:%d:%d] flags[%x]\n", + DBG_ERROR("sxg: %s (%s) ENTER states[%d:%d] flags[%x]\n", __func__, adapter->netdev->name, - adapter->queues_initialized, adapter->state, + adapter->state, adapter->linkstate, dev->flags); /* adapter should be down at this point */ @@ -1679,31 +2083,31 @@ static int sxg_if_init(struct adapter_t *adapter) ASSERT(adapter->linkstate == LINK_DOWN); adapter->devflags_prev = dev->flags; - adapter->macopts = MAC_DIRECTED; + adapter->MacFilter = MAC_DIRECTED; if (dev->flags) { DBG_ERROR("sxg: %s (%s) Set MAC options: ", __func__, adapter->netdev->name); if (dev->flags & IFF_BROADCAST) { - adapter->macopts |= MAC_BCAST; + adapter->MacFilter |= MAC_BCAST; DBG_ERROR("BCAST "); } if (dev->flags & IFF_PROMISC) { - adapter->macopts |= MAC_PROMISC; + adapter->MacFilter |= MAC_PROMISC; DBG_ERROR("PROMISC "); } if (dev->flags & IFF_ALLMULTI) { - adapter->macopts |= MAC_ALLMCAST; + adapter->MacFilter |= MAC_ALLMCAST; DBG_ERROR("ALL_MCAST "); } if (dev->flags & IFF_MULTICAST) { - adapter->macopts |= MAC_MCAST; + adapter->MacFilter |= MAC_MCAST; DBG_ERROR("MCAST "); } DBG_ERROR("\n"); } - status = sxg_register_interrupt(adapter); + status = sxg_register_intr(adapter); if (status != STATUS_SUCCESS) { - DBG_ERROR("sxg_if_init: sxg_register_interrupt FAILED %x\n", + DBG_ERROR("sxg_if_init: sxg_register_intr FAILED %x\n", status); sxg_deregister_interrupt(adapter); return (status); @@ -1711,18 +2115,90 @@ static int sxg_if_init(struct adapter_t *adapter) adapter->state = ADAPT_UP; - /* - * clear any pending events, then enable interrupts - */ + /* clear any pending events, then enable interrupts */ DBG_ERROR("sxg: %s ENABLE interrupts(slic)\n", __func__); return (STATUS_SUCCESS); } -static int sxg_entry_open(p_net_device dev) +void sxg_set_interrupt_aggregation(struct adapter_t *adapter) +{ + /* + * Top bit disables aggregation on xmt (SXG_AGG_XMT_DISABLE). + * Make sure Max is less than 0x8000. + */ + adapter->max_aggregation = SXG_MAX_AGG_DEFAULT; + adapter->min_aggregation = SXG_MIN_AGG_DEFAULT; + WRITE_REG(adapter->UcodeRegs[0].Aggregation, + ((adapter->max_aggregation << SXG_MAX_AGG_SHIFT) | + adapter->min_aggregation), + TRUE); +} + +static int sxg_entry_open(struct net_device *dev) { struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); int status; + static int turn; + int sxg_initial_rcv_data_buffers = SXG_INITIAL_RCV_DATA_BUFFERS; + int i; + + if (adapter->JumboEnabled == TRUE) { + sxg_initial_rcv_data_buffers = + SXG_INITIAL_JUMBO_RCV_DATA_BUFFERS; + SXG_INITIALIZE_RING(adapter->RcvRingZeroInfo, + SXG_JUMBO_RCV_RING_SIZE); + } + + /* + * Allocate receive data buffers. We allocate a block of buffers and + * a corresponding descriptor block at once. See sxghw.h:SXG_RCV_BLOCK + */ + + for (i = 0; i < sxg_initial_rcv_data_buffers; + i += SXG_RCV_DESCRIPTORS_PER_BLOCK) + { + status = sxg_allocate_buffer_memory(adapter, + SXG_RCV_BLOCK_SIZE(SXG_RCV_DATA_HDR_SIZE), + SXG_BUFFER_TYPE_RCV); + if (status != STATUS_SUCCESS) + return status; + } + /* + * NBL resource allocation can fail in the 'AllocateComplete' routine, + * which doesn't return status. Make sure we got the number of buffers + * we requested + */ + + if (adapter->FreeRcvBufferCount < sxg_initial_rcv_data_buffers) { + SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF6", + adapter, adapter->FreeRcvBufferCount, SXG_MAX_ENTRIES, + 0); + return (STATUS_RESOURCES); + } + /* + * The microcode expects it to be downloaded on every open. + */ + DBG_ERROR("sxg: %s ENTER sxg_download_microcode\n", __FUNCTION__); + if (sxg_download_microcode(adapter, SXG_UCODE_SYSTEM)) { + DBG_ERROR("sxg: %s ENTER sxg_adapter_set_hwaddr\n", + __FUNCTION__); + sxg_read_config(adapter); + } else { + adapter->state = ADAPT_FAIL; + adapter->linkstate = LINK_DOWN; + DBG_ERROR("sxg_download_microcode FAILED status[%x]\n", + status); + } + msleep(5); + + if (turn) { + sxg_second_open(adapter->netdev); + + return STATUS_SUCCESS; + } + + turn++; ASSERT(adapter); DBG_ERROR("sxg: %s adapter->activated[%d]\n", __func__, @@ -1762,6 +2238,8 @@ static int sxg_entry_open(p_net_device dev) return (status); } DBG_ERROR("sxg: %s ENABLE ALL INTERRUPTS\n", __func__); + sxg_set_interrupt_aggregation(adapter); + napi_enable(&adapter->napi); /* Enable interrupts */ SXG_ENABLE_ALL_INTERRUPTS(adapter); @@ -1772,71 +2250,162 @@ static int sxg_entry_open(p_net_device dev) return STATUS_SUCCESS; } +int sxg_second_open(struct net_device * dev) +{ + struct adapter_t *adapter = (struct adapter_t*) netdev_priv(dev); + int status = 0; + + spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags); + netif_start_queue(adapter->netdev); + adapter->state = ADAPT_UP; + adapter->linkstate = LINK_UP; + + status = sxg_initialize_adapter(adapter); + sxg_set_interrupt_aggregation(adapter); + napi_enable(&adapter->napi); + /* Re-enable interrupts */ + SXG_ENABLE_ALL_INTERRUPTS(adapter); + + sxg_register_intr(adapter); + spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags); + mod_timer(&adapter->watchdog_timer, jiffies); + return (STATUS_SUCCESS); + +} + static void __devexit sxg_entry_remove(struct pci_dev *pcidev) { - p_net_device dev = pci_get_drvdata(pcidev); - u32 mmio_start = 0; - unsigned int mmio_len = 0; + u32 mmio_start = 0; + u32 mmio_len = 0; + + struct net_device *dev = pci_get_drvdata(pcidev); struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); - ASSERT(adapter); - DBG_ERROR("sxg: %s ENTER dev[%p] adapter[%p]\n", __func__, dev, - adapter); - sxg_deregister_interrupt(adapter); - sxg_unmap_mmio_space(adapter); - DBG_ERROR("sxg: %s unregister_netdev\n", __func__); + flush_scheduled_work(); + + /* Deallocate Resources */ unregister_netdev(dev); + sxg_reset_interrupt_capability(adapter); + sxg_free_resources(adapter); - mmio_start = pci_resource_start(pcidev, 0); - mmio_len = pci_resource_len(pcidev, 0); + ASSERT(adapter); - DBG_ERROR("sxg: %s rel_region(0) start[%x] len[%x]\n", __func__, - mmio_start, mmio_len); - release_mem_region(mmio_start, mmio_len); + mmio_start = pci_resource_start(pcidev, 0); + mmio_len = pci_resource_len(pcidev, 0); - DBG_ERROR("sxg: %s iounmap dev->base_addr[%x]\n", __func__, - (unsigned int)dev->base_addr); - iounmap((char *)dev->base_addr); + DBG_ERROR("sxg: %s rel_region(0) start[%x] len[%x]\n", __FUNCTION__, + mmio_start, mmio_len); + release_mem_region(mmio_start, mmio_len); + + mmio_start = pci_resource_start(pcidev, 2); + mmio_len = pci_resource_len(pcidev, 2); + + DBG_ERROR("sxg: %s rel_region(2) start[%x] len[%x]\n", __FUNCTION__, + mmio_start, mmio_len); + release_mem_region(mmio_start, mmio_len); + + pci_disable_device(pcidev); DBG_ERROR("sxg: %s deallocate device\n", __func__); kfree(dev); DBG_ERROR("sxg: %s EXIT\n", __func__); } -static int sxg_entry_halt(p_net_device dev) +static int sxg_entry_halt(struct net_device *dev) { struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); + struct sxg_hw_regs *HwRegs = adapter->HwRegs; + int i; + u32 RssIds, IsrCount; + unsigned long flags; + RssIds = SXG_RSS_CPU_COUNT(adapter); + IsrCount = adapter->msi_enabled ? RssIds : 1; + /* Disable interrupts */ spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags); - DBG_ERROR("sxg: %s (%s) ENTER\n", __func__, dev->name); - - netif_stop_queue(adapter->netdev); + SXG_DISABLE_ALL_INTERRUPTS(adapter); adapter->state = ADAPT_DOWN; adapter->linkstate = LINK_DOWN; + + spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags); + sxg_deregister_interrupt(adapter); + WRITE_REG(HwRegs->Reset, 0xDEAD, FLUSH); + mdelay(5000); + + del_timer_sync(&adapter->watchdog_timer); + netif_stop_queue(dev); + netif_carrier_off(dev); + + napi_disable(&adapter->napi); + + WRITE_REG(adapter->UcodeRegs[0].RcvCmd, 0, true); adapter->devflags_prev = 0; DBG_ERROR("sxg: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n", __func__, dev->name, adapter, adapter->state); - DBG_ERROR("sxg: %s (%s) EXIT\n", __func__, dev->name); - DBG_ERROR("sxg: %s EXIT\n", __func__); - spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags); + spin_lock(&adapter->RcvQLock); + /* Free all the blocks and the buffers, moved from remove() routine */ + if (!(IsListEmpty(&adapter->AllRcvBlocks))) { + sxg_free_rcvblocks(adapter); + } + + + InitializeListHead(&adapter->FreeRcvBuffers); + InitializeListHead(&adapter->FreeRcvBlocks); + InitializeListHead(&adapter->AllRcvBlocks); + InitializeListHead(&adapter->FreeSglBuffers); + InitializeListHead(&adapter->AllSglBuffers); + + adapter->FreeRcvBufferCount = 0; + adapter->FreeRcvBlockCount = 0; + adapter->AllRcvBlockCount = 0; + adapter->RcvBuffersOnCard = 0; + adapter->PendingRcvCount = 0; + + memset(adapter->RcvRings, 0, sizeof(struct sxg_rcv_ring) * 1); + memset(adapter->EventRings, 0, sizeof(struct sxg_event_ring) * RssIds); + memset(adapter->Isr, 0, sizeof(u32) * IsrCount); + for (i = 0; i < SXG_MAX_RING_SIZE; i++) + adapter->RcvRingZeroInfo.Context[i] = NULL; + SXG_INITIALIZE_RING(adapter->RcvRingZeroInfo, SXG_RCV_RING_SIZE); + SXG_INITIALIZE_RING(adapter->XmtRingZeroInfo, SXG_XMT_RING_SIZE); + + spin_unlock(&adapter->RcvQLock); + + spin_lock_irqsave(&adapter->XmtZeroLock, flags); + adapter->AllSglBufferCount = 0; + adapter->FreeSglBufferCount = 0; + adapter->PendingXmtCount = 0; + memset(adapter->XmtRings, 0, sizeof(struct sxg_xmt_ring) * 1); + memset(adapter->XmtRingZeroIndex, 0, sizeof(u32)); + spin_unlock_irqrestore(&adapter->XmtZeroLock, flags); + + for (i = 0; i < SXG_MAX_RSS; i++) { + adapter->NextEvent[i] = 0; + } + atomic_set(&adapter->pending_allocations, 0); + adapter->intrregistered = 0; + sxg_remove_isr(adapter); + DBG_ERROR("sxg: %s (%s) EXIT\n", __FUNCTION__, dev->name); return (STATUS_SUCCESS); } -static int sxg_ioctl(p_net_device dev, struct ifreq *rq, int cmd) +static int sxg_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { ASSERT(rq); -/* DBG_ERROR("sxg: %s cmd[%x] rq[%p] dev[%p]\n", __func__, cmd, rq, dev); */ +/* DBG_ERROR("sxg: %s cmd[%x] rq[%p] dev[%p]\n", __func__, cmd, rq, dev);*/ switch (cmd) { case SIOCSLICSETINTAGG: { -/* struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); */ + /* struct adapter_t *adapter = (struct adapter_t *) + * netdev_priv(dev); + */ u32 data[7]; u32 intagg; if (copy_from_user(data, rq->ifr_data, 28)) { - DBG_ERROR - ("copy_from_user FAILED getting initial params\n"); + DBG_ERROR("copy_from_user FAILED getting \ + initial params\n"); return -EFAULT; } intagg = data[0]; @@ -1847,7 +2416,7 @@ static int sxg_ioctl(p_net_device dev, struct ifreq *rq, int cmd) } default: -/* DBG_ERROR("sxg: %s UNSUPPORTED[%x]\n", __func__, cmd); */ + /* DBG_ERROR("sxg: %s UNSUPPORTED[%x]\n", __func__, cmd); */ return -EOPNOTSUPP; } return 0; @@ -1856,23 +2425,25 @@ static int sxg_ioctl(p_net_device dev, struct ifreq *rq, int cmd) #define NORMAL_ETHFRAME 0 /* - * * sxg_send_packets - Send a skb packet * * Arguments: - * skb - The packet to send - * dev - Our linux net device that refs our adapter + * skb - The packet to send + * dev - Our linux net device that refs our adapter * * Return: * 0 regardless of outcome XXXTODO refer to e1000 driver */ -static int sxg_send_packets(struct sk_buff *skb, p_net_device dev) +static int sxg_send_packets(struct sk_buff *skb, struct net_device *dev) { struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); u32 status = STATUS_SUCCESS; - DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __func__, - skb); + /* + * DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __FUNCTION__, + * skb); + */ + /* Check the adapter state */ switch (adapter->State) { case SXG_STATE_INITIALIZING: @@ -1909,17 +2480,18 @@ static int sxg_send_packets(struct sk_buff *skb, p_net_device dev) /* reject & complete all the packets if they cant be sent */ if (status != STATUS_SUCCESS) { #if XXXTODO -/* sxg_send_packets_fail(adapter, skb, status); */ + /* sxg_send_packets_fail(adapter, skb, status); */ #else SXG_DROP_DUMB_SEND(adapter, skb); adapter->stats.tx_dropped++; + return NETDEV_TX_BUSY; #endif } DBG_ERROR("sxg: %s EXIT sxg_send_packets status[%x]\n", __func__, status); xmit_done: - return 0; + return NETDEV_TX_OK; } /* @@ -1931,33 +2503,35 @@ static int sxg_send_packets(struct sk_buff *skb, p_net_device dev) * adapter - Pointer to our adapter structure * skb - The packet to be sent * - * Return - - * STATUS of send + * Return - STATUS of send */ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb) { - struct SCATTER_GATHER_LIST *pSgl; - struct SXG_SCATTER_GATHER *SxgSgl; - void *SglBuffer; - u32 SglBufferLength; + struct sxg_x64_sgl *pSgl; + struct sxg_scatter_gather *SxgSgl; + unsigned long sgl_flags; + /* void *SglBuffer; */ + /* u32 SglBufferLength; */ - /* The vast majority of work is done in the shared */ - /* sxg_dumb_sgl routine. */ + /* + * The vast majority of work is done in the shared + * sxg_dumb_sgl routine. + */ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSend", adapter, skb, 0, 0); /* Allocate a SGL buffer */ - SXG_GET_SGL_BUFFER(adapter, SxgSgl); + SXG_GET_SGL_BUFFER(adapter, SxgSgl, 0); if (!SxgSgl) { adapter->Stats.NoSglBuf++; - adapter->Stats.XmtErrors++; + adapter->stats.tx_errors++; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "SndPktF1", adapter, skb, 0, 0); return (STATUS_RESOURCES); } ASSERT(SxgSgl->adapter == adapter); - SglBuffer = SXG_SGL_BUFFER(SxgSgl); - SglBufferLength = SXG_SGL_BUF_SIZE; + /*SglBuffer = SXG_SGL_BUFFER(SxgSgl); + SglBufferLength = SXG_SGL_BUF_SIZE; */ SxgSgl->VlanTag.VlanTci = 0; SxgSgl->VlanTag.VlanTpid = 0; SxgSgl->Type = SXG_SGL_DUMB; @@ -1965,9 +2539,7 @@ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb) pSgl = NULL; /* Call the common sxg_dumb_sgl routine to complete the send. */ - sxg_dumb_sgl(pSgl, SxgSgl); - /* Return success sxg_dumb_sgl (or something later) will complete it. */ - return (STATUS_SUCCESS); + return (sxg_dumb_sgl(pSgl, SxgSgl)); } /* @@ -1975,24 +2547,27 @@ static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb) * * Arguments: * pSgl - - * SxgSgl - SXG_SCATTER_GATHER + * SxgSgl - struct sxg_scatter_gather * * Return Value: - * None. + * Status of send operation. */ -static void sxg_dumb_sgl(struct SCATTER_GATHER_LIST *pSgl, struct SXG_SCATTER_GATHER *SxgSgl) +static int sxg_dumb_sgl(struct sxg_x64_sgl *pSgl, + struct sxg_scatter_gather *SxgSgl) { struct adapter_t *adapter = SxgSgl->adapter; struct sk_buff *skb = SxgSgl->DumbPacket; /* For now, all dumb-nic sends go on RSS queue zero */ - struct SXG_XMT_RING *XmtRing = &adapter->XmtRings[0]; - struct SXG_RING_INFO *XmtRingInfo = &adapter->XmtRingZeroInfo; - struct SXG_CMD *XmtCmd = NULL; -/* u32 Index = 0; */ + struct sxg_xmt_ring *XmtRing = &adapter->XmtRings[0]; + struct sxg_ring_info *XmtRingInfo = &adapter->XmtRingZeroInfo; + struct sxg_cmd *XmtCmd = NULL; + /* u32 Index = 0; */ u32 DataLength = skb->len; -/* unsigned int BufLen; */ -/* u32 SglOffset; */ + /* unsigned int BufLen; */ + /* u32 SglOffset; */ u64 phys_addr; + unsigned long flags; + unsigned long queue_id=0; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl", pSgl, SxgSgl, 0, 0); @@ -2001,25 +2576,67 @@ static void sxg_dumb_sgl(struct SCATTER_GATHER_LIST *pSgl, struct SXG_SCATTER_GA SxgSgl->pSgl = pSgl; /* Sanity check that our SGL format is as we expect. */ - ASSERT(sizeof(SXG_X64_SGE) == sizeof(SCATTER_GATHER_ELEMENT)); + ASSERT(sizeof(struct sxg_x64_sge) == sizeof(struct sxg_x64_sge)); /* Shouldn't be a vlan tag on this frame */ ASSERT(SxgSgl->VlanTag.VlanTci == 0); ASSERT(SxgSgl->VlanTag.VlanTpid == 0); - /* From here below we work with the SGL placed in our */ - /* buffer. */ + /* + * From here below we work with the SGL placed in our + * buffer. + */ SxgSgl->Sgl.NumberOfElements = 1; + /* + * Set ucode Queue ID based on bottom bits of destination TCP port. + * This Queue ID splits slowpath/dumb-nic packet processing across + * multiple threads on the card to improve performance. It is split + * using the TCP port to avoid out-of-order packets that can result + * from multithreaded processing. We use the destination port because + * we expect to be run on a server, so in nearly all cases the local + * port is likely to be constant (well-known server port) and the + * remote port is likely to be random. The exception to this is iSCSI, + * in which case we use the sport instead. Note + * that original attempt at XOR'ing source and dest port resulted in + * poor balance on NTTTCP/iometer applications since they tend to + * line up (even-even, odd-odd..). + */ + + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *ip; + + ip = ip_hdr(skb); + if ((ip->protocol == IPPROTO_TCP)&&(DataLength >= sizeof( + struct tcphdr))){ + queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ? + (ntohs (tcp_hdr(skb)->source) & + SXG_LARGE_SEND_QUEUE_MASK): + (ntohs(tcp_hdr(skb)->dest) & + SXG_LARGE_SEND_QUEUE_MASK)); + } + } else if (skb->protocol == htons(ETH_P_IPV6)) { + if ((ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) && (DataLength >= + sizeof(struct tcphdr)) ) { + queue_id = ((ntohs(tcp_hdr(skb)->dest) == ISCSI_PORT) ? + (ntohs (tcp_hdr(skb)->source) & + SXG_LARGE_SEND_QUEUE_MASK): + (ntohs(tcp_hdr(skb)->dest) & + SXG_LARGE_SEND_QUEUE_MASK)); + } + } /* Grab the spinlock and acquire a command */ - spin_lock(&adapter->XmtZeroLock); + spin_lock_irqsave(&adapter->XmtZeroLock, flags); SXG_GET_CMD(XmtRing, XmtRingInfo, XmtCmd, SxgSgl); if (XmtCmd == NULL) { - /* Call sxg_complete_slow_send to see if we can */ - /* free up any XmtRingZero entries and then try again */ - spin_unlock(&adapter->XmtZeroLock); + /* + * Call sxg_complete_slow_send to see if we can + * free up any XmtRingZero entries and then try again + */ + + spin_unlock_irqrestore(&adapter->XmtZeroLock, flags); sxg_complete_slow_send(adapter); - spin_lock(&adapter->XmtZeroLock); + spin_lock_irqsave(&adapter->XmtZeroLock, flags); SXG_GET_CMD(XmtRing, XmtRingInfo, XmtCmd, SxgSgl); if (XmtCmd == NULL) { adapter->Stats.XmtZeroFull++; @@ -2029,8 +2646,8 @@ static void sxg_dumb_sgl(struct SCATTER_GATHER_LIST *pSgl, struct SXG_SCATTER_GA SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbCmd", XmtCmd, XmtRingInfo->Head, XmtRingInfo->Tail, 0); /* Update stats */ - adapter->Stats.DumbXmtPkts++; - adapter->Stats.DumbXmtBytes += DataLength; + adapter->stats.tx_packets++; + adapter->stats.tx_bytes += DataLength; #if XXXTODO /* Stats stuff */ if (SXG_MULTICAST_PACKET(EtherHdr)) { if (SXG_BROADCAST_PACKET(EtherHdr)) { @@ -2045,70 +2662,92 @@ static void sxg_dumb_sgl(struct SCATTER_GATHER_LIST *pSgl, struct SXG_SCATTER_GA adapter->Stats.DumbXmtUcastBytes += DataLength; } #endif - /* Fill in the command */ - /* Copy out the first SGE to the command and adjust for offset */ - phys_addr = - pci_map_single(adapter->pcidev, skb->data, skb->len, + /* + * Fill in the command + * Copy out the first SGE to the command and adjust for offset + */ + phys_addr = pci_map_single(adapter->pcidev, skb->data, skb->len, PCI_DMA_TODEVICE); - XmtCmd->Buffer.FirstSgeAddress = SXG_GET_ADDR_HIGH(phys_addr); - XmtCmd->Buffer.FirstSgeAddress = XmtCmd->Buffer.FirstSgeAddress << 32; - XmtCmd->Buffer.FirstSgeAddress = - XmtCmd->Buffer.FirstSgeAddress | SXG_GET_ADDR_LOW(phys_addr); -/* XmtCmd->Buffer.FirstSgeAddress = SxgSgl->Sgl.Elements[Index].Address; */ -/* XmtCmd->Buffer.FirstSgeAddress.LowPart += MdlOffset; */ + + /* + * SAHARA SGL WORKAROUND + * See if the SGL straddles a 64k boundary. If so, skip to + * the start of the next 64k boundary and continue + */ + + if ((adapter->asictype == SAHARA_REV_A) && + (SXG_INVALID_SGL(phys_addr,skb->data_len))) + { + spin_unlock_irqrestore(&adapter->XmtZeroLock, flags); + /* Silently drop this packet */ + printk(KERN_EMERG"Dropped a packet for 64k boundary problem\n"); + return STATUS_SUCCESS; + } + memset(XmtCmd, '\0', sizeof(*XmtCmd)); + XmtCmd->Buffer.FirstSgeAddress = phys_addr; XmtCmd->Buffer.FirstSgeLength = DataLength; - /* Set a pointer to the remaining SGL entries */ -/* XmtCmd->Sgl = SxgSgl->PhysicalAddress; */ - /* Advance the physical address of the SxgSgl structure to */ - /* the second SGE */ -/* SglOffset = (u32)((u32 *)(&SxgSgl->Sgl.Elements[Index+1]) - */ -/* (u32 *)SxgSgl); */ -/* XmtCmd->Sgl.LowPart += SglOffset; */ XmtCmd->Buffer.SgeOffset = 0; - /* Note - TotalLength might be overwritten with MSS below.. */ XmtCmd->Buffer.TotalLength = DataLength; - XmtCmd->SgEntries = 1; /*(ushort)(SxgSgl->Sgl.NumberOfElements - Index); */ + XmtCmd->SgEntries = 1; XmtCmd->Flags = 0; - /* */ - /* Advance transmit cmd descripter by 1. */ - /* NOTE - See comments in SxgTcpOutput where we write */ - /* to the XmtCmd register regarding CPU ID values and/or */ - /* multiple commands. */ - /* */ - /* */ - WRITE_REG(adapter->UcodeRegs[0].XmtCmd, 1, TRUE); - /* */ - /* */ + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + /* + * We need to set the Checkum in IP header to 0. This is + * required by hardware. + */ + ip_hdr(skb)->check = 0x0; + XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_IP; + XmtCmd->CsumFlags.Flags |= SXG_SLOWCMD_CSUM_TCP; + /* Dont know if length will require a change in case of VLAN */ + XmtCmd->CsumFlags.MacLen = ETH_HLEN; + XmtCmd->CsumFlags.IpHl = skb_network_header_len(skb) >> + SXG_NW_HDR_LEN_SHIFT; + } + /* + * Advance transmit cmd descripter by 1. + * NOTE - See comments in SxgTcpOutput where we write + * to the XmtCmd register regarding CPU ID values and/or + * multiple commands. + * Top 16 bits specify queue_id. See comments about queue_id above + */ + /* Four queues at the moment */ + ASSERT((queue_id & ~SXG_LARGE_SEND_QUEUE_MASK) == 0); + WRITE_REG(adapter->UcodeRegs[0].XmtCmd, ((queue_id << 16) | 1), TRUE); adapter->Stats.XmtQLen++; /* Stats within lock */ - spin_unlock(&adapter->XmtZeroLock); + spin_unlock_irqrestore(&adapter->XmtZeroLock, flags); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2", XmtCmd, pSgl, SxgSgl, 0); - return; + return STATUS_SUCCESS; abortcmd: - /* NOTE - Only jump to this label AFTER grabbing the */ - /* XmtZeroLock, and DO NOT DROP IT between the */ - /* command allocation and the following abort. */ + /* + * NOTE - Only jump to this label AFTER grabbing the + * XmtZeroLock, and DO NOT DROP IT between the + * command allocation and the following abort. + */ if (XmtCmd) { SXG_ABORT_CMD(XmtRingInfo); } - spin_unlock(&adapter->XmtZeroLock); - -/* failsgl: */ - /* Jump to this label if failure occurs before the */ - /* XmtZeroLock is grabbed */ - adapter->Stats.XmtErrors++; - SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumSGFal", - pSgl, SxgSgl, XmtRingInfo->Head, XmtRingInfo->Tail); - - SXG_COMPLETE_DUMB_SEND(adapter, SxgSgl->DumbPacket); /* SxgSgl->DumbPacket is the skb */ -} - -/*************************************************************** - * Link management functions - ***************************************************************/ + spin_unlock_irqrestore(&adapter->XmtZeroLock, flags); /* + * failsgl: + * Jump to this label if failure occurs before the + * XmtZeroLock is grabbed + */ + adapter->stats.tx_errors++; + SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumSGFal", + pSgl, SxgSgl, XmtRingInfo->Head, XmtRingInfo->Tail); + /* SxgSgl->DumbPacket is the skb */ + // SXG_COMPLETE_DUMB_SEND(adapter, SxgSgl->DumbPacket); + + return STATUS_FAILURE; +} + +/* + * Link management functions + * * sxg_initialize_link - Initialize the link stuff * * Arguments - @@ -2119,10 +2758,11 @@ static void sxg_dumb_sgl(struct SCATTER_GATHER_LIST *pSgl, struct SXG_SCATTER_GA */ static int sxg_initialize_link(struct adapter_t *adapter) { - struct SXG_HW_REGS *HwRegs = adapter->HwRegs; + struct sxg_hw_regs *HwRegs = adapter->HwRegs; u32 Value; u32 ConfigData; u32 MaxFrame; + u32 AxgMacReg1; int status; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "InitLink", @@ -2140,15 +2780,17 @@ static int sxg_initialize_link(struct adapter_t *adapter) /* Reset all MAC modules */ WRITE_REG(HwRegs->MacConfig0, AXGMAC_CFG0_SUB_RESET, TRUE); - /* Link address 0 */ - /* XXXTODO - This assumes the MAC address (0a:0b:0c:0d:0e:0f) */ - /* is stored with the first nibble (0a) in the byte 0 */ - /* of the Mac address. Possibly reverse? */ - Value = *(u32 *) adapter->MacAddr; + /* + * Link address 0 + * XXXTODO - This assumes the MAC address (0a:0b:0c:0d:0e:0f) + * is stored with the first nibble (0a) in the byte 0 + * of the Mac address. Possibly reverse? + */ + Value = *(u32 *) adapter->macaddr; WRITE_REG(HwRegs->LinkAddress0Low, Value, TRUE); /* also write the MAC address to the MAC. Endian is reversed. */ WRITE_REG(HwRegs->MacAddressLow, ntohl(Value), TRUE); - Value = (*(u16 *) & adapter->MacAddr[4] & 0x0000FFFF); + Value = (*(u16 *) & adapter->macaddr[4] & 0x0000FFFF); WRITE_REG(HwRegs->LinkAddress0High, Value | LINK_ADDRESS_ENABLE, TRUE); /* endian swap for the MAC (put high bytes in bits [31:16], swapped) */ Value = ntohl(Value); @@ -2167,47 +2809,76 @@ static int sxg_initialize_link(struct adapter_t *adapter) WRITE_REG(HwRegs->MacConfig0, 0, TRUE); /* Configure MAC */ - WRITE_REG(HwRegs->MacConfig1, (AXGMAC_CFG1_XMT_PAUSE | /* Allow sending of pause */ - AXGMAC_CFG1_XMT_EN | /* Enable XMT */ - AXGMAC_CFG1_RCV_PAUSE | /* Enable detection of pause */ - AXGMAC_CFG1_RCV_EN | /* Enable receive */ - AXGMAC_CFG1_SHORT_ASSERT | /* short frame detection */ - AXGMAC_CFG1_CHECK_LEN | /* Verify frame length */ - AXGMAC_CFG1_GEN_FCS | /* Generate FCS */ - AXGMAC_CFG1_PAD_64), /* Pad frames to 64 bytes */ - TRUE); + AxgMacReg1 = ( /* Enable XMT */ + AXGMAC_CFG1_XMT_EN | + /* Enable receive */ + AXGMAC_CFG1_RCV_EN | + /* short frame detection */ + AXGMAC_CFG1_SHORT_ASSERT | + /* Verify frame length */ + AXGMAC_CFG1_CHECK_LEN | + /* Generate FCS */ + AXGMAC_CFG1_GEN_FCS | + /* Pad frames to 64 bytes */ + AXGMAC_CFG1_PAD_64); + + if (adapter->XmtFcEnabled) { + AxgMacReg1 |= AXGMAC_CFG1_XMT_PAUSE; /* Allow sending of pause */ + } + if (adapter->RcvFcEnabled) { + AxgMacReg1 |= AXGMAC_CFG1_RCV_PAUSE; /* Enable detection of pause */ + } + + WRITE_REG(HwRegs->MacConfig1, AxgMacReg1, TRUE); /* Set AXGMAC max frame length if jumbo. Not needed for standard MTU */ if (adapter->JumboEnabled) { WRITE_REG(HwRegs->MacMaxFrameLen, AXGMAC_MAXFRAME_JUMBO, TRUE); } - /* AMIIM Configuration Register - */ - /* The value placed in the AXGMAC_AMIIM_CFG_HALF_CLOCK portion */ - /* (bottom bits) of this register is used to determine the */ - /* MDC frequency as specified in the A-XGMAC Design Document. */ - /* This value must not be zero. The following value (62 or 0x3E) */ - /* is based on our MAC transmit clock frequency (MTCLK) of 312.5 MHz. */ - /* Given a maximum MDIO clock frequency of 2.5 MHz (see the PHY spec), */ - /* we get: 312.5/(2*(X+1)) < 2.5 ==> X = 62. */ - /* This value happens to be the default value for this register, */ - /* so we really don't have to do this. */ - WRITE_REG(HwRegs->MacAmiimConfig, 0x0000003E, TRUE); + /* + * AMIIM Configuration Register - + * The value placed in the AXGMAC_AMIIM_CFG_HALF_CLOCK portion + * (bottom bits) of this register is used to determine the MDC frequency + * as specified in the A-XGMAC Design Document. This value must not be + * zero. The following value (62 or 0x3E) is based on our MAC transmit + * clock frequency (MTCLK) of 312.5 MHz. Given a maximum MDIO clock + * frequency of 2.5 MHz (see the PHY spec), we get: + * 312.5/(2*(X+1)) < 2.5 ==> X = 62. + * This value happens to be the default value for this register, so we + * really don't have to do this. + */ + if (adapter->asictype == SAHARA_REV_B) { + WRITE_REG(HwRegs->MacAmiimConfig, 0x0000001F, TRUE); + } else { + WRITE_REG(HwRegs->MacAmiimConfig, 0x0000003E, TRUE); + } /* Power up and enable PHY and XAUI/XGXS/Serdes logic */ WRITE_REG(HwRegs->LinkStatus, - (LS_PHY_CLR_RESET | - LS_XGXS_ENABLE | - LS_XGXS_CTL | LS_PHY_CLK_EN | LS_ATTN_ALARM), TRUE); + (LS_PHY_CLR_RESET | + LS_XGXS_ENABLE | + LS_XGXS_CTL | + LS_PHY_CLK_EN | + LS_ATTN_ALARM), + TRUE); DBG_ERROR("After Power Up and enable PHY in sxg_initialize_link\n"); - /* Per information given by Aeluros, wait 100 ms after removing reset. */ - /* It's not enough to wait for the self-clearing reset bit in reg 0 to clear. */ + /* + * Per information given by Aeluros, wait 100 ms after removing reset. + * It's not enough to wait for the self-clearing reset bit in reg 0 to + * clear. + */ mdelay(100); - /* Verify the PHY has come up by checking that the Reset bit has cleared. */ - status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */ - PHY_PMA_CONTROL1, /* PMA/PMD control register */ - &Value); + /* Verify the PHY has come up by checking that the Reset bit has + * cleared. + */ + status = sxg_read_mdio_reg(adapter, + MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */ + PHY_PMA_CONTROL1, /* PMA/PMD control register */ + &Value); + DBG_ERROR("After sxg_read_mdio_reg Value[%x] fail=%x\n", Value, + (Value & PMA_CONTROL1_RESET)); if (status != STATUS_SUCCESS) return (STATUS_FAILURE); if (Value & PMA_CONTROL1_RESET) /* reset complete if bit is 0 */ @@ -2228,16 +2899,26 @@ static int sxg_initialize_link(struct adapter_t *adapter) return (STATUS_FAILURE); /* Enable the Link Alarm */ - status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */ - LASI_CONTROL, /* LASI control register */ - LASI_CTL_LS_ALARM_ENABLE); /* enable link alarm bit */ + + /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module + * LASI_CONTROL - LASI control register + * LASI_CTL_LS_ALARM_ENABLE - enable link alarm bit + */ + status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA, + LASI_CONTROL, + LASI_CTL_LS_ALARM_ENABLE); if (status != STATUS_SUCCESS) return (STATUS_FAILURE); /* XXXTODO - temporary - verify bit is set */ - status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */ - LASI_CONTROL, /* LASI control register */ + + /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module + * LASI_CONTROL - LASI control register + */ + status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, + LASI_CONTROL, &Value); + if (status != STATUS_SUCCESS) return (STATUS_FAILURE); if (!(Value & LASI_CTL_LS_ALARM_ENABLE)) { @@ -2253,6 +2934,11 @@ static int sxg_initialize_link(struct adapter_t *adapter) RCV_CONFIG_TZIPV4 | RCV_CONFIG_HASH_16 | RCV_CONFIG_SOCKET | RCV_CONFIG_BUFSIZE(MaxFrame)); + + if (adapter->asictype == SAHARA_REV_B) { + ConfigData |= (RCV_CONFIG_HIPRICTL | + RCV_CONFIG_NEWSTATUSFMT); + } WRITE_REG(HwRegs->RcvConfig, ConfigData, TRUE); WRITE_REG(HwRegs->XmtConfig, XMT_CONFIG_ENABLE, TRUE); @@ -2277,21 +2963,25 @@ static int sxg_initialize_link(struct adapter_t *adapter) static int sxg_phy_init(struct adapter_t *adapter) { u32 Value; - struct PHY_UCODE *p; + struct phy_ucode *p; int status; DBG_ERROR("ENTER %s\n", __func__); - /* Read a register to identify the PHY type */ - status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */ - 0xC205, /* PHY ID register (?) */ - &Value); /* XXXTODO - add def */ + /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module + * 0xC205 - PHY ID register (?) + * &Value - XXXTODO - add def + */ + status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, + 0xC205, + &Value); if (status != STATUS_SUCCESS) return (STATUS_FAILURE); - if (Value == 0x0012) { /* 0x0012 == AEL2005C PHY(?) - XXXTODO - add def */ - DBG_ERROR - ("AEL2005C PHY detected. Downloading PHY microcode.\n"); + if (Value == 0x0012) { + /* 0x0012 == AEL2005C PHY(?) - XXXTODO - add def */ + DBG_ERROR("AEL2005C PHY detected. Downloading PHY \ + microcode.\n"); /* Initialize AEL2005C PHY and download PHY microcode */ for (p = PhyUcode; p->Addr != 0xFFFF; p++) { @@ -2299,10 +2989,13 @@ static int sxg_phy_init(struct adapter_t *adapter) /* if address == 0, data == sleep time in ms */ mdelay(p->Data); } else { - /* write the given data to the specified address */ - status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */ - p->Addr, /* PHY address */ - p->Data); /* PHY data */ + /* write the given data to the specified address */ + status = sxg_write_mdio_reg(adapter, + MIIM_DEV_PHY_PMA, + /* PHY address */ + p->Addr, + /* PHY data */ + p->Data); if (status != STATUS_SUCCESS) return (STATUS_FAILURE); } @@ -2324,11 +3017,14 @@ static int sxg_phy_init(struct adapter_t *adapter) */ static void sxg_link_event(struct adapter_t *adapter) { - struct SXG_HW_REGS *HwRegs = adapter->HwRegs; + struct sxg_hw_regs *HwRegs = adapter->HwRegs; + struct net_device *netdev = adapter->netdev; enum SXG_LINK_STATE LinkState; int status; u32 Value; + if (adapter->state == ADAPT_DOWN) + return; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "LinkEvnt", adapter, 0, 0, 0); DBG_ERROR("ENTER %s\n", __func__); @@ -2336,35 +3032,57 @@ static void sxg_link_event(struct adapter_t *adapter) /* Check the Link Status register. We should have a Link Alarm. */ READ_REG(HwRegs->LinkStatus, Value); if (Value & LS_LINK_ALARM) { - /* We got a Link Status alarm. First, pause to let the */ - /* link state settle (it can bounce a number of times) */ + /* + * We got a Link Status alarm. First, pause to let the + * link state settle (it can bounce a number of times) + */ mdelay(10); /* Now clear the alarm by reading the LASI status register. */ - status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */ - LASI_STATUS, /* LASI status register */ + /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module */ + status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, + /* LASI status register */ + LASI_STATUS, &Value); if (status != STATUS_SUCCESS) { DBG_ERROR("Error reading LASI Status MDIO register!\n"); sxg_link_state(adapter, SXG_LINK_DOWN); -/* ASSERT(0); */ + /* ASSERT(0); */ } - ASSERT(Value & LASI_STATUS_LS_ALARM); + /* + * We used to assert that the LASI_LS_ALARM bit was set, as + * it should be. But there appears to be cases during + * initialization (when the PHY is reset and re-initialized) + * when we get a link alarm, but the status bit is 0 when we + * read it. Rather than trying to assure this never happens + * (and nver being certain), just ignore it. + + * ASSERT(Value & LASI_STATUS_LS_ALARM); + */ /* Now get and set the link state */ LinkState = sxg_get_link_state(adapter); sxg_link_state(adapter, LinkState); DBG_ERROR("SXG: Link Alarm occurred. Link is %s\n", ((LinkState == SXG_LINK_UP) ? "UP" : "DOWN")); + if (LinkState == SXG_LINK_UP) { + netif_carrier_on(netdev); + netif_tx_start_all_queues(netdev); + } else { + netif_tx_stop_all_queues(netdev); + netif_carrier_off(netdev); + } } else { - /* XXXTODO - Assuming Link Attention is only being generated for the */ - /* Link Alarm pin (and not for a XAUI Link Status change), then it's */ - /* impossible to get here. Yet we've gotten here twice (under extreme */ - /* conditions - bouncing the link up and down many times a second). */ - /* Needs further investigation. */ + /* + * XXXTODO - Assuming Link Attention is only being generated + * for the Link Alarm pin (and not for a XAUI Link Status change) + * , then it's impossible to get here. Yet we've gotten here + * twice (under extreme conditions - bouncing the link up and + * down many times a second). Needs further investigation. + */ DBG_ERROR("SXG: sxg_link_event: Can't get here!\n"); DBG_ERROR("SXG: Link Status == 0x%08X.\n", Value); -/* ASSERT(0); */ + /* ASSERT(0); */ } DBG_ERROR("EXIT %s\n", __func__); @@ -2389,10 +3107,15 @@ static enum SXG_LINK_STATE sxg_get_link_state(struct adapter_t *adapter) SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "GetLink", adapter, 0, 0, 0); - /* Per the Xenpak spec (and the IEEE 10Gb spec?), the link is up if */ - /* the following 3 bits (from 3 different MDIO registers) are all true. */ - status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */ - PHY_PMA_RCV_DET, /* PMA/PMD Receive Signal Detect register */ + /* + * Per the Xenpak spec (and the IEEE 10Gb spec?), the link is up if + * the following 3 bits (from 3 different MDIO registers) are all true. + */ + + /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module */ + status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA, + /* PMA/PMD Receive Signal Detect register */ + PHY_PMA_RCV_DET, &Value); if (status != STATUS_SUCCESS) goto bad; @@ -2401,8 +3124,10 @@ static enum SXG_LINK_STATE sxg_get_link_state(struct adapter_t *adapter) if (!(Value & PMA_RCV_DETECT)) return (SXG_LINK_DOWN); - status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PCS, /* PHY PCS module */ - PHY_PCS_10G_STATUS1, /* PCS 10GBASE-R Status 1 register */ + /* MIIM_DEV_PHY_PCS - PHY PCS module */ + status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PCS, + /* PCS 10GBASE-R Status 1 register */ + PHY_PCS_10G_STATUS1, &Value); if (status != STATUS_SUCCESS) goto bad; @@ -2411,8 +3136,9 @@ static enum SXG_LINK_STATE sxg_get_link_state(struct adapter_t *adapter) if (!(Value & PCS_10B_BLOCK_LOCK)) return (SXG_LINK_DOWN); - status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_XS, /* PHY XS module */ - PHY_XS_LANE_STATUS, /* XS Lane Status register */ + status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_XS,/* PHY XS module */ + /* XS Lane Status register */ + PHY_XS_LANE_STATUS, &Value); if (status != STATUS_SUCCESS) goto bad; @@ -2427,7 +3153,7 @@ static enum SXG_LINK_STATE sxg_get_link_state(struct adapter_t *adapter) return (SXG_LINK_UP); bad: - /* An error occurred reading an MDIO register. This shouldn't happen. */ + /* An error occurred reading an MDIO register. This shouldn't happen. */ DBG_ERROR("Error reading an MDIO register!\n"); ASSERT(0); return (SXG_LINK_DOWN); @@ -2447,6 +3173,37 @@ static void sxg_indicate_link_state(struct adapter_t *adapter, } } +/* + * sxg_change_mtu - Change the Maximum Transfer Unit + * * @returns 0 on success, negative on failure + */ +int sxg_change_mtu (struct net_device *netdev, int new_mtu) +{ + struct adapter_t *adapter = (struct adapter_t *) netdev_priv(netdev); + + if (!((new_mtu == SXG_DEFAULT_MTU) || (new_mtu == SXG_JUMBO_MTU))) + return -EINVAL; + + if(new_mtu == netdev->mtu) + return 0; + + netdev->mtu = new_mtu; + + if (new_mtu == SXG_JUMBO_MTU) { + adapter->JumboEnabled = TRUE; + adapter->FrameSize = JUMBOMAXFRAME; + adapter->ReceiveBufferSize = SXG_RCV_JUMBO_BUFFER_SIZE; + } else { + adapter->JumboEnabled = FALSE; + adapter->FrameSize = ETHERMAXFRAME; + adapter->ReceiveBufferSize = SXG_RCV_DATA_BUFFER_SIZE; + } + + sxg_entry_halt(netdev); + sxg_entry_open(netdev); + return 0; +} + /* * sxg_link_state - Set the link state and if necessary, indicate. * This routine the central point of processing for all link state changes. @@ -2460,27 +3217,32 @@ static void sxg_indicate_link_state(struct adapter_t *adapter, * Return * None */ -static void sxg_link_state(struct adapter_t *adapter, enum SXG_LINK_STATE LinkState) +static void sxg_link_state(struct adapter_t *adapter, + enum SXG_LINK_STATE LinkState) { SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "LnkINDCT", adapter, LinkState, adapter->LinkState, adapter->State); DBG_ERROR("ENTER %s\n", __func__); - /* Hold the adapter lock during this routine. Maybe move */ - /* the lock to the caller. */ - spin_lock(&adapter->AdapterLock); + /* + * Hold the adapter lock during this routine. Maybe move + * the lock to the caller. + */ + /* IMP TODO : Check if we can survive without taking this lock */ +// spin_lock(&adapter->AdapterLock); if (LinkState == adapter->LinkState) { /* Nothing changed.. */ - spin_unlock(&adapter->AdapterLock); - DBG_ERROR("EXIT #0 %s\n", __func__); +// spin_unlock(&adapter->AdapterLock); + DBG_ERROR("EXIT #0 %s. Link status = %d\n", + __func__, LinkState); return; } /* Save the adapter state */ adapter->LinkState = LinkState; /* Drop the lock and indicate link state */ - spin_unlock(&adapter->AdapterLock); +// spin_unlock(&adapter->AdapterLock); DBG_ERROR("EXIT #1 %s\n", __func__); sxg_indicate_link_state(adapter, LinkState); @@ -2501,14 +3263,16 @@ static void sxg_link_state(struct adapter_t *adapter, enum SXG_LINK_STATE LinkSt static int sxg_write_mdio_reg(struct adapter_t *adapter, u32 DevAddr, u32 RegAddr, u32 Value) { - struct SXG_HW_REGS *HwRegs = adapter->HwRegs; - u32 AddrOp; /* Address operation (written to MIIM field reg) */ - u32 WriteOp; /* Write operation (written to MIIM field reg) */ - u32 Cmd; /* Command (written to MIIM command reg) */ + struct sxg_hw_regs *HwRegs = adapter->HwRegs; + /* Address operation (written to MIIM field reg) */ + u32 AddrOp; + /* Write operation (written to MIIM field reg) */ + u32 WriteOp; + u32 Cmd;/* Command (written to MIIM command reg) */ u32 ValueRead; u32 Timeout; -/* DBG_ERROR("ENTER %s\n", __func__); */ + /* DBG_ERROR("ENTER %s\n", __func__); */ SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "WrtMDIO", adapter, 0, 0, 0); @@ -2571,7 +3335,7 @@ static int sxg_write_mdio_reg(struct adapter_t *adapter, } } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY); -/* DBG_ERROR("EXIT %s\n", __func__); */ + /* DBG_ERROR("EXIT %s\n", __func__); */ return (STATUS_SUCCESS); } @@ -2583,7 +3347,7 @@ static int sxg_write_mdio_reg(struct adapter_t *adapter, * adapter - A pointer to our adapter structure * DevAddr - MDIO device number being addressed * RegAddr - register address for the specified MDIO device - * pValue - pointer to where to put data read from the MDIO register + * pValue - pointer to where to put data read from the MDIO register * * Return * status @@ -2591,16 +3355,16 @@ static int sxg_write_mdio_reg(struct adapter_t *adapter, static int sxg_read_mdio_reg(struct adapter_t *adapter, u32 DevAddr, u32 RegAddr, u32 *pValue) { - struct SXG_HW_REGS *HwRegs = adapter->HwRegs; - u32 AddrOp; /* Address operation (written to MIIM field reg) */ - u32 ReadOp; /* Read operation (written to MIIM field reg) */ - u32 Cmd; /* Command (written to MIIM command reg) */ + struct sxg_hw_regs *HwRegs = adapter->HwRegs; + u32 AddrOp; /* Address operation (written to MIIM field reg) */ + u32 ReadOp; /* Read operation (written to MIIM field reg) */ + u32 Cmd; /* Command (written to MIIM command reg) */ u32 ValueRead; u32 Timeout; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "WrtMDIO", adapter, 0, 0, 0); -/* DBG_ERROR("ENTER %s\n", __func__); */ + DBG_ERROR("ENTER %s\n", __FUNCTION__); /* Ensure values don't exceed field width */ DevAddr &= 0x001F; /* 5-bit field */ @@ -2636,6 +3400,8 @@ static int sxg_read_mdio_reg(struct adapter_t *adapter, udelay(100); /* Timeout in 100us units */ READ_REG(HwRegs->MacAmiimIndicator, ValueRead); if (--Timeout == 0) { + DBG_ERROR("EXIT %s with STATUS_FAILURE 1\n", __FUNCTION__); + return (STATUS_FAILURE); } } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY); @@ -2655,6 +3421,8 @@ static int sxg_read_mdio_reg(struct adapter_t *adapter, udelay(100); /* Timeout in 100us units */ READ_REG(HwRegs->MacAmiimIndicator, ValueRead); if (--Timeout == 0) { + DBG_ERROR("EXIT %s with STATUS_FAILURE 2\n", __FUNCTION__); + return (STATUS_FAILURE); } } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY); @@ -2663,7 +3431,7 @@ static int sxg_read_mdio_reg(struct adapter_t *adapter, READ_REG(HwRegs->MacAmiimField, *pValue); *pValue &= 0xFFFF; /* data is in the lower 16 bits */ -/* DBG_ERROR("EXIT %s\n", __func__); */ + DBG_ERROR("EXIT %s\n", __FUNCTION__); return (STATUS_SUCCESS); } @@ -2672,22 +3440,21 @@ static int sxg_read_mdio_reg(struct adapter_t *adapter, * Functions to obtain the CRC corresponding to the destination mac address. * This is a standard ethernet CRC in that it is a 32-bit, reflected CRC using * the polynomial: - * x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1. - * - * After the CRC for the 6 bytes is generated (but before the value is complemented), - * we must then transpose the value and return bits 30-23. + * x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + * + x^4 + x^2 + x^1. * + * After the CRC for the 6 bytes is generated (but before the value is + * complemented), we must then transpose the value and return bits 30-23. */ -static u32 sxg_crc_table[256]; /* Table of CRC's for all possible byte values */ +static u32 sxg_crc_table[256];/* Table of CRC's for all possible byte values */ +static u32 sxg_crc_init; /* Is table initialized */ -/* - * Contruct the CRC32 table - */ +/* Contruct the CRC32 table */ static void sxg_mcast_init_crc32(void) { - u32 c; /* CRC shit reg */ - u32 e = 0; /* Poly X-or pattern */ - int i; /* counter */ + u32 c; /* CRC shit reg */ + u32 e = 0; /* Poly X-or pattern */ + int i; /* counter */ int k; /* byte being shifted into crc */ static int p[] = { 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26 }; @@ -2705,8 +3472,6 @@ static void sxg_mcast_init_crc32(void) } } -#if XXXTODO -static u32 sxg_crc_init; /* Is table initialized */ /* * Return the MAC hast as described above. */ @@ -2737,25 +3502,31 @@ static unsigned char sxg_mcast_get_mac_hash(char *macaddr) static void sxg_mcast_set_mask(struct adapter_t *adapter) { - struct SXG_UCODE_REGS *sxg_regs = adapter->UcodeRegs; + struct sxg_ucode_regs *sxg_regs = adapter->UcodeRegs; - DBG_ERROR("%s ENTER (%s) macopts[%x] mask[%llx]\n", __func__, + DBG_ERROR("%s ENTER (%s) MacFilter[%x] mask[%llx]\n", __FUNCTION__, adapter->netdev->name, (unsigned int)adapter->MacFilter, adapter->MulticastMask); if (adapter->MacFilter & (MAC_ALLMCAST | MAC_PROMISC)) { - /* Turn on all multicast addresses. We have to do this for promiscuous - * mode as well as ALLMCAST mode. It saves the Microcode from having - * to keep state about the MAC configuration. + /* + * Turn on all multicast addresses. We have to do this for + * promiscuous mode as well as ALLMCAST mode. It saves the + * Microcode from having keep state about the MAC configuration + */ + /* DBG_ERROR("sxg: %s MacFilter = MAC_ALLMCAST | MAC_PROMISC\n \ + * SLUT MODE!!!\n",__func__); */ -/* DBG_ERROR("sxg: %s macopts = MAC_ALLMCAST | MAC_PROMISC\n SLUT MODE!!!\n",__func__); */ WRITE_REG(sxg_regs->McastLow, 0xFFFFFFFF, FLUSH); WRITE_REG(sxg_regs->McastHigh, 0xFFFFFFFF, FLUSH); -/* DBG_ERROR("%s (%s) WRITE to slic_regs slic_mcastlow&high 0xFFFFFFFF\n",__func__, adapter->netdev->name); */ + /* DBG_ERROR("%s (%s) WRITE to slic_regs slic_mcastlow&high \ + * 0xFFFFFFFF\n",__func__, adapter->netdev->name); + */ } else { - /* Commit our multicast mast to the SLIC by writing to the multicast - * address mask registers + /* + * Commit our multicast mast to the SLIC by writing to the + * multicast address mask registers */ DBG_ERROR("%s (%s) WRITE mcastlow[%lx] mcasthigh[%lx]\n", __func__, adapter->netdev->name, @@ -2771,38 +3542,6 @@ static void sxg_mcast_set_mask(struct adapter_t *adapter) } } -/* - * Allocate a mcast_address structure to hold the multicast address. - * Link it in. - */ -static int sxg_mcast_add_list(struct adapter_t *adapter, char *address) -{ - p_mcast_address_t mcaddr, mlist; - bool equaladdr; - - /* Check to see if it already exists */ - mlist = adapter->mcastaddrs; - while (mlist) { - ETHER_EQ_ADDR(mlist->address, address, equaladdr); - if (equaladdr) { - return (STATUS_SUCCESS); - } - mlist = mlist->next; - } - - /* Doesn't already exist. Allocate a structure to hold it */ - mcaddr = kmalloc(sizeof(mcast_address_t), GFP_ATOMIC); - if (mcaddr == NULL) - return 1; - - memcpy(mcaddr->address, address, 6); - - mcaddr->next = adapter->mcastaddrs; - adapter->mcastaddrs = mcaddr; - - return (STATUS_SUCCESS); -} - static void sxg_mcast_set_bit(struct adapter_t *adapter, char *address) { unsigned char crcpoly; @@ -2810,7 +3549,8 @@ static void sxg_mcast_set_bit(struct adapter_t *adapter, char *address) /* Get the CRC polynomial for the mac address */ crcpoly = sxg_mcast_get_mac_hash(address); - /* We only have space on the SLIC for 64 entries. Lop + /* + * We only have space on the SLIC for 64 entries. Lop * off the top two bits. (2^6 = 64) */ crcpoly &= 0x3F; @@ -2819,76 +3559,119 @@ static void sxg_mcast_set_bit(struct adapter_t *adapter, char *address) adapter->MulticastMask |= (u64) 1 << crcpoly; } -static void sxg_mcast_set_list(p_net_device dev) +/* + * Function takes MAC addresses from dev_mc_list and generates the Mask + */ + +static void sxg_set_mcast_addr(struct adapter_t *adapter) +{ + struct dev_mc_list *mclist; + struct net_device *dev = adapter->netdev; + int i; + + if (adapter->MacFilter & (MAC_ALLMCAST | MAC_MCAST)) { + for (i = 0, mclist = dev->mc_list; i < dev->mc_count; + i++, mclist = mclist->next) { + sxg_mcast_set_bit(adapter,mclist->da_addr); + } + } + sxg_mcast_set_mask(adapter); +} + +static void sxg_mcast_set_list(struct net_device *dev) { struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); - int status = STATUS_SUCCESS; - int i; - char *addresses; - struct dev_mc_list *mc_list = dev->mc_list; - int mc_count = dev->mc_count; ASSERT(adapter); + if (dev->flags & IFF_PROMISC) + adapter->MacFilter |= MAC_PROMISC; + if (dev->flags & IFF_MULTICAST) + adapter->MacFilter |= MAC_MCAST; + if (dev->flags & IFF_ALLMULTI) + adapter->MacFilter |= MAC_ALLMCAST; - for (i = 1; i <= mc_count; i++) { - addresses = (char *)&mc_list->dmi_addr; - if (mc_list->dmi_addrlen == 6) { - status = sxg_mcast_add_list(adapter, addresses); - if (status != STATUS_SUCCESS) { - break; - } - } else { - status = -EINVAL; - break; - } - sxg_mcast_set_bit(adapter, addresses); - mc_list = mc_list->next; - } - - DBG_ERROR("%s a->devflags_prev[%x] dev->flags[%x] status[%x]\n", - __func__, adapter->devflags_prev, dev->flags, status); - if (adapter->devflags_prev != dev->flags) { - adapter->macopts = MAC_DIRECTED; - if (dev->flags) { - if (dev->flags & IFF_BROADCAST) { - adapter->macopts |= MAC_BCAST; - } - if (dev->flags & IFF_PROMISC) { - adapter->macopts |= MAC_PROMISC; - } - if (dev->flags & IFF_ALLMULTI) { - adapter->macopts |= MAC_ALLMCAST; - } - if (dev->flags & IFF_MULTICAST) { - adapter->macopts |= MAC_MCAST; - } - } - adapter->devflags_prev = dev->flags; - DBG_ERROR("%s call sxg_config_set adapter->macopts[%x]\n", - __func__, adapter->macopts); - sxg_config_set(adapter, TRUE); - } else { - if (status == STATUS_SUCCESS) { - sxg_mcast_set_mask(adapter); - } - } - return; + //XXX handle other flags as well + sxg_set_mcast_addr(adapter); } -#endif -static void sxg_unmap_mmio_space(struct adapter_t *adapter) +void sxg_free_sgl_buffers(struct adapter_t *adapter) { -#if LINUX_FREES_ADAPTER_RESOURCES -/* if (adapter->Regs) { */ -/* iounmap(adapter->Regs); */ -/* } */ -/* adapter->slic_regs = NULL; */ -#endif + struct list_entry *ple; + struct sxg_scatter_gather *Sgl; + + while(!(IsListEmpty(&adapter->AllSglBuffers))) { + ple = RemoveHeadList(&adapter->AllSglBuffers); + Sgl = container_of(ple, struct sxg_scatter_gather, AllList); + kfree(Sgl); + adapter->AllSglBufferCount--; + } } -#if XXXTODO +void sxg_free_rcvblocks(struct adapter_t *adapter) +{ + u32 i; + void *temp_RcvBlock; + struct list_entry *ple; + struct sxg_rcv_block_hdr *RcvBlockHdr; + struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr; + ASSERT((adapter->state == SXG_STATE_INITIALIZING) || + (adapter->state == SXG_STATE_HALTING)); + while(!(IsListEmpty(&adapter->AllRcvBlocks))) { + + ple = RemoveHeadList(&adapter->AllRcvBlocks); + RcvBlockHdr = container_of(ple, struct sxg_rcv_block_hdr, AllList); + + if(RcvBlockHdr->VirtualAddress) { + temp_RcvBlock = RcvBlockHdr->VirtualAddress; + + for(i=0; i< SXG_RCV_DESCRIPTORS_PER_BLOCK; + i++, temp_RcvBlock += SXG_RCV_DATA_HDR_SIZE) { + RcvDataBufferHdr = + (struct sxg_rcv_data_buffer_hdr *)temp_RcvBlock; + SXG_FREE_RCV_PACKET(RcvDataBufferHdr); + } + } + + pci_free_consistent(adapter->pcidev, + SXG_RCV_BLOCK_SIZE(SXG_RCV_DATA_HDR_SIZE), + RcvBlockHdr->VirtualAddress, + RcvBlockHdr->PhysicalAddress); + adapter->AllRcvBlockCount--; + } + ASSERT(adapter->AllRcvBlockCount == 0); + SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFrRBlk", + adapter, 0, 0, 0); +} +void sxg_free_mcast_addrs(struct adapter_t *adapter) +{ + struct sxg_multicast_address *address; + while(adapter->MulticastAddrs) { + address = adapter->MulticastAddrs; + adapter->MulticastAddrs = address->Next; + kfree(address); + } + + adapter->MulticastMask= 0; +} + +void sxg_unmap_resources(struct adapter_t *adapter) +{ + if(adapter->HwRegs) { + iounmap((void *)adapter->HwRegs); + } + if(adapter->UcodeRegs) { + iounmap((void *)adapter->UcodeRegs); + } + + ASSERT(adapter->AllRcvBlockCount == 0); + SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFrRBlk", + adapter, 0, 0, 0); +} + + + /* - * SxgFreeResources - Free everything allocated in SxgAllocateResources + * sxg_free_resources - Free everything allocated in SxgAllocateResources * * Arguments - * adapter - A pointer to our adapter structure @@ -2896,94 +3679,76 @@ static void sxg_unmap_mmio_space(struct adapter_t *adapter) * Return * none */ -void SxgFreeResources(struct adapter_t *adapter) +void sxg_free_resources(struct adapter_t *adapter) { u32 RssIds, IsrCount; - PTCP_OBJECT TcpObject; - u32 i; - BOOLEAN TimerCancelled; - - SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "FreeRes", - adapter, adapter->MaxTcbs, 0, 0); - RssIds = SXG_RSS_CPU_COUNT(adapter); - IsrCount = adapter->MsiEnabled ? RssIds : 1; + IsrCount = adapter->msi_enabled ? RssIds : 1; if (adapter->BasicAllocations == FALSE) { - /* No allocations have been made, including spinlocks, */ - /* or listhead initializations. Return. */ + /* + * No allocations have been made, including spinlocks, + * or listhead initializations. Return. + */ return; } if (!(IsListEmpty(&adapter->AllRcvBlocks))) { - SxgFreeRcvBlocks(adapter); + sxg_free_rcvblocks(adapter); } if (!(IsListEmpty(&adapter->AllSglBuffers))) { - SxgFreeSglBuffers(adapter); - } - /* Free event queues. */ - if (adapter->EventRings) { - pci_free_consistent(adapter->pcidev, - sizeof(struct SXG_EVENT_RING) * RssIds, - adapter->EventRings, adapter->PEventRings); - } - if (adapter->Isr) { - pci_free_consistent(adapter->pcidev, - sizeof(u32) * IsrCount, - adapter->Isr, adapter->PIsr); + sxg_free_sgl_buffers(adapter); } + if (adapter->XmtRingZeroIndex) { pci_free_consistent(adapter->pcidev, sizeof(u32), adapter->XmtRingZeroIndex, adapter->PXmtRingZeroIndex); } - if (adapter->IndirectionTable) { - pci_free_consistent(adapter->pcidev, - SXG_MAX_RSS_TABLE_SIZE, - adapter->IndirectionTable, - adapter->PIndirectionTable); + if (adapter->Isr) { + pci_free_consistent(adapter->pcidev, + sizeof(u32) * IsrCount, + adapter->Isr, adapter->PIsr); + } + + if (adapter->EventRings) { + pci_free_consistent(adapter->pcidev, + sizeof(struct sxg_event_ring) * RssIds, + adapter->EventRings, adapter->PEventRings); + } + if (adapter->RcvRings) { + pci_free_consistent(adapter->pcidev, + sizeof(struct sxg_rcv_ring) * 1, + adapter->RcvRings, + adapter->PRcvRings); + adapter->RcvRings = NULL; + } + + if(adapter->XmtRings) { + pci_free_consistent(adapter->pcidev, + sizeof(struct sxg_xmt_ring) * 1, + adapter->XmtRings, + adapter->PXmtRings); + adapter->XmtRings = NULL; + } + + if (adapter->ucode_stats) { + pci_unmap_single(adapter->pcidev, + sizeof(struct sxg_ucode_stats), + adapter->pucode_stats, PCI_DMA_FROMDEVICE); + adapter->ucode_stats = NULL; } - SXG_FREE_PACKET_POOL(adapter->PacketPoolHandle); - SXG_FREE_BUFFER_POOL(adapter->BufferPoolHandle); /* Unmap register spaces */ - SxgUnmapResources(adapter); + sxg_unmap_resources(adapter); - /* Deregister DMA */ - if (adapter->DmaHandle) { - SXG_DEREGISTER_DMA(adapter->DmaHandle); - } - /* Deregister interrupt */ - SxgDeregisterInterrupt(adapter); - - /* Possibly free system info (5.2 only) */ - SXG_RELEASE_SYSTEM_INFO(adapter); - - SxgDiagFreeResources(adapter); - - SxgFreeMCastAddrs(adapter); - - if (SXG_TIMER_ALLOCATED(adapter->ResetTimer)) { - SXG_CANCEL_TIMER(adapter->ResetTimer, TimerCancelled); - SXG_FREE_TIMER(adapter->ResetTimer); - } - if (SXG_TIMER_ALLOCATED(adapter->RssTimer)) { - SXG_CANCEL_TIMER(adapter->RssTimer, TimerCancelled); - SXG_FREE_TIMER(adapter->RssTimer); - } - if (SXG_TIMER_ALLOCATED(adapter->OffloadTimer)) { - SXG_CANCEL_TIMER(adapter->OffloadTimer, TimerCancelled); - SXG_FREE_TIMER(adapter->OffloadTimer); - } + sxg_free_mcast_addrs(adapter); adapter->BasicAllocations = FALSE; - SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFreeRes", - adapter, adapter->MaxTcbs, 0, 0); } -#endif /* * sxg_allocate_complete - @@ -3000,31 +3765,34 @@ void SxgFreeResources(struct adapter_t *adapter) * Return * None. */ -static void sxg_allocate_complete(struct adapter_t *adapter, +static int sxg_allocate_complete(struct adapter_t *adapter, void *VirtualAddress, dma_addr_t PhysicalAddress, - u32 Length, enum SXG_BUFFER_TYPE Context) + u32 Length, enum sxg_buffer_type Context) { + int status = 0; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocCmp", adapter, VirtualAddress, Length, Context); - ASSERT(adapter->AllocationsPending); - --adapter->AllocationsPending; + ASSERT(atomic_read(&adapter->pending_allocations)); + atomic_dec(&adapter->pending_allocations); switch (Context) { case SXG_BUFFER_TYPE_RCV: - sxg_allocate_rcvblock_complete(adapter, + status = sxg_allocate_rcvblock_complete(adapter, VirtualAddress, PhysicalAddress, Length); break; case SXG_BUFFER_TYPE_SGL: - sxg_allocate_sgl_buffer_complete(adapter, (struct SXG_SCATTER_GATHER*) + sxg_allocate_sgl_buffer_complete(adapter, (struct sxg_scatter_gather *) VirtualAddress, PhysicalAddress, Length); break; } SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlocCmp", adapter, VirtualAddress, Length, Context); + + return status; } /* @@ -3040,7 +3808,7 @@ static void sxg_allocate_complete(struct adapter_t *adapter, * int */ static int sxg_allocate_buffer_memory(struct adapter_t *adapter, - u32 Size, enum SXG_BUFFER_TYPE BufferType) + u32 Size, enum sxg_buffer_type BufferType) { int status; void *Buffer; @@ -3048,39 +3816,40 @@ static int sxg_allocate_buffer_memory(struct adapter_t *adapter, SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocMem", adapter, Size, BufferType, 0); - /* Grab the adapter lock and check the state. */ - /* If we're in anything other than INITIALIZING or */ - /* RUNNING state, fail. This is to prevent */ - /* allocations in an improper driver state */ - spin_lock(&adapter->AdapterLock); + /* + * Grab the adapter lock and check the state. If we're in anything other + * than INITIALIZING or RUNNING state, fail. This is to prevent + * allocations in an improper driver state + */ - /* Increment the AllocationsPending count while holding */ - /* the lock. Pause processing relies on this */ - ++adapter->AllocationsPending; - spin_unlock(&adapter->AdapterLock); + atomic_inc(&adapter->pending_allocations); - /* At initialization time allocate resources synchronously. */ - Buffer = pci_alloc_consistent(adapter->pcidev, Size, &pBuffer); + if(BufferType != SXG_BUFFER_TYPE_SGL) + Buffer = pci_alloc_consistent(adapter->pcidev, Size, &pBuffer); + else { + Buffer = kzalloc(Size, GFP_ATOMIC); + pBuffer = (dma_addr_t)NULL; + } if (Buffer == NULL) { - spin_lock(&adapter->AdapterLock); - /* Decrement the AllocationsPending count while holding */ - /* the lock. Pause processing relies on this */ - --adapter->AllocationsPending; - spin_unlock(&adapter->AdapterLock); + /* + * Decrement the AllocationsPending count while holding + * the lock. Pause processing relies on this + */ + atomic_dec(&adapter->pending_allocations); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlcMemF1", adapter, Size, BufferType, 0); return (STATUS_RESOURCES); } - sxg_allocate_complete(adapter, Buffer, pBuffer, Size, BufferType); - status = STATUS_SUCCESS; + status = sxg_allocate_complete(adapter, Buffer, pBuffer, Size, BufferType); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlocMem", adapter, Size, BufferType, status); - return (status); + return status; } /* - * sxg_allocate_rcvblock_complete - Complete a receive descriptor block allocation + * sxg_allocate_rcvblock_complete - Complete a receive descriptor + * block allocation * * Arguments - * adapter - A pointer to our adapter structure @@ -3089,9 +3858,8 @@ static int sxg_allocate_buffer_memory(struct adapter_t *adapter, * Length - Memory length * * Return - * */ -static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter, +static int sxg_allocate_rcvblock_complete(struct adapter_t *adapter, void *RcvBlock, dma_addr_t PhysicalAddress, u32 Length) @@ -3099,11 +3867,11 @@ static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter, u32 i; u32 BufferSize = adapter->ReceiveBufferSize; u64 Paddr; - struct SXG_RCV_BLOCK_HDR *RcvBlockHdr; - unsigned char *RcvDataBuffer; - struct SXG_RCV_DATA_BUFFER_HDR *RcvDataBufferHdr; - struct SXG_RCV_DESCRIPTOR_BLOCK *RcvDescriptorBlock; - struct SXG_RCV_DESCRIPTOR_BLOCK_HDR *RcvDescriptorBlockHdr; + void *temp_RcvBlock; + struct sxg_rcv_block_hdr *RcvBlockHdr; + struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr; + struct sxg_rcv_descriptor_block *RcvDescriptorBlock; + struct sxg_rcv_descriptor_block_hdr *RcvDescriptorBlockHdr; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlRcvBlk", adapter, RcvBlock, Length, 0); @@ -3113,42 +3881,33 @@ static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter, memset(RcvBlock, 0, Length); ASSERT((BufferSize == SXG_RCV_DATA_BUFFER_SIZE) || (BufferSize == SXG_RCV_JUMBO_BUFFER_SIZE)); - ASSERT(Length == SXG_RCV_BLOCK_SIZE(BufferSize)); - /* First, initialize the contained pool of receive data */ - /* buffers. This initialization requires NBL/NB/MDL allocations, */ - /* If any of them fail, free the block and return without */ - /* queueing the shared memory */ - RcvDataBuffer = RcvBlock; -#if 0 - for (i = 0, Paddr = *PhysicalAddress; - i < SXG_RCV_DESCRIPTORS_PER_BLOCK; - i++, Paddr.LowPart += BufferSize, RcvDataBuffer += BufferSize) -#endif - for (i = 0, Paddr = PhysicalAddress; - i < SXG_RCV_DESCRIPTORS_PER_BLOCK; - i++, Paddr += BufferSize, RcvDataBuffer += BufferSize) { - /* */ - RcvDataBufferHdr = - (struct SXG_RCV_DATA_BUFFER_HDR*) (RcvDataBuffer + - SXG_RCV_DATA_BUFFER_HDR_OFFSET - (BufferSize)); - RcvDataBufferHdr->VirtualAddress = RcvDataBuffer; - RcvDataBufferHdr->PhysicalAddress = Paddr; - RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM; /* For FREE macro assertion */ - RcvDataBufferHdr->Size = - SXG_RCV_BUFFER_DATA_SIZE(BufferSize); + ASSERT(Length == SXG_RCV_BLOCK_SIZE(SXG_RCV_DATA_HDR_SIZE)); + /* + * First, initialize the contained pool of receive data buffers. + * This initialization requires NBL/NB/MDL allocations, if any of them + * fail, free the block and return without queueing the shared memory + */ + //RcvDataBuffer = RcvBlock; + temp_RcvBlock = RcvBlock; + for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK; + i++, temp_RcvBlock += SXG_RCV_DATA_HDR_SIZE) { + RcvDataBufferHdr = (struct sxg_rcv_data_buffer_hdr *) + temp_RcvBlock; + /* For FREE macro assertion */ + RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM; + SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr, BufferSize); + if (RcvDataBufferHdr->SxgDumbRcvPacket == NULL) + goto fail; - SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr); - if (RcvDataBufferHdr->SxgDumbRcvPacket == NULL) - goto fail; + } - } + /* + * Place this entire block of memory on the AllRcvBlocks queue so it + * can be free later + */ - /* Place this entire block of memory on the AllRcvBlocks queue so it can be */ - /* free later */ - RcvBlockHdr = - (struct SXG_RCV_BLOCK_HDR*) ((unsigned char *)RcvBlock + - SXG_RCV_BLOCK_HDR_OFFSET(BufferSize)); + RcvBlockHdr = (struct sxg_rcv_block_hdr *) ((unsigned char *)RcvBlock + + SXG_RCV_BLOCK_HDR_OFFSET(SXG_RCV_DATA_HDR_SIZE)); RcvBlockHdr->VirtualAddress = RcvBlock; RcvBlockHdr->PhysicalAddress = PhysicalAddress; spin_lock(&adapter->RcvQLock); @@ -3156,14 +3915,15 @@ static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter, InsertTailList(&adapter->AllRcvBlocks, &RcvBlockHdr->AllList); spin_unlock(&adapter->RcvQLock); - /* Now free the contained receive data buffers that we initialized above */ - RcvDataBuffer = RcvBlock; + /* Now free the contained receive data buffers that we + * initialized above */ + temp_RcvBlock = RcvBlock; for (i = 0, Paddr = PhysicalAddress; i < SXG_RCV_DESCRIPTORS_PER_BLOCK; - i++, Paddr += BufferSize, RcvDataBuffer += BufferSize) { - RcvDataBufferHdr = (struct SXG_RCV_DATA_BUFFER_HDR*) (RcvDataBuffer + - SXG_RCV_DATA_BUFFER_HDR_OFFSET - (BufferSize)); + i++, Paddr += SXG_RCV_DATA_HDR_SIZE, + temp_RcvBlock += SXG_RCV_DATA_HDR_SIZE) { + RcvDataBufferHdr = + (struct sxg_rcv_data_buffer_hdr *)temp_RcvBlock; spin_lock(&adapter->RcvQLock); SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr); spin_unlock(&adapter->RcvQLock); @@ -3171,13 +3931,13 @@ static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter, /* Locate the descriptor block and put it on a separate free queue */ RcvDescriptorBlock = - (struct SXG_RCV_DESCRIPTOR_BLOCK*) ((unsigned char *)RcvBlock + + (struct sxg_rcv_descriptor_block *) ((unsigned char *)RcvBlock + SXG_RCV_DESCRIPTOR_BLOCK_OFFSET - (BufferSize)); + (SXG_RCV_DATA_HDR_SIZE)); RcvDescriptorBlockHdr = - (struct SXG_RCV_DESCRIPTOR_BLOCK_HDR*) ((unsigned char *)RcvBlock + + (struct sxg_rcv_descriptor_block_hdr *) ((unsigned char *)RcvBlock + SXG_RCV_DESCRIPTOR_BLOCK_HDR_OFFSET - (BufferSize)); + (SXG_RCV_DATA_HDR_SIZE)); RcvDescriptorBlockHdr->VirtualAddress = RcvDescriptorBlock; RcvDescriptorBlockHdr->PhysicalAddress = Paddr; spin_lock(&adapter->RcvQLock); @@ -3185,17 +3945,15 @@ static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter, spin_unlock(&adapter->RcvQLock); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlRBlk", adapter, RcvBlock, Length, 0); - return; - fail: + return STATUS_SUCCESS; +fail: /* Free any allocated resources */ if (RcvBlock) { - RcvDataBuffer = RcvBlock; + temp_RcvBlock = RcvBlock; for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK; - i++, RcvDataBuffer += BufferSize) { + i++, temp_RcvBlock += SXG_RCV_DATA_HDR_SIZE) { RcvDataBufferHdr = - (struct SXG_RCV_DATA_BUFFER_HDR*) (RcvDataBuffer + - SXG_RCV_DATA_BUFFER_HDR_OFFSET - (BufferSize)); + (struct sxg_rcv_data_buffer_hdr *)temp_RcvBlock; SXG_FREE_RCV_PACKET(RcvDataBufferHdr); } pci_free_consistent(adapter->pcidev, @@ -3206,6 +3964,10 @@ static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter, adapter, adapter->FreeRcvBufferCount, adapter->FreeRcvBlockCount, adapter->AllRcvBlockCount); adapter->Stats.NoMem++; + /* As allocation failed, free all previously allocated blocks..*/ + //sxg_free_rcvblocks(adapter); + + return STATUS_RESOURCES; } /* @@ -3213,46 +3975,65 @@ static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter, * * Arguments - * adapter - A pointer to our adapter structure - * SxgSgl - SXG_SCATTER_GATHER buffer + * SxgSgl - struct sxg_scatter_gather buffer * PhysicalAddress - Physical address * Length - Memory length * * Return - * */ static void sxg_allocate_sgl_buffer_complete(struct adapter_t *adapter, - struct SXG_SCATTER_GATHER *SxgSgl, + struct sxg_scatter_gather *SxgSgl, dma_addr_t PhysicalAddress, u32 Length) { + unsigned long sgl_flags; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlSglCmp", adapter, SxgSgl, Length, 0); - spin_lock(&adapter->SglQLock); + spin_lock_irqsave(&adapter->SglQLock, sgl_flags); adapter->AllSglBufferCount++; - memset(SxgSgl, 0, sizeof(struct SXG_SCATTER_GATHER*)); - SxgSgl->PhysicalAddress = PhysicalAddress; /* *PhysicalAddress; */ - SxgSgl->adapter = adapter; /* Initialize backpointer once */ + /* PhysicalAddress; */ + SxgSgl->PhysicalAddress = PhysicalAddress; + /* Initialize backpointer once */ + SxgSgl->adapter = adapter; InsertTailList(&adapter->AllSglBuffers, &SxgSgl->AllList); - spin_unlock(&adapter->SglQLock); + spin_unlock_irqrestore(&adapter->SglQLock, sgl_flags); SxgSgl->State = SXG_BUFFER_BUSY; SXG_FREE_SGL_BUFFER(adapter, SxgSgl, NULL); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlSgl", adapter, SxgSgl, Length, 0); } -static unsigned char temp_mac_address[6] = - { 0x00, 0xab, 0xcd, 0xef, 0x12, 0x69 }; -static void sxg_adapter_set_hwaddr(struct adapter_t *adapter) +static int sxg_adapter_set_hwaddr(struct adapter_t *adapter) { -/* DBG_ERROR ("%s ENTER card->config_set[%x] port[%d] physport[%d] funct#[%d]\n", __func__, */ -/* card->config_set, adapter->port, adapter->physport, adapter->functionnumber); */ -/* */ -/* sxg_dbg_macaddrs(adapter); */ + /* + * DBG_ERROR ("%s ENTER card->config_set[%x] port[%d] physport[%d] \ + * funct#[%d]\n", __func__, card->config_set, + * adapter->port, adapter->physport, adapter->functionnumber); + * + * sxg_dbg_macaddrs(adapter); + */ + /* DBG_ERROR ("%s AFTER copying from config.macinfo into currmacaddr\n", + * __FUNCTION__); + */ + + /* sxg_dbg_macaddrs(adapter); */ + + struct net_device * dev = adapter->netdev; + if(!dev) + { + printk("sxg: Dev is Null\n"); + } + + DBG_ERROR("%s ENTER (%s)\n", __FUNCTION__, adapter->netdev->name); + + if (netif_running(dev)) { + return -EBUSY; + } + if (!adapter) { + return -EBUSY; + } - memcpy(adapter->macaddr, temp_mac_address, sizeof(struct SXG_CONFIG_MAC)); -/* DBG_ERROR ("%s AFTER copying from config.macinfo into currmacaddr\n", __func__); */ -/* sxg_dbg_macaddrs(adapter); */ if (!(adapter->currmacaddr[0] || adapter->currmacaddr[1] || adapter->currmacaddr[2] || @@ -3262,14 +4043,16 @@ static void sxg_adapter_set_hwaddr(struct adapter_t *adapter) } if (adapter->netdev) { memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, 6); + memcpy(adapter->netdev->perm_addr, adapter->currmacaddr, 6); } -/* DBG_ERROR ("%s EXIT port %d\n", __func__, adapter->port); */ + /* DBG_ERROR ("%s EXIT port %d\n", __func__, adapter->port); */ sxg_dbg_macaddrs(adapter); + return 0; } #if XXXTODO -static int sxg_mac_set_address(p_net_device dev, void *ptr) +static int sxg_mac_set_address(struct net_device *dev, void *ptr) { struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev); struct sockaddr *addr = ptr; @@ -3300,34 +4083,34 @@ static int sxg_mac_set_address(p_net_device dev, void *ptr) } #endif -/*****************************************************************************/ -/************* SXG DRIVER FUNCTIONS (below) ********************************/ -/*****************************************************************************/ - /* + * SXG DRIVER FUNCTIONS (below) + * * sxg_initialize_adapter - Initialize adapter * * Arguments - * adapter - A pointer to our adapter structure * - * Return - * int + * Return - int */ static int sxg_initialize_adapter(struct adapter_t *adapter) { u32 RssIds, IsrCount; u32 i; int status; + int sxg_rcv_ring_size = SXG_RCV_RING_SIZE; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "InitAdpt", adapter, 0, 0, 0); RssIds = 1; /* XXXTODO SXG_RSS_CPU_COUNT(adapter); */ - IsrCount = adapter->MsiEnabled ? RssIds : 1; + IsrCount = adapter->msi_enabled ? RssIds : 1; - /* Sanity check SXG_UCODE_REGS structure definition to */ - /* make sure the length is correct */ - ASSERT(sizeof(struct SXG_UCODE_REGS) == SXG_REGISTER_SIZE_PER_CPU); + /* + * Sanity check SXG_UCODE_REGS structure definition to + * make sure the length is correct + */ + ASSERT(sizeof(struct sxg_ucode_regs) == SXG_REGISTER_SIZE_PER_CPU); /* Disable interrupts */ SXG_DISABLE_ALL_INTERRUPTS(adapter); @@ -3370,19 +4153,24 @@ static int sxg_initialize_adapter(struct adapter_t *adapter) /* Receive ring base and size */ WRITE_REG64(adapter, adapter->UcodeRegs[0].RcvBase, adapter->PRcvRings, 0); - WRITE_REG(adapter->UcodeRegs[0].RcvSize, SXG_RCV_RING_SIZE, TRUE); + if (adapter->JumboEnabled == TRUE) + sxg_rcv_ring_size = SXG_JUMBO_RCV_RING_SIZE; + WRITE_REG(adapter->UcodeRegs[0].RcvSize, sxg_rcv_ring_size, TRUE); /* Populate the card with receive buffers */ sxg_stock_rcv_buffers(adapter); - /* Initialize checksum offload capabilities. At the moment */ - /* we always enable IP and TCP receive checksums on the card. */ - /* Depending on the checksum configuration specified by the */ - /* user, we can choose to report or ignore the checksum */ - /* information provided by the card. */ + /* + * Initialize checksum offload capabilities. At the moment we always + * enable IP and TCP receive checksums on the card. Depending on the + * checksum configuration specified by the user, we can choose to + * report or ignore the checksum information provided by the card. + */ WRITE_REG(adapter->UcodeRegs[0].ReceiveChecksum, SXG_RCV_TCP_CSUM_ENABLED | SXG_RCV_IP_CSUM_ENABLED, TRUE); + adapter->flags |= (SXG_RCV_TCP_CSUM_ENABLED | SXG_RCV_IP_CSUM_ENABLED ); + /* Initialize the MAC, XAUI */ DBG_ERROR("sxg: %s ENTER sxg_initialize_link\n", __func__); status = sxg_initialize_link(adapter); @@ -3391,10 +4179,16 @@ static int sxg_initialize_adapter(struct adapter_t *adapter) if (status != STATUS_SUCCESS) { return (status); } - /* Initialize Dead to FALSE. */ - /* SlicCheckForHang or SlicDumpThread will take it from here. */ + /* + * Initialize Dead to FALSE. + * SlicCheckForHang or SlicDumpThread will take it from here. + */ adapter->Dead = FALSE; adapter->PingOutstanding = FALSE; + adapter->XmtFcEnabled = TRUE; + adapter->RcvFcEnabled = TRUE; + + adapter->State = SXG_STATE_RUNNING; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XInit", adapter, 0, 0, 0); @@ -3413,15 +4207,14 @@ static int sxg_initialize_adapter(struct adapter_t *adapter) * status */ static int sxg_fill_descriptor_block(struct adapter_t *adapter, - struct SXG_RCV_DESCRIPTOR_BLOCK_HDR - *RcvDescriptorBlockHdr) + struct sxg_rcv_descriptor_block_hdr *RcvDescriptorBlockHdr) { u32 i; - struct SXG_RING_INFO *RcvRingInfo = &adapter->RcvRingZeroInfo; - struct SXG_RCV_DATA_BUFFER_HDR *RcvDataBufferHdr; - struct SXG_RCV_DESCRIPTOR_BLOCK *RcvDescriptorBlock; - struct SXG_CMD *RingDescriptorCmd; - struct SXG_RCV_RING *RingZero = &adapter->RcvRings[0]; + struct sxg_ring_info *RcvRingInfo = &adapter->RcvRingZeroInfo; + struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr; + struct sxg_rcv_descriptor_block *RcvDescriptorBlock; + struct sxg_cmd *RingDescriptorCmd; + struct sxg_rcv_ring *RingZero = &adapter->RcvRings[0]; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "FilBlk", adapter, adapter->RcvBuffersOnCard, @@ -3429,8 +4222,10 @@ static int sxg_fill_descriptor_block(struct adapter_t *adapter, ASSERT(RcvDescriptorBlockHdr); - /* If we don't have the resources to fill the descriptor block, */ - /* return failure */ + /* + * If we don't have the resources to fill the descriptor block, + * return failure + */ if ((adapter->FreeRcvBufferCount < SXG_RCV_DESCRIPTORS_PER_BLOCK) || SXG_RING_FULL(RcvRingInfo)) { adapter->Stats.NoMem++; @@ -3441,27 +4236,40 @@ static int sxg_fill_descriptor_block(struct adapter_t *adapter, RcvRingInfo, RingDescriptorCmd, RcvDescriptorBlockHdr); ASSERT(RingDescriptorCmd); RcvDescriptorBlockHdr->State = SXG_BUFFER_ONCARD; - RcvDescriptorBlock = - (struct SXG_RCV_DESCRIPTOR_BLOCK*) RcvDescriptorBlockHdr->VirtualAddress; + RcvDescriptorBlock = (struct sxg_rcv_descriptor_block *) + RcvDescriptorBlockHdr->VirtualAddress; /* Fill in the descriptor block */ for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK; i++) { SXG_GET_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr); ASSERT(RcvDataBufferHdr); +// ASSERT(RcvDataBufferHdr->SxgDumbRcvPacket); + if (!RcvDataBufferHdr->SxgDumbRcvPacket) { + SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr, + adapter->ReceiveBufferSize); + if(RcvDataBufferHdr->skb) + RcvDataBufferHdr->SxgDumbRcvPacket = + RcvDataBufferHdr->skb; + else + goto no_memory; + } SXG_REINIATIALIZE_PACKET(RcvDataBufferHdr->SxgDumbRcvPacket); RcvDataBufferHdr->State = SXG_BUFFER_ONCARD; RcvDescriptorBlock->Descriptors[i].VirtualAddress = - (void *)RcvDataBufferHdr; + (void *)RcvDataBufferHdr; + RcvDescriptorBlock->Descriptors[i].PhysicalAddress = RcvDataBufferHdr->PhysicalAddress; } /* Add the descriptor block to receive descriptor ring 0 */ RingDescriptorCmd->Sgl = RcvDescriptorBlockHdr->PhysicalAddress; - /* RcvBuffersOnCard is not protected via the receive lock (see */ - /* sxg_process_event_queue) We don't want to grap a lock every time a */ - /* buffer is returned to us, so we use atomic interlocked functions */ - /* instead. */ + /* + * RcvBuffersOnCard is not protected via the receive lock (see + * sxg_process_event_queue) We don't want to grap a lock every time a + * buffer is returned to us, so we use atomic interlocked functions + * instead. + */ adapter->RcvBuffersOnCard += SXG_RCV_DESCRIPTORS_PER_BLOCK; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DscBlk", @@ -3473,6 +4281,23 @@ static int sxg_fill_descriptor_block(struct adapter_t *adapter, adapter, adapter->RcvBuffersOnCard, adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount); return (STATUS_SUCCESS); +no_memory: + for (; i >= 0 ; i--) { + if (RcvDescriptorBlock->Descriptors[i].VirtualAddress) { + RcvDataBufferHdr = (struct sxg_rcv_data_buffer_hdr *) + RcvDescriptorBlock->Descriptors[i]. + VirtualAddress; + RcvDescriptorBlock->Descriptors[i].PhysicalAddress = + (dma_addr_t)NULL; + RcvDescriptorBlock->Descriptors[i].VirtualAddress=NULL; + } + SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr); + } + RcvDescriptorBlockHdr->State = SXG_BUFFER_FREE; + SXG_RETURN_CMD(RingZero, RcvRingInfo, RingDescriptorCmd, + RcvDescriptorBlockHdr); + + return (-ENOMEM); } /* @@ -3486,34 +4311,42 @@ static int sxg_fill_descriptor_block(struct adapter_t *adapter, */ static void sxg_stock_rcv_buffers(struct adapter_t *adapter) { - struct SXG_RCV_DESCRIPTOR_BLOCK_HDR *RcvDescriptorBlockHdr; + struct sxg_rcv_descriptor_block_hdr *RcvDescriptorBlockHdr; + int sxg_rcv_data_buffers = SXG_RCV_DATA_BUFFERS; + int sxg_min_rcv_data_buffers = SXG_MIN_RCV_DATA_BUFFERS; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "StockBuf", adapter, adapter->RcvBuffersOnCard, adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount); - /* First, see if we've got less than our minimum threshold of */ - /* receive buffers, there isn't an allocation in progress, and */ - /* we haven't exceeded our maximum.. get another block of buffers */ - /* None of this needs to be SMP safe. It's round numbers. */ - if ((adapter->FreeRcvBufferCount < SXG_MIN_RCV_DATA_BUFFERS) && + /* + * First, see if we've got less than our minimum threshold of + * receive buffers, there isn't an allocation in progress, and + * we haven't exceeded our maximum.. get another block of buffers + * None of this needs to be SMP safe. It's round numbers. + */ + if (adapter->JumboEnabled == TRUE) + sxg_min_rcv_data_buffers = SXG_MIN_JUMBO_RCV_DATA_BUFFERS; + if ((adapter->FreeRcvBufferCount < sxg_min_rcv_data_buffers) && (adapter->AllRcvBlockCount < SXG_MAX_RCV_BLOCKS) && - (adapter->AllocationsPending == 0)) { + (atomic_read(&adapter->pending_allocations) == 0)) { sxg_allocate_buffer_memory(adapter, - SXG_RCV_BLOCK_SIZE(adapter-> - ReceiveBufferSize), + SXG_RCV_BLOCK_SIZE + (SXG_RCV_DATA_HDR_SIZE), SXG_BUFFER_TYPE_RCV); } /* Now grab the RcvQLock lock and proceed */ spin_lock(&adapter->RcvQLock); - while (adapter->RcvBuffersOnCard < SXG_RCV_DATA_BUFFERS) { - struct LIST_ENTRY *_ple; + if (adapter->JumboEnabled) + sxg_rcv_data_buffers = SXG_JUMBO_RCV_DATA_BUFFERS; + while (adapter->RcvBuffersOnCard < sxg_rcv_data_buffers) { + struct list_entry *_ple; /* Get a descriptor block */ RcvDescriptorBlockHdr = NULL; if (adapter->FreeRcvBlockCount) { _ple = RemoveHeadList(&adapter->FreeRcvBlocks); RcvDescriptorBlockHdr = - container_of(_ple, struct SXG_RCV_DESCRIPTOR_BLOCK_HDR, + container_of(_ple, struct sxg_rcv_descriptor_block_hdr, FreeList); adapter->FreeRcvBlockCount--; RcvDescriptorBlockHdr->State = SXG_BUFFER_BUSY; @@ -3553,10 +4386,10 @@ static void sxg_stock_rcv_buffers(struct adapter_t *adapter) static void sxg_complete_descriptor_blocks(struct adapter_t *adapter, unsigned char Index) { - struct SXG_RCV_RING *RingZero = &adapter->RcvRings[0]; - struct SXG_RING_INFO *RcvRingInfo = &adapter->RcvRingZeroInfo; - struct SXG_RCV_DESCRIPTOR_BLOCK_HDR *RcvDescriptorBlockHdr; - struct SXG_CMD *RingDescriptorCmd; + struct sxg_rcv_ring *RingZero = &adapter->RcvRings[0]; + struct sxg_ring_info *RcvRingInfo = &adapter->RcvRingZeroInfo; + struct sxg_rcv_descriptor_block_hdr *RcvDescriptorBlockHdr; + struct sxg_cmd *RingDescriptorCmd; SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpRBlks", adapter, Index, RcvRingInfo->Head, RcvRingInfo->Tail); @@ -3564,12 +4397,13 @@ static void sxg_complete_descriptor_blocks(struct adapter_t *adapter, /* Now grab the RcvQLock lock and proceed */ spin_lock(&adapter->RcvQLock); ASSERT(Index != RcvRingInfo->Tail); - while (RcvRingInfo->Tail != Index) { - /* */ - /* Locate the current Cmd (ring descriptor entry), and */ - /* associated receive descriptor block, and advance */ - /* the tail */ - /* */ + while (sxg_ring_get_forward_diff(RcvRingInfo, Index, + RcvRingInfo->Tail) > 3) { + /* + * Locate the current Cmd (ring descriptor entry), and + * associated receive descriptor block, and advance + * the tail + */ SXG_RETURN_CMD(RingZero, RcvRingInfo, RingDescriptorCmd, RcvDescriptorBlockHdr); @@ -3579,23 +4413,66 @@ static void sxg_complete_descriptor_blocks(struct adapter_t *adapter, /* Clear the SGL field */ RingDescriptorCmd->Sgl = 0; - /* Attempt to refill it and hand it right back to the */ - /* card. If we fail to refill it, free the descriptor block */ - /* header. The card will be restocked later via the */ - /* RcvBuffersOnCard test */ - if (sxg_fill_descriptor_block(adapter, RcvDescriptorBlockHdr) == - STATUS_FAILURE) { + /* + * Attempt to refill it and hand it right back to the + * card. If we fail to refill it, free the descriptor block + * header. The card will be restocked later via the + * RcvBuffersOnCard test + */ + if (sxg_fill_descriptor_block(adapter, + RcvDescriptorBlockHdr) == STATUS_FAILURE) SXG_FREE_RCV_DESCRIPTOR_BLOCK(adapter, RcvDescriptorBlockHdr); - } } spin_unlock(&adapter->RcvQLock); SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XCRBlks", adapter, Index, RcvRingInfo->Head, RcvRingInfo->Tail); } +/* + * Read the statistics which the card has been maintaining. + */ +void sxg_collect_statistics(struct adapter_t *adapter) +{ + if(adapter->ucode_stats) + WRITE_REG64(adapter, adapter->UcodeRegs[0].GetUcodeStats, + adapter->pucode_stats, 0); + adapter->stats.rx_fifo_errors = adapter->ucode_stats->ERDrops; + adapter->stats.rx_over_errors = adapter->ucode_stats->NBDrops; + adapter->stats.tx_fifo_errors = adapter->ucode_stats->XDrops; +} + +static struct net_device_stats *sxg_get_stats(struct net_device * dev) +{ + struct adapter_t *adapter = netdev_priv(dev); + + sxg_collect_statistics(adapter); + return (&adapter->stats); +} + +static void sxg_watchdog(unsigned long data) +{ + struct adapter_t *adapter = (struct adapter_t *) data; + + if (adapter->state != ADAPT_DOWN) { + sxg_link_event(adapter); + /* Reset the timer */ + mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ)); + } +} + +static void sxg_update_link_status (struct work_struct *work) +{ + struct adapter_t *adapter = (struct adapter_t *)container_of + (work, struct adapter_t, update_link_status); + if (likely(adapter->link_status_changed)) { + sxg_link_event(adapter); + adapter->link_status_changed = 0; + } +} + static struct pci_driver sxg_driver = { - .name = DRV_NAME, + .name = sxg_driver_name, .id_table = sxg_pci_tbl, .probe = sxg_entry_probe, .remove = sxg_entry_remove, @@ -3603,7 +4480,7 @@ static struct pci_driver sxg_driver = { .suspend = sxgpm_suspend, .resume = sxgpm_resume, #endif -/* .shutdown = slic_shutdown, MOOK_INVESTIGATE */ + /* .shutdown = slic_shutdown, MOOK_INVESTIGATE */ }; static int __init sxg_module_init(void) diff --git a/drivers/staging/sxg/sxg.h b/drivers/staging/sxg/sxg.h index 653cf3ba0c4c..f07aa708d862 100644 --- a/drivers/staging/sxg/sxg.h +++ b/drivers/staging/sxg/sxg.h @@ -42,357 +42,369 @@ #ifndef __SXG_DRIVER_H__ #define __SXG_DRIVER_H__ -#define p_net_device struct net_device * -// SXG_STATS - Probably move these to someplace where -// the slicstat (sxgstat?) program can get them. -struct SXG_STATS { - // Xmt - u32 XmtNBL; // Offload send NBL count - u64 DumbXmtBytes; // Dumbnic send bytes - u64 SlowXmtBytes; // Slowpath send bytes - u64 FastXmtBytes; // Fastpath send bytes - u64 DumbXmtPkts; // Dumbnic send packets - u64 SlowXmtPkts; // Slowpath send packets - u64 FastXmtPkts; // Fastpath send packets - u64 DumbXmtUcastPkts; // directed packets - u64 DumbXmtMcastPkts; // Multicast packets - u64 DumbXmtBcastPkts; // OID_GEN_BROADCAST_FRAMES_RCV - u64 DumbXmtUcastBytes; // OID_GEN_DIRECTED_BYTES_XMIT - u64 DumbXmtMcastBytes; // OID_GEN_MULTICAST_BYTES_XMIT - u64 DumbXmtBcastBytes; // OID_GEN_BROADCAST_BYTES_XMIT - u64 XmtErrors; // OID_GEN_XMIT_ERROR - u64 XmtDiscards; // OID_GEN_XMIT_DISCARDS - u64 XmtOk; // OID_GEN_XMIT_OK - u64 XmtQLen; // OID_GEN_TRANSMIT_QUEUE_LENGTH - u64 XmtZeroFull; // Transmit ring zero full - // Rcv - u32 RcvNBL; // Offload recieve NBL count - u64 DumbRcvBytes; // dumbnic recv bytes - u64 DumbRcvUcastBytes; // OID_GEN_DIRECTED_BYTES_RCV - u64 DumbRcvMcastBytes; // OID_GEN_MULTICAST_BYTES_RCV - u64 DumbRcvBcastBytes; // OID_GEN_BROADCAST_BYTES_RCV - u64 SlowRcvBytes; // Slowpath recv bytes - u64 FastRcvBytes; // Fastpath recv bytes - u64 DumbRcvPkts; // OID_GEN_DIRECTED_FRAMES_RCV - u64 DumbRcvTcpPkts; // See SxgCollectStats - u64 DumbRcvUcastPkts; // directed packets - u64 DumbRcvMcastPkts; // Multicast packets - u64 DumbRcvBcastPkts; // OID_GEN_BROADCAST_FRAMES_RCV - u64 SlowRcvPkts; // OID_GEN_DIRECTED_FRAMES_RCV - u64 RcvErrors; // OID_GEN_RCV_ERROR - u64 RcvDiscards; // OID_GEN_RCV_DISCARDS - u64 RcvNoBuffer; // OID_GEN_RCV_NO_BUFFER - u64 PdqFull; // Processed Data Queue Full - u64 EventRingFull; // Event ring full - // Verbose stats - u64 MaxSends; // Max sends outstanding - u64 NoSglBuf; // SGL buffer allocation failure - u64 SglFail; // NDIS SGL failure - u64 SglAsync; // NDIS SGL failure - u64 NoMem; // Memory allocation failure - u64 NumInts; // Interrupts - u64 FalseInts; // Interrupt with ISR == 0 - u64 XmtDrops; // No sahara DRAM buffer for xmt - // Sahara receive status - u64 TransportCsum; // SXG_RCV_STATUS_TRANSPORT_CSUM - u64 TransportUflow; // SXG_RCV_STATUS_TRANSPORT_UFLOW - u64 TransportHdrLen; // SXG_RCV_STATUS_TRANSPORT_HDRLEN - u64 NetworkCsum; // SXG_RCV_STATUS_NETWORK_CSUM: - u64 NetworkUflow; // SXG_RCV_STATUS_NETWORK_UFLOW: - u64 NetworkHdrLen; // SXG_RCV_STATUS_NETWORK_HDRLEN: - u64 Parity; // SXG_RCV_STATUS_PARITY - u64 LinkParity; // SXG_RCV_STATUS_LINK_PARITY: - u64 LinkEarly; // SXG_RCV_STATUS_LINK_EARLY: - u64 LinkBufOflow; // SXG_RCV_STATUS_LINK_BUFOFLOW: - u64 LinkCode; // SXG_RCV_STATUS_LINK_CODE: - u64 LinkDribble; // SXG_RCV_STATUS_LINK_DRIBBLE: - u64 LinkCrc; // SXG_RCV_STATUS_LINK_CRC: - u64 LinkOflow; // SXG_RCV_STATUS_LINK_OFLOW: - u64 LinkUflow; // SXG_RCV_STATUS_LINK_UFLOW: +#define SLIC_DUMP_ENABLED 0 + +#define SXG_DRV_NAME "sxg" /* TBD: This might be removed eventually */ +#define SXG_DRV_VERSION "1.0.1" + +extern char sxg_driver_name[]; + +#define SXG_NETDEV_WEIGHT 64 + +/* + * struct sxg_stats - Probably move these to someplace where + * the slicstat (sxgstat?) program can get them. + */ +struct sxg_stats { + /* Xmt */ + u64 DumbXmtUcastPkts; /* directed packets */ + u64 DumbXmtMcastPkts; /* Multicast packets */ + u64 DumbXmtBcastPkts; /* OID_GEN_BROADCAST_FRAMES_RCV */ + u64 DumbXmtUcastBytes; /* OID_GEN_DIRECTED_BYTES_XMIT */ + u64 DumbXmtMcastBytes; /* OID_GEN_MULTICAST_BYTES_XMIT */ + u64 DumbXmtBcastBytes; /* OID_GEN_BROADCAST_BYTES_XMIT */ + u64 XmtQLen; /* OID_GEN_TRANSMIT_QUEUE_LENGTH */ + u64 XmtZeroFull; /* Transmit ring zero full */ + /* Rcv */ + u64 DumbRcvUcastBytes; /* OID_GEN_DIRECTED_BYTES_RCV */ + u64 DumbRcvMcastBytes; /* OID_GEN_MULTICAST_BYTES_RCV */ + u64 DumbRcvBcastBytes; /* OID_GEN_BROADCAST_BYTES_RCV */ + u64 DumbRcvUcastPkts; /* directed packets */ + u64 DumbRcvMcastPkts; /* Multicast packets */ + u64 DumbRcvBcastPkts; /* OID_GEN_BROADCAST_FRAMES_RCV */ + u64 PdqFull; /* Processed Data Queue Full */ + u64 EventRingFull; /* Event ring full */ + /* Verbose stats */ + u64 NoSglBuf; /* SGL buffer allocation failure */ + u64 NoMem; /* Memory allocation failure */ + u64 NumInts; /* Interrupts */ + u64 FalseInts; /* Interrupt with ISR == 0 */ + /* Sahara receive status */ + u64 TransportCsum; /* SXG_RCV_STATUS_TRANSPORT_CSUM */ + u64 TransportUflow; /* SXG_RCV_STATUS_TRANSPORT_UFLOW */ + u64 TransportHdrLen; /* SXG_RCV_STATUS_TRANSPORT_HDRLEN */ + u64 NetworkCsum; /* SXG_RCV_STATUS_NETWORK_CSUM: */ + u64 NetworkUflow; /* SXG_RCV_STATUS_NETWORK_UFLOW: */ + u64 NetworkHdrLen; /* SXG_RCV_STATUS_NETWORK_HDRLEN: */ + u64 Parity; /* SXG_RCV_STATUS_PARITY */ + u64 LinkParity; /* SXG_RCV_STATUS_LINK_PARITY: */ + u64 LinkEarly; /* SXG_RCV_STATUS_LINK_EARLY: */ + u64 LinkBufOflow; /* SXG_RCV_STATUS_LINK_BUFOFLOW: */ + u64 LinkCode; /* SXG_RCV_STATUS_LINK_CODE: */ + u64 LinkDribble; /* SXG_RCV_STATUS_LINK_DRIBBLE: */ + u64 LinkCrc; /* SXG_RCV_STATUS_LINK_CRC: */ + u64 LinkOflow; /* SXG_RCV_STATUS_LINK_OFLOW: */ + u64 LinkUflow; /* SXG_RCV_STATUS_LINK_UFLOW: */ }; -/**************************************************************************** - * DUMB-NIC Send path definitions - ****************************************************************************/ +/* DUMB-NIC Send path definitions */ -#define SXG_COMPLETE_DUMB_SEND(_pAdapt, _skb) { \ - ASSERT(_skb); \ - dev_kfree_skb_irq(_skb); \ +#define SXG_COMPLETE_DUMB_SEND(_pAdapt, _skb, _phys_addr, _size) { \ + ASSERT(_skb); \ + pci_unmap_single(_pAdapt->pcidev, _size, _phys_addr, PCI_DMA_TODEVICE); \ + dev_kfree_skb_irq(_skb); \ } -#define SXG_DROP_DUMB_SEND(_pAdapt, _skb) { \ - ASSERT(_skb); \ - dev_kfree_skb(_skb); \ +#define SXG_DROP_DUMB_SEND(_pAdapt, _skb) { \ + ASSERT(_skb); \ } -// Locate current receive header buffer location. Use this -// instead of RcvDataHdr->VirtualAddress since the data -// may have been offset by SXG_ADVANCE_MDL_OFFSET +/* + * Locate current receive header buffer location. Use this + * instead of RcvDataHdr->VirtualAddress since the data + * may have been offset by SXG_ADVANCE_MDL_OFFSET + */ #define SXG_RECEIVE_DATA_LOCATION(_RcvDataHdr) (_RcvDataHdr)->skb->data -/************************************************************************ - * Dumb-NIC receive processing - ************************************************************************/ -// Define an SXG_PACKET as an NDIS_PACKET +/* Dumb-NIC receive processing */ +/* Define an SXG_PACKET as an NDIS_PACKET */ #define PSXG_PACKET struct sk_buff * -// Indications array size +/* Indications array size */ #define SXG_RCV_ARRAYSIZE 64 -#define SXG_ALLOCATE_RCV_PACKET(_pAdapt, _RcvDataBufferHdr) { \ - struct sk_buff * skb; \ - skb = alloc_skb(2048, GFP_ATOMIC); \ - if (skb) { \ - (_RcvDataBufferHdr)->skb = skb; \ - skb->next = NULL; \ - } else { \ - (_RcvDataBufferHdr)->skb = NULL; \ - } \ +#define SXG_ALLOCATE_RCV_PACKET(_pAdapt, _RcvDataBufferHdr, BufferSize) {\ + struct sk_buff * skb; \ + skb = netdev_alloc_skb(_pAdapt->netdev, BufferSize); \ + if (skb) { \ + (_RcvDataBufferHdr)->skb = skb; \ + skb->next = NULL; \ + _RcvDataBufferHdr->PhysicalAddress = pci_map_single(adapter->pcidev,\ + _RcvDataBufferHdr->skb->data, BufferSize, PCI_DMA_FROMDEVICE); \ + if (SXG_INVALID_SGL(_RcvDataBufferHdr->PhysicalAddress,BufferSize)) \ + printk(KERN_EMERG "SXG_ALLOCATE_RCV_PACKET: RCV packet" \ + "non-64k boundary aligned\n"); \ + } else { \ + (_RcvDataBufferHdr)->skb = NULL; \ + } \ } -#define SXG_FREE_RCV_PACKET(_RcvDataBufferHdr) { \ - if((_RcvDataBufferHdr)->skb) { \ - dev_kfree_skb((_RcvDataBufferHdr)->skb); \ - } \ +#define SXG_FREE_RCV_PACKET(_RcvDataBufferHdr) { \ + if((_RcvDataBufferHdr)->skb) { \ + dev_kfree_skb((_RcvDataBufferHdr)->skb); \ + } \ } -// Macro to add a NDIS_PACKET to an indication array -// If we fill up our array of packet pointers, then indicate this -// block up now and start on a new one. -#define SXG_ADD_RCV_PACKET(_pAdapt, _Packet, _PrevPacket, _IndicationList, _NumPackets) { \ - (_IndicationList)[_NumPackets] = (_Packet); \ - (_NumPackets)++; \ - if((_NumPackets) == SXG_RCV_ARRAYSIZE) { \ - SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "IndicRcv", \ - (_NumPackets), 0, 0, 0); \ - netif_rx((_IndicationList),(_NumPackets)); \ - (_NumPackets) = 0; \ - } \ +/* + * Macro to add a NDIS_PACKET to an indication array + * If we fill up our array of packet pointers, then indicate this + * block up now and start on a new one. + */ +#define SXG_ADD_RCV_PACKET(_pAdapt, _Packet, _PrevPacket, _IndicationList, \ + _NumPackets) { \ + (_IndicationList)[_NumPackets] = (_Packet); \ + (_NumPackets)++; \ + if((_NumPackets) == SXG_RCV_ARRAYSIZE) { \ + SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "IndicRcv", \ + (_NumPackets), 0, 0, 0); \ + netif_rx((_IndicationList),(_NumPackets)); \ + (_NumPackets) = 0; \ + } \ } -#define SXG_INDICATE_PACKETS(_pAdapt, _IndicationList, _NumPackets) { \ - if(_NumPackets) { \ - SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "IndicRcv", \ - (_NumPackets), 0, 0, 0); \ - netif_rx((_IndicationList),(_NumPackets)); \ - (_NumPackets) = 0; \ - } \ +#define SXG_INDICATE_PACKETS(_pAdapt, _IndicationList, _NumPackets) { \ + if(_NumPackets) { \ + SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "IndicRcv", \ + (_NumPackets), 0, 0, 0); \ + netif_rx((_IndicationList),(_NumPackets)); \ + (_NumPackets) = 0; \ + } \ } -#define SXG_REINIATIALIZE_PACKET(_Packet) \ - {} /*_NdisReinitializePacket(_Packet)*/ /* this is not necessary with an skb */ +#define SXG_REINIATIALIZE_PACKET(_Packet) \ + {} /*_NdisReinitializePacket(_Packet)*/ + /* this is not necessary with an skb */ -// Definitions to initialize Dumb-nic Receive NBLs -#define SXG_RCV_PACKET_BUFFER_HDR(_Packet) (((PSXG_RCV_NBL_RESERVED)((_Packet)->MiniportReservedEx))->RcvDataBufferHdr) +/* Definitions to initialize Dumb-nic Receive NBLs */ +#define SXG_RCV_PACKET_BUFFER_HDR(_Packet) (((struct sxg_rcv_nbl_reserved *)\ + ((_Packet)->MiniportReservedEx))->RcvDataBufferHdr) -#define SXG_RCV_SET_CHECKSUM_INFO(_Packet, _Cpi) \ - NDIS_PER_PACKET_INFO_FROM_PACKET((_Packet), TcpIpChecksumPacketInfo) = (PVOID)(_Cpi) +#define SXG_RCV_SET_CHECKSUM_INFO(_Packet, _Cpi) \ + NDIS_PER_PACKET_INFO_FROM_PACKET((_Packet), \ + TcpIpChecksumPacketInfo) = (PVOID)(_Cpi) #define SXG_RCV_SET_TOEPLITZ(_Packet, _Toeplitz, _Type, _Function) { \ - NDIS_PACKET_SET_HASH_VALUE((_Packet), (_Toeplitz)); \ - NDIS_PACKET_SET_HASH_TYPE((_Packet), (_Type)); \ - NDIS_PACKET_SET_HASH_FUNCTION((_Packet), (_Function)); \ + NDIS_PACKET_SET_HASH_VALUE((_Packet), (_Toeplitz)); \ + NDIS_PACKET_SET_HASH_TYPE((_Packet), (_Type)); \ + NDIS_PACKET_SET_HASH_FUNCTION((_Packet), (_Function)); \ } -#define SXG_RCV_SET_VLAN_INFO(_Packet, _VlanId, _Priority) { \ - NDIS_PACKET_8021Q_INFO _Packet8021qInfo; \ - _Packet8021qInfo.TagHeader.VlanId = (_VlanId); \ - _Packet8021qInfo.TagHeader.UserPriority = (_Priority); \ +#define SXG_RCV_SET_VLAN_INFO(_Packet, _VlanId, _Priority) { \ + NDIS_PACKET_8021Q_INFO _Packet8021qInfo; \ + _Packet8021qInfo.TagHeader.VlanId = (_VlanId); \ + _Packet8021qInfo.TagHeader.UserPriority = (_Priority); \ NDIS_PER_PACKET_INFO_FROM_PACKET((_Packet), Ieee8021QNetBufferListInfo) = \ - _Packet8021qInfo.Value; \ + _Packet8021qInfo.Value; \ } -#define SXG_ADJUST_RCV_PACKET(_Packet, _RcvDataBufferHdr, _Event) { \ - SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbRcv", \ - (_RcvDataBufferHdr), (_Packet), \ - (_Event)->Status, 0); \ - ASSERT((_Event)->Length <= (_RcvDataBufferHdr)->Size); \ - Packet->len = (_Event)->Length; \ +#define SXG_ADJUST_RCV_PACKET(_Packet, _RcvDataBufferHdr, _Event) { \ + SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbRcv", \ + (_RcvDataBufferHdr), (_Packet), \ + (_Event)->Status, 0); \ + /* ASSERT((_Event)->Length <= (_RcvDataBufferHdr)->Size); */ \ + skb_put(Packet, (_Event)->Length); \ } -/////////////////////////////////////////////////////////////////////////////// -// Macros to free a receive data buffer and receive data descriptor block -/////////////////////////////////////////////////////////////////////////////// -// NOTE - Lock must be held with RCV macros -#define SXG_GET_RCV_DATA_BUFFER(_pAdapt, _Hdr) { \ - struct LIST_ENTRY *_ple; \ - _Hdr = NULL; \ - if((_pAdapt)->FreeRcvBufferCount) { \ - ASSERT(!(IsListEmpty(&(_pAdapt)->FreeRcvBuffers))); \ - _ple = RemoveHeadList(&(_pAdapt)->FreeRcvBuffers); \ - (_Hdr) = container_of(_ple, struct SXG_RCV_DATA_BUFFER_HDR, FreeList); \ - (_pAdapt)->FreeRcvBufferCount--; \ - ASSERT((_Hdr)->State == SXG_BUFFER_FREE); \ - } \ +/* + * Macros to free a receive data buffer and receive data descriptor block + * NOTE - Lock must be held with RCV macros + */ +#define SXG_GET_RCV_DATA_BUFFER(_pAdapt, _Hdr) { \ + struct list_entry *_ple; \ + _Hdr = NULL; \ + if((_pAdapt)->FreeRcvBufferCount) { \ + ASSERT(!(IsListEmpty(&(_pAdapt)->FreeRcvBuffers))); \ + _ple = RemoveHeadList(&(_pAdapt)->FreeRcvBuffers); \ + (_Hdr) = container_of(_ple, struct sxg_rcv_data_buffer_hdr, \ + FreeList); \ + (_pAdapt)->FreeRcvBufferCount--; \ + ASSERT((_Hdr)->State == SXG_BUFFER_FREE); \ + } \ } -#define SXG_FREE_RCV_DATA_BUFFER(_pAdapt, _Hdr) { \ - SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RtnDHdr", \ - (_Hdr), (_pAdapt)->FreeRcvBufferCount, \ - (_Hdr)->State, (_Hdr)->VirtualAddress); \ -/* SXG_RESTORE_MDL_OFFSET(_Hdr); */ \ - (_pAdapt)->FreeRcvBufferCount++; \ - ASSERT(((_pAdapt)->AllRcvBlockCount * SXG_RCV_DESCRIPTORS_PER_BLOCK) >= (_pAdapt)->FreeRcvBufferCount); \ - ASSERT((_Hdr)->State != SXG_BUFFER_FREE); \ - (_Hdr)->State = SXG_BUFFER_FREE; \ - InsertTailList(&(_pAdapt)->FreeRcvBuffers, &((_Hdr)->FreeList)); \ +#define SXG_FREE_RCV_DATA_BUFFER(_pAdapt, _Hdr) { \ + SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RtnDHdr", \ + (_Hdr), (_pAdapt)->FreeRcvBufferCount, \ + (_Hdr)->State, 0/*(_Hdr)->VirtualAddress*/); \ +/* SXG_RESTORE_MDL_OFFSET(_Hdr); */ \ + (_pAdapt)->FreeRcvBufferCount++; \ + ASSERT(((_pAdapt)->AllRcvBlockCount * SXG_RCV_DESCRIPTORS_PER_BLOCK) \ + >= (_pAdapt)->FreeRcvBufferCount); \ + ASSERT((_Hdr)->State != SXG_BUFFER_FREE); \ + (_Hdr)->State = SXG_BUFFER_FREE; \ + InsertTailList(&(_pAdapt)->FreeRcvBuffers, &((_Hdr)->FreeList)); \ } -#define SXG_FREE_RCV_DESCRIPTOR_BLOCK(_pAdapt, _Hdr) { \ - ASSERT((_Hdr)->State != SXG_BUFFER_FREE); \ - (_Hdr)->State = SXG_BUFFER_FREE; \ - (_pAdapt)->FreeRcvBlockCount++; \ +#define SXG_FREE_RCV_DESCRIPTOR_BLOCK(_pAdapt, _Hdr) { \ + ASSERT((_Hdr)->State != SXG_BUFFER_FREE); \ + (_Hdr)->State = SXG_BUFFER_FREE; \ + (_pAdapt)->FreeRcvBlockCount++; \ ASSERT((_pAdapt)->AllRcvBlockCount >= (_pAdapt)->FreeRcvBlockCount); \ - InsertTailList(&(_pAdapt)->FreeRcvBlocks, &(_Hdr)->FreeList); \ + InsertTailList(&(_pAdapt)->FreeRcvBlocks, &(_Hdr)->FreeList); \ } -// SGL macros -#define SXG_FREE_SGL_BUFFER(_pAdapt, _Sgl, _NB) { \ - spin_lock(&(_pAdapt)->SglQLock); \ - (_pAdapt)->FreeSglBufferCount++; \ - ASSERT((_pAdapt)->AllSglBufferCount >= (_pAdapt)->FreeSglBufferCount);\ - ASSERT(!((_Sgl)->State & SXG_BUFFER_FREE)); \ - (_Sgl)->State = SXG_BUFFER_FREE; \ - InsertTailList(&(_pAdapt)->FreeSglBuffers, &(_Sgl)->FreeList); \ - spin_unlock(&(_pAdapt)->SglQLock); \ +/* SGL macros */ +#define SXG_FREE_SGL_BUFFER(_pAdapt, _Sgl, _NB) { \ + spin_lock_irqsave(&(_pAdapt)->SglQLock, sgl_flags); \ + (_pAdapt)->FreeSglBufferCount++; \ + ASSERT((_pAdapt)->AllSglBufferCount >= (_pAdapt)->FreeSglBufferCount); \ + ASSERT(!((_Sgl)->State & SXG_BUFFER_FREE)); \ + (_Sgl)->State = SXG_BUFFER_FREE; \ + InsertTailList(&(_pAdapt)->FreeSglBuffers, &(_Sgl)->FreeList); \ + spin_unlock_irqrestore(&(_pAdapt)->SglQLock, sgl_flags); \ } -// Get an SGL buffer from the free queue. The first part of this macro -// attempts to keep ahead of buffer depletion by allocating more when -// we hit a minimum threshold. Note that we don't grab the lock -// until after that. We're dealing with round numbers here, so we don't need to, -// and not grabbing it avoids a possible double-trip. -#define SXG_GET_SGL_BUFFER(_pAdapt, _Sgl) { \ - struct LIST_ENTRY *_ple; \ +/* + * Get an SGL buffer from the free queue. The first part of this macro + * attempts to keep ahead of buffer depletion by allocating more when + * we hit a minimum threshold. Note that we don't grab the lock + * until after that. We're dealing with round numbers here, so we don't need to, + * and not grabbing it avoids a possible double-trip. + */ +#define SXG_GET_SGL_BUFFER(_pAdapt, _Sgl, _irq) { \ + struct list_entry *_ple; \ if ((_pAdapt->FreeSglBufferCount < SXG_MIN_SGL_BUFFERS) && \ (_pAdapt->AllSglBufferCount < SXG_MAX_SGL_BUFFERS) && \ - (_pAdapt->AllocationsPending == 0)) { \ + (atomic_read(&_pAdapt->pending_allocations) == 0)) { \ sxg_allocate_buffer_memory(_pAdapt, \ - (sizeof(struct SXG_SCATTER_GATHER) + SXG_SGL_BUF_SIZE),\ + (sizeof(struct sxg_scatter_gather) + SXG_SGL_BUF_SIZE),\ SXG_BUFFER_TYPE_SGL); \ } \ _Sgl = NULL; \ - spin_lock(&(_pAdapt)->SglQLock); \ + if(!_irq) \ + spin_lock_irqsave(&(_pAdapt)->SglQLock, sgl_flags); \ + else \ + spin_lock_irqsave(&(_pAdapt)->SglQLock, sgl_flags); \ if((_pAdapt)->FreeSglBufferCount) { \ ASSERT(!(IsListEmpty(&(_pAdapt)->FreeSglBuffers))); \ _ple = RemoveHeadList(&(_pAdapt)->FreeSglBuffers); \ - (_Sgl) = container_of(_ple, struct SXG_SCATTER_GATHER, FreeList); \ + (_Sgl) = container_of(_ple, struct sxg_scatter_gather, \ + FreeList); \ (_pAdapt)->FreeSglBufferCount--; \ ASSERT((_Sgl)->State == SXG_BUFFER_FREE); \ (_Sgl)->State = SXG_BUFFER_BUSY; \ (_Sgl)->pSgl = NULL; \ } \ - spin_unlock(&(_pAdapt)->SglQLock); \ + if(!_irq) \ + spin_unlock_irqrestore(&(_pAdapt)->SglQLock, sgl_flags);\ + else \ + spin_unlock_irqrestore(&(_pAdapt)->SglQLock, sgl_flags);\ } -// -// SXG_MULTICAST_ADDRESS -// -// Linked list of multicast addresses. -struct SXG_MULTICAST_ADDRESS { - unsigned char Address[6]; - struct SXG_MULTICAST_ADDRESS *Next; +/* + * struct sxg_multicast_address + * Linked list of multicast addresses. + */ +struct sxg_multicast_address { + unsigned char Address[6]; + struct sxg_multicast_address *Next; }; -// Structure to maintain chimney send and receive buffer queues. -// This structure maintains NET_BUFFER_LIST queues that are -// given to us via the Chimney MiniportTcpOffloadSend and -// MiniportTcpOffloadReceive routines. This structure DOES NOT -// manage our data buffer queue -struct SXG_BUFFER_QUEUE { - u32 Type; // Slow or fast - See below - u32 Direction; // Xmt or Rcv - u32 Bytes; // Byte count - u32 * Head; // Send queue head - u32 * Tail; // Send queue tail -// PNET_BUFFER_LIST NextNBL; // Short cut - next NBL -// PNET_BUFFER NextNB; // Short cut - next NB +/* + * Structure to maintain chimney send and receive buffer queues. + * This structure maintains NET_BUFFER_LIST queues that are + * given to us via the Chimney MiniportTcpOffloadSend and + * MiniportTcpOffloadReceive routines. This structure DOES NOT + * manage our data buffer queue + */ +struct sxg_buffer_queue { + u32 Type; /* Slow or fast - See below */ + u32 Direction; /* Xmt or Rcv */ + u32 Bytes; /* Byte count */ + u32 * Head; /* Send queue head */ + u32 * Tail; /* Send queue tail */ +/* PNET_BUFFER_LIST NextNBL;*/ /* Short cut - next NBL */ +/* PNET_BUFFER NextNB; */ /* Short cut - next NB */ }; #define SXG_SLOW_SEND_BUFFER 0 #define SXG_FAST_SEND_BUFFER 1 #define SXG_RECEIVE_BUFFER 2 -#define SXG_INIT_BUFFER(_Buffer, _Type) { \ - (_Buffer)->Type = (_Type); \ - if((_Type) == SXG_RECEIVE_BUFFER) { \ - (_Buffer)->Direction = 0; \ - } else { \ +#define SXG_INIT_BUFFER(_Buffer, _Type) { \ + (_Buffer)->Type = (_Type); \ + if((_Type) == SXG_RECEIVE_BUFFER) { \ + (_Buffer)->Direction = 0; \ + } else { \ (_Buffer)->Direction = NDIS_SG_LIST_WRITE_TO_DEVICE; \ - } \ - (_Buffer)->Bytes = 0; \ - (_Buffer)->Head = NULL; \ - (_Buffer)->Tail = NULL; \ + } \ + (_Buffer)->Bytes = 0; \ + (_Buffer)->Head = NULL; \ + (_Buffer)->Tail = NULL; \ } -#define SXG_RSS_CPU_COUNT(_pAdapt) \ +#define SXG_RSS_CPU_COUNT(_pAdapt) \ ((_pAdapt)->RssEnabled ? NR_CPUS : 1) -/**************************************************************************** - * DRIVER and ADAPTER structures - ****************************************************************************/ +/* DRIVER and ADAPTER structures */ -// Adapter states - These states closely match the adapter states -// documented in the DDK (with a few exceptions). +/* + * Adapter states - These states closely match the adapter states + * documented in the DDK (with a few exceptions). + */ enum SXG_STATE { - SXG_STATE_INITIALIZING, // Initializing - SXG_STATE_BOOTDIAG, // Boot-Diagnostic mode - SXG_STATE_PAUSING, // Pausing - SXG_STATE_PAUSED, // Paused - SXG_STATE_RUNNING, // Running - SXG_STATE_RESETTING, // Reset in progress - SXG_STATE_SLEEP, // Sleeping - SXG_STATE_DIAG, // Diagnostic mode - SXG_STATE_HALTING, // Halting - SXG_STATE_HALTED, // Down or not-initialized - SXG_STATE_SHUTDOWN // shutdown + SXG_STATE_INITIALIZING, /* Initializing */ + SXG_STATE_BOOTDIAG, /* Boot-Diagnostic mode */ + SXG_STATE_PAUSING, /* Pausing */ + SXG_STATE_PAUSED, /* Paused */ + SXG_STATE_RUNNING, /* Running */ + SXG_STATE_RESETTING, /* Reset in progress */ + SXG_STATE_SLEEP, /* Sleeping */ + SXG_STATE_DIAG, /* Diagnostic mode */ + SXG_STATE_HALTING, /* Halting */ + SXG_STATE_HALTED, /* Down or not-initialized */ + SXG_STATE_SHUTDOWN /* shutdown */ }; -// Link state +/* Link state */ enum SXG_LINK_STATE { SXG_LINK_DOWN, SXG_LINK_UP }; -// Link initialization timeout in 100us units -#define SXG_LINK_TIMEOUT 100000 // 10 Seconds - REDUCE! +/* Link initialization timeout in 100us units */ +#define SXG_LINK_TIMEOUT 100000 /* 10 Seconds - REDUCE! */ -// Microcode file selection codes +/* Microcode file selection codes */ enum SXG_UCODE_SEL { - SXG_UCODE_SAHARA, // Sahara ucode - SXG_UCODE_SDIAGCPU, // Sahara CPU diagnostic ucode - SXG_UCODE_SDIAGSYS // Sahara system diagnostic ucode + SXG_UCODE_SYSTEM, /* System (operational) uucode */ + SXG_UCODE_SDIAGCPU, /* System CPU diagnostic ucode */ + SXG_UCODE_SDIAGSYS /* System diagnostic ucode */ }; #define SXG_DISABLE_ALL_INTERRUPTS(_padapt) sxg_disable_interrupt(_padapt) #define SXG_ENABLE_ALL_INTERRUPTS(_padapt) sxg_enable_interrupt(_padapt) -// This probably lives in a proto.h file. Move later +/* This probably lives in a proto.h file. Move later */ #define SXG_MULTICAST_PACKET(_pether) ((_pether)->ether_dhost[0] & 0x01) -#define SXG_BROADCAST_PACKET(_pether) ((*(u32 *)(_pether)->ether_dhost == 0xFFFFFFFF) && \ - (*(u16 *)&(_pether)->ether_dhost[4] == 0xFFFF)) +#define SXG_BROADCAST_PACKET(_pether) \ + ((*(u32 *)(_pether)->ether_dhost == 0xFFFFFFFF) && \ + (*(u16 *)&(_pether)->ether_dhost[4] == 0xFFFF)) -// For DbgPrints +/* For DbgPrints */ #define SXG_ID DPFLTR_IHVNETWORK_ID #define SXG_ERROR DPFLTR_ERROR_LEVEL -// -// SXG_DRIVER structure - -// -// contains information about the sxg driver. There is only -// one of these, and it is defined as a global. -struct SXG_DRIVER { - struct adapter_t *Adapters; // Linked list of adapters - ushort AdapterID; // Maintain unique adapter ID +/* + * struct sxg_driver structure - + * + * contains information about the sxg driver. There is only + * one of these, and it is defined as a global. + */ + +struct sxg_driver { + struct adapter_t *Adapters; /* Linked list of adapters */ + ushort AdapterID; /* Maintain unique adapter ID */ }; #ifdef STATUS_SUCCESS #undef STATUS_SUCCESS #endif +/* TODO: We need to try and use NETDEV_TX_* before posting this out */ #define STATUS_SUCCESS 0 #define STATUS_PENDING 0 #define STATUS_FAILURE -1 @@ -404,34 +416,36 @@ struct SXG_DRIVER { #define SLIC_MAX_CARDS 32 #define SLIC_MAX_PORTS 4 /* Max # of ports per card */ #if SLIC_DUMP_ENABLED -// Dump buffer size -// -// This cannot be bigger than the max DMA size the card supports, -// given the current code structure in the host and ucode. -// Mojave supports 16K, Oasis supports 16K-1, so -// just set this at 15K, shouldnt make that much of a diff. -#define DUMP_BUF_SIZE 0x3C00 + +/* + * Dump buffer size + * This cannot be bigger than the max DMA size the card supports, + * given the current code structure in the host and ucode. + * Mojave supports 16K, Oasis supports 16K-1, so + * just set this at 15K, shouldnt make that much of a diff. + */ +#define DUMP_BUF_SIZE 0x3C00 #endif #define MIN(a, b) ((u32)(a) < (u32)(b) ? (a) : (b)) #define MAX(a, b) ((u32)(a) > (u32)(b) ? (a) : (b)) -struct mcast_address_t { - unsigned char address[6]; - struct mcast_address_t *next; +struct mcast_address { + unsigned char address[6]; + struct mcast_address *next; }; -#define CARD_DOWN 0x00000000 -#define CARD_UP 0x00000001 -#define CARD_FAIL 0x00000002 -#define CARD_DIAG 0x00000003 -#define CARD_SLEEP 0x00000004 +#define CARD_DOWN 0x00000000 +#define CARD_UP 0x00000001 +#define CARD_FAIL 0x00000002 +#define CARD_DIAG 0x00000003 +#define CARD_SLEEP 0x00000004 -#define ADAPT_DOWN 0x00 -#define ADAPT_UP 0x01 -#define ADAPT_FAIL 0x02 -#define ADAPT_RESET 0x03 -#define ADAPT_SLEEP 0x04 +#define ADAPT_DOWN 0x00 +#define ADAPT_UP 0x01 +#define ADAPT_FAIL 0x02 +#define ADAPT_RESET 0x03 +#define ADAPT_SLEEP 0x04 #define ADAPT_FLAGS_BOOTTIME 0x0001 #define ADAPT_FLAGS_IS64BIT 0x0002 @@ -443,29 +457,30 @@ struct mcast_address_t { #define ADAPT_FLAGS_STATS_TIMER_SET 0x0080 #define ADAPT_FLAGS_RESET_TIMER_SET 0x0100 -#define LINK_DOWN 0x00 -#define LINK_CONFIG 0x01 -#define LINK_UP 0x02 +#define LINK_DOWN 0x00 +#define LINK_CONFIG 0x01 +#define LINK_UP 0x02 -#define LINK_10MB 0x00 -#define LINK_100MB 0x01 -#define LINK_AUTOSPEED 0x02 -#define LINK_1000MB 0x03 -#define LINK_10000MB 0x04 +#define LINK_10MB 0x00 +#define LINK_100MB 0x01 +#define LINK_AUTOSPEED 0x02 +#define LINK_1000MB 0x03 +#define LINK_10000MB 0x04 -#define LINK_HALFD 0x00 -#define LINK_FULLD 0x01 -#define LINK_AUTOD 0x02 +#define LINK_HALFD 0x00 +#define LINK_FULLD 0x01 +#define LINK_AUTOD 0x02 -#define MAC_DIRECTED 0x00000001 -#define MAC_BCAST 0x00000002 -#define MAC_MCAST 0x00000004 -#define MAC_PROMISC 0x00000008 -#define MAC_LOOPBACK 0x00000010 -#define MAC_ALLMCAST 0x00000020 +#define MAC_DIRECTED 0x00000001 +#define MAC_BCAST 0x00000002 +#define MAC_MCAST 0x00000004 +#define MAC_PROMISC 0x00000008 +#define MAC_LOOPBACK 0x00000010 +#define MAC_ALLMCAST 0x00000020 #define SLIC_DUPLEX(x) ((x==LINK_FULLD) ? "FDX" : "HDX") -#define SLIC_SPEED(x) ((x==LINK_100MB) ? "100Mb" : ((x==LINK_1000MB) ? "1000Mb" : " 10Mb")) +#define SLIC_SPEED(x) ((x==LINK_100MB) ? "100Mb" : \ + ((x==LINK_1000MB) ? "1000Mb" : " 10Mb")) #define SLIC_LINKSTATE(x) ((x==LINK_DOWN) ? "Down" : "Up ") #define SLIC_ADAPTER_STATE(x) ((x==ADAPT_UP) ? "UP" : "Down") #define SLIC_CARD_STATE(x) ((x==CARD_UP) ? "UP" : "Down") @@ -481,32 +496,36 @@ struct ether_header { #define NUM_CFG_SPACES 2 #define NUM_CFG_REGS 64 -struct physcard_t { - struct adapter_t *adapter[SLIC_MAX_PORTS]; - struct physcard_t *next; +/* + * We split LSS sends across four microcode queues derived from + * destination TCP port (if TCP/IP). + */ +#define SXG_LARGE_SEND_QUEUE_MASK 0x3 +#define ISCSI_PORT 0xbc0c /* 3260 */ + +struct physcard { + struct adapter_t *adapter[SLIC_MAX_PORTS]; + struct physcard *next; unsigned int adapters_allocd; }; -struct sxgbase_driver_t { +struct sxgbase_driver { spinlock_t driver_lock; unsigned long flags; /* irqsave for spinlock */ u32 num_sxg_cards; u32 num_sxg_ports; u32 num_sxg_ports_active; u32 dynamic_intagg; - struct physcard_t *phys_card; + struct physcard *phys_card; }; struct adapter_t { void * ifp; unsigned int port; - struct physcard_t *physcard; + struct napi_struct napi; + struct physcard *physcard; unsigned int physport; - unsigned int cardindex; - unsigned int card_size; - unsigned int chipid; - unsigned int busnumber; unsigned int slotnumber; unsigned int functionnumber; ushort vendid; @@ -514,32 +533,23 @@ struct adapter_t { ushort subsysid; u32 irq; - void * sxg_adapter; - u32 nBusySend; - void __iomem * base_addr; u32 memorylength; u32 drambase; u32 dramlength; - unsigned int queues_initialized; - unsigned int allocated; + enum asic_type asictype; /* type of ASIC (chip) */ unsigned int activated; u32 intrregistered; unsigned int isp_initialized; - unsigned int gennumber; - u32 curaddrupper; - u32 isrcopy; unsigned char state; unsigned char linkstate; - unsigned char linkspeed; - unsigned char linkduplex; unsigned int flags; unsigned char macaddr[6]; unsigned char currmacaddr[6]; u32 macopts; ushort devflags_prev; u64 mcastmask; - struct mcast_address_t *mcastaddrs; + struct mcast_address *mcastaddrs; struct timer_list pingtimer; u32 pingtimerset; struct timer_list statstimer; @@ -574,135 +584,140 @@ struct adapter_t { u32 rcv_interrupt_yields; u32 intagg_period; struct net_device_stats stats; - u32 * MiniportHandle; // Our miniport handle - enum SXG_STATE State; // Adapter state - enum SXG_LINK_STATE LinkState; // Link state - u64 LinkSpeed; // Link Speed - u32 PowerState; // NDIS power state - struct adapter_t *Next; // Linked list - ushort AdapterID; // 1..n - unsigned char MacAddr[6]; // Our permanent HW mac address - unsigned char CurrMacAddr[6]; // Our Current mac address - p_net_device netdev; - p_net_device next_netdevice; - struct pci_dev * pcidev; + u32 * MiniportHandle; /* Our miniport handle */ + enum SXG_STATE State; /* Adapter state */ + enum SXG_LINK_STATE LinkState; /* Link state */ + u64 LinkSpeed; /* Link Speed */ + u32 PowerState; /* NDIS power state */ + struct adapter_t *Next; /* Linked list */ + ushort AdapterID; /* 1..n */ + struct net_device * netdev; + struct net_device * next_netdevice; + struct pci_dev *pcidev; + + struct sxg_multicast_address *MulticastAddrs; /* Multicast list */ + u64 MulticastMask; /* Multicast mask */ + u32 *InterruptHandle; /* Register Interrupt handle */ + u32 InterruptLevel; /* From Resource list */ + u32 InterruptVector; /* From Resource list */ + spinlock_t AdapterLock; /* Serialize access adapter routines */ + spinlock_t Bit64RegLock; /* For writing 64-bit addresses */ + struct sxg_hw_regs *HwRegs; /* Sahara HW Register Memory (BAR0/1) */ + struct sxg_ucode_regs *UcodeRegs; /* Microcode Register Memory (BAR2/3) */ + struct sxg_tcb_regs *TcbRegs; /* Same as Ucode regs - See sxghw.h */ + ushort FrameSize; /* Maximum frame size */ + u32 * DmaHandle; /* NDIS DMA handle */ + u32 * PacketPoolHandle; /* Used with NDIS 5.2 only. Don't ifdef out */ + u32 * BufferPoolHandle; /* Used with NDIS 5.2 only. Don't ifdef out */ + u32 MacFilter; /* NDIS MAC Filter */ + struct sxg_event_ring *EventRings; /* Host event rings. 1/CPU to 16 max */ + dma_addr_t PEventRings; /* Physical address */ + u32 NextEvent[SXG_MAX_RSS]; /* Current location in ring */ + dma_addr_t PTcbBuffers; /* TCB Buffers - physical address */ + dma_addr_t PTcbCompBuffers; /* TCB Composite Buffers - phys addr */ + struct sxg_xmt_ring *XmtRings; /* Transmit rings */ + dma_addr_t PXmtRings; /* Transmit rings - physical address */ + struct sxg_ring_info XmtRingZeroInfo; /* Transmit ring 0 info */ - struct SXG_MULTICAST_ADDRESS *MulticastAddrs; // Multicast list - u64 MulticastMask; // Multicast mask - u32 * InterruptHandle; // Register Interrupt handle - u32 InterruptLevel; // From Resource list - u32 InterruptVector; // From Resource list - spinlock_t AdapterLock; /* Serialize access adapter routines */ - spinlock_t Bit64RegLock; /* For writing 64-bit addresses */ - struct SXG_HW_REGS *HwRegs; // Sahara HW Register Memory (BAR0/1) - struct SXG_UCODE_REGS *UcodeRegs; // Microcode Register Memory (BAR2/3) - struct SXG_TCB_REGS *TcbRegs; // Same as Ucode regs - See sxghw.h - ushort ResetDpcCount; // For timeout - ushort RssDpcCount; // For timeout - ushort VendorID; // Vendor ID - ushort DeviceID; // Device ID - ushort SubSystemID; // Sub-System ID - ushort FrameSize; // Maximum frame size - u32 * DmaHandle; // NDIS DMA handle - u32 * PacketPoolHandle; // Used with NDIS 5.2 only. Don't ifdef out - u32 * BufferPoolHandle; // Used with NDIS 5.2 only. Don't ifdef out - u32 MacFilter; // NDIS MAC Filter - ushort IpId; // For slowpath - struct SXG_EVENT_RING *EventRings; // Host event rings. 1/CPU to 16 max - dma_addr_t PEventRings; // Physical address - u32 NextEvent[SXG_MAX_RSS]; // Current location in ring - dma_addr_t PTcbBuffers; // TCB Buffers - physical address - dma_addr_t PTcbCompBuffers; // TCB Composite Buffers - phys addr - struct SXG_XMT_RING *XmtRings; // Transmit rings - dma_addr_t PXmtRings; // Transmit rings - physical address - struct SXG_RING_INFO XmtRingZeroInfo; // Transmit ring 0 info spinlock_t XmtZeroLock; /* Transmit ring 0 lock */ - u32 * XmtRingZeroIndex; // Shared XMT ring 0 index - dma_addr_t PXmtRingZeroIndex; // Shared XMT ring 0 index - physical - struct LIST_ENTRY FreeProtocolHeaders;// Free protocol headers - u32 FreeProtoHdrCount; // Count - void * ProtocolHeaders; // Block of protocol header - dma_addr_t PProtocolHeaders; // Block of protocol headers - phys + u32 * XmtRingZeroIndex; /* Shared XMT ring 0 index */ + dma_addr_t PXmtRingZeroIndex; /* Shared XMT ring 0 index - physical */ + struct list_entry FreeProtocolHeaders;/* Free protocol headers */ + u32 FreeProtoHdrCount; /* Count */ + void * ProtocolHeaders; /* Block of protocol header */ + dma_addr_t PProtocolHeaders; /* Block of protocol headers - phys */ - struct SXG_RCV_RING *RcvRings; // Receive rings - dma_addr_t PRcvRings; // Receive rings - physical address - struct SXG_RING_INFO RcvRingZeroInfo; // Receive ring 0 info + struct sxg_rcv_ring *RcvRings; /* Receive rings */ + dma_addr_t PRcvRings; /* Receive rings - physical address */ + struct sxg_ucode_stats *ucode_stats; /* Ucode Stats */ + /* Ucode Stats - physical address */ + dma_addr_t pucode_stats; - u32 * Isr; // Interrupt status register - dma_addr_t PIsr; // ISR - physical address - u32 IsrCopy[SXG_MAX_RSS]; // Copy of ISR - ushort InterruptsEnabled; // Bitmask of enabled vectors - unsigned char * IndirectionTable; // RSS indirection table - dma_addr_t PIndirectionTable; // Physical address - ushort RssTableSize; // From NDIS_RECEIVE_SCALE_PARAMETERS - ushort HashKeySize; // From NDIS_RECEIVE_SCALE_PARAMETERS - unsigned char HashSecretKey[40]; // rss key - u32 HashInformation; - // Receive buffer queues - spinlock_t RcvQLock; /* Receive Queue Lock */ - struct LIST_ENTRY FreeRcvBuffers; // Free SXG_DATA_BUFFER queue - struct LIST_ENTRY FreeRcvBlocks; // Free SXG_RCV_DESCRIPTOR_BLOCK Q - struct LIST_ENTRY AllRcvBlocks; // All SXG_RCV_BLOCKs - ushort FreeRcvBufferCount; // Number of free rcv data buffers - ushort FreeRcvBlockCount; // # of free rcv descriptor blocks - ushort AllRcvBlockCount; // Number of total receive blocks - ushort ReceiveBufferSize; // SXG_RCV_DATA/JUMBO_BUFFER_SIZE only - u32 AllocationsPending; // Receive allocation pending - u32 RcvBuffersOnCard; // SXG_DATA_BUFFERS owned by card - // SGL buffers + struct sxg_ring_info RcvRingZeroInfo; /* Receive ring 0 info */ + + u32 * Isr; /* Interrupt status register */ + dma_addr_t PIsr; /* ISR - physical address */ + u32 IsrCopy[SXG_MAX_RSS]; /* Copy of ISR */ + ushort InterruptsEnabled; /* Bitmask of enabled vectors */ + unsigned char *IndirectionTable; /* RSS indirection table */ + dma_addr_t PIndirectionTable; /* Physical address */ + ushort RssTableSize; /* From NDIS_RECEIVE_SCALE_PARAMETERS */ + ushort HashKeySize; /* From NDIS_RECEIVE_SCALE_PARAMETERS */ + unsigned char HashSecretKey[40]; /* rss key */ + u32 HashInformation; + /* Receive buffer queues */ + spinlock_t RcvQLock; /* Receive Queue Lock */ + struct list_entry FreeRcvBuffers; /* Free SXG_DATA_BUFFER queue */ + struct list_entry FreeRcvBlocks; /* Free SXG_RCV_DESCRIPTOR_BLOCK Q */ + struct list_entry AllRcvBlocks; /* All SXG_RCV_BLOCKs */ + ushort FreeRcvBufferCount; /* Number of free rcv data buffers */ + ushort FreeRcvBlockCount; /* # of free rcv descriptor blocks */ + ushort AllRcvBlockCount; /* Number of total receive blocks */ + ushort ReceiveBufferSize; /* SXG_RCV_DATA/JUMBO_BUFFER_SIZE only */ + /* Converted this to a atomic variable + u32 AllocationsPending; */ + atomic_t pending_allocations; + u32 AllocationsPending; /* Receive allocation pending */ + u32 RcvBuffersOnCard; /* SXG_DATA_BUFFERS owned by card */ + /* SGL buffers */ spinlock_t SglQLock; /* SGL Queue Lock */ - struct LIST_ENTRY FreeSglBuffers; // Free SXG_SCATTER_GATHER - struct LIST_ENTRY AllSglBuffers; // All SXG_SCATTER_GATHER - ushort FreeSglBufferCount; // Number of free SGL buffers - ushort AllSglBufferCount; // Number of total SGL buffers - u32 CurrentTime; // Tick count - u32 FastpathConnections;// # of fastpath connections - // Various single-bit flags: - u32 BasicAllocations:1; // Locks and listheads - u32 IntRegistered:1; // Interrupt registered - u32 PingOutstanding:1; // Ping outstanding to card - u32 Dead:1; // Card dead - u32 DumpDriver:1; // OID_SLIC_DRIVER_DUMP request - u32 DumpCard:1; // OID_SLIC_CARD_DUMP request - u32 DumpCmdRunning:1; // Dump command in progress - u32 DebugRunning:1; // AGDB debug in progress - u32 JumboEnabled:1; // Jumbo frames enabled - u32 MsiEnabled:1; // MSI interrupt enabled - u32 RssEnabled:1; // RSS Enabled - u32 FailOnBadEeprom:1; // Fail on Bad Eeprom - u32 DiagStart:1; // Init adapter for diagnostic start - // Stats - u32 PendingRcvCount; // Outstanding rcv indications - u32 PendingXmtCount; // Outstanding send requests - struct SXG_STATS Stats; // Statistics - u32 ReassBufs; // Number of reassembly buffers - // Card Crash Info - ushort CrashLocation; // Microcode crash location - unsigned char CrashCpu; // Sahara CPU ID - // Diagnostics - // PDIAG_CMD DiagCmds; // List of free diagnostic commands - // PDIAG_BUFFER DiagBuffers; // List of free diagnostic buffers - // PDIAG_REQ DiagReqQ; // List of outstanding (asynchronous) diag requests - // u32 DiagCmdTimeout; // Time out for diag cmds (seconds) XXXTODO - replace with SXG_PARAM var? - // unsigned char DiagDmaDesc[DMA_CPU_CTXS]; // Free DMA descriptors bit field (32 CPU ctx * 8 DMA ctx) - - ///////////////////////////////////////////////////////////////////// - // Put preprocessor-conditional fields at the end so we don't - // have to recompile sxgdbg everytime we reconfigure the driver - ///////////////////////////////////////////////////////////////////// - void * PendingSetRss; // Pending RSS parameter change - u32 IPv4HdrSize; // Shared 5.2/6.0 encap param - unsigned char * InterruptInfo; // Allocated by us during AddDevice + struct list_entry FreeSglBuffers; /* Free struct sxg_scatter_gather */ + struct list_entry AllSglBuffers; /* All struct sxg_scatter_gather */ + ushort FreeSglBufferCount; /* Number of free SGL buffers */ + ushort AllSglBufferCount; /* Number of total SGL buffers */ + u32 CurrentTime; /* Tick count */ + u32 FastpathConnections;/* # of fastpath connections */ + /* Various single-bit flags: */ + u32 BasicAllocations:1; /* Locks and listheads */ + u32 IntRegistered:1; /* Interrupt registered */ + u32 PingOutstanding:1; /* Ping outstanding to card */ + u32 Dead:1; /* Card dead */ + u32 DumpDriver:1; /* OID_SLIC_DRIVER_DUMP request */ + u32 DumpCard:1; /* OID_SLIC_CARD_DUMP request */ + u32 DumpCmdRunning:1; /* Dump command in progress */ + u32 DebugRunning:1; /* AGDB debug in progress */ + u32 JumboEnabled:1; /* Jumbo frames enabled */ + u32 msi_enabled:1; /* MSI interrupt enabled */ + u32 RssEnabled:1; /* RSS Enabled */ + u32 FailOnBadEeprom:1; /* Fail on Bad Eeprom */ + u32 DiagStart:1; /* Init adapter for diagnostic start */ + u32 XmtFcEnabled:1; + u32 RcvFcEnabled:1; + /* Stats */ + u32 PendingRcvCount; /* Outstanding rcv indications */ + u32 PendingXmtCount; /* Outstanding send requests */ + struct sxg_stats Stats; /* Statistics */ + u32 ReassBufs; /* Number of reassembly buffers */ + /* Card Crash Info */ + ushort CrashLocation; /* Microcode crash location */ + unsigned char CrashCpu; /* Sahara CPU ID */ + /* Diagnostics */ + /* PDIAG_CMD DiagCmds; */ /* List of free diagnostic commands */ + /* PDIAG_BUFFER DiagBuffers; */ /* List of free diagnostic buffers */ + /* PDIAG_REQ DiagReqQ; */ /* List of outstanding (asynchronous) diag requests */ + /* u32 DiagCmdTimeout; */ /* Time out for diag cmds (seconds) XXXTODO - replace with SXG_PARAM var? */ + /* unsigned char DiagDmaDesc[DMA_CPU_CTXS]; */ /* Free DMA descriptors bit field (32 CPU ctx * 8 DMA ctx) */ + /* + * Put preprocessor-conditional fields at the end so we don't + * have to recompile sxgdbg everytime we reconfigure the driver + */ #if defined(CONFIG_X86) - u32 AddrUpper; // Upper 32 bits of 64-bit register + u32 AddrUpper; /* Upper 32 bits of 64-bit register */ #endif - //#if SXG_FAILURE_DUMP - // NDIS_EVENT DumpThreadEvent; // syncronize dump thread - // BOOLEAN DumpThreadRunning; // termination flag - // PSXG_DUMP_CMD DumpBuffer; // 68k - Cmd and Buffer - // dma_addr_t PDumpBuffer; // Physical address - //#endif // SXG_FAILURE_DUMP - + unsigned short max_aggregation; + unsigned short min_aggregation; + /*#if SXG_FAILURE_DUMP */ + /* NDIS_EVENT DumpThreadEvent; */ /* syncronize dump thread */ + /* BOOLEAN DumpThreadRunning; */ /* termination flag */ + /* PSXG_DUMP_CMD DumpBuffer; */ /* 68k - Cmd and Buffer */ + /* dma_addr_t PDumpBuffer; */ /* Physical address */ + /*#endif */ /* SXG_FAILURE_DUMP */ + /*MSI-X related data elements*/ + u32 nr_msix_entries; + struct msix_entry *msi_entries; + struct timer_list watchdog_timer; + struct work_struct update_link_status; + u32 link_status_changed; }; #if SLIC_DUMP_ENABLED @@ -710,12 +725,10 @@ struct adapter_t { #define SLIC_DUMP_IN_PROGRESS 2 #define SLIC_DUMP_DONE 3 -/**************************************************************************** - * +/* * Microcode crash information structure. This * structure is written out to the card's SRAM when the microcode panic's. - * - ****************************************************************************/ + */ struct slic_crash_info { ushort cpu_id; ushort crash_pc; @@ -738,21 +751,25 @@ struct slic_crash_info { (largestat) += ((newstat) - (oldstat)); \ } -#define ETHER_EQ_ADDR(_AddrA, _AddrB, _Result) \ -{ \ - _Result = TRUE; \ - if (*(u32 *)(_AddrA) != *(u32 *)(_AddrB)) \ - _Result = FALSE; \ - if (*(u16 *)(&((_AddrA)[4])) != *(u16 *)(&((_AddrB)[4]))) \ - _Result = FALSE; \ +#define ETHER_EQ_ADDR(_AddrA, _AddrB, _Result) \ +{ \ + _Result = TRUE; \ + if (*(u32 *)(_AddrA) != *(u32 *)(_AddrB)) \ + _Result = FALSE; \ + if (*(u16 *)(&((_AddrA)[4])) != *(u16 *)(&((_AddrB)[4]))) \ + _Result = FALSE; \ } #define ETHERMAXFRAME 1514 #define JUMBOMAXFRAME 9014 +#define SXG_JUMBO_MTU 9000 +#define SXG_DEFAULT_MTU 1500 + #if defined(CONFIG_X86_64) || defined(CONFIG_IA64) #define SXG_GET_ADDR_LOW(_addr) (u32)((u64)(_addr) & 0x00000000FFFFFFFF) -#define SXG_GET_ADDR_HIGH(_addr) (u32)(((u64)(_addr) >> 32) & 0x00000000FFFFFFFF) +#define SXG_GET_ADDR_HIGH(_addr) \ + (u32)(((u64)(_addr) >> 32) & 0x00000000FFFFFFFF) #else #define SXG_GET_ADDR_LOW(_addr) (u32)_addr #define SXG_GET_ADDR_HIGH(_addr) (u32)0 @@ -761,8 +778,10 @@ struct slic_crash_info { #define FLUSH TRUE #define DONT_FLUSH FALSE -#define SIOCSLICDUMPCARD SIOCDEVPRIVATE+9 -#define SIOCSLICSETINTAGG SIOCDEVPRIVATE+10 -#define SIOCSLICTRACEDUMP SIOCDEVPRIVATE+11 +#define SIOCSLICDUMPCARD (SIOCDEVPRIVATE+9) +#define SIOCSLICSETINTAGG (SIOCDEVPRIVATE+10) +#define SIOCSLICTRACEDUMP (SIOCDEVPRIVATE+11) +extern struct ethtool_ops sxg_nic_ethtool_ops; +#define SXG_COMPLETE_SLOW_SEND_LIMIT 128 #endif /* __SXG_DRIVER_H__ */ diff --git a/drivers/staging/sxg/sxg_ethtool.c b/drivers/staging/sxg/sxg_ethtool.c new file mode 100644 index 000000000000..97f765d1250f --- /dev/null +++ b/drivers/staging/sxg/sxg_ethtool.c @@ -0,0 +1,328 @@ +/************************************************************************** + * + * Copyright (C) 2000-2008 Alacritech, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of Alacritech, Inc. + * + **************************************************************************/ + +/* + * FILENAME: sxg_ethtool.c + * + * The ethtool support for SXG driver for Alacritech's 10Gbe products. + * + * NOTE: This is the standard, non-accelerated version of Alacritech's + * IS-NIC driver. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sxg_os.h" +#include "sxghw.h" +#include "sxghif.h" +#include "sxg.h" + +struct sxg_nic_stats { + char stat_string[ETH_GSTRING_LEN]; + int sizeof_stat; + int stat_offset; +}; + +#define SXG_NIC_STATS(m) sizeof(((struct adapter_t *)0)->m), \ + offsetof(struct adapter_t, m) + +#define USER_VIEWABLE_EEPROM_SIZE 28 + +static struct sxg_nic_stats sxg_nic_gstrings_stats[] = { + {"xmit_ring_0_full", SXG_NIC_STATS(Stats.XmtZeroFull)}, + + /* May be will need in future */ +/* {"dumb_xmit_broadcast_packets", SXG_NIC_STATS(Stats.DumbXmtBcastPkts)}, + {"dumb_xmit_broadcast_bytes", SXG_NIC_STATS(Stats.DumbXmtBcastBytes)}, + {"dumb_xmit_unicast_packets", SXG_NIC_STATS(Stats.DumbXmtUcastPkts)}, + {"dumb_xmit_unicast_bytes", SXG_NIC_STATS(Stats.DumbXmtUcastBytes)}, +*/ + {"xmit_queue_length", SXG_NIC_STATS(Stats.XmtQLen)}, + {"memory_allocation_failure", SXG_NIC_STATS(Stats.NoMem)}, + {"Interrupts", SXG_NIC_STATS(Stats.NumInts)}, + {"false_interrupts", SXG_NIC_STATS(Stats.FalseInts)}, + {"processed_data_queue_full", SXG_NIC_STATS(Stats.PdqFull)}, + {"event_ring_full", SXG_NIC_STATS(Stats.EventRingFull)}, + {"transport_checksum_error", SXG_NIC_STATS(Stats.TransportCsum)}, + {"transport_underflow_error", SXG_NIC_STATS(Stats.TransportUflow)}, + {"transport_header_length_error", SXG_NIC_STATS(Stats.TransportHdrLen)}, + {"network_checksum_error", SXG_NIC_STATS(Stats.NetworkCsum)}, + {"network_underflow_error", SXG_NIC_STATS(Stats.NetworkUflow)}, + {"network_header_length_error", SXG_NIC_STATS(Stats.NetworkHdrLen)}, + {"receive_parity_error", SXG_NIC_STATS(Stats.Parity)}, + {"link_parity_error", SXG_NIC_STATS(Stats.LinkParity)}, + {"link/data early_error", SXG_NIC_STATS(Stats.LinkEarly)}, + {"buffer_overflow_error", SXG_NIC_STATS(Stats.LinkBufOflow)}, + {"link_code_error", SXG_NIC_STATS(Stats.LinkCode)}, + {"dribble nibble", SXG_NIC_STATS(Stats.LinkDribble)}, + {"CRC_error", SXG_NIC_STATS(Stats.LinkCrc)}, + {"link_overflow_error", SXG_NIC_STATS(Stats.LinkOflow)}, + {"link_underflow_error", SXG_NIC_STATS(Stats.LinkUflow)}, + + /* May be need in future */ +/* {"dumb_rcv_broadcast_packets", SXG_NIC_STATS(Stats.DumbRcvBcastPkts)}, + {"dumb_rcv_broadcast_bytes", SXG_NIC_STATS(Stats.DumbRcvBcastBytes)}, +*/ {"dumb_rcv_multicast_packets", SXG_NIC_STATS(Stats.DumbRcvMcastPkts)}, + {"dumb_rcv_multicast_bytes", SXG_NIC_STATS(Stats.DumbRcvMcastBytes)}, +/* {"dumb_rcv_unicast_packets", SXG_NIC_STATS(Stats.DumbRcvUcastPkts)}, + {"dumb_rcv_unicast_bytes", SXG_NIC_STATS(Stats.DumbRcvUcastBytes)}, +*/ + {"no_sgl_buffer", SXG_NIC_STATS(Stats.NoSglBuf)}, +}; + +#define SXG_NIC_STATS_LEN ARRAY_SIZE(sxg_nic_gstrings_stats) + +static inline void sxg_reg32_write(void __iomem *reg, u32 value, bool flush) +{ + writel(value, reg); + if (flush) + mb(); +} + +static inline void sxg_reg64_write(struct adapter_t *adapter, void __iomem *reg, + u64 value, u32 cpu) +{ + u32 value_high = (u32) (value >> 32); + u32 value_low = (u32) (value & 0x00000000FFFFFFFF); + unsigned long flags; + + spin_lock_irqsave(&adapter->Bit64RegLock, flags); + writel(value_high, (void __iomem *)(&adapter->UcodeRegs[cpu].Upper)); + writel(value_low, reg); + spin_unlock_irqrestore(&adapter->Bit64RegLock, flags); +} + +static void +sxg_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) +{ + struct adapter_t *adapter = netdev_priv(dev); + strncpy(drvinfo->driver, sxg_driver_name, 32); + strncpy(drvinfo->version, SXG_DRV_VERSION, 32); +// strncpy(drvinfo->fw_version, SAHARA_UCODE_VERS_STRING, 32); + strncpy(drvinfo->bus_info, pci_name(adapter->pcidev), 32); + /* TODO : Read the major and minor number of firmware. Is this + * from the FLASH/EEPROM or download file ? + */ + /* LINSYS : Check if this is correct or if not find the right value + * Also check what is the right EEPROM length : EEPROM_SIZE_XFMR or EEPROM_SIZE_NO_XFMR + */ +} + +static int sxg_nic_set_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + /* No settings are applicable as we support only 10Gb/FIBRE_media */ + return -EOPNOTSUPP; +} + +static void +sxg_nic_get_strings(struct net_device *netdev, u32 stringset, u8 * data) +{ + int index; + + switch(stringset) { + case ETH_SS_TEST: + break; + case ETH_SS_STATS: + for (index = 0; index < SXG_NIC_STATS_LEN; index++) { + memcpy(data + index * ETH_GSTRING_LEN, + sxg_nic_gstrings_stats[index].stat_string, + ETH_GSTRING_LEN); + } + break; + } +} + +static void +sxg_nic_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 * data) +{ + struct adapter_t *adapter = netdev_priv(netdev); + int index; + for (index = 0; index < SXG_NIC_STATS_LEN; index++) { + char *p = (char *)adapter + + sxg_nic_gstrings_stats[index].stat_offset; + data[index] = (sxg_nic_gstrings_stats[index].sizeof_stat == + sizeof(u64)) ? *(u64 *) p : *(u32 *) p; + } +} + +static int sxg_nic_get_sset_count(struct net_device *netdev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return SXG_NIC_STATS_LEN; + default: + return -EOPNOTSUPP; + } +} + +static int sxg_nic_get_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct adapter_t *adapter = netdev_priv(netdev); + + ecmd->supported = SUPPORTED_10000baseT_Full; + ecmd->autoneg = AUTONEG_ENABLE; //VSS check This + ecmd->transceiver = XCVR_EXTERNAL; //VSS check This + + /* For Fibre Channel */ + ecmd->supported |= SUPPORTED_FIBRE; + ecmd->advertising = (ADVERTISED_10000baseT_Full | + ADVERTISED_FIBRE); + ecmd->port = PORT_FIBRE; + + + /* Link Speed */ + if(adapter->LinkState & SXG_LINK_UP) { + ecmd->speed = SPEED_10000; //adapter->LinkSpeed; + ecmd->duplex = DUPLEX_FULL; + } + return 0; +} + +static u32 sxg_nic_get_rx_csum(struct net_device *netdev) +{ + struct adapter_t *adapter = netdev_priv(netdev); + return ((adapter->flags & SXG_RCV_IP_CSUM_ENABLED) && + (adapter->flags & SXG_RCV_TCP_CSUM_ENABLED)); +} + +static int sxg_nic_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct adapter_t *adapter = netdev_priv(netdev); + if (data) + adapter->flags |= SXG_RCV_IP_CSUM_ENABLED; + else + adapter->flags &= ~SXG_RCV_IP_CSUM_ENABLED; + /* + * We dont need to write to the card to do checksums. + * It does it anyways. + */ + return 0; +} + +static int sxg_nic_get_regs_len(struct net_device *dev) +{ + return (SXG_HWREG_MEMSIZE + SXG_UCODEREG_MEMSIZE); +} + +static void sxg_nic_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + struct adapter_t *adapter = netdev_priv(netdev); + struct sxg_hw_regs *HwRegs = adapter->HwRegs; + struct sxg_ucode_regs *UcodeRegs = adapter->UcodeRegs; + u32 *buff = p; + + memset(p, 0, (sizeof(struct sxg_hw_regs)+sizeof(struct sxg_ucode_regs))); + memcpy(buff, HwRegs, sizeof(struct sxg_hw_regs)); + memcpy((buff+sizeof(struct sxg_hw_regs)), UcodeRegs, sizeof(struct sxg_ucode_regs)); +} + +static int sxg_nic_get_eeprom_len(struct net_device *netdev) +{ + return (USER_VIEWABLE_EEPROM_SIZE); +} + +static int sxg_nic_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct adapter_t *adapter = netdev_priv(netdev); + struct sw_cfg_data *data; + unsigned long i, status; + dma_addr_t p_addr; + + data = pci_alloc_consistent(adapter->pcidev, sizeof(struct sw_cfg_data), + &p_addr); + if(!data) { + /* + * We cant get even this much memory. Raise a hell + * Get out of here + */ + printk(KERN_ERR"%s : Could not allocate memory for reading \ + EEPROM\n", __FUNCTION__); + return -ENOMEM; + } + + WRITE_REG(adapter->UcodeRegs[0].ConfigStat, SXG_CFG_TIMEOUT, TRUE); + WRITE_REG64(adapter, adapter->UcodeRegs[0].Config, p_addr, 0); + for(i=0; i<1000; i++) { + READ_REG(adapter->UcodeRegs[0].ConfigStat, status); + if (status != SXG_CFG_TIMEOUT) + break; + mdelay(1); /* Do we really need this */ + } + + memset(bytes, 0, eeprom->len); + memcpy(bytes, data->MacAddr[0].MacAddr, sizeof(struct sxg_config_mac)); + memcpy(bytes+6, data->AtkFru.PartNum, 6); + memcpy(bytes+12, data->AtkFru.Revision, 2); + memcpy(bytes+14, data->AtkFru.Serial, 14); + + return 0; +} + +struct ethtool_ops sxg_nic_ethtool_ops = { + .get_settings = sxg_nic_get_settings, + .set_settings = sxg_nic_set_settings, + .get_drvinfo = sxg_nic_get_drvinfo, + .get_regs_len = sxg_nic_get_regs_len, + .get_regs = sxg_nic_get_regs, + .get_link = ethtool_op_get_link, +// .get_wol = sxg_nic_get_wol, + .get_eeprom_len = sxg_nic_get_eeprom_len, + .get_eeprom = sxg_nic_get_eeprom, +// .get_pauseparam = sxg_nic_get_pauseparam, +// .set_pauseparam = sxg_nic_set_pauseparam, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +// .get_tso = sxg_nic_get_tso, +// .set_tso = sxg_nic_set_tso, +// .self_test = sxg_nic_diag_test, + .get_strings = sxg_nic_get_strings, + .get_ethtool_stats = sxg_nic_get_ethtool_stats, + .get_sset_count = sxg_nic_get_sset_count, + .get_rx_csum = sxg_nic_get_rx_csum, + .set_rx_csum = sxg_nic_set_rx_csum, +// .get_coalesce = sxg_nic_get_intr_coalesce, +// .set_coalesce = sxg_nic_set_intr_coalesce, +}; diff --git a/drivers/staging/sxg/sxg_os.h b/drivers/staging/sxg/sxg_os.h index 6d3f23fb5e1b..68e1a04b61f3 100644 --- a/drivers/staging/sxg/sxg_os.h +++ b/drivers/staging/sxg/sxg_os.h @@ -44,34 +44,34 @@ #define FALSE (0) #define TRUE (1) -struct LIST_ENTRY { - struct LIST_ENTRY *nle_flink; - struct LIST_ENTRY *nle_blink; +struct list_entry { + struct list_entry *nle_flink; + struct list_entry *nle_blink; }; -#define InitializeListHead(l) \ +#define InitializeListHead(l) \ (l)->nle_flink = (l)->nle_blink = (l) -#define IsListEmpty(h) \ +#define IsListEmpty(h) \ ((h)->nle_flink == (h)) -#define RemoveEntryList(e) \ - do { \ - list_entry *b; \ - list_entry *f; \ - \ - f = (e)->nle_flink; \ - b = (e)->nle_blink; \ - b->nle_flink = f; \ - f->nle_blink = b; \ +#define RemoveEntryList(e) \ + do { \ + list_entry *b; \ + list_entry *f; \ + \ + f = (e)->nle_flink; \ + b = (e)->nle_blink; \ + b->nle_flink = f; \ + f->nle_blink = b; \ } while (0) /* These two have to be inlined since they return things. */ -static __inline struct LIST_ENTRY *RemoveHeadList(struct LIST_ENTRY *l) +static inline struct list_entry *RemoveHeadList(struct list_entry *l) { - struct LIST_ENTRY *f; - struct LIST_ENTRY *e; + struct list_entry *f; + struct list_entry *e; e = l->nle_flink; f = e->nle_flink; @@ -81,10 +81,10 @@ static __inline struct LIST_ENTRY *RemoveHeadList(struct LIST_ENTRY *l) return (e); } -static __inline struct LIST_ENTRY *RemoveTailList(struct LIST_ENTRY *l) +static inline struct list_entry *RemoveTailList(struct list_entry *l) { - struct LIST_ENTRY *b; - struct LIST_ENTRY *e; + struct list_entry *b; + struct list_entry *e; e = l->nle_blink; b = e->nle_blink; @@ -94,54 +94,56 @@ static __inline struct LIST_ENTRY *RemoveTailList(struct LIST_ENTRY *l) return (e); } -#define InsertTailList(l, e) \ - do { \ - struct LIST_ENTRY *b; \ - \ - b = (l)->nle_blink; \ - (e)->nle_flink = (l); \ - (e)->nle_blink = b; \ - b->nle_flink = (e); \ - (l)->nle_blink = (e); \ +#define InsertTailList(l, e) \ + do { \ + struct list_entry *b; \ + \ + b = (l)->nle_blink; \ + (e)->nle_flink = (l); \ + (e)->nle_blink = b; \ + b->nle_flink = (e); \ + (l)->nle_blink = (e); \ } while (0) -#define InsertHeadList(l, e) \ - do { \ - struct LIST_ENTRY *f; \ - \ - f = (l)->nle_flink; \ - (e)->nle_flink = f; \ - (e)->nle_blink = l; \ - f->nle_blink = (e); \ - (l)->nle_flink = (e); \ +#define InsertHeadList(l, e) \ + do { \ + struct list_entry *f; \ + \ + f = (l)->nle_flink; \ + (e)->nle_flink = f; \ + (e)->nle_blink = l; \ + f->nle_blink = (e); \ + (l)->nle_flink = (e); \ } while (0) #define ATK_DEBUG 1 #if ATK_DEBUG -#define SLIC_TIMESTAMP(value) { \ - struct timeval timev; \ - do_gettimeofday(&timev); \ - value = timev.tv_sec*1000000 + timev.tv_usec; \ +#define SLIC_TIMESTAMP(value) { \ + struct timeval timev; \ + do_gettimeofday(&timev); \ + value = timev.tv_sec*1000000 + timev.tv_usec; \ } #else #define SLIC_TIMESTAMP(value) #endif -/****************** SXG DEFINES *****************************************/ +/* SXG DEFINES */ #ifdef ATKDBG -#define SXG_TIMESTAMP(value) { \ - struct timeval timev; \ - do_gettimeofday(&timev); \ - value = timev.tv_sec*1000000 + timev.tv_usec; \ +#define SXG_TIMESTAMP(value) { \ + struct timeval timev; \ + do_gettimeofday(&timev); \ + value = timev.tv_sec*1000000 + timev.tv_usec; \ } #else #define SXG_TIMESTAMP(value) #endif -#define WRITE_REG(reg,value,flush) sxg_reg32_write((®), (value), (flush)) -#define WRITE_REG64(a,reg,value,cpu) sxg_reg64_write((a),(®),(value),(cpu)) +#define WRITE_REG(reg,value,flush) \ + sxg_reg32_write((®), (value), (flush)) +#define WRITE_REG64(a,reg,value,cpu) \ + sxg_reg64_write((a),(®),(value),(cpu)) #define READ_REG(reg,value) (value) = readl((void __iomem *)(®)) #endif /* _SLIC_OS_SPECIFIC_H_ */ diff --git a/drivers/staging/sxg/sxgdbg.h b/drivers/staging/sxg/sxgdbg.h index bb58ddf39f30..e613a972b3d0 100644 --- a/drivers/staging/sxg/sxgdbg.h +++ b/drivers/staging/sxg/sxgdbg.h @@ -44,22 +44,23 @@ #define _SXG_DEBUG_H_ #define ATKDBG 1 -#define ATK_TRACE_ENABLED 1 +#define ATK_TRACE_ENABLED 0 -#define DBG_ERROR(n, args...) printk(KERN_EMERG n, ##args) +#define DBG_ERROR(n, args...) printk(KERN_WARNING n, ##args) #ifdef ASSERT #undef ASSERT #endif +#define SXG_ASSERT_ENABLED #ifdef SXG_ASSERT_ENABLED #ifndef ASSERT -#define ASSERT(a) \ - { \ - if (!(a)) { \ - DBG_ERROR("ASSERT() Failure: file %s, function %s line %d\n",\ - __FILE__, __func__, __LINE__); \ - } \ +#define ASSERT(a) \ + { \ + if (!(a)) { \ + DBG_ERROR("ASSERT() Failure: file %s, function %s line %d\n", \ + __FILE__, __func__, __LINE__); \ + } \ } #endif #else @@ -78,7 +79,7 @@ extern ulong ATKTimerDiv; /* - * trace_entry_t - + * trace_entry - * * This structure defines an entry in the trace buffer. The * first few fields mean the same from entry to entry, while @@ -86,34 +87,34 @@ extern ulong ATKTimerDiv; * needs of the trace entry. Typically they are function call * parameters. */ -struct trace_entry_t { - char name[8]; /* 8 character name - like 's'i'm'b'a'r'c'v' */ - u32 time; /* Current clock tic */ - unsigned char cpu; /* Current CPU */ - unsigned char irql; /* Current IRQL */ - unsigned char driver; /* The driver which added the trace call */ - unsigned char pad2; /* pad to 4 byte boundary - will probably get used */ - u32 arg1; /* Caller arg1 */ - u32 arg2; /* Caller arg2 */ - u32 arg3; /* Caller arg3 */ - u32 arg4; /* Caller arg4 */ +struct trace_entry { + char name[8];/* 8 character name - like 's'i'm'b'a'r'c'v' */ + u32 time; /* Current clock tic */ + unsigned char cpu; /* Current CPU */ + unsigned char irql; /* Current IRQL */ + unsigned char driver;/* The driver which added the trace call */ + /* pad to 4 byte boundary - will probably get used */ + unsigned char pad2; + u32 arg1; /* Caller arg1 */ + u32 arg2; /* Caller arg2 */ + u32 arg3; /* Caller arg3 */ + u32 arg4; /* Caller arg4 */ }; -/* - * Driver types for driver field in trace_entry_t - */ +/* Driver types for driver field in struct trace_entry */ #define TRACE_SXG 1 #define TRACE_VPCI 2 #define TRACE_SLIC 3 #define TRACE_ENTRIES 1024 -struct sxg_trace_buffer_t { - unsigned int size; /* aid for windbg extension */ - unsigned int in; /* Where to add */ - unsigned int level; /* Current Trace level */ - spinlock_t lock; /* For MP tracing */ - struct trace_entry_t entries[TRACE_ENTRIES];/* The circular buffer */ +struct sxg_trace_buffer { + /* aid for windbg extension */ + unsigned int size; + unsigned int in; /* Where to add */ + unsigned int level; /* Current Trace level */ + spinlock_t lock; /* For MP tracing */ + struct trace_entry entries[TRACE_ENTRIES];/* The circular buffer */ }; /* @@ -128,15 +129,11 @@ struct sxg_trace_buffer_t { #define TRACE_NOISY 10 /* Everything in the world */ -/********************************************************************** - * - * The macros themselves - - * - *********************************************************************/ +/* The macros themselves */ #if ATK_TRACE_ENABLED #define SXG_TRACE_INIT(buffer, tlevel) \ { \ - memset((buffer), 0, sizeof(struct sxg_trace_buffer_t)); \ + memset((buffer), 0, sizeof(struct sxg_trace_buffer)); \ (buffer)->level = (tlevel); \ (buffer)->size = TRACE_ENTRIES; \ spin_lock_init(&(buffer)->lock); \ @@ -145,40 +142,38 @@ struct sxg_trace_buffer_t { #define SXG_TRACE_INIT(buffer, tlevel) #endif -/* - * The trace macro. This is active only if ATK_TRACE_ENABLED is set. - */ +/*The trace macro. This is active only if ATK_TRACE_ENABLED is set. */ #if ATK_TRACE_ENABLED #define SXG_TRACE(tdriver, buffer, tlevel, tname, a1, a2, a3, a4) { \ - if ((buffer) && ((buffer)->level >= (tlevel))) { \ - unsigned int trace_irql = 0; /* ?????? FIX THIS */ \ - unsigned int trace_len; \ - struct trace_entry_t *trace_entry; \ - struct timeval timev; \ - \ - spin_lock(&(buffer)->lock); \ - trace_entry = &(buffer)->entries[(buffer)->in]; \ - do_gettimeofday(&timev); \ - \ - memset(trace_entry->name, 0, 8); \ - trace_len = strlen(tname); \ - trace_len = trace_len > 8 ? 8 : trace_len; \ - memcpy(trace_entry->name, (tname), trace_len); \ - trace_entry->time = timev.tv_usec; \ - trace_entry->cpu = (unsigned char)(smp_processor_id() & 0xFF); \ - trace_entry->driver = (tdriver); \ - trace_entry->irql = trace_irql; \ - trace_entry->arg1 = (ulong)(a1); \ - trace_entry->arg2 = (ulong)(a2); \ - trace_entry->arg3 = (ulong)(a3); \ - trace_entry->arg4 = (ulong)(a4); \ - \ - (buffer)->in++; \ - if ((buffer)->in == TRACE_ENTRIES) \ - (buffer)->in = 0; \ - \ - spin_unlock(&(buffer)->lock); \ - } \ + if ((buffer) && ((buffer)->level >= (tlevel))) { \ + unsigned int trace_irql = 0;/* ?????? FIX THIS */\ + unsigned int trace_len; \ + struct trace_entry *trace_entry; \ + struct timeval timev; \ + if(spin_trylock(&(buffer)->lock)) { \ + trace_entry = &(buffer)->entries[(buffer)->in]; \ + do_gettimeofday(&timev); \ + \ + memset(trace_entry->name, 0, 8); \ + trace_len = strlen(tname); \ + trace_len = trace_len > 8 ? 8 : trace_len; \ + memcpy(trace_entry->name, (tname), trace_len); \ + trace_entry->time = timev.tv_usec; \ + trace_entry->cpu = (unsigned char)(smp_processor_id() & 0xFF);\ + trace_entry->driver = (tdriver); \ + trace_entry->irql = trace_irql; \ + trace_entry->arg1 = (ulong)(a1); \ + trace_entry->arg2 = (ulong)(a2); \ + trace_entry->arg3 = (ulong)(a3); \ + trace_entry->arg4 = (ulong)(a4); \ + \ + (buffer)->in++; \ + if ((buffer)->in == TRACE_ENTRIES) \ + (buffer)->in = 0; \ + \ + spin_unlock(&(buffer)->lock); \ + } \ + } \ } #else #define SXG_TRACE(tdriver, buffer, tlevel, tname, a1, a2, a3, a4) diff --git a/drivers/staging/sxg/sxghif.h b/drivers/staging/sxg/sxghif.h index a4e94685c544..e190d6add29c 100644 --- a/drivers/staging/sxg/sxghif.h +++ b/drivers/staging/sxg/sxghif.h @@ -1,4 +1,4 @@ -/* +/******************************************************************* * Copyright © 1997-2007 Alacritech, Inc. All rights reserved * * $Id: sxghif.h,v 1.5 2008/07/24 19:18:22 chris Exp $ @@ -7,129 +7,134 @@ * * This file contains structures and definitions for the * Alacritech Sahara host interface - */ + ******************************************************************/ -/******************************************************************************* - * UCODE Registers - *******************************************************************************/ -struct SXG_UCODE_REGS { - // Address 0 - 0x3F = Command codes 0-15 for TCB 0. Excode 0 - u32 Icr; // Code = 0 (extended), ExCode = 0 - Int control - u32 RsvdReg1; // Code = 1 - TOE -NA - u32 RsvdReg2; // Code = 2 - TOE -NA - u32 RsvdReg3; // Code = 3 - TOE -NA - u32 RsvdReg4; // Code = 4 - TOE -NA - u32 RsvdReg5; // Code = 5 - TOE -NA - u32 CardUp; // Code = 6 - Microcode initialized when 1 - u32 RsvdReg7; // Code = 7 - TOE -NA - u32 CodeNotUsed[8]; // Codes 8-15 not used. ExCode = 0 - // This brings us to ExCode 1 at address 0x40 = Interrupt status pointer - u32 Isp; // Code = 0 (extended), ExCode = 1 - u32 PadEx1[15]; // Codes 1-15 not used with extended codes - // ExCode 2 = Interrupt Status Register - u32 Isr; // Code = 0 (extended), ExCode = 2 +#define DBG 1 + +/* UCODE Registers */ +struct sxg_ucode_regs { + /* Address 0 - 0x3F = Command codes 0-15 for TCB 0. Excode 0 */ + u32 Icr; /* Code = 0 (extended), ExCode = 0 - Int control */ + u32 RsvdReg1; /* Code = 1 - TOE -NA */ + u32 RsvdReg2; /* Code = 2 - TOE -NA */ + u32 RsvdReg3; /* Code = 3 - TOE -NA */ + u32 RsvdReg4; /* Code = 4 - TOE -NA */ + u32 RsvdReg5; /* Code = 5 - TOE -NA */ + u32 CardUp; /* Code = 6 - Microcode initialized when 1 */ + u32 RsvdReg7; /* Code = 7 - TOE -NA */ + u32 ConfigStat; /* Code = 8 - Configuration data load status */ + u32 RsvdReg9; /* Code = 9 - TOE -NA */ + u32 CodeNotUsed[6]; /* Codes 10-15 not used. ExCode = 0 */ + /* This brings us to ExCode 1 at address 0x40 = Interrupt status pointer */ + u32 Isp; /* Code = 0 (extended), ExCode = 1 */ + u32 PadEx1[15]; /* Codes 1-15 not used with extended codes */ + /* ExCode 2 = Interrupt Status Register */ + u32 Isr; /* Code = 0 (extended), ExCode = 2 */ u32 PadEx2[15]; - // ExCode 3 = Event base register. Location of event rings - u32 EventBase; // Code = 0 (extended), ExCode = 3 + /* ExCode 3 = Event base register. Location of event rings */ + u32 EventBase; /* Code = 0 (extended), ExCode = 3 */ u32 PadEx3[15]; - // ExCode 4 = Event ring size - u32 EventSize; // Code = 0 (extended), ExCode = 4 + /* ExCode 4 = Event ring size */ + u32 EventSize; /* Code = 0 (extended), ExCode = 4 */ u32 PadEx4[15]; - // ExCode 5 = TCB Buffers base address - u32 TcbBase; // Code = 0 (extended), ExCode = 5 + /* ExCode 5 = TCB Buffers base address */ + u32 TcbBase; /* Code = 0 (extended), ExCode = 5 */ u32 PadEx5[15]; - // ExCode 6 = TCB Composite Buffers base address - u32 TcbCompBase; // Code = 0 (extended), ExCode = 6 + /* ExCode 6 = TCB Composite Buffers base address */ + u32 TcbCompBase; /* Code = 0 (extended), ExCode = 6 */ u32 PadEx6[15]; - // ExCode 7 = Transmit ring base address - u32 XmtBase; // Code = 0 (extended), ExCode = 7 + /* ExCode 7 = Transmit ring base address */ + u32 XmtBase; /* Code = 0 (extended), ExCode = 7 */ u32 PadEx7[15]; - // ExCode 8 = Transmit ring size - u32 XmtSize; // Code = 0 (extended), ExCode = 8 + /* ExCode 8 = Transmit ring size */ + u32 XmtSize; /* Code = 0 (extended), ExCode = 8 */ u32 PadEx8[15]; - // ExCode 9 = Receive ring base address - u32 RcvBase; // Code = 0 (extended), ExCode = 9 + /* ExCode 9 = Receive ring base address */ + u32 RcvBase; /* Code = 0 (extended), ExCode = 9 */ u32 PadEx9[15]; - // ExCode 10 = Receive ring size - u32 RcvSize; // Code = 0 (extended), ExCode = 10 + /* ExCode 10 = Receive ring size */ + u32 RcvSize; /* Code = 0 (extended), ExCode = 10 */ u32 PadEx10[15]; - // ExCode 11 = Read EEPROM Config - u32 Config; // Code = 0 (extended), ExCode = 11 + /* ExCode 11 = Read EEPROM/Flash Config */ + u32 Config; /* Code = 0 (extended), ExCode = 11 */ u32 PadEx11[15]; - // ExCode 12 = Multicast bits 31:0 - u32 McastLow; // Code = 0 (extended), ExCode = 12 + /* ExCode 12 = Multicast bits 31:0 */ + u32 McastLow; /* Code = 0 (extended), ExCode = 12 */ u32 PadEx12[15]; - // ExCode 13 = Multicast bits 63:32 - u32 McastHigh; // Code = 0 (extended), ExCode = 13 + /* ExCode 13 = Multicast bits 63:32 */ + u32 McastHigh; /* Code = 0 (extended), ExCode = 13 */ u32 PadEx13[15]; - // ExCode 14 = Ping - u32 Ping; // Code = 0 (extended), ExCode = 14 + /* ExCode 14 = Ping */ + u32 Ping; /* Code = 0 (extended), ExCode = 14 */ u32 PadEx14[15]; - // ExCode 15 = Link MTU - u32 LinkMtu; // Code = 0 (extended), ExCode = 15 + /* ExCode 15 = Link MTU */ + u32 LinkMtu; /* Code = 0 (extended), ExCode = 15 */ u32 PadEx15[15]; - // ExCode 16 = Download synchronization - u32 LoadSync; // Code = 0 (extended), ExCode = 16 + /* ExCode 16 = Download synchronization */ + u32 LoadSync; /* Code = 0 (extended), ExCode = 16 */ u32 PadEx16[15]; - // ExCode 17 = Upper DRAM address bits on 32-bit systems - u32 Upper; // Code = 0 (extended), ExCode = 17 + /* ExCode 17 = Upper DRAM address bits on 32-bit systems */ + u32 Upper; /* Code = 0 (extended), ExCode = 17 */ u32 PadEx17[15]; - // ExCode 18 = Slowpath Send Index Address - u32 SPSendIndex; // Code = 0 (extended), ExCode = 18 + /* ExCode 18 = Slowpath Send Index Address */ + u32 SPSendIndex; /* Code = 0 (extended), ExCode = 18 */ u32 PadEx18[15]; - u32 RsvdXF; // Code = 0 (extended), ExCode = 19 + /* ExCode 19 = Get ucode statistics */ + u32 GetUcodeStats; /* Code = 0 (extended), ExCode = 19 */ u32 PadEx19[15]; - // ExCode 20 = Aggregation - u32 Aggregation; // Code = 0 (extended), ExCode = 20 + /* ExCode 20 = Aggregation - See sxgmisc.c:SxgSetInterruptAggregation */ + u32 Aggregation; /* Code = 0 (extended), ExCode = 20 */ u32 PadEx20[15]; - // ExCode 21 = Receive MDL push timer - u32 PushTicks; // Code = 0 (extended), ExCode = 21 + /* ExCode 21 = Receive MDL push timer */ + u32 PushTicks; /* Code = 0 (extended), ExCode = 21 */ u32 PadEx21[15]; - // ExCode 22 = TOE NA - u32 AckFrequency; // Code = 0 (extended), ExCode = 22 + /* ExCode 22 = ACK Frequency */ + u32 AckFrequency; /* Code = 0 (extended), ExCode = 22 */ u32 PadEx22[15]; - // ExCode 23 = TOE NA + /* ExCode 23 = TOE NA */ u32 RsvdReg23; u32 PadEx23[15]; - // ExCode 24 = TOE NA + /* ExCode 24 = TOE NA */ u32 RsvdReg24; u32 PadEx24[15]; - // ExCode 25 = TOE NA - u32 RsvdReg25; // Code = 0 (extended), ExCode = 25 + /* ExCode 25 = TOE NA */ + u32 RsvdReg25; /* Code = 0 (extended), ExCode = 25 */ u32 PadEx25[15]; - // ExCode 26 = Receive checksum requirements - u32 ReceiveChecksum; // Code = 0 (extended), ExCode = 26 + /* ExCode 26 = Receive checksum requirements */ + u32 ReceiveChecksum; /* Code = 0 (extended), ExCode = 26 */ u32 PadEx26[15]; - // ExCode 27 = RSS Requirements - u32 Rss; // Code = 0 (extended), ExCode = 27 + /* ExCode 27 = RSS Requirements */ + u32 Rss; /* Code = 0 (extended), ExCode = 27 */ u32 PadEx27[15]; - // ExCode 28 = RSS Table - u32 RssTable; // Code = 0 (extended), ExCode = 28 + /* ExCode 28 = RSS Table */ + u32 RssTable; /* Code = 0 (extended), ExCode = 28 */ u32 PadEx28[15]; - // ExCode 29 = Event ring release entries - u32 EventRelease; // Code = 0 (extended), ExCode = 29 + /* ExCode 29 = Event ring release entries */ + u32 EventRelease; /* Code = 0 (extended), ExCode = 29 */ u32 PadEx29[15]; - // ExCode 30 = Number of receive bufferlist commands on ring 0 - u32 RcvCmd; // Code = 0 (extended), ExCode = 30 + /* ExCode 30 = Number of receive bufferlist commands on ring 0 */ + u32 RcvCmd; /* Code = 0 (extended), ExCode = 30 */ u32 PadEx30[15]; - // ExCode 31 = slowpath transmit command - Data[31:0] = 1 - u32 XmtCmd; // Code = 0 (extended), ExCode = 31 + /* ExCode 31 = slowpath transmit command - Data[31:0] = 1 */ + u32 XmtCmd; /* Code = 0 (extended), ExCode = 31 */ u32 PadEx31[15]; - // ExCode 32 = Dump command - u32 DumpCmd; // Code = 0 (extended), ExCode = 32 + /* ExCode 32 = Dump command */ + u32 DumpCmd; /* Code = 0 (extended), ExCode = 32 */ u32 PadEx32[15]; - // ExCode 33 = Debug command - u32 DebugCmd; // Code = 0 (extended), ExCode = 33 + /* ExCode 33 = Debug command */ + u32 DebugCmd; /* Code = 0 (extended), ExCode = 33 */ u32 PadEx33[15]; - // There are 128 possible extended commands - each of account for 16 - // words (including the non-relevent base command codes 1-15). - // Pad for the remainder of these here to bring us to the next CPU - // base. As extended codes are added, reduce the first array value in - // the following field - u32 PadToNextCpu[94][16]; // 94 = 128 - 34 (34 = Excodes 0 - 33) + /* + * There are 128 possible extended commands - each of account for 16 + * words (including the non-relevent base command codes 1-15). + * Pad for the remainder of these here to bring us to the next CPU + * base. As extended codes are added, reduce the first array value in + * the following field + */ + u32 PadToNextCpu[94][16]; /* 94 = 128 - 34 (34 = Excodes 0 - 33)*/ }; -// Interrupt control register (0) values +/* Interrupt control register (0) values */ #define SXG_ICR_DISABLE 0x00000000 #define SXG_ICR_ENABLE 0x00000001 #define SXG_ICR_MASK 0x00000002 @@ -139,47 +144,65 @@ struct SXG_UCODE_REGS { ((((_MessageId) << SXG_ICR_MSGID_SHIFT) & \ SXG_ICR_MSGID_MASK) | (_Data)) -// The Microcode supports up to 16 RSS queues -#define SXG_MAX_RSS 16 -#define SXG_MAX_RSS_TABLE_SIZE 256 // 256-byte max +#define SXG_MIN_AGG_DEFAULT 0x0010 /* Minimum aggregation default */ +#define SXG_MAX_AGG_DEFAULT 0x0040 /* Maximum aggregation default */ +#define SXG_MAX_AGG_SHIFT 16 /* Maximum in top 16 bits of register */ +/* Disable interrupt aggregation on xmt */ +#define SXG_AGG_XMT_DISABLE 0x80000000 + +/* The Microcode supports up to 16 RSS queues (RevB) */ +#define SXG_MAX_RSS 16 +#define SXG_MAX_RSS_REVA 8 + +#define SXG_MAX_RSS_TABLE_SIZE 256 /* 256-byte max */ + +#define SXG_RSS_REVA_TCP6 0x00000001 /* RSS TCP over IPv6 */ +#define SXG_RSS_REVA_TCP4 0x00000002 /* RSS TCP over IPv4 */ +#define SXG_RSS_IP 0x00000001 /* RSS TCP over IPv6 */ +#define SXG_RSS_TCP 0x00000002 /* RSS TCP over IPv4 */ +#define SXG_RSS_LEGACY 0x00000004 /* Line-base interrupts */ +#define SXG_RSS_TABLE_SIZE 0x0000FF00 /* Table size mask */ -#define SXG_RSS_TCP6 0x00000001 // RSS TCP over IPv6 -#define SXG_RSS_TCP4 0x00000002 // RSS TCP over IPv4 -#define SXG_RSS_LEGACY 0x00000004 // Line-base interrupts -#define SXG_RSS_TABLE_SIZE 0x0000FF00 // Table size mask #define SXG_RSS_TABLE_SHIFT 8 -#define SXG_RSS_BASE_CPU 0x00FF0000 // Base CPU (not used) +#define SXG_RSS_BASE_CPU 0x00FF0000 /* Base CPU (not used) */ #define SXG_RSS_BASE_SHIFT 16 -#define SXG_RCV_IP_CSUM_ENABLED 0x00000001 // ExCode 26 (ReceiveChecksum) -#define SXG_RCV_TCP_CSUM_ENABLED 0x00000002 // ExCode 26 (ReceiveChecksum) +#define SXG_RCV_IP_CSUM_ENABLED 0x00000001 /* ExCode 26 (ReceiveChecksum) */ +#define SXG_RCV_TCP_CSUM_ENABLED 0x00000002 /* ExCode 26 (ReceiveChecksum) */ #define SXG_XMT_CPUID_SHIFT 16 -#if VPCI -#define SXG_CHECK_FOR_HANG_TIME 3000 -#else +/* + * Status returned by ucode in the ConfigStat reg (see above) when attempted + * to load configuration data from the EEPROM/Flash. + */ +#define SXG_CFG_TIMEOUT 1 /* init value - timeout if unchanged */ +#define SXG_CFG_LOAD_EEPROM 2 /* config data loaded from EEPROM */ +#define SXG_CFG_LOAD_FLASH 3 /* config data loaded from flash */ +#define SXG_CFG_LOAD_INVALID 4 /* no valid config data found */ +#define SXG_CFG_LOAD_ERROR 5 /* hardware error */ + #define SXG_CHECK_FOR_HANG_TIME 5 -#endif /* * TCB registers - This is really the same register memory area as UCODE_REGS * above, but defined differently. Bits 17:06 of the address define the TCB, * which means each TCB area occupies 0x40 (64) bytes, or 16 u32S. What really * is happening is that these registers occupy the "PadEx[15]" areas in the - * SXG_UCODE_REGS definition above + * struct sxg_ucode_regs definition above */ -struct SXG_TCB_REGS { - u32 ExCode; /* Extended codes - see SXG_UCODE_REGS */ - u32 Xmt; /* Code = 1 - # of Xmt descriptors added to ring */ - u32 Rcv; /* Code = 2 - # of Rcv descriptors added to ring */ - u32 Rsvd1; /* Code = 3 - TOE NA */ - u32 Rsvd2; /* Code = 4 - TOE NA */ - u32 Rsvd3; /* Code = 5 - TOE NA */ - u32 Invalid; /* Code = 6 - Reserved for "CardUp" see above */ - u32 Rsvd4; /* Code = 7 - TOE NA */ - u32 Rsvd5; /* Code = 8 - TOE NA */ - u32 Pad[7]; /* Codes 8-15 - Not used. */ +struct sxg_tcb_regs { + u32 ExCode; /* Extended codes - see SXG_UCODE_REGS */ + u32 Xmt; /* Code = 1 - # of Xmt descriptors added to ring */ + u32 Rcv; /* Code = 2 - # of Rcv descriptors added to ring */ + u32 Rsvd1; /* Code = 3 - TOE NA */ + u32 Rsvd2; /* Code = 4 - TOE NA */ + u32 Rsvd3; /* Code = 5 - TOE NA */ + u32 Invalid1; /* Code = 6 - Reserved for "CardUp" see above */ + u32 Rsvd4; /* Code = 7 - TOE NA */ + u32 Invalid2; /* Code = 8 - Reserved for "ConfigStat" see above */ + u32 Rsvd5; /* Code = 9 - TOE NA */ + u32 Pad[6]; /* Codes 10-15 - Not used. */ }; /*************************************************************************** @@ -206,29 +229,26 @@ struct SXG_TCB_REGS { * ||---|-CpuId of crash * |----/ ***************************************************************************/ -#define SXG_ISR_ERR 0x80000000 // Error -#define SXG_ISR_EVENT 0x40000000 // Event ring event -#define SXG_ISR_NONE1 0x20000000 // Not used -#define SXG_ISR_UPC 0x10000000 // Dump/debug command complete -#define SXG_ISR_LINK 0x08000000 // Link event -#define SXG_ISR_PDQF 0x04000000 // Processed data queue full -#define SXG_ISR_RMISS 0x02000000 // Drop - no host buf -#define SXG_ISR_BREAK 0x01000000 // Breakpoint hit -#define SXG_ISR_PING 0x00800000 // Heartbeat response -#define SXG_ISR_DEAD 0x00400000 // Card crash -#define SXG_ISR_ERFULL 0x00200000 // Event ring full -#define SXG_ISR_XDROP 0x00100000 // XMT Drop - no DRAM bufs or XMT err -#define SXG_ISR_SPSEND 0x00080000 // Slow send complete -#define SXG_ISR_CPU 0x00070000 // Dead CPU mask -#define SXG_ISR_CPU_SHIFT 16 // Dead CPU shift -#define SXG_ISR_CRASH 0x0000FFFF // Crash address mask +#define SXG_ISR_ERR 0x80000000 /* Error */ +#define SXG_ISR_EVENT 0x40000000 /* Event ring event */ +#define SXG_ISR_NONE1 0x20000000 /* Not used */ +#define SXG_ISR_UPC 0x10000000 /* Dump/debug command complete*/ +#define SXG_ISR_LINK 0x08000000 /* Link event */ +#define SXG_ISR_PDQF 0x04000000 /* Processed data queue full */ +#define SXG_ISR_RMISS 0x02000000 /* Drop - no host buf */ +#define SXG_ISR_BREAK 0x01000000 /* Breakpoint hit */ +#define SXG_ISR_PING 0x00800000 /* Heartbeat response */ +#define SXG_ISR_DEAD 0x00400000 /* Card crash */ +#define SXG_ISR_ERFULL 0x00200000 /* Event ring full */ +#define SXG_ISR_XDROP 0x00100000 /* XMT Drop - no DRAM bufs or XMT err */ +#define SXG_ISR_SPSEND 0x00080000 /* Slow send complete */ +#define SXG_ISR_CPU 0x00070000 /* Dead CPU mask */ +#define SXG_ISR_CPU_SHIFT 16 /* Dead CPU shift */ +#define SXG_ISR_CRASH 0x0000FFFF /* Crash address mask */ /*************************************************************************** - * * Event Ring entry * - ***************************************************************************/ -/* * 31 15 0 * .___________________.___________________. * |<------------ Pad 0 ------------>| @@ -270,196 +290,223 @@ struct SXG_TCB_REGS { * ||------- ISTCPIP * |-------- SCERR * - */ + ************************************************************************/ #pragma pack(push, 1) -struct SXG_EVENT { - u32 Pad[1]; // not used - u32 SndUna; // SndUna value - u32 Resid; // receive MDL resid +struct sxg_event { + u32 Pad[1]; /* not used */ + u32 SndUna; /* SndUna value */ + u32 Resid; /* receive MDL resid */ union { - void *HostHandle; // Receive host handle - u32 Rsvd1; // TOE NA + void * HostHandle; /* Receive host handle */ + u32 Rsvd1; /* TOE NA */ struct { u32 NotUsed; - u32 Rsvd2; // TOE NA + u32 Rsvd2; /* TOE NA */ } Flush; }; - u32 Toeplitz; // RSS Toeplitz hash + u32 Toeplitz; /* RSS Toeplitz hash */ union { - ushort Rsvd3; // TOE NA - ushort HdrOffset; // Slowpath + ushort Rsvd3; /* TOE NA */ + ushort HdrOffset; /* Slowpath */ }; - ushort Length; // - unsigned char Rsvd4; // TOE NA - unsigned char Code; // Event code - unsigned char CommandIndex; // New ring index - unsigned char Status; // Event status + ushort Length; + unsigned char Rsvd4; /* TOE NA */ + unsigned char Code; /* Event code */ + unsigned char CommandIndex; /* New ring index */ + unsigned char Status; /* Event status */ }; #pragma pack(pop) -// Event code definitions -#define EVENT_CODE_BUFFERS 0x01 // Receive buffer list command (ring 0) -#define EVENT_CODE_SLOWRCV 0x02 // Slowpath receive -#define EVENT_CODE_UNUSED 0x04 // Was slowpath commands complete +/* Event code definitions */ +#define EVENT_CODE_BUFFERS 0x01 /* Receive buffer list command (ring 0) */ +#define EVENT_CODE_SLOWRCV 0x02 /* Slowpath receive */ +#define EVENT_CODE_UNUSED 0x04 /* Was slowpath commands complete */ -// Status values -#define EVENT_STATUS_VALID 0x80 // Entry valid +/* Status values */ +#define EVENT_STATUS_VALID 0x80 /* Entry valid */ -// Slowpath status -#define EVENT_STATUS_ERROR 0x40 // Completed with error. Index in next byte -#define EVENT_STATUS_TCPIP4 0x20 // TCPIPv4 frame -#define EVENT_STATUS_TCPBAD 0x10 // Bad TCP checksum -#define EVENT_STATUS_IPBAD 0x08 // Bad IP checksum -#define EVENT_STATUS_RCVERR 0x04 // Slowpath receive error -#define EVENT_STATUS_IPONLY 0x02 // IP frame -#define EVENT_STATUS_TCPIP6 0x01 // TCPIPv6 frame -#define EVENT_STATUS_TCPIP 0x21 // Combination of v4 and v6 +/* Slowpath status */ +#define EVENT_STATUS_ERROR 0x40 /* Completed with error. Index in next byte */ +#define EVENT_STATUS_TCPIP4 0x20 /* TCPIPv4 frame */ +#define EVENT_STATUS_TCPBAD 0x10 /* Bad TCP checksum */ +#define EVENT_STATUS_IPBAD 0x08 /* Bad IP checksum */ +#define EVENT_STATUS_RCVERR 0x04 /* Slowpath receive error */ +#define EVENT_STATUS_IPONLY 0x02 /* IP frame */ +#define EVENT_STATUS_TCPIP6 0x01 /* TCPIPv6 frame */ +#define EVENT_STATUS_TCPIP 0x21 /* Combination of v4 and v6 */ -// Event ring -// Size must be power of 2, between 128 and 16k -#define EVENT_RING_SIZE 4096 // ?? -#define EVENT_RING_BATCH 16 // Hand entries back 16 at a time. -#define EVENT_BATCH_LIMIT 256 // Stop processing events after 256 (16 * 16) +/* + * Event ring + * Size must be power of 2, between 128 and 16k + */ +#define EVENT_RING_SIZE 4096 +#define EVENT_RING_BATCH 16 /* Hand entries back 16 at a time. */ +/* Stop processing events after 4096 (256 * 16) */ +#define EVENT_BATCH_LIMIT 256 -struct SXG_EVENT_RING { - struct SXG_EVENT Ring[EVENT_RING_SIZE]; +struct sxg_event_ring { + struct sxg_event Ring[EVENT_RING_SIZE]; }; -/*************************************************************************** - * - * TCB Buffers - * - ***************************************************************************/ -// Maximum number of TCBS supported by hardware/microcode +/* TCB Buffers */ +/* Maximum number of TCBS supported by hardware/microcode */ #define SXG_MAX_TCB 4096 -// Minimum TCBs before we fail initialization +/* Minimum TCBs before we fail initialization */ #define SXG_MIN_TCB 512 -// TCB Hash -// The bucket is determined by bits 11:4 of the toeplitz if we support 4k -// offloaded connections, 10:4 if we support 2k and so on. +/* + * TCB Hash + * The bucket is determined by bits 11:4 of the toeplitz if we support 4k + * offloaded connections, 10:4 if we support 2k and so on. + */ #define SXG_TCB_BUCKET_SHIFT 4 -#define SXG_TCB_PER_BUCKET 16 -#define SXG_TCB_BUCKET_MASK 0xFF0 // Bucket portion of TCB ID -#define SXG_TCB_ELEMENT_MASK 0x00F // Element within bucket -#define SXG_TCB_BUCKETS 256 // 256 * 16 = 4k +#define SXG_TCB_PER_BUCKET 16 +#define SXG_TCB_BUCKET_MASK 0xFF0 /* Bucket portion of TCB ID */ +#define SXG_TCB_ELEMENT_MASK 0x00F /* Element within bucket */ +#define SXG_TCB_BUCKETS 256 /* 256 * 16 = 4k */ -#define SXG_TCB_BUFFER_SIZE 512 // ASSERT format is correct +#define SXG_TCB_BUFFER_SIZE 512 /* ASSERT format is correct */ -#define SXG_TCB_RCVQ_SIZE 736 +#define SXG_TCB_RCVQ_SIZE 736 #define SXG_TCB_COMPOSITE_BUFFER_SIZE 1024 -#define SXG_LOCATE_TCP_FRAME_HDR(_TcpObject, _IPv6) \ - (((_TcpObject)->VlanId) ? \ - ((_IPv6) ? /* Vlan frame header = yes */ \ - &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp6.SxgTcp : \ - &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp.SxgTcp) : \ - ((_IPv6) ? /* Vlan frame header = No */ \ - &(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp6.SxgTcp : \ +#define SXG_LOCATE_TCP_FRAME_HDR(_TcpObject, _IPv6) \ + (((_TcpObject)->VlanId) ? \ + ((_IPv6) ? /* Vlan frame header = yes */ \ + &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp6.SxgTcp: \ + &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp.SxgTcp): \ + ((_IPv6) ? /* Vlan frame header = No */ \ + &(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp6.SxgTcp : \ &(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp.SxgTcp)) -#define SXG_LOCATE_IP_FRAME_HDR(_TcpObject) \ - (_TcpObject)->VlanId ? \ - &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp.Ip : \ +#define SXG_LOCATE_IP_FRAME_HDR(_TcpObject) \ + (_TcpObject)->VlanId ? \ + &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp.Ip: \ &(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp.Ip -#define SXG_LOCATE_IP6_FRAME_HDR(_TcpObject) \ - (_TcpObject)->VlanId ? \ - &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp6.Ip : \ +#define SXG_LOCATE_IP6_FRAME_HDR(TcpObject) \ + (_TcpObject)->VlanId ? \ + &(_TcpObject)->CompBuffer->Frame.HasVlan.TcpIp6.Ip: \ &(_TcpObject)->CompBuffer->Frame.NoVlan.TcpIp6.Ip #if DBG -// Horrible kludge to distinguish dumb-nic, slowpath, and -// fastpath traffic. Decrement the HopLimit by one -// for slowpath, two for fastpath. This assumes the limit is measurably -// greater than two, which I think is reasonable. -// Obviously this is DBG only. Maybe remove later, or #if 0 so we -// can set it when needed -#define SXG_DBG_HOP_LIMIT(_TcpObject, _FastPath) { \ - PIPV6_HDR _Ip6FrameHdr; \ - if((_TcpObject)->IPv6) { \ - _Ip6FrameHdr = SXG_LOCATE_IP6_FRAME_HDR((_TcpObject)); \ - if(_FastPath) { \ - _Ip6FrameHdr->HopLimit = (_TcpObject)->Cached.TtlOrHopLimit - 2; \ - } else { \ - _Ip6FrameHdr->HopLimit = (_TcpObject)->Cached.TtlOrHopLimit - 1; \ - } \ - } \ +/* + * Horrible kludge to distinguish dumb-nic, slowpath, and + * fastpath traffic. Decrement the HopLimit by one + * for slowpath, two for fastpath. This assumes the limit is measurably + * greater than two, which I think is reasonable. + * Obviously this is DBG only. Maybe remove later, or #if 0 so we + * can set it when needed + */ +#define SXG_DBG_HOP_LIMIT(_TcpObject, _FastPath) { \ + PIPV6_HDR _Ip6FrameHdr; \ + if ((_TcpObject)->IPv6) { \ + _Ip6FrameHdr = SXG_LOCATE_IP6_FRAME_HDR((_TcpObject)); \ + if (_FastPath) { \ + _Ip6FrameHdr->HopLimit = \ + (_TcpObject)->Cached.TtlOrHopLimit - 2; \ + } else { \ + _Ip6FrameHdr->HopLimit = \ + (_TcpObject)->Cached.TtlOrHopLimit - 1; \ + } \ + } \ } #else -// Do nothing with free build +/* Do nothing with free build */ #define SXG_DBG_HOP_LIMIT(_TcpObject, _FastPath) #endif -/*************************************************************************** - * Receive and transmit rings - ***************************************************************************/ +/* Receive and transmit rings */ #define SXG_MAX_RING_SIZE 256 -#define SXG_XMT_RING_SIZE 128 // Start with 128 -#define SXG_RCV_RING_SIZE 128 // Start with 128 +#define SXG_XMT_RING_SIZE 128 /* Start with 128 */ +#define SXG_RCV_RING_SIZE 128 /* Start with 128 */ #define SXG_MAX_ENTRIES 4096 +#define SXG_JUMBO_RCV_RING_SIZE 32 -// Structure and macros to manage a ring -struct SXG_RING_INFO { - unsigned char Head; // Where we add entries - Note unsigned char:RING_SIZE - unsigned char Tail; // Where we pull off completed entries - ushort Size; // Ring size - Must be multiple of 2 - void *Context[SXG_MAX_RING_SIZE]; // Shadow ring +/* Structure and macros to manage a ring */ +struct sxg_ring_info { + /* Where we add entries - Note unsigned char:RING_SIZE */ + unsigned char Head; + unsigned char Tail; /* Where we pull off completed entries */ + ushort Size; /* Ring size - Must be multiple of 2 */ + void * Context[SXG_MAX_RING_SIZE]; /* Shadow ring */ }; -#define SXG_INITIALIZE_RING(_ring, _size) { \ - (_ring).Head = 0; \ - (_ring).Tail = 0; \ - (_ring).Size = (_size); \ +#define SXG_INITIALIZE_RING(_ring, _size) { \ + (_ring).Head = 0; \ + (_ring).Tail = 0; \ + (_ring).Size = (_size); \ } -#define SXG_ADVANCE_INDEX(_index, _size) ((_index) = ((_index) + 1) & ((_size) - 1)) -#define SXG_PREVIOUS_INDEX(_index, _size) (((_index) - 1) &((_size) - 1)) + +#define SXG_ADVANCE_INDEX(_index, _size) \ + ((_index) = ((_index) + 1) & ((_size) - 1)) +#define SXG_PREVIOUS_INDEX(_index, _size) \ + (((_index) - 1) &((_size) - 1)) #define SXG_RING_EMPTY(_ring) ((_ring)->Head == (_ring)->Tail) -#define SXG_RING_FULL(_ring) ((((_ring)->Head + 1) & ((_ring)->Size - 1)) == (_ring)->Tail) -#define SXG_RING_ADVANCE_HEAD(_ring) SXG_ADVANCE_INDEX((_ring)->Head, ((_ring)->Size)) -#define SXG_RING_RETREAT_HEAD(_ring) ((_ring)->Head = \ - SXG_PREVIOUS_INDEX((_ring)->Head, (_ring)->Size)) -#define SXG_RING_ADVANCE_TAIL(_ring) { \ - ASSERT((_ring)->Tail != (_ring)->Head); \ - SXG_ADVANCE_INDEX((_ring)->Tail, ((_ring)->Size)); \ +#define SXG_RING_FULL(_ring) \ + ((((_ring)->Head + 1) & ((_ring)->Size - 1)) == (_ring)->Tail) +#define SXG_RING_ADVANCE_HEAD(_ring) \ + SXG_ADVANCE_INDEX((_ring)->Head, ((_ring)->Size)) +#define SXG_RING_RETREAT_HEAD(_ring) ((_ring)->Head = \ + SXG_PREVIOUS_INDEX((_ring)->Head, (_ring)->Size)) +#define SXG_RING_ADVANCE_TAIL(_ring) { \ + ASSERT((_ring)->Tail != (_ring)->Head); \ + SXG_ADVANCE_INDEX((_ring)->Tail, ((_ring)->Size)); \ } -// Set cmd to the next available ring entry, set the shadow context -// entry and advance the ring. -// The appropriate lock must be held when calling this macro -#define SXG_GET_CMD(_ring, _ringinfo, _cmd, _context) { \ - if(SXG_RING_FULL(_ringinfo)) { \ - (_cmd) = NULL; \ - } else { \ - (_cmd) = &(_ring)->Descriptors[(_ringinfo)->Head]; \ +/* + * Set cmd to the next available ring entry, set the shadow context + * entry and advance the ring. + * The appropriate lock must be held when calling this macro + */ +#define SXG_GET_CMD(_ring, _ringinfo, _cmd, _context) { \ + if(SXG_RING_FULL(_ringinfo)) { \ + (_cmd) = NULL; \ + } else { \ + (_cmd) = &(_ring)->Descriptors[(_ringinfo)->Head]; \ (_ringinfo)->Context[(_ringinfo)->Head] = (void *)(_context);\ - SXG_RING_ADVANCE_HEAD(_ringinfo); \ - } \ + SXG_RING_ADVANCE_HEAD(_ringinfo); \ + } \ } -// Abort the previously allocated command by retreating the head. -// NOTE - The appopriate lock MUST NOT BE DROPPED between the SXG_GET_CMD -// and SXG_ABORT_CMD calls. -#define SXG_ABORT_CMD(_ringinfo) { \ - ASSERT(!(SXG_RING_EMPTY(_ringinfo))); \ - SXG_RING_RETREAT_HEAD(_ringinfo); \ - (_ringinfo)->Context[(_ringinfo)->Head] = NULL; \ +/* + * Abort the previously allocated command by retreating the head. + * NOTE - The appopriate lock MUST NOT BE DROPPED between the SXG_GET_CMD + * and SXG_ABORT_CMD calls. + */ +#define SXG_ABORT_CMD(_ringinfo) { \ + ASSERT(!(SXG_RING_EMPTY(_ringinfo))); \ + SXG_RING_RETREAT_HEAD(_ringinfo); \ + (_ringinfo)->Context[(_ringinfo)->Head] = NULL; \ } -// For the given ring, return a pointer to the tail cmd and context, -// clear the context and advance the tail -#define SXG_RETURN_CMD(_ring, _ringinfo, _cmd, _context) { \ - (_cmd) = &(_ring)->Descriptors[(_ringinfo)->Tail]; \ +/* + * For the given ring, return a pointer to the tail cmd and context, + * clear the context and advance the tail + */ +#define SXG_RETURN_CMD(_ring, _ringinfo, _cmd, _context) { \ + (_cmd) = &(_ring)->Descriptors[(_ringinfo)->Tail]; \ (_context) = (_ringinfo)->Context[(_ringinfo)->Tail]; \ - (_ringinfo)->Context[(_ringinfo)->Tail] = NULL; \ - SXG_RING_ADVANCE_TAIL(_ringinfo); \ + (_ringinfo)->Context[(_ringinfo)->Tail] = NULL; \ + SXG_RING_ADVANCE_TAIL(_ringinfo); \ } -/*************************************************************************** - * +/* + * For a given ring find out how much the first pointer is ahead of + * the second pointer. "ahead" recognises the fact that the ring can wrap + */ +static inline int sxg_ring_get_forward_diff (struct sxg_ring_info *ringinfo, + int a, int b) { + if ((a < 0 || a > ringinfo->Size ) || (b < 0 || b > ringinfo->Size)) + return -1; + if (a > b) /* _a is lagging _b and _b has not wrapped around */ + return (a - b); + else + return ((ringinfo->Size - (b - a))); +} + +/*************************************************************** * Host Command Buffer - commands to INIC via the Cmd Rings * - ***************************************************************************/ -/* * 31 15 0 * .___________________.___________________. * |<-------------- Sgl Low -------------->| @@ -479,42 +526,43 @@ struct SXG_RING_INFO { * |_________|_________|_________|_________|24 0x18 * |<----- LCnt ------>|<----- Flags ----->| * |_________|_________|_________|_________|28 0x1c - */ + ****************************************************************/ #pragma pack(push, 1) -struct SXG_CMD { - dma_addr_t Sgl; // Physical address of SGL +struct sxg_cmd { + dma64_addr_t Sgl; /* Physical address of SGL */ union { struct { - dma64_addr_t FirstSgeAddress; // Address of first SGE - u32 FirstSgeLength; // Length of first SGE + dma64_addr_t FirstSgeAddress; /* Address of first SGE */ + u32 FirstSgeLength; /* Length of first SGE */ union { - u32 Rsvd1; // TOE NA - u32 SgeOffset; // Slowpath - 2nd SGE offset - u32 Resid; // MDL completion - clobbers update + u32 Rsvd1; /* TOE NA */ + u32 SgeOffset; /* Slowpath - 2nd SGE offset */ + /* MDL completion - clobbers update */ + u32 Resid; }; union { - u32 TotalLength; // Total transfer length - u32 Mss; // LSO MSS + u32 TotalLength; /* Total transfer length */ + u32 Mss; /* LSO MSS */ }; } Buffer; }; union { struct { - unsigned char Flags:4; // slowpath flags - unsigned char IpHl:4; // Ip header length (>>2) - unsigned char MacLen; // Mac header len + unsigned char Flags:4; /* slowpath flags */ + unsigned char IpHl:4; /* Ip header length (>>2) */ + unsigned char MacLen; /* Mac header len */ } CsumFlags; struct { - ushort Flags:4; // slowpath flags - ushort TcpHdrOff:7; // TCP - ushort MacLen:5; // Mac header len + ushort Flags:4; /* slowpath flags */ + ushort TcpHdrOff:7; /* TCP */ + ushort MacLen:5; /* Mac header len */ } LsoFlags; - ushort Flags; // flags + ushort Flags; /* flags */ }; union { - ushort SgEntries; // SG entry count including first sge + ushort SgEntries; /* SG entry count including first sge */ struct { - unsigned char Status; // Copied from event status + unsigned char Status; /* Copied from event status */ unsigned char NotUsed; } Status; }; @@ -522,13 +570,13 @@ struct SXG_CMD { #pragma pack(pop) #pragma pack(push, 1) -struct VLAN_HDR { +struct vlan_hdr { ushort VlanTci; ushort VlanTpid; }; #pragma pack(pop) -/* +/******************************************************************** * Slowpath Flags: * * @@ -558,36 +606,36 @@ struct VLAN_HDR { * | LCnt |MAC hlen |Hlen|Flgs| * |___________________|____|____|____|____| * - */ -// Slowpath CMD flags -#define SXG_SLOWCMD_CSUM_IP 0x01 // Checksum IP -#define SXG_SLOWCMD_CSUM_TCP 0x02 // Checksum TCP -#define SXG_SLOWCMD_LSO 0x04 // Large segment send + *****************************************************************/ +/* Slowpath CMD flags */ +#define SXG_SLOWCMD_CSUM_IP 0x01 /* Checksum IP */ +#define SXG_SLOWCMD_CSUM_TCP 0x02 /* Checksum TCP */ +#define SXG_SLOWCMD_LSO 0x04 /* Large segment send */ -struct SXG_XMT_RING { - struct SXG_CMD Descriptors[SXG_XMT_RING_SIZE]; +struct sxg_xmt_ring { + struct sxg_cmd Descriptors[SXG_XMT_RING_SIZE]; }; -struct SXG_RCV_RING { - struct SXG_CMD Descriptors[SXG_RCV_RING_SIZE]; +struct sxg_rcv_ring { + struct sxg_cmd Descriptors[SXG_RCV_RING_SIZE]; }; -/*************************************************************************** +/* * Share memory buffer types - Used to identify asynchronous * shared memory allocation - ***************************************************************************/ -enum SXG_BUFFER_TYPE { - SXG_BUFFER_TYPE_RCV, // Receive buffer - SXG_BUFFER_TYPE_SGL // SGL buffer + */ +enum sxg_buffer_type { + SXG_BUFFER_TYPE_RCV, /* Receive buffer */ + SXG_BUFFER_TYPE_SGL /* SGL buffer */ }; -// State for SXG buffers +/* State for SXG buffers */ #define SXG_BUFFER_FREE 0x01 #define SXG_BUFFER_BUSY 0x02 #define SXG_BUFFER_ONCARD 0x04 #define SXG_BUFFER_UPSTREAM 0x08 -/*************************************************************************** +/* * Receive data buffers * * Receive data buffers are given to the Sahara card 128 at a time. @@ -597,262 +645,370 @@ enum SXG_BUFFER_TYPE { * DMA data into, and a virtual address, which is given back * to the host in the "HostHandle" portion of an event. * The receive descriptor data structure is defined below - * as SXG_RCV_DATA_DESCRIPTOR, and the corresponding block - * is defined as SXG_RCV_DESCRIPTOR_BLOCK. + * as sxg_rcv_data_descriptor, and the corresponding block + * is defined as sxg_rcv_descriptor_block. * * This receive descriptor block is given to the card by filling - * in the Sgl field of a SXG_CMD entry from pAdapt->RcvRings[0] + * in the Sgl field of a sxg_cmd entry from pAdapt->RcvRings[0] * with the physical address of the receive descriptor block. * * Both the receive buffers and the receive descriptor blocks * require additional data structures to maintain them * on a free queue and contain other information associated with them. - * Those data structures are defined as the SXG_RCV_DATA_BUFFER_HDR - * and SXG_RCV_DESCRIPTOR_BLOCK_HDR respectively. + * Those data structures are defined as the sxg_rcv_data_buffer_hdr + * and sxg_rcv_descriptor_block_hdr respectively. * * Since both the receive buffers and the receive descriptor block * must be accessible by the card, both must be allocated out of * shared memory. To ensure that we always have a descriptor * block available for every 128 buffers, we allocate all of * these resources together in a single block. This entire - * block is managed by a SXG_RCV_BLOCK_HDR, who's sole purpose + * block is managed by a struct sxg_rcv_block_hdr, who's sole purpose * is to maintain address information so that the entire block * can be free later. * * Further complicating matters is the fact that the receive * buffers must be variable in length in order to accomodate * jumbo frame configurations. We configure the buffer - * length so that the buffer and it's corresponding SXG_RCV_DATA_BUFFER_HDR - * structure add up to an even boundary. Then we place the - * remaining data structures after 128 of them as shown in - * the following diagram: + * length so that the buffer and it's corresponding struct + * sxg_rcv_data_buffer_hdr structure add up to an even + * boundary. Then we place the remaining data structures after 128 + * of them as shown in the following diagram: * * _________________________________________ * | | * | Variable length receive buffer #1 | * |_________________________________________| * | | - * | SXG_RCV_DATA_BUFFER_HDR #1 | + * | sxg_rcv_data_buffer_hdr #1 | * |_________________________________________| <== Even 2k or 10k boundary * | | * | ... repeat 2-128 .. | * |_________________________________________| * | | - * | SXG_RCV_DESCRIPTOR_BLOCK | - * | Contains SXG_RCV_DATA_DESCRIPTOR * 128 | + * | struct sxg_rcv_descriptor_block | + * | Contains sxg_rcv_data_descriptor * 128 | * |_________________________________________| * | | - * | SXG_RCV_DESCRIPTOR_BLOCK_HDR | + * | struct sxg_rcv_descriptor_block_hdr | * |_________________________________________| * | | - * | SXG_RCV_BLOCK_HDR | + * | struct sxg_rcv_block_hdr | * |_________________________________________| * * Memory consumption: * Non-jumbo: - * Buffers and SXG_RCV_DATA_BUFFER_HDR = 2k * 128 = 256k - * + SXG_RCV_DESCRIPTOR_BLOCK = 2k - * + SXG_RCV_DESCRIPTOR_BLOCK_HDR = ~32 - * + SXG_RCV_BLOCK_HDR = ~32 + * Buffers and sxg_rcv_data_buffer_hdr = 2k * 128 = 256k + * + struct sxg_rcv_descriptor_block = 2k + * + struct sxg_rcv_descriptor_block_hdr = ~32 + * + struct sxg_rcv_block_hdr = ~32 * => Total = ~258k/block * * Jumbo: - * Buffers and SXG_RCV_DATA_BUFFER_HDR = 10k * 128 = 1280k - * + SXG_RCV_DESCRIPTOR_BLOCK = 2k - * + SXG_RCV_DESCRIPTOR_BLOCK_HDR = ~32 - * + SXG_RCV_BLOCK_HDR = ~32 + * Buffers and sxg_rcv_data_buffer_hdr = 10k * 128 = 1280k + * + struct sxg_rcv_descriptor_block = 2k + * + struct sxg_rcv_descriptor_block_hdr = ~32 + * + struct sxg_rcv_block_hdr = ~32 * => Total = ~1282k/block * - ***************************************************************************/ -#define SXG_RCV_DATA_BUFFERS 4096 // Amount to give to the card -#define SXG_INITIAL_RCV_DATA_BUFFERS 8192 // Initial pool of buffers -#define SXG_MIN_RCV_DATA_BUFFERS 2048 // Minimum amount and when to get more -#define SXG_MAX_RCV_BLOCKS 128 // = 16384 receive buffers + */ +#define SXG_RCV_DATA_BUFFERS 8192 /* Amount to give to the card */ +#define SXG_INITIAL_RCV_DATA_BUFFERS 16384 /* Initial pool of buffers */ +/* Minimum amount and when to get more */ +#define SXG_MIN_RCV_DATA_BUFFERS 4096 +#define SXG_MAX_RCV_BLOCKS 256 /* = 32k receive buffers */ +/* Amount to give to the card in case of jumbo frames */ +#define SXG_JUMBO_RCV_DATA_BUFFERS 2048 +/* Initial pool of buffers in case of jumbo buffers */ +#define SXG_INITIAL_JUMBO_RCV_DATA_BUFFERS 4096 +#define SXG_MIN_JUMBO_RCV_DATA_BUFFERS 1024 -// Receive buffer header -struct SXG_RCV_DATA_BUFFER_HDR { - dma_addr_t PhysicalAddress; // Buffer physical address - // Note - DO NOT USE the VirtualAddress field to locate data. - // Use the sxg.h:SXG_RECEIVE_DATA_LOCATION macro instead. - void *VirtualAddress; // Start of buffer - struct LIST_ENTRY FreeList; // Free queue of buffers - struct SXG_RCV_DATA_BUFFER_HDR *Next; // Fastpath data buffer queue - u32 Size; // Buffer size - u32 ByteOffset; // See SXG_RESTORE_MDL_OFFSET - unsigned char State; // See SXG_BUFFER state above - unsigned char Status; // Event status (to log PUSH) - struct sk_buff *skb; // Double mapped (nbl and pkt) +/* Receive buffer header */ +struct sxg_rcv_data_buffer_hdr { + dma64_addr_t PhysicalAddress; /* Buffer physical address */ + /* + * Note - DO NOT USE the VirtualAddress field to locate data. + * Use the sxg.h:SXG_RECEIVE_DATA_LOCATION macro instead. + */ + struct list_entry FreeList; /* Free queue of buffers */ + unsigned char State; /* See SXG_BUFFER state above */ + struct sk_buff * skb; /* Double mapped (nbl and pkt)*/ }; -// SxgSlowReceive uses the PACKET (skb) contained -// in the SXG_RCV_DATA_BUFFER_HDR when indicating dumb-nic data +/* + * SxgSlowReceive uses the PACKET (skb) contained + * in the struct sxg_rcv_data_buffer_hdr when indicating dumb-nic data + */ #define SxgDumbRcvPacket skb -#define SXG_RCV_DATA_HDR_SIZE 256 // Space for SXG_RCV_DATA_BUFFER_HDR -#define SXG_RCV_DATA_BUFFER_SIZE 2048 // Non jumbo = 2k including HDR -#define SXG_RCV_JUMBO_BUFFER_SIZE 10240 // jumbo = 10k including HDR +/* Space for struct sxg_rcv_data_buffer_hdr */ +#define SXG_RCV_DATA_HDR_SIZE sizeof(struct sxg_rcv_data_buffer_hdr) +/* Non jumbo = 2k including HDR */ +#define SXG_RCV_DATA_BUFFER_SIZE 2048 +/* jumbo = 10k including HDR */ +#define SXG_RCV_JUMBO_BUFFER_SIZE 10240 -// Receive data descriptor -struct SXG_RCV_DATA_DESCRIPTOR { +/* Receive data descriptor */ +struct sxg_rcv_data_descriptor { union { - struct sk_buff *VirtualAddress; // Host handle - u64 ForceTo8Bytes; // Force x86 to 8-byte boundary + struct sk_buff *VirtualAddress; /* Host handle */ + u64 ForceTo8Bytes; /*Force x86 to 8-byte boundary*/ }; - dma_addr_t PhysicalAddress; + dma64_addr_t PhysicalAddress; }; -// Receive descriptor block +/* Receive descriptor block */ #define SXG_RCV_DESCRIPTORS_PER_BLOCK 128 -#define SXG_RCV_DESCRIPTOR_BLOCK_SIZE 2048 // For sanity check +#define SXG_RCV_DESCRIPTOR_BLOCK_SIZE 2048 /* For sanity check */ -struct SXG_RCV_DESCRIPTOR_BLOCK { - struct SXG_RCV_DATA_DESCRIPTOR Descriptors[SXG_RCV_DESCRIPTORS_PER_BLOCK]; +struct sxg_rcv_descriptor_block { + struct sxg_rcv_data_descriptor Descriptors[SXG_RCV_DESCRIPTORS_PER_BLOCK]; }; -// Receive descriptor block header -struct SXG_RCV_DESCRIPTOR_BLOCK_HDR { - void *VirtualAddress; // Start of 2k buffer - dma_addr_t PhysicalAddress; // ..and it's physical address - struct LIST_ENTRY FreeList; // Free queue of descriptor blocks - unsigned char State; // See SXG_BUFFER state above +/* Receive descriptor block header */ +struct sxg_rcv_descriptor_block_hdr { + void *VirtualAddress; /* start of 2k buffer */ + dma64_addr_t PhysicalAddress;/* and it's physical address */ + struct list_entry FreeList;/* free queue of descriptor blocks */ + unsigned char State; /* see sxg_buffer state above */ }; -// Receive block header -struct SXG_RCV_BLOCK_HDR { - void *VirtualAddress; // Start of virtual memory - dma_addr_t PhysicalAddress; // ..and it's physical address - struct LIST_ENTRY AllList; // Queue of all SXG_RCV_BLOCKS +/* Receive block header */ +struct sxg_rcv_block_hdr { + void *VirtualAddress; /* Start of virtual memory */ + dma64_addr_t PhysicalAddress;/* ..and it's physical address*/ + struct list_entry AllList; /* Queue of all SXG_RCV_BLOCKS*/ }; -// Macros to determine data structure offsets into receive block -#define SXG_RCV_BLOCK_SIZE(_Buffersize) \ +/* Macros to determine data structure offsets into receive block */ +#define SXG_RCV_BLOCK_SIZE(_Buffersize) \ (((_Buffersize) * SXG_RCV_DESCRIPTORS_PER_BLOCK) + \ - (sizeof(struct SXG_RCV_DESCRIPTOR_BLOCK)) + \ - (sizeof(struct SXG_RCV_DESCRIPTOR_BLOCK_HDR)) + \ - (sizeof(struct SXG_RCV_BLOCK_HDR))) + (sizeof(struct sxg_rcv_descriptor_block)) + \ + (sizeof(struct sxg_rcv_descriptor_block_hdr)) + \ + (sizeof(struct sxg_rcv_block_hdr))) #define SXG_RCV_BUFFER_DATA_SIZE(_Buffersize) \ ((_Buffersize) - SXG_RCV_DATA_HDR_SIZE) #define SXG_RCV_DATA_BUFFER_HDR_OFFSET(_Buffersize) \ ((_Buffersize) - SXG_RCV_DATA_HDR_SIZE) -#define SXG_RCV_DESCRIPTOR_BLOCK_OFFSET(_Buffersize) \ +#define SXG_RCV_DESCRIPTOR_BLOCK_OFFSET(_Buffersize) \ ((_Buffersize) * SXG_RCV_DESCRIPTORS_PER_BLOCK) -#define SXG_RCV_DESCRIPTOR_BLOCK_HDR_OFFSET(_Buffersize) \ +#define SXG_RCV_DESCRIPTOR_BLOCK_HDR_OFFSET(_Buffersize) \ (((_Buffersize) * SXG_RCV_DESCRIPTORS_PER_BLOCK) + \ - (sizeof(struct SXG_RCV_DESCRIPTOR_BLOCK))) + (sizeof(struct sxg_rcv_descriptor_block))) #define SXG_RCV_BLOCK_HDR_OFFSET(_Buffersize) \ (((_Buffersize) * SXG_RCV_DESCRIPTORS_PER_BLOCK) + \ - (sizeof(struct SXG_RCV_DESCRIPTOR_BLOCK)) + \ - (sizeof(struct SXG_RCV_DESCRIPTOR_BLOCK_HDR))) + (sizeof(struct sxg_rcv_descriptor_block)) + \ + (sizeof(struct sxg_rcv_descriptor_block_hdr))) -// Use the miniport reserved portion of the NBL to locate -// our SXG_RCV_DATA_BUFFER_HDR structure. -struct SXG_RCV_NBL_RESERVED { - struct SXG_RCV_DATA_BUFFER_HDR *RcvDataBufferHdr; - void *Available; +/* Scatter gather list buffer */ +#define SXG_INITIAL_SGL_BUFFERS 8192 /* Initial pool of SGL buffers */ +#define SXG_MIN_SGL_BUFFERS 2048 /* Minimum amount and when to get more*/ +/* Maximum to allocate (note ADAPT:ushort) */ +#define SXG_MAX_SGL_BUFFERS 16384 + +/* + * SXG_SGL_POOL_PROPERTIES - This structure is used to define a pool of SGL + * buffers. These buffers are allocated out of shared memory and used to + * contain a physical scatter gather list structure that is shared + * with the card. + * + * We split our SGL buffers into multiple pools based on size. The motivation + * is that some applications perform very large I/Os (1MB for example), so + * we need to be able to allocate an SGL to accommodate such a request. + * But such an SGL would require 256 24-byte SG entries - ~6k. + * Given that the vast majority of I/Os are much smaller than 1M, allocating + * a single pool of SGL buffers would be a horribly inefficient use of + * memory. + * + * The following structure includes two fields relating to its size. + * The NBSize field specifies the largest NET_BUFFER that can be handled + * by the particular pool. The SGEntries field defines the size, in + * entries, of the SGL for that pool. The SGEntries is determined by + * dividing the NBSize by the expected page size (4k), and then padding + * it by some appropriate amount as insurance (20% or so..??). + */ +struct sxg_sgl_pool_properties { + u32 NBSize; /* Largest NET_BUFFER size for this pool */ + ushort SGEntries; /* Number of entries in SGL */ + ushort InitialBuffers; /* Number to allocate at initializationtime */ + ushort MinBuffers; /* When to get more */ + ushort MaxBuffers; /* When to stop */ + ushort PerCpuThreshold;/* See sxgh.h:SXG_RESOURCES */ }; -#define SXG_RCV_NBL_BUFFER_HDR(_NBL) (((PSXG_RCV_NBL_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(_NBL))->RcvDataBufferHdr) +/* + * At the moment I'm going to statically initialize 4 pools: + * 100k buffer pool: The vast majority of the expected buffers are expected + * to be less than or equal to 100k. At 30 entries per and + * 8k initial buffers amounts to ~4MB of memory + * NOTE - This used to be 64K with 20 entries, but during + * WHQL NDIS 6.0 Testing (2c_mini6stress) MS does their + * best to send absurd NBL's with ridiculous SGLs, we + * have received 400byte sends contained in SGL's that + * have 28 entries + * 1M buffer pool: Buffers between 64k and 1M. Allocate 256 initial + * buffers with 300 entries each => ~2MB of memory + * 5M buffer pool: Not expected often, if at all. 32 initial buffers + * at 1500 entries each => ~1MB of memory + * 10M buffer pool: Not expected at all, except under pathelogical conditions. + * Allocate one at initialization time. + * Note - 10M is the current limit of what we can realistically + * support due to the sahara SGL bug described in the + * SAHARA SGL WORKAROUND below. We will likely adjust the + * number of pools and/or pool properties over time. + */ +#define SXG_NUM_SGL_POOLS 4 +#define INITIALIZE_SGL_POOL_PROPERTIES \ +struct sxg_sgl_pool_properties SxgSglPoolProperties[SXG_NUM_SGL_POOLS] =\ +{ \ + { 102400, 30, 8192, 2048, 16384, 256}, \ + { 1048576, 300, 256, 128, 1024, 16}, \ + { 5252880, 1500, 32, 16, 512, 0}, \ + {10485760, 2700, 2, 4, 32, 0}, \ +}; -/*************************************************************************** - * Scatter gather list buffer - ***************************************************************************/ -#define SXG_INITIAL_SGL_BUFFERS 8192 // Initial pool of SGL buffers -#define SXG_MIN_SGL_BUFFERS 2048 // Minimum amount and when to get more -#define SXG_MAX_SGL_BUFFERS 16384 // Maximum to allocate (note ADAPT:ushort) +extern struct sxg_sgl_pool_properties SxgSglPoolProperties[]; -// Self identifying structure type +#define SXG_MAX_SGL_BUFFER_SIZE \ + SxgSglPoolProperties[SXG_NUM_SGL_POOLS - 1].NBSize + +/* + * SAHARA SGL WORKAROUND!! + * The current Sahara card uses a 16-bit counter when advancing + * SGL address locations. This means that if an SGL crosses + * a 64k boundary, the hardware will actually skip back to + * the start of the previous 64k boundary, with obviously + * undesirable results. + * + * We currently workaround this issue by allocating SGL buffers + * in 64k blocks and skipping over buffers that straddle the boundary. + */ +#define SXG_INVALID_SGL(phys_addr,len) \ + (((phys_addr >> 16) != ( (phys_addr + len) >> 16 ))) + +/* + * Allocate SGLs in blocks so we can skip over invalid entries. + * We allocation 64k worth of SGL buffers, including the + * struct sxg_sgl_block_hdr, plus one for padding + */ +#define SXG_SGL_BLOCK_SIZE 65536 +#define SXG_SGL_ALLOCATION_SIZE(_Pool) \ + SXG_SGL_BLOCK_SIZE + SXG_SGL_SIZE(_Pool) + +struct sxg_sgl_block_hdr { + ushort Pool; /* Associated SGL pool */ + /* struct sxg_scatter_gather blocks */ + struct list_entry List; + dma64_addr_t PhysicalAddress;/* physical address */ +}; + +/* + * The following definition denotes the maximum block of memory that the + * card can DMA to.It is specified in the call to NdisMRegisterScatterGatherDma. + * For now, use the same value as used in the Slic/Oasis driver, which + * is 128M. That should cover any expected MDL that I can think of. + */ +#define SXG_MAX_PHYS_MAP (1024 * 1024 * 128) + +/* Self identifying structure type */ enum SXG_SGL_TYPE { - SXG_SGL_DUMB, // Dumb NIC SGL - SXG_SGL_SLOW, // Slowpath protocol header - see below - SXG_SGL_CHIMNEY // Chimney offload SGL + SXG_SGL_DUMB, /* Dumb NIC SGL */ + SXG_SGL_SLOW, /* Slowpath protocol header - see below */ + SXG_SGL_CHIMNEY /* Chimney offload SGL */ }; -// Note - the description below is Microsoft specific -// -// The following definition specifies the amount of shared memory to allocate -// for the SCATTER_GATHER_LIST portion of the SXG_SCATTER_GATHER data structure. -// The following considerations apply when setting this value: -// - First, the Sahara card is designed to read the Microsoft SGL structure -// straight out of host memory. This means that the SGL must reside in -// shared memory. If the length here is smaller than the SGL for the -// NET_BUFFER, then NDIS will allocate its own buffer. The buffer -// that NDIS allocates is not in shared memory, so when this happens, -// the SGL will need to be copied to a set of SXG_SCATTER_GATHER buffers. -// In other words.. we don't want this value to be too small. -// - On the other hand.. we're allocating up to 16k of these things. If -// we make this too big, we start to consume a ton of memory.. -// At the moment, I'm going to limit the number of SG entries to 150. -// If each entry maps roughly 4k, then this should cover roughly 600kB -// NET_BUFFERs. Furthermore, since each entry is 24 bytes, the total -// SGE portion of the structure consumes 3600 bytes, which should allow -// the entire SXG_SCATTER_GATHER structure to reside comfortably within -// a 4k block, providing the remaining fields stay under 500 bytes. -// -// So with 150 entries, the SXG_SCATTER_GATHER structure becomes roughly -// 4k. At 16k of them, that amounts to 64M of shared memory. A ton, but -// manageable. -#define SXG_SGL_ENTRIES 150 - -// The ucode expects an NDIS SGL structure that -// is formatted for an x64 system. When running -// on an x64 system, we can simply hand the NDIS SGL -// to the card directly. For x86 systems we must reconstruct -// the SGL. The following structure defines an x64 -// formatted SGL entry -struct SXG_X64_SGE { - dma64_addr_t Address; // same as wdm.h - u32 Length; // same as wdm.h - u32 CompilerPad; // The compiler pads to 8-bytes - u64 Reserved; // u32 * in wdm.h. Force to 8 bytes +/* + * The ucode expects an NDIS SGL structure that + * is formatted for an x64 system. When running + * on an x64 system, we can simply hand the NDIS SGL + * to the card directly. For x86 systems we must reconstruct + * the SGL. The following structure defines an x64 + * formatted SGL entry + */ +struct sxg_x64_sge { + dma64_addr_t Address; /* same as wdm.h */ + u32 Length; /* same as wdm.h */ + u32 CompilerPad; /* The compiler pads to 8-bytes */ + u64 Reserved; /* u32 * in wdm.h. Force to 8 bytes */ }; -struct SCATTER_GATHER_ELEMENT { - dma64_addr_t Address; // same as wdm.h - u32 Length; // same as wdm.h - u32 CompilerPad; // The compiler pads to 8-bytes - u64 Reserved; // u32 * in wdm.h. Force to 8 bytes -}; - -struct SCATTER_GATHER_LIST { +/* + * Our SGL structure - Essentially the same as + * wdm.h:SCATTER_GATHER_LIST. Note the variable number of + * elements based on the pool specified above + */ +struct sxg_x64_sgl { u32 NumberOfElements; u32 *Reserved; - struct SCATTER_GATHER_ELEMENT Elements[]; + struct sxg_x64_sge Elements[1]; /* Variable */ }; -// The card doesn't care about anything except elements, so -// we can leave the u32 * reserved field alone in the following -// SGL structure. But redefine from wdm.h:SCATTER_GATHER_LIST so -// we can specify SXG_X64_SGE and define a fixed number of elements -struct SXG_X64_SGL { - u32 NumberOfElements; - u32 *Reserved; - struct SXG_X64_SGE Elements[SXG_SGL_ENTRIES]; +struct sxg_scatter_gather { + enum SXG_SGL_TYPE Type; /* FIRST! Dumb-nic or offload */ + ushort Pool; /* Associated SGL pool */ + ushort Entries; /* SGL total entries */ + void * adapter; /* Back pointer to adapter */ + /* Free struct sxg_scatter_gather blocks */ + struct list_entry FreeList; + /* All struct sxg_scatter_gather blocks */ + struct list_entry AllList; + dma64_addr_t PhysicalAddress;/* physical address */ + unsigned char State; /* See SXG_BUFFER state above */ + unsigned char CmdIndex; /* Command ring index */ + struct sk_buff *DumbPacket; /* Associated Packet */ + /* For asynchronous completions */ + u32 Direction; + u32 CurOffset; /* Current SGL offset */ + u32 SglRef; /* SGL reference count */ + struct vlan_hdr VlanTag; /* VLAN tag to be inserted into SGL */ + struct sxg_x64_sgl *pSgl; /* SGL Addr. Possibly &Sgl */ + struct sxg_x64_sgl Sgl; /* SGL handed to card */ }; -struct SXG_SCATTER_GATHER { - enum SXG_SGL_TYPE Type; // FIRST! Dumb-nic or offload - void *adapter; // Back pointer to adapter - struct LIST_ENTRY FreeList; // Free SXG_SCATTER_GATHER blocks - struct LIST_ENTRY AllList; // All SXG_SCATTER_GATHER blocks - dma_addr_t PhysicalAddress; // physical address - unsigned char State; // See SXG_BUFFER state above - unsigned char CmdIndex; // Command ring index - struct sk_buff *DumbPacket; // Associated Packet - u32 Direction; // For asynchronous completions - u32 CurOffset; // Current SGL offset - u32 SglRef; // SGL reference count - struct VLAN_HDR VlanTag; // VLAN tag to be inserted into SGL - struct SCATTER_GATHER_LIST *pSgl; // SGL Addr. Possibly &Sgl - struct SXG_X64_SGL Sgl; // SGL handed to card -}; +/* + * Note - the "- 1" is because struct sxg_scatter_gather=>struct sxg_x64_sgl + * includes 1 SGE.. + */ +#define SXG_SGL_SIZE(_Pool) \ + (sizeof(struct sxg_scatter_gather) + \ + ((SxgSglPoolProperties[_Pool].SGEntries - 1) * \ + sizeof(struct sxg_x64_sge))) +/* Force NDIS to give us it's own buffer so we can reformat to our own */ +#define SXG_SGL_BUFFER(_SxgSgl) NULL +#define SXG_SGL_BUFFER_LENGTH(_SxgSgl) 0 +#define SXG_SGL_BUF_SIZE 0 + +/* #if defined(CONFIG_X86_64) -#define SXG_SGL_BUFFER(_SxgSgl) (&_SxgSgl->Sgl) -#define SXG_SGL_BUF_SIZE sizeof(struct SXG_X64_SGL) +#define SXG_SGL_BUFFER(_SxgSgl) (&_SxgSgl->Sgl) +#define SXG_SGL_BUFFER_LENGTH(_SxgSgl) ((_SxgSgl)->Entries * \ + sizeof(struct sxg_x64_sge)) +#define SXG_SGL_BUF_SIZE sizeof(struct sxg_x64_sgl) #elif defined(CONFIG_X86) // Force NDIS to give us it's own buffer so we can reformat to our own -#define SXG_SGL_BUFFER(_SxgSgl) NULL +#define SXG_SGL_BUFFER(_SxgSgl) NULL +#define SXG_SGL_BUFFER_LENGTH(_SxgSgl) 0 #define SXG_SGL_BUF_SIZE 0 #else #error staging: sxg: driver is for X86 only! #endif +*/ +/* Microcode statistics */ +struct sxg_ucode_stats { + u32 RPDQOflow; /* PDQ overflow (unframed ie dq & drop 1st) */ + u32 XDrops; /* Xmt drops due to no xmt buffer */ + u32 ERDrops; /* Rcv drops due to ER full */ + u32 NBDrops; /* Rcv drops due to out of host buffers */ + u32 PQDrops; /* Rcv drops due to PDQ full */ + /* Rcv drops due to bad frame: no link addr match, frlen > max */ + u32 BFDrops; + u32 UPDrops; /* Rcv drops due to UPFq full */ + u32 XNoBufs; /* Xmt drop due to no DRAM Xmit buffer or PxyBuf */ +}; + +/* + * Macros for handling the Offload engine values + */ +/* Number of positions to shift Network Header Length before passing to card */ +#define SXG_NW_HDR_LEN_SHIFT 2 diff --git a/drivers/staging/sxg/sxghw.h b/drivers/staging/sxg/sxghw.h index b0efff9ff117..81f81d4b0ad0 100644 --- a/drivers/staging/sxg/sxghw.h +++ b/drivers/staging/sxg/sxghw.h @@ -1,4 +1,4 @@ -/* +/************************************************************* * Copyright © 1997-2007 Alacritech, Inc. All rights reserved * * $Id: sxghw.h,v 1.2 2008/07/24 17:24:23 chris Exp $ @@ -7,682 +7,894 @@ * * This file contains structures and definitions for the * Alacritech Sahara hardware - */ + * + **********************************************************/ -/******************************************************************************* - * Configuration space - *******************************************************************************/ +/* PCI Configuration space */ /* PCI Vendor ID */ #define SXG_VENDOR_ID 0x139A /* Alacritech's Vendor ID */ -// PCI Device ID +/* PCI Device ID */ #define SXG_DEVICE_ID 0x0009 /* Sahara Device ID */ -// -// Subsystem IDs. -// -// The subsystem ID value is broken into bit fields as follows: -// Bits [15:12] - Function -// Bits [11:8] - OEM and/or operating system. -// Bits [7:0] - Base SID. -// -// SSID field (bit) masks -#define SSID_BASE_MASK 0x00FF // Base subsystem ID mask -#define SSID_OEM_MASK 0x0F00 // Subsystem OEM mask -#define SSID_FUNC_MASK 0xF000 // Subsystem function mask -// Base SSID's -#define SSID_SAHARA_PROTO 0x0018 // 100022 Sahara prototype (XenPak) board -#define SSID_SAHARA_FIBER 0x0019 // 100023 Sahara 1-port fiber board -#define SSID_SAHARA_COPPER 0x001A // 100024 Sahara 1-port copper board +/* Type of ASIC in use */ +enum asic_type { + SAHARA_REV_A, + SAHARA_REV_B +}; -// Useful SSID macros -#define SSID_BASE(ssid) ((ssid) & SSID_BASE_MASK) // isolate base SSID bits -#define SSID_OEM(ssid) ((ssid) & SSID_OEM_MASK) // isolate SSID OEM bits -#define SSID_FUNC(ssid) ((ssid) & SSID_FUNC_MASK) // isolate SSID function bits +/* Type of Xcvr in fiber card */ +enum xcvr_type { + XCVR_UNKNOWN, + XCVR_NONE, + XCVR_SR, + XCVR_LR, + XCVR_LRM, + XCVR_CR +}; +/* + * Subsystem IDs. + * + * The subsystem ID value is broken into bit fields as follows: + * Bits [15:12] - Function + * Bits [11:8] - OEM and/or operating system. + * Bits [7:0] - Base SID. + */ -/******************************************************************************* - * HW Register Space - *******************************************************************************/ -#define SXG_HWREG_MEMSIZE 0x4000 // 16k +/* SSID field (bit) masks */ +#define SSID_BASE_MASK 0x00FF /* Base subsystem ID mask */ +#define SSID_OEM_MASK 0x0F00 /* Subsystem OEM mask */ +#define SSID_FUNC_MASK 0xF000 /* Subsystem function mask */ + +/* Base SSID's */ +/* 100022 Sahara prototype (XenPak) board */ +#define SSID_SAHARA_PROTO 0x0018 +#define SSID_SAHARA_FIBER 0x0019 /* 100023 Sahara 1-port fiber board */ +#define SSID_SAHARA_COPPER 0x001A /* 100024 Sahara 1-port copper board */ + +/* Useful SSID macros */ +/* isolate base SSID bits */ +#define SSID_BASE(ssid) ((ssid) & SSID_BASE_MASK) +/* isolate SSID OEM bits */ +#define SSID_OEM(ssid) ((ssid) & SSID_OEM_MASK) +/* isolate SSID function bits */ +#define SSID_FUNC(ssid) ((ssid) & SSID_FUNC_MASK) + + +/* HW Register Space */ +#define SXG_HWREG_MEMSIZE 0x4000 /* 16k */ #pragma pack(push, 1) -struct SXG_HW_REGS { - u32 Reset; // Write 0xdead to invoke soft reset - u32 Pad1; // No register defined at offset 4 - u32 InterruptMask0; // Deassert legacy interrupt on function 0 - u32 InterruptMask1; // Deassert legacy interrupt on function 1 - u32 UcodeDataLow; // Store microcode instruction bits 31-0 - u32 UcodeDataMiddle; // Store microcode instruction bits 63-32 - u32 UcodeDataHigh; // Store microcode instruction bits 95-64 - u32 UcodeAddr; // Store microcode address - See flags below - u32 PadTo0x80[24]; // Pad to Xcv configuration registers - u32 MacConfig0; // 0x80 - AXGMAC Configuration Register 0 - u32 MacConfig1; // 0x84 - AXGMAC Configuration Register 1 - u32 MacConfig2; // 0x88 - AXGMAC Configuration Register 2 - u32 MacConfig3; // 0x8C - AXGMAC Configuration Register 3 - u32 MacAddressLow; // 0x90 - AXGMAC MAC Station Address - octets 1-4 - u32 MacAddressHigh; // 0x94 - AXGMAC MAC Station Address - octets 5-6 - u32 MacReserved1[2]; // 0x98 - AXGMAC Reserved - u32 MacMaxFrameLen; // 0xA0 - AXGMAC Maximum Frame Length - u32 MacReserved2[2]; // 0xA4 - AXGMAC Reserved - u32 MacRevision; // 0xAC - AXGMAC Revision Level Register - u32 MacReserved3[4]; // 0xB0 - AXGMAC Reserved - u32 MacAmiimCmd; // 0xC0 - AXGMAC AMIIM Command Register - u32 MacAmiimField; // 0xC4 - AXGMAC AMIIM Field Register - u32 MacAmiimConfig; // 0xC8 - AXGMAC AMIIM Configuration Register - u32 MacAmiimLink; // 0xCC - AXGMAC AMIIM Link Fail Vector Register - u32 MacAmiimIndicator; // 0xD0 - AXGMAC AMIIM Indicator Registor - u32 PadTo0x100[11]; // 0xD4 - 0x100 - Pad - u32 XmtConfig; // 0x100 - Transmit Configuration Register - u32 RcvConfig; // 0x104 - Receive Configuration Register 1 - u32 LinkAddress0Low; // 0x108 - Link address 0 - u32 LinkAddress0High; // 0x10C - Link address 0 - u32 LinkAddress1Low; // 0x110 - Link address 1 - u32 LinkAddress1High; // 0x114 - Link address 1 - u32 LinkAddress2Low; // 0x118 - Link address 2 - u32 LinkAddress2High; // 0x11C - Link address 2 - u32 LinkAddress3Low; // 0x120 - Link address 3 - u32 LinkAddress3High; // 0x124 - Link address 3 - u32 ToeplitzKey[10]; // 0x128 - 0x150 - Toeplitz key - u32 SocketKey[10]; // 0x150 - 0x178 - Socket Key - u32 LinkStatus; // 0x178 - Link status - u32 ClearStats; // 0x17C - Clear Stats - u32 XmtErrorsLow; // 0x180 - Transmit stats - errors - u32 XmtErrorsHigh; // 0x184 - Transmit stats - errors - u32 XmtFramesLow; // 0x188 - Transmit stats - frame count - u32 XmtFramesHigh; // 0x18C - Transmit stats - frame count - u32 XmtBytesLow; // 0x190 - Transmit stats - byte count - u32 XmtBytesHigh; // 0x194 - Transmit stats - byte count - u32 XmtTcpSegmentsLow; // 0x198 - Transmit stats - TCP segments - u32 XmtTcpSegmentsHigh; // 0x19C - Transmit stats - TCP segments - u32 XmtTcpBytesLow; // 0x1A0 - Transmit stats - TCP bytes - u32 XmtTcpBytesHigh; // 0x1A4 - Transmit stats - TCP bytes - u32 RcvErrorsLow; // 0x1A8 - Receive stats - errors - u32 RcvErrorsHigh; // 0x1AC - Receive stats - errors - u32 RcvFramesLow; // 0x1B0 - Receive stats - frame count - u32 RcvFramesHigh; // 0x1B4 - Receive stats - frame count - u32 RcvBytesLow; // 0x1B8 - Receive stats - byte count - u32 RcvBytesHigh; // 0x1BC - Receive stats - byte count - u32 RcvTcpSegmentsLow; // 0x1C0 - Receive stats - TCP segments - u32 RcvTcpSegmentsHigh; // 0x1C4 - Receive stats - TCP segments - u32 RcvTcpBytesLow; // 0x1C8 - Receive stats - TCP bytes - u32 RcvTcpBytesHigh; // 0x1CC - Receive stats - TCP bytes - u32 PadTo0x200[12]; // 0x1D0 - 0x200 - Pad - u32 Software[1920]; // 0x200 - 0x2000 - Software defined (not used) - u32 MsixTable[1024]; // 0x2000 - 0x3000 - MSIX Table - u32 MsixBitArray[1024]; // 0x3000 - 0x4000 - MSIX Pending Bit Array +struct sxg_hw_regs { + u32 Reset; /* Write 0xdead to invoke soft reset */ + u32 Pad1; /* No register defined at offset 4 */ + u32 InterruptMask0; /* Deassert legacy interrupt on function 0 */ + u32 InterruptMask1; /* Deassert legacy interrupt on function 1 */ + u32 UcodeDataLow; /* Store microcode instruction bits 31-0 */ + u32 UcodeDataMiddle; /* Store microcode instruction bits 63-32 */ + u32 UcodeDataHigh; /* Store microcode instruction bits 95-64 */ + u32 UcodeAddr; /* Store microcode address - See flags below */ + u32 PadTo0x80[24]; /* Pad to Xcv configuration registers */ + u32 MacConfig0; /* 0x80 - AXGMAC Configuration Register 0 */ + u32 MacConfig1; /* 0x84 - AXGMAC Configuration Register 1 */ + u32 MacConfig2; /* 0x88 - AXGMAC Configuration Register 2 */ + u32 MacConfig3; /* 0x8C - AXGMAC Configuration Register 3 */ + u32 MacAddressLow; /* 0x90 - AXGMAC MAC Station Address - octets 1-4 */ + u32 MacAddressHigh; /* 0x94 - AXGMAC MAC Station Address - octets 5-6 */ + u32 MacReserved1[2]; /* 0x98 - AXGMAC Reserved */ + u32 MacMaxFrameLen; /* 0xA0 - AXGMAC Maximum Frame Length */ + u32 MacReserved2[2]; /* 0xA4 - AXGMAC Reserved */ + u32 MacRevision; /* 0xAC - AXGMAC Revision Level Register */ + u32 MacReserved3[4]; /* 0xB0 - AXGMAC Reserved */ + u32 MacAmiimCmd; /* 0xC0 - AXGMAC AMIIM Command Register */ + u32 MacAmiimField; /* 0xC4 - AXGMAC AMIIM Field Register */ + u32 MacAmiimConfig; /* 0xC8 - AXGMAC AMIIM Configuration Register */ + u32 MacAmiimLink; /* 0xCC - AXGMAC AMIIM Link Fail Vector Register */ + u32 MacAmiimIndicator; /* 0xD0 - AXGMAC AMIIM Indicator Registor */ + u32 PadTo0x100[11]; /* 0xD4 - 0x100 - Pad */ + u32 XmtConfig; /* 0x100 - Transmit Configuration Register */ + u32 RcvConfig; /* 0x104 - Receive Configuration Register 1 */ + u32 LinkAddress0Low; /* 0x108 - Link address 0 */ + u32 LinkAddress0High; /* 0x10C - Link address 0 */ + u32 LinkAddress1Low; /* 0x110 - Link address 1 */ + u32 LinkAddress1High; /* 0x114 - Link address 1 */ + u32 LinkAddress2Low; /* 0x118 - Link address 2 */ + u32 LinkAddress2High; /* 0x11C - Link address 2 */ + u32 LinkAddress3Low; /* 0x120 - Link address 3 */ + u32 LinkAddress3High; /* 0x124 - Link address 3 */ + u32 ToeplitzKey[10]; /* 0x128 - 0x150 - Toeplitz key */ + u32 SocketKey[10]; /* 0x150 - 0x178 - Socket Key */ + u32 LinkStatus; /* 0x178 - Link status */ + u32 ClearStats; /* 0x17C - Clear Stats */ + u32 XmtErrorsLow; /* 0x180 - Transmit stats - errors */ + u32 XmtErrorsHigh; /* 0x184 - Transmit stats - errors */ + u32 XmtFramesLow; /* 0x188 - Transmit stats - frame count */ + u32 XmtFramesHigh; /* 0x18C - Transmit stats - frame count */ + u32 XmtBytesLow; /* 0x190 - Transmit stats - byte count */ + u32 XmtBytesHigh; /* 0x194 - Transmit stats - byte count */ + u32 XmtTcpSegmentsLow; /* 0x198 - Transmit stats - TCP segments */ + u32 XmtTcpSegmentsHigh; /* 0x19C - Transmit stats - TCP segments */ + u32 XmtTcpBytesLow; /* 0x1A0 - Transmit stats - TCP bytes */ + u32 XmtTcpBytesHigh; /* 0x1A4 - Transmit stats - TCP bytes */ + u32 RcvErrorsLow; /* 0x1A8 - Receive stats - errors */ + u32 RcvErrorsHigh; /* 0x1AC - Receive stats - errors */ + u32 RcvFramesLow; /* 0x1B0 - Receive stats - frame count */ + u32 RcvFramesHigh; /* 0x1B4 - Receive stats - frame count */ + u32 RcvBytesLow; /* 0x1B8 - Receive stats - byte count */ + u32 RcvBytesHigh; /* 0x1BC - Receive stats - byte count */ + u32 RcvTcpSegmentsLow; /* 0x1C0 - Receive stats - TCP segments */ + u32 RcvTcpSegmentsHigh; /* 0x1C4 - Receive stats - TCP segments */ + u32 RcvTcpBytesLow; /* 0x1C8 - Receive stats - TCP bytes */ + u32 RcvTcpBytesHigh; /* 0x1CC - Receive stats - TCP bytes */ + u32 PadTo0x200[12]; /* 0x1D0 - 0x200 - Pad */ + u32 Software[1920]; /* 0x200 - 0x2000 - Software defined (not used) */ + u32 MsixTable[1024]; /* 0x2000 - 0x3000 - MSIX Table */ + u32 MsixBitArray[1024]; /* 0x3000 - 0x4000 - MSIX Pending Bit Array */ }; #pragma pack(pop) -// Microcode Address Flags -#define MICROCODE_ADDRESS_GO 0x80000000 // Start microcode -#define MICROCODE_ADDRESS_WRITE 0x40000000 // Store microcode -#define MICROCODE_ADDRESS_READ 0x20000000 // Read microcode -#define MICROCODE_ADDRESS_PARITY 0x10000000 // Parity error detected -#define MICROCODE_ADDRESS_MASK 0x00001FFF // Address bits +/* Microcode Address Flags */ +#define MICROCODE_ADDRESS_GO 0x80000000 /* Start microcode */ +#define MICROCODE_ADDRESS_WRITE 0x40000000 /* Store microcode */ +#define MICROCODE_ADDRESS_READ 0x20000000 /* Read microcode */ +#define MICROCODE_ADDRESS_PARITY 0x10000000/* Parity error detected */ +#define MICROCODE_ADDRESS_MASK 0x00001FFF /* Address bits */ -// Link Address Registers -#define LINK_ADDRESS_ENABLE 0x80000000 // Applied to link address high +/* Link Address Registers */ +/* Applied to link address high */ +#define LINK_ADDRESS_ENABLE 0x80000000 -// Microsoft register space size -#define SXG_UCODEREG_MEMSIZE 0x40000 // 256k +/* Microsoft register space size */ +#define SXG_UCODEREG_MEMSIZE 0x40000 /* 256k */ -// Sahara microcode register address format. The command code, -// extended command code, and associated processor are encoded in -// the address bits as follows -#define SXG_ADDRESS_CODE_SHIFT 2 // Base command code +/* + * Sahara microcode register address format. The command code, + * extended command code, and associated processor are encoded in + * the address bits as follows + */ +#define SXG_ADDRESS_CODE_SHIFT 2 /* Base command code */ #define SXG_ADDRESS_CODE_MASK 0x0000003C -#define SXG_ADDRESS_EXCODE_SHIFT 6 // Extended (or sub) command code +/* Extended (or sub) command code */ +#define SXG_ADDRESS_EXCODE_SHIFT 6 #define SXG_ADDRESS_EXCODE_MASK 0x00001FC0 -#define SXG_ADDRESS_CPUID_SHIFT 13 // CPU +#define SXG_ADDRESS_CPUID_SHIFT 13 /* CPU */ #define SXG_ADDRESS_CPUID_MASK 0x0003E000 -#define SXG_REGISTER_SIZE_PER_CPU 0x00002000 // Used to sanity check UCODE_REGS structure +/* Used to sanity check UCODE_REGS structure */ +#define SXG_REGISTER_SIZE_PER_CPU 0x00002000 -// Sahara receive sequencer status values -#define SXG_RCV_STATUS_ATTN 0x80000000 // Attention -#define SXG_RCV_STATUS_TRANSPORT_MASK 0x3F000000 // Transport mask -#define SXG_RCV_STATUS_TRANSPORT_ERROR 0x20000000 // Transport error -#define SXG_RCV_STATUS_TRANSPORT_CSUM 0x23000000 // Transport cksum error -#define SXG_RCV_STATUS_TRANSPORT_UFLOW 0x22000000 // Transport underflow -#define SXG_RCV_STATUS_TRANSPORT_HDRLEN 0x20000000 // Transport header length -#define SXG_RCV_STATUS_TRANSPORT_FLAGS 0x10000000 // Transport flags detected -#define SXG_RCV_STATUS_TRANSPORT_OPTS 0x08000000 // Transport options detected -#define SXG_RCV_STATUS_TRANSPORT_SESS_MASK 0x07000000 // Transport DDP -#define SXG_RCV_STATUS_TRANSPORT_DDP 0x06000000 // Transport DDP -#define SXG_RCV_STATUS_TRANSPORT_iSCSI 0x05000000 // Transport iSCSI -#define SXG_RCV_STATUS_TRANSPORT_NFS 0x04000000 // Transport NFS -#define SXG_RCV_STATUS_TRANSPORT_FTP 0x03000000 // Transport FTP -#define SXG_RCV_STATUS_TRANSPORT_HTTP 0x02000000 // Transport HTTP -#define SXG_RCV_STATUS_TRANSPORT_SMB 0x01000000 // Transport SMB -#define SXG_RCV_STATUS_NETWORK_MASK 0x00FF0000 // Network mask -#define SXG_RCV_STATUS_NETWORK_ERROR 0x00800000 // Network error -#define SXG_RCV_STATUS_NETWORK_CSUM 0x00830000 // Network cksum error -#define SXG_RCV_STATUS_NETWORK_UFLOW 0x00820000 // Network underflow error -#define SXG_RCV_STATUS_NETWORK_HDRLEN 0x00800000 // Network header length -#define SXG_RCV_STATUS_NETWORK_OFLOW 0x00400000 // Network overflow detected -#define SXG_RCV_STATUS_NETWORK_MCAST 0x00200000 // Network multicast detected -#define SXG_RCV_STATUS_NETWORK_OPTIONS 0x00100000 // Network options detected -#define SXG_RCV_STATUS_NETWORK_OFFSET 0x00080000 // Network offset detected -#define SXG_RCV_STATUS_NETWORK_FRAGMENT 0x00040000 // Network fragment detected -#define SXG_RCV_STATUS_NETWORK_TRANS_MASK 0x00030000 // Network transport type mask -#define SXG_RCV_STATUS_NETWORK_UDP 0x00020000 // UDP -#define SXG_RCV_STATUS_NETWORK_TCP 0x00010000 // TCP -#define SXG_RCV_STATUS_IPONLY 0x00008000 // IP-only not TCP -#define SXG_RCV_STATUS_PKT_PRI 0x00006000 // Receive priority -#define SXG_RCV_STATUS_PKT_PRI_SHFT 13 // Receive priority shift -#define SXG_RCV_STATUS_PARITY 0x00001000 // MAC Receive RAM parity error -#define SXG_RCV_STATUS_ADDRESS_MASK 0x00000F00 // Link address detection mask -#define SXG_RCV_STATUS_ADDRESS_D 0x00000B00 // Link address D -#define SXG_RCV_STATUS_ADDRESS_C 0x00000A00 // Link address C -#define SXG_RCV_STATUS_ADDRESS_B 0x00000900 // Link address B -#define SXG_RCV_STATUS_ADDRESS_A 0x00000800 // Link address A -#define SXG_RCV_STATUS_ADDRESS_BCAST 0x00000300 // Link address broadcast -#define SXG_RCV_STATUS_ADDRESS_MCAST 0x00000200 // Link address multicast -#define SXG_RCV_STATUS_ADDRESS_CMCAST 0x00000100 // Link control multicast -#define SXG_RCV_STATUS_LINK_MASK 0x000000FF // Link status mask -#define SXG_RCV_STATUS_LINK_ERROR 0x00000080 // Link error -#define SXG_RCV_STATUS_LINK_MASK 0x000000FF // Link status mask -#define SXG_RCV_STATUS_LINK_PARITY 0x00000087 // RcvMacQ parity error -#define SXG_RCV_STATUS_LINK_EARLY 0x00000086 // Data early -#define SXG_RCV_STATUS_LINK_BUFOFLOW 0x00000085 // Buffer overflow -#define SXG_RCV_STATUS_LINK_CODE 0x00000084 // Link code error -#define SXG_RCV_STATUS_LINK_DRIBBLE 0x00000083 // Dribble nibble -#define SXG_RCV_STATUS_LINK_CRC 0x00000082 // CRC error -#define SXG_RCV_STATUS_LINK_OFLOW 0x00000081 // Link overflow -#define SXG_RCV_STATUS_LINK_UFLOW 0x00000080 // Link underflow -#define SXG_RCV_STATUS_LINK_8023 0x00000020 // 802.3 -#define SXG_RCV_STATUS_LINK_SNAP 0x00000010 // Snap -#define SXG_RCV_STATUS_LINK_VLAN 0x00000008 // VLAN -#define SXG_RCV_STATUS_LINK_TYPE_MASK 0x00000007 // Network type mask -#define SXG_RCV_STATUS_LINK_CONTROL 0x00000003 // Control packet -#define SXG_RCV_STATUS_LINK_IPV6 0x00000002 // IPv6 packet -#define SXG_RCV_STATUS_LINK_IPV4 0x00000001 // IPv4 packet +/* Sahara receive sequencer status values */ +#define SXG_RCV_STATUS_ATTN 0x80000000 /* Attention */ +#define SXG_RCV_STATUS_TRANSPORT_MASK 0x3F000000 /* Transport mask */ +#define SXG_RCV_STATUS_TRANSPORT_ERROR 0x20000000 /* Transport error */ +/* Transport cksum error */ +#define SXG_RCV_STATUS_TRANSPORT_CSUM 0x23000000 +/* Transport underflow */ +#define SXG_RCV_STATUS_TRANSPORT_UFLOW 0x22000000 + /* Transport header length */ +#define SXG_RCV_STATUS_TRANSPORT_HDRLEN 0x20000000 +/* Transport flags detected */ +#define SXG_RCV_STATUS_TRANSPORT_FLAGS 0x10000000 + /* Transport options detected */ +#define SXG_RCV_STATUS_TRANSPORT_OPTS 0x08000000 +#define SXG_RCV_STATUS_TRANSPORT_SESS_MASK 0x07000000 /* Transport DDP */ +#define SXG_RCV_STATUS_TRANSPORT_DDP 0x06000000 /* Transport DDP */ +#define SXG_RCV_STATUS_TRANSPORT_iSCSI 0x05000000 /* Transport iSCSI */ +#define SXG_RCV_STATUS_TRANSPORT_NFS 0x04000000 /* Transport NFS */ +#define SXG_RCV_STATUS_TRANSPORT_FTP 0x03000000 /* Transport FTP */ +#define SXG_RCV_STATUS_TRANSPORT_HTTP 0x02000000 /* Transport HTTP */ +#define SXG_RCV_STATUS_TRANSPORT_SMB 0x01000000 /* Transport SMB */ +#define SXG_RCV_STATUS_NETWORK_MASK 0x00FF0000 /* Network mask */ +#define SXG_RCV_STATUS_NETWORK_ERROR 0x00800000 /* Network error */ +/* Network cksum error */ +#define SXG_RCV_STATUS_NETWORK_CSUM 0x00830000 +/* Network underflow error */ +#define SXG_RCV_STATUS_NETWORK_UFLOW 0x00820000 + /* Network header length */ +#define SXG_RCV_STATUS_NETWORK_HDRLEN 0x00800000 + /* Network overflow detected */ +#define SXG_RCV_STATUS_NETWORK_OFLOW 0x00400000 +/* Network multicast detected */ +#define SXG_RCV_STATUS_NETWORK_MCAST 0x00200000 +/* Network options detected */ +#define SXG_RCV_STATUS_NETWORK_OPTIONS 0x00100000 +/* Network offset detected */ +#define SXG_RCV_STATUS_NETWORK_OFFSET 0x00080000 +/* Network fragment detected */ +#define SXG_RCV_STATUS_NETWORK_FRAGMENT 0x00040000 +/* Network transport type mask */ +#define SXG_RCV_STATUS_NETWORK_TRANS_MASK 0x00030000 +#define SXG_RCV_STATUS_NETWORK_UDP 0x00020000 /* UDP */ +#define SXG_RCV_STATUS_NETWORK_TCP 0x00010000 /* TCP */ +#define SXG_RCV_STATUS_IPONLY 0x00008000 /* IP-only not TCP */ +/* Receive priority */ +#define SXG_RCV_STATUS_PKT_PRI 0x00006000 +/* Receive priority shift */ +#define SXG_RCV_STATUS_PKT_PRI_SHFT 13 +/* MAC Receive RAM parity error */ +#define SXG_RCV_STATUS_PARITY 0x00001000 +/* Link address detection mask */ +#define SXG_RCV_STATUS_ADDRESS_MASK 0x00000F00 -/*************************************************************************** - * Sahara receive and transmit configuration registers - ***************************************************************************/ -#define RCV_CONFIG_RESET 0x80000000 // RcvConfig register reset -#define RCV_CONFIG_ENABLE 0x40000000 // Enable the receive logic -#define RCV_CONFIG_ENPARSE 0x20000000 // Enable the receive parser -#define RCV_CONFIG_SOCKET 0x10000000 // Enable the socket detector -#define RCV_CONFIG_RCVBAD 0x08000000 // Receive all bad frames -#define RCV_CONFIG_CONTROL 0x04000000 // Receive all control frames -#define RCV_CONFIG_RCVPAUSE 0x02000000 // Enable pause transmit when attn -#define RCV_CONFIG_TZIPV6 0x01000000 // Include TCP port w/ IPv6 toeplitz -#define RCV_CONFIG_TZIPV4 0x00800000 // Include TCP port w/ IPv4 toeplitz -#define RCV_CONFIG_FLUSH 0x00400000 // Flush buffers -#define RCV_CONFIG_PRIORITY_MASK 0x00300000 // Priority level -#define RCV_CONFIG_HASH_MASK 0x00030000 // Hash depth -#define RCV_CONFIG_HASH_8 0x00000000 // Hash depth 8 -#define RCV_CONFIG_HASH_16 0x00010000 // Hash depth 16 -#define RCV_CONFIG_HASH_4 0x00020000 // Hash depth 4 -#define RCV_CONFIG_HASH_2 0x00030000 // Hash depth 2 -#define RCV_CONFIG_BUFLEN_MASK 0x0000FFF0 // Buffer length bits 15:4. ie multiple of 16. -#define RCV_CONFIG_SKT_DIS 0x00000008 // Disable socket detection on attn -// Macro to determine RCV_CONFIG_BUFLEN based on maximum frame size. -// We add 18 bytes for Sahara receive status and padding, plus 4 bytes for CRC, -// and round up to nearest 16 byte boundary -#define RCV_CONFIG_BUFSIZE(_MaxFrame) ((((_MaxFrame) + 22) + 15) & RCV_CONFIG_BUFLEN_MASK) +#define SXG_RCV_STATUS_ADDRESS_D 0x00000B00 /* Link address D */ +#define SXG_RCV_STATUS_ADDRESS_C 0x00000A00 /* Link address C */ +#define SXG_RCV_STATUS_ADDRESS_B 0x00000900 /* Link address B */ +#define SXG_RCV_STATUS_ADDRESS_A 0x00000800 /* Link address A */ +/* Link address broadcast */ +#define SXG_RCV_STATUS_ADDRESS_BCAST 0x00000300 + /* Link address multicast */ +#define SXG_RCV_STATUS_ADDRESS_MCAST 0x00000200 +/* Link control multicast */ +#define SXG_RCV_STATUS_ADDRESS_CMCAST 0x00000100 +/* Link status mask */ +#define SXG_RCV_STATUS_LINK_MASK 0x000000FF +#define SXG_RCV_STATUS_LINK_ERROR 0x00000080 /* Link error */ +/* Link status mask */ +#define SXG_RCV_STATUS_LINK_MASK 0x000000FF +/* RcvMacQ parity error */ +#define SXG_RCV_STATUS_LINK_PARITY 0x00000087 +#define SXG_RCV_STATUS_LINK_EARLY 0x00000086 /* Data early */ +#define SXG_RCV_STATUS_LINK_BUFOFLOW 0x00000085 /* Buffer overflow */ +#define SXG_RCV_STATUS_LINK_CODE 0x00000084 /* Link code error */ +#define SXG_RCV_STATUS_LINK_DRIBBLE 0x00000083 /* Dribble nibble */ +#define SXG_RCV_STATUS_LINK_CRC 0x00000082 /* CRC error */ +#define SXG_RCV_STATUS_LINK_OFLOW 0x00000081 /* Link overflow */ +#define SXG_RCV_STATUS_LINK_UFLOW 0x00000080 /* Link underflow */ +#define SXG_RCV_STATUS_LINK_8023 0x00000020 /* 802.3 */ +#define SXG_RCV_STATUS_LINK_SNAP 0x00000010 /* Snap */ +#define SXG_RCV_STATUS_LINK_VLAN 0x00000008 /* VLAN */ +/* Network type mask */ +#define SXG_RCV_STATUS_LINK_TYPE_MASK 0x00000007 +#define SXG_RCV_STATUS_LINK_CONTROL 0x00000003 /* Control packet */ +#define SXG_RCV_STATUS_LINK_IPV6 0x00000002 /* IPv6 packet */ +#define SXG_RCV_STATUS_LINK_IPV4 0x00000001 /* IPv4 packet */ -#define XMT_CONFIG_RESET 0x80000000 // XmtConfig register reset -#define XMT_CONFIG_ENABLE 0x40000000 // Enable transmit logic -#define XMT_CONFIG_MAC_PARITY 0x20000000 // Inhibit MAC RAM parity error -#define XMT_CONFIG_BUF_PARITY 0x10000000 // Inhibit D2F buffer parity error -#define XMT_CONFIG_MEM_PARITY 0x08000000 // Inhibit 1T SRAM parity error -#define XMT_CONFIG_INVERT_PARITY 0x04000000 // Invert MAC RAM parity -#define XMT_CONFIG_INITIAL_IPID 0x0000FFFF // Initial IPID +/* Sahara receive and transmit configuration registers */ +/* RcvConfig register reset */ +#define RCV_CONFIG_RESET 0x80000000 +/* Enable the receive logic */ +#define RCV_CONFIG_ENABLE 0x40000000 +/* Enable the receive parser */ +#define RCV_CONFIG_ENPARSE 0x20000000 +/* Enable the socket detector */ +#define RCV_CONFIG_SOCKET 0x10000000 +#define RCV_CONFIG_RCVBAD 0x08000000 /* Receive all bad frames */ +/* Receive all control frames */ +#define RCV_CONFIG_CONTROL 0x04000000 +/* Enable pause transmit when attn */ +#define RCV_CONFIG_RCVPAUSE 0x02000000 +/* Include TCP port w/ IPv6 toeplitz */ +#define RCV_CONFIG_TZIPV6 0x01000000 +/* Include TCP port w/ IPv4 toeplitz */ +#define RCV_CONFIG_TZIPV4 0x00800000 +#define RCV_CONFIG_FLUSH 0x00400000 /* Flush buffers */ +#define RCV_CONFIG_PRIORITY_MASK 0x00300000 /* Priority level */ +#define RCV_CONFIG_CONN_MASK 0x000C0000 /* Number of connections */ +#define RCV_CONFIG_CONN_4K 0x00000000 /* 4k connections */ +#define RCV_CONFIG_CONN_2K 0x00040000 /* 2k connections */ +#define RCV_CONFIG_CONN_1K 0x00080000 /* 1k connections */ +#define RCV_CONFIG_CONN_512 0x000C0000 /* 512 connections */ +#define RCV_CONFIG_HASH_MASK 0x00030000 /* Hash depth */ +#define RCV_CONFIG_HASH_8 0x00000000 /* Hash depth 8 */ +#define RCV_CONFIG_HASH_16 0x00010000 /* Hash depth 16 */ +#define RCV_CONFIG_HASH_4 0x00020000 /* Hash depth 4 */ +#define RCV_CONFIG_HASH_2 0x00030000 /* Hash depth 2 */ +/* Buffer length bits 15:4. ie multiple of 16. */ +#define RCV_CONFIG_BUFLEN_MASK 0x0000FFE0 +/* Disable socket detection on attn */ +#define RCV_CONFIG_SKT_DIS 0x00000008 +#define RCV_CONFIG_HIPRICTL 0x00000002 /* Ctrl frames on high-prioirty RcvQ */ +#define RCV_CONFIG_NEWSTATUSFMT 0x00000001 /* Use RevB status format */ +/* + * Macro to determine RCV_CONFIG_BUFLEN based on maximum frame size. + * We add 18 bytes for Sahara receive status and padding, plus 4 bytes for CRC, + * and round up to nearest 32 byte boundary + */ +#define RCV_CONFIG_BUFSIZE(_MaxFrame) \ + ((((_MaxFrame) + 22) + 31) & RCV_CONFIG_BUFLEN_MASK) -/*************************************************************************** - * A-XGMAC Registers - Occupy 0x80 - 0xD4 of the SXG_HW_REGS +/* XmtConfig register reset */ +#define XMT_CONFIG_RESET 0x80000000 +#define XMT_CONFIG_ENABLE 0x40000000 /* Enable transmit logic */ +/* Inhibit MAC RAM parity error */ +#define XMT_CONFIG_MAC_PARITY 0x20000000 +/* Inhibit D2F buffer parity error */ +#define XMT_CONFIG_BUF_PARITY 0x10000000 +/* Inhibit 1T SRAM parity error */ +#define XMT_CONFIG_MEM_PARITY 0x08000000 +#define XMT_CONFIG_INVERT_PARITY 0x04000000 /* Invert MAC RAM parity */ +#define XMT_CONFIG_INITIAL_IPID 0x0000FFFF /* Initial IPID */ + +/* + * A-XGMAC Registers - Occupy 0x80 - 0xD4 of the struct sxg_hw_regs * * Full register descriptions can be found in axgmac.pdf - ***************************************************************************/ -// A-XGMAC Configuration Register 0 -#define AXGMAC_CFG0_SUB_RESET 0x80000000 // Sub module reset -#define AXGMAC_CFG0_RCNTRL_RESET 0x00400000 // Receive control reset -#define AXGMAC_CFG0_RFUNC_RESET 0x00200000 // Receive function reset -#define AXGMAC_CFG0_TCNTRL_RESET 0x00040000 // Transmit control reset -#define AXGMAC_CFG0_TFUNC_RESET 0x00020000 // Transmit function reset -#define AXGMAC_CFG0_MII_RESET 0x00010000 // MII Management reset + */ +/* A-XGMAC Configuration Register 0 */ +#define AXGMAC_CFG0_SUB_RESET 0x80000000 /* Sub module reset */ +#define AXGMAC_CFG0_RCNTRL_RESET 0x00400000 /* Receive control reset */ +#define AXGMAC_CFG0_RFUNC_RESET 0x00200000 /* Receive function reset */ +#define AXGMAC_CFG0_TCNTRL_RESET 0x00040000 /* Transmit control reset */ +#define AXGMAC_CFG0_TFUNC_RESET 0x00020000 /* Transmit function reset */ +#define AXGMAC_CFG0_MII_RESET 0x00010000 /* MII Management reset */ -// A-XGMAC Configuration Register 1 -#define AXGMAC_CFG1_XMT_PAUSE 0x80000000 // Allow the sending of Pause frames -#define AXGMAC_CFG1_XMT_EN 0x40000000 // Enable transmit -#define AXGMAC_CFG1_RCV_PAUSE 0x20000000 // Allow the detection of Pause frames -#define AXGMAC_CFG1_RCV_EN 0x10000000 // Enable receive -#define AXGMAC_CFG1_XMT_STATE 0x04000000 // Current transmit state - READ ONLY -#define AXGMAC_CFG1_RCV_STATE 0x01000000 // Current receive state - READ ONLY -#define AXGMAC_CFG1_XOFF_SHORT 0x00001000 // Only pause for 64 slot on XOFF -#define AXGMAC_CFG1_XMG_FCS1 0x00000400 // Delay transmit FCS 1 4-byte word -#define AXGMAC_CFG1_XMG_FCS2 0x00000800 // Delay transmit FCS 2 4-byte words -#define AXGMAC_CFG1_XMG_FCS3 0x00000C00 // Delay transmit FCS 3 4-byte words -#define AXGMAC_CFG1_RCV_FCS1 0x00000100 // Delay receive FCS 1 4-byte word -#define AXGMAC_CFG1_RCV_FCS2 0x00000200 // Delay receive FCS 2 4-byte words -#define AXGMAC_CFG1_RCV_FCS3 0x00000300 // Delay receive FCS 3 4-byte words -#define AXGMAC_CFG1_PKT_OVERRIDE 0x00000080 // Per-packet override enable -#define AXGMAC_CFG1_SWAP 0x00000040 // Byte swap enable -#define AXGMAC_CFG1_SHORT_ASSERT 0x00000020 // ASSERT srdrpfrm on short frame (<64) -#define AXGMAC_CFG1_RCV_STRICT 0x00000010 // RCV only 802.3AE when CLEAR -#define AXGMAC_CFG1_CHECK_LEN 0x00000008 // Verify frame length -#define AXGMAC_CFG1_GEN_FCS 0x00000004 // Generate FCS -#define AXGMAC_CFG1_PAD_MASK 0x00000003 // Mask for pad bits -#define AXGMAC_CFG1_PAD_64 0x00000001 // Pad frames to 64 bytes -#define AXGMAC_CFG1_PAD_VLAN 0x00000002 // Detect VLAN and pad to 68 bytes -#define AXGMAC_CFG1_PAD_68 0x00000003 // Pad to 68 bytes +/* A-XGMAC Configuration Register 1 */ +/* Allow the sending of Pause frames */ +#define AXGMAC_CFG1_XMT_PAUSE 0x80000000 +#define AXGMAC_CFG1_XMT_EN 0x40000000 /* Enable transmit */ +/* Allow the detection of Pause frames */ +#define AXGMAC_CFG1_RCV_PAUSE 0x20000000 +#define AXGMAC_CFG1_RCV_EN 0x10000000 /* Enable receive */ +/* Current transmit state - READ ONLY */ +#define AXGMAC_CFG1_XMT_STATE 0x04000000 +/* Current receive state - READ ONLY */ +#define AXGMAC_CFG1_RCV_STATE 0x01000000 +/* Only pause for 64 slot on XOFF */ +#define AXGMAC_CFG1_XOFF_SHORT 0x00001000 +/* Delay transmit FCS 1 4-byte word */ +#define AXGMAC_CFG1_XMG_FCS1 0x00000400 +/* Delay transmit FCS 2 4-byte words */ +#define AXGMAC_CFG1_XMG_FCS2 0x00000800 +/* Delay transmit FCS 3 4-byte words */ +#define AXGMAC_CFG1_XMG_FCS3 0x00000C00 +/* Delay receive FCS 1 4-byte word */ +#define AXGMAC_CFG1_RCV_FCS1 0x00000100 +/* Delay receive FCS 2 4-byte words */ +#define AXGMAC_CFG1_RCV_FCS2 0x00000200 +/* Delay receive FCS 3 4-byte words */ +#define AXGMAC_CFG1_RCV_FCS3 0x00000300 +/* Per-packet override enable */ +#define AXGMAC_CFG1_PKT_OVERRIDE 0x00000080 +#define AXGMAC_CFG1_SWAP 0x00000040 /* Byte swap enable */ +/* ASSERT srdrpfrm on short frame (<64) */ +#define AXGMAC_CFG1_SHORT_ASSERT 0x00000020 +/* RCV only 802.3AE when CLEAR */ +#define AXGMAC_CFG1_RCV_STRICT 0x00000010 +#define AXGMAC_CFG1_CHECK_LEN 0x00000008 /* Verify frame length */ +#define AXGMAC_CFG1_GEN_FCS 0x00000004 /* Generate FCS */ +#define AXGMAC_CFG1_PAD_MASK 0x00000003 /* Mask for pad bits */ +#define AXGMAC_CFG1_PAD_64 0x00000001 /* Pad frames to 64 bytes */ +/* Detect VLAN and pad to 68 bytes */ +#define AXGMAC_CFG1_PAD_VLAN 0x00000002 +#define AXGMAC_CFG1_PAD_68 0x00000003 /* Pad to 68 bytes */ -// A-XGMAC Configuration Register 2 -#define AXGMAC_CFG2_GEN_PAUSE 0x80000000 // Generate single pause frame (test) -#define AXGMAC_CFG2_LF_MANUAL 0x08000000 // Manual link fault sequence -#define AXGMAC_CFG2_LF_AUTO 0x04000000 // Auto link fault sequence -#define AXGMAC_CFG2_LF_REMOTE 0x02000000 // Remote link fault (READ ONLY) -#define AXGMAC_CFG2_LF_LOCAL 0x01000000 // Local link fault (READ ONLY) -#define AXGMAC_CFG2_IPG_MASK 0x001F0000 // Inter packet gap +/* A-XGMAC Configuration Register 2 */ +/* Generate single pause frame (test) */ +#define AXGMAC_CFG2_GEN_PAUSE 0x80000000 +/* Manual link fault sequence */ +#define AXGMAC_CFG2_LF_MANUAL 0x08000000 +/* Auto link fault sequence */ +#define AXGMAC_CFG2_LF_AUTO 0x04000000 +/* Remote link fault (READ ONLY) */ +#define AXGMAC_CFG2_LF_REMOTE 0x02000000 +/* Local link fault (READ ONLY) */ +#define AXGMAC_CFG2_LF_LOCAL 0x01000000 +#define AXGMAC_CFG2_IPG_MASK 0x001F0000 /* Inter packet gap */ #define AXGMAC_CFG2_IPG_SHIFT 16 -#define AXGMAC_CFG2_PAUSE_XMT 0x00008000 // Pause transmit module -#define AXGMAC_CFG2_IPG_EXTEN 0x00000020 // Enable IPG extension algorithm -#define AXGMAC_CFG2_IPGEX_MASK 0x0000001F // IPG extension +#define AXGMAC_CFG2_PAUSE_XMT 0x00008000 /* Pause transmit module */ +/* Enable IPG extension algorithm */ +#define AXGMAC_CFG2_IPG_EXTEN 0x00000020 +#define AXGMAC_CFG2_IPGEX_MASK 0x0000001F /* IPG extension */ -// A-XGMAC Configuration Register 3 -#define AXGMAC_CFG3_RCV_DROP 0xFFFF0000 // Receive frame drop filter -#define AXGMAC_CFG3_RCV_DONT_CARE 0x0000FFFF // Receive frame don't care filter +/* A-XGMAC Configuration Register 3 */ +/* Receive frame drop filter */ +#define AXGMAC_CFG3_RCV_DROP 0xFFFF0000 +/* Receive frame don't care filter */ +#define AXGMAC_CFG3_RCV_DONT_CARE 0x0000FFFF -// A-XGMAC Station Address Register - Octets 1-4 -#define AXGMAC_SARLOW_OCTET_ONE 0xFF000000 // First octet -#define AXGMAC_SARLOW_OCTET_TWO 0x00FF0000 // Second octet -#define AXGMAC_SARLOW_OCTET_THREE 0x0000FF00 // Third octet -#define AXGMAC_SARLOW_OCTET_FOUR 0x000000FF // Fourth octet +/* A-XGMAC Station Address Register - Octets 1-4 */ +#define AXGMAC_SARLOW_OCTET_ONE 0xFF000000 /* First octet */ +#define AXGMAC_SARLOW_OCTET_TWO 0x00FF0000 /* Second octet */ +#define AXGMAC_SARLOW_OCTET_THREE 0x0000FF00 /* Third octet */ +#define AXGMAC_SARLOW_OCTET_FOUR 0x000000FF /* Fourth octet */ -// A-XGMAC Station Address Register - Octets 5-6 -#define AXGMAC_SARHIGH_OCTET_FIVE 0xFF000000 // Fifth octet -#define AXGMAC_SARHIGH_OCTET_SIX 0x00FF0000 // Sixth octet +/* A-XGMAC Station Address Register - Octets 5-6 */ +#define AXGMAC_SARHIGH_OCTET_FIVE 0xFF000000 /* Fifth octet */ +#define AXGMAC_SARHIGH_OCTET_SIX 0x00FF0000 /* Sixth octet */ -// A-XGMAC Maximum frame length register -#define AXGMAC_MAXFRAME_XMT 0x3FFF0000 // Maximum transmit frame length +/* A-XGMAC Maximum frame length register */ +/* Maximum transmit frame length */ +#define AXGMAC_MAXFRAME_XMT 0x3FFF0000 #define AXGMAC_MAXFRAME_XMT_SHIFT 16 -#define AXGMAC_MAXFRAME_RCV 0x0000FFFF // Maximum receive frame length -// This register doesn't need to be written for standard MTU. -// For jumbo, I'll just statically define the value here. This -// value sets the receive byte count to 9036 (0x234C) and the -// transmit WORD count to 2259 (0x8D3). These values include 22 -// bytes of padding beyond the jumbo MTU of 9014 +/* Maximum receive frame length */ +#define AXGMAC_MAXFRAME_RCV 0x0000FFFF +/* + * This register doesn't need to be written for standard MTU. + * For jumbo, I'll just statically define the value here. This + * value sets the receive byte count to 9036 (0x234C) and the + * transmit WORD count to 2259 (0x8D3). These values include 22 + * bytes of padding beyond the jumbo MTU of 9014 + */ #define AXGMAC_MAXFRAME_JUMBO 0x08D3234C -// A-XGMAC Revision level -#define AXGMAC_REVISION_MASK 0x0000FFFF // Revision level +/* A-XGMAC Revision level */ +#define AXGMAC_REVISION_MASK 0x0000FFFF /* Revision level */ -// A-XGMAC AMIIM Command Register -#define AXGMAC_AMIIM_CMD_START 0x00000008 // Command start -#define AXGMAC_AMIIM_CMD_MASK 0x00000007 // Command -#define AXGMAC_AMIIM_CMD_LEGACY_WRITE 1 // 10/100/1000 Mbps Phy Write -#define AXGMAC_AMIIM_CMD_LEGACY_READ 2 // 10/100/1000 Mbps Phy Read -#define AXGMAC_AMIIM_CMD_MONITOR_SINGLE 3 // Monitor single PHY -#define AXGMAC_AMIIM_CMD_MONITOR_MULTIPLE 4 // Monitor multiple contiguous PHYs -#define AXGMAC_AMIIM_CMD_10G_OPERATION 5 // Present AMIIM Field Reg -#define AXGMAC_AMIIM_CMD_CLEAR_LINK_FAIL 6 // Clear Link Fail Bit in MIIM +/* A-XGMAC AMIIM Command Register */ +#define AXGMAC_AMIIM_CMD_START 0x00000008 /* Command start */ +#define AXGMAC_AMIIM_CMD_MASK 0x00000007 /* Command */ +/* 10/100/1000 Mbps Phy Write */ +#define AXGMAC_AMIIM_CMD_LEGACY_WRITE 1 +/* 10/100/1000 Mbps Phy Read */ +#define AXGMAC_AMIIM_CMD_LEGACY_READ 2 +#define AXGMAC_AMIIM_CMD_MONITOR_SINGLE 3 /* Monitor single PHY */ +/* Monitor multiple contiguous PHYs */ +#define AXGMAC_AMIIM_CMD_MONITOR_MULTIPLE 4 +/* Present AMIIM Field Reg */ +#define AXGMAC_AMIIM_CMD_10G_OPERATION 5 +/* Clear Link Fail Bit in MIIM */ +#define AXGMAC_AMIIM_CMD_CLEAR_LINK_FAIL 6 -// A-XGMAC AMIIM Field Register -#define AXGMAC_AMIIM_FIELD_ST 0xC0000000 // 2-bit ST field +/* A-XGMAC AMIIM Field Register */ +#define AXGMAC_AMIIM_FIELD_ST 0xC0000000 /* 2-bit ST field */ #define AXGMAC_AMIIM_FIELD_ST_SHIFT 30 -#define AXGMAC_AMIIM_FIELD_OP 0x30000000 // 2-bit OP field +#define AXGMAC_AMIIM_FIELD_OP 0x30000000 /* 2-bit OP field */ #define AXGMAC_AMIIM_FIELD_OP_SHIFT 28 -#define AXGMAC_AMIIM_FIELD_PORT_ADDR 0x0F800000 // Port address field (hstphyadx in spec) +/* Port address field (hstphyadx in spec) */ +#define AXGMAC_AMIIM_FIELD_PORT_ADDR 0x0F800000 #define AXGMAC_AMIIM_FIELD_PORT_SHIFT 23 -#define AXGMAC_AMIIM_FIELD_DEV_ADDR 0x007C0000 // Device address field (hstregadx in spec) +/* Device address field (hstregadx in spec) */ +#define AXGMAC_AMIIM_FIELD_DEV_ADDR 0x007C0000 #define AXGMAC_AMIIM_FIELD_DEV_SHIFT 18 -#define AXGMAC_AMIIM_FIELD_TA 0x00030000 // 2-bit TA field +#define AXGMAC_AMIIM_FIELD_TA 0x00030000 /* 2-bit TA field */ #define AXGMAC_AMIIM_FIELD_TA_SHIFT 16 -#define AXGMAC_AMIIM_FIELD_DATA 0x0000FFFF // Data field +#define AXGMAC_AMIIM_FIELD_DATA 0x0000FFFF /* Data field */ -// Values for the AXGMAC_AMIIM_FIELD_OP field in the A-XGMAC AMIIM Field Register -#define MIIM_OP_ADDR 0 // MIIM Address set operation -#define MIIM_OP_WRITE 1 // MIIM Write register operation -#define MIIM_OP_READ 2 // MIIM Read register operation +/* Values for the AXGMAC_AMIIM_FIELD_OP field in the A-XGMAC AMIIM Field Register */ +#define MIIM_OP_ADDR 0 /* MIIM Address set operation */ +#define MIIM_OP_WRITE 1 /* MIIM Write register operation */ +#define MIIM_OP_READ 2 /* MIIM Read register operation */ #define MIIM_OP_ADDR_SHIFT (MIIM_OP_ADDR << AXGMAC_AMIIM_FIELD_OP_SHIFT) -// Values for the AXGMAC_AMIIM_FIELD_PORT_ADDR field in the A-XGMAC AMIIM Field Register -#define MIIM_PORT_NUM 1 // All Sahara MIIM modules use port 1 +/* + * Values for the AXGMAC_AMIIM_FIELD_PORT_ADDR field in the A-XGMAC AMIIM + * Field Register + */ +#define MIIM_PORT_NUM 1 /* All Sahara MIIM modules use port 1 */ -// Values for the AXGMAC_AMIIM_FIELD_DEV_ADDR field in the A-XGMAC AMIIM Field Register -#define MIIM_DEV_PHY_PMA 1 // PHY PMA/PMD module MIIM device number -#define MIIM_DEV_PHY_PCS 3 // PHY PCS module MIIM device number -#define MIIM_DEV_PHY_XS 4 // PHY XS module MIIM device number -#define MIIM_DEV_XGXS 5 // XGXS MIIM device number +/* + * Values for the AXGMAC_AMIIM_FIELD_DEV_ADDR field in the A-XGMAC AMIIM + * Field Register + */ +/* PHY PMA/PMD module MIIM device number */ +#define MIIM_DEV_PHY_PMA 1 +/* PHY PCS module MIIM device number */ +#define MIIM_DEV_PHY_PCS 3 +/* PHY XS module MIIM device number */ +#define MIIM_DEV_PHY_XS 4 +#define MIIM_DEV_XGXS 5 /* XGXS MIIM device number */ -// Values for the AXGMAC_AMIIM_FIELD_TA field in the A-XGMAC AMIIM Field Register -#define MIIM_TA_10GB 2 // set to 2 for 10 GB operation +/* + * Values for the AXGMAC_AMIIM_FIELD_TA field in the A-XGMAC AMIIM Field + * Register + */ +#define MIIM_TA_10GB 2 /* set to 2 for 10 GB operation */ -// A-XGMAC AMIIM Configuration Register -#define AXGMAC_AMIIM_CFG_NOPREAM 0x00000080 // Bypass preamble of mngmt frame -#define AXGMAC_AMIIM_CFG_HALF_CLOCK 0x0000007F // half-clock duration of MDC output +/* A-XGMAC AMIIM Configuration Register */ +/* Bypass preamble of mngmt frame */ +#define AXGMAC_AMIIM_CFG_NOPREAM 0x00000080 +/* half-clock duration of MDC output */ +#define AXGMAC_AMIIM_CFG_HALF_CLOCK 0x0000007F -// A-XGMAC AMIIM Indicator Register -#define AXGMAC_AMIIM_INDC_LINK 0x00000010 // Link status from legacy PHY or MMD -#define AXGMAC_AMIIM_INDC_MPHY 0x00000008 // Multiple phy operation in progress -#define AXGMAC_AMIIM_INDC_SPHY 0x00000004 // Single phy operation in progress -#define AXGMAC_AMIIM_INDC_MON 0x00000002 // Single or multiple monitor cmd -#define AXGMAC_AMIIM_INDC_BUSY 0x00000001 // Set until cmd operation complete +/* A-XGMAC AMIIM Indicator Register */ +/* Link status from legacy PHY or MMD */ +#define AXGMAC_AMIIM_INDC_LINK 0x00000010 +/* Multiple phy operation in progress */ +#define AXGMAC_AMIIM_INDC_MPHY 0x00000008 +/* Single phy operation in progress */ +#define AXGMAC_AMIIM_INDC_SPHY 0x00000004 +/* Single or multiple monitor cmd */ +#define AXGMAC_AMIIM_INDC_MON 0x00000002 +/* Set until cmd operation complete */ +#define AXGMAC_AMIIM_INDC_BUSY 0x00000001 -// Link Status and Control Register -#define LS_PHY_CLR_RESET 0x80000000 // Clear reset signal to PHY -#define LS_SERDES_POWER_DOWN 0x40000000 // Power down the Sahara Serdes -#define LS_XGXS_ENABLE 0x20000000 // Enable the XAUI XGXS logic -#define LS_XGXS_CTL 0x10000000 // Hold XAUI XGXS logic reset until Serdes is up -#define LS_SERDES_DOWN 0x08000000 // When 0, XAUI Serdes is up and initialization is complete -#define LS_TRACE_DOWN 0x04000000 // When 0, Trace Serdes is up and initialization is complete -#define LS_PHY_CLK_25MHZ 0x02000000 // Set PHY clock to 25 MHz (else 156.125 MHz) -#define LS_PHY_CLK_EN 0x01000000 // Enable clock to PHY -#define LS_XAUI_LINK_UP 0x00000010 // XAUI link is up -#define LS_XAUI_LINK_CHNG 0x00000008 // XAUI link status has changed -#define LS_LINK_ALARM 0x00000004 // Link alarm pin -#define LS_ATTN_CTRL_MASK 0x00000003 // Mask link attention control bits -#define LS_ATTN_ALARM 0x00000000 // 00 => Attn on link alarm -#define LS_ATTN_ALARM_OR_STAT_CHNG 0x00000001 // 01 => Attn on link alarm or status change -#define LS_ATTN_STAT_CHNG 0x00000002 // 10 => Attn on link status change -#define LS_ATTN_NONE 0x00000003 // 11 => no Attn +/* Link Status and Control Register */ +#define LS_PHY_CLR_RESET 0x80000000 /* Clear reset signal to PHY */ +#define LS_SERDES_POWER_DOWN 0x40000000 /* Power down the Sahara Serdes */ +#define LS_XGXS_ENABLE 0x20000000 /* Enable the XAUI XGXS logic */ +/* Hold XAUI XGXS logic reset until Serdes is up */ +#define LS_XGXS_CTL 0x10000000 +/* When 0, XAUI Serdes is up and initialization is complete */ +#define LS_SERDES_DOWN 0x08000000 +/* When 0, Trace Serdes is up and initialization is complete */ +#define LS_TRACE_DOWN 0x04000000 +/* Set PHY clock to 25 MHz (else 156.125 MHz) */ +#define LS_PHY_CLK_25MHZ 0x02000000 +#define LS_PHY_CLK_EN 0x01000000 /* Enable clock to PHY */ +#define LS_XAUI_LINK_UP 0x00000010 /* XAUI link is up */ +/* XAUI link status has changed */ +#define LS_XAUI_LINK_CHNG 0x00000008 +#define LS_LINK_ALARM 0x00000004 /* Link alarm pin */ +/* Mask link attention control bits */ +#define LS_ATTN_CTRL_MASK 0x00000003 +#define LS_ATTN_ALARM 0x00000000 /* 00 => Attn on link alarm */ +/* 01 => Attn on link alarm or status change */ +#define LS_ATTN_ALARM_OR_STAT_CHNG 0x00000001 +/* 10 => Attn on link status change */ +#define LS_ATTN_STAT_CHNG 0x00000002 +#define LS_ATTN_NONE 0x00000003 /* 11 => no Attn */ -// Link Address High Registers -#define LINK_ADDR_ENABLE 0x80000000 // Enable this link address +/* Link Address High Registers */ +#define LINK_ADDR_ENABLE 0x80000000 /* Enable this link address */ -/*************************************************************************** +/* * XGXS XAUI XGMII Extender registers * * Full register descriptions can be found in mxgxs.pdf - ***************************************************************************/ -// XGXS Register Map -#define XGXS_ADDRESS_CONTROL1 0x0000 // XS Control 1 -#define XGXS_ADDRESS_STATUS1 0x0001 // XS Status 1 -#define XGXS_ADDRESS_DEVID_LOW 0x0002 // XS Device ID (low) -#define XGXS_ADDRESS_DEVID_HIGH 0x0003 // XS Device ID (high) -#define XGXS_ADDRESS_SPEED 0x0004 // XS Speed ability -#define XGXS_ADDRESS_DEV_LOW 0x0005 // XS Devices in package -#define XGXS_ADDRESS_DEV_HIGH 0x0006 // XS Devices in package -#define XGXS_ADDRESS_STATUS2 0x0008 // XS Status 2 -#define XGXS_ADDRESS_PKGID_lOW 0x000E // XS Package Identifier -#define XGXS_ADDRESS_PKGID_HIGH 0x000F // XS Package Identifier -#define XGXS_ADDRESS_LANE_STATUS 0x0018 // 10G XGXS Lane Status -#define XGXS_ADDRESS_TEST_CTRL 0x0019 // 10G XGXS Test Control -#define XGXS_ADDRESS_RESET_LO1 0x8000 // Vendor-Specific Reset Lo 1 -#define XGXS_ADDRESS_RESET_LO2 0x8001 // Vendor-Specific Reset Lo 2 -#define XGXS_ADDRESS_RESET_HI1 0x8002 // Vendor-Specific Reset Hi 1 -#define XGXS_ADDRESS_RESET_HI2 0x8003 // Vendor-Specific Reset Hi 2 + */ +/* XGXS Register Map */ +#define XGXS_ADDRESS_CONTROL1 0x0000 /* XS Control 1 */ +#define XGXS_ADDRESS_STATUS1 0x0001 /* XS Status 1 */ +#define XGXS_ADDRESS_DEVID_LOW 0x0002 /* XS Device ID (low) */ +#define XGXS_ADDRESS_DEVID_HIGH 0x0003 /* XS Device ID (high) */ +#define XGXS_ADDRESS_SPEED 0x0004 /* XS Speed ability */ +#define XGXS_ADDRESS_DEV_LOW 0x0005 /* XS Devices in package */ +#define XGXS_ADDRESS_DEV_HIGH 0x0006 /* XS Devices in package */ +#define XGXS_ADDRESS_STATUS2 0x0008 /* XS Status 2 */ +#define XGXS_ADDRESS_PKGID_lOW 0x000E /* XS Package Identifier */ +#define XGXS_ADDRESS_PKGID_HIGH 0x000F /* XS Package Identifier */ +#define XGXS_ADDRESS_LANE_STATUS 0x0018 /* 10G XGXS Lane Status */ +#define XGXS_ADDRESS_TEST_CTRL 0x0019 /* 10G XGXS Test Control */ +#define XGXS_ADDRESS_RESET_LO1 0x8000 /* Vendor-Specific Reset Lo 1 */ +#define XGXS_ADDRESS_RESET_LO2 0x8001 /* Vendor-Specific Reset Lo 2 */ +#define XGXS_ADDRESS_RESET_HI1 0x8002 /* Vendor-Specific Reset Hi 1 */ +#define XGXS_ADDRESS_RESET_HI2 0x8003 /* Vendor-Specific Reset Hi 2 */ -// XS Control 1 register bit definitions -#define XGXS_CONTROL1_RESET 0x8000 // Reset - self clearing -#define XGXS_CONTROL1_LOOPBACK 0x4000 // Enable loopback -#define XGXS_CONTROL1_SPEED1 0x2000 // 0 = unspecified, 1 = 10Gb+ -#define XGXS_CONTROL1_LOWPOWER 0x0400 // 1 = Low power mode -#define XGXS_CONTROL1_SPEED2 0x0040 // Same as SPEED1 (?) -#define XGXS_CONTROL1_SPEED 0x003C // Everything reserved except zero (?) +/* XS Control 1 register bit definitions */ +#define XGXS_CONTROL1_RESET 0x8000 /* Reset - self clearing */ +#define XGXS_CONTROL1_LOOPBACK 0x4000 /* Enable loopback */ +#define XGXS_CONTROL1_SPEED1 0x2000 /* 0 = unspecified, 1 = 10Gb+ */ +#define XGXS_CONTROL1_LOWPOWER 0x0400 /* 1 = Low power mode */ +#define XGXS_CONTROL1_SPEED2 0x0040 /* Same as SPEED1 (?) */ +/* Everything reserved except zero (?) */ +#define XGXS_CONTROL1_SPEED 0x003C -// XS Status 1 register bit definitions -#define XGXS_STATUS1_FAULT 0x0080 // Fault detected -#define XGXS_STATUS1_LINK 0x0004 // 1 = Link up -#define XGXS_STATUS1_LOWPOWER 0x0002 // 1 = Low power supported +/* XS Status 1 register bit definitions */ +#define XGXS_STATUS1_FAULT 0x0080 /* Fault detected */ +#define XGXS_STATUS1_LINK 0x0004 /* 1 = Link up */ +#define XGXS_STATUS1_LOWPOWER 0x0002 /* 1 = Low power supported */ -// XS Speed register bit definitions -#define XGXS_SPEED_10G 0x0001 // 1 = 10G capable +/* XS Speed register bit definitions */ +#define XGXS_SPEED_10G 0x0001 /* 1 = 10G capable */ -// XS Devices register bit definitions -#define XGXS_DEVICES_DTE 0x0020 // DTE XS Present -#define XGXS_DEVICES_PHY 0x0010 // PHY XS Present -#define XGXS_DEVICES_PCS 0x0008 // PCS Present -#define XGXS_DEVICES_WIS 0x0004 // WIS Present -#define XGXS_DEVICES_PMD 0x0002 // PMD/PMA Present -#define XGXS_DEVICES_CLAUSE22 0x0001 // Clause 22 registers present +/* XS Devices register bit definitions */ +#define XGXS_DEVICES_DTE 0x0020 /* DTE XS Present */ +#define XGXS_DEVICES_PHY 0x0010 /* PHY XS Present */ +#define XGXS_DEVICES_PCS 0x0008 /* PCS Present */ +#define XGXS_DEVICES_WIS 0x0004 /* WIS Present */ +#define XGXS_DEVICES_PMD 0x0002 /* PMD/PMA Present */ +#define XGXS_DEVICES_CLAUSE22 0x0001 /* Clause 22 registers present*/ -// XS Devices High register bit definitions -#define XGXS_DEVICES_VENDOR2 0x8000 // Vendor specific device 2 -#define XGXS_DEVICES_VENDOR1 0x4000 // Vendor specific device 1 +/* XS Devices High register bit definitions */ +#define XGXS_DEVICES_VENDOR2 0x8000 /* Vendor specific device 2 */ +#define XGXS_DEVICES_VENDOR1 0x4000 /* Vendor specific device 1 */ -// XS Status 2 register bit definitions -#define XGXS_STATUS2_DEV_MASK 0xC000 // Device present mask -#define XGXS_STATUS2_DEV_RESPOND 0x8000 // Device responding -#define XGXS_STATUS2_XMT_FAULT 0x0800 // Transmit fault -#define XGXS_STATUS2_RCV_FAULT 0x0400 // Receive fault +/* XS Status 2 register bit definitions */ +#define XGXS_STATUS2_DEV_MASK 0xC000 /* Device present mask */ +#define XGXS_STATUS2_DEV_RESPOND 0x8000 /* Device responding */ +#define XGXS_STATUS2_XMT_FAULT 0x0800 /* Transmit fault */ +#define XGXS_STATUS2_RCV_FAULT 0x0400 /* Receive fault */ -// XS Package ID High register bit definitions -#define XGXS_PKGID_HIGH_ORG 0xFC00 // Organizationally Unique -#define XGXS_PKGID_HIGH_MFG 0x03F0 // Manufacturer Model -#define XGXS_PKGID_HIGH_REV 0x000F // Revision Number +/* XS Package ID High register bit definitions */ +#define XGXS_PKGID_HIGH_ORG 0xFC00 /* Organizationally Unique */ +#define XGXS_PKGID_HIGH_MFG 0x03F0 /* Manufacturer Model */ +#define XGXS_PKGID_HIGH_REV 0x000F /* Revision Number */ -// XS Lane Status register bit definitions -#define XGXS_LANE_PHY 0x1000 // PHY/DTE lane alignment status -#define XGXS_LANE_PATTERN 0x0800 // Pattern testing ability -#define XGXS_LANE_LOOPBACK 0x0400 // PHY loopback ability -#define XGXS_LANE_SYNC3 0x0008 // Lane 3 sync -#define XGXS_LANE_SYNC2 0x0004 // Lane 2 sync -#define XGXS_LANE_SYNC1 0x0002 // Lane 1 sync -#define XGXS_LANE_SYNC0 0x0001 // Lane 0 sync +/* XS Lane Status register bit definitions */ +#define XGXS_LANE_PHY 0x1000 /* PHY/DTE lane alignment status */ +#define XGXS_LANE_PATTERN 0x0800 /* Pattern testing ability */ +#define XGXS_LANE_LOOPBACK 0x0400 /* PHY loopback ability */ +#define XGXS_LANE_SYNC3 0x0008 /* Lane 3 sync */ +#define XGXS_LANE_SYNC2 0x0004 /* Lane 2 sync */ +#define XGXS_LANE_SYNC1 0x0002 /* Lane 1 sync */ +#define XGXS_LANE_SYNC0 0x0001 /* Lane 0 sync */ -// XS Test Control register bit definitions -#define XGXS_TEST_PATTERN_ENABLE 0x0004 // Test pattern enabled -#define XGXS_TEST_PATTERN_MASK 0x0003 // Test patterns -#define XGXS_TEST_PATTERN_RSVD 0x0003 // Test pattern - reserved -#define XGXS_TEST_PATTERN_MIX 0x0002 // Test pattern - mixed -#define XGXS_TEST_PATTERN_LOW 0x0001 // Test pattern - low -#define XGXS_TEST_PATTERN_HIGH 0x0001 // Test pattern - high +/* XS Test Control register bit definitions */ +#define XGXS_TEST_PATTERN_ENABLE 0x0004 /* Test pattern enabled */ +#define XGXS_TEST_PATTERN_MASK 0x0003 /* Test patterns */ +#define XGXS_TEST_PATTERN_RSVD 0x0003 /* Test pattern - reserved */ +#define XGXS_TEST_PATTERN_MIX 0x0002 /* Test pattern - mixed */ +#define XGXS_TEST_PATTERN_LOW 0x0001 /* Test pattern - low */ +#define XGXS_TEST_PATTERN_HIGH 0x0001 /* Test pattern - high */ -/*************************************************************************** +/* * External MDIO Bus Registers * * Full register descriptions can be found in PHY/XENPAK/IEEE specs - ***************************************************************************/ -// LASI (Link Alarm Status Interrupt) Registers (located in MIIM_DEV_PHY_PMA device) -#define LASI_RX_ALARM_CONTROL 0x9000 // LASI RX_ALARM Control -#define LASI_TX_ALARM_CONTROL 0x9001 // LASI TX_ALARM Control -#define LASI_CONTROL 0x9002 // LASI Control -#define LASI_RX_ALARM_STATUS 0x9003 // LASI RX_ALARM Status -#define LASI_TX_ALARM_STATUS 0x9004 // LASI TX_ALARM Status -#define LASI_STATUS 0x9005 // LASI Status + */ +/* + * LASI (Link Alarm Status Interrupt) Registers (located in + * MIIM_DEV_PHY_PMA device) + */ +#define LASI_RX_ALARM_CONTROL 0x9000 /* LASI RX_ALARM Control */ +#define LASI_TX_ALARM_CONTROL 0x9001 /* LASI TX_ALARM Control */ +#define LASI_CONTROL 0x9002 /* LASI Control */ +#define LASI_RX_ALARM_STATUS 0x9003 /* LASI RX_ALARM Status */ +#define LASI_TX_ALARM_STATUS 0x9004 /* LASI TX_ALARM Status */ +#define LASI_STATUS 0x9005 /* LASI Status */ -// LASI_CONTROL bit definitions -#define LASI_CTL_RX_ALARM_ENABLE 0x0004 // Enable RX_ALARM interrupts -#define LASI_CTL_TX_ALARM_ENABLE 0x0002 // Enable TX_ALARM interrupts -#define LASI_CTL_LS_ALARM_ENABLE 0x0001 // Enable Link Status interrupts +/* LASI_CONTROL bit definitions */ +/* Enable RX_ALARM interrupts */ +#define LASI_CTL_RX_ALARM_ENABLE 0x0004 +/* Enable TX_ALARM interrupts */ +#define LASI_CTL_TX_ALARM_ENABLE 0x0002 +/* Enable Link Status interrupts */ +#define LASI_CTL_LS_ALARM_ENABLE 0x0001 -// LASI_STATUS bit definitions -#define LASI_STATUS_RX_ALARM 0x0004 // RX_ALARM status -#define LASI_STATUS_TX_ALARM 0x0002 // TX_ALARM status -#define LASI_STATUS_LS_ALARM 0x0001 // Link Status +/* LASI_STATUS bit definitions */ +#define LASI_STATUS_RX_ALARM 0x0004 /* RX_ALARM status */ +#define LASI_STATUS_TX_ALARM 0x0002 /* TX_ALARM status */ +#define LASI_STATUS_LS_ALARM 0x0001 /* Link Status */ -// PHY registers - PMA/PMD (device 1) -#define PHY_PMA_CONTROL1 0x0000 // PMA/PMD Control 1 -#define PHY_PMA_STATUS1 0x0001 // PMA/PMD Status 1 -#define PHY_PMA_RCV_DET 0x000A // PMA/PMD Receive Signal Detect - // other PMA/PMD registers exist and can be defined as needed +/* PHY registers - PMA/PMD (device 1) */ +#define PHY_PMA_CONTROL1 0x0000 /* PMA/PMD Control 1 */ +#define PHY_PMA_STATUS1 0x0001 /* PMA/PMD Status 1 */ +#define PHY_PMA_RCV_DET 0x000A /* PMA/PMD Receive Signal Detect */ + /* other PMA/PMD registers exist and can be defined as needed */ -// PHY registers - PCS (device 3) -#define PHY_PCS_CONTROL1 0x0000 // PCS Control 1 -#define PHY_PCS_STATUS1 0x0001 // PCS Status 1 -#define PHY_PCS_10G_STATUS1 0x0020 // PCS 10GBASE-R Status 1 - // other PCS registers exist and can be defined as needed +/* PHY registers - PCS (device 3) */ +#define PHY_PCS_CONTROL1 0x0000 /* PCS Control 1 */ +#define PHY_PCS_STATUS1 0x0001 /* PCS Status 1 */ +#define PHY_PCS_10G_STATUS1 0x0020 /* PCS 10GBASE-R Status 1 */ + /* other PCS registers exist and can be defined as needed */ -// PHY registers - XS (device 4) -#define PHY_XS_CONTROL1 0x0000 // XS Control 1 -#define PHY_XS_STATUS1 0x0001 // XS Status 1 -#define PHY_XS_LANE_STATUS 0x0018 // XS Lane Status - // other XS registers exist and can be defined as needed +/* PHY registers - XS (device 4) */ +#define PHY_XS_CONTROL1 0x0000 /* XS Control 1 */ +#define PHY_XS_STATUS1 0x0001 /* XS Status 1 */ +#define PHY_XS_LANE_STATUS 0x0018 /* XS Lane Status */ + /* other XS registers exist and can be defined as needed */ -// PHY_PMA_CONTROL1 register bit definitions -#define PMA_CONTROL1_RESET 0x8000 // PMA/PMD reset +/* PHY_PMA_CONTROL1 register bit definitions */ +#define PMA_CONTROL1_RESET 0x8000 /* PMA/PMD reset */ -// PHY_PMA_RCV_DET register bit definitions -#define PMA_RCV_DETECT 0x0001 // PMA/PMD receive signal detect +/* PHY_PMA_RCV_DET register bit definitions */ +#define PMA_RCV_DETECT 0x0001 /* PMA/PMD receive signal detect */ -// PHY_PCS_10G_STATUS1 register bit definitions -#define PCS_10B_BLOCK_LOCK 0x0001 // PCS 10GBASE-R locked to receive blocks +/* PHY_PCS_10G_STATUS1 register bit definitions */ +#define PCS_10B_BLOCK_LOCK 0x0001 /* PCS 10GBASE-R locked to receive blocks */ -// PHY_XS_LANE_STATUS register bit definitions -#define XS_LANE_ALIGN 0x1000 // XS transmit lanes aligned +/* PHY_XS_LANE_STATUS register bit definitions */ +#define XS_LANE_ALIGN 0x1000 /* XS transmit lanes aligned */ -// PHY Microcode download data structure -struct PHY_UCODE { +#define XCVR_VENDOR_LEN 16 /* xcvr vendor len */ +#define XCVR_MODEL_LEN 16 /* xcvr model len */ + +/* PHY Microcode download data structure */ +struct phy_ucode { ushort Addr; ushort Data; }; +/* Slow Bus Register Definitions */ -/***************************************************************************** +/* Module 0 registers */ +#define GPIO_L_IN 0x15 /* GPIO input (low) */ +#define GPIO_L_OUT 0x16 /* GPIO output (low) */ +#define GPIO_L_DIR 0x17 /* GPIO direction (low) */ +#define GPIO_H_IN 0x19 /* GPIO input (high) */ +#define GPIO_H_OUT 0x1A /* GPIO output (high) */ +#define GPIO_H_DIR 0x1B /* GPIO direction (high) */ + +/* Definitions for other slow bus registers can be added as needed */ + + +/* * Transmit Sequencer Command Descriptor definitions - *****************************************************************************/ - -// This descriptor must be placed in GRAM. The address of this descriptor -// (along with a couple of control bits) is pushed onto the PxhCmdQ or PxlCmdQ -// (Proxy high or low command queue). This data is read by the Proxy Sequencer, -// which pushes it onto the XmtCmdQ, which is (eventually) read by the Transmit -// Sequencer, causing a packet to be transmitted. Not all fields are valid for -// all commands - see the Sahara spec for details. Note that this structure is -// only valid when compiled on a little endian machine. + * + * This descriptor must be placed in GRAM. The address of this descriptor + * (along with a couple of control bits) is pushed onto the PxhCmdQ or PxlCmdQ + * (Proxy high or low command queue). This data is read by the Proxy Sequencer, + * which pushes it onto the XmtCmdQ, which is (eventually) read by the Transmit + * Sequencer, causing a packet to be transmitted. Not all fields are valid for + * all commands - see the Sahara spec for details. Note that this structure is + * only valid when compiled on a little endian machine. + */ #pragma pack(push, 1) -struct XMT_DESC { - ushort XmtLen; // word 0, bits [15:0] - transmit length - unsigned char XmtCtl; // word 0, bits [23:16] - transmit control byte - unsigned char Cmd; // word 0, bits [31:24] - transmit command plus misc. - u32 XmtBufId; // word 1, bits [31:0] - transmit buffer ID - unsigned char TcpStrt; // word 2, bits [7:0] - byte address of TCP header - unsigned char IpStrt; // word 2, bits [15:8] - byte address of IP header - ushort IpCkSum; // word 2, bits [31:16] - partial IP checksum - ushort TcpCkSum; // word 3, bits [15:0] - partial TCP checksum - ushort Rsvd1; // word 3, bits [31:16] - PAD - u32 Rsvd2; // word 4, bits [31:0] - PAD - u32 Rsvd3; // word 5, bits [31:0] - PAD - u32 Rsvd4; // word 6, bits [31:0] - PAD - u32 Rsvd5; // word 7, bits [31:0] - PAD +struct xmt_desc { + ushort XmtLen; /* word 0, bits [15:0] - transmit length */ + /* word 0, bits [23:16] - transmit control byte */ + unsigned char XmtCtl; + /* word 0, bits [31:24] - transmit command plus misc. */ + unsigned char Cmd; + /* word 1, bits [31:0] - transmit buffer ID */ + u32 XmtBufId; + /* word 2, bits [7:0] - byte address of TCP header */ + unsigned char TcpStrt; + /* word 2, bits [15:8] - byte address of IP header */ + unsigned char IpStrt; + /* word 2, bits [31:16] - partial IP checksum */ + ushort IpCkSum; + /* word 3, bits [15:0] - partial TCP checksum */ + ushort TcpCkSum; + ushort Rsvd1; /* word 3, bits [31:16] - PAD */ + u32 Rsvd2; /* word 4, bits [31:0] - PAD */ + u32 Rsvd3; /* word 5, bits [31:0] - PAD */ + u32 Rsvd4; /* word 6, bits [31:0] - PAD */ + u32 Rsvd5; /* word 7, bits [31:0] - PAD */ }; #pragma pack(pop) -// XMT_DESC Cmd byte definitions - // command codes -#define XMT_DESC_CMD_RAW_SEND 0 // raw send descriptor -#define XMT_DESC_CMD_CSUM_INSERT 1 // checksum insert descriptor -#define XMT_DESC_CMD_FORMAT 2 // format descriptor -#define XMT_DESC_CMD_PRIME 3 // prime descriptor -#define XMT_DESC_CMD_CODE_SHFT 6 // comand code shift (shift to bits [31:30] in word 0) - // shifted command codes -#define XMT_RAW_SEND (XMT_DESC_CMD_RAW_SEND << XMT_DESC_CMD_CODE_SHFT) -#define XMT_CSUM_INSERT (XMT_DESC_CMD_CSUM_INSERT << XMT_DESC_CMD_CODE_SHFT) -#define XMT_FORMAT (XMT_DESC_CMD_FORMAT << XMT_DESC_CMD_CODE_SHFT) -#define XMT_PRIME (XMT_DESC_CMD_PRIME << XMT_DESC_CMD_CODE_SHFT) +/* struct xmt_desc Cmd byte definitions */ + /* command codes */ +#define XMT_DESC_CMD_RAW_SEND 0 /* raw send descriptor */ +#define XMT_DESC_CMD_CSUM_INSERT 1 /* checksum insert descriptor */ +#define XMT_DESC_CMD_FORMAT 2 /* format descriptor */ +#define XMT_DESC_CMD_PRIME 3 /* prime descriptor */ +/* comand code shift (shift to bits [31:30] in word 0) */ +#define XMT_DESC_CMD_CODE_SHFT 6 + /* shifted command codes */ +#define XMT_RAW_SEND (XMT_DESC_CMD_RAW_SEND << XMT_DESC_CMD_CODE_SHFT) +#define XMT_CSUM_INSERT (XMT_DESC_CMD_CSUM_INSERT << XMT_DESC_CMD_CODE_SHFT) +#define XMT_FORMAT (XMT_DESC_CMD_FORMAT << XMT_DESC_CMD_CODE_SHFT) +#define XMT_PRIME (XMT_DESC_CMD_PRIME << XMT_DESC_CMD_CODE_SHFT) -// XMT_DESC Control Byte (XmtCtl) definitions -// NOTE: These bits do not work on Sahara (Rev A)! -#define XMT_CTL_PAUSE_FRAME 0x80 // current frame is a pause control frame (for statistics) -#define XMT_CTL_CONTROL_FRAME 0x40 // current frame is a control frame (for statistics) -#define XMT_CTL_PER_PKT_QUAL 0x20 // per packet qualifier -#define XMT_CTL_PAD_MODE_NONE 0x00 // do not pad frame -#define XMT_CTL_PAD_MODE_64 0x08 // pad frame to 64 bytes -#define XMT_CTL_PAD_MODE_VLAN_68 0x10 // pad frame to 64 bytes, and VLAN frames to 68 bytes -#define XMT_CTL_PAD_MODE_68 0x18 // pad frame to 68 bytes -#define XMT_CTL_GEN_FCS 0x04 // generate FCS (CRC) for this frame -#define XMT_CTL_DELAY_FCS_0 0x00 // do not delay FCS calcution -#define XMT_CTL_DELAY_FCS_1 0x01 // delay FCS calculation by 1 (4-byte) word -#define XMT_CTL_DELAY_FCS_2 0x02 // delay FCS calculation by 2 (4-byte) words -#define XMT_CTL_DELAY_FCS_3 0x03 // delay FCS calculation by 3 (4-byte) words +/* + * struct xmt_desc Control Byte (XmtCtl) definitions + * NOTE: These bits do not work on Sahara (Rev A)! + */ +/* current frame is a pause control frame (for statistics) */ +#define XMT_CTL_PAUSE_FRAME 0x80 +/* current frame is a control frame (for statistics) */ +#define XMT_CTL_CONTROL_FRAME 0x40 +#define XMT_CTL_PER_PKT_QUAL 0x20 /* per packet qualifier */ +#define XMT_CTL_PAD_MODE_NONE 0x00 /* do not pad frame */ +#define XMT_CTL_PAD_MODE_64 0x08 /* pad frame to 64 bytes */ +/* pad frame to 64 bytes, and VLAN frames to 68 bytes */ +#define XMT_CTL_PAD_MODE_VLAN_68 0x10 +#define XMT_CTL_PAD_MODE_68 0x18 /* pad frame to 68 bytes */ +/* generate FCS (CRC) for this frame */ +#define XMT_CTL_GEN_FCS 0x04 +#define XMT_CTL_DELAY_FCS_0 0x00 /* do not delay FCS calcution */ +/* delay FCS calculation by 1 (4-byte) word */ +#define XMT_CTL_DELAY_FCS_1 0x01 +/* delay FCS calculation by 2 (4-byte) words */ +#define XMT_CTL_DELAY_FCS_2 0x02 +/* delay FCS calculation by 3 (4-byte) words */ +#define XMT_CTL_DELAY_FCS_3 0x03 -// XMT_DESC XmtBufId definition -#define XMT_BUF_ID_SHFT 8 // The Xmt buffer ID is formed by dividing - // the buffer (DRAM) address by 256 (or << 8) +/* struct xmt_desc XmtBufId definition */ +/* + * The Xmt buffer ID is formed by dividing the buffer (DRAM) address + * by 256 (or << 8) + */ -/***************************************************************************** - * Receiver Sequencer Definitions - *****************************************************************************/ +#define XMT_BUF_ID_SHFT 8 -// Receive Event Queue (queues 3 - 6) bit definitions -#define RCV_EVTQ_RBFID_MASK 0x0000FFFF // bit mask for the Receive Buffer ID +/* Receiver Sequencer Definitions */ -// Receive Buffer ID definition -#define RCV_BUF_ID_SHFT 5 // The Rcv buffer ID is formed by dividing - // the buffer (DRAM) address by 32 (or << 5) +/* Receive Event Queue (queues 3 - 6) bit definitions */ +/* bit mask for the Receive Buffer ID */ +#define RCV_EVTQ_RBFID_MASK 0x0000FFFF -// Format of the 18 byte Receive Buffer returned by the -// Receive Sequencer for received packets +/* Receive Buffer ID definition */ +/* + * The Rcv buffer ID is formed by dividing the buffer (DRAM) address + * by 32 (or << 5) + */ +#define RCV_BUF_ID_SHFT 5 + +/* + * Format of the 18 byte Receive Buffer returned by the + * Receive Sequencer for received packets + */ #pragma pack(push, 1) -struct RCV_BUF_HDR { - u32 Status; // Status word from Rcv Seq Parser - ushort Length; // Rcv packet byte count +struct rcv_buf_hdr { + u32 Status; /* Status word from Rcv Seq Parser */ + ushort Length; /* Rcv packet byte count */ union { - ushort TcpCsum; // TCP checksum + ushort TcpCsum; /* TCP checksum */ struct { - unsigned char TcpCsumL; // lower 8 bits of the TCP checksum - unsigned char LinkHash; // Link hash (multicast frames only) + /* lower 8 bits of the TCP checksum */ + unsigned char TcpCsumL; + /* Link hash (multicast frames only) */ + unsigned char LinkHash; }; }; - ushort SktHash; // Socket hash - unsigned char TcpHdrOffset; // TCP header offset into packet - unsigned char IpHdrOffset; // IP header offset into packet - u32 TpzHash; // Toeplitz hash - ushort Reserved; // Reserved + ushort SktHash; /* Socket hash */ + unsigned char TcpHdrOffset; /* TCP header offset into packet */ + unsigned char IpHdrOffset; /* IP header offset into packet */ + u32 TpzHash; /* Toeplitz hash */ + ushort Reserved; /* Reserved */ }; #pragma pack(pop) - -/***************************************************************************** - * Queue definitions - *****************************************************************************/ +/* Queue definitions */ /* Ingress (read only) queue numbers */ -#define PXY_BUF_Q 0 /* Proxy Buffer Queue */ -#define HST_EVT_Q 1 /* Host Event Queue */ -#define XMT_BUF_Q 2 /* Transmit Buffer Queue */ -#define SKT_EVL_Q 3 /* RcvSqr Socket Event Low Priority Queue */ -#define RCV_EVL_Q 4 /* RcvSqr Rcv Event Low Priority Queue */ -#define SKT_EVH_Q 5 /* RcvSqr Socket Event High Priority Queue */ -#define RCV_EVH_Q 6 /* RcvSqr Rcv Event High Priority Queue */ -#define DMA_RSP_Q 7 /* Dma Response Queue - one per CPU context */ +#define PXY_BUF_Q 0 /* Proxy Buffer Queue */ +#define HST_EVT_Q 1 /* Host Event Queue */ +#define XMT_BUF_Q 2 /* Transmit Buffer Queue */ +#define SKT_EVL_Q 3 /* RcvSqr Socket Event Low Priority Queue */ +#define RCV_EVL_Q 4 /* RcvSqr Rcv Event Low Priority Queue */ +#define SKT_EVH_Q 5 /* RcvSqr Socket Event High Priority Queue */ +#define RCV_EVH_Q 6 /* RcvSqr Rcv Event High Priority Queue */ +#define DMA_RSP_Q 7 /* Dma Response Queue - one per CPU context */ /* Local (read/write) queue numbers */ -#define LOCAL_A_Q 8 /* Spare local Queue */ -#define LOCAL_B_Q 9 /* Spare local Queue */ -#define LOCAL_C_Q 10 /* Spare local Queue */ -#define FSM_EVT_Q 11 /* Finite-State-Machine Event Queue */ -#define SBF_PAL_Q 12 /* System Buffer Physical Address (low) Queue */ -#define SBF_PAH_Q 13 /* System Buffer Physical Address (high) Queue */ -#define SBF_VAL_Q 14 /* System Buffer Virtual Address (low) Queue */ -#define SBF_VAH_Q 15 /* System Buffer Virtual Address (high) Queue */ +#define LOCAL_A_Q 8 /* Spare local Queue */ +#define LOCAL_B_Q 9 /* Spare local Queue */ +#define LOCAL_C_Q 10 /* Spare local Queue */ +#define FSM_EVT_Q 11 /* Finite-State-Machine Event Queue */ +#define SBF_PAL_Q 12 /* System Buffer Physical Address (low) Queue */ +#define SBF_PAH_Q 13 /* System Buffer Physical Address (high) Queue*/ +#define SBF_VAL_Q 14 /* System Buffer Virtual Address (low) Queue */ +#define SBF_VAH_Q 15 /* System Buffer Virtual Address (high) Queue */ /* Egress (write only) queue numbers */ -#define H2G_CMD_Q 16 /* Host to GlbRam DMA Command Queue */ -#define H2D_CMD_Q 17 /* Host to DRAM DMA Command Queue */ -#define G2H_CMD_Q 18 /* GlbRam to Host DMA Command Queue */ -#define G2D_CMD_Q 19 /* GlbRam to DRAM DMA Command Queue */ -#define D2H_CMD_Q 20 /* DRAM to Host DMA Command Queue */ -#define D2G_CMD_Q 21 /* DRAM to GlbRam DMA Command Queue */ -#define D2D_CMD_Q 22 /* DRAM to DRAM DMA Command Queue */ -#define PXL_CMD_Q 23 /* Low Priority Proxy Command Queue */ -#define PXH_CMD_Q 24 /* High Priority Proxy Command Queue */ -#define RSQ_CMD_Q 25 /* Receive Sequencer Command Queue */ -#define RCV_BUF_Q 26 /* Receive Buffer Queue */ +#define H2G_CMD_Q 16 /* Host to GlbRam DMA Command Queue */ +#define H2D_CMD_Q 17 /* Host to DRAM DMA Command Queue */ +#define G2H_CMD_Q 18 /* GlbRam to Host DMA Command Queue */ +#define G2D_CMD_Q 19 /* GlbRam to DRAM DMA Command Queue */ +#define D2H_CMD_Q 20 /* DRAM to Host DMA Command Queue */ +#define D2G_CMD_Q 21 /* DRAM to GlbRam DMA Command Queue */ +#define D2D_CMD_Q 22 /* DRAM to DRAM DMA Command Queue */ +#define PXL_CMD_Q 23 /* Low Priority Proxy Command Queue */ +#define PXH_CMD_Q 24 /* High Priority Proxy Command Queue */ +#define RSQ_CMD_Q 25 /* Receive Sequencer Command Queue */ +#define RCV_BUF_Q 26 /* Receive Buffer Queue */ /* Bit definitions for the Proxy Command queues (PXL_CMD_Q and PXH_CMD_Q) */ -#define PXY_COPY_EN 0x00200000 /* enable copy of xmt descriptor to xmt command queue */ -#define PXY_SIZE_16 0x00000000 /* copy 16 bytes */ -#define PXY_SIZE_32 0x00100000 /* copy 32 bytes */ +/* enable copy of xmt descriptor to xmt command queue */ +#define PXY_COPY_EN 0x00200000 +#define PXY_SIZE_16 0x00000000 /* copy 16 bytes */ +#define PXY_SIZE_32 0x00100000 /* copy 32 bytes */ + +/* SXG EEPROM/Flash Configuration Definitions */ + +/* Location of configuration data in EEPROM or Flash */ +/* start addr for config info in EEPROM */ +#define EEPROM_CONFIG_START_ADDR 0x00 +/* start addr for config info in Flash */ +#define FLASH_CONFIG_START_ADDR 0x80 + +/* Configuration data section defines */ +#define HW_CFG_SECTION_SIZE 512 /* size of H/W section */ +#define HW_CFG_SECTION_SIZE_A 256 /* size of H/W section (Sahara rev A) */ +/* starting location (offset) of S/W section */ +#define SW_CFG_SECTION_START 512 +/* starting location (offset) of S/W section (Sahara rev A) */ +#define SW_CFG_SECTION_START_A 256 +#define SW_CFG_SECTION_SIZE 128 /* size of S/W section */ +/* + * H/W configuration data magic word Goes in Addr field of first + * struct hw_cfg_data entry + */ +#define HW_CFG_MAGIC_WORD 0xA5A5 +/* + * H/W configuration data terminator Goes in Addr field of last + * struct hw_cfg_data entry + */ +#define HW_CFG_TERMINATOR 0xFFFF + +#define SW_CFG_MAGIC_WORD 0x5A5A /* S/W configuration data magic word */ -/***************************************************************************** - * SXG EEPROM/Flash Configuration Definitions - *****************************************************************************/ #pragma pack(push, 1) - -/* */ -struct HW_CFG_DATA { - ushort Addr; - union { - ushort Data; - ushort Checksum; - }; +/* + * Structure for an element of H/W configuration data. + * Read by the Sahara hardware + */ +struct hw_cfg_data { + ushort Addr; + ushort Data; }; -/* */ -#define NUM_HW_CFG_ENTRIES ((128/sizeof(struct HW_CFG_DATA)) - 4) +/* + * Number of struct hw_cfg_data structures to put in the configuration data + * data structure (struct sxg_config or struct sxg_config_a). The number is + * computed to fill the entire H/W config section of the structure. + */ +#define NUM_HW_CFG_ENTRIES \ + (HW_CFG_SECTION_SIZE / sizeof(struct hw_cfg_data)) +#define NUM_HW_CFG_ENTRIES_A \ + (HW_CFG_SECTION_SIZE_A / sizeof(struct hw_cfg_data)) -/* MAC address */ -struct SXG_CONFIG_MAC { - unsigned char MacAddr[6]; /* MAC Address */ +/* MAC address structure */ +struct sxg_config_mac { + unsigned char MacAddr[6]; /* MAC Address */ }; -/* */ -struct ATK_FRU { +/* FRU data structure */ +struct atk_fru { unsigned char PartNum[6]; unsigned char Revision[2]; unsigned char Serial[14]; @@ -697,38 +909,112 @@ struct ATK_FRU { #define EMC_FRU_FORMAT 0x0005 #define NO_FRU_FORMAT 0xFFFF -/* EEPROM/Flash Format */ -struct SXG_CONFIG { - /* */ - /* Section 1 (128 bytes) */ - /* */ - ushort MagicWord; /* EEPROM/FLASH Magic code 'A5A5' */ - ushort SpiClks; /* SPI bus clock dividers */ - struct HW_CFG_DATA HwCfg[NUM_HW_CFG_ENTRIES]; - /* */ - /* */ - /* */ - ushort Version; /* EEPROM format version */ - struct SXG_CONFIG_MAC MacAddr[4]; /* space for 4 MAC addresses */ - struct ATK_FRU AtkFru; /* FRU information */ - ushort OemFruFormat; /* OEM FRU format type */ - unsigned char OemFru[76]; /* OEM FRU information (optional) */ - ushort Checksum; /* Checksum of section 2 */ - /* CS info XXXTODO */ +#define ATK_OEM_ASSY_SIZE 10 /* assy num is 9 chars plus \0 */ + +/* OEM FRU structure for Alacritech */ +struct atk_oem { + unsigned char Assy[ATK_OEM_ASSY_SIZE]; }; + +#define OEM_EEPROM_FRUSIZE 74 /* size of OEM fru info - size */ +/* chosen to fill out the S/W section */ + +union oem_fru { /* OEM FRU information */ + unsigned char OemFru[OEM_EEPROM_FRUSIZE]; + struct atk_oem AtkOem; +}; + +/* Structure to hold the S/W configuration data. */ +struct sw_cfg_data { + ushort MagicWord; /* Magic word for section 2 */ + ushort Version; /* Format version */ + struct sxg_config_mac MacAddr[4]; /* space for 4 MAC addresses */ + struct atk_fru AtkFru; /* FRU information */ + ushort OemFruFormat; /* OEM FRU format type */ + union oem_fru OemFru; /* OEM FRU information */ + ushort Checksum; /* Checksum of section 2 */ +}; + + +/* EEPROM/Flash Format */ +struct sxg_config { + /* H/W Section - Read by Sahara hardware (512 bytes) */ + struct hw_cfg_data HwCfg[NUM_HW_CFG_ENTRIES]; + /* S/W Section - Other configuration data (128 bytes) */ + struct sw_cfg_data SwCfg; +}; + +#ifdef WINDOWS_COMPILER +/* + * The following macro is something of a kludge, but it is the only way + * that I could find to catch certain programming errors at compile time. + * If the asserted condition is true, then nothing happens. If false, then + * the compiler tries to typedef an array with -1 members, which generates + * an error. Unfortunately, the error message is meaningless, but at least + * it catches the problem. This macro would be unnecessary if the compiler + * allowed the sizeof and offsetof macros to be used in the #if directive. + */ +#define compile_time_assert(cond) \ + typedef char comp_error[(cond) ? 1 : -1] + +/* + * A compiler error on either of the next two lines indicates that the struct sxg_config + * structure was built incorrectly. Unfortunately, the error message produced + * is meaningless. But this is apparently the only way to catch this problem + * at compile time. + */ +compile_time_assert (offsetof(struct sxg_config, SwCfg) == SW_CFG_SECTION_START); +compile_time_assert (sizeof(struct sxg_config) == HW_CFG_SECTION_SIZE + + SW_CFG_SECTION_SIZE); + +compile_time_assert (offsetof(struct sxg_config_a, SwCfg) + == SW_CFG_SECTION_START_A); +compile_time_assert (sizeof(struct sxg_config_a) == HW_CFG_SECTION_SIZE_A + + SW_CFG_SECTION_SIZE); +#endif +/* + * Structure used to pass information between driver and user-mode + * control application + */ +struct adapt_userinfo { + bool LinkUp; + /* use LinkUp - any need for other states? */ + /* u32 LinkState; */ + u32 LinkSpeed; /* not currently needed */ + u32 LinkDuplex; /* not currently needed */ + enum xcvr_type XcvrType; /* type of xcvr on fiber card */ + /* fiber card xcvr vendor */ + unsigned char XcvrVendor[XCVR_VENDOR_LEN]; + unsigned char XcvrMode[XCVR_MODEL_LEN]; + u32 Port; /* not currently needed */ + u32 PhysPort; /* not currently needed */ + ushort PciLanes; + unsigned char MacAddr[6]; + unsigned char CurrMacAddr[6]; + struct atk_fru AtkFru; + ushort OemFruFormat; + union oem_fru OemFru; +}; + #pragma pack(pop) -/***************************************************************************** - * Miscellaneous Hardware definitions - *****************************************************************************/ +/* Miscellaneous Hardware definitions */ -// Sahara (ASIC level) defines -#define SAHARA_GRAM_SIZE 0x020000 // GRAM size - 128 KB -#define SAHARA_DRAM_SIZE 0x200000 // DRAM size - 2 MB -#define SAHARA_QRAM_SIZE 0x004000 // QRAM size - 16K entries (64 KB) -#define SAHARA_WCS_SIZE 0x002000 // WCS - 8K instructions (x 108 bits) +/* Hardware Type definitions */ -// Arabia (board level) defines -#define FLASH_SIZE 0x080000 // 512 KB (4 Mb) -#define EEPROM_SIZE_XFMR 512 // true EEPROM size (bytes), including xfmr area -#define EEPROM_SIZE_NO_XFMR 256 // EEPROM size excluding xfmr area +/* Sahara (ASIC level) defines */ +#define SAHARA_GRAM_SIZE 0x020000 /* GRAM size - 128 KB */ +#define SAHARA_DRAM_SIZE 0x200000 /* DRAM size - 2 MB */ +/* QRAM size - 16K entries (64 KB) */ +#define SAHARA_QRAM_SIZE 0x004000 +/* WCS - 8K instructions (x 108 bits) */ +#define SAHARA_WCS_SIZE 0x002000 + +/* Arabia (board level) defines */ +#define FLASH_SIZE 0x080000 /* 512 KB (4 Mb) */ +/* EEPROM size (bytes), including xfmr area */ +#define EEPROM_SIZE_XFMR 1024 +/* EEPROM size excluding xfmr area (512 + 128) */ +#define EEPROM_SIZE_NO_XFMR 640 +/* EEPROM size for Sahara rev A */ +#define EEPROM_SIZE_REV_A 512 diff --git a/drivers/staging/sxg/sxgphycode-1.2.h b/drivers/staging/sxg/sxgphycode-1.2.h new file mode 100644 index 000000000000..b5448b9b2787 --- /dev/null +++ b/drivers/staging/sxg/sxgphycode-1.2.h @@ -0,0 +1,130 @@ +/* + * Copyright ? 1997-2008 Alacritech, Inc. All rights reserved + * + * $Id: sxgphycode.h,v 1.2 2008/10/02 01:44:07 Exp $ + * + * sxgphycode.h: + * + * This file PHY microcode and register initialization data. + */ + +/********************************************************************** + * PHY Microcode + **********************************************************************/ +// +// The following contains both PHY microcode and PHY register +// initialization data. It is specific to both the PHY and the +// type of transceiver. +// + +// Download for AEL2005C PHY with SR/LR transceiver (10GBASE-SR or 10GBASE-LR) +// AEL2005 SR firmware rev 18 (microInit_mdio_SR_AEL2005C_18.tx). +static struct phy_ucode PhyUcode[] = { + // NOTE: An address of 0 is a special case. When the download routine + // sees an address of 0, it does not write to the PHY. Instead, it delays + // the download. The length of the delay (in ms) is given in the data field. + // Delays are required at certain points. + + // Platform-specific MDIO Patches: + // (include patches for 10G RX polarity flip, 50Mhz Synth, etc) + // Addr Data + {0xc017, 0xfeb0}, // flip RX_LOS polarity (mandatory patch for SFP+ applications) + {0xC001, 0x0428}, // flip RX serial polarity + + {0xc013, 0xf341}, // invert lxmit clock (mandatory patch) + {0xc210, 0x8000}, // reset datapath (mandatory patch) + {0xc210, 0x8100}, // reset datapath (mandatory patch) + {0xc210, 0x8000}, // reset datapath (mandatory patch) + {0xc210, 0x0000}, // reset datapath (mandatory patch) + {0x0000, 0x0032}, // wait for 50ms for datapath reset to complete. (mandatory patch) + + // Transceiver-specific MDIO Patches: + {0xc003, 0x0181}, // (bit 7) enable the CDR inc setting in 1.C005 (mandatory patch for SR code) + {0xc010, 0x448a}, // (bit 14) mask out high BER input from the LOS signal in 1.000A (mandatory patch for SR code) + + // Transceiver-specific Microcontroller Initialization: + {0xc04a, 0x5200}, // activate microcontroller and pause + {0x0000, 0x0032}, // wait 50ms for microcontroller before writing in code. + + // code block starts here: + {0xcc00, 0x2ff4}, {0xcc01, 0x3cd4}, {0xcc02, 0x2015}, {0xcc03, 0x3125}, + {0xcc04, 0x6524}, {0xcc05, 0x27ff}, {0xcc06, 0x300f}, {0xcc07, 0x2c8b}, + {0xcc08, 0x300b}, {0xcc09, 0x4009}, {0xcc0a, 0x400e}, {0xcc0b, 0x2f12}, + {0xcc0c, 0x3002}, {0xcc0d, 0x1002}, {0xcc0e, 0x2112}, {0xcc0f, 0x3012}, + {0xcc10, 0x1002}, {0xcc11, 0x2572}, {0xcc12, 0x3012}, {0xcc13, 0x1002}, + {0xcc14, 0xd01e}, {0xcc15, 0x2772}, {0xcc16, 0x3012}, {0xcc17, 0x1002}, + {0xcc18, 0x2004}, {0xcc19, 0x3c84}, {0xcc1a, 0x6436}, {0xcc1b, 0x2007}, + {0xcc1c, 0x3f87}, {0xcc1d, 0x8676}, {0xcc1e, 0x40b7}, {0xcc1f, 0xa746}, + {0xcc20, 0x4047}, {0xcc21, 0x5673}, {0xcc22, 0x2982}, {0xcc23, 0x3002}, + {0xcc24, 0x13d2}, {0xcc25, 0x8bbd}, {0xcc26, 0x2802}, {0xcc27, 0x3012}, + {0xcc28, 0x1002}, {0xcc29, 0x2032}, {0xcc2a, 0x3012}, {0xcc2b, 0x1002}, + {0xcc2c, 0x5cc3}, {0xcc2d, 0x0314}, {0xcc2e, 0x2942}, {0xcc2f, 0x3002}, + {0xcc30, 0x1002}, {0xcc31, 0xd019}, {0xcc32, 0x2fd2}, {0xcc33, 0x3002}, + {0xcc34, 0x1002}, {0xcc35, 0x2a04}, {0xcc36, 0x3c74}, {0xcc37, 0x6435}, + {0xcc38, 0x2fa4}, {0xcc39, 0x3cd4}, {0xcc3a, 0x6624}, {0xcc3b, 0x5563}, + {0xcc3c, 0x2d42}, {0xcc3d, 0x3002}, {0xcc3e, 0x13d2}, {0xcc3f, 0x464d}, + {0xcc40, 0x2802}, {0xcc41, 0x3012}, {0xcc42, 0x1002}, {0xcc43, 0x2fd2}, + {0xcc44, 0x3002}, {0xcc45, 0x1002}, {0xcc46, 0x2fb4}, {0xcc47, 0x3cd4}, + {0xcc48, 0x6624}, {0xcc49, 0x5563}, {0xcc4a, 0x2d42}, {0xcc4b, 0x3002}, + {0xcc4c, 0x13d2}, {0xcc4d, 0x2e72}, {0xcc4e, 0x3002}, {0xcc4f, 0x1002}, + {0xcc50, 0x2f72}, {0xcc51, 0x3002}, {0xcc52, 0x1002}, {0xcc53, 0x0004}, + {0xcc54, 0x2942}, {0xcc55, 0x3002}, {0xcc56, 0x1002}, {0xcc57, 0x2032}, + {0xcc58, 0x3012}, {0xcc59, 0x1002}, {0xcc5a, 0x5cc3}, {0xcc5b, 0x0317}, + {0xcc5c, 0x2f12}, {0xcc5d, 0x3002}, {0xcc5e, 0x1002}, {0xcc5f, 0x2942}, + {0xcc60, 0x3002}, {0xcc61, 0x1002}, {0xcc62, 0x22cd}, {0xcc63, 0x301d}, + {0xcc64, 0x2802}, {0xcc65, 0x3012}, {0xcc66, 0x1002}, {0xcc67, 0x20b2}, + {0xcc68, 0x3012}, {0xcc69, 0x1002}, {0xcc6a, 0x5aa3}, {0xcc6b, 0x2dc2}, + {0xcc6c, 0x3002}, {0xcc6d, 0x1312}, {0xcc6e, 0x2d02}, {0xcc6f, 0x3002}, + {0xcc70, 0x1002}, {0xcc71, 0x2807}, {0xcc72, 0x31a7}, {0xcc73, 0x20c4}, + {0xcc74, 0x3c24}, {0xcc75, 0x6724}, {0xcc76, 0x1002}, {0xcc77, 0x2807}, + {0xcc78, 0x3187}, {0xcc79, 0x20c4}, {0xcc7a, 0x3c24}, {0xcc7b, 0x6724}, + {0xcc7c, 0x1002}, {0xcc7d, 0x2514}, {0xcc7e, 0x3c64}, {0xcc7f, 0x6436}, + {0xcc80, 0xdff4}, {0xcc81, 0x6436}, {0xcc82, 0x1002}, {0xcc83, 0x40a4}, + {0xcc84, 0x643c}, {0xcc85, 0x4016}, {0xcc86, 0x8c6c}, {0xcc87, 0x2b24}, + {0xcc88, 0x3c24}, {0xcc89, 0x6435}, {0xcc8a, 0x1002}, {0xcc8b, 0x2b24}, + {0xcc8c, 0x3c24}, {0xcc8d, 0x643a}, {0xcc8e, 0x4025}, {0xcc8f, 0x8a5a}, + {0xcc90, 0x1002}, {0xcc91, 0x26d1}, {0xcc92, 0x3011}, {0xcc93, 0x1001}, + {0xcc94, 0xc7a0}, {0xcc95, 0x0100}, {0xcc96, 0xc502}, {0xcc97, 0x53ac}, + {0xcc98, 0xc503}, {0xcc99, 0xd5d5}, {0xcc9a, 0xc600}, {0xcc9b, 0x2a6d}, + {0xcc9c, 0xc601}, {0xcc9d, 0x2a4c}, {0xcc9e, 0xc602}, {0xcc9f, 0x0111}, + {0xcca0, 0xc60c}, {0xcca1, 0x5900}, {0xcca2, 0xc710}, {0xcca3, 0x0700}, + {0xcca4, 0xc718}, {0xcca5, 0x0700}, {0xcca6, 0xc720}, {0xcca7, 0x4700}, + {0xcca8, 0xc801}, {0xcca9, 0x7f50}, {0xccaa, 0xc802}, {0xccab, 0x7760}, + {0xccac, 0xc803}, {0xccad, 0x7fce}, {0xccae, 0xc804}, {0xccaf, 0x5700}, + {0xccb0, 0xc805}, {0xccb1, 0x5f11}, {0xccb2, 0xc806}, {0xccb3, 0x4751}, + {0xccb4, 0xc807}, {0xccb5, 0x57e1}, {0xccb6, 0xc808}, {0xccb7, 0x2700}, + {0xccb8, 0xc809}, {0xccb9, 0x0000}, {0xccba, 0xc821}, {0xccbb, 0x0002}, + {0xccbc, 0xc822}, {0xccbd, 0x0014}, {0xccbe, 0xc832}, {0xccbf, 0x1186}, + {0xccc0, 0xc847}, {0xccc1, 0x1e02}, {0xccc2, 0xc013}, {0xccc3, 0xf341}, + {0xccc4, 0xc01a}, {0xccc5, 0x0446}, {0xccc6, 0xc024}, {0xccc7, 0x1000}, + {0xccc8, 0xc025}, {0xccc9, 0x0a00}, {0xccca, 0xc026}, {0xcccb, 0x0c0c}, + {0xcccc, 0xc027}, {0xcccd, 0x0c0c}, {0xccce, 0xc029}, {0xcccf, 0x00a0}, + {0xccd0, 0xc030}, {0xccd1, 0x0a00}, {0xccd2, 0xc03c}, {0xccd3, 0x001c}, + {0xccd4, 0xc005}, {0xccd5, 0x7a06}, {0xccd6, 0x0000}, {0xccd7, 0x26d1}, + {0xccd8, 0x3011}, {0xccd9, 0x1001}, {0xccda, 0xc620}, {0xccdb, 0x0000}, + {0xccdc, 0xc621}, {0xccdd, 0x003f}, {0xccde, 0xc622}, {0xccdf, 0x0000}, + {0xcce0, 0xc623}, {0xcce1, 0x0000}, {0xcce2, 0xc624}, {0xcce3, 0x0000}, + {0xcce4, 0xc625}, {0xcce5, 0x0000}, {0xcce6, 0xc627}, {0xcce7, 0x0000}, + {0xcce8, 0xc628}, {0xcce9, 0x0000}, {0xccea, 0xc62c}, {0xcceb, 0x0000}, + {0xccec, 0x0000}, {0xcced, 0x2806}, {0xccee, 0x3cb6}, {0xccef, 0xc161}, + {0xccf0, 0x6134}, {0xccf1, 0x6135}, {0xccf2, 0x5443}, {0xccf3, 0x0303}, + {0xccf4, 0x6524}, {0xccf5, 0x000b}, {0xccf6, 0x1002}, {0xccf7, 0x2104}, + {0xccf8, 0x3c24}, {0xccf9, 0x2105}, {0xccfa, 0x3805}, {0xccfb, 0x6524}, + {0xccfc, 0xdff4}, {0xccfd, 0x4005}, {0xccfe, 0x6524}, {0xccff, 0x1002}, + {0xcd00, 0x5dd3}, {0xcd01, 0x0306}, {0xcd02, 0x2ff7}, {0xcd03, 0x38f7}, + {0xcd04, 0x60b7}, {0xcd05, 0xdffd}, {0xcd06, 0x000a}, {0xcd07, 0x1002}, + {0xcd08, 0x0000}, + // end of code block + + // Unpause the microcontroller to start program + {0xca00, 0x0080}, + {0xca12, 0x0000}, + {0x0000, 0x000A}, // wait 10ms just to be safe + + // Configure the LED's + {0xc214, 0x0099}, // configure the LED drivers (for Sahara rev B) + {0xc216, 0x0400}, // configure the one LED + {0xc217, 0x0000}, // don't drive the 2nd LED (if it exists) + + {0xffff, 0xffff} // table terminator +}; diff --git a/drivers/staging/sxg/sxgphycode.h b/drivers/staging/sxg/sxgphycode.h deleted file mode 100644 index 167f356ef86b..000000000000 --- a/drivers/staging/sxg/sxgphycode.h +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright (C) 1997-2008 Alacritech, Inc. All rights reserved - * - * sxgphycode.h: - * - * This file PHY microcode and register initialization data. - */ - -/********************************************************************** - * PHY Microcode - * - * The following contains both PHY microcode and PHY register - * initialization data. It is specific to both the PHY and the - * type of transceiver. - * - **********************************************************************/ - -/* - * Download for AEL2005C PHY with SR/LR transceiver (10GBASE-SR or 10GBASE-LR) - */ -static struct PHY_UCODE PhyUcode[] = { - /* - * NOTE: An address of 0 is a special case. When the download routine - * sees an address of 0, it does not write to the PHY. Instead, it - * delays the download. The length of the delay (in ms) is given in - * the data field. - * - * Delays are required at certain points. - */ - - /* - * Platform-specific MDIO Patches: - * (include patches for 10G RX polarity flip, 50Mhz Synth, etc) - */ - /* Addr, Data */ - {0xc017, 0xfeb0}, /* flip RX_LOS polarity (mandatory */ - /* patch for SFP+ applications) */ - {0xC001, 0x0428}, /* flip RX serial polarity */ - - {0xc013, 0xf341}, /* invert lxmit clock (mandatory patch) */ - {0xc210, 0x8000}, /* reset datapath (mandatory patch) */ - {0xc210, 0x8100}, /* reset datapath (mandatory patch) */ - {0xc210, 0x8000}, /* reset datapath (mandatory patch) */ - {0xc210, 0x0000}, /* reset datapath (mandatory patch) */ - {0x0000, 0x0032}, /* wait for 50ms for datapath reset to */ - /* complete. (mandatory patch) */ - - /* Configure the LED's */ - {0xc214, 0x0099}, /* configure the LED drivers */ - {0xc216, 0x5f5f}, /* configure the Activity LED */ - {0xc217, 0x33ff}, /* configure the Link LED */ - - /* Transceiver-specific MDIO Patches: */ - {0xc010, 0x448a}, /* (bit 14) mask out high BER input from the */ - /* LOS signal in 1.000A */ - /* (mandatory patch for SR code) */ - {0xc003, 0x0181}, /* (bit 7) enable the CDR inc setting in */ - /* 1.C005 (mandatory patch for SR code) */ - - /* Transceiver-specific Microcontroller Initialization: */ - {0xc04a, 0x5200}, /* activate microcontroller and pause */ - {0x0000, 0x0032}, /* wait 50ms for microcontroller before */ - /* writing in code. */ - - /* code block starts here: */ - {0xcc00, 0x2009}, - {0xcc01, 0x3009}, - {0xcc02, 0x27ff}, - {0xcc03, 0x300f}, - {0xcc04, 0x200c}, - {0xcc05, 0x300c}, - {0xcc06, 0x20c4}, - {0xcc07, 0x3c04}, - {0xcc08, 0x6437}, - {0xcc09, 0x20c4}, - {0xcc0a, 0x3c04}, - {0xcc0b, 0x6437}, - {0xcc0c, 0x25c4}, - {0xcc0d, 0x3c54}, - {0xcc0e, 0x6724}, - {0xcc0f, 0x25c4}, - {0xcc10, 0x3c54}, - {0xcc11, 0x6724}, - {0xcc12, 0x2042}, - {0xcc13, 0x3012}, - {0xcc14, 0x1002}, - {0xcc15, 0x2482}, - {0xcc16, 0x3012}, - {0xcc17, 0x1002}, - {0xcc18, 0x2a32}, - {0xcc19, 0x3002}, - {0xcc1a, 0x1002}, - {0xcc1b, 0x200d}, - {0xcc1c, 0x304d}, - {0xcc1d, 0x2862}, - {0xcc1e, 0x3012}, - {0xcc1f, 0x1002}, - {0xcc20, 0x2982}, - {0xcc21, 0x3002}, - {0xcc22, 0x1002}, - {0xcc23, 0x628f}, - {0xcc24, 0x20a4}, - {0xcc25, 0x3004}, - {0xcc26, 0x6438}, - {0xcc27, 0x20a4}, - {0xcc28, 0x3004}, - {0xcc29, 0x6438}, - {0xcc2a, 0x2015}, - {0xcc2b, 0x3005}, - {0xcc2c, 0x5853}, - {0xcc2d, 0x2bd2}, - {0xcc2e, 0x3002}, - {0xcc2f, 0x1342}, - {0xcc30, 0x200c}, - {0xcc31, 0x300c}, - {0xcc32, 0x2ff7}, - {0xcc33, 0x30f7}, - {0xcc34, 0x20c4}, - {0xcc35, 0x3c04}, - {0xcc36, 0x6724}, - {0xcc37, 0x20c4}, - {0xcc38, 0x3c04}, - {0xcc39, 0x6724}, - {0xcc3a, 0x2d32}, - {0xcc3b, 0x3002}, - {0xcc3c, 0x1002}, - {0xcc3d, 0x2008}, - {0xcc3e, 0x3008}, - {0xcc3f, 0x5c83}, - {0xcc40, 0x2d52}, - {0xcc41, 0x3002}, - {0xcc42, 0x1352}, - {0xcc43, 0x2008}, - {0xcc44, 0x3008}, - {0xcc45, 0x5c83}, - {0xcc46, 0x2d32}, - {0xcc47, 0x3002}, - {0xcc48, 0x1352}, - {0xcc49, 0x201c}, - {0xcc4a, 0x300c}, - {0xcc4b, 0x200d}, - {0xcc4c, 0x310d}, - {0xcc4d, 0x2862}, - {0xcc4e, 0x3012}, - {0xcc4f, 0x1002}, - {0xcc50, 0x2ed2}, - {0xcc51, 0x3002}, - {0xcc52, 0x1342}, - {0xcc53, 0x6f72}, - {0xcc54, 0x1002}, - {0xcc55, 0x628f}, - {0xcc56, 0x2514}, - {0xcc57, 0x3c64}, - {0xcc58, 0x6436}, - {0xcc59, 0x2514}, - {0xcc5a, 0x3c64}, - {0xcc5b, 0x6436}, - {0xcc5c, 0x2fa4}, - {0xcc5d, 0x3cd4}, - {0xcc5e, 0x6624}, - {0xcc5f, 0x2fa4}, - {0xcc60, 0x3cd4}, - {0xcc61, 0x6624}, - {0xcc62, 0x2f45}, - {0xcc63, 0x3015}, - {0xcc64, 0x5653}, - {0xcc65, 0x2eb2}, - {0xcc66, 0x3002}, - {0xcc67, 0x13d2}, - {0xcc68, 0x2ed2}, - {0xcc69, 0x3002}, - {0xcc6a, 0x1002}, - {0xcc6b, 0x6f72}, - {0xcc6c, 0x1002}, - {0xcc6d, 0x628f}, - {0xcc6e, 0x2602}, - {0xcc6f, 0x3012}, - {0xcc70, 0x1002}, - {0xcc71, 0x200d}, - {0xcc72, 0x320d}, - {0xcc73, 0x2862}, - {0xcc74, 0x3012}, - {0xcc75, 0x1002}, - {0xcc76, 0x25c4}, - {0xcc77, 0x3c54}, - {0xcc78, 0x6437}, - {0xcc79, 0x25c4}, - {0xcc7a, 0x3c54}, - {0xcc7b, 0x6437}, - {0xcc7c, 0x20c4}, - {0xcc7d, 0x3c04}, - {0xcc7e, 0x6724}, - {0xcc7f, 0x20c4}, - {0xcc80, 0x3c04}, - {0xcc81, 0x6724}, - {0xcc82, 0x6f72}, - {0xcc83, 0x1002}, - {0xcc84, 0x628f}, - {0xcc85, 0x26f2}, - {0xcc86, 0x3012}, - {0xcc87, 0x1002}, - {0xcc88, 0xc503}, - {0xcc89, 0xd5d5}, - {0xcc8a, 0xc600}, - {0xcc8b, 0x2a6d}, - {0xcc8c, 0xc601}, - {0xcc8d, 0x2a4c}, - {0xcc8e, 0xc602}, - {0xcc8f, 0x0111}, - {0xcc90, 0xc60c}, - {0xcc91, 0x5900}, - {0xcc92, 0xc710}, - {0xcc93, 0x0700}, - {0xcc94, 0xc718}, - {0xcc95, 0x0700}, - {0xcc96, 0xc720}, - {0xcc97, 0x4700}, - {0xcc98, 0xc801}, - {0xcc99, 0x7f50}, - {0xcc9a, 0xc802}, - {0xcc9b, 0x7760}, - {0xcc9c, 0xc803}, - {0xcc9d, 0x7fce}, - {0xcc9e, 0xc804}, - {0xcc9f, 0x5700}, - {0xcca0, 0xc805}, - {0xcca1, 0x5f11}, - {0xcca2, 0xc806}, - {0xcca3, 0x4751}, - {0xcca4, 0xc807}, - {0xcca5, 0x57e1}, - {0xcca6, 0xc808}, - {0xcca7, 0x2700}, - {0xcca8, 0xc809}, - {0xcca9, 0x0000}, - {0xccaa, 0xc821}, - {0xccab, 0x0002}, - {0xccac, 0xc822}, - {0xccad, 0x0014}, - {0xccae, 0xc832}, - {0xccaf, 0x1186}, - {0xccb0, 0xc847}, - {0xccb1, 0x1e02}, - {0xccb2, 0xc013}, - {0xccb3, 0xf341}, - {0xccb4, 0xc01a}, - {0xccb5, 0x0446}, - {0xccb6, 0xc024}, - {0xccb7, 0x1000}, - {0xccb8, 0xc025}, - {0xccb9, 0x0a00}, - {0xccba, 0xc026}, - {0xccbb, 0x0c0c}, - {0xccbc, 0xc027}, - {0xccbd, 0x0c0c}, - {0xccbe, 0xc029}, - {0xccbf, 0x00a0}, - {0xccc0, 0xc030}, - {0xccc1, 0x0a00}, - {0xccc2, 0xc03c}, - {0xccc3, 0x001c}, - {0xccc4, 0xc005}, - {0xccc5, 0x7a06}, - {0xccc6, 0x0000}, - {0xccc7, 0x0000}, - {0xccc8, 0x628f}, - {0xccc9, 0x26f2}, - {0xccca, 0x3012}, - {0xcccb, 0x1002}, - {0xcccc, 0xc620}, - {0xcccd, 0x0000}, - {0xccce, 0xc621}, - {0xcccf, 0x003f}, - {0xccd0, 0xc622}, - {0xccd1, 0x0000}, - {0xccd2, 0xc623}, - {0xccd3, 0x0000}, - {0xccd4, 0xc624}, - {0xccd5, 0x0000}, - {0xccd6, 0xc625}, - {0xccd7, 0x0000}, - {0xccd8, 0xc627}, - {0xccd9, 0x0000}, - {0xccda, 0xc628}, - {0xccdb, 0x0000}, - {0xccdc, 0xc62c}, - {0xccdd, 0x0000}, - {0xccde, 0x0000}, - {0xccdf, 0x0000}, - {0xcce0, 0x628f}, - {0xcce1, 0xd019}, - {0xcce2, 0x26f2}, - {0xcce3, 0x3012}, - {0xcce4, 0x1002}, - {0xcce5, 0xc210}, - {0xcce6, 0x8000}, - {0xcce7, 0xc210}, - {0xcce8, 0x8010}, - {0xcce9, 0xc210}, - {0xccea, 0x8000}, - {0xcceb, 0xc210}, - {0xccec, 0x0000}, - {0xcced, 0x0000}, - {0xccee, 0x0000}, - {0xccef, 0x8221}, - {0xccf0, 0x2752}, - {0xccf1, 0x3012}, - {0xccf2, 0x1002}, - {0xccf3, 0x6f72}, - {0xccf4, 0x1002}, - {0xccf5, 0x2806}, - {0xccf6, 0x3006}, - {0xccf7, 0x2007}, - {0xccf8, 0x3cc7}, - {0xccf9, 0xe161}, - {0xccfa, 0xc171}, - {0xccfb, 0x6134}, - {0xccfc, 0x6135}, - {0xccfd, 0x5453}, - {0xccfe, 0x2858}, - {0xccff, 0x3018}, - {0xcd00, 0x1348}, - {0xcd01, 0x6524}, - {0xcd02, 0x27b8}, - {0xcd03, 0x3018}, - {0xcd04, 0x1008}, - {0xcd05, 0x1002}, - {0xcd06, 0x628f}, - {0xcd07, 0x5dd3}, - {0xcd08, 0x2906}, - {0xcd09, 0x3016}, - {0xcd0a, 0x1306}, - {0xcd0b, 0x2ff7}, - {0xcd0c, 0x30f7}, - {0xcd0d, 0x60b7}, - {0xcd0e, 0xdffd}, - {0xcd0f, 0x0008}, - {0xcd10, 0x6f72}, - {0xcd11, 0x1002}, - {0xcd12, 0x0000}, - {0xcdff, 0x0a01}, - /* end of code block */ - - /* Unpause the microcontroller to start program */ - {0xca00, 0x0080}, - {0xca12, 0x0000}, - {0x0000, 0x000A}, /* wait 10ms just to be safe */ - {0xffff, 0xffff} /* table terminator */ -}; diff --git a/drivers/staging/uc2322/Kconfig b/drivers/staging/uc2322/Kconfig new file mode 100644 index 000000000000..2e0c6e79df2b --- /dev/null +++ b/drivers/staging/uc2322/Kconfig @@ -0,0 +1,10 @@ +config USB_SERIAL_ATEN2011 + tristate "ATEN 2011 USB to serial device support" + depends on USB_SERIAL + default N + ---help--- + Say Y here if you want to use a ATEN 2011 dual port USB to serial + adapter. + + To compile this driver as a module, choose M here: the module will be + called aten2011. diff --git a/drivers/staging/uc2322/Makefile b/drivers/staging/uc2322/Makefile new file mode 100644 index 000000000000..49c18d6e579f --- /dev/null +++ b/drivers/staging/uc2322/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_USB_SERIAL_ATEN2011) += aten2011.o diff --git a/drivers/staging/uc2322/TODO b/drivers/staging/uc2322/TODO new file mode 100644 index 000000000000..c189a64c4185 --- /dev/null +++ b/drivers/staging/uc2322/TODO @@ -0,0 +1,7 @@ +TODO: + - checkpatch.pl cleanups + - remove dead and useless code (auditing the tty ioctls to + verify that they really are correct and needed.) + +Please send any patches to Greg Kroah-Hartman and +Russell Lang . diff --git a/drivers/staging/uc2322/aten2011.c b/drivers/staging/uc2322/aten2011.c new file mode 100644 index 000000000000..85b705453066 --- /dev/null +++ b/drivers/staging/uc2322/aten2011.c @@ -0,0 +1,2452 @@ +/* + * Aten 2011 USB serial driver for 4 port devices + * + * Copyright (C) 2000 Inside Out Networks + * Copyright (C) 2001-2002, 2009 Greg Kroah-Hartman + * Copyright (C) 2009 Novell Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define ZLP_REG1 0x3A /* Zero_Flag_Reg1 58 */ +#define ZLP_REG2 0x3B /* Zero_Flag_Reg2 59 */ +#define ZLP_REG3 0x3C /* Zero_Flag_Reg3 60 */ +#define ZLP_REG4 0x3D /* Zero_Flag_Reg4 61 */ +#define ZLP_REG5 0x3E /* Zero_Flag_Reg5 62 */ + +/* Interrupt Rotinue Defines */ +#define SERIAL_IIR_RLS 0x06 +#define SERIAL_IIR_RDA 0x04 +#define SERIAL_IIR_CTI 0x0c +#define SERIAL_IIR_THR 0x02 +#define SERIAL_IIR_MS 0x00 + +/* Emulation of the bit mask on the LINE STATUS REGISTER. */ +#define SERIAL_LSR_DR 0x0001 +#define SERIAL_LSR_OE 0x0002 +#define SERIAL_LSR_PE 0x0004 +#define SERIAL_LSR_FE 0x0008 +#define SERIAL_LSR_BI 0x0010 +#define SERIAL_LSR_THRE 0x0020 +#define SERIAL_LSR_TEMT 0x0040 +#define SERIAL_LSR_FIFOERR 0x0080 + +/* MSR bit defines(place holders) */ +#define ATEN_MSR_DELTA_CTS 0x10 +#define ATEN_MSR_DELTA_DSR 0x20 +#define ATEN_MSR_DELTA_RI 0x40 +#define ATEN_MSR_DELTA_CD 0x80 + +/* Serial Port register Address */ +#define RECEIVE_BUFFER_REGISTER ((__u16)(0x00)) +#define TRANSMIT_HOLDING_REGISTER ((__u16)(0x00)) +#define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01)) +#define INTERRUPT_IDENT_REGISTER ((__u16)(0x02)) +#define FIFO_CONTROL_REGISTER ((__u16)(0x02)) +#define LINE_CONTROL_REGISTER ((__u16)(0x03)) +#define MODEM_CONTROL_REGISTER ((__u16)(0x04)) +#define LINE_STATUS_REGISTER ((__u16)(0x05)) +#define MODEM_STATUS_REGISTER ((__u16)(0x06)) +#define SCRATCH_PAD_REGISTER ((__u16)(0x07)) +#define DIVISOR_LATCH_LSB ((__u16)(0x00)) +#define DIVISOR_LATCH_MSB ((__u16)(0x01)) + +#define SP1_REGISTER ((__u16)(0x00)) +#define CONTROL1_REGISTER ((__u16)(0x01)) +#define CLK_MULTI_REGISTER ((__u16)(0x02)) +#define CLK_START_VALUE_REGISTER ((__u16)(0x03)) +#define DCR1_REGISTER ((__u16)(0x04)) +#define GPIO_REGISTER ((__u16)(0x07)) + +#define SERIAL_LCR_DLAB ((__u16)(0x0080)) + +/* + * URB POOL related defines + */ +#define NUM_URBS 16 /* URB Count */ +#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ + +#define USB_VENDOR_ID_ATENINTL 0x0557 +#define ATENINTL_DEVICE_ID_2011 0x2011 +#define ATENINTL_DEVICE_ID_7820 0x7820 + +static struct usb_device_id id_table[] = { + { USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_2011) }, + { USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_7820) }, + { } /* terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* This structure holds all of the local port information */ +struct ATENINTL_port { + int port_num; /*Actual port number in the device(1,2,etc)*/ + __u8 bulk_out_endpoint; /* the bulk out endpoint handle */ + unsigned char *bulk_out_buffer; /* buffer used for the bulk out endpoint */ + struct urb *write_urb; /* write URB for this port */ + __u8 bulk_in_endpoint; /* the bulk in endpoint handle */ + unsigned char *bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ + struct urb *read_urb; /* read URB for this port */ + __u8 shadowLCR; /* last LCR value received */ + __u8 shadowMCR; /* last MCR value received */ + char open; + char chaseResponsePending; + wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ + wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */ + struct async_icount icount; + struct usb_serial_port *port; /* loop back to the owner of this object */ + /*Offsets*/ + __u8 SpRegOffset; + __u8 ControlRegOffset; + __u8 DcrRegOffset; + /* for processing control URBS in interrupt context */ + struct urb *control_urb; + char *ctrl_buf; + int MsrLsr; + + struct urb *write_urb_pool[NUM_URBS]; + /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */ + struct ktermios tmp_termios; /* stores the old termios settings */ + spinlock_t lock; /* private lock */ +}; + +/* This structure holds all of the individual serial device information */ +struct ATENINTL_serial { + __u8 interrupt_in_endpoint; /* the interrupt endpoint handle */ + unsigned char *interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */ + struct urb *interrupt_read_urb; /* our interrupt urb */ + __u8 bulk_in_endpoint; /* the bulk in endpoint handle */ + unsigned char *bulk_in_buffer; /* the buffer we use for the bulk in endpoint */ + struct urb *read_urb; /* our bulk read urb */ + __u8 bulk_out_endpoint; /* the bulk out endpoint handle */ + struct usb_serial *serial; /* loop back to the owner of this object */ + int ATEN2011_spectrum_2or4ports; /* this says the number of ports in the device */ + /* Indicates about the no.of opened ports of an individual USB-serial adapater. */ + unsigned int NoOfOpenPorts; + /* a flag for Status endpoint polling */ + unsigned char status_polling_started; +}; + +static void ATEN2011_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, + struct ktermios *old_termios); +static void ATEN2011_change_port_settings(struct tty_struct *tty, + struct ATENINTL_port *ATEN2011_port, + struct ktermios *old_termios); + +/************************************* + * Bit definitions for each register * + *************************************/ +#define LCR_BITS_5 0x00 /* 5 bits/char */ +#define LCR_BITS_6 0x01 /* 6 bits/char */ +#define LCR_BITS_7 0x02 /* 7 bits/char */ +#define LCR_BITS_8 0x03 /* 8 bits/char */ +#define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ + +#define LCR_STOP_1 0x00 /* 1 stop bit */ +#define LCR_STOP_1_5 0x04 /* 1.5 stop bits (if 5 bits/char) */ +#define LCR_STOP_2 0x04 /* 2 stop bits (if 6-8 bits/char) */ +#define LCR_STOP_MASK 0x04 /* Mask for stop bits field */ + +#define LCR_PAR_NONE 0x00 /* No parity */ +#define LCR_PAR_ODD 0x08 /* Odd parity */ +#define LCR_PAR_EVEN 0x18 /* Even parity */ +#define LCR_PAR_MARK 0x28 /* Force parity bit to 1 */ +#define LCR_PAR_SPACE 0x38 /* Force parity bit to 0 */ +#define LCR_PAR_MASK 0x38 /* Mask for parity field */ + +#define LCR_SET_BREAK 0x40 /* Set Break condition */ +#define LCR_DL_ENABLE 0x80 /* Enable access to divisor latch */ + +#define MCR_DTR 0x01 /* Assert DTR */ +#define MCR_RTS 0x02 /* Assert RTS */ +#define MCR_OUT1 0x04 /* Loopback only: Sets state of RI */ +#define MCR_MASTER_IE 0x08 /* Enable interrupt outputs */ +#define MCR_LOOPBACK 0x10 /* Set internal (digital) loopback mode */ +#define MCR_XON_ANY 0x20 /* Enable any char to exit XOFF mode */ + +#define ATEN2011_MSR_CTS 0x10 /* Current state of CTS */ +#define ATEN2011_MSR_DSR 0x20 /* Current state of DSR */ +#define ATEN2011_MSR_RI 0x40 /* Current state of RI */ +#define ATEN2011_MSR_CD 0x80 /* Current state of CD */ + + +static int debug; + +/* + * Version Information + */ +#define DRIVER_VERSION "2.0" +#define DRIVER_DESC "ATENINTL 2011 USB Serial Adapter" + +/* + * Defines used for sending commands to port + */ + +#define ATEN_WDR_TIMEOUT (50) /* default urb timeout */ + +/* Requests */ +#define ATEN_RD_RTYPE 0xC0 +#define ATEN_WR_RTYPE 0x40 +#define ATEN_RDREQ 0x0D +#define ATEN_WRREQ 0x0E +#define ATEN_CTRL_TIMEOUT 500 +#define VENDOR_READ_LENGTH (0x01) + +/* set to 1 for RS485 mode and 0 for RS232 mode */ +/* FIXME make this somehow dynamic and not build time specific */ +static int RS485mode; + +static int set_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 val) +{ + struct usb_device *dev = port->serial->dev; + val = val & 0x00ff; + + dbg("%s: is %x, value %x", __func__, reg, val); + + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ, + ATEN_WR_RTYPE, val, reg, NULL, 0, + ATEN_WDR_TIMEOUT); +} + +static int get_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 *val) +{ + struct usb_device *dev = port->serial->dev; + int ret; + + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ, + ATEN_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH, + ATEN_WDR_TIMEOUT); + dbg("%s: offset is %x, return val %x", __func__, reg, *val); + *val = (*val) & 0x00ff; + return ret; +} + +static int set_uart_reg(struct usb_serial_port *port, __u16 reg, __u16 val) +{ + struct usb_device *dev = port->serial->dev; + struct ATENINTL_serial *a_serial; + __u16 minor; + + a_serial = usb_get_serial_data(port->serial); + minor = port->serial->minor; + if (minor == SERIAL_TTY_NO_MINOR) + minor = 0; + val = val & 0x00ff; + + /* + * For the UART control registers, + * the application number need to be Or'ed + */ + if (a_serial->ATEN2011_spectrum_2or4ports == 4) + val |= (((__u16)port->number - minor) + 1) << 8; + else { + if (((__u16) port->number - minor) == 0) + val |= (((__u16)port->number - minor) + 1) << 8; + else + val |= (((__u16)port->number - minor) + 2) << 8; + } + dbg("%s: application number is %x", __func__, val); + + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ, + ATEN_WR_RTYPE, val, reg, NULL, 0, + ATEN_WDR_TIMEOUT); +} + +static int get_uart_reg(struct usb_serial_port *port, __u16 reg, __u16 *val) +{ + struct usb_device *dev = port->serial->dev; + int ret = 0; + __u16 wval; + struct ATENINTL_serial *a_serial; + __u16 minor = port->serial->minor; + + a_serial = usb_get_serial_data(port->serial); + if (minor == SERIAL_TTY_NO_MINOR) + minor = 0; + + /* wval is same as application number */ + if (a_serial->ATEN2011_spectrum_2or4ports == 4) + wval = (((__u16)port->number - minor) + 1) << 8; + else { + if (((__u16) port->number - minor) == 0) + wval = (((__u16) port->number - minor) + 1) << 8; + else + wval = (((__u16) port->number - minor) + 2) << 8; + } + dbg("%s: application number is %x", __func__, wval); + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ, + ATEN_RD_RTYPE, wval, reg, val, VENDOR_READ_LENGTH, + ATEN_WDR_TIMEOUT); + *val = (*val) & 0x00ff; + return ret; +} + +static int handle_newMsr(struct ATENINTL_port *port, __u8 newMsr) +{ + struct ATENINTL_port *ATEN2011_port; + struct async_icount *icount; + ATEN2011_port = port; + icount = &ATEN2011_port->icount; + if (newMsr & + (ATEN_MSR_DELTA_CTS | ATEN_MSR_DELTA_DSR | ATEN_MSR_DELTA_RI | + ATEN_MSR_DELTA_CD)) { + icount = &ATEN2011_port->icount; + + /* update input line counters */ + if (newMsr & ATEN_MSR_DELTA_CTS) + icount->cts++; + if (newMsr & ATEN_MSR_DELTA_DSR) + icount->dsr++; + if (newMsr & ATEN_MSR_DELTA_CD) + icount->dcd++; + if (newMsr & ATEN_MSR_DELTA_RI) + icount->rng++; + } + + return 0; +} + +static int handle_newLsr(struct ATENINTL_port *port, __u8 newLsr) +{ + struct async_icount *icount; + + dbg("%s - %02x", __func__, newLsr); + + if (newLsr & SERIAL_LSR_BI) { + /* + * Parity and Framing errors only count if they occur exclusive + * of a break being received. + */ + newLsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI); + } + + /* update input line counters */ + icount = &port->icount; + if (newLsr & SERIAL_LSR_BI) + icount->brk++; + if (newLsr & SERIAL_LSR_OE) + icount->overrun++; + if (newLsr & SERIAL_LSR_PE) + icount->parity++; + if (newLsr & SERIAL_LSR_FE) + icount->frame++; + + return 0; +} + +static void ATEN2011_control_callback(struct urb *urb) +{ + unsigned char *data; + struct ATENINTL_port *ATEN2011_port; + __u8 regval = 0x0; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __func__, + urb->status); + goto exit; + } + + ATEN2011_port = (struct ATENINTL_port *)urb->context; + + dbg("%s urb buffer size is %d", __func__, urb->actual_length); + dbg("%s ATEN2011_port->MsrLsr is %d port %d", __func__, + ATEN2011_port->MsrLsr, ATEN2011_port->port_num); + data = urb->transfer_buffer; + regval = (__u8) data[0]; + dbg("%s data is %x", __func__, regval); + if (ATEN2011_port->MsrLsr == 0) + handle_newMsr(ATEN2011_port, regval); + else if (ATEN2011_port->MsrLsr == 1) + handle_newLsr(ATEN2011_port, regval); + +exit: + return; +} + +static int ATEN2011_get_reg(struct ATENINTL_port *ATEN, __u16 Wval, __u16 reg, + __u16 *val) +{ + struct usb_device *dev = ATEN->port->serial->dev; + struct usb_ctrlrequest *dr = NULL; + unsigned char *buffer = NULL; + int ret = 0; + buffer = (__u8 *) ATEN->ctrl_buf; + + dr = (void *)(buffer + 2); + dr->bRequestType = ATEN_RD_RTYPE; + dr->bRequest = ATEN_RDREQ; + dr->wValue = cpu_to_le16(Wval); + dr->wIndex = cpu_to_le16(reg); + dr->wLength = cpu_to_le16(2); + + usb_fill_control_urb(ATEN->control_urb, dev, usb_rcvctrlpipe(dev, 0), + (unsigned char *)dr, buffer, 2, + ATEN2011_control_callback, ATEN); + ATEN->control_urb->transfer_buffer_length = 2; + ret = usb_submit_urb(ATEN->control_urb, GFP_ATOMIC); + return ret; +} + +static void ATEN2011_interrupt_callback(struct urb *urb) +{ + int result; + int length; + struct ATENINTL_port *ATEN2011_port; + struct ATENINTL_serial *ATEN2011_serial; + struct usb_serial *serial; + __u16 Data; + unsigned char *data; + __u8 sp[5], st; + int i; + __u16 wval; + int minor; + + dbg("%s", " : Entering"); + + ATEN2011_serial = (struct ATENINTL_serial *)urb->context; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __func__, + urb->status); + goto exit; + } + length = urb->actual_length; + data = urb->transfer_buffer; + + serial = ATEN2011_serial->serial; + + /* ATENINTL get 5 bytes + * Byte 1 IIR Port 1 (port.number is 0) + * Byte 2 IIR Port 2 (port.number is 1) + * Byte 3 IIR Port 3 (port.number is 2) + * Byte 4 IIR Port 4 (port.number is 3) + * Byte 5 FIFO status for both */ + + if (length && length > 5) { + dbg("%s", "Wrong data !!!"); + return; + } + + /* MATRIX */ + if (ATEN2011_serial->ATEN2011_spectrum_2or4ports == 4) { + sp[0] = (__u8) data[0]; + sp[1] = (__u8) data[1]; + sp[2] = (__u8) data[2]; + sp[3] = (__u8) data[3]; + st = (__u8) data[4]; + } else { + sp[0] = (__u8) data[0]; + sp[1] = (__u8) data[2]; + /* sp[2]=(__u8)data[2]; */ + /* sp[3]=(__u8)data[3]; */ + st = (__u8) data[4]; + + } + for (i = 0; i < serial->num_ports; i++) { + ATEN2011_port = usb_get_serial_port_data(serial->port[i]); + minor = serial->minor; + if (minor == SERIAL_TTY_NO_MINOR) + minor = 0; + if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) + && (i != 0)) + wval = + (((__u16) serial->port[i]->number - + (__u16) (minor)) + 2) << 8; + else + wval = + (((__u16) serial->port[i]->number - + (__u16) (minor)) + 1) << 8; + if (ATEN2011_port->open != 0) { + if (sp[i] & 0x01) { + dbg("SP%d No Interrupt !!!", i); + } else { + switch (sp[i] & 0x0f) { + case SERIAL_IIR_RLS: + dbg("Serial Port %d: Receiver status error or address bit detected in 9-bit mode", i); + ATEN2011_port->MsrLsr = 1; + ATEN2011_get_reg(ATEN2011_port, wval, + LINE_STATUS_REGISTER, + &Data); + break; + case SERIAL_IIR_MS: + dbg("Serial Port %d: Modem status change", i); + ATEN2011_port->MsrLsr = 0; + ATEN2011_get_reg(ATEN2011_port, wval, + MODEM_STATUS_REGISTER, + &Data); + break; + } + } + } + + } +exit: + if (ATEN2011_serial->status_polling_started == 0) + return; + + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) { + dev_err(&urb->dev->dev, + "%s - Error %d submitting interrupt urb\n", + __func__, result); + } + + return; +} + +static void ATEN2011_bulk_in_callback(struct urb *urb) +{ + int status; + unsigned char *data; + struct usb_serial *serial; + struct usb_serial_port *port; + struct ATENINTL_serial *ATEN2011_serial; + struct ATENINTL_port *ATEN2011_port; + struct tty_struct *tty; + + if (urb->status) { + dbg("nonzero read bulk status received: %d", urb->status); + return; + } + + ATEN2011_port = (struct ATENINTL_port *)urb->context; + + port = (struct usb_serial_port *)ATEN2011_port->port; + serial = port->serial; + + dbg("%s", "Entering..."); + + data = urb->transfer_buffer; + ATEN2011_serial = usb_get_serial_data(serial); + + if (urb->actual_length) { + tty = tty_port_tty_get(&ATEN2011_port->port->port); + if (tty) { + tty_buffer_request_room(tty, urb->actual_length); + tty_insert_flip_string(tty, data, urb->actual_length); + tty_flip_buffer_push(tty); + tty_kref_put(tty); + } + + ATEN2011_port->icount.rx += urb->actual_length; + dbg("ATEN2011_port->icount.rx is %d:", + ATEN2011_port->icount.rx); + } + + if (!ATEN2011_port->read_urb) { + dbg("%s", "URB KILLED !!!"); + return; + } + + if (ATEN2011_port->read_urb->status != -EINPROGRESS) { + ATEN2011_port->read_urb->dev = serial->dev; + + status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC); + if (status) + dbg("usb_submit_urb(read bulk) failed, status = %d", status); + } +} + +static void ATEN2011_bulk_out_data_callback(struct urb *urb) +{ + struct ATENINTL_port *ATEN2011_port; + struct tty_struct *tty; + + if (urb->status) { + dbg("nonzero write bulk status received:%d", urb->status); + return; + } + + ATEN2011_port = (struct ATENINTL_port *)urb->context; + + dbg("%s", "Entering ........."); + + tty = tty_port_tty_get(&ATEN2011_port->port->port); + + if (tty && ATEN2011_port->open) { + /* tell the tty driver that something has changed */ + wake_up_interruptible(&tty->write_wait); + } + + /* schedule_work(&ATEN2011_port->port->work); */ + tty_kref_put(tty); + +} + +#ifdef ATENSerialProbe +static int ATEN2011_serial_probe(struct usb_serial *serial, + const struct usb_device_id *id) +{ + + /*need to implement the mode_reg reading and updating\ + structures usb_serial_ device_type\ + (i.e num_ports, num_bulkin,bulkout etc) */ + /* Also we can update the changes attach */ + return 1; +} +#endif + +static int ATEN2011_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + int response; + int j; + struct usb_serial *serial; + struct urb *urb; + __u16 Data; + int status; + struct ATENINTL_serial *ATEN2011_serial; + struct ATENINTL_port *ATEN2011_port; + struct ktermios tmp_termios; + int minor; + + serial = port->serial; + + ATEN2011_port = usb_get_serial_port_data(port); + + if (ATEN2011_port == NULL) + return -ENODEV; + + ATEN2011_serial = usb_get_serial_data(serial); + if (ATEN2011_serial == NULL) + return -ENODEV; + + /* increment the number of opened ports counter here */ + ATEN2011_serial->NoOfOpenPorts++; + + usb_clear_halt(serial->dev, port->write_urb->pipe); + usb_clear_halt(serial->dev, port->read_urb->pipe); + + /* Initialising the write urb pool */ + for (j = 0; j < NUM_URBS; ++j) { + urb = usb_alloc_urb(0, GFP_ATOMIC); + ATEN2011_port->write_urb_pool[j] = urb; + + if (urb == NULL) { + err("No more urbs???"); + continue; + } + + urb->transfer_buffer = NULL; + urb->transfer_buffer = + kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + if (!urb->transfer_buffer) { + err("%s-out of memory for urb buffers.", __func__); + continue; + } + } + +/***************************************************************************** + * Initialize ATEN2011 -- Write Init values to corresponding Registers + * + * Register Index + * 1 : IER + * 2 : FCR + * 3 : LCR + * 4 : MCR + * + * 0x08 : SP1/2 Control Reg + *****************************************************************************/ + +/* NEED to check the fallowing Block */ + + Data = 0x0; + status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data); + if (status < 0) { + dbg("Reading Spreg failed"); + return -1; + } + Data |= 0x80; + status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); + if (status < 0) { + dbg("writing Spreg failed"); + return -1; + } + + Data &= ~0x80; + status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); + if (status < 0) { + dbg("writing Spreg failed"); + return -1; + } + +/* End of block to be checked */ +/**************************CHECK***************************/ + + if (RS485mode == 0) + Data = 0xC0; + else + Data = 0x00; + status = set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); + if (status < 0) { + dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x", status); + return -1; + } else + dbg("SCRATCH_PAD_REGISTER Writing success status%d", status); + +/**************************CHECK***************************/ + + Data = 0x0; + status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data); + if (status < 0) { + dbg("Reading Controlreg failed"); + return -1; + } + Data |= 0x08; /* Driver done bit */ + Data |= 0x20; /* rx_disable */ + status = 0; + status = + set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data); + if (status < 0) { + dbg("writing Controlreg failed"); + return -1; + } + /* + * do register settings here + * Set all regs to the device default values. + * First Disable all interrupts. + */ + + Data = 0x00; + status = set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); + if (status < 0) { + dbg("disableing interrupts failed"); + return -1; + } + /* Set FIFO_CONTROL_REGISTER to the default value */ + Data = 0x00; + status = set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); + if (status < 0) { + dbg("Writing FIFO_CONTROL_REGISTER failed"); + return -1; + } + + Data = 0xcf; /* chk */ + status = set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); + if (status < 0) { + dbg("Writing FIFO_CONTROL_REGISTER failed"); + return -1; + } + + Data = 0x03; /* LCR_BITS_8 */ + status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data); + ATEN2011_port->shadowLCR = Data; + + Data = 0x0b; /* MCR_DTR|MCR_RTS|MCR_MASTER_IE */ + status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + ATEN2011_port->shadowMCR = Data; + +#ifdef Check + Data = 0x00; + status = get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); + ATEN2011_port->shadowLCR = Data; + + Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */ + status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data); + + Data = 0x0c; + status = set_uart_reg(port, DIVISOR_LATCH_LSB, Data); + + Data = 0x0; + status = set_uart_reg(port, DIVISOR_LATCH_MSB, Data); + + Data = 0x00; + status = get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); + +/* Data = ATEN2011_port->shadowLCR; */ /* data latch disable */ + Data = Data & ~SERIAL_LCR_DLAB; + status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data); + ATEN2011_port->shadowLCR = Data; +#endif + /* clearing Bulkin and Bulkout Fifo */ + Data = 0x0; + status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data); + + Data = Data | 0x0c; + status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); + + Data = Data & ~0x0c; + status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); + /* Finally enable all interrupts */ + Data = 0x0; + Data = 0x0c; + status = set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); + + /* clearing rx_disable */ + Data = 0x0; + status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data); + Data = Data & ~0x20; + status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data); + + /* rx_negate */ + Data = 0x0; + status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data); + Data = Data | 0x10; + status = 0; + status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data); + + /* force low_latency on so that our tty_push actually forces * + * the data through,otherwise it is scheduled, and with * + * high data rates (like with OHCI) data can get lost. */ + + if (tty) + tty->low_latency = 1; + /* + * Check to see if we've set up our endpoint info yet + * (can't set it up in ATEN2011_startup as the structures + * were not set up at that time.) + */ + if (ATEN2011_serial->NoOfOpenPorts == 1) { + /* start the status polling here */ + ATEN2011_serial->status_polling_started = 1; + /* If not yet set, Set here */ + ATEN2011_serial->interrupt_in_buffer = + serial->port[0]->interrupt_in_buffer; + ATEN2011_serial->interrupt_in_endpoint = + serial->port[0]->interrupt_in_endpointAddress; + ATEN2011_serial->interrupt_read_urb = + serial->port[0]->interrupt_in_urb; + + /* set up interrupt urb */ + usb_fill_int_urb(ATEN2011_serial->interrupt_read_urb, + serial->dev, + usb_rcvintpipe(serial->dev, + ATEN2011_serial-> + interrupt_in_endpoint), + ATEN2011_serial->interrupt_in_buffer, + ATEN2011_serial->interrupt_read_urb-> + transfer_buffer_length, + ATEN2011_interrupt_callback, ATEN2011_serial, + ATEN2011_serial->interrupt_read_urb->interval); + + /* start interrupt read for ATEN2011 * + * will continue as long as ATEN2011 is connected */ + + response = + usb_submit_urb(ATEN2011_serial->interrupt_read_urb, + GFP_KERNEL); + if (response) { + dbg("%s - Error %d submitting interrupt urb", + __func__, response); + } + + } + + /* + * See if we've set up our endpoint info yet + * (can't set it up in ATEN2011_startup as the + * structures were not set up at that time.) + */ + + dbg("port number is %d", port->number); + dbg("serial number is %d", port->serial->minor); + dbg("Bulkin endpoint is %d", port->bulk_in_endpointAddress); + dbg("BulkOut endpoint is %d", port->bulk_out_endpointAddress); + dbg("Interrupt endpoint is %d", + port->interrupt_in_endpointAddress); + dbg("port's number in the device is %d", ATEN2011_port->port_num); + ATEN2011_port->bulk_in_buffer = port->bulk_in_buffer; + ATEN2011_port->bulk_in_endpoint = port->bulk_in_endpointAddress; + ATEN2011_port->read_urb = port->read_urb; + ATEN2011_port->bulk_out_endpoint = port->bulk_out_endpointAddress; + + minor = port->serial->minor; + if (minor == SERIAL_TTY_NO_MINOR) + minor = 0; + + /* set up our bulk in urb */ + if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) + && (((__u16) port->number - (__u16) (minor)) != 0)) { + usb_fill_bulk_urb(ATEN2011_port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + (port-> + bulk_in_endpointAddress + + 2)), port->bulk_in_buffer, + ATEN2011_port->read_urb-> + transfer_buffer_length, + ATEN2011_bulk_in_callback, ATEN2011_port); + } else + usb_fill_bulk_urb(ATEN2011_port->read_urb, + serial->dev, + usb_rcvbulkpipe(serial->dev, + port-> + bulk_in_endpointAddress), + port->bulk_in_buffer, + ATEN2011_port->read_urb-> + transfer_buffer_length, + ATEN2011_bulk_in_callback, ATEN2011_port); + + dbg("ATEN2011_open: bulkin endpoint is %d", + port->bulk_in_endpointAddress); + response = usb_submit_urb(ATEN2011_port->read_urb, GFP_KERNEL); + if (response) { + err("%s - Error %d submitting control urb", __func__, + response); + } + + /* initialize our wait queues */ + init_waitqueue_head(&ATEN2011_port->wait_chase); + init_waitqueue_head(&ATEN2011_port->wait_command); + + /* initialize our icount structure */ + memset(&(ATEN2011_port->icount), 0x00, sizeof(ATEN2011_port->icount)); + + /* initialize our port settings */ + ATEN2011_port->shadowMCR = MCR_MASTER_IE; /* Must set to enable ints! */ + ATEN2011_port->chaseResponsePending = 0; + /* send a open port command */ + ATEN2011_port->open = 1; + /* ATEN2011_change_port_settings(ATEN2011_port,old_termios); */ + /* Setup termios */ + ATEN2011_set_termios(tty, port, &tmp_termios); + ATEN2011_port->icount.tx = 0; + ATEN2011_port->icount.rx = 0; + + dbg("usb_serial serial:%x ATEN2011_port:%x\nATEN2011_serial:%x usb_serial_port port:%x", + (unsigned int)serial, (unsigned int)ATEN2011_port, + (unsigned int)ATEN2011_serial, (unsigned int)port); + + return 0; + +} + +static int ATEN2011_chars_in_buffer(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + int i; + int chars = 0; + struct ATENINTL_port *ATEN2011_port; + + /* dbg("%s"," ATEN2011_chars_in_buffer:entering ..........."); */ + + ATEN2011_port = usb_get_serial_port_data(port); + if (ATEN2011_port == NULL) { + dbg("%s", "ATEN2011_break:leaving ..........."); + return -1; + } + + for (i = 0; i < NUM_URBS; ++i) + if (ATEN2011_port->write_urb_pool[i]->status == -EINPROGRESS) + chars += URB_TRANSFER_BUFFER_SIZE; + + dbg("%s - returns %d", __func__, chars); + return chars; + +} + +static void ATEN2011_block_until_tx_empty(struct tty_struct *tty, + struct ATENINTL_port *ATEN2011_port) +{ + int timeout = HZ / 10; + int wait = 30; + int count; + + while (1) { + count = ATEN2011_chars_in_buffer(tty); + + /* Check for Buffer status */ + if (count <= 0) + return; + + /* Block the thread for a while */ + interruptible_sleep_on_timeout(&ATEN2011_port->wait_chase, + timeout); + + /* No activity.. count down section */ + wait--; + if (wait == 0) { + dbg("%s - TIMEOUT", __func__); + return; + } else { + /* Reset timout value back to seconds */ + wait = 30; + } + } +} + +static void ATEN2011_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct usb_serial *serial; + struct ATENINTL_serial *ATEN2011_serial; + struct ATENINTL_port *ATEN2011_port; + int no_urbs; + __u16 Data; + + dbg("%s", "ATEN2011_close:entering..."); + serial = port->serial; + + /* take the Adpater and port's private data */ + ATEN2011_serial = usb_get_serial_data(serial); + ATEN2011_port = usb_get_serial_port_data(port); + if ((ATEN2011_serial == NULL) || (ATEN2011_port == NULL)) + return; + + if (serial->dev) { + /* flush and block(wait) until tx is empty */ + ATEN2011_block_until_tx_empty(tty, ATEN2011_port); + } + /* kill the ports URB's */ + for (no_urbs = 0; no_urbs < NUM_URBS; no_urbs++) + usb_kill_urb(ATEN2011_port->write_urb_pool[no_urbs]); + /* Freeing Write URBs */ + for (no_urbs = 0; no_urbs < NUM_URBS; ++no_urbs) { + kfree(ATEN2011_port->write_urb_pool[no_urbs]->transfer_buffer); + usb_free_urb(ATEN2011_port->write_urb_pool[no_urbs]); + } + /* While closing port, shutdown all bulk read, write * + * and interrupt read if they exists */ + if (serial->dev) { + if (ATEN2011_port->write_urb) { + dbg("%s", "Shutdown bulk write"); + usb_kill_urb(ATEN2011_port->write_urb); + } + if (ATEN2011_port->read_urb) { + dbg("%s", "Shutdown bulk read"); + usb_kill_urb(ATEN2011_port->read_urb); + } + if ((&ATEN2011_port->control_urb)) { + dbg("%s", "Shutdown control read"); + /* usb_kill_urb (ATEN2011_port->control_urb); */ + + } + } + /* if(ATEN2011_port->ctrl_buf != NULL) */ + /* kfree(ATEN2011_port->ctrl_buf); */ + /* decrement the no.of open ports counter of an individual USB-serial adapter. */ + ATEN2011_serial->NoOfOpenPorts--; + dbg("NoOfOpenPorts in close%d:in port%d", + ATEN2011_serial->NoOfOpenPorts, port->number); + if (ATEN2011_serial->NoOfOpenPorts == 0) { + /* stop the stus polling here */ + ATEN2011_serial->status_polling_started = 0; + if (ATEN2011_serial->interrupt_read_urb) { + dbg("%s", "Shutdown interrupt_read_urb"); + /* ATEN2011_serial->interrupt_in_buffer=NULL; */ + /* usb_kill_urb (ATEN2011_serial->interrupt_read_urb); */ + } + } + if (ATEN2011_port->write_urb) { + /* if this urb had a transfer buffer already (old tx) free it */ + kfree(ATEN2011_port->write_urb->transfer_buffer); + usb_free_urb(ATEN2011_port->write_urb); + } + + /* clear the MCR & IER */ + Data = 0x00; + set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + Data = 0x00; + set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); + + ATEN2011_port->open = 0; + dbg("%s", "Leaving ............"); + +} + +static void ATEN2011_block_until_chase_response(struct tty_struct *tty, + struct ATENINTL_port + *ATEN2011_port) +{ + int timeout = 1 * HZ; + int wait = 10; + int count; + + while (1) { + count = ATEN2011_chars_in_buffer(tty); + + /* Check for Buffer status */ + if (count <= 0) { + ATEN2011_port->chaseResponsePending = 0; + return; + } + + /* Block the thread for a while */ + interruptible_sleep_on_timeout(&ATEN2011_port->wait_chase, + timeout); + /* No activity.. count down section */ + wait--; + if (wait == 0) { + dbg("%s - TIMEOUT", __func__); + return; + } else { + /* Reset timout value back to seconds */ + wait = 10; + } + } + +} + +static void ATEN2011_break(struct tty_struct *tty, int break_state) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned char data; + struct usb_serial *serial; + struct ATENINTL_serial *ATEN2011_serial; + struct ATENINTL_port *ATEN2011_port; + + dbg("%s", "Entering ..........."); + dbg("ATEN2011_break: Start"); + + serial = port->serial; + + ATEN2011_serial = usb_get_serial_data(serial); + ATEN2011_port = usb_get_serial_port_data(port); + + if ((ATEN2011_serial == NULL) || (ATEN2011_port == NULL)) + return; + + /* flush and chase */ + ATEN2011_port->chaseResponsePending = 1; + + if (serial->dev) { + /* flush and block until tx is empty */ + ATEN2011_block_until_chase_response(tty, ATEN2011_port); + } + + if (break_state == -1) + data = ATEN2011_port->shadowLCR | LCR_SET_BREAK; + else + data = ATEN2011_port->shadowLCR & ~LCR_SET_BREAK; + + ATEN2011_port->shadowLCR = data; + dbg("ATEN2011_break ATEN2011_port->shadowLCR is %x", + ATEN2011_port->shadowLCR); + set_uart_reg(port, LINE_CONTROL_REGISTER, ATEN2011_port->shadowLCR); + + return; +} + +static int ATEN2011_write_room(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + int i; + int room = 0; + struct ATENINTL_port *ATEN2011_port; + + ATEN2011_port = usb_get_serial_port_data(port); + if (ATEN2011_port == NULL) { + dbg("%s", "ATEN2011_break:leaving ..........."); + return -1; + } + + for (i = 0; i < NUM_URBS; ++i) + if (ATEN2011_port->write_urb_pool[i]->status != -EINPROGRESS) + room += URB_TRANSFER_BUFFER_SIZE; + + dbg("%s - returns %d", __func__, room); + return room; + +} + +static int ATEN2011_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *data, int count) +{ + int status; + int i; + int bytes_sent = 0; + int transfer_size; + int minor; + + struct ATENINTL_port *ATEN2011_port; + struct usb_serial *serial; + struct ATENINTL_serial *ATEN2011_serial; + struct urb *urb; + const unsigned char *current_position = data; + unsigned char *data1; + dbg("%s", "entering ..........."); + + serial = port->serial; + + ATEN2011_port = usb_get_serial_port_data(port); + if (ATEN2011_port == NULL) { + dbg("%s", "ATEN2011_port is NULL"); + return -1; + } + + ATEN2011_serial = usb_get_serial_data(serial); + if (ATEN2011_serial == NULL) { + dbg("%s", "ATEN2011_serial is NULL"); + return -1; + } + + /* try to find a free urb in the list */ + urb = NULL; + + for (i = 0; i < NUM_URBS; ++i) { + if (ATEN2011_port->write_urb_pool[i]->status != -EINPROGRESS) { + urb = ATEN2011_port->write_urb_pool[i]; + dbg("URB:%d", i); + break; + } + } + + if (urb == NULL) { + dbg("%s - no more free urbs", __func__); + goto exit; + } + + if (urb->transfer_buffer == NULL) { + urb->transfer_buffer = + kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + + if (urb->transfer_buffer == NULL) { + err("%s no more kernel memory...", __func__); + goto exit; + } + } + transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); + + memcpy(urb->transfer_buffer, current_position, transfer_size); + /* usb_serial_debug_data (__FILE__, __func__, transfer_size, urb->transfer_buffer); */ + + /* fill urb with data and submit */ + minor = port->serial->minor; + if (minor == SERIAL_TTY_NO_MINOR) + minor = 0; + if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) + && (((__u16) port->number - (__u16) (minor)) != 0)) { + usb_fill_bulk_urb(urb, ATEN2011_serial->serial->dev, + usb_sndbulkpipe(ATEN2011_serial->serial->dev, + (port-> + bulk_out_endpointAddress) + + 2), urb->transfer_buffer, + transfer_size, + ATEN2011_bulk_out_data_callback, + ATEN2011_port); + } else + + usb_fill_bulk_urb(urb, + ATEN2011_serial->serial->dev, + usb_sndbulkpipe(ATEN2011_serial->serial->dev, + port-> + bulk_out_endpointAddress), + urb->transfer_buffer, transfer_size, + ATEN2011_bulk_out_data_callback, + ATEN2011_port); + + data1 = urb->transfer_buffer; + dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress); + /* for(i=0;i < urb->actual_length;i++) */ + /* dbg("Data is %c ",data1[i]); */ + + /* send it down the pipe */ + status = usb_submit_urb(urb, GFP_ATOMIC); + + if (status) { + err("%s - usb_submit_urb(write bulk) failed with status = %d", + __func__, status); + bytes_sent = status; + goto exit; + } + bytes_sent = transfer_size; + ATEN2011_port->icount.tx += transfer_size; + dbg("ATEN2011_port->icount.tx is %d:", ATEN2011_port->icount.tx); + +exit: + return bytes_sent; +} + +static void ATEN2011_throttle(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct ATENINTL_port *ATEN2011_port; + int status; + + dbg("- port %d", port->number); + + ATEN2011_port = usb_get_serial_port_data(port); + + if (ATEN2011_port == NULL) + return; + + if (!ATEN2011_port->open) { + dbg("%s", "port not opened"); + return; + } + + dbg("%s", "Entering .......... "); + + if (!tty) { + dbg("%s - no tty available", __func__); + return; + } + + /* if we are implementing XON/XOFF, send the stop character */ + if (I_IXOFF(tty)) { + unsigned char stop_char = STOP_CHAR(tty); + status = ATEN2011_write(tty, port, &stop_char, 1); + if (status <= 0) + return; + } + + /* if we are implementing RTS/CTS, toggle that line */ + if (tty->termios->c_cflag & CRTSCTS) { + ATEN2011_port->shadowMCR &= ~MCR_RTS; + status = set_uart_reg(port, MODEM_CONTROL_REGISTER, + ATEN2011_port->shadowMCR); + if (status < 0) + return; + } + + return; +} + +static void ATEN2011_unthrottle(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + int status; + struct ATENINTL_port *ATEN2011_port = usb_get_serial_port_data(port); + + if (ATEN2011_port == NULL) + return; + + if (!ATEN2011_port->open) { + dbg("%s - port not opened", __func__); + return; + } + + dbg("%s", "Entering .......... "); + + if (!tty) { + dbg("%s - no tty available", __func__); + return; + } + + /* if we are implementing XON/XOFF, send the start character */ + if (I_IXOFF(tty)) { + unsigned char start_char = START_CHAR(tty); + status = ATEN2011_write(tty, port, &start_char, 1); + if (status <= 0) + return; + } + + /* if we are implementing RTS/CTS, toggle that line */ + if (tty->termios->c_cflag & CRTSCTS) { + ATEN2011_port->shadowMCR |= MCR_RTS; + status = set_uart_reg(port, MODEM_CONTROL_REGISTER, + ATEN2011_port->shadowMCR); + if (status < 0) + return; + } + + return; +} + +static int ATEN2011_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + struct ATENINTL_port *ATEN2011_port; + unsigned int result; + __u16 msr; + __u16 mcr; + /* unsigned int mcr; */ + int status = 0; + ATEN2011_port = usb_get_serial_port_data(port); + + dbg("%s - port %d", __func__, port->number); + + if (ATEN2011_port == NULL) + return -ENODEV; + + status = get_uart_reg(port, MODEM_STATUS_REGISTER, &msr); + status = get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr); + /* mcr = ATEN2011_port->shadowMCR; */ + /* COMMENT2: the Fallowing three line are commented for updating only MSR values */ + result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) + | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) + | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0) + | ((msr & ATEN2011_MSR_CTS) ? TIOCM_CTS : 0) + | ((msr & ATEN2011_MSR_CD) ? TIOCM_CAR : 0) + | ((msr & ATEN2011_MSR_RI) ? TIOCM_RI : 0) + | ((msr & ATEN2011_MSR_DSR) ? TIOCM_DSR : 0); + + dbg("%s - 0x%04X", __func__, result); + + return result; +} + +static int ATEN2011_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + struct ATENINTL_port *ATEN2011_port; + unsigned int mcr; + unsigned int status; + + dbg("%s - port %d", __func__, port->number); + + ATEN2011_port = usb_get_serial_port_data(port); + + if (ATEN2011_port == NULL) + return -ENODEV; + + mcr = ATEN2011_port->shadowMCR; + if (clear & TIOCM_RTS) + mcr &= ~MCR_RTS; + if (clear & TIOCM_DTR) + mcr &= ~MCR_DTR; + if (clear & TIOCM_LOOP) + mcr &= ~MCR_LOOPBACK; + + if (set & TIOCM_RTS) + mcr |= MCR_RTS; + if (set & TIOCM_DTR) + mcr |= MCR_DTR; + if (set & TIOCM_LOOP) + mcr |= MCR_LOOPBACK; + + ATEN2011_port->shadowMCR = mcr; + + status = set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr); + if (status < 0) { + dbg("setting MODEM_CONTROL_REGISTER Failed"); + return -1; + } + + return 0; +} + +static void ATEN2011_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, + struct ktermios *old_termios) +{ + int status; + unsigned int cflag; + struct usb_serial *serial; + struct ATENINTL_port *ATEN2011_port; + + dbg("ATEN2011_set_termios: START"); + + serial = port->serial; + + ATEN2011_port = usb_get_serial_port_data(port); + + if (ATEN2011_port == NULL) + return; + + if (!ATEN2011_port->open) { + dbg("%s - port not opened", __func__); + return; + } + + dbg("%s", "setting termios - "); + + cflag = tty->termios->c_cflag; + + if (!cflag) { + dbg("%s %s", __func__, "cflag is NULL"); + return; + } + + /* check that they really want us to change something */ + if (old_termios) { + if ((cflag == old_termios->c_cflag) && + (RELEVANT_IFLAG(tty->termios->c_iflag) == + RELEVANT_IFLAG(old_termios->c_iflag))) { + dbg("%s", "Nothing to change"); + return; + } + } + + dbg("%s - clfag %08x iflag %08x", __func__, + tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); + + if (old_termios) { + dbg("%s - old clfag %08x old iflag %08x", __func__, + old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); + } + + dbg("%s - port %d", __func__, port->number); + + /* change the port settings to the new ones specified */ + + ATEN2011_change_port_settings(tty, ATEN2011_port, old_termios); + + if (!ATEN2011_port->read_urb) { + dbg("%s", "URB KILLED !!!!!"); + return; + } + + if (ATEN2011_port->read_urb->status != -EINPROGRESS) { + ATEN2011_port->read_urb->dev = serial->dev; + status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC); + if (status) { + dbg + (" usb_submit_urb(read bulk) failed, status = %d", + status); + } + } + return; +} + +static int get_lsr_info(struct tty_struct *tty, + struct ATENINTL_port *ATEN2011_port, + unsigned int __user *value) +{ + int count; + unsigned int result = 0; + + count = ATEN2011_chars_in_buffer(tty); + if (count == 0) { + dbg("%s -- Empty", __func__); + result = TIOCSER_TEMT; + } + + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + return 0; +} + +static int get_number_bytes_avail(struct tty_struct *tty, + struct ATENINTL_port *ATEN2011_port, + unsigned int __user *value) +{ + unsigned int result = 0; + + if (!tty) + return -ENOIOCTLCMD; + + result = tty->read_cnt; + + dbg("%s(%d) = %d", __func__, ATEN2011_port->port->number, result); + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + + return -ENOIOCTLCMD; +} + +static int set_modem_info(struct ATENINTL_port *ATEN2011_port, unsigned int cmd, + unsigned int __user *value) +{ + unsigned int mcr; + unsigned int arg; + __u16 Data; + int status; + struct usb_serial_port *port; + + if (ATEN2011_port == NULL) + return -1; + + port = (struct usb_serial_port *)ATEN2011_port->port; + + mcr = ATEN2011_port->shadowMCR; + + if (copy_from_user(&arg, value, sizeof(int))) + return -EFAULT; + + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + mcr |= MCR_RTS; + if (arg & TIOCM_DTR) + mcr |= MCR_RTS; + if (arg & TIOCM_LOOP) + mcr |= MCR_LOOPBACK; + break; + + case TIOCMBIC: + if (arg & TIOCM_RTS) + mcr &= ~MCR_RTS; + if (arg & TIOCM_DTR) + mcr &= ~MCR_RTS; + if (arg & TIOCM_LOOP) + mcr &= ~MCR_LOOPBACK; + break; + + case TIOCMSET: + /* turn off the RTS and DTR and LOOPBACK + * and then only turn on what was asked to */ + mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK); + mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0); + mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0); + mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0); + break; + } + + ATEN2011_port->shadowMCR = mcr; + + Data = ATEN2011_port->shadowMCR; + status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + if (status < 0) { + dbg("setting MODEM_CONTROL_REGISTER Failed"); + return -1; + } + + return 0; +} + +static int get_modem_info(struct ATENINTL_port *ATEN2011_port, + unsigned int __user *value) +{ + unsigned int result = 0; + __u16 msr; + unsigned int mcr = ATEN2011_port->shadowMCR; + int status; + + status = get_uart_reg(ATEN2011_port->port, MODEM_STATUS_REGISTER, &msr); + result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */ + |((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */ + |((msr & ATEN2011_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */ + |((msr & ATEN2011_MSR_CD) ? TIOCM_CAR : 0) /* 0x040 */ + |((msr & ATEN2011_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */ + |((msr & ATEN2011_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */ + + dbg("%s -- %x", __func__, result); + + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + return 0; +} + +static int get_serial_info(struct ATENINTL_port *ATEN2011_port, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp; + + if (ATEN2011_port == NULL) + return -1; + + if (!retinfo) + return -EFAULT; + + memset(&tmp, 0, sizeof(tmp)); + + tmp.type = PORT_16550A; + tmp.line = ATEN2011_port->port->serial->minor; + if (tmp.line == SERIAL_TTY_NO_MINOR) + tmp.line = 0; + tmp.port = ATEN2011_port->port->number; + tmp.irq = 0; + tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; + tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; + tmp.baud_base = 9600; + tmp.close_delay = 5 * HZ; + tmp.closing_wait = 30 * HZ; + + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int ATEN2011_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + struct ATENINTL_port *ATEN2011_port; + struct async_icount cnow; + struct async_icount cprev; + struct serial_icounter_struct icount; + int ATENret = 0; + unsigned int __user *user_arg = (unsigned int __user *)arg; + + ATEN2011_port = usb_get_serial_port_data(port); + + if (ATEN2011_port == NULL) + return -1; + + dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + + switch (cmd) { + /* return number of bytes available */ + + case TIOCINQ: + dbg("%s (%d) TIOCINQ", __func__, port->number); + return get_number_bytes_avail(tty, ATEN2011_port, user_arg); + break; + + case TIOCOUTQ: + dbg("%s (%d) TIOCOUTQ", __func__, port->number); + return put_user(ATEN2011_chars_in_buffer(tty), user_arg); + break; + + case TIOCSERGETLSR: + dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); + return get_lsr_info(tty, ATEN2011_port, user_arg); + return 0; + + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__, + port->number); + ATENret = set_modem_info(ATEN2011_port, cmd, user_arg); + return ATENret; + + case TIOCMGET: + dbg("%s (%d) TIOCMGET", __func__, port->number); + return get_modem_info(ATEN2011_port, user_arg); + + case TIOCGSERIAL: + dbg("%s (%d) TIOCGSERIAL", __func__, port->number); + return get_serial_info(ATEN2011_port, + (struct serial_struct __user *)arg); + + case TIOCSSERIAL: + dbg("%s (%d) TIOCSSERIAL", __func__, port->number); + break; + + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + cprev = ATEN2011_port->icount; + while (1) { + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + cnow = ATEN2011_port->icount; + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ + break; + + case TIOCGICOUNT: + cnow = ATEN2011_port->icount; + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, + port->number, icount.rx, icount.tx); + if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) + return -EFAULT; + return 0; + + default: + break; + } + + return -ENOIOCTLCMD; +} + +static int ATEN2011_calc_baud_rate_divisor(int baudRate, int *divisor, + __u16 *clk_sel_val) +{ + dbg("%s - %d", __func__, baudRate); + + if (baudRate <= 115200) { + *divisor = 115200 / baudRate; + *clk_sel_val = 0x0; + } + if ((baudRate > 115200) && (baudRate <= 230400)) { + *divisor = 230400 / baudRate; + *clk_sel_val = 0x10; + } else if ((baudRate > 230400) && (baudRate <= 403200)) { + *divisor = 403200 / baudRate; + *clk_sel_val = 0x20; + } else if ((baudRate > 403200) && (baudRate <= 460800)) { + *divisor = 460800 / baudRate; + *clk_sel_val = 0x30; + } else if ((baudRate > 460800) && (baudRate <= 806400)) { + *divisor = 806400 / baudRate; + *clk_sel_val = 0x40; + } else if ((baudRate > 806400) && (baudRate <= 921600)) { + *divisor = 921600 / baudRate; + *clk_sel_val = 0x50; + } else if ((baudRate > 921600) && (baudRate <= 1572864)) { + *divisor = 1572864 / baudRate; + *clk_sel_val = 0x60; + } else if ((baudRate > 1572864) && (baudRate <= 3145728)) { + *divisor = 3145728 / baudRate; + *clk_sel_val = 0x70; + } + return 0; +} + +static int ATEN2011_send_cmd_write_baud_rate(struct ATENINTL_port + *ATEN2011_port, int baudRate) +{ + int divisor = 0; + int status; + __u16 Data; + unsigned char number; + __u16 clk_sel_val; + struct usb_serial_port *port; + int minor; + + if (ATEN2011_port == NULL) + return -1; + + port = (struct usb_serial_port *)ATEN2011_port->port; + + dbg("%s", "Entering .......... "); + + minor = ATEN2011_port->port->serial->minor; + if (minor == SERIAL_TTY_NO_MINOR) + minor = 0; + number = ATEN2011_port->port->number - minor; + + dbg("%s - port = %d, baud = %d", __func__, + ATEN2011_port->port->number, baudRate); + /* reset clk_uart_sel in spregOffset */ + if (baudRate > 115200) { +#ifdef HW_flow_control + /* + * NOTE: need to see the pther register to modify + * setting h/w flow control bit to 1; + */ + /* Data = ATEN2011_port->shadowMCR; */ + Data = 0x2b; + ATEN2011_port->shadowMCR = Data; + status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + if (status < 0) { + dbg("Writing spreg failed in set_serial_baud"); + return -1; + } +#endif + + } else { +#ifdef HW_flow_control + /* setting h/w flow control bit to 0; */ + /* Data = ATEN2011_port->shadowMCR; */ + Data = 0xb; + ATEN2011_port->shadowMCR = Data; + status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + if (status < 0) { + dbg("Writing spreg failed in set_serial_baud"); + return -1; + } +#endif + + } + + if (1) /* baudRate <= 115200) */ { + clk_sel_val = 0x0; + Data = 0x0; + status = + ATEN2011_calc_baud_rate_divisor(baudRate, &divisor, + &clk_sel_val); + status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data); + if (status < 0) { + dbg("reading spreg failed in set_serial_baud"); + return -1; + } + Data = (Data & 0x8f) | clk_sel_val; + status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data); + if (status < 0) { + dbg("Writing spreg failed in set_serial_baud"); + return -1; + } + /* Calculate the Divisor */ + + if (status) { + err("%s - bad baud rate", __func__); + dbg("%s", "bad baud rate"); + return status; + } + /* Enable access to divisor latch */ + Data = ATEN2011_port->shadowLCR | SERIAL_LCR_DLAB; + ATEN2011_port->shadowLCR = Data; + set_uart_reg(port, LINE_CONTROL_REGISTER, Data); + + /* Write the divisor */ + Data = (unsigned char)(divisor & 0xff); + dbg("set_serial_baud Value to write DLL is %x", Data); + set_uart_reg(port, DIVISOR_LATCH_LSB, Data); + + Data = (unsigned char)((divisor & 0xff00) >> 8); + dbg("set_serial_baud Value to write DLM is %x", Data); + set_uart_reg(port, DIVISOR_LATCH_MSB, Data); + + /* Disable access to divisor latch */ + Data = ATEN2011_port->shadowLCR & ~SERIAL_LCR_DLAB; + ATEN2011_port->shadowLCR = Data; + set_uart_reg(port, LINE_CONTROL_REGISTER, Data); + + } + + return status; +} + +static void ATEN2011_change_port_settings(struct tty_struct *tty, + struct ATENINTL_port *ATEN2011_port, + struct ktermios *old_termios) +{ + int baud; + unsigned cflag; + unsigned iflag; + __u8 lData; + __u8 lParity; + __u8 lStop; + int status; + __u16 Data; + struct usb_serial_port *port; + struct usb_serial *serial; + + if (ATEN2011_port == NULL) + return; + + port = (struct usb_serial_port *)ATEN2011_port->port; + + serial = port->serial; + + dbg("%s - port %d", __func__, ATEN2011_port->port->number); + + if (!ATEN2011_port->open) { + dbg("%s - port not opened", __func__); + return; + } + + if ((!tty) || (!tty->termios)) { + dbg("%s - no tty structures", __func__); + return; + } + + dbg("%s", "Entering .......... "); + + lData = LCR_BITS_8; + lStop = LCR_STOP_1; + lParity = LCR_PAR_NONE; + + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; + + /* Change the number of bits */ + + /* COMMENT1: the below Line"if(cflag & CSIZE)" is added for the errors we get for serial loop data test i.e serial_loopback.pl -v */ + /* if(cflag & CSIZE) */ + { + switch (cflag & CSIZE) { + case CS5: + lData = LCR_BITS_5; + break; + + case CS6: + lData = LCR_BITS_6; + break; + + case CS7: + lData = LCR_BITS_7; + break; + default: + case CS8: + lData = LCR_BITS_8; + break; + } + } + /* Change the Parity bit */ + if (cflag & PARENB) { + if (cflag & PARODD) { + lParity = LCR_PAR_ODD; + dbg("%s - parity = odd", __func__); + } else { + lParity = LCR_PAR_EVEN; + dbg("%s - parity = even", __func__); + } + + } else { + dbg("%s - parity = none", __func__); + } + + if (cflag & CMSPAR) + lParity = lParity | 0x20; + + /* Change the Stop bit */ + if (cflag & CSTOPB) { + lStop = LCR_STOP_2; + dbg("%s - stop bits = 2", __func__); + } else { + lStop = LCR_STOP_1; + dbg("%s - stop bits = 1", __func__); + } + + /* Update the LCR with the correct value */ + ATEN2011_port->shadowLCR &= + ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); + ATEN2011_port->shadowLCR |= (lData | lParity | lStop); + + dbg + ("ATEN2011_change_port_settings ATEN2011_port->shadowLCR is %x", + ATEN2011_port->shadowLCR); + /* Disable Interrupts */ + Data = 0x00; + set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); + + Data = 0x00; + set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); + + Data = 0xcf; + set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); + + /* Send the updated LCR value to the ATEN2011 */ + Data = ATEN2011_port->shadowLCR; + + set_uart_reg(port, LINE_CONTROL_REGISTER, Data); + + Data = 0x00b; + ATEN2011_port->shadowMCR = Data; + set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + Data = 0x00b; + set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + + /* set up the MCR register and send it to the ATEN2011 */ + + ATEN2011_port->shadowMCR = MCR_MASTER_IE; + if (cflag & CBAUD) + ATEN2011_port->shadowMCR |= (MCR_DTR | MCR_RTS); + + if (cflag & CRTSCTS) + ATEN2011_port->shadowMCR |= (MCR_XON_ANY); + else + ATEN2011_port->shadowMCR &= ~(MCR_XON_ANY); + + Data = ATEN2011_port->shadowMCR; + set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); + + /* Determine divisor based on baud rate */ + baud = tty_get_baud_rate(tty); + + if (!baud) { + /* pick a default, any default... */ + dbg("%s", "Picked default baud..."); + baud = 9600; + } + + dbg("%s - baud rate = %d", __func__, baud); + status = ATEN2011_send_cmd_write_baud_rate(ATEN2011_port, baud); + + /* Enable Interrupts */ + Data = 0x0c; + set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); + + if (ATEN2011_port->read_urb->status != -EINPROGRESS) { + ATEN2011_port->read_urb->dev = serial->dev; + + status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC); + + if (status) { + dbg + (" usb_submit_urb(read bulk) failed, status = %d", + status); + } + } + dbg + ("ATEN2011_change_port_settings ATEN2011_port->shadowLCR is End %x", + ATEN2011_port->shadowLCR); + + return; +} + +static int ATEN2011_calc_num_ports(struct usb_serial *serial) +{ + + __u16 Data = 0x00; + int ret = 0; + int ATEN2011_2or4ports; + ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + ATEN_RDREQ, ATEN_RD_RTYPE, 0, GPIO_REGISTER, + &Data, VENDOR_READ_LENGTH, ATEN_WDR_TIMEOUT); + +/* ghostgum: here is where the problem appears to bet */ +/* Which of the following are needed? */ +/* Greg used the serial->type->num_ports=2 */ +/* But the code in the ATEN2011_open relies on serial->num_ports=2 */ + if ((Data & 0x01) == 0) { + ATEN2011_2or4ports = 2; + serial->type->num_ports = 2; + serial->num_ports = 2; + } + /* else if(serial->interface->cur_altsetting->desc.bNumEndpoints == 9) */ + else { + ATEN2011_2or4ports = 4; + serial->type->num_ports = 4; + serial->num_ports = 4; + + } + + return ATEN2011_2or4ports; +} + +static int ATEN2011_startup(struct usb_serial *serial) +{ + struct ATENINTL_serial *ATEN2011_serial; + struct ATENINTL_port *ATEN2011_port; + struct usb_device *dev; + int i, status; + int minor; + + __u16 Data; + dbg("%s", " ATEN2011_startup :entering.........."); + + if (!serial) { + dbg("%s", "Invalid Handler"); + return -1; + } + + dev = serial->dev; + + dbg("%s", "Entering..."); + + /* create our private serial structure */ + ATEN2011_serial = kzalloc(sizeof(struct ATENINTL_serial), GFP_KERNEL); + if (ATEN2011_serial == NULL) { + err("%s - Out of memory", __func__); + return -ENOMEM; + } + + /* resetting the private structure field values to zero */ + memset(ATEN2011_serial, 0, sizeof(struct ATENINTL_serial)); + + ATEN2011_serial->serial = serial; + /* initilize status polling flag to 0 */ + ATEN2011_serial->status_polling_started = 0; + + usb_set_serial_data(serial, ATEN2011_serial); + ATEN2011_serial->ATEN2011_spectrum_2or4ports = + ATEN2011_calc_num_ports(serial); + /* we set up the pointers to the endpoints in the ATEN2011_open * + * function, as the structures aren't created yet. */ + + /* set up port private structures */ + for (i = 0; i < serial->num_ports; ++i) { + ATEN2011_port = + kmalloc(sizeof(struct ATENINTL_port), GFP_KERNEL); + if (ATEN2011_port == NULL) { + err("%s - Out of memory", __func__); + usb_set_serial_data(serial, NULL); + kfree(ATEN2011_serial); + return -ENOMEM; + } + memset(ATEN2011_port, 0, sizeof(struct ATENINTL_port)); + + /* + * Initialize all port interrupt end point to port 0 + * int endpoint. Our device has only one interrupt end point + * comman to all port + */ + /* serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; */ + + ATEN2011_port->port = serial->port[i]; + usb_set_serial_port_data(serial->port[i], ATEN2011_port); + + minor = serial->port[i]->serial->minor; + if (minor == SERIAL_TTY_NO_MINOR) + minor = 0; + ATEN2011_port->port_num = + ((serial->port[i]->number - minor) + 1); + + if (ATEN2011_port->port_num == 1) { + ATEN2011_port->SpRegOffset = 0x0; + ATEN2011_port->ControlRegOffset = 0x1; + ATEN2011_port->DcrRegOffset = 0x4; + } else if ((ATEN2011_port->port_num == 2) + && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == + 4)) { + ATEN2011_port->SpRegOffset = 0x8; + ATEN2011_port->ControlRegOffset = 0x9; + ATEN2011_port->DcrRegOffset = 0x16; + } else if ((ATEN2011_port->port_num == 2) + && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == + 2)) { + ATEN2011_port->SpRegOffset = 0xa; + ATEN2011_port->ControlRegOffset = 0xb; + ATEN2011_port->DcrRegOffset = 0x19; + } else if ((ATEN2011_port->port_num == 3) + && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == + 4)) { + ATEN2011_port->SpRegOffset = 0xa; + ATEN2011_port->ControlRegOffset = 0xb; + ATEN2011_port->DcrRegOffset = 0x19; + } else if ((ATEN2011_port->port_num == 4) + && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == + 4)) { + ATEN2011_port->SpRegOffset = 0xc; + ATEN2011_port->ControlRegOffset = 0xd; + ATEN2011_port->DcrRegOffset = 0x1c; + } + + usb_set_serial_port_data(serial->port[i], ATEN2011_port); + + /* enable rx_disable bit in control register */ + + status = get_reg_sync(serial->port[i], + ATEN2011_port->ControlRegOffset, &Data); + if (status < 0) { + dbg("Reading ControlReg failed status-0x%x", + status); + break; + } else + dbg + ("ControlReg Reading success val is %x, status%d", + Data, status); + Data |= 0x08; /* setting driver done bit */ + Data |= 0x04; /* sp1_bit to have cts change reflect in modem status reg */ + + /* Data |= 0x20; */ /* rx_disable bit */ + status = set_reg_sync(serial->port[i], + ATEN2011_port->ControlRegOffset, Data); + if (status < 0) { + dbg + ("Writing ControlReg failed(rx_disable) status-0x%x", + status); + break; + } else + dbg + ("ControlReg Writing success(rx_disable) status%d", + status); + + /* + * Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 + * and 0x24 in DCR3 + */ + Data = 0x01; + status = set_reg_sync(serial->port[i], + (__u16)(ATEN2011_port->DcrRegOffset + 0), + Data); + if (status < 0) { + dbg("Writing DCR0 failed status-0x%x", status); + break; + } else + dbg("DCR0 Writing success status%d", status); + + Data = 0x05; + status = set_reg_sync(serial->port[i], + (__u16)(ATEN2011_port->DcrRegOffset + 1), + Data); + if (status < 0) { + dbg("Writing DCR1 failed status-0x%x", status); + break; + } else + dbg("DCR1 Writing success status%d", status); + + Data = 0x24; + status = set_reg_sync(serial->port[i], + (__u16)(ATEN2011_port->DcrRegOffset + 2), + Data); + if (status < 0) { + dbg("Writing DCR2 failed status-0x%x", status); + break; + } else + dbg("DCR2 Writing success status%d", status); + + /* write values in clkstart0x0 and clkmulti 0x20 */ + Data = 0x0; + status = set_reg_sync(serial->port[i], CLK_START_VALUE_REGISTER, + Data); + if (status < 0) { + dbg + ("Writing CLK_START_VALUE_REGISTER failed status-0x%x", + status); + break; + } else + dbg + ("CLK_START_VALUE_REGISTER Writing success status%d", + status); + + Data = 0x20; + status = set_reg_sync(serial->port[i], CLK_MULTI_REGISTER, + Data); + if (status < 0) { + dbg + ("Writing CLK_MULTI_REGISTER failed status-0x%x", + status); + break; + } else + dbg("CLK_MULTI_REGISTER Writing success status%d", + status); + + /* Zero Length flag register */ + if ((ATEN2011_port->port_num != 1) + && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2)) { + + Data = 0xff; + status = set_reg_sync(serial->port[i], + (__u16)(ZLP_REG1 + ((__u16)ATEN2011_port->port_num)), + Data); + dbg("ZLIP offset%x", + (__u16) (ZLP_REG1 + + ((__u16) ATEN2011_port->port_num))); + if (status < 0) { + dbg + ("Writing ZLP_REG%d failed status-0x%x", + i + 2, status); + break; + } else + dbg("ZLP_REG%d Writing success status%d", + i + 2, status); + } else { + Data = 0xff; + status = set_reg_sync(serial->port[i], + (__u16)(ZLP_REG1 + ((__u16)ATEN2011_port->port_num) - 0x1), + Data); + dbg("ZLIP offset%x", + (__u16) (ZLP_REG1 + + ((__u16) ATEN2011_port->port_num) - + 0x1)); + if (status < 0) { + dbg + ("Writing ZLP_REG%d failed status-0x%x", + i + 1, status); + break; + } else + dbg("ZLP_REG%d Writing success status%d", + i + 1, status); + + } + ATEN2011_port->control_urb = usb_alloc_urb(0, GFP_ATOMIC); + ATEN2011_port->ctrl_buf = kmalloc(16, GFP_KERNEL); + + } + + /* Zero Length flag enable */ + Data = 0x0f; + status = set_reg_sync(serial->port[0], ZLP_REG5, Data); + if (status < 0) { + dbg("Writing ZLP_REG5 failed status-0x%x", status); + return -1; + } else + dbg("ZLP_REG5 Writing success status%d", status); + + /* setting configuration feature to one */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ); + return 0; +} + +static void ATEN2011_shutdown(struct usb_serial *serial) +{ + int i; + struct ATENINTL_port *ATEN2011_port; + + /* check for the ports to be closed,close the ports and disconnect */ + + /* free private structure allocated for serial port * + * stop reads and writes on all ports */ + + for (i = 0; i < serial->num_ports; ++i) { + ATEN2011_port = usb_get_serial_port_data(serial->port[i]); + kfree(ATEN2011_port->ctrl_buf); + usb_kill_urb(ATEN2011_port->control_urb); + kfree(ATEN2011_port); + usb_set_serial_port_data(serial->port[i], NULL); + } + + /* free private structure allocated for serial device */ + + kfree(usb_get_serial_data(serial)); + usb_set_serial_data(serial, NULL); +} + +static struct usb_serial_driver aten_serial_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "aten2011", + }, + .description = DRIVER_DESC, + .id_table = id_table, + .open = ATEN2011_open, + .close = ATEN2011_close, + .write = ATEN2011_write, + .write_room = ATEN2011_write_room, + .chars_in_buffer = ATEN2011_chars_in_buffer, + .throttle = ATEN2011_throttle, + .unthrottle = ATEN2011_unthrottle, + .calc_num_ports = ATEN2011_calc_num_ports, + + .ioctl = ATEN2011_ioctl, + .set_termios = ATEN2011_set_termios, + .break_ctl = ATEN2011_break, + .tiocmget = ATEN2011_tiocmget, + .tiocmset = ATEN2011_tiocmset, + .attach = ATEN2011_startup, + .shutdown = ATEN2011_shutdown, + .read_bulk_callback = ATEN2011_bulk_in_callback, + .read_int_callback = ATEN2011_interrupt_callback, +}; + +static struct usb_driver aten_driver = { + .name = "aten2011", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, +}; + +static int __init aten_init(void) +{ + int retval; + + /* Register with the usb serial */ + retval = usb_serial_register(&aten_serial_driver); + if (retval) + return retval; + + printk(KERN_INFO KBUILD_MODNAME ":" + DRIVER_DESC " " DRIVER_VERSION "\n"); + + /* Register with the usb */ + retval = usb_register(&aten_driver); + if (retval) + usb_serial_deregister(&aten_serial_driver); + + return retval; +} + +static void __exit aten_exit(void) +{ + usb_deregister(&aten_driver); + usb_serial_deregister(&aten_serial_driver); +} + +module_init(aten_init); +module_exit(aten_exit); + +/* Module information */ +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index 2eb61372fe0a..1c710628df0d 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -334,7 +334,7 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, spin_lock_irqsave(&sdev->priv_lock, flags); - priv = kmem_cache_alloc(stub_priv_cache, GFP_ATOMIC); + priv = kmem_cache_zalloc(stub_priv_cache, GFP_ATOMIC); if (!priv) { dev_err(&sdev->interface->dev, "alloc stub_priv\n"); spin_unlock_irqrestore(&sdev->priv_lock, flags); @@ -342,8 +342,6 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, return NULL; } - memset(priv, 0, sizeof(struct stub_priv)); - priv->seqnum = pdu->base.seqnum; priv->sdev = sdev; diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c index 0fd33a62d934..e4c71435aa11 100644 --- a/drivers/staging/usbip/vhci_sysfs.c +++ b/drivers/staging/usbip/vhci_sysfs.c @@ -31,8 +31,7 @@ static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *s = out; int i = 0; - if (!the_controller || !out) - BUG(); + BUG_ON(!the_controller || !out); spin_lock(&the_controller->lock); diff --git a/drivers/staging/winbond/bss_f.h b/drivers/staging/winbond/bss_f.h deleted file mode 100644 index a433b5a85924..000000000000 --- a/drivers/staging/winbond/bss_f.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef __WINBOND_BSS_F_H -#define __WINBOND_BSS_F_H - -#include "core.h" - -struct PMKID_Information_Element; - -// -// BSS descriptor DataBase management global function -// - -void vBSSdescriptionInit(struct wbsoft_priv * adapter); -void vBSSfoundList(struct wbsoft_priv * adapter); -u8 boChanFilter(struct wbsoft_priv * adapter, u8 ChanNo); -u16 wBSSallocateEntry(struct wbsoft_priv * adapter); -u16 wBSSGetEntry(struct wbsoft_priv * adapter); -void vSimpleHouseKeeping(struct wbsoft_priv * adapter); -u16 wBSShouseKeeping(struct wbsoft_priv * adapter); -void ClearBSSdescpt(struct wbsoft_priv * adapter, u16 i); -u16 wBSSfindBssID(struct wbsoft_priv * adapter, u8 *pbBssid); -u16 wBSSfindDedicateCandidate(struct wbsoft_priv * adapter, struct SSID_Element *psSsid, u8 *pbBssid); -u16 wBSSfindMACaddr(struct wbsoft_priv * adapter, u8 *pbMacAddr); -u16 wBSSsearchMACaddr(struct wbsoft_priv * adapter, u8 *pbMacAddr, u8 band); -u16 wBSSaddScanData(struct wbsoft_priv *, u16, psRXDATA); -u16 wBSSUpdateScanData(struct wbsoft_priv * adapter, u16 wBssIdx, psRXDATA psRcvData); -u16 wBSScreateIBSSdata(struct wbsoft_priv * adapter, PWB_BSSDESCRIPTION psDesData); -void DesiredRate2BSSdescriptor(struct wbsoft_priv * adapter, PWB_BSSDESCRIPTION psDesData, - u8 *pBasicRateSet, u8 BasicRateCount, - u8 *pOperationRateSet, u8 OperationRateCount); -void DesiredRate2InfoElement(struct wbsoft_priv * adapter, u8 *addr, u16 *iFildOffset, - u8 *pBasicRateSet, u8 BasicRateCount, - u8 *pOperationRateSet, u8 OperationRateCount); -void BSSAddIBSSdata(struct wbsoft_priv * adapter, PWB_BSSDESCRIPTION psDesData); -unsigned char boCmpMacAddr( u8 *, u8 *); -unsigned char boCmpSSID(struct SSID_Element *psSSID1, struct SSID_Element *psSSID2); -u16 wBSSfindSSID(struct wbsoft_priv * adapter, struct SSID_Element *psSsid); -u16 wRoamingQuery(struct wbsoft_priv * adapter); -void vRateToBitmap(struct wbsoft_priv * adapter, u16 index); -u8 bRateToBitmapIndex(struct wbsoft_priv * adapter, u8 bRate); -u8 bBitmapToRate(u8 i); -unsigned char boIsERPsta(struct wbsoft_priv * adapter, u16 i); -unsigned char boCheckConnect(struct wbsoft_priv * adapter); -unsigned char boCheckSignal(struct wbsoft_priv * adapter); -void AddIBSSIe(struct wbsoft_priv * adapter,PWB_BSSDESCRIPTION psDesData );//added by ws for WPA_None06/01/04 -void BssScanUpToDate(struct wbsoft_priv * adapter); -void BssUpToDate(struct wbsoft_priv * adapter); -void RateSort(u8 *RateArray, u8 num, u8 mode); -void RateReSortForSRate(struct wbsoft_priv * adapter, u8 *RateArray, u8 num); -void Assemble_IE(struct wbsoft_priv * adapter, u16 wBssIdx); -void SetMaxTxRate(struct wbsoft_priv * adapter); - -void CreateWpaIE(struct wbsoft_priv * adapter, u16* iFildOffset, u8 *msg, struct Management_Frame* msgHeader, - struct Association_Request_Frame_Body* msgBody, u16 iMSindex); //added by WS 05/14/05 - -#ifdef _WPA2_ -void CreateRsnIE(struct wbsoft_priv * adapter, u16* iFildOffset, u8 *msg, struct Management_Frame* msgHeader, - struct Association_Request_Frame_Body* msgBody, u16 iMSindex);//added by WS 05/14/05 - -u16 SearchPmkid(struct wbsoft_priv * adapter, struct Management_Frame* msgHeader, - struct PMKID_Information_Element * AssoReq_PMKID ); -#endif - -#endif diff --git a/drivers/staging/winbond/bssdscpt.h b/drivers/staging/winbond/bssdscpt.h deleted file mode 100644 index 3a71d4efb897..000000000000 --- a/drivers/staging/winbond/bssdscpt.h +++ /dev/null @@ -1,164 +0,0 @@ -#ifndef __WINBOND_BSSDSCPT_H -#define __WINBOND_BSSDSCPT_H - -#include - -#include "mds_s.h" -#include "mlme_s.h" - -//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// bssdscpt.c -// BSS descriptor data base -// history : -// -// Description: -// BSS descriptor data base will store the information of the stations at the -// surrounding environment. The first entry( psBSS(0) ) will not be used and the -// second one( psBSS(1) ) will be used for the broadcast address. -//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -//#define MAX_ACC_RSSI_COUNT 10 -#define MAX_ACC_RSSI_COUNT 6 - -/////////////////////////////////////////////////////////////////////////// -// -// BSS Description set Element , to store scan received Beacon information -// -// Our's differs slightly from the specs. The specify a PHY_Parameter_Set. -// Since we're only doing a DS design right now, we just have a DS structure. -////////////////////////////////////////////////////////////////////////////// -typedef struct BSSDescriptionElement -{ - u32 SlotValid; - u32 PowerSaveMode; - RXLAYER1 RxLayer1; - - u8 abPeerAddress[ MAC_ADDR_LENGTH + 2 ]; // peer MAC Address associated with this session. 6-OCTET value - u32 dwBgScanStamp; // BgScan Sequence Counter stamp, record psROAM->dwScanCounter. - - u16 Beacon_Period; - u16 wATIM_Window; - - u8 abBssID[ MAC_ADDR_LENGTH + 2 ]; // 6B - - u8 bBssType; - u8 DTIM_Period; // 1 octet usually from TIM element, if present - u8 boInTimerHandler; - u8 boERP; // analysis ERP or (extended) supported rate element - - u8 Timestamp[8]; - u8 BasicRate[32]; - u8 OperationalRate[32]; - u32 dwBasicRateBitmap; //bit map, retrieve from SupportedRateSet - u32 dwOperationalRateBitmap; //bit map, retrieve from SupportedRateSet and - // ExtendedSupportedRateSet - // For RSSI calculating - u32 HalRssi[MAX_ACC_RSSI_COUNT]; // Encode. It must use MACRO of HAL to get the LNA and AGC data - u32 HalRssiIndex; - - ////From beacon/probe response - struct SSID_Element SSID; // 34B - u8 reserved_1[ 2 ]; - - struct Capability_Information_Element CapabilityInformation; // 2B - u8 reserved_2[ 2 ]; - - struct CF_Parameter_Set_Element CF_Parameter_Set; // 8B - struct IBSS_Parameter_Set_Element IBSS_Parameter_Set; // 4B - struct TIM_Element TIM_Element_Set; // 256B - - struct DS_Parameter_Set_Element DS_Parameter_Set; // 3B - u8 reserved_3; - - struct ERP_Information_Element ERP_Information_Set; // 3B - u8 reserved_4; - - struct Supported_Rates_Element SupportedRateSet; // 10B - u8 reserved_5[2]; - - struct Extended_Supported_Rates_Element ExtendedSupportedRateSet; // 257B - u8 reserved_6[3]; - - u8 band; - u8 reserved_7[3]; - - // for MLME module - u16 wState; // the current state of the system - u16 wIndex; // THIS BSS element entry index - - void* psadapter; // pointer to THIS adapter - struct timer_list timer; // MLME timer - - // Authentication - u16 wAuthAlgo; // peer MAC MLME use Auth algorithm, default OPEN_AUTH - u16 wAuthSeqNum; // current local MAC sendout AuthReq sequence number - - u8 auth_challengeText[128]; - - ////For XP: - u32 ies_len; // information element length - u8 ies[256]; // information element - - ////For WPA - u8 RsnIe_Type[2]; //added by ws for distinguish WPA and WPA2 05/14/04 - u8 RsnIe_len; - u8 Rsn_Num; - - // to record the rsn cipher suites,addded by ws 09/05/04 - SUITE_SELECTOR group_cipher; // 4B - SUITE_SELECTOR pairwise_key_cipher_suites[WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT]; - SUITE_SELECTOR auth_key_mgt_suites[WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT]; - - u16 pairwise_key_cipher_suite_count; - u16 auth_key_mgt_suite_count; - - u8 pairwise_key_cipher_suite_selected; - u8 auth_key_mgt_suite_selected; - u8 reserved_8[2]; - - struct RSN_Capability_Element rsn_capabilities; // 2B - u8 reserved_9[2]; - - //to record the rsn cipher suites for WPA2 - #ifdef _WPA2_ - u32 pre_auth; //added by WS for distinguish for 05/04/04 - SUITE_SELECTOR wpa2_group_cipher; // 4B - SUITE_SELECTOR wpa2_pairwise_key_cipher_suites[WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT]; - SUITE_SELECTOR wpa2_auth_key_mgt_suites[WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT]; - - u16 wpa2_pairwise_key_cipher_suite_count; - u16 wpa2_auth_key_mgt_suite_count; - - u8 wpa2_pairwise_key_cipher_suite_selected; - u8 wpa2_auth_key_mgt_suite_selected; - u8 reserved_10[2]; - - struct RSN_Capability_Element wpa2_rsn_capabilities; // 2B - u8 reserved_11[2]; - #endif //endif _WPA2_ - - //For Replay protection -// u8 PairwiseTSC[6]; -// u8 GroupTSC[6]; - - ////For up-to-date - u32 ScanTimeStamp; //for the decision whether the station/AP(may exist at - //different channels) has left. It must be detected by - //scanning. Local device may connected or disconnected. - u32 BssTimeStamp; //Only for the decision whether the station/AP(exist in - //the same channel, and no scanning) if local device has - //connected successfully. - - // 20061108 Add for storing WPS_IE. [E id][Length][OUI][Data] - u8 WPS_IE_Data[MAX_IE_APPEND_SIZE]; - u16 WPS_IE_length; - u16 WPS_IE_length_tmp; // For verify there is an WPS_IE in Beacon or probe response - -} WB_BSSDESCRIPTION, *PWB_BSSDESCRIPTION; - -#define wBSSConnectedSTA(adapter) \ - ((u16)(adapter)->sLocalPara.wConnectedSTAindex) - -#define psBSS(i) (&(adapter->asBSSDescriptElement[(i)])) - -#endif diff --git a/drivers/staging/winbond/common.h b/drivers/staging/winbond/common.h deleted file mode 100644 index c4d96041e9ac..000000000000 --- a/drivers/staging/winbond/common.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// common.h -// -// This file contains the OS dependant definition and function. -// Every OS has this file individual. -// - -#define DebugUsbdStatusInformation( _A ) - -#ifndef COMMON_DEF -#define COMMON_DEF - -//#define DEBUG_ENABLED 1 - -//================================================================================================== -// Common function definition -//================================================================================================== -#define DEBUG_ENABLED -#define ETH_LENGTH_OF_ADDRESS 6 -#ifdef DEBUG_ENABLED -#define WBDEBUG( _M ) printk _M -#else -#define WBDEBUG( _M ) 0 -#endif - -#endif // COMMON_DEF - diff --git a/drivers/staging/winbond/core.h b/drivers/staging/winbond/core.h index fe142a10ea80..eb4c090972c0 100644 --- a/drivers/staging/winbond/core.h +++ b/drivers/staging/winbond/core.h @@ -3,9 +3,9 @@ #include -#include "bssdscpt.h" -#include "mto.h" +#include "mlme_s.h" #include "wbhal_s.h" +#include "mto.h" #define WBLINUX_PACKET_ARRAY_SIZE (ETHERNET_TX_DESCRIPTORS*4) @@ -15,12 +15,11 @@ struct wbsoft_priv { u32 adapterIndex; // 20060703.4 Add for using padapterContext global adapter point WB_LOCALDESCRIPT sLocalPara; // Myself connected parameters - PWB_BSSDESCRIPTION asBSSDescriptElement; MLME_FRAME sMlmeFrame; // connect to peerSTA parameters MTO_PARAMETERS sMtoPara; // MTO_struct ... - hw_data_t sHwData; //For HAL + struct hw_data sHwData; //For HAL MDS Mds; spinlock_t SpinLock; diff --git a/drivers/staging/winbond/ds_tkip.h b/drivers/staging/winbond/ds_tkip.h deleted file mode 100644 index 9c5c4e73f2c2..000000000000 --- a/drivers/staging/winbond/ds_tkip.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __WINBOND_DS_TKIP_H -#define __WINBOND_DS_TKIP_H - -#include - -// Rotation functions on 32 bit values -#define ROL32( A, n ) \ - ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) - -#define ROR32( A, n ) ROL32( (A), 32-(n) ) - - -typedef struct tkip -{ - u32 K0, K1; // Key - union - { - struct // Current state - { - u32 L; - u32 R; - }; - u8 LR[8]; - }; - union - { - u32 M; // Message accumulator (single word) - u8 Mb[4]; - }; - s32 bytes_in_M; // # bytes in M -} tkip_t; - -//void _append_data( u8 *pData, u16 size, tkip_t *p ); -void Mds_MicGet( void* adapter, void* pRxLayer1, u8 *pKey, u8 *pMic ); -void Mds_MicFill( void* adapter, void* pDes, u8 *XmitBufAddress ); - -#endif diff --git a/drivers/staging/winbond/gl_80211.h b/drivers/staging/winbond/gl_80211.h deleted file mode 100644 index 5a244c44a61a..000000000000 --- a/drivers/staging/winbond/gl_80211.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef __GL_80211_H__ -#define __GL_80211_H__ - -#include - -/****************** CONSTANT AND MACRO SECTION ******************************/ - -/* BSS Type */ -enum { - WLAN_BSSTYPE_INFRASTRUCTURE = 0, - WLAN_BSSTYPE_INDEPENDENT, - WLAN_BSSTYPE_ANY_BSS, -}; - - - -/* Preamble_Type, see */ -typedef enum preamble_type { - WLAN_PREAMBLE_TYPE_SHORT, - WLAN_PREAMBLE_TYPE_LONG, -} preamble_type_e; - - -/* Slot_Time_Type, see */ -typedef enum slot_time_type { - WLAN_SLOT_TIME_TYPE_LONG, - WLAN_SLOT_TIME_TYPE_SHORT, -} slot_time_type_e; - -/*--------------------------------------------------------------------------*/ -/* Encryption Mode */ -typedef enum { - WEP_DISABLE = 0, - WEP_64, - WEP_128, - - ENCRYPT_DISABLE, - ENCRYPT_WEP, - ENCRYPT_WEP_NOKEY, - ENCRYPT_TKIP, - ENCRYPT_TKIP_NOKEY, - ENCRYPT_CCMP, - ENCRYPT_CCMP_NOKEY, -} encryption_mode_e; - -typedef enum _WLAN_RADIO { - WLAN_RADIO_ON, - WLAN_RADIO_OFF, - WLAN_RADIO_MAX, // not a real type, defined as an upper bound -} WLAN_RADIO; - -typedef struct _WLAN_RADIO_STATUS { - WLAN_RADIO HWStatus; - WLAN_RADIO SWStatus; -} WLAN_RADIO_STATUS; - -//---------------------------------------------------------------------------- -// 20041021 1.1.81.1000 ybjiang -// add for radio notification -typedef -void (*RADIO_NOTIFICATION_HANDLER)( - void *Data, - void *RadioStatusBuffer, - u32 RadioStatusBufferLen - ); - -typedef struct _WLAN_RADIO_NOTIFICATION -{ - RADIO_NOTIFICATION_HANDLER RadioChangeHandler; - void *Data; -} WLAN_RADIO_NOTIFICATION; - -//---------------------------------------------------------------------------- -// 20041102 1.1.91.1000 ybjiang -// add for OID_802_11_CUST_REGION_CAPABILITIES and OID_802_11_OID_REGION -typedef enum _WLAN_REGION_CODE -{ - WLAN_REGION_UNKNOWN, - WLAN_REGION_EUROPE, - WLAN_REGION_JAPAN, - WLAN_REGION_USA, - WLAN_REGION_FRANCE, - WLAN_REGION_SPAIN, - WLAN_REGION_ISRAEL, - WLAN_REGION_MAX, // not a real type, defined as an upper bound -} WLAN_REGION_CODE; - -#define REGION_NAME_MAX_LENGTH 256 - -typedef struct _WLAN_REGION_CHANNELS -{ - u32 Length; - u32 NameLength; - u8 Name[REGION_NAME_MAX_LENGTH]; - WLAN_REGION_CODE Code; - u32 Frequency[1]; -} WLAN_REGION_CHANNELS; - -typedef struct _WLAN_REGION_CAPABILITIES -{ - u32 NumberOfItems; - WLAN_REGION_CHANNELS Region[1]; -} WLAN_REGION_CAPABILITIES; - -typedef struct _region_name_map { - WLAN_REGION_CODE region; - u8 *name; - u32 *channels; -} region_name_map; - -/*--------------------------------------------------------------------------*/ -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X" - -// TODO: 0627 kevin -#define MIC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7] -#define MICSTR "%02X %02X %02X %02X %02X %02X %02X %02X" - -#define MICKEY2STR(a) MIC2STR(a) -#define MICKEYSTR MICSTR - - -#endif /* __GL_80211_H__ */ -/*** end of file ***/ - - diff --git a/drivers/staging/winbond/ioctls.h b/drivers/staging/winbond/ioctls.h deleted file mode 100644 index e8b35dc7e321..000000000000 --- a/drivers/staging/winbond/ioctls.h +++ /dev/null @@ -1,678 +0,0 @@ -//============================================================================ -// IOCTLS.H - -// -// Description: -// Define the IOCTL codes. -// -// Revision history: -// -------------------------------------------------------------------------- -// -// Copyright (c) 2002-2004 Winbond Electronics Corp. All rights reserved. -//============================================================================= - -#ifndef _IOCTLS_H -#define _IOCTLS_H - -// PD43 Keep it - Used with the Win33 application -// #include - -//======================================================== -// 20040108 ADD the follow for test -//======================================================== -#define INFORMATION_LENGTH sizeof(unsigned int) - -#define WB32_IOCTL_INDEX 0x0900 //­×§ÄĽHŤKŹŰŽe// - -#define Wb32_RegisterRead CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 0, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb32_RegisterWrite CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 1, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb32_SendPacket CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 2, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb32_QuerySendResult CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 3, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb32_SetFragmentThreshold CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 4, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb32_SetLinkStatus CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 5, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb32_SetBulkIn CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 6, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb32_LoopbackTest CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 7, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb35_EEPromRead CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 8, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb35_EEPromWrite CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 9, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb35_FlashReadData CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 10, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb35_FlashWrite CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 11, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb35_FlashWriteBurst CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 12, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb35_TxBurstStart CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 13, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb35_TxBurstStop CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 14, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define Wb35_TxBurstStatus CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB32_IOCTL_INDEX + 15, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// For IOCTL interface -//================================================ -#define LINKNAME_STRING "\\DosDevices\\W35UND" -#define NTDEVICE_STRING "\\Device\\W35UND" -#define APPLICATION_LINK "\\\\.\\W35UND" - -#define WB_IOCTL_INDEX 0x0800 -#define WB_IOCTL_TS_INDEX WB_IOCTL_INDEX + 60 -#define WB_IOCTL_DUT_INDEX WB_IOCTL_TS_INDEX + 40 - -//============================================================================= -// IOCTLS defined for DUT (Device Under Test) - -// IOCTL_WB_802_11_DUT_MAC_ADDRESS -// Query: Return the dot11StationID -// Set : Set the dot11StationID. Demo only. -// -#define IOCTL_WB_802_11_DUT_MAC_ADDRESS CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 1, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_BSS_DESCRIPTION -// Query: Return the info. of the current connected BSS. -// Set : None. -// -#define IOCTL_WB_802_11_DUT_BSS_DESCRIPTION CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 2, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_TX_RATE -// Query: Return the current transmission rate. -// Set : Set the transmission rate of the Tx packets. -// -#define IOCTL_WB_802_11_DUT_TX_RATE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 3, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_CURRENT_STA_STATE -// Query: Return the current STA state. (WB_STASTATE type) -// Set : None. -// -#define IOCTL_WB_802_11_DUT_CURRENT_STA_STATE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 4, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -/////////// 10/31/02' Added ///////////////////// - -// IOCTL_WB_802_11_DUT_START_IBSS_REQUEST -// Query: None. -// Set : Start a new IBSS -// -#define IOCTL_WB_802_11_DUT_START_IBSS_REQUEST CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 5, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_JOIN_REQUEST -// Query: None. -// Set : Synchronize with the selected BSS -// -#define IOCTL_WB_802_11_DUT_JOIN_REQUEST CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 6, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_AUTHEN_REQUEST -// Query: None. -// Set : Authenticate with the BSS -// -#define IOCTL_WB_802_11_DUT_AUTHEN_REQUEST CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 7, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_DEAUTHEN_REQUEST -// Query: None. -// Set : DeAuthenticate withe the BSS -// -#define IOCTL_WB_802_11_DUT_DEAUTHEN_REQUEST CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 8, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_ASSOC_REQUEST -// Query: None. -// Set : Associate withe the BSS -// -#define IOCTL_WB_802_11_DUT_ASSOC_REQUEST CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 9, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_REASSOC_REQUEST -// Query: None. -// Set : ReAssociate withe the BSS -// -#define IOCTL_WB_802_11_DUT_REASSOC_REQUEST CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 10, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - - -// IOCTL_WB_802_11_DUT_DISASSOC_REQUEST -// Query: None. -// Set : DisAssociate withe the BSS -// -#define IOCTL_WB_802_11_DUT_DISASSOC_REQUEST CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 11, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_FRAG_THRESHOLD -// Query: Return the dot11FragmentThreshold -// Set : Set the dot11FragmentThreshold -// -#define IOCTL_WB_802_11_DUT_FRAG_THRESHOLD CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 12, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_RTS_THRESHOLD -// Query: Return the dot11RTSThreshold -// Set : Set the dot11RTSThresold -// -#define IOCTL_WB_802_11_DUT_RTS_THRESHOLD CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 13, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_WEP_KEYMODE -// Query: Get the WEP key mode. -// Set : Set the WEP key mode: disable/64 bits/128 bits -// -#define IOCTL_WB_802_11_DUT_WEP_KEYMODE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 14, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_WEP_KEYVALUE -// Query: None. -// Set : fill in the WEP key value -// -#define IOCTL_WB_802_11_DUT_WEP_KEYVALUE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 15, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_RESET -// Query: None. -// Set : Reset S/W and H/W -// -#define IOCTL_WB_802_11_DUT_RESET CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 16, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_POWER_SAVE -// Query: None. -// Set : Set Power Save Mode -// -#define IOCTL_WB_802_11_DUT_POWER_SAVE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 17, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_BSSID_LIST_SCAN -// Query: None. -// Set : -// -#define IOCTL_WB_802_11_DUT_BSSID_LIST_SCAN CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 18, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_BSSID_LIST -// Query: Return the BSS info of BSSs in the last scanning process -// Set : None. -// -#define IOCTL_WB_802_11_DUT_BSSID_LIST CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 19, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_STATISTICS -// Query: Return the statistics of Tx/Rx. -// Set : None. -// -#define IOCTL_WB_802_11_DUT_STATISTICS CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 20, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_ACCEPT_BEACON -// Query: Return the current mode to accept beacon or not. -// Set : Enable or disable allowing the HW-MAC to pass the beacon to the SW-MAC -// Arguments: unsigned char -// -#define IOCTL_WB_802_11_DUT_ACCEPT_BEACON CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 21, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_ROAMING -// Query: Return the roaming function status -// Set : Enable/Disable the roaming function. -#define IOCTL_WB_802_11_DUT_ROAMING CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 22, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_DTO -// Query: Return the DTO(Data Throughput Optimization) -// function status (TRUE or FALSE) -// Set : Enable/Disable the DTO function. -// -#define IOCTL_WB_802_11_DUT_DTO CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 23, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_ANTENNA_DIVERSITY -// Query: Return the antenna diversity status. (TRUE/ON or FALSE/OFF) -// Set : Enable/Disable the antenna diversity. -// -#define IOCTL_WB_802_11_DUT_ANTENNA_DIVERSITY CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 24, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -//-------------- new added for a+b+g --------------------- -// IOCTL_WB_802_11_DUT_MAC_OPERATION_MODE -// Query: Return the MAC operation mode. (MODE_802_11_BG, MODE_802_11_A, -// MODE_802_11_ABG, MODE_802_11_BG_IBSS) -// Set : Set the MAC operation mode. -// -#define IOCTL_WB_802_11_DUT_MAC_OPERATION_MODE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 25, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_TX_RATE_REDEFINED -// Query: Return the current tx rate which follows the definition in spec. (for -// example, 5.5M => 0x0b) -// Set : None -// -#define IOCTL_WB_802_11_DUT_TX_RATE_REDEFINED CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 26, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_PREAMBLE_MODE -// Query: Return the preamble mode. (auto or long) -// Set : Set the preamble mode. -// -#define IOCTL_WB_802_11_DUT_PREAMBLE_MODE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 27, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_SLOT_TIME_MODE -// Query: Return the slot time mode. (auto or long) -// Set : Set the slot time mode. -// -#define IOCTL_WB_802_11_DUT_SLOT_TIME_MODE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 28, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) -//------------------------------------------------------------------ - -// IOCTL_WB_802_11_DUT_ADVANCE_STATUS -// Query: -// Set : NONE -// -#define IOCTL_WB_802_11_DUT_ADVANCE_STATUS CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 29, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_TX_RATE_MODE -// Query: Return the tx rate mode. (RATE_AUTO, RATE_1M, .., RATE_54M, RATE_MAX) -// Set : Set the tx rate mode. (RATE_AUTO, RATE_1M, .., RATE_54M, RATE_MAX) -// -#define IOCTL_WB_802_11_DUT_TX_RATE_MODE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 30, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_DTO_PARA -// Query: Return the DTO parameters -// Set : Set the DTO parameters -// -#define IOCTL_WB_802_11_DUT_DTO_PARA CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 31, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_EVENT_LOG -// Query: Return event log -// Set : Reset event log -// -#define IOCTL_WB_802_11_DUT_EVENT_LOG CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 32, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_CWMIN -// Query: NONE(It will be obtained by IOCTL_WB_802_11_DUT_ADVANCE_STATUS) -// Set : Set CWMin value -// -#define IOCTL_WB_802_11_DUT_CWMIN CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 33, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_DUT_CWMAX -// Query: NONE(It will be obtained by IOCTL_WB_802_11_DUT_ADVANCE_STATUS) -// Set : Set CWMax value -// -#define IOCTL_WB_802_11_DUT_CWMAX CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_DUT_INDEX + 34, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - - -//========================================================== -// IOCTLs for Testing - -// IOCTL_WB_802_11_TS_SET_CXX_REG -// Query: None -// Set : Write the value to one of Cxx register. -// -#define IOCTL_WB_802_11_TS_SET_CXX_REG CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 0, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_TS_GET_CXX_REG -// Query: Return the value of the Cxx register. -// Set : Write the reg no. (0x00, 0x04, 0x08 etc) -// -#define IOCTL_WB_802_11_TS_GET_CXX_REG CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 1, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_TS_SET_DXX_REG -// Query: None -// Set : Write the value to one of Dxx register. -// -#define IOCTL_WB_802_11_TS_SET_DXX_REG CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 2, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// IOCTL_WB_802_11_TS_GET_DXX_REG -// Query: Return the value of the Dxx register. -// Set : Write the reg no. (0x00, 0x04, 0x08 etc) -// -#define IOCTL_WB_802_11_TS_GET_DXX_REG CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 3, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -//============================================================ -// [TS] - -#define IOCTL_WB_802_11_TS_TX_RATE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 4, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_CURRENT_CHANNEL CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 5, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_ENABLE_SEQNO CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 6, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_ENALBE_ACKEDPACKET CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 7, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_INHIBIT_CRC CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 8, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_RESET_RCV_COUNTER CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 9, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_SET_TX_TRIGGER CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 10, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_FAILED_TX_COUNT CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 11, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// [TS1] -#define IOCTL_WB_802_11_TS_TX_POWER CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 12, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_MODE_ENABLE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 13, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_MODE_DISABLE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 14, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_ANTENNA CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 15, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_ADAPTER_INFO CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 16, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_MAC_ADDRESS CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 17, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_BSSID CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 18, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_RF_PARAMETER CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 19, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_FILTER CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 20, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_CALIBRATION CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 21, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_BSS_MODE CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 22, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_SET_SSID CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 23, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_IBSS_CHANNEL CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 24, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -// set/query the slot time value(short or long slot time) -#define IOCTL_WB_802_11_TS_SLOT_TIME CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 25, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_SLOT_TIME CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 25, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#define IOCTL_WB_802_11_TS_RX_STATISTICS CTL_CODE( \ - FILE_DEVICE_UNKNOWN, \ - WB_IOCTL_TS_INDEX + 26, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) - -#endif // #ifndef _IOCTLS_H - - diff --git a/drivers/staging/winbond/mds.c b/drivers/staging/winbond/mds.c index e431406e25a6..c7af09257e6f 100644 --- a/drivers/staging/winbond/mds.c +++ b/drivers/staging/winbond/mds.c @@ -1,9 +1,7 @@ -#include "ds_tkip.h" -#include "gl_80211.h" #include "mds_f.h" #include "mlmetxrx_f.h" -#include "mto_f.h" -#include "os_common.h" +#include "mto.h" +#include "sysdef.h" #include "wbhal_f.h" #include "wblinux_f.h" @@ -374,7 +372,7 @@ static void Mds_HeaderCopy(struct wbsoft_priv * adapter, PDESCRIPTOR pDes, u8 *T pDes->TxRate = ctmp1; #ifdef _PE_TX_DUMP_ - WBDEBUG(("Tx rate =%x\n", ctmp1)); + printk("Tx rate =%x\n", ctmp1); #endif pT01->T01_modulation_type = (ctmp1%3) ? 0 : 1; @@ -418,14 +416,14 @@ static void Mds_HeaderCopy(struct wbsoft_priv * adapter, PDESCRIPTOR pDes, u8 *T void Mds_Tx(struct wbsoft_priv * adapter) { - phw_data_t pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; PMDS pMds = &adapter->Mds; DESCRIPTOR TxDes; PDESCRIPTOR pTxDes = &TxDes; u8 *XmitBufAddress; u16 XmitBufSize, PacketSize, stmp, CurrentSize, FragmentThreshold; u8 FillIndex, TxDesIndex, FragmentCount, FillCount; - unsigned char BufferFilled = false, MICAdd = 0; + unsigned char BufferFilled = false; if (pMds->TxPause) @@ -442,7 +440,7 @@ Mds_Tx(struct wbsoft_priv * adapter) FillIndex = pMds->TxFillIndex; if (pMds->TxOwner[FillIndex]) { // Is owned by software 0:Yes 1:No #ifdef _PE_TX_DUMP_ - WBDEBUG(("[Mds_Tx] Tx Owner is H/W.\n")); + printk("[Mds_Tx] Tx Owner is H/W.\n"); #endif break; } @@ -488,7 +486,7 @@ Mds_Tx(struct wbsoft_priv * adapter) // For speed up Key setting if (pTxDes->EapFix) { #ifdef _PE_TX_DUMP_ - WBDEBUG(("35: EPA 4th frame detected. Size = %d\n", PacketSize)); + printk("35: EPA 4th frame detected. Size = %d\n", PacketSize); #endif pHwData->IsKeyPreSet = 1; } @@ -499,12 +497,6 @@ Mds_Tx(struct wbsoft_priv * adapter) // Set RTS/CTS and Normal duration field into buffer Mds_DurationSet(adapter, pTxDes, XmitBufAddress); - // - // Calculation MIC from buffer which maybe fragment, then fill into temporary address 8 byte - // 931130.5.e - if (MICAdd) - Mds_MicFill( adapter, pTxDes, XmitBufAddress ); - //Shift to the next address XmitBufSize += CurrentSize; XmitBufAddress += CurrentSize; @@ -561,7 +553,7 @@ void Mds_SendComplete(struct wbsoft_priv * adapter, PT02_DESCRIPTOR pT02) { PMDS pMds = &adapter->Mds; - phw_data_t pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; u8 PacketId = (u8)pT02->T02_Tx_PktID; unsigned char SendOK = true; u8 RetryCount, TxRate; @@ -585,7 +577,7 @@ Mds_SendComplete(struct wbsoft_priv * adapter, PT02_DESCRIPTOR pT02) else pHwData->tx_retry_count[7] += RetryCount; #ifdef _PE_STATE_DUMP_ - WBDEBUG(("dto_tx_retry_count =%d\n", pHwData->dto_tx_retry_count)); + printk("dto_tx_retry_count =%d\n", pHwData->dto_tx_retry_count); #endif MTO_SetTxCount(adapter, TxRate, RetryCount); } diff --git a/drivers/staging/winbond/mds_s.h b/drivers/staging/winbond/mds_s.h index ebf61e3ce1dc..9ffec1764d6d 100644 --- a/drivers/staging/winbond/mds_s.h +++ b/drivers/staging/winbond/mds_s.h @@ -9,6 +9,12 @@ #include "mac_structures.h" #include "scan_s.h" +/* Preamble_Type, see */ +enum { + WLAN_PREAMBLE_TYPE_SHORT, + WLAN_PREAMBLE_TYPE_LONG, +}; + //////////////////////////////////////////////////////////////////////////////////////////////////////// #define MAX_USB_TX_DESCRIPTOR 15 // IS89C35 ability #define MAX_USB_TX_BUFFER_NUMBER 4 // Virtual pre-buffer number of MAX_USB_TX_BUFFER @@ -17,26 +23,8 @@ #define AUTH_REQUEST_PAIRWISE_ERROR 0 // _F flag setting #define AUTH_REQUEST_GROUP_ERROR 1 // _F flag setting -// For variable setting -#define CURRENT_BSS_TYPE psBSS(psLOCAL->wConnectedSTAindex)->bBssType -#define CURRENT_WEP_MODE psSME->_dot11PrivacyInvoked -#define CURRENT_BSSID psBSS(psLOCAL->wConnectedSTAindex)->abBssID -#define CURRENT_DESIRED_WPA_ENABLE ((psSME->bDesiredAuthMode==WPA_AUTH)||(psSME->bDesiredAuthMode==WPAPSK_AUTH)) -#ifdef _WPA2_ -#define CURRENT_DESIRED_WPA2_ENABLE ((psSME->bDesiredAuthMode==WPA2_AUTH)||(psSME->bDesiredAuthMode==WPA2PSK_AUTH)) -#endif //end def _WPA2_ -#define CURRENT_PAIRWISE_KEY_OK psSME->pairwise_key_ok -//[20040712 WS] -#define CURRENT_GROUP_KEY_OK psSME->group_key_ok -#define CURRENT_PAIRWISE_KEY psSME->tx_mic_key -#define CURRENT_GROUP_KEY psSME->group_tx_mic_key -#define CURRENT_ENCRYPT_STATUS psSME->encrypt_status -#define CURRENT_WEP_ID adapter->sSmePara._dot11WEPDefaultKeyID -#define CURRENT_CONTROL_PORT_BLOCK ( psSME->wpa_ok!=1 || (adapter->Mds.boCounterMeasureBlock==1 && (CURRENT_ENCRYPT_STATUS==ENCRYPT_TKIP)) ) #define CURRENT_FRAGMENT_THRESHOLD (adapter->Mds.TxFragmentThreshold & ~0x1) #define CURRENT_PREAMBLE_MODE psLOCAL->boShortPreamble?WLAN_PREAMBLE_TYPE_SHORT:WLAN_PREAMBLE_TYPE_LONG -#define CURRENT_TX_RATE adapter->sLocalPara.CurrentTxRate -#define CURRENT_FALL_BACK_TX_RATE adapter->sLocalPara.CurrentTxFallbackRate #define CURRENT_TX_RATE_FOR_MNG adapter->sLocalPara.CurrentTxRateForMng #define CURRENT_PROTECT_MECHANISM psLOCAL->boProtectMechanism #define CURRENT_RTS_THRESHOLD adapter->Mds.TxRTSThreshold diff --git a/drivers/staging/winbond/mlme_mib.h b/drivers/staging/winbond/mlme_mib.h deleted file mode 100644 index ca8922ec6338..000000000000 --- a/drivers/staging/winbond/mlme_mib.h +++ /dev/null @@ -1,84 +0,0 @@ -//============================================================================ -// MLMEMIB.H - -// -// Description: -// Get and Set some of MLME MIB attributes. -// -// Revision history: -// -------------------------------------------------------------------------- -// 20030117 PD43 Austin Liu -// Initial release -// -// Copyright (c) 2003 Winbond Electronics Corp. All rights reserved. -//============================================================================ - -#ifndef _MLME_MIB_H -#define _MLME_MIB_H - -//============================================================================ -// MLMESetExcludeUnencrypted -- -// -// Description: -// Set the dot11ExcludeUnencrypted value. -// -// Arguments: -// adapter - The pointer to the miniport adapter context. -// ExUnencrypted - unsigned char type. The value to be set. -// -// Return values: -// None. -//============================================================================ -#define MLMESetExcludeUnencrypted(adapter, ExUnencrypted) \ -{ \ - (adapter)->sLocalPara.ExcludeUnencrypted = ExUnencrypted; \ -} - -//============================================================================ -// MLMEGetExcludeUnencrypted -- -// -// Description: -// Get the dot11ExcludeUnencrypted value. -// -// Arguments: -// adapter - The pointer to the miniport adapter context. -// -// Return values: -// unsigned char type. The current dot11ExcludeUnencrypted value. -//============================================================================ -#define MLMEGetExcludeUnencrypted(adapter) ((unsigned char) (adapter)->sLocalPara.ExcludeUnencrypted) - -//============================================================================ -// MLMESetMaxReceiveLifeTime -- -// -// Description: -// Set the dot11MaxReceiveLifeTime value. -// -// Arguments: -// adapter - The pointer to the miniport adapter context. -// ReceiveLifeTime- u32 type. The value to be set. -// -// Return values: -// None. -//============================================================================ -#define MLMESetMaxReceiveLifeTime(adapter, ReceiveLifeTime) \ -{ \ - (adapter)->Mds.MaxReceiveTime = ReceiveLifeTime; \ -} - -//============================================================================ -// MLMESetMaxReceiveLifeTime -- -// -// Description: -// Get the dot11MaxReceiveLifeTime value. -// -// Arguments: -// adapter - The pointer to the miniport adapter context. -// -// Return values: -// u32 type. The current dot11MaxReceiveLifeTime value. -//============================================================================ -#define MLMEGetMaxReceiveLifeTime(adapter) ((u32) (adapter)->Mds.MaxReceiveTime) - -#endif - - diff --git a/drivers/staging/winbond/mlmetxrx.c b/drivers/staging/winbond/mlmetxrx.c index 07802afd2b87..643ceb060d56 100644 --- a/drivers/staging/winbond/mlmetxrx.c +++ b/drivers/staging/winbond/mlmetxrx.c @@ -15,7 +15,7 @@ // // Copyright (c) 1996-2002 Winbond Electronics Corp. All Rights Reserved. //============================================================================ -#include "os_common.h" +#include "sysdef.h" #include "mds_f.h" diff --git a/drivers/staging/winbond/mto.c b/drivers/staging/winbond/mto.c index de11a05efae2..94a060bcc628 100644 --- a/drivers/staging/winbond/mto.c +++ b/drivers/staging/winbond/mto.c @@ -22,9 +22,8 @@ //============================================================================ // LA20040210_DTO kevin -#include "os_common.h" +#include "sysdef.h" #include "sme_api.h" -#include "gl_80211.h" #include "wbhal_f.h" // Declare SQ3 to rate and fragmentation threshold table @@ -51,20 +50,14 @@ static int retryrate_rec[MTO_MAX_DATA_RATE_LEVELS];//this record the retry rate static int PeriodTotalTxPkt = 0; static int PeriodTotalTxPktRetry = 0; -typedef struct -{ - s32 RSSI; - u8 TxRate; -}RSSI2RATE; - static u8 boSparseTxTraffic = false; -void MTO_Init(MTO_FUNC_INPUT); -void TxRateReductionCtrl(MTO_FUNC_INPUT); +void MTO_Init(struct wbsoft_priv *adapter); +void TxRateReductionCtrl(struct wbsoft_priv *adapter); /** 1.1.31.1000 Turbo modify */ -void MTO_SetTxCount(MTO_FUNC_INPUT, u8 t0, u8 index); -void MTO_TxFailed(MTO_FUNC_INPUT); -void hal_get_dto_para(MTO_FUNC_INPUT, char *buffer); +void MTO_SetTxCount(struct wbsoft_priv *adapter, u8 t0, u8 index); +void MTO_TxFailed(struct wbsoft_priv *adapter); +void hal_get_dto_para(struct wbsoft_priv *adapter, char *buffer); //=========================================================================== // MTO_Init -- @@ -80,10 +73,9 @@ void hal_get_dto_para(MTO_FUNC_INPUT, char *buffer); // Return Value: // None //============================================================================ -void MTO_Init(MTO_FUNC_INPUT) +void MTO_Init(struct wbsoft_priv *adapter) { int i; - //WBDEBUG(("[MTO] -> MTO_Init()\n")); //[WKCHEN]pMTOcore_data = pcore_data; // 20040510 Turbo add for global variable MTO_TMR_CNT() = 0; @@ -196,7 +188,7 @@ void MTO_Init(MTO_FUNC_INPUT) // If we enable DTO, we will ignore the tx count with different tx rate from // DTO rate. This is because when we adjust DTO tx rate, there could be some // packets in the tx queue with previous tx rate -void MTO_SetTxCount(MTO_FUNC_INPUT, u8 tx_rate, u8 index) +void MTO_SetTxCount(struct wbsoft_priv *adapter, u8 tx_rate, u8 index) { MTO_TXFLOWCOUNT()++; if ((MTO_ENABLE==1) && (MTO_RATE_CHANGE_ENABLE()==1)) diff --git a/drivers/staging/winbond/mto.h b/drivers/staging/winbond/mto.h index 0d3775eb2573..56f2465723b3 100644 --- a/drivers/staging/winbond/mto.h +++ b/drivers/staging/winbond/mto.h @@ -13,6 +13,8 @@ #include +struct wbsoft_priv; + #define MTO_DEFAULT_TH_CNT 5 #define MTO_DEFAULT_TH_SQ3 112 //OLD IS 13 reference JohnXu #define MTO_DEFAULT_TH_IDLE_SLOT 15 @@ -131,8 +133,6 @@ typedef struct _MTO_PARAMETERS } MTO_PARAMETERS, *PMTO_PARAMETERS; -#define MTO_FUNC_INPUT struct wbsoft_priv * adapter -#define MTO_FUNC_INPUT_DATA adapter #define MTO_DATA() (adapter->sMtoPara) #define MTO_HAL() (&adapter->sHwData) #define MTO_SET_PREAMBLE_TYPE(x) // 20040511 Turbo mark LM_PREAMBLE_TYPE(&pcore_data->lm_data) = (x) @@ -140,7 +140,6 @@ typedef struct _MTO_PARAMETERS #define MTO_TXPOWER_FROM_EEPROM (adapter->sHwData.PowerIndexFromEEPROM) #define LOCAL_ANTENNA_NO() (adapter->sLocalPara.bAntennaNo) #define LOCAL_IS_CONNECTED() (adapter->sLocalPara.wConnectedSTAindex != 0) -#define LOCAL_IS_IBSS_MODE() (adapter->asBSSDescriptElement[adapter->sLocalPara.wConnectedSTAindex].bBssType == IBSS_NET) #define MTO_INITTXRATE_MODE (adapter->sHwData.SoftwareSet&0x2) //bit 1 // 20040510 Turbo add #define MTO_TMR_CNT() MTO_DATA().TmrCnt @@ -259,6 +258,13 @@ typedef struct _STATISTICS_INFO { s32 Antenna; } STATISTICS_INFO, *PSTATISTICS_INFO; +extern void MTO_Init(struct wbsoft_priv *); +extern void MTO_PeriodicTimerExpired(struct wbsoft_priv *); +extern void MTO_SetDTORateRange(struct wbsoft_priv *, u8 *, u8); +extern u8 MTO_GetTxRate(struct wbsoft_priv *adapter, u32 fpdu_len); +extern u8 MTO_GetTxFallbackRate(struct wbsoft_priv *adapter); +extern void MTO_SetTxCount(struct wbsoft_priv *adapter, u8 t0, u8 index); + #endif //__MTO_H__ diff --git a/drivers/staging/winbond/mto_f.h b/drivers/staging/winbond/mto_f.h deleted file mode 100644 index 81f59137c6d6..000000000000 --- a/drivers/staging/winbond/mto_f.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __WINBOND_MTO_F_H -#define __WINBOND_MTO_F_H - -#include "core.h" - -extern void MTO_Init(struct wbsoft_priv *); -extern void MTO_PeriodicTimerExpired(struct wbsoft_priv *); -extern void MTO_SetDTORateRange(struct wbsoft_priv *, u8 *, u8); -extern u8 MTO_GetTxRate(MTO_FUNC_INPUT, u32 fpdu_len); -extern u8 MTO_GetTxFallbackRate(MTO_FUNC_INPUT); -extern void MTO_SetTxCount(MTO_FUNC_INPUT, u8 t0, u8 index); - -#endif diff --git a/drivers/staging/winbond/os_common.h b/drivers/staging/winbond/os_common.h deleted file mode 100644 index 2c276e3ab512..000000000000 --- a/drivers/staging/winbond/os_common.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "sysdef.h" - diff --git a/drivers/staging/winbond/phy_calibration.c b/drivers/staging/winbond/phy_calibration.c index 6782552d366c..af8c01e313b0 100644 --- a/drivers/staging/winbond/phy_calibration.c +++ b/drivers/staging/winbond/phy_calibration.c @@ -10,7 +10,7 @@ */ /****************** INCLUDE FILES SECTION ***********************************/ -#include "os_common.h" +#include "sysdef.h" #include "phy_calibration.h" #include "wbhal_f.h" @@ -37,8 +37,8 @@ static const fixed Angles[]= }; /****************** LOCAL FUNCTION DECLARATION SECTION **********************/ -//void _phy_rf_write_delay(hw_data_t *phw_data); -//void phy_init_rf(hw_data_t *phw_data); +//void _phy_rf_write_delay(struct hw_data *phw_data); +//void phy_init_rf(struct hw_data *phw_data); /****************** FUNCTION DEFINITION SECTION *****************************/ @@ -341,7 +341,7 @@ void _sin_cos(s32 angle, s32 *sin, s32 *cos) } -void _reset_rx_cal(hw_data_t *phw_data) +void _reset_rx_cal(struct hw_data *phw_data) { u32 val; @@ -366,7 +366,7 @@ void _reset_rx_cal(hw_data_t *phw_data) // // // ********************************************* -void _rxadc_dc_offset_cancellation_winbond(hw_data_t *phw_data, u32 frequency) +void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequency) { u32 reg_agc_ctrl3; u32 reg_a_acq_ctrl; @@ -465,7 +465,7 @@ void _rxadc_dc_offset_cancellation_winbond(hw_data_t *phw_data, u32 frequency) } //////////////////////////////////////////////////////// -void _txidac_dc_offset_cancellation_winbond(hw_data_t *phw_data) +void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data) { u32 reg_agc_ctrl3; u32 reg_mode_ctrl; @@ -600,7 +600,7 @@ void _txidac_dc_offset_cancellation_winbond(hw_data_t *phw_data) } /////////////////////////////////////////////////////// -void _txqdac_dc_offset_cacellation_winbond(hw_data_t *phw_data) +void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data) { u32 reg_agc_ctrl3; u32 reg_mode_ctrl; @@ -726,7 +726,7 @@ void _txqdac_dc_offset_cacellation_winbond(hw_data_t *phw_data) } //20060612.1.a 20060718.1 Modify -u8 _tx_iq_calibration_loop_winbond(hw_data_t *phw_data, +u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data, s32 a_2_threshold, s32 b_2_threshold) { @@ -1032,7 +1032,7 @@ u8 _tx_iq_calibration_loop_winbond(hw_data_t *phw_data, return 1; } -void _tx_iq_calibration_winbond(hw_data_t *phw_data) +void _tx_iq_calibration_winbond(struct hw_data *phw_data) { u32 reg_agc_ctrl3; #ifdef _DEBUG @@ -1195,7 +1195,7 @@ void _tx_iq_calibration_winbond(hw_data_t *phw_data) } ///////////////////////////////////////////////////////////////////////////////////////// -u8 _rx_iq_calibration_loop_winbond(hw_data_t *phw_data, u16 factor, u32 frequency) +u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 frequency) { u32 reg_mode_ctrl; s32 iqcal_tone_i; @@ -1501,7 +1501,7 @@ u8 _rx_iq_calibration_loop_winbond(hw_data_t *phw_data, u16 factor, u32 frequenc ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -void _rx_iq_calibration_winbond(hw_data_t *phw_data, u32 frequency) +void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency) { // figo 20050523 marked thsi flag for can't compile for relesase #ifdef _DEBUG @@ -1579,7 +1579,7 @@ void _rx_iq_calibration_winbond(hw_data_t *phw_data, u32 frequency) } //////////////////////////////////////////////////////////////////////// -void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency) +void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency) { u32 reg_mode_ctrl; u32 iq_alpha; @@ -1618,7 +1618,7 @@ void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency) } //=========================== -void phy_set_rf_data( phw_data_t pHwData, u32 index, u32 value ) +void phy_set_rf_data( struct hw_data * pHwData, u32 index, u32 value ) { u32 ltmp=0; @@ -1660,7 +1660,7 @@ void phy_set_rf_data( phw_data_t pHwData, u32 index, u32 value ) } // 20060717 modify as Bruce's mail -unsigned char adjust_TXVGA_for_iq_mag(hw_data_t *phw_data) +unsigned char adjust_TXVGA_for_iq_mag(struct hw_data *phw_data) { int init_txvga = 0; u32 reg_mode_ctrl; diff --git a/drivers/staging/winbond/phy_calibration.h b/drivers/staging/winbond/phy_calibration.h index 03b820c6181b..51c8fde81e2b 100644 --- a/drivers/staging/winbond/phy_calibration.h +++ b/drivers/staging/winbond/phy_calibration.h @@ -101,7 +101,7 @@ //#define MASK_IQCAL_IMAGE_Q 0x03FFE000 //#define SHIFT_IQCAL_IMAGE_Q(x) ((x)>>13) -void phy_set_rf_data( phw_data_t pHwData, u32 index, u32 value ); +void phy_set_rf_data( struct hw_data * pHwData, u32 index, u32 value ); #define phy_init_rf( _A ) //RFSynthesizer_initial( _A ) #endif diff --git a/drivers/staging/winbond/reg.c b/drivers/staging/winbond/reg.c index cd21272d7a9f..d915cbdd38ed 100644 --- a/drivers/staging/winbond/reg.c +++ b/drivers/staging/winbond/reg.c @@ -1,4 +1,4 @@ -#include "os_common.h" +#include "sysdef.h" #include "wbhal_f.h" /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -915,7 +915,7 @@ u32 w89rf242_txvga_data[][5] = // The address is stored in EthernetIDAddr. //============================================================================================================= void -Uxx_ReadEthernetAddress( phw_data_t pHwData ) +Uxx_ReadEthernetAddress( struct hw_data * pHwData ) { u32 ltmp; @@ -948,14 +948,13 @@ Uxx_ReadEthernetAddress( phw_data_t pHwData ) // Return Value: // None. //============================================================================================================== -void CardGetMulticastBit( u8 Address[ETH_LENGTH_OF_ADDRESS], - u8 *Byte, u8 *Value ) +void CardGetMulticastBit( u8 Address[ETH_ALEN], u8 *Byte, u8 *Value ) { u32 Crc; u32 BitNumber; // First compute the CRC. - Crc = CardComputeCrc(Address, ETH_LENGTH_OF_ADDRESS); + Crc = CardComputeCrc(Address, ETH_ALEN); // The computed CRC is bit0~31 from left to right //At first we should do right shift 25bits, and read 7bits by using '&', 2^7=128 @@ -965,7 +964,7 @@ void CardGetMulticastBit( u8 Address[ETH_LENGTH_OF_ADDRESS], *Value = (u8) ((u8)1 << (BitNumber % 8)); } -void Uxx_power_on_procedure( phw_data_t pHwData ) +void Uxx_power_on_procedure( struct hw_data * pHwData ) { u32 ltmp, loop; @@ -1009,7 +1008,7 @@ void Uxx_power_on_procedure( phw_data_t pHwData ) Wb35Reg_WriteSync( pHwData, 0x03f8, 0x7ff ); } -void Set_ChanIndep_RfData_al7230_24( phw_data_t pHwData, u32 *pltmp ,char number) +void Set_ChanIndep_RfData_al7230_24( struct hw_data * pHwData, u32 *pltmp ,char number) { u8 i; @@ -1020,7 +1019,7 @@ void Set_ChanIndep_RfData_al7230_24( phw_data_t pHwData, u32 *pltmp ,char numbe } } -void Set_ChanIndep_RfData_al7230_50( phw_data_t pHwData, u32 *pltmp, char number) +void Set_ChanIndep_RfData_al7230_50( struct hw_data * pHwData, u32 *pltmp, char number) { u8 i; @@ -1036,7 +1035,7 @@ void Set_ChanIndep_RfData_al7230_50( phw_data_t pHwData, u32 *pltmp, char numbe // RFSynthesizer_initial -- //============================================================================================================= void -RFSynthesizer_initial(phw_data_t pHwData) +RFSynthesizer_initial(struct hw_data * pHwData) { u32 altmp[32]; u32 * pltmp = altmp; @@ -1115,7 +1114,7 @@ RFSynthesizer_initial(phw_data_t pHwData) //Start to fill RF parameters, PLL_ON should be pulled low. Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000000 ); #ifdef _PE_STATE_DUMP_ - WBDEBUG(("* PLL_ON low\n")); + printk("* PLL_ON low\n"); #endif number = sizeof(al7230_rf_data_24)/sizeof(al7230_rf_data_24[0]); @@ -1224,7 +1223,7 @@ RFSynthesizer_initial(phw_data_t pHwData) //pulled high Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000080 ); #ifdef _PE_STATE_DUMP_ - WBDEBUG(("* PLL_ON high\n")); + printk("* PLL_ON high\n"); #endif //2.4GHz @@ -1244,7 +1243,7 @@ RFSynthesizer_initial(phw_data_t pHwData) //5GHz Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000000 ); #ifdef _PE_STATE_DUMP_ - WBDEBUG(("* PLL_ON low\n")); + printk("* PLL_ON low\n"); #endif number = sizeof(al7230_rf_data_50)/sizeof(al7230_rf_data_50[0]); @@ -1256,7 +1255,7 @@ RFSynthesizer_initial(phw_data_t pHwData) Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000080 ); #ifdef _PE_STATE_DUMP_ - WBDEBUG(("* PLL_ON high\n")); + printk("* PLL_ON high\n"); #endif //ltmp = (1 << 31) | (0 << 30) | (24 << 24) | 0x12BACF; @@ -1272,7 +1271,7 @@ RFSynthesizer_initial(phw_data_t pHwData) msleep(5); //Wb35Reg_WriteSync( pHwData, 0x03dc, 0x00000080 ); - //WBDEBUG(("* PLL_ON high\n")); + //printk("* PLL_ON high\n"); break; case RF_WB_242: @@ -1414,7 +1413,7 @@ RFSynthesizer_initial(phw_data_t pHwData) } } -void BBProcessor_AL7230_2400( phw_data_t pHwData) +void BBProcessor_AL7230_2400( struct hw_data * pHwData) { struct wb35_reg *reg = &pHwData->reg; u32 pltmp[12]; @@ -1456,7 +1455,7 @@ void BBProcessor_AL7230_2400( phw_data_t pHwData) } -void BBProcessor_AL7230_5000( phw_data_t pHwData) +void BBProcessor_AL7230_5000( struct hw_data * pHwData) { struct wb35_reg *reg = &pHwData->reg; u32 pltmp[12]; @@ -1510,7 +1509,7 @@ void BBProcessor_AL7230_5000( phw_data_t pHwData) // None. //============================================================================================================= void -BBProcessor_initial( phw_data_t pHwData ) +BBProcessor_initial( struct hw_data * pHwData ) { struct wb35_reg *reg = &pHwData->reg; u32 i, pltmp[12]; @@ -1824,12 +1823,12 @@ BBProcessor_initial( phw_data_t pHwData ) reg->SQ3_filter[i] = 0x2f; // half of Bit 0 ~ 6 } -void set_tx_power_per_channel_max2829( phw_data_t pHwData, ChanInfo Channel) +void set_tx_power_per_channel_max2829( struct hw_data * pHwData, ChanInfo Channel) { RFSynthesizer_SetPowerIndex( pHwData, 100 ); // 20060620.1 Modify } -void set_tx_power_per_channel_al2230( phw_data_t pHwData, ChanInfo Channel ) +void set_tx_power_per_channel_al2230( struct hw_data * pHwData, ChanInfo Channel ) { u8 index = 100; @@ -1839,7 +1838,7 @@ void set_tx_power_per_channel_al2230( phw_data_t pHwData, ChanInfo Channel ) RFSynthesizer_SetPowerIndex( pHwData, index ); } -void set_tx_power_per_channel_al7230( phw_data_t pHwData, ChanInfo Channel) +void set_tx_power_per_channel_al7230( struct hw_data * pHwData, ChanInfo Channel) { u8 i, index = 100; @@ -1869,7 +1868,7 @@ void set_tx_power_per_channel_al7230( phw_data_t pHwData, ChanInfo Channel) RFSynthesizer_SetPowerIndex( pHwData, index ); } -void set_tx_power_per_channel_wb242( phw_data_t pHwData, ChanInfo Channel) +void set_tx_power_per_channel_wb242( struct hw_data * pHwData, ChanInfo Channel) { u8 index = 100; @@ -1902,7 +1901,7 @@ void set_tx_power_per_channel_wb242( phw_data_t pHwData, ChanInfo Channel) // None. //============================================================================================================= void -RFSynthesizer_SwitchingChannel( phw_data_t pHwData, ChanInfo Channel ) +RFSynthesizer_SwitchingChannel( struct hw_data * pHwData, ChanInfo Channel ) { struct wb35_reg *reg = &pHwData->reg; u32 pltmp[16]; // The 16 is the maximum capability of hardware @@ -2012,7 +2011,7 @@ RFSynthesizer_SwitchingChannel( phw_data_t pHwData, ChanInfo Channel ) //Start to fill RF parameters, PLL_ON should be pulled low. //Wb35Reg_Write( pHwData, 0x03dc, 0x00000000 ); - //WBDEBUG(("* PLL_ON low\n")); + //printk("* PLL_ON low\n"); //Channel independent registers if( Channel.band != pHwData->band) @@ -2037,7 +2036,7 @@ RFSynthesizer_SwitchingChannel( phw_data_t pHwData, ChanInfo Channel ) // Write to register. number must less and equal than 16 Wb35Reg_BurstWrite( pHwData, 0x0864, pltmp, number, NO_INCREMENT ); #ifdef _PE_STATE_DUMP_ - WBDEBUG(("Band changed\n")); + printk("Band changed\n"); #endif } @@ -2130,7 +2129,7 @@ RFSynthesizer_SwitchingChannel( phw_data_t pHwData, ChanInfo Channel ) } //Set the tx power directly from DUT GUI, not from the EEPROM. Return the current setting -u8 RFSynthesizer_SetPowerIndex( phw_data_t pHwData, u8 PowerIndex ) +u8 RFSynthesizer_SetPowerIndex( struct hw_data * pHwData, u8 PowerIndex ) { u32 Band = pHwData->band; u8 index=0; @@ -2188,7 +2187,7 @@ u8 RFSynthesizer_SetPowerIndex( phw_data_t pHwData, u8 PowerIndex ) } //-- Sub function -u8 RFSynthesizer_SetMaxim2828_24Power( phw_data_t pHwData, u8 index ) +u8 RFSynthesizer_SetMaxim2828_24Power( struct hw_data * pHwData, u8 index ) { u32 PowerData; if( index > 1 ) index = 1; @@ -2197,7 +2196,7 @@ u8 RFSynthesizer_SetMaxim2828_24Power( phw_data_t pHwData, u8 index ) return index; } //-- -u8 RFSynthesizer_SetMaxim2828_50Power( phw_data_t pHwData, u8 index ) +u8 RFSynthesizer_SetMaxim2828_50Power( struct hw_data * pHwData, u8 index ) { u32 PowerData; if( index > 1 ) index = 1; @@ -2206,7 +2205,7 @@ u8 RFSynthesizer_SetMaxim2828_50Power( phw_data_t pHwData, u8 index ) return index; } //-- -u8 RFSynthesizer_SetMaxim2827_24Power( phw_data_t pHwData, u8 index ) +u8 RFSynthesizer_SetMaxim2827_24Power( struct hw_data * pHwData, u8 index ) { u32 PowerData; if( index > 1 ) index = 1; @@ -2215,7 +2214,7 @@ u8 RFSynthesizer_SetMaxim2827_24Power( phw_data_t pHwData, u8 index ) return index; } //-- -u8 RFSynthesizer_SetMaxim2827_50Power( phw_data_t pHwData, u8 index ) +u8 RFSynthesizer_SetMaxim2827_50Power( struct hw_data * pHwData, u8 index ) { u32 PowerData; if( index > 1 ) index = 1; @@ -2224,7 +2223,7 @@ u8 RFSynthesizer_SetMaxim2827_50Power( phw_data_t pHwData, u8 index ) return index; } //-- -u8 RFSynthesizer_SetMaxim2825Power( phw_data_t pHwData, u8 index ) +u8 RFSynthesizer_SetMaxim2825Power( struct hw_data * pHwData, u8 index ) { u32 PowerData; if( index > 1 ) index = 1; @@ -2233,7 +2232,7 @@ u8 RFSynthesizer_SetMaxim2825Power( phw_data_t pHwData, u8 index ) return index; } //-- -u8 RFSynthesizer_SetAiroha2230Power( phw_data_t pHwData, u8 index ) +u8 RFSynthesizer_SetAiroha2230Power( struct hw_data * pHwData, u8 index ) { u32 PowerData; u8 i,count; @@ -2252,7 +2251,7 @@ u8 RFSynthesizer_SetAiroha2230Power( phw_data_t pHwData, u8 index ) return i; } //-- -u8 RFSynthesizer_SetAiroha7230Power( phw_data_t pHwData, u8 index ) +u8 RFSynthesizer_SetAiroha7230Power( struct hw_data * pHwData, u8 index ) { u32 PowerData; u8 i,count; @@ -2271,7 +2270,7 @@ u8 RFSynthesizer_SetAiroha7230Power( phw_data_t pHwData, u8 index ) return i; } -u8 RFSynthesizer_SetWinbond242Power( phw_data_t pHwData, u8 index ) +u8 RFSynthesizer_SetWinbond242Power( struct hw_data * pHwData, u8 index ) { u32 PowerData; u8 i,count; @@ -2312,7 +2311,7 @@ u8 RFSynthesizer_SetWinbond242Power( phw_data_t pHwData, u8 index ) // Initial the hardware setting and module variable // //=========================================================================================================== -void Dxx_initial( phw_data_t pHwData ) +void Dxx_initial( struct hw_data * pHwData ) { struct wb35_reg *reg = &pHwData->reg; @@ -2326,7 +2325,7 @@ void Dxx_initial( phw_data_t pHwData ) Wb35Reg_WriteSync( pHwData, 0x0400, reg->D00_DmaControl ); } -void Mxx_initial( phw_data_t pHwData ) +void Mxx_initial( struct hw_data * pHwData ) { struct wb35_reg *reg = &pHwData->reg; u32 tmp; @@ -2417,7 +2416,7 @@ void Mxx_initial( phw_data_t pHwData ) } -void Uxx_power_off_procedure( phw_data_t pHwData ) +void Uxx_power_off_procedure( struct hw_data * pHwData ) { // SW, PMU reset and turn off clock Wb35Reg_WriteSync( pHwData, 0x03b0, 3 ); @@ -2425,7 +2424,7 @@ void Uxx_power_off_procedure( phw_data_t pHwData ) } //Decide the TxVga of every channel -void GetTxVgaFromEEPROM( phw_data_t pHwData ) +void GetTxVgaFromEEPROM( struct hw_data * pHwData ) { u32 i, j, ltmp; u16 Value[MAX_TXVGA_EEPROM]; @@ -2479,7 +2478,7 @@ void GetTxVgaFromEEPROM( phw_data_t pHwData ) // or RFSynthesizer_SetPowerIndex be called, new TxVga will take effect. // TxVgaSettingInEEPROM of sHwData is an u8 array point to EEPROM contain for IS89C35 // This function will use default TxVgaSettingInEEPROM data to calculate new TxVga. -void EEPROMTxVgaAdjust( phw_data_t pHwData ) // 20060619.5 Add +void EEPROMTxVgaAdjust( struct hw_data * pHwData ) // 20060619.5 Add { u8 * pTxVga = pHwData->TxVgaSettingInEEPROM; s16 i, stmp; @@ -2612,14 +2611,14 @@ void EEPROMTxVgaAdjust( phw_data_t pHwData ) // 20060619.5 Add } #ifdef _PE_STATE_DUMP_ - WBDEBUG((" TxVgaFor24 : \n")); + printk(" TxVgaFor24 : \n"); DataDmp((u8 *)pHwData->TxVgaFor24, 14 ,0); - WBDEBUG((" TxVgaFor50 : \n")); + printk(" TxVgaFor50 : \n"); DataDmp((u8 *)pHwData->TxVgaFor50, 70 ,0); #endif } -void BBProcessor_RateChanging( phw_data_t pHwData, u8 rate ) // 20060613.1 +void BBProcessor_RateChanging( struct hw_data * pHwData, u8 rate ) // 20060613.1 { struct wb35_reg *reg = &pHwData->reg; unsigned char Is11bRate; diff --git a/drivers/staging/winbond/sme_api.h b/drivers/staging/winbond/sme_api.h index 188a2532bbf4..549878302288 100644 --- a/drivers/staging/winbond/sme_api.h +++ b/drivers/staging/winbond/sme_api.h @@ -17,9 +17,6 @@ #include "localpara.h" -/****************** INCLUDE FILES SECTION ***********************************/ -//#include "GL\gl_core.h" - /****************** CONSTANT AND MACRO SECTION ******************************/ #define _INLINE __inline diff --git a/drivers/staging/winbond/sme_s.h b/drivers/staging/winbond/sme_s.h deleted file mode 100644 index 1bd118f83d20..000000000000 --- a/drivers/staging/winbond/sme_s.h +++ /dev/null @@ -1,236 +0,0 @@ -#ifndef __WINBOND_SME_S_H -#define __WINBOND_SME_S_H - -#include - -#include "mac_structures.h" -#include "localpara.h" - -// -// SME_S.H - -// SME task global CONSTANTS, STRUCTURES, variables -// - -////////////////////////////////////////////////////////////////////////// -//define the msg type of SME module -// 0x00~0x1F : MSG from GUI dispatch -// 0x20~0x3F : MSG from MLME -// 0x40~0x5F : MSG from SCAN -// 0x60~0x6F : MSG from TX/RX -// 0x70~0x7F : MSG from ROAMING -// 0x80~0x8F : MSG from ISR -// 0x90 : MSG TimeOut - -// from GUI -#define SMEMSG_SCAN_REQ 0x01 -//#define SMEMSG_PASSIVE_SCAN_REQ 0x02 -#define SMEMSG_JOIN_REQ 0x03 -#define SMEMSG_START_IBSS 0x04 -#define SMEMSG_DISCONNECT_REQ 0x05 -#define SMEMSG_AUTHEN_REQ 0x06 -#define SMEMSG_DEAUTHEN_REQ 0x07 -#define SMEMSG_ASSOC_REQ 0x08 -#define SMEMSG_REASSOC_REQ 0x09 -#define SMEMSG_DISASSOC_REQ 0x0a -#define SMEMSG_POWERSAVE_REQ 0x0b - - -// from MLME -#define SMEMSG_AUTHEN_CFM 0x21 -#define SMEMSG_AUTHEN_IND 0x22 -#define SMEMSG_ASSOC_CFM 0x23 -#define SMEMSG_DEAUTHEN_IND 0x24 -#define SMEMSG_DISASSOC_IND 0x25 -// from SCAN -#define SMEMSG_SCAN_CFM 0x41 -#define SMEMSG_START_IBSS_CFM 0x42 -// from MTO, function call to set SME parameters - -// 0x60~0x6F : MSG from TX/RX -//#define SMEMSG_IBSS_JOIN_UPDATE_BSSID 0x61 -#define SMEMSG_COUNTERMEASURE_MICFAIL_TIMEOUT 0x62 -#define SMEMSG_COUNTERMEASURE_BLOCK_TIMEOUT 0x63 -// from ROAMING -#define SMEMSG_HANDOVER_JOIN_REQ 0x71 -#define SMEMSG_END_ROAMING 0x72 -#define SMEMSG_SCAN_JOIN_REQ 0x73 -// from ISR -#define SMEMSG_TSF_SYNC_IND 0x81 -// from TimeOut -#define SMEMSG_TIMEOUT 0x91 - - - -#define MAX_PMKID_Accunt 16 -//@added by ws 04/22/05 -#define Cipher_Disabled 0 -#define Cipher_Wep 1 -#define Cipher_Tkip 2 -#define Cipher_Ccmp 4 - - -/////////////////////////////////////////////////////////////////////////// -//Constants - -/////////////////////////////////////////////////////////////////////////// -//Global data structures - -#define NUMOFWEPENTRIES 64 - -typedef enum _WEPKeyMode -{ - WEPKEY_DISABLED = 0, - WEPKEY_64 = 1, - WEPKEY_128 = 2 - -} WEPKEYMODE, *pWEPKEYMODE; - -#ifdef _WPA2_ - -typedef struct _BSSInfo -{ - u8 PreAuthBssID[6]; - PMKID pmkid_value; -}BSSID_Info; - -typedef struct _PMKID_Table //added by ws 05/05/04 -{ - u32 Length; - u32 BSSIDInfoCount; - BSSID_Info BSSIDInfo[16]; - -} PMKID_Table; - -#endif //end def _WPA2_ - -#define MAX_BASIC_RATE_SET 15 -#define MAX_OPT_RATE_SET MAX_BASIC_RATE_SET - - -typedef struct _SME_PARAMETERS -{ - u16 wState; - u8 boDUTmode; - u8 bDesiredPowerSave; - - // SME timer and timeout value - struct timer_list timer; - - u8 boInTimerHandler; - u8 boAuthRetryActive; - u8 reserved_0[2]; - - u32 AuthenRetryTimerVal; // NOTE: Assoc don't fail timeout - u32 JoinFailTimerVal; // 10*Beacon-Interval - - //Rates - u8 BSSBasicRateSet[(MAX_BASIC_RATE_SET + 3) & ~0x03 ]; // BSS basic rate set - u8 OperationalRateSet[(MAX_OPT_RATE_SET + 3) & ~0x03 ]; // Operational rate set - - u8 NumOfBSSBasicRate; - u8 NumOfOperationalRate; - u8 reserved_1[2]; - - u32 BasicRateBitmap; - u32 OpRateBitmap; - - // System parameters Set by GUI - //-------------------- start IBSS parameter ---------------------------// - u32 boStartIBSS; //Start IBSS toggle - - u16 wBeaconPeriod; - u16 wATIM_Window; - - ChanInfo IbssChan; // 2B //channel setting when start IBSS - u8 reserved_2[2]; - - // Join related - u16 wDesiredJoinBSS; // BSS index which desire to join - u8 boJoinReq; //Join request toggle - u8 bDesiredBSSType; //for Join request - - u16 wCapabilityInfo; // Used when invoking the MLME_Associate_request(). - u16 wNonERPcapabilityInfo; - - struct SSID_Element sDesiredSSID; // 34 B - u8 reserved_3[2]; - - u8 abDesiredBSSID[MAC_ADDR_LENGTH + 2]; - - u8 bJoinScanCount; // the time of scan-join action need to do - u8 bDesiredAuthMode; // AUTH_OPEN_SYSTEM or AUTH_SHARED_KEY - u8 reserved_4[2]; - - // Encryption parameters - u8 _dot11PrivacyInvoked; - u8 _dot11PrivacyOptionImplemented; - u8 reserved_5[2]; - - //@ ws added - u8 DesiredEncrypt; - u8 encrypt_status; //ENCRYPT_DISABLE, ENCRYPT_WEP, ENCRYPT_WEP_NOKEY, ENCRYPT_TKIP, ... - u8 key_length; - u8 pairwise_key_ok; - - u8 group_key_ok; - u8 wpa_ok; // indicate the control port of 802.1x is open or close - u8 pairwise_key_type; - u8 group_key_type; - - u32 _dot11WEPDefaultKeyID; - - u8 tx_mic_key[8]; // TODO: 0627 kevin-TKIP - u8 rx_mic_key[8]; // TODO: 0627 kevin-TKIP - u8 group_tx_mic_key[8]; - u8 group_rx_mic_key[8]; - -// #ifdef _WPA_ - u8 AssocReqVarIE[200]; - u8 AssocRespVarIE[200]; - - u16 AssocReqVarLen; - u16 AssocRespVarLen; - u8 boReassoc; //use assoc. or reassoc. - u8 reserved_6[3]; - u16 AssocRespCapability; - u16 AssocRespStatus; -// #endif - - #ifdef _WPA2_ - u8 PmkIdTable[256]; - u32 PmkidTableIndex; - #endif //end def _WPA2_ - -} SME_PARAMETERS, *PSME_PARAMETERS; - -#define psSME (&(adapter->sSmePara)) - -#define wSMEGetCurrentSTAState(adapter) ((u16)(adapter)->sSmePara.wState) - - - -//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// SmeModule.h -// Define the related definitions of SME module -// history -- 01/14/03' created -// -//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -//Define the state of SME module -#define DISABLED 0 -#define INIT_SCAN 1 -#define SCAN_READY 2 -#define START_IBSS 3 -#define JOIN_PENDING 4 -#define JOIN_CFM 5 -#define AUTHENTICATE_PENDING 6 -#define AUTHENTICATED 7 -#define CONNECTED 8 -//#define EAP_STARTING 9 -//#define EAPOL_AUTHEN_PENDING 10 -//#define SECURE_CONNECTED 11 - - -// Static function - -#endif diff --git a/drivers/staging/winbond/wb35_ver.h b/drivers/staging/winbond/wb35_ver.h deleted file mode 100644 index 2433bc073004..000000000000 --- a/drivers/staging/winbond/wb35_ver.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Only define one of follow -// - -#ifdef WB_WIN - #define VER_FILEVERSION 1,00,47,00 - #define VER_FILEVERSION_STR "1.00.47.00" - #define WB32_DRIVER_MAJOR_VERSION 0x0100 - #define WB32_DRIVER_MINOR_VERSION 0x4700 -#endif - -#ifdef WB_CE - #define VER_FILEVERSION 2,00,47,00 - #define VER_FILEVERSION_STR "2.00.47.00" - #define WB32_DRIVER_MAJOR_VERSION 0x0200 - #define WB32_DRIVER_MINOR_VERSION 0x4700 -#endif - -#ifdef WB_LINUX - #define VER_FILEVERSION 3,00,47,00 - #define VER_FILEVERSION_STR "3.00.47.00" - #define WB32_DRIVER_MAJOR_VERSION 0x0300 - #define WB32_DRIVER_MINOR_VERSION 0x4700 -#endif - - - - - - diff --git a/drivers/staging/winbond/wb35reg.c b/drivers/staging/winbond/wb35reg.c index c74b3fdcbda0..f5608ad9ed00 100644 --- a/drivers/staging/winbond/wb35reg.c +++ b/drivers/staging/winbond/wb35reg.c @@ -3,7 +3,7 @@ #include -extern void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency); +extern void phy_calibration_winbond(struct hw_data *phw_data, u32 frequency); // true : read command process successfully // false : register not support @@ -13,7 +13,7 @@ extern void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency); // Flag : AUTO_INCREMENT - RegisterNo will auto increment 4 // NO_INCREMENT - Function will write data into the same register unsigned char -Wb35Reg_BurstWrite(phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterData, u8 NumberOfData, u8 Flag) +Wb35Reg_BurstWrite(struct hw_data * pHwData, u16 RegisterNo, u32 * pRegisterData, u8 NumberOfData, u8 Flag) { struct wb35_reg *reg = &pHwData->reg; struct urb *urb = NULL; @@ -73,7 +73,7 @@ Wb35Reg_BurstWrite(phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterData, u8 N } void -Wb35Reg_Update(phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue) +Wb35Reg_Update(struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue) { struct wb35_reg *reg = &pHwData->reg; switch (RegisterNo) { @@ -118,7 +118,7 @@ Wb35Reg_Update(phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue) // true : read command process successfully // false : register not support unsigned char -Wb35Reg_WriteSync( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue ) +Wb35Reg_WriteSync( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue ) { struct wb35_reg *reg = &pHwData->reg; int ret = -1; @@ -149,7 +149,7 @@ Wb35Reg_WriteSync( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue ) if (ret < 0) { #ifdef _PE_REG_DUMP_ - WBDEBUG(("EP0 Write register usb message sending error\n")); + printk("EP0 Write register usb message sending error\n"); #endif pHwData->SurpriseRemove = 1; // 20060704.2 @@ -162,7 +162,7 @@ Wb35Reg_WriteSync( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue ) // true : read command process successfully // false : register not support unsigned char -Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue ) +Wb35Reg_Write( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue ) { struct wb35_reg *reg = &pHwData->reg; struct usb_ctrlrequest *dr; @@ -222,7 +222,7 @@ Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue ) // true : read command process successfully // false : register not support unsigned char -Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue, +Wb35Reg_WriteWithCallbackValue( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue, s8 *pValue, s8 Len) { struct wb35_reg *reg = &pHwData->reg; @@ -281,7 +281,7 @@ Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, u16 RegisterNo, u32 Register // false : register not support // pRegisterValue : It must be a resident buffer due to asynchronous read register. unsigned char -Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue ) +Wb35Reg_ReadSync( struct hw_data * pHwData, u16 RegisterNo, u32 * pRegisterValue ) { struct wb35_reg *reg = &pHwData->reg; u32 * pltmp = pRegisterValue; @@ -316,7 +316,7 @@ Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue ) if (ret < 0) { #ifdef _PE_REG_DUMP_ - WBDEBUG(("EP0 Read register usb message sending error\n")); + printk("EP0 Read register usb message sending error\n"); #endif pHwData->SurpriseRemove = 1; // 20060704.2 @@ -330,7 +330,7 @@ Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue ) // false : register not support // pRegisterValue : It must be a resident buffer due to asynchronous read register. unsigned char -Wb35Reg_Read(phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue ) +Wb35Reg_Read(struct hw_data * pHwData, u16 RegisterNo, u32 * pRegisterValue ) { struct wb35_reg *reg = &pHwData->reg; struct usb_ctrlrequest * dr; @@ -385,7 +385,7 @@ Wb35Reg_Read(phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue ) void -Wb35Reg_EP0VM_start( phw_data_t pHwData ) +Wb35Reg_EP0VM_start( struct hw_data * pHwData ) { struct wb35_reg *reg = &pHwData->reg; @@ -397,7 +397,7 @@ Wb35Reg_EP0VM_start( phw_data_t pHwData ) } void -Wb35Reg_EP0VM(phw_data_t pHwData ) +Wb35Reg_EP0VM(struct hw_data * pHwData ) { struct wb35_reg *reg = &pHwData->reg; struct urb *urb; @@ -441,7 +441,7 @@ Wb35Reg_EP0VM(phw_data_t pHwData ) if (ret < 0) { #ifdef _PE_REG_DUMP_ - WBDEBUG(("EP0 Irp sending error\n")); + printk("EP0 Irp sending error\n"); #endif goto cleanup; } @@ -457,7 +457,7 @@ Wb35Reg_EP0VM(phw_data_t pHwData ) void Wb35Reg_EP0VM_complete(struct urb *urb) { - phw_data_t pHwData = (phw_data_t)urb->context; + struct hw_data * pHwData = (struct hw_data *)urb->context; struct wb35_reg *reg = &pHwData->reg; struct wb35_reg_queue *reg_queue; @@ -480,8 +480,7 @@ Wb35Reg_EP0VM_complete(struct urb *urb) if (reg->EP0VM_status) { #ifdef _PE_REG_DUMP_ - WBDEBUG(("EP0 IoCompleteRoutine return error\n")); - DebugUsbdStatusInformation( reg->EP0VM_status ); + printk("EP0 IoCompleteRoutine return error\n"); #endif reg->EP0vm_state = VM_STOP; pHwData->SurpriseRemove = 1; @@ -500,7 +499,7 @@ Wb35Reg_EP0VM_complete(struct urb *urb) void -Wb35Reg_destroy(phw_data_t pHwData) +Wb35Reg_destroy(struct hw_data * pHwData) { struct wb35_reg *reg = &pHwData->reg; struct urb *urb; @@ -530,7 +529,7 @@ Wb35Reg_destroy(phw_data_t pHwData) kfree(reg_queue); } else { #ifdef _PE_REG_DUMP_ - WBDEBUG(("EP0 queue release error\n")); + printk("EP0 queue release error\n"); #endif } spin_lock_irq( ®->EP0VM_spin_lock ); @@ -543,7 +542,7 @@ Wb35Reg_destroy(phw_data_t pHwData) //==================================================================================== // The function can be run in passive-level only. //==================================================================================== -unsigned char Wb35Reg_initial(phw_data_t pHwData) +unsigned char Wb35Reg_initial(struct hw_data * pHwData) { struct wb35_reg *reg=&pHwData->reg; u32 ltmp; @@ -599,7 +598,7 @@ unsigned char Wb35Reg_initial(phw_data_t pHwData) Wb35Reg_ReadSync( pHwData, 0x03b4, &Region_ScanInterval ); // Update Ethernet address - memcpy( pHwData->CurrentMacAddress, pHwData->PermanentMacAddress, ETH_LENGTH_OF_ADDRESS ); + memcpy( pHwData->CurrentMacAddress, pHwData->PermanentMacAddress, ETH_ALEN ); // Update software variable pHwData->SoftwareSet = (u16)(SoftwareSet & 0xffff); @@ -723,7 +722,7 @@ u32 BitReverse( u32 dwData, u32 DataLength) return dwData; } -void Wb35Reg_phy_calibration( phw_data_t pHwData ) +void Wb35Reg_phy_calibration( struct hw_data * pHwData ) { u32 BB3c, BB54; diff --git a/drivers/staging/winbond/wb35reg_f.h b/drivers/staging/winbond/wb35reg_f.h index d97215a1eba8..30f5b5ad63ad 100644 --- a/drivers/staging/winbond/wb35reg_f.h +++ b/drivers/staging/winbond/wb35reg_f.h @@ -6,47 +6,47 @@ //==================================== // Interface function declare //==================================== -unsigned char Wb35Reg_initial( phw_data_t pHwData ); -void Uxx_power_on_procedure( phw_data_t pHwData ); -void Uxx_power_off_procedure( phw_data_t pHwData ); -void Uxx_ReadEthernetAddress( phw_data_t pHwData ); -void Dxx_initial( phw_data_t pHwData ); -void Mxx_initial( phw_data_t pHwData ); -void RFSynthesizer_initial( phw_data_t pHwData ); -//void RFSynthesizer_SwitchingChannel( phw_data_t pHwData, s8 Channel ); -void RFSynthesizer_SwitchingChannel( phw_data_t pHwData, ChanInfo Channel ); -void BBProcessor_initial( phw_data_t pHwData ); -void BBProcessor_RateChanging( phw_data_t pHwData, u8 rate ); // 20060613.1 -//void RF_RateChanging( phw_data_t pHwData, u8 rate ); // 20060626.5.c Add -u8 RFSynthesizer_SetPowerIndex( phw_data_t pHwData, u8 PowerIndex ); -u8 RFSynthesizer_SetMaxim2828_24Power( phw_data_t, u8 index ); -u8 RFSynthesizer_SetMaxim2828_50Power( phw_data_t, u8 index ); -u8 RFSynthesizer_SetMaxim2827_24Power( phw_data_t, u8 index ); -u8 RFSynthesizer_SetMaxim2827_50Power( phw_data_t, u8 index ); -u8 RFSynthesizer_SetMaxim2825Power( phw_data_t, u8 index ); -u8 RFSynthesizer_SetAiroha2230Power( phw_data_t, u8 index ); -u8 RFSynthesizer_SetAiroha7230Power( phw_data_t, u8 index ); -u8 RFSynthesizer_SetWinbond242Power( phw_data_t, u8 index ); -void GetTxVgaFromEEPROM( phw_data_t pHwData ); -void EEPROMTxVgaAdjust( phw_data_t pHwData ); // 20060619.5 Add +unsigned char Wb35Reg_initial( struct hw_data * pHwData ); +void Uxx_power_on_procedure( struct hw_data * pHwData ); +void Uxx_power_off_procedure( struct hw_data * pHwData ); +void Uxx_ReadEthernetAddress( struct hw_data * pHwData ); +void Dxx_initial( struct hw_data * pHwData ); +void Mxx_initial( struct hw_data * pHwData ); +void RFSynthesizer_initial( struct hw_data * pHwData ); +//void RFSynthesizer_SwitchingChannel( struct hw_data * pHwData, s8 Channel ); +void RFSynthesizer_SwitchingChannel( struct hw_data * pHwData, ChanInfo Channel ); +void BBProcessor_initial( struct hw_data * pHwData ); +void BBProcessor_RateChanging( struct hw_data * pHwData, u8 rate ); // 20060613.1 +//void RF_RateChanging( struct hw_data * pHwData, u8 rate ); // 20060626.5.c Add +u8 RFSynthesizer_SetPowerIndex( struct hw_data * pHwData, u8 PowerIndex ); +u8 RFSynthesizer_SetMaxim2828_24Power( struct hw_data *, u8 index ); +u8 RFSynthesizer_SetMaxim2828_50Power( struct hw_data *, u8 index ); +u8 RFSynthesizer_SetMaxim2827_24Power( struct hw_data *, u8 index ); +u8 RFSynthesizer_SetMaxim2827_50Power( struct hw_data *, u8 index ); +u8 RFSynthesizer_SetMaxim2825Power( struct hw_data *, u8 index ); +u8 RFSynthesizer_SetAiroha2230Power( struct hw_data *, u8 index ); +u8 RFSynthesizer_SetAiroha7230Power( struct hw_data *, u8 index ); +u8 RFSynthesizer_SetWinbond242Power( struct hw_data *, u8 index ); +void GetTxVgaFromEEPROM( struct hw_data * pHwData ); +void EEPROMTxVgaAdjust( struct hw_data * pHwData ); // 20060619.5 Add #define RFWriteControlData( _A, _V ) Wb35Reg_Write( _A, 0x0864, _V ) -void Wb35Reg_destroy( phw_data_t pHwData ); +void Wb35Reg_destroy( struct hw_data * pHwData ); -unsigned char Wb35Reg_Read( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue ); -unsigned char Wb35Reg_ReadSync( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterValue ); -unsigned char Wb35Reg_Write( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue ); -unsigned char Wb35Reg_WriteSync( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue ); -unsigned char Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, +unsigned char Wb35Reg_Read( struct hw_data * pHwData, u16 RegisterNo, u32 * pRegisterValue ); +unsigned char Wb35Reg_ReadSync( struct hw_data * pHwData, u16 RegisterNo, u32 * pRegisterValue ); +unsigned char Wb35Reg_Write( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue ); +unsigned char Wb35Reg_WriteSync( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue ); +unsigned char Wb35Reg_WriteWithCallbackValue( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue, s8 *pValue, s8 Len); -unsigned char Wb35Reg_BurstWrite( phw_data_t pHwData, u16 RegisterNo, u32 * pRegisterData, u8 NumberOfData, u8 Flag ); +unsigned char Wb35Reg_BurstWrite( struct hw_data * pHwData, u16 RegisterNo, u32 * pRegisterData, u8 NumberOfData, u8 Flag ); -void Wb35Reg_EP0VM( phw_data_t pHwData ); -void Wb35Reg_EP0VM_start( phw_data_t pHwData ); +void Wb35Reg_EP0VM( struct hw_data * pHwData ); +void Wb35Reg_EP0VM_start( struct hw_data * pHwData ); void Wb35Reg_EP0VM_complete(struct urb *urb); u32 BitReverse( u32 dwData, u32 DataLength); @@ -54,8 +54,8 @@ u32 BitReverse( u32 dwData, u32 DataLength); void CardGetMulticastBit( u8 Address[MAC_ADDR_LENGTH], u8 *Byte, u8 *Value ); u32 CardComputeCrc( u8 * Buffer, u32 Length ); -void Wb35Reg_phy_calibration( phw_data_t pHwData ); -void Wb35Reg_Update( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue ); -unsigned char adjust_TXVGA_for_iq_mag( phw_data_t pHwData ); +void Wb35Reg_phy_calibration( struct hw_data * pHwData ); +void Wb35Reg_Update( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue ); +unsigned char adjust_TXVGA_for_iq_mag( struct hw_data * pHwData ); #endif diff --git a/drivers/staging/winbond/wb35rx.c b/drivers/staging/winbond/wb35rx.c index 7f8b6d749a47..3e8cf08b87e6 100644 --- a/drivers/staging/winbond/wb35rx.c +++ b/drivers/staging/winbond/wb35rx.c @@ -82,9 +82,9 @@ static void Wb35Rx_adjust(PDESCRIPTOR pRxDes) static u16 Wb35Rx_indicate(struct ieee80211_hw *hw) { struct wbsoft_priv *priv = hw->priv; - phw_data_t pHwData = &priv->sHwData; + struct hw_data * pHwData = &priv->sHwData; DESCRIPTOR RxDes; - PWB35RX pWb35Rx = &pHwData->Wb35Rx; + struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx; u8 * pRxBufferAddress; u16 PacketSize; u16 stmp, BufferSize, stmp2 = 0; @@ -118,7 +118,7 @@ static u16 Wb35Rx_indicate(struct ieee80211_hw *hw) // Basic check for Rx length. Is length valid? if (PacketSize > MAX_PACKET_SIZE) { #ifdef _PE_RX_DUMP_ - WBDEBUG(("Serious ERROR : Rx data size too long, size =%d\n", PacketSize)); + printk("Serious ERROR : Rx data size too long, size =%d\n", PacketSize); #endif pWb35Rx->EP3vm_state = VM_STOP; @@ -161,8 +161,8 @@ static void Wb35Rx_Complete(struct urb *urb) { struct ieee80211_hw *hw = urb->context; struct wbsoft_priv *priv = hw->priv; - phw_data_t pHwData = &priv->sHwData; - PWB35RX pWb35Rx = &pHwData->Wb35Rx; + struct hw_data * pHwData = &priv->sHwData; + struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx; u8 * pRxBufferAddress; u32 SizeCheck; u16 BulkLength; @@ -194,8 +194,7 @@ static void Wb35Rx_Complete(struct urb *urb) // The URB is completed, check the result if (pWb35Rx->EP3VM_status != 0) { #ifdef _PE_USB_STATE_DUMP_ - WBDEBUG(("EP3 IoCompleteRoutine return error\n")); - DebugUsbdStatusInformation( pWb35Rx->EP3VM_status ); + printk("EP3 IoCompleteRoutine return error\n"); #endif pWb35Rx->EP3vm_state = VM_STOP; goto error; @@ -239,8 +238,8 @@ error: static void Wb35Rx(struct ieee80211_hw *hw) { struct wbsoft_priv *priv = hw->priv; - phw_data_t pHwData = &priv->sHwData; - PWB35RX pWb35Rx = &pHwData->Wb35Rx; + struct hw_data * pHwData = &priv->sHwData; + struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx; u8 * pRxBufferAddress; struct urb *urb = pWb35Rx->RxUrb; int retv; @@ -260,7 +259,7 @@ static void Wb35Rx(struct ieee80211_hw *hw) if (!pWb35Rx->RxOwner[RxBufferId]) { // It's impossible to run here. #ifdef _PE_RX_DUMP_ - WBDEBUG(("Rx driver fifo unavailable\n")); + printk("Rx driver fifo unavailable\n"); #endif goto error; } @@ -302,8 +301,8 @@ error: void Wb35Rx_start(struct ieee80211_hw *hw) { struct wbsoft_priv *priv = hw->priv; - phw_data_t pHwData = &priv->sHwData; - PWB35RX pWb35Rx = &pHwData->Wb35Rx; + struct hw_data * pHwData = &priv->sHwData; + struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx; // Allow only one thread to run into the Wb35Rx() function if (atomic_inc_return(&pWb35Rx->RxFireCounter) == 1) { @@ -314,9 +313,9 @@ void Wb35Rx_start(struct ieee80211_hw *hw) } //===================================================================================== -static void Wb35Rx_reset_descriptor( phw_data_t pHwData ) +static void Wb35Rx_reset_descriptor( struct hw_data * pHwData ) { - PWB35RX pWb35Rx = &pHwData->Wb35Rx; + struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx; u32 i; pWb35Rx->ByteReceived = 0; @@ -330,9 +329,9 @@ static void Wb35Rx_reset_descriptor( phw_data_t pHwData ) pWb35Rx->RxOwner[i] = 1; } -unsigned char Wb35Rx_initial(phw_data_t pHwData) +unsigned char Wb35Rx_initial(struct hw_data * pHwData) { - PWB35RX pWb35Rx = &pHwData->Wb35Rx; + struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx; // Initial the Buffer Queue Wb35Rx_reset_descriptor( pHwData ); @@ -341,23 +340,23 @@ unsigned char Wb35Rx_initial(phw_data_t pHwData) return (!!pWb35Rx->RxUrb); } -void Wb35Rx_stop(phw_data_t pHwData) +void Wb35Rx_stop(struct hw_data * pHwData) { - PWB35RX pWb35Rx = &pHwData->Wb35Rx; + struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx; // Canceling the Irp if already sends it out. if (pWb35Rx->EP3vm_state == VM_RUNNING) { usb_unlink_urb( pWb35Rx->RxUrb ); // Only use unlink, let Wb35Rx_destroy to free them #ifdef _PE_RX_DUMP_ - WBDEBUG(("EP3 Rx stop\n")); + printk("EP3 Rx stop\n"); #endif } } // Needs process context -void Wb35Rx_destroy(phw_data_t pHwData) +void Wb35Rx_destroy(struct hw_data * pHwData) { - PWB35RX pWb35Rx = &pHwData->Wb35Rx; + struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx; do { msleep(10); // Delay for waiting function enter 940623.1.a @@ -367,7 +366,7 @@ void Wb35Rx_destroy(phw_data_t pHwData) if (pWb35Rx->RxUrb) usb_free_urb( pWb35Rx->RxUrb ); #ifdef _PE_RX_DUMP_ - WBDEBUG(("Wb35Rx_destroy OK\n")); + printk("Wb35Rx_destroy OK\n"); #endif } diff --git a/drivers/staging/winbond/wb35rx_f.h b/drivers/staging/winbond/wb35rx_f.h index d993041e0cdd..98acce517d90 100644 --- a/drivers/staging/winbond/wb35rx_f.h +++ b/drivers/staging/winbond/wb35rx_f.h @@ -7,9 +7,9 @@ //==================================== // Interface function declare //==================================== -unsigned char Wb35Rx_initial( phw_data_t pHwData ); -void Wb35Rx_destroy( phw_data_t pHwData ); -void Wb35Rx_stop( phw_data_t pHwData ); +unsigned char Wb35Rx_initial( struct hw_data * pHwData ); +void Wb35Rx_destroy( struct hw_data * pHwData ); +void Wb35Rx_stop( struct hw_data * pHwData ); void Wb35Rx_start(struct ieee80211_hw *hw); #endif diff --git a/drivers/staging/winbond/wb35rx_s.h b/drivers/staging/winbond/wb35rx_s.h index f18350b41c44..4b03274a7d28 100644 --- a/drivers/staging/winbond/wb35rx_s.h +++ b/drivers/staging/winbond/wb35rx_s.h @@ -15,8 +15,7 @@ //==================================== // Internal variable for module //==================================== -typedef struct _WB35RX -{ +struct wb35_rx { u32 ByteReceived;// For calculating throughput of BulkIn atomic_t RxFireCounter;// Does Wb35Rx module fire? @@ -42,7 +41,4 @@ typedef struct _WB35RX int EP3VM_status; u8 * pDRx; - -} WB35RX, *PWB35RX; - - +}; diff --git a/drivers/staging/winbond/wb35tx.c b/drivers/staging/winbond/wb35tx.c index b9b4456c8082..1e4169d9a119 100644 --- a/drivers/staging/winbond/wb35tx.c +++ b/drivers/staging/winbond/wb35tx.c @@ -15,9 +15,9 @@ #include "sysdef.h" unsigned char -Wb35Tx_get_tx_buffer(phw_data_t pHwData, u8 **pBuffer) +Wb35Tx_get_tx_buffer(struct hw_data * pHwData, u8 **pBuffer) { - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; *pBuffer = pWb35Tx->TxBuffer[0]; return true; @@ -28,8 +28,8 @@ static void Wb35Tx(struct wbsoft_priv *adapter); static void Wb35Tx_complete(struct urb * pUrb) { struct wbsoft_priv *adapter = pUrb->context; - phw_data_t pHwData = &adapter->sHwData; - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct hw_data * pHwData = &adapter->sHwData; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; PMDS pMds = &adapter->Mds; printk("wb35: tx complete\n"); @@ -64,8 +64,8 @@ error: static void Wb35Tx(struct wbsoft_priv *adapter) { - phw_data_t pHwData = &adapter->sHwData; - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct hw_data * pHwData = &adapter->sHwData; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; u8 *pTxBufferAddress; PMDS pMds = &adapter->Mds; struct urb * pUrb = (struct urb *)pWb35Tx->Tx4Urb; @@ -115,8 +115,8 @@ static void Wb35Tx(struct wbsoft_priv *adapter) void Wb35Tx_start(struct wbsoft_priv *adapter) { - phw_data_t pHwData = &adapter->sHwData; - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct hw_data * pHwData = &adapter->sHwData; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; // Allow only one thread to run into function if (atomic_inc_return(&pWb35Tx->TxFireCounter) == 1) { @@ -126,9 +126,9 @@ void Wb35Tx_start(struct wbsoft_priv *adapter) atomic_dec(&pWb35Tx->TxFireCounter); } -unsigned char Wb35Tx_initial(phw_data_t pHwData) +unsigned char Wb35Tx_initial(struct hw_data * pHwData) { - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; pWb35Tx->Tx4Urb = usb_alloc_urb(0, GFP_ATOMIC); if (!pWb35Tx->Tx4Urb) @@ -145,29 +145,29 @@ unsigned char Wb35Tx_initial(phw_data_t pHwData) } //====================================================== -void Wb35Tx_stop(phw_data_t pHwData) +void Wb35Tx_stop(struct hw_data * pHwData) { - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; // Trying to canceling the Trp of EP2 if (pWb35Tx->EP2vm_state == VM_RUNNING) usb_unlink_urb( pWb35Tx->Tx2Urb ); // Only use unlink, let Wb35Tx_destrot to free them #ifdef _PE_TX_DUMP_ - WBDEBUG(("EP2 Tx stop\n")); + printk("EP2 Tx stop\n"); #endif // Trying to canceling the Irp of EP4 if (pWb35Tx->EP4vm_state == VM_RUNNING) usb_unlink_urb( pWb35Tx->Tx4Urb ); // Only use unlink, let Wb35Tx_destrot to free them #ifdef _PE_TX_DUMP_ - WBDEBUG(("EP4 Tx stop\n")); + printk("EP4 Tx stop\n"); #endif } //====================================================== -void Wb35Tx_destroy(phw_data_t pHwData) +void Wb35Tx_destroy(struct hw_data * pHwData) { - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; // Wait for VM stop do { @@ -182,14 +182,14 @@ void Wb35Tx_destroy(phw_data_t pHwData) usb_free_urb( pWb35Tx->Tx2Urb ); #ifdef _PE_TX_DUMP_ - WBDEBUG(("Wb35Tx_destroy OK\n")); + printk("Wb35Tx_destroy OK\n"); #endif } void Wb35Tx_CurrentTime(struct wbsoft_priv *adapter, u32 TimeCount) { - phw_data_t pHwData = &adapter->sHwData; - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct hw_data * pHwData = &adapter->sHwData; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; unsigned char Trigger = false; if (pWb35Tx->TxTimer > TimeCount) @@ -208,9 +208,9 @@ static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter); static void Wb35Tx_EP2VM_complete(struct urb * pUrb) { struct wbsoft_priv *adapter = pUrb->context; - phw_data_t pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; T02_DESCRIPTOR T02, TSTATUS; - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; u32 * pltmp = (u32 *)pWb35Tx->EP2_buf; u32 i; u16 InterruptInLength; @@ -229,7 +229,7 @@ static void Wb35Tx_EP2VM_complete(struct urb * pUrb) //The Urb is completed, check the result if (pWb35Tx->EP2VM_status != 0) { - WBDEBUG(("EP2 IoCompleteRoutine return error\n")); + printk("EP2 IoCompleteRoutine return error\n"); pWb35Tx->EP2vm_state= VM_STOP; goto error; } @@ -256,8 +256,8 @@ error: static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter) { - phw_data_t pHwData = &adapter->sHwData; - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct hw_data * pHwData = &adapter->sHwData; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; struct urb * pUrb = (struct urb *)pWb35Tx->Tx2Urb; u32 * pltmp = (u32 *)pWb35Tx->EP2_buf; int retv; @@ -279,7 +279,7 @@ static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter) if (retv < 0) { #ifdef _PE_TX_DUMP_ - WBDEBUG(("EP2 Tx Irp sending error\n")); + printk("EP2 Tx Irp sending error\n"); #endif goto error; } @@ -292,8 +292,8 @@ error: void Wb35Tx_EP2VM_start(struct wbsoft_priv *adapter) { - phw_data_t pHwData = &adapter->sHwData; - PWB35TX pWb35Tx = &pHwData->Wb35Tx; + struct hw_data * pHwData = &adapter->sHwData; + struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx; // Allow only one thread to run into function if (atomic_inc_return(&pWb35Tx->TxResultCount) == 1) { diff --git a/drivers/staging/winbond/wb35tx_f.h b/drivers/staging/winbond/wb35tx_f.h index 4222fa80c7bd..a7af9cbe202a 100644 --- a/drivers/staging/winbond/wb35tx_f.h +++ b/drivers/staging/winbond/wb35tx_f.h @@ -7,14 +7,14 @@ //==================================== // Interface function declare //==================================== -unsigned char Wb35Tx_initial( phw_data_t pHwData ); -void Wb35Tx_destroy( phw_data_t pHwData ); -unsigned char Wb35Tx_get_tx_buffer( phw_data_t pHwData, u8 **pBuffer ); +unsigned char Wb35Tx_initial( struct hw_data * pHwData ); +void Wb35Tx_destroy( struct hw_data * pHwData ); +unsigned char Wb35Tx_get_tx_buffer( struct hw_data * pHwData, u8 **pBuffer ); void Wb35Tx_EP2VM_start(struct wbsoft_priv *adapter); void Wb35Tx_start(struct wbsoft_priv *adapter); -void Wb35Tx_stop( phw_data_t pHwData ); +void Wb35Tx_stop( struct hw_data * pHwData ); void Wb35Tx_CurrentTime(struct wbsoft_priv *adapter, u32 TimeCount); diff --git a/drivers/staging/winbond/wb35tx_s.h b/drivers/staging/winbond/wb35tx_s.h index 3960276cae68..f70f43395591 100644 --- a/drivers/staging/winbond/wb35tx_s.h +++ b/drivers/staging/winbond/wb35tx_s.h @@ -18,8 +18,7 @@ //==================================== -typedef struct _WB35TX -{ +struct wb35_tx { // For Tx buffer u8 TxBuffer[ MAX_USB_TX_BUFFER_NUMBER ][ MAX_USB_TX_BUFFER ]; @@ -43,7 +42,6 @@ typedef struct _WB35TX u32 TxFillCount; // 20060928 u32 TxTimer; // 20060928 Add if sending packet not great than 13 - -} WB35TX, *PWB35TX; +}; #endif diff --git a/drivers/staging/winbond/wbhal.c b/drivers/staging/winbond/wbhal.c index 8a9d21cbb0c0..c985ad065238 100644 --- a/drivers/staging/winbond/wbhal.c +++ b/drivers/staging/winbond/wbhal.c @@ -1,14 +1,14 @@ -#include "os_common.h" +#include "sysdef.h" #include "wbhal_f.h" #include "wblinux_f.h" -void hal_set_ethernet_address( phw_data_t pHwData, u8 *current_address ) +void hal_set_ethernet_address( struct hw_data * pHwData, u8 *current_address ) { u32 ltmp[2]; if( pHwData->SurpriseRemove ) return; - memcpy( pHwData->CurrentMacAddress, current_address, ETH_LENGTH_OF_ADDRESS ); + memcpy( pHwData->CurrentMacAddress, current_address, ETH_ALEN ); ltmp[0]= cpu_to_le32( *(u32 *)pHwData->CurrentMacAddress ); ltmp[1]= cpu_to_le32( *(u32 *)(pHwData->CurrentMacAddress + 4) ) & 0xffff; @@ -16,7 +16,7 @@ void hal_set_ethernet_address( phw_data_t pHwData, u8 *current_address ) Wb35Reg_BurstWrite( pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT ); } -void hal_get_permanent_address( phw_data_t pHwData, u8 *pethernet_address ) +void hal_get_permanent_address( struct hw_data * pHwData, u8 *pethernet_address ) { if( pHwData->SurpriseRemove ) return; @@ -26,7 +26,7 @@ void hal_get_permanent_address( phw_data_t pHwData, u8 *pethernet_address ) static void hal_led_control(unsigned long data) { struct wbsoft_priv *adapter = (struct wbsoft_priv *) data; - phw_data_t pHwData = &adapter->sHwData; + struct hw_data * pHwData = &adapter->sHwData; struct wb35_reg *reg = &pHwData->reg; u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT; u8 LEDgray[20] = { 0,3,4,6,8,10,11,12,13,14,15,14,13,12,11,10,8,6,4,2 }; @@ -311,7 +311,7 @@ static void hal_led_control(unsigned long data) u8 hal_init_hardware(struct ieee80211_hw *hw) { struct wbsoft_priv *priv = hw->priv; - phw_data_t pHwData = &priv->sHwData; + struct hw_data * pHwData = &priv->sHwData; u16 SoftwareSet; // Initial the variable @@ -356,7 +356,7 @@ u8 hal_init_hardware(struct ieee80211_hw *hw) } -void hal_halt(phw_data_t pHwData, void *ppa_data) +void hal_halt(struct hw_data * pHwData, void *ppa_data) { switch( pHwData->InitialResource ) { @@ -370,7 +370,7 @@ void hal_halt(phw_data_t pHwData, void *ppa_data) } //--------------------------------------------------------------------------------------------------- -void hal_set_beacon_period( phw_data_t pHwData, u16 beacon_period ) +void hal_set_beacon_period( struct hw_data * pHwData, u16 beacon_period ) { u32 tmp; @@ -383,7 +383,7 @@ void hal_set_beacon_period( phw_data_t pHwData, u16 beacon_period ) } -static void hal_set_current_channel_ex( phw_data_t pHwData, ChanInfo channel ) +static void hal_set_current_channel_ex( struct hw_data * pHwData, ChanInfo channel ) { struct wb35_reg *reg = &pHwData->reg; @@ -396,7 +396,7 @@ static void hal_set_current_channel_ex( phw_data_t pHwData, ChanInfo channel ) pHwData->Channel = channel.ChanNo; pHwData->band = channel.band; #ifdef _PE_STATE_DUMP_ - WBDEBUG(("Set channel is %d, band =%d\n", pHwData->Channel, pHwData->band)); + printk("Set channel is %d, band =%d\n", pHwData->Channel, pHwData->band); #endif reg->M28_MacControl &= ~0xff; // Clean channel information field reg->M28_MacControl |= channel.ChanNo; @@ -404,12 +404,12 @@ static void hal_set_current_channel_ex( phw_data_t pHwData, ChanInfo channel ) (s8 *)&channel, sizeof(ChanInfo)); } //--------------------------------------------------------------------------------------------------- -void hal_set_current_channel( phw_data_t pHwData, ChanInfo channel ) +void hal_set_current_channel( struct hw_data * pHwData, ChanInfo channel ) { hal_set_current_channel_ex( pHwData, channel ); } //--------------------------------------------------------------------------------------------------- -void hal_set_accept_broadcast( phw_data_t pHwData, u8 enable ) +void hal_set_accept_broadcast( struct hw_data * pHwData, u8 enable ) { struct wb35_reg *reg = &pHwData->reg; @@ -424,7 +424,7 @@ void hal_set_accept_broadcast( phw_data_t pHwData, u8 enable ) } //for wep key error detection, we need to accept broadcast packets to be received temporary. -void hal_set_accept_promiscuous( phw_data_t pHwData, u8 enable) +void hal_set_accept_promiscuous( struct hw_data * pHwData, u8 enable) { struct wb35_reg *reg = &pHwData->reg; @@ -438,7 +438,7 @@ void hal_set_accept_promiscuous( phw_data_t pHwData, u8 enable) } } -void hal_set_accept_multicast( phw_data_t pHwData, u8 enable ) +void hal_set_accept_multicast( struct hw_data * pHwData, u8 enable ) { struct wb35_reg *reg = &pHwData->reg; @@ -449,7 +449,7 @@ void hal_set_accept_multicast( phw_data_t pHwData, u8 enable ) Wb35Reg_Write( pHwData, 0x0800, reg->M00_MacControl ); } -void hal_set_accept_beacon( phw_data_t pHwData, u8 enable ) +void hal_set_accept_beacon( struct hw_data * pHwData, u8 enable ) { struct wb35_reg *reg = &pHwData->reg; @@ -467,7 +467,7 @@ void hal_set_accept_beacon( phw_data_t pHwData, u8 enable ) } //--------------------------------------------------------------------------------------------------- -void hal_stop( phw_data_t pHwData ) +void hal_stop( struct hw_data * pHwData ) { struct wb35_reg *reg = &pHwData->reg; @@ -481,10 +481,10 @@ void hal_stop( phw_data_t pHwData ) Wb35Reg_Write( pHwData, 0x0400, reg->D00_DmaControl ); } -unsigned char hal_idle(phw_data_t pHwData) +unsigned char hal_idle(struct hw_data * pHwData) { struct wb35_reg *reg = &pHwData->reg; - PWBUSB pWbUsb = &pHwData->WbUsb; + struct wb_usb *pWbUsb = &pHwData->WbUsb; if( !pHwData->SurpriseRemove && ( pWbUsb->DetectCount || reg->EP0vm_state!=VM_STOP ) ) return false; @@ -492,12 +492,12 @@ unsigned char hal_idle(phw_data_t pHwData) return true; } //--------------------------------------------------------------------------------------------------- -void hal_set_phy_type( phw_data_t pHwData, u8 PhyType ) +void hal_set_phy_type( struct hw_data * pHwData, u8 PhyType ) { pHwData->phy_type = PhyType; } -void hal_set_radio_mode( phw_data_t pHwData, unsigned char radio_off) +void hal_set_radio_mode( struct hw_data * pHwData, unsigned char radio_off) { struct wb35_reg *reg = &pHwData->reg; @@ -516,7 +516,7 @@ void hal_set_radio_mode( phw_data_t pHwData, unsigned char radio_off) Wb35Reg_Write( pHwData, 0x0824, reg->M24_MacControl ); } -u8 hal_get_antenna_number( phw_data_t pHwData ) +u8 hal_get_antenna_number( struct hw_data * pHwData ) { struct wb35_reg *reg = &pHwData->reg; @@ -528,7 +528,7 @@ u8 hal_get_antenna_number( phw_data_t pHwData ) //---------------------------------------------------------------------------------------------------- //0 : radio on; 1: radio off -u8 hal_get_hw_radio_off( phw_data_t pHwData ) +u8 hal_get_hw_radio_off( struct hw_data * pHwData ) { struct wb35_reg *reg = &pHwData->reg; @@ -545,14 +545,14 @@ u8 hal_get_hw_radio_off( phw_data_t pHwData ) } } -unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, u32 * pValue ) +unsigned char hal_get_dxx_reg( struct hw_data * pHwData, u16 number, u32 * pValue ) { if( number < 0x1000 ) number += 0x1000; return Wb35Reg_ReadSync( pHwData, number, pValue ); } -unsigned char hal_set_dxx_reg( phw_data_t pHwData, u16 number, u32 value ) +unsigned char hal_set_dxx_reg( struct hw_data * pHwData, u16 number, u32 value ) { unsigned char ret; @@ -562,7 +562,7 @@ unsigned char hal_set_dxx_reg( phw_data_t pHwData, u16 number, u32 value ) return ret; } -void hal_set_rf_power(phw_data_t pHwData, u8 PowerIndex) +void hal_set_rf_power(struct hw_data * pHwData, u8 PowerIndex) { RFSynthesizer_SetPowerIndex( pHwData, PowerIndex ); } diff --git a/drivers/staging/winbond/wbhal_f.h b/drivers/staging/winbond/wbhal_f.h index e805f40f6354..efcaefb6aa59 100644 --- a/drivers/staging/winbond/wbhal_f.h +++ b/drivers/staging/winbond/wbhal_f.h @@ -10,56 +10,56 @@ //==================================================================================== // Function declaration //==================================================================================== -void hal_remove_mapping_key( phw_data_t pHwData, u8 *pmac_addr ); -void hal_remove_default_key( phw_data_t pHwData, u32 index ); -unsigned char hal_set_mapping_key( phw_data_t adapter, u8 *pmac_addr, u8 null_key, u8 wep_on, u8 *ptx_tsc, u8 *prx_tsc, u8 key_type, u8 key_len, u8 *pkey_data ); -unsigned char hal_set_default_key( phw_data_t adapter, u8 index, u8 null_key, u8 wep_on, u8 *ptx_tsc, u8 *prx_tsc, u8 key_type, u8 key_len, u8 *pkey_data ); -void hal_clear_all_default_key( phw_data_t pHwData ); -void hal_clear_all_group_key( phw_data_t pHwData ); -void hal_clear_all_mapping_key( phw_data_t pHwData ); -void hal_clear_all_key( phw_data_t pHwData ); -void hal_get_ethernet_address( phw_data_t pHwData, u8 *current_address ); -void hal_set_ethernet_address( phw_data_t pHwData, u8 *current_address ); -void hal_get_permanent_address( phw_data_t pHwData, u8 *pethernet_address ); +void hal_remove_mapping_key( struct hw_data * pHwData, u8 *pmac_addr ); +void hal_remove_default_key( struct hw_data * pHwData, u32 index ); +unsigned char hal_set_mapping_key( struct hw_data * adapter, u8 *pmac_addr, u8 null_key, u8 wep_on, u8 *ptx_tsc, u8 *prx_tsc, u8 key_type, u8 key_len, u8 *pkey_data ); +unsigned char hal_set_default_key( struct hw_data * adapter, u8 index, u8 null_key, u8 wep_on, u8 *ptx_tsc, u8 *prx_tsc, u8 key_type, u8 key_len, u8 *pkey_data ); +void hal_clear_all_default_key( struct hw_data * pHwData ); +void hal_clear_all_group_key( struct hw_data * pHwData ); +void hal_clear_all_mapping_key( struct hw_data * pHwData ); +void hal_clear_all_key( struct hw_data * pHwData ); +void hal_get_ethernet_address( struct hw_data * pHwData, u8 *current_address ); +void hal_set_ethernet_address( struct hw_data * pHwData, u8 *current_address ); +void hal_get_permanent_address( struct hw_data * pHwData, u8 *pethernet_address ); u8 hal_init_hardware(struct ieee80211_hw *hw); -void hal_set_power_save_mode( phw_data_t pHwData, unsigned char power_save, unsigned char wakeup, unsigned char dtim ); -void hal_get_power_save_mode( phw_data_t pHwData, u8 *pin_pwr_save ); -void hal_set_slot_time( phw_data_t pHwData, u8 type ); +void hal_set_power_save_mode( struct hw_data * pHwData, unsigned char power_save, unsigned char wakeup, unsigned char dtim ); +void hal_get_power_save_mode( struct hw_data * pHwData, u8 *pin_pwr_save ); +void hal_set_slot_time( struct hw_data * pHwData, u8 type ); #define hal_set_atim_window( _A, _ATM ) -void hal_start_bss( phw_data_t pHwData, u8 mac_op_mode ); -void hal_join_request( phw_data_t pHwData, u8 bss_type ); // 0:BSS STA 1:IBSS STA// -void hal_stop_sync_bss( phw_data_t pHwData ); -void hal_resume_sync_bss( phw_data_t pHwData); -void hal_set_aid( phw_data_t pHwData, u16 aid ); -void hal_set_bssid( phw_data_t pHwData, u8 *pbssid ); -void hal_get_bssid( phw_data_t pHwData, u8 *pbssid ); -void hal_set_beacon_period( phw_data_t pHwData, u16 beacon_period ); -void hal_set_listen_interval( phw_data_t pHwData, u16 listen_interval ); -void hal_set_cap_info( phw_data_t pHwData, u16 capability_info ); -void hal_set_ssid( phw_data_t pHwData, u8 *pssid, u8 ssid_len ); -void hal_set_current_channel( phw_data_t pHwData, ChanInfo channel ); -void hal_set_accept_broadcast( phw_data_t pHwData, u8 enable ); -void hal_set_accept_multicast( phw_data_t pHwData, u8 enable ); -void hal_set_accept_beacon( phw_data_t pHwData, u8 enable ); -void hal_stop( phw_data_t pHwData ); -void hal_halt( phw_data_t pHwData, void *ppa_data ); -void hal_start_tx0( phw_data_t pHwData ); -void hal_set_phy_type( phw_data_t pHwData, u8 PhyType ); +void hal_start_bss( struct hw_data * pHwData, u8 mac_op_mode ); +void hal_join_request( struct hw_data * pHwData, u8 bss_type ); // 0:BSS STA 1:IBSS STA// +void hal_stop_sync_bss( struct hw_data * pHwData ); +void hal_resume_sync_bss( struct hw_data * pHwData); +void hal_set_aid( struct hw_data * pHwData, u16 aid ); +void hal_set_bssid( struct hw_data * pHwData, u8 *pbssid ); +void hal_get_bssid( struct hw_data * pHwData, u8 *pbssid ); +void hal_set_beacon_period( struct hw_data * pHwData, u16 beacon_period ); +void hal_set_listen_interval( struct hw_data * pHwData, u16 listen_interval ); +void hal_set_cap_info( struct hw_data * pHwData, u16 capability_info ); +void hal_set_ssid( struct hw_data * pHwData, u8 *pssid, u8 ssid_len ); +void hal_set_current_channel( struct hw_data * pHwData, ChanInfo channel ); +void hal_set_accept_broadcast( struct hw_data * pHwData, u8 enable ); +void hal_set_accept_multicast( struct hw_data * pHwData, u8 enable ); +void hal_set_accept_beacon( struct hw_data * pHwData, u8 enable ); +void hal_stop( struct hw_data * pHwData ); +void hal_halt( struct hw_data * pHwData, void *ppa_data ); +void hal_start_tx0( struct hw_data * pHwData ); +void hal_set_phy_type( struct hw_data * pHwData, u8 PhyType ); #define hal_get_cwmin( _A ) ( (_A)->cwmin ) -void hal_set_cwmax( phw_data_t pHwData, u16 cwin_max ); +void hal_set_cwmax( struct hw_data * pHwData, u16 cwin_max ); #define hal_get_cwmax( _A ) ( (_A)->cwmax ) -void hal_set_rsn_wpa( phw_data_t pHwData, u32 * RSN_IE_Bitmap , u32 * RSN_OUI_type , unsigned char bDesiredAuthMode); -void hal_set_connect_info( phw_data_t pHwData, unsigned char boConnect ); -u8 hal_get_est_sq3( phw_data_t pHwData, u8 Count ); -void hal_set_rf_power( phw_data_t pHwData, u8 PowerIndex ); // 20060621 Modify -void hal_set_radio_mode( phw_data_t pHwData, unsigned char boValue); -void hal_descriptor_indicate( phw_data_t pHwData, PDESCRIPTOR pDes ); -u8 hal_get_antenna_number( phw_data_t pHwData ); -u32 hal_get_bss_pk_cnt( phw_data_t pHwData ); +void hal_set_rsn_wpa( struct hw_data * pHwData, u32 * RSN_IE_Bitmap , u32 * RSN_OUI_type , unsigned char bDesiredAuthMode); +void hal_set_connect_info( struct hw_data * pHwData, unsigned char boConnect ); +u8 hal_get_est_sq3( struct hw_data * pHwData, u8 Count ); +void hal_set_rf_power( struct hw_data * pHwData, u8 PowerIndex ); // 20060621 Modify +void hal_set_radio_mode( struct hw_data * pHwData, unsigned char boValue); +void hal_descriptor_indicate( struct hw_data * pHwData, PDESCRIPTOR pDes ); +u8 hal_get_antenna_number( struct hw_data * pHwData ); +u32 hal_get_bss_pk_cnt( struct hw_data * pHwData ); #define hal_get_region_from_EEPROM( _A ) ( (_A)->reg.EEPROMRegion ) -void hal_set_accept_promiscuous ( phw_data_t pHwData, u8 enable); +void hal_set_accept_promiscuous ( struct hw_data * pHwData, u8 enable); #define hal_get_tx_buffer( _A, _B ) Wb35Tx_get_tx_buffer( _A, _B ) -u8 hal_get_hw_radio_off ( phw_data_t pHwData ); +u8 hal_get_hw_radio_off ( struct hw_data * pHwData ); #define hal_software_set( _A ) (_A->SoftwareSet) #define hal_driver_init_OK( _A ) (_A->IsInitOK) #define hal_rssi_boundary_high( _A ) (_A->RSSI_high) @@ -68,8 +68,8 @@ u8 hal_get_hw_radio_off ( phw_data_t pHwData ); #define PHY_DEBUG( msg, args... ) -unsigned char hal_get_dxx_reg( phw_data_t pHwData, u16 number, u32 * pValue ); -unsigned char hal_set_dxx_reg( phw_data_t pHwData, u16 number, u32 value ); +unsigned char hal_get_dxx_reg( struct hw_data * pHwData, u16 number, u32 * pValue ); +unsigned char hal_set_dxx_reg( struct hw_data * pHwData, u16 number, u32 value ); #define hal_get_time_count( _P ) (_P->time_count/10) // return 100ms count #define hal_detect_error( _P ) (_P->WbUsb.DetectCount) @@ -82,7 +82,7 @@ unsigned char hal_set_dxx_reg( phw_data_t pHwData, u16 number, u32 value ); #define hal_get_clear_interrupt(_A) #define hal_ibss_disconnect(_A) hal_stop_sync_bss(_A) #define hal_join_request_stop(_A) -unsigned char hal_idle( phw_data_t pHwData ); +unsigned char hal_idle( struct hw_data * pHwData ); #define hw_get_cxx_reg( _A, _B, _C ) #define hw_set_cxx_reg( _A, _B, _C ) #define hw_get_dxx_reg( _A, _B, _C ) hal_get_dxx_reg( _A, _B, (u32 *)_C ) diff --git a/drivers/staging/winbond/wbhal_s.h b/drivers/staging/winbond/wbhal_s.h index 276d2b12632f..acfebf05d9d7 100644 --- a/drivers/staging/winbond/wbhal_s.h +++ b/drivers/staging/winbond/wbhal_s.h @@ -2,8 +2,7 @@ #define __WINBOND_WBHAL_S_H #include - -#include "common.h" +#include /* for ETH_ALEN */ //[20040722 WK] #define HAL_LED_SET_MASK 0x001c //20060901 Extend @@ -86,19 +85,6 @@ enum { VM_COMPLETED }; -// Be used for 802.11 mac header -typedef struct _MAC_FRAME_CONTROL { - u8 mac_frame_info; // this is a combination of the protovl version, type and subtype - u8 to_ds:1; - u8 from_ds:1; - u8 more_frag:1; - u8 retry:1; - u8 pwr_mgt:1; - u8 more_data:1; - u8 WEP:1; - u8 order:1; -} MAC_FRAME_CONTROL, *PMAC_FRAME_CONTROL; - //----------------------------------------------------- // Normal Key table format //----------------------------------------------------- @@ -106,28 +92,6 @@ typedef struct _MAC_FRAME_CONTROL { #define MAX_KEY_TABLE 24 // 24 entry for storing key data #define GROUP_KEY_START_INDEX 4 #define MAPPING_KEY_START_INDEX 8 -typedef struct _KEY_TABLE -{ - u32 DW0_Valid:1; - u32 DW0_NullKey:1; - u32 DW0_Security_Mode:2;//0:WEP 40 bit 1:WEP 104 bit 2:TKIP 128 bit 3:CCMP 128 bit - u32 DW0_WEPON:1; - u32 DW0_RESERVED:11; - u32 DW0_Address1:16; - - u32 DW1_Address2; - - u32 DW2_RxSequenceCount1; - - u32 DW3_RxSequenceCount2:16; - u32 DW3_RESERVED:16; - - u32 DW4_TxSequenceCount1; - - u32 DW5_TxSequenceCount2:16; - u32 DW5_RESERVED:16; - -} KEY_TABLE, *PKEY_TABLE; //-------------------------------------------------------- // Descriptor @@ -413,8 +377,8 @@ typedef struct _DESCRIPTOR { // Skip length = 8 DWORD #define MAX_RF_PARAMETER 32 typedef struct _TXVGA_FOR_50 { - u8 ChanNo; - u8 TxVgaValue; + u8 ChanNo; + u8 TxVgaValue; } TXVGA_FOR_50; @@ -427,10 +391,8 @@ typedef struct _TXVGA_FOR_50 { #include "wb35tx_s.h" #include "wb35rx_s.h" - // For Hal using ================================================================== -typedef struct _HW_DATA_T -{ +struct hw_data { // For compatible with 33 u32 revision; u32 BB3c_cal; // The value for Tx calibration comes from EEPROM @@ -452,8 +414,8 @@ typedef struct _HW_DATA_T //=============================================== // Definition for MAC address //=============================================== - u8 PermanentMacAddress[ETH_LENGTH_OF_ADDRESS + 2]; // The Enthernet addr that are stored in EEPROM. + 2 to 8-byte alignment - u8 CurrentMacAddress[ETH_LENGTH_OF_ADDRESS + 2]; // The Enthernet addr that are in used. + 2 to 8-byte alignment + u8 PermanentMacAddress[ETH_ALEN + 2]; // The Enthernet addr that are stored in EEPROM. + 2 to 8-byte alignment + u8 CurrentMacAddress[ETH_ALEN + 2]; // The Enthernet addr that are in used. + 2 to 8-byte alignment //===================================================================== // Definition for 802.11 @@ -502,10 +464,10 @@ typedef struct _HW_DATA_T //======================================================================== // Variable for each module //======================================================================== - WBUSB WbUsb; // Need WbUsb.h + struct wb_usb WbUsb; // Need WbUsb.h struct wb35_reg reg; // Need Wb35Reg.h - WB35TX Wb35Tx; // Need Wb35Tx.h - WB35RX Wb35Rx; // Need Wb35Rx.h + struct wb35_tx Wb35Tx; // Need Wb35Tx.h + struct wb35_rx Wb35Rx; // Need Wb35Rx.h struct timer_list LEDTimer;// For LED @@ -578,35 +540,6 @@ typedef struct _HW_DATA_T // 20060828.1 for avoid AP disconnect u32 NullPacketCount; -} hw_data_t, *phw_data_t; - -// The mapping of Rx and Tx descriptor field -typedef struct _HAL_RATE -{ - // DSSS - u32 RESERVED_0; - u32 NumRate2MS; - u32 NumRate55MS; - u32 NumRate11MS; - - u32 RESERVED_1[4]; - - u32 NumRate1M; - u32 NumRate2ML; - u32 NumRate55ML; - u32 NumRate11ML; - - u32 RESERVED_2[4]; - - // OFDM - u32 NumRate6M; - u32 NumRate9M; - u32 NumRate12M; - u32 NumRate18M; - u32 NumRate24M; - u32 NumRate36M; - u32 NumRate48M; - u32 NumRate54M; -} HAL_RATE, *PHAL_RATE; +}; #endif diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index f716b2e92b65..9c3f9439f35e 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -9,7 +9,7 @@ #include "core.h" #include "mds_f.h" #include "mlmetxrx_f.h" -#include "mto_f.h" +#include "mto.h" #include "wbhal_f.h" #include "wblinux_f.h" @@ -149,19 +149,19 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed) hal_set_current_channel(&priv->sHwData, ch); hal_set_beacon_period(&priv->sHwData, conf->beacon_int); // hal_set_cap_info(&priv->sHwData, ?? ); -// hal_set_ssid(phw_data_t pHwData, u8 * pssid, u8 ssid_len); ?? +// hal_set_ssid(struct hw_data * pHwData, u8 * pssid, u8 ssid_len); ?? hal_set_accept_broadcast(&priv->sHwData, 1); hal_set_accept_promiscuous(&priv->sHwData, 1); hal_set_accept_multicast(&priv->sHwData, 1); hal_set_accept_beacon(&priv->sHwData, 1); hal_set_radio_mode(&priv->sHwData, 0); - //hal_set_antenna_number( phw_data_t pHwData, u8 number ) - //hal_set_rf_power(phw_data_t pHwData, u8 PowerIndex) + //hal_set_antenna_number( struct hw_data * pHwData, u8 number ) + //hal_set_rf_power(struct hw_data * pHwData, u8 PowerIndex) // hal_start_bss(&priv->sHwData, WLAN_BSSTYPE_INFRASTRUCTURE); ?? -//void hal_set_rates(phw_data_t pHwData, u8 * pbss_rates, +//void hal_set_rates(struct hw_data * pHwData, u8 * pbss_rates, // u8 length, unsigned char basic_rate_set) return 0; @@ -199,7 +199,7 @@ static const struct ieee80211_ops wbsoft_ops = { static unsigned char wb35_hw_init(struct ieee80211_hw *hw) { struct wbsoft_priv *priv = hw->priv; - phw_data_t pHwData; + struct hw_data * pHwData; u8 *pMacAddr; u8 *pMacAddr2; u32 InitStep = 0; @@ -277,7 +277,7 @@ static unsigned char wb35_hw_init(struct ieee80211_hw *hw) //get current antenna priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData); #ifdef _PE_STATE_DUMP_ - WBDEBUG(("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo)); + printk("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo); #endif hal_get_hw_radio_off( pHwData ); @@ -312,7 +312,7 @@ error: static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id_table) { - PWBUSB pWbUsb; + struct wb_usb *pWbUsb; struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; u32 ltmp; @@ -366,7 +366,7 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id SET_IEEE80211_DEV(dev, &udev->dev); { - phw_data_t pHwData = &priv->sHwData; + struct hw_data * pHwData = &priv->sHwData; unsigned char dev_addr[MAX_ADDR_LEN]; hal_get_permanent_address(pHwData, dev_addr); SET_IEEE80211_PERM_ADDR(dev, dev_addr); @@ -404,7 +404,7 @@ static void wb35_hw_halt(struct wbsoft_priv *adapter) // Turn off Rx and Tx hardware ability hal_stop( &adapter->sHwData ); #ifdef _PE_USB_INI_DUMP_ - WBDEBUG(("[w35und] Hal_stop O.K.\n")); + printk("[w35und] Hal_stop O.K.\n"); #endif msleep(100);// Waiting Irp completed diff --git a/drivers/staging/winbond/wbusb_s.h b/drivers/staging/winbond/wbusb_s.h index 1de93600d848..0c7e6a383f2d 100644 --- a/drivers/staging/winbond/wbusb_s.h +++ b/drivers/staging/winbond/wbusb_s.h @@ -16,22 +16,10 @@ #include -//--------------------------------------------------------------------------- -// RW_CONTEXT -- -// -// Used to track driver-generated io irps -//--------------------------------------------------------------------------- -typedef struct _RW_CONTEXT -{ - void* pHwData; - struct urb *urb; - void* pCallBackFunctionParameter; -} RW_CONTEXT, *PRW_CONTEXT; - -typedef struct _WBUSB { +struct wb_usb { u32 IsUsb20; struct usb_device *udev; u32 DetectCount; -} WBUSB, *PWBUSB; +}; #endif diff --git a/drivers/staging/wlan-ng/README b/drivers/staging/wlan-ng/README index 9c10dbb000d5..028c299b613e 100644 --- a/drivers/staging/wlan-ng/README +++ b/drivers/staging/wlan-ng/README @@ -4,4 +4,6 @@ TODO: - Lindent cleanups - move to use the in-kernel wireless stack -Please send all patches to Greg Kroah-Hartman +Please send any patches or complaints about this driver to Greg +Kroah-Hartman and don't bother the upstream wireless +kernel developers about it, they want nothing to do with it. diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 9b746654a39c..f3e87173471e 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -56,75 +56,37 @@ #ifndef _HFA384x_H #define _HFA384x_H -/*=============================================================*/ -#define HFA384x_FIRMWARE_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#define HFA384x_FIRMWARE_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) -#define HFA384x_LEVEL_TO_dBm(v) (0x100 + (v) * 100 / 255 - 100) +#include -/*------ Constants --------------------------------------------*/ /*--- Mins & Maxs -----------------------------------*/ -#define HFA384x_CMD_ALLOC_LEN_MIN ((u16)4) -#define HFA384x_CMD_ALLOC_LEN_MAX ((u16)2400) -#define HFA384x_BAP_DATALEN_MAX ((u16)4096) -#define HFA384x_BAP_OFFSET_MAX ((u16)4096) #define HFA384x_PORTID_MAX ((u16)7) #define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX+1)) -#define HFA384x_PDR_LEN_MAX ((u16)512) /* in bytes, from EK */ -#define HFA384x_PDA_RECS_MAX ((u16)200) /* a guess */ -#define HFA384x_PDA_LEN_MAX ((u16)1024) /* in bytes, from EK */ +#define HFA384x_PDR_LEN_MAX ((u16)512) /* in bytes, from EK */ +#define HFA384x_PDA_LEN_MAX ((u16)1024) /* in bytes, from EK */ #define HFA384x_SCANRESULT_MAX ((u16)31) #define HFA384x_HSCANRESULT_MAX ((u16)31) #define HFA384x_CHINFORESULT_MAX ((u16)16) -#define HFA384x_DRVR_FIDSTACKLEN_MAX (10) -#define HFA384x_DRVR_TXBUF_MAX (sizeof(hfa384x_tx_frame_t) + \ - WLAN_DATA_MAXLEN - \ - WLAN_WEP_IV_LEN - \ - WLAN_WEP_ICV_LEN + 2) -#define HFA384x_DRVR_MAGIC (0x4a2d) -#define HFA384x_INFODATA_MAXLEN (sizeof(hfa384x_infodata_t)) -#define HFA384x_INFOFRM_MAXLEN (sizeof(hfa384x_InfFrame_t)) -#define HFA384x_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */ +#define HFA384x_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */ #define HFA384x_RIDDATA_MAXLEN HFA384x_RID_GUESSING_MAXLEN #define HFA384x_USB_RWMEM_MAXLEN 2048 /*--- Support Constants -----------------------------*/ -#define HFA384x_BAP_PROC ((u16)0) -#define HFA384x_BAP_int ((u16)1) #define HFA384x_PORTTYPE_IBSS ((u16)0) #define HFA384x_PORTTYPE_BSS ((u16)1) -#define HFA384x_PORTTYPE_WDS ((u16)2) #define HFA384x_PORTTYPE_PSUEDOIBSS ((u16)3) -#define HFA384x_PORTTYPE_HOSTAP ((u16)6) -#define HFA384x_WEPFLAGS_PRIVINVOKED ((u16)BIT0) -#define HFA384x_WEPFLAGS_EXCLUDE ((u16)BIT1) -#define HFA384x_WEPFLAGS_DISABLE_TXCRYPT ((u16)BIT4) -#define HFA384x_WEPFLAGS_DISABLE_RXCRYPT ((u16)BIT7) -#define HFA384x_WEPFLAGS_DISALLOW_MIXED ((u16)BIT11) -#define HFA384x_WEPFLAGS_IV_intERVAL1 ((u16)0) -#define HFA384x_WEPFLAGS_IV_intERVAL10 ((u16)BIT5) -#define HFA384x_WEPFLAGS_IV_intERVAL50 ((u16)BIT6) -#define HFA384x_WEPFLAGS_IV_intERVAL100 ((u16)(BIT5 | BIT6)) -#define HFA384x_WEPFLAGS_FIRMWARE_WPA ((u16)BIT8) -#define HFA384x_WEPFLAGS_HOST_MIC ((u16)BIT9) -#define HFA384x_ROAMMODE_FWSCAN_FWROAM ((u16)1) -#define HFA384x_ROAMMODE_FWSCAN_HOSTROAM ((u16)2) +#define HFA384x_WEPFLAGS_PRIVINVOKED ((u16)BIT(0)) +#define HFA384x_WEPFLAGS_EXCLUDE ((u16)BIT(1)) +#define HFA384x_WEPFLAGS_DISABLE_TXCRYPT ((u16)BIT(4)) +#define HFA384x_WEPFLAGS_DISABLE_RXCRYPT ((u16)BIT(7)) #define HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM ((u16)3) #define HFA384x_PORTSTATUS_DISABLED ((u16)1) -#define HFA384x_PORTSTATUS_INITSRCH ((u16)2) -#define HFA384x_PORTSTATUS_CONN_IBSS ((u16)3) -#define HFA384x_PORTSTATUS_CONN_ESS ((u16)4) -#define HFA384x_PORTSTATUS_OOR_ESS ((u16)5) -#define HFA384x_PORTSTATUS_CONN_WDS ((u16)6) -#define HFA384x_PORTSTATUS_HOSTAP ((u16)8) #define HFA384x_RATEBIT_1 ((u16)1) #define HFA384x_RATEBIT_2 ((u16)2) #define HFA384x_RATEBIT_5dot5 ((u16)4) #define HFA384x_RATEBIT_11 ((u16)8) -/*--- Just some symbolic names for legibility -------*/ -#define HFA384x_TXCMD_NORECL ((u16)0) -#define HFA384x_TXCMD_RECL ((u16)1) - /*--- MAC Internal memory constants and macros ------*/ /* masks and macros used to manipulate MAC internal memory addresses. */ /* MAC internal memory addresses are 23 bit quantities. The MAC uses @@ -139,59 +101,28 @@ * macros below help handle some of this. */ -/* Handy constant */ -#define HFA384x_ADDR_AUX_OFF_MAX ((u16)0x007f) - /* Mask bits for discarding unwanted pieces in a flat address */ #define HFA384x_ADDR_FLAT_AUX_PAGE_MASK (0x007fff80) #define HFA384x_ADDR_FLAT_AUX_OFF_MASK (0x0000007f) #define HFA384x_ADDR_FLAT_CMD_PAGE_MASK (0xffff0000) #define HFA384x_ADDR_FLAT_CMD_OFF_MASK (0x0000ffff) -/* Mask bits for discarding unwanted pieces in AUX format 16-bit address parts */ +/* Mask bits for discarding unwanted pieces in AUX format + 16-bit address parts */ #define HFA384x_ADDR_AUX_PAGE_MASK (0xffff) #define HFA384x_ADDR_AUX_OFF_MASK (0x007f) -/* Mask bits for discarding unwanted pieces in CMD format 16-bit address parts */ -#define HFA384x_ADDR_CMD_PAGE_MASK (0x007f) -#define HFA384x_ADDR_CMD_OFF_MASK (0xffff) - /* Make a 32-bit flat address from AUX format 16-bit page and offset */ -#define HFA384x_ADDR_AUX_MKFLAT(p,o) \ - (((u32)(((u16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) <<7) | \ +#define HFA384x_ADDR_AUX_MKFLAT(p, o) \ + (((u32)(((u16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) << 7) | \ ((u32)(((u16)(o))&HFA384x_ADDR_AUX_OFF_MASK)) -/* Make a 32-bit flat address from CMD format 16-bit page and offset */ -#define HFA384x_ADDR_CMD_MKFLAT(p,o) \ - (((u32)(((u16)(p))&HFA384x_ADDR_CMD_PAGE_MASK)) <<16) | \ - ((u32)(((u16)(o))&HFA384x_ADDR_CMD_OFF_MASK)) - -/* Make AUX format offset and page from a 32-bit flat address */ -#define HFA384x_ADDR_AUX_MKPAGE(f) \ - ((u16)((((u32)(f))&HFA384x_ADDR_FLAT_AUX_PAGE_MASK)>>7)) -#define HFA384x_ADDR_AUX_MKOFF(f) \ - ((u16)(((u32)(f))&HFA384x_ADDR_FLAT_AUX_OFF_MASK)) - /* Make CMD format offset and page from a 32-bit flat address */ #define HFA384x_ADDR_CMD_MKPAGE(f) \ ((u16)((((u32)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16)) #define HFA384x_ADDR_CMD_MKOFF(f) \ ((u16)(((u32)(f))&HFA384x_ADDR_FLAT_CMD_OFF_MASK)) -/*--- Aux register masks/tests ----------------------*/ -/* Some of the upper bits of the AUX offset register are used to */ -/* select address space. */ -#define HFA384x_AUX_CTL_EXTDS (0x00) -#define HFA384x_AUX_CTL_NV (0x01) -#define HFA384x_AUX_CTL_PHY (0x02) -#define HFA384x_AUX_CTL_ICSRAM (0x03) - -/* Make AUX register offset and page values from a flat address */ -#define HFA384x_AUX_MKOFF(f, c) \ - (HFA384x_ADDR_AUX_MKOFF(f) | (((u16)(c))<<12)) -#define HFA384x_AUX_MKPAGE(f) HFA384x_ADDR_AUX_MKPAGE(f) - - /*--- Controller Memory addresses -------------------*/ #define HFA3842_PDA_BASE (0x007f0000UL) #define HFA3841_PDA_BASE (0x003f0000UL) @@ -201,124 +132,25 @@ #define HFA384x_DLSTATE_DISABLED 0 #define HFA384x_DLSTATE_RAMENABLED 1 #define HFA384x_DLSTATE_FLASHENABLED 2 -#define HFA384x_DLSTATE_FLASHWRITTEN 3 -#define HFA384x_DLSTATE_FLASHWRITEPENDING 4 -#define HFA384x_DLSTATE_GENESIS 5 - -#define HFA384x_CMD_OFF (0x00) -#define HFA384x_PARAM0_OFF (0x04) -#define HFA384x_PARAM1_OFF (0x08) -#define HFA384x_PARAM2_OFF (0x0c) -#define HFA384x_STATUS_OFF (0x10) -#define HFA384x_RESP0_OFF (0x14) -#define HFA384x_RESP1_OFF (0x18) -#define HFA384x_RESP2_OFF (0x1c) -#define HFA384x_INFOFID_OFF (0x20) -#define HFA384x_RXFID_OFF (0x40) -#define HFA384x_ALLOCFID_OFF (0x44) -#define HFA384x_TXCOMPLFID_OFF (0x48) -#define HFA384x_SELECT0_OFF (0x30) -#define HFA384x_OFFSET0_OFF (0x38) -#define HFA384x_DATA0_OFF (0x6c) -#define HFA384x_SELECT1_OFF (0x34) -#define HFA384x_OFFSET1_OFF (0x3c) -#define HFA384x_DATA1_OFF (0x70) -#define HFA384x_EVSTAT_OFF (0x60) -#define HFA384x_intEN_OFF (0x64) -#define HFA384x_EVACK_OFF (0x68) -#define HFA384x_CONTROL_OFF (0x28) -#define HFA384x_SWSUPPORT0_OFF (0x50) -#define HFA384x_SWSUPPORT1_OFF (0x54) -#define HFA384x_SWSUPPORT2_OFF (0x58) -#define HFA384x_AUXPAGE_OFF (0x74) -#define HFA384x_AUXOFFSET_OFF (0x78) -#define HFA384x_AUXDATA_OFF (0x7c) -#define HFA384x_PCICOR_OFF (0x4c) -#define HFA384x_PCIHCR_OFF (0x5c) -#define HFA384x_PCI_M0_ADDRH_OFF (0x80) -#define HFA384x_PCI_M0_ADDRL_OFF (0x84) -#define HFA384x_PCI_M0_LEN_OFF (0x88) -#define HFA384x_PCI_M0_CTL_OFF (0x8c) -#define HFA384x_PCI_STATUS_OFF (0x98) -#define HFA384x_PCI_M1_ADDRH_OFF (0xa0) -#define HFA384x_PCI_M1_ADDRL_OFF (0xa4) -#define HFA384x_PCI_M1_LEN_OFF (0xa8) -#define HFA384x_PCI_M1_CTL_OFF (0xac) /*--- Register Field Masks --------------------------*/ -#define HFA384x_CMD_BUSY ((u16)BIT15) -#define HFA384x_CMD_AINFO ((u16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) -#define HFA384x_CMD_MACPORT ((u16)(BIT10 | BIT9 | BIT8)) -#define HFA384x_CMD_RECL ((u16)BIT8) -#define HFA384x_CMD_WRITE ((u16)BIT8) -#define HFA384x_CMD_PROGMODE ((u16)(BIT9 | BIT8)) -#define HFA384x_CMD_CMDCODE ((u16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) - -#define HFA384x_STATUS_RESULT ((u16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) -#define HFA384x_STATUS_CMDCODE ((u16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) - -#define HFA384x_OFFSET_BUSY ((u16)BIT15) -#define HFA384x_OFFSET_ERR ((u16)BIT14) -#define HFA384x_OFFSET_DATAOFF ((u16)(BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1)) - -#define HFA384x_EVSTAT_TICK ((u16)BIT15) -#define HFA384x_EVSTAT_WTERR ((u16)BIT14) -#define HFA384x_EVSTAT_INFDROP ((u16)BIT13) -#define HFA384x_EVSTAT_INFO ((u16)BIT7) -#define HFA384x_EVSTAT_DTIM ((u16)BIT5) -#define HFA384x_EVSTAT_CMD ((u16)BIT4) -#define HFA384x_EVSTAT_ALLOC ((u16)BIT3) -#define HFA384x_EVSTAT_TXEXC ((u16)BIT2) -#define HFA384x_EVSTAT_TX ((u16)BIT1) -#define HFA384x_EVSTAT_RX ((u16)BIT0) - -#define HFA384x_int_BAP_OP (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC) - -#define HFA384x_int_NORMAL (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC|HFA384x_EVSTAT_INFDROP|HFA384x_EVSTAT_ALLOC|HFA384x_EVSTAT_DTIM) - -#define HFA384x_intEN_TICK ((u16)BIT15) -#define HFA384x_intEN_WTERR ((u16)BIT14) -#define HFA384x_intEN_INFDROP ((u16)BIT13) -#define HFA384x_intEN_INFO ((u16)BIT7) -#define HFA384x_intEN_DTIM ((u16)BIT5) -#define HFA384x_intEN_CMD ((u16)BIT4) -#define HFA384x_intEN_ALLOC ((u16)BIT3) -#define HFA384x_intEN_TXEXC ((u16)BIT2) -#define HFA384x_intEN_TX ((u16)BIT1) -#define HFA384x_intEN_RX ((u16)BIT0) - -#define HFA384x_EVACK_TICK ((u16)BIT15) -#define HFA384x_EVACK_WTERR ((u16)BIT14) -#define HFA384x_EVACK_INFDROP ((u16)BIT13) -#define HFA384x_EVACK_INFO ((u16)BIT7) -#define HFA384x_EVACK_DTIM ((u16)BIT5) -#define HFA384x_EVACK_CMD ((u16)BIT4) -#define HFA384x_EVACK_ALLOC ((u16)BIT3) -#define HFA384x_EVACK_TXEXC ((u16)BIT2) -#define HFA384x_EVACK_TX ((u16)BIT1) -#define HFA384x_EVACK_RX ((u16)BIT0) - -#define HFA384x_CONTROL_AUXEN ((u16)(BIT15 | BIT14)) +#define HFA384x_CMD_AINFO ((u16)(BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8))) +#define HFA384x_CMD_MACPORT ((u16)(BIT(10) | BIT(9) | BIT(8))) +#define HFA384x_CMD_PROGMODE ((u16)(BIT(9) | BIT(8))) +#define HFA384x_CMD_CMDCODE ((u16)(BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0))) +#define HFA384x_STATUS_RESULT ((u16)(BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8))) /*--- Command Code Constants --------------------------*/ /*--- Controller Commands --------------------------*/ #define HFA384x_CMDCODE_INIT ((u16)0x00) #define HFA384x_CMDCODE_ENABLE ((u16)0x01) #define HFA384x_CMDCODE_DISABLE ((u16)0x02) -#define HFA384x_CMDCODE_DIAG ((u16)0x03) - -/*--- Buffer Mgmt Commands --------------------------*/ -#define HFA384x_CMDCODE_ALLOC ((u16)0x0A) -#define HFA384x_CMDCODE_TX ((u16)0x0B) -#define HFA384x_CMDCODE_CLRPRST ((u16)0x12) /*--- Regulate Commands --------------------------*/ -#define HFA384x_CMDCODE_NOTIFY ((u16)0x10) #define HFA384x_CMDCODE_INQ ((u16)0x11) /*--- Configure Commands --------------------------*/ -#define HFA384x_CMDCODE_ACCESS ((u16)0x21) #define HFA384x_CMDCODE_DOWNLD ((u16)0x22) /*--- Debugging Commands -----------------------------*/ @@ -327,9 +159,6 @@ #define HFA384x_MONITOR_DISABLE ((u16)(0x0f)) /*--- Result Codes --------------------------*/ -#define HFA384x_SUCCESS ((u16)(0x00)) -#define HFA384x_CARD_FAIL ((u16)(0x01)) -#define HFA384x_NO_BUFF ((u16)(0x05)) #define HFA384x_CMD_ERR ((u16)(0x7F)) /*--- Programming Modes -------------------------- @@ -343,16 +172,6 @@ #define HFA384x_PROGMODE_NV ((u16)0x02) #define HFA384x_PROGMODE_NVWRITE ((u16)0x03) -/*--- AUX register enable --------------------------*/ -#define HFA384x_AUXPW0 ((u16)0xfe01) -#define HFA384x_AUXPW1 ((u16)0xdc23) -#define HFA384x_AUXPW2 ((u16)0xba45) - -#define HFA384x_CONTROL_AUX_ISDISABLED ((u16)0x0000) -#define HFA384x_CONTROL_AUX_ISENABLED ((u16)0xc000) -#define HFA384x_CONTROL_AUX_DOENABLE ((u16)0x8000) -#define HFA384x_CONTROL_AUX_DODISABLE ((u16)0x4000) - /*--- Record ID Constants --------------------------*/ /*-------------------------------------------------------------------- Configuration RIDs: Network Parameters, Static Configuration Entities @@ -362,133 +181,25 @@ Configuration RIDs: Network Parameters, Static Configuration Entities #define HFA384x_RID_CNFDESIREDSSID ((u16)0xFC02) #define HFA384x_RID_CNFOWNCHANNEL ((u16)0xFC03) #define HFA384x_RID_CNFOWNSSID ((u16)0xFC04) -#define HFA384x_RID_CNFOWNATIMWIN ((u16)0xFC05) -#define HFA384x_RID_CNFSYSSCALE ((u16)0xFC06) #define HFA384x_RID_CNFMAXDATALEN ((u16)0xFC07) -#define HFA384x_RID_CNFWDSADDR ((u16)0xFC08) -#define HFA384x_RID_CNFPMENABLED ((u16)0xFC09) -#define HFA384x_RID_CNFPMEPS ((u16)0xFC0A) -#define HFA384x_RID_CNFMULTICASTRX ((u16)0xFC0B) -#define HFA384x_RID_CNFMAXSLEEPDUR ((u16)0xFC0C) -#define HFA384x_RID_CNFPMHOLDDUR ((u16)0xFC0D) -#define HFA384x_RID_CNFOWNNAME ((u16)0xFC0E) -#define HFA384x_RID_CNFOWNDTIMPER ((u16)0xFC10) -#define HFA384x_RID_CNFWDSADDR1 ((u16)0xFC11) -#define HFA384x_RID_CNFWDSADDR2 ((u16)0xFC12) -#define HFA384x_RID_CNFWDSADDR3 ((u16)0xFC13) -#define HFA384x_RID_CNFWDSADDR4 ((u16)0xFC14) -#define HFA384x_RID_CNFWDSADDR5 ((u16)0xFC15) -#define HFA384x_RID_CNFWDSADDR6 ((u16)0xFC16) -#define HFA384x_RID_CNFMCASTPMBUFF ((u16)0xFC17) /*-------------------------------------------------------------------- Configuration RID lengths: Network Params, Static Config Entities This is the length of JUST the DATA part of the RID (does not include the len or code fields) --------------------------------------------------------------------*/ -/* TODO: fill in the rest of these */ -#define HFA384x_RID_CNFPORTTYPE_LEN ((u16)2) #define HFA384x_RID_CNFOWNMACADDR_LEN ((u16)6) #define HFA384x_RID_CNFDESIREDSSID_LEN ((u16)34) -#define HFA384x_RID_CNFOWNCHANNEL_LEN ((u16)2) #define HFA384x_RID_CNFOWNSSID_LEN ((u16)34) -#define HFA384x_RID_CNFOWNATIMWIN_LEN ((u16)2) -#define HFA384x_RID_CNFSYSSCALE_LEN ((u16)0) -#define HFA384x_RID_CNFMAXDATALEN_LEN ((u16)0) -#define HFA384x_RID_CNFWDSADDR_LEN ((u16)6) -#define HFA384x_RID_CNFPMENABLED_LEN ((u16)0) -#define HFA384x_RID_CNFPMEPS_LEN ((u16)0) -#define HFA384x_RID_CNFMULTICASTRX_LEN ((u16)0) -#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((u16)0) -#define HFA384x_RID_CNFPMHOLDDUR_LEN ((u16)0) -#define HFA384x_RID_CNFOWNNAME_LEN ((u16)34) -#define HFA384x_RID_CNFOWNDTIMPER_LEN ((u16)0) -#define HFA384x_RID_CNFWDSADDR1_LEN ((u16)6) -#define HFA384x_RID_CNFWDSADDR2_LEN ((u16)6) -#define HFA384x_RID_CNFWDSADDR3_LEN ((u16)6) -#define HFA384x_RID_CNFWDSADDR4_LEN ((u16)6) -#define HFA384x_RID_CNFWDSADDR5_LEN ((u16)6) -#define HFA384x_RID_CNFWDSADDR6_LEN ((u16)6) -#define HFA384x_RID_CNFMCASTPMBUFF_LEN ((u16)0) -#define HFA384x_RID_CNFAUTHENTICATION_LEN ((u16)sizeof(u16)) -#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((u16)0) /*-------------------------------------------------------------------- Configuration RIDs: Network Parameters, Dynamic Configuration Entities --------------------------------------------------------------------*/ -#define HFA384x_RID_GROUPADDR ((u16)0xFC80) #define HFA384x_RID_CREATEIBSS ((u16)0xFC81) #define HFA384x_RID_FRAGTHRESH ((u16)0xFC82) #define HFA384x_RID_RTSTHRESH ((u16)0xFC83) #define HFA384x_RID_TXRATECNTL ((u16)0xFC84) #define HFA384x_RID_PROMISCMODE ((u16)0xFC85) -#define HFA384x_RID_FRAGTHRESH0 ((u16)0xFC90) -#define HFA384x_RID_FRAGTHRESH1 ((u16)0xFC91) -#define HFA384x_RID_FRAGTHRESH2 ((u16)0xFC92) -#define HFA384x_RID_FRAGTHRESH3 ((u16)0xFC93) -#define HFA384x_RID_FRAGTHRESH4 ((u16)0xFC94) -#define HFA384x_RID_FRAGTHRESH5 ((u16)0xFC95) -#define HFA384x_RID_FRAGTHRESH6 ((u16)0xFC96) -#define HFA384x_RID_RTSTHRESH0 ((u16)0xFC97) -#define HFA384x_RID_RTSTHRESH1 ((u16)0xFC98) -#define HFA384x_RID_RTSTHRESH2 ((u16)0xFC99) -#define HFA384x_RID_RTSTHRESH3 ((u16)0xFC9A) -#define HFA384x_RID_RTSTHRESH4 ((u16)0xFC9B) -#define HFA384x_RID_RTSTHRESH5 ((u16)0xFC9C) -#define HFA384x_RID_RTSTHRESH6 ((u16)0xFC9D) -#define HFA384x_RID_TXRATECNTL0 ((u16)0xFC9E) -#define HFA384x_RID_TXRATECNTL1 ((u16)0xFC9F) -#define HFA384x_RID_TXRATECNTL2 ((u16)0xFCA0) -#define HFA384x_RID_TXRATECNTL3 ((u16)0xFCA1) -#define HFA384x_RID_TXRATECNTL4 ((u16)0xFCA2) -#define HFA384x_RID_TXRATECNTL5 ((u16)0xFCA3) -#define HFA384x_RID_TXRATECNTL6 ((u16)0xFCA4) - -/*-------------------------------------------------------------------- -Configuration RID Lengths: Network Param, Dynamic Config Entities - This is the length of JUST the DATA part of the RID (does not - include the len or code fields) ---------------------------------------------------------------------*/ -/* TODO: fill in the rest of these */ -#define HFA384x_RID_GROUPADDR_LEN ((u16)16 * WLAN_ADDR_LEN) -#define HFA384x_RID_CREATEIBSS_LEN ((u16)0) -#define HFA384x_RID_FRAGTHRESH_LEN ((u16)0) -#define HFA384x_RID_RTSTHRESH_LEN ((u16)0) -#define HFA384x_RID_TXRATECNTL_LEN ((u16)4) -#define HFA384x_RID_PROMISCMODE_LEN ((u16)2) -#define HFA384x_RID_FRAGTHRESH0_LEN ((u16)0) -#define HFA384x_RID_FRAGTHRESH1_LEN ((u16)0) -#define HFA384x_RID_FRAGTHRESH2_LEN ((u16)0) -#define HFA384x_RID_FRAGTHRESH3_LEN ((u16)0) -#define HFA384x_RID_FRAGTHRESH4_LEN ((u16)0) -#define HFA384x_RID_FRAGTHRESH5_LEN ((u16)0) -#define HFA384x_RID_FRAGTHRESH6_LEN ((u16)0) -#define HFA384x_RID_RTSTHRESH0_LEN ((u16)0) -#define HFA384x_RID_RTSTHRESH1_LEN ((u16)0) -#define HFA384x_RID_RTSTHRESH2_LEN ((u16)0) -#define HFA384x_RID_RTSTHRESH3_LEN ((u16)0) -#define HFA384x_RID_RTSTHRESH4_LEN ((u16)0) -#define HFA384x_RID_RTSTHRESH5_LEN ((u16)0) -#define HFA384x_RID_RTSTHRESH6_LEN ((u16)0) -#define HFA384x_RID_TXRATECNTL0_LEN ((u16)0) -#define HFA384x_RID_TXRATECNTL1_LEN ((u16)0) -#define HFA384x_RID_TXRATECNTL2_LEN ((u16)0) -#define HFA384x_RID_TXRATECNTL3_LEN ((u16)0) -#define HFA384x_RID_TXRATECNTL4_LEN ((u16)0) -#define HFA384x_RID_TXRATECNTL5_LEN ((u16)0) -#define HFA384x_RID_TXRATECNTL6_LEN ((u16)0) - -/*-------------------------------------------------------------------- -Configuration RIDs: Behavior Parameters ---------------------------------------------------------------------*/ -#define HFA384x_RID_ITICKTIME ((u16)0xFCE0) - -/*-------------------------------------------------------------------- -Configuration RID Lengths: Behavior Parameters - This is the length of JUST the DATA part of the RID (does not - include the len or code fields) ---------------------------------------------------------------------*/ -#define HFA384x_RID_ITICKTIME_LEN ((u16)2) /*---------------------------------------------------------------------- Information RIDs: NIC Information @@ -502,41 +213,17 @@ Information RIDs: NIC Information #define HFA384x_RID_NICIDENTITY ((u16)0xFD0B) #define HFA384x_RID_MFISUPRANGE ((u16)0xFD0C) #define HFA384x_RID_CFISUPRANGE ((u16)0xFD0D) -#define HFA384x_RID_CHANNELLIST ((u16)0xFD10) -#define HFA384x_RID_REGULATORYDOMAINS ((u16)0xFD11) -#define HFA384x_RID_TEMPTYPE ((u16)0xFD12) -#define HFA384x_RID_CIS ((u16)0xFD13) #define HFA384x_RID_STAIDENTITY ((u16)0xFD20) #define HFA384x_RID_STASUPRANGE ((u16)0xFD21) #define HFA384x_RID_STA_MFIACTRANGES ((u16)0xFD22) #define HFA384x_RID_STA_CFIACTRANGES ((u16)0xFD23) -#define HFA384x_RID_BUILDSEQ ((u16)0xFFFE) -#define HFA384x_RID_FWID ((u16)0xFFFF) /*---------------------------------------------------------------------- Information RID Lengths: NIC Information This is the length of JUST the DATA part of the RID (does not include the len or code fields) --------------------------------------------------------------------*/ -#define HFA384x_RID_MAXLOADTIME_LEN ((u16)0) -#define HFA384x_RID_DOWNLOADBUFFER_LEN ((u16)sizeof(hfa384x_downloadbuffer_t)) -#define HFA384x_RID_PRIIDENTITY_LEN ((u16)8) -#define HFA384x_RID_PRISUPRANGE_LEN ((u16)10) -#define HFA384x_RID_CFIACTRANGES_LEN ((u16)10) #define HFA384x_RID_NICSERIALNUMBER_LEN ((u16)12) -#define HFA384x_RID_NICIDENTITY_LEN ((u16)8) -#define HFA384x_RID_MFISUPRANGE_LEN ((u16)10) -#define HFA384x_RID_CFISUPRANGE_LEN ((u16)10) -#define HFA384x_RID_CHANNELLIST_LEN ((u16)0) -#define HFA384x_RID_REGULATORYDOMAINS_LEN ((u16)12) -#define HFA384x_RID_TEMPTYPE_LEN ((u16)0) -#define HFA384x_RID_CIS_LEN ((u16)480) -#define HFA384x_RID_STAIDENTITY_LEN ((u16)8) -#define HFA384x_RID_STASUPRANGE_LEN ((u16)10) -#define HFA384x_RID_MFIACTRANGES_LEN ((u16)10) -#define HFA384x_RID_CFIACTRANGES2_LEN ((u16)10) -#define HFA384x_RID_BUILDSEQ_LEN ((u16)sizeof(hfa384x_BuildSeq_t)) -#define HFA384x_RID_FWID_LEN ((u16)sizeof(hfa384x_FWID_t)) /*-------------------------------------------------------------------- Information RIDs: MAC Information @@ -544,87 +231,25 @@ Information RIDs: MAC Information #define HFA384x_RID_PORTSTATUS ((u16)0xFD40) #define HFA384x_RID_CURRENTSSID ((u16)0xFD41) #define HFA384x_RID_CURRENTBSSID ((u16)0xFD42) -#define HFA384x_RID_COMMSQUALITY ((u16)0xFD43) #define HFA384x_RID_CURRENTTXRATE ((u16)0xFD44) -#define HFA384x_RID_CURRENTBCNint ((u16)0xFD45) -#define HFA384x_RID_CURRENTSCALETHRESH ((u16)0xFD46) -#define HFA384x_RID_PROTOCOLRSPTIME ((u16)0xFD47) #define HFA384x_RID_SHORTRETRYLIMIT ((u16)0xFD48) #define HFA384x_RID_LONGRETRYLIMIT ((u16)0xFD49) #define HFA384x_RID_MAXTXLIFETIME ((u16)0xFD4A) -#define HFA384x_RID_MAXRXLIFETIME ((u16)0xFD4B) -#define HFA384x_RID_CFPOLLABLE ((u16)0xFD4C) -#define HFA384x_RID_AUTHALGORITHMS ((u16)0xFD4D) #define HFA384x_RID_PRIVACYOPTIMP ((u16)0xFD4F) #define HFA384x_RID_DBMCOMMSQUALITY ((u16)0xFD51) -#define HFA384x_RID_CURRENTTXRATE1 ((u16)0xFD80) -#define HFA384x_RID_CURRENTTXRATE2 ((u16)0xFD81) -#define HFA384x_RID_CURRENTTXRATE3 ((u16)0xFD82) -#define HFA384x_RID_CURRENTTXRATE4 ((u16)0xFD83) -#define HFA384x_RID_CURRENTTXRATE5 ((u16)0xFD84) -#define HFA384x_RID_CURRENTTXRATE6 ((u16)0xFD85) -#define HFA384x_RID_OWNMACADDRESS ((u16)0xFD86) -// #define HFA384x_RID_PCFINFO ((u16)0xFD87) -#define HFA384x_RID_SCANRESULTS ((u16)0xFD88) // NEW -#define HFA384x_RID_HOSTSCANRESULTS ((u16)0xFD89) // NEW -#define HFA384x_RID_AUTHENTICATIONUSED ((u16)0xFD8A) // NEW -#define HFA384x_RID_ASSOCIATEFAILURE ((u16)0xFD8D) // 1.8.0 /*-------------------------------------------------------------------- Information RID Lengths: MAC Information This is the length of JUST the DATA part of the RID (does not include the len or code fields) --------------------------------------------------------------------*/ -#define HFA384x_RID_PORTSTATUS_LEN ((u16)0) -#define HFA384x_RID_CURRENTSSID_LEN ((u16)34) -#define HFA384x_RID_CURRENTBSSID_LEN ((u16)WLAN_BSSID_LEN) -#define HFA384x_RID_COMMSQUALITY_LEN ((u16)sizeof(hfa384x_commsquality_t)) #define HFA384x_RID_DBMCOMMSQUALITY_LEN ((u16)sizeof(hfa384x_dbmcommsquality_t)) -#define HFA384x_RID_CURRENTTXRATE_LEN ((u16)0) -#define HFA384x_RID_CURRENTBCNint_LEN ((u16)0) -#define HFA384x_RID_STACURSCALETHRESH_LEN ((u16)12) -#define HFA384x_RID_APCURSCALETHRESH_LEN ((u16)6) -#define HFA384x_RID_PROTOCOLRSPTIME_LEN ((u16)0) -#define HFA384x_RID_SHORTRETRYLIMIT_LEN ((u16)0) -#define HFA384x_RID_LONGRETRYLIMIT_LEN ((u16)0) -#define HFA384x_RID_MAXTXLIFETIME_LEN ((u16)0) -#define HFA384x_RID_MAXRXLIFETIME_LEN ((u16)0) -#define HFA384x_RID_CFPOLLABLE_LEN ((u16)0) -#define HFA384x_RID_AUTHALGORITHMS_LEN ((u16)4) -#define HFA384x_RID_PRIVACYOPTIMP_LEN ((u16)0) -#define HFA384x_RID_CURRENTTXRATE1_LEN ((u16)0) -#define HFA384x_RID_CURRENTTXRATE2_LEN ((u16)0) -#define HFA384x_RID_CURRENTTXRATE3_LEN ((u16)0) -#define HFA384x_RID_CURRENTTXRATE4_LEN ((u16)0) -#define HFA384x_RID_CURRENTTXRATE5_LEN ((u16)0) -#define HFA384x_RID_CURRENTTXRATE6_LEN ((u16)0) -#define HFA384x_RID_OWNMACADDRESS_LEN ((u16)6) -#define HFA384x_RID_PCFINFO_LEN ((u16)6) -#define HFA384x_RID_CNFAPPCFINFO_LEN ((u16)sizeof(hfa384x_PCFInfo_data_t)) -#define HFA384x_RID_SCANREQUEST_LEN ((u16)sizeof(hfa384x_ScanRequest_data_t)) #define HFA384x_RID_JOINREQUEST_LEN ((u16)sizeof(hfa384x_JoinRequest_data_t)) -#define HFA384x_RID_AUTHENTICATESTA_LEN ((u16)sizeof(hfa384x_authenticateStation_data_t)) -#define HFA384x_RID_CHANNELINFOREQUEST_LEN ((u16)sizeof(hfa384x_ChannelInfoRequest_data_t)) + /*-------------------------------------------------------------------- Information RIDs: Modem Information --------------------------------------------------------------------*/ -#define HFA384x_RID_PHYTYPE ((u16)0xFDC0) #define HFA384x_RID_CURRENTCHANNEL ((u16)0xFDC1) -#define HFA384x_RID_CURRENTPOWERSTATE ((u16)0xFDC2) -#define HFA384x_RID_CCAMODE ((u16)0xFDC3) -#define HFA384x_RID_SUPPORTEDDATARATES ((u16)0xFDC6) -#define HFA384x_RID_LFOSTATUS ((u16)0xFDC7) // 1.7.1 - -/*-------------------------------------------------------------------- -Information RID Lengths: Modem Information - This is the length of JUST the DATA part of the RID (does not - include the len or code fields) ---------------------------------------------------------------------*/ -#define HFA384x_RID_PHYTYPE_LEN ((u16)0) -#define HFA384x_RID_CURRENTCHANNEL_LEN ((u16)0) -#define HFA384x_RID_CURRENTPOWERSTATE_LEN ((u16)0) -#define HFA384x_RID_CCAMODE_LEN ((u16)0) -#define HFA384x_RID_SUPPORTEDDATARATES_LEN ((u16)10) /*-------------------------------------------------------------------- API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) @@ -635,57 +260,22 @@ API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) #define HFA384x_RID_CNFWEPDEFAULTKEY2 ((u16)0xFC26) #define HFA384x_RID_CNFWEPDEFAULTKEY3 ((u16)0xFC27) #define HFA384x_RID_CNFWEPFLAGS ((u16)0xFC28) -#define HFA384x_RID_CNFWEPKEYMAPTABLE ((u16)0xFC29) #define HFA384x_RID_CNFAUTHENTICATION ((u16)0xFC2A) -#define HFA384x_RID_CNFMAXASSOCSTATIONS ((u16)0xFC2B) -#define HFA384x_RID_CNFTXCONTROL ((u16)0xFC2C) #define HFA384x_RID_CNFROAMINGMODE ((u16)0xFC2D) -#define HFA384x_RID_CNFHOSTAUTHASSOC ((u16)0xFC2E) -#define HFA384x_RID_CNFRCVCRCERROR ((u16)0xFC30) -// #define HFA384x_RID_CNFMMLIFE ((u16)0xFC31) -#define HFA384x_RID_CNFALTRETRYCNT ((u16)0xFC32) #define HFA384x_RID_CNFAPBCNint ((u16)0xFC33) -#define HFA384x_RID_CNFAPPCFINFO ((u16)0xFC34) -#define HFA384x_RID_CNFSTAPCFINFO ((u16)0xFC35) -#define HFA384x_RID_CNFPRIORITYQUSAGE ((u16)0xFC37) -#define HFA384x_RID_CNFTIMCTRL ((u16)0xFC40) -#define HFA384x_RID_CNFTHIRTY2TALLY ((u16)0xFC42) -#define HFA384x_RID_CNFENHSECURITY ((u16)0xFC43) -#define HFA384x_RID_CNFDBMADJUST ((u16)0xFC46) // NEW -#define HFA384x_RID_CNFWPADATA ((u16)0xFC48) // 1.7.0 -#define HFA384x_RID_CNFPROPOGATIONDELAY ((u16)0xFC49) // 1.7.6 -#define HFA384x_RID_CNFSHORTPREAMBLE ((u16)0xFCB0) -#define HFA384x_RID_CNFEXCLONGPREAMBLE ((u16)0xFCB1) -#define HFA384x_RID_CNFAUTHRSPTIMEOUT ((u16)0xFCB2) +#define HFA384x_RID_CNFDBMADJUST ((u16)0xFC46) +#define HFA384x_RID_CNFWPADATA ((u16)0xFC48) #define HFA384x_RID_CNFBASICRATES ((u16)0xFCB3) #define HFA384x_RID_CNFSUPPRATES ((u16)0xFCB4) -#define HFA384x_RID_CNFFALLBACKCTRL ((u16)0xFCB5) // NEW -#define HFA384x_RID_WEPKEYSTATUS ((u16)0xFCB6) // NEW -#define HFA384x_RID_WEPKEYMAPINDEX ((u16)0xFCB7) // NEW -#define HFA384x_RID_BROADCASTKEYID ((u16)0xFCB8) // NEW -#define HFA384x_RID_ENTSECFLAGEYID ((u16)0xFCB9) // NEW -#define HFA384x_RID_CNFPASSIVESCANCTRL ((u16)0xFCBA) // NEW STA -#define HFA384x_RID_CNFWPAHANDLING ((u16)0xFCBB) // 1.7.0 -#define HFA384x_RID_MDCCONTROL ((u16)0xFCBC) // 1.7.0/1.4.0 -#define HFA384x_RID_MDCCOUNTRY ((u16)0xFCBD) // 1.7.0/1.4.0 -#define HFA384x_RID_TXPOWERMAX ((u16)0xFCBE) // 1.7.0/1.4.0 -#define HFA384x_RID_CNFLFOENBLED ((u16)0xFCBF) // 1.6.3 -#define HFA384x_RID_CAPINFO ((u16)0xFCC0) // 1.7.0/1.3.7 -#define HFA384x_RID_LISTENintERVAL ((u16)0xFCC1) // 1.7.0/1.3.7 -#define HFA384x_RID_DIVERSITYENABLED ((u16)0xFCC2) // 1.7.0/1.3.7 -#define HFA384x_RID_LED_CONTROL ((u16)0xFCC4) // 1.7.6 -#define HFA384x_RID_HFO_DELAY ((u16)0xFCC5) // 1.7.6 -#define HFA384x_RID_DISSALOWEDBSSID ((u16)0xFCC6) // 1.8.0 -#define HFA384x_RID_SCANREQUEST ((u16)0xFCE1) +#define HFA384x_RID_CNFPASSIVESCANCTRL ((u16)0xFCBA) +#define HFA384x_RID_TXPOWERMAX ((u16)0xFCBE) #define HFA384x_RID_JOINREQUEST ((u16)0xFCE2) #define HFA384x_RID_AUTHENTICATESTA ((u16)0xFCE3) -#define HFA384x_RID_CHANNELINFOREQUEST ((u16)0xFCE4) -#define HFA384x_RID_HOSTSCAN ((u16)0xFCE5) // NEW STA -#define HFA384x_RID_ASSOCIATESTA ((u16)0xFCE6) +#define HFA384x_RID_HOSTSCAN ((u16)0xFCE5) #define HFA384x_RID_CNFWEPDEFAULTKEY_LEN ((u16)6) #define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((u16)14) -#define HFA384x_RID_CNFPRIOQUSAGE_LEN ((u16)4) + /*-------------------------------------------------------------------- PD Record codes --------------------------------------------------------------------*/ @@ -697,22 +287,11 @@ PD Record codes #define HFA384x_PDR_MFISUPRANGE ((u16)0x0006) #define HFA384x_PDR_CFISUPRANGE ((u16)0x0007) #define HFA384x_PDR_NICID ((u16)0x0008) -//#define HFA384x_PDR_REFDAC_MEASUREMENTS ((u16)0x0010) -//#define HFA384x_PDR_VGDAC_MEASUREMENTS ((u16)0x0020) -//#define HFA384x_PDR_LEVEL_COMP_MEASUREMENTS ((u16)0x0030) -//#define HFA384x_PDR_MODEM_TRIMDAC_MEASUREMENTS ((u16)0x0040) -//#define HFA384x_PDR_COREGA_HACK ((u16)0x00ff) #define HFA384x_PDR_MAC_ADDRESS ((u16)0x0101) -//#define HFA384x_PDR_MKK_CALLNAME ((u16)0x0102) #define HFA384x_PDR_REGDOMAIN ((u16)0x0103) #define HFA384x_PDR_ALLOWED_CHANNEL ((u16)0x0104) #define HFA384x_PDR_DEFAULT_CHANNEL ((u16)0x0105) -//#define HFA384x_PDR_PRIVACY_OPTION ((u16)0x0106) #define HFA384x_PDR_TEMPTYPE ((u16)0x0107) -//#define HFA384x_PDR_REFDAC_SETUP ((u16)0x0110) -//#define HFA384x_PDR_VGDAC_SETUP ((u16)0x0120) -//#define HFA384x_PDR_LEVEL_COMP_SETUP ((u16)0x0130) -//#define HFA384x_PDR_TRIMDAC_SETUP ((u16)0x0140) #define HFA384x_PDR_IFR_SETTING ((u16)0x0200) #define HFA384x_PDR_RFR_SETTING ((u16)0x0201) #define HFA384x_PDR_HFA3861_BASELINE ((u16)0x0202) @@ -729,7 +308,6 @@ PD Record codes #define HFA384x_PDR_PCI_PMCONF ((u16)0x0404) #define HFA384x_PDR_RFENRGY ((u16)0x0406) #define HFA384x_PDR_USB_POWER_TYPE ((u16)0x0407) -//#define HFA384x_PDR_UNKNOWN408 ((u16)0x0408) #define HFA384x_PDR_USB_MAX_POWER ((u16)0x0409) #define HFA384x_PDR_USB_MANUFACTURER ((u16)0x0410) #define HFA384x_PDR_USB_PRODUCT ((u16)0x0411) @@ -741,831 +319,122 @@ PD Record codes #define HFA384x_PDR_HFA3861_MANF_TESTI ((u16)0x0901) #define HFA384x_PDR_END_OF_PDA ((u16)0x0000) - -/*=============================================================*/ -/*------ Macros -----------------------------------------------*/ - -/*--- Register ID macros ------------------------*/ - -#define HFA384x_CMD HFA384x_CMD_OFF -#define HFA384x_PARAM0 HFA384x_PARAM0_OFF -#define HFA384x_PARAM1 HFA384x_PARAM1_OFF -#define HFA384x_PARAM2 HFA384x_PARAM2_OFF -#define HFA384x_STATUS HFA384x_STATUS_OFF -#define HFA384x_RESP0 HFA384x_RESP0_OFF -#define HFA384x_RESP1 HFA384x_RESP1_OFF -#define HFA384x_RESP2 HFA384x_RESP2_OFF -#define HFA384x_INFOFID HFA384x_INFOFID_OFF -#define HFA384x_RXFID HFA384x_RXFID_OFF -#define HFA384x_ALLOCFID HFA384x_ALLOCFID_OFF -#define HFA384x_TXCOMPLFID HFA384x_TXCOMPLFID_OFF -#define HFA384x_SELECT0 HFA384x_SELECT0_OFF -#define HFA384x_OFFSET0 HFA384x_OFFSET0_OFF -#define HFA384x_DATA0 HFA384x_DATA0_OFF -#define HFA384x_SELECT1 HFA384x_SELECT1_OFF -#define HFA384x_OFFSET1 HFA384x_OFFSET1_OFF -#define HFA384x_DATA1 HFA384x_DATA1_OFF -#define HFA384x_EVSTAT HFA384x_EVSTAT_OFF -#define HFA384x_intEN HFA384x_INTEN_OFF -#define HFA384x_EVACK HFA384x_EVACK_OFF -#define HFA384x_CONTROL HFA384x_CONTROL_OFF -#define HFA384x_SWSUPPORT0 HFA384x_SWSUPPORT0_OFF -#define HFA384x_SWSUPPORT1 HFA384x_SWSUPPORT1_OFF -#define HFA384x_SWSUPPORT2 HFA384x_SWSUPPORT2_OFF -#define HFA384x_AUXPAGE HFA384x_AUXPAGE_OFF -#define HFA384x_AUXOFFSET HFA384x_AUXOFFSET_OFF -#define HFA384x_AUXDATA HFA384x_AUXDATA_OFF -#define HFA384x_PCICOR HFA384x_PCICOR_OFF -#define HFA384x_PCIHCR HFA384x_PCIHCR_OFF - - /*--- Register Test/Get/Set Field macros ------------------------*/ -#define HFA384x_CMD_ISBUSY(value) ((u16)(((u16)value) & HFA384x_CMD_BUSY)) -#define HFA384x_CMD_AINFO_GET(value) ((u16)(((u16)(value) & HFA384x_CMD_AINFO) >> 8)) #define HFA384x_CMD_AINFO_SET(value) ((u16)((u16)(value) << 8)) -#define HFA384x_CMD_MACPORT_GET(value) ((u16)(HFA384x_CMD_AINFO_GET((u16)(value) & HFA384x_CMD_MACPORT))) #define HFA384x_CMD_MACPORT_SET(value) ((u16)HFA384x_CMD_AINFO_SET(value)) -#define HFA384x_CMD_ISRECL(value) ((u16)(HFA384x_CMD_AINFO_GET((u16)(value) & HFA384x_CMD_RECL))) -#define HFA384x_CMD_RECL_SET(value) ((u16)HFA384x_CMD_AINFO_SET(value)) -#define HFA384x_CMD_QOS_GET(value) ((u16)((((u16)(value))&((u16)0x3000)) >> 12)) -#define HFA384x_CMD_QOS_SET(value) ((u16)((((u16)(value)) << 12) & 0x3000)) -#define HFA384x_CMD_ISWRITE(value) ((u16)(HFA384x_CMD_AINFO_GET((u16)(value) & HFA384x_CMD_WRITE))) -#define HFA384x_CMD_WRITE_SET(value) ((u16)HFA384x_CMD_AINFO_SET((u16)value)) -#define HFA384x_CMD_PROGMODE_GET(value) ((u16)(HFA384x_CMD_AINFO_GET((u16)(value) & HFA384x_CMD_PROGMODE))) #define HFA384x_CMD_PROGMODE_SET(value) ((u16)HFA384x_CMD_AINFO_SET((u16)value)) -#define HFA384x_CMD_CMDCODE_GET(value) ((u16)(((u16)(value)) & HFA384x_CMD_CMDCODE)) #define HFA384x_CMD_CMDCODE_SET(value) ((u16)(value)) -#define HFA384x_STATUS_RESULT_GET(value) ((u16)((((u16)(value)) & HFA384x_STATUS_RESULT) >> 8)) #define HFA384x_STATUS_RESULT_SET(value) (((u16)(value)) << 8) -#define HFA384x_STATUS_CMDCODE_GET(value) (((u16)(value)) & HFA384x_STATUS_CMDCODE) -#define HFA384x_STATUS_CMDCODE_SET(value) ((u16)(value)) - -#define HFA384x_OFFSET_ISBUSY(value) ((u16)(((u16)(value)) & HFA384x_OFFSET_BUSY)) -#define HFA384x_OFFSET_ISERR(value) ((u16)(((u16)(value)) & HFA384x_OFFSET_ERR)) -#define HFA384x_OFFSET_DATAOFF_GET(value) ((u16)(((u16)(value)) & HFA384x_OFFSET_DATAOFF)) -#define HFA384x_OFFSET_DATAOFF_SET(value) ((u16)(value)) - -#define HFA384x_EVSTAT_ISTICK(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_TICK)) -#define HFA384x_EVSTAT_ISWTERR(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_WTERR)) -#define HFA384x_EVSTAT_ISINFDROP(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_INFDROP)) -#define HFA384x_EVSTAT_ISINFO(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_INFO)) -#define HFA384x_EVSTAT_ISDTIM(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_DTIM)) -#define HFA384x_EVSTAT_ISCMD(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_CMD)) -#define HFA384x_EVSTAT_ISALLOC(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_ALLOC)) -#define HFA384x_EVSTAT_ISTXEXC(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_TXEXC)) -#define HFA384x_EVSTAT_ISTX(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_TX)) -#define HFA384x_EVSTAT_ISRX(value) ((u16)(((u16)(value)) & HFA384x_EVSTAT_RX)) - -#define HFA384x_EVSTAT_ISBAP_OP(value) ((u16)(((u16)(value)) & HFA384x_int_BAP_OP)) - -#define HFA384x_intEN_ISTICK(value) ((u16)(((u16)(value)) & HFA384x_INTEN_TICK)) -#define HFA384x_intEN_TICK_SET(value) ((u16)(((u16)(value)) << 15)) -#define HFA384x_intEN_ISWTERR(value) ((u16)(((u16)(value)) & HFA384x_INTEN_WTERR)) -#define HFA384x_intEN_WTERR_SET(value) ((u16)(((u16)(value)) << 14)) -#define HFA384x_intEN_ISINFDROP(value) ((u16)(((u16)(value)) & HFA384x_INTEN_INFDROP)) -#define HFA384x_intEN_INFDROP_SET(value) ((u16)(((u16)(value)) << 13)) -#define HFA384x_intEN_ISINFO(value) ((u16)(((u16)(value)) & HFA384x_INTEN_INFO)) -#define HFA384x_intEN_INFO_SET(value) ((u16)(((u16)(value)) << 7)) -#define HFA384x_intEN_ISDTIM(value) ((u16)(((u16)(value)) & HFA384x_INTEN_DTIM)) -#define HFA384x_intEN_DTIM_SET(value) ((u16)(((u16)(value)) << 5)) -#define HFA384x_intEN_ISCMD(value) ((u16)(((u16)(value)) & HFA384x_INTEN_CMD)) -#define HFA384x_intEN_CMD_SET(value) ((u16)(((u16)(value)) << 4)) -#define HFA384x_intEN_ISALLOC(value) ((u16)(((u16)(value)) & HFA384x_INTEN_ALLOC)) -#define HFA384x_intEN_ALLOC_SET(value) ((u16)(((u16)(value)) << 3)) -#define HFA384x_intEN_ISTXEXC(value) ((u16)(((u16)(value)) & HFA384x_INTEN_TXEXC)) -#define HFA384x_intEN_TXEXC_SET(value) ((u16)(((u16)(value)) << 2)) -#define HFA384x_intEN_ISTX(value) ((u16)(((u16)(value)) & HFA384x_INTEN_TX)) -#define HFA384x_intEN_TX_SET(value) ((u16)(((u16)(value)) << 1)) -#define HFA384x_intEN_ISRX(value) ((u16)(((u16)(value)) & HFA384x_INTEN_RX)) -#define HFA384x_intEN_RX_SET(value) ((u16)(((u16)(value)) << 0)) - -#define HFA384x_EVACK_ISTICK(value) ((u16)(((u16)(value)) & HFA384x_EVACK_TICK)) -#define HFA384x_EVACK_TICK_SET(value) ((u16)(((u16)(value)) << 15)) -#define HFA384x_EVACK_ISWTERR(value) ((u16)(((u16)(value)) & HFA384x_EVACK_WTERR)) -#define HFA384x_EVACK_WTERR_SET(value) ((u16)(((u16)(value)) << 14)) -#define HFA384x_EVACK_ISINFDROP(value) ((u16)(((u16)(value)) & HFA384x_EVACK_INFDROP)) -#define HFA384x_EVACK_INFDROP_SET(value) ((u16)(((u16)(value)) << 13)) -#define HFA384x_EVACK_ISINFO(value) ((u16)(((u16)(value)) & HFA384x_EVACK_INFO)) -#define HFA384x_EVACK_INFO_SET(value) ((u16)(((u16)(value)) << 7)) -#define HFA384x_EVACK_ISDTIM(value) ((u16)(((u16)(value)) & HFA384x_EVACK_DTIM)) -#define HFA384x_EVACK_DTIM_SET(value) ((u16)(((u16)(value)) << 5)) -#define HFA384x_EVACK_ISCMD(value) ((u16)(((u16)(value)) & HFA384x_EVACK_CMD)) -#define HFA384x_EVACK_CMD_SET(value) ((u16)(((u16)(value)) << 4)) -#define HFA384x_EVACK_ISALLOC(value) ((u16)(((u16)(value)) & HFA384x_EVACK_ALLOC)) -#define HFA384x_EVACK_ALLOC_SET(value) ((u16)(((u16)(value)) << 3)) -#define HFA384x_EVACK_ISTXEXC(value) ((u16)(((u16)(value)) & HFA384x_EVACK_TXEXC)) -#define HFA384x_EVACK_TXEXC_SET(value) ((u16)(((u16)(value)) << 2)) -#define HFA384x_EVACK_ISTX(value) ((u16)(((u16)(value)) & HFA384x_EVACK_TX)) -#define HFA384x_EVACK_TX_SET(value) ((u16)(((u16)(value)) << 1)) -#define HFA384x_EVACK_ISRX(value) ((u16)(((u16)(value)) & HFA384x_EVACK_RX)) -#define HFA384x_EVACK_RX_SET(value) ((u16)(((u16)(value)) << 0)) - -#define HFA384x_CONTROL_AUXEN_SET(value) ((u16)(((u16)(value)) << 14)) -#define HFA384x_CONTROL_AUXEN_GET(value) ((u16)(((u16)(value)) >> 14)) - -/* Byte Order */ -#ifdef __KERNEL__ -#define hfa384x2host_16(n) (__le16_to_cpu((u16)(n))) -#define hfa384x2host_32(n) (__le32_to_cpu((u32)(n))) -#define host2hfa384x_16(n) (__cpu_to_le16((u16)(n))) -#define host2hfa384x_32(n) (__cpu_to_le32((u32)(n))) -#endif /* Host Maintained State Info */ #define HFA384x_STATE_PREINIT 0 #define HFA384x_STATE_INIT 1 #define HFA384x_STATE_RUNNING 2 -/*=============================================================*/ -/*------ Types and their related constants --------------------*/ - -#define HFA384x_HOSTAUTHASSOC_HOSTAUTH BIT0 -#define HFA384x_HOSTAUTHASSOC_HOSTASSOC BIT1 - -#define HFA384x_WHAHANDLING_DISABLED 0 -#define HFA384x_WHAHANDLING_PASSTHROUGH BIT1 - /*-------------------------------------------------------------*/ /* Commonly used basic types */ -typedef struct hfa384x_bytestr -{ - u16 len; - u8 data[0]; -} __WLAN_ATTRIB_PACK__ hfa384x_bytestr_t; +typedef struct hfa384x_bytestr { + u16 len; + u8 data[0]; +} __attribute__ ((packed)) hfa384x_bytestr_t; -typedef struct hfa384x_bytestr32 -{ - u16 len; - u8 data[32]; -} __WLAN_ATTRIB_PACK__ hfa384x_bytestr32_t; +typedef struct hfa384x_bytestr32 { + u16 len; + u8 data[32]; +} __attribute__ ((packed)) hfa384x_bytestr32_t; /*-------------------------------------------------------------------- Configuration Record Structures: Network Parameters, Static Configuration Entities --------------------------------------------------------------------*/ -/* Prototype structure: all configuration record structures start with -these members */ - -typedef struct hfa384x_record -{ - u16 reclen; - u16 rid; -} __WLAN_ATTRIB_PACK__ hfa384x_rec_t; - -typedef struct hfa384x_record16 -{ - u16 reclen; - u16 rid; - u16 val; -} __WLAN_ATTRIB_PACK__ hfa384x_rec16_t; - -typedef struct hfa384x_record32 -{ - u16 reclen; - u16 rid; - u32 val; -} __WLAN_ATTRIB_PACK__ hfa384x_rec32; /*-- Hardware/Firmware Component Information ----------*/ -typedef struct hfa384x_compident -{ - u16 id; - u16 variant; - u16 major; - u16 minor; -} __WLAN_ATTRIB_PACK__ hfa384x_compident_t; +typedef struct hfa384x_compident { + u16 id; + u16 variant; + u16 major; + u16 minor; +} __attribute__ ((packed)) hfa384x_compident_t; -typedef struct hfa384x_caplevel -{ - u16 role; - u16 id; - u16 variant; - u16 bottom; - u16 top; -} __WLAN_ATTRIB_PACK__ hfa384x_caplevel_t; - -/*-- Configuration Record: cnfPortType --*/ -typedef struct hfa384x_cnfPortType -{ - u16 cnfPortType; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfPortType_t; - -/*-- Configuration Record: cnfOwnMACAddress --*/ -typedef struct hfa384x_cnfOwnMACAddress -{ - u8 cnfOwnMACAddress[6]; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnMACAddress_t; - -/*-- Configuration Record: cnfDesiredSSID --*/ -typedef struct hfa384x_cnfDesiredSSID -{ - u8 cnfDesiredSSID[34]; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfDesiredSSID_t; - -/*-- Configuration Record: cnfOwnChannel --*/ -typedef struct hfa384x_cnfOwnChannel -{ - u16 cnfOwnChannel; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnChannel_t; - -/*-- Configuration Record: cnfOwnSSID --*/ -typedef struct hfa384x_cnfOwnSSID -{ - u8 cnfOwnSSID[34]; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnSSID_t; - -/*-- Configuration Record: cnfOwnATIMWindow --*/ -typedef struct hfa384x_cnfOwnATIMWindow -{ - u16 cnfOwnATIMWindow; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnATIMWindow_t; - -/*-- Configuration Record: cnfSystemScale --*/ -typedef struct hfa384x_cnfSystemScale -{ - u16 cnfSystemScale; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfSystemScale_t; - -/*-- Configuration Record: cnfMaxDataLength --*/ -typedef struct hfa384x_cnfMaxDataLength -{ - u16 cnfMaxDataLength; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxDataLength_t; - -/*-- Configuration Record: cnfWDSAddress --*/ -typedef struct hfa384x_cnfWDSAddress -{ - u8 cnfWDSAddress[6]; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddress_t; - -/*-- Configuration Record: cnfPMEnabled --*/ -typedef struct hfa384x_cnfPMEnabled -{ - u16 cnfPMEnabled; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEnabled_t; - -/*-- Configuration Record: cnfPMEPS --*/ -typedef struct hfa384x_cnfPMEPS -{ - u16 cnfPMEPS; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEPS_t; - -/*-- Configuration Record: cnfMulticastReceive --*/ -typedef struct hfa384x_cnfMulticastReceive -{ - u16 cnfMulticastReceive; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastReceive_t; +typedef struct hfa384x_caplevel { + u16 role; + u16 id; + u16 variant; + u16 bottom; + u16 top; +} __attribute__ ((packed)) hfa384x_caplevel_t; /*-- Configuration Record: cnfAuthentication --*/ #define HFA384x_CNFAUTHENTICATION_OPENSYSTEM 0x0001 #define HFA384x_CNFAUTHENTICATION_SHAREDKEY 0x0002 #define HFA384x_CNFAUTHENTICATION_LEAP 0x0004 -/*-- Configuration Record: cnfMaxSleepDuration --*/ -typedef struct hfa384x_cnfMaxSleepDuration -{ - u16 cnfMaxSleepDuration; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxSleepDuration_t; - -/*-- Configuration Record: cnfPMHoldoverDuration --*/ -typedef struct hfa384x_cnfPMHoldoverDuration -{ - u16 cnfPMHoldoverDuration; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfPMHoldoverDuration_t; - -/*-- Configuration Record: cnfOwnName --*/ -typedef struct hfa384x_cnfOwnName -{ - u8 cnfOwnName[34]; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnName_t; - -/*-- Configuration Record: cnfOwnDTIMPeriod --*/ -typedef struct hfa384x_cnfOwnDTIMPeriod -{ - u16 cnfOwnDTIMPeriod; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnDTIMPeriod_t; - -/*-- Configuration Record: cnfWDSAddress --*/ -typedef struct hfa384x_cnfWDSAddressN -{ - u8 cnfWDSAddress[6]; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddressN_t; - -/*-- Configuration Record: cnfMulticastPMBuffering --*/ -typedef struct hfa384x_cnfMulticastPMBuffering -{ - u16 cnfMulticastPMBuffering; -} __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastPMBuffering_t; - /*-------------------------------------------------------------------- Configuration Record Structures: Network Parameters, Dynamic Configuration Entities --------------------------------------------------------------------*/ -/*-- Configuration Record: GroupAddresses --*/ -typedef struct hfa384x_GroupAddresses -{ - u8 MACAddress[16][6]; -} __WLAN_ATTRIB_PACK__ hfa384x_GroupAddresses_t; - -/*-- Configuration Record: CreateIBSS --*/ -typedef struct hfa384x_CreateIBSS -{ - u16 CreateIBSS; -} __WLAN_ATTRIB_PACK__ hfa384x_CreateIBSS_t; - #define HFA384x_CREATEIBSS_JOINCREATEIBSS 0 -#define HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS 1 -#define HFA384x_CREATEIBSS_JOINIBSS 2 -#define HFA384x_CREATEIBSS_JOINESS_JOINIBSS 3 - -/*-- Configuration Record: FragmentationThreshold --*/ -typedef struct hfa384x_FragmentationThreshold -{ - u16 FragmentationThreshold; -} __WLAN_ATTRIB_PACK__ hfa384x_FragmentationThreshold_t; - -/*-- Configuration Record: RTSThreshold --*/ -typedef struct hfa384x_RTSThreshold -{ - u16 RTSThreshold; -} __WLAN_ATTRIB_PACK__ hfa384x_RTSThreshold_t; - -/*-- Configuration Record: TxRateControl --*/ -typedef struct hfa384x_TxRateControl -{ - u16 TxRateControl; -} __WLAN_ATTRIB_PACK__ hfa384x_TxRateControl_t; - -/*-- Configuration Record: PromiscuousMode --*/ -typedef struct hfa384x_PromiscuousMode -{ - u16 PromiscuousMode; -} __WLAN_ATTRIB_PACK__ hfa384x_PromiscuousMode_t; - -/*-- Configuration Record: ScanRequest (data portion only) --*/ -typedef struct hfa384x_ScanRequest_data -{ - u16 channelList; - u16 txRate; -} __WLAN_ATTRIB_PACK__ hfa384x_ScanRequest_data_t; /*-- Configuration Record: HostScanRequest (data portion only) --*/ -typedef struct hfa384x_HostScanRequest_data -{ - u16 channelList; - u16 txRate; +typedef struct hfa384x_HostScanRequest_data { + u16 channelList; + u16 txRate; hfa384x_bytestr32_t ssid; -} __WLAN_ATTRIB_PACK__ hfa384x_HostScanRequest_data_t; +} __attribute__ ((packed)) hfa384x_HostScanRequest_data_t; /*-- Configuration Record: JoinRequest (data portion only) --*/ -typedef struct hfa384x_JoinRequest_data -{ - u8 bssid[WLAN_BSSID_LEN]; - u16 channel; -} __WLAN_ATTRIB_PACK__ hfa384x_JoinRequest_data_t; +typedef struct hfa384x_JoinRequest_data { + u8 bssid[WLAN_BSSID_LEN]; + u16 channel; +} __attribute__ ((packed)) hfa384x_JoinRequest_data_t; /*-- Configuration Record: authenticateStation (data portion only) --*/ -typedef struct hfa384x_authenticateStation_data -{ - u8 address[WLAN_ADDR_LEN]; - u16 status; - u16 algorithm; -} __WLAN_ATTRIB_PACK__ hfa384x_authenticateStation_data_t; - -/*-- Configuration Record: associateStation (data portion only) --*/ -typedef struct hfa384x_associateStation_data -{ - u8 address[WLAN_ADDR_LEN]; - u16 status; - u16 type; -} __WLAN_ATTRIB_PACK__ hfa384x_associateStation_data_t; - -/*-- Configuration Record: ChannelInfoRequest (data portion only) --*/ -typedef struct hfa384x_ChannelInfoRequest_data -{ - u16 channelList; - u16 channelDwellTime; -} __WLAN_ATTRIB_PACK__ hfa384x_ChannelInfoRequest_data_t; - -/*-- Configuration Record: WEPKeyMapping (data portion only) --*/ -typedef struct hfa384x_WEPKeyMapping -{ - u8 address[WLAN_ADDR_LEN]; - u16 key_index; - u8 key[16]; - u8 mic_transmit_key[4]; - u8 mic_receive_key[4]; -} __WLAN_ATTRIB_PACK__ hfa384x_WEPKeyMapping_t; +typedef struct hfa384x_authenticateStation_data { + u8 address[ETH_ALEN]; + u16 status; + u16 algorithm; +} __attribute__ ((packed)) hfa384x_authenticateStation_data_t; /*-- Configuration Record: WPAData (data portion only) --*/ -typedef struct hfa384x_WPAData -{ - u16 datalen; - u8 data[0]; // max 80 -} __WLAN_ATTRIB_PACK__ hfa384x_WPAData_t; - -/*-------------------------------------------------------------------- -Configuration Record Structures: Behavior Parameters ---------------------------------------------------------------------*/ - -/*-- Configuration Record: TickTime --*/ -typedef struct hfa384x_TickTime -{ - u16 TickTime; -} __WLAN_ATTRIB_PACK__ hfa384x_TickTime_t; +typedef struct hfa384x_WPAData { + u16 datalen; + u8 data[0]; // max 80 +} __attribute__ ((packed)) hfa384x_WPAData_t; /*-------------------------------------------------------------------- Information Record Structures: NIC Information --------------------------------------------------------------------*/ -/*-- Information Record: MaxLoadTime --*/ -typedef struct hfa384x_MaxLoadTime -{ - u16 MaxLoadTime; -} __WLAN_ATTRIB_PACK__ hfa384x_MaxLoadTime_t; - /*-- Information Record: DownLoadBuffer --*/ /* NOTE: The page and offset are in AUX format */ -typedef struct hfa384x_downloadbuffer -{ - u16 page; - u16 offset; - u16 len; -} __WLAN_ATTRIB_PACK__ hfa384x_downloadbuffer_t; - -/*-- Information Record: PRIIdentity --*/ -typedef struct hfa384x_PRIIdentity -{ - u16 PRICompID; - u16 PRIVariant; - u16 PRIMajorVersion; - u16 PRIMinorVersion; -} __WLAN_ATTRIB_PACK__ hfa384x_PRIIdentity_t; - -/*-- Information Record: PRISupRange --*/ -typedef struct hfa384x_PRISupRange -{ - u16 PRIRole; - u16 PRIID; - u16 PRIVariant; - u16 PRIBottom; - u16 PRITop; -} __WLAN_ATTRIB_PACK__ hfa384x_PRISupRange_t; - -/*-- Information Record: CFIActRanges --*/ -typedef struct hfa384x_CFIActRanges -{ - u16 CFIRole; - u16 CFIID; - u16 CFIVariant; - u16 CFIBottom; - u16 CFITop; -} __WLAN_ATTRIB_PACK__ hfa384x_CFIActRanges_t; - -/*-- Information Record: NICSerialNumber --*/ -typedef struct hfa384x_NICSerialNumber -{ - u8 NICSerialNumber[12]; -} __WLAN_ATTRIB_PACK__ hfa384x_NICSerialNumber_t; - -/*-- Information Record: NICIdentity --*/ -typedef struct hfa384x_NICIdentity -{ - u16 NICCompID; - u16 NICVariant; - u16 NICMajorVersion; - u16 NICMinorVersion; -} __WLAN_ATTRIB_PACK__ hfa384x_NICIdentity_t; - -/*-- Information Record: MFISupRange --*/ -typedef struct hfa384x_MFISupRange -{ - u16 MFIRole; - u16 MFIID; - u16 MFIVariant; - u16 MFIBottom; - u16 MFITop; -} __WLAN_ATTRIB_PACK__ hfa384x_MFISupRange_t; - -/*-- Information Record: CFISupRange --*/ -typedef struct hfa384x_CFISupRange -{ - u16 CFIRole; - u16 CFIID; - u16 CFIVariant; - u16 CFIBottom; - u16 CFITop; -} __WLAN_ATTRIB_PACK__ hfa384x_CFISupRange_t; - -/*-- Information Record: BUILDSEQ:BuildSeq --*/ -typedef struct hfa384x_BuildSeq { - u16 primary; - u16 secondary; -} __WLAN_ATTRIB_PACK__ hfa384x_BuildSeq_t; - -/*-- Information Record: FWID --*/ -#define HFA384x_FWID_LEN 14 -typedef struct hfa384x_FWID { - u8 primary[HFA384x_FWID_LEN]; - u8 secondary[HFA384x_FWID_LEN]; -} __WLAN_ATTRIB_PACK__ hfa384x_FWID_t; - -/*-- Information Record: ChannelList --*/ -typedef struct hfa384x_ChannelList -{ - u16 ChannelList; -} __WLAN_ATTRIB_PACK__ hfa384x_ChannelList_t; - -/*-- Information Record: RegulatoryDomains --*/ -typedef struct hfa384x_RegulatoryDomains -{ - u8 RegulatoryDomains[12]; -} __WLAN_ATTRIB_PACK__ hfa384x_RegulatoryDomains_t; - -/*-- Information Record: TempType --*/ -typedef struct hfa384x_TempType -{ - u16 TempType; -} __WLAN_ATTRIB_PACK__ hfa384x_TempType_t; - -/*-- Information Record: CIS --*/ -typedef struct hfa384x_CIS -{ - u8 CIS[480]; -} __WLAN_ATTRIB_PACK__ hfa384x_CIS_t; - -/*-- Information Record: STAIdentity --*/ -typedef struct hfa384x_STAIdentity -{ - u16 STACompID; - u16 STAVariant; - u16 STAMajorVersion; - u16 STAMinorVersion; -} __WLAN_ATTRIB_PACK__ hfa384x_STAIdentity_t; - -/*-- Information Record: STASupRange --*/ -typedef struct hfa384x_STASupRange -{ - u16 STARole; - u16 STAID; - u16 STAVariant; - u16 STABottom; - u16 STATop; -} __WLAN_ATTRIB_PACK__ hfa384x_STASupRange_t; - -/*-- Information Record: MFIActRanges --*/ -typedef struct hfa384x_MFIActRanges -{ - u16 MFIRole; - u16 MFIID; - u16 MFIVariant; - u16 MFIBottom; - u16 MFITop; -} __WLAN_ATTRIB_PACK__ hfa384x_MFIActRanges_t; +typedef struct hfa384x_downloadbuffer { + u16 page; + u16 offset; + u16 len; +} __attribute__ ((packed)) hfa384x_downloadbuffer_t; /*-------------------------------------------------------------------- Information Record Structures: NIC Information --------------------------------------------------------------------*/ -/*-- Information Record: PortStatus --*/ -typedef struct hfa384x_PortStatus -{ - u16 PortStatus; -} __WLAN_ATTRIB_PACK__ hfa384x_PortStatus_t; - -#define HFA384x_PSTATUS_DISABLED ((u16)1) -#define HFA384x_PSTATUS_SEARCHING ((u16)2) #define HFA384x_PSTATUS_CONN_IBSS ((u16)3) -#define HFA384x_PSTATUS_CONN_ESS ((u16)4) -#define HFA384x_PSTATUS_OUTOFRANGE ((u16)5) -#define HFA384x_PSTATUS_CONN_WDS ((u16)6) - -/*-- Information Record: CurrentSSID --*/ -typedef struct hfa384x_CurrentSSID -{ - u8 CurrentSSID[34]; -} __WLAN_ATTRIB_PACK__ hfa384x_CurrentSSID_t; - -/*-- Information Record: CurrentBSSID --*/ -typedef struct hfa384x_CurrentBSSID -{ - u8 CurrentBSSID[6]; -} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBSSID_t; /*-- Information Record: commsquality --*/ -typedef struct hfa384x_commsquality -{ - u16 CQ_currBSS; - u16 ASL_currBSS; - u16 ANL_currFC; -} __WLAN_ATTRIB_PACK__ hfa384x_commsquality_t; +typedef struct hfa384x_commsquality { + u16 CQ_currBSS; + u16 ASL_currBSS; + u16 ANL_currFC; +} __attribute__ ((packed)) hfa384x_commsquality_t; /*-- Information Record: dmbcommsquality --*/ -typedef struct hfa384x_dbmcommsquality -{ - u16 CQdbm_currBSS; - u16 ASLdbm_currBSS; - u16 ANLdbm_currFC; -} __WLAN_ATTRIB_PACK__ hfa384x_dbmcommsquality_t; - -/*-- Information Record: CurrentTxRate --*/ -typedef struct hfa384x_CurrentTxRate -{ - u16 CurrentTxRate; -} __WLAN_ATTRIB_PACK__ hfa384x_CurrentTxRate_t; - -/*-- Information Record: CurrentBeaconInterval --*/ -typedef struct hfa384x_CurrentBeaconInterval -{ - u16 CurrentBeaconInterval; -} __WLAN_ATTRIB_PACK__ hfa384x_CurrentBeaconInterval_t; - -/*-- Information Record: CurrentScaleThresholds --*/ -typedef struct hfa384x_CurrentScaleThresholds -{ - u16 EnergyDetectThreshold; - u16 CarrierDetectThreshold; - u16 DeferDetectThreshold; - u16 CellSearchThreshold; /* Stations only */ - u16 DeadSpotThreshold; /* Stations only */ -} __WLAN_ATTRIB_PACK__ hfa384x_CurrentScaleThresholds_t; - -/*-- Information Record: ProtocolRspTime --*/ -typedef struct hfa384x_ProtocolRspTime -{ - u16 ProtocolRspTime; -} __WLAN_ATTRIB_PACK__ hfa384x_ProtocolRspTime_t; - -/*-- Information Record: ShortRetryLimit --*/ -typedef struct hfa384x_ShortRetryLimit -{ - u16 ShortRetryLimit; -} __WLAN_ATTRIB_PACK__ hfa384x_ShortRetryLimit_t; - -/*-- Information Record: LongRetryLimit --*/ -typedef struct hfa384x_LongRetryLimit -{ - u16 LongRetryLimit; -} __WLAN_ATTRIB_PACK__ hfa384x_LongRetryLimit_t; - -/*-- Information Record: MaxTransmitLifetime --*/ -typedef struct hfa384x_MaxTransmitLifetime -{ - u16 MaxTransmitLifetime; -} __WLAN_ATTRIB_PACK__ hfa384x_MaxTransmitLifetime_t; - -/*-- Information Record: MaxReceiveLifetime --*/ -typedef struct hfa384x_MaxReceiveLifetime -{ - u16 MaxReceiveLifetime; -} __WLAN_ATTRIB_PACK__ hfa384x_MaxReceiveLifetime_t; - -/*-- Information Record: CFPollable --*/ -typedef struct hfa384x_CFPollable -{ - u16 CFPollable; -} __WLAN_ATTRIB_PACK__ hfa384x_CFPollable_t; - -/*-- Information Record: AuthenticationAlgorithms --*/ -typedef struct hfa384x_AuthenticationAlgorithms -{ - u16 AuthenticationType; - u16 TypeEnabled; -} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_t; - -/*-- Information Record: AuthenticationAlgorithms -(data only --*/ -typedef struct hfa384x_AuthenticationAlgorithms_data -{ - u16 AuthenticationType; - u16 TypeEnabled; -} __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_data_t; - -/*-- Information Record: PrivacyOptionImplemented --*/ -typedef struct hfa384x_PrivacyOptionImplemented -{ - u16 PrivacyOptionImplemented; -} __WLAN_ATTRIB_PACK__ hfa384x_PrivacyOptionImplemented_t; - -/*-- Information Record: OwnMACAddress --*/ -typedef struct hfa384x_OwnMACAddress -{ - u8 OwnMACAddress[6]; -} __WLAN_ATTRIB_PACK__ hfa384x_OwnMACAddress_t; - -/*-- Information Record: PCFInfo --*/ -typedef struct hfa384x_PCFInfo -{ - u16 MediumOccupancyLimit; - u16 CFPPeriod; - u16 CFPMaxDuration; - u16 CFPFlags; -} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_t; - -/*-- Information Record: PCFInfo (data portion only) --*/ -typedef struct hfa384x_PCFInfo_data -{ - u16 MediumOccupancyLimit; - u16 CFPPeriod; - u16 CFPMaxDuration; - u16 CFPFlags; -} __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_data_t; - -/*-------------------------------------------------------------------- -Information Record Structures: Modem Information Records ---------------------------------------------------------------------*/ - -/*-- Information Record: PHYType --*/ -typedef struct hfa384x_PHYType -{ - u16 PHYType; -} __WLAN_ATTRIB_PACK__ hfa384x_PHYType_t; - -/*-- Information Record: CurrentChannel --*/ -typedef struct hfa384x_CurrentChannel -{ - u16 CurrentChannel; -} __WLAN_ATTRIB_PACK__ hfa384x_CurrentChannel_t; - -/*-- Information Record: CurrentPowerState --*/ -typedef struct hfa384x_CurrentPowerState -{ - u16 CurrentPowerState; -} __WLAN_ATTRIB_PACK__ hfa384x_CurrentPowerState_t; - -/*-- Information Record: CCAMode --*/ -typedef struct hfa384x_CCAMode -{ - u16 CCAMode; -} __WLAN_ATTRIB_PACK__ hfa384x_CCAMode_t; - -/*-- Information Record: SupportedDataRates --*/ -typedef struct hfa384x_SupportedDataRates -{ - u8 SupportedDataRates[10]; -} __WLAN_ATTRIB_PACK__ hfa384x_SupportedDataRates_t; - -/*-- Information Record: LFOStatus --*/ -typedef struct hfa384x_LFOStatus -{ - u16 TestResults; - u16 LFOResult; - u16 VRHFOResult; -} __WLAN_ATTRIB_PACK__ hfa384x_LFOStatus_t; - -#define HFA384x_TESTRESULT_ALLPASSED BIT0 -#define HFA384x_TESTRESULT_LFO_FAIL BIT1 -#define HFA384x_TESTRESULT_VR_HF0_FAIL BIT2 -#define HFA384x_HOST_FIRM_COORDINATE BIT7 -#define HFA384x_TESTRESULT_COORDINATE BIT15 - -/*-- Information Record: LEDControl --*/ -typedef struct hfa384x_LEDControl -{ - u16 searching_on; - u16 searching_off; - u16 assoc_on; - u16 assoc_off; - u16 activity; -} __WLAN_ATTRIB_PACK__ hfa384x_LEDControl_t; - -/*-------------------------------------------------------------------- - FRAME DESCRIPTORS AND FRAME STRUCTURES - -FRAME DESCRIPTORS: Offsets - ----------------------------------------------------------------------- -Control Info (offset 44-51) ---------------------------------------------------------------------*/ -#define HFA384x_FD_STATUS_OFF ((u16)0x44) -#define HFA384x_FD_TIME_OFF ((u16)0x46) -#define HFA384x_FD_SWSUPPORT_OFF ((u16)0x4A) -#define HFA384x_FD_SILENCE_OFF ((u16)0x4A) -#define HFA384x_FD_SIGNAL_OFF ((u16)0x4B) -#define HFA384x_FD_RATE_OFF ((u16)0x4C) -#define HFA384x_FD_RXFLOW_OFF ((u16)0x4D) -#define HFA384x_FD_RESERVED_OFF ((u16)0x4E) -#define HFA384x_FD_TXCONTROL_OFF ((u16)0x50) -/*-------------------------------------------------------------------- -802.11 Header (offset 52-6B) ---------------------------------------------------------------------*/ -#define HFA384x_FD_FRAMECONTROL_OFF ((u16)0x52) -#define HFA384x_FD_DURATIONID_OFF ((u16)0x54) -#define HFA384x_FD_ADDRESS1_OFF ((u16)0x56) -#define HFA384x_FD_ADDRESS2_OFF ((u16)0x5C) -#define HFA384x_FD_ADDRESS3_OFF ((u16)0x62) -#define HFA384x_FD_SEQCONTROL_OFF ((u16)0x68) -#define HFA384x_FD_ADDRESS4_OFF ((u16)0x6A) -#define HFA384x_FD_DATALEN_OFF ((u16)0x70) -/*-------------------------------------------------------------------- -802.3 Header (offset 72-7F) ---------------------------------------------------------------------*/ -#define HFA384x_FD_DESTADDRESS_OFF ((u16)0x72) -#define HFA384x_FD_SRCADDRESS_OFF ((u16)0x78) -#define HFA384x_FD_DATALENGTH_OFF ((u16)0x7E) +typedef struct hfa384x_dbmcommsquality { + u16 CQdbm_currBSS; + u16 ASLdbm_currBSS; + u16 ANLdbm_currFC; +} __attribute__ ((packed)) hfa384x_dbmcommsquality_t; /*-------------------------------------------------------------------- FRAME STRUCTURES: Communication Frames @@ -1573,51 +442,46 @@ FRAME STRUCTURES: Communication Frames Communication Frames: Transmit Frames --------------------------------------------------------------------*/ /*-- Communication Frame: Transmit Frame Structure --*/ -typedef struct hfa384x_tx_frame -{ - u16 status; - u16 reserved1; - u16 reserved2; - u32 sw_support; - u8 tx_retrycount; - u8 tx_rate; - u16 tx_control; +typedef struct hfa384x_tx_frame { + u16 status; + u16 reserved1; + u16 reserved2; + u32 sw_support; + u8 tx_retrycount; + u8 tx_rate; + u16 tx_control; /*-- 802.11 Header Information --*/ - u16 frame_control; - u16 duration_id; - u8 address1[6]; - u8 address2[6]; - u8 address3[6]; - u16 sequence_control; - u8 address4[6]; - u16 data_len; /* little endian format */ + u16 frame_control; + u16 duration_id; + u8 address1[6]; + u8 address2[6]; + u8 address3[6]; + u16 sequence_control; + u8 address4[6]; + u16 data_len; /* little endian format */ /*-- 802.3 Header Information --*/ - u8 dest_addr[6]; - u8 src_addr[6]; - u16 data_length; /* big endian format */ -} __WLAN_ATTRIB_PACK__ hfa384x_tx_frame_t; + u8 dest_addr[6]; + u8 src_addr[6]; + u16 data_length; /* big endian format */ +} __attribute__ ((packed)) hfa384x_tx_frame_t; /*-------------------------------------------------------------------- Communication Frames: Field Masks for Transmit Frames --------------------------------------------------------------------*/ /*-- Status Field --*/ -#define HFA384x_TXSTATUS_ACKERR ((u16)BIT5) -#define HFA384x_TXSTATUS_FORMERR ((u16)BIT3) -#define HFA384x_TXSTATUS_DISCON ((u16)BIT2) -#define HFA384x_TXSTATUS_AGEDERR ((u16)BIT1) -#define HFA384x_TXSTATUS_RETRYERR ((u16)BIT0) +#define HFA384x_TXSTATUS_ACKERR ((u16)BIT(5)) +#define HFA384x_TXSTATUS_FORMERR ((u16)BIT(3)) +#define HFA384x_TXSTATUS_DISCON ((u16)BIT(2)) +#define HFA384x_TXSTATUS_AGEDERR ((u16)BIT(1)) +#define HFA384x_TXSTATUS_RETRYERR ((u16)BIT(0)) /*-- Transmit Control Field --*/ -#define HFA384x_TX_CFPOLL ((u16)BIT12) -#define HFA384x_TX_PRST ((u16)BIT11) -#define HFA384x_TX_MACPORT ((u16)(BIT10 | BIT9 | BIT8)) -#define HFA384x_TX_NOENCRYPT ((u16)BIT7) -#define HFA384x_TX_RETRYSTRAT ((u16)(BIT6 | BIT5)) -#define HFA384x_TX_STRUCTYPE ((u16)(BIT4 | BIT3)) -#define HFA384x_TX_TXEX ((u16)BIT2) -#define HFA384x_TX_TXOK ((u16)BIT1) +#define HFA384x_TX_MACPORT ((u16)(BIT(10) | BIT(9) | BIT(8))) +#define HFA384x_TX_STRUCTYPE ((u16)(BIT(4) | BIT(3))) +#define HFA384x_TX_TXEX ((u16)BIT(2)) +#define HFA384x_TX_TXOK ((u16)BIT(1)) /*-------------------------------------------------------------------- Communication Frames: Test/Get/Set Field Values for Transmit Frames --------------------------------------------------------------------*/ @@ -1628,83 +492,53 @@ Communication Frames: Test/Get/Set Field Values for Transmit Frames HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\ HFA384x_TXSTATUS_RETRYERR)) -#define HFA384x_TXSTATUS_ISACKERR(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_ACKERR)) -#define HFA384x_TXSTATUS_ISFORMERR(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_FORMERR)) -#define HFA384x_TXSTATUS_ISDISCON(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_DISCON)) -#define HFA384x_TXSTATUS_ISAGEDERR(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_AGEDERR)) -#define HFA384x_TXSTATUS_ISRETRYERR(v) ((u16)(((u16)(v)) & HFA384x_TXSTATUS_RETRYERR)) +#define HFA384x_TX_SET(v, m, s) ((((u16)(v))<<((u16)(s)))&((u16)(m))) -#define HFA384x_TX_GET(v,m,s) ((((u16)(v))&((u16)(m)))>>((u16)(s))) -#define HFA384x_TX_SET(v,m,s) ((((u16)(v))<<((u16)(s)))&((u16)(m))) - -#define HFA384x_TX_CFPOLL_GET(v) HFA384x_TX_GET(v, HFA384x_TX_CFPOLL,12) -#define HFA384x_TX_CFPOLL_SET(v) HFA384x_TX_SET(v, HFA384x_TX_CFPOLL,12) -#define HFA384x_TX_PRST_GET(v) HFA384x_TX_GET(v, HFA384x_TX_PRST,11) -#define HFA384x_TX_PRST_SET(v) HFA384x_TX_SET(v, HFA384x_TX_PRST,11) -#define HFA384x_TX_MACPORT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_MACPORT, 8) #define HFA384x_TX_MACPORT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8) -#define HFA384x_TX_NOENCRYPT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_NOENCRYPT, 7) -#define HFA384x_TX_NOENCRYPT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_NOENCRYPT, 7) -#define HFA384x_TX_RETRYSTRAT_GET(v) HFA384x_TX_GET(v, HFA384x_TX_RETRYSTRAT, 5) -#define HFA384x_TX_RETRYSTRAT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_RETRYSTRAT, 5) -#define HFA384x_TX_STRUCTYPE_GET(v) HFA384x_TX_GET(v, HFA384x_TX_STRUCTYPE, 3) #define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, HFA384x_TX_STRUCTYPE, 3) -#define HFA384x_TX_TXEX_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXEX, 2) #define HFA384x_TX_TXEX_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXEX, 2) -#define HFA384x_TX_TXOK_GET(v) HFA384x_TX_GET(v, HFA384x_TX_TXOK, 1) #define HFA384x_TX_TXOK_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXOK, 1) /*-------------------------------------------------------------------- Communication Frames: Receive Frames --------------------------------------------------------------------*/ /*-- Communication Frame: Receive Frame Structure --*/ -typedef struct hfa384x_rx_frame -{ +typedef struct hfa384x_rx_frame { /*-- MAC rx descriptor (hfa384x byte order) --*/ - u16 status; - u32 time; - u8 silence; - u8 signal; - u8 rate; - u8 rx_flow; - u16 reserved1; - u16 reserved2; + u16 status; + u32 time; + u8 silence; + u8 signal; + u8 rate; + u8 rx_flow; + u16 reserved1; + u16 reserved2; /*-- 802.11 Header Information (802.11 byte order) --*/ - u16 frame_control; - u16 duration_id; - u8 address1[6]; - u8 address2[6]; - u8 address3[6]; - u16 sequence_control; - u8 address4[6]; - u16 data_len; /* hfa384x (little endian) format */ + u16 frame_control; + u16 duration_id; + u8 address1[6]; + u8 address2[6]; + u8 address3[6]; + u16 sequence_control; + u8 address4[6]; + u16 data_len; /* hfa384x (little endian) format */ /*-- 802.3 Header Information --*/ - u8 dest_addr[6]; - u8 src_addr[6]; - u16 data_length; /* IEEE? (big endian) format */ -} __WLAN_ATTRIB_PACK__ hfa384x_rx_frame_t; + u8 dest_addr[6]; + u8 src_addr[6]; + u16 data_length; /* IEEE? (big endian) format */ +} __attribute__ ((packed)) hfa384x_rx_frame_t; /*-------------------------------------------------------------------- Communication Frames: Field Masks for Receive Frames --------------------------------------------------------------------*/ -/*-- Offsets --------*/ -#define HFA384x_RX_DATA_LEN_OFF ((u16)44) -#define HFA384x_RX_80211HDR_OFF ((u16)14) -#define HFA384x_RX_DATA_OFF ((u16)60) /*-- Status Fields --*/ -#define HFA384x_RXSTATUS_MSGTYPE ((u16)(BIT15 | BIT14 | BIT13)) -#define HFA384x_RXSTATUS_MACPORT ((u16)(BIT10 | BIT9 | BIT8)) -#define HFA384x_RXSTATUS_UNDECR ((u16)BIT1) -#define HFA384x_RXSTATUS_FCSERR ((u16)BIT0) +#define HFA384x_RXSTATUS_MACPORT ((u16)(BIT(10) | BIT(9) | BIT(8))) +#define HFA384x_RXSTATUS_FCSERR ((u16)BIT(0)) /*-------------------------------------------------------------------- Communication Frames: Test/Get/Set Field Values for Receive Frames --------------------------------------------------------------------*/ -#define HFA384x_RXSTATUS_MSGTYPE_GET(value) ((u16)((((u16)(value)) & HFA384x_RXSTATUS_MSGTYPE) >> 13)) -#define HFA384x_RXSTATUS_MSGTYPE_SET(value) ((u16)(((u16)(value)) << 13)) #define HFA384x_RXSTATUS_MACPORT_GET(value) ((u16)((((u16)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8)) -#define HFA384x_RXSTATUS_MACPORT_SET(value) ((u16)(((u16)(value)) << 8)) -#define HFA384x_RXSTATUS_ISUNDECR(value) ((u16)(((u16)(value)) & HFA384x_RXSTATUS_UNDECR)) #define HFA384x_RXSTATUS_ISFCSERR(value) ((u16)(((u16)(value)) & HFA384x_RXSTATUS_FCSERR)) /*-------------------------------------------------------------------- FRAME STRUCTURES: Information Types and Information Frame Structures @@ -1712,7 +546,6 @@ Communication Frames: Test/Get/Set Field Values for Receive Frames Information Types --------------------------------------------------------------------*/ #define HFA384x_IT_HANDOVERADDR ((u16)0xF000UL) -#define HFA384x_IT_HANDOVERDEAUTHADDRESS ((u16)0xF001UL)//AP 1.3.7 #define HFA384x_IT_COMMTALLIES ((u16)0xF100UL) #define HFA384x_IT_SCANRESULTS ((u16)0xF101UL) #define HFA384x_IT_CHINFORESULTS ((u16)0xF102UL) @@ -1730,128 +563,110 @@ Information Frames Structures ---------------------------------------------------------------------- Information Frames: Notification Frame Structures --------------------------------------------------------------------*/ -/*-- Notification Frame,MAC Mgmt: Handover Address --*/ -typedef struct hfa384x_HandoverAddr -{ - u16 framelen; - u16 infotype; - u8 handover_addr[WLAN_BSSID_LEN]; -} __WLAN_ATTRIB_PACK__ hfa384x_HandoverAddr_t; /*-- Inquiry Frame, Diagnose: Communication Tallies --*/ -typedef struct hfa384x_CommTallies16 -{ - u16 txunicastframes; - u16 txmulticastframes; - u16 txfragments; - u16 txunicastoctets; - u16 txmulticastoctets; - u16 txdeferredtrans; - u16 txsingleretryframes; - u16 txmultipleretryframes; - u16 txretrylimitexceeded; - u16 txdiscards; - u16 rxunicastframes; - u16 rxmulticastframes; - u16 rxfragments; - u16 rxunicastoctets; - u16 rxmulticastoctets; - u16 rxfcserrors; - u16 rxdiscardsnobuffer; - u16 txdiscardswrongsa; - u16 rxdiscardswepundecr; - u16 rxmsginmsgfrag; - u16 rxmsginbadmsgfrag; -} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies16_t; +typedef struct hfa384x_CommTallies16 { + u16 txunicastframes; + u16 txmulticastframes; + u16 txfragments; + u16 txunicastoctets; + u16 txmulticastoctets; + u16 txdeferredtrans; + u16 txsingleretryframes; + u16 txmultipleretryframes; + u16 txretrylimitexceeded; + u16 txdiscards; + u16 rxunicastframes; + u16 rxmulticastframes; + u16 rxfragments; + u16 rxunicastoctets; + u16 rxmulticastoctets; + u16 rxfcserrors; + u16 rxdiscardsnobuffer; + u16 txdiscardswrongsa; + u16 rxdiscardswepundecr; + u16 rxmsginmsgfrag; + u16 rxmsginbadmsgfrag; +} __attribute__ ((packed)) hfa384x_CommTallies16_t; -typedef struct hfa384x_CommTallies32 -{ - u32 txunicastframes; - u32 txmulticastframes; - u32 txfragments; - u32 txunicastoctets; - u32 txmulticastoctets; - u32 txdeferredtrans; - u32 txsingleretryframes; - u32 txmultipleretryframes; - u32 txretrylimitexceeded; - u32 txdiscards; - u32 rxunicastframes; - u32 rxmulticastframes; - u32 rxfragments; - u32 rxunicastoctets; - u32 rxmulticastoctets; - u32 rxfcserrors; - u32 rxdiscardsnobuffer; - u32 txdiscardswrongsa; - u32 rxdiscardswepundecr; - u32 rxmsginmsgfrag; - u32 rxmsginbadmsgfrag; -} __WLAN_ATTRIB_PACK__ hfa384x_CommTallies32_t; +typedef struct hfa384x_CommTallies32 { + u32 txunicastframes; + u32 txmulticastframes; + u32 txfragments; + u32 txunicastoctets; + u32 txmulticastoctets; + u32 txdeferredtrans; + u32 txsingleretryframes; + u32 txmultipleretryframes; + u32 txretrylimitexceeded; + u32 txdiscards; + u32 rxunicastframes; + u32 rxmulticastframes; + u32 rxfragments; + u32 rxunicastoctets; + u32 rxmulticastoctets; + u32 rxfcserrors; + u32 rxdiscardsnobuffer; + u32 txdiscardswrongsa; + u32 rxdiscardswepundecr; + u32 rxmsginmsgfrag; + u32 rxmsginbadmsgfrag; +} __attribute__ ((packed)) hfa384x_CommTallies32_t; /*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/ -typedef struct hfa384x_ScanResultSub -{ - u16 chid; - u16 anl; - u16 sl; - u8 bssid[WLAN_BSSID_LEN]; - u16 bcnint; - u16 capinfo; - hfa384x_bytestr32_t ssid; - u8 supprates[10]; /* 802.11 info element */ - u16 proberesp_rate; -} __WLAN_ATTRIB_PACK__ hfa384x_ScanResultSub_t; +typedef struct hfa384x_ScanResultSub { + u16 chid; + u16 anl; + u16 sl; + u8 bssid[WLAN_BSSID_LEN]; + u16 bcnint; + u16 capinfo; + hfa384x_bytestr32_t ssid; + u8 supprates[10]; /* 802.11 info element */ + u16 proberesp_rate; +} __attribute__ ((packed)) hfa384x_ScanResultSub_t; -typedef struct hfa384x_ScanResult -{ - u16 rsvd; - u16 scanreason; - hfa384x_ScanResultSub_t - result[HFA384x_SCANRESULT_MAX]; -} __WLAN_ATTRIB_PACK__ hfa384x_ScanResult_t; +typedef struct hfa384x_ScanResult { + u16 rsvd; + u16 scanreason; + hfa384x_ScanResultSub_t result[HFA384x_SCANRESULT_MAX]; +} __attribute__ ((packed)) hfa384x_ScanResult_t; /*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ -typedef struct hfa384x_ChInfoResultSub -{ - u16 chid; - u16 anl; - u16 pnl; - u16 active; -} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResultSub_t; +typedef struct hfa384x_ChInfoResultSub { + u16 chid; + u16 anl; + u16 pnl; + u16 active; +} __attribute__ ((packed)) hfa384x_ChInfoResultSub_t; -#define HFA384x_CHINFORESULT_BSSACTIVE BIT0 -#define HFA384x_CHINFORESULT_PCFACTIVE BIT1 +#define HFA384x_CHINFORESULT_BSSACTIVE BIT(0) +#define HFA384x_CHINFORESULT_PCFACTIVE BIT(1) -typedef struct hfa384x_ChInfoResult -{ - u16 scanchannels; - hfa384x_ChInfoResultSub_t - result[HFA384x_CHINFORESULT_MAX]; -} __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResult_t; +typedef struct hfa384x_ChInfoResult { + u16 scanchannels; + hfa384x_ChInfoResultSub_t result[HFA384x_CHINFORESULT_MAX]; +} __attribute__ ((packed)) hfa384x_ChInfoResult_t; /*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ -typedef struct hfa384x_HScanResultSub -{ - u16 chid; - u16 anl; - u16 sl; - u8 bssid[WLAN_BSSID_LEN]; - u16 bcnint; - u16 capinfo; - hfa384x_bytestr32_t ssid; - u8 supprates[10]; /* 802.11 info element */ - u16 proberesp_rate; - u16 atim; -} __WLAN_ATTRIB_PACK__ hfa384x_HScanResultSub_t; +typedef struct hfa384x_HScanResultSub { + u16 chid; + u16 anl; + u16 sl; + u8 bssid[WLAN_BSSID_LEN]; + u16 bcnint; + u16 capinfo; + hfa384x_bytestr32_t ssid; + u8 supprates[10]; /* 802.11 info element */ + u16 proberesp_rate; + u16 atim; +} __attribute__ ((packed)) hfa384x_HScanResultSub_t; -typedef struct hfa384x_HScanResult -{ - u16 nresult; - u16 rsvd; - hfa384x_HScanResultSub_t - result[HFA384x_HSCANRESULT_MAX]; -} __WLAN_ATTRIB_PACK__ hfa384x_HScanResult_t; +typedef struct hfa384x_HScanResult { + u16 nresult; + u16 rsvd; + hfa384x_HScanResultSub_t result[HFA384x_HSCANRESULT_MAX]; +} __attribute__ ((packed)) hfa384x_HScanResult_t; /*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/ @@ -1863,100 +678,67 @@ typedef struct hfa384x_HScanResult #define HFA384x_LINK_AP_INRANGE ((u16)5) #define HFA384x_LINK_ASSOCFAIL ((u16)6) -typedef struct hfa384x_LinkStatus -{ - u16 linkstatus; -} __WLAN_ATTRIB_PACK__ hfa384x_LinkStatus_t; - +typedef struct hfa384x_LinkStatus { + u16 linkstatus; +} __attribute__ ((packed)) hfa384x_LinkStatus_t; /*-- Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/ #define HFA384x_ASSOCSTATUS_STAASSOC ((u16)1) #define HFA384x_ASSOCSTATUS_REASSOC ((u16)2) -#define HFA384x_ASSOCSTATUS_DISASSOC ((u16)3) -#define HFA384x_ASSOCSTATUS_ASSOCFAIL ((u16)4) #define HFA384x_ASSOCSTATUS_AUTHFAIL ((u16)5) -typedef struct hfa384x_AssocStatus -{ - u16 assocstatus; - u8 sta_addr[WLAN_ADDR_LEN]; +typedef struct hfa384x_AssocStatus { + u16 assocstatus; + u8 sta_addr[ETH_ALEN]; /* old_ap_addr is only valid if assocstatus == 2 */ - u8 old_ap_addr[WLAN_ADDR_LEN]; - u16 reason; - u16 reserved; -} __WLAN_ATTRIB_PACK__ hfa384x_AssocStatus_t; + u8 old_ap_addr[ETH_ALEN]; + u16 reason; + u16 reserved; +} __attribute__ ((packed)) hfa384x_AssocStatus_t; /*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/ -typedef struct hfa384x_AuthRequest -{ - u8 sta_addr[WLAN_ADDR_LEN]; - u16 algorithm; -} __WLAN_ATTRIB_PACK__ hfa384x_AuthReq_t; - -/*-- Unsolicited Frame, MAC Mgmt: AssocRequest (AP Only) --*/ - -typedef struct hfa384x_AssocRequest -{ - u8 sta_addr[WLAN_ADDR_LEN]; - u16 type; - u8 wpa_data[80]; -} __WLAN_ATTRIB_PACK__ hfa384x_AssocReq_t; - - -#define HFA384x_ASSOCREQ_TYPE_ASSOC 0 -#define HFA384x_ASSOCREQ_TYPE_REASSOC 1 - -/*-- Unsolicited Frame, MAC Mgmt: MIC Failure (AP Only) --*/ - -typedef struct hfa384x_MicFailure -{ - u8 sender[WLAN_ADDR_LEN]; - u8 dest[WLAN_ADDR_LEN]; -} __WLAN_ATTRIB_PACK__ hfa384x_MicFailure_t; +typedef struct hfa384x_AuthRequest { + u8 sta_addr[ETH_ALEN]; + u16 algorithm; +} __attribute__ ((packed)) hfa384x_AuthReq_t; /*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/ -typedef struct hfa384x_PSUserCount -{ - u16 usercnt; -} __WLAN_ATTRIB_PACK__ hfa384x_PSUserCount_t; +typedef struct hfa384x_PSUserCount { + u16 usercnt; +} __attribute__ ((packed)) hfa384x_PSUserCount_t; -typedef struct hfa384x_KeyIDChanged -{ - u8 sta_addr[WLAN_ADDR_LEN]; - u16 keyid; -} __WLAN_ATTRIB_PACK__ hfa384x_KeyIDChanged_t; +typedef struct hfa384x_KeyIDChanged { + u8 sta_addr[ETH_ALEN]; + u16 keyid; +} __attribute__ ((packed)) hfa384x_KeyIDChanged_t; /*-- Collection of all Inf frames ---------------*/ typedef union hfa384x_infodata { - hfa384x_CommTallies16_t commtallies16; - hfa384x_CommTallies32_t commtallies32; - hfa384x_ScanResult_t scanresult; - hfa384x_ChInfoResult_t chinforesult; - hfa384x_HScanResult_t hscanresult; - hfa384x_LinkStatus_t linkstatus; - hfa384x_AssocStatus_t assocstatus; - hfa384x_AuthReq_t authreq; - hfa384x_PSUserCount_t psusercnt; - hfa384x_KeyIDChanged_t keyidchanged; -} __WLAN_ATTRIB_PACK__ hfa384x_infodata_t; + hfa384x_CommTallies16_t commtallies16; + hfa384x_CommTallies32_t commtallies32; + hfa384x_ScanResult_t scanresult; + hfa384x_ChInfoResult_t chinforesult; + hfa384x_HScanResult_t hscanresult; + hfa384x_LinkStatus_t linkstatus; + hfa384x_AssocStatus_t assocstatus; + hfa384x_AuthReq_t authreq; + hfa384x_PSUserCount_t psusercnt; + hfa384x_KeyIDChanged_t keyidchanged; +} __attribute__ ((packed)) hfa384x_infodata_t; -typedef struct hfa384x_InfFrame -{ - u16 framelen; - u16 infotype; - hfa384x_infodata_t info; -} __WLAN_ATTRIB_PACK__ hfa384x_InfFrame_t; +typedef struct hfa384x_InfFrame { + u16 framelen; + u16 infotype; + hfa384x_infodata_t info; +} __attribute__ ((packed)) hfa384x_InfFrame_t; /*-------------------------------------------------------------------- USB Packet structures and constants. --------------------------------------------------------------------*/ -/* Should be sent to the ctrlout endpoint */ -#define HFA384x_USB_ENBULKIN 6 - /* Should be sent to the bulkout endpoint */ #define HFA384x_USB_TXFRM 0 #define HFA384x_USB_CMDREQ 1 @@ -1966,7 +748,6 @@ USB Packet structures and constants. #define HFA384x_USB_RMEMREQ 5 /* Received from the bulkin endpoint */ -#define HFA384x_USB_ISFRM(a) (!((a) & 0x8000)) #define HFA384x_USB_ISTXFRM(a) (((a) & 0x9000) == 0x1000) #define HFA384x_USB_ISRXFRM(a) (!((a) & 0x9000)) #define HFA384x_USB_INFOFRM 0x8000 @@ -1982,380 +763,135 @@ USB Packet structures and constants. /* Request (bulk OUT) packet contents */ typedef struct hfa384x_usb_txfrm { - hfa384x_tx_frame_t desc; - u8 data[WLAN_DATA_MAXLEN]; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_txfrm_t; + hfa384x_tx_frame_t desc; + u8 data[WLAN_DATA_MAXLEN]; +} __attribute__ ((packed)) hfa384x_usb_txfrm_t; typedef struct hfa384x_usb_cmdreq { - u16 type; - u16 cmd; - u16 parm0; - u16 parm1; - u16 parm2; - u8 pad[54]; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdreq_t; + u16 type; + u16 cmd; + u16 parm0; + u16 parm1; + u16 parm2; + u8 pad[54]; +} __attribute__ ((packed)) hfa384x_usb_cmdreq_t; typedef struct hfa384x_usb_wridreq { - u16 type; - u16 frmlen; - u16 rid; - u8 data[HFA384x_RIDDATA_MAXLEN]; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_wridreq_t; + u16 type; + u16 frmlen; + u16 rid; + u8 data[HFA384x_RIDDATA_MAXLEN]; +} __attribute__ ((packed)) hfa384x_usb_wridreq_t; typedef struct hfa384x_usb_rridreq { - u16 type; - u16 frmlen; - u16 rid; - u8 pad[58]; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridreq_t; + u16 type; + u16 frmlen; + u16 rid; + u8 pad[58]; +} __attribute__ ((packed)) hfa384x_usb_rridreq_t; typedef struct hfa384x_usb_wmemreq { - u16 type; - u16 frmlen; - u16 offset; - u16 page; - u8 data[HFA384x_USB_RWMEM_MAXLEN]; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_wmemreq_t; + u16 type; + u16 frmlen; + u16 offset; + u16 page; + u8 data[HFA384x_USB_RWMEM_MAXLEN]; +} __attribute__ ((packed)) hfa384x_usb_wmemreq_t; typedef struct hfa384x_usb_rmemreq { - u16 type; - u16 frmlen; - u16 offset; - u16 page; - u8 pad[56]; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemreq_t; + u16 type; + u16 frmlen; + u16 offset; + u16 page; + u8 pad[56]; +} __attribute__ ((packed)) hfa384x_usb_rmemreq_t; /*------------------------------------*/ /* Response (bulk IN) packet contents */ typedef struct hfa384x_usb_rxfrm { - hfa384x_rx_frame_t desc; - u8 data[WLAN_DATA_MAXLEN]; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_rxfrm_t; + hfa384x_rx_frame_t desc; + u8 data[WLAN_DATA_MAXLEN]; +} __attribute__ ((packed)) hfa384x_usb_rxfrm_t; typedef struct hfa384x_usb_infofrm { - u16 type; - hfa384x_InfFrame_t info; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_infofrm_t; + u16 type; + hfa384x_InfFrame_t info; +} __attribute__ ((packed)) hfa384x_usb_infofrm_t; typedef struct hfa384x_usb_statusresp { - u16 type; - u16 status; - u16 resp0; - u16 resp1; - u16 resp2; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdresp_t; + u16 type; + u16 status; + u16 resp0; + u16 resp1; + u16 resp2; +} __attribute__ ((packed)) hfa384x_usb_cmdresp_t; typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t; typedef struct hfa384x_usb_rridresp { - u16 type; - u16 frmlen; - u16 rid; - u8 data[HFA384x_RIDDATA_MAXLEN]; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_rridresp_t; + u16 type; + u16 frmlen; + u16 rid; + u8 data[HFA384x_RIDDATA_MAXLEN]; +} __attribute__ ((packed)) hfa384x_usb_rridresp_t; typedef hfa384x_usb_cmdresp_t hfa384x_usb_wmemresp_t; typedef struct hfa384x_usb_rmemresp { - u16 type; - u16 frmlen; - u8 data[HFA384x_USB_RWMEM_MAXLEN]; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemresp_t; + u16 type; + u16 frmlen; + u8 data[HFA384x_USB_RWMEM_MAXLEN]; +} __attribute__ ((packed)) hfa384x_usb_rmemresp_t; typedef struct hfa384x_usb_bufavail { - u16 type; - u16 frmlen; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_bufavail_t; + u16 type; + u16 frmlen; +} __attribute__ ((packed)) hfa384x_usb_bufavail_t; typedef struct hfa384x_usb_error { - u16 type; - u16 errortype; -} __WLAN_ATTRIB_PACK__ hfa384x_usb_error_t; + u16 type; + u16 errortype; +} __attribute__ ((packed)) hfa384x_usb_error_t; /*----------------------------------------------------------*/ /* Unions for packaging all the known packet types together */ typedef union hfa384x_usbout { - u16 type; - hfa384x_usb_txfrm_t txfrm; - hfa384x_usb_cmdreq_t cmdreq; - hfa384x_usb_wridreq_t wridreq; - hfa384x_usb_rridreq_t rridreq; - hfa384x_usb_wmemreq_t wmemreq; - hfa384x_usb_rmemreq_t rmemreq; -} __WLAN_ATTRIB_PACK__ hfa384x_usbout_t; + u16 type; + hfa384x_usb_txfrm_t txfrm; + hfa384x_usb_cmdreq_t cmdreq; + hfa384x_usb_wridreq_t wridreq; + hfa384x_usb_rridreq_t rridreq; + hfa384x_usb_wmemreq_t wmemreq; + hfa384x_usb_rmemreq_t rmemreq; +} __attribute__ ((packed)) hfa384x_usbout_t; typedef union hfa384x_usbin { - u16 type; - hfa384x_usb_rxfrm_t rxfrm; - hfa384x_usb_txfrm_t txfrm; - hfa384x_usb_infofrm_t infofrm; - hfa384x_usb_cmdresp_t cmdresp; - hfa384x_usb_wridresp_t wridresp; - hfa384x_usb_rridresp_t rridresp; - hfa384x_usb_wmemresp_t wmemresp; - hfa384x_usb_rmemresp_t rmemresp; - hfa384x_usb_bufavail_t bufavail; - hfa384x_usb_error_t usberror; - u8 boguspad[3000]; -} __WLAN_ATTRIB_PACK__ hfa384x_usbin_t; - -/*-------------------------------------------------------------------- -PD record structures. ---------------------------------------------------------------------*/ - -typedef struct hfa384x_pdr_pcb_partnum -{ - u8 num[8]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_partnum_t; - -typedef struct hfa384x_pdr_pcb_tracenum -{ - u8 num[8]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_tracenum_t; - -typedef struct hfa384x_pdr_nic_serial -{ - u8 num[12]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_serial_t; - -typedef struct hfa384x_pdr_mkk_measurements -{ - double carrier_freq; - double occupied_band; - double power_density; - double tx_spur_f1; - double tx_spur_f2; - double tx_spur_f3; - double tx_spur_f4; - double tx_spur_l1; - double tx_spur_l2; - double tx_spur_l3; - double tx_spur_l4; - double rx_spur_f1; - double rx_spur_f2; - double rx_spur_l1; - double rx_spur_l2; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_measurements_t; - -typedef struct hfa384x_pdr_nic_ramsize -{ - u8 size[12]; /* units of KB */ -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_ramsize_t; - -typedef struct hfa384x_pdr_mfisuprange -{ - u16 id; - u16 variant; - u16 bottom; - u16 top; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mfisuprange_t; - -typedef struct hfa384x_pdr_cfisuprange -{ - u16 id; - u16 variant; - u16 bottom; - u16 top; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_cfisuprange_t; - -typedef struct hfa384x_pdr_nicid -{ - u16 id; - u16 variant; - u16 major; - u16 minor; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nicid_t; - - -typedef struct hfa384x_pdr_refdac_measurements -{ - u16 value[0]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_measurements_t; - -typedef struct hfa384x_pdr_vgdac_measurements -{ - u16 value[0]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_measurements_t; - -typedef struct hfa384x_pdr_level_comp_measurements -{ - u16 value[0]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_compc_measurements_t; - -typedef struct hfa384x_pdr_mac_address -{ - u8 addr[6]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mac_address_t; - -typedef struct hfa384x_pdr_mkk_callname -{ - u8 callname[8]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_callname_t; - -typedef struct hfa384x_pdr_regdomain -{ - u16 numdomains; - u16 domain[5]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_regdomain_t; - -typedef struct hfa384x_pdr_allowed_channel -{ - u16 ch_bitmap; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_allowed_channel_t; - -typedef struct hfa384x_pdr_default_channel -{ - u16 channel; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_default_channel_t; - -typedef struct hfa384x_pdr_privacy_option -{ - u16 available; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_privacy_option_t; - -typedef struct hfa384x_pdr_temptype -{ - u16 type; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_temptype_t; - -typedef struct hfa384x_pdr_refdac_setup -{ - u16 ch_value[14]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_setup_t; - -typedef struct hfa384x_pdr_vgdac_setup -{ - u16 ch_value[14]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_setup_t; - -typedef struct hfa384x_pdr_level_comp_setup -{ - u16 ch_value[14]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_comp_setup_t; - -typedef struct hfa384x_pdr_trimdac_setup -{ - u16 trimidac; - u16 trimqdac; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_trimdac_setup_t; - -typedef struct hfa384x_pdr_ifr_setting -{ - u16 value[3]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_ifr_setting_t; - -typedef struct hfa384x_pdr_rfr_setting -{ - u16 value[3]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_rfr_setting_t; - -typedef struct hfa384x_pdr_hfa3861_baseline -{ - u16 value[50]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_baseline_t; - -typedef struct hfa384x_pdr_hfa3861_shadow -{ - u32 value[32]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_shadow_t; - -typedef struct hfa384x_pdr_hfa3861_ifrf -{ - u32 value[20]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_ifrf_t; - -typedef struct hfa384x_pdr_hfa3861_chcalsp -{ - u16 value[14]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcalsp_t; - -typedef struct hfa384x_pdr_hfa3861_chcali -{ - u16 value[17]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcali_t; - -typedef struct hfa384x_pdr_hfa3861_nic_config -{ - u16 config_bitmap; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_config_t; - -typedef struct hfa384x_pdr_hfo_delay -{ - u8 hfo_delay; -} __WLAN_ATTRIB_PACK__ hfa384x_hfo_delay_t; - -typedef struct hfa384x_pdr_hfa3861_manf_testsp -{ - u16 value[30]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testsp_t; - -typedef struct hfa384x_pdr_hfa3861_manf_testi -{ - u16 value[30]; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testi_t; - -typedef struct hfa384x_end_of_pda -{ - u16 crc; -} __WLAN_ATTRIB_PACK__ hfa384x_pdr_end_of_pda_t; - -typedef struct hfa384x_pdrec -{ - u16 len; /* in words */ - u16 code; - union pdr { - hfa384x_pdr_pcb_partnum_t pcb_partnum; - hfa384x_pdr_pcb_tracenum_t pcb_tracenum; - hfa384x_pdr_nic_serial_t nic_serial; - hfa384x_pdr_mkk_measurements_t mkk_measurements; - hfa384x_pdr_nic_ramsize_t nic_ramsize; - hfa384x_pdr_mfisuprange_t mfisuprange; - hfa384x_pdr_cfisuprange_t cfisuprange; - hfa384x_pdr_nicid_t nicid; - hfa384x_pdr_refdac_measurements_t refdac_measurements; - hfa384x_pdr_vgdac_measurements_t vgdac_measurements; - hfa384x_pdr_level_compc_measurements_t level_compc_measurements; - hfa384x_pdr_mac_address_t mac_address; - hfa384x_pdr_mkk_callname_t mkk_callname; - hfa384x_pdr_regdomain_t regdomain; - hfa384x_pdr_allowed_channel_t allowed_channel; - hfa384x_pdr_default_channel_t default_channel; - hfa384x_pdr_privacy_option_t privacy_option; - hfa384x_pdr_temptype_t temptype; - hfa384x_pdr_refdac_setup_t refdac_setup; - hfa384x_pdr_vgdac_setup_t vgdac_setup; - hfa384x_pdr_level_comp_setup_t level_comp_setup; - hfa384x_pdr_trimdac_setup_t trimdac_setup; - hfa384x_pdr_ifr_setting_t ifr_setting; - hfa384x_pdr_rfr_setting_t rfr_setting; - hfa384x_pdr_hfa3861_baseline_t hfa3861_baseline; - hfa384x_pdr_hfa3861_shadow_t hfa3861_shadow; - hfa384x_pdr_hfa3861_ifrf_t hfa3861_ifrf; - hfa384x_pdr_hfa3861_chcalsp_t hfa3861_chcalsp; - hfa384x_pdr_hfa3861_chcali_t hfa3861_chcali; - hfa384x_pdr_nic_config_t nic_config; - hfa384x_hfo_delay_t hfo_delay; - hfa384x_pdr_hfa3861_manf_testsp_t hfa3861_manf_testsp; - hfa384x_pdr_hfa3861_manf_testi_t hfa3861_manf_testi; - hfa384x_pdr_end_of_pda_t end_of_pda; - - } data; -} __WLAN_ATTRIB_PACK__ hfa384x_pdrec_t; - + u16 type; + hfa384x_usb_rxfrm_t rxfrm; + hfa384x_usb_txfrm_t txfrm; + hfa384x_usb_infofrm_t infofrm; + hfa384x_usb_cmdresp_t cmdresp; + hfa384x_usb_wridresp_t wridresp; + hfa384x_usb_rridresp_t rridresp; + hfa384x_usb_wmemresp_t wmemresp; + hfa384x_usb_rmemresp_t rmemresp; + hfa384x_usb_bufavail_t bufavail; + hfa384x_usb_error_t usberror; + u8 boguspad[3000]; +} __attribute__ ((packed)) hfa384x_usbin_t; #ifdef __KERNEL__ /*-------------------------------------------------------------------- --- MAC state structure, argument to all functions -- --- Also, a collection of support types -- --------------------------------------------------------------------*/ -typedef struct hfa384x_statusresult -{ - u16 status; - u16 resp0; - u16 resp1; - u16 resp2; +typedef struct hfa384x_statusresult { + u16 status; + u16 resp0; + u16 resp1; + u16 resp2; } hfa384x_cmdresult_t; /* USB Control Exchange (CTLX): @@ -2365,20 +901,16 @@ typedef struct hfa384x_statusresult /* The following hfa384x_* structures are arguments to * the usercb() for the different CTLX types. */ -typedef hfa384x_cmdresult_t hfa384x_wridresult_t; -typedef hfa384x_cmdresult_t hfa384x_wmemresult_t; - -typedef struct hfa384x_rridresult -{ - u16 rid; - const void *riddata; - unsigned int riddata_len; +typedef struct hfa384x_rridresult { + u16 rid; + const void *riddata; + unsigned int riddata_len; } hfa384x_rridresult_t; enum ctlx_state { - CTLX_START = 0, /* Start state, not queued */ + CTLX_START = 0, /* Start state, not queued */ - CTLX_COMPLETE, /* CTLX successfully completed */ + CTLX_COMPLETE, /* CTLX successfully completed */ CTLX_REQ_FAILED, /* OUT URB completed w/ error */ CTLX_PENDING, /* Queued, data valid */ @@ -2386,114 +918,98 @@ enum ctlx_state { CTLX_REQ_COMPLETE, /* OUT URB complete */ CTLX_RESP_COMPLETE /* IN URB received */ }; -typedef enum ctlx_state CTLX_STATE; +typedef enum ctlx_state CTLX_STATE; struct hfa384x_usbctlx; struct hfa384x; -typedef void (*ctlx_cmdcb_t)( struct hfa384x*, const struct hfa384x_usbctlx* ); +typedef void (*ctlx_cmdcb_t) (struct hfa384x *, const struct hfa384x_usbctlx *); -typedef void (*ctlx_usercb_t)( - struct hfa384x *hw, - void *ctlxresult, - void *usercb_data); +typedef void (*ctlx_usercb_t) (struct hfa384x *hw, + void *ctlxresult, void *usercb_data); -typedef struct hfa384x_usbctlx -{ - struct list_head list; +typedef struct hfa384x_usbctlx { + struct list_head list; - size_t outbufsize; - hfa384x_usbout_t outbuf; /* pkt buf for OUT */ - hfa384x_usbin_t inbuf; /* pkt buf for IN(a copy) */ + size_t outbufsize; + hfa384x_usbout_t outbuf; /* pkt buf for OUT */ + hfa384x_usbin_t inbuf; /* pkt buf for IN(a copy) */ - CTLX_STATE state; /* Tracks running state */ + CTLX_STATE state; /* Tracks running state */ - struct completion done; - volatile int reapable; /* Food for the reaper task */ + struct completion done; + volatile int reapable; /* Food for the reaper task */ - ctlx_cmdcb_t cmdcb; /* Async command callback */ - ctlx_usercb_t usercb; /* Async user callback, */ - void *usercb_data; /* at CTLX completion */ + ctlx_cmdcb_t cmdcb; /* Async command callback */ + ctlx_usercb_t usercb; /* Async user callback, */ + void *usercb_data; /* at CTLX completion */ - int variant; /* Identifies cmd variant */ + int variant; /* Identifies cmd variant */ } hfa384x_usbctlx_t; -typedef struct hfa384x_usbctlxq -{ - spinlock_t lock; - struct list_head pending; - struct list_head active; - struct list_head completing; - struct list_head reapable; +typedef struct hfa384x_usbctlxq { + spinlock_t lock; + struct list_head pending; + struct list_head active; + struct list_head completing; + struct list_head reapable; } hfa384x_usbctlxq_t; -typedef struct hfa484x_metacmd -{ - u16 cmd; +typedef struct hfa484x_metacmd { + u16 cmd; - u16 parm0; - u16 parm1; - u16 parm2; + u16 parm0; + u16 parm1; + u16 parm2; hfa384x_cmdresult_t result; } hfa384x_metacmd_t; -#define MAX_PRISM2_GRP_ADDR 16 #define MAX_GRP_ADDR 32 -#define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */ +#define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */ -#define MM_SAT_PCF (BIT14) -#define MM_GCSD_PCF (BIT15) -#define MM_GCSD_PCF_EB (BIT14 | BIT15) - -#define WLAN_STATE_STOPPED 0 /* Network is not active. */ -#define WLAN_STATE_STARTED 1 /* Network has been started. */ - -#define WLAN_AUTH_MAX 60 /* Max. # of authenticated stations. */ -#define WLAN_ACCESS_MAX 60 /* Max. # of stations in an access list. */ -#define WLAN_ACCESS_NONE 0 /* No stations may be authenticated. */ -#define WLAN_ACCESS_ALL 1 /* All stations may be authenticated. */ -#define WLAN_ACCESS_ALLOW 2 /* Authenticate only "allowed" stations. */ -#define WLAN_ACCESS_DENY 3 /* Do not authenticate "denied" stations. */ +#define WLAN_AUTH_MAX 60 /* Max. # of authenticated stations. */ +#define WLAN_ACCESS_MAX 60 /* Max. # of stations in an access list. */ +#define WLAN_ACCESS_NONE 0 /* No stations may be authenticated. */ +#define WLAN_ACCESS_ALL 1 /* All stations may be authenticated. */ +#define WLAN_ACCESS_ALLOW 2 /* Authenticate only "allowed" stations. */ +#define WLAN_ACCESS_DENY 3 /* Do not authenticate "denied" stations. */ /* XXX These are going away ASAP */ -typedef struct prism2sta_authlist -{ - unsigned int cnt; - u8 addr[WLAN_AUTH_MAX][WLAN_ADDR_LEN]; - u8 assoc[WLAN_AUTH_MAX]; +typedef struct prism2sta_authlist { + unsigned int cnt; + u8 addr[WLAN_AUTH_MAX][ETH_ALEN]; + u8 assoc[WLAN_AUTH_MAX]; } prism2sta_authlist_t; -typedef struct prism2sta_accesslist -{ - unsigned int modify; - unsigned int cnt; - u8 addr[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; - unsigned int cnt1; - u8 addr1[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; +typedef struct prism2sta_accesslist { + unsigned int modify; + unsigned int cnt; + u8 addr[WLAN_ACCESS_MAX][ETH_ALEN]; + unsigned int cnt1; + u8 addr1[WLAN_ACCESS_MAX][ETH_ALEN]; } prism2sta_accesslist_t; -typedef struct hfa384x -{ +typedef struct hfa384x { /* USB support data */ - struct usb_device *usb; - struct urb rx_urb; - struct sk_buff *rx_urb_skb; - struct urb tx_urb; - struct urb ctlx_urb; - hfa384x_usbout_t txbuff; - hfa384x_usbctlxq_t ctlxq; - struct timer_list reqtimer; - struct timer_list resptimer; + struct usb_device *usb; + struct urb rx_urb; + struct sk_buff *rx_urb_skb; + struct urb tx_urb; + struct urb ctlx_urb; + hfa384x_usbout_t txbuff; + hfa384x_usbctlxq_t ctlxq; + struct timer_list reqtimer; + struct timer_list resptimer; - struct timer_list throttle; + struct timer_list throttle; - struct tasklet_struct reaper_bh; - struct tasklet_struct completion_bh; + struct tasklet_struct reaper_bh; + struct tasklet_struct completion_bh; - struct work_struct usb_work; + struct work_struct usb_work; - unsigned long usb_flags; + unsigned long usb_flags; #define THROTTLE_RX 0 #define THROTTLE_TX 1 #define WORK_RX_HALT 2 @@ -2501,292 +1017,168 @@ typedef struct hfa384x #define WORK_RX_RESUME 4 #define WORK_TX_RESUME 5 - unsigned short req_timer_done:1; - unsigned short resp_timer_done:1; + unsigned short req_timer_done:1; + unsigned short resp_timer_done:1; - int endp_in; - int endp_out; + int endp_in; + int endp_out; - int sniff_fcs; - int sniff_channel; - int sniff_truncate; - int sniffhdr; + int sniff_fcs; + int sniff_channel; + int sniff_truncate; + int sniffhdr; - wait_queue_head_t cmdq; /* wait queue itself */ + wait_queue_head_t cmdq; /* wait queue itself */ /* Controller state */ - u32 state; - u32 isap; - u8 port_enabled[HFA384x_NUMPORTS_MAX]; + u32 state; + u32 isap; + u8 port_enabled[HFA384x_NUMPORTS_MAX]; /* Download support */ - unsigned int dlstate; - hfa384x_downloadbuffer_t bufinfo; - u16 dltimeout; + unsigned int dlstate; + hfa384x_downloadbuffer_t bufinfo; + u16 dltimeout; - int scanflag; /* to signal scan comlete */ - int join_ap; /* are we joined to a specific ap */ - int join_retries; /* number of join retries till we fail */ - hfa384x_JoinRequest_data_t joinreq; /* join request saved data */ + int scanflag; /* to signal scan comlete */ + int join_ap; /* are we joined to a specific ap */ + int join_retries; /* number of join retries till we fail */ + hfa384x_JoinRequest_data_t joinreq; /* join request saved data */ - wlandevice_t *wlandev; + wlandevice_t *wlandev; /* Timer to allow for the deferred processing of linkstatus messages */ - struct work_struct link_bh; + struct work_struct link_bh; - struct work_struct commsqual_bh; - hfa384x_commsquality_t qual; - struct timer_list commsqual_timer; + struct work_struct commsqual_bh; + hfa384x_commsquality_t qual; + struct timer_list commsqual_timer; u16 link_status; u16 link_status_new; - struct sk_buff_head authq; + struct sk_buff_head authq; /* And here we have stuff that used to be in priv */ /* State variables */ - unsigned int presniff_port_type; - u16 presniff_wepflags; - u32 dot11_desired_bss_type; + unsigned int presniff_port_type; + u16 presniff_wepflags; + u32 dot11_desired_bss_type; - int dbmadjust; + int dbmadjust; /* Group Addresses - right now, there are up to a total - of MAX_GRP_ADDR group addresses */ - u8 dot11_grp_addr[MAX_GRP_ADDR][WLAN_ADDR_LEN]; - unsigned int dot11_grpcnt; + of MAX_GRP_ADDR group addresses */ + u8 dot11_grp_addr[MAX_GRP_ADDR][ETH_ALEN]; + unsigned int dot11_grpcnt; /* Component Identities */ - hfa384x_compident_t ident_nic; - hfa384x_compident_t ident_pri_fw; - hfa384x_compident_t ident_sta_fw; - hfa384x_compident_t ident_ap_fw; - u16 mm_mods; + hfa384x_compident_t ident_nic; + hfa384x_compident_t ident_pri_fw; + hfa384x_compident_t ident_sta_fw; + hfa384x_compident_t ident_ap_fw; + u16 mm_mods; /* Supplier compatibility ranges */ - hfa384x_caplevel_t cap_sup_mfi; - hfa384x_caplevel_t cap_sup_cfi; - hfa384x_caplevel_t cap_sup_pri; - hfa384x_caplevel_t cap_sup_sta; - hfa384x_caplevel_t cap_sup_ap; + hfa384x_caplevel_t cap_sup_mfi; + hfa384x_caplevel_t cap_sup_cfi; + hfa384x_caplevel_t cap_sup_pri; + hfa384x_caplevel_t cap_sup_sta; + hfa384x_caplevel_t cap_sup_ap; /* Actor compatibility ranges */ - hfa384x_caplevel_t cap_act_pri_cfi; /* pri f/w to controller interface */ - hfa384x_caplevel_t cap_act_sta_cfi; /* sta f/w to controller interface */ - hfa384x_caplevel_t cap_act_sta_mfi; /* sta f/w to modem interface */ - hfa384x_caplevel_t cap_act_ap_cfi; /* ap f/w to controller interface */ - hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */ + hfa384x_caplevel_t cap_act_pri_cfi; /* pri f/w to controller interface */ + hfa384x_caplevel_t cap_act_sta_cfi; /* sta f/w to controller interface */ + hfa384x_caplevel_t cap_act_sta_mfi; /* sta f/w to modem interface */ + hfa384x_caplevel_t cap_act_ap_cfi; /* ap f/w to controller interface */ + hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */ - u32 psusercount; /* Power save user count. */ - hfa384x_CommTallies32_t tallies; /* Communication tallies. */ - u8 comment[WLAN_COMMENT_MAX+1]; /* User comment */ + u32 psusercount; /* Power save user count. */ + hfa384x_CommTallies32_t tallies; /* Communication tallies. */ + u8 comment[WLAN_COMMENT_MAX + 1]; /* User comment */ /* Channel Info request results (AP only) */ struct { - atomic_t done; - u8 count; - hfa384x_ChInfoResult_t results; + atomic_t done; + u8 count; + hfa384x_ChInfoResult_t results; } channel_info; - hfa384x_InfFrame_t *scanresults; + hfa384x_InfFrame_t *scanresults; - - prism2sta_authlist_t authlist; /* Authenticated station list. */ - unsigned int accessmode; /* Access mode. */ - prism2sta_accesslist_t allow; /* Allowed station list. */ - prism2sta_accesslist_t deny; /* Denied station list. */ + prism2sta_authlist_t authlist; /* Authenticated station list. */ + unsigned int accessmode; /* Access mode. */ + prism2sta_accesslist_t allow; /* Allowed station list. */ + prism2sta_accesslist_t deny; /* Denied station list. */ } hfa384x_t; -/*=============================================================*/ -/*--- Function Declarations -----------------------------------*/ -/*=============================================================*/ -void -hfa384x_create( - hfa384x_t *hw, - struct usb_device *usb); - +void hfa384x_create(hfa384x_t *hw, struct usb_device *usb); void hfa384x_destroy(hfa384x_t *hw); int -hfa384x_corereset( hfa384x_t *hw, int holdtime, int settletime, int genesis); -int -hfa384x_drvr_chinforesults( hfa384x_t *hw); -int -hfa384x_drvr_commtallies( hfa384x_t *hw); -int -hfa384x_drvr_disable(hfa384x_t *hw, u16 macport); -int -hfa384x_drvr_enable(hfa384x_t *hw, u16 macport); -int -hfa384x_drvr_flashdl_enable(hfa384x_t *hw); -int -hfa384x_drvr_flashdl_disable(hfa384x_t *hw); -int -hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void* buf, u32 len); -int -hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len); -int -hfa384x_drvr_handover( hfa384x_t *hw, u8 *addr); -int -hfa384x_drvr_hostscanresults( hfa384x_t *hw); -int -hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd); -int -hfa384x_drvr_mmi_read(hfa384x_t *hw, u32 address, u32 *result); -int -hfa384x_drvr_mmi_write(hfa384x_t *hw, u32 address, u32 data); -int -hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr); -int -hfa384x_drvr_ramdl_disable(hfa384x_t *hw); -int -hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void* buf, u32 len); -int -hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len); -int -hfa384x_drvr_scanresults( hfa384x_t *hw); +hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis); +int hfa384x_drvr_commtallies(hfa384x_t *hw); +int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport); +int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport); +int hfa384x_drvr_flashdl_enable(hfa384x_t *hw); +int hfa384x_drvr_flashdl_disable(hfa384x_t *hw); +int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len); +int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len); +int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr); +int hfa384x_drvr_ramdl_disable(hfa384x_t *hw); +int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len); +int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len); +int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len); -int -hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len); - -static inline int -hfa384x_drvr_getconfig16(hfa384x_t *hw, u16 rid, void *val) +static inline int hfa384x_drvr_getconfig16(hfa384x_t *hw, u16 rid, void *val) { - int result = 0; + int result = 0; result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(u16)); - if ( result == 0 ) { - *((u16*)val) = hfa384x2host_16(*((u16*)val)); - } + if (result == 0) + *((u16 *) val) = le16_to_cpu(*((u16 *) val)); return result; } -static inline int -hfa384x_drvr_getconfig32(hfa384x_t *hw, u16 rid, void *val) +static inline int hfa384x_drvr_setconfig16(hfa384x_t *hw, u16 rid, u16 val) { - int result = 0; - - result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(u32)); - if ( result == 0 ) { - *((u32*)val) = hfa384x2host_32(*((u32*)val)); - } - - return result; -} - -static inline int -hfa384x_drvr_setconfig16(hfa384x_t *hw, u16 rid, u16 val) -{ - u16 value = host2hfa384x_16(val); - return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value)); -} - -static inline int -hfa384x_drvr_setconfig32(hfa384x_t *hw, u16 rid, u32 val) -{ - u32 value = host2hfa384x_32(val); + u16 value = cpu_to_le16(val); return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value)); } int -hfa384x_drvr_getconfig_async(hfa384x_t *hw, - u16 rid, - ctlx_usercb_t usercb, - void *usercb_data); +hfa384x_drvr_getconfig_async(hfa384x_t *hw, + u16 rid, ctlx_usercb_t usercb, void *usercb_data); int hfa384x_drvr_setconfig_async(hfa384x_t *hw, - u16 rid, - void *buf, - u16 len, - ctlx_usercb_t usercb, - void *usercb_data); + u16 rid, + void *buf, + u16 len, ctlx_usercb_t usercb, void *usercb_data); static inline int hfa384x_drvr_setconfig16_async(hfa384x_t *hw, u16 rid, u16 val) { - u16 value = host2hfa384x_16(val); + u16 value = cpu_to_le16(val); return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), - NULL , NULL); -} - -static inline int -hfa384x_drvr_setconfig32_async(hfa384x_t *hw, u16 rid, u32 val) -{ - u32 value = host2hfa384x_32(val); - return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), - NULL , NULL); + NULL, NULL); } +int hfa384x_drvr_start(hfa384x_t *hw); +int hfa384x_drvr_stop(hfa384x_t *hw); +int +hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, + p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); +void hfa384x_tx_timeout(wlandevice_t *wlandev); +int hfa384x_cmd_initialize(hfa384x_t *hw); +int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport); +int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport); +int hfa384x_cmd_allocate(hfa384x_t *hw, u16 len); +int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable); int -hfa384x_drvr_start(hfa384x_t *hw); -int -hfa384x_drvr_stop(hfa384x_t *hw); -int -hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); -void -hfa384x_tx_timeout(wlandevice_t *wlandev); - -int -hfa384x_cmd_initialize(hfa384x_t *hw); -int -hfa384x_cmd_enable(hfa384x_t *hw, u16 macport); -int -hfa384x_cmd_disable(hfa384x_t *hw, u16 macport); -int -hfa384x_cmd_diagnose(hfa384x_t *hw); -int -hfa384x_cmd_allocate(hfa384x_t *hw, u16 len); -int -hfa384x_cmd_transmit(hfa384x_t *hw, u16 reclaim, u16 qos, u16 fid); -int -hfa384x_cmd_clearpersist(hfa384x_t *hw, u16 fid); -int -hfa384x_cmd_access(hfa384x_t *hw, u16 write, u16 rid, void *buf, u16 len); -int -hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable); -int -hfa384x_cmd_download( - hfa384x_t *hw, - u16 mode, - u16 lowaddr, - u16 highaddr, - u16 codelen); -int -hfa384x_cmd_aux_enable(hfa384x_t *hw, int force); -int -hfa384x_cmd_aux_disable(hfa384x_t *hw); -int -hfa384x_copy_from_bap( - hfa384x_t *hw, - u16 bap, - u16 id, - u16 offset, - void *buf, - unsigned int len); -int -hfa384x_copy_to_bap( - hfa384x_t *hw, - u16 bap, - u16 id, - u16 offset, - void *buf, - unsigned int len); -void -hfa384x_copy_from_aux( - hfa384x_t *hw, - u32 cardaddr, - u32 auxctl, - void *buf, - unsigned int len); -void -hfa384x_copy_to_aux( - hfa384x_t *hw, - u32 cardaddr, - u32 auxctl, - void *buf, - unsigned int len); +hfa384x_cmd_download(hfa384x_t *hw, + u16 mode, u16 lowaddr, u16 highaddr, u16 codelen); #endif /* __KERNEL__ */ -#endif /* _HFA384x_H */ +#endif /* _HFA384x_H */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 8a75b50f8635..888198c9a106 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -110,10 +110,6 @@ * -------------------------------------------------------------------- */ -/*================================================================*/ -/* System Includes */ -#define WLAN_DBVAR prism2_debug - #include #include @@ -130,8 +126,7 @@ #include #include #include - -#include "wlan_compat.h" +#include #define SUBMIT_URB(u,f) usb_submit_urb(u,f) @@ -150,69 +145,43 @@ #include "hfa384x.h" #include "prism2mgmt.h" -/*================================================================*/ -/* Local Constants */ - -enum cmd_mode -{ - DOWAIT = 0, - DOASYNC +enum cmd_mode { + DOWAIT = 0, + DOASYNC }; typedef enum cmd_mode CMD_MODE; #define THROTTLE_JIFFIES (HZ/8) - -/*================================================================*/ -/* Local Macros */ +#define URB_ASYNC_UNLINK 0 +#define USB_QUEUE_BULK 0 #define ROUNDUP64(a) (((a)+63)&~63) -/*================================================================*/ -/* Local Types */ - -/*================================================================*/ -/* Local Static Definitions */ -extern int prism2_debug; - -/*================================================================*/ -/* Local Function Declarations */ - #ifdef DEBUG_USB -static void -dbprint_urb(struct urb* urb); +static void dbprint_urb(struct urb *urb); #endif static void -hfa384x_int_rxmonitor( - wlandevice_t *wlandev, - hfa384x_usb_rxfrm_t *rxfrm); +hfa384x_int_rxmonitor(wlandevice_t *wlandev, hfa384x_usb_rxfrm_t *rxfrm); -static void -hfa384x_usb_defer(struct work_struct *data); +static void hfa384x_usb_defer(struct work_struct *data); -static int -submit_rx_urb(hfa384x_t *hw, gfp_t flags); +static int submit_rx_urb(hfa384x_t *hw, gfp_t flags); -static int -submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t flags); +static int submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t flags); /*---------------------------------------------------*/ /* Callbacks */ -static void -hfa384x_usbout_callback(struct urb *urb); -static void -hfa384x_ctlxout_callback(struct urb *urb); -static void -hfa384x_usbin_callback(struct urb *urb); +static void hfa384x_usbout_callback(struct urb *urb); +static void hfa384x_ctlxout_callback(struct urb *urb); +static void hfa384x_usbin_callback(struct urb *urb); static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); -static void -hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb); +static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb); -static void -hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); +static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin); static void hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout); @@ -223,123 +192,94 @@ static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, /*---------------------------------------------------*/ /* Functions to support the prism2 usb command queue */ -static void -hfa384x_usbctlxq_run(hfa384x_t *hw); +static void hfa384x_usbctlxq_run(hfa384x_t *hw); -static void -hfa384x_usbctlx_reqtimerfn(unsigned long data); +static void hfa384x_usbctlx_reqtimerfn(unsigned long data); -static void -hfa384x_usbctlx_resptimerfn(unsigned long data); +static void hfa384x_usbctlx_resptimerfn(unsigned long data); -static void -hfa384x_usb_throttlefn(unsigned long data); +static void hfa384x_usb_throttlefn(unsigned long data); -static void -hfa384x_usbctlx_completion_task(unsigned long data); +static void hfa384x_usbctlx_completion_task(unsigned long data); -static void -hfa384x_usbctlx_reaper_task(unsigned long data); +static void hfa384x_usbctlx_reaper_task(unsigned long data); -static int -hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); +static int hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); -static void -unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); +static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); -struct usbctlx_completor -{ - int (*complete)(struct usbctlx_completor*); +struct usbctlx_completor { + int (*complete) (struct usbctlx_completor *); }; typedef struct usbctlx_completor usbctlx_completor_t; static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, - hfa384x_usbctlx_t *ctlx, - usbctlx_completor_t *completor); + hfa384x_usbctlx_t *ctlx, + usbctlx_completor_t *completor); static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx); -static void -hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); +static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); -static void -hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); +static void hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx); static int usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, - hfa384x_cmdresult_t *result); + hfa384x_cmdresult_t *result); static void usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, - hfa384x_rridresult_t *result); + hfa384x_rridresult_t *result); /*---------------------------------------------------*/ /* Low level req/resp CTLX formatters and submitters */ static int -hfa384x_docmd( - hfa384x_t *hw, - CMD_MODE mode, - hfa384x_metacmd_t *cmd, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data); +hfa384x_docmd(hfa384x_t *hw, + CMD_MODE mode, + hfa384x_metacmd_t *cmd, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dorrid( - hfa384x_t *hw, - CMD_MODE mode, - u16 rid, - void *riddata, - unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data); +hfa384x_dorrid(hfa384x_t *hw, + CMD_MODE mode, + u16 rid, + void *riddata, + unsigned int riddatalen, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dowrid( - hfa384x_t *hw, - CMD_MODE mode, - u16 rid, - void *riddata, - unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data); +hfa384x_dowrid(hfa384x_t *hw, + CMD_MODE mode, + u16 rid, + void *riddata, + unsigned int riddatalen, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dormem( - hfa384x_t *hw, - CMD_MODE mode, - u16 page, - u16 offset, - void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data); +hfa384x_dormem(hfa384x_t *hw, + CMD_MODE mode, + u16 page, + u16 offset, + void *data, + unsigned int len, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); static int -hfa384x_dowmem( - hfa384x_t *hw, - CMD_MODE mode, - u16 page, - u16 offset, - void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data); +hfa384x_dowmem(hfa384x_t *hw, + CMD_MODE mode, + u16 page, + u16 offset, + void *data, + unsigned int len, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); -static int -hfa384x_isgood_pdrcode(u16 pdrcode); +static int hfa384x_isgood_pdrcode(u16 pdrcode); -/*================================================================*/ -/* Function Definitions */ -static inline const char* ctlxstr(CTLX_STATE s) +static inline const char *ctlxstr(CTLX_STATE s) { - static const char* ctlx_str[] = { + static const char *ctlx_str[] = { "Initial state", "Complete", "Request failed", @@ -352,36 +292,36 @@ static inline const char* ctlxstr(CTLX_STATE s) return ctlx_str[s]; }; - -static inline hfa384x_usbctlx_t* -get_active_ctlx(hfa384x_t *hw) +static inline hfa384x_usbctlx_t *get_active_ctlx(hfa384x_t *hw) { return list_entry(hw->ctlxq.active.next, hfa384x_usbctlx_t, list); } - #ifdef DEBUG_USB -void -dbprint_urb(struct urb* urb) +void dbprint_urb(struct urb *urb) { - WLAN_LOG_DEBUG(3,"urb->pipe=0x%08x\n", urb->pipe); - WLAN_LOG_DEBUG(3,"urb->status=0x%08x\n", urb->status); - WLAN_LOG_DEBUG(3,"urb->transfer_flags=0x%08x\n", urb->transfer_flags); - WLAN_LOG_DEBUG(3,"urb->transfer_buffer=0x%08x\n", (unsigned int)urb->transfer_buffer); - WLAN_LOG_DEBUG(3,"urb->transfer_buffer_length=0x%08x\n", urb->transfer_buffer_length); - WLAN_LOG_DEBUG(3,"urb->actual_length=0x%08x\n", urb->actual_length); - WLAN_LOG_DEBUG(3,"urb->bandwidth=0x%08x\n", urb->bandwidth); - WLAN_LOG_DEBUG(3,"urb->setup_packet(ctl)=0x%08x\n", (unsigned int)urb->setup_packet); - WLAN_LOG_DEBUG(3,"urb->start_frame(iso/irq)=0x%08x\n", urb->start_frame); - WLAN_LOG_DEBUG(3,"urb->interval(irq)=0x%08x\n", urb->interval); - WLAN_LOG_DEBUG(3,"urb->error_count(iso)=0x%08x\n", urb->error_count); - WLAN_LOG_DEBUG(3,"urb->timeout=0x%08x\n", urb->timeout); - WLAN_LOG_DEBUG(3,"urb->context=0x%08x\n", (unsigned int)urb->context); - WLAN_LOG_DEBUG(3,"urb->complete=0x%08x\n", (unsigned int)urb->complete); + pr_debug("urb->pipe=0x%08x\n", urb->pipe); + pr_debug("urb->status=0x%08x\n", urb->status); + pr_debug("urb->transfer_flags=0x%08x\n", urb->transfer_flags); + pr_debug("urb->transfer_buffer=0x%08x\n", + (unsigned int)urb->transfer_buffer); + pr_debug("urb->transfer_buffer_length=0x%08x\n", + urb->transfer_buffer_length); + pr_debug("urb->actual_length=0x%08x\n", urb->actual_length); + pr_debug("urb->bandwidth=0x%08x\n", urb->bandwidth); + pr_debug("urb->setup_packet(ctl)=0x%08x\n", + (unsigned int)urb->setup_packet); + pr_debug("urb->start_frame(iso/irq)=0x%08x\n", + urb->start_frame); + pr_debug("urb->interval(irq)=0x%08x\n", urb->interval); + pr_debug("urb->error_count(iso)=0x%08x\n", urb->error_count); + pr_debug("urb->timeout=0x%08x\n", urb->timeout); + pr_debug("urb->context=0x%08x\n", (unsigned int)urb->context); + pr_debug("urb->complete=0x%08x\n", + (unsigned int)urb->complete); } #endif - /*---------------------------------------------------------------- * submit_rx_urb * @@ -398,14 +338,11 @@ dbprint_urb(struct urb* urb) * Call context: * Any ----------------------------------------------------------------*/ -static int -submit_rx_urb(hfa384x_t *hw, gfp_t memflags) +static int submit_rx_urb(hfa384x_t *hw, gfp_t memflags) { struct sk_buff *skb; int result; - DBFENTER; - skb = dev_alloc_skb(sizeof(hfa384x_usbin_t)); if (skb == NULL) { result = -ENOMEM; @@ -414,21 +351,22 @@ submit_rx_urb(hfa384x_t *hw, gfp_t memflags) /* Post the IN urb */ usb_fill_bulk_urb(&hw->rx_urb, hw->usb, - hw->endp_in, - skb->data, sizeof(hfa384x_usbin_t), - hfa384x_usbin_callback, hw->wlandev); + hw->endp_in, + skb->data, sizeof(hfa384x_usbin_t), + hfa384x_usbin_callback, hw->wlandev); hw->rx_urb_skb = skb; result = -ENOLINK; - if ( !hw->wlandev->hwremoved && !test_bit(WORK_RX_HALT, &hw->usb_flags)) { + if (!hw->wlandev->hwremoved && !test_bit(WORK_RX_HALT, &hw->usb_flags)) { result = SUBMIT_URB(&hw->rx_urb, memflags); /* Check whether we need to reset the RX pipe */ if (result == -EPIPE) { - WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n", - hw->wlandev->netdev->name); - if ( !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) + printk(KERN_WARNING + "%s rx pipe stalled: requesting reset\n", + hw->wlandev->netdev->name); + if (!test_and_set_bit(WORK_RX_HALT, &hw->usb_flags)) schedule_work(&hw->usb_work); } } @@ -439,9 +377,7 @@ submit_rx_urb(hfa384x_t *hw, gfp_t memflags) hw->rx_urb_skb = NULL; } - done: - - DBFEXIT; +done: return result; } @@ -463,24 +399,23 @@ submit_rx_urb(hfa384x_t *hw, gfp_t memflags) * Call context: * Any ----------------------------------------------------------------*/ -static int -submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) +static int submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) { struct net_device *netdev = hw->wlandev->netdev; int result; - DBFENTER; - result = -ENOLINK; - if ( netif_running(netdev) ) { + if (netif_running(netdev)) { - if ( !hw->wlandev->hwremoved && !test_bit(WORK_TX_HALT, &hw->usb_flags) ) { + if (!hw->wlandev->hwremoved + && !test_bit(WORK_TX_HALT, &hw->usb_flags)) { result = SUBMIT_URB(tx_urb, memflags); /* Test whether we need to reset the TX pipe */ if (result == -EPIPE) { - WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", - netdev->name); + printk(KERN_WARNING + "%s tx pipe stalled: requesting reset\n", + netdev->name); set_bit(WORK_TX_HALT, &hw->usb_flags); schedule_work(&hw->usb_work); } else if (result == 0) { @@ -489,8 +424,6 @@ submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) } } - DBFEXIT; - return result; } @@ -510,27 +443,22 @@ submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags) * Call context: * process (by design) ----------------------------------------------------------------*/ -static void -hfa384x_usb_defer(struct work_struct *data) +static void hfa384x_usb_defer(struct work_struct *data) { hfa384x_t *hw = container_of(data, struct hfa384x, usb_work); struct net_device *netdev = hw->wlandev->netdev; - DBFENTER; - /* Don't bother trying to reset anything if the plug * has been pulled ... */ - if ( hw->wlandev->hwremoved ) { - DBFEXIT; + if (hw->wlandev->hwremoved) return; - } /* Reception has stopped: try to reset the input pipe */ if (test_bit(WORK_RX_HALT, &hw->usb_flags)) { int ret; - usb_kill_urb(&hw->rx_urb); /* Cannot be holding spinlock! */ + usb_kill_urb(&hw->rx_urb); /* Cannot be holding spinlock! */ ret = usb_clear_halt(hw->usb, hw->endp_in); if (ret != 0) { @@ -539,14 +467,14 @@ hfa384x_usb_defer(struct work_struct *data) netdev->name, ret); } else { printk(KERN_INFO "%s rx pipe reset complete.\n", - netdev->name); + netdev->name); clear_bit(WORK_RX_HALT, &hw->usb_flags); set_bit(WORK_RX_RESUME, &hw->usb_flags); } } /* Resume receiving data back from the device. */ - if ( test_bit(WORK_RX_RESUME, &hw->usb_flags) ) { + if (test_bit(WORK_RX_RESUME, &hw->usb_flags)) { int ret; ret = submit_rx_urb(hw, GFP_KERNEL); @@ -570,7 +498,7 @@ hfa384x_usb_defer(struct work_struct *data) netdev->name, ret); } else { printk(KERN_INFO "%s tx pipe reset complete.\n", - netdev->name); + netdev->name); clear_bit(WORK_TX_HALT, &hw->usb_flags); set_bit(WORK_TX_RESUME, &hw->usb_flags); @@ -583,14 +511,10 @@ hfa384x_usb_defer(struct work_struct *data) } /* Resume transmitting. */ - if ( test_and_clear_bit(WORK_TX_RESUME, &hw->usb_flags) ) { + if (test_and_clear_bit(WORK_TX_RESUME, &hw->usb_flags)) netif_wake_queue(hw->wlandev->netdev); - } - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_create * @@ -612,11 +536,8 @@ hfa384x_usb_defer(struct work_struct *data) * Call context: * process ----------------------------------------------------------------*/ -void -hfa384x_create( hfa384x_t *hw, struct usb_device *usb) +void hfa384x_create(hfa384x_t *hw, struct usb_device *usb) { - DBFENTER; - memset(hw, 0, sizeof(hfa384x_t)); hw->usb = usb; @@ -638,11 +559,9 @@ hfa384x_create( hfa384x_t *hw, struct usb_device *usb) skb_queue_head_init(&hw->authq); tasklet_init(&hw->reaper_bh, - hfa384x_usbctlx_reaper_task, - (unsigned long)hw); + hfa384x_usbctlx_reaper_task, (unsigned long)hw); tasklet_init(&hw->completion_bh, - hfa384x_usbctlx_completion_task, - (unsigned long)hw); + hfa384x_usbctlx_completion_task, (unsigned long)hw); INIT_WORK(&hw->link_bh, prism2sta_processing_defer); INIT_WORK(&hw->usb_work, hfa384x_usb_defer); @@ -665,15 +584,12 @@ hfa384x_create( hfa384x_t *hw, struct usb_device *usb) hw->link_status = HFA384x_LINK_NOTCONNECTED; hw->state = HFA384x_STATE_INIT; - INIT_WORK(&hw->commsqual_bh, prism2sta_commsqual_defer); + INIT_WORK(&hw->commsqual_bh, prism2sta_commsqual_defer); init_timer(&hw->commsqual_timer); - hw->commsqual_timer.data = (unsigned long) hw; + hw->commsqual_timer.data = (unsigned long)hw; hw->commsqual_timer.function = prism2sta_commsqual_timer; - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_destroy * @@ -696,16 +612,12 @@ hfa384x_create( hfa384x_t *hw, struct usb_device *usb) * Call context: * process ----------------------------------------------------------------*/ -void -hfa384x_destroy( hfa384x_t *hw) +void hfa384x_destroy(hfa384x_t *hw) { struct sk_buff *skb; - DBFENTER; - - if ( hw->state == HFA384x_STATE_RUNNING ) { + if (hw->state == HFA384x_STATE_RUNNING) hfa384x_drvr_stop(hw); - } hw->state = HFA384x_STATE_PREINIT; if (hw->scanresults) { @@ -714,23 +626,16 @@ hfa384x_destroy( hfa384x_t *hw) } /* Now to clean out the auth queue */ - while ( (skb = skb_dequeue(&hw->authq)) ) { - dev_kfree_skb(skb); - } - - DBFEXIT; + while ((skb = skb_dequeue(&hw->authq))) + dev_kfree_skb(skb); } - -/*---------------------------------------------------------------- - */ -static hfa384x_usbctlx_t* usbctlx_alloc(void) +static hfa384x_usbctlx_t *usbctlx_alloc(void) { hfa384x_usbctlx_t *ctlx; ctlx = kmalloc(sizeof(*ctlx), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); - if (ctlx != NULL) - { + if (ctlx != NULL) { memset(ctlx, 0, sizeof(*ctlx)); init_completion(&ctlx->done); } @@ -738,70 +643,58 @@ static hfa384x_usbctlx_t* usbctlx_alloc(void) return ctlx; } - -/*---------------------------------------------------------------- - * -----------------------------------------------------------------*/ static int usbctlx_get_status(const hfa384x_usb_cmdresp_t *cmdresp, - hfa384x_cmdresult_t *result) + hfa384x_cmdresult_t *result) { - DBFENTER; + result->status = le16_to_cpu(cmdresp->status); + result->resp0 = le16_to_cpu(cmdresp->resp0); + result->resp1 = le16_to_cpu(cmdresp->resp1); + result->resp2 = le16_to_cpu(cmdresp->resp2); - result->status = hfa384x2host_16(cmdresp->status); - result->resp0 = hfa384x2host_16(cmdresp->resp0); - result->resp1 = hfa384x2host_16(cmdresp->resp1); - result->resp2 = hfa384x2host_16(cmdresp->resp2); + pr_debug("cmdresult:status=0x%04x " + "resp0=0x%04x resp1=0x%04x resp2=0x%04x\n", + result->status, result->resp0, result->resp1, result->resp2); - WLAN_LOG_DEBUG(4, "cmdresult:status=0x%04x " - "resp0=0x%04x resp1=0x%04x resp2=0x%04x\n", - result->status, - result->resp0, - result->resp1, - result->resp2); - - DBFEXIT; - return (result->status & HFA384x_STATUS_RESULT); + return result->status & HFA384x_STATUS_RESULT; } static void usbctlx_get_rridresult(const hfa384x_usb_rridresp_t *rridresp, - hfa384x_rridresult_t *result) + hfa384x_rridresult_t *result) { - DBFENTER; - - result->rid = hfa384x2host_16(rridresp->rid); + result->rid = le16_to_cpu(rridresp->rid); result->riddata = rridresp->data; - result->riddata_len = ((hfa384x2host_16(rridresp->frmlen) - 1) * 2); + result->riddata_len = ((le16_to_cpu(rridresp->frmlen) - 1) * 2); - DBFEXIT; } - /*---------------------------------------------------------------- * Completor object: * This completor must be passed to hfa384x_usbctlx_complete_sync() * when processing a CTLX that returns a hfa384x_cmdresult_t structure. ----------------------------------------------------------------*/ -struct usbctlx_cmd_completor -{ - usbctlx_completor_t head; +struct usbctlx_cmd_completor { + usbctlx_completor_t head; - const hfa384x_usb_cmdresp_t *cmdresp; - hfa384x_cmdresult_t *result; + const hfa384x_usb_cmdresp_t *cmdresp; + hfa384x_cmdresult_t *result; }; typedef struct usbctlx_cmd_completor usbctlx_cmd_completor_t; static int usbctlx_cmd_completor_fn(usbctlx_completor_t *head) { - usbctlx_cmd_completor_t *complete = (usbctlx_cmd_completor_t*)head; + usbctlx_cmd_completor_t *complete = (usbctlx_cmd_completor_t *) head; return usbctlx_get_status(complete->cmdresp, complete->result); } -static inline usbctlx_completor_t* -init_cmd_completor(usbctlx_cmd_completor_t *completor, - const hfa384x_usb_cmdresp_t *cmdresp, - hfa384x_cmdresult_t *result) +static inline usbctlx_completor_t *init_cmd_completor(usbctlx_cmd_completor_t * + completor, + const + hfa384x_usb_cmdresp_t * + cmdresp, + hfa384x_cmdresult_t * + result) { completor->head.complete = usbctlx_cmd_completor_fn; completor->cmdresp = cmdresp; @@ -814,44 +707,41 @@ init_cmd_completor(usbctlx_cmd_completor_t *completor, * This completor must be passed to hfa384x_usbctlx_complete_sync() * when processing a CTLX that reads a RID. ----------------------------------------------------------------*/ -struct usbctlx_rrid_completor -{ - usbctlx_completor_t head; +struct usbctlx_rrid_completor { + usbctlx_completor_t head; - const hfa384x_usb_rridresp_t *rridresp; - void *riddata; - unsigned int riddatalen; + const hfa384x_usb_rridresp_t *rridresp; + void *riddata; + unsigned int riddatalen; }; typedef struct usbctlx_rrid_completor usbctlx_rrid_completor_t; static int usbctlx_rrid_completor_fn(usbctlx_completor_t *head) { - usbctlx_rrid_completor_t *complete = (usbctlx_rrid_completor_t*)head; + usbctlx_rrid_completor_t *complete = (usbctlx_rrid_completor_t *) head; hfa384x_rridresult_t rridresult; usbctlx_get_rridresult(complete->rridresp, &rridresult); /* Validate the length, note body len calculation in bytes */ - if ( rridresult.riddata_len != complete->riddatalen ) { - WLAN_LOG_WARNING( - "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n", - rridresult.rid, - complete->riddatalen, - rridresult.riddata_len); + if (rridresult.riddata_len != complete->riddatalen) { + printk(KERN_WARNING + "RID len mismatch, rid=0x%04x hlen=%d fwlen=%d\n", + rridresult.rid, + complete->riddatalen, rridresult.riddata_len); return -ENODATA; } - memcpy(complete->riddata, - rridresult.riddata, - complete->riddatalen); + memcpy(complete->riddata, rridresult.riddata, complete->riddatalen); return 0; } -static inline usbctlx_completor_t* -init_rrid_completor(usbctlx_rrid_completor_t *completor, - const hfa384x_usb_rridresp_t *rridresp, - void *riddata, - unsigned int riddatalen) +static inline usbctlx_completor_t *init_rrid_completor(usbctlx_rrid_completor_t + *completor, + const + hfa384x_usb_rridresp_t * + rridresp, void *riddata, + unsigned int riddatalen) { completor->head.complete = usbctlx_rrid_completor_fn; completor->rridresp = rridresp; @@ -878,30 +768,29 @@ typedef usbctlx_cmd_completor_t usbctlx_wmem_completor_t; * Completor object: * Interprets the results of a synchronous memory-read ----------------------------------------------------------------*/ -struct usbctlx_rmem_completor -{ - usbctlx_completor_t head; +struct usbctlx_rmem_completor { + usbctlx_completor_t head; - const hfa384x_usb_rmemresp_t *rmemresp; - void *data; - unsigned int len; + const hfa384x_usb_rmemresp_t *rmemresp; + void *data; + unsigned int len; }; typedef struct usbctlx_rmem_completor usbctlx_rmem_completor_t; static int usbctlx_rmem_completor_fn(usbctlx_completor_t *head) { - usbctlx_rmem_completor_t *complete = (usbctlx_rmem_completor_t*)head; + usbctlx_rmem_completor_t *complete = (usbctlx_rmem_completor_t *) head; - WLAN_LOG_DEBUG(4,"rmemresp:len=%d\n", complete->rmemresp->frmlen); + pr_debug("rmemresp:len=%d\n", complete->rmemresp->frmlen); memcpy(complete->data, complete->rmemresp->data, complete->len); return 0; } -static inline usbctlx_completor_t* -init_rmem_completor(usbctlx_rmem_completor_t *completor, - hfa384x_usb_rmemresp_t *rmemresp, - void *data, - unsigned int len) +static inline usbctlx_completor_t *init_rmem_completor(usbctlx_rmem_completor_t + *completor, + hfa384x_usb_rmemresp_t + *rmemresp, void *data, + unsigned int len) { completor->head.complete = usbctlx_rmem_completor_fn; completor->rmemresp = rmemresp; @@ -931,28 +820,23 @@ init_rmem_completor(usbctlx_rmem_completor_t *completor, * Call context: * interrupt ----------------------------------------------------------------*/ -static void -hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) +static void hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) { - DBFENTER; - - if ( ctlx->usercb != NULL ) { + if (ctlx->usercb != NULL) { hfa384x_cmdresult_t cmdresult; if (ctlx->state != CTLX_COMPLETE) { memset(&cmdresult, 0, sizeof(cmdresult)); - cmdresult.status = HFA384x_STATUS_RESULT_SET(HFA384x_CMD_ERR); + cmdresult.status = + HFA384x_STATUS_RESULT_SET(HFA384x_CMD_ERR); } else { usbctlx_get_status(&ctlx->inbuf.cmdresp, &cmdresult); } ctlx->usercb(hw, &cmdresult, ctlx->usercb_data); } - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_cb_rrid * @@ -973,132 +857,114 @@ hfa384x_cb_status(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) * Call context: * interrupt ----------------------------------------------------------------*/ -static void -hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) +static void hfa384x_cb_rrid(hfa384x_t *hw, const hfa384x_usbctlx_t *ctlx) { - DBFENTER; - - if ( ctlx->usercb != NULL ) { + if (ctlx->usercb != NULL) { hfa384x_rridresult_t rridresult; if (ctlx->state != CTLX_COMPLETE) { memset(&rridresult, 0, sizeof(rridresult)); - rridresult.rid = hfa384x2host_16(ctlx->outbuf.rridreq.rid); + rridresult.rid = + le16_to_cpu(ctlx->outbuf.rridreq.rid); } else { - usbctlx_get_rridresult(&ctlx->inbuf.rridresp, &rridresult); + usbctlx_get_rridresult(&ctlx->inbuf.rridresp, + &rridresult); } ctlx->usercb(hw, &rridresult, ctlx->usercb_data); } - - DBFEXIT; } -static inline int -hfa384x_docmd_wait(hfa384x_t *hw, hfa384x_metacmd_t *cmd) +static inline int hfa384x_docmd_wait(hfa384x_t *hw, hfa384x_metacmd_t *cmd) { return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); } static inline int hfa384x_docmd_async(hfa384x_t *hw, - hfa384x_metacmd_t *cmd, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) + hfa384x_metacmd_t *cmd, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { - return hfa384x_docmd(hw, DOASYNC, cmd, - cmdcb, usercb, usercb_data); + return hfa384x_docmd(hw, DOASYNC, cmd, cmdcb, usercb, usercb_data); } static inline int -hfa384x_dorrid_wait(hfa384x_t *hw, u16 rid, void *riddata, unsigned int riddatalen) +hfa384x_dorrid_wait(hfa384x_t *hw, u16 rid, void *riddata, + unsigned int riddatalen) { return hfa384x_dorrid(hw, DOWAIT, - rid, riddata, riddatalen, - NULL, NULL, NULL); + rid, riddata, riddatalen, NULL, NULL, NULL); } static inline int hfa384x_dorrid_async(hfa384x_t *hw, - u16 rid, void *riddata, unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) + u16 rid, void *riddata, unsigned int riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, void *usercb_data) { return hfa384x_dorrid(hw, DOASYNC, - rid, riddata, riddatalen, - cmdcb, usercb, usercb_data); + rid, riddata, riddatalen, + cmdcb, usercb, usercb_data); } static inline int -hfa384x_dowrid_wait(hfa384x_t *hw, u16 rid, void *riddata, unsigned int riddatalen) +hfa384x_dowrid_wait(hfa384x_t *hw, u16 rid, void *riddata, + unsigned int riddatalen) { return hfa384x_dowrid(hw, DOWAIT, - rid, riddata, riddatalen, - NULL, NULL, NULL); + rid, riddata, riddatalen, NULL, NULL, NULL); } static inline int hfa384x_dowrid_async(hfa384x_t *hw, - u16 rid, void *riddata, unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) + u16 rid, void *riddata, unsigned int riddatalen, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, void *usercb_data) { return hfa384x_dowrid(hw, DOASYNC, - rid, riddata, riddatalen, - cmdcb, usercb, usercb_data); + rid, riddata, riddatalen, + cmdcb, usercb, usercb_data); } static inline int hfa384x_dormem_wait(hfa384x_t *hw, - u16 page, u16 offset, void *data, unsigned int len) + u16 page, u16 offset, void *data, unsigned int len) { return hfa384x_dormem(hw, DOWAIT, - page, offset, data, len, - NULL, NULL, NULL); + page, offset, data, len, NULL, NULL, NULL); } static inline int hfa384x_dormem_async(hfa384x_t *hw, - u16 page, u16 offset, void *data, unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) + u16 page, u16 offset, void *data, unsigned int len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, void *usercb_data) { return hfa384x_dormem(hw, DOASYNC, - page, offset, data, len, - cmdcb, usercb, usercb_data); + page, offset, data, len, + cmdcb, usercb, usercb_data); } static inline int -hfa384x_dowmem_wait( - hfa384x_t *hw, - u16 page, - u16 offset, - void *data, - unsigned int len) +hfa384x_dowmem_wait(hfa384x_t *hw, + u16 page, u16 offset, void *data, unsigned int len) { return hfa384x_dowmem(hw, DOWAIT, - page, offset, data, len, - NULL, NULL, NULL); + page, offset, data, len, NULL, NULL, NULL); } static inline int -hfa384x_dowmem_async( - hfa384x_t *hw, - u16 page, - u16 offset, - void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) +hfa384x_dowmem_async(hfa384x_t *hw, + u16 page, + u16 offset, + void *data, + unsigned int len, + ctlx_cmdcb_t cmdcb, + ctlx_usercb_t usercb, void *usercb_data) { return hfa384x_dowmem(hw, DOASYNC, - page, offset, data, len, - cmdcb, usercb, usercb_data); + page, offset, data, len, + cmdcb, usercb, usercb_data); } /*---------------------------------------------------------------- @@ -1120,16 +986,12 @@ hfa384x_dowmem_async( * Call context: * process ----------------------------------------------------------------*/ -int -hfa384x_cmd_initialize(hfa384x_t *hw) +int hfa384x_cmd_initialize(hfa384x_t *hw) { - int result = 0; - int i; + int result = 0; + int i; hfa384x_metacmd_t cmd; - DBFENTER; - - cmd.cmd = HFA384x_CMDCODE_INIT; cmd.parm0 = 0; cmd.parm1 = 0; @@ -1137,27 +999,21 @@ hfa384x_cmd_initialize(hfa384x_t *hw) result = hfa384x_docmd_wait(hw, &cmd); - - WLAN_LOG_DEBUG(3,"cmdresp.init: " - "status=0x%04x, resp0=0x%04x, " - "resp1=0x%04x, resp2=0x%04x\n", - cmd.result.status, - cmd.result.resp0, - cmd.result.resp1, - cmd.result.resp2); - if ( result == 0 ) { - for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + pr_debug("cmdresp.init: " + "status=0x%04x, resp0=0x%04x, " + "resp1=0x%04x, resp2=0x%04x\n", + cmd.result.status, + cmd.result.resp0, cmd.result.resp1, cmd.result.resp2); + if (result == 0) { + for (i = 0; i < HFA384x_NUMPORTS_MAX; i++) hw->port_enabled[i] = 0; - } } - hw->link_status = HFA384x_LINK_NOTCONNECTED; + hw->link_status = HFA384x_LINK_NOTCONNECTED; - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_cmd_disable * @@ -1180,24 +1036,20 @@ hfa384x_cmd_initialize(hfa384x_t *hw) ----------------------------------------------------------------*/ int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) { - int result = 0; + int result = 0; hfa384x_metacmd_t cmd; - DBFENTER; - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) | - HFA384x_CMD_MACPORT_SET(macport); + HFA384x_CMD_MACPORT_SET(macport); cmd.parm0 = 0; cmd.parm1 = 0; cmd.parm2 = 0; result = hfa384x_docmd_wait(hw, &cmd); - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_cmd_enable * @@ -1220,20 +1072,17 @@ int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport) ----------------------------------------------------------------*/ int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) { - int result = 0; + int result = 0; hfa384x_metacmd_t cmd; - DBFENTER; - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | - HFA384x_CMD_MACPORT_SET(macport); + HFA384x_CMD_MACPORT_SET(macport); cmd.parm0 = 0; cmd.parm1 = 0; cmd.parm2 = 0; result = hfa384x_docmd_wait(hw, &cmd); - DBFEXIT; return result; } @@ -1268,24 +1117,20 @@ int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport) ----------------------------------------------------------------*/ int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) { - int result = 0; + int result = 0; hfa384x_metacmd_t cmd; - DBFENTER; - cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) | - HFA384x_CMD_AINFO_SET(enable); + HFA384x_CMD_AINFO_SET(enable); cmd.parm0 = 0; cmd.parm1 = 0; cmd.parm2 = 0; result = hfa384x_docmd_wait(hw, &cmd); - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_cmd_download * @@ -1325,15 +1170,14 @@ int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable) * process ----------------------------------------------------------------*/ int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr, - u16 highaddr, u16 codelen) + u16 highaddr, u16 codelen) { - int result = 0; + int result = 0; hfa384x_metacmd_t cmd; - DBFENTER; - WLAN_LOG_DEBUG(5, - "mode=%d, lowaddr=0x%04x, highaddr=0x%04x, codelen=%d\n", - mode, lowaddr, highaddr, codelen); + printk(KERN_DEBUG + "mode=%d, lowaddr=0x%04x, highaddr=0x%04x, codelen=%d\n", + mode, lowaddr, highaddr, codelen); cmd.cmd = (HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DOWNLD) | HFA384x_CMD_PROGMODE_SET(mode)); @@ -1344,79 +1188,9 @@ int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr, result = hfa384x_docmd_wait(hw, &cmd); - DBFEXIT; return result; } - -/*---------------------------------------------------------------- -* hfa384x_copy_from_aux -* -* Copies a collection of bytes from the controller memory. The -* Auxiliary port MUST be enabled prior to calling this function. -* We _might_ be in a download state. -* -* Arguments: -* hw device structure -* cardaddr address in hfa384x data space to read -* auxctl address space select -* buf ptr to destination host buffer -* len length of data to transfer (in bytes) -* -* Returns: -* nothing -* -* Side effects: -* buf contains the data copied -* -* Call context: -* process -* interrupt -----------------------------------------------------------------*/ -void -hfa384x_copy_from_aux( - hfa384x_t *hw, u32 cardaddr, u32 auxctl, void *buf, unsigned int len) -{ - DBFENTER; - WLAN_LOG_ERROR("not used in USB.\n"); - DBFEXIT; -} - - -/*---------------------------------------------------------------- -* hfa384x_copy_to_aux -* -* Copies a collection of bytes to the controller memory. The -* Auxiliary port MUST be enabled prior to calling this function. -* We _might_ be in a download state. -* -* Arguments: -* hw device structure -* cardaddr address in hfa384x data space to read -* auxctl address space select -* buf ptr to destination host buffer -* len length of data to transfer (in bytes) -* -* Returns: -* nothing -* -* Side effects: -* Controller memory now contains a copy of buf -* -* Call context: -* process -* interrupt -----------------------------------------------------------------*/ -void -hfa384x_copy_to_aux( - hfa384x_t *hw, u32 cardaddr, u32 auxctl, void *buf, unsigned int len) -{ - DBFENTER; - WLAN_LOG_ERROR("not used in USB.\n"); - DBFEXIT; -} - - /*---------------------------------------------------------------- * hfa384x_corereset * @@ -1442,20 +1216,17 @@ hfa384x_copy_to_aux( ----------------------------------------------------------------*/ int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis) { - int result = 0; + int result = 0; - DBFENTER; - - result=usb_reset_device(hw->usb); - if(result<0) { - WLAN_LOG_ERROR("usb_reset_device() failed, result=%d.\n",result); + result = usb_reset_device(hw->usb); + if (result < 0) { + printk(KERN_ERR "usb_reset_device() failed, result=%d.\n", + result); } - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_usbctlx_complete_sync * @@ -1487,8 +1258,6 @@ static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, unsigned long flags; int result; - DBFENTER; - result = wait_for_completion_interruptible(&ctlx->done); spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -1497,14 +1266,11 @@ static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, * We can only handle the CTLX if the USB disconnect * function has not run yet ... */ - cleanup: - if ( hw->wlandev->hwremoved ) - { +cleanup: + if (hw->wlandev->hwremoved) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); result = -ENODEV; - } - else if ( result != 0 ) - { + } else if (result != 0) { int runqueue = 0; /* @@ -1516,8 +1282,7 @@ static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, * NOTE: We can only delete the timers and * the URB if this CTLX is active. */ - if (ctlx == get_active_ctlx(hw)) - { + if (ctlx == get_active_ctlx(hw)) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); del_singleshot_timer_sync(&hw->reqtimer); @@ -1534,7 +1299,7 @@ static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, * This scenario is so unlikely that I'm * happy with a grubby "goto" solution ... */ - if ( hw->wlandev->hwremoved ) + if (hw->wlandev->hwremoved) goto cleanup; } @@ -1555,9 +1320,9 @@ static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, if (ctlx->state == CTLX_COMPLETE) { result = completor->complete(completor); } else { - WLAN_LOG_WARNING("CTLX[%d] error: state(%s)\n", - hfa384x2host_16(ctlx->outbuf.type), - ctlxstr(ctlx->state)); + printk(KERN_WARNING "CTLX[%d] error: state(%s)\n", + le16_to_cpu(ctlx->outbuf.type), + ctlxstr(ctlx->state)); result = -EIO; } @@ -1566,7 +1331,6 @@ static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, kfree(ctlx); } - DBFEXIT; return result; } @@ -1603,39 +1367,32 @@ static int hfa384x_usbctlx_complete_sync(hfa384x_t *hw, * process ----------------------------------------------------------------*/ static int -hfa384x_docmd( - hfa384x_t *hw, - CMD_MODE mode, - hfa384x_metacmd_t *cmd, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) +hfa384x_docmd(hfa384x_t *hw, + CMD_MODE mode, + hfa384x_metacmd_t *cmd, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { - int result; - hfa384x_usbctlx_t *ctlx; + int result; + hfa384x_usbctlx_t *ctlx; - DBFENTER; ctlx = usbctlx_alloc(); - if ( ctlx == NULL ) { + if (ctlx == NULL) { result = -ENOMEM; goto done; } /* Initialize the command */ - ctlx->outbuf.cmdreq.type = host2hfa384x_16(HFA384x_USB_CMDREQ); - ctlx->outbuf.cmdreq.cmd = host2hfa384x_16(cmd->cmd); - ctlx->outbuf.cmdreq.parm0 = host2hfa384x_16(cmd->parm0); - ctlx->outbuf.cmdreq.parm1 = host2hfa384x_16(cmd->parm1); - ctlx->outbuf.cmdreq.parm2 = host2hfa384x_16(cmd->parm2); + ctlx->outbuf.cmdreq.type = cpu_to_le16(HFA384x_USB_CMDREQ); + ctlx->outbuf.cmdreq.cmd = cpu_to_le16(cmd->cmd); + ctlx->outbuf.cmdreq.parm0 = cpu_to_le16(cmd->parm0); + ctlx->outbuf.cmdreq.parm1 = cpu_to_le16(cmd->parm1); + ctlx->outbuf.cmdreq.parm2 = cpu_to_le16(cmd->parm2); ctlx->outbufsize = sizeof(ctlx->outbuf.cmdreq); - WLAN_LOG_DEBUG(4, "cmdreq: cmd=0x%04x " - "parm0=0x%04x parm1=0x%04x parm2=0x%04x\n", - cmd->cmd, - cmd->parm0, - cmd->parm1, - cmd->parm2); + pr_debug("cmdreq: cmd=0x%04x " + "parm0=0x%04x parm1=0x%04x parm2=0x%04x\n", + cmd->cmd, cmd->parm0, cmd->parm1, cmd->parm2); ctlx->reapable = mode; ctlx->cmdcb = cmdcb; @@ -1648,18 +1405,20 @@ hfa384x_docmd( } else if (mode == DOWAIT) { usbctlx_cmd_completor_t completor; - result = hfa384x_usbctlx_complete_sync( - hw, ctlx, init_cmd_completor(&completor, - &ctlx->inbuf.cmdresp, - &cmd->result) ); + result = + hfa384x_usbctlx_complete_sync(hw, ctlx, + init_cmd_completor(&completor, + &ctlx-> + inbuf. + cmdresp, + &cmd-> + result)); } done: - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_dorrid * @@ -1697,31 +1456,27 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dorrid( - hfa384x_t *hw, - CMD_MODE mode, - u16 rid, - void *riddata, - unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) +hfa384x_dorrid(hfa384x_t *hw, + CMD_MODE mode, + u16 rid, + void *riddata, + unsigned int riddatalen, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { - int result; - hfa384x_usbctlx_t *ctlx; + int result; + hfa384x_usbctlx_t *ctlx; - DBFENTER; ctlx = usbctlx_alloc(); - if ( ctlx == NULL ) { + if (ctlx == NULL) { result = -ENOMEM; goto done; } /* Initialize the command */ - ctlx->outbuf.rridreq.type = host2hfa384x_16(HFA384x_USB_RRIDREQ); + ctlx->outbuf.rridreq.type = cpu_to_le16(HFA384x_USB_RRIDREQ); ctlx->outbuf.rridreq.frmlen = - host2hfa384x_16(sizeof(ctlx->outbuf.rridreq.rid)); - ctlx->outbuf.rridreq.rid = host2hfa384x_16(rid); + cpu_to_le16(sizeof(ctlx->outbuf.rridreq.rid)); + ctlx->outbuf.rridreq.rid = cpu_to_le16(rid); ctlx->outbufsize = sizeof(ctlx->outbuf.rridreq); @@ -1737,19 +1492,18 @@ hfa384x_dorrid( } else if (mode == DOWAIT) { usbctlx_rrid_completor_t completor; - result = hfa384x_usbctlx_complete_sync( - hw, ctlx, init_rrid_completor(&completor, - &ctlx->inbuf.rridresp, - riddata, - riddatalen) ); + result = + hfa384x_usbctlx_complete_sync(hw, ctlx, + init_rrid_completor + (&completor, + &ctlx->inbuf.rridresp, + riddata, riddatalen)); } done: - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_dowrid * @@ -1783,38 +1537,34 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dowrid( - hfa384x_t *hw, - CMD_MODE mode, - u16 rid, - void *riddata, - unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) +hfa384x_dowrid(hfa384x_t *hw, + CMD_MODE mode, + u16 rid, + void *riddata, + unsigned int riddatalen, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { - int result; - hfa384x_usbctlx_t *ctlx; + int result; + hfa384x_usbctlx_t *ctlx; - DBFENTER; ctlx = usbctlx_alloc(); - if ( ctlx == NULL ) { + if (ctlx == NULL) { result = -ENOMEM; goto done; } /* Initialize the command */ - ctlx->outbuf.wridreq.type = host2hfa384x_16(HFA384x_USB_WRIDREQ); - ctlx->outbuf.wridreq.frmlen = host2hfa384x_16( - (sizeof(ctlx->outbuf.wridreq.rid) + - riddatalen + 1) / 2); - ctlx->outbuf.wridreq.rid = host2hfa384x_16(rid); + ctlx->outbuf.wridreq.type = cpu_to_le16(HFA384x_USB_WRIDREQ); + ctlx->outbuf.wridreq.frmlen = cpu_to_le16((sizeof + (ctlx->outbuf.wridreq. + rid) + riddatalen + + 1) / 2); + ctlx->outbuf.wridreq.rid = cpu_to_le16(rid); memcpy(ctlx->outbuf.wridreq.data, riddata, riddatalen); ctlx->outbufsize = sizeof(ctlx->outbuf.wridreq.type) + - sizeof(ctlx->outbuf.wridreq.frmlen) + - sizeof(ctlx->outbuf.wridreq.rid) + - riddatalen; + sizeof(ctlx->outbuf.wridreq.frmlen) + + sizeof(ctlx->outbuf.wridreq.rid) + riddatalen; ctlx->reapable = mode; ctlx->cmdcb = cmdcb; @@ -1829,16 +1579,15 @@ hfa384x_dowrid( usbctlx_wrid_completor_t completor; hfa384x_cmdresult_t wridresult; - result = hfa384x_usbctlx_complete_sync( - hw, - ctlx, - init_wrid_completor(&completor, - &ctlx->inbuf.wridresp, - &wridresult) ); + result = hfa384x_usbctlx_complete_sync(hw, + ctlx, + init_wrid_completor + (&completor, + &ctlx->inbuf.wridresp, + &wridresult)); } done: - DBFEXIT; return result; } @@ -1876,47 +1625,41 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dormem( - hfa384x_t *hw, - CMD_MODE mode, - u16 page, - u16 offset, - void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) +hfa384x_dormem(hfa384x_t *hw, + CMD_MODE mode, + u16 page, + u16 offset, + void *data, + unsigned int len, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { - int result; - hfa384x_usbctlx_t *ctlx; + int result; + hfa384x_usbctlx_t *ctlx; - DBFENTER; ctlx = usbctlx_alloc(); - if ( ctlx == NULL ) { + if (ctlx == NULL) { result = -ENOMEM; goto done; } /* Initialize the command */ - ctlx->outbuf.rmemreq.type = host2hfa384x_16(HFA384x_USB_RMEMREQ); - ctlx->outbuf.rmemreq.frmlen = host2hfa384x_16( - sizeof(ctlx->outbuf.rmemreq.offset) + - sizeof(ctlx->outbuf.rmemreq.page) + - len); - ctlx->outbuf.rmemreq.offset = host2hfa384x_16(offset); - ctlx->outbuf.rmemreq.page = host2hfa384x_16(page); + ctlx->outbuf.rmemreq.type = cpu_to_le16(HFA384x_USB_RMEMREQ); + ctlx->outbuf.rmemreq.frmlen = + cpu_to_le16(sizeof(ctlx->outbuf.rmemreq.offset) + + sizeof(ctlx->outbuf.rmemreq.page) + len); + ctlx->outbuf.rmemreq.offset = cpu_to_le16(offset); + ctlx->outbuf.rmemreq.page = cpu_to_le16(page); ctlx->outbufsize = sizeof(ctlx->outbuf.rmemreq); - WLAN_LOG_DEBUG(4, - "type=0x%04x frmlen=%d offset=0x%04x page=0x%04x\n", - ctlx->outbuf.rmemreq.type, - ctlx->outbuf.rmemreq.frmlen, - ctlx->outbuf.rmemreq.offset, - ctlx->outbuf.rmemreq.page); + printk(KERN_DEBUG + "type=0x%04x frmlen=%d offset=0x%04x page=0x%04x\n", + ctlx->outbuf.rmemreq.type, + ctlx->outbuf.rmemreq.frmlen, + ctlx->outbuf.rmemreq.offset, ctlx->outbuf.rmemreq.page); - WLAN_LOG_DEBUG(4,"pktsize=%zd\n", - ROUNDUP64(sizeof(ctlx->outbuf.rmemreq))); + pr_debug("pktsize=%zd\n", + ROUNDUP64(sizeof(ctlx->outbuf.rmemreq))); ctlx->reapable = mode; ctlx->cmdcb = cmdcb; @@ -1926,23 +1669,21 @@ hfa384x_dormem( result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if ( mode == DOWAIT ) { - usbctlx_rmem_completor_t completor; + } else if (mode == DOWAIT) { + usbctlx_rmem_completor_t completor; - result = hfa384x_usbctlx_complete_sync( - hw, ctlx, init_rmem_completor(&completor, - &ctlx->inbuf.rmemresp, - data, - len) ); + result = + hfa384x_usbctlx_complete_sync(hw, ctlx, + init_rmem_completor + (&completor, + &ctlx->inbuf.rmemresp, data, + len)); } done: - DBFEXIT; return result; } - - /*---------------------------------------------------------------- * hfa384x_dowmem * @@ -1977,45 +1718,39 @@ done: * process (DOWAIT or DOASYNC) ----------------------------------------------------------------*/ static int -hfa384x_dowmem( - hfa384x_t *hw, - CMD_MODE mode, - u16 page, - u16 offset, - void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, - void *usercb_data) +hfa384x_dowmem(hfa384x_t *hw, + CMD_MODE mode, + u16 page, + u16 offset, + void *data, + unsigned int len, + ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) { - int result; - hfa384x_usbctlx_t *ctlx; + int result; + hfa384x_usbctlx_t *ctlx; - DBFENTER; - WLAN_LOG_DEBUG(5, "page=0x%04x offset=0x%04x len=%d\n", - page,offset,len); + pr_debug("page=0x%04x offset=0x%04x len=%d\n", + page, offset, len); ctlx = usbctlx_alloc(); - if ( ctlx == NULL ) { + if (ctlx == NULL) { result = -ENOMEM; goto done; } /* Initialize the command */ - ctlx->outbuf.wmemreq.type = host2hfa384x_16(HFA384x_USB_WMEMREQ); - ctlx->outbuf.wmemreq.frmlen = host2hfa384x_16( - sizeof(ctlx->outbuf.wmemreq.offset) + - sizeof(ctlx->outbuf.wmemreq.page) + - len); - ctlx->outbuf.wmemreq.offset = host2hfa384x_16(offset); - ctlx->outbuf.wmemreq.page = host2hfa384x_16(page); + ctlx->outbuf.wmemreq.type = cpu_to_le16(HFA384x_USB_WMEMREQ); + ctlx->outbuf.wmemreq.frmlen = + cpu_to_le16(sizeof(ctlx->outbuf.wmemreq.offset) + + sizeof(ctlx->outbuf.wmemreq.page) + len); + ctlx->outbuf.wmemreq.offset = cpu_to_le16(offset); + ctlx->outbuf.wmemreq.page = cpu_to_le16(page); memcpy(ctlx->outbuf.wmemreq.data, data, len); ctlx->outbufsize = sizeof(ctlx->outbuf.wmemreq.type) + - sizeof(ctlx->outbuf.wmemreq.frmlen) + - sizeof(ctlx->outbuf.wmemreq.offset) + - sizeof(ctlx->outbuf.wmemreq.page) + - len; + sizeof(ctlx->outbuf.wmemreq.frmlen) + + sizeof(ctlx->outbuf.wmemreq.offset) + + sizeof(ctlx->outbuf.wmemreq.page) + len; ctlx->reapable = mode; ctlx->cmdcb = cmdcb; @@ -2025,24 +1760,22 @@ hfa384x_dowmem( result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if ( mode == DOWAIT ) { - usbctlx_wmem_completor_t completor; - hfa384x_cmdresult_t wmemresult; + } else if (mode == DOWAIT) { + usbctlx_wmem_completor_t completor; + hfa384x_cmdresult_t wmemresult; - result = hfa384x_usbctlx_complete_sync( - hw, - ctlx, - init_wmem_completor(&completor, - &ctlx->inbuf.wmemresp, - &wmemresult) ); + result = hfa384x_usbctlx_complete_sync(hw, + ctlx, + init_wmem_completor + (&completor, + &ctlx->inbuf.wmemresp, + &wmemresult)); } done: - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_drvr_commtallies * @@ -2060,12 +1793,10 @@ done: * Call context: * process ----------------------------------------------------------------*/ -int hfa384x_drvr_commtallies( hfa384x_t *hw ) +int hfa384x_drvr_commtallies(hfa384x_t *hw) { hfa384x_metacmd_t cmd; - DBFENTER; - cmd.cmd = HFA384x_CMDCODE_INQ; cmd.parm0 = HFA384x_IT_COMMTALLIES; cmd.parm1 = 0; @@ -2073,11 +1804,9 @@ int hfa384x_drvr_commtallies( hfa384x_t *hw ) hfa384x_docmd_async(hw, &cmd, NULL, NULL, NULL); - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * hfa384x_drvr_disable * @@ -2102,24 +1831,20 @@ int hfa384x_drvr_commtallies( hfa384x_t *hw ) ----------------------------------------------------------------*/ int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport) { - int result = 0; + int result = 0; - DBFENTER; if ((!hw->isap && macport != 0) || (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || - !(hw->port_enabled[macport]) ){ + !(hw->port_enabled[macport])) { result = -EINVAL; } else { result = hfa384x_cmd_disable(hw, macport); - if ( result == 0 ) { + if (result == 0) hw->port_enabled[macport] = 0; - } } - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_drvr_enable * @@ -2144,24 +1869,20 @@ int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport) ----------------------------------------------------------------*/ int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport) { - int result = 0; + int result = 0; - DBFENTER; if ((!hw->isap && macport != 0) || (hw->isap && !(macport <= HFA384x_PORTID_MAX)) || - (hw->port_enabled[macport]) ){ + (hw->port_enabled[macport])) { result = -EINVAL; } else { result = hfa384x_cmd_enable(hw, macport); - if ( result == 0 ) { + if (result == 0) hw->port_enabled[macport] = 1; - } } - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_drvr_flashdl_enable * @@ -2185,45 +1906,43 @@ int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport) ----------------------------------------------------------------*/ int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) { - int result = 0; - int i; + int result = 0; + int i; - DBFENTER; /* Check that a port isn't active */ - for ( i = 0; i < HFA384x_PORTID_MAX; i++) { - if ( hw->port_enabled[i] ) { - WLAN_LOG_DEBUG(1,"called when port enabled.\n"); + for (i = 0; i < HFA384x_PORTID_MAX; i++) { + if (hw->port_enabled[i]) { + pr_debug("called when port enabled.\n"); return -EINVAL; } } /* Check that we're not already in a download state */ - if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { + if (hw->dlstate != HFA384x_DLSTATE_DISABLED) return -EINVAL; - } /* Retrieve the buffer loc&size and timeout */ - if ( (result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, - &(hw->bufinfo), sizeof(hw->bufinfo))) ) { + if ((result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER, + &(hw->bufinfo), + sizeof(hw->bufinfo)))) { return result; } - hw->bufinfo.page = hfa384x2host_16(hw->bufinfo.page); - hw->bufinfo.offset = hfa384x2host_16(hw->bufinfo.offset); - hw->bufinfo.len = hfa384x2host_16(hw->bufinfo.len); - if ( (result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, - &(hw->dltimeout))) ) { + hw->bufinfo.page = le16_to_cpu(hw->bufinfo.page); + hw->bufinfo.offset = le16_to_cpu(hw->bufinfo.offset); + hw->bufinfo.len = le16_to_cpu(hw->bufinfo.len); + if ((result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME, + &(hw->dltimeout)))) { return result; } - hw->dltimeout = hfa384x2host_16(hw->dltimeout); + hw->dltimeout = le16_to_cpu(hw->dltimeout); - WLAN_LOG_DEBUG(1,"flashdl_enable\n"); + pr_debug("flashdl_enable\n"); hw->dlstate = HFA384x_DLSTATE_FLASHENABLED; - DBFEXIT; + return result; } - /*---------------------------------------------------------------- * hfa384x_drvr_flashdl_disable * @@ -2245,24 +1964,20 @@ int hfa384x_drvr_flashdl_enable(hfa384x_t *hw) ----------------------------------------------------------------*/ int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) { - DBFENTER; /* Check that we're already in the download state */ - if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + if (hw->dlstate != HFA384x_DLSTATE_FLASHENABLED) return -EINVAL; - } - WLAN_LOG_DEBUG(1,"flashdl_enable\n"); + pr_debug("flashdl_enable\n"); /* There isn't much we can do at this point, so I don't */ /* bother w/ the return value */ - hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0, 0); hw->dlstate = HFA384x_DLSTATE_DISABLED; - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * hfa384x_drvr_flashdl_write * @@ -2292,48 +2007,42 @@ int hfa384x_drvr_flashdl_disable(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int -hfa384x_drvr_flashdl_write( - hfa384x_t *hw, - u32 daddr, - void *buf, - u32 len) +int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) { - int result = 0; - u32 dlbufaddr; - int nburns; - u32 burnlen; - u32 burndaddr; - u16 burnlo; - u16 burnhi; - int nwrites; - u8 *writebuf; - u16 writepage; - u16 writeoffset; - u32 writelen; - int i; - int j; + int result = 0; + u32 dlbufaddr; + int nburns; + u32 burnlen; + u32 burndaddr; + u16 burnlo; + u16 burnhi; + int nwrites; + u8 *writebuf; + u16 writepage; + u16 writeoffset; + u32 writelen; + int i; + int j; - DBFENTER; - WLAN_LOG_DEBUG(5,"daddr=0x%08x len=%d\n", daddr, len); + pr_debug("daddr=0x%08x len=%d\n", daddr, len); /* Check that we're in the flash download state */ - if ( hw->dlstate != HFA384x_DLSTATE_FLASHENABLED ) { + if (hw->dlstate != HFA384x_DLSTATE_FLASHENABLED) return -EINVAL; - } - WLAN_LOG_INFO("Download %d bytes to flash @0x%06x\n", len, daddr); + printk(KERN_INFO "Download %d bytes to flash @0x%06x\n", len, daddr); /* Convert to flat address for arithmetic */ /* NOTE: dlbuffer RID stores the address in AUX format */ - dlbufaddr = HFA384x_ADDR_AUX_MKFLAT( - hw->bufinfo.page, hw->bufinfo.offset); - WLAN_LOG_DEBUG(5, - "dlbuf.page=0x%04x dlbuf.offset=0x%04x dlbufaddr=0x%08x\n", - hw->bufinfo.page, hw->bufinfo.offset, dlbufaddr); + dlbufaddr = + HFA384x_ADDR_AUX_MKFLAT(hw->bufinfo.page, hw->bufinfo.offset); + printk(KERN_DEBUG + "dlbuf.page=0x%04x dlbuf.offset=0x%04x dlbufaddr=0x%08x\n", + hw->bufinfo.page, hw->bufinfo.offset, dlbufaddr); #if 0 -WLAN_LOG_WARNING("dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, hw->bufinfo.len, hw->dltimeout); + printk(KERN_WARNING "dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, + hw->bufinfo.len, hw->dltimeout); #endif /* Calculations to determine how many fills of the dlbuffer to do * and how many USB wmemreq's to do for each fill. At this point @@ -2351,74 +2060,60 @@ WLAN_LOG_WARNING("dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr, hw->bufinfo.len, hw- nwrites += (hw->bufinfo.len % HFA384x_USB_RWMEM_MAXLEN) ? 1 : 0; /* For each burn */ - for ( i = 0; i < nburns; i++) { + for (i = 0; i < nburns; i++) { /* Get the dest address and len */ burnlen = (len - (hw->bufinfo.len * i)) > hw->bufinfo.len ? - hw->bufinfo.len : - (len - (hw->bufinfo.len * i)); + hw->bufinfo.len : (len - (hw->bufinfo.len * i)); burndaddr = daddr + (hw->bufinfo.len * i); burnlo = HFA384x_ADDR_CMD_MKOFF(burndaddr); burnhi = HFA384x_ADDR_CMD_MKPAGE(burndaddr); - WLAN_LOG_INFO("Writing %d bytes to flash @0x%06x\n", - burnlen, burndaddr); + printk(KERN_INFO "Writing %d bytes to flash @0x%06x\n", + burnlen, burndaddr); /* Set the download mode */ result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV, - burnlo, burnhi, burnlen); - if ( result ) { - WLAN_LOG_ERROR("download(NV,lo=%x,hi=%x,len=%x) " - "cmd failed, result=%d. Aborting d/l\n", - burnlo, burnhi, burnlen, result); + burnlo, burnhi, burnlen); + if (result) { + printk(KERN_ERR "download(NV,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + burnlo, burnhi, burnlen, result); goto exit_proc; } /* copy the data to the flash download buffer */ - for ( j=0; j < nwrites; j++) { + for (j = 0; j < nwrites; j++) { writebuf = buf + - (i*hw->bufinfo.len) + - (j*HFA384x_USB_RWMEM_MAXLEN); + (i * hw->bufinfo.len) + + (j * HFA384x_USB_RWMEM_MAXLEN); - writepage = HFA384x_ADDR_CMD_MKPAGE( - dlbufaddr + - (j*HFA384x_USB_RWMEM_MAXLEN)); - writeoffset = HFA384x_ADDR_CMD_MKOFF( - dlbufaddr + - (j*HFA384x_USB_RWMEM_MAXLEN)); + writepage = HFA384x_ADDR_CMD_MKPAGE(dlbufaddr + + (j * + HFA384x_USB_RWMEM_MAXLEN)); + writeoffset = + HFA384x_ADDR_CMD_MKOFF(dlbufaddr + + (j * + HFA384x_USB_RWMEM_MAXLEN)); - writelen = burnlen-(j*HFA384x_USB_RWMEM_MAXLEN); - writelen = writelen > HFA384x_USB_RWMEM_MAXLEN ? - HFA384x_USB_RWMEM_MAXLEN : - writelen; - - result = hfa384x_dowmem_wait( hw, - writepage, - writeoffset, - writebuf, - writelen ); -#if 0 - -Comment out for debugging, assume the write was successful. - if (result) { - WLAN_LOG_ERROR( - "Write to dl buffer failed, " - "result=0x%04x. Aborting.\n", - result); - goto exit_proc; - } -#endif + writelen = burnlen - (j * HFA384x_USB_RWMEM_MAXLEN); + writelen = writelen > HFA384x_USB_RWMEM_MAXLEN ? + HFA384x_USB_RWMEM_MAXLEN : writelen; + result = hfa384x_dowmem_wait(hw, + writepage, + writeoffset, + writebuf, writelen); } /* set the download 'write flash' mode */ result = hfa384x_cmd_download(hw, - HFA384x_PROGMODE_NVWRITE, - 0,0,0); - if ( result ) { - WLAN_LOG_ERROR( - "download(NVWRITE,lo=%x,hi=%x,len=%x) " - "cmd failed, result=%d. Aborting d/l\n", - burnlo, burnhi, burnlen, result); + HFA384x_PROGMODE_NVWRITE, + 0, 0, 0); + if (result) { + printk(KERN_ERR + "download(NVWRITE,lo=%x,hi=%x,len=%x) " + "cmd failed, result=%d. Aborting d/l\n", + burnlo, burnhi, burnlen, result); goto exit_proc; } @@ -2431,11 +2126,9 @@ exit_proc: /* actually disable programming mode. Remember, that will cause the */ /* the firmware to effectively reset itself. */ - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_drvr_getconfig * @@ -2463,12 +2156,10 @@ exit_proc: ----------------------------------------------------------------*/ int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) { - int result; - DBFENTER; + int result; result = hfa384x_dorrid_wait(hw, rid, buf, len); - DBFEXIT; return result; } @@ -2500,14 +2191,11 @@ int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) * Any ----------------------------------------------------------------*/ int -hfa384x_drvr_getconfig_async( - hfa384x_t *hw, - u16 rid, - ctlx_usercb_t usercb, - void *usercb_data) +hfa384x_drvr_getconfig_async(hfa384x_t *hw, + u16 rid, ctlx_usercb_t usercb, void *usercb_data) { - return hfa384x_dorrid_async(hw, rid, NULL, 0, - hfa384x_cb_rrid, usercb, usercb_data); + return hfa384x_dorrid_async(hw, rid, NULL, 0, + hfa384x_cb_rrid, usercb, usercb_data); } /*---------------------------------------------------------------- @@ -2534,70 +2222,15 @@ hfa384x_drvr_getconfig_async( * process ----------------------------------------------------------------*/ int -hfa384x_drvr_setconfig_async( - hfa384x_t *hw, - u16 rid, - void *buf, - u16 len, - ctlx_usercb_t usercb, - void *usercb_data) +hfa384x_drvr_setconfig_async(hfa384x_t *hw, + u16 rid, + void *buf, + u16 len, ctlx_usercb_t usercb, void *usercb_data) { return hfa384x_dowrid_async(hw, rid, buf, len, hfa384x_cb_status, usercb, usercb_data); } -/*---------------------------------------------------------------- -* hfa384x_drvr_handover -* -* Sends a handover notification to the MAC. -* -* Arguments: -* hw device structure -* addr address of station that's left -* -* Returns: -* zero success. -* -ERESTARTSYS received signal while waiting for semaphore. -* -EIO failed to write to bap, or failed in cmd. -* -* Side effects: -* -* Call context: -* process -----------------------------------------------------------------*/ -int hfa384x_drvr_handover( hfa384x_t *hw, u8 *addr) -{ - DBFENTER; - WLAN_LOG_ERROR("Not currently supported in USB!\n"); - DBFEXIT; - return -EIO; -} - -/*---------------------------------------------------------------- -* hfa384x_drvr_low_level -* -* Write test commands to the card. Some test commands don't make -* sense without prior set-up. For example, continous TX isn't very -* useful until you set the channel. That functionality should be -* -* Side effects: -* -* Call context: -* process thread -* -----------------------------------------------------------------*/ -int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd) -{ - int result; - DBFENTER; - - /* Do i need a host2hfa... conversion ? */ - - result = hfa384x_docmd_wait(hw, cmd); - - DBFEXIT; - return result; -} - /*---------------------------------------------------------------- * hfa384x_drvr_ramdl_disable * @@ -2616,27 +2249,22 @@ int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd) * Call context: * process ----------------------------------------------------------------*/ -int -hfa384x_drvr_ramdl_disable(hfa384x_t *hw) +int hfa384x_drvr_ramdl_disable(hfa384x_t *hw) { - DBFENTER; /* Check that we're already in the download state */ - if ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) { + if (hw->dlstate != HFA384x_DLSTATE_RAMENABLED) return -EINVAL; - } - WLAN_LOG_DEBUG(3,"ramdl_disable()\n"); + pr_debug("ramdl_disable()\n"); /* There isn't much we can do at this point, so I don't */ /* bother w/ the return value */ - hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0 , 0); + hfa384x_cmd_download(hw, HFA384x_PROGMODE_DISABLE, 0, 0, 0); hw->dlstate = HFA384x_DLSTATE_DISABLED; - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * hfa384x_drvr_ramdl_enable * @@ -2661,55 +2289,49 @@ hfa384x_drvr_ramdl_disable(hfa384x_t *hw) * Call context: * process ----------------------------------------------------------------*/ -int -hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr) +int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr) { - int result = 0; - u16 lowaddr; - u16 hiaddr; - int i; - DBFENTER; + int result = 0; + u16 lowaddr; + u16 hiaddr; + int i; + /* Check that a port isn't active */ - for ( i = 0; i < HFA384x_PORTID_MAX; i++) { - if ( hw->port_enabled[i] ) { - WLAN_LOG_ERROR( - "Can't download with a macport enabled.\n"); + for (i = 0; i < HFA384x_PORTID_MAX; i++) { + if (hw->port_enabled[i]) { + printk(KERN_ERR + "Can't download with a macport enabled.\n"); return -EINVAL; } } /* Check that we're not already in a download state */ - if ( hw->dlstate != HFA384x_DLSTATE_DISABLED ) { - WLAN_LOG_ERROR( - "Download state not disabled.\n"); + if (hw->dlstate != HFA384x_DLSTATE_DISABLED) { + printk(KERN_ERR "Download state not disabled.\n"); return -EINVAL; } - WLAN_LOG_DEBUG(3,"ramdl_enable, exeaddr=0x%08x\n", exeaddr); + pr_debug("ramdl_enable, exeaddr=0x%08x\n", exeaddr); /* Call the download(1,addr) function */ lowaddr = HFA384x_ADDR_CMD_MKOFF(exeaddr); - hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr); + hiaddr = HFA384x_ADDR_CMD_MKPAGE(exeaddr); result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_RAM, - lowaddr, hiaddr, 0); + lowaddr, hiaddr, 0); - if ( result == 0) { + if (result == 0) { /* Set the download state */ hw->dlstate = HFA384x_DLSTATE_RAMENABLED; } else { - WLAN_LOG_DEBUG(1, - "cmd_download(0x%04x, 0x%04x) failed, result=%d.\n", - lowaddr, - hiaddr, - result); + printk(KERN_DEBUG + "cmd_download(0x%04x, 0x%04x) failed, result=%d.\n", + lowaddr, hiaddr, result); } - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_drvr_ramdl_write * @@ -2736,57 +2358,54 @@ hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr) * Call context: * process ----------------------------------------------------------------*/ -int -hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void* buf, u32 len) +int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) { - int result = 0; - int nwrites; - u8 *data = buf; - int i; - u32 curraddr; - u16 currpage; - u16 curroffset; - u16 currlen; - DBFENTER; - /* Check that we're in the ram download state */ - if ( hw->dlstate != HFA384x_DLSTATE_RAMENABLED ) { - return -EINVAL; - } + int result = 0; + int nwrites; + u8 *data = buf; + int i; + u32 curraddr; + u16 currpage; + u16 curroffset; + u16 currlen; - WLAN_LOG_INFO("Writing %d bytes to ram @0x%06x\n", len, daddr); + /* Check that we're in the ram download state */ + if (hw->dlstate != HFA384x_DLSTATE_RAMENABLED) + return -EINVAL; + + printk(KERN_INFO "Writing %d bytes to ram @0x%06x\n", len, daddr); /* How many dowmem calls? */ nwrites = len / HFA384x_USB_RWMEM_MAXLEN; nwrites += len % HFA384x_USB_RWMEM_MAXLEN ? 1 : 0; /* Do blocking wmem's */ - for(i=0; i < nwrites; i++) { + for (i = 0; i < nwrites; i++) { /* make address args */ curraddr = daddr + (i * HFA384x_USB_RWMEM_MAXLEN); currpage = HFA384x_ADDR_CMD_MKPAGE(curraddr); curroffset = HFA384x_ADDR_CMD_MKOFF(curraddr); currlen = len - (i * HFA384x_USB_RWMEM_MAXLEN); - if ( currlen > HFA384x_USB_RWMEM_MAXLEN) { + if (currlen > HFA384x_USB_RWMEM_MAXLEN) currlen = HFA384x_USB_RWMEM_MAXLEN; - } - /* Do blocking ctlx */ - result = hfa384x_dowmem_wait( hw, - currpage, - curroffset, - data + (i*HFA384x_USB_RWMEM_MAXLEN), - currlen ); + /* Do blocking ctlx */ + result = hfa384x_dowmem_wait(hw, + currpage, + curroffset, + data + + (i * HFA384x_USB_RWMEM_MAXLEN), + currlen); - if (result) break; + if (result) + break; /* TODO: We really should have a readback. */ } - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_drvr_readpda * @@ -2820,101 +2439,89 @@ hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void* buf, u32 len) ----------------------------------------------------------------*/ int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len) { - int result = 0; - u16 *pda = buf; - int pdaok = 0; - int morepdrs = 1; - int currpdr = 0; /* word offset of the current pdr */ - size_t i; - u16 pdrlen; /* pdr length in bytes, host order */ - u16 pdrcode; /* pdr code, host order */ - u16 currpage; - u16 curroffset; + int result = 0; + u16 *pda = buf; + int pdaok = 0; + int morepdrs = 1; + int currpdr = 0; /* word offset of the current pdr */ + size_t i; + u16 pdrlen; /* pdr length in bytes, host order */ + u16 pdrcode; /* pdr code, host order */ + u16 currpage; + u16 curroffset; struct pdaloc { - u32 cardaddr; - u16 auxctl; - } pdaloc[] = - { - { HFA3842_PDA_BASE, 0}, - { HFA3841_PDA_BASE, 0}, - { HFA3841_PDA_BOGUS_BASE, 0} + u32 cardaddr; + u16 auxctl; + } pdaloc[] = { + { + HFA3842_PDA_BASE, 0}, { + HFA3841_PDA_BASE, 0}, { + HFA3841_PDA_BOGUS_BASE, 0} }; - DBFENTER; - /* Read the pda from each known address. */ - for ( i = 0; i < ARRAY_SIZE(pdaloc); i++) { + for (i = 0; i < ARRAY_SIZE(pdaloc); i++) { /* Make address */ currpage = HFA384x_ADDR_CMD_MKPAGE(pdaloc[i].cardaddr); curroffset = HFA384x_ADDR_CMD_MKOFF(pdaloc[i].cardaddr); - result = hfa384x_dormem_wait(hw, - currpage, - curroffset, - buf, - len); /* units of bytes */ + result = hfa384x_dormem_wait(hw, currpage, curroffset, buf, len); /* units of bytes */ if (result) { - WLAN_LOG_WARNING( - "Read from index %zd failed, continuing\n", - i ); + printk(KERN_WARNING + "Read from index %zd failed, continuing\n", i); continue; } /* Test for garbage */ pdaok = 1; /* initially assume good */ morepdrs = 1; - while ( pdaok && morepdrs ) { - pdrlen = hfa384x2host_16(pda[currpdr]) * 2; - pdrcode = hfa384x2host_16(pda[currpdr+1]); + while (pdaok && morepdrs) { + pdrlen = le16_to_cpu(pda[currpdr]) * 2; + pdrcode = le16_to_cpu(pda[currpdr + 1]); /* Test the record length */ - if ( pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) { - WLAN_LOG_ERROR("pdrlen invalid=%d\n", - pdrlen); + if (pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) { + printk(KERN_ERR "pdrlen invalid=%d\n", pdrlen); pdaok = 0; break; } /* Test the code */ - if ( !hfa384x_isgood_pdrcode(pdrcode) ) { - WLAN_LOG_ERROR("pdrcode invalid=%d\n", - pdrcode); + if (!hfa384x_isgood_pdrcode(pdrcode)) { + printk(KERN_ERR "pdrcode invalid=%d\n", + pdrcode); pdaok = 0; break; } /* Test for completion */ - if ( pdrcode == HFA384x_PDR_END_OF_PDA) { + if (pdrcode == HFA384x_PDR_END_OF_PDA) morepdrs = 0; - } /* Move to the next pdr (if necessary) */ - if ( morepdrs ) { + if (morepdrs) { /* note the access to pda[], need words here */ - currpdr += hfa384x2host_16(pda[currpdr]) + 1; + currpdr += le16_to_cpu(pda[currpdr]) + 1; } } - if ( pdaok ) { - WLAN_LOG_INFO( - "PDA Read from 0x%08x in %s space.\n", - pdaloc[i].cardaddr, - pdaloc[i].auxctl == 0 ? "EXTDS" : - pdaloc[i].auxctl == 1 ? "NV" : - pdaloc[i].auxctl == 2 ? "PHY" : - pdaloc[i].auxctl == 3 ? "ICSRAM" : - ""); + if (pdaok) { + printk(KERN_INFO + "PDA Read from 0x%08x in %s space.\n", + pdaloc[i].cardaddr, + pdaloc[i].auxctl == 0 ? "EXTDS" : + pdaloc[i].auxctl == 1 ? "NV" : + pdaloc[i].auxctl == 2 ? "PHY" : + pdaloc[i].auxctl == 3 ? "ICSRAM" : + ""); break; } } result = pdaok ? 0 : -ENODATA; - if ( result ) { - WLAN_LOG_DEBUG(3,"Failure: pda is not okay\n"); - } + if (result) + pr_debug("Failure: pda is not okay\n"); - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_drvr_setconfig * @@ -2963,9 +2570,8 @@ int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len) int hfa384x_drvr_start(hfa384x_t *hw) { - int result, result1, result2; - u16 status; - DBFENTER; + int result, result1, result2; + u16 status; might_sleep(); @@ -2974,27 +2580,23 @@ int hfa384x_drvr_start(hfa384x_t *hw) * badly if a clear_halt is called when the endpoint is already * ok */ - result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status); + result = + usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status); if (result < 0) { - WLAN_LOG_ERROR( - "Cannot get bulk in endpoint status.\n"); + printk(KERN_ERR "Cannot get bulk in endpoint status.\n"); goto done; } - if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_in)) { - WLAN_LOG_ERROR( - "Failed to reset bulk in endpoint.\n"); - } + if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_in)) + printk(KERN_ERR "Failed to reset bulk in endpoint.\n"); - result = usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status); + result = + usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status); if (result < 0) { - WLAN_LOG_ERROR( - "Cannot get bulk out endpoint status.\n"); + printk(KERN_ERR "Cannot get bulk out endpoint status.\n"); goto done; } - if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_out)) { - WLAN_LOG_ERROR( - "Failed to reset bulk out endpoint.\n"); - } + if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_out)) + printk(KERN_ERR "Failed to reset bulk out endpoint.\n"); /* Synchronous unlink, in case we're trying to restart the driver */ usb_kill_urb(&hw->rx_urb); @@ -3002,9 +2604,8 @@ int hfa384x_drvr_start(hfa384x_t *hw) /* Post the IN urb */ result = submit_rx_urb(hw, GFP_KERNEL); if (result != 0) { - WLAN_LOG_ERROR( - "Fatal, failed to submit RX URB, result=%d\n", - result); + printk(KERN_ERR + "Fatal, failed to submit RX URB, result=%d\n", result); goto done; } @@ -3023,32 +2624,33 @@ int hfa384x_drvr_start(hfa384x_t *hw) result = result2 = hfa384x_cmd_initialize(hw); if (result1 != 0) { if (result2 != 0) { - WLAN_LOG_ERROR( - "cmd_initialize() failed on two attempts, results %d and %d\n", - result1, result2); + printk(KERN_ERR + "cmd_initialize() failed on two attempts, results %d and %d\n", + result1, result2); usb_kill_urb(&hw->rx_urb); goto done; } else { - WLAN_LOG_DEBUG(0, "First cmd_initialize() failed (result %d),\n", - result1); - WLAN_LOG_DEBUG(0, "but second attempt succeeded. All should be ok\n"); + printk(KERN_DEBUG + "First cmd_initialize() failed (result %d),\n", + result1); + printk(KERN_DEBUG + "but second attempt succeeded. All should be ok\n"); } } else if (result2 != 0) { - WLAN_LOG_WARNING( - "First cmd_initialize() succeeded, but second attempt failed (result=%d)\n", - result2); - WLAN_LOG_WARNING("Most likely the card will be functional\n"); - goto done; + printk(KERN_WARNING + "First cmd_initialize() succeeded, but second attempt failed (result=%d)\n", + result2); + printk(KERN_WARNING + "Most likely the card will be functional\n"); + goto done; } hw->state = HFA384x_STATE_RUNNING; done: - DBFEXIT; return result; } - /*---------------------------------------------------------------- * hfa384x_drvr_stop * @@ -3068,19 +2670,17 @@ done: * Call context: * process ----------------------------------------------------------------*/ -int -hfa384x_drvr_stop(hfa384x_t *hw) +int hfa384x_drvr_stop(hfa384x_t *hw) { - int result = 0; - int i; - DBFENTER; + int result = 0; + int i; might_sleep(); /* There's no need for spinlocks here. The USB "disconnect" * function sets this "removed" flag and then calls us. */ - if ( !hw->wlandev->hwremoved ) { + if (!hw->wlandev->hwremoved) { /* Call initialize to leave the MAC in its 'reset' state */ hfa384x_cmd_initialize(hw); @@ -3094,11 +2694,9 @@ hfa384x_drvr_stop(hfa384x_t *hw) del_timer_sync(&hw->commsqual_timer); /* Clear all the port status */ - for ( i = 0; i < HFA384x_NUMPORTS_MAX; i++) { + for (i = 0; i < HFA384x_NUMPORTS_MAX; i++) hw->port_enabled[i] = 0; - } - DBFEXIT; return result; } @@ -3123,18 +2721,17 @@ hfa384x_drvr_stop(hfa384x_t *hw) * Call context: * interrupt ----------------------------------------------------------------*/ -int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) - +int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, + p80211_hdr_t *p80211_hdr, + p80211_metawep_t *p80211_wep) { - int usbpktlen = sizeof(hfa384x_tx_frame_t); - int result; - int ret; - char *ptr; - - DBFENTER; + int usbpktlen = sizeof(hfa384x_tx_frame_t); + int result; + int ret; + char *ptr; if (hw->tx_urb.status == -EINPROGRESS) { - WLAN_LOG_WARNING("TX URB already in use\n"); + printk(KERN_WARNING "TX URB already in use\n"); result = 3; goto exit; } @@ -3144,7 +2741,7 @@ int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p8021 memset(&hw->txbuff.txfrm.desc, 0, sizeof(hw->txbuff.txfrm.desc)); /* Setup the usb type field */ - hw->txbuff.type = host2hfa384x_16(HFA384x_USB_TXFRM); + hw->txbuff.type = cpu_to_le16(HFA384x_USB_TXFRM); /* Set up the sw_support field to identify this frame */ hw->txbuff.txfrm.desc.sw_support = 0x0123; @@ -3152,33 +2749,33 @@ int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p8021 /* Tx complete and Tx exception disable per dleach. Might be causing * buf depletion */ -//#define DOEXC SLP -- doboth breaks horribly under load, doexc less so. +/* #define DOEXC SLP -- doboth breaks horribly under load, doexc less so. */ #if defined(DOBOTH) hw->txbuff.txfrm.desc.tx_control = - HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | - HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1); + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1); #elif defined(DOEXC) hw->txbuff.txfrm.desc.tx_control = - HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | - HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(0); + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(0); #else hw->txbuff.txfrm.desc.tx_control = - HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | - HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0); + HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + HFA384x_TX_TXEX_SET(0) | HFA384x_TX_TXOK_SET(0); #endif hw->txbuff.txfrm.desc.tx_control = - host2hfa384x_16(hw->txbuff.txfrm.desc.tx_control); + cpu_to_le16(hw->txbuff.txfrm.desc.tx_control); /* copy the header over to the txdesc */ - memcpy(&(hw->txbuff.txfrm.desc.frame_control), p80211_hdr, sizeof(p80211_hdr_t)); + memcpy(&(hw->txbuff.txfrm.desc.frame_control), p80211_hdr, + sizeof(p80211_hdr_t)); /* if we're using host WEP, increase size by IV+ICV */ if (p80211_wep->data) { - hw->txbuff.txfrm.desc.data_len = host2hfa384x_16(skb->len+8); - // hw->txbuff.txfrm.desc.tx_control |= HFA384x_TX_NOENCRYPT_SET(1); - usbpktlen+=8; + hw->txbuff.txfrm.desc.data_len = cpu_to_le16(skb->len + 8); + usbpktlen += 8; } else { - hw->txbuff.txfrm.desc.data_len = host2hfa384x_16(skb->len); + hw->txbuff.txfrm.desc.data_len = cpu_to_le16(skb->len); } usbpktlen += skb->len; @@ -3187,59 +2784,51 @@ int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb, p80211_hdr_t *p8021 ptr = hw->txbuff.txfrm.data; if (p80211_wep->data) { memcpy(ptr, p80211_wep->iv, sizeof(p80211_wep->iv)); - ptr+= sizeof(p80211_wep->iv); + ptr += sizeof(p80211_wep->iv); memcpy(ptr, p80211_wep->data, skb->len); } else { memcpy(ptr, skb->data, skb->len); } /* copy over the packet data */ - ptr+= skb->len; + ptr += skb->len; /* copy over the WEP ICV if we are using host WEP */ - if (p80211_wep->data) { + if (p80211_wep->data) memcpy(ptr, p80211_wep->icv, sizeof(p80211_wep->icv)); - } /* Send the USB packet */ - usb_fill_bulk_urb( &(hw->tx_urb), hw->usb, - hw->endp_out, - &(hw->txbuff), ROUNDUP64(usbpktlen), - hfa384x_usbout_callback, hw->wlandev ); + usb_fill_bulk_urb(&(hw->tx_urb), hw->usb, + hw->endp_out, + &(hw->txbuff), ROUNDUP64(usbpktlen), + hfa384x_usbout_callback, hw->wlandev); hw->tx_urb.transfer_flags |= USB_QUEUE_BULK; result = 1; ret = submit_tx_urb(hw, &hw->tx_urb, GFP_ATOMIC); - if ( ret != 0 ) { - WLAN_LOG_ERROR( - "submit_tx_urb() failed, error=%d\n", ret); + if (ret != 0) { + printk(KERN_ERR "submit_tx_urb() failed, error=%d\n", ret); result = 3; } - exit: - DBFEXIT; +exit: return result; } void hfa384x_tx_timeout(wlandevice_t *wlandev) { - hfa384x_t *hw = wlandev->priv; + hfa384x_t *hw = wlandev->priv; unsigned long flags; - DBFENTER; - spin_lock_irqsave(&hw->ctlxq.lock, flags); - if ( !hw->wlandev->hwremoved && - /* Note the bitwise OR, not the logical OR. */ - ( !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) | - !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) ) - { + if (!hw->wlandev->hwremoved && + /* Note the bitwise OR, not the logical OR. */ + (!test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) | + !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags))) { schedule_work(&hw->usb_work); } spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - - DBFEXIT; } /*---------------------------------------------------------------- @@ -3257,12 +2846,10 @@ void hfa384x_tx_timeout(wlandevice_t *wlandev) ----------------------------------------------------------------*/ static void hfa384x_usbctlx_reaper_task(unsigned long data) { - hfa384x_t *hw = (hfa384x_t*)data; + hfa384x_t *hw = (hfa384x_t *) data; struct list_head *entry; struct list_head *temp; - unsigned long flags; - - DBFENTER; + unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3270,7 +2857,7 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) * has unplugged the adapter. */ list_for_each_safe(entry, temp, &hw->ctlxq.reapable) { - hfa384x_usbctlx_t *ctlx; + hfa384x_usbctlx_t *ctlx; ctlx = list_entry(entry, hfa384x_usbctlx_t, list); list_del(&ctlx->list); @@ -3279,7 +2866,6 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - DBFEXIT; } /*---------------------------------------------------------------- @@ -3298,15 +2884,13 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) ----------------------------------------------------------------*/ static void hfa384x_usbctlx_completion_task(unsigned long data) { - hfa384x_t *hw = (hfa384x_t*)data; + hfa384x_t *hw = (hfa384x_t *) data; struct list_head *entry; struct list_head *temp; unsigned long flags; int reap = 0; - DBFENTER; - spin_lock_irqsave(&hw->ctlxq.lock, flags); /* This list is guaranteed to be empty if someone @@ -3320,7 +2904,7 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) /* Call the completion function that this * command was assigned, assuming it has one. */ - if ( ctlx->cmdcb != NULL ) { + if (ctlx->cmdcb != NULL) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); ctlx->cmdcb(hw, ctlx); spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3333,8 +2917,7 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) /* Did someone yank the adapter out * while our list was (briefly) unlocked? */ - if ( hw->wlandev->hwremoved ) - { + if (hw->wlandev->hwremoved) { reap = 0; break; } @@ -3345,7 +2928,7 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) * threads waiting for them to die. Hence they must * be delivered to The Reaper! */ - if ( ctlx->reapable ) { + if (ctlx->reapable) { /* Move the CTLX off the "completing" list (hopefully) * on to the "reapable" list where the reaper task * can find it. And "reapable" means that this CTLX @@ -3361,8 +2944,6 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) if (reap) tasklet_schedule(&hw->reaper_bh); - - DBFEXIT; } /*---------------------------------------------------------------- @@ -3382,12 +2963,11 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) * Call context: * Either process or interrupt, but presumably interrupt ----------------------------------------------------------------*/ -static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) +static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, + hfa384x_usbctlx_t *ctlx) { int ret; - DBFENTER; - /* * Try to delete the URB containing our request packet. * If we succeed, then its completion handler will be @@ -3408,8 +2988,6 @@ static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) ret = 0; } - DBFEXIT; - return ret; } @@ -3437,8 +3015,6 @@ static int unlocked_usbctlx_cancel_async(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) ----------------------------------------------------------------*/ static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) { - DBFENTER; - /* Timers have been stopped, and ctlx should be in * a terminal state. Retire it from the "active" * queue. @@ -3453,13 +3029,11 @@ static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) break; default: - WLAN_LOG_ERROR("CTLX[%d] not in a terminating state(%s)\n", - hfa384x2host_16(ctlx->outbuf.type), - ctlxstr(ctlx->state)); + printk(KERN_ERR "CTLX[%d] not in a terminating state(%s)\n", + le16_to_cpu(ctlx->outbuf.type), + ctlxstr(ctlx->state)); break; - } /* switch */ - - DBFEXIT; + } /* switch */ } /*---------------------------------------------------------------- @@ -3478,11 +3052,9 @@ static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) * Call context: * any ----------------------------------------------------------------*/ -static void -hfa384x_usbctlxq_run(hfa384x_t *hw) +static void hfa384x_usbctlxq_run(hfa384x_t *hw) { - unsigned long flags; - DBFENTER; + unsigned long flags; /* acquire lock */ spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3494,28 +3066,26 @@ hfa384x_usbctlxq_run(hfa384x_t *hw) * Don't touch any of these CTLXs if the hardware * has been removed or the USB subsystem is stalled. */ - if ( !list_empty(&hw->ctlxq.active) || - test_bit(WORK_TX_HALT, &hw->usb_flags) || - hw->wlandev->hwremoved ) + if (!list_empty(&hw->ctlxq.active) || + test_bit(WORK_TX_HALT, &hw->usb_flags) || hw->wlandev->hwremoved) goto unlock; - while ( !list_empty(&hw->ctlxq.pending) ) { - hfa384x_usbctlx_t *head; - int result; + while (!list_empty(&hw->ctlxq.pending)) { + hfa384x_usbctlx_t *head; + int result; /* This is the first pending command */ head = list_entry(hw->ctlxq.pending.next, - hfa384x_usbctlx_t, - list); + hfa384x_usbctlx_t, list); /* We need to split this off to avoid a race condition */ list_move_tail(&head->list, &hw->ctlxq.active); /* Fill the out packet */ - usb_fill_bulk_urb( &(hw->ctlx_urb), hw->usb, - hw->endp_out, - &(head->outbuf), ROUNDUP64(head->outbufsize), - hfa384x_ctlxout_callback, hw); + usb_fill_bulk_urb(&(hw->ctlx_urb), hw->usb, + hw->endp_out, + &(head->outbuf), ROUNDUP64(head->outbufsize), + hfa384x_ctlxout_callback, hw); hw->ctlx_urb.transfer_flags |= USB_QUEUE_BULK; /* Now submit the URB and update the CTLX's state @@ -3531,7 +3101,7 @@ hfa384x_usbctlxq_run(hfa384x_t *hw) /* Start the IN wait timer */ hw->resp_timer_done = 0; - hw->resptimer.expires = jiffies + 2*HZ; + hw->resptimer.expires = jiffies + 2 * HZ; add_timer(&hw->resptimer); break; @@ -3542,8 +3112,9 @@ hfa384x_usbctlxq_run(hfa384x_t *hw) * this CTLX back in the "pending" queue * and schedule a reset ... */ - WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", - hw->wlandev->netdev->name); + printk(KERN_WARNING + "%s tx pipe stalled: requesting reset\n", + hw->wlandev->netdev->name); list_move(&head->list, &hw->ctlxq.pending); set_bit(WORK_TX_HALT, &hw->usb_flags); schedule_work(&hw->usb_work); @@ -3551,23 +3122,20 @@ hfa384x_usbctlxq_run(hfa384x_t *hw) } if (result == -ESHUTDOWN) { - WLAN_LOG_WARNING("%s urb shutdown!\n", - hw->wlandev->netdev->name); + printk(KERN_WARNING "%s urb shutdown!\n", + hw->wlandev->netdev->name); break; } - WLAN_LOG_ERROR("Failed to submit CTLX[%d]: error=%d\n", - hfa384x2host_16(head->outbuf.type), result); + printk(KERN_ERR "Failed to submit CTLX[%d]: error=%d\n", + le16_to_cpu(head->outbuf.type), result); unlocked_usbctlx_complete(hw, head); - } /* while */ + } /* while */ - unlock: +unlock: spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_usbin_callback * @@ -3586,13 +3154,13 @@ hfa384x_usbctlxq_run(hfa384x_t *hw) ----------------------------------------------------------------*/ static void hfa384x_usbin_callback(struct urb *urb) { - wlandevice_t *wlandev = urb->context; - hfa384x_t *hw; - hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) urb->transfer_buffer; - struct sk_buff *skb = NULL; - int result; - int urb_status; - u16 type; + wlandevice_t *wlandev = urb->context; + hfa384x_t *hw; + hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) urb->transfer_buffer; + struct sk_buff *skb = NULL; + int result; + int urb_status; + u16 type; enum USBIN_ACTION { HANDLE, @@ -3600,11 +3168,7 @@ static void hfa384x_usbin_callback(struct urb *urb) ABORT } action; - DBFENTER; - - if ( !wlandev || - !wlandev->netdev || - wlandev->hwremoved ) + if (!wlandev || !wlandev->netdev || wlandev->hwremoved) goto exit; hw = wlandev->priv; @@ -3612,9 +3176,8 @@ static void hfa384x_usbin_callback(struct urb *urb) goto exit; skb = hw->rx_urb_skb; - if (!skb || (skb->data != urb->transfer_buffer)) { - BUG(); - } + BUG_ON(!skb || (skb->data != urb->transfer_buffer)); + hw->rx_urb_skb = NULL; /* Check for error conditions within the URB */ @@ -3623,7 +3186,7 @@ static void hfa384x_usbin_callback(struct urb *urb) action = HANDLE; /* Check for short packet */ - if ( urb->actual_length == 0 ) { + if (urb->actual_length == 0) { ++(wlandev->linux_stats.rx_errors); ++(wlandev->linux_stats.rx_length_errors); action = RESUBMIT; @@ -3631,9 +3194,9 @@ static void hfa384x_usbin_callback(struct urb *urb) break; case -EPIPE: - WLAN_LOG_WARNING("%s rx pipe stalled: requesting reset\n", - wlandev->netdev->name); - if ( !test_and_set_bit(WORK_RX_HALT, &hw->usb_flags) ) + printk(KERN_WARNING "%s rx pipe stalled: requesting reset\n", + wlandev->netdev->name); + if (!test_and_set_bit(WORK_RX_HALT, &hw->usb_flags)) schedule_work(&hw->usb_work); ++(wlandev->linux_stats.rx_errors); action = ABORT; @@ -3642,8 +3205,8 @@ static void hfa384x_usbin_callback(struct urb *urb) case -EILSEQ: case -ETIMEDOUT: case -EPROTO: - if ( !test_and_set_bit(THROTTLE_RX, &hw->usb_flags) && - !timer_pending(&hw->throttle) ) { + if (!test_and_set_bit(THROTTLE_RX, &hw->usb_flags) && + !timer_pending(&hw->throttle)) { mod_timer(&hw->throttle, jiffies + THROTTLE_JIFFIES); } ++(wlandev->linux_stats.rx_errors); @@ -3657,19 +3220,20 @@ static void hfa384x_usbin_callback(struct urb *urb) case -ENODEV: case -ESHUTDOWN: - WLAN_LOG_DEBUG(3,"status=%d, device removed.\n", urb->status); + pr_debug("status=%d, device removed.\n", urb->status); action = ABORT; break; case -ENOENT: case -ECONNRESET: - WLAN_LOG_DEBUG(3,"status=%d, urb explicitly unlinked.\n", urb->status); + pr_debug("status=%d, urb explicitly unlinked.\n", + urb->status); action = ABORT; break; default: - WLAN_LOG_DEBUG(3,"urb status=%d, transfer flags=0x%x\n", - urb->status, urb->transfer_flags); + pr_debug("urb status=%d, transfer flags=0x%x\n", + urb->status, urb->transfer_flags); ++(wlandev->linux_stats.rx_errors); action = RESUBMIT; break; @@ -3682,9 +3246,9 @@ static void hfa384x_usbin_callback(struct urb *urb) result = submit_rx_urb(hw, GFP_ATOMIC); if (result != 0) { - WLAN_LOG_ERROR( - "Fatal, failed to resubmit rx_urb. error=%d\n", - result); + printk(KERN_ERR + "Fatal, failed to resubmit rx_urb. error=%d\n", + result); } } @@ -3692,7 +3256,7 @@ static void hfa384x_usbin_callback(struct urb *urb) /* Note: the check of the sw_support field, the type field doesn't * have bit 12 set like the docs suggest. */ - type = hfa384x2host_16(usbin->type); + type = le16_to_cpu(usbin->type); if (HFA384x_USB_ISRXFRM(type)) { if (action == HANDLE) { if (usbin->txfrm.desc.sw_support == 0x0123) { @@ -3728,30 +3292,28 @@ static void hfa384x_usbin_callback(struct urb *urb) break; case HFA384x_USB_BUFAVAIL: - WLAN_LOG_DEBUG(3,"Received BUFAVAIL packet, frmlen=%d\n", - usbin->bufavail.frmlen); + pr_debug("Received BUFAVAIL packet, frmlen=%d\n", + usbin->bufavail.frmlen); break; case HFA384x_USB_ERROR: - WLAN_LOG_DEBUG(3,"Received USB_ERROR packet, errortype=%d\n", - usbin->usberror.errortype); + pr_debug("Received USB_ERROR packet, errortype=%d\n", + usbin->usberror.errortype); break; default: - WLAN_LOG_DEBUG(3,"Unrecognized USBIN packet, type=%x, status=%d\n", - usbin->type, urb_status); + printk(KERN_DEBUG + "Unrecognized USBIN packet, type=%x, status=%d\n", + usbin->type, urb_status); break; - } /* switch */ + } /* switch */ exit: if (skb) dev_kfree_skb(skb); - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_usbin_ctlx * @@ -3775,11 +3337,9 @@ exit: static void hfa384x_usbin_ctlx(hfa384x_t *hw, hfa384x_usbin_t *usbin, int urb_status) { - hfa384x_usbctlx_t *ctlx; - int run_queue = 0; - unsigned long flags; - - DBFENTER; + hfa384x_usbctlx_t *ctlx; + int run_queue = 0; + unsigned long flags; retry: spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -3788,9 +3348,8 @@ retry: * at any one time, and this is the CTLX that the * timers are waiting for. */ - if ( list_empty(&hw->ctlxq.active) ) { + if (list_empty(&hw->ctlxq.active)) goto unlock; - } /* Remove the "response timeout". It's possible that * we are already too late, and that the timeout is @@ -3803,8 +3362,7 @@ retry: spin_unlock_irqrestore(&hw->ctlxq.lock, flags); goto retry; } - } - else { + } else { hw->resp_timer_done = 1; } @@ -3819,15 +3377,16 @@ retry: if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) run_queue = 1; } else { - const u16 intype = (usbin->type&~host2hfa384x_16(0x8000)); + const u16 intype = (usbin->type & ~cpu_to_le16(0x8000)); /* * Check that our message is what we're expecting ... */ if (ctlx->outbuf.type != intype) { - WLAN_LOG_WARNING("Expected IN[%d], received IN[%d] - ignored.\n", - hfa384x2host_16(ctlx->outbuf.type), - hfa384x2host_16(intype)); + printk(KERN_WARNING + "Expected IN[%d], received IN[%d] - ignored.\n", + le16_to_cpu(ctlx->outbuf.type), + le16_to_cpu(intype)); goto unlock; } @@ -3841,7 +3400,8 @@ retry: * our request has been acknowledged. Odd, * but our OUT URB is still alive... */ - WLAN_LOG_DEBUG(0, "Causality violation: please reboot Universe, or email linux-wlan-devel@lists.linux-wlan.com\n"); + printk(KERN_DEBUG + "Causality violation: please reboot Universe, or email linux-wlan-devel@lists.linux-wlan.com\n"); ctlx->state = CTLX_RESP_COMPLETE; break; @@ -3860,14 +3420,15 @@ retry: /* * Throw this CTLX away ... */ - WLAN_LOG_ERROR("Matched IN URB, CTLX[%d] in invalid state(%s)." - " Discarded.\n", - hfa384x2host_16(ctlx->outbuf.type), - ctlxstr(ctlx->state)); + printk(KERN_ERR + "Matched IN URB, CTLX[%d] in invalid state(%s)." + " Discarded.\n", + le16_to_cpu(ctlx->outbuf.type), + ctlxstr(ctlx->state)); if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) run_queue = 1; break; - } /* switch */ + } /* switch */ } unlock: @@ -3875,11 +3436,8 @@ unlock: if (run_queue) hfa384x_usbctlxq_run(hw); - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_usbin_txcompl * @@ -3897,25 +3455,20 @@ unlock: * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) +static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, + hfa384x_usbin_t *usbin) { - u16 status; - DBFENTER; + u16 status; - status = hfa384x2host_16(usbin->type); /* yeah I know it says type...*/ + status = le16_to_cpu(usbin->type); /* yeah I know it says type... */ /* Was there an error? */ - if (HFA384x_TXSTATUS_ISERROR(status)) { + if (HFA384x_TXSTATUS_ISERROR(status)) prism2sta_ev_txexc(wlandev, status); - } else { + else prism2sta_ev_tx(wlandev, status); - } - // prism2sta_ev_alloc(wlandev); - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_usbin_rx * @@ -3935,34 +3488,29 @@ static void hfa384x_usbin_txcompl(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) ----------------------------------------------------------------*/ static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) { - hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) skb->data; - hfa384x_t *hw = wlandev->priv; - int hdrlen; - p80211_rxmeta_t *rxmeta; - u16 data_len; - u16 fc; - - DBFENTER; + hfa384x_usbin_t *usbin = (hfa384x_usbin_t *) skb->data; + hfa384x_t *hw = wlandev->priv; + int hdrlen; + p80211_rxmeta_t *rxmeta; + u16 data_len; + u16 fc; /* Byte order convert once up front. */ - usbin->rxfrm.desc.status = - hfa384x2host_16(usbin->rxfrm.desc.status); - usbin->rxfrm.desc.time = - hfa384x2host_32(usbin->rxfrm.desc.time); + usbin->rxfrm.desc.status = le16_to_cpu(usbin->rxfrm.desc.status); + usbin->rxfrm.desc.time = le32_to_cpu(usbin->rxfrm.desc.time); /* Now handle frame based on port# */ - switch( HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status) ) - { + switch (HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status)) { case 0: - fc = ieee2host16(usbin->rxfrm.desc.frame_control); + fc = le16_to_cpu(usbin->rxfrm.desc.frame_control); /* If exclude and we receive an unencrypted, drop it */ - if ( (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) && - !WLAN_GET_FC_ISWEP(fc)){ + if ((wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) && + !WLAN_GET_FC_ISWEP(fc)) { goto done; } - data_len = hfa384x2host_16(usbin->rxfrm.desc.data_len); + data_len = le16_to_cpu(usbin->rxfrm.desc.data_len); /* How much header data do we have? */ hdrlen = p80211_headerlen(fc); @@ -3974,8 +3522,7 @@ static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) * with an "overlapping" copy */ memmove(skb_push(skb, hdrlen), - &usbin->rxfrm.desc.frame_control, - hdrlen); + &usbin->rxfrm.desc.frame_control, hdrlen); skb->dev = wlandev->netdev; skb->dev->last_rx = jiffies; @@ -4001,24 +3548,24 @@ static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb) break; case 7: - if ( ! HFA384x_RXSTATUS_ISFCSERR(usbin->rxfrm.desc.status) ) { + if (!HFA384x_RXSTATUS_ISFCSERR(usbin->rxfrm.desc.status)) { /* Copy to wlansnif skb */ - hfa384x_int_rxmonitor( wlandev, &usbin->rxfrm); + hfa384x_int_rxmonitor(wlandev, &usbin->rxfrm); dev_kfree_skb(skb); } else { - WLAN_LOG_DEBUG(3,"Received monitor frame: FCSerr set\n"); + printk(KERN_DEBUG + "Received monitor frame: FCSerr set\n"); } break; default: - WLAN_LOG_WARNING("Received frame on unsupported port=%d\n", - HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status) ); + printk(KERN_WARNING "Received frame on unsupported port=%d\n", + HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status)); goto done; break; } done: - DBFEXIT; return; } @@ -4043,97 +3590,93 @@ done: * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, hfa384x_usb_rxfrm_t *rxfrm) +static void hfa384x_int_rxmonitor(wlandevice_t *wlandev, + hfa384x_usb_rxfrm_t *rxfrm) { - hfa384x_rx_frame_t *rxdesc = &(rxfrm->desc); - unsigned int hdrlen = 0; - unsigned int datalen = 0; - unsigned int skblen = 0; - u8 *datap; - u16 fc; - struct sk_buff *skb; - hfa384x_t *hw = wlandev->priv; + hfa384x_rx_frame_t *rxdesc = &(rxfrm->desc); + unsigned int hdrlen = 0; + unsigned int datalen = 0; + unsigned int skblen = 0; + u8 *datap; + u16 fc; + struct sk_buff *skb; + hfa384x_t *hw = wlandev->priv; - - DBFENTER; /* Don't forget the status, time, and data_len fields are in host order */ /* Figure out how big the frame is */ - fc = ieee2host16(rxdesc->frame_control); + fc = le16_to_cpu(rxdesc->frame_control); hdrlen = p80211_headerlen(fc); - datalen = hfa384x2host_16(rxdesc->data_len); + datalen = le16_to_cpu(rxdesc->data_len); /* Allocate an ind message+framesize skb */ - skblen = sizeof(p80211_caphdr_t) + - hdrlen + datalen + WLAN_CRC_LEN; + skblen = sizeof(p80211_caphdr_t) + hdrlen + datalen + WLAN_CRC_LEN; /* sanity check the length */ - if ( skblen > - (sizeof(p80211_caphdr_t) + - WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) { - WLAN_LOG_DEBUG(1, "overlen frm: len=%zd\n", - skblen - sizeof(p80211_caphdr_t)); + if (skblen > + (sizeof(p80211_caphdr_t) + + WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN)) { + pr_debug("overlen frm: len=%zd\n", + skblen - sizeof(p80211_caphdr_t)); } - if ( (skb = dev_alloc_skb(skblen)) == NULL ) { - WLAN_LOG_ERROR("alloc_skb failed trying to allocate %d bytes\n", skblen); + if ((skb = dev_alloc_skb(skblen)) == NULL) { + printk(KERN_ERR + "alloc_skb failed trying to allocate %d bytes\n", + skblen); return; } /* only prepend the prism header if in the right mode */ if ((wlandev->netdev->type == ARPHRD_IEEE80211_PRISM) && (hw->sniffhdr != 0)) { - p80211_caphdr_t *caphdr; + p80211_caphdr_t *caphdr; /* The NEW header format! */ datap = skb_put(skb, sizeof(p80211_caphdr_t)); - caphdr = (p80211_caphdr_t*) datap; + caphdr = (p80211_caphdr_t *) datap; - caphdr->version = htonl(P80211CAPTURE_VERSION); - caphdr->length = htonl(sizeof(p80211_caphdr_t)); - caphdr->mactime = __cpu_to_be64(rxdesc->time) * 1000; - caphdr->hosttime = __cpu_to_be64(jiffies); - caphdr->phytype = htonl(4); /* dss_dot11_b */ - caphdr->channel = htonl(hw->sniff_channel); - caphdr->datarate = htonl(rxdesc->rate); - caphdr->antenna = htonl(0); /* unknown */ - caphdr->priority = htonl(0); /* unknown */ - caphdr->ssi_type = htonl(3); /* rssi_raw */ - caphdr->ssi_signal = htonl(rxdesc->signal); - caphdr->ssi_noise = htonl(rxdesc->silence); - caphdr->preamble = htonl(0); /* unknown */ - caphdr->encoding = htonl(1); /* cck */ + caphdr->version = htonl(P80211CAPTURE_VERSION); + caphdr->length = htonl(sizeof(p80211_caphdr_t)); + caphdr->mactime = __cpu_to_be64(rxdesc->time) * 1000; + caphdr->hosttime = __cpu_to_be64(jiffies); + caphdr->phytype = htonl(4); /* dss_dot11_b */ + caphdr->channel = htonl(hw->sniff_channel); + caphdr->datarate = htonl(rxdesc->rate); + caphdr->antenna = htonl(0); /* unknown */ + caphdr->priority = htonl(0); /* unknown */ + caphdr->ssi_type = htonl(3); /* rssi_raw */ + caphdr->ssi_signal = htonl(rxdesc->signal); + caphdr->ssi_noise = htonl(rxdesc->silence); + caphdr->preamble = htonl(0); /* unknown */ + caphdr->encoding = htonl(1); /* cck */ } /* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */ datap = skb_put(skb, hdrlen); - memcpy( datap, &(rxdesc->frame_control), hdrlen); + memcpy(datap, &(rxdesc->frame_control), hdrlen); /* If any, copy the data from the card to the skb */ - if ( datalen > 0 ) - { + if (datalen > 0) { datap = skb_put(skb, datalen); memcpy(datap, rxfrm->data, datalen); /* check for unencrypted stuff if WEP bit set. */ - if (*(datap - hdrlen + 1) & 0x40) // wep set - if ((*(datap) == 0xaa) && (*(datap+1) == 0xaa)) - *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header! + if (*(datap - hdrlen + 1) & 0x40) /* wep set */ + if ((*(datap) == 0xaa) && (*(datap + 1) == 0xaa)) + *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header! } if (hw->sniff_fcs) { /* Set the FCS */ datap = skb_put(skb, WLAN_CRC_LEN); - memset( datap, 0xff, WLAN_CRC_LEN); + memset(datap, 0xff, WLAN_CRC_LEN); } /* pass it back up */ prism2sta_ev_rx(wlandev, skb); - DBFEXIT; return; } - - /*---------------------------------------------------------------- * hfa384x_usbin_info * @@ -4151,18 +3694,13 @@ static void hfa384x_int_rxmonitor( wlandevice_t *wlandev, hfa384x_usb_rxfrm_t *r * Call context: * interrupt ----------------------------------------------------------------*/ -static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) +static void hfa384x_usbin_info(wlandevice_t * wlandev, hfa384x_usbin_t * usbin) { - DBFENTER; - - usbin->infofrm.info.framelen = hfa384x2host_16(usbin->infofrm.info.framelen); + usbin->infofrm.info.framelen = + le16_to_cpu(usbin->infofrm.info.framelen); prism2sta_ev_info(wlandev, &usbin->infofrm.info); - - DBFEXIT; } - - /*---------------------------------------------------------------- * hfa384x_usbout_callback * @@ -4181,48 +3719,49 @@ static void hfa384x_usbin_info(wlandevice_t *wlandev, hfa384x_usbin_t *usbin) ----------------------------------------------------------------*/ static void hfa384x_usbout_callback(struct urb *urb) { - wlandevice_t *wlandev = urb->context; - hfa384x_usbout_t *usbout = urb->transfer_buffer; - DBFENTER; + wlandevice_t *wlandev = urb->context; + hfa384x_usbout_t *usbout = urb->transfer_buffer; #ifdef DEBUG_USB dbprint_urb(urb); #endif - if ( wlandev && - wlandev->netdev ) { + if (wlandev && wlandev->netdev) { - switch(urb->status) { + switch (urb->status) { case 0: hfa384x_usbout_tx(wlandev, usbout); break; case -EPIPE: - { - hfa384x_t *hw = wlandev->priv; - WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", - wlandev->netdev->name); - if ( !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) ) - schedule_work(&hw->usb_work); - ++(wlandev->linux_stats.tx_errors); - break; - } + { + hfa384x_t *hw = wlandev->priv; + printk(KERN_WARNING + "%s tx pipe stalled: requesting reset\n", + wlandev->netdev->name); + if (!test_and_set_bit + (WORK_TX_HALT, &hw->usb_flags)) + schedule_work(&hw->usb_work); + ++(wlandev->linux_stats.tx_errors); + break; + } case -EPROTO: case -ETIMEDOUT: case -EILSEQ: - { - hfa384x_t *hw = wlandev->priv; + { + hfa384x_t *hw = wlandev->priv; - if ( !test_and_set_bit(THROTTLE_TX, &hw->usb_flags) - && !timer_pending(&hw->throttle) ) { - mod_timer(&hw->throttle, - jiffies + THROTTLE_JIFFIES); + if (!test_and_set_bit + (THROTTLE_TX, &hw->usb_flags) + && !timer_pending(&hw->throttle)) { + mod_timer(&hw->throttle, + jiffies + THROTTLE_JIFFIES); + } + ++(wlandev->linux_stats.tx_errors); + netif_stop_queue(wlandev->netdev); + break; } - ++(wlandev->linux_stats.tx_errors); - netif_stop_queue(wlandev->netdev); - break; - } case -ENOENT: case -ESHUTDOWN: @@ -4230,16 +3769,14 @@ static void hfa384x_usbout_callback(struct urb *urb) break; default: - WLAN_LOG_INFO("unknown urb->status=%d\n", urb->status); + printk(KERN_INFO "unknown urb->status=%d\n", + urb->status); ++(wlandev->linux_stats.tx_errors); break; - } /* switch */ + } /* switch */ } - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_ctlxout_callback * @@ -4258,22 +3795,19 @@ static void hfa384x_usbout_callback(struct urb *urb) ----------------------------------------------------------------*/ static void hfa384x_ctlxout_callback(struct urb *urb) { - hfa384x_t *hw = urb->context; - int delete_resptimer = 0; - int timer_ok = 1; - int run_queue = 0; - hfa384x_usbctlx_t *ctlx; - unsigned long flags; + hfa384x_t *hw = urb->context; + int delete_resptimer = 0; + int timer_ok = 1; + int run_queue = 0; + hfa384x_usbctlx_t *ctlx; + unsigned long flags; - DBFENTER; - - WLAN_LOG_DEBUG(3,"urb->status=%d\n", urb->status); + pr_debug("urb->status=%d\n", urb->status); #ifdef DEBUG_USB dbprint_urb(urb); #endif - if ( (urb->status == -ESHUTDOWN) || - (urb->status == -ENODEV) || - (hw == NULL) ) + if ((urb->status == -ESHUTDOWN) || + (urb->status == -ENODEV) || (hw == NULL)) goto done; retry: @@ -4285,7 +3819,7 @@ retry: * rely on the disconnect function to clean everything * up if someone unplugged the adapter. */ - if ( list_empty(&hw->ctlxq.active) ) { + if (list_empty(&hw->ctlxq.active)) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); goto done; } @@ -4304,16 +3838,15 @@ retry: spin_unlock_irqrestore(&hw->ctlxq.lock, flags); goto retry; } - } - else { + } else { hw->req_timer_done = 1; } ctlx = get_active_ctlx(hw); - if ( urb->status == 0 ) { + if (urb->status == 0) { /* Request portion of a CTLX is successful */ - switch ( ctlx->state ) { + switch (ctlx->state) { case CTLX_REQ_SUBMITTED: /* This OUT-ACK received before IN */ ctlx->state = CTLX_REQ_COMPLETE; @@ -4330,18 +3863,19 @@ retry: default: /* This is NOT a valid CTLX "success" state! */ - WLAN_LOG_ERROR( - "Illegal CTLX[%d] success state(%s, %d) in OUT URB\n", - hfa384x2host_16(ctlx->outbuf.type), - ctlxstr(ctlx->state), urb->status); + printk(KERN_ERR + "Illegal CTLX[%d] success state(%s, %d) in OUT URB\n", + le16_to_cpu(ctlx->outbuf.type), + ctlxstr(ctlx->state), urb->status); break; - } /* switch */ + } /* switch */ } else { /* If the pipe has stalled then we need to reset it */ - if ( (urb->status == -EPIPE) && - !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags) ) { - WLAN_LOG_WARNING("%s tx pipe stalled: requesting reset\n", - hw->wlandev->netdev->name); + if ((urb->status == -EPIPE) && + !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags)) { + printk(KERN_WARNING + "%s tx pipe stalled: requesting reset\n", + hw->wlandev->netdev->name); schedule_work(&hw->usb_work); } @@ -4354,7 +3888,7 @@ retry: run_queue = 1; } - delresp: +delresp: if (delete_resptimer) { if ((timer_ok = del_timer(&hw->resptimer)) != 0) { hw->resp_timer_done = 1; @@ -4363,7 +3897,7 @@ retry: spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - if ( !timer_ok && (hw->resp_timer_done == 0) ) { + if (!timer_ok && (hw->resp_timer_done == 0)) { spin_lock_irqsave(&hw->ctlxq.lock, flags); goto delresp; } @@ -4371,11 +3905,10 @@ retry: if (run_queue) hfa384x_usbctlxq_run(hw); - done: - DBFEXIT; +done: + ; } - /*---------------------------------------------------------------- * hfa384x_usbctlx_reqtimerfn * @@ -4394,12 +3927,10 @@ retry: * Call context: * interrupt ----------------------------------------------------------------*/ -static void -hfa384x_usbctlx_reqtimerfn(unsigned long data) +static void hfa384x_usbctlx_reqtimerfn(unsigned long data) { - hfa384x_t *hw = (hfa384x_t*)data; - unsigned long flags; - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) data; + unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -4408,15 +3939,13 @@ hfa384x_usbctlx_reqtimerfn(unsigned long data) /* Removing the hardware automatically empties * the active list ... */ - if ( !list_empty(&hw->ctlxq.active) ) - { + if (!list_empty(&hw->ctlxq.active)) { /* * We must ensure that our URB is removed from * the system, if it hasn't already expired. */ hw->ctlx_urb.transfer_flags |= URB_ASYNC_UNLINK; - if (usb_unlink_urb(&hw->ctlx_urb) == -EINPROGRESS) - { + if (usb_unlink_urb(&hw->ctlx_urb) == -EINPROGRESS) { hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); ctlx->state = CTLX_REQ_FAILED; @@ -4436,11 +3965,8 @@ hfa384x_usbctlx_reqtimerfn(unsigned long data) } spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_usbctlx_resptimerfn * @@ -4459,13 +3985,10 @@ hfa384x_usbctlx_reqtimerfn(unsigned long data) * Call context: * interrupt ----------------------------------------------------------------*/ -static void -hfa384x_usbctlx_resptimerfn(unsigned long data) +static void hfa384x_usbctlx_resptimerfn(unsigned long data) { - hfa384x_t *hw = (hfa384x_t*)data; - unsigned long flags; - - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) data; + unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -4474,12 +3997,10 @@ hfa384x_usbctlx_resptimerfn(unsigned long data) /* The active list will be empty if the * adapter has been unplugged ... */ - if ( !list_empty(&hw->ctlxq.active) ) - { + if (!list_empty(&hw->ctlxq.active)) { hfa384x_usbctlx_t *ctlx = get_active_ctlx(hw); - if ( unlocked_usbctlx_cancel_async(hw, ctlx) == 0 ) - { + if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) { spin_unlock_irqrestore(&hw->ctlxq.lock, flags); hfa384x_usbctlxq_run(hw); goto done; @@ -4488,8 +4009,9 @@ hfa384x_usbctlx_resptimerfn(unsigned long data) spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - done: - DBFEXIT; +done: + ; + } /*---------------------------------------------------------------- @@ -4507,13 +4029,10 @@ hfa384x_usbctlx_resptimerfn(unsigned long data) * Call context: * Interrupt ----------------------------------------------------------------*/ -static void -hfa384x_usb_throttlefn(unsigned long data) +static void hfa384x_usb_throttlefn(unsigned long data) { - hfa384x_t *hw = (hfa384x_t*)data; - unsigned long flags; - - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) data; + unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -4521,25 +4040,20 @@ hfa384x_usb_throttlefn(unsigned long data) * We need to check BOTH the RX and the TX throttle controls, * so we use the bitwise OR instead of the logical OR. */ - WLAN_LOG_DEBUG(3, "flags=0x%lx\n", hw->usb_flags); - if ( !hw->wlandev->hwremoved && - ( - (test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) && - !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) - | - (test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) && - !test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags)) - ) ) - { + pr_debug("flags=0x%lx\n", hw->usb_flags); + if (!hw->wlandev->hwremoved && + ((test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) && + !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) + | + (test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) && + !test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags)) + )) { schedule_work(&hw->usb_work); } spin_unlock_irqrestore(&hw->ctlxq.lock, flags); - - DBFEXIT; } - /*---------------------------------------------------------------- * hfa384x_usbctlx_submit * @@ -4558,16 +4072,11 @@ hfa384x_usb_throttlefn(unsigned long data) * Call context: * process or interrupt ----------------------------------------------------------------*/ -static int -hfa384x_usbctlx_submit( - hfa384x_t *hw, - hfa384x_usbctlx_t *ctlx) +static int hfa384x_usbctlx_submit(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx) { unsigned long flags; int ret; - DBFENTER; - spin_lock_irqsave(&hw->ctlxq.lock, flags); if (hw->wlandev->hwremoved) { @@ -4582,11 +4091,9 @@ hfa384x_usbctlx_submit( ret = 0; } - DBFEXIT; return ret; } - /*---------------------------------------------------------------- * hfa384x_usbout_tx * @@ -4608,11 +4115,7 @@ hfa384x_usbctlx_submit( ----------------------------------------------------------------*/ static void hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout) { - DBFENTER; - prism2sta_ev_alloc(wlandev); - - DBFEXIT; } /*---------------------------------------------------------------- @@ -4631,10 +4134,9 @@ static void hfa384x_usbout_tx(wlandevice_t *wlandev, hfa384x_usbout_t *usbout) * * Call context: ----------------------------------------------------------------*/ -static int -hfa384x_isgood_pdrcode(u16 pdrcode) +static int hfa384x_isgood_pdrcode(u16 pdrcode) { - switch(pdrcode) { + switch (pdrcode) { case HFA384x_PDR_END_OF_PDA: case HFA384x_PDR_PCB_PARTNUM: case HFA384x_PDR_PDAVER: @@ -4668,23 +4170,20 @@ hfa384x_isgood_pdrcode(u16 pdrcode) return 1; break; default: - if ( pdrcode < 0x1000 ) { + if (pdrcode < 0x1000) { /* code is OK, but we don't know exactly what it is */ - WLAN_LOG_DEBUG(3, - "Encountered unknown PDR#=0x%04x, " - "assuming it's ok.\n", - pdrcode); + printk(KERN_DEBUG + "Encountered unknown PDR#=0x%04x, " + "assuming it's ok.\n", pdrcode); return 1; } else { /* bad code */ - WLAN_LOG_DEBUG(3, - "Encountered unknown PDR#=0x%04x, " - "(>=0x1000), assuming it's bad.\n", - pdrcode); + printk(KERN_DEBUG + "Encountered unknown PDR#=0x%04x, " + "(>=0x1000), assuming it's bad.\n", pdrcode); return 0; } break; } - return 0; /* avoid compiler warnings */ + return 0; /* avoid compiler warnings */ } - diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index dfc7b3a1e9c9..2abce0c34444 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -48,10 +48,8 @@ * 802.11 frame conversions. * * -------------------------------------------------------------------- -*/ -/*================================================================*/ -/* System Includes */ - +* +*================================================================ */ #include #include @@ -63,14 +61,10 @@ #include #include #include +#include #include -#include "wlan_compat.h" - -/*================================================================*/ -/* Project Includes */ - #include "p80211types.h" #include "p80211hdr.h" #include "p80211conv.h" @@ -80,30 +74,8 @@ #include "p80211ioctl.h" #include "p80211req.h" - -/*================================================================*/ -/* Local Constants */ - -/*================================================================*/ -/* Local Macros */ - - -/*================================================================*/ -/* Local Types */ - - -/*================================================================*/ -/* Local Static Definitions */ - -static u8 oui_rfc1042[] = {0x00, 0x00, 0x00}; -static u8 oui_8021h[] = {0x00, 0x00, 0xf8}; - -/*================================================================*/ -/* Local Function Declarations */ - - -/*================================================================*/ -/* Function Definitions */ +static u8 oui_rfc1042[] = { 0x00, 0x00, 0x00 }; +static u8 oui_8021h[] = { 0x00, 0x00, 0xf8 }; /*---------------------------------------------------------------- * p80211pb_ether_to_80211 @@ -130,35 +102,36 @@ static u8 oui_8021h[] = {0x00, 0x00, 0xf8}; * Call context: * May be called in interrupt or non-interrupt context ----------------------------------------------------------------*/ -int skb_ether_to_p80211( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) +int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, + struct sk_buff *skb, p80211_hdr_t *p80211_hdr, + p80211_metawep_t *p80211_wep) { - u16 fc; - u16 proto; - wlan_ethhdr_t e_hdr; - wlan_llc_t *e_llc; - wlan_snap_t *e_snap; + u16 fc; + u16 proto; + wlan_ethhdr_t e_hdr; + wlan_llc_t *e_llc; + wlan_snap_t *e_snap; int foo; - DBFENTER; memcpy(&e_hdr, skb->data, sizeof(e_hdr)); if (skb->len <= 0) { - WLAN_LOG_DEBUG(1, "zero-length skb!\n"); + pr_debug("zero-length skb!\n"); return 1; } - if ( ethconv == WLAN_ETHCONV_ENCAP ) { /* simplest case */ - WLAN_LOG_DEBUG(3, "ENCAP len: %d\n", skb->len); + if (ethconv == WLAN_ETHCONV_ENCAP) { /* simplest case */ + pr_debug("ENCAP len: %d\n", skb->len); /* here, we don't care what kind of ether frm. Just stick it */ /* in the 80211 payload */ /* which is to say, leave the skb alone. */ } else { /* step 1: classify ether frame, DIX or 802.3? */ proto = ntohs(e_hdr.type); - if ( proto <= 1500 ) { - WLAN_LOG_DEBUG(3, "802.3 len: %d\n", skb->len); - /* codes <= 1500 reserved for 802.3 lengths */ + if (proto <= 1500) { + pr_debug("802.3 len: %d\n", skb->len); + /* codes <= 1500 reserved for 802.3 lengths */ /* it's 802.3, pass ether payload unchanged, */ /* trim off ethernet header */ @@ -167,23 +140,28 @@ int skb_ether_to_p80211( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb /* leave off any PAD octets. */ skb_trim(skb, proto); } else { - WLAN_LOG_DEBUG(3, "DIXII len: %d\n", skb->len); + pr_debug("DIXII len: %d\n", skb->len); /* it's DIXII, time for some conversion */ /* trim off ethernet header */ skb_pull(skb, WLAN_ETHHDR_LEN); /* tack on SNAP */ - e_snap = (wlan_snap_t *) skb_push(skb, sizeof(wlan_snap_t)); + e_snap = + (wlan_snap_t *) skb_push(skb, sizeof(wlan_snap_t)); e_snap->type = htons(proto); - if ( ethconv == WLAN_ETHCONV_8021h && p80211_stt_findproto(proto) ) { - memcpy( e_snap->oui, oui_8021h, WLAN_IEEE_OUI_LEN); + if (ethconv == WLAN_ETHCONV_8021h + && p80211_stt_findproto(proto)) { + memcpy(e_snap->oui, oui_8021h, + WLAN_IEEE_OUI_LEN); } else { - memcpy( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN); + memcpy(e_snap->oui, oui_rfc1042, + WLAN_IEEE_OUI_LEN); } /* tack on llc */ - e_llc = (wlan_llc_t *) skb_push(skb, sizeof(wlan_llc_t)); + e_llc = + (wlan_llc_t *) skb_push(skb, sizeof(wlan_llc_t)); e_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */ e_llc->ssap = 0xAA; e_llc->ctl = 0x03; @@ -193,62 +171,61 @@ int skb_ether_to_p80211( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb /* Set up the 802.11 header */ /* It's a data frame */ - fc = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) | - WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY)); + fc = cpu_to_le16(WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) | + WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY)); - switch ( wlandev->macmode ) { + switch (wlandev->macmode) { case WLAN_MACMODE_IBSS_STA: - memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, WLAN_ADDR_LEN); - memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, WLAN_ADDR_LEN); - memcpy(p80211_hdr->a3.a3, wlandev->bssid, WLAN_ADDR_LEN); + memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, ETH_ALEN); + memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, ETH_ALEN); + memcpy(p80211_hdr->a3.a3, wlandev->bssid, ETH_ALEN); break; case WLAN_MACMODE_ESS_STA: - fc |= host2ieee16(WLAN_SET_FC_TODS(1)); - memcpy(p80211_hdr->a3.a1, wlandev->bssid, WLAN_ADDR_LEN); - memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, WLAN_ADDR_LEN); - memcpy(p80211_hdr->a3.a3, &e_hdr.daddr, WLAN_ADDR_LEN); + fc |= cpu_to_le16(WLAN_SET_FC_TODS(1)); + memcpy(p80211_hdr->a3.a1, wlandev->bssid, ETH_ALEN); + memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, ETH_ALEN); + memcpy(p80211_hdr->a3.a3, &e_hdr.daddr, ETH_ALEN); break; case WLAN_MACMODE_ESS_AP: - fc |= host2ieee16(WLAN_SET_FC_FROMDS(1)); - memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, WLAN_ADDR_LEN); - memcpy(p80211_hdr->a3.a2, wlandev->bssid, WLAN_ADDR_LEN); - memcpy(p80211_hdr->a3.a3, &e_hdr.saddr, WLAN_ADDR_LEN); + fc |= cpu_to_le16(WLAN_SET_FC_FROMDS(1)); + memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, ETH_ALEN); + memcpy(p80211_hdr->a3.a2, wlandev->bssid, ETH_ALEN); + memcpy(p80211_hdr->a3.a3, &e_hdr.saddr, ETH_ALEN); break; default: - WLAN_LOG_ERROR("Error: Converting eth to wlan in unknown mode.\n"); + printk(KERN_ERR + "Error: Converting eth to wlan in unknown mode.\n"); return 1; break; } p80211_wep->data = NULL; - if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && (wlandev->hostwep & HOSTWEP_ENCRYPT)) { - // XXXX need to pick keynum other than default? + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) + && (wlandev->hostwep & HOSTWEP_ENCRYPT)) { + /* XXXX need to pick keynum other than default? */ -#if 1 p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC); -#else - p80211_wep->data = skb->data; -#endif if ((foo = wep_encrypt(wlandev, skb->data, p80211_wep->data, skb->len, - (wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK), - p80211_wep->iv, p80211_wep->icv))) { - WLAN_LOG_WARNING("Host en-WEP failed, dropping frame (%d).\n", foo); + (wlandev-> + hostwep & HOSTWEP_DEFAULTKEY_MASK), + p80211_wep->iv, p80211_wep->icv))) { + printk(KERN_WARNING + "Host en-WEP failed, dropping frame (%d).\n", + foo); return 2; } - fc |= host2ieee16(WLAN_SET_FC_ISWEP(1)); + fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1)); } - - // skb->nh.raw = skb->data; + /* skb->nh.raw = skb->data; */ p80211_hdr->a3.fc = fc; p80211_hdr->a3.dur = 0; p80211_hdr->a3.seq = 0; - DBFEXIT; return 0; } @@ -256,22 +233,24 @@ int skb_ether_to_p80211( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, p80211_rxmeta_t *rxmeta) { - int i; + int i; - /* Gather wireless spy statistics: for each packet, compare the - * source address with out list, and if match, get the stats... */ + /* Gather wireless spy statistics: for each packet, compare the + * source address with out list, and if match, get the stats... */ - for (i = 0; i < wlandev->spy_number; i++) { + for (i = 0; i < wlandev->spy_number; i++) { - if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) { + if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) { memcpy(wlandev->spy_address[i], mac, ETH_ALEN); - wlandev->spy_stat[i].level = rxmeta->signal; - wlandev->spy_stat[i].noise = rxmeta->noise; - wlandev->spy_stat[i].qual = (rxmeta->signal > rxmeta->noise) ? \ - (rxmeta->signal - rxmeta->noise) : 0; - wlandev->spy_stat[i].updated = 0x7; - } - } + wlandev->spy_stat[i].level = rxmeta->signal; + wlandev->spy_stat[i].noise = rxmeta->noise; + wlandev->spy_stat[i].qual = + (rxmeta->signal > + rxmeta->noise) ? (rxmeta->signal - + rxmeta->noise) : 0; + wlandev->spy_stat[i].updated = 0x7; + } + } } /*---------------------------------------------------------------- @@ -293,43 +272,42 @@ static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, * Call context: * May be called in interrupt or non-interrupt context ----------------------------------------------------------------*/ -int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb) +int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, + struct sk_buff *skb) { - netdevice_t *netdev = wlandev->netdev; - u16 fc; - unsigned int payload_length; - unsigned int payload_offset; - u8 daddr[WLAN_ETHADDR_LEN]; - u8 saddr[WLAN_ETHADDR_LEN]; - p80211_hdr_t *w_hdr; - wlan_ethhdr_t *e_hdr; - wlan_llc_t *e_llc; - wlan_snap_t *e_snap; + netdevice_t *netdev = wlandev->netdev; + u16 fc; + unsigned int payload_length; + unsigned int payload_offset; + u8 daddr[WLAN_ETHADDR_LEN]; + u8 saddr[WLAN_ETHADDR_LEN]; + p80211_hdr_t *w_hdr; + wlan_ethhdr_t *e_hdr; + wlan_llc_t *e_llc; + wlan_snap_t *e_snap; int foo; - DBFENTER; - payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN; payload_offset = WLAN_HDR_A3_LEN; w_hdr = (p80211_hdr_t *) skb->data; - /* setup some vars for convenience */ - fc = ieee2host16(w_hdr->a3.fc); - if ( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0) ) { + /* setup some vars for convenience */ + fc = le16_to_cpu(w_hdr->a3.fc); + if ((WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0)) { memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN); memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN); - } else if( (WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 1) ) { + } else if ((WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 1)) { memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN); memcpy(saddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN); - } else if( (WLAN_GET_FC_TODS(fc) == 1) && (WLAN_GET_FC_FROMDS(fc) == 0) ) { + } else if ((WLAN_GET_FC_TODS(fc) == 1) && (WLAN_GET_FC_FROMDS(fc) == 0)) { memcpy(daddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN); memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN); } else { payload_offset = WLAN_HDR_A4_LEN; if (payload_length < WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN) { - WLAN_LOG_ERROR("A4 frame too short!\n"); + printk(KERN_ERR "A4 frame too short!\n"); return 1; } payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN); @@ -338,18 +316,22 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb } /* perform de-wep if necessary.. */ - if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc) && (wlandev->hostwep & HOSTWEP_DECRYPT)) { + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc) + && (wlandev->hostwep & HOSTWEP_DECRYPT)) { if (payload_length <= 8) { - WLAN_LOG_ERROR("WEP frame too short (%u).\n", - skb->len); + printk(KERN_ERR "WEP frame too short (%u).\n", + skb->len); return 1; } if ((foo = wep_decrypt(wlandev, skb->data + payload_offset + 4, payload_length - 8, -1, skb->data + payload_offset, - skb->data + payload_offset + payload_length - 4))) { + skb->data + payload_offset + + payload_length - 4))) { /* de-wep failed, drop skb. */ - WLAN_LOG_DEBUG(1, "Host de-WEP failed, dropping frame (%d).\n", foo); + printk(KERN_DEBUG + "Host de-WEP failed, dropping frame (%d).\n", + foo); wlandev->rx.decrypt_err++; return 2; } @@ -367,21 +349,22 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb e_hdr = (wlan_ethhdr_t *) (skb->data + payload_offset); e_llc = (wlan_llc_t *) (skb->data + payload_offset); - e_snap = (wlan_snap_t *) (skb->data + payload_offset + sizeof(wlan_llc_t)); + e_snap = + (wlan_snap_t *) (skb->data + payload_offset + sizeof(wlan_llc_t)); /* Test for the various encodings */ - if ( (payload_length >= sizeof(wlan_ethhdr_t)) && - ( e_llc->dsap != 0xaa || e_llc->ssap != 0xaa ) && - ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) || + if ((payload_length >= sizeof(wlan_ethhdr_t)) && + (e_llc->dsap != 0xaa || e_llc->ssap != 0xaa) && + ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) || (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0))) { - WLAN_LOG_DEBUG(3, "802.3 ENCAP len: %d\n", payload_length); + pr_debug("802.3 ENCAP len: %d\n", payload_length); /* 802.3 Encapsulated */ /* Test for an overlength frame */ - if ( payload_length > (netdev->mtu + WLAN_ETHHDR_LEN)) { + if (payload_length > (netdev->mtu + WLAN_ETHHDR_LEN)) { /* A bogus length ethfrm has been encap'd. */ /* Is someone trying an oflow attack? */ - WLAN_LOG_ERROR("ENCAP frame too large (%d > %d)\n", - payload_length, netdev->mtu + WLAN_ETHHDR_LEN); + printk(KERN_ERR "ENCAP frame too large (%d > %d)\n", + payload_length, netdev->mtu + WLAN_ETHHDR_LEN); return 1; } @@ -390,25 +373,25 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb /* chop off the 802.11 CRC */ skb_trim(skb, skb->len - WLAN_CRC_LEN); - } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) && - (e_llc->dsap == 0xaa) && - (e_llc->ssap == 0xaa) && - (e_llc->ctl == 0x03) && - (((memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)==0) && - (ethconv == WLAN_ETHCONV_8021h) && - (p80211_stt_findproto(ieee2host16(e_snap->type)))) || - (memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)!=0))) - { - WLAN_LOG_DEBUG(3, "SNAP+RFC1042 len: %d\n", payload_length); + } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) + && (e_llc->dsap == 0xaa) && (e_llc->ssap == 0xaa) + && (e_llc->ctl == 0x03) + && + (((memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) == 0) + && (ethconv == WLAN_ETHCONV_8021h) + && (p80211_stt_findproto(le16_to_cpu(e_snap->type)))) + || (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) != + 0))) { + pr_debug("SNAP+RFC1042 len: %d\n", payload_length); /* it's a SNAP + RFC1042 frame && protocol is in STT */ /* build 802.3 + RFC1042 */ /* Test for an overlength frame */ - if ( payload_length > netdev->mtu ) { + if (payload_length > netdev->mtu) { /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ - WLAN_LOG_ERROR("SNAP frame too large (%d > %d)\n", - payload_length, netdev->mtu); + printk(KERN_ERR "SNAP frame too large (%d > %d)\n", + payload_length, netdev->mtu); return 1; } @@ -424,11 +407,10 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb /* chop off the 802.11 CRC */ skb_trim(skb, skb->len - WLAN_CRC_LEN); - } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) && - (e_llc->dsap == 0xaa) && - (e_llc->ssap == 0xaa) && - (e_llc->ctl == 0x03) ) { - WLAN_LOG_DEBUG(3, "802.1h/RFC1042 len: %d\n", payload_length); + } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) + && (e_llc->dsap == 0xaa) && (e_llc->ssap == 0xaa) + && (e_llc->ctl == 0x03)) { + pr_debug("802.1h/RFC1042 len: %d\n", payload_length); /* it's an 802.1h frame || (an RFC1042 && protocol is not in STT) */ /* build a DIXII + RFC894 */ @@ -437,10 +419,9 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb > netdev->mtu) { /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ - WLAN_LOG_ERROR("DIXII frame too large (%ld > %d)\n", - (long int) (payload_length - sizeof(wlan_llc_t) - - sizeof(wlan_snap_t)), - netdev->mtu); + printk(KERN_ERR "DIXII frame too large (%ld > %d)\n", + (long int)(payload_length - sizeof(wlan_llc_t) - + sizeof(wlan_snap_t)), netdev->mtu); return 1; } @@ -462,19 +443,18 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb /* chop off the 802.11 CRC */ skb_trim(skb, skb->len - WLAN_CRC_LEN); } else { - WLAN_LOG_DEBUG(3, "NON-ENCAP len: %d\n", payload_length); + pr_debug("NON-ENCAP len: %d\n", payload_length); /* any NON-ENCAP */ /* it's a generic 80211+LLC or IPX 'Raw 802.3' */ /* build an 802.3 frame */ /* allocate space and setup hostbuf */ /* Test for an overlength frame */ - if ( payload_length > netdev->mtu ) { + if (payload_length > netdev->mtu) { /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ - WLAN_LOG_ERROR("OTHER frame too large (%d > %d)\n", - payload_length, - netdev->mtu); + printk(KERN_ERR "OTHER frame too large (%d > %d)\n", + payload_length, netdev->mtu); return 1; } @@ -492,26 +472,26 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb } - /* - * Note that eth_type_trans() expects an skb w/ skb->data pointing - * at the MAC header, it then sets the following skb members: - * skb->mac_header, - * skb->data, and - * skb->pkt_type. - * It then _returns_ the value that _we're_ supposed to stuff in - * skb->protocol. This is nuts. - */ + /* + * Note that eth_type_trans() expects an skb w/ skb->data pointing + * at the MAC header, it then sets the following skb members: + * skb->mac_header, + * skb->data, and + * skb->pkt_type. + * It then _returns_ the value that _we're_ supposed to stuff in + * skb->protocol. This is nuts. + */ skb->protocol = eth_type_trans(skb, netdev); - /* jkriegl: process signal and noise as set in hfa384x_int_rx() */ + /* jkriegl: process signal and noise as set in hfa384x_int_rx() */ /* jkriegl: only process signal/noise if requested by iwspy */ - if (wlandev->spy_number) - orinoco_spy_gather(wlandev, eth_hdr(skb)->h_source, P80211SKB_RXMETA(skb)); + if (wlandev->spy_number) + orinoco_spy_gather(wlandev, eth_hdr(skb)->h_source, + P80211SKB_RXMETA(skb)); /* Free the metadata */ p80211skb_rxmeta_detach(skb); - DBFEXIT; return 0; } @@ -536,11 +516,11 @@ int p80211_stt_findproto(u16 proto) /* Always return found for now. This is the behavior used by the */ /* Zoom Win95 driver when 802.1h mode is selected */ /* TODO: If necessary, add an actual search we'll probably - need this to match the CMAC's way of doing things. - Need to do some testing to confirm. - */ + need this to match the CMAC's way of doing things. + Need to do some testing to confirm. + */ - if (proto == 0x80f3) /* APPLETALK */ + if (proto == 0x80f3) /* APPLETALK */ return 1; return 0; @@ -561,26 +541,24 @@ int p80211_stt_findproto(u16 proto) * Call context: * May be called in interrupt or non-interrupt context ----------------------------------------------------------------*/ -void -p80211skb_rxmeta_detach(struct sk_buff *skb) +void p80211skb_rxmeta_detach(struct sk_buff *skb) { - p80211_rxmeta_t *rxmeta; - p80211_frmmeta_t *frmmeta; + p80211_rxmeta_t *rxmeta; + p80211_frmmeta_t *frmmeta; - DBFENTER; /* Sanity checks */ - if ( skb==NULL ) { /* bad skb */ - WLAN_LOG_DEBUG(1, "Called w/ null skb.\n"); + if (skb == NULL) { /* bad skb */ + pr_debug("Called w/ null skb.\n"); goto exit; } frmmeta = P80211SKB_FRMMETA(skb); - if ( frmmeta == NULL ) { /* no magic */ - WLAN_LOG_DEBUG(1, "Called w/ bad frmmeta magic.\n"); + if (frmmeta == NULL) { /* no magic */ + pr_debug("Called w/ bad frmmeta magic.\n"); goto exit; } rxmeta = frmmeta->rx; - if ( rxmeta == NULL ) { /* bad meta ptr */ - WLAN_LOG_DEBUG(1, "Called w/ bad rxmeta ptr.\n"); + if (rxmeta == NULL) { /* bad meta ptr */ + pr_debug("Called w/ bad rxmeta ptr.\n"); goto exit; } @@ -590,7 +568,6 @@ p80211skb_rxmeta_detach(struct sk_buff *skb) /* Clear skb->cb */ memset(skb->cb, 0, sizeof(skb->cb)); exit: - DBFEXIT; return; } @@ -610,19 +587,16 @@ exit: * Call context: * May be called in interrupt or non-interrupt context ----------------------------------------------------------------*/ -int -p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) +int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) { - int result = 0; - p80211_rxmeta_t *rxmeta; - p80211_frmmeta_t *frmmeta; - - DBFENTER; + int result = 0; + p80211_rxmeta_t *rxmeta; + p80211_frmmeta_t *frmmeta; /* If these already have metadata, we error out! */ if (P80211SKB_RXMETA(skb) != NULL) { - WLAN_LOG_ERROR("%s: RXmeta already attached!\n", - wlandev->name); + printk(KERN_ERR "%s: RXmeta already attached!\n", + wlandev->name); result = 0; goto exit; } @@ -630,9 +604,9 @@ p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) /* Allocate the rxmeta */ rxmeta = kmalloc(sizeof(p80211_rxmeta_t), GFP_ATOMIC); - if ( rxmeta == NULL ) { - WLAN_LOG_ERROR("%s: Failed to allocate rxmeta.\n", - wlandev->name); + if (rxmeta == NULL) { + printk(KERN_ERR "%s: Failed to allocate rxmeta.\n", + wlandev->name); result = 1; goto exit; } @@ -644,11 +618,10 @@ p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) /* Overlay a frmmeta_t onto skb->cb */ memset(skb->cb, 0, sizeof(p80211_frmmeta_t)); - frmmeta = (p80211_frmmeta_t*)(skb->cb); + frmmeta = (p80211_frmmeta_t *) (skb->cb); frmmeta->magic = P80211_FRMMETA_MAGIC; frmmeta->rx = rxmeta; exit: - DBFEXIT; return result; } @@ -668,19 +641,15 @@ exit: * Call context: * May be called in interrupt or non-interrupt context ----------------------------------------------------------------*/ -void -p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb) +void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb) { - p80211_frmmeta_t *meta; - DBFENTER; - meta = P80211SKB_FRMMETA(skb); - if ( meta && meta->rx) { - p80211skb_rxmeta_detach(skb); - } else { - WLAN_LOG_ERROR("Freeing an skb (%p) w/ no frmmeta.\n", skb); - } + p80211_frmmeta_t *meta; + meta = P80211SKB_FRMMETA(skb); + if (meta && meta->rx) + p80211skb_rxmeta_detach(skb); + else + printk(KERN_ERR "Freeing an skb (%p) w/ no frmmeta.\n", skb); dev_kfree_skb(skb); - DBFEXIT; return; } diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h index 538e9bd14902..6fe163be24f6 100644 --- a/drivers/staging/wlan-ng/p80211conv.h +++ b/drivers/staging/wlan-ng/p80211conv.h @@ -53,134 +53,109 @@ #ifndef _LINUX_P80211CONV_H #define _LINUX_P80211CONV_H -/*================================================================*/ -/* Constants */ - #define WLAN_ETHADDR_LEN 6 #define WLAN_IEEE_OUI_LEN 3 #define WLAN_ETHCONV_ENCAP 1 -#define WLAN_ETHCONV_RFC1042 2 #define WLAN_ETHCONV_8021h 3 -#define WLAN_MIN_ETHFRM_LEN 60 -#define WLAN_MAX_ETHFRM_LEN 1514 #define WLAN_ETHHDR_LEN 14 #define P80211CAPTURE_VERSION 0x80211001 -/*================================================================*/ -/* Macros */ - #define P80211_FRMMETA_MAGIC 0x802110 #define P80211SKB_FRMMETA(s) \ - (((((p80211_frmmeta_t*)((s)->cb))->magic)==P80211_FRMMETA_MAGIC) ? \ - ((p80211_frmmeta_t*)((s)->cb)) : \ + (((((p80211_frmmeta_t *)((s)->cb))->magic) == P80211_FRMMETA_MAGIC) ? \ + ((p80211_frmmeta_t *)((s)->cb)) : \ (NULL)) #define P80211SKB_RXMETA(s) \ - (P80211SKB_FRMMETA((s)) ? P80211SKB_FRMMETA((s))->rx : ((p80211_rxmeta_t*)(NULL))) + (P80211SKB_FRMMETA((s)) ? P80211SKB_FRMMETA((s))->rx : ((p80211_rxmeta_t *)(NULL))) -typedef struct p80211_rxmeta -{ - struct wlandevice *wlandev; +typedef struct p80211_rxmeta { + struct wlandevice *wlandev; - u64 mactime; /* Hi-rez MAC-supplied time value */ - u64 hosttime; /* Best-rez host supplied time value */ + u64 mactime; /* Hi-rez MAC-supplied time value */ + u64 hosttime; /* Best-rez host supplied time value */ - unsigned int rxrate; /* Receive data rate in 100kbps */ - unsigned int priority; /* 0-15, 0=contention, 6=CF */ - int signal; /* An SSI, see p80211netdev.h */ - int noise; /* An SSI, see p80211netdev.h */ - unsigned int channel; /* Receive channel (mostly for snifs) */ - unsigned int preamble; /* P80211ENUM_preambletype_* */ - unsigned int encoding; /* P80211ENUM_encoding_* */ + unsigned int rxrate; /* Receive data rate in 100kbps */ + unsigned int priority; /* 0-15, 0=contention, 6=CF */ + int signal; /* An SSI, see p80211netdev.h */ + int noise; /* An SSI, see p80211netdev.h */ + unsigned int channel; /* Receive channel (mostly for snifs) */ + unsigned int preamble; /* P80211ENUM_preambletype_* */ + unsigned int encoding; /* P80211ENUM_encoding_* */ } p80211_rxmeta_t; -typedef struct p80211_frmmeta -{ - unsigned int magic; - p80211_rxmeta_t *rx; +typedef struct p80211_frmmeta { + unsigned int magic; + p80211_rxmeta_t *rx; } p80211_frmmeta_t; void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb); int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb); void p80211skb_rxmeta_detach(struct sk_buff *skb); -/*================================================================*/ -/* Types */ - /* * Frame capture header. (See doc/capturefrm.txt) */ -typedef struct p80211_caphdr -{ - u32 version; - u32 length; - u64 mactime; - u64 hosttime; - u32 phytype; - u32 channel; - u32 datarate; - u32 antenna; - u32 priority; - u32 ssi_type; - s32 ssi_signal; - s32 ssi_noise; - u32 preamble; - u32 encoding; +typedef struct p80211_caphdr { + u32 version; + u32 length; + u64 mactime; + u64 hosttime; + u32 phytype; + u32 channel; + u32 datarate; + u32 antenna; + u32 priority; + u32 ssi_type; + s32 ssi_signal; + s32 ssi_noise; + u32 preamble; + u32 encoding; } p80211_caphdr_t; /* buffer free method pointer type */ -typedef void (* freebuf_method_t)(void *buf, int size); +typedef void (*freebuf_method_t) (void *buf, int size); typedef struct p80211_metawep { - void *data; + void *data; u8 iv[4]; u8 icv[4]; } p80211_metawep_t; /* local ether header type */ -typedef struct wlan_ethhdr -{ - u8 daddr[WLAN_ETHADDR_LEN]; - u8 saddr[WLAN_ETHADDR_LEN]; - u16 type; -} __WLAN_ATTRIB_PACK__ wlan_ethhdr_t; +typedef struct wlan_ethhdr { + u8 daddr[WLAN_ETHADDR_LEN]; + u8 saddr[WLAN_ETHADDR_LEN]; + u16 type; +} __attribute__ ((packed)) wlan_ethhdr_t; /* local llc header type */ -typedef struct wlan_llc -{ - u8 dsap; - u8 ssap; - u8 ctl; -} __WLAN_ATTRIB_PACK__ wlan_llc_t; +typedef struct wlan_llc { + u8 dsap; + u8 ssap; + u8 ctl; +} __attribute__ ((packed)) wlan_llc_t; /* local snap header type */ -typedef struct wlan_snap -{ - u8 oui[WLAN_IEEE_OUI_LEN]; - u16 type; -} __WLAN_ATTRIB_PACK__ wlan_snap_t; +typedef struct wlan_snap { + u8 oui[WLAN_IEEE_OUI_LEN]; + u16 type; +} __attribute__ ((packed)) wlan_snap_t; /* Circular include trick */ struct wlandevice; -/*================================================================*/ -/* Externs */ - -/*================================================================*/ -/*Function Declarations */ - -int skb_p80211_to_ether( struct wlandevice *wlandev, u32 ethconv, - struct sk_buff *skb); -int skb_ether_to_p80211( struct wlandevice *wlandev, u32 ethconv, - struct sk_buff *skb, p80211_hdr_t *p80211_hdr, - p80211_metawep_t *p80211_wep ); +int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv, + struct sk_buff *skb); +int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv, + struct sk_buff *skb, p80211_hdr_t *p80211_hdr, + p80211_metawep_t *p80211_wep); int p80211_stt_findproto(u16 proto); -int p80211_stt_addproto(u16 proto); #endif diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h index 72f12aff3900..ded477517690 100644 --- a/drivers/staging/wlan-ng/p80211hdr.h +++ b/drivers/staging/wlan-ng/p80211hdr.h @@ -63,43 +63,23 @@ /*================================================================*/ /* System Includes */ +#include + /*================================================================*/ /* Project Includes */ -#ifndef _WLAN_COMPAT_H -#include "wlan_compat.h" -#endif /*================================================================*/ /* Constants */ /*--- Sizes -----------------------------------------------*/ -#define WLAN_ADDR_LEN 6 #define WLAN_CRC_LEN 4 #define WLAN_BSSID_LEN 6 -#define WLAN_BSS_TS_LEN 8 #define WLAN_HDR_A3_LEN 24 #define WLAN_HDR_A4_LEN 30 #define WLAN_SSID_MAXLEN 32 #define WLAN_DATA_MAXLEN 2312 -#define WLAN_A3FR_MAXLEN (WLAN_HDR_A3_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) -#define WLAN_A4FR_MAXLEN (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) -#define WLAN_BEACON_FR_MAXLEN (WLAN_HDR_A3_LEN + 334) -#define WLAN_ATIM_FR_MAXLEN (WLAN_HDR_A3_LEN + 0) -#define WLAN_DISASSOC_FR_MAXLEN (WLAN_HDR_A3_LEN + 2) -#define WLAN_ASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 48) -#define WLAN_ASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16) -#define WLAN_REASSOCREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 54) -#define WLAN_REASSOCRESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 16) -#define WLAN_PROBEREQ_FR_MAXLEN (WLAN_HDR_A3_LEN + 44) -#define WLAN_PROBERESP_FR_MAXLEN (WLAN_HDR_A3_LEN + 78) -#define WLAN_AUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 261) -#define WLAN_DEAUTHEN_FR_MAXLEN (WLAN_HDR_A3_LEN + 2) -#define WLAN_WEP_NKEYS 4 -#define WLAN_WEP_MAXKEYLEN 13 -#define WLAN_CHALLENGE_IE_LEN 130 -#define WLAN_CHALLENGE_LEN 128 #define WLAN_WEP_IV_LEN 4 #define WLAN_WEP_ICV_LEN 4 @@ -143,7 +123,6 @@ #define WLAN_FSTYPE_CFPOLL 0x06 #define WLAN_FSTYPE_CFACK_CFPOLL 0x07 - /*================================================================*/ /* Macros */ @@ -166,97 +145,51 @@ /* SET_FC_FSTYPE(WLAN_FSTYPE_RTS) ); */ /*------------------------------------------------------------*/ -#define WLAN_GET_FC_PVER(n) (((u16)(n)) & (BIT0 | BIT1)) -#define WLAN_GET_FC_FTYPE(n) ((((u16)(n)) & (BIT2 | BIT3)) >> 2) -#define WLAN_GET_FC_FSTYPE(n) ((((u16)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4) -#define WLAN_GET_FC_TODS(n) ((((u16)(n)) & (BIT8)) >> 8) -#define WLAN_GET_FC_FROMDS(n) ((((u16)(n)) & (BIT9)) >> 9) -#define WLAN_GET_FC_MOREFRAG(n) ((((u16)(n)) & (BIT10)) >> 10) -#define WLAN_GET_FC_RETRY(n) ((((u16)(n)) & (BIT11)) >> 11) -#define WLAN_GET_FC_PWRMGT(n) ((((u16)(n)) & (BIT12)) >> 12) -#define WLAN_GET_FC_MOREDATA(n) ((((u16)(n)) & (BIT13)) >> 13) -#define WLAN_GET_FC_ISWEP(n) ((((u16)(n)) & (BIT14)) >> 14) -#define WLAN_GET_FC_ORDER(n) ((((u16)(n)) & (BIT15)) >> 15) +#define WLAN_GET_FC_FTYPE(n) ((((u16)(n)) & (BIT(2) | BIT(3))) >> 2) +#define WLAN_GET_FC_FSTYPE(n) ((((u16)(n)) & (BIT(4)|BIT(5)|BIT(6)|BIT(7))) >> 4) +#define WLAN_GET_FC_TODS(n) ((((u16)(n)) & (BIT(8))) >> 8) +#define WLAN_GET_FC_FROMDS(n) ((((u16)(n)) & (BIT(9))) >> 9) +#define WLAN_GET_FC_ISWEP(n) ((((u16)(n)) & (BIT(14))) >> 14) -#define WLAN_SET_FC_PVER(n) ((u16)(n)) #define WLAN_SET_FC_FTYPE(n) (((u16)(n)) << 2) #define WLAN_SET_FC_FSTYPE(n) (((u16)(n)) << 4) #define WLAN_SET_FC_TODS(n) (((u16)(n)) << 8) #define WLAN_SET_FC_FROMDS(n) (((u16)(n)) << 9) -#define WLAN_SET_FC_MOREFRAG(n) (((u16)(n)) << 10) -#define WLAN_SET_FC_RETRY(n) (((u16)(n)) << 11) -#define WLAN_SET_FC_PWRMGT(n) (((u16)(n)) << 12) -#define WLAN_SET_FC_MOREDATA(n) (((u16)(n)) << 13) #define WLAN_SET_FC_ISWEP(n) (((u16)(n)) << 14) -#define WLAN_SET_FC_ORDER(n) (((u16)(n)) << 15) -/*--- Duration Macros ----------------------------------------*/ -/* Macros to get/set the bitfields of the Duration Field */ -/* - the duration value is only valid when bit15 is zero */ -/* - the firmware handles these values, so I'm not going */ -/* these macros right now. */ -/*------------------------------------------------------------*/ - -/*--- Sequence Control Macros -------------------------------*/ -/* Macros to get/set the bitfields of the Sequence Control */ -/* Field. */ -/*------------------------------------------------------------*/ -#define WLAN_GET_SEQ_FRGNUM(n) (((u16)(n)) & (BIT0|BIT1|BIT2|BIT3)) -#define WLAN_GET_SEQ_SEQNUM(n) ((((u16)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4) - -/*--- Data ptr macro -----------------------------------------*/ -/* Creates a u8* to the data portion of a frame */ -/* Assumes you're passing in a ptr to the beginning of the hdr*/ -/*------------------------------------------------------------*/ -#define WLAN_HDR_A3_DATAP(p) (((u8*)(p)) + WLAN_HDR_A3_LEN) -#define WLAN_HDR_A4_DATAP(p) (((u8*)(p)) + WLAN_HDR_A4_LEN) - -#define DOT11_RATE5_ISBASIC_GET(r) (((u8)(r)) & BIT7) +#define DOT11_RATE5_ISBASIC_GET(r) (((u8)(r)) & BIT(7)) /*================================================================*/ /* Types */ -/* BSS Timestamp */ -typedef u8 wlan_bss_ts_t[WLAN_BSS_TS_LEN]; - /* Generic 802.11 Header types */ -typedef struct p80211_hdr_a3 -{ - u16 fc; - u16 dur; - u8 a1[WLAN_ADDR_LEN]; - u8 a2[WLAN_ADDR_LEN]; - u8 a3[WLAN_ADDR_LEN]; - u16 seq; -} __WLAN_ATTRIB_PACK__ p80211_hdr_a3_t; +typedef struct p80211_hdr_a3 { + u16 fc; + u16 dur; + u8 a1[ETH_ALEN]; + u8 a2[ETH_ALEN]; + u8 a3[ETH_ALEN]; + u16 seq; +} __attribute__ ((packed)) p80211_hdr_a3_t; -typedef struct p80211_hdr_a4 -{ - u16 fc; - u16 dur; - u8 a1[WLAN_ADDR_LEN]; - u8 a2[WLAN_ADDR_LEN]; - u8 a3[WLAN_ADDR_LEN]; - u16 seq; - u8 a4[WLAN_ADDR_LEN]; -} __WLAN_ATTRIB_PACK__ p80211_hdr_a4_t; +typedef struct p80211_hdr_a4 { + u16 fc; + u16 dur; + u8 a1[ETH_ALEN]; + u8 a2[ETH_ALEN]; + u8 a3[ETH_ALEN]; + u16 seq; + u8 a4[ETH_ALEN]; +} __attribute__ ((packed)) p80211_hdr_a4_t; -typedef union p80211_hdr -{ - p80211_hdr_a3_t a3; - p80211_hdr_a4_t a4; -} __WLAN_ATTRIB_PACK__ p80211_hdr_t; +typedef union p80211_hdr { + p80211_hdr_a3_t a3; + p80211_hdr_a4_t a4; +} __attribute__ ((packed)) p80211_hdr_t; -/*================================================================*/ -/* Extern Declarations */ - - -/*================================================================*/ -/* Function Declarations */ - -/* Frame and header lenght macros */ +/* Frame and header length macros */ #define WLAN_CTL_FRAMELEN(fstype) (\ (fstype) == WLAN_FSTYPE_BLOCKACKREQ ? 24 : \ @@ -271,23 +204,22 @@ typedef union p80211_hdr #define WLAN_FCS_LEN 4 /* ftcl in HOST order */ -inline static u16 p80211_headerlen(u16 fctl) +static inline u16 p80211_headerlen(u16 fctl) { u16 hdrlen = 0; - switch ( WLAN_GET_FC_FTYPE(fctl) ) { + switch (WLAN_GET_FC_FTYPE(fctl)) { case WLAN_FTYPE_MGMT: hdrlen = WLAN_HDR_A3_LEN; break; case WLAN_FTYPE_DATA: hdrlen = WLAN_HDR_A3_LEN; - if ( WLAN_GET_FC_TODS(fctl) && WLAN_GET_FC_FROMDS(fctl) ) { - hdrlen += WLAN_ADDR_LEN; - } + if (WLAN_GET_FC_TODS(fctl) && WLAN_GET_FC_FROMDS(fctl)) + hdrlen += ETH_ALEN; break; case WLAN_FTYPE_CTL: hdrlen = WLAN_CTL_FRAMELEN(WLAN_GET_FC_FSTYPE(fctl)) - - WLAN_FCS_LEN; + WLAN_FCS_LEN; break; default: hdrlen = WLAN_HDR_A3_LEN; diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h index ad67b698fa43..64ca7f95262c 100644 --- a/drivers/staging/wlan-ng/p80211ioctl.h +++ b/drivers/staging/wlan-ng/p80211ioctl.h @@ -60,14 +60,9 @@ * -------------------------------------------------------------------- */ - #ifndef _P80211IOCTL_H #define _P80211IOCTL_H -/*================================================================*/ -/* Constants */ - -/*----------------------------------------------------------------*/ /* p80211 ioctl "request" codes. See argument 2 of ioctl(2). */ #define P80211_IFTEST (SIOCDEVPRIVATE + 0) @@ -78,46 +73,17 @@ #define P80211_IOCTL_MAGIC (0x4a2d464dUL) -/*----------------------------------------------------------------*/ -/* Netlink protocol numbers for the indication interface */ - -#define P80211_NL_SOCK_IND NETLINK_USERSOCK - -/*----------------------------------------------------------------*/ -/* Netlink multicast bits for different types of messages */ - -#define P80211_NL_MCAST_GRP_MLME BIT0 /* Local station messages */ -#define P80211_NL_MCAST_GRP_SNIFF BIT1 /* Sniffer messages */ -#define P80211_NL_MCAST_GRP_DIST BIT2 /* Distribution system messages */ - -/*================================================================*/ -/* Macros */ - - -/*================================================================*/ -/* Types */ - /*----------------------------------------------------------------*/ /* A ptr to the following structure type is passed as the third */ /* argument to the ioctl system call when issuing a request to */ /* the p80211 module. */ -typedef struct p80211ioctl_req -{ - char name[WLAN_DEVNAMELEN_MAX]; +typedef struct p80211ioctl_req { + char name[WLAN_DEVNAMELEN_MAX]; caddr_t data; - u32 magic; - u16 len; - u32 result; -} __WLAN_ATTRIB_PACK__ p80211ioctl_req_t; - - -/*================================================================*/ -/* Extern Declarations */ - - -/*================================================================*/ -/* Function Declarations */ - + u32 magic; + u16 len; + u32 result; +} __attribute__ ((packed)) p80211ioctl_req_t; #endif /* _P80211IOCTL_H */ diff --git a/drivers/staging/wlan-ng/p80211meta.h b/drivers/staging/wlan-ng/p80211meta.h index 8b61e5fc292b..2f3c9fc3358c 100644 --- a/drivers/staging/wlan-ng/p80211meta.h +++ b/drivers/staging/wlan-ng/p80211meta.h @@ -57,51 +57,9 @@ #ifndef _P80211META_H #define _P80211META_H -/*================================================================*/ -/* System Includes */ - /*================================================================*/ /* Project Includes */ -#ifndef _WLAN_COMPAT_H -#include "wlan_compat.h" -#endif - -/*================================================================*/ -/* Constants */ - -/*----------------------------------------------------------------*/ -/* */ - -/*================================================================*/ -/* Macros */ - -/*----------------------------------------------------------------*/ -/* The following macros are used to ensure consistent naming */ -/* conventions for all the different metadata lists. */ - -#define MKREQMETANAME(name) p80211meta_ ## req ## _ ## name -#define MKINDMETANAME(name) p80211meta_ ## ind ## _ ## name -#define MKMIBMETANAME(name) p80211meta_ ## mib ## _ ## name -#define MKGRPMETANAME(name) p80211meta_ ## grp ## _ ## name - -#define MKREQMETASIZE(name) p80211meta_ ## req ## _ ## name ## _ ## size -#define MKINDMETASIZE(name) p80211meta_ ## ind ## _ ## name ## _ ## size -#define MKMIBMETASIZE(name) p80211meta_ ## mib ## _ ## name ## _ ## size -#define MKGRPMETASIZE(name) p80211meta_ ## grp ## _ ## name ## _ ## size - -#define GETMETASIZE(aptr) (**((u32**)(aptr))) - -/*----------------------------------------------------------------*/ -/* The following ifdef depends on the following defines: */ -/* P80211_NOINCLUDESTRINGS - if defined, all metadata name fields */ -/* are empty strings */ - -#ifdef P80211_NOINCLUDESTRINGS - #define MKITEMNAME(s) ("") -#else - #define MKITEMNAME(s) (s) -#endif /*================================================================*/ /* Types */ @@ -111,59 +69,29 @@ /* representation of category list metadata, group list metadata, */ /* and data item metadata for both Mib and Messages. */ -typedef struct p80211meta -{ - char *name; /* data item name */ - u32 did; /* partial did */ - u32 flags; /* set of various flag bits */ - u32 min; /* min value of a BOUNDEDint */ - u32 max; /* max value of a BOUNDEDint */ +typedef struct p80211meta { + char *name; /* data item name */ + u32 did; /* partial did */ + u32 flags; /* set of various flag bits */ + u32 min; /* min value of a BOUNDEDint */ + u32 max; /* max value of a BOUNDEDint */ - u32 maxlen; /* maxlen of a OCTETSTR or DISPLAYSTR */ - u32 minlen; /* minlen of a OCTETSTR or DISPLAYSTR */ - p80211enum_t *enumptr; /* ptr to the enum type for ENUMint */ - p80211_totext_t totextptr; /* ptr to totext conversion function */ - p80211_fromtext_t fromtextptr; /* ptr to totext conversion function */ - p80211_valid_t validfunptr; /* ptr to totext conversion function */ + u32 maxlen; /* maxlen of a OCTETSTR or DISPLAYSTR */ + u32 minlen; /* minlen of a OCTETSTR or DISPLAYSTR */ + p80211enum_t *enumptr; /* ptr to the enum type for ENUMint */ + p80211_totext_t totextptr; /* ptr to totext conversion function */ + p80211_fromtext_t fromtextptr; /* ptr to totext conversion function */ + p80211_valid_t validfunptr; /* ptr to totext conversion function */ } p80211meta_t; -typedef struct grplistitem -{ - char *name; - p80211meta_t *itemlist; +typedef struct grplistitem { + char *name; + p80211meta_t *itemlist; } grplistitem_t; -typedef struct catlistitem -{ - char *name; - grplistitem_t *grplist; +typedef struct catlistitem { + char *name; + grplistitem_t *grplist; } catlistitem_t; -/*================================================================*/ -/* Extern Declarations */ - -/*----------------------------------------------------------------*/ -/* */ - -/*================================================================*/ -/* Function Declarations */ - -/*----------------------------------------------------------------*/ -/* */ -u32 p80211_text2did(catlistitem_t *catlist, char *catname, char *grpname, char *itemname); -u32 p80211_text2catdid(catlistitem_t *list, char *name ); -u32 p80211_text2grpdid(grplistitem_t *list, char *name ); -u32 p80211_text2itemdid(p80211meta_t *list, char *name ); -u32 p80211_isvalid_did( catlistitem_t *catlist, u32 did ); -u32 p80211_isvalid_catdid( catlistitem_t *catlist, u32 did ); -u32 p80211_isvalid_grpdid( catlistitem_t *catlist, u32 did ); -u32 p80211_isvalid_itemdid( catlistitem_t *catlist, u32 did ); -catlistitem_t *p80211_did2cat( catlistitem_t *catlist, u32 did ); -grplistitem_t *p80211_did2grp( catlistitem_t *catlist, u32 did ); -p80211meta_t *p80211_did2item( catlistitem_t *catlist, u32 did ); -u32 p80211item_maxdatalen( struct catlistitem *metalist, u32 did ); -u32 p80211_metaname2did(struct catlistitem *metalist, char *itemname); -u32 p80211item_getoffset( struct catlistitem *metalist, u32 did ); -int p80211item_gettype(p80211meta_t *meta); - #endif /* _P80211META_H */ diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h index ce4fdd547fc2..a29d6ae3e770 100644 --- a/drivers/staging/wlan-ng/p80211metadef.h +++ b/drivers/staging/wlan-ng/p80211metadef.h @@ -47,20 +47,9 @@ #ifndef _P80211MKMETADEF_H #define _P80211MKMETADEF_H - -#define DIDmsg_cat_dot11req \ - P80211DID_MKSECTION(1) #define DIDmsg_dot11req_mibget \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(1)) -#define DIDmsg_dot11req_mibget_mibattribute \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(1) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_dot11req_mibget_resultcode \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(1) | \ - P80211DID_MKITEM(2) | 0x00000000) #define DIDmsg_dot11req_mibset \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(2)) @@ -75,579 +64,48 @@ #define DIDmsg_dot11req_scan \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(4)) -#define DIDmsg_dot11req_scan_bsstype \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_dot11req_scan_bssid \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_dot11req_scan_ssid \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(3) | 0x00000000) -#define DIDmsg_dot11req_scan_scantype \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(4) | 0x00000000) -#define DIDmsg_dot11req_scan_probedelay \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(5) | 0x00000000) -#define DIDmsg_dot11req_scan_channellist \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(6) | 0x00000000) -#define DIDmsg_dot11req_scan_minchanneltime \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(7) | 0x00000000) -#define DIDmsg_dot11req_scan_maxchanneltime \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(8) | 0x00000000) -#define DIDmsg_dot11req_scan_resultcode \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(9) | 0x00000000) -#define DIDmsg_dot11req_scan_numbss \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(10) | 0x00000000) -#define DIDmsg_dot11req_scan_append \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(11) | 0x00000000) #define DIDmsg_dot11req_scan_results \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(5)) -#define DIDmsg_dot11req_scan_results_bssindex \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_dot11req_scan_results_resultcode \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_dot11req_scan_results_signal \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(3) | 0x00000000) -#define DIDmsg_dot11req_scan_results_noise \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(4) | 0x00000000) -#define DIDmsg_dot11req_scan_results_bssid \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(5) | 0x00000000) -#define DIDmsg_dot11req_scan_results_ssid \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(6) | 0x00000000) -#define DIDmsg_dot11req_scan_results_bsstype \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(7) | 0x00000000) -#define DIDmsg_dot11req_scan_results_beaconperiod \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(8) | 0x00000000) -#define DIDmsg_dot11req_scan_results_dtimperiod \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(9) | 0x00000000) -#define DIDmsg_dot11req_scan_results_timestamp \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(10) | 0x00000000) -#define DIDmsg_dot11req_scan_results_localtime \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(11) | 0x00000000) -#define DIDmsg_dot11req_scan_results_fhdwelltime \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(12) | 0x00000000) -#define DIDmsg_dot11req_scan_results_fhhopset \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(13) | 0x00000000) -#define DIDmsg_dot11req_scan_results_fhhoppattern \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(14) | 0x00000000) -#define DIDmsg_dot11req_scan_results_fhhopindex \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(15) | 0x00000000) -#define DIDmsg_dot11req_scan_results_dschannel \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(16) | 0x00000000) -#define DIDmsg_dot11req_scan_results_cfpcount \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(17) | 0x00000000) -#define DIDmsg_dot11req_scan_results_cfpperiod \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(18) | 0x00000000) -#define DIDmsg_dot11req_scan_results_cfpmaxduration \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(19) | 0x00000000) -#define DIDmsg_dot11req_scan_results_cfpdurremaining \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(20) | 0x00000000) -#define DIDmsg_dot11req_scan_results_ibssatimwindow \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(21) | 0x00000000) -#define DIDmsg_dot11req_scan_results_cfpollable \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(22) | 0x00000000) -#define DIDmsg_dot11req_scan_results_cfpollreq \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(23) | 0x00000000) -#define DIDmsg_dot11req_scan_results_privacy \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(24) | 0x00000000) -#define DIDmsg_dot11req_scan_results_basicrate1 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(25) | 0x00000000) -#define DIDmsg_dot11req_scan_results_basicrate2 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(26) | 0x00000000) -#define DIDmsg_dot11req_scan_results_basicrate3 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(27) | 0x00000000) -#define DIDmsg_dot11req_scan_results_basicrate4 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(28) | 0x00000000) -#define DIDmsg_dot11req_scan_results_basicrate5 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(29) | 0x00000000) -#define DIDmsg_dot11req_scan_results_basicrate6 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(30) | 0x00000000) -#define DIDmsg_dot11req_scan_results_basicrate7 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(31) | 0x00000000) -#define DIDmsg_dot11req_scan_results_basicrate8 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(32) | 0x00000000) -#define DIDmsg_dot11req_scan_results_supprate1 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(33) | 0x00000000) -#define DIDmsg_dot11req_scan_results_supprate2 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(34) | 0x00000000) -#define DIDmsg_dot11req_scan_results_supprate3 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(35) | 0x00000000) -#define DIDmsg_dot11req_scan_results_supprate4 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(36) | 0x00000000) -#define DIDmsg_dot11req_scan_results_supprate5 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(37) | 0x00000000) -#define DIDmsg_dot11req_scan_results_supprate6 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(38) | 0x00000000) -#define DIDmsg_dot11req_scan_results_supprate7 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(39) | 0x00000000) -#define DIDmsg_dot11req_scan_results_supprate8 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(40) | 0x00000000) #define DIDmsg_dot11req_start \ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(13)) -#define DIDmsg_dot11req_start_ssid \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_dot11req_start_bsstype \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_dot11req_start_beaconperiod \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(3) | 0x00000000) -#define DIDmsg_dot11req_start_dtimperiod \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(4) | 0x00000000) -#define DIDmsg_dot11req_start_cfpperiod \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(5) | 0x00000000) -#define DIDmsg_dot11req_start_cfpmaxduration \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(6) | 0x00000000) -#define DIDmsg_dot11req_start_fhdwelltime \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(7) | 0x00000000) -#define DIDmsg_dot11req_start_fhhopset \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(8) | 0x00000000) -#define DIDmsg_dot11req_start_fhhoppattern \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(9) | 0x00000000) -#define DIDmsg_dot11req_start_dschannel \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(10) | 0x00000000) -#define DIDmsg_dot11req_start_ibssatimwindow \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(11) | 0x00000000) -#define DIDmsg_dot11req_start_probedelay \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(12) | 0x00000000) -#define DIDmsg_dot11req_start_cfpollable \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(13) | 0x00000000) -#define DIDmsg_dot11req_start_cfpollreq \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(14) | 0x00000000) -#define DIDmsg_dot11req_start_basicrate1 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(15) | 0x00000000) -#define DIDmsg_dot11req_start_basicrate2 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(16) | 0x00000000) -#define DIDmsg_dot11req_start_basicrate3 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(17) | 0x00000000) -#define DIDmsg_dot11req_start_basicrate4 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(18) | 0x00000000) -#define DIDmsg_dot11req_start_basicrate5 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(19) | 0x00000000) -#define DIDmsg_dot11req_start_basicrate6 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(20) | 0x00000000) -#define DIDmsg_dot11req_start_basicrate7 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(21) | 0x00000000) -#define DIDmsg_dot11req_start_basicrate8 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(22) | 0x00000000) -#define DIDmsg_dot11req_start_operationalrate1 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(23) | 0x00000000) -#define DIDmsg_dot11req_start_operationalrate2 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(24) | 0x00000000) -#define DIDmsg_dot11req_start_operationalrate3 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(25) | 0x00000000) -#define DIDmsg_dot11req_start_operationalrate4 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(26) | 0x00000000) -#define DIDmsg_dot11req_start_operationalrate5 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(27) | 0x00000000) -#define DIDmsg_dot11req_start_operationalrate6 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(28) | 0x00000000) -#define DIDmsg_dot11req_start_operationalrate7 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(29) | 0x00000000) -#define DIDmsg_dot11req_start_operationalrate8 \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(30) | 0x00000000) -#define DIDmsg_dot11req_start_resultcode \ - (P80211DID_MKSECTION(1) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(31) | 0x00000000) -#define DIDmsg_cat_dot11ind \ - P80211DID_MKSECTION(2) #define DIDmsg_dot11ind_authenticate \ (P80211DID_MKSECTION(2) | \ P80211DID_MKGROUP(1)) -#define DIDmsg_dot11ind_authenticate_peerstaaddress \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(1) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_dot11ind_authenticate_authenticationtype \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(1) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_dot11ind_deauthenticate \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(2)) -#define DIDmsg_dot11ind_deauthenticate_peerstaaddress \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_dot11ind_deauthenticate_reasoncode \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(2) | 0x00000000) #define DIDmsg_dot11ind_associate \ (P80211DID_MKSECTION(2) | \ P80211DID_MKGROUP(3)) -#define DIDmsg_dot11ind_associate_peerstaaddress \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(3) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_dot11ind_associate_aid \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(3) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_dot11ind_reassociate \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(4)) -#define DIDmsg_dot11ind_reassociate_peerstaaddress \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_dot11ind_reassociate_aid \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_dot11ind_reassociate_oldapaddress \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(3) | 0x00000000) -#define DIDmsg_dot11ind_disassociate \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(5)) -#define DIDmsg_dot11ind_disassociate_peerstaaddress \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_dot11ind_disassociate_reasoncode \ - (P80211DID_MKSECTION(2) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_cat_lnxreq \ - P80211DID_MKSECTION(3) #define DIDmsg_lnxreq_ifstate \ (P80211DID_MKSECTION(3) | \ P80211DID_MKGROUP(1)) -#define DIDmsg_lnxreq_ifstate_ifstate \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(1) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_lnxreq_ifstate_resultcode \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(1) | \ - P80211DID_MKITEM(2) | 0x00000000) #define DIDmsg_lnxreq_wlansniff \ (P80211DID_MKSECTION(3) | \ P80211DID_MKGROUP(2)) -#define DIDmsg_lnxreq_wlansniff_enable \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_lnxreq_wlansniff_channel \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_lnxreq_wlansniff_prismheader \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(3) | 0x00000000) -#define DIDmsg_lnxreq_wlansniff_wlanheader \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(4) | 0x00000000) -#define DIDmsg_lnxreq_wlansniff_keepwepflags \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(5) | 0x00000000) -#define DIDmsg_lnxreq_wlansniff_stripfcs \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(6) | 0x00000000) -#define DIDmsg_lnxreq_wlansniff_packet_trunc \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(7) | 0x00000000) -#define DIDmsg_lnxreq_wlansniff_resultcode \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(8) | 0x00000000) #define DIDmsg_lnxreq_hostwep \ (P80211DID_MKSECTION(3) | \ P80211DID_MKGROUP(3)) -#define DIDmsg_lnxreq_hostwep_resultcode \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(3) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_lnxreq_hostwep_decrypt \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(3) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_lnxreq_hostwep_encrypt \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(3) | \ - P80211DID_MKITEM(3) | 0x00000000) #define DIDmsg_lnxreq_commsquality \ (P80211DID_MKSECTION(3) | \ P80211DID_MKGROUP(4)) -#define DIDmsg_lnxreq_commsquality_resultcode \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_lnxreq_commsquality_dbm \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_lnxreq_commsquality_link \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(3) | 0x00000000) -#define DIDmsg_lnxreq_commsquality_level \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(4) | 0x00000000) -#define DIDmsg_lnxreq_commsquality_noise \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(4) | \ - P80211DID_MKITEM(5) | 0x00000000) #define DIDmsg_lnxreq_autojoin \ (P80211DID_MKSECTION(3) | \ P80211DID_MKGROUP(5)) -#define DIDmsg_lnxreq_autojoin_ssid \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_lnxreq_autojoin_authtype \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_lnxreq_autojoin_resultcode \ - (P80211DID_MKSECTION(3) | \ - P80211DID_MKGROUP(5) | \ - P80211DID_MKITEM(3) | 0x00000000) -#define DIDmsg_cat_p2req \ - P80211DID_MKSECTION(5) #define DIDmsg_p2req_readpda \ (P80211DID_MKSECTION(5) | \ P80211DID_MKGROUP(2)) -#define DIDmsg_p2req_readpda_pda \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_p2req_readpda_resultcode \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(2) | \ - P80211DID_MKITEM(2) | 0x00000000) #define DIDmsg_p2req_ramdl_state \ (P80211DID_MKSECTION(5) | \ P80211DID_MKGROUP(11)) -#define DIDmsg_p2req_ramdl_state_enable \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(11) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_p2req_ramdl_state_exeaddr \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(11) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_p2req_ramdl_state_resultcode \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(11) | \ - P80211DID_MKITEM(3) | 0x00000000) #define DIDmsg_p2req_ramdl_write \ (P80211DID_MKSECTION(5) | \ P80211DID_MKGROUP(12)) -#define DIDmsg_p2req_ramdl_write_addr \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(12) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_p2req_ramdl_write_len \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(12) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_p2req_ramdl_write_data \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(12) | \ - P80211DID_MKITEM(3) | 0x00000000) -#define DIDmsg_p2req_ramdl_write_resultcode \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(12) | \ - P80211DID_MKITEM(4) | 0x00000000) #define DIDmsg_p2req_flashdl_state \ (P80211DID_MKSECTION(5) | \ P80211DID_MKGROUP(13)) -#define DIDmsg_p2req_flashdl_state_enable \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_p2req_flashdl_state_resultcode \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(13) | \ - P80211DID_MKITEM(2) | 0x00000000) #define DIDmsg_p2req_flashdl_write \ (P80211DID_MKSECTION(5) | \ P80211DID_MKGROUP(14)) -#define DIDmsg_p2req_flashdl_write_addr \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(14) | \ - P80211DID_MKITEM(1) | 0x00000000) -#define DIDmsg_p2req_flashdl_write_len \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(14) | \ - P80211DID_MKITEM(2) | 0x00000000) -#define DIDmsg_p2req_flashdl_write_data \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(14) | \ - P80211DID_MKITEM(3) | 0x00000000) -#define DIDmsg_p2req_flashdl_write_resultcode \ - (P80211DID_MKSECTION(5) | \ - P80211DID_MKGROUP(14) | \ - P80211DID_MKITEM(4) | 0x00000000) #define DIDmib_cat_dot11smt \ P80211DID_MKSECTION(1) #define DIDmib_dot11smt_dot11WEPDefaultKeysTable \ @@ -684,8 +142,6 @@ (P80211DID_MKSECTION(1) | \ P80211DID_MKGROUP(6) | \ P80211DID_MKITEM(4) | 0x18000000) -#define DIDmib_cat_dot11mac \ - P80211DID_MKSECTION(2) #define DIDmib_dot11mac_dot11OperationTable \ (P80211DID_MKSECTION(2) | \ P80211DID_MKGROUP(1)) diff --git a/drivers/staging/wlan-ng/p80211metamib.h b/drivers/staging/wlan-ng/p80211metamib.h deleted file mode 100644 index 9cd72ede441c..000000000000 --- a/drivers/staging/wlan-ng/p80211metamib.h +++ /dev/null @@ -1,105 +0,0 @@ -/* p80211metamib.h -* -* Macros, const, types, and funcs for p80211 mib metadata -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file declares some of the constants and types used in various -* parts of the linux-wlan system. -* -* Notes: -* - Constant values are always in HOST byte order. -* -* All functions and statics declared here are implemented in p80211types.c -* -------------------------------------------------------------------- -*/ - -#ifndef _P80211METAMIB_H -#define _P80211METAMIB_H - -/*================================================================*/ -/* System Includes */ - -/*================================================================*/ -/* Project Includes */ - -#ifndef _WLAN_COMPAT_H -#include "wlan_compat.h" -#endif - -/*================================================================*/ -/* Constants */ - -/*----------------------------------------------------------------*/ -/* */ - -/*================================================================*/ -/* Macros */ - -/*----------------------------------------------------------------*/ -/* */ - -/*================================================================*/ -/* Types */ - -/*----------------------------------------------------------------*/ -/* */ - -/*================================================================*/ -/* Extern Declarations */ - -/*----------------------------------------------------------------*/ -/* The following is the external declaration for the mib */ -/* category metadata list */ - -extern catlistitem_t mib_catlist[]; -extern u32 mib_catlist_size; - - -/*================================================================*/ -/* Function Declarations */ - -/*----------------------------------------------------------------*/ -/* */ - -#endif /* _P80211METAMIB_H */ diff --git a/drivers/staging/wlan-ng/p80211metamsg.h b/drivers/staging/wlan-ng/p80211metamsg.h deleted file mode 100644 index 6e659eae8afc..000000000000 --- a/drivers/staging/wlan-ng/p80211metamsg.h +++ /dev/null @@ -1,105 +0,0 @@ -/* p80211metamsg.h -* -* Macros, const, types, and funcs for p80211 msg metadata -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -* -* This file declares some of the constants and types used in various -* parts of the linux-wlan system. -* -* Notes: -* - Constant values are always in HOST byte order. -* -* All functions and statics declared here are implemented in p80211types.c -* -------------------------------------------------------------------- -*/ - -#ifndef _P80211METAMSG_H -#define _P80211METAMSG_H - -/*================================================================*/ -/* System Includes */ - -/*================================================================*/ -/* Project Includes */ - -#ifndef _WLAN_COMPAT_H -#include "wlan_compat.h" -#endif - -/*================================================================*/ -/* Constants */ - -/*----------------------------------------------------------------*/ -/* */ - -/*================================================================*/ -/* Macros */ - -/*----------------------------------------------------------------*/ -/* */ - -/*================================================================*/ -/* Types */ - -/*----------------------------------------------------------------*/ -/* */ - -/*================================================================*/ -/* Extern Declarations */ - -/*----------------------------------------------------------------*/ -/* The following is the external declaration for the message */ -/* category metadata list */ - -extern catlistitem_t msg_catlist[]; -extern u32 msg_catlist_size; - - -/*================================================================*/ -/* Function Declarations */ - -/*----------------------------------------------------------------*/ -/* */ - -#endif /* _P80211METAMSG_H */ diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h index d2258b0e89c2..db12713eeaa9 100644 --- a/drivers/staging/wlan-ng/p80211metastruct.h +++ b/drivers/staging/wlan-ng/p80211metastruct.h @@ -47,239 +47,223 @@ #ifndef _P80211MKMETASTRUCT_H #define _P80211MKMETASTRUCT_H +typedef struct p80211msg_dot11req_mibget { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_unk392_t mibattribute; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_dot11req_mibget_t; -typedef struct p80211msg_dot11req_mibget -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_unk392_t mibattribute ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibget_t; +typedef struct p80211msg_dot11req_mibset { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_unk392_t mibattribute; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_dot11req_mibset_t; -typedef struct p80211msg_dot11req_mibset -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_unk392_t mibattribute ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_mibset_t; +typedef struct p80211msg_dot11req_scan { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t bsstype; + p80211item_pstr6_t bssid; + u8 pad_0C[1]; + p80211item_pstr32_t ssid; + u8 pad_1D[3]; + p80211item_uint32_t scantype; + p80211item_uint32_t probedelay; + p80211item_pstr14_t channellist; + u8 pad_2C[1]; + p80211item_uint32_t minchanneltime; + p80211item_uint32_t maxchanneltime; + p80211item_uint32_t resultcode; + p80211item_uint32_t numbss; + p80211item_uint32_t append; +} __attribute__ ((packed)) p80211msg_dot11req_scan_t; -typedef struct p80211msg_dot11req_scan -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t bsstype ; - p80211item_pstr6_t bssid ; - u8 pad_0C[1] ; - p80211item_pstr32_t ssid ; - u8 pad_1D[3] ; - p80211item_uint32_t scantype ; - p80211item_uint32_t probedelay ; - p80211item_pstr14_t channellist ; - u8 pad_2C[1] ; - p80211item_uint32_t minchanneltime ; - p80211item_uint32_t maxchanneltime ; - p80211item_uint32_t resultcode ; - p80211item_uint32_t numbss ; - p80211item_uint32_t append ; -} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_scan_t; +typedef struct p80211msg_dot11req_scan_results { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t bssindex; + p80211item_uint32_t resultcode; + p80211item_uint32_t signal; + p80211item_uint32_t noise; + p80211item_pstr6_t bssid; + u8 pad_3C[1]; + p80211item_pstr32_t ssid; + u8 pad_4D[3]; + p80211item_uint32_t bsstype; + p80211item_uint32_t beaconperiod; + p80211item_uint32_t dtimperiod; + p80211item_uint32_t timestamp; + p80211item_uint32_t localtime; + p80211item_uint32_t fhdwelltime; + p80211item_uint32_t fhhopset; + p80211item_uint32_t fhhoppattern; + p80211item_uint32_t fhhopindex; + p80211item_uint32_t dschannel; + p80211item_uint32_t cfpcount; + p80211item_uint32_t cfpperiod; + p80211item_uint32_t cfpmaxduration; + p80211item_uint32_t cfpdurremaining; + p80211item_uint32_t ibssatimwindow; + p80211item_uint32_t cfpollable; + p80211item_uint32_t cfpollreq; + p80211item_uint32_t privacy; + p80211item_uint32_t basicrate1; + p80211item_uint32_t basicrate2; + p80211item_uint32_t basicrate3; + p80211item_uint32_t basicrate4; + p80211item_uint32_t basicrate5; + p80211item_uint32_t basicrate6; + p80211item_uint32_t basicrate7; + p80211item_uint32_t basicrate8; + p80211item_uint32_t supprate1; + p80211item_uint32_t supprate2; + p80211item_uint32_t supprate3; + p80211item_uint32_t supprate4; + p80211item_uint32_t supprate5; + p80211item_uint32_t supprate6; + p80211item_uint32_t supprate7; + p80211item_uint32_t supprate8; +} __attribute__ ((packed)) p80211msg_dot11req_scan_results_t; -typedef struct p80211msg_dot11req_scan_results -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t bssindex ; - p80211item_uint32_t resultcode ; - p80211item_uint32_t signal ; - p80211item_uint32_t noise ; - p80211item_pstr6_t bssid ; - u8 pad_3C[1] ; - p80211item_pstr32_t ssid ; - u8 pad_4D[3] ; - p80211item_uint32_t bsstype ; - p80211item_uint32_t beaconperiod ; - p80211item_uint32_t dtimperiod ; - p80211item_uint32_t timestamp ; - p80211item_uint32_t localtime ; - p80211item_uint32_t fhdwelltime ; - p80211item_uint32_t fhhopset ; - p80211item_uint32_t fhhoppattern ; - p80211item_uint32_t fhhopindex ; - p80211item_uint32_t dschannel ; - p80211item_uint32_t cfpcount ; - p80211item_uint32_t cfpperiod ; - p80211item_uint32_t cfpmaxduration ; - p80211item_uint32_t cfpdurremaining ; - p80211item_uint32_t ibssatimwindow ; - p80211item_uint32_t cfpollable ; - p80211item_uint32_t cfpollreq ; - p80211item_uint32_t privacy ; - p80211item_uint32_t basicrate1 ; - p80211item_uint32_t basicrate2 ; - p80211item_uint32_t basicrate3 ; - p80211item_uint32_t basicrate4 ; - p80211item_uint32_t basicrate5 ; - p80211item_uint32_t basicrate6 ; - p80211item_uint32_t basicrate7 ; - p80211item_uint32_t basicrate8 ; - p80211item_uint32_t supprate1 ; - p80211item_uint32_t supprate2 ; - p80211item_uint32_t supprate3 ; - p80211item_uint32_t supprate4 ; - p80211item_uint32_t supprate5 ; - p80211item_uint32_t supprate6 ; - p80211item_uint32_t supprate7 ; - p80211item_uint32_t supprate8 ; -} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_scan_results_t; +typedef struct p80211msg_dot11req_start { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_pstr32_t ssid; + u8 pad_12D[3]; + p80211item_uint32_t bsstype; + p80211item_uint32_t beaconperiod; + p80211item_uint32_t dtimperiod; + p80211item_uint32_t cfpperiod; + p80211item_uint32_t cfpmaxduration; + p80211item_uint32_t fhdwelltime; + p80211item_uint32_t fhhopset; + p80211item_uint32_t fhhoppattern; + p80211item_uint32_t dschannel; + p80211item_uint32_t ibssatimwindow; + p80211item_uint32_t probedelay; + p80211item_uint32_t cfpollable; + p80211item_uint32_t cfpollreq; + p80211item_uint32_t basicrate1; + p80211item_uint32_t basicrate2; + p80211item_uint32_t basicrate3; + p80211item_uint32_t basicrate4; + p80211item_uint32_t basicrate5; + p80211item_uint32_t basicrate6; + p80211item_uint32_t basicrate7; + p80211item_uint32_t basicrate8; + p80211item_uint32_t operationalrate1; + p80211item_uint32_t operationalrate2; + p80211item_uint32_t operationalrate3; + p80211item_uint32_t operationalrate4; + p80211item_uint32_t operationalrate5; + p80211item_uint32_t operationalrate6; + p80211item_uint32_t operationalrate7; + p80211item_uint32_t operationalrate8; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_dot11req_start_t; -typedef struct p80211msg_dot11req_start -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_pstr32_t ssid ; - u8 pad_12D[3] ; - p80211item_uint32_t bsstype ; - p80211item_uint32_t beaconperiod ; - p80211item_uint32_t dtimperiod ; - p80211item_uint32_t cfpperiod ; - p80211item_uint32_t cfpmaxduration ; - p80211item_uint32_t fhdwelltime ; - p80211item_uint32_t fhhopset ; - p80211item_uint32_t fhhoppattern ; - p80211item_uint32_t dschannel ; - p80211item_uint32_t ibssatimwindow ; - p80211item_uint32_t probedelay ; - p80211item_uint32_t cfpollable ; - p80211item_uint32_t cfpollreq ; - p80211item_uint32_t basicrate1 ; - p80211item_uint32_t basicrate2 ; - p80211item_uint32_t basicrate3 ; - p80211item_uint32_t basicrate4 ; - p80211item_uint32_t basicrate5 ; - p80211item_uint32_t basicrate6 ; - p80211item_uint32_t basicrate7 ; - p80211item_uint32_t basicrate8 ; - p80211item_uint32_t operationalrate1 ; - p80211item_uint32_t operationalrate2 ; - p80211item_uint32_t operationalrate3 ; - p80211item_uint32_t operationalrate4 ; - p80211item_uint32_t operationalrate5 ; - p80211item_uint32_t operationalrate6 ; - p80211item_uint32_t operationalrate7 ; - p80211item_uint32_t operationalrate8 ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_dot11req_start_t; +typedef struct p80211msg_lnxreq_ifstate { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t ifstate; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_lnxreq_ifstate_t; -typedef struct p80211msg_lnxreq_ifstate -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t ifstate ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_ifstate_t; +typedef struct p80211msg_lnxreq_wlansniff { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t enable; + p80211item_uint32_t channel; + p80211item_uint32_t prismheader; + p80211item_uint32_t wlanheader; + p80211item_uint32_t keepwepflags; + p80211item_uint32_t stripfcs; + p80211item_uint32_t packet_trunc; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_lnxreq_wlansniff_t; -typedef struct p80211msg_lnxreq_wlansniff -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t enable ; - p80211item_uint32_t channel ; - p80211item_uint32_t prismheader ; - p80211item_uint32_t wlanheader ; - p80211item_uint32_t keepwepflags ; - p80211item_uint32_t stripfcs ; - p80211item_uint32_t packet_trunc ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_wlansniff_t; +typedef struct p80211msg_lnxreq_hostwep { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t resultcode; + p80211item_uint32_t decrypt; + p80211item_uint32_t encrypt; +} __attribute__ ((packed)) p80211msg_lnxreq_hostwep_t; -typedef struct p80211msg_lnxreq_hostwep -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t resultcode ; - p80211item_uint32_t decrypt ; - p80211item_uint32_t encrypt ; -} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_hostwep_t; +typedef struct p80211msg_lnxreq_commsquality { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t resultcode; + p80211item_uint32_t dbm; + p80211item_uint32_t link; + p80211item_uint32_t level; + p80211item_uint32_t noise; +} __attribute__ ((packed)) p80211msg_lnxreq_commsquality_t; -typedef struct p80211msg_lnxreq_commsquality -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t resultcode ; - p80211item_uint32_t dbm ; - p80211item_uint32_t link ; - p80211item_uint32_t level ; - p80211item_uint32_t noise ; -} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_commsquality_t; +typedef struct p80211msg_lnxreq_autojoin { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_pstr32_t ssid; + u8 pad_19D[3]; + p80211item_uint32_t authtype; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_lnxreq_autojoin_t; -typedef struct p80211msg_lnxreq_autojoin -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_pstr32_t ssid ; - u8 pad_19D[3] ; - p80211item_uint32_t authtype ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_lnxreq_autojoin_t; +typedef struct p80211msg_p2req_readpda { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_unk1024_t pda; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_p2req_readpda_t; -typedef struct p80211msg_p2req_readpda -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_unk1024_t pda ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_p2req_readpda_t; +typedef struct p80211msg_p2req_ramdl_state { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t enable; + p80211item_uint32_t exeaddr; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_p2req_ramdl_state_t; -typedef struct p80211msg_p2req_ramdl_state -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t enable ; - p80211item_uint32_t exeaddr ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_p2req_ramdl_state_t; +typedef struct p80211msg_p2req_ramdl_write { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t addr; + p80211item_uint32_t len; + p80211item_unk4096_t data; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_p2req_ramdl_write_t; -typedef struct p80211msg_p2req_ramdl_write -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t addr ; - p80211item_uint32_t len ; - p80211item_unk4096_t data ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_p2req_ramdl_write_t; +typedef struct p80211msg_p2req_flashdl_state { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t enable; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_p2req_flashdl_state_t; -typedef struct p80211msg_p2req_flashdl_state -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t enable ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_p2req_flashdl_state_t; - -typedef struct p80211msg_p2req_flashdl_write -{ - u32 msgcode ; - u32 msglen ; - u8 devname[WLAN_DEVNAMELEN_MAX] ; - p80211item_uint32_t addr ; - p80211item_uint32_t len ; - p80211item_unk4096_t data ; - p80211item_uint32_t resultcode ; -} __WLAN_ATTRIB_PACK__ p80211msg_p2req_flashdl_write_t; +typedef struct p80211msg_p2req_flashdl_write { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t addr; + p80211item_uint32_t len; + p80211item_unk4096_t data; + p80211item_uint32_t resultcode; +} __attribute__ ((packed)) p80211msg_p2req_flashdl_write_t; #endif diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h index 6cc16c3f8b15..6235fe7f235c 100644 --- a/drivers/staging/wlan-ng/p80211mgmt.h +++ b/drivers/staging/wlan-ng/p80211mgmt.h @@ -100,15 +100,9 @@ #ifndef _P80211MGMT_H #define _P80211MGMT_H -/*================================================================*/ -/* System Includes */ - /*================================================================*/ /* Project Includes */ -#ifndef _WLAN_COMPAT_H -#include "wlan_compat.h" -#endif #ifndef _P80211HDR_H #include "p80211hdr.h" @@ -160,8 +154,6 @@ #define WLAN_MGMT_STATUS_ASSOC_DENIED_NOPBCC 20 #define WLAN_MGMT_STATUS_ASSOC_DENIED_NOAGILITY 21 - - /*-- Auth Algorithm Field ---------------------------*/ #define WLAN_AUTH_ALG_OPENSYSTEM 0 #define WLAN_AUTH_ALG_SHAREDKEY 1 @@ -211,20 +203,16 @@ #define WLAN_DEAUTHEN_OFF_REASON 0 - -/*================================================================*/ -/* Macros */ - /*-- Capability Field ---------------------------*/ -#define WLAN_GET_MGMT_CAP_INFO_ESS(n) ((n) & BIT0) -#define WLAN_GET_MGMT_CAP_INFO_IBSS(n) (((n) & BIT1) >> 1) -#define WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(n) (((n) & BIT2) >> 2) -#define WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(n) (((n) & BIT3) >> 3) -#define WLAN_GET_MGMT_CAP_INFO_PRIVACY(n) (((n) & BIT4) >> 4) +#define WLAN_GET_MGMT_CAP_INFO_ESS(n) ((n) & BIT(0)) +#define WLAN_GET_MGMT_CAP_INFO_IBSS(n) (((n) & BIT(1)) >> 1) +#define WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(n) (((n) & BIT(2)) >> 2) +#define WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(n) (((n) & BIT(3)) >> 3) +#define WLAN_GET_MGMT_CAP_INFO_PRIVACY(n) (((n) & BIT(4)) >> 4) /* p80211b additions */ -#define WLAN_GET_MGMT_CAP_INFO_SHORT(n) (((n) & BIT5) >> 5) -#define WLAN_GET_MGMT_CAP_INFO_PBCC(n) (((n) & BIT6) >> 6) -#define WLAN_GET_MGMT_CAP_INFO_AGILITY(n) (((n) & BIT7) >> 7) +#define WLAN_GET_MGMT_CAP_INFO_SHORT(n) (((n) & BIT(5)) >> 5) +#define WLAN_GET_MGMT_CAP_INFO_PBCC(n) (((n) & BIT(6)) >> 6) +#define WLAN_GET_MGMT_CAP_INFO_AGILITY(n) (((n) & BIT(7)) >> 7) #define WLAN_SET_MGMT_CAP_INFO_ESS(n) (n) #define WLAN_SET_MGMT_CAP_INFO_IBSS(n) ((n) << 1) @@ -236,143 +224,126 @@ #define WLAN_SET_MGMT_CAP_INFO_PBCC(n) ((n) << 6) #define WLAN_SET_MGMT_CAP_INFO_AGILITY(n) ((n) << 7) - -/*================================================================*/ -/* Types */ - /*-- Information Element Types --------------------*/ /* prototype structure, all IEs start with these members */ -typedef struct wlan_ie -{ - u8 eid; - u8 len; -} __WLAN_ATTRIB_PACK__ wlan_ie_t; +typedef struct wlan_ie { + u8 eid; + u8 len; +} __attribute__ ((packed)) wlan_ie_t; /*-- Service Set Identity (SSID) -----------------*/ -typedef struct wlan_ie_ssid -{ - u8 eid; - u8 len; - u8 ssid[1]; /* may be zero, ptrs may overlap */ -} __WLAN_ATTRIB_PACK__ wlan_ie_ssid_t; +typedef struct wlan_ie_ssid { + u8 eid; + u8 len; + u8 ssid[1]; /* may be zero, ptrs may overlap */ +} __attribute__ ((packed)) wlan_ie_ssid_t; /*-- Supported Rates -----------------------------*/ -typedef struct wlan_ie_supp_rates -{ - u8 eid; - u8 len; - u8 rates[1]; /* had better be at LEAST one! */ -} __WLAN_ATTRIB_PACK__ wlan_ie_supp_rates_t; +typedef struct wlan_ie_supp_rates { + u8 eid; + u8 len; + u8 rates[1]; /* had better be at LEAST one! */ +} __attribute__ ((packed)) wlan_ie_supp_rates_t; /*-- FH Parameter Set ----------------------------*/ -typedef struct wlan_ie_fh_parms -{ - u8 eid; - u8 len; - u16 dwell; - u8 hopset; - u8 hoppattern; - u8 hopindex; -} __WLAN_ATTRIB_PACK__ wlan_ie_fh_parms_t; +typedef struct wlan_ie_fh_parms { + u8 eid; + u8 len; + u16 dwell; + u8 hopset; + u8 hoppattern; + u8 hopindex; +} __attribute__ ((packed)) wlan_ie_fh_parms_t; /*-- DS Parameter Set ----------------------------*/ -typedef struct wlan_ie_ds_parms -{ - u8 eid; - u8 len; - u8 curr_ch; -} __WLAN_ATTRIB_PACK__ wlan_ie_ds_parms_t; +typedef struct wlan_ie_ds_parms { + u8 eid; + u8 len; + u8 curr_ch; +} __attribute__ ((packed)) wlan_ie_ds_parms_t; /*-- CF Parameter Set ----------------------------*/ -typedef struct wlan_ie_cf_parms -{ - u8 eid; - u8 len; - u8 cfp_cnt; - u8 cfp_period; - u16 cfp_maxdur; - u16 cfp_durremaining; -} __WLAN_ATTRIB_PACK__ wlan_ie_cf_parms_t; +typedef struct wlan_ie_cf_parms { + u8 eid; + u8 len; + u8 cfp_cnt; + u8 cfp_period; + u16 cfp_maxdur; + u16 cfp_durremaining; +} __attribute__ ((packed)) wlan_ie_cf_parms_t; /*-- TIM ------------------------------------------*/ -typedef struct wlan_ie_tim -{ - u8 eid; - u8 len; - u8 dtim_cnt; - u8 dtim_period; - u8 bitmap_ctl; - u8 virt_bm[1]; -} __WLAN_ATTRIB_PACK__ wlan_ie_tim_t; +typedef struct wlan_ie_tim { + u8 eid; + u8 len; + u8 dtim_cnt; + u8 dtim_period; + u8 bitmap_ctl; + u8 virt_bm[1]; +} __attribute__ ((packed)) wlan_ie_tim_t; /*-- IBSS Parameter Set ---------------------------*/ -typedef struct wlan_ie_ibss_parms -{ - u8 eid; - u8 len; - u16 atim_win; -} __WLAN_ATTRIB_PACK__ wlan_ie_ibss_parms_t; +typedef struct wlan_ie_ibss_parms { + u8 eid; + u8 len; + u16 atim_win; +} __attribute__ ((packed)) wlan_ie_ibss_parms_t; /*-- Challenge Text ------------------------------*/ -typedef struct wlan_ie_challenge -{ - u8 eid; - u8 len; - u8 challenge[1]; -} __WLAN_ATTRIB_PACK__ wlan_ie_challenge_t; +typedef struct wlan_ie_challenge { + u8 eid; + u8 len; + u8 challenge[1]; +} __attribute__ ((packed)) wlan_ie_challenge_t; /*-------------------------------------------------*/ /* Frame Types */ /* prototype structure, all mgmt frame types will start with these members */ -typedef struct wlan_fr_mgmt -{ - u16 type; - u16 len; /* DOES NOT include CRC !!!!*/ - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_mgmt { + u16 type; + u16 len; /* DOES NOT include CRC !!!! */ + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ /*-- info elements ----------*/ } wlan_fr_mgmt_t; /*-- Beacon ---------------------------------------*/ -typedef struct wlan_fr_beacon -{ - u16 type; - u16 len; - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_beacon { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ - u64 *ts; - u16 *bcn_int; - u16 *cap_info; + u64 *ts; + u16 *bcn_int; + u16 *cap_info; /*-- info elements ----------*/ - wlan_ie_ssid_t *ssid; - wlan_ie_supp_rates_t *supp_rates; - wlan_ie_fh_parms_t *fh_parms; - wlan_ie_ds_parms_t *ds_parms; - wlan_ie_cf_parms_t *cf_parms; - wlan_ie_ibss_parms_t *ibss_parms; - wlan_ie_tim_t *tim; + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_fh_parms_t *fh_parms; + wlan_ie_ds_parms_t *ds_parms; + wlan_ie_cf_parms_t *cf_parms; + wlan_ie_ibss_parms_t *ibss_parms; + wlan_ie_tim_t *tim; } wlan_fr_beacon_t; - /*-- IBSS ATIM ------------------------------------*/ -typedef struct wlan_fr_ibssatim -{ - u16 type; - u16 len; - u8* buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_ibssatim { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ /*-- info elements ----------*/ @@ -382,194 +353,176 @@ typedef struct wlan_fr_ibssatim } wlan_fr_ibssatim_t; /*-- Disassociation -------------------------------*/ -typedef struct wlan_fr_disassoc -{ - u16 type; - u16 len; - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_disassoc { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ - u16 *reason; + u16 *reason; /*-- info elements ----------*/ } wlan_fr_disassoc_t; /*-- Association Request --------------------------*/ -typedef struct wlan_fr_assocreq -{ - u16 type; - u16 len; - u8* buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_assocreq { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ - u16 *cap_info; - u16 *listen_int; + u16 *cap_info; + u16 *listen_int; /*-- info elements ----------*/ - wlan_ie_ssid_t *ssid; - wlan_ie_supp_rates_t *supp_rates; + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; } wlan_fr_assocreq_t; /*-- Association Response -------------------------*/ -typedef struct wlan_fr_assocresp -{ - u16 type; - u16 len; - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_assocresp { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ - u16 *cap_info; - u16 *status; - u16 *aid; + u16 *cap_info; + u16 *status; + u16 *aid; /*-- info elements ----------*/ - wlan_ie_supp_rates_t *supp_rates; + wlan_ie_supp_rates_t *supp_rates; } wlan_fr_assocresp_t; /*-- Reassociation Request ------------------------*/ -typedef struct wlan_fr_reassocreq -{ - u16 type; - u16 len; - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_reassocreq { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ - u16 *cap_info; - u16 *listen_int; - u8 *curr_ap; + u16 *cap_info; + u16 *listen_int; + u8 *curr_ap; /*-- info elements ----------*/ - wlan_ie_ssid_t *ssid; - wlan_ie_supp_rates_t *supp_rates; + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; } wlan_fr_reassocreq_t; /*-- Reassociation Response -----------------------*/ -typedef struct wlan_fr_reassocresp -{ - u16 type; - u16 len; - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_reassocresp { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ - u16 *cap_info; - u16 *status; - u16 *aid; + u16 *cap_info; + u16 *status; + u16 *aid; /*-- info elements ----------*/ - wlan_ie_supp_rates_t *supp_rates; + wlan_ie_supp_rates_t *supp_rates; } wlan_fr_reassocresp_t; /*-- Probe Request --------------------------------*/ -typedef struct wlan_fr_probereq -{ - u16 type; - u16 len; - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_probereq { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ /*-- info elements ----------*/ - wlan_ie_ssid_t *ssid; - wlan_ie_supp_rates_t *supp_rates; + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; } wlan_fr_probereq_t; /*-- Probe Response -------------------------------*/ -typedef struct wlan_fr_proberesp -{ - u16 type; - u16 len; - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_proberesp { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ - u64 *ts; - u16 *bcn_int; - u16 *cap_info; + u64 *ts; + u16 *bcn_int; + u16 *cap_info; /*-- info elements ----------*/ - wlan_ie_ssid_t *ssid; - wlan_ie_supp_rates_t *supp_rates; - wlan_ie_fh_parms_t *fh_parms; - wlan_ie_ds_parms_t *ds_parms; - wlan_ie_cf_parms_t *cf_parms; - wlan_ie_ibss_parms_t *ibss_parms; + wlan_ie_ssid_t *ssid; + wlan_ie_supp_rates_t *supp_rates; + wlan_ie_fh_parms_t *fh_parms; + wlan_ie_ds_parms_t *ds_parms; + wlan_ie_cf_parms_t *cf_parms; + wlan_ie_ibss_parms_t *ibss_parms; } wlan_fr_proberesp_t; /*-- Authentication -------------------------------*/ -typedef struct wlan_fr_authen -{ - u16 type; - u16 len; - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_authen { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ - u16 *auth_alg; - u16 *auth_seq; - u16 *status; + u16 *auth_alg; + u16 *auth_seq; + u16 *status; /*-- info elements ----------*/ - wlan_ie_challenge_t *challenge; + wlan_ie_challenge_t *challenge; } wlan_fr_authen_t; /*-- Deauthenication -----------------------------*/ -typedef struct wlan_fr_deauthen -{ - u16 type; - u16 len; - u8 *buf; - p80211_hdr_t *hdr; +typedef struct wlan_fr_deauthen { + u16 type; + u16 len; + u8 *buf; + p80211_hdr_t *hdr; /* used for target specific data, skb in Linux */ - void *priv; + void *priv; /*-- fixed fields -----------*/ - u16 *reason; + u16 *reason; /*-- info elements ----------*/ } wlan_fr_deauthen_t; - -/*================================================================*/ -/* Extern Declarations */ - - -/*================================================================*/ -/* Function Declarations */ - -void wlan_mgmt_encode_beacon( wlan_fr_beacon_t *f ); -void wlan_mgmt_decode_beacon( wlan_fr_beacon_t *f ); -void wlan_mgmt_encode_disassoc( wlan_fr_disassoc_t *f ); -void wlan_mgmt_decode_disassoc( wlan_fr_disassoc_t *f ); -void wlan_mgmt_encode_assocreq( wlan_fr_assocreq_t *f ); -void wlan_mgmt_decode_assocreq( wlan_fr_assocreq_t *f ); -void wlan_mgmt_encode_assocresp( wlan_fr_assocresp_t *f ); -void wlan_mgmt_decode_assocresp( wlan_fr_assocresp_t *f ); -void wlan_mgmt_encode_reassocreq( wlan_fr_reassocreq_t *f ); -void wlan_mgmt_decode_reassocreq( wlan_fr_reassocreq_t *f ); -void wlan_mgmt_encode_reassocresp( wlan_fr_reassocresp_t *f ); -void wlan_mgmt_decode_reassocresp( wlan_fr_reassocresp_t *f ); -void wlan_mgmt_encode_probereq( wlan_fr_probereq_t *f ); -void wlan_mgmt_decode_probereq( wlan_fr_probereq_t *f ); -void wlan_mgmt_encode_proberesp( wlan_fr_proberesp_t *f ); -void wlan_mgmt_decode_proberesp( wlan_fr_proberesp_t *f ); -void wlan_mgmt_encode_authen( wlan_fr_authen_t *f ); -void wlan_mgmt_decode_authen( wlan_fr_authen_t *f ); -void wlan_mgmt_encode_deauthen( wlan_fr_deauthen_t *f ); -void wlan_mgmt_decode_deauthen( wlan_fr_deauthen_t *f ); - +void wlan_mgmt_encode_beacon(wlan_fr_beacon_t *f); +void wlan_mgmt_decode_beacon(wlan_fr_beacon_t *f); +void wlan_mgmt_encode_disassoc(wlan_fr_disassoc_t *f); +void wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t *f); +void wlan_mgmt_encode_assocreq(wlan_fr_assocreq_t *f); +void wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t *f); +void wlan_mgmt_encode_assocresp(wlan_fr_assocresp_t *f); +void wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t *f); +void wlan_mgmt_encode_reassocreq(wlan_fr_reassocreq_t *f); +void wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t *f); +void wlan_mgmt_encode_reassocresp(wlan_fr_reassocresp_t *f); +void wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t *f); +void wlan_mgmt_encode_probereq(wlan_fr_probereq_t *f); +void wlan_mgmt_decode_probereq(wlan_fr_probereq_t *f); +void wlan_mgmt_encode_proberesp(wlan_fr_proberesp_t *f); +void wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t *f); +void wlan_mgmt_encode_authen(wlan_fr_authen_t *f); +void wlan_mgmt_decode_authen(wlan_fr_authen_t *f); +void wlan_mgmt_encode_deauthen(wlan_fr_deauthen_t *f); +void wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t *f); #endif /* _P80211MGMT_H */ diff --git a/drivers/staging/wlan-ng/p80211msg.h b/drivers/staging/wlan-ng/p80211msg.h index 3a575d8cc99e..f15a5d921f3c 100644 --- a/drivers/staging/wlan-ng/p80211msg.h +++ b/drivers/staging/wlan-ng/p80211msg.h @@ -48,55 +48,19 @@ #ifndef _P80211MSG_H #define _P80211MSG_H -/*================================================================*/ -/* System Includes */ - /*================================================================*/ /* Project Includes */ -#ifndef _WLAN_COMPAT_H -#include "wlan_compat.h" -#endif -/*================================================================*/ -/* Constants */ - -#define MSG_BUFF_LEN 4000 #define WLAN_DEVNAMELEN_MAX 16 -/*================================================================*/ -/* Macros */ - -/*================================================================*/ -/* Types */ - -/*--------------------------------------------------------------------*/ -/*----- Message Structure Types --------------------------------------*/ - /*--------------------------------------------------------------------*/ /* Prototype msg type */ -typedef struct p80211msg -{ - u32 msgcode; - u32 msglen; - u8 devname[WLAN_DEVNAMELEN_MAX]; -} __WLAN_ATTRIB_PACK__ p80211msg_t; - -typedef struct p80211msgd -{ - u32 msgcode; - u32 msglen; - u8 devname[WLAN_DEVNAMELEN_MAX]; - u8 args[0]; -} __WLAN_ATTRIB_PACK__ p80211msgd_t; - -/*================================================================*/ -/* Extern Declarations */ - - -/*================================================================*/ -/* Function Declarations */ - -#endif /* _P80211MSG_H */ +typedef struct p80211msg { + u32 msgcode; + u32 msglen; + u8 devname[WLAN_DEVNAMELEN_MAX]; +} __attribute__ ((packed)) p80211msg_t; +#endif /* _P80211MSG_H */ diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 59e5ad10dbda..b2a606a36936 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -49,13 +49,7 @@ * -------------------------------------------------------------------- */ - -/*================================================================*/ -/* System Includes */ - - #include - #include #include #include @@ -70,9 +64,10 @@ #include #include #include - -#include -#include +#include +#include +#include +#include #include #ifdef SIOCETHTOOL @@ -85,7 +80,6 @@ /*================================================================*/ /* Project Includes */ -#include "wlan_compat.h" #include "p80211types.h" #include "p80211hdr.h" #include "p80211conv.h" @@ -97,33 +91,22 @@ #include "p80211metastruct.h" #include "p80211metadef.h" -/*================================================================*/ -/* Local Constants */ - -/*================================================================*/ -/* Local Macros */ - - -/*================================================================*/ -/* Local Types */ - -/*================================================================*/ -/* Local Function Declarations */ - /* Support functions */ static void p80211netdev_rx_bh(unsigned long arg); /* netdevice method functions */ -static int p80211knetdev_init( netdevice_t *netdev); -static struct net_device_stats* p80211knetdev_get_stats(netdevice_t *netdev); -static int p80211knetdev_open( netdevice_t *netdev); -static int p80211knetdev_stop( netdevice_t *netdev ); -static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev); +static int p80211knetdev_init(netdevice_t *netdev); +static struct net_device_stats *p80211knetdev_get_stats(netdevice_t *netdev); +static int p80211knetdev_open(netdevice_t *netdev); +static int p80211knetdev_stop(netdevice_t *netdev); +static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, + netdevice_t *netdev); static void p80211knetdev_set_multicast_list(netdevice_t *dev); -static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd); +static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, + int cmd); static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr); static void p80211knetdev_tx_timeout(netdevice_t *netdev); -static int p80211_rx_typedrop( wlandevice_t *wlandev, u16 fc); +static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc); int wlan_watchdog = 5000; module_param(wlan_watchdog, int, 0644); @@ -133,15 +116,6 @@ int wlan_wext_write = 1; module_param(wlan_wext_write, int, 0644); MODULE_PARM_DESC(wlan_wext_write, "enable write wireless extensions"); -#ifdef WLAN_INCLUDE_DEBUG -int wlan_debug=0; -module_param(wlan_debug, int, 0644); -MODULE_PARM_DESC(wlan_debug, "p80211 debug level"); -#endif - -/*================================================================*/ -/* Function Definitions */ - /*---------------------------------------------------------------- * p80211knetdev_init * @@ -154,18 +128,15 @@ MODULE_PARM_DESC(wlan_debug, "p80211 debug level"); * Returns: * nothing ----------------------------------------------------------------*/ -static int p80211knetdev_init( netdevice_t *netdev) +static int p80211knetdev_init(netdevice_t *netdev) { - DBFENTER; /* Called in response to register_netdev */ /* This is usually the probe function, but the probe has */ /* already been done by the MSD and the create_kdev */ /* function. All we do here is return success */ - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * p80211knetdev_get_stats * @@ -180,20 +151,16 @@ static int p80211knetdev_init( netdevice_t *netdev) * Returns: * the address of the statistics structure ----------------------------------------------------------------*/ -static struct net_device_stats* -p80211knetdev_get_stats(netdevice_t *netdev) +static struct net_device_stats *p80211knetdev_get_stats(netdevice_t *netdev) { - wlandevice_t *wlandev = netdev->ml_priv; - DBFENTER; + wlandevice_t *wlandev = netdev->ml_priv; /* TODO: review the MIB stats for items that correspond to - linux stats */ + linux stats */ - DBFEXIT; return &(wlandev->linux_stats); } - /*---------------------------------------------------------------- * p80211knetdev_open * @@ -208,22 +175,19 @@ p80211knetdev_get_stats(netdevice_t *netdev) * Returns: * zero on success, non-zero otherwise ----------------------------------------------------------------*/ -static int p80211knetdev_open( netdevice_t *netdev ) +static int p80211knetdev_open(netdevice_t *netdev) { - int result = 0; /* success */ - wlandevice_t *wlandev = netdev->ml_priv; - - DBFENTER; + int result = 0; /* success */ + wlandevice_t *wlandev = netdev->ml_priv; /* Check to make sure the MSD is running */ - if ( wlandev->msdstate != WLAN_MSD_RUNNING ) { + if (wlandev->msdstate != WLAN_MSD_RUNNING) return -ENODEV; - } /* Tell the MSD to open */ - if ( wlandev->open != NULL) { + if (wlandev->open != NULL) { result = wlandev->open(wlandev); - if ( result == 0 ) { + if (result == 0) { netif_start_queue(wlandev->netdev); wlandev->state = WLAN_DEVICE_OPEN; } @@ -231,11 +195,9 @@ static int p80211knetdev_open( netdevice_t *netdev ) result = -EAGAIN; } - DBFEXIT; return result; } - /*---------------------------------------------------------------- * p80211knetdev_stop * @@ -248,21 +210,17 @@ static int p80211knetdev_open( netdevice_t *netdev ) * Returns: * zero on success, non-zero otherwise ----------------------------------------------------------------*/ -static int p80211knetdev_stop( netdevice_t *netdev ) +static int p80211knetdev_stop(netdevice_t *netdev) { - int result = 0; - wlandevice_t *wlandev = netdev->ml_priv; + int result = 0; + wlandevice_t *wlandev = netdev->ml_priv; - DBFENTER; - - if ( wlandev->close != NULL ) { + if (wlandev->close != NULL) result = wlandev->close(wlandev); - } netif_stop_queue(wlandev->netdev); wlandev->state = WLAN_DEVICE_CLOSED; - DBFEXIT; return result; } @@ -279,17 +237,13 @@ static int p80211knetdev_stop( netdevice_t *netdev ) * Side effects: * ----------------------------------------------------------------*/ -void -p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb ) +void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb) { - DBFENTER; - /* Enqueue for post-irq processing */ skb_queue_tail(&wlandev->nsd_rxq, skb); tasklet_schedule(&wlandev->rx_bh); - DBFEXIT; return; } @@ -310,19 +264,17 @@ static void p80211netdev_rx_bh(unsigned long arg) { wlandevice_t *wlandev = (wlandevice_t *) arg; struct sk_buff *skb = NULL; - netdevice_t *dev = wlandev->netdev; + netdevice_t *dev = wlandev->netdev; p80211_hdr_a3_t *hdr; u16 fc; - DBFENTER; - /* Let's empty our our queue */ - while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) { + while ((skb = skb_dequeue(&wlandev->nsd_rxq))) { if (wlandev->state == WLAN_DEVICE_OPEN) { if (dev->type != ARPHRD_ETHER) { /* RAW frame; we shouldn't convert it */ - // XXX Append the Prism Header here instead. + /* XXX Append the Prism Header here instead. */ /* set up various data fields */ skb->dev = dev; @@ -337,8 +289,8 @@ static void p80211netdev_rx_bh(unsigned long arg) netif_rx_ni(skb); continue; } else { - hdr = (p80211_hdr_a3_t *)skb->data; - fc = ieee2host16(hdr->fc); + hdr = (p80211_hdr_a3_t *) skb->data; + fc = le16_to_cpu(hdr->fc); if (p80211_rx_typedrop(wlandev, fc)) { dev_kfree_skb(skb); continue; @@ -347,7 +299,9 @@ static void p80211netdev_rx_bh(unsigned long arg) /* perform mcast filtering */ if (wlandev->netdev->flags & IFF_ALLMULTI) { /* allow my local address through */ - if (memcmp(hdr->a1, wlandev->netdev->dev_addr, WLAN_ADDR_LEN) != 0) { + if (memcmp + (hdr->a1, wlandev->netdev->dev_addr, + ETH_ALEN) != 0) { /* but reject anything else that isn't multicast */ if (!(hdr->a1[0] & 0x01)) { dev_kfree_skb(skb); @@ -356,23 +310,22 @@ static void p80211netdev_rx_bh(unsigned long arg) } } - if ( skb_p80211_to_ether(wlandev, wlandev->ethconv, skb) == 0 ) { + if (skb_p80211_to_ether + (wlandev, wlandev->ethconv, skb) == 0) { skb->dev->last_rx = jiffies; wlandev->linux_stats.rx_packets++; - wlandev->linux_stats.rx_bytes += skb->len; + wlandev->linux_stats.rx_bytes += + skb->len; netif_rx_ni(skb); continue; } - WLAN_LOG_DEBUG(1, "p80211_to_ether failed.\n"); + pr_debug("p80211_to_ether failed.\n"); } } dev_kfree_skb(skb); } - - DBFEXIT; } - /*---------------------------------------------------------------- * p80211knetdev_hard_start_xmit * @@ -392,21 +345,19 @@ static void p80211netdev_rx_bh(unsigned long arg) * Returns: * zero on success, non-zero on failure. ----------------------------------------------------------------*/ -static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev) +static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, + netdevice_t *netdev) { - int result = 0; - int txresult = -1; - wlandevice_t *wlandev = netdev->ml_priv; - p80211_hdr_t p80211_hdr; + int result = 0; + int txresult = -1; + wlandevice_t *wlandev = netdev->ml_priv; + p80211_hdr_t p80211_hdr; p80211_metawep_t p80211_wep; - DBFENTER; - - if (skb == NULL) { + if (skb == NULL) return 0; - } - if (wlandev->state != WLAN_DEVICE_OPEN) { + if (wlandev->state != WLAN_DEVICE_OPEN) { result = 1; goto failed; } @@ -414,8 +365,8 @@ static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netd memset(&p80211_hdr, 0, sizeof(p80211_hdr_t)); memset(&p80211_wep, 0, sizeof(p80211_metawep_t)); - if ( netif_queue_stopped(netdev) ) { - WLAN_LOG_DEBUG(1, "called when queue stopped.\n"); + if (netif_queue_stopped(netdev)) { + pr_debug("called when queue stopped.\n"); result = 1; goto failed; } @@ -423,7 +374,7 @@ static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netd netif_stop_queue(netdev); /* Check to see that a valid mode is set */ - switch( wlandev->macmode ) { + switch (wlandev->macmode) { case WLAN_MACMODE_IBSS_STA: case WLAN_MACMODE_ESS_STA: case WLAN_MACMODE_ESS_AP: @@ -433,10 +384,10 @@ static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netd * and return success . * TODO: we need a saner way to handle this */ - if(skb->protocol != ETH_P_80211_RAW) { + if (skb->protocol != ETH_P_80211_RAW) { netif_start_queue(wlandev->netdev); - WLAN_LOG_NOTICE( - "Tx attempt prior to association, frame dropped.\n"); + printk(KERN_NOTICE + "Tx attempt prior to association, frame dropped.\n"); wlandev->linux_stats.tx_dropped++; result = 0; goto failed; @@ -445,7 +396,7 @@ static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netd } /* Check for raw transmits */ - if(skb->protocol == ETH_P_80211_RAW) { + if (skb->protocol == ETH_P_80211_RAW) { if (!capable(CAP_NET_ADMIN)) { result = 1; goto failed; @@ -454,15 +405,17 @@ static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netd memcpy(&p80211_hdr, skb->data, sizeof(p80211_hdr_t)); skb_pull(skb, sizeof(p80211_hdr_t)); } else { - if ( skb_ether_to_p80211(wlandev, wlandev->ethconv, skb, &p80211_hdr, &p80211_wep) != 0 ) { + if (skb_ether_to_p80211 + (wlandev, wlandev->ethconv, skb, &p80211_hdr, + &p80211_wep) != 0) { /* convert failed */ - WLAN_LOG_DEBUG(1, "ether_to_80211(%d) failed.\n", - wlandev->ethconv); + pr_debug("ether_to_80211(%d) failed.\n", + wlandev->ethconv); result = 1; goto failed; } } - if ( wlandev->txframe == NULL ) { + if (wlandev->txframe == NULL) { result = 1; goto failed; } @@ -475,28 +428,28 @@ static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netd txresult = wlandev->txframe(wlandev, skb, &p80211_hdr, &p80211_wep); - if ( txresult == 0) { + if (txresult == 0) { /* success and more buf */ /* avail, re: hw_txdata */ netif_wake_queue(wlandev->netdev); result = 0; - } else if ( txresult == 1 ) { + } else if (txresult == 1) { /* success, no more avail */ - WLAN_LOG_DEBUG(3, "txframe success, no more bufs\n"); + pr_debug("txframe success, no more bufs\n"); /* netdev->tbusy = 1; don't set here, irqhdlr */ /* may have already cleared it */ result = 0; - } else if ( txresult == 2 ) { + } else if (txresult == 2) { /* alloc failure, drop frame */ - WLAN_LOG_DEBUG(3, "txframe returned alloc_fail\n"); + pr_debug("txframe returned alloc_fail\n"); result = 1; } else { /* buffer full or queue busy, drop frame. */ - WLAN_LOG_DEBUG(3, "txframe returned full or busy\n"); + pr_debug("txframe returned full or busy\n"); result = 1; } - failed: +failed: /* Free up the WEP buffer if it's not the same as the skb */ if ((p80211_wep.data) && (p80211_wep.data != skb->data)) kfree(p80211_wep.data); @@ -505,11 +458,9 @@ static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netd if (!result) dev_kfree_skb(skb); - DBFEXIT; return result; } - /*---------------------------------------------------------------- * p80211knetdev_set_multicast_list * @@ -524,16 +475,13 @@ static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netd ----------------------------------------------------------------*/ static void p80211knetdev_set_multicast_list(netdevice_t *dev) { - wlandevice_t *wlandev = dev->ml_priv; - - DBFENTER; + wlandevice_t *wlandev = dev->ml_priv; /* TODO: real multicast support as well */ if (wlandev->set_multicast_list) wlandev->set_multicast_list(wlandev, dev); - DBFEXIT; } #ifdef SIOCETHTOOL @@ -558,9 +506,6 @@ static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr) snprintf(info.version, sizeof(info.version), "%s", WLAN_RELEASE); - // info.fw_version - // info.bus_info - if (copy_to_user(useraddr, &info, sizeof(info))) return -EFAULT; return 0; @@ -576,7 +521,7 @@ static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr) } if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; + return -EFAULT; return 0; } #endif @@ -615,45 +560,47 @@ static int p80211netdev_ethtool(wlandevice_t *wlandev, void __user *useraddr) ----------------------------------------------------------------*/ static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) { - int result = 0; - p80211ioctl_req_t *req = (p80211ioctl_req_t*)ifr; - wlandevice_t *wlandev = dev->ml_priv; - u8 *msgbuf; - DBFENTER; + int result = 0; + p80211ioctl_req_t *req = (p80211ioctl_req_t *) ifr; + wlandevice_t *wlandev = dev->ml_priv; + u8 *msgbuf; - WLAN_LOG_DEBUG(2, "rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); + pr_debug("rx'd ioctl, cmd=%d, len=%d\n", cmd, req->len); + + mutex_lock(&wlandev->ioctl_lock); #ifdef SIOCETHTOOL if (cmd == SIOCETHTOOL) { - result = p80211netdev_ethtool(wlandev, (void __user *) ifr->ifr_data); + result = + p80211netdev_ethtool(wlandev, (void __user *)ifr->ifr_data); goto bail; } #endif /* Test the magic, assume ifr is good if it's there */ - if ( req->magic != P80211_IOCTL_MAGIC ) { + if (req->magic != P80211_IOCTL_MAGIC) { result = -ENOSYS; goto bail; } - if ( cmd == P80211_IFTEST ) { + if (cmd == P80211_IFTEST) { result = 0; goto bail; - } else if ( cmd != P80211_IFREQ ) { + } else if (cmd != P80211_IFREQ) { result = -ENOSYS; goto bail; } /* Allocate a buf of size req->len */ - if ((msgbuf = kmalloc( req->len, GFP_KERNEL))) { - if ( copy_from_user( msgbuf, (void __user *) req->data, req->len) ) { + if ((msgbuf = kmalloc(req->len, GFP_KERNEL))) { + if (copy_from_user(msgbuf, (void __user *)req->data, req->len)) result = -EFAULT; - } else { - result = p80211req_dorequest( wlandev, msgbuf); - } + else + result = p80211req_dorequest(wlandev, msgbuf); - if ( result == 0 ) { - if ( copy_to_user( (void __user *) req->data, msgbuf, req->len)) { + if (result == 0) { + if (copy_to_user + ((void __user *)req->data, msgbuf, req->len)) { result = -EFAULT; } } @@ -662,9 +609,9 @@ static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd) result = -ENOMEM; } bail: - DBFEXIT; + mutex_unlock(&wlandev->ioctl_lock); - return result; /* If allocate,copyfrom or copyto fails, return errno */ + return result; /* If allocate,copyfrom or copyto fails, return errno */ } /*---------------------------------------------------------------- @@ -694,22 +641,20 @@ bail: ----------------------------------------------------------------*/ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) { - struct sockaddr *new_addr = addr; - p80211msg_dot11req_mibset_t dot11req; - p80211item_unk392_t *mibattr; - p80211item_pstr6_t *macaddr; - p80211item_uint32_t *resultcode; + struct sockaddr *new_addr = addr; + p80211msg_dot11req_mibset_t dot11req; + p80211item_unk392_t *mibattr; + p80211item_pstr6_t *macaddr; + p80211item_uint32_t *resultcode; int result = 0; - DBFENTER; /* If we're running, we don't allow MAC address changes */ - if (netif_running(dev)) { + if (netif_running(dev)) return -EBUSY; - } /* Set up some convenience pointers. */ mibattr = &dot11req.mibattribute; - macaddr = (p80211item_pstr6_t*)&mibattr->data; + macaddr = (p80211item_pstr6_t *)&mibattr->data; resultcode = &dot11req.resultcode; /* Set up a dot11req_mibset */ @@ -717,8 +662,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) dot11req.msgcode = DIDmsg_dot11req_mibset; dot11req.msglen = sizeof(p80211msg_dot11req_mibset_t); memcpy(dot11req.devname, - ((wlandevice_t *)dev->ml_priv)->name, - WLAN_DEVNAMELEN_MAX - 1); + ((wlandevice_t *) dev->ml_priv)->name, WLAN_DEVNAMELEN_MAX - 1); /* Set up the mibattribute argument */ mibattr->did = DIDmsg_dot11req_mibset_mibattribute; @@ -728,8 +672,8 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) macaddr->did = DIDmib_dot11mac_dot11OperationTable_dot11MACAddress; macaddr->status = P80211ENUM_msgitem_status_data_ok; macaddr->len = sizeof(macaddr->data); - macaddr->data.len = WLAN_ADDR_LEN; - memcpy(&macaddr->data.data, new_addr->sa_data, WLAN_ADDR_LEN); + macaddr->data.len = ETH_ALEN; + memcpy(&macaddr->data.data, new_addr->sa_data, ETH_ALEN); /* Set up the resultcode argument */ resultcode->did = DIDmsg_dot11req_mibset_resultcode; @@ -743,36 +687,30 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr) /* If the request wasn't successful, report an error and don't * change the netdev address */ - if ( result != 0 || resultcode->data != P80211ENUM_resultcode_success) { - WLAN_LOG_ERROR( - "Low-level driver failed dot11req_mibset(dot11MACAddress).\n"); + if (result != 0 || resultcode->data != P80211ENUM_resultcode_success) { + printk(KERN_ERR + "Low-level driver failed dot11req_mibset(dot11MACAddress).\n"); result = -EADDRNOTAVAIL; } else { /* everything's ok, change the addr in netdev */ memcpy(dev->dev_addr, new_addr->sa_data, dev->addr_len); } - DBFEXIT; return result; } static int wlan_change_mtu(netdevice_t *dev, int new_mtu) { - DBFENTER; - // 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap) - // and another 8 for wep. - if ( (new_mtu < 68) || (new_mtu > (2312 - 20 - 8))) - return -EINVAL; + /* 2312 is max 802.11 payload, 20 is overhead, (ether + llc +snap) + and another 8 for wep. */ + if ((new_mtu < 68) || (new_mtu > (2312 - 20 - 8))) + return -EINVAL; - dev->mtu = new_mtu; + dev->mtu = new_mtu; - DBFEXIT; - - return 0; + return 0; } - - /*---------------------------------------------------------------- * wlan_setup * @@ -797,10 +735,8 @@ static int wlan_change_mtu(netdevice_t *dev, int new_mtu) ----------------------------------------------------------------*/ int wlan_setup(wlandevice_t *wlandev) { - int result = 0; - netdevice_t *dev; - - DBFENTER; + int result = 0; + netdevice_t *dev; /* Set up the wlandev */ wlandev->state = WLAN_DEVICE_CLOSED; @@ -810,28 +746,26 @@ int wlan_setup(wlandevice_t *wlandev) /* Set up the rx queue */ skb_queue_head_init(&wlandev->nsd_rxq); tasklet_init(&wlandev->rx_bh, - p80211netdev_rx_bh, - (unsigned long)wlandev); + p80211netdev_rx_bh, (unsigned long)wlandev); /* Allocate and initialize the struct device */ - dev = alloc_netdev(0,"wlan%d",ether_setup); - if ( dev == NULL ) { - WLAN_LOG_ERROR("Failed to alloc netdev.\n"); + dev = alloc_netdev(0, "wlan%d", ether_setup); + if (dev == NULL) { + printk(KERN_ERR "Failed to alloc netdev.\n"); result = 1; } else { wlandev->netdev = dev; dev->ml_priv = wlandev; - dev->hard_start_xmit = p80211knetdev_hard_start_xmit; - dev->get_stats = p80211knetdev_get_stats; -#ifdef HAVE_PRIVATE_IOCTL - dev->do_ioctl = p80211knetdev_do_ioctl; -#endif -#ifdef HAVE_MULTICAST - dev->set_multicast_list = p80211knetdev_set_multicast_list; -#endif - dev->init = p80211knetdev_init; - dev->open = p80211knetdev_open; - dev->stop = p80211knetdev_stop; + dev->hard_start_xmit = p80211knetdev_hard_start_xmit; + dev->get_stats = p80211knetdev_get_stats; + dev->init = p80211knetdev_init; + dev->open = p80211knetdev_open; + dev->stop = p80211knetdev_stop; + + mutex_init(&wlandev->ioctl_lock); + /* block ioctls until fully initialised. Don't forget to call + allow_ioctls at some point!*/ + mutex_lock(&wlandev->ioctl_lock); #if (WIRELESS_EXT < 21) dev->get_wireless_stats = p80211wext_get_wireless_stats; @@ -839,20 +773,9 @@ int wlan_setup(wlandevice_t *wlandev) dev->wireless_handlers = &p80211wext_handler_def; netif_stop_queue(dev); -#ifdef HAVE_CHANGE_MTU - dev->change_mtu = wlan_change_mtu; -#endif -#ifdef HAVE_SET_MAC_ADDR - dev->set_mac_address = p80211knetdev_set_mac_address; -#endif -#ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = &p80211knetdev_tx_timeout; - dev->watchdog_timeo = (wlan_watchdog * HZ) / 1000; -#endif netif_carrier_off(dev); } - DBFEXIT; return result; } @@ -879,26 +802,21 @@ int wlan_setup(wlandevice_t *wlandev) ----------------------------------------------------------------*/ int wlan_unsetup(wlandevice_t *wlandev) { - int result = 0; - - DBFENTER; + int result = 0; tasklet_kill(&wlandev->rx_bh); - if (wlandev->netdev == NULL ) { - WLAN_LOG_ERROR("called without wlandev->netdev set.\n"); + if (wlandev->netdev == NULL) { + printk(KERN_ERR "called without wlandev->netdev set.\n"); result = 1; } else { free_netdev(wlandev->netdev); wlandev->netdev = NULL; } - DBFEXIT; return 0; } - - /*---------------------------------------------------------------- * register_wlandev * @@ -920,19 +838,15 @@ int wlan_unsetup(wlandevice_t *wlandev) ----------------------------------------------------------------*/ int register_wlandev(wlandevice_t *wlandev) { - int i = 0; - - DBFENTER; + int i = 0; i = register_netdev(wlandev->netdev); if (i) return i; - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * unregister_wlandev * @@ -954,20 +868,15 @@ int unregister_wlandev(wlandevice_t *wlandev) { struct sk_buff *skb; - DBFENTER; - unregister_netdev(wlandev->netdev); /* Now to clean out the rx queue */ - while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) { + while ((skb = skb_dequeue(&wlandev->nsd_rxq))) dev_kfree_skb(skb); - } - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * p80211netdev_hwremoved * @@ -1000,18 +909,13 @@ int unregister_wlandev(wlandevice_t *wlandev) ----------------------------------------------------------------*/ void p80211netdev_hwremoved(wlandevice_t *wlandev) { - DBFENTER; wlandev->hwremoved = 1; - if ( wlandev->state == WLAN_DEVICE_OPEN) { + if (wlandev->state == WLAN_DEVICE_OPEN) netif_stop_queue(wlandev->netdev); - } netif_device_detach(wlandev->netdev); - - DBFEXIT; } - /*---------------------------------------------------------------- * p80211_rx_typedrop * @@ -1033,28 +937,27 @@ void p80211netdev_hwremoved(wlandevice_t *wlandev) * Call context: * interrupt ----------------------------------------------------------------*/ -static int p80211_rx_typedrop( wlandevice_t *wlandev, u16 fc) +static int p80211_rx_typedrop(wlandevice_t *wlandev, u16 fc) { - u16 ftype; - u16 fstype; - int drop = 0; + u16 ftype; + u16 fstype; + int drop = 0; /* Classify frame, increment counter */ ftype = WLAN_GET_FC_FTYPE(fc); fstype = WLAN_GET_FC_FSTYPE(fc); #if 0 - WLAN_LOG_DEBUG(4, - "rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype); + pr_debug("rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype); #endif - switch ( ftype ) { + switch (ftype) { case WLAN_FTYPE_MGMT: if ((wlandev->netdev->flags & IFF_PROMISC) || - (wlandev->netdev->flags & IFF_ALLMULTI)) { + (wlandev->netdev->flags & IFF_ALLMULTI)) { drop = 1; break; } - WLAN_LOG_DEBUG(3, "rx'd mgmt:\n"); + pr_debug("rx'd mgmt:\n"); wlandev->rx.mgmt++; - switch( fstype ) { + switch (fstype) { case WLAN_FSTYPE_ASSOCREQ: /* printk("assocreq"); */ wlandev->rx.assocreq++; @@ -1110,13 +1013,13 @@ static int p80211_rx_typedrop( wlandevice_t *wlandev, u16 fc) case WLAN_FTYPE_CTL: if ((wlandev->netdev->flags & IFF_PROMISC) || - (wlandev->netdev->flags & IFF_ALLMULTI)) { + (wlandev->netdev->flags & IFF_ALLMULTI)) { drop = 1; break; } - WLAN_LOG_DEBUG(3, "rx'd ctl:\n"); + pr_debug("rx'd ctl:\n"); wlandev->rx.ctl++; - switch( fstype ) { + switch (fstype) { case WLAN_FSTYPE_PSPOLL: /* printk("pspoll"); */ wlandev->rx.pspoll++; @@ -1152,7 +1055,7 @@ static int p80211_rx_typedrop( wlandevice_t *wlandev, u16 fc) case WLAN_FTYPE_DATA: wlandev->rx.data++; - switch( fstype ) { + switch (fstype) { case WLAN_FSTYPE_DATAONLY: wlandev->rx.dataonly++; break; @@ -1166,19 +1069,19 @@ static int p80211_rx_typedrop( wlandevice_t *wlandev, u16 fc) wlandev->rx.data__cfack_cfpoll++; break; case WLAN_FSTYPE_NULL: - WLAN_LOG_DEBUG(3, "rx'd data:null\n"); + pr_debug("rx'd data:null\n"); wlandev->rx.null++; break; case WLAN_FSTYPE_CFACK: - WLAN_LOG_DEBUG(3, "rx'd data:cfack\n"); + pr_debug("rx'd data:cfack\n"); wlandev->rx.cfack++; break; case WLAN_FSTYPE_CFPOLL: - WLAN_LOG_DEBUG(3, "rx'd data:cfpoll\n"); + pr_debug("rx'd data:cfpoll\n"); wlandev->rx.cfpoll++; break; case WLAN_FSTYPE_CFACK_CFPOLL: - WLAN_LOG_DEBUG(3, "rx'd data:cfack_cfpoll\n"); + pr_debug("rx'd data:cfack_cfpoll\n"); wlandev->rx.cfack_cfpoll++; break; default: @@ -1192,18 +1095,20 @@ static int p80211_rx_typedrop( wlandevice_t *wlandev, u16 fc) return drop; } -static void p80211knetdev_tx_timeout( netdevice_t *netdev) +static void p80211knetdev_tx_timeout(netdevice_t *netdev) { - wlandevice_t *wlandev = netdev->ml_priv; - DBFENTER; + wlandevice_t *wlandev = netdev->ml_priv; if (wlandev->tx_timeout) { wlandev->tx_timeout(wlandev); } else { - WLAN_LOG_WARNING("Implement tx_timeout for %s\n", - wlandev->nsdname); + printk(KERN_WARNING "Implement tx_timeout for %s\n", + wlandev->nsdname); netif_wake_queue(wlandev->netdev); } - - DBFEXIT; +} + +void p80211_allow_ioctls(wlandevice_t *wlandev) +{ + mutex_unlock(&wlandev->ioctl_lock); } diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 940146fba9c1..b96090d87880 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -55,10 +55,16 @@ #include #include +#include /*================================================================*/ /* Constants */ +#undef netdevice_t +typedef struct net_device netdevice_t; + +#define WLAN_RELEASE "0.3.0-staging" + #define WLAN_DEVICE_CLOSED 0 #define WLAN_DEVICE_OPEN 1 @@ -68,8 +74,6 @@ #define WLAN_MACMODE_ESS_AP 3 /* MSD States */ -#define WLAN_MSD_START -1 -#define WLAN_MSD_DRIVERLOADED 0 #define WLAN_MSD_HWPRESENT_PENDING 1 #define WLAN_MSD_HWFAIL 2 #define WLAN_MSD_HWPRESENT 3 @@ -79,79 +83,66 @@ #define WLAN_MSD_RUNNING 7 #ifndef ETH_P_ECONET -#define ETH_P_ECONET 0x0018 /* needed for 2.2.x kernels */ +#define ETH_P_ECONET 0x0018 /* needed for 2.2.x kernels */ #endif #define ETH_P_80211_RAW (ETH_P_ECONET + 1) #ifndef ARPHRD_IEEE80211 -#define ARPHRD_IEEE80211 801 /* kernel 2.4.6 */ +#define ARPHRD_IEEE80211 801 /* kernel 2.4.6 */ #endif -#ifndef ARPHRD_IEEE80211_PRISM /* kernel 2.4.18 */ +#ifndef ARPHRD_IEEE80211_PRISM /* kernel 2.4.18 */ #define ARPHRD_IEEE80211_PRISM 802 #endif /*--- NSD Capabilities Flags ------------------------------*/ -#define P80211_NSDCAP_HARDWAREWEP 0x01 /* hardware wep engine */ -#define P80211_NSDCAP_TIEDWEP 0x02 /* can't decouple en/de */ -#define P80211_NSDCAP_NOHOSTWEP 0x04 /* must use hardware wep */ -#define P80211_NSDCAP_PBCC 0x08 /* hardware supports PBCC */ -#define P80211_NSDCAP_SHORT_PREAMBLE 0x10 /* hardware supports */ -#define P80211_NSDCAP_AGILITY 0x20 /* hardware supports */ -#define P80211_NSDCAP_AP_RETRANSMIT 0x40 /* nsd handles retransmits */ -#define P80211_NSDCAP_HWFRAGMENT 0x80 /* nsd handles frag/defrag */ -#define P80211_NSDCAP_AUTOJOIN 0x100 /* nsd does autojoin */ -#define P80211_NSDCAP_NOSCAN 0x200 /* nsd can scan */ - -/*================================================================*/ -/* Macros */ - -/*================================================================*/ -/* Types */ +#define P80211_NSDCAP_HARDWAREWEP 0x01 /* hardware wep engine */ +#define P80211_NSDCAP_SHORT_PREAMBLE 0x10 /* hardware supports */ +#define P80211_NSDCAP_HWFRAGMENT 0x80 /* nsd handles frag/defrag */ +#define P80211_NSDCAP_AUTOJOIN 0x100 /* nsd does autojoin */ +#define P80211_NSDCAP_NOSCAN 0x200 /* nsd can scan */ /* Received frame statistics */ -typedef struct p80211_frmrx_t -{ - u32 mgmt; - u32 assocreq; - u32 assocresp; - u32 reassocreq; - u32 reassocresp; - u32 probereq; - u32 proberesp; - u32 beacon; - u32 atim; - u32 disassoc; - u32 authen; - u32 deauthen; - u32 mgmt_unknown; - u32 ctl; - u32 pspoll; - u32 rts; - u32 cts; - u32 ack; - u32 cfend; - u32 cfendcfack; - u32 ctl_unknown; - u32 data; - u32 dataonly; - u32 data_cfack; - u32 data_cfpoll; - u32 data__cfack_cfpoll; - u32 null; - u32 cfack; - u32 cfpoll; - u32 cfack_cfpoll; - u32 data_unknown; - u32 decrypt; - u32 decrypt_err; +typedef struct p80211_frmrx_t { + u32 mgmt; + u32 assocreq; + u32 assocresp; + u32 reassocreq; + u32 reassocresp; + u32 probereq; + u32 proberesp; + u32 beacon; + u32 atim; + u32 disassoc; + u32 authen; + u32 deauthen; + u32 mgmt_unknown; + u32 ctl; + u32 pspoll; + u32 rts; + u32 cts; + u32 ack; + u32 cfend; + u32 cfendcfack; + u32 ctl_unknown; + u32 data; + u32 dataonly; + u32 data_cfack; + u32 data_cfpoll; + u32 data__cfack_cfpoll; + u32 null; + u32 cfack; + u32 cfpoll; + u32 cfack_cfpoll; + u32 data_unknown; + u32 decrypt; + u32 decrypt_err; } p80211_frmrx_t; /* called by /proc/net/wireless */ -struct iw_statistics* p80211wext_get_wireless_stats(netdevice_t *dev); +struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t * dev); /* wireless extensions' ioctls */ -int p80211wext_support_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd); extern struct iw_handler_def p80211wext_handler_def; int p80211wext_event_associated(struct wlandevice *wlandev, int assoc); @@ -159,96 +150,99 @@ int p80211wext_event_associated(struct wlandevice *wlandev, int assoc); #define NUM_WEPKEYS 4 #define MAX_KEYLEN 32 -#define HOSTWEP_DEFAULTKEY_MASK (BIT1|BIT0) -#define HOSTWEP_DECRYPT BIT4 -#define HOSTWEP_ENCRYPT BIT5 -#define HOSTWEP_PRIVACYINVOKED BIT6 -#define HOSTWEP_EXCLUDEUNENCRYPTED BIT7 +#define HOSTWEP_DEFAULTKEY_MASK (BIT(1)|BIT(0)) +#define HOSTWEP_DECRYPT BIT(4) +#define HOSTWEP_ENCRYPT BIT(5) +#define HOSTWEP_PRIVACYINVOKED BIT(6) +#define HOSTWEP_EXCLUDEUNENCRYPTED BIT(7) extern int wlan_watchdog; extern int wlan_wext_write; /* WLAN device type */ -typedef struct wlandevice -{ - struct wlandevice *next; /* link for list of devices */ - void *priv; /* private data for MSD */ +typedef struct wlandevice { + struct wlandevice *next; /* link for list of devices */ + void *priv; /* private data for MSD */ /* Subsystem State */ - char name[WLAN_DEVNAMELEN_MAX]; /* Dev name, from register_wlandev()*/ - char *nsdname; + char name[WLAN_DEVNAMELEN_MAX]; /* Dev name, from register_wlandev() */ + char *nsdname; - u32 state; /* Device I/F state (open/closed) */ - u32 msdstate; /* state of underlying driver */ - u32 hwremoved; /* Has the hw been yanked out? */ + u32 state; /* Device I/F state (open/closed) */ + u32 msdstate; /* state of underlying driver */ + u32 hwremoved; /* Has the hw been yanked out? */ /* Hardware config */ - unsigned int irq; - unsigned int iobase; - unsigned int membase; - u32 nsdcaps; /* NSD Capabilities flags */ + unsigned int irq; + unsigned int iobase; + unsigned int membase; + u32 nsdcaps; /* NSD Capabilities flags */ /* Config vars */ - unsigned int ethconv; + unsigned int ethconv; /* device methods (init by MSD, used by p80211 */ - int (*open)(struct wlandevice *wlandev); - int (*close)(struct wlandevice *wlandev); - void (*reset)(struct wlandevice *wlandev ); - int (*txframe)(struct wlandevice *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); - int (*mlmerequest)(struct wlandevice *wlandev, p80211msg_t *msg); - int (*set_multicast_list)(struct wlandevice *wlandev, - netdevice_t *dev); - void (*tx_timeout)(struct wlandevice *wlandev); + int (*open) (struct wlandevice *wlandev); + int (*close) (struct wlandevice *wlandev); + void (*reset) (struct wlandevice *wlandev); + int (*txframe) (struct wlandevice *wlandev, struct sk_buff *skb, + p80211_hdr_t *p80211_hdr, + p80211_metawep_t *p80211_wep); + int (*mlmerequest) (struct wlandevice *wlandev, p80211msg_t *msg); + int (*set_multicast_list) (struct wlandevice *wlandev, + netdevice_t *dev); + void (*tx_timeout) (struct wlandevice *wlandev); /* 802.11 State */ - u8 bssid[WLAN_BSSID_LEN]; - p80211pstr32_t ssid; - u32 macmode; - int linkstatus; + u8 bssid[WLAN_BSSID_LEN]; + p80211pstr32_t ssid; + u32 macmode; + int linkstatus; /* WEP State */ u8 wep_keys[NUM_WEPKEYS][MAX_KEYLEN]; u8 wep_keylens[NUM_WEPKEYS]; - int hostwep; + int hostwep; /* Request/Confirm i/f state (used by p80211) */ - unsigned long request_pending; /* flag, access atomically */ + unsigned long request_pending; /* flag, access atomically */ /* netlink socket */ /* queue for indications waiting for cmd completion */ /* Linux netdevice and support */ - netdevice_t *netdev; /* ptr to linux netdevice */ + netdevice_t *netdev; /* ptr to linux netdevice */ struct net_device_stats linux_stats; /* Rx bottom half */ - struct tasklet_struct rx_bh; + struct tasklet_struct rx_bh; - struct sk_buff_head nsd_rxq; + struct sk_buff_head nsd_rxq; /* 802.11 device statistics */ - struct p80211_frmrx_t rx; + struct p80211_frmrx_t rx; - struct iw_statistics wstats; + struct iw_statistics wstats; /* jkriegl: iwspy fields */ - u8 spy_number; - char spy_address[IW_MAX_SPY][ETH_ALEN]; - struct iw_quality spy_stat[IW_MAX_SPY]; + u8 spy_number; + char spy_address[IW_MAX_SPY][ETH_ALEN]; + struct iw_quality spy_stat[IW_MAX_SPY]; + + struct mutex ioctl_lock; } wlandevice_t; /* WEP stuff */ -int wep_change_key(wlandevice_t *wlandev, int keynum, u8* key, int keylen); -int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv); -int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 *iv, u8 *icv); - -void p80211netdev_startup(void); -void p80211netdev_shutdown(void); -int wlan_setup(wlandevice_t *wlandev); -int wlan_unsetup(wlandevice_t *wlandev); -int register_wlandev(wlandevice_t *wlandev); -int unregister_wlandev(wlandevice_t *wlandev); -void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb); -void p80211netdev_hwremoved(wlandevice_t *wlandev); +int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen); +int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, + u8 *iv, u8 *icv); +int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, + u8 *iv, u8 *icv); +int wlan_setup(wlandevice_t *wlandev); +int wlan_unsetup(wlandevice_t *wlandev); +int register_wlandev(wlandevice_t *wlandev); +int unregister_wlandev(wlandevice_t *wlandev); +void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb); +void p80211netdev_hwremoved(wlandevice_t *wlandev); +void p80211_allow_ioctls(wlandevice_t *wlandev); #endif diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 6e20bff0e67e..15ecba6e4693 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -50,11 +50,6 @@ * -------------------------------------------------------------------- */ -/*================================================================*/ -/* System Includes */ - - - #include #include #include @@ -67,11 +62,6 @@ #include #include -#include "wlan_compat.h" - -/*================================================================*/ -/* Project Includes */ - #include "p80211types.h" #include "p80211hdr.h" #include "p80211mgmt.h" @@ -83,30 +73,10 @@ #include "p80211metastruct.h" #include "p80211req.h" -/*================================================================*/ -/* Local Constants */ - -/* Maximum amount of time we'll wait for a request to complete */ -#define P80211REQ_MAXTIME 3*HZ /* 3 seconds */ - -/*================================================================*/ -/* Local Macros */ - -/*================================================================*/ -/* Local Types */ - -/*================================================================*/ -/* Local Static Definitions */ - -/*================================================================*/ -/* Local Function Declarations */ - -static void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg); -static int p80211req_mibset_mibget(wlandevice_t *wlandev, p80211msg_dot11req_mibget_t *mib_msg, int isget); - -/*================================================================*/ -/* Function Definitions */ - +static void p80211req_handlemsg(wlandevice_t *wlandev, p80211msg_t *msg); +static int p80211req_mibset_mibget(wlandevice_t *wlandev, + p80211msg_dot11req_mibget_t *mib_msg, + int isget); /*---------------------------------------------------------------- * p80211req_dorequest @@ -124,33 +94,30 @@ static int p80211req_mibset_mibget(wlandevice_t *wlandev, p80211msg_dot11req_mib * Potentially blocks the caller, so it's a good idea to * not call this function from an interrupt context. ----------------------------------------------------------------*/ -int p80211req_dorequest( wlandevice_t *wlandev, u8 *msgbuf) +int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf) { - int result = 0; - p80211msg_t *msg = (p80211msg_t*)msgbuf; - - DBFENTER; + int result = 0; + p80211msg_t *msg = (p80211msg_t *) msgbuf; /* Check to make sure the MSD is running */ - if ( - !((wlandev->msdstate == WLAN_MSD_HWPRESENT && - msg->msgcode == DIDmsg_lnxreq_ifstate) || - wlandev->msdstate == WLAN_MSD_RUNNING || - wlandev->msdstate == WLAN_MSD_FWLOAD) ) { + if (!((wlandev->msdstate == WLAN_MSD_HWPRESENT && + msg->msgcode == DIDmsg_lnxreq_ifstate) || + wlandev->msdstate == WLAN_MSD_RUNNING || + wlandev->msdstate == WLAN_MSD_FWLOAD)) { return -ENODEV; } /* Check Permissions */ - if (!capable(CAP_NET_ADMIN) && - (msg->msgcode != DIDmsg_dot11req_mibget)) { - WLAN_LOG_ERROR("%s: only dot11req_mibget allowed for non-root.\n", wlandev->name); + if (!capable(CAP_NET_ADMIN) && (msg->msgcode != DIDmsg_dot11req_mibget)) { + printk(KERN_ERR + "%s: only dot11req_mibget allowed for non-root.\n", + wlandev->name); return -EPERM; } /* Check for busy status */ - if ( test_and_set_bit(1, &(wlandev->request_pending))) { + if (test_and_set_bit(1, &(wlandev->request_pending))) return -EBUSY; - } /* Allow p80211 to look at msg and handle if desired. */ /* So far, all p80211 msgs are immediate, no waitq/timer necessary */ @@ -158,12 +125,11 @@ int p80211req_dorequest( wlandevice_t *wlandev, u8 *msgbuf) p80211req_handlemsg(wlandev, msg); /* Pass it down to wlandev via wlandev->mlmerequest */ - if ( wlandev->mlmerequest != NULL ) + if (wlandev->mlmerequest != NULL) wlandev->mlmerequest(wlandev, msg); - clear_bit( 1, &(wlandev->request_pending)); - DBFEXIT; - return result; /* if result==0, msg->status still may contain an err */ + clear_bit(1, &(wlandev->request_pending)); + return result; /* if result==0, msg->status still may contain an err */ } /*---------------------------------------------------------------- @@ -184,34 +150,32 @@ int p80211req_dorequest( wlandevice_t *wlandev, u8 *msgbuf) * Call context: * Process thread ----------------------------------------------------------------*/ -static void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg) +static void p80211req_handlemsg(wlandevice_t *wlandev, p80211msg_t *msg) { - DBFENTER; - switch (msg->msgcode) { - case DIDmsg_lnxreq_hostwep: { - p80211msg_lnxreq_hostwep_t *req = (p80211msg_lnxreq_hostwep_t*) msg; - wlandev->hostwep &= ~(HOSTWEP_DECRYPT|HOSTWEP_ENCRYPT); - if (req->decrypt.data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_DECRYPT; - if (req->encrypt.data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_ENCRYPT; + case DIDmsg_lnxreq_hostwep:{ + p80211msg_lnxreq_hostwep_t *req = + (p80211msg_lnxreq_hostwep_t *) msg; + wlandev->hostwep &= + ~(HOSTWEP_DECRYPT | HOSTWEP_ENCRYPT); + if (req->decrypt.data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_DECRYPT; + if (req->encrypt.data == P80211ENUM_truth_true) + wlandev->hostwep |= HOSTWEP_ENCRYPT; - break; - } + break; + } case DIDmsg_dot11req_mibget: - case DIDmsg_dot11req_mibset: { - int isget = (msg->msgcode == DIDmsg_dot11req_mibget); - p80211msg_dot11req_mibget_t *mib_msg = (p80211msg_dot11req_mibget_t *) msg; - p80211req_mibset_mibget (wlandev, mib_msg, isget); - } + case DIDmsg_dot11req_mibset:{ + int isget = (msg->msgcode == DIDmsg_dot11req_mibget); + p80211msg_dot11req_mibget_t *mib_msg = + (p80211msg_dot11req_mibget_t *) msg; + p80211req_mibset_mibget(wlandev, mib_msg, isget); + } default: - // XXX do nothing! ; - } /* switch msg->msgcode */ - - DBFEXIT; + } /* switch msg->msgcode */ return; } @@ -220,81 +184,82 @@ static int p80211req_mibset_mibget(wlandevice_t *wlandev, p80211msg_dot11req_mibget_t *mib_msg, int isget) { - p80211itemd_t *mibitem = (p80211itemd_t *) mib_msg->mibattribute.data; - p80211pstrd_t *pstr = (p80211pstrd_t*) mibitem->data; + p80211itemd_t *mibitem = (p80211itemd_t *) mib_msg->mibattribute.data; + p80211pstrd_t *pstr = (p80211pstrd_t *) mibitem->data; u8 *key = mibitem->data + sizeof(p80211pstrd_t); - DBFENTER; - switch (mibitem->did) { - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0: { - if (!isget) - wep_change_key(wlandev, 0, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1: { - if (!isget) - wep_change_key(wlandev, 1, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2: { - if (!isget) - wep_change_key(wlandev, 2, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3: { - if (!isget) - wep_change_key(wlandev, 3, key, pstr->len); - break; - } - case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID: { - u32 *data = (u32 *) mibitem->data; + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0:{ + if (!isget) + wep_change_key(wlandev, 0, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1:{ + if (!isget) + wep_change_key(wlandev, 1, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2:{ + if (!isget) + wep_change_key(wlandev, 2, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3:{ + if (!isget) + wep_change_key(wlandev, 3, key, pstr->len); + break; + } + case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID:{ + u32 *data = (u32 *) mibitem->data; - if (isget) { - *data = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; + if (isget) { + *data = + wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; } else { wlandev->hostwep &= ~(HOSTWEP_DEFAULTKEY_MASK); - wlandev->hostwep |= (*data & HOSTWEP_DEFAULTKEY_MASK); + wlandev->hostwep |= + (*data & HOSTWEP_DEFAULTKEY_MASK); } - break; - } - case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked: { - u32 *data = (u32 *) mibitem->data; + break; + } + case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked:{ + u32 *data = (u32 *) mibitem->data; - if (isget) { - if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) - *data = P80211ENUM_truth_true; - else - *data = P80211ENUM_truth_false; - } else { + if (isget) { + if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { wlandev->hostwep &= ~(HOSTWEP_PRIVACYINVOKED); if (*data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_PRIVACYINVOKED; + wlandev->hostwep |= + HOSTWEP_PRIVACYINVOKED; + } + break; } - break; - } - case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted: { - u32 *data = (u32 *) mibitem->data; + case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted:{ + u32 *data = (u32 *) mibitem->data; - if (isget) { - if (wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) - *data = P80211ENUM_truth_true; - else - *data = P80211ENUM_truth_false; - } else { - wlandev->hostwep &= ~(HOSTWEP_EXCLUDEUNENCRYPTED); - if (*data == P80211ENUM_truth_true) - wlandev->hostwep |= HOSTWEP_EXCLUDEUNENCRYPTED; + if (isget) { + if (wlandev-> + hostwep & HOSTWEP_EXCLUDEUNENCRYPTED) + *data = P80211ENUM_truth_true; + else + *data = P80211ENUM_truth_false; + } else { + wlandev->hostwep &= + ~(HOSTWEP_EXCLUDEUNENCRYPTED); + if (*data == P80211ENUM_truth_true) + wlandev->hostwep |= + HOSTWEP_EXCLUDEUNENCRYPTED; + } + break; } - break; - } default: - // XXXX do nothing! ; } - DBFEXIT; return 0; } - diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h index 497a4d6eb59a..a95a45a6814d 100644 --- a/drivers/staging/wlan-ng/p80211req.h +++ b/drivers/staging/wlan-ng/p80211req.h @@ -48,21 +48,6 @@ #ifndef _LINUX_P80211REQ_H #define _LINUX_P80211REQ_H -/*================================================================*/ -/* Constants */ - -/*================================================================*/ -/* Macros */ - -/*================================================================*/ -/* Types */ - -/*================================================================*/ -/* Externs */ - -/*================================================================*/ -/* Function Declarations */ - -int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf); +int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf); #endif diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h index 5be6737e3e5d..a22437ceddca 100644 --- a/drivers/staging/wlan-ng/p80211types.h +++ b/drivers/staging/wlan-ng/p80211types.h @@ -57,38 +57,10 @@ #ifndef _P80211TYPES_H #define _P80211TYPES_H -/*================================================================*/ -/* System Includes */ -/*================================================================*/ - /*================================================================*/ /* Project Includes */ /*================================================================*/ -#ifndef _WLAN_COMPAT_H -#include "wlan_compat.h" -#endif - -/*================================================================*/ -/* Constants */ -/*================================================================*/ - -/*----------------------------------------------------------------*/ -/* p80211 data type codes used for MIB items and message */ -/* arguments. The various metadata structures provide additional */ -/* information about these types. */ - -#define P80211_TYPE_OCTETSTR 1 /* pascal array of bytes */ -#define P80211_TYPE_DISPLAYSTR 2 /* pascal array of bytes containing ascii */ -#define P80211_TYPE_int 4 /* u32 min and max limited by 32 bits */ -#define P80211_TYPE_ENUMint 5 /* u32 holding a numeric - code that can be mapped - to a textual name */ -#define P80211_TYPE_UNKDATA 6 /* Data item containing an - unknown data type */ -#define P80211_TYPE_intARRAY 7 /* Array of 32-bit integers. */ -#define P80211_TYPE_BITARRAY 8 /* Array of bits. */ -#define P80211_TYPE_MACARRAY 9 /* Array of MAC addresses. */ /*----------------------------------------------------------------*/ /* The following constants are indexes into the Mib Category List */ @@ -106,25 +78,6 @@ /* Message Category List */ #define P80211_MSG_CAT_DOT11REQ 1 #define P80211_MSG_CAT_DOT11IND 2 -/* #define P80211_MSG_CAT_DOT11CFM 3 (doesn't exist at this time) */ - -#define P80211SEC_DOT11REQ P80211_MSG_CAT_DOT11REQ -#define P80211SEC_DOT11IND P80211_MSG_CAT_DOT11IND -/* #define P80211SEC_DOT11CFM P80211_MSG_CAT_DOT11CFM (doesn't exist at this time */ - - - -/*----------------------------------------------------------------*/ -/* p80211 DID field codes that represent access type and */ -/* is_table status. */ - -#define P80211DID_ACCESS_READ 0x10000000 -#define P80211DID_ACCESS_WRITE 0x08000000 -#define P80211DID_WRITEONLY 0x00000001 -#define P80211DID_READONLY 0x00000002 -#define P80211DID_READWRITE 0x00000003 -#define P80211DID_ISTABLE_FALSE 0 -#define P80211DID_ISTABLE_TRUE 1 /*----------------------------------------------------------------*/ /* p80211 enumeration constants. The value to text mappings for */ @@ -132,104 +85,30 @@ /* from the mappings. */ /* error codes for lookups */ -#define P80211ENUM_BAD 0xffffffffUL -#define P80211ENUM_BADSTR "P80211ENUM_BAD" #define P80211ENUM_truth_false 0 #define P80211ENUM_truth_true 1 #define P80211ENUM_ifstate_disable 0 #define P80211ENUM_ifstate_fwload 1 #define P80211ENUM_ifstate_enable 2 -#define P80211ENUM_powermgmt_active 1 -#define P80211ENUM_powermgmt_powersave 2 #define P80211ENUM_bsstype_infrastructure 1 #define P80211ENUM_bsstype_independent 2 #define P80211ENUM_bsstype_any 3 #define P80211ENUM_authalg_opensystem 1 #define P80211ENUM_authalg_sharedkey 2 -#define P80211ENUM_phytype_fhss 1 -#define P80211ENUM_phytype_dsss 2 -#define P80211ENUM_phytype_irbaseband 3 -#define P80211ENUM_temptype_commercial 1 -#define P80211ENUM_temptype_industrial 2 -#define P80211ENUM_regdomain_fcc 16 -#define P80211ENUM_regdomain_doc 32 -#define P80211ENUM_regdomain_etsi 48 -#define P80211ENUM_regdomain_spain 49 -#define P80211ENUM_regdomain_france 50 -#define P80211ENUM_regdomain_mkk 64 -#define P80211ENUM_ccamode_edonly 1 -#define P80211ENUM_ccamode_csonly 2 -#define P80211ENUM_ccamode_edandcs 4 -#define P80211ENUM_ccamode_cswithtimer 8 -#define P80211ENUM_ccamode_hrcsanded 16 -#define P80211ENUM_diversity_fixedlist 1 -#define P80211ENUM_diversity_notsupported 2 -#define P80211ENUM_diversity_dynamic 3 #define P80211ENUM_scantype_active 1 -#define P80211ENUM_scantype_passive 2 -#define P80211ENUM_scantype_both 3 #define P80211ENUM_resultcode_success 1 #define P80211ENUM_resultcode_invalid_parameters 2 #define P80211ENUM_resultcode_not_supported 3 -#define P80211ENUM_resultcode_timeout 4 -#define P80211ENUM_resultcode_too_many_req 5 #define P80211ENUM_resultcode_refused 6 -#define P80211ENUM_resultcode_bss_already 7 -#define P80211ENUM_resultcode_invalid_access 8 -#define P80211ENUM_resultcode_invalid_mibattribute 9 #define P80211ENUM_resultcode_cant_set_readonly_mib 10 #define P80211ENUM_resultcode_implementation_failure 11 #define P80211ENUM_resultcode_cant_get_writeonly_mib 12 -#define P80211ENUM_reason_unspec_reason 1 -#define P80211ENUM_reason_auth_not_valid 2 -#define P80211ENUM_reason_deauth_lv_ss 3 -#define P80211ENUM_reason_inactivity 4 -#define P80211ENUM_reason_ap_overload 5 -#define P80211ENUM_reason_class23_err 6 -#define P80211ENUM_reason_class3_err 7 -#define P80211ENUM_reason_disas_lv_ss 8 -#define P80211ENUM_reason_asoc_not_auth 9 #define P80211ENUM_status_successful 0 #define P80211ENUM_status_unspec_failure 1 -#define P80211ENUM_status_unsup_cap 10 -#define P80211ENUM_status_reasoc_no_asoc 11 -#define P80211ENUM_status_fail_other 12 -#define P80211ENUM_status_unspt_alg 13 -#define P80211ENUM_status_auth_seq_fail 14 -#define P80211ENUM_status_chlng_fail 15 -#define P80211ENUM_status_auth_timeout 16 #define P80211ENUM_status_ap_full 17 -#define P80211ENUM_status_unsup_rate 18 -#define P80211ENUM_status_unsup_shortpreamble 19 -#define P80211ENUM_status_unsup_pbcc 20 -#define P80211ENUM_status_unsup_agility 21 #define P80211ENUM_msgitem_status_data_ok 0 #define P80211ENUM_msgitem_status_no_value 1 -#define P80211ENUM_msgitem_status_invalid_itemname 2 -#define P80211ENUM_msgitem_status_invalid_itemdata 3 -#define P80211ENUM_msgitem_status_missing_itemdata 4 -#define P80211ENUM_msgitem_status_incomplete_itemdata 5 -#define P80211ENUM_msgitem_status_invalid_msg_did 6 -#define P80211ENUM_msgitem_status_invalid_mib_did 7 -#define P80211ENUM_msgitem_status_missing_conv_func 8 -#define P80211ENUM_msgitem_status_string_too_long 9 -#define P80211ENUM_msgitem_status_data_out_of_range 10 -#define P80211ENUM_msgitem_status_string_too_short 11 -#define P80211ENUM_msgitem_status_missing_valid_func 12 -#define P80211ENUM_msgitem_status_unknown 13 -#define P80211ENUM_msgitem_status_invalid_did 14 -#define P80211ENUM_msgitem_status_missing_print_func 15 - -#define P80211ENUM_lnxroam_reason_unknown 0 -#define P80211ENUM_lnxroam_reason_beacon 1 -#define P80211ENUM_lnxroam_reason_signal 2 -#define P80211ENUM_lnxroam_reason_txretry 3 -#define P80211ENUM_lnxroam_reason_notjoined 4 - -#define P80211ENUM_p2preamble_long 0 -#define P80211ENUM_p2preamble_short 2 -#define P80211ENUM_p2preamble_mixed 3 /*----------------------------------------------------------------*/ /* p80211 max length constants for the different pascal strings. */ @@ -243,46 +122,6 @@ /* is a DID-LEN-DATA triple */ /* with a max size of 4+4+384 */ -#define P80211_SET_int(item, value) do { \ - (item).data = (value); \ - (item).status = P80211ENUM_msgitem_status_data_ok; \ - } while(0) -/*----------------------------------------------------------------*/ -/* string constants */ - -#define NOT_SET "NOT_SET" -#define NOT_SUPPORTED "NOT_SUPPORTED" -#define UNKNOWN_DATA "UNKNOWN_DATA" - - -/*--------------------------------------------------------------------*/ -/* Metadata flags */ - -/* MSM: Do these belong in p80211meta.h? I'm not sure. */ - -#define ISREQUIRED (0x80000000UL) -#define ISREQUEST (0x40000000UL) -#define ISCONFIRM (0x20000000UL) - - -/*================================================================*/ -/* Macros */ - -/*--------------------------------------------------------------------*/ -/* The following macros are used to manipulate the 'flags' field in */ -/* the metadata. These are only used when the metadata is for */ -/* command arguments to determine if the data item is required, and */ -/* whether the metadata item is for a request command, confirm */ -/* command or both. */ -/*--------------------------------------------------------------------*/ -/* MSM: Do these belong in p80211meta.h? I'm not sure */ - -#define P80211ITEM_SETFLAGS(q, r, c) ( q | r | c ) - -#define P80211ITEM_ISREQUIRED(flags) (((u32)(flags & ISREQUIRED)) >> 31 ) -#define P80211ITEM_ISREQUEST(flags) (((u32)(flags & ISREQUEST)) >> 30 ) -#define P80211ITEM_ISCONFIRM(flags) (((u32)(flags & ISCONFIRM)) >> 29 ) - /*----------------------------------------------------------------*/ /* The following macro creates a name for an enum */ @@ -302,9 +141,6 @@ * . - Unused */ -#define P80211DID_INVALID 0xffffffffUL -#define P80211DID_VALID 0x00000000UL - #define P80211DID_LSB_SECTION (0) #define P80211DID_LSB_GROUP (6) #define P80211DID_LSB_ITEM (12) @@ -319,35 +155,32 @@ #define P80211DID_MASK_ISTABLE (0x00000001UL) #define P80211DID_MASK_ACCESS (0x00000003UL) - -#define P80211DID_MK(a,m,l) ((((u32)(a)) & (m)) << (l)) +#define P80211DID_MK(a, m, l) ((((u32)(a)) & (m)) << (l)) #define P80211DID_MKSECTION(a) P80211DID_MK(a, \ P80211DID_MASK_SECTION, \ - P80211DID_LSB_SECTION ) + P80211DID_LSB_SECTION) #define P80211DID_MKGROUP(a) P80211DID_MK(a, \ P80211DID_MASK_GROUP, \ - P80211DID_LSB_GROUP ) + P80211DID_LSB_GROUP) #define P80211DID_MKITEM(a) P80211DID_MK(a, \ P80211DID_MASK_ITEM, \ - P80211DID_LSB_ITEM ) + P80211DID_LSB_ITEM) #define P80211DID_MKINDEX(a) P80211DID_MK(a, \ P80211DID_MASK_INDEX, \ - P80211DID_LSB_INDEX ) + P80211DID_LSB_INDEX) #define P80211DID_MKISTABLE(a) P80211DID_MK(a, \ P80211DID_MASK_ISTABLE, \ - P80211DID_LSB_ISTABLE ) - + P80211DID_LSB_ISTABLE) #define P80211DID_MKID(s,g,i,n,t,a) (P80211DID_MKSECTION(s) | \ P80211DID_MKGROUP(g) | \ P80211DID_MKITEM(i) | \ P80211DID_MKINDEX(n) | \ P80211DID_MKISTABLE(t) | \ - (a) ) + (a)) - -#define P80211DID_GET(a,m,l) ((((u32)(a)) >> (l)) & (m)) +#define P80211DID_GET(a, m, l) ((((u32)(a)) >> (l)) & (m)) #define P80211DID_SECTION(a) P80211DID_GET(a, \ P80211DID_MASK_SECTION, \ @@ -368,23 +201,18 @@ P80211DID_MASK_ACCESS, \ P80211DID_LSB_ACCESS) -/*================================================================*/ -/* Types */ - /*----------------------------------------------------------------*/ /* The following structure types are used for the represenation */ /* of ENUMint type metadata. */ -typedef struct p80211enumpair -{ - u32 val; - char *name; +typedef struct p80211enumpair { + u32 val; + char *name; } p80211enumpair_t; -typedef struct p80211enum -{ - int nitems; - p80211enumpair_t *list; +typedef struct p80211enum { + int nitems; + p80211enumpair_t *list; } p80211enum_t; /*----------------------------------------------------------------*/ @@ -392,140 +220,123 @@ typedef struct p80211enum /* messages. */ /* Template pascal string */ -typedef struct p80211pstr -{ - u8 len; -} __WLAN_ATTRIB_PACK__ p80211pstr_t; +typedef struct p80211pstr { + u8 len; +} __attribute__ ((packed)) p80211pstr_t; -typedef struct p80211pstrd -{ - u8 len; - u8 data[0]; -} __WLAN_ATTRIB_PACK__ p80211pstrd_t; +typedef struct p80211pstrd { + u8 len; + u8 data[0]; +} __attribute__ ((packed)) p80211pstrd_t; /* Maximum pascal string */ -typedef struct p80211pstr255 -{ - u8 len; - u8 data[MAXLEN_PSTR255]; -} __WLAN_ATTRIB_PACK__ p80211pstr255_t; +typedef struct p80211pstr255 { + u8 len; + u8 data[MAXLEN_PSTR255]; +} __attribute__ ((packed)) p80211pstr255_t; /* pascal string for macaddress and bssid */ -typedef struct p80211pstr6 -{ - u8 len; - u8 data[MAXLEN_PSTR6]; -} __WLAN_ATTRIB_PACK__ p80211pstr6_t; +typedef struct p80211pstr6 { + u8 len; + u8 data[MAXLEN_PSTR6]; +} __attribute__ ((packed)) p80211pstr6_t; /* pascal string for channel list */ -typedef struct p80211pstr14 -{ - u8 len; - u8 data[MAXLEN_PSTR14]; -} __WLAN_ATTRIB_PACK__ p80211pstr14_t; +typedef struct p80211pstr14 { + u8 len; + u8 data[MAXLEN_PSTR14]; +} __attribute__ ((packed)) p80211pstr14_t; /* pascal string for ssid */ -typedef struct p80211pstr32 -{ - u8 len; - u8 data[MAXLEN_PSTR32]; -} __WLAN_ATTRIB_PACK__ p80211pstr32_t; +typedef struct p80211pstr32 { + u8 len; + u8 data[MAXLEN_PSTR32]; +} __attribute__ ((packed)) p80211pstr32_t; /* MAC address array */ -typedef struct p80211macarray -{ - u32 cnt; - u8 data[1][MAXLEN_PSTR6]; -} __WLAN_ATTRIB_PACK__ p80211macarray_t; +typedef struct p80211macarray { + u32 cnt; + u8 data[1][MAXLEN_PSTR6]; +} __attribute__ ((packed)) p80211macarray_t; /* prototype template */ -typedef struct p80211item -{ - u32 did; - u16 status; - u16 len; -} __WLAN_ATTRIB_PACK__ p80211item_t; +typedef struct p80211item { + u32 did; + u16 status; + u16 len; +} __attribute__ ((packed)) p80211item_t; /* prototype template w/ data item */ -typedef struct p80211itemd -{ - u32 did; - u16 status; - u16 len; - u8 data[0]; -} __WLAN_ATTRIB_PACK__ p80211itemd_t; +typedef struct p80211itemd { + u32 did; + u16 status; + u16 len; + u8 data[0]; +} __attribute__ ((packed)) p80211itemd_t; /* message data item for int, BOUNDEDINT, ENUMINT */ -typedef struct p80211item_uint32 -{ - u32 did; - u16 status; - u16 len; - u32 data; -} __WLAN_ATTRIB_PACK__ p80211item_uint32_t; +typedef struct p80211item_uint32 { + u32 did; + u16 status; + u16 len; + u32 data; +} __attribute__ ((packed)) p80211item_uint32_t; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr6 -{ - u32 did; - u16 status; - u16 len; - p80211pstr6_t data; -} __WLAN_ATTRIB_PACK__ p80211item_pstr6_t; +typedef struct p80211item_pstr6 { + u32 did; + u16 status; + u16 len; + p80211pstr6_t data; +} __attribute__ ((packed)) p80211item_pstr6_t; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr14 -{ - u32 did; - u16 status; - u16 len; - p80211pstr14_t data; -} __WLAN_ATTRIB_PACK__ p80211item_pstr14_t; +typedef struct p80211item_pstr14 { + u32 did; + u16 status; + u16 len; + p80211pstr14_t data; +} __attribute__ ((packed)) p80211item_pstr14_t; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr32 -{ - u32 did; - u16 status; - u16 len; - p80211pstr32_t data; -} __WLAN_ATTRIB_PACK__ p80211item_pstr32_t; +typedef struct p80211item_pstr32 { + u32 did; + u16 status; + u16 len; + p80211pstr32_t data; +} __attribute__ ((packed)) p80211item_pstr32_t; /* message data item for OCTETSTR, DISPLAYSTR */ -typedef struct p80211item_pstr255 -{ - u32 did; - u16 status; - u16 len; - p80211pstr255_t data; -} __WLAN_ATTRIB_PACK__ p80211item_pstr255_t; +typedef struct p80211item_pstr255 { + u32 did; + u16 status; + u16 len; + p80211pstr255_t data; +} __attribute__ ((packed)) p80211item_pstr255_t; /* message data item for UNK 392, namely mib items */ -typedef struct p80211item_unk392 -{ - u32 did; - u16 status; - u16 len; - u8 data[MAXLEN_MIBATTRIBUTE]; -} __WLAN_ATTRIB_PACK__ p80211item_unk392_t; +typedef struct p80211item_unk392 { + u32 did; + u16 status; + u16 len; + u8 data[MAXLEN_MIBATTRIBUTE]; +} __attribute__ ((packed)) p80211item_unk392_t; /* message data item for UNK 1025, namely p2 pdas */ -typedef struct p80211item_unk1024 -{ - u32 did; - u16 status; - u16 len; - u8 data[1024]; -} __WLAN_ATTRIB_PACK__ p80211item_unk1024_t; +typedef struct p80211item_unk1024 { + u32 did; + u16 status; + u16 len; + u8 data[1024]; +} __attribute__ ((packed)) p80211item_unk1024_t; /* message data item for UNK 4096, namely p2 download chunks */ -typedef struct p80211item_unk4096 -{ - u32 did; - u16 status; - u16 len; - u8 data[4096]; -} __WLAN_ATTRIB_PACK__ p80211item_unk4096_t; +typedef struct p80211item_unk4096 { + u32 did; + u16 status; + u16 len; + u8 data[4096]; +} __attribute__ ((packed)) p80211item_unk4096_t; struct catlistitem; @@ -534,13 +345,11 @@ struct catlistitem; /* metadata items. Some components may choose to use more, */ /* less or different metadata items. */ -typedef void (*p80211_totext_t)( struct catlistitem *, u32 did, u8* itembuf, char *textbuf); -typedef void (*p80211_fromtext_t)( struct catlistitem *, u32 did, u8* itembuf, char *textbuf); -typedef u32 (*p80211_valid_t)( struct catlistitem *, u32 did, u8* itembuf); - - -/*================================================================*/ -/* Extern Declarations */ +typedef void (*p80211_totext_t) (struct catlistitem *, u32 did, u8 *itembuf, + char *textbuf); +typedef void (*p80211_fromtext_t) (struct catlistitem *, u32 did, u8 *itembuf, + char *textbuf); +typedef u32(*p80211_valid_t) (struct catlistitem *, u32 did, u8 *itembuf); /*----------------------------------------------------------------*/ /* Enumeration Lists */ @@ -568,108 +377,4 @@ extern p80211enum_t MKENUMNAME(lnxroam_reason); extern p80211enum_t MKENUMNAME(p2preamble); -/*================================================================*/ -/* Function Declarations */ - -/*----------------------------------------------------------------*/ -/* The following declare some utility functions for use with the */ -/* p80211enum_t type. */ - -u32 p80211enum_text2int(p80211enum_t *ep, char *text); -u32 p80211enum_int2text(p80211enum_t *ep, u32 val, char *text); -void p80211_error2text(int err_code, char *err_str); - -/*----------------------------------------------------------------*/ -/* The following declare some utility functions for use with the */ -/* p80211item_t and p80211meta_t types. */ - -/*----------------------------------------------------------------*/ -/* The following declare functions that perform validation and */ -/* text to binary conversions based on the metadata for interface */ -/* and MIB data items. */ -/*----------------------------------------------------------------*/ - -/*-- DISPLAYSTR ------------------------------------------------------*/ -/* pstr ==> cstr */ -void p80211_totext_displaystr( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* cstr ==> pstr */ -void p80211_fromtext_displaystr( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* function that checks validity of a displaystr binary value */ -u32 p80211_isvalid_displaystr( struct catlistitem *metalist, u32 did, u8 *itembuf ); - -/*-- OCTETSTR --------------------------------------------------------*/ -/* pstr ==> "xx:xx:...." */ -void p80211_totext_octetstr( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* "xx:xx:...." ==> pstr */ -void p80211_fromtext_octetstr( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* function that checks validity of an octetstr binary value */ -u32 p80211_isvalid_octetstr( struct catlistitem *metalist, u32 did, u8 *itembuf ); - -/*-- int -------------------------------------------------------------*/ -/* u32 ==> %d */ -void p80211_totext_int( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* %d ==> u32 */ -void p80211_fromtext_int( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* function that checks validity of an int's binary value (always successful) */ -u32 p80211_isvalid_int( struct catlistitem *metalist, u32 did, u8 *itembuf ); - -/*-- ENUMint ---------------------------------------------------------*/ -/* u32 ==> */ -void p80211_totext_enumint( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* ==> u32 */ -void p80211_fromtext_enumint( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* function that checks validity of an enum's binary value */ -u32 p80211_isvalid_enumint( struct catlistitem *metalist, u32 did, u8 *itembuf ); - -/*-- intARRAY --------------------------------------------------------*/ -/* u32[] => %d,%d,%d,... */ -void p80211_totext_intarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* %d,%d,%d,... ==> u32[] */ -void p80211_fromtext_intarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* function that checks validity of an integer array's value */ -u32 p80211_isvalid_intarray( struct catlistitem *metalist, u32 did, u8 *itembuf ); - -/*-- BITARRAY --------------------------------------------------------*/ -/* u32 ==> %d,%d,%d,... */ -void p80211_totext_bitarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* %d,%d,%d,... ==> u32 */ -void p80211_fromtext_bitarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* function that checks validity of a bit array's value */ -u32 p80211_isvalid_bitarray( struct catlistitem *metalist, u32 did, u8 *itembuf ); - -/*-- MACARRAY --------------------------------------------------------*/ -void p80211_totext_macarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -void p80211_fromtext_macarray( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* function that checks validity of a MAC address array's value */ -u32 p80211_isvalid_macarray( struct catlistitem *metalist, u32 did, u8 *itembuf ); - -/*-- MIBATTRIUBTE ------------------------------------------------------*/ -/* ==> */ -void p80211_totext_getmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); -void p80211_totext_setmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - - -/* ==> */ -void p80211_fromtext_getmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); -void p80211_fromtext_setmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf, char *textbuf ); - -/* function that checks validity of a mibitem's binary value */ -u32 p80211_isvalid_getmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf ); -u32 p80211_isvalid_setmibattribute( struct catlistitem *metalist, u32 did, u8 *itembuf ); - #endif /* _P80211TYPES_H */ - diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index 46a2a6b3bdca..405ce89e4e6e 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -55,8 +55,7 @@ #include #include #include - -#include "wlan_compat.h" +#include // #define WEP_DEBUG @@ -72,17 +71,8 @@ /*================================================================*/ /* Local Constants */ -#define SSWAP(a,b) {u8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;} #define WEP_KEY(x) (((x) & 0xC0) >> 6) -/*================================================================*/ -/* Local Macros */ - - -/*================================================================*/ -/* Local Types */ - - /*================================================================*/ /* Local Static Definitions */ @@ -211,7 +201,7 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, u8 *i j = 0; for (i = 0; i < 256; i++) { j = (j + s[i] + key[i % keylen]) & 0xff; - SSWAP(i,j); + swap(i,j); } /* Apply the RC4 to the data, update the CRC32 */ @@ -220,7 +210,7 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, u8 *i for (k = 0; k < len; k++) { i = (i+1) & 0xff; j = (j+s[i]) & 0xff; - SSWAP(i,j); + swap(i,j); buf[k] ^= s[(s[i] + s[j]) & 0xff]; crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8); } @@ -235,7 +225,7 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, u8 *i for (k = 0; k < 4; k++) { i = (i + 1) & 0xff; j = (j+s[i]) & 0xff; - SSWAP(i,j); + swap(i,j); if ((c_crc[k] ^ s[(s[i] + s[j]) & 0xff]) != icv[k]) return -(4 | (k << 4)) ; /* ICV mismatch */ } @@ -283,7 +273,7 @@ int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 j = 0; for (i = 0; i < 256; i++) { j = (j + s[i] + key[i % keylen]) & 0xff; - SSWAP(i,j); + swap(i,j); } /* Update CRC32 then apply RC4 to the data */ @@ -293,7 +283,7 @@ int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8); i = (i+1) & 0xff; j = (j+s[i]) & 0xff; - SSWAP(i,j); + swap(i,j); dst[k] = buf[k] ^ s[(s[i] + s[j]) & 0xff]; } crc = ~crc; @@ -307,7 +297,7 @@ int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, u8 for (k = 0; k < 4; k++) { i = (i + 1) & 0xff; j = (j+s[i]) & 0xff; - SSWAP(i,j); + swap(i,j); icv[k] ^= s[(s[i] + s[j]) & 0xff]; } diff --git a/drivers/staging/wlan-ng/p80211wext.c b/drivers/staging/wlan-ng/p80211wext.c index 0d570f1f378c..96078b0ea6aa 100644 --- a/drivers/staging/wlan-ng/p80211wext.c +++ b/drivers/staging/wlan-ng/p80211wext.c @@ -51,12 +51,12 @@ #include #include #include +#include +#include /*================================================================*/ /* Project Includes */ -#include "wlan_compat.h" - #include "p80211types.h" #include "p80211hdr.h" #include "p80211conv.h" @@ -77,16 +77,14 @@ static int p80211wext_giwessid(netdevice_t *dev, static u8 p80211_mhz_to_channel(u16 mhz) { - if (mhz >= 5000) { - return ((mhz - 5000) / 5); - } + if (mhz >= 5000) + return (mhz - 5000) / 5; if (mhz == 2482) return 14; - if (mhz >= 2407) { - return ((mhz - 2407) / 5); - } + if (mhz >= 2407) + return (mhz - 2407) / 5; return 0; } @@ -100,19 +98,15 @@ static u16 p80211_channel_to_mhz(u8 ch, int dot11a) return 0; /* 5G */ - - if (dot11a) { - return (5000 + (5 * ch)); - } + if (dot11a) + return 5000 + (5 * ch); /* 2.4G */ - if (ch == 14) return 2484; - if ((ch < 14) && (ch > 0)) { - return (2407 + (5 * ch)); - } + if ((ch < 14) && (ch > 0)) + return 2407 + (5 * ch); return 0; } @@ -122,54 +116,46 @@ static const long p80211wext_channel_freq[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; + #define NUM_CHANNELS ARRAY_SIZE(p80211wext_channel_freq) -/* steal a spare bit to store the shared/opensystems state. should default to open if not set */ -#define HOSTWEP_SHAREDKEY BIT3 +/* steal a spare bit to store the shared/opensystems state. + should default to open if not set */ +#define HOSTWEP_SHAREDKEY BIT(3) - -/** function declarations =============== */ - -static int qual_as_percent(int snr ) { - if ( snr <= 0 ) - return 0; - if ( snr <= 40 ) - return snr*5/2; - return 100; +static int qual_as_percent(int snr) +{ + if (snr <= 0) + return 0; + if (snr <= 40) + return snr * 5 / 2; + return 100; } - - - static int p80211wext_dorequest(wlandevice_t *wlandev, u32 did, u32 data) { - p80211msg_dot11req_mibset_t msg; - p80211item_uint32_t mibitem; - int result; - - DBFENTER; + p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + int result; msg.msgcode = DIDmsg_dot11req_mibset; mibitem.did = did; mibitem.data = data; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); - DBFEXIT; return result; } static int p80211wext_autojoin(wlandevice_t *wlandev) { - p80211msg_lnxreq_autojoin_t msg; - struct iw_point data; + p80211msg_lnxreq_autojoin_t msg; + struct iw_point data; char ssid[IW_ESSID_MAX_SIZE]; int result; int err = 0; - DBFENTER; - /* Get ESSID */ result = p80211wext_giwessid(wlandev->netdev, NULL, &data, ssid); @@ -178,23 +164,22 @@ static int p80211wext_autojoin(wlandevice_t *wlandev) goto exit; } - if ( wlandev->hostwep & HOSTWEP_SHAREDKEY ) - msg.authtype.data = P80211ENUM_authalg_sharedkey; + if (wlandev->hostwep & HOSTWEP_SHAREDKEY) + msg.authtype.data = P80211ENUM_authalg_sharedkey; else - msg.authtype.data = P80211ENUM_authalg_opensystem; + msg.authtype.data = P80211ENUM_authalg_opensystem; msg.msgcode = DIDmsg_lnxreq_autojoin; /* Trim the last '\0' to fit the SSID format */ - if (data.length && ssid[data.length-1] == '\0') { + if (data.length && ssid[data.length - 1] == '\0') data.length = data.length - 1; - } memcpy(msg.ssid.data.data, ssid, data.length); msg.ssid.data.len = data.length; - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -203,22 +188,20 @@ static int p80211wext_autojoin(wlandevice_t *wlandev) exit: - DBFEXIT; return err; } /* called by /proc/net/wireless */ -struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev) +struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t * dev) { - p80211msg_lnxreq_commsquality_t quality; + p80211msg_lnxreq_commsquality_t quality; wlandevice_t *wlandev = dev->ml_priv; - struct iw_statistics* wstats = &wlandev->wstats; + struct iw_statistics *wstats = &wlandev->wstats; int retval; - DBFENTER; /* Check */ - if ( (wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING) ) + if ((wlandev == NULL) || (wlandev->msdstate != WLAN_MSD_RUNNING)) return NULL; /* XXX Only valid in station mode */ @@ -230,26 +213,24 @@ struct iw_statistics* p80211wext_get_wireless_stats (netdevice_t *dev) quality.dbm.status = P80211ENUM_msgitem_status_data_ok; /* send message to nsd */ - if ( wlandev->mlmerequest == NULL ) + if (wlandev->mlmerequest == NULL) return NULL; - retval = wlandev->mlmerequest(wlandev, (p80211msg_t*) &quality); + retval = wlandev->mlmerequest(wlandev, (p80211msg_t *)&quality); - wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */ - wstats->qual.level = quality.level.data; /* instant signal level */ - wstats->qual.noise = quality.noise.data; /* instant noise level */ + wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */ + wstats->qual.level = quality.level.data; /* instant signal level */ + wstats->qual.noise = quality.noise.data; /* instant noise level */ wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; wstats->discard.code = wlandev->rx.decrypt_err; wstats->discard.nwid = 0; wstats->discard.misc = 0; - wstats->discard.fragment = 0; // incomplete fragments - wstats->discard.retries = 0; // tx retries. + wstats->discard.fragment = 0; /* incomplete fragments */ + wstats->discard.retries = 0; /* tx retries. */ wstats->miss.beacon = 0; - DBFEXIT; - return wstats; } @@ -261,8 +242,6 @@ static int p80211wext_giwname(netdevice_t *dev, int result; int err = 0; - DBFENTER; - result = p80211wext_giwrate(dev, NULL, &rate, NULL); if (result) { @@ -281,7 +260,6 @@ static int p80211wext_giwname(netdevice_t *dev, break; } exit: - DBFEXIT; return err; } @@ -290,17 +268,15 @@ static int p80211wext_giwfreq(netdevice_t *dev, struct iw_freq *freq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; - DBFENTER; - msg.msgcode = DIDmsg_dot11req_mibget; mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -318,8 +294,7 @@ static int p80211wext_giwfreq(netdevice_t *dev, freq->e = 1; freq->m = p80211_channel_to_mhz(mibitem.data, 0) * 100000; - exit: - DBFEXIT; +exit: return err; } @@ -328,13 +303,11 @@ static int p80211wext_siwfreq(netdevice_t *dev, struct iw_freq *freq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; - DBFENTER; - if (!wlan_wext_write) { err = (-EOPNOTSUPP); goto exit; @@ -344,21 +317,20 @@ static int p80211wext_siwfreq(netdevice_t *dev, mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel; mibitem.status = P80211ENUM_msgitem_status_data_ok; - if ( (freq->e == 0) && (freq->m <= 1000) ) + if ((freq->e == 0) && (freq->m <= 1000)) mibitem.data = freq->m; else mibitem.data = p80211_mhz_to_channel(freq->m); memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; goto exit; } - exit: - DBFEXIT; +exit: return err; } @@ -368,8 +340,6 @@ static int p80211wext_giwmode(netdevice_t *dev, { wlandevice_t *wlandev = dev->ml_priv; - DBFENTER; - switch (wlandev->macmode) { case WLAN_MACMODE_IBSS_STA: *mode = IW_MODE_ADHOC; @@ -385,7 +355,6 @@ static int p80211wext_giwmode(netdevice_t *dev, *mode = IW_MODE_AUTO; } - DBFEXIT; return 0; } @@ -394,12 +363,10 @@ static int p80211wext_siwmode(netdevice_t *dev, __u32 *mode, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; - int result; - int err = 0; - - DBFENTER; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; if (!wlan_wext_write) { err = (-EOPNOTSUPP); @@ -428,7 +395,7 @@ static int p80211wext_siwmode(netdevice_t *dev, break; default: /* Not set yet. */ - WLAN_LOG_INFO("Operation mode: %d not support\n", *mode); + printk(KERN_INFO "Operation mode: %d not support\n", *mode); return -EOPNOTSUPP; } @@ -437,33 +404,28 @@ static int p80211wext_siwmode(netdevice_t *dev, mibitem.did = DIDmib_p2_p2Static_p2CnfPortType; mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) err = -EFAULT; - exit: - DBFEXIT; - +exit: return err; } - static int p80211wext_giwrange(netdevice_t *dev, struct iw_request_info *info, struct iw_point *data, char *extra) { - struct iw_range *range = (struct iw_range *) extra; + struct iw_range *range = (struct iw_range *)extra; int i, val; - DBFENTER; - - // for backward compatability set size & zero everything we don't understand + /* for backward compatability set size and zero everything we don't understand */ data->length = sizeof(*range); - memset(range,0,sizeof(*range)); + memset(range, 0, sizeof(*range)); range->txpower_capa = IW_TXPOW_DBM; - // XXX what about min/max_pmp, min/max_pmt, etc. + /* XXX what about min/max_pmp, min/max_pmt, etc. */ range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 13; @@ -473,18 +435,18 @@ static int p80211wext_giwrange(netdevice_t *dev, range->min_retry = 0; range->max_retry = 255; - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | //mode/freq/ssid - IW_EVENT_CAPA_MASK(SIOCGIWAP) | - IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; //encode - range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) | - IW_EVENT_CAPA_MASK(IWEVCUSTOM) ); + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | /* mode/freq/ssid */ + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; /* encode */ + range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVQUAL) | + IW_EVENT_CAPA_MASK(IWEVCUSTOM)); range->num_channels = NUM_CHANNELS; /* XXX need to filter against the regulatory domain &| active set */ val = 0; - for (i = 0; i < NUM_CHANNELS ; i++) { + for (i = 0; i < NUM_CHANNELS; i++) { range->freq[val].i = i + 1; range->freq[val].m = p80211wext_channel_freq[i] * 100000; range->freq[val].e = 1; @@ -498,7 +460,7 @@ static int p80211wext_giwrange(netdevice_t *dev, range->max_qual.level = 0; range->max_qual.noise = 0; range->sensitivity = 3; - // XXX these need to be nsd-specific! + /* XXX these need to be nsd-specific! */ range->min_rts = 0; range->max_rts = 2347; @@ -510,14 +472,13 @@ static int p80211wext_giwrange(netdevice_t *dev, range->encoding_size[0] = 5; range->encoding_size[1] = 13; - // XXX what about num_bitrates/throughput? + /* XXX what about num_bitrates/throughput? */ range->num_bitrates = 0; /* estimated max throughput */ - // XXX need to cap it if we're running at ~2Mbps.. + /* XXX need to cap it if we're running at ~2Mbps.. */ range->throughput = 5500000; - DBFEXIT; return 0; } @@ -528,12 +489,9 @@ static int p80211wext_giwap(netdevice_t *dev, wlandevice_t *wlandev = dev->ml_priv; - DBFENTER; - memcpy(ap_addr->sa_data, wlandev->bssid, WLAN_BSSID_LEN); ap_addr->sa_family = ARPHRD_ETHER; - DBFEXIT; return 0; } @@ -545,8 +503,6 @@ static int p80211wext_giwencode(netdevice_t *dev, int err = 0; int i; - DBFENTER; - i = (erq->flags & IW_ENCODE_INDEX) - 1; erq->flags = 0; @@ -576,8 +532,7 @@ static int p80211wext_giwencode(netdevice_t *dev, erq->length = wlandev->wep_keylens[i]; memcpy(key, wlandev->wep_keys[i], erq->length); - exit: - DBFEXIT; +exit: return err; } @@ -586,32 +541,33 @@ static int p80211wext_siwencode(netdevice_t *dev, struct iw_point *erq, char *key) { wlandevice_t *wlandev = dev->ml_priv; - p80211msg_dot11req_mibset_t msg; - p80211item_pstr32_t pstr; + p80211msg_dot11req_mibset_t msg; + p80211item_pstr32_t pstr; int err = 0; int result = 0; int i; - DBFENTER; if (!wlan_wext_write) { err = (-EOPNOTSUPP); goto exit; } /* Check the Key index first. */ - if((i = (erq->flags & IW_ENCODE_INDEX))) { + if ((i = (erq->flags & IW_ENCODE_INDEX))) { if ((i < 1) || (i > NUM_WEPKEYS)) { err = -EINVAL; goto exit; - } - else + } else i--; /* Set current key number only if no keys are given */ if (erq->flags & IW_ENCODE_NOKEY) { - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, i); + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + i); if (result) { err = -EFAULT; @@ -620,12 +576,12 @@ static int p80211wext_siwencode(netdevice_t *dev, } } else { - // Use defaultkey if no Key Index + /* Use defaultkey if no Key Index */ i = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; } /* Check if there is no key information in the iwconfig request */ - if((erq->flags & IW_ENCODE_NOKEY) == 0 ) { + if ((erq->flags & IW_ENCODE_NOKEY) == 0) { /*------------------------------------------------------------ * If there is WEP Key for setting, check the Key Information @@ -642,32 +598,35 @@ static int p80211wext_siwencode(netdevice_t *dev, memcpy(pstr.data.data, key, erq->length); pstr.data.len = erq->length; - switch(i) - { - case 0: - pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; + switch (i) { + case 0: + pstr.did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; - case 1: - pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; + case 1: + pstr.did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; - case 2: - pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; + case 2: + pstr.did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; - case 3: - pstr.did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; + case 3: + pstr.did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; - default: - err = -EINVAL; - goto exit; + default: + err = -EINVAL; + goto exit; } msg.msgcode = DIDmsg_dot11req_mibset; memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -679,9 +638,15 @@ static int p80211wext_siwencode(netdevice_t *dev, /* Check the PrivacyInvoked flag */ if (erq->flags & IW_ENCODE_DISABLED) { - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false); + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + P80211ENUM_truth_false); } else { - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true); + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + P80211ENUM_truth_true); } if (result) { @@ -690,17 +655,22 @@ static int p80211wext_siwencode(netdevice_t *dev, } /* The security mode may be open or restricted, and its meaning - depends on the card used. With most cards, in open mode no - authentication is used and the card may also accept non- - encrypted sessions, whereas in restricted mode only encrypted - sessions are accepted and the card will use authentication if - available. - */ + depends on the card used. With most cards, in open mode no + authentication is used and the card may also accept non- + encrypted sessions, whereas in restricted mode only encrypted + sessions are accepted and the card will use authentication if + available. + */ if (erq->flags & IW_ENCODE_RESTRICTED) { - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true); - } - else if (erq->flags & IW_ENCODE_OPEN) { - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false); + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + P80211ENUM_truth_true); + } else if (erq->flags & IW_ENCODE_OPEN) { + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + P80211ENUM_truth_false); } if (result) { @@ -708,9 +678,8 @@ static int p80211wext_siwencode(netdevice_t *dev, goto exit; } - exit: +exit: - DBFEXIT; return err; } @@ -720,8 +689,6 @@ static int p80211wext_giwessid(netdevice_t *dev, { wlandevice_t *wlandev = dev->ml_priv; - DBFENTER; - if (wlandev->ssid.len) { data->length = wlandev->ssid.len; data->flags = 1; @@ -731,12 +698,11 @@ static int p80211wext_giwessid(netdevice_t *dev, data->length++; #endif } else { - memset(essid, 0, sizeof(wlandev->ssid.data)); + memset(essid, 0, sizeof(wlandev->ssid.data)); data->length = 0; data->flags = 0; } - DBFEXIT; return 0; } @@ -745,55 +711,49 @@ static int p80211wext_siwessid(netdevice_t *dev, struct iw_point *data, char *essid) { wlandevice_t *wlandev = dev->ml_priv; - p80211msg_lnxreq_autojoin_t msg; + p80211msg_lnxreq_autojoin_t msg; int result; int err = 0; int length = data->length; - DBFENTER; - if (!wlan_wext_write) { err = (-EOPNOTSUPP); goto exit; } - - if ( wlandev->hostwep & HOSTWEP_SHAREDKEY ) - msg.authtype.data = P80211ENUM_authalg_sharedkey; + if (wlandev->hostwep & HOSTWEP_SHAREDKEY) + msg.authtype.data = P80211ENUM_authalg_sharedkey; else - msg.authtype.data = P80211ENUM_authalg_opensystem; + msg.authtype.data = P80211ENUM_authalg_opensystem; msg.msgcode = DIDmsg_lnxreq_autojoin; #if (WIRELESS_EXT < 21) - if (length) length--; + if (length) + length--; #endif /* Trim the last '\0' to fit the SSID format */ - - if (length && essid[length-1] == '\0') { - length--; - } + if (length && essid[length - 1] == '\0') + length--; memcpy(msg.ssid.data.data, essid, length); msg.ssid.data.len = length; - WLAN_LOG_DEBUG(1,"autojoin_ssid for %s \n",essid); - result = p80211req_dorequest(wlandev, (u8*)&msg); - WLAN_LOG_DEBUG(1,"autojoin_ssid %d\n",result); + pr_debug("autojoin_ssid for %s \n", essid); + result = p80211req_dorequest(wlandev, (u8 *)&msg); + pr_debug("autojoin_ssid %d\n", result); if (result) { err = -EFAULT; goto exit; } - exit: - DBFEXIT; +exit: return err; } - static int p80211wext_siwcommit(netdevice_t *dev, struct iw_request_info *info, struct iw_point *data, char *essid) @@ -801,8 +761,6 @@ static int p80211wext_siwcommit(netdevice_t *dev, wlandevice_t *wlandev = dev->ml_priv; int err = 0; - DBFENTER; - if (!wlan_wext_write) { err = (-EOPNOTSUPP); goto exit; @@ -811,28 +769,24 @@ static int p80211wext_siwcommit(netdevice_t *dev, /* Auto Join */ err = p80211wext_autojoin(wlandev); - exit: - DBFEXIT; +exit: return err; } - static int p80211wext_giwrate(netdevice_t *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; - DBFENTER; - msg.msgcode = DIDmsg_dot11req_mibget; mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -841,7 +795,7 @@ static int p80211wext_giwrate(netdevice_t *dev, memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); - rrq->fixed = 0; /* can it change? */ + rrq->fixed = 0; /* can it change? */ rrq->disabled = 0; rrq->value = 0; @@ -866,8 +820,7 @@ static int p80211wext_giwrate(netdevice_t *dev, default: err = -EINVAL; } - exit: - DBFEXIT; +exit: return err; } @@ -876,17 +829,15 @@ static int p80211wext_giwrts(netdevice_t *dev, struct iw_param *rts, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; - DBFENTER; - msg.msgcode = DIDmsg_dot11req_mibget; mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -899,24 +850,20 @@ static int p80211wext_giwrts(netdevice_t *dev, rts->disabled = (rts->value == 2347); rts->fixed = 1; - exit: - DBFEXIT; +exit: return err; } - static int p80211wext_siwrts(netdevice_t *dev, struct iw_request_info *info, struct iw_param *rts, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; - DBFENTER; - if (!wlan_wext_write) { err = (-EOPNOTSUPP); goto exit; @@ -930,15 +877,14 @@ static int p80211wext_siwrts(netdevice_t *dev, mibitem.data = rts->value; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; goto exit; } - exit: - DBFEXIT; +exit: return err; } @@ -947,17 +893,16 @@ static int p80211wext_giwfrag(netdevice_t *dev, struct iw_param *frag, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; - DBFENTER; - msg.msgcode = DIDmsg_dot11req_mibget; - mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold; + mibitem.did = + DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -970,8 +915,7 @@ static int p80211wext_giwfrag(netdevice_t *dev, frag->disabled = (frag->value == 2346); frag->fixed = 1; - exit: - DBFEXIT; +exit: return err; } @@ -980,20 +924,19 @@ static int p80211wext_siwfrag(netdevice_t *dev, struct iw_param *frag, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; - DBFENTER; - if (!wlan_wext_write) { err = (-EOPNOTSUPP); goto exit; } msg.msgcode = DIDmsg_dot11req_mibset; - mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold; + mibitem.did = + DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold; if (frag->disabled) mibitem.data = 2346; @@ -1001,15 +944,14 @@ static int p80211wext_siwfrag(netdevice_t *dev, mibitem.data = frag->value; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; goto exit; } - exit: - DBFEXIT; +exit: return err; } @@ -1026,19 +968,17 @@ static int p80211wext_giwretry(netdevice_t *dev, struct iw_param *rrq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; u16 shortretry, longretry, lifetime; - DBFENTER; - msg.msgcode = DIDmsg_dot11req_mibget; mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -1052,7 +992,7 @@ static int p80211wext_giwretry(netdevice_t *dev, mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -1063,10 +1003,11 @@ static int p80211wext_giwretry(netdevice_t *dev, longretry = mibitem.data; - mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime; + mibitem.did = + DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -1094,8 +1035,7 @@ static int p80211wext_giwretry(netdevice_t *dev, } } - exit: - DBFEXIT; +exit: return err; } @@ -1105,13 +1045,11 @@ static int p80211wext_siwretry(netdevice_t *dev, struct iw_param *rrq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; - DBFENTER; - if (!wlan_wext_write) { err = (-EOPNOTSUPP); goto exit; @@ -1125,11 +1063,12 @@ static int p80211wext_siwretry(netdevice_t *dev, msg.msgcode = DIDmsg_dot11req_mibset; if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime; - mibitem.data = rrq->value /= 1024; + mibitem.did = + DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime; + mibitem.data = rrq->value /= 1024; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -1137,11 +1076,13 @@ static int p80211wext_siwretry(netdevice_t *dev, } } else { if (rrq->flags & IW_RETRY_LONG) { - mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit; + mibitem.did = + DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit; mibitem.data = rrq->value; - memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + memcpy(&msg.mibattribute.data, &mibitem, + sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -1150,11 +1091,13 @@ static int p80211wext_siwretry(netdevice_t *dev, } if (rrq->flags & IW_RETRY_SHORT) { - mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit; + mibitem.did = + DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit; mibitem.data = rrq->value; - memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + memcpy(&msg.mibattribute.data, &mibitem, + sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -1163,46 +1106,43 @@ static int p80211wext_siwretry(netdevice_t *dev, } } - exit: - DBFEXIT; +exit: return err; } static int p80211wext_siwtxpow(netdevice_t *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) + struct iw_request_info *info, + struct iw_param *rrq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; - int result; - int err = 0; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; + int result; + int err = 0; - DBFENTER; + if (!wlan_wext_write) { + err = (-EOPNOTSUPP); + goto exit; + } - if (!wlan_wext_write) { - err = (-EOPNOTSUPP); - goto exit; - } - - msg.msgcode = DIDmsg_dot11req_mibset; - mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; + msg.msgcode = DIDmsg_dot11req_mibset; + mibitem.did = + DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; if (rrq->fixed == 0) - mibitem.data = 30; + mibitem.data = 30; else - mibitem.data = rrq->value; - memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + mibitem.data = rrq->value; + memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); + result = p80211req_dorequest(wlandev, (u8 *)&msg); - if (result) { - err = -EFAULT; - goto exit; - } + if (result) { + err = -EFAULT; + goto exit; + } - exit: - DBFEXIT; - return err; +exit: + return err; } static int p80211wext_giwtxpow(netdevice_t *dev, @@ -1210,18 +1150,17 @@ static int p80211wext_giwtxpow(netdevice_t *dev, struct iw_param *rrq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211item_uint32_t mibitem; - p80211msg_dot11req_mibset_t msg; + p80211item_uint32_t mibitem; + p80211msg_dot11req_mibset_t msg; int result; int err = 0; - DBFENTER; - msg.msgcode = DIDmsg_dot11req_mibget; - mibitem.did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; + mibitem.did = + DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem)); - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; @@ -1230,15 +1169,14 @@ static int p80211wext_giwtxpow(netdevice_t *dev, memcpy(&mibitem, &msg.mibattribute.data, sizeof(mibitem)); - // XXX handle OFF by setting disabled = 1; + /* XXX handle OFF by setting disabled = 1; */ - rrq->flags = 0; // IW_TXPOW_DBM; + rrq->flags = 0; /* IW_TXPOW_DBM; */ rrq->disabled = 0; rrq->fixed = 0; rrq->value = mibitem.data; - exit: - DBFEXIT; +exit: return err; } @@ -1247,33 +1185,32 @@ static int p80211wext_siwspy(netdevice_t *dev, struct iw_point *srq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - struct sockaddr address[IW_MAX_SPY]; - int number = srq->length; - int i; - - DBFENTER; + struct sockaddr address[IW_MAX_SPY]; + int number = srq->length; + int i; /* Copy the data from the input buffer */ - memcpy(address, extra, sizeof(struct sockaddr)*number); + memcpy(address, extra, sizeof(struct sockaddr) * number); - wlandev->spy_number = 0; + wlandev->spy_number = 0; - if (number > 0) { + if (number > 0) { - /* extract the addresses */ - for (i = 0; i < number; i++) { + /* extract the addresses */ + for (i = 0; i < number; i++) { - memcpy(wlandev->spy_address[i], address[i].sa_data, ETH_ALEN); + memcpy(wlandev->spy_address[i], address[i].sa_data, + ETH_ALEN); } - /* reset stats */ - memset(wlandev->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY); + /* reset stats */ + memset(wlandev->spy_stat, 0, + sizeof(struct iw_quality) * IW_MAX_SPY); - /* set number of addresses */ - wlandev->spy_number = number; - } + /* set number of addresses */ + wlandev->spy_number = number; + } - DBFEXIT; return 0; } @@ -1284,74 +1221,72 @@ static int p80211wext_giwspy(netdevice_t *dev, { wlandevice_t *wlandev = dev->ml_priv; - struct sockaddr address[IW_MAX_SPY]; - struct iw_quality spy_stat[IW_MAX_SPY]; - int number; - int i; + struct sockaddr address[IW_MAX_SPY]; + struct iw_quality spy_stat[IW_MAX_SPY]; + int number; + int i; - DBFENTER; + number = wlandev->spy_number; - number = wlandev->spy_number; + if (number > 0) { - if (number > 0) { - - /* populate address and spy struct's */ - for (i = 0; i < number; i++) { - memcpy(address[i].sa_data, wlandev->spy_address[i], ETH_ALEN); - address[i].sa_family = AF_UNIX; - memcpy(&spy_stat[i], &wlandev->spy_stat[i], sizeof(struct iw_quality)); - } + /* populate address and spy struct's */ + for (i = 0; i < number; i++) { + memcpy(address[i].sa_data, wlandev->spy_address[i], + ETH_ALEN); + address[i].sa_family = AF_UNIX; + memcpy(&spy_stat[i], &wlandev->spy_stat[i], + sizeof(struct iw_quality)); + } /* reset update flag */ - for (i=0; i < number; i++) - wlandev->spy_stat[i].updated = 0; - } + for (i = 0; i < number; i++) + wlandev->spy_stat[i].updated = 0; + } - /* push stuff to user space */ - srq->length = number; - memcpy(extra, address, sizeof(struct sockaddr)*number); - memcpy(extra+sizeof(struct sockaddr)*number, spy_stat, sizeof(struct iw_quality)*number); + /* push stuff to user space */ + srq->length = number; + memcpy(extra, address, sizeof(struct sockaddr) * number); + memcpy(extra + sizeof(struct sockaddr) * number, spy_stat, + sizeof(struct iw_quality) * number); - DBFEXIT; return 0; } -static int prism2_result2err (int prism2_result) +static int prism2_result2err(int prism2_result) { int err = 0; switch (prism2_result) { - case P80211ENUM_resultcode_invalid_parameters: - err = -EINVAL; - break; - case P80211ENUM_resultcode_implementation_failure: - err = -EIO; - break; - case P80211ENUM_resultcode_not_supported: - err = -EOPNOTSUPP; - break; - default: - err = 0; - break; + case P80211ENUM_resultcode_invalid_parameters: + err = -EINVAL; + break; + case P80211ENUM_resultcode_implementation_failure: + err = -EIO; + break; + case P80211ENUM_resultcode_not_supported: + err = -EOPNOTSUPP; + break; + default: + err = 0; + break; } return err; } static int p80211wext_siwscan(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *srq, char *extra) + struct iw_request_info *info, + struct iw_point *srq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211msg_dot11req_scan_t msg; + p80211msg_dot11req_scan_t msg; int result; int err = 0; int i = 0; - DBFENTER; - if (wlandev->macmode == WLAN_MACMODE_ESS_AP) { - WLAN_LOG_ERROR("Can't scan in AP mode\n"); + printk(KERN_ERR "Can't scan in AP mode\n"); err = (-EOPNOTSUPP); goto exit; } @@ -1360,36 +1295,34 @@ static int p80211wext_siwscan(netdevice_t *dev, msg.msgcode = DIDmsg_dot11req_scan; msg.bsstype.data = P80211ENUM_bsstype_any; - memset(&(msg.bssid.data), 0xFF, sizeof (p80211item_pstr6_t)); + memset(&(msg.bssid.data), 0xFF, sizeof(p80211item_pstr6_t)); msg.bssid.data.len = 6; msg.scantype.data = P80211ENUM_scantype_active; msg.probedelay.data = 0; for (i = 1; i <= 14; i++) - msg.channellist.data.data[i-1] = i; + msg.channellist.data.data[i - 1] = i; msg.channellist.data.len = 14; msg.maxchanneltime.data = 250; msg.minchanneltime.data = 200; - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) - err = prism2_result2err (msg.resultcode.data); + err = prism2_result2err(msg.resultcode.data); - exit: - DBFEXIT; +exit: return err; } - /* Helper to translate scan into Wireless Extensions scan results. * Inspired by the prism54 code, which was in turn inspired by the * airo driver code. */ -static char * -wext_translate_bss(struct iw_request_info *info, char *current_ev, - char *end_buf, p80211msg_dot11req_scan_results_t *bss) +static char *wext_translate_bss(struct iw_request_info *info, char *current_ev, + char *end_buf, + p80211msg_dot11req_scan_results_t *bss) { struct iw_event iwe; /* Temporary buffer */ @@ -1397,7 +1330,9 @@ wext_translate_bss(struct iw_request_info *info, char *current_ev, memcpy(iwe.u.ap_addr.sa_data, bss->bssid.data.data, WLAN_BSSID_LEN); iwe.u.ap_addr.sa_family = ARPHRD_ETHER; iwe.cmd = SIOCGIWAP; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); + current_ev = + iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_ADDR_LEN); /* The following entries will be displayed in the same order we give them */ @@ -1406,33 +1341,39 @@ wext_translate_bss(struct iw_request_info *info, char *current_ev, char essid[IW_ESSID_MAX_SIZE + 1]; int size; - size = wlan_min(IW_ESSID_MAX_SIZE, bss->ssid.data.len); - memset(&essid, 0, sizeof (essid)); + size = + min_t(unsigned short, IW_ESSID_MAX_SIZE, + bss->ssid.data.len); + memset(&essid, 0, sizeof(essid)); memcpy(&essid, bss->ssid.data.data, size); - WLAN_LOG_DEBUG(1, " essid size = %d\n", size); + pr_debug(" essid size = %d\n", size); iwe.u.data.length = size; iwe.u.data.flags = 1; iwe.cmd = SIOCGIWESSID; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, &essid[0]); - WLAN_LOG_DEBUG(1, " essid size OK.\n"); + current_ev = + iwe_stream_add_point(info, current_ev, end_buf, &iwe, + &essid[0]); + pr_debug(" essid size OK.\n"); } switch (bss->bsstype.data) { - case P80211ENUM_bsstype_infrastructure: - iwe.u.mode = IW_MODE_MASTER; - break; + case P80211ENUM_bsstype_infrastructure: + iwe.u.mode = IW_MODE_MASTER; + break; - case P80211ENUM_bsstype_independent: - iwe.u.mode = IW_MODE_ADHOC; - break; + case P80211ENUM_bsstype_independent: + iwe.u.mode = IW_MODE_ADHOC; + break; - default: - iwe.u.mode = 0; - break; + default: + iwe.u.mode = 0; + break; } iwe.cmd = SIOCGIWMODE; if (iwe.u.mode) - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + current_ev = + iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_UINT_LEN); /* Encryption capability */ if (bss->privacy.data == P80211ENUM_truth_true) @@ -1441,13 +1382,16 @@ wext_translate_bss(struct iw_request_info *info, char *current_ev, iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; iwe.cmd = SIOCGIWENCODE; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL); + current_ev = + iwe_stream_add_point(info, current_ev, end_buf, &iwe, NULL); /* Add frequency. (short) bss->channel is the frequency in MHz */ iwe.u.freq.m = bss->dschannel.data; iwe.u.freq.e = 0; iwe.cmd = SIOCGIWFREQ; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); + current_ev = + iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_FREQ_LEN); /* Add quality statistics */ iwe.u.qual.level = bss->signal.data; @@ -1455,26 +1399,25 @@ wext_translate_bss(struct iw_request_info *info, char *current_ev, /* do a simple SNR for quality */ iwe.u.qual.qual = qual_as_percent(bss->signal.data - bss->noise.data); iwe.cmd = IWEVQUAL; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + current_ev = + iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_QUAL_LEN); return current_ev; } - static int p80211wext_giwscan(netdevice_t *dev, - struct iw_request_info *info, - struct iw_point *srq, char *extra) + struct iw_request_info *info, + struct iw_point *srq, char *extra) { wlandevice_t *wlandev = dev->ml_priv; - p80211msg_dot11req_scan_results_t msg; + p80211msg_dot11req_scan_results_t msg; int result = 0; int err = 0; int i = 0; int scan_good = 0; char *current_ev = extra; - DBFENTER; - /* Since wireless tools doesn't really have a way of passing how * many scan results results there were back here, keep grabbing them * until we fail. @@ -1484,110 +1427,115 @@ static int p80211wext_giwscan(netdevice_t *dev, msg.msgcode = DIDmsg_dot11req_scan_results; msg.bssindex.data = i; - result = p80211req_dorequest(wlandev, (u8*)&msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if ((result != 0) || (msg.resultcode.data != P80211ENUM_resultcode_success)) { break; } - current_ev = wext_translate_bss(info, current_ev, extra + IW_SCAN_MAX_DATA, &msg); + current_ev = + wext_translate_bss(info, current_ev, + extra + IW_SCAN_MAX_DATA, &msg); scan_good = 1; i++; } while (i < IW_MAX_AP); srq->length = (current_ev - extra); - srq->flags = 0; /* todo */ + srq->flags = 0; /* todo */ if (result && !scan_good) - err = prism2_result2err (msg.resultcode.data); + err = prism2_result2err(msg.resultcode.data); - DBFEXIT; return err; } -/*****************************************************/ -//extra wireless extensions stuff to support NetworkManager (I hope) +/* extra wireless extensions stuff to support NetworkManager (I hope) */ /* SIOCSIWENCODEEXT */ static int p80211wext_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - wlandevice_t *wlandev = dev->ml_priv; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - p80211msg_dot11req_mibset_t msg; - p80211item_pstr32_t *pstr; + wlandevice_t *wlandev = dev->ml_priv; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + p80211msg_dot11req_mibset_t msg; + p80211item_pstr32_t *pstr; - int result = 0; - struct iw_point *encoding = &wrqu->encoding; - int idx = encoding->flags & IW_ENCODE_INDEX; + int result = 0; + struct iw_point *encoding = &wrqu->encoding; + int idx = encoding->flags & IW_ENCODE_INDEX; - WLAN_LOG_DEBUG(1,"set_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len); + pr_debug("set_encode_ext flags[%d] alg[%d] keylen[%d]\n", + ext->ext_flags, (int)ext->alg, (int)ext->key_len); + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* set default key ? I'm not sure if this the the correct thing to do here */ - if ( ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY ) { - // set default key ? I'm not sure if this the the correct thing to do here + if (idx) { + if (idx < 1 || idx > NUM_WEPKEYS) + return -EINVAL; + else + idx--; + } + pr_debug("setting default key (%d)\n", idx); + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + idx); + if (result) + return -EFAULT; + } - if ( idx ) { - if (idx < 1 || idx > NUM_WEPKEYS) { - return -EINVAL; - } else - idx--; - } - WLAN_LOG_DEBUG(1,"setting default key (%d)\n",idx); - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, idx); - if ( result ) - return -EFAULT; - } + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + if (!(ext->alg & IW_ENCODE_ALG_WEP)) { + pr_debug("asked to set a non wep key :("); + return -EINVAL; + } + if (idx) { + if (idx < 1 || idx > NUM_WEPKEYS) + return -EINVAL; + else + idx--; + } + pr_debug("Set WEP key (%d)\n", idx); + wlandev->wep_keylens[idx] = ext->key_len; + memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len); - - if ( ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY ) { - if (!(ext->alg & IW_ENCODE_ALG_WEP)) { - WLAN_LOG_DEBUG(1,"asked to set a non wep key :("); - return -EINVAL; - } - if (idx) { - if (idx <1 || idx > NUM_WEPKEYS) - return -EINVAL; - else - idx--; - } - WLAN_LOG_DEBUG(1,"Set WEP key (%d)\n",idx); - wlandev->wep_keylens[idx] = ext->key_len; - memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len); - - memset( &msg,0,sizeof(msg)); - pstr = (p80211item_pstr32_t*)&msg.mibattribute.data; - memcpy(pstr->data.data, ext->key,ext->key_len); - pstr->data.len = ext->key_len; - switch (idx) { - case 0: - pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; - break; - case 1: - pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; - break; - case 2: - pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; - break; - case 3: - pstr->did = DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; - break; - default: - break; - } - msg.msgcode = DIDmsg_dot11req_mibset; - result = p80211req_dorequest(wlandev,(u8*)&msg); - WLAN_LOG_DEBUG(1,"result (%d)\n",result); - } - return result; + memset(&msg, 0, sizeof(msg)); + pstr = (p80211item_pstr32_t *)&msg.mibattribute.data; + memcpy(pstr->data.data, ext->key, ext->key_len); + pstr->data.len = ext->key_len; + switch (idx) { + case 0: + pstr->did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0; + break; + case 1: + pstr->did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1; + break; + case 2: + pstr->did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2; + break; + case 3: + pstr->did = + DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3; + break; + default: + break; + } + msg.msgcode = DIDmsg_dot11req_mibset; + result = p80211req_dorequest(wlandev, (u8 *)&msg); + pr_debug("result (%d)\n", result); + } + return result; } /* SIOCGIWENCODEEXT */ static int p80211wext_get_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) - + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { wlandevice_t *wlandev = dev->ml_priv; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; @@ -1597,24 +1545,24 @@ static int p80211wext_get_encodeext(struct net_device *dev, int max_len; int idx; - DBFENTER; - - WLAN_LOG_DEBUG(1,"get_encode_ext flags[%d] alg[%d] keylen[%d]\n",ext->ext_flags,(int)ext->alg,(int)ext->key_len); - + pr_debug("get_encode_ext flags[%d] alg[%d] keylen[%d]\n", + ext->ext_flags, (int)ext->alg, (int)ext->key_len); max_len = encoding->length - sizeof(*ext); - if ( max_len <= 0) { - WLAN_LOG_DEBUG(1,"get_encodeext max_len [%d] invalid\n",max_len); + if (max_len <= 0) { + pr_debug("get_encodeext max_len [%d] invalid\n", + max_len); result = -EINVAL; goto exit; } idx = encoding->flags & IW_ENCODE_INDEX; - WLAN_LOG_DEBUG(1,"get_encode_ext index [%d]\n",idx); + pr_debug("get_encode_ext index [%d]\n", idx); if (idx) { - if (idx < 1 || idx > NUM_WEPKEYS ) { - WLAN_LOG_DEBUG(1,"get_encode_ext invalid key index [%d]\n",idx); + if (idx < 1 || idx > NUM_WEPKEYS) { + printk(KERN_DEBUG + "get_encode_ext invalid key index [%d]\n", idx); result = -EINVAL; goto exit; } @@ -1625,203 +1573,207 @@ static int p80211wext_get_encodeext(struct net_device *dev, } encoding->flags = idx + 1; - memset(ext,0,sizeof(*ext)); + memset(ext, 0, sizeof(*ext)); ext->alg = IW_ENCODE_ALG_WEP; ext->key_len = wlandev->wep_keylens[idx]; - memcpy( ext->key, wlandev->wep_keys[idx] , ext->key_len ); + memcpy(ext->key, wlandev->wep_keys[idx], ext->key_len); encoding->flags |= IW_ENCODE_ENABLED; exit: - DBFEXIT; + return result; +} + +/* SIOCSIWAUTH */ +static int p80211_wext_set_iwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wlandevice_t *wlandev = dev->ml_priv; + struct iw_param *param = &wrqu->param; + int result = 0; + + pr_debug("set_iwauth flags[%d]\n", + (int)param->flags & IW_AUTH_INDEX); + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + pr_debug("drop_unencrypted %d\n", param->value); + if (param->value) + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + P80211ENUM_truth_true); + else + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + P80211ENUM_truth_false); + break; + + case IW_AUTH_PRIVACY_INVOKED: + pr_debug("privacy invoked %d\n", param->value); + if (param->value) + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + P80211ENUM_truth_true); + else + result = + p80211wext_dorequest(wlandev, + DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + P80211ENUM_truth_false); + + break; + + case IW_AUTH_80211_AUTH_ALG: + if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { + pr_debug("set open_system\n"); + wlandev->hostwep &= ~HOSTWEP_SHAREDKEY; + } else if (param->value & IW_AUTH_ALG_SHARED_KEY) { + pr_debug("set shared key\n"); + wlandev->hostwep |= HOSTWEP_SHAREDKEY; + } else { + /* don't know what to do know */ + pr_debug("unknown AUTH_ALG (%d)\n", + param->value); + result = -EINVAL; + } + break; + + default: + break; + } return result; } - /* SIOCSIWAUTH */ -static int p80211_wext_set_iwauth (struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) +static int p80211_wext_get_iwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { - wlandevice_t *wlandev = dev->ml_priv; - struct iw_param *param = &wrqu->param; - int result =0; + wlandevice_t *wlandev = dev->ml_priv; + struct iw_param *param = &wrqu->param; + int result = 0; - WLAN_LOG_DEBUG(1,"set_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX ); + pr_debug("get_iwauth flags[%d]\n", + (int)param->flags & IW_AUTH_INDEX); - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_DROP_UNENCRYPTED: - WLAN_LOG_DEBUG(1,"drop_unencrypted %d\n",param->value); - if (param->value) - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_true); - else - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, P80211ENUM_truth_false); - break; + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_DROP_UNENCRYPTED: + param->value = + wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED ? 1 : 0; + break; - case IW_AUTH_PRIVACY_INVOKED: - WLAN_LOG_DEBUG(1,"privacy invoked %d\n",param->value); - if ( param->value) - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true); - else - result = p80211wext_dorequest(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false); + case IW_AUTH_PRIVACY_INVOKED: + param->value = + wlandev->hostwep & HOSTWEP_PRIVACYINVOKED ? 1 : 0; + break; - break; + case IW_AUTH_80211_AUTH_ALG: + param->value = + wlandev-> + hostwep & HOSTWEP_SHAREDKEY ? IW_AUTH_ALG_SHARED_KEY : + IW_AUTH_ALG_OPEN_SYSTEM; + break; - case IW_AUTH_80211_AUTH_ALG: - if ( param->value & IW_AUTH_ALG_OPEN_SYSTEM ) { - WLAN_LOG_DEBUG(1,"set open_system\n"); - wlandev->hostwep &= ~HOSTWEP_SHAREDKEY; - } else if ( param->value & IW_AUTH_ALG_SHARED_KEY) { - WLAN_LOG_DEBUG(1,"set shared key\n"); - wlandev->hostwep |= HOSTWEP_SHAREDKEY; - } else { - /* don't know what to do know :( */ - WLAN_LOG_DEBUG(1,"unknown AUTH_ALG (%d)\n",param->value); - result = -EINVAL; - } - break; + default: + break; + } - default: - break; - } - - - - return result; + return result; } -/* SIOCSIWAUTH */ -static int p80211_wext_get_iwauth (struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wlandevice_t *wlandev = dev->ml_priv; - struct iw_param *param = &wrqu->param; - int result =0; - - WLAN_LOG_DEBUG(1,"get_iwauth flags[%d]\n",(int)param->flags & IW_AUTH_INDEX ); - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_DROP_UNENCRYPTED: - param->value = wlandev->hostwep & HOSTWEP_EXCLUDEUNENCRYPTED?1:0; - break; - - case IW_AUTH_PRIVACY_INVOKED: - param->value = wlandev->hostwep & HOSTWEP_PRIVACYINVOKED?1:0; - break; - - case IW_AUTH_80211_AUTH_ALG: - param->value = wlandev->hostwep & HOSTWEP_SHAREDKEY?IW_AUTH_ALG_SHARED_KEY:IW_AUTH_ALG_OPEN_SYSTEM; - break; - - - default: - break; - } - - - - return result; -} - -static iw_handler p80211wext_handlers[] = { - (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */ - (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */ - (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */ - (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */ - (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */ - (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */ - (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */ - (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */ - (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCSIWAP */ - (iw_handler) p80211wext_giwap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */ - (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */ - (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */ - (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCSIWRATE */ - (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */ - (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */ - (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */ - (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */ - (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */ - (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */ - (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */ - (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */ - (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */ - (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */ - (iw_handler) NULL, /* SIOCSIWPOWER */ - (iw_handler) NULL, /* SIOCGIWPOWER */ +static iw_handler p80211wext_handlers[] = { + (iw_handler) p80211wext_siwcommit, /* SIOCSIWCOMMIT */ + (iw_handler) p80211wext_giwname, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) p80211wext_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) p80211wext_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) p80211wext_siwmode, /* SIOCSIWMODE */ + (iw_handler) p80211wext_giwmode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* not used *//* SIOCSIWRANGE */ + (iw_handler) p80211wext_giwrange, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* not used *//* SIOCSIWPRIV */ + (iw_handler) NULL, /* kernel code *//* SIOCGIWPRIV */ + (iw_handler) NULL, /* not used *//* SIOCSIWSTATS */ + (iw_handler) NULL, /* kernel code *//* SIOCGIWSTATS */ + (iw_handler) p80211wext_siwspy, /* SIOCSIWSPY */ + (iw_handler) p80211wext_giwspy, /* SIOCGIWSPY */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWAP */ + (iw_handler) p80211wext_giwap, /* SIOCGIWAP */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCGIWAPLIST */ + (iw_handler) p80211wext_siwscan, /* SIOCSIWSCAN */ + (iw_handler) p80211wext_giwscan, /* SIOCGIWSCAN */ + (iw_handler) p80211wext_siwessid, /* SIOCSIWESSID */ + (iw_handler) p80211wext_giwessid, /* SIOCGIWESSID */ + (iw_handler) NULL, /* SIOCSIWNICKN */ + (iw_handler) p80211wext_giwessid, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWRATE */ + (iw_handler) p80211wext_giwrate, /* SIOCGIWRATE */ + (iw_handler) p80211wext_siwrts, /* SIOCSIWRTS */ + (iw_handler) p80211wext_giwrts, /* SIOCGIWRTS */ + (iw_handler) p80211wext_siwfrag, /* SIOCSIWFRAG */ + (iw_handler) p80211wext_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) p80211wext_siwtxpow, /* SIOCSIWTXPOW */ + (iw_handler) p80211wext_giwtxpow, /* SIOCGIWTXPOW */ + (iw_handler) p80211wext_siwretry, /* SIOCSIWRETRY */ + (iw_handler) p80211wext_giwretry, /* SIOCGIWRETRY */ + (iw_handler) p80211wext_siwencode, /* SIOCSIWENCODE */ + (iw_handler) p80211wext_giwencode, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) NULL, /* SIOCGIWPOWER */ /* WPA operations */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */ - (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */ - (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */ - (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCSIWGENIE set generic IE */ + (iw_handler) NULL, /* SIOCGIWGENIE get generic IE */ + (iw_handler) p80211_wext_set_iwauth, /* SIOCSIWAUTH set authentication mode params */ + (iw_handler) p80211_wext_get_iwauth, /* SIOCGIWAUTH get authentication mode params */ - (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */ - (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */ - (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */ + (iw_handler) p80211wext_set_encodeext, /* SIOCSIWENCODEEXT set encoding token & mode */ + (iw_handler) p80211wext_get_encodeext, /* SIOCGIWENCODEEXT get encoding token & mode */ + (iw_handler) NULL, /* SIOCSIWPMKSA PMKSA cache operation */ }; struct iw_handler_def p80211wext_handler_def = { .num_standard = ARRAY_SIZE(p80211wext_handlers), .num_private = 0, .num_private_args = 0, - .standard = p80211wext_handlers, + .standard = p80211wext_handlers, .private = NULL, .private_args = NULL, .get_wireless_stats = p80211wext_get_wireless_stats }; - int p80211wext_event_associated(wlandevice_t *wlandev, int assoc) { - union iwreq_data data; + union iwreq_data data; - DBFENTER; + /* Send the association state first */ + data.ap_addr.sa_family = ARPHRD_ETHER; + if (assoc) + memcpy(data.ap_addr.sa_data, wlandev->bssid, ETH_ALEN); + else + memset(data.ap_addr.sa_data, 0, ETH_ALEN); - /* Send the association state first */ - data.ap_addr.sa_family = ARPHRD_ETHER; - if (assoc) { - memcpy(data.ap_addr.sa_data, wlandev->bssid, WLAN_ADDR_LEN); - } else { - memset(data.ap_addr.sa_data, 0, WLAN_ADDR_LEN); - } + if (wlan_wext_write) + wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL); - if (wlan_wext_write) - wireless_send_event(wlandev->netdev, SIOCGIWAP, &data, NULL); + if (!assoc) + goto done; - if (!assoc) goto done; + /* XXX send association data, like IEs, etc etc. */ - // XXX send association data, like IEs, etc etc. - - done: - DBFEXIT; - return 0; +done: + return 0; } - - - - diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index f1727ba6ec6f..e7a7939b4280 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -57,11 +57,6 @@ * -------------------------------------------------------------------- */ -/*================================================================*/ -/* System Includes */ -#define WLAN_DBVAR prism2_debug - - #include #include #include @@ -76,8 +71,7 @@ #include #include #include - -#include "wlan_compat.h" +#include /*================================================================*/ /* Project Includes */ @@ -94,10 +88,10 @@ #include "prism2mgmt.h" /* Converts 802.11 format rate specifications to prism2 */ -#define p80211rate_to_p2bit(n) ((((n)&~BIT7) == 2) ? BIT0 : \ - (((n)&~BIT7) == 4) ? BIT1 : \ - (((n)&~BIT7) == 11) ? BIT2 : \ - (((n)&~BIT7) == 22) ? BIT3 : 0) +#define p80211rate_to_p2bit(n) ((((n)&~BIT(7)) == 2) ? BIT(0) : \ + (((n)&~BIT(7)) == 4) ? BIT(1) : \ + (((n)&~BIT(7)) == 11) ? BIT(2) : \ + (((n)&~BIT(7)) == 22) ? BIT(3) : 0) /*---------------------------------------------------------------- * prism2mgmt_scan @@ -125,183 +119,188 @@ ----------------------------------------------------------------*/ int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) { - int result = 0; - hfa384x_t *hw = wlandev->priv; - p80211msg_dot11req_scan_t *msg = msgp; - u16 roamingmode, word; - int i, timeout; - int istmpenable = 0; + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_scan_t *msg = msgp; + u16 roamingmode, word; + int i, timeout; + int istmpenable = 0; - hfa384x_HostScanRequest_data_t scanreq; + hfa384x_HostScanRequest_data_t scanreq; - DBFENTER; - - /* gatekeeper check */ - if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, - hw->ident_sta_fw.minor, - hw->ident_sta_fw.variant) < - HFA384x_FIRMWARE_VERSION(1,3,2)) { - WLAN_LOG_ERROR("HostScan not supported with current firmware (<1.3.2).\n"); - result = 1; - msg->resultcode.data = P80211ENUM_resultcode_not_supported; + /* gatekeeper check */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) < + HFA384x_FIRMWARE_VERSION(1, 3, 2)) { + printk(KERN_ERR + "HostScan not supported with current firmware (<1.3.2).\n"); + result = 1; + msg->resultcode.data = P80211ENUM_resultcode_not_supported; goto exit; } - memset(&scanreq, 0, sizeof(scanreq)); + memset(&scanreq, 0, sizeof(scanreq)); - /* save current roaming mode */ - result = hfa384x_drvr_getconfig16(hw, - HFA384x_RID_CNFROAMINGMODE, &roamingmode); - if ( result ) { - WLAN_LOG_ERROR("getconfig(ROAMMODE) failed. result=%d\n", - result); - msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; - goto exit; - } + /* save current roaming mode */ + result = hfa384x_drvr_getconfig16(hw, + HFA384x_RID_CNFROAMINGMODE, + &roamingmode); + if (result) { + printk(KERN_ERR "getconfig(ROAMMODE) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } - /* drop into mode 3 for the scan */ - result = hfa384x_drvr_setconfig16(hw, - HFA384x_RID_CNFROAMINGMODE, - HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); - if ( result ) { - WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", - result); - msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; - goto exit; - } + /* drop into mode 3 for the scan */ + result = hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFROAMINGMODE, + HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); + if (result) { + printk(KERN_ERR "setconfig(ROAMINGMODE) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } - /* active or passive? */ - if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, - hw->ident_sta_fw.minor, - hw->ident_sta_fw.variant) > - HFA384x_FIRMWARE_VERSION(1,5,0)) { - if (msg->scantype.data != P80211ENUM_scantype_active) { - word = host2hfa384x_16(msg->maxchanneltime.data); - } else { - word = 0; - } - result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, word); - if ( result ) { - WLAN_LOG_WARNING("Passive scan not supported with " - "current firmware. (<1.5.1)\n"); - } - } + /* active or passive? */ + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) > + HFA384x_FIRMWARE_VERSION(1, 5, 0)) { + if (msg->scantype.data != P80211ENUM_scantype_active) + word = cpu_to_le16(msg->maxchanneltime.data); + else + word = 0; + + result = + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, + word); + if (result) { + printk(KERN_WARNING "Passive scan not supported with " + "current firmware. (<1.5.1)\n"); + } + } /* set up the txrate to be 2MBPS. Should be fastest basicrate... */ word = HFA384x_RATEBIT_2; - scanreq.txRate = host2hfa384x_16(word); + scanreq.txRate = cpu_to_le16(word); - /* set up the channel list */ - word = 0; - for (i = 0; i < msg->channellist.data.len; i++) { - u8 channel = msg->channellist.data.data[i]; - if (channel > 14) continue; - /* channel 1 is BIT0 ... channel 14 is BIT13 */ - word |= (1 << (channel-1)); - } - scanreq.channelList = host2hfa384x_16(word); + /* set up the channel list */ + word = 0; + for (i = 0; i < msg->channellist.data.len; i++) { + u8 channel = msg->channellist.data.data[i]; + if (channel > 14) + continue; + /* channel 1 is BIT 0 ... channel 14 is BIT 13 */ + word |= (1 << (channel - 1)); + } + scanreq.channelList = cpu_to_le16(word); - /* set up the ssid, if present. */ - scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len); - memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len); + /* set up the ssid, if present. */ + scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len); + memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len); /* Enable the MAC port if it's not already enabled */ result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word); - if ( result ) { - WLAN_LOG_ERROR("getconfig(PORTSTATUS) failed. " - "result=%d\n", result); + if (result) { + printk(KERN_ERR "getconfig(PORTSTATUS) failed. " + "result=%d\n", result); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; goto exit; } if (word == HFA384x_PORTSTATUS_DISABLED) { u16 wordbuf[17]; result = hfa384x_drvr_setconfig16(hw, - HFA384x_RID_CNFROAMINGMODE, - HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); - if ( result ) { - WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", result); + HFA384x_RID_CNFROAMINGMODE, + HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); + if (result) { + printk(KERN_ERR + "setconfig(ROAMINGMODE) failed. result=%d\n", + result); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; goto exit; } /* Construct a bogus SSID and assign it to OwnSSID and * DesiredSSID */ - wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN); + wordbuf[0] = cpu_to_le16(WLAN_SSID_MAXLEN); get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN); - result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID, - wordbuf, HFA384x_RID_CNFOWNSSID_LEN); - if ( result ) { - WLAN_LOG_ERROR("Failed to set OwnSSID.\n"); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID, + wordbuf, + HFA384x_RID_CNFOWNSSID_LEN); + if (result) { + printk(KERN_ERR "Failed to set OwnSSID.\n"); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; goto exit; } - result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID, - wordbuf, HFA384x_RID_CNFDESIREDSSID_LEN); - if ( result ) { - WLAN_LOG_ERROR("Failed to set DesiredSSID.\n"); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, + wordbuf, + HFA384x_RID_CNFDESIREDSSID_LEN); + if (result) { + printk(KERN_ERR "Failed to set DesiredSSID.\n"); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; goto exit; } /* bsstype */ result = hfa384x_drvr_setconfig16(hw, - HFA384x_RID_CNFPORTTYPE, - HFA384x_PORTTYPE_IBSS); - if ( result ) { - WLAN_LOG_ERROR("Failed to set CNFPORTTYPE.\n"); + HFA384x_RID_CNFPORTTYPE, + HFA384x_PORTTYPE_IBSS); + if (result) { + printk(KERN_ERR "Failed to set CNFPORTTYPE.\n"); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; goto exit; } /* ibss options */ result = hfa384x_drvr_setconfig16(hw, - HFA384x_RID_CREATEIBSS, - HFA384x_CREATEIBSS_JOINCREATEIBSS); - if ( result ) { - WLAN_LOG_ERROR("Failed to set CREATEIBSS.\n"); + HFA384x_RID_CREATEIBSS, + HFA384x_CREATEIBSS_JOINCREATEIBSS); + if (result) { + printk(KERN_ERR "Failed to set CREATEIBSS.\n"); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; goto exit; } result = hfa384x_drvr_enable(hw, 0); - if ( result ) { - WLAN_LOG_ERROR("drvr_enable(0) failed. " - "result=%d\n", result); + if (result) { + printk(KERN_ERR "drvr_enable(0) failed. " + "result=%d\n", result); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; goto exit; } istmpenable = 1; } - /* Figure out our timeout first Kus, then HZ */ - timeout = msg->channellist.data.len * msg->maxchanneltime.data; - timeout = (timeout * HZ)/1000; + /* Figure out our timeout first Kus, then HZ */ + timeout = msg->channellist.data.len * msg->maxchanneltime.data; + timeout = (timeout * HZ) / 1000; - /* Issue the scan request */ - hw->scanflag = 0; + /* Issue the scan request */ + hw->scanflag = 0; - WLAN_HEX_DUMP(5,"hscanreq", &scanreq, sizeof(scanreq)); + result = hfa384x_drvr_setconfig(hw, + HFA384x_RID_HOSTSCAN, &scanreq, + sizeof(hfa384x_HostScanRequest_data_t)); + if (result) { + printk(KERN_ERR "setconfig(SCANREQUEST) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } - result = hfa384x_drvr_setconfig( hw, - HFA384x_RID_HOSTSCAN, &scanreq, - sizeof(hfa384x_HostScanRequest_data_t)); - if ( result ) { - WLAN_LOG_ERROR("setconfig(SCANREQUEST) failed. result=%d\n", - result); - msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; - goto exit; - } - - /* sleep until info frame arrives */ - wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout); + /* sleep until info frame arrives */ + wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout); msg->numbss.status = P80211ENUM_msgitem_status_data_ok; if (hw->scanflag == -1) @@ -309,16 +308,16 @@ int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) msg->numbss.data = hw->scanflag; - hw->scanflag = 0; + hw->scanflag = 0; /* Disable port if we temporarily enabled it. */ if (istmpenable) { result = hfa384x_drvr_disable(hw, 0); - if ( result ) { - WLAN_LOG_ERROR("drvr_disable(0) failed. " - "result=%d\n", result); + if (result) { + printk(KERN_ERR "drvr_disable(0) failed. " + "result=%d\n", result); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; goto exit; } } @@ -326,25 +325,23 @@ int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) /* restore original roaming mode */ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, roamingmode); - if ( result ) { - WLAN_LOG_ERROR("setconfig(ROAMMODE) failed. result=%d\n", - result); - msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; - goto exit; - } + if (result) { + printk(KERN_ERR "setconfig(ROAMMODE) failed. result=%d\n", + result); + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; + goto exit; + } - result = 0; - msg->resultcode.data = P80211ENUM_resultcode_success; + result = 0; + msg->resultcode.data = P80211ENUM_resultcode_success; - exit: +exit: msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; - DBFEXIT; return result; } - /*---------------------------------------------------------------- * prism2mgmt_scan_results * @@ -367,32 +364,32 @@ int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) { - int result = 0; - p80211msg_dot11req_scan_results_t *req; - hfa384x_t *hw = wlandev->priv; + int result = 0; + p80211msg_dot11req_scan_results_t *req; + hfa384x_t *hw = wlandev->priv; hfa384x_HScanResultSub_t *item = NULL; int count; - DBFENTER; - - req = (p80211msg_dot11req_scan_results_t *) msgp; + req = (p80211msg_dot11req_scan_results_t *) msgp; req->resultcode.status = P80211ENUM_msgitem_status_data_ok; - if (! hw->scanresults) { - WLAN_LOG_ERROR("dot11req_scan_results can only be used after a successful dot11req_scan.\n"); + if (!hw->scanresults) { + printk(KERN_ERR + "dot11req_scan_results can only be used after a successful dot11req_scan.\n"); result = 2; req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; goto exit; } - count = (hw->scanresults->framelen - 3) / 32; - if (count > 32) count = 32; + count = (hw->scanresults->framelen - 3) / 32; + if (count > 32) + count = 32; if (req->bssindex.data >= count) { - WLAN_LOG_DEBUG(0, "requested index (%d) out of range (%d)\n", - req->bssindex.data, count); + pr_debug("requested index (%d) out of range (%d)\n", + req->bssindex.data, count); result = 2; req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; goto exit; @@ -402,8 +399,8 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* signal and noise */ req->signal.status = P80211ENUM_msgitem_status_data_ok; req->noise.status = P80211ENUM_msgitem_status_data_ok; - req->signal.data = hfa384x2host_16(item->sl); - req->noise.data = hfa384x2host_16(item->anl); + req->signal.data = le16_to_cpu(item->sl); + req->noise.data = le16_to_cpu(item->anl); /* BSSID */ req->bssid.status = P80211ENUM_msgitem_status_data_ok; @@ -412,13 +409,13 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* SSID */ req->ssid.status = P80211ENUM_msgitem_status_data_ok; - req->ssid.data.len = hfa384x2host_16(item->ssid.len); + req->ssid.data.len = le16_to_cpu(item->ssid.len); memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); /* supported rates */ - for (count = 0; count < 10 ; count++) - if (item->supprates[count] == 0) - break; + for (count = 0; count < 10; count++) + if (item->supprates[count] == 0) + break; #define REQBASICRATE(N) \ if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \ @@ -452,7 +449,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* beacon period */ req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok; - req->beaconperiod.data = hfa384x2host_16(item->bcnint); + req->beaconperiod.data = le16_to_cpu(item->bcnint); /* timestamps */ req->timestamp.status = P80211ENUM_msgitem_status_data_ok; @@ -462,14 +459,14 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* atim window */ req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok; - req->ibssatimwindow.data = hfa384x2host_16(item->atim); + req->ibssatimwindow.data = le16_to_cpu(item->atim); /* Channel */ req->dschannel.status = P80211ENUM_msgitem_status_data_ok; - req->dschannel.data = hfa384x2host_16(item->chid); + req->dschannel.data = le16_to_cpu(item->chid); /* capinfo bits */ - count = hfa384x2host_16(item->capinfo); + count = le16_to_cpu(item->capinfo); /* privacy flag */ req->privacy.status = P80211ENUM_msgitem_status_data_ok; @@ -484,25 +481,14 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count); /* bsstype */ - req->bsstype.status = P80211ENUM_msgitem_status_data_ok; + req->bsstype.status = P80211ENUM_msgitem_status_data_ok; req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ? - P80211ENUM_bsstype_infrastructure : - P80211ENUM_bsstype_independent; - - // item->proberesp_rate -/* - req->fhdwelltime - req->fhhopset - req->fhhoppattern - req->fhhopindex - req->cfpdurremaining -*/ + P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent; result = 0; req->resultcode.data = P80211ENUM_resultcode_success; - exit: - DBFEXIT; +exit: return result; } @@ -527,15 +513,14 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) { - int result = 0; - hfa384x_t *hw = wlandev->priv; - p80211msg_dot11req_start_t *msg = msgp; + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_dot11req_start_t *msg = msgp; - p80211pstrd_t *pstr; - u8 bytebuf[80]; - hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf; - u16 word; - DBFENTER; + p80211pstrd_t *pstr; + u8 bytebuf[80]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf; + u16 word; wlandev->macmode = WLAN_MACMODE_NONE; @@ -547,7 +532,7 @@ int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, hw->ident_sta_fw.minor, hw->ident_sta_fw.variant) < - HFA384x_FIRMWARE_VERSION(0,8,3)) { + HFA384x_FIRMWARE_VERSION(0, 8, 3)) { /* Ad-Hoc not quite supported on Prism2 */ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; msg->resultcode.data = P80211ENUM_resultcode_not_supported; @@ -559,18 +544,19 @@ int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) /*** STATION ***/ /* Set the REQUIRED config items */ /* SSID */ - pstr = (p80211pstrd_t*)&(msg->ssid.data); + pstr = (p80211pstrd_t *)&(msg->ssid.data); prism2mgmt_pstr2bytestr(p2bytestr, pstr); - result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID, - bytebuf, HFA384x_RID_CNFOWNSSID_LEN); - if ( result ) { - WLAN_LOG_ERROR("Failed to set CnfOwnSSID\n"); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID, + bytebuf, HFA384x_RID_CNFOWNSSID_LEN); + if (result) { + printk(KERN_ERR "Failed to set CnfOwnSSID\n"); goto failed; } - result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID, - bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN); - if ( result ) { - WLAN_LOG_ERROR("Failed to set CnfDesiredSSID\n"); + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, + bytebuf, + HFA384x_RID_CNFDESIREDSSID_LEN); + if (result) { + printk(KERN_ERR "Failed to set CnfDesiredSSID\n"); goto failed; } @@ -581,84 +567,84 @@ int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) /* beacon period */ word = msg->beaconperiod.data; result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word); - if ( result ) { - WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word); + if (result) { + printk(KERN_ERR "Failed to set beacon period=%d.\n", word); goto failed; } /* dschannel */ word = msg->dschannel.data; result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word); - if ( result ) { - WLAN_LOG_ERROR("Failed to set channel=%d.\n", word); + if (result) { + printk(KERN_ERR "Failed to set channel=%d.\n", word); goto failed; } /* Basic rates */ word = p80211rate_to_p2bit(msg->basicrate1.data); - if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) { + if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->basicrate2.data); - } - if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->basicrate3.data); - } - if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->basicrate4.data); - } - if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->basicrate5.data); - } - if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->basicrate6.data); - } - if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->basicrate7.data); - } - if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->basicrate8.data); - } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word); - if ( result ) { - WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word); + if (result) { + printk(KERN_ERR "Failed to set basicrates=%d.\n", word); goto failed; } /* Operational rates (supprates and txratecontrol) */ word = p80211rate_to_p2bit(msg->operationalrate1.data); - if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) { + if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->operationalrate2.data); - } - if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->operationalrate3.data); - } - if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->operationalrate4.data); - } - if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->operationalrate5.data); - } - if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->operationalrate6.data); - } - if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->operationalrate7.data); - } - if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) { + + if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok) word |= p80211rate_to_p2bit(msg->operationalrate8.data); - } + result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word); - if ( result ) { - WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word); + if (result) { + printk(KERN_ERR "Failed to set supprates=%d.\n", word); goto failed; } result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word); - if ( result ) { - WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word); + if (result) { + printk(KERN_ERR "Failed to set txrates=%d.\n", word); goto failed; } /* Set the macmode so the frame setup code knows what to do */ - if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) { + if (msg->bsstype.data == P80211ENUM_bsstype_independent) { wlandev->macmode = WLAN_MACMODE_IBSS_STA; /* lets extend the data length a bit */ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304); @@ -666,8 +652,8 @@ int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) /* Enable the Port */ result = hfa384x_drvr_enable(hw, 0); - if ( result ) { - WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result); + if (result) { + printk(KERN_ERR "Enable macport failed, result=%d.\n", result); goto failed; } @@ -675,13 +661,12 @@ int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) goto done; failed: - WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result); + pr_debug("Failed to set a config option, result=%d\n", result); msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; done: result = 0; - DBFEXIT; return result; } @@ -705,40 +690,35 @@ done: ----------------------------------------------------------------*/ int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; - p80211msg_p2req_readpda_t *msg = msgp; - int result; - DBFENTER; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_readpda_t *msg = msgp; + int result; /* We only support collecting the PDA when in the FWLOAD * state. */ if (wlandev->msdstate != WLAN_MSD_FWLOAD) { - WLAN_LOG_ERROR( - "PDA may only be read " - "in the fwload state.\n"); + printk(KERN_ERR + "PDA may only be read " "in the fwload state.\n"); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; } else { /* Call drvr_readpda(), it handles the auxport enable * and validating the returned PDA. */ - result = hfa384x_drvr_readpda( - hw, - msg->pda.data, - HFA384x_PDA_LEN_MAX); + result = hfa384x_drvr_readpda(hw, + msg->pda.data, + HFA384x_PDA_LEN_MAX); if (result) { - WLAN_LOG_ERROR( - "hfa384x_drvr_readpda() failed, " - "result=%d\n", - result); + printk(KERN_ERR + "hfa384x_drvr_readpda() failed, " + "result=%d\n", result); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; msg->resultcode.status = - P80211ENUM_msgitem_status_data_ok; - DBFEXIT; + P80211ENUM_msgitem_status_data_ok; return 0; } msg->pda.status = P80211ENUM_msgitem_status_data_ok; @@ -746,7 +726,6 @@ int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; } - DBFEXIT; return 0; } @@ -777,30 +756,29 @@ int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; - p80211msg_p2req_ramdl_state_t *msg = msgp; - DBFENTER; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_ramdl_state_t *msg = msgp; if (wlandev->msdstate != WLAN_MSD_FWLOAD) { - WLAN_LOG_ERROR( - "ramdl_state(): may only be called " - "in the fwload state.\n"); + printk(KERN_ERR + "ramdl_state(): may only be called " + "in the fwload state.\n"); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; - DBFEXIT; return 0; } /* - ** Note: Interrupts are locked out if this is an AP and are NOT - ** locked out if this is a station. - */ + ** Note: Interrupts are locked out if this is an AP and are NOT + ** locked out if this is a station. + */ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; - if ( msg->enable.data == P80211ENUM_truth_true ) { - if ( hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data) ) { - msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + if (msg->enable.data == P80211ENUM_truth_true) { + if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) { + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; } else { msg->resultcode.data = P80211ENUM_resultcode_success; } @@ -809,11 +787,9 @@ int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) msg->resultcode.data = P80211ENUM_resultcode_success; } - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * prism2mgmt_ramdl_write * @@ -836,45 +812,41 @@ int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; - p80211msg_p2req_ramdl_write_t *msg = msgp; - u32 addr; - u32 len; - u8 *buf; - DBFENTER; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_ramdl_write_t *msg = msgp; + u32 addr; + u32 len; + u8 *buf; if (wlandev->msdstate != WLAN_MSD_FWLOAD) { - WLAN_LOG_ERROR( - "ramdl_write(): may only be called " - "in the fwload state.\n"); + printk(KERN_ERR + "ramdl_write(): may only be called " + "in the fwload state.\n"); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; - DBFEXIT; return 0; } msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; /* first validate the length */ - if ( msg->len.data > sizeof(msg->data.data) ) { - msg->resultcode.status = P80211ENUM_resultcode_invalid_parameters; + if (msg->len.data > sizeof(msg->data.data)) { + msg->resultcode.status = + P80211ENUM_resultcode_invalid_parameters; return 0; } /* call the hfa384x function to do the write */ addr = msg->addr.data; len = msg->len.data; buf = msg->data.data; - if ( hfa384x_drvr_ramdl_write(hw, addr, buf, len) ) { + if (hfa384x_drvr_ramdl_write(hw, addr, buf, len)) msg->resultcode.data = P80211ENUM_resultcode_refused; - } msg->resultcode.data = P80211ENUM_resultcode_success; - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * prism2mgmt_flashdl_state * @@ -902,31 +874,30 @@ int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) { - int result = 0; - hfa384x_t *hw = wlandev->priv; - p80211msg_p2req_flashdl_state_t *msg = msgp; - DBFENTER; + int result = 0; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_flashdl_state_t *msg = msgp; if (wlandev->msdstate != WLAN_MSD_FWLOAD) { - WLAN_LOG_ERROR( - "flashdl_state(): may only be called " - "in the fwload state.\n"); + printk(KERN_ERR + "flashdl_state(): may only be called " + "in the fwload state.\n"); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; - DBFEXIT; return 0; } /* - ** Note: Interrupts are locked out if this is an AP and are NOT - ** locked out if this is a station. - */ + ** Note: Interrupts are locked out if this is an AP and are NOT + ** locked out if this is a station. + */ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; - if ( msg->enable.data == P80211ENUM_truth_true ) { - if ( hfa384x_drvr_flashdl_enable(hw) ) { - msg->resultcode.data = P80211ENUM_resultcode_implementation_failure; + if (msg->enable.data == P80211ENUM_truth_true) { + if (hfa384x_drvr_flashdl_enable(hw)) { + msg->resultcode.data = + P80211ENUM_resultcode_implementation_failure; } else { msg->resultcode.data = P80211ENUM_resultcode_success; } @@ -943,19 +914,17 @@ int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) wlandev->msdstate = WLAN_MSD_HWPRESENT; result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload); if (result != P80211ENUM_resultcode_success) { - WLAN_LOG_ERROR("prism2sta_ifstate(fwload) failed," - "P80211ENUM_resultcode=%d\n", result); + printk(KERN_ERR "prism2sta_ifstate(fwload) failed," + "P80211ENUM_resultcode=%d\n", result); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; result = -1; } } - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * prism2mgmt_flashdl_write * @@ -976,47 +945,43 @@ int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; - p80211msg_p2req_flashdl_write_t *msg = msgp; - u32 addr; - u32 len; - u8 *buf; - DBFENTER; + hfa384x_t *hw = wlandev->priv; + p80211msg_p2req_flashdl_write_t *msg = msgp; + u32 addr; + u32 len; + u8 *buf; if (wlandev->msdstate != WLAN_MSD_FWLOAD) { - WLAN_LOG_ERROR( - "flashdl_write(): may only be called " - "in the fwload state.\n"); + printk(KERN_ERR + "flashdl_write(): may only be called " + "in the fwload state.\n"); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; - DBFEXIT; return 0; } /* - ** Note: Interrupts are locked out if this is an AP and are NOT - ** locked out if this is a station. - */ + ** Note: Interrupts are locked out if this is an AP and are NOT + ** locked out if this is a station. + */ msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; /* first validate the length */ - if ( msg->len.data > sizeof(msg->data.data) ) { + if (msg->len.data > sizeof(msg->data.data)) { msg->resultcode.status = - P80211ENUM_resultcode_invalid_parameters; + P80211ENUM_resultcode_invalid_parameters; return 0; } /* call the hfa384x function to do the write */ addr = msg->addr.data; len = msg->len.data; buf = msg->data.data; - if ( hfa384x_drvr_flashdl_write(hw, addr, buf, len) ) { + if (hfa384x_drvr_flashdl_write(hw, addr, buf, len)) msg->resultcode.data = P80211ENUM_resultcode_refused; - } msg->resultcode.data = P80211ENUM_resultcode_success; - DBFEXIT; return 0; } @@ -1041,15 +1006,14 @@ int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; - int result = 0; - u16 reg; - u16 port_type; - p80211msg_lnxreq_autojoin_t *msg = msgp; - p80211pstrd_t *pstr; - u8 bytebuf[256]; - hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t*)bytebuf; - DBFENTER; + hfa384x_t *hw = wlandev->priv; + int result = 0; + u16 reg; + u16 port_type; + p80211msg_lnxreq_autojoin_t *msg = msgp; + p80211pstrd_t *pstr; + u8 bytebuf[256]; + hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf; wlandev->macmode = WLAN_MACMODE_NONE; @@ -1064,39 +1028,21 @@ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f); /* Set the auth type */ - if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) { + if (msg->authtype.data == P80211ENUM_authalg_sharedkey) reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY; - } else { + else reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; - } + hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg); /* Set the ssid */ memset(bytebuf, 0, 256); - pstr = (p80211pstrd_t*)&(msg->ssid.data); + pstr = (p80211pstrd_t *)&(msg->ssid.data); prism2mgmt_pstr2bytestr(p2bytestr, pstr); - result = hfa384x_drvr_setconfig( - hw, HFA384x_RID_CNFDESIREDSSID, - bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN); -#if 0 - /* we can use the new-fangled auto-unknown mode if the firmware - is 1.3.3 or newer */ - if (HFA384x_FIRMARE_VERSION(hw->ident_sta_fw.major, - hw->ident_sta_fw.minor, - hw->ident_sta_fw.variant) >= - HFA384x_FIRMWARE_VERSION(1,3,3)) { - /* Set up the IBSS options */ - reg = HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS; - hfa384x_drvr_setconfig16(hw, HFA384x_RID_CREATEIBSS, reg); - - /* Set the PortType */ - port_type = HFA384x_PORTTYPE_IBSS; - } else { - port_type = HFA384x_PORTTYPE_BSS; - } -#else + result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, + bytebuf, + HFA384x_RID_CNFDESIREDSSID_LEN); port_type = HFA384x_PORTTYPE_BSS; -#endif /* Set the PortType */ hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type); @@ -1107,11 +1053,9 @@ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; msg->resultcode.data = P80211ENUM_resultcode_success; - DBFEXIT; return result; } - /*---------------------------------------------------------------- * prism2mgmt_wlansniff * @@ -1133,38 +1077,36 @@ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) ----------------------------------------------------------------*/ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) { - int result = 0; - p80211msg_lnxreq_wlansniff_t *msg = msgp; + int result = 0; + p80211msg_lnxreq_wlansniff_t *msg = msgp; - hfa384x_t *hw = wlandev->priv; - u16 word; - - DBFENTER; + hfa384x_t *hw = wlandev->priv; + u16 word; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; - switch (msg->enable.data) - { + switch (msg->enable.data) { case P80211ENUM_truth_false: /* Confirm that we're in monitor mode */ - if ( wlandev->netdev->type == ARPHRD_ETHER ) { - msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; + if (wlandev->netdev->type == ARPHRD_ETHER) { + msg->resultcode.data = + P80211ENUM_resultcode_invalid_parameters; result = 0; goto exit; } /* Disable monitor mode */ result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE); - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to disable monitor mode, result=%d\n", - result); + if (result) { + printk(KERN_DEBUG + "failed to disable monitor mode, result=%d\n", + result); goto failed; } /* Disable port 0 */ result = hfa384x_drvr_disable(hw, 0); - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to disable port 0 after sniffing, result=%d\n", - result); + if (result) { + printk(KERN_DEBUG + "failed to disable port 0 after sniffing, result=%d\n", + result); goto failed; } /* Clear the driver state */ @@ -1172,32 +1114,34 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) /* Restore the wepflags */ result = hfa384x_drvr_setconfig16(hw, - HFA384x_RID_CNFWEPFLAGS, - hw->presniff_wepflags); - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to restore wepflags=0x%04x, result=%d\n", - hw->presniff_wepflags, - result); + HFA384x_RID_CNFWEPFLAGS, + hw->presniff_wepflags); + if (result) { + printk(KERN_DEBUG + "failed to restore wepflags=0x%04x, result=%d\n", + hw->presniff_wepflags, result); goto failed; } /* Set the port to its prior type and enable (if necessary) */ - if (hw->presniff_port_type != 0 ) { + if (hw->presniff_port_type != 0) { word = hw->presniff_port_type; result = hfa384x_drvr_setconfig16(hw, - HFA384x_RID_CNFPORTTYPE, word); - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to restore porttype, result=%d\n", - result); + HFA384x_RID_CNFPORTTYPE, + word); + if (result) { + printk(KERN_DEBUG + "failed to restore porttype, result=%d\n", + result); goto failed; } /* Enable the port */ result = hfa384x_drvr_enable(hw, 0); - if ( result ) { - WLAN_LOG_DEBUG(1, "failed to enable port to presniff setting, result=%d\n", result); + if (result) { + printk(KERN_DEBUG + "failed to enable port to presniff setting, result=%d\n", + result); goto failed; } } else { @@ -1205,46 +1149,52 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) } - WLAN_LOG_INFO("monitor mode disabled\n"); + printk(KERN_INFO "monitor mode disabled\n"); msg->resultcode.data = P80211ENUM_resultcode_success; result = 0; goto exit; break; case P80211ENUM_truth_true: /* Disable the port (if enabled), only check Port 0 */ - if ( hw->port_enabled[0]) { + if (hw->port_enabled[0]) { if (wlandev->netdev->type == ARPHRD_ETHER) { /* Save macport 0 state */ result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFPORTTYPE, - &(hw->presniff_port_type)); - if ( result ) { - WLAN_LOG_DEBUG(1,"failed to read porttype, result=%d\n", result); + &(hw-> + presniff_port_type)); + if (result) { + printk(KERN_DEBUG + "failed to read porttype, result=%d\n", + result); goto failed; } /* Save the wepflags state */ result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFWEPFLAGS, - &(hw->presniff_wepflags)); - if ( result ) { - WLAN_LOG_DEBUG(1,"failed to read wepflags, result=%d\n", result); + &(hw-> + presniff_wepflags)); + if (result) { + printk(KERN_DEBUG + "failed to read wepflags, result=%d\n", + result); goto failed; } hfa384x_drvr_stop(hw); result = hfa384x_drvr_start(hw); - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to restart the card for sniffing, result=%d\n", - result); + if (result) { + printk(KERN_DEBUG + "failed to restart the card for sniffing, result=%d\n", + result); goto failed; } } else { /* Disable the port */ result = hfa384x_drvr_disable(hw, 0); - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to enable port for sniffing, result=%d\n", - result); + if (result) { + printk(KERN_DEBUG + "failed to enable port for sniffing, result=%d\n", + result); goto failed; } } @@ -1255,14 +1205,14 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) /* Set the channel we wish to sniff */ word = msg->channel.data; result = hfa384x_drvr_setconfig16(hw, - HFA384x_RID_CNFOWNCHANNEL, word); - hw->sniff_channel=word; + HFA384x_RID_CNFOWNCHANNEL, + word); + hw->sniff_channel = word; - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to set channel %d, result=%d\n", - word, - result); + if (result) { + printk(KERN_DEBUG + "failed to set channel %d, result=%d\n", + word, result); goto failed; } @@ -1271,39 +1221,46 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) /* Set the port type to pIbss */ word = HFA384x_PORTTYPE_PSUEDOIBSS; result = hfa384x_drvr_setconfig16(hw, - HFA384x_RID_CNFPORTTYPE, word); - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to set porttype %d, result=%d\n", - word, - result); + HFA384x_RID_CNFPORTTYPE, + word); + if (result) { + printk(KERN_DEBUG + "failed to set porttype %d, result=%d\n", + word, result); goto failed; } - if ((msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && (msg->keepwepflags.data != P80211ENUM_truth_true)) { + if ((msg->keepwepflags.status == + P80211ENUM_msgitem_status_data_ok) + && (msg->keepwepflags.data != + P80211ENUM_truth_true)) { /* Set the wepflags for no decryption */ word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT | - HFA384x_WEPFLAGS_DISABLE_RXCRYPT; - result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, word); + HFA384x_WEPFLAGS_DISABLE_RXCRYPT; + result = + hfa384x_drvr_setconfig16(hw, + HFA384x_RID_CNFWEPFLAGS, + word); } - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to set wepflags=0x%04x, result=%d\n", - word, - result); + if (result) { + printk(KERN_DEBUG + "failed to set wepflags=0x%04x, result=%d\n", + word, result); goto failed; } } /* Do we want to strip the FCS in monitor mode? */ - if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) && (msg->stripfcs.data == P80211ENUM_truth_true)) { + if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) + && (msg->stripfcs.data == P80211ENUM_truth_true)) { hw->sniff_fcs = 0; } else { hw->sniff_fcs = 1; } /* Do we want to truncate the packets? */ - if (msg->packet_trunc.status == P80211ENUM_msgitem_status_data_ok) { + if (msg->packet_trunc.status == + P80211ENUM_msgitem_status_data_ok) { hw->sniff_truncate = msg->packet_trunc.data; } else { hw->sniff_truncate = 0; @@ -1311,31 +1268,35 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) /* Enable the port */ result = hfa384x_drvr_enable(hw, 0); - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to enable port for sniffing, result=%d\n", - result); + if (result) { + printk(KERN_DEBUG + "failed to enable port for sniffing, result=%d\n", + result); goto failed; } /* Enable monitor mode */ result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE); - if ( result ) { - WLAN_LOG_DEBUG(1, - "failed to enable monitor mode, result=%d\n", - result); + if (result) { + printk(KERN_DEBUG + "failed to enable monitor mode, result=%d\n", + result); goto failed; } - if (wlandev->netdev->type == ARPHRD_ETHER) { - WLAN_LOG_INFO("monitor mode enabled\n"); - } + if (wlandev->netdev->type == ARPHRD_ETHER) + printk(KERN_INFO "monitor mode enabled\n"); /* Set the driver state */ /* Do we want the prism2 header? */ - if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) { + if ((msg->prismheader.status == + P80211ENUM_msgitem_status_data_ok) + && (msg->prismheader.data == P80211ENUM_truth_true)) { hw->sniffhdr = 0; wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; - } else if ((msg->wlanheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->wlanheader.data == P80211ENUM_truth_true)) { + } else + if ((msg->wlanheader.status == + P80211ENUM_msgitem_status_data_ok) + && (msg->wlanheader.data == P80211ENUM_truth_true)) { hw->sniffhdr = 1; wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; } else { @@ -1357,7 +1318,5 @@ failed: msg->resultcode.data = P80211ENUM_resultcode_refused; result = 0; exit: - - DBFEXIT; return result; } diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index caf808d57966..07eecebeb6cc 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -60,43 +60,16 @@ #ifndef _PRISM2MGMT_H #define _PRISM2MGMT_H +extern int prism2_reset_holdtime; +extern int prism2_reset_settletime; -/*=============================================================*/ -/*------ Constants --------------------------------------------*/ +u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate); -/*=============================================================*/ -/*------ Macros -----------------------------------------------*/ - -/*=============================================================*/ -/*------ Types and their related constants --------------------*/ - -/*=============================================================*/ -/*------ Static variable externs ------------------------------*/ - -extern int prism2_debug; -extern int prism2_reset_holdtime; -extern int prism2_reset_settletime; -/*=============================================================*/ -/*--- Function Declarations -----------------------------------*/ -/*=============================================================*/ - -u32 -prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate); - -void -prism2sta_ev_dtim(wlandevice_t *wlandev); -void -prism2sta_ev_infdrop(wlandevice_t *wlandev); -void -prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -void -prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status); -void -prism2sta_ev_tx(wlandevice_t *wlandev, u16 status); -void -prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb); -void -prism2sta_ev_alloc(wlandevice_t *wlandev); +void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); +void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status); +void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status); +void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb); +void prism2sta_ev_alloc(wlandevice_t *wlandev); int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp); int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp); @@ -122,34 +95,16 @@ void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len); void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr); void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr); -/* integer conversion functions */ -void prism2mgmt_prism2int2p80211int(u16 *prism2int, u32 *wlanint); -void prism2mgmt_p80211int2prism2int(u16 *prism2int, u32 *wlanint); - -/* enumerated integer conversion functions */ -void prism2mgmt_prism2enum2p80211enum(u16 *prism2enum, u32 *wlanenum, u16 rid); -void prism2mgmt_p80211enum2prism2enum(u16 *prism2enum, u32 *wlanenum, u16 rid); - -/* functions to convert a bit area to/from an Operational Rate Set */ -void prism2mgmt_get_oprateset(u16 *rate, p80211pstrd_t *pstr); -void prism2mgmt_set_oprateset(u16 *rate, p80211pstrd_t *pstr); - /* functions to convert Group Addresses */ -void prism2mgmt_get_grpaddr(u32 did, - p80211pstrd_t *pstr, hfa384x_t *priv ); +void prism2mgmt_get_grpaddr(u32 did, p80211pstrd_t *pstr, hfa384x_t *priv); int prism2mgmt_set_grpaddr(u32 did, - u8 *prism2buf, p80211pstrd_t *pstr, hfa384x_t *priv ); -int prism2mgmt_get_grpaddr_index( u32 did ); + u8 *prism2buf, p80211pstrd_t *pstr, + hfa384x_t *priv); +int prism2mgmt_get_grpaddr_index(u32 did); void prism2sta_processing_defer(struct work_struct *data); void prism2sta_commsqual_defer(struct work_struct *data); void prism2sta_commsqual_timer(unsigned long data); -/*=============================================================*/ -/*--- Inline Function Definitions (if supported) --------------*/ -/*=============================================================*/ - - - #endif diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 539c4479d381..5a6ba86009df 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -50,12 +50,7 @@ * -------------------------------------------------------------------- */ -/*================================================================*/ -/* System Includes */ -#define WLAN_DBVAR prism2_debug - #include - #include #include #include @@ -63,13 +58,11 @@ #include #include #include -#include +#include #include #include #include - -/*================================================================*/ -/* Project Includes */ +#include #include "p80211types.h" #include "p80211hdr.h" @@ -82,196 +75,169 @@ #include "hfa384x.h" #include "prism2mgmt.h" -/*================================================================*/ -/* Local Constants */ +#define MIB_TMP_MAXLEN 200 /* Max length of RID record (in bytes). */ -#define MIB_TMP_MAXLEN 200 /* Max length of RID record (in bytes). */ +#define F_STA 0x1 /* MIB is supported on stations. */ +#define F_READ 0x2 /* MIB may be read. */ +#define F_WRITE 0x4 /* MIB may be written. */ -/*================================================================*/ -/* Local Types */ - -#define F_STA 0x1 /* MIB is supported on stations. */ -#define F_READ 0x2 /* MIB may be read. */ -#define F_WRITE 0x4 /* MIB may be written. */ - -typedef struct mibrec -{ - u32 did; - u16 flag; - u16 parm1; - u16 parm2; - u16 parm3; - int (*func)(struct mibrec *mib, - int isget, - wlandevice_t *wlandev, - hfa384x_t *hw, - p80211msg_dot11req_mibset_t *msg, - void *data); +typedef struct mibrec { + u32 did; + u16 flag; + u16 parm1; + u16 parm2; + u16 parm3; + int (*func) (struct mibrec *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, void *data); } mibrec_t; -/*================================================================*/ -/* Local Function Declarations */ +static int prism2mib_bytearea2pstr(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data); -static int prism2mib_bytearea2pstr( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data); +static int prism2mib_uint32(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, void *data); -static int prism2mib_uint32( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data); +static int prism2mib_flag(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, void *data); -static int prism2mib_flag( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data); +static int prism2mib_wepdefaultkey(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data); -static int prism2mib_wepdefaultkey( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data); +static int prism2mib_privacyinvoked(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data); -static int prism2mib_privacyinvoked( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data); +static int prism2mib_excludeunencrypted(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data); -static int prism2mib_excludeunencrypted( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data); +static int prism2mib_fragmentationthreshold(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data); -static int prism2mib_fragmentationthreshold( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data); - -static int prism2mib_priv( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data); - -/*================================================================*/ -/* Local Static Definitions */ +static int prism2mib_priv(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, void *data); static mibrec_t mibtab[] = { - /* dot11smt MIB's */ - { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0, - F_STA | F_WRITE, - HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, - prism2mib_wepdefaultkey }, - { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1, - F_STA | F_WRITE, - HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, - prism2mib_wepdefaultkey }, - { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2, - F_STA | F_WRITE, - HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, - prism2mib_wepdefaultkey }, - { DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3, - F_STA | F_WRITE, - HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0, - prism2mib_wepdefaultkey }, - { DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, - F_STA | F_READ | F_WRITE, - HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_PRIVINVOKED, 0, - prism2mib_privacyinvoked }, - { DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, - F_STA | F_READ | F_WRITE, - HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0, - prism2mib_uint32 }, - { DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, - F_STA | F_READ | F_WRITE, - HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0, - prism2mib_excludeunencrypted }, + /* dot11smt MIB's */ + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0, + F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY0, 0, 0, + prism2mib_wepdefaultkey}, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1, + F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY1, 0, 0, + prism2mib_wepdefaultkey}, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2, + F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY2, 0, 0, + prism2mib_wepdefaultkey}, + {DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3, + F_STA | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEY3, 0, 0, + prism2mib_wepdefaultkey}, + {DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_PRIVINVOKED, 0, + prism2mib_privacyinvoked}, + {DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPDEFAULTKEYID, 0, 0, + prism2mib_uint32}, + {DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0, + prism2mib_excludeunencrypted}, - /* dot11mac MIB's */ + /* dot11mac MIB's */ - { DIDmib_dot11mac_dot11OperationTable_dot11MACAddress, - F_STA | F_READ | F_WRITE, - HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0, - prism2mib_bytearea2pstr }, - { DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, - F_STA | F_READ | F_WRITE, - HFA384x_RID_RTSTHRESH, 0, 0, - prism2mib_uint32 }, - { DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit, - F_STA | F_READ, - HFA384x_RID_SHORTRETRYLIMIT, 0, 0, - prism2mib_uint32 }, - { DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit, - F_STA | F_READ, - HFA384x_RID_LONGRETRYLIMIT, 0, 0, - prism2mib_uint32 }, - { DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, - F_STA | F_READ | F_WRITE, - HFA384x_RID_FRAGTHRESH, 0, 0, - prism2mib_fragmentationthreshold }, - { DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime, - F_STA | F_READ, - HFA384x_RID_MAXTXLIFETIME, 0, 0, - prism2mib_uint32 }, + {DIDmib_dot11mac_dot11OperationTable_dot11MACAddress, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFOWNMACADDR, HFA384x_RID_CNFOWNMACADDR_LEN, 0, + prism2mib_bytearea2pstr}, + {DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_RTSTHRESH, 0, 0, + prism2mib_uint32}, + {DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit, + F_STA | F_READ, + HFA384x_RID_SHORTRETRYLIMIT, 0, 0, + prism2mib_uint32}, + {DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit, + F_STA | F_READ, + HFA384x_RID_LONGRETRYLIMIT, 0, 0, + prism2mib_uint32}, + {DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold, + F_STA | F_READ | F_WRITE, + HFA384x_RID_FRAGTHRESH, 0, 0, + prism2mib_fragmentationthreshold}, + {DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime, + F_STA | F_READ, + HFA384x_RID_MAXTXLIFETIME, 0, 0, + prism2mib_uint32}, - /* dot11phy MIB's */ + /* dot11phy MIB's */ - { DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, - F_STA | F_READ, - HFA384x_RID_CURRENTCHANNEL, 0, 0, - prism2mib_uint32 }, - { DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel, - F_STA | F_READ | F_WRITE, - HFA384x_RID_TXPOWERMAX, 0, 0, - prism2mib_uint32 }, + {DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel, + F_STA | F_READ, + HFA384x_RID_CURRENTCHANNEL, 0, 0, + prism2mib_uint32}, + {DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel, + F_STA | F_READ | F_WRITE, + HFA384x_RID_TXPOWERMAX, 0, 0, + prism2mib_uint32}, - /* p2Static MIB's */ + /* p2Static MIB's */ - { DIDmib_p2_p2Static_p2CnfPortType, - F_STA | F_READ | F_WRITE, - HFA384x_RID_CNFPORTTYPE, 0, 0, - prism2mib_uint32 }, + {DIDmib_p2_p2Static_p2CnfPortType, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFPORTTYPE, 0, 0, + prism2mib_uint32}, - /* p2MAC MIB's */ + /* p2MAC MIB's */ - { DIDmib_p2_p2MAC_p2CurrentTxRate, - F_STA | F_READ, - HFA384x_RID_CURRENTTXRATE, 0, 0, - prism2mib_uint32 }, + {DIDmib_p2_p2MAC_p2CurrentTxRate, + F_STA | F_READ, + HFA384x_RID_CURRENTTXRATE, 0, 0, + prism2mib_uint32}, - /* And finally, lnx mibs */ - { DIDmib_lnx_lnxConfigTable_lnxRSNAIE, - F_STA | F_READ | F_WRITE, - HFA384x_RID_CNFWPADATA, 0, 0, - prism2mib_priv }, - { 0, 0, 0, 0, 0, NULL}}; - -/*================================================================*/ -/* Function Definitions */ + /* And finally, lnx mibs */ + {DIDmib_lnx_lnxConfigTable_lnxRSNAIE, + F_STA | F_READ | F_WRITE, + HFA384x_RID_CNFWPADATA, 0, 0, + prism2mib_priv}, + {0, 0, 0, 0, 0, NULL} +}; /*---------------------------------------------------------------- * prism2mgmt_mibset_mibget @@ -295,32 +261,30 @@ static mibrec_t mibtab[] = { int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp) { - hfa384x_t *hw = wlandev->priv; - int result, isget; - mibrec_t *mib; + hfa384x_t *hw = wlandev->priv; + int result, isget; + mibrec_t *mib; - u16 which; + u16 which; - p80211msg_dot11req_mibset_t *msg = msgp; - p80211itemd_t *mibitem; - - DBFENTER; + p80211msg_dot11req_mibset_t *msg = msgp; + p80211itemd_t *mibitem; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; msg->resultcode.data = P80211ENUM_resultcode_success; /* - ** Determine if this is an Access Point or a station. - */ + ** Determine if this is an Access Point or a station. + */ which = F_STA; /* - ** Find the MIB in the MIB table. Note that a MIB may be in the - ** table twice...once for an AP and once for a station. Make sure - ** to get the correct one. Note that DID=0 marks the end of the - ** MIB table. - */ + ** Find the MIB in the MIB table. Note that a MIB may be in the + ** table twice...once for an AP and once for a station. Make sure + ** to get the correct one. Note that DID=0 marks the end of the + ** MIB table. + */ mibitem = (p80211itemd_t *) msg->mibattribute.data; @@ -334,58 +298,55 @@ int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp) } /* - ** Determine if this is a "mibget" or a "mibset". If this is a - ** "mibget", then make sure that the MIB may be read. Otherwise, - ** this is a "mibset" so make make sure that the MIB may be written. - */ + ** Determine if this is a "mibget" or a "mibset". If this is a + ** "mibget", then make sure that the MIB may be read. Otherwise, + ** this is a "mibset" so make make sure that the MIB may be written. + */ isget = (msg->msgcode == DIDmsg_dot11req_mibget); if (isget) { if (!(mib->flag & F_READ)) { msg->resultcode.data = - P80211ENUM_resultcode_cant_get_writeonly_mib; + P80211ENUM_resultcode_cant_get_writeonly_mib; goto done; } } else { if (!(mib->flag & F_WRITE)) { msg->resultcode.data = - P80211ENUM_resultcode_cant_set_readonly_mib; + P80211ENUM_resultcode_cant_set_readonly_mib; goto done; } } /* - ** Execute the MIB function. If things worked okay, then make - ** sure that the MIB function also worked okay. If so, and this - ** is a "mibget", then the status value must be set for both the - ** "mibattribute" parameter and the mib item within the data - ** portion of the "mibattribute". - */ + ** Execute the MIB function. If things worked okay, then make + ** sure that the MIB function also worked okay. If so, and this + ** is a "mibget", then the status value must be set for both the + ** "mibattribute" parameter and the mib item within the data + ** portion of the "mibattribute". + */ - result = mib->func(mib, isget, wlandev, hw, msg, - (void *) mibitem->data); + result = mib->func(mib, isget, wlandev, hw, msg, (void *)mibitem->data); if (msg->resultcode.data == P80211ENUM_resultcode_success) { if (result != 0) { - WLAN_LOG_DEBUG(1, "get/set failure, result=%d\n", - result); + pr_debug("get/set failure, result=%d\n", + result); msg->resultcode.data = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; } else { if (isget) { msg->mibattribute.status = - P80211ENUM_msgitem_status_data_ok; + P80211ENUM_msgitem_status_data_ok; mibitem->status = - P80211ENUM_msgitem_status_data_ok; + P80211ENUM_msgitem_status_data_ok; } } } done: - DBFEXIT; - - return(0); + return 0; } /*---------------------------------------------------------------- @@ -413,31 +374,29 @@ done: * ----------------------------------------------------------------*/ -static int prism2mib_bytearea2pstr( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data) +static int prism2mib_bytearea2pstr(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data) { - int result; - p80211pstrd_t *pstr = (p80211pstrd_t*) data; - u8 bytebuf[MIB_TMP_MAXLEN]; - - DBFENTER; + int result; + p80211pstrd_t *pstr = (p80211pstrd_t *) data; + u8 bytebuf[MIB_TMP_MAXLEN]; if (isget) { - result = hfa384x_drvr_getconfig(hw, mib->parm1, bytebuf, mib->parm2); + result = + hfa384x_drvr_getconfig(hw, mib->parm1, bytebuf, mib->parm2); prism2mgmt_bytearea2pstr(bytebuf, pstr, mib->parm2); } else { memset(bytebuf, 0, mib->parm2); prism2mgmt_pstr2bytearea(bytebuf, pstr); - result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2); + result = + hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2); } - DBFEXIT; - return(result); + return result; } /*---------------------------------------------------------------- @@ -465,37 +424,26 @@ void *data) * ----------------------------------------------------------------*/ -static int prism2mib_uint32( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data) +static int prism2mib_uint32(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, void *data) { - int result; - u32 *uint32 = (u32*) data; - u8 bytebuf[MIB_TMP_MAXLEN]; - u16 *wordbuf = (u16*) bytebuf; - - DBFENTER; + int result; + u32 *uint32 = (u32 *) data; + u8 bytebuf[MIB_TMP_MAXLEN]; + u16 *wordbuf = (u16 *) bytebuf; if (isget) { result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); *uint32 = *wordbuf; - /* [MSM] Removed, getconfig16 returns the value in host order. - * prism2mgmt_prism2int2p80211int(wordbuf, uint32); - */ } else { - /* [MSM] Removed, setconfig16 expects host order. - * prism2mgmt_p80211int2prism2int(wordbuf, uint32); - */ *wordbuf = *uint32; result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); } - DBFEXIT; - return(result); + return result; } /*---------------------------------------------------------------- @@ -523,46 +471,36 @@ void *data) * ----------------------------------------------------------------*/ -static int prism2mib_flag( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data) +static int prism2mib_flag(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, void *data) { - int result; - u32 *uint32 = (u32*) data; - u8 bytebuf[MIB_TMP_MAXLEN]; - u16 *wordbuf = (u16*) bytebuf; - u32 flags; - - DBFENTER; + int result; + u32 *uint32 = (u32 *) data; + u8 bytebuf[MIB_TMP_MAXLEN]; + u16 *wordbuf = (u16 *) bytebuf; + u32 flags; result = hfa384x_drvr_getconfig16(hw, mib->parm1, wordbuf); if (result == 0) { - /* [MSM] Removed, getconfig16 returns the value in host order. - * prism2mgmt_prism2int2p80211int(wordbuf, &flags); - */ flags = *wordbuf; if (isget) { *uint32 = (flags & mib->parm2) ? - P80211ENUM_truth_true : P80211ENUM_truth_false; + P80211ENUM_truth_true : P80211ENUM_truth_false; } else { if ((*uint32) == P80211ENUM_truth_true) flags |= mib->parm2; else flags &= ~mib->parm2; - /* [MSM] Removed, setconfig16 expects host order. - * prism2mgmt_p80211int2prism2int(wordbuf, &flags); - */ *wordbuf = flags; - result = hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); + result = + hfa384x_drvr_setconfig16(hw, mib->parm1, *wordbuf); } } - DBFEXIT; - return(result); + return result; } /*---------------------------------------------------------------- @@ -590,33 +528,29 @@ void *data) * ----------------------------------------------------------------*/ -static int prism2mib_wepdefaultkey( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data) +static int prism2mib_wepdefaultkey(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data) { - int result; - p80211pstrd_t *pstr = (p80211pstrd_t*) data; - u8 bytebuf[MIB_TMP_MAXLEN]; - u16 len; - - DBFENTER; + int result; + p80211pstrd_t *pstr = (p80211pstrd_t *) data; + u8 bytebuf[MIB_TMP_MAXLEN]; + u16 len; if (isget) { - result = 0; /* Should never happen. */ + result = 0; /* Should never happen. */ } else { len = (pstr->len > 5) ? HFA384x_RID_CNFWEP128DEFAULTKEY_LEN : - HFA384x_RID_CNFWEPDEFAULTKEY_LEN; + HFA384x_RID_CNFWEPDEFAULTKEY_LEN; memset(bytebuf, 0, len); prism2mgmt_pstr2bytearea(bytebuf, pstr); result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, len); } - DBFEXIT; - return(result); + return result; } /*---------------------------------------------------------------- @@ -644,17 +578,14 @@ void *data) * ----------------------------------------------------------------*/ -static int prism2mib_privacyinvoked( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data) +static int prism2mib_privacyinvoked(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data) { - int result; - - DBFENTER; + int result; if (wlandev->hostwep & HOSTWEP_DECRYPT) { if (wlandev->hostwep & HOSTWEP_DECRYPT) @@ -665,8 +596,7 @@ void *data) result = prism2mib_flag(mib, isget, wlandev, hw, msg, data); - DBFEXIT; - return(result); + return result; } /*---------------------------------------------------------------- @@ -694,22 +624,18 @@ void *data) * ----------------------------------------------------------------*/ -static int prism2mib_excludeunencrypted( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data) +static int prism2mib_excludeunencrypted(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data) { - int result; - - DBFENTER; + int result; result = prism2mib_flag(mib, isget, wlandev, hw, msg, data); - DBFEXIT; - return(result); + return result; } /*---------------------------------------------------------------- @@ -737,31 +663,28 @@ void *data) * ----------------------------------------------------------------*/ -static int prism2mib_fragmentationthreshold( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data) +static int prism2mib_fragmentationthreshold(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, + void *data) { - int result; - u32 *uint32 = (u32*) data; - - DBFENTER; + int result; + u32 *uint32 = (u32 *) data; if (!isget) if ((*uint32) % 2) { - WLAN_LOG_WARNING("Attempt to set odd number " - "FragmentationThreshold\n"); - msg->resultcode.data = P80211ENUM_resultcode_not_supported; - return(0); + printk(KERN_WARNING "Attempt to set odd number " + "FragmentationThreshold\n"); + msg->resultcode.data = + P80211ENUM_resultcode_not_supported; + return 0; } result = prism2mib_uint32(mib, isget, wlandev, hw, msg, data); - DBFEXIT; - return(result); + return result; } /*---------------------------------------------------------------- @@ -789,43 +712,43 @@ void *data) * ----------------------------------------------------------------*/ -static int prism2mib_priv( -mibrec_t *mib, -int isget, -wlandevice_t *wlandev, -hfa384x_t *hw, -p80211msg_dot11req_mibset_t *msg, -void *data) +static int prism2mib_priv(mibrec_t *mib, + int isget, + wlandevice_t *wlandev, + hfa384x_t *hw, + p80211msg_dot11req_mibset_t *msg, void *data) { - p80211pstrd_t *pstr = (p80211pstrd_t*) data; + p80211pstrd_t *pstr = (p80211pstrd_t *) data; - int result; - - DBFENTER; + int result; switch (mib->did) { - case DIDmib_lnx_lnxConfigTable_lnxRSNAIE: { - hfa384x_WPAData_t wpa; - if (isget) { - hfa384x_drvr_getconfig( hw, HFA384x_RID_CNFWPADATA, - (u8 *) &wpa, sizeof(wpa)); - pstr->len = hfa384x2host_16(wpa.datalen); - memcpy(pstr->data, wpa.data, pstr->len); - } else { - wpa.datalen = host2hfa384x_16(pstr->len); - memcpy(wpa.data, pstr->data, pstr->len); + case DIDmib_lnx_lnxConfigTable_lnxRSNAIE:{ + hfa384x_WPAData_t wpa; + if (isget) { + hfa384x_drvr_getconfig(hw, + HFA384x_RID_CNFWPADATA, + (u8 *)&wpa, + sizeof(wpa)); + pstr->len = le16_to_cpu(wpa.datalen); + memcpy(pstr->data, wpa.data, pstr->len); + } else { + wpa.datalen = cpu_to_le16(pstr->len); + memcpy(wpa.data, pstr->data, pstr->len); - result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFWPADATA, - (u8 *) &wpa, sizeof(wpa)); + result = + hfa384x_drvr_setconfig(hw, + HFA384x_RID_CNFWPADATA, + (u8 *)&wpa, + sizeof(wpa)); + } + break; } - break; - } default: - WLAN_LOG_ERROR("Unhandled DID 0x%08x\n", mib->did); + printk(KERN_ERR "Unhandled DID 0x%08x\n", mib->did); } - DBFEXIT; - return(0); + return 0; } /*---------------------------------------------------------------- @@ -845,14 +768,10 @@ void *data) void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) { - DBFENTER; - - bytestr->len = host2hfa384x_16((u16)(pstr->len)); + bytestr->len = cpu_to_le16((u16) (pstr->len)); memcpy(bytestr->data, pstr->data, pstr->len); - DBFEXIT; } - /*---------------------------------------------------------------- * prism2mgmt_pstr2bytearea * @@ -870,13 +789,9 @@ void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) void prism2mgmt_pstr2bytearea(u8 *bytearea, p80211pstrd_t *pstr) { - DBFENTER; - memcpy(bytearea, pstr->data, pstr->len); - DBFEXIT; } - /*---------------------------------------------------------------- * prism2mgmt_bytestr2pstr * @@ -894,14 +809,10 @@ void prism2mgmt_pstr2bytearea(u8 *bytearea, p80211pstrd_t *pstr) void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) { - DBFENTER; - - pstr->len = (u8)(hfa384x2host_16((u16)(bytestr->len))); + pstr->len = (u8) (le16_to_cpu((u16) (bytestr->len))); memcpy(pstr->data, bytestr->data, pstr->len); - DBFEXIT; } - /*---------------------------------------------------------------- * prism2mgmt_bytearea2pstr * @@ -919,217 +830,11 @@ void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr) void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len) { - DBFENTER; - - pstr->len = (u8)len; + pstr->len = (u8) len; memcpy(pstr->data, bytearea, len); - DBFEXIT; -} - - -/*---------------------------------------------------------------- -* prism2mgmt_prism2int2p80211int -* -* Convert an hfa384x integer into a wlan integer -* -* Arguments: -* prism2enum pointer to hfa384x integer -* wlanenum pointer to p80211 integer -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ - -void prism2mgmt_prism2int2p80211int(u16 *prism2int, u32 *wlanint) -{ - DBFENTER; - - *wlanint = (u32)hfa384x2host_16(*prism2int); - DBFEXIT; -} - - -/*---------------------------------------------------------------- -* prism2mgmt_p80211int2prism2int -* -* Convert a wlan integer into an hfa384x integer -* -* Arguments: -* prism2enum pointer to hfa384x integer -* wlanenum pointer to p80211 integer -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ - -void prism2mgmt_p80211int2prism2int(u16 *prism2int, u32 *wlanint) -{ - DBFENTER; - - *prism2int = host2hfa384x_16((u16)(*wlanint)); - DBFEXIT; -} - - -/*---------------------------------------------------------------- -* prism2mgmt_prism2enum2p80211enum -* -* Convert the hfa384x enumerated int into a p80211 enumerated int -* -* Arguments: -* prism2enum pointer to hfa384x integer -* wlanenum pointer to p80211 integer -* rid hfa384x record id -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ -void prism2mgmt_prism2enum2p80211enum(u16 *prism2enum, u32 *wlanenum, u16 rid) -{ - DBFENTER; - - /* At the moment, the need for this functionality hasn't - presented itself. All the wlan enumerated values are - a 1-to-1 match against the Prism2 enumerated values*/ - DBFEXIT; - return; -} - - -/*---------------------------------------------------------------- -* prism2mgmt_p80211enum2prism2enum -* -* Convert the p80211 enumerated int into an hfa384x enumerated int -* -* Arguments: -* prism2enum pointer to hfa384x integer -* wlanenum pointer to p80211 integer -* rid hfa384x record id -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ -void prism2mgmt_p80211enum2prism2enum(u16 *prism2enum, u32 *wlanenum, u16 rid) -{ - DBFENTER; - - /* At the moment, the need for this functionality hasn't - presented itself. All the wlan enumerated values are - a 1-to-1 match against the Prism2 enumerated values*/ - DBFEXIT; - return; } -/*---------------------------------------------------------------- -* prism2mgmt_get_oprateset -* -* Convert the hfa384x bit area into a wlan octet string. -* -* Arguments: -* rate Prism2 bit area -* pstr wlan octet string -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ -void prism2mgmt_get_oprateset(u16 *rate, p80211pstrd_t *pstr) -{ - u8 len; - u8 *datarate; - - DBFENTER; - - len = 0; - datarate = pstr->data; - - /* 1 Mbps */ - if ( BIT0 & (*rate) ) { - len += (u8)1; - *datarate = (u8)2; - datarate++; - } - - /* 2 Mbps */ - if ( BIT1 & (*rate) ) { - len += (u8)1; - *datarate = (u8)4; - datarate++; - } - - /* 5.5 Mbps */ - if ( BIT2 & (*rate) ) { - len += (u8)1; - *datarate = (u8)11; - datarate++; - } - - /* 11 Mbps */ - if ( BIT3 & (*rate) ) { - len += (u8)1; - *datarate = (u8)22; - datarate++; - } - - pstr->len = len; - - DBFEXIT; - return; -} - -/*---------------------------------------------------------------- -* prism2mgmt_set_oprateset -* -* Convert the wlan octet string into an hfa384x bit area. -* -* Arguments: -* rate Prism2 bit area -* pstr wlan octet string -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ -void prism2mgmt_set_oprateset(u16 *rate, p80211pstrd_t *pstr) -{ - u8 *datarate; - int i; - - DBFENTER; - - *rate = 0; - - datarate = pstr->data; - - for ( i=0; i < pstr->len; i++, datarate++ ) { - switch (*datarate) { - case 2: /* 1 Mbps */ - *rate |= BIT0; - break; - case 4: /* 2 Mbps */ - *rate |= BIT1; - break; - case 11: /* 5.5 Mbps */ - *rate |= BIT2; - break; - case 22: /* 11 Mbps */ - *rate |= BIT3; - break; - default: - WLAN_LOG_DEBUG(1, "Unrecoginzed Rate of %d\n", - *datarate); - break; - } - } - - DBFEXIT; - return; -} diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index b279c97cbc02..9d57f82f4a25 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -50,10 +50,6 @@ * -------------------------------------------------------------------- */ -/*================================================================*/ -/* System Includes */ -#define WLAN_DBVAR prism2_debug - #include #include #include @@ -65,13 +61,15 @@ #include #include #include +#include +#include #include #include #include #include - -#include "wlan_compat.h" +#include +#include /*================================================================*/ /* Project Includes */ @@ -88,111 +86,78 @@ #include "hfa384x.h" #include "prism2mgmt.h" -/*================================================================*/ -/* Local Constants */ +#define wlan_hexchar(x) (((x) < 0x0a) ? ('0' + (x)) : ('a' + ((x) - 0x0a))) -/*================================================================*/ -/* Local Macros */ - -/*================================================================*/ -/* Local Types */ - -/*================================================================*/ -/* Local Static Definitions */ +/* Create a string of printable chars from something that might not be */ +/* It's recommended that the str be 4*len + 1 bytes long */ +#define wlan_mkprintstr(buf, buflen, str, strlen) \ +{ \ + int i = 0; \ + int j = 0; \ + memset(str, 0, (strlen)); \ + for (i = 0; i < (buflen); i++) { \ + if (isprint((buf)[i])) { \ + (str)[j] = (buf)[i]; \ + j++; \ + } else { \ + (str)[j] = '\\'; \ + (str)[j+1] = 'x'; \ + (str)[j+2] = wlan_hexchar(((buf)[i] & 0xf0) >> 4); \ + (str)[j+3] = wlan_hexchar(((buf)[i] & 0x0f)); \ + j += 4; \ + } \ + } \ +} static char *dev_info = "prism2_usb"; - static wlandevice_t *create_wlan(void); -/*----------------------------------------------------------------*/ -/* --Module Parameters */ +int prism2_reset_holdtime = 30; /* Reset hold time in ms */ +int prism2_reset_settletime = 100; /* Reset settle time in ms */ -int prism2_reset_holdtime=30; /* Reset hold time in ms */ -int prism2_reset_settletime=100; /* Reset settle time in ms */ +static int prism2_doreset = 0; /* Do a reset at init? */ -static int prism2_doreset=0; /* Do a reset at init? */ - -#ifdef WLAN_INCLUDE_DEBUG -int prism2_debug=0; -module_param( prism2_debug, int, 0644); -MODULE_PARM_DESC(prism2_debug, "prism2 debugging"); -#endif - -module_param( prism2_doreset, int, 0644); +module_param(prism2_doreset, int, 0644); MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization"); -module_param( prism2_reset_holdtime, int, 0644); -MODULE_PARM_DESC( prism2_reset_holdtime, "reset hold time in ms"); -module_param( prism2_reset_settletime, int, 0644); -MODULE_PARM_DESC( prism2_reset_settletime, "reset settle time in ms"); +module_param(prism2_reset_holdtime, int, 0644); +MODULE_PARM_DESC(prism2_reset_holdtime, "reset hold time in ms"); +module_param(prism2_reset_settletime, int, 0644); +MODULE_PARM_DESC(prism2_reset_settletime, "reset settle time in ms"); MODULE_LICENSE("Dual MPL/GPL"); -/*================================================================*/ -/* Local Function Declarations */ - -static int prism2sta_open(wlandevice_t *wlandev); -static int prism2sta_close(wlandevice_t *wlandev); -static void prism2sta_reset(wlandevice_t *wlandev ); -static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep); -static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg); -static int prism2sta_getcardinfo(wlandevice_t *wlandev); -static int prism2sta_globalsetup(wlandevice_t *wlandev); -static int prism2sta_setmulticast(wlandevice_t *wlandev, - netdevice_t *dev); - -static void prism2sta_inf_handover( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_tallies( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_hostscanresults( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_scanresults( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_chinforesults( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_linkstatus( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_assocstatus( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_authreq( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_authreq_defer( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); -static void prism2sta_inf_psusercnt( - wlandevice_t *wlandev, hfa384x_InfFrame_t *inf); - -/*================================================================*/ -/* Function Definitions */ - -/*---------------------------------------------------------------- -* dmpmem -* -* Debug utility function to dump memory to the kernel debug log. -* -* Arguments: -* buf ptr data we want dumped -* len length of data -* -* Returns: -* nothing -* Side effects: -* -* Call context: -* process thread -* interrupt -----------------------------------------------------------------*/ -inline void dmpmem(void *buf, int n) -{ - int c; - for ( c= 0; c < n; c++) { - if ( (c % 16) == 0 ) printk(KERN_DEBUG"dmp[%d]: ", c); - printk("%02x ", ((u8*)buf)[c]); - if ( (c % 16) == 15 ) printk("\n"); - } - if ( (c % 16) != 0 ) printk("\n"); -} +static int prism2sta_open(wlandevice_t *wlandev); +static int prism2sta_close(wlandevice_t *wlandev); +static void prism2sta_reset(wlandevice_t *wlandev); +static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, + p80211_hdr_t *p80211_hdr, + p80211_metawep_t *p80211_wep); +static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg); +static int prism2sta_getcardinfo(wlandevice_t *wlandev); +static int prism2sta_globalsetup(wlandevice_t *wlandev); +static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev); +static void prism2sta_inf_handover(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); +static void prism2sta_inf_tallies(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); +static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); +static void prism2sta_inf_scanresults(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); +static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); +static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); +static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); +static void prism2sta_inf_authreq(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); +static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); +static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf); /*---------------------------------------------------------------- * prism2sta_open @@ -217,8 +182,6 @@ inline void dmpmem(void *buf, int n) ----------------------------------------------------------------*/ static int prism2sta_open(wlandevice_t *wlandev) { - DBFENTER; - /* We don't currently have to do anything else. * The setup of the MAC should be subsequently completed via * the mlme commands. @@ -227,11 +190,9 @@ static int prism2sta_open(wlandevice_t *wlandev) * frames because of dev->flags&IFF_UP is true. */ - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * prism2sta_close * @@ -255,19 +216,15 @@ static int prism2sta_open(wlandevice_t *wlandev) ----------------------------------------------------------------*/ static int prism2sta_close(wlandevice_t *wlandev) { - DBFENTER; - /* We don't currently have to do anything else. * Higher layers know we're not ready from dev->start==0 and * dev->tbusy==1. Our rx path knows to not pass up received * frames because of dev->flags&IFF_UP is false. */ - DBFEXIT; return 0; } - /*---------------------------------------------------------------- * prism2sta_reset * @@ -285,14 +242,11 @@ static int prism2sta_close(wlandevice_t *wlandev) * Call context: * process thread ----------------------------------------------------------------*/ -static void prism2sta_reset(wlandevice_t *wlandev ) +static void prism2sta_reset(wlandevice_t *wlandev) { - DBFENTER; - DBFEXIT; return; } - /*---------------------------------------------------------------- * prism2sta_txframe * @@ -318,22 +272,20 @@ static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; - int result; - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + int result; /* If necessary, set the 802.11 WEP bit */ - if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) == HOSTWEP_PRIVACYINVOKED) { - p80211_hdr->a3.fc |= host2ieee16(WLAN_SET_FC_ISWEP(1)); + if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) == + HOSTWEP_PRIVACYINVOKED) { + p80211_hdr->a3.fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1)); } result = hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep); - DBFEXIT; return result; } - /*---------------------------------------------------------------- * prism2sta_mlmerequest * @@ -360,109 +312,113 @@ static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, ----------------------------------------------------------------*/ static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; int result = 0; - DBFENTER; - switch( msg->msgcode ) - { - case DIDmsg_dot11req_mibget : - WLAN_LOG_DEBUG(2,"Received mibget request\n"); + switch (msg->msgcode) { + case DIDmsg_dot11req_mibget: + pr_debug("Received mibget request\n"); result = prism2mgmt_mibset_mibget(wlandev, msg); break; - case DIDmsg_dot11req_mibset : - WLAN_LOG_DEBUG(2,"Received mibset request\n"); + case DIDmsg_dot11req_mibset: + pr_debug("Received mibset request\n"); result = prism2mgmt_mibset_mibget(wlandev, msg); break; - case DIDmsg_dot11req_scan : - WLAN_LOG_DEBUG(2,"Received scan request\n"); + case DIDmsg_dot11req_scan: + pr_debug("Received scan request\n"); result = prism2mgmt_scan(wlandev, msg); break; - case DIDmsg_dot11req_scan_results : - WLAN_LOG_DEBUG(2,"Received scan_results request\n"); + case DIDmsg_dot11req_scan_results: + pr_debug("Received scan_results request\n"); result = prism2mgmt_scan_results(wlandev, msg); break; - case DIDmsg_dot11req_start : - WLAN_LOG_DEBUG(2,"Received mlme start request\n"); + case DIDmsg_dot11req_start: + pr_debug("Received mlme start request\n"); result = prism2mgmt_start(wlandev, msg); break; - /* - * Prism2 specific messages - */ - case DIDmsg_p2req_readpda : - WLAN_LOG_DEBUG(2,"Received mlme readpda request\n"); + /* + * Prism2 specific messages + */ + case DIDmsg_p2req_readpda: + pr_debug("Received mlme readpda request\n"); result = prism2mgmt_readpda(wlandev, msg); break; - case DIDmsg_p2req_ramdl_state : - WLAN_LOG_DEBUG(2,"Received mlme ramdl_state request\n"); + case DIDmsg_p2req_ramdl_state: + pr_debug("Received mlme ramdl_state request\n"); result = prism2mgmt_ramdl_state(wlandev, msg); break; - case DIDmsg_p2req_ramdl_write : - WLAN_LOG_DEBUG(2,"Received mlme ramdl_write request\n"); + case DIDmsg_p2req_ramdl_write: + pr_debug("Received mlme ramdl_write request\n"); result = prism2mgmt_ramdl_write(wlandev, msg); break; - case DIDmsg_p2req_flashdl_state : - WLAN_LOG_DEBUG(2,"Received mlme flashdl_state request\n"); + case DIDmsg_p2req_flashdl_state: + pr_debug("Received mlme flashdl_state request\n"); result = prism2mgmt_flashdl_state(wlandev, msg); break; - case DIDmsg_p2req_flashdl_write : - WLAN_LOG_DEBUG(2,"Received mlme flashdl_write request\n"); + case DIDmsg_p2req_flashdl_write: + pr_debug("Received mlme flashdl_write request\n"); result = prism2mgmt_flashdl_write(wlandev, msg); break; - /* - * Linux specific messages - */ - case DIDmsg_lnxreq_hostwep : - break; // ignore me. - case DIDmsg_lnxreq_ifstate : + /* + * Linux specific messages + */ + case DIDmsg_lnxreq_hostwep: + break; /* ignore me. */ + case DIDmsg_lnxreq_ifstate: { - p80211msg_lnxreq_ifstate_t *ifstatemsg; - WLAN_LOG_DEBUG(2,"Received mlme ifstate request\n"); - ifstatemsg = (p80211msg_lnxreq_ifstate_t*)msg; - result = prism2sta_ifstate(wlandev, ifstatemsg->ifstate.data); - ifstatemsg->resultcode.status = - P80211ENUM_msgitem_status_data_ok; - ifstatemsg->resultcode.data = result; - result = 0; + p80211msg_lnxreq_ifstate_t *ifstatemsg; + pr_debug("Received mlme ifstate request\n"); + ifstatemsg = (p80211msg_lnxreq_ifstate_t *) msg; + result = + prism2sta_ifstate(wlandev, + ifstatemsg->ifstate.data); + ifstatemsg->resultcode.status = + P80211ENUM_msgitem_status_data_ok; + ifstatemsg->resultcode.data = result; + result = 0; } - break; - case DIDmsg_lnxreq_wlansniff : - WLAN_LOG_DEBUG(2,"Received mlme wlansniff request\n"); - result = prism2mgmt_wlansniff(wlandev, msg); - break; - case DIDmsg_lnxreq_autojoin : - WLAN_LOG_DEBUG(2,"Received mlme autojoin request\n"); + break; + case DIDmsg_lnxreq_wlansniff: + pr_debug("Received mlme wlansniff request\n"); + result = prism2mgmt_wlansniff(wlandev, msg); + break; + case DIDmsg_lnxreq_autojoin: + pr_debug("Received mlme autojoin request\n"); result = prism2mgmt_autojoin(wlandev, msg); break; - case DIDmsg_lnxreq_commsquality: { - p80211msg_lnxreq_commsquality_t *qualmsg; + case DIDmsg_lnxreq_commsquality:{ + p80211msg_lnxreq_commsquality_t *qualmsg; - WLAN_LOG_DEBUG(2,"Received commsquality request\n"); + pr_debug("Received commsquality request\n"); - qualmsg = (p80211msg_lnxreq_commsquality_t*) msg; + qualmsg = (p80211msg_lnxreq_commsquality_t *) msg; - qualmsg->link.status = P80211ENUM_msgitem_status_data_ok; - qualmsg->level.status = P80211ENUM_msgitem_status_data_ok; - qualmsg->noise.status = P80211ENUM_msgitem_status_data_ok; + qualmsg->link.status = + P80211ENUM_msgitem_status_data_ok; + qualmsg->level.status = + P80211ENUM_msgitem_status_data_ok; + qualmsg->noise.status = + P80211ENUM_msgitem_status_data_ok; + qualmsg->link.data = + le16_to_cpu(hw->qual.CQ_currBSS); + qualmsg->level.data = + le16_to_cpu(hw->qual.ASL_currBSS); + qualmsg->noise.data = + le16_to_cpu(hw->qual.ANL_currFC); - qualmsg->link.data = hfa384x2host_16(hw->qual.CQ_currBSS); - qualmsg->level.data = hfa384x2host_16(hw->qual.ASL_currBSS); - qualmsg->noise.data = hfa384x2host_16(hw->qual.ANL_currFC); - - break; - } + break; + } default: - WLAN_LOG_WARNING("Unknown mgmt request message 0x%08x", msg->msgcode); + printk(KERN_WARNING "Unknown mgmt request message 0x%08x", + msg->msgcode); break; } - DBFEXIT; return result; } - /*---------------------------------------------------------------- * prism2sta_ifstate * @@ -486,16 +442,14 @@ static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg) ----------------------------------------------------------------*/ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; - u32 result; - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + u32 result; result = P80211ENUM_resultcode_implementation_failure; - WLAN_LOG_DEBUG(2, "Current MSD state(%d), requesting(%d)\n", - wlandev->msdstate, ifstate); - switch (ifstate) - { + pr_debug("Current MSD state(%d), requesting(%d)\n", + wlandev->msdstate, ifstate); + switch (ifstate) { case P80211ENUM_ifstate_fwload: switch (wlandev->msdstate) { case WLAN_MSD_HWPRESENT: @@ -504,12 +458,12 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) * Initialize the device+driver sufficiently * for firmware loading. */ - if ((result=hfa384x_drvr_start(hw))) { - WLAN_LOG_ERROR( - "hfa384x_drvr_start() failed," - "result=%d\n", (int)result); + if ((result = hfa384x_drvr_start(hw))) { + printk(KERN_ERR + "hfa384x_drvr_start() failed," + "result=%d\n", (int)result); result = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; wlandev->msdstate = WLAN_MSD_HWPRESENT; break; } @@ -521,9 +475,9 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) result = P80211ENUM_resultcode_success; break; case WLAN_MSD_RUNNING: - WLAN_LOG_WARNING( - "Cannot enter fwload state from enable state," - "you must disable first.\n"); + printk(KERN_WARNING + "Cannot enter fwload state from enable state," + "you must disable first.\n"); result = P80211ENUM_resultcode_invalid_parameters; break; case WLAN_MSD_HWFAIL: @@ -548,32 +502,32 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) * can't make any assumptions about the state * of the hardware or a previous firmware load. */ - if ((result=hfa384x_drvr_start(hw))) { - WLAN_LOG_ERROR( - "hfa384x_drvr_start() failed," - "result=%d\n", (int)result); + if ((result = hfa384x_drvr_start(hw))) { + printk(KERN_ERR + "hfa384x_drvr_start() failed," + "result=%d\n", (int)result); result = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; wlandev->msdstate = WLAN_MSD_HWPRESENT; break; } - if ((result=prism2sta_getcardinfo(wlandev))) { - WLAN_LOG_ERROR( - "prism2sta_getcardinfo() failed," - "result=%d\n", (int)result); + if ((result = prism2sta_getcardinfo(wlandev))) { + printk(KERN_ERR + "prism2sta_getcardinfo() failed," + "result=%d\n", (int)result); result = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; hfa384x_drvr_stop(hw); wlandev->msdstate = WLAN_MSD_HWPRESENT; break; } - if ((result=prism2sta_globalsetup(wlandev))) { - WLAN_LOG_ERROR( - "prism2sta_globalsetup() failed," - "result=%d\n", (int)result); + if ((result = prism2sta_globalsetup(wlandev))) { + printk(KERN_ERR + "prism2sta_globalsetup() failed," + "result=%d\n", (int)result); result = - P80211ENUM_resultcode_implementation_failure; + P80211ENUM_resultcode_implementation_failure; hfa384x_drvr_stop(hw); wlandev->msdstate = WLAN_MSD_HWPRESENT; break; @@ -584,7 +538,7 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) result = P80211ENUM_resultcode_success; break; case WLAN_MSD_RUNNING: - /* Do nothing, we're already in this state.*/ + /* Do nothing, we're already in this state. */ result = P80211ENUM_resultcode_success; break; case WLAN_MSD_HWFAIL: @@ -599,7 +553,7 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) case P80211ENUM_ifstate_disable: switch (wlandev->msdstate) { case WLAN_MSD_HWPRESENT: - /* Do nothing, we're already in this state.*/ + /* Do nothing, we're already in this state. */ result = P80211ENUM_resultcode_success; break; case WLAN_MSD_FWLOAD: @@ -634,11 +588,9 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) break; } - DBFEXIT; return result; } - /*---------------------------------------------------------------- * prism2sta_getcardinfo * @@ -660,269 +612,284 @@ u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) ----------------------------------------------------------------*/ static int prism2sta_getcardinfo(wlandevice_t *wlandev) { - int result = 0; - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; - u16 temp; - u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN]; - char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1]; - - DBFENTER; + int result = 0; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + u16 temp; + u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN]; + char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1]; /* Collect version and compatibility info */ /* Some are critical, some are not */ /* NIC identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY, - &hw->ident_nic, sizeof(hfa384x_compident_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve NICIDENTITY\n"); + &hw->ident_nic, + sizeof(hfa384x_compident_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve NICIDENTITY\n"); goto failed; } /* get all the nic id fields in host byte order */ - hw->ident_nic.id = hfa384x2host_16(hw->ident_nic.id); - hw->ident_nic.variant = hfa384x2host_16(hw->ident_nic.variant); - hw->ident_nic.major = hfa384x2host_16(hw->ident_nic.major); - hw->ident_nic.minor = hfa384x2host_16(hw->ident_nic.minor); + hw->ident_nic.id = le16_to_cpu(hw->ident_nic.id); + hw->ident_nic.variant = le16_to_cpu(hw->ident_nic.variant); + hw->ident_nic.major = le16_to_cpu(hw->ident_nic.major); + hw->ident_nic.minor = le16_to_cpu(hw->ident_nic.minor); - WLAN_LOG_INFO( "ident: nic h/w: id=0x%02x %d.%d.%d\n", - hw->ident_nic.id, hw->ident_nic.major, - hw->ident_nic.minor, hw->ident_nic.variant); + printk(KERN_INFO "ident: nic h/w: id=0x%02x %d.%d.%d\n", + hw->ident_nic.id, hw->ident_nic.major, + hw->ident_nic.minor, hw->ident_nic.variant); /* Primary f/w identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY, - &hw->ident_pri_fw, sizeof(hfa384x_compident_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve PRIIDENTITY\n"); + &hw->ident_pri_fw, + sizeof(hfa384x_compident_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve PRIIDENTITY\n"); goto failed; } /* get all the private fw id fields in host byte order */ - hw->ident_pri_fw.id = hfa384x2host_16(hw->ident_pri_fw.id); - hw->ident_pri_fw.variant = hfa384x2host_16(hw->ident_pri_fw.variant); - hw->ident_pri_fw.major = hfa384x2host_16(hw->ident_pri_fw.major); - hw->ident_pri_fw.minor = hfa384x2host_16(hw->ident_pri_fw.minor); + hw->ident_pri_fw.id = le16_to_cpu(hw->ident_pri_fw.id); + hw->ident_pri_fw.variant = le16_to_cpu(hw->ident_pri_fw.variant); + hw->ident_pri_fw.major = le16_to_cpu(hw->ident_pri_fw.major); + hw->ident_pri_fw.minor = le16_to_cpu(hw->ident_pri_fw.minor); - WLAN_LOG_INFO( "ident: pri f/w: id=0x%02x %d.%d.%d\n", - hw->ident_pri_fw.id, hw->ident_pri_fw.major, - hw->ident_pri_fw.minor, hw->ident_pri_fw.variant); + printk(KERN_INFO "ident: pri f/w: id=0x%02x %d.%d.%d\n", + hw->ident_pri_fw.id, hw->ident_pri_fw.major, + hw->ident_pri_fw.minor, hw->ident_pri_fw.variant); /* Station (Secondary?) f/w identity */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY, - &hw->ident_sta_fw, sizeof(hfa384x_compident_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve STAIDENTITY\n"); + &hw->ident_sta_fw, + sizeof(hfa384x_compident_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve STAIDENTITY\n"); goto failed; } if (hw->ident_nic.id < 0x8000) { - WLAN_LOG_ERROR("FATAL: Card is not an Intersil Prism2/2.5/3\n"); + printk(KERN_ERR + "FATAL: Card is not an Intersil Prism2/2.5/3\n"); result = -1; goto failed; } /* get all the station fw id fields in host byte order */ - hw->ident_sta_fw.id = hfa384x2host_16(hw->ident_sta_fw.id); - hw->ident_sta_fw.variant = hfa384x2host_16(hw->ident_sta_fw.variant); - hw->ident_sta_fw.major = hfa384x2host_16(hw->ident_sta_fw.major); - hw->ident_sta_fw.minor = hfa384x2host_16(hw->ident_sta_fw.minor); + hw->ident_sta_fw.id = le16_to_cpu(hw->ident_sta_fw.id); + hw->ident_sta_fw.variant = le16_to_cpu(hw->ident_sta_fw.variant); + hw->ident_sta_fw.major = le16_to_cpu(hw->ident_sta_fw.major); + hw->ident_sta_fw.minor = le16_to_cpu(hw->ident_sta_fw.minor); /* strip out the 'special' variant bits */ - hw->mm_mods = hw->ident_sta_fw.variant & (BIT14 | BIT15); - hw->ident_sta_fw.variant &= ~((u16)(BIT14 | BIT15)); + hw->mm_mods = hw->ident_sta_fw.variant & (BIT(14) | BIT(15)); + hw->ident_sta_fw.variant &= ~((u16) (BIT(14) | BIT(15))); - if ( hw->ident_sta_fw.id == 0x1f ) { - WLAN_LOG_INFO( - "ident: sta f/w: id=0x%02x %d.%d.%d\n", - hw->ident_sta_fw.id, hw->ident_sta_fw.major, - hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + if (hw->ident_sta_fw.id == 0x1f) { + printk(KERN_INFO + "ident: sta f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); } else { - WLAN_LOG_INFO( - "ident: ap f/w: id=0x%02x %d.%d.%d\n", - hw->ident_sta_fw.id, hw->ident_sta_fw.major, - hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); - WLAN_LOG_ERROR("Unsupported Tertiary AP firmeare loaded!\n"); + printk(KERN_INFO + "ident: ap f/w: id=0x%02x %d.%d.%d\n", + hw->ident_sta_fw.id, hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); + printk(KERN_ERR "Unsupported Tertiary AP firmeare loaded!\n"); goto failed; } /* Compatibility range, Modem supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE, - &hw->cap_sup_mfi, sizeof(hfa384x_caplevel_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve MFISUPRANGE\n"); + &hw->cap_sup_mfi, + sizeof(hfa384x_caplevel_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve MFISUPRANGE\n"); goto failed; } /* get all the Compatibility range, modem interface supplier - fields in byte order */ - hw->cap_sup_mfi.role = hfa384x2host_16(hw->cap_sup_mfi.role); - hw->cap_sup_mfi.id = hfa384x2host_16(hw->cap_sup_mfi.id); - hw->cap_sup_mfi.variant = hfa384x2host_16(hw->cap_sup_mfi.variant); - hw->cap_sup_mfi.bottom = hfa384x2host_16(hw->cap_sup_mfi.bottom); - hw->cap_sup_mfi.top = hfa384x2host_16(hw->cap_sup_mfi.top); + fields in byte order */ + hw->cap_sup_mfi.role = le16_to_cpu(hw->cap_sup_mfi.role); + hw->cap_sup_mfi.id = le16_to_cpu(hw->cap_sup_mfi.id); + hw->cap_sup_mfi.variant = le16_to_cpu(hw->cap_sup_mfi.variant); + hw->cap_sup_mfi.bottom = le16_to_cpu(hw->cap_sup_mfi.bottom); + hw->cap_sup_mfi.top = le16_to_cpu(hw->cap_sup_mfi.top); - WLAN_LOG_INFO( - "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_sup_mfi.role, hw->cap_sup_mfi.id, - hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom, - hw->cap_sup_mfi.top); + printk(KERN_INFO + "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_mfi.role, hw->cap_sup_mfi.id, + hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom, + hw->cap_sup_mfi.top); /* Compatibility range, Controller supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE, - &hw->cap_sup_cfi, sizeof(hfa384x_caplevel_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve CFISUPRANGE\n"); + &hw->cap_sup_cfi, + sizeof(hfa384x_caplevel_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve CFISUPRANGE\n"); goto failed; } /* get all the Compatibility range, controller interface supplier - fields in byte order */ - hw->cap_sup_cfi.role = hfa384x2host_16(hw->cap_sup_cfi.role); - hw->cap_sup_cfi.id = hfa384x2host_16(hw->cap_sup_cfi.id); - hw->cap_sup_cfi.variant = hfa384x2host_16(hw->cap_sup_cfi.variant); - hw->cap_sup_cfi.bottom = hfa384x2host_16(hw->cap_sup_cfi.bottom); - hw->cap_sup_cfi.top = hfa384x2host_16(hw->cap_sup_cfi.top); + fields in byte order */ + hw->cap_sup_cfi.role = le16_to_cpu(hw->cap_sup_cfi.role); + hw->cap_sup_cfi.id = le16_to_cpu(hw->cap_sup_cfi.id); + hw->cap_sup_cfi.variant = le16_to_cpu(hw->cap_sup_cfi.variant); + hw->cap_sup_cfi.bottom = le16_to_cpu(hw->cap_sup_cfi.bottom); + hw->cap_sup_cfi.top = le16_to_cpu(hw->cap_sup_cfi.top); - WLAN_LOG_INFO( - "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_sup_cfi.role, hw->cap_sup_cfi.id, - hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom, - hw->cap_sup_cfi.top); + printk(KERN_INFO + "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_cfi.role, hw->cap_sup_cfi.id, + hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom, + hw->cap_sup_cfi.top); /* Compatibility range, Primary f/w supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE, - &hw->cap_sup_pri, sizeof(hfa384x_caplevel_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve PRISUPRANGE\n"); + &hw->cap_sup_pri, + sizeof(hfa384x_caplevel_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve PRISUPRANGE\n"); goto failed; } /* get all the Compatibility range, primary firmware supplier - fields in byte order */ - hw->cap_sup_pri.role = hfa384x2host_16(hw->cap_sup_pri.role); - hw->cap_sup_pri.id = hfa384x2host_16(hw->cap_sup_pri.id); - hw->cap_sup_pri.variant = hfa384x2host_16(hw->cap_sup_pri.variant); - hw->cap_sup_pri.bottom = hfa384x2host_16(hw->cap_sup_pri.bottom); - hw->cap_sup_pri.top = hfa384x2host_16(hw->cap_sup_pri.top); + fields in byte order */ + hw->cap_sup_pri.role = le16_to_cpu(hw->cap_sup_pri.role); + hw->cap_sup_pri.id = le16_to_cpu(hw->cap_sup_pri.id); + hw->cap_sup_pri.variant = le16_to_cpu(hw->cap_sup_pri.variant); + hw->cap_sup_pri.bottom = le16_to_cpu(hw->cap_sup_pri.bottom); + hw->cap_sup_pri.top = le16_to_cpu(hw->cap_sup_pri.top); - WLAN_LOG_INFO( - "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_sup_pri.role, hw->cap_sup_pri.id, - hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom, - hw->cap_sup_pri.top); + printk(KERN_INFO + "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_pri.role, hw->cap_sup_pri.id, + hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom, + hw->cap_sup_pri.top); /* Compatibility range, Station f/w supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE, - &hw->cap_sup_sta, sizeof(hfa384x_caplevel_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve STASUPRANGE\n"); + &hw->cap_sup_sta, + sizeof(hfa384x_caplevel_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve STASUPRANGE\n"); goto failed; } /* get all the Compatibility range, station firmware supplier - fields in byte order */ - hw->cap_sup_sta.role = hfa384x2host_16(hw->cap_sup_sta.role); - hw->cap_sup_sta.id = hfa384x2host_16(hw->cap_sup_sta.id); - hw->cap_sup_sta.variant = hfa384x2host_16(hw->cap_sup_sta.variant); - hw->cap_sup_sta.bottom = hfa384x2host_16(hw->cap_sup_sta.bottom); - hw->cap_sup_sta.top = hfa384x2host_16(hw->cap_sup_sta.top); + fields in byte order */ + hw->cap_sup_sta.role = le16_to_cpu(hw->cap_sup_sta.role); + hw->cap_sup_sta.id = le16_to_cpu(hw->cap_sup_sta.id); + hw->cap_sup_sta.variant = le16_to_cpu(hw->cap_sup_sta.variant); + hw->cap_sup_sta.bottom = le16_to_cpu(hw->cap_sup_sta.bottom); + hw->cap_sup_sta.top = le16_to_cpu(hw->cap_sup_sta.top); - if ( hw->cap_sup_sta.id == 0x04 ) { - WLAN_LOG_INFO( - "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_sup_sta.role, hw->cap_sup_sta.id, - hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, - hw->cap_sup_sta.top); + if (hw->cap_sup_sta.id == 0x04) { + printk(KERN_INFO + "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_sta.role, hw->cap_sup_sta.id, + hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, + hw->cap_sup_sta.top); } else { - WLAN_LOG_INFO( - "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_sup_sta.role, hw->cap_sup_sta.id, - hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, - hw->cap_sup_sta.top); + printk(KERN_INFO + "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_sup_sta.role, hw->cap_sup_sta.id, + hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom, + hw->cap_sup_sta.top); } /* Compatibility range, primary f/w actor, CFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES, - &hw->cap_act_pri_cfi, sizeof(hfa384x_caplevel_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve PRI_CFIACTRANGES\n"); + &hw->cap_act_pri_cfi, + sizeof(hfa384x_caplevel_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve PRI_CFIACTRANGES\n"); goto failed; } /* get all the Compatibility range, primary f/w actor, CFI supplier - fields in byte order */ - hw->cap_act_pri_cfi.role = hfa384x2host_16(hw->cap_act_pri_cfi.role); - hw->cap_act_pri_cfi.id = hfa384x2host_16(hw->cap_act_pri_cfi.id); - hw->cap_act_pri_cfi.variant = hfa384x2host_16(hw->cap_act_pri_cfi.variant); - hw->cap_act_pri_cfi.bottom = hfa384x2host_16(hw->cap_act_pri_cfi.bottom); - hw->cap_act_pri_cfi.top = hfa384x2host_16(hw->cap_act_pri_cfi.top); + fields in byte order */ + hw->cap_act_pri_cfi.role = le16_to_cpu(hw->cap_act_pri_cfi.role); + hw->cap_act_pri_cfi.id = le16_to_cpu(hw->cap_act_pri_cfi.id); + hw->cap_act_pri_cfi.variant = + le16_to_cpu(hw->cap_act_pri_cfi.variant); + hw->cap_act_pri_cfi.bottom = + le16_to_cpu(hw->cap_act_pri_cfi.bottom); + hw->cap_act_pri_cfi.top = le16_to_cpu(hw->cap_act_pri_cfi.top); - WLAN_LOG_INFO( - "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id, - hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom, - hw->cap_act_pri_cfi.top); + printk(KERN_INFO + "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id, + hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom, + hw->cap_act_pri_cfi.top); /* Compatibility range, sta f/w actor, CFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES, - &hw->cap_act_sta_cfi, sizeof(hfa384x_caplevel_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve STA_CFIACTRANGES\n"); + &hw->cap_act_sta_cfi, + sizeof(hfa384x_caplevel_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve STA_CFIACTRANGES\n"); goto failed; } /* get all the Compatibility range, station f/w actor, CFI supplier - fields in byte order */ - hw->cap_act_sta_cfi.role = hfa384x2host_16(hw->cap_act_sta_cfi.role); - hw->cap_act_sta_cfi.id = hfa384x2host_16(hw->cap_act_sta_cfi.id); - hw->cap_act_sta_cfi.variant = hfa384x2host_16(hw->cap_act_sta_cfi.variant); - hw->cap_act_sta_cfi.bottom = hfa384x2host_16(hw->cap_act_sta_cfi.bottom); - hw->cap_act_sta_cfi.top = hfa384x2host_16(hw->cap_act_sta_cfi.top); + fields in byte order */ + hw->cap_act_sta_cfi.role = le16_to_cpu(hw->cap_act_sta_cfi.role); + hw->cap_act_sta_cfi.id = le16_to_cpu(hw->cap_act_sta_cfi.id); + hw->cap_act_sta_cfi.variant = + le16_to_cpu(hw->cap_act_sta_cfi.variant); + hw->cap_act_sta_cfi.bottom = + le16_to_cpu(hw->cap_act_sta_cfi.bottom); + hw->cap_act_sta_cfi.top = le16_to_cpu(hw->cap_act_sta_cfi.top); - WLAN_LOG_INFO( - "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id, - hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom, - hw->cap_act_sta_cfi.top); + printk(KERN_INFO + "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id, + hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom, + hw->cap_act_sta_cfi.top); /* Compatibility range, sta f/w actor, MFI supplier */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES, - &hw->cap_act_sta_mfi, sizeof(hfa384x_caplevel_t)); - if ( result ) { - WLAN_LOG_ERROR("Failed to retrieve STA_MFIACTRANGES\n"); + &hw->cap_act_sta_mfi, + sizeof(hfa384x_caplevel_t)); + if (result) { + printk(KERN_ERR "Failed to retrieve STA_MFIACTRANGES\n"); goto failed; } /* get all the Compatibility range, station f/w actor, MFI supplier - fields in byte order */ - hw->cap_act_sta_mfi.role = hfa384x2host_16(hw->cap_act_sta_mfi.role); - hw->cap_act_sta_mfi.id = hfa384x2host_16(hw->cap_act_sta_mfi.id); - hw->cap_act_sta_mfi.variant = hfa384x2host_16(hw->cap_act_sta_mfi.variant); - hw->cap_act_sta_mfi.bottom = hfa384x2host_16(hw->cap_act_sta_mfi.bottom); - hw->cap_act_sta_mfi.top = hfa384x2host_16(hw->cap_act_sta_mfi.top); + fields in byte order */ + hw->cap_act_sta_mfi.role = le16_to_cpu(hw->cap_act_sta_mfi.role); + hw->cap_act_sta_mfi.id = le16_to_cpu(hw->cap_act_sta_mfi.id); + hw->cap_act_sta_mfi.variant = + le16_to_cpu(hw->cap_act_sta_mfi.variant); + hw->cap_act_sta_mfi.bottom = + le16_to_cpu(hw->cap_act_sta_mfi.bottom); + hw->cap_act_sta_mfi.top = le16_to_cpu(hw->cap_act_sta_mfi.top); - WLAN_LOG_INFO( - "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", - hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id, - hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom, - hw->cap_act_sta_mfi.top); + printk(KERN_INFO + "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n", + hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id, + hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom, + hw->cap_act_sta_mfi.top); /* Serial Number */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, - snum, HFA384x_RID_NICSERIALNUMBER_LEN); - if ( !result ) { + snum, HFA384x_RID_NICSERIALNUMBER_LEN); + if (!result) { wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN, pstr, sizeof(pstr)); - WLAN_LOG_INFO("Prism2 card SN: %s\n", pstr); + printk(KERN_INFO "Prism2 card SN: %s\n", pstr); } else { - WLAN_LOG_ERROR("Failed to retrieve Prism2 Card SN\n"); + printk(KERN_ERR "Failed to retrieve Prism2 Card SN\n"); goto failed; } /* Collect the MAC address */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNMACADDR, - wlandev->netdev->dev_addr, WLAN_ADDR_LEN); - if ( result != 0 ) { - WLAN_LOG_ERROR("Failed to retrieve mac address\n"); + wlandev->netdev->dev_addr, ETH_ALEN); + if (result != 0) { + printk(KERN_ERR "Failed to retrieve mac address\n"); goto failed; } @@ -939,10 +906,10 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) hw->dbmadjust = temp; /* Only enable scan by default on newer firmware */ - if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, - hw->ident_sta_fw.minor, - hw->ident_sta_fw.variant) < - HFA384x_FIRMWARE_VERSION(1,5,5)) { + if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, + hw->ident_sta_fw.minor, + hw->ident_sta_fw.variant) < + HFA384x_FIRMWARE_VERSION(1, 5, 5)) { wlandev->nsdcaps |= P80211_NSDCAP_NOSCAN; } @@ -950,13 +917,11 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) goto done; failed: - WLAN_LOG_ERROR("Failed, result=%d\n", result); + printk(KERN_ERR "Failed, result=%d\n", result); done: - DBFEXIT; return result; } - /*---------------------------------------------------------------- * prism2sta_globalsetup * @@ -977,43 +942,33 @@ done: ----------------------------------------------------------------*/ static int prism2sta_globalsetup(wlandevice_t *wlandev) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; /* Set the maximum frame size */ return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, - WLAN_DATA_MAXLEN); + WLAN_DATA_MAXLEN); } static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev) { int result = 0; - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; - u16 promisc; - - DBFENTER; + u16 promisc; /* If we're not ready, what's the point? */ - if ( hw->state != HFA384x_STATE_RUNNING ) + if (hw->state != HFA384x_STATE_RUNNING) goto exit; - if ( (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0 ) + if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) promisc = P80211ENUM_truth_true; else promisc = P80211ENUM_truth_false; - result = hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE, promisc); - - /* XXX TODO: configure the multicast list */ - // CLEAR_HW_MULTICAST_LIST - // struct dev_mc_list element = dev->mc_list; - // while (element != null) { - // HW_ADD_MULTICAST_ADDR(element->dmi_addr, dmi_addrlen) - // element = element->next; - // } - - exit: - DBFEXIT; + result = + hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE, + promisc); +exit: return result; } @@ -1035,15 +990,13 @@ static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev) * Call context: * interrupt ----------------------------------------------------------------*/ -static void prism2sta_inf_handover(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +static void prism2sta_inf_handover(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) { - DBFENTER; - WLAN_LOG_DEBUG(2,"received infoframe:HANDOVER (unhandled)\n"); - DBFEXIT; + pr_debug("received infoframe:HANDOVER (unhandled)\n"); return; } - /*---------------------------------------------------------------- * prism2sta_inf_tallies * @@ -1061,37 +1014,34 @@ static void prism2sta_inf_handover(wlandevice_t *wlandev, hfa384x_InfFrame_t *in * Call context: * interrupt ----------------------------------------------------------------*/ -static void prism2sta_inf_tallies(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) +static void prism2sta_inf_tallies(wlandevice_t *wlandev, + hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; - u16 *src16; - u32 *dst; - u32 *src32; - int i; - int cnt; - - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + u16 *src16; + u32 *dst; + u32 *src32; + int i; + int cnt; /* - ** Determine if these are 16-bit or 32-bit tallies, based on the - ** record length of the info record. - */ + ** Determine if these are 16-bit or 32-bit tallies, based on the + ** record length of the info record. + */ cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(u32); if (inf->framelen > 22) { - dst = (u32 *) &hw->tallies; - src32 = (u32 *) &inf->info.commtallies32; + dst = (u32 *)&hw->tallies; + src32 = (u32 *)&inf->info.commtallies32; for (i = 0; i < cnt; i++, dst++, src32++) - *dst += hfa384x2host_32(*src32); + *dst += le32_to_cpu(*src32); } else { - dst = (u32 *) &hw->tallies; - src16 = (u16 *) &inf->info.commtallies16; + dst = (u32 *)&hw->tallies; + src16 = (u16 *)&inf->info.commtallies16; for (i = 0; i < cnt; i++, dst++, src16++) - *dst += hfa384x2host_16(*src16); + *dst += le16_to_cpu(*src16); } - DBFEXIT; - return; } @@ -1116,44 +1066,40 @@ static void prism2sta_inf_scanresults(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; - int nbss; - hfa384x_ScanResult_t *sr = &(inf->info.scanresult); - int i; - hfa384x_JoinRequest_data_t joinreq; - int result; - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + int nbss; + hfa384x_ScanResult_t *sr = &(inf->info.scanresult); + int i; + hfa384x_JoinRequest_data_t joinreq; + int result; /* Get the number of results, first in bytes, then in results */ nbss = (inf->framelen * sizeof(u16)) - - sizeof(inf->infotype) - - sizeof(inf->info.scanresult.scanreason); + sizeof(inf->infotype) - sizeof(inf->info.scanresult.scanreason); nbss /= sizeof(hfa384x_ScanResultSub_t); /* Print em */ - WLAN_LOG_DEBUG(1,"rx scanresults, reason=%d, nbss=%d:\n", - inf->info.scanresult.scanreason, nbss); - for ( i = 0; i < nbss; i++) { - WLAN_LOG_DEBUG(1, "chid=%d anl=%d sl=%d bcnint=%d\n", - sr->result[i].chid, - sr->result[i].anl, - sr->result[i].sl, - sr->result[i].bcnint); - WLAN_LOG_DEBUG(1, " capinfo=0x%04x proberesp_rate=%d\n", - sr->result[i].capinfo, - sr->result[i].proberesp_rate); + pr_debug("rx scanresults, reason=%d, nbss=%d:\n", + inf->info.scanresult.scanreason, nbss); + for (i = 0; i < nbss; i++) { + pr_debug("chid=%d anl=%d sl=%d bcnint=%d\n", + sr->result[i].chid, + sr->result[i].anl, + sr->result[i].sl, sr->result[i].bcnint); + pr_debug(" capinfo=0x%04x proberesp_rate=%d\n", + sr->result[i].capinfo, sr->result[i].proberesp_rate); } /* issue a join request */ joinreq.channel = sr->result[0].chid; - memcpy( joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN); - result = hfa384x_drvr_setconfig( hw, - HFA384x_RID_JOINREQUEST, - &joinreq, HFA384x_RID_JOINREQUEST_LEN); + memcpy(joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN); + result = hfa384x_drvr_setconfig(hw, + HFA384x_RID_JOINREQUEST, + &joinreq, HFA384x_RID_JOINREQUEST_LEN); if (result) { - WLAN_LOG_ERROR("setconfig(joinreq) failed, result=%d\n", result); + printk(KERN_ERR "setconfig(joinreq) failed, result=%d\n", + result); } - DBFEXIT; return; } @@ -1177,18 +1123,16 @@ static void prism2sta_inf_scanresults(wlandevice_t *wlandev, static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; - int nbss; - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + int nbss; nbss = (inf->framelen - 3) / 32; - WLAN_LOG_DEBUG(1, "Received %d hostscan results\n", nbss); + pr_debug("Received %d hostscan results\n", nbss); if (nbss > 32) nbss = 32; - if (hw->scanresults) - kfree(hw->scanresults); + kfree(hw->scanresults); hw->scanresults = kmalloc(sizeof(hfa384x_InfFrame_t), GFP_ATOMIC); memcpy(hw->scanresults, inf, sizeof(hfa384x_InfFrame_t)); @@ -1196,11 +1140,9 @@ static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, if (nbss == 0) nbss = -1; - /* Notify/wake the sleeping caller. */ - hw->scanflag = nbss; - wake_up_interruptible(&hw->cmdq); - - DBFEXIT; + /* Notify/wake the sleeping caller. */ + hw->scanflag = nbss; + wake_up_interruptible(&hw->cmdq); }; /*---------------------------------------------------------------- @@ -1223,55 +1165,60 @@ static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev, static void prism2sta_inf_chinforesults(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; - unsigned int i, n; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + unsigned int i, n; - DBFENTER; hw->channel_info.results.scanchannels = - hfa384x2host_16(inf->info.chinforesult.scanchannels); -#if 0 - memcpy(&inf->info.chinforesult, &hw->channel_info.results, sizeof(hfa384x_ChInfoResult_t)); -#endif + le16_to_cpu(inf->info.chinforesult.scanchannels); - for (i=0, n=0; ichannel_info.results.scanchannels & (1<info.chinforesult.result[n].chid)-1; - hfa384x_ChInfoResultSub_t *chinforesult=&hw->channel_info.results.result[channel]; - chinforesult->chid = channel; - chinforesult->anl = hfa384x2host_16(inf->info.chinforesult.result[n].anl); - chinforesult->pnl = hfa384x2host_16(inf->info.chinforesult.result[n].pnl); - chinforesult->active = hfa384x2host_16(inf->info.chinforesult.result[n].active); - WLAN_LOG_DEBUG(2, "chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n", - channel+1, - chinforesult->active & - HFA384x_CHINFORESULT_BSSACTIVE ? "signal" : "noise", - chinforesult->anl, chinforesult->pnl, - chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE ? 1 : 0 - ); + for (i = 0, n = 0; i < HFA384x_CHINFORESULT_MAX; i++) { + if (hw->channel_info.results.scanchannels & (1 << i)) { + int channel = + le16_to_cpu(inf->info.chinforesult.result[n]. + chid) - 1; + hfa384x_ChInfoResultSub_t *chinforesult = + &hw->channel_info.results.result[channel]; + chinforesult->chid = channel; + chinforesult->anl = + le16_to_cpu(inf->info.chinforesult.result[n]. + anl); + chinforesult->pnl = + le16_to_cpu(inf->info.chinforesult.result[n]. + pnl); + chinforesult->active = + le16_to_cpu(inf->info.chinforesult.result[n]. + active); + printk(KERN_DEBUG + "chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n", + channel + 1, + chinforesult-> + active & HFA384x_CHINFORESULT_BSSACTIVE ? + "signal" : "noise", chinforesult->anl, + chinforesult->pnl, + chinforesult-> + active & HFA384x_CHINFORESULT_PCFACTIVE ? 1 : 0); n++; } } atomic_set(&hw->channel_info.done, 2); hw->channel_info.count = n; - DBFEXIT; return; } void prism2sta_processing_defer(struct work_struct *data) { - hfa384x_t *hw = container_of(data, struct hfa384x, link_bh); - wlandevice_t *wlandev = hw->wlandev; + hfa384x_t *hw = container_of(data, struct hfa384x, link_bh); + wlandevice_t *wlandev = hw->wlandev; hfa384x_bytestr32_t ssid; - int result; + int result; - DBFENTER; /* First let's process the auth frames */ { - struct sk_buff *skb; + struct sk_buff *skb; hfa384x_InfFrame_t *inf; - while ( (skb = skb_dequeue(&hw->authq)) ) { + while ((skb = skb_dequeue(&hw->authq))) { inf = (hfa384x_InfFrame_t *) skb->data; prism2sta_inf_authreq_defer(wlandev, inf); } @@ -1284,7 +1231,7 @@ void prism2sta_processing_defer(struct work_struct *data) hw->link_status = hw->link_status_new; - switch(hw->link_status) { + switch (hw->link_status) { case HFA384x_LINK_NOTCONNECTED: /* I'm currently assuming that this is the initial link * state. It should only be possible immediately @@ -1294,7 +1241,7 @@ void prism2sta_processing_defer(struct work_struct *data) */ netif_carrier_off(wlandev->netdev); - WLAN_LOG_INFO("linkstatus=NOTCONNECTED (unhandled)\n"); + printk(KERN_INFO "linkstatus=NOTCONNECTED (unhandled)\n"); break; case HFA384x_LINK_CONNECTED: @@ -1311,53 +1258,56 @@ void prism2sta_processing_defer(struct work_struct *data) netif_carrier_on(wlandev->netdev); /* If we are joining a specific AP, set our state and reset retries */ - if(hw->join_ap == 1) + if (hw->join_ap == 1) hw->join_ap = 2; hw->join_retries = 60; /* Don't call this in monitor mode */ - if ( wlandev->netdev->type == ARPHRD_ETHER ) { - u16 portstatus; + if (wlandev->netdev->type == ARPHRD_ETHER) { + u16 portstatus; - WLAN_LOG_INFO("linkstatus=CONNECTED\n"); + printk(KERN_INFO "linkstatus=CONNECTED\n"); /* For non-usb devices, we can use the sync versions */ /* Collect the BSSID, and set state to allow tx */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, - wlandev->bssid, WLAN_BSSID_LEN); - if ( result ) { - WLAN_LOG_DEBUG(1, - "getconfig(0x%02x) failed, result = %d\n", - HFA384x_RID_CURRENTBSSID, result); + wlandev->bssid, + WLAN_BSSID_LEN); + if (result) { + printk(KERN_DEBUG + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTBSSID, result); goto failed; } result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTSSID, &ssid, sizeof(ssid)); - if ( result ) { - WLAN_LOG_DEBUG(1, - "getconfig(0x%02x) failed, result = %d\n", - HFA384x_RID_CURRENTSSID, result); + if (result) { + printk(KERN_DEBUG + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTSSID, result); goto failed; } prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid, - (p80211pstrd_t *) &wlandev->ssid); + (p80211pstrd_t *)&wlandev-> + ssid); /* Collect the port status */ result = hfa384x_drvr_getconfig16(hw, - HFA384x_RID_PORTSTATUS, &portstatus); - if ( result ) { - WLAN_LOG_DEBUG(1, - "getconfig(0x%02x) failed, result = %d\n", - HFA384x_RID_PORTSTATUS, result); + HFA384x_RID_PORTSTATUS, + &portstatus); + if (result) { + printk(KERN_DEBUG + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_PORTSTATUS, result); goto failed; } wlandev->macmode = - (portstatus == HFA384x_PSTATUS_CONN_IBSS) ? - WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA; + (portstatus == HFA384x_PSTATUS_CONN_IBSS) ? + WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA; /* Get the ball rolling on the comms quality stuff */ prism2sta_commsqual_defer(&hw->commsqual_bh); @@ -1374,18 +1324,20 @@ void prism2sta_processing_defer(struct work_struct *data) * Indicate Deauthentication * Block Transmits, Ignore receives of data frames */ - if(hw->join_ap == 2) - { - hfa384x_JoinRequest_data_t joinreq; + if (hw->join_ap == 2) { + hfa384x_JoinRequest_data_t joinreq; joinreq = hw->joinreq; /* Send the join request */ - hfa384x_drvr_setconfig( hw, - HFA384x_RID_JOINREQUEST, - &joinreq, HFA384x_RID_JOINREQUEST_LEN); - WLAN_LOG_INFO("linkstatus=DISCONNECTED (re-submitting join)\n"); + hfa384x_drvr_setconfig(hw, + HFA384x_RID_JOINREQUEST, + &joinreq, + HFA384x_RID_JOINREQUEST_LEN); + printk(KERN_INFO + "linkstatus=DISCONNECTED (re-submitting join)\n"); } else { if (wlandev->netdev->type == ARPHRD_ETHER) - WLAN_LOG_INFO("linkstatus=DISCONNECTED (unhandled)\n"); + printk(KERN_INFO + "linkstatus=DISCONNECTED (unhandled)\n"); } wlandev->macmode = WLAN_MACMODE_NONE; @@ -1408,30 +1360,29 @@ void prism2sta_processing_defer(struct work_struct *data) * Indicate Reassociation * Enable Transmits, Receives and pass up data frames */ - WLAN_LOG_INFO("linkstatus=AP_CHANGE\n"); + printk(KERN_INFO "linkstatus=AP_CHANGE\n"); result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, wlandev->bssid, WLAN_BSSID_LEN); - if ( result ) { - WLAN_LOG_DEBUG(1, - "getconfig(0x%02x) failed, result = %d\n", - HFA384x_RID_CURRENTBSSID, result); + if (result) { + printk(KERN_DEBUG + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTBSSID, result); goto failed; } result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTSSID, &ssid, sizeof(ssid)); - if ( result ) { - WLAN_LOG_DEBUG(1, - "getconfig(0x%02x) failed, result = %d\n", - HFA384x_RID_CURRENTSSID, result); + if (result) { + printk(KERN_DEBUG + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTSSID, result); goto failed; } prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid, - (p80211pstrd_t *) &wlandev->ssid); - + (p80211pstrd_t *)&wlandev->ssid); hw->link_status = HFA384x_LINK_CONNECTED; netif_carrier_on(wlandev->netdev); @@ -1450,7 +1401,7 @@ void prism2sta_processing_defer(struct work_struct *data) * Response: * Block Transmits, Ignore receives of data frames */ - WLAN_LOG_INFO("linkstatus=AP_OUTOFRANGE (unhandled)\n"); + printk(KERN_INFO "linkstatus=AP_OUTOFRANGE (unhandled)\n"); netif_carrier_off(wlandev->netdev); @@ -1463,7 +1414,7 @@ void prism2sta_processing_defer(struct work_struct *data) * Response: * Enable Transmits, Receives and pass up data frames */ - WLAN_LOG_INFO("linkstatus=AP_INRANGE\n"); + printk(KERN_INFO "linkstatus=AP_INRANGE\n"); hw->link_status = HFA384x_LINK_CONNECTED; netif_carrier_on(wlandev->netdev); @@ -1479,17 +1430,18 @@ void prism2sta_processing_defer(struct work_struct *data) * Response: * Disable Transmits, Ignore receives of data frames */ - if(hw->join_ap && --hw->join_retries > 0) - { - hfa384x_JoinRequest_data_t joinreq; + if (hw->join_ap && --hw->join_retries > 0) { + hfa384x_JoinRequest_data_t joinreq; joinreq = hw->joinreq; /* Send the join request */ - hfa384x_drvr_setconfig( hw, - HFA384x_RID_JOINREQUEST, - &joinreq, HFA384x_RID_JOINREQUEST_LEN); - WLAN_LOG_INFO("linkstatus=ASSOCFAIL (re-submitting join)\n"); + hfa384x_drvr_setconfig(hw, + HFA384x_RID_JOINREQUEST, + &joinreq, + HFA384x_RID_JOINREQUEST_LEN); + printk(KERN_INFO + "linkstatus=ASSOCFAIL (re-submitting join)\n"); } else { - WLAN_LOG_INFO("linkstatus=ASSOCFAIL (unhandled)\n"); + printk(KERN_INFO "linkstatus=ASSOCFAIL (unhandled)\n"); } netif_carrier_off(wlandev->netdev); @@ -1498,8 +1450,8 @@ void prism2sta_processing_defer(struct work_struct *data) default: /* This is bad, IO port problems? */ - WLAN_LOG_WARNING( - "unknown linkstatus=0x%02x\n", hw->link_status); + printk(KERN_WARNING + "unknown linkstatus=0x%02x\n", hw->link_status); goto failed; break; } @@ -1509,8 +1461,8 @@ void prism2sta_processing_defer(struct work_struct *data) p80211wext_event_associated(wlandev, wlandev->linkstatus); #endif - failed: - DBFEXIT; +failed: + return; } /*---------------------------------------------------------------- @@ -1533,15 +1485,12 @@ void prism2sta_processing_defer(struct work_struct *data) static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; - DBFENTER; - - hw->link_status_new = hfa384x2host_16(inf->info.linkstatus.linkstatus); + hw->link_status_new = le16_to_cpu(inf->info.linkstatus.linkstatus); schedule_work(&hw->link_bh); - DBFEXIT; return; } @@ -1566,45 +1515,43 @@ static void prism2sta_inf_linkstatus(wlandevice_t *wlandev, static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; - hfa384x_AssocStatus_t rec; - int i; - - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + hfa384x_AssocStatus_t rec; + int i; memcpy(&rec, &inf->info.assocstatus, sizeof(rec)); - rec.assocstatus = hfa384x2host_16(rec.assocstatus); - rec.reason = hfa384x2host_16(rec.reason); + rec.assocstatus = le16_to_cpu(rec.assocstatus); + rec.reason = le16_to_cpu(rec.reason); /* - ** Find the address in the list of authenticated stations. If it wasn't - ** found, then this address has not been previously authenticated and - ** something weird has happened if this is anything other than an - ** "authentication failed" message. If the address was found, then - ** set the "associated" flag for that station, based on whether the - ** station is associating or losing its association. Something weird - ** has also happened if we find the address in the list of authenticated - ** stations but we are getting an "authentication failed" message. - */ + ** Find the address in the list of authenticated stations. If it wasn't + ** found, then this address has not been previously authenticated and + ** something weird has happened if this is anything other than an + ** "authentication failed" message. If the address was found, then + ** set the "associated" flag for that station, based on whether the + ** station is associating or losing its association. Something weird + ** has also happened if we find the address in the list of authenticated + ** stations but we are getting an "authentication failed" message. + */ for (i = 0; i < hw->authlist.cnt; i++) - if (memcmp(rec.sta_addr, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0) + if (memcmp(rec.sta_addr, hw->authlist.addr[i], ETH_ALEN) == 0) break; if (i >= hw->authlist.cnt) { if (rec.assocstatus != HFA384x_ASSOCSTATUS_AUTHFAIL) - WLAN_LOG_WARNING("assocstatus info frame received for non-authenticated station.\n"); + printk(KERN_WARNING + "assocstatus info frame received for non-authenticated station.\n"); } else { hw->authlist.assoc[i] = - (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC || - rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC); + (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC || + rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC); if (rec.assocstatus == HFA384x_ASSOCSTATUS_AUTHFAIL) - WLAN_LOG_WARNING("authfail assocstatus info frame received for authenticated station.\n"); + printk(KERN_WARNING + "authfail assocstatus info frame received for authenticated station.\n"); } - DBFEXIT; - return; } @@ -1630,11 +1577,9 @@ static void prism2sta_inf_assocstatus(wlandevice_t *wlandev, static void prism2sta_inf_authreq(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; struct sk_buff *skb; - DBFENTER; - skb = dev_alloc_skb(sizeof(*inf)); if (skb) { skb_put(skb, sizeof(*inf)); @@ -1642,132 +1587,129 @@ static void prism2sta_inf_authreq(wlandevice_t *wlandev, skb_queue_tail(&hw->authq, skb); schedule_work(&hw->link_bh); } - - DBFEXIT; } static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; - hfa384x_authenticateStation_data_t rec; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; + hfa384x_authenticateStation_data_t rec; - int i, added, result, cnt; - u8 *addr; - - DBFENTER; + int i, added, result, cnt; + u8 *addr; /* - ** Build the AuthenticateStation record. Initialize it for denying - ** authentication. - */ + ** Build the AuthenticateStation record. Initialize it for denying + ** authentication. + */ - memcpy(rec.address, inf->info.authreq.sta_addr, WLAN_ADDR_LEN); + memcpy(rec.address, inf->info.authreq.sta_addr, ETH_ALEN); rec.status = P80211ENUM_status_unspec_failure; /* - ** Authenticate based on the access mode. - */ + ** Authenticate based on the access mode. + */ switch (hw->accessmode) { - case WLAN_ACCESS_NONE: + case WLAN_ACCESS_NONE: - /* - ** Deny all new authentications. However, if a station - ** is ALREADY authenticated, then accept it. - */ + /* + ** Deny all new authentications. However, if a station + ** is ALREADY authenticated, then accept it. + */ - for (i = 0; i < hw->authlist.cnt; i++) - if (memcmp(rec.address, hw->authlist.addr[i], - WLAN_ADDR_LEN) == 0) { - rec.status = P80211ENUM_status_successful; - break; - } - - break; - - case WLAN_ACCESS_ALL: - - /* - ** Allow all authentications. - */ - - rec.status = P80211ENUM_status_successful; - break; - - case WLAN_ACCESS_ALLOW: - - /* - ** Only allow the authentication if the MAC address - ** is in the list of allowed addresses. - ** - ** Since this is the interrupt handler, we may be here - ** while the access list is in the middle of being - ** updated. Choose the list which is currently okay. - ** See "prism2mib_priv_accessallow()" for details. - */ - - if (hw->allow.modify == 0) { - cnt = hw->allow.cnt; - addr = hw->allow.addr[0]; - } else { - cnt = hw->allow.cnt1; - addr = hw->allow.addr1[0]; + for (i = 0; i < hw->authlist.cnt; i++) + if (memcmp(rec.address, hw->authlist.addr[i], + ETH_ALEN) == 0) { + rec.status = P80211ENUM_status_successful; + break; } - for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN) - if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) { - rec.status = P80211ENUM_status_successful; - break; - } + break; - break; + case WLAN_ACCESS_ALL: - case WLAN_ACCESS_DENY: + /* + ** Allow all authentications. + */ - /* - ** Allow the authentication UNLESS the MAC address is - ** in the list of denied addresses. - ** - ** Since this is the interrupt handler, we may be here - ** while the access list is in the middle of being - ** updated. Choose the list which is currently okay. - ** See "prism2mib_priv_accessdeny()" for details. - */ + rec.status = P80211ENUM_status_successful; + break; - if (hw->deny.modify == 0) { - cnt = hw->deny.cnt; - addr = hw->deny.addr[0]; - } else { - cnt = hw->deny.cnt1; - addr = hw->deny.addr1[0]; + case WLAN_ACCESS_ALLOW: + + /* + ** Only allow the authentication if the MAC address + ** is in the list of allowed addresses. + ** + ** Since this is the interrupt handler, we may be here + ** while the access list is in the middle of being + ** updated. Choose the list which is currently okay. + ** See "prism2mib_priv_accessallow()" for details. + */ + + if (hw->allow.modify == 0) { + cnt = hw->allow.cnt; + addr = hw->allow.addr[0]; + } else { + cnt = hw->allow.cnt1; + addr = hw->allow.addr1[0]; + } + + for (i = 0; i < cnt; i++, addr += ETH_ALEN) + if (memcmp(rec.address, addr, ETH_ALEN) == 0) { + rec.status = P80211ENUM_status_successful; + break; } - rec.status = P80211ENUM_status_successful; + break; - for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN) - if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) { - rec.status = P80211ENUM_status_unspec_failure; - break; - } + case WLAN_ACCESS_DENY: - break; + /* + ** Allow the authentication UNLESS the MAC address is + ** in the list of denied addresses. + ** + ** Since this is the interrupt handler, we may be here + ** while the access list is in the middle of being + ** updated. Choose the list which is currently okay. + ** See "prism2mib_priv_accessdeny()" for details. + */ + + if (hw->deny.modify == 0) { + cnt = hw->deny.cnt; + addr = hw->deny.addr[0]; + } else { + cnt = hw->deny.cnt1; + addr = hw->deny.addr1[0]; + } + + rec.status = P80211ENUM_status_successful; + + for (i = 0; i < cnt; i++, addr += ETH_ALEN) + if (memcmp(rec.address, addr, ETH_ALEN) == 0) { + rec.status = P80211ENUM_status_unspec_failure; + break; + } + + break; } /* - ** If the authentication is okay, then add the MAC address to the list - ** of authenticated stations. Don't add the address if it is already in - ** the list. (802.11b does not seem to disallow a station from issuing - ** an authentication request when the station is already authenticated. - ** Does this sort of thing ever happen? We might as well do the check - ** just in case.) - */ + ** If the authentication is okay, then add the MAC address to the list + ** of authenticated stations. Don't add the address if it is already in + ** the list. (802.11b does not seem to disallow a station from issuing + ** an authentication request when the station is already authenticated. + ** Does this sort of thing ever happen? We might as well do the check + ** just in case.) + */ added = 0; if (rec.status == P80211ENUM_status_successful) { for (i = 0; i < hw->authlist.cnt; i++) - if (memcmp(rec.address, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0) + if (memcmp(rec.address, hw->authlist.addr[i], ETH_ALEN) + == 0) break; if (i >= hw->authlist.cnt) { @@ -1775,7 +1717,7 @@ static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, rec.status = P80211ENUM_status_ap_full; } else { memcpy(hw->authlist.addr[hw->authlist.cnt], - rec.address, WLAN_ADDR_LEN); + rec.address, ETH_ALEN); hw->authlist.cnt++; added = 1; } @@ -1783,27 +1725,26 @@ static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, } /* - ** Send back the results of the authentication. If this doesn't work, - ** then make sure to remove the address from the authenticated list if - ** it was added. - */ + ** Send back the results of the authentication. If this doesn't work, + ** then make sure to remove the address from the authenticated list if + ** it was added. + */ - rec.status = host2hfa384x_16(rec.status); + rec.status = cpu_to_le16(rec.status); rec.algorithm = inf->info.authreq.algorithm; result = hfa384x_drvr_setconfig(hw, HFA384x_RID_AUTHENTICATESTA, - &rec, sizeof(rec)); + &rec, sizeof(rec)); if (result) { - if (added) hw->authlist.cnt--; - WLAN_LOG_ERROR("setconfig(authenticatestation) failed, result=%d\n", result); + if (added) + hw->authlist.cnt--; + printk(KERN_ERR + "setconfig(authenticatestation) failed, result=%d\n", + result); } - - DBFEXIT; - return; } - /*---------------------------------------------------------------- * prism2sta_inf_psusercnt * @@ -1825,73 +1766,13 @@ static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev, static void prism2sta_inf_psusercnt(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; + hfa384x_t *hw = (hfa384x_t *) wlandev->priv; - DBFENTER; - - hw->psusercount = hfa384x2host_16(inf->info.psusercnt.usercnt); - - DBFEXIT; + hw->psusercount = le16_to_cpu(inf->info.psusercnt.usercnt); return; } -/*---------------------------------------------------------------- -* prism2sta_ev_dtim -* -* Handles the DTIM early warning event. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ -void prism2sta_ev_dtim(wlandevice_t *wlandev) -{ -#if 0 - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; -#endif - DBFENTER; - WLAN_LOG_DEBUG(3, "DTIM event, currently unhandled.\n"); - DBFEXIT; - return; -} - - -/*---------------------------------------------------------------- -* prism2sta_ev_infdrop -* -* Handles the InfDrop event. -* -* Arguments: -* wlandev wlan device structure -* -* Returns: -* nothing -* -* Side effects: -* -* Call context: -* interrupt -----------------------------------------------------------------*/ -void prism2sta_ev_infdrop(wlandevice_t *wlandev) -{ -#if 0 - hfa384x_t *hw = (hfa384x_t *)wlandev->priv; -#endif - DBFENTER; - WLAN_LOG_DEBUG(3, "Info frame dropped due to card mem low.\n"); - DBFEXIT; - return; -} - - /*---------------------------------------------------------------- * prism2sta_ev_info * @@ -1911,56 +1792,53 @@ void prism2sta_ev_infdrop(wlandevice_t *wlandev) ----------------------------------------------------------------*/ void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) { - DBFENTER; - inf->infotype = hfa384x2host_16(inf->infotype); + inf->infotype = le16_to_cpu(inf->infotype); /* Dispatch */ - switch ( inf->infotype ) { - case HFA384x_IT_HANDOVERADDR: - prism2sta_inf_handover(wlandev, inf); - break; - case HFA384x_IT_COMMTALLIES: - prism2sta_inf_tallies(wlandev, inf); - break; - case HFA384x_IT_HOSTSCANRESULTS: - prism2sta_inf_hostscanresults(wlandev, inf); - break; - case HFA384x_IT_SCANRESULTS: - prism2sta_inf_scanresults(wlandev, inf); - break; - case HFA384x_IT_CHINFORESULTS: - prism2sta_inf_chinforesults(wlandev, inf); - break; - case HFA384x_IT_LINKSTATUS: - prism2sta_inf_linkstatus(wlandev, inf); - break; - case HFA384x_IT_ASSOCSTATUS: - prism2sta_inf_assocstatus(wlandev, inf); - break; - case HFA384x_IT_AUTHREQ: - prism2sta_inf_authreq(wlandev, inf); - break; - case HFA384x_IT_PSUSERCNT: - prism2sta_inf_psusercnt(wlandev, inf); - break; - case HFA384x_IT_KEYIDCHANGED: - WLAN_LOG_WARNING("Unhandled IT_KEYIDCHANGED\n"); - break; - case HFA384x_IT_ASSOCREQ: - WLAN_LOG_WARNING("Unhandled IT_ASSOCREQ\n"); - break; - case HFA384x_IT_MICFAILURE: - WLAN_LOG_WARNING("Unhandled IT_MICFAILURE\n"); - break; - default: - WLAN_LOG_WARNING( - "Unknown info type=0x%02x\n", inf->infotype); - break; + switch (inf->infotype) { + case HFA384x_IT_HANDOVERADDR: + prism2sta_inf_handover(wlandev, inf); + break; + case HFA384x_IT_COMMTALLIES: + prism2sta_inf_tallies(wlandev, inf); + break; + case HFA384x_IT_HOSTSCANRESULTS: + prism2sta_inf_hostscanresults(wlandev, inf); + break; + case HFA384x_IT_SCANRESULTS: + prism2sta_inf_scanresults(wlandev, inf); + break; + case HFA384x_IT_CHINFORESULTS: + prism2sta_inf_chinforesults(wlandev, inf); + break; + case HFA384x_IT_LINKSTATUS: + prism2sta_inf_linkstatus(wlandev, inf); + break; + case HFA384x_IT_ASSOCSTATUS: + prism2sta_inf_assocstatus(wlandev, inf); + break; + case HFA384x_IT_AUTHREQ: + prism2sta_inf_authreq(wlandev, inf); + break; + case HFA384x_IT_PSUSERCNT: + prism2sta_inf_psusercnt(wlandev, inf); + break; + case HFA384x_IT_KEYIDCHANGED: + printk(KERN_WARNING "Unhandled IT_KEYIDCHANGED\n"); + break; + case HFA384x_IT_ASSOCREQ: + printk(KERN_WARNING "Unhandled IT_ASSOCREQ\n"); + break; + case HFA384x_IT_MICFAILURE: + printk(KERN_WARNING "Unhandled IT_MICFAILURE\n"); + break; + default: + printk(KERN_WARNING + "Unknown info type=0x%02x\n", inf->infotype); + break; } - DBFEXIT; return; } - /*---------------------------------------------------------------- * prism2sta_ev_txexc * @@ -1982,15 +1860,11 @@ void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf) ----------------------------------------------------------------*/ void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status) { - DBFENTER; + pr_debug("TxExc status=0x%x.\n", status); - WLAN_LOG_DEBUG(3, "TxExc status=0x%x.\n", status); - - DBFEXIT; return; } - /*---------------------------------------------------------------- * prism2sta_ev_tx * @@ -2009,15 +1883,12 @@ void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status) ----------------------------------------------------------------*/ void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status) { - DBFENTER; - WLAN_LOG_DEBUG(4, "Tx Complete, status=0x%04x\n", status); + pr_debug("Tx Complete, status=0x%04x\n", status); /* update linux network stats */ wlandev->linux_stats.tx_packets++; - DBFEXIT; return; } - /*---------------------------------------------------------------- * prism2sta_ev_rx * @@ -2036,11 +1907,7 @@ void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status) ----------------------------------------------------------------*/ void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb) { - DBFENTER; - p80211netdev_rx(wlandev, skb); - - DBFEXIT; return; } @@ -2062,11 +1929,7 @@ void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb) ----------------------------------------------------------------*/ void prism2sta_ev_alloc(wlandevice_t *wlandev) { - DBFENTER; - netif_wake_queue(wlandev->netdev); - - DBFEXIT; return; } @@ -2091,17 +1954,17 @@ void prism2sta_ev_alloc(wlandevice_t *wlandev) ----------------------------------------------------------------*/ static wlandevice_t *create_wlan(void) { - wlandevice_t *wlandev = NULL; - hfa384x_t *hw = NULL; + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; - /* Alloc our structures */ - wlandev = kmalloc(sizeof(wlandevice_t), GFP_KERNEL); - hw = kmalloc(sizeof(hfa384x_t), GFP_KERNEL); + /* Alloc our structures */ + wlandev = kmalloc(sizeof(wlandevice_t), GFP_KERNEL); + hw = kmalloc(sizeof(hfa384x_t), GFP_KERNEL); if (!wlandev || !hw) { - WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); - if (wlandev) kfree(wlandev); - if (hw) kfree(hw); + printk(KERN_ERR "%s: Memory allocation failure.\n", dev_info); + kfree(wlandev); + kfree(hw); return NULL; } @@ -2121,24 +1984,21 @@ static wlandevice_t *create_wlan(void) wlandev->set_multicast_list = prism2sta_setmulticast; wlandev->tx_timeout = hfa384x_tx_timeout; - wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT | - P80211_NSDCAP_AUTOJOIN; + wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT | P80211_NSDCAP_AUTOJOIN; /* Initialize the device private data stucture. */ - hw->dot11_desired_bss_type = 1; + hw->dot11_desired_bss_type = 1; return wlandev; } void prism2sta_commsqual_defer(struct work_struct *data) { - hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh); - wlandevice_t *wlandev = hw->wlandev; + hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh); + wlandevice_t *wlandev = hw->wlandev; hfa384x_bytestr32_t ssid; int result = 0; - DBFENTER; - if (hw->wlandev->hwremoved) goto done; @@ -2155,58 +2015,49 @@ void prism2sta_commsqual_defer(struct work_struct *data) HFA384x_RID_DBMCOMMSQUALITY_LEN); if (result) { - WLAN_LOG_ERROR("error fetching commsqual\n"); + printk(KERN_ERR "error fetching commsqual\n"); goto done; } - // qual.CQ_currBSS; // link - // ASL_currBSS; // level - // qual.ANL_currFC; // noise - - WLAN_LOG_DEBUG(3, "commsqual %d %d %d\n", - hfa384x2host_16(hw->qual.CQ_currBSS), - hfa384x2host_16(hw->qual.ASL_currBSS), - hfa384x2host_16(hw->qual.ANL_currFC)); + pr_debug("commsqual %d %d %d\n", + le16_to_cpu(hw->qual.CQ_currBSS), + le16_to_cpu(hw->qual.ASL_currBSS), + le16_to_cpu(hw->qual.ANL_currFC)); } /* Lastly, we need to make sure the BSSID didn't change on us */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, wlandev->bssid, WLAN_BSSID_LEN); - if ( result ) { - WLAN_LOG_DEBUG(1, - "getconfig(0x%02x) failed, result = %d\n", - HFA384x_RID_CURRENTBSSID, result); + if (result) { + printk(KERN_DEBUG + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTBSSID, result); goto done; } result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTSSID, &ssid, sizeof(ssid)); - if ( result ) { - WLAN_LOG_DEBUG(1, - "getconfig(0x%02x) failed, result = %d\n", - HFA384x_RID_CURRENTSSID, result); + if (result) { + printk(KERN_DEBUG + "getconfig(0x%02x) failed, result = %d\n", + HFA384x_RID_CURRENTSSID, result); goto done; } prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid, - (p80211pstrd_t *) &wlandev->ssid); - + (p80211pstrd_t *)&wlandev->ssid); /* Reschedule timer */ mod_timer(&hw->commsqual_timer, jiffies + HZ); - done: - DBFEXIT; +done: + ; } void prism2sta_commsqual_timer(unsigned long data) { - hfa384x_t *hw = (hfa384x_t *) data; - - DBFENTER; + hfa384x_t *hw = (hfa384x_t *) data; schedule_work(&hw->commsqual_bh); - - DBFEXIT; } diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index 8f7b1f281f0a..d8a12982135d 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -11,44 +11,70 @@ static struct usb_device_id usb_prism_tbl[] = { {PRISM_USB_DEVICE(0x04bb, 0x0922, "IOData AirPort WN-B11/USBS")}, {PRISM_USB_DEVICE(0x07aa, 0x0012, "Corega Wireless LAN USB Stick-11")}, {PRISM_USB_DEVICE(0x09aa, 0x3642, "Prism2.x 11Mbps WLAN USB Adapter")}, - {PRISM_USB_DEVICE(0x1668, 0x0408, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")}, - {PRISM_USB_DEVICE(0x1668, 0x0421, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")}, - {PRISM_USB_DEVICE(0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps WLAN USB Adapter")}, - {PRISM_USB_DEVICE(0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps WLAN USB Adapter")}, - {PRISM_USB_DEVICE(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps WLAN USB Adapter")}, - {PRISM_USB_DEVICE(0x067c, 0x1022, "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter")}, - {PRISM_USB_DEVICE(0x049f, 0x0033, "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter")}, - {PRISM_USB_DEVICE(0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter")}, - {PRISM_USB_DEVICE(0x08de, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")}, - {PRISM_USB_DEVICE(0x8086, 0x1111, "Intel PRO/Wireless 2011B LAN USB Adapter")}, - {PRISM_USB_DEVICE(0x0d8e, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")}, - {PRISM_USB_DEVICE(0x045e, 0x006e, "Microsoft MN510 Wireless USB Adapter")}, + {PRISM_USB_DEVICE + (0x1668, 0x0408, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE + (0x1668, 0x0421, "Actiontec Prism2.5 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE + (0x1915, 0x2236, "Linksys WUSB11v3.0 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE + (0x066b, 0x2212, "Linksys WUSB11v2.5 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE + (0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE + (0x067c, 0x1022, "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE + (0x049f, 0x0033, + "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter")}, + {PRISM_USB_DEVICE + (0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter")}, + {PRISM_USB_DEVICE + (0x08de, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")}, + {PRISM_USB_DEVICE + (0x8086, 0x1111, "Intel PRO/Wireless 2011B LAN USB Adapter")}, + {PRISM_USB_DEVICE + (0x0d8e, 0x7a01, "PRISM25 IEEE 802.11 Mini USB Adapter")}, + {PRISM_USB_DEVICE + (0x045e, 0x006e, "Microsoft MN510 Wireless USB Adapter")}, {PRISM_USB_DEVICE(0x0967, 0x0204, "Acer Warplink USB Adapter")}, - {PRISM_USB_DEVICE(0x0cde, 0x0002, "Z-Com 725/726 Prism2.5 USB/USB Integrated")}, - {PRISM_USB_DEVICE(0x0cde, 0x0005, "Z-Com Xl735 Wireless 802.11b USB Adapter")}, - {PRISM_USB_DEVICE(0x413c, 0x8100, "Dell TrueMobile 1180 Wireless USB Adapter")}, - {PRISM_USB_DEVICE(0x0b3b, 0x1601, "ALLNET 0193 11Mbps WLAN USB Adapter")}, - {PRISM_USB_DEVICE(0x0b3b, 0x1602, "ZyXEL ZyAIR B200 Wireless USB Adapter")}, - {PRISM_USB_DEVICE(0x0baf, 0x00eb, "USRobotics USR1120 Wireless USB Adapter")}, - {PRISM_USB_DEVICE(0x0411, 0x0027, "Melco WLI-USB-KS11G 11Mbps WLAN Adapter")}, - {PRISM_USB_DEVICE(0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter")}, + {PRISM_USB_DEVICE + (0x0cde, 0x0002, "Z-Com 725/726 Prism2.5 USB/USB Integrated")}, + {PRISM_USB_DEVICE + (0x0cde, 0x0005, "Z-Com Xl735 Wireless 802.11b USB Adapter")}, + {PRISM_USB_DEVICE + (0x413c, 0x8100, "Dell TrueMobile 1180 Wireless USB Adapter")}, + {PRISM_USB_DEVICE + (0x0b3b, 0x1601, "ALLNET 0193 11Mbps WLAN USB Adapter")}, + {PRISM_USB_DEVICE + (0x0b3b, 0x1602, "ZyXEL ZyAIR B200 Wireless USB Adapter")}, + {PRISM_USB_DEVICE + (0x0baf, 0x00eb, "USRobotics USR1120 Wireless USB Adapter")}, + {PRISM_USB_DEVICE + (0x0411, 0x0027, "Melco WLI-USB-KS11G 11Mbps WLAN Adapter")}, + {PRISM_USB_DEVICE + (0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter")}, {PRISM_USB_DEVICE(0x0846, 0x4110, "NetGear MA111")}, - {PRISM_USB_DEVICE(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter")}, -// {PRISM_USB_DEVICE(0x0ace, 0x1201, "ZyDAS ZD1201 Wireless USB Adapter")}, + {PRISM_USB_DEVICE(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter")}, +/* {PRISM_USB_DEVICE(0x0ace, 0x1201, "ZyDAS ZD1201 Wireless USB Adapter")}, */ {PRISM_USB_DEVICE(0x2821, 0x3300, "ASUS-WL140 Wireless USB Adapter")}, {PRISM_USB_DEVICE(0x2001, 0x3700, "DWL-122 Wireless USB Adapter")}, - {PRISM_USB_DEVICE(0x2001, 0x3702, "DWL-120 Rev F Wireless USB Adapter")}, + {PRISM_USB_DEVICE + (0x2001, 0x3702, "DWL-120 Rev F Wireless USB Adapter")}, {PRISM_USB_DEVICE(0x50c2, 0x4013, "Averatec USB WLAN Adapter")}, {PRISM_USB_DEVICE(0x2c02, 0x14ea, "Planex GW-US11H WLAN USB Adapter")}, {PRISM_USB_DEVICE(0x124a, 0x168b, "Airvast PRISM3 WLAN USB Adapter")}, {PRISM_USB_DEVICE(0x083a, 0x3503, "T-Sinus 111 USB WLAN Adapter")}, {PRISM_USB_DEVICE(0x2821, 0x3300, "Hawking HighDB USB Adapter")}, - {PRISM_USB_DEVICE(0x0411, 0x0044, "Melco WLI-USB-KB11 11Mbps WLAN Adapter")}, + {PRISM_USB_DEVICE + (0x0411, 0x0044, "Melco WLI-USB-KB11 11Mbps WLAN Adapter")}, {PRISM_USB_DEVICE(0x1668, 0x6106, "ROPEX FreeLan 802.11b USB Adapter")}, - {PRISM_USB_DEVICE(0x124a, 0x4017, "Pheenet WL-503IA 802.11b USB Adapter")}, + {PRISM_USB_DEVICE + (0x124a, 0x4017, "Pheenet WL-503IA 802.11b USB Adapter")}, {PRISM_USB_DEVICE(0x0bb2, 0x0302, "Ambit Microsystems Corp.")}, - {PRISM_USB_DEVICE(0x9016, 0x182d, "Sitecom WL-022 802.11b USB Adapter")}, - {PRISM_USB_DEVICE(0x0543, 0x0f01, "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)")}, + {PRISM_USB_DEVICE + (0x9016, 0x182d, "Sitecom WL-022 802.11b USB Adapter")}, + {PRISM_USB_DEVICE + (0x0543, 0x0f01, "ViewSonic Airsync USB Adapter 11Mbps (Prism2.5)")}, { /* terminator */ } }; @@ -75,29 +101,26 @@ MODULE_DEVICE_TABLE(usb, usb_prism_tbl); * I'm not sure, assume it's interrupt. * ----------------------------------------------------------------*/ -static int prism2sta_probe_usb( - struct usb_interface *interface, - const struct usb_device_id *id) +static int prism2sta_probe_usb(struct usb_interface *interface, + const struct usb_device_id *id) { struct usb_device *dev; - wlandevice_t *wlandev = NULL; - hfa384x_t *hw = NULL; - int result = 0; - - DBFENTER; + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; + int result = 0; dev = interface_to_usbdev(interface); if ((wlandev = create_wlan()) == NULL) { - WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info); + printk(KERN_ERR "%s: Memory allocation failure.\n", dev_info); result = -EIO; goto failed; } hw = wlandev->priv; - if ( wlan_setup(wlandev) != 0 ) { - WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info); + if (wlan_setup(wlandev) != 0) { + printk(KERN_ERR "%s: wlan_setup() failed.\n", dev_info); result = -EIO; goto failed; } @@ -114,15 +137,14 @@ static int prism2sta_probe_usb( /* Do a chip-level reset on the MAC */ if (prism2_doreset) { result = hfa384x_corereset(hw, - prism2_reset_holdtime, - prism2_reset_settletime, 0); + prism2_reset_holdtime, + prism2_reset_settletime, 0); if (result != 0) { unregister_wlandev(wlandev); hfa384x_destroy(hw); result = -EIO; - WLAN_LOG_ERROR( - "%s: hfa384x_corereset() failed.\n", - dev_info); + printk(KERN_ERR + "%s: hfa384x_corereset() failed.\n", dev_info); goto failed; } } @@ -131,30 +153,28 @@ static int prism2sta_probe_usb( wlandev->msdstate = WLAN_MSD_HWPRESENT; - if ( register_wlandev(wlandev) != 0 ) { - WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info); + if (register_wlandev(wlandev) != 0) { + printk(KERN_ERR "%s: register_wlandev() failed.\n", dev_info); result = -EIO; goto failed; - } + } /* enable the card */ prism2sta_ifstate(wlandev, P80211ENUM_ifstate_enable); goto done; - failed: - if (wlandev) kfree(wlandev); - if (hw) kfree(hw); +failed: + kfree(wlandev); + kfree(hw); wlandev = NULL; - done: - DBFEXIT; - +done: + p80211_allow_ioctls(wlandev); usb_set_intfdata(interface, wlandev); return result; } - /*---------------------------------------------------------------- * prism2sta_disconnect_usb * @@ -174,22 +194,19 @@ static int prism2sta_probe_usb( * Call context: * process ----------------------------------------------------------------*/ -static void -prism2sta_disconnect_usb(struct usb_interface *interface) +static void prism2sta_disconnect_usb(struct usb_interface *interface) { - wlandevice_t *wlandev; - - DBFENTER; + wlandevice_t *wlandev; wlandev = (wlandevice_t *) usb_get_intfdata(interface); - if ( wlandev != NULL ) { + if (wlandev != NULL) { LIST_HEAD(cleanlist); - struct list_head *entry; - struct list_head *temp; - unsigned long flags; + struct list_head *entry; + struct list_head *temp; + unsigned long flags; - hfa384x_t *hw = wlandev->priv; + hfa384x_t *hw = wlandev->priv; if (!hw) goto exit; @@ -231,7 +248,7 @@ prism2sta_disconnect_usb(struct usb_interface *interface) * responses that we have shut down. */ list_for_each(entry, &cleanlist) { - hfa384x_usbctlx_t *ctlx; + hfa384x_usbctlx_t *ctlx; ctlx = list_entry(entry, hfa384x_usbctlx_t, list); complete(&ctlx->done); @@ -264,13 +281,10 @@ prism2sta_disconnect_usb(struct usb_interface *interface) kfree(wlandev); } - exit: - +exit: usb_set_intfdata(interface, NULL); - DBFEXIT; } - static struct usb_driver prism2_usb_driver = { .name = "prism2_usb", .probe = prism2sta_probe_usb, @@ -281,21 +295,13 @@ static struct usb_driver prism2_usb_driver = { static int __init prism2usb_init(void) { - DBFENTER; - /* This call will result in calls to prism2sta_probe_usb. */ return usb_register(&prism2_usb_driver); - - DBFEXIT; }; static void __exit prism2usb_cleanup(void) { - DBFENTER; - usb_deregister(&prism2_usb_driver); - - DBFEXIT; }; module_init(prism2usb_init); diff --git a/drivers/staging/wlan-ng/wlan_compat.h b/drivers/staging/wlan-ng/wlan_compat.h deleted file mode 100644 index 8b8a510685c9..000000000000 --- a/drivers/staging/wlan-ng/wlan_compat.h +++ /dev/null @@ -1,193 +0,0 @@ -/* wlan_compat.h -* -* Types and macros to aid in portability -* -* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. -* -------------------------------------------------------------------- -* -* linux-wlan -* -* The contents of this file are subject to the Mozilla Public -* License Version 1.1 (the "License"); you may not use this file -* except in compliance with the License. You may obtain a copy of -* the License at http://www.mozilla.org/MPL/ -* -* Software distributed under the License is distributed on an "AS -* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -* implied. See the License for the specific language governing -* rights and limitations under the License. -* -* Alternatively, the contents of this file may be used under the -* terms of the GNU Public License version 2 (the "GPL"), in which -* case the provisions of the GPL are applicable instead of the -* above. If you wish to allow the use of your version of this file -* only under the terms of the GPL and not to allow others to use -* your version of this file under the MPL, indicate your decision -* by deleting the provisions above and replace them with the notice -* and other provisions required by the GPL. If you do not delete -* the provisions above, a recipient may use your version of this -* file under either the MPL or the GPL. -* -* -------------------------------------------------------------------- -* -* Inquiries regarding the linux-wlan Open Source project can be -* made directly to: -* -* AbsoluteValue Systems Inc. -* info@linux-wlan.com -* http://www.linux-wlan.com -* -* -------------------------------------------------------------------- -* -* Portions of the development of this software were funded by -* Intersil Corporation as part of PRISM(R) chipset product development. -* -* -------------------------------------------------------------------- -*/ - -#ifndef _WLAN_COMPAT_H -#define _WLAN_COMPAT_H - -/*=============================================================*/ -/*------ Bit settings -----------------------------------------*/ -/*=============================================================*/ - -#define BIT0 0x00000001 -#define BIT1 0x00000002 -#define BIT2 0x00000004 -#define BIT3 0x00000008 -#define BIT4 0x00000010 -#define BIT5 0x00000020 -#define BIT6 0x00000040 -#define BIT7 0x00000080 -#define BIT8 0x00000100 -#define BIT9 0x00000200 -#define BIT10 0x00000400 -#define BIT11 0x00000800 -#define BIT12 0x00001000 -#define BIT13 0x00002000 -#define BIT14 0x00004000 -#define BIT15 0x00008000 -#define BIT16 0x00010000 -#define BIT17 0x00020000 -#define BIT18 0x00040000 -#define BIT19 0x00080000 -#define BIT20 0x00100000 -#define BIT21 0x00200000 -#define BIT22 0x00400000 -#define BIT23 0x00800000 -#define BIT24 0x01000000 -#define BIT25 0x02000000 -#define BIT26 0x04000000 -#define BIT27 0x08000000 -#define BIT28 0x10000000 -#define BIT29 0x20000000 -#define BIT30 0x40000000 -#define BIT31 0x80000000 - -/*=============================================================*/ -/*------ Compiler Portability Macros --------------------------*/ -/*=============================================================*/ -#define __WLAN_ATTRIB_PACK__ __attribute__ ((packed)) - -/*=============================================================*/ -/*------ OS Portability Macros --------------------------------*/ -/*=============================================================*/ - -#ifndef WLAN_DBVAR -#define WLAN_DBVAR wlan_debug -#endif - -#define WLAN_RELEASE "0.3.0-lkml" - -#include - -#define WLAN_LOG_ERROR(x,args...) printk(KERN_ERR "%s: " x , __func__ , ##args); - -#define WLAN_LOG_WARNING(x,args...) printk(KERN_WARNING "%s: " x , __func__ , ##args); - -#define WLAN_LOG_NOTICE(x,args...) printk(KERN_NOTICE "%s: " x , __func__ , ##args); - -#define WLAN_LOG_INFO(args... ) printk(KERN_INFO args) - -#if defined(WLAN_INCLUDE_DEBUG) - #define WLAN_HEX_DUMP( l, x, p, n) if( WLAN_DBVAR >= (l) ){ \ - int __i__; \ - printk(KERN_DEBUG x ":"); \ - for( __i__=0; __i__ < (n); __i__++) \ - printk( " %02x", ((u8*)(p))[__i__]); \ - printk("\n"); } - #define DBFENTER { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"---->\n"); } } - #define DBFEXIT { if ( WLAN_DBVAR >= 5 ){ WLAN_LOG_DEBUG(3,"<----\n"); } } - - #define WLAN_LOG_DEBUG(l,x,args...) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s(%lu): " x , __func__, (preempt_count() & PREEMPT_MASK), ##args ); -#else - #define WLAN_HEX_DUMP( l, s, p, n) - #define DBFENTER - #define DBFEXIT - - #define WLAN_LOG_DEBUG(l, s, args...) -#endif - -#undef netdevice_t -typedef struct net_device netdevice_t; - -#define URB_ASYNC_UNLINK 0 -#define USB_QUEUE_BULK 0 - -/*=============================================================*/ -/*------ Hardware Portability Macros --------------------------*/ -/*=============================================================*/ - -#define ieee2host16(n) __le16_to_cpu(n) -#define ieee2host32(n) __le32_to_cpu(n) -#define host2ieee16(n) __cpu_to_le16(n) -#define host2ieee32(n) __cpu_to_le32(n) - -/*=============================================================*/ -/*--- General Macros ------------------------------------------*/ -/*=============================================================*/ - -#define wlan_max(a, b) (((a) > (b)) ? (a) : (b)) -#define wlan_min(a, b) (((a) < (b)) ? (a) : (b)) - -#define wlan_isprint(c) (((c) > (0x19)) && ((c) < (0x7f))) - -#define wlan_hexchar(x) (((x) < 0x0a) ? ('0' + (x)) : ('a' + ((x) - 0x0a))) - -/* Create a string of printable chars from something that might not be */ -/* It's recommended that the str be 4*len + 1 bytes long */ -#define wlan_mkprintstr(buf, buflen, str, strlen) \ -{ \ - int i = 0; \ - int j = 0; \ - memset(str, 0, (strlen)); \ - for (i = 0; i < (buflen); i++) { \ - if ( wlan_isprint((buf)[i]) ) { \ - (str)[j] = (buf)[i]; \ - j++; \ - } else { \ - (str)[j] = '\\'; \ - (str)[j+1] = 'x'; \ - (str)[j+2] = wlan_hexchar(((buf)[i] & 0xf0) >> 4); \ - (str)[j+3] = wlan_hexchar(((buf)[i] & 0x0f)); \ - j += 4; \ - } \ - } \ -} - -/*=============================================================*/ -/*--- Variables -----------------------------------------------*/ -/*=============================================================*/ - -#ifdef WLAN_INCLUDE_DEBUG -extern int wlan_debug; -#endif - -extern int wlan_ethconv; /* What's the default ethconv? */ - -/*=============================================================*/ -/*--- Functions -----------------------------------------------*/ -/*=============================================================*/ -#endif /* _WLAN_COMPAT_H */ - diff --git a/firmware/Makefile b/firmware/Makefile index baf5ae45642d..16664894966d 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -49,6 +49,12 @@ fw-shipped-$(CONFIG_SND_SB16_CSP) += sb16/mulaw_main.csp sb16/alaw_main.csp \ sb16/ima_adpcm_init.csp \ sb16/ima_adpcm_playback.csp \ sb16/ima_adpcm_capture.csp +fw-shipped-$(CONFIG_SLICOSS) += slicoss/gbdownload.sys slicoss/gbrcvucode.sys \ + slicoss/oasisdbgdownload.sys \ + slicoss/oasisdownload.sys \ + slicoss/oasisrcvucode.sys +fw-shipped-$(CONFIG_SXG) += sxg/saharadownloadB.sys \ + sxg/saharadbgdownloadB.sys fw-shipped-$(CONFIG_SND_YMFPCI) += yamaha/ds1_ctrl.fw yamaha/ds1_dsp.fw \ yamaha/ds1e_ctrl.fw fw-shipped-$(CONFIG_TEHUTI) += tehuti/bdx.bin diff --git a/firmware/WHENCE b/firmware/WHENCE index 3814d7d42665..d6c227db37c2 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -364,6 +364,59 @@ Found in hex form in kernel source. -------------------------------------------------------------------------- +Driver: SLICOSS - Alacritech IS-NIC products + +File: slicoss/gbdownload.sys.ihex +File: slicoss/gbrcvucode.sys.ihex +File: slicoss/oasisdbgdownload.sys.ihex +File: slicoss/oasisdownload.sys.ihex +File: slicoss/oasisrcvucode.sys.ihex + +Licence: + Copyright (C) 1999-2009 Alacritech, Inc. + + as an unpublished work. This notice does not imply unrestricted or + public access to the source code from which this firmware image is + derived. Except as noted below this firmware image may not be + reproduced, used, sold or transferred to any third party without + Alacritech's prior written consent. All Rights Reserved. + + Permission is hereby granted for the distribution of this firmware + image as part of a Linux or other Open Source operating system kernel + in text or binary form as required. + + This firmware may not be modified and may only be used with + Alacritech hardware. + +Found in hex form in kernel source. + +-------------------------------------------------------------------------- + +Driver: SXG - Alacritech IS-NIC products + +File: sxg/saharadownloadB.sys.ihex +File: sxg/saharadbgdownloadB.sys.ihex + +Licence: + Copyright (C) 1999-2009 Alacritech, Inc. + + as an unpublished work. This notice does not imply unrestricted or + public access to the source code from which this firmware image is + derived. Except as noted below this firmware image may not be + reproduced, used, sold or transferred to any third party without + Alacritech's prior written consent. All Rights Reserved. + + Permission is hereby granted for the distribution of this firmware + image as part of a Linux or other Open Source operating system kernel + in text or binary form as required. + + This firmware may not be modified and may only be used with + Alacritech hardware. + +Found in hex form in kernel source. + +-------------------------------------------------------------------------- + Driver: cxgb3 - Chelsio Terminator 3 1G/10G Ethernet adapter File: cxgb3/t3b_psram-1.1.0.bin.ihex diff --git a/firmware/slicoss/gbdownload.sys.ihex b/firmware/slicoss/gbdownload.sys.ihex new file mode 100644 index 000000000000..dc17e639b69a --- /dev/null +++ b/firmware/slicoss/gbdownload.sys.ihex @@ -0,0 +1,6148 @@ +:10000000020000000080000000000100000000006D +:10001000008000001200004081B200001800004083 +:1000200081B200001E00004081B2000003000040C9 +:1000300081B20000000000A898B001000480A24036 +:10004000FD7F00000900A249DD7D00000000004C9A +:1000500080B2010007000040D1B100000000004C58 +:1000600080B201000900A240757D000060000040E0 +:10007000619901000B00A8B17E3100000900004029 +:1000800081B200001100004081B2000000801FE931 +:1000900018310000000041E980B201000F0040E982 +:1000A00080B2000000000040A59901001600294020 +:1000B00081320000160014BC803200000F0093BC97 +:1000C000803200000000504081B2010000800040FA +:1000D00081B2000010000040A59901001C002940D9 +:1000E000813200001C0014BC80320000110093BC5F +:1000F000803200000000504081B2010001800040C9 +:1001000081B2000020000040A59901002200294092 +:1001100081320000220014BC803200000E0093BC2B +:100120008032000000000049DD8101002B01004009 +:10013000813201003C01004081320100270014BCE3 +:1001400080320000140113BC80320000549500403E +:1001500045990100FFFF0040E599010000002F4094 +:1001600049B1010000000040E1B101000000004B76 +:10017000B7B3010000000040B5B30100D900004052 +:10018000B333010000000040B6D30100320095E80F +:1001900080320000FFFF00E880880100B8002640A0 +:1001A0008132000000000040FDB30100000000406B +:1001B000FFB301003C002250836C000000000045AA +:1001C000FD930100A5A500A6B4A701003C00A25024 +:1001D000B573000000010040813201003C00A245DF +:1001E0008032000000000046FD9301004100004005 +:1001F00081B200007F000020F5CF01001C0100FA51 +:10020000B3330100A5A500DAB5AB01009900A250F7 +:10021000B563000000000044FD930100D5000044D8 +:10022000B333010000000040D5990100000000DA5E +:10023000D7B10100FFFF00DAED8B0100D5000046C9 +:10024000B333010008000040D5990100000000DA36 +:10025000D7B10100FF0000DAEF8B0100FF0000DAE8 +:10026000E38F0100D5000048B33301003C0000409B +:10027000D5990100FF0000DAD78D0100FFFF00DAF9 +:10028000F1DB0100FF0000DAE98B0100000000480B +:10029000E9E30100D500004BB33301002C0000401E +:1002A000D5990100000000DAD7B10100D500004C5B +:1002B000B3330100FFFF00DAEBDB0100D500004E95 +:1002C000B3330100030000DA818801000000005C04 +:1002D00081E00100FFFF00DAB5DB01005C00264091 +:1002E00081320000010000DAB5CF010000F000A764 +:1002F000B4870100000000DA819401000000004092 +:10030000D8B10100D5000050B3330100FFFF00DA7F +:10031000B58B01006200264CB5630000010000DAD5 +:10032000B5CF0100000000DADFB10100D5000052B6 +:10033000B3330100FF0000DA4B890100080000DA46 +:10034000DFF70100FF0000EFDF8B010069002240B2 +:10035000DF7F000000000047FD9301002000004007 +:10036000B39B0100D500004081320100060000402F +:10037000D5990100080000DAD7E50100F80000DA9D +:10038000B38B010034000040D5990100000000D972 +:10039000D7B10100020000D9D5C90100000000DA80 +:1003A000D7B1010022000040B39B0100D5000040FE +:1003B0008132010000000048B5F30100030000DABB +:1003C0007B89010000010040DD9B0100D500005D3C +:1003D000B3330100FFFF00DAE78B01008A002640FB +:1003E0008132000000000041FD9301000000005038 +:1003F000E7E3010000010040D5990100000000F68C +:10040000E7970100000000F3D7B10100D500005EBE +:10041000B3330100FF0000DAE58B01000000004863 +:10042000E5E3010008010040D5990100FF0000DA72 +:10043000B58F0100000000F7B5970100000000DA59 +:10044000D7B101003C010040D5990100000000F83F +:10045000E5970100000000F2D7B101000002004062 +:10046000DD9B0100960022F5813200000000004271 +:10047000FD930100000000EED5B10100000000F680 +:10048000EB970100000000F5D7B10100080000EA79 +:10049000D4C90100000000F7E3970100000000F15B +:1004A000D7B101003C0000EEDDCB0100000000EE02 +:1004B000D5B10100000000F8E9970100000000F448 +:1004C000D7B10100D500004AB3330100FFFF00DAC5 +:1004D000DD890100B700004081B20000000000404B +:1004E000D5990100050000A6D6B101009A1300EBD2 +:1004F000D699010008000040D5990100000200A62D +:10050000D6B10100010000EBD69901002C0000409B +:10051000D5990100050000A6D6B101009A1300EBA1 +:10052000D69901003C010040D5990100000200402D +:10053000D799010000000042FD9301003C000040FB +:10054000D5990100000000A6D6B10100000100EB22 +:10055000D699010000010040D5990100060000A6CF +:10056000D6B101009A1300EBD699010008010040B2 +:10057000D5990100000200A6D6B10100010000EBF0 +:10058000D699010000000040D9B1010000000040F0 +:10059000DFB1010006000040D5990100A00000A6CF +:1005A000D6B10100640000404B99010000000040FA +:1005B0007B99010002040040DD990100B70013BCE3 +:1005C0008032000002080040DD9901000000004C6C +:1005D000DD910100B80095E88430000000002FE9AB +:1005E000FAB3010000000040D1B10100FF00004259 +:1005F000808801003400004080CE0100B800A64091 +:1006000081320000C100004081320100028022409E +:1006100080320000B800004081B200000000004FAE +:1006200081B00100CA0009F981320000C80008F950 +:1006300081320000D4001FFDF9330000C7009EFD89 +:10064000813200000000004AF3930100000080485E +:10065000F3930100000000FDF7B3010000008049A2 +:10066000F3930100000000FC19B10100CF000AF96A +:1006700081320000000040FB81B20100000041FD1A +:1006800081B20100000780F9F38F0100000742F9F1 +:10069000F38F0100D300A2FFF76F0000000043407A +:1006A00081B201000000A2FFFBEF0000000080FC0F +:1006B000E1B101000000804081B00100D80006FED9 +:1006C0008132000000000041B3E301001C0100FA88 +:1006D000B3C30000DA0000428DB00000000000410A +:1006E0008DB001000004004083980100EB00004041 +:1006F000813201000000005083B0010000008496A8 +:1007000080B2000026010040813201002501004036 +:100710002D110100000000402D810100000000DAD1 +:10072000B5EB0100E400849680320000E500004053 +:10073000B593000000000040B5830100DE00A24137 +:1007400083500000000000422D810100260100417D +:100750002D01010000000041B3C30100DA00A241F5 +:100760008D500000000080DAB5BF01000000004B92 +:1007700081B00100000000DB81D00100000000D941 +:10078000B9B3010000000040B8E30100000000DC44 +:10079000B9EB010000000041B8970100150000DC32 +:1007A000B9E70100000000412D810100000000DBDD +:1007B00081B00100270100422D11010025010040F8 +:1007C0002D110100280100402D0101000000004111 +:1007D0002D910100260100408132010025010040D9 +:1007E0002D110100000000402D8101000000A241F8 +:1007F00081D000000000849680320100FF00A0DC60 +:10080000B96B0000F80000412D910000F800004194 +:100810002D810000D8000040B3330100000090DAC1 +:100820008BB000001100004588F401004000004436 +:1008300080CE01000000A44081B200000000A3446B +:1008400089EC00000000004289D001000000004255 +:1008500087B00100D9000043B2330100000000500E +:10086000B5F301000C01A0DA8B400000000000414C +:100870008BC001000000004187C001000801A241B7 +:1008800089500000FFFF00458888010010000045E6 +:100890008AF40100120190448A40000000000041E7 +:1008A0008BC00100FFFF00458AA8010000008050B6 +:1008B0008BE0010000800040F99B010000C0004077 +:1008C000B3CF01001C0100FC193101001C0140DA0A +:1008D00081320100000041DA81B2010000000041D4 +:1008E000F9C3010016019FDA813200000280004046 +:1008F00081B200000000004491B00100000000D966 +:100900002BB101001E019F9480320000180000945A +:1009100092E4010000000048B5F301000000004926 +:10092000B497010000000041B3C301001D01A241C2 +:1009300091500000000080402BB1010029010051BE +:1009400093B000002901004D93B000002901004937 +:1009500093B000000000004293B001002901A241C1 +:10096000935000000000804081B201000000104060 +:1009700081B201000000114081B20100000012406C +:1009800081B201000000134081B201000000144058 +:1009900081B201000000154081B201000000164044 +:1009A00081B201000000174081B201000000184030 +:1009B00081B201000000194081B2010000001A401C +:1009C00081B2010000001B4081B2010000001C4008 +:1009D00081B2010000001D4081B2010000001E40F4 +:1009E00081B2010000001F4081B201000000804080 +:1009F00081B2010000040040A199010000000050F4 +:100A0000A1D10100000000401BB001000000004027 +:100A100019B001000000004017B0010000000040C4 +:100A200015B001000000004013B0010000000040BC +:100A300011B00100000000400FB0010000000040B4 +:100A40000DB00100000000400BB0010000000040AC +:100A500009B001000000004007B0010000000040A4 +:100A600005B001000000004003B00100000000409C +:100A700001B0010044012048A15100000000804065 +:100A800081B201005001224B747D000000008040C3 +:100A900081B201006000004B60990100000000B1CC +:100AA0007EB101005101A840813200004E0100409A +:100AB00081B20000040080409798010000000058B7 +:100AC00007900100F39F004081B200000000004445 +:100AD000A5B30100AF02004081320100C502004011 +:100AE000813201000000005C07900100F39F00408C +:100AF000BFB300005F0122CC857F000000000051E1 +:100B000007900100F39F004081B200000000004008 +:100B100049B10100AE0300CBA3C90100D0140040CD +:100B2000A19B01000000002046B101000000004828 +:100B3000F1B10100000000D0F1B10100000000CAD5 +:100B4000F1B10100000000D5E1B101000700004053 +:100B5000619901002000002062DD01006801A840C9 +:100B600081320000000000CC85930100C5020040E6 +:100B700081320100D014004043990100000000FAC6 +:100B8000BAB30100000000FAA4B30100000000F8AD +:100B9000BCB3010000142F4081B00100000000E749 +:100BA000A7B30100000000D8A9B30100FF0000DDD9 +:100BB000818801000200004080F4010078010040BB +:100BC00080C80100880100DD813200000000004083 +:100BD00010B100008901004081B200008A0100408C +:100BE00081B200008B01004081B200008C01004006 +:100BF00081B200008D01004081B200008F010040F1 +:100C000081B200009101004081B200005501004016 +:100C100081B20000D201004081B2000055010040C5 +:100C200081B20000E001004081B20000E10100401B +:100C300081B200007F02004081B2000080020040CB +:100C400081B20000F19F004081B20000F29F00409D +:100C500081B200007701004181C01A005A01514061 +:100C600081B21A005A01524081B21A005A0155400D +:100C700081B21A005A01564081B21A005501918181 +:100C800080301A005A01454081B21A005501918204 +:100C900080301A005A01464081B200000000004036 +:100CA00089B0010000002F4081B001000014004015 +:100CB00049990100B50122DEE16D00000000004C01 +:100CC00049C101000000004181C001009401A2441B +:100CD000816C00000000004C49D101009C012240C1 +:100CE000E16D00009801A2418150000055010041D2 +:100CF000BFB3000000000042BFB301005501A00FC8 +:100D0000BD6F0000000000DEE1B101000000004402 +:100D100049C10100B701004019990100000042409B +:100D200081B20100000043FF85B00100000000DE39 +:100D300019B10100000042FF87B00100000043FF2D +:100D4000E1B101000000004449C1010000002FFF93 +:100D5000E1B10100081400A480CC0100AC012640E0 +:100D6000813200000000004185C00100AA01A24CB0 +:100D700081500000B60122D281320000B10122412F +:100D8000A56F00005501A2E081320000000000D2F2 +:100D9000C1B301000000005C8990010000004042E6 +:100DA00080B201000000414380B20100000000F069 +:100DB000889401005A010044E0B10000B3010048EA +:100DC00049C10000B101005B89900000B09F00A004 +:100DD0009EB000000000004D81B001000000004303 +:100DE000CB8301000000454081B20100BA01A2415D +:100DF000815000000000454081B2010000004540E4 +:100E000081B20100C4019182823000000000008A9A +:100E100080B00100B69F004080CE0100C301A64013 +:100E200081320000C401564081B20000000000532E +:100E30006F930100F39F00526F9300000000004D7C +:100E400081B0010000000042CD8301000000464057 +:100E500081B20100C701A24181500000000046405C +:100E600081B201000000464081B20100D1019181B0 +:100E7000823000000000008980B00100B69F004071 +:100E800080CE0100D001A64081320000D101554042 +:100E900081B20000000000526F930100F39F0053E5 +:100EA0006F9300000000004083B001000014004078 +:100EB000499901000000234081B00100DA0122DEDF +:100EC000E16D00000000004C49C10100000000413C +:100ED00081C00100D501A244816C0000550100438E +:100EE000BFB30000000000F818B10100000040F896 +:100EF00080B20100000041F080B20100000000401B +:100F0000F1B1010000000040F1B101005A010040C0 +:100F1000E1B10000E201004091B00000000000419A +:100F200091B00100D0142E4049B1010005000040ED +:100F3000A39B0100080000DD81F40100E7010040EF +:100F400080C801000000004010B10000ED01004029 +:100F500081B00000580100DEA1B30000FF01004095 +:100F600081B200000102004081B000000702004091 +:100F700081B20000570100DFE1B10000000000D0A5 +:100F8000BAB30100000000DEA1B10100020000D2EE +:100F9000A5E70100000000D2C1B30100000000007D +:100FA000F0B10100F7012244C1530000F601844171 +:100FB00081400000FA01004081320100000000D0B1 +:100FC00045B10100F1010041A1C10000B1020040A2 +:100FD00081320100C5020040813201005A0100DD6A +:100FE000A1B100000000004081B0010040000040BD +:100FF000A59B0100B102004081320100400000D3F6 +:10100000A7CB0100C50200E0A5B30000030000402B +:10101000A39B0100580100DEA1B3000000000044C2 +:10102000BFB30100000000DE819001005501A2BAAB +:1010300080040000600000DE619901000402A8B194 +:101040008030000057010040E0B10000000000D0F7 +:10105000BAB3010068020040819801005D02004DB2 +:101060008330010000000044E1B3010000000044AF +:10107000E3B3010000000044E5B3010000000044B8 +:10108000E9B3010000000044EBB30100000000449C +:10109000F5B3010000000044F7B301000000004474 +:1010A000F9B30100150222408F6F00007502004065 +:1010B000819801005D0200C7833001007D0200407D +:1010C000819801005D02004283300100000000E8C9 +:1010D000F1B10100000000E9F1B10100000000EAF7 +:1010E000F1B10100000000EBF1B10100000000854A +:1010F000F0B10100000000ECF1B10100000000EDD2 +:10110000F1B10100000000B2F0B10100E09F004029 +:101110008132010000000040F0B1010000000040F9 +:10112000F1B10100000000ABF0B10100000000B817 +:10113000F0B10100000000B9F0B10100000000BAF8 +:10114000F0B10100000000BBF0B101002902B8407D +:101150008130000000000040819001002B02B94066 +:101160008132000000000041819001002D02BA4050 +:101170008132000000000042819001002F02BB403C +:101180008132000000000043819001003102BC4028 +:101190008132000000000044819001003302BD4014 +:1011A0008132000000000045819001003502BE4000 +:1011B0008132000000000046819001003702BF40EC +:1011C0008132000000000047819001003902C840D0 +:1011D0008132000000000048819001003B02C940BC +:1011E0008132000000000049819001003D02CA40A8 +:1011F000813200000000004A819001003F02CB4094 +:10120000813200000000004B819001004102CC407F +:10121000813200000000004C819001004302CD406B +:10122000813200000000004D819001004502CE4057 +:10123000813200000000004E819001004702CF4043 +:10124000813200000000004F81900100000000404A +:10125000F0B1010040000040A59B0100AF0200403A +:1012600081320100C502004081320100D0142E06F7 +:10127000A5B30100400000D3A7CB0100000000F09F +:10128000F1B10100000000F1F1B10100000000F235 +:10129000F1B10100000000F4F1B10100000000F51F +:1012A000F1B10100000000FAF1B10100000000FB03 +:1012B000F1B10100000000FCF1B10100000000EB01 +:1012C000F1B10100000000EEF1B10100000000EFFB +:1012D000F1B10100000000F3F1B10100000000F6DF +:1012E000F1B10100000000FDF1B10100F70100C7FC +:1012F000E1B100000000804081B2010063020048BB +:1013000080320000000051401AB1010000004D4041 +:1013100081B201000000454081B201006002A2419B +:10132000835000005C02494081B20000000052403E +:101330001CB1010000004E4081B201000000464097 +:1013400081B201006502A241835000005C024A4064 +:1013500081B20000000000A09EB0010000000080EB +:10136000D8B30100000000A1D0B30100000000A22A +:10137000D2B30100000000A4D4B30100000000D0EB +:10138000D6B30100000000D1DCB30100000000D2A0 +:10139000DEB3010000000088DAB30100000000D4D1 +:1013A0008EB30100000000D3E6B30100000000ACE2 +:1013B000ECB3010000000099FAB30100000000D571 +:1013C000E0B30100000000D5E2B30100000000D549 +:1013D000E4B30100000000D5E8B30100000000D52F +:1013E000EAB30100000000D5F4B30100000000D50D +:1013F000F6B30100000000D5F8B30100000000C7FB +:10140000A9B101000000004F40B10100810200407D +:1014100091B000000000004191B0010007000040C1 +:10142000A39B0100080000DD81F40100850200405B +:1014300080C801000000004010B100008A02004096 +:1014400081B200009502004081B200009502004682 +:10145000A3B300009802004081B200009E02004049 +:1014600081B200008C022350A56F000000000050E4 +:10147000A5B30100BC020042A5630100C502004003 +:1014800081320100D0142D4049B10100000000D08C +:10149000BAB30100000000DEA1B10100000000F8B5 +:1014A00000B0010094022244A553000091020041C3 +:1014B000A1C100005A0100DDA1B10000BC0200DEA4 +:1014C000A1330100C5020040813201005A010040F1 +:1014D00081B2000000000045BFB301005501A2D257 +:1014E000777D0000000000D261B10100000000DE45 +:1014F00063B101009B02A840813200005A01004004 +:1015000081B20000BC020054A5330100C5020040B6 +:1015100081320100D0142D4049B10100000000F8D3 +:10152000D0B30100000000F8D2B30100000000F8C1 +:10153000D4B30100000000F8D6B30100000000F8A9 +:1015400008B10100A9020040819801005D02004637 +:10155000833001005A01004081B20000000000A069 +:101560009EB00100000000E843B10100000000E966 +:1015700045B10100000000EA49B10100000000EBA4 +:10158000A1B101000000004F40B10100000000E7E0 +:10159000A7B30100000000D8A9B30100000000407B +:1015A00049B10100AE0300CBA3C901000000002037 +:1015B00046B10100000000D2F1B10100000000D3EB +:1015C000F1B10100000000D4F1B10100000000D031 +:1015D000E1B10100000000D161B101002000002054 +:1015E00062DD0100B902A84081320000000080CC19 +:1015F00085930100000000E7A7B30100000000D8B8 +:10160000A9B301000000004049B10100AE0300CBC6 +:10161000A3C901000000002046B10100000000D273 +:10162000F1B10100000000D0F1B10100000000D3D1 +:10163000F1B10100B80200D4E1B100000000A2CC79 +:1016400085FF00000000005081B00100C702A241E8 +:1016500081500000C602A2F280300000000080CC61 +:10166000858301000000004081B00100CB0280A50D +:1016700080320000CC0200A5803200000000004152 +:1016800081C00100CD0280A58032000080010040B1 +:1016900083980100D602204F816C000000010040B9 +:1016A00083980100D602204B816C0000800000402E +:1016B00083980100D6022047816C000000000040A2 +:1016C000839801000000004182DC0100039000418A +:1016D000209901000000004049B1010000142F4C86 +:1016E00083B0010000000040F1B10100DA02A24124 +:1016F00083500000020000A580C80100DD02A2A501 +:10170000806C000020000090209901000000005F24 +:1017100023910100E0021F91803200003000009010 +:10172000209901000000005F23910100E3021F9156 +:10173000803200007000009020A901000000005FCE +:1017400023910100E6021F91803200000000005F3B +:1017500023910100E8021F91803200004068009050 +:1017600020A90100E0000040619901002100004033 +:1017700061990100220000406199010023000040AE +:10178000619901002400004061990100250000409A +:101790006199010026000040619901002700004086 +:1017A00061990100C000004061990100D01400401F +:1017B00045990100020100A680B001000403004029 +:1017C00080980100060500A682B0010008070041CC +:1017D0008298010000000040F0B1010000000041CB +:1017E000E0B10100300300408530010039030040C2 +:1017F00081320100D814004043990100FF02A2F891 +:10180000806C0000000322F0826C000000000042A7 +:1018100021910100D0142040E1B101003003000CFF +:10182000853001003003004D851001003003004E6B +:1018300085100100D014204FE1B101003003004FAA +:10184000851001003903000C85300100D8142043B5 +:1018500081B001000F0322F09E6E00003903004D9D +:1018600085100100D814204281B001000F0322F03E +:101870009E6E00003903004E85100100D8142041EF +:1018800081B001001103A2F09E6E0000000000492B +:1018900081E001000000004020950100030000905D +:1018A000208D010000000043219501000000001B75 +:1018B00089B00100D0142040E1B1010030030017CD +:1018C00085300100300300588510010030030059B5 +:1018D00085100100D014204FE1B101003003005AFF +:1018E000851001003903001785300100D81420400D +:1018F00081B00100230322F09E6E000039030058DE +:1019000085100100D814204181B00100230322F08A +:101910009E6E00003903005985100100D814204242 +:1019200081B001002703A2F09E6E0000030000902A +:10193000208D0100000000402095010000000018EB +:1019400089B001000000004088E001002F03A2429E +:10195000217D0000A5A5004081980100D014204001 +:10196000E0B101003003004484300100390300403D +:1019700081320100D814204081B201002F03A2F06F +:10198000806C00000000004189E00100E000804020 +:10199000619901007015004047990100000000485E +:1019A000F1B1010000000042F0B10100D01400408C +:1019B000F19901000000005587B4010004000040C7 +:1019C0006199010070150043629901003603A84037 +:1019D000813200004103004081B2000070150040D8 +:1019E0004799010000000048F1B10100D8140040FF +:1019F000F199010000000042F0B101000000005523 +:101A000087B4010002000040619901007015004395 +:101A1000629901003F03A8408132000000000048A5 +:101A200087B001004203A241875000000000A2F2EB +:101A300086B00000100000F186F40100410326404A +:101A4000813200000400004081B200000000004725 +:101A500084B001000000A248848400000000005F00 +:101A600061B101000000005C8F90010000000047A0 +:101A700062B101004903A84081320000F59F004790 +:101A800098300100000800478EC801004703005C41 +:101A90008F800000E00000406199010058152D4042 +:101AA0008DB00100D0142DF088B00100000000FAC4 +:101AB0008AB001000000004581B001000700004528 +:101AC00082880100000000438BF001000000004804 +:101AD00083E00100000000468294010020000041E4 +:101AE00060990100000000418DC001006403225F85 +:101AF0008D6C00005503A24181500000530300404B +:101B000081B20000080000408598010000000044F8 +:101B100082B001000000004186B00100001C0043BB +:101B200086D801000000A6418550010060030041F5 +:101B300083E000005E0300408132010000000048A5 +:101B400085E00100D0142F4684940100200000425B +:101B500060990100C00000406199010000008040D0 +:101B600081B20100070000458088010000000043A9 +:101B70008BF0010000040040839801006F03A04136 +:101B8000815000006D03004182E8000000008041A8 +:101B90008EC00100AE030040A39901000000005474 +:101BA00081B00100601500408598010008000040E8 +:101BB00040E401000000005A419401000000005080 +:101BC00041E001000000004240940100000000419B +:101BD00081C001000000A355816C0100000000419C +:101BE000A3C101007303005085C000000000004045 +:101BF00049B1010000020040839801000016004036 +:101C00004599010000000040F1B101007E03A241AE +:101C1000835000000000004085B001000B0000442C +:101C200082F401001A1500A686B00100701500406C +:101C30004599010000080040F199010000000042B0 +:101C4000F0B1010000160040E199010004000040DD +:101C50006199010070150043629901008803A84052 +:101C6000813200008A03225A737D00007A0000400E +:101C7000619901008B03A8B17E3100000008004289 +:101C800084C801008303A24183500000000080400B +:101C900081B201000400004081B200000400004055 +:101CA00081B200000400004081B200000400004046 +:101CB00081B200000400004081B200000400004036 +:101CC00081B200000400004081B200000400004026 +:101CD00081B200000400004081B200000400004016 +:101CE00081B200000400004081B200000400004006 +:101CF00081B200000400004081B2000004000040F6 +:101D000081B200000400004081B2000004000040E5 +:101D100081B200000400004081B2000004000040D5 +:101D200081B200000400004081B2000004000040C5 +:101D300081B200000400004081B2000004000040B5 +:101D400081B200000400004081B2000004000040A5 +:101D500081B200000400004081B200000400004095 +:101D600081B200000400004081B200000400004085 +:101D700081B200000400004081B200000400004075 +:101D800081B200000400004081B200000400004065 +:101D900081B200000400004081B200000400004055 +:101DA00081B200000400004081B200000400004045 +:101DB00081B200000400004081B200000400004035 +:101DC00081B200000400004081B200000400004025 +:101DD00081B200000400004081B200000400004015 +:101DE00081B200000400004081B200000400004005 +:101DF00081B200000400004081B2000004000040F5 +:101E000081B200000400004081B2000004000040E4 +:101E100081B200000400004081B2000004000040D4 +:101E200081B200000400004081B2000004000040C4 +:101E300081B200000400004081B2000004000040B4 +:101E400081B200000400004081B2000004000040A4 +:101E500081B200000400004081B200000400004094 +:101E600081B200000400004081B200000400004084 +:101E700081B200000400004081B200000400004074 +:101E800081B200000400004081B200000400004064 +:101E900081B200000400004081B200000400004054 +:101EA00081B200000400004081B200000400004044 +:101EB00081B200000400004081B200000400004034 +:101EC00081B200000400004081B200000400004024 +:101ED00081B200000400004081B200000400004014 +:101EE00081B200000400004081B200000400004004 +:101EF00081B200000400004081B2000004000040F4 +:101F000081B200000400004081B2000004000040E3 +:101F100081B200000400004081B2000004000040D3 +:101F200081B200000400004081B2000004000040C3 +:101F300081B200000400004081B2000004000040B3 +:101F400081B200000400004081B2000004000040A3 +:101F500081B200000400004081B200000400004093 +:101F600081B200000400004081B200000400004083 +:101F700081B200000400004081B200000400004073 +:101F800081B200000400004081B200000400004063 +:101F900081B200000400004081B200000400004053 +:101FA00081B200000400004081B200000400004043 +:101FB00081B200000400004081B200000400004033 +:101FC00081B200000400004081B200000400004023 +:101FD00081B200000400004081B200000400004013 +:101FE00081B200000400004081B200000400004003 +:101FF00081B200000400004081B2000004000040F3 +:1020000081B200000400004081B2000004000040E2 +:1020100081B200000400004081B2000004000040D2 +:1020200081B200000400004081B2000004000040C2 +:1020300081B200000400004081B2000004000040B2 +:1020400081B200000400004081B2000004000040A2 +:1020500081B200000400004081B200000400004092 +:1020600081B200000400004081B200000400004082 +:1020700081B200000400004081B200000400004072 +:1020800081B200000400004081B200000400004062 +:1020900081B200000400004081B200000400004052 +:1020A00081B200000400004081B200000400004042 +:1020B00081B200000400004081B200000400004032 +:1020C00081B200000400004081B200000400004022 +:1020D00081B200000400004081B200000400004012 +:1020E00081B200000400004081B200000400004002 +:1020F00081B200000400004081B2000004000040F2 +:1021000081B200000400004081B2000004000040E1 +:1021100081B200000400004081B2000004000040D1 +:1021200081B200000400004081B2000004000040C1 +:1021300081B200000400004081B2000004000040B1 +:1021400081B200000400004081B2000004000040A1 +:1021500081B200000400004081B200000400004091 +:1021600081B200000400004081B200000400004081 +:1021700081B200000400004081B200000400004071 +:1021800081B200000400004081B200000400004061 +:1021900081B200000400004081B200000400004051 +:1021A00081B200000400004081B200000400004041 +:1021B00081B200000400004081B200000400004031 +:1021C00081B200000400004081B200000400004021 +:1021D00081B200000400004081B200000400004011 +:1021E00081B200000400004081B200000400004001 +:1021F00081B200000400004081B2000004000040F1 +:1022000081B200000400004081B2000004000040E0 +:1022100081B200000400004081B2000004000040D0 +:1022200081B200000400004081B2000004000040C0 +:1022300081B200000400004081B2000004000040B0 +:1022400081B200000400004081B2000004000040A0 +:1022500081B200000400004081B200000400004090 +:1022600081B200000400004081B200000400004080 +:1022700081B200000400004081B200000400004070 +:1022800081B200000400004081B200000400004060 +:1022900081B200000400004081B200000400004050 +:1022A00081B200000400004081B200000400004040 +:1022B00081B200000400004081B200000400004030 +:1022C00081B200000400004081B200000400004020 +:1022D00081B200000400004081B200000400004010 +:1022E00081B200000400004081B200000400004000 +:1022F00081B200000400004081B2000004000040F0 +:1023000081B200000400004081B2000004000040DF +:1023100081B200000400004081B2000004000040CF +:1023200081B200000400004081B2000004000040BF +:1023300081B200000400004081B2000004000040AF +:1023400081B200000400004081B20000040000409F +:1023500081B200000400004081B20000040000408F +:1023600081B200000400004081B20000040000407F +:1023700081B200000400004081B20000040000406F +:1023800081B200000400004081B20000040000405F +:1023900081B200000400004081B20000040000404F +:1023A00081B200000400004081B20000040000403F +:1023B00081B200000400004081B20000040000402F +:1023C00081B200000400004081B20000040000401F +:1023D00081B200000400004081B20000040000400F +:1023E00081B200000400004081B2000004000040FF +:1023F00081B200000400004081B2000004000040EF +:1024000081B200000400004081B2000004000040DE +:1024100081B200000400004081B2000004000040CE +:1024200081B200000400004081B2000004000040BE +:1024300081B200000400004081B2000004000040AE +:1024400081B200000400004081B20000040000409E +:1024500081B200000400004081B20000040000408E +:1024600081B200000400004081B20000040000407E +:1024700081B200000400004081B20000040000406E +:1024800081B200000400004081B20000040000405E +:1024900081B200000400004081B20000040000404E +:1024A00081B200000400004081B20000040000403E +:1024B00081B200000400004081B20000040000402E +:1024C00081B200000400004081B20000040000401E +:1024D00081B200000400004081B20000040000400E +:1024E00081B200000400004081B2000004000040FE +:1024F00081B200000400004081B2000004000040EE +:1025000081B200000400004081B2000004000040DD +:1025100081B200000400004081B2000004000040CD +:1025200081B200000400004081B2000004000040BD +:1025300081B200000400004081B2000004000040AD +:1025400081B200000400004081B20000040000409D +:1025500081B200000400004081B20000040000408D +:1025600081B200000400004081B20000040000407D +:1025700081B200000400004081B20000040000406D +:1025800081B200000400004081B20000040000405D +:1025900081B200000400004081B20000040000404D +:1025A00081B200000400004081B20000040000403D +:1025B00081B200000400004081B20000040000402D +:1025C00081B200000400004081B20000040000401D +:1025D00081B200000400004081B20000040000400D +:1025E00081B200000400004081B2000004000040FD +:1025F00081B200000400004081B2000004000040ED +:1026000081B200000400004081B2000004000040DC +:1026100081B200000400004081B2000004000040CC +:1026200081B200000400004081B2000004000040BC +:1026300081B200000400004081B2000004000040AC +:1026400081B200000400004081B20000040000409C +:1026500081B200000400004081B20000040000408C +:1026600081B200000400004081B20000040000407C +:1026700081B200000400004081B20000040000406C +:1026800081B200000400004081B20000040000405C +:1026900081B200000400004081B20000040000404C +:1026A00081B200000400004081B20000040000403C +:1026B00081B200000400004081B20000040000402C +:1026C00081B200000400004081B20000040000401C +:1026D00081B200000400004081B20000040000400C +:1026E00081B200000400004081B2000004000040FC +:1026F00081B200000400004081B2000004000040EC +:1027000081B200000400004081B2000004000040DB +:1027100081B200000400004081B2000004000040CB +:1027200081B200000400004081B2000004000040BB +:1027300081B200000400004081B2000004000040AB +:1027400081B200000400004081B20000040000409B +:1027500081B200000400004081B20000040000408B +:1027600081B200000400004081B20000040000407B +:1027700081B200000400004081B20000040000406B +:1027800081B200000400004081B20000040000405B +:1027900081B200000400004081B20000040000404B +:1027A00081B200000400004081B20000040000403B +:1027B00081B200000400004081B20000040000402B +:1027C00081B200000400004081B20000040000401B +:1027D00081B200000400004081B20000040000400B +:1027E00081B200000400004081B2000004000040FB +:1027F00081B200000400004081B2000004000040EB +:1028000081B200000400004081B2000004000040DA +:1028100081B200000400004081B2000004000040CA +:1028200081B200000400004081B2000004000040BA +:1028300081B200000400004081B2000004000040AA +:1028400081B200000400004081B20000040000409A +:1028500081B200000400004081B20000040000408A +:1028600081B200000400004081B20000040000407A +:1028700081B200000400004081B20000040000406A +:1028800081B200000400004081B20000040000405A +:1028900081B200000400004081B20000040000404A +:1028A00081B200000400004081B20000040000403A +:1028B00081B200000400004081B20000040000402A +:1028C00081B200000400004081B20000040000401A +:1028D00081B200000400004081B20000040000400A +:1028E00081B200000400004081B2000004000040FA +:1028F00081B200000400004081B2000004000040EA +:1029000081B200000400004081B2000004000040D9 +:1029100081B200000400004081B2000004000040C9 +:1029200081B200000400004081B2000004000040B9 +:1029300081B200000400004081B2000004000040A9 +:1029400081B200000400004081B200000400004099 +:1029500081B200000400004081B200000400004089 +:1029600081B200000400004081B200000400004079 +:1029700081B200000400004081B200000400004069 +:1029800081B200000400004081B200000400004059 +:1029900081B200000400004081B200000400004049 +:1029A00081B200000400004081B200000400004039 +:1029B00081B200000400004081B200000400004029 +:1029C00081B200000400004081B200000400004019 +:1029D00081B200000400004081B200000400004009 +:1029E00081B200000400004081B2000004000040F9 +:1029F00081B200000400004081B2000004000040E9 +:102A000081B200000400004081B2000004000040D8 +:102A100081B200000400004081B2000004000040C8 +:102A200081B200000400004081B2000004000040B8 +:102A300081B200000400004081B2000004000040A8 +:102A400081B200000400004081B200000400004098 +:102A500081B200000400004081B200000400004088 +:102A600081B200000400004081B200000400004078 +:102A700081B200000400004081B200000400004068 +:102A800081B200000400004081B200000400004058 +:102A900081B200000400004081B200000400004048 +:102AA00081B200000400004081B200000400004038 +:102AB00081B200000400004081B200000400004028 +:102AC00081B200000400004081B200000400004018 +:102AD00081B200000400004081B200000400004008 +:102AE00081B200000400004081B2000004000040F8 +:102AF00081B200000400004081B2000004000040E8 +:102B000081B200000400004081B2000004000040D7 +:102B100081B200000400004081B2000004000040C7 +:102B200081B200000400004081B2000004000040B7 +:102B300081B200000400004081B2000004000040A7 +:102B400081B200000400004081B200000400004097 +:102B500081B200000400004081B200000400004087 +:102B600081B200000400004081B200000400004077 +:102B700081B200000400004081B200000400004067 +:102B800081B200000400004081B200000400004057 +:102B900081B200000400004081B200000400004047 +:102BA00081B200000400004081B200000400004037 +:102BB00081B200000400004081B200000400004027 +:102BC00081B200000400004081B200000400004017 +:102BD00081B200000400004081B200000400004007 +:102BE00081B200000400004081B2000004000040F7 +:102BF00081B200000400004081B2000004000040E7 +:102C000081B200000400004081B2000004000040D6 +:102C100081B200000400004081B2000004000040C6 +:102C200081B200000400004081B2000004000040B6 +:102C300081B200000400004081B2000004000040A6 +:102C400081B200000400004081B200000400004096 +:102C500081B200000400004081B200000400004086 +:102C600081B200000400004081B200000400004076 +:102C700081B200000400004081B200000400004066 +:102C800081B200000400004081B200000400004056 +:102C900081B200000400004081B200000400004046 +:102CA00081B200000400004081B200000400004036 +:102CB00081B200000400004081B200000400004026 +:102CC00081B200000400004081B200000400004016 +:102CD00081B200000400004081B200000400004006 +:102CE00081B200000400004081B2000004000040F6 +:102CF00081B200000400004081B2000004000040E6 +:102D000081B200000400004081B2000004000040D5 +:102D100081B200000400004081B2000004000040C5 +:102D200081B200000400004081B2000004000040B5 +:102D300081B200000400004081B2000004000040A5 +:102D400081B200000400004081B200000400004095 +:102D500081B200000400004081B200000400004085 +:102D600081B200000400004081B200000400004075 +:102D700081B200000400004081B200000400004065 +:102D800081B200000400004081B200000400004055 +:102D900081B200000400004081B200000400004045 +:102DA00081B200000400004081B200000400004035 +:102DB00081B200000400004081B200000400004025 +:102DC00081B200000400004081B200000400004015 +:102DD00081B200000400004081B200000400004005 +:102DE00081B200000400004081B2000004000040F5 +:102DF00081B200000400004081B2000004000040E5 +:102E000081B200000400004081B2000004000040D4 +:102E100081B200000400004081B2000004000040C4 +:102E200081B200000400004081B2000004000040B4 +:102E300081B200000400004081B2000004000040A4 +:102E400081B200000400004081B200000400004094 +:102E500081B200000400004081B200000400004084 +:102E600081B200000400004081B200000400004074 +:102E700081B200000400004081B200000400004064 +:102E800081B200000400004081B200000400004054 +:102E900081B200000400004081B200000400004044 +:102EA00081B200000400004081B200000400004034 +:102EB00081B200000400004081B200000400004024 +:102EC00081B200000400004081B200000400004014 +:102ED00081B200000400004081B200000400004004 +:102EE00081B200000400004081B2000004000040F4 +:102EF00081B200000400004081B2000004000040E4 +:102F000081B200000400004081B2000004000040D3 +:102F100081B200000400004081B2000004000040C3 +:102F200081B200000400004081B2000004000040B3 +:102F300081B200000400004081B2000004000040A3 +:102F400081B200000400004081B200000400004093 +:102F500081B200000400004081B200000400004083 +:102F600081B200000400004081B200000400004073 +:102F700081B200000400004081B200000400004063 +:102F800081B200000400004081B200000400004053 +:102F900081B200000400004081B200000400004043 +:102FA00081B200000400004081B200000400004033 +:102FB00081B200000400004081B200000400004023 +:102FC00081B200000400004081B200000400004013 +:102FD00081B200000400004081B200000400004003 +:102FE00081B200000400004081B2000004000040F3 +:102FF00081B200000400004081B2000004000040E3 +:1030000081B200000400004081B2000004000040D2 +:1030100081B200000400004081B2000004000040C2 +:1030200081B200000400004081B2000004000040B2 +:1030300081B200000400004081B2000004000040A2 +:1030400081B200000400004081B200000400004092 +:1030500081B200000400004081B200000400004082 +:1030600081B200000400004081B200000400004072 +:1030700081B200000400004081B200000400004062 +:1030800081B200000400004081B200000400004052 +:1030900081B200000400004081B200000400004042 +:1030A00081B200000400004081B200000400004032 +:1030B00081B200000400004081B200000400004022 +:1030C00081B200000400004081B200000400004012 +:1030D00081B200000400004081B200000400004002 +:1030E00081B200000400004081B2000004000040F2 +:1030F00081B200000400004081B2000004000040E2 +:1031000081B200000400004081B2000004000040D1 +:1031100081B200000400004081B2000004000040C1 +:1031200081B200000400004081B2000004000040B1 +:1031300081B200000400004081B2000004000040A1 +:1031400081B200000400004081B200000400004091 +:1031500081B200000400004081B200000400004081 +:1031600081B200000400004081B200000400004071 +:1031700081B200000400004081B200000400004061 +:1031800081B200000400004081B200000400004051 +:1031900081B200000400004081B200000400004041 +:1031A00081B200000400004081B200000400004031 +:1031B00081B200000400004081B200000400004021 +:1031C00081B200000400004081B200000400004011 +:1031D00081B200000400004081B200000400004001 +:1031E00081B200000400004081B2000004000040F1 +:1031F00081B200000400004081B2000004000040E1 +:1032000081B200000400004081B2000004000040D0 +:1032100081B200000400004081B2000004000040C0 +:1032200081B200000400004081B2000004000040B0 +:1032300081B200000400004081B2000004000040A0 +:1032400081B200000400004081B200000400004090 +:1032500081B200000400004081B200000400004080 +:1032600081B200000400004081B200000400004070 +:1032700081B200000400004081B200000400004060 +:1032800081B200000400004081B200000400004050 +:1032900081B200000400004081B200000400004040 +:1032A00081B200000400004081B200000400004030 +:1032B00081B200000400004081B200000400004020 +:1032C00081B200000400004081B200000400004010 +:1032D00081B200000400004081B200000400004000 +:1032E00081B200000400004081B2000004000040F0 +:1032F00081B200000400004081B2000004000040E0 +:1033000081B200000400004081B2000004000040CF +:1033100081B200000400004081B2000004000040BF +:1033200081B200000400004081B2000004000040AF +:1033300081B200000400004081B20000040000409F +:1033400081B200000400004081B20000040000408F +:1033500081B200000400004081B20000040000407F +:1033600081B200000400004081B20000040000406F +:1033700081B200000400004081B20000040000405F +:1033800081B200000400004081B20000040000404F +:1033900081B200000400004081B20000040000403F +:1033A00081B200000400004081B20000040000402F +:1033B00081B200000400004081B20000040000401F +:1033C00081B200000400004081B20000040000400F +:1033D00081B200000400004081B2000004000040FF +:1033E00081B200000400004081B2000004000040EF +:1033F00081B200000400004081B2000004000040DF +:1034000081B200000400004081B2000004000040CE +:1034100081B200000400004081B2000004000040BE +:1034200081B200000400004081B2000004000040AE +:1034300081B200000400004081B20000040000409E +:1034400081B200000400004081B20000040000408E +:1034500081B200000400004081B20000040000407E +:1034600081B200000400004081B20000040000406E +:1034700081B200000400004081B20000040000405E +:1034800081B200000400004081B20000040000404E +:1034900081B200000400004081B20000040000403E +:1034A00081B200000400004081B20000040000402E +:1034B00081B200000400004081B20000040000401E +:1034C00081B200000400004081B20000040000400E +:1034D00081B200000400004081B2000004000040FE +:1034E00081B200000400004081B2000004000040EE +:1034F00081B200000400004081B2000004000040DE +:1035000081B200000400004081B2000004000040CD +:1035100081B200000400004081B2000004000040BD +:1035200081B200000400004081B2000004000040AD +:1035300081B200000400004081B20000040000409D +:1035400081B200000400004081B20000040000408D +:1035500081B200000400004081B20000040000407D +:1035600081B200000400004081B20000040000406D +:1035700081B200000400004081B20000040000405D +:1035800081B200000400004081B20000040000404D +:1035900081B200000400004081B20000040000403D +:1035A00081B200000400004081B20000040000402D +:1035B00081B200000400004081B20000040000401D +:1035C00081B200000400004081B20000040000400D +:1035D00081B200000400004081B2000004000040FD +:1035E00081B200000400004081B2000004000040ED +:1035F00081B200000400004081B2000004000040DD +:1036000081B200000400004081B2000004000040CC +:1036100081B200000400004081B2000004000040BC +:1036200081B200000400004081B2000004000040AC +:1036300081B200000400004081B20000040000409C +:1036400081B200000400004081B20000040000408C +:1036500081B200000400004081B20000040000407C +:1036600081B200000400004081B20000040000406C +:1036700081B200000400004081B20000040000405C +:1036800081B200000400004081B20000040000404C +:1036900081B200000400004081B20000040000403C +:1036A00081B200000400004081B20000040000402C +:1036B00081B200000400004081B20000040000401C +:1036C00081B200000400004081B20000040000400C +:1036D00081B200000400004081B2000004000040FC +:1036E00081B200000400004081B2000004000040EC +:1036F00081B200000400004081B2000004000040DC +:1037000081B200000400004081B2000004000040CB +:1037100081B200000400004081B2000004000040BB +:1037200081B200000400004081B2000004000040AB +:1037300081B200000400004081B20000040000409B +:1037400081B200000400004081B20000040000408B +:1037500081B200000400004081B20000040000407B +:1037600081B200000400004081B20000040000406B +:1037700081B200000400004081B20000040000405B +:1037800081B200000400004081B20000040000404B +:1037900081B200000400004081B20000040000403B +:1037A00081B200000400004081B20000040000402B +:1037B00081B200000400004081B20000040000401B +:1037C00081B200000400004081B20000040000400B +:1037D00081B200000400004081B2000004000040FB +:1037E00081B200000400004081B2000004000040EB +:1037F00081B200000400004081B2000004000040DB +:1038000081B200000400004081B2000004000040CA +:1038100081B200000400004081B2000004000040BA +:1038200081B200000400004081B2000004000040AA +:1038300081B200000400004081B20000040000409A +:1038400081B200000400004081B20000040000408A +:1038500081B200000400004081B20000040000407A +:1038600081B200000400004081B20000040000406A +:1038700081B200000400004081B20000040000405A +:1038800081B200000400004081B20000040000404A +:1038900081B200000400004081B20000040000403A +:1038A00081B200000400004081B20000040000402A +:1038B00081B200000400004081B20000040000401A +:1038C00081B200000400004081B20000040000400A +:1038D00081B200000400004081B2000004000040FA +:1038E00081B200000400004081B2000004000040EA +:1038F00081B200000400004081B2000004000040DA +:1039000081B200000400004081B2000004000040C9 +:1039100081B200000400004081B2000004000040B9 +:1039200081B200000400004081B2000004000040A9 +:1039300081B200000400004081B200000400004099 +:1039400081B200000400004081B200000400004089 +:1039500081B200000400004081B200000400004079 +:1039600081B200000400004081B200000400004069 +:1039700081B200000400004081B200000400004059 +:1039800081B200000400004081B200000400004049 +:1039900081B200000400004081B200000400004039 +:1039A00081B200000400004081B200000400004029 +:1039B00081B200000400004081B200000400004019 +:1039C00081B200000400004081B200000400004009 +:1039D00081B200000400004081B2000004000040F9 +:1039E00081B200000400004081B2000004000040E9 +:1039F00081B200000400004081B2000004000040D9 +:103A000081B200000400004081B2000004000040C8 +:103A100081B200000400004081B2000004000040B8 +:103A200081B200000400004081B2000004000040A8 +:103A300081B200000400004081B200000400004098 +:103A400081B200000400004081B200000400004088 +:103A500081B200000400004081B200000400004078 +:103A600081B200000400004081B200000400004068 +:103A700081B200000400004081B200000400004058 +:103A800081B200000400004081B200000400004048 +:103A900081B200000400004081B200000400004038 +:103AA00081B200000400004081B200000400004028 +:103AB00081B200000400004081B200000400004018 +:103AC00081B200000400004081B200000400004008 +:103AD00081B200000400004081B2000004000040F8 +:103AE00081B200000400004081B2000004000040E8 +:103AF00081B200000400004081B2000004000040D8 +:103B000081B200000400004081B2000004000040C7 +:103B100081B200000400004081B2000004000040B7 +:103B200081B200000400004081B2000004000040A7 +:103B300081B200000400004081B200000400004097 +:103B400081B200000400004081B200000400004087 +:103B500081B200000400004081B200000400004077 +:103B600081B200000400004081B200000400004067 +:103B700081B200000400004081B200000400004057 +:103B800081B200000400004081B200000400004047 +:103B900081B200000400004081B200000400004037 +:103BA00081B200000400004081B200000400004027 +:103BB00081B200000400004081B200000400004017 +:103BC00081B200000400004081B200000400004007 +:103BD00081B200000400004081B2000004000040F7 +:103BE00081B200000400004081B2000004000040E7 +:103BF00081B200000400004081B2000004000040D7 +:103C000081B200000400004081B2000004000040C6 +:103C100081B200000400004081B2000004000040B6 +:103C200081B200000400004081B2000004000040A6 +:103C300081B200000400004081B200000400004096 +:103C400081B200000400004081B200000400004086 +:103C500081B200000400004081B200000400004076 +:103C600081B200000400004081B200000400004066 +:103C700081B200000400004081B200000400004056 +:103C800081B200000400004081B200000400004046 +:103C900081B200000400004081B200000400004036 +:103CA00081B200000400004081B200000400004026 +:103CB00081B200000400004081B200000400004016 +:103CC00081B200000400004081B200000400004006 +:103CD00081B200000400004081B2000004000040F6 +:103CE00081B200000400004081B2000004000040E6 +:103CF00081B200000400004081B2000004000040D6 +:103D000081B200000400004081B2000004000040C5 +:103D100081B200000400004081B2000004000040B5 +:103D200081B200000400004081B2000004000040A5 +:103D300081B200000400004081B200000400004095 +:103D400081B200000400004081B200000400004085 +:103D500081B200000400004081B200000400004075 +:103D600081B200000400004081B200000400004065 +:103D700081B200000400004081B200000400004055 +:103D800081B200000400004081B200000400004045 +:103D900081B200000400004081B200000400004035 +:103DA00081B200000400004081B200000400004025 +:103DB00081B200000400004081B200000400004015 +:103DC00081B200000400004081B200000400004005 +:103DD00081B200000400004081B2000004000040F5 +:103DE00081B200000400004081B2000004000040E5 +:103DF00081B200000400004081B2000004000040D5 +:103E000081B200000400004081B2000004000040C4 +:103E100081B200000400004081B2000004000040B4 +:103E200081B200000400004081B2000004000040A4 +:103E300081B200000400004081B200000400004094 +:103E400081B200000400004081B200000400004084 +:103E500081B200000400004081B200000400004074 +:103E600081B200000400004081B200000400004064 +:103E700081B200000400004081B200000400004054 +:103E800081B200000400004081B200000400004044 +:103E900081B200000400004081B200000400004034 +:103EA00081B200000400004081B200000400004024 +:103EB00081B200000400004081B200000400004014 +:103EC00081B200000400004081B200000400004004 +:103ED00081B200000400004081B2000004000040F4 +:103EE00081B200000400004081B2000004000040E4 +:103EF00081B200000400004081B2000004000040D4 +:103F000081B200000400004081B2000004000040C3 +:103F100081B200000400004081B2000004000040B3 +:103F200081B200000400004081B2000004000040A3 +:103F300081B200000400004081B200000400004093 +:103F400081B200000400004081B200000400004083 +:103F500081B200000400004081B200000400004073 +:103F600081B200000400004081B200000400004063 +:103F700081B200000400004081B200000400004053 +:103F800081B200000400004081B200000400004043 +:103F900081B200000400004081B200000400004033 +:103FA00081B200000400004081B200000400004023 +:103FB00081B200000400004081B200000400004013 +:103FC00081B200000400004081B200000400004003 +:103FD00081B200000400004081B2000004000040F3 +:103FE00081B200000400004081B2000004000040E3 +:103FF00081B200000400004081B2000004000040D3 +:1040000081B200000400004081B2000004000040C2 +:1040100081B200000400004081B2000004000040B2 +:1040200081B200000400004081B2000004000040A2 +:1040300081B200000400004081B200000400004092 +:1040400081B200000400004081B200000400004082 +:1040500081B200000400004081B200000400004072 +:1040600081B200000400004081B200000400004062 +:1040700081B200000400004081B200000400004052 +:1040800081B200000400004081B200000400004042 +:1040900081B200000400004081B200000400004032 +:1040A00081B200000400004081B200000400004022 +:1040B00081B200000400004081B200000400004012 +:1040C00081B200000400004081B200000400004002 +:1040D00081B200000400004081B2000004000040F2 +:1040E00081B200000400004081B2000004000040E2 +:1040F00081B200000400004081B2000004000040D2 +:1041000081B200000400004081B2000004000040C1 +:1041100081B200000400004081B2000004000040B1 +:1041200081B200000400004081B2000004000040A1 +:1041300081B200000400004081B200000400004091 +:1041400081B200000400004081B200000400004081 +:1041500081B200000400004081B200000400004071 +:1041600081B200000400004081B200000400004061 +:1041700081B200000400004081B200000400004051 +:1041800081B200000400004081B200000400004041 +:1041900081B200000400004081B200000400004031 +:1041A00081B200000400004081B200000400004021 +:1041B00081B200000400004081B200000400004011 +:1041C00081B200000400004081B200000400004001 +:1041D00081B200000400004081B2000004000040F1 +:1041E00081B200000400004081B2000004000040E1 +:1041F00081B200000400004081B2000004000040D1 +:1042000081B200000400004081B2000004000040C0 +:1042100081B200000400004081B2000004000040B0 +:1042200081B200000400004081B2000004000040A0 +:1042300081B200000400004081B200000400004090 +:1042400081B200000400004081B200000400004080 +:1042500081B200000400004081B200000400004070 +:1042600081B200000400004081B200000400004060 +:1042700081B200000400004081B200000400004050 +:1042800081B200000400004081B200000400004040 +:1042900081B200000400004081B200000400004030 +:1042A00081B200000400004081B200000400004020 +:1042B00081B200000400004081B200000400004010 +:1042C00081B200000400004081B200000400004000 +:1042D00081B200000400004081B2000004000040F0 +:1042E00081B200000400004081B2000004000040E0 +:1042F00081B200000400004081B2000004000040D0 +:1043000081B200000400004081B2000004000040BF +:1043100081B200000400004081B2000004000040AF +:1043200081B200000400004081B20000040000409F +:1043300081B200000400004081B20000040000408F +:1043400081B200000400004081B20000040000407F +:1043500081B200000400004081B20000040000406F +:1043600081B200000400004081B20000040000405F +:1043700081B200000400004081B20000040000404F +:1043800081B200000400004081B20000040000403F +:1043900081B200000400004081B20000040000402F +:1043A00081B200000400004081B20000040000401F +:1043B00081B200000400004081B20000040000400F +:1043C00081B200000400004081B2000004000040FF +:1043D00081B200000400004081B2000004000040EF +:1043E00081B200000400004081B2000004000040DF +:1043F00081B200000400004081B2000004000040CF +:1044000081B200000400004081B2000004000040BE +:1044100081B200000400004081B2000004000040AE +:1044200081B200000400004081B20000040000409E +:1044300081B200000400004081B20000040000408E +:1044400081B200000400004081B20000040000407E +:1044500081B200000400004081B20000040000406E +:1044600081B200000400004081B20000040000405E +:1044700081B200000400004081B20000040000404E +:1044800081B200000400004081B20000040000403E +:1044900081B200000400004081B20000040000402E +:1044A00081B200000400004081B20000040000401E +:1044B00081B200000400004081B20000040000400E +:1044C00081B200000400004081B2000004000040FE +:1044D00081B200000400004081B2000004000040EE +:1044E00081B200000400004081B2000004000040DE +:1044F00081B200000400004081B2000004000040CE +:1045000081B200000400004081B2000004000040BD +:1045100081B200000400004081B2000004000040AD +:1045200081B200000400004081B20000040000409D +:1045300081B200000400004081B20000040000408D +:1045400081B200000400004081B20000040000407D +:1045500081B200000400004081B20000040000406D +:1045600081B200000400004081B20000040000405D +:1045700081B200000400004081B20000040000404D +:1045800081B200000400004081B20000040000403D +:1045900081B200000400004081B20000040000402D +:1045A00081B200000400004081B20000040000401D +:1045B00081B200000400004081B20000040000400D +:1045C00081B200000400004081B2000004000040FD +:1045D00081B200000400004081B2000004000040ED +:1045E00081B200000400004081B2000004000040DD +:1045F00081B200000400004081B2000004000040CD +:1046000081B200000400004081B2000004000040BC +:1046100081B200000400004081B2000004000040AC +:1046200081B200000400004081B20000040000409C +:1046300081B200000400004081B20000040000408C +:1046400081B200000400004081B20000040000407C +:1046500081B200000400004081B20000040000406C +:1046600081B200000400004081B20000040000405C +:1046700081B200000400004081B20000040000404C +:1046800081B200000400004081B20000040000403C +:1046900081B200000400004081B20000040000402C +:1046A00081B200000400004081B20000040000401C +:1046B00081B200000400004081B20000040000400C +:1046C00081B200000400004081B2000004000040FC +:1046D00081B200000400004081B2000004000040EC +:1046E00081B200000400004081B2000004000040DC +:1046F00081B200000400004081B2000004000040CC +:1047000081B200000400004081B2000004000040BB +:1047100081B200000400004081B2000004000040AB +:1047200081B200000400004081B20000040000409B +:1047300081B200000400004081B20000040000408B +:1047400081B200000400004081B20000040000407B +:1047500081B200000400004081B20000040000406B +:1047600081B200000400004081B20000040000405B +:1047700081B200000400004081B20000040000404B +:1047800081B200000400004081B20000040000403B +:1047900081B200000400004081B20000040000402B +:1047A00081B200000400004081B20000040000401B +:1047B00081B200000400004081B20000040000400B +:1047C00081B200000400004081B2000004000040FB +:1047D00081B200000400004081B2000004000040EB +:1047E00081B200000400004081B2000004000040DB +:1047F00081B200000400004081B2000004000040CB +:1048000081B200000400004081B2000004000040BA +:1048100081B200000400004081B2000004000040AA +:1048200081B200000400004081B20000040000409A +:1048300081B200000400004081B20000040000408A +:1048400081B200000400004081B20000040000407A +:1048500081B200000400004081B20000040000406A +:1048600081B200000400004081B20000040000405A +:1048700081B200000400004081B20000040000404A +:1048800081B200000400004081B20000040000403A +:1048900081B200000400004081B20000040000402A +:1048A00081B200000400004081B20000040000401A +:1048B00081B200000400004081B20000040000400A +:1048C00081B200000400004081B2000004000040FA +:1048D00081B200000400004081B2000004000040EA +:1048E00081B200000400004081B2000004000040DA +:1048F00081B200000400004081B2000004000040CA +:1049000081B200000400004081B2000004000040B9 +:1049100081B200000400004081B2000004000040A9 +:1049200081B200000400004081B200000400004099 +:1049300081B200000400004081B200000400004089 +:1049400081B200000400004081B200000400004079 +:1049500081B200000400004081B200000400004069 +:1049600081B200000400004081B200000400004059 +:1049700081B200000400004081B200000400004049 +:1049800081B200000400004081B200000400004039 +:1049900081B200000400004081B200000400004029 +:1049A00081B200000400004081B200000400004019 +:1049B00081B200000400004081B200000400004009 +:1049C00081B200000400004081B2000004000040F9 +:1049D00081B200000400004081B2000004000040E9 +:1049E00081B200000400004081B2000004000040D9 +:1049F00081B200000400004081B2000004000040C9 +:104A000081B200000400004081B2000004000040B8 +:104A100081B200000400004081B2000004000040A8 +:104A200081B200000400004081B200000400004098 +:104A300081B200000400004081B200000400004088 +:104A400081B200000400004081B200000400004078 +:104A500081B200000400004081B200000400004068 +:104A600081B200000400004081B200000400004058 +:104A700081B200000400004081B200000400004048 +:104A800081B200000400004081B200000400004038 +:104A900081B200000400004081B200000400004028 +:104AA00081B200000400004081B200000400004018 +:104AB00081B200000400004081B200000400004008 +:104AC00081B200000400004081B2000004000040F8 +:104AD00081B200000400004081B2000004000040E8 +:104AE00081B200000400004081B2000004000040D8 +:104AF00081B200000400004081B2000004000040C8 +:104B000081B200000400004081B2000004000040B7 +:104B100081B200000400004081B2000004000040A7 +:104B200081B200000400004081B200000400004097 +:104B300081B200000400004081B200000400004087 +:104B400081B200000400004081B200000400004077 +:104B500081B200000400004081B200000400004067 +:104B600081B200000400004081B200000400004057 +:104B700081B200000400004081B200000400004047 +:104B800081B200000400004081B200000400004037 +:104B900081B200000400004081B200000400004027 +:104BA00081B200000400004081B200000400004017 +:104BB00081B200000400004081B200000400004007 +:104BC00081B200000400004081B2000004000040F7 +:104BD00081B200000400004081B2000004000040E7 +:104BE00081B200000400004081B2000004000040D7 +:104BF00081B200000400004081B2000004000040C7 +:104C000081B200000400004081B2000004000040B6 +:104C100081B200000400004081B2000004000040A6 +:104C200081B200000400004081B200000400004096 +:104C300081B200000400004081B200000400004086 +:104C400081B200000400004081B200000400004076 +:104C500081B200000400004081B200000400004066 +:104C600081B200000400004081B200000400004056 +:104C700081B200000400004081B200000400004046 +:104C800081B200000400004081B200000400004036 +:104C900081B200000400004081B200000400004026 +:104CA00081B200000400004081B200000400004016 +:104CB00081B200000400004081B200000400004006 +:104CC00081B200000400004081B2000004000040F6 +:104CD00081B200000400004081B2000004000040E6 +:104CE00081B200000400004081B2000004000040D6 +:104CF00081B200000400004081B2000004000040C6 +:104D000081B200000400004081B2000004000040B5 +:104D100081B200000400004081B2000004000040A5 +:104D200081B200000400004081B200000400004095 +:104D300081B200000400004081B200000400004085 +:104D400081B200000400004081B200000400004075 +:104D500081B200000400004081B200000400004065 +:104D600081B200000400004081B200000400004055 +:104D700081B200000400004081B200000400004045 +:104D800081B200000400004081B200000400004035 +:104D900081B200000400004081B200000400004025 +:104DA00081B200000400004081B200000400004015 +:104DB00081B200000400004081B200000400004005 +:104DC00081B200000400004081B2000004000040F5 +:104DD00081B200000400004081B2000004000040E5 +:104DE00081B200000400004081B2000004000040D5 +:104DF00081B200000400004081B2000004000040C5 +:104E000081B200000400004081B2000004000040B4 +:104E100081B200000400004081B2000004000040A4 +:104E200081B200000400004081B200000400004094 +:104E300081B200000400004081B200000400004084 +:104E400081B200000400004081B200000400004074 +:104E500081B200000400004081B200000400004064 +:104E600081B200000400004081B200000400004054 +:104E700081B200000400004081B200000400004044 +:104E800081B200000400004081B200000400004034 +:104E900081B200000400004081B200000400004024 +:104EA00081B200000400004081B200000400004014 +:104EB00081B200000400004081B200000400004004 +:104EC00081B200000400004081B2000004000040F4 +:104ED00081B200000400004081B2000004000040E4 +:104EE00081B200000400004081B2000004000040D4 +:104EF00081B200000400004081B2000004000040C4 +:104F000081B200000400004081B2000004000040B3 +:104F100081B200000400004081B2000004000040A3 +:104F200081B200000400004081B200000400004093 +:104F300081B200000400004081B200000400004083 +:104F400081B200000400004081B200000400004073 +:104F500081B200000400004081B200000400004063 +:104F600081B200000400004081B200000400004053 +:104F700081B200000400004081B200000400004043 +:104F800081B200000400004081B200000400004033 +:104F900081B200000400004081B200000400004023 +:104FA00081B200000400004081B200000400004013 +:104FB00081B200000400004081B200000400004003 +:104FC00081B200000400004081B2000004000040F3 +:104FD00081B200000400004081B2000004000040E3 +:104FE00081B200000400004081B2000004000040D3 +:104FF00081B200000400004081B2000004000040C3 +:1050000081B200000400004081B2000004000040B2 +:1050100081B200000400004081B2000004000040A2 +:1050200081B200000400004081B200000400004092 +:1050300081B200000400004081B200000400004082 +:1050400081B200000400004081B200000400004072 +:1050500081B200000400004081B200000400004062 +:1050600081B200000400004081B200000400004052 +:1050700081B200000400004081B200000400004042 +:1050800081B200000400004081B200000400004032 +:1050900081B200000400004081B200000400004022 +:1050A00081B200000400004081B200000400004012 +:1050B00081B200000400004081B200000400004002 +:1050C00081B200000400004081B2000004000040F2 +:1050D00081B200000400004081B2000004000040E2 +:1050E00081B200000400004081B2000004000040D2 +:1050F00081B200000400004081B2000004000040C2 +:1051000081B200000400004081B2000004000040B1 +:1051100081B200000400004081B2000004000040A1 +:1051200081B200000400004081B200000400004091 +:1051300081B200000400004081B200000400004081 +:1051400081B200000400004081B200000400004071 +:1051500081B200000400004081B200000400004061 +:1051600081B200000400004081B200000400004051 +:1051700081B200000400004081B200000400004041 +:1051800081B200000400004081B200000400004031 +:1051900081B200000400004081B200000400004021 +:1051A00081B200000400004081B200000400004011 +:1051B00081B200000400004081B200000400004001 +:1051C00081B200000400004081B2000004000040F1 +:1051D00081B200000400004081B2000004000040E1 +:1051E00081B200000400004081B2000004000040D1 +:1051F00081B200000400004081B2000004000040C1 +:1052000081B200000400004081B2000004000040B0 +:1052100081B200000400004081B2000004000040A0 +:1052200081B200000400004081B200000400004090 +:1052300081B200000400004081B200000400004080 +:1052400081B200000400004081B200000400004070 +:1052500081B200000400004081B200000400004060 +:1052600081B200000400004081B200000400004050 +:1052700081B200000400004081B200000400004040 +:1052800081B200000400004081B200000400004030 +:1052900081B200000400004081B200000400004020 +:1052A00081B200000400004081B200000400004010 +:1052B00081B200000400004081B200000400004000 +:1052C00081B200000400004081B2000004000040F0 +:1052D00081B200000400004081B2000004000040E0 +:1052E00081B200000400004081B2000004000040D0 +:1052F00081B200000400004081B2000004000040C0 +:1053000081B200000400004081B2000004000040AF +:1053100081B200000400004081B20000040000409F +:1053200081B200000400004081B20000040000408F +:1053300081B200000400004081B20000040000407F +:1053400081B200000400004081B20000040000406F +:1053500081B200000400004081B20000040000405F +:1053600081B200000400004081B20000040000404F +:1053700081B200000400004081B20000040000403F +:1053800081B200000400004081B20000040000402F +:1053900081B200000400004081B20000040000401F +:1053A00081B200000400004081B20000040000400F +:1053B00081B200000400004081B2000004000040FF +:1053C00081B200000400004081B2000004000040EF +:1053D00081B200000400004081B2000004000040DF +:1053E00081B200000400004081B2000004000040CF +:1053F00081B200000400004081B2000004000040BF +:1054000081B200000400004081B2000004000040AE +:1054100081B200000400004081B20000040000409E +:1054200081B200000400004081B20000040000408E +:1054300081B200000400004081B20000040000407E +:1054400081B200000400004081B20000040000406E +:1054500081B200000400004081B20000040000405E +:1054600081B200000400004081B20000040000404E +:1054700081B200000400004081B20000040000403E +:1054800081B200000400004081B20000040000402E +:1054900081B200000400004081B20000040000401E +:1054A00081B200000400004081B20000040000400E +:1054B00081B200000400004081B2000004000040FE +:1054C00081B200000400004081B2000004000040EE +:1054D00081B200000400004081B2000004000040DE +:1054E00081B200000400004081B2000004000040CE +:1054F00081B200000400004081B2000004000040BE +:1055000081B200000400004081B2000004000040AD +:1055100081B200000400004081B20000040000409D +:1055200081B200000400004081B20000040000408D +:1055300081B200000400004081B20000040000407D +:1055400081B200000400004081B20000040000406D +:1055500081B200000400004081B20000040000405D +:1055600081B200000400004081B20000040000404D +:1055700081B200000400004081B20000040000403D +:1055800081B200000400004081B20000040000402D +:1055900081B200000400004081B20000040000401D +:1055A00081B200000400004081B20000040000400D +:1055B00081B200000400004081B2000004000040FD +:1055C00081B200000400004081B2000004000040ED +:1055D00081B200000400004081B2000004000040DD +:1055E00081B200000400004081B2000004000040CD +:1055F00081B200000400004081B2000004000040BD +:1056000081B200000400004081B2000004000040AC +:1056100081B200000400004081B20000040000409C +:1056200081B200000400004081B20000040000408C +:1056300081B200000400004081B20000040000407C +:1056400081B200000400004081B20000040000406C +:1056500081B200000400004081B20000040000405C +:1056600081B200000400004081B20000040000404C +:1056700081B200000400004081B20000040000403C +:1056800081B200000400004081B20000040000402C +:1056900081B200000400004081B20000040000401C +:1056A00081B200000400004081B20000040000400C +:1056B00081B200000400004081B2000004000040FC +:1056C00081B200000400004081B2000004000040EC +:1056D00081B200000400004081B2000004000040DC +:1056E00081B200000400004081B2000004000040CC +:1056F00081B200000400004081B2000004000040BC +:1057000081B200000400004081B2000004000040AB +:1057100081B200000400004081B20000040000409B +:1057200081B200000400004081B20000040000408B +:1057300081B200000400004081B20000040000407B +:1057400081B200000400004081B20000040000406B +:1057500081B200000400004081B20000040000405B +:1057600081B200000400004081B20000040000404B +:1057700081B200000400004081B20000040000403B +:1057800081B200000400004081B20000040000402B +:1057900081B200000400004081B20000040000401B +:1057A00081B200000400004081B20000040000400B +:1057B00081B200000400004081B2000004000040FB +:1057C00081B200000400004081B2000004000040EB +:1057D00081B200000400004081B2000004000040DB +:1057E00081B200000400004081B2000004000040CB +:1057F00081B200000400004081B2000004000040BB +:1058000081B200000400004081B2000004000040AA +:1058100081B200000400004081B20000040000409A +:1058200081B200000400004081B20000040000408A +:1058300081B200000400004081B20000040000407A +:1058400081B200000400004081B20000040000406A +:1058500081B200000400004081B20000040000405A +:1058600081B200000400004081B20000040000404A +:1058700081B200000400004081B20000040000403A +:1058800081B200000400004081B20000040000402A +:1058900081B200000400004081B20000040000401A +:1058A00081B200000400004081B20000040000400A +:1058B00081B200000400004081B2000004000040FA +:1058C00081B200000400004081B2000004000040EA +:1058D00081B200000400004081B2000004000040DA +:1058E00081B200000400004081B2000004000040CA +:1058F00081B200000400004081B2000004000040BA +:1059000081B200000400004081B2000004000040A9 +:1059100081B200000400004081B200000400004099 +:1059200081B200000400004081B200000400004089 +:1059300081B200000400004081B200000400004079 +:1059400081B200000400004081B200000400004069 +:1059500081B200000400004081B200000400004059 +:1059600081B200000400004081B200000400004049 +:1059700081B200000400004081B200000400004039 +:1059800081B200000400004081B200000400004029 +:1059900081B200000400004081B200000400004019 +:1059A00081B200000400004081B200000400004009 +:1059B00081B200000400004081B2000004000040F9 +:1059C00081B200000400004081B2000004000040E9 +:1059D00081B200000400004081B2000004000040D9 +:1059E00081B200000400004081B2000004000040C9 +:1059F00081B200000400004081B2000004000040B9 +:105A000081B200000400004081B2000004000040A8 +:105A100081B200000400004081B200000400004098 +:105A200081B200000400004081B200000400004088 +:105A300081B200000400004081B200000400004078 +:105A400081B200000400004081B200000400004068 +:105A500081B200000400004081B200000400004058 +:105A600081B200000400004081B200000400004048 +:105A700081B200000400004081B200000400004038 +:105A800081B200000400004081B200000400004028 +:105A900081B200000400004081B200000400004018 +:105AA00081B200000400004081B200000400004008 +:105AB00081B200000400004081B2000004000040F8 +:105AC00081B200000400004081B2000004000040E8 +:105AD00081B200000400004081B2000004000040D8 +:105AE00081B200000400004081B2000004000040C8 +:105AF00081B200000400004081B2000004000040B8 +:105B000081B200000400004081B2000004000040A7 +:105B100081B200000400004081B200000400004097 +:105B200081B200000400004081B200000400004087 +:105B300081B200000400004081B200000400004077 +:105B400081B200000400004081B200000400004067 +:105B500081B200000400004081B200000400004057 +:105B600081B200000400004081B200000400004047 +:105B700081B200000400004081B200000400004037 +:105B800081B200000400004081B200000400004027 +:105B900081B200000400004081B200000400004017 +:105BA00081B200000400004081B200000400004007 +:105BB00081B200000400004081B2000004000040F7 +:105BC00081B200000400004081B2000004000040E7 +:105BD00081B200000400004081B2000004000040D7 +:105BE00081B200000400004081B2000004000040C7 +:105BF00081B200000400004081B2000004000040B7 +:105C000081B200000400004081B2000004000040A6 +:105C100081B200000400004081B200000400004096 +:105C200081B200000400004081B200000400004086 +:105C300081B200000400004081B200000400004076 +:105C400081B200000400004081B200000400004066 +:105C500081B200000400004081B200000400004056 +:105C600081B200000400004081B200000400004046 +:105C700081B200000400004081B200000400004036 +:105C800081B200000400004081B200000400004026 +:105C900081B200000400004081B200000400004016 +:105CA00081B200000400004081B200000400004006 +:105CB00081B200000400004081B2000004000040F6 +:105CC00081B200000400004081B2000004000040E6 +:105CD00081B200000400004081B2000004000040D6 +:105CE00081B200000400004081B2000004000040C6 +:105CF00081B200000400004081B2000004000040B6 +:105D000081B200000400004081B2000004000040A5 +:105D100081B200000400004081B200000400004095 +:105D200081B200000400004081B200000400004085 +:105D300081B200000400004081B200000400004075 +:105D400081B200000400004081B200000400004065 +:105D500081B200000400004081B200000400004055 +:105D600081B200000400004081B200000400004045 +:105D700081B200000400004081B200000400004035 +:105D800081B200000400004081B200000400004025 +:105D900081B200000400004081B200000400004015 +:105DA00081B200000400004081B200000400004005 +:105DB00081B200000400004081B2000004000040F5 +:105DC00081B200000400004081B2000004000040E5 +:105DD00081B200000400004081B2000004000040D5 +:105DE00081B200000400004081B2000004000040C5 +:105DF00081B200000400004081B2000004000040B5 +:105E000081B200000400004081B2000004000040A4 +:105E100081B200000400004081B200000400004094 +:105E200081B200000400004081B200000400004084 +:105E300081B200000400004081B200000400004074 +:105E400081B200000400004081B200000400004064 +:105E500081B200000400004081B200000400004054 +:105E600081B200000400004081B200000400004044 +:105E700081B200000400004081B200000400004034 +:105E800081B200000400004081B200000400004024 +:105E900081B200000400004081B200000400004014 +:105EA00081B200000400004081B200000400004004 +:105EB00081B200000400004081B2000004000040F4 +:105EC00081B200000400004081B2000004000040E4 +:105ED00081B200000400004081B2000004000040D4 +:105EE00081B200000400004081B2000004000040C4 +:105EF00081B200000400004081B2000004000040B4 +:105F000081B200000400004081B2000004000040A3 +:105F100081B200000400004081B200000400004093 +:105F200081B200000400004081B200000400004083 +:105F300081B200000400004081B200000400004073 +:105F400081B200000400004081B200000400004063 +:105F500081B200000400004081B200000400004053 +:105F600081B200000400004081B200000400004043 +:105F700081B200000400004081B200000400004033 +:105F800081B200000400004081B200000400004023 +:105F900081B200000400004081B200000400004013 +:105FA00081B200000400004081B200000400004003 +:105FB00081B200000400004081B2000004000040F3 +:105FC00081B200000400004081B2000004000040E3 +:105FD00081B200000400004081B2000004000040D3 +:105FE00081B200000400004081B2000004000040C3 +:105FF00081B200000400004081B2000004000040B3 +:1060000081B200000400004081B2000004000040A2 +:1060100081B200000400004081B200000400004092 +:1060200081B200000400004081B200000400004082 +:1060300081B200000400004081B200000400004072 +:1060400081B200000400004081B200000400004062 +:1060500081B200000400004081B200000400004052 +:1060600081B200000400004081B200000400004042 +:1060700081B200000400004081B200000400004032 +:1060800081B200000400004081B200000400004022 +:1060900081B200000400004081B200000400004012 +:1060A00081B200000400004081B200000400004002 +:1060B00081B200000400004081B2000004000040F2 +:1060C00081B200000400004081B2000004000040E2 +:1060D00081B200000400004081B2000004000040D2 +:1060E00081B200000400004081B2000004000040C2 +:1060F00081B200000400004081B2000004000040B2 +:1061000081B200000400004081B2000004000040A1 +:1061100081B200000400004081B200000400004091 +:1061200081B200000400004081B200000400004081 +:1061300081B200000400004081B200000400004071 +:1061400081B200000400004081B200000400004061 +:1061500081B200000400004081B200000400004051 +:1061600081B200000400004081B200000400004041 +:1061700081B200000400004081B200000400004031 +:1061800081B200000400004081B200000400004021 +:1061900081B200000400004081B200000400004011 +:1061A00081B200000400004081B200000400004001 +:1061B00081B200000400004081B2000004000040F1 +:1061C00081B200000400004081B2000004000040E1 +:1061D00081B200000400004081B2000004000040D1 +:1061E00081B200000400004081B2000004000040C1 +:1061F00081B200000400004081B2000004000040B1 +:1062000081B200000400004081B2000004000040A0 +:1062100081B200000400004081B200000400004090 +:1062200081B200000400004081B200000400004080 +:1062300081B200000400004081B200000400004070 +:1062400081B200000400004081B200000400004060 +:1062500081B200000400004081B200000400004050 +:1062600081B200000400004081B200000400004040 +:1062700081B200000400004081B200000400004030 +:1062800081B200000400004081B200000400004020 +:1062900081B200000400004081B200000400004010 +:1062A00081B200000400004081B200000400004000 +:1062B00081B200000400004081B2000004000040F0 +:1062C00081B200000400004081B2000004000040E0 +:1062D00081B200000400004081B2000004000040D0 +:1062E00081B200000400004081B2000004000040C0 +:1062F00081B200000400004081B2000004000040B0 +:1063000081B200000400004081B20000040000409F +:1063100081B200000400004081B20000040000408F +:1063200081B200000400004081B20000040000407F +:1063300081B200000400004081B20000040000406F +:1063400081B200000400004081B20000040000405F +:1063500081B200000400004081B20000040000404F +:1063600081B200000400004081B20000040000403F +:1063700081B200000400004081B20000040000402F +:1063800081B200000400004081B20000040000401F +:1063900081B200000400004081B20000040000400F +:1063A00081B200000400004081B2000004000040FF +:1063B00081B200000400004081B2000004000040EF +:1063C00081B200000400004081B2000004000040DF +:1063D00081B200000400004081B2000004000040CF +:1063E00081B200000400004081B2000004000040BF +:1063F00081B200000400004081B2000004000040AF +:1064000081B200000400004081B20000040000409E +:1064100081B200000400004081B20000040000408E +:1064200081B200000400004081B20000040000407E +:1064300081B200000400004081B20000040000406E +:1064400081B200000400004081B20000040000405E +:1064500081B200000400004081B20000040000404E +:1064600081B200000400004081B20000040000403E +:1064700081B200000400004081B20000040000402E +:1064800081B200000400004081B20000040000401E +:1064900081B200000400004081B20000040000400E +:1064A00081B200000400004081B2000004000040FE +:1064B00081B200000400004081B2000004000040EE +:1064C00081B200000400004081B2000004000040DE +:1064D00081B200000400004081B2000004000040CE +:1064E00081B200000400004081B2000004000040BE +:1064F00081B200000400004081B2000004000040AE +:1065000081B200000400004081B20000040000409D +:1065100081B200000400004081B20000040000408D +:1065200081B200000400004081B20000040000407D +:1065300081B200000400004081B20000040000406D +:1065400081B200000400004081B20000040000405D +:1065500081B200000400004081B20000040000404D +:1065600081B200000400004081B20000040000403D +:1065700081B200000400004081B20000040000402D +:1065800081B200000400004081B20000040000401D +:1065900081B200000400004081B20000040000400D +:1065A00081B200000400004081B2000004000040FD +:1065B00081B200000400004081B2000004000040ED +:1065C00081B200000400004081B2000004000040DD +:1065D00081B200000400004081B2000004000040CD +:1065E00081B200000400004081B2000004000040BD +:1065F00081B200000400004081B2000004000040AD +:1066000081B200000400004081B20000040000409C +:1066100081B200000400004081B20000040000408C +:1066200081B200000400004081B20000040000407C +:1066300081B200000400004081B20000040000406C +:1066400081B200000400004081B20000040000405C +:1066500081B200000400004081B20000040000404C +:1066600081B200000400004081B20000040000403C +:1066700081B200000400004081B20000040000402C +:1066800081B200000400004081B20000040000401C +:1066900081B200000400004081B20000040000400C +:1066A00081B200000400004081B2000004000040FC +:1066B00081B200000400004081B2000004000040EC +:1066C00081B200000400004081B2000004000040DC +:1066D00081B200000400004081B2000004000040CC +:1066E00081B200000400004081B2000004000040BC +:1066F00081B200000400004081B2000004000040AC +:1067000081B200000400004081B20000040000409B +:1067100081B200000400004081B20000040000408B +:1067200081B200000400004081B20000040000407B +:1067300081B200000400004081B20000040000406B +:1067400081B200000400004081B20000040000405B +:1067500081B200000400004081B20000040000404B +:1067600081B200000400004081B20000040000403B +:1067700081B200000400004081B20000040000402B +:1067800081B200000400004081B20000040000401B +:1067900081B200000400004081B20000040000400B +:1067A00081B200000400004081B2000004000040FB +:1067B00081B200000400004081B2000004000040EB +:1067C00081B200000400004081B2000004000040DB +:1067D00081B200000400004081B2000004000040CB +:1067E00081B200000400004081B2000004000040BB +:1067F00081B200000400004081B2000004000040AB +:1068000081B200000400004081B20000040000409A +:1068100081B200000400004081B20000040000408A +:1068200081B200000400004081B20000040000407A +:1068300081B200000400004081B20000040000406A +:1068400081B200000400004081B20000040000405A +:1068500081B200000400004081B20000040000404A +:1068600081B200000400004081B20000040000403A +:1068700081B200000400004081B20000040000402A +:1068800081B200000400004081B20000040000401A +:1068900081B200000400004081B20000040000400A +:1068A00081B200000400004081B2000004000040FA +:1068B00081B200000400004081B2000004000040EA +:1068C00081B200000400004081B2000004000040DA +:1068D00081B200000400004081B2000004000040CA +:1068E00081B200000400004081B2000004000040BA +:1068F00081B200000400004081B2000004000040AA +:1069000081B200000400004081B200000400004099 +:1069100081B200000400004081B200000400004089 +:1069200081B200000400004081B200000400004079 +:1069300081B200000400004081B200000400004069 +:1069400081B200000400004081B200000400004059 +:1069500081B200000400004081B200000400004049 +:1069600081B200000400004081B200000400004039 +:1069700081B200000400004081B200000400004029 +:1069800081B200000400004081B200000400004019 +:1069900081B200000400004081B200000400004009 +:1069A00081B200000400004081B2000004000040F9 +:1069B00081B200000400004081B2000004000040E9 +:1069C00081B200000400004081B2000004000040D9 +:1069D00081B200000400004081B2000004000040C9 +:1069E00081B200000400004081B2000004000040B9 +:1069F00081B200000400004081B2000004000040A9 +:106A000081B200000400004081B200000400004098 +:106A100081B200000400004081B200000400004088 +:106A200081B200000400004081B200000400004078 +:106A300081B200000400004081B200000400004068 +:106A400081B200000400004081B200000400004058 +:106A500081B200000400004081B200000400004048 +:106A600081B200000400004081B200000400004038 +:106A700081B200000400004081B200000400004028 +:106A800081B200000400004081B200000400004018 +:106A900081B200000400004081B200000400004008 +:106AA00081B200000400004081B2000004000040F8 +:106AB00081B200000400004081B2000004000040E8 +:106AC00081B200000400004081B2000004000040D8 +:106AD00081B200000400004081B2000004000040C8 +:106AE00081B200000400004081B2000004000040B8 +:106AF00081B200000400004081B2000004000040A8 +:106B000081B200000400004081B200000400004097 +:106B100081B200000400004081B200000400004087 +:106B200081B200000400004081B200000400004077 +:106B300081B200000400004081B200000400004067 +:106B400081B200000400004081B200000400004057 +:106B500081B200000400004081B200000400004047 +:106B600081B200000400004081B200000400004037 +:106B700081B200000400004081B200000400004027 +:106B800081B200000400004081B200000400004017 +:106B900081B200000400004081B200000400004007 +:106BA00081B200000400004081B2000004000040F7 +:106BB00081B200000400004081B2000004000040E7 +:106BC00081B200000400004081B2000004000040D7 +:106BD00081B200000400004081B2000004000040C7 +:106BE00081B200000400004081B2000004000040B7 +:106BF00081B200000400004081B2000004000040A7 +:106C000081B200000400004081B200000400004096 +:106C100081B200000400004081B200000400004086 +:106C200081B200000400004081B200000400004076 +:106C300081B200000400004081B200000400004066 +:106C400081B200000400004081B200000400004056 +:106C500081B200000400004081B200000400004046 +:106C600081B200000400004081B200000400004036 +:106C700081B200000400004081B200000400004026 +:106C800081B200000400004081B200000400004016 +:106C900081B200000400004081B200000400004006 +:106CA00081B200000400004081B2000004000040F6 +:106CB00081B200000400004081B2000004000040E6 +:106CC00081B200000400004081B2000004000040D6 +:106CD00081B200000400004081B2000004000040C6 +:106CE00081B200000400004081B2000004000040B6 +:106CF00081B200000400004081B2000004000040A6 +:106D000081B200000400004081B200000400004095 +:106D100081B200000400004081B200000400004085 +:106D200081B200000400004081B200000400004075 +:106D300081B200000400004081B200000400004065 +:106D400081B200000400004081B200000400004055 +:106D500081B200000400004081B200000400004045 +:106D600081B200000400004081B200000400004035 +:106D700081B200000400004081B200000400004025 +:106D800081B200000400004081B200000400004015 +:106D900081B200000400004081B200000400004005 +:106DA00081B200000400004081B2000004000040F5 +:106DB00081B200000400004081B2000004000040E5 +:106DC00081B200000400004081B2000004000040D5 +:106DD00081B200000400004081B2000004000040C5 +:106DE00081B200000400004081B2000004000040B5 +:106DF00081B200000400004081B2000004000040A5 +:106E000081B200000400004081B200000400004094 +:106E100081B200000400004081B200000400004084 +:106E200081B200000400004081B200000400004074 +:106E300081B200000400004081B200000400004064 +:106E400081B200000400004081B200000400004054 +:106E500081B200000400004081B200000400004044 +:106E600081B200000400004081B200000400004034 +:106E700081B200000400004081B200000400004024 +:106E800081B200000400004081B200000400004014 +:106E900081B200000400004081B200000400004004 +:106EA00081B200000400004081B2000004000040F4 +:106EB00081B200000400004081B2000004000040E4 +:106EC00081B200000400004081B2000004000040D4 +:106ED00081B200000400004081B2000004000040C4 +:106EE00081B200000400004081B2000004000040B4 +:106EF00081B200000400004081B2000004000040A4 +:106F000081B200000400004081B200000400004093 +:106F100081B200000400004081B200000400004083 +:106F200081B200000400004081B200000400004073 +:106F300081B200000400004081B200000400004063 +:106F400081B200000400004081B200000400004053 +:106F500081B200000400004081B200000400004043 +:106F600081B200000400004081B200000400004033 +:106F700081B200000400004081B200000400004023 +:106F800081B200000400004081B200000400004013 +:106F900081B200000400004081B200000400004003 +:106FA00081B200000400004081B2000004000040F3 +:106FB00081B200000400004081B2000004000040E3 +:106FC00081B200000400004081B2000004000040D3 +:106FD00081B200000400004081B2000004000040C3 +:106FE00081B200000400004081B2000004000040B3 +:106FF00081B200000400004081B2000004000040A3 +:1070000081B200000400004081B200000400004092 +:1070100081B200000400004081B200000400004082 +:1070200081B200000400004081B200000400004072 +:1070300081B200000400004081B200000400004062 +:1070400081B200000400004081B200000400004052 +:1070500081B200000400004081B200000400004042 +:1070600081B200000400004081B200000400004032 +:1070700081B200000400004081B200000400004022 +:1070800081B200000400004081B200000400004012 +:1070900081B200000400004081B200000400004002 +:1070A00081B200000400004081B2000004000040F2 +:1070B00081B200000400004081B2000004000040E2 +:1070C00081B200000400004081B2000004000040D2 +:1070D00081B200000400004081B2000004000040C2 +:1070E00081B200000400004081B2000004000040B2 +:1070F00081B200000400004081B2000004000040A2 +:1071000081B200000400004081B200000400004091 +:1071100081B200000400004081B200000400004081 +:1071200081B200000400004081B200000400004071 +:1071300081B200000400004081B200000400004061 +:1071400081B200000400004081B200000400004051 +:1071500081B200000400004081B200000400004041 +:1071600081B200000400004081B200000400004031 +:1071700081B200000400004081B200000400004021 +:1071800081B200000400004081B200000400004011 +:1071900081B200000400004081B200000400004001 +:1071A00081B200000400004081B2000004000040F1 +:1071B00081B200000400004081B2000004000040E1 +:1071C00081B200000400004081B2000004000040D1 +:1071D00081B200000400004081B2000004000040C1 +:1071E00081B200000400004081B2000004000040B1 +:1071F00081B200000400004081B2000004000040A1 +:1072000081B200000400004081B200000400004090 +:1072100081B200000400004081B200000400004080 +:1072200081B200000400004081B200000400004070 +:1072300081B200000400004081B200000400004060 +:1072400081B200000400004081B200000400004050 +:1072500081B200000400004081B200000400004040 +:1072600081B200000400004081B200000400004030 +:1072700081B200000400004081B200000400004020 +:1072800081B200000400004081B200000400004010 +:1072900081B200000400004081B200000400004000 +:1072A00081B200000400004081B2000004000040F0 +:1072B00081B200000400004081B2000004000040E0 +:1072C00081B200000400004081B2000004000040D0 +:1072D00081B200000400004081B2000004000040C0 +:1072E00081B200000400004081B2000004000040B0 +:1072F00081B200000400004081B2000004000040A0 +:1073000081B200000400004081B20000040000408F +:1073100081B200000400004081B20000040000407F +:1073200081B200000400004081B20000040000406F +:1073300081B200000400004081B20000040000405F +:1073400081B200000400004081B20000040000404F +:1073500081B200000400004081B20000040000403F +:1073600081B200000400004081B20000040000402F +:1073700081B200000400004081B20000040000401F +:1073800081B200000400004081B20000040000400F +:1073900081B200000400004081B2000004000040FF +:1073A00081B200000400004081B2000004000040EF +:1073B00081B200000400004081B2000004000040DF +:1073C00081B200000400004081B2000004000040CF +:1073D00081B200000400004081B2000004000040BF +:1073E00081B200000400004081B2000004000040AF +:1073F00081B200000400004081B20000040000409F +:1074000081B200000400004081B20000040000408E +:1074100081B200000400004081B20000040000407E +:1074200081B200000400004081B20000040000406E +:1074300081B200000400004081B20000040000405E +:1074400081B200000400004081B20000040000404E +:1074500081B200000400004081B20000040000403E +:1074600081B200000400004081B20000040000402E +:1074700081B200000400004081B20000040000401E +:1074800081B200000400004081B20000040000400E +:1074900081B200000400004081B2000004000040FE +:1074A00081B200000400004081B2000004000040EE +:1074B00081B200000400004081B2000004000040DE +:1074C00081B200000400004081B2000004000040CE +:1074D00081B200000400004081B2000004000040BE +:1074E00081B200000400004081B2000004000040AE +:1074F00081B200000400004081B20000040000409E +:1075000081B200000400004081B20000040000408D +:1075100081B200000400004081B20000040000407D +:1075200081B200000400004081B20000040000406D +:1075300081B200000400004081B20000040000405D +:1075400081B200000400004081B20000040000404D +:1075500081B200000400004081B20000040000403D +:1075600081B200000400004081B20000040000402D +:1075700081B200000400004081B20000040000401D +:1075800081B200000400004081B20000040000400D +:1075900081B200000400004081B2000004000040FD +:1075A00081B200000400004081B2000004000040ED +:1075B00081B200000400004081B2000004000040DD +:1075C00081B200000400004081B2000004000040CD +:1075D00081B200000400004081B2000004000040BD +:1075E00081B200000400004081B2000004000040AD +:1075F00081B200000400004081B20000040000409D +:1076000081B200000400004081B20000040000408C +:1076100081B200000400004081B20000040000407C +:1076200081B200000400004081B20000040000406C +:1076300081B200000400004081B20000040000405C +:1076400081B200000400004081B20000040000404C +:1076500081B200000400004081B20000040000403C +:1076600081B200000400004081B20000040000402C +:1076700081B200000400004081B20000040000401C +:1076800081B200000400004081B20000040000400C +:1076900081B200000400004081B2000004000040FC +:1076A00081B200000400004081B2000004000040EC +:1076B00081B200000400004081B2000004000040DC +:1076C00081B200000400004081B2000004000040CC +:1076D00081B200000400004081B2000004000040BC +:1076E00081B200000400004081B2000004000040AC +:1076F00081B200000400004081B20000040000409C +:1077000081B200000400004081B20000040000408B +:1077100081B200000400004081B20000040000407B +:1077200081B200000400004081B20000040000406B +:1077300081B200000400004081B20000040000405B +:1077400081B200000400004081B20000040000404B +:1077500081B200000400004081B20000040000403B +:1077600081B200000400004081B20000040000402B +:1077700081B200000400004081B20000040000401B +:1077800081B200000400004081B20000040000400B +:1077900081B200000400004081B2000004000040FB +:1077A00081B200000400004081B2000004000040EB +:1077B00081B200000400004081B2000004000040DB +:1077C00081B200000400004081B2000004000040CB +:1077D00081B200000400004081B2000004000040BB +:1077E00081B200000400004081B2000004000040AB +:1077F00081B200000400004081B20000040000409B +:1078000081B200000400004081B20000040000408A +:1078100081B200000400004081B20000040000407A +:1078200081B200000400004081B20000040000406A +:1078300081B200000400004081B20000040000405A +:1078400081B200000400004081B20000040000404A +:1078500081B200000400004081B20000040000403A +:1078600081B200000400004081B20000040000402A +:1078700081B200000400004081B20000040000401A +:1078800081B200000400004081B20000040000400A +:1078900081B200000400004081B2000004000040FA +:1078A00081B200000400004081B2000004000040EA +:1078B00081B200000400004081B2000004000040DA +:1078C00081B200000400004081B2000004000040CA +:1078D00081B200000400004081B2000004000040BA +:1078E00081B200000400004081B2000004000040AA +:1078F00081B200000400004081B20000040000409A +:1079000081B200000400004081B200000400004089 +:1079100081B200000400004081B200000400004079 +:1079200081B200000400004081B200000400004069 +:1079300081B200000400004081B200000400004059 +:1079400081B200000400004081B200000400004049 +:1079500081B200000400004081B200000400004039 +:1079600081B200000400004081B200000400004029 +:1079700081B200000400004081B200000400004019 +:1079800081B200000400004081B200000400004009 +:1079900081B200000400004081B2000004000040F9 +:1079A00081B200000400004081B2000004000040E9 +:1079B00081B200000400004081B2000004000040D9 +:1079C00081B200000400004081B2000004000040C9 +:1079D00081B200000400004081B2000004000040B9 +:1079E00081B200000400004081B2000004000040A9 +:1079F00081B200000400004081B200000400004099 +:107A000081B200000400004081B200000400004088 +:107A100081B200000400004081B200000400004078 +:107A200081B200000400004081B200000400004068 +:107A300081B200000400004081B200000400004058 +:107A400081B200000400004081B200000400004048 +:107A500081B200000400004081B200000400004038 +:107A600081B200000400004081B200000400004028 +:107A700081B200000400004081B200000400004018 +:107A800081B200000400004081B200000400004008 +:107A900081B200000400004081B2000004000040F8 +:107AA00081B200000400004081B2000004000040E8 +:107AB00081B200000400004081B2000004000040D8 +:107AC00081B200000400004081B2000004000040C8 +:107AD00081B200000400004081B2000004000040B8 +:107AE00081B200000400004081B2000004000040A8 +:107AF00081B200000400004081B200000400004098 +:107B000081B200000400004081B200000400004087 +:107B100081B200000400004081B200000400004077 +:107B200081B200000400004081B200000400004067 +:107B300081B200000400004081B200000400004057 +:107B400081B200000400004081B200000400004047 +:107B500081B200000400004081B200000400004037 +:107B600081B200000400004081B200000400004027 +:107B700081B200000400004081B200000400004017 +:107B800081B200000400004081B200000400004007 +:107B900081B200000400004081B2000004000040F7 +:107BA00081B200000400004081B2000004000040E7 +:107BB00081B200000400004081B2000004000040D7 +:107BC00081B200000400004081B2000004000040C7 +:107BD00081B200000400004081B2000004000040B7 +:107BE00081B200000400004081B2000004000040A7 +:107BF00081B200000400004081B200000400004097 +:107C000081B200000400004081B200000400004086 +:107C100081B200000400004081B200000400004076 +:107C200081B200000400004081B200000400004066 +:107C300081B200000400004081B200000400004056 +:107C400081B200000400004081B200000400004046 +:107C500081B200000400004081B200000400004036 +:107C600081B200000400004081B200000400004026 +:107C700081B200000400004081B200000400004016 +:107C800081B200000400004081B200000400004006 +:107C900081B200000400004081B2000004000040F6 +:107CA00081B200000400004081B2000004000040E6 +:107CB00081B200000400004081B2000004000040D6 +:107CC00081B200000400004081B2000004000040C6 +:107CD00081B200000400004081B2000004000040B6 +:107CE00081B200000400004081B2000004000040A6 +:107CF00081B200000400004081B200000400004096 +:107D000081B200000400004081B200000400004085 +:107D100081B200000400004081B200000400004075 +:107D200081B200000400004081B200000400004065 +:107D300081B200000400004081B200000400004055 +:107D400081B200000400004081B200000400004045 +:107D500081B200000400004081B200000400004035 +:107D600081B200000400004081B200000400004025 +:107D700081B200000400004081B200000400004015 +:107D800081B200000400004081B200000400004005 +:107D900081B200000400004081B2000004000040F5 +:107DA00081B200000400004081B2000004000040E5 +:107DB00081B200000400004081B2000004000040D5 +:107DC00081B200000400004081B2000004000040C5 +:107DD00081B200000400004081B2000004000040B5 +:107DE00081B200000400004081B2000004000040A5 +:107DF00081B200000400004081B200000400004095 +:107E000081B200000400004081B200000400004084 +:107E100081B200000400004081B200000400004074 +:107E200081B200000400004081B200000400004064 +:107E300081B200000400004081B200000400004054 +:107E400081B200000400004081B200000400004044 +:107E500081B200000400004081B200000400004034 +:107E600081B200000400004081B200000400004024 +:107E700081B200000400004081B200000400004014 +:107E800081B200000400004081B200000400004004 +:107E900081B200000400004081B2000004000040F4 +:107EA00081B200000400004081B2000004000040E4 +:107EB00081B200000400004081B2000004000040D4 +:107EC00081B200000400004081B2000004000040C4 +:107ED00081B200000400004081B2000004000040B4 +:107EE00081B200000400004081B2000004000040A4 +:107EF00081B200000400004081B200000400004094 +:107F000081B200000400004081B200000400004083 +:107F100081B200000400004081B200000400004073 +:107F200081B200000400004081B200000400004063 +:107F300081B200000400004081B200000400004053 +:107F400081B200000400004081B200000400004043 +:107F500081B200000400004081B200000400004033 +:107F600081B200000400004081B200000400004023 +:107F700081B200000400004081B200000400004013 +:107F800081B200000400004081B200000400004003 +:107F900081B200000400004081B2000004000040F3 +:107FA00081B200000400004081B2000004000040E3 +:107FB00081B200000400004081B2000004000040D3 +:107FC00081B200000400004081B20000F70F00BC45 +:107FD00080B200000380004081B2000003800040B6 +:107FE00081B200000380004081B2000003800040A5 +:107FF00081B200000380004081B200000380004095 +:1080000081B200000380004081B200000380004084 +:1080100081B200003180004081B200003480004015 +:1080200081B200003580004081B2000004000040B1 +:1080300081B200001B80818080320000EC89A24068 +:10804000916F00000000004C90B301005C952EA2DF +:1080500080B00100FF000080F489010090952AC8DB +:10806000E5B10100000000A1F0B1010000000040F6 +:10807000F0B10100000000A4F0B10100000000D048 +:10808000F0B10100000000D1F0B10100000000D209 +:10809000F0B101000000004CF0B10100000000D47C +:1080A000F0B10100000000D3F0B10100000000EECB +:1080B000F0B101000000004EF0B1010000000040EE +:1080C00044B1010018801181983000000000514037 +:1080D00081B201001A8011829830000000005240E5 +:1080E00081B20100EC890048FD930000B603004016 +:1080F000A19901002380A242FD7F00002080008022 +:1081000080320000228011818230000022805140A4 +:1081100081B2000022801182823000002280524011 +:1081200081B200002C800048FD9300002780008071 +:10813000803200002680A253077C000000005153CB +:10814000079001002A800052079000002980A25267 +:10815000077C00000000525207900100000000530D +:108160000790010000000048FD9301000000004559 +:10817000F39301005C952EA252B30100FF00008032 +:10818000F48901000000004CE4B10100000000A9E6 +:1081900045B101003080004C80B200000000454035 +:1081A00081B201000000554081B201001B840540EE +:1081B00049B100001B84054049B1000000000540A2 +:1081C00049B10100E1800040813201000000004B14 +:1081D000DEB20100770000404B9901000000004032 +:1081E000FD93010000000048FD83010002000040F3 +:1081F0009B9B0100000000A59CB30100F699004084 +:108200008132010058952044E0B1010000C000A671 +:1082100036B10100D014004047990100050000402C +:10822000F599010000380040F59901000006004072 +:10823000F599010000000040F59901000518004083 +:10824000F599010002090040F59901000400004081 +:10825000F599010050030040813201007B0300408A +:1082600081320100E083004081320100108400402F +:108270008132010008840040813201006095204075 +:10828000E1B1010070952040E1B10100000000491A +:10829000DD9101000000004091B3010000000040AA +:1082A00085B301005C952040E1B101001A820040D5 +:1082B0008132010071830040813201000200009789 +:1082C00080980100000000402EB101000200004033 +:1082D0002EDD01009001004093980100290100402B +:1082E000813201005C810040AF3301007999004088 +:1082F000813201000000454081B20100000055407C +:1083000081B201004984004081B2000004000040B5 +:1083100081B200000400004081B20000040000406F +:1083200081B200000400004081B20000040000405F +:1083300081B200000400004081B20000040000404F +:1083400081B200000400004081B20000040000403F +:1083500081B200007701004181C00000718051406E +:1083600081B200007280524081B20000738055409B +:1083700081B200007480564081B2000055019181A5 +:10838000803000005A01454081B2000055019182C1 +:10839000803000005A01464081B200005A01004876 +:1083A000FD9300005A010048FD9300005A01004966 +:1083B000FD8300005A01004AFD83000000000040D8 +:1083C00049B10100AE0300CBA3C9010000000020A9 +:1083D00046B10100000000D2F1B10100000000D35D +:1083E000F1B1010000000042F0B1010000000045C1 +:1083F00061B101002000002062DD01000000A8D072 +:10840000E1B100007C80004081B20000000000A8C3 +:1084100098B00100048000408BB30000B10300401D +:10842000A19901008480A241976F000000000045DF +:10843000A1C101000000000080B001000000A20402 +:108440008094000080153F4297E301000000004047 +:1084500049B10100000060030294010000000040E7 +:1084600007B00100040000CB99CB0100000000CC54 +:10847000F38301008E80A241976F0000000000CBC3 +:10848000F3930100AE0300CBA3C90100000000205C +:1084900044B1010000000044F1B1010000000000FF +:1084A000F0B1010000000004F0B10100000000A1E3 +:1084B000E0B10100050000406199010020000020AA +:1084C00062DD01009580A84081320000C6020020D4 +:1084D000423101000000A241056C0100000080CB88 +:1084E000DB910100000019418BB3010060000040E6 +:1084F000619901009B80A8B18C33000060000040AE +:10850000619901009D80A8B194330000A38014C636 +:1085100081320000180000C683F401006A84224FF3 +:10852000830400007F80004081B20000FF0100C68C +:1085300081880100000000C697A301007F801F5CB6 +:10854000975300009E831DC68132000000002F4318 +:1085500081F00100A980004010C9000005810040A1 +:1085600081B200003681004081B20000DA8100CA89 +:1085700063B300002D81004081B200001481004DE2 +:1085800083B000001E81004E61B100000D810040EB +:1085900085B000001481004C83B00000F0800040E2 +:1085A00085B000009181004049B100003D8100404C +:1085B000C1B100008D81004081B200000D810040FA +:1085C00085B00000DD81004049B100006A8400CA26 +:1085D0009BB3000046810040C1B100004E810040C5 +:1085E000C1B1000055810040C1B10000568100407A +:1085F000C1B1000057810040C1B100005881004066 +:10860000C1B100005981004081B000005981004192 +:1086100081B00000CE81004081B20000DD8300BB4C +:10862000ABB30000DB8100CACFB30000D3800040B1 +:1086300049B10000DF80004081B20000DC810040D1 +:1086400081B200006A84004081B20000DA800040FC +:1086500081B200006A8400CA77B300001581004D22 +:1086600083B000001C81004E61B100000D8100BB91 +:1086700085B000001581004C83B000000D8100BB67 +:1086800085B00000F08000BB85B00000E2800040B3 +:1086900081B200006A8400CA4DB3000064820040C9 +:1086A00049B100008F82004049B10000C8142EBBC0 +:1086B00085B00100000000EE82B001000000004122 +:1086C000E0B10100FF7F00A2A08B01000000004488 +:1086D000A5B30100758000CAA733010002810040E4 +:1086E00081B200004E01004D933001004E01004E5A +:1086F000933001004E01004C93300100088400408B +:10870000813201006A84004081B20000549500402B +:10871000459901006A8400CAE5B10000000080406C +:1087200097B00100E88022428F6F0000EA8022416A +:108730008F6F0000EC801ECA81320000EE801FCADD +:1087400081320000000000CAC9B101006A84004201 +:108750008FB30000000000CACDB101006A8400415F +:108760008FB30000000000CACFB101006A8400404E +:108770008FB30000008100A6C6B101006A840040EA +:1087800081B20000008000A6C6B101006A840040EA +:108790008FB30000781800404999010010002F9C09 +:1087A00089B00100078100403933010018002F9B78 +:1087B00089B00100078100403733010000002F9A83 +:1087C00089B00100078100403533010008002F996E +:1087D00089B001000781004033330100008000AE02 +:1087E00047C9010080000040F1990100000000CA63 +:1087F000F1B1010000000042F0B10100401800405A +:10880000E19901000000004561B10100200000AEC7 +:1088100063DD01000281284081320000FF800040BA +:1088200081B2000002814240813200000000005C01 +:10883000699301006A841A449393000005814240C1 +:108840008132000004810058699300000000004458 +:10885000F0D101000000A44081B200000C81A240D0 +:10886000E16D00000000004445D10100000080409F +:10887000E1B1010000008041E1D101000D81375CD0 +:10888000613100000000004262B101001181284006 +:10889000813200000E81004081B20000000000CA59 +:1088A00063B101001181A840813200006A84174041 +:1088B00081B200001681004081B00000168100BB2B +:1088C00081B000000000004160B1010000000040E4 +:1088D00062B101001781A84081320000000000CA87 +:1088E00063B101006A842840813200001981004090 +:1088F00081B2000050950040479901001F8100BBE4 +:1089000087B0000050952F4087B0010021812240A0 +:10891000957F00006A8460409583000002002DF07E +:1089200084B0010022813640813200000000004204 +:1089300062B101002381A8408132000000000043A1 +:1089400062B101002581A84081320000000000CA08 +:1089500063B101002781A840813200000000164069 +:1089600081B201006A84224143510000000800CA1C +:1089700095CB01002281004185C000002F81A242D9 +:10898000676F00000000004167B301002F81424083 +:10899000813200000000004065B30100000000408B +:1089A0009383010000001ACA699701006A84264077 +:1089B0008132000034814240813200006A841A44CE +:1089C000939300006A842043956F00006A8480CAF4 +:1089D000673300006A842240656F00006A84006F7C +:1089E000DB910000C100004081320100358022404F +:1089F000803200006A84004081B200000000005F05 +:108A0000959301004281A244216F00000000005FA5 +:108A1000958301000000005E95930100000000575F +:108A200095930100000000CAC3B101004581225B9B +:108A3000957F00000000004BFD9301006A84004018 +:108A400081B2000049812240AF6F00001BF500CACF +:108A5000959B01004A81004081B200001BFD00CAC5 +:108A6000959B0100000000CA7FB30100260100CAE7 +:108A7000C53101000000005F958301006A8400CACF +:108A8000C5B10000DF6F00CA959B010000000055D2 +:108A900095930100000000CAC7B101006A84225FFB +:108AA000957F000026010040813201000000005F38 +:108AB000958301006A8400CAC7B100006A8400CAB5 +:108AC000C9B100006A8400CACBB100006A8400CA40 +:108AD000CDB100006A8400CACFB1000000002E4270 +:108AE00081E001009814004048C901006A8400CA6E +:108AF000E1B100000000004009B10100200000A623 +:108B000082B001005E81A25E0B7D0000008000410A +:108B1000089901006081A25E0B7D0000208000A604 +:108B200008B1010062819F85823000006181A24FFF +:108B30000B7D00000000004121B30100028000A66F +:108B400082B00100C9810040813201001000004163 +:108B500084E40100038000A682B00100C9810040C6 +:108B600081320100F0FF00418688010000000043CF +:108B7000849401000F0000A686B0010010C40043D9 +:108B8000869801007581A243846C000000000043B8 +:108B900021B30100200000A682B001001C000041AA +:108BA00082DC01007281A25E0B7D000004000041A6 +:108BB000089901007E81004081B20000410100A6B9 +:108BC00086B00100500C0043869801007A81A243D0 +:108BD000846C00000000004121B301007E81004050 +:108BE00081B20000410100A686B00100600C004384 +:108BF000869801007E81A243846C00000000004240 +:108C000021B30100200000A682B001007F81A25E96 +:108C10000B7D000040130041089901008781224329 +:108C2000216F0000200000A682B001001200004168 +:108C300082DC01008481A25E0B7D00000004004103 +:108C4000089901008C81004081B20000200000A63C +:108C500082B001001900004182DC01008981A25E1E +:108C60000B7D000000A00041089901008C810040AC +:108C700081B200000000804081B20100200000A607 +:108C800080B00100000000CA819401008F81A25EC3 +:108C90000B7D00006A84004008B10000C8142EBBA0 +:108CA00085B001009281A25E0B7D000000000040B3 +:108CB00087B00100A1812243216F0000B0812244CE +:108CC000216F0000118000A682B00100C981004020 +:108CD00081320100B881224A837C000000000040FC +:108CE000879001009C81224D837C000000000041A0 +:108CF000879001009E81224F837C0000000000438A +:108D000087900100A081224E837C00000000004279 +:108D100087900100B881004081B20000018000A668 +:108D200082B00100C981004081320100018000A6AB +:108D300082B00100C981004081320100B881224225 +:108D4000837C000000000040879001001C8000A68A +:108D500082B00100C981004081320100AB8122450F +:108D6000837C00000000004187900100AD81224417 +:108D7000837C00000000004387900100AF81224304 +:108D8000837C00000000004287900100B881004011 +:108D900081B20000018000A682B00100C9810040BC +:108DA00081320100018000A682B00100C98100402B +:108DB00081320100B8812242837C00000000004023 +:108DC00087900100000000438790010000000041EF +:108DD00087900100008000A682B00100C981004098 +:108DE00081320100BC81224B837C000000000040E6 +:108DF0008780010000000043E0B101000000004056 +:108E0000AFB30100C5812240877C0000C581A2412B +:108E1000877C000000000041AEB30100000000406C +:108E200081B30100C4812242877C0000C581000B10 +:108E30007DB300000000000F7DB30100FF7F00A2A2 +:108E4000A08B010000000044A5B30100758000CA9A +:108E5000A73301000281004081B2000020000041E0 +:108E600082DC0100CA81A25E0B7D0000000000418F +:108E700008B10100CC819F85823000000000804055 +:108E800081B20100D18114F781300000D181A24963 +:108E9000FD7F000000000048FD930100D48115F81B +:108EA00081140000D481A24AFD7F00000000004828 +:108EB000FD930100D681A2C881320000400000402D +:108EC00080DC01000010004080DC01000000004058 +:108ED000EFB30100D8814240F1330000048100402B +:108EE000689700006A8400BB6BB300006A8400BB13 +:108EF000B1B300006A84004081B20000CC142E405F +:108F000087B00100FF7F00A2A08B0100D8000043C2 +:108F1000B2330100000068DA89B001007C00004033 +:108F20008B9801000000005089F001000000004112 +:108F300089D0010003000044888C01000000004239 +:108F400087C0010000000041A5B30100D800004324 +:108F5000B2330100000000DAF1B10100000000426C +:108F600087C0010000000041A5C30100F881224430 +:108F700089500000F88122448B500000E781A25004 +:108F8000A56F000000000042A5E30100000000CA38 +:108F9000A7B30100758000BB85300100CC142ED230 +:108FA00095C30100AE0300CBA3C90100000000205F +:108FB00042B101000000005081B00100F581A241E2 +:108FC00081500000F481A2F280300000E78100406F +:108FD000A5B3000000000042A5E30100000000CAA4 +:108FE000A7B30100758000BB8530010002810040FD +:108FF00081B20000D9000041B3730100000080502D +:10900000B5F30100D8000041B3F30000000000D91F +:10901000B3FB0100003000A6B8B30100F20000402D +:1090200081320100250100422D01010000020040B3 +:1090300083980100EB0000408132010000000050E5 +:1090400081B001002601004081320100098210DA5E +:10905000B56B00000A8200412D8100000000004134 +:109060002D910100280100408132010025010040BE +:109070002D110100000000402D8101000682A24157 +:1090800081500000260100422D0101002501004011 +:1090900081320100260100422D110100250100400E +:1090A0002D110100158204402D0100002501004012 +:1090B000813201001182004081B20000280100408D +:1090C00081320100250100422D010100F200004023 +:1090D000B9330100000000422D81010000008041F1 +:1090E0002D8101000000804081B20100000300409A +:1090F000819801000000004018B10100800000408C +:109100008398010000190040459901000000424089 +:1091100081B20100000043FFF1B10100000000FF37 +:10912000F1B101000000004181C0010000000040D9 +:1091300018B101001F82A2418350000000160040B8 +:1091400045990100001900404399010000000047C3 +:1091500043C101000000004083B00100000000F3A3 +:1091600080B001000000005B81D0010000000041E0 +:1091700080D0010000000040F6B101000000005B5B +:1091800043C101000000004183C001002982A254B4 +:10919000836C000000000040F7B1010000000041B6 +:1091A00083C001003082A206836C00000000804072 +:1091B00081B201000000800791B00100E180004011 +:1091C000813201003982A240976C000028000040E3 +:1091D000B39B01003A82004081B2000028000040A9 +:1091E000B39B0100FC81004081320100000000DAE5 +:1091F000F5B10100FC810042B3430100000000DA38 +:10920000F5B10100FC810042B3430100000000DA27 +:10921000F5B101004E000040B39B0100FC8100400D +:1092200081320100080000DAF7F50100500000402B +:1092300091980100000000478FB00100FC810048B8 +:10924000B2330100000000DAF7B10100080000DAD3 +:10925000F7F501000000004291C001004582A241E3 +:109260008F5000000000004145D10100080000407F +:10927000B39B0100FC81004081320100000000DA54 +:10928000FDB101000A000040B39B0100FC810040D9 +:1092900081320100000000DAFDB101001800004039 +:1092A000B39B0100FC81004081320100000000DA24 +:1092B000FDB1010016000040B39B0100FC8100409D +:1092C00081320100000000DAFDB10100348200406B +:1092D000813201001E000048B2CB0100FC81004039 +:1092E00081320100000000DA91C001000000004856 +:1092F000B2CB0100FC8100408132010000006EDA37 +:109300008FB0010002000048B2CB0100FC81004098 +:1093100081320100000000DAFDB1010004000048C4 +:10932000B2CB0100FC81004081320100000080DAF4 +:10933000FDB101006F822250FD7F00006F82224547 +:10934000FD7F000040160040459901003582004035 +:109350004931010008000048B2CB0100FE81004005 +:10936000813201006D82A2408F6C00007282222047 +:10937000B56F00006F82004081B20000DB820040C8 +:109380008132010072822240976C00006F8242405D +:10939000813200000000004F6993010004810058F1 +:1093A000699300005416004047990100000000FE38 +:1093B000F4B101000000004081B20100000000FE95 +:1093C000F4B101000000004081B20100000000FE85 +:1093D000F4B101000000004081B20100000000FE75 +:1093E000F4B101000000004081B20100000000FE65 +:1093F000F4B101000000004081B20100000000FE55 +:10940000F4B101000000004081B20100000000FE44 +:10941000F4B1010046000040B39B0100FC81004014 +:1094200081320100080000DAF7F501004800004031 +:10943000959801000000004497B00100FC81004AAB +:10944000B2330100000000DAF7B10100080000DAD1 +:10945000F7F501000000004295C001008582A2419D +:10946000975000002A000040A59B010040160040D4 +:10947000A19B0100000000CAA7B30100758000BBDA +:10948000853001000281004081B20000A7822245A0 +:10949000FD7F0000E0150040479901001A0000A27E +:1094A00080DC010000000050F1B10100F015004027 +:1094B000F1990100000000CAF1B10100070000406D +:1094C00061990100A000004062DD01009682A8BB06 +:1094D000E13100000000005083B001009982A241F8 +:1094E000835000009882A2F282300000E1800040A8 +:1094F000813201009F82A240976C0000280000404A +:10950000B39B0100A082004081B20000280000400F +:10951000B39B0100F015004043990100FC8100401D +:1095200081320100A782A2FAB46F0000FC810042E0 +:10953000B3430100A782A2FAB46F0000FC8100428D +:10954000B3430100AA8222FAB46F0000A78242400E +:10955000813200000000004E699301000481005830 +:109560006993000040160040459901003582004093 +:1095700049310100F6150040439901005C16004096 +:109580004599010000006EFA8EB001000000004015 +:1095900081B20100000000FEF4B1010000000040B3 +:1095A00081B20100000000FEF4B1010000000040A3 +:1095B00081B20100000000F0B4B30100B882A24003 +:1095C0008F6C0000FC152020E1B10100BD8200403D +:1095D00081B20000DB82004081320100BD82224066 +:1095E000976C0000BA824240813200000000004FB8 +:1095F000699301000481005869930000348200409F +:10960000813201001E000048B2CB0100FC81004005 +:1096100081320100C2822250B56F0000000000506C +:1096200091C0010000000048B2CB0100F6150040D7 +:1096300043990100FF8100F2B433010002000048A9 +:10964000B2CB0100F815004043990100FF8100F200 +:10965000B433010004000048B2CB0100FA15004009 +:1096600043990100FF8100F2B43301000800004873 +:10967000B2CB0100FC15004043990100000000F04E +:1096800094B00100FFFF004AB48B0100FF8100404D +:10969000813201000A000048B2CB01001000004AEC +:1096A000B4F70100FF8100408132010034820040A4 +:1096B000813201001E000048B2CB0100FC81004055 +:1096C00081320100D8822250B56F0000D98200504B +:1096D000B5B3000000000040B5B30100FF810040B9 +:1096E000813201000281004081B20000001600407A +:1096F0004799010030310040F599010032330040B4 +:10970000F599010034350040F599010036370040E5 +:10971000F599010038390040F599010041420040B7 +:10972000F599010043440040F59901004546004089 +:10973000F599010047480040F5990100494A004069 +:10974000F59901002C0000408398010000000040C2 +:10975000F7B10100E782A2418350000080162E0677 +:1097600083B00100360000FBF6A90100EA82A241A5 +:10977000835000002200004083980100000000FB9D +:10978000F6B10100ED82A24183500000620000406A +:1097900095980100008300408132010000162D06DB +:1097A00083B0010080160040459901005C0000FB79 +:1097B000F6A90100F382A24183500000000000706E +:1097C000F9B1010000000071F9B101000000007260 +:1097D000F9B1010000000073F9B10100000000744C +:1097E000F9B1010054000040959801000083004049 +:1097F000813201000000007095B00100FF822270EC +:10980000B56F00000000804197B00100000080406B +:1098100097B00100456700A6E0B201000123007087 +:10982000E19A0100CDEF00A6E2B2010089AB007120 +:10983000E39A0100BA9800A6E4B20100FEDC0072CF +:10984000E59A0100321000A6E6B2010076540073DA +:10985000E79A0100D2C300A6E8B20100F0E100746B +:10986000E99A01008016004A44C90100000000077F +:1098700081B001000000004A80D0010000000040DB +:10988000F7B101000D83A241815000008016004A0B +:1098900044C90100FC162A47E7B501000300004A4D +:1098A000E8E50100000000408DB0010050030040D9 +:1098B000A399010080163D468DE001000000005094 +:1098C00089B00100000000FC40B001000000004130 +:1098D000A3C101001683A24189500000000000705E +:1098E000EBB2010000000071EDB201000000007257 +:1098F000EFB2010000000073F1B20100000000743B +:10990000F3B201000000004083B001000F000041ED +:109910008088010050030040A2C901003383A05099 +:10992000836C00000D00004098C801000000004F4B +:10993000998401005003004CA2C9010000000020DE +:1099400086B001000800004098C801000000004FE8 +:10995000998401005003004CA2C9010000000020BE +:1099600086A401000200004098C801000000004FDA +:10997000998401005003004CA2C90100000000209E +:1099800086A4010050030040A2C90100000000436A +:1099900040A401000100002088E401000000005FF5 +:1099A00041F00100000000444094010005000075F2 +:1099B00089E401001B00007585F4010000000044EB +:1099C000849401003D83A353836C00000000007663 +:1099D00089B0010000000077898401000000007652 +:1099E0008BB00100000000208BA401000000007873 +:1099F0008B8401004C8300458894000027000041BF +:109A000080CE01004283AA4081320000000000762F +:109A100089B001000000007789A401004C83007820 +:109A200089A400003B00004180CE01003F83AA4092 +:109A3000813200000000007689B00100000000774C +:109A400089840100000000768BB0010000000078DE +:109A50008B8401000000004588940100000000771D +:109A60008BB00100000000788B8401004C8300451E +:109A7000889400000000004484C0010000000079C8 +:109A800085C001000000002084C001005383A3535F +:109A9000836C0000825A00A684C0010099790042BC +:109AA00084C801006083004081B2000027000041AB +:109AB00080CE01005883AA4081320000D96E00A6F2 +:109AC00084C00100A1EB004284C801006083004013 +:109AD00081B200003B00004180CE01005D83AA40BE +:109AE000813200001B8F00A684C00100DCBC004254 +:109AF00084C801006083004081B2000062CA00A6F1 +:109B000084C00100D6C1004284C8010060830040C7 +:109B100081B2000000000078F3B20100000000777D +:109B2000F1B201001E00007689E401000200007617 +:109B3000EFF6010000000044EE9601000000007501 +:109B4000EDB2010000000042EAB201000000004155 +:109B500083C001004F00004180CE01001F832A40D6 +:109B60008132000000000075E1C2010000000076B3 +:109B7000E3C2010000000077E5C2010000000078A8 +:109B8000E7C2010000000079E9C2010013838141AE +:109B90008D4000000000804081B201009D83A24BF7 +:109BA000B76F00009D83A2412F7D00000000005090 +:109BB000FD930100401600404599010035820040A8 +:109BC000493101009C8322408F6C0000080000484E +:109BD000B2CB0100FE81004081320100DB820040F7 +:109BE000813201009C83A240976C00005E16004009 +:109BF000439901007C1620F6E0B10100000000400E +:109C000031B301008083224F8F7C0000000000519F +:109C1000FD930100828322408F7C000086830054E4 +:109C2000FD930000848322428F7C000000000052DC +:109C3000FD930100868322418F7C000000000053C9 +:109C4000FD9301009A832251FD7F00003482004081 +:109C5000813201000C000048B2CB0100FC810040C1 +:109C6000813201009583A240B56F00001E000048BC +:109C7000B2CB0100FC81004896300100000000DA00 +:109C800097C001000400004BB2CB0100FC810040F2 +:109C9000813201000E000048B2CB0100FF8100407C +:109CA000813201000C000048B2CB010000000030FE +:109CB000B5B30100FF810040813201000E00004871 +:109CC000B2CB0100FC810040813201009983224027 +:109CD000B56F00009D830054FD930000000000510B +:109CE000FD8301001C0000FE7FD901009D83A6407A +:109CF0008132000000000055FD930100000080400B +:109D000081B20100B6030040A199010000002F417B +:109D100099B30100A8832244816C0000B0832248DB +:109D2000816C0000AA83224C816C0000B483225015 +:109D3000816C0000B5832254816C0000B7832258E7 +:109D4000816C0000BC83225C816C000055010040E6 +:109D500081B20000000000BC09B001006A8400CAA2 +:109D600001B000000000004003B00100000000410D +:109D7000F3830100AE83A242056C000000000041A5 +:109D800005B001006A8422CA071400006A840045F5 +:109D9000F39300006A842043956F00006A8480CAB0 +:109DA000053000006A842201803000006A8400CB04 +:109DB000DB9100005C0100BCABB30000000000BC04 +:109DC000B1B301006A8400CACFB30000FF0000CA2B +:109DD000818801006A84A240747D000060002040F8 +:109DE00060990100B983A8B182300000B8830040B7 +:109DF00081B200006A8400CA79B300000000004EFE +:109E000081B0010000000043CB8301000000454009 +:109E100081B20100BF83A241815000000000454093 +:109E200081B201000000454081B20100CA839182E5 +:109E3000823000000000008A80B00100B69F004020 +:109E400080CE0100C883A64081320000CA835640FC +:109E500081B20000B6030040A19901000000005348 +:109E600007900100B6030040A199010000000052D4 +:109E700007900100F39F00418BB300000000004EEB +:109E800081B0010000000042CD8301000000464087 +:109E900081B20100CF83A241815000000000464002 +:109EA00081B201000000464081B20100DA83918155 +:109EB000823000000000008980B00100B69F0040A1 +:109EC00080CE0100D883A64081320000DA8355405D +:109ED00081B20000B6030040A199010000000052C9 +:109EE00007900100B6030040A19901000000005353 +:109EF00007900100F39F00418BB30000B1030040C5 +:109F0000A1990100C4142F4099B301005C010040E5 +:109F100049B1000058152D408DB00100D0142DF02E +:109F200088B00100000000408FB00100010000A6D1 +:109F300090B0010000F80048909801000000004532 +:109F400093B00100000000FA8AB001006A030040EB +:109F500081320100020000A680B00100EC832240A3 +:109F6000826C0000F0830040813201004703004012 +:109F700081320100000000418DC00100F583225FA5 +:109F80008D6C0000E783A24193500000E583004000 +:109F900081B20000FF070047848801000000A6404E +:109FA00081B20000F59F00478030010000020047A9 +:109FB0008EC80100F083004081B200000000004420 +:109FC00050B30100FB832018896C0000040000A638 +:109FD00084B00100200000A686B0010000100040FF +:109FE000559B0100FE83004081B20000040000A6E2 +:109FF00084B00100200000A686B0010000100040DF +:10A00000559B01000000004250D30100000000A851 +:10A010004FB30100000000434ED301005E03004037 +:10A02000813201006C03004280300100F083004067 +:10A0300081320100078422A78F6C00004903004091 +:10A04000813201000484004081B2000000008040A1 +:10A0500081B20100A0942E4397B00100000000409F +:10A06000F1B101000984A2419750000050952040B1 +:10A07000E1B10100AC942E4397B001000000004014 +:10A08000F1B101000D84A241975000000000804012 +:10A0900081B20100AE030040A3990100000000401E +:10A0A00081B0010060150040859801000800004063 +:10A0B00040E40100000000594194010000000050FC +:10A0C00041E0010000000042409401000000004116 +:10A0D00081C001000000A341816C0100000000412B +:10A0E000A3C101001384005085C000004984A2412F +:10A0F000017D000021842258737D0000780000401B +:10A10000619901001C84A8B19C30000030003845E2 +:10A110009DE001000100000E10C90000218433C43D +:10A12000813000002484A1AD9D2000001B841340D9 +:10A1300081B200000000134E5A8301003000384500 +:10A140009DE001002C8422AB800400002A84A24000 +:10A15000017D00002C84225F577D0000278A00408B +:10A1600081B200002C84225E577D00008A8A004064 +:10A1700081B2000031842254737D000074000040DD +:10A18000619901002C84A8B1003000000086A25F14 +:10A19000017C00006289004081B200003384A25F2C +:10A1A000592700003584A25C737D00003C84A25EC8 +:10A1B000737D00004684225C737D00004784374035 +:10A1C000813200007C000040619901003684A8B112 +:10A1D000363000007C000040619901003884A8B14D +:10A1E000003000001F000000028801002F86174089 +:10A1F00081B2000047843440813200007E0000407C +:10A20000619901003D84A8B11230000044845221BC +:10A2100013040000000014412FC30100FF3F000998 +:10A22000008C01000000004301F00100878400342D +:10A2300013840000FF3F1409008C0100E7840043F1 +:10A2400001F000000000004081B20100478433406B +:10A25000813200001B84134E5A930000EC89A248FF +:10A26000FD7F00004E842259737D0000790000407C +:10A27000619901004A8428B17E3100004B8400407E +:10A2800081B20000528421AC9C20000000000041FB +:10A290001FC301000400A05F9D6C00000000004E81 +:10A2A000589101005684225A737D00007A000040C4 +:10A2B000619901005384A8B17E310000010000CFF4 +:10A2C00011C900005C84A240937F00005C8422449A +:10A2D000937F0000588442A5803000005B84A24038 +:10A2E000937F000071841A409393000000001A408D +:10A2F00081B201009A80A240737D0000A1892244AE +:10A30000216F000098892240657D0000A689A25B2C +:10A31000737D00000400A249337D0000668422485A +:10A32000337D0000FF01009980D80100000000503B +:10A3300081E00100A8982F4033B1010000000040E7 +:10A34000E0C1010069842240AF6F000069842240AF +:10A35000816F0000F5891FA5826F000049840040CD +:10A3600081B200001B8400408BB300000000005845 +:10A3700061B101000000004E62B101001B84284061 +:10A38000813200006C84004081B200006F84334051 +:10A390001F3000001B84134E5A9300007384A0CE1C +:10A3A000815000008584A0CD816C0000000000A5D4 +:10A3B0009CB30100000000B181B00100858422B58A +:10A3C0008114000080152F4049B10100778442407C +:10A3D00081320000000060B465970100D0152E4066 +:10A3E00069B3010000001A44938301001A0000A21F +:10A3F00080DC010000000044F1B10100000000B168 +:10A40000F1B10100000000B5F1B10100050000400C +:10A41000619901000000004062B101008084A8A1A0 +:10A42000E03100005C8400889EB300005C84A2419F +:10A43000676F00005C84006FDB9100008584424000 +:10A44000813200005C841A40938300000099000967 +:10A4500046C901003F0000F30C8801009084A64229 +:10A460001360000055970095033001008B84454030 +:10A470008132000075000040619901008C84A8B110 +:10A480000C3000005C971D1094300100918400583E +:10A490001F9000004E970095033001001B84008838 +:10A4A0001CB0000000002D0348B1010004002DF095 +:10A4B0002EB00100EE070040979801009884234BCE +:10A4C000E46D00009884224BFD7F000000000040F6 +:10A4D0001F90010022002F4081B201009B8483174E +:10A4E0008032000026000040479901009D848517B6 +:10A4F000803200000000004847C10100A3842255BB +:10A500002F7C00000000004243D101000F0000FA40 +:10A51000968801000000004297E001000000004220 +:10A5200097D00100A484004B44C10000120000A297 +:10A5300044C90100280000F602CC01000A0000A175 +:10A5400042C90100000000F816B00100000028F028 +:10A5500010B00100000000F01AB00100000000A2DD +:10A560002AB00100C0283C460DE0010000002D4447 +:10A5700095B00100B084A2F80E300000C0842241E2 +:10A580009550000000002D5049C10100AC840040EE +:10A5900081B20000AD84A2F8166C0000AD84A2F870 +:10A5A000106C0000AD84A2F01A6C0000BE8422582A +:10A5B0001F7C000000993F4213F00100B584474022 +:10A5C00081320000B984A2F3740600000000000686 +:10A5D000E6950100BE841F4081B200000000000625 +:10A5E00096B001003F001FF30C88010000000055E9 +:10A5F00061B101000000004B62B10100BC84A840C1 +:10A6000081320000BE84474081320000C6841F4171 +:10A610002DC30000C48422581F7C00000000005598 +:10A6200061B101000000000662B10100C284A840CF +:10A6300081320000C484474081320000EE841F4113 +:10A640002DC30000030000071AF401002196000743 +:10A6500016300100D5842241816C0000CC84224256 +:10A66000816C00001B8400881CB00000D484225F31 +:10A670000F7C00001597005F01100100D28422407A +:10A68000956C00000480000342C90100000000F244 +:10A6900002B001008A960052953001009196004B5D +:10A6A00002B000006797000996300100058A00405B +:10A6B0000FB00000DD84A25A1F7C00009B95004073 +:10A6C00081320100DD842220856C0000DA849C0F39 +:10A6D000803200001B8400881CB000007C96005C67 +:10A6E0001F0001009B980042613101001B8400881B +:10A6F0001CB00000E69900079630010000002D050F +:10A7000048B10100E08482F0183000006C8B0045F5 +:10A710008FB00000282000A696B00100E484221724 +:10A72000960400000B98004B953001006C8B004B99 +:10A730008FB000002197000348310100FC940040D5 +:10A74000813001006C8B004081B2000000002E10AF +:10A7500048B101000000685003B001000000000390 +:10A76000F0B101000000004261B1010000000010E2 +:10A7700062B10100EB84A800E03100001B84008876 +:10A780001CB0000000002D0348B101000000004093 +:10A790000FB00100000000F82EB00100000000F230 +:10A7A00002B001000000004017B00100004100A607 +:10A7B00096B00100EE072E47979001000185221701 +:10A7C00096040000FF84224BFD7F0000FF8423A23B +:10A7D000026C00008A96005295300100040022416C +:10A7E000975000000C002D0012B00100000000F096 +:10A7F00000B001000000005C018001009196004B58 +:10A8000002B000000000000900B00100000000508C +:10A8100003B001001E85005C1790000013852243E1 +:10A820002F7C0000000000451F9001000C85225F76 +:10A830002F7C000000002E1048B1010000000058DD +:10A84000F1B1010010000003F0C901001000000088 +:10A85000E0C9010008854542613100000000001098 +:10A8600062B101000985A840813200001B841D8867 +:10A870001CB0000020002D0348B10100FF0F00F6BE +:10A88000808801001085A2A6816C0000138500F26B +:10A890003AB00000FD85A24BFD7F0000E29500402C +:10A8A000813201001B8A004081B200001E85224ACD +:10A8B0002F7C00001E8522482F7C00000A002D03FB +:10A8C00048B101003F0000F2868801001F000043EC +:10A8D000848801000500004380F4010098943D4203 +:10A8E00081E001001E85A242E07D0000FD85A24BB3 +:10A8F000FD7F0000E2950040813201001B8A00408C +:10A9000081B200001E85474081320000000000A394 +:10A9100009B0010000001F4147C30100248522A1A6 +:10A92000096C00006B8400881CB0000021850003C6 +:10A9300048B100005E85A392036C00000A990040B4 +:10A94000953001000000004143C3010000000016E3 +:10A9500080B201001B8A2708803200002B85225C10 +:10A96000177C00002C8500002AB0000012000000B7 +:10A970002AC801000200000880C801003085A243F7 +:10A980002F7C00000E980040813201004C85005E53 +:10A9900017900000040000018CCC01000E98004CC0 +:10A9A0000330010000002E4602B00100100000102C +:10A9B00048C901000C000001F0CD01002C0000404E +:10A9C000F0C9010000000016F0B1010010000015F0 +:10A9D000E0C901000000004361B10100A00000A433 +:10A9E00062DD01003985A854171000004C85005E17 +:10A9F00017900000120000002AC801004B85224376 +:10AA00002F7C0000040000018CCC01000000004CF1 +:10AA100003B001002F9800436131010000002E4671 +:10AA200002B001001000001048C901000C00000134 +:10AA3000F0CD01000C000009F0C901000000001871 +:10AA4000F0B1010010000015E0C901000000004352 +:10AA500061B10100A00000A462DD01004C85285412 +:10AA6000171000004885004081B200002F98004375 +:10AA7000613101004E8522502F7C000000000056FD +:10AA80001790010007000017988801005185A24126 +:10AA9000996C000000000055179001000000004371 +:10AAA00061B101004000001062DD01005285A84044 +:10AAB000813200001B8400881CB000001698004002 +:10AAC00081320100598522432F7C0000168000034B +:10AAD00044C901000000001DE4B10100B797005E09 +:10AAE000051001005C85A25F2F7C0000CE94000160 +:10AAF00038430100E2950040813201001B8A00408A +:10AB000081B200006085A24BFD7F0000FA85004104 +:10AB100043C300000000004027B0010000000040D7 +:10AB20002DB001000000004011B001006385350127 +:10AB3000863000006D000040619901006B8528B1EE +:10AB4000303000006485224D757D00000000001645 +:10AB500080B20100EA85A740116C000000000041AE +:10AB600043C30100F985004081B200006D00004040 +:10AB7000619901006B85A8B1123000000000001639 +:10AB800080B201007585A740116C000000000041F3 +:10AB900043C301000000000910B0010000000018CC +:10ABA0002CB00100DE07004380CE01006485AA407E +:10ABB000813200007A85004081B2000040003E43AF +:10ABC00027E0010000000009F0B1010000000018BA +:10ABD000E0B101000000004127C001006485A30B23 +:10ABE00087500000000015401BB00100000000402D +:10ABF00023B00100120000002AC8010040002D40CF +:10AC000039B001008285A240276C000022000008B4 +:10AC100012C80100DE07004025980100858500402C +:10AC200081B20000000000F812B00100000000F046 +:10AC300030B001000000000B25B001000000001042 +:10AC400032B0010014002001E0B10100EE07004025 +:10AC5000379801008A852301366C0000000000014E +:10AC600036B001009585824123400000208000100D +:10AC700042C9010091852240E36D000000000043BD +:10AC800061B101004000001062DD01008E85A84026 +:10AC9000813200001B8400881CB000000196004334 +:10ACA000233001000000001032B00100000000411C +:10ACB00023B001000000000348B10100008000192A +:10ACC00044C90100A48522451F7C00000000004CFF +:10ACD000F1B1010000000009F0B10100000000180E +:10ACE000F0B101000000004361B101002000001933 +:10ACF00062DD01009B85A815E031000000000050D6 +:10AD000003D001000000005033C001000000004CDF +:10AD100025D001000C002D4C13C001000000005094 +:10AD200037D00100000000502BC001008A8500458B +:10AD30001F800000A685A312366C0000A785681B43 +:10AD400028B000000000681228B0010000000009CF +:10AD5000F0B1010000000018F0B101000000004354 +:10AD600061B101002000001962DD0100AA85A8156B +:10AD7000E0310000D0852214025000000000005095 +:10AD800033C001000000001424D001000C002D1479 +:10AD900012C00100C985A21436500000BA85225C99 +:10ADA0001F7C00003080001042C90100B88522409D +:10ADB000E36D00000000004261B10100400000109E +:10ADC00062DD0100B585A840813200001B84008847 +:10ADD0001CB000000000000348B101000C002D5C15 +:10ADE0001F800100100000F02AC801000000005C74 +:10ADF0002B800100F007004037980100BF85230138 +:10AE0000366C00000000000136B00100CA85221B2C +:10AE1000026C00003000001048C9010000002E5CE8 +:10AE20001F90010000000050F1B10100000000037C +:10AE3000F0B10100FF070015E08D010000000042A5 +:10AE400061B10100A00000A462DD0100C685A84038 +:10AE500081320000CA85000348B1000000000014E0 +:10AE60002AC001008A85A240256C00000000004134 +:10AE700039C0010040003D4339E001000000000BF3 +:10AE800025B00100000000F812B001008A8500F032 +:10AE900030B000000080001942C90100D685224070 +:10AEA000E36D00000000004361B1010040000019A3 +:10AEB00062DD0100D385A840813200001B84008838 +:10AEC0001CB00000019600402B30010018002E033A +:10AED00048B10100DA8522502F7C000000000056A6 +:10AEE000179001000700001798880100DD85A24136 +:10AEF000996C00000000005517900100E085224386 +:10AF00002F7C000000000054179001001600201D47 +:10AF1000E4B10100E285A340276C0000E485605F96 +:10AF2000179000000084000B16DC01000000601385 +:10AF300016940100B797005E051001001B8AA25FFE +:10AF40002F7C00001480000342C90100000000F2C1 +:10AF500002B00100CE940001384301001B8A00407A +:10AF600081B200000000004083B001000000004DED +:10AF700061B101000000001662B10100EC85A8403B +:10AF8000813200000000000862B10100EE85A84097 +:10AF900081320000F9852213826C000040003D439D +:10AFA00083E00100000000F810B00100000000F094 +:10AFB0002CB001000000001662B10100F485A84029 +:10AFC000813200000000000862B10100F685A8404F +:10AFD00081320000F085004183C000000000154070 +:10AFE00081B20100008200A604B00100A0980040D8 +:10AFF00047990100E9890041893001008A96005291 +:10B00000953001009196004B02B000001B8A004071 +:10B010000FB000000000005F018001001000000080 +:10B020000EF401003F00000000880100030000074B +:10B030001AF4010021960007163001000B86224108 +:10B04000816C000009862242816C00001B8400880C +:10B050001CB000000A86225F0F7C0000058A0040B9 +:10B060000FB000001386A25A1F7C00009B95004081 +:10B070008132010013862220856C000010869C0F0F +:10B08000803200001B8400881CB000007C96005CAD +:10B090001F0001009B980042613101001B84008861 +:10B0A0001CB00000E69900079630010000002D0555 +:10B0B00048B10100000000F018B001001986223AE2 +:10B0C000016C0000000000008EB001006C8B00409D +:10B0D00001B000000000004081B201002E002D05EB +:10B0E00048B101001D86A240E76D00000A00004043 +:10B0F0008F9801006C8B004001B000006695004005 +:10B10000813201004E970095033001001B840088B6 +:10B110001CB0000000002D0348B1010022002DF0FA +:10B120002EB00100282000A696B001002686221726 +:10B13000960400000B98004B953001006C8B004C7E +:10B140008FB0000028868317803200000000004482 +:10B1500043C101002A8685178032000000000048A4 +:10B1600043C10100280000F602CC0100120000A13A +:10B170002AC801002197004081320100FC9400415F +:10B18000813001006C8B004081B2000000000001A2 +:10B1900000D0010000002E1048B10100280000403E +:10B1A000F199010000000003F0B10100000000006F +:10B1B000F0B1010034864647613100000000001004 +:10B1C00062B101003586A81BE03100001B841E8897 +:10B1D0001CB000000000004503E0010008002D0342 +:10B1E00048B101005A8601FB08300000AD8687FB9C +:10B1F00022300000000000FA0EB00100000000F84C +:10B2000014B00100030000071AF4010021960007A2 +:10B210001630010050862241816C00004486224293 +:10B22000816C00001B8400881CB000004F86225FE8 +:10B230000F7C0000380000047E8901004886A65F6C +:10B240000F00000074950040053001004D8600405D +:10B2500081B20000130000408798010000002D0318 +:10B2600048B101000C002DF082B00100000000F098 +:10B2700084B0010000970040053001000000005C30 +:10B280001F900100058A00400FB000005886A25AA6 +:10B290001F7C00009B9500408132010058862220CF +:10B2A000856C000055869C0F803200001B8400884E +:10B2B0001CB000007C96005C1F0001009B980042BF +:10B2C000613101001B8400881CB00000E699000772 +:10B2D0009630010000002D0548B10100000000F08B +:10B2E00018B001005C862104802000005D860040CB +:10B2F00010C90000AE8A004B81B000007C8600437C +:10B3000081B00000808600FB22B00000AE8A0041C0 +:10B3100081B000006C8B004E8FB000007886005A20 +:10B320008FB00000658600478FB00000AE8A0053E2 +:10B3300081B00000AE8A005681B0000032002D05B9 +:10B3400048B101006C8BA00AE46D00006B86A2413D +:10B35000197C00006A86220A803200006C8B005340 +:10B360008FB000006C8B00548FB000007486220AEE +:10B37000803200006E86A20AE46D00006C8B005DD6 +:10B380008FB00000000000F280B001000000000A51 +:10B3900080D001007286A091816C00006C8B005EF1 +:10B3A0008FB00000250000408F9801006C8B00409A +:10B3B00081B2000076862091E56D00006C8B005410 +:10B3C0008FB00000210000408F9801006C8B00407E +:10B3D00081B2000032002D0548B101006C8BA00A3B +:10B3E000E46D0000240000408F9801006C8B004049 +:10B3F00081B2000037002D0548B10100040000F3C0 +:10B4000082F40100AE8AA042836C0000AE8A005430 +:10B4100081B00000000000F20EB001000300000740 +:10B420001AF4010000B5000D42C901000700000731 +:10B43000168801008986220BE67D00000A00004084 +:10B4400087980100559900408132010000000040BA +:10B450000FB00100058A005C1F9000009B862250FF +:10B46000FD7F00009686A254FD7F00008E86225547 +:10B47000FD7F000082000040879801008686004022 +:10B4800081B2000086862253FD7F000014800003F5 +:10B4900042C90100000000F096B001001000004B0E +:10B4A00080F401000CBC004087980100968622437E +:10B4B000806C0000FFFF004B808801008686A2435D +:10B4C000806C00007C9600404799010097864340BD +:10B4D000813200009A86A0F0306F00008C861B40FD +:10B4E00081B2000000001B4131C30100A59500405E +:10B4F000253001009F869C0F803200001B8400884D +:10B500001CB000007C96005C1F000100148000034A +:10B5100042C90100000000F096B0010000002F05B4 +:10B5200048B101001000000718E401000008000CF9 +:10B53000E0990100E69900079630010000B5000D82 +:10B5400046C90100A6863040813200000000000B91 +:10B55000E6910100000200A146C901000000000BB5 +:10B56000E691010004002E0548B1010000001040E2 +:10B57000E1B10100AE8A004081B00000000000FB94 +:10B5800028B00100000000FB86B00100000000F8B8 +:10B5900014B00100B7862246237C0000B386224007 +:10B5A000877C0000000000481F900100B586224102 +:10B5B000877C0000000000471F900100B7862242F0 +:10B5C000877C0000000000451F900100B786471BE4 +:10B5D0002C300000000000A013B0010000001F414B +:10B5E00041C30100E6862392156C0000E686A24561 +:10B5F0001F7C0000EA86224BFD7F0000170000D070 +:10B60000A2C901000000004027B001000200000AAA +:10B6100024C80100DD9500400F300100E4862208B7 +:10B620004030000000000041A3C10100F0070012FB +:10B6300024CC0100C086AA4127400000010000136D +:10B6400080CC0100E086264023300000000000404E +:10B6500083B001006000000384C8010010000010E6 +:10B6600048CD0100170000D0A2C90100CD86A2403C +:10B67000836C0000D986004183B000000080004246 +:10B6800044990100000068213896010000002E5006 +:10B6900049C10100D286A244236C0000300000039F +:10B6A00048C9010000000044F1B101000C00002075 +:10B6B000F0C901000000004461B10100A00000A435 +:10B6C00062DD0100D586A842E031000000000044A0 +:10B6D00085C001000000004123C0010000000041BE +:10B6E000A3C10100CB86A24181500000E086224028 +:10B6F000236C00000000004461B101004000001014 +:10B7000062DD0100DD86A840813200001B840088D4 +:10B710001CB000000000000348B10100EE0700402B +:10B7200025980100170000D02AC80100F3860017F1 +:10B7300010B00000C097004081320100EA8600404E +:10B7400081B20000DD95009225300100000000402C +:10B7500031B00100EA8622082E300000F386004155 +:10B7600027B00000808000A604B001000600004061 +:10B77000879801005599000A8C30010000000040B4 +:10B780000FB001000000005C1F900100F286229FB4 +:10B79000136C0000020000881CCC01006B84004088 +:10B7A00081B20000058A00413FC300000000004054 +:10B7B0000FB001002800000180CE010007872A4059 +:10B7C000813000000080001044C9010040000040AA +:10B7D00081980100FC86A2481F7C0000FC86A247DD +:10B7E0001F7C0000FC86A307036C00008000004063 +:10B7F00081980100FF86A340026C00002800000130 +:10B80000F0CD0100018700400FB00000280000408B +:10B81000F0CD0100040000400ECC01002800000320 +:10B82000F0C9010028000000F0C901000000001666 +:10B83000E0B101000000004761B1010020000010EC +:10B8400062DD01000587A85C1F10000000000040B9 +:10B8500043990100000000F008B00100A0012D4054 +:10B8600000C00100ED88220F4205000018879C0FE0 +:10B87000803200000000005C1F800100008000108A +:10B8800042C9010013872240E36D00000000004719 +:10B8900061B101004000001062DD01001087A84086 +:10B8A000813200001B8400881CB00000188722072A +:10B8B000803200000000000342B1010000000007D8 +:10B8C00042C10100008000A1469901000000005F14 +:10B8D000E1910100D787A2451F7C00001000000302 +:10B8E00048C9010000002D5429C00100000000F8E3 +:10B8F00018B00100000000F804B00100000000F8DA +:10B900000EB00100420000030AC801000C0000A4B0 +:10B910000CC801000000004017B001000000001436 +:10B9200002B001000000001424D001000000001447 +:10B9300010C001001200000810C801000000004003 +:10B9400023B00100FE7F000544C90100298720942F +:10B95000156C00002A870094E5B100000000000A81 +:10B96000E4B10100438722018032000000003C4422 +:10B9700023E0010000002EA480B0010000000010B0 +:10B9800048C101003087A307026C000031876801BD +:10B990001AB00000000068071AB001000000000D96 +:10B9A00002D0010000000005F0B101000000000C11 +:10B9B000F0B1010000000002E0B101000000000D44 +:10B9C0000AC001003D872240036C00003D872242EF +:10B9D000236C00000000004123C00100000000476C +:10B9E00061B10100A00000A462DD0100658728406C +:10B9F000813200003A87004081B200000000001050 +:10BA000080C001000000004761B10100000000405B +:10BA100062B101003F87A840233000001B840088EA +:10BA20001CB000006587004081B2000000003C446B +:10BA300023E00100000000A486B0010000002E10E9 +:10BA400048C101004887A3120E6C000049876807AF +:10BA50001AB00000000068121AB001004C8780087C +:10BA6000F03100000100001198C801000000004CF6 +:10BA70001E9001000000000CF0B101000000000267 +:10BA8000E0B101000000001086C001000000004687 +:10BA900061B10100011F004362DD01005087A85C15 +:10BAA0001F1000008387220D146C00005687220DA2 +:10BAB000246C00000000000D10C001005A87000D2A +:10BAC00024D00000000000412BC001000000001540 +:10BAD000A2B101001000002010C80100F0070040D2 +:10BAE000259801005C872242236C00006587004195 +:10BAF00023C000000000004661B1010040000010BA +:10BB000062DD01005D87A85C1F0000001B840088C7 +:10BB10001CB000000000001048B1010063872247FC +:10BB20001F7C000011960043233001000E00000F1F +:10BB30001E8C01000000004023B001008387220D0D +:10BB4000145000008287A20D0E500000718722461B +:10BB50001F7C0000000000461F80010030800010A4 +:10BB600042C901006F872240E36D000000000047DA +:10BB700061B101004000001062DD01006C87A84047 +:10BB8000813200001B8400881CB00000208000036C +:10BB9000469901000000005FE191010000002D06C0 +:10BBA00048B10100000000F818B00100000000F8E2 +:10BBB00004B0010076871FF00E3000002A87004C89 +:10BBC0000DC0000000002E5F0F8001002A872307B0 +:10BBD000146C00003000001048C90100240000402F +:10BBE000F199010000000003F0B101000000000025 +:10BBF000F0B1010000000016F0B1010024000000C7 +:10BC000000C801000000004761B10100A00000A4CD +:10BC100062DD01007F87A8461F1000002A8700030D +:10BC20000CB000002A87000D18C0000004002E147C +:10BC30000AD001001200000548CD0100FE7F00057A +:10BC400042C901000C002AF2E0B1010089872240BC +:10BC5000316C000000006018389601001E000040A2 +:10BC600043990100008100F680CE01008D87A64037 +:10BC7000813200000000004443C101008F87220B85 +:10BC8000ED6D0000080000A142C90100020000A102 +:10BC900046C901000F0000FA948801000200004A22 +:10BCA00086E40100000000F60EB0010097872247ED +:10BCB0001F7C000004001F430E5000009787A04621 +:10BCC0000F400000000000410FC001009B87224888 +:10BCD0001F7C00000000004091B0010004000FA292 +:10BCE000423100009E87004089B000000C0000A295 +:10BCF00042C901000000004389B001000000004378 +:10BD000095D00100000000FC82B00100A187A04195 +:10BD1000904000000000004191C00100A68722472A +:10BD20001F7C0000A687A043896C0000A6872045E1 +:10BD3000896C0000A687A0410E4000000000004171 +:10BD40000FC001000000004189C001009E87A24190 +:10BD500095500000AF8722481F7C0000100000486B +:10BD600092F40100FFFF004890880100AD879048E1 +:10BD7000924000000000004193C001000A0000A2B0 +:10BD800044C901000000662093A401003080001027 +:10BD900044C9010012000014F0C90100000000179E +:10BDA000F0B1010012000005E0CD010030000010EC +:10BDB00080C801000000004461B101002000004083 +:10BDC00062DD0100B587A84081320000C287225C95 +:10BDD0001F7C000000003C4423E0010000002D1007 +:10BDE00048C10100BF872240E36D0000000000460B +:10BDF00061B101004000001062DD0100BC87A84075 +:10BE0000813200001B8400881CB00000C287875C60 +:10BE10001F0000000000001048B101001196004111 +:10BE200023400100C487A2471F7C000058890017E7 +:10BE300010B0000000002F0348B10100C787A00721 +:10BE4000164000000000004117C001000000000B78 +:10BE5000E4B101000000005017F00100CB8790F220 +:10BE6000164000000000004117C0010000006620DD +:10BE700017A40100100000142AC80100000000509F +:10BE80002BE00100000000F22A9401003080001035 +:10BE900042C90100D5872240E36D00000000004444 +:10BEA00061B101004000001062DD0100D287A840AE +:10BEB000813200001B8400881CB000000080001745 +:10BEC00010DC01005889004081B20000A5950040B7 +:10BED00081320100DB87225C1F7C00001B8400880C +:10BEE0001CB000007C96005C1F0001000080000573 +:10BEF00044C9010000000040E1B1010004002D032D +:10BF000048B10100000000F03CB00100280000141E +:10BF100002C801000000000134B0010000002D053E +:10BF200032B00100220000050AC801001000000321 +:10BF300048C90100000000F818B00100000000F836 +:10BF400004B00100000000F80EB001000C0000A4D5 +:10BF50000CC801000000004017B0010000000040C4 +:10BF600023B00100218822018032000000003C44FF +:10BF700023E0010000002EA480B0010000000010AA +:10BF800048C10100F087A307026C0000F187680137 +:10BF90001AB00000000068071AB001000000000D90 +:10BFA00002D0010000000005F0B101000000000C0B +:10BFB000F0B1010000000002E0B101000000000D3E +:10BFC0000AC0010003882240036C0000FD87224262 +:10BFD000236C00000000004123C001000000004766 +:10BFE00061B10100A00000A462DD01003D8828408D +:10BFF00081320000FA87004081B20000000000108A +:10C0000080C001000000004761B101000000004055 +:10C0100062B10100FF87A840233000001B84008824 +:10C020001CB000003D88004081B2000000000010FC +:10C0300080C001000000004761B101000000004025 +:10C0400062B101000588A840233000001B840088ED +:10C050001CB000002200001948C9010000002D1486 +:10C0600048C101000F0000F23A88010000000042C0 +:10C070003BE001000E00001402C801000000001D9A +:10C0800002C001001188231A02500000000000467F +:10C0900003C001003D88000134C000000C002D1DCC +:10C0A00048C10100F00000F23088010000000042A9 +:10C0B00031F001000000001402B001000000001D7A +:10C0C00002C001000000001802C001001988221AF5 +:10C0D000025000003D88000134C000002200001919 +:10C0E00048C9010002002D1448C10100000000F6FB +:10C0F00014B001000000001D14D001000000001861 +:10C1000014D001000000001E24B00100120000172E +:10C1100010C801003D88001A10C0000000003C4417 +:10C1200023E00100000000A486B0010000002E10F2 +:10C1300048C101002688A3120E6C000027886807FA +:10C140001AB00000000068121AB001002A888008A6 +:10C15000F03100000100001198C801000000004CFF +:10C160001E9001000000000CF0B101000000000270 +:10C17000E0B101000000001086C001000000004690 +:10C1800061B10100011F004362DD01002E88A85C3F +:10C190001F1000005A88220D145000005A88220DEA +:10C1A000245000000000000D10C00100358822421C +:10C1B000236C00003D88004123C0000000000046C1 +:10C1C00061B101004000001062DD01003688A85C0A +:10C1D0001F0000001B8400881CB00000000000103D +:10C1E00048B1010011960043233001000E00000FFA +:10C1F0001E8C01000000004023B001005988A20DF0 +:10C200000E500000488822461F7C000000000046B7 +:10C210001F8001003080001042C901004688224082 +:10C22000E36D00000000004761B101004000001014 +:10C2300062DD01004388A840813200001B84008831 +:10C240001CB0000020800003469901000000005F40 +:10C25000E191010000002D0648B10100000000F846 +:10C2600018B00100000000F804B001004D881FF074 +:10C270000E300000EA87004C0DC0000000002E5F69 +:10C280000F800100EA872307146C000030000010C3 +:10C2900048C9010024000040F1990100000000039A +:10C2A000F0B1010000000000F0B101000000001634 +:10C2B000F0B101002400000000C8010000000047A8 +:10C2C00061B10100A00000A462DD01005688A8460B +:10C2D0001F100000EA8700030CB00000EA87000D81 +:10C2E00018C000007788A2441F7C000000000019DD +:10C2F0000AB001002200000548C901000A002D14FF +:10C3000048C1010002002040E5B1010004002040C6 +:10C31000E5B101000D002D1D48C10100090000F329 +:10C32000388801000D002050E7B1010004002D40C5 +:10C330003FB00100000000F432B0010004002040D2 +:10C34000E1B101002200000548C9010000002D14E0 +:10C3500048C101000200001D94F4010000000040EB +:10C3600091B001006C88A0FC9040000000000041EA +:10C3700091C001006A88A241955000000480000528 +:10C3800044C9010000000048F0B10100000000189D +:10C3900048C101000200001894F4010000002D18AB +:10C3A00090B001007488A0FC9040000000000041A3 +:10C3B00091C001007288A241955000000000004821 +:10C3C000E0B1010010002040E5B1010022000005AD +:10C3D00048C901000000001448C1010004800005A4 +:10C3E00042C90100000000F880B00100000000F028 +:10C3F00016C001007C8842303D0700000000009E0E +:10C4000085B0010000001A413DC301000400204234 +:10C41000ECB101000000001E82B0010002002E1DE0 +:10C4200082C001000000661882C0010000000042C6 +:10C4300080C001008688A0418044000000000041C7 +:10C4400081C001001000004092F401000A002E306B +:10C45000818401008A8890409240000000000041E1 +:10C4600093C001000000662093A401000000001D9D +:10C4700048C1010004002019E8B101000000001EBD +:10C4800016C001009088A019164400000000004169 +:10C4900017C001000D002F1E32C001009588A24078 +:10C4A000156C00009488A01C16400000000000419C +:10C4B00017C00100000063F338940100100000056C +:10C4C00048C9010004002E1E98B001000000601A47 +:10C4D00098C001000C002040E1B10100A388224671 +:10C4E0001F7C0000000000461F800100308000100B +:10C4F00042C90100A1882240E36D0000000000470E +:10C5000061B101004000001062DD01009E88A8407A +:10C51000813200001B8400881CB0000020800003D2 +:10C52000469901000000005FE19101003080001099 +:10C5300044C901001200001AF0C9010000000017F0 +:10C54000F0B1010010000005E0C90100300000104A +:10C5500080C801000000004461B1010020000040DB +:10C5600062DD0100A988A84081320000B788225C02 +:10C570001F7C000000003C4423E0010000002D105F +:10C5800048C10100B3882240E36D0000000000466E +:10C5900061B101004000001062DD0100B088A840D8 +:10C5A000813200001B8400881CB000000000005C89 +:10C5B0001F8001000000001048B1010011960041E9 +:10C5C000234001000E00000F1E8C010020002F05EB +:10C5D00048B101000000000BE4B101000000005070 +:10C5E00017F00100BC8890F21640000000000041E6 +:10C5F00017C001000000662017A4010010000014FD +:10C600002AC801000000001D2AC0010000000050DF +:10C610002BE00100000000F22A940100308000109D +:10C6200042C90100C7882240E36D000000000044B9 +:10C6300061B101004000001062DD0100C488A84023 +:10C64000813200001B8400881CB0000000800017AD +:10C6500010DC0100E4882240156C0000CF88A24461 +:10C660001F7C0000000000441F900100CE88229F24 +:10C67000136C0000020000881CCC01006B84004099 +:10C6800081B20000000000413FC3010066990040F4 +:10C6900081320100D288A241877C00000000001E88 +:10C6A0003EC00100E4882240156C0000D588201EA1 +:10C6B000146C00000000000A3CB00100DD95001E73 +:10C6C00024300100DA8822082E30000000000052D9 +:10C6D00011C001000000001A10C001003D88004098 +:10C6E00017B000006B8400881CB00000DD9500408E +:10C6F00081320100D788A2082E300000808000A679 +:10C7000004B001000600004087980100008000038B +:10C710004499010004002204E03100005599001FF3 +:10C720008C300100000000400FB00100058A005C61 +:10C730001F900000008000034499010004002204BF +:10C74000E03100006699004081320100E988A24191 +:10C75000877C0000EA88001E3EC000000000001F29 +:10C760008CB001000000004005B001005599004068 +:10C770000F300100058A005C1F900000F5889C0FB7 +:10C78000803200000000005C1F800100008000106B +:10C7900042C90100F5882240E36D00000000004717 +:10C7A00061B101004000001062DD0100F288A84084 +:10C7B000813200001B8400881CB00000FA88220728 +:10C7C000803200000000000342B1010000000007B9 +:10C7D00042C10100008000A1469901000000005FF5 +:10C7E000E191010004002E0348B10100FD8820946E +:10C7F000156C0000FE880094E1B100000000000A02 +:10C80000E0B1010001892240316C00000C000040C1 +:10C8100045990100000060183896010000002E10B4 +:10C8200048B1010000000050F1B101000000000813 +:10C83000F0B1010000000003E0B10100000000447D +:10C8400061B101000000001062B101000689A8403A +:10C85000233000001B8400881CB0000000002D5213 +:10C8600011C001001000000348C90100000000F8D9 +:10C8700018B00100000000F804B00100000000F84A +:10C880000EB001000C0000A40CC8010000003C44E4 +:10C8900023E00100000000A486B0010000002E107B +:10C8A00048C101001489A3120E6C000015896807A5 +:10C8B0001AB00000000068121AB001000000001059 +:10C8C00086C0010000000008F0B101000000000C6B +:10C8D000F0B1010000000002E0B1010000000046DC +:10C8E00061B10100011F004362DD01001A89A85CEB +:10C8F0001F1000004B89220D146C00002089220DAE +:10C90000246C00000000000D10C001002489000DFF +:10C9100024D00000000000412BC0010000000015E1 +:10C92000A2B101001000002010C80100F007004073 +:10C930002598010026892242236C00002D890041A0 +:10C9400023C000000000004661B10100400000105B +:10C9500062DD01002789A85C1F0000001B8400889D +:10C960001CB000000000001048B10100D794004343 +:10C97000233001000000004023B001000400220D1C +:10C98000145000004A89A20D0E5000003989224639 +:10C990001F7C0000000000461F8001003080001056 +:10C9A00042C9010037892240E36D000000000047C2 +:10C9B00061B101004000001062DD01003489A8402F +:10C9C000813200001B8400881CB00000208000031E +:10C9D000469901000000005FE191010000002D0672 +:10C9E00048B10100000000F818B00100000000F894 +:10C9F00004B001003E891FF00E3000000F89004C8A +:10CA00000DC0000000002E5F0F8001000F8923077A +:10CA1000146C00003000001048C9010024000040E0 +:10CA2000F199010000000003F0B1010000000000D6 +:10CA3000F0B1010000000016F0B101002400000078 +:10CA400000C801000000004761B10100A00000A47F +:10CA500062DD01004789A8461F1000000F8900030E +:10CA60000CB000000F89000D18C000005489225C32 +:10CA70001F7C00000000005C1F80010000003C449F +:10CA800023E0010000002D1048C10100548922401C +:10CA9000E36D00000000004661B10100400000109D +:10CAA00062DD01005189A840813200001B840088AA +:10CAB0001CB000000000001048B10100D7940041F4 +:10CAC000234001000000001710B001005889004009 +:10CAD0002BB0000000800003449901000000000416 +:10CAE000E0B101005D89229F136C00000200008804 +:10CAF0001CCC01006B84004081B2000066990041AB +:10CB00003F430100000000408DB0010000000040E4 +:10CB100005B00100559900400F3001001B8A005CF0 +:10CB20001F900000100000000EF401000000003A09 +:10CB300001840100030000071AF401002196000798 +:10CB4000163001006C892241816C00006A89224202 +:10CB5000816C00001B8400881CB000006B89225F80 +:10CB60000F7C0000058A00400FB000007489A25AB3 +:10CB70001F7C00009B9500408132010074892220B7 +:10CB8000856C000071899C0F803200001B84008836 +:10CB90001CB000007C96005C1F0001009B980042C6 +:10CBA000613101001B8400881CB00000E699000779 +:10CBB0009630010000002D0548B10100000000F092 +:10CBC00018B001000000000080B00100AE8AA25F32 +:10CBD000816C0000A8002D431980010037002DF062 +:10CBE00024B00100040000F38EF401000F0000F3F4 +:10CBF00090880100838922488E6C00003600004036 +:10CC00004399010058003D43E7E1010083891FF08B +:10CC1000246C0000828923418F6C0000AE8A00479B +:10CC200081B00000AE8A004881B0000040000040A2 +:10CC300043990100B0002DF014B001008889220A48 +:10CC4000904000003999004091300100AE8AA24026 +:10CC500080320000B0002D4581B00100948922F09F +:10CC60002C300000A3002D3083B00100AC002DF368 +:10CC700082E001008E89A3412C6C000000000016A8 +:10CC800082B0010098002DF082C0010088002DF0D4 +:10CC900082D00100000000F298E80100AE8A204C2A +:10CCA000826C00007C002D4198E80100AE8A20F0E3 +:10CCB000986C0000058A220A803200004002000CB5 +:10CCC0007E890100058AA64081320000AE8A0049B3 +:10CCD00081B00000200000A680B001009C892243A2 +:10CCE000216F00001380004080DC01009D8900401E +:10CCF00081B200001A80004080DC01009D89A25EA4 +:10CD00000B7D00000000004008B101009F899F8555 +:10CD100080320000A389004081B200005F8422407D +:10CD2000577D00000100004057990100A38942404F +:10CD300081320000000000449393010049841A5B93 +:10CD4000699300007B00004061990100A689A8B1A9 +:10CD500080300000CF891D4080320000C089224011 +:10CD6000AF6F0000C089225B817C00000400225D5F +:10CD7000737D00007D00004061990100AC89A8B17D +:10CD8000943000000000005F61B101000000004A23 +:10CD900062B10100AF89A84081320000B1894340EF +:10CDA00081320000BF892257737D00007700004068 +:10CDB00061990100B389A8B1943000007700004068 +:10CDC00061990100B589A8B19630000000000048C3 +:10CDD00061B101000000004A62B10100B889A84AAF +:10CDE00080330000BD89225F957C00000000004B6D +:10CDF00062B10100BB89A84BAC33000000001BA549 +:10CE000082B30100C08900BE83C3000000001B4044 +:10CE100081B301004018004049990100040000A6B8 +:10CE200086B00100CD89A240860400001B849C408E +:10CE300080320000FFFF004088880100E98900502F +:10CE4000473101003600004488CC0100C9895240B6 +:10CE500081320000E98900404731010000000041B3 +:10CE600089B00100E989004847310100E9890005DE +:10CE7000473101001B84004081B2000028000040BF +:10CE8000479901001B840041E1C10000781800406F +:10CE900049990100D6892254817C0000D189424001 +:10CEA00081320000008200B469DF010000001A44F2 +:10CEB000939301002800004047990100E98900414F +:10CEC00089300100E4890F4080320000FF7F00407C +:10CED00088880100E989005047310100360000448C +:10CEE00088CC0100DC8999408032000000000048B5 +:10CEF00089D00100DE899B40803200000000004C98 +:10CF000089D00100E0891F4480320000E989004097 +:10CF1000473101000000004189B00100E989004863 +:10CF200047310100E9890058473101001B84004066 +:10CF300081B200001000004086F401006F00004341 +:10CF4000868801001B84260547310000E9890041DD +:10CF5000893001001B84004081B200000000A04421 +:10CF6000F04101000000004081B20100000080415A +:10CF7000E1C10100040000CB81C80100EF8922401B +:10CF8000F27F00008180006F97330100F189224019 +:10CF9000737D00009B8000418BB30000EC89225917 +:10CFA000737D00007900004061990100EC8928B18F +:10CFB0007E310000F289004081B20000040022C0EE +:10CFC00095300000000000D697B00100FA89225D7C +:10CFD000737D00007D00004061990100F889A8B1CF +:10CFE000803000000000005E7F830100000000BF71 +:10CFF000C5B10100040000408198010025010040F6 +:10D0000081320100FD89A24181500000FF89435F08 +:10D010007F130000260100BFC53101000000005F42 +:10D020007F8301000000005E7F9301008B9800BFAA +:10D03000C53101001B84004081B200000C8A9C0FA6 +:10D04000803200000080001042C901000C8A22409A +:10D05000E36D00000000004561B1010040000010D8 +:10D0600062DD0100098AA840813200001B8400882B +:10D070001CB0000077952202803200000D8A4240E9 +:10D0800081320000000000449393010077951A025A +:10D0900068970000178A9C0F803200000080001003 +:10D0A00042C90100178A2240E36D000000000045DC +:10D0B00061B101004000001062DD0100148AA84047 +:10D0C000813200001B8400881CB000008195220280 +:10D0D00080320000188A4240813200000000004483 +:10D0E0009393010081951A0268970000228A9C0F91 +:10D0F000803200000080001042C90100228A2240D4 +:10D10000E36D00000000004561B101004000001027 +:10D1100062DD01001F8AA840813200001B84008864 +:10D120001CB000006F84220280320000238A42403B +:10D1300081320000000000449393010000001A02B5 +:10D14000689701006F84004005B00000008000A6D1 +:10D1500056B1010056952F4005B00100738AA240D8 +:10D16000E76D0000B8942941E7B1010000000054C8 +:10D17000EF930100000000F20EB001002900004012 +:10D180000D9801000900000712E40100000000A74B +:10D1900013C00100030000071AF401000700000794 +:10D1A00016880100FFFF001034D8010000000003C2 +:10D1B000349401000000004023B00100201800401A +:10D1C0001198010000B5000D42C90100578A220BD9 +:10D1D000E67D0000388A444081320000FFFF0007EE +:10D1E000848901003F8A05C224300000679800400E +:10D1F0008132010000002D0548B10100748A1CF045 +:10D2000018300100578A004081B2000000001C4025 +:10D2100081B201004E8AA048236C0000000000503B +:10D2200035D001000080001A42C90100488A22401E +:10D23000E36D00000000004261B101004000001AEF +:10D2400062DD0100458AA840813200001B8400880D +:10D250001CB000002098004043990100748A00F837 +:10D2600018300100498AA24123500000FFFF00103E +:10D2700034D801000000000334940100201800405D +:10D280001198010000002E1A48B10100000000446E +:10D29000F1B1010000000008F0B1010000000042FF +:10D2A00061B101002000001A62DD0100528AA80964 +:10D2B000E03100000000004123C0010000000050E8 +:10D2C00035C001000000004411C00100638A224102 +:10D2D0000D500000000000410FC001005F8AA0AAAD +:10D2E0000F6C0000000000410FB0010009000007B2 +:10D2F00012E40100000000A713C00100000000407C +:10D300001BB00100368A004117B00000000200097E +:10D3100012C80100368A8341174000000000004017 +:10D3200017B00100368A00411BC000006E8A2340FE +:10D33000236C00000000005035D001000080001A6E +:10D3400042C901006B8A2240E36D000000000042E8 +:10D3500061B101004000001A62DD0100688AA84046 +:10D36000813200001B8400881CB00000209800401F +:10D3700043990100748A00F8183001006C8AA241B8 +:10D3800023500000000000410FC00100718AA0AAD4 +:10D390000F6C0000000000410FB00100B89420079E +:10D3A000E4B1010056952040E7B10100058A004034 +:10D3B0000FB00000FFFF000C80D80100C002000C7D +:10D3C0007E890100868A2654613100007C8A870CA0 +:10D3D000803200000F000040629901007C8A2840E2 +:10D3E000813200007C8AA254777D0000788A004058 +:10D3F00081B20000818A2246197C00000D000040A5 +:10D40000629901000000A84081B200000000A2540F +:10D41000777D01007D8A004081B20000868A224922 +:10D42000197C00000E000040629901000000A84035 +:10D4300081B200000000A254777D0100818A004083 +:10D4400081B2000010000040629901000000A84075 +:10D4500081B200000000A254777D0100868A00405E +:10D4600081B2000030942F55F1930100004000A6D6 +:10D4700056B101006F84A241E551000064000040F4 +:10D48000E59901008E8A424081320000918AA29380 +:10D49000576F00000000004157C3010000001AABA5 +:10D4A00027B301006F842250FD7F00006F8422515A +:10D4B000FD7F00006F84A2411D53000050460040D4 +:10D4C0001D9B010034820040813201000E000048A3 +:10D4D000B2CB0100FC810040493101009D8A22400D +:10D4E000B56F00000E000048B2CB0100FF81004183 +:10D4F000B55301006F84004081B20000000000516C +:10D50000FD8301004016004045990100358200402E +:10D51000493101001E000048B2CB0100FC810040EF +:10D5200081320100000000DA91C0010004000048CF +:10D53000B2CB0100FF810040B533010060162040EE +:10D54000E5B10100DB820040B5330100080000486E +:10D55000B2CB0100FFFF004AB48B0100FF81004005 +:10D56000813201000A000048B2CB01001000004ADD +:10D57000B4F70100FF810040813201006F84004058 +:10D5800081B200000500004043990100000000F353 +:10D5900008B0010004002040E6B101000300004093 +:10D5A00096E401000000000496C00100B48A004B1C +:10D5B00010C90000D78D004109B000000400002010 +:10D5C0008FB00000040000208FB000000400002095 +:10D5D0008FB00000040000208FB000000400002085 +:10D5E0008FB00000040000208FB000000400002075 +:10D5F0008FB00000040000208FB000000B8E0041AF +:10D6000009B00000040000208FB0000004000020DA +:10D610008FB00000040000208FB000000400002044 +:10D620008FB00000040000208FB000000400002034 +:10D630008FB00000040000208FB000000400002024 +:10D640008FB000003D8E004509B000003D8E0045C2 +:10D6500009B000003D8E004509B000003D8E004538 +:10D6600009B00000040000208FB00000040000207A +:10D670008FB00000040000208FB0000004000020E4 +:10D680008FB000007C8E004309B00000A58E0043DF +:10D6900009B00000A98E004409B0000011900045B7 +:10D6A00009B00000040000208FB00000040000203A +:10D6B0008FB00000040000208FB0000004000020A4 +:10D6C0008FB00000040000208FB00000B58E004332 +:10D6D00009B00000B48E004309B00000D58D0045AC +:10D6E00009B00000040000208FB0000004000020FA +:10D6F0008FB00000040000208FB000000400002064 +:10D700008FB00000758F004209B00000758F004394 +:10D7100009B00000758F004409B00000D58D0045A8 +:10D7200009B00000040000208FB0000004000020B9 +:10D730008FB00000040000208FB000000400002023 +:10D740008FB00000040000208FB00000A18F0043C4 +:10D7500009B00000040000208FB00000D58D004506 +:10D7600009B00000040000208FB000000400002079 +:10D770008FB00000040000208FB0000004000020E3 +:10D780008FB00000040000208FB00000BF8F004366 +:10D7900009B00000BF8F004409B00000D58D0045DE +:10D7A00009B00000040000208FB000000400002039 +:10D7B0008FB00000040000208FB0000004000020A3 +:10D7C0008FB00000040000208FB00000BF8F004227 +:10D7D00009B00000040000208FB00000D58D004586 +:10D7E00009B00000040000208FB0000004000020F9 +:10D7F0008FB00000040000208FB000000400002063 +:10D800008FB00000040000208FB00000E78F0044BC +:10D8100009B00000040000208FB00000D58D004545 +:10D8200009B00000040000208FB0000004000020B8 +:10D830008FB00000040000208FB000000400002022 +:10D840008FB00000D58D004209B00000F88F004570 +:10D8500009B00000F88F004509B00000D58D0045E3 +:10D8600009B00000040000208FB000000400002078 +:10D870008FB00000040000208FB0000004000020E2 +:10D880008FB00000FA8F004209B00000FA8F004309 +:10D8900009B00000FA8F004409B00000FA8F00457B +:10D8A00009B00000040000208FB000000400002038 +:10D8B0008FB00000040000208FB0000004000020A2 +:10D8C0008FB00000040000208FB000000400002092 +:10D8D0008FB000000290004409B00000D58D0045D3 +:10D8E00009B00000040000208FB0000004000020F8 +:10D8F0008FB00000040000208FB000000400002062 +:10D900008FB000001390004209B000000390004364 +:10D9100009B000001390004409B00000D58D004507 +:10D9200009B00000040000208FB0000004000020B7 +:10D930008FB00000040000208FB000000400002021 +:10D940008FB00000040000208FB00000149000434E +:10D9500009B000000A90004409B00000D58D0045D0 +:10D9600009B00000040000208FB000000400002077 +:10D970008FB00000040000208FB00000D58D004162 +:10D9800009B00000738F004209B00000738F00439C +:10D9900009B00000738F004409B00000D58D004528 +:10D9A00009B00000040000208FB000000400002037 +:10D9B0008FB00000040000208FB00000D58D004122 +:10D9C00009B000001590004209B000001590004316 +:10D9D00009B000001590004409B00000D58D004545 +:10D9E00009B00000040000208FB0000004000020F7 +:10D9F0008FB00000040000208FB000000400002061 +:10DA00008FB00000040000208FB000000400002050 +:10DA10008FB00000040000208FB000001C90004573 +:10DA200009B00000040000208FB0000004000020B6 +:10DA30008FB00000040000208FB000001E90004254 +:10DA400009B00000040000208FB000000400002096 +:10DA50008FB00000040000208FB000000400002000 +:10DA60008FB00000040000208FB0000004000020F0 +:10DA70008FB00000040000208FB0000004000020E0 +:10DA80008FB000002A90004309B00000939000433B +:10DA900009B00000A98E004409B0000011900045B3 +:10DAA00009B00000040000208FB000000400002036 +:10DAB0008FB00000040000208FB0000004000020A0 +:10DAC0008FB00000040000208FB000009B90004346 +:10DAD00009B00000A98E004409B000001190004573 +:10DAE00009B00000040000208FB0000004000020F6 +:10DAF0008FB00000040000208FB000000400002060 +:10DB00008FB00000040000208FB00000AC900043F4 +:10DB100009B00000040000208FB00000D58D004542 +:10DB200009B00000040000208FB0000004000020B5 +:10DB30008FB00000040000208FB00000040000201F +:10DB40008FB00000798E004309B000009790004329 +:10DB500009B00000A98E004409B0000011900045F2 +:10DB600009B00000040000208FB000000400002075 +:10DB70008FB0000007002D0548B10100000000F340 +:10DB800008B0010006002047E6B10100040000478C +:10DB900096E401000000004796D001000000004715 +:10DBA00096D001000000000496C00100748B004B69 +:10DBB00010C90000C490004909B000000400002012 +:10DBC00085B000000400002085B0000004000020A3 +:10DBD00085B000000400002085B000000400002093 +:10DBE00085B000000400002085B000000400002083 +:10DBF00085B000000400002085B000000400002073 +:10DC000085B000000400002085B000000400002062 +:10DC100085B000000400002085B000000400002052 +:10DC200085B000000400002085B00000FD90004297 +:10DC300009B000000400002085B0000004000020AE +:10DC400085B000000400002085B000000400002022 +:10DC500085B000000400002085B000000400002012 +:10DC600085B000000400002085B000000400002002 +:10DC700085B000000400002085B0000004000020F2 +:10DC800085B000000400002085B0000004000020E2 +:10DC900085B000000400002085B00000039100461C +:10DCA00009B000000400002085B00000040000203E +:10DCB00085B000000400002085B0000004000020B2 +:10DCC00085B000000400002085B0000004000020A2 +:10DCD00085B000000400002085B000000400002092 +:10DCE00085B000000400002085B000000400002082 +:10DCF00085B000000400002085B000000400002072 +:10DD000085B000000400002085B000000400002061 +:10DD100085B000001191004209B00000040000200D +:10DD200085B000003391004209B0000004000020DB +:10DD300085B000000400002085B000000400002031 +:10DD400085B000000400002085B000000400002021 +:10DD500085B000000400002085B000002E91004A2C +:10DD600009B000000400002085B00000040000207D +:10DD700085B000000400002085B0000004000020F1 +:10DD800085B000003691004309B000000400002077 +:10DD900085B000008F91004409B00000040000200D +:10DDA00085B000000400002085B0000004000020C1 +:10DDB00085B000000400002085B0000004000020B1 +:10DDC00085B000000400002085B000008E91004B5B +:10DDD00009B000000400002085B00000040000200D +:10DDE00085B000000400002085B0000006910041CD +:10DDF00009B000000400002085B000000691004337 +:10DE000009B000000691004409B0000006910045E9 +:10DE100009B000000691004609B0000006910047D5 +:10DE200009B000000691004809B0000006910049C1 +:10DE300009B000000691004A09B000000691004BAD +:10DE400009B000000691004C09B000000691004D99 +:10DE500009B000000400002085B00000040000208C +:10DE600085B00000EE91004209B0000004000020DF +:10DE700085B00000EE91004409B0000004000020CD +:10DE800085B000000400002085B0000004000020E0 +:10DE900085B000000400002085B0000004000020D0 +:10DEA00085B000000400002085B00000EE91004B1A +:10DEB00009B000000400002085B00000040000202C +:10DEC00085B000000400002085B0000004000020A0 +:10DED00085B000000400002085B0000006920045D7 +:10DEE00009B000000400002085B0000004000020FC +:10DEF00085B000000400002085B000000400002070 +:10DF000085B000001D92004709B000000400002009 +:10DF100085B00000FA91004509B00000040000201F +:10DF200085B000000400002085B000007C9400460D +:10DF300009B000000400002085B0000004000020AB +:10DF400085B000000400002085B00000040000201F +:10DF500085B000000400002085B000003391004629 +:10DF600009B000001191004609B000002C91004753 +:10DF700009B000002C91004809B000000400002006 +:10DF800085B000000400002085B0000004000020DF +:10DF900085B000002E91004A09B000000400002066 +:10DFA00085B000000400002085B0000004000020BF +:10DFB00085B000000400002085B0000004000020AF +:10DFC00085B000000400002085B000008F9100455E +:10DFD00009B000003691004309B000002C910047C1 +:10DFE00009B000002C91004809B000000400002096 +:10DFF00085B000000400002085B00000040000206F +:10E0000085B000008E91004C09B000000400002093 +:10E0100085B000000400002085B00000040000204E +:10E0200085B000000400002085B00000040000203E +:10E0300085B000000400002085B000002392004459 +:10E0400009B000002392004209B00000C08D0047D3 +:10E0500009B00000C08D004809B000000400002095 +:10E0600085B000000400002085B0000004000020FE +:10E0700085B000002392004B09B00000040000208E +:10E0800085B000000400002085B00000069100412A +:10E0900009B000004692004709B0000004000020CB +:10E0A00085B000002E92004709B000000400002057 +:10E0B00085B000000400002085B0000004000020AE +:10E0C00085B000000400002085B00000040000209E +:10E0D00085B000000400002085B000002E920047AB +:10E0E00009B000000400002085B0000004000020FA +:10E0F00085B000000400002085B00000040000206E +:10E1000085B000000400002085B00000040000205D +:10E1100085B000000400002085B000002E9200476A +:10E1200009B000004692004709B000002C9100475A +:10E1300009B000002C91004809B000000400002044 +:10E1400085B000000400002085B00000040000201D +:10E1500085B000002E92004709B0000004000020A6 +:10E1600085B000000400002085B0000004000020FD +:10E1700085B000000400002085B0000004000020ED +:10E1800085B000000400002085B0000004000020DD +:10E1900085B000000400002085B0000055920047C3 +:10E1A00009B000005592004809B0000004000020AA +:10E1B00085B000000400002085B0000004000020AD +:10E1C00085B000000400002085B00000040000209D +:10E1D00085B000000400002085B00000B892004027 +:10E1E00009B00000D692004709B00000CA9200486A +:10E1F00009B000002692004709B0000026920047AF +:10E2000009B00000D692004709B00000DD92004737 +:10E2100009B00000DD92004809B0000004000020B1 +:10E2200085B00000CA92004809B00000269200475D +:10E2300009B000002692004709B00000CA920048C9 +:10E2400009B000000400002085B000000400002098 +:10E2500085B000000400002085B00000EE9100436E +:10E2600009B000000400002085B00000EE910045D8 +:10E2700009B00000EE91004609B000002C91004763 +:10E2800009B000002C91004809B0000004000020F3 +:10E2900085B00000EE91004A09B0000004000020A3 +:10E2A00085B00000EE91004C09B000000400002091 +:10E2B00085B000000400002085B0000004000020AC +:10E2C00085B000004592004709B00000399200482F +:10E2D00009B000002D92004709B000002D920047C0 +:10E2E00009B000004592004709B00000C08D00470A +:10E2F00009B00000C08D004809B0000004000020F3 +:10E3000085B000003992004809B000002D92004706 +:10E3100009B000002D92004709B000003992004872 +:10E3200009B000000400002085B0000004000020B7 +:10E3300085B00000DF92004209B000000400002018 +:10E3400085B00000DF92004409B000000400002006 +:10E3500085B000000400002085B00000040000200B +:10E3600085B000000400002085B0000004000020FB +:10E3700085B000000400002085B00000DF92004B53 +:10E3800009B000000400002085B000000400002057 +:10E3900085B000000400002085B0000004000020CB +:10E3A00085B000000400002085B00000DF9200432B +:10E3B00009B000000400002085B00000DF92004595 +:10E3C00009B00000DF92004609B00000DF9200476C +:10E3D00009B00000DF92004809B0000004000020EE +:10E3E00085B00000DF92004A09B000000400002060 +:10E3F00085B00000DF92004C09B00000DF92004CB5 +:10E4000009B000000400002085B0000004000020D6 +:10E4100085B000000400002085B00000FA9200469C +:10E4200009B000000400002085B0000004000020B6 +:10E4300085B000000400002085B00000040000202A +:10E4400085B000001D92004709B0000004000020C4 +:10E4500085B00000FA92004609B0000004000020D8 +:10E4600085B000000400002085B0000004000020FA +:10E4700085B000000400002085B0000004000020EA +:10E4800085B000000400002085B00000069400461E +:10E4900009B000000400002085B000000400002046 +:10E4A00085B000000400002085B0000004000020BA +:10E4B00085B000001D92004709B000000400002054 +:10E4C00085B000000694004609B00000040000205A +:10E4D00085B000000400002085B0000006940046CE +:10E4E00009B000000400002085B0000004000020F6 +:10E4F00085B000000400002085B00000040000206A +:10E5000085B000002B94004209B0000004000020F8 +:10E5100085B000000400002085B000000400002049 +:10E5200085B000000400002085B000000400002039 +:10E5300085B000000400002085B000002A94004A45 +:10E5400009B000000400002085B000000400002095 +:10E5500085B000000400002085B000000400002009 +:10E5600085B000000400002085B0000004000020F9 +:10E5700085B000000400002085B000002B94004608 +:10E5800009B000000400002085B000002C91004775 +:10E5900009B000002C91004809B0000004000020E0 +:10E5A00085B000000400002085B0000004000020B9 +:10E5B00085B000002A94004A09B000000400002041 +:10E5C00085B000000400002085B000000400002099 +:10E5D00085B000000400002085B000000400002089 +:10E5E00085B000000400002085B000000400002079 +:10E5F00085B000000400002085B000000400002069 +:10E6000085B000000400002085B00000EA920041BF +:10E6100009B000000400002085B0000004000020C4 +:10E6200085B000000400002085B000000400002038 +:10E6300085B000000400002085B000000400002028 +:10E6400085B00000F792004209B0000004000020ED +:10E6500085B00000F792004409B0000004000020DB +:10E6600085B000000400002085B0000004000020F8 +:10E6700085B000000400002085B0000004000020E8 +:10E6800085B000000400002085B00000F792004B28 +:10E6900009B000000400002085B000000400002044 +:10E6A00085B000000400002085B0000004000020B8 +:10E6B00085B000000400002085B00000F792004300 +:10E6C00009B000000400002085B00000F79200456A +:10E6D00009B00000F792004609B00000F792004729 +:10E6E00009B00000F792004809B0000004000020C3 +:10E6F00085B000000400002085B000000400002068 +:10E7000085B00000F792004C09B000000400002022 +:10E7100085B000000400002085B000000400002047 +:10E7200085B000000400002085B000000692004C77 +:10E7300009B000000400002085B0000004000020A3 +:10E7400085B000000400002085B000000400002017 +:10E7500085B000001D92004709B0000004000020B1 +:10E7600085B00000FA91004C09B0000004000020C0 +:10E7700085B000000400002085B00000CD94004664 +:10E7800009B000000400002085B000000400002053 +:10E7900085B000007194004209B000000400002020 +:10E7A00085B000007194004409B00000040000200E +:10E7B00085B000000400002085B0000004000020A7 +:10E7C00085B000000400002085B000000400002097 +:10E7D00085B000000400002085B000007194004B5B +:10E7E00009B000000400002085B0000004000020F3 +:10E7F00085B000000400002085B000000400002067 +:10E8000085B000000400002085B000000400002056 +:10E8100085B000000400002085B000007194004520 +:10E8200009B000007194004609B000002C91004727 +:10E8300009B000002C91004809B00000040000203D +:10E8400085B000000400002085B000000400002016 +:10E8500085B000007194004C09B000000400002055 +:10E8600085B000000400002085B0000004000020F6 +:10E8700085B00000FA91004209B000007C94004687 +:10E8800009B000000400002085B000000400002052 +:10E8900085B00000FA91004609B000000400002095 +:10E8A00085B000001D92004709B000000400002060 +:10E8B00085B000007C94004609B0000004000020F0 +:10E8C00085B000000400002085B000007C94004664 +:10E8D00009B000000400002085B000000400002002 +:10E8E00085B000000400002085B000008094004343 +:10E8F00009B000000400002085B0000004000020E2 +:10E9000085B000000400002085B000000400002055 +:10E9100085B000001D92004709B0000004000020EF +:10E9200085B000008094004309B00000040000207E +:10E9300085B000000400002085B000008094004DE8 +:10E9400009B000000400002085B000000400002091 +:10E9500085B000000400002085B000000400002005 +:10E9600085B000009294004309B00000040000202C +:10E9700085B000000400002085B0000004000020E5 +:10E9800085B000000400002085B0000004000020D5 +:10E9900085B000000400002085B000006F94004A9C +:10E9A00009B000000400002085B000000400002031 +:10E9B00085B000000400002085B0000004000020A5 +:10E9C00085B000000400002085B000000400002095 +:10E9D00085B000000400002085B000009294004340 +:10E9E00009B000000400002085B000002C91004711 +:10E9F00009B000002C91004809B00000040000207C +:10EA000085B000000400002085B000000400002054 +:10EA100085B000006F94004A09B000000400002097 +:10EA200085B000000400002085B000000400002034 +:10EA300085B000000400002085B00000A4940043CD +:10EA400009B000000400002085B000000400002090 +:10EA500085B000000400002085B000000400002004 +:10EA600085B000001D92004709B00000040000209E +:10EA700085B00000A494004309B000000400002009 +:10EA800085B000000400002085B00000A494004D73 +:10EA900009B000000400002085B000000400002040 +:10EAA00085B000001191004209B000000400002070 +:10EAB00085B000003391004209B00000040000203E +:10EAC00085B000000400002085B000000400002094 +:10EAD00085B000000400002085B000000400002084 +:10EAE00085B000000400002085B00000C3940042FF +:10EAF00009B000000400002085B0000004000020E0 +:10EB000085B000000400002085B000000400002053 +:10EB100085B000000400002085B000000400002043 +:10EB200085B000000400002085B00000339100464D +:10EB300009B000001191004609B000002C91004777 +:10EB400009B000002C91004809B00000040000202A +:10EB500085B000000400002085B000000400002003 +:10EB600085B00000C394004609B0000004000020F6 +:10EB700085B000000400002085B0000004000020E3 +:10EB800085B000000400002085B00000C594004A54 +:10EB900009B000000400002085B00000040000203F +:10EBA00085B000000400002085B0000004000020B3 +:10EBB00085B000001D92004709B00000040000204D +:10EBC00085B00000C594004A09B000000400002090 +:10EBD00085B000000400002085B000007D94004650 +:10EBE00009B000000400002085B0000004000020EF +:10EBF00085B000000400002085B000007D94004630 +:10EC000009B000000400002085B0000004000020CE +:10EC100085B000000400002085B000000400002042 +:10EC200085B000001D92004709B0000004000020DC +:10EC300085B000007D94004609B00000040000206B +:10EC400085B000000400002085B000007D940046DF +:10EC500009B000000400002085B00000040000207E +:10EC600085B000000400002085B0000004000020F2 +:10EC700085B00000CB94004209B0000004000020E1 +:10EC800085B000000400002085B0000004000020D2 +:10EC900085B000000400002085B0000004000020C2 +:10ECA00085B000000400002085B000006F94004A89 +:10ECB00009B000000400002085B00000040000201E +:10ECC00085B000000400002085B000000400002092 +:10ECD00085B000000400002085B000000400002082 +:10ECE00085B000000400002085B00000CB940046F1 +:10ECF00009B000000400002085B000002C910047FE +:10ED000009B000002C91004809B000000400002068 +:10ED100085B000000400002085B000000400002041 +:10ED200085B000006F94004A09B000000400002084 +:10ED300085B000000400002085B000000400002021 +:10ED400085B000003691004D09B00000040000209D +:10ED500085B000000400002085B000000400002001 +:10ED600085B000000400002085B0000004000020F1 +:10ED700085B000000400002085B0000004000020E1 +:10ED800085B000000400002085B0000004000020D1 +:10ED900085B000000400002085B0000004000020C1 +:10EDA00085B000000400002085B0000004000020B1 +:10EDB00085B000000400002085B0000004000020A1 +:10EDC00085B000000400002085B000000400002091 +:10EDD00085B000003691004D09B000002C9100472D +:10EDE00009B000002C91004809B000000400002088 +:10EDF00085B000000400002085B000000400002061 +:10EE000085B000000400002085B000000400002050 +:10EE100085B0000007002E4B19900100108A0004F5 +:10EE2000E6B10000C08D2242197C0000C597003A6F +:10EE300081300100C08D004081B20000C08D2242AF +:10EE4000197C0000FF1F000F1E8C01003797004047 +:10EE500081320100D08D9C0F803200000000005CE8 +:10EE60001F8001000080001042C90100D08D2240A7 +:10EE7000E36D00000000004561B10100400000109A +:10EE800062DD0100CD8DA840813200001B84008826 +:10EE90001CB000001986220280320000D18D424051 +:10EEA00081320000000000449393010000001A0228 +:10EEB000689701001986004005B0000005002E4B40 +:10EEC00019900100108A0004E6B100000000004023 +:10EED00087B00100000000408DB0010000800003F9 +:10EEE00042C90100400000A144C90100000000F037 +:10EEF000E0B101005599000607400100000000063E +:10EF000007D00100D4002E5C1F9001000000000714 +:10EF1000F0B101000C80000342C90100000000F0C4 +:10EF2000F0B101000000004081B20100000000FECD +:10EF300096B00100000000FE96C00100000000F045 +:10EF4000F0B101000000004081B20100000000FEAD +:10EF500096C00100000000FE96C00100000000F015 +:10EF6000F0B101000000004081B20100000000FA91 +:10EF700096C00100000000FE96C001000030004B6A +:10EF8000948801000000004695F001000000004A4E +:10EF900096C001005E012E34978401000200004BF0 +:10EFA000E4E5010064012040E1B10100090000072F +:10EFB00086E4010000002EA787C0010010000010A9 +:10EFC00048C9010010000040F199010058010043B8 +:10EFD000F0C9010058010005E0C90100000000442B +:10EFE00061B10100A00000A462DD0100FA8DA8401B +:10EFF000813200000000000548B101001A00004005 +:10F000009798010008002E4095B00100028E204B19 +:10F01000946C000000000040F1B10100FF8D004140 +:10F0200095C000001080001042C90100098E2240E6 +:10F03000E36D00000000004461B1010040000010D9 +:10F0400062DD0100058EA840813200001B8400882B +:10F050001CB000000000000548B10100C597004049 +:10F0600081300100D58D004081B200000C8000038A +:10F0700042C90100000000F886B00100000000F85D +:10F0800088B001000E8E424081320000118EA24CE9 +:10F09000FD7F0000128E004CFD930000138E20F0C7 +:10F0A000566F0000000000F056B3010000001A4047 +:10F0B00081B201000080001044C9010064000040DA +:10F0C000F199010070000005F0C901000000004343 +:10F0D000F0B101000000004761B101002000001004 +:10F0E00062DD0100198EA844E0310000100000101C +:10F0F0008CC801000080004644C901004000004067 +:10F10000F199010068010005F0C9010064000043A5 +:10F11000F0C901000000004761B101000000004695 +:10F1200062B10100218EA844E03100001B840088F8 +:10F130001CB000000900000786E4010038002EA77B +:10F1400087C001008B002D0548B10100298E2243A4 +:10F15000E77D00000000004445C101002C8E2244E0 +:10F16000E77D00000000004C45C101000000004A9E +:10F1700019900100680120A2E4B10100880000405C +:10F1800043990100308E230BE56D00000000004123 +:10F19000199001000080001044C901005000004097 +:10F1A000F199010058010043F0C901005801000520 +:10F1B000E0C901000000004461B10100000000103E +:10F1C00062B10100358EA840813200001B840088A6 +:10F1D0001CB000005C002E0548B101000080000357 +:10F1E00042C90100000060F096B00100C5970041DF +:10F1F00081300100D58D004081B20000408EA249CF +:10F20000197C00008600004047990100448E0040B0 +:10F21000E5B1000086002F4919800100448EA2F25A +:10F22000803200008B00004047990100000000423E +:10F23000E7910100478EA246197C0000A000004023 +:10F24000479901004B8E0040E5B10000A0002F4619 +:10F25000198001004B8EA2F2803200008B0000402A +:10F260004799010000000041E7910100A80000401B +:10F270004399010034002DF024B00100000000FB90 +:10F280000CB00100000000FB10B00100000000FB0A +:10F2900012B001000F0000F316880100040000F313 +:10F2A00014F40100768E2640813200005E8E220A20 +:10F2B000166C000058003D4313E00100000000F808 +:10F2C00082B00100040022F084300000FD9800406C +:10F2D000813201001B8400881CB000000000000582 +:10F2E00048B101000000004113C001005D8EA04341 +:10F2F000136C00000000004013B00100538E004169 +:10F3000015D00000768E220A8032000058003D435E +:10F3100013E00100000000F882B00100040022F0B8 +:10F3200084300000FD980040813201004000204000 +:10F33000E1B101001B8400881CB000000000000542 +:10F3400048B10100768E22411550000000000041B6 +:10F3500011C001006A8EA043116C00000000004043 +:10F3600011B0010058003D4311E00100000000F819 +:10F3700036B00100040022F0003000000000005010 +:10F3800083B0010004980047613101001B840088AC +:10F390001CB00000749500054831010000000045D4 +:10F3A00061B101004000001062DD0100728EA840D2 +:10F3B000813200001B8400881CB00000668E0005AE +:10F3C00048B1000037002040E7B1010036980051F5 +:10F3D00081300100D58D004081B2000034002E4103 +:10F3E000F5B1010000110040E59901007E8E004852 +:10F3F0001990000034002E41F5B1010000110040C9 +:10F40000E59901000080000342C90100000000F8F6 +:10F4100094B00100838E2245237C0000B0002FF0C1 +:10F420008CB00100000060F08CC001009000004032 +:10F430004399010035002DF08CB0010058003E4387 +:10F44000E7E10100888E2248197C0000000000419D +:10F450008DC001000000680A8CC0010038002A4AF3 +:10F46000E0B1010028000000E0C901003C00201BC1 +:10F47000E0B101001080000342C90100000000F863 +:10F4800038B00100000000F826B00100040022F8A6 +:10F4900002300000968E2301146C0000000000F87A +:10F4A00080B00100000000F882B001004C0020F0A4 +:10F4B000E4B1010044002040E0B1010048002041D7 +:10F4C000E0B10100A8002D1032B00100399900F020 +:10F4D000243001009F8EA244816C00009D8E224149 +:10F4E000197C0000A09600403B300100C38EA208AA +:10F4F0003C3000009F8E004081B20000DD9500404E +:10F5000081320100C38EA2083C3000005000201C54 +:10F51000E0B1010054002013E0B101004E002001D1 +:10F52000E4B101004000200AE0B101003698005F1C +:10F5300081300100D58D004081B2000037000040CD +:10F54000479901007F9600F3943001007E8E224A95 +:10F5500080320000AB8E004081B2000037000040D6 +:10F56000479901007F9600F39430010058003E4314 +:10F5700097E001000000001BF0B101001F006000D7 +:10F58000008C0100D58D85118032000004800003BD +:10F5900042C90100B0002FF08CB00100000060F003 +:10F5A0008CC001003698005F81300100D58D00408D +:10F5B00081B20000B58E004919800000BA8E224148 +:10F5C000197C0000A09600403B300100BE8EA208CE +:10F5D0003C3000003698005F81300100D58D00403E +:10F5E00081B20000DD95004081320100BE8EA2088C +:10F5F0003C3000003698005F81300100D58D00401E +:10F6000081B2000050002D1032B0010054002DF0E6 +:10F6100038B001004E002DF026B0010040002DF260 +:10F6200002B00100000000F014B001003000001032 +:10F630008CC801000080004644C9010068012D44C7 +:10F6400061B10100100068F280C8010000000008EC +:10F65000F0B1010058010005E0C901000000000BF5 +:10F6600037B001000000004036D001005C012E40A0 +:10F6700010C001000000000680C001000000005220 +:10F6800081D00100D18E2094816C0000CB97009432 +:10F69000E5310100D28E004081B20000CB970040DE +:10F6A000E43101002000004662DD0100D28EA84056 +:10F6B000233000000E00000F1E8C0100E28E8241FC +:10F6C000234000002080001042C90100DC8E22404F +:10F6D000E36D00000000004661B101004000001031 +:10F6E00062DD0100D98EA840813200001B840088B1 +:10F6F0001CB000000000001048B10100119600434A +:10F70000233001000000000548B101000000001096 +:10F7100032B001000000004123B001000E00000FD4 +:10F720001E8C01000080001944C90100EA8E2241AC +:10F73000197C0000E68EA3010C6C0000E78E000629 +:10F7400004B000000000000104B00100E98E2002B6 +:10F75000366C00000000001B04B00100ED8E0002BA +:10F76000F0B10000EC8EA3010C6C0000ED8E680679 +:10F7700004B000000000680104B00100EF8E8008B2 +:10F78000F0310000000000111E9001000000001C7C +:10F79000F0B101000000004661B10100011F001935 +:10F7A00062DD0100F18EA813E0310000288F2202F3 +:10F7B0001450000044002D020CD00100188FA2024A +:10F7C00002500000FF8E225C1F7C0000208000039E +:10F7D00042C90100FE8E2240E36D00000000004798 +:10F7E00061B101004000001062DD0100FA8EA84006 +:10F7F000813200001B8400881CB00000000000055E +:10F8000048B1010044002D5C1F80010048002DF02C +:10F8100038B001004C002DF026B0010038002FF266 +:10F8200002B00100198F2201146C00000C8F2246D7 +:10F830001F7C0000000000461F80010020002D03F7 +:10F8400048B101000B8F2240E36D0000000000442E +:10F8500061B101004000001062DD0100088FA84086 +:10F86000813200001B8400881CB0000038002F0586 +:10F8700048B10100000000F894B0010038002DF0FC +:10F8800096B001000000004CE1C10100200000031F +:10F8900048C901000000224AF1B1010044000005FE +:10F8A000F0C901000000004AF0B101000000004B67 +:10F8B000E0B101000000004761B10100A00000A418 +:10F8C00062DD0100158FA85C1F100000198F000574 +:10F8D00048B100000000000238C00100238F22065A +:10F8E000803200000000005033C00100218FA202CE +:10F8F000366C000004008F0D42310000100000F84B +:10F9000010C801000000005C11800100F0070040F9 +:10F9100037980100D58E00A11AB000000000000247 +:10F9200010C00100D58E000236D000005000201C0F +:10F93000E0B1010054002013E0B101004E002001AD +:10F94000E4B101004000200AE0B101002D8F005F0A +:10F9500001B0000037002D4601B00100040000F3A3 +:10F9600080F401002C8FA043816C00000000005542 +:10F9700001B0010040002040E1B101000080001909 +:10F9800042C90100338F2240E36D000000000046B1 +:10F9900061B101004000001962DD0100308FA84014 +:10F9A000813200001B8400881CB0000011960010FA +:10F9B000483101003080001042C901003A8F2240D6 +:10F9C000E36D00000000004461B101004000001040 +:10F9D00062DD0100378FA840813200001B8400885F +:10F9E0001CB0000060012F0548B101000000000BB1 +:10F9F000E4B101000000005017F001003F8F90F2C9 +:10FA0000164000000000004117C001000000662001 +:10FA100017A40100320000A62AC00100000000F275 +:10FA20002A940100488F22491F7C000000000049F1 +:10FA30001F8001000000004005B0010000F0000C34 +:10FA4000188C01000B98004C95300100588F000075 +:10FA500092B000004F8F2240AF6F000000C0001E28 +:10FA600094DC01000000001596B001008898004069 +:10FA7000053001004E8FA240976C0000618F004757 +:10FA800019800000588F000092B000004F8F43484B +:10FA90006131000000D0001E62DD0100548F28405B +:10FAA00005300000508F2248777D0000578F0040BE +:10FAB00081B200000000001562B10100608F284093 +:10FAC00081320000548F004081B2000000001B0012 +:10FAD00092B001005D8F2241197C0000008000037C +:10FAE00042C90100E29500F8003001005A8FA2419E +:10FAF0003B500000618F004900B00000FF07001E6E +:10FB0000008C0100E295004081320100618F0049C4 +:10FB100000B0000000001B4719800100648F225FC5 +:10FB2000016C00006399004081320100B08A00003E +:10FB300080B000006B8F225C1F7C000020800003DF +:10FB400042C901006B8F2240E36D000000000047B6 +:10FB500061B101004000001062DD0100688FA84023 +:10FB6000813200001B8400881CB000006B8F4005B0 +:10FB700048310000FFFF000794890100718F85CA9A +:10FB8000943000006399185C1F0001000E00000F04 +:10FB90001E8C01007889004081B200003698180060 +:10FBA00080300100D58D0047198000000000004022 +:10FBB00019800100D58D2247197C0000DD95004099 +:10FBC00081320100788FA20880320000D58D00407C +:10FBD00081B20000CB9700400D3001009C01004035 +:10FBE00045990100FFFF000B988801008B002D5004 +:10FBF00017F001007E8F904C16400000000000417D +:10FC000017C00100808F2243E77D00000000004400 +:10FC100045C101000000662017A4010068010040F2 +:10FC2000439901005C012EF280B001003E000040CB +:10FC300080CE0100878F2440813200000000004602 +:10FC400081C00100888F0094E5B10000020062408D +:10FC50007ECD01000000005781C0010000002E1081 +:10FC600048B1010003000040F08D010000000008D1 +:10FC7000F0B1010058010005E0C901000000004496 +:10FC800061B101000000001062B101008E8FA84038 +:10FC9000813200001B8400881CB0000000000005B9 +:10FCA00048B101009A8F2240AF6F00000040000869 +:10FCB00094DC01008898004081320100988F224036 +:10FCC000976C0000E295000800300100D58D0040DF +:10FCD00081B200000000004005B00100D58D004752 +:10FCE000198000009A8F43486131000000500008DD +:10FCF00062DD0100A08F2840053000009B8F224864 +:10FD0000777D0000E2951B0800300100D58D004092 +:10FD100081B20000D58D1B471980000035000040DE +:10FD200047990100010063F384C80100A58FA04337 +:10FD3000856C00000000634085B00100A800004011 +:10FD40004399010037002FF024B00100010063F354 +:10FD500082CC0100B08FA2419E060000D58D2244C6 +:10FD600083700000360000404399010058003D4375 +:10FD7000E7E10100D58D1FF0246C00006399004875 +:10FD800081300100B08A2341836C0000B08A0047B3 +:10FD900081B0000058003D4385E00100000000F8FC +:10FDA00036B00100000000F000B001002800004063 +:10FDB0008398010004980047613101001B8400888A +:10FDC0001CB0000000002D0348B1010008002DF018 +:10FDD00094B00100000000F88EB0010090002DF0FA +:10FDE00014B001000000000548B10100848EA2405B +:10FDF0008F7C0000BE8F22478F7C0000848E0048DD +:10FE0000199000002D90004081B2000036002D5D59 +:10FE100005B4010037002DF380B00100000000F3AD +:10FE20008EB001005C003D4381E00100A8002DF090 +:10FE300094B00100000000F024B001002000001088 +:10FE400086DC01004080000344C90100E394004ABD +:10FE5000F031010036002F5C1F900100CC8FA250C2 +:10FE60008F50000034002040E1B10100D58D0040EA +:10FE700081B200000000634181C00100CF8FA04328 +:10FE8000816C00000000634081B001003700204712 +:10FE9000E6B10100D58D2247803200000400004702 +:10FEA0000CF401000000004F8F840100E48F224712 +:10FEB0000C6C000058003D4381E00100E48F1FF00E +:10FEC000246C00000000005C1F8001000080001016 +:10FED00042C90100DD8F2240E36D000000000045B3 +:10FEE00061B101004000001062DD0100DA8FA8401E +:10FEF000813200001B8400881CB00000DD8F42406E +:10FF000005300000000000449393010000001A5DDA +:10FF100069930100E28F23410D6C0000BF8F000543 +:10FF200048B100006399000548310100B08A0048DB +:10FF300081B00000D58D22408F6C00003698005FA4 +:10FF400081300100D58D004081B20000A200004048 +:10FF500043990100000000F384B00100A6002D4980 +:10FF600019900100020000F280F40100B8002D4059 +:10FF700081B20100000000F280C0010000000040DA +:10FF800082F801001900004081980100F38FA04021 +:10FF9000826C00002C01004081980100F38FA34087 +:10FFA000826C00000000004180B00100F58F204C01 +:10FFB000856C00000000004185C0010086002040E3 +:10FFC000E4B10100A2002042E6B10100D58D00405D +:10FFD00081B20000C597005081300100D58D0040EE +:10FFE00081B200000480000342C90100040022F035 +:10FFF00080300000000000408DB0010055990040A5 +:020000021000EC +:1000000087300100B0002F5C1F900100000060F0FD +:1000100080C001003698005F81300100D58D00401E +:1000200081B200000400004081B20000D58D22465C +:10003000197C0000A000004047990100010062F215 +:1000400096CC0100D58DA640813200003698004A3A +:10005000813001000B98004695300100D58D00409D +:1000600081B20000D58D2249197C00008600004035 +:1000700047990100010062F280CC0100D58DA640B5 +:10008000813200003698004A813001000B98004709 +:1000900095300100D58D004081B20000749500407C +:1000A00081320100D58D005C1F900000D58D00408D +:1000B00081B20000D58D004081B20000BA0000403E +:1000C00047990100010062F280C801001990904038 +:1000D00080320000FFFF624081980100A4000040D0 +:1000E00047990100D58D2240E56D0000D58D004176 +:1000F000E5C10000C597004D81300100D58D00405D +:1001000081B200005C00004047990100040022F029 +:100110009630000000000040E1B1010000800003C3 +:1001200044C901000000004BE0B1010000000040A4 +:100130008DB0010055990040873001008B000040D0 +:1001400047990100299080F396300000000000409C +:10015000E78101000000004719900100D58D005C87 +:100160001F9000003400004045990100010000404C +:10017000F599010000110040E5990100DD9500406E +:10018000813201003E90A20880320000370000401A +:1001900047990100000000F382B0010000006351A4 +:1001A00083D001003400004047990100010063F34F +:1001B00084CC010036909F428032000000006342F0 +:1001C00085B001000000004503F0010000000001BF +:1001D00000C001003890375C613100000000001B56 +:1001E00062B101003990A84B191000000000000016 +:1001F00062B101003B90A84081320000058A17409F +:1002000081B200000080000342C9010090002DF07F +:1002100094B00100AC002DF030B0010035002DF09D +:1002200028B0010058003E43E7E10100010000183A +:10023000F0C901000000004AE0B1010038002000D0 +:10024000E0B101003C00201BE0B101004000204073 +:10025000E1B10100000000402BB001001A980040FD +:100260000D3001000000001816C001004D90A014D0 +:10027000164400000000004117C001000E0000A25B +:1002800044C9010000000018F8B10100B0002D14AD +:10029000F8B1010010500040879801005690224AA2 +:1002A000197C00000030004386C801000030000BBC +:1002B00016C801005690A4408132000000000041A1 +:1002C00017C0010001006E4386980100519800306C +:1002D000813001005A90A041174000000000004109 +:1002E00017C001006190224A197C0000080000A29A +:1002F00044C90100CC002DABF9B10100000000ABF6 +:1003000017C001006090A0F01644000000000041FA +:1003100017C00100000064F082B0010090000040AE +:10032000459901000000604131C00100BC0000405F +:10033000439901006790060C80320000A00020F273 +:10034000E4B1010004000946191000009C010040BE +:1003500045990100FFFF000B988801008B002D508C +:1003600017F001006C90904C164000000000004116 +:1003700017C001006E902243E77D0000000000449A +:1003800045C101000000662017A40100680100407B +:10039000439901005C012EF280B001003E00004054 +:1003A00080CE01007590244081320000000000469C +:1003B00081C0010076900094E5B100000200624027 +:1003C0007ECD01000000005781C0010000002E100A +:1003D00048B1010003000040F08D0100000000085A +:1003E000F0B1010058010005E0C90100000000441F +:1003F00061B101000000001062B101007C90A840D2 +:10040000813200001B8400881CB000000000000541 +:1004100048B1010086902240AF6F00000040000804 +:1004200094DC010088980040813201008190A24054 +:10043000976C000035000040479901008A90004009 +:1004400005B000008690434861310000005000086C +:1004500062DD01008790A8400530000035001B4098 +:1004600047990100010063F384C801008D90A04307 +:10047000856C00000000634085B00100370000403B +:1004800047990100010063F382CC01008B0000401A +:100490004799010000000045E79101003698005F90 +:1004A00081300100D58D004081B20000370000404E +:1004B000479901007F9600F3943001002D90224A65 +:1004C00080320000AB8E004081B200003700004057 +:1004D000479901007F9600F3943001007B8E224AF9 +:1004E00080320000AB8E004081B200003600004038 +:1004F00043990100000000FB12B001000F0000F35F +:1005000090880100040000F30CF40100A58E22067F +:10051000906C00005C003D4313E00100A8002DF04A +:1005200094B0010037002FF024B0010036002A50AB +:10053000E7D101000000634113C00100A790A04370 +:10054000136C000000000040E7B10100E1940010CE +:10055000863001001B8400881CB00000A990420571 +:10056000483100000000004493930100A58E1A5DFD +:100570006993000036002D1086B001005C003D43F9 +:10058000E7E10100A8002DF094B0010035002FF044 +:1005900024B0010001006BFB84C80100B490A043AB +:1005A000856C000035002040E7B1010000000040EC +:1005B00081B20100010063F312C80100B790A043AB +:1005C000136C000000000040E7B101004080000310 +:1005D00044C90100E394004AF03101001B84008803 +:1005E0001CB00000BA9042054831000000000044F1 +:1005F0009393010000001A5D6993010037000040E9 +:1006000047990100110063F382CC0100A98F2241B8 +:100610009E060000350000404399010058003D430C +:10062000E7E10100000000F836B00100B38F00F0F0 +:1006300000B000005E012D0548B10100C59047F2F1 +:100640001230000000993F4213F00100CA90224787 +:10065000E77D00006B841F881CB00000C490004040 +:1006600081B2000000000047E791010000001F4236 +:10067000199001007500004061990100CC90A8B16B +:100680000C3000005C970010943001001B8400883F +:100690001CB000005E012E0548B10100C0A83D4617 +:1006A0000DE001000000004097B00100D69022400C +:1006B000E16D00000400024197400000D39000501B +:1006C00043C10000E290224B803200000000624BE8 +:1006D000129401000900000796E40100000000A741 +:1006E00097C001003000001094C801000080004A4B +:1006F0004499010000000042F1B101005E01004B8D +:10070000F0C901005E010005E0C9010000000044DD +:1007100061B101002000004A62DD0100E090A840C4 +:10072000813200000080001044C901000000005028 +:10073000F1B101000400000996E40100000068A87E +:1007400097C00100D4000005E0C90100000000448A +:1007500061B101000000001062B10100E890A84002 +:10076000813200001B8400881CB0000000993F42C9 +:1007700013F00100EC904740813200003F0000F38D +:100780009688010000000040E7B1010000001F55FD +:1007900061B101000000000662B10100F090A840C4 +:1007A00081320000F590224B803200000000004BA7 +:1007B00062B10100F390A840813200000000009770 +:1007C00013B001000000009697B00100FB902009D3 +:1007D000966C0000FB901F09962400006B84008833 +:1007E0001CB00000F690004081B20000C597005791 +:1007F00081300100C08D000548B100002E0000408E +:1008000043990100019122F380320000C597004214 +:1008100081300100058A004081B200003698005204 +:1008200081300100C08D004219800000C597003A58 +:10083000813001003698005281300100C08D0040A7 +:1008400081B200000000004005B00100DF960040CA +:1008500095300100C08D2240956C00000C91A240A3 +:100860001F7C0000E295004081320100058A0040B3 +:1008700081B200000480000342C90100000000F2C0 +:1008800002B001008A960052953001009196004B0B +:1008900002B00000058A004081B200000A990040C1 +:1008A000953001001891A208803200001891A2161C +:1008B00080320000058A2242197C00000000004BB3 +:1008C00019900100C597003A81300100058A004067 +:1008D00081B20000002300A616B001001B91831E08 +:1008E000803200000008000B16DC01000000000050 +:1008F0002AC001000E980008803001001F91005EA0 +:10090000179000002F98004361310100EF940040E0 +:100910008D300100169800071614010000800010A9 +:1009200042C9010027912240E36D0000000000430E +:1009300061B101004000001062DD01002491A84077 +:10094000813200001B8400881CB00000B797005E55 +:1009500005100100E2950040813201002B9122092F +:10096000803000003698004013300100C58D00052E +:1009700048B100000F97004081320100C08D004057 +:1009800081B200000000004A1F9001003291224312 +:100990003D7C00000000004419900100000000436D +:1009A0003D800100339100421990000014002D4554 +:1009B0001F9001008F91831E803200008F910044B0 +:1009C00019900000D4950040813201004791A2089F +:1009D000803200004791A216803200004391A2426B +:1009E000197C00000082000204DC0100A098004095 +:1009F00047990100E9890041893001004091A241F5 +:100A0000197C0000E295004081320100058A004017 +:100A100081B200008A960015943001009196004B37 +:100A200002B00000058A004081B200000F9700402C +:100A3000813201000000004B19900100C597003A77 +:100A400081300100058A004081B200004A912242B3 +:100A5000197C00000F970040813201004B9100404B +:100A600081B20000DF96004081320100779122417F +:100A7000197C0000C000001598C801007791A00BF8 +:100A8000996C00003000001080C801000080004018 +:100A90004499010000000050F1B101000000000382 +:100AA000F0B101000000004261B10100000000400F +:100AB00062B101005391A800E03100001B8400885E +:100AC0001CB000000000000548B10100C000001586 +:100AD00098C8010030002E0B99D0010000006A5028 +:100AE00099C00100C000620180CC01000C800003AD +:100AF00042C901002D002DF022B001000000004C81 +:100B000080C001000000005C23800100D4003F4150 +:100B1000E7E101000B000011E4F501002F00204780 +:100B2000E7B501006491230B816C00000000004FC9 +:100B3000E59101000000000880B001000000000BFA +:100B400003B001000000001502D001000E98000063 +:100B50002A4001000000004361B101004000001084 +:100B600062DD01006991A840813200001B84008889 +:100B70001CB00000E295000548310100C0000001F2 +:100B800080CE010075912611003000001000000099 +:100B90002AC801000000000880B001000000000128 +:100BA00080C00100C00000409998010000000001D1 +:100BB00098D001000E98004C02300100C0000040A7 +:100BC000039801007C91004081B2000030002F08A2 +:100BD00080B00100C0000015F4C90100C000000190 +:100BE000E4CD0100C0000040039801000E98000011 +:100BF0002A400100819122441F7C0000AC002F405C +:100C000013B0010000000001E0C10100B00000408D +:100C10004799010082910001E0D10000EF9400406B +:100C20008D300100806300A616B001001698000701 +:100C3000161401000080001042C901008A91224070 +:100C4000E36D00000000004361B1010040000010AE +:100C500062DD01008791A840813200001B8400887A +:100C60001CB00000B797005E051001008D912209AD +:100C7000803000003698004081320100C08D0005B0 +:100C800048B100008F91004A1F9000000000000052 +:100C900010B0010024002D1510C0010028002DF017 +:100CA00016B0010022002DF026B0010014002FF232 +:100CB0000CB0010000000001E0D1010000000010B4 +:100CC00032B001000000000B1BB0010004001F1532 +:100CD0001A5000000000004023B001000000000195 +:100CE0002AB001007197004035B000002F0020406D +:100CF000E7B10100D391A2451F7C00002400200B26 +:100D0000E0B1010028002013E0B10100220020061C +:100D1000E4B10100A991225C1F7C00000000005C8E +:100D20001F8001003080001042C90100A9912240BB +:100D3000E36D00000000004761B1010040000010B9 +:100D400062DD0100A591A840813200001B8400886B +:100D50001CB000000000000548B10100008000192F +:100D600042C90100CC912240E36D0000BA912242B9 +:100D7000197C0000379700408132010089950040BE +:100D800081320100C791224B8032000000000043F5 +:100D900061B101004000001062DD0100B091A84087 +:100DA000813200001B8400881CB00000B6912241F3 +:100DB000197C0000F895004011300100B791000542 +:100DC00048B10000E295004081320100B99122094A +:100DD0008030000036980040813201006F8400406E +:100DE00005B0000037970040813201008595004032 +:100DF000813201000000004361B101004000001099 +:100E000062DD0100BD91A840813200001B84008892 +:100E10001CB00000C3912241197C0000F8950040ED +:100E200011300100C491000548B10000E295004076 +:100E300081320100C69122098030000036980040BE +:100E4000813201006F84004005B0000000000043C3 +:100E500061B101004000001062DD0100C891A840AE +:100E6000813200001B8400881CB0000000000005D7 +:100E700048B10100CF912241197C0000F895004053 +:100E800011300100D091000548B10000E29500400A +:100E900081320100D2912209803000003698004052 +:100EA00013300100C58D004005B00000008000191E +:100EB00042C90100DA912240E36D000000000043C6 +:100EC00061B101004000001062DD0100D691A84030 +:100ED000813200001B8400881CB000000000000567 +:100EE00048B101000000004005B00100DE91224140 +:100EF000197C0000F895004011300100DF910005D9 +:100F000048B10000E29500408132010008002D0A3E +:100F100084B00100000000F082B001001400204005 +:100F2000E1B10100E491031E80320000E59100412F +:100F300087B0000021000040879801000097004022 +:100F4000813201000000005C1F900100E99122093C +:100F5000803000003698004013300100EC912244AC +:100F6000197C00003698004F8130010000000044D9 +:100F700019800100C08DA24A1F7C0000C58D004071 +:100F800081B20000BA002040E5B10100F2919C1747 +:100F900080320000CC0000404399010013990040CA +:100FA00081320100A398004013300100C0000040CE +:100FB00043990100C4002DF082B00100EE9800F0CA +:100FC00084300100E295004081320100C58D220984 +:100FD000803000003698004013300100C58D00407D +:100FE00081B200002E00004043990100FE91224092 +:100FF000E76D000032000040439901000692A240D4 +:10100000E56D0000CC960040813201002400200BE9 +:10101000E0B1010028002013E0B101002200200609 +:10102000E4B101001400200AE0B10100C58D2209DD +:10103000803000003698004013300100C58D00401C +:1010400081B20000CC9600408132010085960040BC +:101050008132010014922241197C00000000000B33 +:1010600099B0010004001F1598500000149220014F +:10107000986C00007000000348C9010000002E4673 +:101080001F90010000000050F1B1010000000003BA +:10109000F0B101000000004261B10100A00000A415 +:1010A00062DD01001192A800E0310000000000059F +:1010B00048B10100AC002F0010B001000000000199 +:1010C000E0C1010014002F1510C001000000000A4B +:1010D00080B001000000600180D0010000000047E6 +:1010E000199001009691220980320000369800097B +:1010F000803001009691004013B000000080000392 +:1011000042C90100000000F082B00100130000405D +:10111000879801000000004C43C10100009700F0D7 +:1011200084300100C08D005C1F9000002C00204026 +:10113000E7B101002D002040E7B10100C08D004261 +:1011400019800000F2960040813201000B9800489F +:10115000953001000000004561B101004000001021 +:1011600062DD01002992A840133000001B84008832 +:101170001CB000002F92000548B100002E920040E4 +:1011800013B000000000000012B001000800004091 +:101190004399010014002DF082B00100040022F0F8 +:1011A0008430000013000040879801000097004041 +:1011B000813201000000005C1F900100479200098D +:1011C00000B00000C08D8742191000008B002F472F +:1011D00019800100C08D0040E79100002F00004001 +:1011E0004799010045922247E77D0000669500403F +:1011F000E731010045922200803200004092A24077 +:101200001F7C0000E29500408132010045920040C1 +:1012100081B20000300000404399010032002DF2FD +:1012200094B001008A9600F2023001009196004BC2 +:1012300002B000000000000548B1010046920040E5 +:1012400001B000000000004005B001004C922200F7 +:10125000803200004B92A242197C0000DF960040D1 +:10126000813201004C92004081B200000F97004093 +:1012700081320100D892225C1F7C00000000005CDB +:101280001F8001000080001042C9010054922240DA +:10129000E36D00000000004561B101004000001056 +:1012A00062DD01005192A840813200001B84008859 +:1012B0001CB00000D892000548B10000D495004051 +:1012C000813201005B92A208803200005B92A2167C +:1012D00080320000C597004D81300100008200027D +:1012E00004DC0100058A004081B200007400004067 +:1012F00043990100000000F882B00100000000F0F6 +:1013000084B001000000004196B0010069922242C1 +:10131000961400000080001044C901006400684079 +:101320009798010000000041F0B101000000004268 +:10133000F0B1010070000005E0C9010000000045A7 +:1013400061B101002000001062DD01006692A8403A +:10135000813200000000005C1F9001000000004589 +:1013600061B101004000001062DD01006A92A85CDA +:101370001F0000001B8400881CB000005E012D05CA +:1013800048B101006E9247F21230000000993F42CE +:1013900013F0010073922247E77D00006B841F88E1 +:1013A0001CB000006D92004081B2000000000047B8 +:1013B000E791010004001F0996E40100008000107D +:1013C00044C9010000000044F1B10100000068A818 +:1013D00097C0010000000003E0B10100008000039D +:1013E000449901000000004461B1010000000010B8 +:1013F00062B101007B92A840E13100001B840088AB +:101400001CB0000000993F4213F001007F92470595 +:10141000483100003F0000F39688010000000040C2 +:10142000E7B1010000001F4081B201008792224B0A +:10143000803200000000005561B101000000004B47 +:1014400062B101008592A8408132000000000007CF +:1014500016B001000062000B16DC0100669500402A +:10146000813201009F922200803200001597005FB8 +:101470000110010089922240956C0000008000104C +:1014800044C9010000000050F1B101000000000358 +:10149000F0B101000000004261B101000000001045 +:1014A00062B101009192A800E03100001B84008825 +:1014B0001CB000000000000548B1010004800003DA +:1014C00042C90100000000F202B001008A960052F9 +:1014D00095300100E295004081320100899222415D +:1014E000975000000C80000342C90100000000F08A +:1014F00000B001000000005C018001009196004BEB +:1015000002B000008992000548B100001698004022 +:10151000033001001780000344C9010000F0000CF3 +:10152000968801000000634C97F0010010800003D2 +:1015300044C90100000000ABE1B10100B797005EB3 +:1015400005100100030000071AF40100070000075E +:101550001688010000B5000D46C90100A99230406F +:10156000813200000000000BE681010000B7000D91 +:1015700046C901000000000BE68101001000100FB9 +:1015800094F40100E999005F950401006B96004016 +:1015900081320100B3922250FD7F0000B19243409E +:1015A0008132000000001B4131D3010000002E05F4 +:1015B00048B1010000000040E1B10100000000401E +:1015C0000FB00100CD95004181300100058A004037 +:1015D00081B20000D495004081320100C592A2087A +:1015E00080320000C592A216803200000082000204 +:1015F00004DC01000000004503F0010000000001D0 +:1016000000C00100BE92375C613100000000001B89 +:1016100062B10100C292284081320000BF920040B6 +:1016200081B200000000000062B10100C292A84037 +:1016300081320000058A174081B200007400224008 +:10164000F1B1010000000040E1B101000B98004A37 +:1016500095300100F296005C1F1001005B92004083 +:1016600081B200002F00004047990100D692224726 +:10167000E77D000066950040E7310100D692220028 +:1016800080320000D192A2401F7C0000E295004011 +:1016900081320100D692004081B20000300000404B +:1016A0004399010032002DF294B001008A9600F2B5 +:1016B000023001009196004B02B0000000000005CE +:1016C00048B101000B98004895300100F296005C8B +:1016D0001F100100DB928742191000008B002F477A +:1016E0001980010000000040E79101003698004297 +:1016F00081300100C08D004081B20000F2960040B0 +:1017000081320100C08D005C1F900000BA002040B3 +:10171000E5B10100A398004081320100C000004003 +:1017200043990100C4002DF082B00100EE9800F052 +:1017300084300100E2950040813201003698004576 +:1017400081300100C08D2242197C0000C597003A0B +:1017500081300100C08D004081B2000004000040D3 +:1017600081B20000D495004081320100F092A208BD +:1017700080320000F092A21680320000C597004728 +:10178000803001000082000204DC0100058A004074 +:1017900081B200001080000344C9010000E100A6EE +:1017A00084B0010000000040F1B1010000000040E1 +:1017B000F1B101000000600784940100B797005E5A +:1017C00005100100C08D004081B200008A00004079 +:1017D00047990100E2950041E7410100C58D0040B5 +:1017E00081B20000CC960040813201008596004015 +:1017F00081320100000000012CB001000000001542 +:1018000010B001000000000010C0010004001F0A19 +:101810002C5000000000001032B001000700000B47 +:10182000968801000C932647972400000000004191 +:1018300097C001000C93234B0C6C00004998004B9F +:10184000043001000000005033C00100000000021D +:1018500010C001000000000216C0010000000006D8 +:1018600004B001004998004B045001000D93004062 +:1018700081B2000049980006043001001393A24889 +:101880001F7C0000119384481F100000AC00004032 +:10189000479901001393000AE0C100000000000A0C +:1018A00002B00100EF9400018C3001000000004301 +:1018B00061B101004000001062DD01001493A840F6 +:1018C000813200001B8400881CB00000000000056D +:1018D00048B101000000000210C00100219322065F +:1018E000145000003A9700451F0001000093225C4D +:1018F0001F7C00000000004761B1010040000010A3 +:1019000062DD01001D93A85C1F0000001B8400889D +:101910001CB000000093000548B100000000000B5F +:101920001BB0010008002D4085B00100000000F050 +:1019300082B001000000004005B0010000970041A6 +:10194000873001000000004561B101004000001037 +:1019500062DD01002793A840813200001B840088CB +:101960001CB000000000000548B101002D932209C1 +:10197000803000003698004013300100319322443B +:10198000197C00003698004F813001003193A24746 +:101990001F7C00000000004419800100FF070008C0 +:1019A000008C01003F93224A1F7C00003793A2164F +:1019B00002300000E2950040813201002F002040FB +:1019C000E7B10100C08D004081B200002D002D085C +:1019D0002AB001003B932242197C00000F9700407F +:1019E000813201003C93004081B20000DF9600404C +:1019F0008132010030002E002AD0010032002A1569 +:101A0000E4B10100C08D0016E4B10000529322162B +:101A100002300000000000082AB001000A990040CE +:101A2000953001004493A240116C00005393224072 +:101A30002D6C0000AC00004047990100B0002B0164 +:101A4000E0C10100002B00A616B00100000000015B +:101A5000E0D101000E980008803001004B93005E39 +:101A6000179000002F9800436131010000000043EF +:101A700061B101004000001062DD01004C93A840FC +:101A8000813200001B8400881CB0000000000005AB +:101A900048B101001698000716140100B797005EC0 +:101AA00005100100E2950040813201002F00204026 +:101AB000E7B10100C58D004081B200000000000BBD +:101AC0001BB0010004001F151A500000609320167F +:101AD0001A6C00007000000348C901000000225089 +:101AE000F1B1010000000003F0B1010000000000AE +:101AF000E0B101000000004261B10100A00000A4BB +:101B000062DD01005D93A8461F1000000000000583 +:101B100048B101000000000010B0010000000015F5 +:101B200010C001000000000A2AB001000000000AF5 +:101B30002CD00100AC002F4023B0010067938445F6 +:101B40001F1000006893000AE0C100000000000AB6 +:101B500002B001007197004035B00000008000190C +:101B600042C9010070932240E36D00000000004371 +:101B700061B101004000001062DD01006C93A840DB +:101B8000813200001B8400881CB0000000000005AA +:101B900048B101008093A2021A50000081932240B4 +:101BA0002D6C00000080001044C9010000000050AE +:101BB000F1B1010000000003F0B10100FF070008CF +:101BC000E08D01000000004261B101000000001042 +:101BD00062B101007793A840813200001B84008825 +:101BE0001CB000000000000548B101002F00204794 +:101BF000E7B501000C80000342C90100100000F0AD +:101C000010C80100F00700401B9801008193005CA0 +:101C1000118000000000000210C00100F895004093 +:101C20001F0001000000000548B101008593230D4D +:101C30002C6C0000000000401F9001008E93224693 +:101C40001F7C0000000000461F8001007080000320 +:101C500042C901008E932240E36D00000000004263 +:101C600061B101004000001062DD01008A93A840CC +:101C7000813200001B8400881CB0000000000005B9 +:101C800048B1010008002D4085B00100000000F0BF +:101C900082B001000000004005B001000097004143 +:101CA000873001000000004561B1010040000010D4 +:101CB00062DD01009393A840813200001B840088FC +:101CC0001CB000000000000548B1010099932209F2 +:101CD0008030000036980040133001009D9322446C +:101CE000197C00003698004F813001009D93A24777 +:101CF0001F7C00000000004419800100FF0700085D +:101D0000008C0100B293224A1F7C0000A393A2160C +:101D100002300000E2950040813201002F00204097 +:101D2000E7B10100C08D004081B200002D002D08F8 +:101D30002AB00100AE932242197C0000A793A2F3BF +:101D400084300000000000A585B0010000000041C3 +:101D500085D00100D4003E4185E00100AB932240D4 +:101D60001F7C00000000005A119001000B000008C9 +:101D7000E4F501000F97004081320100AF9300406D +:101D800081B20000DF9600408132010030002E0059 +:101D90002AD0010032002A15E4B10100C08D0016DE +:101DA000E4B10000B593A21602300000E2950040B5 +:101DB000813201000494004081B200002D002D0802 +:101DC0002AB00100C39322471F7C0000BF93224228 +:101DD000197C0000BA93A2F384300000000000A533 +:101DE00085B001000000004185D00100D4003E41D3 +:101DF00085E00100BE9322401F7C00000000005AD5 +:101E0000119001000B000008E4F5010058012D00BD +:101E10002AD0010060012DF010B00100000000F098 +:101E20002CB001004791004081B200000A990041A6 +:101E300095300100CB93A20880320000CB93A2160C +:101E4000803200000000004197B00100C993230DCB +:101E5000026C00000000004197C001009196004B09 +:101E600002B000000494000548B10000AC002F014E +:101E700014B00100B0002B01E0C10100002B00A64E +:101E800016B0010000000001E0D10100DB93230D3A +:101E9000026C00000080001044C9010000000050E6 +:101EA000F1B1010000000003F0B1010000000042A8 +:101EB00061B101000000001062B10100D493A800DC +:101EC000E03100001B8400881CB000000000000509 +:101ED00048B101000C80000342C90100100000F06D +:101EE00022C801000000005C238001000000000106 +:101EF00084B00100DE93230D026C00000000000D91 +:101F000002B001000000000880B00100E39322400D +:101F10001B6C00000E98000184500100EB932240DE +:101F2000856C00000000000180C0010010800010DE +:101F300046C901000000004F43810100000000423B +:101F4000F0B1010020000040F0C9010000000016BF +:101F5000F0B101000000004361B10100A00000A148 +:101F600062DD0100E993A811E0310000FA93005E00 +:101F700017900000EE93230D026C00000000000D8E +:101F800002B001000000000184D00100F393224060 +:101F90001B6C00002F98004361310100FA9322402E +:101FA000856C00000000000112C0010010800010CC +:101FB00046C901000000004F4381010000000042BB +:101FC000F0B1010000000009F0B1010000000018AC +:101FD000F0B10100A00000A162DD0100F893A8119A +:101FE000E03100000000004361B10100400000103A +:101FF00062DD0100FB93A80A023000001B84008808 +:102000001CB00000E2950005483101000294230D48 +:10201000026C0000FF070011008C0100E2950040F7 +:10202000813201001698000716140100B797005E70 +:10203000051001002F002040E7B10100C58D0040D0 +:1020400081B200000080000342C90100000000F8D6 +:1020500082B00100000000F88CB00100000000F028 +:102060008EB00100C996004013300100000000400E +:1020700085B001000097004187300100859600403F +:10208000813201000080001042C9010015942240F5 +:10209000E36D00000000004561B101004000001048 +:1020A00062DD01001194A840813200001B84008889 +:1020B0001CB000000000000548B10100179422097F +:1020C0008030000036980040133001000000000B03 +:1020D0001BB00100000000151AD001001E94A2419F +:1020E000197C00000A99004095300100000000169C +:1020F00080B201002794270880320000449300003A +:102100002AC000000A990041953001000000001625 +:1021100080B201002294270880320000CB93000097 +:102120002AC000000000004197B001002594230D53 +:10213000026C00000000004197C001009196004B26 +:1021400002B000000000000548B10100C08D22422D +:10215000197C0000C597003A81300100C08D004015 +:1021600081B200002B94004A1F9000000A960000E4 +:10217000103001000000001510C001000000001028 +:1021800032B001000700000B968801003994264701 +:10219000972400000000004197C001003994234BB0 +:1021A0000C6C00004998004B043001000000005006 +:1021B00033C001000000000210C001000000000256 +:1021C00016C001000000000604B001004998004B51 +:1021D000045001003A94004081B200004998000682 +:1021E000043001003F94A2441F7C00000000000B5B +:1021F0001BB001000000000A2CD001000000000A02 +:1022000002B00100EF9400018C3001000080001941 +:1022100042C9010046942240E36D000000000043E3 +:1022200061B101004000001062DD01004294A8404D +:10223000813200001B8400881CB0000000000005F3 +:1022400048B101000000000210C001004F942206B6 +:10225000145000003A9700451F0001002D94225CA5 +:102260001F7C00000000004761B101004000001029 +:1022700062DD01004B94A85C1F0000001B840088F5 +:102280001CB000002D94000548B1000008002D404E +:1022900085B00100000000F082B0010000000040A5 +:1022A00005B00100009700418730010000000045A3 +:1022B00061B101004000001062DD01005494A840AB +:1022C000813200001B8400881CB000000000000563 +:1022D00048B101005A94220980300000369800402D +:1022E000133001005D942244197C00003698004FA1 +:1022F000813001000000004419800100FF07000840 +:10230000008C01006B94224A1F7C00006394A2168B +:1023100002300000E2950040813201002F00204091 +:10232000E7B10100C08D004081B200002D002D08F2 +:102330002AB0010067942242197C00000F970040E8 +:10234000813201006894004081B20000DF960040B5 +:102350008132010030002E002AD0010032002A15FF +:10236000E4B10100C08D0016E4B100004093A21654 +:1023700002300000E2950040813201002F00204031 +:10238000E7B10100C58D004081B200000A96004A05 +:102390001F1001005593001032B000008A00204049 +:1023A000E7B101007594A241197C0000E29500405C +:1023B000813201007894004081B200008A960015B5 +:1023C000943001009196004B02B00000000000051F +:1023D00048B101007A942242197C0000C597003A66 +:1023E000813001003698004581300100C08D0040E9 +:1023F00081B20000069200451F900000CC9600407C +:102400008132010085960040813201005593000120 +:102410002CB00000D4950040813201008D94A208B8 +:10242000803200008D94A2168032000000820002EB +:1024300004DC01000000004503F001000000000181 +:1024400000C001008694375C613100000000001B71 +:1024500062B101008A9428408132000087940040D4 +:1024600081B200000000000062B101008A94A8401F +:1024700081320000058A174081B20000580120080F +:10248000E0B1010060012016E0B10100CC960047E8 +:102490001F10010085960040813201005593000114 +:1024A0002CB00000D49500471F100100A094A20892 +:1024B00080320000A094A216803200009C94A242B8 +:1024C000197C00000082000204DC0100A09800409A +:1024D00047990100E9890041893001008A96001579 +:1024E000943001009196004B02B00000058A004034 +:1024F00081B200000F970040813201000000004BC4 +:1025000019900100C597003A81300100058A00400A +:1025100081B2000058012008E0B1010060012016DE +:10252000E0B101000A9600103230010055930040DE +:1025300013B00000D495004081320100B194A2088C +:1025400080320000B194A2168032000000820002A6 +:1025500004DC01000000004503F001000000000160 +:1025600000C00100AA94375C613100000000001B2C +:1025700062B10100AE94284081320000AB9400406B +:1025800081B200000000000062B10100AE94A840DA +:1025900081320000058A174081B2000000800003EC +:1025A00042C90100000000F882B00100000000F8FC +:1025B0008CB00100000000F08EB00100C996004010 +:1025C000133001000000004085B001000097004179 +:1025D00087300100859600408132010000800010A4 +:1025E00042C90100C0942240E36D00000000004594 +:1025F00061B101004000001062DD0100BC94A84000 +:10260000813200001B8400881CB00000000000051F +:1026100048B10100479122098030000036980040FF +:10262000133001004791004081B2000014002D4595 +:102630001F9001008F91004419900000C894A2419E +:10264000197C00000000004A1F900100FA9200402F +:1026500081B20000CC96004A1F1001008596004010 +:1026600081320100559300012CB000000A96004011 +:10267000813201005593001032B0000006920045EF +:102680001F9000000000004137C30100000000411E +:1026900033C301003600000102CC01000000D2402B +:1026A00081B20000D49485178032000000009F485A +:1026B00003D00000D6949C178032000000009F4C8D +:1026C00003D000000000800134C3010002002D117E +:1026D00010C10000DB94004043C10000DB940050B7 +:1026E00043C10000200000A142C90100DF94224044 +:1026F000E56D00000400A240E57D00000000004000 +:1027000023B00100000080491F9001000000A24199 +:1027100023D00000DB94005043D100004080000330 +:1027200044C901000000004AF0B10100000000406F +:10273000F1B1010000000012F0B10100E695004186 +:10274000E13101000080004344C901001000004055 +:10275000F199010000000048F0B1010000000049BB +:10276000F0B1010040000003E0C901000000004595 +:1027700061B101000000004362B101000000A84007 +:1027800081B20000EC94004081B20000BA00204009 +:10279000E5B10100B0002F018CD00100000000461F +:1027A000E0C10100AC002F4013B00100CC002D01AE +:1027B000E0C10100F6949C1780320000139900409C +:1027C00081320100F8942247197C00000000005F6C +:1027D00013900100A398004719100100C0002D4478 +:1027E0001F900100C4002DF082B00100EE9800F0AF +:1027F00084B0000090002D0548B101000D95A24B5A +:102800001F7C00006095A24C1F7C00000D951F1CD2 +:10281000E06D00001095A20180320000A8002D4656 +:102820008FB0010006951F1CE06D0000B400004051 +:1028300043990100089522F03A6C00005D951FF065 +:102840003A6C00000000A24080B200000000804FFF +:102850008FB001008A000040439901005E9520423C +:10286000E76D00000C952240803200000000805986 +:102870008FB00100000080588FB001000F952240FA +:10288000803200000000805C8FB001000000805B9F +:102890008FB00100AC00004043990100B0002DF062 +:1028A00084B001001495A242246C00001D9523F011 +:1028B000026C00001A95A2F0803200005F95A242DF +:1028C000246C00005F95A241036C00001995A240A2 +:1028D00080320000000080518FB001000000805263 +:1028E0008FB001005F951F12845000005F95A0011A +:1028F000846C00000D95004081B200008B00004008 +:10290000439901004895A246E77D0000140000406D +:10291000439901003A9522F0143000002695200AD0 +:10292000026C00003795031E803200002595A240FE +:1029300080320000000080448FB001000000804918 +:102940008FB001002B95220A026C00002E95A24147 +:10295000197C00002A95A2408032000000008055BA +:102960008FB00100000080568FB001002D95A2406D +:1029700080320000000080438FB0010000008048DA +:102980008FB001000000000182B001000000000AC9 +:1029900082D0010034952091836C00003395A240D1 +:1029A00080320000260080408F9801002700804080 +:1029B0008F9801003695A240803200001F008040B1 +:1029C0008F980100200080408F9801003995A24027 +:1029D00080320000220080408F9801002300804058 +:1029E0008F98010088002D448FB001004395A241CB +:1029F000197C00004095A2433D7C00004095A2F266 +:102A0000026C00000000A24080B20000000080497B +:102A10008FB001004295A240803200000000804348 +:102A20008FB00100000080488FB001004095A09158 +:102A3000036C00003E9522433D7C00004795A24078 +:102A400080320000280080408F98010029008040DB +:102A50008F98010014000040439901005195A2F0A5 +:102A60001430000088002D448FB001004E95A2F272 +:102A7000026C00000000A24080B20000000080490B +:102A80008FB0010040952241197C00003E952091B5 +:102A9000036C00004095004081B200005595200A6B +:102AA000026C00005495A240803200000000804477 +:102AB0008FB00100000080498FB001005A95220AB2 +:102AC000026C00002E95A241197C00005995A2408D +:102AD00080320000000080558FB001000000805659 +:102AE0008FB001005C95A24080320000000080435E +:102AF0008FB00100000080488FB001006295004354 +:102B000095B000006295004195B0000062950042CA +:102B100095B000006295004495B000006295004CAD +:102B200095B000000B980040813201006595A240ED +:102B3000803200000000804B8FB001000000804C0C +:102B40008FB001002D000040439901002E002FF3AB +:102B500084B001006A95A2F3963000000000804026 +:102B600001B001002D002A41E7D10100D4003D4110 +:102B700085E001000B0000F200E401007095225A8C +:102B8000017C0000000000401F9001007195005A78 +:102B900001800000000000401F8001000000634130 +:102BA00085C001000000A0A5856C01000000E34085 +:102BB00085B001000C80000342C9010012000040F2 +:102BC00087980100559900F08CB000007E95224056 +:102BD0000F6C000000002F0548B101007B95A24B4F +:102BE000197C00007C9522F0186C00000000604BFE +:102BF0001990010048960007103001006F840040D2 +:102C000005B000008095225A1F7C0000CD95004041 +:102C1000813001006F84004005B0000000002F05E6 +:102C200048B101000000604B199001004896000770 +:102C3000103001006F84004005B0000000002F0537 +:102C400048B101000000604B199001004896000750 +:102C5000103001000000804005B00100899533402C +:102C6000813200008C95A1AD952000009A9513400B +:102C700081B200000000134A5A8301003000394538 +:102C800095E001001F00000F5ED801000000005A0F +:102C90005F9001000000004045B00100000000040A +:102CA00048B00100000000054AB001000000000C1F +:102CB00058B00100000000074EB001001886004027 +:102CC0005D9801000000005861B101000000004A59 +:102CD00062B101000000A84197B000009795004044 +:102CE00081B200000000804097B001009B9544072E +:102CF00096300000FFFF004B8489010000001CC2D9 +:102D000024B00100A595A245257C00009F953120A7 +:102D100085300000A6952212487F000067981112A6 +:102D2000480301001000001296E401000000004B6F +:102D30001E9401000000805A1F900100A5953140AB +:102D400081320000000000B424B00100A6952212D8 +:102D5000487F0000679800408132010000002F0585 +:102D600048B10100B3950BF084300000000011124F +:102D700048830100B0952250857000005E0100403C +:102D800043990100679700F296300100E99900121B +:102D9000943001000000005A1F9001001000001242 +:102DA00096E401000000804B1E94010010000042D8 +:102DB00010F4010000B73F4311F0010007000008C4 +:102DC0008A880100B69530A10C300000B9952245E3 +:102DD000E67D0000A695104081B2000000002A4563 +:102DE000E69101000000101248830100000011402C +:102DF00081B201000000604B858001005E0100404F +:102E000043990100679700F296300100008000109E +:102E100044C90100D8000040819801002E002D0512 +:102E200048B10100C4952240E76D000080000040D9 +:102E300080C8010000000040F0B101000900000856 +:102E400086E40100000068A787C00100000000447C +:102E500061B101000000001062B10100C895A80531 +:102E6000E03100001000001296E401000014004B55 +:102E700096DC01000000804B1E9401001000000F42 +:102E800084F401001F00004284880100D195224093 +:102E900080320000D295004268B10000000000427C +:102EA0006AB10100D295315A1F0000000000914222 +:102EB00048930100D4953540813200006D000040F8 +:102EC00061990100DA9528B12C300000D595224D8A +:102ED000757D0000000000402DB00100000095400D +:102EE00011B001006D00004061990100DA95A8B1B0 +:102EF000103000000000954081B201007F000040CA +:102F000061990100E19528B110300000DD959FBA6C +:102F1000803200000000804011B0010000008024D9 +:102F2000118401000000005F61B101000010000089 +:102F300062DD01000000A84081B20000E39500407E +:102F400081B20000AC94004047990100E7953240FF +:102F500081320000ED9522F896300000000000F864 +:102F600090B00100000000F092B001000100004BA1 +:102F7000F0CD010020009248E0C901006C00004043 +:102F800061990100F19528B192300000ED95224C35 +:102F9000757D00000400124091B000006C000040FC +:102FA00061990100F195A8B190300000FF00004840 +:102FB000968801000000004B90D001000100004BFA +:102FC000F0CD010020000048F0C901000000924946 +:102FD000E0B101000C002D1048B10100FF0700080E +:102FE000828C0100FF0700F0008C01000000A2416C +:102FF00000EC0000FE95221A006C0000E295000033 +:10300000343001000000005049C10100FA95A2418E +:10301000235000000000804081B201000C002D1000 +:1030200048B10100FF070015828C0100FF0700F086 +:10303000008C01000000A24100EC00000796220D68 +:10304000006C0000E29500001A3001000000005002 +:1030500049C101000396A2412350000000008040B6 +:1030600081B201000C96831E8032000000000044F3 +:103070001990010024002D012CB0010028002DF032 +:1030800016B0010022002DF026B0010014002FF22E +:103090000CB0010000008040E1B1010002002D11E0 +:1030A00010C100001596004043C100001596005065 +:1030B00043C10000200000A142C901001A9622402D +:1030C000F56D00000000004243D101000400A24061 +:1030D000E57D00000000004023B0010000008049B1 +:1030E0001F9001001D9622111E7C00001F96A0F06B +:1030F000164000001F96004117C000001F96A0F464 +:10310000164000000000004117C001000000A2416D +:1031100023D000001596005243D1000000B5000DE9 +:1031200042C9010022963047170400002596A20BE1 +:10313000E67D00000000904281B0010000B7000D64 +:1031400046C901002996A20BE67D00000000000B95 +:10315000E69101000000904181B0010000001040A4 +:1031600081B201002A96400796300000F399004092 +:10317000813201003496A245957C000001973F41C1 +:1031800095E00100000000F396B001000000004E41 +:10319000E6B1010040973E4097E001000000004E7C +:1031A000E6B1010040973E409DE001004796003B9C +:1031B000E7B1000034963040813200003E96A20B09 +:1031C000E67D000000B5000D46C901003A96A20B4D +:1031D000E67D00000000104081B20100000098422E +:1031E00081B0010000B7000D46C901000000000BCE +:1031F000E69101000000104081B2010000009841FA +:1032000081B00100040021A2952000000000104AB6 +:103210004483010000973E4195E001000000004E0C +:10322000F6B101000000004EE6B1010040973E40BB +:103230009DE001000000003BE7B101000000004AF2 +:1032400090B10100FFFF0007928901000000984043 +:1032500081B001000300000886F4010000B70043BC +:1032600046C9010007000008828801004B9640080B +:1032700096300000F39900408132010057962245B4 +:10328000957C00005396225A1F7C00001000000F0E +:1032900096F401005096315F970400000000114B36 +:1032A000489301000000004B6AB101005396304082 +:1032B0008132000000000041E68101000000104062 +:1032C00081B201000000984081B2010000973F41A7 +:1032D00095E00100000000F396B0010040973D40EA +:1032E00097E00100000063F388B001005F96A23B05 +:1032F000896C00000000004A90B10100010000A6A6 +:1033000092B101006096184A4493000000001840F2 +:1033100081B201003000394597E001006596225ADC +:103320001F7C00001F04000F98D801000000004C13 +:103330005E940100679600054AB000001F0400A7D4 +:103340005E840100000000404BB001000000005806 +:1033500061B101000000004B62B101000000A84013 +:1033600081B200006896004081B200006B96400771 +:1033700096300000F3990040813201006F9622459B +:10338000957C00000000984081B20100F199004A4C +:103390004413010000973F4195E00100000000F355 +:1033A00096B0010040973D4097E00100000063F3B4 +:1033B00088B001003000384597E001000000005F50 +:1033C0000F9001000000005861B101000000004BA7 +:1033D00062B101007796A840813200007096A23B4E +:1033E000896C0000300038459DE0010000009840E5 +:1033F00081B20100E9990012943001004896005A08 +:103400001F0001000000805A1F9001001100004AB7 +:10341000E6C9010034002F4F95840100000000F33D +:1034200096B001000100634B84C801000000A04376 +:10343000856C01000000E34085B0010030002D44A0 +:103440001F90010032002DF22AB00100040022F288 +:103450000230000066950010323001003200A040BA +:10346000E5B101000000004097B00100F007004006 +:10347000999801000000004A02C0010000000050BD +:1034800003D001000000004197C001000000A34CE0 +:1034900002D000008E96004081B20000000000A81B +:1034A00036B001009E9622410350000000800010BB +:1034B00044C9010000000050F1B101007000000398 +:1034C000F0C901000000004261B1010000000010DD +:1034D00062B101009796A800E03100001B840088CB +:1034E0001CB00000E2950040813201007C800003A6 +:1034F00042C90100000000F000B001009296005C9B +:1035000001800000E2950040813201000000001BB4 +:1035100010B1000068012D0682B00100000000F229 +:1035200082C001000080000346C90100DD95004013 +:1035300081320100C5962240116C0000000068082D +:1035400038960100F007004182CC0100A396AA4101 +:103550003B400000000000F810B001000000005CDB +:10356000118001000100001D04CC0100C496264614 +:10357000233000000800000312C80100640120F09D +:10358000E0B10100C3962241055000002000000375 +:1035900048C901000C0000F886C801000000224460 +:1035A000F1B1010000000043F0B10100000000098A +:1035B000E0B101000000004461B10100A00000A4DE +:1035C00062DD0100B596A8461F100000C296224198 +:1035D00005500000C096A24123500000000000A149 +:1035E0001AB001000000004461B101004000001069 +:1035F00062DD0100BB96A846233000001B840088D2 +:103600001CB000001000000348C901000000000DBC +:1036100042B101000000004413C00100B096005008 +:1036200049C100000000000548B10100048000030A +:103630001AC801000000804081B20100C4962240F7 +:103640003B6C0000000000F800B00100E295005C57 +:1036500001000100C59600413BD0000000008D47ED +:1036600080320100B0002F5F13B001000000E0F0D5 +:103670008CC001000080000342C90100000000F876 +:1036800094B00100000000F88CB00100D1968CF8D5 +:103690008E3000000000004419900100040022F860 +:1036A00014300000000000F816B00100000000F81F +:1036B00026B0010008002EF80CB001000C002A4AC8 +:1036C000E0B1010028000000E0C901001000201B4B +:1036D000E0B10100DE96200A0C6C0000000000F84A +:1036E00094B00100000000F896B00100200020F026 +:1036F000E4B101001800204AE0B101001C00204B99 +:10370000E0B10100C996004013B000002C002D422A +:10371000199001002E002FF382B00100000000F389 +:1037200096B00100E496A2A5976C000000008041CD +:1037300095B00100E796A240976C000000000040A1 +:1037400083B001002D002040E7B10100000063417B +:1037500097C00100D4003E4183E001000000004119 +:1037600083C00100EC96A0A5836C0000000000401F +:1037700083B001002C002041E6B10100F196224007 +:103780001F7C00000004000098DC01000B00004CCE +:10379000E4F50100000080401F8001000B00800064 +:1037A000E4F50100E6950040813201000480000349 +:1037B00044C9010000000040F1B1010000000040D8 +:1037C000F1B101000000604187B0010000800010ED +:1037D00044C9010000000050F1B1010000000048A0 +:1037E000F0B1010000000049F0B101000000000349 +:1037F000E0B101000000004561B1010020000010AF +:1038000062DD01000000A85D05900000FD9600400B +:1038100081B20000E6950040813201000080000383 +:1038200044C9010000000041F0B101000000004265 +:10383000F0B1010000000040F1B1010000000043C0 +:10384000F0B101000080001044C9010000000050E8 +:10385000F1B1010000000048F0B101000000004992 +:10386000F0B1010000000003E0B1010000000045DC +:1038700061B101002000001062DD01000000A85DC0 +:10388000059000000C97004081B200002D00004020 +:10389000439901002E002FF384B00100010063F36F +:1038A00096C8010014979F4185500000010000A5B3 +:1038B00085CC01002D00A042E6B101005E012D0083 +:1038C00080B001001997524381600000020000F2AD +:1038D00082F401001A970041809400000000005F0C +:1038E000819001000000005E61B101000000004015 +:1038F00062B101000000A84095B000001B979EBB7C +:10390000803200002097A2401F7C0000E29500401A +:1039100081B200000000804195B001000400001554 +:1039200042C90100000000542BC00100000000FC4F +:1039300024B00100000000FC38B00100000000FECF +:103940003CB00100000000FE3AB0010035979C1722 +:10395000803200002A97A24A197C00000000804CA7 +:103960001F9001000C00001E98F401002997A24846 +:10397000996C00000000001542B101002997A28A4D +:10398000F16D00000C00000102CC0100000000FC01 +:103990003EB00100010000F428CC0100CC002D0550 +:1039A00048B10100349720F03E6C00000000004B4D +:1039B0001F9001000000004C2BC00100BF002D052E +:1039C00048B10100000080F33AE0010000002E4BF6 +:1039D0001990010007002A0CE4B1010000008004E6 +:1039E000E6B1010018000040439901001C002DF0D1 +:1039F00016B0010020002DF026B001000C002FF2BF +:103A00000CB001000000A20614EC00004197224512 +:103A10001F7C00000000A3062AEC0000000000F854 +:103A200094B00100000000F096B001000C002D40A1 +:103A300081B2010000002A4CE1C1010030000010F9 +:103A400048C901000A000040F19901001800000572 +:103A5000F0C901000000004AF0B101000000004B75 +:103A6000E0B101000000004761B10100A00000A426 +:103A700062DD01004B97A85C1F100000000080056C +:103A800048B1010000002E1048B10100000068019B +:103A900096B0010000000003F0B1010051974542CB +:103AA000613100000000001062B101005297A800CF +:103AB000E031000000009D4081B2010000002E10A6 +:103AC00048B101000000680196B001000000000349 +:103AD000F0B101005897454261310000200000100C +:103AE00062DD01005997A800E031000000009D4010 +:103AF00081B201003080004A44C901000000000684 +:103B0000F1B10100C0A83D460DE00100FF7F00A11A +:103B1000F08901000200000996F40100000000464F +:103B200097E00100000060A897C00100639746423B +:103B3000613100003000004A62C901006497A8406A +:103B40008132000000009E4081B2010000993F4296 +:103B500097F001006897474081320000709722F388 +:103B6000740600003F0000F3948801000000000785 +:103B7000E785010000001F5561B101000000004A07 +:103B800062B101000000A84081B200006D970040C2 +:103B900081B2000000009F4081B20100000000A837 +:103BA00036B0010080978241234000007597A244FF +:103BB0001F7C0000EF9400018C3001002080001079 +:103BC00042C901007B972240E36D000000000043E2 +:103BD00061B101004000001062DD01007897A8404B +:103BE000813200001B8400881CB0000000000041EE +:103BF00023B001000000001032B001008097224184 +:103C0000197C0000F89500432330010000000041BA +:103C100023B001008297A3150C6C00008397000667 +:103C200004B000000000001504B0010085972002D8 +:103C30001A6C00000000000D04B001000700000B2A +:103C4000968801008A9726479724000000000041CB +:103C500097C001008A97234B046C00000000004BC2 +:103C600004B001004998000548310100B4972202D0 +:103C7000145000008E97A2022A500000B497A2456B +:103C80001F7C0000909722020C50000099970002C0 +:103C900016C000009897225C1F7C00003080001046 +:103CA00042C9010098972240E36D000000000047E0 +:103CB00061B101004000001062DD01009497A8404E +:103CC000813200001B8400881CB000000000000549 +:103CD00048B101003A97005C1F000100B49722151B +:103CE000803200000000005033C00100B397A202F0 +:103CF0001A500000A59722461F7C00007080000328 +:103D000042C90100000000461F800100A597224023 +:103D1000E36D00000000004261B1010040000010AE +:103D200062DD0100A197A840813200001B84008859 +:103D30001CB000000000000548B101000C80000329 +:103D400042C90100100000F010C801002F002F5CD4 +:103D50001180010000000047E7910100F0070040DA +:103D60001B980100729720151A6C00007000000368 +:103D700048C9010000002250F1B101000000000319 +:103D8000F0B10100FF070008E08D010000000042D3 +:103D900061B10100A00000A462DD0100B097A84657 +:103DA0001F1000007297000548B1000072970002D2 +:103DB00010C00000B697A2441F7C0000EF940001E1 +:103DC0008C3001000000001B10B1000000800010CA +:103DD00044C901000C000040F199010010000008E6 +:103DE000F0C9010000000016F0B10100100000034E +:103DF000E0C901000000004561B101002000001091 +:103E000062DD01000000A85C1F900000BD9700402B +:103E100081B20000170000D0A2C901000000A2403A +:103E200027EC00000000002000B00100E2950041F6 +:103E3000A3410100C197004127D0000010000007F6 +:103E400096E401000000004B809401000000005443 +:103E500061B101000080004062DD01000000A84067 +:103E600081B20000C897004081B200001A9800405B +:103E70002B300100AC002D0616C0010090002DF083 +:103E800016C40100D097A0F01644000000000041C5 +:103E900017C001000E0000A244C9010000006CF030 +:103EA00030B00100AC002D4087B0010000006CF084 +:103EB00028B00100D997224A197C00000030004345 +:103EC00086C801000030000B16C80100D997A44035 +:103ED000813200000000004117C00100FA9722065D +:103EE00080320000E697A206146C0000E397224897 +:103EF000197C0000DE97A04117400000000000413F +:103F000017C001000000004131C0010090002018DE +:103F1000E0B101008B002D48198001008B00204585 +:103F2000E7910100E69700408790000008000043F9 +:103F300086980100E697A048174000000000004165 +:103F400017C00100B0000040439901001050004329 +:103F5000FCC9010051980030813001000000004090 +:103F6000E5B10100F197224A197C0000080000A287 +:103F700044C90100CC002DABF9B10100000000AB39 +:103F800017C00100F097A0F01644000000000041A7 +:103F900017C00100F59764F082B00000A400004053 +:103FA00047990100F597A2F280320000000000411D +:103FB000E5B101008C002018E0B101009000004044 +:103FC000459901000000600630C001000000860C29 +:103FD00080B20000BC002D4619900100A000A0F2A4 +:103FE000E4B10100B00000404399010010500043CB +:103FF000FCC9010051980030813001000000A24A44 +:1040000019FC0000080000A244C90100CC002DAB3F +:10401000F9B10100000000AB17C001000398A0F047 +:10402000164400000000004117C001000000E4F049 +:1040300082B001000080001044C90100000000416E +:10404000F0B1010000000003F0B101000000000029 +:10405000F0B101000000001062B101000000A81BD7 +:10406000E0B100000898004081B2000000F0000CB0 +:104070007E8901000000A64C956001000000804A86 +:10408000189401000080001044C9010004002201BE +:10409000F031000020000040F0C9010000000016CF +:1040A000F0B101000000004361B1010020000010E8 +:1040B00062DD01000000A815E0B100001398004087 +:1040C00081B200001080000344C901000000000616 +:1040D000F0B1010000000001F0B101000000E85F54 +:1040E0001790010070000040439901007A012EFEF4 +:1040F00092B001008B002DF616B0010020982243EB +:10410000E77D00000000004445C10100040000A656 +:104110002AB0010028006E0682C801002498224AB5 +:10412000197C00000000004245D1010000006E4CE7 +:1041300083C001000000004192C001002598423078 +:104140003D0700000000669E83B0010000001A4198 +:104150003DC301000000004192C00100060000A222 +:1041600044C901001000004998F401002E9826303F +:10417000930400002E98904C9240000000000041F3 +:1041800093C00100FFFF8049ECA9010000800010EE +:1041900044C9010004002201F031000000000009C0 +:1041A000F0B1010000000018F0B101002000001083 +:1041B00062DD01000000A815E0B100003398004066 +:1041C00081B200004098225F817C00003F98A240AD +:1041D000197C00000000004019900100000000540C +:1041E00061B101001000000796E401000000004FDB +:1041F000979401000000004B62B101003F982840F5 +:10420000813200003C98004081B200000000A221F1 +:10421000818400004398A25F816C00000000A243EB +:10422000197C0100000000431990010000000054B7 +:1042300061B101001000000796E401000000004099 +:10424000969401000000004B62B101000000A840FC +:1042500081B200004698004081B200000080001941 +:1042600044C9010004002202F03100000000000BEC +:10427000F0B1010000000013F0B1010000000043A4 +:1042800061B101002000001962DD01000000A808F2 +:10429000E0B100004E98004081B200007C002DF09B +:1042A00084B00100020000F098F401005798204CFF +:1042B000846C00008800004043990100579820F268 +:1042C000846C00000000004085B0010098002D14AF +:1042D00082B00100000000F098B00100A3002D148E +:1042E00098D001005C98204C846C00000000004CC9 +:1042F00084B00100000000F380E001005F982340DB +:10430000846C00000000004084B00100D000201444 +:10431000E0B101009800254280B0010000006EF37A +:1043200080F001000000A64282C000006598A04015 +:10433000164000000000004117C0010000009FF07F +:1043400082EC00009800A041E0B1010068980012E2 +:1043500010C90000004880400B980100C04980400F +:104360000B980100804B80400B980100404D80402D +:104370000B980100004F80400B980100C050804016 +:104380000B980100805280400B98010040548040FF +:104390000B980100005680400B980100C0578040E8 +:1043A0000B980100805980400B980100405B8040D1 +:1043B0000B980100005D80400B980100C05E8040BA +:1043C0000B980100806080400B98010040628040A3 +:1043D0000B980100006480400B980100C06580408C +:1043E0000B980100806780400B9801004069804075 +:1043F0000B980100006B80400B980100C06C80405E +:104400000B980100806E80400B9801004070804046 +:104410000B980100007280400B980100C07380402F +:104420000B980100807580400B9801004077804018 +:104430000B980100007980400B980100C07A804001 +:104440000B980100807C80400B980100407E8040EA +:104450000B98010088984357613100009498A25747 +:10446000737D00009498A240816F00000000004816 +:1044700061B101000010004A62DD01008C98A84A79 +:10448000803300009198225F957C00000000004B73 +:1044900062B101008F98A84BAC33000000001BA54F +:1044A00082B30100000000BE83C301000000804011 +:1044B00097B001000010004A62DD01009898284082 +:1044C0008132000094982257777D000000009B20E5 +:1044D00097B001000000004B62B101009898A8401D +:1044E0008132000000009B4097B0010000002E10B8 +:1044F00048B10100A8010040F19901000000000549 +:10450000F0B101000900000796E40100000060A777 +:1045100097C001000000001062B101000000A84037 +:1045200081B20000A098004081B20000A8002D1CBC +:104530008AB0010000009FF08AD000000000A24075 +:104540008BEC00008A002040E7B10100B40000407D +:1045500047990100A4002D45E0D10100AD989C17BA +:1045600080320000BE002FAB83B001001799001409 +:1045700082500100B298004081B20000B29822F24D +:10458000823000008C00004043990100B2989F1CCB +:10459000E06D0000BE0000404799010017990040FF +:1045A00081320100A800201CE0B101009C002D30E8 +:1045B00081B0010088002DF084B0010094002DF23C +:1045C00086B00100DC9823F0846C00000C000042EF +:1045D00088F40100DC982050896C0000CB98A392ED +:1045E000876C0000BB98004410C90000DC98000AEA +:1045F00087B00000DC98000987B00000DC98000854 +:1046000087B00000DC98000787B00000DC98000746 +:1046100087B00000DC98000787B00000DC98000637 +:1046200087B00000DC98000687B00000DC98000628 +:1046300087B00000DC98000687B00000DC98000618 +:1046400087B00000DC98000587B00000DC9800050A +:1046500087B00000DC98000587B00000DC980005FA +:1046600087B00000DC98000587B00000CC980044BB +:1046700010C90000DC98000F87B00000DC98000E25 +:1046800087B00000DC98000D87B00000DC98000CBB +:1046900087B00000DC98000C87B00000DC98000CAC +:1046A00087B00000DC98000C87B00000DC98000C9C +:1046B00087B00000DC98000C87B00000DC98000B8D +:1046C00087B00000DC98000B87B00000DC98000B7E +:1046D00087B00000DC98000B87B00000DC98000B6E +:1046E00087B00000DC98000B87B00000DC98000B5E +:1046F00087B00000BF002D4384C0010090002DF35F +:1047000080E00100E1982340846C00009400209D2B +:10471000E1B101000000004084B00100E598A2F082 +:10472000386C00009C002042E0B101000000005FF6 +:104730001394010000008046198001009C00204273 +:10474000E0B101003700004043990100040000F38C +:1047500080F401000F0000F382880100EB982341F0 +:10476000806C00000000005F139401000000890CC1 +:1047700080B20000BC00004043990100A000A0F2FC +:10478000E4B1010000009F4124EC0000F598A64030 +:104790008132000000009F4238EC0000F598A640EE +:1047A00081320000B400004043990100F798A3F063 +:1047B0003A6C00000000804081B20100B40000406B +:1047C00043990100FB9822F03A6C0000B400201DD0 +:1047D000E0B1010080002D5F13940100FB9823F0ED +:1047E0003A6C00008000201DE0B10100C0002012E2 +:1047F000E0B10100C400A01CE0B101000080000392 +:1048000044C9010000000042E0B101001200004074 +:104810008798010004999F41246C0000000000412A +:104820008CB00100000000128CD0010005990041FD +:1048300024B00000000000408DB0010055990040F8 +:10484000813201000000004561B10100400000100C +:1048500062DD01000000A84081B20000079900401D +:1048600081B20000D49500408132010000000016A2 +:1048700080B201000000A708803201000F99A24019 +:10488000956C0000E295004081320100008200A694 +:1048900004B00100000000402DB00100A0982F409E +:1048A00011B00100E989004189B0000000009FF8C3 +:1048B0003EEC000000009F12E0ED0000C80020ABBD +:1048C000E1B10100CC00A01FE0B101001999A35F84 +:1048D000E76D000000000041E7C10100A6000040B4 +:1048E000479901002D9922F2863000000300004311 +:1048F00084F401000100004180CC0100B8002D4289 +:1049000080D001000000624086C0010021991F4351 +:10491000803200002299A240876C000000006241B2 +:1049200087B0010026999F408032000000000040BF +:1049300085B001000000004084D00100000000426A +:1049400080B00100000000F288B0010002000044C5 +:1049500084F40100B8002E4280D0010000006240C3 +:1049600088C001002C991F44803200003099A24079 +:10497000896C00003099624189B0000003006241F7 +:1049800086E40100B8000040459901000100624141 +:1049900088E40100A4002040E5B10100A20020400D +:1049A000E7B10100BC002E4387F001000000004485 +:1049B00086C0010036992043876C000000008043C8 +:1049C000E5B101004001004380CE01000000A44396 +:1049D000E43101004001E2408798010088002D4445 +:1049E00081B0010090002DF22EB001009C002DF04E +:1049F00086B0010090002DF082B00100BA002DF0C9 +:104A000098B001004399A212986C0000BC002DF2EE +:104A100098B001004399A0F2986C000000000017C4 +:104A200082B001009C002041E0B10100B4002D12D1 +:104A300086D001004699A341E06D0000479900F03F +:104A400084B000000000004184B0010080002D43CC +:104A500084D001004A999F4280320000000000404B +:104A600085B001004C99A342146C00004D99000AD6 +:104A70000CB00000000000420CB001004F99A017DC +:104A80000C6C0000000080170CB00100549922400B +:104A90000D6C00000000A00A0CEC0000010000F00A +:104AA00082F401005499A0410C6C00000000A2F0B7 +:104AB000803201000000804081B00100E695004096 +:104AC000813201000480000344C901000000004657 +:104AD000F0B1010000000040F1B1010000006041B0 +:104AE000879401000080001044C9010000000050BC +:104AF000F1B1010000000048F0B1010000000049E0 +:104B0000F0B1010000000003E0B101000000004529 +:104B100061B101002000001062DD01000000A85D0D +:104B2000059000006099004081B2000000002E4B0B +:104B30001990010005002A0CE4B101000000800476 +:104B4000E6B101006A9922491F7C00004200004042 +:104B500087980100000000491F800100C0970040B5 +:104B60008DB0000070992240AF6F0000000000156A +:104B700096B0010088980008943001006F99224097 +:104B8000976C0000C097004687B00000000080408E +:104B900087B001007099434861310000001000089F +:104BA00062DD010075992840873000007199224824 +:104BB000777D0000C0971B4687B000007899225F80 +:104BC000117C000004002215623100007699A84093 +:104BD0008132000000009B4081B2010000000040D3 +:104BE00049B1010030000040A199010000000040DF +:104BF00093B00100000000401FB00100C9990049B6 +:104C0000963001000700004906E401000039000366 +:104C100006C801000000004005B00100200000D0DF +:104C2000A0C901000000004193C001007D99A0547B +:104C3000936C000000002E0597B001000048004072 +:104C40004999010000000040E1B10100C00100A24B +:104C500044C901008699A24197500000000000203D +:104C600049B30100CE9900404931010000B52E083A +:104C700097B0010000000040F1B101008C99A24101 +:104C800097500000180000409798010000972E40B0 +:104C900081B2010000000040F1B101009099A241F1 +:104CA000975000000000004049B1010040182E0557 +:104CB00097B0010000000040F1B101009499A241B9 +:104CC0009750000057952040E7B101003094004014 +:104CD0004599010064000040E59901005695204087 +:104CE000E7B10100B8942041E5B10100BA94204138 +:104CF000E5B1010098940040459901000200004090 +:104D00009798010000000040F1B101009E99A24176 +:104D1000975000000000004097B0010000000040E4 +:104D20006FB101000000004B68B10100A2998541FC +:104D300097400000DB9900408132010000000040F4 +:104D400039B301000000004037B30100000000400B +:104D500035B301000000004033B301000000004003 +:104D600041B30100000000403FB301003C0000409F +:104D7000299B0100EE050040259B010042000040F8 +:104D80004B9B0100000000402FB3010000000040D9 +:104D90002DB301000000004047B3010000000040B7 +:104DA00043B30100600000402B9B01000000005451 +:104DB000EF93010000000055F1930100FFFF00A5F3 +:104DC0003C8B01000000002C5BB301000000002CB4 +:104DD00045B301000000004059B30100000000404D +:104DE00057B301000000004027B30100000000405D +:104DF00053B30100BF99A250FD7F0000BF99A2519B +:104E0000FD7F0000C09900401DB3000050460040E7 +:104E10001D9B010000C000A688B30100FF3F00A653 +:104E20003AB3010000C0009D3B9B0100B405004067 +:104E3000239B0100000000404DB30100080A00A6BA +:104E400014B301000101008A159B0100008000A637 +:104E500056B101000000805E57B501001800004BFC +:104E600020E401000600004B96E401000043004BE3 +:104E700096C801001800001020DC01000000804BE3 +:104E80002094010000992E0A97B001000000004014 +:104E9000F1B10100CF99A2419750000000030040FA +:104EA0009798010000A900404599010000000040CA +:104EB000F1B10100D399A2419750000030000040A9 +:104EC000979801000000005561B101000000004BFF +:104ED00062B10100D799A84081320000D799A24160 +:104EE000975000000000804081B2010000000040A7 +:104EF00087B101000000004097B001000000004BA6 +:104F000080B10100010000A682B10100DD99854158 +:104F1000974000000000004097B1010000000040F1 +:104F200097B001000000004B90B10100010000A605 +:104F300092B10100E2998541974000000000804055 +:104F400081B20100E6994440813200000000001265 +:104F500080B10100FFFF9C4B82890100E999444028 +:104F6000813200000000004A80B1010001009CA6CF +:104F700082B10100EC99444081320000FFFF004BF8 +:104F80008489010000009CC224B001000000004A96 +:104F900090B10100FFFF804B928901000000004AA0 +:104FA00090B10100010080A692B10100FFFF004B0B +:104FB00094890100000080CA94B001000000804084 +:104FC00081B201000000004081B00100F79980A586 +:104FD00080320000F89900A58032000000000041F6 +:104FE00081C00100F99980A5803200008001004055 +:104FF00083980100029A204F816C0000000100405C +:1050000083980100029A204B816C000080000040D0 +:1050100083980100029A2047816C00000000004044 +:10502000839801000000004182DC010003900041F0 +:10503000209901000000004049B1010000142F4CEC +:1050400083B0010000000040F1B10100069AA241C6 +:1050500083500000640000A580C80100099AA2A541 +:10506000806C000020000090209901000000005F8B +:10507000239101000C9A1F918032000030000090B3 +:10508000209901000000005F239101000F9A1F91F9 +:10509000803200007000009020A901000000005F35 +:1050A00023910100129A1F91803200000000005FDE +:1050B00023910100149A1F918032000040680090F3 +:1050C00020A90100E000004061990100210000409A +:1050D0006199010022000040619901002300004015 +:1050E0006199010024000040619901002500004001 +:1050F00061990100260000406199010027000040ED +:1051000061990100C000004061990100D014004085 +:105110004599010000000040F1B10100000000408D +:10512000E1B101003003004085300100D01400409F +:1051300045990100020100A680B00100040300406F +:1051400080980100060500A682B001000807004112 +:105150008298010000000040F0B101000000004111 +:10516000E0B10100080000408598010030030040D4 +:10517000813201003903004081320100D81400401F +:1051800043990100FF02A2F8806C0000000322F0A6 +:10519000826C0000FF02004081B20000D0142E405B +:1051A00049B1010005000040A39B01000000004040 +:1051B000C1B30100080000DD81F40100369A00400F +:1051C00010C900003C9A000581B000005501004064 +:1051D00081B20000449A000581B0000055010040F2 +:1051E00081B20000499A0044A5B300004B9A0044E4 +:1051F000A5B3000002000040A4E70100000000E0A9 +:1052000081B10100FFFF00C1F0890100419A2241F4 +:10521000815000003D9A0041C1C30000B10200402E +:1052200081320100C5020040813201005A01004074 +:1052300081B2000002000040A4E70100000000E08D +:1052400091B10100FFFF00C9F0890100419A22419C +:1052500081500000459A0041C1C30000FFFF00DEFD +:1052600085890100419A00C2E0B10000FFFF00DE25 +:1052700095890100419A00CAE0B10000040000CB0A +:1052800081C801006A840040F293000004000040DD +:1052900081B200000400004081B200000400004020 +:1052A00081B200000400004081B200000400004010 +:1052B00081B200000400004081B200000400004000 +:1052C00081B200000400004081B2000004000040F0 +:1052D00081B200000400004081B2000004000040E0 +:1052E00081B200000400004081B2000004000040D0 +:1052F00081B200000400004081B2000004000040C0 +:1053000081B200000400004081B2000004000040AF +:1053100081B200000400004081B20000040000409F +:1053200081B200000400004081B20000040000408F +:1053300081B200000400004081B20000040000407F +:1053400081B200000400004081B20000040000406F +:1053500081B200000400004081B20000040000405F +:1053600081B200000400004081B20000040000404F +:1053700081B200000400004081B20000040000403F +:1053800081B200000400004081B20000040000402F +:1053900081B200000400004081B20000040000401F +:1053A00081B200000400004081B20000040000400F +:1053B00081B200000400004081B2000004000040FF +:1053C00081B200000400004081B2000004000040EF +:1053D00081B200000400004081B2000004000040DF +:1053E00081B200000400004081B2000004000040CF +:1053F00081B200000400004081B2000004000040BF +:1054000081B200000400004081B2000004000040AE +:1054100081B200000400004081B20000040000409E +:1054200081B200000400004081B20000040000408E +:1054300081B200000400004081B20000040000407E +:1054400081B200000400004081B20000040000406E +:1054500081B200000400004081B20000040000405E +:1054600081B200000400004081B20000040000404E +:1054700081B200000400004081B20000040000403E +:1054800081B200000400004081B20000040000402E +:1054900081B200000400004081B20000040000401E +:1054A00081B200000400004081B20000040000400E +:1054B00081B200000400004081B2000004000040FE +:1054C00081B200000400004081B2000004000040EE +:1054D00081B200000400004081B2000004000040DE +:1054E00081B200000400004081B2000004000040CE +:1054F00081B200000400004081B2000004000040BE +:1055000081B200000400004081B2000004000040AD +:1055100081B200000400004081B20000040000409D +:1055200081B200000400004081B20000040000408D +:1055300081B200000400004081B20000040000407D +:1055400081B200000400004081B20000040000406D +:1055500081B200000400004081B20000040000405D +:1055600081B200000400004081B20000040000404D +:1055700081B200000400004081B20000040000403D +:1055800081B200000400004081B20000040000402D +:1055900081B200000400004081B20000040000401D +:1055A00081B200000400004081B20000040000400D +:1055B00081B200000400004081B2000004000040FD +:1055C00081B200000400004081B2000004000040ED +:1055D00081B200000400004081B2000004000040DD +:1055E00081B200000400004081B2000004000040CD +:1055F00081B200000400004081B2000004000040BD +:1056000081B200000400004081B2000004000040AC +:1056100081B200000400004081B20000040000409C +:1056200081B200000400004081B20000040000408C +:1056300081B200000400004081B20000040000407C +:1056400081B200000400004081B20000040000406C +:1056500081B200000400004081B20000040000405C +:1056600081B200000400004081B20000040000404C +:1056700081B200000400004081B20000040000403C +:1056800081B200000400004081B20000040000402C +:1056900081B200000400004081B20000040000401C +:1056A00081B200000400004081B20000040000400C +:1056B00081B200000400004081B2000004000040FC +:1056C00081B200000400004081B2000004000040EC +:1056D00081B200000400004081B2000004000040DC +:1056E00081B200000400004081B2000004000040CC +:1056F00081B200000400004081B2000004000040BC +:1057000081B200000400004081B2000004000040AB +:1057100081B200000400004081B20000040000409B +:1057200081B200000400004081B20000040000408B +:1057300081B200000400004081B20000040000407B +:1057400081B200000400004081B20000040000406B +:1057500081B200000400004081B20000040000405B +:1057600081B200000400004081B20000040000404B +:1057700081B200000400004081B20000040000403B +:1057800081B200000400004081B20000040000402B +:1057900081B200000400004081B20000040000401B +:1057A00081B200000400004081B20000040000400B +:1057B00081B200000400004081B2000004000040FB +:1057C00081B200000400004081B2000004000040EB +:1057D00081B200000400004081B2000004000040DB +:1057E00081B200000400004081B2000004000040CB +:1057F00081B200000400004081B2000004000040BB +:1058000081B200000400004081B2000004000040AA +:1058100081B200000400004081B20000040000409A +:1058200081B200000400004081B20000040000408A +:1058300081B200000400004081B20000040000407A +:1058400081B200000400004081B20000040000406A +:1058500081B200000400004081B20000040000405A +:1058600081B200000400004081B20000040000404A +:1058700081B200000400004081B20000040000403A +:1058800081B200000400004081B20000040000402A +:1058900081B200000400004081B20000040000401A +:1058A00081B200000400004081B20000040000400A +:1058B00081B200000400004081B2000004000040FA +:1058C00081B200000400004081B2000004000040EA +:1058D00081B200000400004081B2000004000040DA +:1058E00081B200000400004081B2000004000040CA +:1058F00081B200000400004081B2000004000040BA +:1059000081B200000400004081B2000004000040A9 +:1059100081B200000400004081B200000400004099 +:1059200081B200000400004081B200000400004089 +:1059300081B200000400004081B200000400004079 +:1059400081B200000400004081B200000400004069 +:1059500081B200000400004081B200000400004059 +:1059600081B200000400004081B200000400004049 +:1059700081B200000400004081B200000400004039 +:1059800081B200000400004081B200000400004029 +:1059900081B200000400004081B200000400004019 +:1059A00081B200000400004081B200000400004009 +:1059B00081B200000400004081B2000004000040F9 +:1059C00081B200000400004081B2000004000040E9 +:1059D00081B200000400004081B2000004000040D9 +:1059E00081B200000400004081B2000004000040C9 +:1059F00081B200000400004081B2000004000040B9 +:105A000081B200000400004081B2000004000040A8 +:105A100081B200000400004081B200000400004098 +:105A200081B200000400004081B200000400004088 +:105A300081B200000400004081B200000400004078 +:105A400081B200000400004081B200000400004068 +:105A500081B200000400004081B200000400004058 +:105A600081B200000400004081B200000400004048 +:105A700081B200000400004081B200000400004038 +:105A800081B200000400004081B200000400004028 +:105A900081B200000400004081B200000400004018 +:105AA00081B200000400004081B200000400004008 +:105AB00081B200000400004081B2000004000040F8 +:105AC00081B200000400004081B2000004000040E8 +:105AD00081B200000400004081B2000004000040D8 +:105AE00081B200000400004081B2000004000040C8 +:105AF00081B200000400004081B2000004000040B8 +:105B000081B200000400004081B2000004000040A7 +:105B100081B200000400004081B200000400004097 +:105B200081B200000400004081B200000400004087 +:105B300081B200000400004081B200000400004077 +:105B400081B200000400004081B200000400004067 +:105B500081B200000400004081B200000400004057 +:105B600081B200000400004081B200000400004047 +:105B700081B200000400004081B200000400004037 +:105B800081B200000400004081B200000400004027 +:105B900081B200000400004081B200000400004017 +:105BA00081B200000400004081B200000400004007 +:105BB00081B200000400004081B2000004000040F7 +:105BC00081B200000400004081B2000004000040E7 +:105BD00081B200000400004081B2000004000040D7 +:105BE00081B200000400004081B2000004000040C7 +:105BF00081B200000400004081B2000004000040B7 +:105C000081B200000400004081B2000004000040A6 +:105C100081B200000400004081B200000400004096 +:105C200081B200000400004081B200000400004086 +:105C300081B200000400004081B200000400004076 +:105C400081B200000400004081B200000400004066 +:105C500081B200000400004081B200000400004056 +:105C600081B200000400004081B200000400004046 +:105C700081B200000400004081B200000400004036 +:105C800081B200000400004081B200000400004026 +:105C900081B200000400004081B200000400004016 +:105CA00081B200000400004081B200000400004006 +:105CB00081B200000400004081B2000004000040F6 +:105CC00081B200000400004081B2000004000040E6 +:105CD00081B200000400004081B2000004000040D6 +:105CE00081B200000400004081B2000004000040C6 +:105CF00081B200000400004081B2000004000040B6 +:105D000081B200000400004081B2000004000040A5 +:105D100081B200000400004081B200000400004095 +:105D200081B200000400004081B200000400004085 +:105D300081B200000400004081B200000400004075 +:105D400081B200000400004081B200000400004065 +:105D500081B200000400004081B200000400004055 +:105D600081B200000400004081B200000400004045 +:105D700081B200000400004081B200000400004035 +:105D800081B200000400004081B200000400004025 +:105D900081B200000400004081B200000400004015 +:105DA00081B200000400004081B200000400004005 +:105DB00081B200000400004081B2000004000040F5 +:105DC00081B200000400004081B2000004000040E5 +:105DD00081B200000400004081B2000004000040D5 +:105DE00081B200000400004081B2000004000040C5 +:105DF00081B200000400004081B2000004000040B5 +:105E000081B200000400004081B2000004000040A4 +:105E100081B200000400004081B200000400004094 +:105E200081B200000400004081B200000400004084 +:105E300081B200000400004081B200000400004074 +:105E400081B200000400004081B200000400004064 +:105E500081B200000400004081B200000400004054 +:105E600081B200000400004081B200000400004044 +:105E700081B200000400004081B200000400004034 +:105E800081B200000400004081B200000400004024 +:105E900081B200000400004081B200000400004014 +:105EA00081B200000400004081B200000400004004 +:105EB00081B200000400004081B2000004000040F4 +:105EC00081B200000400004081B2000004000040E4 +:105ED00081B200000400004081B2000004000040D4 +:105EE00081B200000400004081B2000004000040C4 +:105EF00081B200000400004081B2000004000040B4 +:105F000081B200000400004081B2000004000040A3 +:105F100081B200000400004081B200000400004093 +:105F200081B200000400004081B200000400004083 +:105F300081B200000400004081B200000400004073 +:105F400081B200000400004081B200000400004063 +:105F500081B200000400004081B200000400004053 +:105F600081B200000400004081B200000400004043 +:105F700081B200000400004081B200000400004033 +:105F800081B200000400004081B200000400004023 +:105F900081B200000400004081B200000400004013 +:105FA00081B200000400004081B200000400004003 +:105FB00081B200000400004081B2000004000040F3 +:105FC00081B200000400004081B2000004000040E3 +:105FD00081B200000400004081B2000004000040D3 +:105FE00081B200000400004081B2000004000040C3 +:105FF00081B200000400004081B2000004000040B3 +:1060000081B200000400004081B2000004000040A2 +:1060100081B200000400004081B200000400004092 +:1060200081B200000400004081B200000400004082 +:1060300081B200000400004081B200000400004072 +:1060400081B200000400004081B200000400004062 +:1060500081B200000400004081B200000400004052 +:1060600081B200000400004081B200000400004042 +:1060700081B200000400004081B200000400004032 +:1060800081B200000400004081B200000400004022 +:1060900081B200000400004081B200000400004012 +:1060A00081B200000400004081B200000400004002 +:1060B00081B200000400004081B2000004000040F2 +:1060C00081B200000400004081B2000004000040E2 +:1060D00081B200000400004081B2000004000040D2 +:1060E00081B200000400004081B2000004000040C2 +:1060F00081B200000400004081B2000004000040B2 +:1061000081B200000400004081B2000004000040A1 +:1061100081B200000400004081B200000400004091 +:1061200081B200000400004081B200000400004081 +:1061300081B200000400004081B200000400004071 +:1061400081B200000400004081B200000400004061 +:1061500081B200000400004081B200000400004051 +:1061600081B200000400004081B200000400004041 +:1061700081B200000400004081B200000400004031 +:1061800081B200000400004081B200000400004021 +:1061900081B200000400004081B200000400004011 +:1061A00081B200000400004081B200000400004001 +:1061B00081B200000400004081B2000004000040F1 +:1061C00081B200000400004081B2000004000040E1 +:1061D00081B200000400004081B2000004000040D1 +:1061E00081B200000400004081B2000004000040C1 +:1061F00081B200000400004081B2000004000040B1 +:1062000081B200000400004081B2000004000040A0 +:1062100081B200000400004081B200000400004090 +:1062200081B200000400004081B200000400004080 +:1062300081B200000400004081B200000400004070 +:1062400081B200000400004081B200000400004060 +:1062500081B200000400004081B200000400004050 +:1062600081B200000400004081B200000400004040 +:1062700081B200000400004081B200000400004030 +:1062800081B200000400004081B200000400004020 +:1062900081B200000400004081B200000400004010 +:1062A00081B200000400004081B200000400004000 +:1062B00081B200000400004081B2000004000040F0 +:1062C00081B200000400004081B2000004000040E0 +:1062D00081B200000400004081B2000004000040D0 +:1062E00081B200000400004081B2000004000040C0 +:1062F00081B200000400004081B2000004000040B0 +:1063000081B200000400004081B20000040000409F +:1063100081B200000400004081B20000040000408F +:1063200081B200000400004081B20000040000407F +:1063300081B200000400004081B20000040000406F +:1063400081B200000400004081B20000040000405F +:1063500081B200000400004081B20000040000404F +:1063600081B200000400004081B20000040000403F +:1063700081B200000400004081B20000040000402F +:1063800081B200000400004081B20000040000401F +:1063900081B200000400004081B20000040000400F +:1063A00081B200000400004081B2000004000040FF +:1063B00081B200000400004081B2000004000040EF +:1063C00081B200000400004081B2000004000040DF +:1063D00081B200000400004081B2000004000040CF +:1063E00081B200000400004081B2000004000040BF +:1063F00081B200000400004081B2000004000040AF +:1064000081B200000400004081B20000040000409E +:1064100081B200000400004081B20000040000408E +:1064200081B200000400004081B20000040000407E +:1064300081B200000400004081B20000040000406E +:1064400081B200000400004081B20000040000405E +:1064500081B200000400004081B20000040000404E +:1064600081B200000400004081B20000040000403E +:1064700081B200000400004081B20000040000402E +:1064800081B200000400004081B20000040000401E +:1064900081B200000400004081B20000040000400E +:1064A00081B200000400004081B2000004000040FE +:1064B00081B200000400004081B2000004000040EE +:1064C00081B200000400004081B2000004000040DE +:1064D00081B200000400004081B2000004000040CE +:1064E00081B200000400004081B2000004000040BE +:1064F00081B200000400004081B2000004000040AE +:1065000081B200000400004081B20000040000409D +:1065100081B200000400004081B20000040000408D +:1065200081B200000400004081B20000040000407D +:1065300081B200000400004081B20000040000406D +:1065400081B200000400004081B20000040000405D +:1065500081B200000400004081B20000040000404D +:1065600081B200000400004081B20000040000403D +:1065700081B200000400004081B20000040000402D +:1065800081B200000400004081B20000040000401D +:1065900081B200000400004081B20000040000400D +:1065A00081B200000400004081B2000004000040FD +:1065B00081B200000400004081B2000004000040ED +:1065C00081B200000400004081B2000004000040DD +:1065D00081B200000400004081B2000004000040CD +:1065E00081B200000400004081B2000004000040BD +:1065F00081B200000400004081B2000004000040AD +:1066000081B200000400004081B20000040000409C +:1066100081B200000400004081B20000040000408C +:1066200081B200000400004081B20000040000407C +:1066300081B200000400004081B20000040000406C +:1066400081B200000400004081B20000040000405C +:1066500081B200000400004081B20000040000404C +:1066600081B200000400004081B20000040000403C +:1066700081B200000400004081B20000040000402C +:1066800081B200000400004081B20000040000401C +:1066900081B200000400004081B20000040000400C +:1066A00081B200000400004081B2000004000040FC +:1066B00081B200000400004081B2000004000040EC +:1066C00081B200000400004081B2000004000040DC +:1066D00081B200000400004081B2000004000040CC +:1066E00081B200000400004081B2000004000040BC +:1066F00081B200000400004081B2000004000040AC +:1067000081B200000400004081B20000040000409B +:1067100081B200000400004081B20000040000408B +:1067200081B200000400004081B20000040000407B +:1067300081B200000400004081B20000040000406B +:1067400081B200000400004081B20000040000405B +:1067500081B200000400004081B20000040000404B +:1067600081B200000400004081B20000040000403B +:1067700081B200000400004081B20000040000402B +:1067800081B200000400004081B20000040000401B +:1067900081B200000400004081B20000040000400B +:1067A00081B200000400004081B2000004000040FB +:1067B00081B200000400004081B2000004000040EB +:1067C00081B200000400004081B2000004000040DB +:1067D00081B200000400004081B2000004000040CB +:1067E00081B200000400004081B2000004000040BB +:1067F00081B200000400004081B2000004000040AB +:1068000081B200000400004081B20000040000409A +:1068100081B200000400004081B20000040000408A +:1068200081B200000400004081B20000040000407A +:1068300081B200000400004081B20000040000406A +:1068400081B200000400004081B20000040000405A +:1068500081B200000400004081B20000040000404A +:1068600081B200000400004081B20000040000403A +:1068700081B200000400004081B20000040000402A +:1068800081B200000400004081B20000040000401A +:1068900081B200000400004081B20000040000400A +:1068A00081B200000400004081B2000004000040FA +:1068B00081B200000400004081B2000004000040EA +:1068C00081B200000400004081B2000004000040DA +:1068D00081B200000400004081B2000004000040CA +:1068E00081B200000400004081B2000004000040BA +:1068F00081B200000400004081B2000004000040AA +:1069000081B200000400004081B200000400004099 +:1069100081B200000400004081B200000400004089 +:1069200081B200000400004081B200000400004079 +:1069300081B200000400004081B200000400004069 +:1069400081B200000400004081B200000400004059 +:1069500081B200000400004081B200000400004049 +:1069600081B200000400004081B200000400004039 +:1069700081B200000400004081B200000400004029 +:1069800081B200000400004081B200000400004019 +:1069900081B200000400004081B200000400004009 +:1069A00081B200000400004081B2000004000040F9 +:1069B00081B200000400004081B2000004000040E9 +:1069C00081B200000400004081B2000004000040D9 +:1069D00081B200000400004081B2000004000040C9 +:1069E00081B200000400004081B2000004000040B9 +:1069F00081B200000400004081B2000004000040A9 +:106A000081B200000400004081B200000400004098 +:106A100081B200000400004081B200000400004088 +:106A200081B200000400004081B200000400004078 +:106A300081B200000400004081B200000400004068 +:106A400081B200000400004081B200000400004058 +:106A500081B200000400004081B200000400004048 +:106A600081B200000400004081B200000400004038 +:106A700081B200000400004081B200000400004028 +:106A800081B200000400004081B200000400004018 +:106A900081B200000400004081B200000400004008 +:106AA00081B200000400004081B2000004000040F8 +:106AB00081B200000400004081B2000004000040E8 +:106AC00081B200000400004081B2000004000040D8 +:106AD00081B200000400004081B2000004000040C8 +:106AE00081B200000400004081B2000004000040B8 +:106AF00081B200000400004081B2000004000040A8 +:106B000081B200000400004081B200000400004097 +:106B100081B200000400004081B200000400004087 +:106B200081B200000400004081B200000400004077 +:106B300081B200000400004081B200000400004067 +:106B400081B200000400004081B200000400004057 +:106B500081B200000400004081B200000400004047 +:106B600081B200000400004081B200000400004037 +:106B700081B200000400004081B200000400004027 +:106B800081B200000400004081B200000400004017 +:106B900081B200000400004081B200000400004007 +:106BA00081B200000400004081B2000004000040F7 +:106BB00081B200000400004081B2000004000040E7 +:106BC00081B200000400004081B2000004000040D7 +:106BD00081B200000400004081B2000004000040C7 +:106BE00081B200000400004081B2000004000040B7 +:106BF00081B200000400004081B2000004000040A7 +:106C000081B200000400004081B200000400004096 +:106C100081B200000400004081B200000400004086 +:106C200081B200000400004081B200000400004076 +:106C300081B200000400004081B200000400004066 +:106C400081B200000400004081B200000400004056 +:106C500081B200000400004081B200000400004046 +:106C600081B200000400004081B200000400004036 +:106C700081B200000400004081B200000400004026 +:106C800081B200000400004081B200000400004016 +:106C900081B200000400004081B200000400004006 +:106CA00081B200000400004081B2000004000040F6 +:106CB00081B200000400004081B2000004000040E6 +:106CC00081B200000400004081B2000004000040D6 +:106CD00081B200000400004081B2000004000040C6 +:106CE00081B200000400004081B2000004000040B6 +:106CF00081B200000400004081B2000004000040A6 +:106D000081B200000400004081B200000400004095 +:106D100081B200000400004081B200000400004085 +:106D200081B200000400004081B200000400004075 +:106D300081B200000400004081B200000400004065 +:106D400081B200000400004081B200000400004055 +:106D500081B200000400004081B200000400004045 +:106D600081B200000400004081B200000400004035 +:106D700081B200000400004081B200000400004025 +:106D800081B200000400004081B200000400004015 +:106D900081B200000400004081B200000400004005 +:106DA00081B200000400004081B2000004000040F5 +:106DB00081B200000400004081B2000004000040E5 +:106DC00081B200000400004081B2000004000040D5 +:106DD00081B200000400004081B2000004000040C5 +:106DE00081B200000400004081B2000004000040B5 +:106DF00081B200000400004081B2000004000040A5 +:106E000081B200000400004081B200000400004094 +:106E100081B200000400004081B200000400004084 +:106E200081B200000400004081B200000400004074 +:106E300081B200000400004081B200000400004064 +:106E400081B200000400004081B200000400004054 +:106E500081B200000400004081B200000400004044 +:106E600081B200000400004081B200000400004034 +:106E700081B200000400004081B200000400004024 +:106E800081B200000400004081B200000400004014 +:106E900081B200000400004081B200000400004004 +:106EA00081B200000400004081B2000004000040F4 +:106EB00081B200000400004081B2000004000040E4 +:106EC00081B200000400004081B2000004000040D4 +:106ED00081B200000400004081B2000004000040C4 +:106EE00081B200000400004081B2000004000040B4 +:106EF00081B200000400004081B2000004000040A4 +:106F000081B200000400004081B200000400004093 +:106F100081B200000400004081B200000400004083 +:106F200081B200000400004081B200000400004073 +:106F300081B200000400004081B200000400004063 +:106F400081B200000400004081B200000400004053 +:106F500081B200000400004081B200000400004043 +:106F600081B200000400004081B200000400004033 +:106F700081B200000400004081B200000400004023 +:106F800081B200000400004081B200000400004013 +:106F900081B200000400004081B200000400004003 +:106FA00081B200000400004081B2000004000040F3 +:106FB00081B200000400004081B2000004000040E3 +:106FC00081B200000400004081B2000004000040D3 +:106FD00081B200000400004081B2000004000040C3 +:106FE00081B200000400004081B2000004000040B3 +:106FF00081B200000400004081B2000004000040A3 +:1070000081B200000400004081B200000400004092 +:1070100081B200000400004081B200000400004082 +:1070200081B200000400004081B200000400004072 +:1070300081B200000400004081B200000400004062 +:1070400081B200000400004081B200000400004052 +:1070500081B200000400004081B200000400004042 +:1070600081B200000400004081B200000400004032 +:1070700081B200000400004081B200000400004022 +:1070800081B200000400004081B200000400004012 +:1070900081B200000400004081B200000400004002 +:1070A00081B200000400004081B2000004000040F2 +:1070B00081B200000400004081B2000004000040E2 +:1070C00081B200000400004081B2000004000040D2 +:1070D00081B200000400004081B2000004000040C2 +:1070E00081B200000400004081B2000004000040B2 +:1070F00081B200000400004081B2000004000040A2 +:1071000081B200000400004081B200000400004091 +:1071100081B200000400004081B200000400004081 +:1071200081B200000400004081B200000400004071 +:1071300081B200000400004081B200000400004061 +:1071400081B200000400004081B200000400004051 +:1071500081B200000400004081B200000400004041 +:1071600081B200000400004081B200000400004031 +:1071700081B200000400004081B200000400004021 +:1071800081B200000400004081B200000400004011 +:1071900081B200000400004081B200000400004001 +:1071A00081B200000400004081B2000004000040F1 +:1071B00081B200000400004081B2000004000040E1 +:1071C00081B200000400004081B2000004000040D1 +:1071D00081B200000400004081B2000004000040C1 +:1071E00081B200000400004081B2000004000040B1 +:1071F00081B200000400004081B2000004000040A1 +:1072000081B200000400004081B200000400004090 +:1072100081B200000400004081B200000400004080 +:1072200081B200000400004081B200000400004070 +:1072300081B200000400004081B200000400004060 +:1072400081B200000400004081B200000400004050 +:1072500081B200000400004081B200000400004040 +:1072600081B200000400004081B200000400004030 +:1072700081B200000400004081B200000400004020 +:1072800081B200000400004081B200000400004010 +:1072900081B200000400004081B200000400004000 +:1072A00081B200000400004081B2000004000040F0 +:1072B00081B200000400004081B2000004000040E0 +:1072C00081B200000400004081B2000004000040D0 +:1072D00081B200000400004081B2000004000040C0 +:1072E00081B200000400004081B2000004000040B0 +:1072F00081B200000400004081B2000004000040A0 +:1073000081B200000400004081B20000040000408F +:1073100081B200000400004081B20000040000407F +:1073200081B200000400004081B20000040000406F +:1073300081B200000400004081B20000040000405F +:1073400081B200000400004081B20000040000404F +:1073500081B200000400004081B20000040000403F +:1073600081B200000400004081B20000040000402F +:1073700081B200000400004081B20000040000401F +:1073800081B200000400004081B20000040000400F +:1073900081B200000400004081B2000004000040FF +:1073A00081B200000400004081B2000004000040EF +:1073B00081B200000400004081B2000004000040DF +:1073C00081B200000400004081B2000004000040CF +:1073D00081B200000400004081B2000004000040BF +:1073E00081B200000400004081B2000004000040AF +:1073F00081B200000400004081B20000040000409F +:1074000081B200000400004081B20000040000408E +:1074100081B200000400004081B20000040000407E +:1074200081B200000400004081B20000040000406E +:1074300081B200000400004081B20000040000405E +:1074400081B200000400004081B20000040000404E +:1074500081B200000400004081B20000040000403E +:1074600081B200000400004081B20000040000402E +:1074700081B200000400004081B20000040000401E +:1074800081B200000400004081B20000040000400E +:1074900081B200000400004081B2000004000040FE +:1074A00081B200000400004081B2000004000040EE +:1074B00081B200000400004081B2000004000040DE +:1074C00081B200000400004081B2000004000040CE +:1074D00081B200000400004081B2000004000040BE +:1074E00081B200000400004081B2000004000040AE +:1074F00081B200000400004081B20000040000409E +:1075000081B200000400004081B20000040000408D +:1075100081B200000400004081B20000040000407D +:1075200081B200000400004081B20000040000406D +:1075300081B200000400004081B20000040000405D +:1075400081B200000400004081B20000040000404D +:1075500081B200000400004081B20000040000403D +:1075600081B200000400004081B20000040000402D +:1075700081B200000400004081B20000040000401D +:1075800081B200000400004081B20000040000400D +:1075900081B200000400004081B2000004000040FD +:1075A00081B200000400004081B2000004000040ED +:1075B00081B200000400004081B2000004000040DD +:1075C00081B200000400004081B2000004000040CD +:1075D00081B200000400004081B2000004000040BD +:1075E00081B200000400004081B2000004000040AD +:1075F00081B200000400004081B20000040000409D +:1076000081B200000400004081B20000040000408C +:1076100081B200000400004081B20000040000407C +:1076200081B200000400004081B20000040000406C +:1076300081B200000400004081B20000040000405C +:1076400081B200000400004081B20000040000404C +:1076500081B200000400004081B20000040000403C +:1076600081B200000400004081B20000040000402C +:1076700081B200000400004081B20000040000401C +:1076800081B200000400004081B20000040000400C +:1076900081B200000400004081B2000004000040FC +:1076A00081B200000400004081B2000004000040EC +:1076B00081B200000400004081B2000004000040DC +:1076C00081B200000400004081B2000004000040CC +:1076D00081B200000400004081B2000004000040BC +:1076E00081B200000400004081B2000004000040AC +:1076F00081B200000400004081B20000040000409C +:1077000081B200000400004081B20000040000408B +:1077100081B200000400004081B20000040000407B +:1077200081B200000400004081B20000040000406B +:1077300081B200000400004081B20000040000405B +:1077400081B200000400004081B20000040000404B +:1077500081B200000400004081B20000040000403B +:1077600081B200000400004081B20000040000402B +:1077700081B200000400004081B20000040000401B +:1077800081B200000400004081B20000040000400B +:1077900081B200000400004081B2000004000040FB +:1077A00081B200000400004081B2000004000040EB +:1077B00081B200000400004081B2000004000040DB +:1077C00081B200000400004081B2000004000040CB +:1077D00081B200000400004081B2000004000040BB +:1077E00081B200000400004081B2000004000040AB +:1077F00081B200000400004081B20000040000409B +:1078000081B200000400004081B20000040000408A +:1078100081B200000400004081B20000040000407A +:1078200081B200000400004081B20000040000406A +:1078300081B200000400004081B20000040000405A +:1078400081B200000400004081B20000040000404A +:1078500081B200000400004081B20000040000403A +:1078600081B200000400004081B20000040000402A +:1078700081B200000400004081B20000040000401A +:1078800081B200000400004081B20000040000400A +:1078900081B200000400004081B2000004000040FA +:1078A00081B200000400004081B2000004000040EA +:1078B00081B200000400004081B2000004000040DA +:1078C00081B200000400004081B2000004000040CA +:1078D00081B200000400004081B2000004000040BA +:1078E00081B200000400004081B2000004000040AA +:1078F00081B200000400004081B20000040000409A +:1079000081B200000400004081B200000400004089 +:1079100081B200000400004081B200000400004079 +:1079200081B200000400004081B200000400004069 +:1079300081B200000400004081B200000400004059 +:1079400081B200000400004081B200000400004049 +:1079500081B200000400004081B200000400004039 +:1079600081B200000400004081B200000400004029 +:1079700081B200000400004081B200000400004019 +:1079800081B200000400004081B200000400004009 +:1079900081B200000400004081B2000004000040F9 +:1079A00081B200000400004081B2000004000040E9 +:1079B00081B200000400004081B2000004000040D9 +:1079C00081B200000400004081B2000004000040C9 +:1079D00081B200000400004081B2000004000040B9 +:1079E00081B200000400004081B2000004000040A9 +:1079F00081B200000400004081B200000400004099 +:107A000081B200000400004081B200000400004088 +:107A100081B200000400004081B200000400004078 +:107A200081B200000400004081B200000400004068 +:107A300081B200000400004081B200000400004058 +:107A400081B200000400004081B200000400004048 +:107A500081B200000400004081B200000400004038 +:107A600081B200000400004081B200000400004028 +:107A700081B200000400004081B200000400004018 +:107A800081B200000400004081B200000400004008 +:107A900081B200000400004081B2000004000040F8 +:107AA00081B200000400004081B2000004000040E8 +:107AB00081B200000400004081B2000004000040D8 +:107AC00081B200000400004081B2000004000040C8 +:107AD00081B200000400004081B2000004000040B8 +:107AE00081B200000400004081B2000004000040A8 +:107AF00081B200000400004081B200000400004098 +:107B000081B200000400004081B200000400004087 +:107B100081B200000400004081B200000400004077 +:107B200081B200000400004081B200000400004067 +:107B300081B200000400004081B200000400004057 +:107B400081B200000400004081B200000400004047 +:107B500081B200000400004081B200000400004037 +:107B600081B200000400004081B200000400004027 +:107B700081B200000400004081B200000400004017 +:107B800081B200000400004081B200000400004007 +:107B900081B200000400004081B2000004000040F7 +:107BA00081B200000400004081B2000004000040E7 +:107BB00081B200000400004081B2000004000040D7 +:107BC00081B200000400004081B2000004000040C7 +:107BD00081B200000400004081B2000004000040B7 +:107BE00081B200000400004081B2000004000040A7 +:107BF00081B200000400004081B200000400004097 +:107C000081B200000400004081B200000400004086 +:107C100081B200000400004081B200000400004076 +:107C200081B200000400004081B200000400004066 +:107C300081B200000400004081B200000400004056 +:107C400081B200000400004081B200000400004046 +:107C500081B200000400004081B200000400004036 +:107C600081B200000400004081B200000400004026 +:107C700081B200000400004081B200000400004016 +:107C800081B200000400004081B200000400004006 +:107C900081B200000400004081B2000004000040F6 +:107CA00081B200000400004081B2000004000040E6 +:107CB00081B200000400004081B2000004000040D6 +:107CC00081B200000400004081B2000004000040C6 +:107CD00081B200000400004081B2000004000040B6 +:107CE00081B200000400004081B2000004000040A6 +:107CF00081B200000400004081B200000400004096 +:107D000081B200000400004081B200000400004085 +:107D100081B200000400004081B200000400004075 +:107D200081B200000400004081B200000400004065 +:107D300081B200000400004081B200000400004055 +:107D400081B200000400004081B200000400004045 +:107D500081B200000400004081B200000400004035 +:107D600081B200000400004081B200000400004025 +:107D700081B200000400004081B200000400004015 +:107D800081B200000400004081B200000400004005 +:107D900081B20000B69F00889AB00000B69F0088AC +:107DA0009AB00000B69F00889AB00000B69F008885 +:107DB0009AB00000B69F00889AB0000000000088CA +:107DC0009AB00100B69F414081320000B99F224025 +:107DD0007B6F0000B69F194081B20000000019417E +:107DE0007BB30100000000A4C4B30100000000A1A7 +:107DF000C6B3010000002FA2C8B301000814004060 +:107E000049990100B09F004D9ACC0100C29F2640C5 +:107E1000813200000000004C49C10100C09FA24116 +:107E20009B500000C69F80808032000000005249B5 +:107E3000FD9301000000004AFD930100C99F00422C +:107E4000CD9300000000514AFD930100000000495D +:107E5000FD930100C99F0043CB93000000005040F8 +:107E600081B20100D99F004019990100000000F083 +:107E70009AB001000000004449D10100000040F028 +:107E800080B201000000414D80B20100D19F00404E +:107E90001999010000004C4081B20100000000442B +:107EA00049D10100000000F09AB001000000004D2F +:107EB00010B10000000000E249B10100000000E341 +:107EC00043B10100000000E445B1010000000040A2 +:107ED0007BB301000000484F40B10100D99F004032 +:107EE00081B200000400004081B2000004000040A4 +:107EF00081B200000400004081B200000400004094 +:107F000081B200000400004081B200000400004083 +:107F100081B200000000804081B0010004000040F8 +:107F200081B200000400004081B200000400004063 +:107F300081B200000400004081B200000400004053 +:107F400081B200000400004081B200000400004043 +:107F500081B200000400004081B200000400004033 +:107F600081B200000400004081B200000400004023 +:107F700081B200000400004081B200000400004013 +:107F800081B200000400004081B200000400004003 +:107F900081B200006A84004081B20000319A004042 +:107FA00081B200000400004081B200004D9A004000 +:107FB00081B200000400004081B200000000804057 +:107FC00081B20100000000A810B1000004000040D0 +:107FD00081B200000400004081B2000004000040B3 +:107FE00081B200000400004081B2000004000040A3 +:107FF00081B200000400004081B200000400004093 +:1080000081B200000400004081B200000400004082 +:0480100081B2000039 +:00000001FF diff --git a/firmware/slicoss/gbrcvucode.sys.ihex b/firmware/slicoss/gbrcvucode.sys.ihex new file mode 100644 index 000000000000..bc7a83989c08 --- /dev/null +++ b/firmware/slicoss/gbrcvucode.sys.ihex @@ -0,0 +1,162 @@ +:10000000000200004775010004A01301001CB75B4B +:10001000093000B65F01001C00000020183B783A50 +:10002000001CA27701001C071D017018AD7BF1FFB9 +:100030001CB37BA9AA1EB47B010C1CB57B29061C32 +:1000400000005064080C315A70040C315A80040CC2 +:10005000314E90040C314AA000092555C0040C31E2 +:1000600052B000E92455C004CCB3001C1CEB2D0198 +:10007000001C065652D408079D00001C7BB70200E6 +:1000800010A00F51540906565EC004A0307403003E +:10009000AC30750300CD033A001C7BB702001C6036 +:1000A0008E5154092925750300808E5154098C30D6 +:1000B000910004471C01001CA00F5154090000646A +:1000C0000004471C65C004471C7503006C30010028 +:1000D0001C4D3402001C7BB702001CA00F515409B8 +:1000E000C88337001C800100001C0000640004A0CD +:1000F0000F505409000074C3047BFBF2001CCC3386 +:100100000D001CB47BFD031C800E505409E0FB0560 +:10011000001C0000AC0300B30F5154090000EC7048 +:10012000040000EC80040000AC93006176ADC304D1 +:10013000C08D515409E07B00C01FA0FDC50100CC5B +:100140003305001CD403003C1CD4D31B001CC0D3BB +:1001500052001C00007C13048E8E5254095B807E7A +:100160001304000000001C0000940100A00F515473 +:1001700009A00F515409C003FC7F1CA001A001007D +:100180000000A40100A00F515409C003FC031CF59A +:100190007701001C267A02061CA00F515409B30FE8 +:1001A000515409B50202001CA00F5154097A7E0275 +:1001B000001CB50202001C530F525409AF0301008A +:1001C0001C7A0E525409B50202001C000002001CE9 +:1001D000A03DAA11040000AC1104D4D352001CB5F8 +:1001E0003EB2010020FBFDFF1F802C8C0300B93ABA +:1001F0009E0100753B02001CA71C010010DB83164A +:10020000001CC71D21C104B93B8DC1048B2C01000A +:100210001C6B2C35C1040000781100CB2C79C10473 +:10022000A00F515409A00F51540954D002001C4989 +:1002300025B10100AB2C81C104A71D750300CC338F +:1002400009001CEB2D01001CEA2901001CA00F5124 +:100250005409AE0F515409A00F515409D407FC039F +:100260001C993A02001CBB3802001C003800001C1C +:100270000000FC0104DB3B7E001CC71D01001C26A6 +:100280007A16061C271D01001CB30F5154097A0E63 +:10029000525409530F5254097A0E525409530F52B3 +:1002A00054097A0E525409530F525409A00F515455 +:1002B000097A0602001C530F525409AF0301001CB7 +:1002C0007A0E525409530F5254097A0E525409535C +:1002D0000F5254097A0E525409530F5254097A0E90 +:1002E000525409003D02001C0000581200CB2C01A2 +:1002F000001C753B02001CA71C010010A67BFD051D +:100300001C000090C204A67BFD051C0000A8C204CE +:10031000CB2F05001C602C00001CC71CE90200A0AC +:100320000F515409530702001CC083F1321C000016 +:10033000600204467AE6051C7A0E525409C083F125 +:10034000321C000068020440FA15001C0000A802DC +:1003500004467AE6051CA00F515409A00F51540918 +:10036000A00F515409A00F515409B37B01C01F7451 +:100370000E505409C0039C001C8000F802000000CD +:10038000F802040000CC1205071D01001CD4D32B79 +:10039000001CD4D352001C80769D1304000000037F +:1003A00000A67BB50310C79C00001C802C00001C1D +:1003B00000007C0204000074C304AB2DF912050791 +:1003C0001DD5C2048B2D01001C692501001CA67BD4 +:1003D000B50310CB2F09001C602C00001C00006826 +:1003E0000300530F525409467AE6051C7A0E525404 +:1003F0000940FA15001C0000300304467AE6051C8B +:10040000B50F515409A00F51540973EC4A0304600D +:100410002C00001C0000480300C71C01001C000049 +:10042000481305071D01001CC0D722001C75569EED +:100430001304602C00001CE71C650304E79C00000B +:100440001CA67BB50310802C00001C0000180304C0 +:10045000000074C304B97B01001C0000ACC304CBD2 +:10046000AFFC071CCB2F01041CC79F80031C00009E +:10047000ACC304CBAFFC071CCB2F0D041CC79F8063 +:10048000031C0000ACC304CBAF00F81DCB2F010050 +:100490001DA67BB5031CC79CACC3040000AC1305B0 +:1004A000071D01001CC01DFCD308279D040400A0EB +:1004B000EE66D400FB75291404207B06001CC01CCA +:1004C0003C04000000D0D308000020F400C0EFF28C +:1004D000001C20257C140460B7F2030000002C15DA +:1004E00000CCB3FC031CCC3305021C00002CC5045B +:1004F00060B72E050400002C150400007CC404C065 +:100500001DB8F304000088C404079D00001C1B7480 +:100510001DF404A67B11041CA00F895409E07B0084 +:10052000FC1F397F02001C071DBDC304A67BCD0341 +:100530001C000088C404E01C00001C0000C403046C +:10054000CBAF00F81DCB2F01101D0000CCC3040061 +:1005500000CC0304CBAF00F81DCB2F01181DC79FA3 +:10056000000B1C0000CCC304FB7501001C071D011F +:10057000001CCCB3FC031CCC3301021C0000CCC318 +:1005800004A01C00001CA0EEC20304CBAFFC071C9F +:10059000CB2F09041CFB7501001C0000CCC304CC4C +:1005A000B3FC031CCC3301021C00002CC50400006A +:1005B000983405CCB3FC031CCC3315021C479D7446 +:1005C000C4040000984400801D9C5404871DAD04A1 +:1005D00000CE7601001CEF76BDC404A477AD2409DB +:1005E000E47601001CC47601001C0000B85404D756 +:1005F00076015018F67601001C000000301800004B +:10060000000010CC3061C504EB2D01001CEA29016B +:10061000001CC05901001CF57749C504E030FC04FA +:1006200000004CD00400204C140500000008050018 +:10063000CCB3FC031CCC3309021CEB2DD5C404CC79 +:10064000B3FC031CCC3319021CEB2DD5C404CCB372 +:10065000FC031CCC330D021CEB2DD5C404CCB3FC25 +:10066000031CCC3311021CEB2DD5C404007B00808D +:100670001CAE77610500000004C004D38B00FC1F92 +:10068000607A3C001C604CE00400C02F20051FE095 +:1006900030D004008025D00400B55BD10404692665 +:1006A00001001C6A2B01001C801D00001CA9256193 +:1006B0000500EE3000001CAF77210500B45F01405B +:1006C00018079D645504B77601001C967601001C3E +:1006D000471D01001CA433016018A42F0160186499 +:1006E000770160182477016018447701001C648842 +:1006F00003001CA43F01001CA43B01001C537B0011 +:10070000C01CD3CF1B001C534F02001CDACF00C00B +:100710001FD5570F001CD3D337001CD4530F001C18 +:10072000E02900001CF5D5CC05000000B855047781 +:100730005601001C565301001C0000001018000058 +:1007400004C004F55501001C0000D0550477560183 +:10075000001C565301001C0000001018000004C0CB +:1007600004CB2F011810CB2F011010CB2F01081034 +:10077000CB2F010810CB2F012010CB2F010010CB65 +:100780002F012810892571C20400000CC304000049 +:1007900074C304000074C304000074C30400007038 +:1007A000C20400000CC304000074C304000074C33E +:1007B00004000074C304401C6CC004401C9CC004B2 +:1007C000A77775C3040000C4C004271DF1C004004E +:1007D0000074C304000074C304000074C304000068 +:1007E00048C604000048C604000048C6040000488B +:1007F000C604000048C604000048C604000048C6FD +:1008000004000048C604000048C604000048C604AE +:10081000000048C604000048C604000048C60400A2 +:100820000048C604000048C604000048C604000092 +:1008300048C604000048C604000048C6040000483A +:10084000C604000048C604000048C604000048C6AC +:1008500004000048C604000048C604000048C6045E +:10086000000048C604000048C604000048C6040052 +:100870000048C604000048C604000048C604000042 +:1008800048C604000048C604000048C604000048EA +:10089000C604000048C604000048C604000048C65C +:1008A00004000048C604000048C604000048C6040E +:1008B000000048C604000048C604000048C6040002 +:1008C0000048C604000048C604000048C6040000F2 +:1008D00048C604000048C604000048C6040000489A +:1008E000C604000048C604000048C604000048C60C +:1008F00004000048C604000048C604000048C604BE +:10090000000048C604000048C604000048C60400B1 +:100910000048C604000048C604000048C6040000A1 +:1009200048C604000048C604000048C60400004849 +:10093000C604000048C604000048C604000048C6BB +:1009400004000048C604000048C604000048C6046D +:10095000000048C604000048C604000048C6040061 +:100960000048C604000048C604000048C604000051 +:1009700048C604000048C604000048C604000048F9 +:10098000C604000048C604000048C604000048C66B +:1009900004000048C604000048C604000048C6041D +:1009A000000048C604000048C604000048C6040011 +:1009B0000048C604000048C604000048C604000001 +:1009C00048C604000048C604000048C604000048A9 +:1009D000C604000048C604000048C604000048C61B +:1009E00004000048C604000048C604000048C604CD +:1009F000000048C604000048C604000048C60400C1 +:040A00000048C604E0 +:00000001FF diff --git a/firmware/slicoss/oasisdbgdownload.sys.ihex b/firmware/slicoss/oasisdbgdownload.sys.ihex new file mode 100644 index 000000000000..18b376a9f8ad --- /dev/null +++ b/firmware/slicoss/oasisdbgdownload.sys.ihex @@ -0,0 +1,5124 @@ +:1000000002000000004000000000010000000000AD +:10001000008000001500004081B200001B0000407D +:1000200081B200002100004081B2000003000040C6 +:1000300081B20000000000A898B001000480A24036 +:10004000FD7F00000900A249DD7D00000000004C9A +:1000500080B2010007000040D1B100000000004C58 +:1000600080B201000900A240757D000060000040E0 +:10007000619901000B00A8B17E3100000900004029 +:1000800081B2000000808F981831000010000098A5 +:1000900080E40100000041988094010000000040CD +:1000A00081B201001000009880E401000E00409829 +:1000B000809400001100004081B200000000004068 +:1000C000A59901001900294081320000190014BCD3 +:1000D000803200000E0093BC8032000000005040CF +:1000E00081B201000080004081B200001000004099 +:1000F000A59901001F002940813200001F0014BC97 +:1001000080320000120093BC80320000000050409A +:1001100081B201000180004081B200002000004057 +:10012000A59901002500294081320000250014BC5A +:1001300080320000140093BC8032000000000049AF +:10014000DD810100120100408132010033010040D5 +:10015000813201002A0014BC80320000FE0013BC72 +:10016000803200005495004045990100FFFF004097 +:10017000E599010000002F4049B101000000004056 +:10018000E1B1010000000040FDB3010000000040AB +:10019000FFB30100330018EE803200000000005071 +:1001A00089B001003200A24189500000990000404E +:1001B000813201003094004043990100000000F8B2 +:1001C00020B10100000000FAE0B30100390098EE10 +:1001D00080320000000000FB80B001003B0080F393 +:1001E000DE33000000000047FD9301003E0083F372 +:1001F00080320000F00000F38088010001800040A0 +:100200002EDD0100009400404399010000000046EB +:1002100043C10100000000FA24B101007C0018EE87 +:1002200080320000450095E880320000FFFF00E8C2 +:10023000808801007C0026408132000000000040E0 +:10024000D5990100000000F2ECB30100000000F8B5 +:10025000D6B1010008000040D5990100000000F06F +:10026000D6B10100FF0000F8EE8B0100080100404C +:10027000D5990100FF0000F0808C0100000000F71C +:100280008194010000000040D6B10100FF0000F899 +:10029000808801003C000040D5990100FF0000F07B +:1002A000D68D0100FFFF00F0F0DB010000000048E8 +:1002B00081E00100000000F8819401003C01004051 +:1002C000D599010000000040D6B10100FF0000F800 +:1002D000808801000000004881E00100000000F873 +:1002E000819401003C020040D599010000000040CB +:1002F000D6B101002C000040D5990100000000F8A3 +:10030000D6B101001E0000F082F40100FF3F00F8AA +:1003100080D80100640026408132000000000041C6 +:1003200081D00100FFFF004080D8010000000041A3 +:100330008094010000000040D8B10100680022FA5A +:10034000803000000000004C81E00100010000400E +:1003500080CC010000000040DEB10100000100403F +:10036000D5990100100000FA80E40100000000F6B9 +:100370008194010000000040D6B10100000200405D +:10038000D5990100100000FA80E40100000000F699 +:100390008194010000000040D6B101000600004039 +:1003A000D5990100100000FBD6E5010007000040D0 +:1003B000D5990100180000FBD6E501004800004077 +:1003C000D5990100100000FAD6E501005000004068 +:1003D000D5990100100000FBD6E50100030000FBE9 +:1003E0007A890100000000F0DCB101007C00004CC3 +:1003F000DD9100007C0095E88430000000002FE9CA +:10040000FAB3010000000040D1B10100FF0000423A +:10041000808801003400004080CE01007C00A640AE +:1004200081320000850000408132010002802240BC +:10043000803200007C00004081B200000000004FCC +:1004400081B001008E0009F9813200008C0008F9AA +:100450008132000098001FFDF93300008B009EFDE3 +:10046000813200000000004AF39301000000804840 +:10047000F3930100000000FDF7B301000000804984 +:10048000F3930100000000FC19B1010093000AF988 +:1004900081320000000040FB81B20100000041FDFC +:1004A00081B20100000780F9F38F0100000742F9D3 +:1004B000F38F01009700A2FFF76F00000000434098 +:1004C00081B201000000A2FFFBEF0000000080FCF1 +:1004D000E1B101000000804081B0010000940040C3 +:1004E00047990100BB000040813201000000A24694 +:1004F000FD7F01000094004047990100CE000040BC +:10050000813201000000A244FD7F01000094004000 +:100510004599010000000040F1B10100FF7F00405B +:10052000F5990100FF7F0040F59901009A13004002 +:10053000F599010007000040F59901000100004015 +:10054000F599010000020040F59901000200004009 +:10055000F599010000020040F599010003010040F7 +:10056000F599010000000040F59901009A13004040 +:10057000F59901000B000040F59901008000004052 +:10058000F599010000000040F599010000000040CD +:10059000F599010007000040F599010008000040AE +:1005A000F5990100B0020040F599010000000040FB +:1005B000F599010000000040F59901000229004072 +:1005C000F599010000000040F59901000067004026 +:1005D000F599010000000040F599010080000040FD +:1005E000F599010000008040F599010000000045E8 +:1005F000FD83010000000046FD830100FF7F0040F5 +:1006000025990100C4000040813201000000A2448D +:1006100080B2000000000045FD930100E2000040B0 +:10062000833001000000A2458032010000008046B6 +:10063000FD9301000010004083980100DD000040A0 +:100640002B3101000000A24688B0000000000041EC +:1006500089B00100000000948CB00100FFFF00464B +:1006600080880100A5A5A24080CE000000000048BF +:100670008DF00100C90082418940000000008040E7 +:1006800089B0010000000044FD830100D400004057 +:10069000813201000000A24480B20000E2000008A4 +:1006A000833001000000A245803201000000804438 +:1006B000FD93010000300008839801008000004095 +:1006C0002B990100DB000040893001000000A246A8 +:1006D00080B20000FFFF009480880100A5A5A24021 +:1006E000804E01000000804389B001000384004176 +:1006F0002C990100DE00004081B200000388004117 +:100700002C990100000000208DB0010000009F9690 +:1007100080B20000DF00A2418D5000000000804048 +:1007200081B20100FF7F0040259901000000004CCC +:1007300089E00100DD000044821401000000909473 +:100740008AB0000000000045F0B101001000004533 +:1007500088F401000000004489D00100DD0000445D +:100760002B410100EC00084180320000ED000094B4 +:1007700024B100001000009424F501000000009452 +:10078000F0B10100F200A04489500000DD000044F7 +:100790002B41010000000094F0B10100EF00204463 +:1007A000895000001000004588F40100000000FAA4 +:1007B0008AB001000000A34289D00000F700A0FA2F +:1007C0008A400000000000418BC00100F500A342F8 +:1007D00089500000FFFF0045888801001000004597 +:1007E0008AF40100FC0090448A40000000000041AF +:1007F0008BC00100FFFF00458AA801000000805067 +:100800008BE00100FF7F0040259901007C00004043 +:100810002B9901000030004083980100DD000008A2 +:1008200083140100000000942AB101000080004000 +:10083000F99B0100DD0000FC19310100000040942B +:1008400080B20100DD0000442B4101000000419412 +:1008500080B2010000000041F9C301000000004423 +:100860002BC1010004019F948032000002800040EF +:1008700081B200001001005193B000001001004D42 +:1008800093B000001001004993B000000000004246 +:1008900093B001001001A24193500000000080407D +:1008A00081B201000000104081B20100000011403F +:1008B00081B201000000124081B20100000013402B +:1008C00081B201000000144081B201000000154017 +:1008D00081B201000000164081B201000000174003 +:1008E00081B201000000184081B2010000001940EF +:1008F00081B2010000001A4081B2010000001B40DB +:1009000081B2010000001C4081B2010000001D40C6 +:1009100081B2010000001E4081B2010000001F40B2 +:1009200081B201000000704081B2010000007140FE +:1009300081B201000000724081B2010000007340EA +:1009400081B201000000744081B2010000007540D6 +:1009500081B201000000764081B2010000007740C2 +:1009600081B201000000784081B2010000007940AE +:1009700081B2010000007A4081B2010000007B409A +:1009800081B2010000007C4081B2010000007D4086 +:1009900081B2010000007E4081B2010000007F4072 +:1009A00081B201000000804081B2010000040040DB +:1009B000A199010000000050A1D1010000000040F9 +:1009C0001BB001000000004019B001000000004011 +:1009D00017B001000000004015B001000000004009 +:1009E00013B001000000004011B001000000004001 +:1009F0000FB00100000000400DB0010000000040F9 +:100A00000BB001000000004009B0010000000040F0 +:100A100007B001000000004005B0010000000040E8 +:100A200003B001000000004001B001003B0120487C +:100A3000A15100000000804081B201004701224B1B +:100A4000747D00000000804081B201006000004B16 +:100A500060990100000000B17EB101004801A8408A +:100A6000813200004501004081B200000500804055 +:100A700097980100180000AA9688010000008043A2 +:100A800097F00100070000AA96880100000080404E +:100A900081B201000000005807900100D89F00407B +:100AA00081B2000000000044A5B30100D80200405C +:100AB00081320100F8020040813201000000005C38 +:100AC00007900100D89F0040BFB300005A0122CC1C +:100AD000857F00000000005107900100D89F004072 +:100AE00081B200000000004049B10100AE0300CB1C +:100AF000A3C90100D0140040A19B01000000002008 +:100B000046B1010000000048F1B10100000000D032 +:100B1000F1B10100000000CAF1B10100000000D5F0 +:100B2000E1B10100070000406199010020000020B0 +:100B300062DD01006301A84081320000000000CCAA +:100B400085930100F802004081320100D01400407A +:100B500043990100000000FABAB30100000000FA56 +:100B6000A4B30100000000F8BCB3010000142F4042 +:100B700081B00100000000E7A7B30100000000D829 +:100B8000A9B30100FF0000DD8188010002000040E0 +:100B900080F401007301004080C80100860100DD7F +:100BA000813200000000004010B1000087010040C9 +:100BB00081B200008801004081B20000890100403C +:100BC00081B200008A01004081B200008B01004028 +:100BD00081B200008D01004081B200008F01004011 +:100BE00081B200005001004081B20000B601004017 +:100BF00081B200005001004081B20000C4010040F9 +:100C000081B20000C501004081B2000082020040B4 +:100C100081B200008302004081B22800B802004087 +:100C200081B22800D49F004081B22800D59F0040A7 +:100C300081B22800D69F004081B22800D79F004093 +:100C400081B228007201004181C02800550151493C +:100C5000FD9328005501524AFD932A00550155493C +:100C6000FD832A005501564AFD832A0050019181D7 +:100C700080302A005501454081B22A0050019182FE +:100C800080302A005501464081B22A000000004011 +:100C900089B02B0000002F4081B0010000140040FB +:100CA00049990100B30122DEE16D00000000004C13 +:100CB00049C101000000004181C001009201A2442D +:100CC000816C00000000004C49D101009A012240D3 +:100CD000E16D00009601A2418150000050010041E9 +:100CE000BFB3000000000042BFB301005001A00FDD +:100CF000BD6F0000000000DEE1B101000000004413 +:100D000049C10100B50100401999010000004240AD +:100D100081B20100000043FF85B00100000000DE49 +:100D200019B10100000042FF87B00100000043FF3D +:100D3000E1B101000000004449C1010000002FFFA3 +:100D4000E1B10100081400A480CC0100AA012640F2 +:100D5000813200000000004185C00100A801A24CC2 +:100D600081500000B40122D281320000AF01224143 +:100D7000A56F00005001A2E081320000000000D207 +:100D8000C1B301000000005C8990010000004042F6 +:100D900080B201000000414380B20100000000F079 +:100DA0008894010055010044E0B10000B101004801 +:100DB00049C10000AF01005B89900000A89F00A01E +:100DC0009EB000000000004083B00100001400400D +:100DD000499901000000234081B00100BE0122DEDC +:100DE000E16D00000000004C49C10100000000411D +:100DF00081C00100B901A244816C00005001004390 +:100E0000BFB30000000000F818B10100000040F876 +:100E100080B20100000041F080B2010000000040FB +:100E2000F1B1010000000040F1B1010055010040A6 +:100E3000E1B10000C601004091B000000000004197 +:100E400091B00100D0142E4049B1010005000040CE +:100E5000A39B0100080000DD81F40100CB010040EC +:100E600080C801000000004010B10000D101004026 +:100E700081B00000530100DEA1B30000E301004097 +:100E800081B20000E501004081B00000EB010040AC +:100E900081B20000520100DFE1B10000000000D08B +:100EA000BAB30100000000DEA1B10100020000D2CF +:100EB000A5E70100000000D2C1B30100000000005E +:100EC000F0B10100DB012244C1530000DA0184418A +:100ED00081400000DE01004081320100000000D0AE +:100EE00045B10100D5010041A1C10000DA02004076 +:100EF00081320100F802004081320100550100DD1D +:100F0000A1B100000000004081B00100400000409D +:100F1000A59B0100DA02004081320100400000D3AD +:100F2000A7CB0100F80200E0A5B3000003000040D9 +:100F3000A39B0100530100DEA1B3000000000044A8 +:100F4000BFB30100000000DE819001005001A2BA91 +:100F500080040000600000DE61990100E801A8B192 +:100F60008030000052010040E0B10000000000D0DD +:100F7000BAB301006B020040819801006002004D8D +:100F80008330010000000044E1B301000000004490 +:100F9000E3B3010000000044E5B301000000004499 +:100FA000E9B3010000000044EBB30100000000447D +:100FB000F5B3010000000044F7B301000000004455 +:100FC000F9B30100F90122408F6F00007802004060 +:100FD00081980100600200C7833001008002004058 +:100FE000819801006002004283300100000000E8A7 +:100FF000F1B10100000000E9F1B10100000000EAD8 +:10100000F1B10100000000EBF1B10100000000852A +:10101000F0B10100000000ECF1B10100000000EDB2 +:10102000F1B10100000000B2F0B10100000000A920 +:10103000F0B10100000000ACF0B10100000000AB15 +:10104000F0B10100000000B8F0B10100000000B9EB +:10105000F0B10100000000BAF0B10100000000BBD7 +:10106000F0B101000C02B8408130000000000040E7 +:10107000819001000E02B940813200000000004161 +:10108000819001001002BA4081320000000000424D +:10109000819001001202BB40813200000000004339 +:1010A000819001001402BC40813200000000004425 +:1010B000819001001602BD40813200000000004511 +:1010C000819001001802BE408132000000000046FD +:1010D000819001001A02BF408132000000000047E9 +:1010E000819001001C02C8408132000000000048CD +:1010F000819001001E02C9408132000000000049B9 +:10110000819001002002CA40813200000000004AA4 +:10111000819001002202CB40813200000000004B90 +:10112000819001002402CC40813200000000004C7C +:10113000819001002602CD40813200000000004D68 +:10114000819001002802CE40813200000000004E54 +:10115000819001002A02CF40813200000000004F40 +:10116000819001002C02F04081320000000000500C +:10117000819001002E02F1408132000000000051F8 +:10118000819001003002F2408132000000000052E4 +:10119000819001003202F3408132000000000053D0 +:1011A000819001003402F4408132000000000054BC +:1011B000819001003602F5408132000000000055A8 +:1011C000819001003802F640813200000000005694 +:1011D000819001003A02F740813200000000005780 +:1011E000819001003C02F84081320000000000586C +:1011F000819001003E02F940813200000000005958 +:10120000819001004002FA40813200000000005A43 +:10121000819001004202FB40813200000000005B2F +:10122000819001004402FC40813200000000005C1B +:10123000819001004602FD40813200000000005D07 +:10124000819001004802FE40813200000000005EF3 +:10125000819001004A02FF40813200000000005FDF +:101260008190010000000040F0B10100400000400A +:10127000A59B0100D802004081320100F802004025 +:1012800081320100D0142E06A5B30100400000D326 +:10129000A7CB0100000000F0F1B10100000000F157 +:1012A000F1B10100000000F2F1B10100000000F412 +:1012B000F1B10100000000F5F1B10100000000FAF9 +:1012C000F1B10100000000FBF1B10100000000FCE1 +:1012D000F1B10100000000EBF1B10100000000EEEF +:1012E000F1B10100000000EFF1B10100000000F3D6 +:1012F000F1B10100000000F6F1B10100000000FDB5 +:10130000F1B10100DB0100C7E1B100000000804045 +:1013100081B20100660200488032000000005140A6 +:101320001AB1010000004D4081B2010000004540AB +:1013300081B201006302A241835000005F02494074 +:1013400081B20000000052401CB1010000004E407C +:1013500081B201000000464081B201006802A24152 +:10136000835000005F024A4081B20000000000A0EC +:101370009EB0010000000080D8B30100000000A171 +:10138000D0B30100000000A2D2B30100000000A40D +:10139000D4B30100000000D0D6B30100000000D19A +:1013A000DCB30100000000D2DEB3010000000088C1 +:1013B000DAB30100000000D48EB30100000000D3B6 +:1013C000E6B30100000000ACECB30100000000999E +:1013D000FAB30100000000D5E0B30100000000D521 +:1013E000E2B30100000000D5E4B30100000000D525 +:1013F000E8B30100000000D5EAB30100000000D509 +:10140000F4B30100000000D5F6B30100000000D5E0 +:10141000F8B30100000000C7A9B101000000004FAF +:1014200040B101008402004091B000000000004182 +:1014300091B0010007000040A39B0100080000DDFF +:1014400081F401008802004080C8010000000040D3 +:1014500010B100008D02004081B2000098020040EF +:1014600081B2000098020046A3B300009B02004036 +:1014700081B20000A102004081B200008F0223501F +:10148000A56F000000000050A5B30100E802004273 +:10149000A5630100F802004081320100D0142D4004 +:1014A00049B10100000000D0BAB30100000000DE25 +:1014B000A1B10100000000F800B001009702224431 +:1014C000A553000094020041A1C10000550100DDB8 +:1014D000A1B10000E80200DEA1330100F8020040E3 +:1014E000813201005501004081B20000000000453A +:1014F000BFB301005001A2D2777D0000000000D2EE +:1015000061B10100000000DE63B101009E02A8404D +:10151000813200005501004081B20000E802005411 +:10152000A5330100F802004081320100D0142D40A3 +:1015300049B10100000000F8D0B30100000000F83C +:10154000D2B30100000000F8D4B30100000000F89D +:10155000D6B30100000000F808B10100AC02004061 +:10156000819801006002004683300100550100406F +:1015700081B20000000000A09EB00100000000E861 +:1015800043B10100000000E945B10100000000EA9C +:1015900049B10100000000EBA1B101000000004FC3 +:1015A00040B101000400004081B20000040000408E +:1015B00081B200000400004081B20000040000403D +:1015C00081B200000400004081B20000040000402D +:1015D00081B20000D0142E4049B101000500004046 +:1015E000A39B010000000040C1B30100080000DD22 +:1015F00081F40100BD02004010C90000C3020005D3 +:1016000081B000005001004081B20000CB02000513 +:1016100081B000005001004081B20000D0020044BF +:10162000A5B30000D2020044A5B3000002000040B0 +:10163000A4E70100000000E081B10100FFFF00C14C +:10164000F0890100C802224181500000C40200411B +:10165000C1C30000DA02004081320100F8020040FC +:10166000813201005501004081B2000002000040BB +:10167000A4E70100000000E091B10100FFFF00C9F4 +:10168000F0890100C802224181500000CC020041D3 +:10169000C1C30000FFFF00DE85890100C80200C24F +:1016A000E0B10000FFFF00DE95890100C80200CA1A +:1016B000E0B100000400004081B2000004000040DE +:1016C00081B200000400004081B20000040000402C +:1016D00081B20000000000E7A7B30100000000D8BD +:1016E000A9B301000000004049B10100AE0300CBE6 +:1016F000A3C901000000002046B10100000000D293 +:10170000F1B10100000000D3F1B10100000000D4EC +:10171000F1B10100000000D0E1B10100000000D1F2 +:1017200061B101002000002062DD0100E202A8405A +:1017300081320000000080CC85930100040000404D +:1017400081B200000400004081B2000004000040AB +:1017500081B20000000000E7A7B30100000000D83C +:10176000A9B301000000004049B10100AE0300CB65 +:10177000A3C901000000002046B10100000000D212 +:10178000F1B10100000000D0F1B10100000000D370 +:10179000F1B10100E10200D4E1B100000400004019 +:1017A00081B200000400004081B20000040000404B +:1017B00081B200000400004081B20000040000403B +:1017C00081B200000400004081B20000040000402B +:1017D00081B200000000A2CC85FF00000000005094 +:1017E00081B00100FA02A24181500000F902A2F288 +:1017F00080300000000080CC8583010004000040A0 +:1018000081B200000400004081B2000004000040EA +:1018100081B20000B5030040A199010000002F41F2 +:1018200099B301000A032244816C0000120322488C +:10183000816C00000C03224C816C000016032250C6 +:10184000816C000017032254816C00001903225898 +:10185000816C00001E03225C816C0000500100407E +:1018600081B20000000000BC09B00100DD9F00CA89 +:1018700001B000000000004003B001000000004182 +:10188000F38301001003A242056C00000000004138 +:1018900005B00100DD9F22CA07140000DD9F00454E +:1018A000F3930000DD9F2043956F0000DD9F80CA09 +:1018B00005300000DD9F220180300000DD9F00CB5D +:1018C000DB910000570100BCABB30000000000BC7E +:1018D000B1B30100DD9F00CACFB30000FF0000CA12 +:1018E00081880100DD9FA240747D000060002040DF +:1018F000609901001B03A8B1823000001A03004068 +:1019000081B20000DD9F00CA79B3000004000040EE +:1019100081B200000000004E81B0010000000043D1 +:10192000CB8301000000454081B201002203A241A7 +:10193000815000000000454081B201000000454098 +:1019400081B201002D039182823000000000008AE4 +:1019500080B00100AE9F004080CE01002B03A64066 +:10196000813200002D03564081B20000B5030040D3 +:10197000A19901000000005307900100B503004049 +:10198000A19901000000005207900100D89F00417A +:101990008BB300000000004E81B001000000004247 +:1019A000CD8301000000464081B201003203A24114 +:1019B000815000000000464081B201000000464016 +:1019C00081B201003D039181823000000000008956 +:1019D00080B00100AE9F004080CE01003B03A640D6 +:1019E000813200003D03554081B20000B503004044 +:1019F000A19901000000005207900100B5030040CA +:101A0000A19901000000005307900100D89F0041F8 +:101A10008BB30000B0030040A1990100C4142F4013 +:101A200099B301005701004049B100000400004093 +:101A300081B200000400004081B2000004000040B8 +:101A400081B200000400004081B2000004000040A8 +:101A500081B200003094004043990100009000F8EA +:101A600080980100100000F288E40100200000408E +:101A7000209901000000005F239101004D031F9198 +:101A80008032000030000040209901000000005F1B +:101A90002391010050031F9180320000400000405C +:101AA000209901000000005F2391010053031F9162 +:101AB000803200000000005F2391010055031F9158 +:101AC000803200000008804020990100040000409E +:101AD00081B200000000004784B001000000A2486D +:101AE000848400000000005F61B101000000005C20 +:101AF0008F9001000000004762B101005A03A84026 +:101B000081320000000800478EC801005803005CC5 +:101B10008F800000E00000406199010058152D40C1 +:101B20008DB00100D0142DF088B00100000000FA43 +:101B30008AB001000000004581B0010007000045A7 +:101B400082880100000000438BF001000000004883 +:101B500083E0010000000046829401002000004163 +:101B600060990100000000418DC001007403225FF4 +:101B70008D6C00006503A2418150000063030040AA +:101B800081B2000008000040859801000000004478 +:101B900082B001000000004186B00100001C00433B +:101BA00086D801000000A641855001007003004165 +:101BB00083E000006E030040813201000000004815 +:101BC00085E00100D0142F468494010020000042DB +:101BD00060990100C0000040619901000000804050 +:101BE00081B201000400004081B200000400004006 +:101BF00081B200000400004081B2000004000040F7 +:101C000081B200000400004081B2000004000040E6 +:101C100081B20000070000458088010000000043F9 +:101C20008BF0010000040040839801008503A0416F +:101C3000815000008303004182E8000000008041E1 +:101C40008EC001000400004081B20000040000408A +:101C500081B200000000004049B1010000020040D4 +:101C600083980100003900404599010000000040C0 +:101C7000F1B101008B03A24183500000000000403D +:101C800085B001000B00004482F401001A1500A683 +:101C900086B0010070150040459901000008004021 +:101CA000F199010000000042F0B10100003900404C +:101CB000E1990100040000406199010070150043A2 +:101CC000629901009503A840813200009703225ACF +:101CD000737D00007A000040619901009803A8B16B +:101CE0007E3100000008004284C801009003A24138 +:101CF000835000000000804081B2010004000040D9 +:101D000081B200000400004081B2000004000040E5 +:101D100081B2000058152D408DB00100D0142DF077 +:101D200088B00100000000408FB00100010000A653 +:101D300090B0010000F800489098010000000045B4 +:101D400093B00100000000FA8AB001008003004057 +:101D500081320100020000A680B00100AC032240E5 +:101D6000826C0000B0030040813201005803004043 +:101D700081320100000000418DC00100B503225FE7 +:101D80008D6C0000A703A24193500000A503004002 +:101D900081B20000FF070047848801000000A640D0 +:101DA00081B20000ED9F0047803001000002004733 +:101DB0008EC80100B003004081B200000000004462 +:101DC00050B30100BB032018896C0000040000A67A +:101DD00084B00100200000A686B001000010004081 +:101DE000559B0100BE03004081B20000040000A624 +:101DF00084B00100200000A686B001000010004061 +:101E0000559B01000000004250D30100000000A8D3 +:101E10004FB30100000000434ED301006E030040A9 +:101E2000813201008203004280300100B003004093 +:101E300081320100C70322A78F6C00005A030040C3 +:101E400081320100C403004081B2000000008040E4 +:101E500081B20100C8142EBB85B00100000000EE65 +:101E600082B0010000000041E0B10100000000A2CA +:101E7000A0B3010000000044A5B30100E19F00CA27 +:101E8000A7330100E09F004081B200000400004041 +:101E900081B20000D6032242756F0000D8032241B0 +:101EA000756F0000DA031ECA81320000DC031FCA0E +:101EB00081320000000000CAC9B10100DD9F00426C +:101EC00075B30000000000CACDB10100DD9F0041E4 +:101ED00075B30000000000CACFB10100DD9F0040D3 +:101EE00075B30000008100A6C6B10100DD9F00406F +:101EF00081B20000008000A6C6B10100DD9F004055 +:101F000075B300000400004081B2000004000040EE +:101F100081B200004501004D933001004501004EA3 +:101F2000933001004501004C93300100EC9F0040CC +:101F300081320100DD9F004081B2000004000040BA +:101F400081B200000400004081B2000004000040A3 +:101F500081B200005495004045990100DD9F00CA00 +:101F6000E5B100000400004081B200000400004020 +:101F700081B200000400004081B200000400004073 +:101F800081B200000400004081B200000400004063 +:101F900081B20000CC142E4087B00100000000A2E6 +:101FA000A0B3010015040043B2330100000068DA59 +:101FB00089B001007C0000408B98010000000050B7 +:101FC00089F001000000004189D0010003000044B5 +:101FD000888C01000000004487C00100000000411F +:101FE000A5B3010015040043B2330100000000DA7C +:101FF000F1B101000000004487C001000000004171 +:10200000A5C301000B042244895000000B042244A4 +:102010008B500000FA03A250A56F000000000042A0 +:10202000A5E30100000000CAA7B30100E19F00BBC7 +:1020300085300100CC142ED295C30100AE0300CB35 +:10204000A3C901000000002042B1010000000050BF +:1020500081B001000804A241815000000704A2F2EF +:1020600080300000FA030040A5B3000000000042E9 +:10207000A5E30100000000CAA7B30100E19F00BB77 +:1020800085300100E09F004081B200000400004064 +:1020900081B20000000000D92BB101000010004007 +:1020A00083980100DB00004081320100FFFF0094B3 +:1020B000B48B01000000804081B20100000000D913 +:1020C0002BB101000010004083980100DD000040AA +:1020D0008132010000008094B4B30100040000408C +:1020E00081B200000400004081B200000400004002 +:1020F00081B200000400004081B2000004000040F2 +:1021000081B200000400004081B2000004000040E1 +:1021100081B20000000000D92BB10100000000DAFC +:1021200027B1010006C000402D990100DE000040EB +:1021300081320100001000408398010002C4004178 +:102140002C990100DE000040813201000040004077 +:1021500083980100058200412C990100DE000040B7 +:10216000813201002D048094803200000C01004077 +:10217000813201002804004081B200000480004048 +:102180002D990100DE0000408132010000008040F6 +:1021900081B201003104001210C9000000488040E3 +:1021A0000B980100C04980400B980100804B804093 +:1021B0000B980100404D80400B980100004F80407B +:1021C0000B980100C05080400B9801008052804065 +:1021D0000B980100405480400B980100005680404D +:1021E0000B980100C05780400B9801008059804037 +:1021F0000B980100405B80400B980100005D80401F +:102200000B980100C05E80400B9801008060804008 +:102210000B980100406280400B98010000648040F0 +:102220000B980100C06580400B98010080678040DA +:102230000B980100406980400B980100006B8040C2 +:102240000B980100C06C80400B980100806E8040AC +:102250000B980100407080400B9801000072804094 +:102260000B980100C07380400B980100807580407E +:102270000B980100407780400B9801000079804066 +:102280000B980100C07A80400B980100807C804050 +:102290000B980100407E80400B9801000400004034 +:1022A00081B200000400004081B200000400004040 +:1022B00081B200000400004081B200000400004030 +:1022C00081B200000400004081B200000400004020 +:1022D00081B200005904001210C900000080804043 +:1022E0000B980100008280400B9801000084804020 +:1022F0000B980100008680400B9801000088804008 +:102300000B980100008A80400B980100008C8040EF +:102310000B980100008E80400B98010000908040D7 +:102320000B980100009280400B98010000948040BF +:102330000B980100009680400B98010000988040A7 +:102340000B980100009A80400B980100009C80408F +:102350000B980100009E80400B98010000A0804077 +:102360000B98010000A280400B98010000A480405F +:102370000B98010000A680400B98010000A8804047 +:102380000B98010000AA80400B98010000AC80402F +:102390000B98010000AE80400B98010000B0804017 +:1023A0000B98010000B280400B98010000B48040FF +:1023B0000B98010000B680400B98010000B88040E7 +:1023C0000B98010000BA80400B98010000BC8040CF +:1023D0000B98010000BE80400B98010004000040F3 +:1023E00081B200000400004081B2000004000040FF +:1023F00081B200000400004081B2000004000040EF +:1024000081B200000400004081B2000004000040DE +:1024100081B200000000004087B1010000000040D0 +:1024200097B001000000004B80B10100010000A640 +:1024300082B1010082048541974000000000004005 +:1024400097B101000000004097B001000000004B70 +:1024500090B10100010000A692B1010087048541FE +:10246000974000000000804081B20100040000405D +:1024700081B200000400004081B20000040000406E +:1024800081B200000400004081B20000040000405E +:1024900081B2000090046040813200000000001210 +:1024A00080B10100FFFFF04B82890100930460407E +:1024B000813200000000004A80B101000100F0A656 +:1024C00082B101009604604081320000FFFF004BA2 +:1024D000848901000000F0C224B001000000004A1D +:1024E00090B10100FFFF804B928901000000004A7B +:1024F00090B10100010080A692B10100FFFF004BE6 +:1025000094890100000080CA94B0010004000040DA +:1025100081B200001000004E98E4010000000007A6 +:10252000989401000000004399E001000000008041 +:10253000989401000000004999E001000000004C5F +:1025400088940100A604474081320000AD04222097 +:10255000876F000000001F4081B2010000000040B2 +:1025600081B201000000004081B201000000004083 +:1025700081B20100A604004081B2000000001F806B +:1025800086B30100B004224F777D0000C0040040F4 +:10259000813201000000004F61B1010000000044E1 +:1025A00062B10100B104A84081320000B804224B9E +:1025B000897C0000B604224F777D0000C0040040F3 +:1025C000813201000000004562B10100B604A8405C +:1025D000813200000000802087B301000400004029 +:1025E00081B200000400004081B2000004000040FD +:1025F00081B200000400004081B2000004000040ED +:1026000081B200000400004081B2000004000040DC +:1026100081B200000000005099B001006F0000403E +:1026200061990100C104A8B152330000C604224BD5 +:10263000537F00006F00004061990100C404A8B1FD +:102640007E310000C104A241995000000000A24F59 +:1026500077FD00000400004081B20000040000404B +:1026600081B200000400004081B20000040000407C +:1026700081B200000400004081B20000040000406C +:1026800081B200000400004081B20000040000405C +:1026900081B200001000004E98E401000000000725 +:1026A000989401000000004399E0010000000080C0 +:1026B000989401000000004899E00100D604004C05 +:1026C00088940000D604474081320000DD042220B7 +:1026D000876F000000001F4081B201000000004031 +:1026E00081B201000000004081B201000000004002 +:1026F00081B20100D604004081B2000000001F80BA +:1027000086B30100E004224F777D0000F004004012 +:10271000813201000000004F61B10100000000445F +:1027200062B10100E104A84081320000E804224ABD +:10273000897C0000E604224F777D0000F004004011 +:10274000813201000000004562B10100E604A840AA +:10275000813200000000802087B3010004000040A7 +:1027600081B200000400004081B20000040000407B +:1027700081B200000400004081B20000040000406B +:1027800081B200000400004081B20000040000405B +:1027900081B200000000005099B001006F000040BD +:1027A00061990100F104A8B152330000F604224AF5 +:1027B000537F00006F00004061990100F404A8B14C +:1027C0007E310000F104A241995000000000A24FA8 +:1027D00077FD00000400004081B2000004000040CA +:1027E00081B200000400004081B2000004000040FB +:1027F00081B200000400004081B2000004000040EB +:1028000081B200000400004081B2000004000040DA +:1028100081B200007B000040619901000005A8B171 +:102820008030000012051D4080320000401800403A +:1028300049990100040000A686B001001005A240DD +:1028400086040000DE9F9C4080320000FFFF0040B5 +:1028500088880100300500504731010036000044EF +:1028600088CC01000C055240813200003005004048 +:10287000473101000000004189B0010030050048E7 +:10288000473101003005000547310100DE9F00405F +:1028900081B200002800004047991B00DE9F0041E4 +:1028A000E1C11A007818004049991B00190522540B +:1028B000817C1A001405424081321A00008200B364 +:1028C00067DF1B0000001A4493931B0028000040A0 +:1028D00047991B00300500418930010027050F4052 +:1028E00080320000FF7F00408888010030050050E2 +:1028F000473101003600004488CC01001F05994093 +:10290000803200000000004889D0010021059B4072 +:10291000803200000000004C89D0010023051F44D4 +:1029200080320000300500404731010000000041C6 +:1029300089B00100300500484731010030050058DA +:1029400047310100DE9F004081B2000010000040CE +:1029500086F401006F00004386880100DE9F260593 +:10296000473100003005004189300100DE9F004002 +:1029700081B200000400004081B200000400004069 +:1029800081B200000400004081B200000400004059 +:1029900081B200000000A044F041010000000040AE +:1029A00081B2010000008041E1C10100040000404B +:1029B00081B200000400004081B200000400004029 +:1029C00081B200000400004081B200000400004019 +:1029D00081B200004C010007913001000000A240CC +:1029E00097EC00000000800591C001000400004049 +:1029F00081B200000400004081B2000004000040E9 +:102A000081B200000400004081B2000004000040D8 +:102A100081B200004C010040813201004405A24017 +:102A2000976C00003A000040B39B01004505004050 +:102A300081B2000040000040B39B01001004004040 +:102A400081320100000000DAF5B1010010040042FB +:102A5000B3430100000000DAF5B1010010040042A8 +:102A6000B3430100000000DAF5B101004E00004060 +:102A7000B39B01001004004081320100080000DA1D +:102A8000F7F5010050000040919801000000004758 +:102A90008FB0010010040048B2330100000000DADA +:102AA000F7B10100080000DAF7F50100000000426C +:102AB00091C001005005A2418F500000000000416C +:102AC00045D1010008000040B39B01001004004004 +:102AD00081320100000000DAFDB101000A0000406F +:102AE000B39B01001004004081320100000000DAB5 +:102AF000FDB101001A000040B39B0100100400402A +:102B000081320100000000DAFDB101001800004030 +:102B1000B39B01001004004081320100000000DA84 +:102B2000FDB1010038050040813201001E0000485F +:102B3000B2CB01001004004081320100000000DA35 +:102B400091C0010000000048B2CB01001004004019 +:102B50008132010000006EDA8FB0010002000048EF +:102B6000B2CB01001004004081320100000000DA05 +:102B7000FDB1010004000048B2CB01001004004088 +:102B800081320100000080DAFDB101000400004044 +:102B900081B200007A052245FD7F0000401600400A +:102BA00045990100DB9F00404931010008000048C1 +:102BB000B2CB010015040040813201007805A2402B +:102BC0008F6C00007D052220B56F00007A05004063 +:102BD00081B20000DA9F004081321F007D05224053 +:102BE000976C1E007A05424081321E000000004FA3 +:102BF00067931F00DF9F005867931E005416004024 +:102C000047991F00000000FEF4B11F0000000040C3 +:102C100081B21F00000000FEF4B10100000000407E +:102C200081B20100000000FEF4B10100000000408C +:102C300081B20100000000FEF4B10100000000407C +:102C400081B20100000000FEF4B10100000000406C +:102C500081B20100000000FEF4B10100000000405C +:102C600081B20100000000FEF4B101004600004006 +:102C7000B39B01001004004081320100080000DA1B +:102C8000F7F501004800004095980100000000445D +:102C900097B001001004004AB2330100000000DACE +:102CA000F7B10100080000DAF7F50100000000426A +:102CB00095C001009005A241975000002A000040F5 +:102CC000A59B010040160040A19B0100000000CA26 +:102CD000A7B30100E19F00BB85300100E09F0040E9 +:102CE00081B200000400004081B2000004000040F6 +:102CF00081B200000400004081B2000004000040E6 +:102D000081B200000400004081B2000004000040D5 +:102D100081B20000B8052245FD7F0000E0150040AB +:102D2000479901001A0000A280DC01000000005059 +:102D3000F1B10100F0150040F1990100000000CA56 +:102D4000F1B101000700004061990100200000403E +:102D500062DD0100A705A8BBE131000000000050C2 +:102D600083B00100AA05A24183500000A905A2F288 +:102D7000823000004C01004081320100B005A240C9 +:102D8000976C00003A000040B39B0100B105004081 +:102D900081B2000040000040B39B0100F0150040EC +:102DA000439901001004004081320100B805A2FAE5 +:102DB000B46F000010040042B3430100B805A2FA4A +:102DC000B46F000010040042B3430100BB0522FAB7 +:102DD000B46F0000B8054240813220000000004E70 +:102DE00067932100DF9F0058679320004016004042 +:102DF00045992100DB9F004049312100F615004034 +:102E0000439921005C1600404599210000006EFAAC +:102E10008EB021000000004081B20100000000FEE1 +:102E2000F4B101000000004081B20100000000FE8A +:102E3000F4B101000000004081B20100000000F088 +:102E4000B4B30100C905A2408F6C0000FC1520201E +:102E5000E1B10100CE05004081B22400DA9F0040BC +:102E600081322500CE052240976C2400CB054240DC +:102E7000813224000000004F67932500DF9F005837 +:102E80006793240038050040813225001E00004869 +:102E9000B2CB25001004004081320100D30522503E +:102EA000B56F00000000005091C001000000004814 +:102EB000B2CB0100F615004043990100200400F256 +:102EC000B433010002000048B2CB0100F815004005 +:102ED00043990100200400F2B433010004000048CB +:102EE000B2CB0100FA15004043990100200400F222 +:102EF000B433010008000048B2CB0100FC150040CB +:102F000043990100000000F094B00100FFFF004A67 +:102F1000B48B010020040040813201000A00004807 +:102F2000B2CB01001000004AB4F7010020040040B9 +:102F30008132010038050040813201001E00004846 +:102F4000B2CB01001004004081320100E90522509B +:102F5000B56F0000EA050050B5B300000000004066 +:102F6000B5B301002004004081320100E09F004021 +:102F700081B200000400004081B200000400004063 +:102F800081B200000400004081B200000400004053 +:102F900081B2000000160040479901003031004026 +:102FA000F599010032330040F599010034350040B5 +:102FB000F599010036370040F59901003839004095 +:102FC000F599010041420040F59901004344004059 +:102FD000F599010045460040F59901004748004039 +:102FE000F5990100494A0040F59901002C00004084 +:102FF0008398010000000040F7B10100FC05A241E8 +:103000008350000080162E0683B00100360000FBBE +:10301000F6A90100FF05A2418350000022000040F4 +:1030200083980100000000FBF6B101000206A241F6 +:10303000835000006200004095980100DC9F004032 +:103040008132010000162D0683B001008016004079 +:10305000459901005C0000FBF6A901000806A241A9 +:103060008350000000000070F9B101000000007101 +:10307000F9B1010000000072F9B101000000007315 +:10308000F9B1010000000074F9B1010054000040E2 +:1030900095980100DC9F0040813201000000007023 +:1030A00095B0010014062270B56F00000000804149 +:1030B00097B001000000804097B00100040000407C +:1030C00081B200000400004081B200000400004012 +:1030D00081B20000456700A6E0B201000123007044 +:1030E000E19A0100CDEF00A6E2B2010089AB0071C8 +:1030F000E39A0100BA9800A6E4B20100FEDC007277 +:10310000E59A0100321000A6E6B201007654007381 +:10311000E79A0100D2C300A6E8B20100F0E1007412 +:10312000E99A01008016004A44C901000000000726 +:1031300081B001000000004A80D001000000004082 +:10314000F7B101002506A241815000008016004A17 +:1031500044C90100FC162A47E7B501000300004AF4 +:10316000E8E50100000000408DB001005003004080 +:10317000A399010080163D468DE00100000000503B +:1031800089B00100000000FC40B0010000000041D7 +:10319000A3C101002E06A24189500000000000706A +:1031A000EBB2010000000071EDB2010000000072FE +:1031B000EFB2010000000073F1B2010000000074E2 +:1031C000F3B201000000004083B001000F00004195 +:1031D0008088010050030040A2C901004B06A050A6 +:1031E000836C00000D00004098C801000000004FF3 +:1031F000998401005003004CA2C901000000002086 +:1032000086B001000800004098C801000000004F8F +:10321000998401005003004CA2C901000000002065 +:1032200086A401000200004098C801000000004F81 +:10323000998401005003004CA2C901000000002045 +:1032400086A4010050030040A2C901000000004311 +:1032500040A401000100002088E401000000005F9C +:1032600041F0010000000044409401000500007599 +:1032700089E401001B00007585F401000000004492 +:10328000849401005506A353836C0000000000766F +:1032900089B00100000000778984010000000076F9 +:1032A0008BB00100000000208BA40100000000781A +:1032B0008B840100640600458894000027000041CB +:1032C00080CE01005A06AA4081320000000000763C +:1032D00089B001000000007789A40100640600782D +:1032E00089A400003B00004180CE01005706AA409F +:1032F000813200000000007689B0010000000077F4 +:1033000089840100000000768BB001000000007885 +:103310008B840100000000458894010000000077C4 +:103320008BB00100000000788B840100640600452A +:10333000889400000000004484C00100000000796F +:1033400085C001000000002084C001006B06A3536B +:10335000836C0000825A00A684C001009979004263 +:1033600084C801007806004081B2000027000041B7 +:1033700080CE01007006AA4081320000D96E00A6FE +:1033800084C00100A1EB004284C80100780600401F +:1033900081B200003B00004180CE01007506AA40CA +:1033A000813200001B8F00A684C00100DCBC0042FB +:1033B00084C801007806004081B2000062CA00A6FD +:1033C00084C00100D6C1004284C8010078060040D4 +:1033D00081B2000000000078F3B201000000007725 +:1033E000F1B201001E00007689E4010002000076BF +:1033F000EFF6010000000044EE96010000000075A9 +:10340000EDB2010000000042EAB2010000000041FC +:1034100083C001004F00004180CE010037062A40E2 +:103420008132000000000075E1C20100000000765A +:10343000E3C2010000000077E5C20100000000784F +:10344000E7C2010000000079E9C201002B068141BA +:103450008D4000000000804081B201000400004067 +:1034600081B200000400004081B20000040000406E +:1034700081B200000400004081B20000040000405E +:1034800081B200000400004081B20000040000404E +:1034900081B2000000000050FD9301004016004082 +:1034A00045990100DB9F00404931010008000048B8 +:1034B000B2CB01001504004081320100B906224060 +:1034C0008F6C0000DA9F004081320100B906A240F3 +:1034D000976C00005E160040439901007C1620F6B0 +:1034E000E0B101000000004031B301009D06224F11 +:1034F0008F7C000000000051FD9301009F062240D8 +:103500008F7C0000A3060054FD930000A106224218 +:103510008F7C000000000052FD930100A3062241B1 +:103520008F7C000000000053FD930100B70622517C +:10353000FD7F000038050040813201000C0000488A +:10354000B2CB01001004004081320100B206A2405B +:10355000B56F00001E000048B2CB01001004004807 +:1035600096300100000000DA97C001000400004B13 +:10357000B2CB010010040040813201000E0000486F +:10358000B2CB010020040040813201000C00004851 +:10359000B2CB010000000030B5B3010020040040B0 +:1035A000813201000E000048B2CB0100100400403F +:1035B00081320100B6062240B56F0000BA06005401 +:1035C000FD93000000000051FD8301001C0000FE7F +:1035D0007FD90100BA06A6408132000000000055E4 +:1035E000FD9301000000804081B201000400004012 +:1035F00081B200000400004081B2000004000040DD +:1036000081B200000400004081B2000004000040CC +:1036100081B20000E79F004081320100C406225CB5 +:103620001F7C0000E39F00881CB00000E99F005C45 +:103630001F00010000002E0548B1010000000040FD +:10364000E1B1010004002D0348B10100000000F0C9 +:103650003CB001002800001402C801000000000175 +:1036600034B0010000002D0532B001002200000539 +:103670000AC801001000000348C90100000000F85A +:1036800018B00100000000F804B00100000000F8CC +:103690000EB001000C0000A40CC80100EA9F00401D +:1036A000813201000000004023B001000A0722011E +:1036B0008032000000003C4423E0010000002EA402 +:1036C00080B001000000001048C10100D906A30726 +:1036D000026C0000DA0668011AB0000000006807FA +:1036E0001AB001000000000D02D00100000000052A +:1036F000F0B101000000000CF0B101000000000278 +:10370000E0B101000000000D0AC00100EC062240FB +:10371000036C0000E6062242236C0000000000411A +:1037200023C001000000004761B10100200000A497 +:1037300062DD01002307284081320000E3060040DB +:1037400081B200000000001080C0010000000047AE +:1037500061B101000000004062B10100E806A8402C +:1037600023300000E39F00881CB0000023070040C6 +:1037700081B200000000001080C00100000000477E +:1037800061B101000000004062B10100EE06A840F6 +:1037900023300000E39F00881CB0000022000019C5 +:1037A00048C9010000002D1448C101000F0000F2BB +:1037B0003A880100000000423BE001000E000014C6 +:1037C00002C801000000001D02C00100FA06231A11 +:1037D000025000000000004603C001002307000162 +:1037E00034C000000C002D1D48C10100F00000F2A3 +:1037F000308801000000004231F001000000001498 +:1038000002B001000000001D02C00100000000180D +:1038100002C001000207221A025000002307000123 +:1038200034C000002200001948C9010002002D1414 +:1038300048C10100000000F614B001000000001DA6 +:1038400014D001000000001814D001000000001E78 +:1038500024B001001200001710C801002307001A4D +:1038600010C0000000003C4423E00100000000A460 +:1038700086B0010000002E1048C101000F07A312FE +:103880000E6C0000100760071AB000000000601204 +:103890001AB001000000680D16940100FFFF000B34 +:1038A00016D8010000000008F0B101000000000C73 +:1038B000F0B1010000000002E0B1010000000010C2 +:1038C00086C001000000004661B1010020000043F5 +:1038D00062DD01001707A85C1F1000004007220DE1 +:1038E000145000004007220D245000000000000D7D +:1038F00010C001001E072242236C00002307004174 +:1039000023C000000000004661B10100400000102B +:1039100062DD01001F07A85C1F000000E39F008814 +:103920001CB000000000004023B001003F07A20DC2 +:103930000E5000002E0722461F7C000000000046AB +:103940001F8001003080001042C901002C0722F2C4 +:10395000640600000000004761B101004000001053 +:1039600062DD01002907A84081320000E39F008842 +:103970001CB0000020800003469901000000005F99 +:10398000E191010000002D0648B10100000000F89F +:1039900018B00100000000F804B0010033071FF068 +:1039A0000E300000D306004C0DC0000000002E5F5A +:1039B0000F800100D3062307146C000030000010B4 +:1039C00048C9010024000040F199010000000003F3 +:1039D000F0B1010000000000F0B10100000000168D +:1039E000F0B101002400000000C801000000004701 +:1039F00061B10100200000A462DD01003C07A8467F +:103A00001F100000D30600030CB00000D306000D09 +:103A100018C000005F07A2441F7C000000000019CE +:103A20000AB001002200000548C901000A002D1457 +:103A300048C1010002002040E5B10100040020401F +:103A4000E5B101000D002D1D48C10100090000F382 +:103A5000388801000D002050E7B1010004002D401E +:103A60003FB00100000000F432B00100040020402B +:103A7000E1B101002200000548C9010000002D1439 +:103A800048C101000200001D94F401000000004044 +:103A900091B001005207A0FC9040000000000041DE +:103AA00091C001005007A24195500000000000A401 +:103AB00096B0010004002E0548B101000000004846 +:103AC000F0B101000000004B48B1010000000018F7 +:103AD00048C101000200001894F4010000002D18F4 +:103AE00090B001005C07A0FC904000000000004185 +:103AF00091C001005A07A241955000000000004803 +:103B0000E0B1010010002040E5B1010004002D05E6 +:103B100048B10100000000F880B02D00000000F066 +:103B200016B02D002200000548C92D000000001429 +:103B300048C12D00640743303D072C000000009E63 +:103B400085B02D0000001B413DC32D000400204224 +:103B5000ECB12D000000001E82B0010002002E1DFD +:103B600082C001000000661882C00100000000420F +:103B700080C001006E07A0418044000000000041A9 +:103B800081C001001000004092F401000A002E30B4 +:103B900081840100720790409240000000000041C3 +:103BA00093C001000000662093A401000000001DE6 +:103BB00048C1010004002019E8B101000000001E06 +:103BC00016C001007807A01916440000000000414B +:103BD00017C001000D002F1E32C001007D07A2405A +:103BE000156C00007C07A01C16400000000000417E +:103BF00017C00100000063F33894010010000005B5 +:103C000048C9010004002E1E98B001000000601A8F +:103C100098C001000C002040E1B101008B07224652 +:103C20001F7C0000000000461F8001003080001053 +:103C300042C90100890722F2640600000000004723 +:103C400061B101004000001062DD01008607A8405C +:103C500081320000E39F00881CB000002080000338 +:103C6000469901000000005FE191010030800010E2 +:103C700044C901001200001AF0C901000000001739 +:103C8000F0B1010010000005E0C901003000001093 +:103C900080C801000000004461B101002000004024 +:103CA00062DD01009107A840813200009B07225C81 +:103CB0001F7C000000003C4423E0010000002D10A8 +:103CC00048C101009B0722F2640600000000004684 +:103CD00061B101004000001062DD01009807A840BA +:103CE00081320000E39F00881CB00000EB9F005C65 +:103CF0001F00010020002F0548B101000000000B4B +:103D0000E4B101000000005017F00100A10790F29B +:103D1000164000000000004117C0010000006620AE +:103D200017A40100100000142AC801000000001DA3 +:103D30002AC00100000000502BE00100000000F24A +:103D40002A9401003080001042C90100AC0722F221 +:103D5000640600000000004461B101004000001052 +:103D600062DD0100A907A84081320000E39F0088BE +:103D70001CB000000080001710DC0100C9072240C1 +:103D8000156C0000B407A2441F7C00000000004432 +:103D90001F900100B307229F136C000002000088EF +:103DA0001CCC0100E49F004081B2000000000041F3 +:103DB0003FC30100E69F004081320100B707A241E6 +:103DC000877C00000000001E3EC00100C9072240A1 +:103DD000156C0000BA07201E146C00000000000AD9 +:103DE0003CB00100E59F001E24300100BF072208FF +:103DF0002E3000000000005211C001000000001A27 +:103E000010C001002307004017B00000E49F0088A5 +:103E10001CB00000E59F004081320100BC07A208F1 +:103E20002E300000808000A604B001000600004093 +:103E300087980100008000034499010004002204D7 +:103E4000E0310000E89F001F8C30010000000040BE +:103E50000FB00100E29F005C1F9000000080000393 +:103E60004499010004002204E0310000E69F004074 +:103E700081320100CE07A241877C0000CF07001EDF +:103E80003EC000000000001F8CB001000000004098 +:103E900005B00100E89F00400F300100E29F005C88 +:103EA0001F9000000400004081B2000004000040A8 +:103EB00081B200000400004081B200000400004014 +:103EC00081B200000400004081B200000400004004 +:103ED00081B200000400004081B2000004000040F4 +:103EE00081B200000400004081B2000004000040E4 +:103EF00081B200000400004081B2000004000040D4 +:103F000081B200000400004081B2000004000040C3 +:103F100081B200000400004081B2000004000040B3 +:103F200081B200000400004081B2000004000040A3 +:103F300081B200000400004081B200000400004093 +:103F400081B200000400004081B200000400004083 +:103F500081B200000400004081B200000400004073 +:103F600081B200000400004081B200000400004063 +:103F700081B200000400004081B200000400004053 +:103F800081B200000400004081B200000400004043 +:103F900081B200000400004081B200000400004033 +:103FA00081B200000400004081B200000400004023 +:103FB00081B200000400004081B200000400004013 +:103FC00081B200000400004081B20000F70700BC8D +:103FD00080B200000380004081B2000003800040F6 +:103FE00081B200000380004081B2000003800040E5 +:103FF00081B200000380004081B2000003800040D5 +:1040000081B200000380004081B2000003800040C4 +:1040100081B200003180004081B200003480004055 +:1040200081B200003580004081B2000004000040F1 +:1040300081B200001B80818080320000E787A240AF +:10404000916F00000000004C90B301005C952EA21F +:1040500080B00100FF000080F489010090952AC81B +:10406000E5B10100000000A1F0B101000000004036 +:10407000F0B10100000000A4F0B10100000000D088 +:10408000F0B10100000000D1F0B10100000000D249 +:10409000F0B101000000004CF0B10100000000D4BC +:1040A000F0B10100000000D3F0B10100000000EE0B +:1040B000F0B101000000004EF0B10100000000402E +:1040C00044B1010018801181983000000000514077 +:1040D00081B201001A801182983000000000524025 +:1040E00081B20100E7870048FD930000B60300405D +:1040F000A19901002380A242FD7F00002080008062 +:1041000080320000228011818230000022805140E4 +:1041100081B2000022801182823000002280524051 +:1041200081B200002C800048FD93000027800080B1 +:10413000803200002680A253077C0000000051530B +:10414000079001002A800052079000002980A252A7 +:10415000077C00000000525207900100000000534D +:104160000790010000000048FD9301000000004698 +:10417000F39301005C952EA252B30100FF00008072 +:10418000F48901000000004CE4B10100000000A926 +:1041900045B101003080004C80B200000000454075 +:1041A00081B201000000554081B20100C682054085 +:1041B00049B10000C682054049B100000000054039 +:1041C00049B101004C010040813201000000004B68 +:1041D000DEB2010000000040FD9301000000004835 +:1041E000FD830100020000409B9B0100000000A530 +:1041F0009CB30100480300408132010058952044DF +:10420000E0B101000494004043990100000000F275 +:1042100024B10100000C00EE968801000000004A65 +:1042200097F001004480A243976C00000000004218 +:10423000FD93010000C000A636B10100D01400407B +:104240004799010005000040F59901000038004041 +:10425000F599010000060040F599010003000040B7 +:10426000F599010005100040F59901000209004090 +:10427000F599010004000040F59901006003004039 +:10428000813201008803004081320100A003004018 +:1042900081320100B982004081320100B1820040C8 +:1042A0008132010060952040E1B10100709520400D +:1042B000E1B1010000000049DD9101000000004073 +:1042C00091B30100000000407BB30100A0980040C2 +:1042D000813201000000004085B301005C95204060 +:1042E000E1B101003C8200408132010090060040B3 +:1042F000813201000000005F2F810100A281004097 +:1043000081320100A5980040813201000000454043 +:1043100081B201000000554081B2010001830040DC +:1043200081B200000400004081B20000040000409F +:1043300081B200000400004081B20000040000408F +:1043400081B200000400004081B20000040000407F +:1043500081B200002800004047990100C682004158 +:10436000E1C1000078180040499901001905225464 +:10437000817C00006C80424081320000008200B4E9 +:1043800069DF010000001A449393010028000040F7 +:10439000479901001805004081B200000400004068 +:1043A00081B200000400004081B20000040000401F +:1043B00081B200000400004081B20000040000400F +:1043C00081B200000400004081B2000004000040FF +:1043D00081B2000055820040813201007D80224080 +:1043E000976C00007A804240813200000000004F4C +:1043F00069930100438100586993000054160040FE +:1044000047990100000000FEF4B101008005004062 +:1044100081B2000080804240813200000000004EE6 +:1044200069930100438100586993000040160040E1 +:10443000459901004005004049310100F615004052 +:10444000439901005C1600404599010000006EFA96 +:104450008EB00100C105004081B2000004000040A0 +:1044600081B200000400004081B20000040000405E +:1044700081B200000400004081B20000040000404E +:1044800081B200000400004081B20000040000403E +:1044900081B200009680004081B200005582004049 +:1044A0008132010096802240976C00009380424048 +:1044B000813200000000004F6993010043810058E1 +:1044C0006993000038050040813201001E00004859 +:1044D000B2CB0100D005004081B2000004000040D2 +:1044E00081B200000400004081B2000004000040DE +:1044F00081B200000400004081B2000004000040CE +:1045000081B200000400004081B2000004000040BD +:1045100081B200008302004081B20000B802004076 +:1045200081B20000D49F004081B20000D59F0040BE +:1045300081B20000D69F004081B20000D79F0040AA +:1045400081B200007201004181C000005501514953 +:10455000FD9300005501524AFD9300005501554955 +:10456000FD8300005501564AFD83000050019181F2 +:10457000803000005501454081B200005001918219 +:10458000803000005501464081B20000000000402C +:1045900089B00100000000F880B00100000000F0C8 +:1045A00016B001002200000548C9010000000014F7 +:1045B00048C10100B48043303D0700000000009E68 +:1045C00085B0010000001B413DC3010004002042F2 +:1045D000ECB101000000A240916F0100000000401A +:1045E00049B10100AE0300CBA3C9010000000020C7 +:1045F00046B10100C480A240E16D0000000000D27D +:10460000F1B10100000000D3F1B10100000000424F +:10461000F0B101000000004561B101002000002060 +:1046200062DD01000000A8D0E1B10000C1800040BF +:1046300081B20000000000A898B001000480004092 +:104640008BB30000B1030040A1990100C980A242D0 +:10465000976F000000000045A1C1010000000000AC +:1046600080B001000000A2048094000080153F4249 +:1046700097E301000000004049B101000000600321 +:10468000029401000000004007B00100040000CBCC +:1046900099CB0100000000CCF3830100D380A2423B +:1046A000976F0000000000CBF3930100AE0300CB36 +:1046B000A3C901000000002044B101000000004433 +:1046C000F1B1010000000000F0B1010000000004A1 +:1046D000F0B10100000000A1E0B1010005000040C0 +:1046E000619901002000002062DD0100DA80A8400D +:1046F00081320000F9020020423101000000A24195 +:10470000056C0100000080CBDB9101000000194125 +:104710008BB301006000004061990100E080A8B106 +:104720008C3300006000004061990100E280A8B174 +:1047300094330000E88014C681320000180000C6DF +:1047400083F401002283224F83040000C4800040D0 +:1047500081B20000FF0100C681880100000000C690 +:1047600097A30100C4801F5C975300006D821EC692 +:1047700081320000F2802248FD7F0000F280225842 +:10478000816C0000F2802248816C0000C000004073 +:1047900084CC0100F2809F428032000022830040DE +:1047A00081B20000C480A2C68F060000C4801EC66D +:1047B0008132000000002F4381F00100F6800040AC +:1047C00010C900004481004081B200007E81004099 +:1047D00081B20000398200CA63B3000075810040D5 +:1047E00081B200005581004D83B000006081004E11 +:1047F00061B100004C81004085B000005581004C43 +:1048000083B000002E81004085B00000F881004098 +:1048100049B1000086810040C1B10000F481004030 +:1048200081B200004C81004085B00000F0030040E0 +:1048300049B10000228300CA9BB300009081004070 +:10484000C1B1000094810040C1B100009B810040D3 +:10485000C1B100009C810040C1B100009D810040B9 +:10486000C1B100009E810040C1B100009F810040A5 +:1048700081B000009F81004181B000002D82004086 +:1048800081B20000AE8200BBABB300003A8200CA26 +:10489000CFB30000C803004049B10000E803004066 +:1048A00081B20000C480004081B200002283004039 +:1048B00081B20000E003004081B20000228300CA00 +:1048C00077B300005681004D83B000005E81004E3A +:1048D00061B100004C8100BB85B000005681004CE6 +:1048E00083B000004C8100BB85B000002E8100BB6E +:1048F00085B000002081004081B20000228300CA00 +:104900004DB300007005004049B10000A005004013 +:1049100049B10000268122428F6F00002881224188 +:104920008F6F00002A811ECA813200002C811FCAAD +:1049300081320000000000CAC9B101002283004298 +:104940008FB30000000000CACDB1010022830041F6 +:104950008FB30000000000CACFB1010022830040E5 +:104960008FB30000008100A6C6B101002283004081 +:1049700081B20000008000A6C6B101002283004081 +:104980008FB30000781800404999010010002F9C57 +:1049900089B00100468100403933010018002F9B87 +:1049A00089B00100468100403733010000002F9A92 +:1049B00089B00100468100403533010008002F997D +:1049C00089B001004681004033330100008000AE11 +:1049D00047C90100C480A240E16D00008000004092 +:1049E000F1990100000000CAF1B10100000000428D +:1049F000F0B1010040180040E199010000000045BD +:104A000061B10100200000AE63DD0100418128405A +:104A1000813200003E81004081B20000418142406D +:104A2000813200000000005C6993010022831A4477 +:104A3000939300004481424081320000438100583A +:104A40006993000000000044F0D101000000A44080 +:104A500081B200004B81A240E16D000000000044E3 +:104A600045D1010000008040E1B10100000080411B +:104A7000E1D101004C81375C61310000000000424F +:104A800062B1010052812840813200004D81225CD8 +:104A9000777D0000C480174081B200004D81004046 +:104AA00081B20000000000CA63B101005281A84039 +:104AB000813200002283174081B2000057810040FC +:104AC00081B00000578100BB81B0000000000041B0 +:104AD00060B10100C480A241767D0000000000406A +:104AE00062B101005981A84081320000000000CA73 +:104AF00063B1010022832840813200005B810040C5 +:104B000081B200005095004047990100618100BBCF +:104B100087B0000050952F4087B00100658122408A +:104B2000957F0000C480A240E16D0000C480224057 +:104B3000956F0000228360409583000002002DF0F5 +:104B400084B00100C4802240856C0000C480A24073 +:104B5000857C0000C480A24E777D000069813640CC +:104B6000813200000000004262B101006A81A84069 +:104B7000813200000000004362B101006C81A84056 +:104B800081320000000000CA63B101006E81A840BC +:104B9000813200000000164081B201007481224180 +:104BA00043510000000800CA95CB01006881004114 +:104BB00085C0000022830040E1B100007781A2425D +:104BC000676F00000000004167B301007781424039 +:104BD000813200000000004065B301000000004089 +:104BE0009383010000001ACA6997010022832640BE +:104BF000813200007C8142408132000022831A44CD +:104C000093930000C4802043956F0000228380CAE4 +:104C10006733000022832240656F0000C480A248F1 +:104C2000DB7D00002283006FDB91000085000040E7 +:104C30008132010035802240803200002283004012 +:104C400081B2000000000058959301000000005F51 +:104C5000959301008C81A244216F00000000005F49 +:104C6000958301000000005E95930100000000574D +:104C700095930100000000CAC3B101008F81225B3F +:104C8000957F00000000004BFD930100228300404F +:104C900081B200001BFD00CA959B01000D0100CAF6 +:104CA000C53101000000005F95830100228300CA26 +:104CB000C5B10000DF6F00CA959B010000000055E0 +:104CC00095930100000000CAC7B101002283225F52 +:104CD000957F00000D010040813201000000005F5F +:104CE00095830100228300CAC7B10000228300CA55 +:104CF000C9B10000228300CACBB10000228300CAE0 +:104D0000CDB10000228300CACFB1000000002E42C6 +:104D100081E001009814004048C90100228300CAC4 +:104D2000E1B100000000004009B10100200000A630 +:104D300082B00100A481A25E0B7D000000800041D2 +:104D400008990100A681A25E0B7D0000208000A6CC +:104D500008B10100A8819F8582300000000000306A +:104D600083840100DD812230836C0000A781A24F83 +:104D70000B7D00000000004121B30100028000A66D +:104D800082B0010028820040813201001000004101 +:104D900084E40100038000A682B001002882004064 +:104DA00081320100F0FF00418688010000000043CD +:104DB000849401000F0000A686B0010010C40043D7 +:104DC00086980100BD81A243846C0000000000436E +:104DD00021B30100200000A682B001001C000041A8 +:104DE00082DC0100BA81A25E0B7D0000040000415C +:104DF00008990100CF81004081B20000410100A666 +:104E000086B00100500C004386980100C281A24385 +:104E1000846C00000000004121B30100CF810040FC +:104E200081B20000410100A686B00100600C004381 +:104E300086980100CF81A243846C000000000042EC +:104E400021B30100188000A682B001002882004032 +:104E500081320100FFFF004182880100007700419C +:104E6000828C010001020041829801002000004173 +:104E700082DC01001800004182DC0100CD81A25ECD +:104E80000B7D00000000004108B10100200000A6D9 +:104E900082B00100D081A25E0B7D00004013004172 +:104EA00008990100D8812243216F0000200000A64C +:104EB00082B001001200004182DC0100D581A25EB7 +:104EC0000B7D00000004004108990100F3810040BF +:104ED00081B20000200000A682B00100190000414C +:104EE00082DC0100DA81A25E0B7D000000A000419F +:104EF00008990100F381004081B2000000000044E5 +:104F000021B301000000004083B001000000005FF9 +:104F1000839001000000005E8390010000000057B4 +:104F20008390010000000041C2B101000C0100406B +:104F3000813201000000005F838001000000004119 +:104F4000C2B101000C01004081320100200000A626 +:104F500082B001000400004182DC01002000004119 +:104F600008990100200000A682B001001100004154 +:104F700082DC0100EC81A25E0B7D0000010000419B +:104F800008990100200000A682B00100EF81A25E16 +:104F90000B7D00004013004108990100010000A6AC +:104FA00082B00100400000412E99010000008040C5 +:104FB00081B20100200000A680B00100000000CAFC +:104FC00081940100F681A25E0B7D000022830040E7 +:104FD00008B10000C8142EBB85B00100F981A25EA3 +:104FE0000B7D00000000004087B0010008822243D2 +:104FF000216F000017822244216F0000118000A65B +:1050000082B0010028820040813201001F82224AC2 +:10501000837C000000000040879001000382224D45 +:10502000837C000000000041879001000582224F30 +:10503000837C000000000043879001000782224E1D +:10504000837C000000000042879001001F82004026 +:1050500081B20000018000A682B0010028820040D9 +:1050600081320100018000A682B001002882004048 +:10507000813201001F822242837C00000000004038 +:10508000879001001C8000A682B0010028820040A9 +:105090008132010012822245837C00000000004121 +:1050A0008790010014822244837C000000000043AA +:1050B0008790010016822243837C0000000000429A +:1050C000879001001F82004081B20000018000A68D +:1050D00082B001002882004081320100018000A6D8 +:1050E00082B0010028820040813201001F822242EA +:1050F000837C000000000040879001000000004316 +:10510000879001000000004187900100008000A608 +:1051100082B0010028820040813201002382224BAC +:10512000837C0000000000408780010000000043F5 +:10513000E0B10100FF7F00A2A08B0100000000444D +:10514000A5B30100B88000CAA73301004181004027 +:1051500081B200002000004182DC01002982A25EB1 +:105160000B7D00000000004108B101002B829F85EB +:10517000823000000000804081B20100308214F7CC +:10518000813000003082A249FD7F0000000000480D +:10519000FD930100338215F8811400003382A24A86 +:1051A000FD7F000000000048FD9301003582A2C889 +:1051B000813200004000004080DC0100001000400F +:1051C00080DC010000000040EFB301003782424064 +:1051D000F13300004381004068970000228300BB48 +:1051E0006BB30000228300BBB1B3000022830040F8 +:1051F00081B20000000300408198010000000040DF +:1052000018B101008000004083980100001900409F +:10521000459901000000424081B20100000043FFB7 +:10522000F1B10100000000FFF1B1010000000041F8 +:1052300081C001000000004018B101004082A2417D +:1052400083500000001600404599010000190040FD +:10525000439901000000004743C1010000000040E5 +:1052600083B00100000000F380B001000000005B8B +:1052700081D001000000004180D00100000000400A +:10528000F6B101000000005B43C1010000000041D5 +:1052900083C001004A82A254836C000000000040D9 +:1052A000F7B101000000004183C001005182A20655 +:1052B000836C00000000804081B2010000160040B5 +:1052C0004399010080162E0683B00100360000FBD2 +:1052D000F6A901005782A24183500000220000403D +:1052E00083980100000000FBF6B101005A82A24140 +:1052F000835000006200004095980100DC9F004050 +:105300008132010000162D0683B001008016004096 +:10531000459901005C0000FBF6A901006082A241F2 +:105320008350000000000070F9B10100000000711E +:10533000F9B1010000000072F9B101000000007332 +:10534000F9B1010000000074F9B1010054000040FF +:1053500095980100DC9F0040813201000000007040 +:1053600095B001006C822270B56F00000000804192 +:1053700097B001000000804097B00100C480A242B5 +:10538000976F0000B6030040A199010000002F4272 +:1053900099B3010078822244816C00008082224807 +:1053A000816C00007A82224C816C00008582225040 +:1053B000816C000086822254816C00008882225811 +:1053C000816C00008D82225C816C000050010040E5 +:1053D00081B20000000000BC09B00100228300CAB5 +:1053E00001B000000000004003B0010000000041D7 +:1053F000F38301007E82A242056C000000000041A0 +:1054000005B00100228322CA07140000228300464F +:10541000F393000022832043956F0000228380CA0B +:10542000053000002283220180300000C480A248A1 +:10543000DB7D0000228300CBDB910000570100BC24 +:10544000ABB30000000000BCB1B30100228300CA6E +:10545000CFB30000FF0000CA818801002283A24070 +:10546000747D000060002040609901008A82A8B12C +:10547000823000008982004081B20000228300CA8D +:1054800079B300000000004E81B00100000000432D +:10549000CB8301000000454081B201009082A2410F +:1054A000815000000000454081B2010000004540ED +:1054B00081B201009B829182823000000000008A4C +:1054C00080B00100AE9F004080CE01009982A640CE +:1054D000813200009B82564081B20000B60300403A +:1054E000A19901000000005307900100B60300409D +:1054F000A19901000000005207900100D89F0041CF +:105500008BB300000000004E81B00100000000429B +:10551000CD8301000000464081B20100A082A2417B +:10552000815000000000464081B20100000046406A +:1055300081B20100AB8291818230000000000089BD +:1055400080B00100AE9F004080CE0100A982A6403D +:1055500081320000AB82554081B20000B6030040AA +:10556000A19901000000005207900100B60300401D +:10557000A19901000000005307900100D89F00414D +:105580008BB30000B1030040A1990100C4142F4067 +:1055900099B301005701004049B10000A0942E4387 +:1055A00097B0010000000040F1B10100B282A241B9 +:1055B0009750000050952040E1B10100AC942E437B +:1055C00097B0010000000040F1B10100B682A24195 +:1055D000975000000000804081B20100AE030040FF +:1055E000A39901000000004081B001006015004057 +:1055F000859801000800004040E4010000000059C7 +:10560000419401000000005041E001000000004210 +:10561000409401000000005741900100000000414B +:1056200081C001000000A342816C01000000004124 +:10563000A3C10100BC82A042816C0000BC8200506A +:1056400085C000000183A241017D0000CF82225865 +:10565000737D00007800004061990100C782A8B105 +:105660009C300000300038459DE001000400A25F3E +:105670001F7C00000400225E1F7C000000C000A60A +:105680001EA401000100000E10C90000CF8233C427 +:1056900081300000D282A1AD9D200000C68213405F +:1056A00081B200000000134E5A83010030003845DB +:1056B0009DE001000400A25F1F7C00000400A25EC8 +:1056C0001F7C00000400A240056C0000DD8222ABBC +:1056D00080040000DB82A240017D0000DD82225FA9 +:1056E000577D00001288005F1FB40000DD82225E3B +:1056F000577D00008088005F1FB40000E3822254C1 +:10570000737D00007400004061990100DD82A8B142 +:10571000003000000000005F1FB40100F784A25FAA +:10572000017C00009587004081B20000E582A25F05 +:1057300059270000E782A25C737D0000EE82A25E22 +:10574000737D0000FA82225C737D0000FB8237408B +:10575000813200007C00004061990100E882A8B11C +:10576000363000007C00004061990100EA82A8B157 +:10577000003000001F000000028801003785175F1D +:105780001FB40000FB823440813200007E000040E4 +:1057900061990100EF82A8B112300000F782522116 +:1057A00013040000000014412FC301000000005F3B +:1057B0001FB40100FF3F0009008C010000000043FE +:1057C00001F001004F83003413840000FF3F1409EF +:1057D000008C01000000005F1FB40100C48300437F +:1057E00001F000000000004081B20100FB82334064 +:1057F000813200000400A24E5A7F00000700004ED4 +:1058000080E401000039004080C801000400A2408B +:10581000066C0000C682134E5A930000E787A24828 +:10582000FD7F0000058302E681320000068383E5E8 +:10583000813200008E82004297B300009E820042B7 +:1058400097B3000009832246F37F00000C83A24136 +:10585000F37F0000C6800042973301000C8322448E +:10586000F37F00000C83A241F37F0000C680006F2D +:10587000973301000400A2AC803200001183225A49 +:10588000737D00007A000040619901000E83A8B189 +:105890007E310000010000CF11C900001783A24033 +:1058A000937F000017832244937F0000138342A557 +:1058B000803000001683A240937F000038831A4096 +:1058C0009393000000001A4081B20100DF80A240E3 +:1058D000737D0000E2872244216F0000D9872240B7 +:1058E000657D00000005A25B737D00000400A249F5 +:1058F000337D000021832248337D0000FF010099A1 +:1059000080D801000000005081E00100A8982F40DD +:1059100033B1010000000040E0C1010001830040FC +:1059200081B20000C68200408BB300000400A25E7A +:105930001F7C00000400225F1F7C00000000005E4E +:105940001F900100C682005F1F8000000400A25E5D +:105950001F7C00000400225F1F7C00000000005E2E +:105960001F9001000000005F1F8001000000005830 +:1059700061B101000000004E62B10100C682284002 +:10598000813200002C83004081B200000000004002 +:105990000FB001000400A25E1F7C00000400225F23 +:1059A0001F7C0000328333401F3000000400A24EF1 +:1059B0005A7F00000700004E80E4010000390040DB +:1059C00080C801000400A240066C0000C682134E8D +:1059D0005A9300003A83A0CE815000004D83A0CDA1 +:1059E000816C0000000000A59CB30100000000B124 +:1059F00081B001004D8322B58114000080152F4035 +:105A000049B101003E83424081320000000060B491 +:105A100065970100D0152E4069B3010000001A44BB +:105A20009383010004002240E16D00001A0000A2EF +:105A300080DC010000000044F1B10100000000B171 +:105A4000F1B10100000000B5F1B101000500004016 +:105A5000619901008000004062DD01004883A8A137 +:105A6000E0310000178300889EB300001783A24135 +:105A7000676F00001783006FDB9100004D83424089 +:105A80008132000017831A40938300000004004015 +:105A900089980100099900008A3001000400A25A87 +:105AA000017C000004002240016C00000099000904 +:105AB00046C901003F0000F30C8801005C83A64248 +:105AC000136000009B9600950330010057836140EE +:105AD0008132000075000040619901005883A8B12F +:105AE0000C300000A9967110943001005D830058BD +:105AF0001F9000008D9600950330010023830088DD +:105B00001CB0000000002D0348B1010004002DF07E +:105B10002EB0010080040017968801000400A64002 +:105B2000813200004AC1001796D801000400A64047 +:105B300081320000EE070040979801006883234BF4 +:105B4000E46D00006883224BFD7F000000000040F0 +:105B50001F90010022002F4081B201006B83831748 +:105B60008032000026000040479901006D838517B0 +:105B7000803200000000004847C1010073832255B5 +:105B80002F7C00000000004243D101000F0000FA0A +:105B9000968801000000004297E0010000000042EA +:105BA00097D001007483004B44C10000120000A292 +:105BB00044C90100280000F602CC01000A0000A13F +:105BC00042C90100000000F816B00100000028F0F2 +:105BD00010B00100000000F01AB00100000000A2A7 +:105BE0002AB00100C0283C460DE0010000002D4411 +:105BF00095B001008083A2F80E300000908322410E +:105C00009550000000002D5049C101007C830040E8 +:105C100081B200007D83A2F8166C00007D83A2F89B +:105C2000106C00007D83A2F01A6C00008E83225855 +:105C30001F7C000000993F4213F0010085836540FE +:105C4000813200008983A2F3740600000000000680 +:105C5000E69501008E83754081B2000000000006C9 +:105C600096B001003F0075F30C880100000000555C +:105C700061B101000000004B62B101008C83A840BB +:105C8000813200008E836740813200009683774125 +:105C90002DC30000948322581F7C00000000005593 +:105CA00061B101000000000662B101009283A840CA +:105CB000813200009483674081320000D5837741B0 +:105CC0002DC30000030000071AF401001895000717 +:105CD00016300100A8832241816C00009C8322427F +:105CE000816C0000238300881CB00000A783225F22 +:105CF0000F7C00004E96005F01100100A28322403D +:105D0000956C00000480000342C90100000000F20D +:105D100002B00100A595005295300100AC95004BF2 +:105D200002B000000000005F0F800100010400408D +:105D300089980100099900008A300100B496000991 +:105D400096300100F08700400FB00000B783A25AE0 +:105D50001F7C00000400A25A1F7C000000B5000D4B +:105D600042C901000400220BE67D000000B7000DCF +:105D700042C901000400220BE67D0000709400403F +:105D800081320100B7832220856C0000B2839C0F12 +:105D900080320000238300881CB000008D95005CD9 +:105DA0001F000100C8970042613101002383008871 +:105DB0001CB00000900400079630010000002D0583 +:105DC00048B101000400A24BE17D00000400A25C88 +:105DD0001F7C000000002D0548B10100BB8382F04C +:105DE000183000006C8900458FB00000282000A604 +:105DF00096B00100C18322179604000034040040CD +:105E000089980100099900008A3001005B97004BD6 +:105E1000953001006C89004B8FB000005D96000347 +:105E200048310100AF930040813001006C8900408F +:105E300081B20000000000400FB0010000040040EB +:105E400089980100099900008A300100040022406D +:105E5000016C000000002E1048B1010000006850E5 +:105E600003B0010000000003F0B101004000000099 +:105E7000E0C9010000002E5049C10100000000509F +:105E8000F1B1010000000003F0B101000000004288 +:105E900061B101002000001062DD0100D083A84044 +:105EA000813200001000001062C90100D283A800F6 +:105EB000E0310000238300881CB0000000002D03A7 +:105EC00048B10100000000400FB00100000000F8E0 +:105ED0002EB00100000000F202B0010000000040FE +:105EE00017B00100004100A696B00100EE072E4752 +:105EF00097900100E883221796040000E683224B66 +:105F0000FD7F0000E68323A2026C0000A5950052ED +:105F10009530010004002241975000000C002D0034 +:105F200012B00100000000F000B001000000005CB1 +:105F300001800100AC95004B02B000000000000998 +:105F400000B001000000005003B001000584005CB7 +:105F500017900000FA8322432F7C000000000045C8 +:105F60001F900100F383225F2F7C000000002E10A1 +:105F700048B1010000000058F1B101001000000319 +:105F8000F0C9010010000000E0C90100EF83624287 +:105F9000613100000000001062B10100F083A840F0 +:105FA00081320000238372881CB0000020002D0382 +:105FB00048B10100FF0F00F680880100F783A2A618 +:105FC000816C0000FA8300F23AB00000F484A24B26 +:105FD000FD7F0000C9940040813201000688004026 +:105FE00081B200000584224A2F7C000005842248EB +:105FF0002F7C00000A002D0348B101003F0000F291 +:10600000868801001F0000438488010005000043CA +:1060100080F4010098943D4281E001000584A24291 +:10602000E07D0000F484A24BFD7F0000C994004095 +:10603000813201000688004081B200000204004065 +:1060400089980100099900008A300100078469409D +:1060500081320000000000A309B001000000794176 +:1060600047C301000400A0A1096C00000E8422A116 +:10607000096C0000278300881CB000000A8400031C +:1060800048B100004884A392036C00002B980040A4 +:10609000953001000000004143C3010000000016DC +:1060A00080B2010006882708803200001584225C37 +:1060B000177C0000168400002AB0000012000000C7 +:1060C0002AC801000200000880C801001A84A24307 +:1060D0002F7C00005E970040813201003684005E14 +:1060E00017900000040000018CCC01005E97004C6A +:1060F0000330010000002E4602B001001000001025 +:1061000048C901000C000001F0CD01002C00004046 +:10611000F0C9010000000016F0B1010010000015E8 +:10612000E0C901000000004361B10100A00000A42B +:1061300062DD01002384A854171000003684005E3D +:1061400017900000120000002AC801003584224385 +:106150002F7C0000040000018CCC01000000004CEA +:1061600003B001007F9700436131010000002E461B +:1061700002B001001000001048C901000C0000012D +:10618000F0CD01000C000009F0C90100000000186A +:10619000F0B1010010000015E0C90100000000434B +:1061A00061B10100A00000A462DD01003684285422 +:1061B000171000003284004081B200007F97004336 +:1061C00061310100388422502F7C0000000000560D +:1061D0001790010007000017988801003B84A24136 +:1061E000996C00000000005517900100000000436A +:1061F00061B101004000001062DD01003C84A84054 +:1062000081320000238300881CB0000066970040A4 +:1062100081320100438422432F7C0000168000035A +:1062200044C901000000001DE4B101000097005EB8 +:10623000051001004684A25F2F7C000086930001B8 +:1062400038430100C99400408132010006880040B3 +:1062500081B200004A84A24BFD7F0000F18400411E +:1062600043C300000000004027B0010000000040D0 +:106270002DB001000000004011B001004D84350137 +:10628000863000006D00004061990100568428B1FD +:10629000303000004E84224D757D00000000001655 +:1062A00080B20100DD84A740116C000000000041B5 +:1062B00043C301000400A240276C0000F0840040AA +:1062C00081B200006D000040619901005684A8B1C0 +:1062D000123000000000001680B201006084A74068 +:1062E000116C00000000004143C3010000000009E0 +:1062F00010B00100000000182CB00100DE070043C0 +:1063000080CE01004E84AA408132000065840040A6 +:1063100081B2000040003E4327E001000000000978 +:10632000F0B1010000000018E0B1010000000041E0 +:1063300027C001004E84A30B8750000000001540C9 +:106340001BB001000000004023B001000400A203C4 +:10635000486D0000120000002AC8010040002D40D6 +:1063600039B001006F84A240276C000022000008B1 +:1063700012C801000400A216306C0000DE070040C5 +:10638000259801007284004081B20000000000F8EE +:1063900012B00100000000F030B001000000000B5E +:1063A00025B001000000001032B0010014002001EF +:1063B000E0B10100EE070040379801007784230127 +:1063C000366C00000000000136B00100828482417A +:1063D000234000002080001042C901007E8422403A +:1063E000E36D00000000004361B1010040000010B7 +:1063F00062DD01007B84A840813200002383008895 +:106400001CB00000F3940043233001000000001092 +:1064100032B001000000004123B001000000000381 +:1064200048B101000080001944C90100938422454D +:106430001F7C00000400A241236C00000400A20B9A +:10644000256C00000000004CF1B1010000000009C3 +:10645000F0B1010000000018F0B10100000000439D +:1064600061B101002000001962DD01008A84A815D5 +:10647000E03100000000005003D001000000005097 +:1064800033C001000000004C25D001000C002D4C51 +:1064900013C001000000005037D001000000005080 +:1064A0002BC00100778400451F8000009584A31253 +:1064B000366C00009684681B28B00000000068124B +:1064C00028B0010000000009F0B101000000001830 +:1064D000F0B101000000004361B10100200000198B +:1064E00062DD01009984A815E0310000C184221406 +:1064F000025000000000005033C0010000000014F2 +:1065000024D001000C002D1412C00100B984A21483 +:1065100036500000A984225C1F7C000030800010EF +:1065200042C90100A7842240E36D00000000004240 +:1065300061B101004000001062DD0100A484A840A8 +:1065400081320000238300881CB00000000000039B +:1065500048B101000C002D5C1F800100100000F00C +:106560002AC801000000005C2B80010004002250BA +:106570002B6C0000F007004037980100AF84230126 +:10658000366C00000000000136B00100BA84221B06 +:10659000026C00003000001048C9010000002E5CB1 +:1065A0001F90010000000050F1B101000000000345 +:1065B000F0B10100FF070015E08D0100000000426E +:1065C00061B10100A00000A462DD0100B684A84012 +:1065D00081320000BA84000348B1000000000014BA +:1065E0002AC001007784A240256C00000000004111 +:1065F00039C0010004002013386C000040003D4306 +:1066000039E001000000000B25B00100000000F897 +:1066100012B00100778400F030B000000400A25CEA +:106620001F7C00000080001942C90100C88422407C +:10663000E36D00000000004361B10100400000195B +:1066400062DD0100C584A8408132000023830088F8 +:106650001CB00000F39400402B30010018002E0302 +:1066600048B10100CC8422502F7C0000000000566D +:10667000179001000700001798880100CF84A241FD +:10668000996C00000000005517900100D28422434D +:106690002F7C000000000054179001001600201D00 +:1066A000E4B10100D484A340276C0000D684605F6D +:1066B000179000000084000B16DC0100000060133E +:1066C000169401000097005E051001000400A2402E +:1066D0000F6C00000688A25F2F7C0000148000036E +:1066E00042C90100000000F202B0010086930001DF +:1066F000384301000688004081B200000400A20374 +:10670000486D00000400224D757D0000000000402F +:1067100083B001000000004D61B1010000000016CF +:1067200080B2010004002740116C00000000001638 +:1067300062B10100E384A84081320000000000083B +:1067400062B10100E584A84081320000F084221388 +:10675000826C000040003D4383E00100000000F82F +:1067600010B00100000000F02CB001000000001685 +:1067700062B10100EB84A8408132000000000008F3 +:1067800062B10100ED84A84081320000E78400413D +:1067900083C000000000154081B20100008200A605 +:1067A00004B00100A0980040479901003005004165 +:1067B00089300100A595005295300100AC95004B41 +:1067C00002B00000068800400FB000000000005F2B +:1067D00001800100100000000EF4010004002640BA +:1067E000813200003F0000000088010005040040E5 +:1067F00089980100099900008A3001000300000710 +:106800001AF401001895000716300100088522418E +:10681000816C000003852242816C00002383008884 +:106820001CB000000785225F0F7C00000000005FA5 +:106830000F800100060400408998010009990000BA +:106840008A300100F08700400FB000001785A25A7F +:106850001F7C00000400A25A1F7C000000B5000D40 +:1068600042C901000400220BE67D000000B7000DC4 +:1068700042C901000400220BE67D00007094004034 +:106880008132010017852220856C000012859C0F43 +:1068900080320000238300881CB000008D95005CCE +:1068A0001F000100C8970042613101002383008866 +:1068B0001CB00000900400079630010000002D0578 +:1068C00048B101000400A24BE17D000000002D054D +:1068D00048B10100000000F018B001001C85223A08 +:1068E000016C0000000000008EB001006C890040C7 +:1068F00001B000000000004081B201002E002D0513 +:1069000048B101002185A240E76D00000A00004067 +:106910008F9801006C89004001B000001D94004078 +:106920008132010004002200803200003504004062 +:1069300089980100099900008A3001008D96009520 +:1069400003300100238300881CB0000000002D03E9 +:1069500048B1010022002DF02EB0010004001F17E5 +:1069600080320000282000A696B001002E85221754 +:10697000960400005B97004B953001006C89004C39 +:106980008FB0000030858317803200000000004483 +:1069900043C10100328585178032000000000048A5 +:1069A00043C10100280000F602CC0100120000A142 +:1069B0002AC801005D96004081320100AF9300417A +:1069C000813001006C89004081B2000000000001AC +:1069D00000D0010000002E1048B101002800004046 +:1069E000F199010000000003F0B101000000000077 +:1069F000F0B101003C8564476131000000000010E7 +:106A000062B101003D85A81BE0310000238374883A +:106A10001CB000000000004503E001000400A005D8 +:106A2000036C00000400A309036C000008002D03A0 +:106A300048B101006E8501FB08300000D88587FB56 +:106A400022300000000000FA0EB00100000000F843 +:106A500014B00100030000071AF4010018950007A4 +:106A6000163001005F852241816C00004E85224274 +:106A7000816C0000238300881CB000005E85225FCB +:106A80000F7C0000380000047E8901005485A65F59 +:106A90000F00000031940040053001000A0400405E +:106AA00089980100099900008A3001005B85004047 +:106AB00081B20000130000408798010000002D0300 +:106AC00048B101000C002DF082B00100000000F080 +:106AD00084B001002C9600400530010008040040FD +:106AE00089980100099900008A3001000400A25C25 +:106AF0001F7C00000000005C1F900100F087004038 +:106B00000FB000006C85A25A1F7C00000400A25A3E +:106B10001F7C000000B5000D42C901000400220BDB +:106B2000E67D000000B7000D42C901000400220B01 +:106B3000E67D000070940040813201006C852220C7 +:106B4000856C000069859C0F8032000023830088DB +:106B50001CB000008D95005C1F000100C89700422A +:106B600061310100238300881CB0000090040007FD +:106B70009630010000002D0548B10100000000F032 +:106B800018B001007085210480200000718500404C +:106B900010C90000A488004B81B000009F8500430D +:106BA00081B00000A38500FB22B00000A488004152 +:106BB00081B000006C89004E8FB000009485005AAF +:106BC0008FB00000798500478FB00000A488005383 +:106BD00081B00000A488005681B0000032002D056D +:106BE00048B101000704004089980100099900009C +:106BF0008A3001003C040040899801000999000A8C +:106C00008A3001003D0400408998010018000011FD +:106C10008AE40100099900F28A1401000000004092 +:106C200081B201006C89A00AE46D00008785A24151 +:106C3000197C00008685220A803200006C8900538E +:106C40008FB000006C8900548FB000009085220A3C +:106C5000803200008A85A20AE46D00006C89005D24 +:106C60008FB00000000000F280B001000000000AB8 +:106C700080D001008E85A091816C00006C89005E3F +:106C80008FB00000250000408F9801006C89004003 +:106C900081B2000092852091E56D00006C8900545E +:106CA0008FB00000210000408F9801006C890040E7 +:106CB00081B2000032002D0548B1010007040040F8 +:106CC00089980100099900008A3001003C040040C5 +:106CD000899801000999000A8A3001003D040040AA +:106CE00089980100099900F28A30010000000040F3 +:106CF00081B201006C89A00AE46D0000240000400C +:106D00008F9801006C89004081B2000037002D058A +:106D100048B10100040000F382F40100A488A042FD +:106D2000836C0000A488005481B00000000000F2D1 +:106D30000EB00100040023400F6C0000040020AAE4 +:106D40000F6C0000090400408998010009990000B7 +:106D50008A300100030000071AF4010000B5000D9D +:106D600042C901000700000716880100B185220B07 +:106D7000E67D00000A000040879801007F980040EF +:106D80008132010004001C0F80320000000000402E +:106D90000FB00100F087005C1F900000C3852250F7 +:106DA000FD7F0000BE85A254FD7F0000B685225500 +:106DB000FD7F00008200004087980100AD85004003 +:106DC00081B2000004002253FD7F00001480000304 +:106DD00042C90100000000F096B001001000004B15 +:106DE00080F401000CBC004087980100BE8522435E +:106DF000806C0000FFFF004B80880100AD85A2433E +:106E0000806C00007C96004047990100BF85464099 +:106E100081320000C285A0F0306F0000B4851E40B2 +:106E200081B2000000001E4131C301007F94004088 +:106E300025300100C7859C0F803200002383008825 +:106E40001CB000008D95005C1F0001001480000341 +:106E500042C901000400225A1F7C0000000000F01B +:106E600096B0010000002F0548B101001000000796 +:106E700018E401000008000CE099010090040007EC +:106E80009630010000B5000D46C90100CF853040A5 +:106E9000813200000400A20BE67D00000000000B20 +:106EA000E6910100000200A146C901000400A20B06 +:106EB000E67D00000000000BE691010004002E05B5 +:106EC00048B1010000001040E1B10100A488004079 +:106ED00081B00000000000FB28B00100000000FBB2 +:106EE00086B00100000000F814B00100E3852246DE +:106EF000237C000004002240876C0000DF852240D4 +:106F0000877C0000000000481F900100E1852241BD +:106F1000877C0000000000471F900100E3852242AB +:106F2000877C0000000000451F9001000400224003 +:106F3000097C0000E485661B2C300000000000A0E6 +:106F400013B001000000764141C301001686239270 +:106F5000156C00001686A2451F7C00001C86224B83 +:106F6000FD7F0000170000D0A2C901000000004012 +:106F700027B001000200000A24C80100BF940040AD +:106F80000F3001001486220840300000000000414C +:106F9000A3C10100F007001224CC0100ED85AA4135 +:106FA000274000000400A349276C000001000013E3 +:106FB00080CC01000E8626402330000000000040F7 +:106FC00083B001006000000384C8010010000010BD +:106FD00048CD0100170000D0A2C90100FB85A240E6 +:106FE000836C00000786004183B0000000800042EF +:106FF00044990100000068213896010000002E50DD +:1070000049C101000086A244236C00003000000347 +:1070100048C9010000000044F1B101000C0000204B +:10702000F0C901000000004461B10100A00000A40B +:1070300062DD01000386A842E03100000000004448 +:1070400085C001000000004123C001000000004194 +:10705000A3C10100F985A241815000000E862240A3 +:10706000236C00000000004461B1010040000010EA +:1070700062DD01000B86A840813200002383008876 +:107080001CB000000B040040899801000999000021 +:107090008A3001000000000348B10100EE07004003 +:1070A00025980100170000D02AC801002786001784 +:1070B00010B000000A970040813201001C86004099 +:1070C00081B20000BF940092253001000000004012 +:1070D00031B001000B0400408998010009990000BB +:1070E0008A3001001C8622082E30000027860041CD +:1070F00027B00000808000A604B001000600004018 +:10710000879801007F98000A8C30010004001C0F52 +:1071100080320000000000400FB001000000005C61 +:107120001F9001000400A09F136C00002686229F80 +:10713000136C0000020000881CCC01002783004073 +:1071400081B20000F08700413FC300000000004012 +:107150000FB001002800000180CE01003B862A40CC +:10716000813000000080001044C901004000004050 +:10717000819801003086A2481F7C00003086A2471B +:107180001F7C00003086A307036C000080000040D5 +:10719000819801003386A340026C000028000001A2 +:1071A000F0CD0100358600400FB0000028000040FF +:1071B000F0CD0100040000400ECC010028000003C7 +:1071C000F0C9010028000000F0C90100000000160D +:1071D000E0B101000000004761B101002000001093 +:1071E00062DD01003986A85C1F1000000400220A3D +:1071F000803200000400A203486D0000000000403F +:1072000043990100000000F008B00100A0012D40EA +:1072100000C001001C87220F420500004E869C0F13 +:10722000803200000000005C1F8001000080001020 +:1072300042C9010049862240E36D0000000000477A +:1072400061B101004000001062DD01004686A840E7 +:1072500081320000238300881CB000004E86220784 +:10726000803200000000000342B10100000000076E +:1072700042C10100008000A1469901000000005FAA +:10728000E1910100C006A2451F7C00001000000330 +:1072900048C9010000002D5429C00100000000F879 +:1072A00018B00100000000F804B00100000000F870 +:1072B0000EB0010004002640813200000400A25FED +:1072C0000F7C00003E00001480CE01000400AA40A4 +:1072D00081320000420000030AC801000C0000A433 +:1072E0000CC8010016950040813201000000001416 +:1072F00002B001000000001424D0010000000014BE +:1073000010C001001200000810C801000000004079 +:1073100023B00100FE7F000544C901000400A2A2C1 +:10732000860600000000000AE4B101007C8622010C +:107330008032000000003C4423E0010000002EA445 +:1073400080B001000000001048C101006986A30759 +:10735000026C00006A8668011AB00000000068072D +:107360001AB001000000000D02D00100000000056D +:10737000F0B101000000000CF0B1010000000002BB +:10738000E0B101000000000D0AC001007686224035 +:10739000036C000076862242236C0000000000414E +:1073A00023C001000000004761B10100A00000A45B +:1073B00062DD01009C862840813200007386004017 +:1073C00081B200000000001080C0010000000047F2 +:1073D00061B101000000004062B101007886A84060 +:1073E00023300000238300881CB000009C860040EE +:1073F00081B2000000003C4423E00100000000A432 +:1074000086B0010000002E1048C101008186A31241 +:107410000E6C0000828660071AB000000000601247 +:107420001AB001000000680D16940100FFFF000B68 +:1074300016D801001B990008983001000000680868 +:107440003E9601000000000CF0B1010000000002B7 +:10745000E0B101000000001086C0010000000046FD +:1074600061B101002000004362DD01008A86A85C52 +:107470001F100000BC86220D146C00009086220DA7 +:10748000246C00000000000D10C001009586000D66 +:1074900024D000000400224BFD7F000000000041CA +:1074A0002BC0010000000015A2B101001000002057 +:1074B00010C80100F007004025980100978622427D +:1074C000236C00009C86004123C0000000000046A1 +:1074D00061B101004000001062DD01009886A85CE7 +:1074E0001F000000238300881CB000000000004043 +:1074F00023B00100BC86220D14500000BB86A20DF3 +:107500000E500000A88622461F7C000000000046A6 +:107510001F8001003080001042C90100A686224071 +:10752000E36D00000000004761B101004000001061 +:1075300062DD0100A386A840813200002383008819 +:107540001CB0000020800003469901000000005F8D +:10755000E191010000002D0648B10100000000F893 +:1075600018B00100000000F804B00100040022F08F +:107570000E300000AE86A25F0F7C00006386004CD8 +:107580000DC0000000002E5F0F80010063862307FE +:10759000146C00000400A2461F7C000030000010A4 +:1075A00048C9010024000040F199010000000003D7 +:1075B000F0B1010000000000F0B101000000001671 +:1075C000F0B101002400000000C8010000000047E5 +:1075D00061B10100A00000A462DD0100B886A846E8 +:1075E0001F100000638600030CB000006386000DCE +:1075F00018C0000004002E140AD00100120000057B +:1076000048CD0100FE7F000542C901000400A2A48C +:10761000860600000400A2A1860600000C002AF2E3 +:10762000E0B10100C4862240316C00000000601807 +:10763000389601001E00004043990100008100F6C9 +:1076400080CE0100C886A6408132000000000044C0 +:1076500043C10100CA86220BED6D0000080000A1A5 +:1076600042C90100020000A146C901000400A2A114 +:10767000860600000F0000FA948801000400A2456D +:10768000956C00000200004A86E40100000000F64C +:107690000EB00100D48622471F7C000004001F4367 +:1076A0000E500000D486A0460F40000000000041AC +:1076B0000FC00100D88622481F7C00000000004057 +:1076C00091B0010004000FA242310000DB860040AF +:1076D00089B000000C0000A242C901000000004374 +:1076E00089B001000000004395D00100000000FCBB +:1076F00082B00100DE86A041904000000000004101 +:1077000091C00100E38622471F7C0000E386A0436E +:10771000896C0000E3862045896C0000E386A04167 +:107720000E400000000000410FC0010000000041B9 +:1077300089C00100DB86A24195500000F0862248F6 +:107740001F7C00001000004892F40100FFFF004879 +:1077500090880100EA8690489240000000000041B5 +:1077600093C001000A0000A244C901000000662085 +:1077700093A401000A00004380CC0100000000A295 +:1077800080C001000400A240426D00000400A2A1DC +:10779000860600000400A2461F7C00001B9900170B +:1077A00098300100FF0700177E8901000400A64001 +:1077B000813200003080001044C901001200001422 +:1077C000F0C9010000000017F0B10100120000052F +:1077D000E0CD01003000001080C80100000000442E +:1077E00061B101002000004062DD0100FA86A8407E +:1077F000813200000587225C1F7C000000003C44B1 +:1078000023E0010000002D1048C101000487224040 +:10781000E36D00000000004661B10100400000106F +:1078200062DD01000187A8408132000023830088C7 +:107830001CB000000000005C1F8001000887A24708 +:107840001F7C00000C9500408132010088870017E2 +:1078500010B00000139500408132010000002F039A +:1078600048B101000C87A00716400000000000414D +:1078700017C001000000000BE4B10100000000503F +:1078800017F00100108790F2164000000000004140 +:1078900017C001000000662017A4010010000014AA +:1078A0002AC80100000000502BE00100000000F297 +:1078B0002A9401003080001042C901001A8722403A +:1078C000E36D00000000004461B1010040000010C1 +:1078D00062DD01001787A840813200002383008801 +:1078E0001CB000000080001710DC010088870040F9 +:1078F00081B2000024879C0F803200000000005CF1 +:107900001F8001000080001042C90100248722402E +:10791000E36D00000000004761B10100400000106D +:1079200062DD01002187A8408132000023830088A6 +:107930001CB00000298722078032000000000003ED +:1079400042B101000000000742C10100008000A117 +:10795000469901000000005FE191010004002E0340 +:1079600048B101000000000AE0B101002E8722406A +:10797000316C00000C0000404599010000006018C7 +:107980003896010000002E1048B1010000000050A0 +:10799000F1B1010000000008F0B101000000000397 +:1079A000E0B101000000004461B1010000000010DE +:1079B00062B101003387A840233000002383008890 +:1079C0001CB0000000002D5211C001001000000387 +:1079D00048C90100000000F818B00100000000F8DC +:1079E00004B00100000000F80EB001000C0000A47B +:1079F0000CC8010004002240156C000000003C444B +:107A000023E00100000000A486B0010000002E1059 +:107A100048C101004287A3120E6C0000438768072B +:107A20001AB00000000068121AB001001B9900088B +:107A3000983001000000004081B2010000000010F9 +:107A400086C00100000068083E9601000000000C9E +:107A5000F0B1010000000002E0B1010000000046AA +:107A600061B101002000004362DD01004A87A85C8B +:107A70001F1000007C87220D146C00005087220D1F +:107A8000246C00000000000D10C001005587000D9F +:107A900024D000000400224BFD7F000000000041C4 +:107AA0002BC0010000000015A2B101001000002051 +:107AB00010C80100F00700402598010057872242B6 +:107AC000236C00005C87004123C0000000000046DA +:107AD00061B101004000001062DD01005887A85C20 +:107AE0001F000000238300881CB00000000000403D +:107AF00023B001000400220D145000007B87A20D6A +:107B00000E500000688722461F7C000000000046DF +:107B10001F8001003080001042C9010066872240AA +:107B2000E36D00000000004761B10100400000105B +:107B300062DD01006387A840813200002383008852 +:107B40001CB0000020800003469901000000005F87 +:107B5000E191010000002D0648B10100000000F88D +:107B600018B00100000000F804B00100040022F089 +:107B70000E3000006E87A25F0F7C00003C87004C37 +:107B80000DC0000000002E5F0F8001003C8723071E +:107B9000146C00000400A2461F7C0000300000109E +:107BA00048C9010024000040F199010000000003D1 +:107BB000F0B1010000000000F0B10100000000166B +:107BC000F0B101002400000000C8010000000047DF +:107BD00061B10100A00000A462DD01007887A84621 +:107BE0001F1000003C8700030CB000003C87000D14 +:107BF00018C000000400A2461F7C00008687225C9B +:107C00001F7C00000000005C1F80010000003C445D +:107C100023E0010000002D1048C1010086872240AA +:107C2000E36D00000000004661B10100400000105B +:107C300062DD01008387A840813200002383008831 +:107C40001CB000000000001710B001008887004041 +:107C50002BB00000008000034499010000000004E4 +:107C6000E0B1010004002640813200000400A09F22 +:107C7000136C00008F87229F136C000002000088A5 +:107C80001CCC01002783004081B200009498004181 +:107C90003F430100000000408DB0010000000040A3 +:107CA00005B001007F9800400F3001000400A25C85 +:107CB0001F7C00000688005C1F9000001000000080 +:107CC0000EF4010004002640813200000000003A5A +:107CD000018401009B872250016C00000D040040CC +:107CE00089980100099900008A300100030000070B +:107CF0001AF401001895000716300100A6872241EA +:107D0000816C0000A1872242816C000023830088DF +:107D10001CB00000A587225F0F7C00000000005F00 +:107D20000F8001000E0400408998010009990000AD +:107D30008A300100F08700400FB00000B387A25ADC +:107D40001F7C00000400A25A1F7C000000B5000D3B +:107D500042C901000400220BE67D000000B7000DBF +:107D600042C901000400220BE67D0000709400402F +:107D700081320100B3872220856C0000B0879C0F00 +:107D800080320000238300881CB000008D95005CC9 +:107D90001F000100C8970042613101002383008861 +:107DA0001CB00000900400079630010000002D0573 +:107DB00048B10100000000F018B001000000000010 +:107DC00080B00100A488A25F816C0000A8002D4350 +:107DD0001980010037002DF024B00100040000F3E9 +:107DE0008EF401000F0000F3908801000400A3430B +:107DF0008F6C00000400A343916C0000C4872248EC +:107E00008E6C0000360000404399010058003D434D +:107E1000E7E10100C4871FF0246C0000C387234101 +:107E20008F6C0000A488004781B00000A48800483F +:107E300081B000004000004043990100B0002DF0E7 +:107E400014B00100C987220A904000005F980040EA +:107E500091300100A488A24080320000B0002D457E +:107E600081B00100D58722F02C300000A3002D3016 +:107E700083B00100AC002DF382E00100CF87A34165 +:107E80002C6C00000000001682B0010098002DF05C +:107E900082C0010088002DF082D00100000000F2B5 +:107EA00098E80100A488204C826C00007C002D41E1 +:107EB00098E80100A48820F0986C0000F087220A5E +:107EC000803200004002000C7E890100F087A6404D +:107ED00081320000A488004981B00000200000A683 +:107EE00080B00100DD872243216F00001380004035 +:107EF00080DC0100DE87004081B200001A80004073 +:107F000080DC0100DE87A25E0B7D000000000040E7 +:107F100008B10100E0879F8580320000E4870040BF +:107F200081B200001A832240577D0000010000400A +:107F300057990100E487424081320000000000446C +:107F40009393010001831A5B69930000EA8722463C +:107F5000F37F0000EA87A241F37F0000C680004261 +:107F600097330100040000CB81C80100ED87224057 +:107F7000F27F0000C680006F97330100EF87224038 +:107F8000737D0000E08000418BB30000E787004074 +:107F900081B20000F7879C0F803200000080001043 +:107FA00042C90100F7872240E36D00000000004550 +:107FB00061B101004000001062DD0100F487A840BB +:107FC00081320000238300881CB000003494220218 +:107FD00080320000F88742408132000000000044F7 +:107FE0009393010034941A026897000002889C0F52 +:107FF000803200000080001042C901000288224047 +:10800000E36D00000000004561B101004000001078 +:1080100062DD0100FF87A8408132000023830088D1 +:108020001CB00000449422028032000003884240C9 +:1080300081320000000000449393010044941A022E +:10804000689700000D889C0F8032000000800010AF +:1080500042C901000D882240E36D00000000004588 +:1080600061B101004000001062DD01000A88A840F3 +:1080700081320000238300881CB000002F8322027D +:10808000803200000E88424081320000000000442F +:108090009393010000001A02689701002F830040AB +:1080A00005B00000008000A656B1010056952F4093 +:1080B00005B001000400A240E76D0000B89429411A +:1080C000E7B1010000000054EF930100000000F24E +:1080D0000EB001000400A30C556F00002900004001 +:1080E0000D9801000900000712E40100000000A73C +:1080F00013C00100030000071AF401000700000785 +:1081000016880100FFFF001034D8010000000003B2 +:10811000349401000000004023B00100201800400A +:1081200011980100040020AA0F6C000000B5000D9A +:1081300042C901004688220BE67D00002588604088 +:1081400081320000FFFF0007848901002E8805C2EC +:1081500024300000580400408132010000002D0549 +:1081600048B10100638870F0183001001000000C65 +:1081700082F401000400A2410E6C00004688004019 +:1081800081B200000000704081B201003D88A0482B +:10819000236C00000000005035D001000080001A60 +:1081A00042C9010037882240E36D00000000004210 +:1081B00061B101004000001A62DD01003488A8406E +:1081C00081320000238300881CB00000209800400A +:1081D00043990100638800F8183001003888A241F3 +:1081E00023500000FFFF001034D8010000000003FE +:1081F00034940100201800401198010000002E1A4C +:1082000048B1010000000044F1B101000000000885 +:10821000F0B101000000004261B101002000001A2D +:1082200062DD01004188A809E03100000000004142 +:1082300023C001000000005035C0010000000044D0 +:1082400011C00100528822410D5000000000004181 +:108250000FC001004E88A0AA0F6C00000000004172 +:108260000FB001000900000712E40100000000A7A0 +:1082700013C00100000000401BB001002288004133 +:1082800017B000000002000912C8010022888341D3 +:10829000174000000000004017B001002288004194 +:1082A0001BC000005D882340236C000000000050CC +:1082B00035D001000080001A42C901005A882240CE +:1082C000E36D00000000004261B101004000001AAF +:1082D00062DD01005788A8408132000023830088B6 +:1082E0001CB000002098004043990100638800F80A +:1082F000183001005B88A2412350000000000041BB +:108300000FC001006088A0AA0F6C000000000041AF +:108310000FB00100B8942007E4B101005695204049 +:10832000E7B10100F08700400FB00000FFFF000C34 +:1083300080D801000400264081320000C002000CF9 +:108340007E8901007C882654613100006F88870C8B +:10835000803200001F040040899801000999000C38 +:108360008A3001000000005461B101000F0000409C +:10837000629901006F882840813200000400A254F5 +:10838000777D00006B88004081B20000778822462C +:10839000197C00002A040040899801000999000C0A +:1083A0008A3001000000005461B101000D0000405E +:1083B000629901000000A84081B200000400A254AC +:1083C000777D00007088004081B200007C882249DF +:1083D000197C00000E000040629901000000A840D6 +:1083E00081B200000400A254777D0000778800402D +:1083F00081B2000010000040629901000000A84016 +:1084000081B200000400A254777D00007C88004007 +:1084100081B2000030942F55F1930100004000A676 +:1084200056B101002F83A241E551000064000040D5 +:10843000E599010084884440813200008788A29336 +:10844000576F00000000004157C3010000001CAB43 +:1084500027B301002F832250FD7F00002F8322517C +:10846000FD7F00002F83A2411D53000050460040B5 +:108470001D9B010038050040813201000E000048BC +:10848000B2CB010010040040493101009388224022 +:10849000B56F00000E000048B2CB0100200400417F +:1084A000B55301002F83004081B20000000000514D +:1084B000FD83010040160040459901004005004041 +:1084C000493101001E000048B2CB010010040040F9 +:1084D00081320100000000DA91C001000400004870 +:1084E000B2CB010020040040B533010060162040EB +:1084F000E5B1010055820040B53301000800004895 +:10850000B2CB0100FFFF004AB48B01002004004001 +:10851000813201000A000048B2CB01001000004A7D +:10852000B4F7010020040040813201002F83004095 +:1085300081B200000400A205486D00000200004066 +:10854000439901000400A2F20E6C00000400A20294 +:10855000803200000500004043990100000000F354 +:1085600008B00100AE882250816C00000F0400406A +:1085700089980100100000408AE401000999000474 +:108580008A14010004002048096C000004002057F0 +:10859000816C000004002040E6B1010003000040AF +:1085A00096E401000000000496C00100B488004B6E +:1085B00010C90000E48B004109B000000400002055 +:1085C0008FB00000040000208FB0000004000020E5 +:1085D0008FB00000040000208FB0000004000020D5 +:1085E0008FB00000040000208FB0000004000020C5 +:1085F0008FB00000040000208FB00000198C0041F3 +:1086000009B00000040000208FB00000040000202A +:108610008FB00000040000208FB000000400002094 +:108620008FB00000040000208FB000000400002084 +:108630008FB00000040000208FB000000400002074 +:108640008FB00000558C004509B00000558C0045E6 +:1086500009B00000558C004509B00000558C00455C +:1086600009B00000040000208FB0000004000020CA +:108670008FB00000040000208FB000000400002034 +:108680008FB000009C8C004309B00000CB8C0043ED +:1086900009B00000CF8C004409B000003E8E0045B8 +:1086A00009B00000040000208FB00000040000208A +:1086B0008FB00000040000208FB0000004000020F4 +:1086C0008FB00000040000208FB00000DF8C00435A +:1086D00009B00000DD8C004309B00000E08B0045CC +:1086E00009B00000040000208FB00000040000204A +:1086F0008FB00000040000208FB0000004000020B4 +:108700008FB00000988D004209B00000988D0043A2 +:1087100009B00000988D004409B00000E08B0045CE +:1087200009B00000040000208FB000000400002009 +:108730008FB00000040000208FB000000400002073 +:108740008FB00000040000208FB00000B88D0043FF +:1087500009B00000040000208FB00000E08B00454D +:1087600009B00000040000208FB0000004000020C9 +:108770008FB00000040000208FB000000400002033 +:108780008FB00000040000208FB00000E08D004397 +:1087900009B00000E08D004409B00000E08B004506 +:1087A00009B00000040000208FB000000400002089 +:1087B0008FB00000040000208FB0000004000020F3 +:1087C0008FB00000040000208FB00000E08D004258 +:1087D00009B00000040000208FB00000E08B0045CD +:1087E00009B00000040000208FB000000400002049 +:1087F0008FB00000040000208FB0000004000020B3 +:108800008FB00000040000208FB000000F8E0044E5 +:1088100009B00000040000208FB00000E08B00458C +:1088200009B00000040000208FB000000400002008 +:108830008FB00000040000208FB000000400002072 +:108840008FB00000E08B004209B00000228E00458E +:1088500009B00000228E004509B00000E08B004501 +:1088600009B00000040000208FB0000004000020C8 +:108870008FB00000040000208FB000000400002032 +:108880008FB00000248E004209B00000248E004307 +:1088900009B00000248E004409B00000248E004579 +:1088A00009B00000040000208FB000000400002088 +:1088B0008FB00000040000208FB0000004000020F2 +:1088C0008FB00000040000208FB0000004000020E2 +:1088D0008FB000002F8E004409B00000E08B0045EF +:1088E00009B00000040000208FB000000400002048 +:1088F0008FB00000040000208FB0000004000020B2 +:108900008FB00000418E004209B00000308E00435D +:1089100009B00000418E004409B00000E08B004522 +:1089200009B00000040000208FB000000400002007 +:108930008FB00000040000208FB000000400002071 +:108940008FB00000040000208FB00000438E004371 +:1089500009B00000378E004409B00000E08B0045EC +:1089600009B00000040000208FB0000004000020C7 +:108970008FB00000040000208FB00000E08B0041A9 +:1089800009B00000968D004209B00000968D0043AA +:1089900009B00000968D004409B00000E08B00454E +:1089A00009B00000040000208FB000000400002087 +:1089B0008FB00000040000208FB00000E08B004169 +:1089C00009B00000458E004209B00000458E00430A +:1089D00009B00000458E004409B00000E08B00455E +:1089E00009B00000040000208FB000000400002047 +:1089F0008FB00000040000208FB0000004000020B1 +:108A00008FB00000040000208FB0000004000020A0 +:108A10008FB00000040000208FB000004C8E004595 +:108A200009B00000040000208FB000000400002006 +:108A30008FB00000040000208FB000004E8E004276 +:108A400009B00000040000208FB0000004000020E6 +:108A50008FB00000040000208FB000000400002050 +:108A60008FB00000040000208FB000000400002040 +:108A70008FB00000040000208FB000000400002030 +:108A80008FB000005B8E004309B00000C18E004330 +:108A900009B00000CF8C004409B000003E8E0045B4 +:108AA00009B00000040000208FB000000400002086 +:108AB0008FB00000040000208FB0000004000020F0 +:108AC0008FB00000040000208FB00000C98E00436A +:108AD00009B00000CF8C004409B000003E8E004574 +:108AE00009B00000040000208FB000000400002046 +:108AF0008FB00000040000208FB0000004000020B0 +:108B00008FB00000040000208FB00000DD8E004315 +:108B100009B00000040000208FB00000E08B004589 +:108B200009B00000040000208FB000000400002005 +:108B30008FB00000040000208FB00000040000206F +:108B40008FB00000968C004309B00000C58E004332 +:108B500009B00000CF8C004409B000003E8E0045F3 +:108B600009B00000040000208FB0000004000020C5 +:108B70008FB0000002002D0548B101000400A2F2F0 +:108B80000E6C00000400A2028032000007002D409D +:108B900081B20100000000F308B0010010040040A1 +:108BA00089980100100000478AE401000999000437 +:108BB0008A1401000400204E096C00002A000047BE +:108BC00080CE0100040024408132000006002047CE +:108BD000E6B101000400004796E4010000000047F0 +:108BE00096D001000000004796D00100000000046C +:108BF00096C001007D89004B10C90000F98E004924 +:108C000009B000000400002085B00000040000202E +:108C100085B000000400002085B0000004000020A2 +:108C200085B000000400002085B000000400002092 +:108C300085B000000400002085B000000400002082 +:108C400085B000000400002085B000000400002072 +:108C500085B000000400002085B000000400002062 +:108C600085B000000400002085B000000400002052 +:108C700085B00000328F004209B0000004000020DF +:108C800085B000000400002085B000000400002032 +:108C900085B000000400002085B000000400002022 +:108CA00085B000000400002085B000000400002012 +:108CB00085B000000400002085B000000400002002 +:108CC00085B000000400002085B0000004000020F2 +:108CD00085B000000400002085B0000004000020E2 +:108CE00085B00000398F004609B000000400002064 +:108CF00085B000000400002085B0000004000020C2 +:108D000085B000000400002085B0000004000020B1 +:108D100085B000000400002085B0000004000020A1 +:108D200085B000000400002085B000000400002091 +:108D300085B000000400002085B000000400002081 +:108D400085B000000400002085B000000400002071 +:108D500085B000000400002085B000004A8F00426A +:108D600009B000000400002085B000006D8F0042B3 +:108D700009B000000400002085B0000004000020BD +:108D800085B000000400002085B000000400002031 +:108D900085B000000400002085B000000400002021 +:108DA00085B00000678F004A09B000000400002071 +:108DB00085B000000400002085B000000400002001 +:108DC00085B000000400002085B00000748F0043CF +:108DD00009B000000400002085B00000DF8F0044CF +:108DE00009B000000400002085B00000040000204D +:108DF00085B000000400002085B0000004000020C1 +:108E000085B000000400002085B0000004000020B0 +:108E100085B00000DD8F004B09B000000400002089 +:108E200085B000000400002085B000000400002090 +:108E300085B000003D8F004109B000000400002013 +:108E400085B000003D8F004309B000003D8F004415 +:108E500009B000003D8F004509B000003D8F00467D +:108E600009B000003D8F004709B000003D8F004869 +:108E700009B000003D8F004909B000003D8F004A55 +:108E800009B000003D8F004B09B000003D8F004C41 +:108E900009B000003D8F004D09B000000400002023 +:108EA00085B000000400002085B00000489000421A +:108EB00009B000000400002085B000004890004484 +:108EC00009B000000400002085B00000040000206C +:108ED00085B000000400002085B0000004000020E0 +:108EE00085B000000400002085B0000004000020D0 +:108EF00085B000004890004B09B00000040000203D +:108F000085B000000400002085B0000004000020AF +:108F100085B000000400002085B00000040000209F +:108F200085B000006590004509B0000004000020F5 +:108F300085B000000400002085B00000040000207F +:108F400085B000000400002085B000007D9000473F +:108F500009B000000400002085B0000056900045D4 +:108F600009B000000400002085B0000004000020CB +:108F700085B000001593004609B0000004000020F1 +:108F800085B000000400002085B00000040000202F +:108F900085B000000400002085B00000040000201F +:108FA00085B000006D8F004609B000004A8F004672 +:108FB00009B00000658F004709B00000658F0048C8 +:108FC00009B000000400002085B00000040000206B +:108FD00085B000000400002085B00000678F004AC3 +:108FE00009B000000400002085B00000040000204B +:108FF00085B000000400002085B0000004000020BF +:1090000085B000000400002085B0000004000020AE +:1090100085B00000DF8F004509B00000748F004369 +:1090200009B00000658F004709B00000658F004857 +:1090300009B000000400002085B0000004000020FA +:1090400085B000000400002085B00000DD8F004CDA +:1090500009B000000400002085B0000004000020DA +:1090600085B000000400002085B00000040000204E +:1090700085B000000400002085B00000040000203E +:1090800085B000008490004409B000008490004244 +:1090900009B00000C98B004709B00000C98B004827 +:1090A00009B000000400002085B00000040000208A +:1090B00085B000000400002085B000008490004BC3 +:1090C00009B000000400002085B00000040000206A +:1090D00085B000003D8F004109B00000AF9000470F +:1090E00009B000000400002085B000009290004705 +:1090F00009B000000400002085B00000040000203A +:1091000085B000000400002085B0000004000020AD +:1091100085B000000400002085B00000040000209D +:1091200085B000009290004709B0000004000020C4 +:1091300085B000000400002085B00000040000207D +:1091400085B000000400002085B00000040000206D +:1091500085B000000400002085B00000040000205D +:1091600085B000009290004709B00000AF90004722 +:1091700009B00000658F004709B00000658F004806 +:1091800009B000000400002085B0000004000020A9 +:1091900085B000000400002085B0000092900047D8 +:1091A00009B000000400002085B000000400002089 +:1091B00085B000000400002085B0000004000020FD +:1091C00085B000000400002085B0000004000020ED +:1091D00085B000000400002085B0000004000020DD +:1091E00085B00000BE90004709B00000BE90004866 +:1091F00009B000000400002085B000000400002039 +:1092000085B000000400002085B0000004000020AC +:1092100085B000000400002085B00000040000209C +:1092200085B000002F91004009B000005191004727 +:1092300009B000004391004809B000008A9000473F +:1092400009B000008A90004709B000005191004722 +:1092500009B000005A91004709B000005A91004837 +:1092600009B000000400002085B0000043910048D0 +:1092700009B000008A90004709B000008A900047BA +:1092800009B000004391004809B00000040000202C +:1092900085B000000400002085B00000040000201C +:1092A00085B000004890004309B000000400002091 +:1092B00085B000004890004509B000004890004685 +:1092C00009B00000658F004709B00000658F0048B5 +:1092D00009B000000400002085B000004890004A5A +:1092E00009B000000400002085B000004890004C48 +:1092F00009B000000400002085B000000400002038 +:1093000085B000000400002085B00000AE9000474A +:1093100009B00000A090004809B0000091900047FB +:1093200009B000009190004709B00000AE900047DE +:1093300009B00000C98B004709B00000C98B004884 +:1093400009B000000400002085B00000A090004893 +:1093500009B000009190004709B0000091900047CB +:1093600009B00000A090004809B0000004000020EF +:1093700085B000000400002085B000005D9100422F +:1093800009B000000400002085B000005D91004499 +:1093900009B000000400002085B000000400002097 +:1093A00085B000000400002085B00000040000200B +:1093B00085B000000400002085B0000004000020FB +:1093C00085B000005D91004B09B000000400002052 +:1093D00085B000000400002085B0000004000020DB +:1093E00085B000000400002085B0000004000020CB +:1093F00085B000005D91004309B00000040000202A +:1094000085B000005D91004509B000005D91004607 +:1094100009B000005D91004709B000005D9100486F +:1094200009B000000400002085B000005D91004AF2 +:1094300009B000000400002085B000005D91004CE0 +:1094400009B000005D91004C09B00000040000204C +:1094500085B000000400002085B00000040000205A +:1094600085B000007A91004609B000000400002099 +:1094700085B000000400002085B00000040000203A +:1094800085B000000400002085B000007D900047FA +:1094900009B000000400002085B000007A91004669 +:1094A00009B000000400002085B000000400002086 +:1094B00085B000000400002085B0000004000020FA +:1094C00085B000000400002085B0000004000020EA +:1094D00085B000009C92004609B000000400002006 +:1094E00085B000000400002085B0000004000020CA +:1094F00085B000000400002085B000007D9000478A +:1095000009B000000400002085B000009C920046D5 +:1095100009B000000400002085B000000400002015 +:1095200085B000009C92004609B0000004000020B5 +:1095300085B000000400002085B000000400002079 +:1095400085B000000400002085B00000C5920042F4 +:1095500009B000000400002085B0000004000020D5 +:1095600085B000000400002085B000000400002049 +:1095700085B000000400002085B000000400002039 +:1095800085B00000C392004A09B00000040000202A +:1095900085B000000400002085B000000400002019 +:1095A00085B000000400002085B000000400002009 +:1095B00085B000000400002085B0000004000020F9 +:1095C00085B00000C592004609B0000004000020EC +:1095D00085B00000658F004709B00000658F004826 +:1095E00009B000000400002085B000000400002045 +:1095F00085B000000400002085B00000C392004A3E +:1096000009B000000400002085B000000400002024 +:1096100085B000000400002085B000000400002098 +:1096200085B000000400002085B000000400002088 +:1096300085B000000400002085B000000400002078 +:1096400085B000000400002085B000000400002068 +:1096500085B000006A91004109B0000004000020BC +:1096600085B000000400002085B000000400002048 +:1096700085B000000400002085B000000400002038 +:1096800085B000000400002085B000007791004202 +:1096900009B000000400002085B00000779100446C +:1096A00009B000000400002085B000000400002084 +:1096B00085B000000400002085B0000004000020F8 +:1096C00085B000000400002085B0000004000020E8 +:1096D00085B000007791004B09B000000400002025 +:1096E00085B000000400002085B0000004000020C8 +:1096F00085B000000400002085B0000004000020B8 +:1097000085B000007791004309B0000004000020FC +:1097100085B000007791004509B0000077910046C0 +:1097200009B000007791004709B000007791004828 +:1097300009B000000400002085B0000004000020F3 +:1097400085B000000400002085B000007791004C37 +:1097500009B000000400002085B0000004000020D3 +:1097600085B000000400002085B000000400002047 +:1097700085B000006590004C09B000000400002096 +:1097800085B000000400002085B000000400002027 +:1097900085B000000400002085B000007D900047E7 +:1097A00009B000000400002085B000005690004C75 +:1097B00009B000000400002085B000000400002073 +:1097C00085B000008393004609B00000040000202B +:1097D00085B000000400002085B000000A9300421C +:1097E00009B000000400002085B000000A93004486 +:1097F00009B000000400002085B000000400002033 +:1098000085B000000400002085B0000004000020A6 +:1098100085B000000400002085B000000400002096 +:1098200085B000000A93004B09B00000040000203E +:1098300085B000000400002085B000000400002076 +:1098400085B000000400002085B000000400002066 +:1098500085B000000400002085B000000400002056 +:1098600085B000000A93004509B000000A93004645 +:1098700009B00000658F004709B00000658F0048FF +:1098800009B000000400002085B0000004000020A2 +:1098900085B000000400002085B000000A93004C51 +:1098A00009B000000400002085B000000400002082 +:1098B00085B000000400002085B0000056900042F2 +:1098C00009B000001593004609B000000400002014 +:1098D00085B000000400002085B0000056900046CE +:1098E00009B000000400002085B000007D90004712 +:1098F00009B000000400002085B000001593004668 +:1099000009B000000400002085B000000400002021 +:1099100085B000001593004609B000000400002047 +:1099200085B000000400002085B000000400002085 +:1099300085B000001C93004309B000000400002023 +:1099400085B000000400002085B000000400002065 +:1099500085B000000400002085B000007D90004725 +:1099600009B000000400002085B000001C930043F3 +:1099700009B000000400002085B0000004000020B1 +:1099800085B000001C93004D09B0000004000020C9 +:1099900085B000000400002085B000000400002015 +:1099A00085B000000400002085B000003293004321 +:1099B00009B000000400002085B000000400002071 +:1099C00085B000000400002085B0000004000020E5 +:1099D00085B000000400002085B0000004000020D5 +:1099E00085B000000393004A09B000000400002085 +:1099F00085B000000400002085B0000004000020B5 +:109A000085B000000400002085B0000004000020A4 +:109A100085B000000400002085B000000400002094 +:109A200085B000003293004309B00000040000201C +:109A300085B00000658F004709B00000658F0048C1 +:109A400009B000000400002085B0000004000020E0 +:109A500085B000000400002085B000000393004A98 +:109A600009B000000400002085B0000004000020C0 +:109A700085B000000400002085B000000400002034 +:109A800085B000004A93004309B0000004000020A4 +:109A900085B000000400002085B000000400002014 +:109AA00085B000000400002085B000007D900047D4 +:109AB00009B000000400002085B000004A93004374 +:109AC00009B000000400002085B000000400002060 +:109AD00085B000004A93004D09B00000040000204A +:109AE00085B000000400002085B000004A8F0042CD +:109AF00009B000000400002085B000006D8F004216 +:109B000009B000000400002085B00000040000201F +:109B100085B000000400002085B000000400002093 +:109B200085B000000400002085B000000400002083 +:109B300085B000006D93004209B0000004000020D1 +:109B400085B000000400002085B000000400002063 +:109B500085B000000400002085B000000400002053 +:109B600085B000000400002085B000000400002043 +:109B700085B000006D8F004609B000004A8F004696 +:109B800009B00000658F004709B00000658F0048EC +:109B900009B000000400002085B00000040000208F +:109BA00085B000000400002085B000006D930046E1 +:109BB00009B000000400002085B00000040000206F +:109BC00085B000000400002085B0000004000020E3 +:109BD00085B000007493004A09B000000400002022 +:109BE00085B000000400002085B0000004000020C3 +:109BF00085B000000400002085B000007D90004783 +:109C000009B000000400002085B000007493004AF1 +:109C100009B000000400002085B00000040000200E +:109C200085B000001693004609B000000400002033 +:109C300085B000000400002085B000000400002072 +:109C400085B000001693004609B000000400002013 +:109C500085B000000400002085B000000400002052 +:109C600085B000000400002085B000007D90004712 +:109C700009B000000400002085B0000016930046E3 +:109C800009B000000400002085B00000040000209E +:109C900085B000001693004609B0000004000020C3 +:109CA00085B000000400002085B000000400002002 +:109CB00085B000000400002085B000007D930042C4 +:109CC00009B000000400002085B00000040000205E +:109CD00085B000000400002085B0000004000020D2 +:109CE00085B000000400002085B0000004000020C2 +:109CF00085B000000393004A09B000000400002072 +:109D000085B000000400002085B0000004000020A1 +:109D100085B000000400002085B000000400002091 +:109D200085B000000400002085B000000400002081 +:109D300085B000007D93004609B0000004000020BB +:109D400085B00000658F004709B00000658F0048AE +:109D500009B000000400002085B0000004000020CD +:109D600085B000000400002085B000000393004A85 +:109D700009B000000400002085B0000004000020AD +:109D800085B000000400002085B00000748F004DF5 +:109D900009B000000400002085B00000040000208D +:109DA00085B000000400002085B000000400002001 +:109DB00085B000000400002085B0000004000020F1 +:109DC00085B000000400002085B0000004000020E1 +:109DD00085B000000400002085B0000004000020D1 +:109DE00085B000000400002085B0000004000020C1 +:109DF00085B000000400002085B0000004000020B1 +:109E000085B000000400002085B0000004000020A0 +:109E100085B000000400002085B00000748F004D64 +:109E200009B00000658F004709B00000658F004849 +:109E300009B000000400002085B0000004000020EC +:109E400085B000000400002085B000000400002060 +:109E500085B000000400002085B000000400A205C9 +:109E6000486D0000040022078032000007002E4BDE +:109E700019900100FB870004E6B10000C98B224263 +:109E8000197C00000F97003A81300100C98B004017 +:109E900081B20000C98B2242197C0000FF1F000F15 +:109EA0001E8C01007396004081320100DB8B9C0FF9 +:109EB000803200000000005C1F8001000080001064 +:109EC00042C90100DB8B2240E36D00000000004529 +:109ED00061B101004000001062DD0100D88BA84094 +:109EE00081320000238300881CB000001D852202FF +:109EF00080320000DC8B42408132000000000044D0 +:109F00009393010000001A02689701001D8500402C +:109F100005B000000400A205486D000004002207FF +:109F20008032000005002E4B19900100FB870004D1 +:109F3000E6B100000000004087B0010000000040D2 +:109F40008DB001000080000342C90100400000A163 +:109F500044C90100000000F0E0B101007F98000654 +:109F6000074001000400A25C1F7C00000000000606 +:109F700007D00100D4002E5C1F90010000000007F4 +:109F8000F0B101000C80000342C90100000000F0A4 +:109F9000F0B101000000004081B20100000000FEAD +:109FA00096B00100000000FE96C00100000000F025 +:109FB000F0B101000000004081B20100000000FE8D +:109FC00096C00100000000FE96C00100000000F0F5 +:109FD000F0B101000000004081B20100000000FA71 +:109FE00096C00100000000FE96C001000030004B4A +:109FF000948801000000004695F001000000004A2E +:10A0000096C001005E012E34978401000200004BCF +:10A01000E4E5010064012040E1B10100090000070E +:10A0200086E4010000002EA787C001001000001088 +:10A0300048C9010010000040F19901005801004397 +:10A04000F0C9010058010005E0C90100000000440A +:10A0500061B10100A00000A462DD0100088CA840ED +:10A06000813200000000000548B101001A000040E4 +:10A070009798010008002E4095B00100108C204BED +:10A08000946C000000000040F1B101000D8C004113 +:10A0900095C000001080001042C90100178C2240BA +:10A0A000E36D00000000004461B1010040000010B9 +:10A0B00062DD0100138CA8408132000023830088F8 +:10A0C0001CB000000000000548B101000F970040DF +:10A0D00081300100E08B004081B200000C80000361 +:10A0E00042C90100000000F886B00100000000F83D +:10A0F00088B001001480000398C801000400A2A1E8 +:10A10000986C00001E8C444081320000218CA24CCF +:10A11000FD7F0000228C004CFD930000238C20F07A +:10A12000566F0000000000F056B3010000001C4014 +:10A1300081B2010064000040819801006400004089 +:10A1400080CC01000400A64081320000D80000400D +:10A15000819801000400A2438104000000800010E7 +:10A1600044C9010064000040F1990100700000053D +:10A17000F0C9010000000043F0B1010000000047F9 +:10A1800061B101002000001062DD01002E8CA844A6 +:10A19000E0310000100000108CC801000080004673 +:10A1A00044C9010040000040F19901006801000528 +:10A1B000F0C9010064000043F0C90100040024401C +:10A1C000813200000000004761B10100000000463C +:10A1D00062B10100378CA844E0310000238300887D +:10A1E0001CB000000900000786E4010038002EA71B +:10A1F00087C001008B002D0548B101003F8C224330 +:10A20000E77D00000000004445C10100428C22446B +:10A21000E77D00000000004C45C101000000004A3D +:10A2200019900100680120A2E4B1010088000040FB +:10A2300043990100468C230BE56D000000000041AE +:10A24000199001000080001044C901005000004036 +:10A25000F199010058010043F0C9010058010005BF +:10A26000E0C901000000004461B1010000000010DD +:10A2700062B101004B8CA84081320000238300882A +:10A280001CB000005C002E0548B1010000800003F6 +:10A2900042C90100000060F096B00100A00000403B +:10A2A000439901000400A2F2803200000F970041A0 +:10A2B00081300100E08B004081B20000588CA2493F +:10A2C000197C000086000040479901005C8C00402A +:10A2D000E5B1000086002F49198001005C8CA2F2D4 +:10A2E000803200008B0000404799010000000042CE +:10A2F000E79101005F8CA246197C0000A00000409D +:10A3000047990100638C0040E5B10000A0002F4692 +:10A3100019800100638CA2F2803200008B000040A3 +:10A320004799010000000041E79101000700004E3D +:10A3300080E401000039004080C801000400A24010 +:10A34000066C0000A80000404399010034002DF085 +:10A3500024B00100000000FB0CB00100000000FB75 +:10A3600010B00100000000FB12B001000F0000F36C +:10A3700016880100040000F314F40100938C2640B9 +:10A3800081320000798C220A166C000058003D438F +:10A3900013E00100000000F882B00100040022F088 +:10A3A000843000001B980040813201002383008824 +:10A3B0001CB000000000000548B101000000004191 +:10A3C00013C00100788CA043136C00000000004013 +:10A3D00013B001006E8C004115D00000938C220A4E +:10A3E000803200000400A208126C000058003D43B7 +:10A3F00013E00100000000F882B00100040022F028 +:10A40000843000001B980040813201004000204051 +:10A41000E1B10100238300881CB0000000000005AA +:10A4200048B10100938C224115500000000000410A +:10A4300011C00100868CA043116C00000000004098 +:10A4400011B0010004002206106C000058003D43CA +:10A4500011E00100000000F836B00100040022F015 +:10A46000003000000000005083B001005497004706 +:10A4700061310100238300881CB000003194000585 +:10A48000483101000000004561B1010040000010AA +:10A4900062DD01008F8CA840813200002383008898 +:10A4A0001CB00000828C000548B10000370020403D +:10A4B000E7B101008697005181300100E08B004038 +:10A4C00081B2000037000040439901000400A2F36C +:10A4D0008032000034002E41F5B10100001100402F +:10A4E000E59901000400A248197C0000A08C0048F6 +:10A4F0001990000037000040439901000400A2F3C6 +:10A500008032000034002E41F5B1010000110040FE +:10A51000E59901000080000342C90100000000F835 +:10A5200094B00100A78C2245237C0000B0002FF0DE +:10A530008CB00100000060F08CC001007C00004085 +:10A54000439901000400A3F08C6C000090000040CF +:10A550004399010035002DF08CB0010034002DF33B +:10A5600084B00100040022F3846C000058003E43D4 +:10A5700085E00100AE8C2248197C000000000041FB +:10A580008DC001000000680A8CC0010038002A4A12 +:10A59000E0B1010028000000E0C901003C00201BE0 +:10A5A000E0B101001080000342C90100000000F882 +:10A5B00038B00100000000F826B00100040022F8C5 +:10A5C00002300000BC8C2301146C0000000000F875 +:10A5D00080B00100000000F882B001004C0020F0C3 +:10A5E000E4B1010044002040E0B1010048002041F6 +:10A5F000E0B10100A8002D1032B001005F9800F01A +:10A6000024300100C58CA244816C0000C38C22411F +:10A61000197C0000BC9500403B300100ED8CA20885 +:10A620003C300000C58C004081B20000BF94004067 +:10A6300081320100ED8CA2083C3000005000201C4B +:10A64000E0B1010054002013E0B101004E002001F0 +:10A65000E4B101004000200AE0B101008697005FEC +:10A6600081300100E08B004081B2000037000040E3 +:10A6700047990100959500F394300100A08C224A7F +:10A6800080320000D18C004081B2000037000040D1 +:10A6900047990100959500F3943001000400204390 +:10A6A000976C000058003E4397E001000000001B3B +:10A6B000F0B101001F006000008C0100E08B8511EB +:10A6C000803200000480000342C90100B0002FF076 +:10A6D0008CB00100000060F08CC001007C000040E4 +:10A6E000439901000400A3F08C6C00008697005F82 +:10A6F00081300100E08B004081B20000040022495B +:10A70000197C0000DF8C004919800000E48C224194 +:10A71000197C0000BC9500403B300100E88CA20889 +:10A720003C3000008697005F81300100E08B0040E4 +:10A7300081B20000BF94004081320100E88CA20881 +:10A740003C3000008697005F81300100E08B0040C4 +:10A7500081B2000050002D1032B0010054002DF0E5 +:10A7600038B001004E002DF026B0010040002DF25F +:10A7700002B00100000000F014B001003000001031 +:10A780008CC801000080004644C9010068012D44C6 +:10A7900061B10100100068F280C8010000000008EB +:10A7A000F0B1010058010005E0C901000000000BF4 +:10A7B00037B001000000004036D001005C012E409F +:10A7C00010C001000000000680C00100000000521F +:10A7D00081D0010018970040E431010020000046BC +:10A7E00062DD0100F98CA840233000000E95004086 +:10A7F000813201001695004081320100078D8241AF +:10A80000234000002080001042C90100048D224036 +:10A81000E36D00000000004661B10100400000103F +:10A8200062DD0100018DA840813200002383008891 +:10A830001CB000000000000548B10100000000103D +:10A8400032B001000000004123B001000080001977 +:10A8500044C901000F8D2241197C00000B8DA3011A +:10A860000C6C00000C8D000604B00000000000011C +:10A8700004B001000E8D2002366C00000000001BA9 +:10A8800004B00100128D0002E0B10000118DA3019F +:10A890000C6C0000128D000604B0000000000001E6 +:10A8A00004B001000000680216940100FFFF000BD5 +:10A8B00016D80100000068083E9601000000001C48 +:10A8C000F0B101000000004661B101002000001954 +:10A8D00062DD0100178DA813E0310000548D2202C3 +:10A8E0001450000044002D020CD001003F8DA20244 +:10A8F00002500000258D225C1F7C00002080000398 +:10A9000042C90100248D2240E36D00000000004791 +:10A9100061B101004000001062DD0100208DA840FF +:10A9200081320000238300881CB000000000000575 +:10A9300048B1010044002D5C1F80010048002DF04B +:10A9400038B001004C002DF026B0010038002FF285 +:10A9500002B00100418D2201146C00000400A440EB +:10A9600081320000338D22461F7C0000000000462B +:10A970001F80010020002D0348B10100328D2240CC +:10A98000E36D00000000004461B1010040000010D0 +:10A9900062DD01002F8DA8408132000023830088F2 +:10A9A0001CB0000038002F0548B10100000000F87D +:10A9B00094B0010038002DF096B001000000004C6A +:10A9C000E1C101002000000348C901000000224A43 +:10A9D000F1B1010044000005F0C901000000004A87 +:10A9E000F0B101000000004BE0B1010000000047A1 +:10A9F00061B10100A00000A462DD01003C8DA85CF3 +:10AA00001F100000418D000548B100000000000249 +:10AA100038C0010004002440813200004F8D22061E +:10AA2000803200000000005033C001004D8DA202B2 +:10AA3000366C000004002241197C000004008F0DD8 +:10AA400042310000040022F0803200000400225C49 +:10AA5000E17D00000400A2F06A060000100000F88A +:10AA600010C801000000005C11800100F0070040E8 +:10AA700037980100FD8C00A11AB000000000000210 +:10AA800010C00100FD8C000236D000005000201CD8 +:10AA9000E0B1010054002013E0B101004E0020019C +:10AAA000E4B101004000200AE0B101005B8D005FCD +:10AAB00001B000000400A202026C00000400A20227 +:10AAC0000C6C000037002D4601B00100040000F3BB +:10AAD00080F401005A8DA043816C000000000055F5 +:10AAE00001B0010040002040E1B1010000800019E8 +:10AAF00042C90100618D2240E36D00000000004664 +:10AB000061B101004000001962DD01005E8DA840C6 +:10AB100081320000238300881CB0000013950040A0 +:10AB2000813201003080001042C90100688D22404E +:10AB3000E36D00000000004461B10100400000101E +:10AB400062DD0100658DA84081320000238300880A +:10AB50001CB0000060012F0548B101000000000B8F +:10AB6000E4B101000000005017F001006D8D90F27B +:10AB7000164000000000004117C0010000006620E0 +:10AB800017A40100320000A62AC00100000000F254 +:10AB90002A940100708D45486131000000D0001EEC +:10ABA00062DD0100758D284005300000718D22485E +:10ABB000777D0000788D004081B200000000001514 +:10ABC00062B10100838D284081320000758D004004 +:10ABD00081B2000000001D0092B00100808D224172 +:10ABE000197C0000040022403B6C00000400A348D4 +:10ABF0003B6C00000080000342C90100C99400F8CA +:10AC0000003001007D8DA2413B500000848D004941 +:10AC100000B00000FF07001E008C0100C994004036 +:10AC200081320100848D004900B0000000001D4702 +:10AC300019800100878D225F016C00008E98004012 +:10AC400081320100AA88000080B000008E8D225C55 +:10AC50001F7C00002080000342C901008E8D22402D +:10AC6000E36D00000000004761B1010040000010EA +:10AC700062DD01008B8DA8408132000023830088B3 +:10AC80001CB000008E8D400548310000FFFF00071A +:10AC900094890100948D85CA943000008E98185CC8 +:10ACA0001F0001000E00000F1E8C0100B78700403E +:10ACB00081B200008697180080300100E08B0047C9 +:10ACC000198000000000004019800100E08B22473D +:10ACD000197C0000BF940040813201009B8DA208C6 +:10ACE00080320000E08B004081B2000018970040E5 +:10ACF0000D3001009C01004045990100FFFF000B51 +:10AD0000988801008B002D5017F00100A18D904C08 +:10AD1000164000000000004117C00100A38D22432F +:10AD2000E77D00000000004445C1010000006620EE +:10AD300017A4010068010040439901005C012EF254 +:10AD400080B00100020062407ECD0100000000578B +:10AD500081C0010000002E1048B101000300004036 +:10AD6000F08D010000000008F0B10100580100055D +:10AD7000E0C901000000004461B1010000000010C2 +:10AD800062B10100AD8DA8408132000023830088AC +:10AD90001CB000000000000548B10100B18D45481D +:10ADA000613100000050000862DD0100B78D2840CD +:10ADB00005300000B28D2248777D0000C9941D083F +:10ADC00000300100E08B004081B20000E08B1D47A5 +:10ADD000198000000400A205486D00003500004005 +:10ADE00047990100010063F384C80100BD8DA043B1 +:10ADF000856C00000000634085B00100A8000040A1 +:10AE00004399010037002FF024B00100040022F321 +:10AE10009E060000010063F382CC0100CB8DA241AD +:10AE20009E060000E08B224483700000A8000040D2 +:10AE3000439901000400A2F0246C00003600004099 +:10AE40004399010058003D43E7E10100E08B1FF00A +:10AE5000246C00008E98004881300100AA882341AC +:10AE6000836C0000AA88004781B0000034000040D5 +:10AE70004399010004002242E66D000058003D4362 +:10AE800085E00100000000F836B00100000000F08D +:10AE900000B0010004002200803200000400A20083 +:10AEA000BE06000028000040839801005497004728 +:10AEB00061310100238300881CB0000000002D03D5 +:10AEC00048B1010008002DF094B00100000000F826 +:10AED0008EB0010090002DF014B0010000000005BC +:10AEE00048B10100A88CA2408F7C0000DE8D224773 +:10AEF0008F7C00000400A248197C0000A88C004848 +:10AF000019900000040022468F7C0000608E0040F3 +:10AF100081B200000400A205486D000036002D5DDE +:10AF200005B4010037002DF380B00100000000F3EC +:10AF30008EB00100F00000477E8901000400264029 +:10AF4000813200005C003D4381E00100A8002DF04B +:10AF500094B001000400224A80320000000000F09A +:10AF600024B001002000001086DC010040800003B6 +:10AF700044C901009293004AF03101000400A25C30 +:10AF80001F7C000036002F5C1F900100F28DA25044 +:10AF90008F50000034002040E1B10100E08B004000 +:10AFA00081B20000F00000477E89010004002640C5 +:10AFB000813200000000634181C00100F78DA04391 +:10AFC000816C00000000634081B001003700204721 +:10AFD000E6B10100E08B2247803200000400004708 +:10AFE0000CF401000000004F8F8401000C8E2247FA +:10AFF0000C6C000058003D4381E001000C8E1FF0F6 +:10B00000246C00000000005C1F8001000080001024 +:10B0100042C90100058E2240E36D0000000000459A +:10B0200061B101004000001062DD0100028EA84005 +:10B0300081320000238300881CB00000058E42404E +:10B0400005300000000000449393010000001A5DE9 +:10B05000699301000A8E23410D6C0000E08D00050C +:10B0600048B100008E98000548310100AA880048C8 +:10B0700081B00000E08B22408F6C00008697005F5B +:10B0800081300100E08B004081B200004002000CE2 +:10B090007E8901000400A64081320000A200004029 +:10B0A00043990100000000F384B00100A6002D497F +:10B0B00019900100020000F280F40100B8002D4058 +:10B0C00081B20100000000F280C0010000000040D9 +:10B0D00082F8010019000040819801001D8EA040F7 +:10B0E000826C00002C010040819801001D8EA3405D +:10B0F000826C00000000004180B001001F8E204CD7 +:10B10000856C00000000004185C0010086002040E1 +:10B11000E4B10100A2002042E6B10100E08B004052 +:10B1200081B200000F97005081300100E08B004099 +:10B1300081B200000480000342C90100040022F033 +:10B1400080300000000000408DB001007F9800407A +:10B15000873001000400A25C1F7C0000B0002F5C5F +:10B160001F900100000060F080C001007C000040E2 +:10B17000439901000400A3F0806C00008697005FF3 +:10B1800081300100E08B004081B2000004000040EB +:10B1900081B20000E08B2246197C0000A000004034 +:10B1A00047990100010062F296CC0100E08BA640B5 +:10B1B000813200008697004A813001005B9700468B +:10B1C00095300100E08B004081B20000E08B224905 +:10B1D000197C00008600004047990100010062F2DE +:10B1E00080CC0100E08BA640813200008697004AA7 +:10B1F000813001005B97004795300100E08B0040F3 +:10B2000081B2000031940040813201000400A25C50 +:10B210001F7C0000E08B005C1F9000000400A24631 +:10B22000197C0000E08B004081B200000400A249BC +:10B23000197C0000E08B004081B20000BA000040A1 +:10B2400047990100010062F280C80100498E9040D8 +:10B2500080320000FFFF624081980100A40000409E +:10B2600047990100E08B2240E56D0000E08B004132 +:10B27000E5C100000F97004D81300100E08B0040D8 +:10B2800081B200005C00004047990100040022F0F8 +:10B290009630000000000040E1B101000080000392 +:10B2A00044C901000000004BE0B101000000004073 +:10B2B0008DB001007F980040873001008B00004076 +:10B2C00047990100598E80F396300000000000403D +:10B2D000E781010000000047199001000400A25C12 +:10B2E0001F7C0000E08B005C1F90000037000040D6 +:10B2F000439901000400A2F38032000034000040B2 +:10B300004599010001000040F5990100001100403D +:10B31000E5990100BF94004081320100718EA208BE +:10B32000803200003700004047990100000000F320 +:10B3300082B001000000635183D00100340000405E +:10B3400047990100010063F384CC0100698E9F429C +:10B35000803200000000634285B00100000000451B +:10B3600003F001000000000100C001006B8E375C9B +:10B37000613100000000001B62B101006C8EA84B1F +:10B38000191000000000000062B101006E8EA8409C +:10B3900081320000F087174081B200000080000376 +:10B3A00042C9010090002DF094B00100AC002DF0D6 +:10B3B00030B0010035002DF028B0010034002DF32D +:10B3C00084B00100040022F3846C000058003E4366 +:10B3D00085E0010001000018F0C901000000004AEA +:10B3E000E0B1010038002000E0B101003C00201B6A +:10B3F000E0B1010040002040E1B101000000004048 +:10B400002BB001006A9700400D30010000000018C9 +:10B4100016C00100828EA0141644000000000041F6 +:10B4200017C001000E0000A244C90100000000186E +:10B43000F8B10100B0002D14F8B101001050004027 +:10B44000879801008B8E224A197C0000003000434F +:10B4500086C801000030000B16C801008B8EA44086 +:10B46000813200000000004117C0010001006E435E +:10B4700086980100AE970030813001008F8EA04188 +:10B48000174000000000004117C00100968E224ABC +:10B49000197C0000080000A244C90100CC002DABBB +:10B4A000F9B10100000000AB17C00100958EA0F0BB +:10B4B000164400000000004117C00100000064F0C5 +:10B4C00082B00100900000404599010000006041F9 +:10B4D00031C00100BC000040439901009C8E060C65 +:10B4E00080320000A00020F2E4B10100040009460F +:10B4F000191000009C01004045990100FFFF000B5E +:10B50000988801008B002D5017F00100A18E904CFF +:10B51000164000000000004117C00100A38E224326 +:10B52000E77D00000000004445C1010000006620E6 +:10B5300017A4010068010040439901005C012EF24C +:10B5400080B00100020062407ECD01000000005783 +:10B5500081C0010000002E1048B10100030000402E +:10B56000F08D010000000008F0B101005801000555 +:10B57000E0C901000000004461B1010000000010BA +:10B5800062B10100AD8EA8408132000023830088A3 +:10B590001CB000000000000548B10100B18E454814 +:10B5A000613100000050000862DD0100B28EA84049 +:10B5B0000530000035001D4047990100010063F38C +:10B5C00084C80100B88EA043856C00000000634071 +:10B5D00085B001003700004047990100040022F3C4 +:10B5E0009E060000010063F382CC01000400A2412A +:10B5F0009E0600008B000040479901000400A24510 +:10B60000E77D000000000045E79101008697005F9C +:10B6100081300100E08B004081B200003700004023 +:10B6200047990100959500F394300100608E224AFD +:10B6300080320000D18C004081B200003700004011 +:10B6400047990100959500F3943001009A8C224AA5 +:10B6500080320000D18C004081B2000036000040F2 +:10B6600043990100000000FB12B001000F0000F33D +:10B6700090880100040000F30CF40100040026404F +:10B6800081320000CB8C2206906C00000400AA409E +:10B69000813200005C003D4313E00100A8002DF062 +:10B6A00094B0010004002240956C000037002FF098 +:10B6B00024B0010036002A50E7D1010000006341A8 +:10B6C00013C00100D88EA043136C0000000000409E +:10B6D000E7B101008F9300108630010023830088BA +:10B6E0001CB00000DA8E4205483100000000004422 +:10B6F00093930100CB8C1A5D699300000400A205AE +:10B70000486D000036002D1086B001005C003D43FE +:10B71000E7E10100A8002DF094B001000400224AE6 +:10B720008032000035002FF024B0010001006BFBD7 +:10B7300084C80100E78EA043856C000035002040DE +:10B74000E7B101000000004081B20100010063F395 +:10B7500012C80100EA8EA043136C000000000040F4 +:10B76000E7B101004080000344C901009293004A00 +:10B77000F0310100238300881CB00000ED8E4205EB +:10B7800048310000000000449393010000001A5D5E +:10B79000699301003700004047990100040022F33B +:10B7A0009E060000110063F382CC010004001F41DB +:10B7B00080320000C28D22419E060000350000400C +:10B7C0004399010058003D43E7E10100000000F803 +:10B7D00036B00100D08D00F000B000005E012D05F4 +:10B7E00048B10100FA8E65F21230000000993F4224 +:10B7F00013F00100FF8E2247E77D00002783758844 +:10B800001CB00000F98E004081B20000000000472B +:10B81000E791010000007542199001007500004099 +:10B8200061990100018FA8B10C300000A9960010A9 +:10B8300094300100238300881CB000005E012E05B7 +:10B8400048B10100C0A83D460DE0010000000040E5 +:10B8500097B001000B8F2240E16D0000040002410F +:10B8600097400000088F005043C10000178F224B03 +:10B87000803200000000624B1294010009000007B2 +:10B8800096E40100000000A797C0010030000010FE +:10B8900094C801000080004A449901000000004261 +:10B8A000F1B101005E01004BF0C901005E0100052D +:10B8B000E0C901000000004461B101002000004A1D +:10B8C00062DD0100158FA840813200000080001069 +:10B8D00044C9010000000050F1B10100040000095A +:10B8E00096E40100000068A897C00100D40000059C +:10B8F000E0C901000000004461B101000000001037 +:10B9000062B101001D8FA8408132000023830088AE +:10B910001CB0000000993F4213F00100218F6540E8 +:10B92000813200003F0000F39688010000000040D3 +:10B93000E7B101000000755561B10100000000068B +:10B9400062B10100258FA840813200002A8F224B6E +:10B95000803200000000004B62B10100288FA84037 +:10B96000813200000000009713B001000000009633 +:10B9700097B00100308F2009966C0000308F1F09AE +:10B9800096240000278300881CB000002B8F004005 +:10B9900081B200000F97005781300100C98B00056C +:10B9A00048B1000004002242197C00002E00004033 +:10B9B00043990100378F22F3803200000F97004235 +:10B9C00081300100F087004081B20000869700526C +:10B9D00081300100C98B004219800000040022421E +:10B9E000197C00000F97003A8130010086970052C1 +:10B9F00081300100C98B004081B20000000000408E +:10BA000005B001000596004095300100C98B224029 +:10BA1000956C0000240400408998010009990000F9 +:10BA20008A300100458FA2401F7C0000C99400406D +:10BA300081320100F087004081B2000004800003E1 +:10BA400042C90100000000F202B00100A5950052B9 +:10BA500095300100AC95004B02B00000F08700402B +:10BA600081B200002B98004095300100518FA20850 +:10BA700080320000518FA21680320000F0872242EF +:10BA8000197C00000000004B199001000F97003A4C +:10BA900081300100F087004081B20000002300A641 +:10BAA00016B00100548F831E803200000008000B86 +:10BAB00016DC0100000000002AC001005E970008AB +:10BAC00080300100588F005E179000007F97004380 +:10BAD000613101009E9300408D30010066970007A0 +:10BAE000161401000080001042C90100608F22403E +:10BAF000E36D00000000004361B101004000001050 +:10BB000062DD01005D8FA840813200002383008840 +:10BB10001CB000000097005E05100100C9940040B1 +:10BB200081320100648F2209803000008697004036 +:10BB300013300100D08B000548B100003C96004056 +:10BB400081320100C98B004081B200000400A24A8A +:10BB50001F7C00000000004A1F9001006C8F2243F0 +:10BB60003D7C0000000000441990010000000043EB +:10BB70003D8001006D8F0042199000000400A24F2B +:10BB80002B7C00000400A2451F7C000014002D4502 +:10BB90001F9001000400A2F0146C00000400A0013A +:10BBA000146C0000DF8F831E80320000DF8F0044A2 +:10BBB000199000002F000040439901000400A247A3 +:10BBC000E77D0000B494004081320100878FA20815 +:10BBD00080320000878FA21680320000838FA2423D +:10BBE000197C00000082000204DC0100A0980040E3 +:10BBF000479901003005004189300100808FA24142 +:10BC0000197C0000C994004081320100F087004097 +:10BC100081B20000A595001594300100AC95004B51 +:10BC200002B00000F087004081B200003C96004066 +:10BC3000813201000000004B199001000F97003A7B +:10BC400081300100F087004081B200008A8F2242DB +:10BC5000197C00003C960040813201008B8F00402F +:10BC600081B200000596004081320100C38F22415D +:10BC7000197C0000C000001598C80100C38FA00BFC +:10BC8000996C0000040022441F7C0000FF070000A4 +:10BC90007E8901000400A6408132000030000010BF +:10BCA00080C801000080004044990100000000505D +:10BCB000F1B1010000000003F0B1010000000042FA +:10BCC00061B101000000004062B10100968FA80040 +:10BCD000E0310000238300881CB000000000000554 +:10BCE00048B10100C000001598C8010030002E0BBB +:10BCF00099D0010000006A5099C001000400200B97 +:10BD0000996C0000C000620180CC01000C8000032F +:10BD100042C901002D002DF022B001000000004CAE +:10BD200080C001000000005C23800100D4003F417E +:10BD3000E7E1010004002242197C00000B0000F240 +:10BD400098E401000000005A998001000400A2005C +:10BD5000986C0000200400408998010009990011A6 +:10BD60008A3001000B000011E4F501002F0020478C +:10BD7000E7B50100AE8F230B816C00000000004F7F +:10BD8000E59101000000000880B00100C100000141 +:10BD900080CE01000400A440813200000000000BAE +:10BDA00003B001000000001502D001005E97000002 +:10BDB0002A4001000000004361B101004000001072 +:10BDC00062DD0100B58FA840813200002383008826 +:10BDD0001CB00000C994000548310100C0000001FA +:10BDE00080CE0100C18F261100300000100000003D +:10BDF0002AC801000000000880B001000000000116 +:10BE000080C00100C00000409998010000000001BE +:10BE100098D001005E97004C02300100C000004045 +:10BE200003980100CB8F004081B2000030002F0842 +:10BE300080B00100C0000015F4C90100C00000017D +:10BE4000E4CD0100C100000180CE01000400A44047 +:10BE5000813200000400200BE56D0000C0000040AE +:10BE6000039801005E9700002A400100D08F224411 +:10BE70001F7C0000AC002F4013B001000000000147 +:10BE8000E0C10100B000004047990100D18F0001DE +:10BE9000E0D100009E9300408D300100806300A639 +:10BEA00016B001006697000716140100008000100C +:10BEB00042C90100D98F2240E36D00000000004319 +:10BEC00061B101004000001062DD0100D68FA84082 +:10BED00081320000238300881CB000000097005EC0 +:10BEE00005100100DC8F2209803000008697004099 +:10BEF00081320100C98B000548B100000400A24A4C +:10BF00001F7C0000DF8F004A1F9000000400A24F3A +:10BF10002B7C00000400A25C1F7C00000400A244F3 +:10BF20001F7C00000000000010B0010024002D154F +:10BF300010C0010028002DF016B0010022002DF0E5 +:10BF400026B0010014002FF20CB001000000000127 +:10BF5000E0D101000000001032B001000000000B31 +:10BF60001BB0010004001F151A5000000000004023 +:10BF700023B00100000000012AB00100BE9600407D +:10BF800035B000002F002040E7B101002990A24504 +:10BF90001F7C00000400A205486D00002400200B57 +:10BFA000E0B1010028002013E0B1010022002006CA +:10BFB000E4B10100FD8F225C1F7C00000000005CEA +:10BFC0001F8001003080001042C90100FD8F224017 +:10BFD000E36D00000000004761B101004000001067 +:10BFE00062DD0100F98FA8408132000023830088C0 +:10BFF0001CB000000000000548B101001400004022 +:10C00000439901000400A2F0146C000000800019A4 +:10C0100042C9010022902240E36D000010902242AC +:10C02000197C000073960040813201005A94004050 +:10C03000813201001D90224B80320000000000433D +:10C0400061B101004000001062DD01000690A840CF +:10C0500081320000238300881CB000000C90224134 +:10C06000197C0000E7940040113001000D9000059C +:10C0700048B10000C9940040813201000F902209AC +:10C080008030000086970040813201002F830040FD +:10C0900005B0000073960040813201004F940040CB +:10C0A000813201000000004361B101004000001036 +:10C0B00062DD01001390A8408132000023830088D4 +:10C0C0001CB0000019902241197C0000E794004048 +:10C0D000113001001A90000548B10000C9940040D9 +:10C0E000813201001C9022098030000086970040B8 +:10C0F000813201002F83004005B0000000000043A2 +:10C1000061B101004000001062DD01001E90A840F6 +:10C1100081320000238300881CB00000000000056D +:10C1200048B1010025902241197C0000E7940040AD +:10C13000113001002690000548B10000C99400406C +:10C14000813201002890220980300000869700404B +:10C1500013300100D08B004005B0000014000040F7 +:10C16000439901000400A2F0146C00000080001943 +:10C1700042C9010032902240E36D000000000043FC +:10C1800061B101004000001062DD01002E90A84066 +:10C1900081320000238300881CB0000000000005ED +:10C1A00048B101000000004005B001003690224176 +:10C1B000197C0000E7940040113001003790000521 +:10C1C00048B10000C99400408132010008002D0AE6 +:10C1D00084B00100000000F082B00100040026409D +:10C1E0008132000014002040E1B101003D90031EA7 +:10C1F000803200003E90004187B0000021000040E6 +:10C20000879801002C960040813201000400A25C56 +:10C210001F7C00000000005C1F9001004390220979 +:10C220008030000086970040133001004690224481 +:10C23000197C00008697004F813001000000004407 +:10C2400019800100C98BA24A1F7C0000D08B0040DE +:10C2500081B200000400A205486D0000BA00204031 +:10C26000E5B101004E909C17803200000400224A84 +:10C27000197C0000CC000040439901003698004032 +:10C2800081320100D497004013300100C00000400B +:10C2900043990100C4002DF082B001000B9800F01A +:10C2A00084300100C994004081320100D08B220902 +:10C2B000803000008697004013300100D08B004092 +:10C2C00081B200002E000040439901005A902240A4 +:10C2D000E76D000032000040439901006590A240E4 +:10C2E000E56D0000F2950040813201002400200B32 +:10C2F000E0B1010028002013E0B101002200200677 +:10C30000E4B1010004002242197C00001400004046 +:10C31000439901000400A2F0803200001400200ABA +:10C32000E0B10100D08B22098030000086970040E8 +:10C3300013300100D08B004081B20000F295004024 +:10C34000813201009D9500408132010073902241AD +:10C35000197C00000000000B99B0010004001F15BB +:10C360009850000073902001986C0000700000034A +:10C3700048C9010000002E461F9001000000005037 +:10C38000F1B1010000000003F0B101000000004223 +:10C3900061B10100A00000A462DD01007090A8005E +:10C3A000E03100000000000548B10100AC002F00A2 +:10C3B00010B0010000000001E0C1010014002F15C1 +:10C3C00010C001000400A2F0803200000000000A4A +:10C3D00080B001000000600180D001000000004733 +:10C3E00019900100E98F2209803200008697000928 +:10C3F00080300100E98F004013B00000008000038E +:10C4000042C90100000000F082B0010013000040AA +:10C41000879801000000004C43C101002C9600F0F9 +:10C42000843001000400A25C1F7C0000C98B005C0A +:10C430001F9000002C002040E7B101002D0020409B +:10C44000E7B101002E000040439901000400A2F36F +:10C450008032000004002242197C0000C98B004297 +:10C46000198000001C960040813201005B97004853 +:10C47000953001000000004561B10100400000104E +:10C4800062DD01008D90A8401330000023830088F6 +:10C490001CB000009390000548B10000929000404D +:10C4A00013B000000000000012B0010008000040BE +:10C4B0004399010014002DF082B0010004002640D1 +:10C4C00081320000040022F084300000130000409C +:10C4D000879801002C960040813201000400A25C84 +:10C4E0001F7C00000000005C1F900100B09000095C +:10C4F00000B000000400A205486D0000C98B87420F +:10C50000191000008B002F4719800100C98B0040D3 +:10C51000E79100000400A2401F7C00002F000040B3 +:10C5200047990100AE902247E77D000004002241B8 +:10C53000197C00001D940040E7310100AE902200FC +:10C5400080320000A990A2401F7C0000C9940040E6 +:10C5500081320100AE90004081B200003000004006 +:10C560004399010032002DF294B00100A59500F22C +:10C5700002300100AC95004B02B000000000000545 +:10C5800048B10100AF90004001B000000000004041 +:10C5900005B00100B590220080320000B490A242A4 +:10C5A000197C00000596004081320100B5900040E2 +:10C5B00081B200003C960040813201005491225C1F +:10C5C0001F7C00000000005C1F8001000080001044 +:10C5D00042C90100BD902240E36D0000000000450B +:10C5E00061B101004000001062DD0100BA90A84076 +:10C5F00081320000238300881CB0000054910005A4 +:10C6000048B10000B494004081320100C490A208F7 +:10C6100080320000C490A216803200000F97004DB7 +:10C62000813001000082000204DC0100F08700403C +:10C6300081B200007400004043990100000000F83E +:10C6400082B00100000000F084B001000000004151 +:10C6500096B00100D5902242961400000080001090 +:10C6600044C9010064006840979801006400004BD1 +:10C6700080CE01000400A64081320000000000418D +:10C68000F0B1010000000042F0B1010070000005AF +:10C69000E0C901000000004561B101002000001068 +:10C6A00062DD0100D190A840813200000400A25C4C +:10C6B0001F7C00000000005C1F900100000000458E +:10C6C00061B101004000001062DD0100D690A85C5D +:10C6D0001F000000238300881CB000005E012D05B0 +:10C6E00048B10100DA9065F21230000000993F4233 +:10C6F00013F00100DF902247E77D00002783758853 +:10C700001CB00000D990004081B20000000000473A +:10C71000E79101000400750996E401000080001013 +:10C7200044C9010000000044F1B10100000068A804 +:10C7300097C0010000000003E0B101000080000389 +:10C74000449901000000004461B1010000000010A4 +:10C7500062B10100E790A840E13100002383008826 +:10C760001CB0000000993F4213F00100EB906505FA +:10C77000483100003F0000F39688010000000040AF +:10C78000E7B101000000754081B20100F390224B37 +:10C79000803200000000005561B101000000004B34 +:10C7A00062B10100F190A840813200000000000752 +:10C7B00016B001000062000B16DC01002F000040E3 +:10C7C000439901000400A247E77D00001D9400404A +:10C7D0008132010010912200803200004E96005FED +:10C7E00001100100F7902240956C000004002241E6 +:10C7F000197C0000040022401F7C00000080001013 +:10C8000044C9010000000050F1B101000000000324 +:10C81000F0B101000000004261B101000000001011 +:10C8200062B101000191A800E0310000238300887B +:10C830001CB000000000000548B1010004800003A6 +:10C8400042C90100000000F202B0010004002031E2 +:10C85000036C0000A595005295300100C99400407A +:10C8600081320100F7902241975000000C800003B4 +:10C8700042C90100000000F000B001000000005CAF +:10C8800001800100AC95004B02B00000F79000055C +:10C8900048B1000066970040033001001780000394 +:10C8A00044C9010000F0000C968801000000634CB0 +:10C8B00097F001000400204D976C00000400224016 +:10C8C000976C00001080000344C90100000000AB19 +:10C8D000E1B101000097005E0510010003000007B0 +:10C8E0001AF40100070000071688010000B5000DCA +:10C8F00046C901001C913040813200000400220B27 +:10C90000E67D00000000000BE681010000B7000D8D +:10C9100046C901000400220BE67D00000000000B68 +:10C92000E68101001000100F94F401009304005FF1 +:10C930009504010076950040813201002A91225031 +:10C94000FD7F000026914640813200002991A240DF +:10C95000316F000004001E4081B2000000001E4143 +:10C9600031D3010000002E0548B101000000004055 +:10C97000E1B10100000000400FB00100AB940041A4 +:10C9800081300100F087004081B20000B494004083 +:10C99000813201003D91A208803200003D91A21633 +:10C9A000803200000082000204DC0100000000452B +:10C9B00003F001000000000100C001003591375C68 +:10C9C000613100000000001B62B101003A91284073 +:10C9D000813200000400A25C777D000036910040A7 +:10C9E00081B200000000000062B101003A91A8404D +:10C9F00081320000F087174081B2000074002240AD +:10CA0000F1B1010000000040E1B101005B97004A74 +:10CA1000953001000400A25C1F7C00001C96005CA5 +:10CA20001F100100C490004081B200000400A24029 +:10CA30001F7C00002F0000404799010051912247C0 +:10CA4000E77D000004002241197C00001D94004095 +:10CA5000E731010051912200803200004C91A24048 +:10CA60001F7C0000C99400408132010051910040B8 +:10CA700081B20000300000404399010032002DF2E5 +:10CA800094B00100A59500F202300100AC95004B76 +:10CA900002B000000000000548B101005B970048AB +:10CAA000953001000400A25C1F7C00001C96005C15 +:10CAB0001F1001000400A205486D00005891874234 +:10CAC000191000008B002F47198001000000004062 +:10CAD000E79101008697004281300100C98B004038 +:10CAE00081B200001C960040813201000400A25C6B +:10CAF0001F7C0000C98B005C1F900000B00000404C +:10CB0000439901000400A2F080320000BA002040E6 +:10CB1000E5B10100D497004081320100C00000401F +:10CB200043990100C4002DF082B001000B9800F081 +:10CB300084300100C994004081320100869700458D +:10CB400081300100C98B2242197C00000F97003A06 +:10CB500081300100C98B004081B200000400004018 +:10CB600081B20000B4940040813201007091A208AB +:10CB7000803200007091A216803200000F970047AB +:10CB8000803001000082000204DC0100F0870040D8 +:10CB900081B200001080000344C9010000E100A63A +:10CBA00084B0010000000040F1B10100000000402D +:10CBB000F1B1010000006007849401000097005E5D +:10CBC00005100100C98B004081B200008A000040BE +:10CBD00047990100C9940041E7410100D08B004012 +:10CBE00081B200000400A205486D00000400A241CB +:10CBF000197C00000400A2481F7C0000F295004050 +:10CC0000813201000400A30A0C6C00009D950040D5 +:10CC100081320100000000012CB00100000000156D +:10CC200010B001000000000010C0010004001F0A45 +:10CC30002C50000014000040439901000400A2F0B1 +:10CC4000803200000000001032B00100A197000601 +:10CC5000043001008E91A2481F7C00008C91844812 +:10CC60001F100000AC000040479901008E91000A9F +:10CC7000E0C100000000000A02B001009E93000124 +:10CC80008C3001000000004361B101004000001041 +:10CC900062DD01008F91A84081320000238300886B +:10CCA0001CB000000000000548B1010000000002B7 +:10CCB00010C001009C91220214500000799600459A +:10CCC0001F0001008691225C1F7C000000000047CD +:10CCD00061B101004000001062DD01009891A85C84 +:10CCE0001F000000238300881CB00000869100050F +:10CCF00048B100000000000B1BB0010008002D40EF +:10CD000085B00100000000F082B00100000000408A +:10CD100005B001002C96004187300100000000455D +:10CD200061B101004000001062DD0100A291A84045 +:10CD300081320000238300881CB000000000000541 +:10CD400048B10100A8912209803000008697004078 +:10CD500013300100AC912244197C00008697004FEB +:10CD600081300100AC91A2471F7C0000000000440C +:10CD700019800100FF070008008C01000400264014 +:10CD800081320000BB91224A1F7C0000B391A216A1 +:10CD900002300000C9940040813201002F00204081 +:10CDA000E7B10100C98B004081B200002D002D08C1 +:10CDB0002AB00100B7912242197C00003C96004045 +:10CDC00081320100B891004081B200000596004018 +:10CDD0008132010030002E002AD0010032002A15D5 +:10CDE000E4B10100C98B0016E4B10000D191221614 +:10CDF000023000000400A2471F7C00000000000871 +:10CE00002AB001002B98004095300100C191A2404A +:10CE1000116C0000D29122402D6C00000400A2058C +:10CE2000486D0000040022441F7C0000AC0000405C +:10CE300047990100B0002B01E0C10100002B00A6C2 +:10CE400016B0010000000001E0D101005E9700086B +:10CE500080300100CA91005E179000007F97004368 +:10CE6000613101000000004361B101004000001089 +:10CE700062DD0100CB91A84081320000238300884D +:10CE80001CB000000000000548B1010066970007D3 +:10CE9000161401000097005E05100100C9940040BF +:10CEA000813201002F002040E7B10100D08B00400B +:10CEB00081B200000000000B1BB0010004001F1530 +:10CEC0001A500000E09120161A6C00000400224065 +:10CED0001F7C00007000000348C9010000002250C0 +:10CEE000F1B1010000000003F0B1010000000000FA +:10CEF000E0B101000000004261B10100A00000A407 +:10CF000062DD0100DD91A8461F1000000000000551 +:10CF100048B101000000000010B001000000001541 +:10CF200010C001000000000A2AB001000000000A41 +:10CF30002CD0010004001F168032000014000040B5 +:10CF4000439901000400A2F080320000AC002F40A1 +:10CF500023B00100EA9184451F100000EB91000A04 +:10CF6000E0C100000000000A02B00100BE960040CF +:10CF700035B000000400A25C1F7C00000080001996 +:10CF800042C90100F4912240E36D0000000000431B +:10CF900061B101004000001062DD0100F091A84085 +:10CFA00081320000238300881CB0000000000005CF +:10CFB00048B101000592A2021A5000000A922240D4 +:10CFC0002D6C0000040022401F7C00000080001037 +:10CFD00044C9010000000050F1B10100000000034D +:10CFE000F0B10100FF070008E08D010000000042E1 +:10CFF00061B101000000001062B10100FC91A84085 +:10D0000081320000238300881CB00000000000056E +:10D0100048B101002F002047E7B501000C80000354 +:10D0200042C90100100000F010C80100F0070040E4 +:10D030001B9801000A92005C118000000400A25FAE +:10D040001B7C0000FF070008988801000000000218 +:10D0500098C001000400200B996C00000000000241 +:10D0600010C0010004002240236C00000400A34310 +:10D07000236C0000E79400401F0001000000000541 +:10D0800048B101001092230D2C6C000000000040FC +:10D090001F900100199222461F7C000000000046EC +:10D0A0001F8001007080000342C9010019922240D4 +:10D0B000E36D00000000004261B10100400000107B +:10D0C00062DD01001592A8408132000023830088B0 +:10D0D0001CB000000000000548B1010008002D4010 +:10D0E00085B00100000000F082B0010000000040A7 +:10D0F00005B001002C96004187300100000000457A +:10D1000061B101004000001062DD01001E92A840E4 +:10D1100081320000238300881CB00000000000055D +:10D1200048B1010024922209803000008697004017 +:10D130001330010028922244197C00008697004F8A +:10D14000813001002892A2471F7C000000000044AB +:10D1500019800100FF070008008C01000400264030 +:10D16000813200003E92224A1F7C00002F92A216BC +:10D1700002300000C9940040813201002F0020409D +:10D18000E7B10100C98B004081B200002D002D08DD +:10D190002AB001003A922242197C00003392A2F395 +:10D1A00084300000000000A585B0010000000041AF +:10D1B00085D00100D4003E4185E001003792224035 +:10D1C0001F7C00000000005A119001000B000008B5 +:10D1D000E4F501003C960040813201003B920040A2 +:10D1E00081B20000059600408132010030002E001F +:10D1F0002AD0010032002A15E4B10100C98B0016C3 +:10D20000E4B100004192A21602300000C99400402F +:10D21000813201009A92004081B200002D002D0859 +:10D220002AB00100549222471F7C00000400A09104 +:10D23000036C00004E922242197C00004792A2F338 +:10D2400084300000000000A585B00100000000410E +:10D2500085D00100D4003E4185E001004B92224080 +:10D260001F7C00000000005A119001000B00000814 +:10D27000E4F50100200400408998010009990008A4 +:10D280008A30010058012D002AD0010060012DF0E4 +:10D2900010B00100000000F02CB0010000000016EA +:10D2A00080B2010004002740116C0000878F00400D +:10D2B00081B200000400A391036C00002B98004190 +:10D2C000953001005D92A208803200005D92A216A6 +:10D2D000803200000000004197B001005B92230DF6 +:10D2E000026C00000000004197C00100AC95004BAB +:10D2F00002B000009A92000548B100000400A205A7 +:10D30000486D0000040022441F7C0000AC002F0187 +:10D3100014B00100B0002B01E0C10100002B00A6F9 +:10D3200016B0010004002241197C00000000000139 +:10D33000E0D101007092230D026C0000008000100B +:10D3400044C9010000000050F1B1010000000003D9 +:10D35000F0B101000000004261B1010000000010C6 +:10D3600062B101006992A800E031000023830088C7 +:10D370001CB000000000000548B101000C80000353 +:10D3800042C90100100000F022C801000000005C4A +:10D39000238001000000000184B001007392230D7E +:10D3A000026C00000000000D02B001000000000847 +:10D3B00080B00100789222401B6C00005E97000153 +:10D3C0008450010081922240856C00000000000121 +:10D3D00080C001001080001046C901000000004F0D +:10D3E0004381010000000042F0B101002000004034 +:10D3F000F0C9010000000016F0B101000000004378 +:10D4000061B10100A00000A162DD01007E92A811BF +:10D41000E031000004002240236C00009092005E86 +:10D42000179000008492230D026C00000000000D94 +:10D4300002B001000000000184D001008992224066 +:10D440001B6C00007F9700436131010090922240E5 +:10D45000856C00000000000112C001001080001067 +:10D4600046C901000000004F438101000000004256 +:10D47000F0B1010000000009F0B101000000001847 +:10D48000F0B10100A00000A162DD01008E92A811A0 +:10D49000E03100000000004361B1010040000010D5 +:10D4A00062DD01009192A80A023000002383008807 +:10D4B0001CB00000C9940005483101009892230D6A +:10D4C000026C0000FF070011008C0100C9940040AD +:10D4D0008132010066970007161401000097005E74 +:10D4E000051001002F002040E7B10100D08B004063 +:10D4F00081B200000080000342C90100000000F872 +:10D5000082B001000400264081320000000000F8D3 +:10D510008CB00100000000F08EB00100EC950040DE +:10D520001330010004000C4780320000000000406E +:10D5300085B001002C960041873001009D95004088 +:10D540008132010004002091036C00000080001073 +:10D5500042C90100AE922240E36D00000000004588 +:10D5600061B101004000001062DD0100AA92A840F4 +:10D5700081320000238300881CB0000000000005F9 +:10D5800048B10100B0922209803000008697004027 +:10D59000133001000000000B1BB00100000000155B +:10D5A0001AD00100B792A241197C00002B980040CC +:10D5B000953001000000001680B20100C0922708DB +:10D5C00080320000C19100002AC000002B98004169 +:10D5D000953001000000001680B20100BB922708C0 +:10D5E000803200005D9200002AC00000000000416F +:10D5F00097B00100BE92230D026C000000000041B4 +:10D6000097C00100AC95004B02B00000000000057F +:10D6100048B10100C98B2242197C00000F97003AE3 +:10D6200081300100C98B004081B200000400A24A91 +:10D630001F7C0000C592004A1F9000000400A24118 +:10D64000197C00000400A24F2B7C00000400A244BF +:10D650001F7C00000400A2451F7C0000FF94000016 +:10D66000103001000000001510C001000000001083 +:10D6700032B00100A197000604300100D292A2440A +:10D680001F7C00000000000B1BB001000000000A1E +:10D690002CD001000000000A02B001009E9300019E +:10D6A0008C3001000080001942C90100D99222404B +:10D6B000E36D00000000004361B101004000001074 +:10D6C00062DD0100D592A8408132000023830088EA +:10D6D0001CB000000000000548B10100000000027D +:10D6E00010C00100E2922202145000007996004519 +:10D6F0001F000100CB92225C1F7C0000000000474D +:10D7000061B101004000001062DD0100DE92A85C02 +:10D710001F000000238300881CB00000CB9200058E +:10D7200048B1000008002D4085B00100000000F065 +:10D7300082B001000000004005B001002C960041BD +:10D74000873001000000004561B101004000001079 +:10D7500062DD0100E792A840813200002383008847 +:10D760001CB000000000000548B10100ED92220944 +:10D77000803000008697004013300100F092224470 +:10D78000197C00008697004F8130010000000044A2 +:10D7900019800100FF070008008C010004002640EA +:10D7A00081320000FF92224A1F7C0000F792A216ED +:10D7B00002300000C9940040813201002F00204057 +:10D7C000E7B10100C98B004081B200002D002D0897 +:10D7D0002AB00100FB922242197C00003C960040D6 +:10D7E00081320100FC92004081B2000005960040A9 +:10D7F0008132010030002E002AD0010032002A15AB +:10D80000E4B10100C98B0016E4B10000BC91A2167E +:10D8100002300000C9940040813201002F002040F6 +:10D82000E7B10100D08B004081B20000040022412A +:10D83000197C00000400A24F2B7C00000400A244CD +:10D840001F7C00000400A2451F7C00000400A24AC7 +:10D850001F7C0000FF94004A1F100100D4910010AB +:10D8600032B000008A002040E7B101000E93A241CF +:10D87000197C0000C99400408132010011930040DE +:10D8800081B20000A595001594300100AC95004BC5 +:10D8900002B000000000000548B1010013932242CD +:10D8A000197C00000F97003A8130010086970045EF +:10D8B00081300100C98B004081B2000065900045B5 +:10D8C0001F90000004002241197C00000400A247C0 +:10D8D0001F7C0000F2950040813201000400A30A81 +:10D8E0000C6C00009D95004081320100D491000134 +:10D8F0002CB0000004002241197C00000400A24862 +:10D900001F7C0000B4940040813201002C93A208D7 +:10D91000803200002C93A2168032000000820002A8 +:10D9200004DC01000000004503F0010000000001DC +:10D9300000C001002493375C613100000000001B2F +:10D9400062B1010029932840813200000400A25CEA +:10D95000777D00002593004081B2000000000000A8 +:10D9600062B101002993A84081320000F08717407E +:10D9700081B2000058012008E0B1010060012016CA +:10D98000E0B10100F29500471F1001000400A30A56 +:10D990000C6C00009D95004081320100D491000183 +:10D9A0002CB0000004002241197C00000400A247B2 +:10D9B0001F7C0000B49400471F1001004393A2088D +:10D9C000803200004393A216803200003F93A242AF +:10D9D000197C00000082000204DC0100A0980040D5 +:10D9E00047990100300500418930010004002241BF +:10D9F000197C0000A595001594300100AC95004BF2 +:10DA000002B00000F087004081B200003C96004068 +:10DA1000813201000000004B199001000F97003A7D +:10DA200081300100F087004081B2000058012008D9 +:10DA3000E0B1010060012016E0B101000400A24F36 +:10DA40002B7C00000400A2441F7C00000400A245BF +:10DA50001F7C0000FF94001032300100D491004080 +:10DA600013B00000B4940040813201005893A20822 +:10DA7000803200005893A21680320000008200021B +:10DA800004DC01000000004503F00100000000017B +:10DA900000C001005093375C613100000000001BA2 +:10DAA00062B1010055932840813200000400A25C5D +:10DAB000777D00005193004081B20000000000001B +:10DAC00062B101005593A84081320000F0871740F1 +:10DAD00081B200000080000342C90100000000F88C +:10DAE00082B001000400264081320000000000F8EE +:10DAF0008CB00100000000F08EB00100EC950040F9 +:10DB00001330010004000C47803200000000004088 +:10DB100085B001002C960041873001009D950040A2 +:10DB2000813201000400A091036C0000008000100D +:10DB300042C901006A932240E36D000000000045E5 +:10DB400061B101004000001062DD01006693A84051 +:10DB500081320000238300881CB000000000000513 +:10DB600048B10100878F220980300000869700406D +:10DB700013300100878F004081B200000400831E33 +:10DB8000803200000400A24F2B7C00000400A2455C +:10DB90001F7C000014002D451F9001000400A2F01E +:10DBA000146C00000400A001146C0000DF8F00441E +:10DBB000199000000400A24A1F7C00007893A24143 +:10DBC000197C00000000004A1F9001007A9100407B +:10DBD00081B200000400A2481F7C0000F295004AB8 +:10DBE0001F1001000400A30A0C6C00009D9500406A +:10DBF00081320100D49100012CB0000004002241C8 +:10DC0000197C00000400A24F2B7C00000400A244F9 +:10DC10001F7C00000400A2451F7C0000FF94004010 +:10DC200081320100D491001032B000008B0000401E +:10DC3000439901000400A246E77D0000659000457D +:10DC40001F9000000000004137C3010000000041A8 +:10DC500033C301003600000102CC01000000D240B5 +:10DC600081B200008C9385178032000000009F482D +:10DC700003D000008E939C178032000000009F4C60 +:10DC800003D000000000800134C301004080000385 +:10DC900044C901000000004AF0B101000400264020 +:10DCA0008132000000000040F1B1010000000012CC +:10DCB000F0B10100D1940041E13101000080004346 +:10DCC00044C9010010000040F19901000000004823 +:10DCD000F0B1010000000049F0B101004000000374 +:10DCE000E0C901000000004561B1010000000043EF +:10DCF00062B101000000A84081B200009B93004087 +:10DD000081B200002D04004089980100099900A506 +:10DD10008A300100BA002040E5B10100B0002F01B7 +:10DD20008CD0010004001FF080320000000000468B +:10DD3000E0C10100AC002F4013B00100CC002D0168 +:10DD4000E0C10100A9939C17803200000400224A20 +:10DD5000197C00003698004081320100AB932247C5 +:10DD6000197C00000000005F13900100D497004769 +:10DD700019100100C0002D441F900100C4002DF0B7 +:10DD800082B001000B9800F084B0000090002D05D7 +:10DD900048B10100C093A24B1F7C00001594A24C17 +:10DDA0001F7C0000C0931F1CE06D0000C393A20104 +:10DDB00080320000A8002D468FB00100B9931F1CCF +:10DDC000E06D0000B400004043990100BB9322F0D5 +:10DDD0003A6C000012941FF03A6C00000000A24060 +:10DDE00080B200000000804F8FB001008A00004028 +:10DDF0004399010013942042E76D0000BF93224035 +:10DE000080320000000080598FB00100000080586F +:10DE10008FB00100C2932240803200000000805C7D +:10DE20008FB001000000805B8FB00100AC000040AB +:10DE300043990100B0002DF084B00100C793A242C5 +:10DE4000246C0000D29323F0026C0000B00000A10B +:10DE500080CE01000400A64081320000CF93A2F0E2 +:10DE6000803200001494A242246C00001494A24159 +:10DE7000036C0000CE93A24080320000000080516D +:10DE80008FB00100000080528FB0010014941F1267 +:10DE9000845000001494A001846C0000C0930040E2 +:10DEA00081B200008B00004043990100FD93A2461F +:10DEB000E77D00001400004043990100EF9322F039 +:10DEC00014300000DB93200A026C0000EC93031E68 +:10DED00080320000DA93A2408032000000008044CB +:10DEE0008FB00100000080498FB00100E093220A4A +:10DEF000026C0000E393A241197C0000DF93A24072 +:10DF000080320000000080558FB001000000805674 +:10DF10008FB00100E293A2408032000000008043F5 +:10DF20008FB00100000080488FB0010000000001A8 +:10DF300082B001000000000A82D00100E993209124 +:10DF4000836C0000E893A2408032000026008040ED +:10DF50008F980100270080408F980100EB93A2402A +:10DF6000803200001F0080408F9801002000804018 +:10DF70008F980100EE93A240803200002200804082 +:10DF80008F980100230080408F98010088002D4465 +:10DF90008FB00100F893A241197C0000F593A243D1 +:10DFA0003D7C0000F593A2F2026C00000000A2404C +:10DFB00080B20000000080498FB00100F793A240BA +:10DFC00080320000000080438FB0010000008048D4 +:10DFD0008FB00100F593A091036C0000F3932243EE +:10DFE0003D7C0000FC93A24080320000280080406D +:10DFF0008F980100290080408F9801001400004094 +:10E00000439901000694A2F01430000088002D44CA +:10E010008FB001000394A2F2026C00000000A24045 +:10E0200080B20000000080498FB00100F5932241CA +:10E03000197C0000F3932091036C0000F5930040DD +:10E0400081B200000A94200A026C00000994A240E8 +:10E0500080320000000080448FB001000000804941 +:10E060008FB001000F94220A026C0000E393A241DA +:10E07000197C00000E94A240803200000000805500 +:10E080008FB00100000080568FB001001194A240B3 +:10E0900080320000000080438FB001000000804803 +:10E0A0008FB001001794004395B000001794004111 +:10E0B00095B000001794004295B0000017940044FA +:10E0C00095B000001794004C95B00000300400405B +:10E0D000899801000999004A8A3001005B97004045 +:10E0E000813201001C94A240803200000000804B6D +:10E0F0008FB001000000804C8FB001000400A20529 +:10E10000486D00002D000040439901002E002FF3C0 +:10E1100084B001002294A2F39630000000008040F9 +:10E1200001B001002D002A41E7D10100D4003D419A +:10E1300085E001000B0000F200E401002894225A5F +:10E14000017C0000000000401F9001002994005A4B +:10E1500001800000000000401F80010000006341BA +:10E1600085C001002C94A0A5856C000000006340D0 +:10E1700085B001001204004089980100099900004F +:10E180008A3001000000804081B201000000A0A59B +:10E19000856C01000000E34085B001000C800003A5 +:10E1A00042C9010012000040879801007F9800F0EA +:10E1B0008CB000000400225F1F7C000041942240CC +:10E1C0000F6C000000002F0548B101000400225A26 +:10E1D0001F7C0000100000F098F401000400A2076A +:10E1E000986C00001000000C98F401000400A207D5 +:10E1F000986C00003E94A24B197C00003F9422F0E2 +:10E20000186C00000000604B199001004395000756 +:10E21000103001002F83004005B000004394225AC3 +:10E220001F7C0000AB940040813001002F83004030 +:10E2300005B000000400225F1F7C000000002F05D5 +:10E2400048B101000000604B199001000400225AFF +:10E250001F7C0000040022400F6C0000100000F042 +:10E2600096F401000400A207966C00001000000C58 +:10E2700096F401000400A207966C00004395000785 +:10E28000103001002F83004005B000000400225F21 +:10E290001F7C000000002F0548B101000000604B0A +:10E2A000199001000400225A1F7C00000400224043 +:10E2B0000F6C0000100000F096F401000400A207AB +:10E2C000966C00001000000C96F401000400A207F8 +:10E2D000966C00004395000710300100000080405C +:10E2E00005B001005A943340813200005D94A1AD25 +:10E2F000952000006F94134081B200000000134A83 +:10E300005A8301003000394595E001000400A25F06 +:10E310005F7C00000400A25E5F7C00001F00000F15 +:10E320005ED801000000005A5F9001000000005E0E +:10E330005F9001000000004045B0010000000004B3 +:10E3400048B00100000000054AB001000000000CC8 +:10E3500058B00100000000074EB001001C850040CD +:10E360005D9801000400A2445F7C0000000000589A +:10E3700061B101000000004A62B101000000A84143 +:10E3800097B000006C94004081B200000000804013 +:10E3900097B001000400A240056C00001C990040E9 +:10E3A000813201007294600796300000FFFF004B3D +:10E3B00084890100000070C224B001007F94A2454E +:10E3C000257C000076943120853000008094221254 +:10E3D000487F000058041112480301001000001289 +:10E3E00096E401000000004B1E9401001704004059 +:10E3F00089980100000000128AB001000999005FAD +:10E400008B1001000000805A1F9001007F94314062 +:10E4100081320000000000B424B001008094221278 +:10E42000487F00005804004081320100170400407A +:10E4300089980100099900128A30010000002F0517 +:10E4400048B101008F940BF08430000000001112DD +:10E45000488301008C942250857000005E010040CA +:10E4600043990100B49600F2963001009304001223 +:10E47000943001000000005A1F90010010000012AB +:10E4800096E401000000804B1E9401001000004241 +:10E4900010F40100040022088032000000B73F435E +:10E4A00011F00100070000088A880100939430A150 +:10E4B0000C30000096942245E67D000080941040C8 +:10E4C00081B2000000002A45E69101000000101210 +:10E4D000488301000400A205486D000000001140BF +:10E4E00081B201000000604B858001005E010040A8 +:10E4F00043990100B49600F29630010000800010AC +:10E5000044C90100D8000040819801002E002D056B +:10E5100048B10100A2942240E76D00008000004055 +:10E5200080C8010000000040F0B1010009000008AF +:10E5300086E40100000068A787C0010000000044D5 +:10E5400061B101000000001062B10100A694A805AD +:10E55000E03100001000001296E401000014004BAE +:10E5600096DC01000000804B1E9401000400225A3A +:10E570001F7C00001000000F84F401001F00004207 +:10E5800084880100B094224080320000B19400429F +:10E5900068B10000000000426AB10100B194315A34 +:10E5A0001F0000000400A242487F000000009142CA +:10E5B00048930100B4943540813200006D00004062 +:10E5C00061990100BA9428B12C300000B594224D15 +:10E5D000757D0000000000402DB001000000954056 +:10E5E00011B001006D00004061990100BA94A8B11A +:10E5F000103000000000001680B20100040027085F +:10E60000803200000000954081B201007F00004090 +:10E6100061990100C59428B110300000BF949FBAE1 +:10E6200080320000150000408998010009990040DF +:10E63000813201000000804011B001000400225C22 +:10E64000117C00000400A25A117C00000400220882 +:10E650004806000000008024118401000400A25C30 +:10E66000017C00000400A25A017C0000040022008A +:10E670004806000004001FBB803200000000005F5D +:10E6800061B101000010000062DD01000000A8403F +:10E6900081B20000CE94004081B20000AC940040F2 +:10E6A00047990100D294324081320000DA9422F876 +:10E6B00096300000000000F890B00100000000F06B +:10E6C00092B001000000004880B201000400274918 +:10E6D000803200000100004BF0CD01002000924884 +:10E6E000E0C901006C00004061990100DE9428B18E +:10E6F00092300000DA94224C757D00000400124034 +:10E7000091B000006C00004061990100DE94A8B156 +:10E71000903000000000004980B20100040027484A +:10E7200080320000FF000048968801000000004B86 +:10E7300090D001000100004BF0CD01002000004806 +:10E74000F0C9010000009249E0B101000C002D1059 +:10E7500048B10100FF070008828C01000400A25CA0 +:10E76000837C0000FF0700F0008C01000400A25C25 +:10E77000017C000004002240016C00000000A24166 +:10E7800000EC0000F094221A006C0000C994000014 +:10E79000343001000000005049C10100EA94A24158 +:10E7A000235000000000804081B201000C002D10B9 +:10E7B00048B10100FF070015828C01000400A25C33 +:10E7C000837C0000FF0700F0008C01000400A25CC5 +:10E7D000017C000004002240016C00000000A24106 +:10E7E00000EC0000FC94220D006C0000C9940000B5 +:10E7F0001A3001000000005049C10100F694A24106 +:10E80000235000000000804081B201000195831E6A +:10E8100080320000000000441990010024002D0106 +:10E820002CB0010028002DF016B0010022002DF0C0 +:10E8300026B0010014002FF20CB001000400A2F079 +:10E84000146C000004002001146C000000008040E3 +:10E85000E1B10100300000409798010060972E4020 +:10E8600081B2010000000040F1B101000A95A2410F +:10E870009750000064973E439DE0010000008040F7 +:10E88000E1B1010064973E439DE001000000800B70 +:10E89000E8B1010064973F439DE00100000000F0F3 +:10E8A00016C0010000008040E1B1010064973F43C1 +:10E8B0009DE00100000000F416B00100000080405F +:10E8C000E1B1010060173D439DE00100100080A10F +:10E8D00016E401000400A207166C00001A040040B0 +:10E8E000899801001000000B8AE401000999000DCD +:10E8F0008A14010000B5000D42C901001D95304782 +:10E90000170400002095A20BE67D00000000904255 +:10E9100081B0010000B7000D46C901002495A20B8B +:10E92000E67D00000000000BE69101000000904130 +:10E9300081B001000000104081B201002595400720 +:10E94000963000009D040040813201002F95A245C1 +:10E95000957C000001973F4195E00100000000F325 +:10E9600096B001000000004EE6B1010040973E4025 +:10E9700097E001000000004EE6B1010040973E40E4 +:10E980009DE001004295003BE7B100002F9530402B +:10E99000813200003995A20BE67D000000B5000D24 +:10E9A00046C901003595A20BE67D0000000010402D +:10E9B00081B201000000984281B0010000B7000D53 +:10E9C00046C901000000000BE69101000000104064 +:10E9D00081B201000000984181B00100040021A231 +:10E9E000952000000000104A4483010000973E413A +:10E9F00095E001000000004EF6B101000000004E5D +:10EA0000E6B1010040973E409DE001000000003B60 +:10EA1000E7B101000000004A90B10100FFFF0007CC +:10EA2000928901000000984081B00100110400406B +:10EA300089980100099900088A3001000300000844 +:10EA400086F4010000B7004346C901000700000832 +:10EA50008288010004002208803200000400224164 +:10EA6000E67D00004A954008963000009D04004075 +:10EA70008132010058952245957C00005395225A19 +:10EA80001F7C00001000000F96F401004F95315FCD +:10EA9000970400000400A24B487F00000000114BC7 +:10EAA000489301000000004B6AB1010053953040CB +:10EAB0008132000004002241E67D00000000004198 +:10EAC000E68101000000104081B201000000984082 +:10EAD00081B2010000973F4195E00100000000F382 +:10EAE00096B0010040973D4097E00100000063F3BD +:10EAF00088B001006195A23B896C00000000004ACB +:10EB000090B10100010000A692B101000400A24AE8 +:10EB1000447F00006295184A4493000000001840AA +:10EB200081B201003F0400408998010016000012E4 +:10EB30008AE401000999004B8A140100300039452C +:10EB400097E001000400A25F5F7C00000400225EE9 +:10EB50005F7C00001F04002F7ED901000400A64046 +:10EB6000813200006E95225A1F7C00001F04000FA6 +:10EB700098D801000000004C5E94010070950005DB +:10EB80004AB000001F0400A75E840100000000409E +:10EB90004BB001000000005E5F9001000400A2087D +:10EBA0004E6C00000000005861B101000000004BF5 +:10EBB00062B101000000A84081B2000073950040DE +:10EBC00081B20000330400408998010009990007D0 +:10EBD0008A30010078954007963000009D0400407F +:10EBE000813201007C952245957C00000000984010 +:10EBF00081B201000400A24A447F00009B04004A45 +:10EC00004413010000973F4195E00100000000F32C +:10EC100096B0010040973D4097E00100000063F38B +:10EC200088B001003000384597E001000400A25F81 +:10EC30001F7C00000400225E1F7C0000040020AA4C +:10EC40000F6C00000000005F0F90010000000058F2 +:10EC500061B101000000004B62B101008895A8403D +:10EC6000813200007E95A23B896C0000300038455F +:10EC70009DE001000000984081B2010004002208DC +:10EC8000803200000300000894F4010000B7004A3D +:10EC900046C9010007000008968801000400224BC5 +:10ECA000E67D000093040012943001004395005A61 +:10ECB0001F0001000000805A1F9001001100004A4F +:10ECC000E6C901003000004A80CE01000400244063 +:10ECD0008132000034002F4F95840100000000F3C2 +:10ECE00096B001000100634B84C801000000A043FE +:10ECF000856C01000000E34085B0010030002D4428 +:10ED00001F90010032002DF22AB0010004002640BD +:10ED100081320000040022F2023000001D94001035 +:10ED20003230010004002200803200000400224240 +:10ED3000197C00003200A040E5B101000000004055 +:10ED400097B00100F0070040999801000000004AC8 +:10ED500002C001000000005003D00100000000418B +:10ED600097C001000000A34C02D00000A99500400C +:10ED700081B20000000000A836B00100BA9522411F +:10ED8000035000000080001044C901000000005042 +:10ED9000F1B1010070000003F0C901000000004261 +:10EDA00061B101000000001062B10100B295A8003D +:10EDB000E0310000238300881CB00000C9940040AB +:10EDC000813201007C80000342C90100040022401E +:10EDD000E16D0000000000F000B00100AD95005CA6 +:10EDE00001800000C9940040813201000000001B36 +:10EDF00010B1000068012D0682B00100000000F291 +:10EE000082C001000080000346C90100BF94004099 +:10EE100081320100E8952240116C00000000680872 +:10EE2000389601003A0400408998010009990008C9 +:10EE30008A300100F007004182CC0100BF95AA4151 +:10EE40003B400000000000F810B001000000005C32 +:10EE5000118001000400A3483B6C00000100001D6C +:10EE600004CC0100E695264623300000080000038C +:10EE700012C801000480000398C801000400A24CDD +:10EE8000426D00000400A205486D0000640120F0FE +:10EE9000E0B10100E595224105500000200000038B +:10EEA00048C901000C0000F886C801000000224497 +:10EEB000F1B1010000000043F0B1010000000009C1 +:10EEC000E0B101000000004461B10100A00000A415 +:10EED00062DD0100D795A8461F100000E49522418D +:10EEE00005500000E295A24123500000000000A15F +:10EEF0001AB001000000004461B1010040000010A0 +:10EF000062DD0100DD95A8462330000023830088E0 +:10EF10001CB000001000000348C901000000000DF3 +:10EF200042B101000000004413C00100D29500501E +:10EF300049C100000000000548B101000480000341 +:10EF40001AC801000400A205486D000000008040BE +:10EF500081B20100E69522403B6C0000000000F801 +:10EF600000B00100C994005C01000100E895004177 +:10EF70003BD0000000008D4780320100B0002F5FC1 +:10EF800013B00100000060F08CC001007C00004064 +:10EF9000439901000400A3F08C6C00000000804045 +:10EFA00081B201000080000342C90100000000F8A6 +:10EFB00094B00100000000F88CB00100F7958CF8C7 +:10EFC0008E3000000000004419900100040022F877 +:10EFD00014300000000000F816B00100000000F836 +:10EFE00026B0010008002EF80CB001000C002A4ADF +:10EFF000E0B1010028000000E0C901001000201B62 +:10F00000E0B101000496200A0C6C0000000000F83A +:10F0100094B00100000000F896B00100200020F03C +:10F02000E4B101001800204AE0B101001C00204BAF +:10F03000E0B10100EC95004013B000000400A2050F +:10F04000486D00002C002D42199001002E002FF376 +:10F0500082B00100000000F396B001000B96A2A55B +:10F06000976C00000000804195B001000E96A24010 +:10F07000976C00000000004083B001002D0020408C +:10F08000E7B101000000634197C00100D4003E4198 +:10F0900083E001000000004183C001001396A0A599 +:10F0A000836C00000000004083B001002C00204170 +:10F0B000E6B10100189622401F7C00000004000009 +:10F0C00098DC01000B00004CE4F5010019960040AB +:10F0D0001F8000000B000000E4F501001E0400404A +:10F0E00089980100099900008A30010000008040E1 +:10F0F00081B20100D1940040813201000080000300 +:10F1000042C9010004002240E16D000004800003B8 +:10F1100044C9010000000040F1B1010000000040BE +:10F12000F1B101000000604187B0010000800010D3 +:10F1300044C9010000000050F1B101000000004886 +:10F14000F0B1010000000049F0B10100000000032F +:10F15000E0B101000000004561B101002000001095 +:10F1600062DD01000000A85D0590000029960040C6 +:10F1700081B20000D1940040813201000080000380 +:10F1800044C9010000000041F0B101000400264024 +:10F190008132000000000042F0B101000000004098 +:10F1A000F1B1010000000043F0B101000080001047 +:10F1B00044C9010000000050F1B101000000004806 +:10F1C000F0B1010000000049F0B1010000000003AF +:10F1D000E0B101000000004561B101002000001015 +:10F1E00062DD01000000A85D059000003996004036 +:10F1F00081B200000400A205486D00000400820CEA +:10F20000803200002D000040439901002E002FF3B2 +:10F2100084B00100010063F396C8010043969F414A +:10F2200085500000010000A585CC01002D00204282 +:10F23000E6B101000400A3A5976C0000D4003D4195 +:10F2400085E001000B0000F298E401004A9622409C +:10F250001F7C00000400225A997C00000000005A24 +:10F26000998001000400A200986C00002004004076 +:10F2700089980100099900008A300100000080404F +:10F2800081B2010021040040899801000999000021 +:10F290008A3001000400A2006A0600005E012D0011 +:10F2A00080B001005596524381600000020000F2D8 +:10F2B00082F4010056960041809400000000005F37 +:10F2C000819001000000005E61B10100000000407B +:10F2D00062B101000000A84095B0000057969EBBA7 +:10F2E000803200005C96A2401F7C0000C994004060 +:10F2F00081B200000000804195B0010004000015BB +:10F3000042C90100000000542BC00100000000FCB5 +:10F3100024B00100000000FC38B00100000000FE35 +:10F320003CB00100000000FE3AB0010071969C174D +:10F33000803200006696A24A197C00000000804CD2 +:10F340001F9001000C00001E98F401006596A24871 +:10F35000996C00000000001542B101006596A28A78 +:10F36000F16D00000C00000102CC0100000000FC67 +:10F370003EB00100010000F428CC0100CC002D05B6 +:10F3800048B10100709620F03E6C00000000004B78 +:10F390001F9001000000004C2BC00100BF002D0594 +:10F3A00048B10100000080F33AE001000400A2052A +:10F3B000486D00001000000C96F401000400A20744 +:10F3C000966C000000002E4B1990010007002A0CDB +:10F3D000E4B1010000008004E6B101001800004023 +:10F3E000439901001C002DF016B0010020002DF003 +:10F3F00026B001000C002FF20CB001000000A206A4 +:10F4000014EC0000809622451F7C00000000A3063B +:10F410002AEC0000000000F894B00100000000F0A9 +:10F4200096B001000C002D4081B2010000002A4C72 +:10F43000E1C101003000001048C901000A0000408D +:10F44000F199010018000005F0C901000000004A10 +:10F45000F0B101000000004BE0B1010000000047E6 +:10F4600061B10100A00000A462DD01008A96A85CE1 +:10F470001F1000000000800548B101000400A295A3 +:10F48000036C000000002E1048B101004000000194 +:10F49000F0CD010040000003F0C901004000000071 +:10F4A000E0C9010000002E5049C101000000000623 +:10F4B000F1B1010000000003F0B101009596624235 +:10F4C000613100002000001062DD01009696A84026 +:10F4D000813200001000001062C901009896A80057 +:10F4E000E03100000000F24081B201000400A2956A +:10F4F000036C000000002E1048B101004000000124 +:10F50000F0CD010040000003F0C901004000000000 +:10F51000E0C9010000002E5049C1010000000006B2 +:10F52000F1B1010000000003F0B10100A3966242B6 +:10F53000613100002000001062DD0100A496A840A7 +:10F5400081320000A00000A462DD0100A696A800A0 +:10F55000E03100000000F24081B201003080004A3A +:10F5600044C9010000000006F1B10100C0A83D46F9 +:10F570000DE00100FF7F00A1F089010002000009F9 +:10F5800096F401000000004697E00100000060A82A +:10F5900097C00100B0966342613100003000004A1C +:10F5A00062C90100B196A840813200000000F3401A +:10F5B00081B2010000993F4297F00100B596654085 +:10F5C00081320000BD9622F3740600003F0000F374 +:10F5D0009488010000000007E785010000007555D0 +:10F5E00061B101000000004A62B101000000A840C2 +:10F5F00081B20000BA96004081B200000000F540E0 +:10F6000081B20100000000A836B00100CD96824111 +:10F6100023400000C296A2441F7C00009E9300017C +:10F620008C3001002080001042C90100C8962240A1 +:10F63000E36D00000000004361B1010040000010D4 +:10F6400062DD0100C596A840813200002383008856 +:10F650001CB000000000004123B0010000000010B9 +:10F6600032B00100CD962241197C0000E79400439E +:10F67000233001000000004123B00100CF96A31504 +:10F680000C6C0000D096000604B0000000000015CD +:10F6900004B00100D29620021A6C00000000000D98 +:10F6A00004B00100A197000548310100FD96220237 +:10F6B00014500000D696A2022A500000FD96A245E2 +:10F6C0001F7C0000D89622020C500000E196000238 +:10F6D00016C00000E096225C1F7C00003080001005 +:10F6E00042C90100E0962240E36D0000000000479F +:10F6F00061B101004000001062DD0100DC96A8400D +:10F7000081320000238300881CB000000000000547 +:10F7100048B101007996005C1F000100FD9622159A +:10F72000803200000000005033C00100FC96A202AD +:10F730001A500000ED9622461F7C000070800003E6 +:10F7400042C90100000000461F800100ED962240E2 +:10F75000E36D00000000004261B1010040000010B4 +:10F7600062DD0100E996A840813200002383008811 +:10F770001CB000000000000548B101000C8000032F +:10F7800042C90100040022F080320000100000F0A5 +:10F7900010C801002F002F5C1180010000000047FD +:10F7A000E7910100F00700401B980100BF9620156B +:10F7B0001A6C00007000000348C9010000002250CC +:10F7C000F1B1010000000003F0B10100FF070008E3 +:10F7D000E08D01000000004261B10100A00000A422 +:10F7E00062DD0100F996A8461F100000BF960005D3 +:10F7F00048B10000BF96000210C00000FF96A2446E +:10F800001F7C00009E9300018C3001000000001B53 +:10F8100010B100000080001044C901000C0000403D +:10F82000F199010010000008F0C901000000001665 +:10F83000F0B1010010000003E0C901000400A25C67 +:10F840001F7C00000000004561B101002000001095 +:10F8500062DD01000000A85C1F90000007970040D7 +:10F8600081B20000170000D0A2C901000000A24030 +:10F8700027EC00000000002000B00100C994004106 +:10F88000A34101000B97004127D00000360400403F +:10F8900089980100099900408A3001001000000792 +:10F8A00096E401000000004B809401000000005429 +:10F8B00061B101000080004062DD01000000A8404D +:10F8C00081B20000040014BB803200001497004095 +:10F8D00081B200000400A205486D00006A97004054 +:10F8E0002B300100AC002D0616C0010090002DF059 +:10F8F00016C401001E97A0F016440000000000414D +:10F9000017C001000E0000A244C9010000006CF005 +:10F9100030B00100AC002D4087B0010000006CF059 +:10F9200028B001002797224A197C000000300043CC +:10F9300086C801000030000B16C801002797A440BC +:10F94000813200000000004117C001004A972206E2 +:10F95000803200003597A206146C000032972248CE +:10F96000197C00002C97A0411740000000000041C6 +:10F9700017C001000000004131C0010090002018B4 +:10F98000E0B101008B002D48198001000400A24560 +:10F99000E77D00008B002045E7910100359700408E +:10F9A0008790000008000043869801003597A04822 +:10F9B000174000000000004117C00100B0000040E7 +:10F9C0004399010010500043FCC90100AE9700307C +:10F9D0008130010000000040E5B101004097224A5B +:10F9E000197C0000080000A244C90100CC002DAB26 +:10F9F000F9B10100000000AB17C001003F97A0F073 +:10FA0000164400000000004117C00100449764F054 +:10FA100082B00000A4000040479901004497A2F280 +:10FA20008032000000000041E5B101008C00201888 +:10FA3000E0B101009000004045990100000060061F +:10FA400030C001000000860C80B200000400A24912 +:10FA5000197C0000BC002D4619900100A000A0F206 +:10FA6000E4B10100B0000040439901001050004390 +:10FA7000FCC90100AE970030813001000000A24AAD +:10FA800019FC0000080000A244C90100CC002DAB05 +:10FA9000F9B10100000000AB17C001005397A0F0BE +:10FAA000164400000000004117C001000000E4F00F +:10FAB00082B001000080001044C901000000004134 +:10FAC000F0B1010000000003F0B1010000000000EF +:10FAD000F0B101000000001062B101000000A81B9D +:10FAE000E0B100005897004081B2000000F0000C27 +:10FAF0007E8901000000A64C956001000000804A4C +:10FB0000189401000080001044C901000400220183 +:10FB1000F031000020000040F0C901000000001694 +:10FB2000F0B101000000004361B1010020000010AD +:10FB300062DD01000000A815E0B1000063970040FD +:10FB400081B200001080000344C9010000000006DB +:10FB5000F0B1010000000001F0B101000000E85F19 +:10FB60001790010070000040439901007A012EFEB9 +:10FB700092B001008B002DF616B001007097224361 +:10FB8000E77D00000000004445C10100040000A61C +:10FB90002AB0010028006E0682C801007497224A2C +:10FBA000197C00000000004245D1010000006E4CAD +:10FBB00083C001000000004192C0010075974330EE +:10FBC0003D0700000000669E83B0010000001B415D +:10FBD0003DC301000000004192C00100060000A2E8 +:10FBE00044C901001000004998F401007E972630B6 +:10FBF000930400007E97904C92400000000000416A +:10FC000093C00100FFFF8049ECA9010000800010B3 +:10FC100044C9010004002201F03100000000000985 +:10FC2000F0B1010000000018F0B101002000001048 +:10FC300062DD01000000A815E0B1000083970040DC +:10FC400081B2000004002220816C000004002240E8 +:10FC5000816C00009597225F817C00009297A24002 +:10FC6000197C0000000000401990010000000054C1 +:10FC700061B101001000000796E401000000004F90 +:10FC8000979401000000004B62B101009297284058 +:10FC9000813200000400A254777D00008E9700405E +:10FCA00081B20000250400408998010009990040B4 +:10FCB0008A3001000000A221818400009897A25F91 +:10FCC000816C00000000A243197C01000000004389 +:10FCD000199001002504004089980100099900400D +:10FCE0008A3001000000005461B1010010000007DB +:10FCF00096E4010000000040969401000000004BD3 +:10FD000062B101000000A84081B200000400A254CA +:10FD1000777D00009D97004081B20000040022081A +:10FD2000803200000400220280320000A697A24B1D +:10FD3000FD7F0000B405000280CE01000400AA404F +:10FD4000813200000080001944C901000400220231 +:10FD5000F03100000000000BF0B1010000000013C2 +:10FD6000F0B101000000004361B101002000001962 +:10FD700062DD01000000A808E0B10000AB97004080 +:10FD800081B200000400A205486D0000B00000A18F +:10FD900080CE01000400A640813200007C002DF0DE +:10FDA00084B00100020000F098F40100B797204CE5 +:10FDB000846C00008800004043990100B79720F24E +:10FDC000846C00000000004085B0010098002D14F4 +:10FDD00082B00100000000F098B00100A3002D14D3 +:10FDE00098D00100BC97204C846C00000000004CAF +:10FDF00084B001000400A230816C0000000000F318 +:10FE000080E00100C0972340846C000000000040A7 +:10FE100084B00100D0002014E0B101009800254218 +:10FE200080B0010000006EF380F001000000A642E7 +:10FE300082C00000C697A0401640000000000041AC +:10FE400017C0010000009FF082EC00009800A04164 +:10FE5000E0B101000400A25C1F7C000037040040F8 +:10FE600089980100099900058A30010000000042CC +:10FE700061B1010000002E1048B10100A80100404E +:10FE8000F199010000000005F0B101000900000730 +:10FE900096E40100000060A797C001000000001078 +:10FEA00062B101000000A84081B20000D19700407B +:10FEB00081B20000A8002D1C8AB0010000009FF054 +:10FEC0008AD000000000A2408BEC00008A00204095 +:10FED000E7B10100B400004047990100A4002D459E +:10FEE000E0D10100DF979C17803200000400224A15 +:10FEF000197C0000BE002FAB83B001003C980014B9 +:10FF000082500100E497004081B20000E49722F2A1 +:10FF1000823000008C00004043990100E4979F1C50 +:10FF2000E06D0000BE000040479901003C98004091 +:10FF300081320100A800201CE0B101009C002D309E +:10FF400081B0010088002DF084B0010094002DF2F2 +:10FF500086B00100F89723F0846C0000EC972392A0 +:10FF6000876C0000C90400A694B00100EE97004021 +:10FF700081B20000200000A694B001006089004A10 +:10FF800094980100EE9768408132000004002240FE +:10FF9000BD7D00000000004AB0B10100BF002D424D +:10FFA000B2B1010090002DF380E00100F397D4403E +:10FFB00081320000000078DA84C00100FD97234000 +:10FFC000846C00009400209DE1B10100FD97004089 +:10FFD00084B00000BF002D4384C0010090002DF3C9 +:10FFE00080E00100FD972340846C00009400209D78 +:10FFF000E1B101000000004084B001000198A2F0CE +:020000021000EC +:10000000386C00009C002042E0B101000000005F5D +:100010001394010000008046198001009C002042DA +:10002000E0B101003700004043990100040000F3F3 +:1000300080F401000F0000F382880100079823413B +:10004000806C00000000005F139401000000890C28 +:1000500080B200000400860C80320000BC0000402A +:1000600043990100A000A0F2E4B1010000009F410B +:1000700024EC00001398A6408132000000009F424B +:1000800038EC00001398A64081320000B400004014 +:10009000439901001598A3F03A6C00000400A440B5 +:1000A000813200000000804081B20100B4000040B5 +:1000B00043990100199822F03A6C0000B400201D09 +:1000C000E0B1010080002D5F13940100199823F026 +:1000D0003A6C00008000201DE0B10100C000201239 +:1000E000E0B10100C400A01CE0B101002704004001 +:1000F00089980100099900428A3001000400A20594 +:10010000486D00000080000344C901000000004267 +:10011000E0B10100120000408798010025989F413E +:10012000246C0000000000418CB0010000000012AF +:100130008CD001002698004124B00000000000404F +:100140008DB001007F980040813201000000004521 +:1001500061B101004000001062DD01000000A84014 +:1001600081B200002898004081B20000B4940040A1 +:10017000813201000000001680B201000000A708D3 +:10018000803201003204004089980100099900087A +:100190008A3001003298A240956C0000C99400405A +:1001A00081320100008200A604B00100000000407E +:1001B0002DB00100A0982F4011B001003005004182 +:1001C00089B00000CC0000A180CE01000400A64050 +:1001D0008132000000009FF83EEC000000009F12FA +:1001E000E0ED0000C80020ABE1B10100CC00A01F91 +:1001F000E0B101000400A205486D00003F98A35F34 +:10020000E76D000000000041E7C10100A6000040CA +:1002100047990100539822F2863000000300004302 +:1002200084F401000100004180CC0100B8002D429F +:1002300080D001000000624086C0010047981F4343 +:10024000803200004898A240876C000000006241A4 +:1002500087B001004C989F408032000000000040B1 +:1002600085B001000000004084D001000000004281 +:1002700080B00100000000F288B0010002000044DC +:1002800084F40100B8002E4280D0010000006240DA +:1002900088C0010052981F44803200005698A24046 +:1002A000896C00005698624189B0000003006241E9 +:1002B00086E40100B8000040459901000100624158 +:1002C00088E40100A4002040E5B10100A200204024 +:1002D000E7B10100BC002E4387F00100000000449C +:1002E00086C001005C982043876C000000008043BA +:1002F000E5B101004001004380CE01000000A443AD +:10030000E43101004001E240879801000400A205A9 +:10031000486D00000400220A8032000088002D444D +:1003200081B0010090002DF22EB001009C002DF054 +:1003300086B0010090002DF082B00100BA002DF0CF +:1003400098B001006B98A212986C0000BC002DF2CE +:1003500098B001006B98A0F2986C000000000017A4 +:1003600082B001009C002041E0B10100B4002D12D8 +:1003700086D001006E98A341E06D00006F9800F0F8 +:1003800084B000000000004184B0010080002D43D3 +:1003900084D0010072989F4280320000000000402B +:1003A00085B001007498A342146C00007598000A8F +:1003B0000CB00000000000420CB001007798A017BC +:1003C0000C6C0000000080170CB001007C982240EB +:1003D0000D6C00000000A00A0CEC0000010000F011 +:1003E00082F401007C98A0410C6C00000000A2F097 +:1003F00080320100290000408998010009990040DD +:10040000813201000000804081B00100D1940040A1 +:1004100081320100040022038032000004800003C6 +:1004200044C9010000000046F0B101000000004096 +:10043000F1B10100000060418794010000800010CC +:1004400044C9010000000050F1B101000000004863 +:10045000F0B1010000000049F0B10100000000030C +:10046000E0B101000000004561B101002000001072 +:1004700062DD01000000A85D059000008B9800403F +:1004800081B200000400A205486D00001000000CBD +:1004900096F401000400A207966C000000002E4BA9 +:1004A0001990010005002A0CE4B10100000080044D +:1004B000E6B101003E040040899801000999000856 +:1004C0008A3001009698454861310000001000080C +:1004D00062DD01009C9828408730000097982248F0 +:1004E000777D000004002240276C00000A971D461B +:1004F00087B000009F98225F117C00000400221545 +:10050000623100009D98A8408132000000009D40AB +:1005100081B201000000004049B1010000142F4CDD +:1005200083B0010000000040F1B10100A298A24197 +:10053000835000000000804081B2010000000040B4 +:1005400049B1010030000040A199010000000040C5 +:1005500093B00100000000401FB00100F698004970 +:10056000963001000700004906E40100003900034D +:1005700006C801000000004005B00100200000D0C6 +:10058000A0C901000000004193C00100A998A05437 +:10059000936C000000002E0597B001000080004021 +:1005A0004999010000000040E1B10100000200A2F1 +:1005B00044C90100B298A2419750000000000020F9 +:1005C00049B30100FC980040493101000895004002 +:1005D0008132010000B52E0897B0010000000040F4 +:1005E000F1B10100B998A2419750000018000040F5 +:1005F0009798010000972E4081B201000000004052 +:10060000F1B10100BD98A2419750000000000040E8 +:1006100049B1010040182E0597B0010000000040CC +:10062000F1B10100C198A2419750000057952040B8 +:10063000E7B101003094004045990100640000409A +:10064000E599010056952040E7B10100B89420419A +:10065000E5B10100BA942041E5B101009894004051 +:1006600045990100020000409798010000000040F9 +:10067000F1B10100CB98A24197500000000000406A +:1006800097B00100000000406FB101000000004B76 +:1006900068B10100CF988541974000008004004078 +:1006A000813201000000004039B301000000004029 +:1006B00037B301000000004035B3010000000040E6 +:1006C00033B301000000004041B3010000000040CE +:1006D0003FB30100EE050040259B010042000040B1 +:1006E0004B9B0100000000402FB3010000000040C0 +:1006F0002DB301000000004047B30100000000409E +:1007000043B30100600000402B9B01000000005437 +:10071000EF93010000000055F1930100FFFF00A5D9 +:100720003C8B01000000002C5BB301000000002C9A +:1007300045B301000000004059B301000000004033 +:1007400057B301000000004027B301000000004043 +:1007500053B30100EB98A250FD7F0000EB98A2512B +:10076000FD7F0000EC9800401DB3000050460040A3 +:100770001D9B010000C000A688B30100FF3F00A63A +:100780003AB3010000C0009D3B9B0100B40500404E +:10079000239B0100000000404DB30100080A00A6A1 +:1007A00014B301000101008A159B01000000002024 +:1007B00087B30100008000A656B101000000805EF2 +:1007C00057B501001800004B20E401000600004B63 +:1007D00096E401000043004B96C801001800001089 +:1007E00020DC01000000004B209401000000805735 +:1007F0002190010000992E0A97B0010000000040EE +:10080000F1B10100FD98A2419750000000030040A3 +:100810009798010000A900404599010000000040A0 +:10082000F1B101000199A241975000003000004051 +:10083000979801000000005561B101000000004BD5 +:1008400062B101000599A840813200000599A241DA +:10085000975000000000804081B201001000004E5F +:1008600098E4010000000007989401000000004394 +:1008700099E0010000000080989401000000004809 +:1008800099E001000000004C889401000F996A4033 +:10089000813200001299224F777D0000F004004061 +:1008A000813201000000004F61B1010000000044EE +:1008B00062B101001399A840813200001A99224ABE +:1008C000897C00001899224F777D0000F0040040D9 +:1008D000813201000000004562B101001899A84072 +:1008E000813200000000FA4081B201000000804027 +:1008F00081B201000400A25A1F7C00001000000F0A +:1009000098F401000400A25F9904000000008040F8 +:1009100081B201000000804081B20100040000406B +:1009200081B200000400004081B2000004000040D9 +:1009300081B200000400004081B2000004000040C9 +:1009400081B200000400004081B2000004000040B9 +:1009500081B200000400004081B2000004000040A9 +:1009600081B200000400004081B200000400004099 +:1009700081B200000400004081B200000400004089 +:1009800081B200000400004081B200000400004079 +:1009900081B200000400004081B200000400004069 +:1009A00081B200000400004081B200000400004059 +:1009B00081B200000400004081B200000400004049 +:1009C00081B200000400004081B200000400004039 +:1009D00081B200000400004081B200000400004029 +:1009E00081B200000400004081B200000400004019 +:1009F00081B200000400004081B200000400004009 +:100A000081B200000400004081B2000004000040F8 +:100A100081B200000400004081B2000004000040E8 +:100A200081B200000400004081B2000004000040D8 +:100A300081B200000400004081B2000004000040C8 +:100A400081B200000400004081B2000004000040B8 +:100A500081B200000400004081B2000004000040A8 +:100A600081B200000400004081B200000400004098 +:100A700081B200000400004081B200000400004088 +:100A800081B200000400004081B200000400004078 +:100A900081B200000400004081B200000400004068 +:100AA00081B200000400004081B200000400004058 +:100AB00081B200000400004081B200000400004048 +:100AC00081B200000400004081B200000400004038 +:100AD00081B200000400004081B200000400004028 +:100AE00081B200000400004081B200000400004018 +:100AF00081B200000400004081B200000400004008 +:100B000081B200000400004081B2000004000040F7 +:100B100081B200000400004081B2000004000040E7 +:100B200081B200000400004081B2000004000040D7 +:100B300081B200000400004081B2000004000040C7 +:100B400081B200000400004081B2000004000040B7 +:100B500081B200000400004081B2000004000040A7 +:100B600081B200000400004081B200000400004097 +:100B700081B200000400004081B200000400004087 +:100B800081B200000400004081B200000400004077 +:100B900081B200000400004081B200000400004067 +:100BA00081B200000400004081B200000400004057 +:100BB00081B200000400004081B200000400004047 +:100BC00081B200000400004081B200000400004037 +:100BD00081B200000400004081B200000400004027 +:100BE00081B200000400004081B200000400004017 +:100BF00081B200000400004081B200000400004007 +:100C000081B200000400004081B2000004000040F6 +:100C100081B200000400004081B2000004000040E6 +:100C200081B200000400004081B2000004000040D6 +:100C300081B200000400004081B2000004000040C6 +:100C400081B200000400004081B2000004000040B6 +:100C500081B200000400004081B2000004000040A6 +:100C600081B200000400004081B200000400004096 +:100C700081B200000400004081B200000400004086 +:100C800081B200000400004081B200000400004076 +:100C900081B200000400004081B200000400004066 +:100CA00081B200000400004081B200000400004056 +:100CB00081B200000400004081B200000400004046 +:100CC00081B200000400004081B200000400004036 +:100CD00081B200000400004081B200000400004026 +:100CE00081B200000400004081B200000400004016 +:100CF00081B200000400004081B200000400004006 +:100D000081B200000400004081B2000004000040F5 +:100D100081B200000400004081B2000004000040E5 +:100D200081B200000400004081B2000004000040D5 +:100D300081B200000400004081B2000004000040C5 +:100D400081B200000400004081B2000004000040B5 +:100D500081B200000400004081B2000004000040A5 +:100D600081B200000400004081B200000400004095 +:100D700081B200000400004081B200000400004085 +:100D800081B200000400004081B200000400004075 +:100D900081B200000400004081B200000400004065 +:100DA00081B200000400004081B200000400004055 +:100DB00081B200000400004081B200000400004045 +:100DC00081B200000400004081B200000400004035 +:100DD00081B200000400004081B200000400004025 +:100DE00081B200000400004081B200000400004015 +:100DF00081B200000400004081B200000400004005 +:100E000081B200000400004081B2000004000040F4 +:100E100081B200000400004081B2000004000040E4 +:100E200081B200000400004081B2000004000040D4 +:100E300081B200000400004081B2000004000040C4 +:100E400081B200000400004081B2000004000040B4 +:100E500081B200000400004081B2000004000040A4 +:100E600081B200000400004081B200000400004094 +:100E700081B200000400004081B200000400004084 +:100E800081B200000400004081B200000400004074 +:100E900081B200000400004081B200000400004064 +:100EA00081B200000400004081B200000400004054 +:100EB00081B200000400004081B200000400004044 +:100EC00081B200000400004081B200000400004034 +:100ED00081B200000400004081B200000400004024 +:100EE00081B200000400004081B200000400004014 +:100EF00081B200000400004081B200000400004004 +:100F000081B200000400004081B2000004000040F3 +:100F100081B200000400004081B2000004000040E3 +:100F200081B200000400004081B2000004000040D3 +:100F300081B200000400004081B2000004000040C3 +:100F400081B200000400004081B2000004000040B3 +:100F500081B200000400004081B2000004000040A3 +:100F600081B200000400004081B200000400004093 +:100F700081B200000400004081B200000400004083 +:100F800081B200000400004081B200000400004073 +:100F900081B200000400004081B200000400004063 +:100FA00081B200000400004081B200000400004053 +:100FB00081B200000400004081B200000400004043 +:100FC00081B200000400004081B200000400004033 +:100FD00081B200000400004081B200000400004023 +:100FE00081B200000400004081B200000400004013 +:100FF00081B200000400004081B200000400004003 +:1010000081B200000400004081B2000004000040F2 +:1010100081B200000400004081B2000004000040E2 +:1010200081B200000400004081B2000004000040D2 +:1010300081B200000400004081B2000004000040C2 +:1010400081B200000400004081B2000004000040B2 +:1010500081B200000400004081B2000004000040A2 +:1010600081B200000400004081B200000400004092 +:1010700081B200000400004081B200000400004082 +:1010800081B200000400004081B200000400004072 +:1010900081B200000400004081B200000400004062 +:1010A00081B200000400004081B200000400004052 +:1010B00081B200000400004081B200000400004042 +:1010C00081B200000400004081B200000400004032 +:1010D00081B200000400004081B200000400004022 +:1010E00081B200000400004081B200000400004012 +:1010F00081B200000400004081B200000400004002 +:1011000081B200000400004081B2000004000040F1 +:1011100081B200000400004081B2000004000040E1 +:1011200081B200000400004081B2000004000040D1 +:1011300081B200000400004081B2000004000040C1 +:1011400081B200000400004081B2000004000040B1 +:1011500081B200000400004081B2000004000040A1 +:1011600081B200000400004081B200000400004091 +:1011700081B200000400004081B200000400004081 +:1011800081B200000400004081B200000400004071 +:1011900081B200000400004081B200000400004061 +:1011A00081B200000400004081B200000400004051 +:1011B00081B200000400004081B200000400004041 +:1011C00081B200000400004081B200000400004031 +:1011D00081B200000400004081B200000400004021 +:1011E00081B200000400004081B200000400004011 +:1011F00081B200000400004081B200000400004001 +:1012000081B200000400004081B2000004000040F0 +:1012100081B200000400004081B2000004000040E0 +:1012200081B200000400004081B2000004000040D0 +:1012300081B200000400004081B2000004000040C0 +:1012400081B200000400004081B2000004000040B0 +:1012500081B200000400004081B2000004000040A0 +:1012600081B200000400004081B200000400004090 +:1012700081B200000400004081B200000400004080 +:1012800081B200000400004081B200000400004070 +:1012900081B200000400004081B200000400004060 +:1012A00081B200000400004081B200000400004050 +:1012B00081B200000400004081B200000400004040 +:1012C00081B200000400004081B200000400004030 +:1012D00081B200000400004081B200000400004020 +:1012E00081B200000400004081B200000400004010 +:1012F00081B200000400004081B200000400004000 +:1013000081B200000400004081B2000004000040EF +:1013100081B200000400004081B2000004000040DF +:1013200081B200000400004081B2000004000040CF +:1013300081B200000400004081B2000004000040BF +:1013400081B200000400004081B2000004000040AF +:1013500081B200000400004081B20000040000409F +:1013600081B200000400004081B20000040000408F +:1013700081B200000400004081B20000040000407F +:1013800081B200000400004081B20000040000406F +:1013900081B200000400004081B20000040000405F +:1013A00081B200000400004081B20000040000404F +:1013B00081B200000400004081B20000040000403F +:1013C00081B200000400004081B20000040000402F +:1013D00081B200000400004081B20000040000401F +:1013E00081B200000400004081B20000040000400F +:1013F00081B200000400004081B2000004000040FF +:1014000081B200000400004081B2000004000040EE +:1014100081B200000400004081B2000004000040DE +:1014200081B200000400004081B2000004000040CE +:1014300081B200000400004081B2000004000040BE +:1014400081B200000400004081B2000004000040AE +:1014500081B200000400004081B20000040000409E +:1014600081B200000400004081B20000040000408E +:1014700081B200000400004081B20000040000407E +:1014800081B200000400004081B20000040000406E +:1014900081B200000400004081B20000040000405E +:1014A00081B200000400004081B20000040000404E +:1014B00081B200000400004081B20000040000403E +:1014C00081B200000400004081B20000040000402E +:1014D00081B200000400004081B20000040000401E +:1014E00081B200000400004081B20000040000400E +:1014F00081B200000400004081B2000004000040FE +:1015000081B200000400004081B2000004000040ED +:1015100081B200000400004081B2000004000040DD +:1015200081B200000400004081B2000004000040CD +:1015300081B200000400004081B2000004000040BD +:1015400081B200000400004081B2000004000040AD +:1015500081B200000400004081B20000040000409D +:1015600081B200000400004081B20000040000408D +:1015700081B200000400004081B20000040000407D +:1015800081B200000400004081B20000040000406D +:1015900081B200000400004081B20000040000405D +:1015A00081B200000400004081B20000040000404D +:1015B00081B200000400004081B20000040000403D +:1015C00081B200000400004081B20000040000402D +:1015D00081B200000400004081B20000040000401D +:1015E00081B200000400004081B20000040000400D +:1015F00081B200000400004081B2000004000040FD +:1016000081B200000400004081B2000004000040EC +:1016100081B200000400004081B2000004000040DC +:1016200081B200000400004081B2000004000040CC +:1016300081B200000400004081B2000004000040BC +:1016400081B200000400004081B2000004000040AC +:1016500081B200000400004081B20000040000409C +:1016600081B200000400004081B20000040000408C +:1016700081B200000400004081B20000040000407C +:1016800081B200000400004081B20000040000406C +:1016900081B200000400004081B20000040000405C +:1016A00081B200000400004081B20000040000404C +:1016B00081B200000400004081B20000040000403C +:1016C00081B200000400004081B20000040000402C +:1016D00081B200000400004081B20000040000401C +:1016E00081B200000400004081B20000040000400C +:1016F00081B200000400004081B2000004000040FC +:1017000081B200000400004081B2000004000040EB +:1017100081B200000400004081B2000004000040DB +:1017200081B200000400004081B2000004000040CB +:1017300081B200000400004081B2000004000040BB +:1017400081B200000400004081B2000004000040AB +:1017500081B200000400004081B20000040000409B +:1017600081B200000400004081B20000040000408B +:1017700081B200000400004081B20000040000407B +:1017800081B200000400004081B20000040000406B +:1017900081B200000400004081B20000040000405B +:1017A00081B200000400004081B20000040000404B +:1017B00081B200000400004081B20000040000403B +:1017C00081B200000400004081B20000040000402B +:1017D00081B200000400004081B20000040000401B +:1017E00081B200000400004081B20000040000400B +:1017F00081B200000400004081B2000004000040FB +:1018000081B200000400004081B2000004000040EA +:1018100081B200000400004081B2000004000040DA +:1018200081B200000400004081B2000004000040CA +:1018300081B200000400004081B2000004000040BA +:1018400081B200000400004081B2000004000040AA +:1018500081B200000400004081B20000040000409A +:1018600081B200000400004081B20000040000408A +:1018700081B200000400004081B20000040000407A +:1018800081B200000400004081B20000040000406A +:1018900081B200000400004081B20000040000405A +:1018A00081B200000400004081B20000040000404A +:1018B00081B200000400004081B20000040000403A +:1018C00081B200000400004081B20000040000402A +:1018D00081B200000400004081B20000040000401A +:1018E00081B200000400004081B20000040000400A +:1018F00081B200000400004081B2000004000040FA +:1019000081B200000400004081B2000004000040E9 +:1019100081B200000400004081B2000004000040D9 +:1019200081B200000400004081B2000004000040C9 +:1019300081B200000400004081B2000004000040B9 +:1019400081B200000400004081B2000004000040A9 +:1019500081B200000400004081B200000400004099 +:1019600081B200000400004081B200000400004089 +:1019700081B200000400004081B200000400004079 +:1019800081B200000400004081B200000400004069 +:1019900081B200000400004081B200000400004059 +:1019A00081B200000400004081B200000400004049 +:1019B00081B200000400004081B200000400004039 +:1019C00081B200000400004081B200000400004029 +:1019D00081B200000400004081B200000400004019 +:1019E00081B200000400004081B200000400004009 +:1019F00081B200000400004081B2000004000040F9 +:101A000081B200000400004081B2000004000040E8 +:101A100081B200000400004081B2000004000040D8 +:101A200081B200000400004081B2000004000040C8 +:101A300081B200000400004081B2000004000040B8 +:101A400081B200000400004081B2000004000040A8 +:101A500081B200000400004081B200000400004098 +:101A600081B200000400004081B200000400004088 +:101A700081B200000400004081B200000400004078 +:101A800081B200000400004081B200000400004068 +:101A900081B200000400004081B200000400004058 +:101AA00081B200000400004081B200000400004048 +:101AB00081B200000400004081B200000400004038 +:101AC00081B200000400004081B200000400004028 +:101AD00081B200000400004081B200000400004018 +:101AE00081B200000400004081B200000400004008 +:101AF00081B200000400004081B2000004000040F8 +:101B000081B200000400004081B2000004000040E7 +:101B100081B200000400004081B2000004000040D7 +:101B200081B200000400004081B2000004000040C7 +:101B300081B200000400004081B2000004000040B7 +:101B400081B200000400004081B2000004000040A7 +:101B500081B200000400004081B200000400004097 +:101B600081B200000400004081B200000400004087 +:101B700081B200000400004081B200000400004077 +:101B800081B200000400004081B200000400004067 +:101B900081B200000400004081B200000400004057 +:101BA00081B200000400004081B200000400004047 +:101BB00081B200000400004081B200000400004037 +:101BC00081B200000400004081B200000400004027 +:101BD00081B200000400004081B200000400004017 +:101BE00081B200000400004081B200000400004007 +:101BF00081B200000400004081B2000004000040F7 +:101C000081B200000400004081B2000004000040E6 +:101C100081B200000400004081B2000004000040D6 +:101C200081B200000400004081B2000004000040C6 +:101C300081B200000400004081B2000004000040B6 +:101C400081B200000400004081B2000004000040A6 +:101C500081B200000400004081B200000400004096 +:101C600081B200000400004081B200000400004086 +:101C700081B200000400004081B200000400004076 +:101C800081B200000400004081B200000400004066 +:101C900081B200000400004081B200000400004056 +:101CA00081B200000400004081B200000400004046 +:101CB00081B200000400004081B200000400004036 +:101CC00081B200000400004081B200000400004026 +:101CD00081B200000400004081B200000400004016 +:101CE00081B200000400004081B200000400004006 +:101CF00081B200000400004081B2000004000040F6 +:101D000081B200000400004081B2000004000040E5 +:101D100081B200000400004081B2000004000040D5 +:101D200081B200000400004081B2000004000040C5 +:101D300081B200000400004081B2000004000040B5 +:101D400081B200000400004081B2000004000040A5 +:101D500081B200000400004081B200000400004095 +:101D600081B200000400004081B200000400004085 +:101D700081B200000400004081B200000400004075 +:101D800081B200000400004081B200000400004065 +:101D900081B200000400004081B200000400004055 +:101DA00081B200000400004081B200000400004045 +:101DB00081B200000400004081B200000400004035 +:101DC00081B200000400004081B200000400004025 +:101DD00081B200000400004081B200000400004015 +:101DE00081B200000400004081B200000400004005 +:101DF00081B200000400004081B2000004000040F5 +:101E000081B200000400004081B2000004000040E4 +:101E100081B200000400004081B2000004000040D4 +:101E200081B200000400004081B2000004000040C4 +:101E300081B200000400004081B2000004000040B4 +:101E400081B200000400004081B2000004000040A4 +:101E500081B200000400004081B200000400004094 +:101E600081B200000400004081B200000400004084 +:101E700081B200000400004081B200000400004074 +:101E800081B200000400004081B200000400004064 +:101E900081B200000400004081B200000400004054 +:101EA00081B200000400004081B200000400004044 +:101EB00081B200000400004081B200000400004034 +:101EC00081B200000400004081B200000400004024 +:101ED00081B200000400004081B200000400004014 +:101EE00081B200000400004081B200000400004004 +:101EF00081B200000400004081B2000004000040F4 +:101F000081B200000400004081B2000004000040E3 +:101F100081B200000400004081B2000004000040D3 +:101F200081B200000400004081B2000004000040C3 +:101F300081B200000400004081B2000004000040B3 +:101F400081B200000400004081B2000004000040A3 +:101F500081B200000400004081B200000400004093 +:101F600081B200000400004081B200000400004083 +:101F700081B200000400004081B200000400004073 +:101F800081B200000400004081B200000400004063 +:101F900081B200000400004081B200000400004053 +:101FA00081B200000400004081B200000400004043 +:101FB00081B200000400004081B200000400004033 +:101FC00081B200000400004081B200000400004023 +:101FD00081B200000400004081B200000400004013 +:101FE00081B200000400004081B200000400004003 +:101FF00081B200000400004081B2000004000040F3 +:1020000081B200000400004081B2000004000040E2 +:1020100081B200000400004081B2000004000040D2 +:1020200081B200000400004081B2000004000040C2 +:1020300081B200000400004081B2000004000040B2 +:1020400081B200000400004081B2000004000040A2 +:1020500081B200000400004081B200000400004092 +:1020600081B200000400004081B200000400004082 +:1020700081B200000400004081B200000400004072 +:1020800081B200000400004081B200000400004062 +:1020900081B200000400004081B200000400004052 +:1020A00081B200000400004081B200000400004042 +:1020B00081B200000400004081B200000400004032 +:1020C00081B200000400004081B200000400004022 +:1020D00081B200000400004081B200000400004012 +:1020E00081B200000400004081B200000400004002 +:1020F00081B200000400004081B2000004000040F2 +:1021000081B200000400004081B2000004000040E1 +:1021100081B200000400004081B2000004000040D1 +:1021200081B200000400004081B2000004000040C1 +:1021300081B200000400004081B2000004000040B1 +:1021400081B200000400004081B2000004000040A1 +:1021500081B200000400004081B200000400004091 +:1021600081B200000400004081B200000400004081 +:1021700081B200000400004081B200000400004071 +:1021800081B200000400004081B200000400004061 +:1021900081B200000400004081B200000400004051 +:1021A00081B200000400004081B200000400004041 +:1021B00081B200000400004081B200000400004031 +:1021C00081B200000400004081B200000400004021 +:1021D00081B200000400004081B200000400004011 +:1021E00081B200000400004081B200000400004001 +:1021F00081B200000400004081B2000004000040F1 +:1022000081B200000400004081B2000004000040E0 +:1022100081B200000400004081B2000004000040D0 +:1022200081B200000400004081B2000004000040C0 +:1022300081B200000400004081B2000004000040B0 +:1022400081B200000400004081B2000004000040A0 +:1022500081B200000400004081B200000400004090 +:1022600081B200000400004081B200000400004080 +:1022700081B200000400004081B200000400004070 +:1022800081B200000400004081B200000400004060 +:1022900081B200000400004081B200000400004050 +:1022A00081B200000400004081B200000400004040 +:1022B00081B200000400004081B200000400004030 +:1022C00081B200000400004081B200000400004020 +:1022D00081B200000400004081B200000400004010 +:1022E00081B200000400004081B200000400004000 +:1022F00081B200000400004081B2000004000040F0 +:1023000081B200000400004081B2000004000040DF +:1023100081B200000400004081B2000004000040CF +:1023200081B200000400004081B2000004000040BF +:1023300081B200000400004081B2000004000040AF +:1023400081B200000400004081B20000040000409F +:1023500081B200000400004081B20000040000408F +:1023600081B200000400004081B20000040000407F +:1023700081B200000400004081B20000040000406F +:1023800081B200000400004081B20000040000405F +:1023900081B200000400004081B20000040000404F +:1023A00081B200000400004081B20000040000403F +:1023B00081B200000400004081B20000040000402F +:1023C00081B200000400004081B20000040000401F +:1023D00081B200000400004081B20000040000400F +:1023E00081B200000400004081B2000004000040FF +:1023F00081B200000400004081B2000004000040EF +:1024000081B200000400004081B2000004000040DE +:1024100081B200000400004081B2000004000040CE +:1024200081B200000400004081B2000004000040BE +:1024300081B200000400004081B2000004000040AE +:1024400081B200000400004081B20000040000409E +:1024500081B200000400004081B20000040000408E +:1024600081B200000400004081B20000040000407E +:1024700081B200000400004081B20000040000406E +:1024800081B200000400004081B20000040000405E +:1024900081B200000400004081B20000040000404E +:1024A00081B200000400004081B20000040000403E +:1024B00081B200000400004081B20000040000402E +:1024C00081B200000400004081B20000040000401E +:1024D00081B200000400004081B20000040000400E +:1024E00081B200000400004081B2000004000040FE +:1024F00081B200000400004081B2000004000040EE +:1025000081B200000400004081B2000004000040DD +:1025100081B200000400004081B2000004000040CD +:1025200081B200000400004081B2000004000040BD +:1025300081B200000400004081B2000004000040AD +:1025400081B200000400004081B20000040000409D +:1025500081B200000400004081B20000040000408D +:1025600081B200000400004081B20000040000407D +:1025700081B200000400004081B20000040000406D +:1025800081B200000400004081B20000040000405D +:1025900081B200000400004081B20000040000404D +:1025A00081B200000400004081B20000040000403D +:1025B00081B200000400004081B20000040000402D +:1025C00081B200000400004081B20000040000401D +:1025D00081B200000400004081B20000040000400D +:1025E00081B200000400004081B2000004000040FD +:1025F00081B200000400004081B2000004000040ED +:1026000081B200000400004081B2000004000040DC +:1026100081B200000400004081B2000004000040CC +:1026200081B200000400004081B2000004000040BC +:1026300081B200000400004081B2000004000040AC +:1026400081B200000400004081B20000040000409C +:1026500081B200000400004081B20000040000408C +:1026600081B200000400004081B20000040000407C +:1026700081B200000400004081B20000040000406C +:1026800081B200000400004081B20000040000405C +:1026900081B200000400004081B20000040000404C +:1026A00081B200000400004081B20000040000403C +:1026B00081B200000400004081B20000040000402C +:1026C00081B200000400004081B20000040000401C +:1026D00081B200000400004081B20000040000400C +:1026E00081B200000400004081B2000004000040FC +:1026F00081B200000400004081B2000004000040EC +:1027000081B200000400004081B2000004000040DB +:1027100081B200000400004081B2000004000040CB +:1027200081B200000400004081B2000004000040BB +:1027300081B200000400004081B2000004000040AB +:1027400081B200000400004081B20000040000409B +:1027500081B200000400004081B20000040000408B +:1027600081B200000400004081B20000040000407B +:1027700081B200000400004081B20000040000406B +:1027800081B200000400004081B20000040000405B +:1027900081B200000400004081B20000040000404B +:1027A00081B200000400004081B20000040000403B +:1027B00081B200000400004081B20000040000402B +:1027C00081B200000400004081B20000040000401B +:1027D00081B200000400004081B20000040000400B +:1027E00081B200000400004081B2000004000040FB +:1027F00081B200000400004081B2000004000040EB +:1028000081B200000400004081B2000004000040DA +:1028100081B200000400004081B2000004000040CA +:1028200081B200000400004081B2000004000040BA +:1028300081B200000400004081B2000004000040AA +:1028400081B200000400004081B20000040000409A +:1028500081B200000400004081B20000040000408A +:1028600081B200000400004081B20000040000407A +:1028700081B200000400004081B20000040000406A +:1028800081B200000400004081B20000040000405A +:1028900081B200000400004081B20000040000404A +:1028A00081B200000400004081B20000040000403A +:1028B00081B200000400004081B20000040000402A +:1028C00081B200000400004081B20000040000401A +:1028D00081B200000400004081B20000040000400A +:1028E00081B200000400004081B2000004000040FA +:1028F00081B200000400004081B2000004000040EA +:1029000081B200000400004081B2000004000040D9 +:1029100081B200000400004081B2000004000040C9 +:1029200081B200000400004081B2000004000040B9 +:1029300081B200000400004081B2000004000040A9 +:1029400081B200000400004081B200000400004099 +:1029500081B200000400004081B200000400004089 +:1029600081B200000400004081B200000400004079 +:1029700081B200000400004081B200000400004069 +:1029800081B200000400004081B200000400004059 +:1029900081B200000400004081B200000400004049 +:1029A00081B200000400004081B200000400004039 +:1029B00081B200000400004081B200000400004029 +:1029C00081B200000400004081B200000400004019 +:1029D00081B200000400004081B200000400004009 +:1029E00081B200000400004081B2000004000040F9 +:1029F00081B200000400004081B2000004000040E9 +:102A000081B200000400004081B2000004000040D8 +:102A100081B200000400004081B2000004000040C8 +:102A200081B200000400004081B2000004000040B8 +:102A300081B200000400004081B2000004000040A8 +:102A400081B200000400004081B200000400004098 +:102A500081B200000400004081B200000400004088 +:102A600081B200000400004081B200000400004078 +:102A700081B200000400004081B200000400004068 +:102A800081B200000400004081B200000400004058 +:102A900081B200000400004081B200000400004048 +:102AA00081B200000400004081B200000400004038 +:102AB00081B200000400004081B200000400004028 +:102AC00081B200000400004081B200000400004018 +:102AD00081B200000400004081B200000400004008 +:102AE00081B200000400004081B2000004000040F8 +:102AF00081B200000400004081B2000004000040E8 +:102B000081B200000400004081B2000004000040D7 +:102B100081B200000400004081B2000004000040C7 +:102B200081B200000400004081B2000004000040B7 +:102B300081B200000400004081B2000004000040A7 +:102B400081B200000400004081B200000400004097 +:102B500081B200000400004081B200000400004087 +:102B600081B200000400004081B200000400004077 +:102B700081B200000400004081B200000400004067 +:102B800081B200000400004081B200000400004057 +:102B900081B200000400004081B200000400004047 +:102BA00081B200000400004081B200000400004037 +:102BB00081B200000400004081B200000400004027 +:102BC00081B200000400004081B200000400004017 +:102BD00081B200000400004081B200000400004007 +:102BE00081B200000400004081B2000004000040F7 +:102BF00081B200000400004081B2000004000040E7 +:102C000081B200000400004081B2000004000040D6 +:102C100081B200000400004081B2000004000040C6 +:102C200081B200000400004081B2000004000040B6 +:102C300081B200000400004081B2000004000040A6 +:102C400081B200000400004081B200000400004096 +:102C500081B200000400004081B200000400004086 +:102C600081B200000400004081B200000400004076 +:102C700081B200000400004081B200000400004066 +:102C800081B200000400004081B200000400004056 +:102C900081B200000400004081B200000400004046 +:102CA00081B200000400004081B200000400004036 +:102CB00081B200000400004081B200000400004026 +:102CC00081B200000400004081B200000400004016 +:102CD00081B200000400004081B200000400004006 +:102CE00081B200000400004081B2000004000040F6 +:102CF00081B200000400004081B2000004000040E6 +:102D000081B200000400004081B2000004000040D5 +:102D100081B200000400004081B2000004000040C5 +:102D200081B200000400004081B2000004000040B5 +:102D300081B200000400004081B2000004000040A5 +:102D400081B200000400004081B200000400004095 +:102D500081B200000400004081B200000400004085 +:102D600081B200000400004081B200000400004075 +:102D700081B200000400004081B200000400004065 +:102D800081B200000400004081B200000400004055 +:102D900081B200000400004081B200000400004045 +:102DA00081B200000400004081B200000400004035 +:102DB00081B200000400004081B200000400004025 +:102DC00081B200000400004081B200000400004015 +:102DD00081B200000400004081B200000400004005 +:102DE00081B200000400004081B2000004000040F5 +:102DF00081B200000400004081B2000004000040E5 +:102E000081B200000400004081B2000004000040D4 +:102E100081B200000400004081B2000004000040C4 +:102E200081B200000400004081B2000004000040B4 +:102E300081B200000400004081B2000004000040A4 +:102E400081B200000400004081B200000400004094 +:102E500081B200000400004081B200000400004084 +:102E600081B200000400004081B200000400004074 +:102E700081B200000400004081B200000400004064 +:102E800081B200000400004081B200000400004054 +:102E900081B200000400004081B200000400004044 +:102EA00081B200000400004081B200000400004034 +:102EB00081B200000400004081B200000400004024 +:102EC00081B200000400004081B200000400004014 +:102ED00081B200000400004081B200000400004004 +:102EE00081B200000400004081B2000004000040F4 +:102EF00081B200000400004081B2000004000040E4 +:102F000081B200000400004081B2000004000040D3 +:102F100081B200000400004081B2000004000040C3 +:102F200081B200000400004081B2000004000040B3 +:102F300081B200000400004081B2000004000040A3 +:102F400081B200000400004081B200000400004093 +:102F500081B200000400004081B200000400004083 +:102F600081B200000400004081B200000400004073 +:102F700081B200000400004081B200000400004063 +:102F800081B200000400004081B200000400004053 +:102F900081B200000400004081B200000400004043 +:102FA00081B200000400004081B200000400004033 +:102FB00081B200000400004081B200000400004023 +:102FC00081B200000400004081B200000400004013 +:102FD00081B200000400004081B200000400004003 +:102FE00081B200000400004081B2000004000040F3 +:102FF00081B200000400004081B2000004000040E3 +:1030000081B200000400004081B2000004000040D2 +:1030100081B200000400004081B2000004000040C2 +:1030200081B200000400004081B2000004000040B2 +:1030300081B200000400004081B2000004000040A2 +:1030400081B200000400004081B200000400004092 +:1030500081B200000400004081B200000400004082 +:1030600081B200000400004081B200000400004072 +:1030700081B200000400004081B200000400004062 +:1030800081B200000400004081B200000400004052 +:1030900081B200000400004081B200000400004042 +:1030A00081B200000400004081B200000400004032 +:1030B00081B200000400004081B200000400004022 +:1030C00081B200000400004081B200000400004012 +:1030D00081B200000400004081B200000400004002 +:1030E00081B200000400004081B2000004000040F2 +:1030F00081B200000400004081B2000004000040E2 +:1031000081B200000400004081B2000004000040D1 +:1031100081B200000400004081B2000004000040C1 +:1031200081B200000400004081B2000004000040B1 +:1031300081B200000400004081B2000004000040A1 +:1031400081B200000400004081B200000400004091 +:1031500081B200000400004081B200000400004081 +:1031600081B200000400004081B200000400004071 +:1031700081B200000400004081B200000400004061 +:1031800081B200000400004081B200000400004051 +:1031900081B200000400004081B200000400004041 +:1031A00081B200000400004081B200000400004031 +:1031B00081B200000400004081B200000400004021 +:1031C00081B200000400004081B200000400004011 +:1031D00081B200000400004081B200000400004001 +:1031E00081B200000400004081B2000004000040F1 +:1031F00081B200000400004081B2000004000040E1 +:1032000081B200000400004081B2000004000040D0 +:1032100081B200000400004081B2000004000040C0 +:1032200081B200000400004081B2000004000040B0 +:1032300081B200000400004081B2000004000040A0 +:1032400081B200000400004081B200000400004090 +:1032500081B200000400004081B200000400004080 +:1032600081B200000400004081B200000400004070 +:1032700081B200000400004081B200000400004060 +:1032800081B200000400004081B200000400004050 +:1032900081B200000400004081B200000400004040 +:1032A00081B200000400004081B200000400004030 +:1032B00081B200000400004081B200000400004020 +:1032C00081B200000400004081B200000400004010 +:1032D00081B200000400004081B200000400004000 +:1032E00081B200000400004081B2000004000040F0 +:1032F00081B200000400004081B2000004000040E0 +:1033000081B200000400004081B2000004000040CF +:1033100081B200000400004081B2000004000040BF +:1033200081B200000400004081B2000004000040AF +:1033300081B200000400004081B20000040000409F +:1033400081B200000400004081B20000040000408F +:1033500081B200000400004081B20000040000407F +:1033600081B200000400004081B20000040000406F +:1033700081B200000400004081B20000040000405F +:1033800081B200000400004081B20000040000404F +:1033900081B200000400004081B20000040000403F +:1033A00081B200000400004081B20000040000402F +:1033B00081B200000400004081B20000040000401F +:1033C00081B200000400004081B20000040000400F +:1033D00081B200000400004081B2000004000040FF +:1033E00081B200000400004081B2000004000040EF +:1033F00081B200000400004081B2000004000040DF +:1034000081B200000400004081B2000004000040CE +:1034100081B200000400004081B2000004000040BE +:1034200081B200000400004081B2000004000040AE +:1034300081B200000400004081B20000040000409E +:1034400081B200000400004081B20000040000408E +:1034500081B200000400004081B20000040000407E +:1034600081B200000400004081B20000040000406E +:1034700081B200000400004081B20000040000405E +:1034800081B200000400004081B20000040000404E +:1034900081B200000400004081B20000040000403E +:1034A00081B200000400004081B20000040000402E +:1034B00081B200000400004081B20000040000401E +:1034C00081B200000400004081B20000040000400E +:1034D00081B200000400004081B2000004000040FE +:1034E00081B200000400004081B2000004000040EE +:1034F00081B200000400004081B2000004000040DE +:1035000081B200000400004081B2000004000040CD +:1035100081B200000400004081B2000004000040BD +:1035200081B200000400004081B2000004000040AD +:1035300081B200000400004081B20000040000409D +:1035400081B200000400004081B20000040000408D +:1035500081B200000400004081B20000040000407D +:1035600081B200000400004081B20000040000406D +:1035700081B200000400004081B20000040000405D +:1035800081B200000400004081B20000040000404D +:1035900081B200000400004081B20000040000403D +:1035A00081B200000400004081B20000040000402D +:1035B00081B200000400004081B20000040000401D +:1035C00081B200000400004081B20000040000400D +:1035D00081B200000400004081B2000004000040FD +:1035E00081B200000400004081B2000004000040ED +:1035F00081B200000400004081B2000004000040DD +:1036000081B200000400004081B2000004000040CC +:1036100081B200000400004081B2000004000040BC +:1036200081B200000400004081B2000004000040AC +:1036300081B200000400004081B20000040000409C +:1036400081B200000400004081B20000040000408C +:1036500081B200000400004081B20000040000407C +:1036600081B200000400004081B20000040000406C +:1036700081B200000400004081B20000040000405C +:1036800081B200000400004081B20000040000404C +:1036900081B200000400004081B20000040000403C +:1036A00081B200000400004081B20000040000402C +:1036B00081B200000400004081B20000040000401C +:1036C00081B200000400004081B20000040000400C +:1036D00081B200000400004081B2000004000040FC +:1036E00081B200000400004081B2000004000040EC +:1036F00081B200000400004081B2000004000040DC +:1037000081B200000400004081B2000004000040CB +:1037100081B200000400004081B2000004000040BB +:1037200081B200000400004081B2000004000040AB +:1037300081B200000400004081B20000040000409B +:1037400081B200000400004081B20000040000408B +:1037500081B200000400004081B20000040000407B +:1037600081B200000400004081B20000040000406B +:1037700081B200000400004081B20000040000405B +:1037800081B200000400004081B20000040000404B +:1037900081B200000400004081B20000040000403B +:1037A00081B200000400004081B20000040000402B +:1037B00081B200000400004081B20000040000401B +:1037C00081B200000400004081B20000040000400B +:1037D00081B200000400004081B2000004000040FB +:1037E00081B200000400004081B2000004000040EB +:1037F00081B200000400004081B2000004000040DB +:1038000081B200000400004081B2000004000040CA +:1038100081B200000400004081B2000004000040BA +:1038200081B200000400004081B2000004000040AA +:1038300081B200000400004081B20000040000409A +:1038400081B200000400004081B20000040000408A +:1038500081B200000400004081B20000040000407A +:1038600081B200000400004081B20000040000406A +:1038700081B200000400004081B20000040000405A +:1038800081B200000400004081B20000040000404A +:1038900081B200000400004081B20000040000403A +:1038A00081B200000400004081B20000040000402A +:1038B00081B200000400004081B20000040000401A +:1038C00081B200000400004081B20000040000400A +:1038D00081B200000400004081B2000004000040FA +:1038E00081B200000400004081B2000004000040EA +:1038F00081B200000400004081B2000004000040DA +:1039000081B200000400004081B2000004000040C9 +:1039100081B200000400004081B2000004000040B9 +:1039200081B200000400004081B2000004000040A9 +:1039300081B200000400004081B200000400004099 +:1039400081B200000400004081B200000400004089 +:1039500081B200000400004081B200000400004079 +:1039600081B200000400004081B200000400004069 +:1039700081B200000400004081B200000400004059 +:1039800081B200000400004081B200000400004049 +:1039900081B200000400004081B200000400004039 +:1039A00081B200000400004081B200000400004029 +:1039B00081B200000400004081B200000400004019 +:1039C00081B200000400004081B200000400004009 +:1039D00081B200000400004081B2000004000040F9 +:1039E00081B200000400004081B2000004000040E9 +:1039F00081B200000400004081B2000004000040D9 +:103A000081B200000400004081B2000004000040C8 +:103A100081B200000400004081B2000004000040B8 +:103A200081B200000400004081B2000004000040A8 +:103A300081B200000400004081B200000400004098 +:103A400081B200000400004081B200000400004088 +:103A500081B200000400004081B200000400004078 +:103A600081B200000400004081B200000400004068 +:103A700081B200000400004081B200000400004058 +:103A800081B200000400004081B200000400004048 +:103A900081B200000400004081B200000400004038 +:103AA00081B200000400004081B200000400004028 +:103AB00081B200000400004081B200000400004018 +:103AC00081B200000400004081B200000400004008 +:103AD00081B200000400004081B2000004000040F8 +:103AE00081B200000400004081B2000004000040E8 +:103AF00081B200000400004081B2000004000040D8 +:103B000081B200000400004081B2000004000040C7 +:103B100081B200000400004081B2000004000040B7 +:103B200081B200000400004081B2000004000040A7 +:103B300081B200000400004081B200000400004097 +:103B400081B200000400004081B200000400004087 +:103B500081B200000400004081B200000400004077 +:103B600081B200000400004081B200000400004067 +:103B700081B200000400004081B200000400004057 +:103B800081B200000400004081B200000400004047 +:103B900081B200000400004081B200000400004037 +:103BA00081B200000400004081B200000400004027 +:103BB00081B200000400004081B200000400004017 +:103BC00081B200000400004081B200000400004007 +:103BD00081B200000400004081B2000004000040F7 +:103BE00081B200000400004081B2000004000040E7 +:103BF00081B200000400004081B2000004000040D7 +:103C000081B200000400004081B2000004000040C6 +:103C100081B200000400004081B2000004000040B6 +:103C200081B200000400004081B2000004000040A6 +:103C300081B200000400004081B200000400004096 +:103C400081B200000400004081B200000400004086 +:103C500081B200000400004081B200000400004076 +:103C600081B200000400004081B200000400004066 +:103C700081B200000400004081B200000400004056 +:103C800081B200000400004081B200000400004046 +:103C900081B200000400004081B200000400004036 +:103CA00081B200000400004081B200000400004026 +:103CB00081B200000400004081B200000400004016 +:103CC00081B200000400004081B200000400004006 +:103CD00081B200000400004081B2000004000040F6 +:103CE00081B200000400004081B2000004000040E6 +:103CF00081B200000400004081B2000004000040D6 +:103D000081B200000400004081B2000004000040C5 +:103D100081B200000400004081B2000004000040B5 +:103D200081B200000400004081B2000004000040A5 +:103D300081B200000400004081B200000400004095 +:103D400081B200000400004081B200000400004085 +:103D500081B20000AE9F00889AB00000AE9F00883C +:103D60009AB00000AE9F00889AB00000AE9F008815 +:103D70009AB00000AE9F00889AB000000000008852 +:103D80009AB00100AE9F414081320000B29F2240B4 +:103D90007B6F00000000194081B20100AE9F00401F +:103DA00081B20000000019417BB30100000000A4B3 +:103DB000C4B30100000000A1C6B3010000002FA29F +:103DC000C8B301000814004049990100A89F004DA4 +:103DD0009ACC0100BB9F2640813200000000004CBD +:103DE00049C10100B99FA2419B500000BF9F808044 +:103DF0008032000000005249FD9301000000004A9B +:103E0000FD930100C29F0042CD9300000000514A83 +:103E1000FD93010000000049FD930100C29F004393 +:103E2000CB9300000000504081B20100D29F0040BF +:103E300019990100000000F09AB001000000004450 +:103E400049D10100000040F080B201000000414D66 +:103E500080B20100CA9F00401999010000004C4047 +:103E600081B201000000004449D10100000000F0CF +:103E70009AB001000000004D10B10000000000E207 +:103E800049B10100000000E343B10100000000E47B +:103E900045B10100000000407BB301000000484F25 +:103EA00040B10100D29F004081B2000004000040F8 +:103EB00081B200000400004081B200000400004014 +:103EC00081B200000400004081B200000400004004 +:103ED00081B20000040000CB81C8010022830040B1 +:103EE000F29300005582004081B20000400500407E +:103EF00081B200001806004081B200002283004019 +:103F000081B20000C682004081B2000043810040BF +:103F100081B200004181004081B20000B8800040C1 +:103F200081B20000F087004081B20000238300408E +:103F300081B200002783004081B20000BF9400409E +:103F400081B200009498004081B200007F9400404C +:103F500081B200007F98004081B200008D95004042 +:103F600081B200001695004081B20000109500401B +:103F700081B20000B182004081B20000209900406F +:103F800081B200000400004081B200000400004043 +:103F900081B200000400004081B200000400004033 +:103FA00081B200000400004081B200000400004023 +:103FB00081B200000400004081B200000400004013 +:103FC00081B200000400004081B200000400004003 +:103FD00081B200000400004081B2000004000040F3 +:103FE00081B200000400004081B2000004000040E3 +:103FF00081B200000400004081B2000004000040D3 +:1040000081B200000400004081B2000004000040C2 +:0440100081B2000079 +:00000001FF diff --git a/firmware/slicoss/oasisdownload.sys.ihex b/firmware/slicoss/oasisdownload.sys.ihex new file mode 100644 index 000000000000..82026c2cd957 --- /dev/null +++ b/firmware/slicoss/oasisdownload.sys.ihex @@ -0,0 +1,5124 @@ +:1000000002000000004000000000010000000000AD +:10001000008000001500004081B200001B0000407D +:1000200081B200002100004081B2000003000040C6 +:1000300081B20000000000A898B001000480A24036 +:10004000FD7F00000900A249DD7D00000000004C9A +:1000500080B2010007000040D1B100000000004C58 +:1000600080B201000900A240757D000060000040E0 +:10007000619901000B00A8B17E3100000900004029 +:1000800081B2000000808F981831000010000098A5 +:1000900080E40100000041988094010000000040CD +:1000A00081B201001000009880E401000E00409829 +:1000B000809400001100004081B200000000004068 +:1000C000A59901001900294081320000190014BCD3 +:1000D000803200000E0093BC8032000000005040CF +:1000E00081B201000080004081B200001000004099 +:1000F000A59901001F002940813200001F0014BC97 +:1001000080320000120093BC80320000000050409A +:1001100081B201000180004081B200002000004057 +:10012000A59901002500294081320000250014BC5A +:1001300080320000140093BC8032000000000049AF +:10014000DD810100120100408132010033010040D5 +:10015000813201002A0014BC80320000FE0013BC72 +:10016000803200005495004045990100FFFF004097 +:10017000E599010000002F4049B101000000004056 +:10018000E1B1010000000040FDB3010000000040AB +:10019000FFB30100330018EE803200000000005071 +:1001A00089B001003200A24189500000990000404E +:1001B000813201003094004043990100000000F8B2 +:1001C00020B10100000000FAE0B30100390098EE10 +:1001D00080320000000000FB80B001003B0080F393 +:1001E000DE33000000000047FD9301003E0083F372 +:1001F00080320000F00000F38088010001800040A0 +:100200002EDD0100009400404399010000000046EB +:1002100043C10100000000FA24B101007C0018EE87 +:1002200080320000450095E880320000FFFF00E8C2 +:10023000808801007C0026408132000000000040E0 +:10024000D5990100000000F2ECB30100000000F8B5 +:10025000D6B1010008000040D5990100000000F06F +:10026000D6B10100FF0000F8EE8B0100080100404C +:10027000D5990100FF0000F0808C0100000000F71C +:100280008194010000000040D6B10100FF0000F899 +:10029000808801003C000040D5990100FF0000F07B +:1002A000D68D0100FFFF00F0F0DB010000000048E8 +:1002B00081E00100000000F8819401003C01004051 +:1002C000D599010000000040D6B10100FF0000F800 +:1002D000808801000000004881E00100000000F873 +:1002E000819401003C020040D599010000000040CB +:1002F000D6B101002C000040D5990100000000F8A3 +:10030000D6B101001E0000F082F40100FF3F00F8AA +:1003100080D80100640026408132000000000041C6 +:1003200081D00100FFFF004080D8010000000041A3 +:100330008094010000000040D8B10100680022FA5A +:10034000803000000000004C81E00100010000400E +:1003500080CC010000000040DEB10100000100403F +:10036000D5990100100000FA80E40100000000F6B9 +:100370008194010000000040D6B10100000200405D +:10038000D5990100100000FA80E40100000000F699 +:100390008194010000000040D6B101000600004039 +:1003A000D5990100100000FBD6E5010007000040D0 +:1003B000D5990100180000FBD6E501004800004077 +:1003C000D5990100100000FAD6E501005000004068 +:1003D000D5990100100000FBD6E50100030000FBE9 +:1003E0007A890100000000F0DCB101007C00004CC3 +:1003F000DD9100007C0095E88430000000002FE9CA +:10040000FAB3010000000040D1B10100FF0000423A +:10041000808801003400004080CE01007C00A640AE +:1004200081320000850000408132010002802240BC +:10043000803200007C00004081B200000000004FCC +:1004400081B001008E0009F9813200008C0008F9AA +:100450008132000098001FFDF93300008B009EFDE3 +:10046000813200000000004AF39301000000804840 +:10047000F3930100000000FDF7B301000000804984 +:10048000F3930100000000FC19B1010093000AF988 +:1004900081320000000040FB81B20100000041FDFC +:1004A00081B20100000780F9F38F0100000742F9D3 +:1004B000F38F01009700A2FFF76F00000000434098 +:1004C00081B201000000A2FFFBEF0000000080FCF1 +:1004D000E1B101000000804081B0010000940040C3 +:1004E00047990100BB000040813201000000A24694 +:1004F000FD7F01000094004047990100CE000040BC +:10050000813201000000A244FD7F01000094004000 +:100510004599010000000040F1B10100FF7F00405B +:10052000F5990100FF7F0040F59901009A13004002 +:10053000F599010007000040F59901000100004015 +:10054000F599010000020040F59901000200004009 +:10055000F599010000020040F599010003010040F7 +:10056000F599010000000040F59901009A13004040 +:10057000F59901000B000040F59901008000004052 +:10058000F599010000000040F599010000000040CD +:10059000F599010007000040F599010008000040AE +:1005A000F5990100B0020040F599010000000040FB +:1005B000F599010000000040F59901000229004072 +:1005C000F599010000000040F59901000067004026 +:1005D000F599010000000040F599010080000040FD +:1005E000F599010000008040F599010000000045E8 +:1005F000FD83010000000046FD830100FF7F0040F5 +:1006000025990100C4000040813201000000A2448D +:1006100080B2000000000045FD930100E2000040B0 +:10062000833001000000A2458032010000008046B6 +:10063000FD9301000010004083980100DD000040A0 +:100640002B3101000000A24688B0000000000041EC +:1006500089B00100000000948CB00100FFFF00464B +:1006600080880100A5A5A24080CE000000000048BF +:100670008DF00100C90082418940000000008040E7 +:1006800089B0010000000044FD830100D400004057 +:10069000813201000000A24480B20000E2000008A4 +:1006A000833001000000A245803201000000804438 +:1006B000FD93010000300008839801008000004095 +:1006C0002B990100DB000040893001000000A246A8 +:1006D00080B20000FFFF009480880100A5A5A24021 +:1006E000804E01000000804389B001000384004176 +:1006F0002C990100DE00004081B200000388004117 +:100700002C990100000000208DB0010000009F9690 +:1007100080B20000DF00A2418D5000000000804048 +:1007200081B20100FF7F0040259901000000004CCC +:1007300089E00100DD000044821401000000909473 +:100740008AB0000000000045F0B101001000004533 +:1007500088F401000000004489D00100DD0000445D +:100760002B410100EC00084180320000ED000094B4 +:1007700024B100001000009424F501000000009452 +:10078000F0B10100F200A04489500000DD000044F7 +:100790002B41010000000094F0B10100EF00204463 +:1007A000895000001000004588F40100000000FAA4 +:1007B0008AB001000000A34289D00000F700A0FA2F +:1007C0008A400000000000418BC00100F500A342F8 +:1007D00089500000FFFF0045888801001000004597 +:1007E0008AF40100FC0090448A40000000000041AF +:1007F0008BC00100FFFF00458AA801000000805067 +:100800008BE00100FF7F0040259901007C00004043 +:100810002B9901000030004083980100DD000008A2 +:1008200083140100000000942AB101000080004000 +:10083000F99B0100DD0000FC19310100000040942B +:1008400080B20100DD0000442B4101000000419412 +:1008500080B2010000000041F9C301000000004423 +:100860002BC1010004019F948032000002800040EF +:1008700081B200001001005193B000001001004D42 +:1008800093B000001001004993B000000000004246 +:1008900093B001001001A24193500000000080407D +:1008A00081B201000000104081B20100000011403F +:1008B00081B201000000124081B20100000013402B +:1008C00081B201000000144081B201000000154017 +:1008D00081B201000000164081B201000000174003 +:1008E00081B201000000184081B2010000001940EF +:1008F00081B2010000001A4081B2010000001B40DB +:1009000081B2010000001C4081B2010000001D40C6 +:1009100081B2010000001E4081B2010000001F40B2 +:1009200081B201000000704081B2010000007140FE +:1009300081B201000000724081B2010000007340EA +:1009400081B201000000744081B2010000007540D6 +:1009500081B201000000764081B2010000007740C2 +:1009600081B201000000784081B2010000007940AE +:1009700081B2010000007A4081B2010000007B409A +:1009800081B2010000007C4081B2010000007D4086 +:1009900081B2010000007E4081B2010000007F4072 +:1009A00081B201000000804081B2010000040040DB +:1009B000A199010000000050A1D1010000000040F9 +:1009C0001BB001000000004019B001000000004011 +:1009D00017B001000000004015B001000000004009 +:1009E00013B001000000004011B001000000004001 +:1009F0000FB00100000000400DB0010000000040F9 +:100A00000BB001000000004009B0010000000040F0 +:100A100007B001000000004005B0010000000040E8 +:100A200003B001000000004001B001003B0120487C +:100A3000A15100000000804081B201004701224B1B +:100A4000747D00000000804081B201006000004B16 +:100A500060990100000000B17EB101004801A8408A +:100A6000813200004501004081B200000500804055 +:100A700097980100180000AA9688010000008043A2 +:100A800097F00100070000AA96880100000080404E +:100A900081B201000000005807900100D89F00407B +:100AA00081B2000000000044A5B30100D80200405C +:100AB00081320100F8020040813201000000005C38 +:100AC00007900100D89F0040BFB300005A0122CC1C +:100AD000857F00000000005107900100D89F004072 +:100AE00081B200000000004049B10100AE0300CB1C +:100AF000A3C90100D0140040A19B01000000002008 +:100B000046B1010000000048F1B10100000000D032 +:100B1000F1B10100000000CAF1B10100000000D5F0 +:100B2000E1B10100070000406199010020000020B0 +:100B300062DD01006301A84081320000000000CCAA +:100B400085930100F802004081320100D01400407A +:100B500043990100000000FABAB30100000000FA56 +:100B6000A4B30100000000F8BCB3010000142F4042 +:100B700081B00100000000E7A7B30100000000D829 +:100B8000A9B30100FF0000DD8188010002000040E0 +:100B900080F401007301004080C80100860100DD7F +:100BA000813200000000004010B1000087010040C9 +:100BB00081B200008801004081B20000890100403C +:100BC00081B200008A01004081B200008B01004028 +:100BD00081B200008D01004081B200008F01004011 +:100BE00081B200005001004081B20000B601004017 +:100BF00081B200005001004081B20000C4010040F9 +:100C000081B20000C501004081B2000082020040B4 +:100C100081B200008302004081B22800B802004087 +:100C200081B22800D49F004081B22800D59F0040A7 +:100C300081B22800D69F004081B22800D79F004093 +:100C400081B228007201004181C02800550151493C +:100C5000FD9328005501524AFD932A00550155493C +:100C6000FD832A005501564AFD832A0050019181D7 +:100C700080302A005501454081B22A0050019182FE +:100C800080302A005501464081B22A000000004011 +:100C900089B02B0000002F4081B0010000140040FB +:100CA00049990100B30122DEE16D00000000004C13 +:100CB00049C101000000004181C001009201A2442D +:100CC000816C00000000004C49D101009A012240D3 +:100CD000E16D00009601A2418150000050010041E9 +:100CE000BFB3000000000042BFB301005001A00FDD +:100CF000BD6F0000000000DEE1B101000000004413 +:100D000049C10100B50100401999010000004240AD +:100D100081B20100000043FF85B00100000000DE49 +:100D200019B10100000042FF87B00100000043FF3D +:100D3000E1B101000000004449C1010000002FFFA3 +:100D4000E1B10100081400A480CC0100AA012640F2 +:100D5000813200000000004185C00100A801A24CC2 +:100D600081500000B40122D281320000AF01224143 +:100D7000A56F00005001A2E081320000000000D207 +:100D8000C1B301000000005C8990010000004042F6 +:100D900080B201000000414380B20100000000F079 +:100DA0008894010055010044E0B10000B101004801 +:100DB00049C10000AF01005B89900000A89F00A01E +:100DC0009EB000000000004083B00100001400400D +:100DD000499901000000234081B00100BE0122DEDC +:100DE000E16D00000000004C49C10100000000411D +:100DF00081C00100B901A244816C00005001004390 +:100E0000BFB30000000000F818B10100000040F876 +:100E100080B20100000041F080B2010000000040FB +:100E2000F1B1010000000040F1B1010055010040A6 +:100E3000E1B10000C601004091B000000000004197 +:100E400091B00100D0142E4049B1010005000040CE +:100E5000A39B0100080000DD81F40100CB010040EC +:100E600080C801000000004010B10000D101004026 +:100E700081B00000530100DEA1B30000E301004097 +:100E800081B20000E501004081B00000EB010040AC +:100E900081B20000520100DFE1B10000000000D08B +:100EA000BAB30100000000DEA1B10100020000D2CF +:100EB000A5E70100000000D2C1B30100000000005E +:100EC000F0B10100DB012244C1530000DA0184418A +:100ED00081400000DE01004081320100000000D0AE +:100EE00045B10100D5010041A1C10000DA02004076 +:100EF00081320100F802004081320100550100DD1D +:100F0000A1B100000000004081B00100400000409D +:100F1000A59B0100DA02004081320100400000D3AD +:100F2000A7CB0100F80200E0A5B3000003000040D9 +:100F3000A39B0100530100DEA1B3000000000044A8 +:100F4000BFB30100000000DE819001005001A2BA91 +:100F500080040000600000DE61990100E801A8B192 +:100F60008030000052010040E0B10000000000D0DD +:100F7000BAB301006B020040819801006002004D8D +:100F80008330010000000044E1B301000000004490 +:100F9000E3B3010000000044E5B301000000004499 +:100FA000E9B3010000000044EBB30100000000447D +:100FB000F5B3010000000044F7B301000000004455 +:100FC000F9B30100F90122408F6F00007802004060 +:100FD00081980100600200C7833001008002004058 +:100FE000819801006002004283300100000000E8A7 +:100FF000F1B10100000000E9F1B10100000000EAD8 +:10100000F1B10100000000EBF1B10100000000852A +:10101000F0B10100000000ECF1B10100000000EDB2 +:10102000F1B10100000000B2F0B10100000000A920 +:10103000F0B10100000000ACF0B10100000000AB15 +:10104000F0B10100000000B8F0B10100000000B9EB +:10105000F0B10100000000BAF0B10100000000BBD7 +:10106000F0B101000C02B8408130000000000040E7 +:10107000819001000E02B940813200000000004161 +:10108000819001001002BA4081320000000000424D +:10109000819001001202BB40813200000000004339 +:1010A000819001001402BC40813200000000004425 +:1010B000819001001602BD40813200000000004511 +:1010C000819001001802BE408132000000000046FD +:1010D000819001001A02BF408132000000000047E9 +:1010E000819001001C02C8408132000000000048CD +:1010F000819001001E02C9408132000000000049B9 +:10110000819001002002CA40813200000000004AA4 +:10111000819001002202CB40813200000000004B90 +:10112000819001002402CC40813200000000004C7C +:10113000819001002602CD40813200000000004D68 +:10114000819001002802CE40813200000000004E54 +:10115000819001002A02CF40813200000000004F40 +:10116000819001002C02F04081320000000000500C +:10117000819001002E02F1408132000000000051F8 +:10118000819001003002F2408132000000000052E4 +:10119000819001003202F3408132000000000053D0 +:1011A000819001003402F4408132000000000054BC +:1011B000819001003602F5408132000000000055A8 +:1011C000819001003802F640813200000000005694 +:1011D000819001003A02F740813200000000005780 +:1011E000819001003C02F84081320000000000586C +:1011F000819001003E02F940813200000000005958 +:10120000819001004002FA40813200000000005A43 +:10121000819001004202FB40813200000000005B2F +:10122000819001004402FC40813200000000005C1B +:10123000819001004602FD40813200000000005D07 +:10124000819001004802FE40813200000000005EF3 +:10125000819001004A02FF40813200000000005FDF +:101260008190010000000040F0B10100400000400A +:10127000A59B0100D802004081320100F802004025 +:1012800081320100D0142E06A5B30100400000D326 +:10129000A7CB0100000000F0F1B10100000000F157 +:1012A000F1B10100000000F2F1B10100000000F412 +:1012B000F1B10100000000F5F1B10100000000FAF9 +:1012C000F1B10100000000FBF1B10100000000FCE1 +:1012D000F1B10100000000EBF1B10100000000EEEF +:1012E000F1B10100000000EFF1B10100000000F3D6 +:1012F000F1B10100000000F6F1B10100000000FDB5 +:10130000F1B10100DB0100C7E1B100000000804045 +:1013100081B20100660200488032000000005140A6 +:101320001AB1010000004D4081B2010000004540AB +:1013300081B201006302A241835000005F02494074 +:1013400081B20000000052401CB1010000004E407C +:1013500081B201000000464081B201006802A24152 +:10136000835000005F024A4081B20000000000A0EC +:101370009EB0010000000080D8B30100000000A171 +:10138000D0B30100000000A2D2B30100000000A40D +:10139000D4B30100000000D0D6B30100000000D19A +:1013A000DCB30100000000D2DEB3010000000088C1 +:1013B000DAB30100000000D48EB30100000000D3B6 +:1013C000E6B30100000000ACECB30100000000999E +:1013D000FAB30100000000D5E0B30100000000D521 +:1013E000E2B30100000000D5E4B30100000000D525 +:1013F000E8B30100000000D5EAB30100000000D509 +:10140000F4B30100000000D5F6B30100000000D5E0 +:10141000F8B30100000000C7A9B101000000004FAF +:1014200040B101008402004091B000000000004182 +:1014300091B0010007000040A39B0100080000DDFF +:1014400081F401008802004080C8010000000040D3 +:1014500010B100008D02004081B2000098020040EF +:1014600081B2000098020046A3B300009B02004036 +:1014700081B20000A102004081B200008F0223501F +:10148000A56F000000000050A5B30100E802004273 +:10149000A5630100F802004081320100D0142D4004 +:1014A00049B10100000000D0BAB30100000000DE25 +:1014B000A1B10100000000F800B001009702224431 +:1014C000A553000094020041A1C10000550100DDB8 +:1014D000A1B10000E80200DEA1330100F8020040E3 +:1014E000813201005501004081B20000000000453A +:1014F000BFB301005001A2D2777D0000000000D2EE +:1015000061B10100000000DE63B101009E02A8404D +:10151000813200005501004081B20000E802005411 +:10152000A5330100F802004081320100D0142D40A3 +:1015300049B10100000000F8D0B30100000000F83C +:10154000D2B30100000000F8D4B30100000000F89D +:10155000D6B30100000000F808B10100AC02004061 +:10156000819801006002004683300100550100406F +:1015700081B20000000000A09EB00100000000E861 +:1015800043B10100000000E945B10100000000EA9C +:1015900049B10100000000EBA1B101000000004FC3 +:1015A00040B101000400004081B20000040000408E +:1015B00081B200000400004081B20000040000403D +:1015C00081B200000400004081B20000040000402D +:1015D00081B20000D0142E4049B101000500004046 +:1015E000A39B010000000040C1B30100080000DD22 +:1015F00081F40100BD02004010C90000C3020005D3 +:1016000081B000005001004081B20000CB02000513 +:1016100081B000005001004081B20000D0020044BF +:10162000A5B30000D2020044A5B3000002000040B0 +:10163000A4E70100000000E081B10100FFFF00C14C +:10164000F0890100C802224181500000C40200411B +:10165000C1C30000DA02004081320100F8020040FC +:10166000813201005501004081B2000002000040BB +:10167000A4E70100000000E091B10100FFFF00C9F4 +:10168000F0890100C802224181500000CC020041D3 +:10169000C1C30000FFFF00DE85890100C80200C24F +:1016A000E0B10000FFFF00DE95890100C80200CA1A +:1016B000E0B100000400004081B2000004000040DE +:1016C00081B200000400004081B20000040000402C +:1016D00081B20000000000E7A7B30100000000D8BD +:1016E000A9B301000000004049B10100AE0300CBE6 +:1016F000A3C901000000002046B10100000000D293 +:10170000F1B10100000000D3F1B10100000000D4EC +:10171000F1B10100000000D0E1B10100000000D1F2 +:1017200061B101002000002062DD0100E202A8405A +:1017300081320000000080CC85930100040000404D +:1017400081B200000400004081B2000004000040AB +:1017500081B20000000000E7A7B30100000000D83C +:10176000A9B301000000004049B10100AE0300CB65 +:10177000A3C901000000002046B10100000000D212 +:10178000F1B10100000000D0F1B10100000000D370 +:10179000F1B10100E10200D4E1B100000400004019 +:1017A00081B200000400004081B20000040000404B +:1017B00081B200000400004081B20000040000403B +:1017C00081B200000400004081B20000040000402B +:1017D00081B200000000A2CC85FF00000000005094 +:1017E00081B00100FA02A24181500000F902A2F288 +:1017F00080300000000080CC8583010004000040A0 +:1018000081B200000400004081B2000004000040EA +:1018100081B20000B5030040A199010000002F41F2 +:1018200099B301000A032244816C0000120322488C +:10183000816C00000C03224C816C000016032250C6 +:10184000816C000017032254816C00001903225898 +:10185000816C00001E03225C816C0000500100407E +:1018600081B20000000000BC09B00100DD9F00CA89 +:1018700001B000000000004003B001000000004182 +:10188000F38301001003A242056C00000000004138 +:1018900005B00100DD9F22CA07140000DD9F00454E +:1018A000F3930000DD9F2043956F0000DD9F80CA09 +:1018B00005300000DD9F220180300000DD9F00CB5D +:1018C000DB910000570100BCABB30000000000BC7E +:1018D000B1B30100DD9F00CACFB30000FF0000CA12 +:1018E00081880100DD9FA240747D000060002040DF +:1018F000609901001B03A8B1823000001A03004068 +:1019000081B20000DD9F00CA79B3000004000040EE +:1019100081B200000000004E81B0010000000043D1 +:10192000CB8301000000454081B201002203A241A7 +:10193000815000000000454081B201000000454098 +:1019400081B201002D039182823000000000008AE4 +:1019500080B00100AE9F004080CE01002B03A64066 +:10196000813200002D03564081B20000B5030040D3 +:10197000A19901000000005307900100B503004049 +:10198000A19901000000005207900100D89F00417A +:101990008BB300000000004E81B001000000004247 +:1019A000CD8301000000464081B201003203A24114 +:1019B000815000000000464081B201000000464016 +:1019C00081B201003D039181823000000000008956 +:1019D00080B00100AE9F004080CE01003B03A640D6 +:1019E000813200003D03554081B20000B503004044 +:1019F000A19901000000005207900100B5030040CA +:101A0000A19901000000005307900100D89F0041F8 +:101A10008BB30000B0030040A1990100C4142F4013 +:101A200099B301005701004049B100000400004093 +:101A300081B200000400004081B2000004000040B8 +:101A400081B200000400004081B2000004000040A8 +:101A500081B200003094004043990100009000F8EA +:101A600080980100100000F288E40100200000408E +:101A7000209901000000005F239101004D031F9198 +:101A80008032000030000040209901000000005F1B +:101A90002391010050031F9180320000400000405C +:101AA000209901000000005F2391010053031F9162 +:101AB000803200000000005F2391010055031F9158 +:101AC000803200000008804020990100040000409E +:101AD00081B200000000004784B001000000A2486D +:101AE000848400000000005F61B101000000005C20 +:101AF0008F9001000000004762B101005A03A84026 +:101B000081320000000800478EC801005803005CC5 +:101B10008F800000E00000406199010058152D40C1 +:101B20008DB00100D0142DF088B00100000000FA43 +:101B30008AB001000000004581B0010007000045A7 +:101B400082880100000000438BF001000000004883 +:101B500083E0010000000046829401002000004163 +:101B600060990100000000418DC001007403225FF4 +:101B70008D6C00006503A2418150000063030040AA +:101B800081B2000008000040859801000000004478 +:101B900082B001000000004186B00100001C00433B +:101BA00086D801000000A641855001007003004165 +:101BB00083E000006E030040813201000000004815 +:101BC00085E00100D0142F468494010020000042DB +:101BD00060990100C0000040619901000000804050 +:101BE00081B201000400004081B200000400004006 +:101BF00081B200000400004081B2000004000040F7 +:101C000081B200000400004081B2000004000040E6 +:101C100081B20000070000458088010000000043F9 +:101C20008BF0010000040040839801008503A0416F +:101C3000815000008303004182E8000000008041E1 +:101C40008EC001000400004081B20000040000408A +:101C500081B200000000004049B1010000020040D4 +:101C600083980100003900404599010000000040C0 +:101C7000F1B101008B03A24183500000000000403D +:101C800085B001000B00004482F401001A1500A683 +:101C900086B0010070150040459901000008004021 +:101CA000F199010000000042F0B10100003900404C +:101CB000E1990100040000406199010070150043A2 +:101CC000629901009503A840813200009703225ACF +:101CD000737D00007A000040619901009803A8B16B +:101CE0007E3100000008004284C801009003A24138 +:101CF000835000000000804081B2010004000040D9 +:101D000081B200000400004081B2000004000040E5 +:101D100081B2000058152D408DB00100D0142DF077 +:101D200088B00100000000408FB00100010000A653 +:101D300090B0010000F800489098010000000045B4 +:101D400093B00100000000FA8AB001008003004057 +:101D500081320100020000A680B00100AC032240E5 +:101D6000826C0000B0030040813201005803004043 +:101D700081320100000000418DC00100B503225FE7 +:101D80008D6C0000A703A24193500000A503004002 +:101D900081B20000FF070047848801000000A640D0 +:101DA00081B20000ED9F0047803001000002004733 +:101DB0008EC80100B003004081B200000000004462 +:101DC00050B30100BB032018896C0000040000A67A +:101DD00084B00100200000A686B001000010004081 +:101DE000559B0100BE03004081B20000040000A624 +:101DF00084B00100200000A686B001000010004061 +:101E0000559B01000000004250D30100000000A8D3 +:101E10004FB30100000000434ED301006E030040A9 +:101E2000813201008203004280300100B003004093 +:101E300081320100C70322A78F6C00005A030040C3 +:101E400081320100C403004081B2000000008040E4 +:101E500081B20100C8142EBB85B00100000000EE65 +:101E600082B0010000000041E0B10100000000A2CA +:101E7000A0B3010000000044A5B30100E19F00CA27 +:101E8000A7330100E09F004081B200000400004041 +:101E900081B20000D6032242756F0000D8032241B0 +:101EA000756F0000DA031ECA81320000DC031FCA0E +:101EB00081320000000000CAC9B10100DD9F00426C +:101EC00075B30000000000CACDB10100DD9F0041E4 +:101ED00075B30000000000CACFB10100DD9F0040D3 +:101EE00075B30000008100A6C6B10100DD9F00406F +:101EF00081B20000008000A6C6B10100DD9F004055 +:101F000075B300000400004081B2000004000040EE +:101F100081B200004501004D933001004501004EA3 +:101F2000933001004501004C93300100EC9F0040CC +:101F300081320100DD9F004081B2000004000040BA +:101F400081B200000400004081B2000004000040A3 +:101F500081B200005495004045990100DD9F00CA00 +:101F6000E5B100000400004081B200000400004020 +:101F700081B200000400004081B200000400004073 +:101F800081B200000400004081B200000400004063 +:101F900081B20000CC142E4087B00100000000A2E6 +:101FA000A0B3010015040043B2330100000068DA59 +:101FB00089B001007C0000408B98010000000050B7 +:101FC00089F001000000004189D0010003000044B5 +:101FD000888C01000000004487C00100000000411F +:101FE000A5B3010015040043B2330100000000DA7C +:101FF000F1B101000000004487C001000000004171 +:10200000A5C301000B042244895000000B042244A4 +:102010008B500000FA03A250A56F000000000042A0 +:10202000A5E30100000000CAA7B30100E19F00BBC7 +:1020300085300100CC142ED295C30100AE0300CB35 +:10204000A3C901000000002042B1010000000050BF +:1020500081B001000804A241815000000704A2F2EF +:1020600080300000FA030040A5B3000000000042E9 +:10207000A5E30100000000CAA7B30100E19F00BB77 +:1020800085300100E09F004081B200000400004064 +:1020900081B20000000000D92BB101000010004007 +:1020A00083980100DB00004081320100FFFF0094B3 +:1020B000B48B01000000804081B20100000000D913 +:1020C0002BB101000010004083980100DD000040AA +:1020D0008132010000008094B4B30100040000408C +:1020E00081B200000400004081B200000400004002 +:1020F00081B200000400004081B2000004000040F2 +:1021000081B200000400004081B2000004000040E1 +:1021100081B20000000000D92BB10100000000DAFC +:1021200027B1010006C000402D990100DE000040EB +:1021300081320100001000408398010002C4004178 +:102140002C990100DE000040813201000040004077 +:1021500083980100058200412C990100DE000040B7 +:10216000813201002D048094803200000C01004077 +:10217000813201002804004081B200000480004048 +:102180002D990100DE0000408132010000008040F6 +:1021900081B201003104001210C9000000488040E3 +:1021A0000B980100C04980400B980100804B804093 +:1021B0000B980100404D80400B980100004F80407B +:1021C0000B980100C05080400B9801008052804065 +:1021D0000B980100405480400B980100005680404D +:1021E0000B980100C05780400B9801008059804037 +:1021F0000B980100405B80400B980100005D80401F +:102200000B980100C05E80400B9801008060804008 +:102210000B980100406280400B98010000648040F0 +:102220000B980100C06580400B98010080678040DA +:102230000B980100406980400B980100006B8040C2 +:102240000B980100C06C80400B980100806E8040AC +:102250000B980100407080400B9801000072804094 +:102260000B980100C07380400B980100807580407E +:102270000B980100407780400B9801000079804066 +:102280000B980100C07A80400B980100807C804050 +:102290000B980100407E80400B9801000400004034 +:1022A00081B200000400004081B200000400004040 +:1022B00081B200000400004081B200000400004030 +:1022C00081B200000400004081B200000400004020 +:1022D00081B200005904001210C900000080804043 +:1022E0000B980100008280400B9801000084804020 +:1022F0000B980100008680400B9801000088804008 +:102300000B980100008A80400B980100008C8040EF +:102310000B980100008E80400B98010000908040D7 +:102320000B980100009280400B98010000948040BF +:102330000B980100009680400B98010000988040A7 +:102340000B980100009A80400B980100009C80408F +:102350000B980100009E80400B98010000A0804077 +:102360000B98010000A280400B98010000A480405F +:102370000B98010000A680400B98010000A8804047 +:102380000B98010000AA80400B98010000AC80402F +:102390000B98010000AE80400B98010000B0804017 +:1023A0000B98010000B280400B98010000B48040FF +:1023B0000B98010000B680400B98010000B88040E7 +:1023C0000B98010000BA80400B98010000BC8040CF +:1023D0000B98010000BE80400B98010004000040F3 +:1023E00081B200000400004081B2000004000040FF +:1023F00081B200000400004081B2000004000040EF +:1024000081B200000400004081B2000004000040DE +:1024100081B200000000004087B1010000000040D0 +:1024200097B001000000004B80B10100010000A640 +:1024300082B1010082048541974000000000004005 +:1024400097B101000000004097B001000000004B70 +:1024500090B10100010000A692B1010087048541FE +:10246000974000000000804081B20100040000405D +:1024700081B200000400004081B20000040000406E +:1024800081B200000400004081B20000040000405E +:1024900081B2000090046040813200000000001210 +:1024A00080B10100FFFFF04B82890100930460407E +:1024B000813200000000004A80B101000100F0A656 +:1024C00082B101009604604081320000FFFF004BA2 +:1024D000848901000000F0C224B001000000004A1D +:1024E00090B10100FFFF804B928901000000004A7B +:1024F00090B10100010080A692B10100FFFF004BE6 +:1025000094890100000080CA94B0010004000040DA +:1025100081B200001000004E98E4010000000007A6 +:10252000989401000000004399E001000000008041 +:10253000989401000000004999E001000000004C5F +:1025400088940100A604474081320000AD04222097 +:10255000876F000000001F4081B2010000000040B2 +:1025600081B201000000004081B201000000004083 +:1025700081B20100A604004081B2000000001F806B +:1025800086B30100B004224F777D0000C0040040F4 +:10259000813201000000004F61B1010000000044E1 +:1025A00062B10100B104A84081320000B804224B9E +:1025B000897C0000B604224F777D0000C0040040F3 +:1025C000813201000000004562B10100B604A8405C +:1025D000813200000000802087B301000400004029 +:1025E00081B200000400004081B2000004000040FD +:1025F00081B200000400004081B2000004000040ED +:1026000081B200000400004081B2000004000040DC +:1026100081B200000000005099B001006F0000403E +:1026200061990100C104A8B152330000C604224BD5 +:10263000537F00006F00004061990100C404A8B1FD +:102640007E310000C104A241995000000000A24F59 +:1026500077FD00000400004081B20000040000404B +:1026600081B200000400004081B20000040000407C +:1026700081B200000400004081B20000040000406C +:1026800081B200000400004081B20000040000405C +:1026900081B200001000004E98E401000000000725 +:1026A000989401000000004399E0010000000080C0 +:1026B000989401000000004899E00100D604004C05 +:1026C00088940000D604474081320000DD042220B7 +:1026D000876F000000001F4081B201000000004031 +:1026E00081B201000000004081B201000000004002 +:1026F00081B20100D604004081B2000000001F80BA +:1027000086B30100E004224F777D0000F004004012 +:10271000813201000000004F61B10100000000445F +:1027200062B10100E104A84081320000E804224ABD +:10273000897C0000E604224F777D0000F004004011 +:10274000813201000000004562B10100E604A840AA +:10275000813200000000802087B3010004000040A7 +:1027600081B200000400004081B20000040000407B +:1027700081B200000400004081B20000040000406B +:1027800081B200000400004081B20000040000405B +:1027900081B200000000005099B001006F000040BD +:1027A00061990100F104A8B152330000F604224AF5 +:1027B000537F00006F00004061990100F404A8B14C +:1027C0007E310000F104A241995000000000A24FA8 +:1027D00077FD00000400004081B2000004000040CA +:1027E00081B200000400004081B2000004000040FB +:1027F00081B200000400004081B2000004000040EB +:1028000081B200000400004081B2000004000040DA +:1028100081B200007B000040619901000005A8B171 +:102820008030000012051D4080320000401800403A +:1028300049990100040000A686B001001005A240DD +:1028400086040000DE9F9C4080320000FFFF0040B5 +:1028500088880100300500504731010036000044EF +:1028600088CC01000C055240813200003005004048 +:10287000473101000000004189B0010030050048E7 +:10288000473101003005000547310100DE9F00405F +:1028900081B200002800004047991B00DE9F0041E4 +:1028A000E1C11A007818004049991B00190522540B +:1028B000817C1A001405424081321A00008200B364 +:1028C00067DF1B0000001A4493931B0028000040A0 +:1028D00047991B00300500418930010027050F4052 +:1028E00080320000FF7F00408888010030050050E2 +:1028F000473101003600004488CC01001F05994093 +:10290000803200000000004889D0010021059B4072 +:10291000803200000000004C89D0010023051F44D4 +:1029200080320000300500404731010000000041C6 +:1029300089B00100300500484731010030050058DA +:1029400047310100DE9F004081B2000010000040CE +:1029500086F401006F00004386880100DE9F260593 +:10296000473100003005004189300100DE9F004002 +:1029700081B200000400004081B200000400004069 +:1029800081B200000400004081B200000400004059 +:1029900081B200000000A044F041010000000040AE +:1029A00081B2010000008041E1C10100040000404B +:1029B00081B200000400004081B200000400004029 +:1029C00081B200000400004081B200000400004019 +:1029D00081B200004C010007913001000000A240CC +:1029E00097EC00000000800591C001000400004049 +:1029F00081B200000400004081B2000004000040E9 +:102A000081B200000400004081B2000004000040D8 +:102A100081B200004C010040813201004405A24017 +:102A2000976C00003A000040B39B01004505004050 +:102A300081B2000040000040B39B01001004004040 +:102A400081320100000000DAF5B1010010040042FB +:102A5000B3430100000000DAF5B1010010040042A8 +:102A6000B3430100000000DAF5B101004E00004060 +:102A7000B39B01001004004081320100080000DA1D +:102A8000F7F5010050000040919801000000004758 +:102A90008FB0010010040048B2330100000000DADA +:102AA000F7B10100080000DAF7F50100000000426C +:102AB00091C001005005A2418F500000000000416C +:102AC00045D1010008000040B39B01001004004004 +:102AD00081320100000000DAFDB101000A0000406F +:102AE000B39B01001004004081320100000000DAB5 +:102AF000FDB101001A000040B39B0100100400402A +:102B000081320100000000DAFDB101001800004030 +:102B1000B39B01001004004081320100000000DA84 +:102B2000FDB1010038050040813201001E0000485F +:102B3000B2CB01001004004081320100000000DA35 +:102B400091C0010000000048B2CB01001004004019 +:102B50008132010000006EDA8FB0010002000048EF +:102B6000B2CB01001004004081320100000000DA05 +:102B7000FDB1010004000048B2CB01001004004088 +:102B800081320100000080DAFDB101000400004044 +:102B900081B200007A052245FD7F0000401600400A +:102BA00045990100DB9F00404931010008000048C1 +:102BB000B2CB010015040040813201007805A2402B +:102BC0008F6C00007D052220B56F00007A05004063 +:102BD00081B20000DA9F004081321F007D05224053 +:102BE000976C1E007A05424081321E000000004FA3 +:102BF00067931F00DF9F005867931E005416004024 +:102C000047991F00000000FEF4B11F0000000040C3 +:102C100081B21F00000000FEF4B10100000000407E +:102C200081B20100000000FEF4B10100000000408C +:102C300081B20100000000FEF4B10100000000407C +:102C400081B20100000000FEF4B10100000000406C +:102C500081B20100000000FEF4B10100000000405C +:102C600081B20100000000FEF4B101004600004006 +:102C7000B39B01001004004081320100080000DA1B +:102C8000F7F501004800004095980100000000445D +:102C900097B001001004004AB2330100000000DACE +:102CA000F7B10100080000DAF7F50100000000426A +:102CB00095C001009005A241975000002A000040F5 +:102CC000A59B010040160040A19B0100000000CA26 +:102CD000A7B30100E19F00BB85300100E09F0040E9 +:102CE00081B200000400004081B2000004000040F6 +:102CF00081B200000400004081B2000004000040E6 +:102D000081B200000400004081B2000004000040D5 +:102D100081B20000B8052245FD7F0000E0150040AB +:102D2000479901001A0000A280DC01000000005059 +:102D3000F1B10100F0150040F1990100000000CA56 +:102D4000F1B101000700004061990100200000403E +:102D500062DD0100A705A8BBE131000000000050C2 +:102D600083B00100AA05A24183500000A905A2F288 +:102D7000823000004C01004081320100B005A240C9 +:102D8000976C00003A000040B39B0100B105004081 +:102D900081B2000040000040B39B0100F0150040EC +:102DA000439901001004004081320100B805A2FAE5 +:102DB000B46F000010040042B3430100B805A2FA4A +:102DC000B46F000010040042B3430100BB0522FAB7 +:102DD000B46F0000B8054240813220000000004E70 +:102DE00067932100DF9F0058679320004016004042 +:102DF00045992100DB9F004049312100F615004034 +:102E0000439921005C1600404599210000006EFAAC +:102E10008EB021000000004081B20100000000FEE1 +:102E2000F4B101000000004081B20100000000FE8A +:102E3000F4B101000000004081B20100000000F088 +:102E4000B4B30100C905A2408F6C0000FC1520201E +:102E5000E1B10100CE05004081B22400DA9F0040BC +:102E600081322500CE052240976C2400CB054240DC +:102E7000813224000000004F67932500DF9F005837 +:102E80006793240038050040813225001E00004869 +:102E9000B2CB25001004004081320100D30522503E +:102EA000B56F00000000005091C001000000004814 +:102EB000B2CB0100F615004043990100200400F256 +:102EC000B433010002000048B2CB0100F815004005 +:102ED00043990100200400F2B433010004000048CB +:102EE000B2CB0100FA15004043990100200400F222 +:102EF000B433010008000048B2CB0100FC150040CB +:102F000043990100000000F094B00100FFFF004A67 +:102F1000B48B010020040040813201000A00004807 +:102F2000B2CB01001000004AB4F7010020040040B9 +:102F30008132010038050040813201001E00004846 +:102F4000B2CB01001004004081320100E90522509B +:102F5000B56F0000EA050050B5B300000000004066 +:102F6000B5B301002004004081320100E09F004021 +:102F700081B200000400004081B200000400004063 +:102F800081B200000400004081B200000400004053 +:102F900081B2000000160040479901003031004026 +:102FA000F599010032330040F599010034350040B5 +:102FB000F599010036370040F59901003839004095 +:102FC000F599010041420040F59901004344004059 +:102FD000F599010045460040F59901004748004039 +:102FE000F5990100494A0040F59901002C00004084 +:102FF0008398010000000040F7B10100FC05A241E8 +:103000008350000080162E0683B00100360000FBBE +:10301000F6A90100FF05A2418350000022000040F4 +:1030200083980100000000FBF6B101000206A241F6 +:10303000835000006200004095980100DC9F004032 +:103040008132010000162D0683B001008016004079 +:10305000459901005C0000FBF6A901000806A241A9 +:103060008350000000000070F9B101000000007101 +:10307000F9B1010000000072F9B101000000007315 +:10308000F9B1010000000074F9B1010054000040E2 +:1030900095980100DC9F0040813201000000007023 +:1030A00095B0010014062270B56F00000000804149 +:1030B00097B001000000804097B00100040000407C +:1030C00081B200000400004081B200000400004012 +:1030D00081B20000456700A6E0B201000123007044 +:1030E000E19A0100CDEF00A6E2B2010089AB0071C8 +:1030F000E39A0100BA9800A6E4B20100FEDC007277 +:10310000E59A0100321000A6E6B201007654007381 +:10311000E79A0100D2C300A6E8B20100F0E1007412 +:10312000E99A01008016004A44C901000000000726 +:1031300081B001000000004A80D001000000004082 +:10314000F7B101002506A241815000008016004A17 +:1031500044C90100FC162A47E7B501000300004AF4 +:10316000E8E50100000000408DB001005003004080 +:10317000A399010080163D468DE00100000000503B +:1031800089B00100000000FC40B0010000000041D7 +:10319000A3C101002E06A24189500000000000706A +:1031A000EBB2010000000071EDB2010000000072FE +:1031B000EFB2010000000073F1B2010000000074E2 +:1031C000F3B201000000004083B001000F00004195 +:1031D0008088010050030040A2C901004B06A050A6 +:1031E000836C00000D00004098C801000000004FF3 +:1031F000998401005003004CA2C901000000002086 +:1032000086B001000800004098C801000000004F8F +:10321000998401005003004CA2C901000000002065 +:1032200086A401000200004098C801000000004F81 +:10323000998401005003004CA2C901000000002045 +:1032400086A4010050030040A2C901000000004311 +:1032500040A401000100002088E401000000005F9C +:1032600041F0010000000044409401000500007599 +:1032700089E401001B00007585F401000000004492 +:10328000849401005506A353836C0000000000766F +:1032900089B00100000000778984010000000076F9 +:1032A0008BB00100000000208BA40100000000781A +:1032B0008B840100640600458894000027000041CB +:1032C00080CE01005A06AA4081320000000000763C +:1032D00089B001000000007789A40100640600782D +:1032E00089A400003B00004180CE01005706AA409F +:1032F000813200000000007689B0010000000077F4 +:1033000089840100000000768BB001000000007885 +:103310008B840100000000458894010000000077C4 +:103320008BB00100000000788B840100640600452A +:10333000889400000000004484C00100000000796F +:1033400085C001000000002084C001006B06A3536B +:10335000836C0000825A00A684C001009979004263 +:1033600084C801007806004081B2000027000041B7 +:1033700080CE01007006AA4081320000D96E00A6FE +:1033800084C00100A1EB004284C80100780600401F +:1033900081B200003B00004180CE01007506AA40CA +:1033A000813200001B8F00A684C00100DCBC0042FB +:1033B00084C801007806004081B2000062CA00A6FD +:1033C00084C00100D6C1004284C8010078060040D4 +:1033D00081B2000000000078F3B201000000007725 +:1033E000F1B201001E00007689E4010002000076BF +:1033F000EFF6010000000044EE96010000000075A9 +:10340000EDB2010000000042EAB2010000000041FC +:1034100083C001004F00004180CE010037062A40E2 +:103420008132000000000075E1C20100000000765A +:10343000E3C2010000000077E5C20100000000784F +:10344000E7C2010000000079E9C201002B068141BA +:103450008D4000000000804081B201000400004067 +:1034600081B200000400004081B20000040000406E +:1034700081B200000400004081B20000040000405E +:1034800081B200000400004081B20000040000404E +:1034900081B2000000000050FD9301004016004082 +:1034A00045990100DB9F00404931010008000048B8 +:1034B000B2CB01001504004081320100B906224060 +:1034C0008F6C0000DA9F004081320100B906A240F3 +:1034D000976C00005E160040439901007C1620F6B0 +:1034E000E0B101000000004031B301009D06224F11 +:1034F0008F7C000000000051FD9301009F062240D8 +:103500008F7C0000A3060054FD930000A106224218 +:103510008F7C000000000052FD930100A3062241B1 +:103520008F7C000000000053FD930100B70622517C +:10353000FD7F000038050040813201000C0000488A +:10354000B2CB01001004004081320100B206A2405B +:10355000B56F00001E000048B2CB01001004004807 +:1035600096300100000000DA97C001000400004B13 +:10357000B2CB010010040040813201000E0000486F +:10358000B2CB010020040040813201000C00004851 +:10359000B2CB010000000030B5B3010020040040B0 +:1035A000813201000E000048B2CB0100100400403F +:1035B00081320100B6062240B56F0000BA06005401 +:1035C000FD93000000000051FD8301001C0000FE7F +:1035D0007FD90100BA06A6408132000000000055E4 +:1035E000FD9301000000804081B201000400004012 +:1035F00081B200000400004081B2000004000040DD +:1036000081B200000400004081B2000004000040CC +:1036100081B20000E79F004081320100C406225CB5 +:103620001F7C0000E39F00881CB00000E99F005C45 +:103630001F00010000002E0548B1010000000040FD +:10364000E1B1010004002D0348B10100000000F0C9 +:103650003CB001002800001402C801000000000175 +:1036600034B0010000002D0532B001002200000539 +:103670000AC801001000000348C90100000000F85A +:1036800018B00100000000F804B00100000000F8CC +:103690000EB001000C0000A40CC80100EA9F00401D +:1036A000813201000000004023B001000A0722011E +:1036B0008032000000003C4423E0010000002EA402 +:1036C00080B001000000001048C10100D906A30726 +:1036D000026C0000DA0668011AB0000000006807FA +:1036E0001AB001000000000D02D00100000000052A +:1036F000F0B101000000000CF0B101000000000278 +:10370000E0B101000000000D0AC00100EC062240FB +:10371000036C0000E6062242236C0000000000411A +:1037200023C001000000004761B10100200000A497 +:1037300062DD01002307284081320000E3060040DB +:1037400081B200000000001080C0010000000047AE +:1037500061B101000000004062B10100E806A8402C +:1037600023300000E39F00881CB0000023070040C6 +:1037700081B200000000001080C00100000000477E +:1037800061B101000000004062B10100EE06A840F6 +:1037900023300000E39F00881CB0000022000019C5 +:1037A00048C9010000002D1448C101000F0000F2BB +:1037B0003A880100000000423BE001000E000014C6 +:1037C00002C801000000001D02C00100FA06231A11 +:1037D000025000000000004603C001002307000162 +:1037E00034C000000C002D1D48C10100F00000F2A3 +:1037F000308801000000004231F001000000001498 +:1038000002B001000000001D02C00100000000180D +:1038100002C001000207221A025000002307000123 +:1038200034C000002200001948C9010002002D1414 +:1038300048C10100000000F614B001000000001DA6 +:1038400014D001000000001814D001000000001E78 +:1038500024B001001200001710C801002307001A4D +:1038600010C0000000003C4423E00100000000A460 +:1038700086B0010000002E1048C101000F07A312FE +:103880000E6C0000100760071AB000000000601204 +:103890001AB001000000680D16940100FFFF000B34 +:1038A00016D8010000000008F0B101000000000C73 +:1038B000F0B1010000000002E0B1010000000010C2 +:1038C00086C001000000004661B1010020000043F5 +:1038D00062DD01001707A85C1F1000004007220DE1 +:1038E000145000004007220D245000000000000D7D +:1038F00010C001001E072242236C00002307004174 +:1039000023C000000000004661B10100400000102B +:1039100062DD01001F07A85C1F000000E39F008814 +:103920001CB000000000004023B001003F07A20DC2 +:103930000E5000002E0722461F7C000000000046AB +:103940001F8001003080001042C901002C0722F2C4 +:10395000640600000000004761B101004000001053 +:1039600062DD01002907A84081320000E39F008842 +:103970001CB0000020800003469901000000005F99 +:10398000E191010000002D0648B10100000000F89F +:1039900018B00100000000F804B0010033071FF068 +:1039A0000E300000D306004C0DC0000000002E5F5A +:1039B0000F800100D3062307146C000030000010B4 +:1039C00048C9010024000040F199010000000003F3 +:1039D000F0B1010000000000F0B10100000000168D +:1039E000F0B101002400000000C801000000004701 +:1039F00061B10100200000A462DD01003C07A8467F +:103A00001F100000D30600030CB00000D306000D09 +:103A100018C000005F07A2441F7C000000000019CE +:103A20000AB001002200000548C901000A002D1457 +:103A300048C1010002002040E5B10100040020401F +:103A4000E5B101000D002D1D48C10100090000F382 +:103A5000388801000D002050E7B1010004002D401E +:103A60003FB00100000000F432B00100040020402B +:103A7000E1B101002200000548C9010000002D1439 +:103A800048C101000200001D94F401000000004044 +:103A900091B001005207A0FC9040000000000041DE +:103AA00091C001005007A24195500000000000A401 +:103AB00096B0010004002E0548B101000000004846 +:103AC000F0B101000000004B48B1010000000018F7 +:103AD00048C101000200001894F4010000002D18F4 +:103AE00090B001005C07A0FC904000000000004185 +:103AF00091C001005A07A241955000000000004803 +:103B0000E0B1010010002040E5B1010004002D05E6 +:103B100048B10100000000F880B02D00000000F066 +:103B200016B02D002200000548C92D000000001429 +:103B300048C12D00640743303D072C000000009E63 +:103B400085B02D0000001B413DC32D000400204224 +:103B5000ECB12D000000001E82B0010002002E1DFD +:103B600082C001000000661882C00100000000420F +:103B700080C001006E07A0418044000000000041A9 +:103B800081C001001000004092F401000A002E30B4 +:103B900081840100720790409240000000000041C3 +:103BA00093C001000000662093A401000000001DE6 +:103BB00048C1010004002019E8B101000000001E06 +:103BC00016C001007807A01916440000000000414B +:103BD00017C001000D002F1E32C001007D07A2405A +:103BE000156C00007C07A01C16400000000000417E +:103BF00017C00100000063F33894010010000005B5 +:103C000048C9010004002E1E98B001000000601A8F +:103C100098C001000C002040E1B101008B07224652 +:103C20001F7C0000000000461F8001003080001053 +:103C300042C90100890722F2640600000000004723 +:103C400061B101004000001062DD01008607A8405C +:103C500081320000E39F00881CB000002080000338 +:103C6000469901000000005FE191010030800010E2 +:103C700044C901001200001AF0C901000000001739 +:103C8000F0B1010010000005E0C901003000001093 +:103C900080C801000000004461B101002000004024 +:103CA00062DD01009107A840813200009B07225C81 +:103CB0001F7C000000003C4423E0010000002D10A8 +:103CC00048C101009B0722F2640600000000004684 +:103CD00061B101004000001062DD01009807A840BA +:103CE00081320000E39F00881CB00000EB9F005C65 +:103CF0001F00010020002F0548B101000000000B4B +:103D0000E4B101000000005017F00100A10790F29B +:103D1000164000000000004117C0010000006620AE +:103D200017A40100100000142AC801000000001DA3 +:103D30002AC00100000000502BE00100000000F24A +:103D40002A9401003080001042C90100AC0722F221 +:103D5000640600000000004461B101004000001052 +:103D600062DD0100A907A84081320000E39F0088BE +:103D70001CB000000080001710DC0100C9072240C1 +:103D8000156C0000B407A2441F7C00000000004432 +:103D90001F900100B307229F136C000002000088EF +:103DA0001CCC0100E49F004081B2000000000041F3 +:103DB0003FC30100E69F004081320100B707A241E6 +:103DC000877C00000000001E3EC00100C9072240A1 +:103DD000156C0000BA07201E146C00000000000AD9 +:103DE0003CB00100E59F001E24300100BF072208FF +:103DF0002E3000000000005211C001000000001A27 +:103E000010C001002307004017B00000E49F0088A5 +:103E10001CB00000E59F004081320100BC07A208F1 +:103E20002E300000808000A604B001000600004093 +:103E300087980100008000034499010004002204D7 +:103E4000E0310000E89F001F8C30010000000040BE +:103E50000FB00100E29F005C1F9000000080000393 +:103E60004499010004002204E0310000E69F004074 +:103E700081320100CE07A241877C0000CF07001EDF +:103E80003EC000000000001F8CB001000000004098 +:103E900005B00100E89F00400F300100E29F005C88 +:103EA0001F9000000400004081B2000004000040A8 +:103EB00081B200000400004081B200000400004014 +:103EC00081B200000400004081B200000400004004 +:103ED00081B200000400004081B2000004000040F4 +:103EE00081B200000400004081B2000004000040E4 +:103EF00081B200000400004081B2000004000040D4 +:103F000081B200000400004081B2000004000040C3 +:103F100081B200000400004081B2000004000040B3 +:103F200081B200000400004081B2000004000040A3 +:103F300081B200000400004081B200000400004093 +:103F400081B200000400004081B200000400004083 +:103F500081B200000400004081B200000400004073 +:103F600081B200000400004081B200000400004063 +:103F700081B200000400004081B200000400004053 +:103F800081B200000400004081B200000400004043 +:103F900081B200000400004081B200000400004033 +:103FA00081B200000400004081B200000400004023 +:103FB00081B200000400004081B200000400004013 +:103FC00081B200000400004081B20000F70700BC8D +:103FD00080B200000380004081B2000003800040F6 +:103FE00081B200000380004081B2000003800040E5 +:103FF00081B200000380004081B2000003800040D5 +:1040000081B200000380004081B2000003800040C4 +:1040100081B200003180004081B200003480004055 +:1040200081B200003580004081B2000004000040F1 +:1040300081B200001B808180803200001487A24082 +:10404000916F00000000004C90B301005C952EA21F +:1040500080B00100FF000080F489010090952AC81B +:10406000E5B10100000000A1F0B101000000004036 +:10407000F0B10100000000A4F0B10100000000D088 +:10408000F0B10100000000D1F0B10100000000D249 +:10409000F0B101000000004CF0B10100000000D4BC +:1040A000F0B10100000000D3F0B10100000000EE0B +:1040B000F0B101000000004EF0B10100000000402E +:1040C00044B1010018801181983000000000514077 +:1040D00081B201001A801182983000000000524025 +:1040E00081B2010014870048FD930000B603004030 +:1040F000A19901002380A242FD7F00002080008062 +:1041000080320000228011818230000022805140E4 +:1041100081B2000022801182823000002280524051 +:1041200081B200002C800048FD93000027800080B1 +:10413000803200002680A253077C0000000051530B +:10414000079001002A800052079000002980A252A7 +:10415000077C00000000525207900100000000534D +:104160000790010000000048FD9301000000004698 +:10417000F39301005C952EA252B30100FF00008072 +:10418000F48901000000004CE4B10100000000A926 +:1041900045B101003080004C80B200000000454075 +:1041A00081B201000000554081B20100AF8205409C +:1041B00049B10000AF82054049B100000000054050 +:1041C00049B101004C010040813201000000004B68 +:1041D000DEB2010000000040FD9301000000004835 +:1041E000FD830100020000409B9B0100000000A530 +:1041F0009CB30100480300408132010058952044DF +:10420000E0B101000494004043990100000000F275 +:1042100024B10100000C00EE968801000000004A65 +:1042200097F001004480A243976C00000000004218 +:10423000FD93010000C000A636B10100D01400407B +:104240004799010005000040F59901000038004041 +:10425000F599010000060040F599010000000040BA +:10426000F599010005100040F59901000209004090 +:10427000F599010004000040F59901006003004039 +:10428000813201008803004081320100A003004018 +:1042900081320100A2820040813201009A820040F6 +:1042A0008132010060952040E1B10100709520400D +:1042B000E1B1010000000049DD9101000000004073 +:1042C00091B30100F99500408132010000000040E7 +:1042D00085B301005C952040E1B1010027820040D8 +:1042E0008132010090060040813201000000005F31 +:1042F0002F8101008D81004081320100FE95004038 +:10430000813201000000454081B2010000005540AB +:1043100081B20100DD82004081B200000400004053 +:1043200081B200000400004081B20000040000409F +:1043300081B200000400004081B20000040000408F +:1043400081B200000400004081B20000040000407F +:1043500081B200002800004047990100AF8200416F +:10436000E1C1000078180040499901001905225464 +:10437000817C00006C80424081320000008200B4E9 +:1043800069DF010000001A449393010028000040F7 +:10439000479901001805004081B200000400004068 +:1043A00081B200000400004081B20000040000401F +:1043B00081B200000400004081B20000040000400F +:1043C00081B200000400004081B2000004000040FF +:1043D00081B2000040820040813201007D80224095 +:1043E000976C00007A804240813200000000004F4C +:1043F0006993010038810058699300005416004009 +:1044000047990100000000FEF4B101008005004062 +:1044100081B2000080804240813200000000004EE6 +:1044200069930100388100586993000040160040EC +:10443000459901004005004049310100F615004052 +:10444000439901005C1600404599010000006EFA96 +:104450008EB00100C105004081B2000004000040A0 +:1044600081B200000400004081B20000040000405E +:1044700081B200000400004081B20000040000404E +:1044800081B200000400004081B20000040000403E +:1044900081B200009680004081B20000408200405E +:1044A0008132010096802240976C00009380424048 +:1044B000813200000000004F6993010038810058EC +:1044C0006993000038050040813201001E00004859 +:1044D000B2CB0100D005004081B2000004000040D2 +:1044E00081B200000400004081B2000004000040DE +:1044F00081B200000400004081B2000004000040CE +:1045000081B200000400004081B2000004000040BD +:1045100081B200008302004081B20000B802004076 +:1045200081B20000D49F004081B20000D59F0040BE +:1045300081B20000D69F004081B20000D79F0040AA +:1045400081B200007201004181C000005501514854 +:10455000FD93000055015248FD9300005501554957 +:10456000FD8300005501564AFD83000050019181F2 +:10457000803000005501454081B200005001918219 +:10458000803000005501464081B20000000000402C +:1045900089B00100000000F880B00100000000F0C8 +:1045A00016B001002200000548C9010000000014F7 +:1045B00048C10100B48043303D0700000000009E68 +:1045C00085B0010000001B413DC3010004002042F2 +:1045D000ECB101000000004049B10100AE0300CB86 +:1045E000A3C901000000002046B10100000000D274 +:1045F000F1B10100000000D3F1B101000000004260 +:10460000F0B101000000004561B101002000002070 +:1046100062DD01000000A8D0E1B10000BF800040D1 +:1046200081B20000000000A898B0010004800040A2 +:104630008BB30000B1030040A1990100C780A242E2 +:10464000976F000000000045A1C1010000000000BC +:1046500080B001000000A2048094000080153F4259 +:1046600097E301000000004049B101000000600331 +:10467000029401000000004007B00100040000CBDC +:1046800099CB0100000000CCF3830100D180A2424D +:10469000976F0000000000CBF3930100AE0300CB46 +:1046A000A3C901000000002044B101000000004443 +:1046B000F1B1010000000000F0B1010000000004B1 +:1046C000F0B10100000000A1E0B1010005000040D0 +:1046D000619901002000002062DD0100D880A8401F +:1046E00081320000F9020020423101000000A241A5 +:1046F000056C0100000080CBDB9101000000194136 +:104700008BB301006000004061990100DE80A8B118 +:104710008C3300006000004061990100E080A8B186 +:1047200094330000E68014C681320000180000C6F1 +:1047300083F40100F482224F83040000C280004011 +:1047400081B20000FF0100C681880100000000C6A0 +:1047500097A30100C2801F5C9753000058821EC6B9 +:104760008132000000002F4381F00100EC80004006 +:1047700010C900003981004081B200006A81004008 +:1047800081B20000248200CA63B30000618100404E +:1047900081B200004881004D83B000005281004E7C +:1047A00061B100004181004085B000004881004CAB +:1047B00083B000002481004085B00000E381004008 +:1047C00049B1000071810040C1B10000DF810040AB +:1047D00081B200004181004085B00000F00300403C +:1047E00049B10000F48200CA9BB300007B81004005 +:1047F000C1B100007F810040C1B10000868100404E +:10480000C1B1000087810040C1B100008881004033 +:10481000C1B1000089810040C1B100008A8100401F +:1048200081B000008A81004181B000001882004000 +:1048300081B20000978200BBABB30000258200CAA2 +:10484000CFB30000C803004049B10000E8030040B6 +:1048500081B200002682004081B20000F482004054 +:1048600081B20000E003004081B20000F48200CA7F +:1048700077B300004981004D83B000005081004EA5 +:1048800061B10000418100BB85B000004981004C4E +:1048900083B00000418100BB85B00000248100BBD3 +:1048A00085B000001681004081B20000F48200CA89 +:1048B0004DB300007005004049B10000A005004064 +:1048C00049B100001C8122428F6F00001E812241ED +:1048D0008F6F000020811ECA8132000022811FCA12 +:1048E00081320000000000CAC9B10100F482004218 +:1048F0008FB30000000000CACDB10100F482004176 +:104900008FB30000000000CACFB10100F482004064 +:104910008FB30000008100A6C6B10100F482004000 +:1049200081B20000008000A6C6B10100F482004000 +:104930008FB30000781800404999010010002F9CA7 +:1049400089B001003B8100403933010018002F9BE2 +:1049500089B001003B8100403733010000002F9AED +:1049600089B001003B8100403533010008002F99D8 +:1049700089B001003B81004033330100008000AE6C +:1049800047C9010080000040F1990100000000CA01 +:10499000F1B1010000000042F0B1010040180040F8 +:1049A000E19901000000004561B10100200000AE66 +:1049B00063DD0100368128408132000033810040F0 +:1049C00081B2000036814240813200000000005C6C +:1049D00069930100F4821A449393000039814240A4 +:1049E00081320000388100586993000000000044C3 +:1049F000F0D101000000A44081B200004081A2403B +:104A0000E16D00000000004445D10100000080403D +:104A1000E1B1010000008041E1D101004181375C3A +:104A2000613100000000004262B101004581284070 +:104A3000813200004281004081B20000000000CAC3 +:104A400063B101004581A84081320000F482174023 +:104A500081B200004A81004081B000004A8100BB61 +:104A600081B000000000004160B101000000004082 +:104A700062B101004B81A84081320000000000CAF1 +:104A800063B10100F4822840813200004D81004072 +:104A900081B200005095004047990100538100BB4E +:104AA00087B0000050952F4087B00100558122400B +:104AB000957F0000F48260409583000002002DF095 +:104AC00084B001005681364081320000000000426F +:104AD00062B101005781A84081320000000000430C +:104AE00062B101005981A84081320000000000CA73 +:104AF00063B101005B81A8408132000000001640D4 +:104B000081B20100F482224143510000000800CA32 +:104B100095CB01005681004185C000006381A2420F +:104B2000676F00000000004167B3010063814240ED +:104B3000813200000000004065B301000000004029 +:104B40009383010000001ACA69970100F48226408D +:104B5000813200006881424081320000F4821A44B0 +:104B600093930000F4822043956F0000F48280CA82 +:104B700067330000F4822240656F0000F482006F0A +:104B8000DB91000085000040813201003580224029 +:104B900080320000F482004081B200000000005822 +:104BA000959301000000005F959301007781A24476 +:104BB000216F00000000005F958301000000005E8F +:104BC000959301000000005795930100000000CA72 +:104BD000C3B101007A81225B957F00000000004B89 +:104BE000FD930100F482004081B200001BFD00CA69 +:104BF000959B01000D0100CAC53101000000005F56 +:104C000095830100F48200CAC5B10000DF6F00CABD +:104C1000959B01000000005595930100000000CA1B +:104C2000C7B10100F482225F957F00000D010040B2 +:104C3000813201000000005F95830100F48200CA08 +:104C4000C7B10000F48200CAC9B10000F48200CAF2 +:104C5000CBB10000F48200CACDB10000F48200CADA +:104C6000CFB1000000002E4281E001009814004006 +:104C700048C90100F48200CAE1B100000000004010 +:104C800009B10100200000A682B001008F81A25E60 +:104C90000B7D000000800041089901009181A25E17 +:104CA0000B7D0000208000A608B1010093819F8544 +:104CB000823000000000003083840100C88122306F +:104CC000836C00009281A24F0B7D00000000004128 +:104CD00021B30100028000A682B0010013820040CF +:104CE000813201001000004184E40100038000A62D +:104CF00082B001001382004081320100F0FF0041C8 +:104D00008688010000000043849401000F0000A683 +:104D100086B0010010C4004386980100A881A24318 +:104D2000846C00000000004321B30100200000A6B5 +:104D300082B001001C00004182DC0100A581A25E5E +:104D40000B7D00000400004108990100BA81004079 +:104D500081B20000410100A686B00100500C004362 +:104D600086980100AD81A243846C000000000041E0 +:104D700021B30100BA81004081B20000410100A6C8 +:104D800086B00100600C004386980100BA81A243FE +:104D9000846C00000000004221B30100188000A6CE +:104DA00082B001001382004081320100FFFF004108 +:104DB0008288010000770041828C010001020041DD +:104DC000829801002000004182DC010018000041AF +:104DD00082DC0100B881A25E0B7D00000000004172 +:104DE00008B10100200000A682B00100BB81A25ED4 +:104DF0000B7D00004013004108990100C38122434C +:104E0000216F0000200000A682B0010012000041C6 +:104E100082DC0100C081A25E0B7D00000004004125 +:104E200008990100DE81004081B20000200000A648 +:104E300082B001001900004182DC0100C581A25E40 +:104E40000B7D000000A0004108990100DE810040B8 +:104E500081B200000000004421B3010000000040C6 +:104E600083B001000000005F839001000000005E3D +:104E70008390010000000057839001000000004172 +:104E8000C2B101000C010040813201000000005F4E +:104E90008380010000000041C2B101000C0100400C +:104EA00081320100200000A682B001000400004110 +:104EB00082DC01002000004108990100200000A6CA +:104EC00082B001001100004182DC0100D781A25EA6 +:104ED0000B7D00000100004108990100200000A6A0 +:104EE00082B00100DA81A25E0B7D00004013004118 +:104EF00008990100010000A682B0010040000041B5 +:104F00002E9901000000804081B20100200000A61F +:104F100080B00100000000CA81940100E181A25E1E +:104F20000B7D0000F482004008B10000C8142EBBC5 +:104F300085B00100E481A25E0B7D0000000000400E +:104F400087B00100F3812243216F000002822244D6 +:104F5000216F0000118000A682B001001382004082 +:104F6000813201000A82224A837C00000000004056 +:104F700087900100EE81224D837C000000000041FB +:104F800087900100F081224F837C000000000043E5 +:104F900087900100F281224E837C000000000042D5 +:104FA000879001000A82004081B20000018000A6C3 +:104FB00082B001001382004081320100018000A60E +:104FC00082B0010013820040813201000A82224235 +:104FD000837C000000000040879001001C8000A638 +:104FE00082B001001382004081320100FD81224520 +:104FF000837C00000000004187900100FF81224473 +:10500000837C00000000004387900100018222435E +:10501000837C000000000042879001000A8200406B +:1050200081B20000018000A682B00100138200401E +:1050300081320100018000A682B00100138200408D +:10504000813201000A822242837C0000000000407D +:10505000879001000000004387900100000000419C +:1050600087900100008000A682B0010013820040FA +:10507000813201000E82224B837C00000000004040 +:105080008780010000000043E0B10100FF7F00A223 +:10509000A08B010000000044A5B30100B88000CA45 +:1050A000A73301003681004081B20000200000419A +:1050B00082DC01001482A25E0B7D00000000004132 +:1050C00008B1010016829F858230000000008040F8 +:1050D00081B201001B8214F7813000001B82A249BB +:1050E000FD7F000000000048FD9301001E8215F8BE +:1050F000811400001E82A24AFD7F000000000048CB +:10510000FD9301002082A2C88132000040000040CF +:1051100080DC01000010004080DC01000000004045 +:10512000EFB3010022824240F13300003881004099 +:1051300068970000F48200BB6BB30000F48200BBF0 +:10514000B1B30000F482004081B2000000030040CF +:10515000819801000000004018B10100800000406B +:105160008398010000190040459901000000424069 +:1051700081B20100000043FFF1B10100000000FF17 +:10518000F1B101000000004181C0010000000040B9 +:1051900018B101002B82A24183500000001600408C +:1051A00045990100001900404399010000000047A3 +:1051B00043C101000000004083B00100000000F383 +:1051C00080B001000000005B81D0010000000041C0 +:1051D00080D0010000000040F6B101000000005B3B +:1051E00043C101000000004183C001003582A25488 +:1051F000836C000000000040F7B101000000004196 +:1052000083C001003C82A206836C00000000804045 +:1052100081B20100001600404399010080162E065D +:1052200083B00100360000FBF6A901004282A241D2 +:10523000835000002200004083980100000000FB22 +:10524000F6B101004582A241835000006200004097 +:1052500095980100DC9F00408132010000162D0668 +:1052600083B0010080160040459901005C0000FBFE +:10527000F6A901004B82A24183500000000000709B +:10528000F9B1010000000071F9B1010000000072E5 +:10529000F9B1010000000073F9B1010000000074D1 +:1052A000F9B101005400004095980100DC9F0040D6 +:1052B000813201000000007095B001005782227019 +:1052C000B56F00000000804197B0010000008040F1 +:1052D00097B00100B6030040A199010000002F42E1 +:1052E00099B3010062822244816C00006A822248E4 +:1052F000816C00006482224C816C00006E8222501E +:10530000816C00006F822254816C000071822258EF +:10531000816C00007682225C816C000050010040AC +:1053200081B20000000000BC09B00100F48200CA94 +:1053300001B000000000004003B001000000004187 +:10534000F38301006882A242056C00000000004166 +:1053500005B00100F48222CA07140000F48200465E +:10536000F3930000F4822043956F0000F48280CA1A +:1053700005300000F482220180300000F48200CB6E +:10538000DB910000570100BCABB30000000000BC83 +:10539000B1B30100F48200CACFB30000FF0000CA1D +:1053A00081880100F482A240747D000060002040EA +:1053B000609901007382A8B18230000072820040BF +:1053C00081B20000F48200CA79B300000000004EF0 +:1053D00081B0010000000043CB8301000000454084 +:1053E00081B201007982A241815000000000454055 +:1053F00081B201000000454081B2010084829182A7 +:10540000823000000000008A80B00100AE9F0040A2 +:1054100080CE01008282A640813200008482564004 +:1054200081B20000B6030040A199010000000053C2 +:1054300007900100B6030040A1990100000000524E +:1054400007900100D89F00418BB300000000004E80 +:1054500081B0010000000042CD8301000000464001 +:1054600081B201008982A2418150000000004640C3 +:1054700081B201000000464081B201009482918116 +:10548000823000000000008980B00100AE9F004023 +:1054900080CE01009282A640813200009482554065 +:1054A00081B20000B6030040A19901000000005243 +:1054B00007900100B6030040A199010000000053CD +:1054C00007900100D89F00418BB30000B10300405A +:1054D000A1990100C4142F4099B301005701004065 +:1054E00049B10000A0942E4397B001000000004095 +:1054F000F1B101009B82A2419750000050952040DD +:10550000E1B10100AC942E4397B0010000000040CF +:10551000F1B101009F82A24197500000000080403D +:1055200081B20100AE030040A399010000000040D9 +:1055300081B001006015004085980100080000401E +:1055400040E40100000000594194010000000050B7 +:1055500041E00100000000424094010000000057BB +:10556000419001000000004181C001000000A34201 +:10557000816C010000000041A3C10100A582A0428E +:10558000816C0000A582005085C00000DD82A24130 +:10559000017D0000B5822258737D00007800004034 +:1055A00061990100B082A8B19C30000030003845FC +:1055B0009DE001000100000E10C90000B58233C457 +:1055C00081300000B882A1AD9D200000AF82134061 +:1055D00081B200000000134E5A83010030003845AC +:1055E0009DE00100C08222AB80040000BE82A24088 +:1055F000017D0000C082225F577D00003C87004093 +:1056000081B20000C082225E577D00009F8700406B +:1056100081B20000C5822254737D000074000040F6 +:1056200061990100C082A8B1003000009084A25F9F +:10563000017C0000D086004081B20000C782A25FDA +:1056400059270000C982A25C737D0000D082A25E4F +:10565000737D0000DA82225C737D0000DB823740BC +:10566000813200007C00004061990100CA82A8B12B +:10567000363000007C00004061990100CC82A8B166 +:10568000003000001F00000002880100BF841740A6 +:1056900081B20000DB823440813200007E00004095 +:1056A00061990100D182A8B112300000D882522144 +:1056B00013040000000014412FC30100FF3F000944 +:1056C000008C01000000004301F001001183003450 +:1056D00013840000FF3F1409008C01007183004314 +:1056E00001F000000000004081B20100DB82334085 +:1056F00081320000AF82134E5A9300001487A248F3 +:10570000FD7F00000400A2AC80320000E382225A38 +:10571000737D00007A00004061990100E082A8B129 +:105720007E310000010000CF11C90000E982A240D3 +:10573000937F0000E9822244937F0000E58242A526 +:1057400080300000E882A240937F0000FB821A4074 +:105750009393000000001A4081B20100DD80A24056 +:10576000737D00000F872244216F000006872240CE +:10577000657D00000005A25B737D00000400A24966 +:10578000337D0000F3822248337D0000FF01009941 +:1057900080D801000000005081E00100A8982F404F +:1057A00033B1010000000040E0C10100DD82004093 +:1057B00081B20000AF8200408BB3000000000058AF +:1057C00061B101000000004E62B10100AF822840CB +:1057D00081320000F682004081B20000F98233403D +:1057E0001F300000AF82134E5A930000FD82A0CEFE +:1057F000815000000F83A0CD816C0000000000A547 +:105800009CB30100000000B181B001000F8322B5FC +:105810008114000080152F4049B1010001834240EE +:1058200081320000000060B465970100D0152E4061 +:1058300069B3010000001A44938301001A0000A21A +:1058400080DC010000000044F1B10100000000B163 +:10585000F1B10100000000B5F1B101000500004008 +:10586000619901008000004062DD01000A83A8A167 +:10587000E0310000E98200889EB30000E982A24185 +:10588000676F0000E982006FDB9100000F834240E8 +:1058900081320000E9821A409383000000990009D8 +:1058A00046C901003F0000F30C8801001A83A6429C +:1058B00013600000299400950330010015836140B6 +:1058C0008132000075000040619901001683A8B183 +:1058D0000C30000036947110943001001B83005886 +:1058E0001F9000001C94009503300100AF820088D7 +:1058F0001CB0000000002D0348B1010004002DF091 +:105900002EB00100EE070040979801002283234B40 +:10591000E46D00002283224BFD7F00000000004068 +:105920001F90010022002F4081B2010025838317C0 +:105930008032000026000040479901002783851728 +:10594000803200000000004847C101002D8322552D +:105950002F7C00000000004243D101000F0000FA3C +:10596000968801000000004297E00100000000421C +:1059700097D001002E83004B44C10000120000A20A +:1059800044C90100280000F602CC01000A0000A171 +:1059900042C90100000000F816B00100000028F024 +:1059A00010B00100000000F01AB00100000000A2D9 +:1059B0002AB00100C0283C460DE0010000002D4443 +:1059C00095B001003A83A2F80E3000004A832241CC +:1059D0009550000000002D5049C101003683004061 +:1059E00081B200003783A2F8166C00003783A2F85A +:1059F000106C00003783A2F01A6C00004883225814 +:105A00001F7C000000993F4213F001003F83654076 +:105A1000813200004383A2F37406000000000006F8 +:105A2000E69501004883754081B200000000000641 +:105A300096B001003F0075F30C880100000000558E +:105A400061B101000000004B62B101004683A84033 +:105A500081320000488367408132000050837741E3 +:105A60002DC300004E8322581F7C0000000000550B +:105A700061B101000000000662B101004C83A84042 +:105A8000813200004E836740813200007E8377417F +:105A90002DC30000030000071AF40100EF92000775 +:105AA000163001005F832241816C00005683224240 +:105AB000816C0000AF8200881CB000005E83225F12 +:105AC0000F7C0000E393005F011001005C83224023 +:105AD000956C00000480000342C90100000000F240 +:105AE00002B0010058930052953001005F93004BC3 +:105AF00002B0000041940009963001001A8700406E +:105B00000FB000006783A25A1F7C0000699200401A +:105B10008132010067832220856C000064839C0F22 +:105B200080320000AF8200881CB000004A93005C05 +:105B30001F0001003C95004261310100AF820088E6 +:105B40001CB00000900400079630010000002D05F5 +:105B500048B101006A8382F0183000008188004556 +:105B60008FB00000282000A696B001006E83221797 +:105B700096040000E094004B953001008188004BB2 +:105B80008FB00000EF93000348310100CA9100403C +:105B9000813001008188004081B2000000002E1099 +:105BA00048B101000000685003B00100000000038C +:105BB000F0B1010040000000E0C9010000002E50DB +:105BC00049C1010000000050F1B1010000000003D4 +:105BD000F0B101000000004261B10100200000109E +:105BE00062DD01007983A8408132000010000010BE +:105BF00062C901007B83A800E0310000AF82008809 +:105C00001CB0000000002D0348B10100000000405E +:105C10000FB00100000000F82EB00100000000F2FB +:105C200002B001000000004017B00100004100A6D2 +:105C300096B00100EE072E4797900100918322173E +:105C4000960400008F83224BFD7F00008F8323A2E8 +:105C5000026C00005893005295300100040022416C +:105C6000975000000C002D0012B00100000000F061 +:105C700000B001000000005C018001005F93004B58 +:105C800002B000000000000900B001000000005058 +:105C900003B00100AE83005C17900000A383224391 +:105CA0002F7C0000000000451F9001009C83225FB4 +:105CB0002F7C000000002E1048B1010000000058A9 +:105CC000F1B1010010000003F0C901001000000054 +:105CD000E0C90100988362426131000000000010B9 +:105CE00062B101009983A84081320000AF827288BE +:105CF0001CB0000020002D0348B10100FF0F00F68A +:105D000080880100A083A2A6816C0000A38300F21A +:105D10003AB000008D84A24BFD7F0000B09200409D +:105D2000813201003087004081B20000AE83224AF8 +:105D30002F7C0000AE8322482F7C00000A002D0338 +:105D400048B101003F0000F2868801001F000043B7 +:105D5000848801000500004380F4010098943D42CE +:105D600081E00100AE83A242E07D00008D84A24B61 +:105D7000FD7F0000B092004081320100308700407A +:105D800081B20000AE83694081320000000000A3B0 +:105D900009B001000000794147C30100B48322A18A +:105DA000096C0000F58200881CB00000B18300037C +:105DB00048B10000EE83A392036C0000949500406C +:105DC000953001000000004143C3010000000016AF +:105DD00080B201003087270880320000BB83225C3C +:105DE000177C0000BC8300002AB0000012000000F5 +:105DF0002AC801000200000880C80100C083A24335 +:105E00002F7C0000E394004081320100DC83005EBF +:105E100017900000040000018CCC0100E394004CBA +:105E20000330010000002E4602B0010010000010F7 +:105E300048C901000C000001F0CD01002C00004019 +:105E4000F0C9010000000016F0B1010010000015BB +:105E5000E0C901000000004361B10100A00000A4FE +:105E600062DD0100C983A85417100000DC83005EC6 +:105E700017900000120000002AC80100DB832243B3 +:105E80002F7C0000040000018CCC01000000004CBD +:105E900003B00100049500436131010000002E466B +:105EA00002B001001000001048C901000C00000100 +:105EB000F0CD01000C000009F0C90100000000183D +:105EC000F0B1010010000015E0C90100000000431E +:105ED00061B10100A00000A462DD0100DC83285450 +:105EE00017100000D883004081B2000004950043E1 +:105EF00061310100DE8322502F7C0000000000563B +:105F0000179001000700001798880100E183A24163 +:105F1000996C00000000005517900100000000433C +:105F200061B101004000001062DD0100E283A84081 +:105F300081320000AF8200881CB00000EB9400406A +:105F400081320100E98322432F7C00001680000388 +:105F500044C901000000001DE4B101008C94005E02 +:105F600005100100EC83A25F2F7C0000A6910001C8 +:105F700038430100B0920040813201003087004078 +:105F800081B20000F083A24BFD7F00008A840041B3 +:105F900043C300000000004027B0010000000040A3 +:105FA0002DB001000000004011B00100F383350165 +:105FB000863000006D00004061990100FB8328B12C +:105FC00030300000F483224D757D00000000001683 +:105FD00080B201007A84A740116C000000000041EB +:105FE00043C301008984004081B200006D0000407D +:105FF00061990100FB83A8B1123000000000001677 +:1060000080B201000584A740116C0000000000412F +:1060100043C301000000000910B001000000001897 +:106020002CB00100DE07004380CE0100F483AA40BB +:10603000813200000A84004081B2000040003E43EB +:1060400027E0010000000009F0B101000000001885 +:10605000E0B101000000004127C00100F483A30B60 +:1060600087500000000015401BB0010000000040F8 +:1060700023B00100120000002AC8010040002D409A +:1060800039B001001284A240276C000022000008F1 +:1060900012C80100DE070040259801001584004069 +:1060A00081B20000000000F812B00100000000F012 +:1060B00030B001000000000B25B00100000000100E +:1060C00032B0010014002001E0B10100EE070040F1 +:1060D000379801001A842301366C0000000000018B +:1060E00036B001002584824123400000208000104A +:1060F00042C9010021842240E36D000000000043FA +:1061000061B101004000001062DD01001E84A84062 +:1061100081320000AF8200881CB00000CF920043A3 +:10612000233001000000001032B0010000000041E7 +:1061300023B001000000000348B1010000800019F5 +:1061400044C90100348422451F7C00000000004C3B +:10615000F1B1010000000009F0B1010000000018D9 +:10616000F0B101000000004361B1010020000019FE +:1061700062DD01002B84A815E03100000000005012 +:1061800003D001000000005033C001000000004CAB +:1061900025D001000C002D4C13C001000000005060 +:1061A00037D00100000000502BC001001A840045C8 +:1061B0001F8000003684A312366C00003784681BF1 +:1061C00028B000000000681228B00100000000099B +:1061D000F0B1010000000018F0B101000000004320 +:1061E00061B101002000001962DD01003A84A815A8 +:1061F000E0310000608422140250000000000050D2 +:1062000033C001000000001424D001000C002D1444 +:1062100012C001005984A214365000004A84225C46 +:106220001F7C00003080001042C9010048842240D9 +:10623000E36D00000000004261B101004000001069 +:1062400062DD01004584A84081320000AF820088F1 +:106250001CB000000000000348B101000C002D5CE0 +:106260001F800100100000F02AC801000000005C3F +:106270002B800100F0070040379801004F84230174 +:10628000366C00000000000136B001005A84221B69 +:10629000026C00003000001048C9010000002E5CB4 +:1062A0001F90010000000050F1B101000000000348 +:1062B000F0B10100FF070015E08D01000000004271 +:1062C00061B10100A00000A462DD01005684A84075 +:1062D000813200005A84000348B10000000000141D +:1062E0002AC001001A84A240256C00000000004171 +:1062F00039C0010040003D4339E001000000000BBF +:1063000025B00100000000F812B001001A8400F06E +:1063100030B000000080001942C9010066842240AC +:10632000E36D00000000004361B10100400000196E +:1063300062DD01006384A84081320000AF820088E2 +:106340001CB00000CF9200402B30010018002E033B +:1063500048B101006A8422502F7C000000000056E2 +:106360001790010007000017988801006D84A24172 +:10637000996C0000000000551790010070842243C2 +:106380002F7C000000000054179001001600201D13 +:10639000E4B101007284A340276C00007484605F44 +:1063A000179000000084000B16DC01000000601351 +:1063B000169401008C94005E051001003087A25FE6 +:1063C0002F7C00001480000342C90100000000F28D +:1063D00002B00100A691000138430100308700405F +:1063E00081B200000000004083B001000000004DB9 +:1063F00061B101000000001662B101007C84A84078 +:10640000813200000000000862B101007E84A840D3 +:106410008132000089842213826C000040003D43D9 +:1064200083E00100000000F810B00100000000F05F +:106430002CB001000000001662B101008484A84065 +:10644000813200000000000862B101008684A8408B +:10645000813200008084004183C0000000001540AC +:1064600081B20100008200A604B00100A0980040A3 +:1064700047990100300500418930010058930052CE +:10648000953001005F93004B02B000003087004060 +:106490000FB000000000005F01800100100000004C +:1064A0000EF401003F000000008801000300000717 +:1064B0001AF40100EF920007163001009B8422417C +:1064C000816C000099842242816C0000AF820088B8 +:1064D0001CB000009A84225F0F7C00001A870040E5 +:1064E0000FB00000A384A25A1F7C000069920040F4 +:1064F00081320100A3842220856C0000A0849C0FBF +:1065000080320000AF8200881CB000004A93005C1B +:106510001F0001003C95004261310100AF820088FC +:106520001CB00000900400079630010000002D050B +:1065300048B10100000000F018B00100A984223A1F +:10654000016C0000000000008EB001008188004056 +:1065500001B000000000004081B201002E002D05B6 +:1065600048B10100AD84A240E76D00000A00004080 +:106570008F9801008188004001B0000034920040F3 +:10658000813201001C94009503300100AF82008825 +:106590001CB0000000002D0348B1010022002DF0C6 +:1065A0002EB00100282000A696B00100B684221764 +:1065B00096040000E094004B953001008188004C67 +:1065C0008FB00000B88483178032000000000044C0 +:1065D00043C10100BA8485178032000000000048E2 +:1065E00043C10100280000F602CC0100120000A106 +:1065F0002AC80100EF93004081320100CA91004196 +:10660000813001008188004081B20000000000015B +:1066100000D0010000002E1048B101002800004009 +:10662000F199010000000003F0B10100000000003A +:10663000F0B10100C4846447613100000000001023 +:1066400062B10100C584A81BE0310000AF827488EC +:106650001CB000000000004503E0010008002D030D +:1066600048B10100EA8401FB083000003D8587FB4A +:1066700022300000000000FA0EB00100000000F817 +:1066800014B00100030000071AF40100EF920007A4 +:1066900016300100E0842241816C0000D484224243 +:1066A000816C0000AF8200881CB00000DF84225F94 +:1066B0000F7C0000380000047E890100D884A65FAA +:1066C0000F0000004292004005300100DD840040D0 +:1066D00081B20000130000408798010000002D03E4 +:1066E00048B101000C002DF082B00100000000F064 +:1066F00084B00100CE930040053001000000005C32 +:106700001F9001001A8700400FB00000E884A25AD1 +:106710001F7C00006992004081320100E884222041 +:10672000856C0000E5849C0F80320000AF820088F9 +:106730001CB000004A93005C1F0001003C95004221 +:1067400061310100AF8200881CB000009004000796 +:106750009630010000002D0548B10100000000F056 +:1067600018B00100EC84210480200000ED8400407A +:1067700010C90000C387004B81B000000C850043A6 +:1067800081B00000108500FB22B00000C3870041EB +:1067900081B000008188004E8FB000000885005A4B +:1067A0008FB00000F58400478FB00000C38700530E +:1067B00081B00000C387005681B0000032002D0573 +:1067C00048B101008188A00AE46D0000FB84A24169 +:1067D000197C0000FA84220A80320000818800536C +:1067E0008FB00000818800548FB000000485220A19 +:1067F00080320000FE84A20AE46D00008188005D02 +:106800008FB00000000000F280B001000000000A1C +:1068100080D001000285A091816C00008188005E1B +:106820008FB00000250000408F9801008188004053 +:1068300081B2000006852091E56D0000818800543A +:106840008FB00000210000408F9801008188004037 +:1068500081B2000032002D0548B101008188A00AF4 +:10686000E46D0000240000408F9801008188004002 +:1068700081B2000037002D0548B10100040000F38B +:1068800082F40100C387A042836C0000C3870054D8 +:1068900081B00000000000F20EB00100030000070C +:1068A0001AF4010000B5000D42C9010007000007FD +:1068B000168801001985220BE67D00000A000040C1 +:1068C00087980100DF950040813201000000004000 +:1068D0000FB001001A87005C1F9000002B8522502A +:1068E000FD7F00002685A254FD7F00001E852255F5 +:1068F000FD7F00008200004087980100168500405F +:1069000081B2000016852253FD7F00001480000331 +:1069100042C90100000000F096B001001000004BD9 +:1069200080F401000CBC00408798010026852243BA +:10693000806C0000FFFF004B808801001685A24399 +:10694000806C00007C9600404799010027854640F6 +:10695000813200002A85A0F0306F00001C851E40A7 +:1069600081B2000000001E4131C30100739200405B +:10697000253001002F859C0F80320000AF820088F7 +:106980001CB000004A93005C1F000100148000034B +:1069900042C90100000000F096B0010000002F0580 +:1069A00048B101001000000718E401000008000CC5 +:1069B000E0990100900400079630010000B5000D39 +:1069C00046C9010036853040813200000000000BCE +:1069D000E6910100000200A146C901000000000B81 +:1069E000E691010004002E0548B1010000001040AE +:1069F000E1B10100C387004081B00000000000FB4E +:106A000028B00100000000FB86B00100000000F883 +:106A100014B0010047852246237C000043852240B4 +:106A2000877C0000000000481F900100458522413E +:106A3000877C0000000000471F900100478522422C +:106A4000877C0000000000451F9001004785661B01 +:106A50002C300000000000A013B0010000007641BF +:106A600041C3010076852392156C00007685A2450E +:106A70001F7C00007A85224BFD7F0000170000D0AC +:106A8000A2C901000000004027B001000200000A76 +:106A900024C80100AB9200400F3001007485220829 +:106AA0004030000000000041A3C10100F0070012C7 +:106AB00024CC01005085AA412740000001000013AA +:106AC00080CC01007085264023300000000000408B +:106AD00083B001006000000384C8010010000010B2 +:106AE00048CD0100170000D0A2C901005D85A24079 +:106AF000836C00006985004183B000000080004283 +:106B000044990100000068213896010000002E50D1 +:106B100049C101006285A244236C000030000003DB +:106B200048C9010000000044F1B101000C00002040 +:106B3000F0C901000000004461B10100A00000A400 +:106B400062DD01006585A842E031000000000044DC +:106B500085C001000000004123C001000000004189 +:106B6000A3C101005B85A2418150000070852240D5 +:106B7000236C00000000004461B1010040000010DF +:106B800062DD01006D85A84081320000AF8200887F +:106B90001CB000000000000348B10100EE070040F7 +:106BA00025980100170000D02AC80100838500172E +:106BB00010B0000095940040813201007A850040B9 +:106BC00081B20000AB92009225300100000000402D +:106BD00031B001007A8522082E3000008385004103 +:106BE00027B00000808000A604B00100060000402D +:106BF00087980100DF95000A8C30010000000040FA +:106C00000FB001000000005C1F9001008285229FF0 +:106C1000136C0000020000881CCC0100F5820040CB +:106C200081B200001A8700413FC30000000000400D +:106C30000FB001002800000180CE010097852A4096 +:106C4000813000000080001044C901004000004075 +:106C5000819801008C85A2481F7C00008C85A2478A +:106C60001F7C00008C85A307036C0000800000409F +:106C7000819801008F85A340026C0000280000016C +:106C8000F0CD0100918500400FB0000028000040C9 +:106C9000F0CD0100040000400ECC010028000003EC +:106CA000F0C9010028000000F0C901000000001632 +:106CB000E0B101000000004761B1010020000010B8 +:106CC00062DD01009585A85C1F10000000000040F7 +:106CD00043990100000000F008B00100A0012D4020 +:106CE00000C001006186220F42050000A8859C0FAC +:106CF000803200000000005C1F8001000080001056 +:106D000042C90100A3852240E36D00000000004756 +:106D100061B101004000001062DD0100A085A840C3 +:106D200081320000AF8200881CB00000A8852207D5 +:106D3000803200000000000342B1010000000007A3 +:106D400042C10100008000A1469901000000005FDF +:106D5000E1910100C006A2451F7C00001000000365 +:106D600048C9010000002D5429C00100000000F8AE +:106D700018B00100000000F804B00100000000F8A5 +:106D80000EB00100420000030AC801000C0000A47C +:106D90000CC80100ED920040813201000000001497 +:106DA00002B001000000001424D001000000001413 +:106DB00010C001001200000810C8010000000040CF +:106DC00023B00100FE7F000544C901000000000A55 +:106DD000E4B10100D18522018032000000003C4472 +:106DE00023E0010000002EA480B00100000000108C +:106DF00048C10100BE85A307026C0000BF85680181 +:106E00001AB00000000068071AB001000000000D71 +:106E100002D0010000000005F0B101000000000CEC +:106E2000F0B1010000000002E0B101000000000D1F +:106E30000AC00100CB852240036C0000CB852242B2 +:106E4000236C00000000004123C001000000004747 +:106E500061B10100A00000A462DD0100EF852840BF +:106E600081320000C885004081B20000000000109F +:106E700080C001000000004761B101000000004037 +:106E800062B10100CD85A84023300000AF820088A8 +:106E90001CB00000EF85004081B2000000003C44BF +:106EA00023E00100000000A486B0010000002E10C5 +:106EB00048C10100D685A3120E6C0000D78560077B +:106EC0001AB00000000060121AB001000000680D46 +:106ED00016940100FFFF000B16D80100000068089F +:106EE0003E9601000000000CF0B10100000000021D +:106EF000E0B101000000001086C001000000004663 +:106F000061B101002000004362DD0100DE85A85C64 +:106F10001F1000000D86220D146C0000E485220D68 +:106F2000246C00000000000D10C00100E885000D79 +:106F300024D00000000000412BC00100000000151B +:106F4000A2B101001000002010C80100F0070040AD +:106F500025980100EA852242236C0000EF8500415C +:106F600023C000000000004661B101004000001095 +:106F700062DD0100EB85A85C1F000000AF82008885 +:106F80001CB000000000004023B001000D86220D5F +:106F9000145000000C86A20D0E500000FB85224606 +:106FA0001F7C0000000000461F80010030800010A0 +:106FB00042C90100F9852240E36D0000000000474E +:106FC00061B101004000001062DD0100F685A840BB +:106FD00081320000AF8200881CB0000020800003D6 +:106FE000469901000000005FE191010000002D06BC +:106FF00048B10100000000F818B00100000000F8DE +:1070000004B0010000861FF00E300000B885004C6F +:107010000DC0000000002E5F0F800100B88523071F +:10702000146C00003000001048C90100240000402A +:10703000F199010000000003F0B101000000000020 +:10704000F0B1010000000016F0B1010024000000C2 +:1070500000C801000000004761B10100A00000A4C9 +:1070600062DD01000986A8461F100000B8850003F4 +:107070000CB00000B885000D18C0000004002E14EC +:107080000AD001001200000548CD0100FE7F000576 +:1070900042C901000C002AF2E0B10100138622402F +:1070A000316C000000006018389601001E0000409E +:1070B00043990100008100F680CE01001786A640AA +:1070C000813200000000004443C101001986220BF8 +:1070D000ED6D0000080000A142C90100020000A1FE +:1070E00046C901000F0000FA948801000200004A1E +:1070F00086E40100000000F60EB001002186224760 +:107100001F7C000004001F430E5000002186A04693 +:107110000F400000000000410FC0010025862248FA +:107120001F7C00000000004091B0010004000FA28D +:10713000423100002886004089B000000C0000A207 +:1071400042C901000000004389B001000000004373 +:1071500095D00100000000FC82B001002B86A04108 +:10716000904000000000004191C00100308622479D +:107170001F7C00003086A043896C000030862045CB +:10718000896C00003086A0410E40000000000041E4 +:107190000FC001000000004189C001002886A24103 +:1071A00095500000398622481F7C000010000048DE +:1071B00092F40100FFFF0048908801003786904854 +:1071C000924000000000004193C001000A0000A2AC +:1071D00044C901000000662093A401003080001023 +:1071E00044C9010012000014F0C90100000000179A +:1071F000F0B1010012000005E0CD010030000010E8 +:1072000080C801000000004461B10100200000407E +:1072100062DD01003F86A840813200004A86225C80 +:107220001F7C000000003C4423E0010000002D1002 +:1072300048C1010049862240E36D0000000000467D +:1072400061B101004000001062DD01004686A840E7 +:1072500081320000AF8200881CB000000000005C9A +:107260001F8001004D86A2471F7C0000E392004072 +:1072700081320100C686001710B00000EA9200407B +:107280008132010000002F0348B101005186A007A0 +:10729000164000000000004117C001000000000B74 +:1072A000E4B101000000005017F00100558690F293 +:1072B000164000000000004117C0010000006620D9 +:1072C00017A40100100000142AC80100000000509B +:1072D0002BE00100000000F22A9401003080001031 +:1072E00042C901005F862240E36D000000000044B7 +:1072F00061B101004000001062DD01005C86A84021 +:1073000081320000AF8200881CB0000000800017AE +:1073100010DC0100C686004081B2000069869C0F27 +:10732000803200000000005C1F800100008000101F +:1073300042C9010069862240E36D00000000004759 +:1073400061B101004000001062DD01006686A840C6 +:1073500081320000AF8200881CB000006E862207D8 +:10736000803200000000000342B10100000000076D +:1073700042C10100008000A1469901000000005FA9 +:10738000E191010004002E0348B101000000000A51 +:10739000E0B1010073862240316C00000C00004017 +:1073A00045990100000060183896010000002E1079 +:1073B00048B1010000000050F1B1010000000008D8 +:1073C000F0B1010000000003E0B101000000004442 +:1073D00061B101000000001062B101007886A84090 +:1073E00023300000AF8200881CB0000000002D5246 +:1073F00011C001001000000348C90100000000F89E +:1074000018B00100000000F804B00100000000F80E +:107410000EB001000C0000A40CC8010000003C44A8 +:1074200023E00100000000A486B0010000002E103F +:1074300048C101008686A3120E6C0000878668078B +:107440001AB00000000068121AB00100000000101D +:1074500086C00100000068083E9601000000000C94 +:10746000F0B1010000000002E0B1010000000046A0 +:1074700061B101002000004362DD01008C86A85C40 +:107480001F100000BB86220D146C00009286220D96 +:10749000246C00000000000D10C001009686000D55 +:1074A00024D00000000000412BC0010000000015A6 +:1074B000A2B101001000002010C80100F007004038 +:1074C0002598010098862242236C00009D86004189 +:1074D00023C000000000004661B101004000001020 +:1074E00062DD01009986A85C1F000000AF82008861 +:1074F0001CB000000000004023B001000400220D79 +:1075000014500000BA86A20D0E500000A986224633 +:107510001F7C0000000000461F800100308000102A +:1075200042C90100A7862240E36D00000000004729 +:1075300061B101004000001062DD0100A486A84096 +:1075400081320000AF8200881CB000002080000360 +:10755000469901000000005FE191010000002D0646 +:1075600048B10100000000F818B00100000000F868 +:1075700004B00100AE861FF00E3000008186004C82 +:107580000DC0000000002E5F0F80010081862307E0 +:10759000146C00003000001048C9010024000040B5 +:1075A000F199010000000003F0B1010000000000AB +:1075B000F0B1010000000016F0B10100240000004D +:1075C00000C801000000004761B10100A00000A454 +:1075D00062DD0100B786A8461F1000008186000307 +:1075E0000CB000008186000D18C00000C486225C2B +:1075F0001F7C00000000005C1F80010000003C4474 +:1076000023E0010000002D1048C10100C486224083 +:10761000E36D00000000004661B101004000001071 +:1076200062DD0100C186A84081320000AF8200887F +:107630001CB000000000001710B00100C68600401A +:107640002BB00000008000034499010000000004FA +:10765000E0B10100CB86229F136C0000020000887D +:107660001CCC0100F582004081B20000F095004181 +:107670003F430100000000408DB0010000000040C9 +:1076800005B00100DF9500400F3001003087005C3D +:107690001F900000100000000EF401000000003AEE +:1076A00001840100030000071AF40100EF920007B3 +:1076B00016300100DA862241816C0000D886224211 +:1076C000816C0000AF8200881CB00000D986225F68 +:1076D0000F7C00001A8700400FB00000E286A25A1B +:1076E0001F7C00006992004081320100E286222066 +:1076F000856C0000DF869C0F80320000AF8200881E +:107700001CB000004A93005C1F0001003C95004241 +:1077100061310100AF8200881CB0000090040007B6 +:107720009630010000002D0548B10100000000F076 +:1077300018B001000000000080B00100C387A25F04 +:10774000816C0000A8002D431980010037002DF046 +:1077500024B00100040000F38EF401000F0000F3D8 +:1077600090880100F18622488E6C000036000040AF +:107770004399010058003D43E7E10100F1861FF005 +:10778000246C0000F08623418F6C0000C387004703 +:1077900081B00000C387004881B000004000004075 +:1077A00043990100B0002DF014B00100F686220AC2 +:1077B00090400000C395004091300100C387A24073 +:1077C00080320000B0002D4581B00100028722F018 +:1077D0002C300000A3002D3083B00100AC002DF34D +:1077E00082E00100FC86A3412C6C00000000001622 +:1077F00082B0010098002DF082C0010088002DF0B9 +:1078000082D00100000000F298E80100C387204CFC +:10781000826C00007C002D4198E80100C38720F0B5 +:10782000986C00001A87220A803200004002000C87 +:107830007E8901001A87A64081320000C387004973 +:1078400081B00000200000A680B001000A8722431A +:10785000216F00001380004080DC01000B87004096 +:1078600081B200001A80004080DC01000B87A25E1C +:107870000B7D00000000004008B101000D879F85CE +:10788000803200001187004081B20000EC8222406B +:10789000577D0000010000405799010011874240C8 +:1078A000813200000000004493930100DD821A5BE6 +:1078B00069930000040000CB81C8010017872240B3 +:1078C000F27F0000C480006F9733010019872240C7 +:1078D000737D0000DE8000418BB300001487004000 +:1078E00081B2000021879C0F8032000000800010D0 +:1078F00042C9010021872240E36D000000000045DD +:1079000061B101004000001062DD01001E87A84047 +:1079100081320000AF8200881CB000004592220234 +:107920008032000022874240813200000000004483 +:107930009393010045921A02689700002C879C0FD0 +:10794000803200000080001042C901002C872240D4 +:10795000E36D00000000004561B10100400000102F +:1079600062DD01002987A84081320000AF820088D3 +:107970001CB000004F922202803200002D8742404E +:107980008132000000000044939301004F921A02DC +:107990006897000037879C0F80320000008000103D +:1079A00042C9010037872240E36D00000000004516 +:1079B00061B101004000001062DD01003487A84081 +:1079C00081320000AF8200881CB00000F9822202E0 +:1079D00080320000388742408132000000000044BD +:1079E0009393010000001A0268970100F982004099 +:1079F00005B00000008000A656B1010056952F404A +:107A000005B001008887A240E76D0000B8942941C5 +:107A1000E7B1010000000054EF930100000000F204 +:107A20000EB00100290000400D9801000900000778 +:107A300012E40100000000A713C0010003000007CA +:107A40001AF401000700000716880100FFFF00106C +:107A500034D801000000000334940100000000400D +:107A600023B00100201800401198010000B5000D5E +:107A700042C901006C87220BE67D00004D87604003 +:107A800081320000FFFF000784890100548705C28E +:107A900024300000580400408132010000002D0510 +:107AA00048B10100898770F0183001006C870040F0 +:107AB00081B200000000704081B201006387A048DD +:107AC000236C00000000005035D001000080001A37 +:107AD00042C901005D872240E36D000000000042C2 +:107AE00061B101004000001A62DD01005A87A84020 +:107AF00081320000AF8200881CB000002098004056 +:107B000043990100898700F8183001005E87A2417F +:107B100023500000FFFF001034D8010000000003D4 +:107B200034940100201800401198010000002E1A22 +:107B300048B1010000000044F1B10100000000085C +:107B4000F0B101000000004261B101002000001A04 +:107B500062DD01006787A809E031000000000041F4 +:107B600023C001000000005035C0010000000044A7 +:107B700011C00100788722410D5000000000004133 +:107B80000FC001007487A0AA0F6C00000000004124 +:107B90000FB001000900000712E40100000000A777 +:107BA00013C00100000000401BB001004B870041E2 +:107BB00017B000000002000912C801004B87834182 +:107BC000174000000000004017B001004B87004143 +:107BD0001BC0000083872340236C0000000000507E +:107BE00035D001000080001A42C901008087224080 +:107BF000E36D00000000004261B101004000001A86 +:107C000062DD01007D87A84081320000AF820088DC +:107C10001CB000002098004043990100898700F8BB +:107C2000183001008187A24123500000000000416C +:107C30000FC001008687A0AA0F6C00000000004161 +:107C40000FB00100B8942007E4B101005695204020 +:107C5000E7B101001A8700400FB00000FFFF000CE1 +:107C600080D80100C002000C7E8901009B87265449 +:107C7000613100009187870C803200000F000040C6 +:107C80006299010091872840813200009187A254B7 +:107C9000777D00008D87004081B2000096872246E4 +:107CA000197C00000D000040629901000000A8400E +:107CB00081B200000000A254777D0100928700404D +:107CC00081B200009B872249197C00000E00004011 +:107CD000629901000000A84081B200000000A25497 +:107CE000777D01009687004081B2000010000040BF +:107CF000629901000000A84081B200000000A25477 +:107D0000777D01009B87004081B2000030942F55A1 +:107D1000F1930100004000A656B10100F982A24192 +:107D2000E551000064000040E5990100A38744404C +:107D300081320000A687A293576F00000000004127 +:107D400057C3010000001CAB27B30100F982225089 +:107D5000FD7F0000F9822251FD7F0000F982A241DF +:107D60001D530000504600401D9B01003805004097 +:107D7000813201000E000048B2CB01001004004027 +:107D800049310100B2872240B56F00000E00004863 +:107D9000B2CB010020040041B5530100F98200403C +:107DA00081B2000000000051FD8301004016004038 +:107DB0004599010040050040493101001E0000487E +:107DC000B2CB01001004004081320100000000DA53 +:107DD00091C0010004000048B2CB01002004004023 +:107DE000B533010060162040E5B10100408200403B +:107DF000B533010008000048B2CB0100FFFF004A84 +:107E0000B48B010020040040813201000A000048C8 +:107E1000B2CB01001000004AB4F70100200400407A +:107E200081320100F982004081B20000050000406B +:107E300043990100000000F308B001000400204055 +:107E4000E6B101000300004096E4010000000004D8 +:107E500096C00100C987004B10C90000EC8A0041A0 +:107E600009B00000040000208FB0000004000020D2 +:107E70008FB00000040000208FB00000040000203C +:107E80008FB00000040000208FB00000040000202C +:107E90008FB00000040000208FB00000040000201C +:107EA0008FB00000208B004109B0000004000020CA +:107EB0008FB00000040000208FB0000004000020FC +:107EC0008FB00000040000208FB0000004000020EC +:107ED0008FB00000040000208FB0000004000020DC +:107EE0008FB00000040000208FB00000528B0045CE +:107EF00009B00000528B004509B00000528B0045CC +:107F000009B00000528B004509B0000004000020B9 +:107F10008FB00000040000208FB00000040000209B +:107F20008FB00000040000208FB00000918B004350 +:107F300009B00000BA8B004309B00000BE8B0044BA +:107F400009B00000098D004509B0000004000020C0 +:107F50008FB00000040000208FB00000040000205B +:107F60008FB00000040000208FB00000040000204B +:107F70008FB00000CA8B004309B00000C98B0043DA +:107F800009B00000EA8A004509B0000004000020A2 +:107F90008FB00000040000208FB00000040000201B +:107FA0008FB00000040000208FB00000798C0042E8 +:107FB00009B00000798C004309B00000798C0044BE +:107FC00009B00000EA8A004509B000000400002062 +:107FD0008FB00000040000208FB0000004000020DB +:107FE0008FB00000040000208FB0000004000020CB +:107FF0008FB00000998C004309B0000004000020FD +:108000008FB00000EA8A004509B00000040000209B +:108010008FB00000040000208FB00000040000209A +:108020008FB00000040000208FB00000040000208A +:108030008FB00000B78C004309B00000B78C00443B +:1080400009B00000EA8A004509B0000004000020E1 +:108050008FB00000040000208FB00000040000205A +:108060008FB00000040000208FB00000040000204A +:108070008FB00000B78C004209B00000040000205F +:108080008FB00000EA8A004509B00000040000201B +:108090008FB00000040000208FB00000040000201A +:1080A0008FB00000040000208FB00000040000200A +:1080B0008FB00000DF8C004409B0000004000020F5 +:1080C0008FB00000EA8A004509B0000004000020DB +:1080D0008FB00000040000208FB0000004000020DA +:1080E0008FB00000040000208FB00000EA8A004238 +:1080F00009B00000F08C004509B00000F08C00458C +:1081000009B00000EA8A004509B000000400002020 +:108110008FB00000040000208FB000000400002099 +:108120008FB00000040000208FB00000F28C0042ED +:1081300009B00000F28C004309B00000F28C00444A +:1081400009B00000F28C004509B0000004000020D6 +:108150008FB00000040000208FB000000400002059 +:108160008FB00000040000208FB000000400002049 +:108170008FB00000040000208FB00000FA8C004493 +:1081800009B00000EA8A004509B0000004000020A0 +:108190008FB00000040000208FB000000400002019 +:1081A0008FB00000040000208FB000000B8D004253 +:1081B00009B00000FB8C004309B000000B8D0044A7 +:1081C00009B00000EA8A004509B000000400002060 +:1081D0008FB00000040000208FB0000004000020D9 +:1081E0008FB00000040000208FB0000004000020C9 +:1081F0008FB000000C8D004309B00000028D0044D8 +:1082000009B00000EA8A004509B00000040000201F +:108210008FB00000040000208FB000000400002098 +:108220008FB00000EA8A004109B00000778C00425C +:1082300009B00000778C004309B00000778C00443F +:1082400009B00000EA8A004509B0000004000020DF +:108250008FB00000040000208FB000000400002058 +:108260008FB00000EA8A004109B000000D8D004285 +:1082700009B000000D8D004309B000000D8D0044D1 +:1082800009B00000EA8A004509B00000040000209F +:108290008FB00000040000208FB000000400002018 +:1082A0008FB00000040000208FB000000400002008 +:1082B0008FB00000040000208FB0000004000020F8 +:1082C0008FB00000148D004509B0000004000020AC +:1082D0008FB00000040000208FB0000004000020D8 +:1082E0008FB00000168D004209B00000040000208D +:1082F0008FB00000040000208FB0000004000020B8 +:108300008FB00000040000208FB0000004000020A7 +:108310008FB00000040000208FB000000400002097 +:108320008FB00000040000208FB00000228D0043B9 +:1083300009B00000818D004309B00000BE8B0044ED +:1083400009B00000098D004509B0000004000020BC +:108350008FB00000040000208FB000000400002057 +:108360008FB00000040000208FB000000400002047 +:108370008FB00000898D004309B00000BE8B00441F +:1083800009B00000098D004509B00000040000207C +:108390008FB00000040000208FB000000400002017 +:1083A0008FB00000040000208FB000000400002007 +:1083B0008FB000009A8D004309B000000400002037 +:1083C0008FB00000EA8A004509B0000004000020D8 +:1083D0008FB00000040000208FB0000004000020D7 +:1083E0008FB00000040000208FB000008E8B00438F +:1083F00009B00000858D004309B00000BE8B004429 +:1084000009B00000098D004509B0000004000020FB +:108410008FB00000040000208FB0000007002D0581 +:1084200048B10100000000F308B001000600204739 +:10843000E6B101000400004796E401000000004797 +:1084400096D001000000004796D001000000000413 +:1084500096C001008988004B10C90000B28D004908 +:1084600009B000000400002085B0000004000020D6 +:1084700085B000000400002085B00000040000204A +:1084800085B000000400002085B00000040000203A +:1084900085B000000400002085B00000040000202A +:1084A00085B000000400002085B00000040000201A +:1084B00085B000000400002085B00000040000200A +:1084C00085B000000400002085B0000004000020FA +:1084D00085B00000EB8D004209B0000004000020D0 +:1084E00085B000000400002085B0000004000020DA +:1084F00085B000000400002085B0000004000020CA +:1085000085B000000400002085B0000004000020B9 +:1085100085B000000400002085B0000004000020A9 +:1085200085B000000400002085B000000400002099 +:1085300085B000000400002085B000000400002089 +:1085400085B00000F18D004609B000000400002055 +:1085500085B000000400002085B000000400002069 +:1085600085B000000400002085B000000400002059 +:1085700085B000000400002085B000000400002049 +:1085800085B000000400002085B000000400002039 +:1085900085B000000400002085B000000400002029 +:1085A00085B000000400002085B000000400002019 +:1085B00085B000000400002085B00000FF8D00425F +:1085C00009B000000400002085B00000218E0042A8 +:1085D00009B000000400002085B000000400002065 +:1085E00085B000000400002085B0000004000020D9 +:1085F00085B000000400002085B0000004000020C9 +:1086000085B000001C8E004A09B000000400002064 +:1086100085B000000400002085B0000004000020A8 +:1086200085B000000400002085B00000248E0043C7 +:1086300009B000000400002085B000007D8E0044D9 +:1086400009B000000400002085B0000004000020F4 +:1086500085B000000400002085B000000400002068 +:1086600085B000000400002085B000000400002058 +:1086700085B000007C8E004B09B000000400002093 +:1086800085B000000400002085B000000400002038 +:1086900085B00000F48D004109B000000400002006 +:1086A00085B00000F48D004309B00000F48D004453 +:1086B00009B00000F48D004509B00000F48D0046BB +:1086C00009B00000F48D004709B00000F48D0048A7 +:1086D00009B00000F48D004909B00000F48D004A93 +:1086E00009B00000F48D004B09B00000F48D004C7F +:1086F00009B00000F48D004D09B000000400002016 +:1087000085B000000400002085B00000DC8E00422F +:1087100009B000000400002085B00000DC8E004499 +:1087200009B000000400002085B000000400002013 +:1087300085B000000400002085B000000400002087 +:1087400085B000000400002085B000000400002077 +:1087500085B00000DC8E004B09B000000400002052 +:1087600085B000000400002085B000000400002057 +:1087700085B000000400002085B000000400002047 +:1087800085B00000F48E004509B000000400002010 +:1087900085B000000400002085B000000400002027 +:1087A00085B000000400002085B000000B8F00475A +:1087B00009B000000400002085B00000E88E0045EC +:1087C00009B000000400002085B000000400002073 +:1087D00085B000005491004609B00000040000205C +:1087E00085B000000400002085B0000004000020D7 +:1087F00085B000000400002085B0000004000020C7 +:1088000085B00000218E004609B00000FF8D0046B3 +:1088100009B000001A8E004709B000001A8E004807 +:1088200009B000000400002085B000000400002012 +:1088300085B000000400002085B000001C8E004AB6 +:1088400009B000000400002085B0000004000020F2 +:1088500085B000000400002085B000000400002066 +:1088600085B000000400002085B000000400002056 +:1088700085B000007D8E004509B00000248E0043C5 +:1088800009B000001A8E004709B000001A8E004897 +:1088900009B000000400002085B0000004000020A2 +:1088A00085B000000400002085B000007C8E004CE4 +:1088B00009B000000400002085B000000400002082 +:1088C00085B000000400002085B0000004000020F6 +:1088D00085B000000400002085B0000004000020E6 +:1088E00085B00000118F004409B00000118F0042D4 +:1088F00009B00000D58A004709B00000D58A0048B9 +:1089000009B000000400002085B000000400002031 +:1089100085B000000400002085B00000118F004BDE +:1089200009B000000400002085B000000400002011 +:1089300085B00000F48D004109B00000348F00477D +:1089400009B000000400002085B000001C8F004723 +:1089500009B000000400002085B0000004000020E1 +:1089600085B000000400002085B000000400002055 +:1089700085B000000400002085B000000400002045 +:1089800085B000001C8F004709B0000004000020E3 +:1089900085B000000400002085B000000400002025 +:1089A00085B000000400002085B000000400002015 +:1089B00085B000000400002085B000000400002005 +:1089C00085B000001C8F004709B00000348F0047BD +:1089D00009B000001A8E004709B000001A8E004846 +:1089E00009B000000400002085B000000400002051 +:1089F00085B000000400002085B000001C8F0047F7 +:108A000009B000000400002085B000000400002030 +:108A100085B000000400002085B0000004000020A4 +:108A200085B000000400002085B000000400002094 +:108A300085B000000400002085B000000400002084 +:108A400085B00000438F004709B00000438F004805 +:108A500009B000000400002085B0000004000020E0 +:108A600085B000000400002085B000000400002054 +:108A700085B000000400002085B000000400002044 +:108A800085B00000A68F004009B00000C48F0047E9 +:108A900009B00000B88F004809B00000148F0047EB +:108AA00009B00000148F004709B00000C48F0047D0 +:108AB00009B00000CB8F004709B00000CB8F004801 +:108AC00009B000000400002085B00000B88F004805 +:108AD00009B00000148F004709B00000148F004750 +:108AE00009B00000B88F004809B000000400002061 +:108AF00085B000000400002085B0000004000020C4 +:108B000085B00000DC8E004309B0000004000020A6 +:108B100085B00000DC8E004509B00000DC8E004608 +:108B200009B000001A8E004709B000001A8E0048F4 +:108B300009B000000400002085B00000DC8E004A6F +:108B400009B000000400002085B00000DC8E004C5D +:108B500009B000000400002085B0000004000020DF +:108B600085B000000400002085B00000338F00476E +:108B700009B00000278F004809B000001B8F004794 +:108B800009B000001B8F004709B00000338F004779 +:108B900009B00000D58A004709B00000D58A004816 +:108BA00009B000000400002085B00000278F0048B5 +:108BB00009B000001B8F004709B000001B8F004761 +:108BC00009B00000278F004809B000000400002011 +:108BD00085B000000400002085B00000CD8F004269 +:108BE00009B000000400002085B00000CD8F0044D3 +:108BF00009B000000400002085B00000040000203F +:108C000085B000000400002085B0000004000020B2 +:108C100085B000000400002085B0000004000020A2 +:108C200085B00000CD8F004B09B00000040000208B +:108C300085B000000400002085B000000400002082 +:108C400085B000000400002085B000000400002072 +:108C500085B00000CD8F004309B000000400002063 +:108C600085B00000CD8F004509B00000CD8F0046D3 +:108C700009B00000CD8F004709B00000CD8F00483B +:108C800009B000000400002085B00000CD8F004A2C +:108C900009B000000400002085B00000CD8F004C1A +:108CA00009B00000CD8F004C09B000000400002086 +:108CB00085B000000400002085B000000400002002 +:108CC00085B00000E88F004609B0000004000020D5 +:108CD00085B000000400002085B0000004000020E2 +:108CE00085B000000400002085B000000B8F004715 +:108CF00009B000000400002085B00000E88F0046A5 +:108D000009B000000400002085B00000040000202D +:108D100085B000000400002085B0000004000020A1 +:108D200085B000000400002085B000000400002091 +:108D300085B00000E990004609B000000400002062 +:108D400085B000000400002085B000000400002071 +:108D500085B000000400002085B000000B8F0047A4 +:108D600009B000000400002085B00000E990004632 +:108D700009B000000400002085B0000004000020BD +:108D800085B00000E990004609B000000400002012 +:108D900085B000000400002085B000000400002021 +:108DA00085B000000400002085B000000E91004254 +:108DB00009B000000400002085B00000040000207D +:108DC00085B000000400002085B0000004000020F1 +:108DD00085B000000400002085B0000004000020E1 +:108DE00085B000000D91004A09B000000400002089 +:108DF00085B000000400002085B0000004000020C1 +:108E000085B000000400002085B0000004000020B0 +:108E100085B000000400002085B0000004000020A0 +:108E200085B000000E91004609B00000040000204B +:108E300085B000001A8E004709B000001A8E004865 +:108E400009B000000400002085B0000004000020EC +:108E500085B000000400002085B000000D91004A9C +:108E600009B000000400002085B0000004000020CC +:108E700085B000000400002085B000000400002040 +:108E800085B000000400002085B000000400002030 +:108E900085B000000400002085B000000400002020 +:108EA00085B000000400002085B000000400002010 +:108EB00085B00000D88F004109B0000004000020F8 +:108EC00085B000000400002085B0000004000020F0 +:108ED00085B000000400002085B0000004000020E0 +:108EE00085B000000400002085B00000E58F00423E +:108EF00009B000000400002085B00000E58F0044A8 +:108F000009B000000400002085B00000040000202B +:108F100085B000000400002085B00000040000209F +:108F200085B000000400002085B00000040000208F +:108F300085B00000E58F004B09B000000400002060 +:108F400085B000000400002085B00000040000206F +:108F500085B000000400002085B00000040000205F +:108F600085B00000E58F004309B000000400002038 +:108F700085B00000E58F004509B00000E58F004690 +:108F800009B00000E58F004709B00000E58F0048F8 +:108F900009B000000400002085B00000040000209B +:108FA00085B000000400002085B00000E58F004C73 +:108FB00009B000000400002085B00000040000207B +:108FC00085B000000400002085B0000004000020EF +:108FD00085B00000F48E004C09B0000004000020B1 +:108FE00085B000000400002085B0000004000020CF +:108FF00085B000000400002085B000000B8F004702 +:1090000009B000000400002085B00000E88E004C8C +:1090100009B000000400002085B00000040000201A +:1090200085B00000A591004609B0000004000020B2 +:1090300085B000000400002085B000004991004286 +:1090400009B000000400002085B0000049910044F0 +:1090500009B000000400002085B0000004000020DA +:1090600085B000000400002085B00000040000204E +:1090700085B000000400002085B00000040000203E +:1090800085B000004991004B09B0000004000020A9 +:1090900085B000000400002085B00000040000201E +:1090A00085B000000400002085B00000040000200E +:1090B00085B000000400002085B0000004000020FE +:1090C00085B000004991004509B000004991004673 +:1090D00009B000001A8E004709B000001A8E00483F +:1090E00009B000000400002085B00000040000204A +:1090F00085B000000400002085B000004991004CBC +:1091000009B000000400002085B000000400002029 +:1091100085B000000400002085B00000E88E004209 +:1091200009B000005491004609B00000040000207E +:1091300085B000000400002085B00000E88E0046E5 +:1091400009B000000400002085B000000B8F00472C +:1091500009B000000400002085B0000054910046D2 +:1091600009B000000400002085B0000004000020C9 +:1091700085B000005491004609B0000004000020B2 +:1091800085B000000400002085B00000040000202D +:1091900085B000005891004309B000000400002091 +:1091A00085B000000400002085B00000040000200D +:1091B00085B000000400002085B000000B8F004740 +:1091C00009B000000400002085B000005891004361 +:1091D00009B000000400002085B000000400002059 +:1091E00085B000005891004D09B000000400002037 +:1091F00085B000000400002085B0000004000020BD +:1092000085B000000400002085B000006A91004392 +:1092100009B000000400002085B000000400002018 +:1092200085B000000400002085B00000040000208C +:1092300085B000000400002085B00000040000207C +:1092400085B000004791004A09B0000004000020EA +:1092500085B000000400002085B00000040000205C +:1092600085B000000400002085B00000040000204C +:1092700085B000000400002085B00000040000203C +:1092800085B000006A91004309B00000040000208E +:1092900085B000001A8E004709B000001A8E004801 +:1092A00009B000000400002085B000000400002088 +:1092B00085B000000400002085B000004791004AFE +:1092C00009B000000400002085B000000400002068 +:1092D00085B000000400002085B0000004000020DC +:1092E00085B000007C91004309B00000040000201C +:1092F00085B000000400002085B0000004000020BC +:1093000085B000000400002085B000000B8F0047EE +:1093100009B000000400002085B000007C910043EB +:1093200009B000000400002085B000000400002007 +:1093300085B000007C91004D09B0000004000020C1 +:1093400085B000000400002085B00000FF8D0042C1 +:1093500009B000000400002085B00000218E00420A +:1093600009B000000400002085B0000004000020C7 +:1093700085B000000400002085B00000040000203B +:1093800085B000000400002085B00000040000202B +:1093900085B000009B91004209B00000040000204D +:1093A00085B000000400002085B00000040000200B +:1093B00085B000000400002085B0000004000020FB +:1093C00085B000000400002085B0000004000020EB +:1093D00085B00000218E004609B00000FF8D0046D8 +:1093E00009B000001A8E004709B000001A8E00482C +:1093F00009B000000400002085B000000400002037 +:1094000085B000000400002085B000009B9100465C +:1094100009B000000400002085B000000400002016 +:1094200085B000000400002085B00000040000208A +:1094300085B000009D91004A09B0000004000020A2 +:1094400085B000000400002085B00000040000206A +:1094500085B000000400002085B000000B8F00479D +:1094600009B000000400002085B000009D91004A72 +:1094700009B000000400002085B0000004000020B6 +:1094800085B000005591004609B00000040000209E +:1094900085B000000400002085B00000040000201A +:1094A00085B000005591004609B00000040000207E +:1094B00085B000000400002085B0000004000020FA +:1094C00085B000000400002085B000000B8F00472D +:1094D00009B000000400002085B00000559100464E +:1094E00009B000000400002085B000000400002046 +:1094F00085B000005591004609B00000040000202E +:1095000085B000000400002085B0000004000020A9 +:1095100085B000000400002085B00000A391004247 +:1095200009B000000400002085B000000400002005 +:1095300085B000000400002085B000000400002079 +:1095400085B000000400002085B000000400002069 +:1095500085B000004791004A09B0000004000020D7 +:1095600085B000000400002085B000000400002049 +:1095700085B000000400002085B000000400002039 +:1095800085B000000400002085B000000400002029 +:1095900085B00000A391004609B00000040000203F +:1095A00085B000001A8E004709B000001A8E0048EE +:1095B00009B000000400002085B000000400002075 +:1095C00085B000000400002085B000004791004AEB +:1095D00009B000000400002085B000000400002055 +:1095E00085B000000400002085B00000248E004DEE +:1095F00009B000000400002085B000000400002035 +:1096000085B000000400002085B0000004000020A8 +:1096100085B000000400002085B000000400002098 +:1096200085B000000400002085B000000400002088 +:1096300085B000000400002085B000000400002078 +:1096400085B000000400002085B000000400002068 +:1096500085B000000400002085B000000400002058 +:1096600085B000000400002085B000000400002048 +:1096700085B000000400002085B00000248E004D5D +:1096800009B000001A8E004709B000001A8E004889 +:1096900009B000000400002085B000000400002094 +:1096A00085B000000400002085B000000400002008 +:1096B00085B000000400002085B0000007002E4B9C +:1096C0001990010025870004E6B10000D58A2242E6 +:1096D000197C00009A94003A81300100D58A00403C +:1096E00081B20000D58A2242197C0000FF1F000FC2 +:1096F0001E8C01000594004081320100E58A9C0F18 +:10970000803200000000005C1F800100008000101B +:1097100042C90100E58A2240E36D000000000045D7 +:1097200061B101004000001062DD0100E28AA84042 +:1097300081320000AF8200881CB00000A9842202A0 +:1097400080320000E68A424081320000000000447E +:109750009393010000001A0268970100A984004059 +:1097600005B0000005002E4B19900100258700046C +:10977000E6B100000000004087B00100000000409A +:109780008DB001000080000342C90100400000A12B +:1097900044C90100000000F0E0B10100DF950006BF +:1097A000074001000000000607D00100D4002E5C35 +:1097B0001F90010000000007F0B101000C800003C1 +:1097C00042C90100000000F0F0B1010000000040BB +:1097D00081B20100000000FE96B00100000000FE12 +:1097E00096C00100000000F0F0B101000000004050 +:1097F00081B20100000000FE96C00100000000FEE2 +:1098000096C00100000000F0F0B10100000000402F +:1098100081B20100000000FA96C00100000000FEC5 +:1098200096C001000030004B948801000000004603 +:1098300095F001000000004A96C001005E012E3440 +:10984000978401000200004BE4E501006401204020 +:10985000E1B101000900000786E4010000002EA725 +:1098600087C001001000001048C90100100000402E +:10987000F199010058010043F0C9010058010005A9 +:10988000E0C901000000004461B10100A00000A493 +:1098900062DD01000F8BA84081320000000000054E +:1098A00048B101001A0000409798010008002E40BE +:1098B00095B00100178B204B946C00000000004015 +:1098C000F1B10100148B004195C000001080001020 +:1098D00042C901001E8B2240E36D000000000044DD +:1098E00061B101004000001062DD01001A8BA84048 +:1098F00081320000AF8200881CB00000000000052B +:1099000048B101009A94004081300100EA8A004089 +:1099100081B200000C80000342C90100000000F881 +:1099200086B00100000000F888B00100238B44409D +:1099300081320000268BA24CFD7F0000278B004C5B +:10994000FD930000288B20F0566F0000000000F00F +:1099500056B3010000001C4081B2010000800010DD +:1099600044C9010064000040F19901007000000545 +:10997000F0C9010000000043F0B101000000004701 +:1099800061B101002000001062DD01002E8BA844AF +:10999000E0310000100000108CC80100008000467B +:1099A00044C9010040000040F19901006801000530 +:1099B000F0C9010064000043F0C901000000004745 +:1099C00061B101000000004662B10100368BA8447D +:1099D000E0310000AF8200881CB0000009000007E1 +:1099E00086E4010038002EA787C001008B002D05FA +:1099F00048B101003E8B2243E77D00000000004497 +:109A000045C10100418B2244E77D00000000004C6D +:109A100045C101000000004A19900100680120A220 +:109A2000E4B101008800004043990100458B230BFD +:109A3000E56D000000000041199001000080001059 +:109A400044C9010050000040F19901005801004351 +:109A5000F0C9010058010005E0C901000000004400 +:109A600061B101000000001062B101004A8BA84002 +:109A700081320000AF8200881CB000005C002E051F +:109A800048B101000080000342C90100000060F0FD +:109A900096B001009A94004181300100EA8A0040AA +:109AA00081B20000558BA249197C0000860000405D +:109AB00047990100598B0040E5B1000086002F490D +:109AC00019800100598BA2F2803200008B00004007 +:109AD0004799010000000042E79101005C8BA2461B +:109AE000197C0000A000004047990100608B0040F5 +:109AF000E5B10000A0002F4619800100608BA2F2A2 +:109B0000803200008B0000404799010000000041B6 +:109B1000E7910100A80000404399010034002DF0B6 +:109B200024B00100000000FB0CB00100000000FBAD +:109B300010B00100000000FB12B001000F0000F3A4 +:109B400016880100040000F314F401008B8B2640FA +:109B500081320000738B220A166C000058003D43CE +:109B600013E00100000000F882B00100040022F0C0 +:109B7000843000008795004081320100AF82008868 +:109B80001CB000000000000548B1010000000041C9 +:109B900013C00100728BA043136C00000000004052 +:109BA00013B00100688B004115D000008B8B220A96 +:109BB0008032000058003D4313E00100000000F82F +:109BC00082B00100040022F084300000879500403C +:109BD0008132010040002040E1B10100AF820088E5 +:109BE0001CB000000000000548B101008B8B224131 +:109BF000155000000000004111C001007F8BA04300 +:109C0000116C00000000004011B0010058003D43FD +:109C100011E00100000000F836B00100040022F05D +:109C2000003000000000005083B00100D9940047CC +:109C300061310100AF8200881CB000004292000533 +:109C4000483101000000004561B1010040000010F2 +:109C500062DD0100878BA84081320000AF8200885E +:109C60001CB000007B8B000548B10000370020408D +:109C7000E7B101000B95005181300100EA8A0040F4 +:109C800081B2000034002E41F5B101000011004006 +:109C9000E5990100938B00481990000034002E4193 +:109CA000F5B1010000110040E599010000800003BA +:109CB00042C90100000000F894B00100988B2245D1 +:109CC000237C0000B0002FF08CB00100000060F099 +:109CD0008CC00100900000404399010035002DF038 +:109CE0008CB0010058003E43E7E101009D8B224803 +:109CF000197C0000000000418DC001000000680ACE +:109D00008CC0010038002A4AE0B1010028000000A0 +:109D1000E0C901003C00201BE0B1010010800003FD +:109D200042C90100000000F838B00100000000F84E +:109D300026B00100040022F802300000AB8B2301A2 +:109D4000146C0000000000F880B00100000000F872 +:109D500082B001004C0020F0E4B10100440020403A +:109D6000E0B1010048002041E0B10100A8002D1041 +:109D700032B00100C39500F024300100B48BA2443E +:109D8000816C0000B28B2241197C00006E93004070 +:109D90003B300100D88BA2083C300000B48B00405F +:109DA00081B20000AB92004081320100D88BA20842 +:109DB0003C3000005000201CE0B101005400201392 +:109DC000E0B101004E002001E4B101004000200A92 +:109DD000E0B101000B95005F81300100EA8A00408C +:109DE00081B2000037000040479901004D9300F315 +:109DF00094300100938B224A80320000C08B0040D7 +:109E000081B2000037000040479901004D9300F3F4 +:109E10009430010058003E4397E001000000001B11 +:109E2000F0B101001F006000008C0100EA8A85117A +:109E3000803200000480000342C90100B0002FF00E +:109E40008CB00100000060F08CC001000B95005F39 +:109E500081300100EA8A004081B20000CA8B0049CB +:109E600019800000CF8B2241197C00006E930040C6 +:109E70003B300100D38BA2083C3000000B95005F03 +:109E800081300100EA8A004081B20000AB920040BC +:109E900081320100D38BA2083C3000000B95005F9B +:109EA00081300100EA8A004081B2000050002D108C +:109EB00032B0010054002DF038B001004E002DF0FA +:109EC00026B0010040002DF202B00100000000F0B9 +:109ED00014B00100300000108CC801000080004662 +:109EE00044C9010068012D4461B10100100068F20D +:109EF00080C8010000000008F0B101005801000511 +:109F0000E0C901000000000B37B001000000004074 +:109F100036D001005C012E4010C001000000000698 +:109F200080C001000000005281D00100A0940040D8 +:109F3000E43101002000004662DD0100E48BA8400E +:109F400023300000E592004081320100ED92004094 +:109F500081320100F28B82412340000020800010FA +:109F600042C90100EF8B2240E36D00000000004673 +:109F700061B101004000001062DD0100EC8BA840DF +:109F800081320000AF8200881CB000000000000594 +:109F900048B101000000001032B001000000004193 +:109FA00023B001000080001944C90100FA8B22414E +:109FB000197C0000F68BA3010C6C0000F78B0006E7 +:109FC00004B000000000000104B00100F98B200281 +:109FD000366C00000000001B04B00100FD8B000285 +:109FE000E0B10000FC8BA3010C6C0000FD8B0006AF +:109FF00004B000000000000104B00100000068028D +:10A0000016940100FFFF000B16D80100000068083D +:10A010003E9601000000001CF0B101000000004667 +:10A0200061B101002000001962DD0100028CA8135B +:10A03000E0310000398C22021450000044002D024F +:10A040000CD00100298CA20202500000108C225C6E +:10A050001F7C00002080000342C901000F8C2240B9 +:10A06000E36D00000000004761B1010040000010F6 +:10A0700062DD01000B8CA84081320000AF820088B5 +:10A080001CB000000000000548B1010044002D5C38 +:10A090001F80010048002DF038B001004C002DF069 +:10A0A00026B0010038002FF202B001002A8C2201F4 +:10A0B000146C00001D8C22461F7C0000000000462E +:10A0C0001F80010020002D0348B101001C8C22409C +:10A0D000E36D00000000004461B101004000001089 +:10A0E00062DD0100198CA84081320000AF82008837 +:10A0F0001CB0000038002F0548B10100000000F836 +:10A1000094B0010038002DF096B001000000004C22 +:10A11000E1C101002000000348C901000000224AFB +:10A12000F1B1010044000005F0C901000000004A3F +:10A13000F0B101000000004BE0B101000000004759 +:10A1400061B10100A00000A462DD0100268CA85CC2 +:10A150001F1000002A8C000548B10000000000021A +:10A1600038C00100348C220680320000000000500C +:10A1700033C00100328CA202366C000004008F0D47 +:10A1800042310000100000F810C801000000005C1F +:10A1900011800100F007004037980100E88B00A112 +:10A1A0001AB000000000000210C00100E88B00029D +:10A1B00036D000005000201CE0B1010054002013F4 +:10A1C000E0B101004E002001E4B101004000200A8E +:10A1D000E0B101003E8C005F01B0000037002D4669 +:10A1E00001B00100040000F380F401003D8CA043A5 +:10A1F000816C00000000005501B0010040002040CB +:10A20000E1B101000080001942C90100448C2240E4 +:10A21000E36D00000000004661B10100400000193C +:10A2200062DD0100418CA84081320000AF820088CD +:10A230001CB00000EA920040813201003080001022 +:10A2400042C901004B8C2240E36D00000000004435 +:10A2500061B101004000001062DD0100488CA8409F +:10A2600081320000AF8200881CB0000060012F0521 +:10A2700048B101000000000BE4B1010000000050F3 +:10A2800017F00100508C90F21640000000000041D1 +:10A2900017C001000000662017A40100320000A6CC +:10A2A0002AC00100000000F22A940100538C4548A6 +:10A2B0006131000000D0001E62DD0100588C284092 +:10A2C00005300000548C2248777D00005B8C0040F4 +:10A2D00081B200000000001562B10100648C2840CA +:10A2E00081320000588C004081B2000000001D0047 +:10A2F00092B00100618C2241197C000000800003B3 +:10A3000042C90100B09200F8003001005E8CA24109 +:10A310003B500000658C004900B00000FF07001EA4 +:10A32000008C0100B092004081320100658C004930 +:10A3300000B0000000001D4719800100688C225FFA +:10A34000016C0000ED95004081320100C5870000DE +:10A3500080B000006F8C225C1F7C00002080000316 +:10A3600042C901006F8C2240E36D000000000047ED +:10A3700061B101004000001062DD01006C8CA8405A +:10A3800081320000AF8200881CB000006F8C400555 +:10A3900048310000FFFF000794890100758C85CAD1 +:10A3A00094300000ED95185C1F0001000E00000FB6 +:10A3B0001E8C0100E686004081B200000B9518005B +:10A3C00080300100EA8A0047198000000000004048 +:10A3D00019800100EA8A2247197C0000AB920040F4 +:10A3E000813201007C8CA20880320000EA8A0040A1 +:10A3F00081B20000A09400400D3001009C0100409B +:10A4000045990100FFFF000B988801008B002D503B +:10A4100017F00100828C904C1640000000000041B3 +:10A4200017C00100848C2243E77D00000000004437 +:10A4300045C101000000662017A40100680100402A +:10A44000439901005C012EF280B0010002006240DD +:10A450007ECD01000000005781C0010000002E10D9 +:10A4600048B1010003000040F08D01000000000829 +:10A47000F0B1010058010005E0C9010000000044EE +:10A4800061B101000000001062B101008E8CA84093 +:10A4900081320000AF8200881CB00000000000057F +:10A4A00048B10100928C454861310000005000081D +:10A4B00062DD0100988C284005300000938C224812 +:10A4C000777D0000B0921D0800300100EA8A00404C +:10A4D00081B20000EA8A1D47198000003500004063 +:10A4E00047990100010063F384C801009D8CA043DB +:10A4F000856C00000000634085B00100A8000040AA +:10A500004399010037002FF024B00100010063F3EC +:10A5100082CC0100A88CA2419E060000EA8A224457 +:10A5200083700000360000404399010058003D430D +:10A53000E7E10100EA8A1FF0246C0000ED95004875 +:10A5400081300100C5872341836C0000C587004727 +:10A5500081B0000058003D4385E00100000000F894 +:10A5600036B00100000000F000B0010028000040FB +:10A5700083980100D994004761310100AF820088BF +:10A580001CB0000000002D0348B1010008002DF0B0 +:10A5900094B00100000000F88EB0010090002DF092 +:10A5A00014B001000000000548B10100998BA240E1 +:10A5B0008F7C0000B68C22478F7C0000998B00486E +:10A5C00019900000258D004081B2000036002D5DFD +:10A5D00005B4010037002DF380B00100000000F346 +:10A5E0008EB001005C003D4381E00100A8002DF029 +:10A5F00094B00100000000F024B001002000001021 +:10A6000086DC01004080000344C90100B191004A8A +:10A61000F031010036002F5C1F900100C48CA25065 +:10A620008F50000034002040E1B10100EA8A004070 +:10A6300081B200000000634181C00100C78CA043CB +:10A64000816C00000000634081B0010037002047AA +:10A65000E6B10100EA8A2247803200000400004788 +:10A660000CF401000000004F8F840100DC8C2247B5 +:10A670000C6C000058003D4381E00100DC8C1FF0B1 +:10A68000246C00000000005C1F80010000800010AE +:10A6900042C90100D58C2240E36D00000000004556 +:10A6A00061B101004000001062DD0100D28CA840C1 +:10A6B00081320000AF8200881CB00000D58C42407F +:10A6C00005300000000000449393010000001A5D73 +:10A6D00069930100DA8C23410D6C0000B78C0005F2 +:10A6E00048B10000ED95000548310100C5870048DC +:10A6F00081B00000EA8A22408F6C00000B95005F59 +:10A7000081300100EA8A004081B20000A2000040CE +:10A7100043990100000000F384B00100A6002D4918 +:10A7200019900100020000F280F40100B8002D40F1 +:10A7300081B20100000000F280C001000000004072 +:10A7400082F801001900004081980100EB8CA040C4 +:10A75000826C00002C01004081980100EB8CA3402A +:10A76000826C00000000004180B00100ED8C204CA4 +:10A77000856C00000000004185C00100860020407B +:10A78000E4B10100A2002042E6B10100EA8A0040E3 +:10A7900081B200009A94005081300100EA8A0040A2 +:10A7A00081B200000480000342C90100040022F0CD +:10A7B00080300000000000408DB00100DF950040B7 +:10A7C00087300100B0002F5C1F900100000060F096 +:10A7D00080C001000B95005F81300100EA8A0040D3 +:10A7E00081B200000400004081B20000EA8A2246E3 +:10A7F000197C0000A000004047990100010062F2AE +:10A8000096CC0100EA8AA640813200000B95004AEE +:10A8100081300100E094004695300100EA8A004052 +:10A8200081B20000EA8A2249197C000086000040BB +:10A8300047990100010062F280CC0100EA8AA6403B +:10A84000813200000B95004A81300100E0940047FE +:10A8500095300100EA8A004081B200004292004037 +:10A8600081320100EA8A005C1F900000EA8A004001 +:10A8700081B20000EA8A004081B20000BA000040C4 +:10A8800047990100010062F280C80100118D9040DB +:10A8900080320000FFFF624081980100A400004068 +:10A8A00047990100EA8A2240E56D0000EA8A0041EA +:10A8B000E5C100009A94004D81300100EA8A004011 +:10A8C00081B200005C00004047990100040022F0C2 +:10A8D0009630000000000040E1B10100008000035C +:10A8E00044C901000000004BE0B10100000000403D +:10A8F0008DB00100DF950040873001008B000040E3 +:10A9000047990100218D80F396300000000000403F +:10A91000E78101000000004719900100EA8A005C0D +:10A920001F900000340000404599010001000040E4 +:10A93000F599010000110040E5990100AB9200403B +:10A9400081320100368DA2088032000037000040BD +:10A9500047990100000000F382B00100000063513C +:10A9600083D001003400004047990100010063F3E7 +:10A9700084CC01002E8D9F42803200000000634293 +:10A9800085B001000000004503F001000000000157 +:10A9900000C00100308D375C613100000000001BF9 +:10A9A00062B10100318DA84B1910000000000000B9 +:10A9B00062B10100338DA840813200001A87174030 +:10A9C00081B200000080000342C9010090002DF018 +:10A9D00094B00100AC002DF030B0010035002DF036 +:10A9E00028B0010058003E43E7E1010001000018D3 +:10A9F000F0C901000000004AE0B101003800200069 +:10AA0000E0B101003C00201BE0B10100400020400B +:10AA1000E1B10100000000402BB00100EF940040C4 +:10AA20000D3001000000001816C00100458DA01473 +:10AA3000164400000000004117C001000E0000A2F3 +:10AA400044C9010000000018F8B10100B0002D1445 +:10AA5000F8B1010010500040879801004E8D224A45 +:10AA6000197C00000030004386C801000030000B54 +:10AA700016C801004E8DA440813200000000004144 +:10AA800017C0010001006E43869801002695003032 +:10AA900081300100528DA0411740000000000041AC +:10AAA00017C00100598D224A197C0000080000A23D +:10AAB00044C90100CC002DABF9B10100000000AB8E +:10AAC00017C00100588DA0F016440000000000419E +:10AAD00017C00100000064F082B001009000004047 +:10AAE000459901000000604131C00100BC000040F8 +:10AAF000439901005F8D060C80320000A00020F217 +:10AB0000E4B1010004000946191000009C01004056 +:10AB100045990100FFFF000B988801008B002D5024 +:10AB200017F00100648D904C1640000000000041B9 +:10AB300017C00100668D2243E77D0000000000443D +:10AB400045C101000000662017A401006801004013 +:10AB5000439901005C012EF280B0010002006240C6 +:10AB60007ECD01000000005781C0010000002E10C2 +:10AB700048B1010003000040F08D01000000000812 +:10AB8000F0B1010058010005E0C9010000000044D7 +:10AB900061B101000000001062B10100708DA84099 +:10ABA00081320000AF8200881CB000000000000568 +:10ABB00048B10100748D4548613100000050000823 +:10ABC00062DD0100758DA8400530000035001D4094 +:10ABD00047990100010063F384C801007B8DA04305 +:10ABE000856C00000000634085B001003700004024 +:10ABF00047990100010063F382CC01008B00004003 +:10AC00004799010000000045E79101000B95005FA6 +:10AC100081300100EA8A004081B200003700004024 +:10AC2000479901004D9300F394300100258D224A8D +:10AC300080320000C08B004081B20000370000402D +:10AC4000479901004D9300F394300100908B224A04 +:10AC500080320000C08B004081B20000360000400E +:10AC600043990100000000FB12B001000F0000F347 +:10AC700090880100040000F30CF40100BA8B220656 +:10AC8000906C00005C003D4313E00100A8002DF033 +:10AC900094B0010037002FF024B0010036002A5094 +:10ACA000E7D101000000634113C00100958DA0436E +:10ACB000136C000000000040E7B10100AF910010EC +:10ACC00086300100AF8200881CB00000978D4205DD +:10ACD000483100000000004493930100BA8B1A5DD4 +:10ACE0006993000036002D1086B001005C003D43E2 +:10ACF000E7E10100A8002DF094B0010035002FF02D +:10AD000024B0010001006BFB84C80100A28DA043A8 +:10AD1000856C000035002040E7B1010000000040D4 +:10AD200081B20100010063F312C80100A58DA043A8 +:10AD3000136C000000000040E7B1010040800003F8 +:10AD400044C90100B191004AF0310100AF8200888E +:10AD50001CB00000A88D42054831000000000044EE +:10AD60009393010000001A5D6993010037000040D1 +:10AD700047990100110063F382CC0100A18C2241AC +:10AD80009E060000350000404399010058003D43F5 +:10AD9000E7E10100000000F836B00100AB8C00F0E4 +:10ADA00000B000005E012D0548B10100B38D65F2D1 +:10ADB0001230000000993F4213F00100B88D224785 +:10ADC000E77D0000F58275881CB00000B28D004060 +:10ADD00081B2000000000047E791010000007542C9 +:10ADE000199001007500004061990100BA8DA8B169 +:10ADF0000C3000003694001094300100AF820088BF +:10AE00001CB000005E012E0548B10100C0A83D46FF +:10AE10000DE001000000004097B00100C48D224009 +:10AE2000E16D00000400024197400000C18D005018 +:10AE300043C10000D08D224B803200000000624BE5 +:10AE4000129401000900000796E40100000000A729 +:10AE500097C001003000001094C801000080004A33 +:10AE60004499010000000042F1B101005E01004B75 +:10AE7000F0C901005E010005E0C9010000000044C6 +:10AE800061B101002000004A62DD0100CE8DA840C2 +:10AE9000813200000080001044C901000000005011 +:10AEA000F1B101000400000996E40100000068A867 +:10AEB00097C00100D4000005E0C901000000004473 +:10AEC00061B101000000001062B10100D68DA84000 +:10AED00081320000AF8200881CB0000000993F4220 +:10AEE00013F00100DA8D6540813200003F0000F36D +:10AEF0009688010000000040E7B101000000755590 +:10AF000061B101000000000662B10100DE8DA840C1 +:10AF100081320000E38D224B803200000000004BA4 +:10AF200062B10100E18DA84081320000000000976D +:10AF300013B001000000009697B00100E98D2009D0 +:10AF4000966C0000E98D1F0996240000F5820088A8 +:10AF50001CB00000E48D004081B200009A940057BC +:10AF600081300100D58A000548B100002E00004064 +:10AF700043990100EF8D22F3803200009A94004241 +:10AF8000813001001A87004081B200000B95005209 +:10AF900081300100D58A0042198000009A94003A5D +:10AFA000813001000B95005281300100D58A0040AC +:10AFB00081B200000000004005B00100AD930040E8 +:10AFC00095300100D58A2240956C0000FA8DA24090 +:10AFD0001F7C0000B0920040813201001A870040BF +:10AFE00081B200000480000342C90100000000F2A9 +:10AFF00002B0010058930052953001005F93004B5E +:10B0000002B000001A87004081B200009495004011 +:10B0100095300100068EA20880320000068EA2162E +:10B02000803200001A872242197C00000000004B89 +:10B03000199001009A94003A813001001A8700406B +:10B0400081B20000002300A616B00100098E831E05 +:10B05000803200000008000B16DC01000000000038 +:10B060002AC00100E3940008803001000D8E005ECC +:10B07000179000000495004361310100BD9100402C +:10B080008D300100EB9400071614010000800010C1 +:10B0900042C90100158E2240E36D0000000000430C +:10B0A00061B101004000001062DD0100128EA84075 +:10B0B00081320000AF8200881CB000008C94005EDA +:10B0C00005100100B092004081320100198E220962 +:10B0D000803000000B95004013300100DA8A000533 +:10B0E00048B10000DD93004081320100D58A004064 +:10B0F00081B200000000004A1F900100208E224310 +:10B100003D7C000000000044199001000000004355 +:10B110003D800100218E00421990000014002D4551 +:10B120001F9001007D8E831E803200007D8E0044C2 +:10B1300019900000A292004081320100358EA208D1 +:10B1400080320000358EA21680320000318EA2427D +:10B15000197C00000082000204DC0100A09800407D +:10B160004799010030050041893001002E8EA2412F +:10B17000197C0000B0920040813201001A87004023 +:10B1800081B2000058930015943001005F93004B8A +:10B1900002B000001A87004081B20000DD93004039 +:10B1A000813201000000004B199001009A94003A8E +:10B1B000813001001A87004081B20000388E22429F +:10B1C000197C0000DD93004081320100398E00407F +:10B1D00081B20000AD93004081320100658E2241B2 +:10B1E000197C0000C000001598C80100658EA00BF6 +:10B1F000996C00003000001080C801000080004001 +:10B200004499010000000050F1B10100000000036A +:10B21000F0B101000000004261B1010000000040F7 +:10B2200062B10100418EA800E0310000AF820088C9 +:10B230001CB000000000000548B10100C00000156E +:10B2400098C8010030002E0B99D0010000006A5010 +:10B2500099C00100C000620180CC01000C80000395 +:10B2600042C901002D002DF022B001000000004C69 +:10B2700080C001000000005C23800100D4003F4139 +:10B28000E7E101000B000011E4F501002F00204769 +:10B29000E7B50100528E230B816C00000000004FC7 +:10B2A000E59101000000000880B001000000000BE3 +:10B2B00003B001000000001502D00100E39400007B +:10B2C0002A4001000000004361B10100400000106D +:10B2D00062DD0100578EA84081320000AF820088F5 +:10B2E0001CB00000B092000548310100C000000110 +:10B2F00080CE0100638E2611003000001000000097 +:10B300002AC801000000000880B001000000000110 +:10B3100080C00100C00000409998010000000001B9 +:10B3200098D00100E394004C02300100C0000040BE +:10B33000039801006A8E004081B2000030002F089F +:10B3400080B00100C0000015F4C90100C000000178 +:10B35000E4CD0100C000004003980100E394000028 +:10B360002A4001006F8E22441F7C0000AC002F4059 +:10B3700013B0010000000001E0C10100B000004076 +:10B3800047990100708E0001E0D10000BD9100409E +:10B390008D300100806300A616B00100EB94000719 +:10B3A000161401000080001042C90100788E22406E +:10B3B000E36D00000000004361B101004000001097 +:10B3C00062DD0100758EA84081320000AF820088E6 +:10B3D0001CB000008C94005E051001007B8E2209D9 +:10B3E000803000000B95004081320100D58A0005B5 +:10B3F00048B100007D8E004A1F9000000000000050 +:10B4000010B0010024002D1510C0010028002DF0FF +:10B4100016B0010022002DF026B0010014002FF21A +:10B420000CB0010000000001E0D10100000000109C +:10B4300032B001000000000B1BB0010004001F151A +:10B440001A5000000000004023B00100000000017D +:10B450002AB001004B94004035B000002F0020407E +:10B46000E7B10100C18EA2451F7C00002400200B23 +:10B47000E0B1010028002013E0B101002200200605 +:10B48000E4B10100978E225C1F7C00000000005C8C +:10B490001F8001003080001042C90100978E2240B9 +:10B4A000E36D00000000004761B1010040000010A2 +:10B4B00062DD0100938EA84081320000AF820088D7 +:10B4C0001CB000000000000548B101000080001918 +:10B4D00042C90100BA8E2240E36D0000A88E2242CC +:10B4E000197C000005940040813201005792004011 +:10B4F00081320100B58E224B8032000000000043F3 +:10B5000061B101004000001062DD01009E8EA84084 +:10B5100081320000AF8200881CB00000A48E22415E +:10B52000197C0000C692004011300100A58E000574 +:10B5300048B10000B092004081320100A78E22097C +:10B54000803000000B95004081320100F9820040FC +:10B5500005B0000005940040813201005392004084 +:10B56000813201000000004361B101004000001081 +:10B5700062DD0100AB8EA84081320000AF820088FE +:10B580001CB00000B18E2241197C0000C692004020 +:10B5900011300100B28E000548B10000B0920040A9 +:10B5A00081320100B48E2209803000000B950040EA +:10B5B00081320100F982004005B000000000004324 +:10B5C00061B101004000001062DD0100B68EA840AC +:10B5D00081320000AF8200881CB00000000000052E +:10B5E00048B10100BD8E2241197C0000C692004086 +:10B5F00011300100BE8E000548B10000B09200403D +:10B6000081320100C08E2209803000000B9500407D +:10B6100013300100DA8A004005B0000000800019F4 +:10B6200042C90100C88E2240E36D000000000043C3 +:10B6300061B101004000001062DD0100C48EA8402D +:10B6400081320000AF8200881CB0000000000005BD +:10B6500048B101000000004005B00100CC8E22413D +:10B66000197C0000C692004011300100CD8E00050B +:10B6700048B10000B09200408132010008002D0A5C +:10B6800084B00100000000F082B0010014002040EE +:10B69000E1B10100D28E031E80320000D38E004142 +:10B6A00087B000002100004087980100CE93004041 +:10B6B000813201000000005C1F900100D78E22093A +:10B6C000803000000B95004013300100DA8E2244D8 +:10B6D000197C00000B95004F8130010000000044F0 +:10B6E00019800100D58AA24A1F7C0000DA8A004036 +:10B6F00081B20000BA002040E5B10100E08E9C1745 +:10B7000080320000CC000040439901009D9500402C +:10B71000813201004495004013300100C000004018 +:10B7200043990100C4002DF082B00100789500F02B +:10B7300084300100B092004081320100DA8A22098F +:10B74000803000000B95004013300100DA8A004081 +:10B7500081B200002E00004043990100EC8E22408F +:10B76000E76D00003200004043990100F48EA240D2 +:10B77000E56D00009A930040813201002400200B07 +:10B78000E0B1010028002013E0B1010022002006F2 +:10B79000E4B101001400200AE0B10100DA8A2209B4 +:10B7A000803000000B95004013300100DA8A004021 +:10B7B00081B200009A93004081320100539300400F +:10B7C00081320100028F2241197C00000000000B31 +:10B7D00099B0010004001F1598500000028F20014D +:10B7E000986C00007000000348C9010000002E465C +:10B7F0001F90010000000050F1B1010000000003A3 +:10B80000F0B101000000004261B10100A00000A4FD +:10B8100062DD0100FF8EA800E0310000000000059D +:10B8200048B10100AC002F0010B001000000000181 +:10B83000E0C1010014002F1510C001000000000A33 +:10B8400080B001000000600180D0010000000047CE +:10B8500019900100848E2209803200000B950009A6 +:10B8600080300100848E004013B00000008000038F +:10B8700042C90100000000F082B001001300004046 +:10B88000879801000000004C43C10100CE9300F0F6 +:10B8900084300100D58A005C1F9000002C002040FD +:10B8A000E7B101002D002040E7B10100D58A004238 +:10B8B00019800000C093004081320100E0940048EC +:10B8C000953001000000004561B10100400000100A +:10B8D00062DD0100178FA84013300000AF8200889E +:10B8E0001CB000001D8F000548B100001C8F0040F7 +:10B8F00013B000000000000012B00100080000407A +:10B900004399010014002DF082B00100040022F0E0 +:10B91000843000001300004087980100CE9300405F +:10B92000813201000000005C1F900100358F00098A +:10B9300000B00000D58A8742191000008B002F4705 +:10B9400019800100D58A0040E79100002F000040D7 +:10B9500047990100338F2247E77D00003492004071 +:10B96000E7310100338F2200803200002E8FA24089 +:10B970001F7C0000B092004081320100338F0040F4 +:10B9800081B20000300000404399010032002DF2E6 +:10B9900094B00100589300F2023001005F93004B15 +:10B9A00002B000000000000548B10100348F0040E3 +:10B9B00001B000000000004005B001003A8F2200F5 +:10B9C00080320000398FA242197C0000AD93004004 +:10B9D000813201003A8F004081B20000DD930040C7 +:10B9E00081320100C68F225C1F7C00000000005CD9 +:10B9F0001F8001000080001042C90100428F2240D8 +:10BA0000E36D00000000004561B10100400000103E +:10BA100062DD01003F8FA84081320000AF820088C4 +:10BA20001CB00000C68F000548B10000A292004083 +:10BA300081320100498FA20880320000498FA2168E +:10BA4000803200009A94004D813001000082000293 +:10BA500004DC01001A87004081B20000740000403D +:10BA600043990100000000F882B00100000000F0DE +:10BA700084B001000000004196B00100578F2242BF +:10BA8000961400000080001044C901006400684062 +:10BA90009798010000000041F0B101000000004251 +:10BAA000F0B1010070000005E0C901000000004590 +:10BAB00061B101002000001062DD0100548FA84038 +:10BAC000813200000000005C1F9001000000004572 +:10BAD00061B101004000001062DD0100588FA85CD8 +:10BAE0001F000000AF8200881CB000005E012D0521 +:10BAF00048B101005C8F65F21230000000993F42AE +:10BB000013F00100618F2247E77D0000F582758800 +:10BB10001CB000005B8F004081B2000000000047B5 +:10BB2000E79101000400750996E40100008000100F +:10BB300044C9010000000044F1B10100000068A800 +:10BB400097C0010000000003E0B101000080000385 +:10BB5000449901000000004461B1010000000010A0 +:10BB600062B10100698FA840E1310000AF82008816 +:10BB70001CB0000000993F4213F001006D8F650575 +:10BB8000483100003F0000F39688010000000040AB +:10BB9000E7B101000000754081B20100758F224BB2 +:10BBA000803200000000005561B101000000004B30 +:10BBB00062B10100738FA8408132000000000007CD +:10BBC00016B001000062000B16DC01003492004048 +:10BBD000813201008D8F220080320000E393005FEC +:10BBE00001100100778F2240956C0000008000104A +:10BBF00044C9010000000050F1B101000000000341 +:10BC0000F0B101000000004261B10100000000102D +:10BC100062B101007F8FA800E0310000AF82008890 +:10BC20001CB000000000000548B1010004800003C2 +:10BC300042C90100000000F202B001005893005216 +:10BC400095300100B092004081320100778F22418F +:10BC5000975000000C80000342C90100000000F072 +:10BC600000B001000000005C018001005F93004B08 +:10BC700002B00000778F000548B10000EB9400404F +:10BC8000033001001780000344C9010000F0000CDC +:10BC9000968801000000634C97F0010010800003BB +:10BCA00044C90100000000ABE1B101008C94005ECA +:10BCB00005100100030000071AF401000700000747 +:10BCC0001688010000B5000D46C90100978F30406D +:10BCD000813200000000000BE681010000B7000D7A +:10BCE00046C901000000000BE68101001000100FA2 +:10BCF00094F401009304005F95040100399300401F +:10BD000081320100A18F2250FD7F00009F8F4640AD +:10BD10008132000000001E4131D3010000002E05D9 +:10BD200048B1010000000040E1B101000000004006 +:10BD30000FB001009B920041813001001A87004042 +:10BD400081B20000A292004081320100B38FA208AC +:10BD500080320000B38FA216803200000082000201 +:10BD600004DC01000000004503F0010000000001B8 +:10BD700000C00100AC8F375C613100000000001B87 +:10BD800062B10100B08F284081320000AD8F0040C9 +:10BD900081B200000000000062B10100B08FA84035 +:10BDA000813200001A87174081B2000074002240DF +:10BDB000F1B1010000000040E1B10100E094004A4F +:10BDC00095300100C093005C1F100100498F0040B6 +:10BDD00081B200002F00004047990100C48F224724 +:10BDE000E77D000034920040E7310100C48F22005B +:10BDF00080320000BF8FA2401F7C0000B092004044 +:10BE000081320100C48F004081B200003000004048 +:10BE10004399010032002DF294B00100589300F2D2 +:10BE2000023001005F93004B02B0000000000005EB +:10BE300048B10100E094004895300100C093005CD7 +:10BE40001F100100C98F8742191000008B002F4777 +:10BE50001980010000000040E79101000B950042AD +:10BE600081300100D58A004081B20000C0930040BB +:10BE700081320100D58A005C1F900000BA0020408A +:10BE8000E5B101004495004081320100C00000404E +:10BE900043990100C4002DF082B00100789500F0B4 +:10BEA00084300100B0920040813201000B950045C2 +:10BEB00081300100D58A2242197C00009A94003A10 +:10BEC00081300100D58A004081B2000004000040AA +:10BED00081B20000A292004081320100DE8FA208F0 +:10BEE00080320000DE8FA216803200009A94004754 +:10BEF000803001000082000204DC01001A8700404B +:10BF000081B200001080000344C9010000E100A6D6 +:10BF100084B0010000000040F1B1010000000040C9 +:10BF2000F1B1010000006007849401008C94005E70 +:10BF300005100100D58A004081B200008A0000404F +:10BF400047990100B0920041E7410100DA8A0040C0 +:10BF500081B200009A930040813201005393004067 +:10BF600081320100000000012CB00100000000152A +:10BF700010B001000000000010C0010004001F0A02 +:10BF80002C5000000000001032B001001E95000689 +:10BF900004300100F68FA2481F7C0000F48F844813 +:10BFA0001F100000AC00004047990100F68F000A06 +:10BFB000E0C100000000000A02B00100BD910001D4 +:10BFC0008C3001000000004361B10100400000100E +:10BFD00062DD0100F78FA84081320000AF82008847 +:10BFE0001CB000000000000548B101000000000284 +:10BFF00010C0010004902202145000000894004573 +:10C000001F000100EE8F225C1F7C00000000004733 +:10C0100061B101004000001062DD01000090A85CE9 +:10C020001F000000AF8200881CB00000EE8F0005EA +:10C0300048B100000000000B1BB0010008002D40BB +:10C0400085B00100000000F082B001000000004057 +:10C0500005B00100CE93004187300100000000458B +:10C0600061B101004000001062DD01000A90A840AB +:10C0700081320000AF8200881CB000000000000583 +:10C0800048B1010010902209803000000B9500405B +:10C090001330010014902244197C00000B95004FCE +:10C0A000813001001490A2471F7C00000000004472 +:10C0B00019800100FF070008008C01002290224A2D +:10C0C0001F7C00001A90A21602300000B0920040BF +:10C0D000813201002F002040E7B10100D58A0040E5 +:10C0E00081B200002D002D082AB001001E902242CE +:10C0F000197C0000DD930040813201001F90004058 +:10C1000081B20000AD9300408132010030002E006A +:10C110002AD0010032002A15E4B10100D58A0016A8 +:10C12000E4B1000035902216023000000000000843 +:10C130002AB0010094950040953001002790A2405C +:10C14000116C0000369022402D6C0000AC000040C5 +:10C1500047990100B0002B01E0C10100002B00A6AF +:10C1600016B0010000000001E0D10100E3940008D6 +:10C17000803001002E90005E17900000049500436F +:10C18000613101000000004361B101004000001076 +:10C1900062DD01002F90A84081320000AF8200884C +:10C1A0001CB000000000000548B10100EB9400073E +:10C1B000161401008C94005E05100100B09200403E +:10C1C000813201002F002040E7B10100DA8A0040EF +:10C1D00081B200000000000B1BB0010004001F151D +:10C1E0001A500000439020161A6C000070000003E3 +:10C1F00048C9010000002250F1B101000000000315 +:10C20000F0B1010000000000E0B1010000000042B8 +:10C2100061B10100A00000A462DD01004090A846C9 +:10C220001F1000000000000548B1010000000000E0 +:10C2300010B001000000001510C001000000000A4D +:10C240002AB001000000000A2CD00100AC002F40F1 +:10C2500023B001004A9084451F1000004B90000A53 +:10C26000E0C100000000000A02B001004B94004051 +:10C2700035B000000080001942C9010053902240EF +:10C28000E36D00000000004361B1010040000010B8 +:10C2900062DD01004F90A84081320000AF8200882B +:10C2A0001CB000000000000548B101006390A2022C +:10C2B0001A500000649022402D6C00000080001095 +:10C2C00044C9010000000050F1B10100000000036A +:10C2D000F0B10100FF070008E08D010000000042FE +:10C2E00061B101000000001062B101005A90A84045 +:10C2F00081320000AF8200881CB000000000000501 +:10C3000048B101002F002047E7B501000C80000371 +:10C3100042C90100100000F010C80100F007004001 +:10C320001B9801006490005C118000000000000276 +:10C3300010C00100C69200401F000100000000056F +:10C3400048B101006890230D2C6C000000000040F3 +:10C350001F900100719022461F7C000000000046E3 +:10C360001F8001007080000342C9010071902240CB +:10C37000E36D00000000004261B1010040000010C8 +:10C3800062DD01006D90A84081320000AF8200881C +:10C390001CB000000000000548B1010008002D405D +:10C3A00085B00100000000F082B0010000000040F4 +:10C3B00005B00100CE930041873001000000004528 +:10C3C00061B101004000001062DD01007690A840DC +:10C3D00081320000AF8200881CB000000000000520 +:10C3E00048B101007C902209803000000B9500408C +:10C3F0001330010080902244197C00000B95004FFF +:10C40000813001008090A2471F7C000000000044A2 +:10C4100019800100FF070008008C01009590224A56 +:10C420001F7C00008690A21602300000B0920040EF +:10C43000813201002F002040E7B10100D58A004081 +:10C4400081B200002D002D082AB0010091902242F7 +:10C45000197C00008A90A2F384300000000000A53F +:10C4600085B001000000004185D00100D4003E41AC +:10C4700085E001008E9022401F7C00000000005AE1 +:10C48000119001000B000008E4F50100DD9300406D +:10C49000813201009290004081B20000AD930040D3 +:10C4A0008132010030002E002AD0010032002A150E +:10C4B000E4B10100D58A0016E4B100009890A216FC +:10C4C00002300000B092004081320100E79000404D +:10C4D00081B200002D002D082AB00100A69022474D +:10C4E0001F7C0000A2902242197C00009D90A2F3C4 +:10C4F00084300000000000A585B00100000000416C +:10C5000085D00100D4003E4185E00100A190224089 +:10C510001F7C00000000005A119001000B00000871 +:10C52000E4F5010058012D002AD0010060012DF032 +:10C5300010B00100000000F02CB00100358E00406A +:10C5400081B200009495004195300100AE90A208A0 +:10C5500080320000AE90A216803200000000004140 +:10C5600097B00100AC90230D026C00000000004168 +:10C5700097C001005F93004B02B00000E7900005F8 +:10C5800048B10000AC002F0114B00100B0002B0135 +:10C59000E0C10100002B00A616B001000000000160 +:10C5A000E0D10100BE90230D026C0000008000105D +:10C5B00044C9010000000050F1B101000000000377 +:10C5C000F0B101000000004261B101000000001064 +:10C5D00062B10100B790A800E0310000AF8200888E +:10C5E0001CB000000000000548B101000C800003F1 +:10C5F00042C90100100000F022C801000000005CE8 +:10C60000238001000000000184B00100C190230DCF +:10C61000026C00000000000D02B0010000000008E4 +:10C6200080B00100C69022401B6C0000E394000122 +:10C6300084500100CE902240856C00000000000173 +:10C6400080C001001080001046C901000000004FAA +:10C650004381010000000042F0B1010020000040D1 +:10C66000F0C9010000000016F0B101000000004315 +:10C6700061B10100A00000A162DD0100CC90A81111 +:10C68000E0310000DD90005E17900000D190230D96 +:10C69000026C00000000000D02B00100000000016B +:10C6A00084D00100D69022401B6C0000049500430A +:10C6B00061310100DD902240856C00000000000126 +:10C6C00012C001001080001046C901000000004F98 +:10C6D0004381010000000042F0B1010000000009A8 +:10C6E000F0B1010000000018F0B10100A00000A1AD +:10C6F00062DD0100DB90A811E03100000000004382 +:10C7000061B101004000001062DD0100DE90A80A66 +:10C7100002300000AF8200881CB00000B09200051B +:10C7200048310100E590230D026C0000FF07001165 +:10C73000008C0100B092004081320100EB940007B0 +:10C74000161401008C94005E051001002F0020409B +:10C75000E7B10100DA8A004081B2000000800003E6 +:10C7600042C90100000000F882B00100000000F89A +:10C770008CB00100000000F08EB0010097930040E3 +:10C78000133001000000004085B00100CE9300414D +:10C790008730010053930040813201000080001077 +:10C7A00042C90100F8902240E36D000000000045FE +:10C7B00061B101004000001062DD0100F490A8406A +:10C7C00081320000AF8200881CB00000000000052C +:10C7D00048B10100FA902209803000000B9500401A +:10C7E000133001000000000B1BB001000000001519 +:10C7F0001AD001000191A241197C000094950040DB +:10C80000953001000000001680B201000A9127084F +:10C8100080320000279000002AC00000949500415B +:10C82000953001000000001680B201000591270834 +:10C8300080320000AE9000002AC0000000000041DD +:10C8400097B001000891230D026C00000000004128 +:10C8500097C001005F93004B02B00000000000058C +:10C8600048B10100D58A2242197C00009A94003A0E +:10C8700081300100D58A004081B200000E91004A4B +:10C880001F900000D8920000103001000000001539 +:10C8900010C001000000001032B001001E9500061B +:10C8A000043001001791A2441F7C00000000000B1F +:10C8B0001BB001000000000A2CD001000000000A9B +:10C8C00002B00100BD9100018C3001000080001910 +:10C8D00042C901001E912240E36D000000000043A8 +:10C8E00061B101004000001062DD01001A91A84012 +:10C8F00081320000AF8200881CB0000000000005FB +:10C9000048B101000000000210C00100279122027E +:10C9100014500000089400451F0001001091225C93 +:10C920001F7C00000000004761B1010040000010C2 +:10C9300062DD01002391A85C1F000000AF82008827 +:10C940001CB000001091000548B1000008002D4007 +:10C9500085B00100000000F082B00100000000403E +:10C9600005B00100CE930041873001000000004572 +:10C9700061B101004000001062DD01002C91A8406F +:10C9800081320000AF8200881CB00000000000056A +:10C9900048B1010032912209803000000B9500401F +:10C9A0001330010035912244197C00000B95004F93 +:10C9B000813001000000004419800100FF070008D9 +:10C9C000008C01004391224A1F7C00003B91A2167B +:10C9D00002300000B0920040813201002F00204060 +:10C9E000E7B10100D58A004081B200002D002D087A +:10C9F0002AB001003F912242197C0000DD930040E3 +:10CA0000813201004091004081B20000AD930040AE +:10CA10008132010030002E002AD0010032002A1598 +:10CA2000E4B10100D58A0016E4B100002390A216FB +:10CA300002300000B0920040813201002F002040FF +:10CA4000E7B10100DA8A004081B20000D892004AC2 +:10CA50001F1001003890001032B000008A00204002 +:10CA6000E7B101004D91A241197C0000B092004055 +:10CA7000813201005091004081B2000058930015AE +:10CA8000943001005F93004B02B0000000000005ED +:10CA900048B1010052912242197C00009A94003A58 +:10CAA000813001000B95004581300100D58A00409E +:10CAB00081B20000F48E00451F9000009A93004060 +:10CAC000813201005393004081320100389000010F +:10CAD0002CB00000A2920040813201006591A208B2 +:10CAE000803200006591A2168032000000820002B0 +:10CAF00004DC01000000004503F00100000000011B +:10CB000000C001005E91375C613100000000001B35 +:10CB100062B1010062912840813200005F910040C3 +:10CB200081B200000000000062B101006291A840E3 +:10CB3000813200001A87174081B200005801200896 +:10CB4000E0B1010060012016E0B101009A930047B6 +:10CB50001F10010053930040813201003890000102 +:10CB60002CB00000A29200471F1001007891A2088B +:10CB7000803200007891A216803200007491A242A7 +:10CB8000197C00000082000204DC0100A098004033 +:10CB90004799010030050041893001005893001584 +:10CBA000943001005F93004B02B000001A870040F0 +:10CBB00081B20000DD930040813201000000004B93 +:10CBC000199001009A94003A813001001A870040C0 +:10CBD00081B2000058012008E0B101006001201678 +:10CBE000E0B10100D89200103230010038900040CE +:10CBF00013B00000A2920040813201008991A20886 +:10CC0000803200008991A21680320000008200026A +:10CC100004DC01000000004503F0010000000001F9 +:10CC200000C001008291375C613100000000001BF0 +:10CC300062B101008691284081320000839100405A +:10CC400081B200000000000062B101008691A8409E +:10CC5000813200001A87174081B200000080000373 +:10CC600042C90100000000F882B00100000000F895 +:10CC70008CB00100000000F08EB0010097930040DE +:10CC8000133001000000004085B00100CE93004148 +:10CC90008730010053930040813201000080001072 +:10CCA00042C9010098912240E36D00000000004558 +:10CCB00061B101004000001062DD01009491A840C4 +:10CCC00081320000AF8200881CB000000000000527 +:10CCD00048B10100358E2209803000000B950040DC +:10CCE00013300100358E004081B2000014002D4544 +:10CCF0001F9001007D8E004419900000A091A24178 +:10CD0000197C00000000004A1F900100E88F0040DD +:10CD100081B200009A93004A1F1001005393004013 +:10CD200081320100389000012CB00000D892004000 +:10CD3000813201003890001032B00000F48E0045BE +:10CD40001F9000000000004137C3010000000041B7 +:10CD500033C301003600000102CC01000000D240C4 +:10CD600081B20000AC9185178032000000009F481E +:10CD700003D00000AE919C178032000000009F4C51 +:10CD800003D000000000800134C301004080000394 +:10CD900044C901000000004AF0B101000000004059 +:10CDA000F1B1010000000012F0B10100B4920041A5 +:10CDB000E13101000080004344C90100100000403F +:10CDC000F199010000000048F0B1010000000049A5 +:10CDD000F0B1010040000003E0C90100000000457F +:10CDE00061B101000000004362B101000000A840F1 +:10CDF00081B20000BA91004081B20000BA00204028 +:10CE0000E5B10100B0002F018CD001000000004608 +:10CE1000E0C10100AC002F4013B00100CC002D0197 +:10CE2000E0C10100C4919C17803200009D95004034 +:10CE300081320100C6912247197C00000000005F8A +:10CE4000139001004495004719100100C0002D44C3 +:10CE50001F900100C4002DF082B00100789500F011 +:10CE600084B0000090002D0548B10100DB91A24B79 +:10CE70001F7C00002E92A24C1F7C0000DB911F1C27 +:10CE8000E06D0000DE91A20180320000A8002D4676 +:10CE90008FB00100D4911F1CE06D0000B400004071 +:10CEA00043990100D69122F03A6C00002B921FF0BA +:10CEB0003A6C00000000A24080B200000000804FE9 +:10CEC0008FB001008A000040439901002C9220425B +:10CED000E76D0000DA9122408032000000008059A6 +:10CEE0008FB00100000080588FB00100DD9122401A +:10CEF000803200000000805C8FB001000000805B89 +:10CF00008FB00100AC00004043990100B0002DF04B +:10CF100084B00100E291A242246C0000EB9123F066 +:10CF2000026C0000E891A2F0803200002D92A24233 +:10CF3000246C00002D92A241036C0000E791A240F6 +:10CF400080320000000080518FB00100000080524C +:10CF50008FB001002D921F12845000002D92A0016D +:10CF6000846C0000DB91004081B200008B00004027 +:10CF7000439901001692A246E77D0000140000408C +:10CF800043990100089222F014300000F491200A25 +:10CF9000026C00000592031E80320000F391A24053 +:10CFA00080320000000080448FB001000000804902 +:10CFB0008FB00100F991220A026C0000FC91A2419D +:10CFC000197C0000F891A2408032000000008055DA +:10CFD0008FB00100000080568FB00100FB91A2408D +:10CFE00080320000000080438FB0010000008048C4 +:10CFF0008FB001000000000182B001000000000AB3 +:10D0000082D0010002922091836C00000192A24024 +:10D0100080320000260080408F9801002700804069 +:10D020008F9801000492A240803200001F008040CF +:10D030008F980100200080408F9801000792A24045 +:10D0400080320000220080408F9801002300804041 +:10D050008F98010088002D448FB001001192A241E9 +:10D06000197C00000E92A2433D7C00000E92A2F2B9 +:10D07000026C00000000A24080B200000000804965 +:10D080008FB001001092A240803200000000804367 +:10D090008FB00100000080488FB001000E92A09177 +:10D0A000036C00000C9222433D7C00001592A240CC +:10D0B00080320000280080408F98010029008040C5 +:10D0C0008F98010014000040439901001F92A2F0C4 +:10D0D0001430000088002D448FB001001C92A2F291 +:10D0E000026C00000000A24080B2000000008049F5 +:10D0F0008FB001000E922241197C00000C92209109 +:10D10000036C00000E92004081B200002392200ABE +:10D11000026C00002292A240803200000000804495 +:10D120008FB00100000080498FB001002892220AD0 +:10D13000026C0000FC91A241197C00002792A240E1 +:10D1400080320000000080558FB001000000805642 +:10D150008FB001002A92A24080320000000080437C +:10D160008FB00100000080488FB001003092004372 +:10D1700095B000003092004195B00000309200421E +:10D1800095B000003092004495B000003092004C01 +:10D1900095B00000E0940040813201003392A2403B +:10D1A000803200000000804B8FB001000000804CF6 +:10D1B0008FB001002D000040439901002E002FF395 +:10D1C00084B001003892A2F3963000000000804045 +:10D1D00001B001002D002A41E7D10100D4003D41FA +:10D1E00085E001000B0000F200E401003E92225AAB +:10D1F000017C0000000000401F9001003F92005A97 +:10D2000001800000000000401F8001000000634119 +:10D2100085C001000000A0A5856C01000000E3406E +:10D2200085B001000C80000342C9010012000040DB +:10D2300087980100DF9500F08CB000004C922240EE +:10D240000F6C000000002F0548B101004992A24B6D +:10D25000197C00004A9222F0186C00000000604B1C +:10D26000199001001693000710300100F982004068 +:10D2700005B000004E92225A1F7C00009B92004095 +:10D2800081300100F982004005B0000000002F0548 +:10D2900048B101000000604B19900100169300078F +:10D2A00010300100F982004005B0000000002F0599 +:10D2B00048B101000000604B19900100169300076F +:10D2C000103001000000804005B00100579233404B +:10D2D000813200005A92A1AD95200000689213405F +:10D2E00081B200000000134A5A8301003000394522 +:10D2F00095E001001F00000F5ED801000000005AF9 +:10D300005F9001000000004045B0010000000004F3 +:10D3100048B00100000000054AB001000000000C08 +:10D3200058B00100000000074EB00100A884004082 +:10D330005D9801000000005861B101000000004A42 +:10D3400062B101000000A84197B000006592004062 +:10D3500081B200000000804097B001006992600730 +:10D3600096300000FFFF004B84890100000070C26E +:10D3700024B001007392A245257C00006D923120FB +:10D380008530000074922212487F00005804111268 +:10D39000480301001000001296E401000000004B59 +:10D3A0001E9401000000805A1F90010073923140CA +:10D3B00081320000000000B424B0010074922212F7 +:10D3C000487F0000580400408132010000002F0512 +:10D3D00048B1010081920BF084300000000011126E +:10D3E000488301007E922250857000005E0100405B +:10D3F00043990100419400F2963001009304001219 +:10D40000943001000000005A1F900100100000122B +:10D4100096E401000000804B1E94010010000042C1 +:10D4200010F4010000B73F4311F0010007000008AD +:10D430008A880100849230A10C3000008792224536 +:10D44000E67D00007492104081B2000000002A4581 +:10D45000E691010000001012488301000000114015 +:10D4600081B201000000604B858001005E01004038 +:10D4700043990100419400F29630010000800010B1 +:10D4800044C90100D8000040819801002E002D05FC +:10D4900048B1010092922240E76D000080000040F8 +:10D4A00080C8010000000040F0B101000900000840 +:10D4B00086E40100000068A787C001000000004466 +:10D4C00061B101000000001062B101009692A80550 +:10D4D000E03100001000001296E401000014004B3F +:10D4E00096DC01000000804B1E9401001000000F2C +:10D4F00084F401001F000042848801009F922240B2 +:10D5000080320000A092004268B10000000000429A +:10D510006AB10100A092315A1F0000000000914240 +:10D5200048930100A2923540813200006D00004016 +:10D5300061990100A89228B12C300000A392224DDD +:10D54000757D0000000000402DB0010000009540F6 +:10D5500011B001006D00004061990100A892A8B1CE +:10D56000103000000000954081B201007F000040B3 +:10D5700061990100AF9228B110300000AB929FBAC0 +:10D58000803200000000804011B0010000008024C3 +:10D59000118401000000005F61B101000010000073 +:10D5A00062DD01000000A84081B20000B19200409D +:10D5B00081B20000AC94004047990100B59232401E +:10D5C00081320000BB9222F896300000000000F883 +:10D5D00090B00100000000F092B001000100004B8B +:10D5E000F0CD010020009248E0C901006C0000402D +:10D5F00061990100BF9228B192300000BB92224C89 +:10D60000757D00000400124091B000006C000040E5 +:10D6100061990100BF92A8B190300000FF0000485E +:10D62000968801000000004B90D001000100004BE3 +:10D63000F0CD010020000048F0C90100000092492F +:10D64000E0B101000C002D1048B10100FF070008F7 +:10D65000828C0100FF0700F0008C01000000A24155 +:10D6600000EC0000CC92221A006C0000B092000086 +:10D67000343001000000005049C10100C892A241AD +:10D68000235000000000804081B201000C002D10EA +:10D6900048B10100FF070015828C0100FF0700F070 +:10D6A000008C01000000A24100EC0000D592220D88 +:10D6B000006C0000B09200001A3001000000005021 +:10D6C00049C10100D192A2412350000000008040D6 +:10D6D00081B20100DA92831E803200000000004413 +:10D6E0001990010024002D012CB0010028002DF01C +:10D6F00016B0010022002DF026B0010014002FF218 +:10D700000CB0010000008040E1B101003000004099 +:10D710009798010060972E4081B201000000004000 +:10D72000F1B10100E192A2419750000064973E439D +:10D730009DE0010000008040E1B1010064973E439C +:10D740009DE001000000800BE8B1010064973F43B9 +:10D750009DE00100000000F016C0010000008040C4 +:10D76000E1B1010064973F439DE00100000000F437 +:10D7700016B0010000008040E1B1010060173D4398 +:10D780009DE00100100080A116E4010000B5000D2D +:10D7900042C90100F092304717040000F392A20B37 +:10D7A000E67D00000000904281B0010000B7000D4E +:10D7B00046C90100F792A20BE67D00000000000BB5 +:10D7C000E69101000000904181B00100000010408E +:10D7D00081B20100F8924007963000009D0400409D +:10D7E000813201000293A245957C000001973F41E0 +:10D7F00095E00100000000F396B001000000004E2B +:10D80000E6B1010040973E4097E001000000004E65 +:10D81000E6B1010040973E409DE001001593003BBA +:10D82000E7B1000002933040813200000C93A20B5C +:10D83000E67D000000B5000D46C901000893A20B6B +:10D84000E67D00000000104081B201000000984217 +:10D8500081B0010000B7000D46C901000000000BB7 +:10D86000E69101000000104081B2010000009841E3 +:10D8700081B00100040021A2952000000000104AA0 +:10D880004483010000973E4195E001000000004EF6 +:10D89000F6B101000000004EE6B1010040973E40A5 +:10D8A0009DE001000000003BE7B101000000004ADC +:10D8B00090B10100FFFF000792890100000098402D +:10D8C00081B001000300000886F4010000B70043A6 +:10D8D00046C901000700000882880100199340082A +:10D8E000963000009D0400408132010025932245BE +:10D8F000957C00002193225A1F7C00001000000F2D +:10D9000096F401001E93315F970400000000114B54 +:10D91000489301000000004B6AB1010021933040A0 +:10D920008132000000000041E6810100000010404B +:10D9300081B201000000984081B2010000973F4190 +:10D9400095E00100000000F396B0010040973D40D3 +:10D9500097E00100000063F388B001002D93A23B23 +:10D96000896C00000000004A90B10100010000A68F +:10D9700092B101002E93184A449300000000184011 +:10D9800081B201003000394597E001003393225AFB +:10D990001F7C00001F04000F98D801000000004CFD +:10D9A0005E940100359300054AB000001F0400A7F3 +:10D9B0005E840100000000404BB0010000000058F0 +:10D9C00061B101000000004B62B101000000A840FD +:10D9D00081B200003693004081B2000039934007C5 +:10D9E000963000009D040040813201003D932245A5 +:10D9F000957C00000000984081B201009B04004A21 +:10DA00004413010000973F4195E00100000000F33E +:10DA100096B0010040973D4097E00100000063F39D +:10DA200088B001003000384597E001000000005F39 +:10DA30000F9001000000005861B101000000004B90 +:10DA400062B101004593A840813200003E93A23BA1 +:10DA5000896C0000300038459DE0010000009840CE +:10DA600081B2010093040012943001001693005A11 +:10DA70001F0001000000805A1F9001001100004AA1 +:10DA8000E6C9010034002F4F95840100000000F327 +:10DA900096B001000100634B84C801000000A04360 +:10DAA000856C01000000E34085B0010030002D448A +:10DAB0001F90010032002DF22AB00100040022F272 +:10DAC0000230000034920010323001003200A040D9 +:10DAD000E5B101000000004097B00100F0070040F0 +:10DAE000999801000000004A02C0010000000050A7 +:10DAF00003D001000000004197C001000000A34CCA +:10DB000002D000005C93004081B20000000000A839 +:10DB100036B001006C9322410350000000800010D9 +:10DB200044C9010000000050F1B101007000000381 +:10DB3000F0C901000000004261B1010000000010C6 +:10DB400062B101006593A800E0310000AF82008857 +:10DB50001CB00000B0920040813201007C800003C4 +:10DB600042C90100000000F000B001006093005CB9 +:10DB700001800000B0920040813201000000001BD3 +:10DB800010B1000068012D0682B00100000000F213 +:10DB900082C001000080000346C90100AB92004032 +:10DBA0008132010093932240116C0000000068084C +:10DBB00038960100F007004182CC01007193AA4120 +:10DBC0003B400000000000F810B001000000005CC5 +:10DBD000118001000100001D04CC01009293264633 +:10DBE000233000000800000312C80100640120F087 +:10DBF000E0B1010091932241055000002000000394 +:10DC000048C901000C0000F886C801000000224449 +:10DC1000F1B1010000000043F0B101000000000973 +:10DC2000E0B101000000004461B10100A00000A4C7 +:10DC300062DD01008393A8461F10000090932241EB +:10DC4000055000008E93A24123500000000000A167 +:10DC50001AB001000000004461B101004000001052 +:10DC600062DD01008993A84623300000AF8200885E +:10DC70001CB000001000000348C901000000000DA6 +:10DC800042B101000000004413C001007E93005027 +:10DC900049C100000000000548B1010004800003F4 +:10DCA0001AC801000000804081B201009293224016 +:10DCB0003B6C0000000000F800B00100B092005C76 +:10DCC00001000100939300413BD0000000008D470C +:10DCD00080320100B0002F5F13B001000000E0F0BF +:10DCE0008CC001000080000342C90100000000F860 +:10DCF00094B00100000000F88CB001009F938CF8F4 +:10DD00008E3000000000004419900100040022F849 +:10DD100014300000000000F816B00100000000F808 +:10DD200026B0010008002EF80CB001000C002A4AB1 +:10DD3000E0B1010028000000E0C901001000201B34 +:10DD4000E0B10100AC93200A0C6C0000000000F868 +:10DD500094B00100000000F896B00100200020F00F +:10DD6000E4B101001800204AE0B101001C00204B82 +:10DD7000E0B101009793004013B000002C002D4249 +:10DD8000199001002E002FF382B00100000000F373 +:10DD900096B00100B293A2A5976C000000008041EC +:10DDA00095B00100B593A240976C000000000040C0 +:10DDB00083B001002D002040E7B101000000634165 +:10DDC00097C00100D4003E4183E001000000004103 +:10DDD00083C00100BA93A0A5836C0000000000403E +:10DDE00083B001002C002041E6B10100BF93224026 +:10DDF0001F7C00000004000098DC01000B00004CB8 +:10DE0000E4F50100000080401F8001000B0080004D +:10DE1000E4F50100B4920040813201000480000367 +:10DE200044C9010000000040F1B1010000000040C1 +:10DE3000F1B101000000604187B0010000800010D6 +:10DE400044C9010000000050F1B101000000004889 +:10DE5000F0B1010000000049F0B101000000000332 +:10DE6000E0B101000000004561B101002000001098 +:10DE700062DD01000000A85D05900000CB9300402A +:10DE800081B20000B49200408132010000800003A2 +:10DE900044C9010000000041F0B10100000000424F +:10DEA000F0B1010000000040F1B1010000000043AA +:10DEB000F0B101000080001044C9010000000050D2 +:10DEC000F1B1010000000048F0B10100000000497C +:10DED000F0B1010000000003E0B1010000000045C6 +:10DEE00061B101002000001062DD01000000A85DAA +:10DEF00005900000DA93004081B200002D00004040 +:10DF0000439901002E002FF384B00100010063F358 +:10DF100096C80100E2939F4185500000010000A5D2 +:10DF200085CC01002D00A042E6B101005E012D006C +:10DF300080B00100E793524381600000020000F2CC +:10DF400082F40100E8930041809400000000005F2B +:10DF5000819001000000005E61B1010000000040FE +:10DF600062B101000000A84095B00000E9939EBB9B +:10DF700080320000EE93A2401F7C0000B09200406F +:10DF800081B200000000804195B00100040000153E +:10DF900042C90100000000542BC00100000000FC39 +:10DFA00024B00100000000FC38B00100000000FEB9 +:10DFB0003CB00100000000FE3AB0010003949C1741 +:10DFC00080320000F893A24A197C00000000804CC7 +:10DFD0001F9001000C00001E98F40100F793A24866 +:10DFE000996C00000000001542B10100F793A28A6D +:10DFF000F16D00000C00000102CC0100000000FCEB +:10E000003EB00100010000F428CC0100CC002D0539 +:10E0100048B10100029420F03E6C00000000004B6B +:10E020001F9001000000004C2BC00100BF002D0517 +:10E0300048B10100000080F33AE0010000002E4BDF +:10E040001990010007002A0CE4B1010000008004CF +:10E05000E6B1010018000040439901001C002DF0BA +:10E0600016B0010020002DF026B001000C002FF2A8 +:10E070000CB001000000A20614EC00000F94224531 +:10E080001F7C00000000A3062AEC0000000000F83E +:10E0900094B00100000000F096B001000C002D408B +:10E0A00081B2010000002A4CE1C1010030000010E3 +:10E0B00048C901000A000040F1990100180000055C +:10E0C000F0C901000000004AF0B101000000004B5F +:10E0D000E0B101000000004761B10100A00000A410 +:10E0E00062DD01001994A85C1F100000000080058B +:10E0F00048B1010000002E1048B1010040000001AD +:10E10000F0CD010040000003F0C901004000000014 +:10E11000E0C9010000002E5049C1010000000006C6 +:10E12000F1B1010000000003F0B10100239462424C +:10E13000613100002000001062DD01002494A8403D +:10E14000813200001000001062C901002694A8006E +:10E15000E03100000000F24081B2010000002E100A +:10E1600048B1010040000001F0CD01004000000373 +:10E17000F0C9010040000000E0C9010000002E507D +:10E1800049C1010000000006F1B1010000000003D8 +:10E19000F0B10100309462426131000020000010B3 +:10E1A00062DD01003194A84081320000A00000A48B +:10E1B00062DD01003394A800E03100000000F2406D +:10E1C00081B201003080004A44C90100000000060D +:10E1D000F1B10100C0A83D460DE00100FF7F00A1A4 +:10E1E000F08901000200000996F4010000000046D9 +:10E1F00097E00100000060A897C001003D946342D1 +:10E20000613100003000004A62C901003E94A8401C +:10E21000813200000000F34081B2010000993F42CA +:10E2200097F0010042946540813200004A9422F345 +:10E23000740600003F0000F394880100000000070E +:10E24000E78501000000755561B101000000004A3A +:10E2500062B101000000A84081B200004794004074 +:10E2600081B200000000F54081B20100000000A86A +:10E2700036B001005A948241234000004F94A244DA +:10E280001F7C0000BD9100018C3001002080001037 +:10E2900042C9010055942240E36D00000000004394 +:10E2A00061B101004000001062DD01005294A840FD +:10E2B00081320000AF8200881CB0000000000041E5 +:10E2C00023B001000000001032B001005A94224136 +:10E2D000197C0000C6920043233001000000004179 +:10E2E00023B001005C94A3150C6C00005D94000643 +:10E2F00004B000000000001504B001005F9420028B +:10E300001A6C00000000000D04B001001E9500050D +:10E310004831010089942202145000006394A20243 +:10E320002A5000008994A2451F7C000065942202B7 +:10E330000C5000006E94000216C000006D94225C28 +:10E340001F7C00003080001042C901006D94224003 +:10E35000E36D00000000004761B1010040000010C3 +:10E3600062DD01006994A84081320000AF8200881C +:10E370001CB000000000000548B101000894005CDA +:10E380001F00010089942215803200000000005017 +:10E3900033C001008894A2021A5000007A942246E9 +:10E3A0001F7C00007080000342C90100000000468D +:10E3B0001F8001007A942240E36D000000000042BB +:10E3C00061B101004000001062DD01007694A840B8 +:10E3D00081320000AF8200881CB000000000000500 +:10E3E00048B101000C80000342C90100100000F098 +:10E3F00010C801002F002F5C1180010000000047B1 +:10E40000E7910100F00700401B9801004C94201593 +:10E410001A6C00007000000348C90100000022507F +:10E42000F1B1010000000003F0B10100FF07000896 +:10E43000E08D01000000004261B10100A00000A4D5 +:10E4400062DD01008594A8461F1000004C94000571 +:10E4500048B100004C94000210C000008B94A2440C +:10E460001F7C0000BD9100018C3001000000001BEA +:10E4700010B100000080001044C901000C000040F1 +:10E48000F199010010000008F0C901000000001619 +:10E49000F0B1010010000003E0C9010000000045D8 +:10E4A00061B101002000001062DD01000000A85CE5 +:10E4B0001F9000009294004081B20000170000D02D +:10E4C000A2C901000000A24027EC000000000020CB +:10E4D00000B00100B0920041A341010096940041B8 +:10E4E00027D000001000000796E401000000004B58 +:10E4F000809401000000005461B1010000800040E0 +:10E5000062DD01000000A84081B200009D9400403F +:10E5100081B20000EF9400402B300100AC002D06CA +:10E5200016C0010090002DF016C40100A594A0F0C3 +:10E53000164400000000004117C001000E0000A2B8 +:10E5400044C9010000006CF030B00100AC002D4067 +:10E5500087B0010000006CF028B00100AE94224AA0 +:10E56000197C00000030004386C801000030000B19 +:10E5700016C80100AE94A4408132000000000041A2 +:10E5800017C00100CF94220680320000BB94A2067F +:10E59000146C0000B8942248197C0000B394A04188 +:10E5A000174000000000004117C0010000000041BA +:10E5B00031C0010090002018E0B101008B002D480F +:10E5C000198001008B002045E7910100BB940040B9 +:10E5D000879000000800004386980100BB94A04883 +:10E5E000174000000000004117C00100B0000040CB +:10E5F0004399010010500043FCC9010026950030EA +:10E600008130010000000040E5B10100C694224ABB +:10E61000197C0000080000A244C90100CC002DAB09 +:10E62000F9B10100000000AB17C00100C594A0F0D3 +:10E63000164400000000004117C00100CA9464F0B5 +:10E6400082B00000A400004047990100CA94A2F2E1 +:10E650008032000000000041E5B101008C0020186C +:10E66000E0B1010090000040459901000000600603 +:10E6700030C001000000860C80B20000BC002D46B6 +:10E6800019900100A000A0F2E4B10100B000004028 +:10E690004399010010500043FCC901002695003049 +:10E6A000813001000000A24A19FC0000080000A20D +:10E6B00044C90100CC002DABF9B10100000000AB52 +:10E6C00017C00100D894A0F01644000000000041DB +:10E6D00017C001000000E4F082B0010000800010CB +:10E6E00044C9010000000041F0B101000000000336 +:10E6F000F0B1010000000000F0B1010000000010C6 +:10E7000062B101000000A81BE0B10000DD940040F0 +:10E7100081B2000000F0000C7E8901000000A64CD0 +:10E72000956001000000804A1894010000800010EC +:10E7300044C9010004002201F03100002000004023 +:10E74000F0C9010000000016F0B101000000004314 +:10E7500061B101002000001062DD01000000A81579 +:10E76000E0B10000E894004081B200001080000396 +:10E7700044C9010000000006F0B1010000000001E2 +:10E78000F0B101000000E85F179001007000004048 +:10E79000439901007A012EFE92B001008B002DF604 +:10E7A00016B00100F5942243E77D0000000000440C +:10E7B00045C10100040000A62AB0010028006E0631 +:10E7C00082C80100F994224A197C0000000000422E +:10E7D00045D1010000006E4C83C0010000000041E3 +:10E7E00092C00100FA9443303D0700000000669E8D +:10E7F00083B0010000001B413DC301000000004147 +:10E8000092C00100060000A244C9010010000049A6 +:10E8100098F4010003952630930400000395904C72 +:10E82000924000000000004193C00100FFFF8049BA +:10E83000ECA901000080001044C90100040022017D +:10E84000F031000000000009F0B1010000000018E4 +:10E85000F0B101002000001062DD01000000A815E9 +:10E86000E0B100000895004081B200001595225FDC +:10E87000817C00001495A240197C0000000000403B +:10E88000199001000000005461B101001000000760 +:10E8900096E401000000004F979401000000004B37 +:10E8A00062B10100149528408132000011950040AA +:10E8B00081B200000000A221818400001895A25FAF +:10E8C000816C00000000A243197C0100000000439D +:10E8D000199001000000005461B101001000000710 +:10E8E00096E4010000000040969401000000004BF7 +:10E8F00062B101000000A84081B200001B950040F9 +:10E9000081B200000080001944C901000400220205 +:10E91000F03100000000000BF0B101000000001316 +:10E92000F0B101000000004361B1010020000019B6 +:10E9300062DD01000000A808E0B10000239500405E +:10E9400081B200007C002DF084B00100020000F0D4 +:10E9500098F401002C95204C846C00008800004045 +:10E96000439901002C9520F2846C000000000040C7 +:10E9700085B0010098002D1482B00100000000F065 +:10E9800098B00100A3002D1498D001003195204CBF +:10E99000846C00000000004C84B00100000000F313 +:10E9A00080E0010034952340846C000000000040AA +:10E9B00084B00100D0002014E0B10100980025428D +:10E9C00080B0010000006EF380F001000000A6425C +:10E9D00082C000003A95A0401640000000000041AF +:10E9E00017C0010000009FF082EC00009800A041D9 +:10E9F000E0B1010000002E1048B10100A801004064 +:10EA0000F199010000000005F0B1010009000007C4 +:10EA100096E40100000060A797C00100000000100C +:10EA200062B101000000A84081B2000041950040A1 +:10EA300081B20000A8002D1C8AB0010000009FF0E8 +:10EA40008AD000000000A2408BEC00008A00204029 +:10EA5000E7B10100B400004047990100A4002D4532 +:10EA6000E0D101004E959C1780320000BE002FAB14 +:10EA700083B00100A195001482500100539500401D +:10EA800081B20000539522F2823000008C000040D9 +:10EA90004399010053959F1CE06D0000BE000040AB +:10EAA00047990100A195004081320100A800201C77 +:10EAB000E0B101009C002D3081B0010088002DF0F4 +:10EAC00084B0010094002DF286B00100669523F019 +:10EAD000846C00005B952392876C0000C90400A63B +:10EAE00094B001005D95004081B20000200000A6B6 +:10EAF00094B001006089004A949801005D956840D7 +:10EB0000813200000000004AB0B10100BF002D4278 +:10EB1000B2B1010090002DF380E001006195D44076 +:10EB200081320000000078DA84C001006B95234038 +:10EB3000846C00009400209DE1B101006B950040C1 +:10EB400084B00000BF002D4384C0010090002DF36D +:10EB500080E001006B952340846C00009400209DB0 +:10EB6000E1B101000000004084B001006F95A2F007 +:10EB7000386C00009C002042E0B101000000005F02 +:10EB80001394010000008046198001009C0020427F +:10EB9000E0B101003700004043990100040000F398 +:10EBA00080F401000F0000F3828801007595234175 +:10EBB000806C00000000005F139401000000890CCD +:10EBC00080B20000BC00004043990100A000A0F208 +:10EBD000E4B1010000009F4124EC00007F95A640B5 +:10EBE0008132000000009F4238EC00007F95A64073 +:10EBF00081320000B4000040439901008195A3F0E8 +:10EC00003A6C00000000804081B20100B400004076 +:10EC100043990100859522F03A6C0000B400201D54 +:10EC2000E0B1010080002D5F13940100859523F071 +:10EC30003A6C00008000201DE0B10100C0002012ED +:10EC4000E0B10100C400A01CE0B10100008000039D +:10EC500044C9010000000042E0B101001200004080 +:10EC6000879801008E959F41246C000000000041B0 +:10EC70008CB00100000000128CD001008F95004183 +:10EC800024B00000000000408DB00100DF9500407E +:10EC9000813201000000004561B101004000001018 +:10ECA00062DD01000000A84081B2000091950040A3 +:10ECB00081B20000A29200408132010000000016E3 +:10ECC00080B201000000A708803201009995A2409F +:10ECD000956C0000B092004081320100008200A6D5 +:10ECE00004B00100000000402DB00100A0982F40AA +:10ECF00011B001003005004189B0000000009FF80C +:10ED00003EEC000000009F12E0ED0000C80020ABC8 +:10ED1000E1B10100CC00A01FE0B10100A395A35F09 +:10ED2000E76D000000000041E7C10100A6000040BF +:10ED300047990100B79522F2863000000300004396 +:10ED400084F401000100004180CC0100B8002D4294 +:10ED500080D001000000624086C00100AB951F43D7 +:10ED600080320000AC95A240876C00000000624138 +:10ED700087B00100B0959F40803200000000004045 +:10ED800085B001000000004084D001000000004276 +:10ED900080B00100000000F288B0010002000044D1 +:10EDA00084F40100B8002E4280D0010000006240CF +:10EDB00088C00100B6951F4480320000BA95A24079 +:10EDC000896C0000BA95624189B00000030062417D +:10EDD00086E40100B800004045990100010062414D +:10EDE00088E40100A4002040E5B10100A200204019 +:10EDF000E7B10100BC002E4387F001000000004491 +:10EE000086C00100C0952043876C0000000080434D +:10EE1000E5B101004001004380CE01000000A443A1 +:10EE2000E43101004001E2408798010088002D4450 +:10EE300081B0010090002DF22EB001009C002DF059 +:10EE400086B0010090002DF082B00100BA002DF0D4 +:10EE500098B00100CD95A212986C0000BC002DF274 +:10EE600098B00100CD95A0F2986C0000000000174A +:10EE700082B001009C002041E0B10100B4002D12DD +:10EE800086D00100D095A341E06D0000D19500F03F +:10EE900084B000000000004184B0010080002D43D8 +:10EEA00084D00100D4959F428032000000000040D1 +:10EEB00085B00100D695A342146C0000D795000AD6 +:10EEC0000CB00000000000420CB00100D995A01762 +:10EED0000C6C0000000080170CB00100DE95224091 +:10EEE0000D6C00000000A00A0CEC0000010000F016 +:10EEF00082F40100DE95A0410C6C00000000A2F03D +:10EF0000803201000000804081B00100B4920040D6 +:10EF1000813201000480000344C901000000004662 +:10EF2000F0B1010000000040F1B1010000006041BB +:10EF3000879401000080001044C9010000000050C7 +:10EF4000F1B1010000000048F0B1010000000049EB +:10EF5000F0B1010000000003E0B101000000004535 +:10EF600061B101002000001062DD01000000A85D19 +:10EF700005900000EA95004081B2000000002E4B91 +:10EF80001990010005002A0CE4B101000000800482 +:10EF9000E6B10100F095454861310000001000081D +:10EFA00062DD0100F595284087300000F195224888 +:10EFB000777D000095941D4687B00000F895225F8C +:10EFC000117C00000400221562310000F695A84073 +:10EFD0008132000000009D4081B20100000000402D +:10EFE00049B1010000142F4C83B001000000004023 +:10EFF000F1B10100FB95A241835000000000804068 +:10F0000081B201000000004049B101003000004021 +:10F01000A19901000000004093B0010000000040F1 +:10F020001FB001004E9600499630010007000049CC +:10F0300006E401000039000306C80100000000409A +:10F0400005B00100200000D0A0C90100000000416F +:10F0500093C001000296A054936C000000002E059E +:10F0600097B0010000800040499901000000004075 +:10F07000E1B10100000200A244C901000B96A241C7 +:10F08000975000000000002049B301005496004052 +:10F0900049310100DF9200408132010000B52E08A5 +:10F0A00097B0010000000040F1B101001296A241AA +:10F0B00097500000180000409798010000972E40DC +:10F0C00081B2010000000040F1B101001696A2419A +:10F0D000975000000000004049B1010040182E0583 +:10F0E00097B0010000000040F1B101001A96A24162 +:10F0F0009750000057952040E7B101003094004040 +:10F100004599010064000040E599010056952040B2 +:10F11000E7B10100B8942041E5B10100BA94204163 +:10F12000E5B10100989400404599010002000040BB +:10F130009798010000000040F1B101002496A2411F +:10F14000975000000000004097B001000000004010 +:10F150006FB101000000004B68B1010028968541A5 +:10F160009740000080040040813201000000004010 +:10F1700039B301000000004037B301000000004037 +:10F1800035B301000000004033B30100000000402F +:10F1900041B30100000000403FB30100EE05004014 +:10F1A000259B0100420000404B9B010000000040F5 +:10F1B0002FB30100000000402DB30100000000400B +:10F1C00047B301000000004043B30100600000406D +:10F1D0002B9B010000000054EF930100000000553C +:10F1E000F1930100FFFF00A53C8B01000000002C03 +:10F1F0005BB301000000002C45B30100000000409B +:10F2000059B301000000004057B301000000004066 +:10F2100027B301000000004053B301004496A25000 +:10F22000FD7F00004496A251FD7F000045960040FE +:10F230001DB30000504600401D9B010000C000A609 +:10F2400088B30100FF3F00A63AB3010000C0009D53 +:10F250003B9B0100B4050040239B010000000040DF +:10F260004DB30100080A00A614B301000101008A91 +:10F27000159B0100008000A656B101000000805ED1 +:10F2800057B501001800004B20E401000600004BB8 +:10F2900096E401000043004B96C8010018000010DE +:10F2A00020DC01000000004B20940100000080578A +:10F2B0002190010000992E0A97B001000000004043 +:10F2C000F1B101005596A2419750000000030040A3 +:10F2D0009798010000A900404599010000000040F6 +:10F2E000F1B101005996A241975000003000004052 +:10F2F000979801000000005561B101000000004B2B +:10F3000062B101005D96A840813200005D96A24185 +:10F31000975000000000804081B201000000804052 +:10F3200081B201000400004081B2000004000040EE +:10F3300081B200000400004081B2000004000040DF +:10F3400081B200000400004081B2000004000040CF +:10F3500081B200000400004081B2000004000040BF +:10F3600081B200000400004081B2000004000040AF +:10F3700081B200000400004081B20000040000409F +:10F3800081B200000400004081B20000040000408F +:10F3900081B200000400004081B20000040000407F +:10F3A00081B200000400004081B20000040000406F +:10F3B00081B200000400004081B20000040000405F +:10F3C00081B200000400004081B20000040000404F +:10F3D00081B200000400004081B20000040000403F +:10F3E00081B200000400004081B20000040000402F +:10F3F00081B200000400004081B20000040000401F +:10F4000081B200000400004081B20000040000400E +:10F4100081B200000400004081B2000004000040FE +:10F4200081B200000400004081B2000004000040EE +:10F4300081B200000400004081B2000004000040DE +:10F4400081B200000400004081B2000004000040CE +:10F4500081B200000400004081B2000004000040BE +:10F4600081B200000400004081B2000004000040AE +:10F4700081B200000400004081B20000040000409E +:10F4800081B200000400004081B20000040000408E +:10F4900081B200000400004081B20000040000407E +:10F4A00081B200000400004081B20000040000406E +:10F4B00081B200000400004081B20000040000405E +:10F4C00081B200000400004081B20000040000404E +:10F4D00081B200000400004081B20000040000403E +:10F4E00081B200000400004081B20000040000402E +:10F4F00081B200000400004081B20000040000401E +:10F5000081B200000400004081B20000040000400D +:10F5100081B200000400004081B2000004000040FD +:10F5200081B200000400004081B2000004000040ED +:10F5300081B200000400004081B2000004000040DD +:10F5400081B200000400004081B2000004000040CD +:10F5500081B200000400004081B2000004000040BD +:10F5600081B200000400004081B2000004000040AD +:10F5700081B200000400004081B20000040000409D +:10F5800081B200000400004081B20000040000408D +:10F5900081B200000400004081B20000040000407D +:10F5A00081B200000400004081B20000040000406D +:10F5B00081B200000400004081B20000040000405D +:10F5C00081B200000400004081B20000040000404D +:10F5D00081B200000400004081B20000040000403D +:10F5E00081B200000400004081B20000040000402D +:10F5F00081B200000400004081B20000040000401D +:10F6000081B200000400004081B20000040000400C +:10F6100081B200000400004081B2000004000040FC +:10F6200081B200000400004081B2000004000040EC +:10F6300081B200000400004081B2000004000040DC +:10F6400081B200000400004081B2000004000040CC +:10F6500081B200000400004081B2000004000040BC +:10F6600081B200000400004081B2000004000040AC +:10F6700081B200000400004081B20000040000409C +:10F6800081B200000400004081B20000040000408C +:10F6900081B200000400004081B20000040000407C +:10F6A00081B200000400004081B20000040000406C +:10F6B00081B200000400004081B20000040000405C +:10F6C00081B200000400004081B20000040000404C +:10F6D00081B200000400004081B20000040000403C +:10F6E00081B200000400004081B20000040000402C +:10F6F00081B200000400004081B20000040000401C +:10F7000081B200000400004081B20000040000400B +:10F7100081B200000400004081B2000004000040FB +:10F7200081B200000400004081B2000004000040EB +:10F7300081B200000400004081B2000004000040DB +:10F7400081B200000400004081B2000004000040CB +:10F7500081B200000400004081B2000004000040BB +:10F7600081B200000400004081B2000004000040AB +:10F7700081B200000400004081B20000040000409B +:10F7800081B200000400004081B20000040000408B +:10F7900081B200000400004081B20000040000407B +:10F7A00081B200000400004081B20000040000406B +:10F7B00081B200000400004081B20000040000405B +:10F7C00081B200000400004081B20000040000404B +:10F7D00081B200000400004081B20000040000403B +:10F7E00081B200000400004081B20000040000402B +:10F7F00081B200000400004081B20000040000401B +:10F8000081B200000400004081B20000040000400A +:10F8100081B200000400004081B2000004000040FA +:10F8200081B200000400004081B2000004000040EA +:10F8300081B200000400004081B2000004000040DA +:10F8400081B200000400004081B2000004000040CA +:10F8500081B200000400004081B2000004000040BA +:10F8600081B200000400004081B2000004000040AA +:10F8700081B200000400004081B20000040000409A +:10F8800081B200000400004081B20000040000408A +:10F8900081B200000400004081B20000040000407A +:10F8A00081B200000400004081B20000040000406A +:10F8B00081B200000400004081B20000040000405A +:10F8C00081B200000400004081B20000040000404A +:10F8D00081B200000400004081B20000040000403A +:10F8E00081B200000400004081B20000040000402A +:10F8F00081B200000400004081B20000040000401A +:10F9000081B200000400004081B200000400004009 +:10F9100081B200000400004081B2000004000040F9 +:10F9200081B200000400004081B2000004000040E9 +:10F9300081B200000400004081B2000004000040D9 +:10F9400081B200000400004081B2000004000040C9 +:10F9500081B200000400004081B2000004000040B9 +:10F9600081B200000400004081B2000004000040A9 +:10F9700081B200000400004081B200000400004099 +:10F9800081B200000400004081B200000400004089 +:10F9900081B200000400004081B200000400004079 +:10F9A00081B200000400004081B200000400004069 +:10F9B00081B200000400004081B200000400004059 +:10F9C00081B200000400004081B200000400004049 +:10F9D00081B200000400004081B200000400004039 +:10F9E00081B200000400004081B200000400004029 +:10F9F00081B200000400004081B200000400004019 +:10FA000081B200000400004081B200000400004008 +:10FA100081B200000400004081B2000004000040F8 +:10FA200081B200000400004081B2000004000040E8 +:10FA300081B200000400004081B2000004000040D8 +:10FA400081B200000400004081B2000004000040C8 +:10FA500081B200000400004081B2000004000040B8 +:10FA600081B200000400004081B2000004000040A8 +:10FA700081B200000400004081B200000400004098 +:10FA800081B200000400004081B200000400004088 +:10FA900081B200000400004081B200000400004078 +:10FAA00081B200000400004081B200000400004068 +:10FAB00081B200000400004081B200000400004058 +:10FAC00081B200000400004081B200000400004048 +:10FAD00081B200000400004081B200000400004038 +:10FAE00081B200000400004081B200000400004028 +:10FAF00081B200000400004081B200000400004018 +:10FB000081B200000400004081B200000400004007 +:10FB100081B200000400004081B2000004000040F7 +:10FB200081B200000400004081B2000004000040E7 +:10FB300081B200000400004081B2000004000040D7 +:10FB400081B200000400004081B2000004000040C7 +:10FB500081B200000400004081B2000004000040B7 +:10FB600081B200000400004081B2000004000040A7 +:10FB700081B200000400004081B200000400004097 +:10FB800081B200000400004081B200000400004087 +:10FB900081B200000400004081B200000400004077 +:10FBA00081B200000400004081B200000400004067 +:10FBB00081B200000400004081B200000400004057 +:10FBC00081B200000400004081B200000400004047 +:10FBD00081B200000400004081B200000400004037 +:10FBE00081B200000400004081B200000400004027 +:10FBF00081B200000400004081B200000400004017 +:10FC000081B200000400004081B200000400004006 +:10FC100081B200000400004081B2000004000040F6 +:10FC200081B200000400004081B2000004000040E6 +:10FC300081B200000400004081B2000004000040D6 +:10FC400081B200000400004081B2000004000040C6 +:10FC500081B200000400004081B2000004000040B6 +:10FC600081B200000400004081B2000004000040A6 +:10FC700081B200000400004081B200000400004096 +:10FC800081B200000400004081B200000400004086 +:10FC900081B200000400004081B200000400004076 +:10FCA00081B200000400004081B200000400004066 +:10FCB00081B200000400004081B200000400004056 +:10FCC00081B200000400004081B200000400004046 +:10FCD00081B200000400004081B200000400004036 +:10FCE00081B200000400004081B200000400004026 +:10FCF00081B200000400004081B200000400004016 +:10FD000081B200000400004081B200000400004005 +:10FD100081B200000400004081B2000004000040F5 +:10FD200081B200000400004081B2000004000040E5 +:10FD300081B200000400004081B2000004000040D5 +:10FD400081B200000400004081B2000004000040C5 +:10FD500081B200000400004081B2000004000040B5 +:10FD600081B200000400004081B2000004000040A5 +:10FD700081B200000400004081B200000400004095 +:10FD800081B200000400004081B200000400004085 +:10FD900081B200000400004081B200000400004075 +:10FDA00081B200000400004081B200000400004065 +:10FDB00081B200000400004081B200000400004055 +:10FDC00081B200000400004081B200000400004045 +:10FDD00081B200000400004081B200000400004035 +:10FDE00081B200000400004081B200000400004025 +:10FDF00081B200000400004081B200000400004015 +:10FE000081B200000400004081B200000400004004 +:10FE100081B200000400004081B2000004000040F4 +:10FE200081B200000400004081B2000004000040E4 +:10FE300081B200000400004081B2000004000040D4 +:10FE400081B200000400004081B2000004000040C4 +:10FE500081B200000400004081B2000004000040B4 +:10FE600081B200000400004081B2000004000040A4 +:10FE700081B200000400004081B200000400004094 +:10FE800081B200000400004081B200000400004084 +:10FE900081B200000400004081B200000400004074 +:10FEA00081B200000400004081B200000400004064 +:10FEB00081B200000400004081B200000400004054 +:10FEC00081B200000400004081B200000400004044 +:10FED00081B200000400004081B200000400004034 +:10FEE00081B200000400004081B200000400004024 +:10FEF00081B200000400004081B200000400004014 +:10FF000081B200000400004081B200000400004003 +:10FF100081B200000400004081B2000004000040F3 +:10FF200081B200000400004081B2000004000040E3 +:10FF300081B200000400004081B2000004000040D3 +:10FF400081B200000400004081B2000004000040C3 +:10FF500081B200000400004081B2000004000040B3 +:10FF600081B200000400004081B2000004000040A3 +:10FF700081B200000400004081B200000400004093 +:10FF800081B200000400004081B200000400004083 +:10FF900081B200000400004081B200000400004073 +:10FFA00081B200000400004081B200000400004063 +:10FFB00081B200000400004081B200000400004053 +:10FFC00081B200000400004081B200000400004043 +:10FFD00081B200000400004081B200000400004033 +:10FFE00081B200000400004081B200000400004023 +:10FFF00081B200000400004081B200000400004013 +:020000021000EC +:1000000081B200000400004081B200000400004002 +:1000100081B200000400004081B2000004000040F2 +:1000200081B200000400004081B2000004000040E2 +:1000300081B200000400004081B2000004000040D2 +:1000400081B200000400004081B2000004000040C2 +:1000500081B200000400004081B2000004000040B2 +:1000600081B200000400004081B2000004000040A2 +:1000700081B200000400004081B200000400004092 +:1000800081B200000400004081B200000400004082 +:1000900081B200000400004081B200000400004072 +:1000A00081B200000400004081B200000400004062 +:1000B00081B200000400004081B200000400004052 +:1000C00081B200000400004081B200000400004042 +:1000D00081B200000400004081B200000400004032 +:1000E00081B200000400004081B200000400004022 +:1000F00081B200000400004081B200000400004012 +:1001000081B200000400004081B200000400004001 +:1001100081B200000400004081B2000004000040F1 +:1001200081B200000400004081B2000004000040E1 +:1001300081B200000400004081B2000004000040D1 +:1001400081B200000400004081B2000004000040C1 +:1001500081B200000400004081B2000004000040B1 +:1001600081B200000400004081B2000004000040A1 +:1001700081B200000400004081B200000400004091 +:1001800081B200000400004081B200000400004081 +:1001900081B200000400004081B200000400004071 +:1001A00081B200000400004081B200000400004061 +:1001B00081B200000400004081B200000400004051 +:1001C00081B200000400004081B200000400004041 +:1001D00081B200000400004081B200000400004031 +:1001E00081B200000400004081B200000400004021 +:1001F00081B200000400004081B200000400004011 +:1002000081B200000400004081B200000400004000 +:1002100081B200000400004081B2000004000040F0 +:1002200081B200000400004081B2000004000040E0 +:1002300081B200000400004081B2000004000040D0 +:1002400081B200000400004081B2000004000040C0 +:1002500081B200000400004081B2000004000040B0 +:1002600081B200000400004081B2000004000040A0 +:1002700081B200000400004081B200000400004090 +:1002800081B200000400004081B200000400004080 +:1002900081B200000400004081B200000400004070 +:1002A00081B200000400004081B200000400004060 +:1002B00081B200000400004081B200000400004050 +:1002C00081B200000400004081B200000400004040 +:1002D00081B200000400004081B200000400004030 +:1002E00081B200000400004081B200000400004020 +:1002F00081B200000400004081B200000400004010 +:1003000081B200000400004081B2000004000040FF +:1003100081B200000400004081B2000004000040EF +:1003200081B200000400004081B2000004000040DF +:1003300081B200000400004081B2000004000040CF +:1003400081B200000400004081B2000004000040BF +:1003500081B200000400004081B2000004000040AF +:1003600081B200000400004081B20000040000409F +:1003700081B200000400004081B20000040000408F +:1003800081B200000400004081B20000040000407F +:1003900081B200000400004081B20000040000406F +:1003A00081B200000400004081B20000040000405F +:1003B00081B200000400004081B20000040000404F +:1003C00081B200000400004081B20000040000403F +:1003D00081B200000400004081B20000040000402F +:1003E00081B200000400004081B20000040000401F +:1003F00081B200000400004081B20000040000400F +:1004000081B200000400004081B2000004000040FE +:1004100081B200000400004081B2000004000040EE +:1004200081B200000400004081B2000004000040DE +:1004300081B200000400004081B2000004000040CE +:1004400081B200000400004081B2000004000040BE +:1004500081B200000400004081B2000004000040AE +:1004600081B200000400004081B20000040000409E +:1004700081B200000400004081B20000040000408E +:1004800081B200000400004081B20000040000407E +:1004900081B200000400004081B20000040000406E +:1004A00081B200000400004081B20000040000405E +:1004B00081B200000400004081B20000040000404E +:1004C00081B200000400004081B20000040000403E +:1004D00081B200000400004081B20000040000402E +:1004E00081B200000400004081B20000040000401E +:1004F00081B200000400004081B20000040000400E +:1005000081B200000400004081B2000004000040FD +:1005100081B200000400004081B2000004000040ED +:1005200081B200000400004081B2000004000040DD +:1005300081B200000400004081B2000004000040CD +:1005400081B200000400004081B2000004000040BD +:1005500081B200000400004081B2000004000040AD +:1005600081B200000400004081B20000040000409D +:1005700081B200000400004081B20000040000408D +:1005800081B200000400004081B20000040000407D +:1005900081B200000400004081B20000040000406D +:1005A00081B200000400004081B20000040000405D +:1005B00081B200000400004081B20000040000404D +:1005C00081B200000400004081B20000040000403D +:1005D00081B200000400004081B20000040000402D +:1005E00081B200000400004081B20000040000401D +:1005F00081B200000400004081B20000040000400D +:1006000081B200000400004081B2000004000040FC +:1006100081B200000400004081B2000004000040EC +:1006200081B200000400004081B2000004000040DC +:1006300081B200000400004081B2000004000040CC +:1006400081B200000400004081B2000004000040BC +:1006500081B200000400004081B2000004000040AC +:1006600081B200000400004081B20000040000409C +:1006700081B200000400004081B20000040000408C +:1006800081B200000400004081B20000040000407C +:1006900081B200000400004081B20000040000406C +:1006A00081B200000400004081B20000040000405C +:1006B00081B200000400004081B20000040000404C +:1006C00081B200000400004081B20000040000403C +:1006D00081B200000400004081B20000040000402C +:1006E00081B200000400004081B20000040000401C +:1006F00081B200000400004081B20000040000400C +:1007000081B200000400004081B2000004000040FB +:1007100081B200000400004081B2000004000040EB +:1007200081B200000400004081B2000004000040DB +:1007300081B200000400004081B2000004000040CB +:1007400081B200000400004081B2000004000040BB +:1007500081B200000400004081B2000004000040AB +:1007600081B200000400004081B20000040000409B +:1007700081B200000400004081B20000040000408B +:1007800081B200000400004081B20000040000407B +:1007900081B200000400004081B20000040000406B +:1007A00081B200000400004081B20000040000405B +:1007B00081B200000400004081B20000040000404B +:1007C00081B200000400004081B20000040000403B +:1007D00081B200000400004081B20000040000402B +:1007E00081B200000400004081B20000040000401B +:1007F00081B200000400004081B20000040000400B +:1008000081B200000400004081B2000004000040FA +:1008100081B200000400004081B2000004000040EA +:1008200081B200000400004081B2000004000040DA +:1008300081B200000400004081B2000004000040CA +:1008400081B200000400004081B2000004000040BA +:1008500081B200000400004081B2000004000040AA +:1008600081B200000400004081B20000040000409A +:1008700081B200000400004081B20000040000408A +:1008800081B200000400004081B20000040000407A +:1008900081B200000400004081B20000040000406A +:1008A00081B200000400004081B20000040000405A +:1008B00081B200000400004081B20000040000404A +:1008C00081B200000400004081B20000040000403A +:1008D00081B200000400004081B20000040000402A +:1008E00081B200000400004081B20000040000401A +:1008F00081B200000400004081B20000040000400A +:1009000081B200000400004081B2000004000040F9 +:1009100081B200000400004081B2000004000040E9 +:1009200081B200000400004081B2000004000040D9 +:1009300081B200000400004081B2000004000040C9 +:1009400081B200000400004081B2000004000040B9 +:1009500081B200000400004081B2000004000040A9 +:1009600081B200000400004081B200000400004099 +:1009700081B200000400004081B200000400004089 +:1009800081B200000400004081B200000400004079 +:1009900081B200000400004081B200000400004069 +:1009A00081B200000400004081B200000400004059 +:1009B00081B200000400004081B200000400004049 +:1009C00081B200000400004081B200000400004039 +:1009D00081B200000400004081B200000400004029 +:1009E00081B200000400004081B200000400004019 +:1009F00081B200000400004081B200000400004009 +:100A000081B200000400004081B2000004000040F8 +:100A100081B200000400004081B2000004000040E8 +:100A200081B200000400004081B2000004000040D8 +:100A300081B200000400004081B2000004000040C8 +:100A400081B200000400004081B2000004000040B8 +:100A500081B200000400004081B2000004000040A8 +:100A600081B200000400004081B200000400004098 +:100A700081B200000400004081B200000400004088 +:100A800081B200000400004081B200000400004078 +:100A900081B200000400004081B200000400004068 +:100AA00081B200000400004081B200000400004058 +:100AB00081B200000400004081B200000400004048 +:100AC00081B200000400004081B200000400004038 +:100AD00081B200000400004081B200000400004028 +:100AE00081B200000400004081B200000400004018 +:100AF00081B200000400004081B200000400004008 +:100B000081B200000400004081B2000004000040F7 +:100B100081B200000400004081B2000004000040E7 +:100B200081B200000400004081B2000004000040D7 +:100B300081B200000400004081B2000004000040C7 +:100B400081B200000400004081B2000004000040B7 +:100B500081B200000400004081B2000004000040A7 +:100B600081B200000400004081B200000400004097 +:100B700081B200000400004081B200000400004087 +:100B800081B200000400004081B200000400004077 +:100B900081B200000400004081B200000400004067 +:100BA00081B200000400004081B200000400004057 +:100BB00081B200000400004081B200000400004047 +:100BC00081B200000400004081B200000400004037 +:100BD00081B200000400004081B200000400004027 +:100BE00081B200000400004081B200000400004017 +:100BF00081B200000400004081B200000400004007 +:100C000081B200000400004081B2000004000040F6 +:100C100081B200000400004081B2000004000040E6 +:100C200081B200000400004081B2000004000040D6 +:100C300081B200000400004081B2000004000040C6 +:100C400081B200000400004081B2000004000040B6 +:100C500081B200000400004081B2000004000040A6 +:100C600081B200000400004081B200000400004096 +:100C700081B200000400004081B200000400004086 +:100C800081B200000400004081B200000400004076 +:100C900081B200000400004081B200000400004066 +:100CA00081B200000400004081B200000400004056 +:100CB00081B200000400004081B200000400004046 +:100CC00081B200000400004081B200000400004036 +:100CD00081B200000400004081B200000400004026 +:100CE00081B200000400004081B200000400004016 +:100CF00081B200000400004081B200000400004006 +:100D000081B200000400004081B2000004000040F5 +:100D100081B200000400004081B2000004000040E5 +:100D200081B200000400004081B2000004000040D5 +:100D300081B200000400004081B2000004000040C5 +:100D400081B200000400004081B2000004000040B5 +:100D500081B200000400004081B2000004000040A5 +:100D600081B200000400004081B200000400004095 +:100D700081B200000400004081B200000400004085 +:100D800081B200000400004081B200000400004075 +:100D900081B200000400004081B200000400004065 +:100DA00081B200000400004081B200000400004055 +:100DB00081B200000400004081B200000400004045 +:100DC00081B200000400004081B200000400004035 +:100DD00081B200000400004081B200000400004025 +:100DE00081B200000400004081B200000400004015 +:100DF00081B200000400004081B200000400004005 +:100E000081B200000400004081B2000004000040F4 +:100E100081B200000400004081B2000004000040E4 +:100E200081B200000400004081B2000004000040D4 +:100E300081B200000400004081B2000004000040C4 +:100E400081B200000400004081B2000004000040B4 +:100E500081B200000400004081B2000004000040A4 +:100E600081B200000400004081B200000400004094 +:100E700081B200000400004081B200000400004084 +:100E800081B200000400004081B200000400004074 +:100E900081B200000400004081B200000400004064 +:100EA00081B200000400004081B200000400004054 +:100EB00081B200000400004081B200000400004044 +:100EC00081B200000400004081B200000400004034 +:100ED00081B200000400004081B200000400004024 +:100EE00081B200000400004081B200000400004014 +:100EF00081B200000400004081B200000400004004 +:100F000081B200000400004081B2000004000040F3 +:100F100081B200000400004081B2000004000040E3 +:100F200081B200000400004081B2000004000040D3 +:100F300081B200000400004081B2000004000040C3 +:100F400081B200000400004081B2000004000040B3 +:100F500081B200000400004081B2000004000040A3 +:100F600081B200000400004081B200000400004093 +:100F700081B200000400004081B200000400004083 +:100F800081B200000400004081B200000400004073 +:100F900081B200000400004081B200000400004063 +:100FA00081B200000400004081B200000400004053 +:100FB00081B200000400004081B200000400004043 +:100FC00081B200000400004081B200000400004033 +:100FD00081B200000400004081B200000400004023 +:100FE00081B200000400004081B200000400004013 +:100FF00081B200000400004081B200000400004003 +:1010000081B200000400004081B2000004000040F2 +:1010100081B200000400004081B2000004000040E2 +:1010200081B200000400004081B2000004000040D2 +:1010300081B200000400004081B2000004000040C2 +:1010400081B200000400004081B2000004000040B2 +:1010500081B200000400004081B2000004000040A2 +:1010600081B200000400004081B200000400004092 +:1010700081B200000400004081B200000400004082 +:1010800081B200000400004081B200000400004072 +:1010900081B200000400004081B200000400004062 +:1010A00081B200000400004081B200000400004052 +:1010B00081B200000400004081B200000400004042 +:1010C00081B200000400004081B200000400004032 +:1010D00081B200000400004081B200000400004022 +:1010E00081B200000400004081B200000400004012 +:1010F00081B200000400004081B200000400004002 +:1011000081B200000400004081B2000004000040F1 +:1011100081B200000400004081B2000004000040E1 +:1011200081B200000400004081B2000004000040D1 +:1011300081B200000400004081B2000004000040C1 +:1011400081B200000400004081B2000004000040B1 +:1011500081B200000400004081B2000004000040A1 +:1011600081B200000400004081B200000400004091 +:1011700081B200000400004081B200000400004081 +:1011800081B200000400004081B200000400004071 +:1011900081B200000400004081B200000400004061 +:1011A00081B200000400004081B200000400004051 +:1011B00081B200000400004081B200000400004041 +:1011C00081B200000400004081B200000400004031 +:1011D00081B200000400004081B200000400004021 +:1011E00081B200000400004081B200000400004011 +:1011F00081B200000400004081B200000400004001 +:1012000081B200000400004081B2000004000040F0 +:1012100081B200000400004081B2000004000040E0 +:1012200081B200000400004081B2000004000040D0 +:1012300081B200000400004081B2000004000040C0 +:1012400081B200000400004081B2000004000040B0 +:1012500081B200000400004081B2000004000040A0 +:1012600081B200000400004081B200000400004090 +:1012700081B200000400004081B200000400004080 +:1012800081B200000400004081B200000400004070 +:1012900081B200000400004081B200000400004060 +:1012A00081B200000400004081B200000400004050 +:1012B00081B200000400004081B200000400004040 +:1012C00081B200000400004081B200000400004030 +:1012D00081B200000400004081B200000400004020 +:1012E00081B200000400004081B200000400004010 +:1012F00081B200000400004081B200000400004000 +:1013000081B200000400004081B2000004000040EF +:1013100081B200000400004081B2000004000040DF +:1013200081B200000400004081B2000004000040CF +:1013300081B200000400004081B2000004000040BF +:1013400081B200000400004081B2000004000040AF +:1013500081B200000400004081B20000040000409F +:1013600081B200000400004081B20000040000408F +:1013700081B200000400004081B20000040000407F +:1013800081B200000400004081B20000040000406F +:1013900081B200000400004081B20000040000405F +:1013A00081B200000400004081B20000040000404F +:1013B00081B200000400004081B20000040000403F +:1013C00081B200000400004081B20000040000402F +:1013D00081B200000400004081B20000040000401F +:1013E00081B200000400004081B20000040000400F +:1013F00081B200000400004081B2000004000040FF +:1014000081B200000400004081B2000004000040EE +:1014100081B200000400004081B2000004000040DE +:1014200081B200000400004081B2000004000040CE +:1014300081B200000400004081B2000004000040BE +:1014400081B200000400004081B2000004000040AE +:1014500081B200000400004081B20000040000409E +:1014600081B200000400004081B20000040000408E +:1014700081B200000400004081B20000040000407E +:1014800081B200000400004081B20000040000406E +:1014900081B200000400004081B20000040000405E +:1014A00081B200000400004081B20000040000404E +:1014B00081B200000400004081B20000040000403E +:1014C00081B200000400004081B20000040000402E +:1014D00081B200000400004081B20000040000401E +:1014E00081B200000400004081B20000040000400E +:1014F00081B200000400004081B2000004000040FE +:1015000081B200000400004081B2000004000040ED +:1015100081B200000400004081B2000004000040DD +:1015200081B200000400004081B2000004000040CD +:1015300081B200000400004081B2000004000040BD +:1015400081B200000400004081B2000004000040AD +:1015500081B200000400004081B20000040000409D +:1015600081B200000400004081B20000040000408D +:1015700081B200000400004081B20000040000407D +:1015800081B200000400004081B20000040000406D +:1015900081B200000400004081B20000040000405D +:1015A00081B200000400004081B20000040000404D +:1015B00081B200000400004081B20000040000403D +:1015C00081B200000400004081B20000040000402D +:1015D00081B200000400004081B20000040000401D +:1015E00081B200000400004081B20000040000400D +:1015F00081B200000400004081B2000004000040FD +:1016000081B200000400004081B2000004000040EC +:1016100081B200000400004081B2000004000040DC +:1016200081B200000400004081B2000004000040CC +:1016300081B200000400004081B2000004000040BC +:1016400081B200000400004081B2000004000040AC +:1016500081B200000400004081B20000040000409C +:1016600081B200000400004081B20000040000408C +:1016700081B200000400004081B20000040000407C +:1016800081B200000400004081B20000040000406C +:1016900081B200000400004081B20000040000405C +:1016A00081B200000400004081B20000040000404C +:1016B00081B200000400004081B20000040000403C +:1016C00081B200000400004081B20000040000402C +:1016D00081B200000400004081B20000040000401C +:1016E00081B200000400004081B20000040000400C +:1016F00081B200000400004081B2000004000040FC +:1017000081B200000400004081B2000004000040EB +:1017100081B200000400004081B2000004000040DB +:1017200081B200000400004081B2000004000040CB +:1017300081B200000400004081B2000004000040BB +:1017400081B200000400004081B2000004000040AB +:1017500081B200000400004081B20000040000409B +:1017600081B200000400004081B20000040000408B +:1017700081B200000400004081B20000040000407B +:1017800081B200000400004081B20000040000406B +:1017900081B200000400004081B20000040000405B +:1017A00081B200000400004081B20000040000404B +:1017B00081B200000400004081B20000040000403B +:1017C00081B200000400004081B20000040000402B +:1017D00081B200000400004081B20000040000401B +:1017E00081B200000400004081B20000040000400B +:1017F00081B200000400004081B2000004000040FB +:1018000081B200000400004081B2000004000040EA +:1018100081B200000400004081B2000004000040DA +:1018200081B200000400004081B2000004000040CA +:1018300081B200000400004081B2000004000040BA +:1018400081B200000400004081B2000004000040AA +:1018500081B200000400004081B20000040000409A +:1018600081B200000400004081B20000040000408A +:1018700081B200000400004081B20000040000407A +:1018800081B200000400004081B20000040000406A +:1018900081B200000400004081B20000040000405A +:1018A00081B200000400004081B20000040000404A +:1018B00081B200000400004081B20000040000403A +:1018C00081B200000400004081B20000040000402A +:1018D00081B200000400004081B20000040000401A +:1018E00081B200000400004081B20000040000400A +:1018F00081B200000400004081B2000004000040FA +:1019000081B200000400004081B2000004000040E9 +:1019100081B200000400004081B2000004000040D9 +:1019200081B200000400004081B2000004000040C9 +:1019300081B200000400004081B2000004000040B9 +:1019400081B200000400004081B2000004000040A9 +:1019500081B200000400004081B200000400004099 +:1019600081B200000400004081B200000400004089 +:1019700081B200000400004081B200000400004079 +:1019800081B200000400004081B200000400004069 +:1019900081B200000400004081B200000400004059 +:1019A00081B200000400004081B200000400004049 +:1019B00081B200000400004081B200000400004039 +:1019C00081B200000400004081B200000400004029 +:1019D00081B200000400004081B200000400004019 +:1019E00081B200000400004081B200000400004009 +:1019F00081B200000400004081B2000004000040F9 +:101A000081B200000400004081B2000004000040E8 +:101A100081B200000400004081B2000004000040D8 +:101A200081B200000400004081B2000004000040C8 +:101A300081B200000400004081B2000004000040B8 +:101A400081B200000400004081B2000004000040A8 +:101A500081B200000400004081B200000400004098 +:101A600081B200000400004081B200000400004088 +:101A700081B200000400004081B200000400004078 +:101A800081B200000400004081B200000400004068 +:101A900081B200000400004081B200000400004058 +:101AA00081B200000400004081B200000400004048 +:101AB00081B200000400004081B200000400004038 +:101AC00081B200000400004081B200000400004028 +:101AD00081B200000400004081B200000400004018 +:101AE00081B200000400004081B200000400004008 +:101AF00081B200000400004081B2000004000040F8 +:101B000081B200000400004081B2000004000040E7 +:101B100081B200000400004081B2000004000040D7 +:101B200081B200000400004081B2000004000040C7 +:101B300081B200000400004081B2000004000040B7 +:101B400081B200000400004081B2000004000040A7 +:101B500081B200000400004081B200000400004097 +:101B600081B200000400004081B200000400004087 +:101B700081B200000400004081B200000400004077 +:101B800081B200000400004081B200000400004067 +:101B900081B200000400004081B200000400004057 +:101BA00081B200000400004081B200000400004047 +:101BB00081B200000400004081B200000400004037 +:101BC00081B200000400004081B200000400004027 +:101BD00081B200000400004081B200000400004017 +:101BE00081B200000400004081B200000400004007 +:101BF00081B200000400004081B2000004000040F7 +:101C000081B200000400004081B2000004000040E6 +:101C100081B200000400004081B2000004000040D6 +:101C200081B200000400004081B2000004000040C6 +:101C300081B200000400004081B2000004000040B6 +:101C400081B200000400004081B2000004000040A6 +:101C500081B200000400004081B200000400004096 +:101C600081B200000400004081B200000400004086 +:101C700081B200000400004081B200000400004076 +:101C800081B200000400004081B200000400004066 +:101C900081B200000400004081B200000400004056 +:101CA00081B200000400004081B200000400004046 +:101CB00081B200000400004081B200000400004036 +:101CC00081B200000400004081B200000400004026 +:101CD00081B200000400004081B200000400004016 +:101CE00081B200000400004081B200000400004006 +:101CF00081B200000400004081B2000004000040F6 +:101D000081B200000400004081B2000004000040E5 +:101D100081B200000400004081B2000004000040D5 +:101D200081B200000400004081B2000004000040C5 +:101D300081B200000400004081B2000004000040B5 +:101D400081B200000400004081B2000004000040A5 +:101D500081B200000400004081B200000400004095 +:101D600081B200000400004081B200000400004085 +:101D700081B200000400004081B200000400004075 +:101D800081B200000400004081B200000400004065 +:101D900081B200000400004081B200000400004055 +:101DA00081B200000400004081B200000400004045 +:101DB00081B200000400004081B200000400004035 +:101DC00081B200000400004081B200000400004025 +:101DD00081B200000400004081B200000400004015 +:101DE00081B200000400004081B200000400004005 +:101DF00081B200000400004081B2000004000040F5 +:101E000081B200000400004081B2000004000040E4 +:101E100081B200000400004081B2000004000040D4 +:101E200081B200000400004081B2000004000040C4 +:101E300081B200000400004081B2000004000040B4 +:101E400081B200000400004081B2000004000040A4 +:101E500081B200000400004081B200000400004094 +:101E600081B200000400004081B200000400004084 +:101E700081B200000400004081B200000400004074 +:101E800081B200000400004081B200000400004064 +:101E900081B200000400004081B200000400004054 +:101EA00081B200000400004081B200000400004044 +:101EB00081B200000400004081B200000400004034 +:101EC00081B200000400004081B200000400004024 +:101ED00081B200000400004081B200000400004014 +:101EE00081B200000400004081B200000400004004 +:101EF00081B200000400004081B2000004000040F4 +:101F000081B200000400004081B2000004000040E3 +:101F100081B200000400004081B2000004000040D3 +:101F200081B200000400004081B2000004000040C3 +:101F300081B200000400004081B2000004000040B3 +:101F400081B200000400004081B2000004000040A3 +:101F500081B200000400004081B200000400004093 +:101F600081B200000400004081B200000400004083 +:101F700081B200000400004081B200000400004073 +:101F800081B200000400004081B200000400004063 +:101F900081B200000400004081B200000400004053 +:101FA00081B200000400004081B200000400004043 +:101FB00081B200000400004081B200000400004033 +:101FC00081B200000400004081B200000400004023 +:101FD00081B200000400004081B200000400004013 +:101FE00081B200000400004081B200000400004003 +:101FF00081B200000400004081B2000004000040F3 +:1020000081B200000400004081B2000004000040E2 +:1020100081B200000400004081B2000004000040D2 +:1020200081B200000400004081B2000004000040C2 +:1020300081B200000400004081B2000004000040B2 +:1020400081B200000400004081B2000004000040A2 +:1020500081B200000400004081B200000400004092 +:1020600081B200000400004081B200000400004082 +:1020700081B200000400004081B200000400004072 +:1020800081B200000400004081B200000400004062 +:1020900081B200000400004081B200000400004052 +:1020A00081B200000400004081B200000400004042 +:1020B00081B200000400004081B200000400004032 +:1020C00081B200000400004081B200000400004022 +:1020D00081B200000400004081B200000400004012 +:1020E00081B200000400004081B200000400004002 +:1020F00081B200000400004081B2000004000040F2 +:1021000081B200000400004081B2000004000040E1 +:1021100081B200000400004081B2000004000040D1 +:1021200081B200000400004081B2000004000040C1 +:1021300081B200000400004081B2000004000040B1 +:1021400081B200000400004081B2000004000040A1 +:1021500081B200000400004081B200000400004091 +:1021600081B200000400004081B200000400004081 +:1021700081B200000400004081B200000400004071 +:1021800081B200000400004081B200000400004061 +:1021900081B200000400004081B200000400004051 +:1021A00081B200000400004081B200000400004041 +:1021B00081B200000400004081B200000400004031 +:1021C00081B200000400004081B200000400004021 +:1021D00081B200000400004081B200000400004011 +:1021E00081B200000400004081B200000400004001 +:1021F00081B200000400004081B2000004000040F1 +:1022000081B200000400004081B2000004000040E0 +:1022100081B200000400004081B2000004000040D0 +:1022200081B200000400004081B2000004000040C0 +:1022300081B200000400004081B2000004000040B0 +:1022400081B200000400004081B2000004000040A0 +:1022500081B200000400004081B200000400004090 +:1022600081B200000400004081B200000400004080 +:1022700081B200000400004081B200000400004070 +:1022800081B200000400004081B200000400004060 +:1022900081B200000400004081B200000400004050 +:1022A00081B200000400004081B200000400004040 +:1022B00081B200000400004081B200000400004030 +:1022C00081B200000400004081B200000400004020 +:1022D00081B200000400004081B200000400004010 +:1022E00081B200000400004081B200000400004000 +:1022F00081B200000400004081B2000004000040F0 +:1023000081B200000400004081B2000004000040DF +:1023100081B200000400004081B2000004000040CF +:1023200081B200000400004081B2000004000040BF +:1023300081B200000400004081B2000004000040AF +:1023400081B200000400004081B20000040000409F +:1023500081B200000400004081B20000040000408F +:1023600081B200000400004081B20000040000407F +:1023700081B200000400004081B20000040000406F +:1023800081B200000400004081B20000040000405F +:1023900081B200000400004081B20000040000404F +:1023A00081B200000400004081B20000040000403F +:1023B00081B200000400004081B20000040000402F +:1023C00081B200000400004081B20000040000401F +:1023D00081B200000400004081B20000040000400F +:1023E00081B200000400004081B2000004000040FF +:1023F00081B200000400004081B2000004000040EF +:1024000081B200000400004081B2000004000040DE +:1024100081B200000400004081B2000004000040CE +:1024200081B200000400004081B2000004000040BE +:1024300081B200000400004081B2000004000040AE +:1024400081B200000400004081B20000040000409E +:1024500081B200000400004081B20000040000408E +:1024600081B200000400004081B20000040000407E +:1024700081B200000400004081B20000040000406E +:1024800081B200000400004081B20000040000405E +:1024900081B200000400004081B20000040000404E +:1024A00081B200000400004081B20000040000403E +:1024B00081B200000400004081B20000040000402E +:1024C00081B200000400004081B20000040000401E +:1024D00081B200000400004081B20000040000400E +:1024E00081B200000400004081B2000004000040FE +:1024F00081B200000400004081B2000004000040EE +:1025000081B200000400004081B2000004000040DD +:1025100081B200000400004081B2000004000040CD +:1025200081B200000400004081B2000004000040BD +:1025300081B200000400004081B2000004000040AD +:1025400081B200000400004081B20000040000409D +:1025500081B200000400004081B20000040000408D +:1025600081B200000400004081B20000040000407D +:1025700081B200000400004081B20000040000406D +:1025800081B200000400004081B20000040000405D +:1025900081B200000400004081B20000040000404D +:1025A00081B200000400004081B20000040000403D +:1025B00081B200000400004081B20000040000402D +:1025C00081B200000400004081B20000040000401D +:1025D00081B200000400004081B20000040000400D +:1025E00081B200000400004081B2000004000040FD +:1025F00081B200000400004081B2000004000040ED +:1026000081B200000400004081B2000004000040DC +:1026100081B200000400004081B2000004000040CC +:1026200081B200000400004081B2000004000040BC +:1026300081B200000400004081B2000004000040AC +:1026400081B200000400004081B20000040000409C +:1026500081B200000400004081B20000040000408C +:1026600081B200000400004081B20000040000407C +:1026700081B200000400004081B20000040000406C +:1026800081B200000400004081B20000040000405C +:1026900081B200000400004081B20000040000404C +:1026A00081B200000400004081B20000040000403C +:1026B00081B200000400004081B20000040000402C +:1026C00081B200000400004081B20000040000401C +:1026D00081B200000400004081B20000040000400C +:1026E00081B200000400004081B2000004000040FC +:1026F00081B200000400004081B2000004000040EC +:1027000081B200000400004081B2000004000040DB +:1027100081B200000400004081B2000004000040CB +:1027200081B200000400004081B2000004000040BB +:1027300081B200000400004081B2000004000040AB +:1027400081B200000400004081B20000040000409B +:1027500081B200000400004081B20000040000408B +:1027600081B200000400004081B20000040000407B +:1027700081B200000400004081B20000040000406B +:1027800081B200000400004081B20000040000405B +:1027900081B200000400004081B20000040000404B +:1027A00081B200000400004081B20000040000403B +:1027B00081B200000400004081B20000040000402B +:1027C00081B200000400004081B20000040000401B +:1027D00081B200000400004081B20000040000400B +:1027E00081B200000400004081B2000004000040FB +:1027F00081B200000400004081B2000004000040EB +:1028000081B200000400004081B2000004000040DA +:1028100081B200000400004081B2000004000040CA +:1028200081B200000400004081B2000004000040BA +:1028300081B200000400004081B2000004000040AA +:1028400081B200000400004081B20000040000409A +:1028500081B200000400004081B20000040000408A +:1028600081B200000400004081B20000040000407A +:1028700081B200000400004081B20000040000406A +:1028800081B200000400004081B20000040000405A +:1028900081B200000400004081B20000040000404A +:1028A00081B200000400004081B20000040000403A +:1028B00081B200000400004081B20000040000402A +:1028C00081B200000400004081B20000040000401A +:1028D00081B200000400004081B20000040000400A +:1028E00081B200000400004081B2000004000040FA +:1028F00081B200000400004081B2000004000040EA +:1029000081B200000400004081B2000004000040D9 +:1029100081B200000400004081B2000004000040C9 +:1029200081B200000400004081B2000004000040B9 +:1029300081B200000400004081B2000004000040A9 +:1029400081B200000400004081B200000400004099 +:1029500081B200000400004081B200000400004089 +:1029600081B200000400004081B200000400004079 +:1029700081B200000400004081B200000400004069 +:1029800081B200000400004081B200000400004059 +:1029900081B200000400004081B200000400004049 +:1029A00081B200000400004081B200000400004039 +:1029B00081B200000400004081B200000400004029 +:1029C00081B200000400004081B200000400004019 +:1029D00081B200000400004081B200000400004009 +:1029E00081B200000400004081B2000004000040F9 +:1029F00081B200000400004081B2000004000040E9 +:102A000081B200000400004081B2000004000040D8 +:102A100081B200000400004081B2000004000040C8 +:102A200081B200000400004081B2000004000040B8 +:102A300081B200000400004081B2000004000040A8 +:102A400081B200000400004081B200000400004098 +:102A500081B200000400004081B200000400004088 +:102A600081B200000400004081B200000400004078 +:102A700081B200000400004081B200000400004068 +:102A800081B200000400004081B200000400004058 +:102A900081B200000400004081B200000400004048 +:102AA00081B200000400004081B200000400004038 +:102AB00081B200000400004081B200000400004028 +:102AC00081B200000400004081B200000400004018 +:102AD00081B200000400004081B200000400004008 +:102AE00081B200000400004081B2000004000040F8 +:102AF00081B200000400004081B2000004000040E8 +:102B000081B200000400004081B2000004000040D7 +:102B100081B200000400004081B2000004000040C7 +:102B200081B200000400004081B2000004000040B7 +:102B300081B200000400004081B2000004000040A7 +:102B400081B200000400004081B200000400004097 +:102B500081B200000400004081B200000400004087 +:102B600081B200000400004081B200000400004077 +:102B700081B200000400004081B200000400004067 +:102B800081B200000400004081B200000400004057 +:102B900081B200000400004081B200000400004047 +:102BA00081B200000400004081B200000400004037 +:102BB00081B200000400004081B200000400004027 +:102BC00081B200000400004081B200000400004017 +:102BD00081B200000400004081B200000400004007 +:102BE00081B200000400004081B2000004000040F7 +:102BF00081B200000400004081B2000004000040E7 +:102C000081B200000400004081B2000004000040D6 +:102C100081B200000400004081B2000004000040C6 +:102C200081B200000400004081B2000004000040B6 +:102C300081B200000400004081B2000004000040A6 +:102C400081B200000400004081B200000400004096 +:102C500081B200000400004081B200000400004086 +:102C600081B200000400004081B200000400004076 +:102C700081B200000400004081B200000400004066 +:102C800081B200000400004081B200000400004056 +:102C900081B200000400004081B200000400004046 +:102CA00081B200000400004081B200000400004036 +:102CB00081B200000400004081B200000400004026 +:102CC00081B200000400004081B200000400004016 +:102CD00081B200000400004081B200000400004006 +:102CE00081B200000400004081B2000004000040F6 +:102CF00081B200000400004081B2000004000040E6 +:102D000081B200000400004081B2000004000040D5 +:102D100081B200000400004081B2000004000040C5 +:102D200081B200000400004081B2000004000040B5 +:102D300081B200000400004081B2000004000040A5 +:102D400081B200000400004081B200000400004095 +:102D500081B200000400004081B200000400004085 +:102D600081B200000400004081B200000400004075 +:102D700081B200000400004081B200000400004065 +:102D800081B200000400004081B200000400004055 +:102D900081B200000400004081B200000400004045 +:102DA00081B200000400004081B200000400004035 +:102DB00081B200000400004081B200000400004025 +:102DC00081B200000400004081B200000400004015 +:102DD00081B200000400004081B200000400004005 +:102DE00081B200000400004081B2000004000040F5 +:102DF00081B200000400004081B2000004000040E5 +:102E000081B200000400004081B2000004000040D4 +:102E100081B200000400004081B2000004000040C4 +:102E200081B200000400004081B2000004000040B4 +:102E300081B200000400004081B2000004000040A4 +:102E400081B200000400004081B200000400004094 +:102E500081B200000400004081B200000400004084 +:102E600081B200000400004081B200000400004074 +:102E700081B200000400004081B200000400004064 +:102E800081B200000400004081B200000400004054 +:102E900081B200000400004081B200000400004044 +:102EA00081B200000400004081B200000400004034 +:102EB00081B200000400004081B200000400004024 +:102EC00081B200000400004081B200000400004014 +:102ED00081B200000400004081B200000400004004 +:102EE00081B200000400004081B2000004000040F4 +:102EF00081B200000400004081B2000004000040E4 +:102F000081B200000400004081B2000004000040D3 +:102F100081B200000400004081B2000004000040C3 +:102F200081B200000400004081B2000004000040B3 +:102F300081B200000400004081B2000004000040A3 +:102F400081B200000400004081B200000400004093 +:102F500081B200000400004081B200000400004083 +:102F600081B200000400004081B200000400004073 +:102F700081B200000400004081B200000400004063 +:102F800081B200000400004081B200000400004053 +:102F900081B200000400004081B200000400004043 +:102FA00081B200000400004081B200000400004033 +:102FB00081B200000400004081B200000400004023 +:102FC00081B200000400004081B200000400004013 +:102FD00081B200000400004081B200000400004003 +:102FE00081B200000400004081B2000004000040F3 +:102FF00081B200000400004081B2000004000040E3 +:1030000081B200000400004081B2000004000040D2 +:1030100081B200000400004081B2000004000040C2 +:1030200081B200000400004081B2000004000040B2 +:1030300081B200000400004081B2000004000040A2 +:1030400081B200000400004081B200000400004092 +:1030500081B200000400004081B200000400004082 +:1030600081B200000400004081B200000400004072 +:1030700081B200000400004081B200000400004062 +:1030800081B200000400004081B200000400004052 +:1030900081B200000400004081B200000400004042 +:1030A00081B200000400004081B200000400004032 +:1030B00081B200000400004081B200000400004022 +:1030C00081B200000400004081B200000400004012 +:1030D00081B200000400004081B200000400004002 +:1030E00081B200000400004081B2000004000040F2 +:1030F00081B200000400004081B2000004000040E2 +:1031000081B200000400004081B2000004000040D1 +:1031100081B200000400004081B2000004000040C1 +:1031200081B200000400004081B2000004000040B1 +:1031300081B200000400004081B2000004000040A1 +:1031400081B200000400004081B200000400004091 +:1031500081B200000400004081B200000400004081 +:1031600081B200000400004081B200000400004071 +:1031700081B200000400004081B200000400004061 +:1031800081B200000400004081B200000400004051 +:1031900081B200000400004081B200000400004041 +:1031A00081B200000400004081B200000400004031 +:1031B00081B200000400004081B200000400004021 +:1031C00081B200000400004081B200000400004011 +:1031D00081B200000400004081B200000400004001 +:1031E00081B200000400004081B2000004000040F1 +:1031F00081B200000400004081B2000004000040E1 +:1032000081B200000400004081B2000004000040D0 +:1032100081B200000400004081B2000004000040C0 +:1032200081B200000400004081B2000004000040B0 +:1032300081B200000400004081B2000004000040A0 +:1032400081B200000400004081B200000400004090 +:1032500081B200000400004081B200000400004080 +:1032600081B200000400004081B200000400004070 +:1032700081B200000400004081B200000400004060 +:1032800081B200000400004081B200000400004050 +:1032900081B200000400004081B200000400004040 +:1032A00081B200000400004081B200000400004030 +:1032B00081B200000400004081B200000400004020 +:1032C00081B200000400004081B200000400004010 +:1032D00081B200000400004081B200000400004000 +:1032E00081B200000400004081B2000004000040F0 +:1032F00081B200000400004081B2000004000040E0 +:1033000081B200000400004081B2000004000040CF +:1033100081B200000400004081B2000004000040BF +:1033200081B200000400004081B2000004000040AF +:1033300081B200000400004081B20000040000409F +:1033400081B200000400004081B20000040000408F +:1033500081B200000400004081B20000040000407F +:1033600081B200000400004081B20000040000406F +:1033700081B200000400004081B20000040000405F +:1033800081B200000400004081B20000040000404F +:1033900081B200000400004081B20000040000403F +:1033A00081B200000400004081B20000040000402F +:1033B00081B200000400004081B20000040000401F +:1033C00081B200000400004081B20000040000400F +:1033D00081B200000400004081B2000004000040FF +:1033E00081B200000400004081B2000004000040EF +:1033F00081B200000400004081B2000004000040DF +:1034000081B200000400004081B2000004000040CE +:1034100081B200000400004081B2000004000040BE +:1034200081B200000400004081B2000004000040AE +:1034300081B200000400004081B20000040000409E +:1034400081B200000400004081B20000040000408E +:1034500081B200000400004081B20000040000407E +:1034600081B200000400004081B20000040000406E +:1034700081B200000400004081B20000040000405E +:1034800081B200000400004081B20000040000404E +:1034900081B200000400004081B20000040000403E +:1034A00081B200000400004081B20000040000402E +:1034B00081B200000400004081B20000040000401E +:1034C00081B200000400004081B20000040000400E +:1034D00081B200000400004081B2000004000040FE +:1034E00081B200000400004081B2000004000040EE +:1034F00081B200000400004081B2000004000040DE +:1035000081B200000400004081B2000004000040CD +:1035100081B200000400004081B2000004000040BD +:1035200081B200000400004081B2000004000040AD +:1035300081B200000400004081B20000040000409D +:1035400081B200000400004081B20000040000408D +:1035500081B200000400004081B20000040000407D +:1035600081B200000400004081B20000040000406D +:1035700081B200000400004081B20000040000405D +:1035800081B200000400004081B20000040000404D +:1035900081B200000400004081B20000040000403D +:1035A00081B200000400004081B20000040000402D +:1035B00081B200000400004081B20000040000401D +:1035C00081B200000400004081B20000040000400D +:1035D00081B200000400004081B2000004000040FD +:1035E00081B200000400004081B2000004000040ED +:1035F00081B200000400004081B2000004000040DD +:1036000081B200000400004081B2000004000040CC +:1036100081B200000400004081B2000004000040BC +:1036200081B200000400004081B2000004000040AC +:1036300081B200000400004081B20000040000409C +:1036400081B200000400004081B20000040000408C +:1036500081B200000400004081B20000040000407C +:1036600081B200000400004081B20000040000406C +:1036700081B200000400004081B20000040000405C +:1036800081B200000400004081B20000040000404C +:1036900081B200000400004081B20000040000403C +:1036A00081B200000400004081B20000040000402C +:1036B00081B200000400004081B20000040000401C +:1036C00081B200000400004081B20000040000400C +:1036D00081B200000400004081B2000004000040FC +:1036E00081B200000400004081B2000004000040EC +:1036F00081B200000400004081B2000004000040DC +:1037000081B200000400004081B2000004000040CB +:1037100081B200000400004081B2000004000040BB +:1037200081B200000400004081B2000004000040AB +:1037300081B200000400004081B20000040000409B +:1037400081B200000400004081B20000040000408B +:1037500081B200000400004081B20000040000407B +:1037600081B200000400004081B20000040000406B +:1037700081B200000400004081B20000040000405B +:1037800081B200000400004081B20000040000404B +:1037900081B200000400004081B20000040000403B +:1037A00081B200000400004081B20000040000402B +:1037B00081B200000400004081B20000040000401B +:1037C00081B200000400004081B20000040000400B +:1037D00081B200000400004081B2000004000040FB +:1037E00081B200000400004081B2000004000040EB +:1037F00081B200000400004081B2000004000040DB +:1038000081B200000400004081B2000004000040CA +:1038100081B200000400004081B2000004000040BA +:1038200081B200000400004081B2000004000040AA +:1038300081B200000400004081B20000040000409A +:1038400081B200000400004081B20000040000408A +:1038500081B200000400004081B20000040000407A +:1038600081B200000400004081B20000040000406A +:1038700081B200000400004081B20000040000405A +:1038800081B200000400004081B20000040000404A +:1038900081B200000400004081B20000040000403A +:1038A00081B200000400004081B20000040000402A +:1038B00081B200000400004081B20000040000401A +:1038C00081B200000400004081B20000040000400A +:1038D00081B200000400004081B2000004000040FA +:1038E00081B200000400004081B2000004000040EA +:1038F00081B200000400004081B2000004000040DA +:1039000081B200000400004081B2000004000040C9 +:1039100081B200000400004081B2000004000040B9 +:1039200081B200000400004081B2000004000040A9 +:1039300081B200000400004081B200000400004099 +:1039400081B200000400004081B200000400004089 +:1039500081B200000400004081B200000400004079 +:1039600081B200000400004081B200000400004069 +:1039700081B200000400004081B200000400004059 +:1039800081B200000400004081B200000400004049 +:1039900081B200000400004081B200000400004039 +:1039A00081B200000400004081B200000400004029 +:1039B00081B200000400004081B200000400004019 +:1039C00081B200000400004081B200000400004009 +:1039D00081B200000400004081B2000004000040F9 +:1039E00081B200000400004081B2000004000040E9 +:1039F00081B200000400004081B2000004000040D9 +:103A000081B200000400004081B2000004000040C8 +:103A100081B200000400004081B2000004000040B8 +:103A200081B200000400004081B2000004000040A8 +:103A300081B200000400004081B200000400004098 +:103A400081B200000400004081B200000400004088 +:103A500081B200000400004081B200000400004078 +:103A600081B200000400004081B200000400004068 +:103A700081B200000400004081B200000400004058 +:103A800081B200000400004081B200000400004048 +:103A900081B200000400004081B200000400004038 +:103AA00081B200000400004081B200000400004028 +:103AB00081B200000400004081B200000400004018 +:103AC00081B200000400004081B200000400004008 +:103AD00081B200000400004081B2000004000040F8 +:103AE00081B200000400004081B2000004000040E8 +:103AF00081B200000400004081B2000004000040D8 +:103B000081B200000400004081B2000004000040C7 +:103B100081B200000400004081B2000004000040B7 +:103B200081B200000400004081B2000004000040A7 +:103B300081B200000400004081B200000400004097 +:103B400081B200000400004081B200000400004087 +:103B500081B200000400004081B200000400004077 +:103B600081B200000400004081B200000400004067 +:103B700081B200000400004081B200000400004057 +:103B800081B200000400004081B200000400004047 +:103B900081B200000400004081B200000400004037 +:103BA00081B200000400004081B200000400004027 +:103BB00081B200000400004081B200000400004017 +:103BC00081B200000400004081B200000400004007 +:103BD00081B200000400004081B2000004000040F7 +:103BE00081B200000400004081B2000004000040E7 +:103BF00081B200000400004081B2000004000040D7 +:103C000081B200000400004081B2000004000040C6 +:103C100081B200000400004081B2000004000040B6 +:103C200081B200000400004081B2000004000040A6 +:103C300081B200000400004081B200000400004096 +:103C400081B200000400004081B200000400004086 +:103C500081B200000400004081B200000400004076 +:103C600081B200000400004081B200000400004066 +:103C700081B200000400004081B200000400004056 +:103C800081B200000400004081B200000400004046 +:103C900081B200000400004081B200000400004036 +:103CA00081B200000400004081B200000400004026 +:103CB00081B200000400004081B200000400004016 +:103CC00081B200000400004081B200000400004006 +:103CD00081B200000400004081B2000004000040F6 +:103CE00081B200000400004081B2000004000040E6 +:103CF00081B200000400004081B2000004000040D6 +:103D000081B200000400004081B2000004000040C5 +:103D100081B200000400004081B2000004000040B5 +:103D200081B200000400004081B2000004000040A5 +:103D300081B200000400004081B200000400004095 +:103D400081B200000400004081B200000400004085 +:103D500081B20000AE9F00889AB00000AE9F00883C +:103D60009AB00000AE9F00889AB00000AE9F008815 +:103D70009AB00000AE9F00889AB000000000008852 +:103D80009AB00100AE9F414081320000B29F2240B4 +:103D90007B6F00000000194081B20100AE9F00401F +:103DA00081B20000000019417BB30100000000A4B3 +:103DB000C4B30100000000A1C6B3010000002FA29F +:103DC000C8B301000814004049990100A89F004DA4 +:103DD0009ACC0100BB9F2640813200000000004CBD +:103DE00049C10100B99FA2419B500000BF9F808044 +:103DF0008032000000005249FD9301000000004A9B +:103E0000FD930100C29F0042CD9300000000514A83 +:103E1000FD93010000000049FD930100C29F004393 +:103E2000CB9300000000504081B20100D29F0040BF +:103E300019990100000000F09AB001000000004450 +:103E400049D10100000040F080B201000000414D66 +:103E500080B20100CA9F00401999010000004C4047 +:103E600081B201000000004449D10100000000F0CF +:103E70009AB001000000004D10B10000000000E207 +:103E800049B10100000000E343B10100000000E47B +:103E900045B10100000000407BB301000000484F25 +:103EA00040B10100D29F004081B2000004000040F8 +:103EB00081B200000400004081B200000400004014 +:103EC00081B200000400004081B200000400004004 +:103ED00081B20000040000CB81C80100F4820040E0 +:103EE000F29300004082004081B200004005004093 +:103EF00081B200001806004081B20000F482004048 +:103F000081B20000AF82004081B2000038810040E1 +:103F100081B200003681004081B20000B8800040CC +:103F200081B200001A87004081B20000AF820040D9 +:103F300081B20000F582004081B20000AB920040E7 +:103F400081B20000F095004081B200007392004001 +:103F500081B20000DF95004081B200004A9300402A +:103F600081B20000ED92004081B20000E792004073 +:103F700081B200009A82004081B2000000008040BF +:103F800081B201000400004081B200000400004042 +:103F900081B200000400004081B200000400004033 +:103FA00081B200000400004081B200000400004023 +:103FB00081B200000400004081B200000400004013 +:103FC00081B200000400004081B200000400004003 +:103FD00081B200000400004081B2000004000040F3 +:103FE00081B200000400004081B2000004000040E3 +:103FF00081B200000400004081B2000004000040D3 +:1040000081B200000400004081B2000004000040C2 +:0440100081B2000079 +:00000001FF diff --git a/firmware/slicoss/oasisrcvucode.sys.ihex b/firmware/slicoss/oasisrcvucode.sys.ihex new file mode 100644 index 000000000000..813bea4e133e --- /dev/null +++ b/firmware/slicoss/oasisrcvucode.sys.ihex @@ -0,0 +1,162 @@ +:10000000000200004775010004A01301001CB75B4B +:10001000093000B65F01001C00000020183B783A50 +:10002000001CA27701001C071D017018AD7BF1FFB9 +:100030001CB37BA9AA1EB47B010C1CB57B0D061C4E +:1000400000003064080C315A70040C315A80040CE2 +:10005000314E90040C314AA000092555C0040C31E2 +:1000600052B000E92455C004CCB3001C1CEB2D0198 +:10007000001C065632D408079D00001C7BB7020006 +:1000800010A00F31540906565EC004A0305403007E +:10009000AC30550300CD033A001C7BB702001C6056 +:1000A0008E3154092925550300808E3154098C3036 +:1000B000910004471C01001CA00F3154090000648A +:1000C0000004471C65C004471C5503006C30010048 +:1000D0001C4D3402001C7BB702001CA00F315409D8 +:1000E000C88337001C800100001C0000640004A0CD +:1000F0000F305409000054C3047BFBF2001CCC33C6 +:100100000D001CB47BFD031C800E305409E0FB0580 +:10011000001C00008C0300B30F3154090000EC7088 +:10012000040000EC800400008C930061768DC30411 +:10013000C08D315409E07B00C01FA0FDC50100CC7B +:100140003305001CD403003C1CD4D31B001CC0D3BB +:1001500052001C00005C13048E8E3254095B805EDA +:100160001304000000001C0000940100A00F315493 +:1001700009A00F315409C003FC7F1CA001A001009D +:100180000000A40100A00F315409C003FC031CF5BA +:100190007701001C267AE6051CA00F315409B30F25 +:1001A000315409B50202001CA00F3154097A7E02B5 +:1001B000001CB50202001C530F325409AF030100AA +:1001C0001C7A0E325409B50202001C000002001C09 +:1001D000A03DAA11040000AC1104D4D352001CB5F8 +:1001E0003EB2010020FBFDFF1F802C6C0300B93ADA +:1001F0009E0100753B02001CA71C010010DB83164A +:10020000001CC71D21C104B93B8DC1048B2C01000A +:100210001C6B2C35C1040000781100CB2C79C10473 +:10022000A00F315409A00F31540954D002001C49C9 +:1002300025B10100AB2C81C104A71D550300CC33AF +:1002400009001CEB2D01001CEA2901001CA00F3144 +:100250005409AE0F315409A00F315409D407FC03DF +:100260001C993A02001CBB3802001C003800001C1C +:100270000000FC0104DB3B7E001CC71D01001C26A6 +:100280007AFA051C271D01001CB30F3154097A0EA0 +:10029000325409530F3254097A0E325409530F3233 +:1002A00054097A0E325409530F325409A00F3154B5 +:1002B000097A0602001C530F325409AF0301001CD7 +:1002C0007A0E325409530F3254097A0E32540953BC +:1002D0000F3254097A0E325409530F3254097A0EF0 +:1002E000325409003D02001C0000581200CB2C01C2 +:1002F000001C753B02001CA71C010010CB2F050041 +:100300001C602C00001CC71CC90200A00F3154093E +:10031000530702001C467ACA051C7A0E3254094063 +:10032000FA19001C0000880204467ACA051CA00FB6 +:10033000315409A00F315409A00F315409A00F31D5 +:100340005409B37B01C01F740E305409C0039C00D4 +:100350001C8000D802000000D802040000AC120586 +:10036000071D01001CD4D32B001CD4D352001C80C9 +:10037000767D13040000E00200A67B950310C79C65 +:1003800000001C802C00001C00006C0204000054C3 +:10039000C304AB2DD91205071DB5C2048B2D010076 +:1003A0001C692501001CA67B950310CB2F09001C9E +:1003B000602C00001C0000480300530F3254094613 +:1003C0007ACA051C7A0E32540940FA19001C000042 +:1003D000100304467ACA051CB50F315409A00F3129 +:1003E000540973EC2A0304602C00001C000028034D +:1003F00000C71C01001C0000281305071D01001C7C +:10040000C0D722001C75567E1304602C00001CE728 +:100410001C450304E79C00001CA67B950310802C60 +:1004200000001C0000F80204000054C304B97B0162 +:10043000001C00008CC304CBAFFC071CCB2F0104B5 +:100440001CC79F80031C00008CC304CBAFFC071C9F +:10045000CB2F0D041CC79F80031C00008CC304CB52 +:10046000AF00F81DCB2F01001DA67B95031CC79C78 +:100470008CC30400008C1305071D01001CC01DDC8B +:10048000D308279DE40300A0EE46D400FB750914B1 +:1004900004207B06001CC01C1C04000000B0D30814 +:1004A000000000F400C0EFF2001C20255C14046082 +:1004B000B7D2030000000C1500CCB3FC031CCC33F6 +:1004C00005021C00000CC50460B70E050400000CFA +:1004D000150400005CC404C01D98F304000068C447 +:1004E00004079D00001C1B74FDF304A67BF1031C94 +:1004F000A00F695409E07B00FC1F397F02001C0734 +:100500001D9DC304A67BAD031C000068C404E01C51 +:1005100000001C0000A40304CBAF00F81DCB2F018A +:10052000101D0000ACC3040000AC0304CBAF00F806 +:100530001DCB2F01181DC79F000B1C0000ACC3046E +:10054000FB7501001C071D01001CCCB3FC031CCC77 +:100550003301021C0000ACC304A01C00001CA0EE70 +:10056000A20304CBAFFC071CCB2F09041CFB7501B5 +:10057000001C0000ACC304CCB3FC031CCC33010250 +:100580001C00000CC5040000783405CCB3FC031C2F +:10059000CC3315021C479D54C404000078440080ED +:1005A0001D7C5404871D8D0400CE7601001CEF765F +:1005B0009DC404A4778D2409E47601001CC476014F +:1005C000001C0000985404D776015018F6760100FC +:1005D0001C00000030180000000010CC3045C5049D +:1005E000EB2D01001CEA2901001CC05901001CF57B +:1005F0007729C504E030DC0400004CB00400204C36 +:10060000F404000000E80400CCB3FC031CCC330964 +:10061000021CEB2DB5C404CCB3FC031CCC33190273 +:100620001CEB2DB5C404CCB3FC031CCC330D021C55 +:10063000EB2DB5C404CCB3FC031CCC3311021CEB72 +:100640002DB5C404007B00801CAE7745050000007A +:1006500004C004D38B00FC1F607A3C001C604CC0BB +:100660000400C02F20051FE030B004008025B00436 +:1006700000B55BB10404692601001C6A2B01001C53 +:10068000801D00001CA925450500EE3000001CAFB0 +:10069000770105000000AC2404B45F014018079DF9 +:1006A000485504B77601001C967601001C471D01D1 +:1006B000001CA433016018A42F0160186477016046 +:1006C000182477016018447701001C648803001C1B +:1006D000A43F01001CA43B01001C537B00C01CD3A1 +:1006E000CF1B001C534F02001CDACF00C01FD55790 +:1006F0000F001CD3D337001CD4530F001CE029007B +:10070000001CF5D5B0050000009C5504775601008B +:100710001C565301001C0000001018000004C00407 +:10072000F55501001C0000B45504775601001C5615 +:100730005301001C0000001018000004C004CB2F5F +:10074000011810CB2F011010CB2F010810CB2F0157 +:100750000810CB2F012010CB2F012810CB2F010028 +:1007600010892561C2040000ECC204000054C304D7 +:10077000000054C304000054C304000060C204001D +:1007800000ECC204000054C304000054C304000081 +:1007900054C304401C6CC004401C9CC004A7775583 +:1007A000C3040000C4C004271DF1C004000054C3EA +:1007B00004000054C304000054C30400002CC60409 +:1007C00000002CC60400002CC60400002CC6040047 +:1007D000002CC60400002CC60400002CC604000037 +:1007E0002CC60400002CC60400002CC60400002CFB +:1007F000C60400002CC60400002CC60400002CC651 +:100800000400002CC60400002CC60400002CC60402 +:1008100000002CC60400002CC60400002CC60400F6 +:10082000002CC60400002CC60400002CC6040000E6 +:100830002CC60400002CC60400002CC60400002CAA +:10084000C60400002CC60400002CC60400002CC600 +:100850000400002CC60400002CC60400002CC604B2 +:1008600000002CC60400002CC60400002CC60400A6 +:10087000002CC60400002CC60400002CC604000096 +:100880002CC60400002CC60400002CC60400002C5A +:10089000C60400002CC60400002CC60400002CC6B0 +:1008A0000400002CC60400002CC60400002CC60462 +:1008B00000002CC60400002CC60400002CC6040056 +:1008C000002CC60400002CC60400002CC604000046 +:1008D0002CC60400002CC60400002CC60400002C0A +:1008E000C60400002CC60400002CC60400002CC660 +:1008F0000400002CC60400002CC60400002CC60412 +:1009000000002CC60400002CC60400002CC6040005 +:10091000002CC60400002CC60400002CC6040000F5 +:100920002CC60400002CC60400002CC60400002CB9 +:10093000C60400002CC60400002CC60400002CC60F +:100940000400002CC60400002CC60400002CC604C1 +:1009500000002CC60400002CC60400002CC60400B5 +:10096000002CC60400002CC60400002CC6040000A5 +:100970002CC60400002CC60400002CC60400002C69 +:10098000C60400002CC60400002CC60400002CC6BF +:100990000400002CC60400002CC60400002CC60471 +:1009A00000002CC60400002CC60400002CC6040065 +:1009B000002CC60400002CC60400002CC604000055 +:1009C0002CC60400002CC60400002CC60400002C19 +:1009D000C60400002CC60400002CC60400002CC66F +:1009E0000400002CC60400002CC60400002CC60421 +:1009F00000002CC60400002CC60400002CC6040015 +:040A0000002CC604FC +:00000001FF diff --git a/firmware/sxg/saharadbgdownloadB.sys.ihex b/firmware/sxg/saharadbgdownloadB.sys.ihex new file mode 100644 index 000000000000..e3016d34feee --- /dev/null +++ b/firmware/sxg/saharadbgdownloadB.sys.ihex @@ -0,0 +1,3937 @@ +:1000000002000000DCF500000C0000000000000011 +:10001000FF1F00000100000000000088824D293A07 +:1000200000000404000000800200009000000900AD +:100030000000008002000090000009000000008025 +:100040000200009000000900000000800200009003 +:10005000000009000000008002000090000009007C +:1000600000000080020000900000090000000080F5 +:1000700002000090000009000000008002000090D3 +:10008000FEFF0000000000AC020036320000360027 +:10009000000000A80200009200001613000000807B +:1000A0000200009000001613000000800200009083 +:1000B00000001613000000800200009000001613DC +:1000C0000000008002000090000016130000008075 +:1000D0000200009000002000000000D80F8028924D +:1000E00000002100000000D80F80289200002200AC +:1000F000000000D80F80289200002300000000D8E4 +:100100000F402B9200002400000000D80F8028929E +:1001100000002500000000D80F8028920000260073 +:10012000000000D80F80289200002700000000D8AF +:100130000F80289200002800000000D80F8028922D +:1001400000002900000000D80F80289200002A003B +:10015000000000D80F8028920000360000000098B0 +:100160001E80E99A00002C00000000D80F80289221 +:1001700000002D00000000D80F80289200002E0003 +:10018000000000D80F80289200002F00000000D847 +:100190000F80289200003000000000D40F00009271 +:1001A00000003000000000D40F400092000030003A +:1001B000000000D40F80009200003400000000D442 +:1001C0000FC0009200003000000000D40F00019228 +:1001D00000003000000000D40F4001920000300009 +:1001E000000000D40F80019200003000000000D415 +:1001F0000FC0019200003000000000D40F000292F6 +:1002000000003000000000D40F40029200003000D7 +:10021000000000D40F80029200001613000000803E +:100220000200009000003000000000D40F00039294 +:1002300000003000000000D40F40039200003000A6 +:10024000000000D40F80039200003000000000D4B2 +:100250000FC0039200000000000000D05F3F003498 +:10026000000016130400008042FFFCB000000000F4 +:10027000000000881280FD3A000016130000008084 +:10028000020000901613161302010080828DFDBC3F +:1002900000000000000000881280FD3A000000000D +:1002A000000000F803C001323800000000010084A3 +:1002B000824D281A000036000000007409400092A8 +:1002C00000004F00000000FC020000920000480007 +:1002D000000000800200009000004D00000000902F +:1002E0000E80189200001B030000000008C020923E +:1002F000000089000000000008002192000019039E +:10030000000000000840219200008600000000006C +:100310000885219000009B03000000EC02C022929F +:1003200000009404000000800200009000005800CB +:10033000000000FC0240189D00005100000000D0A9 +:10034000020000920000E003000000800200009024 +:100350000000161300000080020000900000000062 +:10036000000100800200007000004C00000000004E +:1003700009C0219200004A0012010000088522B045 +:1003800018003600000000F8738A029900008E0001 +:100390006A000080020000B008008E00000000F833 +:1003A0002340019900000000000100E80200907263 +:1003B0000000161380010080B200E9B600000204BC +:1003C0000000007C1EC0E79A08000000000000F852 +:1003D000134001390000F60300000008B801009442 +:1003E000000016130300007809401ABD0000161320 +:1003F00004010080E28097BC00000000000000A023 +:10040000E125003408000000000000F8B340013985 +:1004100000000204B20000D8020000B2000016136F +:1004200017010080020000B000001F06001001F854 +:1004300002006E9200005B000A0100CC020000B2D4 +:1004400000007000030100FC024019BD0800020416 +:10045000000000F8A34001990000000000000084A3 +:1004600001C02F320000000000000090F1010034B4 +:10047000000000000000009401C02F320000600066 +:10048000800100801281FCB6000016130401008078 +:1004900002C02FBC02006000B00000A0F20B00B947 +:1004A000000063000401008002C0B0BC00006E00C8 +:1004B000A000008002000090000065008001008024 +:1004C000F24BD0B600006E00A00000800200009049 +:1004D00000000000A0000004FD4BD03400006B00C1 +:1004E000800100801281FCB60000C211000000D81B +:1004F000020000D20000161304000080028092BCAB +:1005000018000000000000F8730A03396E0036007E +:10051000000000C00200369200009611000000D8D2 +:10052000020000D20000161304000080028092BC7A +:1005300018003600000000F8730A03F900005B00A1 +:10054000030100FC024018BD00008500030000FC10 +:10055000024019BD000000000000009401C02F32CD +:100560000000000000000080F101003400000000E5 +:100570000000008401C02F3200007500800100805F +:100580001281FCB6000016130401008002C02FBCCB +:1005900002007500B00000A0F20B00B90000780066 +:1005A0000401008002C0B0BC00008300A0000080F5 +:1005B0000200009000007A0080010080F24BD0B66B +:1005C00000008300A00000800200009000000000F6 +:1005D000A0000004FD4BD0340000800080010080AA +:1005E0001281FCB60000C211000000D8020000D247 +:1005F0000000161304000080028092BC1800000066 +:10060000000000F8730A033983003600000000C0C0 +:100610000200369200009611000000D8020000D2BD +:100620000000161304000080028092BC18003600FF +:10063000000000F8730A03F900007000030100FCD9 +:10064000024019BD00005B00030100FC024018BD20 +:1006500008000204000000F8A3400199080000000F +:10066000000000F87340013900008E008001008016 +:10067000E20180B600008B000000008002000090C4 +:10068000080091030C0000F8534001B900008D00F0 +:1006900080010080E20180B600001613120000689D +:1006A000020580B00000F6030000006C1FC0F69A3F +:1006B000000000000000000008058030000000007D +:1006C000000000FC020001320000000000000010E9 +:1006D00008803D3200000000000000CC0200003223 +:1006E00000000000000000100900363200008012F7 +:1006F00000000014090080D2000016138000008062 +:1007000062802FB60000161302010080823A80BC7E +:100710000000161306010080923A80BC0090161368 +:1007200004010080A20D80B000001613120100BC6D +:1007300008C021B200000000000000D40200003216 +:1007400002A0000000000000A90D80320000161376 +:100750001200005402A438B2000200800000002CF5 +:100760000800373218003600000000F8730A03F959 +:100770000000000000080004088072320000A2009F +:100780009F00005C080072B28300A100800100801D +:1007900082CD85B00000B6000000002CD8C1829444 +:1007A0000000B6000000002C88C1829400001613DF +:1007B00006010080827D80BC000FAC000401008037 +:1007C00082CD85B00000AC00800000803281FCB694 +:1007D0000000161312000068020580B0000000003F +:1007E0000000006C1FC0F63A00000000000000FC92 +:1007F000020001320000AA00040100DC43603DB3A6 +:100800000000F603000000FC020000921800000047 +:10081000000000F8738A0339A7003600000000C00A +:10082000020036920000AE0080010080F2C085B662 +:100830000000BE000000002C98C182941000C3008C +:1008400087000000792116B80000C30080010078FD +:10085000390090B08300C3008700007889CD85B04F +:100860000000B30080000080028097B60000B60050 +:100870000000002C88C182940000B5008000008038 +:1008800022C185B60000B6000000002CD8C18294B9 +:100890000000C3000000002C98C182940000BC003E +:1008A00080010080D2C182B60000C30080010080B8 +:1008B0007280FCB600000000001800A8423D7230B3 +:1008C00000000000541809FEF2C07C300000EA006D +:1008D00080010080F2C185B60000C50000000080E4 +:1008E00002000090000016138001008082C182B6D1 +:1008F0000000B800800000808280FCB60900C300C0 +:10090000040000B428BF17B88300C500870000ACFE +:1009100088CD85B00000C30004000080D2E28AB018 +:1009200000000000001800A8423D72300000C50021 +:10093000541809FEF2C07C9000000000540000FC36 +:100940000200003200000000001800200700003202 +:100950008000802000000080C2CD85300000DA00D9 +:100960000B000080020000B01800000000000078BA +:1009700079A116382000EA0004000080828D97BC1F +:100980000000D100800100806280FCB68300D100AD +:100990008700007889CD85B00000CD008000008000 +:1009A000028097B60000D10080010080128097B6C7 +:1009B0000000D1008001008072C185B610000000E7 +:1009C00000000078796116380000D800040100802A +:1009D000328097BC0000EA000000002CB8C182946D +:1009E0000000D800800100805280FCB60000D800D2 +:1009F0008000008072C185B60000D80080010080B0 +:100A000002C185B60000D80080010080D2C185B641 +:100A1000180000000000007879E116380000D800C6 +:100A200004010080328097BC0000EA000000002C26 +:100A3000C8C18294000000000000000408000432D5 +:100A40000000EA000000002CA8C182940800000009 +:100A500000000078792117380000EA0004000080C7 +:100A6000328097BC0000EA0004010080228097BC1D +:100A70001F0000000012000889CD72300500000040 +:100A800000120000B9DC173800000000000000A8C8 +:100A9000220090370000EA008000868022247CB685 +:100AA00000000000000000780905803000001613E7 +:100AB0000201008082BA97BC000016130601008074 +:100AC00092BA97BC0000161312000068020580B0AD +:100AD00000000000000000FC020001320000E800FD +:100AE000040100DC43603DB30000F603000000FC9D +:100AF0000200009218000000000000F8738A033919 +:100B0000E5003600000000C002003692020000003E +:100B100000000010090036320000801200000014AE +:100B2000090080D20000F10012010060084023B2E9 +:100B30003200000000000010090036320000801270 +:100B400000000014090080D20082000000000008AC +:100B5000088036320000E100000000641F40F69A71 +:100B60000000161312000024080023B20000161320 +:100B70001200002008C023B2000016131200001853 +:100B8000088023B200000000000000FC02000132D7 +:100B90000000F800040000DC43603DB318000000D2 +:100BA000000000F8738A0339F4003600000000C02A +:100BB0000200369200000000000000FC02008532B6 +:100BC00000000000000000D8028001320000000098 +:100BD000000000D00200003200C007011801000C24 +:100BE000A8CD3EB20000F80012000038028081B2A9 +:100BF000000000000000003C020082320000000003 +:100C0000000000300240823200000000000000348A +:100C10000200863220800000000000080880363282 +:100C2000000000000000005C1FC0F53A000000005A +:100C300000000078090580300000161302010080D2 +:100C400082BA97BC000016130601008092BA97BCC6 +:100C50000000F60312010068020580B000001613C0 +:100C600000000080020000900000000000180078E2 +:100C70000900723200230A0104010080A2CD82B073 +:100C800000000B0100000000090000920000161394 +:100C90009F16000029C172BC00000000001800006F +:100CA000078081320000000000200000070082322F +:100CB00000000000002800000780973210000000AC +:100CC00000300000172090390000000000380000BC +:100CD00007C0823200000000000000D8020000328D +:100CE00000000000000000000740803200001401F6 +:100CF00080010080A2C182B600001501000800003A +:100D000057008097050000000008000007A0043984 +:100D10000000161304100000074082B2000000001B +:100D20000018000007008632000016131200005061 +:100D3000F2C138B418003600000000F8730A03F955 +:100D40000000161312000068020580B000000000C9 +:100D500000000078090580300000161302010080B1 +:100D600082BA97BC000016130601008092BA97BCA5 +:100D7000000016131200004802C080B20000F60303 +:100D8000CA010008E8818094000000000000008093 +:100D9000024590300000161304010080120028BCA8 +:100DA00000001613120100BC08C021B208000000A8 +:100DB000000000F89340013910000000540000FCCE +:100DC000824D9036000016130200008042C02FBCF6 +:100DD00000002501F00100D8020000B20000000070 +:100DE000620401A802C06E3200000000000401008D +:100DF00059C06E37000000000004017819C06E3A37 +:100E0000000000004E0401EC06BD97300000000019 +:100E1000E00000F41E40EF3A0000161304190B82A4 +:100E200002C07CBC0000000000180BCE074000325E +:100E30000000000000000000074009320000161307 +:100E400004010080020036BC000000000008000021 +:100E500077C029370000161304100000173D90BA20 +:100E600000000000001800000780F4320000161394 +:100E700012000040F2C138B40B0000000000001066 +:100E8000090036320000801200000014098083D26D +:100E900000000000000000FC32C02F300000000005 +:100EA0000000001008803D3218003600000000F8F5 +:100EB000730A03F900000000000000D402000032B1 +:100EC000000016130401008002802DBC0000CE013A +:100ED0008038008022C072B600003E01120000C8B7 +:100EE000020020B2000045011201005C088020B21F +:100EF000000016131200006002802CB218000000DF +:100F0000000000F8738A03393B013600000000C07E +:100F10000200369200000000000000F81F80FF3A37 +:100F200000000000000000FC320085300000A3013A +:100F30000400008042603DB318000000000000F88B +:100F4000738A033941013600000000C00200369266 +:100F5000080000000000000088CD85370000000078 +:100F60000000002008007232000000000008002489 +:100F700008007232000016130410006C080072B2F0 +:100F8000000000000018004C080072320000161328 +:100F900004200018080072B2000000000030002891 +:100FA00008007232000016130200008082BD82BC6D +:100FB000000000000028003008007232000000002D +:100FC00000000060088082320000560106000080A8 +:100FD00062A082BC000016139F3C0014288072BCE3 +:100FE00000000000000000000700063207000000BB +:100FF00000080000774A09390000161304100000A9 +:10100000070082B200000000CA19000007408232C7 +:101010000000161312000040F2C138B400000000B6 +:10102000000000D80240003200007D010438007842 +:10103000D9C572B000005A0180010080028097B6C5 +:1010400000000000000000F882802F3400005C01E6 +:1010500080010080128097B600000000000000F8B8 +:1010600092802F34000016130401008002402DBC32 +:10107000040000000038003CB81C173800000000D5 +:101080000000003C28C0833700000000003A002C1C +:1010900008C07232000000000000001CB8E0833A73 +:1010A00000000000CB2900200700003200007C0176 +:1010B0000400008002C081BC000000000000003479 +:1010C00078A0813E000000000000001CD8E0813CB8 +:1010D00000006A01063A0080B25C83BC0000000098 +:1010E000003A000089C17237070069012B01000432 +:1010F000790A04B900000000CB00000419419034C3 +:1011000000006D01003A002C070000920000000072 +:10111000003A002CD7E0723C000000000000000004 +:101120000900003200000000000000040900003245 +:10113000000000000000000007648332000000008F +:1011400000080000070080320000161304100000A1 +:1011500007C086B2000000000018000007C08432FB +:1011600000008C0104000028D8A082BC00001613E7 +:1011700009010080020000B0000000000000000033 +:10118000D820803A000077010400008072802DBCD6 +:10119000000016131200004412E438B20000780177 +:1011A000000000D812802D9A000075120000000483 +:1011B000F94190F400007A0104000018D8A081BC25 +:1011C000000062010000006CD8E0869A0000201246 +:1011D0000000004408802DF2000062010000003091 +:1011E0000800009200000000CB1900200700003228 +:1011F00007007F012B010004790A02B900000000FA +:10120000CB00000419419034000000004D000000A4 +:10121000A7A0813E00000000000800000700803207 +:10122000000016130410000007C086B20000000082 +:101230000018000007C0843200008C010400002860 +:10124000D8A082BC0000161304010080626083BC39 +:101250000000000000000000D820803A0000890152 +:101260000400008072802DBC0000161312000044A0 +:1012700012E438B200008A01000000D812802D9AD2 +:101280000000751200000004F94190F400002012E3 +:101290000000004408802DF200007D0100000030B5 +:1012A000080000920000161380000080A2802FB674 +:1012B0000000000000000004F94190340000161303 +:1012C0001200004412E438B218003600000000F8A2 +:1012D000730A03F9000016130400008002802DBC7D +:1012E00000000000001800040980733200000000B4 +:1012F000002800088980733700000000000000808B +:1013000007008632410000000006008C07003632DC +:10131000000098012908008007C085B200009B01E9 +:101320002810008C070000B200009C01001200840D +:1013300007000092000000000010008CF7E0823AE5 +:1013400000009B0128180080074090B200009C011B +:1013500000120084070000920000000000120084C8 +:1013600027E4823200000000000000783900853058 +:101370000000161304010080F28B97BC0000A1014D +:101380000400008042603DB318000000000000F837 +:10139000738A03399C013600000000C002003692B7 +:1013A00000000000000000FC02008532000016135F +:1013B0001200005C52812CB400000000000000D834 +:1013C00002800132000000000000008002003B3279 +:1013D0000840A501F0010008088036B200000000B6 +:1013E0000004013808C06E3200000000E00000F484 +:1013F0001E40EF3C0000AC010B01008C080000B265 +:101400000000A901F2010080020000B0000000000D +:10141000000000F00E003A320000BE01E200008041 +:101420000E8083920000AC01F2010078C93B3ABC07 +:101430000000B60102010080828097BC000000001D +:10144000000000A80200E8320000B10104000080A2 +:1014500022A22ABC0000B50104190B8202C07CBC88 +:10146000000000000000008C18C0883A0000000056 +:10147000000000A812802A3A00000000000000A826 +:1014800002BD2A300000AF0104010080E2A02ABCA6 +:101490000000BB010200008082C088BC0000000088 +:1014A000E20000080800003200000000000000A870 +:1014B000028088320000161304190B8212C07CBC13 +:1014C0000000000000180BCE070000320000F603F9 +:1014D000000000DC03000092000000000000003863 +:1014E00008802A3200000000000000F00E003A32AE +:1014F00000000000E20000800E802A3200000000A0 +:10150000000000A8028088320000161304190B8224 +:1015100012C07CBC0000000000180BCE0700003297 +:1015200000000000000000DC030000320000161381 +:1015300004000080227AE8BA0000000000000000E9 +:1015400007808332000000000000000079C02937C6 +:101550006020000000000000890D903A00000000AB +:10156000CA0100D812802D3A0000000000000000DF +:101570000700013200000000000800000700903260 +:1015800000000000001000000740E83200000000EA +:10159000001800000780E83200000000000000FC96 +:1015A000020000320000F60312010048F2C138B414 +:1015B00000001613000000800200009000001613C7 +:1015C0000401008002402DBC0000161304010080BD +:1015D00002802DBC000016138000008072802FB6A0 +:1015E0000000000000300078088072320400000023 +:1015F00000380054A85C16380B0000000038002C9E +:10160000A8DC1638140000000000001C884D853A44 +:101610002200000000000010090036321000801285 +:1016200000380014A99C87D90000000000000020A9 +:101630000800723200000000000800240800723226 +:10164000000000000010006C080072320000000072 +:101650000018004C08007232000016130420001815 +:10166000080072B20000000000280030080072324A +:10167000000016139F3C0014188072BC0000E501A6 +:1016800004000080024081BC000000000000001443 +:101690001840813C000000000000000007000632F6 +:1016A0000700000000080000774A093900001613FF +:1016B00004100000070082B200000000CA190000F8 +:1016C000074082320000161312000040F2C138B405 +:1016D00000000000000000D80240003200000000BE +:1016E0000000006478C02937021000000000006488 +:1016F000884D863A0000000000000080080000329B +:10170000000000000000004008000032000000005F +:101710004D00000077A0813E00000000000800009E +:1017200007408632000016130410000007C086B27E +:10173000000000000018000007C084320000000212 +:101740000400001CD8E081BC0000161309010080D1 +:10175000020000B00000000000000064D860863A7B +:101760000000F4010400008072802DBC00001613FC +:101770001200004002C038B20000FC01000000D896 +:1017800012802D9A0000161312000040F2C138B4E6 +:1017900018003600000000F8730A03F90000FA018F +:1017A0000401008002802DBC00001613800100801F +:1017B000A2802FB60000F501670000F8A2802FB5C7 +:1017C00000001613120000E802C021B20000161338 +:1017D0000401008072802DBC00000000000000D8D1 +:1017E000024000320000FE0104000018D8A081BCB5 +:1017F0000000EA010000006CD8E0869A0000C910E1 +:101800000000004408802DF20000EA0100000030D2 +:10181000080000920000161312000040F2C138B414 +:1018200018003600000000F8730A03F900000602F1 +:101830000401008002802DBC00001613800100808E +:10184000A2802FB600000102670000F8A2802FB529 +:1018500000001613120000E802C021B200001202BC +:1018600004010080020084BC00000000000000D4DD +:101870000240003200000000000000A42240853A2F +:10188000040000000018004088CD743600000000FD +:10189000000000402800843700000000000000D451 +:1018A00002000032140012020400001C880D84BCE7 +:1018B0000000161309010080020000B000000000C3 +:1018C000000000780961853A800016130601008047 +:1018D000828D97BC0000000000000064D860863A4A +:1018E0000000FC01000000D8024000920000140239 +:1018F00004000018D8A081BC000016020000006C93 +:10190000D8E0869A0000C9100000004408802DF23B +:10191000000000000000003008000032000000005D +:10192000000000D40240003200000000000000A4CB +:1019300022C0823A000000000000003CB860853CF4 +:1019400004001C028100006088CD74B60000000015 +:1019500000040028F8A0753C00001D020008007477 +:10196000088075920000000000080028F8A0753C6F +:10197000000000000000002808A1823C00000000D8 +:10198000000000A4F2602A3A0000000000080048AD +:1019900008007532000000000020007C08807532CD +:1019A00009002302041A007088CD74B009000000F9 +:1019B000001A004C87CD74317F00000000000064E5 +:1019C000884D863100000000000000642840863AFF +:1019D00023000000000000100900363200008012D1 +:1019E00000000014098082D20C00000000000010EA +:1019F000090036320000801200000014098084D2F1 +:101A000000000000000000D802400032000000008A +:101A1000001000000740863200000000000000D8DF +:101A20000280003200000000001000005761863A7A +:101A300000003002120000C8020020B20000330291 +:101A40001201005C088020B2000016131200006032 +:101A500002802CB2000040012A0100D4020000B232 +:101A600018003600CA0000F8730A03F900004101AB +:101A7000000000F81F80FF9A00000000000000D462 +:101A800002400032080000000000000088CD8537C9 +:101A9000000000000000001CE8A1823E00000000E1 +:101AA000000000A42240853A000000000008005019 +:101AB0000780843200003A020401008072A082BCD8 +:101AC00000000000001A004CC7E174320000000062 +:101AD0000000006808E1813A00003D0290010078B2 +:101AE000F9A186BA00000000000000781980973A3A +:101AF000000000000020005807809732000000001E +:101B0000000000D802800032000000000000000049 +:101B10000700843200000000400800005721803A8E +:101B2000000041021200004CF2C138B40000000075 +:101B3000000000000821803A0000000000000004BE +:101B400008C0813200000000510000D802C00032FD +:101B500000000000000000D402000032000000007D +:101B6000CB1900200700003200001613020100808C +:101B700032802DBC07004A022B010084780A02B98A +:101B800000000000CB0000841841883400000000F1 +:101B90004D00000077A0813E00000000000800001A +:101BA00007008032000016130410000007C086B240 +:101BB000000000000018000007C084320000161367 +:101BC0009F000028D8A082BC000068020400001C0E +:101BD000D8E081BC0000161304010080626083BC61 +:101BE000000059022D000000D82080BA00005402E5 +:101BF000120100E802C021B218003600000000F80F +:101C0000730A03F9000056020401008022802DBCF3 +:101C100000005902CD0100D8024084920000161342 +:101C20000401008002802DBC00001613800100809A +:101C3000A2802FB600005302000000F8A2802F956A +:101C400000005C020400008072802DBC00001613AE +:101C50001200004412E238B200006602000000D810 +:101C600012802D9A0000000000000084F8418834A2 +:101C7000000016131200004412E238B218003600B9 +:101C8000000000F8730A03F90000640206010080F6 +:101C900022802DBC000016130401008002802DBCA0 +:101CA0000000161380010080A2802FB600005E02A3 +:101CB000670000F8A2802FB500005F02000000E876 +:101CC00002C02192000016130401008072802DBC16 +:101CD00000000000000000D802C000320000C9105F +:101CE0000000004408802DF2000047020000003090 +:101CF000080000920000700280000080D2802FB6A1 +:101D000000006B02120100E802C021B21800360088 +:101D1000000000F8730A03F900006D02040100805E +:101D200022802DBC00007002000000D80240849286 +:101D3000000016130401008002802DBC0000161361 +:101D400080010080A2802FB600006A02000000F827 +:101D5000A2802F9500000000CD000084F841883457 +:101D6000000016131200004412E238B20000000016 +:101D7000000000D40240003200000000000000A477 +:101D800022C0823A0000790204010080420086BC31 +:101D90000000000000080058074087320000780269 +:101DA0008F010074184087BA000000000000007422 +:101DB0000800003200007B0200040058F7A0869A59 +:101DC0000000000000000078F9A0863A280000001A +:101DD00000080058878D973C00000000000000D8E4 +:101DE000024000321800000000000000B760853992 +:101DF000080000000008000087CD853700007E0243 +:101E00001200004CF2C138B400000000000000488D +:101E100018A0843A00000000000000D40200003244 +:101E2000000000000000008057A1863A4100000039 +:101E30000006008C07003632000000000008008019 +:101E400007C08532000000000010008C074085327A +:101E500000000000000000D80280003200001613CD +:101E600004000058088071B20000000000000080EB +:101E70000880003218003600000000F8730A03F9E9 +:101E800000008C020401008002802DBC00001613AB +:101E900080010080A2802FB600008802000000F8B8 +:101EA000A2802F950000880204010080180088BCE1 +:101EB00000008F0290190058E89C85BA00000000CD +:101EC000000000581880853A0000000000180080CB +:101ED000078585300000940204010080420086BC22 +:101EE00000000000000000D80240003200000000A6 +:101EF00000000008898071370000950200120084FC +:101F000027E48292000000000012008407000032E3 +:101F100000009902270000FC020085B2000099022F +:101F20000400008042603DB318000000000000F88B +:101F3000738A033995023600000000C00200369211 +:101F4000000016131200005C52812CB400009D02A8 +:101F500004010080028082BC000016138000008013 +:101F6000A2802FB60000A301000000D4020000925E +:101F70000000A00204010018D8A081BC0000C91014 +:101F80000000004408802DF200002D02C70100303F +:101F90000800009200002D02C701006CD8E0869A6C +:101FA00008000000C60100F8934001391900000044 +:101FB00000000010090036320000801200000014FA +:101FC000094081D200000000000000140845813063 +:101FD00000001613120100BC08C021B20000161345 +:101FE00080000080A2802FB60000F6038001808070 +:101FF000320B6AB600006A100000003C030038F2A1 +:102000000000AC020406018002C06EBC0000161382 +:10201000870601EC56E06EBA0000F3030000008072 +:102020000200009000001613870601EC56E06EBA1D +:1020300000000000000000F842802F3408C0161392 +:1020400012000040A2CD39B218003600000000F89E +:10205000730A03F90000161303B8000009C06EBD2F +:10206000B202000000000088820D903A2F005E0648 +:102070000000001C080036920000161300000080CB +:10208000020000902C005E060000001C0800369242 +:1020900000001613000000800200009000001613DC +:1020A0000000008002000090000016130000008075 +:1020B0000200009038005E060000001C0800369206 +:1020C00039005E060000001C08003692080000007F +:1020D000000000F89340013900001613120100BC03 +:1020E00008C021B20000161380000080A2802FB625 +:1020F0000000161380008080320B6AB600006A1060 +:102100000000003C030038F20000C102040000801F +:10211000524082BC0000161304010080624082BC61 +:10212000000016130405018002C06EBC0000000010 +:10213000000000F842802F3408C01613120000403F +:10214000A2CD39B218003600000000F8730A03F976 +:10215000000000000004017809C06E320000000099 +:10216000006201EC068097320900000000000010B8 +:1021700009003632000080120004011409C06ED23A +:102180000200CB0204B8008082CD6EBC080016139A +:1021900004B9008082CD6EBC00000000000601EC96 +:1021A000064000320000CC02B50000D8020000B2A8 +:1021B00000000000A50080A0360B6A34000000007B +:1021C000003002E806C02C320000000000000000D1 +:1021D000078000320000000000000078A9002D37C1 +:1021E0001805010000080000C78D973A00000000A4 +:1021F0000000007899C02C3718010000000000781A +:10220000898D973A000016130210000087BF97BA15 +:1022100000000000001800000740FE320000161306 +:1022200012000048F2C138B418003600000000F86F +:10223000730A03F900000000001801E006000032F4 +:1022400000000000000000F882852F3000006806C2 +:102250000000001C0800369208000000000000F892 +:102260009340013900001613120100BC08C021B2CE +:102270000000161380000080A2802FB660001613A5 +:10228000040100F8828D2FB007000000000000104C +:10229000090036320000801200000014094081D28B +:1022A0000000E50280008080320B6AB61700000053 +:1022B00000000010090036320000801200380014BF +:1022C00009C06ED20000F6030000008002000090FA +:1022D00000006A1000000038030038F20000E80235 +:1022E0000402018002C06EBC0000F303000201EC96 +:1022F00056E06E9A00000000C00301EC56E06E3A12 +:10230000000016138001008002802FB600C0161353 +:1023100012000040A28D39B218003600000000F80B +:10232000730A03F9200016130439008082CD6EBCB5 +:102330001200000000000010090036320000801278 +:102340000030001409006ED21500000000000010DB +:1023500009003632180000000002011489CD6E37E2 +:102360000000801200200114895B91D21B00F4024E +:1023700038010010090036B200008012003001144C +:1023800009006ED21800000000000010090036326B +:102390000800000000000014790B143810008012AF +:1023A00000500114A95B91D90000F902042801141E +:1023B00009006EB21C00801200000010090036D225 +:1023C000000005033828001809006EB20000FD0265 +:1023D0000421010869246EBC000016130901008065 +:1023E000020000B0030068060000001C08003692DE +:1023F0000000010302300080829B90BC00000003BB +:102400000603018012C06EBC040068060000001CB8 +:1024100008003692050068060000001C080036928D +:10242000000016130430008002006EB200000403A6 +:102430000603018012C06EBC0B0068060000001C81 +:10244000080036920C0068060000001C0800369256 +:10245000000008030421010869246EBC0000161363 +:1024600009010080020000B0030068060000001CA3 +:102470000800369200000C0302300080829B90BC62 +:1024800000000B030603018012C06EBC0400680646 +:102490000000001C08003692050068060000001CC1 +:1024A0000800369200000E039F31010C69246EBCB7 +:1024B000000000000000000C0900003200001203C0 +:1024C00004310004899B90BC0000110306030180C5 +:1024D00012C06EBC200068060000001C0800369286 +:1024E000210068060000001C080036920000161348 +:1024F0009F000080024090B200001503040201809A +:1025000012C06EBC220068060000001C0800369253 +:10251000000017030401000039A490BC23006806E2 +:102520000000001C08003692000016139F00008077 +:10253000020090B2240068060000001C08003692D9 +:10254000080016130C0000F8634001B910001D03C9 +:10255000C50100CC02201598080091030C0000F87A +:10256000434001B910000000C50100CC022015381D +:102570000000000000000010090036320000801248 +:1025800000000014090080D200001613120100BCE4 +:1025900008C021B200006A100000003C030038F2BD +:1025A000000000000000005C0805803000001613E9 +:1025B0000401008002402DBC0000161302010080BF +:1025C00082FA85BC000016130601008092FA85BCD1 +:1025D0000000270336010080020000B00F006806EB +:1025E0000000001C0800369210000000002C0200C1 +:1025F000A9DB8539000016131200005402A438B27A +:10260000000000000008028C08C06E3200000000CC +:10261000000C029828806E37000000000000009C2B +:1026200038221437000032030430002808006EB24C +:10263000000016130410006C08006EB200000000C9 +:102640000018004C08006E32000016130420001819 +:1026500008006EB200000000003C001408806E32DA +:10266000050035030038020078E16E990000000093 +:10267000510000D80200003200000000003802784B +:1026800009C06E32050000006808000077A1973984 +:10269000000037031201000009C021B21800360003 +:1026A000000000F8730A03F900000000545401FC14 +:1026B00002C06E3214103B0304000080A20D72B001 +:1026C0000000F3110000002809C002F20E006806A5 +:1026D0000000001C08003692000016130609008056 +:1026E00082BD72BC00004F03331500A402C072B259 +:1026F00000008C0380010080B20172B60101420328 +:1027000004290080828D74BC080A8C03042D00808B +:10271000828D74BC000000000030007C080075321F +:1027200000004903003800881800759C080A8C03D3 +:1027300004290080828D74BC10000000002C007CF5 +:10274000888D7537000000000030007C68DD87321E +:10275000000048039F390088188075BC10000000F5 +:1027600000340088888D7537000049030000008818 +:102770001880889C1000000000340088689D88390B +:1027800037000000000000100900363200008012FF +:102790000000001409C087D23B00000000000010B8 +:1027A000090036320000801200000014098088D22F +:1027B000000050039FF1018082DB87BC00008C0386 +:1027C000000000800200009000008C038000008068 +:1027D000B20172B60000000000080048080075321F +:1027E00000000000001000700800753200000000BA +:1027F000001C007438A2753700005503831B007855 +:1028000008C074B200000000000000F8C2802F343D +:102810002F00000000000010090036320000801276 +:1028200000000014098084D2340000000000001071 +:10283000090036320000801200000014090087D21F +:1028400000006B039F780180C2216EBC00005D0315 +:102850009F990164881B87BC00006C039F6801641A +:10286000885B86BA000000000000006408000032A7 +:1028700000000000001600A402C072320000000038 +:10288000003C02A4B25B2A3A00000000003A027841 +:1028900009C06E3200006D0308010004E8A575BC94 +:1028A0003F000000000000100900363210008012C6 +:1028B00000040014695D80D910008C030B01001C1A +:1028C000080036B200006B0304A10180829B84BC27 +:1028D000000068069F980180C2216EBC0000680657 +:1028E00006B10180825B87BC00008B030B01008076 +:1028F000020000B000006C0304990180C2216EBC8C +:102900000000890302D4018092FB6EBC16006806A9 +:102910000000001C08003692170068060000001C2A +:10292000080036921C0068060000001C0800369261 +:102930003F00000000000010090036321000801235 +:1029400000040014695D80D90000710304A10180B6 +:10295000829B84BC0000780306A80180825B80BC57 +:102960000000750304A9018002006EBC00008A0308 +:1029700004A10180829B84BC00008A0304010080C2 +:10298000124080BC140068060000001C080036924B +:1029900000008A039FA0017829216EBC00008A03F1 +:1029A0000201008012A097BC00006B0300000080B1 +:1029B000020000900000850304000080028082BCB9 +:1029C000000016130402018002C06EBC00007E03EA +:1029D00002000080A26080BC060068062C01001C7A +:1029E000080036B200C0820304010080A28D2FB01F +:1029F000060068060000001C0800369200008203F2 +:102A000004000080A26080BC0000810306030180F6 +:102A100012C06EBC090068060000001C0800369257 +:102A20000A0068060000001C0800369200008403BB +:102A30000603018012C06EBC070068060000001C7F +:102A400008003692080068060000001C0800369254 +:102A5000020068063801001C080036B20000880336 +:102A6000020C0280A25B80BC1F0068060000001CF4 +:102A7000080036921E0068060000001C080036920E +:102A800000008D03000000280940009200008D0323 +:102A9000000000280980009200008D03000000283B +:102AA00009C0009200008D03000000280900019277 +:102AB00030000000000000100900363200008012D3 +:102AC00000000014098092D20E00F3110000001CD7 +:102AD000080036F200006806000000800200009046 +:102AE000100016132A0000CC022015B80D000000BB +:102AF00000000010090036320000801200000014AF +:102B0000090080D200001613120100BC08C021B2D7 +:102B100000006A100000003C030038F21D00990319 +:102B20008001007809E000B800001613040100805D +:102B3000328097BC1D0068060000001C0800369219 +:102B40000000161304010080228097BC150068065F +:102B50000000001C08003692000000000000001C6D +:102B6000A8052830000016130400008002C02CBC09 +:102B700000001613120100BC08C021B20000161399 +:102B800080000080A2802FB660001613040100F8B8 +:102B9000828D2FB008000000000000F8834001394A +:102BA0003600A4030400008082CD81BC0500000033 +:102BB00000000010090036320000801200000014EE +:102BC00009C081D20000020480018080320B6AB605 +:102BD00000006A1000000038030038F22C0068067C +:102BE0000201008082CD81BC00005E0600000080F2 +:102BF0000200009000001613120100BC08C021B2B0 +:102C00000000AB031D41025CF80168B44100F3030E +:102C1000000000F8A28D2F91350000000000001088 +:102C200009003632000080120000001409C085D26D +:102C300010000000D02C0200A9DB85390000290318 +:102C40001201005402A438B20000161300000080E4 +:102C5000020000900000B40304B0008002006EBCCB +:102C60000000B40380B9008082806EB600000013BB +:102C70000078016008006EF230005E06D700001C8C +:102C8000080036920000B60380010080D2812FB682 +:102C900031005E06D700001C080036920000B80321 +:102CA0008001008042812FB635005E06D700001CEF +:102CB000080036920000C50304A8010809006EB29E +:102CC0000000000000200208899B903E00000000E8 +:102CD00000A00108899B903A0000C5039F88010865 +:102CE000899B90BC000000000034020009C06E3DCA +:102CF00000000000000C020409A46E370000C103AC +:102D00000200008012A490BC000000000000000837 +:102D1000198090370000C50302010280829B90BC9D +:102D200031005E06D700001C080036920000C50383 +:102D300004B0008002006EBC0012C50304010080D4 +:102D4000A28D2FB032005E06D700001C080036921C +:102D50000000F303000000F872812F9500000000CE +:102D6000000000F842802F3408C0AF02120100407A +:102D7000A2CD39B2000016130000008002000090BE +:102D800008000000000000F893400139080000002E +:102D9000000000100900363200008012000000140C +:102DA00009C081D2000016130400008002C02CBCB0 +:102DB0000000161380000080A2802FB6600016135A +:102DC000040100F8828D2FB0000002048001808091 +:102DD000320B6AB600000000000000140840903278 +:102DE00000006A1000000038030038F22C0068066A +:102DF0000201008082CD81BC00005E0600000080E0 +:102E00000200009008000000000000F89340013923 +:102E10000800000000000010090036321000801287 +:102E200000000014894D81D70000161304000080B3 +:102E300002C02CBC0000161380000080A2802FB6B8 +:102E400060001613040100F8828D2FB00000020408 +:102E500080018080320B6AB600006A1000000038E2 +:102E6000030038F20000DF030420018052206EBC12 +:102E70000000161309010080020000B02600680659 +:102E80000000001C08003692250068060000001CA7 +:102E9000080036920000E503040100D81E80EDBC56 +:102EA0000000E103B70000D80EC0EDB20000E4035B +:102EB00004010080423BEEBC00000000000000E086 +:102EC0001E00EE3A00000000A70000D00E00EE3217 +:102ED00000000000007486CC02806C32000000000C +:102EE000000000000940E7320000E9038001808013 +:102EF000320B6AB6360016131200002C82CD2EB2A9 +:102F00000000EB030401008042C52CBC0000EC0370 +:102F1000000000CC0200009200000000000000CC85 +:102F200012C02C3A0000E70304010000190090BC15 +:102F300000000000007486C806C02C32080002049D +:102F4000000000F8C34001990000F1030400008074 +:102F5000028080BC0000161304550180B2DB2FBC38 +:102F6000000054100000002C090000F20000F603DD +:102F700000000080020000900000F50304000080C3 +:102F8000028080BC0000161304550180B2DB2FBC08 +:102F9000000054100000002CF90100F40000FF03B1 +:102FA00004000028098080B200000000000000D862 +:102FB000020000320000811100000008080000D269 +:102FC0000000FF0304000080028092BC180036005D +:102FD000000000F8730A03F9000002048001008079 +:102FE000A2802FB6000002041201000009C021B225 +:102FF00018000000000000F8730A033902043600CC +:10300000000000C00200369200000204800100802F +:10301000A2802FB6000002041201000009C021B2F4 +:1030200018003600000000F8730A03F900000000E1 +:10303000000000F80200003218003600000000F81E +:10304000738A029910000000000000E40300363289 +:1030500002000001000000E0030037320000000021 +:10306000000000E40300363204000001000000E02C +:1030700003003732AA040000000000E403003632E7 +:1030800009000001000000E00300373200000000EA +:10309000000000CC0F00003200070000000000E438 +:1030A0000300363206000001000000E00300373262 +:1030B00020000000000000E4030036320800000198 +:1030C000000000E00300373200010000000000E4CF +:1030D0000300363205000001000000E00300373233 +:1030E00030000000000000E4030036320700000159 +:1030F000000000E00300373200A00000000000E400 +:103100000300363208000008000000E003003732F8 +:1031100000000000000000A00200003200000000DB +:10312000000000000B000032000016048B0100A01C +:1031300012002ABA00000000000000A802000032BD +:1031400000000000000000E0070000320000190449 +:103150000601008002802ABC000000000000009CE4 +:103160000200003200000000000000D40200003223 +:1031700000000000000000CC02000032000000004F +:10318000000000D80200003200000000000000D063 +:103190000200003200000000000000DC02000032EB +:1031A00000000000000000F80200003200000000F3 +:1031B000000000C80200003200000000000000C44F +:1031C0000200003200001C048501009C12C029BAD4 +:1031D00000000000000000E4030036320B00000491 +:1031E000000000E00300373280000000000000E42F +:1031F0000300363213000004000000E00300373201 +:1032000000200000000000E4030036320C0000043F +:10321000000000E00300373200000000000000E47E +:10322000030006320F000004000000E00300373204 +:1032300000040100000000E4030037320D00000428 +:10324000000000E00300373200040000000000E44A +:103250000300363214000004000000E0030037329F +:103260009F000000000000E4030036321500000457 +:10327000000000E00300373200000000000000E41E +:103280000300363218000004000000E0030037326B +:1032900060000000000000E4030036321D0000045E +:1032A000000000E00300373200000000000000E4EE +:1032B000030004321E000004000000E00300373267 +:1032C00070000000000000E4030036321F0000041C +:1032D000000000E00300373200000000000000E4BE +:1032E0000300003220000004000000E00300373239 +:1032F000A0030000000000E40300363217000004C1 +:10330000000000E00300373240000000000000E44D +:10331000030036321B000004000000E003003732D7 +:1033200060000000000000E4030036321C000004CE +:10333000000000E00300373200000000000000E45D +:103340000340003216000004000000E003003732A2 +:1033500000010000000000E4030036321A000004FF +:10336000000000E00300373220010000000000E40C +:103370000300363219000004000000E00300373279 +:1033800080000000000000E4030036320B00000162 +:10339000000000E00300373200010000000000E4FC +:1033A000030036320C000001000000E00300373259 +:1033B000FEFF0000000000AC0200363200000000FA +:1033C000000000000900003218000000000000F8B2 +:1033D0000364023900004F0485010000190090BA0F +:1033E00025260000000000E4030036320100000141 +:1033F000000000E003003732000000000000008001 +:103400000F00003200000000000000840F000032B6 +:1034100008000000000000F8F34001390800000037 +:10342000000000F8E340013908000000000000F847 +:10343000C340013908000000000000F8B340013922 +:1034400008000000000000F8A34001390800000057 +:10345000000000F89340013908000000000000F867 +:103460008340013908000000000000F87340013972 +:1034700008000000000000F8634001390800000067 +:10348000000000F85340013908000000000000F877 +:103490004340013908000000000000F833400139C2 +:1034A00008000000000000F813400139000000008F +:1034B000000000F80380003200000000000000C897 +:1034C0003F80FC35000000000000009C020000323C +:1034D0000000000000000000030000323E00000079 +:1034E000000000D00200363200000000000000287A +:1034F000034038320000161304010080D20130B6B8 +:1035000000006704040100D012002DBCA0040000DC +:10351000000000E40300363203000001000000E078 +:103520000300373200000000170000D00200003214 +:1035300000000000000000ACE100003400000000CA +:10354000000001E00600003200000000000801E475 +:103550000600003200000000000E01EC0600003200 +:1035600000000000001001E0060000320000000032 +:10357000000000D012002D3A3E006F0402010080CE +:10358000820D2DBC020000000000009CAE0D023236 +:1035900000000000000000A802000032300000001F +:1035A000008886CC0700363200000000008A86CCF6 +:1035B0000700003A002400000000000409803632B1 +:1035C0000000161312000064024090B200000000D8 +:1035D000000000042940903A00007B0412000078AB +:1035E00009C020B20000161380010080F28197B656 +:1035F0001D00161380010078E9E500B80000000006 +:103600000000007809459030000079040201008034 +:10361000C28297BC0000000000000084020000325B +:1036200000000000000000CC030000320000810414 +:103630008E010080024028B20000BD10000000D8BA +:10364000020000D2AA1100000000008C0E003632E9 +:1036500052000000000000740E0036321800000016 +:10366000000000E40300363209000002000000E020 +:1036700003003732FECA0000000000E403003632C7 +:103680000A000002000000E00300373200008C0452 +:1036900012010000094020B200008A0400000080EE +:1036A0000200009000008C0412000004094020B2C7 +:1036B00000008F049F010080020090B200008E0481 +:1036C00012000008094020B202008A0404010078B8 +:1036D000092417B8060000000000007809641638B5 +:1036E00000008A0404010080028197BCFE000000F3 +:1036F0000000004403003632FE003600000000489F +:10370000030036920000161312000000094020B298 +:103710000000950412000004094020B20000980443 +:103720009F010080020090B2000097041200000880 +:10373000094020B200000000000000B402009032F6 +:103740000000161300000080020000900000161315 +:1037500000000080020000900000161300000080AE +:10376000020000900000161300000080020000908C +:1037700000001613000000800200009000001613E5 +:10378000000000800200009000001613000000807E +:10379000020000900600AA040000000C09641698BC +:1037A0000000A10200000014084090920000DB021B +:1037B00000000014084090923400C9030000001C6F +:1037C000080036921200C9030000001C080036925F +:1037D0003A00C9030000001C0800369200001613CE +:1037E00000000080020000900000BA0200000014F7 +:1037F000084090920000DE0400000080020000906B +:103800000000D4030000001408409092AB040000B4 +:103810000000008882CD903A0D00CD04000000FC2D +:1038200002E416980D00DF04000000FC02E4169884 +:103830000D00E804000000FC02E416980000F60405 +:103840000000008002000090000000050000000061 +:103850000940909D000006050000008002000090D5 +:1038600000001005000000800200009000001A0512 +:10387000000000800200009000002405000000000D +:103880000940909D00002B05000000800200009080 +:1038900000003405000000000940909D00003B0539 +:1038A00000000080020000900000AA050000000057 +:1038B000090000920000AA050000000009400092E3 +:1038C0001D07AC05000000A0020036920000BA05FA +:1038D000000000800200009000001613000000802D +:1038E000020000900000DE04000000DC0F40909217 +:1038F00000007E05000000800200009000008305AB +:10390000000000D40200009210009805000000841E +:103910001F6414980000DE04000000EC0E4090923A +:103920000000A40500000080020000900000DE04FA +:10393000000000D40E4090920000A7050000008017 +:103940000200009000004E06000000DC0E40909245 +:103950000000CB0500000080020000900800D005A8 +:10396000000000501F2416980000E805000000D851 +:10397000020000920D00F305000000FC02E416981E +:103980000000F405000000D00200009200001F01BA +:10399000000000D00200009200001513000000801B +:1039A000020000900000161300000080020000904A +:1039B00008000000000000F89340013900000000FA +:1039C00000000078094590300000161306010080C1 +:1039D000228097BC3F00161304010080820D00B0C6 +:1039E0000200D104B00000A0F20B00B900000000FA +:1039F000A00000046B4190340000020480010080AC +:103A00000240B0B600000204040000800280B0BC96 +:103A100000000000000000D802000032000000009A +:103A2000000000A822C02F370000000000000000A6 +:103A3000670100340042000000080000878D2A3A28 +:103A400000001613041000000700B0B200000000D0 +:103A5000001800000700D0320000161312000048C2 +:103A6000F2C138B418000000000000F8730A0339EE +:103A700002043600000000C0020036920800020472 +:103A8000000000F8934001990000E2049F000080CC +:103A9000020090B2000000000000000809409032CF +:103AA000000000000000000409C0FD320200E20432 +:103AB000B00000A0F20B00B9000000000000000000 +:103AC0000B80903200000000000000000D4090329A +:103AD00000000000A00000043B40B0310000DE0404 +:103AE0000400008002C02FBC8411DE040000008CA2 +:103AF0000E003692000016130200008002C12FBC97 +:103B000008000000000000F8934001390200EA04B8 +:103B1000B00000A0F20B00B90000ED0480010080AD +:103B20001240B0B600000000000000043B40B0337B +:103B30000000000000000004FD4BD0350000000034 +:103B4000000000080B00003200000000A000000C84 +:103B50001BE4B032000002040B000080020000B041 +:103B60000000F30404000080024090B21F00020431 +:103B700000000080114000990000F2040400008061 +:103B8000123EF8BA00000000000000800100F83288 +:103B900000000204000000900140F892000016139B +:103BA000800000800281FCB60000FA049F000080C3 +:103BB000020090B2000000000000000809409032AE +:103BC000000000000000000409C0FD3200001613D0 +:103BD00004010080428590B000000000000000E475 +:103BE0000380903209000004000000E00300373237 +:103BF00000000000000000E4034090320A000004CE +:103C0000000000E0030037320000DE04000000C8BE +:103C10000F81FC940000161302010080724290BCD8 +:103C20000000161306010080E24290BC000016134B +:103C300004010078096490B500000000000000E471 +:103C40007300903C10000004000000E003003732D5 +:103C50000000DE0400000080020000900000090562 +:103C60009F000080020090B20000000000000008E9 +:103C700009409032000000000000000409C0FD323D +:103C80000000161304010080428590B0000000007F +:103C9000000000E40380903201000004000000E016 +:103CA0000300373200000000000000E00F80903277 +:103CB00000000000000000E4034090320200000415 +:103CC000000000E0030037320000DE04000000E4E2 +:103CD0000F409092000013059F000080020090B2F8 +:103CE00000000000000000080940903200000000C1 +:103CF0000000000409C0FD3200001613040100801A +:103D0000428590B000000000000000E40380903283 +:103D100003000004000000E0030037320000000050 +:103D2000000000A80E80903200000000000000E4B7 +:103D30000340903204000004000000E0030037322A +:103D40000000DE04000000AC0E40909200001D0553 +:103D50009F000080020090B20000000000000008F8 +:103D600009409032000000000000000409C0FD324C +:103D70000000161304010080428590B0000000008E +:103D8000000000E40380903205000004000000E021 +:103D90000300373200000000000000E403409032CE +:103DA00006000004000000E00300373200000000BD +:103DB000000000440F8090320000DE040000004844 +:103DC0000F4090920000161306010080824290BCC2 +:103DD0000000161304010078096490B5000028055E +:103DE00004010080824290BC00000000000000003E +:103DF0000900003200000000000000E403009032DF +:103E000012000004000000E0030037320000DE046E +:103E1000000000401F40909C00002E059F00008085 +:103E2000020090B20000000000000008094090323B +:103E3000000000000000000409C0FD32000016135D +:103E400004010080428590B000000000000000E402 +:103E50000380903207000004000000E003003732C6 +:103E600000000000000000E403409032080000045D +:103E7000000000E0030037320000DE040000008094 +:103E8000020000900000161306010080824290BCE0 +:103E90000000161304010078096490B5000038058D +:103EA00004010080824290BC00000000000000007D +:103EB0000900003200000000000000E4030090321E +:103EC00011000004000000E0030037320000DE04AF +:103ED000000000FC1F40909C00003E059F000080F9 +:103EE000020090B20000000000000008094090327B +:103EF000000000000000000409C0FD3203090000BA +:103F0000000000280800363200005705000000308D +:103F1000080036D20000610500000044088000D28D +:103F20000000470504010080020084B2030E000077 +:103F300000000028080036328000570500000030DD +:103F4000080036D2000061050000004408C000D21D +:103F50000000470504010080020084B200004E0505 +:103F600000000044080001928002000000000000F0 +:103F7000070036328C0501000008000007003732C8 +:103F80000000161304100000078090B2000000002B +:103F900000180000074090320000000000000048B8 +:103FA000F2C138340000161312000080020000B085 +:103FB00018003600000000F8730A03F92000000022 +:103FC000000000E40300363209000002000000E0B7 +:103FD0000300373200000000000000E40340843298 +:103FE0000A000002000000E0030037328C050100E7 +:103FF000000000A802003732A0000000000000000E +:104000000900363200000000000000E00700003226 +:104010000000540506010000190090BC0000DE04F9 +:1040200000000080020000908C050100000000C824 +:1040300002003732800200000000003C08003632E7 +:1040400000000000000000340800013200005C05A0 +:1040500002000080D2E083BC0000000000000034B9 +:1040600008C083320000720500000080020000F0EA +:1040700000000000000000A0078083320000000064 +:1040800000000030D820833A00005A050401003CAB +:10409000D8E083BC00000000000100800200005056 +:1040A0000000000000000040080000320000000096 +:1040B00000000048080000328C050100000000C824 +:1040C0000200373200020000000000C8828D2C3A46 +:1040D000800000000000003C0800363200000000B4 +:1040E00000000078098078325A5A000004010080EC +:1040F000828D975C00006A0502010048A89E84BA80 +:1041000000000000000000481880843A00006805A4 +:104110000601003C28C083BC0000000000000078BD +:10412000098584301000000000000048888D843626 +:1041300000006F0590010048E8A584BA0000000067 +:10414000000000481880843A000000000000004889 +:104150000885843000000000040100800285845C32 +:104160000000000000010040084000520000000074 +:10417000000000E40300833201000002000000E0C0 +:10418000030037320C0078050000002CD8A082F91B +:1041900005000002000000E00300373200000000CC +:1041A0000000008002000030000000000001003824 +:1041B00008403E7200000000000000E403C08232AC +:1041C00002000002000000E003003732020000029B +:1041D000000000E003003732000000000000008013 +:1041E0000200003000007A0580000080F2403EB6F8 +:1041F0000000000000010080020000700000810546 +:104200009F000080020090B2000000000000000843 +:1042100009409032000000000000000409C0FD3297 +:1042200000000000000000840E8090320000DE04D8 +:10423000000000880E40909208000000000000F886 +:1042400093400139000087059F000080020090B272 +:10425000000000000000000809409032000000004B +:104260000000000409C0FD32000000000000002032 +:104270000740F5320000000000080020070000326F +:10428000000000000010002007C0F5320000000010 +:10429000001800200740F632000000000020002037 +:1042A0000780F632000000000028002007C0F63228 +:1042B00000000000003000200700F732000000007E +:1042C000003800200780FF3200000000000000D806 +:1042D0000200003200000000000000000740093228 +:1042E000000000000008000077C02937000000002F +:1042F000001000000780903200000000001800004D +:10430000074090320000161312000048F2C138B482 +:1043100018003600000000F8730A03F900000000DE +:1043200000000008C80100340000F603000000FC93 +:104330000200009200009A0580010080F24190B6D0 +:1043400000009B05000000C82F81FC9400000000C5 +:10435000000000C82F81FC35000000000000008034 +:104360000F45903000009E0502000080027EF8BCE0 +:1043700000000000000000840F00F8320000000080 +:10438000000000001940F837000000000000008421 +:104390003F40F83700000000000000840F64F83A46 +:1043A00000000000000000001900F83700000000C5 +:1043B000000000803F00F8370000DE0400000080AD +:1043C0000F24F89A0000A60580010080F24190B603 +:1043D0000000DE04000000C83F81FC940000DE0401 +:1043E000000000C83F81FC950000A9050401008081 +:1043F000024090BC000000000000000409C0003230 +:104400000000DE04000000E41E40909C000000005C +:10441000000000A8220090370000DE04000086C0E3 +:104420000740909208000000000000F89340013916 +:104430000D000000000000FC02E41638000000003F +:1044400000000000090002320000B40504000080F2 +:104450000200B0B200000000000000000B000032BB +:1044600020000000000000A0820D2A3A0000AF05E5 +:1044700004010000190090BC0000B60500000028EF +:104480007901009400000000000000C83F80FC3467 +:1044900040800000000000280980363200008111B1 +:1044A000000000D8020000D20000020404000080D6 +:1044B000028092BC18000000000000F8730A033963 +:1044C00002043600000000C002003692EA05C00572 +:1044D00004010080824D90BC00000000000000EC50 +:1044E0000F00153200FE1F00000000F00F003732F1 +:1044F000F0FF0000000000E80F00363298050000D1 +:10450000000000F40F0036320000C605000000C8AD +:104510004F80FC953623161304010080824D90BC19 +:1045200000000000000000EC0F80143200F81F00B3 +:10453000000000F00F003732C0FF0000000000E86C +:104540000F00363298270000000000F40F003632CA +:1045500000000000000000C84F80FC340400000090 +:10456000000000608F4D903A00001613600100803B +:10457000020000B0000016137A010080020000B0B3 +:104580000000421100000080020000D00000DE04A4 +:1045900000000080020000900000CD058001008036 +:1045A000024090B600000000000000C86F80FC349C +:1045B0000000CF0580010080124090B6000000008E +:1045C000000000C85F80FC340000DE0400000080B2 +:1045D000020000900000D20504010080B24190B0BA +:1045E0008007DE04000000C88F8DFC910000D40518 +:1045F00080000080124090B60000D505000000C881 +:104600007F80FC9500000000000000C87F80FC3423 +:104610000000D70580000080024090B60000D80559 +:10462000000000C88F80FC9500000000000000C85A +:104630008F80FC340000DA0580000080424090B694 +:104640000000DB05000000C89F80FC950000000012 +:10465000000000C89F80FC340000DD058000008061 +:10466000324090B60000DE05000000C8AF80FC9527 +:1046700000000000000000C8AF80FC340000E1052D +:1046800080000080224090B6841100000000008C61 +:104690000E0036320000E305000000C81F81FC95C3 +:1046A000AA1100000000008C0E003632000000004D +:1046B000000000C81F81FC340000161306010080B2 +:1046C0008202F5BC00001613030000780900F5BD56 +:1046D0000000161304010080E225F5B5100000006B +:1046E0000000004C1F2416380000DE0400000050BB +:1046F0001F00F59C8007161304000080828DFCB01B +:104700000000EC059F000080020090B20000000055 +:104710000000000809409032000000000000000482 +:1047200009C0FD3200000000000000001700F53A4B +:104730008C04010000080000070037320000161347 +:1047400004100000078090B2000000000018000074 +:10475000074090320000161312000040F2C138B436 +:1047600018003600000000F8730A03F90000DE04A8 +:1047700000000080020000900000DE04000000EC59 +:10478000034090920000161304000080024090BC89 +:104790000000F505B20000D8020000B200000000E1 +:1047A000000201EC16E46E3A08000000000000F878 +:1047B0009340013900001F06171001F802006EB285 +:1047C0000600000604010080828D2FB00300000067 +:1047D000000000F8828D2F3200C061100000002818 +:1047E000098036D200000000000201EC16C06E3CC9 +:1047F00000000000001886C80600003218003600CD +:10480000000000F8730A03F900000106000000D060 +:1048100002000092000007060419868002806CBC2A +:10482000000016138001008012802FB600000000E7 +:104830000000000009006E3200000000C108000402 +:1048400009006E3200000000C01586780FC06C327F +:1048500000000D068001008022802FB600000D06AA +:10486000001886C8064000920000161380010080E0 +:1048700022802FB6000000000040000009006E32C8 +:1048800000000000C248000409006E320000000071 +:10489000C01686780FC06C3200000D0680010080C3 +:1048A00012802FB600000000001886C806000032F3 +:1048B0000040000000000028098036320000150684 +:1048C0000402018002C06EBC00006110000201EC15 +:1048D00016C06EDC000013068000008002802FB638 +:1048E00000001506810000F822802FB40000150694 +:1048F000001886C80640009200001506820000F8E5 +:1049000012802FB400000000001886C80600003294 +:10491000000016130401008002002DBC00001613D5 +:104920000401008002802DBC00000000001086C839 +:1049300006000032000000000000000007C00A323C +:10494000003800000008000007003632000016138F +:1049500004100000070090B20000000000180000E2 +:10496000074090320000161312000040F2C138B424 +:1049700018003600000000F8730A03F90000000078 +:10498000170100F8A2802F34000016130210868051 +:1049900072826CBC00000000001086A842806C3758 +:1049A00000002A061200703802007EB200001613C2 +:1049B0001200703C02007EB200001613120070302C +:1049C00002007EB2000016131200703402007EB2A4 +:1049D0000000210602010080B2822ABC0000000013 +:1049E000170000D00200003206000006040100801B +:1049F000828D2FB00000FA050403018002C06EBC56 +:104A000000003506000000800200009000002C0627 +:104A10000403018002C06EBC00003506001086C889 +:104A200046802A9600000000001086C846802A367C +:104A3000000030068000008012802FB6030032068E +:104A4000220000F8828D2FB200003206001886C8BE +:104A500006000092000035068000008022802FB6FC +:104A600000000000C20100F802802F3500C0611074 +:104A700000000028098036D200000000000201EC8E +:104A800016C06E3C18003600000000F8730A03F9E7 +:104A900000000000001001E006802F32000000003E +:104AA000000000A8E100003400000000A20000FCAB +:104AB000020000320000F60380010080A2802FB6C1 +:104AC00000003B06B90100D8028001B20000F603E5 +:104AD000000000F802000092000000000000003812 +:104AE0001880F73A0000000000000038F8BF83305B +:104AF00000003F0604010080F2BD83BC0000F60305 +:104B0000A90000F80200009200C046061801000C3F +:104B1000A8CD3EB200004206840000741F40F7BAE0 +:104B20000000F603A90000F8020000920000000057 +:104B3000000000740F00003200C046061801000C8F +:104B4000A8CD3EB218003600000000F8738A03F9C1 +:104B500000004306000000B00200009200000000C8 +:104B60000000007C0F80833200000000002800005D +:104B70000700003200000000003000000700003293 +:104B800000010080003800000700373200000000FC +:104B9000003C000C0780833200001613120000480E +:104BA00002C080B20000161380010080A2802FB6E0 +:104BB0000000F603A9000008E80100940000540674 +:104BC00004010080A2C0EDBC52000000000000748F +:104BD0000E00363200000000000000C00E4001321E +:104BE000407E0500000000B40E00373200000000D7 +:104BF000000000C40E80073264005A06000000CC9A +:104C00000E003692640016130401008082CDEDBCC4 +:104C100029000000000000740E0036320000000081 +:104C2000000000C00E400032A08C0000000000B464 +:104C30000E00363200000000000000C40EC000323A +:104C400000000000000000CC0E80023210000000C6 +:104C5000000000E4337BEC391E000001000000E09E +:104C60000300373200000000000000C86EC0EC37BF +:104C70000000DE04000000D80EC0ED920000161304 +:104C800004310280A2DB2CBC00001613040100805A +:104C9000028080B200001613021C018052C06EBC5C +:104CA0002C0016130201008082CD81BC3F00161338 +:104CB0000200008082CD81BC3600670604000080BF +:104CC00082CD81BC0F0000000000001009003632C8 +:104CD0002C0000000000001489CD813C10008012DF +:104CE000001C011459E46ED96F0600000000008812 +:104CF00082CD813A0000161304010080028080B248 +:104D00000000161304310280A2DB2CBC0000161335 +:104D10000218018092C06EBC2C00161302000080A5 +:104D200082CD81BC10000000000000100900363266 +:104D3000100080120018011479E06ED96F0600008F +:104D40000000008882CD813AAE060000001801887C +:104D500082CD6E3AB70600000018018882CD6E3A07 +:104D6000C00600000018018882CD6E3AC906000016 +:104D70000018018882CD6E3AD20600000018018822 +:104D800082CD6E3ADB0600000018018882CD6E3AB3 +:104D9000E40600000018018882CD6E3AED0600009E +:104DA0000018018882CD6E3AF606000000180188CE +:104DB00082CD6E3AFF0600000018018882CD6E3A5F +:104DC000080700000018018882CD6E3A1107000024 +:104DD0000018018882CD6E3A1A0700000018018879 +:104DE00082CD6E3A230700000018018882CD6E3A0A +:104DF0002C0700000018018882CD6E3A35070000AC +:104E00000018018882CD6E3A3E0700000018018824 +:104E100082CD6E3A470700000018018882CD6E3AB5 +:104E2000500700000018018882CD6E3A5907000033 +:104E30000018018882CD6E3A6207000000180188D0 +:104E400082CD6E3A6B0700000018018882CD6E3A61 +:104E5000740700000018018882CD6E3A7D070000BB +:104E60000018018882CD6E3A86070000001801887C +:104E700082CD6E3A8F0700000018018882CD6E3A0D +:104E8000980700000018018882CD6E3AA107000043 +:104E90000018018882CD6E3AAA0700000018018828 +:104EA00082CD6E3AB30700000018018882CD6E3AB9 +:104EB000BC0700000018018882CD6E3AC5070000CB +:104EC0000018018882CD6E3ACE07000000180188D4 +:104ED00082CD6E3AD70700000018018882CD6E3A65 +:104EE000E00700000018018882CD6E3AE907000053 +:104EF0000018018882CD6E3AF20700000018018880 +:104F000082CD6E3AFB0700000018018882CD6E3A10 +:104F1000040800000018018882CD6E3A0D080000D8 +:104F20000018018882CD6E3A16080000001801882A +:104F300082CD6E3A1F0800000018018882CD6E3ABB +:104F40000000A803000000D4020000920000EC0260 +:104F5000000000800200009028080000001C01886A +:104F600082CD6E3A2D080000001C018882CD6E3A79 +:104F700032080000001C018882CD6E3A370800001C +:104F8000001C018882CD6E3A3C080000001C01889C +:104F900082CD6E3A41080000001C018882CD6E3A35 +:104FA00046080000001C018882CD6E3A4B080000C4 +:104FB000001C018882CD6E3A50080000001C018858 +:104FC00082CD6E3A55080000001C018882CD6E3AF1 +:104FD0005A080000001C018882CD6E3A5F0800006C +:104FE000001C018882CD6E3A64080000001C018814 +:104FF00082CD6E3A69080000001C018882CD6E3AAD +:105000006E080000001C018882CD6E3A7308000013 +:10501000001C018882CD6E3A78080000001C0188CF +:1050200082CD6E3A0000B003000000D4020000926E +:105030000000C603000000D4020000920000710AC4 +:10504000000000100880019200001613000000808C +:105050000200009000001613000000800200009083 +:1050600000001613000000800200009000001613DC +:105070000000008002000090000016130000008075 +:105080000200009000001613000000800200009053 +:1050900000001613000000800200009000001613AC +:1050A0000000008002000090000016130000008045 +:1050B000020000900000B10A000000100880009279 +:1050C000000016130000008002000090000016137C +:1050D0000000008002000090000016130000008015 +:1050E00002000090000016130000008002000090F3 +:1050F000000016130000008002000090000016134C +:1051000000000080020000900000161300000080E4 +:1051100002000090000016130000008002000090C2 +:105120000000161300000080020000900000C00A7A +:10513000000000100880009200001613000000809C +:105140000200009000001613000000800200009092 +:105150000000130B0000001008400192000016131D +:105160000000008002000090000016130000008084 +:105170000200009000001613000000800200009062 +:1051800000001613000000800200009000001613BB +:10519000000000800200009000001B0B00000010C7 +:1051A00008C000920000161300000080020000906A +:1051B00000001B0B0000001008C000920000220E2F +:1051C000000000100840019200001613000000804B +:1051D0000200009000001B0B0000001008C00092AD +:1051E000000016130000008002000090000016135B +:1051F00000000080020000900000161300000080F4 +:105200000200009000002E0B0000001008C0009269 +:1052100000001613000000800200009000002E0B1A +:105220000000001008C000920000220E00000010D4 +:105230000840019200001613000000800200009058 +:1052400000002E0B0000001008C000920000161392 +:105250000000008002000090000016130000008093 +:105260000200009000001613000000800200009071 +:1052700000002C0B0000001008C000920000161364 +:10528000000000800200009000002C0B00000010C5 +:1052900008C000920000220E000000100840019299 +:1052A00000001613000000800200009000002C0B8C +:1052B0000000001008C000920000161300000080DB +:1052C0000200009000001613000000800200009011 +:1052D000000016130000008002000090000016136A +:1052E00000000080020000900000F50B000000109C +:1052F00008C000920000180B000000100800019286 +:105300000000130B0000001008400192000016136B +:1053100000000080020000900000161300000080D2 +:1053200002000090000016130000008002000090B0 +:105330000000161300000080020000900000161309 +:1053400000000080020000900000161300000080A2 +:10535000020000900000EB0B00000010088000929B +:105360000000180B00000010080001920000130B51 +:105370000000001008400192000016130000008099 +:105380000200009000001613000000800200009050 +:1053900000001613000000800200009000001613A9 +:1053A0000000008002000090000016130000008042 +:1053B0000200009000001613000000800200009020 +:1053C0000000EB0B00000010080001920000180B19 +:1053D00000000010080001920000130B00000010F4 +:1053E00008400192000016130000008002000090A7 +:1053F0000000161300000080020000900000161349 +:1054000000000080020000900000161300000080E1 +:1054100002000090000016130000008002000090BF +:105420000000161300000080020000900000790CBC +:1054300000000010088000920000180B000000100F +:10544000080001920000130B0000001008400192B8 +:1054500000001613000000800200009000001613E8 +:105460000000008002000090000016130000008081 +:10547000020000900000161300000080020000905F +:1054800000001613000000800200009000001613B8 +:1054900000000080020000900000790C0000001065 +:1054A000080001920000180B000000100800019293 +:1054B0000000130B000000100840019200001613BA +:1054C0000000008002000090000016130000008021 +:1054D00002000090000016130000008002000090FF +:1054E0000000161300000080020000900000161358 +:1054F000000000800200009000002D0B0000001052 +:105500000880009200001613000000800200009046 +:1055100000002D0B00000010088000920000220EF9 +:1055200000000010084001920000161300000080E7 +:10553000020000900000161300000080020000909E +:1055400000001613000000800200009000001613F7 +:105550000000008002000090000016130000008090 +:105560000200009000002D0B0000001008000192C6 +:1055700000001613000000800200009000002D0BB8 +:1055800000000010080001920000220E0000001030 +:1055900008400192000016130000008002000090F5 +:1055A0000000161300000080020000900000161397 +:1055B0000000008002000090000016130000008030 +:1055C000020000900000161300000080020000900E +:1055D00000001613000000800200009000007D080B +:1055E0000000001008000192000016130000008067 +:1055F0000200009000007D080000001008400192A9 +:105600000000161300000080020000900000161336 +:1056100000000080020000900000161300000080CF +:1056200002000090000016130000008002000090AD +:105630000000161300000080020000900000430EDE +:1056400000000010084001920000390E0000001018 +:10565000084001920000430E000000100840019233 +:105660000000130B00000010084001920000161308 +:1056700000000080020000900000430E00000010B7 +:105680000840019200001613000000800200009004 +:105690000000161300000080020000900000B90A0C +:1056A00000000010084000920000B90A000000103D +:1056B000088000920000B90A0000001008C00092A3 +:1056C0000000B90A00000010080001920000BE0AA4 +:1056D00000000010084001920000B90A000000100C +:1056E000088001920000B90A0000001008C0019271 +:1056F0000000161300000080020000900000161346 +:1057000000000080020000900000161300000080DE +:10571000020000900000F60C0000001008800092CB +:105720000000F60C0000001008C000920000F60C0B +:1057300000000010080001920000130B0000001090 +:105740000840019200001613000000800200009043 +:105750000000F60C0000001008C0019200001613B3 +:10576000000000800200009000001613000000807E +:10577000020000900000161300000080020000905C +:1057800000001613000000800200009000001613B5 +:10579000000000800200009000001613000000804E +:1057A0000200009000004D0E000000100840019221 +:1057B0000000161300000080020000900000161385 +:1057C000000000800200009000001613000000801E +:1057D00002000090000016130000008002000090FC +:1057E0000000CB0E00000010084001920000CF0E18 +:1057F00000000010084001920000310E000000106F +:10580000084001920000CF0E0000001008400192F5 +:1058100000007D08000000100840019200001613EF +:1058200000000080020000900000CF0E0000001079 +:105830000840019200007E0800000010080002925B +:1058400000001613000000800200009000001613F4 +:1058500000000080020000900000D00E0000001048 +:10586000084001920000310E000000100840019233 +:105870000000D00E000000100840019200007D08DA +:105880000000001008400192000016130000008084 +:10589000020000900000D00E0000001008400192AD +:1058A0000000161300000080020000900000161394 +:1058B000000000800200009000001613000000802D +:1058C000020000900000D50E000000100880009239 +:1058D0000000D50E0000001008C000920000D50E98 +:1058E00000000010080001920000130B00000010DF +:1058F0000840019200001613000000800200009092 +:105900000000D50E0000001008C001920000161320 +:1059100000000080020000900000161300000080CC +:1059200002000090000016130000008002000090AA +:105930000000161300000080020000900000161303 +:10594000000000800200009000001613000000809C +:10595000020000900000161300000080020000907A +:105960000000A00A0000001008400092000016137A +:10597000000000800200009000001613000000806C +:10598000020000900000161300000080020000904A +:105990000000161300000080020000900000EA0ED4 +:1059A00000000010088000920000EA0E00000010C5 +:1059B00008C000920000EA0E0000001008000192EA +:1059C0000000130B000000100840019200001613A5 +:1059D00000000080020000900000EA0E00000010AD +:1059E00008C0019200001613000000800200009021 +:1059F0000000161300000080020000900000161343 +:105A000000000080020000900000030F0000001062 +:105A1000088000920000030F0000001008C00092F0 +:105A20000000030F00000010080001920000130B9B +:105A300000000010084001920000161300000080D2 +:105A4000020000900000030F0000001008C0019247 +:105A500000001613000000800200009000007D0886 +:105A600000000010080000920000161300000080E3 +:105A70000200009000007D080000001008800092E5 +:105A80000000150F0000001008C0009200007D0803 +:105A9000000000100800019200007D0800000010C6 +:105AA00008400192000016130000008002000090E0 +:105AB0000000161300000080020000900000161382 +:105AC000000000800200009000001613000000801B +:105AD00002000090000016130000008002000090F9 +:105AE00000007D0800000010088000920000260FD2 +:105AF000000000100880009200007D0800000010E7 +:105B00000800019200007D0800000010084001928A +:105B10000000161300000080020000900000161321 +:105B200000000080020000900000161300000080BA +:105B30000200009000001613000000800200009098 +:105B400000001613000000800200009000007D0895 +:105B500000000010088000920000260F00000010D6 +:105B60000800019200007D0800000010080001926A +:105B700000007D080000001008400192000016138C +:105B8000000000800200009000001613000000805A +:105B90000200009000001613000000800200009038 +:105BA0000000161300000080020000900000161391 +:105BB000000000800200009000001613000000802A +:105BC0000200009000007D08000000100880009294 +:105BD00000001613000000800200009000007D0805 +:105BE0000000001008400192000016130000008021 +:105BF00002000090000016130000008002000090D8 +:105C00000000161300000080020000900000161330 +:105C100000000080020000900000161300000080C9 +:105C2000020000900000FA0E0000001008800092B0 +:105C30000000FA0E0000001008C000920000FA0EEA +:105C400000000010080001920000130B000000107B +:105C5000084001920000161300000080020000902E +:105C60000000FA0E0000001008C001920000161398 +:105C70000000008002000090000016130000008069 +:105C80000200009000001613000000800200009047 +:105C900000001613000000800200009000001613A0 +:105CA0000000008002000090000016130000008039 +:105CB000020000900000390F00000010080002925E +:105CC0000000161300000080020000900000161370 +:105CD0000000008002000090000016130000008009 +:105CE00002000090000016130000008002000090E7 +:105CF0000000161300000080020000900000C00A9F +:105D00000000001008C0019200001613000000807F +:105D100002000090000016130000008002000090B6 +:105D20000000130B00000010084001920000161341 +:105D300000000080020000900000010B0000001035 +:105D400008C00192000016130000008002000090BD +:105D500000001613000000800200009000001613DF +:105D600000000080020000900000C00A0000001047 +:105D700008800092000016130000008002000090CE +:105D80000000161300000080020000900000130BBA +:105D9000000000100840019200001613000000806F +:105DA000020000900000010B0000001008C00192EA +:105DB000000016130000008002000090000016137F +:105DC0000000008002000090000016130000008018 +:105DD000020000900000260D0000001008800092D4 +:105DE0000000161300000080020000900000260D45 +:105DF00000000010088000920000220E0000001039 +:105E0000084001920000161300000080020000907C +:105E10000000260D000000100880009200001613FC +:105E200000000080020000900000161300000080B7 +:105E30000200009000001613000000800200009095 +:105E40000000260D0000001008000192000016134B +:105E500000000080020000900000260D00000010ED +:105E6000080001920000220E00000010084001927C +:105E70000000161300000080020000900000260DB4 +:105E800000000010080001920000161300000080BE +:105E90000200009000001613000000800200009035 +:105EA0000000161300000080020000900000260D84 +:105EB000000000100800019200001613000000808E +:105EC000020000900000260D000000100800019262 +:105ED0000000220E0000001008400192000016137E +:105EE00000000080020000900000260D000000105D +:105EF00008000192000016130000008002000090CC +:105F0000000016130000008002000090000016132D +:105F100000000080020000900000260D000000102C +:105F2000088000920000161300000080020000901C +:105F30000000260D00000010088000920000220ED4 +:105F400000000010084001920000161300000080BD +:105F5000020000900000260D000000100880009252 +:105F600000001613000000800200009000001613CD +:105F70000000008002000090000016130000008066 +:105F80000200009000001613000000800200009044 +:105F90000000161300000080020000900000260D93 +:105FA0000000001008C001920000220E0000001046 +:105FB00008400192000016130000008002000090CB +:105FC0000000260D0000001008C00192000016130A +:105FD0000000008002000090000016130000008006 +:105FE00002000090000016130000008002000090E4 +:105FF0000000AB0D00000010088000920000161396 +:1060000000000080020000900000161300000080D5 +:106010000200009000007D0800000010084001927E +:106020000000161300000080020000900000AB0D7D +:10603000000000100880009200001613000000808D +:106040000200009000001613000000800200009083 +:106050000000161300000080020000900000AB0D4D +:10606000000000100880009200001613000000805D +:106070000200009000001613000000800200009053 +:1060800000007D0800000010084001920000161377 +:1060900000000080020000900000AB0D0000001026 +:1060A00008C001920000161300000080020000905A +:1060B000000016130000008002000090000016137C +:1060C0000000008002000090000016130000008015 +:1060D00002000090000016130000008002000090F3 +:1060E00000001613000000800200009000007D08F0 +:1060F000000000100840019200001613000000800C +:10610000020000900000B50D0000001008C00192D0 +:10611000000016130000008002000090000016131B +:1061200000000080020000900000161300000080B4 +:106130000200009000001613000000800200009092 +:1061400000001613000000800200009000001613EB +:10615000000000800200009000007D080000001098 +:106160000840019200001613000000800200009019 +:106170000000B50D0000001008800092000016130A +:106180000000008002000090000016130000008054 +:106190000200009000001613000000800200009032 +:1061A000000016130000008002000090000016138B +:1061B0000000008002000090000016130000008024 +:1061C000020000900000B30E000000100840019291 +:1061D000000016130000008002000090000016135B +:1061E00000000080020000900000161300000080F4 +:1061F0000200009000008608000000100840009295 +:10620000000016130000008002000090000016132A +:1062100000000080020000900000161300000080C3 +:1062200002000090000016130000008002000090A1 +:106230000000161300000080020000900000DD083E +:10624000000000100880009200001613000000807B +:106250000200009000001613000000800200009071 +:106260000000C6090000001008000192000016138B +:10627000000000800200009000008508000000106F +:10628000080001920000D0090000001008000192EF +:106290000000D00900000010080001920000D009A1 +:1062A000000000100800019200001613000000809A +:1062B0000200009000001613000000800200009011 +:1062C0000000EF0800000010088000920000161384 +:1062D000000000800200009000008508000000100F +:1062E00008000192000016130000008002000090D8 +:1062F000000016130000008002000090000000095A +:1063000000000010088000920000C4090000001086 +:10631000088000920000850800000010080001922B +:106320000000161300000080020000900000E60943 +:1063300000000010084000920000E6090000001074 +:10634000088000920000E6090000001008C00092DA +:1063500000008508000000100800019200001613DC +:106360000000008002000090000016130000008072 +:106370000200009000000C0A0000001008C000920B +:106380000000161300000080020000900000850845 +:1063900000000010080001920000161300000080A9 +:1063A0000200009000001613000000800200009020 +:1063B00000000F0A000000100800019200000F0A00 +:1063C0000000001008000192000085080000001085 +:1063D00008000192000016130000008002000090E7 +:1063E0000000161300000080020000900000110A57 +:1063F00000000010088000920000110A0000001048 +:1064000008C00092000085080000001008000192FA +:1064100000001613000000800200009000008508B4 +:1064200000000010084000920000DC09000000108D +:10643000088000920000DC090000001008C00092F3 +:106440000000850800000010080001920000850887 +:1064500000000010080000920000850800000010F5 +:10646000084000920000250A0000001008800092F9 +:106470000000250A0000001008C0009200008508F6 +:1064800000000010080001920000161300000080B8 +:10649000020000900000161300000080020000902F +:1064A0000000600A000000100880009200008508CB +:1064B0000000001008C000920000850800000010D5 +:1064C00008000192000016130000008002000090F6 +:1064D00000001613000000800200009000003F0A38 +:1064E00000000010088000920000161300000080D9 +:1064F00002000090000085080000001008000192D2 +:106500000000161300000080020000900000161327 +:1065100000000080020000900000EC080000001065 +:106520000880009200001613000000800200009016 +:1065300000008508000000100800019200001613FA +:106540000000008002000090000016130000008090 +:10655000020000900000540A000000100880009221 +:106560000000540A0000001008C0009200008508D6 +:1065700000000010080001920000161300000080C7 +:10658000020000900000161300000080020000903E +:1065900000001C0A000000100880009200001C0A85 +:1065A0000000001008C000920000850800000010E4 +:1065B0000800019200001613000000800200009005 +:1065C00000001613000000800200009000006D0A19 +:1065D000000000100880009200006D0A000000100A +:1065E00008C0009200008508000000100800019219 +:1065F0000800F303001801E8762081990800EF03F2 +:10660000001801E87620819900004B1200000080FC +:10661000020000F0080082081D1901E8762081B907 +:106620000000F303000000F862812F950000F303DF +:106630008000008002812FB62A0016131200002C61 +:1066400082CD2EB20000F303000000F802812F94E7 +:106650000800F303001C01E876208199000016135E +:10666000800F018002C06EB600000000000000D85C +:106670000200003200000000000E01EC06C06E3582 +:106680005400000000000000070036320000000047 +:10669000000000BCA8002D37B40401000008000071 +:1066A000C7CD8B3A000000000000007899C02C375D +:1066B000B400000000000078898D973A000016139E +:1066C0000210000087BF97BA000000000018000009 +:1066D0000740FE320000161312000040F2C138B429 +:1066E000000000000090007809006E3200001613D0 +:1066F00004A0000009806EB20000950804A5000403 +:1067000009806EB200000000000000040900903211 +:106710000000161302010080026490BC000098087B +:1067200004010004096490BC0000000000000004A3 +:1067300009400032080000006E3402E81624903947 +:1067400000009908B71002E0068097B200009C088C +:1067500080000080F280FCB600009D08000000C8A8 +:10676000FF80FC9400009E089F990080821BEEBC75 +:1067700000000000009800E00E006E3200000000F3 +:10678000A70000800200003018003600000000F86A +:10679000730A03F9000000000010021C09006E32A9 +:1067A0004000A3080601008082CD91BC00C0A4086F +:1067B000001802E00680369200E00000001802E0B7 +:1067C00006803632000000000000002009800332FD +:1067D0000000A70880D7018032C06EB6000000001C +:1067E000000000204900923A0000000000980118C3 +:1067F00009006E3200000000000A022409C06E3257 +:106800000000000000C0012809806E320000B508B9 +:10681000800E018012C06EB602000000003C02EC47 +:106820000600363200000000000000004901923AE4 +:106830000000B10880D6018042C06EB60082000020 +:10684000001002E0A6CD913200A00000002C02E86A +:10685000060036322800BF08003A02EC06003692E5 +:1068600000000000D301001CD9C191340082000057 +:10687000001002E0A6CD913200A00000002C02E83A +:10688000060036323400BF08003A02EC06003692A9 +:1068900004000000003C02EC060036322800000034 +:1068A00000000000890D923A0000BB0880D60180EC +:1068B00042C06EB600860000001002E0A6CD913204 +:1068C00004A00000002C02E8060036321400BF08C5 +:1068D000003A02EC0600369200000000D301001CD2 +:1068E000D9C1913400860000001002E0A6CD91329B +:1068F00004A00000002C02E8060036322000BF0889 +:10690000003A02EC0600369212000000003802EC59 +:1069100086CD913A08000000002802E886249039CC +:1069200000000000002002E0962414370000000060 +:10693000004001E0068091320000C508040100809B +:10694000028092BC0000000000C001E0060000329E +:1069500000000000003000E00600003200000000EF +:1069600000B000E00600003220000000000000003F +:10697000070036320000000000000078A9002D3723 +:106980000005010000080000C78D973A00000000D4 +:106990000000007899C02C3700010000000000784A +:1069A000898D973A000016130210000087BF97BA2E +:1069B00000000000001800000740FE32000016131F +:1069C00012000048F2C138B40000D20880D7012C70 +:1069D00009C06EB200000000DAD701EC06C06E35C7 +:1069E00000000000005A01EC0640ED32AE0000004D +:1069F000000000781900363AAF0016130401008039 +:106A0000828D97BC00000000005C01E806808B329C +:106A10000000D7088001008062C092B6000000002C +:106A2000000000F882812F3418003600000000F8C2 +:106A3000730A03F9000000000004013808C06E3238 +:106A40000000161304C9018002806EBC0000000023 +:106A5000006201EC06808332010085081201002CDF +:106A600082CD2EB2000016130000008002000090BC +:106A700000000000005401FC02C06E320000000063 +:106A8000000000D80280013200C0E3081801000CA9 +:106A9000A8CD3EB2208000000000000808803632F9 +:106AA0002D00EF031201002C82CD2EB20000161330 +:106AB0000000008002000090000000000062013829 +:106AC00008C06E320008008000000028090037323C +:106AD0000060EB1100000008088036F20000161379 +:106AE000870601EC16C06EBC000085080B00008014 +:106AF000020000B0000085088000008072812FB67F +:106B000000000000000000F872812F343D0085086D +:106B10001201002C82CD2EB200001613000000805E +:106B200002000090000016130407018012C06EBC22 +:106B30000000161380000080B2812FB60000EF081D +:106B4000000000F8B2812F940000161304A0001872 +:106B500008006EB2000016130406018002C06EBC6D +:106B600000009E1200000080020000F000000013F0 +:106B70000078016008006EF20000F508120100C8FC +:106B8000020020B20000F80800000080020000901F +:106B9000000005091201005C088020B20000F8081E +:106BA0001201006002802CB2000016130000008069 +:106BB000020000900000FA0804000080024080BC3F +:106BC00000000000000000F81F80FF3A0000FD08F0 +:106BD00080010080A2802FB618003600CA0000F89D +:106BE000730A03F9000016130401008002802DBC13 +:106BF000000085088000008072812FB63D001613CA +:106C00001200002C82CD2EB200008508000000F892 +:106C100072812F94000016130406018002C06EBC1E +:106C20000000000000BC001408806E320000F8086C +:106C3000120000C8020020B20000F6081200005C3A +:106C4000088020B20000161304A0001808006EB2DD +:106C5000000000000000007879613832000016134F +:106C60001218024CE2256EB20000161304010080D7 +:106C700002402DBC080000000010020078E16E39CF +:106C8000000000000018002007000032070000008C +:106C90000000003878CAE939000016130400003CEF +:106CA000084080B2000000000090006C08006E32C6 +:106CB000000000000098004C08006E32000016131F +:106CC0000400008032E186B200000000510000D8CC +:106CD00002000032000000004D00000067E0833E2B +:106CE00000000000000800000700803200000000E3 +:106CF0000010000007C086320000000000180000ED +:106D000007C084320000000000000018D8A0813CB9 +:106D10000000840904B000E0D6206EBC0000161309 +:106D200009010080020000B0000043090400003C9B +:106D3000D8E083BC0000161304010080028081BCEF +:106D4000000024098000008092802FB600001C09FA +:106D50001201000009C021B218003600000000F83E +:106D6000730A03F91D0000000000007809A4173819 +:106D70000000210904010080128097BC0000161356 +:106D800080010080A2802FB600001B09670000F878 +:106D9000A2802FB500001C090000000009C021924C +:106DA0000000230904000080228097BC0000161315 +:106DB00004010080328097BC00000000C90100D8A7 +:106DC00002408432000027090400008072802DBC3C +:106DD0000000161312000044E2E038B2000034094B +:106DE000510000D812802D9A0000000000000078A9 +:106DF000F98183340000161312000044E2E538B232 +:106E000000002C098000008082802FB60000F7115E +:106E100000A0015008006EF20000000000F801E040 +:106E20000600853200002E09120100E802C021B2DE +:106E300018003600000000F8730A03F90000320958 +:106E40000401008002802DBC000016138001008028 +:106E5000A2802FB600002D09670000F8A2802FB590 +:106E600000001613120000E802C021B20000161341 +:106E70000401008072802DBC00000000510000D889 +:106E800002000032000039092A010000D82080BA2F +:106E9000000038091201000009C021B218003600B4 +:106EA000000000F8730A03F900000000000000D899 +:106EB000024084321D0016130400008002A417B89B +:106EC00000000000CAE0006C08006E320000000004 +:106ED00000E8004C08006E320000161304F00018A1 +:106EE00008006EB2000000000000003818818335F1 +:106EF0000000100904B00080829B81BC00001613C2 +:106F00000D010080020000B0000016139F00001465 +:106F1000184081BC00000000CA0100F842802F35F3 +:106F200008A0100912010040A2CD39B200001613CA +:106F3000000000800200009000004E09293402B8D1 +:106F400008806EB2000046091201000009C021B29B +:106F500018003600000000F8730A03F91D00000055 +:106F60000000007809A4173800004B0904010080D4 +:106F7000128097BC0000161380010080A2802FB6FB +:106F800000004509670000F8A2802FB500004609FF +:106F90000000000009C0219200004D09040000809B +:106FA000228097BC0000161304010080328097BC39 +:106FB00000000000C90100D8024084320000000037 +:106FC00000000078F9818334000016131200004499 +:106FD000E2E538B2000056092800006CD8E086BA15 +:106FE0000000F61100A0015008006EF200005609E2 +:106FF0001DF801E0060085B20000560980000080FF +:1070000002812FB62A0016131200002C82CD2EB258 +:1070100000000000000000F802812F3400005C092D +:1070200004A000E0068081B20000000000BC00E87F +:107030000640813200000000009000E006C0863269 +:1070400000000000009800E006C084320000161323 +:107050000400008032E186B2000070090000008068 +:10706000020000900000620980010080A2802FB61B +:1070700000005F091201000009C021B218003600AB +:10708000000000F8730A03F91D0062090401008082 +:1070900002A417B80000161380000080E2802FB60B +:1070A00000005E09000000F8E2802F94000000005C +:1070B00000E0006C08006E3200000000CAE8004CDE +:1070C00008006E32000016130400008032E186B220 +:1070D0000000161304F0001808006EB200006B09DF +:1070E00004B00080829B81BC000016130D0100805B +:1070F000020000B0000016139F000014184081BC6D +:1071000000000000CA0100F842802F3508A01613C5 +:1071100012000040A2CD39B20000000000A000E043 +:107120000680813200000000009800E006C0843232 +:1071300000000000009000E006C086320000161338 +:107140000400008032E186B20000000000BC00E8CC +:1071500006408132000076092A5D01E806808BB284 +:10716000000073091201000009C021B218003600A6 +:10717000000000F8730A03F91D007609040100807D +:1071800002A417B80000161380000080E2802FB61A +:1071900000007209000000F8E2802F9410247909A1 +:1071A000370000F8A28D2FB13D0016131200002CFD +:1071B00082CD2EB200000000000000F872812F3452 +:1071C00008000000CA1C01E8762081390000541034 +:1071D0000000002CF90100F400007F09800000800D +:1071E000E2802FB600007E091201000009C021B222 +:1071F00018003600000000F8730A03F91D0016138A +:107200000401008002A417B800001613800100805A +:1072100082802FB60000161304010080C20003BC58 +:10722000100000000018008067A173393000F603D9 +:107230001201005CA28D2CB2000016130000008029 +:107240000200009000008A098000008092802FB622 +:1072500018003600000000F8730A03F91D00161329 +:107260000400007809A417B8000089090400008010 +:10727000228097BC0000161304010080328097BC66 +:1072800000000000C90100D802408432000016133B +:1072900004010080D2E083BC000016132A000078AD +:1072A000F98183B40000161312000044E2E538B2FD +:1072B0000000641100000030030038F20000920961 +:1072C0001D000038188183B50000920980000080FD +:1072D00002812FB62A0016131200002C82CD2EB286 +:1072E00000000000000000F802812F340000161397 +:1072F000870601EC16C06EBC000096090B000080EA +:10730000020000B000000000CA0100F842802F34E3 +:1073100008C0161312000040A2CD39B2000099092E +:107320008000008082802FB60000F71100A001507D +:1073300008006EF20000000000F801E0060085324F +:1073400000009B091201000009C021B2180036009C +:10735000000000F8730A03F90000BD092A3502B8DD +:1073600008806EB200009E091201000009C021B21F +:1073700018003600000000F8730A03F9000000004E +:10738000000000F8A2802F350000B509040000803D +:10739000026180BC0000AD0980B8000009C06EB277 +:1073A0004000A50904000080820D90BC80001613E7 +:1073B00004010080820D90BC0000A50902B000808D +:1073C000821B84BC0000AD09000000F8B2812F943C +:1073D000000016130407018012C06EBC00001613D3 +:1073E00080000080B2812FB60000161380D6018085 +:1073F00052C06EB60000000000D601EC56C06E34DC +:1074000000000000000000601800863A0000000044 +:1074100000000080B701783400000000007801E02F +:10742000060086324000BD0904000080820D90BC39 +:107430000000161304A0001808006EB200009E128F +:1074400000000000D82080FA000016130600003C5F +:10745000182084BC0000161304B0003C88DB83BEF7 +:107460000000161380010080C20178B60000000001 +:1074700000000080F720783A00000000587801E012 +:10748000F620863A00000C0900000004F860809A9B +:107490000000B80980B9000009C06EB22F00BD0914 +:1074A0001201002C82CD2EB20000161300000080C5 +:1074B000020000904000BA0904010080820D90BCD7 +:1074C0003800BC09000000780900369280001613CD +:1074D00004010080820D90BC39000000000000789B +:1074E00009003632000016131200002CE2E52EB21D +:1074F000000016138001008082802FB60000161352 +:1075000004010080C20003BC1000000000180080CD +:1075100067A1733900000000005C01E806808B322F +:1075200010240000000000F8A28D2F3130008508E3 +:107530001201005CA28D2CB2000016130000008026 +:10754000020000900000161380010080C2812FB657 +:1075500000000009000000F8C2812F950000000023 +:10756000005401FC02C06E3200000000000000D890 +:107570000280013200C0CC091801000CA8CD3EB237 +:107580002080000000000008088036322D00EF0344 +:107590001201002C82CD2EB20000161300000080D4 +:1075A00002000090000000000062013808C06E3246 +:1075B0000008008000000028090037320060EB114D +:1075C00000000008088036F20000DA0900000080A0 +:1075D000020000900000D20980000080C2812FB616 +:1075E0000000D50900D001E806000092000000006C +:1075F000000000F8C2812F350000D50904D10180B8 +:1076000002806EBC0000000000D601EC26C06E3483 +:107610000000D7098000008092812FB60000DA09AF +:1076200000C801E80600009200000000000000F819 +:1076300092812F350000DA0904C9018002806EBCF6 +:107640000000000000D601EC16C06E341100850861 +:107650001201002C82CD2EB2000016130000008013 +:1076600002000090000085089A0100F842812FB5C1 +:107670000000E309120100C8020020B2000000006F +:10768000005C01EC0640003200008508370000F87D +:1076900042812FB400000000000000F872812F34F6 +:1076A0003D0085081201002C82CD2EB20000161379 +:1076B00000000080020000900000EE091201005C52 +:1076C000088020B20000DE091201006002802CB2A6 +:1076D0000000161300000080020000900000EB097B +:1076E000120100C8020020B200008508370000F82F +:1076F000D2812FB400000000000000F872812F3406 +:107700003D0085081201002C82CD2EB20000161318 +:1077100000000080020000900000EE091201005CF1 +:10772000088020B20000E7091201006002802CB23C +:10773000000016130000008002000090000000000E +:107740000000007879613832000016131218024CDC +:10775000E2256EB200000000003402B808806E32EC +:107760000000000000A0015008006E320000000080 +:107770000078016008006E320000F5099D110234A6 +:1077800009006EB20000000000F0018808006E32AF +:107790000000121200A8010809006EF200000000AB +:1077A000D4F801E00600853200000000DA5C01E850 +:1077B00006808B3200006411DD000030030038F2D7 +:1077C0000000FB092329020409806EB23E00161353 +:1077D0001200002C82CD2EB20800FF091D1C01E80A +:1077E000762081B90000FF098000008002812FB659 +:1077F0002A0016131200002C82CD2EB200000000C9 +:10780000000000F802812F34000054100000002C0A +:10781000F90100F40000030A9D010080074093B2C3 +:107820000000000000300080078088320000000067 +:10783000003800800700EE320000000000080080E1 +:1078400007C0853200000000001000800740903221 +:107850001000000000180080878D853700000000B0 +:107860000020008007008632000000000028008011 +:107870000700853200000A0A1201000009C021B287 +:1078800018003600000000F8730A03F93000F60310 +:107890001201005CA28D2CB20000161300000080C3 +:1078A000020000900012161304010080A28D2FB078 +:1078B0000000000000CC017809806E3200008508CD +:1078C000DCD101E806809792130085081201002C94 +:1078D00082CD2EB20000161300000080020000903E +:1078E0000000E30F00000018094081F20000C70FFC +:1078F00000A8012009006EF20000850880010080C8 +:10790000F2802FB60000190A120100C8020020B24E +:10791000000085088000008072812FB60000000002 +:10792000000000F872812F343D0085081201002C00 +:1079300082CD2EB2000016130000008002000090DD +:107940000000EE091201005C088020B20000150A58 +:107950001201006002802CB20000161300000080AB +:107960000200009000008508350100F812812FB553 +:1079700000000000000000D802800132000000007A +:10798000005401FC02C06E3200C0230A1801000C32 +:10799000A8CD3EB220800000D10100080880363218 +:1079A0003B00F3031201002C82CD2EB2000016130F +:1079B00000000080020000900000E2110098012801 +:1079C00009006EF2000085080000008002000090AF +:1079D00000002F0A80010080A2812FB600002F0A2C +:1079E0008000008042812FB61F00000000000010C0 +:1079F00009003632000080120000001409802FD2E6 +:107A00003C00000000000010090036320000801227 +:107A10000000001409803CD200002F0A085B01EC32 +:107A200006FB6EBC00000000005A01EC06000032AC +:107A300000002F0A370000F842812FB43D000000FB +:107A4000D701002C82CD2E320000360A8001008042 +:107A500092812FB60000161380000080C2812FB6DD +:107A600000003D0A08C901E806BB6EBC000000002A +:107A700000C801E806000032330016131200002C83 +:107A800082CD2EB20000F31100000028098001F21F +:107A900000008508000000800200009000003D0A00 +:107AA00080010080C2812FB6000016138000008084 +:107AB00092812FB600003D0A08D101E806BB6EBCDA +:107AC0000000000000D001E8060000323300161369 +:107AD0001200002C82CD2EB20000F311000000280D +:107AE00009C001F20000850800000080020000903B +:107AF0000000850880010080F2812FB618008508FB +:107B00000000002C82CD2E92000016130407018085 +:107B100012C06EBC0000430A120000C8020020B26E +:107B20000000460A1201005C088020B20000161313 +:107B30001200006002802CB200000000000000F87B +:107B40001F80FF3A0000F3031201002C72E02EB2F6 +:107B500000001613000000800200009000000000EA +:107B60000000007879613832000016131218024CB8 +:107B7000E2256EB200000000003402B808806E32C8 +:107B800000000000D4A0015008006E320000000088 +:107B9000DB79016008006E320000F711DD0000049F +:107BA000080000F21000000000180080878D853763 +:107BB0000000000000F801E0060085320000500AD5 +:107BC0001201000009C021B218003600000000F8C0 +:107BD000730A03F9300016131200005CA28D2CB258 +:107BE00000001613040701EC16C06EBC0000000074 +:107BF00000B000E00600003200008508DA5C01E811 +:107C000006808B92000085089F41018052206EBC47 +:107C100000005F0A9F98018052206EBC00000000A7 +:107C2000000000D80280013200000000005401FC76 +:107C300002C06E3200C05D0A1801000CA8CD3EB231 +:107C40002080850831000008088036B2000000005E +:107C5000000000F812812F343B0085081201002C2F +:107C600082CD2EB2000016130000008002000090AA +:107C70000000E2110098012809006EF2000085085A +:107C8000000000800200009000008508D54101E05E +:107C9000064081920000850804B0008002006EBC9E +:107CA000000000000090010008006E320000001388 +:107CB0000078016008006EF2000085080000008076 +:107CC0000200009000000000000C027809806E3273 +:107CD0000000670A04D4018012C06EBC00000000DE +:107CE000000000781980973700000000009001E044 +:107CF000E6256E3A0000001300000080020000F04C +:107D000000006B0A0000008002000090000085085F +:107D1000009001E00600809200000000009001E069 +:107D20000600803200000009000000800200009080 +:107D30000000161380000080F2802FB60000C70FED +:107D400000A8012009006EF20000140A80000080E3 +:107D5000F2802FB60000850800000080020000902D +:107D600000000000000000D8028001320000000086 +:107D70000000007809006E320200760A04B9008023 +:107D800082CD6EBC0000780A800000807280FCB654 +:107D900000007B0A000000FC020000920000780A4C +:107DA000800000808280FCB600007B0A000000FC9E +:107DB0000200009200001613040000800200F5BCCF +:107DC00000000000000000A842BD97300000000045 +:107DD000541809FEF2C07C3000C0810A1801000C62 +:107DE000A8CD3EB200000000000E01EC06000034F9 +:107DF00000000000005401EC06C02F32208000007B +:107E000000000008088036320000F3031201002C45 +:107E100082CD2EB2000016130000008002000090F8 +:107E2000000000000062013808C06E3200080080C7 +:107E300000000028090037320000EB1100000008A4 +:107E4000E80100F400001613040701EC16C06EBC34 +:107E500000000000000000A8A2002D370A0000006A +:107E6000000000780900363200000000001809E226 +:107E7000070000320000870A04010078198097BCCF +:107E80000200920A04B9008082CD6EBC0000004856 +:107E9000D6010078C9CD2C3200008B0AB6000080D4 +:107EA000020000B00000161312000064028097B2B6 +:107EB00000008D0A1208006402006EB200008E0AF3 +:107EC0001218006402006EB200008F0A12100064E3 +:107ED00002006EB200000000A65401EC06C02F3272 +:107EE00000007D08000E01EC060000940020004C0C +:107EF000D6010078C9CD2C320000930AB60000806C +:107F0000020000B00000161312000064028097B255 +:107F10000000950A1208006402006EB20000960A82 +:107F20001230006402006EB20000970A123800643A +:107F300002006EB20000980A1240006402006EB2A5 +:107F40000000990A1248006402006EB200009A0A0A +:107F50001210006402006EB200009B0A1218006446 +:107F600002006EB200009C0A1220006402006EB291 +:107F700000009D0A1228006402006EB2000000009A +:107F8000A65401EC06C02F3203007D08000E01EC60 +:107F90000600369200000000000000FC02000132E2 +:107FA0000000A30A0000001408803D9200000000B9 +:107FB000000000FC020001320000A60A040000DC00 +:107FC00053603DB318000000000000F8738A0339C5 +:107FD000A20A3600000000C0020036920000000035 +:107FE000005401FC02C06E3200000000000000D806 +:107FF0000280013200C0AC0A1801000CA8CD3EB2CC +:108000002080000000000008088036321500EF03D1 +:108010001201002C82CD2EB2000016130000008049 +:10802000020000900000000000280000070000325D +:10803000000000000030000007C02C320010008259 +:108040000038000007003732000016131200004805 +:1080500002C080B200007D08CA010008E801009457 +:10806000000016138001008062812FB62D001613C8 +:108070001200002C82CD2EB20000B50A1D01008036 +:10808000020000B000007D08000000F862812F951A +:10809000000016138000008002812FB6000000004F +:1080A000000000F802812F342A007D081201002C04 +:1080B00082CD2EB200001613000000800200009056 +:1080C0000000D7110000002C09C085D20000641107 +:1080D00000000030030038F20000F303230100F831 +:1080E00022812FB43E00F3031201002C82CD2EB268 +:1080F0000000161300000080020000900000D7115D +:108100000000002C09C085D20000F303000000F835 +:1081100022812F940000C50A380100D8028001B2E4 +:108120000000C30A1E000080020000B00000C50A63 +:108130001A010080020000B0000038120000006840 +:108140001F80F6FA0000F303000000800200009098 +:108150000000C90A12010060084023B2008200003A +:108160000000000808803632000038120000006469 +:108170001F40F6FA0000F3030000008002000090A8 +:108180000000161312000024080023B2000016138A +:108190001200002008C023B20000161312000018BD +:1081A000088023B200C0D40A1801000CA8CD3EB24A +:1081B0000000CC0A12000038028081B200001613C1 +:1081C0001200003C020082B20000161312000030C0 +:1081D000024082B20000161312000034020086B280 +:1081E00020800000000000080880363200003812AD +:1081F0000000005C1FC0F5FA0000F30300000080DF +:108200000200009000000000450000D8020000328B +:108210000000000000000000074080320000000065 +:10822000001000000740823200000000001800002B +:10823000070086320000161312000050F2C138B455 +:1082400000007A0F003001E016206EFA0000DD0A0F +:108250003801002CF8010BB40000DD0A020D028089 +:10826000A25B80BC000000000000002CC8C182346A +:108270000000DF0A8000008042812FB60000B40FAA +:1082800000000080020000F0000016139FA801E02B +:1082900016206EBC0000D40F00000080020000F029 +:1082A0000000E50A270100D8028001B200000000AA +:1082B000C700002CE8C08234000000000000000865 +:1082C000D801003400000000D54001E006008732EC +:1082D00008004B12001801E8762081F900006411B3 +:1082E00000000030030038F20000E90A2319000002 +:1082F000078081B23E0016131200002C82CD2EB2F0 +:108300000000EB0A1D210000070082B20000EE0A07 +:10831000000000F862812F950000EE0A80000080C6 +:1083200002812FB62A0016131200002C82CD2EB225 +:1083300000000000000000F802812F340000161336 +:1083400080000080A2802FB6000054100000002C96 +:10835000F90100F4000016130401008062802DBCB6 +:108360001000F40A2C30000017E02CB90000F60AC7 +:108370008E39000007C082B20000F60A0008000033 +:10838000070087920000F60A8E390000B7C182B458 +:108390000000000000080000070087320000F80A13 +:1083A000120100E802C021B218003600000000F8F7 +:1083B000730A03F90000F60A9F010014184081BCFB +:1083C0000000FE0A0400008002C085BC00001613F5 +:1083D0001200006802C585B00000000000000078AF +:1083E00009C58530000016130201008082BA97BCCF +:1083F000000016130601008092BA97BC0000161305 +:108400001200004802C080B2000016130401008070 +:10841000D28180B50000F603CA010008E88180948B +:10842000000016138001008082812FB60000040B2B +:108430001E000080020000B00000060B1A01008040 +:10844000020000B000003812000000681F80F6FA39 +:108450000000F303000000800200009000001613EB +:108460009FA801E016206EBC00007A0F00000014E7 +:10847000080000F200000A0B8000008042812FB645 +:108480000000B40F00000080020000F00000D40FD4 +:1084900000000080020000F000007F08040000805F +:1084A000024081BC00000E0B120100E802C021B2A4 +:1084B00018003600000000F8730A03F900000000FD +:1084C0000000007809C58530000016130201008005 +:1084D00082BA97BC000016130601008092BA97BCBE +:1084E00000007F081201006802C585B00000161365 +:1084F000000000800200009000007D0880000080E5 +:10850000F2C185B60000170B1C41028006C085B27F +:10851000000000000000006802C585300000000077 +:10852000000000701F00F73A00007D08000000F80E +:1085300022812F9400007D0880000080F2C185B662 +:108540000000D7110000002C09C085D20000F30301 +:10855000D20100941E40E99A00001613042000186E +:1085600008006EB20000161380000080F2812FB662 +:1085700000008C1200000080020000F000001613C2 +:1085800004010080028080BC0000161304510180A9 +:1085900002806EBC000016130421018002006EBC34 +:1085A00000000000003C00E8064081320000250B7E +:1085B0001F000080020000B00000220B9E400278E5 +:1085C000094068B20000161300000080020000900D +:1085D0000000290B8001008082812FB600007F08F7 +:1085E0002A3101E0060000B218000000CA0000F8BD +:1085F000730A03397F083600000000C0020036927B +:1086000000007F0880010080A2802FB618000000C3 +:10861000CA0000F8730A03397F083600000000C062 +:10862000020036920D002F0B000000580800369211 +:1086300000002F0B00000058080000921B000000F3 +:1086400000000058080036320000161304200018FD +:1086500008006EB20000161380000080F2812FB671 +:1086600000008C1200000080020000F000000000FA +:108670000030002808006E3200000000545401FC55 +:1086800002C06E320000940B380000A4088082B251 +:108690000000940B0428010408006EB200001613B9 +:1086A0009F500104A85B80BC00000000005001E85E +:1086B0000600003200005E0B0801007819A082BCA1 +:1086C00000000000002801E0A660803C00003C0B98 +:1086D0002A010014080000B200000000CA000014C3 +:1086E0001840813A0000C70F00A80120A9206EFAA7 +:1086F0000000161306010280821B92BC00000000DD +:10870000002001E0A6206E3C00000000003000E0E8 +:10871000060000320000000000A801E006009232CE +:1087200000000000000000D80280013200C0500BA1 +:108730001801000CA8CD3EB20000470B04000080D9 +:10874000024081BC0000000000000014080000325C +:1087500018000000000000F8730A0339410B3600CE +:10876000000000C0020036922080000000000028B7 +:108770000980363200008111000000D8020000D2CA +:1087800000004B0B04000080028092BC18003600F1 +:10879000000000F8730A03F900000000000000D890 +:1087A0000280013200C0500B1801000CA8CD3EB26F +:1087B00018000000000000F8738A03394B0B00001A +:1087C000000000C0020036320000360000000080C9 +:1087D0000200009000000000DE000008E801003404 +:1087E00000000000DF00013808C06E320000000009 +:1087F0000010000007000032000000000018000018 +:1088000007808232000000000030000007C02C32D8 +:108810000020008000380000070037320000000010 +:10882000CA3D000C078083320000000000000014E5 +:108830001840813A00005C0B040201EC16C06EBCCB +:1088400000000000C00100141840813A0000000040 +:10885000000000F892802F3400C016131200004070 +:10886000A28D39B20000D70B1201004802C080B2BD +:1088700000001613000000800200009000000000BD +:10888000000000280880973200000000000000A4CB +:1088900008808232000000000010006C18206E3A40 +:1088A000000000000018004C08006E320000C70FE6 +:1088B00000A8012019206EFA00001613060102809C +:1088C000821B92BC00000000002001E016206E3CDC +:1088D0000000000000A801E0060092320000690BD1 +:1088E000003801E006408092000000000060006C4B +:1088F00018206E3A000000000068004C08006E323C +:1089000000006B0B9F010004686080BC0000740BCA +:10891000000000181820009C000016138001008041 +:10892000A2802FB600006E0B120100E802C021B237 +:1089300018003600000000F8730A03F90000000078 +:10894000CA70001808006E320000670B0201008038 +:10895000626080BC000016139F000014184081BCA8 +:1089600000000000CA0100F802802F3500A0690B4A +:1089700012010040A28D39B20000161300000080E1 +:10898000020000900000790B80000080A2802FB6CA +:1089900000007C0B04000080A2A081BC0000161324 +:1089A0009F000014184081BC00000000CA0100F8BC +:1089B00002802F3500A0161312000040A28D39B29C +:1089C00000000000000000F8A2802F3500007C0BA2 +:1089D000120100E802C021B218003600000000F8C1 +:1089E000730A03F900000000002801E006000032CD +:1089F00000000000003C00E806408132000000005A +:108A0000003000E00680823200000000002000E01C +:108A10000680813200000000001000E006C08632AF +:108A200000000000001800E006C0843200001613A9 +:108A30000400008032E186B20000860B1F010008AE +:108A4000090000B20000970B0420018002006EBCF8 +:108A500000001613000000800200009010000000CB +:108A600000000010790B1638080000000000000C10 +:108A7000790B16380000000000000004A9002D3713 +:108A80000004010000000004C94D903A02000000FB +:108A9000000000A8820D913700000000000000A82F +:108AA00012A42A3A00008F0B80400280E2017CB6BB +:108AB0000000161304400278B93F7CB000000000AB +:108AC00000000008E9A5903A0000910B9F010010FA +:108AD000190091BC9F000000000000100900363210 +:108AE00000008A0B0401008042E490BC00001613D1 +:108AF00004210180829B90BC0000970B0000008045 +:108B000002000090000000000010006C08006E32AF +:108B1000000000000018004C08006E320000161320 +:108B20000400008032E186B200003210510000D80B +:108B3000020000F200009A0B0050013CA85B809CF0 +:108B400000007F08003001E00600009200009F0B4B +:108B50003E510100A81B80BA00000000DE0000F8B2 +:108B6000F2812F3400000000005801EC06C0EE3204 +:108B700000009F0B80010080328087B6000000005B +:108B8000000000F8E2802F340000E310603001E0C4 +:108B9000060000F20000E90B0000008002000090D7 +:108BA0000000000000000014080000320000A90BC3 +:108BB000040201EC16C06EBC00000000C9010014E4 +:108BC0001840813A00000000C001013808C06E3230 +:108BD00000000000DF0000A4A8608A3C000016131B +:108BE0000F000080020000B000C0AD0B1201004079 +:108BF000A28D39B200001613000000800200009020 +:108C000000000000003000E006000032000000001C +:108C1000DF0000A4A8608A3C000016130F0000804B +:108C2000020000B0000000000000013808C06E32F1 +:108C300000000000DEA8012099226E3A0000161301 +:108C400006010280821B92BC000016139F2001E0E7 +:108C500096226EBC0000B20B80000080F2802FB61E +:108C60000000C70F00000080020000F00000B90BF8 +:108C70001F5001E8060000B20000B50B04000080A0 +:108C800002C083BC0000B90B005001E8F660809C74 +:108C90000800000000400278399AFE3800001613E0 +:108CA0000201008082BA97BC000016130601008002 +:108CB00092BA97BC0800000000400268129AFE3881 +:108CC0000000BE0B2AA901E0060092B2180036008F +:108CD000CA0000F8730A03F91D00BE0B04000080EF +:108CE00002A417B80000BA0B04000014184081BC9D +:108CF00000001613000000800200009000006411C4 +:108D000000000030030038F20000C10B8001008039 +:108D100032802FB63E0016131200002C82CD2EB2E8 +:108D200000000000000000D80280013200C0D20B19 +:108D30001801000CA8CD3EB220800000C30000281E +:108D40000980363200008111000000D8020000D2F4 +:108D50000000C70B04000080028092BC00000000ED +:108D6000000000141840813A0000CC0B0400008081 +:108D7000024081BC18003600000000F8730A03F9B5 +:108D80000000D00B04000014184081BC0000C80B88 +:108D90001200000009C021B20000C90B00000080D1 +:108DA0000200009018003600000000F8738A03F9F2 +:108DB0000000641100000030030038F20000D00B06 +:108DC0008001008032802FB63E0016131200002C66 +:108DD00082CD2EB200000000C30000D80280013214 +:108DE00000C0CC0B1800000CA8CD3EB2000016133A +:108DF0008000008072802FB60020008000000028D4 +:108E0000090037320000661200000008E80100F493 +:108E1000000016131200004802C080B200000000DB +:108E2000000000141840813A0000161380010080F1 +:108E3000A2802FB618003600CA0000F8730A03F9A2 +:108E40001D0016130400008002A417B800001613BA +:108E50009F000014184081BC0000D80B0B0100805B +:108E6000020000B000004B1200000080020000F081 +:108E70000000E00B8001008092802FB62B00E60BF3 +:108E80001201002C82CD2EB20000161300000080CB +:108E9000020000900000E30B1D010080020000B002 +:108EA0000000E60B8001008062812FB600001613DF +:108EB00000000080020000900000E60B80000080AF +:108EC00002812FB62A0016131200002C82CD2EB27A +:108ED00000000000000000F802812F3400007D082F +:108EE00004000080028085BC00005D12000000804C +:108EF000020000F0000069060000001C0880859256 +:108F000000007F0880010080A2802FB600001613A9 +:108F10000000008002000090000016138000008016 +:108F2000E2802FB60000EE0B8001008082812FB618 +:108F3000000016130431018002006EBC00001613FD +:108F400004310080829B82BC000016130201008065 +:108F500012A082BC00000000CE0100D802800132C5 +:108F600000C0F50B1801000CA8CD3EB22080000017 +:108F70000000000808803632000038120000005C53 +:108F80001FC0F5FA0000F30300000080020000900B +:108F90000000161380000080A2802FB60000161378 +:108FA0008000008082802FB600001613040000802D +:108FB000028082BC00000000600000D80200003285 +:108FC0000000FD0B3F00003C084080B20000FD0B9C +:108FD00080010080E2812FB600000000DE0000F872 +:108FE000F2812F3400000000005801EC06C0EE3280 +:108FF000000000004D00000067E0833E000000001C +:10900000000800000700803200000000001000008F +:1090100007C08632000000000018000007C084323C +:109020000000490C04000028D8A082BC00001613E0 +:1090300009010080020000B00000000000000018DC +:10904000D8A0813C00001F0C0400003CD8E083BC89 +:109050000000161304010080028081BC0000090C8E +:109060000400008072802DBC000016131200005016 +:1090700002C038B200001D0C510000D812802D9A99 +:109080000000161312000050F2C138B40000160C94 +:10909000280000D8020000B20000130C80010080FC +:1090A000F2C185B600000F0C1F400284E60100B437 +:1090B0000000130C1D0100F822812FB40000130CD6 +:1090C000000000F862812F950000110C1D01008046 +:1090D000020000B000000000000000F862812F359F +:1090E00000000000004002800240683200001613B9 +:1090F0001F010080020000B00000150C343000E0B9 +:1091000016206EBC0000B40F00000080020000F0CA +:109110000000D50FDA5B01EC0640EDF218003600D6 +:10912000000000F8730A03F900001B0C0400008023 +:1091300072802DBC0000161380010080A2802FB623 +:109140000000160C670000F8A2802FB5000016136F +:10915000120000E802C021B20000161304010080D2 +:1091600072802DBC00000000510000D802000032C7 +:1091700000003E1000000000D82080FA0000FE0B26 +:109180004D00000067E0839E00001613120000509F +:10919000F2C138B400002C0C28000080084000B256 +:1091A0000000290C80010080F2C185B60000250C6A +:1091B0001F400284E60100B40000290C1D0100F8E4 +:1091C00022812FB40000290C000000F862812F9545 +:1091D0000000270C1D010080020000B0000000000C +:1091E000000000F862812F3500000000004002807E +:1091F00002406832000016131F010080020000B018 +:1092000000002B0C343000E016206EBC0000B40FC0 +:1092100000000080020000F00000D50FDA5B01ECD6 +:109220000640EDF200004F0C80000080E2802FB677 +:109230000000300C042100E0068081B200003E10E6 +:1092400000000034080000F200000000002000E0F0 +:109250000680813200000000003C00E806408132B8 +:109260000000360C2A1100E0D6E086BA180036005D +:10927000CA0000F8730A03F91D00360C04010080CF +:1092800002A417B80000320C9F010080180088BCAF +:1092900000001613000000800200009000004B1236 +:1092A00000000080020000F00000641100000030A7 +:1092B000030038F208003A0C231901E8762081B93E +:1092C0003E0016131200002C82CD2EB200003E0C80 +:1092D0001D1800E006C084B200003E0C8000008033 +:1092E00002812FB62A0016131200002C82CD2EB256 +:1092F00000000000000000F802812F34000054102C +:109300000000002CF90100F40000430C0400008070 +:10931000020088BC0000420C1201000009C021B20A +:1093200018003600000000F8730A03F91D00161338 +:109330000401008002A417B8000016130401008085 +:10934000028080BC000000000000007809C5853064 +:10935000000016130201008082BA97BC00001613A9 +:109360000601008092BA97BC0000F6031201006863 +:1093700002C585B0000016130000008002000090B6 +:10938000000000000030007819206E3C0000161329 +:1093900004010080E2A582BC00001613800000805A +:1093A000A2802FB60000161304010080020088BCC2 +:1093B0000000161304010080028080BC0000161318 +:1093C00012000050F2C138B400000000C0010138A2 +:1093D00008C06E320000530C040201EC16C06EBCD3 +:1093E00000C0161312000040A28D39B20000540CC8 +:1093F000C90100140800009200000000453000E0A0 +:10940000060000320000600C28000008E80100B4EB +:1094100000005D0C80010080F2C185B60000590C8F +:109420001F400284E60100B400005D0C1D0100F83D +:1094300022812FB400005D0C000000F862812F959E +:1094400000005B0C1D010080020000B00000000065 +:10945000000000F862812F3500000000004002800B +:1094600002406832000016131F010080020000B0A5 +:1094700000005F0C8000008042812FB60000B40F16 +:1094800000000080020000F00000D50FDA5B01EC64 +:109490000640EDF200200080DF000028090037328E +:1094A00000006612DE0000D8028001F208004B12B4 +:1094B000001801E8762081F90000641100000030F6 +:1094C000030038F20000660C8001008032802FB665 +:1094D0003E0016131200002C82CD2EB200006B0C41 +:1094E000290801E406C02DB20000700C1D000080A8 +:1094F000020000B00000700C8000008002812FB6D6 +:109500002A0016131200002C82CD2EB20000700C1F +:10951000000000F802812F9400006D0C1201000081 +:1095200009C021B218003600000000F8730A03F9E0 +:109530001D006F0C0401008002A417B800006C0C21 +:10954000000000141840819C2B0016131200002C00 +:1095500082CD2EB2000055100000002CF90100F45D +:109560000000730C04010080024081BC180036002A +:10957000000000F8730A03F90000161312000048F7 +:1095800002C080B2000000000000007809C58530EC +:10959000000016130201008082BA97BC0000161367 +:1095A0000601008092BA97BC0000F6031201006821 +:1095B00002C585B000001613000000800200009074 +:1095C000000016138000008082802FB60000161362 +:1095D00004310080829B82BC0000161302000080D0 +:1095E00012A082BC0000161304000080028082BC1E +:1095F0002500000000000010090036321000801223 +:1096000000000014A96080D900000000000000D80C +:109610000280013200C0840C1801000CA8CD3EB2BB +:109620002080000000000008088036320000381258 +:109630000000005C1FC0F5FA0000F303000000808A +:109640000200009000C00000000000F8A28D2F3141 +:1096500000000000000000D80200003200000000FE +:1096600000000000078081320000000000080000B8 +:1096700007008032000000000010000007C08632A2 +:10968000000000000018000007C08432000016131C +:1096900012000050F2C138B40000900C800000802D +:1096A00082802FB60000000000000068A860803CA7 +:1096B000000000000000003C084080320000D40F91 +:1096C00000000004088082F20000910C12010000EA +:1096D00009C021B218003600000000F8730A03F92F +:1096E0001D00940C0400008002A417B8000016139B +:1096F00080010080A2802FB60000900C000000F8CE +:10970000A2802F9500000000000000006820803A31 +:1097100000009A0C0400002868A082BC0000161308 +:109720000C000080020000B00000161380000080D2 +:10973000E2802FB600003E1000000080020000F022 +:109740000000860C000000D80200009200001613F2 +:1097500080000080A2802FB600000000000000D82A +:10976000028001320020008000000028090037320A +:109770000000621200000008E80100F41800360042 +:10978000CA0000F8730A03F90000A50C040201ECFA +:1097900016C06EBC00000000C00100F892802F349B +:1097A00000C0A30C12010040A28D39B200001613B4 +:1097B00000000080020000902B00A50C1201002C7C +:1097C00082CD2EB20000161300000080020000902F +:1097D000000016131F010080020000B00000A80C5A +:1097E0008001008082812FB60000161304310180B1 +:1097F00002006EBC00000000000000D802800132B0 +:109800000000AB0C12010060084023B20082B40CCF +:1098100000000008A88D809200001613120000249A +:10982000080023B2000016131200002008C023B263 +:109830000000161312000018088023B200C0C90CE3 +:109840001801000CA8CD3EB20000AE0C120000388A +:10985000028081B2000016131200003C020082B2A6 +:109860000000161312000030024082B200001613EE +:1098700012000034020086B22080000000000008C0 +:10988000A88D80320000BC0C80010080F2C185B63A +:109890000000B80C1F400284E60100B40000BC0CBC +:1098A0001D0100F822812FB40000BC0C000000F85C +:1098B00062812F950000BA0C1D010080020000B0EB +:1098C00000000000000000F862812F350000000059 +:1098D0000040028002406832000016131F01008021 +:1098E000020000B032000000000000100900363213 +:1098F0000000801200000014090080D2000016133E +:109900001200006802C585B0000000000000007869 +:1099100009C58530000016130201008082BA97BC89 +:10992000000016130601008092BA97BC0000C40C18 +:109930003400005C1FC0F5BA0000B40F00000080C6 +:10994000020000F00000C60C8000008092802FB65C +:1099500000007F08003000E00600009200007F0851 +:10996000120100E802C021B218000000000000F857 +:10997000730A03397F083600000000C002003692E7 +:1099800000000000450000D8024000320000000046 +:10999000410000000780863200000000000800003F +:1099A00007008032000000000010000007408232F3 +:1099B00000000000001800000700863200001613A7 +:1099C00012000050F2C138B400000000000000781E +:1099D000388087350000161380000080728087B6BB +:1099E0000000000000A001E016206E3A0000000018 +:1099F0000000007809C585300000000000A801E0E3 +:109A000016206E3C08000000D2010078E9E5833999 +:109A1000180016131F410284E6A197B90000D90C63 +:109A2000365101E816E083BC0000D90C1D0100800E +:109A3000020000B000000000000000F862812F3535 +:109A4000000016139F2001E0064080B20000DC0CED +:109A50008001008082812FB600000000003001E00C +:109A60000640803200000000000000D80280013271 +:109A70000000DF0C34180000078081B20000B40F32 +:109A800000000080020000F010004B1200300000C7 +:109A900017E02CF900100080003800000700373272 +:109AA0000000641100000030030038F20000E40CF4 +:109AB0008001008032802FB63E0016131200002C69 +:109AC00082CD2EB20000E90C29210000070082B2ED +:109AD0000000E70C1201000009C021B21800360096 +:109AE000000000F8730A03F91D00EF0C0401008068 +:109AF00002A417B80000E50C000000140800009252 +:109B00000000EC0C1D3100E0060000B20000EF0C7C +:109B10008001008062812FB60000161300000080D3 +:109B2000020000900000EF0C8000008002812FB640 +:109B30002A0016131200002C82CD2EB20000000065 +:109B4000000000F802812F3400005D120000002C9C +:109B5000F90100F400005410000000F8A2802FF476 +:109B60000000F40C04000080024081BC0000F40CF2 +:109B7000120100E802C021B218003600000000F80F +:109B8000730A03F90000F6031201004802C080B214 +:109B90000000161300000080020000900000FE0C80 +:109BA00080010080F2C185B60000FA0C1F400284DB +:109BB000E60100B40000FE0C1D0100F822812FB464 +:109BC0000000FE0C000000F862812F950000FC0CE4 +:109BD0001D010080020000B000000000000000F83D +:109BE00062812F3500000000004002800240683290 +:109BF000000016131F010080020000B00000000DDD +:109C000004000080024086BC0000AB1200900108F6 +:109C100009006EF20000DF1200000080020000F078 +:109C20000000070D330100D8028001B20000070DCB +:109C300080010080B20172B60000070D9FF0018024 +:109C400082DB87BC0000070D9FF8018022216EBCDB +:109C50000000000000E801E00600EE320000000015 +:109C600000F001E006C0873208000000001801E89B +:109C70007620813900000D0D80010080D2802FB642 +:109C800000000D0D04B0008002006EBC000000005A +:109C9000CD0000F872812F343D000D0D1201002C13 +:109CA00082CD2EB20000161300000080020000904A +:109CB00000001C0D270901E406C02DB200C0140DE0 +:109CC0001801000CA8CD3EB2000000000000007892 +:109CD00009C58530000016130201008082BA97BCC6 +:109CE000000016130601008092BA97BC00001613FC +:109CF0001200006802C585B020807F0800000008BF +:109D0000088036922C000000000000100900363256 +:109D1000000080120098011409006ED200000000BB +:109D2000004001E00640883200000000D508000035 +:109D300007408832000000000030000007C02C32CD +:109D400000400080CA3900000700373200001613B7 +:109D50001200004802C080B200600000000000084D +:109D6000088036320000200D1D000080020000B087 +:109D70000000200D8000008002812FB62A001613FB +:109D80001200002C82CD2EB200000000000000F86E +:109D900002812F34000055100000002CF90100F45E +:109DA000000000000000007809C58530000016138F +:109DB0000201008082BA97BC0000161306010080E1 +:109DC00092BA97BC0000F6031201006802C585B084 +:109DD0000000161300000080020000900000000048 +:109DE000545401FC02C06E3200000000000000D894 +:109DF0000280013200C02C0D1801000CA8CD3EB22B +:109E00002080000000000008088036320000F303C4 +:109E10001201002C72E02EB2000016130000008028 +:109E200002000090000016138001008082812FB68E +:109E300000008C120020001808006EF200001613BB +:109E40001F30002808006EB200000000000000A4CF +:109E500008808232000000000010006C08006E32A2 +:109E6000000000000018004C08006E3200001613BD +:109E70000400008032E186B2000032100000008051 +:109E8000020000F00000360D0050013CA85B809CF1 +:109E90000000161300000080020000900000000087 +:109EA00000500100A81B803A000000000000008064 +:109EB0000800003200000000510000D8020000320B +:109EC000000000004D00000067E0833E000000003D +:109ED00000080000070080320000000000100000B1 +:109EE00007C08632000000000018000007C084325E +:109EF00000006D0D04000028D8A082BC00001613DD +:109F000009010080020000B00000000000000018FD +:109F1000D8A0813C0000540D0400003CD8E083BC74 +:109F20000000161304010080028081BC0000450D72 +:109F30000400008072802DBC000016131200005037 +:109F400002C038B200004D0D510000D812802D9A89 +:109F50000000161312000050F2C138B41800360089 +:109F6000000000F8730A03F900004B0D04000080A4 +:109F700072802DBC0000161380010080A2802FB6D5 +:109F80000000460D670000F8A2802FB500001613F0 +:109F9000120000E802C021B2000016130401008084 +:109FA00072802DBC00000000510000D80200003279 +:109FB0000000520D2A010000D82080BA0000510D87 +:109FC0001201000009C021B218003600000000F89C +:109FD000730A03F900000000000000D80240843238 +:109FE0001D0016130400008002A417B800004610DC +:109FF0000060006C08006EF200003A0D4D00000099 +:10A0000067E0839E0000161312000050F2C138B4BE +:10A0100018003600000000F8730A03F91D005B0DFC +:10A020000400008002A417B800001613800100800D +:10A03000A2802FB60000550D670000F8A2802FB552 +:10A04000000016131200000009C021B21D001613F3 +:10A050000401008002A417B8080000000040027844 +:10A06000399AFE38000016130201008082BA97BCAC +:10A07000000016130601008092BA97BC0800161360 +:10A0800012400268129AFEB8000016130B000080FE +:10A09000020000B00000641100000030030038F23C +:10A0A000000016131F00006CD8E086BA00003210C2 +:10A0B000510000D8020000F20000650D0000003CD5 +:10A0C00008408092000016130000008002000090FB +:10A0D0000000390D04010080028081BC00006B0D7E +:10A0E00080010080A2802FB600006A0D12010000DE +:10A0F00009C021B218003600000000F8730A03F905 +:10A1000000000000000000D8024084321D00161339 +:10A110000400008002A417B8000046100060006C24 +:10A1200008006EF200003A0D4D00000067E0839ECB +:10A130000000161380000080A2802FB600000000EF +:10A14000C001013808C06E3200000000453000E058 +:10A15000060000320000161312000050F2C138B49D +:10A160000000750D040201EC16C06EBC000000007A +:10A17000C90100141840813A00C0750D1201004059 +:10A18000A28D39B20000161300000080020000907A +:10A1900000C00000000000F8A28D2F310000000078 +:10A1A00000A8012099226E3A0000161306010280D1 +:10A1B000821B92BC000016139F2001E096226EBC09 +:10A1C00000007B0D80000080F2802FB60000C70FDA +:10A1D00000000080020000F000007F0D0400003C41 +:10A1E000D8E083BC00007E0D9F3101E096226EBC5A +:10A1F00000000000003001E0060000320000860D83 +:10A20000005001E8F660809C0800000000400278E1 +:10A21000399AFE38000016130201008082BA97BCFA +:10A22000000016130601008092BA97BC08000000D7 +:10A2300000400268129AFE380000850D9F3101E04F +:10A2400096226EBC00000000003001E006000032E3 +:10A2500000000000005001E806000032000000008D +:10A2600000A801E00600923218003600000000F855 +:10A27000730A03F91D008B0D0400008002A417B8B7 +:10A280000000870D04000014184081BC0000161364 +:10A290000000008002000090000016138000008083 +:10A2A00072802FB600000000000000D8028001324A +:10A2B00000200080000000280900373200006612EC +:10A2C00000000008E80100F4000016131200004826 +:10A2D00002C080B20000641100000030030038F2B8 +:10A2E0000000930D23010014184081BA3E0016139C +:10A2F0001200002C82CD2EB20000161380010080C7 +:10A30000A2802FB618003600CA0000F8730A03F9BD +:10A310001D0016130400008002A417B800001613D5 +:10A320009F000014184081BC0000940D0B010080B8 +:10A33000020000B000004B1200000080020000F09C +:10A3400000009C0D2931010C09006EB22B007D0824 +:10A350001201002C82CD2EB20000161300000080E6 +:10A36000020000900000BE0F000C020009806EF297 +:10A370000000A50D000000800200009000005D12AA +:10A3800000000080020000F0000000000000001C3F +:10A39000080090320000A40D04000028098080B25B +:10A3A00000008111000000D8020000D20000A40DBE +:10A3B00004000080028092BC18003600000000F803 +:10A3C000730A03F900006806000000080800009204 +:10A3D0000000A80D1D010080020000B000007D08F3 +:10A3E0008001008062812FB60000161300000080FB +:10A3F0000200009000007D088000008002812FB6DE +:10A400002A0016131200002C82CD2EB200007D0807 +:10A41000000000F802812F940000161380010080D4 +:10A4200082812FB60000161304000018094081B283 +:10A430000000E30F00000080020000F00000C70FE2 +:10A4400000A8012009006EF2000000000030010C9D +:10A4500009006E320000BE0F000C020009806EF28F +:10A4600000007F08000000800200009000004B12F6 +:10A4700000000080020000F000005D12000000807B +:10A48000020000F0000068060000001C0800909226 +:10A4900000000000545401FC02C06E32000016138C +:10A4A0008001008082812FB6000016131F000080FB +:10A4B000020000B010000000000000A8780B163861 +:10A4C00008000000000000AC780B16380000000007 +:10A4D000000000B0A8002D3700040100000000B00B +:10A4E000C80D8B3A00000000005001B408806E32A5 +:10A4F0000000C70D0431019008006EB20200000098 +:10A50000000000C8828D8A3700000000000000C8EB +:10A51000C2A22C3A1800C50D86410278880D78B683 +:10A520000000161304000080A2E28ABC000016138B +:10A5300004410280B23F78B00000BE0D9F0100A828 +:10A5400018808ABC9F00BE0D000000A8080036924B +:10A550000000000000400204B83F78300000DA0D2F +:10A5600000000004D862809C00001613020C0280D8 +:10A57000A21B89BC000016138000008082802FB6C9 +:10A5800002000000000000C8828D8A370000000031 +:10A59000000000C8C2A22C3A1800D00D86410278F3 +:10A5A000880D78B60000161304000080A2E28ABC71 +:10A5B0000000161304410280B23F78B00000C90DBC +:10A5C0009F0100A818808ABC9F00C90D000000A848 +:10A5D000080036920000D30D28400204B83F78B03E +:10A5E00000000000C8010004D862803C000016137F +:10A5F0009F000080024080B20000D70D0201009051 +:10A60000182089BC00000000000000B408000032DF +:10A610000000C90D9F0100A818808ABC9F00C90DC9 +:10A62000000000A8080036920000DA0D0400009037 +:10A63000182089BA000016139F000004486280BCED +:10A6400000001613900000B448628BBA0300161382 +:10A6500004400200081EFFB80000E20D00000000E8 +:10A66000D822809A0000090E04000080A2E28ABC71 +:10A6700002000000000000C8828D8A370000000040 +:10A68000000000C8C2A22C3A1800070E86400278CB +:10A69000880D78B60000161304400204B83F78B065 +:10A6A0000300161304400200081EFFB83800000023 +:10A6B0000000001009003632000080120000001473 +:10A6C000090080D20000E80D12010060084023B2AA +:10A6D0000082000000000008088036320000F3030A +:10A6E0001201002C72E02EB2000016130000008050 +:10A6F000020000900000161312000024080023B28C +:10A70000000016131200002008C023B20000161328 +:10A7100012000018088023B200000000000000D8DA +:10A720000280013200C0F20D1801000CA8CD3EB22B +:10A730000000EC0D12000038028081B200001613F8 +:10A740001200003C020082B200001613120000301A +:10A75000024082B20000161312000034020086B2DA +:10A760002080E60D000000080880369200000000FE +:10A77000000000D802000032000000000038020093 +:10A78000B81B803A00000000643001E016206E3AE9 +:10A7900000000000000000000740803200000000C0 +:10A7A00000080000070080320000000000100000D8 +:10A7B00007408232000000000018000007008632C7 +:10A7C0000000161312000050F2C138B4000000005F +:10A7D000000000D8028001320000000000180000D4 +:10A7E0000780813200000000002000000700823254 +:10A7F000100000000030000017E02C3900000000BD +:10A8000000380000F7010B340000010E80010080C9 +:10A81000328087B60000000000380000B7017034B5 +:10A820000000000000000008E80100340000130EE2 +:10A83000020C0280A21B89BC18003600000000F840 +:10A84000730A03F90000641100000030030038F2BD +:10A85000000016131200004802C080B21800360033 +:10A86000000000F8730A03F90000DC0D9F0100A846 +:10A8700018808ABC9F00DC0D000000A808003692FA +:10A8800028000C0E0401008082CD81BC0000000075 +:10A890000020017809006E320000161304010080C8 +:10A8A00042A297BC00000E0E8001008032802FB6BD +:10A8B0003E0016131200002C82CD2EB20000100EA6 +:10A8C0001D010080020000B000007D08000000F8BB +:10A8D00062812F9500007D088000008002812FB6E4 +:10A8E0002A0016131200002C82CD2EB200007D0823 +:10A8F000000000F802812F940000000000380000E2 +:10A90000C70170340000641100000030030038F209 +:10A910000800170E231901E8762081B93E001613AE +:10A920001200002C82CD2EB20000190E1D010080F5 +:10A93000020000B000001C0E000000F862812F959C +:10A9400000001C0E8000008002812FB62A00161322 +:10A950001200002C82CD2EB200000000000000F892 +:10A9600002812F340000161380000080A2802FB6D1 +:10A97000000054100000002CF90100F40000200E2B +:10A98000120100E802C021B218003600000000F8F1 +:10A99000730A03F9000016131200004802C080B2C7 +:10A9A0000000F603000000F8A2802F9400000000D1 +:10A9B000000000D8028001320000000000300028B2 +:10A9C00008006E3200000000545401FC02C06E32D8 +:10A9D00000C02E0E1801000CA8CD3EB22080000051 +:10A9E000000000280980363200008111000000D8E4 +:10A9F000020000D200002B0E04000080028092BCF6 +:10AA000018000000000000F8730A03392C0E36000D +:10AA1000000000C00200369218003600000000F866 +:10AA2000738A03F900000000000000D802800132A0 +:10AA300000C02B0E1800000CA8CD3EB200200084F0 +:10AA400000000028090037320000621200000008F0 +:10AA5000E80100F400007D08000000800200009082 +:10AA600000000000000000D8028001320000000059 +:10AA7000545401FC02C06E3200C0370E1801000CA5 +:10AA8000A8CD3EB2208000000000000808803632C9 +:10AA90000000EF031201002C72E02EB2000016132A +:10AAA00000000080020000900000F3110000002868 +:10AAB000090002F200003F0E0000005C0800009256 +:10AAC00000000000000000D80280013200000000F9 +:10AAD000545401FC02C06E3200C03F0E1801000C3D +:10AAE000A8CD3EB220800000000000080880363269 +:10AAF000000038120000005C1FC0F5FA0000F303EC +:10AB000000000080020000900000000000300028DB +:10AB100008006E320020008400000028090037324F +:10AB20000000621200000008E80100F40000440E7A +:10AB300000000080020000900000000000000008FB +:10AB40000800003200004A0E0400008002C085B2F6 +:10AB500000004A0E80000080F2C185B60000490E58 +:10AB60001C41028006C085B20000000000000068A1 +:10AB700002C5853000000000000000701F00F73A99 +:10AB800000000000000000F822812F340000D00EE9 +:10AB900080010080A2802FB618000000000000F89D +:10ABA000730A0339D00E3600CA0000C00200369284 +:10ABB0000000990E8001008082812FB60000A10E56 +:10ABC0001F20010809006EB20000990E0430010830 +:10ABD000899B90BC0000560E0431018002006EBCBF +:10ABE0000000321000000080020000F00000540E4F +:10ABF0000050014808806E9200001613000000808B +:10AC00000200009000000000000000042861803C69 +:10AC100000006B0E000000002821809A000016132F +:10AC20009F000080028090B2000032100030014886 +:10AC300008006EF200005A0E00500104A85B809CD0 +:10AC400000001613000000800200009000000000C9 +:10AC500000500100A81B803A0000680E0700004861 +:10AC600018A084BC0800000000400200189AFE38BA +:10AC70000000161302010080823A80BC0000161307 +:10AC800006010080923A80BC0000000000000068CD +:10AC9000020080320000321000000080020000F04C +:10ACA0000000630E000000800200009000001613F8 +:10ACB00000000080020000900000680E07000048BD +:10ACC00018A084BC0800000000400200189AFE385A +:10ACD0000000161302010080823A80BC00001613A7 +:10ACE00006010080923A80BC0000600E00000068FF +:10ACF0000200809200006B0E0400004818A084BA85 +:10AD0000000016139F000004286180BC00000000B2 +:10AD1000000000002821803A00000000005401FCDF +:10AD200002C06E320000740E12010060084023B2AF +:10AD300000820000D6010008088036320300161396 +:10AD400004400200381AFFB8030000000000007839 +:10AD50000960803918000000D241028CE6A19739C1 +:10AD600000000000005001E8068084322900F3034F +:10AD70001201002C82CD2EB20000161300000080BC +:10AD8000020000900000161312000024080023B2F5 +:10AD9000000016131200002008C023B20000161392 +:10ADA00012000018088023B200000000000000D844 +:10ADB0000280013200C07F0E1801000CA8CD3EB207 +:10ADC00020800000D6010008088036320000790E8D +:10ADD00012000038028081B2000016131200003CFD +:10ADE000020082B20000161312000030024082B24C +:10ADF00000006E0E12010034020086B2000016132D +:10AE00000000008002000090080000000040025C8A +:10AE1000189AFE38000000000000004808000032C8 +:10AE200000000000000000D8020000320000000016 +:10AE30000000000007408032000000000008000011 +:10AE4000070080320000000000100000074082323E +:10AE500000000000001800000700863200001613F2 +:10AE600012000050F2C138B400000000D60100D832 +:10AE700002800132000000000018000007808132CB +:10AE800000000000002000000700823210000000D7 +:10AE90000030000017E02C3900008E0E800000808A +:10AEA000328087B60010008000380000070037327B +:10AEB00000008F0E0000008002000090001000884B +:10AEC000003800000700373218003600000000F894 +:10AED000730A03F9000000000000006802C0853218 +:10AEE000000016130201008082FA85BC00001613D0 +:10AEF0000601008092FA85BC0000000000000008F6 +:10AF0000E8010034000016131200004802C080B2AD +:10AF100018003600000000F8730A03F90000321030 +:10AF200000000080020000F000006B0E00000080B6 +:10AF3000020000900000A10E0000008002000090BE +:10AF40000000321000000080020000F000009C0EA3 +:10AF500000380200B81B809C0000A10E0000008099 +:10AF600002000090050000000000006802A0FE380A +:10AF7000050000000000007809A0FE38000016134C +:10AF80000201008082BA97BC0000161306010080FF +:10AF900092BA97BC0000990E00400280024068926D +:10AFA00000000000CA0100D8020000320000A50E17 +:10AFB00004B8018002006EBC000016139FB801782F +:10AFC000891BEEBC0000000000B801E0861BEE3CCF +:10AFD0004C000000000000000700363200000000B6 +:10AFE00000000078A9002D37B4040100000800001B +:10AFF000C78D973A000000000000007899C02C37F8 +:10B00000B400000000000078898D973A0000161304 +:10B010000210000087BF97BA00000000001800006F +:10B020000740FE320000161312000048F2C138B487 +:10B030000000AD0EB6000080020000B00020161324 +:10B0400012000064A2CD2CB200000000A600008017 +:10B05000020000300000B20E80010080A2802FB6F6 +:10B0600018003600CA0000F8730A03F900007D08D2 +:10B07000005401FC02C06E92000016138001008093 +:10B0800062812FB6000016138001008082812FB6E6 +:10B09000000016131F000080020000B00000000036 +:10B0A000005401FC02C06E320000BB0E12010060B1 +:10B0B000084023B2008200000000000808803632F9 +:10B0C0002900F3031201002C82CD2EB200001613CA +:10B0D00000000080020000900000161312000024FF +:10B0E000080023B2000016131200002008C023B28B +:10B0F0000000161312000018088023B200000000A0 +:10B10000000000D80280013200C0C60E1801000CF9 +:10B11000A8CD3EB220800000000000080880363232 +:10B120000000C00E12000038028081B20000161329 +:10B130001200003C020082B2000016131200003020 +:10B14000024082B20000B90E12010034020086B241 +:10B150000000161300000080020000900000321072 +:10B1600000000048080000F20800C90E0040025C20 +:10B17000189AFE980000161300000080020000904C +:10B180000000000000500100A81B803A0000810E62 +:10B190000000004808000092000016131F01008004 +:10B1A000020000B000000000005401FC02C06E323A +:10B1B0000000F31100000028098002F20000AD0E2B +:10B1C00000000080020000900000F3110000002841 +:10B1D000090002F20000D30E9A0100F862812FB438 +:10B1E00010240000000000F8A28D2F3100000000A4 +:10B1F00000D601EC06C06E342E007D081201002C32 +:10B2000082CD2EB2000016130000008002000090D4 +:10B210000000161304A9018002006EB20000DE0EC9 +:10B2200080010080F2C185B60000DA0E1F40028462 +:10B23000E60100B40000DE0E1D0100F822812FB4EB +:10B240000000DE0E000000F862812F950000DC0E89 +:10B250001D010080020000B000000000000000F8A6 +:10B2600062812F35000000000040028002406832F9 +:10B27000000016131F010080020000B00000E00E65 +:10B2800004980164881B87BC0000AB120090010881 +:10B2900009006EF20000DF1200000080020000F0E2 +:10B2A000000000000000007809C58530000016137A +:10B2B0000201008082BA97BC0000161306010080CC +:10B2C00092BA97BC000016131200006802C585B040 +:10B2D00000000000000000F8D2802F3500007F0839 +:10B2E000370000F8D2812FB400000000000000F801 +:10B2F00072812F343D007F081201002C82CD2EB2C6 +:10B300000000161300000080020000900000F20E02 +:10B3100080010080F2C185B60000EE0E1F4002845D +:10B32000E60100B40000F20E1D0100F822812FB4E6 +:10B330000000F20E000000F862812F950000F00E70 +:10B340001D010080020000B000000000000000F8B5 +:10B3500062812F3500000000004002800240683208 +:10B36000000016131F010080020000B00000000062 +:10B3700000D401EC16C06E3A000000000000007816 +:10B3800009C58530000016130201008082BA97BCFF +:10B39000000016130601008092BA97BC0000161335 +:10B3A0001200006802C585B000007F0804B000806C +:10B3B00002006EBC37007F081201002C82CD2EB235 +:10B3C0000000161300000080020000900000020F31 +:10B3D00080010080F2C185B60000FE0E1F4002848D +:10B3E000E60100B40000020F1D0100F822812FB415 +:10B3F0000000020F000000F862812F950000000F8E +:10B400001D010080020000B000000000000000F8F4 +:10B4100062812F3500000000004002800240683247 +:10B42000000016131F010080020000B000000F0F83 +:10B43000000000800200009000000B0F80010080DF +:10B44000F2C185B60000070F1F400284E60100B478 +:10B4500000000B0F1D0100F822812FB400000B0F1C +:10B46000000000F862812F950000090F1D01008087 +:10B47000020000B000000000000000F862812F35DB +:10B4800000000000004002800240683200001613F5 +:10B490001F010080020000B000000F0F370000F80D +:10B4A000D2812FB400000000000000F872812F3418 +:10B4B0003D000F0F1201002C82CD2EB2000016139A +:10B4C00000000080020000900000000000D401ECA9 +:10B4D00006000032000000000000007809C5853039 +:10B4E000000016130201008082BA97BC00001613F8 +:10B4F0000601008092BA97BC00007F081201006824 +:10B5000002C585B000001613000000800200009004 +:10B5100000007D0880010080F2812FB600007D08C8 +:10B5200080000080E2812FB60000190F80000080AB +:10B5300002812FB6000016131D010080020000B02A +:10B54000000016130458018002C06EBC00007D0884 +:10B55000085901EC06FB6EBC00000000000000D89A +:10B560000280013200000000545401FC02C06E321F +:10B5700000C0220F1801000CA8CD3EB20000000050 +:10B58000005801EC06FB6E3A208000000000000825 +:10B59000088036320000EF031201002C72E02EB258 +:10B5A00000001613000000800200009000005D12F1 +:10B5B000000000F8E2812FF40000250F060301804F +:10B5C00012C06EBC190068060000001C080036920C +:10B5D0001A0068060000001C0800369200001613CE +:10B5E00080010080F2812FB60000161380010080D8 +:10B5F000E2812FB60000161304550180B2DB2FBC88 +:10B6000000C00000000000F8A28D2F3100000000F3 +:10B61000000000D802800132002000C00000002895 +:10B6200009003732000000000030002808006E32A8 +:10B6300000000000453000E0060000320000621209 +:10B6400000000008E80100F40000340F040201ECDF +:10B6500016C06EBC00000000C90100141840813AF9 +:10B6600000000000000000F802802F3400C0340FFA +:10B6700012010040A28D39B20000161300000080B4 +:10B680000200009018003600CA0000F8730A03F99F +:10B690000000340F9F010014184081BC00007F0897 +:10B6A0008001008092802FB62B007F081201002CB1 +:10B6B00082CD2EB200001613000000800200009020 +:10B6C000000016131F0100D8028001B20000000024 +:10B6D000005401FC02C06E3200C0440F1801000C7F +:10B6E000A8CD3EB22080000000000028098036323C +:10B6F00000008111000000D8020000D20000410FBC +:10B7000004000080028092BC18000000000000F8D5 +:10B71000730A0339420F3600000000C0020036925F +:10B7200018003600000000F8738A03F900000000DA +:10B73000000000D80280013200C0410F1800000C48 +:10B74000A8CD3EB200005D12000000D8024000F219 +:10B7500000F04C0F1D400200A80D68B10000161348 +:10B760000B000080020000B0000016131E4002848F +:10B77000060000B200004A0F12000028020580B047 +:10B780000800450F000000F8234001990000450F14 +:10B7900012010068020580B000001613000000804E +:10B7A0000200009000004C0FB5000080020000B0C5 +:10B7B00000000000A50080A0360B6A3500000000E4 +:10B7C0000000005009C02932000000000056012886 +:10B7D00008C06E320000000000000078390B2E32E5 +:10B7E0000000000000000020F38197340000560F95 +:10B7F00004000078D90130B600001613040100805F +:10B80000328097BC0000000000000000B905303015 +:10B8100018000000000000F803A403390000000035 +:10B8200000000034330B2F3200006F0F040000784B +:10B83000D90130B60000161304010080328097BC95 +:10B840000000000000000078B905303000005D0FF6 +:10B850000400008042E529BC00000000000000F860 +:10B860000200003218000000000000F8738A02395C +:10B87000000000000000009C028097320A000000D7 +:10B880000000001009003632000080120000001491 +:10B8900009C029D20000690F25010008080000B284 +:10B8A0000000161380000080F20180B60000000046 +:10B8B0000000002C090580300000161302010080F2 +:10B8C00082FA92BC000016130601008092FA92BC24 +:10B8D0000000670F12000028020580B00800690F01 +:10B8E000000000F8234001990000690F1201006870 +:10B8F000020580B0000016130000008002000090D6 +:10B9000000006D0F0400008002402FBC000000000A +:10B910000000007809002C32210316130400008077 +:10B92000828D97BC9603161304000080828D97BC0D +:10B930000000161380000080A2802FB60000560F72 +:10B94000000000F4020000920000730F0400008069 +:10B9500042E529BC00000000000000F802000032AF +:10B9600018000000000000F8738A0239000000008F +:10B970000000009C0200953200000000CA0100D8BF +:10B9800002800132000000000030000007C02C32AD +:10B99000001000A00038000007003732000000004F +:10B9A000002000000700EE32000000000038000C0C +:10B9B00007808232000016131200004802C080B2D5 +:10B9C0000000F60300000008E80100940000930F57 +:10B9D00002000080A24280BC0000930F8000008023 +:10B9E000F2C185B60000930F1F400208B9BF68B0CE +:10B9F0000000830F80410280E28168B608000000E9 +:10BA00000000001079618039000016139F2001E0CA +:10BA100016206EBA00000000000000F822812F34CA +:10BA20001800000000400288E62191390000000063 +:10BA30000001005C08000072000000000000000C23 +:10BA400019A0903A0000930F06010080D2FF90BC2D +:10BA50000000870F2C410278F98168B400000000D3 +:10BA600000000078B9819734010000000000001048 +:10BA700009003632000080120000001459C085D73A +:10BA80000300000000400200291AFF3800000000F7 +:10BA900000380200B91B903A00000000D241028831 +:10BAA00016A0973A00000000450000D8024000327E +:10BAB000000016139F2001E016206EBA000000005F +:10BAC0000000000007408032000000000008000075 +:10BAD0002724903A000000000010000007008A327E +:10BAE0000000000012010058F2C138740000161363 +:10BAF00000000080020000900800A20F1A0000342D +:10BB0000796180B90000AE0F1E010080020000B014 +:10BB10000000AE0F1F400200094068B20000950F00 +:10BB200080000080E20190B6000016133800005437 +:10BB30001F40F5BA0000000000000008B93F903037 +:10BB400000000000002801E026246E3A08001613C9 +:10BB50001E00000009A4FEB83D0000000000001017 +:10BB6000090036320000801200000014090090D253 +:10BB70000000000000000078090590300000161356 +:10BB80000201008082BA97BC0000161306010080F3 +:10BB900092BA97BC0000AE0F12010068020590B087 +:10BBA0000000161300000080020000900000AE0F9D +:10BBB0008000008082812FB60000AC0F1F41020080 +:10BBC000094068B200000000002801E016206E3A2B +:10BBD0000000A80F80010080F2C185B600000000BF +:10BBE00000400284E60100340000000000000080F4 +:10BBF0000200003000000000004002800240683275 +:10BC000000001613380000541F40F5BA0000161348 +:10BC10009F2001E016206EBA0000000000010080A5 +:10BC2000020000700000A30F80000080E20190B6C7 +:10BC30000000970F000000541F40F59A000000001C +:10BC40000000005C08000032000016139F2001E095 +:10BC500016206EBA00000000000000F822812F3488 +:10BC6000180000001E410284E6619379000016135B +:10BC700000000080020000900000FFFF0000008034 +:10BC8000020000900000B90F1D5D01EC16C06EBCF3 +:10BC9000000000000F010080020000700000161379 +:10BCA000045D018002C06EBC00001613800000809D +:10BCB00042812FB600000000000100F8B2802F740E +:10BCC000000000000F010080020000700000B70FAC +:10BCD000045E01EC16C06EBC00000000005C01ECCC +:10BCE00006400032000000000001008002000070E9 +:10BCF0000000FFFF00000080020000900000000034 +:10BD00000420018082DB907C000016130420018057 +:10BD100002006EBC000016131F000080020000B07D +:10BD200000000000020C0280A2DB907C0000C40F27 +:10BD300006210180821B90BC2700C50F0000000077 +:10BD40000900369228000000000000000900363289 +:10BD5000000000000000008812002C3A0000FFFFE5 +:10BD600000000080020000900600000000000010AB +:10BD7000090036320000801200000014090092D23F +:10BD80000000161304000080020092BC00000000B6 +:10BD90002FA00178891B927A0000000006880178A4 +:10BDA000899B977C000000000034020409C06E3DAE +:10BDB00000000000000C020019A46E370000D20F32 +:10BDC0000200008002A497BC0000D20F0200008095 +:10BDD000020000B00100000000000078898D973754 +:10BDE0000000000002010280829B977C000000009E +:10BDF000000100F8F2802F740000FFFF00000080B7 +:10BE00000200009000000000DA5B01EC0640ED3219 +:10BE10002D000000000000100900363200008012E2 +:10BE2000005C011409806ED20000DA0F040100806A +:10BE3000024086BC0000000000A001E016206E3A1F +:10BE40000000DC0F00D401EC060000920000AB12F1 +:10BE50000090010809006EF20000000000A001E05F +:10BE600016206E3A0000DF12330100F882802FB4F2 +:10BE70000000DF129FF0018082DB87BC0000DF1230 +:10BE80009FF8018022216EBC0000000000E801E064 +:10BE90000600EE320000000000F001E006C087322C +:10BEA0000000DF1200000080020000900000FFFF91 +:10BEB00000000080020000900000161308000080BF +:10BEC000028091BC11000000000000100900363211 +:10BED0001000801200500114A99B91D91500000098 +:10BEE000000000100900363210000000002001148C +:10BEF000890D6E370000801200300114895B91D2E9 +:10BF00001A00000000000010090036320000801204 +:10BF10000000001409C02DD2000016130621018074 +:10BF2000829B91BC0000000000A8017809006E32DD +:10BF30000000161306010280829B97BC00000110CE +:10BF40000421013069246EBC000000000050010093 +:10BF5000A99B913A0000F90F1F400224094068B2E2 +:10BF60000000F00F80000080E24192B60000000067 +:10BF700000000008B97F92300000000000000000BF +:10BF80002924903C080000000000007899A4FE38A5 +:10BF9000000016130201008082BA97BC000016133D +:10BFA0000601008092BA97BC0800F00F12010068E9 +:10BFB00092A4FEB80000161300000080020000905A +:10BFC0000000161304290180821B90BC00000000B1 +:10BFD00000A801E066246E3A000016139F2001E0DD +:10BFE000060093B20000FE0F8000008082812FB611 +:10BFF0000000FF0F002801E0060000920000000092 +:10C00000003001E00600003200000000005001E8AE +:10C0100006000032000000000001008002000070F5 +:10C020000000071038510100A99B91BA00000510CB +:10C0300004410208B9FF68B0000016138041028075 +:10C04000E2C168B60000021000400280024068921F +:10C05000000014109F3101E066246EBC0000141033 +:10C06000003001E0060000920000111004280104D5 +:10C0700009006EB20000161306500180A25B90BC4E +:10C0800000000F109F010000192490BC0000000068 +:10C0900000A801E066246E3A00000000002801E0DC +:10C0A0000624003C00000000005001E806000032B9 +:10C0B000000016139F2001E0060093B2000000006C +:10C0C000000100800200007000000000002801E074 +:10C0D0000600003200001D1004000080020090BC29 +:10C0E0000000141004410208B9FF68B000001613E4 +:10C0F00080410280E2C168B6000011100040028059 +:10C10000024068920000181002000080222490BCB7 +:10C1100000001D1080400280F2C168B600000000DF +:10C120000040028CB6C1683500001D10000000F808 +:10C1300022812F940800000000400278399AFE38CE +:10C14000000016130201008082BA97BC000016138B +:10C150000601008092BA97BC0800161312400268CC +:10C16000129AFEB80000111004010000292490BCAE +:10C17000000000000000000809000032100000006C +:10C1800000000010790B1638080000000000000CB9 +:10C19000790B1638000016130400008042E490BCAE +:10C1A0000000000000000004A9002D370004010079 +:10C1B00000000004C94D903A02000000000000A8F1 +:10C1C000820D913700000000000000A812A42A3A56 +:10C1D0000000281080400280E2017CB600001613A7 +:10C1E00004400278B93F7CB0000000000000000865 +:10C1F000E9A5903A00002A109F010010190091BC97 +:10C200009F000000000000100900363200002310DB +:10C210000401008042E490BC0000000000000078AF +:10C22000C924903A000016130401008022A497BC90 +:10C230000000000000A801E066246E3A0000000043 +:10C24000005001E806009032000016139F2001E024 +:10C25000060093B2000000000001008002000070A0 +:10C260000000FFFF00000080020000901800341062 +:10C270001F41027888CD68B60000000000000088E9 +:10C2800012002C3A0000371080010080628087B6CF +:10C290000000161304410280B2FF68B000003210A3 +:10C2A000004002800240689203001613044002001E +:10C2B000381AFFB8000016131F400204B8FF68B018 +:10C2C0000000000000380200B81B803A2E00000079 +:10C2D0000000001009003632000080120000001437 +:10C2E000090080D200000000000100800200007000 +:10C2F0000000FFFF000000800200009000004510D9 +:10C3000080010080A2802FB60000421012010000C0 +:10C3100009C021B218003600000000F8730A03F9C2 +:10C3200000000000000000D8024084321D004510CB +:10C330000401008002A417B800003F109F01008094 +:10C34000180088BC00001613000000800200009056 +:10C35000000000000060006C08006E320000000069 +:10C36000CA68004C08006E320000161304700018F2 +:10C3700008006EB2200000000000001009003632F4 +:10C380001000801200000014A96081D90000000094 +:10C3900004000080A2A0817C000016130D01008023 +:10C3A000020000B000004F1080010080E2802FB634 +:10C3B00000004F101B000080020000B000000000D1 +:10C3C0000600008062E0837C000016139F000014CA +:10C3D000184081BC00000000CA0100F802802F351F +:10C3E00000A0000012010040A28D39720000161357 +:10C3F00000000080020000900000FFFF00000080AD +:10C400000200009000000000000801E406C02D3288 +:10C41000EEFF0000001001E0868D2F3100000000CB +:10C420000000001CB3E4393200005B100400007807 +:10C43000D90130B60000161304010080328097BC89 +:10C440000000000000000078B9053030180000003E +:10C45000000000F8E3A503390000000000000034EC +:10C46000330B2F320000000004000078D901307631 +:10C470000000161304010080328097BC0000000009 +:10C4800000000078B905303018000000000100F805 +:10C49000E3A503790000FFFF000000800200009088 +:10C4A000000016130401008002002DBC00001613CA +:10C4B0000401008002802DBC00000000000000CCC0 +:10C4C00002000032000066102000012C09C06EB28C +:10C4D00000006710001686CC06C092920000000093 +:10C4E000001486CC06C09232000000001201004009 +:10C4F000628E92520000161300000080020000902D +:10C500000000FFFF000000800200009000006D109E +:10C5100004000078D90130B6000016130401008031 +:10C52000428097BC6D103600000000C002003692B9 +:10C530006000161304010080828D2FB100000000FE +:10C54000000000140300383200000000000000E08A +:10C55000020030320000B91004000024D80130B6C7 +:10C560007210000000000088824D823A000016130D +:10C570000000008002000090000016130000008000 +:10C5800002000090000016130000008002000090DE +:10C590000000161300000080020000906D103600AD +:10C5A000000000C00200369200009E1000000080D3 +:10C5B0000200009000007A10000000204805309032 +:10C5C000000016130000008002000090000086109A +:10C5D000921101BC08006EB200000000000801DCEE +:10C5E00002406E3200007E101F1101E026C18BB5A3 +:10C5F000000086101D000080020000B00000000056 +:10C60000000000D80200003280020000000000009C +:10C61000070036320000000000000078A9002D3726 +:10C620002005010000080000C78D973A0A000000AD +:10C6300000000078890D8237000000000010000023 +:10C64000A7BA973A000000000018000007C0EA32BD +:10C65000000016131200004802C038B200008A1011 +:10C66000800E01BC08C06EB2000000000000000097 +:10C67000190E823200E0921012010048A20D90B211 +:10C68000000016130000008002000090000000006F +:10C69000000000D802400032B4000000000000009A +:10C6A000070036320000000000000078A9002D3796 +:10C6B0000004010000080000C78D973A0000000048 +:10C6C0000000007899008237000016130210000065 +:10C6D00087BF97BA00000000001800000740FE3234 +:10C6E0000000161312000048F2C138B418003600DA +:10C6F000000000F8730A03F90000000000000004C5 +:10C70000896038321D0000000000007809A4173845 +:10C71000000098108000008002C08BB600009910C5 +:10C7200004000080328097BC0000161300000080D7 +:10C73000020000900000161304010080028097BCE4 +:10C740000000000000000018F341903400009E102B +:10C7500004000078D90130B60000161304010080EF +:10C76000328097BC0000000000000000B9053030A6 +:10C7700018000000000000F803A4033900000000C6 +:10C780000000000019CE2C32006016131200004089 +:10C79000A20D90B200000000000000D8020000329C +:10C7A00060000000000000000700363200000000BA +:10C7B000000000BCA8002D37A00701000008000001 +:10C7C000C7CD8B3A0A0000000000007889CD2C37D5 +:10C7D0008002000000000078898D973A0000000078 +:10C7E00000100000A7BA973A0000000000180000EF +:10C7F00007C0EA320000161312000040F2C138B43C +:10C8000018003600000000F8730A03F90000000069 +:10C81000000801DC02406E321D00000000000078BC +:10C8200009A417380000161304010080028097BC89 +:10C83000000016138010018022016EB60A00B010AD +:10C840001F01007889CD2CB70000B7101D1001F82A +:10C8500002006EB2800200000000000007003632C5 +:10C860002005010000080000C7CD8B3A0000000041 +:10C8700000100000A7BA973A00000000001800005E +:10C8800007C0EA320000161312000040F2C138B4AB +:10C8900018003600000000F8730A03F900000000D9 +:10C8A000001001F802006E32EEFF16130401008042 +:10C8B000828D2FB000000000000100800200007097 +:10C8C000EEFF161304110180820D6EB0000000000F +:10C8D000001001F802006E3200000000000901DCC7 +:10C8E00002406E720000FFFF000000800200009016 +:10C8F0000000000000000000090000320E000000EF +:10C9000000000004894D0D3600000000000000000A +:10C9100007800B3200000000000800000700903282 +:10C920000000000000100000070036320000C210B6 +:10C930001200004CF2C138B400000000000000807A +:10C94000020000300000C3101200008002C021B2BB +:10C950000000000000000000E902903A0000BF1053 +:10C9600004010004194090BC000000000001008098 +:10C97000020000500000FFFF000000800200009055 +:10C980000000D21080010080A2802FB60000CC10E1 +:10C99000120100E802C021B218003600000000F8C1 +:10C9A000730A03F90000D1100400008002802DBC3E +:10C9B000000016130401008022802DBC0000161315 +:10C9C0009F000080180088BC0000CC10120100E815 +:10C9D00002C021B20000CB100000008002000090D5 +:10C9E00000000000CA0000D8024084320000161384 +:10C9F0000401008002402DBC0000161304000080DA +:10CA000002802DBC000000000040006C881C833AAE +:10CA1000000000000048004C0800723200001613AD +:10CA200008500018C82072BC0000000004000080FC +:10CA30000240817C00000000000000141840813C8E +:10CA40000000161302000020880182BA00000000D6 +:10CA5000000000D8020000320000000000000000CA +:10CA6000070006320000161304010080020036BCE5 +:10CA70000700000000080000774A093900000000A4 +:10CA8000001000000700823200000000CA190000F8 +:10CA9000074082320000161312000040F2C138B481 +:10CAA00000000000000100D8024084720000FFFF77 +:10CAB0000000008002000090000000004D00000017 +:10CAC00067E0833E0000000000080000070080329D +:10CAD000000000000010000007C0863200000000C7 +:10CAE0000018000007C0843200003C110400002838 +:10CAF000D8A082BC0000161309010080020000B01B +:10CB00000000000000000018D8A0813C0000FE10CA +:10CB10000400003CD8E083BC000016130401008030 +:10CB2000028081BC0000EF100400008072802DBCE8 +:10CB3000000016131200005002C038B20000F710B7 +:10CB4000510000D812802D9A0000161312000050D8 +:10CB5000F2C138B418003600000000F8730A03F977 +:10CB60000000F5100400008072802DBC0000161338 +:10CB700080010080A2802FB60000F010670000F84E +:10CB8000A2802FB500001613120000E802C021B2E7 +:10CB9000000016130401008072802DBC000000000C +:10CBA000510000D8020000320000FC102A010000F1 +:10CBB000D82080BA0000FB101201000009C021B289 +:10CBC00018003600000000F8730A03F900000000A6 +:10CBD000000000D8024084321D00161304000080BB +:10CBE00002A417B8000046100060006C08006EF246 +:10CBF0000000E4104D00000067E0839E0000161363 +:10CC000012000050F2C138B418003600000000F8DD +:10CC1000730A03F91D0005110400008002A417B86F +:10CC20000000161380010080A2802FB60000FF10C4 +:10CC3000670000F8A2802FB5000016131200000054 +:10CC400009C021B21D0016130401008002A417B808 +:10CC50000800000000400278399AFE3800001613E0 +:10CC60000201008082BA97BC000016130601008002 +:10CC700092BA97BC0800161312400268129AFEB8C6 +:10CC8000000016130B000080020000B000006411C9 +:10CC900000000030030038F200001B111F00006C80 +:10CCA000D8E086BA00003210510000D8020000F22D +:10CCB00000000F110000003C0840809200001B1192 +:10CCC000000000800200009000001311800100802D +:10CCD000F2812FB60000131180000080E2802FB691 +:10CCE0000000131180010080328087B60000000030 +:10CCF000000000F8E2802F340000E31004010080FF +:10CD0000028081BC0000191180010080A2802FB632 +:10CD1000000018111201000009C021B218003600ED +:10CD2000000000F8730A03F900000000000000D8BA +:10CD3000024084321D0016130400008002A417B8BC +:10CD4000000046100060006C08006EF20000E41065 +:10CD50004D00000067E0839E0000201180010080EC +:10CD6000E2802FB60000401180010080A2802FB623 +:10CD700018003600CA0000F8730A03F91D004011BC +:10CD80000401008002A417B8000016130000008000 +:10CD90000200009000000000000000A4A8608A3C8F +:10CDA0000000161304210180825B8ABC000024115C +:10CDB0002FA8012099226EBA0000C70F0000008042 +:10CDC000020000F00000161306010280821B92BCD4 +:10CDD0000000000000A801E0060092320000000000 +:10CDE000005001E80600003200002911232101E073 +:10CDF000060000B23E0016131200002C82CD2EB2A7 +:10CE000000001613043000E0068082B200003311E7 +:10CE1000042100E0068081B200001613800000802B +:10CE2000E2802FB60000311180010080A2802FB671 +:10CE3000000030111201000009C021B218003600B4 +:10CE4000000000F8730A03F900000000000000D899 +:10CE5000024084321D0016130400008002A417B89B +:10CE6000000046100060006C08006EF20000000038 +:10CE7000002000E00680813200000000003C00E855 +:10CE80000640813200000000001000E006C086323B +:10CE900000000000001800E006C0843200001613F5 +:10CEA0000400008032E186B2000000002A01008008 +:10CEB0000200007000003A111201000009C021B206 +:10CEC00018003600000000F8730A03F91D0016135D +:10CED0000400008002A417B800000000000100F860 +:10CEE000A2802F75000000000000003CD8E0833CC9 +:10CEF0000000161312000050F2C138B400001613DF +:10CF000080000080A2802FB600000000000000F822 +:10CF1000A2802F34000000000000008812002C3A8C +:10CF20000000FFFF000000800200009000000000F1 +:10CF3000000000000900003200000000000000783E +:10CF40000900003200000000000000A802000032CA +:10CF5000EE05481104010080820DF6BC00060000B9 +:10CF6000000000080900363200004A1100000004E9 +:10CF700009C00992002800000000000809003632AC +:10CF80000000000000000004098009321E000000BB +:10CF9000000060C087CD003700000000000860C0BE +:10CFA000078097320030000000000078898D2A3A0F +:10CFB000000016131200005C528197B400000000BC +:10CFC000000000002924903A0800000000000078CA +:10CFD000890D903600000000000000041940903CCC +:10CFE00000000000000000A852822A3A00084A11FE +:10CFF00002010080828D2ABC00005B1106000080C7 +:10D00000024090BC00001613120000A8020020B2DB +:10D010001E000000000000C087CD003700000000A7 +:10D02000000800C007809732000016131200005C51 +:10D0300052812AB400000000000000002924903A28 +:10D040000800000000000078890D9036000054119F +:10D0500004010004194090BC0500000000000078A5 +:10D06000890D903600000000000000A00E8097326D +:10D070000000161312000068028097B20000000042 +:10D08000000000A40E8097320000000000000000A5 +:10D090002924903A000000000000007859009036E2 +:10D0A00000005D1195010080222490BA000000006C +:10D0B00000010080020000500000FFFF000000801F +:10D0C0000200009000007E1104010078D90130B602 +:10D0D000000000000000002809C029320000000004 +:10D0E0000000009CB2452830000070118601000845 +:10D0F00009802FB2000000000000002C094081329E +:10D1000000000000000000F80200003200000000F3 +:10D11000000000F40200003218000000000000F8D7 +:10D12000738A0239000000000000009C02809232E5 +:10D1300000006F110407018002C06EBC000079116D +:10D14000C30701ECB6E46E9A00007911000601EC09 +:10D15000B6E46E9A0000161380010080528090B6EB +:10D16000000000000000002C0905803000000000D5 +:10D17000000000F80200003200000000000000F48F +:10D180000200003218000000000000F8738A023923 +:10D19000000000000000009C028092320000161384 +:10D1A0000201008082FA92BC000016130601008082 +:10D1B00092FA92BC0000D71100000080020000D05B +:10D1C000210000000000001009003632000080122B +:10D1D0000000001409C092D20000000000000030DE +:10D1E0000300383200007E1104010078D90130B606 +:10D1F000000067110000009CB2452890000000006C +:10D20000040000802280977C00001613000000803C +:10D21000020000900000FFFF00000080020000906C +:10D22000000016130400008002C0E8BC00001613C2 +:10D230000200008002C12FBC000000000000008836 +:10D2400002C0E83202008411B00000A0F20B00B965 +:10D25000000000000000000CABE4B03200008911B7 +:10D2600080010080F24BD0B600000000A000002832 +:10D2700009000032000000000001008002000050A0 +:10D2800000008B1104010080123EF8BA00009611D4 +:10D29000A0000004FD4BD09400009211800100809A +:10D2A000D28192B600009211800100802281FCB6EA +:10D2B00000000000A0000004FD4BD034000000007E +:10D2C0000000008401C02F32000000000000008038 +:10D2D000F1010034000000000000009401C02F3272 +:10D2E0000000961100000090F10100940000000081 +:10D2F000A000008401C02F32000000000000008068 +:10D30000F101F83400000000000000900140F83204 +:10D310000000000000010028090000520000161360 +:10D3200080010080F24BD0B600009C11040100285F +:10D330000934B0BA0000161380010080F24BD0B659 +:10D3400000009911B0000080020000B00000000051 +:10D35000A0000004FD4BD0350000000000010028B3 +:10D360000900005200009C11B00000A822C02FB795 +:10D3700000001613040084C037ACB0B200000000F7 +:10D38000A000000C0B000032FFFF0000000000783E +:10D39000A94DB0300000A411800000800240B0B65A +:10D3A00000001613800000801240B0B6000000009C +:10D3B00000000078698197350000000000008408B3 +:10D3C0000B007C320000000000000000E725013265 +:10D3D0000042000000080000878D2A3A000000008B +:10D3E000001000000700B03200000000001800002C +:10D3F0000700D0320000000012010048F2C138548A +:10D400000000161300000080020000900000AA1126 +:10D41000B00000A0020000B2000000000000000CFC +:10D42000ABE4B0320000AF11800100800240D0B602 +:10D4300000000000A00000280900003200000000E9 +:10D4400000010080020000500000B11104010080C2 +:10D45000123EF8BA0000C211A00000040D40D094A2 +:10D460000000BB1180010080D28192B60000BB1188 +:10D47000800100802281FCB600000000A0000004B2 +:10D480000D40D034000000000000007809C02F32A9 +:10D4900000000000000000FC02000032000000005C +:10D4A0000000008401C02F32000000000000008056 +:10D4B000F1010034000000000000009401C02F3290 +:10D4C0000000000000000090F10100340000C211D3 +:10D4D000000000FC0280979200000000A00000788D +:10D4E00009C02F3200000000000000FC02000032E2 +:10D4F000000000000000008401C02F320000000086 +:10D5000000000080F101F8340000000000000090ED +:10D510000140F83200000000000000FC0280973259 +:10D52000000000000001002809000052000016134E +:10D53000800100800240D0B60000C811040100281C +:10D540000934B0BA00001613800100800240D0B642 +:10D550000000C511B0000080020000B00000000013 +:10D56000A00000040D40D03500000000000100289C +:10D57000090000520000C811B00000A8020000B26B +:10D5800000001613040084C037ACB0B200000000E5 +:10D59000A000000C0B000032FFFF0000000000782C +:10D5A000A94DB0300000D011800000800240B0B61C +:10D5B00000001613800000801240B0B6000000008A +:10D5C00000000078698197350000000000008408A1 +:10D5D0000B007C320000000000000000E725013253 +:10D5E0000042000000080000878D2A3A0000000079 +:10D5F000001000000700B03200000000001800001A +:10D600000700D0320000000012010048F2C1385477 +:10D610000000161300000080020000900000FFFFD1 +:10D6200000000080020000900000D9111C40028020 +:10D6300006C092B244000000000100F8A28D2F52F3 +:10D64000000000000000007809C5923000001613A9 +:10D650000201008082BA97BC000016130601008008 +:10D6600092BA97BC000016131200006802C592B06F +:10D67000000016130B000080020000B02400000020 +:10D680000000001009003632000080120000001473 +:10D6900009C092D200000000000100701F00F75A7C +:10D6A0000000FFFF00000080020000902C0000003E +:10D6B0000000001009003632000080120000001443 +:10D6C000098092D200000000D50800000780923245 +:10D6D000000000000030000007C02C320040008035 +:10D6E000003800000700373200000000CA4101E0A6 +:10D6F00006809232000016131200004802C080B269 +:10D700000060000000010008088036720000FFFF82 +:10D7100000000080020000900000161380000080CE +:10D72000A2802FB6000016130401008062802DBC79 +:10D730000000000000380000078092320000000066 +:10D740000030000007C02C3200000000CA3D000C71 +:10D7500007808332000000001201004802C080727E +:10D760000000161300000080020000900000FFFF80 +:10D7700000000080020000900000000004570180BB +:10D7800002C06E7C00000000005701EC068092721F +:10D790000000FFFF00000080020000900000641104 +:10D7A00000000030030038F23300000000000010D9 +:10D7B00009003632100080120000001419A02CD984 +:10D7C0000000FB119D11020C09006EB20000FC115B +:10D7D00000F0011C09006E920000000000B8011C5E +:10D7E00009006E320000FE112CCD011809806EB2C6 +:10D7F000000000000000000CC9C1903400000212BB +:10D800003B29020409806EB20000161380D6018005 +:10D8100052C06EB60000000000D601EC56C06E3457 +:10D82000000000000000000CB9C19034000012128A +:10D8300000A8010809006EF2000006129D01008098 +:10D8400017E090BA000000000030008007C091325D +:10D8500000000912003800800700EE920000091253 +:10D860000401008002C091BC0000000000B801E08B +:10D870000600EE3200000000007001E00600863273 +:10D8800000000C123908008007C085B20000161392 +:10D8900080000080C2812FB600000000D9C901E8D5 +:10D8A0000680913200000000C811008007409032CD +:10D8B00000000F123B210080070086B2000000002C +:10D8C000DB0000601800863A00000000587801E094 +:10D8D0001620863A000000000029008007008572AB +:10D8E0000000FFFF00000080020000900000161200 +:10D8F000020C0280A29B90BC000000000000027895 +:10D9000029006E360000161202000080E2A590BCCD +:10D91000000000000000000809000032000018129A +:10D920009F89017849216EBC00000000000000784A +:10D93000090000320000000000000008E9A5903F47 +:10D9400000001E1204200208899B90BE0000000007 +:10D95000000A0258B89B90360000000000000078D2 +:10D9600049A1903A000000009F880180829B977C2B +:10D9700000000000008901E00680977200000000AE +:10D98000000B0258B89B90760000FFFF000000805B +:10D99000020000900000271280010080A2802FB6B4 +:10D9A000000025121201007809C021B218003600CB +:10D9B000000000F8730A03F9000016130401008048 +:10D9C00002802DBC00002712CA0000D802408492B9 +:10D9D0001500161304010078E96517B8000000006F +:10D9E000000000F8A2802F3500001613040100800B +:10D9F00002402DBC000016130400008002802DBCE4 +:10DA0000000000000040006C881C833A0000000009 +:10DA10000048004C0800723200001613085000182D +:10DA2000C82072BC000000000600008062A0827C5A +:10DA3000000016139F000014184081BC000016134C +:10DA400002000020880182BA00000000000000D817 +:10DA50000200003200000000000000000700063253 +:10DA60000000161304010080020036BC070000000D +:10DA700000080000774A093900000000001000008B +:10DA80000700823200000000CA19000007408232FD +:10DA90000000161312000040F2C138B4000000006C +:10DAA000000100D8024084720000FFFF00000080E7 +:10DAB000020000902B000000000000100900363228 +:10DAC000000080120000001409C085D2000042123C +:10DAD00080010080F2C185B600003E121F40028422 +:10DAE000E60100B4000042121D0100F822812FB4AB +:10DAF00000004212000000F862812F9500004012E1 +:10DB00001D010080020000B000000000000000F8CD +:10DB100062812F3500000000004002800240683220 +:10DB2000000016131F010080020000B00000161351 +:10DB30001200006802C585B00000000000000078F7 +:10DB400009C58530000016130201008082BA97BC17 +:10DB5000000016130601008092BA97BC0000000076 +:10DB60001D00008002000070010000000401008020 +:10DB7000A28D2F702A0016131200002C82CD2EB217 +:10DB800000000000000100F802812F740000FFFF78 +:10DB9000000000800200009080A8000004000080C7 +:10DBA000828D2F700000521280010080D2802FB62B +:10DBB000000016138000008072812FB60000521200 +:10DBC00004B0008002006EBC00000000000000F8FD +:10DBD00072812F343D0055121201002C82CD2EB2DD +:10DBE0000000161300000080020000900000551293 +:10DBF00080010080F2802FB63C0058121201002CE8 +:10DC000082CD2EB2000016130000008002000090AA +:10DC10000000581280010080B2802FB63500161324 +:10DC20001200002C82CD2EB200000000000000F88F +:10DC300042812F348000000004000080828D2F700C +:10DC40000200000004010080A28D2F703B0016131B +:10DC50001200002C82CD2EB200000000000100F85E +:10DC600012812F740000FFFF00000080020000906E +:10DC70000000161380000080A2802FB6000016134B +:10DC800004310280A2DB2CBC08000000001801E86F +:10DC900076208139EEFF0000000100F8828D2F719F +:10DCA0000000FFFF000000800200009000006612EC +:10DCB0000000013808C06EF20000000012010048A8 +:10DCC00002C0807200001613000000800200009065 +:10DCD0000000FFFF00000080020000900E00000026 +:10DCE00000000010090036320000801200380114D4 +:10DCF00009006ED200006A120438017809006EB281 +:10DD000000000000003801E0060000320000161399 +:10DD100080000080A2802FB600000000CA11000021 +:10DD20000780823200006E122E190000078097B221 +:10DD30000000000000000028E98192340000731206 +:10DD40002731000007C02CB200000000D5080000F9 +:10DD50000700873200000000C7000028E9809234E5 +:10DD600000000000004001E00600873200000000D3 +:10DD700000000008D8818034100000000039000045 +:10DD8000E7A092790000FFFF0000008002000090F1 +:10DD9000140000000000001009003632000080125C +:10DDA00000000014094090D2000016131200004435 +:10DDB00012E438B218003600000000F8730A03F9C4 +:10DDC00000007D120401008002802DBC00001613AB +:10DDD00080010080A2802FB600007812670000F852 +:10DDE000A2802FB500001613120000E802C021B275 +:10DDF000000016130401008072802DBC000000009A +:10DE0000000100D8024000720000FFFF0000008007 +:10DE1000020000901B00000000000010790A9139F8 +:10DE20000F00000000000010390B91390C000000B9 +:10DE300000000010590A913909008312F101001005 +:10DE4000690B91B903000000002486A8828D6C370D +:10DE500000000000000088E0070091320000000090 +:10DE6000000088E00740913200C089120201008062 +:10DE7000828D2ABC00008A12E12486C80600009226 +:10DE800003000000E12486C8868D2A3600000000C9 +:10DE900000010080020000500000FFFF0000008031 +:10DEA000020000900000921204300080829B81BC2E +:10DEB000000016130D010080020000B000001613D0 +:10DEC0009F3C001428806EBC000016138000008068 +:10DED000A2802FB600000000CA0100F802802F3592 +:10DEE00000A0161312000040A28D39B20000941257 +:10DEF00080390080E2806EB6000016138038008002 +:10DF0000F2806EB600C0161304010080A28D2FB0FF +:10DF100000C09A1204380078898D6EB010009A12F1 +:10DF20009F0100F8E2A52FB900001613040000803D +:10DF300002C0EEBC00000000005801EC06C0EE324A +:10DF4000000000000000008002000030000000001F +:10DF50000428001809006E720000E30F0000008022 +:10DF6000020000F00000C70F00A8012009006E9217 +:10DF70000000FFFF00000080020000900000A712D8 +:10DF800004B00080829B81BC000016130D0100804C +:10DF9000020000B0000016139FBC001428806EBC65 +:10DFA0000000161380000080A2802FB60000161318 +:10DFB00080B8008082806EB60000000000B800E8E3 +:10DFC00086806E3400000000CA0100F842802F35C0 +:10DFD00008A0000012010040A2CD39720000161303 +:10DFE00000000080020000900000161380B800803E +:10DFF00082806EB60000000000B800E886806E34B3 +:10E000000000000000010080020000700000FFFF1F +:10E0100000000080020000902800000000000010B6 +:10E02000090036320000801200000014098090D2EE +:10E030000000B01233CD01BC08806EB20000EE12B9 +:10E04000000000282922EEDC0000B512000000804C +:10E05000020000900000B51204B8012809006EB259 +:10E060000000B5129F710180C2216EBC0000161322 +:10E070009F000028A924EEBC0000EE12000000283A +:10E08000198092DF000000000000008002000030D4 +:10E090000000C91202810180829B90BC000016130F +:10E0A00004000080028090BCEE05C112060C0280C4 +:10E0B000828D6EBC00904C0000000084020037325C +:10E0C0000000BB12B8010080020000B00000B912CD +:10E0D000000000800200009000000000000000C46A +:10E0E000038090320000000000B001E096216E3CF9 +:10E0F00000000000619801E0060087320000000087 +:10E1000000D401EC0600003200000000A8000078F6 +:10E1100049403C370000CE1200000008E9A5909A63 +:10E120006089200000000084020037320000C41221 +:10E13000B8010080020000B00000C21200000080A0 +:10E140000200009000000000000000C40380903234 +:10E150000000000000B001E096216E3C00000000CD +:10E16000619801E0060087320000000000D401EC55 +:10E17000060000320000CE12A8000008198F909A05 +:10E18000000000000000007899A1893E0000000016 +:10E1900000000008E9A5903A0000000000B001E08E +:10E1A00096216E3C00000000619801E00600873275 +:10E1B0000000000000D401EC060000320000D11283 +:10E1C0000600008072A290BC00C0FF3F008001E00A +:10E1D00006003732000000000000000809C0893244 +:10E1E0000000D61204790180821B87BC0000D41283 +:10E1F00004B0008002006EBC0000D912D99001E08A +:10E20000068090920000DC128000008052812FB6C0 +:10E210000000DC12D54101E0060087920000D9120F +:10E220003C9001E0068090B200001613800100804F +:10E2300092812FB60000000000C801E806C08B32B2 +:10E24000000000009501008002802F720000DD12A6 +:10E250009F410180821B87BC0000000000010080FC +:10E260000200007000000000D99001E006809032AA +:10E2700000000000000100F872802F740000FFFF12 +:10E280000000008002000090270000000000001045 +:10E29000090036320000801200000014094087D2C5 +:10E2A0000000E7129FD8018022216EBC0000000010 +:10E2B0000B010080020000700000E7129FE0018067 +:10E2C000C2216EBC000000000B0100800200007043 +:10E2D0000000E7129FB00180D2216EBC0000000058 +:10E2E00000010080020000700000E9120668018051 +:10E2F000825B87BC00000000006801E006408732B6 +:10E300000000EB1237B001E0064087B200000000C9 +:10E31000000000F8D2802F340000000000D801E097 +:10E32000068084320000000000E101E006008772F0 +:10E330000000FFFF000000800200009000001613A4 +:10E3400008000080028092BC0000FB1204C101841E +:10E3500002006EB20500000000C001E8868D923711 +:10E360000300000000C401E8868D92370000000021 +:10E3700000000080020000300300000000C0012CFB +:10E38000898D6E360000000000C4012CA9DB923A92 +:10E39000000000000000002C29C0923600000000A0 +:10E3A0000000002C19FB923F000000000000002834 +:10E3B0002980923A000000000000002CA9E4923F5E +:10E3C000000000006FCC01E826FB923E0000000038 +:10E3D00000B901E0060000520000000000000094B7 +:10E3E000028092320000000000C001E006402832A6 +:10E3F000100000006FCC01E886CD2A360000000036 +:10E4000000B901E0060000520000FFFF000000809C +:10E41000020000900000161304B0008002006EB2EB +:10E4200000000000009001BC08006E3200000000F7 +:10E4300000B001BC88DB8B3E00000000009801BCEE +:10E4400088DB8B3A00000C139F0000BC88E18BBC7A +:10E4500000000C13040C0240A8DB8BBE000000007F +:10E4600000B00004881B843E0000091304B1008042 +:10E47000825B80BC00000000000100F8C2802F74A5 +:10E4800000000000040C0280A25B807C00000C13E2 +:10E490000468017819006EB60000000002000080D8 +:10E4A000E265807C2900000000000010090036327F +:10E4B000000080120000001409C08BD20000000090 +:10E4C0000000008812002C3A0000FFFF00000080CE +:10E4D000020000900000161304310280A2DB2CBC65 +:10E4E0000000161380000080A2802FB608000000F4 +:10E4F000001C01E876208139EEFF0000000100F8E1 +:10E50000828D2F710000FFFF00000080020000904C +:10E5100000001613000000B40F40FB940000000040 +:10E52000000000880F402B32000000000000009027 +:10E530000F00283200000000000000940F00293274 +:10E5400010000000000000B85F461839FF0000000E +:10E550000000009C0F003632000000000000009C0C +:10E560005FCAF935000000000000004403C0F93222 +:10E5700000000000000000E4030000324100001031 +:10E58000000000E00300373200000000000000E45B +:10E590000300003240000010000000E003003732AA +:10E5A00000002513670000980F802AB200000000C9 +:10E5B000000000A8020000320000231312C186E010 +:10E5C00007C021B20000000000B886C006802A32D1 +:10E5D0004C420000000000A8020036322713381415 +:10E5E000000000B00F003692000000000000009C08 +:10E5F0000200003200012414000000AC0F0036D2EB +:10E6000000000000000000AC0F802A320020000053 +:10E61000000000A802003632000000000000009C4C +:10E620000F007E3200000000000000A00F007E32CC +:10E6300000000000000000A40F007E320000000077 +:10E64000000000A80F007E3200000000000000A8BB +:10E6500002C0FA3200000000000000E007C0F932FA +:10E6600000000000000000E00700FA320000000097 +:10E67000000000E00740FA3200003B13000000E019 +:10E680000780FAD200000000000000E00780FB32A3 +:10E6900001006213040100B48F4DFBB002000000C2 +:10E6A000000000A002000039408000000000000CC3 +:10E6B000ABCDB032100000000000000C5BCAB039D6 +:10E6C000000000000000000C2BFEB03200006114BE +:10E6D000000000800200009000000000000000F830 +:10E6E0000300013200000000000100E007803F52FB +:10E6F00018000000000000F8738A023900000000D2 +:10E7000000000044530A1635000000000000009C81 +:10E710000F80963200000000000000A00FC096326B +:10E7200000000000000000A40F009732A260030068 +:10E730000000005803003732481300000000005C5E +:10E74000030036320000000000000050830D00344A +:10E750000000000000000048830D003400000000AD +:10E7600000000044530A003400003600000000801E +:10E7700002000090000000000000006809C0F932AB +:10E78000000000000000006C0900FA3200000000E8 +:10E79000000000700940FA3200005A1300000080A7 +:10E7A0000200009002000000000000A0F20B0039FF +:10E7B00000004F13800100801240B0B6000000003E +:10E7C000000000043B40B0330000000000000004E3 +:10E7D000FD4BD035000053130000000C0B00979246 +:10E7E00002000000000000A0F20B003900005313EB +:10E7F000000000046B01979400005313120000689E +:10E80000094020B2000054131200006C094020B2ED +:10E810000D000000000000FCA2E5163800005913AE +:10E820009F000080028096B200000000000000708F +:10E8300009C0963200005A130000006C09C0FD9216 +:10E840000000591312000070094020B200000000BF +:10E850000000009C0200003200000000000000D810 +:10E860000200003202005313040100BCAF2517B8A8 +:10E8700006005113040000BCAF6516B800004C132D +:10E880000400008022C0FBBC00006A13040000806A +:10E8900012C1FBBC200053130401008082CDFBBCDD +:10E8A00002000000000000A0F20B003900006B1312 +:10E8B00000000080020000D0641300000000008807 +:10E8C00082CDF93A00005A14000000800200009046 +:10E8D00000009313000000800200009000009413D9 +:10E8E00000000080020000900000981300000080EB +:10E8F000020000900000A0130000008002000090C1 +:10E900000000F91300000080020000900000531383 +:10E91000000000DC0F0097920000000000000000E3 +:10E920000700033240420000000000A80200363217 +:10E93000000000000008000007802A3200000000EC +:10E9400000100000070097320000000000180000CF +:10E9500007C096320880701312000040028036B261 +:10E960000000000000000080020000300000721370 +:10E970001200009C0FC021B21D007513040000801E +:10E9800072BE17B800007213000000F81E80EF9AE4 +:10E99000130000000000009C7FBE173800007813B1 +:10E9A0000400008012C0F9BC00007213000000F8DF +:10E9B0001E80EF9A000000000000009C0F007E32D5 +:10E9C00000000000000000A00F007E3200000000E8 +:10E9D000000000A40F007E320000000000010000D3 +:10E9E0000700FA52000000000000009C0200003204 +:10E9F0004C420000000000A8020036320000000077 +:10EA00000008000007802A3200004E140000008039 +:10EA1000020000D00000521400000080020000D06C +:10EA2000000000000000000CCBC1B034000000006A +:10EA30000000009C0200003200000000000000D82E +:10EA400002000032000081110000002809C0B0D28D +:10EA50000000821304000080028092B2000086133E +:10EA60001200009C0FC021B21D0089130400008019 +:10EA700072BE17B800008613000000F81E80EF9ADF +:10EA8000130000000000009C7FBE173800008C13AC +:10EA90000400008012C0F9BC00008613000000F8DA +:10EAA0001E80EF9A02008E13040100B48F4DFBB05C +:10EAB00000005313000000800200009008000000D6 +:10EAC000000000F89340013900000000000000B48D +:10EAD0001F40FB35FE0000000000004803003632F6 +:10EAE0000000000000000044030000340000821316 +:10EAF0000000000C8BC1B09400005E140008000000 +:10EB00000740FA9200004E14000800000740FAD2B5 +:10EB10000880951312000050028036B20000531492 +:10EB200000000080020000D000006014000000809F +:10EB300002000090000800000000009C0F00363228 +:10EB400000040100000000A80200373200000000AD +:10EB5000000000A00200003200000000000000E001 +:10EB60000700B03200000000000000A012002A3AA6 +:10EB700000009B130401009C1FC0F9BC00040100AD +:10EB8000000000A80200373202005D14000000A05F +:10EB9000F20B00990000A813040100800240FAB2B1 +:10EBA00000040100000000A8020037320000AA1390 +:10EBB00000000080020000D00000B71300000084B5 +:10EBC000020000D200000000000000E007C03C325C +:10EBD0000000A4138E010080024028B2000401004E +:10EBE000000000A40F0037320000931300000080E3 +:10EBF0000200009000040100000000A4CF4DFA3A8A +:10EC0000000093130000008002000090000000004C +:10EC10000000009C0F00003210000001000000AC5A +:10EC20000F0037320000BC1300000080020000D04B +:10EC30000800AC130401008082CDF9BC0000000084 +:10EC40000000009C0F0000320E000001000000AC2C +:10EC50000F0037320000BC1300000080020000D01B +:10EC60000B00B0130401008082CDF9BC200000002D +:10EC70000000009C0F0036320F000001000000ACC5 +:10EC80000F0037320000BC1300000080020000D0EB +:10EC90002700B4130401008082CDF9BC00000000FD +:10ECA0000001008002000050000000000000009CF5 +:10ECB0000F0000320F000001000000AC0F003732DF +:10ECC0000000BC1300000080020000D02000B91337 +:10ECD0000401008082CDF9BC00000000000100802A +:10ECE0000200005000000000000000E403C0F93200 +:10ECF0000D000001000000E00300373200000000BA +:10ED0000000000E003C0FA3200000000000000E054 +:10ED100007403E32000000000001009C1FC0F95A6D +:10ED200000000000000000E003C0F9320000000015 +:10ED3000000000E007403E32000000000000009CA0 +:10ED40001FC0F93AFF000000000100AC8FCDF95060 +:10ED5000000000000000009C0FC02F3200000000E7 +:10ED6000000000FC0200003200000000000000E093 +:10ED700007803E3200000000000000FC12C02F3A65 +:10ED80000F00C7130401008082CD2FBC00000000DB +:10ED9000000000E007803E3200000000000100FC9F +:10EDA00002C0F95200000000000000E007003A3203 +:10EDB00000000000000000E007403A3200000000C0 +:10EDC000000000E007803A3200000000000000E090 +:10EDD00007C03A32000000000000009C0FC02F3234 +:10EDE00000000000000000FC0200003200000000F3 +:10EDF000000000E007003D3200000000000000E0DD +:10EE000007403D320000D213830100FC12C02FBA2C +:10EE100000000000000100FC02C0F95200000000E8 +:10EE20000000009C0F0000320C00000000000008F1 +:10EE3000733E003900000000000000E0070030329F +:10EE4000000000000000009C1FC0F93A7000D713BA +:10EE50000401008082CDF9BC000000000000000C1D +:10EE60000300003200000000000000E00700303224 +:10EE7000000000000000001003000032000000004D +:10EE8000000000E007003032000000000000009C9D +:10EE90000F00003200000000000000A00FC0293267 +:10EEA000000000000000009C02C0F93200000000D9 +:10EEB000000000A40FC02C32000000000000009CE5 +:10EEC0000200FA32180000000000002C737EFA39AC +:10EED00000000000000000E0070030320000E013F6 +:10EEE0008501009C1FC0F9BA0000000000010080ED +:10EEF00002000050010000010000009C0F003732AA +:10EF00000000C11300000080020000D00E00EF13CB +:10EF10000401008082CDFABC00000000000000E087 +:10EF20000700003200000000000000E0070000328F +:10EF300000000000000000E0070000320000E913BC +:10EF40000000009C3FC0F99A1C00E91304010080F6 +:10EF500082CDFABC0200C1130000009C8FCDF9DA0B +:10EF600000000000000100800200005001000002CB +:10EF70000000009C0F0037320000C1130000008029 +:10EF8000020000D00E00F7130401008082CDFABC0D +:10EF900000000000000000E0070000320000F31352 +:10EFA0000000009C1FC0F99A2600F31304010080A2 +:10EFB00082CDFABC00000000000100800200005079 +:10EFC00000000000000000A80F40293200040100EA +:10EFD000000000A8020037320000E81300000080A3 +:10EFE000020000D00000F21300000080020000D0F8 +:10EFF0000000C51300000080020000D000000000E7 +:10F00000000000E00780183200000000000000E06F +:10F0100007401A3200000000000000E007001A322A +:10F0200000000000000000E007801A32000000002D +:10F03000000000E007C01A3200000000000000A03D +:10F040000F000032A26003000000005803003732B6 +:10F050000B1400000000005C0300363200000000CA +:10F060000000009C0F802A3200000B140400008076 +:10F07000024029B20000000000000050833E00342E +:10F080000000000000000048833E00340000000043 +:10F0900000000044530A003400000C1400000088F3 +:10F0A0000F402B9200000000000000900F0028325B +:10F0B00000000000000000940F0029320000000052 +:10F0C000000000980F802A3200000000000000A815 +:10F0D00002C0F93211143814000000B00F0036924B +:10F0E0000700141404000080824D29BC00000000B9 +:10F0F000000000A01F00FA3A000008140000009C65 +:10F100000F802A92C0010000000000AC0F003632D0 +:10F11000010000000000009C0200363200002414B0 +:10F1200000000080020000D01F001A1404000080BC +:10F1300082CD29BCC0000000000000AC8FCDFA3A9F +:10F14000000016140000009C12C0299A0000D6137B +:10F1500000000080020000D00000CC1300000080FE +:10F16000020000D00000221404000080528AFABC81 +:10F17000A260030000000058030037322214000090 +:10F180000000005C03003632000000000000005068 +:10F19000A33E00340000000000000048A33E0034FD +:10F1A0000000000000000044530A00340004010085 +:10F1B000000000A40F00373200009313000000800D +:10F1C0000200009000000000000000C402C0FA32FB +:10F1D000030000000000009C0F0036320000000019 +:10F1E000000000BC0F402F3200002B140400009CD4 +:10F1F0001FC0F9BC00002A140400008002402FB296 +:10F2000000002714000000E007002C9200002714E3 +:10F21000000000E00700369200000000000000E05F +:10F2200007402C3200000000000000E007802C3274 +:10F2300000000000000000E007C02C3200000000C9 +:10F24000000000E007002D3200000000000000E098 +:10F2500007402D3200000000000000E007802D3242 +:10F2600000000000000000E007C02D320000000098 +:10F27000000000E007C0FB3200000000000000E0DA +:10F2800007802F3200000000000000E007C02F328E +:10F2900018000000000000F8730A023900000000A6 +:10F2A000000100E007803F52FF0000000000004422 +:10F2B0000300363200000000000000E00700F932D1 +:10F2C00000000000000000E00740283200000000BD +:10F2D000000000E00780F832030000000000009CFE +:10F2E0000F00363200000000000000BC0FC02B32BF +:10F2F000000041140400009C1FC0F9BC0000401431 +:10F300000400008002C02BB200003D14000000E0A9 +:10F3100007C0289200003D14000000E0070036926C +:10F3200000000000000000E00740F932000000008B +:10F33000000000E00740293200000000000000E06B +:10F340000780293200000000000000E007C02932D9 +:10F3500000000000000000E007002A32000000006A +:10F36000000000E007402A3200000000000000E03A +:10F370000780F93200000000000000E007C02A32D8 +:10F3800000000000000000E007C02F320000000075 +:10F39000000000E007402B3200000000000000E009 +:10F3A00007802B3200000000000000E007C0FB32A5 +:10F3B00000000000000000880200FB320000000096 +:10F3C0000000009C0200003200000000000000D895 +:10F3D0000200003200000000001000000700973219 +:10F3E000000000000019000007C096520880521467 +:10F3F00012000048028036B20000000000000080C9 +:10F4000002000030000054141200009C0FC021B212 +:10F410001D0057140400008072BE17B80000541479 +:10F42000000000F81E80EF9A130000000000009C0E +:10F430007FBE1738000000000400008012C0F95C95 +:10F4400000005414000000F81E80EF9A0000000035 +:10F45000000000B40F40FB35000000000000009CDD +:10F46000020000324C420000000000A802003632C8 +:10F47000000000000008000007802A3200004E143F +:10F4800000000080020000D0000052140000008044 +:10F49000020000D0000000000000000CCBC1B0341E +:10F4A000000000000000009C02000032000000008C +:10F4B000000000D80200003200006B140000002899 +:10F4C00009C0B0D20000611404000080028092B232 +:10F4D000000065141200009C0FC021B21D006814CA +:10F4E0000400008072BE17B800006514000000F828 +:10F4F0001E80EF9A130000000000009C7FBE1738AA +:10F50000000053130400008012C0F9BC0000651411 +:10F51000000000F81E80EF9A00000000000000FCD0 +:10F520000200003202000000000000A0F20B0039CF +:10F5300000006F14040100280934B0BA0000000074 +:10F54000000100280900005200000000000000A88F +:10F5500022C02F3700000000000084C037ACB0325A +:10F56000000000000000000C0B000032FFFF000054 +:10F57000000000C0AF4DB030000075148000008066 +:10F580000240B0B600000000000000C06F01FC3572 +:10F590000000000000000000073F013200420000B0 +:10F5A00000080000878D2A3A0000000000100000CB +:10F5B0000700B03200000000001800000700D03241 +:10F5C00000000000000000C03FC13834000000000F +:10F5D00012010048F201FC5400007A14000000807F +:10F5E000020000900000FFFF000000800200009079 +:0CF5F000000036000000008002000090C7 +:00000001FF diff --git a/firmware/sxg/saharadownloadB.sys.ihex b/firmware/sxg/saharadownloadB.sys.ihex new file mode 100644 index 000000000000..0309852443b6 --- /dev/null +++ b/firmware/sxg/saharadownloadB.sys.ihex @@ -0,0 +1,3385 @@ +:10000000020000005CD300000C00000000000000B3 +:10001000FF1F00000100000000000088824D293A07 +:100020000000400300000080020000900000090072 +:100030000000008002000090000009000000008025 +:100040000200009000000900000000800200009003 +:10005000000009000000008002000090000009007C +:1000600000000080020000900000090000000080F5 +:1000700002000090000009000000008002000090D3 +:10008000FEFF0000000000AC020036320000360027 +:10009000000000A80200009200003610000000805E +:1000A0000200009000003610000000800200009066 +:1000B00000003610000000800200009000003610A2 +:1000C0000000008002000090000036100000008058 +:1000D0000200009000002000000000D80F8028924D +:1000E00000002100000000D80F80289200002200AC +:1000F000000000D80F80289200002300000000D8E4 +:100100000F402B9200002400000000D80F8028929E +:1001100000002500000000D80F8028920000260073 +:10012000000000D80F80289200002700000000D8AF +:100130000F80289200002800000000D80F8028922D +:1001400000002900000000D80F80289200002A003B +:10015000000000D80F8028920000360000000098B0 +:100160001E80E99A00002C00000000D80F80289221 +:1001700000002D00000000D80F80289200002E0003 +:10018000000000D80F80289200002F00000000D847 +:100190000F80289200003000000000D40F00009271 +:1001A00000003000000000D40F400092000030003A +:1001B000000000D40F80009200003400000000D442 +:1001C0000FC0009200003000000000D40F00019228 +:1001D00000003000000000D40F4001920000300009 +:1001E000000000D40F80019200003000000000D415 +:1001F0000FC0019200003000000000D40F000292F6 +:1002000000003000000000D40F40029200003000D7 +:10021000000000D40F800292000036100000008021 +:100220000200009000003000000000D40F00039294 +:1002300000003000000000D40F40039200003000A6 +:10024000000000D40F80039200003000000000D4B2 +:100250000FC0039200000000000000D05F3F003498 +:10026000000036100400008042FFFCB000000000D7 +:10027000000000881280FD3A000036100000008067 +:10028000020000903610361002010080828DFDBC05 +:1002900000000000000000881280FD3A000000000D +:1002A000000000F803C001323800000000010084A3 +:1002B000824D281A000036000000007409400092A8 +:1002C00000004F00000000FC020000920000480007 +:1002D000000000800200009000004D00000000902F +:1002E0000E80189200008F020000000008C02092CB +:1002F00000007F00000000000800219200008D0235 +:10030000000000000840219200007C000000000076 +:10031000088521900000F202000000EC02C0229249 +:100320000000CE0300000080020000900000560094 +:10033000000000FC0240189D00005100000000D0A9 +:1003400002000092000020030000008002000090E4 +:100350000000361000000080020000900000000045 +:10036000000100800200007000004C00000000004E +:1003700009C0219200004A0012010000088522B045 +:1003800018003600000000F8738A0299000084000B +:100390006A000080020000B008008400000000F83D +:1003A0002340019900000000000100E80200907263 +:1003B0000000361080010080B200E9B600003E0364 +:1003C0000000007C1EC0E79A08000000000000F852 +:1003D000134001390000320300000008B801009406 +:1003E000000036100300007809401ABD000000002C +:1003F000000000A0E125003408000000000000F823 +:10040000B340013900003E03B20000D8020000B240 +:1004100000004005001001F802006E920000590033 +:100420000A0100CC020000B200006A00030100FCD7 +:10043000024019BD08003E03000000F8A3400199E6 +:10044000000000000000008401C02F320000000006 +:1004500000000090F1010034000000000000009452 +:1004600001C02F3202005C00B00000A0F20B00B906 +:1004700000005F000401008002C0B0BC0000680002 +:10048000A000008002000090000061008001008058 +:10049000F24BD0B600006800A0000080020000907F +:1004A00000000000A0000004FD4BD03400006600F6 +:1004B000800100801281FCB600002D0F000000D8E2 +:1004C000020000D218000000000000F8730A03398F +:1004D00068003600000000C0020036920000040FE1 +:1004E000000000D8020000D218003600000000F81A +:1004F000730A03F900005900030100FC024018BD13 +:1005000000007B00030000FC024019BD0000000059 +:100510000000009401C02F320000000000000080A5 +:10052000F1010034000000000000008401C02F32FF +:1005300002006D00B00000A0F20B00B900007000D6 +:100540000401008002C0B0BC00007900A00000805F +:10055000020000900000720080010080F24BD0B6D3 +:1005600000007900A0000080020000900000000060 +:10057000A0000004FD4BD034000077008001008013 +:100580001281FCB600002D0F000000D8020000D23E +:1005900018000000000000F8730A033979003600E3 +:1005A000000000C0020036920000040F000000D8D6 +:1005B000020000D218003600000000F8730A03F9A8 +:1005C00000006A00030100FC024019BD0000590050 +:1005D000030100FC024018BD08003E03000000F8C3 +:1005E000A340019908000000000000F873400139A1 +:1005F0000000840080010080E20180B600008100DC +:1006000000000080020000900800ED020C0000F8DD +:10061000534001B90000830080010080E20180B6F0 +:100620000000361012000068020580B0000032039E +:100630000000006C1FC0F69A0000000000000000DF +:100640000805803000000000000000FC02000132BC +:10065000000000000000001008803D320000000093 +:10066000000000D40200003202A0000000000000E0 +:10067000A90D8032000088001200005402A438B294 +:10068000000200800000002C0800373218003600FD +:10069000000000F8730A03F90000000000080004DD +:1006A00008807232000090009F00005C080072B267 +:1006B00087008F008001008082CD85B00000A100FE +:1006C0000000002CD8C182940000A1000000002C82 +:1006D00088C18294000F99000401008082CD85B00A +:1006E00000009900800000804281FCB600003610B6 +:1006F00012000068020580B0000000000000006CDD +:100700001FC0F63A00000000000000FC02000132A9 +:1007100000009700040100DC43603DB30000320399 +:10072000000000FC0200009218000000000000F829 +:10073000738A033994003600000000C0020036922C +:1007400010009F0087000078792116B801009F00F3 +:1007500004010080828D97BC8700A8008700007884 +:1007600089CD85B000009E0004010080128097BCF6 +:100770000000A1000000002CD8C182940000A1005C +:100780000000002C88C182940000A8008001008035 +:10079000F2C085B60000A8000000002C98C1829429 +:1007A0000000A70080010080D2C182B60000A8002E +:1007B000800100807280FCB600000000001800A8D4 +:1007C000423D723000000000541889FCF2C07C30B9 +:1007D0000000CB0080010080F2C185B60000A900B6 +:1007E00000000080020000900000A3008000008054 +:1007F0008280FCB600000000540000FC02000032C1 +:100800008000802000000080C2CD85300000BE0046 +:100810000B000080020000B018000000000000780B +:1008200079A116382000CB0004000080828D97BC8F +:100830000000B500800100806280FCB68700B50032 +:100840008700007889CD85B00000B10004000080E9 +:10085000128097BC0000B50004010080228097BC84 +:100860000000B5008001008072C185B61000000054 +:1008700000000078796116380000BC000401008097 +:10088000328097BC0000CB000000002CB8C18294DD +:100890000000BC00800100805280FCB60000BC005B +:1008A0008000008072C185B60000BC00800100801D +:1008B00002C185B60000BC0080010080D2C185B6AF +:1008C000180000000000007879E116380000BC0034 +:1008D00004010080328097BC0000CB000000002C97 +:1008E000C8C1829400000000000000040800043227 +:1008F0000000CB000000002CA8C18294080000007A +:1009000000000078792117380000CB000400008037 +:10091000328097BC0000CB0004010080228097BC8D +:100920001F0000000012000889CD72300500000091 +:1009300000120000B9DC173800000000000000A819 +:10094000220090370000CB008000868022247CB6F5 +:100950000000361012000068020580B000000000A0 +:10096000000000FC020001320000C900040100DCAC +:1009700043603DB300003203000000FC020000921F +:1009800018000000000000F8738A0339C600360022 +:10099000000000C0020036920000CE00120100608C +:1009A000084023B2008200000000000808803632B0 +:1009B0000000C500000000641F40F69A00003610D9 +:1009C00012000024080023B200003610120000209C +:1009D00008C023B20000361012000018088023B2AD +:1009E00000000000000000FC020001320000D50001 +:1009F000040000DC43603DB318000000000000F874 +:100A0000738A0339D1003600000000C0020036921C +:100A100000000000000000FC020085320000000021 +:100A2000000000D80280013200000000000000D069 +:100A30000200003200C0E1001801000CA8CD3EB257 +:100A40000000D50012000038028081B200000000D2 +:100A50000000003C02008232000000000000003074 +:100A600002408232000000000000003402008632A2 +:100A700020800000000000080880363200000000DE +:100A80000000005C1FC0F53A00003203120100684C +:100A9000020580B0000036100000008002000090C7 +:100AA0000000000000180078090072320023E40002 +:100AB00004010080A2CD82B00000E500000000002B +:100AC00009000092000036109F16000029C172BC78 +:100AD00000000000001800000780813200000000C4 +:100AE0000020000007008232000000000028000003 +:100AF0000780973210000000003000001720903966 +:100B0000000000000038000007C082320000000032 +:100B1000000000D8020000320000000000000000C9 +:100B2000074080320000EE0080010080A2C182B642 +:100B30000000EF000008000057008097050000004B +:100B40000008000007A0043900003610041000005F +:100B5000074082B200000000001800000700863243 +:100B60000000F10012000050F2C138B41800360045 +:100B7000000000F8730A03F9000036101200006844 +:100B8000020580B00000F4001200004802C080B2EC +:100B900000003203CA010008E881809408000000C8 +:100BA000000000F89340013910000000540000FCE0 +:100BB000824D90360000F800F00100D8020000B22B +:100BC00000000000620401A802C06E3200000000B4 +:100BD0000004010059C06E370000000000040178D5 +:100BE00019C06E3A000000004E0401EC06BD9730BB +:100BF00000000000E00000F41E40EF3A000000009A +:100C000000188BCC074000320000000000000000FC +:100C100007400932000000000008000077C02937B3 +:100C20000000361004100000173D90BA00000000CC +:100C3000001800000780F432000003011200004099 +:100C4000F2C138B400000000000000FC32C02F30B8 +:100C5000000000000000001008803D32180036003F +:100C6000000000F8730A03F900000000000000D43F +:100C700002000032000090018038008022C072B66D +:100C800000000C01120000C8020020B20000130195 +:100C90001201005C088020B20000361012000060D3 +:100CA00002802CB218000000000000F8738A03399B +:100CB00009013600000000C002003692000000006A +:100CC000000000F81F80FF3A00000000000000FC58 +:100CD00032008530000068010400008042603DB3AE +:100CE00018000000000000F8738A03390F01360075 +:100CF000000000C002003692080000000000000062 +:100D000088CD853700000000000000200800723206 +:100D100000000000000800240800723200003610B5 +:100D20000410006C080072B2000000000018004CB3 +:100D3000080072320000361004200018080072B259 +:100D4000000000000030002808007232000000009F +:100D5000002800300800723200000000000000602F +:100D600008808232000022010600008062A082BC5E +:100D7000000000000000000007000632070000002D +:100D800000080000774A09390000361004100000FE +:100D9000070082B200000000CA190000074082323A +:100DA0000000210112000040F2C138B40000000030 +:100DB000000000D8024000320000470104380078EB +:100DC000D9C572B00000260180010080028097B66C +:100DD00000000000000000F882802F34000028018D +:100DE00080010080128097B600000000000000F82B +:100DF00092802F34040000000038003CB81C1738E3 +:100E0000000000000000003C28C083370000000004 +:100E1000003A002C08C07232000000000000001CE4 +:100E2000B8E0833A00000000CB2900200700003220 +:100E3000000046010400008002C081BC00000000E8 +:100E40000000003478A0813E000000000000001C7B +:100E5000D8E0813C00003501063A0080B25C83BCDA +:100E600000000000003A000089C172370700340119 +:100E70002B010004790A04B900000000CB00000433 +:100E80001941903400003801003A002C070000920C +:100E900000000000003A002CD7E0723C0000000087 +:100EA0000000000009000032000000000000000403 +:100EB00009000032000000000000000007648332D7 +:100EC000000000000008000007008032000036101B +:100ED0000410000007C086B20000000000180000E7 +:100EE00007C084320000550104000028D8A082BC4D +:100EF0000000000000000000D820803A00004101FE +:100F00000400008072802DBC00003F0112000044EC +:100F100012E438B200004201000000D812802D9A7D +:100F20000000BD0F00000004F94190F400004401EE +:100F300004000018D8A081BC00002D010000006C46 +:100F4000D8E0869A00007A0F0000004408802DF255 +:100F500000002D0100000030080000920000000099 +:100F6000CB19002007000032070049012B010004C3 +:100F7000790A02B900000000CB0000041941903446 +:100F8000000000004D000000A7A0813E000000000E +:100F90000008000007008032000036100410000036 +:100FA00007C086B2000000000018000007C08432AD +:100FB0000000550104000028D8A082BC00000000F9 +:100FC00000000000D820803A000052010400008098 +:100FD00072802DBC000050011200004412E438B2AF +:100FE00000005301000000D812802D9A0000BD0FB0 +:100FF00000000004F94190F400007A0F0000004462 +:1010000008802DF200004701000000300800009227 +:101010000000000000000004F94190340000560177 +:101020001200004412E438B218003600000000F844 +:10103000730A03F9000000000018000409807332ED +:1010400000000000002800088980733700000000BD +:101050000000008007008632410000000006008C7E +:101060000700363200005F012908008007C085B202 +:10107000000062012810008C070000B2000063012C +:101080000012008407000092000000000010008C95 +:10109000F7E0823A0000620128180080074090B211 +:1010A00000006301001200840700009200000000AD +:1010B0000012008427E482320000660104000080F0 +:1010C00042603DB318000000000000F8738A033945 +:1010D00063013600000000C00200369200000000EC +:1010E000000000FC02008532000036101200005C97 +:1010F00052812CB400000000000000D802800132B0 +:10110000000000000000008002003B3208406A013D +:10111000F0010008088036B2000000000004013829 +:1011200008C06E3200000000E00000F41E40EF3CFA +:10113000000071010B01008C080000B200006E017C +:10114000F2010080020000B000000000000000F08A +:101150000E003A3200008201E20000800E8083928D +:1011600000007101F2010078C93B3ABC00007B012C +:1011700002010080828097BC00000000000000A8EF +:101180000200E832000076010400008022A22ABC9E +:1011900000007A0104198B8002C07CBC00000000B2 +:1011A0000000008C18C0883A00000000000000A871 +:1011B00012802A3A00000000000000A802BD2A3078 +:1011C0000000740104010080E2A02ABC00007F013D +:1011D0000200008082C088BC00000000E20000081D +:1011E0000800003200000000000000A802808832E1 +:1011F0000000000000188BCC070000320000320312 +:10120000000000DC03000092000000000000003835 +:1012100008802A3200000000000000F00E003A3280 +:1012200000000000E20000800E802A320000000072 +:10123000000000A8028088320000000000188BCC5B +:101240000700003200000000000000DC0300003254 +:101250000000000000000000078083320000000052 +:101260000000000079C02937602000000000000065 +:10127000890D903A00000000CA0100D812802D3A72 +:101280000000000000000000070001320000000024 +:10129000000800000700903200000000001000006D +:1012A0000740E83200000000001800000780E83224 +:1012B00000000000000000FC0200003200003203C9 +:1012C00012010048F2C138B400008E010000008015 +:1012D00002000090000000000030007808807232A8 +:1012E0000400000000380054A85C16380B00000011 +:1012F0000038002CA8DC1638140000000000001C88 +:10130000884D853A0000000000000020080072327D +:1013100000000000000800240800723200000000F5 +:101320000010006C08007232000000000018004C31 +:10133000080072320000361004200018080072B253 +:101340000000000000280030080072320000A101F7 +:10135000083C0014188072BC00000000000000145B +:101360001840813C00000000000000000700063229 +:101370000700000000080000774A09390000361015 +:1013800004100000070082B200000000CA1900002B +:10139000074082320000A00112000040F2C138B4C0 +:1013A00000000000000000D80240003200000000F1 +:1013B0000000006478C029370210000000000064BB +:1013C000884D863A000000000000008008000032CE +:1013D0000000000000000040080000320000000093 +:1013E0004D00000077A0813E0000000000080000D2 +:1013F00007408632000036100410000007C086B295 +:10140000000000000018000007C084320000B9018D +:101410000400001CD8E081BC000000000000006453 +:10142000D860863A0000AF010400008072802DBCB5 +:101430000000AD011200004002C038B20000B5014A +:10144000000000D812802D9A0000AF011200004069 +:10145000F2C138B418003600000000F8730A03F92E +:101460000000B4010401008002802DBC0000B00126 +:10147000670000F8A2802FB500003610120000E8C7 +:1014800002C021B200000000000000D8024000327B +:101490000000B70104000018D8A081BC0000A6011C +:1014A0000000006CD8E0869A00005D0E0000004449 +:1014B00008802DF20000A601000000300800009214 +:1014C0000000B90112000040F2C138B41800360023 +:1014D000000000F8730A03F90000BE010401008057 +:1014E00002802DBC0000BA01670000F8A2802FB571 +:1014F00000003610120000E802C021B20000C9014D +:1015000004010080020084BC00000000000000D440 +:101510000240003200000000000000A42240853A92 +:10152000040000000018004088CD74360000000060 +:10153000000000402800843700000000000000D4B4 +:10154000020000321400C9010400001C880D84BC94 +:1015500000000000000000780961853A8000361024 +:1015600006010080828D97BC00000000000000642E +:10157000D860863A0000B501000000D80240009211 +:101580000000CB0104000018D8A081BC0000CD01F0 +:101590000000006CD8E0869A00005D0E0000004458 +:1015A00008802DF20000000000000030080000322A +:1015B00000000000000000D40240003200000000E3 +:1015C000000000A422C0823A000000000000003C9D +:1015D000B860853C0400D3018100006088CD74B6FA +:1015E0000000000000040028F8A0753C0000D401B1 +:1015F00000080074088075920000000000080028B0 +:10160000F8A0753C000000000000002808A1823C02 +:1016100000000000000000A4F2602A3A0000000070 +:101620000008004808007532000000000020007C1F +:10163000088075320900DA01041A007088CD74B090 +:1016400009000000001A004C87CD74317F000000B3 +:1016500000000064884D8631000000000000006436 +:101660002840863A00000000000000D80240003206 +:10167000000000000010000007408632000000005B +:10168000000000D8028000320000000000100000BE +:101690005761863A0000E301120000C8020020B240 +:1016A0000000E6011201005C088020B20000361044 +:1016B0001200006002802CB200000E012A0100D44A +:1016C000020000B218003600CA0000F8730A03F9DD +:1016D00000000F01000000F81F80FF9A00000000CA +:1016E000000000D4024000320800000000000000AA +:1016F00088CD8537000000000000001CE8A1823E74 +:1017000000000000000000A42240853A0000000014 +:1017100000080050078084320000ED0104010080C1 +:1017200072A082BC00000000001A004CC7E17432B5 +:10173000000000000000006808E1813A0000F001AC +:1017400090010078F9A186BA00000000000000783E +:101750001980973A00000000002000580780973257 +:1017600000000000000000D80280003200000000ED +:101770000000000007008432000000004008000064 +:101780005721803A0000F4011200004CF2C138B435 +:1017900000000000000000000821803A0000000066 +:1017A0000000000408C0813200000000510000D891 +:1017B00002C0003200000000000000D4020000322D +:1017C00000000000CB190020070000320700FC01D8 +:1017D0002B010084780A02B900000000CB000084CD +:1017E00018418834000000004D00000077A0813EC1 +:1017F00000000000000800000700803200003610E2 +:101800000410000007C086B20000000000180000AD +:1018100007C08432000036109F000028D8A082BC88 +:10182000000014020400001CD8E081BC0000080283 +:101830002D000000D82080BA00000502120100E847 +:1018400002C021B218003600000000F8730A03F944 +:10185000000007020401008022802DBC0000080265 +:10186000CD0100D80240849200000402000000F87C +:10187000A2802F9500000B020400008072802DBC16 +:10188000000009021200004412E238B20000120205 +:10189000000000D812802D9A000000000000008493 +:1018A000F841883400000C021200004412E238B201 +:1018B00018003600000000F8730A03F90000110256 +:1018C0000601008022802DBC00000D02670000F898 +:1018D000A2802FB500000E02000000E802C0219295 +:1018E00000000000000000D802C0003200005D0EC1 +:1018F0000000004408802DF20000FA0100000030D2 +:101900000800009200001A0280000080D2802FB6EA +:1019100000001702120100E802C021B218003600D0 +:10192000000000F8730A03F90000190204010080A6 +:1019300022802DBC00001A02000000D802408492D0 +:1019400000001602000000F8A2802F9500000000A1 +:10195000CD000084F841883400001B0212000044CE +:1019600012E238B200000000000000D40240003251 +:1019700000000000000000A422C0823A0000230200 +:1019800004010080420086BC0000000000080058EE +:1019900007408732000022028F010074184087BA86 +:1019A0000000000000000074080000320000250262 +:1019B00000040058F7A0869A00000000000000789C +:1019C000F9A0863A2800000000080058878D973C4F +:1019D00000000000000000D80240003218000000A3 +:1019E00000000000B7608539080000000008000012 +:1019F00087CD8537000028021200004CF2C138B4B0 +:101A0000000000000000004818A0843A0000000018 +:101A1000000000D40200003200000000000000803E +:101A200057A1863A410000000006008C07003632BC +:101A3000000000000008008007C0853200000000A0 +:101A40000010008C0740853200000000000000D824 +:101A5000028000320000361004000058088071B285 +:101A600000000000000000800880003218003600EE +:101A7000000000F8730A03F9000035020401008039 +:101A800002802DBC00003202000000F8A2802F95D9 +:101A90000000320204010080180088BC00003802F7 +:101AA00090190058E89C85BA00000000000000581A +:101AB0001880853A000000000018008007858530F6 +:101AC00000003D0204010080420086BC00000000CE +:101AD000000000D8024000320000000000000008B2 +:101AE0008980713700003E020012008427E4829250 +:101AF00000000000001200840700003200004202D3 +:101B0000270000FC020085B20000420204000080B1 +:101B100042603DB318000000000000F8738A0339EA +:101B20003E023600000000C002003692000036106F +:101B30001200005C52812CB40000450204010080B8 +:101B4000028082BC00006801000000D40200009204 +:101B50000000480204010018D8A081BC00005D0EFE +:101B60000000004408802DF20000E001C7010030B1 +:101B7000080000920000E001C701006CD8E0869ADE +:101B800008000000C60100F893400139000032034C +:101B900080018080320B6AB600000C0E0000003C11 +:101BA000030038F200004E020406018002C06EBC41 +:101BB00000003103000601EC56E06E9A00000000C0 +:101BC000C40701EC56E06E3A08C04F021200004014 +:101BD000A2CD39B218003600000000F8730A03F9EC +:101BE0000000361003B8000009C06EBD53020000AB +:101BF00000000088820D903A2F007C050000001C38 +:101C000008003692000036100000008002000090AC +:101C10002C007C050000001C0800369200003610E5 +:101C200000000080020000900000361000000080DC +:101C300002000090000036100000008002000090BA +:101C400038007C050000001C0800369239007C0535 +:101C50000000001C0800369208000000000000F898 +:101C60009340013900000C0E0000003C030038F2E4 +:101C700000000000000000F842802F3408C05E021F +:101C800012000040A2CD39B218003600000000F862 +:101C9000730A03F9000000000004017809C06E32E5 +:101CA00000000000006201EC068097320000000096 +:101CB000000601EC0640003200006302B50000D8C7 +:101CC000020000B200000000A50080A0360B6A34BC +:101CD00000000000003002E806C02C3200000000C6 +:101CE000001801E00600003200000000000000F8CB +:101CF00082852F3000007D050000001C0800369210 +:101D000008000000000000F89340013900006C0258 +:101D100080008080320B6AB6000032030000008031 +:101D20000200009000000C0E00000038030038F2A2 +:101D300000006F020402018002C06EBC000031038B +:101D4000000201EC56E06E9A00000000C00301ECB6 +:101D500056E06E3A00C0700212000040A28D39B207 +:101D600018003600000000F8730A03F900007C0236 +:101D70003828001809006EB200007502042101081D +:101D800069246EBC03007D050000001C080036922B +:101D90000000790202300080829B90BC0000780233 +:101DA0000603018012C06EBC04007D050000001C0B +:101DB0000800369205007D050000001C08003692E0 +:101DC00000007B020603018012C06EBC0B007D0583 +:101DD0000000001C080036920C007D050000001C6D +:101DE0000800369200007E020421010869246EBCBE +:101DF00003007D050000001C0800369200008202EE +:101E000002300080829B90BC0000810206030180AA +:101E100012C06EBC04007D050000001C0800369254 +:101E200005007D050000001C0800369200008402B9 +:101E30009F31010C69246EBC000000000000000C02 +:101E4000090000320000880204310004899B90BC24 +:101E5000000087020603018012C06EBC20007D05D1 +:101E60000000001C0800369221007D050000001CC7 +:101E70000800369200008A020402018012C06EBC83 +:101E800022007D050000001C0800369200008C0234 +:101E90000401000039A490BC23007D050000001C53 +:101EA0000800369224007D050000001C08003692D0 +:101EB000080036100C0000F8634001B910009102D0 +:101EC000C50100CC022015980800ED020C0000F8B6 +:101ED000434001B910000000C50100CC02201538B4 +:101EE00000000C0E0000003C030038F200009402D9 +:101EF0003601005C080580B00F007D050000001C65 +:101F00000800369210000000002C0200A9DB853981 +:101F1000000095021200005402A438B20000000034 +:101F20000008028C08C06E3200000000000C02980D +:101F300028806E37000000000000009C3822143713 +:101F400000009E020430002808006EB20000361027 +:101F50000410006C08006EB2000000000018004C75 +:101F600008006E32000036100420001808006EB21F +:101F70000500A1020038020078E16E99000000001F +:101F8000510000D802000032000000000038027842 +:101F900009C06E32050000006808000077A197397B +:101FA0000000A3021201000009C021B2180036008F +:101FB000000000F8730A03F900000000545401FC0B +:101FC00002C06E321410A70204000080A20D72B08D +:101FD0000000510F0000002809C002F20E007D052C +:101FE0000000001C080036920000B602331500A461 +:101FF00002C072B20000EA0280010080B20172B633 +:102000000101AD0204290080828D74BC080AEA0235 +:10201000042D0080828D74BC000000000030007C24 +:10202000080075320000B402003800881800759C62 +:10203000080AEA0204290080828D74BC10000000A6 +:10204000002C007C888D7537000000000030007C7B +:1020500068DD87320000B3029F390088188075BCA4 +:102060001000000000340088888D75370000B4022D +:10207000000000881880889C100000000034008850 +:10208000689D88390000B7029FF1018082DB87BC20 +:102090000000EA0200000080020000900000EA0256 +:1020A00080000080B20172B6000000000008004805 +:1020B0000800753200000000001000700800753242 +:1020C00000000000001C007438A275370000BC023C +:1020D000831B007808C074B200000000000000F804 +:1020E000C2802F340000CC029F780180C2216EBCD8 +:1020F0000000C0029F990164881B87BC0000CD02CC +:102100009F680164885B86BA0000000000000064DC +:102110000800003200000000001600A402C0723265 +:1021200000000000003C02A4B25B2A3A000000005C +:10213000003A027809C06E320000CE0208010004A5 +:10214000E8A575BC1000EA020B01001C080036B2BD +:102150000000CC0204A10180829B84BC00007D05AC +:102160009F980180C2216EBC00007D0506B10180F0 +:10217000825B87BC0000E9020B010080020000B016 +:102180000000CD0204990180C2216EBC0000E7026C +:1021900002D4018092FB6EBC16007D050000001C7D +:1021A0000800369217007D050000001C08003692DA +:1021B0001C007D050000001C080036920000D002C3 +:1021C00004A10180829B84BC0000D70206A8018084 +:1021D000825B80BC0000D40204A9018002006EBCB6 +:1021E0000000E80204A10180829B84BC0000E80298 +:1021F00004010080124080BC14007D050000001C1A +:10220000080036920000E8029FA0017829216EBCE8 +:102210000000E8020201008012A097BC0000CC027E +:1022200000000080020000900000E3020400008033 +:10223000028082BC0000DC0202000080A26080BC40 +:1022400006007D052C01001C080036B200C0E0022B +:1022500004010080A28D2FB006007D050000001C47 +:10226000080036920000E00204000080A26080BCFA +:102270000000DF020603018012C06EBC09007D056C +:102280000000001C080036920A007D050000001CBA +:10229000080036920000E2020603018012C06EBC04 +:1022A00007007D050000001C0800369208007D052F +:1022B0000000001C0800369202007D053801001C59 +:1022C000080036B20000E602020C0280A25B80BC6D +:1022D0001F007D050000001C080036921E007D05D1 +:1022E0000000001C080036920000EB0200000028ED +:1022F000094000920000EB020000002809800092D3 +:102300000000EB020000002809C000920000EB0270 +:1023100000000028090001920E00510F0000001C6F +:10232000080036F200007D050000008002000090E9 +:10233000100036102A0000CC022015B800000C0E48 +:102340000000003C030038F21D00F102800100781B +:1023500009E000B81D007D050000001C0800369251 +:1023600015007D050000001C0800369200000000EA +:102370000000001CA805283008000000000000F83C +:102380008340013900003E0380018080320B6AB631 +:1023900000000C0E00000038030038F27E0500003B +:1023A0000000008882CD813A0000F9021D41025CE4 +:1023B000F80168B441003103000000F8A28D2F91AC +:1023C00010000000D02C0200A9DB85390000960225 +:1023D0001201005402A438B20000FA02000000808A +:1023E000020000900000000304B0008002006EBCF8 +:1023F0000000000380B9008082806EB600002510C6 +:102400000078016008006EF230007C05D700001CE7 +:10241000080036920000020380010080D2812FB6AE +:1024200031007C05D700001C080036920000040330 +:102430008001008042812FB635007C05D700001C4A +:10244000080036920000110304A8010809006EB2CA +:102450000000000000200208899B903E0000000060 +:1024600000A00108899B903A000011039F88010891 +:10247000899B90BC000000000034020009C06E3D42 +:1024800000000000000C020409A46E3700000D03D8 +:102490000200008012A490BC0000000000000008B0 +:1024A000198090370000110302010280829B90BCCA +:1024B00031007C05D700001C080036920000110393 +:1024C00004B0008002006EBC001211030401008001 +:1024D000A28D2FB032007C05D700001C0800369278 +:1024E00000003103000000F872812F950000000009 +:1024F000000000F842802F3408C050021201004052 +:10250000A2CD39B200001303000000800200009049 +:1025100008000000000000F89340013900003E036D +:1025200080018080320B6AB60000000000000014B9 +:102530000840903200000C0E00000038030038F212 +:102540007E0500000000008882CD813A080000006E +:10255000000000F89340013900003E0380018080B4 +:10256000320B6AB600000C0E00000038030038F28F +:1025700000001F030420018052206EBC26007D0550 +:102580000000001C0800369225007D050000001C9C +:102590000800369200002503040100D81E80EDBC1F +:1025A00000002103B70000D80EC0EDB200002403E4 +:1025B00004010080423BEEBC00000000000000E08F +:1025C0001E00EE3A00000000A70000D00E00EE3220 +:1025D00000000000007486CC02806C320000000015 +:1025E000000000000940E7320000290380018080DC +:1025F000320B6AB6360028031200002C82CD2EB2B0 +:1026000000002B030401008042C52CBC00002C03F9 +:10261000000000CC0200009200000000000000CC8E +:1026200012C02C3A0000270304010000190090BCDE +:1026300000000000007486C806C02C3208003E036B +:10264000000000F8C34001990000FA0D0000002CC2 +:10265000090000F200003203000000800200009038 +:102660000000FA0D0000002CF90100F400003B030B +:1026700004000028098080B200000000000000D89B +:10268000020000320000F10E00000008080000D235 +:1026900000003B0304000080028092BC180036005A +:1026A000000000F8730A03F900003E038001008077 +:1026B000A2802FB600003E031201000009C021B223 +:1026C00018000000000000F8730A03393E033600CA +:1026D000000000C00200369200003E03800100802E +:1026E000A2802FB600003E031201000009C021B2F3 +:1026F00018003600000000F8730A03F9000000001B +:10270000000000F80200003218003600000000F857 +:10271000738A029910000000000000E403003632C2 +:1027200002000001000000E003003732000000005A +:10273000000000E40300363204000001000000E065 +:1027400003003732AA040000000000E40300363220 +:1027500009000001000000E0030037320000000023 +:10276000000000CC0F00003200070000000000E471 +:102770000300363206000001000000E0030037329B +:1027800020000000000000E40300363208000001D1 +:10279000000000E00300373200010000000000E408 +:1027A0000300363205000001000000E0030037326C +:1027B00030000000000000E4030036320700000192 +:1027C000000000E00300373200A00000000000E439 +:1027D0000300363208000008000000E00300373232 +:1027E00000000000000000A0020000320000000015 +:1027F000000000000B000032000052038B0100A01B +:1028000012002ABA00000000000000A802000032F6 +:1028100000000000000000E0070000320000550347 +:102820000601008002802ABC000000000000009C1D +:102830000200003200000000000000D4020000325C +:1028400000000000000000CC020000320000000088 +:10285000000000D80200003200000000000000D09C +:102860000200003200000000000000DC0200003224 +:1028700000000000000000F802000032000000002C +:10288000000000C80200003200000000000000C488 +:1028900002000032000058038501009C12C029BAD2 +:1028A00000000000000000E4030036320B000004CA +:1028B000000000E00300373280000000000000E468 +:1028C0000300363213000004000000E0030037323A +:1028D00000200000000000E4030036320C00000479 +:1028E000000000E00300373200000000000000E4B8 +:1028F000030006320F000004000000E0030037323E +:1029000000440000000000E4030036320D00000423 +:10291000000000E00300373200040000000000E483 +:102920000300363214000004000000E003003732D8 +:102930009F000000000000E4030036321500000490 +:10294000000000E00300373200000000000000E457 +:102950000300363218000004000000E003003732A4 +:1029600060000000000000E4030036321D00000497 +:10297000000000E00300373200000000000000E427 +:10298000030004321E000004000000E003003732A0 +:1029900070000000000000E4030036321F00000455 +:1029A000000000E00300373200000000000000E4F7 +:1029B0000300003220000004000000E00300373272 +:1029C000A0030000000000E40300363217000004FA +:1029D000000000E00300373240000000000000E487 +:1029E000030036321B000004000000E00300373211 +:1029F00060000000000000E4030036321C00000408 +:102A0000000000E00300373200000000000000E496 +:102A10000340003216000004000000E003003732DB +:102A200000010000000000E4030036321A00000438 +:102A3000000000E00300373220010000000000E445 +:102A40000300363219000004000000E003003732B2 +:102A500080000000000000E4030036320B0000019B +:102A6000000000E00300373200010000000000E435 +:102A7000030036320C000001000000E00300373292 +:102A8000FEFF0000000000AC020036320000000033 +:102A9000000000000900003218000000000000F8EB +:102AA0000364023900008B0385010000190090BA0D +:102AB00025260000000000E403003632010000017A +:102AC000000000E00300373200000000000000803A +:102AD0000F00003200000000000000840F000032F0 +:102AE00008000000000000F8F34001390800000071 +:102AF000000000F8E340013908000000000000F881 +:102B0000C340013908000000000000F8B34001395B +:102B100008000000000000F8A34001390800000090 +:102B2000000000F89340013908000000000000F8A0 +:102B30008340013908000000000000F873400139AB +:102B400008000000000000F86340013908000000A0 +:102B5000000000F85340013908000000000000F8B0 +:102B60004340013908000000000000F833400139FB +:102B700008000000000000F81340013900000000C8 +:102B8000000000F80380003200000000000000C8D0 +:102B90003F80FC35000000000000009C0200003275 +:102BA0000000000000000000030000326E00000082 +:102BB000000000D0020036320000000000000028B3 +:102BC000034038320000361004010080D20130B6D4 +:102BD0000000A303040100D012002DBCE00300009C +:102BE000000000E40300363203000001000000E0B2 +:102BF0000300373200000000170000D0020000324E +:102C000000000000000000ACE10000340000000003 +:102C1000000001E00600003200000000000801E4AE +:102C20000600003200000000000E01EC0600003239 +:102C300000000000001001E006000032000000006B +:102C4000000000D012002D3A6E00AB03020100809C +:102C5000820D2DBC020000000000009CAE0D02326F +:102C600000000000000000A8020000320000000088 +:102C7000008886CC0700363200000000008A86CC2F +:102C80000700003A002400000000000409803632EA +:102C90000000361012000064024090B200000000F4 +:102CA000000000042940903A0000B70312000078A9 +:102CB00009C020B2000000000000007809459030F3 +:102CC0000000B50302010080C28297BC0000000032 +:102CD000000000840200003200000000000000CC70 +:102CE000030000320000BB038E010080024028B2C6 +:102CF0000000510E000000D8020000D2150F0000A5 +:102D00000000008C0E0036325200000000000074FB +:102D10000E00363218000000000000E403003632D6 +:102D200009000002000000E003003732FECA000084 +:102D3000000000E4030036320A000002000000E058 +:102D4000030037320000C60312010000094020B220 +:102D50000000C40300000080020000900000C603D1 +:102D600012000004094020B20000C9039F01008046 +:102D7000020090B20000C80312000008094020B20F +:102D80000200C40304010078092417B806000000FB +:102D900000000078096416380000C40304010080B4 +:102DA000028197BCFE0000000000004403003632A0 +:102DB000FE00360000000048030036920000361086 +:102DC00012000000094020B20000CF0312000004EE +:102DD000094020B20000D2039F010080020090B29F +:102DE0000000D10312000008094020B200000000DA +:102DF000000000B402009032000036100000008095 +:102E000002000090000036100000008002000090D8 +:102E10000000361000000080020000900000361014 +:102E200000000080020000900000361000000080CA +:102E300002000090000036100000008002000090A8 +:102E400000003610000000800200009000003610E4 +:102E5000000000800200009000003610000000809A +:102E60000200009000003610000000800200009078 +:102E700000003610000000800200009000003610B4 +:102E8000000000800200009000003610000000806A +:102E9000020000900600EA030000000C0964169886 +:102EA00000004902000000140840909200006902EE +:102EB0000000001408409092340015030000001C2C +:102EC00008003692120015030000001C080036921C +:102ED0003A0015030000001C08003692000036106E +:102EE000000000800200009000005B02000000145F +:102EF0000840909200001D04000000800200009035 +:102F000000001A030000001408409092EB03000038 +:102F10000000008882CD903A0D000D04000000FCF6 +:102F200002E416980D001E04000000FC02E416984E +:102F30000D002704000000FC02E416980000340491 +:102F4000000000800200009000003D04000000002E +:102F50000940909D000040040000008002000090A5 +:102F600000004904000000800200009000005204AC +:102F7000000000800200009000005B0400000000E0 +:102F80000940909D00006004000000800200009055 +:102F900000006804000000000940909D00006D04DE +:102FA00000000080020000900000DC04000000002F +:102FB000090000920000DC040000000009400092BB +:102FC0001D07DE04000000A0020036920000EC04A1 +:102FD0000000008002000090000036100000008019 +:102FE0000200009000001D04000000DC0F409092E1 +:102FF0000000B00400000080020000900000B50452 +:10300000000000D4020000921000CA0400000084F6 +:103010001F64149800001D04000000EC0E40909204 +:103020000000D604000000800200009000001D0493 +:10303000000000D40E4090920000D90400000080EF +:103040000200009000006D05000000DC0E40909230 +:103050000000FB0400000080020000900800000552 +:10306000000000501F24169800000F05000000D833 +:10307000020000920D001905000000FC02E4169801 +:1030800000001A05000000D0020000920000F600C7 +:10309000000000D002000092000035100000008007 +:1030A0000200009000003610000000800200009036 +:1030B00008000000000000F8934001390000000003 +:1030C000000000780945903000003E0306010080B2 +:1030D000228097BC02001004B00000A0F20B00B9DF +:1030E00000000000A00000046B41903400003E038B +:1030F000800100800240B0B600003E030400008062 +:103100000280B0BC00000000000000D802000032C5 +:1031100000000000000000A822C02F3700000000BF +:1031200000000000670100340042000000080000B9 +:10313000878D2A3A00003610041000000700B0B254 +:1031400000000000001800000700D03200001A0440 +:1031500012000048F2C138B418000000000000F866 +:10316000730A03393E033600000000C002003692A5 +:1031700008003E03000000F893400199000021047C +:103180009F000080020090B20000000000000008D4 +:1031900009409032000000000000000409C0FD3228 +:1031A00002002104B00000A0F20B00B900000000F2 +:1031B000000000000B8090320000000000000000C2 +:1031C0000D40903200000000A00000043B40B031F0 +:1031D00000001D040400008002C02FBCF20E1D047C +:1031E0000000008C0E00369208000000000000F87D +:1031F0009340013902002804B00000A0F20B00B98E +:1032000000002B04800100801240B0B600000000D6 +:10321000000000043B40B033000000000000000448 +:10322000FD4BD03500000000000000080B0000320C +:1032300000000000A000000C1BE4B03200003E03C0 +:103240000B000080020000B0000031040400008088 +:10325000024090B21F003E03000000801140009920 +:103260000000300404000080123EF8BA00000000A4 +:10327000000000800100F83200003E0300000090D2 +:103280000140F89200003610800000800281FCB6F8 +:10329000000038049F000080020090B2000000008F +:1032A0000000000809409032000000000000000407 +:1032B00009C0FD3200000000000000E403809032ED +:1032C00009000004000000E00300373200000000A5 +:1032D000000000E4034090320A000004000000E017 +:1032E0000300373200001D04000000C80F81FC9469 +:1032F00000000000000000E47300903C1000000497 +:10330000000000E00300373200001D0400000080D0 +:1033100002000090000043049F000080020090B271 +:10332000000000000000000809409032000000008A +:103330000000000409C0FD3200000000000000E4AD +:103340000380903201000004000000E003003732E7 +:1033500000000000000000E00F809032000000003C +:10336000000000E40340903202000004000000E08E +:103370000300373200001D04000000E40F4090926B +:1033800000004C049F000080020090B2000000008A +:103390000000000809409032000000000000000416 +:1033A00009C0FD3200000000000000E403809032FC +:1033B00003000004000000E00300373200000000BA +:1033C000000000A80E80903200000000000000E421 +:1033D0000340903204000004000000E00300373294 +:1033E00000001D04000000AC0E4090920000550447 +:1033F0009F000080020090B2000000000000000862 +:1034000009409032000000000000000409C0FD32B5 +:1034100000000000000000E403809032050000047A +:10342000000000E00300373200000000000000E46C +:103430000340903206000004000000E00300373231 +:1034400000000000000000440F80903200001D04C6 +:10345000000000480F40909200005D0404010080CD +:10346000824290BC00000000000000000900003211 +:1034700000000000000000E403009032120000048D +:10348000000000E00300373200001D04000000408F +:103490001F40909C000063049F000080020090B2D7 +:1034A0000000000000000008094090320000000009 +:1034B0000000000409C0FD3200000000000000E42C +:1034C0000380903207000004000000E00300373260 +:1034D00000000000000000E40340903208000004F7 +:1034E000000000E00300373200001D0400000080EF +:1034F0000200009000006A0404010080824290BC37 +:103500000000000000000000090000320000000080 +:10351000000000E40300903211000004000000E00D +:103520000300373200001D04000000FC1F40909C87 +:10353000000070049F000080020090B200000000B4 +:103540000000000809409032000000000000000464 +:1035500009C0FD32030900000000002808003632CF +:103560000000890400000030080036D200009304F7 +:1035700000000044088000D20000790404010080AB +:10358000020084B2030E000000000028080036325A +:103590008000890400000030080036D20000930447 +:1035A0000000004408C000D200007904040100803B +:1035B000020084B200008004000000440800019270 +:1035C0008002000000000000070036328C45000039 +:1035D000000800000700363200003610041000001A +:1035E000078090B2000000000018000007409032F1 +:1035F0000000000000000048F2C1383400007E04E2 +:1036000012000080020000B018003600000000F830 +:10361000730A03F920000000000000E403003632C2 +:1036200009000002000000E0030037320000000043 +:10363000000000E4034084320A000002000000E0C1 +:10364000030037328C450000000000A8020036322B +:10365000A000000000000000090036320000000059 +:10366000000000E0070000320000860406010000B0 +:10367000190090BC00001D040000008002000090B2 +:103680008C450000000000C80200363280020000B5 +:103690000000003C0800363200000000000000344A +:1036A0000800013200008E0402000080D2E083BCDA +:1036B000000000000000003408C083320000A404B1 +:1036C00000000080020000F000000000000000A0E8 +:1036D000078083320000000000000030D820833AC9 +:1036E00000008C040401003CD8E083BC0000000012 +:1036F00000010080020000500000000000000040B7 +:1037000008000032000000000000004808000032FD +:103710008C450000000000C80200363200020000A4 +:10372000000000C8828D2C3A800000000000003CA0 +:10373000080036320000000000000078098078326E +:103740005A5A000004010080828D975C00009C049E +:1037500002010048A89E84BA000000000000004852 +:103760001880843A00009A040601003C28C083BCFB +:10377000000000000000007809858430100000007F +:1037800000000048888D84360000A10490010048A4 +:10379000E8A584BA00000000000000481880843AC0 +:1037A0000000000000000048088584300000000090 +:1037B000040100800285845C0000000000010040DC +:1037C0000840005200000000000000E403008332C3 +:1037D00001000002000000E0030037320C00AA04E0 +:1037E0000000002CD8A082F905000002000000E0D3 +:1037F00003003732000000000000008002000030AB +:10380000000000000001003808403E720000000087 +:10381000000000E403C0823202000002000000E069 +:103820000300373202000002000000E003003732DC +:103830000000000000000080020000300000AC0426 +:1038400080000080F2403EB60000000000010080D1 +:10385000020000700000B3049F000080020090B2DC +:103860000000000000000008094090320000000045 +:103870000000000409C0FD320000000000000084C8 +:103880000E80903200001D04000000880E409092CF +:1038900008000000000000F8934001390000B9045E +:1038A0009F000080020090B20000000000000008AD +:1038B00009409032000000000000000409C0FD3201 +:1038C00000000000000000200740F532000000006A +:1038D0000008002007000032000000000010002057 +:1038E00007C0F53200000000001800200740F63243 +:1038F00000000000002000200780F63200000000D9 +:103900000028002007C0F632000000000030002030 +:103910000700F73200000000003800200780FF3267 +:1039200000000000000000D802000032000000008B +:1039300000000000074009320000000000080000FD +:1039400077C0293700000000001000000780903287 +:103950000000000000180000074090320000C6047C +:1039600012000048F2C138B418003600000000F818 +:10397000730A03F90000000000000008C8010034C9 +:1039800000003203000000FC020000920000CC04A2 +:1039900080010080F24190B60000CD04000000C814 +:1039A0002F81FC9400000000000000C82F81FC352E +:1039B00000000000000000800F4590300000D0049F +:1039C00002000080027EF8BC0000000000000084BD +:1039D0000F00F83200000000000000001940F83726 +:1039E00000000000000000843F40F83700000000A5 +:1039F000000000840F64F83A00000000000000009E +:103A00001900F83700000000000000803F00F83780 +:103A100000001D04000000800F24F89A0000D80464 +:103A200080010080F24190B600001D04000000C833 +:103A30004F81FC9400001D04000000C84F81FC95DC +:103A40000000DB0404010080024090BC0000000084 +:103A50000000000409C0003200001D04000000E462 +:103A60001E40909C00000000000000A8220090373B +:103A700000001D04000086C007409092080000006E +:103A8000000000F8934001390D000000000000FC28 +:103A900002E41638000000000000000009000232B5 +:103AA0000000E604040000800200B0B20000000044 +:103AB000000000000B00003220000000000000A009 +:103AC000820D2A3A0000E10404010000190090BCB4 +:103AD0000000E804000000287901009400000000C4 +:103AE000000000C83F80FC34408000000000002837 +:103AF000098036320000F10E000000D8020000D22A +:103B000000003E0304000080028092BC1800000008 +:103B1000000000F8730A03393E033600000000C0BD +:103B200002003692EA05F20404010080824D90BC46 +:103B300000000000000000EC0F00153200FE1F0026 +:103B4000000000F00F003732F0FF0000000000E836 +:103B50000F00363298050000000000F40F003632E6 +:103B60000000F804000000C84F80FC953623361092 +:103B700004010080824D90BC00000000000000ECB9 +:103B80000F80143200F81F00000000F00F003732E1 +:103B9000C0FF0000000000E80F0036329827000048 +:103BA000000000F40F00363200000000000000C8E2 +:103BB0004F80FC3404000000000000608F4D903AFC +:103BC0000000BC0E00000080020000D000001D04B8 +:103BD00000000080020000900000FD0480010080D1 +:103BE000024090B600000000000000C86F80FC3466 +:103BF0000000FF0480010080124090B60000000029 +:103C0000000000C85F80FC3400001D04000000803C +:103C1000020000900000020504010080324090B0D4 +:103C200080011D04000000C88F8DFC910000040578 +:103C300080000080124090B600000505000000C81A +:103C40007F80FC9500000000000000C87F80FC34ED +:103C50000000070580000080024090B600000805C3 +:103C6000000000C88F80FC9500000000000000C824 +:103C70008F80FC3400000B0580000080224090B64D +:103C8000F20E00000000008C0E00363200000D0520 +:103C9000000000C81F81FC95150F00000000008C7B +:103CA0000E00363200000000000000C81F81FC3406 +:103CB000100000000000004C1F24163800001D04F6 +:103CC000000000501F00F59C000012059F000080BE +:103CD000020090B20000000000000008094090328D +:103CE000000000000000000409C0FD3200000000D8 +:103CF000000000001700F53A8C44000000080000A6 +:103D0000070036320000361004100000078090B221 +:103D10000000000000180000074090320000160567 +:103D200012000040F2C138B418003600000000F85C +:103D3000730A03F900001D040000008002000090D7 +:103D400000001D04000000EC0340909200001A05E2 +:103D5000B20000D8020000B200000000000201EC36 +:103D600016E46E3A08000000000000F893400139A4 +:103D700000004005171001F802006EB2060025058C +:103D800004010080828D2FB003000000000000F8C5 +:103D9000828D2F3200C0050E00000028098036D227 +:103DA00000000000000201EC16C06E3C00000000A4 +:103DB000001886C80600003218003600000000F81F +:103DC000730A03F900002605000000D002000092EB +:103DD00000002B050419868002806CBC00000000E6 +:103DE0000000000009006E3200000000C10800045D +:103DF00009006E3200000000C01586780FC06C32DA +:103E0000000030058001008022802FB600003005C0 +:103E1000001886C806400092000000000040000024 +:103E200009006E3200000000C248000409006E3232 +:103E300000000000C01686780FC06C32000030050C +:103E40008001008012802FB600000000001886C894 +:103E500006000032004000000000002809803632D1 +:103E6000000038050402018002C06EBC0000050E8F +:103E7000000201EC16C06EDC0000360580000080F8 +:103E800002802FB600003805810000F822802FB490 +:103E900000003805001886C806400092000038056A +:103EA000820000F812802FB400000000001886C8BD +:103EB0000600003200000000001086C80600003234 +:103EC000000000000000000007C00A3200380000B7 +:103ED0000008000007003632000036100410000011 +:103EE000070090B200000000001800000740903268 +:103EF00000003D0512000040F2C138B41800360041 +:103F0000000000F8730A03F900000000170100F830 +:103F1000A2802F3400000000001086A842806C3779 +:103F200000004A051200703802007EB20000361010 +:103F30001200703C02007EB2000036101200703099 +:103F400002007EB2000036101200703402007EB211 +:103F50000000410502010080B2822ABC000000007E +:103F6000170000D002000032060025050401008081 +:103F7000828D2FB000001F050403018002C06EBCBB +:103F800000005505000000800200009000004C0574 +:103F90000403018002C06EBC00005505001086C8F5 +:103FA00046802A9600000000001086C846802A3607 +:103FB000000050058000008012802FB603005205DB +:103FC000220000F8828D2FB200005205001886C82A +:103FD00006000092000055058000008022802FB668 +:103FE00000000000C20100F802802F3500C0050E5D +:103FF00000000028098036D200000000000201EC19 +:1040000016C06E3C18003600000000F8730A03F971 +:1040100000000000001001E006802F3200000000C8 +:10402000000000A8E100003400000000A20000FC35 +:10403000020000320000320380010080A2802FB60F +:1040400000005B05B90100D8028001B20000320314 +:10405000000000F80200009200000000000000389C +:104060001880F73A0000000000000038F8BF8330E5 +:1040700000005F0504010080F2BD83BC0000320334 +:10408000A90000F80200009200C066051801000CAB +:10409000A8CD3EB200006205840000741F40F7BA4C +:1040A00000003203A90000F80200009200000000A6 +:1040B000000000740F00003200C066051801000CFB +:1040C000A8CD3EB218003600000000F8738A03F94C +:1040D00000006305000000B0020000920000000034 +:1040E0000000007C0F8083320000000000280000E8 +:1040F000070000320000000000300000070000321E +:104100000001008000380000070037320000000086 +:10411000003C000C0780833200006B051200004851 +:1041200002C080B200003203A9000008E801009438 +:104130000000730504010080A2C0EDBC5200000025 +:10414000000000740E00363200000000000000C0C5 +:104150000E400132407E0500000000B40E003732F0 +:1041600000000000000000C40E80073264007805E3 +:10417000000000CC0E003692290000000000007400 +:104180000E00363200000000000000C00E40003279 +:10419000A08C0000000000B40E00363200000000C9 +:1041A000000000C40EC0003200000000000000CC7F +:1041B0000E80023210000000000000E4337BEC3976 +:1041C0001E000001000000E0030037320000000084 +:1041D000000000C86EC0EC3700001D04000000D8CD +:1041E0000EC0ED927E0500000000008882CD813A6D +:1041F0007E0500000000008882CD813ABD050000E8 +:104200000018018882CD6E3AC605000000180188AA +:1042100082CD6E3ACF0500000018018882CD6E3A3B +:10422000D80500000018018882CD6E3AE105000033 +:104230000018018882CD6E3AEA0500000018018856 +:1042400082CD6E3AF30500000018018882CD6E3AE7 +:10425000FC0500000018018882CD6E3A05060000BA +:104260000018018882CD6E3A0E0600000018018801 +:1042700082CD6E3A170600000018018882CD6E3A92 +:10428000200600000018018882CD6E3A2906000041 +:104290000018018882CD6E3A3206000000180188AD +:1042A00082CD6E3A3B0600000018018882CD6E3A3E +:1042B000440600000018018882CD6E3A4D060000C9 +:1042C0000018018882CD6E3A560600000018018859 +:1042D00082CD6E3A5F0600000018018882CD6E3AEA +:1042E000680600000018018882CD6E3A7106000051 +:1042F0000018018882CD6E3A7A0600000018018805 +:1043000082CD6E3A830600000018018882CD6E3A95 +:104310008C0600000018018882CD6E3A95060000D8 +:104320000018018882CD6E3A9E06000000180188B0 +:1043300082CD6E3AA70600000018018882CD6E3A41 +:10434000B00600000018018882CD6E3AB906000060 +:104350000018018882CD6E3AC2060000001801885C +:1043600082CD6E3ACB0600000018018882CD6E3AED +:10437000D40600000018018882CD6E3ADD060000E8 +:104380000018018882CD6E3AE60600000018018808 +:1043900082CD6E3AEF0600000018018882CD6E3A99 +:1043A000F80600000018018882CD6E3A010700006F +:1043B0000018018882CD6E3A0A07000000180188B3 +:1043C00082CD6E3A130700000018018882CD6E3A44 +:1043D0001C0700000018018882CD6E3A25070000F6 +:1043E0000018018882CD6E3A2E070000001801885F +:1043F00082CD6E3A0000F702000000D40200009265 +:1044000000007202000000800200009037070000E8 +:10441000001C018882CD6E3A3C070000001C018818 +:1044200082CD6E3A41070000001C018882CD6E3AB1 +:1044300046070000001C018882CD6E3A4B07000041 +:10444000001C018882CD6E3A50070000001C0188D4 +:1044500082CD6E3A55070000001C018882CD6E3A6D +:104460005A070000001C018882CD6E3A5F070000E9 +:10447000001C018882CD6E3A64070000001C018890 +:1044800082CD6E3A69070000001C018882CD6E3A29 +:104490006E070000001C018882CD6E3A7307000091 +:1044A000001C018882CD6E3A78070000001C01884C +:1044B00082CD6E3A7D070000001C018882CD6E3AE5 +:1044C00082070000001C018882CD6E3A8707000039 +:1044D000001C018882CD6E3A0000FC02000000D46E +:1044E0000200009200001203000000D402000092BB +:1044F00000003C0900000010088001920000361006 +:1045000000000080020000900000361000000080D3 +:1045100002000090000036100000008002000090B1 +:1045200000003610000000800200009000003610ED +:1045300000000080020000900000361000000080A3 +:104540000200009000003610000000800200009081 +:1045500000003610000000800200009000003610BD +:10456000000000800200009000007B0900000010A5 +:1045700008800092000036100000008002000090C9 +:10458000000036100000008002000090000036108D +:104590000000008002000090000036100000008043 +:1045A0000200009000003610000000800200009021 +:1045B000000036100000008002000090000036105D +:1045C0000000008002000090000036100000008013 +:1045D00002000090000036100000008002000090F1 +:1045E00000008809000000100880009200003610CA +:1045F00000000080020000900000361000000080E3 +:10460000020000900000CF09000000100840019255 +:1046100000003610000000800200009000003610FC +:1046200000000080020000900000361000000080B2 +:104630000200009000003610000000800200009090 +:104640000000361000000080020000900000D70932 +:104650000000001008C0009200003610000000802A +:10466000020000900000D7090000001008C000926E +:1046700000003D0C000000100840019200003610C0 +:1046800000000080020000900000D7090000001028 +:1046900008C0009200003610000000800200009068 +:1046A000000036100000008002000090000036106C +:1046B00000000080020000900000E40900000010EB +:1046C00008C0009200003610000000800200009038 +:1046D0000000E4090000001008C0009200003D0C3A +:1046E0000000001008400192000036100000008019 +:1046F000020000900000E4090000001008C00092D1 +:10470000000036100000008002000090000036100B +:1047100000000080020000900000361000000080C1 +:10472000020000900000E2090000001008C00092A2 +:104730000000361000000080020000900000E20936 +:104740000000001008C0009200003D0C00000010A6 +:104750000840019200003610000000800200009026 +:104760000000E2090000001008C0009200003610AE +:104770000000008002000090000036100000008061 +:10478000020000900000361000000080020000903F +:1047900000003610000000800200009000007A0A3D +:1047A0000000001008C000920000D40900000010B2 +:1047B000080001920000CF0900000010084001929B +:1047C000000036100000008002000090000036104B +:1047D0000000008002000090000036100000008001 +:1047E00002000090000036100000008002000090DF +:1047F000000036100000008002000090000036101B +:1048000000000080020000900000750A0000001007 +:10481000088000920000D4090000001008000192F6 +:104820000000CF090000001008400192000036107F +:1048300000000080020000900000361000000080A0 +:10484000020000900000361000000080020000907E +:1048500000003610000000800200009000003610BA +:104860000000008002000090000036100000008070 +:10487000020000900000750A00000010080001927C +:104880000000D40900000010080001920000CF09C8 +:104890000000001008400192000036100000008067 +:1048A000020000900000361000000080020000901E +:1048B000000036100000008002000090000036105A +:1048C0000000008002000090000036100000008010 +:1048D00002000090000036100000008002000090EE +:1048E0000000E40A00000010088000920000D409D3 +:1048F00000000010080001920000CF090000001025 +:104900000840019200003610000000800200009074 +:1049100000003610000000800200009000003610F9 +:1049200000000080020000900000361000000080AF +:10493000020000900000361000000080020000908D +:104940000000361000000080020000900000E40A21 +:1049500000000010080001920000D40900000010BF +:10496000080001920000CF090000001008400192E9 +:104970000000361000000080020000900000361099 +:10498000000000800200009000003610000000804F +:10499000020000900000361000000080020000902D +:1049A0000000361000000080020000900000E309C3 +:1049B0000000001008800092000036100000008007 +:1049C000020000900000E30900000010088000923F +:1049D00000003D0C0000001008400192000036105D +:1049E00000000080020000900000361000000080EF +:1049F00002000090000036100000008002000090CD +:104A00000000361000000080020000900000361008 +:104A100000000080020000900000E3090000001088 +:104A20000800019200003610000000800200009093 +:104A30000000E309000000100800019200003D0C96 +:104A400000000010084001920000361000000080B5 +:104A5000020000900000361000000080020000906C +:104A600000003610000000800200009000003610A8 +:104A7000000000800200009000003610000000805E +:104A8000020000900000361000000080020000903C +:104A900000008C0700000010080001920000361092 +:104AA000000000800200009000008C070000001051 +:104AB00008400192000036100000008002000090C3 +:104AC0000000361000000080020000900000361048 +:104AD00000000080020000900000361000000080FE +:104AE00002000090000036100000008002000090DC +:104AF00000005E0C00000010084001920000540C01 +:104B0000000000100840019200005E0C0000001040 +:104B1000084001920000CF090000001008400192F7 +:104B200000003610000000800200009000005E0CC3 +:104B300000000010084001920000361000000080C4 +:104B4000020000900000361000000080020000907B +:104B50000000810900000010084000920000810957 +:104B60000000001008800092000081090000001081 +:104B700008C00092000081090000001008000192A6 +:104B80000000860900000010084001920000810921 +:104B90000000001008800192000081090000001050 +:104BA00008C0019200003610000000800200009052 +:104BB0000000361000000080020000900000361057 +:104BC00000000080020000900000490B000000106F +:104BD000088000920000490B0000001008C00092FD +:104BE0000000490B00000010080001920000CF09EE +:104BF0000000001008400192000036100000008004 +:104C0000020000900000490B0000001008C0019253 +:104C100000003610000000800200009000003610F6 +:104C200000000080020000900000361000000080AC +:104C3000020000900000361000000080020000908A +:104C400000003610000000800200009000003610C6 +:104C500000000080020000900000680C00000010BE +:104C60000840019200003610000000800200009011 +:104C70000000361000000080020000900000361096 +:104C8000000000800200009000003610000000804C +:104C9000020000900000D80C0000001008400192B3 +:104CA0000000DB0C000000100840019200004C0CDA +:104CB00000000010084001920000DB0C0000001012 +:104CC0000840019200008C0700000010084001928B +:104CD0000000361000000080020000900000DB0C95 +:104CE000000000100840019200008D070000001035 +:104CF00008000292000036100000008002000090C0 +:104D00000000361000000080020000900000DC0C63 +:104D1000000000100840019200004C0C0000001040 +:104D2000084001920000DC0C0000001008400192D5 +:104D300000008C07000000100840019200003610AF +:104D400000000080020000900000DC0C0000001059 +:104D50000840019200003610000000800200009020 +:104D600000003610000000800200009000003610A5 +:104D700000000080020000900000E10C0000001024 +:104D8000088000920000E10C0000001008C00092B2 +:104D90000000E10C00000010080001920000CF09A3 +:104DA0000000001008400192000036100000008052 +:104DB000020000900000E10C0000001008C0019209 +:104DC0000000361000000080020000900000361045 +:104DD00000000080020000900000361000000080FB +:104DE00002000090000036100000008002000090D9 +:104DF0000000361000000080020000900000361015 +:104E000000000080020000900000361000000080CA +:104E10000200009000006A090000001008400092A3 +:104E200000003610000000800200009000003610E4 +:104E3000000000800200009000003610000000809A +:104E40000200009000003610000000800200009078 +:104E50000000F10C00000010088000920000F10C2E +:104E60000000001008C000920000F10C00000010CB +:104E7000080001920000CF090000001008400192D4 +:104E80000000361000000080020000900000F10CCD +:104E90000000001008C001920000361000000080E1 +:104EA0000200009000003610000000800200009018 +:104EB0000000361000000080020000900000050D88 +:104EC00000000010088000920000050D0000001096 +:104ED00008C000920000050D0000001008000192BB +:104EE0000000CF09000000100840019200003610B9 +:104EF00000000080020000900000050D000000107E +:104F000008C00192000036100000008002000090EE +:104F100000008C070000001008000092000036100E +:104F2000000000800200009000008C0700000010CC +:104F3000088000920000130D0000001008C00092CD +:104F400000008C07000000100800019200008C0790 +:104F500000000010084001920000361000000080A0 +:104F60000200009000003610000000800200009057 +:104F70000000361000000080020000900000361093 +:104F80000000008002000090000036100000008049 +:104F90000200009000008C070000001008800092C2 +:104FA0000000210D000000100880009200008C0716 +:104FB000000000100800019200008C0700000010A3 +:104FC00008400192000036100000008002000090AE +:104FD0000000361000000080020000900000361033 +:104FE00000000080020000900000361000000080E9 +:104FF00002000090000036100000008002000090C7 +:1050000000008C0700000010088000920000210DB5 +:10501000000000100800019200008C070000001042 +:105020000800019200008C07000000100840019267 +:1050300000003610000000800200009000003610D2 +:105040000000008002000090000036100000008088 +:105050000200009000003610000000800200009066 +:1050600000003610000000800200009000003610A2 +:10507000000000800200009000008C07000000107B +:1050800008800092000036100000008002000090AE +:1050900000008C070000001008400192000036104C +:1050A0000000008002000090000036100000008028 +:1050B0000200009000003610000000800200009006 +:1050C0000000361000000080020000900000361042 +:1050D00000000080020000900000FD0C00000010A5 +:1050E000088000920000FD0C0000001008C0009233 +:1050F0000000FD0C00000010080001920000CF0924 +:1051000000000010084001920000361000000080EE +:10511000020000900000FD0C0000001008C0019289 +:1051200000003610000000800200009000003610E1 +:105130000000008002000090000036100000008097 +:105140000200009000003610000000800200009075 +:1051500000003610000000800200009000003610B1 +:1051600000000080020000900000310D00000010DF +:10517000080002920000361000000080020000903B +:105180000000361000000080020000900000361081 +:105190000000008002000090000036100000008037 +:1051A0000200009000003610000000800200009015 +:1051B000000088090000001008C0019200003610AD +:1051C0000000008002000090000036100000008007 +:1051D000020000900000CF0900000010084001927A +:1051E0000000361000000080020000900000C1099D +:1051F0000000001008C0019200003610000000807E +:1052000002000090000036100000008002000090B4 +:1052100000003610000000800200009000008809A5 +:10522000000000100880009200003610000000808E +:105230000200009000003610000000800200009084 +:105240000000CF0900000010084001920000361055 +:1052500000000080020000900000C1090000001062 +:1052600008C001920000361000000080020000908B +:105270000000361000000080020000900000361090 +:10528000000000800200009000006F0B0000001082 +:10529000088000920000361000000080020000909C +:1052A00000006F0B000000100880009200003D0C11 +:1052B000000000100840019200003610000000803D +:1052C0000200009000006F0B0000001008800092A8 +:1052D0000000361000000080020000900000361030 +:1052E00000000080020000900000361000000080E6 +:1052F0000200009000006F0B0000001008000192F7 +:1053000000003610000000800200009000006F0BCB +:10531000000000100800019200003D0C0000001089 +:10532000084001920000361000000080020000904A +:1053300000006F0B00000010080001920000361002 +:105340000000008002000090000036100000008085 +:105350000200009000003610000000800200009063 +:1053600000006F0B000000100800019200003610D2 +:10537000000000800200009000006F0B0000001091 +:105380000800019200003D0C00000010084001924E +:1053900000003610000000800200009000006F0B3B +:1053A000000000100800019200003610000000808C +:1053B0000200009000003610000000800200009003 +:1053C00000003610000000800200009000006F0B0B +:1053D00000000010088000920000361000000080DD +:1053E0000200009000006F0B000000100880009287 +:1053F00000003D0C00000010084001920000361033 +:10540000000000800200009000006F0B0000001000 +:10541000088000920000361000000080020000901A +:1054200000003610000000800200009000003610DE +:105430000000008002000090000036100000008094 +:105440000200009000003610000000800200009072 +:1054500000006F0B0000001008C0019200003D0C1E +:10546000000000100840019200003610000000808B +:105470000200009000006F0B0000001008C00192B5 +:10548000000036100000008002000090000036107E +:105490000000008002000090000036100000008034 +:1054A000020000900000D70B00000010088000925E +:1054B000000036100000008002000090000036104E +:1054C000000000800200009000008C070000001027 +:1054D0000840019200003610000000800200009099 +:1054E0000000D70B0000001008800092000036106A +:1054F00000000080020000900000361000000080D4 +:1055000002000090000036100000008002000090B1 +:105510000000D70B00000010088000920000361039 +:1055200000000080020000900000361000000080A3 +:105530000200009000008C0700000010084001925B +:105540000000361000000080020000900000D70B21 +:105550000000001008C0019200003610000000801A +:105560000200009000003610000000800200009051 +:10557000000036100000008002000090000036108D +:105580000000008002000090000036100000008043 +:105590000200009000003610000000800200009021 +:1055A00000008C0700000010084001920000361037 +:1055B00000000080020000900000DF0B00000010DF +:1055C00008C0019200003610000000800200009028 +:1055D000000036100000008002000090000036102D +:1055E00000000080020000900000361000000080E3 +:1055F00002000090000036100000008002000090C1 +:1056000000003610000000800200009000008C07AF +:1056100000000010084001920000361000000080D9 +:10562000020000900000DF0B0000001008800092D4 +:1056300000003610000000800200009000003610CC +:105640000000008002000090000036100000008082 +:105650000200009000003610000000800200009060 +:10566000000036100000008002000090000036109C +:1056700000000080020000900000C30C0000001039 +:1056800008400192000036100000008002000090E7 +:10569000000036100000008002000090000036106C +:1056A000000000800200009000009407000000103D +:1056B00008400092000036100000008002000090B8 +:1056C000000036100000008002000090000036103C +:1056D00000000080020000900000361000000080F2 +:1056E00002000090000036100000008002000090D0 +:1056F0000000E6070000001008800092000036104D +:1057000000000080020000900000361000000080C1 +:105710000200009000009B080000001008000192A9 +:105720000000361000000080020000900000930787 +:1057300000000010080001920000A5080000001001 +:10574000080001920000A508000000100800019266 +:105750000000A508000000100800019200003610AB +:105760000000008002000090000036100000008061 +:10577000020000900000F507000000100880009271 +:105780000000361000000080020000900000930727 +:105790000000001008000192000036100000008098 +:1057A000020000900000361000000080020000900F +:1057B00000000308000000100880009200009A0812 +:1057C0000000001008800092000093070000001005 +:1057D00008000192000036100000008002000090D6 +:1057E0000000BB0800000010084000920000BB0849 +:1057F00000000010088000920000BB0800000010AC +:1058000008C00092000093070000001008000192F9 +:1058100000003610000000800200009000003610EA +:1058200000000080020000900000E008000000106E +:1058300008C00092000036100000008002000090B6 +:1058400000009307000000100800019200003610CD +:105850000000008002000090000036100000008070 +:10586000020000900000E208000000100800019211 +:105870000000E208000000100800019200009307F9 +:1058800000000010080001920000361000000080A7 +:10589000020000900000361000000080020000901E +:1058A0000000E40800000010088000920000E408F6 +:1058B0000000001008C000920000930700000010D4 +:1058C00008000192000036100000008002000090E5 +:1058D0000000930700000010084000920000B1088B +:1058E00000000010088000920000B10800000010C5 +:1058F00008C0009200009307000000100800019209 +:1059000000009307000000100800009200009307B9 +:1059100000000010084000920000F808000000108D +:10592000088000920000F8080000001008C00092F3 +:1059300000009307000000100800019200003610DC +:10594000000000800200009000003610000000807F +:105950000200009000002C09000000100880009256 +:10596000000093070000001008C000920000930799 +:1059700000000010080001920000361000000080B6 +:10598000020000900000361000000080020000902D +:1059900000000C0900000010088000920000361082 +:1059A000000000800200009000009307000000103B +:1059B00008000192000036100000008002000090F4 +:1059C0000000361000000080020000900000F40784 +:1059D00000000010088000920000361000000080D7 +:1059E00002000090000093070000001008000192E0 +:1059F0000000361000000080020000900000361009 +:105A0000000000800200009000002009000000104B +:105A100008800092000020090000001008C00092D9 +:105A200000009307000000100800019200003610EB +:105A3000000000800200009000003610000000808E +:105A4000020000900000EF080000001008800092A3 +:105A50000000EF080000001008C00092000093074B +:105A600000000010080001920000361000000080C5 +:105A7000020000900000361000000080020000903C +:105A80000000390900000010088000920000390968 +:105A90000000001008C000920000930700000010F2 +:105AA0000800019208003103001801E8762081996E +:105AB00008002F03001801E8762081990000990F53 +:105AC00000000080020000F0080091071D1901E8A5 +:105AD000762081B900003103000000F862812F9523 +:105AE000000031038000008002812FB62A003103BC +:105AF000D001002C82CD2E9208003103001C01E859 +:105B00007620819900000000000000D802000032D9 +:105B100000000000000E01EC06C06E3554000000CD +:105B2000000000000700363200000000000000BC4A +:105B3000A8002D37B44400000008000087CD8B3A40 +:105B4000000000000000007899C02C37B40000006D +:105B500000000078898D973A00003610021000008E +:105B600087BF97BA00000000001800000740FE320F +:105B700000009D0712000040F2C138B40000000090 +:105B80000090007809006E320000361004A000007A +:105B900009806EB20000A20704A5000409806EB25D +:105BA0000000000000000004090090320000A4077B +:105BB00004010004096490BC00000000000000041F +:105BC00009400032080000006E3402E816249039C3 +:105BD0000000A507B71002E0068097B20000A807F2 +:105BE00080000080F280FCB60000A907000000C819 +:105BF000FF80FC940000AA079F990080821BEEBCE6 +:105C000000000000009800E00E006E32000000006E +:105C1000A70000800200003018003600000000F8E5 +:105C2000730A03F9000000000010021C09006E3224 +:105C30004000AF070601008082CD91BC00C0B007D4 +:105C4000001802E00680369200E00000001802E032 +:105C50000680363200000000000000200980033278 +:105C60000000B30780D7018032C06EB6000000008C +:105C7000000000204900923A00000000009801183E +:105C800009006E3200000000000A022409C06E32D2 +:105C90000000000000C0012809806E320000C1072A +:105CA000800E018012C06EB602000000003C02ECC3 +:105CB0000600363200000000000000004901923A60 +:105CC0000000BD0780D6018042C06EB60082000091 +:105CD000001002E0A6CD913200A00000002C02E8E6 +:105CE000060036322800CB07003A02EC0600369256 +:105CF00000000000D301001CD9C1913400820000D3 +:105D0000001002E0A6CD913200A00000002C02E8B5 +:105D1000060036323400CB07003A02EC0600369219 +:105D200004000000003C02EC0600363228000000AF +:105D300000000000890D923A0000C70780D601805C +:105D400042C06EB600860000001002E0A6CD91327F +:105D500004A00000002C02E8060036321400CB0735 +:105D6000003A02EC0600369200000000D301001C4D +:105D7000D9C1913400860000001002E0A6CD913216 +:105D800004A00000002C02E8060036322000CB07F9 +:105D9000003A02EC0600369212000000003802ECD5 +:105DA00086CD913A08000000002802E88624903948 +:105DB00000000000002002E09624143700000000DC +:105DC000004001E0068091320000D107040100800C +:105DD000028092BC0000000000C001E0060000321A +:105DE00000000000003000E006000032000000006B +:105DF00000B000E0060000322000000000000000BB +:105E0000070036320000000000000078A9002D379E +:105E10000045000000080000878D973A0000000050 +:105E20000000007899C02C370001000000000078C5 +:105E3000898D973A000036100210000087BF97BA8C +:105E400000000000001800000740FE320000DA07E2 +:105E500012000048F2C138B40000DE0780D7012CE0 +:105E600009C06EB200000000DAD701EC06C06E3542 +:105E700000000000005A01EC0640ED320000000076 +:105E8000005C01E806808B320000E10780010080A1 +:105E900062C092B600000000000000F882812F343A +:105EA00018003600000000F8730A03F90000000033 +:105EB0000004013808C06E3200000000006201ECEE +:105EC00006808332010093071201002C82CD2EB28E +:105ED0000000E407000000800200009000000000C5 +:105EE000005401FC02C06E3200000000000000D827 +:105EF0000280013200C0EC071801000CA8CD3EB2B0 +:105F00002080000000000008088036322D002F039A +:105F10001201002C82CD2EB20000EA0700000080A2 +:105F200002000090000000000062013808C06E32DC +:105F300000080080000000280900373200604B0F85 +:105F400000000008088036F200009307040601EC08 +:105F500016C06EBC000093078000008072812FB6CF +:105F600000000000000000F872812F343D0093070C +:105F70001201002C82CD2EB20000F207000000803A +:105F8000020000900000F507000000F8B2812F9495 +:105F90000000CF0F00A0001808006EF200002510CE +:105FA0000078016008006EF20000F907120100C8D5 +:105FB000020020B20000FC070000008002000090F8 +:105FC000000006081201005C088020B20000FC07F7 +:105FD0001201006002802CB20000FA07000000806D +:105FE000020000900000FE0704000080024080BC18 +:105FF00000000000000000F81F80FF3A00000008C9 +:1060000080010080A2802FB618003600CA0000F878 +:10601000730A03F9000093078000008072812FB695 +:106020003D0001081200002C82CD2EB20000930723 +:10603000000000F872812F940000FC07120000C8D5 +:10604000020020B20000FA071200005C088020B2B3 +:106050000000361004A0001808006EB20000000016 +:106060000000007879613832000007081218024CED +:10607000E2256EB2080000000010020078E16E39DF +:106080000000000000180020070000320700000098 +:106090000000003878CAE939000036100400003CDE +:1060A000084080B2000036100490006C08006EB208 +:1060B000000000000098004C08006E320000000054 +:1060C000510000D802000032000000004D00000026 +:1060D00067E0833E000000000008000007008032F7 +:1060E000000000000010000007C086320000000021 +:1060F0000018000007C084320000000000000018F3 +:10610000D8A0813C0000680804B000E0D6206EBC36 +:10611000000038080400003CD8E083BC00001E08E2 +:106120008000008092802FB6000019081201000044 +:1061300009C021B218003600000000F8730A03F904 +:106140001D0000000000007809A4173800001D0899 +:1061500004010080128097BC00001808670000F856 +:10616000A2802FB5000019080000000009C021928C +:1061700000000000C90100D802408432000021085C +:106180000400008072802DBC00001F081200004433 +:10619000E2E038B200002C08510000D812802D9A9D +:1061A0000000000000000078F9818334000022081C +:1061B00012000044E2E538B20000260880000080AA +:1061C00082802FB60000550F00A0015008006EF22B +:1061D0000000000000F801E00600853200002808F9 +:1061E000120100E802C021B218003600000000F8D9 +:1061F000730A03F900002B080401008002802DBC03 +:1062000000002708670000F8A2802FB500003610B4 +:10621000120000E802C021B200000000510000D8C6 +:1062200002000032000030082A010000D82080BAA5 +:10623000000030081201000009C021B21800360029 +:10624000000000F8730A03F900000000000000D805 +:106250000240843200000000CAE0006C08006E3288 +:106260000000000000E8004C08006E32000036100C +:1062700004F0001808006EB20000000000000038B2 +:106280001881833500000F0804B00080829B81BC18 +:1062900000000000CA0100F842802F3508A00F0856 +:1062A00012010040A2CD39B2000036080000008083 +:1062B0000200009000004008293402B808806EB245 +:1062C00000003B081201000009C021B2180036008E +:1062D000000000F8730A03F91D00000000000078B8 +:1062E00009A4173800003F0804010080128097BC01 +:1062F00000003A08670000F8A2802FB500003B08B4 +:106300000000000009C0219200000000C90100D86F +:10631000024084320000000000000078F9818334DC +:106320000000410812000044E2E538B200004708CE +:106330002800006CD8E086BA0000540F00A001507D +:1063400008006EF2000047081DF801E0060085B263 +:10635000000047088000008002812FB62A0000005C +:10636000D001002C82CD2E3200004A0804A000E0AB +:10637000068081B200003610049000E006C086B2AC +:1063800000005808009800E006C0849200004F0802 +:1063900080010080A2802FB600004D08120100008D +:1063A00009C021B218003600000000F8730A03F992 +:1063B0001D004F080401008002A417B800004C081B +:1063C000000000F8E2802F940000361004E0006C1A +:1063D00008006EB200000000CAE8004C08006E32EF +:1063E0000000361004F0001808006EB200005508D6 +:1063F00004B00080829B81BC00000000CA0100F84C +:1064000042802F3508A0540812000040A2CD39B2B6 +:106410000000000000A000E00680813200000000C3 +:10642000009800E006C0843200003610049000E0BE +:1064300006C086B200005D082A5D01E806808BB2C6 +:1064400000005B081201000009C021B218003600EC +:10645000000000F8730A03F91D005D0804010080C4 +:1064600002A417B800005A08000000F8E2802F9438 +:1064700010246008370000F8A28D2FB13D005E089F +:106480001200002C82CD2EB200000000000000F8A7 +:1064900072812F3408000000CA1C01E8762081397F +:1064A0000000FA0D0000002CF90100F4000065085E +:1064B00080000080E2802FB6000065081201000015 +:1064C00009C021B218003600000000F8730A03F971 +:1064D000100000000018008067A1733930003203FB +:1064E0001201005CA28D2CB200003610000000806A +:1064F0000200009000006B088000008092802FB6A0 +:1065000018003600000000F8730A03F900000000CC +:10651000C90100D802408432000036102A000078F9 +:10652000F98183B400006C0812000044E2E538B23F +:106530000000DC0E00000030030038F2000071089B +:106540001D000038188183B50000710880000080AC +:1065500002812FB62A000000D001002C82CD2E32FD +:1065600000007408040601EC16C06EBC00000000B8 +:10657000CA0100F842802F3408C07308120000409E +:10658000A2CD39B2000077088000008082802FB64B +:106590000000550F00A0015008006EF2000000003E +:1065A00000F801E0060085320000790812010000C1 +:1065B00009C021B218003600000000F8730A03F980 +:1065C000000095082A3502B808806EB200007C08E9 +:1065D0001201000009C021B218003600000000F8C6 +:1065E000730A03F900000000000000F8A2802F35B4 +:1065F00000008E0804000080026180BC0000870853 +:1066000080B8000009C06EB240008208040000801B +:10661000820D90BC0000820802B00080821B84BC06 +:1066200000008708000000F8B2812F9400000000ED +:1066300000D601EC56C06E3400000000000000607F +:106640001800863A0000000000000080B70178348E +:1066500000000000007801E0060086324000950846 +:1066600004000080820D90BC0000361004A00018C9 +:1066700008006EB20000CF0F00000000D82080FAA2 +:10668000000036100600003C182084BC00003610C4 +:1066900004B0003C88DB83BE0000000000000080E6 +:1066A000F720783A00000000587801E0F620863A9A +:1066B00000000C0800000004F860809A00009108B7 +:1066C00080B9000009C06EB22F0095081201002C9D +:1066D00082CD2EB200008F080000008002000090E2 +:1066E0004000930804010080820D90BC380094089B +:1066F00000000078090036923900000000000078A0 +:1067000009003632000094081200002CE2E52EB297 +:10671000100000000018008067A17339000000001D +:10672000005C01E806808B3210240000000000F8B5 +:10673000A28D2F31300093071201005CA28D2CB284 +:1067400000003610000000800200009000000308E6 +:10675000000000F8C2812F9500000000005401FCE9 +:1067600002C06E3200000000000000D8028001323A +:1067700000C0A1081801000CA8CD3EB22080000086 +:1067800000000008088036322D002F031201002C73 +:1067900082CD2EB200009F08000000800200009011 +:1067A000000000000062013808C06E32000800805E +:1067B000000000280900373200604B0F000000087D +:1067C000088036F20000AF08000000800200009050 +:1067D0000000A70880000080C2812FB60000AA0830 +:1067E00000D001E80600009200000000000000F860 +:1067F000C2812F350000AA0804D1018002806EBC3E +:106800000000000000D601EC26C06E340000AC0889 +:106810008000008092812FB60000AF0800C801E818 +:106820000600009200000000000000F892812F3561 +:106830000000AF0804C9018002806EBC00000000A7 +:1068400000D601EC16C06E34110093071201002C23 +:1068500082CD2EB20000AF08000000800200009040 +:10686000000093079A0100F842812FB50000B80894 +:10687000120100C8020020B200000000005C01EC20 +:106880000640003200009307370000F842812FB421 +:1068900000000000000000F872812F343D009307D3 +:1068A0001201002C82CD2EB20000B608000000803C +:1068B000020000900000C3081201005C088020B2B2 +:1068C0000000B3081201006002802CB200003610F4 +:1068D00000000080020000900000C008120100C803 +:1068E000020020B200009307370000F8D2812FB4D5 +:1068F00000000000000000F872812F343D00930773 +:106900001201002C82CD2EB20000BE0800000080D3 +:10691000020000900000C3081201005C088020B251 +:106920000000BC081201006002802CB2000036108A +:1069300000000080020000900000000000000078CD +:10694000796138320000C4081218024CE2256EB298 +:1069500000000000003402B808806E320000000021 +:1069600000A0015008006E320000000000780160B5 +:1069700008006E320000CA089D11023409006EB290 +:106980000000000000F0018808006E3200006C0F6B +:1069900000A8010809006EF200000000D4F801E030 +:1069A0000600853200000000DA5C01E806808B32C8 +:1069B0000000DC0EDD000030030038F20000D008DB +:1069C0002329020409806EB23E00CF081200002C79 +:1069D00082CD2EB20800D3081D1C01E8762081B9B3 +:1069E0000000D3088000008002812FB62A0000003A +:1069F000D001002C82CD2E320000FA0D0000002CB8 +:106A0000F90100F40000D7089D010080074093B20F +:106A10000000000000300080078088320000000085 +:106A2000003800800700EE320000000000080080FF +:106A300007C085320000000000100080074090323F +:106A40001000000000180080878D853700000000CE +:106A5000002000800700863200000000002800802F +:106A6000070085320000DE081201000009C021B2D3 +:106A700018003600000000F8730A03F930003203F2 +:106A80001201005CA28D2CB20000361000000080C4 +:106A9000020000900000000000CC017809806E32F6 +:106AA00000009307DCD101E806809792130093075A +:106AB0001201002C82CD2EB20000E20800000080FE +:106AC000020000900000BA0D00000018094081F299 +:106AD0000000A30D00A8012009006EF2000093073A +:106AE00080010080F2802FB60000EC08120100C87F +:106AF000020020B2000093078000008072812FB650 +:106B000000000000000000F872812F343D00930760 +:106B10001201002C82CD2EB20000EA080000008095 +:106B2000020000900000C3081201005C088020B23F +:106B30000000E8081201006002802CB2000036104C +:106B4000000000800200009000009307350100F86B +:106B500012812FB500000000000000D80280013231 +:106B600000000000005401FC02C06E3200C0F608B4 +:106B70001801000CA8CD3EB220800000D101000811 +:106B8000088036323B0031031201002C82CD2EB238 +:106B90000000F40800000080020000900000440F94 +:106BA0000098012809006EF20000930700000080A1 +:106BB000020000900000FE0880010080A2812FB634 +:106BC0000000FE088000008042812FB60000FE0811 +:106BD000085B01EC06FB6EBC00000000005A01ECF3 +:106BE000060000320000FE08370000F842812FB492 +:106BF0003D000000D701002C82CD2E320000040998 +:106C00008001008092812FB600000A0908C901E8BE +:106C100006BB6EBC0000000000C801E806000032A0 +:106C2000330001091200002C82CD2EB20000510F5A +:106C300000000028098001F2000093070000008096 +:106C40000200009000000A0980010080C2812FB676 +:106C500000000A0908D101E806BB6EBC0000000074 +:106C600000D001E806000032330007091200002CB2 +:106C700082CD2EB20000510F0000002809C001F2A1 +:106C800000009307000000800200009000009307BE +:106C900080010080F2812FB6180093070000002CBD +:106CA00082CD2E9200000F09120000C8020020B20F +:106CB000000012091201005C088020B200003610AA +:106CC0001200006002802CB200000000000000F8FA +:106CD0001F80FF3A000031031201002C72E02EB237 +:106CE0000000100900000080020000900000000079 +:106CF0000000007879613832000013091218024C44 +:106D0000E2256EB200000000003402B808806E3246 +:106D100000000000D4A0015008006E320000000006 +:106D2000DB79016008006E320000550FDD000004C1 +:106D3000080000F21000000000180080878D8537E1 +:106D40000000000000F801E00600853200001C0988 +:106D50001201000009C021B218003600000000F83E +:106D6000730A03F9300036101200005CA28D2CB2B9 +:106D700000003610040701EC16C06EBC00000000D5 +:106D800000B000E00600003200009307DA5C01E882 +:106D900006808B92000093079F41018052206EBCB9 +:106DA00000002B099F98018052206EBC000000005B +:106DB000000000D80280013200000000005401FCF5 +:106DC00002C06E3200C029091801000CA8CD3EB2E5 +:106DD0002080930731000008088036B200000000D0 +:106DE000000000F812812F343B0093071201002CA1 +:106DF00082CD2EB200002709000000800200009022 +:106E00000000440F0098012809006EF2000093076B +:106E1000000000800200009000009307D54101E0CF +:106E2000064081920000930704B0008002006EBC0F +:106E3000000000000090010008006E3200002510E4 +:106E40000078016008006EF20000930700000080E7 +:106E50000200009000000000000C027809806E32F1 +:106E60000000330904D4018012C06EBC0000000091 +:106E7000000000781980973700000000009001E0C2 +:106E8000E6256E3A0000251000000080020000F0A8 +:106E90000000370900000080020000900000930706 +:106EA000009001E00600809200000000009001E0E8 +:106EB00006008032000003080000008002000090FD +:106EC0000000A30D00A8012009006EF20000E708F1 +:106ED00080000080F2802FB6000093070000008041 +:106EE0000200009000000000000000D80280013283 +:106EF000000000000000007809006E320200410925 +:106F000004B9008082CD6EBC00004309800000807F +:106F10007280FCB600004509000000FC02000092EF +:106F200000004309800000808280FCB60000450913 +:106F3000000000FC0200009200000000000000A819 +:106F400042BD973000000000541889FCF2C07C302C +:106F500000C04B091801000CA8CD3EB20000000093 +:106F6000000E01EC0600003400000000005401ECAB +:106F700006C02F3220800000000000080880363252 +:106F8000000031031201002C82CD2EB2000049090D +:106F90000000008002000090000000000062013844 +:106FA00008C06E3200080080000000280900373257 +:106FB00000004B0F00000008E80100F4000036104C +:106FC000040701EC16C06EBC00000000000000A821 +:106FD000A2002D370A0000000000007809003632B8 +:106FE00000000000001889E007000032000051098D +:106FF00004010078198097BC02005C0904B9008084 +:1070000082CD6EBC00000048D6010078C9CD2C327C +:1070100000005509B6000080020000B000005609CB +:1070200012000064028097B2000057091208006441 +:1070300002006EB2000058091218006402006EB21D +:10704000000059091210006402006EB20000000036 +:10705000A65401EC06C02F3200008C07000E01EC94 +:10706000060000940020004CD6010078C9CD2C32D7 +:1070700000005D09B6000080020000B000005E095B +:1070800012000064028097B200005F0912080064D9 +:1070900002006EB2000060091230006402006EB29D +:1070A000000061091238006402006EB2000062093B +:1070B0001240006402006EB20000630912480064CE +:1070C00002006EB2000064091210006402006EB289 +:1070D000000065091218006402006EB20000660923 +:1070E0001220006402006EB20000670912280064DA +:1070F00002006EB200000000A65401EC06C02F3260 +:1071000003008C07000E01EC060036920000000020 +:10711000000000FC0200013200006D0900000014B4 +:1071200008803D9200000000000000FC02000132D7 +:1071300000007009040000DC53603DB3180000003B +:10714000000000F8738A03396C093600000000C0A3 +:107150000200369200000000005401FC02C06E32B2 +:1071600000000000000000D80280013200C0760953 +:107170001801000CA8CD3EB22080000000000008DD +:107180000880363215002F031201002C82CD2EB25A +:107190000000740900000080020000900000000060 +:1071A000002800000700003200000000003000004E +:1071B00007C02C3200100082003800000700373270 +:1071C000000079091200004802C080B200008C075C +:1071D000CA010008E80100942D007B091200002C70 +:1071E00082CD2EB200007E091D010080020000B099 +:1071F00000008C07000000F862812F95000000005D +:10720000000000F802812F342A008C071201002CA4 +:1072100082CD2EB200007F090000008002000090A5 +:1072200000003F0F0000002C09C085D20000DC0EDA +:1072300000000030030038F200003103230100F8A1 +:1072400022812FB43E0031031201002C82CD2EB2D8 +:1072500000008409000000800200009000003F0F41 +:107260000000002C09C085D200003103000000F8A6 +:1072700022812F9400008D09380100D8028001B2CC +:1072800000008B091E000080020000B000008D0984 +:107290001A010080020000B000008C0F000000689E +:1072A0001F80F6FA00003103000000800200009009 +:1072B0000000910912010060084023B20082000022 +:1072C000000000080880363200008C0F00000064C7 +:1072D0001F40F6FA00003103000000800200009019 +:1072E0000000361012000024080023B200003610FF +:1072F0001200002008C023B200003610120000184F +:10730000088023B200C09C091801000CA8CD3EB231 +:107310000000940912000038028081B2000036108B +:107320001200003C020082B2000036101200003051 +:10733000024082B20000361012000034020086B211 +:1073400020800000000000080880363200008C0F0A +:107350000000005C1FC0F5FA00003103000000804F +:107360000200009000000000450000D8020000323A +:107370000000000000000000074080320000000014 +:1073800000100000074082320000000000180000DA +:10739000070086320000A00912000050F2C138B484 +:1073A0000000640D003001E016206EFA0000A5090F +:1073B0003801002CF8010BB40000A509020D028071 +:1073C000A25B80BC000000000000002CC8C1823419 +:1073D0000000A7098000008042812FB60000940DB4 +:1073E00000000080020000F00000AD0D00A801E0E8 +:1073F00016206EFC0000AC09270100D8028001B203 +:1074000000000000C700002CE8C08234000000002B +:1074100000000008D801003400000000D54001E061 +:10742000060087320800990F001801E8762081F9DC +:107430000000DC0E00000030030038F20000B0094C +:1074400023190000078081B23E00AF091200002C12 +:1074500082CD2EB20000B2091D210000070082B2C9 +:107460000000B409000000F862812F950000B40903 +:107470008000008002812FB62A000000D001002C7D +:1074800082CD2E320000FA0D0000002CF90100F42C +:107490001000B8092C30000017E02CB90000BA0920 +:1074A0008E39000007C082B20000BA09000800004F +:1074B000070087920000BA098E390000B7C182B474 +:1074C0000000000000080000070087320000BC092F +:1074D000120100E802C021B218003600000000F8D6 +:1074E000730A03F90000BA099F010014184081BC17 +:1074F0000000BF090400008002C085BC00003610F7 +:107500001200006802C585B00000BF0912000048E3 +:1075100002C080B200003203CA010008E8818094F2 +:107520000000C3091E000080020000B00000C50971 +:107530001A010080020000B000008C0F00000068FB +:107540001F80F6FA00003103000000800200009066 +:10755000000036109FA801E016206EBC0000640DEC +:1075600000000014080000F20000C909800000803B +:1075700042812FB60000940D00000080020000F050 +:107580000000AD0D00000080020000F000008E073A +:1075900004000080024081BC0000CD09120100E817 +:1075A00002C021B218003600000000F8730A03F987 +:1075B00000008E071201006802C585B00000361079 +:1075C000000000800200009000008C078000008016 +:1075D000F2C185B60000D3091C41028006C085B205 +:1075E000000000000000006802C5853000000000B7 +:1075F000000000701F00F73A00008C07000000F840 +:1076000022812F9400008C0780000080F2C185B693 +:1076100000003F0F0000002C09C085D2000031039C +:10762000D20100941E40E99A0000C40F0020001807 +:1076300008006EF20000DB091F000080020000B0AD +:107640000000D8099E400278094068B20000361058 +:1076500000000080020000900000DF09800100802F +:1076600082812FB600008E072A3101E0060000B2A9 +:1076700018000000CA0000F8730A03398E073600AC +:10768000000000C00200369200008E0780010080DA +:10769000A2802FB618000000CA0000F8730A033950 +:1076A0008E073600000000C0020036920D00E5098A +:1076B00000000058080036920000E509000000585C +:1076C000080000921B00000000000058080036323D +:1076D0000000C40F0020001808006EF20000000037 +:1076E0000030002808006E3200000000545401FCF5 +:1076F00002C06E320000300A380000A4088082B256 +:107700000000300A0428010408006EB200003610A0 +:107710009F500104A85B80BC00000000005001E8FD +:10772000060000320000110A0801007819A082BC8E +:1077300000000000002801E0A660803C0000F00985 +:107740002A010014080000B200000000CA00001462 +:107750001840813A0000A30D00A80120A9206EFA6C +:1077600000000000002001E0A6206E3C00000000A8 +:10777000003000E0060000320000000000A801E038 +:107780000600923200000000000000D802800132A2 +:1077900000C0030A1801000CA8CD3EB20000FA098F +:1077A00004000080024081BC0000000000000014C2 +:1077B0000800003218000000000000F8730A0339C6 +:1077C000F4093600000000C002003692208000005C +:1077D00000000028098036320000F10E000000D8B9 +:1077E000020000D20000FE0904000080028092BC6A +:1077F00018003600000000F8730A03F900000000CA +:10780000000000D80280013200C0030A1801000CF9 +:10781000A8CD3EB218000000000000F8738A0339BA +:10782000FE090000000000C00200363200003600F1 +:10783000000000800200009000000000DE00000850 +:10784000E801003400000000DF00013808C06E329B +:1078500000000000001000000700003200000000DF +:107860000018000007808232000000000030000095 +:1078700007C02C320020008000380000070037329B +:1078800000000000CA3D000C0780833200000000A9 +:10789000000000141840813A00000F0A040201ECB5 +:1078A00016C06EBC00000000C00100141840813AF0 +:1078B00000000000000000F892802F3400C00E0A83 +:1078C00012000040A28D39B20000690A120100487E +:1078D00002C080B200000F0A000000800200009089 +:1078E000000000000000002808809732000000001F +:1078F000000000A408808232000000000010006C2C +:1079000018206E3A000000000018004C08006E328B +:107910000000A30D00A8012019206EFA000000004D +:10792000002001E016206E3C0000000000A801E0ED +:107930000600923200001B0A003801E006408092E7 +:10794000000000000060006C18206E3A000000008B +:107950000068004C08006E3200001D0A9F01000400 +:10796000686080BC0000240A000000181820009CF9 +:1079700000001F0A120100E802C021B21800360000 +:10798000000000F8730A03F900000000CA70001834 +:1079900008006E320000190A02010080626080BC9B +:1079A00000000000CA0100F802802F3500A01B0A69 +:1079B00012010040A28D39B20000220A00000080AE +:1079C000020000900000280A80000080A2802FB6EC +:1079D00000002B0A04000080A2A081BC000000006F +:1079E000CA0100F802802F3500A0270A12000040CB +:1079F000A28D39B200000000000000F8A2802F35EF +:107A000000002B0A120100E802C021B21800360063 +:107A1000000000F8730A03F900000000002801E0EC +:107A20000600003200000000003000E006808232D4 +:107A300000000000002000E00680813200003610C7 +:107A4000041000E006C086B20000320A001800E010 +:107A500006C08492000036100410006C08006EB25C +:107A6000000000000018004C08006E320000E00D1D +:107A7000510000D8020000F20000350A0050013C1D +:107A8000A85B809C00008E07003001E00600009299 +:107A900000003A0A3E510100A81B80BA0000000015 +:107AA000DE0000F8F2812F3400000000005801ECE5 +:107AB00006C0EE3200003A0A80010080328087B6AC +:107AC00000000000000000F8E2802F340000730E78 +:107AD000603001E0060000F200008E070000008028 +:107AE00002000090000000000000001408000032B6 +:107AF0000000430A040201EC16C06EBC0000000046 +:107B0000C90100141840813A00000000C00101388A +:107B100008C06E3200000000DF0000A4A8608A3CAC +:107B200000C0460A12010040A28D39B20000410A8D +:107B3000000000800200009000000000003000E023 +:107B40000600003200000000DF0000A4A8608A3CAC +:107B5000000000000000013808C06E320000000084 +:107B6000DEA8012099226E3A0000490A2F2001E088 +:107B700096226EBC0000A30D00000080020000F001 +:107B800000004D0A1F5001E8060000B200004C0A38 +:107B90000400008002C083BC00004D0A005001E8D0 +:107BA000F660809C0800000000400268129AFE38CF +:107BB0000000510A2AA901E0060092B2180036001E +:107BC000CA0000F8730A03F91D00510A040000807E +:107BD00002A417B800004E0A000000141840819C4F +:107BE0000000DC0E00000030030038F20000540AF0 +:107BF0008001008032802FB63E00530A1200002C14 +:107C000082CD2EB200000000000000D802800132B8 +:107C100000C0650A1801000CA8CD3EB2208000000B +:107C2000C3000028098036320000F10E000000D8A1 +:107C3000020000D200005A0A04000080028092BCB8 +:107C400000000000000000141840813A00005F0AA4 +:107C500004000080024081BC18003600000000F8DB +:107C6000730A03F90000630A04000014184081BC81 +:107C700000005B0A1200000009C021B200005C0A8B +:107C8000000000800200009018003600000000F89C +:107C9000738A03F90000DC0E00000030030038F2A4 +:107CA0000000630A8001008032802FB63E00620A25 +:107CB0001200002C82CD2EB200000000C30000D8BC +:107CC0000280013200C05F0A1800000CA8CD3EB24D +:107CD0000020008000000028090037320000B10FAA +:107CE00000000008E80100F40000670A12000048E4 +:107CF00002C080B200000000000000141840813A69 +:107D000018003600CA0000F8730A03F90000690A77 +:107D100004010014184081BC0000990F000000808D +:107D2000020000F000006F0A8001008092802FB6F0 +:107D30002B00720A1201002C82CD2EB200006D0AB7 +:107D400000000080020000900000720A1D00008008 +:107D5000020000B00000720A8000008002812FB68D +:107D60002A000000D001002C82CD2E3200008C07AA +:107D700004000080028085BC0000AA0F0000008083 +:107D8000020000F000007D050000001C08808592C4 +:107D900000000000CE0100D80280013200C07A0A43 +:107DA0001801000CA8CD3EB22080000000000008A1 +:107DB0000880363200008C0F0000005C1FC0F5FA0E +:107DC000000031030000008002000090000000006D +:107DD000600000D80200003200007F0A3F00003C33 +:107DE000084080B200007F0A80010080E2812FB647 +:107DF00000000000DE0000F8F2812F3400000000D7 +:107E0000005801EC06C0EE32000000004D000000FA +:107E100067E0833E00000000000800000700803299 +:107E2000000000000010000007C0863200000000C3 +:107E30000018000007C084320000BE0A04000028B9 +:107E4000D8A082BC0000000000000018D8A0813C2F +:107E500000009C0A0400003CD8E083BC0000890AB2 +:107E60000400008072802DBC0000870A12000050C0 +:107E700002C038B200009A0A510000D812802D9A30 +:107E80000000890A12000050F2C138B40000950ABF +:107E9000280000D8020000B20000920A8001008091 +:107EA000F2C185B600008F0A1F400284E60100B4CB +:107EB0000000920A1D0100F822812FB40000920AEE +:107EC000000000F862812F950000910A1D010080DA +:107ED000020000B000000000000000F862812F35B1 +:107EE0000000000000400280024068320000940A56 +:107EF000343000E016206EBC0000940D00000080BD +:107F0000020000F00000AE0DDA5B01EC0640EDF27D +:107F100018003600000000F8730A03F90000990AFF +:107F20000400008072802DBC0000950A670000F8F4 +:107F3000A2802FB500003610120000E802C021B266 +:107F400000000000510000D8020000320000E80DDF +:107F500000000000D82080FA0000800A4D000000D8 +:107F600067E0839E00009C0A12000050F2C138B402 +:107F70000000A80A28000080084000B20000A50AFE +:107F800080010080F2C185B60000A20A1F40028471 +:107F9000E60100B40000A50A1D0100F822812FB4FB +:107FA0000000A50A000000F862812F950000A40AD5 +:107FB0001D010080020000B000000000000000F879 +:107FC00062812F35000000000040028002406832CC +:107FD0000000A70A343000E016206EBC0000940DAB +:107FE00000000080020000F00000AE0DDA5B01EC42 +:107FF0000640EDF20000BF0A80000080E2802FB64C +:108000000000AC0A042100E0068081B20000E80D07 +:1080100000000034080000F200000000002000E032 +:10802000068081320000B10A2A1100E0D6E086BA4B +:1080300018003600CA0000F8730A03F91D00B10ADF +:108040000401008002A417B80000AD0A9F0100805F +:10805000180088BC0000361000000080020000906C +:108060000000990F00000080020000F00000DC0E0C +:1080700000000030030038F20800B50A231901E8B7 +:10808000762081B93E00B40A1200002C82CD2EB2B7 +:108090000000B80A1D1800E006C084B20000B80A4B +:1080A0008000008002812FB62A000000D001002C41 +:1080B00082CD2E320000FA0D0000002CF90100F4F0 +:1080C0000000BC0A04000080020088BC0000BC0A5A +:1080D0001201000009C021B218003600000000F8AB +:1080E000730A03F9000032031201006802C585B06B +:1080F0000000361000000080020000900000BE0A60 +:1081000012000050F2C138B400000000C001013874 +:1081100008C06E320000C30A040201EC16C06EBC37 +:1081200000C0C10A12000040A28D39B20000C40A8A +:10813000C90100140800009200000000453000E072 +:10814000060000320000CF0A28000008E80100B451 +:108150000000CC0A80010080F2C185B60000C90A87 +:108160001F400284E60100B40000CC0A1D0100F8A3 +:1081700022812FB40000CC0A000000F862812F9504 +:108180000000CB0A1D010080020000B000000000CA +:10819000000000F862812F350000000000400280DE +:1081A000024068320000CE0A8000008042812FB673 +:1081B0000000940D00000080020000F00000AE0DF1 +:1081C000DA5B01EC0640EDF200200080DF000028C1 +:1081D000090037320000B10FDE0000D8028001F242 +:1081E0000800990F001801E8762081F90000DC0EE4 +:1081F00000000030030038F20000D50A8001008042 +:1082000032802FB63E00D40A1200002C82CD2EB24E +:108210000000D90A290801E406C02DB20000DE0AD8 +:108220001D000080020000B00000DE0A8000008017 +:1082300002812FB62A00DE0AD001002C82CD2E92B8 +:108240000000DB0A1201000009C021B2180036004C +:10825000000000F8730A03F91D00DD0A0401008024 +:1082600002A417B80000DA0A000000141840819C2C +:108270002B00DD0A1200002C82CD2EB20000FB0D77 +:108280000000002CF90100F40000E10A0401008064 +:10829000024081BC18003600000000F8730A03F9A0 +:1082A0000000E10A1200004802C080B20000320360 +:1082B0001201006802C585B00000E20A00000080DB +:1082C0000200009000000000000000D8028001328F +:1082D00000C0E90A1801000CA8CD3EB220800000C1 +:1082E000000000080880363200008C0F0000005C9F +:1082F0001FC0F5FA0000310300000080020000906A +:1083000000C00000000000F8A28D2F310000000026 +:10831000000000D802000032000000000000000051 +:108320000780813200000000000800000700803252 +:10833000000000000010000007C0863200000000AE +:108340000018000007C084320000EF0A120000503D +:10835000F2C138B40000F50A8000008082802FB698 +:108360000000000000000068A860803C00000000E1 +:108370000000003C084080320000AD0D0000000409 +:10838000088082F20000F60A1201000009C021B242 +:1083900018003600000000F8730A03F91D00F80AFF +:1083A0000400008002A417B80000F50A000000F8DD +:1083B000A2802F9500000000000000006820803A95 +:1083C0000000FC0A0400002868A082BC0000E80D40 +:1083D00000000080020000F00000EB0A000000D85E +:1083E0000200009200000000000000D8028001326C +:1083F0000020008000000028090037320000AD0F87 +:1084000000000008E80100F418003600CA0000F877 +:10841000730A03F90000060B040201EC16C06EBCDF +:1084200000000000C00100F892802F3400C0040B4F +:1084300012010040A28D39B20000020B0000008042 +:10844000020000902B00060B1201002C82CD2EB2F0 +:108450000000040B000000800200009000000000FB +:10846000000000D8028001320000090B12010060F8 +:10847000084023B20082120B00000008A88D8092F1 +:108480000000361012000024080023B2000036104D +:108490001200002008C023B200003610120000189D +:1084A000088023B200C0210B1801000CA8CD3EB2F9 +:1084B00000000C0B12000038028081B20000361060 +:1084C0001200003C020082B20000361012000030A0 +:1084D000024082B20000361012000034020086B260 +:1084E0002080000000000008A88D80320000190BD9 +:1084F00080010080F2C185B60000160B1F40028487 +:10850000E60100B40000190B1D0100F822812FB410 +:108510000000190B000000F862812F950000180B75 +:108520001D010080020000B000000000000000F803 +:1085300062812F3500000000004002800240683256 +:10854000000036101200006802C585B000001C0B48 +:108550003400005C1FC0F5BA0000940D00000080DC +:10856000020000F000001E0B8000008092802FB6F9 +:1085700000008E07003000E00600009200008E0729 +:10858000120100E802C021B218000000000000F84B +:10859000730A03398E073600000000C002003692CD +:1085A00000000000450000D802400032000000003A +:1085B0004100000007808632000000000008000033 +:1085C00007008032000000000010000007408232E7 +:1085D0000000000000180000070086320000260B93 +:1085E00012000050F2C138B4000000000000007812 +:1085F000388087350000000000A001E016206E3AA8 +:10860000000000000000007809C58530000000006F +:1086100000A801E016206E3C08000000D20100789E +:10862000E9E58339180036101F410284E6A197B9A5 +:108630000000300B365101E816E083BC0000300B1F +:108640001D010080020000B000000000000000F8E2 +:1086500062812F350000320B382101E0064080B2E4 +:1086600000000000003001E0064080320000000001 +:10867000000000D8028001320000350B34180000E1 +:10868000078081B20000940D00000080020000F01D +:108690001000990F0030000017E02CF90010008046 +:1086A00000380000070037320000DC0E0000003008 +:1086B000030038F200003A0B8001008032802FB6B0 +:1086C0003E00390B1200002C82CD2EB200003F0B71 +:1086D00029210000070082B200003D0B12010000BA +:1086E00009C021B218003600000000F8730A03F92F +:1086F0001D00420B0401008002A417B800003B0BD0 +:1087000000000014080000920000420B1D3000E041 +:10871000060000B20000420B8000008002812FB6EC +:108720002A000000D001002C82CD2E320000AA0FBA +:108730000000002CF90100F40000FA0D000000F820 +:10874000A2802FF40000470B04000080024081BC8F +:108750000000470B120100E802C021B218003600E9 +:10876000000000F8730A03F9000032031201004808 +:1087700002C080B20000470B0000008002000090A1 +:108780000000500B80010080F2C185B600004D0B47 +:108790001F400284E60100B40000500B1D0100F8E8 +:1087A00022812FB40000500B000000F862812F9549 +:1087B00000004F0B1D010080020000B0000000000F +:1087C000000000F862812F350000000000400280A8 +:1087D000024068320000520B04000080024086BC58 +:1087E0000000D70F0090010809006EF2000007108A +:1087F00000000080020000F00000590B330100D897 +:10880000028001B20000590B80010080B20172B6F3 +:108810000000590B9FF0018082DB87BC0000590BE0 +:108820009FF8018022216EBC0000000000E801E0FA +:108830000600EE320000000000F001E006C08732C2 +:1088400008000000001801E87620813900005F0B65 +:1088500080010080D2802FB600005F0B04B0008042 +:1088600002006EBC00000000CD0000F872812F34C1 +:108870003D005F0B1201002C82CD2EB200005D0B7B +:1088800000000080020000900000690B270901E44D +:1088900006C02DB200C0630B1801000CA8CD3EB27B +:1088A000000036101200006802C585B020808E07D7 +:1088B000000000080880369200000000004001E03F +:1088C0000640883200000000D508000007408832CA +:1088D000000000000030000007C02C320040008083 +:1088E000CA390000070037320000670B1200004849 +:1088F00002C080B20060000000000008088036322C +:1089000000006C0B1D000080020000B000006C0B2A +:108910008000008002812FB62A000000D001002CC8 +:1089200082CD2E320000FB0D0000002CF90100F476 +:10893000000032031201006802C585B00000361045 +:10894000000000800200009000000000545401FC70 +:1089500002C06E3200000000000000D80280013228 +:1089600000C0750B1801000CA8CD3EB2208000009D +:108970000000000808803632000031031201002C8C +:1089800072E02EB20000730B000000800200009025 +:108990000000C40F0020001808006EF2000036101E +:1089A0001F30002808006EB200000000000000A484 +:1089B00008808232000036100410006C08006EB28D +:1089C0000000E00D0018004C08006EF200007C0B67 +:1089D0000050013CA85B809C000036100000008025 +:1089E000020000900000000000500100A81B803A27 +:1089F00000000000510000D802000032000000001A +:108A00004D00000067E0833E000000000008000009 +:108A100007008032000000000010000007C086320E +:108A2000000000000018000007C084320000A60B00 +:108A300004000028D8A082BC00000000000000183C +:108A4000D8A0813C0000940B0400003CD8E083BC1B +:108A50000000880B0400008072802DBC0000860B93 +:108A60001200005002C038B200008E0B510000D836 +:108A700012802D9A0000880B12000050F2C138B409 +:108A800018003600000000F8730A03F900008D0B8F +:108A90000400008072802DBC0000890B670000F884 +:108AA000A2802FB500003610120000E802C021B2EB +:108AB00000000000510000D8020000320000920BBC +:108AC0002A010000D82080BA0000920B1201000099 +:108AD00009C021B218003600000000F8730A03F93B +:108AE00000000000000000D8024084320000F00DB9 +:108AF0000060006C08006EF200007F0B4D0000006B +:108B000067E0839E0000940B12000050F2C138B45D +:108B100018003600000000F8730A03F91D00990BD5 +:108B20000400008002A417B80000950B670000F84D +:108B3000A2802FB5000036101200000009C021B23B +:108B40000800361012400268129AFEB80000DC0ECF +:108B500000000030030038F2000036101F00006CE7 +:108B6000D8E086BA0000E00D510000D8020000F203 +:108B700000009F0B0000003C08408092000036106F +:108B8000000000800200009000007E0B04010080C5 +:108B9000028081BC0000A40B80010080A2802FB65F +:108BA0000000A40B1201000009C021B21800360019 +:108BB000000000F8730A03F900000000000000D86C +:108BC000024084320000F00D0060006C08006EF27C +:108BD00000007F0B4D00000067E0839E0000000056 +:108BE000C001013808C06E3200000000453000E0CE +:108BF000060000320000A80B12000050F2C138B489 +:108C00000000AD0B040201EC16C06EBC00000000B9 +:108C1000C90100141840813A00C0AD0B1201004098 +:108C2000A28D39B20000AB0B000000800200009062 +:108C300000C00000000000F8A28D2F3100000000ED +:108C400000A8012099226E3A0000B10B2F2001E00C +:108C500096226EBC0000A30D00000080020000F010 +:108C60000000B50B0400003CD8E083BC0000B40B4E +:108C70009F3101E096226EBC00000000003001E050 +:108C8000060000320000B90B005001E8F660809C3D +:108C90000800000000400268129AFE380000B80B7D +:108CA0009F3101E096226EBC00000000003001E020 +:108CB0000600003200000000005001E8060000320B +:108CC0000000000000A801E0060092321800360003 +:108CD000000000F8730A03F91D00BD0B04000080BA +:108CE00002A417B80000BA0B000000141840819CC1 +:108CF00000000000000000D8028001320020008047 +:108D000000000028090037320000B10F0000000801 +:108D1000E80100F40000C00B1200004802C080B25D +:108D20000000DC0E00000030030038F20000C40B2D +:108D300023010014184081BA3E00C30B1200002C1E +:108D400082CD2EB218003600CA0000F8730A03F96B +:108D50000000C40B04010014184081BC0000990FEE +:108D600000000080020000F00000CA0B2931010C55 +:108D700009006EB22B008C071201002C82CD2EB29E +:108D80000000C80B000000800200009000009C0D55 +:108D9000000C020009806EF20000D30B000000807E +:108DA000020000900000AA0F00000080020000F006 +:108DB000000000000000001C080090320000D20BF0 +:108DC00004000028098080B20000F10E000000D8E5 +:108DD000020000D20000D20B04000080028092BC8E +:108DE00018003600000000F8730A03F900007D0542 +:108DF000000000080800009200008C071D000080A1 +:108E0000020000B000008C078000008002812FB6B5 +:108E10002A00D50B1200002C82CD2EB200008C0748 +:108E2000000000F802812F940000BA0D0000001825 +:108E3000094081F20000A30D00A8012009006EF294 +:108E4000000000000030010C09006E3200009C0D93 +:108E5000000C020009806EF200008E070000008006 +:108E6000020000900000990F00000080020000F056 +:108E70000000AA0F00000080020000F000007D0545 +:108E80000000001C0800909200000000545401FCF7 +:108E900002C06E3210000000000000A8780B1638E7 +:108EA00008000000000000AC780B1638000000003D +:108EB000000000B0A8002D3700440000000000B002 +:108EC000880D8B3A00000000005001B408806E321B +:108ED0000000ED0B0431019008006EB202000000AA +:108EE000000000C8828D8A3700000000000000C822 +:108EF000C2A22C3A1800EB0B86410278880D78B696 +:108F00000000E60B9F0100A818808ABC9F00E60BBA +:108F1000000000A808003692000000000040020493 +:108F2000B83F78300000FB0B00000004D862809C42 +:108F300002000000000000C8828D8A370000000097 +:108F4000000000C8C2A22C3A1800F20B8641027839 +:108F5000880D78B60000ED0B9F0100A818808ABC30 +:108F60009F00ED0B000000A8080036920000F40BF3 +:108F700028400204B83F78B000000000C801000497 +:108F8000D862803C0000F80B02010090182089BCD8 +:108F900000000000000000B4080000320000ED0BEB +:108FA0009F0100A818808ABC9F00ED0B000000A85C +:108FB000080036920000FB0B04000090182089BACC +:108FC000000036109F000004486280BC000036108C +:108FD000900000B448628BBA0300361004400200CF +:108FE000081EFFB80000030C00000000D822809A81 +:108FF0000000280C04000080A2E28ABC02000000ED +:10900000000000C8828D8A3700000000000000C800 +:10901000C2A22C3A1800260C86400278880D78B639 +:109020000000361004400204B83F78B00300361048 +:1090300004400200081EFFB80000070C1201006087 +:10904000084023B200820000000000080880363289 +:10905000000031031201002C72E02EB20000050C5A +:109060000000008002000090000036101200002472 +:10907000080023B2000036101200002008C023B2FE +:109080000000361012000018088023B20000000013 +:10909000000000D80280013200C0110C1801000C41 +:1090A000A8CD3EB200000B0C12000038028081B245 +:1090B000000036101200003C020082B200003610A0 +:1090C00012000030024082B200003610120000345C +:1090D000020086B22080050C00000008088036924D +:1090E00000000000000000D8020000320000000074 +:1090F00000380200B81B803A00000000643001E034 +:1091000016206E3A00000000000000000740803288 +:10911000000000000008000007008032000000008E +:10912000001000000740823200000000001800001C +:10913000070086320000180C12000050F2C138B44B +:1091400000000000000000D8028001320000000092 +:10915000001800000780813200000000002000009D +:1091600007008232100000000030000017E02C39A8 +:109170000000000000380000F7010B340000200C54 +:1091800080010080328087B60000000000380000B7 +:10919000B70170340000000000000008E80100344E +:1091A00000002F0C020C0280A21B89BC18003600A4 +:1091B000000000F8730A03F90000DC0E0000003024 +:1091C000030038F20000240C1200004802C080B2F4 +:1091D00018003600000000F8730A03F90000FD0BC8 +:1091E0009F0100A818808ABC9F00FD0B000000A80A +:1091F0000800369200002A0C8001008032802FB6D1 +:109200003E00290C1200002C82CD2EB200002C0C46 +:109210001D010080020000B000008C07000000F873 +:1092200062812F9500008C078000008002812FB69C +:109230002A002D0C1200002C82CD2EB200008C07CB +:10924000000000F802812F940000000000380000A8 +:10925000C70170340000DC0E00000030030038F25B +:109260000800330C231901E8762081B93E00320C46 +:109270001200002C82CD2EB20000350C1D010080A2 +:10928000020000B00000380C000000F862812F9549 +:109290000000380C8000008002812FB62A00360CB6 +:1092A0001200002C82CD2EB200000000000000F859 +:1092B00002812F340000FA0D0000002CF90100F4A7 +:1092C00000003B0C120100E802C021B21800360079 +:1092D000000000F8730A03F900003B0C120000487C +:1092E00002C080B200003203000000F8A2802F9478 +:1092F00000000000000000D80280013200000000E1 +:109300000030002808006E3200000000545401FCB8 +:1093100002C06E3200C0490C1801000CA8CD3EB24C +:109320002080000000000028098036320000F10E85 +:10933000000000D8020000D20000460C04000080AB +:10934000028092BC18000000000000F8730A033984 +:10935000470C3600000000C00200369218003600AC +:10936000000000F8738A03F900000000000000D834 +:109370000280013200C0460C1800000CA8CD3EB29D +:109380000020008400000028090037320000AD0FE3 +:1093900000000008E80100F400008C0700000080D5 +:1093A0000200009000000000000000D8028001329E +:1093B00000000000545401FC02C06E3200C0520C88 +:1093C0001801000CA8CD3EB220800000000000086B +:1093D0000880363200002F031201002C72E02EB2FA +:1093E0000000500C00000080020000900000510FAF +:1093F00000000028090002F200005A0C0000005C86 +:109400000800009200000000000000D80280013235 +:1094100000000000545401FC02C06E3200C05A0C1F +:109420001801000CA8CD3EB220800000000000080A +:109430000880363200008C0F0000005C1FC0F5FA77 +:1094400000003103000000800200009000000000D6 +:109450000030002808006E32002000840000002840 +:10946000090037320000AD0F00000008E80100F4E9 +:1094700000005F0C0000008002000090000000006F +:1094800000000008080000320000650C04000080A5 +:1094900002C085B20000650C80000080F2C185B674 +:1094A0000000640C1C41028006C085B20000000070 +:1094B0000000006802C58530000000000000007058 +:1094C0001F00F73A00000000000000F822812F344E +:1094D0000000DC0C80010080A2802FB61800000084 +:1094E000000000F8730A0339DC0C3600CA0000C023 +:1094F000020036920000AD0C8001008082812FB600 +:109500000000B20C1F20010809006EB20000AD0C73 +:1095100004300108899B90BC0000710C043101806B +:1095200002006EBC0000E00D00000080020000F0B0 +:1095300000006F0C0050014808806E920000361049 +:109540000000008002000090000000000000000405 +:109550002861803C0000810C000000002821809AD6 +:109560000000E00D0030014808006EF20000740CAD +:1095700000500104A85B809C0000361000000080B1 +:10958000020000900000000000500100A81B803A7B +:1095900000007E0C0700004818A084BC08000000F2 +:1095A00000400200189AFE38000000000000006829 +:1095B000020080320000E00D00000080020000F098 +:1095C00000007B0C000000800200009000003610BC +:1095D000000000800200009000007E0C07000048A0 +:1095E00018A084BC0800000000400200189AFE3851 +:1095F0000000780C00000068020080920000810CDE +:109600000400004818A084BA000036109F0000042F +:10961000286180BC00000000000000002821803A82 +:1096200000000000005401FC02C06E3200008A0CF1 +:1096300012010060084023B200820000D601000839 +:10964000088036320300361004400200381AFFB892 +:109650000300000000000078096080391800000055 +:10966000D241028CE6A1973900000000005001E8C9 +:1096700006808432290031031201002C82CD2EB2E3 +:109680000000880C000000800200009000003610EE +:1096900012000024080023B200003610120000203F +:1096A00008C023B20000361012000018088023B250 +:1096B00000000000000000D80280013200C0950CBC +:1096C0001801000CA8CD3EB220800000D601000891 +:1096D0000880363200008F0C12000038028081B200 +:1096E000000036101200003C020082B2000036106A +:1096F00012000030024082B20000840C12010034DB +:10970000020086B2000036100000008002000090C7 +:10971000080000000040025C189AFE3800000000BB +:10972000000000480800003200000000000000D8DF +:1097300002000032000000000000000007408032FC +:109740000000000000080000070080320000000058 +:1097500000100000074082320000000000180000E6 +:109760000700863200009C0C12000050F2C138B491 +:1097700000000000D60100D8028001320000000085 +:109780000018000007808132000000000020000067 +:1097900007008232100000000030000017E02C3972 +:1097A0000000A40C80000080328087B6001000808A +:1097B00000380000070037320000A50C00000080D0 +:1097C00002000090001000880038000007003732C7 +:1097D00018003600000000F8730A03F900000000CA +:1097E0000000006802C08532000000000000000890 +:1097F000E80100340000A80C1200004802C080B24A +:1098000018003600000000F8730A03F90000E00DAC +:1098100000000080020000F00000810C00000080C9 +:10982000020000900000B20C0000008002000090D6 +:109830000000E00D00000080020000F00000B00C0D +:1098400000380200B81B809C0000B20C00000080B1 +:1098500002000090050000000000006802A0FE3831 +:109860000000AD0C00400280024068920000000041 +:10987000CA0100D8020000320000B50C04B8018013 +:1098800002006EBC0000000000B801E0861BEE3C48 +:109890004C0000000000000007003632000000000D +:1098A00000000078A9002D37B44400000008000033 +:1098B000878D973A000000000000007899C02C378F +:1098C000B400000000000078898D973A000036103F +:1098D0000210000087BF97BA0000000000180000C7 +:1098E0000740FE320000BC0C12000048F2C138B440 +:1098F0000000BD0CB6000080020000B00020BE0CCD +:1099000012000064A2CD2CB200000000A60000806E +:10991000020000300000C20C80010080A2802FB63F +:1099200018003600CA0000F8730A03F900008C071B +:10993000005401FC02C06E9200000000005401FCC3 +:1099400002C06E320000C80C12010060084023B251 +:109950000082000000000008088036322900310330 +:109960001201002C82CD2EB20000C60C0000008037 +:10997000020000900000361012000024080023B2FC +:10998000000036101200002008C023B2000036107C +:1099900012000018088023B200000000000000D868 +:1099A0000280013200C0D30C1801000CA8CD3EB2D9 +:1099B0002080000000000008088036320000CD0C36 +:1099C00012000038028081B2000036101200003C04 +:1099D000020082B20000361012000030024082B253 +:1099E0000000C60C12010034020086B200003610DE +:1099F00000000080020000900000E00D0000004820 +:109A0000080000F20800D60C0040025C189AFE988C +:109A100000003610000000800200009000000000EE +:109A200000500100A81B803A0000970C000000487D +:109A30000800009200000000005401FC02C06E32D9 +:109A40000000510F00000028098002F20000BD0C48 +:109A500000000080020000900000510F000000286C +:109A6000090002F20000DF0C9A0100F862812FB4B5 +:109A700010240000000000F8A28D2F31000000002B +:109A800000D601EC06C06E342E008C071201002CAB +:109A900082CD2EB20000DF0C00000080020000909A +:109AA0000000E80C80010080F2C185B60000E50CE2 +:109AB0001F400284E60100B40000E80C1D0100F81C +:109AC00022812FB40000E80C000000F862812F957D +:109AD0000000E70C1D010080020000B00000000043 +:109AE000000000F862812F35000000000040028075 +:109AF000024068320000EA0C04980164881B87BCAD +:109B00000000D70F0090010809006EF20000071056 +:109B100000000080020000F0000036101200006813 +:109B200002C585B000000000000000F8D2802F358B +:109B300000008E07370000F8D2812FB4000000002B +:109B4000000000F872812F343D008E071201002CB6 +:109B500082CD2EB20000EF0C0000008002000090C9 +:109B60000000F80C80010080F2C185B60000F50C01 +:109B70001F400284E60100B40000F80C1D0100F84B +:109B800022812FB40000F80C000000F862812F95AC +:109B90000000F70C1D010080020000B00000000072 +:109BA000000000F862812F350000000000400280B4 +:109BB000024068320000000000D401EC16C06E3A8A +:109BC000000036101200006802C585B000008E0744 +:109BD00004B0008002006EBC37008E071201002C1A +:109BE00082CD2EB20000FB0C00000080020000902D +:109BF0000000040D80010080F2C185B60000010D57 +:109C00001F400284E60100B40000040D1D0100F8AD +:109C100022812FB40000040D000000F862812F950E +:109C20000000030D1D010080020000B000000000D4 +:109C3000000000F862812F35000000000040028023 +:109C4000024068320000100D000000800200009009 +:109C500000000C0D80010080F2C185B60000090DE6 +:109C60001F400284E60100B400000C0D1D0100F845 +:109C700022812FB400000C0D000000F862812F95A6 +:109C800000000B0D1D010080020000B0000000006C +:109C9000000000F862812F350000000000400280C3 +:109CA000024068320000100D370000F8D2812FB456 +:109CB00000000000000000F872812F343D00100DFC +:109CC0001201002C82CD2EB200000E0D000000808B +:109CD000020000900000000000D401EC06000032F9 +:109CE00000008E071201006802C585B00000361022 +:109CF000000000800200009000008C0780010080BE +:109D0000F2812FB600008C0780000080E2812FB620 +:109D100000008C07085901EC06FB6EBC0000000037 +:109D2000000000D80280013200000000545401FC01 +:109D300002C06E3200C01D0D1801000CA8CD3EB24D +:109D400000000000005801EC06FB6E3A2080000085 +:109D5000000000080880363200002F031201002C9A +:109D600072E02EB200001B0D000000800200009087 +:109D70000000AA0F000000F8E2812FF40000200D7F +:109D80000603018012C06EBC19007D050000001C96 +:109D9000080036921A007D050000001C080036926B +:109DA00000C00000000000F8A28D2F31000000006C +:109DB000000000D802800132002000C0000000280E +:109DC00009003732000000000030002808006E3221 +:109DD00000000000453000E0060000320000AD0F3A +:109DE00000000008E80100F400002C0D040201EC62 +:109DF00016C06EBC00000000C90100141840813A72 +:109E000000000000000000F802802F3400C02C0D7C +:109E100012010040A28D39B200002A0D000000801E +:109E20000200009018003600CA0000F8730A03F917 +:109E300000002C0D9F010014184081BC00008E070B +:109E40008001008092802FB62B008E071201002C1B +:109E500082CD2EB200002F0D000000800200009085 +:109E6000000036101F0100D8028001B2000000007F +:109E7000005401FC02C06E3200C03C0D1801000C01 +:109E8000A8CD3EB2208000000000002809803632B4 +:109E90000000F10E000000D8020000D20000390DD1 +:109EA00004000080028092BC18000000000000F84E +:109EB000730A03393A0D3600000000C002003692E2 +:109EC00018003600000000F8738A03F90000000053 +:109ED000000000D80280013200C0390D1800000CCB +:109EE000A8CD3EB20000AA0F000000D8024000F248 +:109EF00000F0430D1D400200A80D68B100003610AF +:109F00001E400284060000B20000410D120000282D +:109F1000020580B008003D0D000000F823400199C3 +:109F200000003D0D12010068020580B000003610EF +:109F300000000080020000900000430DB50000808A +:109F4000020000B000000000A50080A0360B6A35BA +:109F5000000000000000005009C02932000000008D +:109F60000056012808C06E32000000000000007892 +:109F7000390B2E320000000000000020F3819734DE +:109F800000004C0D04000078D90130B6000000003C +:109F900000000000B905303018000000000000F893 +:109FA00003A403390000000000000034330B2F32FB +:109FB0000000590D04000078D90130B600000000FF +:109FC00000000078B90530300000520D0400008018 +:109FD00042E529BC00000000000000F80200003249 +:109FE00018000000000000F8738A02390000000029 +:109FF0000000009C028097320000580D25010008E7 +:10A00000080000B20000560D12000028020580B0C2 +:10A010000800580D000000F8234001990000580D79 +:10A0200012010068020580B00000361000000080B8 +:10A030000200009000004C0D000000F402000092AD +:10A0400000005D0D0400008042E529BC0000000016 +:10A05000000000F80200003218000000000000F8C4 +:10A06000738A0239000000000000009C0200953253 +:10A0700000000000CA0100D8028001320000000088 +:10A080000030000007C02C32001000A00038000093 +:10A090000700373200000000002000000700EE3209 +:10A0A000000000000038000C078082320000620DC2 +:10A0B0001200004802C080B2000032030000000815 +:10A0C000E801009400007A0D02000080A24280BCEA +:10A0D00000007A0D80000080F2C185B600007A0D84 +:10A0E0001F400208B9BF68B000006C0D80410280BB +:10A0F000E28168B608000000000000107961803934 +:10A1000000000000D22101E016206E3A1800000085 +:10A1100000400288E6219139000000000001005C47 +:10A1200008000072000000000000000C19A0903A26 +:10A1300000007A0D06010080D2FF90BC0000700D77 +:10A140002C410278F98168B400000000000000781A +:10A15000B98197340300000000400200291AFF383B +:10A160000000000000380200B91B903A0000000017 +:10A17000D241028816A0973A00000000450000D89E +:10A1800002400032000036109F2001E016206EBA17 +:10A1900000000000000000000740803200000000C6 +:10A1A000000800002724903A000000000010000082 +:10A1B00007008A320000000012010058F2C1387412 +:10A1C0000000780D00000080020000900800840D5F +:10A1D0001A000034796180B900008F0D1E010080E3 +:10A1E000020000B000008F0D1F400200094068B25D +:10A1F00000007C0D80000080E20190B60000361067 +:10A20000380000541F40F5BA0000000000000008AC +:10A21000B93F903000000000002801E026246E3A8B +:10A22000080036101E00000009A4FEB800008F0DC3 +:10A2300012010068020590B0000036100000008096 +:10A240000200009000008F0D8000008082812FB6F8 +:10A2500000008D0D1F410200094068B2000000009F +:10A26000002801E016206E3A00008A0D800100806F +:10A27000F2C185B60000000000400284E60100340F +:10A28000000000000000008002000030000000001C +:10A29000004002800240683200003610380000544E +:10A2A0001F40F5BA00000000002101E016206E7A80 +:10A2B0000000850D80000080E20190B600007E0D58 +:10A2C000000000541F40F59A000000000000005CF0 +:10A2D0000800003200000000D22101E016206E3A92 +:10A2E000180000001E410284E661937900003610D8 +:10A2F00000000080020000900000FFFF00000080CE +:10A30000020000900000970D1D5D01EC16C06EBCB0 +:10A31000000000000F01008002000070000000003B +:10A32000000100F8B2802F74000000000F010080CF +:10A33000020000700000960D045E01EC16C06EBCB9 +:10A3400000000000005C01EC06400032000000004C +:10A3500000010080020000700000FFFF000000808C +:10A3600002000090000000000420018082DB907C4D +:10A3700000000000020C0280A2DB907C0000A00D17 +:10A3800006210180821B90BC2700A10D0000000067 +:10A390000900369228000000000000000900363253 +:10A3A000000000000000008812002C3A0000FFFFAF +:10A3B0000000008002000090000000002FA0017843 +:10A3C000891B927A0000000006880178899B977C9F +:10A3D000000000000034020409C06E3D00000000CF +:10A3E000000C020019A46E370000AB0D02000080C3 +:10A3F00002A497BC0000AB0D02000080020000B078 +:10A400000100000000000078898D973700000000EF +:10A4100002010280829B977C00000000000100F88E +:10A42000F2802F740000FFFF000000800200009007 +:10A4300000000000DA5B01EC0640ED320000B10DD7 +:10A4400004010080024086BC0000000000A001E082 +:10A4500016206E3A0000B30D00D401EC0600009205 +:10A460000000D70F0090010809006EF20000000004 +:10A4700000A001E016206E3A00000710330100F83A +:10A4800082802FB4000007109FF0018082DB87BC20 +:10A49000000007109FF8018022216EBC0000000020 +:10A4A00000E801E00600EE320000000000F001E0EC +:10A4B00006C08732000007100000008002000090F4 +:10A4C0000000FFFF00000080020000900000C50DAA +:10A4D0000421013069246EBC0000BF0D1F4002241E +:10A4E000094068B20000BB0D80000080E24192B6D6 +:10A4F0000800BB0D1201006892A4FEB800003610DF +:10A5000000000080020000900000000000A801E0B0 +:10A5100066246E3A0000C20D382001E0060093B2B6 +:10A520000000C30D002801E00600009200000000BA +:10A53000003001E00600003200000000005001E899 +:10A5400006000032000000000001008002000070E0 +:10A550000000CA0D38510100A99B91BA0000C80D36 +:10A5600004410208B9FF68B00000C60D0040028037 +:10A57000024068920000D50D9F3101E066246EBC58 +:10A580000000D50D003001E0060000920000D30D60 +:10A590000428010409006EB20000D10D9F010000E3 +:10A5A000192490BC0000000000A801E066246E3A67 +:10A5B00000000000002801E00624003C000000002C +:10A5C000005001E806000032000036109F2001E034 +:10A5D000060093B20000000000010080020000703D +:10A5E00000000000002801E0060000320000DB0D42 +:10A5F00004000080020090BC0000D50D0441020858 +:10A60000B9FF68B00000D30D00400280024068929C +:10A610000000D90D02000080222490BC0000DB0D58 +:10A6200080400280F2C168B6000000000040028C49 +:10A63000B6C168350000DB0D000000F822812F94C0 +:10A640000800361012400268129AFEB80000D30DBE +:10A6500004010000292490BC0000000000A801E0D3 +:10A6600066246E3A00000000005001E806009032B7 +:10A67000000036109F2001E0060093B200000000A9 +:10A6800000010080020000700000FFFF0000008059 +:10A69000020000901800E20D1F41027888CD68B6D4 +:10A6A000000000000000008812002C3A0000E40DB9 +:10A6B00080010080628087B60000E00D00400280CB +:10A6C000024068920300361004400200381AFFB8B6 +:10A6D000000036101F400204B8FF68B00000000000 +:10A6E00000390200B81B807A0000FFFF00000080E4 +:10A6F000020000900000EF0D80010080A2802FB6C4 +:10A700000000EC0D1201000009C021B21800360053 +:10A71000000000F8730A03F900000000000000D8F0 +:10A72000024084321D00EF0D0401008002A417B81E +:10A730000000E90D9F010080180088BC0000361061 +:10A740000000008002000090000000000060006C2B +:10A7500008006E3200000000CA68004C08006E322B +:10A76000000036100470001808006EB200000000EF +:10A7700004000080A2A0817C0000F60D8001008012 +:10A78000E2802FB60000F60D1B000080020000B032 +:10A79000000000000600008062E0837C00000000F2 +:10A7A000CA0100F802802F3500A00000120100400D +:10A7B000A28D39720000F70D0000008002000090A9 +:10A7C0000000FFFF00000080020000900000000079 +:10A7D000000801E406C02D32EEFF0000001001E089 +:10A7E000868D2F31000000000000001CB3E43932D8 +:10A7F0000000000E04000078D90130B6000000000F +:10A8000000000078B905303018000000000000F8A2 +:10A81000E3A503390000000000000034330B2F32A1 +:10A820000000000004000078D9013076000000002C +:10A8300000000078B905303018000000000100F871 +:10A84000E3A503790000FFFF0000008002000090F4 +:10A8500000000000000000CC020000320000080EE2 +:10A860002000012C09C06EB20000090E001686CC33 +:10A8700006C0929200000000001486CC06C09232FE +:10A880000000000012010040628E92520000090E8A +:10A8900000000080020000900000FFFF0000008028 +:10A8A0000200009000000E0E04000078D90130B6BE +:10A8B0000E0E3600000000C00200369200000000BC +:10A8C000000000140300383200000000000000E027 +:10A8D0000200303200004E0E04000024D80130B6D1 +:10A8E000120E000000000088824D823A00003610EF +:10A8F0000000008002000090000036100000008080 +:10A90000020000900000361000000080020000905D +:10A910000000361000000080020000900E0E36008D +:10A92000000000C0020036920000380E00000080D7 +:10A930000200009000001A0E000000204805309030 +:10A940000000361000000080020000900000260E7B +:10A95000921101BC08006EB200000000000801DC8A +:10A9600002406E3200001E0E1F1101E026C18BB5A1 +:10A970000000260E1D000080020000B00000000054 +:10A98000000000D802000032800200000000000039 +:10A99000070036320000000000000078A9002D37C3 +:10A9A0002045000000080000878D973A0A0000004B +:10A9B00000000078890D82370000000000100000C0 +:10A9C000A7BA973A000000000018000007C0EA325A +:10A9D0000000250E1200004802C038B200002A0E06 +:10A9E000800E01BC08C06EB2000000000000000034 +:10A9F000190E823200E0320E12010048A20D90B210 +:10AA00000000280E000000800200009000000000FE +:10AA1000000000D802400032B40000000000000036 +:10AA2000070036320000000000000078A9002D3732 +:10AA30000044000000080000878D973A00000000E5 +:10AA400000000078990082370000361002100000E4 +:10AA500087BF97BA00000000001800000740FE32D0 +:10AA60000000310E12000048F2C138B41800360060 +:10AA7000000000F8730A03F9000000000000000461 +:10AA8000896038320000000000000018F341903463 +:10AA90000000380E04000078D90130B60000000034 +:10AAA00000000000B905303018000000000000F878 +:10AAB00003A40339000000000000000019CE2C326E +:10AAC0000060390E12000040A20D90B2000000009C +:10AAD000000000D80200003260000000000000000A +:10AAE0000700363200000000000000BCA8002D372F +:10AAF000A04700000008000087CD8B3A0A00000044 +:10AB00000000007889CD2C3780020000000000781A +:10AB1000898D973A0000000000100000A7BA973A0C +:10AB2000000000000018000007C0EA320000420EDA +:10AB300012000040F2C138B418003600000000F8DE +:10AB4000730A03F900000000000801DC02406E32C5 +:10AB50000A00470E1F01007889CD2CB700000000C5 +:10AB60001D1001F802006E7280020000000000005B +:10AB700007003632204500000008000087CD8B3AE0 +:10AB80000000000000100000A7BA973A0000000083 +:10AB90000018000007C0EA3200004B0E120000400F +:10ABA000F2C138B418003600000000F8730A03F947 +:10ABB00000000000001101F802006E7200000000A9 +:10ABC000001001F802006E3200000000000901DCF4 +:10ABD00002406E720000FFFF000000800200009043 +:10ABE0000000000000000000090000320E0000001C +:10ABF00000000004894D0D36000000000000000038 +:10AC000007800B32000000000008000007009032AF +:10AC10000000000000100000070036320000560E51 +:10AC20001200004CF2C138B40000000000000080A7 +:10AC3000020000300000570E1200008002C021B256 +:10AC40000000000000000000E902903A0000530EEE +:10AC500004010004194090BC0000000000010080C5 +:10AC6000020000500000FFFF000000800200009082 +:10AC70000000650E80010080A2802FB60000600EEB +:10AC8000120100E802C021B218003600000000F8EE +:10AC9000730A03F90000640E0400008002802DBCDA +:10ACA000000036109F000080180088BC0000600E75 +:10ACB000120100E802C021B200005F0E0000008017 +:10ACC0000200009000000000CA0000D80240843258 +:10ACD000000000000040006C881C833A0000000067 +:10ACE0000048004C0800723200003610085000186E +:10ACF000C82072BC00000000040000800240817C7B +:10AD000000000000000000141840813C00003610D4 +:10AD100002000020880182BA00000000000000D874 +:10AD200002000032000000000000000007000632B0 +:10AD30000700000000080000774A09390000000001 +:10AD4000001000000700823200000000CA19000055 +:10AD5000074082320000700E12000040F2C138B489 +:10AD600000000000000100D8024084720000FFFFD4 +:10AD70000000008002000090000000004D00000074 +:10AD800067E0833E000000000008000007008032FA +:10AD9000000000000010000007C086320000000024 +:10ADA0000018000007C084320000B70E040000281D +:10ADB000D8A082BC0000000000000018D8A0813C90 +:10ADC0000000890E0400003CD8E083BC00007D0E2A +:10ADD0000400008072802DBC00007B0E1200005029 +:10ADE00002C038B20000830E510000D812802D9AA4 +:10ADF00000007D0E12000050F2C138B41800360079 +:10AE0000000000F8730A03F90000820E04000080BD +:10AE100072802DBC00007E0E670000F8A2802FB566 +:10AE200000003610120000E802C021B2000000004D +:10AE3000510000D8020000320000870E2A010000F5 +:10AE4000D82080BA0000870E1201000009C021B28C +:10AE500018003600000000F8730A03F90000000033 +:10AE6000000000D8024084320000F00D0060006C49 +:10AE700008006EF20000740E4D00000067E0839E33 +:10AE80000000890E12000050F2C138B418003600DC +:10AE9000000000F8730A03F91D008E0E0400008004 +:10AEA00002A417B800008A0E670000F8A2802FB530 +:10AEB000000036101200000009C021B20800361050 +:10AEC00012400268129AFEB80000DC0E000000304A +:10AED000030038F200009F0E1F00006CD8E086BA15 +:10AEE0000000E00D510000D8020000F20000940EB6 +:10AEF0000000003C0840809200009F0E000000808F +:10AF0000020000900000980E80010080F2812FB6B0 +:10AF10000000980E80000080E2802FB60000980E9E +:10AF200080010080328087B600000000000000F839 +:10AF3000E2802F340000730E04010080028081BC87 +:10AF400000009D0E80010080A2802FB600009D0EA3 +:10AF50001201000009C021B218003600000000F8FC +:10AF6000730A03F900000000000000D80240843298 +:10AF70000000F00D0060006C08006EF20000740E1E +:10AF80004D00000067E0839E0000A30E800100805A +:10AF9000E2802FB60000BA0E80010080A2802FB69A +:10AFA00018000000CA0000F8730A0339BA0E360010 +:10AFB000000000C00200369200000000000000A463 +:10AFC000A8608A3C0000A60E2FA8012099226EBA24 +:10AFD0000000A30D00000080020000F0000000004F +:10AFE00000A801E00600923200000000005001E8D5 +:10AFF000060000320000AA0E232101E0060000B284 +:10B000003E00A90E1200002C82CD2EB20000361098 +:10B01000043000E0068082B20000B20E042100E09D +:10B02000068081B20000B00E80010080A2802FB6A1 +:10B030000000B00E1201000009C021B21800360055 +:10B04000000000F8730A03F900000000000000D8B7 +:10B05000024084320000F00D0060006C08006EF2C7 +:10B0600000000000002000E0068081320000361061 +:10B07000041000E006C086B2000000002A1900E0BB +:10B0800006C0847200000000000000F8A2802F3586 +:10B09000000000001201000009C0217218003600F3 +:10B0A000000000F8730A0399000000000000003C53 +:10B0B000D8E0833C0000B80E12000050F2C138B452 +:10B0C00000000000000000F8A2802F340000000003 +:10B0D0000000008812002C3A0000FFFF00000080F2 +:10B0E0000200009000000000000000000900003293 +:10B0F000000000000000007809000032000000009D +:10B10000000000A802000032EE05C20E040100801B +:10B11000820DF6BC0006000000000008090036326F +:10B120000000C40E0000000409C0099200280000BD +:10B130000000000809003632000000000000000492 +:10B14000098009321E000000000060C087CD003772 +:10B1500000000000000860C0078097320030000047 +:10B1600000000078898D2A3A000036101200005C39 +:10B17000528197B400000000000000002924903A9A +:10B180000800000000000078890D903600000000E3 +:10B19000000000041940903C00000000000000A8DE +:10B1A00052822A3A0008C40E02010080828D2ABC15 +:10B1B0000000D50E06000080024090BC0000361052 +:10B1C000120000A8020020B21E000000000000C013 +:10B1D00087CD003700000000000800C007809732CC +:10B1E000000036101200005C52812AB400000000FA +:10B1F000000000002924903A0800000000000078B8 +:10B20000890D90360000CE0E04010004194090BC58 +:10B210000500000000000078890D9036000036100F +:10B2200012000068028097B20000000000000000D9 +:10B230002924903A00000000000000785900903660 +:10B240000000D60E95010080222490BA0000000074 +:10B2500000010080020000500000FFFF000000809D +:10B26000020000900000000004010078D90130764F +:10B27000000000000000002809C029320000000082 +:10B280000000009CB24528300000E80E860100084E +:10B2900009802FB2000000000000002C094081321C +:10B2A00000000000000000F8020000320000000072 +:10B2B000000000F40200003218000000000000F856 +:10B2C000738A0239000000000000009C0280923264 +:10B2D0000000E70E0407018002C06EBC0000ED0E06 +:10B2E000C30701ECB6E46E9A0000ED0E000601EC17 +:10B2F000B6E46E9A000000000000002C09058030C2 +:10B3000000000000000000F8020000320000000011 +:10B31000000000F40200003218000000000000F8F5 +:10B32000738A023900003F0F0000009C028092D215 +:10B330000000000000000030030038320000000070 +:10B3400004010078D90130760000DF0E0000009C77 +:10B35000B24528900000FFFF00000080020000902E +:10B36000000000000000008802C0E8320200F20E77 +:10B37000B00000A0F20B00B9000000000000000CBB +:10B38000ABE4B0320000F70E80010080F24BD0B683 +:10B3900000000000A00000280900003200000000AA +:10B3A00000010080020000500000F90E040100803E +:10B3B000123EF8BA0000040FA0000004FD4BD09428 +:10B3C0000000000F80010080D28192B60000000FC3 +:10B3D000800100802281FCB600000000A000000473 +:10B3E000FD4BD034000000000000008401C02F326B +:10B3F0000000000000000080F101003400000000A7 +:10B400000000009401C02F320000040F00000090E3 +:10B41000F101009400000000A000008401C02F3260 +:10B420000000000000000080F101F834000000007E +:10B43000000000900140F8320000000000010028E8 +:10B44000090000520000080F040100280934B0BAB6 +:10B450000000050FB0000080020000B000000000F6 +:10B46000A0000004FD4BD0350000000000010028C2 +:10B47000090000520000080FB00000A822C02FB73A +:10B480000000060F040084C037ACB0B2000000001A +:10B49000A000000C0B000032FFFF0000000000784D +:10B4A000A94DB03000000F0F800000800240B0B600 +:10B4B000000000000000007869819735000000005E +:10B4C000000084080B007C32000000000000000037 +:10B4D000E72501320042000000080000878D2A3A6B +:10B4E00000000000001000000700B0320000000063 +:10B4F000001800000700D0320000000012010048D0 +:10B50000F2C138540000130F0000008002000090C8 +:10B510000000150FB00000A0020000B20000000003 +:10B520000000000CABE4B03200001A0F8001008074 +:10B530000240D0B600000000A00000280900003240 +:10B5400000000000000100800200005000001C0FFD +:10B5500004010080123EF8BA00002D0FA000000484 +:10B560000D40D0940000260F80010080D28192B659 +:10B570000000260F800100802281FCB60000000040 +:10B58000A00000040D40D03400000000000000784E +:10B5900009C02F3200000000000000FC0200003251 +:10B5A000000000000000008401C02F3200000000F5 +:10B5B00000000080F1010034000000000000009451 +:10B5C00001C02F320000000000000090F1010034A3 +:10B5D00000002D0F000000FC028097920000000088 +:10B5E000A000007809C02F3200000000000000FC1D +:10B5F00002000032000000000000008401C02F3271 +:10B600000000000000000080F101F834000000009C +:10B61000000000900140F83200000000000000FC33 +:10B62000028097320000000000010028090000524B +:10B630000000310F040100280934B0BA00002E0FB9 +:10B64000B0000080020000B000000000A000000474 +:10B650000D40D03500000000000100280900005214 +:10B660000000310FB00000A8020000B200002F0F50 +:10B67000040084C037ACB0B200000000A000000C91 +:10B680000B000032FFFF000000000078A94DB03031 +:10B690000000380F800000800240B0B600000000BB +:10B6A00000000078698197350000000000008408E0 +:10B6B0000B007C320000000000000000E725013292 +:10B6C0000042000000080000878D2A3A00000000B8 +:10B6D000001000000700B032000000000018000059 +:10B6E0000700D0320000000012010048F2C13854B7 +:10B6F00000003C0F00000080020000900000FFFFEF +:10B7000000000080020000900000410F1C400280F9 +:10B7100006C092B244000000000100F8A28D2F5232 +:10B72000000036101200006802C592B00000000050 +:10B73000000100701F00F75A0000FFFF00000080AA +:10B740000200009000000000D5080000078092323F +:10B75000000000000030000007C02C3200400080D4 +:10B76000003800000700373200000000CA4101E045 +:10B77000068092320000480F1200004802C080B2DA +:10B780000060000000010008088036720000FFFF22 +:10B79000000000800200009000000000003800005F +:10B7A00007809232000000000030000007C02C32F9 +:10B7B00000000000CA3D000C07808332000000003A +:10B7C0001201004802C0807200004E0F000000808D +:10B7D000020000900000FFFF0000008002000090C7 +:10B7E000000000000457018002C06E7C00000000D1 +:10B7F000005701EC068092720000FFFF00000080FD +:10B80000020000900000DC0E00000030030038F25F +:10B810000000570F9D11020C09006EB20000580F76 +:10B8200000F0011C09006E920000000000B8011C2D +:10B8300009006E3200005A0F2CCD011809806EB23B +:10B84000000000000000000CC9C1903400005D0F32 +:10B850003B29020409806EB20000000000D601EC12 +:10B8600056C06E34000000000000000CB9C19034D6 +:10B8700000006C0F00A8010809006EF20000610FC3 +:10B880009D01008017E090BA0000000000300080A9 +:10B8900007C091320000640F003800800700EE926C +:10B8A0000000640F0401008002C091BC0000000091 +:10B8B00000B801E00600EE3200000000007001E078 +:10B8C000060086320000660F3908008007C085B286 +:10B8D00000000000D9C901E8068091320000000094 +:10B8E000C8110080074090320000690F3B210080A2 +:10B8F000070086B200000000DB0000601800863AF6 +:10B9000000000000587801E01620863A0000000090 +:10B9100000290080070085720000FFFF0000008002 +:10B92000020000900000700F020C0280A29B90BCED +:10B93000000000000000027829006E360000700F41 +:10B9400002000080E2A590BC00000000000000089A +:10B95000090000320000720F9F89017849216EBCF6 +:10B960000000000000000078090000320000000024 +:10B9700000000008E9A5903F0000780F04200208AD +:10B98000899B90BE00000000000A0258B89B9036C8 +:10B99000000000000000007849A1903A000000007B +:10B9A0009F880180829B977C00000000008901E055 +:10B9B0000680977200000000000B0258B89B90763A +:10B9C0000000FFFF000000800200009000007F0FD9 +:10B9D00080010080A2802FB600007E0F1201007847 +:10B9E00009C021B218003600000000F8730A03F9FC +:10B9F00000007F0FCA0000D80240849200000000BF +:10BA0000000000F8A2802F35000000000040006C0C +:10BA1000881C833A000000000048004C0800723285 +:10BA20000000361008500018C82072BC000000004A +:10BA30000600008062A0827C000036100200002018 +:10BA4000880182BA00000000000000D80200003225 +:10BA500000000000000000000700063207000000A0 +:10BA600000080000774A09390000000000100000BB +:10BA70000700823200000000CA190000074082322D +:10BA80000000890F12000040F2C138B4000000002D +:10BA9000000100D8024084720000FFFF0000008017 +:10BAA000020000900000930F80010080F2C185B673 +:10BAB0000000900F1F400284E60100B40000930FC5 +:10BAC0001D0100F822812FB40000930F000000F840 +:10BAD00062812F950000920F1D010080020000B0CE +:10BAE00000000000000000F862812F350000000017 +:10BAF00000400280024068320000361012000068E8 +:10BB000002C585B0000000001D000080020000702A +:10BB10000100000004010080A28D2F702A00960F02 +:10BB20001200002C82CD2EB200000000000100F8AF +:10BB300002812F740000FFFF0000008002000090CF +:10BB400080A8000004000080828D2F7000009F0FED +:10BB500080010080D2802FB600009F0F04B00080CB +:10BB600002006EBC00000000000000F872812F345B +:10BB70003D00A20F1201002C82CD2EB200009D0FBD +:10BB800000000080020000900000A20F80010080F1 +:10BB9000F2802FB63C00A50F1201002C82CD2EB2F0 +:10BBA0000000A00F00000080020000900000A50F20 +:10BBB00080010080B2802FB63500A30F1200002C48 +:10BBC00082CD2EB200000000000000F842812F3428 +:10BBD0008000000004000080828D2F7002000000B1 +:10BBE00004010080A28D2F703B00A70F1200002CD3 +:10BBF00082CD2EB200000000000100F812812F74E7 +:10BC00000000FFFF0000008002000090080000001C +:10BC1000001801E876208139EEFF0000000100F8ED +:10BC2000828D2F710000FFFF000000800200009055 +:10BC30000000B10F0000013808C06EF200000000E3 +:10BC40001201004802C080720000AE0F00000080A8 +:10BC5000020000900000FFFF000000800200009042 +:10BC60000000B30F0438017809006EB20000000034 +:10BC7000003801E00600003200000000CA11000098 +:10BC8000078082320000B60F2E190000078097B29D +:10BC90000000000000000028E98192340000BB0F82 +:10BCA0002731000007C02CB200000000D5080000BA +:10BCB0000700873200000000C7000028E9809234A6 +:10BCC00000000000004001E0060087320000000094 +:10BCD00000000008D8818034100000000039000006 +:10BCE000E7A092790000FFFF0000008002000090B2 +:10BCF0000000BD0F1200004412E438B218003600F4 +:10BD0000000000F8730A03F90000C20F040100806C +:10BD100002802DBC0000BE0F670000F8A2802FB586 +:10BD200000003610120000E802C021B2000000003E +:10BD3000000100D8024000720000FFFF00000080F8 +:10BD4000020000900000C70F04300080829B81BC7D +:10BD500000000000CA0100F802802F3500A0C60FC5 +:10BD600012000040A28D39B200C0CB0F0438007819 +:10BD7000898D6EB01000CB0F9F0100F8E2A52FB99E +:10BD800000000000005801EC06C0EE320000000088 +:10BD900000000080020000300000000004280018AD +:10BDA00009006E720000BA0D00000080020000F071 +:10BDB0000000A30D00A8012009006E920000FFFF03 +:10BDC00000000080020000900000D40F04B000804A +:10BDD000829B81BC0000000000B800E886806E34C1 +:10BDE00000000000CA0100F842802F3508A00000C2 +:10BDF00012010040A2CD39720000D20F0000008075 +:10BE0000020000900000000000B800E886806E3458 +:10BE10000000000000010080020000700000FFFF31 +:10BE200000000080020000900000DA0F33CD01BC5A +:10BE300008806EB200001410000000282922EEDCF9 +:10BE40000000DF0F00000080020000900000DF0F04 +:10BE500004B8012809006EB20000DF0F9F71018055 +:10BE6000C2216EBC000036109F000028A924EEBC41 +:10BE70000000141000000028198092DF000000006C +:10BE800000000080020000300000F20F02810180FB +:10BE9000829B90BCEE05EA0F060C0280828D6EBC80 +:10BEA00000904C0000000084020037320000E40FD4 +:10BEB000B8010080020000B00000E20F0000008026 +:10BEC0000200009000000000000000C403809032D7 +:10BED0000000000000B001E096216E3C0000000070 +:10BEE000619801E0060087320000000000D401ECF8 +:10BEF0000600003200000000A800007849403C37EE +:10BF00000000F70F00000008E9A5909A6089200062 +:10BF100000000084020037320000ED0FB8010080FD +:10BF2000020000B00000EB0F000000800200009053 +:10BF300000000000000000C40380903200000000F8 +:10BF400000B001E096216E3C00000000619801E025 +:10BF5000060087320000000000D401EC0600003229 +:10BF60000000F70FA8000008198F909A0000000049 +:10BF70000000007899A1893E000000000000000840 +:10BF8000E9A5903A0000000000B001E096216E3C67 +:10BF900000000000619801E0060087320000000008 +:10BFA00000D401EC060000320000FA0F0600008009 +:10BFB00072A290BC00C0FF3F008001E00600373253 +:10BFC000000000000000000809C089320000FF0FD7 +:10BFD00004790180821B87BC0000FD0F04B0008043 +:10BFE00002006EBC00000110D99001E00680909222 +:10BFF000000004108000008052812FB60000041061 +:10C00000D54101E006008792000001103C9001E05C +:10C01000068090B20000000000C801E806C08B3224 +:10C02000000000009501008002802F7200000510C2 +:10C030009F410180821B87BC00000000000100803E +:10C040000200007000000000D99001E006809032EC +:10C0500000000000000100F872802F740000FFFF54 +:10C06000000000800200009000000D109FD80180A9 +:10C0700022216EBC000000000B0100800200007055 +:10C0800000000D109FE00180C2216EBC0000000086 +:10C090000B0100800200007000000D109FB00180B5 +:10C0A000D2216EBC00000000000100800200007080 +:10C0B00000000F1006680180825B87BC0000000052 +:10C0C000006801E0064087320000111037B001E03F +:10C0D000064087B200000000000000F8D2802F3434 +:10C0E0000000000000D801E006808432000000005B +:10C0F00000E101E0060087720000FFFF0000008001 +:10C10000020000900000201004C1018402006EB201 +:10C110000500000000C001E8868D92370300000092 +:10C1200000C401E8868D9237000000000000008006 +:10C13000020000300300000000C0012C898D6E3623 +:10C140000000000000C4012CA9DB923A00000000AE +:10C150000000002C29C09236000000000000002CD6 +:10C1600019FB923F00000000000000282980923A4D +:10C17000000000000000002CA9E4923F0000000035 +:10C180006FCC01E826FB923E0000000000B901E000 +:10C19000060000520000000000000094028092326D +:10C1A0000000000000C001E006402832100000003E +:10C1B0006FCC01E886CD2A360000000000B901E00E +:10C1C000060000520000FFFF000000800200009007 +:10C1D00000000000009001BC08006E32000000006A +:10C1E00000B001BC88DB8B3E00000000009801BC61 +:10C1F00088DB8B3A000030109F0000BC88E18BBCCC +:10C2000000003010040C0240A8DB8BBE00000000D0 +:10C2100000B00004881B843E00002D1004B1008093 +:10C22000825B80BC00000000000100F8C2802F7417 +:10C2300000000000040C0280A25B807C0000301033 +:10C240000468017819006EB600000000020000804A +:10C25000E265807C000000000000008812002C3A9B +:10C260000000FFFF000000800200009008000000B6 +:10C27000001C01E876208139EEFF0000000100F883 +:10C28000828D2F710000FFFF0000008002000090EF +:10C2900000003610000000B40F40FB9400000000C6 +:10C2A000000000880F402B320000000000000090CA +:10C2B0000F00283200000000000000940F00293217 +:10C2C00010000000000000B85F461839FF000000B1 +:10C2D0000000009C0F003632000000000000009CAF +:10C2E0005FCAF935000000000000004403C0F932C5 +:10C2F00000000000000000E40300003241000010D4 +:10C30000000000E00300373200000000000000E4FD +:10C310000300003240000010000000E0030037324C +:10C3200000004510670000980F802AB2000000004E +:10C33000000000A8020000320000431012C186E095 +:10C3400007C021B20000000000B886C006802A3273 +:10C350004C420000000000A802003632471058117D +:10C36000000000B00F003692000000000000009CAA +:10C370000200003200014411000000AC0F0036D270 +:10C3800000000000000000AC0F802A3200200000F6 +:10C39000000000A802003632000000000000009CEF +:10C3A0000F007E3200000000000000A00F007E326F +:10C3B00000000000000000A40F007E32000000001A +:10C3C000000000A80F007E3200000000000000A85E +:10C3D00002C0FA3200000000000000E007C0F9329D +:10C3E00000000000000000E00700FA32000000003A +:10C3F000000000E00740FA3200005B10000000E09F +:10C400000780FAD200000000000000E00780FB3245 +:10C4100001008210040100B48F4DFBB00200000047 +:10C42000000000A002000039408000000000000C65 +:10C43000ABCDB032100000000000000C5BCAB03978 +:10C44000000000000000000C2BFEB0320000811143 +:10C45000000000800200009000000000000000F8D2 +:10C460000300013200000000000100E007803F529D +:10C4700018000000000000F8738A02390000000074 +:10C4800000000044530A1635000000000000009C24 +:10C490000F80963200000000000000A00FC096320E +:10C4A00000000000000000A40F009732A26003000B +:10C4B0000000005803003732681000000000005CE4 +:10C4C000030036320000000000000050830D0034ED +:10C4D0000000000000000048830D00340000000050 +:10C4E00000000044530A00340000360000000080C1 +:10C4F00002000090000000000000006809C0F9324E +:10C50000000000000000006C0900FA32000000008A +:10C51000000000700940FA3200007A10000000802C +:10C520000200009002000000000000A0F20B0039A1 +:10C5300000006F10800100801240B0B600000000C3 +:10C54000000000043B40B033000000000000000485 +:10C55000FD4BD035000073100000000C0B009792CB +:10C5600002000000000000A0F20B00390000731070 +:10C57000000000046B019794000073101200006823 +:10C58000094020B2000074101200006C094020B273 +:10C590000D000000000000FCA2E516380000791034 +:10C5A0009F000080028096B2000000000000007032 +:10C5B00009C0963200007A100000006C09C0FD929C +:10C5C0000000791012000070094020B20000000045 +:10C5D0000000009C0200003200000000000000D8B3 +:10C5E0000200003202007310040100BCAF2517B82E +:10C5F00006007110040000BCAF6516B800006C1096 +:10C600000400008022C0FBBC00008A1004000080EF +:10C6100012C1FBBC200073100401008082CDFBBC62 +:10C6200002000000000000A0F20B003900008B1097 +:10C6300000000080020000D084100000000000888C +:10C6400082CDF93A00007A110000008002000090CB +:10C650000000B31000000080020000900000B41041 +:10C6600000000080020000900000B8100000008070 +:10C67000020000900000C010000000800200009046 +:10C6800000001911000000800200009000007310EB +:10C69000000000DC0F009792000000000000000086 +:10C6A0000700033240420000000000A802003632BA +:10C6B000000000000008000007802A32000000008F +:10C6C0000010000007009732000000000018000072 +:10C6D00007C096320880901012000040028036B2E7 +:10C6E00000000000000000800200003000009210F6 +:10C6F0001200009C0FC021B21D00951004000080A4 +:10C7000072BE17B800009210000000F81E80EF9A69 +:10C71000130000000000009C7FBE17380000981036 +:10C720000400008012C0F9BC00009210000000F864 +:10C730001E80EF9A000000000000009C0F007E3277 +:10C7400000000000000000A00F007E32000000008A +:10C75000000000A40F007E32000000000001000075 +:10C760000700FA52000000000000009C02000032A6 +:10C770004C420000000000A8020036320000000019 +:10C780000008000007802A3200006E1100000080BF +:10C79000020000D00000721100000080020000D0F2 +:10C7A000000000000000000CCBC1B034000000000D +:10C7B0000000009C0200003200000000000000D8D1 +:10C7C000020000320000F10E0000002809C0B0D2C3 +:10C7D0000000A21004000080028092B20000A610A7 +:10C7E0001200009C0FC021B21D00A910040000809F +:10C7F00072BE17B80000A610000000F81E80EF9A65 +:10C80000130000000000009C7FBE17380000AC1031 +:10C810000400008012C0F9BC0000A610000000F85F +:10C820001E80EF9A0200AE10040100B48F4DFBB0E1 +:10C83000000073100000008002000090080000005B +:10C84000000000F89340013900000000000000B42F +:10C850001F40FB35FE000000000000480300363298 +:10C860000000000000000044030000340000A2109B +:10C870000000000C8BC1B09400007E110008000085 +:10C880000740FA9200006E11000800000740FAD23B +:10C890000880B51012000050028036B200007311FB +:10C8A00000000080020000D0000080110000008025 +:10C8B00002000090000800000000009C0F003632CB +:10C8C00000440000000000A8020036320000000012 +:10C8D000000000A00200003200000000000000E0A4 +:10C8E0000700B03200000000000000A012002A3A49 +:10C8F0000000BB100401009C1FC0F9BC00440000F4 +:10C90000000000A80200363202007D11000000A0E5 +:10C91000F20B00990000C810040100800240FAB236 +:10C9200000440000000000A8020036320000CA10D7 +:10C9300000000080020000D00000D710000000843A +:10C94000020000D200000000000000E007C03C32FE +:10C950000000C4108E010080024028B20044000094 +:10C96000000000A40F0036320000B3100000008069 +:10C970000200009000440000000000A48F4DFA3A2D +:10C980000000B310000000800200009000000000D2 +:10C990000000009C0F00003210000001000000ACFD +:10C9A0000F0037320000DC1000000080020000D0D1 +:10C9B0000800CC100401008082CDF9BC000000000A +:10C9C0000000009C0F0000320E000001000000ACCF +:10C9D0000F0037320000DC1000000080020000D0A1 +:10C9E0000B00D0100401008082CDF9BC20000000B3 +:10C9F0000000009C0F0036320F000001000000AC68 +:10CA00000F0037320000DC1000000080020000D070 +:10CA10002700D4100401008082CDF9BC0000000082 +:10CA20000001008002000050000000000000009C97 +:10CA30000F0000320F000001000000AC0F00373281 +:10CA40000000DC1000000080020000D02000D9109F +:10CA50000401008082CDF9BC0000000000010080CC +:10CA60000200005000000000000000E403C0F932A2 +:10CA70000D000001000000E003003732000000005C +:10CA8000000000E003C0FA3200000000000000E0F7 +:10CA900007403E32000000000001009C1FC0F95A10 +:10CAA00000000000000000E003C0F93200000000B8 +:10CAB000000000E007403E32000000000000009C43 +:10CAC0001FC0F93AFF000000000100AC8FCDF95003 +:10CAD000000000000000009C0FC02F32000000008A +:10CAE000000000FC0200003200000000000000E036 +:10CAF00007803E3200000000000000FC12C02F3A08 +:10CB00000F00E7100401008082CD2FBC0000000060 +:10CB1000000000E007803E3200000000000100FC41 +:10CB200002C0F95200000000000000E007003A32A5 +:10CB300000000000000000E007403A320000000062 +:10CB4000000000E007803A3200000000000000E032 +:10CB500007C03A32000000000000009C0FC02F32D6 +:10CB600000000000000000FC020000320000000095 +:10CB7000000000E007003D3200000000000000E07F +:10CB800007403D320000F210830100FC12C02FBAB2 +:10CB900000000000000100FC02C0F952000000008B +:10CBA0000000009C0F0000320C0000000000000894 +:10CBB000733E003900000000000000E00700303242 +:10CBC000000000000000009C1FC0F93A7000F71040 +:10CBD0000401008082CDF9BC000000000000000CC0 +:10CBE0000300003200000000000000E007003032C7 +:10CBF00000000000000000100300003200000000F0 +:10CC0000000000E007003032000000000000009C3F +:10CC10000F00003200000000000000A00FC0293209 +:10CC2000000000000000009C02C0F932000000007B +:10CC3000000000A40FC02C32000000000000009C87 +:10CC40000200FA32180000000000002C737EFA394E +:10CC500000000000000000E007003032000000117A +:10CC60008501009C1FC0F9BA00000000000100808F +:10CC700002000050010000010000009C0F0037324C +:10CC80000000E11000000080020000D00E000F1133 +:10CC90000401008082CDFABC00000000000000E02A +:10CCA0000700003200000000000000E00700003232 +:10CCB00000000000000000E0070000320000091141 +:10CCC0000000009C3FC0F99A1C000911040100807B +:10CCD00082CDFABC0200E1100000009C8FCDF9DA91 +:10CCE000000000000001008002000050010000026E +:10CCF0000000009C0F0037320000E11000000080AF +:10CD0000020000D00E0017110401008082CDFABC91 +:10CD100000000000000000E00700003200001311D6 +:10CD20000000009C1FC0F99A260013110401008026 +:10CD300082CDFABC0000000000010080020000501B +:10CD400000000000000000A80F402932004400004D +:10CD5000000000A802003632000008110000008028 +:10CD6000020000D00000121100000080020000D07C +:10CD70000000E51000000080020000D0000000006C +:10CD8000000000E00780183200000000000000E012 +:10CD900007401A3200000000000000E007001A32CD +:10CDA00000000000000000E007801A3200000000D0 +:10CDB000000000E007C01A3200000000000000A0E0 +:10CDC0000F000032A2600300000000580300373259 +:10CDD0002B1100000000005C030036320000000050 +:10CDE0000000009C0F802A3200002B1104000080FC +:10CDF000024029B20000000000000050833E0034D1 +:10CE00000000000000000048833E003400000000E5 +:10CE100000000044530A003400002C110000008878 +:10CE20000F402B9200000000000000900F002832FD +:10CE300000000000000000940F00293200000000F4 +:10CE4000000000980F802A3200000000000000A8B7 +:10CE500002C0F93231115811000000B00F003692B3 +:10CE60000700341104000080824D29BC000000003E +:10CE7000000000A01F00FA3A000028110000009CEA +:10CE80000F802A92C0010000000000AC0F00363273 +:10CE9000010000000000009C020036320000441136 +:10CEA00000000080020000D01F003A110400008042 +:10CEB00082CD29BCC0000000000000AC8FCDFA3A42 +:10CEC000000036110000009C12C0299A0000F610E4 +:10CED00000000080020000D00000EC100000008084 +:10CEE000020000D00000421104000080528AFABC07 +:10CEF000A260030000000058030037324211000016 +:10CF00000000005C0300363200000000000000500A +:10CF1000A33E00340000000000000048A33E00349F +:10CF20000000000000000044530A003400440000E8 +:10CF3000000000A40F0036320000B3100000008093 +:10CF40000200009000000000000000C402C0FA329D +:10CF5000030000000000009C0F00363200000000BB +:10CF6000000000BC0F402F3200004B110400009C59 +:10CF70001FC0F9BC00004A110400008002402FB21B +:10CF800000004711000000E007002C92000047114C +:10CF9000000000E00700369200000000000000E002 +:10CFA00007402C3200000000000000E007802C3217 +:10CFB00000000000000000E007C02C32000000006C +:10CFC000000000E007002D3200000000000000E03B +:10CFD00007402D3200000000000000E007802D32E5 +:10CFE00000000000000000E007C02D32000000003B +:10CFF000000000E007C0FB3200000000000000E07D +:10D0000007802F3200000000000000E007C02F3230 +:10D0100018000000000000F8730A02390000000048 +:10D02000000100E007803F52FF00000000000044C4 +:10D030000300363200000000000000E00700F93273 +:10D0400000000000000000E007402832000000005F +:10D05000000000E00780F832030000000000009CA0 +:10D060000F00363200000000000000BC0FC02B3261 +:10D07000000061110400009C1FC0F9BC0000601199 +:10D080000400008002C02BB200005D11000000E02F +:10D0900007C0289200005D11000000E007003692F2 +:10D0A00000000000000000E00740F932000000002E +:10D0B000000000E00740293200000000000000E00E +:10D0C0000780293200000000000000E007C029327C +:10D0D00000000000000000E007002A32000000000D +:10D0E000000000E007402A3200000000000000E0DD +:10D0F0000780F93200000000000000E007C02A327B +:10D1000000000000000000E007C02F320000000017 +:10D11000000000E007402B3200000000000000E0AB +:10D1200007802B3200000000000000E007C0FB3247 +:10D1300000000000000000880200FB320000000038 +:10D140000000009C0200003200000000000000D837 +:10D1500002000032000000000010000007009732BB +:10D16000000000000019000007C0965208807211EC +:10D1700012000048028036B200000000000000806B +:10D1800002000030000074111200009C0FC021B298 +:10D190001D0077110400008072BE17B800007411E2 +:10D1A000000000F81E80EF9A130000000000009CB1 +:10D1B0007FBE1738000000000400008012C0F95C38 +:10D1C00000007411000000F81E80EF9A00000000BB +:10D1D000000000B40F40FB35000000000000009C80 +:10D1E000020000324C420000000000A8020036326B +:10D1F000000000000008000007802A3200006E11C5 +:10D2000000000080020000D00000721100000080C9 +:10D21000020000D0000000000000000CCBC1B034C0 +:10D22000000000000000009C02000032000000002E +:10D23000000000D80200003200008B11000000281E +:10D2400009C0B0D20000811104000080028092B2B7 +:10D25000000085111200009C0FC021B21D00881132 +:10D260000400008072BE17B800008511000000F8AD +:10D270001E80EF9A130000000000009C7FBE17384C +:10D28000000073100400008012C0F9BC000085117A +:10D29000000000F81E80EF9A00000000000000FC73 +:10D2A0000200003202000000000000A0F20B003972 +:10D2B00000008F11040100280934B0BA00000000FA +:10D2C000000100280900005200000000000000A832 +:10D2D00022C02F3700000000000084C037ACB032FD +:10D2E000000000000000000C0B000032FFFF0000F7 +:10D2F000000000C0AF4DB0300000951180000080EC +:10D300000240B0B600000000000000C06F01FC3514 +:10D310000000000000000000073F01320042000052 +:10D3200000080000878D2A3A00000000001000006D +:10D330000700B03200000000001800000700D032E3 +:10D3400000000000000000C03FC1383400000000B1 +:10D3500012010048F201FC5400009A110000008004 +:10D36000020000900000FFFF00000080020000901B +:0CD3700000003600000000800200009069 +:00000001FF diff --git a/include/linux/connector.h b/include/linux/connector.h index fc65d219d88c..b9966e64604e 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -39,8 +39,10 @@ #define CN_IDX_V86D 0x4 #define CN_VAL_V86D_UVESAFB 0x1 #define CN_IDX_BB 0x5 /* BlackBoard, from the TSP GPL sampling framework */ +#define CN_DST_IDX 0x6 +#define CN_DST_VAL 0x1 -#define CN_NETLINK_USERS 6 +#define CN_NETLINK_USERS 7 /* * Maximum connector's message size. diff --git a/include/linux/dst.h b/include/linux/dst.h new file mode 100644 index 000000000000..e26fed84b1aa --- /dev/null +++ b/include/linux/dst.h @@ -0,0 +1,587 @@ +/* + * 2007+ Copyright (c) Evgeniy Polyakov + * All rights reserved. + * + * 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. + */ + +#ifndef __DST_H +#define __DST_H + +#include +#include + +#define DST_NAMELEN 32 +#define DST_NAME "dst" + +enum { + /* Remove node with given id from storage */ + DST_DEL_NODE = 0, + /* Add remote node with given id to the storage */ + DST_ADD_REMOTE, + /* Add local node with given id to the storage to be exported and used by remote peers */ + DST_ADD_EXPORT, + /* Crypto initialization command (hash/cipher used to protect the connection) */ + DST_CRYPTO, + /* Security attributes for given connection (permissions for example) */ + DST_SECURITY, + /* Register given node in the block layer subsystem */ + DST_START, + DST_CMD_MAX +}; + +struct dst_ctl +{ + /* Storage name */ + char name[DST_NAMELEN]; + /* Command flags */ + __u32 flags; + /* Command itself (see above) */ + __u32 cmd; + /* Maximum number of pages per single request in this device */ + __u32 max_pages; + /* Stale/error transaction scanning timeout in milliseconds */ + __u32 trans_scan_timeout; + /* Maximum number of retry sends before completing transaction as broken */ + __u32 trans_max_retries; + /* Storage size */ + __u64 size; +}; + +/* Reply command carries completion status */ +struct dst_ctl_ack +{ + struct cn_msg msg; + int error; + int unused[3]; +}; + +/* + * Unfortunaltely socket address structure is not exported to userspace + * and is redefined there. + */ +#define SADDR_MAX_DATA 128 + +struct saddr { + /* address family, AF_xxx */ + unsigned short sa_family; + /* 14 bytes of protocol address */ + char sa_data[SADDR_MAX_DATA]; + /* Number of bytes used in sa_data */ + unsigned short sa_data_len; +}; + +/* Address structure */ +struct dst_network_ctl +{ + /* Socket type: datagram, stream...*/ + unsigned int type; + /* Let me guess, is it a Jupiter diameter? */ + unsigned int proto; + /* Peer's address */ + struct saddr addr; +}; + +struct dst_crypto_ctl +{ + /* Cipher and hash names */ + char cipher_algo[DST_NAMELEN]; + char hash_algo[DST_NAMELEN]; + + /* Key sizes. Can be zero for digest for example */ + unsigned int cipher_keysize, hash_keysize; + /* Alignment. Calculated by the DST itself. */ + unsigned int crypto_attached_size; + /* Number of threads to perform crypto operations */ + int thread_num; +}; + +/* Export security attributes have this bits checked in when client connects */ +#define DST_PERM_READ (1<<0) +#define DST_PERM_WRITE (1<<1) + +/* + * Right now it is simple model, where each remote address + * is assigned to set of permissions it is allowed to perform. + * In real world block device does not know anything but + * reading and writing, so it should be more than enough. + */ +struct dst_secure_user +{ + unsigned int permissions; + struct saddr addr; +}; + +/* + * Export control command: device to export and network address to accept + * clients to work with given device + */ +struct dst_export_ctl +{ + char device[DST_NAMELEN]; + struct dst_network_ctl ctl; +}; + +enum { + DST_CFG = 1, /* Request remote configuration */ + DST_IO, /* IO command */ + DST_IO_RESPONSE, /* IO response */ + DST_PING, /* Keepalive message */ + DST_NCMD_MAX, +}; + +struct dst_cmd +{ + /* Network command itself, see above */ + __u32 cmd; + /* + * Size of the attached data + * (in most cases, for READ command it means how many bytes were requested) + */ + __u32 size; + /* Crypto size: number of attached bytes with digest/hmac */ + __u32 csize; + /* Here we can carry secret data */ + __u32 reserved; + /* Read/write bits, see how they are encoded in bio structure */ + __u64 rw; + /* BIO flags */ + __u64 flags; + /* Unique command id (like transaction ID) */ + __u64 id; + /* Sector to start IO from */ + __u64 sector; + /* Hash data is placed after this header */ + __u8 hash[0]; +}; + +/* + * Convert command to/from network byte order. + * We do not use hton*() functions, since there is + * no 64-bit implementation. + */ +static inline void dst_convert_cmd(struct dst_cmd *c) +{ + c->cmd = __cpu_to_be32(c->cmd); + c->csize = __cpu_to_be32(c->csize); + c->size = __cpu_to_be32(c->size); + c->sector = __cpu_to_be64(c->sector); + c->id = __cpu_to_be64(c->id); + c->flags = __cpu_to_be64(c->flags); + c->rw = __cpu_to_be64(c->rw); +} + +/* Transaction id */ +typedef __u64 dst_gen_t; + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_DST_DEBUG +#define dprintk(f, a...) printk(KERN_NOTICE f, ##a) +#else +static inline void __attribute__ ((format (printf, 1, 2))) + dprintk(const char *fmt, ...) {} +#endif + +struct dst_node; + +struct dst_trans +{ + /* DST node we are working with */ + struct dst_node *n; + + /* Entry inside transaction tree */ + struct rb_node trans_entry; + + /* Merlin kills this transaction when this memory cell equals zero */ + atomic_t refcnt; + + /* How this transaction should be processed by crypto engine */ + short enc; + /* How many times this transaction was resent */ + short retries; + /* Completion status */ + int error; + + /* When did we send it to the remote peer */ + long send_time; + + /* My name is... + * Well, computers does not speak, they have unique id instead */ + dst_gen_t gen; + + /* Block IO we are working with */ + struct bio *bio; + + /* Network command for above block IO request */ + struct dst_cmd cmd; +}; + +struct dst_crypto_engine +{ + /* What should we do with all block requests */ + struct crypto_hash *hash; + struct crypto_ablkcipher *cipher; + + /* Pool of pages used to encrypt data into before sending */ + int page_num; + struct page **pages; + + /* What to do with current request */ + int enc; + /* Who we are and where do we go */ + struct scatterlist *src, *dst; + + /* Maximum timeout waiting for encryption to be completed */ + long timeout; + /* IV is a 64-bit sequential counter */ + u64 iv; + + /* Secret data */ + void *private; + + /* Cached temporary data lives here */ + int size; + void *data; +}; + +struct dst_state +{ + /* The main state protection */ + struct mutex state_lock; + + /* Polling machinery for sockets */ + wait_queue_t wait; + wait_queue_head_t *whead; + /* Most of events are being waited here */ + wait_queue_head_t thread_wait; + + /* Who owns this? */ + struct dst_node *node; + + /* Network address for this state */ + struct dst_network_ctl ctl; + + /* Permissions to work with: read-only or rw connection */ + u32 permissions; + + /* Called when we need to clean private data */ + void (* cleanup)(struct dst_state *st); + + /* Used by the server: BIO completion queues BIOs here */ + struct list_head request_list; + spinlock_t request_lock; + + /* Guess what? No, it is not number of planets */ + atomic_t refcnt; + + /* This flags is set when connection should be dropped */ + int need_exit; + + /* + * Socket to work with. Second pointer is used for + * lockless check if socket was changed before performing + * next action (like working with cached polling result) + */ + struct socket *socket, *read_socket; + + /* Cached preallocated data */ + void *data; + unsigned int size; + + /* Currently processed command */ + struct dst_cmd cmd; +}; + +struct dst_info +{ + /* Device size */ + u64 size; + + /* Local device name for export devices */ + char local[DST_NAMELEN]; + + /* Network setup */ + struct dst_network_ctl net; + + /* Sysfs bits use this */ + struct device device; +}; + +struct dst_node +{ + struct list_head node_entry; + + /* Hi, my name is stored here */ + char name[DST_NAMELEN]; + /* My cache name is stored here */ + char cache_name[DST_NAMELEN]; + + /* Block device attached to given node. + * Only valid for exporting nodes */ + struct block_device *bdev; + /* Network state machine for given peer */ + struct dst_state *state; + + /* Block IO machinery */ + struct request_queue *queue; + struct gendisk *disk; + + /* Number of threads in processing pool */ + int thread_num; + /* Maximum number of pages in single IO */ + int max_pages; + + /* I'm that big in bytes */ + loff_t size; + + /* Exported to userspace node information */ + struct dst_info *info; + + /* + * Security attribute list. + * Used only by exporting node currently. + */ + struct list_head security_list; + struct mutex security_lock; + + /* + * When this unerflows below zero, university collapses. + * But this will not happen, since node will be freed, + * when reference counter reaches zero. + */ + atomic_t refcnt; + + /* How precisely should I be started? */ + int (*start)(struct dst_node *); + + /* Crypto capabilities */ + struct dst_crypto_ctl crypto; + u8 *hash_key; + u8 *cipher_key; + + /* Pool of processing thread */ + struct thread_pool *pool; + + /* Transaction IDs live here */ + atomic_long_t gen; + + /* + * How frequently and how many times transaction + * tree should be scanned to drop stale objects. + */ + long trans_scan_timeout; + int trans_max_retries; + + /* Small gnomes live here */ + struct rb_root trans_root; + struct mutex trans_lock; + + /* + * Transaction cache/memory pool. + * It is big enough to contain not only transaction + * itself, but additional crypto data (digest/hmac). + */ + struct kmem_cache *trans_cache; + mempool_t *trans_pool; + + /* This entity scans transaction tree */ + struct delayed_work trans_work; + + wait_queue_head_t wait; +}; + +/* Kernel representation of the security attribute */ +struct dst_secure +{ + struct list_head sec_entry; + struct dst_secure_user sec; +}; + +int dst_process_bio(struct dst_node *n, struct bio *bio); + +int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r); +int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le); + +static inline struct dst_state *dst_state_get(struct dst_state *st) +{ + BUG_ON(atomic_read(&st->refcnt) == 0); + atomic_inc(&st->refcnt); + return st; +} + +void dst_state_put(struct dst_state *st); + +struct dst_state *dst_state_alloc(struct dst_node *n); +int dst_state_socket_create(struct dst_state *st); +void dst_state_socket_release(struct dst_state *st); + +void dst_state_exit_connected(struct dst_state *st); + +int dst_state_schedule_receiver(struct dst_state *st); + +void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str); + +static inline void dst_state_lock(struct dst_state *st) +{ + mutex_lock(&st->state_lock); +} + +static inline void dst_state_unlock(struct dst_state *st) +{ + mutex_unlock(&st->state_lock); +} + +void dst_poll_exit(struct dst_state *st); +int dst_poll_init(struct dst_state *st); + +static inline unsigned int dst_state_poll(struct dst_state *st) +{ + unsigned int revents = POLLHUP | POLLERR; + + dst_state_lock(st); + if (st->socket) + revents = st->socket->ops->poll(NULL, st->socket, NULL); + dst_state_unlock(st); + + return revents; +} + +static inline int dst_thread_setup(void *private, void *data) +{ + return 0; +} + +void dst_node_put(struct dst_node *n); + +static inline struct dst_node *dst_node_get(struct dst_node *n) +{ + atomic_inc(&n->refcnt); + return n; +} + +int dst_data_recv(struct dst_state *st, void *data, unsigned int size); +int dst_recv_cdata(struct dst_state *st, void *cdata); +int dst_data_send_header(struct socket *sock, + void *data, unsigned int size, int more); + +int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio); + +int dst_process_io(struct dst_state *st); +int dst_export_crypto(struct dst_node *n, struct bio *bio); +int dst_export_send_bio(struct bio *bio); +int dst_start_export(struct dst_node *n); + +int __init dst_export_init(void); +void dst_export_exit(void); + +/* Private structure for export block IO requests */ +struct dst_export_priv +{ + struct list_head request_entry; + struct dst_state *state; + struct bio *bio; + struct dst_cmd cmd; +}; + +static inline void dst_trans_get(struct dst_trans *t) +{ + atomic_inc(&t->refcnt); +} + +struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen); +int dst_trans_remove(struct dst_trans *t); +int dst_trans_remove_nolock(struct dst_trans *t); +void dst_trans_put(struct dst_trans *t); + +/* + * Convert bio into network command. + */ +static inline void dst_bio_to_cmd(struct bio *bio, struct dst_cmd *cmd, + u32 command, u64 id) +{ + cmd->cmd = command; + cmd->flags = (bio->bi_flags << BIO_POOL_BITS) >> BIO_POOL_BITS; + cmd->rw = bio->bi_rw; + cmd->size = bio->bi_size; + cmd->csize = 0; + cmd->id = id; + cmd->sector = bio->bi_sector; +}; + +int dst_trans_send(struct dst_trans *t); +int dst_trans_crypto(struct dst_trans *t); + +int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl); +void dst_node_crypto_exit(struct dst_node *n); + +static inline int dst_need_crypto(struct dst_node *n) +{ + struct dst_crypto_ctl *c = &n->crypto; + /* + * Logical OR is appropriate here, but boolean one produces + * more optimal code, so it is used instead. + */ + return (c->hash_algo[0] | c->cipher_algo[0]); +} + +int dst_node_trans_init(struct dst_node *n, unsigned int size); +void dst_node_trans_exit(struct dst_node *n); + +/* + * Pool of threads. + * Ready list contains threads currently free to be used, + * active one contains threads with some work scheduled for them. + * Caller can wait in given queue when thread is ready. + */ +struct thread_pool +{ + int thread_num; + struct mutex thread_lock; + struct list_head ready_list, active_list; + + wait_queue_head_t wait; +}; + +void thread_pool_del_worker(struct thread_pool *p); +void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id); +int thread_pool_add_worker(struct thread_pool *p, + char *name, + unsigned int id, + void *(* init)(void *data), + void (* cleanup)(void *data), + void *data); + +void thread_pool_destroy(struct thread_pool *p); +struct thread_pool *thread_pool_create(int num, char *name, + void *(* init)(void *data), + void (* cleanup)(void *data), + void *data); + +int thread_pool_schedule(struct thread_pool *p, + int (* setup)(void *stored_private, void *setup_data), + int (* action)(void *stored_private, void *setup_data), + void *setup_data, long timeout); +int thread_pool_schedule_private(struct thread_pool *p, + int (* setup)(void *private, void *data), + int (* action)(void *private, void *data), + void *data, long timeout, void *id); + +#endif /* __KERNEL__ */ +#endif /* __DST_H */ diff --git a/mm/filemap.c b/mm/filemap.c index fc11974f2bee..2e2d38ebda4b 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -513,6 +513,7 @@ int add_to_page_cache_lru(struct page *page, struct address_space *mapping, } return ret; } +EXPORT_SYMBOL_GPL(add_to_page_cache_lru); #ifdef CONFIG_NUMA struct page *__page_cache_alloc(gfp_t gfp) @@ -645,6 +646,7 @@ int __lock_page_killable(struct page *page) return __wait_on_bit_lock(page_waitqueue(page), &wait, sync_page_killable, TASK_KILLABLE); } +EXPORT_SYMBOL_GPL(__lock_page_killable); /** * __lock_page_nosync - get a lock on the page, without calling sync_page()